Import Cobalt 14.119169

Change-Id: I3dabd6dd8bc7397e38771542aea50f2f57c0a000
diff --git a/src/base/base.gyp b/src/base/base.gyp
index 56a0c9a..6b048fc 100644
--- a/src/base/base.gyp
+++ b/src/base/base.gyp
@@ -183,7 +183,6 @@
         'containers/mru_cache_unittest.cc',
         'containers/small_map_unittest.cc',
         'containers/stack_container_unittest.cc',
-        'cpu_unittest.cc',
         'debug/leak_tracker_unittest.cc',
         'debug/stack_trace_unittest.cc',
         'debug/trace_event_unittest.cc',
diff --git a/src/base/base.gypi b/src/base/base.gypi
index fe57218..e5c56ef 100644
--- a/src/base/base.gypi
+++ b/src/base/base.gypi
@@ -54,8 +54,6 @@
           'containers/mru_cache.h',
           'containers/small_map.h',
           'containers/stack_container.h',
-          'cpu.cc',
-          'cpu.h',
           'critical_closure.h',
           'debug/alias.cc',
           'debug/alias.h',
diff --git a/src/base/cpu.cc b/src/base/cpu.cc
deleted file mode 100644
index cf4f2f1..0000000
--- a/src/base/cpu.cc
+++ /dev/null
@@ -1,140 +0,0 @@
-// Copyright (c) 2012 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 "base/cpu.h"
-
-#include <string.h>
-
-#include <algorithm>
-
-#include "build/build_config.h"
-
-#if defined(ARCH_CPU_X86_FAMILY)
-#if defined(_MSC_VER)
-#include <intrin.h>
-#endif
-#endif
-
-namespace base {
-
-CPU::CPU()
-  : type_(0),
-    family_(0),
-    model_(0),
-    stepping_(0),
-    ext_model_(0),
-    ext_family_(0),
-    has_mmx_(false),
-    has_sse_(false),
-    has_sse2_(false),
-    has_sse3_(false),
-    has_ssse3_(false),
-    has_sse41_(false),
-    has_sse42_(false),
-    cpu_vendor_("unknown") {
-  Initialize();
-}
-
-#if defined(ARCH_CPU_X86_FAMILY)
-#ifndef _MSC_VER
-
-#if defined(__pic__) && defined(__i386__)
-
-void __cpuid(int cpu_info[4], int info_type) {
-  __asm__ volatile (
-    "mov %%ebx, %%edi\n"
-    "cpuid\n"
-    "xchg %%edi, %%ebx\n"
-    : "=a"(cpu_info[0]), "=D"(cpu_info[1]), "=c"(cpu_info[2]), "=d"(cpu_info[3])
-    : "a"(info_type)
-  );
-}
-
-void __cpuidex(int cpu_info[4], int info_type, int info_index) {
-  __asm__ volatile (
-    "mov %%ebx, %%edi\n"
-    "cpuid\n"
-    "xchg %%edi, %%ebx\n"
-    : "=a"(cpu_info[0]), "=D"(cpu_info[1]), "=c"(cpu_info[2]), "=d"(cpu_info[3])
-    : "a"(info_type), "c"(info_index)
-  );
-}
-
-#else
-
-void __cpuid(int cpu_info[4], int info_type) {
-  __asm__ volatile (
-    "cpuid \n\t"
-    : "=a"(cpu_info[0]), "=b"(cpu_info[1]), "=c"(cpu_info[2]), "=d"(cpu_info[3])
-    : "a"(info_type)
-  );
-}
-
-void __cpuidex(int cpu_info[4], int info_type, int info_index) {
-  __asm__ volatile (
-    "cpuid \n\t"
-    : "=a"(cpu_info[0]), "=b"(cpu_info[1]), "=c"(cpu_info[2]), "=d"(cpu_info[3])
-    : "a"(info_type), "c"(info_index)
-  );
-}
-
-#endif
-#endif  // _MSC_VER
-#endif  // ARCH_CPU_X86_FAMILY
-
-void CPU::Initialize() {
-#if defined(ARCH_CPU_X86_FAMILY)
-  int cpu_info[4] = {-1};
-  char cpu_string[48];
-
-  // __cpuid with an InfoType argument of 0 returns the number of
-  // valid Ids in CPUInfo[0] and the CPU identification string in
-  // the other three array elements. The CPU identification string is
-  // not in linear order. The code below arranges the information
-  // in a human readable form. The human readable order is CPUInfo[1] |
-  // CPUInfo[3] | CPUInfo[2]. CPUInfo[2] and CPUInfo[3] are swapped
-  // before using memcpy to copy these three array elements to cpu_string.
-  __cpuid(cpu_info, 0);
-  int num_ids = cpu_info[0];
-  std::swap(cpu_info[2], cpu_info[3]);
-  memcpy(cpu_string, &cpu_info[1], 3 * sizeof(cpu_info[1]));
-  cpu_vendor_.assign(cpu_string, 3 * sizeof(cpu_info[1]));
-
-  // Interpret CPU feature information.
-  if (num_ids > 0) {
-    __cpuid(cpu_info, 1);
-    stepping_ = cpu_info[0] & 0xf;
-    model_ = ((cpu_info[0] >> 4) & 0xf) + ((cpu_info[0] >> 12) & 0xf0);
-    family_ = (cpu_info[0] >> 8) & 0xf;
-    type_ = (cpu_info[0] >> 12) & 0x3;
-    ext_model_ = (cpu_info[0] >> 16) & 0xf;
-    ext_family_ = (cpu_info[0] >> 20) & 0xff;
-    has_mmx_ = (cpu_info[3] & 0x00800000) != 0;
-    has_sse_ = (cpu_info[3] & 0x02000000) != 0;
-    has_sse2_ = (cpu_info[3] & 0x04000000) != 0;
-    has_sse3_ = (cpu_info[2] & 0x00000001) != 0;
-    has_ssse3_ = (cpu_info[2] & 0x00000200) != 0;
-    has_sse41_ = (cpu_info[2] & 0x00080000) != 0;
-    has_sse42_ = (cpu_info[2] & 0x00100000) != 0;
-  }
-
-  // Get the brand string of the cpu.
-  __cpuid(cpu_info, 0x80000000);
-  const int parameter_end = 0x80000004;
-
-  if (cpu_info[0] >= parameter_end) {
-    char* cpu_string_ptr = cpu_string;
-
-    for (int parameter = 0x80000002; parameter <= parameter_end &&
-         cpu_string_ptr < &cpu_string[sizeof(cpu_string)]; parameter++) {
-      __cpuid(cpu_info, parameter);
-      memcpy(cpu_string_ptr, cpu_info, sizeof(cpu_info));
-      cpu_string_ptr += sizeof(cpu_info);
-    }
-    cpu_brand_.assign(cpu_string, cpu_string_ptr - cpu_string);
-  }
-#endif
-}
-
-}  // namespace base
diff --git a/src/base/cpu.h b/src/base/cpu.h
deleted file mode 100644
index 957b1a5..0000000
--- a/src/base/cpu.h
+++ /dev/null
@@ -1,60 +0,0 @@
-// Copyright (c) 2012 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 BASE_CPU_H_
-#define BASE_CPU_H_
-
-#include <string>
-
-#include "base/base_export.h"
-
-namespace base {
-
-// Query information about the processor.
-class BASE_EXPORT CPU {
- public:
-  // Constructor
-  CPU();
-
-  // Accessors for CPU information.
-  const std::string& vendor_name() const { return cpu_vendor_; }
-  int stepping() const { return stepping_; }
-  int model() const { return model_; }
-  int family() const { return family_; }
-  int type() const { return type_; }
-  int extended_model() const { return ext_model_; }
-  int extended_family() const { return ext_family_; }
-  bool has_mmx() const { return has_mmx_; }
-  bool has_sse() const { return has_sse_; }
-  bool has_sse2() const { return has_sse2_; }
-  bool has_sse3() const { return has_sse3_; }
-  bool has_ssse3() const { return has_ssse3_; }
-  bool has_sse41() const { return has_sse41_; }
-  bool has_sse42() const { return has_sse42_; }
-  const std::string& cpu_brand() const { return cpu_brand_; }
-
- private:
-  // Query the processor for CPUID information.
-  void Initialize();
-
-  int type_;  // process type
-  int family_;  // family of the processor
-  int model_;  // model of processor
-  int stepping_;  // processor revision number
-  int ext_model_;
-  int ext_family_;
-  bool has_mmx_;
-  bool has_sse_;
-  bool has_sse2_;
-  bool has_sse3_;
-  bool has_ssse3_;
-  bool has_sse41_;
-  bool has_sse42_;
-  std::string cpu_vendor_;
-  std::string cpu_brand_;
-};
-
-}  // namespace base
-
-#endif  // BASE_CPU_H_
diff --git a/src/base/cpu_unittest.cc b/src/base/cpu_unittest.cc
deleted file mode 100644
index d059dee..0000000
--- a/src/base/cpu_unittest.cc
+++ /dev/null
@@ -1,92 +0,0 @@
-// Copyright (c) 2012 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 "base/cpu.h"
-#include "build/build_config.h"
-
-#include "testing/gtest/include/gtest/gtest.h"
-
-// Tests whether we can run extended instructions represented by the CPU
-// information. This test actually executes some extended instructions (such as
-// MMX, SSE, etc.) supported by the CPU and sees we can run them without
-// "undefined instruction" exceptions. That is, this test succeeds when this
-// test finishes without a crash.
-TEST(CPU, RunExtendedInstructions) {
-#if defined(ARCH_CPU_X86_FAMILY)
-  // Retrieve the CPU information.
-  base::CPU cpu;
-
-#if defined(OS_WIN)
-  ASSERT_TRUE(cpu.has_mmx());
-
-  // Execute an MMX instruction.
-  __asm emms;
-
-  if (cpu.has_sse()) {
-    // Execute an SSE instruction.
-    __asm xorps xmm0, xmm0;
-  }
-
-  if (cpu.has_sse2()) {
-    // Execute an SSE 2 instruction.
-    __asm psrldq xmm0, 0;
-  }
-
-  if (cpu.has_sse3()) {
-    // Execute an SSE 3 instruction.
-    __asm addsubpd xmm0, xmm0;
-  }
-
-  if (cpu.has_ssse3()) {
-    // Execute a Supplimental SSE 3 instruction.
-    __asm psignb xmm0, xmm0;
-  }
-
-  if (cpu.has_sse41()) {
-    // Execute an SSE 4.1 instruction.
-    __asm pmuldq xmm0, xmm0;
-  }
-
-  if (cpu.has_sse42()) {
-    // Execute an SSE 4.2 instruction.
-    __asm crc32 eax, eax;
-  }
-#elif defined(OS_POSIX) && defined(__x86_64__)
-  ASSERT_TRUE(cpu.has_mmx());
-
-  // Execute an MMX instruction.
-  __asm__ __volatile__("emms\n" : : : "mm0");
-
-  if (cpu.has_sse()) {
-    // Execute an SSE instruction.
-    __asm__ __volatile__("xorps %%xmm0, %%xmm0\n" : : : "xmm0");
-  }
-
-  if (cpu.has_sse2()) {
-    // Execute an SSE 2 instruction.
-    __asm__ __volatile__("psrldq $0, %%xmm0\n" : : : "xmm0");
-  }
-
-  if (cpu.has_sse3()) {
-    // Execute an SSE 3 instruction.
-    __asm__ __volatile__("addsubpd %%xmm0, %%xmm0\n" : : : "xmm0");
-  }
-
-  if (cpu.has_ssse3()) {
-    // Execute a Supplimental SSE 3 instruction.
-    __asm__ __volatile__("psignb %%xmm0, %%xmm0\n" : : : "xmm0");
-  }
-
-  if (cpu.has_sse41()) {
-    // Execute an SSE 4.1 instruction.
-    __asm__ __volatile__("pmuldq %%xmm0, %%xmm0\n" : : : "xmm0");
-  }
-
-  if (cpu.has_sse42()) {
-    // Execute an SSE 4.2 instruction.
-    __asm__ __volatile__("crc32 %%eax, %%eax\n" : : : "eax");
-  }
-#endif
-#endif
-}
diff --git a/src/base/file_path.cc b/src/base/file_path.cc
index 4715417..f62acae 100644
--- a/src/base/file_path.cc
+++ b/src/base/file_path.cc
@@ -44,14 +44,6 @@
 
 namespace {
 
-#if defined(FILE_PATH_USES_WIN_SEPARATORS) && defined(OS_POSIX)
-inline bool StartsWith(const std::string& str,
-                       const std::string& search,
-                       bool case_sensitive) {
-  return StartsWithASCII(str, search, case_sensitive);
-}
-#endif
-
 const char* kCommonDoubleExtensionSuffixes[] = { "gz", "z", "bz2" };
 const char* kCommonDoubleExtensions[] = { "user.js" };
 
diff --git a/src/base/file_util_starboard.cc b/src/base/file_util_starboard.cc
index a2e9b2b..0856c69 100644
--- a/src/base/file_util_starboard.cc
+++ b/src/base/file_util_starboard.cc
@@ -39,7 +39,7 @@
   "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
   "abcdefghijklmnopqrstuvwxyz"
   "0123456789"
-  "._-"
+  "_-"
 };
 const int kPortableFilenameCharactersLength =
     SB_ARRAY_SIZE_INT(kPortableFilenameCharacters) - 1;
diff --git a/src/base/string_util.h b/src/base/string_util.h
index 84831d0..9290bee 100644
--- a/src/base/string_util.h
+++ b/src/base/string_util.h
@@ -371,6 +371,15 @@
                             const string16& search,
                             bool case_sensitive);
 
+// Generic version.
+template <typename StringType>
+inline bool StartsWith(const StringType& str, const StringType& search,
+                       bool case_sensitive) {
+  std::wstring str_16(str.begin(), str.end());
+  std::wstring search_16(search.begin(), search.end());
+  return StartsWith(str_16, search_16, case_sensitive);
+}
+
 // Returns true if str ends with search, or false otherwise.
 BASE_EXPORT bool EndsWith(const std::string& str,
                           const std::string& search,
diff --git a/src/base/sys_info.h b/src/base/sys_info.h
index e653590..c5415e0 100644
--- a/src/base/sys_info.h
+++ b/src/base/sys_info.h
@@ -67,8 +67,6 @@
   //      whereas a x86-64 kernel on the same CPU will return "x86_64"
   static std::string OperatingSystemArchitecture();
 
-  // Avoid using this. Use base/cpu.h to get information about the CPU instead.
-  // http://crbug.com/148884
   // Returns the CPU model name of the system. If it can not be figured out,
   // an empty string is returned.
   static std::string CPUModelName();
diff --git a/src/base/test/test_suite.cc b/src/base/test/test_suite.cc
index 40d4071..6e0444d 100644
--- a/src/base/test/test_suite.cc
+++ b/src/base/test/test_suite.cc
@@ -32,10 +32,6 @@
 #endif  // OS_IOS
 #endif  // OS_MACOSX
 
-#if defined(OS_STARBOARD)
-#include "starboard/system.h"
-#endif
-
 #if defined(OS_ANDROID) || defined(__LB_ANDROID__)
 #include "base/test/test_support_android.h"
 #endif
@@ -103,11 +99,6 @@
 #if defined(OS_WIN)
   testing::GTEST_FLAG(catch_exceptions) = false;
 #endif
-
-#if defined(OS_STARBOARD)
-  testing::GTEST_FLAG(break_on_failure) = SbSystemIsDebuggerAttached();
-#endif
-
   base::EnableTerminationOnHeapCorruption();
   initialized_command_line_ = CommandLine::Init(argc, argv);
   testing::InitGoogleTest(&argc, argv);
diff --git a/src/cobalt/accessibility/screen_reader_tests.cc b/src/cobalt/accessibility/screen_reader_tests.cc
index 611d7ed..9974b6b 100644
--- a/src/cobalt/accessibility/screen_reader_tests.cc
+++ b/src/cobalt/accessibility/screen_reader_tests.cc
@@ -26,7 +26,9 @@
 #include "cobalt/accessibility/tts_engine.h"
 #include "cobalt/browser/web_module.h"
 #include "cobalt/dom/element.h"
+#include "cobalt/dom/window.h"
 #include "cobalt/test/document_loader.h"
+#include "starboard/window.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
@@ -127,6 +129,10 @@
   base::WaitableEvent quit_event_;
   scoped_ptr<accessibility::ScreenReader> screen_reader_;
 };
+
+// Return a NULL SbWindow, since we do not need to pass a valid SbWindow to an
+// on screen keyboard.
+SbWindow GetNullSbWindow() { return NULL; }
 }  // namespace
 
 TEST_P(TextAlternativeTest, TextAlternativeTest) {
@@ -173,9 +179,10 @@
       base::Bind(&LiveRegionMutationTest::OnError, base::Unretained(this)),
       base::Bind(&LiveRegionMutationTest::OnClose, base::Unretained(this)),
       base::Closure(), /* window_minimize_callback */
-      NULL /* can_play_type_handler */, NULL /* web_media_player_factory */,
-      &network_module, kDefaultViewportSize, kDefaultVideoPixelRatio,
-      &resource_provider, kRefreshRate, web_module_options);
+      base::Bind(&GetNullSbWindow), NULL /* can_play_type_handler */,
+      NULL /* web_media_player_factory */, &network_module,
+      kDefaultViewportSize, kDefaultVideoPixelRatio, &resource_provider,
+      kRefreshRate, web_module_options);
 
   // Wait for the test to quit.
   quit_event_.Wait();
diff --git a/src/cobalt/base/base.gyp b/src/cobalt/base/base.gyp
index ee51357..2f25385 100644
--- a/src/cobalt/base/base.gyp
+++ b/src/cobalt/base/base.gyp
@@ -53,6 +53,8 @@
         'log_message_handler.h',
         'math.h',
         'message_queue.h',
+        'on_screen_keyboard_hidden_event.h',
+        'on_screen_keyboard_shown_event.h',
         'path_provider.cc',
         'path_provider.h',
         'poller.h',
diff --git a/src/cobalt/base/language.cc b/src/cobalt/base/language.cc
index 93869a1..fc72003 100644
--- a/src/cobalt/base/language.cc
+++ b/src/cobalt/base/language.cc
@@ -14,6 +14,8 @@
 
 #include "cobalt/base/language.h"
 
+#include <algorithm>
+
 #include "base/basictypes.h"
 #include "base/logging.h"
 #include "third_party/icu/source/common/unicode/uloc.h"
@@ -42,4 +44,28 @@
   // We should end up with something like "en" or "en-US".
   return language;
 }
+
+std::string GetSystemLanguageScript() {
+  char buffer[ULOC_LANG_CAPACITY];
+  UErrorCode icu_result = U_ZERO_ERROR;
+
+  // Combine the ISO language and script.
+  uloc_getLanguage(NULL, buffer, arraysize(buffer), &icu_result);
+  if (!U_SUCCESS(icu_result)) {
+    DLOG(FATAL) << __FUNCTION__ << ": Unable to get language from ICU for "
+                << "default locale " << uloc_getDefault() << ".";
+    return "en";
+  }
+
+  std::string language = buffer;
+  uloc_getScript(NULL, buffer, arraysize(buffer), &icu_result);
+  if (U_SUCCESS(icu_result) && buffer[0]) {
+    language += "-";
+    language += buffer;
+  }
+
+  // We should end up with something like "en" or "en-Latn".
+  return language;
+}
+
 }  // namespace base
diff --git a/src/cobalt/base/language.h b/src/cobalt/base/language.h
index 174035f..4e59a72 100644
--- a/src/cobalt/base/language.h
+++ b/src/cobalt/base/language.h
@@ -19,12 +19,18 @@
 
 namespace base {
 
-// Gets the system language.
+// Gets the system language and ISO 3166-1 country code.
 // NOTE: should be in the format described by bcp47.
 // http://www.rfc-editor.org/rfc/bcp/bcp47.txt
 // Example: "en-US" or "de"
 std::string GetSystemLanguage();
 
+// Gets the system language and ISO 15924 script code.
+// NOTE: should be in the format described by bcp47.
+// http://www.rfc-editor.org/rfc/bcp/bcp47.txt
+// Example: "en-US" or "de"
+std::string GetSystemLanguageScript();
+
 }  // namespace base
 
 #endif  // COBALT_BASE_LANGUAGE_H_
diff --git a/src/cobalt/base/on_screen_keyboard_hidden_event.h b/src/cobalt/base/on_screen_keyboard_hidden_event.h
new file mode 100644
index 0000000..81539a9
--- /dev/null
+++ b/src/cobalt/base/on_screen_keyboard_hidden_event.h
@@ -0,0 +1,32 @@
+// Copyright 2017 Google Inc. All Rights Reserved.
+//
+// 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.
+
+#ifndef COBALT_BASE_ON_SCREEN_KEYBOARD_HIDDEN_EVENT_H_
+#define COBALT_BASE_ON_SCREEN_KEYBOARD_HIDDEN_EVENT_H_
+
+#include "cobalt/base/event.h"
+#include "starboard/event.h"
+
+namespace base {
+
+class OnScreenKeyboardHiddenEvent : public Event {
+ public:
+  OnScreenKeyboardHiddenEvent() {}
+
+  BASE_EVENT_SUBCLASS(OnScreenKeyboardHiddenEvent);
+};
+
+}  // namespace base
+
+#endif  // COBALT_BASE_ON_SCREEN_KEYBOARD_HIDDEN_EVENT_H_
diff --git a/src/cobalt/base/on_screen_keyboard_shown_event.h b/src/cobalt/base/on_screen_keyboard_shown_event.h
new file mode 100644
index 0000000..b48f76a
--- /dev/null
+++ b/src/cobalt/base/on_screen_keyboard_shown_event.h
@@ -0,0 +1,32 @@
+// Copyright 2017 Google Inc. All Rights Reserved.
+//
+// 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.
+
+#ifndef COBALT_BASE_ON_SCREEN_KEYBOARD_SHOWN_EVENT_H_
+#define COBALT_BASE_ON_SCREEN_KEYBOARD_SHOWN_EVENT_H_
+
+#include "cobalt/base/event.h"
+#include "starboard/event.h"
+
+namespace base {
+
+class OnScreenKeyboardShownEvent : public Event {
+ public:
+  OnScreenKeyboardShownEvent() {}
+
+  BASE_EVENT_SUBCLASS(OnScreenKeyboardShownEvent);
+};
+
+}  // namespace base
+
+#endif  // COBALT_BASE_ON_SCREEN_KEYBOARD_SHOWN_EVENT_H_
diff --git a/src/cobalt/base/tokens.h b/src/cobalt/base/tokens.h
index 891c4a6..758a2d2 100644
--- a/src/cobalt/base/tokens.h
+++ b/src/cobalt/base/tokens.h
@@ -64,6 +64,8 @@
     MacroOpWithNameOnly(focusout)                                    \
     MacroOpWithNameOnly(gotpointercapture)                           \
     MacroOpWithNameOnly(hashchange)                                  \
+    MacroOpWithNameOnly(hide)                                        \
+    MacroOpWithNameOnly(input)                                       \
     MacroOpWithNameOnly(keydown)                                     \
     MacroOpWithNameOnly(keypress)                                    \
     MacroOpWithNameOnly(keystatuseschange)                           \
@@ -109,6 +111,7 @@
     MacroOpWithNameOnly(securitypolicyviolation)                     \
     MacroOpWithNameOnly(seeked)                                      \
     MacroOpWithNameOnly(seeking)                                     \
+    MacroOpWithNameOnly(show)                                        \
     MacroOpWithNameOnly(soundend)                                    \
     MacroOpWithNameOnly(soundstart)                                  \
     MacroOpWithNameOnly(sourceclose)                                 \
diff --git a/src/cobalt/base/window_size_changed_event.h b/src/cobalt/base/window_size_changed_event.h
index 50034c8..0fbaa8d 100644
--- a/src/cobalt/base/window_size_changed_event.h
+++ b/src/cobalt/base/window_size_changed_event.h
@@ -17,6 +17,7 @@
 
 #include "cobalt/base/event.h"
 #include "starboard/event.h"
+#include "starboard/window.h"
 
 namespace base {
 
diff --git a/src/cobalt/bindings/contexts.py b/src/cobalt/bindings/contexts.py
index 4bebf81..f1b9381 100644
--- a/src/cobalt/bindings/contexts.py
+++ b/src/cobalt/bindings/contexts.py
@@ -194,6 +194,9 @@
   if extended_attributes.has_key('Clamp'):
     flags.append('kConversionFlagClamped')
 
+  if is_object_type(idl_type):
+    flags.append('kConversionFlagObjectOnly')
+
   if flags:
     return '(%s)' % ' | '.join(flags)
   else:
@@ -264,7 +267,7 @@
     elif idl_type.name == 'void':
       cobalt_type = 'void'
     elif is_object_type(idl_type):
-      cobalt_type = '::cobalt::script::OpaqueHandle'
+      cobalt_type = '::cobalt::script::ValueHandle'
     elif is_any_type(idl_type):
       cobalt_type = '::cobalt::script::ValueHandle'
     elif idl_type.is_dictionary:
@@ -545,7 +548,8 @@
     # Get the method contexts for all operations.
     methods = [
         self.method_context(interface, operation)
-        for operation in interface.operations if operation.name
+        for operation in interface.operations
+        if operation.name
     ]
 
     # Create overload sets for static and non-static methods seperately.
diff --git a/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_anonymous_indexed_getter_interface.cc b/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_anonymous_indexed_getter_interface.cc
index 6f7ac05..8d8e5b6 100644
--- a/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_anonymous_indexed_getter_interface.cc
+++ b/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_anonymous_indexed_getter_interface.cc
@@ -22,8 +22,8 @@
 #include "base/debug/trace_event.h"
 #include "cobalt/base/polymorphic_downcast.h"
 #include "cobalt/script/global_environment.h"
-#include "cobalt/script/opaque_handle.h"
 #include "cobalt/script/script_value.h"
+#include "cobalt/script/value_handle.h"
 
 #include "mozjs_gen_type_conversion.h"
 
@@ -34,7 +34,6 @@
 #include "cobalt/script/mozjs-45/mozjs_callback_function.h"
 #include "cobalt/script/mozjs-45/mozjs_exception_state.h"
 #include "cobalt/script/mozjs-45/mozjs_global_environment.h"
-#include "cobalt/script/mozjs-45/mozjs_object_handle.h"
 #include "cobalt/script/mozjs-45/mozjs_property_enumerator.h"
 #include "cobalt/script/mozjs-45/mozjs_user_object_holder.h"
 #include "cobalt/script/mozjs-45/mozjs_value_handle.h"
@@ -53,10 +52,10 @@
 using cobalt::bindings::testing::MozjsAnonymousIndexedGetterInterface;
 using cobalt::script::CallbackInterfaceTraits;
 using cobalt::script::GlobalEnvironment;
-using cobalt::script::OpaqueHandle;
-using cobalt::script::OpaqueHandleHolder;
 using cobalt::script::ScriptValue;
 using cobalt::script::ValueHandle;
+using cobalt::script::ValueHandle;
+using cobalt::script::ValueHandleHolder;
 using cobalt::script::Wrappable;
 
 using cobalt::script::CallbackFunction;
@@ -80,6 +79,7 @@
 using cobalt::script::mozjs::kConversionFlagRestricted;
 using cobalt::script::mozjs::kConversionFlagTreatNullAsEmptyString;
 using cobalt::script::mozjs::kConversionFlagTreatUndefinedAsEmptyString;
+using cobalt::script::mozjs::kConversionFlagObjectOnly;
 using cobalt::script::mozjs::kNoConversionFlags;
 }  // namespace
 
@@ -501,3 +501,5 @@
 }  // namespace testing
 }  // namespace bindings
 }  // namespace cobalt
+
+
diff --git a/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_anonymous_named_getter_interface.cc b/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_anonymous_named_getter_interface.cc
index 99c1120..f058a0f 100644
--- a/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_anonymous_named_getter_interface.cc
+++ b/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_anonymous_named_getter_interface.cc
@@ -22,8 +22,8 @@
 #include "base/debug/trace_event.h"
 #include "cobalt/base/polymorphic_downcast.h"
 #include "cobalt/script/global_environment.h"
-#include "cobalt/script/opaque_handle.h"
 #include "cobalt/script/script_value.h"
+#include "cobalt/script/value_handle.h"
 
 #include "mozjs_gen_type_conversion.h"
 
@@ -34,7 +34,6 @@
 #include "cobalt/script/mozjs-45/mozjs_callback_function.h"
 #include "cobalt/script/mozjs-45/mozjs_exception_state.h"
 #include "cobalt/script/mozjs-45/mozjs_global_environment.h"
-#include "cobalt/script/mozjs-45/mozjs_object_handle.h"
 #include "cobalt/script/mozjs-45/mozjs_property_enumerator.h"
 #include "cobalt/script/mozjs-45/mozjs_user_object_holder.h"
 #include "cobalt/script/mozjs-45/mozjs_value_handle.h"
@@ -53,10 +52,10 @@
 using cobalt::bindings::testing::MozjsAnonymousNamedGetterInterface;
 using cobalt::script::CallbackInterfaceTraits;
 using cobalt::script::GlobalEnvironment;
-using cobalt::script::OpaqueHandle;
-using cobalt::script::OpaqueHandleHolder;
 using cobalt::script::ScriptValue;
 using cobalt::script::ValueHandle;
+using cobalt::script::ValueHandle;
+using cobalt::script::ValueHandleHolder;
 using cobalt::script::Wrappable;
 
 using cobalt::script::CallbackFunction;
@@ -80,6 +79,7 @@
 using cobalt::script::mozjs::kConversionFlagRestricted;
 using cobalt::script::mozjs::kConversionFlagTreatNullAsEmptyString;
 using cobalt::script::mozjs::kConversionFlagTreatUndefinedAsEmptyString;
+using cobalt::script::mozjs::kConversionFlagObjectOnly;
 using cobalt::script::mozjs::kNoConversionFlags;
 }  // namespace
 
@@ -449,3 +449,5 @@
 }  // namespace testing
 }  // namespace bindings
 }  // namespace cobalt
+
+
diff --git a/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_anonymous_named_indexed_getter_interface.cc b/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_anonymous_named_indexed_getter_interface.cc
index 9afcce7..5bae384 100644
--- a/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_anonymous_named_indexed_getter_interface.cc
+++ b/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_anonymous_named_indexed_getter_interface.cc
@@ -22,8 +22,8 @@
 #include "base/debug/trace_event.h"
 #include "cobalt/base/polymorphic_downcast.h"
 #include "cobalt/script/global_environment.h"
-#include "cobalt/script/opaque_handle.h"
 #include "cobalt/script/script_value.h"
+#include "cobalt/script/value_handle.h"
 
 #include "mozjs_gen_type_conversion.h"
 
@@ -34,7 +34,6 @@
 #include "cobalt/script/mozjs-45/mozjs_callback_function.h"
 #include "cobalt/script/mozjs-45/mozjs_exception_state.h"
 #include "cobalt/script/mozjs-45/mozjs_global_environment.h"
-#include "cobalt/script/mozjs-45/mozjs_object_handle.h"
 #include "cobalt/script/mozjs-45/mozjs_property_enumerator.h"
 #include "cobalt/script/mozjs-45/mozjs_user_object_holder.h"
 #include "cobalt/script/mozjs-45/mozjs_value_handle.h"
@@ -53,10 +52,10 @@
 using cobalt::bindings::testing::MozjsAnonymousNamedIndexedGetterInterface;
 using cobalt::script::CallbackInterfaceTraits;
 using cobalt::script::GlobalEnvironment;
-using cobalt::script::OpaqueHandle;
-using cobalt::script::OpaqueHandleHolder;
 using cobalt::script::ScriptValue;
 using cobalt::script::ValueHandle;
+using cobalt::script::ValueHandle;
+using cobalt::script::ValueHandleHolder;
 using cobalt::script::Wrappable;
 
 using cobalt::script::CallbackFunction;
@@ -80,6 +79,7 @@
 using cobalt::script::mozjs::kConversionFlagRestricted;
 using cobalt::script::mozjs::kConversionFlagTreatNullAsEmptyString;
 using cobalt::script::mozjs::kConversionFlagTreatUndefinedAsEmptyString;
+using cobalt::script::mozjs::kConversionFlagObjectOnly;
 using cobalt::script::mozjs::kNoConversionFlags;
 }  // namespace
 
@@ -598,3 +598,5 @@
 }  // namespace testing
 }  // namespace bindings
 }  // namespace cobalt
+
+
diff --git a/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_arbitrary_interface.cc b/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_arbitrary_interface.cc
index de68231..b873842 100644
--- a/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_arbitrary_interface.cc
+++ b/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_arbitrary_interface.cc
@@ -22,8 +22,8 @@
 #include "base/debug/trace_event.h"
 #include "cobalt/base/polymorphic_downcast.h"
 #include "cobalt/script/global_environment.h"
-#include "cobalt/script/opaque_handle.h"
 #include "cobalt/script/script_value.h"
+#include "cobalt/script/value_handle.h"
 
 #include "mozjs_gen_type_conversion.h"
 
@@ -34,7 +34,6 @@
 #include "cobalt/script/mozjs-45/mozjs_callback_function.h"
 #include "cobalt/script/mozjs-45/mozjs_exception_state.h"
 #include "cobalt/script/mozjs-45/mozjs_global_environment.h"
-#include "cobalt/script/mozjs-45/mozjs_object_handle.h"
 #include "cobalt/script/mozjs-45/mozjs_property_enumerator.h"
 #include "cobalt/script/mozjs-45/mozjs_user_object_holder.h"
 #include "cobalt/script/mozjs-45/mozjs_value_handle.h"
@@ -53,10 +52,10 @@
 using cobalt::bindings::testing::MozjsArbitraryInterface;
 using cobalt::script::CallbackInterfaceTraits;
 using cobalt::script::GlobalEnvironment;
-using cobalt::script::OpaqueHandle;
-using cobalt::script::OpaqueHandleHolder;
 using cobalt::script::ScriptValue;
 using cobalt::script::ValueHandle;
+using cobalt::script::ValueHandle;
+using cobalt::script::ValueHandleHolder;
 using cobalt::script::Wrappable;
 
 using cobalt::script::CallbackFunction;
@@ -80,6 +79,7 @@
 using cobalt::script::mozjs::kConversionFlagRestricted;
 using cobalt::script::mozjs::kConversionFlagTreatNullAsEmptyString;
 using cobalt::script::mozjs::kConversionFlagTreatUndefinedAsEmptyString;
+using cobalt::script::mozjs::kConversionFlagObjectOnly;
 using cobalt::script::mozjs::kNoConversionFlags;
 }  // namespace
 
@@ -529,3 +529,5 @@
 }  // namespace testing
 }  // namespace bindings
 }  // namespace cobalt
+
+
diff --git a/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_base_interface.cc b/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_base_interface.cc
index 954072a..3277ead 100644
--- a/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_base_interface.cc
+++ b/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_base_interface.cc
@@ -22,8 +22,8 @@
 #include "base/debug/trace_event.h"
 #include "cobalt/base/polymorphic_downcast.h"
 #include "cobalt/script/global_environment.h"
-#include "cobalt/script/opaque_handle.h"
 #include "cobalt/script/script_value.h"
+#include "cobalt/script/value_handle.h"
 
 #include "mozjs_gen_type_conversion.h"
 
@@ -34,7 +34,6 @@
 #include "cobalt/script/mozjs-45/mozjs_callback_function.h"
 #include "cobalt/script/mozjs-45/mozjs_exception_state.h"
 #include "cobalt/script/mozjs-45/mozjs_global_environment.h"
-#include "cobalt/script/mozjs-45/mozjs_object_handle.h"
 #include "cobalt/script/mozjs-45/mozjs_property_enumerator.h"
 #include "cobalt/script/mozjs-45/mozjs_user_object_holder.h"
 #include "cobalt/script/mozjs-45/mozjs_value_handle.h"
@@ -53,10 +52,10 @@
 using cobalt::bindings::testing::MozjsBaseInterface;
 using cobalt::script::CallbackInterfaceTraits;
 using cobalt::script::GlobalEnvironment;
-using cobalt::script::OpaqueHandle;
-using cobalt::script::OpaqueHandleHolder;
 using cobalt::script::ScriptValue;
 using cobalt::script::ValueHandle;
+using cobalt::script::ValueHandle;
+using cobalt::script::ValueHandleHolder;
 using cobalt::script::Wrappable;
 
 using cobalt::script::CallbackFunction;
@@ -80,6 +79,7 @@
 using cobalt::script::mozjs::kConversionFlagRestricted;
 using cobalt::script::mozjs::kConversionFlagTreatNullAsEmptyString;
 using cobalt::script::mozjs::kConversionFlagTreatUndefinedAsEmptyString;
+using cobalt::script::mozjs::kConversionFlagObjectOnly;
 using cobalt::script::mozjs::kNoConversionFlags;
 }  // namespace
 
@@ -477,3 +477,5 @@
 }  // namespace testing
 }  // namespace bindings
 }  // namespace cobalt
+
+
diff --git a/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_boolean_type_test_interface.cc b/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_boolean_type_test_interface.cc
index 64e9741..35f47c0 100644
--- a/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_boolean_type_test_interface.cc
+++ b/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_boolean_type_test_interface.cc
@@ -22,8 +22,8 @@
 #include "base/debug/trace_event.h"
 #include "cobalt/base/polymorphic_downcast.h"
 #include "cobalt/script/global_environment.h"
-#include "cobalt/script/opaque_handle.h"
 #include "cobalt/script/script_value.h"
+#include "cobalt/script/value_handle.h"
 
 #include "mozjs_gen_type_conversion.h"
 
@@ -34,7 +34,6 @@
 #include "cobalt/script/mozjs-45/mozjs_callback_function.h"
 #include "cobalt/script/mozjs-45/mozjs_exception_state.h"
 #include "cobalt/script/mozjs-45/mozjs_global_environment.h"
-#include "cobalt/script/mozjs-45/mozjs_object_handle.h"
 #include "cobalt/script/mozjs-45/mozjs_property_enumerator.h"
 #include "cobalt/script/mozjs-45/mozjs_user_object_holder.h"
 #include "cobalt/script/mozjs-45/mozjs_value_handle.h"
@@ -53,10 +52,10 @@
 using cobalt::bindings::testing::MozjsBooleanTypeTestInterface;
 using cobalt::script::CallbackInterfaceTraits;
 using cobalt::script::GlobalEnvironment;
-using cobalt::script::OpaqueHandle;
-using cobalt::script::OpaqueHandleHolder;
 using cobalt::script::ScriptValue;
 using cobalt::script::ValueHandle;
+using cobalt::script::ValueHandle;
+using cobalt::script::ValueHandleHolder;
 using cobalt::script::Wrappable;
 
 using cobalt::script::CallbackFunction;
@@ -80,6 +79,7 @@
 using cobalt::script::mozjs::kConversionFlagRestricted;
 using cobalt::script::mozjs::kConversionFlagTreatNullAsEmptyString;
 using cobalt::script::mozjs::kConversionFlagTreatUndefinedAsEmptyString;
+using cobalt::script::mozjs::kConversionFlagObjectOnly;
 using cobalt::script::mozjs::kNoConversionFlags;
 }  // namespace
 
@@ -580,3 +580,5 @@
 }  // namespace testing
 }  // namespace bindings
 }  // namespace cobalt
+
+
diff --git a/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_callback_function_interface.cc b/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_callback_function_interface.cc
index 3cf816e..129215d 100644
--- a/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_callback_function_interface.cc
+++ b/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_callback_function_interface.cc
@@ -22,8 +22,8 @@
 #include "base/debug/trace_event.h"
 #include "cobalt/base/polymorphic_downcast.h"
 #include "cobalt/script/global_environment.h"
-#include "cobalt/script/opaque_handle.h"
 #include "cobalt/script/script_value.h"
+#include "cobalt/script/value_handle.h"
 #include "cobalt/bindings/testing/arbitrary_interface.h"
 #include "cobalt/bindings/testing/mozjs_arbitrary_interface.h"
 
@@ -36,7 +36,6 @@
 #include "cobalt/script/mozjs-45/mozjs_callback_function.h"
 #include "cobalt/script/mozjs-45/mozjs_exception_state.h"
 #include "cobalt/script/mozjs-45/mozjs_global_environment.h"
-#include "cobalt/script/mozjs-45/mozjs_object_handle.h"
 #include "cobalt/script/mozjs-45/mozjs_property_enumerator.h"
 #include "cobalt/script/mozjs-45/mozjs_user_object_holder.h"
 #include "cobalt/script/mozjs-45/mozjs_value_handle.h"
@@ -57,10 +56,10 @@
 using cobalt::bindings::testing::MozjsArbitraryInterface;
 using cobalt::script::CallbackInterfaceTraits;
 using cobalt::script::GlobalEnvironment;
-using cobalt::script::OpaqueHandle;
-using cobalt::script::OpaqueHandleHolder;
 using cobalt::script::ScriptValue;
 using cobalt::script::ValueHandle;
+using cobalt::script::ValueHandle;
+using cobalt::script::ValueHandleHolder;
 using cobalt::script::Wrappable;
 
 using cobalt::script::CallbackFunction;
@@ -84,6 +83,7 @@
 using cobalt::script::mozjs::kConversionFlagRestricted;
 using cobalt::script::mozjs::kConversionFlagTreatNullAsEmptyString;
 using cobalt::script::mozjs::kConversionFlagTreatUndefinedAsEmptyString;
+using cobalt::script::mozjs::kConversionFlagObjectOnly;
 using cobalt::script::mozjs::kNoConversionFlags;
 }  // namespace
 
@@ -903,3 +903,5 @@
 }  // namespace testing
 }  // namespace bindings
 }  // namespace cobalt
+
+
diff --git a/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_callback_interface_interface.cc b/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_callback_interface_interface.cc
index 657efc9..ff95770 100644
--- a/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_callback_interface_interface.cc
+++ b/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_callback_interface_interface.cc
@@ -22,8 +22,8 @@
 #include "base/debug/trace_event.h"
 #include "cobalt/base/polymorphic_downcast.h"
 #include "cobalt/script/global_environment.h"
-#include "cobalt/script/opaque_handle.h"
 #include "cobalt/script/script_value.h"
+#include "cobalt/script/value_handle.h"
 #include "cobalt/bindings/testing/mozjs_single_operation_interface.h"
 #include "cobalt/bindings/testing/single_operation_interface.h"
 
@@ -36,7 +36,6 @@
 #include "cobalt/script/mozjs-45/mozjs_callback_function.h"
 #include "cobalt/script/mozjs-45/mozjs_exception_state.h"
 #include "cobalt/script/mozjs-45/mozjs_global_environment.h"
-#include "cobalt/script/mozjs-45/mozjs_object_handle.h"
 #include "cobalt/script/mozjs-45/mozjs_property_enumerator.h"
 #include "cobalt/script/mozjs-45/mozjs_user_object_holder.h"
 #include "cobalt/script/mozjs-45/mozjs_value_handle.h"
@@ -57,10 +56,10 @@
 using cobalt::bindings::testing::SingleOperationInterface;
 using cobalt::script::CallbackInterfaceTraits;
 using cobalt::script::GlobalEnvironment;
-using cobalt::script::OpaqueHandle;
-using cobalt::script::OpaqueHandleHolder;
 using cobalt::script::ScriptValue;
 using cobalt::script::ValueHandle;
+using cobalt::script::ValueHandle;
+using cobalt::script::ValueHandleHolder;
 using cobalt::script::Wrappable;
 
 using cobalt::script::CallbackFunction;
@@ -84,6 +83,7 @@
 using cobalt::script::mozjs::kConversionFlagRestricted;
 using cobalt::script::mozjs::kConversionFlagTreatNullAsEmptyString;
 using cobalt::script::mozjs::kConversionFlagTreatUndefinedAsEmptyString;
+using cobalt::script::mozjs::kConversionFlagObjectOnly;
 using cobalt::script::mozjs::kNoConversionFlags;
 }  // namespace
 
@@ -578,3 +578,5 @@
 }  // namespace testing
 }  // namespace bindings
 }  // namespace cobalt
+
+
diff --git a/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_conditional_interface.cc b/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_conditional_interface.cc
index ae18a41..5149de4 100644
--- a/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_conditional_interface.cc
+++ b/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_conditional_interface.cc
@@ -24,8 +24,8 @@
 #include "base/debug/trace_event.h"
 #include "cobalt/base/polymorphic_downcast.h"
 #include "cobalt/script/global_environment.h"
-#include "cobalt/script/opaque_handle.h"
 #include "cobalt/script/script_value.h"
+#include "cobalt/script/value_handle.h"
 
 #include "mozjs_gen_type_conversion.h"
 
@@ -36,7 +36,6 @@
 #include "cobalt/script/mozjs-45/mozjs_callback_function.h"
 #include "cobalt/script/mozjs-45/mozjs_exception_state.h"
 #include "cobalt/script/mozjs-45/mozjs_global_environment.h"
-#include "cobalt/script/mozjs-45/mozjs_object_handle.h"
 #include "cobalt/script/mozjs-45/mozjs_property_enumerator.h"
 #include "cobalt/script/mozjs-45/mozjs_user_object_holder.h"
 #include "cobalt/script/mozjs-45/mozjs_value_handle.h"
@@ -55,10 +54,10 @@
 using cobalt::bindings::testing::MozjsConditionalInterface;
 using cobalt::script::CallbackInterfaceTraits;
 using cobalt::script::GlobalEnvironment;
-using cobalt::script::OpaqueHandle;
-using cobalt::script::OpaqueHandleHolder;
 using cobalt::script::ScriptValue;
 using cobalt::script::ValueHandle;
+using cobalt::script::ValueHandle;
+using cobalt::script::ValueHandleHolder;
 using cobalt::script::Wrappable;
 
 using cobalt::script::CallbackFunction;
@@ -82,6 +81,7 @@
 using cobalt::script::mozjs::kConversionFlagRestricted;
 using cobalt::script::mozjs::kConversionFlagTreatNullAsEmptyString;
 using cobalt::script::mozjs::kConversionFlagTreatUndefinedAsEmptyString;
+using cobalt::script::mozjs::kConversionFlagObjectOnly;
 using cobalt::script::mozjs::kNoConversionFlags;
 }  // namespace
 
@@ -684,4 +684,6 @@
 }  // namespace testing
 }  // namespace bindings
 }  // namespace cobalt
+
+
 #endif  // defined(ENABLE_CONDITIONAL_INTERFACE)
diff --git a/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_constants_interface.cc b/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_constants_interface.cc
index cd9cc40..eb073de 100644
--- a/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_constants_interface.cc
+++ b/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_constants_interface.cc
@@ -22,8 +22,8 @@
 #include "base/debug/trace_event.h"
 #include "cobalt/base/polymorphic_downcast.h"
 #include "cobalt/script/global_environment.h"
-#include "cobalt/script/opaque_handle.h"
 #include "cobalt/script/script_value.h"
+#include "cobalt/script/value_handle.h"
 
 #include "mozjs_gen_type_conversion.h"
 
@@ -34,7 +34,6 @@
 #include "cobalt/script/mozjs-45/mozjs_callback_function.h"
 #include "cobalt/script/mozjs-45/mozjs_exception_state.h"
 #include "cobalt/script/mozjs-45/mozjs_global_environment.h"
-#include "cobalt/script/mozjs-45/mozjs_object_handle.h"
 #include "cobalt/script/mozjs-45/mozjs_property_enumerator.h"
 #include "cobalt/script/mozjs-45/mozjs_user_object_holder.h"
 #include "cobalt/script/mozjs-45/mozjs_value_handle.h"
@@ -53,10 +52,10 @@
 using cobalt::bindings::testing::MozjsConstantsInterface;
 using cobalt::script::CallbackInterfaceTraits;
 using cobalt::script::GlobalEnvironment;
-using cobalt::script::OpaqueHandle;
-using cobalt::script::OpaqueHandleHolder;
 using cobalt::script::ScriptValue;
 using cobalt::script::ValueHandle;
+using cobalt::script::ValueHandle;
+using cobalt::script::ValueHandleHolder;
 using cobalt::script::Wrappable;
 
 using cobalt::script::CallbackFunction;
@@ -80,6 +79,7 @@
 using cobalt::script::mozjs::kConversionFlagRestricted;
 using cobalt::script::mozjs::kConversionFlagTreatNullAsEmptyString;
 using cobalt::script::mozjs::kConversionFlagTreatUndefinedAsEmptyString;
+using cobalt::script::mozjs::kConversionFlagObjectOnly;
 using cobalt::script::mozjs::kNoConversionFlags;
 }  // namespace
 
@@ -419,3 +419,5 @@
 }  // namespace testing
 }  // namespace bindings
 }  // namespace cobalt
+
+
diff --git a/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_constructor_interface.cc b/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_constructor_interface.cc
index eb15fb1..59b6267 100644
--- a/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_constructor_interface.cc
+++ b/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_constructor_interface.cc
@@ -22,8 +22,8 @@
 #include "base/debug/trace_event.h"
 #include "cobalt/base/polymorphic_downcast.h"
 #include "cobalt/script/global_environment.h"
-#include "cobalt/script/opaque_handle.h"
 #include "cobalt/script/script_value.h"
+#include "cobalt/script/value_handle.h"
 
 #include "mozjs_gen_type_conversion.h"
 
@@ -34,7 +34,6 @@
 #include "cobalt/script/mozjs-45/mozjs_callback_function.h"
 #include "cobalt/script/mozjs-45/mozjs_exception_state.h"
 #include "cobalt/script/mozjs-45/mozjs_global_environment.h"
-#include "cobalt/script/mozjs-45/mozjs_object_handle.h"
 #include "cobalt/script/mozjs-45/mozjs_property_enumerator.h"
 #include "cobalt/script/mozjs-45/mozjs_user_object_holder.h"
 #include "cobalt/script/mozjs-45/mozjs_value_handle.h"
@@ -53,10 +52,10 @@
 using cobalt::bindings::testing::MozjsConstructorInterface;
 using cobalt::script::CallbackInterfaceTraits;
 using cobalt::script::GlobalEnvironment;
-using cobalt::script::OpaqueHandle;
-using cobalt::script::OpaqueHandleHolder;
 using cobalt::script::ScriptValue;
 using cobalt::script::ValueHandle;
+using cobalt::script::ValueHandle;
+using cobalt::script::ValueHandleHolder;
 using cobalt::script::Wrappable;
 
 using cobalt::script::CallbackFunction;
@@ -80,6 +79,7 @@
 using cobalt::script::mozjs::kConversionFlagRestricted;
 using cobalt::script::mozjs::kConversionFlagTreatNullAsEmptyString;
 using cobalt::script::mozjs::kConversionFlagTreatUndefinedAsEmptyString;
+using cobalt::script::mozjs::kConversionFlagObjectOnly;
 using cobalt::script::mozjs::kNoConversionFlags;
 }  // namespace
 
@@ -437,3 +437,5 @@
 }  // namespace testing
 }  // namespace bindings
 }  // namespace cobalt
+
+
diff --git a/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_constructor_with_arguments_interface.cc b/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_constructor_with_arguments_interface.cc
index 416a407..6d4747e 100644
--- a/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_constructor_with_arguments_interface.cc
+++ b/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_constructor_with_arguments_interface.cc
@@ -22,8 +22,8 @@
 #include "base/debug/trace_event.h"
 #include "cobalt/base/polymorphic_downcast.h"
 #include "cobalt/script/global_environment.h"
-#include "cobalt/script/opaque_handle.h"
 #include "cobalt/script/script_value.h"
+#include "cobalt/script/value_handle.h"
 
 #include "mozjs_gen_type_conversion.h"
 
@@ -34,7 +34,6 @@
 #include "cobalt/script/mozjs-45/mozjs_callback_function.h"
 #include "cobalt/script/mozjs-45/mozjs_exception_state.h"
 #include "cobalt/script/mozjs-45/mozjs_global_environment.h"
-#include "cobalt/script/mozjs-45/mozjs_object_handle.h"
 #include "cobalt/script/mozjs-45/mozjs_property_enumerator.h"
 #include "cobalt/script/mozjs-45/mozjs_user_object_holder.h"
 #include "cobalt/script/mozjs-45/mozjs_value_handle.h"
@@ -53,10 +52,10 @@
 using cobalt::bindings::testing::MozjsConstructorWithArgumentsInterface;
 using cobalt::script::CallbackInterfaceTraits;
 using cobalt::script::GlobalEnvironment;
-using cobalt::script::OpaqueHandle;
-using cobalt::script::OpaqueHandleHolder;
 using cobalt::script::ScriptValue;
 using cobalt::script::ValueHandle;
+using cobalt::script::ValueHandle;
+using cobalt::script::ValueHandleHolder;
 using cobalt::script::Wrappable;
 
 using cobalt::script::CallbackFunction;
@@ -80,6 +79,7 @@
 using cobalt::script::mozjs::kConversionFlagRestricted;
 using cobalt::script::mozjs::kConversionFlagTreatNullAsEmptyString;
 using cobalt::script::mozjs::kConversionFlagTreatUndefinedAsEmptyString;
+using cobalt::script::mozjs::kConversionFlagObjectOnly;
 using cobalt::script::mozjs::kNoConversionFlags;
 }  // namespace
 
@@ -582,3 +582,5 @@
 }  // namespace testing
 }  // namespace bindings
 }  // namespace cobalt
+
+
diff --git a/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_derived_getter_setter_interface.cc b/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_derived_getter_setter_interface.cc
index c6eb535..4e37f83 100644
--- a/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_derived_getter_setter_interface.cc
+++ b/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_derived_getter_setter_interface.cc
@@ -22,8 +22,8 @@
 #include "base/debug/trace_event.h"
 #include "cobalt/base/polymorphic_downcast.h"
 #include "cobalt/script/global_environment.h"
-#include "cobalt/script/opaque_handle.h"
 #include "cobalt/script/script_value.h"
+#include "cobalt/script/value_handle.h"
 #include "cobalt/bindings/testing/mozjs_named_indexed_getter_interface.h"
 #include "cobalt/bindings/testing/named_indexed_getter_interface.h"
 
@@ -36,7 +36,6 @@
 #include "cobalt/script/mozjs-45/mozjs_callback_function.h"
 #include "cobalt/script/mozjs-45/mozjs_exception_state.h"
 #include "cobalt/script/mozjs-45/mozjs_global_environment.h"
-#include "cobalt/script/mozjs-45/mozjs_object_handle.h"
 #include "cobalt/script/mozjs-45/mozjs_property_enumerator.h"
 #include "cobalt/script/mozjs-45/mozjs_user_object_holder.h"
 #include "cobalt/script/mozjs-45/mozjs_value_handle.h"
@@ -57,10 +56,10 @@
 using cobalt::bindings::testing::NamedIndexedGetterInterface;
 using cobalt::script::CallbackInterfaceTraits;
 using cobalt::script::GlobalEnvironment;
-using cobalt::script::OpaqueHandle;
-using cobalt::script::OpaqueHandleHolder;
 using cobalt::script::ScriptValue;
 using cobalt::script::ValueHandle;
+using cobalt::script::ValueHandle;
+using cobalt::script::ValueHandleHolder;
 using cobalt::script::Wrappable;
 
 using cobalt::script::CallbackFunction;
@@ -84,6 +83,7 @@
 using cobalt::script::mozjs::kConversionFlagRestricted;
 using cobalt::script::mozjs::kConversionFlagTreatNullAsEmptyString;
 using cobalt::script::mozjs::kConversionFlagTreatUndefinedAsEmptyString;
+using cobalt::script::mozjs::kConversionFlagObjectOnly;
 using cobalt::script::mozjs::kNoConversionFlags;
 }  // namespace
 
@@ -909,3 +909,5 @@
 }  // namespace testing
 }  // namespace bindings
 }  // namespace cobalt
+
+
diff --git a/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_derived_interface.cc b/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_derived_interface.cc
index 3e5b114..6f9fb06 100644
--- a/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_derived_interface.cc
+++ b/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_derived_interface.cc
@@ -22,8 +22,8 @@
 #include "base/debug/trace_event.h"
 #include "cobalt/base/polymorphic_downcast.h"
 #include "cobalt/script/global_environment.h"
-#include "cobalt/script/opaque_handle.h"
 #include "cobalt/script/script_value.h"
+#include "cobalt/script/value_handle.h"
 #include "cobalt/bindings/testing/base_interface.h"
 #include "cobalt/bindings/testing/mozjs_base_interface.h"
 
@@ -36,7 +36,6 @@
 #include "cobalt/script/mozjs-45/mozjs_callback_function.h"
 #include "cobalt/script/mozjs-45/mozjs_exception_state.h"
 #include "cobalt/script/mozjs-45/mozjs_global_environment.h"
-#include "cobalt/script/mozjs-45/mozjs_object_handle.h"
 #include "cobalt/script/mozjs-45/mozjs_property_enumerator.h"
 #include "cobalt/script/mozjs-45/mozjs_user_object_holder.h"
 #include "cobalt/script/mozjs-45/mozjs_value_handle.h"
@@ -57,10 +56,10 @@
 using cobalt::bindings::testing::MozjsBaseInterface;
 using cobalt::script::CallbackInterfaceTraits;
 using cobalt::script::GlobalEnvironment;
-using cobalt::script::OpaqueHandle;
-using cobalt::script::OpaqueHandleHolder;
 using cobalt::script::ScriptValue;
 using cobalt::script::ValueHandle;
+using cobalt::script::ValueHandle;
+using cobalt::script::ValueHandleHolder;
 using cobalt::script::Wrappable;
 
 using cobalt::script::CallbackFunction;
@@ -84,6 +83,7 @@
 using cobalt::script::mozjs::kConversionFlagRestricted;
 using cobalt::script::mozjs::kConversionFlagTreatNullAsEmptyString;
 using cobalt::script::mozjs::kConversionFlagTreatUndefinedAsEmptyString;
+using cobalt::script::mozjs::kConversionFlagObjectOnly;
 using cobalt::script::mozjs::kNoConversionFlags;
 }  // namespace
 
@@ -481,3 +481,5 @@
 }  // namespace testing
 }  // namespace bindings
 }  // namespace cobalt
+
+
diff --git a/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_dictionary_interface.cc b/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_dictionary_interface.cc
index 85aa292..8a170b0 100644
--- a/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_dictionary_interface.cc
+++ b/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_dictionary_interface.cc
@@ -22,8 +22,8 @@
 #include "base/debug/trace_event.h"
 #include "cobalt/base/polymorphic_downcast.h"
 #include "cobalt/script/global_environment.h"
-#include "cobalt/script/opaque_handle.h"
 #include "cobalt/script/script_value.h"
+#include "cobalt/script/value_handle.h"
 #include "cobalt/bindings/testing/derived_dictionary.h"
 #include "cobalt/bindings/testing/dictionary_with_dictionary_member.h"
 #include "cobalt/bindings/testing/test_dictionary.h"
@@ -37,7 +37,6 @@
 #include "cobalt/script/mozjs-45/mozjs_callback_function.h"
 #include "cobalt/script/mozjs-45/mozjs_exception_state.h"
 #include "cobalt/script/mozjs-45/mozjs_global_environment.h"
-#include "cobalt/script/mozjs-45/mozjs_object_handle.h"
 #include "cobalt/script/mozjs-45/mozjs_property_enumerator.h"
 #include "cobalt/script/mozjs-45/mozjs_user_object_holder.h"
 #include "cobalt/script/mozjs-45/mozjs_value_handle.h"
@@ -59,10 +58,10 @@
 using cobalt::bindings::testing::TestDictionary;
 using cobalt::script::CallbackInterfaceTraits;
 using cobalt::script::GlobalEnvironment;
-using cobalt::script::OpaqueHandle;
-using cobalt::script::OpaqueHandleHolder;
 using cobalt::script::ScriptValue;
 using cobalt::script::ValueHandle;
+using cobalt::script::ValueHandle;
+using cobalt::script::ValueHandleHolder;
 using cobalt::script::Wrappable;
 
 using cobalt::script::CallbackFunction;
@@ -86,6 +85,7 @@
 using cobalt::script::mozjs::kConversionFlagRestricted;
 using cobalt::script::mozjs::kConversionFlagTreatNullAsEmptyString;
 using cobalt::script::mozjs::kConversionFlagTreatUndefinedAsEmptyString;
+using cobalt::script::mozjs::kConversionFlagObjectOnly;
 using cobalt::script::mozjs::kNoConversionFlags;
 }  // namespace
 
@@ -665,3 +665,5 @@
 }  // namespace testing
 }  // namespace bindings
 }  // namespace cobalt
+
+
diff --git a/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_disabled_interface.cc b/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_disabled_interface.cc
index 0a829bb..6d32fdc 100644
--- a/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_disabled_interface.cc
+++ b/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_disabled_interface.cc
@@ -24,8 +24,8 @@
 #include "base/debug/trace_event.h"
 #include "cobalt/base/polymorphic_downcast.h"
 #include "cobalt/script/global_environment.h"
-#include "cobalt/script/opaque_handle.h"
 #include "cobalt/script/script_value.h"
+#include "cobalt/script/value_handle.h"
 
 #include "mozjs_gen_type_conversion.h"
 
@@ -36,7 +36,6 @@
 #include "cobalt/script/mozjs-45/mozjs_callback_function.h"
 #include "cobalt/script/mozjs-45/mozjs_exception_state.h"
 #include "cobalt/script/mozjs-45/mozjs_global_environment.h"
-#include "cobalt/script/mozjs-45/mozjs_object_handle.h"
 #include "cobalt/script/mozjs-45/mozjs_property_enumerator.h"
 #include "cobalt/script/mozjs-45/mozjs_user_object_holder.h"
 #include "cobalt/script/mozjs-45/mozjs_value_handle.h"
@@ -55,10 +54,10 @@
 using cobalt::bindings::testing::MozjsDisabledInterface;
 using cobalt::script::CallbackInterfaceTraits;
 using cobalt::script::GlobalEnvironment;
-using cobalt::script::OpaqueHandle;
-using cobalt::script::OpaqueHandleHolder;
 using cobalt::script::ScriptValue;
 using cobalt::script::ValueHandle;
+using cobalt::script::ValueHandle;
+using cobalt::script::ValueHandleHolder;
 using cobalt::script::Wrappable;
 
 using cobalt::script::CallbackFunction;
@@ -82,6 +81,7 @@
 using cobalt::script::mozjs::kConversionFlagRestricted;
 using cobalt::script::mozjs::kConversionFlagTreatNullAsEmptyString;
 using cobalt::script::mozjs::kConversionFlagTreatUndefinedAsEmptyString;
+using cobalt::script::mozjs::kConversionFlagObjectOnly;
 using cobalt::script::mozjs::kNoConversionFlags;
 }  // namespace
 
@@ -509,4 +509,6 @@
 }  // namespace testing
 }  // namespace bindings
 }  // namespace cobalt
+
+
 #endif  // defined(NO_ENABLE_CONDITIONAL_INTERFACE)
diff --git a/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_dom_string_test_interface.cc b/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_dom_string_test_interface.cc
index 2f4b7f8..8958824 100644
--- a/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_dom_string_test_interface.cc
+++ b/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_dom_string_test_interface.cc
@@ -22,8 +22,8 @@
 #include "base/debug/trace_event.h"
 #include "cobalt/base/polymorphic_downcast.h"
 #include "cobalt/script/global_environment.h"
-#include "cobalt/script/opaque_handle.h"
 #include "cobalt/script/script_value.h"
+#include "cobalt/script/value_handle.h"
 
 #include "mozjs_gen_type_conversion.h"
 
@@ -34,7 +34,6 @@
 #include "cobalt/script/mozjs-45/mozjs_callback_function.h"
 #include "cobalt/script/mozjs-45/mozjs_exception_state.h"
 #include "cobalt/script/mozjs-45/mozjs_global_environment.h"
-#include "cobalt/script/mozjs-45/mozjs_object_handle.h"
 #include "cobalt/script/mozjs-45/mozjs_property_enumerator.h"
 #include "cobalt/script/mozjs-45/mozjs_user_object_holder.h"
 #include "cobalt/script/mozjs-45/mozjs_value_handle.h"
@@ -53,10 +52,10 @@
 using cobalt::bindings::testing::MozjsDOMStringTestInterface;
 using cobalt::script::CallbackInterfaceTraits;
 using cobalt::script::GlobalEnvironment;
-using cobalt::script::OpaqueHandle;
-using cobalt::script::OpaqueHandleHolder;
 using cobalt::script::ScriptValue;
 using cobalt::script::ValueHandle;
+using cobalt::script::ValueHandle;
+using cobalt::script::ValueHandleHolder;
 using cobalt::script::Wrappable;
 
 using cobalt::script::CallbackFunction;
@@ -80,6 +79,7 @@
 using cobalt::script::mozjs::kConversionFlagRestricted;
 using cobalt::script::mozjs::kConversionFlagTreatNullAsEmptyString;
 using cobalt::script::mozjs::kConversionFlagTreatUndefinedAsEmptyString;
+using cobalt::script::mozjs::kConversionFlagObjectOnly;
 using cobalt::script::mozjs::kNoConversionFlags;
 }  // namespace
 
@@ -884,3 +884,5 @@
 }  // namespace testing
 }  // namespace bindings
 }  // namespace cobalt
+
+
diff --git a/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_enumeration_interface.cc b/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_enumeration_interface.cc
index fb1bbf3..d8c8ddf 100644
--- a/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_enumeration_interface.cc
+++ b/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_enumeration_interface.cc
@@ -22,8 +22,8 @@
 #include "base/debug/trace_event.h"
 #include "cobalt/base/polymorphic_downcast.h"
 #include "cobalt/script/global_environment.h"
-#include "cobalt/script/opaque_handle.h"
 #include "cobalt/script/script_value.h"
+#include "cobalt/script/value_handle.h"
 #include "cobalt/bindings/testing/test_enum.h"
 
 #include "mozjs_gen_type_conversion.h"
@@ -35,7 +35,6 @@
 #include "cobalt/script/mozjs-45/mozjs_callback_function.h"
 #include "cobalt/script/mozjs-45/mozjs_exception_state.h"
 #include "cobalt/script/mozjs-45/mozjs_global_environment.h"
-#include "cobalt/script/mozjs-45/mozjs_object_handle.h"
 #include "cobalt/script/mozjs-45/mozjs_property_enumerator.h"
 #include "cobalt/script/mozjs-45/mozjs_user_object_holder.h"
 #include "cobalt/script/mozjs-45/mozjs_value_handle.h"
@@ -55,10 +54,10 @@
 using cobalt::bindings::testing::TestEnum;
 using cobalt::script::CallbackInterfaceTraits;
 using cobalt::script::GlobalEnvironment;
-using cobalt::script::OpaqueHandle;
-using cobalt::script::OpaqueHandleHolder;
 using cobalt::script::ScriptValue;
 using cobalt::script::ValueHandle;
+using cobalt::script::ValueHandle;
+using cobalt::script::ValueHandleHolder;
 using cobalt::script::Wrappable;
 
 using cobalt::script::CallbackFunction;
@@ -82,6 +81,7 @@
 using cobalt::script::mozjs::kConversionFlagRestricted;
 using cobalt::script::mozjs::kConversionFlagTreatNullAsEmptyString;
 using cobalt::script::mozjs::kConversionFlagTreatUndefinedAsEmptyString;
+using cobalt::script::mozjs::kConversionFlagObjectOnly;
 using cobalt::script::mozjs::kNoConversionFlags;
 }  // namespace
 
@@ -547,3 +547,5 @@
 }  // namespace testing
 }  // namespace bindings
 }  // namespace cobalt
+
+
diff --git a/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_exception_object_interface.cc b/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_exception_object_interface.cc
index f826cee..5d41a65 100644
--- a/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_exception_object_interface.cc
+++ b/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_exception_object_interface.cc
@@ -22,8 +22,8 @@
 #include "base/debug/trace_event.h"
 #include "cobalt/base/polymorphic_downcast.h"
 #include "cobalt/script/global_environment.h"
-#include "cobalt/script/opaque_handle.h"
 #include "cobalt/script/script_value.h"
+#include "cobalt/script/value_handle.h"
 
 #include "mozjs_gen_type_conversion.h"
 
@@ -34,7 +34,6 @@
 #include "cobalt/script/mozjs-45/mozjs_callback_function.h"
 #include "cobalt/script/mozjs-45/mozjs_exception_state.h"
 #include "cobalt/script/mozjs-45/mozjs_global_environment.h"
-#include "cobalt/script/mozjs-45/mozjs_object_handle.h"
 #include "cobalt/script/mozjs-45/mozjs_property_enumerator.h"
 #include "cobalt/script/mozjs-45/mozjs_user_object_holder.h"
 #include "cobalt/script/mozjs-45/mozjs_value_handle.h"
@@ -54,10 +53,10 @@
 using cobalt::bindings::testing::MozjsExceptionObjectInterface;
 using cobalt::script::CallbackInterfaceTraits;
 using cobalt::script::GlobalEnvironment;
-using cobalt::script::OpaqueHandle;
-using cobalt::script::OpaqueHandleHolder;
 using cobalt::script::ScriptValue;
 using cobalt::script::ValueHandle;
+using cobalt::script::ValueHandle;
+using cobalt::script::ValueHandleHolder;
 using cobalt::script::Wrappable;
 
 using cobalt::script::CallbackFunction;
@@ -81,6 +80,7 @@
 using cobalt::script::mozjs::kConversionFlagRestricted;
 using cobalt::script::mozjs::kConversionFlagTreatNullAsEmptyString;
 using cobalt::script::mozjs::kConversionFlagTreatUndefinedAsEmptyString;
+using cobalt::script::mozjs::kConversionFlagObjectOnly;
 using cobalt::script::mozjs::kNoConversionFlags;
 }  // namespace
 
@@ -464,3 +464,5 @@
 }  // namespace testing
 }  // namespace bindings
 }  // namespace cobalt
+
+
diff --git a/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_exceptions_interface.cc b/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_exceptions_interface.cc
index c68f5b0..ae894b0 100644
--- a/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_exceptions_interface.cc
+++ b/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_exceptions_interface.cc
@@ -22,8 +22,8 @@
 #include "base/debug/trace_event.h"
 #include "cobalt/base/polymorphic_downcast.h"
 #include "cobalt/script/global_environment.h"
-#include "cobalt/script/opaque_handle.h"
 #include "cobalt/script/script_value.h"
+#include "cobalt/script/value_handle.h"
 
 #include "mozjs_gen_type_conversion.h"
 
@@ -34,7 +34,6 @@
 #include "cobalt/script/mozjs-45/mozjs_callback_function.h"
 #include "cobalt/script/mozjs-45/mozjs_exception_state.h"
 #include "cobalt/script/mozjs-45/mozjs_global_environment.h"
-#include "cobalt/script/mozjs-45/mozjs_object_handle.h"
 #include "cobalt/script/mozjs-45/mozjs_property_enumerator.h"
 #include "cobalt/script/mozjs-45/mozjs_user_object_holder.h"
 #include "cobalt/script/mozjs-45/mozjs_value_handle.h"
@@ -53,10 +52,10 @@
 using cobalt::bindings::testing::MozjsExceptionsInterface;
 using cobalt::script::CallbackInterfaceTraits;
 using cobalt::script::GlobalEnvironment;
-using cobalt::script::OpaqueHandle;
-using cobalt::script::OpaqueHandleHolder;
 using cobalt::script::ScriptValue;
 using cobalt::script::ValueHandle;
+using cobalt::script::ValueHandle;
+using cobalt::script::ValueHandleHolder;
 using cobalt::script::Wrappable;
 
 using cobalt::script::CallbackFunction;
@@ -80,6 +79,7 @@
 using cobalt::script::mozjs::kConversionFlagRestricted;
 using cobalt::script::mozjs::kConversionFlagTreatNullAsEmptyString;
 using cobalt::script::mozjs::kConversionFlagTreatUndefinedAsEmptyString;
+using cobalt::script::mozjs::kConversionFlagObjectOnly;
 using cobalt::script::mozjs::kNoConversionFlags;
 }  // namespace
 
@@ -533,3 +533,5 @@
 }  // namespace testing
 }  // namespace bindings
 }  // namespace cobalt
+
+
diff --git a/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_extended_idl_attributes_interface.cc b/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_extended_idl_attributes_interface.cc
index 0bb6b92..1e0ef66 100644
--- a/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_extended_idl_attributes_interface.cc
+++ b/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_extended_idl_attributes_interface.cc
@@ -22,8 +22,8 @@
 #include "base/debug/trace_event.h"
 #include "cobalt/base/polymorphic_downcast.h"
 #include "cobalt/script/global_environment.h"
-#include "cobalt/script/opaque_handle.h"
 #include "cobalt/script/script_value.h"
+#include "cobalt/script/value_handle.h"
 
 #include "mozjs_gen_type_conversion.h"
 
@@ -34,7 +34,6 @@
 #include "cobalt/script/mozjs-45/mozjs_callback_function.h"
 #include "cobalt/script/mozjs-45/mozjs_exception_state.h"
 #include "cobalt/script/mozjs-45/mozjs_global_environment.h"
-#include "cobalt/script/mozjs-45/mozjs_object_handle.h"
 #include "cobalt/script/mozjs-45/mozjs_property_enumerator.h"
 #include "cobalt/script/mozjs-45/mozjs_user_object_holder.h"
 #include "cobalt/script/mozjs-45/mozjs_value_handle.h"
@@ -53,10 +52,10 @@
 using cobalt::bindings::testing::MozjsExtendedIDLAttributesInterface;
 using cobalt::script::CallbackInterfaceTraits;
 using cobalt::script::GlobalEnvironment;
-using cobalt::script::OpaqueHandle;
-using cobalt::script::OpaqueHandleHolder;
 using cobalt::script::ScriptValue;
 using cobalt::script::ValueHandle;
+using cobalt::script::ValueHandle;
+using cobalt::script::ValueHandleHolder;
 using cobalt::script::Wrappable;
 
 using cobalt::script::CallbackFunction;
@@ -80,6 +79,7 @@
 using cobalt::script::mozjs::kConversionFlagRestricted;
 using cobalt::script::mozjs::kConversionFlagTreatNullAsEmptyString;
 using cobalt::script::mozjs::kConversionFlagTreatUndefinedAsEmptyString;
+using cobalt::script::mozjs::kConversionFlagObjectOnly;
 using cobalt::script::mozjs::kNoConversionFlags;
 }  // namespace
 
@@ -576,3 +576,5 @@
 }  // namespace testing
 }  // namespace bindings
 }  // namespace cobalt
+
+
diff --git a/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_garbage_collection_test_interface.cc b/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_garbage_collection_test_interface.cc
index 516292d..bc23f28 100644
--- a/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_garbage_collection_test_interface.cc
+++ b/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_garbage_collection_test_interface.cc
@@ -22,8 +22,8 @@
 #include "base/debug/trace_event.h"
 #include "cobalt/base/polymorphic_downcast.h"
 #include "cobalt/script/global_environment.h"
-#include "cobalt/script/opaque_handle.h"
 #include "cobalt/script/script_value.h"
+#include "cobalt/script/value_handle.h"
 #include "cobalt/bindings/testing/garbage_collection_test_interface.h"
 #include "cobalt/bindings/testing/mozjs_garbage_collection_test_interface.h"
 
@@ -36,7 +36,6 @@
 #include "cobalt/script/mozjs-45/mozjs_callback_function.h"
 #include "cobalt/script/mozjs-45/mozjs_exception_state.h"
 #include "cobalt/script/mozjs-45/mozjs_global_environment.h"
-#include "cobalt/script/mozjs-45/mozjs_object_handle.h"
 #include "cobalt/script/mozjs-45/mozjs_property_enumerator.h"
 #include "cobalt/script/mozjs-45/mozjs_user_object_holder.h"
 #include "cobalt/script/mozjs-45/mozjs_value_handle.h"
@@ -57,10 +56,10 @@
 using cobalt::bindings::testing::MozjsGarbageCollectionTestInterface;
 using cobalt::script::CallbackInterfaceTraits;
 using cobalt::script::GlobalEnvironment;
-using cobalt::script::OpaqueHandle;
-using cobalt::script::OpaqueHandleHolder;
 using cobalt::script::ScriptValue;
 using cobalt::script::ValueHandle;
+using cobalt::script::ValueHandle;
+using cobalt::script::ValueHandleHolder;
 using cobalt::script::Wrappable;
 
 using cobalt::script::CallbackFunction;
@@ -84,6 +83,7 @@
 using cobalt::script::mozjs::kConversionFlagRestricted;
 using cobalt::script::mozjs::kConversionFlagTreatNullAsEmptyString;
 using cobalt::script::mozjs::kConversionFlagTreatUndefinedAsEmptyString;
+using cobalt::script::mozjs::kConversionFlagObjectOnly;
 using cobalt::script::mozjs::kNoConversionFlags;
 }  // namespace
 
@@ -590,3 +590,5 @@
 }  // namespace testing
 }  // namespace bindings
 }  // namespace cobalt
+
+
diff --git a/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_global_interface_parent.cc b/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_global_interface_parent.cc
index aae9abc..bd1c4f6 100644
--- a/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_global_interface_parent.cc
+++ b/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_global_interface_parent.cc
@@ -22,8 +22,8 @@
 #include "base/debug/trace_event.h"
 #include "cobalt/base/polymorphic_downcast.h"
 #include "cobalt/script/global_environment.h"
-#include "cobalt/script/opaque_handle.h"
 #include "cobalt/script/script_value.h"
+#include "cobalt/script/value_handle.h"
 
 #include "mozjs_gen_type_conversion.h"
 
@@ -34,7 +34,6 @@
 #include "cobalt/script/mozjs-45/mozjs_callback_function.h"
 #include "cobalt/script/mozjs-45/mozjs_exception_state.h"
 #include "cobalt/script/mozjs-45/mozjs_global_environment.h"
-#include "cobalt/script/mozjs-45/mozjs_object_handle.h"
 #include "cobalt/script/mozjs-45/mozjs_property_enumerator.h"
 #include "cobalt/script/mozjs-45/mozjs_user_object_holder.h"
 #include "cobalt/script/mozjs-45/mozjs_value_handle.h"
@@ -53,10 +52,10 @@
 using cobalt::bindings::testing::MozjsGlobalInterfaceParent;
 using cobalt::script::CallbackInterfaceTraits;
 using cobalt::script::GlobalEnvironment;
-using cobalt::script::OpaqueHandle;
-using cobalt::script::OpaqueHandleHolder;
 using cobalt::script::ScriptValue;
 using cobalt::script::ValueHandle;
+using cobalt::script::ValueHandle;
+using cobalt::script::ValueHandleHolder;
 using cobalt::script::Wrappable;
 
 using cobalt::script::CallbackFunction;
@@ -80,6 +79,7 @@
 using cobalt::script::mozjs::kConversionFlagRestricted;
 using cobalt::script::mozjs::kConversionFlagTreatNullAsEmptyString;
 using cobalt::script::mozjs::kConversionFlagTreatUndefinedAsEmptyString;
+using cobalt::script::mozjs::kConversionFlagObjectOnly;
 using cobalt::script::mozjs::kNoConversionFlags;
 }  // namespace
 
@@ -401,3 +401,5 @@
 }  // namespace testing
 }  // namespace bindings
 }  // namespace cobalt
+
+
diff --git a/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_indexed_getter_interface.cc b/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_indexed_getter_interface.cc
index 3dbdd6f..77a6cac 100644
--- a/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_indexed_getter_interface.cc
+++ b/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_indexed_getter_interface.cc
@@ -22,8 +22,8 @@
 #include "base/debug/trace_event.h"
 #include "cobalt/base/polymorphic_downcast.h"
 #include "cobalt/script/global_environment.h"
-#include "cobalt/script/opaque_handle.h"
 #include "cobalt/script/script_value.h"
+#include "cobalt/script/value_handle.h"
 
 #include "mozjs_gen_type_conversion.h"
 
@@ -34,7 +34,6 @@
 #include "cobalt/script/mozjs-45/mozjs_callback_function.h"
 #include "cobalt/script/mozjs-45/mozjs_exception_state.h"
 #include "cobalt/script/mozjs-45/mozjs_global_environment.h"
-#include "cobalt/script/mozjs-45/mozjs_object_handle.h"
 #include "cobalt/script/mozjs-45/mozjs_property_enumerator.h"
 #include "cobalt/script/mozjs-45/mozjs_user_object_holder.h"
 #include "cobalt/script/mozjs-45/mozjs_value_handle.h"
@@ -53,10 +52,10 @@
 using cobalt::bindings::testing::MozjsIndexedGetterInterface;
 using cobalt::script::CallbackInterfaceTraits;
 using cobalt::script::GlobalEnvironment;
-using cobalt::script::OpaqueHandle;
-using cobalt::script::OpaqueHandleHolder;
 using cobalt::script::ScriptValue;
 using cobalt::script::ValueHandle;
+using cobalt::script::ValueHandle;
+using cobalt::script::ValueHandleHolder;
 using cobalt::script::Wrappable;
 
 using cobalt::script::CallbackFunction;
@@ -80,6 +79,7 @@
 using cobalt::script::mozjs::kConversionFlagRestricted;
 using cobalt::script::mozjs::kConversionFlagTreatNullAsEmptyString;
 using cobalt::script::mozjs::kConversionFlagTreatUndefinedAsEmptyString;
+using cobalt::script::mozjs::kConversionFlagObjectOnly;
 using cobalt::script::mozjs::kNoConversionFlags;
 }  // namespace
 
@@ -735,3 +735,5 @@
 }  // namespace testing
 }  // namespace bindings
 }  // namespace cobalt
+
+
diff --git a/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_interface_with_any.cc b/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_interface_with_any.cc
index 9251dee..941f391 100644
--- a/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_interface_with_any.cc
+++ b/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_interface_with_any.cc
@@ -22,8 +22,8 @@
 #include "base/debug/trace_event.h"
 #include "cobalt/base/polymorphic_downcast.h"
 #include "cobalt/script/global_environment.h"
-#include "cobalt/script/opaque_handle.h"
 #include "cobalt/script/script_value.h"
+#include "cobalt/script/value_handle.h"
 
 #include "mozjs_gen_type_conversion.h"
 
@@ -34,7 +34,6 @@
 #include "cobalt/script/mozjs-45/mozjs_callback_function.h"
 #include "cobalt/script/mozjs-45/mozjs_exception_state.h"
 #include "cobalt/script/mozjs-45/mozjs_global_environment.h"
-#include "cobalt/script/mozjs-45/mozjs_object_handle.h"
 #include "cobalt/script/mozjs-45/mozjs_property_enumerator.h"
 #include "cobalt/script/mozjs-45/mozjs_user_object_holder.h"
 #include "cobalt/script/mozjs-45/mozjs_value_handle.h"
@@ -53,10 +52,10 @@
 using cobalt::bindings::testing::MozjsInterfaceWithAny;
 using cobalt::script::CallbackInterfaceTraits;
 using cobalt::script::GlobalEnvironment;
-using cobalt::script::OpaqueHandle;
-using cobalt::script::OpaqueHandleHolder;
 using cobalt::script::ScriptValue;
 using cobalt::script::ValueHandle;
+using cobalt::script::ValueHandle;
+using cobalt::script::ValueHandleHolder;
 using cobalt::script::Wrappable;
 
 using cobalt::script::CallbackFunction;
@@ -80,6 +79,7 @@
 using cobalt::script::mozjs::kConversionFlagRestricted;
 using cobalt::script::mozjs::kConversionFlagTreatNullAsEmptyString;
 using cobalt::script::mozjs::kConversionFlagTreatUndefinedAsEmptyString;
+using cobalt::script::mozjs::kConversionFlagObjectOnly;
 using cobalt::script::mozjs::kNoConversionFlags;
 }  // namespace
 
@@ -496,3 +496,5 @@
 }  // namespace testing
 }  // namespace bindings
 }  // namespace cobalt
+
+
diff --git a/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_interface_with_any_dictionary.cc b/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_interface_with_any_dictionary.cc
index 72f9597..7c1d349 100644
--- a/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_interface_with_any_dictionary.cc
+++ b/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_interface_with_any_dictionary.cc
@@ -22,8 +22,8 @@
 #include "base/debug/trace_event.h"
 #include "cobalt/base/polymorphic_downcast.h"
 #include "cobalt/script/global_environment.h"
-#include "cobalt/script/opaque_handle.h"
 #include "cobalt/script/script_value.h"
+#include "cobalt/script/value_handle.h"
 
 #include "mozjs_gen_type_conversion.h"
 
@@ -34,7 +34,6 @@
 #include "cobalt/script/mozjs-45/mozjs_callback_function.h"
 #include "cobalt/script/mozjs-45/mozjs_exception_state.h"
 #include "cobalt/script/mozjs-45/mozjs_global_environment.h"
-#include "cobalt/script/mozjs-45/mozjs_object_handle.h"
 #include "cobalt/script/mozjs-45/mozjs_property_enumerator.h"
 #include "cobalt/script/mozjs-45/mozjs_user_object_holder.h"
 #include "cobalt/script/mozjs-45/mozjs_value_handle.h"
@@ -53,10 +52,10 @@
 using cobalt::bindings::testing::MozjsInterfaceWithAnyDictionary;
 using cobalt::script::CallbackInterfaceTraits;
 using cobalt::script::GlobalEnvironment;
-using cobalt::script::OpaqueHandle;
-using cobalt::script::OpaqueHandleHolder;
 using cobalt::script::ScriptValue;
 using cobalt::script::ValueHandle;
+using cobalt::script::ValueHandle;
+using cobalt::script::ValueHandleHolder;
 using cobalt::script::Wrappable;
 
 using cobalt::script::CallbackFunction;
@@ -80,6 +79,7 @@
 using cobalt::script::mozjs::kConversionFlagRestricted;
 using cobalt::script::mozjs::kConversionFlagTreatNullAsEmptyString;
 using cobalt::script::mozjs::kConversionFlagTreatUndefinedAsEmptyString;
+using cobalt::script::mozjs::kConversionFlagObjectOnly;
 using cobalt::script::mozjs::kNoConversionFlags;
 }  // namespace
 
@@ -606,3 +606,5 @@
 }  // namespace testing
 }  // namespace bindings
 }  // namespace cobalt
+
+
diff --git a/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_interface_with_unsupported_properties.cc b/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_interface_with_unsupported_properties.cc
index 1e9f8a3..69406e6 100644
--- a/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_interface_with_unsupported_properties.cc
+++ b/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_interface_with_unsupported_properties.cc
@@ -22,8 +22,8 @@
 #include "base/debug/trace_event.h"
 #include "cobalt/base/polymorphic_downcast.h"
 #include "cobalt/script/global_environment.h"
-#include "cobalt/script/opaque_handle.h"
 #include "cobalt/script/script_value.h"
+#include "cobalt/script/value_handle.h"
 
 #include "mozjs_gen_type_conversion.h"
 
@@ -34,7 +34,6 @@
 #include "cobalt/script/mozjs-45/mozjs_callback_function.h"
 #include "cobalt/script/mozjs-45/mozjs_exception_state.h"
 #include "cobalt/script/mozjs-45/mozjs_global_environment.h"
-#include "cobalt/script/mozjs-45/mozjs_object_handle.h"
 #include "cobalt/script/mozjs-45/mozjs_property_enumerator.h"
 #include "cobalt/script/mozjs-45/mozjs_user_object_holder.h"
 #include "cobalt/script/mozjs-45/mozjs_value_handle.h"
@@ -53,10 +52,10 @@
 using cobalt::bindings::testing::MozjsInterfaceWithUnsupportedProperties;
 using cobalt::script::CallbackInterfaceTraits;
 using cobalt::script::GlobalEnvironment;
-using cobalt::script::OpaqueHandle;
-using cobalt::script::OpaqueHandleHolder;
 using cobalt::script::ScriptValue;
 using cobalt::script::ValueHandle;
+using cobalt::script::ValueHandle;
+using cobalt::script::ValueHandleHolder;
 using cobalt::script::Wrappable;
 
 using cobalt::script::CallbackFunction;
@@ -80,6 +79,7 @@
 using cobalt::script::mozjs::kConversionFlagRestricted;
 using cobalt::script::mozjs::kConversionFlagTreatNullAsEmptyString;
 using cobalt::script::mozjs::kConversionFlagTreatUndefinedAsEmptyString;
+using cobalt::script::mozjs::kConversionFlagObjectOnly;
 using cobalt::script::mozjs::kNoConversionFlags;
 }  // namespace
 
@@ -406,3 +406,5 @@
 }  // namespace testing
 }  // namespace bindings
 }  // namespace cobalt
+
+
diff --git a/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_named_constructor_interface.cc b/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_named_constructor_interface.cc
index a045a97..e1f0dd7 100644
--- a/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_named_constructor_interface.cc
+++ b/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_named_constructor_interface.cc
@@ -22,8 +22,8 @@
 #include "base/debug/trace_event.h"
 #include "cobalt/base/polymorphic_downcast.h"
 #include "cobalt/script/global_environment.h"
-#include "cobalt/script/opaque_handle.h"
 #include "cobalt/script/script_value.h"
+#include "cobalt/script/value_handle.h"
 
 #include "mozjs_gen_type_conversion.h"
 
@@ -34,7 +34,6 @@
 #include "cobalt/script/mozjs-45/mozjs_callback_function.h"
 #include "cobalt/script/mozjs-45/mozjs_exception_state.h"
 #include "cobalt/script/mozjs-45/mozjs_global_environment.h"
-#include "cobalt/script/mozjs-45/mozjs_object_handle.h"
 #include "cobalt/script/mozjs-45/mozjs_property_enumerator.h"
 #include "cobalt/script/mozjs-45/mozjs_user_object_holder.h"
 #include "cobalt/script/mozjs-45/mozjs_value_handle.h"
@@ -53,10 +52,10 @@
 using cobalt::bindings::testing::MozjsNamedConstructorInterface;
 using cobalt::script::CallbackInterfaceTraits;
 using cobalt::script::GlobalEnvironment;
-using cobalt::script::OpaqueHandle;
-using cobalt::script::OpaqueHandleHolder;
 using cobalt::script::ScriptValue;
 using cobalt::script::ValueHandle;
+using cobalt::script::ValueHandle;
+using cobalt::script::ValueHandleHolder;
 using cobalt::script::Wrappable;
 
 using cobalt::script::CallbackFunction;
@@ -80,6 +79,7 @@
 using cobalt::script::mozjs::kConversionFlagRestricted;
 using cobalt::script::mozjs::kConversionFlagTreatNullAsEmptyString;
 using cobalt::script::mozjs::kConversionFlagTreatUndefinedAsEmptyString;
+using cobalt::script::mozjs::kConversionFlagObjectOnly;
 using cobalt::script::mozjs::kNoConversionFlags;
 }  // namespace
 
@@ -374,3 +374,5 @@
 }  // namespace testing
 }  // namespace bindings
 }  // namespace cobalt
+
+
diff --git a/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_named_getter_interface.cc b/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_named_getter_interface.cc
index 0ab91ae..1ebe67d 100644
--- a/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_named_getter_interface.cc
+++ b/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_named_getter_interface.cc
@@ -22,8 +22,8 @@
 #include "base/debug/trace_event.h"
 #include "cobalt/base/polymorphic_downcast.h"
 #include "cobalt/script/global_environment.h"
-#include "cobalt/script/opaque_handle.h"
 #include "cobalt/script/script_value.h"
+#include "cobalt/script/value_handle.h"
 
 #include "mozjs_gen_type_conversion.h"
 
@@ -34,7 +34,6 @@
 #include "cobalt/script/mozjs-45/mozjs_callback_function.h"
 #include "cobalt/script/mozjs-45/mozjs_exception_state.h"
 #include "cobalt/script/mozjs-45/mozjs_global_environment.h"
-#include "cobalt/script/mozjs-45/mozjs_object_handle.h"
 #include "cobalt/script/mozjs-45/mozjs_property_enumerator.h"
 #include "cobalt/script/mozjs-45/mozjs_user_object_holder.h"
 #include "cobalt/script/mozjs-45/mozjs_value_handle.h"
@@ -53,10 +52,10 @@
 using cobalt::bindings::testing::MozjsNamedGetterInterface;
 using cobalt::script::CallbackInterfaceTraits;
 using cobalt::script::GlobalEnvironment;
-using cobalt::script::OpaqueHandle;
-using cobalt::script::OpaqueHandleHolder;
 using cobalt::script::ScriptValue;
 using cobalt::script::ValueHandle;
+using cobalt::script::ValueHandle;
+using cobalt::script::ValueHandleHolder;
 using cobalt::script::Wrappable;
 
 using cobalt::script::CallbackFunction;
@@ -80,6 +79,7 @@
 using cobalt::script::mozjs::kConversionFlagRestricted;
 using cobalt::script::mozjs::kConversionFlagTreatNullAsEmptyString;
 using cobalt::script::mozjs::kConversionFlagTreatUndefinedAsEmptyString;
+using cobalt::script::mozjs::kConversionFlagObjectOnly;
 using cobalt::script::mozjs::kNoConversionFlags;
 }  // namespace
 
@@ -683,3 +683,5 @@
 }  // namespace testing
 }  // namespace bindings
 }  // namespace cobalt
+
+
diff --git a/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_named_indexed_getter_interface.cc b/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_named_indexed_getter_interface.cc
index d306f6c..fe2a9a0 100644
--- a/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_named_indexed_getter_interface.cc
+++ b/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_named_indexed_getter_interface.cc
@@ -22,8 +22,8 @@
 #include "base/debug/trace_event.h"
 #include "cobalt/base/polymorphic_downcast.h"
 #include "cobalt/script/global_environment.h"
-#include "cobalt/script/opaque_handle.h"
 #include "cobalt/script/script_value.h"
+#include "cobalt/script/value_handle.h"
 
 #include "mozjs_gen_type_conversion.h"
 
@@ -34,7 +34,6 @@
 #include "cobalt/script/mozjs-45/mozjs_callback_function.h"
 #include "cobalt/script/mozjs-45/mozjs_exception_state.h"
 #include "cobalt/script/mozjs-45/mozjs_global_environment.h"
-#include "cobalt/script/mozjs-45/mozjs_object_handle.h"
 #include "cobalt/script/mozjs-45/mozjs_property_enumerator.h"
 #include "cobalt/script/mozjs-45/mozjs_user_object_holder.h"
 #include "cobalt/script/mozjs-45/mozjs_value_handle.h"
@@ -53,10 +52,10 @@
 using cobalt::bindings::testing::MozjsNamedIndexedGetterInterface;
 using cobalt::script::CallbackInterfaceTraits;
 using cobalt::script::GlobalEnvironment;
-using cobalt::script::OpaqueHandle;
-using cobalt::script::OpaqueHandleHolder;
 using cobalt::script::ScriptValue;
 using cobalt::script::ValueHandle;
+using cobalt::script::ValueHandle;
+using cobalt::script::ValueHandleHolder;
 using cobalt::script::Wrappable;
 
 using cobalt::script::CallbackFunction;
@@ -80,6 +79,7 @@
 using cobalt::script::mozjs::kConversionFlagRestricted;
 using cobalt::script::mozjs::kConversionFlagTreatNullAsEmptyString;
 using cobalt::script::mozjs::kConversionFlagTreatUndefinedAsEmptyString;
+using cobalt::script::mozjs::kConversionFlagObjectOnly;
 using cobalt::script::mozjs::kNoConversionFlags;
 }  // namespace
 
@@ -1057,3 +1057,5 @@
 }  // namespace testing
 }  // namespace bindings
 }  // namespace cobalt
+
+
diff --git a/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_nested_put_forwards_interface.cc b/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_nested_put_forwards_interface.cc
index 1873dba..55d4725 100644
--- a/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_nested_put_forwards_interface.cc
+++ b/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_nested_put_forwards_interface.cc
@@ -22,8 +22,8 @@
 #include "base/debug/trace_event.h"
 #include "cobalt/base/polymorphic_downcast.h"
 #include "cobalt/script/global_environment.h"
-#include "cobalt/script/opaque_handle.h"
 #include "cobalt/script/script_value.h"
+#include "cobalt/script/value_handle.h"
 #include "cobalt/bindings/testing/mozjs_put_forwards_interface.h"
 #include "cobalt/bindings/testing/put_forwards_interface.h"
 
@@ -36,7 +36,6 @@
 #include "cobalt/script/mozjs-45/mozjs_callback_function.h"
 #include "cobalt/script/mozjs-45/mozjs_exception_state.h"
 #include "cobalt/script/mozjs-45/mozjs_global_environment.h"
-#include "cobalt/script/mozjs-45/mozjs_object_handle.h"
 #include "cobalt/script/mozjs-45/mozjs_property_enumerator.h"
 #include "cobalt/script/mozjs-45/mozjs_user_object_holder.h"
 #include "cobalt/script/mozjs-45/mozjs_value_handle.h"
@@ -57,10 +56,10 @@
 using cobalt::bindings::testing::PutForwardsInterface;
 using cobalt::script::CallbackInterfaceTraits;
 using cobalt::script::GlobalEnvironment;
-using cobalt::script::OpaqueHandle;
-using cobalt::script::OpaqueHandleHolder;
 using cobalt::script::ScriptValue;
 using cobalt::script::ValueHandle;
+using cobalt::script::ValueHandle;
+using cobalt::script::ValueHandleHolder;
 using cobalt::script::Wrappable;
 
 using cobalt::script::CallbackFunction;
@@ -84,6 +83,7 @@
 using cobalt::script::mozjs::kConversionFlagRestricted;
 using cobalt::script::mozjs::kConversionFlagTreatNullAsEmptyString;
 using cobalt::script::mozjs::kConversionFlagTreatUndefinedAsEmptyString;
+using cobalt::script::mozjs::kConversionFlagObjectOnly;
 using cobalt::script::mozjs::kNoConversionFlags;
 }  // namespace
 
@@ -484,3 +484,5 @@
 }  // namespace testing
 }  // namespace bindings
 }  // namespace cobalt
+
+
diff --git a/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_no_constructor_interface.cc b/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_no_constructor_interface.cc
index 242d0db..c02f954 100644
--- a/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_no_constructor_interface.cc
+++ b/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_no_constructor_interface.cc
@@ -22,8 +22,8 @@
 #include "base/debug/trace_event.h"
 #include "cobalt/base/polymorphic_downcast.h"
 #include "cobalt/script/global_environment.h"
-#include "cobalt/script/opaque_handle.h"
 #include "cobalt/script/script_value.h"
+#include "cobalt/script/value_handle.h"
 
 #include "mozjs_gen_type_conversion.h"
 
@@ -34,7 +34,6 @@
 #include "cobalt/script/mozjs-45/mozjs_callback_function.h"
 #include "cobalt/script/mozjs-45/mozjs_exception_state.h"
 #include "cobalt/script/mozjs-45/mozjs_global_environment.h"
-#include "cobalt/script/mozjs-45/mozjs_object_handle.h"
 #include "cobalt/script/mozjs-45/mozjs_property_enumerator.h"
 #include "cobalt/script/mozjs-45/mozjs_user_object_holder.h"
 #include "cobalt/script/mozjs-45/mozjs_value_handle.h"
@@ -53,10 +52,10 @@
 using cobalt::bindings::testing::MozjsNoConstructorInterface;
 using cobalt::script::CallbackInterfaceTraits;
 using cobalt::script::GlobalEnvironment;
-using cobalt::script::OpaqueHandle;
-using cobalt::script::OpaqueHandleHolder;
 using cobalt::script::ScriptValue;
 using cobalt::script::ValueHandle;
+using cobalt::script::ValueHandle;
+using cobalt::script::ValueHandleHolder;
 using cobalt::script::Wrappable;
 
 using cobalt::script::CallbackFunction;
@@ -80,6 +79,7 @@
 using cobalt::script::mozjs::kConversionFlagRestricted;
 using cobalt::script::mozjs::kConversionFlagTreatNullAsEmptyString;
 using cobalt::script::mozjs::kConversionFlagTreatUndefinedAsEmptyString;
+using cobalt::script::mozjs::kConversionFlagObjectOnly;
 using cobalt::script::mozjs::kNoConversionFlags;
 }  // namespace
 
@@ -352,3 +352,5 @@
 }  // namespace testing
 }  // namespace bindings
 }  // namespace cobalt
+
+
diff --git a/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_no_interface_object_interface.cc b/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_no_interface_object_interface.cc
index ef77f03..354cf74 100644
--- a/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_no_interface_object_interface.cc
+++ b/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_no_interface_object_interface.cc
@@ -22,8 +22,8 @@
 #include "base/debug/trace_event.h"
 #include "cobalt/base/polymorphic_downcast.h"
 #include "cobalt/script/global_environment.h"
-#include "cobalt/script/opaque_handle.h"
 #include "cobalt/script/script_value.h"
+#include "cobalt/script/value_handle.h"
 
 #include "mozjs_gen_type_conversion.h"
 
@@ -34,7 +34,6 @@
 #include "cobalt/script/mozjs-45/mozjs_callback_function.h"
 #include "cobalt/script/mozjs-45/mozjs_exception_state.h"
 #include "cobalt/script/mozjs-45/mozjs_global_environment.h"
-#include "cobalt/script/mozjs-45/mozjs_object_handle.h"
 #include "cobalt/script/mozjs-45/mozjs_property_enumerator.h"
 #include "cobalt/script/mozjs-45/mozjs_user_object_holder.h"
 #include "cobalt/script/mozjs-45/mozjs_value_handle.h"
@@ -53,10 +52,10 @@
 using cobalt::bindings::testing::MozjsNoInterfaceObjectInterface;
 using cobalt::script::CallbackInterfaceTraits;
 using cobalt::script::GlobalEnvironment;
-using cobalt::script::OpaqueHandle;
-using cobalt::script::OpaqueHandleHolder;
 using cobalt::script::ScriptValue;
 using cobalt::script::ValueHandle;
+using cobalt::script::ValueHandle;
+using cobalt::script::ValueHandleHolder;
 using cobalt::script::Wrappable;
 
 using cobalt::script::CallbackFunction;
@@ -80,6 +79,7 @@
 using cobalt::script::mozjs::kConversionFlagRestricted;
 using cobalt::script::mozjs::kConversionFlagTreatNullAsEmptyString;
 using cobalt::script::mozjs::kConversionFlagTreatUndefinedAsEmptyString;
+using cobalt::script::mozjs::kConversionFlagObjectOnly;
 using cobalt::script::mozjs::kNoConversionFlags;
 }  // namespace
 
@@ -301,3 +301,5 @@
 }  // namespace testing
 }  // namespace bindings
 }  // namespace cobalt
+
+
diff --git a/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_nullable_types_test_interface.cc b/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_nullable_types_test_interface.cc
index 9608bc5..6b1d665 100644
--- a/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_nullable_types_test_interface.cc
+++ b/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_nullable_types_test_interface.cc
@@ -22,8 +22,8 @@
 #include "base/debug/trace_event.h"
 #include "cobalt/base/polymorphic_downcast.h"
 #include "cobalt/script/global_environment.h"
-#include "cobalt/script/opaque_handle.h"
 #include "cobalt/script/script_value.h"
+#include "cobalt/script/value_handle.h"
 #include "cobalt/bindings/testing/arbitrary_interface.h"
 #include "cobalt/bindings/testing/mozjs_arbitrary_interface.h"
 
@@ -36,7 +36,6 @@
 #include "cobalt/script/mozjs-45/mozjs_callback_function.h"
 #include "cobalt/script/mozjs-45/mozjs_exception_state.h"
 #include "cobalt/script/mozjs-45/mozjs_global_environment.h"
-#include "cobalt/script/mozjs-45/mozjs_object_handle.h"
 #include "cobalt/script/mozjs-45/mozjs_property_enumerator.h"
 #include "cobalt/script/mozjs-45/mozjs_user_object_holder.h"
 #include "cobalt/script/mozjs-45/mozjs_value_handle.h"
@@ -57,10 +56,10 @@
 using cobalt::bindings::testing::MozjsArbitraryInterface;
 using cobalt::script::CallbackInterfaceTraits;
 using cobalt::script::GlobalEnvironment;
-using cobalt::script::OpaqueHandle;
-using cobalt::script::OpaqueHandleHolder;
 using cobalt::script::ScriptValue;
 using cobalt::script::ValueHandle;
+using cobalt::script::ValueHandle;
+using cobalt::script::ValueHandleHolder;
 using cobalt::script::Wrappable;
 
 using cobalt::script::CallbackFunction;
@@ -84,6 +83,7 @@
 using cobalt::script::mozjs::kConversionFlagRestricted;
 using cobalt::script::mozjs::kConversionFlagTreatNullAsEmptyString;
 using cobalt::script::mozjs::kConversionFlagTreatUndefinedAsEmptyString;
+using cobalt::script::mozjs::kConversionFlagObjectOnly;
 using cobalt::script::mozjs::kNoConversionFlags;
 }  // namespace
 
@@ -1268,3 +1268,5 @@
 }  // namespace testing
 }  // namespace bindings
 }  // namespace cobalt
+
+
diff --git a/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_numeric_types_test_interface.cc b/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_numeric_types_test_interface.cc
index c366032..561aeaa 100644
--- a/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_numeric_types_test_interface.cc
+++ b/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_numeric_types_test_interface.cc
@@ -22,8 +22,8 @@
 #include "base/debug/trace_event.h"
 #include "cobalt/base/polymorphic_downcast.h"
 #include "cobalt/script/global_environment.h"
-#include "cobalt/script/opaque_handle.h"
 #include "cobalt/script/script_value.h"
+#include "cobalt/script/value_handle.h"
 
 #include "mozjs_gen_type_conversion.h"
 
@@ -34,7 +34,6 @@
 #include "cobalt/script/mozjs-45/mozjs_callback_function.h"
 #include "cobalt/script/mozjs-45/mozjs_exception_state.h"
 #include "cobalt/script/mozjs-45/mozjs_global_environment.h"
-#include "cobalt/script/mozjs-45/mozjs_object_handle.h"
 #include "cobalt/script/mozjs-45/mozjs_property_enumerator.h"
 #include "cobalt/script/mozjs-45/mozjs_user_object_holder.h"
 #include "cobalt/script/mozjs-45/mozjs_value_handle.h"
@@ -53,10 +52,10 @@
 using cobalt::bindings::testing::MozjsNumericTypesTestInterface;
 using cobalt::script::CallbackInterfaceTraits;
 using cobalt::script::GlobalEnvironment;
-using cobalt::script::OpaqueHandle;
-using cobalt::script::OpaqueHandleHolder;
 using cobalt::script::ScriptValue;
 using cobalt::script::ValueHandle;
+using cobalt::script::ValueHandle;
+using cobalt::script::ValueHandleHolder;
 using cobalt::script::Wrappable;
 
 using cobalt::script::CallbackFunction;
@@ -80,6 +79,7 @@
 using cobalt::script::mozjs::kConversionFlagRestricted;
 using cobalt::script::mozjs::kConversionFlagTreatNullAsEmptyString;
 using cobalt::script::mozjs::kConversionFlagTreatUndefinedAsEmptyString;
+using cobalt::script::mozjs::kConversionFlagObjectOnly;
 using cobalt::script::mozjs::kNoConversionFlags;
 }  // namespace
 
@@ -3480,3 +3480,5 @@
 }  // namespace testing
 }  // namespace bindings
 }  // namespace cobalt
+
+
diff --git a/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_object_type_bindings_interface.cc b/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_object_type_bindings_interface.cc
index 9ab8de4..b800056 100644
--- a/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_object_type_bindings_interface.cc
+++ b/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_object_type_bindings_interface.cc
@@ -22,8 +22,8 @@
 #include "base/debug/trace_event.h"
 #include "cobalt/base/polymorphic_downcast.h"
 #include "cobalt/script/global_environment.h"
-#include "cobalt/script/opaque_handle.h"
 #include "cobalt/script/script_value.h"
+#include "cobalt/script/value_handle.h"
 #include "cobalt/bindings/testing/arbitrary_interface.h"
 #include "cobalt/bindings/testing/base_interface.h"
 #include "cobalt/bindings/testing/derived_interface.h"
@@ -40,7 +40,6 @@
 #include "cobalt/script/mozjs-45/mozjs_callback_function.h"
 #include "cobalt/script/mozjs-45/mozjs_exception_state.h"
 #include "cobalt/script/mozjs-45/mozjs_global_environment.h"
-#include "cobalt/script/mozjs-45/mozjs_object_handle.h"
 #include "cobalt/script/mozjs-45/mozjs_property_enumerator.h"
 #include "cobalt/script/mozjs-45/mozjs_user_object_holder.h"
 #include "cobalt/script/mozjs-45/mozjs_value_handle.h"
@@ -65,10 +64,10 @@
 using cobalt::bindings::testing::MozjsDerivedInterface;
 using cobalt::script::CallbackInterfaceTraits;
 using cobalt::script::GlobalEnvironment;
-using cobalt::script::OpaqueHandle;
-using cobalt::script::OpaqueHandleHolder;
 using cobalt::script::ScriptValue;
 using cobalt::script::ValueHandle;
+using cobalt::script::ValueHandle;
+using cobalt::script::ValueHandleHolder;
 using cobalt::script::Wrappable;
 
 using cobalt::script::CallbackFunction;
@@ -92,6 +91,7 @@
 using cobalt::script::mozjs::kConversionFlagRestricted;
 using cobalt::script::mozjs::kConversionFlagTreatNullAsEmptyString;
 using cobalt::script::mozjs::kConversionFlagTreatUndefinedAsEmptyString;
+using cobalt::script::mozjs::kConversionFlagObjectOnly;
 using cobalt::script::mozjs::kNoConversionFlags;
 }  // namespace
 
@@ -521,12 +521,12 @@
       WrapperPrivate::GetFromObject(context, object);
   ObjectTypeBindingsInterface* impl =
       wrapper_private->wrappable<ObjectTypeBindingsInterface>().get();
-  TypeTraits<::cobalt::script::OpaqueHandle >::ConversionType value;
+  TypeTraits<::cobalt::script::ValueHandle >::ConversionType value;
   if (args.length() != 1) {
     NOTREACHED();
     return false;
   }
-  FromJSValue(context, args[0], (kConversionFlagNullable), &exception_state,
+  FromJSValue(context, args[0], (kConversionFlagNullable | kConversionFlagObjectOnly), &exception_state,
               &value);
   if (exception_state.is_exception_set()) {
     return false;
@@ -736,3 +736,5 @@
 }  // namespace testing
 }  // namespace bindings
 }  // namespace cobalt
+
+
diff --git a/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_operations_test_interface.cc b/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_operations_test_interface.cc
index f8e366d..607f7e8 100644
--- a/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_operations_test_interface.cc
+++ b/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_operations_test_interface.cc
@@ -22,8 +22,8 @@
 #include "base/debug/trace_event.h"
 #include "cobalt/base/polymorphic_downcast.h"
 #include "cobalt/script/global_environment.h"
-#include "cobalt/script/opaque_handle.h"
 #include "cobalt/script/script_value.h"
+#include "cobalt/script/value_handle.h"
 #include "cobalt/bindings/testing/arbitrary_interface.h"
 #include "cobalt/bindings/testing/mozjs_arbitrary_interface.h"
 
@@ -36,7 +36,6 @@
 #include "cobalt/script/mozjs-45/mozjs_callback_function.h"
 #include "cobalt/script/mozjs-45/mozjs_exception_state.h"
 #include "cobalt/script/mozjs-45/mozjs_global_environment.h"
-#include "cobalt/script/mozjs-45/mozjs_object_handle.h"
 #include "cobalt/script/mozjs-45/mozjs_property_enumerator.h"
 #include "cobalt/script/mozjs-45/mozjs_user_object_holder.h"
 #include "cobalt/script/mozjs-45/mozjs_value_handle.h"
@@ -57,10 +56,10 @@
 using cobalt::bindings::testing::MozjsArbitraryInterface;
 using cobalt::script::CallbackInterfaceTraits;
 using cobalt::script::GlobalEnvironment;
-using cobalt::script::OpaqueHandle;
-using cobalt::script::OpaqueHandleHolder;
 using cobalt::script::ScriptValue;
 using cobalt::script::ValueHandle;
+using cobalt::script::ValueHandle;
+using cobalt::script::ValueHandleHolder;
 using cobalt::script::Wrappable;
 
 using cobalt::script::CallbackFunction;
@@ -84,6 +83,7 @@
 using cobalt::script::mozjs::kConversionFlagRestricted;
 using cobalt::script::mozjs::kConversionFlagTreatNullAsEmptyString;
 using cobalt::script::mozjs::kConversionFlagTreatUndefinedAsEmptyString;
+using cobalt::script::mozjs::kConversionFlagObjectOnly;
 using cobalt::script::mozjs::kNoConversionFlags;
 }  // namespace
 
@@ -1904,3 +1904,5 @@
 }  // namespace testing
 }  // namespace bindings
 }  // namespace cobalt
+
+
diff --git a/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_promise_interface.cc b/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_promise_interface.cc
index 593cefe..c720acf 100644
--- a/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_promise_interface.cc
+++ b/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_promise_interface.cc
@@ -22,8 +22,8 @@
 #include "base/debug/trace_event.h"
 #include "cobalt/base/polymorphic_downcast.h"
 #include "cobalt/script/global_environment.h"
-#include "cobalt/script/opaque_handle.h"
 #include "cobalt/script/script_value.h"
+#include "cobalt/script/value_handle.h"
 
 #include "mozjs_gen_type_conversion.h"
 
@@ -34,7 +34,6 @@
 #include "cobalt/script/mozjs-45/mozjs_callback_function.h"
 #include "cobalt/script/mozjs-45/mozjs_exception_state.h"
 #include "cobalt/script/mozjs-45/mozjs_global_environment.h"
-#include "cobalt/script/mozjs-45/mozjs_object_handle.h"
 #include "cobalt/script/mozjs-45/mozjs_property_enumerator.h"
 #include "cobalt/script/mozjs-45/mozjs_user_object_holder.h"
 #include "cobalt/script/mozjs-45/mozjs_value_handle.h"
@@ -53,10 +52,10 @@
 using cobalt::bindings::testing::MozjsPromiseInterface;
 using cobalt::script::CallbackInterfaceTraits;
 using cobalt::script::GlobalEnvironment;
-using cobalt::script::OpaqueHandle;
-using cobalt::script::OpaqueHandleHolder;
 using cobalt::script::ScriptValue;
 using cobalt::script::ValueHandle;
+using cobalt::script::ValueHandle;
+using cobalt::script::ValueHandleHolder;
 using cobalt::script::Wrappable;
 
 using cobalt::script::CallbackFunction;
@@ -80,6 +79,7 @@
 using cobalt::script::mozjs::kConversionFlagRestricted;
 using cobalt::script::mozjs::kConversionFlagTreatNullAsEmptyString;
 using cobalt::script::mozjs::kConversionFlagTreatUndefinedAsEmptyString;
+using cobalt::script::mozjs::kConversionFlagObjectOnly;
 using cobalt::script::mozjs::kNoConversionFlags;
 }  // namespace
 
@@ -621,3 +621,5 @@
 }  // namespace testing
 }  // namespace bindings
 }  // namespace cobalt
+
+
diff --git a/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_put_forwards_interface.cc b/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_put_forwards_interface.cc
index c7ae942..f3ffe60 100644
--- a/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_put_forwards_interface.cc
+++ b/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_put_forwards_interface.cc
@@ -22,8 +22,8 @@
 #include "base/debug/trace_event.h"
 #include "cobalt/base/polymorphic_downcast.h"
 #include "cobalt/script/global_environment.h"
-#include "cobalt/script/opaque_handle.h"
 #include "cobalt/script/script_value.h"
+#include "cobalt/script/value_handle.h"
 #include "cobalt/bindings/testing/arbitrary_interface.h"
 #include "cobalt/bindings/testing/mozjs_arbitrary_interface.h"
 
@@ -36,7 +36,6 @@
 #include "cobalt/script/mozjs-45/mozjs_callback_function.h"
 #include "cobalt/script/mozjs-45/mozjs_exception_state.h"
 #include "cobalt/script/mozjs-45/mozjs_global_environment.h"
-#include "cobalt/script/mozjs-45/mozjs_object_handle.h"
 #include "cobalt/script/mozjs-45/mozjs_property_enumerator.h"
 #include "cobalt/script/mozjs-45/mozjs_user_object_holder.h"
 #include "cobalt/script/mozjs-45/mozjs_value_handle.h"
@@ -57,10 +56,10 @@
 using cobalt::bindings::testing::MozjsArbitraryInterface;
 using cobalt::script::CallbackInterfaceTraits;
 using cobalt::script::GlobalEnvironment;
-using cobalt::script::OpaqueHandle;
-using cobalt::script::OpaqueHandleHolder;
 using cobalt::script::ScriptValue;
 using cobalt::script::ValueHandle;
+using cobalt::script::ValueHandle;
+using cobalt::script::ValueHandleHolder;
 using cobalt::script::Wrappable;
 
 using cobalt::script::CallbackFunction;
@@ -84,6 +83,7 @@
 using cobalt::script::mozjs::kConversionFlagRestricted;
 using cobalt::script::mozjs::kConversionFlagTreatNullAsEmptyString;
 using cobalt::script::mozjs::kConversionFlagTreatUndefinedAsEmptyString;
+using cobalt::script::mozjs::kConversionFlagObjectOnly;
 using cobalt::script::mozjs::kNoConversionFlags;
 }  // namespace
 
@@ -543,3 +543,5 @@
 }  // namespace testing
 }  // namespace bindings
 }  // namespace cobalt
+
+
diff --git a/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_sequence_user.cc b/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_sequence_user.cc
index 7416868..81f0938 100644
--- a/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_sequence_user.cc
+++ b/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_sequence_user.cc
@@ -22,8 +22,8 @@
 #include "base/debug/trace_event.h"
 #include "cobalt/base/polymorphic_downcast.h"
 #include "cobalt/script/global_environment.h"
-#include "cobalt/script/opaque_handle.h"
 #include "cobalt/script/script_value.h"
+#include "cobalt/script/value_handle.h"
 #include "cobalt/bindings/testing/arbitrary_interface.h"
 #include "cobalt/bindings/testing/mozjs_arbitrary_interface.h"
 
@@ -36,7 +36,6 @@
 #include "cobalt/script/mozjs-45/mozjs_callback_function.h"
 #include "cobalt/script/mozjs-45/mozjs_exception_state.h"
 #include "cobalt/script/mozjs-45/mozjs_global_environment.h"
-#include "cobalt/script/mozjs-45/mozjs_object_handle.h"
 #include "cobalt/script/mozjs-45/mozjs_property_enumerator.h"
 #include "cobalt/script/mozjs-45/mozjs_user_object_holder.h"
 #include "cobalt/script/mozjs-45/mozjs_value_handle.h"
@@ -57,10 +56,10 @@
 using cobalt::bindings::testing::MozjsArbitraryInterface;
 using cobalt::script::CallbackInterfaceTraits;
 using cobalt::script::GlobalEnvironment;
-using cobalt::script::OpaqueHandle;
-using cobalt::script::OpaqueHandleHolder;
 using cobalt::script::ScriptValue;
 using cobalt::script::ValueHandle;
+using cobalt::script::ValueHandle;
+using cobalt::script::ValueHandleHolder;
 using cobalt::script::Wrappable;
 
 using cobalt::script::CallbackFunction;
@@ -84,6 +83,7 @@
 using cobalt::script::mozjs::kConversionFlagRestricted;
 using cobalt::script::mozjs::kConversionFlagTreatNullAsEmptyString;
 using cobalt::script::mozjs::kConversionFlagTreatUndefinedAsEmptyString;
+using cobalt::script::mozjs::kConversionFlagObjectOnly;
 using cobalt::script::mozjs::kNoConversionFlags;
 }  // namespace
 
@@ -1232,3 +1232,5 @@
 }  // namespace testing
 }  // namespace bindings
 }  // namespace cobalt
+
+
diff --git a/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_single_operation_interface.cc b/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_single_operation_interface.cc
index 6f5cd15..c12d824 100644
--- a/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_single_operation_interface.cc
+++ b/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_single_operation_interface.cc
@@ -51,12 +51,6 @@
 
 MozjsSingleOperationInterface::MozjsSingleOperationInterface(
     JSContext* context,
-    JS::HandleObject implementing_object)
-    : context_(context),
-      implementing_object_(context, implementing_object) { }
-
-MozjsSingleOperationInterface::MozjsSingleOperationInterface(
-    JSContext* context,
     JS::HandleValue implementing_object_value)
     : context_(context),
       implementing_object_(context, implementing_object_value) { }
diff --git a/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_single_operation_interface.h b/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_single_operation_interface.h
index 9338c40..9be2024 100644
--- a/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_single_operation_interface.h
+++ b/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_single_operation_interface.h
@@ -36,8 +36,6 @@
   typedef SingleOperationInterface BaseType;
 
   MozjsSingleOperationInterface(
-      JSContext* context, JS::HandleObject implementing_object);
-  MozjsSingleOperationInterface(
       JSContext* context, JS::HandleValue implementing_object_value);
   base::optional<int32_t > HandleCallback(
       const scoped_refptr<script::Wrappable>& callback_this,
diff --git a/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_static_properties_interface.cc b/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_static_properties_interface.cc
index b8b9c56..2dabdcc 100644
--- a/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_static_properties_interface.cc
+++ b/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_static_properties_interface.cc
@@ -22,8 +22,8 @@
 #include "base/debug/trace_event.h"
 #include "cobalt/base/polymorphic_downcast.h"
 #include "cobalt/script/global_environment.h"
-#include "cobalt/script/opaque_handle.h"
 #include "cobalt/script/script_value.h"
+#include "cobalt/script/value_handle.h"
 #include "cobalt/bindings/testing/arbitrary_interface.h"
 #include "cobalt/bindings/testing/mozjs_arbitrary_interface.h"
 
@@ -36,7 +36,6 @@
 #include "cobalt/script/mozjs-45/mozjs_callback_function.h"
 #include "cobalt/script/mozjs-45/mozjs_exception_state.h"
 #include "cobalt/script/mozjs-45/mozjs_global_environment.h"
-#include "cobalt/script/mozjs-45/mozjs_object_handle.h"
 #include "cobalt/script/mozjs-45/mozjs_property_enumerator.h"
 #include "cobalt/script/mozjs-45/mozjs_user_object_holder.h"
 #include "cobalt/script/mozjs-45/mozjs_value_handle.h"
@@ -57,10 +56,10 @@
 using cobalt::bindings::testing::MozjsArbitraryInterface;
 using cobalt::script::CallbackInterfaceTraits;
 using cobalt::script::GlobalEnvironment;
-using cobalt::script::OpaqueHandle;
-using cobalt::script::OpaqueHandleHolder;
 using cobalt::script::ScriptValue;
 using cobalt::script::ValueHandle;
+using cobalt::script::ValueHandle;
+using cobalt::script::ValueHandleHolder;
 using cobalt::script::Wrappable;
 
 using cobalt::script::CallbackFunction;
@@ -84,6 +83,7 @@
 using cobalt::script::mozjs::kConversionFlagRestricted;
 using cobalt::script::mozjs::kConversionFlagTreatNullAsEmptyString;
 using cobalt::script::mozjs::kConversionFlagTreatUndefinedAsEmptyString;
+using cobalt::script::mozjs::kConversionFlagObjectOnly;
 using cobalt::script::mozjs::kNoConversionFlags;
 }  // namespace
 
@@ -668,3 +668,5 @@
 }  // namespace testing
 }  // namespace bindings
 }  // namespace cobalt
+
+
diff --git a/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_stringifier_anonymous_operation_interface.cc b/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_stringifier_anonymous_operation_interface.cc
index 13b3bcf..8992fff 100644
--- a/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_stringifier_anonymous_operation_interface.cc
+++ b/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_stringifier_anonymous_operation_interface.cc
@@ -22,8 +22,8 @@
 #include "base/debug/trace_event.h"
 #include "cobalt/base/polymorphic_downcast.h"
 #include "cobalt/script/global_environment.h"
-#include "cobalt/script/opaque_handle.h"
 #include "cobalt/script/script_value.h"
+#include "cobalt/script/value_handle.h"
 
 #include "mozjs_gen_type_conversion.h"
 
@@ -34,7 +34,6 @@
 #include "cobalt/script/mozjs-45/mozjs_callback_function.h"
 #include "cobalt/script/mozjs-45/mozjs_exception_state.h"
 #include "cobalt/script/mozjs-45/mozjs_global_environment.h"
-#include "cobalt/script/mozjs-45/mozjs_object_handle.h"
 #include "cobalt/script/mozjs-45/mozjs_property_enumerator.h"
 #include "cobalt/script/mozjs-45/mozjs_user_object_holder.h"
 #include "cobalt/script/mozjs-45/mozjs_value_handle.h"
@@ -53,10 +52,10 @@
 using cobalt::bindings::testing::MozjsStringifierAnonymousOperationInterface;
 using cobalt::script::CallbackInterfaceTraits;
 using cobalt::script::GlobalEnvironment;
-using cobalt::script::OpaqueHandle;
-using cobalt::script::OpaqueHandleHolder;
 using cobalt::script::ScriptValue;
 using cobalt::script::ValueHandle;
+using cobalt::script::ValueHandle;
+using cobalt::script::ValueHandleHolder;
 using cobalt::script::Wrappable;
 
 using cobalt::script::CallbackFunction;
@@ -80,6 +79,7 @@
 using cobalt::script::mozjs::kConversionFlagRestricted;
 using cobalt::script::mozjs::kConversionFlagTreatNullAsEmptyString;
 using cobalt::script::mozjs::kConversionFlagTreatUndefinedAsEmptyString;
+using cobalt::script::mozjs::kConversionFlagObjectOnly;
 using cobalt::script::mozjs::kNoConversionFlags;
 }  // namespace
 
@@ -413,3 +413,5 @@
 }  // namespace testing
 }  // namespace bindings
 }  // namespace cobalt
+
+
diff --git a/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_stringifier_attribute_interface.cc b/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_stringifier_attribute_interface.cc
index 78d93ea..4cfb373 100644
--- a/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_stringifier_attribute_interface.cc
+++ b/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_stringifier_attribute_interface.cc
@@ -22,8 +22,8 @@
 #include "base/debug/trace_event.h"
 #include "cobalt/base/polymorphic_downcast.h"
 #include "cobalt/script/global_environment.h"
-#include "cobalt/script/opaque_handle.h"
 #include "cobalt/script/script_value.h"
+#include "cobalt/script/value_handle.h"
 
 #include "mozjs_gen_type_conversion.h"
 
@@ -34,7 +34,6 @@
 #include "cobalt/script/mozjs-45/mozjs_callback_function.h"
 #include "cobalt/script/mozjs-45/mozjs_exception_state.h"
 #include "cobalt/script/mozjs-45/mozjs_global_environment.h"
-#include "cobalt/script/mozjs-45/mozjs_object_handle.h"
 #include "cobalt/script/mozjs-45/mozjs_property_enumerator.h"
 #include "cobalt/script/mozjs-45/mozjs_user_object_holder.h"
 #include "cobalt/script/mozjs-45/mozjs_value_handle.h"
@@ -53,10 +52,10 @@
 using cobalt::bindings::testing::MozjsStringifierAttributeInterface;
 using cobalt::script::CallbackInterfaceTraits;
 using cobalt::script::GlobalEnvironment;
-using cobalt::script::OpaqueHandle;
-using cobalt::script::OpaqueHandleHolder;
 using cobalt::script::ScriptValue;
 using cobalt::script::ValueHandle;
+using cobalt::script::ValueHandle;
+using cobalt::script::ValueHandleHolder;
 using cobalt::script::Wrappable;
 
 using cobalt::script::CallbackFunction;
@@ -80,6 +79,7 @@
 using cobalt::script::mozjs::kConversionFlagRestricted;
 using cobalt::script::mozjs::kConversionFlagTreatNullAsEmptyString;
 using cobalt::script::mozjs::kConversionFlagTreatUndefinedAsEmptyString;
+using cobalt::script::mozjs::kConversionFlagObjectOnly;
 using cobalt::script::mozjs::kNoConversionFlags;
 }  // namespace
 
@@ -519,3 +519,5 @@
 }  // namespace testing
 }  // namespace bindings
 }  // namespace cobalt
+
+
diff --git a/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_stringifier_operation_interface.cc b/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_stringifier_operation_interface.cc
index 14a2c07..c537e6e 100644
--- a/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_stringifier_operation_interface.cc
+++ b/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_stringifier_operation_interface.cc
@@ -22,8 +22,8 @@
 #include "base/debug/trace_event.h"
 #include "cobalt/base/polymorphic_downcast.h"
 #include "cobalt/script/global_environment.h"
-#include "cobalt/script/opaque_handle.h"
 #include "cobalt/script/script_value.h"
+#include "cobalt/script/value_handle.h"
 
 #include "mozjs_gen_type_conversion.h"
 
@@ -34,7 +34,6 @@
 #include "cobalt/script/mozjs-45/mozjs_callback_function.h"
 #include "cobalt/script/mozjs-45/mozjs_exception_state.h"
 #include "cobalt/script/mozjs-45/mozjs_global_environment.h"
-#include "cobalt/script/mozjs-45/mozjs_object_handle.h"
 #include "cobalt/script/mozjs-45/mozjs_property_enumerator.h"
 #include "cobalt/script/mozjs-45/mozjs_user_object_holder.h"
 #include "cobalt/script/mozjs-45/mozjs_value_handle.h"
@@ -53,10 +52,10 @@
 using cobalt::bindings::testing::MozjsStringifierOperationInterface;
 using cobalt::script::CallbackInterfaceTraits;
 using cobalt::script::GlobalEnvironment;
-using cobalt::script::OpaqueHandle;
-using cobalt::script::OpaqueHandleHolder;
 using cobalt::script::ScriptValue;
 using cobalt::script::ValueHandle;
+using cobalt::script::ValueHandle;
+using cobalt::script::ValueHandleHolder;
 using cobalt::script::Wrappable;
 
 using cobalt::script::CallbackFunction;
@@ -80,6 +79,7 @@
 using cobalt::script::mozjs::kConversionFlagRestricted;
 using cobalt::script::mozjs::kConversionFlagTreatNullAsEmptyString;
 using cobalt::script::mozjs::kConversionFlagTreatUndefinedAsEmptyString;
+using cobalt::script::mozjs::kConversionFlagObjectOnly;
 using cobalt::script::mozjs::kNoConversionFlags;
 }  // namespace
 
@@ -468,3 +468,5 @@
 }  // namespace testing
 }  // namespace bindings
 }  // namespace cobalt
+
+
diff --git a/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_target_interface.cc b/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_target_interface.cc
index 1ebf396..7b49c6e 100644
--- a/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_target_interface.cc
+++ b/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_target_interface.cc
@@ -22,8 +22,8 @@
 #include "base/debug/trace_event.h"
 #include "cobalt/base/polymorphic_downcast.h"
 #include "cobalt/script/global_environment.h"
-#include "cobalt/script/opaque_handle.h"
 #include "cobalt/script/script_value.h"
+#include "cobalt/script/value_handle.h"
 
 #include "mozjs_gen_type_conversion.h"
 
@@ -34,7 +34,6 @@
 #include "cobalt/script/mozjs-45/mozjs_callback_function.h"
 #include "cobalt/script/mozjs-45/mozjs_exception_state.h"
 #include "cobalt/script/mozjs-45/mozjs_global_environment.h"
-#include "cobalt/script/mozjs-45/mozjs_object_handle.h"
 #include "cobalt/script/mozjs-45/mozjs_property_enumerator.h"
 #include "cobalt/script/mozjs-45/mozjs_user_object_holder.h"
 #include "cobalt/script/mozjs-45/mozjs_value_handle.h"
@@ -53,10 +52,10 @@
 using cobalt::bindings::testing::MozjsTargetInterface;
 using cobalt::script::CallbackInterfaceTraits;
 using cobalt::script::GlobalEnvironment;
-using cobalt::script::OpaqueHandle;
-using cobalt::script::OpaqueHandleHolder;
 using cobalt::script::ScriptValue;
 using cobalt::script::ValueHandle;
+using cobalt::script::ValueHandle;
+using cobalt::script::ValueHandleHolder;
 using cobalt::script::Wrappable;
 
 using cobalt::script::CallbackFunction;
@@ -80,6 +79,7 @@
 using cobalt::script::mozjs::kConversionFlagRestricted;
 using cobalt::script::mozjs::kConversionFlagTreatNullAsEmptyString;
 using cobalt::script::mozjs::kConversionFlagTreatUndefinedAsEmptyString;
+using cobalt::script::mozjs::kConversionFlagObjectOnly;
 using cobalt::script::mozjs::kNoConversionFlags;
 }  // namespace
 
@@ -450,3 +450,5 @@
 }  // namespace testing
 }  // namespace bindings
 }  // namespace cobalt
+
+
diff --git a/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_union_types_interface.cc b/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_union_types_interface.cc
index 2a312fd..7a46163 100644
--- a/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_union_types_interface.cc
+++ b/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_union_types_interface.cc
@@ -22,8 +22,8 @@
 #include "base/debug/trace_event.h"
 #include "cobalt/base/polymorphic_downcast.h"
 #include "cobalt/script/global_environment.h"
-#include "cobalt/script/opaque_handle.h"
 #include "cobalt/script/script_value.h"
+#include "cobalt/script/value_handle.h"
 #include "cobalt/bindings/testing/arbitrary_interface.h"
 #include "cobalt/bindings/testing/base_interface.h"
 #include "cobalt/bindings/testing/mozjs_arbitrary_interface.h"
@@ -38,7 +38,6 @@
 #include "cobalt/script/mozjs-45/mozjs_callback_function.h"
 #include "cobalt/script/mozjs-45/mozjs_exception_state.h"
 #include "cobalt/script/mozjs-45/mozjs_global_environment.h"
-#include "cobalt/script/mozjs-45/mozjs_object_handle.h"
 #include "cobalt/script/mozjs-45/mozjs_property_enumerator.h"
 #include "cobalt/script/mozjs-45/mozjs_user_object_holder.h"
 #include "cobalt/script/mozjs-45/mozjs_value_handle.h"
@@ -61,10 +60,10 @@
 using cobalt::bindings::testing::MozjsBaseInterface;
 using cobalt::script::CallbackInterfaceTraits;
 using cobalt::script::GlobalEnvironment;
-using cobalt::script::OpaqueHandle;
-using cobalt::script::OpaqueHandleHolder;
 using cobalt::script::ScriptValue;
 using cobalt::script::ValueHandle;
+using cobalt::script::ValueHandle;
+using cobalt::script::ValueHandleHolder;
 using cobalt::script::Wrappable;
 
 using cobalt::script::CallbackFunction;
@@ -88,6 +87,7 @@
 using cobalt::script::mozjs::kConversionFlagRestricted;
 using cobalt::script::mozjs::kConversionFlagTreatNullAsEmptyString;
 using cobalt::script::mozjs::kConversionFlagTreatUndefinedAsEmptyString;
+using cobalt::script::mozjs::kConversionFlagObjectOnly;
 using cobalt::script::mozjs::kNoConversionFlags;
 }  // namespace
 
@@ -784,3 +784,5 @@
 }  // namespace testing
 }  // namespace bindings
 }  // namespace cobalt
+
+
diff --git a/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_window.cc b/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_window.cc
index 0118eab..c31604c 100644
--- a/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_window.cc
+++ b/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_window.cc
@@ -22,8 +22,8 @@
 #include "base/debug/trace_event.h"
 #include "cobalt/base/polymorphic_downcast.h"
 #include "cobalt/script/global_environment.h"
-#include "cobalt/script/opaque_handle.h"
 #include "cobalt/script/script_value.h"
+#include "cobalt/script/value_handle.h"
 #include "cobalt/bindings/testing/anonymous_indexed_getter_interface.h"
 #include "cobalt/bindings/testing/anonymous_named_getter_interface.h"
 #include "cobalt/bindings/testing/anonymous_named_indexed_getter_interface.h"
@@ -132,7 +132,6 @@
 #include "cobalt/script/mozjs-45/mozjs_callback_function.h"
 #include "cobalt/script/mozjs-45/mozjs_exception_state.h"
 #include "cobalt/script/mozjs-45/mozjs_global_environment.h"
-#include "cobalt/script/mozjs-45/mozjs_object_handle.h"
 #include "cobalt/script/mozjs-45/mozjs_property_enumerator.h"
 #include "cobalt/script/mozjs-45/mozjs_user_object_holder.h"
 #include "cobalt/script/mozjs-45/mozjs_value_handle.h"
@@ -257,10 +256,10 @@
 using cobalt::bindings::testing::Window;
 using cobalt::script::CallbackInterfaceTraits;
 using cobalt::script::GlobalEnvironment;
-using cobalt::script::OpaqueHandle;
-using cobalt::script::OpaqueHandleHolder;
 using cobalt::script::ScriptValue;
 using cobalt::script::ValueHandle;
+using cobalt::script::ValueHandle;
+using cobalt::script::ValueHandleHolder;
 using cobalt::script::Wrappable;
 
 using cobalt::script::CallbackFunction;
@@ -284,6 +283,7 @@
 using cobalt::script::mozjs::kConversionFlagRestricted;
 using cobalt::script::mozjs::kConversionFlagTreatNullAsEmptyString;
 using cobalt::script::mozjs::kConversionFlagTreatUndefinedAsEmptyString;
+using cobalt::script::mozjs::kConversionFlagObjectOnly;
 using cobalt::script::mozjs::kNoConversionFlags;
 JSObject* DummyFunctor(
     JSContext* context, const scoped_refptr<Wrappable>& wrappable) {
@@ -1062,223 +1062,233 @@
 }  // namespace bindings
 }  // namespace cobalt
 
+
 namespace cobalt {
 namespace script {
+namespace mozjs {
 
-template<>
-void GlobalEnvironment::CreateGlobalObject<Window>(
-    const scoped_refptr<Window>& global_interface,
+template <typename GlobalInterface>
+void MozjsGlobalEnvironment::CreateGlobalObject(
+    const scoped_refptr<GlobalInterface>& global_interface,
     EnvironmentSettings* environment_settings) {
-  MozjsGlobalEnvironment* mozjs_global_environment =
-      base::polymorphic_downcast<MozjsGlobalEnvironment*>(this);
-  JSContext* context = mozjs_global_environment->context();
+  JSAutoRequest auto_request(context_);
+  MozjsWindow::CreateProxy(context_, global_interface);
 
-  JSAutoRequest auto_request(context);
-  MozjsWindow::CreateProxy(
-      context, global_interface);
-  mozjs_global_environment->SetEnvironmentSettings(environment_settings);
-  mozjs_global_environment->EvaluateAutomatics();
+  DCHECK(!environment_settings_);
+  DCHECK(environment_settings);
+  environment_settings_ = environment_settings;
+  EvaluateAutomatics();
 
-  WrapperFactory* wrapper_factory =
-      mozjs_global_environment->wrapper_factory();
-  wrapper_factory->RegisterWrappableType(
+  wrapper_factory_->RegisterWrappableType(
       AnonymousIndexedGetterInterface::AnonymousIndexedGetterInterfaceWrappableType(),
       base::Bind(MozjsAnonymousIndexedGetterInterface::CreateProxy),
       base::Bind(MozjsAnonymousIndexedGetterInterface::PrototypeClass));
-  wrapper_factory->RegisterWrappableType(
+  wrapper_factory_->RegisterWrappableType(
       AnonymousNamedGetterInterface::AnonymousNamedGetterInterfaceWrappableType(),
       base::Bind(MozjsAnonymousNamedGetterInterface::CreateProxy),
       base::Bind(MozjsAnonymousNamedGetterInterface::PrototypeClass));
-  wrapper_factory->RegisterWrappableType(
+  wrapper_factory_->RegisterWrappableType(
       AnonymousNamedIndexedGetterInterface::AnonymousNamedIndexedGetterInterfaceWrappableType(),
       base::Bind(MozjsAnonymousNamedIndexedGetterInterface::CreateProxy),
       base::Bind(MozjsAnonymousNamedIndexedGetterInterface::PrototypeClass));
-  wrapper_factory->RegisterWrappableType(
+  wrapper_factory_->RegisterWrappableType(
       ArbitraryInterface::ArbitraryInterfaceWrappableType(),
       base::Bind(MozjsArbitraryInterface::CreateProxy),
       base::Bind(MozjsArbitraryInterface::PrototypeClass));
-  wrapper_factory->RegisterWrappableType(
+  wrapper_factory_->RegisterWrappableType(
       BaseInterface::BaseInterfaceWrappableType(),
       base::Bind(MozjsBaseInterface::CreateProxy),
       base::Bind(MozjsBaseInterface::PrototypeClass));
-  wrapper_factory->RegisterWrappableType(
+  wrapper_factory_->RegisterWrappableType(
       BooleanTypeTestInterface::BooleanTypeTestInterfaceWrappableType(),
       base::Bind(MozjsBooleanTypeTestInterface::CreateProxy),
       base::Bind(MozjsBooleanTypeTestInterface::PrototypeClass));
-  wrapper_factory->RegisterWrappableType(
+  wrapper_factory_->RegisterWrappableType(
       CallbackFunctionInterface::CallbackFunctionInterfaceWrappableType(),
       base::Bind(MozjsCallbackFunctionInterface::CreateProxy),
       base::Bind(MozjsCallbackFunctionInterface::PrototypeClass));
-  wrapper_factory->RegisterWrappableType(
+  wrapper_factory_->RegisterWrappableType(
       CallbackInterfaceInterface::CallbackInterfaceInterfaceWrappableType(),
       base::Bind(MozjsCallbackInterfaceInterface::CreateProxy),
       base::Bind(MozjsCallbackInterfaceInterface::PrototypeClass));
 #if defined(ENABLE_CONDITIONAL_INTERFACE)
-  wrapper_factory->RegisterWrappableType(
+  wrapper_factory_->RegisterWrappableType(
       ConditionalInterface::ConditionalInterfaceWrappableType(),
       base::Bind(MozjsConditionalInterface::CreateProxy),
       base::Bind(MozjsConditionalInterface::PrototypeClass));
 #endif  // defined(ENABLE_CONDITIONAL_INTERFACE)
-  wrapper_factory->RegisterWrappableType(
+  wrapper_factory_->RegisterWrappableType(
       ConstantsInterface::ConstantsInterfaceWrappableType(),
       base::Bind(MozjsConstantsInterface::CreateProxy),
       base::Bind(MozjsConstantsInterface::PrototypeClass));
-  wrapper_factory->RegisterWrappableType(
+  wrapper_factory_->RegisterWrappableType(
       ConstructorInterface::ConstructorInterfaceWrappableType(),
       base::Bind(MozjsConstructorInterface::CreateProxy),
       base::Bind(MozjsConstructorInterface::PrototypeClass));
-  wrapper_factory->RegisterWrappableType(
+  wrapper_factory_->RegisterWrappableType(
       ConstructorWithArgumentsInterface::ConstructorWithArgumentsInterfaceWrappableType(),
       base::Bind(MozjsConstructorWithArgumentsInterface::CreateProxy),
       base::Bind(MozjsConstructorWithArgumentsInterface::PrototypeClass));
-  wrapper_factory->RegisterWrappableType(
+  wrapper_factory_->RegisterWrappableType(
       DOMStringTestInterface::DOMStringTestInterfaceWrappableType(),
       base::Bind(MozjsDOMStringTestInterface::CreateProxy),
       base::Bind(MozjsDOMStringTestInterface::PrototypeClass));
-  wrapper_factory->RegisterWrappableType(
+  wrapper_factory_->RegisterWrappableType(
       DerivedGetterSetterInterface::DerivedGetterSetterInterfaceWrappableType(),
       base::Bind(MozjsDerivedGetterSetterInterface::CreateProxy),
       base::Bind(MozjsDerivedGetterSetterInterface::PrototypeClass));
-  wrapper_factory->RegisterWrappableType(
+  wrapper_factory_->RegisterWrappableType(
       DerivedInterface::DerivedInterfaceWrappableType(),
       base::Bind(MozjsDerivedInterface::CreateProxy),
       base::Bind(MozjsDerivedInterface::PrototypeClass));
-  wrapper_factory->RegisterWrappableType(
+  wrapper_factory_->RegisterWrappableType(
       DictionaryInterface::DictionaryInterfaceWrappableType(),
       base::Bind(MozjsDictionaryInterface::CreateProxy),
       base::Bind(MozjsDictionaryInterface::PrototypeClass));
 #if defined(NO_ENABLE_CONDITIONAL_INTERFACE)
-  wrapper_factory->RegisterWrappableType(
+  wrapper_factory_->RegisterWrappableType(
       DisabledInterface::DisabledInterfaceWrappableType(),
       base::Bind(MozjsDisabledInterface::CreateProxy),
       base::Bind(MozjsDisabledInterface::PrototypeClass));
 #endif  // defined(NO_ENABLE_CONDITIONAL_INTERFACE)
-  wrapper_factory->RegisterWrappableType(
+  wrapper_factory_->RegisterWrappableType(
       EnumerationInterface::EnumerationInterfaceWrappableType(),
       base::Bind(MozjsEnumerationInterface::CreateProxy),
       base::Bind(MozjsEnumerationInterface::PrototypeClass));
-  wrapper_factory->RegisterWrappableType(
+  wrapper_factory_->RegisterWrappableType(
       ExceptionObjectInterface::ExceptionObjectInterfaceWrappableType(),
       base::Bind(MozjsExceptionObjectInterface::CreateProxy),
       base::Bind(MozjsExceptionObjectInterface::PrototypeClass));
-  wrapper_factory->RegisterWrappableType(
+  wrapper_factory_->RegisterWrappableType(
       ExceptionsInterface::ExceptionsInterfaceWrappableType(),
       base::Bind(MozjsExceptionsInterface::CreateProxy),
       base::Bind(MozjsExceptionsInterface::PrototypeClass));
-  wrapper_factory->RegisterWrappableType(
+  wrapper_factory_->RegisterWrappableType(
       ExtendedIDLAttributesInterface::ExtendedIDLAttributesInterfaceWrappableType(),
       base::Bind(MozjsExtendedIDLAttributesInterface::CreateProxy),
       base::Bind(MozjsExtendedIDLAttributesInterface::PrototypeClass));
-  wrapper_factory->RegisterWrappableType(
+  wrapper_factory_->RegisterWrappableType(
       GarbageCollectionTestInterface::GarbageCollectionTestInterfaceWrappableType(),
       base::Bind(MozjsGarbageCollectionTestInterface::CreateProxy),
       base::Bind(MozjsGarbageCollectionTestInterface::PrototypeClass));
-  wrapper_factory->RegisterWrappableType(
+  wrapper_factory_->RegisterWrappableType(
       GlobalInterfaceParent::GlobalInterfaceParentWrappableType(),
       base::Bind(MozjsGlobalInterfaceParent::CreateProxy),
       base::Bind(MozjsGlobalInterfaceParent::PrototypeClass));
-  wrapper_factory->RegisterWrappableType(
+  wrapper_factory_->RegisterWrappableType(
       ImplementedInterface::ImplementedInterfaceWrappableType(),
       base::Bind(MozjsImplementedInterface::CreateProxy),
       base::Bind(MozjsImplementedInterface::PrototypeClass));
-  wrapper_factory->RegisterWrappableType(
+  wrapper_factory_->RegisterWrappableType(
       IndexedGetterInterface::IndexedGetterInterfaceWrappableType(),
       base::Bind(MozjsIndexedGetterInterface::CreateProxy),
       base::Bind(MozjsIndexedGetterInterface::PrototypeClass));
-  wrapper_factory->RegisterWrappableType(
+  wrapper_factory_->RegisterWrappableType(
       InterfaceWithAny::InterfaceWithAnyWrappableType(),
       base::Bind(MozjsInterfaceWithAny::CreateProxy),
       base::Bind(MozjsInterfaceWithAny::PrototypeClass));
-  wrapper_factory->RegisterWrappableType(
+  wrapper_factory_->RegisterWrappableType(
       InterfaceWithAnyDictionary::InterfaceWithAnyDictionaryWrappableType(),
       base::Bind(MozjsInterfaceWithAnyDictionary::CreateProxy),
       base::Bind(MozjsInterfaceWithAnyDictionary::PrototypeClass));
-  wrapper_factory->RegisterWrappableType(
+  wrapper_factory_->RegisterWrappableType(
       InterfaceWithUnsupportedProperties::InterfaceWithUnsupportedPropertiesWrappableType(),
       base::Bind(MozjsInterfaceWithUnsupportedProperties::CreateProxy),
       base::Bind(MozjsInterfaceWithUnsupportedProperties::PrototypeClass));
-  wrapper_factory->RegisterWrappableType(
+  wrapper_factory_->RegisterWrappableType(
       NamedConstructorInterface::NamedConstructorInterfaceWrappableType(),
       base::Bind(MozjsNamedConstructorInterface::CreateProxy),
       base::Bind(MozjsNamedConstructorInterface::PrototypeClass));
-  wrapper_factory->RegisterWrappableType(
+  wrapper_factory_->RegisterWrappableType(
       NamedGetterInterface::NamedGetterInterfaceWrappableType(),
       base::Bind(MozjsNamedGetterInterface::CreateProxy),
       base::Bind(MozjsNamedGetterInterface::PrototypeClass));
-  wrapper_factory->RegisterWrappableType(
+  wrapper_factory_->RegisterWrappableType(
       NamedIndexedGetterInterface::NamedIndexedGetterInterfaceWrappableType(),
       base::Bind(MozjsNamedIndexedGetterInterface::CreateProxy),
       base::Bind(MozjsNamedIndexedGetterInterface::PrototypeClass));
-  wrapper_factory->RegisterWrappableType(
+  wrapper_factory_->RegisterWrappableType(
       NestedPutForwardsInterface::NestedPutForwardsInterfaceWrappableType(),
       base::Bind(MozjsNestedPutForwardsInterface::CreateProxy),
       base::Bind(MozjsNestedPutForwardsInterface::PrototypeClass));
-  wrapper_factory->RegisterWrappableType(
+  wrapper_factory_->RegisterWrappableType(
       NoConstructorInterface::NoConstructorInterfaceWrappableType(),
       base::Bind(MozjsNoConstructorInterface::CreateProxy),
       base::Bind(MozjsNoConstructorInterface::PrototypeClass));
-  wrapper_factory->RegisterWrappableType(
+  wrapper_factory_->RegisterWrappableType(
       NoInterfaceObjectInterface::NoInterfaceObjectInterfaceWrappableType(),
       base::Bind(MozjsNoInterfaceObjectInterface::CreateProxy),
       base::Bind(MozjsNoInterfaceObjectInterface::PrototypeClass));
-  wrapper_factory->RegisterWrappableType(
+  wrapper_factory_->RegisterWrappableType(
       NullableTypesTestInterface::NullableTypesTestInterfaceWrappableType(),
       base::Bind(MozjsNullableTypesTestInterface::CreateProxy),
       base::Bind(MozjsNullableTypesTestInterface::PrototypeClass));
-  wrapper_factory->RegisterWrappableType(
+  wrapper_factory_->RegisterWrappableType(
       NumericTypesTestInterface::NumericTypesTestInterfaceWrappableType(),
       base::Bind(MozjsNumericTypesTestInterface::CreateProxy),
       base::Bind(MozjsNumericTypesTestInterface::PrototypeClass));
-  wrapper_factory->RegisterWrappableType(
+  wrapper_factory_->RegisterWrappableType(
       ObjectTypeBindingsInterface::ObjectTypeBindingsInterfaceWrappableType(),
       base::Bind(MozjsObjectTypeBindingsInterface::CreateProxy),
       base::Bind(MozjsObjectTypeBindingsInterface::PrototypeClass));
-  wrapper_factory->RegisterWrappableType(
+  wrapper_factory_->RegisterWrappableType(
       OperationsTestInterface::OperationsTestInterfaceWrappableType(),
       base::Bind(MozjsOperationsTestInterface::CreateProxy),
       base::Bind(MozjsOperationsTestInterface::PrototypeClass));
-  wrapper_factory->RegisterWrappableType(
+  wrapper_factory_->RegisterWrappableType(
       PromiseInterface::PromiseInterfaceWrappableType(),
       base::Bind(MozjsPromiseInterface::CreateProxy),
       base::Bind(MozjsPromiseInterface::PrototypeClass));
-  wrapper_factory->RegisterWrappableType(
+  wrapper_factory_->RegisterWrappableType(
       PutForwardsInterface::PutForwardsInterfaceWrappableType(),
       base::Bind(MozjsPutForwardsInterface::CreateProxy),
       base::Bind(MozjsPutForwardsInterface::PrototypeClass));
-  wrapper_factory->RegisterWrappableType(
+  wrapper_factory_->RegisterWrappableType(
       SequenceUser::SequenceUserWrappableType(),
       base::Bind(MozjsSequenceUser::CreateProxy),
       base::Bind(MozjsSequenceUser::PrototypeClass));
-  wrapper_factory->RegisterWrappableType(
+  wrapper_factory_->RegisterWrappableType(
       StaticPropertiesInterface::StaticPropertiesInterfaceWrappableType(),
       base::Bind(MozjsStaticPropertiesInterface::CreateProxy),
       base::Bind(MozjsStaticPropertiesInterface::PrototypeClass));
-  wrapper_factory->RegisterWrappableType(
+  wrapper_factory_->RegisterWrappableType(
       StringifierAnonymousOperationInterface::StringifierAnonymousOperationInterfaceWrappableType(),
       base::Bind(MozjsStringifierAnonymousOperationInterface::CreateProxy),
       base::Bind(MozjsStringifierAnonymousOperationInterface::PrototypeClass));
-  wrapper_factory->RegisterWrappableType(
+  wrapper_factory_->RegisterWrappableType(
       StringifierAttributeInterface::StringifierAttributeInterfaceWrappableType(),
       base::Bind(MozjsStringifierAttributeInterface::CreateProxy),
       base::Bind(MozjsStringifierAttributeInterface::PrototypeClass));
-  wrapper_factory->RegisterWrappableType(
+  wrapper_factory_->RegisterWrappableType(
       StringifierOperationInterface::StringifierOperationInterfaceWrappableType(),
       base::Bind(MozjsStringifierOperationInterface::CreateProxy),
       base::Bind(MozjsStringifierOperationInterface::PrototypeClass));
-  wrapper_factory->RegisterWrappableType(
+  wrapper_factory_->RegisterWrappableType(
       TargetInterface::TargetInterfaceWrappableType(),
       base::Bind(MozjsTargetInterface::CreateProxy),
       base::Bind(MozjsTargetInterface::PrototypeClass));
-  wrapper_factory->RegisterWrappableType(
+  wrapper_factory_->RegisterWrappableType(
       UnionTypesInterface::UnionTypesInterfaceWrappableType(),
       base::Bind(MozjsUnionTypesInterface::CreateProxy),
       base::Bind(MozjsUnionTypesInterface::PrototypeClass));
-  wrapper_factory->RegisterWrappableType(
+  wrapper_factory_->RegisterWrappableType(
       Window::WindowWrappableType(),
       base::Bind(DummyFunctor),
       base::Bind(MozjsWindow::PrototypeClass));
 
 }
 
+}  // namespace mozjs
+
+template<>
+void GlobalEnvironment::CreateGlobalObject<Window>(
+    const scoped_refptr<Window>& global_interface,
+    EnvironmentSettings* environment_settings) {
+  base::polymorphic_downcast<MozjsGlobalEnvironment*>(this)->CreateGlobalObject(
+      global_interface, environment_settings);
+}
+
 }  // namespace script
 }  // namespace cobalt
+
+
diff --git a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/derived_dictionary.h b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/derived_dictionary.h
new file mode 100644
index 0000000..cd27ab6
--- /dev/null
+++ b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/derived_dictionary.h
@@ -0,0 +1,83 @@
+/*
+ * Copyright 2017 Google Inc. All Rights Reserved.
+ *
+ * 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.
+ */
+
+// clang-format off
+
+// This file has been auto-generated by bindings/code_generator_cobalt.py. DO NOT MODIFY!
+// Auto-generated from template: bindings/templates/dictionary.h.template
+
+#ifndef DerivedDictionary_h
+#define DerivedDictionary_h
+
+#include <string>
+
+#include "base/optional.h"
+#include "cobalt/script/script_value.h"
+#include "cobalt/script/sequence.h"
+#include "cobalt/script/value_handle.h"
+#include "cobalt/bindings/testing/test_dictionary.h"
+
+using cobalt::bindings::testing::TestDictionary;
+
+namespace cobalt {
+namespace bindings {
+namespace testing {
+
+class DerivedDictionary : public cobalt::bindings::testing::TestDictionary {
+ public:
+  DerivedDictionary() {
+    additional_member_ = false;
+  }
+
+  DerivedDictionary(const DerivedDictionary& other)
+    : cobalt::bindings::testing::TestDictionary(other) {
+    additional_member_ = other.additional_member_;
+  }
+
+  DerivedDictionary& operator=(const DerivedDictionary& other) {
+    cobalt::bindings::testing::TestDictionary::operator=(other);
+    additional_member_ = other.additional_member_;
+    return *this;
+  }
+
+  bool has_additional_member() const {
+    return true;
+  }
+  bool additional_member() const {
+    return additional_member_;
+  }
+  void set_additional_member(bool value) {
+    additional_member_ = value;
+  }
+
+ private:
+  bool additional_member_;
+};
+
+// This ostream override is necessary for MOCK_METHODs commonly used
+// in idl test code
+inline std::ostream& operator<<(
+    std::ostream& stream, const cobalt::bindings::testing::DerivedDictionary& in) {
+  UNREFERENCED_PARAMETER(in);
+  stream << "[DerivedDictionary]";
+  return stream;
+}
+
+}  // namespace cobalt
+}  // namespace bindings
+}  // namespace testing
+
+#endif  // DerivedDictionary_h
diff --git a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/dictionary_with_dictionary_member.h b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/dictionary_with_dictionary_member.h
new file mode 100644
index 0000000..02dbce6
--- /dev/null
+++ b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/dictionary_with_dictionary_member.h
@@ -0,0 +1,87 @@
+/*
+ * Copyright 2017 Google Inc. All Rights Reserved.
+ *
+ * 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.
+ */
+
+// clang-format off
+
+// This file has been auto-generated by bindings/code_generator_cobalt.py. DO NOT MODIFY!
+// Auto-generated from template: bindings/templates/dictionary.h.template
+
+#ifndef DictionaryWithDictionaryMember_h
+#define DictionaryWithDictionaryMember_h
+
+#include <string>
+
+#include "base/optional.h"
+#include "cobalt/script/script_value.h"
+#include "cobalt/script/sequence.h"
+#include "cobalt/script/value_handle.h"
+#include "cobalt/bindings/testing/test_dictionary.h"
+
+using cobalt::bindings::testing::TestDictionary;
+
+namespace cobalt {
+namespace bindings {
+namespace testing {
+
+class DictionaryWithDictionaryMember {
+ public:
+  DictionaryWithDictionaryMember() {
+    has_nested_dictionary_ = false;
+    nested_dictionary_ = TestDictionary();
+  }
+
+  DictionaryWithDictionaryMember(const DictionaryWithDictionaryMember& other) {
+    has_nested_dictionary_ = other.has_nested_dictionary_;
+    nested_dictionary_ = other.nested_dictionary_;
+  }
+
+  DictionaryWithDictionaryMember& operator=(const DictionaryWithDictionaryMember& other) {
+    has_nested_dictionary_ = other.has_nested_dictionary_;
+    nested_dictionary_ = other.nested_dictionary_;
+    return *this;
+  }
+
+  bool has_nested_dictionary() const {
+    return has_nested_dictionary_;
+  }
+  TestDictionary nested_dictionary() const {
+    DCHECK(has_nested_dictionary_);
+    return nested_dictionary_;
+  }
+  void set_nested_dictionary(TestDictionary value) {
+    has_nested_dictionary_ = true;
+    nested_dictionary_ = value;
+  }
+
+ private:
+  bool has_nested_dictionary_;
+  TestDictionary nested_dictionary_;
+};
+
+// This ostream override is necessary for MOCK_METHODs commonly used
+// in idl test code
+inline std::ostream& operator<<(
+    std::ostream& stream, const cobalt::bindings::testing::DictionaryWithDictionaryMember& in) {
+  UNREFERENCED_PARAMETER(in);
+  stream << "[DictionaryWithDictionaryMember]";
+  return stream;
+}
+
+}  // namespace cobalt
+}  // namespace bindings
+}  // namespace testing
+
+#endif  // DictionaryWithDictionaryMember_h
diff --git a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/test_dictionary.h b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/test_dictionary.h
new file mode 100644
index 0000000..4ec2228
--- /dev/null
+++ b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/test_dictionary.h
@@ -0,0 +1,289 @@
+/*
+ * Copyright 2017 Google Inc. All Rights Reserved.
+ *
+ * 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.
+ */
+
+// clang-format off
+
+// This file has been auto-generated by bindings/code_generator_cobalt.py. DO NOT MODIFY!
+// Auto-generated from template: bindings/templates/dictionary.h.template
+
+#ifndef TestDictionary_h
+#define TestDictionary_h
+
+#include <string>
+
+#include "base/optional.h"
+#include "cobalt/script/script_value.h"
+#include "cobalt/script/sequence.h"
+#include "cobalt/script/value_handle.h"
+#include "cobalt/bindings/testing/arbitrary_interface.h"
+
+using cobalt::bindings::testing::ArbitraryInterface;
+
+namespace cobalt {
+namespace bindings {
+namespace testing {
+
+class TestDictionary {
+ public:
+  TestDictionary() {
+    has_boolean_member_ = false;
+    boolean_member_ = bool();
+    has_short_clamp_member_ = false;
+    short_clamp_member_ = int16_t();
+    has_long_member_ = false;
+    long_member_ = int32_t();
+    has_double_member_ = false;
+    double_member_ = double();
+    has_string_member_ = false;
+    string_member_ = std::string();
+    has_interface_member_ = false;
+    interface_member_ = scoped_refptr<ArbitraryInterface>();
+    member_with_default_ = 5;
+    has_non_default_member_ = false;
+    non_default_member_ = int32_t();
+    has_any_member_ = false;
+  }
+
+  TestDictionary(const TestDictionary& other) {
+    has_boolean_member_ = other.has_boolean_member_;
+    boolean_member_ = other.boolean_member_;
+    has_short_clamp_member_ = other.has_short_clamp_member_;
+    short_clamp_member_ = other.short_clamp_member_;
+    has_long_member_ = other.has_long_member_;
+    long_member_ = other.long_member_;
+    has_double_member_ = other.has_double_member_;
+    double_member_ = other.double_member_;
+    has_string_member_ = other.has_string_member_;
+    string_member_ = other.string_member_;
+    has_interface_member_ = other.has_interface_member_;
+    interface_member_ = other.interface_member_;
+    member_with_default_ = other.member_with_default_;
+    has_non_default_member_ = other.has_non_default_member_;
+    non_default_member_ = other.non_default_member_;
+    if (other.any_member_with_default_) {
+      any_member_with_default_.reset(
+          new script::ScriptValue<::cobalt::script::ValueHandle>::StrongReference(
+              other.any_member_with_default_->referenced_value()));
+    }
+    has_any_member_ = other.has_any_member_;
+    if (other.any_member_) {
+      any_member_.reset(
+          new script::ScriptValue<::cobalt::script::ValueHandle>::StrongReference(
+              other.any_member_->referenced_value()));
+    }
+  }
+
+  TestDictionary& operator=(const TestDictionary& other) {
+    has_boolean_member_ = other.has_boolean_member_;
+    boolean_member_ = other.boolean_member_;
+    has_short_clamp_member_ = other.has_short_clamp_member_;
+    short_clamp_member_ = other.short_clamp_member_;
+    has_long_member_ = other.has_long_member_;
+    long_member_ = other.long_member_;
+    has_double_member_ = other.has_double_member_;
+    double_member_ = other.double_member_;
+    has_string_member_ = other.has_string_member_;
+    string_member_ = other.string_member_;
+    has_interface_member_ = other.has_interface_member_;
+    interface_member_ = other.interface_member_;
+    member_with_default_ = other.member_with_default_;
+    has_non_default_member_ = other.has_non_default_member_;
+    non_default_member_ = other.non_default_member_;
+    if (other.any_member_with_default_) {
+      any_member_with_default_.reset(
+          new script::ScriptValue<::cobalt::script::ValueHandle>::StrongReference(
+                other.any_member_with_default_->referenced_value()));
+    } else {
+      any_member_with_default_.reset();
+    }
+    has_any_member_ = other.has_any_member_;
+    if (other.any_member_) {
+      any_member_.reset(
+          new script::ScriptValue<::cobalt::script::ValueHandle>::StrongReference(
+                other.any_member_->referenced_value()));
+    } else {
+      any_member_.reset();
+    }
+    return *this;
+  }
+
+  bool has_boolean_member() const {
+    return has_boolean_member_;
+  }
+  bool boolean_member() const {
+    DCHECK(has_boolean_member_);
+    return boolean_member_;
+  }
+  void set_boolean_member(bool value) {
+    has_boolean_member_ = true;
+    boolean_member_ = value;
+  }
+
+  bool has_short_clamp_member() const {
+    return has_short_clamp_member_;
+  }
+  int16_t short_clamp_member() const {
+    DCHECK(has_short_clamp_member_);
+    return short_clamp_member_;
+  }
+  void set_short_clamp_member(int16_t value) {
+    has_short_clamp_member_ = true;
+    short_clamp_member_ = value;
+  }
+
+  bool has_long_member() const {
+    return has_long_member_;
+  }
+  int32_t long_member() const {
+    DCHECK(has_long_member_);
+    return long_member_;
+  }
+  void set_long_member(int32_t value) {
+    has_long_member_ = true;
+    long_member_ = value;
+  }
+
+  bool has_double_member() const {
+    return has_double_member_;
+  }
+  double double_member() const {
+    DCHECK(has_double_member_);
+    return double_member_;
+  }
+  void set_double_member(double value) {
+    has_double_member_ = true;
+    double_member_ = value;
+  }
+
+  bool has_string_member() const {
+    return has_string_member_;
+  }
+  const std::string& string_member() const {
+    DCHECK(has_string_member_);
+    return string_member_;
+  }
+  void set_string_member(const std::string& value) {
+    has_string_member_ = true;
+    string_member_ = value;
+  }
+
+  bool has_interface_member() const {
+    return has_interface_member_;
+  }
+  const scoped_refptr<ArbitraryInterface>& interface_member() const {
+    DCHECK(has_interface_member_);
+    return interface_member_;
+  }
+  void set_interface_member(const scoped_refptr<ArbitraryInterface>& value) {
+    has_interface_member_ = true;
+    interface_member_ = value;
+  }
+
+  bool has_member_with_default() const {
+    return true;
+  }
+  int32_t member_with_default() const {
+    return member_with_default_;
+  }
+  void set_member_with_default(int32_t value) {
+    member_with_default_ = value;
+  }
+
+  bool has_non_default_member() const {
+    return has_non_default_member_;
+  }
+  int32_t non_default_member() const {
+    DCHECK(has_non_default_member_);
+    return non_default_member_;
+  }
+  void set_non_default_member(int32_t value) {
+    has_non_default_member_ = true;
+    non_default_member_ = value;
+  }
+
+  bool has_any_member_with_default() const {
+    return true;
+  }
+  const ::cobalt::script::ScriptValue<::cobalt::script::ValueHandle>* any_member_with_default() const {
+    if (!any_member_with_default_) {
+      return NULL;
+    }
+    return &(any_member_with_default_->referenced_value());
+  }
+  void set_any_member_with_default(const ::cobalt::script::ScriptValue<::cobalt::script::ValueHandle>* value) {
+    if (value) {
+      any_member_with_default_.reset(
+          new script::ScriptValue<::cobalt::script::ValueHandle>::StrongReference(*value));
+    } else {
+      any_member_with_default_.reset();
+    }
+  }
+
+  bool has_any_member() const {
+    return has_any_member_;
+  }
+  const ::cobalt::script::ScriptValue<::cobalt::script::ValueHandle>* any_member() const {
+    DCHECK(has_any_member_);
+    if (!any_member_) {
+      return NULL;
+    }
+    return &(any_member_->referenced_value());
+  }
+  void set_any_member(const ::cobalt::script::ScriptValue<::cobalt::script::ValueHandle>* value) {
+    has_any_member_ = true;
+    if (value) {
+      any_member_.reset(
+          new script::ScriptValue<::cobalt::script::ValueHandle>::StrongReference(*value));
+    } else {
+      any_member_.reset();
+    }
+  }
+
+ private:
+  bool has_boolean_member_;
+  bool boolean_member_;
+  bool has_short_clamp_member_;
+  int16_t short_clamp_member_;
+  bool has_long_member_;
+  int32_t long_member_;
+  bool has_double_member_;
+  double double_member_;
+  bool has_string_member_;
+  std::string string_member_;
+  bool has_interface_member_;
+  scoped_refptr<ArbitraryInterface> interface_member_;
+  int32_t member_with_default_;
+  bool has_non_default_member_;
+  int32_t non_default_member_;
+  scoped_ptr<script::ScriptValue<::cobalt::script::ValueHandle>::StrongReference> any_member_with_default_;
+  bool has_any_member_;
+  scoped_ptr<script::ScriptValue<::cobalt::script::ValueHandle>::StrongReference> any_member_;
+};
+
+// This ostream override is necessary for MOCK_METHODs commonly used
+// in idl test code
+inline std::ostream& operator<<(
+    std::ostream& stream, const cobalt::bindings::testing::TestDictionary& in) {
+  UNREFERENCED_PARAMETER(in);
+  stream << "[TestDictionary]";
+  return stream;
+}
+
+}  // namespace cobalt
+}  // namespace bindings
+}  // namespace testing
+
+#endif  // TestDictionary_h
diff --git a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/test_enum.h b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/test_enum.h
new file mode 100644
index 0000000..5e4bb69
--- /dev/null
+++ b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/test_enum.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2017 Google Inc. All Rights Reserved.
+ *
+ * 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.
+ */
+
+// clang-format off
+
+// This file has been auto-generated by bindings/code_generator_cobalt.py. DO NOT MODIFY!
+// Auto-generated from template: bindings/templates/enumeration.h.template
+
+#ifndef TestEnum_h
+#define TestEnum_h
+
+namespace cobalt {
+namespace bindings {
+namespace testing {
+
+enum TestEnum {
+  kTestEnumAlpha,
+  kTestEnumBeta,
+  kTestEnumGamma,
+  kTestEnumEnumWithDashes,
+  kTestEnumEnumWithSpaces,
+  kTestEnumTerribleEnum,
+  kTestEnumThisIsATerribleEnum,
+};
+
+}  // namespace cobalt
+}  // namespace bindings
+}  // namespace testing
+
+#endif  // TestEnum_h
diff --git a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_anonymous_indexed_getter_interface.cc b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_anonymous_indexed_getter_interface.cc
new file mode 100644
index 0000000..2883330
--- /dev/null
+++ b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_anonymous_indexed_getter_interface.cc
@@ -0,0 +1,191 @@
+
+
+// Copyright 2017 Google Inc. All Rights Reserved.
+//
+// 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.
+
+// clang-format off
+
+// This file has been auto-generated by bindings/code_generator_cobalt.py. DO NOT MODIFY!
+// Auto-generated from template: bindings/v8c/templates/interface.cc.template
+
+#include "cobalt/bindings/testing/v8c_anonymous_indexed_getter_interface.h"
+
+#include "base/debug/trace_event.h"
+#include "cobalt/base/polymorphic_downcast.h"
+#include "cobalt/script/global_environment.h"
+#include "cobalt/script/script_value.h"
+#include "cobalt/script/value_handle.h"
+
+#include "v8c_gen_type_conversion.h"
+
+#include "cobalt/script/callback_interface_traits.h"
+#include "cobalt/script/v8c/callback_function_conversion.h"
+#include "cobalt/script/v8c/conversion_helpers.h"
+#include "cobalt/script/v8c/native_promise.h"
+#include "cobalt/script/v8c/type_traits.h"
+#include "cobalt/script/v8c/v8c_callback_function.h"
+#include "cobalt/script/v8c/v8c_callback_interface_holder.h"
+#include "cobalt/script/v8c/v8c_exception_state.h"
+#include "cobalt/script/v8c/v8c_global_environment.h"
+#include "cobalt/script/v8c/v8c_value_handle.h"
+#include "cobalt/script/v8c/wrapper_private.h"
+#include "v8/include/v8.h"
+
+
+namespace {
+using cobalt::bindings::testing::AnonymousIndexedGetterInterface;
+using cobalt::bindings::testing::V8cAnonymousIndexedGetterInterface;
+using cobalt::script::CallbackInterfaceTraits;
+using cobalt::script::GlobalEnvironment;
+using cobalt::script::ScriptValue;
+using cobalt::script::ValueHandle;
+using cobalt::script::ValueHandle;
+using cobalt::script::ValueHandleHolder;
+using cobalt::script::Wrappable;
+
+using cobalt::script::v8c::FromJSValue;
+using cobalt::script::v8c::InterfaceData;
+using cobalt::script::v8c::kConversionFlagClamped;
+using cobalt::script::v8c::kConversionFlagNullable;
+using cobalt::script::v8c::kConversionFlagRestricted;
+using cobalt::script::v8c::kConversionFlagTreatNullAsEmptyString;
+using cobalt::script::v8c::kConversionFlagTreatUndefinedAsEmptyString;
+using cobalt::script::v8c::kNoConversionFlags;
+using cobalt::script::v8c::TypeTraits;
+using cobalt::script::v8c::V8cExceptionState;
+using cobalt::script::v8c::V8cGlobalEnvironment;
+using cobalt::script::v8c::WrapperFactory;
+using cobalt::script::v8c::WrapperPrivate;
+
+v8::Local<v8::Object> DummyFunctor(V8cGlobalEnvironment*, const scoped_refptr<Wrappable>&) {
+  NOTIMPLEMENTED();
+  return {};
+}
+
+}  // namespace
+
+namespace cobalt {
+namespace bindings {
+namespace testing {
+
+
+namespace {
+
+void AnonymousIndexedGetterInterfaceConstructor(const v8::FunctionCallbackInfo<v8::Value>& args) {
+  NOTIMPLEMENTED();
+  if (!args.IsConstructCall()) {
+    // TODO: Probably throw something here...
+    return;
+  }
+
+  DCHECK(args.This()->InternalFieldCount() == 1);
+  args.This()->SetInternalField(0, v8::External::New(args.GetIsolate(), nullptr));
+  args.GetReturnValue().Set(args.This());
+}
+
+
+void v8cGet_length(
+  v8::Local<v8::String> property,
+  const v8::PropertyCallbackInfo<v8::Value>& info)
+{
+  NOTIMPLEMENTED();
+
+  v8::Local<v8::External> external = v8::Local<v8::External>::Cast(info.Holder()->GetInternalField(0));
+  WrapperPrivate* wrapper_private = static_cast<WrapperPrivate*>(external->Value());
+  AnonymousIndexedGetterInterface* impl = static_cast<AnonymousIndexedGetterInterface*>(wrapper_private->wrappable<AnonymousIndexedGetterInterface>());
+
+  v8::Local<v8::Value> result_value;
+}
+
+
+
+void DummyFunction(const v8::FunctionCallbackInfo<v8::Value>& info) {
+  LOG(INFO) << __func__;
+}
+
+void InitializeTemplate(
+  V8cGlobalEnvironment* env,
+  InterfaceData* interface_data) {
+  v8::Isolate* isolate = env->isolate();
+  v8::Local<v8::FunctionTemplate> function_template = v8::FunctionTemplate::New(
+    isolate);
+  function_template->SetClassName(
+    v8::String::NewFromUtf8(isolate, "AnonymousIndexedGetterInterface",
+        v8::NewStringType::kInternalized).ToLocalChecked());
+  v8::Local<v8::ObjectTemplate> instance_template = function_template->InstanceTemplate();
+  instance_template->SetInternalFieldCount(1);
+
+  v8::Local<v8::ObjectTemplate> prototype_template = function_template->PrototypeTemplate();
+  prototype_template->SetInternalFieldCount(1);
+
+  instance_template->SetAccessor(
+    v8::String::NewFromUtf8(isolate, "length",
+                              v8::NewStringType::kInternalized)
+          .ToLocalChecked(),
+    v8cGet_length
+  );
+
+
+  interface_data->templ.Set(env->isolate(), function_template);
+}
+
+inline InterfaceData* GetInterfaceData(V8cGlobalEnvironment* env) {
+  const int kInterfaceUniqueId = 0;
+  // By convention, the |V8cGlobalEnvironment| that we are associated with
+  // will hold our |InterfaceData| at index |kInterfaceUniqueId|, as we asked
+  // for it to be there in the first place, and could not have conflicted with
+  // any other interface.
+  return env->GetInterfaceData(kInterfaceUniqueId);
+}
+
+}  // namespace
+
+v8::Local<v8::Object> V8cAnonymousIndexedGetterInterface::CreateWrapper(V8cGlobalEnvironment* env, const scoped_refptr<Wrappable>& wrappable) {
+  v8::Isolate* isolate = env->isolate();
+  v8::Isolate::Scope isolate_scope(isolate);
+  v8::EscapableHandleScope handle_scope(isolate);
+  v8::Local<v8::Context> context = env->context();
+  v8::Context::Scope scope(context);
+
+  InterfaceData* interface_data = GetInterfaceData(env);
+  if (interface_data->templ.IsEmpty()) {
+    InitializeTemplate(env, interface_data);
+  }
+  DCHECK(!interface_data->templ.IsEmpty());
+
+  v8::Local<v8::FunctionTemplate> function_template = interface_data->templ.Get(isolate);
+  DCHECK(function_template->InstanceTemplate()->InternalFieldCount() == 1);
+  v8::Local<v8::Object> object = function_template->InstanceTemplate()->NewInstance(context).ToLocalChecked();
+  DCHECK(object->InternalFieldCount() == 1);
+
+  // |WrapperPrivate|'s lifetime will be managed by V8.
+  new WrapperPrivate(isolate, wrappable, object);
+  return handle_scope.Escape(object);
+}
+
+v8::Local<v8::FunctionTemplate> V8cAnonymousIndexedGetterInterface::CreateTemplate(V8cGlobalEnvironment* env) {
+  InterfaceData* interface_data = GetInterfaceData(env);
+  if (interface_data->templ.IsEmpty()) {
+    InitializeTemplate(env, interface_data);
+  }
+
+  return interface_data->templ.Get(env->isolate());
+}
+
+
+}  // namespace testing
+}  // namespace bindings
+}  // namespace cobalt
+
+
diff --git a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_anonymous_indexed_getter_interface.h b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_anonymous_indexed_getter_interface.h
new file mode 100644
index 0000000..4031ab3
--- /dev/null
+++ b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_anonymous_indexed_getter_interface.h
@@ -0,0 +1,50 @@
+
+// Copyright 2017 Google Inc. All Rights Reserved.
+//
+// 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.
+
+// clang-format off
+
+// This file has been auto-generated by bindings/code_generator_cobalt.py. DO NOT MODIFY!
+// Auto-generated from template: bindings/v8c/templates/interface.h.template
+
+#ifndef V8cAnonymousIndexedGetterInterface_h
+#define V8cAnonymousIndexedGetterInterface_h
+
+#include "base/hash_tables.h"
+#include "base/lazy_instance.h"
+#include "base/memory/ref_counted.h"
+#include "base/threading/thread_checker.h"
+#include "cobalt/base/polymorphic_downcast.h"
+#include "cobalt/script/wrappable.h"
+#include "cobalt/bindings/testing/anonymous_indexed_getter_interface.h"
+
+#include "cobalt/script/v8c/v8c_global_environment.h"
+#include "v8/include/v8.h"
+
+namespace cobalt {
+namespace bindings {
+namespace testing {
+
+class V8cAnonymousIndexedGetterInterface {
+ public:
+  static v8::Local<v8::Object> CreateWrapper(script::v8c::V8cGlobalEnvironment* env, const scoped_refptr<script::Wrappable>& wrappable);
+  static v8::Local<v8::FunctionTemplate> CreateTemplate(script::v8c::V8cGlobalEnvironment* env);
+  // TODO: Add |GetInterfaceObject|.
+};
+
+}  // namespace testing
+}  // namespace bindings
+}  // namespace cobalt
+
+#endif  // V8cAnonymousIndexedGetterInterface_h
diff --git a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_anonymous_named_getter_interface.cc b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_anonymous_named_getter_interface.cc
new file mode 100644
index 0000000..2fed76f
--- /dev/null
+++ b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_anonymous_named_getter_interface.cc
@@ -0,0 +1,170 @@
+
+
+// Copyright 2017 Google Inc. All Rights Reserved.
+//
+// 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.
+
+// clang-format off
+
+// This file has been auto-generated by bindings/code_generator_cobalt.py. DO NOT MODIFY!
+// Auto-generated from template: bindings/v8c/templates/interface.cc.template
+
+#include "cobalt/bindings/testing/v8c_anonymous_named_getter_interface.h"
+
+#include "base/debug/trace_event.h"
+#include "cobalt/base/polymorphic_downcast.h"
+#include "cobalt/script/global_environment.h"
+#include "cobalt/script/script_value.h"
+#include "cobalt/script/value_handle.h"
+
+#include "v8c_gen_type_conversion.h"
+
+#include "cobalt/script/callback_interface_traits.h"
+#include "cobalt/script/v8c/callback_function_conversion.h"
+#include "cobalt/script/v8c/conversion_helpers.h"
+#include "cobalt/script/v8c/native_promise.h"
+#include "cobalt/script/v8c/type_traits.h"
+#include "cobalt/script/v8c/v8c_callback_function.h"
+#include "cobalt/script/v8c/v8c_callback_interface_holder.h"
+#include "cobalt/script/v8c/v8c_exception_state.h"
+#include "cobalt/script/v8c/v8c_global_environment.h"
+#include "cobalt/script/v8c/v8c_value_handle.h"
+#include "cobalt/script/v8c/wrapper_private.h"
+#include "v8/include/v8.h"
+
+
+namespace {
+using cobalt::bindings::testing::AnonymousNamedGetterInterface;
+using cobalt::bindings::testing::V8cAnonymousNamedGetterInterface;
+using cobalt::script::CallbackInterfaceTraits;
+using cobalt::script::GlobalEnvironment;
+using cobalt::script::ScriptValue;
+using cobalt::script::ValueHandle;
+using cobalt::script::ValueHandle;
+using cobalt::script::ValueHandleHolder;
+using cobalt::script::Wrappable;
+
+using cobalt::script::v8c::FromJSValue;
+using cobalt::script::v8c::InterfaceData;
+using cobalt::script::v8c::kConversionFlagClamped;
+using cobalt::script::v8c::kConversionFlagNullable;
+using cobalt::script::v8c::kConversionFlagRestricted;
+using cobalt::script::v8c::kConversionFlagTreatNullAsEmptyString;
+using cobalt::script::v8c::kConversionFlagTreatUndefinedAsEmptyString;
+using cobalt::script::v8c::kNoConversionFlags;
+using cobalt::script::v8c::TypeTraits;
+using cobalt::script::v8c::V8cExceptionState;
+using cobalt::script::v8c::V8cGlobalEnvironment;
+using cobalt::script::v8c::WrapperFactory;
+using cobalt::script::v8c::WrapperPrivate;
+
+v8::Local<v8::Object> DummyFunctor(V8cGlobalEnvironment*, const scoped_refptr<Wrappable>&) {
+  NOTIMPLEMENTED();
+  return {};
+}
+
+}  // namespace
+
+namespace cobalt {
+namespace bindings {
+namespace testing {
+
+
+namespace {
+
+void AnonymousNamedGetterInterfaceConstructor(const v8::FunctionCallbackInfo<v8::Value>& args) {
+  NOTIMPLEMENTED();
+  if (!args.IsConstructCall()) {
+    // TODO: Probably throw something here...
+    return;
+  }
+
+  DCHECK(args.This()->InternalFieldCount() == 1);
+  args.This()->SetInternalField(0, v8::External::New(args.GetIsolate(), nullptr));
+  args.GetReturnValue().Set(args.This());
+}
+
+
+void DummyFunction(const v8::FunctionCallbackInfo<v8::Value>& info) {
+  LOG(INFO) << __func__;
+}
+
+void InitializeTemplate(
+  V8cGlobalEnvironment* env,
+  InterfaceData* interface_data) {
+  v8::Isolate* isolate = env->isolate();
+  v8::Local<v8::FunctionTemplate> function_template = v8::FunctionTemplate::New(
+    isolate);
+  function_template->SetClassName(
+    v8::String::NewFromUtf8(isolate, "AnonymousNamedGetterInterface",
+        v8::NewStringType::kInternalized).ToLocalChecked());
+  v8::Local<v8::ObjectTemplate> instance_template = function_template->InstanceTemplate();
+  instance_template->SetInternalFieldCount(1);
+
+  v8::Local<v8::ObjectTemplate> prototype_template = function_template->PrototypeTemplate();
+  prototype_template->SetInternalFieldCount(1);
+
+
+
+  interface_data->templ.Set(env->isolate(), function_template);
+}
+
+inline InterfaceData* GetInterfaceData(V8cGlobalEnvironment* env) {
+  const int kInterfaceUniqueId = 1;
+  // By convention, the |V8cGlobalEnvironment| that we are associated with
+  // will hold our |InterfaceData| at index |kInterfaceUniqueId|, as we asked
+  // for it to be there in the first place, and could not have conflicted with
+  // any other interface.
+  return env->GetInterfaceData(kInterfaceUniqueId);
+}
+
+}  // namespace
+
+v8::Local<v8::Object> V8cAnonymousNamedGetterInterface::CreateWrapper(V8cGlobalEnvironment* env, const scoped_refptr<Wrappable>& wrappable) {
+  v8::Isolate* isolate = env->isolate();
+  v8::Isolate::Scope isolate_scope(isolate);
+  v8::EscapableHandleScope handle_scope(isolate);
+  v8::Local<v8::Context> context = env->context();
+  v8::Context::Scope scope(context);
+
+  InterfaceData* interface_data = GetInterfaceData(env);
+  if (interface_data->templ.IsEmpty()) {
+    InitializeTemplate(env, interface_data);
+  }
+  DCHECK(!interface_data->templ.IsEmpty());
+
+  v8::Local<v8::FunctionTemplate> function_template = interface_data->templ.Get(isolate);
+  DCHECK(function_template->InstanceTemplate()->InternalFieldCount() == 1);
+  v8::Local<v8::Object> object = function_template->InstanceTemplate()->NewInstance(context).ToLocalChecked();
+  DCHECK(object->InternalFieldCount() == 1);
+
+  // |WrapperPrivate|'s lifetime will be managed by V8.
+  new WrapperPrivate(isolate, wrappable, object);
+  return handle_scope.Escape(object);
+}
+
+v8::Local<v8::FunctionTemplate> V8cAnonymousNamedGetterInterface::CreateTemplate(V8cGlobalEnvironment* env) {
+  InterfaceData* interface_data = GetInterfaceData(env);
+  if (interface_data->templ.IsEmpty()) {
+    InitializeTemplate(env, interface_data);
+  }
+
+  return interface_data->templ.Get(env->isolate());
+}
+
+
+}  // namespace testing
+}  // namespace bindings
+}  // namespace cobalt
+
+
diff --git a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_anonymous_named_getter_interface.h b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_anonymous_named_getter_interface.h
new file mode 100644
index 0000000..6dfff10
--- /dev/null
+++ b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_anonymous_named_getter_interface.h
@@ -0,0 +1,50 @@
+
+// Copyright 2017 Google Inc. All Rights Reserved.
+//
+// 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.
+
+// clang-format off
+
+// This file has been auto-generated by bindings/code_generator_cobalt.py. DO NOT MODIFY!
+// Auto-generated from template: bindings/v8c/templates/interface.h.template
+
+#ifndef V8cAnonymousNamedGetterInterface_h
+#define V8cAnonymousNamedGetterInterface_h
+
+#include "base/hash_tables.h"
+#include "base/lazy_instance.h"
+#include "base/memory/ref_counted.h"
+#include "base/threading/thread_checker.h"
+#include "cobalt/base/polymorphic_downcast.h"
+#include "cobalt/script/wrappable.h"
+#include "cobalt/bindings/testing/anonymous_named_getter_interface.h"
+
+#include "cobalt/script/v8c/v8c_global_environment.h"
+#include "v8/include/v8.h"
+
+namespace cobalt {
+namespace bindings {
+namespace testing {
+
+class V8cAnonymousNamedGetterInterface {
+ public:
+  static v8::Local<v8::Object> CreateWrapper(script::v8c::V8cGlobalEnvironment* env, const scoped_refptr<script::Wrappable>& wrappable);
+  static v8::Local<v8::FunctionTemplate> CreateTemplate(script::v8c::V8cGlobalEnvironment* env);
+  // TODO: Add |GetInterfaceObject|.
+};
+
+}  // namespace testing
+}  // namespace bindings
+}  // namespace cobalt
+
+#endif  // V8cAnonymousNamedGetterInterface_h
diff --git a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_anonymous_named_indexed_getter_interface.cc b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_anonymous_named_indexed_getter_interface.cc
new file mode 100644
index 0000000..44a8765
--- /dev/null
+++ b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_anonymous_named_indexed_getter_interface.cc
@@ -0,0 +1,191 @@
+
+
+// Copyright 2017 Google Inc. All Rights Reserved.
+//
+// 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.
+
+// clang-format off
+
+// This file has been auto-generated by bindings/code_generator_cobalt.py. DO NOT MODIFY!
+// Auto-generated from template: bindings/v8c/templates/interface.cc.template
+
+#include "cobalt/bindings/testing/v8c_anonymous_named_indexed_getter_interface.h"
+
+#include "base/debug/trace_event.h"
+#include "cobalt/base/polymorphic_downcast.h"
+#include "cobalt/script/global_environment.h"
+#include "cobalt/script/script_value.h"
+#include "cobalt/script/value_handle.h"
+
+#include "v8c_gen_type_conversion.h"
+
+#include "cobalt/script/callback_interface_traits.h"
+#include "cobalt/script/v8c/callback_function_conversion.h"
+#include "cobalt/script/v8c/conversion_helpers.h"
+#include "cobalt/script/v8c/native_promise.h"
+#include "cobalt/script/v8c/type_traits.h"
+#include "cobalt/script/v8c/v8c_callback_function.h"
+#include "cobalt/script/v8c/v8c_callback_interface_holder.h"
+#include "cobalt/script/v8c/v8c_exception_state.h"
+#include "cobalt/script/v8c/v8c_global_environment.h"
+#include "cobalt/script/v8c/v8c_value_handle.h"
+#include "cobalt/script/v8c/wrapper_private.h"
+#include "v8/include/v8.h"
+
+
+namespace {
+using cobalt::bindings::testing::AnonymousNamedIndexedGetterInterface;
+using cobalt::bindings::testing::V8cAnonymousNamedIndexedGetterInterface;
+using cobalt::script::CallbackInterfaceTraits;
+using cobalt::script::GlobalEnvironment;
+using cobalt::script::ScriptValue;
+using cobalt::script::ValueHandle;
+using cobalt::script::ValueHandle;
+using cobalt::script::ValueHandleHolder;
+using cobalt::script::Wrappable;
+
+using cobalt::script::v8c::FromJSValue;
+using cobalt::script::v8c::InterfaceData;
+using cobalt::script::v8c::kConversionFlagClamped;
+using cobalt::script::v8c::kConversionFlagNullable;
+using cobalt::script::v8c::kConversionFlagRestricted;
+using cobalt::script::v8c::kConversionFlagTreatNullAsEmptyString;
+using cobalt::script::v8c::kConversionFlagTreatUndefinedAsEmptyString;
+using cobalt::script::v8c::kNoConversionFlags;
+using cobalt::script::v8c::TypeTraits;
+using cobalt::script::v8c::V8cExceptionState;
+using cobalt::script::v8c::V8cGlobalEnvironment;
+using cobalt::script::v8c::WrapperFactory;
+using cobalt::script::v8c::WrapperPrivate;
+
+v8::Local<v8::Object> DummyFunctor(V8cGlobalEnvironment*, const scoped_refptr<Wrappable>&) {
+  NOTIMPLEMENTED();
+  return {};
+}
+
+}  // namespace
+
+namespace cobalt {
+namespace bindings {
+namespace testing {
+
+
+namespace {
+
+void AnonymousNamedIndexedGetterInterfaceConstructor(const v8::FunctionCallbackInfo<v8::Value>& args) {
+  NOTIMPLEMENTED();
+  if (!args.IsConstructCall()) {
+    // TODO: Probably throw something here...
+    return;
+  }
+
+  DCHECK(args.This()->InternalFieldCount() == 1);
+  args.This()->SetInternalField(0, v8::External::New(args.GetIsolate(), nullptr));
+  args.GetReturnValue().Set(args.This());
+}
+
+
+void v8cGet_length(
+  v8::Local<v8::String> property,
+  const v8::PropertyCallbackInfo<v8::Value>& info)
+{
+  NOTIMPLEMENTED();
+
+  v8::Local<v8::External> external = v8::Local<v8::External>::Cast(info.Holder()->GetInternalField(0));
+  WrapperPrivate* wrapper_private = static_cast<WrapperPrivate*>(external->Value());
+  AnonymousNamedIndexedGetterInterface* impl = static_cast<AnonymousNamedIndexedGetterInterface*>(wrapper_private->wrappable<AnonymousNamedIndexedGetterInterface>());
+
+  v8::Local<v8::Value> result_value;
+}
+
+
+
+void DummyFunction(const v8::FunctionCallbackInfo<v8::Value>& info) {
+  LOG(INFO) << __func__;
+}
+
+void InitializeTemplate(
+  V8cGlobalEnvironment* env,
+  InterfaceData* interface_data) {
+  v8::Isolate* isolate = env->isolate();
+  v8::Local<v8::FunctionTemplate> function_template = v8::FunctionTemplate::New(
+    isolate);
+  function_template->SetClassName(
+    v8::String::NewFromUtf8(isolate, "AnonymousNamedIndexedGetterInterface",
+        v8::NewStringType::kInternalized).ToLocalChecked());
+  v8::Local<v8::ObjectTemplate> instance_template = function_template->InstanceTemplate();
+  instance_template->SetInternalFieldCount(1);
+
+  v8::Local<v8::ObjectTemplate> prototype_template = function_template->PrototypeTemplate();
+  prototype_template->SetInternalFieldCount(1);
+
+  instance_template->SetAccessor(
+    v8::String::NewFromUtf8(isolate, "length",
+                              v8::NewStringType::kInternalized)
+          .ToLocalChecked(),
+    v8cGet_length
+  );
+
+
+  interface_data->templ.Set(env->isolate(), function_template);
+}
+
+inline InterfaceData* GetInterfaceData(V8cGlobalEnvironment* env) {
+  const int kInterfaceUniqueId = 2;
+  // By convention, the |V8cGlobalEnvironment| that we are associated with
+  // will hold our |InterfaceData| at index |kInterfaceUniqueId|, as we asked
+  // for it to be there in the first place, and could not have conflicted with
+  // any other interface.
+  return env->GetInterfaceData(kInterfaceUniqueId);
+}
+
+}  // namespace
+
+v8::Local<v8::Object> V8cAnonymousNamedIndexedGetterInterface::CreateWrapper(V8cGlobalEnvironment* env, const scoped_refptr<Wrappable>& wrappable) {
+  v8::Isolate* isolate = env->isolate();
+  v8::Isolate::Scope isolate_scope(isolate);
+  v8::EscapableHandleScope handle_scope(isolate);
+  v8::Local<v8::Context> context = env->context();
+  v8::Context::Scope scope(context);
+
+  InterfaceData* interface_data = GetInterfaceData(env);
+  if (interface_data->templ.IsEmpty()) {
+    InitializeTemplate(env, interface_data);
+  }
+  DCHECK(!interface_data->templ.IsEmpty());
+
+  v8::Local<v8::FunctionTemplate> function_template = interface_data->templ.Get(isolate);
+  DCHECK(function_template->InstanceTemplate()->InternalFieldCount() == 1);
+  v8::Local<v8::Object> object = function_template->InstanceTemplate()->NewInstance(context).ToLocalChecked();
+  DCHECK(object->InternalFieldCount() == 1);
+
+  // |WrapperPrivate|'s lifetime will be managed by V8.
+  new WrapperPrivate(isolate, wrappable, object);
+  return handle_scope.Escape(object);
+}
+
+v8::Local<v8::FunctionTemplate> V8cAnonymousNamedIndexedGetterInterface::CreateTemplate(V8cGlobalEnvironment* env) {
+  InterfaceData* interface_data = GetInterfaceData(env);
+  if (interface_data->templ.IsEmpty()) {
+    InitializeTemplate(env, interface_data);
+  }
+
+  return interface_data->templ.Get(env->isolate());
+}
+
+
+}  // namespace testing
+}  // namespace bindings
+}  // namespace cobalt
+
+
diff --git a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_anonymous_named_indexed_getter_interface.h b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_anonymous_named_indexed_getter_interface.h
new file mode 100644
index 0000000..07a6fa9
--- /dev/null
+++ b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_anonymous_named_indexed_getter_interface.h
@@ -0,0 +1,50 @@
+
+// Copyright 2017 Google Inc. All Rights Reserved.
+//
+// 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.
+
+// clang-format off
+
+// This file has been auto-generated by bindings/code_generator_cobalt.py. DO NOT MODIFY!
+// Auto-generated from template: bindings/v8c/templates/interface.h.template
+
+#ifndef V8cAnonymousNamedIndexedGetterInterface_h
+#define V8cAnonymousNamedIndexedGetterInterface_h
+
+#include "base/hash_tables.h"
+#include "base/lazy_instance.h"
+#include "base/memory/ref_counted.h"
+#include "base/threading/thread_checker.h"
+#include "cobalt/base/polymorphic_downcast.h"
+#include "cobalt/script/wrappable.h"
+#include "cobalt/bindings/testing/anonymous_named_indexed_getter_interface.h"
+
+#include "cobalt/script/v8c/v8c_global_environment.h"
+#include "v8/include/v8.h"
+
+namespace cobalt {
+namespace bindings {
+namespace testing {
+
+class V8cAnonymousNamedIndexedGetterInterface {
+ public:
+  static v8::Local<v8::Object> CreateWrapper(script::v8c::V8cGlobalEnvironment* env, const scoped_refptr<script::Wrappable>& wrappable);
+  static v8::Local<v8::FunctionTemplate> CreateTemplate(script::v8c::V8cGlobalEnvironment* env);
+  // TODO: Add |GetInterfaceObject|.
+};
+
+}  // namespace testing
+}  // namespace bindings
+}  // namespace cobalt
+
+#endif  // V8cAnonymousNamedIndexedGetterInterface_h
diff --git a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_arbitrary_interface.cc b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_arbitrary_interface.cc
new file mode 100644
index 0000000..33694aa
--- /dev/null
+++ b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_arbitrary_interface.cc
@@ -0,0 +1,217 @@
+
+
+// Copyright 2017 Google Inc. All Rights Reserved.
+//
+// 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.
+
+// clang-format off
+
+// This file has been auto-generated by bindings/code_generator_cobalt.py. DO NOT MODIFY!
+// Auto-generated from template: bindings/v8c/templates/interface.cc.template
+
+#include "cobalt/bindings/testing/v8c_arbitrary_interface.h"
+
+#include "base/debug/trace_event.h"
+#include "cobalt/base/polymorphic_downcast.h"
+#include "cobalt/script/global_environment.h"
+#include "cobalt/script/script_value.h"
+#include "cobalt/script/value_handle.h"
+
+#include "v8c_gen_type_conversion.h"
+
+#include "cobalt/script/callback_interface_traits.h"
+#include "cobalt/script/v8c/callback_function_conversion.h"
+#include "cobalt/script/v8c/conversion_helpers.h"
+#include "cobalt/script/v8c/native_promise.h"
+#include "cobalt/script/v8c/type_traits.h"
+#include "cobalt/script/v8c/v8c_callback_function.h"
+#include "cobalt/script/v8c/v8c_callback_interface_holder.h"
+#include "cobalt/script/v8c/v8c_exception_state.h"
+#include "cobalt/script/v8c/v8c_global_environment.h"
+#include "cobalt/script/v8c/v8c_value_handle.h"
+#include "cobalt/script/v8c/wrapper_private.h"
+#include "v8/include/v8.h"
+
+
+namespace {
+using cobalt::bindings::testing::ArbitraryInterface;
+using cobalt::bindings::testing::V8cArbitraryInterface;
+using cobalt::script::CallbackInterfaceTraits;
+using cobalt::script::GlobalEnvironment;
+using cobalt::script::ScriptValue;
+using cobalt::script::ValueHandle;
+using cobalt::script::ValueHandle;
+using cobalt::script::ValueHandleHolder;
+using cobalt::script::Wrappable;
+
+using cobalt::script::v8c::FromJSValue;
+using cobalt::script::v8c::InterfaceData;
+using cobalt::script::v8c::kConversionFlagClamped;
+using cobalt::script::v8c::kConversionFlagNullable;
+using cobalt::script::v8c::kConversionFlagRestricted;
+using cobalt::script::v8c::kConversionFlagTreatNullAsEmptyString;
+using cobalt::script::v8c::kConversionFlagTreatUndefinedAsEmptyString;
+using cobalt::script::v8c::kNoConversionFlags;
+using cobalt::script::v8c::TypeTraits;
+using cobalt::script::v8c::V8cExceptionState;
+using cobalt::script::v8c::V8cGlobalEnvironment;
+using cobalt::script::v8c::WrapperFactory;
+using cobalt::script::v8c::WrapperPrivate;
+
+v8::Local<v8::Object> DummyFunctor(V8cGlobalEnvironment*, const scoped_refptr<Wrappable>&) {
+  NOTIMPLEMENTED();
+  return {};
+}
+
+}  // namespace
+
+namespace cobalt {
+namespace bindings {
+namespace testing {
+
+
+namespace {
+
+void ArbitraryInterfaceConstructor(const v8::FunctionCallbackInfo<v8::Value>& args) {
+  NOTIMPLEMENTED();
+  if (!args.IsConstructCall()) {
+    // TODO: Probably throw something here...
+    return;
+  }
+
+  DCHECK(args.This()->InternalFieldCount() == 1);
+  args.This()->SetInternalField(0, v8::External::New(args.GetIsolate(), nullptr));
+  args.GetReturnValue().Set(args.This());
+}
+
+
+void v8cGet_arbitraryProperty(
+  v8::Local<v8::String> property,
+  const v8::PropertyCallbackInfo<v8::Value>& info)
+{
+  NOTIMPLEMENTED();
+
+  v8::Local<v8::External> external = v8::Local<v8::External>::Cast(info.Holder()->GetInternalField(0));
+  WrapperPrivate* wrapper_private = static_cast<WrapperPrivate*>(external->Value());
+  ArbitraryInterface* impl = static_cast<ArbitraryInterface*>(wrapper_private->wrappable<ArbitraryInterface>());
+
+  v8::Local<v8::Value> result_value;
+}
+
+
+void v8cSet_arbitraryProperty(
+  v8::Local<v8::String> property,
+  v8::Local<v8::Value> v8_value,
+  const v8::PropertyCallbackInfo<void>& info)
+{
+  v8::Local<v8::External> external = v8::Local<v8::External>::Cast(info.Holder()->GetInternalField(0));
+  WrapperPrivate* wrapper_private = static_cast<WrapperPrivate*>(external->Value());
+  ArbitraryInterface* impl = static_cast<ArbitraryInterface*>(wrapper_private->wrappable<ArbitraryInterface>());
+
+  TypeTraits<std::string>::ConversionType conversion_value;
+  V8cExceptionState exception_state{};
+  FromJSValue(info.GetIsolate(), v8_value, kNoConversionFlags, &exception_state, &conversion_value);
+  impl->set_arbitrary_property(
+    conversion_value
+  );
+}
+
+
+
+void DummyFunction(const v8::FunctionCallbackInfo<v8::Value>& info) {
+  LOG(INFO) << __func__;
+}
+
+void InitializeTemplate(
+  V8cGlobalEnvironment* env,
+  InterfaceData* interface_data) {
+  v8::Isolate* isolate = env->isolate();
+  v8::Local<v8::FunctionTemplate> function_template = v8::FunctionTemplate::New(
+    isolate);
+  function_template->SetClassName(
+    v8::String::NewFromUtf8(isolate, "ArbitraryInterface",
+        v8::NewStringType::kInternalized).ToLocalChecked());
+  v8::Local<v8::ObjectTemplate> instance_template = function_template->InstanceTemplate();
+  instance_template->SetInternalFieldCount(1);
+
+  v8::Local<v8::ObjectTemplate> prototype_template = function_template->PrototypeTemplate();
+  prototype_template->SetInternalFieldCount(1);
+
+  instance_template->SetAccessor(
+    v8::String::NewFromUtf8(isolate, "arbitraryProperty",
+                              v8::NewStringType::kInternalized)
+          .ToLocalChecked(),
+    v8cGet_arbitraryProperty
+    ,v8cSet_arbitraryProperty
+  );
+
+  instance_template->Set(
+      v8::String::NewFromUtf8(
+          isolate,
+          "arbitraryFunction",
+          v8::NewStringType::kInternalized).ToLocalChecked(),
+      v8::FunctionTemplate::New(isolate, DummyFunction)
+  );
+
+  interface_data->templ.Set(env->isolate(), function_template);
+}
+
+inline InterfaceData* GetInterfaceData(V8cGlobalEnvironment* env) {
+  const int kInterfaceUniqueId = 3;
+  // By convention, the |V8cGlobalEnvironment| that we are associated with
+  // will hold our |InterfaceData| at index |kInterfaceUniqueId|, as we asked
+  // for it to be there in the first place, and could not have conflicted with
+  // any other interface.
+  return env->GetInterfaceData(kInterfaceUniqueId);
+}
+
+}  // namespace
+
+v8::Local<v8::Object> V8cArbitraryInterface::CreateWrapper(V8cGlobalEnvironment* env, const scoped_refptr<Wrappable>& wrappable) {
+  v8::Isolate* isolate = env->isolate();
+  v8::Isolate::Scope isolate_scope(isolate);
+  v8::EscapableHandleScope handle_scope(isolate);
+  v8::Local<v8::Context> context = env->context();
+  v8::Context::Scope scope(context);
+
+  InterfaceData* interface_data = GetInterfaceData(env);
+  if (interface_data->templ.IsEmpty()) {
+    InitializeTemplate(env, interface_data);
+  }
+  DCHECK(!interface_data->templ.IsEmpty());
+
+  v8::Local<v8::FunctionTemplate> function_template = interface_data->templ.Get(isolate);
+  DCHECK(function_template->InstanceTemplate()->InternalFieldCount() == 1);
+  v8::Local<v8::Object> object = function_template->InstanceTemplate()->NewInstance(context).ToLocalChecked();
+  DCHECK(object->InternalFieldCount() == 1);
+
+  // |WrapperPrivate|'s lifetime will be managed by V8.
+  new WrapperPrivate(isolate, wrappable, object);
+  return handle_scope.Escape(object);
+}
+
+v8::Local<v8::FunctionTemplate> V8cArbitraryInterface::CreateTemplate(V8cGlobalEnvironment* env) {
+  InterfaceData* interface_data = GetInterfaceData(env);
+  if (interface_data->templ.IsEmpty()) {
+    InitializeTemplate(env, interface_data);
+  }
+
+  return interface_data->templ.Get(env->isolate());
+}
+
+
+}  // namespace testing
+}  // namespace bindings
+}  // namespace cobalt
+
+
diff --git a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_arbitrary_interface.h b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_arbitrary_interface.h
new file mode 100644
index 0000000..fee3b78
--- /dev/null
+++ b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_arbitrary_interface.h
@@ -0,0 +1,50 @@
+
+// Copyright 2017 Google Inc. All Rights Reserved.
+//
+// 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.
+
+// clang-format off
+
+// This file has been auto-generated by bindings/code_generator_cobalt.py. DO NOT MODIFY!
+// Auto-generated from template: bindings/v8c/templates/interface.h.template
+
+#ifndef V8cArbitraryInterface_h
+#define V8cArbitraryInterface_h
+
+#include "base/hash_tables.h"
+#include "base/lazy_instance.h"
+#include "base/memory/ref_counted.h"
+#include "base/threading/thread_checker.h"
+#include "cobalt/base/polymorphic_downcast.h"
+#include "cobalt/script/wrappable.h"
+#include "cobalt/bindings/testing/arbitrary_interface.h"
+
+#include "cobalt/script/v8c/v8c_global_environment.h"
+#include "v8/include/v8.h"
+
+namespace cobalt {
+namespace bindings {
+namespace testing {
+
+class V8cArbitraryInterface {
+ public:
+  static v8::Local<v8::Object> CreateWrapper(script::v8c::V8cGlobalEnvironment* env, const scoped_refptr<script::Wrappable>& wrappable);
+  static v8::Local<v8::FunctionTemplate> CreateTemplate(script::v8c::V8cGlobalEnvironment* env);
+  // TODO: Add |GetInterfaceObject|.
+};
+
+}  // namespace testing
+}  // namespace bindings
+}  // namespace cobalt
+
+#endif  // V8cArbitraryInterface_h
diff --git a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_base_interface.cc b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_base_interface.cc
new file mode 100644
index 0000000..ae6dbeb
--- /dev/null
+++ b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_base_interface.cc
@@ -0,0 +1,198 @@
+
+
+// Copyright 2017 Google Inc. All Rights Reserved.
+//
+// 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.
+
+// clang-format off
+
+// This file has been auto-generated by bindings/code_generator_cobalt.py. DO NOT MODIFY!
+// Auto-generated from template: bindings/v8c/templates/interface.cc.template
+
+#include "cobalt/bindings/testing/v8c_base_interface.h"
+
+#include "base/debug/trace_event.h"
+#include "cobalt/base/polymorphic_downcast.h"
+#include "cobalt/script/global_environment.h"
+#include "cobalt/script/script_value.h"
+#include "cobalt/script/value_handle.h"
+
+#include "v8c_gen_type_conversion.h"
+
+#include "cobalt/script/callback_interface_traits.h"
+#include "cobalt/script/v8c/callback_function_conversion.h"
+#include "cobalt/script/v8c/conversion_helpers.h"
+#include "cobalt/script/v8c/native_promise.h"
+#include "cobalt/script/v8c/type_traits.h"
+#include "cobalt/script/v8c/v8c_callback_function.h"
+#include "cobalt/script/v8c/v8c_callback_interface_holder.h"
+#include "cobalt/script/v8c/v8c_exception_state.h"
+#include "cobalt/script/v8c/v8c_global_environment.h"
+#include "cobalt/script/v8c/v8c_value_handle.h"
+#include "cobalt/script/v8c/wrapper_private.h"
+#include "v8/include/v8.h"
+
+
+namespace {
+using cobalt::bindings::testing::BaseInterface;
+using cobalt::bindings::testing::V8cBaseInterface;
+using cobalt::script::CallbackInterfaceTraits;
+using cobalt::script::GlobalEnvironment;
+using cobalt::script::ScriptValue;
+using cobalt::script::ValueHandle;
+using cobalt::script::ValueHandle;
+using cobalt::script::ValueHandleHolder;
+using cobalt::script::Wrappable;
+
+using cobalt::script::v8c::FromJSValue;
+using cobalt::script::v8c::InterfaceData;
+using cobalt::script::v8c::kConversionFlagClamped;
+using cobalt::script::v8c::kConversionFlagNullable;
+using cobalt::script::v8c::kConversionFlagRestricted;
+using cobalt::script::v8c::kConversionFlagTreatNullAsEmptyString;
+using cobalt::script::v8c::kConversionFlagTreatUndefinedAsEmptyString;
+using cobalt::script::v8c::kNoConversionFlags;
+using cobalt::script::v8c::TypeTraits;
+using cobalt::script::v8c::V8cExceptionState;
+using cobalt::script::v8c::V8cGlobalEnvironment;
+using cobalt::script::v8c::WrapperFactory;
+using cobalt::script::v8c::WrapperPrivate;
+
+v8::Local<v8::Object> DummyFunctor(V8cGlobalEnvironment*, const scoped_refptr<Wrappable>&) {
+  NOTIMPLEMENTED();
+  return {};
+}
+
+}  // namespace
+
+namespace cobalt {
+namespace bindings {
+namespace testing {
+
+
+namespace {
+
+void BaseInterfaceConstructor(const v8::FunctionCallbackInfo<v8::Value>& args) {
+  NOTIMPLEMENTED();
+  if (!args.IsConstructCall()) {
+    // TODO: Probably throw something here...
+    return;
+  }
+
+  DCHECK(args.This()->InternalFieldCount() == 1);
+  args.This()->SetInternalField(0, v8::External::New(args.GetIsolate(), nullptr));
+  args.GetReturnValue().Set(args.This());
+}
+
+
+void v8cGet_baseAttribute(
+  v8::Local<v8::String> property,
+  const v8::PropertyCallbackInfo<v8::Value>& info)
+{
+  NOTIMPLEMENTED();
+
+  v8::Local<v8::External> external = v8::Local<v8::External>::Cast(info.Holder()->GetInternalField(0));
+  WrapperPrivate* wrapper_private = static_cast<WrapperPrivate*>(external->Value());
+  BaseInterface* impl = static_cast<BaseInterface*>(wrapper_private->wrappable<BaseInterface>());
+
+  v8::Local<v8::Value> result_value;
+}
+
+
+
+void DummyFunction(const v8::FunctionCallbackInfo<v8::Value>& info) {
+  LOG(INFO) << __func__;
+}
+
+void InitializeTemplate(
+  V8cGlobalEnvironment* env,
+  InterfaceData* interface_data) {
+  v8::Isolate* isolate = env->isolate();
+  v8::Local<v8::FunctionTemplate> function_template = v8::FunctionTemplate::New(
+    isolate);
+  function_template->SetClassName(
+    v8::String::NewFromUtf8(isolate, "BaseInterface",
+        v8::NewStringType::kInternalized).ToLocalChecked());
+  v8::Local<v8::ObjectTemplate> instance_template = function_template->InstanceTemplate();
+  instance_template->SetInternalFieldCount(1);
+
+  v8::Local<v8::ObjectTemplate> prototype_template = function_template->PrototypeTemplate();
+  prototype_template->SetInternalFieldCount(1);
+
+  instance_template->SetAccessor(
+    v8::String::NewFromUtf8(isolate, "baseAttribute",
+                              v8::NewStringType::kInternalized)
+          .ToLocalChecked(),
+    v8cGet_baseAttribute
+  );
+
+  instance_template->Set(
+      v8::String::NewFromUtf8(
+          isolate,
+          "baseOperation",
+          v8::NewStringType::kInternalized).ToLocalChecked(),
+      v8::FunctionTemplate::New(isolate, DummyFunction)
+  );
+
+  interface_data->templ.Set(env->isolate(), function_template);
+}
+
+inline InterfaceData* GetInterfaceData(V8cGlobalEnvironment* env) {
+  const int kInterfaceUniqueId = 4;
+  // By convention, the |V8cGlobalEnvironment| that we are associated with
+  // will hold our |InterfaceData| at index |kInterfaceUniqueId|, as we asked
+  // for it to be there in the first place, and could not have conflicted with
+  // any other interface.
+  return env->GetInterfaceData(kInterfaceUniqueId);
+}
+
+}  // namespace
+
+v8::Local<v8::Object> V8cBaseInterface::CreateWrapper(V8cGlobalEnvironment* env, const scoped_refptr<Wrappable>& wrappable) {
+  v8::Isolate* isolate = env->isolate();
+  v8::Isolate::Scope isolate_scope(isolate);
+  v8::EscapableHandleScope handle_scope(isolate);
+  v8::Local<v8::Context> context = env->context();
+  v8::Context::Scope scope(context);
+
+  InterfaceData* interface_data = GetInterfaceData(env);
+  if (interface_data->templ.IsEmpty()) {
+    InitializeTemplate(env, interface_data);
+  }
+  DCHECK(!interface_data->templ.IsEmpty());
+
+  v8::Local<v8::FunctionTemplate> function_template = interface_data->templ.Get(isolate);
+  DCHECK(function_template->InstanceTemplate()->InternalFieldCount() == 1);
+  v8::Local<v8::Object> object = function_template->InstanceTemplate()->NewInstance(context).ToLocalChecked();
+  DCHECK(object->InternalFieldCount() == 1);
+
+  // |WrapperPrivate|'s lifetime will be managed by V8.
+  new WrapperPrivate(isolate, wrappable, object);
+  return handle_scope.Escape(object);
+}
+
+v8::Local<v8::FunctionTemplate> V8cBaseInterface::CreateTemplate(V8cGlobalEnvironment* env) {
+  InterfaceData* interface_data = GetInterfaceData(env);
+  if (interface_data->templ.IsEmpty()) {
+    InitializeTemplate(env, interface_data);
+  }
+
+  return interface_data->templ.Get(env->isolate());
+}
+
+
+}  // namespace testing
+}  // namespace bindings
+}  // namespace cobalt
+
+
diff --git a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_base_interface.h b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_base_interface.h
new file mode 100644
index 0000000..429707a
--- /dev/null
+++ b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_base_interface.h
@@ -0,0 +1,50 @@
+
+// Copyright 2017 Google Inc. All Rights Reserved.
+//
+// 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.
+
+// clang-format off
+
+// This file has been auto-generated by bindings/code_generator_cobalt.py. DO NOT MODIFY!
+// Auto-generated from template: bindings/v8c/templates/interface.h.template
+
+#ifndef V8cBaseInterface_h
+#define V8cBaseInterface_h
+
+#include "base/hash_tables.h"
+#include "base/lazy_instance.h"
+#include "base/memory/ref_counted.h"
+#include "base/threading/thread_checker.h"
+#include "cobalt/base/polymorphic_downcast.h"
+#include "cobalt/script/wrappable.h"
+#include "cobalt/bindings/testing/base_interface.h"
+
+#include "cobalt/script/v8c/v8c_global_environment.h"
+#include "v8/include/v8.h"
+
+namespace cobalt {
+namespace bindings {
+namespace testing {
+
+class V8cBaseInterface {
+ public:
+  static v8::Local<v8::Object> CreateWrapper(script::v8c::V8cGlobalEnvironment* env, const scoped_refptr<script::Wrappable>& wrappable);
+  static v8::Local<v8::FunctionTemplate> CreateTemplate(script::v8c::V8cGlobalEnvironment* env);
+  // TODO: Add |GetInterfaceObject|.
+};
+
+}  // namespace testing
+}  // namespace bindings
+}  // namespace cobalt
+
+#endif  // V8cBaseInterface_h
diff --git a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_boolean_type_test_interface.cc b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_boolean_type_test_interface.cc
new file mode 100644
index 0000000..3885210
--- /dev/null
+++ b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_boolean_type_test_interface.cc
@@ -0,0 +1,224 @@
+
+
+// Copyright 2017 Google Inc. All Rights Reserved.
+//
+// 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.
+
+// clang-format off
+
+// This file has been auto-generated by bindings/code_generator_cobalt.py. DO NOT MODIFY!
+// Auto-generated from template: bindings/v8c/templates/interface.cc.template
+
+#include "cobalt/bindings/testing/v8c_boolean_type_test_interface.h"
+
+#include "base/debug/trace_event.h"
+#include "cobalt/base/polymorphic_downcast.h"
+#include "cobalt/script/global_environment.h"
+#include "cobalt/script/script_value.h"
+#include "cobalt/script/value_handle.h"
+
+#include "v8c_gen_type_conversion.h"
+
+#include "cobalt/script/callback_interface_traits.h"
+#include "cobalt/script/v8c/callback_function_conversion.h"
+#include "cobalt/script/v8c/conversion_helpers.h"
+#include "cobalt/script/v8c/native_promise.h"
+#include "cobalt/script/v8c/type_traits.h"
+#include "cobalt/script/v8c/v8c_callback_function.h"
+#include "cobalt/script/v8c/v8c_callback_interface_holder.h"
+#include "cobalt/script/v8c/v8c_exception_state.h"
+#include "cobalt/script/v8c/v8c_global_environment.h"
+#include "cobalt/script/v8c/v8c_value_handle.h"
+#include "cobalt/script/v8c/wrapper_private.h"
+#include "v8/include/v8.h"
+
+
+namespace {
+using cobalt::bindings::testing::BooleanTypeTestInterface;
+using cobalt::bindings::testing::V8cBooleanTypeTestInterface;
+using cobalt::script::CallbackInterfaceTraits;
+using cobalt::script::GlobalEnvironment;
+using cobalt::script::ScriptValue;
+using cobalt::script::ValueHandle;
+using cobalt::script::ValueHandle;
+using cobalt::script::ValueHandleHolder;
+using cobalt::script::Wrappable;
+
+using cobalt::script::v8c::FromJSValue;
+using cobalt::script::v8c::InterfaceData;
+using cobalt::script::v8c::kConversionFlagClamped;
+using cobalt::script::v8c::kConversionFlagNullable;
+using cobalt::script::v8c::kConversionFlagRestricted;
+using cobalt::script::v8c::kConversionFlagTreatNullAsEmptyString;
+using cobalt::script::v8c::kConversionFlagTreatUndefinedAsEmptyString;
+using cobalt::script::v8c::kNoConversionFlags;
+using cobalt::script::v8c::TypeTraits;
+using cobalt::script::v8c::V8cExceptionState;
+using cobalt::script::v8c::V8cGlobalEnvironment;
+using cobalt::script::v8c::WrapperFactory;
+using cobalt::script::v8c::WrapperPrivate;
+
+v8::Local<v8::Object> DummyFunctor(V8cGlobalEnvironment*, const scoped_refptr<Wrappable>&) {
+  NOTIMPLEMENTED();
+  return {};
+}
+
+}  // namespace
+
+namespace cobalt {
+namespace bindings {
+namespace testing {
+
+
+namespace {
+
+void BooleanTypeTestInterfaceConstructor(const v8::FunctionCallbackInfo<v8::Value>& args) {
+  NOTIMPLEMENTED();
+  if (!args.IsConstructCall()) {
+    // TODO: Probably throw something here...
+    return;
+  }
+
+  DCHECK(args.This()->InternalFieldCount() == 1);
+  args.This()->SetInternalField(0, v8::External::New(args.GetIsolate(), nullptr));
+  args.GetReturnValue().Set(args.This());
+}
+
+
+void v8cGet_booleanProperty(
+  v8::Local<v8::String> property,
+  const v8::PropertyCallbackInfo<v8::Value>& info)
+{
+  NOTIMPLEMENTED();
+
+  v8::Local<v8::External> external = v8::Local<v8::External>::Cast(info.Holder()->GetInternalField(0));
+  WrapperPrivate* wrapper_private = static_cast<WrapperPrivate*>(external->Value());
+  BooleanTypeTestInterface* impl = static_cast<BooleanTypeTestInterface*>(wrapper_private->wrappable<BooleanTypeTestInterface>());
+
+  v8::Local<v8::Value> result_value;
+}
+
+
+void v8cSet_booleanProperty(
+  v8::Local<v8::String> property,
+  v8::Local<v8::Value> v8_value,
+  const v8::PropertyCallbackInfo<void>& info)
+{
+  v8::Local<v8::External> external = v8::Local<v8::External>::Cast(info.Holder()->GetInternalField(0));
+  WrapperPrivate* wrapper_private = static_cast<WrapperPrivate*>(external->Value());
+  BooleanTypeTestInterface* impl = static_cast<BooleanTypeTestInterface*>(wrapper_private->wrappable<BooleanTypeTestInterface>());
+
+  TypeTraits<bool>::ConversionType conversion_value;
+  V8cExceptionState exception_state{};
+  FromJSValue(info.GetIsolate(), v8_value, kNoConversionFlags, &exception_state, &conversion_value);
+  impl->set_boolean_property(
+    conversion_value
+  );
+}
+
+
+
+void DummyFunction(const v8::FunctionCallbackInfo<v8::Value>& info) {
+  LOG(INFO) << __func__;
+}
+
+void InitializeTemplate(
+  V8cGlobalEnvironment* env,
+  InterfaceData* interface_data) {
+  v8::Isolate* isolate = env->isolate();
+  v8::Local<v8::FunctionTemplate> function_template = v8::FunctionTemplate::New(
+    isolate);
+  function_template->SetClassName(
+    v8::String::NewFromUtf8(isolate, "BooleanTypeTestInterface",
+        v8::NewStringType::kInternalized).ToLocalChecked());
+  v8::Local<v8::ObjectTemplate> instance_template = function_template->InstanceTemplate();
+  instance_template->SetInternalFieldCount(1);
+
+  v8::Local<v8::ObjectTemplate> prototype_template = function_template->PrototypeTemplate();
+  prototype_template->SetInternalFieldCount(1);
+
+  instance_template->SetAccessor(
+    v8::String::NewFromUtf8(isolate, "booleanProperty",
+                              v8::NewStringType::kInternalized)
+          .ToLocalChecked(),
+    v8cGet_booleanProperty
+    ,v8cSet_booleanProperty
+  );
+
+  instance_template->Set(
+      v8::String::NewFromUtf8(
+          isolate,
+          "booleanArgumentOperation",
+          v8::NewStringType::kInternalized).ToLocalChecked(),
+      v8::FunctionTemplate::New(isolate, DummyFunction)
+  );
+  instance_template->Set(
+      v8::String::NewFromUtf8(
+          isolate,
+          "booleanReturnOperation",
+          v8::NewStringType::kInternalized).ToLocalChecked(),
+      v8::FunctionTemplate::New(isolate, DummyFunction)
+  );
+
+  interface_data->templ.Set(env->isolate(), function_template);
+}
+
+inline InterfaceData* GetInterfaceData(V8cGlobalEnvironment* env) {
+  const int kInterfaceUniqueId = 5;
+  // By convention, the |V8cGlobalEnvironment| that we are associated with
+  // will hold our |InterfaceData| at index |kInterfaceUniqueId|, as we asked
+  // for it to be there in the first place, and could not have conflicted with
+  // any other interface.
+  return env->GetInterfaceData(kInterfaceUniqueId);
+}
+
+}  // namespace
+
+v8::Local<v8::Object> V8cBooleanTypeTestInterface::CreateWrapper(V8cGlobalEnvironment* env, const scoped_refptr<Wrappable>& wrappable) {
+  v8::Isolate* isolate = env->isolate();
+  v8::Isolate::Scope isolate_scope(isolate);
+  v8::EscapableHandleScope handle_scope(isolate);
+  v8::Local<v8::Context> context = env->context();
+  v8::Context::Scope scope(context);
+
+  InterfaceData* interface_data = GetInterfaceData(env);
+  if (interface_data->templ.IsEmpty()) {
+    InitializeTemplate(env, interface_data);
+  }
+  DCHECK(!interface_data->templ.IsEmpty());
+
+  v8::Local<v8::FunctionTemplate> function_template = interface_data->templ.Get(isolate);
+  DCHECK(function_template->InstanceTemplate()->InternalFieldCount() == 1);
+  v8::Local<v8::Object> object = function_template->InstanceTemplate()->NewInstance(context).ToLocalChecked();
+  DCHECK(object->InternalFieldCount() == 1);
+
+  // |WrapperPrivate|'s lifetime will be managed by V8.
+  new WrapperPrivate(isolate, wrappable, object);
+  return handle_scope.Escape(object);
+}
+
+v8::Local<v8::FunctionTemplate> V8cBooleanTypeTestInterface::CreateTemplate(V8cGlobalEnvironment* env) {
+  InterfaceData* interface_data = GetInterfaceData(env);
+  if (interface_data->templ.IsEmpty()) {
+    InitializeTemplate(env, interface_data);
+  }
+
+  return interface_data->templ.Get(env->isolate());
+}
+
+
+}  // namespace testing
+}  // namespace bindings
+}  // namespace cobalt
+
+
diff --git a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_boolean_type_test_interface.h b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_boolean_type_test_interface.h
new file mode 100644
index 0000000..80ab3b1
--- /dev/null
+++ b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_boolean_type_test_interface.h
@@ -0,0 +1,50 @@
+
+// Copyright 2017 Google Inc. All Rights Reserved.
+//
+// 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.
+
+// clang-format off
+
+// This file has been auto-generated by bindings/code_generator_cobalt.py. DO NOT MODIFY!
+// Auto-generated from template: bindings/v8c/templates/interface.h.template
+
+#ifndef V8cBooleanTypeTestInterface_h
+#define V8cBooleanTypeTestInterface_h
+
+#include "base/hash_tables.h"
+#include "base/lazy_instance.h"
+#include "base/memory/ref_counted.h"
+#include "base/threading/thread_checker.h"
+#include "cobalt/base/polymorphic_downcast.h"
+#include "cobalt/script/wrappable.h"
+#include "cobalt/bindings/testing/boolean_type_test_interface.h"
+
+#include "cobalt/script/v8c/v8c_global_environment.h"
+#include "v8/include/v8.h"
+
+namespace cobalt {
+namespace bindings {
+namespace testing {
+
+class V8cBooleanTypeTestInterface {
+ public:
+  static v8::Local<v8::Object> CreateWrapper(script::v8c::V8cGlobalEnvironment* env, const scoped_refptr<script::Wrappable>& wrappable);
+  static v8::Local<v8::FunctionTemplate> CreateTemplate(script::v8c::V8cGlobalEnvironment* env);
+  // TODO: Add |GetInterfaceObject|.
+};
+
+}  // namespace testing
+}  // namespace bindings
+}  // namespace cobalt
+
+#endif  // V8cBooleanTypeTestInterface_h
diff --git a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_callback_function_interface.cc b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_callback_function_interface.cc
new file mode 100644
index 0000000..0304336
--- /dev/null
+++ b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_callback_function_interface.cc
@@ -0,0 +1,289 @@
+
+
+// Copyright 2017 Google Inc. All Rights Reserved.
+//
+// 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.
+
+// clang-format off
+
+// This file has been auto-generated by bindings/code_generator_cobalt.py. DO NOT MODIFY!
+// Auto-generated from template: bindings/v8c/templates/interface.cc.template
+
+#include "cobalt/bindings/testing/v8c_callback_function_interface.h"
+
+#include "base/debug/trace_event.h"
+#include "cobalt/base/polymorphic_downcast.h"
+#include "cobalt/script/global_environment.h"
+#include "cobalt/script/script_value.h"
+#include "cobalt/script/value_handle.h"
+#include "cobalt/bindings/testing/arbitrary_interface.h"
+#include "cobalt/bindings/testing/v8c_arbitrary_interface.h"
+
+#include "v8c_gen_type_conversion.h"
+
+#include "cobalt/script/callback_interface_traits.h"
+#include "cobalt/script/v8c/callback_function_conversion.h"
+#include "cobalt/script/v8c/conversion_helpers.h"
+#include "cobalt/script/v8c/native_promise.h"
+#include "cobalt/script/v8c/type_traits.h"
+#include "cobalt/script/v8c/v8c_callback_function.h"
+#include "cobalt/script/v8c/v8c_callback_interface_holder.h"
+#include "cobalt/script/v8c/v8c_exception_state.h"
+#include "cobalt/script/v8c/v8c_global_environment.h"
+#include "cobalt/script/v8c/v8c_value_handle.h"
+#include "cobalt/script/v8c/wrapper_private.h"
+#include "v8/include/v8.h"
+
+
+namespace {
+using cobalt::bindings::testing::CallbackFunctionInterface;
+using cobalt::bindings::testing::V8cCallbackFunctionInterface;
+using cobalt::bindings::testing::ArbitraryInterface;
+using cobalt::bindings::testing::V8cArbitraryInterface;
+using cobalt::script::CallbackInterfaceTraits;
+using cobalt::script::GlobalEnvironment;
+using cobalt::script::ScriptValue;
+using cobalt::script::ValueHandle;
+using cobalt::script::ValueHandle;
+using cobalt::script::ValueHandleHolder;
+using cobalt::script::Wrappable;
+
+using cobalt::script::v8c::FromJSValue;
+using cobalt::script::v8c::InterfaceData;
+using cobalt::script::v8c::kConversionFlagClamped;
+using cobalt::script::v8c::kConversionFlagNullable;
+using cobalt::script::v8c::kConversionFlagRestricted;
+using cobalt::script::v8c::kConversionFlagTreatNullAsEmptyString;
+using cobalt::script::v8c::kConversionFlagTreatUndefinedAsEmptyString;
+using cobalt::script::v8c::kNoConversionFlags;
+using cobalt::script::v8c::TypeTraits;
+using cobalt::script::v8c::V8cExceptionState;
+using cobalt::script::v8c::V8cGlobalEnvironment;
+using cobalt::script::v8c::WrapperFactory;
+using cobalt::script::v8c::WrapperPrivate;
+
+v8::Local<v8::Object> DummyFunctor(V8cGlobalEnvironment*, const scoped_refptr<Wrappable>&) {
+  NOTIMPLEMENTED();
+  return {};
+}
+
+}  // namespace
+
+namespace cobalt {
+namespace bindings {
+namespace testing {
+
+
+namespace {
+
+void CallbackFunctionInterfaceConstructor(const v8::FunctionCallbackInfo<v8::Value>& args) {
+  NOTIMPLEMENTED();
+  if (!args.IsConstructCall()) {
+    // TODO: Probably throw something here...
+    return;
+  }
+
+  DCHECK(args.This()->InternalFieldCount() == 1);
+  args.This()->SetInternalField(0, v8::External::New(args.GetIsolate(), nullptr));
+  args.GetReturnValue().Set(args.This());
+}
+
+
+void v8cGet_callbackAttribute(
+  v8::Local<v8::String> property,
+  const v8::PropertyCallbackInfo<v8::Value>& info)
+{
+  NOTIMPLEMENTED();
+
+  v8::Local<v8::External> external = v8::Local<v8::External>::Cast(info.Holder()->GetInternalField(0));
+  WrapperPrivate* wrapper_private = static_cast<WrapperPrivate*>(external->Value());
+  CallbackFunctionInterface* impl = static_cast<CallbackFunctionInterface*>(wrapper_private->wrappable<CallbackFunctionInterface>());
+
+  v8::Local<v8::Value> result_value;
+}
+
+
+void v8cSet_callbackAttribute(
+  v8::Local<v8::String> property,
+  v8::Local<v8::Value> v8_value,
+  const v8::PropertyCallbackInfo<void>& info)
+{
+  v8::Local<v8::External> external = v8::Local<v8::External>::Cast(info.Holder()->GetInternalField(0));
+  WrapperPrivate* wrapper_private = static_cast<WrapperPrivate*>(external->Value());
+  CallbackFunctionInterface* impl = static_cast<CallbackFunctionInterface*>(wrapper_private->wrappable<CallbackFunctionInterface>());
+
+  TypeTraits<CallbackFunctionInterface::VoidFunction>::ConversionType conversion_value;
+  V8cExceptionState exception_state{};
+  FromJSValue(info.GetIsolate(), v8_value, kNoConversionFlags, &exception_state, &conversion_value);
+  impl->set_callback_attribute(
+    conversion_value
+  );
+}
+
+
+
+void v8cGet_nullableCallbackAttribute(
+  v8::Local<v8::String> property,
+  const v8::PropertyCallbackInfo<v8::Value>& info)
+{
+  NOTIMPLEMENTED();
+
+  v8::Local<v8::External> external = v8::Local<v8::External>::Cast(info.Holder()->GetInternalField(0));
+  WrapperPrivate* wrapper_private = static_cast<WrapperPrivate*>(external->Value());
+  CallbackFunctionInterface* impl = static_cast<CallbackFunctionInterface*>(wrapper_private->wrappable<CallbackFunctionInterface>());
+
+  v8::Local<v8::Value> result_value;
+}
+
+
+void v8cSet_nullableCallbackAttribute(
+  v8::Local<v8::String> property,
+  v8::Local<v8::Value> v8_value,
+  const v8::PropertyCallbackInfo<void>& info)
+{
+  v8::Local<v8::External> external = v8::Local<v8::External>::Cast(info.Holder()->GetInternalField(0));
+  WrapperPrivate* wrapper_private = static_cast<WrapperPrivate*>(external->Value());
+  CallbackFunctionInterface* impl = static_cast<CallbackFunctionInterface*>(wrapper_private->wrappable<CallbackFunctionInterface>());
+
+  TypeTraits<CallbackFunctionInterface::VoidFunction>::ConversionType conversion_value;
+  V8cExceptionState exception_state{};
+  FromJSValue(info.GetIsolate(), v8_value, (kConversionFlagNullable), &exception_state, &conversion_value);
+  impl->set_nullable_callback_attribute(
+    conversion_value
+  );
+}
+
+
+
+void DummyFunction(const v8::FunctionCallbackInfo<v8::Value>& info) {
+  LOG(INFO) << __func__;
+}
+
+void InitializeTemplate(
+  V8cGlobalEnvironment* env,
+  InterfaceData* interface_data) {
+  v8::Isolate* isolate = env->isolate();
+  v8::Local<v8::FunctionTemplate> function_template = v8::FunctionTemplate::New(
+    isolate);
+  function_template->SetClassName(
+    v8::String::NewFromUtf8(isolate, "CallbackFunctionInterface",
+        v8::NewStringType::kInternalized).ToLocalChecked());
+  v8::Local<v8::ObjectTemplate> instance_template = function_template->InstanceTemplate();
+  instance_template->SetInternalFieldCount(1);
+
+  v8::Local<v8::ObjectTemplate> prototype_template = function_template->PrototypeTemplate();
+  prototype_template->SetInternalFieldCount(1);
+
+  instance_template->SetAccessor(
+    v8::String::NewFromUtf8(isolate, "callbackAttribute",
+                              v8::NewStringType::kInternalized)
+          .ToLocalChecked(),
+    v8cGet_callbackAttribute
+    ,v8cSet_callbackAttribute
+  );
+  instance_template->SetAccessor(
+    v8::String::NewFromUtf8(isolate, "nullableCallbackAttribute",
+                              v8::NewStringType::kInternalized)
+          .ToLocalChecked(),
+    v8cGet_nullableCallbackAttribute
+    ,v8cSet_nullableCallbackAttribute
+  );
+
+  instance_template->Set(
+      v8::String::NewFromUtf8(
+          isolate,
+          "takesFunctionThatReturnsString",
+          v8::NewStringType::kInternalized).ToLocalChecked(),
+      v8::FunctionTemplate::New(isolate, DummyFunction)
+  );
+  instance_template->Set(
+      v8::String::NewFromUtf8(
+          isolate,
+          "takesFunctionWithNullableParameters",
+          v8::NewStringType::kInternalized).ToLocalChecked(),
+      v8::FunctionTemplate::New(isolate, DummyFunction)
+  );
+  instance_template->Set(
+      v8::String::NewFromUtf8(
+          isolate,
+          "takesFunctionWithOneParameter",
+          v8::NewStringType::kInternalized).ToLocalChecked(),
+      v8::FunctionTemplate::New(isolate, DummyFunction)
+  );
+  instance_template->Set(
+      v8::String::NewFromUtf8(
+          isolate,
+          "takesFunctionWithSeveralParameters",
+          v8::NewStringType::kInternalized).ToLocalChecked(),
+      v8::FunctionTemplate::New(isolate, DummyFunction)
+  );
+  instance_template->Set(
+      v8::String::NewFromUtf8(
+          isolate,
+          "takesVoidFunction",
+          v8::NewStringType::kInternalized).ToLocalChecked(),
+      v8::FunctionTemplate::New(isolate, DummyFunction)
+  );
+
+  interface_data->templ.Set(env->isolate(), function_template);
+}
+
+inline InterfaceData* GetInterfaceData(V8cGlobalEnvironment* env) {
+  const int kInterfaceUniqueId = 6;
+  // By convention, the |V8cGlobalEnvironment| that we are associated with
+  // will hold our |InterfaceData| at index |kInterfaceUniqueId|, as we asked
+  // for it to be there in the first place, and could not have conflicted with
+  // any other interface.
+  return env->GetInterfaceData(kInterfaceUniqueId);
+}
+
+}  // namespace
+
+v8::Local<v8::Object> V8cCallbackFunctionInterface::CreateWrapper(V8cGlobalEnvironment* env, const scoped_refptr<Wrappable>& wrappable) {
+  v8::Isolate* isolate = env->isolate();
+  v8::Isolate::Scope isolate_scope(isolate);
+  v8::EscapableHandleScope handle_scope(isolate);
+  v8::Local<v8::Context> context = env->context();
+  v8::Context::Scope scope(context);
+
+  InterfaceData* interface_data = GetInterfaceData(env);
+  if (interface_data->templ.IsEmpty()) {
+    InitializeTemplate(env, interface_data);
+  }
+  DCHECK(!interface_data->templ.IsEmpty());
+
+  v8::Local<v8::FunctionTemplate> function_template = interface_data->templ.Get(isolate);
+  DCHECK(function_template->InstanceTemplate()->InternalFieldCount() == 1);
+  v8::Local<v8::Object> object = function_template->InstanceTemplate()->NewInstance(context).ToLocalChecked();
+  DCHECK(object->InternalFieldCount() == 1);
+
+  // |WrapperPrivate|'s lifetime will be managed by V8.
+  new WrapperPrivate(isolate, wrappable, object);
+  return handle_scope.Escape(object);
+}
+
+v8::Local<v8::FunctionTemplate> V8cCallbackFunctionInterface::CreateTemplate(V8cGlobalEnvironment* env) {
+  InterfaceData* interface_data = GetInterfaceData(env);
+  if (interface_data->templ.IsEmpty()) {
+    InitializeTemplate(env, interface_data);
+  }
+
+  return interface_data->templ.Get(env->isolate());
+}
+
+
+}  // namespace testing
+}  // namespace bindings
+}  // namespace cobalt
+
+
diff --git a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_callback_function_interface.h b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_callback_function_interface.h
new file mode 100644
index 0000000..5fcc5da
--- /dev/null
+++ b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_callback_function_interface.h
@@ -0,0 +1,50 @@
+
+// Copyright 2017 Google Inc. All Rights Reserved.
+//
+// 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.
+
+// clang-format off
+
+// This file has been auto-generated by bindings/code_generator_cobalt.py. DO NOT MODIFY!
+// Auto-generated from template: bindings/v8c/templates/interface.h.template
+
+#ifndef V8cCallbackFunctionInterface_h
+#define V8cCallbackFunctionInterface_h
+
+#include "base/hash_tables.h"
+#include "base/lazy_instance.h"
+#include "base/memory/ref_counted.h"
+#include "base/threading/thread_checker.h"
+#include "cobalt/base/polymorphic_downcast.h"
+#include "cobalt/script/wrappable.h"
+#include "cobalt/bindings/testing/callback_function_interface.h"
+
+#include "cobalt/script/v8c/v8c_global_environment.h"
+#include "v8/include/v8.h"
+
+namespace cobalt {
+namespace bindings {
+namespace testing {
+
+class V8cCallbackFunctionInterface {
+ public:
+  static v8::Local<v8::Object> CreateWrapper(script::v8c::V8cGlobalEnvironment* env, const scoped_refptr<script::Wrappable>& wrappable);
+  static v8::Local<v8::FunctionTemplate> CreateTemplate(script::v8c::V8cGlobalEnvironment* env);
+  // TODO: Add |GetInterfaceObject|.
+};
+
+}  // namespace testing
+}  // namespace bindings
+}  // namespace cobalt
+
+#endif  // V8cCallbackFunctionInterface_h
diff --git a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_callback_interface_interface.cc b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_callback_interface_interface.cc
new file mode 100644
index 0000000..683397b
--- /dev/null
+++ b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_callback_interface_interface.cc
@@ -0,0 +1,228 @@
+
+
+// Copyright 2017 Google Inc. All Rights Reserved.
+//
+// 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.
+
+// clang-format off
+
+// This file has been auto-generated by bindings/code_generator_cobalt.py. DO NOT MODIFY!
+// Auto-generated from template: bindings/v8c/templates/interface.cc.template
+
+#include "cobalt/bindings/testing/v8c_callback_interface_interface.h"
+
+#include "base/debug/trace_event.h"
+#include "cobalt/base/polymorphic_downcast.h"
+#include "cobalt/script/global_environment.h"
+#include "cobalt/script/script_value.h"
+#include "cobalt/script/value_handle.h"
+#include "cobalt/bindings/testing/single_operation_interface.h"
+#include "cobalt/bindings/testing/v8c_single_operation_interface.h"
+
+#include "v8c_gen_type_conversion.h"
+
+#include "cobalt/script/callback_interface_traits.h"
+#include "cobalt/script/v8c/callback_function_conversion.h"
+#include "cobalt/script/v8c/conversion_helpers.h"
+#include "cobalt/script/v8c/native_promise.h"
+#include "cobalt/script/v8c/type_traits.h"
+#include "cobalt/script/v8c/v8c_callback_function.h"
+#include "cobalt/script/v8c/v8c_callback_interface_holder.h"
+#include "cobalt/script/v8c/v8c_exception_state.h"
+#include "cobalt/script/v8c/v8c_global_environment.h"
+#include "cobalt/script/v8c/v8c_value_handle.h"
+#include "cobalt/script/v8c/wrapper_private.h"
+#include "v8/include/v8.h"
+
+
+namespace {
+using cobalt::bindings::testing::CallbackInterfaceInterface;
+using cobalt::bindings::testing::V8cCallbackInterfaceInterface;
+using cobalt::bindings::testing::SingleOperationInterface;
+using cobalt::bindings::testing::V8cSingleOperationInterface;
+using cobalt::script::CallbackInterfaceTraits;
+using cobalt::script::GlobalEnvironment;
+using cobalt::script::ScriptValue;
+using cobalt::script::ValueHandle;
+using cobalt::script::ValueHandle;
+using cobalt::script::ValueHandleHolder;
+using cobalt::script::Wrappable;
+
+using cobalt::script::v8c::FromJSValue;
+using cobalt::script::v8c::InterfaceData;
+using cobalt::script::v8c::kConversionFlagClamped;
+using cobalt::script::v8c::kConversionFlagNullable;
+using cobalt::script::v8c::kConversionFlagRestricted;
+using cobalt::script::v8c::kConversionFlagTreatNullAsEmptyString;
+using cobalt::script::v8c::kConversionFlagTreatUndefinedAsEmptyString;
+using cobalt::script::v8c::kNoConversionFlags;
+using cobalt::script::v8c::TypeTraits;
+using cobalt::script::v8c::V8cExceptionState;
+using cobalt::script::v8c::V8cGlobalEnvironment;
+using cobalt::script::v8c::WrapperFactory;
+using cobalt::script::v8c::WrapperPrivate;
+
+v8::Local<v8::Object> DummyFunctor(V8cGlobalEnvironment*, const scoped_refptr<Wrappable>&) {
+  NOTIMPLEMENTED();
+  return {};
+}
+
+}  // namespace
+
+namespace cobalt {
+namespace bindings {
+namespace testing {
+
+
+namespace {
+
+void CallbackInterfaceInterfaceConstructor(const v8::FunctionCallbackInfo<v8::Value>& args) {
+  NOTIMPLEMENTED();
+  if (!args.IsConstructCall()) {
+    // TODO: Probably throw something here...
+    return;
+  }
+
+  DCHECK(args.This()->InternalFieldCount() == 1);
+  args.This()->SetInternalField(0, v8::External::New(args.GetIsolate(), nullptr));
+  args.GetReturnValue().Set(args.This());
+}
+
+
+void v8cGet_callbackAttribute(
+  v8::Local<v8::String> property,
+  const v8::PropertyCallbackInfo<v8::Value>& info)
+{
+  NOTIMPLEMENTED();
+
+  v8::Local<v8::External> external = v8::Local<v8::External>::Cast(info.Holder()->GetInternalField(0));
+  WrapperPrivate* wrapper_private = static_cast<WrapperPrivate*>(external->Value());
+  CallbackInterfaceInterface* impl = static_cast<CallbackInterfaceInterface*>(wrapper_private->wrappable<CallbackInterfaceInterface>());
+
+  v8::Local<v8::Value> result_value;
+}
+
+
+void v8cSet_callbackAttribute(
+  v8::Local<v8::String> property,
+  v8::Local<v8::Value> v8_value,
+  const v8::PropertyCallbackInfo<void>& info)
+{
+  v8::Local<v8::External> external = v8::Local<v8::External>::Cast(info.Holder()->GetInternalField(0));
+  WrapperPrivate* wrapper_private = static_cast<WrapperPrivate*>(external->Value());
+  CallbackInterfaceInterface* impl = static_cast<CallbackInterfaceInterface*>(wrapper_private->wrappable<CallbackInterfaceInterface>());
+
+  TypeTraits<::cobalt::script::CallbackInterfaceTraits<SingleOperationInterface >>::ConversionType conversion_value;
+  V8cExceptionState exception_state{};
+  FromJSValue(info.GetIsolate(), v8_value, (kConversionFlagNullable), &exception_state, &conversion_value);
+  impl->set_callback_attribute(
+    conversion_value
+  );
+}
+
+
+
+void DummyFunction(const v8::FunctionCallbackInfo<v8::Value>& info) {
+  LOG(INFO) << __func__;
+}
+
+void InitializeTemplate(
+  V8cGlobalEnvironment* env,
+  InterfaceData* interface_data) {
+  v8::Isolate* isolate = env->isolate();
+  v8::Local<v8::FunctionTemplate> function_template = v8::FunctionTemplate::New(
+    isolate);
+  function_template->SetClassName(
+    v8::String::NewFromUtf8(isolate, "CallbackInterfaceInterface",
+        v8::NewStringType::kInternalized).ToLocalChecked());
+  v8::Local<v8::ObjectTemplate> instance_template = function_template->InstanceTemplate();
+  instance_template->SetInternalFieldCount(1);
+
+  v8::Local<v8::ObjectTemplate> prototype_template = function_template->PrototypeTemplate();
+  prototype_template->SetInternalFieldCount(1);
+
+  instance_template->SetAccessor(
+    v8::String::NewFromUtf8(isolate, "callbackAttribute",
+                              v8::NewStringType::kInternalized)
+          .ToLocalChecked(),
+    v8cGet_callbackAttribute
+    ,v8cSet_callbackAttribute
+  );
+
+  instance_template->Set(
+      v8::String::NewFromUtf8(
+          isolate,
+          "registerCallback",
+          v8::NewStringType::kInternalized).ToLocalChecked(),
+      v8::FunctionTemplate::New(isolate, DummyFunction)
+  );
+  instance_template->Set(
+      v8::String::NewFromUtf8(
+          isolate,
+          "someOperation",
+          v8::NewStringType::kInternalized).ToLocalChecked(),
+      v8::FunctionTemplate::New(isolate, DummyFunction)
+  );
+
+  interface_data->templ.Set(env->isolate(), function_template);
+}
+
+inline InterfaceData* GetInterfaceData(V8cGlobalEnvironment* env) {
+  const int kInterfaceUniqueId = 7;
+  // By convention, the |V8cGlobalEnvironment| that we are associated with
+  // will hold our |InterfaceData| at index |kInterfaceUniqueId|, as we asked
+  // for it to be there in the first place, and could not have conflicted with
+  // any other interface.
+  return env->GetInterfaceData(kInterfaceUniqueId);
+}
+
+}  // namespace
+
+v8::Local<v8::Object> V8cCallbackInterfaceInterface::CreateWrapper(V8cGlobalEnvironment* env, const scoped_refptr<Wrappable>& wrappable) {
+  v8::Isolate* isolate = env->isolate();
+  v8::Isolate::Scope isolate_scope(isolate);
+  v8::EscapableHandleScope handle_scope(isolate);
+  v8::Local<v8::Context> context = env->context();
+  v8::Context::Scope scope(context);
+
+  InterfaceData* interface_data = GetInterfaceData(env);
+  if (interface_data->templ.IsEmpty()) {
+    InitializeTemplate(env, interface_data);
+  }
+  DCHECK(!interface_data->templ.IsEmpty());
+
+  v8::Local<v8::FunctionTemplate> function_template = interface_data->templ.Get(isolate);
+  DCHECK(function_template->InstanceTemplate()->InternalFieldCount() == 1);
+  v8::Local<v8::Object> object = function_template->InstanceTemplate()->NewInstance(context).ToLocalChecked();
+  DCHECK(object->InternalFieldCount() == 1);
+
+  // |WrapperPrivate|'s lifetime will be managed by V8.
+  new WrapperPrivate(isolate, wrappable, object);
+  return handle_scope.Escape(object);
+}
+
+v8::Local<v8::FunctionTemplate> V8cCallbackInterfaceInterface::CreateTemplate(V8cGlobalEnvironment* env) {
+  InterfaceData* interface_data = GetInterfaceData(env);
+  if (interface_data->templ.IsEmpty()) {
+    InitializeTemplate(env, interface_data);
+  }
+
+  return interface_data->templ.Get(env->isolate());
+}
+
+
+}  // namespace testing
+}  // namespace bindings
+}  // namespace cobalt
+
+
diff --git a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_callback_interface_interface.h b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_callback_interface_interface.h
new file mode 100644
index 0000000..f134c69
--- /dev/null
+++ b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_callback_interface_interface.h
@@ -0,0 +1,50 @@
+
+// Copyright 2017 Google Inc. All Rights Reserved.
+//
+// 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.
+
+// clang-format off
+
+// This file has been auto-generated by bindings/code_generator_cobalt.py. DO NOT MODIFY!
+// Auto-generated from template: bindings/v8c/templates/interface.h.template
+
+#ifndef V8cCallbackInterfaceInterface_h
+#define V8cCallbackInterfaceInterface_h
+
+#include "base/hash_tables.h"
+#include "base/lazy_instance.h"
+#include "base/memory/ref_counted.h"
+#include "base/threading/thread_checker.h"
+#include "cobalt/base/polymorphic_downcast.h"
+#include "cobalt/script/wrappable.h"
+#include "cobalt/bindings/testing/callback_interface_interface.h"
+
+#include "cobalt/script/v8c/v8c_global_environment.h"
+#include "v8/include/v8.h"
+
+namespace cobalt {
+namespace bindings {
+namespace testing {
+
+class V8cCallbackInterfaceInterface {
+ public:
+  static v8::Local<v8::Object> CreateWrapper(script::v8c::V8cGlobalEnvironment* env, const scoped_refptr<script::Wrappable>& wrappable);
+  static v8::Local<v8::FunctionTemplate> CreateTemplate(script::v8c::V8cGlobalEnvironment* env);
+  // TODO: Add |GetInterfaceObject|.
+};
+
+}  // namespace testing
+}  // namespace bindings
+}  // namespace cobalt
+
+#endif  // V8cCallbackInterfaceInterface_h
diff --git a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_conditional_interface.cc b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_conditional_interface.cc
new file mode 100644
index 0000000..94f8e5d
--- /dev/null
+++ b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_conditional_interface.cc
@@ -0,0 +1,275 @@
+
+
+// Copyright 2017 Google Inc. All Rights Reserved.
+//
+// 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.
+
+// clang-format off
+
+// This file has been auto-generated by bindings/code_generator_cobalt.py. DO NOT MODIFY!
+// Auto-generated from template: bindings/v8c/templates/interface.cc.template
+
+#if defined(ENABLE_CONDITIONAL_INTERFACE)
+
+#include "cobalt/bindings/testing/v8c_conditional_interface.h"
+
+#include "base/debug/trace_event.h"
+#include "cobalt/base/polymorphic_downcast.h"
+#include "cobalt/script/global_environment.h"
+#include "cobalt/script/script_value.h"
+#include "cobalt/script/value_handle.h"
+
+#include "v8c_gen_type_conversion.h"
+
+#include "cobalt/script/callback_interface_traits.h"
+#include "cobalt/script/v8c/callback_function_conversion.h"
+#include "cobalt/script/v8c/conversion_helpers.h"
+#include "cobalt/script/v8c/native_promise.h"
+#include "cobalt/script/v8c/type_traits.h"
+#include "cobalt/script/v8c/v8c_callback_function.h"
+#include "cobalt/script/v8c/v8c_callback_interface_holder.h"
+#include "cobalt/script/v8c/v8c_exception_state.h"
+#include "cobalt/script/v8c/v8c_global_environment.h"
+#include "cobalt/script/v8c/v8c_value_handle.h"
+#include "cobalt/script/v8c/wrapper_private.h"
+#include "v8/include/v8.h"
+
+
+namespace {
+using cobalt::bindings::testing::ConditionalInterface;
+using cobalt::bindings::testing::V8cConditionalInterface;
+using cobalt::script::CallbackInterfaceTraits;
+using cobalt::script::GlobalEnvironment;
+using cobalt::script::ScriptValue;
+using cobalt::script::ValueHandle;
+using cobalt::script::ValueHandle;
+using cobalt::script::ValueHandleHolder;
+using cobalt::script::Wrappable;
+
+using cobalt::script::v8c::FromJSValue;
+using cobalt::script::v8c::InterfaceData;
+using cobalt::script::v8c::kConversionFlagClamped;
+using cobalt::script::v8c::kConversionFlagNullable;
+using cobalt::script::v8c::kConversionFlagRestricted;
+using cobalt::script::v8c::kConversionFlagTreatNullAsEmptyString;
+using cobalt::script::v8c::kConversionFlagTreatUndefinedAsEmptyString;
+using cobalt::script::v8c::kNoConversionFlags;
+using cobalt::script::v8c::TypeTraits;
+using cobalt::script::v8c::V8cExceptionState;
+using cobalt::script::v8c::V8cGlobalEnvironment;
+using cobalt::script::v8c::WrapperFactory;
+using cobalt::script::v8c::WrapperPrivate;
+
+v8::Local<v8::Object> DummyFunctor(V8cGlobalEnvironment*, const scoped_refptr<Wrappable>&) {
+  NOTIMPLEMENTED();
+  return {};
+}
+
+}  // namespace
+
+namespace cobalt {
+namespace bindings {
+namespace testing {
+
+
+namespace {
+
+void ConditionalInterfaceConstructor(const v8::FunctionCallbackInfo<v8::Value>& args) {
+  NOTIMPLEMENTED();
+  if (!args.IsConstructCall()) {
+    // TODO: Probably throw something here...
+    return;
+  }
+
+  DCHECK(args.This()->InternalFieldCount() == 1);
+  args.This()->SetInternalField(0, v8::External::New(args.GetIsolate(), nullptr));
+  args.GetReturnValue().Set(args.This());
+}
+
+#if defined(ENABLE_CONDITIONAL_PROPERTY)
+
+void v8cGet_enabledAttribute(
+  v8::Local<v8::String> property,
+  const v8::PropertyCallbackInfo<v8::Value>& info)
+{
+  NOTIMPLEMENTED();
+
+  v8::Local<v8::External> external = v8::Local<v8::External>::Cast(info.Holder()->GetInternalField(0));
+  WrapperPrivate* wrapper_private = static_cast<WrapperPrivate*>(external->Value());
+  ConditionalInterface* impl = static_cast<ConditionalInterface*>(wrapper_private->wrappable<ConditionalInterface>());
+
+  v8::Local<v8::Value> result_value;
+}
+
+
+void v8cSet_enabledAttribute(
+  v8::Local<v8::String> property,
+  v8::Local<v8::Value> v8_value,
+  const v8::PropertyCallbackInfo<void>& info)
+{
+  v8::Local<v8::External> external = v8::Local<v8::External>::Cast(info.Holder()->GetInternalField(0));
+  WrapperPrivate* wrapper_private = static_cast<WrapperPrivate*>(external->Value());
+  ConditionalInterface* impl = static_cast<ConditionalInterface*>(wrapper_private->wrappable<ConditionalInterface>());
+
+  TypeTraits<int32_t>::ConversionType conversion_value;
+  V8cExceptionState exception_state{};
+  FromJSValue(info.GetIsolate(), v8_value, kNoConversionFlags, &exception_state, &conversion_value);
+  impl->set_enabled_attribute(
+    conversion_value
+  );
+}
+
+
+#endif  // ENABLE_CONDITIONAL_PROPERTY
+#if defined(NO_ENABLE_CONDITIONAL_PROPERTY)
+
+void v8cGet_disabledAttribute(
+  v8::Local<v8::String> property,
+  const v8::PropertyCallbackInfo<v8::Value>& info)
+{
+  NOTIMPLEMENTED();
+
+  v8::Local<v8::External> external = v8::Local<v8::External>::Cast(info.Holder()->GetInternalField(0));
+  WrapperPrivate* wrapper_private = static_cast<WrapperPrivate*>(external->Value());
+  ConditionalInterface* impl = static_cast<ConditionalInterface*>(wrapper_private->wrappable<ConditionalInterface>());
+
+  v8::Local<v8::Value> result_value;
+}
+
+
+void v8cSet_disabledAttribute(
+  v8::Local<v8::String> property,
+  v8::Local<v8::Value> v8_value,
+  const v8::PropertyCallbackInfo<void>& info)
+{
+  v8::Local<v8::External> external = v8::Local<v8::External>::Cast(info.Holder()->GetInternalField(0));
+  WrapperPrivate* wrapper_private = static_cast<WrapperPrivate*>(external->Value());
+  ConditionalInterface* impl = static_cast<ConditionalInterface*>(wrapper_private->wrappable<ConditionalInterface>());
+
+  TypeTraits<int32_t>::ConversionType conversion_value;
+  V8cExceptionState exception_state{};
+  FromJSValue(info.GetIsolate(), v8_value, kNoConversionFlags, &exception_state, &conversion_value);
+  impl->set_disabled_attribute(
+    conversion_value
+  );
+}
+
+
+#endif  // NO_ENABLE_CONDITIONAL_PROPERTY
+
+void DummyFunction(const v8::FunctionCallbackInfo<v8::Value>& info) {
+  LOG(INFO) << __func__;
+}
+
+void InitializeTemplate(
+  V8cGlobalEnvironment* env,
+  InterfaceData* interface_data) {
+  v8::Isolate* isolate = env->isolate();
+  v8::Local<v8::FunctionTemplate> function_template = v8::FunctionTemplate::New(
+    isolate);
+  function_template->SetClassName(
+    v8::String::NewFromUtf8(isolate, "ConditionalInterface",
+        v8::NewStringType::kInternalized).ToLocalChecked());
+  v8::Local<v8::ObjectTemplate> instance_template = function_template->InstanceTemplate();
+  instance_template->SetInternalFieldCount(1);
+
+  v8::Local<v8::ObjectTemplate> prototype_template = function_template->PrototypeTemplate();
+  prototype_template->SetInternalFieldCount(1);
+
+#if defined(ENABLE_CONDITIONAL_PROPERTY)
+  instance_template->SetAccessor(
+    v8::String::NewFromUtf8(isolate, "enabledAttribute",
+                              v8::NewStringType::kInternalized)
+          .ToLocalChecked(),
+    v8cGet_enabledAttribute
+    ,v8cSet_enabledAttribute
+  );
+#endif  // ENABLE_CONDITIONAL_PROPERTY
+#if defined(NO_ENABLE_CONDITIONAL_PROPERTY)
+  instance_template->SetAccessor(
+    v8::String::NewFromUtf8(isolate, "disabledAttribute",
+                              v8::NewStringType::kInternalized)
+          .ToLocalChecked(),
+    v8cGet_disabledAttribute
+    ,v8cSet_disabledAttribute
+  );
+#endif  // NO_ENABLE_CONDITIONAL_PROPERTY
+
+  instance_template->Set(
+      v8::String::NewFromUtf8(
+          isolate,
+          "disabledOperation",
+          v8::NewStringType::kInternalized).ToLocalChecked(),
+      v8::FunctionTemplate::New(isolate, DummyFunction)
+  );
+  instance_template->Set(
+      v8::String::NewFromUtf8(
+          isolate,
+          "enabledOperation",
+          v8::NewStringType::kInternalized).ToLocalChecked(),
+      v8::FunctionTemplate::New(isolate, DummyFunction)
+  );
+
+  interface_data->templ.Set(env->isolate(), function_template);
+}
+
+inline InterfaceData* GetInterfaceData(V8cGlobalEnvironment* env) {
+  const int kInterfaceUniqueId = 8;
+  // By convention, the |V8cGlobalEnvironment| that we are associated with
+  // will hold our |InterfaceData| at index |kInterfaceUniqueId|, as we asked
+  // for it to be there in the first place, and could not have conflicted with
+  // any other interface.
+  return env->GetInterfaceData(kInterfaceUniqueId);
+}
+
+}  // namespace
+
+v8::Local<v8::Object> V8cConditionalInterface::CreateWrapper(V8cGlobalEnvironment* env, const scoped_refptr<Wrappable>& wrappable) {
+  v8::Isolate* isolate = env->isolate();
+  v8::Isolate::Scope isolate_scope(isolate);
+  v8::EscapableHandleScope handle_scope(isolate);
+  v8::Local<v8::Context> context = env->context();
+  v8::Context::Scope scope(context);
+
+  InterfaceData* interface_data = GetInterfaceData(env);
+  if (interface_data->templ.IsEmpty()) {
+    InitializeTemplate(env, interface_data);
+  }
+  DCHECK(!interface_data->templ.IsEmpty());
+
+  v8::Local<v8::FunctionTemplate> function_template = interface_data->templ.Get(isolate);
+  DCHECK(function_template->InstanceTemplate()->InternalFieldCount() == 1);
+  v8::Local<v8::Object> object = function_template->InstanceTemplate()->NewInstance(context).ToLocalChecked();
+  DCHECK(object->InternalFieldCount() == 1);
+
+  // |WrapperPrivate|'s lifetime will be managed by V8.
+  new WrapperPrivate(isolate, wrappable, object);
+  return handle_scope.Escape(object);
+}
+
+v8::Local<v8::FunctionTemplate> V8cConditionalInterface::CreateTemplate(V8cGlobalEnvironment* env) {
+  InterfaceData* interface_data = GetInterfaceData(env);
+  if (interface_data->templ.IsEmpty()) {
+    InitializeTemplate(env, interface_data);
+  }
+
+  return interface_data->templ.Get(env->isolate());
+}
+
+
+}  // namespace testing
+}  // namespace bindings
+}  // namespace cobalt
+
+
+#endif  // defined(ENABLE_CONDITIONAL_INTERFACE)
diff --git a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_conditional_interface.h b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_conditional_interface.h
new file mode 100644
index 0000000..0ceed59
--- /dev/null
+++ b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_conditional_interface.h
@@ -0,0 +1,54 @@
+
+// Copyright 2017 Google Inc. All Rights Reserved.
+//
+// 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.
+
+// clang-format off
+
+// This file has been auto-generated by bindings/code_generator_cobalt.py. DO NOT MODIFY!
+// Auto-generated from template: bindings/v8c/templates/interface.h.template
+
+#ifndef V8cConditionalInterface_h
+#define V8cConditionalInterface_h
+
+#if defined(ENABLE_CONDITIONAL_INTERFACE)
+
+#include "base/hash_tables.h"
+#include "base/lazy_instance.h"
+#include "base/memory/ref_counted.h"
+#include "base/threading/thread_checker.h"
+#include "cobalt/base/polymorphic_downcast.h"
+#include "cobalt/script/wrappable.h"
+#include "cobalt/bindings/testing/conditional_interface.h"
+
+#include "cobalt/script/v8c/v8c_global_environment.h"
+#include "v8/include/v8.h"
+
+namespace cobalt {
+namespace bindings {
+namespace testing {
+
+class V8cConditionalInterface {
+ public:
+  static v8::Local<v8::Object> CreateWrapper(script::v8c::V8cGlobalEnvironment* env, const scoped_refptr<script::Wrappable>& wrappable);
+  static v8::Local<v8::FunctionTemplate> CreateTemplate(script::v8c::V8cGlobalEnvironment* env);
+  // TODO: Add |GetInterfaceObject|.
+};
+
+}  // namespace testing
+}  // namespace bindings
+}  // namespace cobalt
+
+#endif  // defined(ENABLE_CONDITIONAL_INTERFACE)
+
+#endif  // V8cConditionalInterface_h
diff --git a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_constants_interface.cc b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_constants_interface.cc
new file mode 100644
index 0000000..8fbc01f
--- /dev/null
+++ b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_constants_interface.cc
@@ -0,0 +1,170 @@
+
+
+// Copyright 2017 Google Inc. All Rights Reserved.
+//
+// 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.
+
+// clang-format off
+
+// This file has been auto-generated by bindings/code_generator_cobalt.py. DO NOT MODIFY!
+// Auto-generated from template: bindings/v8c/templates/interface.cc.template
+
+#include "cobalt/bindings/testing/v8c_constants_interface.h"
+
+#include "base/debug/trace_event.h"
+#include "cobalt/base/polymorphic_downcast.h"
+#include "cobalt/script/global_environment.h"
+#include "cobalt/script/script_value.h"
+#include "cobalt/script/value_handle.h"
+
+#include "v8c_gen_type_conversion.h"
+
+#include "cobalt/script/callback_interface_traits.h"
+#include "cobalt/script/v8c/callback_function_conversion.h"
+#include "cobalt/script/v8c/conversion_helpers.h"
+#include "cobalt/script/v8c/native_promise.h"
+#include "cobalt/script/v8c/type_traits.h"
+#include "cobalt/script/v8c/v8c_callback_function.h"
+#include "cobalt/script/v8c/v8c_callback_interface_holder.h"
+#include "cobalt/script/v8c/v8c_exception_state.h"
+#include "cobalt/script/v8c/v8c_global_environment.h"
+#include "cobalt/script/v8c/v8c_value_handle.h"
+#include "cobalt/script/v8c/wrapper_private.h"
+#include "v8/include/v8.h"
+
+
+namespace {
+using cobalt::bindings::testing::ConstantsInterface;
+using cobalt::bindings::testing::V8cConstantsInterface;
+using cobalt::script::CallbackInterfaceTraits;
+using cobalt::script::GlobalEnvironment;
+using cobalt::script::ScriptValue;
+using cobalt::script::ValueHandle;
+using cobalt::script::ValueHandle;
+using cobalt::script::ValueHandleHolder;
+using cobalt::script::Wrappable;
+
+using cobalt::script::v8c::FromJSValue;
+using cobalt::script::v8c::InterfaceData;
+using cobalt::script::v8c::kConversionFlagClamped;
+using cobalt::script::v8c::kConversionFlagNullable;
+using cobalt::script::v8c::kConversionFlagRestricted;
+using cobalt::script::v8c::kConversionFlagTreatNullAsEmptyString;
+using cobalt::script::v8c::kConversionFlagTreatUndefinedAsEmptyString;
+using cobalt::script::v8c::kNoConversionFlags;
+using cobalt::script::v8c::TypeTraits;
+using cobalt::script::v8c::V8cExceptionState;
+using cobalt::script::v8c::V8cGlobalEnvironment;
+using cobalt::script::v8c::WrapperFactory;
+using cobalt::script::v8c::WrapperPrivate;
+
+v8::Local<v8::Object> DummyFunctor(V8cGlobalEnvironment*, const scoped_refptr<Wrappable>&) {
+  NOTIMPLEMENTED();
+  return {};
+}
+
+}  // namespace
+
+namespace cobalt {
+namespace bindings {
+namespace testing {
+
+
+namespace {
+
+void ConstantsInterfaceConstructor(const v8::FunctionCallbackInfo<v8::Value>& args) {
+  NOTIMPLEMENTED();
+  if (!args.IsConstructCall()) {
+    // TODO: Probably throw something here...
+    return;
+  }
+
+  DCHECK(args.This()->InternalFieldCount() == 1);
+  args.This()->SetInternalField(0, v8::External::New(args.GetIsolate(), nullptr));
+  args.GetReturnValue().Set(args.This());
+}
+
+
+void DummyFunction(const v8::FunctionCallbackInfo<v8::Value>& info) {
+  LOG(INFO) << __func__;
+}
+
+void InitializeTemplate(
+  V8cGlobalEnvironment* env,
+  InterfaceData* interface_data) {
+  v8::Isolate* isolate = env->isolate();
+  v8::Local<v8::FunctionTemplate> function_template = v8::FunctionTemplate::New(
+    isolate);
+  function_template->SetClassName(
+    v8::String::NewFromUtf8(isolate, "ConstantsInterface",
+        v8::NewStringType::kInternalized).ToLocalChecked());
+  v8::Local<v8::ObjectTemplate> instance_template = function_template->InstanceTemplate();
+  instance_template->SetInternalFieldCount(1);
+
+  v8::Local<v8::ObjectTemplate> prototype_template = function_template->PrototypeTemplate();
+  prototype_template->SetInternalFieldCount(1);
+
+
+
+  interface_data->templ.Set(env->isolate(), function_template);
+}
+
+inline InterfaceData* GetInterfaceData(V8cGlobalEnvironment* env) {
+  const int kInterfaceUniqueId = 9;
+  // By convention, the |V8cGlobalEnvironment| that we are associated with
+  // will hold our |InterfaceData| at index |kInterfaceUniqueId|, as we asked
+  // for it to be there in the first place, and could not have conflicted with
+  // any other interface.
+  return env->GetInterfaceData(kInterfaceUniqueId);
+}
+
+}  // namespace
+
+v8::Local<v8::Object> V8cConstantsInterface::CreateWrapper(V8cGlobalEnvironment* env, const scoped_refptr<Wrappable>& wrappable) {
+  v8::Isolate* isolate = env->isolate();
+  v8::Isolate::Scope isolate_scope(isolate);
+  v8::EscapableHandleScope handle_scope(isolate);
+  v8::Local<v8::Context> context = env->context();
+  v8::Context::Scope scope(context);
+
+  InterfaceData* interface_data = GetInterfaceData(env);
+  if (interface_data->templ.IsEmpty()) {
+    InitializeTemplate(env, interface_data);
+  }
+  DCHECK(!interface_data->templ.IsEmpty());
+
+  v8::Local<v8::FunctionTemplate> function_template = interface_data->templ.Get(isolate);
+  DCHECK(function_template->InstanceTemplate()->InternalFieldCount() == 1);
+  v8::Local<v8::Object> object = function_template->InstanceTemplate()->NewInstance(context).ToLocalChecked();
+  DCHECK(object->InternalFieldCount() == 1);
+
+  // |WrapperPrivate|'s lifetime will be managed by V8.
+  new WrapperPrivate(isolate, wrappable, object);
+  return handle_scope.Escape(object);
+}
+
+v8::Local<v8::FunctionTemplate> V8cConstantsInterface::CreateTemplate(V8cGlobalEnvironment* env) {
+  InterfaceData* interface_data = GetInterfaceData(env);
+  if (interface_data->templ.IsEmpty()) {
+    InitializeTemplate(env, interface_data);
+  }
+
+  return interface_data->templ.Get(env->isolate());
+}
+
+
+}  // namespace testing
+}  // namespace bindings
+}  // namespace cobalt
+
+
diff --git a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_constants_interface.h b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_constants_interface.h
new file mode 100644
index 0000000..22e49c0
--- /dev/null
+++ b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_constants_interface.h
@@ -0,0 +1,50 @@
+
+// Copyright 2017 Google Inc. All Rights Reserved.
+//
+// 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.
+
+// clang-format off
+
+// This file has been auto-generated by bindings/code_generator_cobalt.py. DO NOT MODIFY!
+// Auto-generated from template: bindings/v8c/templates/interface.h.template
+
+#ifndef V8cConstantsInterface_h
+#define V8cConstantsInterface_h
+
+#include "base/hash_tables.h"
+#include "base/lazy_instance.h"
+#include "base/memory/ref_counted.h"
+#include "base/threading/thread_checker.h"
+#include "cobalt/base/polymorphic_downcast.h"
+#include "cobalt/script/wrappable.h"
+#include "cobalt/bindings/testing/constants_interface.h"
+
+#include "cobalt/script/v8c/v8c_global_environment.h"
+#include "v8/include/v8.h"
+
+namespace cobalt {
+namespace bindings {
+namespace testing {
+
+class V8cConstantsInterface {
+ public:
+  static v8::Local<v8::Object> CreateWrapper(script::v8c::V8cGlobalEnvironment* env, const scoped_refptr<script::Wrappable>& wrappable);
+  static v8::Local<v8::FunctionTemplate> CreateTemplate(script::v8c::V8cGlobalEnvironment* env);
+  // TODO: Add |GetInterfaceObject|.
+};
+
+}  // namespace testing
+}  // namespace bindings
+}  // namespace cobalt
+
+#endif  // V8cConstantsInterface_h
diff --git a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_constructor_interface.cc b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_constructor_interface.cc
new file mode 100644
index 0000000..8de3e47
--- /dev/null
+++ b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_constructor_interface.cc
@@ -0,0 +1,170 @@
+
+
+// Copyright 2017 Google Inc. All Rights Reserved.
+//
+// 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.
+
+// clang-format off
+
+// This file has been auto-generated by bindings/code_generator_cobalt.py. DO NOT MODIFY!
+// Auto-generated from template: bindings/v8c/templates/interface.cc.template
+
+#include "cobalt/bindings/testing/v8c_constructor_interface.h"
+
+#include "base/debug/trace_event.h"
+#include "cobalt/base/polymorphic_downcast.h"
+#include "cobalt/script/global_environment.h"
+#include "cobalt/script/script_value.h"
+#include "cobalt/script/value_handle.h"
+
+#include "v8c_gen_type_conversion.h"
+
+#include "cobalt/script/callback_interface_traits.h"
+#include "cobalt/script/v8c/callback_function_conversion.h"
+#include "cobalt/script/v8c/conversion_helpers.h"
+#include "cobalt/script/v8c/native_promise.h"
+#include "cobalt/script/v8c/type_traits.h"
+#include "cobalt/script/v8c/v8c_callback_function.h"
+#include "cobalt/script/v8c/v8c_callback_interface_holder.h"
+#include "cobalt/script/v8c/v8c_exception_state.h"
+#include "cobalt/script/v8c/v8c_global_environment.h"
+#include "cobalt/script/v8c/v8c_value_handle.h"
+#include "cobalt/script/v8c/wrapper_private.h"
+#include "v8/include/v8.h"
+
+
+namespace {
+using cobalt::bindings::testing::ConstructorInterface;
+using cobalt::bindings::testing::V8cConstructorInterface;
+using cobalt::script::CallbackInterfaceTraits;
+using cobalt::script::GlobalEnvironment;
+using cobalt::script::ScriptValue;
+using cobalt::script::ValueHandle;
+using cobalt::script::ValueHandle;
+using cobalt::script::ValueHandleHolder;
+using cobalt::script::Wrappable;
+
+using cobalt::script::v8c::FromJSValue;
+using cobalt::script::v8c::InterfaceData;
+using cobalt::script::v8c::kConversionFlagClamped;
+using cobalt::script::v8c::kConversionFlagNullable;
+using cobalt::script::v8c::kConversionFlagRestricted;
+using cobalt::script::v8c::kConversionFlagTreatNullAsEmptyString;
+using cobalt::script::v8c::kConversionFlagTreatUndefinedAsEmptyString;
+using cobalt::script::v8c::kNoConversionFlags;
+using cobalt::script::v8c::TypeTraits;
+using cobalt::script::v8c::V8cExceptionState;
+using cobalt::script::v8c::V8cGlobalEnvironment;
+using cobalt::script::v8c::WrapperFactory;
+using cobalt::script::v8c::WrapperPrivate;
+
+v8::Local<v8::Object> DummyFunctor(V8cGlobalEnvironment*, const scoped_refptr<Wrappable>&) {
+  NOTIMPLEMENTED();
+  return {};
+}
+
+}  // namespace
+
+namespace cobalt {
+namespace bindings {
+namespace testing {
+
+
+namespace {
+
+void ConstructorInterfaceConstructor(const v8::FunctionCallbackInfo<v8::Value>& args) {
+  NOTIMPLEMENTED();
+  if (!args.IsConstructCall()) {
+    // TODO: Probably throw something here...
+    return;
+  }
+
+  DCHECK(args.This()->InternalFieldCount() == 1);
+  args.This()->SetInternalField(0, v8::External::New(args.GetIsolate(), nullptr));
+  args.GetReturnValue().Set(args.This());
+}
+
+
+void DummyFunction(const v8::FunctionCallbackInfo<v8::Value>& info) {
+  LOG(INFO) << __func__;
+}
+
+void InitializeTemplate(
+  V8cGlobalEnvironment* env,
+  InterfaceData* interface_data) {
+  v8::Isolate* isolate = env->isolate();
+  v8::Local<v8::FunctionTemplate> function_template = v8::FunctionTemplate::New(
+    isolate);
+  function_template->SetClassName(
+    v8::String::NewFromUtf8(isolate, "ConstructorInterface",
+        v8::NewStringType::kInternalized).ToLocalChecked());
+  v8::Local<v8::ObjectTemplate> instance_template = function_template->InstanceTemplate();
+  instance_template->SetInternalFieldCount(1);
+
+  v8::Local<v8::ObjectTemplate> prototype_template = function_template->PrototypeTemplate();
+  prototype_template->SetInternalFieldCount(1);
+
+
+
+  interface_data->templ.Set(env->isolate(), function_template);
+}
+
+inline InterfaceData* GetInterfaceData(V8cGlobalEnvironment* env) {
+  const int kInterfaceUniqueId = 10;
+  // By convention, the |V8cGlobalEnvironment| that we are associated with
+  // will hold our |InterfaceData| at index |kInterfaceUniqueId|, as we asked
+  // for it to be there in the first place, and could not have conflicted with
+  // any other interface.
+  return env->GetInterfaceData(kInterfaceUniqueId);
+}
+
+}  // namespace
+
+v8::Local<v8::Object> V8cConstructorInterface::CreateWrapper(V8cGlobalEnvironment* env, const scoped_refptr<Wrappable>& wrappable) {
+  v8::Isolate* isolate = env->isolate();
+  v8::Isolate::Scope isolate_scope(isolate);
+  v8::EscapableHandleScope handle_scope(isolate);
+  v8::Local<v8::Context> context = env->context();
+  v8::Context::Scope scope(context);
+
+  InterfaceData* interface_data = GetInterfaceData(env);
+  if (interface_data->templ.IsEmpty()) {
+    InitializeTemplate(env, interface_data);
+  }
+  DCHECK(!interface_data->templ.IsEmpty());
+
+  v8::Local<v8::FunctionTemplate> function_template = interface_data->templ.Get(isolate);
+  DCHECK(function_template->InstanceTemplate()->InternalFieldCount() == 1);
+  v8::Local<v8::Object> object = function_template->InstanceTemplate()->NewInstance(context).ToLocalChecked();
+  DCHECK(object->InternalFieldCount() == 1);
+
+  // |WrapperPrivate|'s lifetime will be managed by V8.
+  new WrapperPrivate(isolate, wrappable, object);
+  return handle_scope.Escape(object);
+}
+
+v8::Local<v8::FunctionTemplate> V8cConstructorInterface::CreateTemplate(V8cGlobalEnvironment* env) {
+  InterfaceData* interface_data = GetInterfaceData(env);
+  if (interface_data->templ.IsEmpty()) {
+    InitializeTemplate(env, interface_data);
+  }
+
+  return interface_data->templ.Get(env->isolate());
+}
+
+
+}  // namespace testing
+}  // namespace bindings
+}  // namespace cobalt
+
+
diff --git a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_constructor_interface.h b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_constructor_interface.h
new file mode 100644
index 0000000..9f8db95
--- /dev/null
+++ b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_constructor_interface.h
@@ -0,0 +1,50 @@
+
+// Copyright 2017 Google Inc. All Rights Reserved.
+//
+// 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.
+
+// clang-format off
+
+// This file has been auto-generated by bindings/code_generator_cobalt.py. DO NOT MODIFY!
+// Auto-generated from template: bindings/v8c/templates/interface.h.template
+
+#ifndef V8cConstructorInterface_h
+#define V8cConstructorInterface_h
+
+#include "base/hash_tables.h"
+#include "base/lazy_instance.h"
+#include "base/memory/ref_counted.h"
+#include "base/threading/thread_checker.h"
+#include "cobalt/base/polymorphic_downcast.h"
+#include "cobalt/script/wrappable.h"
+#include "cobalt/bindings/testing/constructor_interface.h"
+
+#include "cobalt/script/v8c/v8c_global_environment.h"
+#include "v8/include/v8.h"
+
+namespace cobalt {
+namespace bindings {
+namespace testing {
+
+class V8cConstructorInterface {
+ public:
+  static v8::Local<v8::Object> CreateWrapper(script::v8c::V8cGlobalEnvironment* env, const scoped_refptr<script::Wrappable>& wrappable);
+  static v8::Local<v8::FunctionTemplate> CreateTemplate(script::v8c::V8cGlobalEnvironment* env);
+  // TODO: Add |GetInterfaceObject|.
+};
+
+}  // namespace testing
+}  // namespace bindings
+}  // namespace cobalt
+
+#endif  // V8cConstructorInterface_h
diff --git a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_constructor_with_arguments_interface.cc b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_constructor_with_arguments_interface.cc
new file mode 100644
index 0000000..5885ede
--- /dev/null
+++ b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_constructor_with_arguments_interface.cc
@@ -0,0 +1,233 @@
+
+
+// Copyright 2017 Google Inc. All Rights Reserved.
+//
+// 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.
+
+// clang-format off
+
+// This file has been auto-generated by bindings/code_generator_cobalt.py. DO NOT MODIFY!
+// Auto-generated from template: bindings/v8c/templates/interface.cc.template
+
+#include "cobalt/bindings/testing/v8c_constructor_with_arguments_interface.h"
+
+#include "base/debug/trace_event.h"
+#include "cobalt/base/polymorphic_downcast.h"
+#include "cobalt/script/global_environment.h"
+#include "cobalt/script/script_value.h"
+#include "cobalt/script/value_handle.h"
+
+#include "v8c_gen_type_conversion.h"
+
+#include "cobalt/script/callback_interface_traits.h"
+#include "cobalt/script/v8c/callback_function_conversion.h"
+#include "cobalt/script/v8c/conversion_helpers.h"
+#include "cobalt/script/v8c/native_promise.h"
+#include "cobalt/script/v8c/type_traits.h"
+#include "cobalt/script/v8c/v8c_callback_function.h"
+#include "cobalt/script/v8c/v8c_callback_interface_holder.h"
+#include "cobalt/script/v8c/v8c_exception_state.h"
+#include "cobalt/script/v8c/v8c_global_environment.h"
+#include "cobalt/script/v8c/v8c_value_handle.h"
+#include "cobalt/script/v8c/wrapper_private.h"
+#include "v8/include/v8.h"
+
+
+namespace {
+using cobalt::bindings::testing::ConstructorWithArgumentsInterface;
+using cobalt::bindings::testing::V8cConstructorWithArgumentsInterface;
+using cobalt::script::CallbackInterfaceTraits;
+using cobalt::script::GlobalEnvironment;
+using cobalt::script::ScriptValue;
+using cobalt::script::ValueHandle;
+using cobalt::script::ValueHandle;
+using cobalt::script::ValueHandleHolder;
+using cobalt::script::Wrappable;
+
+using cobalt::script::v8c::FromJSValue;
+using cobalt::script::v8c::InterfaceData;
+using cobalt::script::v8c::kConversionFlagClamped;
+using cobalt::script::v8c::kConversionFlagNullable;
+using cobalt::script::v8c::kConversionFlagRestricted;
+using cobalt::script::v8c::kConversionFlagTreatNullAsEmptyString;
+using cobalt::script::v8c::kConversionFlagTreatUndefinedAsEmptyString;
+using cobalt::script::v8c::kNoConversionFlags;
+using cobalt::script::v8c::TypeTraits;
+using cobalt::script::v8c::V8cExceptionState;
+using cobalt::script::v8c::V8cGlobalEnvironment;
+using cobalt::script::v8c::WrapperFactory;
+using cobalt::script::v8c::WrapperPrivate;
+
+v8::Local<v8::Object> DummyFunctor(V8cGlobalEnvironment*, const scoped_refptr<Wrappable>&) {
+  NOTIMPLEMENTED();
+  return {};
+}
+
+}  // namespace
+
+namespace cobalt {
+namespace bindings {
+namespace testing {
+
+
+namespace {
+
+void ConstructorWithArgumentsInterfaceConstructor(const v8::FunctionCallbackInfo<v8::Value>& args) {
+  NOTIMPLEMENTED();
+  if (!args.IsConstructCall()) {
+    // TODO: Probably throw something here...
+    return;
+  }
+
+  DCHECK(args.This()->InternalFieldCount() == 1);
+  args.This()->SetInternalField(0, v8::External::New(args.GetIsolate(), nullptr));
+  args.GetReturnValue().Set(args.This());
+}
+
+
+void v8cGet_longArg(
+  v8::Local<v8::String> property,
+  const v8::PropertyCallbackInfo<v8::Value>& info)
+{
+  NOTIMPLEMENTED();
+
+  v8::Local<v8::External> external = v8::Local<v8::External>::Cast(info.Holder()->GetInternalField(0));
+  WrapperPrivate* wrapper_private = static_cast<WrapperPrivate*>(external->Value());
+  ConstructorWithArgumentsInterface* impl = static_cast<ConstructorWithArgumentsInterface*>(wrapper_private->wrappable<ConstructorWithArgumentsInterface>());
+
+  v8::Local<v8::Value> result_value;
+}
+
+
+
+void v8cGet_booleanArg(
+  v8::Local<v8::String> property,
+  const v8::PropertyCallbackInfo<v8::Value>& info)
+{
+  NOTIMPLEMENTED();
+
+  v8::Local<v8::External> external = v8::Local<v8::External>::Cast(info.Holder()->GetInternalField(0));
+  WrapperPrivate* wrapper_private = static_cast<WrapperPrivate*>(external->Value());
+  ConstructorWithArgumentsInterface* impl = static_cast<ConstructorWithArgumentsInterface*>(wrapper_private->wrappable<ConstructorWithArgumentsInterface>());
+
+  v8::Local<v8::Value> result_value;
+}
+
+
+
+void v8cGet_stringArg(
+  v8::Local<v8::String> property,
+  const v8::PropertyCallbackInfo<v8::Value>& info)
+{
+  NOTIMPLEMENTED();
+
+  v8::Local<v8::External> external = v8::Local<v8::External>::Cast(info.Holder()->GetInternalField(0));
+  WrapperPrivate* wrapper_private = static_cast<WrapperPrivate*>(external->Value());
+  ConstructorWithArgumentsInterface* impl = static_cast<ConstructorWithArgumentsInterface*>(wrapper_private->wrappable<ConstructorWithArgumentsInterface>());
+
+  v8::Local<v8::Value> result_value;
+}
+
+
+
+void DummyFunction(const v8::FunctionCallbackInfo<v8::Value>& info) {
+  LOG(INFO) << __func__;
+}
+
+void InitializeTemplate(
+  V8cGlobalEnvironment* env,
+  InterfaceData* interface_data) {
+  v8::Isolate* isolate = env->isolate();
+  v8::Local<v8::FunctionTemplate> function_template = v8::FunctionTemplate::New(
+    isolate);
+  function_template->SetClassName(
+    v8::String::NewFromUtf8(isolate, "ConstructorWithArgumentsInterface",
+        v8::NewStringType::kInternalized).ToLocalChecked());
+  v8::Local<v8::ObjectTemplate> instance_template = function_template->InstanceTemplate();
+  instance_template->SetInternalFieldCount(1);
+
+  v8::Local<v8::ObjectTemplate> prototype_template = function_template->PrototypeTemplate();
+  prototype_template->SetInternalFieldCount(1);
+
+  instance_template->SetAccessor(
+    v8::String::NewFromUtf8(isolate, "longArg",
+                              v8::NewStringType::kInternalized)
+          .ToLocalChecked(),
+    v8cGet_longArg
+  );
+  instance_template->SetAccessor(
+    v8::String::NewFromUtf8(isolate, "booleanArg",
+                              v8::NewStringType::kInternalized)
+          .ToLocalChecked(),
+    v8cGet_booleanArg
+  );
+  instance_template->SetAccessor(
+    v8::String::NewFromUtf8(isolate, "stringArg",
+                              v8::NewStringType::kInternalized)
+          .ToLocalChecked(),
+    v8cGet_stringArg
+  );
+
+
+  interface_data->templ.Set(env->isolate(), function_template);
+}
+
+inline InterfaceData* GetInterfaceData(V8cGlobalEnvironment* env) {
+  const int kInterfaceUniqueId = 11;
+  // By convention, the |V8cGlobalEnvironment| that we are associated with
+  // will hold our |InterfaceData| at index |kInterfaceUniqueId|, as we asked
+  // for it to be there in the first place, and could not have conflicted with
+  // any other interface.
+  return env->GetInterfaceData(kInterfaceUniqueId);
+}
+
+}  // namespace
+
+v8::Local<v8::Object> V8cConstructorWithArgumentsInterface::CreateWrapper(V8cGlobalEnvironment* env, const scoped_refptr<Wrappable>& wrappable) {
+  v8::Isolate* isolate = env->isolate();
+  v8::Isolate::Scope isolate_scope(isolate);
+  v8::EscapableHandleScope handle_scope(isolate);
+  v8::Local<v8::Context> context = env->context();
+  v8::Context::Scope scope(context);
+
+  InterfaceData* interface_data = GetInterfaceData(env);
+  if (interface_data->templ.IsEmpty()) {
+    InitializeTemplate(env, interface_data);
+  }
+  DCHECK(!interface_data->templ.IsEmpty());
+
+  v8::Local<v8::FunctionTemplate> function_template = interface_data->templ.Get(isolate);
+  DCHECK(function_template->InstanceTemplate()->InternalFieldCount() == 1);
+  v8::Local<v8::Object> object = function_template->InstanceTemplate()->NewInstance(context).ToLocalChecked();
+  DCHECK(object->InternalFieldCount() == 1);
+
+  // |WrapperPrivate|'s lifetime will be managed by V8.
+  new WrapperPrivate(isolate, wrappable, object);
+  return handle_scope.Escape(object);
+}
+
+v8::Local<v8::FunctionTemplate> V8cConstructorWithArgumentsInterface::CreateTemplate(V8cGlobalEnvironment* env) {
+  InterfaceData* interface_data = GetInterfaceData(env);
+  if (interface_data->templ.IsEmpty()) {
+    InitializeTemplate(env, interface_data);
+  }
+
+  return interface_data->templ.Get(env->isolate());
+}
+
+
+}  // namespace testing
+}  // namespace bindings
+}  // namespace cobalt
+
+
diff --git a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_constructor_with_arguments_interface.h b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_constructor_with_arguments_interface.h
new file mode 100644
index 0000000..1711903
--- /dev/null
+++ b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_constructor_with_arguments_interface.h
@@ -0,0 +1,50 @@
+
+// Copyright 2017 Google Inc. All Rights Reserved.
+//
+// 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.
+
+// clang-format off
+
+// This file has been auto-generated by bindings/code_generator_cobalt.py. DO NOT MODIFY!
+// Auto-generated from template: bindings/v8c/templates/interface.h.template
+
+#ifndef V8cConstructorWithArgumentsInterface_h
+#define V8cConstructorWithArgumentsInterface_h
+
+#include "base/hash_tables.h"
+#include "base/lazy_instance.h"
+#include "base/memory/ref_counted.h"
+#include "base/threading/thread_checker.h"
+#include "cobalt/base/polymorphic_downcast.h"
+#include "cobalt/script/wrappable.h"
+#include "cobalt/bindings/testing/constructor_with_arguments_interface.h"
+
+#include "cobalt/script/v8c/v8c_global_environment.h"
+#include "v8/include/v8.h"
+
+namespace cobalt {
+namespace bindings {
+namespace testing {
+
+class V8cConstructorWithArgumentsInterface {
+ public:
+  static v8::Local<v8::Object> CreateWrapper(script::v8c::V8cGlobalEnvironment* env, const scoped_refptr<script::Wrappable>& wrappable);
+  static v8::Local<v8::FunctionTemplate> CreateTemplate(script::v8c::V8cGlobalEnvironment* env);
+  // TODO: Add |GetInterfaceObject|.
+};
+
+}  // namespace testing
+}  // namespace bindings
+}  // namespace cobalt
+
+#endif  // V8cConstructorWithArgumentsInterface_h
diff --git a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_derived_dictionary.cc b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_derived_dictionary.cc
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_derived_dictionary.cc
diff --git a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_derived_getter_setter_interface.cc b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_derived_getter_setter_interface.cc
new file mode 100644
index 0000000..b05d6cb
--- /dev/null
+++ b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_derived_getter_setter_interface.cc
@@ -0,0 +1,256 @@
+
+
+// Copyright 2017 Google Inc. All Rights Reserved.
+//
+// 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.
+
+// clang-format off
+
+// This file has been auto-generated by bindings/code_generator_cobalt.py. DO NOT MODIFY!
+// Auto-generated from template: bindings/v8c/templates/interface.cc.template
+
+#include "cobalt/bindings/testing/v8c_derived_getter_setter_interface.h"
+
+#include "base/debug/trace_event.h"
+#include "cobalt/base/polymorphic_downcast.h"
+#include "cobalt/script/global_environment.h"
+#include "cobalt/script/script_value.h"
+#include "cobalt/script/value_handle.h"
+#include "cobalt/bindings/testing/named_indexed_getter_interface.h"
+#include "cobalt/bindings/testing/v8c_named_indexed_getter_interface.h"
+
+#include "v8c_gen_type_conversion.h"
+
+#include "cobalt/script/callback_interface_traits.h"
+#include "cobalt/script/v8c/callback_function_conversion.h"
+#include "cobalt/script/v8c/conversion_helpers.h"
+#include "cobalt/script/v8c/native_promise.h"
+#include "cobalt/script/v8c/type_traits.h"
+#include "cobalt/script/v8c/v8c_callback_function.h"
+#include "cobalt/script/v8c/v8c_callback_interface_holder.h"
+#include "cobalt/script/v8c/v8c_exception_state.h"
+#include "cobalt/script/v8c/v8c_global_environment.h"
+#include "cobalt/script/v8c/v8c_value_handle.h"
+#include "cobalt/script/v8c/wrapper_private.h"
+#include "v8/include/v8.h"
+
+
+namespace {
+using cobalt::bindings::testing::DerivedGetterSetterInterface;
+using cobalt::bindings::testing::V8cDerivedGetterSetterInterface;
+using cobalt::bindings::testing::NamedIndexedGetterInterface;
+using cobalt::bindings::testing::V8cNamedIndexedGetterInterface;
+using cobalt::script::CallbackInterfaceTraits;
+using cobalt::script::GlobalEnvironment;
+using cobalt::script::ScriptValue;
+using cobalt::script::ValueHandle;
+using cobalt::script::ValueHandle;
+using cobalt::script::ValueHandleHolder;
+using cobalt::script::Wrappable;
+
+using cobalt::script::v8c::FromJSValue;
+using cobalt::script::v8c::InterfaceData;
+using cobalt::script::v8c::kConversionFlagClamped;
+using cobalt::script::v8c::kConversionFlagNullable;
+using cobalt::script::v8c::kConversionFlagRestricted;
+using cobalt::script::v8c::kConversionFlagTreatNullAsEmptyString;
+using cobalt::script::v8c::kConversionFlagTreatUndefinedAsEmptyString;
+using cobalt::script::v8c::kNoConversionFlags;
+using cobalt::script::v8c::TypeTraits;
+using cobalt::script::v8c::V8cExceptionState;
+using cobalt::script::v8c::V8cGlobalEnvironment;
+using cobalt::script::v8c::WrapperFactory;
+using cobalt::script::v8c::WrapperPrivate;
+
+v8::Local<v8::Object> DummyFunctor(V8cGlobalEnvironment*, const scoped_refptr<Wrappable>&) {
+  NOTIMPLEMENTED();
+  return {};
+}
+
+}  // namespace
+
+namespace cobalt {
+namespace bindings {
+namespace testing {
+
+
+namespace {
+
+void DerivedGetterSetterInterfaceConstructor(const v8::FunctionCallbackInfo<v8::Value>& args) {
+  NOTIMPLEMENTED();
+  if (!args.IsConstructCall()) {
+    // TODO: Probably throw something here...
+    return;
+  }
+
+  DCHECK(args.This()->InternalFieldCount() == 1);
+  args.This()->SetInternalField(0, v8::External::New(args.GetIsolate(), nullptr));
+  args.GetReturnValue().Set(args.This());
+}
+
+
+void v8cGet_length(
+  v8::Local<v8::String> property,
+  const v8::PropertyCallbackInfo<v8::Value>& info)
+{
+  NOTIMPLEMENTED();
+
+  v8::Local<v8::External> external = v8::Local<v8::External>::Cast(info.Holder()->GetInternalField(0));
+  WrapperPrivate* wrapper_private = static_cast<WrapperPrivate*>(external->Value());
+  DerivedGetterSetterInterface* impl = static_cast<DerivedGetterSetterInterface*>(wrapper_private->wrappable<DerivedGetterSetterInterface>());
+
+  v8::Local<v8::Value> result_value;
+}
+
+
+
+void v8cGet_propertyOnDerivedClass(
+  v8::Local<v8::String> property,
+  const v8::PropertyCallbackInfo<v8::Value>& info)
+{
+  NOTIMPLEMENTED();
+
+  v8::Local<v8::External> external = v8::Local<v8::External>::Cast(info.Holder()->GetInternalField(0));
+  WrapperPrivate* wrapper_private = static_cast<WrapperPrivate*>(external->Value());
+  DerivedGetterSetterInterface* impl = static_cast<DerivedGetterSetterInterface*>(wrapper_private->wrappable<DerivedGetterSetterInterface>());
+
+  v8::Local<v8::Value> result_value;
+}
+
+
+void v8cSet_propertyOnDerivedClass(
+  v8::Local<v8::String> property,
+  v8::Local<v8::Value> v8_value,
+  const v8::PropertyCallbackInfo<void>& info)
+{
+  v8::Local<v8::External> external = v8::Local<v8::External>::Cast(info.Holder()->GetInternalField(0));
+  WrapperPrivate* wrapper_private = static_cast<WrapperPrivate*>(external->Value());
+  DerivedGetterSetterInterface* impl = static_cast<DerivedGetterSetterInterface*>(wrapper_private->wrappable<DerivedGetterSetterInterface>());
+
+  TypeTraits<bool>::ConversionType conversion_value;
+  V8cExceptionState exception_state{};
+  FromJSValue(info.GetIsolate(), v8_value, kNoConversionFlags, &exception_state, &conversion_value);
+  impl->set_property_on_derived_class(
+    conversion_value
+  );
+}
+
+
+
+void DummyFunction(const v8::FunctionCallbackInfo<v8::Value>& info) {
+  LOG(INFO) << __func__;
+}
+
+void InitializeTemplate(
+  V8cGlobalEnvironment* env,
+  InterfaceData* interface_data) {
+  v8::Isolate* isolate = env->isolate();
+  v8::Local<v8::FunctionTemplate> function_template = v8::FunctionTemplate::New(
+    isolate);
+  function_template->SetClassName(
+    v8::String::NewFromUtf8(isolate, "DerivedGetterSetterInterface",
+        v8::NewStringType::kInternalized).ToLocalChecked());
+  v8::Local<v8::ObjectTemplate> instance_template = function_template->InstanceTemplate();
+  instance_template->SetInternalFieldCount(1);
+
+  v8::Local<v8::ObjectTemplate> prototype_template = function_template->PrototypeTemplate();
+  prototype_template->SetInternalFieldCount(1);
+
+  instance_template->SetAccessor(
+    v8::String::NewFromUtf8(isolate, "length",
+                              v8::NewStringType::kInternalized)
+          .ToLocalChecked(),
+    v8cGet_length
+  );
+  instance_template->SetAccessor(
+    v8::String::NewFromUtf8(isolate, "propertyOnDerivedClass",
+                              v8::NewStringType::kInternalized)
+          .ToLocalChecked(),
+    v8cGet_propertyOnDerivedClass
+    ,v8cSet_propertyOnDerivedClass
+  );
+
+  instance_template->Set(
+      v8::String::NewFromUtf8(
+          isolate,
+          "derivedIndexedGetter",
+          v8::NewStringType::kInternalized).ToLocalChecked(),
+      v8::FunctionTemplate::New(isolate, DummyFunction)
+  );
+  instance_template->Set(
+      v8::String::NewFromUtf8(
+          isolate,
+          "derivedIndexedSetter",
+          v8::NewStringType::kInternalized).ToLocalChecked(),
+      v8::FunctionTemplate::New(isolate, DummyFunction)
+  );
+  instance_template->Set(
+      v8::String::NewFromUtf8(
+          isolate,
+          "operationOnDerivedClass",
+          v8::NewStringType::kInternalized).ToLocalChecked(),
+      v8::FunctionTemplate::New(isolate, DummyFunction)
+  );
+
+  interface_data->templ.Set(env->isolate(), function_template);
+}
+
+inline InterfaceData* GetInterfaceData(V8cGlobalEnvironment* env) {
+  const int kInterfaceUniqueId = 14;
+  // By convention, the |V8cGlobalEnvironment| that we are associated with
+  // will hold our |InterfaceData| at index |kInterfaceUniqueId|, as we asked
+  // for it to be there in the first place, and could not have conflicted with
+  // any other interface.
+  return env->GetInterfaceData(kInterfaceUniqueId);
+}
+
+}  // namespace
+
+v8::Local<v8::Object> V8cDerivedGetterSetterInterface::CreateWrapper(V8cGlobalEnvironment* env, const scoped_refptr<Wrappable>& wrappable) {
+  v8::Isolate* isolate = env->isolate();
+  v8::Isolate::Scope isolate_scope(isolate);
+  v8::EscapableHandleScope handle_scope(isolate);
+  v8::Local<v8::Context> context = env->context();
+  v8::Context::Scope scope(context);
+
+  InterfaceData* interface_data = GetInterfaceData(env);
+  if (interface_data->templ.IsEmpty()) {
+    InitializeTemplate(env, interface_data);
+  }
+  DCHECK(!interface_data->templ.IsEmpty());
+
+  v8::Local<v8::FunctionTemplate> function_template = interface_data->templ.Get(isolate);
+  DCHECK(function_template->InstanceTemplate()->InternalFieldCount() == 1);
+  v8::Local<v8::Object> object = function_template->InstanceTemplate()->NewInstance(context).ToLocalChecked();
+  DCHECK(object->InternalFieldCount() == 1);
+
+  // |WrapperPrivate|'s lifetime will be managed by V8.
+  new WrapperPrivate(isolate, wrappable, object);
+  return handle_scope.Escape(object);
+}
+
+v8::Local<v8::FunctionTemplate> V8cDerivedGetterSetterInterface::CreateTemplate(V8cGlobalEnvironment* env) {
+  InterfaceData* interface_data = GetInterfaceData(env);
+  if (interface_data->templ.IsEmpty()) {
+    InitializeTemplate(env, interface_data);
+  }
+
+  return interface_data->templ.Get(env->isolate());
+}
+
+
+}  // namespace testing
+}  // namespace bindings
+}  // namespace cobalt
+
+
diff --git a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_derived_getter_setter_interface.h b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_derived_getter_setter_interface.h
new file mode 100644
index 0000000..0bd0509
--- /dev/null
+++ b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_derived_getter_setter_interface.h
@@ -0,0 +1,51 @@
+
+// Copyright 2017 Google Inc. All Rights Reserved.
+//
+// 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.
+
+// clang-format off
+
+// This file has been auto-generated by bindings/code_generator_cobalt.py. DO NOT MODIFY!
+// Auto-generated from template: bindings/v8c/templates/interface.h.template
+
+#ifndef V8cDerivedGetterSetterInterface_h
+#define V8cDerivedGetterSetterInterface_h
+
+#include "base/hash_tables.h"
+#include "base/lazy_instance.h"
+#include "base/memory/ref_counted.h"
+#include "base/threading/thread_checker.h"
+#include "cobalt/base/polymorphic_downcast.h"
+#include "cobalt/script/wrappable.h"
+#include "cobalt/bindings/testing/derived_getter_setter_interface.h"
+#include "cobalt/bindings/testing/v8c_named_indexed_getter_interface.h"
+
+#include "cobalt/script/v8c/v8c_global_environment.h"
+#include "v8/include/v8.h"
+
+namespace cobalt {
+namespace bindings {
+namespace testing {
+
+class V8cDerivedGetterSetterInterface {
+ public:
+  static v8::Local<v8::Object> CreateWrapper(script::v8c::V8cGlobalEnvironment* env, const scoped_refptr<script::Wrappable>& wrappable);
+  static v8::Local<v8::FunctionTemplate> CreateTemplate(script::v8c::V8cGlobalEnvironment* env);
+  // TODO: Add |GetInterfaceObject|.
+};
+
+}  // namespace testing
+}  // namespace bindings
+}  // namespace cobalt
+
+#endif  // V8cDerivedGetterSetterInterface_h
diff --git a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_derived_interface.cc b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_derived_interface.cc
new file mode 100644
index 0000000..b43c1dc
--- /dev/null
+++ b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_derived_interface.cc
@@ -0,0 +1,202 @@
+
+
+// Copyright 2017 Google Inc. All Rights Reserved.
+//
+// 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.
+
+// clang-format off
+
+// This file has been auto-generated by bindings/code_generator_cobalt.py. DO NOT MODIFY!
+// Auto-generated from template: bindings/v8c/templates/interface.cc.template
+
+#include "cobalt/bindings/testing/v8c_derived_interface.h"
+
+#include "base/debug/trace_event.h"
+#include "cobalt/base/polymorphic_downcast.h"
+#include "cobalt/script/global_environment.h"
+#include "cobalt/script/script_value.h"
+#include "cobalt/script/value_handle.h"
+#include "cobalt/bindings/testing/base_interface.h"
+#include "cobalt/bindings/testing/v8c_base_interface.h"
+
+#include "v8c_gen_type_conversion.h"
+
+#include "cobalt/script/callback_interface_traits.h"
+#include "cobalt/script/v8c/callback_function_conversion.h"
+#include "cobalt/script/v8c/conversion_helpers.h"
+#include "cobalt/script/v8c/native_promise.h"
+#include "cobalt/script/v8c/type_traits.h"
+#include "cobalt/script/v8c/v8c_callback_function.h"
+#include "cobalt/script/v8c/v8c_callback_interface_holder.h"
+#include "cobalt/script/v8c/v8c_exception_state.h"
+#include "cobalt/script/v8c/v8c_global_environment.h"
+#include "cobalt/script/v8c/v8c_value_handle.h"
+#include "cobalt/script/v8c/wrapper_private.h"
+#include "v8/include/v8.h"
+
+
+namespace {
+using cobalt::bindings::testing::DerivedInterface;
+using cobalt::bindings::testing::V8cDerivedInterface;
+using cobalt::bindings::testing::BaseInterface;
+using cobalt::bindings::testing::V8cBaseInterface;
+using cobalt::script::CallbackInterfaceTraits;
+using cobalt::script::GlobalEnvironment;
+using cobalt::script::ScriptValue;
+using cobalt::script::ValueHandle;
+using cobalt::script::ValueHandle;
+using cobalt::script::ValueHandleHolder;
+using cobalt::script::Wrappable;
+
+using cobalt::script::v8c::FromJSValue;
+using cobalt::script::v8c::InterfaceData;
+using cobalt::script::v8c::kConversionFlagClamped;
+using cobalt::script::v8c::kConversionFlagNullable;
+using cobalt::script::v8c::kConversionFlagRestricted;
+using cobalt::script::v8c::kConversionFlagTreatNullAsEmptyString;
+using cobalt::script::v8c::kConversionFlagTreatUndefinedAsEmptyString;
+using cobalt::script::v8c::kNoConversionFlags;
+using cobalt::script::v8c::TypeTraits;
+using cobalt::script::v8c::V8cExceptionState;
+using cobalt::script::v8c::V8cGlobalEnvironment;
+using cobalt::script::v8c::WrapperFactory;
+using cobalt::script::v8c::WrapperPrivate;
+
+v8::Local<v8::Object> DummyFunctor(V8cGlobalEnvironment*, const scoped_refptr<Wrappable>&) {
+  NOTIMPLEMENTED();
+  return {};
+}
+
+}  // namespace
+
+namespace cobalt {
+namespace bindings {
+namespace testing {
+
+
+namespace {
+
+void DerivedInterfaceConstructor(const v8::FunctionCallbackInfo<v8::Value>& args) {
+  NOTIMPLEMENTED();
+  if (!args.IsConstructCall()) {
+    // TODO: Probably throw something here...
+    return;
+  }
+
+  DCHECK(args.This()->InternalFieldCount() == 1);
+  args.This()->SetInternalField(0, v8::External::New(args.GetIsolate(), nullptr));
+  args.GetReturnValue().Set(args.This());
+}
+
+
+void v8cGet_derivedAttribute(
+  v8::Local<v8::String> property,
+  const v8::PropertyCallbackInfo<v8::Value>& info)
+{
+  NOTIMPLEMENTED();
+
+  v8::Local<v8::External> external = v8::Local<v8::External>::Cast(info.Holder()->GetInternalField(0));
+  WrapperPrivate* wrapper_private = static_cast<WrapperPrivate*>(external->Value());
+  DerivedInterface* impl = static_cast<DerivedInterface*>(wrapper_private->wrappable<DerivedInterface>());
+
+  v8::Local<v8::Value> result_value;
+}
+
+
+
+void DummyFunction(const v8::FunctionCallbackInfo<v8::Value>& info) {
+  LOG(INFO) << __func__;
+}
+
+void InitializeTemplate(
+  V8cGlobalEnvironment* env,
+  InterfaceData* interface_data) {
+  v8::Isolate* isolate = env->isolate();
+  v8::Local<v8::FunctionTemplate> function_template = v8::FunctionTemplate::New(
+    isolate);
+  function_template->SetClassName(
+    v8::String::NewFromUtf8(isolate, "DerivedInterface",
+        v8::NewStringType::kInternalized).ToLocalChecked());
+  v8::Local<v8::ObjectTemplate> instance_template = function_template->InstanceTemplate();
+  instance_template->SetInternalFieldCount(1);
+
+  v8::Local<v8::ObjectTemplate> prototype_template = function_template->PrototypeTemplate();
+  prototype_template->SetInternalFieldCount(1);
+
+  instance_template->SetAccessor(
+    v8::String::NewFromUtf8(isolate, "derivedAttribute",
+                              v8::NewStringType::kInternalized)
+          .ToLocalChecked(),
+    v8cGet_derivedAttribute
+  );
+
+  instance_template->Set(
+      v8::String::NewFromUtf8(
+          isolate,
+          "derivedOperation",
+          v8::NewStringType::kInternalized).ToLocalChecked(),
+      v8::FunctionTemplate::New(isolate, DummyFunction)
+  );
+
+  interface_data->templ.Set(env->isolate(), function_template);
+}
+
+inline InterfaceData* GetInterfaceData(V8cGlobalEnvironment* env) {
+  const int kInterfaceUniqueId = 15;
+  // By convention, the |V8cGlobalEnvironment| that we are associated with
+  // will hold our |InterfaceData| at index |kInterfaceUniqueId|, as we asked
+  // for it to be there in the first place, and could not have conflicted with
+  // any other interface.
+  return env->GetInterfaceData(kInterfaceUniqueId);
+}
+
+}  // namespace
+
+v8::Local<v8::Object> V8cDerivedInterface::CreateWrapper(V8cGlobalEnvironment* env, const scoped_refptr<Wrappable>& wrappable) {
+  v8::Isolate* isolate = env->isolate();
+  v8::Isolate::Scope isolate_scope(isolate);
+  v8::EscapableHandleScope handle_scope(isolate);
+  v8::Local<v8::Context> context = env->context();
+  v8::Context::Scope scope(context);
+
+  InterfaceData* interface_data = GetInterfaceData(env);
+  if (interface_data->templ.IsEmpty()) {
+    InitializeTemplate(env, interface_data);
+  }
+  DCHECK(!interface_data->templ.IsEmpty());
+
+  v8::Local<v8::FunctionTemplate> function_template = interface_data->templ.Get(isolate);
+  DCHECK(function_template->InstanceTemplate()->InternalFieldCount() == 1);
+  v8::Local<v8::Object> object = function_template->InstanceTemplate()->NewInstance(context).ToLocalChecked();
+  DCHECK(object->InternalFieldCount() == 1);
+
+  // |WrapperPrivate|'s lifetime will be managed by V8.
+  new WrapperPrivate(isolate, wrappable, object);
+  return handle_scope.Escape(object);
+}
+
+v8::Local<v8::FunctionTemplate> V8cDerivedInterface::CreateTemplate(V8cGlobalEnvironment* env) {
+  InterfaceData* interface_data = GetInterfaceData(env);
+  if (interface_data->templ.IsEmpty()) {
+    InitializeTemplate(env, interface_data);
+  }
+
+  return interface_data->templ.Get(env->isolate());
+}
+
+
+}  // namespace testing
+}  // namespace bindings
+}  // namespace cobalt
+
+
diff --git a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_derived_interface.h b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_derived_interface.h
new file mode 100644
index 0000000..245aa39
--- /dev/null
+++ b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_derived_interface.h
@@ -0,0 +1,51 @@
+
+// Copyright 2017 Google Inc. All Rights Reserved.
+//
+// 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.
+
+// clang-format off
+
+// This file has been auto-generated by bindings/code_generator_cobalt.py. DO NOT MODIFY!
+// Auto-generated from template: bindings/v8c/templates/interface.h.template
+
+#ifndef V8cDerivedInterface_h
+#define V8cDerivedInterface_h
+
+#include "base/hash_tables.h"
+#include "base/lazy_instance.h"
+#include "base/memory/ref_counted.h"
+#include "base/threading/thread_checker.h"
+#include "cobalt/base/polymorphic_downcast.h"
+#include "cobalt/script/wrappable.h"
+#include "cobalt/bindings/testing/derived_interface.h"
+#include "cobalt/bindings/testing/v8c_base_interface.h"
+
+#include "cobalt/script/v8c/v8c_global_environment.h"
+#include "v8/include/v8.h"
+
+namespace cobalt {
+namespace bindings {
+namespace testing {
+
+class V8cDerivedInterface {
+ public:
+  static v8::Local<v8::Object> CreateWrapper(script::v8c::V8cGlobalEnvironment* env, const scoped_refptr<script::Wrappable>& wrappable);
+  static v8::Local<v8::FunctionTemplate> CreateTemplate(script::v8c::V8cGlobalEnvironment* env);
+  // TODO: Add |GetInterfaceObject|.
+};
+
+}  // namespace testing
+}  // namespace bindings
+}  // namespace cobalt
+
+#endif  // V8cDerivedInterface_h
diff --git a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_dictionary_interface.cc b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_dictionary_interface.cc
new file mode 100644
index 0000000..705a8f0
--- /dev/null
+++ b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_dictionary_interface.cc
@@ -0,0 +1,237 @@
+
+
+// Copyright 2017 Google Inc. All Rights Reserved.
+//
+// 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.
+
+// clang-format off
+
+// This file has been auto-generated by bindings/code_generator_cobalt.py. DO NOT MODIFY!
+// Auto-generated from template: bindings/v8c/templates/interface.cc.template
+
+#include "cobalt/bindings/testing/v8c_dictionary_interface.h"
+
+#include "base/debug/trace_event.h"
+#include "cobalt/base/polymorphic_downcast.h"
+#include "cobalt/script/global_environment.h"
+#include "cobalt/script/script_value.h"
+#include "cobalt/script/value_handle.h"
+#include "cobalt/bindings/testing/derived_dictionary.h"
+#include "cobalt/bindings/testing/dictionary_with_dictionary_member.h"
+#include "cobalt/bindings/testing/test_dictionary.h"
+
+#include "v8c_gen_type_conversion.h"
+
+#include "cobalt/script/callback_interface_traits.h"
+#include "cobalt/script/v8c/callback_function_conversion.h"
+#include "cobalt/script/v8c/conversion_helpers.h"
+#include "cobalt/script/v8c/native_promise.h"
+#include "cobalt/script/v8c/type_traits.h"
+#include "cobalt/script/v8c/v8c_callback_function.h"
+#include "cobalt/script/v8c/v8c_callback_interface_holder.h"
+#include "cobalt/script/v8c/v8c_exception_state.h"
+#include "cobalt/script/v8c/v8c_global_environment.h"
+#include "cobalt/script/v8c/v8c_value_handle.h"
+#include "cobalt/script/v8c/wrapper_private.h"
+#include "v8/include/v8.h"
+
+
+namespace {
+using cobalt::bindings::testing::DictionaryInterface;
+using cobalt::bindings::testing::V8cDictionaryInterface;
+using cobalt::bindings::testing::DerivedDictionary;
+using cobalt::bindings::testing::DictionaryWithDictionaryMember;
+using cobalt::bindings::testing::TestDictionary;
+using cobalt::script::CallbackInterfaceTraits;
+using cobalt::script::GlobalEnvironment;
+using cobalt::script::ScriptValue;
+using cobalt::script::ValueHandle;
+using cobalt::script::ValueHandle;
+using cobalt::script::ValueHandleHolder;
+using cobalt::script::Wrappable;
+
+using cobalt::script::v8c::FromJSValue;
+using cobalt::script::v8c::InterfaceData;
+using cobalt::script::v8c::kConversionFlagClamped;
+using cobalt::script::v8c::kConversionFlagNullable;
+using cobalt::script::v8c::kConversionFlagRestricted;
+using cobalt::script::v8c::kConversionFlagTreatNullAsEmptyString;
+using cobalt::script::v8c::kConversionFlagTreatUndefinedAsEmptyString;
+using cobalt::script::v8c::kNoConversionFlags;
+using cobalt::script::v8c::TypeTraits;
+using cobalt::script::v8c::V8cExceptionState;
+using cobalt::script::v8c::V8cGlobalEnvironment;
+using cobalt::script::v8c::WrapperFactory;
+using cobalt::script::v8c::WrapperPrivate;
+
+v8::Local<v8::Object> DummyFunctor(V8cGlobalEnvironment*, const scoped_refptr<Wrappable>&) {
+  NOTIMPLEMENTED();
+  return {};
+}
+
+}  // namespace
+
+namespace cobalt {
+namespace bindings {
+namespace testing {
+
+
+namespace {
+
+void DictionaryInterfaceConstructor(const v8::FunctionCallbackInfo<v8::Value>& args) {
+  NOTIMPLEMENTED();
+  if (!args.IsConstructCall()) {
+    // TODO: Probably throw something here...
+    return;
+  }
+
+  DCHECK(args.This()->InternalFieldCount() == 1);
+  args.This()->SetInternalField(0, v8::External::New(args.GetIsolate(), nullptr));
+  args.GetReturnValue().Set(args.This());
+}
+
+
+void v8cGet_dictionarySequence(
+  v8::Local<v8::String> property,
+  const v8::PropertyCallbackInfo<v8::Value>& info)
+{
+  NOTIMPLEMENTED();
+
+  v8::Local<v8::External> external = v8::Local<v8::External>::Cast(info.Holder()->GetInternalField(0));
+  WrapperPrivate* wrapper_private = static_cast<WrapperPrivate*>(external->Value());
+  DictionaryInterface* impl = static_cast<DictionaryInterface*>(wrapper_private->wrappable<DictionaryInterface>());
+
+  v8::Local<v8::Value> result_value;
+}
+
+
+void v8cSet_dictionarySequence(
+  v8::Local<v8::String> property,
+  v8::Local<v8::Value> v8_value,
+  const v8::PropertyCallbackInfo<void>& info)
+{
+  v8::Local<v8::External> external = v8::Local<v8::External>::Cast(info.Holder()->GetInternalField(0));
+  WrapperPrivate* wrapper_private = static_cast<WrapperPrivate*>(external->Value());
+  DictionaryInterface* impl = static_cast<DictionaryInterface*>(wrapper_private->wrappable<DictionaryInterface>());
+
+  TypeTraits<::cobalt::script::Sequence< TestDictionary >>::ConversionType conversion_value;
+  V8cExceptionState exception_state{};
+  FromJSValue(info.GetIsolate(), v8_value, kNoConversionFlags, &exception_state, &conversion_value);
+  impl->set_dictionary_sequence(
+    conversion_value
+  );
+}
+
+
+
+void DummyFunction(const v8::FunctionCallbackInfo<v8::Value>& info) {
+  LOG(INFO) << __func__;
+}
+
+void InitializeTemplate(
+  V8cGlobalEnvironment* env,
+  InterfaceData* interface_data) {
+  v8::Isolate* isolate = env->isolate();
+  v8::Local<v8::FunctionTemplate> function_template = v8::FunctionTemplate::New(
+    isolate);
+  function_template->SetClassName(
+    v8::String::NewFromUtf8(isolate, "DictionaryInterface",
+        v8::NewStringType::kInternalized).ToLocalChecked());
+  v8::Local<v8::ObjectTemplate> instance_template = function_template->InstanceTemplate();
+  instance_template->SetInternalFieldCount(1);
+
+  v8::Local<v8::ObjectTemplate> prototype_template = function_template->PrototypeTemplate();
+  prototype_template->SetInternalFieldCount(1);
+
+  instance_template->SetAccessor(
+    v8::String::NewFromUtf8(isolate, "dictionarySequence",
+                              v8::NewStringType::kInternalized)
+          .ToLocalChecked(),
+    v8cGet_dictionarySequence
+    ,v8cSet_dictionarySequence
+  );
+
+  instance_template->Set(
+      v8::String::NewFromUtf8(
+          isolate,
+          "derivedDictionaryOperation",
+          v8::NewStringType::kInternalized).ToLocalChecked(),
+      v8::FunctionTemplate::New(isolate, DummyFunction)
+  );
+  instance_template->Set(
+      v8::String::NewFromUtf8(
+          isolate,
+          "dictionaryOperation",
+          v8::NewStringType::kInternalized).ToLocalChecked(),
+      v8::FunctionTemplate::New(isolate, DummyFunction)
+  );
+  instance_template->Set(
+      v8::String::NewFromUtf8(
+          isolate,
+          "testOperation",
+          v8::NewStringType::kInternalized).ToLocalChecked(),
+      v8::FunctionTemplate::New(isolate, DummyFunction)
+  );
+
+  interface_data->templ.Set(env->isolate(), function_template);
+}
+
+inline InterfaceData* GetInterfaceData(V8cGlobalEnvironment* env) {
+  const int kInterfaceUniqueId = 16;
+  // By convention, the |V8cGlobalEnvironment| that we are associated with
+  // will hold our |InterfaceData| at index |kInterfaceUniqueId|, as we asked
+  // for it to be there in the first place, and could not have conflicted with
+  // any other interface.
+  return env->GetInterfaceData(kInterfaceUniqueId);
+}
+
+}  // namespace
+
+v8::Local<v8::Object> V8cDictionaryInterface::CreateWrapper(V8cGlobalEnvironment* env, const scoped_refptr<Wrappable>& wrappable) {
+  v8::Isolate* isolate = env->isolate();
+  v8::Isolate::Scope isolate_scope(isolate);
+  v8::EscapableHandleScope handle_scope(isolate);
+  v8::Local<v8::Context> context = env->context();
+  v8::Context::Scope scope(context);
+
+  InterfaceData* interface_data = GetInterfaceData(env);
+  if (interface_data->templ.IsEmpty()) {
+    InitializeTemplate(env, interface_data);
+  }
+  DCHECK(!interface_data->templ.IsEmpty());
+
+  v8::Local<v8::FunctionTemplate> function_template = interface_data->templ.Get(isolate);
+  DCHECK(function_template->InstanceTemplate()->InternalFieldCount() == 1);
+  v8::Local<v8::Object> object = function_template->InstanceTemplate()->NewInstance(context).ToLocalChecked();
+  DCHECK(object->InternalFieldCount() == 1);
+
+  // |WrapperPrivate|'s lifetime will be managed by V8.
+  new WrapperPrivate(isolate, wrappable, object);
+  return handle_scope.Escape(object);
+}
+
+v8::Local<v8::FunctionTemplate> V8cDictionaryInterface::CreateTemplate(V8cGlobalEnvironment* env) {
+  InterfaceData* interface_data = GetInterfaceData(env);
+  if (interface_data->templ.IsEmpty()) {
+    InitializeTemplate(env, interface_data);
+  }
+
+  return interface_data->templ.Get(env->isolate());
+}
+
+
+}  // namespace testing
+}  // namespace bindings
+}  // namespace cobalt
+
+
diff --git a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_dictionary_interface.h b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_dictionary_interface.h
new file mode 100644
index 0000000..0c81e13
--- /dev/null
+++ b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_dictionary_interface.h
@@ -0,0 +1,50 @@
+
+// Copyright 2017 Google Inc. All Rights Reserved.
+//
+// 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.
+
+// clang-format off
+
+// This file has been auto-generated by bindings/code_generator_cobalt.py. DO NOT MODIFY!
+// Auto-generated from template: bindings/v8c/templates/interface.h.template
+
+#ifndef V8cDictionaryInterface_h
+#define V8cDictionaryInterface_h
+
+#include "base/hash_tables.h"
+#include "base/lazy_instance.h"
+#include "base/memory/ref_counted.h"
+#include "base/threading/thread_checker.h"
+#include "cobalt/base/polymorphic_downcast.h"
+#include "cobalt/script/wrappable.h"
+#include "cobalt/bindings/testing/dictionary_interface.h"
+
+#include "cobalt/script/v8c/v8c_global_environment.h"
+#include "v8/include/v8.h"
+
+namespace cobalt {
+namespace bindings {
+namespace testing {
+
+class V8cDictionaryInterface {
+ public:
+  static v8::Local<v8::Object> CreateWrapper(script::v8c::V8cGlobalEnvironment* env, const scoped_refptr<script::Wrappable>& wrappable);
+  static v8::Local<v8::FunctionTemplate> CreateTemplate(script::v8c::V8cGlobalEnvironment* env);
+  // TODO: Add |GetInterfaceObject|.
+};
+
+}  // namespace testing
+}  // namespace bindings
+}  // namespace cobalt
+
+#endif  // V8cDictionaryInterface_h
diff --git a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_dictionary_with_dictionary_member.cc b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_dictionary_with_dictionary_member.cc
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_dictionary_with_dictionary_member.cc
diff --git a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_disabled_interface.cc b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_disabled_interface.cc
new file mode 100644
index 0000000..987f284
--- /dev/null
+++ b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_disabled_interface.cc
@@ -0,0 +1,220 @@
+
+
+// Copyright 2017 Google Inc. All Rights Reserved.
+//
+// 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.
+
+// clang-format off
+
+// This file has been auto-generated by bindings/code_generator_cobalt.py. DO NOT MODIFY!
+// Auto-generated from template: bindings/v8c/templates/interface.cc.template
+
+#if defined(NO_ENABLE_CONDITIONAL_INTERFACE)
+
+#include "cobalt/bindings/testing/v8c_disabled_interface.h"
+
+#include "base/debug/trace_event.h"
+#include "cobalt/base/polymorphic_downcast.h"
+#include "cobalt/script/global_environment.h"
+#include "cobalt/script/script_value.h"
+#include "cobalt/script/value_handle.h"
+
+#include "v8c_gen_type_conversion.h"
+
+#include "cobalt/script/callback_interface_traits.h"
+#include "cobalt/script/v8c/callback_function_conversion.h"
+#include "cobalt/script/v8c/conversion_helpers.h"
+#include "cobalt/script/v8c/native_promise.h"
+#include "cobalt/script/v8c/type_traits.h"
+#include "cobalt/script/v8c/v8c_callback_function.h"
+#include "cobalt/script/v8c/v8c_callback_interface_holder.h"
+#include "cobalt/script/v8c/v8c_exception_state.h"
+#include "cobalt/script/v8c/v8c_global_environment.h"
+#include "cobalt/script/v8c/v8c_value_handle.h"
+#include "cobalt/script/v8c/wrapper_private.h"
+#include "v8/include/v8.h"
+
+
+namespace {
+using cobalt::bindings::testing::DisabledInterface;
+using cobalt::bindings::testing::V8cDisabledInterface;
+using cobalt::script::CallbackInterfaceTraits;
+using cobalt::script::GlobalEnvironment;
+using cobalt::script::ScriptValue;
+using cobalt::script::ValueHandle;
+using cobalt::script::ValueHandle;
+using cobalt::script::ValueHandleHolder;
+using cobalt::script::Wrappable;
+
+using cobalt::script::v8c::FromJSValue;
+using cobalt::script::v8c::InterfaceData;
+using cobalt::script::v8c::kConversionFlagClamped;
+using cobalt::script::v8c::kConversionFlagNullable;
+using cobalt::script::v8c::kConversionFlagRestricted;
+using cobalt::script::v8c::kConversionFlagTreatNullAsEmptyString;
+using cobalt::script::v8c::kConversionFlagTreatUndefinedAsEmptyString;
+using cobalt::script::v8c::kNoConversionFlags;
+using cobalt::script::v8c::TypeTraits;
+using cobalt::script::v8c::V8cExceptionState;
+using cobalt::script::v8c::V8cGlobalEnvironment;
+using cobalt::script::v8c::WrapperFactory;
+using cobalt::script::v8c::WrapperPrivate;
+
+v8::Local<v8::Object> DummyFunctor(V8cGlobalEnvironment*, const scoped_refptr<Wrappable>&) {
+  NOTIMPLEMENTED();
+  return {};
+}
+
+}  // namespace
+
+namespace cobalt {
+namespace bindings {
+namespace testing {
+
+
+namespace {
+
+void DisabledInterfaceConstructor(const v8::FunctionCallbackInfo<v8::Value>& args) {
+  NOTIMPLEMENTED();
+  if (!args.IsConstructCall()) {
+    // TODO: Probably throw something here...
+    return;
+  }
+
+  DCHECK(args.This()->InternalFieldCount() == 1);
+  args.This()->SetInternalField(0, v8::External::New(args.GetIsolate(), nullptr));
+  args.GetReturnValue().Set(args.This());
+}
+
+
+void v8cGet_disabledProperty(
+  v8::Local<v8::String> property,
+  const v8::PropertyCallbackInfo<v8::Value>& info)
+{
+  NOTIMPLEMENTED();
+
+  v8::Local<v8::External> external = v8::Local<v8::External>::Cast(info.Holder()->GetInternalField(0));
+  WrapperPrivate* wrapper_private = static_cast<WrapperPrivate*>(external->Value());
+  DisabledInterface* impl = static_cast<DisabledInterface*>(wrapper_private->wrappable<DisabledInterface>());
+
+  v8::Local<v8::Value> result_value;
+}
+
+
+void v8cSet_disabledProperty(
+  v8::Local<v8::String> property,
+  v8::Local<v8::Value> v8_value,
+  const v8::PropertyCallbackInfo<void>& info)
+{
+  v8::Local<v8::External> external = v8::Local<v8::External>::Cast(info.Holder()->GetInternalField(0));
+  WrapperPrivate* wrapper_private = static_cast<WrapperPrivate*>(external->Value());
+  DisabledInterface* impl = static_cast<DisabledInterface*>(wrapper_private->wrappable<DisabledInterface>());
+
+  TypeTraits<int32_t>::ConversionType conversion_value;
+  V8cExceptionState exception_state{};
+  FromJSValue(info.GetIsolate(), v8_value, kNoConversionFlags, &exception_state, &conversion_value);
+  impl->set_disabled_property(
+    conversion_value
+  );
+}
+
+
+
+void DummyFunction(const v8::FunctionCallbackInfo<v8::Value>& info) {
+  LOG(INFO) << __func__;
+}
+
+void InitializeTemplate(
+  V8cGlobalEnvironment* env,
+  InterfaceData* interface_data) {
+  v8::Isolate* isolate = env->isolate();
+  v8::Local<v8::FunctionTemplate> function_template = v8::FunctionTemplate::New(
+    isolate);
+  function_template->SetClassName(
+    v8::String::NewFromUtf8(isolate, "DisabledInterface",
+        v8::NewStringType::kInternalized).ToLocalChecked());
+  v8::Local<v8::ObjectTemplate> instance_template = function_template->InstanceTemplate();
+  instance_template->SetInternalFieldCount(1);
+
+  v8::Local<v8::ObjectTemplate> prototype_template = function_template->PrototypeTemplate();
+  prototype_template->SetInternalFieldCount(1);
+
+  instance_template->SetAccessor(
+    v8::String::NewFromUtf8(isolate, "disabledProperty",
+                              v8::NewStringType::kInternalized)
+          .ToLocalChecked(),
+    v8cGet_disabledProperty
+    ,v8cSet_disabledProperty
+  );
+
+  instance_template->Set(
+      v8::String::NewFromUtf8(
+          isolate,
+          "disabledFunction",
+          v8::NewStringType::kInternalized).ToLocalChecked(),
+      v8::FunctionTemplate::New(isolate, DummyFunction)
+  );
+
+  interface_data->templ.Set(env->isolate(), function_template);
+}
+
+inline InterfaceData* GetInterfaceData(V8cGlobalEnvironment* env) {
+  const int kInterfaceUniqueId = 18;
+  // By convention, the |V8cGlobalEnvironment| that we are associated with
+  // will hold our |InterfaceData| at index |kInterfaceUniqueId|, as we asked
+  // for it to be there in the first place, and could not have conflicted with
+  // any other interface.
+  return env->GetInterfaceData(kInterfaceUniqueId);
+}
+
+}  // namespace
+
+v8::Local<v8::Object> V8cDisabledInterface::CreateWrapper(V8cGlobalEnvironment* env, const scoped_refptr<Wrappable>& wrappable) {
+  v8::Isolate* isolate = env->isolate();
+  v8::Isolate::Scope isolate_scope(isolate);
+  v8::EscapableHandleScope handle_scope(isolate);
+  v8::Local<v8::Context> context = env->context();
+  v8::Context::Scope scope(context);
+
+  InterfaceData* interface_data = GetInterfaceData(env);
+  if (interface_data->templ.IsEmpty()) {
+    InitializeTemplate(env, interface_data);
+  }
+  DCHECK(!interface_data->templ.IsEmpty());
+
+  v8::Local<v8::FunctionTemplate> function_template = interface_data->templ.Get(isolate);
+  DCHECK(function_template->InstanceTemplate()->InternalFieldCount() == 1);
+  v8::Local<v8::Object> object = function_template->InstanceTemplate()->NewInstance(context).ToLocalChecked();
+  DCHECK(object->InternalFieldCount() == 1);
+
+  // |WrapperPrivate|'s lifetime will be managed by V8.
+  new WrapperPrivate(isolate, wrappable, object);
+  return handle_scope.Escape(object);
+}
+
+v8::Local<v8::FunctionTemplate> V8cDisabledInterface::CreateTemplate(V8cGlobalEnvironment* env) {
+  InterfaceData* interface_data = GetInterfaceData(env);
+  if (interface_data->templ.IsEmpty()) {
+    InitializeTemplate(env, interface_data);
+  }
+
+  return interface_data->templ.Get(env->isolate());
+}
+
+
+}  // namespace testing
+}  // namespace bindings
+}  // namespace cobalt
+
+
+#endif  // defined(NO_ENABLE_CONDITIONAL_INTERFACE)
diff --git a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_disabled_interface.h b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_disabled_interface.h
new file mode 100644
index 0000000..fb3b5fc
--- /dev/null
+++ b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_disabled_interface.h
@@ -0,0 +1,54 @@
+
+// Copyright 2017 Google Inc. All Rights Reserved.
+//
+// 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.
+
+// clang-format off
+
+// This file has been auto-generated by bindings/code_generator_cobalt.py. DO NOT MODIFY!
+// Auto-generated from template: bindings/v8c/templates/interface.h.template
+
+#ifndef V8cDisabledInterface_h
+#define V8cDisabledInterface_h
+
+#if defined(NO_ENABLE_CONDITIONAL_INTERFACE)
+
+#include "base/hash_tables.h"
+#include "base/lazy_instance.h"
+#include "base/memory/ref_counted.h"
+#include "base/threading/thread_checker.h"
+#include "cobalt/base/polymorphic_downcast.h"
+#include "cobalt/script/wrappable.h"
+#include "cobalt/bindings/testing/disabled_interface.h"
+
+#include "cobalt/script/v8c/v8c_global_environment.h"
+#include "v8/include/v8.h"
+
+namespace cobalt {
+namespace bindings {
+namespace testing {
+
+class V8cDisabledInterface {
+ public:
+  static v8::Local<v8::Object> CreateWrapper(script::v8c::V8cGlobalEnvironment* env, const scoped_refptr<script::Wrappable>& wrappable);
+  static v8::Local<v8::FunctionTemplate> CreateTemplate(script::v8c::V8cGlobalEnvironment* env);
+  // TODO: Add |GetInterfaceObject|.
+};
+
+}  // namespace testing
+}  // namespace bindings
+}  // namespace cobalt
+
+#endif  // defined(NO_ENABLE_CONDITIONAL_INTERFACE)
+
+#endif  // V8cDisabledInterface_h
diff --git a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_dom_string_test_interface.cc b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_dom_string_test_interface.cc
new file mode 100644
index 0000000..0a89b27
--- /dev/null
+++ b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_dom_string_test_interface.cc
@@ -0,0 +1,372 @@
+
+
+// Copyright 2017 Google Inc. All Rights Reserved.
+//
+// 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.
+
+// clang-format off
+
+// This file has been auto-generated by bindings/code_generator_cobalt.py. DO NOT MODIFY!
+// Auto-generated from template: bindings/v8c/templates/interface.cc.template
+
+#include "cobalt/bindings/testing/v8c_dom_string_test_interface.h"
+
+#include "base/debug/trace_event.h"
+#include "cobalt/base/polymorphic_downcast.h"
+#include "cobalt/script/global_environment.h"
+#include "cobalt/script/script_value.h"
+#include "cobalt/script/value_handle.h"
+
+#include "v8c_gen_type_conversion.h"
+
+#include "cobalt/script/callback_interface_traits.h"
+#include "cobalt/script/v8c/callback_function_conversion.h"
+#include "cobalt/script/v8c/conversion_helpers.h"
+#include "cobalt/script/v8c/native_promise.h"
+#include "cobalt/script/v8c/type_traits.h"
+#include "cobalt/script/v8c/v8c_callback_function.h"
+#include "cobalt/script/v8c/v8c_callback_interface_holder.h"
+#include "cobalt/script/v8c/v8c_exception_state.h"
+#include "cobalt/script/v8c/v8c_global_environment.h"
+#include "cobalt/script/v8c/v8c_value_handle.h"
+#include "cobalt/script/v8c/wrapper_private.h"
+#include "v8/include/v8.h"
+
+
+namespace {
+using cobalt::bindings::testing::DOMStringTestInterface;
+using cobalt::bindings::testing::V8cDOMStringTestInterface;
+using cobalt::script::CallbackInterfaceTraits;
+using cobalt::script::GlobalEnvironment;
+using cobalt::script::ScriptValue;
+using cobalt::script::ValueHandle;
+using cobalt::script::ValueHandle;
+using cobalt::script::ValueHandleHolder;
+using cobalt::script::Wrappable;
+
+using cobalt::script::v8c::FromJSValue;
+using cobalt::script::v8c::InterfaceData;
+using cobalt::script::v8c::kConversionFlagClamped;
+using cobalt::script::v8c::kConversionFlagNullable;
+using cobalt::script::v8c::kConversionFlagRestricted;
+using cobalt::script::v8c::kConversionFlagTreatNullAsEmptyString;
+using cobalt::script::v8c::kConversionFlagTreatUndefinedAsEmptyString;
+using cobalt::script::v8c::kNoConversionFlags;
+using cobalt::script::v8c::TypeTraits;
+using cobalt::script::v8c::V8cExceptionState;
+using cobalt::script::v8c::V8cGlobalEnvironment;
+using cobalt::script::v8c::WrapperFactory;
+using cobalt::script::v8c::WrapperPrivate;
+
+v8::Local<v8::Object> DummyFunctor(V8cGlobalEnvironment*, const scoped_refptr<Wrappable>&) {
+  NOTIMPLEMENTED();
+  return {};
+}
+
+}  // namespace
+
+namespace cobalt {
+namespace bindings {
+namespace testing {
+
+
+namespace {
+
+void DOMStringTestInterfaceConstructor(const v8::FunctionCallbackInfo<v8::Value>& args) {
+  NOTIMPLEMENTED();
+  if (!args.IsConstructCall()) {
+    // TODO: Probably throw something here...
+    return;
+  }
+
+  DCHECK(args.This()->InternalFieldCount() == 1);
+  args.This()->SetInternalField(0, v8::External::New(args.GetIsolate(), nullptr));
+  args.GetReturnValue().Set(args.This());
+}
+
+
+void v8cGet_property(
+  v8::Local<v8::String> property,
+  const v8::PropertyCallbackInfo<v8::Value>& info)
+{
+  NOTIMPLEMENTED();
+
+  v8::Local<v8::External> external = v8::Local<v8::External>::Cast(info.Holder()->GetInternalField(0));
+  WrapperPrivate* wrapper_private = static_cast<WrapperPrivate*>(external->Value());
+  DOMStringTestInterface* impl = static_cast<DOMStringTestInterface*>(wrapper_private->wrappable<DOMStringTestInterface>());
+
+  v8::Local<v8::Value> result_value;
+}
+
+
+void v8cSet_property(
+  v8::Local<v8::String> property,
+  v8::Local<v8::Value> v8_value,
+  const v8::PropertyCallbackInfo<void>& info)
+{
+  v8::Local<v8::External> external = v8::Local<v8::External>::Cast(info.Holder()->GetInternalField(0));
+  WrapperPrivate* wrapper_private = static_cast<WrapperPrivate*>(external->Value());
+  DOMStringTestInterface* impl = static_cast<DOMStringTestInterface*>(wrapper_private->wrappable<DOMStringTestInterface>());
+
+  TypeTraits<std::string>::ConversionType conversion_value;
+  V8cExceptionState exception_state{};
+  FromJSValue(info.GetIsolate(), v8_value, kNoConversionFlags, &exception_state, &conversion_value);
+  impl->set_property(
+    conversion_value
+  );
+}
+
+
+
+void v8cGet_readOnlyProperty(
+  v8::Local<v8::String> property,
+  const v8::PropertyCallbackInfo<v8::Value>& info)
+{
+  NOTIMPLEMENTED();
+
+  v8::Local<v8::External> external = v8::Local<v8::External>::Cast(info.Holder()->GetInternalField(0));
+  WrapperPrivate* wrapper_private = static_cast<WrapperPrivate*>(external->Value());
+  DOMStringTestInterface* impl = static_cast<DOMStringTestInterface*>(wrapper_private->wrappable<DOMStringTestInterface>());
+
+  v8::Local<v8::Value> result_value;
+}
+
+
+
+void v8cGet_readOnlyTokenProperty(
+  v8::Local<v8::String> property,
+  const v8::PropertyCallbackInfo<v8::Value>& info)
+{
+  NOTIMPLEMENTED();
+
+  v8::Local<v8::External> external = v8::Local<v8::External>::Cast(info.Holder()->GetInternalField(0));
+  WrapperPrivate* wrapper_private = static_cast<WrapperPrivate*>(external->Value());
+  DOMStringTestInterface* impl = static_cast<DOMStringTestInterface*>(wrapper_private->wrappable<DOMStringTestInterface>());
+
+  v8::Local<v8::Value> result_value;
+}
+
+
+
+void v8cGet_nullIsEmptyProperty(
+  v8::Local<v8::String> property,
+  const v8::PropertyCallbackInfo<v8::Value>& info)
+{
+  NOTIMPLEMENTED();
+
+  v8::Local<v8::External> external = v8::Local<v8::External>::Cast(info.Holder()->GetInternalField(0));
+  WrapperPrivate* wrapper_private = static_cast<WrapperPrivate*>(external->Value());
+  DOMStringTestInterface* impl = static_cast<DOMStringTestInterface*>(wrapper_private->wrappable<DOMStringTestInterface>());
+
+  v8::Local<v8::Value> result_value;
+}
+
+
+void v8cSet_nullIsEmptyProperty(
+  v8::Local<v8::String> property,
+  v8::Local<v8::Value> v8_value,
+  const v8::PropertyCallbackInfo<void>& info)
+{
+  v8::Local<v8::External> external = v8::Local<v8::External>::Cast(info.Holder()->GetInternalField(0));
+  WrapperPrivate* wrapper_private = static_cast<WrapperPrivate*>(external->Value());
+  DOMStringTestInterface* impl = static_cast<DOMStringTestInterface*>(wrapper_private->wrappable<DOMStringTestInterface>());
+
+  TypeTraits<std::string>::ConversionType conversion_value;
+  V8cExceptionState exception_state{};
+  FromJSValue(info.GetIsolate(), v8_value, (kConversionFlagTreatNullAsEmptyString), &exception_state, &conversion_value);
+  impl->set_null_is_empty_property(
+    conversion_value
+  );
+}
+
+
+
+void v8cGet_undefinedIsEmptyProperty(
+  v8::Local<v8::String> property,
+  const v8::PropertyCallbackInfo<v8::Value>& info)
+{
+  NOTIMPLEMENTED();
+
+  v8::Local<v8::External> external = v8::Local<v8::External>::Cast(info.Holder()->GetInternalField(0));
+  WrapperPrivate* wrapper_private = static_cast<WrapperPrivate*>(external->Value());
+  DOMStringTestInterface* impl = static_cast<DOMStringTestInterface*>(wrapper_private->wrappable<DOMStringTestInterface>());
+
+  v8::Local<v8::Value> result_value;
+}
+
+
+void v8cSet_undefinedIsEmptyProperty(
+  v8::Local<v8::String> property,
+  v8::Local<v8::Value> v8_value,
+  const v8::PropertyCallbackInfo<void>& info)
+{
+  v8::Local<v8::External> external = v8::Local<v8::External>::Cast(info.Holder()->GetInternalField(0));
+  WrapperPrivate* wrapper_private = static_cast<WrapperPrivate*>(external->Value());
+  DOMStringTestInterface* impl = static_cast<DOMStringTestInterface*>(wrapper_private->wrappable<DOMStringTestInterface>());
+
+  TypeTraits<std::string>::ConversionType conversion_value;
+  V8cExceptionState exception_state{};
+  FromJSValue(info.GetIsolate(), v8_value, (kConversionFlagTreatUndefinedAsEmptyString), &exception_state, &conversion_value);
+  impl->set_undefined_is_empty_property(
+    conversion_value
+  );
+}
+
+
+
+void v8cGet_nullableUndefinedIsEmptyProperty(
+  v8::Local<v8::String> property,
+  const v8::PropertyCallbackInfo<v8::Value>& info)
+{
+  NOTIMPLEMENTED();
+
+  v8::Local<v8::External> external = v8::Local<v8::External>::Cast(info.Holder()->GetInternalField(0));
+  WrapperPrivate* wrapper_private = static_cast<WrapperPrivate*>(external->Value());
+  DOMStringTestInterface* impl = static_cast<DOMStringTestInterface*>(wrapper_private->wrappable<DOMStringTestInterface>());
+
+  v8::Local<v8::Value> result_value;
+}
+
+
+void v8cSet_nullableUndefinedIsEmptyProperty(
+  v8::Local<v8::String> property,
+  v8::Local<v8::Value> v8_value,
+  const v8::PropertyCallbackInfo<void>& info)
+{
+  v8::Local<v8::External> external = v8::Local<v8::External>::Cast(info.Holder()->GetInternalField(0));
+  WrapperPrivate* wrapper_private = static_cast<WrapperPrivate*>(external->Value());
+  DOMStringTestInterface* impl = static_cast<DOMStringTestInterface*>(wrapper_private->wrappable<DOMStringTestInterface>());
+
+  TypeTraits<base::optional<std::string >>::ConversionType conversion_value;
+  V8cExceptionState exception_state{};
+  FromJSValue(info.GetIsolate(), v8_value, (kConversionFlagNullable | kConversionFlagTreatUndefinedAsEmptyString), &exception_state, &conversion_value);
+  impl->set_nullable_undefined_is_empty_property(
+    conversion_value
+  );
+}
+
+
+
+void DummyFunction(const v8::FunctionCallbackInfo<v8::Value>& info) {
+  LOG(INFO) << __func__;
+}
+
+void InitializeTemplate(
+  V8cGlobalEnvironment* env,
+  InterfaceData* interface_data) {
+  v8::Isolate* isolate = env->isolate();
+  v8::Local<v8::FunctionTemplate> function_template = v8::FunctionTemplate::New(
+    isolate);
+  function_template->SetClassName(
+    v8::String::NewFromUtf8(isolate, "DOMStringTestInterface",
+        v8::NewStringType::kInternalized).ToLocalChecked());
+  v8::Local<v8::ObjectTemplate> instance_template = function_template->InstanceTemplate();
+  instance_template->SetInternalFieldCount(1);
+
+  v8::Local<v8::ObjectTemplate> prototype_template = function_template->PrototypeTemplate();
+  prototype_template->SetInternalFieldCount(1);
+
+  instance_template->SetAccessor(
+    v8::String::NewFromUtf8(isolate, "property",
+                              v8::NewStringType::kInternalized)
+          .ToLocalChecked(),
+    v8cGet_property
+    ,v8cSet_property
+  );
+  instance_template->SetAccessor(
+    v8::String::NewFromUtf8(isolate, "readOnlyProperty",
+                              v8::NewStringType::kInternalized)
+          .ToLocalChecked(),
+    v8cGet_readOnlyProperty
+  );
+  instance_template->SetAccessor(
+    v8::String::NewFromUtf8(isolate, "readOnlyTokenProperty",
+                              v8::NewStringType::kInternalized)
+          .ToLocalChecked(),
+    v8cGet_readOnlyTokenProperty
+  );
+  instance_template->SetAccessor(
+    v8::String::NewFromUtf8(isolate, "nullIsEmptyProperty",
+                              v8::NewStringType::kInternalized)
+          .ToLocalChecked(),
+    v8cGet_nullIsEmptyProperty
+    ,v8cSet_nullIsEmptyProperty
+  );
+  instance_template->SetAccessor(
+    v8::String::NewFromUtf8(isolate, "undefinedIsEmptyProperty",
+                              v8::NewStringType::kInternalized)
+          .ToLocalChecked(),
+    v8cGet_undefinedIsEmptyProperty
+    ,v8cSet_undefinedIsEmptyProperty
+  );
+  instance_template->SetAccessor(
+    v8::String::NewFromUtf8(isolate, "nullableUndefinedIsEmptyProperty",
+                              v8::NewStringType::kInternalized)
+          .ToLocalChecked(),
+    v8cGet_nullableUndefinedIsEmptyProperty
+    ,v8cSet_nullableUndefinedIsEmptyProperty
+  );
+
+
+  interface_data->templ.Set(env->isolate(), function_template);
+}
+
+inline InterfaceData* GetInterfaceData(V8cGlobalEnvironment* env) {
+  const int kInterfaceUniqueId = 12;
+  // By convention, the |V8cGlobalEnvironment| that we are associated with
+  // will hold our |InterfaceData| at index |kInterfaceUniqueId|, as we asked
+  // for it to be there in the first place, and could not have conflicted with
+  // any other interface.
+  return env->GetInterfaceData(kInterfaceUniqueId);
+}
+
+}  // namespace
+
+v8::Local<v8::Object> V8cDOMStringTestInterface::CreateWrapper(V8cGlobalEnvironment* env, const scoped_refptr<Wrappable>& wrappable) {
+  v8::Isolate* isolate = env->isolate();
+  v8::Isolate::Scope isolate_scope(isolate);
+  v8::EscapableHandleScope handle_scope(isolate);
+  v8::Local<v8::Context> context = env->context();
+  v8::Context::Scope scope(context);
+
+  InterfaceData* interface_data = GetInterfaceData(env);
+  if (interface_data->templ.IsEmpty()) {
+    InitializeTemplate(env, interface_data);
+  }
+  DCHECK(!interface_data->templ.IsEmpty());
+
+  v8::Local<v8::FunctionTemplate> function_template = interface_data->templ.Get(isolate);
+  DCHECK(function_template->InstanceTemplate()->InternalFieldCount() == 1);
+  v8::Local<v8::Object> object = function_template->InstanceTemplate()->NewInstance(context).ToLocalChecked();
+  DCHECK(object->InternalFieldCount() == 1);
+
+  // |WrapperPrivate|'s lifetime will be managed by V8.
+  new WrapperPrivate(isolate, wrappable, object);
+  return handle_scope.Escape(object);
+}
+
+v8::Local<v8::FunctionTemplate> V8cDOMStringTestInterface::CreateTemplate(V8cGlobalEnvironment* env) {
+  InterfaceData* interface_data = GetInterfaceData(env);
+  if (interface_data->templ.IsEmpty()) {
+    InitializeTemplate(env, interface_data);
+  }
+
+  return interface_data->templ.Get(env->isolate());
+}
+
+
+}  // namespace testing
+}  // namespace bindings
+}  // namespace cobalt
+
+
diff --git a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_dom_string_test_interface.h b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_dom_string_test_interface.h
new file mode 100644
index 0000000..edb0d77
--- /dev/null
+++ b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_dom_string_test_interface.h
@@ -0,0 +1,50 @@
+
+// Copyright 2017 Google Inc. All Rights Reserved.
+//
+// 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.
+
+// clang-format off
+
+// This file has been auto-generated by bindings/code_generator_cobalt.py. DO NOT MODIFY!
+// Auto-generated from template: bindings/v8c/templates/interface.h.template
+
+#ifndef V8cDOMStringTestInterface_h
+#define V8cDOMStringTestInterface_h
+
+#include "base/hash_tables.h"
+#include "base/lazy_instance.h"
+#include "base/memory/ref_counted.h"
+#include "base/threading/thread_checker.h"
+#include "cobalt/base/polymorphic_downcast.h"
+#include "cobalt/script/wrappable.h"
+#include "cobalt/bindings/testing/dom_string_test_interface.h"
+
+#include "cobalt/script/v8c/v8c_global_environment.h"
+#include "v8/include/v8.h"
+
+namespace cobalt {
+namespace bindings {
+namespace testing {
+
+class V8cDOMStringTestInterface {
+ public:
+  static v8::Local<v8::Object> CreateWrapper(script::v8c::V8cGlobalEnvironment* env, const scoped_refptr<script::Wrappable>& wrappable);
+  static v8::Local<v8::FunctionTemplate> CreateTemplate(script::v8c::V8cGlobalEnvironment* env);
+  // TODO: Add |GetInterfaceObject|.
+};
+
+}  // namespace testing
+}  // namespace bindings
+}  // namespace cobalt
+
+#endif  // V8cDOMStringTestInterface_h
diff --git a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_enumeration_interface.cc b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_enumeration_interface.cc
new file mode 100644
index 0000000..5855537
--- /dev/null
+++ b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_enumeration_interface.cc
@@ -0,0 +1,219 @@
+
+
+// Copyright 2017 Google Inc. All Rights Reserved.
+//
+// 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.
+
+// clang-format off
+
+// This file has been auto-generated by bindings/code_generator_cobalt.py. DO NOT MODIFY!
+// Auto-generated from template: bindings/v8c/templates/interface.cc.template
+
+#include "cobalt/bindings/testing/v8c_enumeration_interface.h"
+
+#include "base/debug/trace_event.h"
+#include "cobalt/base/polymorphic_downcast.h"
+#include "cobalt/script/global_environment.h"
+#include "cobalt/script/script_value.h"
+#include "cobalt/script/value_handle.h"
+#include "cobalt/bindings/testing/test_enum.h"
+
+#include "v8c_gen_type_conversion.h"
+
+#include "cobalt/script/callback_interface_traits.h"
+#include "cobalt/script/v8c/callback_function_conversion.h"
+#include "cobalt/script/v8c/conversion_helpers.h"
+#include "cobalt/script/v8c/native_promise.h"
+#include "cobalt/script/v8c/type_traits.h"
+#include "cobalt/script/v8c/v8c_callback_function.h"
+#include "cobalt/script/v8c/v8c_callback_interface_holder.h"
+#include "cobalt/script/v8c/v8c_exception_state.h"
+#include "cobalt/script/v8c/v8c_global_environment.h"
+#include "cobalt/script/v8c/v8c_value_handle.h"
+#include "cobalt/script/v8c/wrapper_private.h"
+#include "v8/include/v8.h"
+
+
+namespace {
+using cobalt::bindings::testing::EnumerationInterface;
+using cobalt::bindings::testing::V8cEnumerationInterface;
+using cobalt::bindings::testing::TestEnum;
+using cobalt::script::CallbackInterfaceTraits;
+using cobalt::script::GlobalEnvironment;
+using cobalt::script::ScriptValue;
+using cobalt::script::ValueHandle;
+using cobalt::script::ValueHandle;
+using cobalt::script::ValueHandleHolder;
+using cobalt::script::Wrappable;
+
+using cobalt::script::v8c::FromJSValue;
+using cobalt::script::v8c::InterfaceData;
+using cobalt::script::v8c::kConversionFlagClamped;
+using cobalt::script::v8c::kConversionFlagNullable;
+using cobalt::script::v8c::kConversionFlagRestricted;
+using cobalt::script::v8c::kConversionFlagTreatNullAsEmptyString;
+using cobalt::script::v8c::kConversionFlagTreatUndefinedAsEmptyString;
+using cobalt::script::v8c::kNoConversionFlags;
+using cobalt::script::v8c::TypeTraits;
+using cobalt::script::v8c::V8cExceptionState;
+using cobalt::script::v8c::V8cGlobalEnvironment;
+using cobalt::script::v8c::WrapperFactory;
+using cobalt::script::v8c::WrapperPrivate;
+
+v8::Local<v8::Object> DummyFunctor(V8cGlobalEnvironment*, const scoped_refptr<Wrappable>&) {
+  NOTIMPLEMENTED();
+  return {};
+}
+
+}  // namespace
+
+namespace cobalt {
+namespace bindings {
+namespace testing {
+
+
+namespace {
+
+void EnumerationInterfaceConstructor(const v8::FunctionCallbackInfo<v8::Value>& args) {
+  NOTIMPLEMENTED();
+  if (!args.IsConstructCall()) {
+    // TODO: Probably throw something here...
+    return;
+  }
+
+  DCHECK(args.This()->InternalFieldCount() == 1);
+  args.This()->SetInternalField(0, v8::External::New(args.GetIsolate(), nullptr));
+  args.GetReturnValue().Set(args.This());
+}
+
+
+void v8cGet_enumProperty(
+  v8::Local<v8::String> property,
+  const v8::PropertyCallbackInfo<v8::Value>& info)
+{
+  NOTIMPLEMENTED();
+
+  v8::Local<v8::External> external = v8::Local<v8::External>::Cast(info.Holder()->GetInternalField(0));
+  WrapperPrivate* wrapper_private = static_cast<WrapperPrivate*>(external->Value());
+  EnumerationInterface* impl = static_cast<EnumerationInterface*>(wrapper_private->wrappable<EnumerationInterface>());
+
+  v8::Local<v8::Value> result_value;
+}
+
+
+void v8cSet_enumProperty(
+  v8::Local<v8::String> property,
+  v8::Local<v8::Value> v8_value,
+  const v8::PropertyCallbackInfo<void>& info)
+{
+  v8::Local<v8::External> external = v8::Local<v8::External>::Cast(info.Holder()->GetInternalField(0));
+  WrapperPrivate* wrapper_private = static_cast<WrapperPrivate*>(external->Value());
+  EnumerationInterface* impl = static_cast<EnumerationInterface*>(wrapper_private->wrappable<EnumerationInterface>());
+
+  TypeTraits<TestEnum>::ConversionType conversion_value;
+  V8cExceptionState exception_state{};
+  FromJSValue(info.GetIsolate(), v8_value, kNoConversionFlags, &exception_state, &conversion_value);
+  impl->set_enum_property(
+    conversion_value
+  );
+}
+
+
+
+void DummyFunction(const v8::FunctionCallbackInfo<v8::Value>& info) {
+  LOG(INFO) << __func__;
+}
+
+void InitializeTemplate(
+  V8cGlobalEnvironment* env,
+  InterfaceData* interface_data) {
+  v8::Isolate* isolate = env->isolate();
+  v8::Local<v8::FunctionTemplate> function_template = v8::FunctionTemplate::New(
+    isolate);
+  function_template->SetClassName(
+    v8::String::NewFromUtf8(isolate, "EnumerationInterface",
+        v8::NewStringType::kInternalized).ToLocalChecked());
+  v8::Local<v8::ObjectTemplate> instance_template = function_template->InstanceTemplate();
+  instance_template->SetInternalFieldCount(1);
+
+  v8::Local<v8::ObjectTemplate> prototype_template = function_template->PrototypeTemplate();
+  prototype_template->SetInternalFieldCount(1);
+
+  instance_template->SetAccessor(
+    v8::String::NewFromUtf8(isolate, "enumProperty",
+                              v8::NewStringType::kInternalized)
+          .ToLocalChecked(),
+    v8cGet_enumProperty
+    ,v8cSet_enumProperty
+  );
+
+  instance_template->Set(
+      v8::String::NewFromUtf8(
+          isolate,
+          "optionalEnumWithDefault",
+          v8::NewStringType::kInternalized).ToLocalChecked(),
+      v8::FunctionTemplate::New(isolate, DummyFunction)
+  );
+
+  interface_data->templ.Set(env->isolate(), function_template);
+}
+
+inline InterfaceData* GetInterfaceData(V8cGlobalEnvironment* env) {
+  const int kInterfaceUniqueId = 19;
+  // By convention, the |V8cGlobalEnvironment| that we are associated with
+  // will hold our |InterfaceData| at index |kInterfaceUniqueId|, as we asked
+  // for it to be there in the first place, and could not have conflicted with
+  // any other interface.
+  return env->GetInterfaceData(kInterfaceUniqueId);
+}
+
+}  // namespace
+
+v8::Local<v8::Object> V8cEnumerationInterface::CreateWrapper(V8cGlobalEnvironment* env, const scoped_refptr<Wrappable>& wrappable) {
+  v8::Isolate* isolate = env->isolate();
+  v8::Isolate::Scope isolate_scope(isolate);
+  v8::EscapableHandleScope handle_scope(isolate);
+  v8::Local<v8::Context> context = env->context();
+  v8::Context::Scope scope(context);
+
+  InterfaceData* interface_data = GetInterfaceData(env);
+  if (interface_data->templ.IsEmpty()) {
+    InitializeTemplate(env, interface_data);
+  }
+  DCHECK(!interface_data->templ.IsEmpty());
+
+  v8::Local<v8::FunctionTemplate> function_template = interface_data->templ.Get(isolate);
+  DCHECK(function_template->InstanceTemplate()->InternalFieldCount() == 1);
+  v8::Local<v8::Object> object = function_template->InstanceTemplate()->NewInstance(context).ToLocalChecked();
+  DCHECK(object->InternalFieldCount() == 1);
+
+  // |WrapperPrivate|'s lifetime will be managed by V8.
+  new WrapperPrivate(isolate, wrappable, object);
+  return handle_scope.Escape(object);
+}
+
+v8::Local<v8::FunctionTemplate> V8cEnumerationInterface::CreateTemplate(V8cGlobalEnvironment* env) {
+  InterfaceData* interface_data = GetInterfaceData(env);
+  if (interface_data->templ.IsEmpty()) {
+    InitializeTemplate(env, interface_data);
+  }
+
+  return interface_data->templ.Get(env->isolate());
+}
+
+
+}  // namespace testing
+}  // namespace bindings
+}  // namespace cobalt
+
+
diff --git a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_enumeration_interface.h b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_enumeration_interface.h
new file mode 100644
index 0000000..f83a0e4
--- /dev/null
+++ b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_enumeration_interface.h
@@ -0,0 +1,50 @@
+
+// Copyright 2017 Google Inc. All Rights Reserved.
+//
+// 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.
+
+// clang-format off
+
+// This file has been auto-generated by bindings/code_generator_cobalt.py. DO NOT MODIFY!
+// Auto-generated from template: bindings/v8c/templates/interface.h.template
+
+#ifndef V8cEnumerationInterface_h
+#define V8cEnumerationInterface_h
+
+#include "base/hash_tables.h"
+#include "base/lazy_instance.h"
+#include "base/memory/ref_counted.h"
+#include "base/threading/thread_checker.h"
+#include "cobalt/base/polymorphic_downcast.h"
+#include "cobalt/script/wrappable.h"
+#include "cobalt/bindings/testing/enumeration_interface.h"
+
+#include "cobalt/script/v8c/v8c_global_environment.h"
+#include "v8/include/v8.h"
+
+namespace cobalt {
+namespace bindings {
+namespace testing {
+
+class V8cEnumerationInterface {
+ public:
+  static v8::Local<v8::Object> CreateWrapper(script::v8c::V8cGlobalEnvironment* env, const scoped_refptr<script::Wrappable>& wrappable);
+  static v8::Local<v8::FunctionTemplate> CreateTemplate(script::v8c::V8cGlobalEnvironment* env);
+  // TODO: Add |GetInterfaceObject|.
+};
+
+}  // namespace testing
+}  // namespace bindings
+}  // namespace cobalt
+
+#endif  // V8cEnumerationInterface_h
diff --git a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_exception_object_interface.cc b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_exception_object_interface.cc
new file mode 100644
index 0000000..93e2870
--- /dev/null
+++ b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_exception_object_interface.cc
@@ -0,0 +1,212 @@
+
+
+// Copyright 2017 Google Inc. All Rights Reserved.
+//
+// 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.
+
+// clang-format off
+
+// This file has been auto-generated by bindings/code_generator_cobalt.py. DO NOT MODIFY!
+// Auto-generated from template: bindings/v8c/templates/interface.cc.template
+
+#include "cobalt/bindings/testing/v8c_exception_object_interface.h"
+
+#include "base/debug/trace_event.h"
+#include "cobalt/base/polymorphic_downcast.h"
+#include "cobalt/script/global_environment.h"
+#include "cobalt/script/script_value.h"
+#include "cobalt/script/value_handle.h"
+
+#include "v8c_gen_type_conversion.h"
+
+#include "cobalt/script/callback_interface_traits.h"
+#include "cobalt/script/v8c/callback_function_conversion.h"
+#include "cobalt/script/v8c/conversion_helpers.h"
+#include "cobalt/script/v8c/native_promise.h"
+#include "cobalt/script/v8c/type_traits.h"
+#include "cobalt/script/v8c/v8c_callback_function.h"
+#include "cobalt/script/v8c/v8c_callback_interface_holder.h"
+#include "cobalt/script/v8c/v8c_exception_state.h"
+#include "cobalt/script/v8c/v8c_global_environment.h"
+#include "cobalt/script/v8c/v8c_value_handle.h"
+#include "cobalt/script/v8c/wrapper_private.h"
+#include "v8/include/v8.h"
+
+
+namespace {
+using cobalt::bindings::testing::ExceptionObjectInterface;
+using cobalt::bindings::testing::V8cExceptionObjectInterface;
+using cobalt::script::CallbackInterfaceTraits;
+using cobalt::script::GlobalEnvironment;
+using cobalt::script::ScriptValue;
+using cobalt::script::ValueHandle;
+using cobalt::script::ValueHandle;
+using cobalt::script::ValueHandleHolder;
+using cobalt::script::Wrappable;
+
+using cobalt::script::v8c::FromJSValue;
+using cobalt::script::v8c::InterfaceData;
+using cobalt::script::v8c::kConversionFlagClamped;
+using cobalt::script::v8c::kConversionFlagNullable;
+using cobalt::script::v8c::kConversionFlagRestricted;
+using cobalt::script::v8c::kConversionFlagTreatNullAsEmptyString;
+using cobalt::script::v8c::kConversionFlagTreatUndefinedAsEmptyString;
+using cobalt::script::v8c::kNoConversionFlags;
+using cobalt::script::v8c::TypeTraits;
+using cobalt::script::v8c::V8cExceptionState;
+using cobalt::script::v8c::V8cGlobalEnvironment;
+using cobalt::script::v8c::WrapperFactory;
+using cobalt::script::v8c::WrapperPrivate;
+
+v8::Local<v8::Object> DummyFunctor(V8cGlobalEnvironment*, const scoped_refptr<Wrappable>&) {
+  NOTIMPLEMENTED();
+  return {};
+}
+
+}  // namespace
+
+namespace cobalt {
+namespace bindings {
+namespace testing {
+
+
+namespace {
+
+void ExceptionObjectInterfaceConstructor(const v8::FunctionCallbackInfo<v8::Value>& args) {
+  NOTIMPLEMENTED();
+  if (!args.IsConstructCall()) {
+    // TODO: Probably throw something here...
+    return;
+  }
+
+  DCHECK(args.This()->InternalFieldCount() == 1);
+  args.This()->SetInternalField(0, v8::External::New(args.GetIsolate(), nullptr));
+  args.GetReturnValue().Set(args.This());
+}
+
+
+void v8cGet_error(
+  v8::Local<v8::String> property,
+  const v8::PropertyCallbackInfo<v8::Value>& info)
+{
+  NOTIMPLEMENTED();
+
+  v8::Local<v8::External> external = v8::Local<v8::External>::Cast(info.Holder()->GetInternalField(0));
+  WrapperPrivate* wrapper_private = static_cast<WrapperPrivate*>(external->Value());
+  ExceptionObjectInterface* impl = static_cast<ExceptionObjectInterface*>(wrapper_private->wrappable<ExceptionObjectInterface>());
+
+  v8::Local<v8::Value> result_value;
+}
+
+
+
+void v8cGet_message(
+  v8::Local<v8::String> property,
+  const v8::PropertyCallbackInfo<v8::Value>& info)
+{
+  NOTIMPLEMENTED();
+
+  v8::Local<v8::External> external = v8::Local<v8::External>::Cast(info.Holder()->GetInternalField(0));
+  WrapperPrivate* wrapper_private = static_cast<WrapperPrivate*>(external->Value());
+  ExceptionObjectInterface* impl = static_cast<ExceptionObjectInterface*>(wrapper_private->wrappable<ExceptionObjectInterface>());
+
+  v8::Local<v8::Value> result_value;
+}
+
+
+
+void DummyFunction(const v8::FunctionCallbackInfo<v8::Value>& info) {
+  LOG(INFO) << __func__;
+}
+
+void InitializeTemplate(
+  V8cGlobalEnvironment* env,
+  InterfaceData* interface_data) {
+  v8::Isolate* isolate = env->isolate();
+  v8::Local<v8::FunctionTemplate> function_template = v8::FunctionTemplate::New(
+    isolate);
+  function_template->SetClassName(
+    v8::String::NewFromUtf8(isolate, "ExceptionObjectInterface",
+        v8::NewStringType::kInternalized).ToLocalChecked());
+  v8::Local<v8::ObjectTemplate> instance_template = function_template->InstanceTemplate();
+  instance_template->SetInternalFieldCount(1);
+
+  v8::Local<v8::ObjectTemplate> prototype_template = function_template->PrototypeTemplate();
+  prototype_template->SetInternalFieldCount(1);
+
+  instance_template->SetAccessor(
+    v8::String::NewFromUtf8(isolate, "error",
+                              v8::NewStringType::kInternalized)
+          .ToLocalChecked(),
+    v8cGet_error
+  );
+  instance_template->SetAccessor(
+    v8::String::NewFromUtf8(isolate, "message",
+                              v8::NewStringType::kInternalized)
+          .ToLocalChecked(),
+    v8cGet_message
+  );
+
+
+  interface_data->templ.Set(env->isolate(), function_template);
+}
+
+inline InterfaceData* GetInterfaceData(V8cGlobalEnvironment* env) {
+  const int kInterfaceUniqueId = 20;
+  // By convention, the |V8cGlobalEnvironment| that we are associated with
+  // will hold our |InterfaceData| at index |kInterfaceUniqueId|, as we asked
+  // for it to be there in the first place, and could not have conflicted with
+  // any other interface.
+  return env->GetInterfaceData(kInterfaceUniqueId);
+}
+
+}  // namespace
+
+v8::Local<v8::Object> V8cExceptionObjectInterface::CreateWrapper(V8cGlobalEnvironment* env, const scoped_refptr<Wrappable>& wrappable) {
+  v8::Isolate* isolate = env->isolate();
+  v8::Isolate::Scope isolate_scope(isolate);
+  v8::EscapableHandleScope handle_scope(isolate);
+  v8::Local<v8::Context> context = env->context();
+  v8::Context::Scope scope(context);
+
+  InterfaceData* interface_data = GetInterfaceData(env);
+  if (interface_data->templ.IsEmpty()) {
+    InitializeTemplate(env, interface_data);
+  }
+  DCHECK(!interface_data->templ.IsEmpty());
+
+  v8::Local<v8::FunctionTemplate> function_template = interface_data->templ.Get(isolate);
+  DCHECK(function_template->InstanceTemplate()->InternalFieldCount() == 1);
+  v8::Local<v8::Object> object = function_template->InstanceTemplate()->NewInstance(context).ToLocalChecked();
+  DCHECK(object->InternalFieldCount() == 1);
+
+  // |WrapperPrivate|'s lifetime will be managed by V8.
+  new WrapperPrivate(isolate, wrappable, object);
+  return handle_scope.Escape(object);
+}
+
+v8::Local<v8::FunctionTemplate> V8cExceptionObjectInterface::CreateTemplate(V8cGlobalEnvironment* env) {
+  InterfaceData* interface_data = GetInterfaceData(env);
+  if (interface_data->templ.IsEmpty()) {
+    InitializeTemplate(env, interface_data);
+  }
+
+  return interface_data->templ.Get(env->isolate());
+}
+
+
+}  // namespace testing
+}  // namespace bindings
+}  // namespace cobalt
+
+
diff --git a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_exception_object_interface.h b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_exception_object_interface.h
new file mode 100644
index 0000000..4b31a28
--- /dev/null
+++ b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_exception_object_interface.h
@@ -0,0 +1,50 @@
+
+// Copyright 2017 Google Inc. All Rights Reserved.
+//
+// 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.
+
+// clang-format off
+
+// This file has been auto-generated by bindings/code_generator_cobalt.py. DO NOT MODIFY!
+// Auto-generated from template: bindings/v8c/templates/interface.h.template
+
+#ifndef V8cExceptionObjectInterface_h
+#define V8cExceptionObjectInterface_h
+
+#include "base/hash_tables.h"
+#include "base/lazy_instance.h"
+#include "base/memory/ref_counted.h"
+#include "base/threading/thread_checker.h"
+#include "cobalt/base/polymorphic_downcast.h"
+#include "cobalt/script/wrappable.h"
+#include "cobalt/bindings/testing/exception_object_interface.h"
+
+#include "cobalt/script/v8c/v8c_global_environment.h"
+#include "v8/include/v8.h"
+
+namespace cobalt {
+namespace bindings {
+namespace testing {
+
+class V8cExceptionObjectInterface {
+ public:
+  static v8::Local<v8::Object> CreateWrapper(script::v8c::V8cGlobalEnvironment* env, const scoped_refptr<script::Wrappable>& wrappable);
+  static v8::Local<v8::FunctionTemplate> CreateTemplate(script::v8c::V8cGlobalEnvironment* env);
+  // TODO: Add |GetInterfaceObject|.
+};
+
+}  // namespace testing
+}  // namespace bindings
+}  // namespace cobalt
+
+#endif  // V8cExceptionObjectInterface_h
diff --git a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_exceptions_interface.cc b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_exceptions_interface.cc
new file mode 100644
index 0000000..d668a39
--- /dev/null
+++ b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_exceptions_interface.cc
@@ -0,0 +1,219 @@
+
+
+// Copyright 2017 Google Inc. All Rights Reserved.
+//
+// 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.
+
+// clang-format off
+
+// This file has been auto-generated by bindings/code_generator_cobalt.py. DO NOT MODIFY!
+// Auto-generated from template: bindings/v8c/templates/interface.cc.template
+
+#include "cobalt/bindings/testing/v8c_exceptions_interface.h"
+
+#include "base/debug/trace_event.h"
+#include "cobalt/base/polymorphic_downcast.h"
+#include "cobalt/script/global_environment.h"
+#include "cobalt/script/script_value.h"
+#include "cobalt/script/value_handle.h"
+
+#include "v8c_gen_type_conversion.h"
+
+#include "cobalt/script/callback_interface_traits.h"
+#include "cobalt/script/v8c/callback_function_conversion.h"
+#include "cobalt/script/v8c/conversion_helpers.h"
+#include "cobalt/script/v8c/native_promise.h"
+#include "cobalt/script/v8c/type_traits.h"
+#include "cobalt/script/v8c/v8c_callback_function.h"
+#include "cobalt/script/v8c/v8c_callback_interface_holder.h"
+#include "cobalt/script/v8c/v8c_exception_state.h"
+#include "cobalt/script/v8c/v8c_global_environment.h"
+#include "cobalt/script/v8c/v8c_value_handle.h"
+#include "cobalt/script/v8c/wrapper_private.h"
+#include "v8/include/v8.h"
+
+
+namespace {
+using cobalt::bindings::testing::ExceptionsInterface;
+using cobalt::bindings::testing::V8cExceptionsInterface;
+using cobalt::script::CallbackInterfaceTraits;
+using cobalt::script::GlobalEnvironment;
+using cobalt::script::ScriptValue;
+using cobalt::script::ValueHandle;
+using cobalt::script::ValueHandle;
+using cobalt::script::ValueHandleHolder;
+using cobalt::script::Wrappable;
+
+using cobalt::script::v8c::FromJSValue;
+using cobalt::script::v8c::InterfaceData;
+using cobalt::script::v8c::kConversionFlagClamped;
+using cobalt::script::v8c::kConversionFlagNullable;
+using cobalt::script::v8c::kConversionFlagRestricted;
+using cobalt::script::v8c::kConversionFlagTreatNullAsEmptyString;
+using cobalt::script::v8c::kConversionFlagTreatUndefinedAsEmptyString;
+using cobalt::script::v8c::kNoConversionFlags;
+using cobalt::script::v8c::TypeTraits;
+using cobalt::script::v8c::V8cExceptionState;
+using cobalt::script::v8c::V8cGlobalEnvironment;
+using cobalt::script::v8c::WrapperFactory;
+using cobalt::script::v8c::WrapperPrivate;
+
+v8::Local<v8::Object> DummyFunctor(V8cGlobalEnvironment*, const scoped_refptr<Wrappable>&) {
+  NOTIMPLEMENTED();
+  return {};
+}
+
+}  // namespace
+
+namespace cobalt {
+namespace bindings {
+namespace testing {
+
+
+namespace {
+
+void ExceptionsInterfaceConstructor(const v8::FunctionCallbackInfo<v8::Value>& args) {
+  NOTIMPLEMENTED();
+  if (!args.IsConstructCall()) {
+    // TODO: Probably throw something here...
+    return;
+  }
+
+  DCHECK(args.This()->InternalFieldCount() == 1);
+  args.This()->SetInternalField(0, v8::External::New(args.GetIsolate(), nullptr));
+  args.GetReturnValue().Set(args.This());
+}
+
+
+void v8cGet_attributeThrowsException(
+  v8::Local<v8::String> property,
+  const v8::PropertyCallbackInfo<v8::Value>& info)
+{
+  NOTIMPLEMENTED();
+
+  v8::Local<v8::External> external = v8::Local<v8::External>::Cast(info.Holder()->GetInternalField(0));
+  WrapperPrivate* wrapper_private = static_cast<WrapperPrivate*>(external->Value());
+  ExceptionsInterface* impl = static_cast<ExceptionsInterface*>(wrapper_private->wrappable<ExceptionsInterface>());
+
+  v8::Local<v8::Value> result_value;
+}
+
+
+void v8cSet_attributeThrowsException(
+  v8::Local<v8::String> property,
+  v8::Local<v8::Value> v8_value,
+  const v8::PropertyCallbackInfo<void>& info)
+{
+  v8::Local<v8::External> external = v8::Local<v8::External>::Cast(info.Holder()->GetInternalField(0));
+  WrapperPrivate* wrapper_private = static_cast<WrapperPrivate*>(external->Value());
+  ExceptionsInterface* impl = static_cast<ExceptionsInterface*>(wrapper_private->wrappable<ExceptionsInterface>());
+
+  TypeTraits<bool>::ConversionType conversion_value;
+  V8cExceptionState exception_state{};
+  FromJSValue(info.GetIsolate(), v8_value, kNoConversionFlags, &exception_state, &conversion_value);
+  V8cExceptionState exception;
+  impl->set_attribute_throws_exception(
+    conversion_value
+    ,&exception
+  );
+}
+
+
+
+void DummyFunction(const v8::FunctionCallbackInfo<v8::Value>& info) {
+  LOG(INFO) << __func__;
+}
+
+void InitializeTemplate(
+  V8cGlobalEnvironment* env,
+  InterfaceData* interface_data) {
+  v8::Isolate* isolate = env->isolate();
+  v8::Local<v8::FunctionTemplate> function_template = v8::FunctionTemplate::New(
+    isolate);
+  function_template->SetClassName(
+    v8::String::NewFromUtf8(isolate, "ExceptionsInterface",
+        v8::NewStringType::kInternalized).ToLocalChecked());
+  v8::Local<v8::ObjectTemplate> instance_template = function_template->InstanceTemplate();
+  instance_template->SetInternalFieldCount(1);
+
+  v8::Local<v8::ObjectTemplate> prototype_template = function_template->PrototypeTemplate();
+  prototype_template->SetInternalFieldCount(1);
+
+  instance_template->SetAccessor(
+    v8::String::NewFromUtf8(isolate, "attributeThrowsException",
+                              v8::NewStringType::kInternalized)
+          .ToLocalChecked(),
+    v8cGet_attributeThrowsException
+    ,v8cSet_attributeThrowsException
+  );
+
+  instance_template->Set(
+      v8::String::NewFromUtf8(
+          isolate,
+          "functionThrowsException",
+          v8::NewStringType::kInternalized).ToLocalChecked(),
+      v8::FunctionTemplate::New(isolate, DummyFunction)
+  );
+
+  interface_data->templ.Set(env->isolate(), function_template);
+}
+
+inline InterfaceData* GetInterfaceData(V8cGlobalEnvironment* env) {
+  const int kInterfaceUniqueId = 21;
+  // By convention, the |V8cGlobalEnvironment| that we are associated with
+  // will hold our |InterfaceData| at index |kInterfaceUniqueId|, as we asked
+  // for it to be there in the first place, and could not have conflicted with
+  // any other interface.
+  return env->GetInterfaceData(kInterfaceUniqueId);
+}
+
+}  // namespace
+
+v8::Local<v8::Object> V8cExceptionsInterface::CreateWrapper(V8cGlobalEnvironment* env, const scoped_refptr<Wrappable>& wrappable) {
+  v8::Isolate* isolate = env->isolate();
+  v8::Isolate::Scope isolate_scope(isolate);
+  v8::EscapableHandleScope handle_scope(isolate);
+  v8::Local<v8::Context> context = env->context();
+  v8::Context::Scope scope(context);
+
+  InterfaceData* interface_data = GetInterfaceData(env);
+  if (interface_data->templ.IsEmpty()) {
+    InitializeTemplate(env, interface_data);
+  }
+  DCHECK(!interface_data->templ.IsEmpty());
+
+  v8::Local<v8::FunctionTemplate> function_template = interface_data->templ.Get(isolate);
+  DCHECK(function_template->InstanceTemplate()->InternalFieldCount() == 1);
+  v8::Local<v8::Object> object = function_template->InstanceTemplate()->NewInstance(context).ToLocalChecked();
+  DCHECK(object->InternalFieldCount() == 1);
+
+  // |WrapperPrivate|'s lifetime will be managed by V8.
+  new WrapperPrivate(isolate, wrappable, object);
+  return handle_scope.Escape(object);
+}
+
+v8::Local<v8::FunctionTemplate> V8cExceptionsInterface::CreateTemplate(V8cGlobalEnvironment* env) {
+  InterfaceData* interface_data = GetInterfaceData(env);
+  if (interface_data->templ.IsEmpty()) {
+    InitializeTemplate(env, interface_data);
+  }
+
+  return interface_data->templ.Get(env->isolate());
+}
+
+
+}  // namespace testing
+}  // namespace bindings
+}  // namespace cobalt
+
+
diff --git a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_exceptions_interface.h b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_exceptions_interface.h
new file mode 100644
index 0000000..e34dfb1
--- /dev/null
+++ b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_exceptions_interface.h
@@ -0,0 +1,50 @@
+
+// Copyright 2017 Google Inc. All Rights Reserved.
+//
+// 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.
+
+// clang-format off
+
+// This file has been auto-generated by bindings/code_generator_cobalt.py. DO NOT MODIFY!
+// Auto-generated from template: bindings/v8c/templates/interface.h.template
+
+#ifndef V8cExceptionsInterface_h
+#define V8cExceptionsInterface_h
+
+#include "base/hash_tables.h"
+#include "base/lazy_instance.h"
+#include "base/memory/ref_counted.h"
+#include "base/threading/thread_checker.h"
+#include "cobalt/base/polymorphic_downcast.h"
+#include "cobalt/script/wrappable.h"
+#include "cobalt/bindings/testing/exceptions_interface.h"
+
+#include "cobalt/script/v8c/v8c_global_environment.h"
+#include "v8/include/v8.h"
+
+namespace cobalt {
+namespace bindings {
+namespace testing {
+
+class V8cExceptionsInterface {
+ public:
+  static v8::Local<v8::Object> CreateWrapper(script::v8c::V8cGlobalEnvironment* env, const scoped_refptr<script::Wrappable>& wrappable);
+  static v8::Local<v8::FunctionTemplate> CreateTemplate(script::v8c::V8cGlobalEnvironment* env);
+  // TODO: Add |GetInterfaceObject|.
+};
+
+}  // namespace testing
+}  // namespace bindings
+}  // namespace cobalt
+
+#endif  // V8cExceptionsInterface_h
diff --git a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_extended_idl_attributes_interface.cc b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_extended_idl_attributes_interface.cc
new file mode 100644
index 0000000..1f7f07c
--- /dev/null
+++ b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_extended_idl_attributes_interface.cc
@@ -0,0 +1,224 @@
+
+
+// Copyright 2017 Google Inc. All Rights Reserved.
+//
+// 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.
+
+// clang-format off
+
+// This file has been auto-generated by bindings/code_generator_cobalt.py. DO NOT MODIFY!
+// Auto-generated from template: bindings/v8c/templates/interface.cc.template
+
+#include "cobalt/bindings/testing/v8c_extended_idl_attributes_interface.h"
+
+#include "base/debug/trace_event.h"
+#include "cobalt/base/polymorphic_downcast.h"
+#include "cobalt/script/global_environment.h"
+#include "cobalt/script/script_value.h"
+#include "cobalt/script/value_handle.h"
+
+#include "v8c_gen_type_conversion.h"
+
+#include "cobalt/script/callback_interface_traits.h"
+#include "cobalt/script/v8c/callback_function_conversion.h"
+#include "cobalt/script/v8c/conversion_helpers.h"
+#include "cobalt/script/v8c/native_promise.h"
+#include "cobalt/script/v8c/type_traits.h"
+#include "cobalt/script/v8c/v8c_callback_function.h"
+#include "cobalt/script/v8c/v8c_callback_interface_holder.h"
+#include "cobalt/script/v8c/v8c_exception_state.h"
+#include "cobalt/script/v8c/v8c_global_environment.h"
+#include "cobalt/script/v8c/v8c_value_handle.h"
+#include "cobalt/script/v8c/wrapper_private.h"
+#include "v8/include/v8.h"
+
+
+namespace {
+using cobalt::bindings::testing::ExtendedIDLAttributesInterface;
+using cobalt::bindings::testing::V8cExtendedIDLAttributesInterface;
+using cobalt::script::CallbackInterfaceTraits;
+using cobalt::script::GlobalEnvironment;
+using cobalt::script::ScriptValue;
+using cobalt::script::ValueHandle;
+using cobalt::script::ValueHandle;
+using cobalt::script::ValueHandleHolder;
+using cobalt::script::Wrappable;
+
+using cobalt::script::v8c::FromJSValue;
+using cobalt::script::v8c::InterfaceData;
+using cobalt::script::v8c::kConversionFlagClamped;
+using cobalt::script::v8c::kConversionFlagNullable;
+using cobalt::script::v8c::kConversionFlagRestricted;
+using cobalt::script::v8c::kConversionFlagTreatNullAsEmptyString;
+using cobalt::script::v8c::kConversionFlagTreatUndefinedAsEmptyString;
+using cobalt::script::v8c::kNoConversionFlags;
+using cobalt::script::v8c::TypeTraits;
+using cobalt::script::v8c::V8cExceptionState;
+using cobalt::script::v8c::V8cGlobalEnvironment;
+using cobalt::script::v8c::WrapperFactory;
+using cobalt::script::v8c::WrapperPrivate;
+
+v8::Local<v8::Object> DummyFunctor(V8cGlobalEnvironment*, const scoped_refptr<Wrappable>&) {
+  NOTIMPLEMENTED();
+  return {};
+}
+
+}  // namespace
+
+namespace cobalt {
+namespace bindings {
+namespace testing {
+
+
+namespace {
+
+void ExtendedIDLAttributesInterfaceConstructor(const v8::FunctionCallbackInfo<v8::Value>& args) {
+  NOTIMPLEMENTED();
+  if (!args.IsConstructCall()) {
+    // TODO: Probably throw something here...
+    return;
+  }
+
+  DCHECK(args.This()->InternalFieldCount() == 1);
+  args.This()->SetInternalField(0, v8::External::New(args.GetIsolate(), nullptr));
+  args.GetReturnValue().Set(args.This());
+}
+
+
+void v8cGet_default(
+  v8::Local<v8::String> property,
+  const v8::PropertyCallbackInfo<v8::Value>& info)
+{
+  NOTIMPLEMENTED();
+
+  v8::Local<v8::External> external = v8::Local<v8::External>::Cast(info.Holder()->GetInternalField(0));
+  WrapperPrivate* wrapper_private = static_cast<WrapperPrivate*>(external->Value());
+  ExtendedIDLAttributesInterface* impl = static_cast<ExtendedIDLAttributesInterface*>(wrapper_private->wrappable<ExtendedIDLAttributesInterface>());
+
+  v8::Local<v8::Value> result_value;
+}
+
+
+void v8cSet_default(
+  v8::Local<v8::String> property,
+  v8::Local<v8::Value> v8_value,
+  const v8::PropertyCallbackInfo<void>& info)
+{
+  v8::Local<v8::External> external = v8::Local<v8::External>::Cast(info.Holder()->GetInternalField(0));
+  WrapperPrivate* wrapper_private = static_cast<WrapperPrivate*>(external->Value());
+  ExtendedIDLAttributesInterface* impl = static_cast<ExtendedIDLAttributesInterface*>(wrapper_private->wrappable<ExtendedIDLAttributesInterface>());
+
+  TypeTraits<bool>::ConversionType conversion_value;
+  V8cExceptionState exception_state{};
+  FromJSValue(info.GetIsolate(), v8_value, kNoConversionFlags, &exception_state, &conversion_value);
+  impl->set_attribute_default(
+    conversion_value
+  );
+}
+
+
+
+void DummyFunction(const v8::FunctionCallbackInfo<v8::Value>& info) {
+  LOG(INFO) << __func__;
+}
+
+void InitializeTemplate(
+  V8cGlobalEnvironment* env,
+  InterfaceData* interface_data) {
+  v8::Isolate* isolate = env->isolate();
+  v8::Local<v8::FunctionTemplate> function_template = v8::FunctionTemplate::New(
+    isolate);
+  function_template->SetClassName(
+    v8::String::NewFromUtf8(isolate, "ExtendedIDLAttributesInterface",
+        v8::NewStringType::kInternalized).ToLocalChecked());
+  v8::Local<v8::ObjectTemplate> instance_template = function_template->InstanceTemplate();
+  instance_template->SetInternalFieldCount(1);
+
+  v8::Local<v8::ObjectTemplate> prototype_template = function_template->PrototypeTemplate();
+  prototype_template->SetInternalFieldCount(1);
+
+  instance_template->SetAccessor(
+    v8::String::NewFromUtf8(isolate, "default",
+                              v8::NewStringType::kInternalized)
+          .ToLocalChecked(),
+    v8cGet_default
+    ,v8cSet_default
+  );
+
+  instance_template->Set(
+      v8::String::NewFromUtf8(
+          isolate,
+          "callWithSettings",
+          v8::NewStringType::kInternalized).ToLocalChecked(),
+      v8::FunctionTemplate::New(isolate, DummyFunction)
+  );
+  instance_template->Set(
+      v8::String::NewFromUtf8(
+          isolate,
+          "clampArgument",
+          v8::NewStringType::kInternalized).ToLocalChecked(),
+      v8::FunctionTemplate::New(isolate, DummyFunction)
+  );
+
+  interface_data->templ.Set(env->isolate(), function_template);
+}
+
+inline InterfaceData* GetInterfaceData(V8cGlobalEnvironment* env) {
+  const int kInterfaceUniqueId = 22;
+  // By convention, the |V8cGlobalEnvironment| that we are associated with
+  // will hold our |InterfaceData| at index |kInterfaceUniqueId|, as we asked
+  // for it to be there in the first place, and could not have conflicted with
+  // any other interface.
+  return env->GetInterfaceData(kInterfaceUniqueId);
+}
+
+}  // namespace
+
+v8::Local<v8::Object> V8cExtendedIDLAttributesInterface::CreateWrapper(V8cGlobalEnvironment* env, const scoped_refptr<Wrappable>& wrappable) {
+  v8::Isolate* isolate = env->isolate();
+  v8::Isolate::Scope isolate_scope(isolate);
+  v8::EscapableHandleScope handle_scope(isolate);
+  v8::Local<v8::Context> context = env->context();
+  v8::Context::Scope scope(context);
+
+  InterfaceData* interface_data = GetInterfaceData(env);
+  if (interface_data->templ.IsEmpty()) {
+    InitializeTemplate(env, interface_data);
+  }
+  DCHECK(!interface_data->templ.IsEmpty());
+
+  v8::Local<v8::FunctionTemplate> function_template = interface_data->templ.Get(isolate);
+  DCHECK(function_template->InstanceTemplate()->InternalFieldCount() == 1);
+  v8::Local<v8::Object> object = function_template->InstanceTemplate()->NewInstance(context).ToLocalChecked();
+  DCHECK(object->InternalFieldCount() == 1);
+
+  // |WrapperPrivate|'s lifetime will be managed by V8.
+  new WrapperPrivate(isolate, wrappable, object);
+  return handle_scope.Escape(object);
+}
+
+v8::Local<v8::FunctionTemplate> V8cExtendedIDLAttributesInterface::CreateTemplate(V8cGlobalEnvironment* env) {
+  InterfaceData* interface_data = GetInterfaceData(env);
+  if (interface_data->templ.IsEmpty()) {
+    InitializeTemplate(env, interface_data);
+  }
+
+  return interface_data->templ.Get(env->isolate());
+}
+
+
+}  // namespace testing
+}  // namespace bindings
+}  // namespace cobalt
+
+
diff --git a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_extended_idl_attributes_interface.h b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_extended_idl_attributes_interface.h
new file mode 100644
index 0000000..6a70006
--- /dev/null
+++ b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_extended_idl_attributes_interface.h
@@ -0,0 +1,50 @@
+
+// Copyright 2017 Google Inc. All Rights Reserved.
+//
+// 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.
+
+// clang-format off
+
+// This file has been auto-generated by bindings/code_generator_cobalt.py. DO NOT MODIFY!
+// Auto-generated from template: bindings/v8c/templates/interface.h.template
+
+#ifndef V8cExtendedIDLAttributesInterface_h
+#define V8cExtendedIDLAttributesInterface_h
+
+#include "base/hash_tables.h"
+#include "base/lazy_instance.h"
+#include "base/memory/ref_counted.h"
+#include "base/threading/thread_checker.h"
+#include "cobalt/base/polymorphic_downcast.h"
+#include "cobalt/script/wrappable.h"
+#include "cobalt/bindings/testing/extended_idl_attributes_interface.h"
+
+#include "cobalt/script/v8c/v8c_global_environment.h"
+#include "v8/include/v8.h"
+
+namespace cobalt {
+namespace bindings {
+namespace testing {
+
+class V8cExtendedIDLAttributesInterface {
+ public:
+  static v8::Local<v8::Object> CreateWrapper(script::v8c::V8cGlobalEnvironment* env, const scoped_refptr<script::Wrappable>& wrappable);
+  static v8::Local<v8::FunctionTemplate> CreateTemplate(script::v8c::V8cGlobalEnvironment* env);
+  // TODO: Add |GetInterfaceObject|.
+};
+
+}  // namespace testing
+}  // namespace bindings
+}  // namespace cobalt
+
+#endif  // V8cExtendedIDLAttributesInterface_h
diff --git a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_garbage_collection_test_interface.cc b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_garbage_collection_test_interface.cc
new file mode 100644
index 0000000..414e1c2
--- /dev/null
+++ b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_garbage_collection_test_interface.cc
@@ -0,0 +1,254 @@
+
+
+// Copyright 2017 Google Inc. All Rights Reserved.
+//
+// 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.
+
+// clang-format off
+
+// This file has been auto-generated by bindings/code_generator_cobalt.py. DO NOT MODIFY!
+// Auto-generated from template: bindings/v8c/templates/interface.cc.template
+
+#include "cobalt/bindings/testing/v8c_garbage_collection_test_interface.h"
+
+#include "base/debug/trace_event.h"
+#include "cobalt/base/polymorphic_downcast.h"
+#include "cobalt/script/global_environment.h"
+#include "cobalt/script/script_value.h"
+#include "cobalt/script/value_handle.h"
+#include "cobalt/bindings/testing/garbage_collection_test_interface.h"
+#include "cobalt/bindings/testing/v8c_garbage_collection_test_interface.h"
+
+#include "v8c_gen_type_conversion.h"
+
+#include "cobalt/script/callback_interface_traits.h"
+#include "cobalt/script/v8c/callback_function_conversion.h"
+#include "cobalt/script/v8c/conversion_helpers.h"
+#include "cobalt/script/v8c/native_promise.h"
+#include "cobalt/script/v8c/type_traits.h"
+#include "cobalt/script/v8c/v8c_callback_function.h"
+#include "cobalt/script/v8c/v8c_callback_interface_holder.h"
+#include "cobalt/script/v8c/v8c_exception_state.h"
+#include "cobalt/script/v8c/v8c_global_environment.h"
+#include "cobalt/script/v8c/v8c_value_handle.h"
+#include "cobalt/script/v8c/wrapper_private.h"
+#include "v8/include/v8.h"
+
+
+namespace {
+using cobalt::bindings::testing::GarbageCollectionTestInterface;
+using cobalt::bindings::testing::V8cGarbageCollectionTestInterface;
+using cobalt::bindings::testing::GarbageCollectionTestInterface;
+using cobalt::bindings::testing::V8cGarbageCollectionTestInterface;
+using cobalt::script::CallbackInterfaceTraits;
+using cobalt::script::GlobalEnvironment;
+using cobalt::script::ScriptValue;
+using cobalt::script::ValueHandle;
+using cobalt::script::ValueHandle;
+using cobalt::script::ValueHandleHolder;
+using cobalt::script::Wrappable;
+
+using cobalt::script::v8c::FromJSValue;
+using cobalt::script::v8c::InterfaceData;
+using cobalt::script::v8c::kConversionFlagClamped;
+using cobalt::script::v8c::kConversionFlagNullable;
+using cobalt::script::v8c::kConversionFlagRestricted;
+using cobalt::script::v8c::kConversionFlagTreatNullAsEmptyString;
+using cobalt::script::v8c::kConversionFlagTreatUndefinedAsEmptyString;
+using cobalt::script::v8c::kNoConversionFlags;
+using cobalt::script::v8c::TypeTraits;
+using cobalt::script::v8c::V8cExceptionState;
+using cobalt::script::v8c::V8cGlobalEnvironment;
+using cobalt::script::v8c::WrapperFactory;
+using cobalt::script::v8c::WrapperPrivate;
+
+v8::Local<v8::Object> DummyFunctor(V8cGlobalEnvironment*, const scoped_refptr<Wrappable>&) {
+  NOTIMPLEMENTED();
+  return {};
+}
+
+}  // namespace
+
+namespace cobalt {
+namespace bindings {
+namespace testing {
+
+
+namespace {
+
+void GarbageCollectionTestInterfaceConstructor(const v8::FunctionCallbackInfo<v8::Value>& args) {
+  NOTIMPLEMENTED();
+  if (!args.IsConstructCall()) {
+    // TODO: Probably throw something here...
+    return;
+  }
+
+  DCHECK(args.This()->InternalFieldCount() == 1);
+  args.This()->SetInternalField(0, v8::External::New(args.GetIsolate(), nullptr));
+  args.GetReturnValue().Set(args.This());
+}
+
+
+void v8cGet_previous(
+  v8::Local<v8::String> property,
+  const v8::PropertyCallbackInfo<v8::Value>& info)
+{
+  NOTIMPLEMENTED();
+
+  v8::Local<v8::External> external = v8::Local<v8::External>::Cast(info.Holder()->GetInternalField(0));
+  WrapperPrivate* wrapper_private = static_cast<WrapperPrivate*>(external->Value());
+  GarbageCollectionTestInterface* impl = static_cast<GarbageCollectionTestInterface*>(wrapper_private->wrappable<GarbageCollectionTestInterface>());
+
+  v8::Local<v8::Value> result_value;
+}
+
+
+void v8cSet_previous(
+  v8::Local<v8::String> property,
+  v8::Local<v8::Value> v8_value,
+  const v8::PropertyCallbackInfo<void>& info)
+{
+  v8::Local<v8::External> external = v8::Local<v8::External>::Cast(info.Holder()->GetInternalField(0));
+  WrapperPrivate* wrapper_private = static_cast<WrapperPrivate*>(external->Value());
+  GarbageCollectionTestInterface* impl = static_cast<GarbageCollectionTestInterface*>(wrapper_private->wrappable<GarbageCollectionTestInterface>());
+
+  TypeTraits<scoped_refptr<GarbageCollectionTestInterface>>::ConversionType conversion_value;
+  V8cExceptionState exception_state{};
+  FromJSValue(info.GetIsolate(), v8_value, (kConversionFlagNullable), &exception_state, &conversion_value);
+  impl->set_previous(
+    conversion_value
+  );
+}
+
+
+
+void v8cGet_next(
+  v8::Local<v8::String> property,
+  const v8::PropertyCallbackInfo<v8::Value>& info)
+{
+  NOTIMPLEMENTED();
+
+  v8::Local<v8::External> external = v8::Local<v8::External>::Cast(info.Holder()->GetInternalField(0));
+  WrapperPrivate* wrapper_private = static_cast<WrapperPrivate*>(external->Value());
+  GarbageCollectionTestInterface* impl = static_cast<GarbageCollectionTestInterface*>(wrapper_private->wrappable<GarbageCollectionTestInterface>());
+
+  v8::Local<v8::Value> result_value;
+}
+
+
+void v8cSet_next(
+  v8::Local<v8::String> property,
+  v8::Local<v8::Value> v8_value,
+  const v8::PropertyCallbackInfo<void>& info)
+{
+  v8::Local<v8::External> external = v8::Local<v8::External>::Cast(info.Holder()->GetInternalField(0));
+  WrapperPrivate* wrapper_private = static_cast<WrapperPrivate*>(external->Value());
+  GarbageCollectionTestInterface* impl = static_cast<GarbageCollectionTestInterface*>(wrapper_private->wrappable<GarbageCollectionTestInterface>());
+
+  TypeTraits<scoped_refptr<GarbageCollectionTestInterface>>::ConversionType conversion_value;
+  V8cExceptionState exception_state{};
+  FromJSValue(info.GetIsolate(), v8_value, (kConversionFlagNullable), &exception_state, &conversion_value);
+  impl->set_next(
+    conversion_value
+  );
+}
+
+
+
+void DummyFunction(const v8::FunctionCallbackInfo<v8::Value>& info) {
+  LOG(INFO) << __func__;
+}
+
+void InitializeTemplate(
+  V8cGlobalEnvironment* env,
+  InterfaceData* interface_data) {
+  v8::Isolate* isolate = env->isolate();
+  v8::Local<v8::FunctionTemplate> function_template = v8::FunctionTemplate::New(
+    isolate);
+  function_template->SetClassName(
+    v8::String::NewFromUtf8(isolate, "GarbageCollectionTestInterface",
+        v8::NewStringType::kInternalized).ToLocalChecked());
+  v8::Local<v8::ObjectTemplate> instance_template = function_template->InstanceTemplate();
+  instance_template->SetInternalFieldCount(1);
+
+  v8::Local<v8::ObjectTemplate> prototype_template = function_template->PrototypeTemplate();
+  prototype_template->SetInternalFieldCount(1);
+
+  instance_template->SetAccessor(
+    v8::String::NewFromUtf8(isolate, "previous",
+                              v8::NewStringType::kInternalized)
+          .ToLocalChecked(),
+    v8cGet_previous
+    ,v8cSet_previous
+  );
+  instance_template->SetAccessor(
+    v8::String::NewFromUtf8(isolate, "next",
+                              v8::NewStringType::kInternalized)
+          .ToLocalChecked(),
+    v8cGet_next
+    ,v8cSet_next
+  );
+
+
+  interface_data->templ.Set(env->isolate(), function_template);
+}
+
+inline InterfaceData* GetInterfaceData(V8cGlobalEnvironment* env) {
+  const int kInterfaceUniqueId = 23;
+  // By convention, the |V8cGlobalEnvironment| that we are associated with
+  // will hold our |InterfaceData| at index |kInterfaceUniqueId|, as we asked
+  // for it to be there in the first place, and could not have conflicted with
+  // any other interface.
+  return env->GetInterfaceData(kInterfaceUniqueId);
+}
+
+}  // namespace
+
+v8::Local<v8::Object> V8cGarbageCollectionTestInterface::CreateWrapper(V8cGlobalEnvironment* env, const scoped_refptr<Wrappable>& wrappable) {
+  v8::Isolate* isolate = env->isolate();
+  v8::Isolate::Scope isolate_scope(isolate);
+  v8::EscapableHandleScope handle_scope(isolate);
+  v8::Local<v8::Context> context = env->context();
+  v8::Context::Scope scope(context);
+
+  InterfaceData* interface_data = GetInterfaceData(env);
+  if (interface_data->templ.IsEmpty()) {
+    InitializeTemplate(env, interface_data);
+  }
+  DCHECK(!interface_data->templ.IsEmpty());
+
+  v8::Local<v8::FunctionTemplate> function_template = interface_data->templ.Get(isolate);
+  DCHECK(function_template->InstanceTemplate()->InternalFieldCount() == 1);
+  v8::Local<v8::Object> object = function_template->InstanceTemplate()->NewInstance(context).ToLocalChecked();
+  DCHECK(object->InternalFieldCount() == 1);
+
+  // |WrapperPrivate|'s lifetime will be managed by V8.
+  new WrapperPrivate(isolate, wrappable, object);
+  return handle_scope.Escape(object);
+}
+
+v8::Local<v8::FunctionTemplate> V8cGarbageCollectionTestInterface::CreateTemplate(V8cGlobalEnvironment* env) {
+  InterfaceData* interface_data = GetInterfaceData(env);
+  if (interface_data->templ.IsEmpty()) {
+    InitializeTemplate(env, interface_data);
+  }
+
+  return interface_data->templ.Get(env->isolate());
+}
+
+
+}  // namespace testing
+}  // namespace bindings
+}  // namespace cobalt
+
+
diff --git a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_garbage_collection_test_interface.h b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_garbage_collection_test_interface.h
new file mode 100644
index 0000000..5ede33a
--- /dev/null
+++ b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_garbage_collection_test_interface.h
@@ -0,0 +1,50 @@
+
+// Copyright 2017 Google Inc. All Rights Reserved.
+//
+// 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.
+
+// clang-format off
+
+// This file has been auto-generated by bindings/code_generator_cobalt.py. DO NOT MODIFY!
+// Auto-generated from template: bindings/v8c/templates/interface.h.template
+
+#ifndef V8cGarbageCollectionTestInterface_h
+#define V8cGarbageCollectionTestInterface_h
+
+#include "base/hash_tables.h"
+#include "base/lazy_instance.h"
+#include "base/memory/ref_counted.h"
+#include "base/threading/thread_checker.h"
+#include "cobalt/base/polymorphic_downcast.h"
+#include "cobalt/script/wrappable.h"
+#include "cobalt/bindings/testing/garbage_collection_test_interface.h"
+
+#include "cobalt/script/v8c/v8c_global_environment.h"
+#include "v8/include/v8.h"
+
+namespace cobalt {
+namespace bindings {
+namespace testing {
+
+class V8cGarbageCollectionTestInterface {
+ public:
+  static v8::Local<v8::Object> CreateWrapper(script::v8c::V8cGlobalEnvironment* env, const scoped_refptr<script::Wrappable>& wrappable);
+  static v8::Local<v8::FunctionTemplate> CreateTemplate(script::v8c::V8cGlobalEnvironment* env);
+  // TODO: Add |GetInterfaceObject|.
+};
+
+}  // namespace testing
+}  // namespace bindings
+}  // namespace cobalt
+
+#endif  // V8cGarbageCollectionTestInterface_h
diff --git a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_global_interface_parent.cc b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_global_interface_parent.cc
new file mode 100644
index 0000000..9e15781
--- /dev/null
+++ b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_global_interface_parent.cc
@@ -0,0 +1,177 @@
+
+
+// Copyright 2017 Google Inc. All Rights Reserved.
+//
+// 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.
+
+// clang-format off
+
+// This file has been auto-generated by bindings/code_generator_cobalt.py. DO NOT MODIFY!
+// Auto-generated from template: bindings/v8c/templates/interface.cc.template
+
+#include "cobalt/bindings/testing/v8c_global_interface_parent.h"
+
+#include "base/debug/trace_event.h"
+#include "cobalt/base/polymorphic_downcast.h"
+#include "cobalt/script/global_environment.h"
+#include "cobalt/script/script_value.h"
+#include "cobalt/script/value_handle.h"
+
+#include "v8c_gen_type_conversion.h"
+
+#include "cobalt/script/callback_interface_traits.h"
+#include "cobalt/script/v8c/callback_function_conversion.h"
+#include "cobalt/script/v8c/conversion_helpers.h"
+#include "cobalt/script/v8c/native_promise.h"
+#include "cobalt/script/v8c/type_traits.h"
+#include "cobalt/script/v8c/v8c_callback_function.h"
+#include "cobalt/script/v8c/v8c_callback_interface_holder.h"
+#include "cobalt/script/v8c/v8c_exception_state.h"
+#include "cobalt/script/v8c/v8c_global_environment.h"
+#include "cobalt/script/v8c/v8c_value_handle.h"
+#include "cobalt/script/v8c/wrapper_private.h"
+#include "v8/include/v8.h"
+
+
+namespace {
+using cobalt::bindings::testing::GlobalInterfaceParent;
+using cobalt::bindings::testing::V8cGlobalInterfaceParent;
+using cobalt::script::CallbackInterfaceTraits;
+using cobalt::script::GlobalEnvironment;
+using cobalt::script::ScriptValue;
+using cobalt::script::ValueHandle;
+using cobalt::script::ValueHandle;
+using cobalt::script::ValueHandleHolder;
+using cobalt::script::Wrappable;
+
+using cobalt::script::v8c::FromJSValue;
+using cobalt::script::v8c::InterfaceData;
+using cobalt::script::v8c::kConversionFlagClamped;
+using cobalt::script::v8c::kConversionFlagNullable;
+using cobalt::script::v8c::kConversionFlagRestricted;
+using cobalt::script::v8c::kConversionFlagTreatNullAsEmptyString;
+using cobalt::script::v8c::kConversionFlagTreatUndefinedAsEmptyString;
+using cobalt::script::v8c::kNoConversionFlags;
+using cobalt::script::v8c::TypeTraits;
+using cobalt::script::v8c::V8cExceptionState;
+using cobalt::script::v8c::V8cGlobalEnvironment;
+using cobalt::script::v8c::WrapperFactory;
+using cobalt::script::v8c::WrapperPrivate;
+
+v8::Local<v8::Object> DummyFunctor(V8cGlobalEnvironment*, const scoped_refptr<Wrappable>&) {
+  NOTIMPLEMENTED();
+  return {};
+}
+
+}  // namespace
+
+namespace cobalt {
+namespace bindings {
+namespace testing {
+
+
+namespace {
+
+void GlobalInterfaceParentConstructor(const v8::FunctionCallbackInfo<v8::Value>& args) {
+  NOTIMPLEMENTED();
+  if (!args.IsConstructCall()) {
+    // TODO: Probably throw something here...
+    return;
+  }
+
+  DCHECK(args.This()->InternalFieldCount() == 1);
+  args.This()->SetInternalField(0, v8::External::New(args.GetIsolate(), nullptr));
+  args.GetReturnValue().Set(args.This());
+}
+
+
+void DummyFunction(const v8::FunctionCallbackInfo<v8::Value>& info) {
+  LOG(INFO) << __func__;
+}
+
+void InitializeTemplate(
+  V8cGlobalEnvironment* env,
+  InterfaceData* interface_data) {
+  v8::Isolate* isolate = env->isolate();
+  v8::Local<v8::FunctionTemplate> function_template = v8::FunctionTemplate::New(
+    isolate);
+  function_template->SetClassName(
+    v8::String::NewFromUtf8(isolate, "GlobalInterfaceParent",
+        v8::NewStringType::kInternalized).ToLocalChecked());
+  v8::Local<v8::ObjectTemplate> instance_template = function_template->InstanceTemplate();
+  instance_template->SetInternalFieldCount(1);
+
+  v8::Local<v8::ObjectTemplate> prototype_template = function_template->PrototypeTemplate();
+  prototype_template->SetInternalFieldCount(1);
+
+
+  instance_template->Set(
+      v8::String::NewFromUtf8(
+          isolate,
+          "parentOperation",
+          v8::NewStringType::kInternalized).ToLocalChecked(),
+      v8::FunctionTemplate::New(isolate, DummyFunction)
+  );
+
+  interface_data->templ.Set(env->isolate(), function_template);
+}
+
+inline InterfaceData* GetInterfaceData(V8cGlobalEnvironment* env) {
+  const int kInterfaceUniqueId = 24;
+  // By convention, the |V8cGlobalEnvironment| that we are associated with
+  // will hold our |InterfaceData| at index |kInterfaceUniqueId|, as we asked
+  // for it to be there in the first place, and could not have conflicted with
+  // any other interface.
+  return env->GetInterfaceData(kInterfaceUniqueId);
+}
+
+}  // namespace
+
+v8::Local<v8::Object> V8cGlobalInterfaceParent::CreateWrapper(V8cGlobalEnvironment* env, const scoped_refptr<Wrappable>& wrappable) {
+  v8::Isolate* isolate = env->isolate();
+  v8::Isolate::Scope isolate_scope(isolate);
+  v8::EscapableHandleScope handle_scope(isolate);
+  v8::Local<v8::Context> context = env->context();
+  v8::Context::Scope scope(context);
+
+  InterfaceData* interface_data = GetInterfaceData(env);
+  if (interface_data->templ.IsEmpty()) {
+    InitializeTemplate(env, interface_data);
+  }
+  DCHECK(!interface_data->templ.IsEmpty());
+
+  v8::Local<v8::FunctionTemplate> function_template = interface_data->templ.Get(isolate);
+  DCHECK(function_template->InstanceTemplate()->InternalFieldCount() == 1);
+  v8::Local<v8::Object> object = function_template->InstanceTemplate()->NewInstance(context).ToLocalChecked();
+  DCHECK(object->InternalFieldCount() == 1);
+
+  // |WrapperPrivate|'s lifetime will be managed by V8.
+  new WrapperPrivate(isolate, wrappable, object);
+  return handle_scope.Escape(object);
+}
+
+v8::Local<v8::FunctionTemplate> V8cGlobalInterfaceParent::CreateTemplate(V8cGlobalEnvironment* env) {
+  InterfaceData* interface_data = GetInterfaceData(env);
+  if (interface_data->templ.IsEmpty()) {
+    InitializeTemplate(env, interface_data);
+  }
+
+  return interface_data->templ.Get(env->isolate());
+}
+
+
+}  // namespace testing
+}  // namespace bindings
+}  // namespace cobalt
+
+
diff --git a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_global_interface_parent.h b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_global_interface_parent.h
new file mode 100644
index 0000000..1bc768e
--- /dev/null
+++ b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_global_interface_parent.h
@@ -0,0 +1,50 @@
+
+// Copyright 2017 Google Inc. All Rights Reserved.
+//
+// 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.
+
+// clang-format off
+
+// This file has been auto-generated by bindings/code_generator_cobalt.py. DO NOT MODIFY!
+// Auto-generated from template: bindings/v8c/templates/interface.h.template
+
+#ifndef V8cGlobalInterfaceParent_h
+#define V8cGlobalInterfaceParent_h
+
+#include "base/hash_tables.h"
+#include "base/lazy_instance.h"
+#include "base/memory/ref_counted.h"
+#include "base/threading/thread_checker.h"
+#include "cobalt/base/polymorphic_downcast.h"
+#include "cobalt/script/wrappable.h"
+#include "cobalt/bindings/testing/global_interface_parent.h"
+
+#include "cobalt/script/v8c/v8c_global_environment.h"
+#include "v8/include/v8.h"
+
+namespace cobalt {
+namespace bindings {
+namespace testing {
+
+class V8cGlobalInterfaceParent {
+ public:
+  static v8::Local<v8::Object> CreateWrapper(script::v8c::V8cGlobalEnvironment* env, const scoped_refptr<script::Wrappable>& wrappable);
+  static v8::Local<v8::FunctionTemplate> CreateTemplate(script::v8c::V8cGlobalEnvironment* env);
+  // TODO: Add |GetInterfaceObject|.
+};
+
+}  // namespace testing
+}  // namespace bindings
+}  // namespace cobalt
+
+#endif  // V8cGlobalInterfaceParent_h
diff --git a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_indexed_getter_interface.cc b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_indexed_getter_interface.cc
new file mode 100644
index 0000000..a115c90
--- /dev/null
+++ b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_indexed_getter_interface.cc
@@ -0,0 +1,212 @@
+
+
+// Copyright 2017 Google Inc. All Rights Reserved.
+//
+// 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.
+
+// clang-format off
+
+// This file has been auto-generated by bindings/code_generator_cobalt.py. DO NOT MODIFY!
+// Auto-generated from template: bindings/v8c/templates/interface.cc.template
+
+#include "cobalt/bindings/testing/v8c_indexed_getter_interface.h"
+
+#include "base/debug/trace_event.h"
+#include "cobalt/base/polymorphic_downcast.h"
+#include "cobalt/script/global_environment.h"
+#include "cobalt/script/script_value.h"
+#include "cobalt/script/value_handle.h"
+
+#include "v8c_gen_type_conversion.h"
+
+#include "cobalt/script/callback_interface_traits.h"
+#include "cobalt/script/v8c/callback_function_conversion.h"
+#include "cobalt/script/v8c/conversion_helpers.h"
+#include "cobalt/script/v8c/native_promise.h"
+#include "cobalt/script/v8c/type_traits.h"
+#include "cobalt/script/v8c/v8c_callback_function.h"
+#include "cobalt/script/v8c/v8c_callback_interface_holder.h"
+#include "cobalt/script/v8c/v8c_exception_state.h"
+#include "cobalt/script/v8c/v8c_global_environment.h"
+#include "cobalt/script/v8c/v8c_value_handle.h"
+#include "cobalt/script/v8c/wrapper_private.h"
+#include "v8/include/v8.h"
+
+
+namespace {
+using cobalt::bindings::testing::IndexedGetterInterface;
+using cobalt::bindings::testing::V8cIndexedGetterInterface;
+using cobalt::script::CallbackInterfaceTraits;
+using cobalt::script::GlobalEnvironment;
+using cobalt::script::ScriptValue;
+using cobalt::script::ValueHandle;
+using cobalt::script::ValueHandle;
+using cobalt::script::ValueHandleHolder;
+using cobalt::script::Wrappable;
+
+using cobalt::script::v8c::FromJSValue;
+using cobalt::script::v8c::InterfaceData;
+using cobalt::script::v8c::kConversionFlagClamped;
+using cobalt::script::v8c::kConversionFlagNullable;
+using cobalt::script::v8c::kConversionFlagRestricted;
+using cobalt::script::v8c::kConversionFlagTreatNullAsEmptyString;
+using cobalt::script::v8c::kConversionFlagTreatUndefinedAsEmptyString;
+using cobalt::script::v8c::kNoConversionFlags;
+using cobalt::script::v8c::TypeTraits;
+using cobalt::script::v8c::V8cExceptionState;
+using cobalt::script::v8c::V8cGlobalEnvironment;
+using cobalt::script::v8c::WrapperFactory;
+using cobalt::script::v8c::WrapperPrivate;
+
+v8::Local<v8::Object> DummyFunctor(V8cGlobalEnvironment*, const scoped_refptr<Wrappable>&) {
+  NOTIMPLEMENTED();
+  return {};
+}
+
+}  // namespace
+
+namespace cobalt {
+namespace bindings {
+namespace testing {
+
+
+namespace {
+
+void IndexedGetterInterfaceConstructor(const v8::FunctionCallbackInfo<v8::Value>& args) {
+  NOTIMPLEMENTED();
+  if (!args.IsConstructCall()) {
+    // TODO: Probably throw something here...
+    return;
+  }
+
+  DCHECK(args.This()->InternalFieldCount() == 1);
+  args.This()->SetInternalField(0, v8::External::New(args.GetIsolate(), nullptr));
+  args.GetReturnValue().Set(args.This());
+}
+
+
+void v8cGet_length(
+  v8::Local<v8::String> property,
+  const v8::PropertyCallbackInfo<v8::Value>& info)
+{
+  NOTIMPLEMENTED();
+
+  v8::Local<v8::External> external = v8::Local<v8::External>::Cast(info.Holder()->GetInternalField(0));
+  WrapperPrivate* wrapper_private = static_cast<WrapperPrivate*>(external->Value());
+  IndexedGetterInterface* impl = static_cast<IndexedGetterInterface*>(wrapper_private->wrappable<IndexedGetterInterface>());
+
+  v8::Local<v8::Value> result_value;
+}
+
+
+
+void DummyFunction(const v8::FunctionCallbackInfo<v8::Value>& info) {
+  LOG(INFO) << __func__;
+}
+
+void InitializeTemplate(
+  V8cGlobalEnvironment* env,
+  InterfaceData* interface_data) {
+  v8::Isolate* isolate = env->isolate();
+  v8::Local<v8::FunctionTemplate> function_template = v8::FunctionTemplate::New(
+    isolate);
+  function_template->SetClassName(
+    v8::String::NewFromUtf8(isolate, "IndexedGetterInterface",
+        v8::NewStringType::kInternalized).ToLocalChecked());
+  v8::Local<v8::ObjectTemplate> instance_template = function_template->InstanceTemplate();
+  instance_template->SetInternalFieldCount(1);
+
+  v8::Local<v8::ObjectTemplate> prototype_template = function_template->PrototypeTemplate();
+  prototype_template->SetInternalFieldCount(1);
+
+  instance_template->SetAccessor(
+    v8::String::NewFromUtf8(isolate, "length",
+                              v8::NewStringType::kInternalized)
+          .ToLocalChecked(),
+    v8cGet_length
+  );
+
+  instance_template->Set(
+      v8::String::NewFromUtf8(
+          isolate,
+          "indexedDeleter",
+          v8::NewStringType::kInternalized).ToLocalChecked(),
+      v8::FunctionTemplate::New(isolate, DummyFunction)
+  );
+  instance_template->Set(
+      v8::String::NewFromUtf8(
+          isolate,
+          "indexedGetter",
+          v8::NewStringType::kInternalized).ToLocalChecked(),
+      v8::FunctionTemplate::New(isolate, DummyFunction)
+  );
+  instance_template->Set(
+      v8::String::NewFromUtf8(
+          isolate,
+          "indexedSetter",
+          v8::NewStringType::kInternalized).ToLocalChecked(),
+      v8::FunctionTemplate::New(isolate, DummyFunction)
+  );
+
+  interface_data->templ.Set(env->isolate(), function_template);
+}
+
+inline InterfaceData* GetInterfaceData(V8cGlobalEnvironment* env) {
+  const int kInterfaceUniqueId = 26;
+  // By convention, the |V8cGlobalEnvironment| that we are associated with
+  // will hold our |InterfaceData| at index |kInterfaceUniqueId|, as we asked
+  // for it to be there in the first place, and could not have conflicted with
+  // any other interface.
+  return env->GetInterfaceData(kInterfaceUniqueId);
+}
+
+}  // namespace
+
+v8::Local<v8::Object> V8cIndexedGetterInterface::CreateWrapper(V8cGlobalEnvironment* env, const scoped_refptr<Wrappable>& wrappable) {
+  v8::Isolate* isolate = env->isolate();
+  v8::Isolate::Scope isolate_scope(isolate);
+  v8::EscapableHandleScope handle_scope(isolate);
+  v8::Local<v8::Context> context = env->context();
+  v8::Context::Scope scope(context);
+
+  InterfaceData* interface_data = GetInterfaceData(env);
+  if (interface_data->templ.IsEmpty()) {
+    InitializeTemplate(env, interface_data);
+  }
+  DCHECK(!interface_data->templ.IsEmpty());
+
+  v8::Local<v8::FunctionTemplate> function_template = interface_data->templ.Get(isolate);
+  DCHECK(function_template->InstanceTemplate()->InternalFieldCount() == 1);
+  v8::Local<v8::Object> object = function_template->InstanceTemplate()->NewInstance(context).ToLocalChecked();
+  DCHECK(object->InternalFieldCount() == 1);
+
+  // |WrapperPrivate|'s lifetime will be managed by V8.
+  new WrapperPrivate(isolate, wrappable, object);
+  return handle_scope.Escape(object);
+}
+
+v8::Local<v8::FunctionTemplate> V8cIndexedGetterInterface::CreateTemplate(V8cGlobalEnvironment* env) {
+  InterfaceData* interface_data = GetInterfaceData(env);
+  if (interface_data->templ.IsEmpty()) {
+    InitializeTemplate(env, interface_data);
+  }
+
+  return interface_data->templ.Get(env->isolate());
+}
+
+
+}  // namespace testing
+}  // namespace bindings
+}  // namespace cobalt
+
+
diff --git a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_indexed_getter_interface.h b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_indexed_getter_interface.h
new file mode 100644
index 0000000..d553d00
--- /dev/null
+++ b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_indexed_getter_interface.h
@@ -0,0 +1,50 @@
+
+// Copyright 2017 Google Inc. All Rights Reserved.
+//
+// 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.
+
+// clang-format off
+
+// This file has been auto-generated by bindings/code_generator_cobalt.py. DO NOT MODIFY!
+// Auto-generated from template: bindings/v8c/templates/interface.h.template
+
+#ifndef V8cIndexedGetterInterface_h
+#define V8cIndexedGetterInterface_h
+
+#include "base/hash_tables.h"
+#include "base/lazy_instance.h"
+#include "base/memory/ref_counted.h"
+#include "base/threading/thread_checker.h"
+#include "cobalt/base/polymorphic_downcast.h"
+#include "cobalt/script/wrappable.h"
+#include "cobalt/bindings/testing/indexed_getter_interface.h"
+
+#include "cobalt/script/v8c/v8c_global_environment.h"
+#include "v8/include/v8.h"
+
+namespace cobalt {
+namespace bindings {
+namespace testing {
+
+class V8cIndexedGetterInterface {
+ public:
+  static v8::Local<v8::Object> CreateWrapper(script::v8c::V8cGlobalEnvironment* env, const scoped_refptr<script::Wrappable>& wrappable);
+  static v8::Local<v8::FunctionTemplate> CreateTemplate(script::v8c::V8cGlobalEnvironment* env);
+  // TODO: Add |GetInterfaceObject|.
+};
+
+}  // namespace testing
+}  // namespace bindings
+}  // namespace cobalt
+
+#endif  // V8cIndexedGetterInterface_h
diff --git a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_interface_with_any.cc b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_interface_with_any.cc
new file mode 100644
index 0000000..6f5212a
--- /dev/null
+++ b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_interface_with_any.cc
@@ -0,0 +1,184 @@
+
+
+// Copyright 2017 Google Inc. All Rights Reserved.
+//
+// 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.
+
+// clang-format off
+
+// This file has been auto-generated by bindings/code_generator_cobalt.py. DO NOT MODIFY!
+// Auto-generated from template: bindings/v8c/templates/interface.cc.template
+
+#include "cobalt/bindings/testing/v8c_interface_with_any.h"
+
+#include "base/debug/trace_event.h"
+#include "cobalt/base/polymorphic_downcast.h"
+#include "cobalt/script/global_environment.h"
+#include "cobalt/script/script_value.h"
+#include "cobalt/script/value_handle.h"
+
+#include "v8c_gen_type_conversion.h"
+
+#include "cobalt/script/callback_interface_traits.h"
+#include "cobalt/script/v8c/callback_function_conversion.h"
+#include "cobalt/script/v8c/conversion_helpers.h"
+#include "cobalt/script/v8c/native_promise.h"
+#include "cobalt/script/v8c/type_traits.h"
+#include "cobalt/script/v8c/v8c_callback_function.h"
+#include "cobalt/script/v8c/v8c_callback_interface_holder.h"
+#include "cobalt/script/v8c/v8c_exception_state.h"
+#include "cobalt/script/v8c/v8c_global_environment.h"
+#include "cobalt/script/v8c/v8c_value_handle.h"
+#include "cobalt/script/v8c/wrapper_private.h"
+#include "v8/include/v8.h"
+
+
+namespace {
+using cobalt::bindings::testing::InterfaceWithAny;
+using cobalt::bindings::testing::V8cInterfaceWithAny;
+using cobalt::script::CallbackInterfaceTraits;
+using cobalt::script::GlobalEnvironment;
+using cobalt::script::ScriptValue;
+using cobalt::script::ValueHandle;
+using cobalt::script::ValueHandle;
+using cobalt::script::ValueHandleHolder;
+using cobalt::script::Wrappable;
+
+using cobalt::script::v8c::FromJSValue;
+using cobalt::script::v8c::InterfaceData;
+using cobalt::script::v8c::kConversionFlagClamped;
+using cobalt::script::v8c::kConversionFlagNullable;
+using cobalt::script::v8c::kConversionFlagRestricted;
+using cobalt::script::v8c::kConversionFlagTreatNullAsEmptyString;
+using cobalt::script::v8c::kConversionFlagTreatUndefinedAsEmptyString;
+using cobalt::script::v8c::kNoConversionFlags;
+using cobalt::script::v8c::TypeTraits;
+using cobalt::script::v8c::V8cExceptionState;
+using cobalt::script::v8c::V8cGlobalEnvironment;
+using cobalt::script::v8c::WrapperFactory;
+using cobalt::script::v8c::WrapperPrivate;
+
+v8::Local<v8::Object> DummyFunctor(V8cGlobalEnvironment*, const scoped_refptr<Wrappable>&) {
+  NOTIMPLEMENTED();
+  return {};
+}
+
+}  // namespace
+
+namespace cobalt {
+namespace bindings {
+namespace testing {
+
+
+namespace {
+
+void InterfaceWithAnyConstructor(const v8::FunctionCallbackInfo<v8::Value>& args) {
+  NOTIMPLEMENTED();
+  if (!args.IsConstructCall()) {
+    // TODO: Probably throw something here...
+    return;
+  }
+
+  DCHECK(args.This()->InternalFieldCount() == 1);
+  args.This()->SetInternalField(0, v8::External::New(args.GetIsolate(), nullptr));
+  args.GetReturnValue().Set(args.This());
+}
+
+
+void DummyFunction(const v8::FunctionCallbackInfo<v8::Value>& info) {
+  LOG(INFO) << __func__;
+}
+
+void InitializeTemplate(
+  V8cGlobalEnvironment* env,
+  InterfaceData* interface_data) {
+  v8::Isolate* isolate = env->isolate();
+  v8::Local<v8::FunctionTemplate> function_template = v8::FunctionTemplate::New(
+    isolate);
+  function_template->SetClassName(
+    v8::String::NewFromUtf8(isolate, "InterfaceWithAny",
+        v8::NewStringType::kInternalized).ToLocalChecked());
+  v8::Local<v8::ObjectTemplate> instance_template = function_template->InstanceTemplate();
+  instance_template->SetInternalFieldCount(1);
+
+  v8::Local<v8::ObjectTemplate> prototype_template = function_template->PrototypeTemplate();
+  prototype_template->SetInternalFieldCount(1);
+
+
+  instance_template->Set(
+      v8::String::NewFromUtf8(
+          isolate,
+          "getAny",
+          v8::NewStringType::kInternalized).ToLocalChecked(),
+      v8::FunctionTemplate::New(isolate, DummyFunction)
+  );
+  instance_template->Set(
+      v8::String::NewFromUtf8(
+          isolate,
+          "setAny",
+          v8::NewStringType::kInternalized).ToLocalChecked(),
+      v8::FunctionTemplate::New(isolate, DummyFunction)
+  );
+
+  interface_data->templ.Set(env->isolate(), function_template);
+}
+
+inline InterfaceData* GetInterfaceData(V8cGlobalEnvironment* env) {
+  const int kInterfaceUniqueId = 27;
+  // By convention, the |V8cGlobalEnvironment| that we are associated with
+  // will hold our |InterfaceData| at index |kInterfaceUniqueId|, as we asked
+  // for it to be there in the first place, and could not have conflicted with
+  // any other interface.
+  return env->GetInterfaceData(kInterfaceUniqueId);
+}
+
+}  // namespace
+
+v8::Local<v8::Object> V8cInterfaceWithAny::CreateWrapper(V8cGlobalEnvironment* env, const scoped_refptr<Wrappable>& wrappable) {
+  v8::Isolate* isolate = env->isolate();
+  v8::Isolate::Scope isolate_scope(isolate);
+  v8::EscapableHandleScope handle_scope(isolate);
+  v8::Local<v8::Context> context = env->context();
+  v8::Context::Scope scope(context);
+
+  InterfaceData* interface_data = GetInterfaceData(env);
+  if (interface_data->templ.IsEmpty()) {
+    InitializeTemplate(env, interface_data);
+  }
+  DCHECK(!interface_data->templ.IsEmpty());
+
+  v8::Local<v8::FunctionTemplate> function_template = interface_data->templ.Get(isolate);
+  DCHECK(function_template->InstanceTemplate()->InternalFieldCount() == 1);
+  v8::Local<v8::Object> object = function_template->InstanceTemplate()->NewInstance(context).ToLocalChecked();
+  DCHECK(object->InternalFieldCount() == 1);
+
+  // |WrapperPrivate|'s lifetime will be managed by V8.
+  new WrapperPrivate(isolate, wrappable, object);
+  return handle_scope.Escape(object);
+}
+
+v8::Local<v8::FunctionTemplate> V8cInterfaceWithAny::CreateTemplate(V8cGlobalEnvironment* env) {
+  InterfaceData* interface_data = GetInterfaceData(env);
+  if (interface_data->templ.IsEmpty()) {
+    InitializeTemplate(env, interface_data);
+  }
+
+  return interface_data->templ.Get(env->isolate());
+}
+
+
+}  // namespace testing
+}  // namespace bindings
+}  // namespace cobalt
+
+
diff --git a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_interface_with_any.h b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_interface_with_any.h
new file mode 100644
index 0000000..7c75a6b
--- /dev/null
+++ b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_interface_with_any.h
@@ -0,0 +1,50 @@
+
+// Copyright 2017 Google Inc. All Rights Reserved.
+//
+// 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.
+
+// clang-format off
+
+// This file has been auto-generated by bindings/code_generator_cobalt.py. DO NOT MODIFY!
+// Auto-generated from template: bindings/v8c/templates/interface.h.template
+
+#ifndef V8cInterfaceWithAny_h
+#define V8cInterfaceWithAny_h
+
+#include "base/hash_tables.h"
+#include "base/lazy_instance.h"
+#include "base/memory/ref_counted.h"
+#include "base/threading/thread_checker.h"
+#include "cobalt/base/polymorphic_downcast.h"
+#include "cobalt/script/wrappable.h"
+#include "cobalt/bindings/testing/interface_with_any.h"
+
+#include "cobalt/script/v8c/v8c_global_environment.h"
+#include "v8/include/v8.h"
+
+namespace cobalt {
+namespace bindings {
+namespace testing {
+
+class V8cInterfaceWithAny {
+ public:
+  static v8::Local<v8::Object> CreateWrapper(script::v8c::V8cGlobalEnvironment* env, const scoped_refptr<script::Wrappable>& wrappable);
+  static v8::Local<v8::FunctionTemplate> CreateTemplate(script::v8c::V8cGlobalEnvironment* env);
+  // TODO: Add |GetInterfaceObject|.
+};
+
+}  // namespace testing
+}  // namespace bindings
+}  // namespace cobalt
+
+#endif  // V8cInterfaceWithAny_h
diff --git a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_interface_with_any_dictionary.cc b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_interface_with_any_dictionary.cc
new file mode 100644
index 0000000..4a360cc
--- /dev/null
+++ b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_interface_with_any_dictionary.cc
@@ -0,0 +1,198 @@
+
+
+// Copyright 2017 Google Inc. All Rights Reserved.
+//
+// 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.
+
+// clang-format off
+
+// This file has been auto-generated by bindings/code_generator_cobalt.py. DO NOT MODIFY!
+// Auto-generated from template: bindings/v8c/templates/interface.cc.template
+
+#include "cobalt/bindings/testing/v8c_interface_with_any_dictionary.h"
+
+#include "base/debug/trace_event.h"
+#include "cobalt/base/polymorphic_downcast.h"
+#include "cobalt/script/global_environment.h"
+#include "cobalt/script/script_value.h"
+#include "cobalt/script/value_handle.h"
+
+#include "v8c_gen_type_conversion.h"
+
+#include "cobalt/script/callback_interface_traits.h"
+#include "cobalt/script/v8c/callback_function_conversion.h"
+#include "cobalt/script/v8c/conversion_helpers.h"
+#include "cobalt/script/v8c/native_promise.h"
+#include "cobalt/script/v8c/type_traits.h"
+#include "cobalt/script/v8c/v8c_callback_function.h"
+#include "cobalt/script/v8c/v8c_callback_interface_holder.h"
+#include "cobalt/script/v8c/v8c_exception_state.h"
+#include "cobalt/script/v8c/v8c_global_environment.h"
+#include "cobalt/script/v8c/v8c_value_handle.h"
+#include "cobalt/script/v8c/wrapper_private.h"
+#include "v8/include/v8.h"
+
+
+namespace {
+using cobalt::bindings::testing::InterfaceWithAnyDictionary;
+using cobalt::bindings::testing::V8cInterfaceWithAnyDictionary;
+using cobalt::script::CallbackInterfaceTraits;
+using cobalt::script::GlobalEnvironment;
+using cobalt::script::ScriptValue;
+using cobalt::script::ValueHandle;
+using cobalt::script::ValueHandle;
+using cobalt::script::ValueHandleHolder;
+using cobalt::script::Wrappable;
+
+using cobalt::script::v8c::FromJSValue;
+using cobalt::script::v8c::InterfaceData;
+using cobalt::script::v8c::kConversionFlagClamped;
+using cobalt::script::v8c::kConversionFlagNullable;
+using cobalt::script::v8c::kConversionFlagRestricted;
+using cobalt::script::v8c::kConversionFlagTreatNullAsEmptyString;
+using cobalt::script::v8c::kConversionFlagTreatUndefinedAsEmptyString;
+using cobalt::script::v8c::kNoConversionFlags;
+using cobalt::script::v8c::TypeTraits;
+using cobalt::script::v8c::V8cExceptionState;
+using cobalt::script::v8c::V8cGlobalEnvironment;
+using cobalt::script::v8c::WrapperFactory;
+using cobalt::script::v8c::WrapperPrivate;
+
+v8::Local<v8::Object> DummyFunctor(V8cGlobalEnvironment*, const scoped_refptr<Wrappable>&) {
+  NOTIMPLEMENTED();
+  return {};
+}
+
+}  // namespace
+
+namespace cobalt {
+namespace bindings {
+namespace testing {
+
+
+namespace {
+
+void InterfaceWithAnyDictionaryConstructor(const v8::FunctionCallbackInfo<v8::Value>& args) {
+  NOTIMPLEMENTED();
+  if (!args.IsConstructCall()) {
+    // TODO: Probably throw something here...
+    return;
+  }
+
+  DCHECK(args.This()->InternalFieldCount() == 1);
+  args.This()->SetInternalField(0, v8::External::New(args.GetIsolate(), nullptr));
+  args.GetReturnValue().Set(args.This());
+}
+
+
+void DummyFunction(const v8::FunctionCallbackInfo<v8::Value>& info) {
+  LOG(INFO) << __func__;
+}
+
+void InitializeTemplate(
+  V8cGlobalEnvironment* env,
+  InterfaceData* interface_data) {
+  v8::Isolate* isolate = env->isolate();
+  v8::Local<v8::FunctionTemplate> function_template = v8::FunctionTemplate::New(
+    isolate);
+  function_template->SetClassName(
+    v8::String::NewFromUtf8(isolate, "InterfaceWithAnyDictionary",
+        v8::NewStringType::kInternalized).ToLocalChecked());
+  v8::Local<v8::ObjectTemplate> instance_template = function_template->InstanceTemplate();
+  instance_template->SetInternalFieldCount(1);
+
+  v8::Local<v8::ObjectTemplate> prototype_template = function_template->PrototypeTemplate();
+  prototype_template->SetInternalFieldCount(1);
+
+
+  instance_template->Set(
+      v8::String::NewFromUtf8(
+          isolate,
+          "getAny",
+          v8::NewStringType::kInternalized).ToLocalChecked(),
+      v8::FunctionTemplate::New(isolate, DummyFunction)
+  );
+  instance_template->Set(
+      v8::String::NewFromUtf8(
+          isolate,
+          "hasAny",
+          v8::NewStringType::kInternalized).ToLocalChecked(),
+      v8::FunctionTemplate::New(isolate, DummyFunction)
+  );
+  instance_template->Set(
+      v8::String::NewFromUtf8(
+          isolate,
+          "hasAnyDefault",
+          v8::NewStringType::kInternalized).ToLocalChecked(),
+      v8::FunctionTemplate::New(isolate, DummyFunction)
+  );
+  instance_template->Set(
+      v8::String::NewFromUtf8(
+          isolate,
+          "setAny",
+          v8::NewStringType::kInternalized).ToLocalChecked(),
+      v8::FunctionTemplate::New(isolate, DummyFunction)
+  );
+
+  interface_data->templ.Set(env->isolate(), function_template);
+}
+
+inline InterfaceData* GetInterfaceData(V8cGlobalEnvironment* env) {
+  const int kInterfaceUniqueId = 28;
+  // By convention, the |V8cGlobalEnvironment| that we are associated with
+  // will hold our |InterfaceData| at index |kInterfaceUniqueId|, as we asked
+  // for it to be there in the first place, and could not have conflicted with
+  // any other interface.
+  return env->GetInterfaceData(kInterfaceUniqueId);
+}
+
+}  // namespace
+
+v8::Local<v8::Object> V8cInterfaceWithAnyDictionary::CreateWrapper(V8cGlobalEnvironment* env, const scoped_refptr<Wrappable>& wrappable) {
+  v8::Isolate* isolate = env->isolate();
+  v8::Isolate::Scope isolate_scope(isolate);
+  v8::EscapableHandleScope handle_scope(isolate);
+  v8::Local<v8::Context> context = env->context();
+  v8::Context::Scope scope(context);
+
+  InterfaceData* interface_data = GetInterfaceData(env);
+  if (interface_data->templ.IsEmpty()) {
+    InitializeTemplate(env, interface_data);
+  }
+  DCHECK(!interface_data->templ.IsEmpty());
+
+  v8::Local<v8::FunctionTemplate> function_template = interface_data->templ.Get(isolate);
+  DCHECK(function_template->InstanceTemplate()->InternalFieldCount() == 1);
+  v8::Local<v8::Object> object = function_template->InstanceTemplate()->NewInstance(context).ToLocalChecked();
+  DCHECK(object->InternalFieldCount() == 1);
+
+  // |WrapperPrivate|'s lifetime will be managed by V8.
+  new WrapperPrivate(isolate, wrappable, object);
+  return handle_scope.Escape(object);
+}
+
+v8::Local<v8::FunctionTemplate> V8cInterfaceWithAnyDictionary::CreateTemplate(V8cGlobalEnvironment* env) {
+  InterfaceData* interface_data = GetInterfaceData(env);
+  if (interface_data->templ.IsEmpty()) {
+    InitializeTemplate(env, interface_data);
+  }
+
+  return interface_data->templ.Get(env->isolate());
+}
+
+
+}  // namespace testing
+}  // namespace bindings
+}  // namespace cobalt
+
+
diff --git a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_interface_with_any_dictionary.h b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_interface_with_any_dictionary.h
new file mode 100644
index 0000000..b016bb5
--- /dev/null
+++ b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_interface_with_any_dictionary.h
@@ -0,0 +1,50 @@
+
+// Copyright 2017 Google Inc. All Rights Reserved.
+//
+// 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.
+
+// clang-format off
+
+// This file has been auto-generated by bindings/code_generator_cobalt.py. DO NOT MODIFY!
+// Auto-generated from template: bindings/v8c/templates/interface.h.template
+
+#ifndef V8cInterfaceWithAnyDictionary_h
+#define V8cInterfaceWithAnyDictionary_h
+
+#include "base/hash_tables.h"
+#include "base/lazy_instance.h"
+#include "base/memory/ref_counted.h"
+#include "base/threading/thread_checker.h"
+#include "cobalt/base/polymorphic_downcast.h"
+#include "cobalt/script/wrappable.h"
+#include "cobalt/bindings/testing/interface_with_any_dictionary.h"
+
+#include "cobalt/script/v8c/v8c_global_environment.h"
+#include "v8/include/v8.h"
+
+namespace cobalt {
+namespace bindings {
+namespace testing {
+
+class V8cInterfaceWithAnyDictionary {
+ public:
+  static v8::Local<v8::Object> CreateWrapper(script::v8c::V8cGlobalEnvironment* env, const scoped_refptr<script::Wrappable>& wrappable);
+  static v8::Local<v8::FunctionTemplate> CreateTemplate(script::v8c::V8cGlobalEnvironment* env);
+  // TODO: Add |GetInterfaceObject|.
+};
+
+}  // namespace testing
+}  // namespace bindings
+}  // namespace cobalt
+
+#endif  // V8cInterfaceWithAnyDictionary_h
diff --git a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_interface_with_unsupported_properties.cc b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_interface_with_unsupported_properties.cc
new file mode 100644
index 0000000..ea91e2b
--- /dev/null
+++ b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_interface_with_unsupported_properties.cc
@@ -0,0 +1,191 @@
+
+
+// Copyright 2017 Google Inc. All Rights Reserved.
+//
+// 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.
+
+// clang-format off
+
+// This file has been auto-generated by bindings/code_generator_cobalt.py. DO NOT MODIFY!
+// Auto-generated from template: bindings/v8c/templates/interface.cc.template
+
+#include "cobalt/bindings/testing/v8c_interface_with_unsupported_properties.h"
+
+#include "base/debug/trace_event.h"
+#include "cobalt/base/polymorphic_downcast.h"
+#include "cobalt/script/global_environment.h"
+#include "cobalt/script/script_value.h"
+#include "cobalt/script/value_handle.h"
+
+#include "v8c_gen_type_conversion.h"
+
+#include "cobalt/script/callback_interface_traits.h"
+#include "cobalt/script/v8c/callback_function_conversion.h"
+#include "cobalt/script/v8c/conversion_helpers.h"
+#include "cobalt/script/v8c/native_promise.h"
+#include "cobalt/script/v8c/type_traits.h"
+#include "cobalt/script/v8c/v8c_callback_function.h"
+#include "cobalt/script/v8c/v8c_callback_interface_holder.h"
+#include "cobalt/script/v8c/v8c_exception_state.h"
+#include "cobalt/script/v8c/v8c_global_environment.h"
+#include "cobalt/script/v8c/v8c_value_handle.h"
+#include "cobalt/script/v8c/wrapper_private.h"
+#include "v8/include/v8.h"
+
+
+namespace {
+using cobalt::bindings::testing::InterfaceWithUnsupportedProperties;
+using cobalt::bindings::testing::V8cInterfaceWithUnsupportedProperties;
+using cobalt::script::CallbackInterfaceTraits;
+using cobalt::script::GlobalEnvironment;
+using cobalt::script::ScriptValue;
+using cobalt::script::ValueHandle;
+using cobalt::script::ValueHandle;
+using cobalt::script::ValueHandleHolder;
+using cobalt::script::Wrappable;
+
+using cobalt::script::v8c::FromJSValue;
+using cobalt::script::v8c::InterfaceData;
+using cobalt::script::v8c::kConversionFlagClamped;
+using cobalt::script::v8c::kConversionFlagNullable;
+using cobalt::script::v8c::kConversionFlagRestricted;
+using cobalt::script::v8c::kConversionFlagTreatNullAsEmptyString;
+using cobalt::script::v8c::kConversionFlagTreatUndefinedAsEmptyString;
+using cobalt::script::v8c::kNoConversionFlags;
+using cobalt::script::v8c::TypeTraits;
+using cobalt::script::v8c::V8cExceptionState;
+using cobalt::script::v8c::V8cGlobalEnvironment;
+using cobalt::script::v8c::WrapperFactory;
+using cobalt::script::v8c::WrapperPrivate;
+
+v8::Local<v8::Object> DummyFunctor(V8cGlobalEnvironment*, const scoped_refptr<Wrappable>&) {
+  NOTIMPLEMENTED();
+  return {};
+}
+
+}  // namespace
+
+namespace cobalt {
+namespace bindings {
+namespace testing {
+
+
+namespace {
+
+void InterfaceWithUnsupportedPropertiesConstructor(const v8::FunctionCallbackInfo<v8::Value>& args) {
+  NOTIMPLEMENTED();
+  if (!args.IsConstructCall()) {
+    // TODO: Probably throw something here...
+    return;
+  }
+
+  DCHECK(args.This()->InternalFieldCount() == 1);
+  args.This()->SetInternalField(0, v8::External::New(args.GetIsolate(), nullptr));
+  args.GetReturnValue().Set(args.This());
+}
+
+
+void v8cGet_supportedAttribute(
+  v8::Local<v8::String> property,
+  const v8::PropertyCallbackInfo<v8::Value>& info)
+{
+  NOTIMPLEMENTED();
+
+  v8::Local<v8::External> external = v8::Local<v8::External>::Cast(info.Holder()->GetInternalField(0));
+  WrapperPrivate* wrapper_private = static_cast<WrapperPrivate*>(external->Value());
+  InterfaceWithUnsupportedProperties* impl = static_cast<InterfaceWithUnsupportedProperties*>(wrapper_private->wrappable<InterfaceWithUnsupportedProperties>());
+
+  v8::Local<v8::Value> result_value;
+}
+
+
+
+void DummyFunction(const v8::FunctionCallbackInfo<v8::Value>& info) {
+  LOG(INFO) << __func__;
+}
+
+void InitializeTemplate(
+  V8cGlobalEnvironment* env,
+  InterfaceData* interface_data) {
+  v8::Isolate* isolate = env->isolate();
+  v8::Local<v8::FunctionTemplate> function_template = v8::FunctionTemplate::New(
+    isolate);
+  function_template->SetClassName(
+    v8::String::NewFromUtf8(isolate, "InterfaceWithUnsupportedProperties",
+        v8::NewStringType::kInternalized).ToLocalChecked());
+  v8::Local<v8::ObjectTemplate> instance_template = function_template->InstanceTemplate();
+  instance_template->SetInternalFieldCount(1);
+
+  v8::Local<v8::ObjectTemplate> prototype_template = function_template->PrototypeTemplate();
+  prototype_template->SetInternalFieldCount(1);
+
+  instance_template->SetAccessor(
+    v8::String::NewFromUtf8(isolate, "supportedAttribute",
+                              v8::NewStringType::kInternalized)
+          .ToLocalChecked(),
+    v8cGet_supportedAttribute
+  );
+
+
+  interface_data->templ.Set(env->isolate(), function_template);
+}
+
+inline InterfaceData* GetInterfaceData(V8cGlobalEnvironment* env) {
+  const int kInterfaceUniqueId = 29;
+  // By convention, the |V8cGlobalEnvironment| that we are associated with
+  // will hold our |InterfaceData| at index |kInterfaceUniqueId|, as we asked
+  // for it to be there in the first place, and could not have conflicted with
+  // any other interface.
+  return env->GetInterfaceData(kInterfaceUniqueId);
+}
+
+}  // namespace
+
+v8::Local<v8::Object> V8cInterfaceWithUnsupportedProperties::CreateWrapper(V8cGlobalEnvironment* env, const scoped_refptr<Wrappable>& wrappable) {
+  v8::Isolate* isolate = env->isolate();
+  v8::Isolate::Scope isolate_scope(isolate);
+  v8::EscapableHandleScope handle_scope(isolate);
+  v8::Local<v8::Context> context = env->context();
+  v8::Context::Scope scope(context);
+
+  InterfaceData* interface_data = GetInterfaceData(env);
+  if (interface_data->templ.IsEmpty()) {
+    InitializeTemplate(env, interface_data);
+  }
+  DCHECK(!interface_data->templ.IsEmpty());
+
+  v8::Local<v8::FunctionTemplate> function_template = interface_data->templ.Get(isolate);
+  DCHECK(function_template->InstanceTemplate()->InternalFieldCount() == 1);
+  v8::Local<v8::Object> object = function_template->InstanceTemplate()->NewInstance(context).ToLocalChecked();
+  DCHECK(object->InternalFieldCount() == 1);
+
+  // |WrapperPrivate|'s lifetime will be managed by V8.
+  new WrapperPrivate(isolate, wrappable, object);
+  return handle_scope.Escape(object);
+}
+
+v8::Local<v8::FunctionTemplate> V8cInterfaceWithUnsupportedProperties::CreateTemplate(V8cGlobalEnvironment* env) {
+  InterfaceData* interface_data = GetInterfaceData(env);
+  if (interface_data->templ.IsEmpty()) {
+    InitializeTemplate(env, interface_data);
+  }
+
+  return interface_data->templ.Get(env->isolate());
+}
+
+
+}  // namespace testing
+}  // namespace bindings
+}  // namespace cobalt
+
+
diff --git a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_interface_with_unsupported_properties.h b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_interface_with_unsupported_properties.h
new file mode 100644
index 0000000..cac9ae8
--- /dev/null
+++ b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_interface_with_unsupported_properties.h
@@ -0,0 +1,50 @@
+
+// Copyright 2017 Google Inc. All Rights Reserved.
+//
+// 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.
+
+// clang-format off
+
+// This file has been auto-generated by bindings/code_generator_cobalt.py. DO NOT MODIFY!
+// Auto-generated from template: bindings/v8c/templates/interface.h.template
+
+#ifndef V8cInterfaceWithUnsupportedProperties_h
+#define V8cInterfaceWithUnsupportedProperties_h
+
+#include "base/hash_tables.h"
+#include "base/lazy_instance.h"
+#include "base/memory/ref_counted.h"
+#include "base/threading/thread_checker.h"
+#include "cobalt/base/polymorphic_downcast.h"
+#include "cobalt/script/wrappable.h"
+#include "cobalt/bindings/testing/interface_with_unsupported_properties.h"
+
+#include "cobalt/script/v8c/v8c_global_environment.h"
+#include "v8/include/v8.h"
+
+namespace cobalt {
+namespace bindings {
+namespace testing {
+
+class V8cInterfaceWithUnsupportedProperties {
+ public:
+  static v8::Local<v8::Object> CreateWrapper(script::v8c::V8cGlobalEnvironment* env, const scoped_refptr<script::Wrappable>& wrappable);
+  static v8::Local<v8::FunctionTemplate> CreateTemplate(script::v8c::V8cGlobalEnvironment* env);
+  // TODO: Add |GetInterfaceObject|.
+};
+
+}  // namespace testing
+}  // namespace bindings
+}  // namespace cobalt
+
+#endif  // V8cInterfaceWithUnsupportedProperties_h
diff --git a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_named_constructor_interface.cc b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_named_constructor_interface.cc
new file mode 100644
index 0000000..ccb2242
--- /dev/null
+++ b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_named_constructor_interface.cc
@@ -0,0 +1,170 @@
+
+
+// Copyright 2017 Google Inc. All Rights Reserved.
+//
+// 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.
+
+// clang-format off
+
+// This file has been auto-generated by bindings/code_generator_cobalt.py. DO NOT MODIFY!
+// Auto-generated from template: bindings/v8c/templates/interface.cc.template
+
+#include "cobalt/bindings/testing/v8c_named_constructor_interface.h"
+
+#include "base/debug/trace_event.h"
+#include "cobalt/base/polymorphic_downcast.h"
+#include "cobalt/script/global_environment.h"
+#include "cobalt/script/script_value.h"
+#include "cobalt/script/value_handle.h"
+
+#include "v8c_gen_type_conversion.h"
+
+#include "cobalt/script/callback_interface_traits.h"
+#include "cobalt/script/v8c/callback_function_conversion.h"
+#include "cobalt/script/v8c/conversion_helpers.h"
+#include "cobalt/script/v8c/native_promise.h"
+#include "cobalt/script/v8c/type_traits.h"
+#include "cobalt/script/v8c/v8c_callback_function.h"
+#include "cobalt/script/v8c/v8c_callback_interface_holder.h"
+#include "cobalt/script/v8c/v8c_exception_state.h"
+#include "cobalt/script/v8c/v8c_global_environment.h"
+#include "cobalt/script/v8c/v8c_value_handle.h"
+#include "cobalt/script/v8c/wrapper_private.h"
+#include "v8/include/v8.h"
+
+
+namespace {
+using cobalt::bindings::testing::NamedConstructorInterface;
+using cobalt::bindings::testing::V8cNamedConstructorInterface;
+using cobalt::script::CallbackInterfaceTraits;
+using cobalt::script::GlobalEnvironment;
+using cobalt::script::ScriptValue;
+using cobalt::script::ValueHandle;
+using cobalt::script::ValueHandle;
+using cobalt::script::ValueHandleHolder;
+using cobalt::script::Wrappable;
+
+using cobalt::script::v8c::FromJSValue;
+using cobalt::script::v8c::InterfaceData;
+using cobalt::script::v8c::kConversionFlagClamped;
+using cobalt::script::v8c::kConversionFlagNullable;
+using cobalt::script::v8c::kConversionFlagRestricted;
+using cobalt::script::v8c::kConversionFlagTreatNullAsEmptyString;
+using cobalt::script::v8c::kConversionFlagTreatUndefinedAsEmptyString;
+using cobalt::script::v8c::kNoConversionFlags;
+using cobalt::script::v8c::TypeTraits;
+using cobalt::script::v8c::V8cExceptionState;
+using cobalt::script::v8c::V8cGlobalEnvironment;
+using cobalt::script::v8c::WrapperFactory;
+using cobalt::script::v8c::WrapperPrivate;
+
+v8::Local<v8::Object> DummyFunctor(V8cGlobalEnvironment*, const scoped_refptr<Wrappable>&) {
+  NOTIMPLEMENTED();
+  return {};
+}
+
+}  // namespace
+
+namespace cobalt {
+namespace bindings {
+namespace testing {
+
+
+namespace {
+
+void NamedConstructorInterfaceConstructor(const v8::FunctionCallbackInfo<v8::Value>& args) {
+  NOTIMPLEMENTED();
+  if (!args.IsConstructCall()) {
+    // TODO: Probably throw something here...
+    return;
+  }
+
+  DCHECK(args.This()->InternalFieldCount() == 1);
+  args.This()->SetInternalField(0, v8::External::New(args.GetIsolate(), nullptr));
+  args.GetReturnValue().Set(args.This());
+}
+
+
+void DummyFunction(const v8::FunctionCallbackInfo<v8::Value>& info) {
+  LOG(INFO) << __func__;
+}
+
+void InitializeTemplate(
+  V8cGlobalEnvironment* env,
+  InterfaceData* interface_data) {
+  v8::Isolate* isolate = env->isolate();
+  v8::Local<v8::FunctionTemplate> function_template = v8::FunctionTemplate::New(
+    isolate);
+  function_template->SetClassName(
+    v8::String::NewFromUtf8(isolate, "NamedConstructorInterface",
+        v8::NewStringType::kInternalized).ToLocalChecked());
+  v8::Local<v8::ObjectTemplate> instance_template = function_template->InstanceTemplate();
+  instance_template->SetInternalFieldCount(1);
+
+  v8::Local<v8::ObjectTemplate> prototype_template = function_template->PrototypeTemplate();
+  prototype_template->SetInternalFieldCount(1);
+
+
+
+  interface_data->templ.Set(env->isolate(), function_template);
+}
+
+inline InterfaceData* GetInterfaceData(V8cGlobalEnvironment* env) {
+  const int kInterfaceUniqueId = 30;
+  // By convention, the |V8cGlobalEnvironment| that we are associated with
+  // will hold our |InterfaceData| at index |kInterfaceUniqueId|, as we asked
+  // for it to be there in the first place, and could not have conflicted with
+  // any other interface.
+  return env->GetInterfaceData(kInterfaceUniqueId);
+}
+
+}  // namespace
+
+v8::Local<v8::Object> V8cNamedConstructorInterface::CreateWrapper(V8cGlobalEnvironment* env, const scoped_refptr<Wrappable>& wrappable) {
+  v8::Isolate* isolate = env->isolate();
+  v8::Isolate::Scope isolate_scope(isolate);
+  v8::EscapableHandleScope handle_scope(isolate);
+  v8::Local<v8::Context> context = env->context();
+  v8::Context::Scope scope(context);
+
+  InterfaceData* interface_data = GetInterfaceData(env);
+  if (interface_data->templ.IsEmpty()) {
+    InitializeTemplate(env, interface_data);
+  }
+  DCHECK(!interface_data->templ.IsEmpty());
+
+  v8::Local<v8::FunctionTemplate> function_template = interface_data->templ.Get(isolate);
+  DCHECK(function_template->InstanceTemplate()->InternalFieldCount() == 1);
+  v8::Local<v8::Object> object = function_template->InstanceTemplate()->NewInstance(context).ToLocalChecked();
+  DCHECK(object->InternalFieldCount() == 1);
+
+  // |WrapperPrivate|'s lifetime will be managed by V8.
+  new WrapperPrivate(isolate, wrappable, object);
+  return handle_scope.Escape(object);
+}
+
+v8::Local<v8::FunctionTemplate> V8cNamedConstructorInterface::CreateTemplate(V8cGlobalEnvironment* env) {
+  InterfaceData* interface_data = GetInterfaceData(env);
+  if (interface_data->templ.IsEmpty()) {
+    InitializeTemplate(env, interface_data);
+  }
+
+  return interface_data->templ.Get(env->isolate());
+}
+
+
+}  // namespace testing
+}  // namespace bindings
+}  // namespace cobalt
+
+
diff --git a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_named_constructor_interface.h b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_named_constructor_interface.h
new file mode 100644
index 0000000..f871bae
--- /dev/null
+++ b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_named_constructor_interface.h
@@ -0,0 +1,50 @@
+
+// Copyright 2017 Google Inc. All Rights Reserved.
+//
+// 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.
+
+// clang-format off
+
+// This file has been auto-generated by bindings/code_generator_cobalt.py. DO NOT MODIFY!
+// Auto-generated from template: bindings/v8c/templates/interface.h.template
+
+#ifndef V8cNamedConstructorInterface_h
+#define V8cNamedConstructorInterface_h
+
+#include "base/hash_tables.h"
+#include "base/lazy_instance.h"
+#include "base/memory/ref_counted.h"
+#include "base/threading/thread_checker.h"
+#include "cobalt/base/polymorphic_downcast.h"
+#include "cobalt/script/wrappable.h"
+#include "cobalt/bindings/testing/named_constructor_interface.h"
+
+#include "cobalt/script/v8c/v8c_global_environment.h"
+#include "v8/include/v8.h"
+
+namespace cobalt {
+namespace bindings {
+namespace testing {
+
+class V8cNamedConstructorInterface {
+ public:
+  static v8::Local<v8::Object> CreateWrapper(script::v8c::V8cGlobalEnvironment* env, const scoped_refptr<script::Wrappable>& wrappable);
+  static v8::Local<v8::FunctionTemplate> CreateTemplate(script::v8c::V8cGlobalEnvironment* env);
+  // TODO: Add |GetInterfaceObject|.
+};
+
+}  // namespace testing
+}  // namespace bindings
+}  // namespace cobalt
+
+#endif  // V8cNamedConstructorInterface_h
diff --git a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_named_getter_interface.cc b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_named_getter_interface.cc
new file mode 100644
index 0000000..954dec9
--- /dev/null
+++ b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_named_getter_interface.cc
@@ -0,0 +1,191 @@
+
+
+// Copyright 2017 Google Inc. All Rights Reserved.
+//
+// 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.
+
+// clang-format off
+
+// This file has been auto-generated by bindings/code_generator_cobalt.py. DO NOT MODIFY!
+// Auto-generated from template: bindings/v8c/templates/interface.cc.template
+
+#include "cobalt/bindings/testing/v8c_named_getter_interface.h"
+
+#include "base/debug/trace_event.h"
+#include "cobalt/base/polymorphic_downcast.h"
+#include "cobalt/script/global_environment.h"
+#include "cobalt/script/script_value.h"
+#include "cobalt/script/value_handle.h"
+
+#include "v8c_gen_type_conversion.h"
+
+#include "cobalt/script/callback_interface_traits.h"
+#include "cobalt/script/v8c/callback_function_conversion.h"
+#include "cobalt/script/v8c/conversion_helpers.h"
+#include "cobalt/script/v8c/native_promise.h"
+#include "cobalt/script/v8c/type_traits.h"
+#include "cobalt/script/v8c/v8c_callback_function.h"
+#include "cobalt/script/v8c/v8c_callback_interface_holder.h"
+#include "cobalt/script/v8c/v8c_exception_state.h"
+#include "cobalt/script/v8c/v8c_global_environment.h"
+#include "cobalt/script/v8c/v8c_value_handle.h"
+#include "cobalt/script/v8c/wrapper_private.h"
+#include "v8/include/v8.h"
+
+
+namespace {
+using cobalt::bindings::testing::NamedGetterInterface;
+using cobalt::bindings::testing::V8cNamedGetterInterface;
+using cobalt::script::CallbackInterfaceTraits;
+using cobalt::script::GlobalEnvironment;
+using cobalt::script::ScriptValue;
+using cobalt::script::ValueHandle;
+using cobalt::script::ValueHandle;
+using cobalt::script::ValueHandleHolder;
+using cobalt::script::Wrappable;
+
+using cobalt::script::v8c::FromJSValue;
+using cobalt::script::v8c::InterfaceData;
+using cobalt::script::v8c::kConversionFlagClamped;
+using cobalt::script::v8c::kConversionFlagNullable;
+using cobalt::script::v8c::kConversionFlagRestricted;
+using cobalt::script::v8c::kConversionFlagTreatNullAsEmptyString;
+using cobalt::script::v8c::kConversionFlagTreatUndefinedAsEmptyString;
+using cobalt::script::v8c::kNoConversionFlags;
+using cobalt::script::v8c::TypeTraits;
+using cobalt::script::v8c::V8cExceptionState;
+using cobalt::script::v8c::V8cGlobalEnvironment;
+using cobalt::script::v8c::WrapperFactory;
+using cobalt::script::v8c::WrapperPrivate;
+
+v8::Local<v8::Object> DummyFunctor(V8cGlobalEnvironment*, const scoped_refptr<Wrappable>&) {
+  NOTIMPLEMENTED();
+  return {};
+}
+
+}  // namespace
+
+namespace cobalt {
+namespace bindings {
+namespace testing {
+
+
+namespace {
+
+void NamedGetterInterfaceConstructor(const v8::FunctionCallbackInfo<v8::Value>& args) {
+  NOTIMPLEMENTED();
+  if (!args.IsConstructCall()) {
+    // TODO: Probably throw something here...
+    return;
+  }
+
+  DCHECK(args.This()->InternalFieldCount() == 1);
+  args.This()->SetInternalField(0, v8::External::New(args.GetIsolate(), nullptr));
+  args.GetReturnValue().Set(args.This());
+}
+
+
+void DummyFunction(const v8::FunctionCallbackInfo<v8::Value>& info) {
+  LOG(INFO) << __func__;
+}
+
+void InitializeTemplate(
+  V8cGlobalEnvironment* env,
+  InterfaceData* interface_data) {
+  v8::Isolate* isolate = env->isolate();
+  v8::Local<v8::FunctionTemplate> function_template = v8::FunctionTemplate::New(
+    isolate);
+  function_template->SetClassName(
+    v8::String::NewFromUtf8(isolate, "NamedGetterInterface",
+        v8::NewStringType::kInternalized).ToLocalChecked());
+  v8::Local<v8::ObjectTemplate> instance_template = function_template->InstanceTemplate();
+  instance_template->SetInternalFieldCount(1);
+
+  v8::Local<v8::ObjectTemplate> prototype_template = function_template->PrototypeTemplate();
+  prototype_template->SetInternalFieldCount(1);
+
+
+  instance_template->Set(
+      v8::String::NewFromUtf8(
+          isolate,
+          "namedDeleter",
+          v8::NewStringType::kInternalized).ToLocalChecked(),
+      v8::FunctionTemplate::New(isolate, DummyFunction)
+  );
+  instance_template->Set(
+      v8::String::NewFromUtf8(
+          isolate,
+          "namedGetter",
+          v8::NewStringType::kInternalized).ToLocalChecked(),
+      v8::FunctionTemplate::New(isolate, DummyFunction)
+  );
+  instance_template->Set(
+      v8::String::NewFromUtf8(
+          isolate,
+          "namedSetter",
+          v8::NewStringType::kInternalized).ToLocalChecked(),
+      v8::FunctionTemplate::New(isolate, DummyFunction)
+  );
+
+  interface_data->templ.Set(env->isolate(), function_template);
+}
+
+inline InterfaceData* GetInterfaceData(V8cGlobalEnvironment* env) {
+  const int kInterfaceUniqueId = 31;
+  // By convention, the |V8cGlobalEnvironment| that we are associated with
+  // will hold our |InterfaceData| at index |kInterfaceUniqueId|, as we asked
+  // for it to be there in the first place, and could not have conflicted with
+  // any other interface.
+  return env->GetInterfaceData(kInterfaceUniqueId);
+}
+
+}  // namespace
+
+v8::Local<v8::Object> V8cNamedGetterInterface::CreateWrapper(V8cGlobalEnvironment* env, const scoped_refptr<Wrappable>& wrappable) {
+  v8::Isolate* isolate = env->isolate();
+  v8::Isolate::Scope isolate_scope(isolate);
+  v8::EscapableHandleScope handle_scope(isolate);
+  v8::Local<v8::Context> context = env->context();
+  v8::Context::Scope scope(context);
+
+  InterfaceData* interface_data = GetInterfaceData(env);
+  if (interface_data->templ.IsEmpty()) {
+    InitializeTemplate(env, interface_data);
+  }
+  DCHECK(!interface_data->templ.IsEmpty());
+
+  v8::Local<v8::FunctionTemplate> function_template = interface_data->templ.Get(isolate);
+  DCHECK(function_template->InstanceTemplate()->InternalFieldCount() == 1);
+  v8::Local<v8::Object> object = function_template->InstanceTemplate()->NewInstance(context).ToLocalChecked();
+  DCHECK(object->InternalFieldCount() == 1);
+
+  // |WrapperPrivate|'s lifetime will be managed by V8.
+  new WrapperPrivate(isolate, wrappable, object);
+  return handle_scope.Escape(object);
+}
+
+v8::Local<v8::FunctionTemplate> V8cNamedGetterInterface::CreateTemplate(V8cGlobalEnvironment* env) {
+  InterfaceData* interface_data = GetInterfaceData(env);
+  if (interface_data->templ.IsEmpty()) {
+    InitializeTemplate(env, interface_data);
+  }
+
+  return interface_data->templ.Get(env->isolate());
+}
+
+
+}  // namespace testing
+}  // namespace bindings
+}  // namespace cobalt
+
+
diff --git a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_named_getter_interface.h b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_named_getter_interface.h
new file mode 100644
index 0000000..18c7957
--- /dev/null
+++ b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_named_getter_interface.h
@@ -0,0 +1,50 @@
+
+// Copyright 2017 Google Inc. All Rights Reserved.
+//
+// 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.
+
+// clang-format off
+
+// This file has been auto-generated by bindings/code_generator_cobalt.py. DO NOT MODIFY!
+// Auto-generated from template: bindings/v8c/templates/interface.h.template
+
+#ifndef V8cNamedGetterInterface_h
+#define V8cNamedGetterInterface_h
+
+#include "base/hash_tables.h"
+#include "base/lazy_instance.h"
+#include "base/memory/ref_counted.h"
+#include "base/threading/thread_checker.h"
+#include "cobalt/base/polymorphic_downcast.h"
+#include "cobalt/script/wrappable.h"
+#include "cobalt/bindings/testing/named_getter_interface.h"
+
+#include "cobalt/script/v8c/v8c_global_environment.h"
+#include "v8/include/v8.h"
+
+namespace cobalt {
+namespace bindings {
+namespace testing {
+
+class V8cNamedGetterInterface {
+ public:
+  static v8::Local<v8::Object> CreateWrapper(script::v8c::V8cGlobalEnvironment* env, const scoped_refptr<script::Wrappable>& wrappable);
+  static v8::Local<v8::FunctionTemplate> CreateTemplate(script::v8c::V8cGlobalEnvironment* env);
+  // TODO: Add |GetInterfaceObject|.
+};
+
+}  // namespace testing
+}  // namespace bindings
+}  // namespace cobalt
+
+#endif  // V8cNamedGetterInterface_h
diff --git a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_named_indexed_getter_interface.cc b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_named_indexed_getter_interface.cc
new file mode 100644
index 0000000..0bce93c
--- /dev/null
+++ b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_named_indexed_getter_interface.cc
@@ -0,0 +1,266 @@
+
+
+// Copyright 2017 Google Inc. All Rights Reserved.
+//
+// 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.
+
+// clang-format off
+
+// This file has been auto-generated by bindings/code_generator_cobalt.py. DO NOT MODIFY!
+// Auto-generated from template: bindings/v8c/templates/interface.cc.template
+
+#include "cobalt/bindings/testing/v8c_named_indexed_getter_interface.h"
+
+#include "base/debug/trace_event.h"
+#include "cobalt/base/polymorphic_downcast.h"
+#include "cobalt/script/global_environment.h"
+#include "cobalt/script/script_value.h"
+#include "cobalt/script/value_handle.h"
+
+#include "v8c_gen_type_conversion.h"
+
+#include "cobalt/script/callback_interface_traits.h"
+#include "cobalt/script/v8c/callback_function_conversion.h"
+#include "cobalt/script/v8c/conversion_helpers.h"
+#include "cobalt/script/v8c/native_promise.h"
+#include "cobalt/script/v8c/type_traits.h"
+#include "cobalt/script/v8c/v8c_callback_function.h"
+#include "cobalt/script/v8c/v8c_callback_interface_holder.h"
+#include "cobalt/script/v8c/v8c_exception_state.h"
+#include "cobalt/script/v8c/v8c_global_environment.h"
+#include "cobalt/script/v8c/v8c_value_handle.h"
+#include "cobalt/script/v8c/wrapper_private.h"
+#include "v8/include/v8.h"
+
+
+namespace {
+using cobalt::bindings::testing::NamedIndexedGetterInterface;
+using cobalt::bindings::testing::V8cNamedIndexedGetterInterface;
+using cobalt::script::CallbackInterfaceTraits;
+using cobalt::script::GlobalEnvironment;
+using cobalt::script::ScriptValue;
+using cobalt::script::ValueHandle;
+using cobalt::script::ValueHandle;
+using cobalt::script::ValueHandleHolder;
+using cobalt::script::Wrappable;
+
+using cobalt::script::v8c::FromJSValue;
+using cobalt::script::v8c::InterfaceData;
+using cobalt::script::v8c::kConversionFlagClamped;
+using cobalt::script::v8c::kConversionFlagNullable;
+using cobalt::script::v8c::kConversionFlagRestricted;
+using cobalt::script::v8c::kConversionFlagTreatNullAsEmptyString;
+using cobalt::script::v8c::kConversionFlagTreatUndefinedAsEmptyString;
+using cobalt::script::v8c::kNoConversionFlags;
+using cobalt::script::v8c::TypeTraits;
+using cobalt::script::v8c::V8cExceptionState;
+using cobalt::script::v8c::V8cGlobalEnvironment;
+using cobalt::script::v8c::WrapperFactory;
+using cobalt::script::v8c::WrapperPrivate;
+
+v8::Local<v8::Object> DummyFunctor(V8cGlobalEnvironment*, const scoped_refptr<Wrappable>&) {
+  NOTIMPLEMENTED();
+  return {};
+}
+
+}  // namespace
+
+namespace cobalt {
+namespace bindings {
+namespace testing {
+
+
+namespace {
+
+void NamedIndexedGetterInterfaceConstructor(const v8::FunctionCallbackInfo<v8::Value>& args) {
+  NOTIMPLEMENTED();
+  if (!args.IsConstructCall()) {
+    // TODO: Probably throw something here...
+    return;
+  }
+
+  DCHECK(args.This()->InternalFieldCount() == 1);
+  args.This()->SetInternalField(0, v8::External::New(args.GetIsolate(), nullptr));
+  args.GetReturnValue().Set(args.This());
+}
+
+
+void v8cGet_length(
+  v8::Local<v8::String> property,
+  const v8::PropertyCallbackInfo<v8::Value>& info)
+{
+  NOTIMPLEMENTED();
+
+  v8::Local<v8::External> external = v8::Local<v8::External>::Cast(info.Holder()->GetInternalField(0));
+  WrapperPrivate* wrapper_private = static_cast<WrapperPrivate*>(external->Value());
+  NamedIndexedGetterInterface* impl = static_cast<NamedIndexedGetterInterface*>(wrapper_private->wrappable<NamedIndexedGetterInterface>());
+
+  v8::Local<v8::Value> result_value;
+}
+
+
+
+void v8cGet_propertyOnBaseClass(
+  v8::Local<v8::String> property,
+  const v8::PropertyCallbackInfo<v8::Value>& info)
+{
+  NOTIMPLEMENTED();
+
+  v8::Local<v8::External> external = v8::Local<v8::External>::Cast(info.Holder()->GetInternalField(0));
+  WrapperPrivate* wrapper_private = static_cast<WrapperPrivate*>(external->Value());
+  NamedIndexedGetterInterface* impl = static_cast<NamedIndexedGetterInterface*>(wrapper_private->wrappable<NamedIndexedGetterInterface>());
+
+  v8::Local<v8::Value> result_value;
+}
+
+
+void v8cSet_propertyOnBaseClass(
+  v8::Local<v8::String> property,
+  v8::Local<v8::Value> v8_value,
+  const v8::PropertyCallbackInfo<void>& info)
+{
+  v8::Local<v8::External> external = v8::Local<v8::External>::Cast(info.Holder()->GetInternalField(0));
+  WrapperPrivate* wrapper_private = static_cast<WrapperPrivate*>(external->Value());
+  NamedIndexedGetterInterface* impl = static_cast<NamedIndexedGetterInterface*>(wrapper_private->wrappable<NamedIndexedGetterInterface>());
+
+  TypeTraits<bool>::ConversionType conversion_value;
+  V8cExceptionState exception_state{};
+  FromJSValue(info.GetIsolate(), v8_value, kNoConversionFlags, &exception_state, &conversion_value);
+  impl->set_property_on_base_class(
+    conversion_value
+  );
+}
+
+
+
+void DummyFunction(const v8::FunctionCallbackInfo<v8::Value>& info) {
+  LOG(INFO) << __func__;
+}
+
+void InitializeTemplate(
+  V8cGlobalEnvironment* env,
+  InterfaceData* interface_data) {
+  v8::Isolate* isolate = env->isolate();
+  v8::Local<v8::FunctionTemplate> function_template = v8::FunctionTemplate::New(
+    isolate);
+  function_template->SetClassName(
+    v8::String::NewFromUtf8(isolate, "NamedIndexedGetterInterface",
+        v8::NewStringType::kInternalized).ToLocalChecked());
+  v8::Local<v8::ObjectTemplate> instance_template = function_template->InstanceTemplate();
+  instance_template->SetInternalFieldCount(1);
+
+  v8::Local<v8::ObjectTemplate> prototype_template = function_template->PrototypeTemplate();
+  prototype_template->SetInternalFieldCount(1);
+
+  instance_template->SetAccessor(
+    v8::String::NewFromUtf8(isolate, "length",
+                              v8::NewStringType::kInternalized)
+          .ToLocalChecked(),
+    v8cGet_length
+  );
+  instance_template->SetAccessor(
+    v8::String::NewFromUtf8(isolate, "propertyOnBaseClass",
+                              v8::NewStringType::kInternalized)
+          .ToLocalChecked(),
+    v8cGet_propertyOnBaseClass
+    ,v8cSet_propertyOnBaseClass
+  );
+
+  instance_template->Set(
+      v8::String::NewFromUtf8(
+          isolate,
+          "indexedGetter",
+          v8::NewStringType::kInternalized).ToLocalChecked(),
+      v8::FunctionTemplate::New(isolate, DummyFunction)
+  );
+  instance_template->Set(
+      v8::String::NewFromUtf8(
+          isolate,
+          "indexedSetter",
+          v8::NewStringType::kInternalized).ToLocalChecked(),
+      v8::FunctionTemplate::New(isolate, DummyFunction)
+  );
+  instance_template->Set(
+      v8::String::NewFromUtf8(
+          isolate,
+          "namedGetter",
+          v8::NewStringType::kInternalized).ToLocalChecked(),
+      v8::FunctionTemplate::New(isolate, DummyFunction)
+  );
+  instance_template->Set(
+      v8::String::NewFromUtf8(
+          isolate,
+          "namedSetter",
+          v8::NewStringType::kInternalized).ToLocalChecked(),
+      v8::FunctionTemplate::New(isolate, DummyFunction)
+  );
+  instance_template->Set(
+      v8::String::NewFromUtf8(
+          isolate,
+          "operationOnBaseClass",
+          v8::NewStringType::kInternalized).ToLocalChecked(),
+      v8::FunctionTemplate::New(isolate, DummyFunction)
+  );
+
+  interface_data->templ.Set(env->isolate(), function_template);
+}
+
+inline InterfaceData* GetInterfaceData(V8cGlobalEnvironment* env) {
+  const int kInterfaceUniqueId = 32;
+  // By convention, the |V8cGlobalEnvironment| that we are associated with
+  // will hold our |InterfaceData| at index |kInterfaceUniqueId|, as we asked
+  // for it to be there in the first place, and could not have conflicted with
+  // any other interface.
+  return env->GetInterfaceData(kInterfaceUniqueId);
+}
+
+}  // namespace
+
+v8::Local<v8::Object> V8cNamedIndexedGetterInterface::CreateWrapper(V8cGlobalEnvironment* env, const scoped_refptr<Wrappable>& wrappable) {
+  v8::Isolate* isolate = env->isolate();
+  v8::Isolate::Scope isolate_scope(isolate);
+  v8::EscapableHandleScope handle_scope(isolate);
+  v8::Local<v8::Context> context = env->context();
+  v8::Context::Scope scope(context);
+
+  InterfaceData* interface_data = GetInterfaceData(env);
+  if (interface_data->templ.IsEmpty()) {
+    InitializeTemplate(env, interface_data);
+  }
+  DCHECK(!interface_data->templ.IsEmpty());
+
+  v8::Local<v8::FunctionTemplate> function_template = interface_data->templ.Get(isolate);
+  DCHECK(function_template->InstanceTemplate()->InternalFieldCount() == 1);
+  v8::Local<v8::Object> object = function_template->InstanceTemplate()->NewInstance(context).ToLocalChecked();
+  DCHECK(object->InternalFieldCount() == 1);
+
+  // |WrapperPrivate|'s lifetime will be managed by V8.
+  new WrapperPrivate(isolate, wrappable, object);
+  return handle_scope.Escape(object);
+}
+
+v8::Local<v8::FunctionTemplate> V8cNamedIndexedGetterInterface::CreateTemplate(V8cGlobalEnvironment* env) {
+  InterfaceData* interface_data = GetInterfaceData(env);
+  if (interface_data->templ.IsEmpty()) {
+    InitializeTemplate(env, interface_data);
+  }
+
+  return interface_data->templ.Get(env->isolate());
+}
+
+
+}  // namespace testing
+}  // namespace bindings
+}  // namespace cobalt
+
+
diff --git a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_named_indexed_getter_interface.h b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_named_indexed_getter_interface.h
new file mode 100644
index 0000000..e921b42
--- /dev/null
+++ b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_named_indexed_getter_interface.h
@@ -0,0 +1,50 @@
+
+// Copyright 2017 Google Inc. All Rights Reserved.
+//
+// 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.
+
+// clang-format off
+
+// This file has been auto-generated by bindings/code_generator_cobalt.py. DO NOT MODIFY!
+// Auto-generated from template: bindings/v8c/templates/interface.h.template
+
+#ifndef V8cNamedIndexedGetterInterface_h
+#define V8cNamedIndexedGetterInterface_h
+
+#include "base/hash_tables.h"
+#include "base/lazy_instance.h"
+#include "base/memory/ref_counted.h"
+#include "base/threading/thread_checker.h"
+#include "cobalt/base/polymorphic_downcast.h"
+#include "cobalt/script/wrappable.h"
+#include "cobalt/bindings/testing/named_indexed_getter_interface.h"
+
+#include "cobalt/script/v8c/v8c_global_environment.h"
+#include "v8/include/v8.h"
+
+namespace cobalt {
+namespace bindings {
+namespace testing {
+
+class V8cNamedIndexedGetterInterface {
+ public:
+  static v8::Local<v8::Object> CreateWrapper(script::v8c::V8cGlobalEnvironment* env, const scoped_refptr<script::Wrappable>& wrappable);
+  static v8::Local<v8::FunctionTemplate> CreateTemplate(script::v8c::V8cGlobalEnvironment* env);
+  // TODO: Add |GetInterfaceObject|.
+};
+
+}  // namespace testing
+}  // namespace bindings
+}  // namespace cobalt
+
+#endif  // V8cNamedIndexedGetterInterface_h
diff --git a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_nested_put_forwards_interface.cc b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_nested_put_forwards_interface.cc
new file mode 100644
index 0000000..56de5d5
--- /dev/null
+++ b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_nested_put_forwards_interface.cc
@@ -0,0 +1,209 @@
+
+
+// Copyright 2017 Google Inc. All Rights Reserved.
+//
+// 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.
+
+// clang-format off
+
+// This file has been auto-generated by bindings/code_generator_cobalt.py. DO NOT MODIFY!
+// Auto-generated from template: bindings/v8c/templates/interface.cc.template
+
+#include "cobalt/bindings/testing/v8c_nested_put_forwards_interface.h"
+
+#include "base/debug/trace_event.h"
+#include "cobalt/base/polymorphic_downcast.h"
+#include "cobalt/script/global_environment.h"
+#include "cobalt/script/script_value.h"
+#include "cobalt/script/value_handle.h"
+#include "cobalt/bindings/testing/put_forwards_interface.h"
+#include "cobalt/bindings/testing/v8c_put_forwards_interface.h"
+
+#include "v8c_gen_type_conversion.h"
+
+#include "cobalt/script/callback_interface_traits.h"
+#include "cobalt/script/v8c/callback_function_conversion.h"
+#include "cobalt/script/v8c/conversion_helpers.h"
+#include "cobalt/script/v8c/native_promise.h"
+#include "cobalt/script/v8c/type_traits.h"
+#include "cobalt/script/v8c/v8c_callback_function.h"
+#include "cobalt/script/v8c/v8c_callback_interface_holder.h"
+#include "cobalt/script/v8c/v8c_exception_state.h"
+#include "cobalt/script/v8c/v8c_global_environment.h"
+#include "cobalt/script/v8c/v8c_value_handle.h"
+#include "cobalt/script/v8c/wrapper_private.h"
+#include "v8/include/v8.h"
+
+
+namespace {
+using cobalt::bindings::testing::NestedPutForwardsInterface;
+using cobalt::bindings::testing::V8cNestedPutForwardsInterface;
+using cobalt::bindings::testing::PutForwardsInterface;
+using cobalt::bindings::testing::V8cPutForwardsInterface;
+using cobalt::script::CallbackInterfaceTraits;
+using cobalt::script::GlobalEnvironment;
+using cobalt::script::ScriptValue;
+using cobalt::script::ValueHandle;
+using cobalt::script::ValueHandle;
+using cobalt::script::ValueHandleHolder;
+using cobalt::script::Wrappable;
+
+using cobalt::script::v8c::FromJSValue;
+using cobalt::script::v8c::InterfaceData;
+using cobalt::script::v8c::kConversionFlagClamped;
+using cobalt::script::v8c::kConversionFlagNullable;
+using cobalt::script::v8c::kConversionFlagRestricted;
+using cobalt::script::v8c::kConversionFlagTreatNullAsEmptyString;
+using cobalt::script::v8c::kConversionFlagTreatUndefinedAsEmptyString;
+using cobalt::script::v8c::kNoConversionFlags;
+using cobalt::script::v8c::TypeTraits;
+using cobalt::script::v8c::V8cExceptionState;
+using cobalt::script::v8c::V8cGlobalEnvironment;
+using cobalt::script::v8c::WrapperFactory;
+using cobalt::script::v8c::WrapperPrivate;
+
+v8::Local<v8::Object> DummyFunctor(V8cGlobalEnvironment*, const scoped_refptr<Wrappable>&) {
+  NOTIMPLEMENTED();
+  return {};
+}
+
+}  // namespace
+
+namespace cobalt {
+namespace bindings {
+namespace testing {
+
+
+namespace {
+
+void NestedPutForwardsInterfaceConstructor(const v8::FunctionCallbackInfo<v8::Value>& args) {
+  NOTIMPLEMENTED();
+  if (!args.IsConstructCall()) {
+    // TODO: Probably throw something here...
+    return;
+  }
+
+  DCHECK(args.This()->InternalFieldCount() == 1);
+  args.This()->SetInternalField(0, v8::External::New(args.GetIsolate(), nullptr));
+  args.GetReturnValue().Set(args.This());
+}
+
+
+void v8cGet_nestedForwardingAttribute(
+  v8::Local<v8::String> property,
+  const v8::PropertyCallbackInfo<v8::Value>& info)
+{
+  NOTIMPLEMENTED();
+
+  v8::Local<v8::External> external = v8::Local<v8::External>::Cast(info.Holder()->GetInternalField(0));
+  WrapperPrivate* wrapper_private = static_cast<WrapperPrivate*>(external->Value());
+  NestedPutForwardsInterface* impl = static_cast<NestedPutForwardsInterface*>(wrapper_private->wrappable<NestedPutForwardsInterface>());
+
+  NOTIMPLEMENTED();
+}
+
+
+void v8cSet_nestedForwardingAttribute(
+  v8::Local<v8::String> property,
+  v8::Local<v8::Value> v8_value,
+  const v8::PropertyCallbackInfo<void>& info)
+{
+  v8::Local<v8::External> external = v8::Local<v8::External>::Cast(info.Holder()->GetInternalField(0));
+  WrapperPrivate* wrapper_private = static_cast<WrapperPrivate*>(external->Value());
+  NestedPutForwardsInterface* impl = static_cast<NestedPutForwardsInterface*>(wrapper_private->wrappable<NestedPutForwardsInterface>());
+
+  NOTIMPLEMENTED();
+}
+
+
+
+void DummyFunction(const v8::FunctionCallbackInfo<v8::Value>& info) {
+  LOG(INFO) << __func__;
+}
+
+void InitializeTemplate(
+  V8cGlobalEnvironment* env,
+  InterfaceData* interface_data) {
+  v8::Isolate* isolate = env->isolate();
+  v8::Local<v8::FunctionTemplate> function_template = v8::FunctionTemplate::New(
+    isolate);
+  function_template->SetClassName(
+    v8::String::NewFromUtf8(isolate, "NestedPutForwardsInterface",
+        v8::NewStringType::kInternalized).ToLocalChecked());
+  v8::Local<v8::ObjectTemplate> instance_template = function_template->InstanceTemplate();
+  instance_template->SetInternalFieldCount(1);
+
+  v8::Local<v8::ObjectTemplate> prototype_template = function_template->PrototypeTemplate();
+  prototype_template->SetInternalFieldCount(1);
+
+  instance_template->SetAccessor(
+    v8::String::NewFromUtf8(isolate, "nestedForwardingAttribute",
+                              v8::NewStringType::kInternalized)
+          .ToLocalChecked(),
+    v8cGet_nestedForwardingAttribute
+    ,v8cSet_nestedForwardingAttribute
+  );
+
+
+  interface_data->templ.Set(env->isolate(), function_template);
+}
+
+inline InterfaceData* GetInterfaceData(V8cGlobalEnvironment* env) {
+  const int kInterfaceUniqueId = 33;
+  // By convention, the |V8cGlobalEnvironment| that we are associated with
+  // will hold our |InterfaceData| at index |kInterfaceUniqueId|, as we asked
+  // for it to be there in the first place, and could not have conflicted with
+  // any other interface.
+  return env->GetInterfaceData(kInterfaceUniqueId);
+}
+
+}  // namespace
+
+v8::Local<v8::Object> V8cNestedPutForwardsInterface::CreateWrapper(V8cGlobalEnvironment* env, const scoped_refptr<Wrappable>& wrappable) {
+  v8::Isolate* isolate = env->isolate();
+  v8::Isolate::Scope isolate_scope(isolate);
+  v8::EscapableHandleScope handle_scope(isolate);
+  v8::Local<v8::Context> context = env->context();
+  v8::Context::Scope scope(context);
+
+  InterfaceData* interface_data = GetInterfaceData(env);
+  if (interface_data->templ.IsEmpty()) {
+    InitializeTemplate(env, interface_data);
+  }
+  DCHECK(!interface_data->templ.IsEmpty());
+
+  v8::Local<v8::FunctionTemplate> function_template = interface_data->templ.Get(isolate);
+  DCHECK(function_template->InstanceTemplate()->InternalFieldCount() == 1);
+  v8::Local<v8::Object> object = function_template->InstanceTemplate()->NewInstance(context).ToLocalChecked();
+  DCHECK(object->InternalFieldCount() == 1);
+
+  // |WrapperPrivate|'s lifetime will be managed by V8.
+  new WrapperPrivate(isolate, wrappable, object);
+  return handle_scope.Escape(object);
+}
+
+v8::Local<v8::FunctionTemplate> V8cNestedPutForwardsInterface::CreateTemplate(V8cGlobalEnvironment* env) {
+  InterfaceData* interface_data = GetInterfaceData(env);
+  if (interface_data->templ.IsEmpty()) {
+    InitializeTemplate(env, interface_data);
+  }
+
+  return interface_data->templ.Get(env->isolate());
+}
+
+
+}  // namespace testing
+}  // namespace bindings
+}  // namespace cobalt
+
+
diff --git a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_nested_put_forwards_interface.h b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_nested_put_forwards_interface.h
new file mode 100644
index 0000000..d2f9972
--- /dev/null
+++ b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_nested_put_forwards_interface.h
@@ -0,0 +1,50 @@
+
+// Copyright 2017 Google Inc. All Rights Reserved.
+//
+// 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.
+
+// clang-format off
+
+// This file has been auto-generated by bindings/code_generator_cobalt.py. DO NOT MODIFY!
+// Auto-generated from template: bindings/v8c/templates/interface.h.template
+
+#ifndef V8cNestedPutForwardsInterface_h
+#define V8cNestedPutForwardsInterface_h
+
+#include "base/hash_tables.h"
+#include "base/lazy_instance.h"
+#include "base/memory/ref_counted.h"
+#include "base/threading/thread_checker.h"
+#include "cobalt/base/polymorphic_downcast.h"
+#include "cobalt/script/wrappable.h"
+#include "cobalt/bindings/testing/nested_put_forwards_interface.h"
+
+#include "cobalt/script/v8c/v8c_global_environment.h"
+#include "v8/include/v8.h"
+
+namespace cobalt {
+namespace bindings {
+namespace testing {
+
+class V8cNestedPutForwardsInterface {
+ public:
+  static v8::Local<v8::Object> CreateWrapper(script::v8c::V8cGlobalEnvironment* env, const scoped_refptr<script::Wrappable>& wrappable);
+  static v8::Local<v8::FunctionTemplate> CreateTemplate(script::v8c::V8cGlobalEnvironment* env);
+  // TODO: Add |GetInterfaceObject|.
+};
+
+}  // namespace testing
+}  // namespace bindings
+}  // namespace cobalt
+
+#endif  // V8cNestedPutForwardsInterface_h
diff --git a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_no_constructor_interface.cc b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_no_constructor_interface.cc
new file mode 100644
index 0000000..634eddb
--- /dev/null
+++ b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_no_constructor_interface.cc
@@ -0,0 +1,170 @@
+
+
+// Copyright 2017 Google Inc. All Rights Reserved.
+//
+// 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.
+
+// clang-format off
+
+// This file has been auto-generated by bindings/code_generator_cobalt.py. DO NOT MODIFY!
+// Auto-generated from template: bindings/v8c/templates/interface.cc.template
+
+#include "cobalt/bindings/testing/v8c_no_constructor_interface.h"
+
+#include "base/debug/trace_event.h"
+#include "cobalt/base/polymorphic_downcast.h"
+#include "cobalt/script/global_environment.h"
+#include "cobalt/script/script_value.h"
+#include "cobalt/script/value_handle.h"
+
+#include "v8c_gen_type_conversion.h"
+
+#include "cobalt/script/callback_interface_traits.h"
+#include "cobalt/script/v8c/callback_function_conversion.h"
+#include "cobalt/script/v8c/conversion_helpers.h"
+#include "cobalt/script/v8c/native_promise.h"
+#include "cobalt/script/v8c/type_traits.h"
+#include "cobalt/script/v8c/v8c_callback_function.h"
+#include "cobalt/script/v8c/v8c_callback_interface_holder.h"
+#include "cobalt/script/v8c/v8c_exception_state.h"
+#include "cobalt/script/v8c/v8c_global_environment.h"
+#include "cobalt/script/v8c/v8c_value_handle.h"
+#include "cobalt/script/v8c/wrapper_private.h"
+#include "v8/include/v8.h"
+
+
+namespace {
+using cobalt::bindings::testing::NoConstructorInterface;
+using cobalt::bindings::testing::V8cNoConstructorInterface;
+using cobalt::script::CallbackInterfaceTraits;
+using cobalt::script::GlobalEnvironment;
+using cobalt::script::ScriptValue;
+using cobalt::script::ValueHandle;
+using cobalt::script::ValueHandle;
+using cobalt::script::ValueHandleHolder;
+using cobalt::script::Wrappable;
+
+using cobalt::script::v8c::FromJSValue;
+using cobalt::script::v8c::InterfaceData;
+using cobalt::script::v8c::kConversionFlagClamped;
+using cobalt::script::v8c::kConversionFlagNullable;
+using cobalt::script::v8c::kConversionFlagRestricted;
+using cobalt::script::v8c::kConversionFlagTreatNullAsEmptyString;
+using cobalt::script::v8c::kConversionFlagTreatUndefinedAsEmptyString;
+using cobalt::script::v8c::kNoConversionFlags;
+using cobalt::script::v8c::TypeTraits;
+using cobalt::script::v8c::V8cExceptionState;
+using cobalt::script::v8c::V8cGlobalEnvironment;
+using cobalt::script::v8c::WrapperFactory;
+using cobalt::script::v8c::WrapperPrivate;
+
+v8::Local<v8::Object> DummyFunctor(V8cGlobalEnvironment*, const scoped_refptr<Wrappable>&) {
+  NOTIMPLEMENTED();
+  return {};
+}
+
+}  // namespace
+
+namespace cobalt {
+namespace bindings {
+namespace testing {
+
+
+namespace {
+
+void NoConstructorInterfaceConstructor(const v8::FunctionCallbackInfo<v8::Value>& args) {
+  NOTIMPLEMENTED();
+  if (!args.IsConstructCall()) {
+    // TODO: Probably throw something here...
+    return;
+  }
+
+  DCHECK(args.This()->InternalFieldCount() == 1);
+  args.This()->SetInternalField(0, v8::External::New(args.GetIsolate(), nullptr));
+  args.GetReturnValue().Set(args.This());
+}
+
+
+void DummyFunction(const v8::FunctionCallbackInfo<v8::Value>& info) {
+  LOG(INFO) << __func__;
+}
+
+void InitializeTemplate(
+  V8cGlobalEnvironment* env,
+  InterfaceData* interface_data) {
+  v8::Isolate* isolate = env->isolate();
+  v8::Local<v8::FunctionTemplate> function_template = v8::FunctionTemplate::New(
+    isolate);
+  function_template->SetClassName(
+    v8::String::NewFromUtf8(isolate, "NoConstructorInterface",
+        v8::NewStringType::kInternalized).ToLocalChecked());
+  v8::Local<v8::ObjectTemplate> instance_template = function_template->InstanceTemplate();
+  instance_template->SetInternalFieldCount(1);
+
+  v8::Local<v8::ObjectTemplate> prototype_template = function_template->PrototypeTemplate();
+  prototype_template->SetInternalFieldCount(1);
+
+
+
+  interface_data->templ.Set(env->isolate(), function_template);
+}
+
+inline InterfaceData* GetInterfaceData(V8cGlobalEnvironment* env) {
+  const int kInterfaceUniqueId = 34;
+  // By convention, the |V8cGlobalEnvironment| that we are associated with
+  // will hold our |InterfaceData| at index |kInterfaceUniqueId|, as we asked
+  // for it to be there in the first place, and could not have conflicted with
+  // any other interface.
+  return env->GetInterfaceData(kInterfaceUniqueId);
+}
+
+}  // namespace
+
+v8::Local<v8::Object> V8cNoConstructorInterface::CreateWrapper(V8cGlobalEnvironment* env, const scoped_refptr<Wrappable>& wrappable) {
+  v8::Isolate* isolate = env->isolate();
+  v8::Isolate::Scope isolate_scope(isolate);
+  v8::EscapableHandleScope handle_scope(isolate);
+  v8::Local<v8::Context> context = env->context();
+  v8::Context::Scope scope(context);
+
+  InterfaceData* interface_data = GetInterfaceData(env);
+  if (interface_data->templ.IsEmpty()) {
+    InitializeTemplate(env, interface_data);
+  }
+  DCHECK(!interface_data->templ.IsEmpty());
+
+  v8::Local<v8::FunctionTemplate> function_template = interface_data->templ.Get(isolate);
+  DCHECK(function_template->InstanceTemplate()->InternalFieldCount() == 1);
+  v8::Local<v8::Object> object = function_template->InstanceTemplate()->NewInstance(context).ToLocalChecked();
+  DCHECK(object->InternalFieldCount() == 1);
+
+  // |WrapperPrivate|'s lifetime will be managed by V8.
+  new WrapperPrivate(isolate, wrappable, object);
+  return handle_scope.Escape(object);
+}
+
+v8::Local<v8::FunctionTemplate> V8cNoConstructorInterface::CreateTemplate(V8cGlobalEnvironment* env) {
+  InterfaceData* interface_data = GetInterfaceData(env);
+  if (interface_data->templ.IsEmpty()) {
+    InitializeTemplate(env, interface_data);
+  }
+
+  return interface_data->templ.Get(env->isolate());
+}
+
+
+}  // namespace testing
+}  // namespace bindings
+}  // namespace cobalt
+
+
diff --git a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_no_constructor_interface.h b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_no_constructor_interface.h
new file mode 100644
index 0000000..88bb222
--- /dev/null
+++ b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_no_constructor_interface.h
@@ -0,0 +1,50 @@
+
+// Copyright 2017 Google Inc. All Rights Reserved.
+//
+// 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.
+
+// clang-format off
+
+// This file has been auto-generated by bindings/code_generator_cobalt.py. DO NOT MODIFY!
+// Auto-generated from template: bindings/v8c/templates/interface.h.template
+
+#ifndef V8cNoConstructorInterface_h
+#define V8cNoConstructorInterface_h
+
+#include "base/hash_tables.h"
+#include "base/lazy_instance.h"
+#include "base/memory/ref_counted.h"
+#include "base/threading/thread_checker.h"
+#include "cobalt/base/polymorphic_downcast.h"
+#include "cobalt/script/wrappable.h"
+#include "cobalt/bindings/testing/no_constructor_interface.h"
+
+#include "cobalt/script/v8c/v8c_global_environment.h"
+#include "v8/include/v8.h"
+
+namespace cobalt {
+namespace bindings {
+namespace testing {
+
+class V8cNoConstructorInterface {
+ public:
+  static v8::Local<v8::Object> CreateWrapper(script::v8c::V8cGlobalEnvironment* env, const scoped_refptr<script::Wrappable>& wrappable);
+  static v8::Local<v8::FunctionTemplate> CreateTemplate(script::v8c::V8cGlobalEnvironment* env);
+  // TODO: Add |GetInterfaceObject|.
+};
+
+}  // namespace testing
+}  // namespace bindings
+}  // namespace cobalt
+
+#endif  // V8cNoConstructorInterface_h
diff --git a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_no_interface_object_interface.cc b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_no_interface_object_interface.cc
new file mode 100644
index 0000000..35b5038
--- /dev/null
+++ b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_no_interface_object_interface.cc
@@ -0,0 +1,170 @@
+
+
+// Copyright 2017 Google Inc. All Rights Reserved.
+//
+// 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.
+
+// clang-format off
+
+// This file has been auto-generated by bindings/code_generator_cobalt.py. DO NOT MODIFY!
+// Auto-generated from template: bindings/v8c/templates/interface.cc.template
+
+#include "cobalt/bindings/testing/v8c_no_interface_object_interface.h"
+
+#include "base/debug/trace_event.h"
+#include "cobalt/base/polymorphic_downcast.h"
+#include "cobalt/script/global_environment.h"
+#include "cobalt/script/script_value.h"
+#include "cobalt/script/value_handle.h"
+
+#include "v8c_gen_type_conversion.h"
+
+#include "cobalt/script/callback_interface_traits.h"
+#include "cobalt/script/v8c/callback_function_conversion.h"
+#include "cobalt/script/v8c/conversion_helpers.h"
+#include "cobalt/script/v8c/native_promise.h"
+#include "cobalt/script/v8c/type_traits.h"
+#include "cobalt/script/v8c/v8c_callback_function.h"
+#include "cobalt/script/v8c/v8c_callback_interface_holder.h"
+#include "cobalt/script/v8c/v8c_exception_state.h"
+#include "cobalt/script/v8c/v8c_global_environment.h"
+#include "cobalt/script/v8c/v8c_value_handle.h"
+#include "cobalt/script/v8c/wrapper_private.h"
+#include "v8/include/v8.h"
+
+
+namespace {
+using cobalt::bindings::testing::NoInterfaceObjectInterface;
+using cobalt::bindings::testing::V8cNoInterfaceObjectInterface;
+using cobalt::script::CallbackInterfaceTraits;
+using cobalt::script::GlobalEnvironment;
+using cobalt::script::ScriptValue;
+using cobalt::script::ValueHandle;
+using cobalt::script::ValueHandle;
+using cobalt::script::ValueHandleHolder;
+using cobalt::script::Wrappable;
+
+using cobalt::script::v8c::FromJSValue;
+using cobalt::script::v8c::InterfaceData;
+using cobalt::script::v8c::kConversionFlagClamped;
+using cobalt::script::v8c::kConversionFlagNullable;
+using cobalt::script::v8c::kConversionFlagRestricted;
+using cobalt::script::v8c::kConversionFlagTreatNullAsEmptyString;
+using cobalt::script::v8c::kConversionFlagTreatUndefinedAsEmptyString;
+using cobalt::script::v8c::kNoConversionFlags;
+using cobalt::script::v8c::TypeTraits;
+using cobalt::script::v8c::V8cExceptionState;
+using cobalt::script::v8c::V8cGlobalEnvironment;
+using cobalt::script::v8c::WrapperFactory;
+using cobalt::script::v8c::WrapperPrivate;
+
+v8::Local<v8::Object> DummyFunctor(V8cGlobalEnvironment*, const scoped_refptr<Wrappable>&) {
+  NOTIMPLEMENTED();
+  return {};
+}
+
+}  // namespace
+
+namespace cobalt {
+namespace bindings {
+namespace testing {
+
+
+namespace {
+
+void NoInterfaceObjectInterfaceConstructor(const v8::FunctionCallbackInfo<v8::Value>& args) {
+  NOTIMPLEMENTED();
+  if (!args.IsConstructCall()) {
+    // TODO: Probably throw something here...
+    return;
+  }
+
+  DCHECK(args.This()->InternalFieldCount() == 1);
+  args.This()->SetInternalField(0, v8::External::New(args.GetIsolate(), nullptr));
+  args.GetReturnValue().Set(args.This());
+}
+
+
+void DummyFunction(const v8::FunctionCallbackInfo<v8::Value>& info) {
+  LOG(INFO) << __func__;
+}
+
+void InitializeTemplate(
+  V8cGlobalEnvironment* env,
+  InterfaceData* interface_data) {
+  v8::Isolate* isolate = env->isolate();
+  v8::Local<v8::FunctionTemplate> function_template = v8::FunctionTemplate::New(
+    isolate);
+  function_template->SetClassName(
+    v8::String::NewFromUtf8(isolate, "NoInterfaceObjectInterface",
+        v8::NewStringType::kInternalized).ToLocalChecked());
+  v8::Local<v8::ObjectTemplate> instance_template = function_template->InstanceTemplate();
+  instance_template->SetInternalFieldCount(1);
+
+  v8::Local<v8::ObjectTemplate> prototype_template = function_template->PrototypeTemplate();
+  prototype_template->SetInternalFieldCount(1);
+
+
+
+  interface_data->templ.Set(env->isolate(), function_template);
+}
+
+inline InterfaceData* GetInterfaceData(V8cGlobalEnvironment* env) {
+  const int kInterfaceUniqueId = 35;
+  // By convention, the |V8cGlobalEnvironment| that we are associated with
+  // will hold our |InterfaceData| at index |kInterfaceUniqueId|, as we asked
+  // for it to be there in the first place, and could not have conflicted with
+  // any other interface.
+  return env->GetInterfaceData(kInterfaceUniqueId);
+}
+
+}  // namespace
+
+v8::Local<v8::Object> V8cNoInterfaceObjectInterface::CreateWrapper(V8cGlobalEnvironment* env, const scoped_refptr<Wrappable>& wrappable) {
+  v8::Isolate* isolate = env->isolate();
+  v8::Isolate::Scope isolate_scope(isolate);
+  v8::EscapableHandleScope handle_scope(isolate);
+  v8::Local<v8::Context> context = env->context();
+  v8::Context::Scope scope(context);
+
+  InterfaceData* interface_data = GetInterfaceData(env);
+  if (interface_data->templ.IsEmpty()) {
+    InitializeTemplate(env, interface_data);
+  }
+  DCHECK(!interface_data->templ.IsEmpty());
+
+  v8::Local<v8::FunctionTemplate> function_template = interface_data->templ.Get(isolate);
+  DCHECK(function_template->InstanceTemplate()->InternalFieldCount() == 1);
+  v8::Local<v8::Object> object = function_template->InstanceTemplate()->NewInstance(context).ToLocalChecked();
+  DCHECK(object->InternalFieldCount() == 1);
+
+  // |WrapperPrivate|'s lifetime will be managed by V8.
+  new WrapperPrivate(isolate, wrappable, object);
+  return handle_scope.Escape(object);
+}
+
+v8::Local<v8::FunctionTemplate> V8cNoInterfaceObjectInterface::CreateTemplate(V8cGlobalEnvironment* env) {
+  InterfaceData* interface_data = GetInterfaceData(env);
+  if (interface_data->templ.IsEmpty()) {
+    InitializeTemplate(env, interface_data);
+  }
+
+  return interface_data->templ.Get(env->isolate());
+}
+
+
+}  // namespace testing
+}  // namespace bindings
+}  // namespace cobalt
+
+
diff --git a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_no_interface_object_interface.h b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_no_interface_object_interface.h
new file mode 100644
index 0000000..49b3f03
--- /dev/null
+++ b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_no_interface_object_interface.h
@@ -0,0 +1,49 @@
+
+// Copyright 2017 Google Inc. All Rights Reserved.
+//
+// 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.
+
+// clang-format off
+
+// This file has been auto-generated by bindings/code_generator_cobalt.py. DO NOT MODIFY!
+// Auto-generated from template: bindings/v8c/templates/interface.h.template
+
+#ifndef V8cNoInterfaceObjectInterface_h
+#define V8cNoInterfaceObjectInterface_h
+
+#include "base/hash_tables.h"
+#include "base/lazy_instance.h"
+#include "base/memory/ref_counted.h"
+#include "base/threading/thread_checker.h"
+#include "cobalt/base/polymorphic_downcast.h"
+#include "cobalt/script/wrappable.h"
+#include "cobalt/bindings/testing/no_interface_object_interface.h"
+
+#include "cobalt/script/v8c/v8c_global_environment.h"
+#include "v8/include/v8.h"
+
+namespace cobalt {
+namespace bindings {
+namespace testing {
+
+class V8cNoInterfaceObjectInterface {
+ public:
+  static v8::Local<v8::Object> CreateWrapper(script::v8c::V8cGlobalEnvironment* env, const scoped_refptr<script::Wrappable>& wrappable);
+  static v8::Local<v8::FunctionTemplate> CreateTemplate(script::v8c::V8cGlobalEnvironment* env);
+};
+
+}  // namespace testing
+}  // namespace bindings
+}  // namespace cobalt
+
+#endif  // V8cNoInterfaceObjectInterface_h
diff --git a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_nullable_types_test_interface.cc b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_nullable_types_test_interface.cc
new file mode 100644
index 0000000..6108a01
--- /dev/null
+++ b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_nullable_types_test_interface.cc
@@ -0,0 +1,390 @@
+
+
+// Copyright 2017 Google Inc. All Rights Reserved.
+//
+// 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.
+
+// clang-format off
+
+// This file has been auto-generated by bindings/code_generator_cobalt.py. DO NOT MODIFY!
+// Auto-generated from template: bindings/v8c/templates/interface.cc.template
+
+#include "cobalt/bindings/testing/v8c_nullable_types_test_interface.h"
+
+#include "base/debug/trace_event.h"
+#include "cobalt/base/polymorphic_downcast.h"
+#include "cobalt/script/global_environment.h"
+#include "cobalt/script/script_value.h"
+#include "cobalt/script/value_handle.h"
+#include "cobalt/bindings/testing/arbitrary_interface.h"
+#include "cobalt/bindings/testing/v8c_arbitrary_interface.h"
+
+#include "v8c_gen_type_conversion.h"
+
+#include "cobalt/script/callback_interface_traits.h"
+#include "cobalt/script/v8c/callback_function_conversion.h"
+#include "cobalt/script/v8c/conversion_helpers.h"
+#include "cobalt/script/v8c/native_promise.h"
+#include "cobalt/script/v8c/type_traits.h"
+#include "cobalt/script/v8c/v8c_callback_function.h"
+#include "cobalt/script/v8c/v8c_callback_interface_holder.h"
+#include "cobalt/script/v8c/v8c_exception_state.h"
+#include "cobalt/script/v8c/v8c_global_environment.h"
+#include "cobalt/script/v8c/v8c_value_handle.h"
+#include "cobalt/script/v8c/wrapper_private.h"
+#include "v8/include/v8.h"
+
+
+namespace {
+using cobalt::bindings::testing::NullableTypesTestInterface;
+using cobalt::bindings::testing::V8cNullableTypesTestInterface;
+using cobalt::bindings::testing::ArbitraryInterface;
+using cobalt::bindings::testing::V8cArbitraryInterface;
+using cobalt::script::CallbackInterfaceTraits;
+using cobalt::script::GlobalEnvironment;
+using cobalt::script::ScriptValue;
+using cobalt::script::ValueHandle;
+using cobalt::script::ValueHandle;
+using cobalt::script::ValueHandleHolder;
+using cobalt::script::Wrappable;
+
+using cobalt::script::v8c::FromJSValue;
+using cobalt::script::v8c::InterfaceData;
+using cobalt::script::v8c::kConversionFlagClamped;
+using cobalt::script::v8c::kConversionFlagNullable;
+using cobalt::script::v8c::kConversionFlagRestricted;
+using cobalt::script::v8c::kConversionFlagTreatNullAsEmptyString;
+using cobalt::script::v8c::kConversionFlagTreatUndefinedAsEmptyString;
+using cobalt::script::v8c::kNoConversionFlags;
+using cobalt::script::v8c::TypeTraits;
+using cobalt::script::v8c::V8cExceptionState;
+using cobalt::script::v8c::V8cGlobalEnvironment;
+using cobalt::script::v8c::WrapperFactory;
+using cobalt::script::v8c::WrapperPrivate;
+
+v8::Local<v8::Object> DummyFunctor(V8cGlobalEnvironment*, const scoped_refptr<Wrappable>&) {
+  NOTIMPLEMENTED();
+  return {};
+}
+
+}  // namespace
+
+namespace cobalt {
+namespace bindings {
+namespace testing {
+
+
+namespace {
+
+void NullableTypesTestInterfaceConstructor(const v8::FunctionCallbackInfo<v8::Value>& args) {
+  NOTIMPLEMENTED();
+  if (!args.IsConstructCall()) {
+    // TODO: Probably throw something here...
+    return;
+  }
+
+  DCHECK(args.This()->InternalFieldCount() == 1);
+  args.This()->SetInternalField(0, v8::External::New(args.GetIsolate(), nullptr));
+  args.GetReturnValue().Set(args.This());
+}
+
+
+void v8cGet_nullableBooleanProperty(
+  v8::Local<v8::String> property,
+  const v8::PropertyCallbackInfo<v8::Value>& info)
+{
+  NOTIMPLEMENTED();
+
+  v8::Local<v8::External> external = v8::Local<v8::External>::Cast(info.Holder()->GetInternalField(0));
+  WrapperPrivate* wrapper_private = static_cast<WrapperPrivate*>(external->Value());
+  NullableTypesTestInterface* impl = static_cast<NullableTypesTestInterface*>(wrapper_private->wrappable<NullableTypesTestInterface>());
+
+  v8::Local<v8::Value> result_value;
+}
+
+
+void v8cSet_nullableBooleanProperty(
+  v8::Local<v8::String> property,
+  v8::Local<v8::Value> v8_value,
+  const v8::PropertyCallbackInfo<void>& info)
+{
+  v8::Local<v8::External> external = v8::Local<v8::External>::Cast(info.Holder()->GetInternalField(0));
+  WrapperPrivate* wrapper_private = static_cast<WrapperPrivate*>(external->Value());
+  NullableTypesTestInterface* impl = static_cast<NullableTypesTestInterface*>(wrapper_private->wrappable<NullableTypesTestInterface>());
+
+  TypeTraits<base::optional<bool >>::ConversionType conversion_value;
+  V8cExceptionState exception_state{};
+  FromJSValue(info.GetIsolate(), v8_value, (kConversionFlagNullable), &exception_state, &conversion_value);
+  impl->set_nullable_boolean_property(
+    conversion_value
+  );
+}
+
+
+
+void v8cGet_nullableNumericProperty(
+  v8::Local<v8::String> property,
+  const v8::PropertyCallbackInfo<v8::Value>& info)
+{
+  NOTIMPLEMENTED();
+
+  v8::Local<v8::External> external = v8::Local<v8::External>::Cast(info.Holder()->GetInternalField(0));
+  WrapperPrivate* wrapper_private = static_cast<WrapperPrivate*>(external->Value());
+  NullableTypesTestInterface* impl = static_cast<NullableTypesTestInterface*>(wrapper_private->wrappable<NullableTypesTestInterface>());
+
+  v8::Local<v8::Value> result_value;
+}
+
+
+void v8cSet_nullableNumericProperty(
+  v8::Local<v8::String> property,
+  v8::Local<v8::Value> v8_value,
+  const v8::PropertyCallbackInfo<void>& info)
+{
+  v8::Local<v8::External> external = v8::Local<v8::External>::Cast(info.Holder()->GetInternalField(0));
+  WrapperPrivate* wrapper_private = static_cast<WrapperPrivate*>(external->Value());
+  NullableTypesTestInterface* impl = static_cast<NullableTypesTestInterface*>(wrapper_private->wrappable<NullableTypesTestInterface>());
+
+  TypeTraits<base::optional<int32_t >>::ConversionType conversion_value;
+  V8cExceptionState exception_state{};
+  FromJSValue(info.GetIsolate(), v8_value, (kConversionFlagNullable), &exception_state, &conversion_value);
+  impl->set_nullable_numeric_property(
+    conversion_value
+  );
+}
+
+
+
+void v8cGet_nullableStringProperty(
+  v8::Local<v8::String> property,
+  const v8::PropertyCallbackInfo<v8::Value>& info)
+{
+  NOTIMPLEMENTED();
+
+  v8::Local<v8::External> external = v8::Local<v8::External>::Cast(info.Holder()->GetInternalField(0));
+  WrapperPrivate* wrapper_private = static_cast<WrapperPrivate*>(external->Value());
+  NullableTypesTestInterface* impl = static_cast<NullableTypesTestInterface*>(wrapper_private->wrappable<NullableTypesTestInterface>());
+
+  v8::Local<v8::Value> result_value;
+}
+
+
+void v8cSet_nullableStringProperty(
+  v8::Local<v8::String> property,
+  v8::Local<v8::Value> v8_value,
+  const v8::PropertyCallbackInfo<void>& info)
+{
+  v8::Local<v8::External> external = v8::Local<v8::External>::Cast(info.Holder()->GetInternalField(0));
+  WrapperPrivate* wrapper_private = static_cast<WrapperPrivate*>(external->Value());
+  NullableTypesTestInterface* impl = static_cast<NullableTypesTestInterface*>(wrapper_private->wrappable<NullableTypesTestInterface>());
+
+  TypeTraits<base::optional<std::string >>::ConversionType conversion_value;
+  V8cExceptionState exception_state{};
+  FromJSValue(info.GetIsolate(), v8_value, (kConversionFlagNullable), &exception_state, &conversion_value);
+  impl->set_nullable_string_property(
+    conversion_value
+  );
+}
+
+
+
+void v8cGet_nullableObjectProperty(
+  v8::Local<v8::String> property,
+  const v8::PropertyCallbackInfo<v8::Value>& info)
+{
+  NOTIMPLEMENTED();
+
+  v8::Local<v8::External> external = v8::Local<v8::External>::Cast(info.Holder()->GetInternalField(0));
+  WrapperPrivate* wrapper_private = static_cast<WrapperPrivate*>(external->Value());
+  NullableTypesTestInterface* impl = static_cast<NullableTypesTestInterface*>(wrapper_private->wrappable<NullableTypesTestInterface>());
+
+  v8::Local<v8::Value> result_value;
+}
+
+
+void v8cSet_nullableObjectProperty(
+  v8::Local<v8::String> property,
+  v8::Local<v8::Value> v8_value,
+  const v8::PropertyCallbackInfo<void>& info)
+{
+  v8::Local<v8::External> external = v8::Local<v8::External>::Cast(info.Holder()->GetInternalField(0));
+  WrapperPrivate* wrapper_private = static_cast<WrapperPrivate*>(external->Value());
+  NullableTypesTestInterface* impl = static_cast<NullableTypesTestInterface*>(wrapper_private->wrappable<NullableTypesTestInterface>());
+
+  TypeTraits<scoped_refptr<ArbitraryInterface>>::ConversionType conversion_value;
+  V8cExceptionState exception_state{};
+  FromJSValue(info.GetIsolate(), v8_value, (kConversionFlagNullable), &exception_state, &conversion_value);
+  impl->set_nullable_object_property(
+    conversion_value
+  );
+}
+
+
+
+void DummyFunction(const v8::FunctionCallbackInfo<v8::Value>& info) {
+  LOG(INFO) << __func__;
+}
+
+void InitializeTemplate(
+  V8cGlobalEnvironment* env,
+  InterfaceData* interface_data) {
+  v8::Isolate* isolate = env->isolate();
+  v8::Local<v8::FunctionTemplate> function_template = v8::FunctionTemplate::New(
+    isolate);
+  function_template->SetClassName(
+    v8::String::NewFromUtf8(isolate, "NullableTypesTestInterface",
+        v8::NewStringType::kInternalized).ToLocalChecked());
+  v8::Local<v8::ObjectTemplate> instance_template = function_template->InstanceTemplate();
+  instance_template->SetInternalFieldCount(1);
+
+  v8::Local<v8::ObjectTemplate> prototype_template = function_template->PrototypeTemplate();
+  prototype_template->SetInternalFieldCount(1);
+
+  instance_template->SetAccessor(
+    v8::String::NewFromUtf8(isolate, "nullableBooleanProperty",
+                              v8::NewStringType::kInternalized)
+          .ToLocalChecked(),
+    v8cGet_nullableBooleanProperty
+    ,v8cSet_nullableBooleanProperty
+  );
+  instance_template->SetAccessor(
+    v8::String::NewFromUtf8(isolate, "nullableNumericProperty",
+                              v8::NewStringType::kInternalized)
+          .ToLocalChecked(),
+    v8cGet_nullableNumericProperty
+    ,v8cSet_nullableNumericProperty
+  );
+  instance_template->SetAccessor(
+    v8::String::NewFromUtf8(isolate, "nullableStringProperty",
+                              v8::NewStringType::kInternalized)
+          .ToLocalChecked(),
+    v8cGet_nullableStringProperty
+    ,v8cSet_nullableStringProperty
+  );
+  instance_template->SetAccessor(
+    v8::String::NewFromUtf8(isolate, "nullableObjectProperty",
+                              v8::NewStringType::kInternalized)
+          .ToLocalChecked(),
+    v8cGet_nullableObjectProperty
+    ,v8cSet_nullableObjectProperty
+  );
+
+  instance_template->Set(
+      v8::String::NewFromUtf8(
+          isolate,
+          "nullableBooleanArgument",
+          v8::NewStringType::kInternalized).ToLocalChecked(),
+      v8::FunctionTemplate::New(isolate, DummyFunction)
+  );
+  instance_template->Set(
+      v8::String::NewFromUtf8(
+          isolate,
+          "nullableBooleanOperation",
+          v8::NewStringType::kInternalized).ToLocalChecked(),
+      v8::FunctionTemplate::New(isolate, DummyFunction)
+  );
+  instance_template->Set(
+      v8::String::NewFromUtf8(
+          isolate,
+          "nullableNumericArgument",
+          v8::NewStringType::kInternalized).ToLocalChecked(),
+      v8::FunctionTemplate::New(isolate, DummyFunction)
+  );
+  instance_template->Set(
+      v8::String::NewFromUtf8(
+          isolate,
+          "nullableNumericOperation",
+          v8::NewStringType::kInternalized).ToLocalChecked(),
+      v8::FunctionTemplate::New(isolate, DummyFunction)
+  );
+  instance_template->Set(
+      v8::String::NewFromUtf8(
+          isolate,
+          "nullableObjectArgument",
+          v8::NewStringType::kInternalized).ToLocalChecked(),
+      v8::FunctionTemplate::New(isolate, DummyFunction)
+  );
+  instance_template->Set(
+      v8::String::NewFromUtf8(
+          isolate,
+          "nullableObjectOperation",
+          v8::NewStringType::kInternalized).ToLocalChecked(),
+      v8::FunctionTemplate::New(isolate, DummyFunction)
+  );
+  instance_template->Set(
+      v8::String::NewFromUtf8(
+          isolate,
+          "nullableStringArgument",
+          v8::NewStringType::kInternalized).ToLocalChecked(),
+      v8::FunctionTemplate::New(isolate, DummyFunction)
+  );
+  instance_template->Set(
+      v8::String::NewFromUtf8(
+          isolate,
+          "nullableStringOperation",
+          v8::NewStringType::kInternalized).ToLocalChecked(),
+      v8::FunctionTemplate::New(isolate, DummyFunction)
+  );
+
+  interface_data->templ.Set(env->isolate(), function_template);
+}
+
+inline InterfaceData* GetInterfaceData(V8cGlobalEnvironment* env) {
+  const int kInterfaceUniqueId = 36;
+  // By convention, the |V8cGlobalEnvironment| that we are associated with
+  // will hold our |InterfaceData| at index |kInterfaceUniqueId|, as we asked
+  // for it to be there in the first place, and could not have conflicted with
+  // any other interface.
+  return env->GetInterfaceData(kInterfaceUniqueId);
+}
+
+}  // namespace
+
+v8::Local<v8::Object> V8cNullableTypesTestInterface::CreateWrapper(V8cGlobalEnvironment* env, const scoped_refptr<Wrappable>& wrappable) {
+  v8::Isolate* isolate = env->isolate();
+  v8::Isolate::Scope isolate_scope(isolate);
+  v8::EscapableHandleScope handle_scope(isolate);
+  v8::Local<v8::Context> context = env->context();
+  v8::Context::Scope scope(context);
+
+  InterfaceData* interface_data = GetInterfaceData(env);
+  if (interface_data->templ.IsEmpty()) {
+    InitializeTemplate(env, interface_data);
+  }
+  DCHECK(!interface_data->templ.IsEmpty());
+
+  v8::Local<v8::FunctionTemplate> function_template = interface_data->templ.Get(isolate);
+  DCHECK(function_template->InstanceTemplate()->InternalFieldCount() == 1);
+  v8::Local<v8::Object> object = function_template->InstanceTemplate()->NewInstance(context).ToLocalChecked();
+  DCHECK(object->InternalFieldCount() == 1);
+
+  // |WrapperPrivate|'s lifetime will be managed by V8.
+  new WrapperPrivate(isolate, wrappable, object);
+  return handle_scope.Escape(object);
+}
+
+v8::Local<v8::FunctionTemplate> V8cNullableTypesTestInterface::CreateTemplate(V8cGlobalEnvironment* env) {
+  InterfaceData* interface_data = GetInterfaceData(env);
+  if (interface_data->templ.IsEmpty()) {
+    InitializeTemplate(env, interface_data);
+  }
+
+  return interface_data->templ.Get(env->isolate());
+}
+
+
+}  // namespace testing
+}  // namespace bindings
+}  // namespace cobalt
+
+
diff --git a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_nullable_types_test_interface.h b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_nullable_types_test_interface.h
new file mode 100644
index 0000000..9acc4f0
--- /dev/null
+++ b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_nullable_types_test_interface.h
@@ -0,0 +1,50 @@
+
+// Copyright 2017 Google Inc. All Rights Reserved.
+//
+// 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.
+
+// clang-format off
+
+// This file has been auto-generated by bindings/code_generator_cobalt.py. DO NOT MODIFY!
+// Auto-generated from template: bindings/v8c/templates/interface.h.template
+
+#ifndef V8cNullableTypesTestInterface_h
+#define V8cNullableTypesTestInterface_h
+
+#include "base/hash_tables.h"
+#include "base/lazy_instance.h"
+#include "base/memory/ref_counted.h"
+#include "base/threading/thread_checker.h"
+#include "cobalt/base/polymorphic_downcast.h"
+#include "cobalt/script/wrappable.h"
+#include "cobalt/bindings/testing/nullable_types_test_interface.h"
+
+#include "cobalt/script/v8c/v8c_global_environment.h"
+#include "v8/include/v8.h"
+
+namespace cobalt {
+namespace bindings {
+namespace testing {
+
+class V8cNullableTypesTestInterface {
+ public:
+  static v8::Local<v8::Object> CreateWrapper(script::v8c::V8cGlobalEnvironment* env, const scoped_refptr<script::Wrappable>& wrappable);
+  static v8::Local<v8::FunctionTemplate> CreateTemplate(script::v8c::V8cGlobalEnvironment* env);
+  // TODO: Add |GetInterfaceObject|.
+};
+
+}  // namespace testing
+}  // namespace bindings
+}  // namespace cobalt
+
+#endif  // V8cNullableTypesTestInterface_h
diff --git a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_numeric_types_test_interface.cc b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_numeric_types_test_interface.cc
new file mode 100644
index 0000000..d3a3457
--- /dev/null
+++ b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_numeric_types_test_interface.cc
@@ -0,0 +1,1030 @@
+
+
+// Copyright 2017 Google Inc. All Rights Reserved.
+//
+// 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.
+
+// clang-format off
+
+// This file has been auto-generated by bindings/code_generator_cobalt.py. DO NOT MODIFY!
+// Auto-generated from template: bindings/v8c/templates/interface.cc.template
+
+#include "cobalt/bindings/testing/v8c_numeric_types_test_interface.h"
+
+#include "base/debug/trace_event.h"
+#include "cobalt/base/polymorphic_downcast.h"
+#include "cobalt/script/global_environment.h"
+#include "cobalt/script/script_value.h"
+#include "cobalt/script/value_handle.h"
+
+#include "v8c_gen_type_conversion.h"
+
+#include "cobalt/script/callback_interface_traits.h"
+#include "cobalt/script/v8c/callback_function_conversion.h"
+#include "cobalt/script/v8c/conversion_helpers.h"
+#include "cobalt/script/v8c/native_promise.h"
+#include "cobalt/script/v8c/type_traits.h"
+#include "cobalt/script/v8c/v8c_callback_function.h"
+#include "cobalt/script/v8c/v8c_callback_interface_holder.h"
+#include "cobalt/script/v8c/v8c_exception_state.h"
+#include "cobalt/script/v8c/v8c_global_environment.h"
+#include "cobalt/script/v8c/v8c_value_handle.h"
+#include "cobalt/script/v8c/wrapper_private.h"
+#include "v8/include/v8.h"
+
+
+namespace {
+using cobalt::bindings::testing::NumericTypesTestInterface;
+using cobalt::bindings::testing::V8cNumericTypesTestInterface;
+using cobalt::script::CallbackInterfaceTraits;
+using cobalt::script::GlobalEnvironment;
+using cobalt::script::ScriptValue;
+using cobalt::script::ValueHandle;
+using cobalt::script::ValueHandle;
+using cobalt::script::ValueHandleHolder;
+using cobalt::script::Wrappable;
+
+using cobalt::script::v8c::FromJSValue;
+using cobalt::script::v8c::InterfaceData;
+using cobalt::script::v8c::kConversionFlagClamped;
+using cobalt::script::v8c::kConversionFlagNullable;
+using cobalt::script::v8c::kConversionFlagRestricted;
+using cobalt::script::v8c::kConversionFlagTreatNullAsEmptyString;
+using cobalt::script::v8c::kConversionFlagTreatUndefinedAsEmptyString;
+using cobalt::script::v8c::kNoConversionFlags;
+using cobalt::script::v8c::TypeTraits;
+using cobalt::script::v8c::V8cExceptionState;
+using cobalt::script::v8c::V8cGlobalEnvironment;
+using cobalt::script::v8c::WrapperFactory;
+using cobalt::script::v8c::WrapperPrivate;
+
+v8::Local<v8::Object> DummyFunctor(V8cGlobalEnvironment*, const scoped_refptr<Wrappable>&) {
+  NOTIMPLEMENTED();
+  return {};
+}
+
+}  // namespace
+
+namespace cobalt {
+namespace bindings {
+namespace testing {
+
+
+namespace {
+
+void NumericTypesTestInterfaceConstructor(const v8::FunctionCallbackInfo<v8::Value>& args) {
+  NOTIMPLEMENTED();
+  if (!args.IsConstructCall()) {
+    // TODO: Probably throw something here...
+    return;
+  }
+
+  DCHECK(args.This()->InternalFieldCount() == 1);
+  args.This()->SetInternalField(0, v8::External::New(args.GetIsolate(), nullptr));
+  args.GetReturnValue().Set(args.This());
+}
+
+
+void v8cGet_byteProperty(
+  v8::Local<v8::String> property,
+  const v8::PropertyCallbackInfo<v8::Value>& info)
+{
+  NOTIMPLEMENTED();
+
+  v8::Local<v8::External> external = v8::Local<v8::External>::Cast(info.Holder()->GetInternalField(0));
+  WrapperPrivate* wrapper_private = static_cast<WrapperPrivate*>(external->Value());
+  NumericTypesTestInterface* impl = static_cast<NumericTypesTestInterface*>(wrapper_private->wrappable<NumericTypesTestInterface>());
+
+  v8::Local<v8::Value> result_value;
+}
+
+
+void v8cSet_byteProperty(
+  v8::Local<v8::String> property,
+  v8::Local<v8::Value> v8_value,
+  const v8::PropertyCallbackInfo<void>& info)
+{
+  v8::Local<v8::External> external = v8::Local<v8::External>::Cast(info.Holder()->GetInternalField(0));
+  WrapperPrivate* wrapper_private = static_cast<WrapperPrivate*>(external->Value());
+  NumericTypesTestInterface* impl = static_cast<NumericTypesTestInterface*>(wrapper_private->wrappable<NumericTypesTestInterface>());
+
+  TypeTraits<int8_t>::ConversionType conversion_value;
+  V8cExceptionState exception_state{};
+  FromJSValue(info.GetIsolate(), v8_value, kNoConversionFlags, &exception_state, &conversion_value);
+  impl->set_byte_property(
+    conversion_value
+  );
+}
+
+
+
+void v8cGet_byteClampProperty(
+  v8::Local<v8::String> property,
+  const v8::PropertyCallbackInfo<v8::Value>& info)
+{
+  NOTIMPLEMENTED();
+
+  v8::Local<v8::External> external = v8::Local<v8::External>::Cast(info.Holder()->GetInternalField(0));
+  WrapperPrivate* wrapper_private = static_cast<WrapperPrivate*>(external->Value());
+  NumericTypesTestInterface* impl = static_cast<NumericTypesTestInterface*>(wrapper_private->wrappable<NumericTypesTestInterface>());
+
+  v8::Local<v8::Value> result_value;
+}
+
+
+void v8cSet_byteClampProperty(
+  v8::Local<v8::String> property,
+  v8::Local<v8::Value> v8_value,
+  const v8::PropertyCallbackInfo<void>& info)
+{
+  v8::Local<v8::External> external = v8::Local<v8::External>::Cast(info.Holder()->GetInternalField(0));
+  WrapperPrivate* wrapper_private = static_cast<WrapperPrivate*>(external->Value());
+  NumericTypesTestInterface* impl = static_cast<NumericTypesTestInterface*>(wrapper_private->wrappable<NumericTypesTestInterface>());
+
+  TypeTraits<int8_t>::ConversionType conversion_value;
+  V8cExceptionState exception_state{};
+  FromJSValue(info.GetIsolate(), v8_value, (kConversionFlagClamped), &exception_state, &conversion_value);
+  impl->set_byte_clamp_property(
+    conversion_value
+  );
+}
+
+
+
+void v8cGet_octetProperty(
+  v8::Local<v8::String> property,
+  const v8::PropertyCallbackInfo<v8::Value>& info)
+{
+  NOTIMPLEMENTED();
+
+  v8::Local<v8::External> external = v8::Local<v8::External>::Cast(info.Holder()->GetInternalField(0));
+  WrapperPrivate* wrapper_private = static_cast<WrapperPrivate*>(external->Value());
+  NumericTypesTestInterface* impl = static_cast<NumericTypesTestInterface*>(wrapper_private->wrappable<NumericTypesTestInterface>());
+
+  v8::Local<v8::Value> result_value;
+}
+
+
+void v8cSet_octetProperty(
+  v8::Local<v8::String> property,
+  v8::Local<v8::Value> v8_value,
+  const v8::PropertyCallbackInfo<void>& info)
+{
+  v8::Local<v8::External> external = v8::Local<v8::External>::Cast(info.Holder()->GetInternalField(0));
+  WrapperPrivate* wrapper_private = static_cast<WrapperPrivate*>(external->Value());
+  NumericTypesTestInterface* impl = static_cast<NumericTypesTestInterface*>(wrapper_private->wrappable<NumericTypesTestInterface>());
+
+  TypeTraits<uint8_t>::ConversionType conversion_value;
+  V8cExceptionState exception_state{};
+  FromJSValue(info.GetIsolate(), v8_value, kNoConversionFlags, &exception_state, &conversion_value);
+  impl->set_octet_property(
+    conversion_value
+  );
+}
+
+
+
+void v8cGet_octetClampProperty(
+  v8::Local<v8::String> property,
+  const v8::PropertyCallbackInfo<v8::Value>& info)
+{
+  NOTIMPLEMENTED();
+
+  v8::Local<v8::External> external = v8::Local<v8::External>::Cast(info.Holder()->GetInternalField(0));
+  WrapperPrivate* wrapper_private = static_cast<WrapperPrivate*>(external->Value());
+  NumericTypesTestInterface* impl = static_cast<NumericTypesTestInterface*>(wrapper_private->wrappable<NumericTypesTestInterface>());
+
+  v8::Local<v8::Value> result_value;
+}
+
+
+void v8cSet_octetClampProperty(
+  v8::Local<v8::String> property,
+  v8::Local<v8::Value> v8_value,
+  const v8::PropertyCallbackInfo<void>& info)
+{
+  v8::Local<v8::External> external = v8::Local<v8::External>::Cast(info.Holder()->GetInternalField(0));
+  WrapperPrivate* wrapper_private = static_cast<WrapperPrivate*>(external->Value());
+  NumericTypesTestInterface* impl = static_cast<NumericTypesTestInterface*>(wrapper_private->wrappable<NumericTypesTestInterface>());
+
+  TypeTraits<uint8_t>::ConversionType conversion_value;
+  V8cExceptionState exception_state{};
+  FromJSValue(info.GetIsolate(), v8_value, (kConversionFlagClamped), &exception_state, &conversion_value);
+  impl->set_octet_clamp_property(
+    conversion_value
+  );
+}
+
+
+
+void v8cGet_shortProperty(
+  v8::Local<v8::String> property,
+  const v8::PropertyCallbackInfo<v8::Value>& info)
+{
+  NOTIMPLEMENTED();
+
+  v8::Local<v8::External> external = v8::Local<v8::External>::Cast(info.Holder()->GetInternalField(0));
+  WrapperPrivate* wrapper_private = static_cast<WrapperPrivate*>(external->Value());
+  NumericTypesTestInterface* impl = static_cast<NumericTypesTestInterface*>(wrapper_private->wrappable<NumericTypesTestInterface>());
+
+  v8::Local<v8::Value> result_value;
+}
+
+
+void v8cSet_shortProperty(
+  v8::Local<v8::String> property,
+  v8::Local<v8::Value> v8_value,
+  const v8::PropertyCallbackInfo<void>& info)
+{
+  v8::Local<v8::External> external = v8::Local<v8::External>::Cast(info.Holder()->GetInternalField(0));
+  WrapperPrivate* wrapper_private = static_cast<WrapperPrivate*>(external->Value());
+  NumericTypesTestInterface* impl = static_cast<NumericTypesTestInterface*>(wrapper_private->wrappable<NumericTypesTestInterface>());
+
+  TypeTraits<int16_t>::ConversionType conversion_value;
+  V8cExceptionState exception_state{};
+  FromJSValue(info.GetIsolate(), v8_value, kNoConversionFlags, &exception_state, &conversion_value);
+  impl->set_short_property(
+    conversion_value
+  );
+}
+
+
+
+void v8cGet_shortClampProperty(
+  v8::Local<v8::String> property,
+  const v8::PropertyCallbackInfo<v8::Value>& info)
+{
+  NOTIMPLEMENTED();
+
+  v8::Local<v8::External> external = v8::Local<v8::External>::Cast(info.Holder()->GetInternalField(0));
+  WrapperPrivate* wrapper_private = static_cast<WrapperPrivate*>(external->Value());
+  NumericTypesTestInterface* impl = static_cast<NumericTypesTestInterface*>(wrapper_private->wrappable<NumericTypesTestInterface>());
+
+  v8::Local<v8::Value> result_value;
+}
+
+
+void v8cSet_shortClampProperty(
+  v8::Local<v8::String> property,
+  v8::Local<v8::Value> v8_value,
+  const v8::PropertyCallbackInfo<void>& info)
+{
+  v8::Local<v8::External> external = v8::Local<v8::External>::Cast(info.Holder()->GetInternalField(0));
+  WrapperPrivate* wrapper_private = static_cast<WrapperPrivate*>(external->Value());
+  NumericTypesTestInterface* impl = static_cast<NumericTypesTestInterface*>(wrapper_private->wrappable<NumericTypesTestInterface>());
+
+  TypeTraits<int16_t>::ConversionType conversion_value;
+  V8cExceptionState exception_state{};
+  FromJSValue(info.GetIsolate(), v8_value, (kConversionFlagClamped), &exception_state, &conversion_value);
+  impl->set_short_clamp_property(
+    conversion_value
+  );
+}
+
+
+
+void v8cGet_unsignedShortProperty(
+  v8::Local<v8::String> property,
+  const v8::PropertyCallbackInfo<v8::Value>& info)
+{
+  NOTIMPLEMENTED();
+
+  v8::Local<v8::External> external = v8::Local<v8::External>::Cast(info.Holder()->GetInternalField(0));
+  WrapperPrivate* wrapper_private = static_cast<WrapperPrivate*>(external->Value());
+  NumericTypesTestInterface* impl = static_cast<NumericTypesTestInterface*>(wrapper_private->wrappable<NumericTypesTestInterface>());
+
+  v8::Local<v8::Value> result_value;
+}
+
+
+void v8cSet_unsignedShortProperty(
+  v8::Local<v8::String> property,
+  v8::Local<v8::Value> v8_value,
+  const v8::PropertyCallbackInfo<void>& info)
+{
+  v8::Local<v8::External> external = v8::Local<v8::External>::Cast(info.Holder()->GetInternalField(0));
+  WrapperPrivate* wrapper_private = static_cast<WrapperPrivate*>(external->Value());
+  NumericTypesTestInterface* impl = static_cast<NumericTypesTestInterface*>(wrapper_private->wrappable<NumericTypesTestInterface>());
+
+  TypeTraits<uint16_t>::ConversionType conversion_value;
+  V8cExceptionState exception_state{};
+  FromJSValue(info.GetIsolate(), v8_value, kNoConversionFlags, &exception_state, &conversion_value);
+  impl->set_unsigned_short_property(
+    conversion_value
+  );
+}
+
+
+
+void v8cGet_unsignedShortClampProperty(
+  v8::Local<v8::String> property,
+  const v8::PropertyCallbackInfo<v8::Value>& info)
+{
+  NOTIMPLEMENTED();
+
+  v8::Local<v8::External> external = v8::Local<v8::External>::Cast(info.Holder()->GetInternalField(0));
+  WrapperPrivate* wrapper_private = static_cast<WrapperPrivate*>(external->Value());
+  NumericTypesTestInterface* impl = static_cast<NumericTypesTestInterface*>(wrapper_private->wrappable<NumericTypesTestInterface>());
+
+  v8::Local<v8::Value> result_value;
+}
+
+
+void v8cSet_unsignedShortClampProperty(
+  v8::Local<v8::String> property,
+  v8::Local<v8::Value> v8_value,
+  const v8::PropertyCallbackInfo<void>& info)
+{
+  v8::Local<v8::External> external = v8::Local<v8::External>::Cast(info.Holder()->GetInternalField(0));
+  WrapperPrivate* wrapper_private = static_cast<WrapperPrivate*>(external->Value());
+  NumericTypesTestInterface* impl = static_cast<NumericTypesTestInterface*>(wrapper_private->wrappable<NumericTypesTestInterface>());
+
+  TypeTraits<uint16_t>::ConversionType conversion_value;
+  V8cExceptionState exception_state{};
+  FromJSValue(info.GetIsolate(), v8_value, (kConversionFlagClamped), &exception_state, &conversion_value);
+  impl->set_unsigned_short_clamp_property(
+    conversion_value
+  );
+}
+
+
+
+void v8cGet_longProperty(
+  v8::Local<v8::String> property,
+  const v8::PropertyCallbackInfo<v8::Value>& info)
+{
+  NOTIMPLEMENTED();
+
+  v8::Local<v8::External> external = v8::Local<v8::External>::Cast(info.Holder()->GetInternalField(0));
+  WrapperPrivate* wrapper_private = static_cast<WrapperPrivate*>(external->Value());
+  NumericTypesTestInterface* impl = static_cast<NumericTypesTestInterface*>(wrapper_private->wrappable<NumericTypesTestInterface>());
+
+  v8::Local<v8::Value> result_value;
+}
+
+
+void v8cSet_longProperty(
+  v8::Local<v8::String> property,
+  v8::Local<v8::Value> v8_value,
+  const v8::PropertyCallbackInfo<void>& info)
+{
+  v8::Local<v8::External> external = v8::Local<v8::External>::Cast(info.Holder()->GetInternalField(0));
+  WrapperPrivate* wrapper_private = static_cast<WrapperPrivate*>(external->Value());
+  NumericTypesTestInterface* impl = static_cast<NumericTypesTestInterface*>(wrapper_private->wrappable<NumericTypesTestInterface>());
+
+  TypeTraits<int32_t>::ConversionType conversion_value;
+  V8cExceptionState exception_state{};
+  FromJSValue(info.GetIsolate(), v8_value, kNoConversionFlags, &exception_state, &conversion_value);
+  impl->set_long_property(
+    conversion_value
+  );
+}
+
+
+
+void v8cGet_longClampProperty(
+  v8::Local<v8::String> property,
+  const v8::PropertyCallbackInfo<v8::Value>& info)
+{
+  NOTIMPLEMENTED();
+
+  v8::Local<v8::External> external = v8::Local<v8::External>::Cast(info.Holder()->GetInternalField(0));
+  WrapperPrivate* wrapper_private = static_cast<WrapperPrivate*>(external->Value());
+  NumericTypesTestInterface* impl = static_cast<NumericTypesTestInterface*>(wrapper_private->wrappable<NumericTypesTestInterface>());
+
+  v8::Local<v8::Value> result_value;
+}
+
+
+void v8cSet_longClampProperty(
+  v8::Local<v8::String> property,
+  v8::Local<v8::Value> v8_value,
+  const v8::PropertyCallbackInfo<void>& info)
+{
+  v8::Local<v8::External> external = v8::Local<v8::External>::Cast(info.Holder()->GetInternalField(0));
+  WrapperPrivate* wrapper_private = static_cast<WrapperPrivate*>(external->Value());
+  NumericTypesTestInterface* impl = static_cast<NumericTypesTestInterface*>(wrapper_private->wrappable<NumericTypesTestInterface>());
+
+  TypeTraits<int32_t>::ConversionType conversion_value;
+  V8cExceptionState exception_state{};
+  FromJSValue(info.GetIsolate(), v8_value, (kConversionFlagClamped), &exception_state, &conversion_value);
+  impl->set_long_clamp_property(
+    conversion_value
+  );
+}
+
+
+
+void v8cGet_unsignedLongProperty(
+  v8::Local<v8::String> property,
+  const v8::PropertyCallbackInfo<v8::Value>& info)
+{
+  NOTIMPLEMENTED();
+
+  v8::Local<v8::External> external = v8::Local<v8::External>::Cast(info.Holder()->GetInternalField(0));
+  WrapperPrivate* wrapper_private = static_cast<WrapperPrivate*>(external->Value());
+  NumericTypesTestInterface* impl = static_cast<NumericTypesTestInterface*>(wrapper_private->wrappable<NumericTypesTestInterface>());
+
+  v8::Local<v8::Value> result_value;
+}
+
+
+void v8cSet_unsignedLongProperty(
+  v8::Local<v8::String> property,
+  v8::Local<v8::Value> v8_value,
+  const v8::PropertyCallbackInfo<void>& info)
+{
+  v8::Local<v8::External> external = v8::Local<v8::External>::Cast(info.Holder()->GetInternalField(0));
+  WrapperPrivate* wrapper_private = static_cast<WrapperPrivate*>(external->Value());
+  NumericTypesTestInterface* impl = static_cast<NumericTypesTestInterface*>(wrapper_private->wrappable<NumericTypesTestInterface>());
+
+  TypeTraits<uint32_t>::ConversionType conversion_value;
+  V8cExceptionState exception_state{};
+  FromJSValue(info.GetIsolate(), v8_value, kNoConversionFlags, &exception_state, &conversion_value);
+  impl->set_unsigned_long_property(
+    conversion_value
+  );
+}
+
+
+
+void v8cGet_unsignedLongClampProperty(
+  v8::Local<v8::String> property,
+  const v8::PropertyCallbackInfo<v8::Value>& info)
+{
+  NOTIMPLEMENTED();
+
+  v8::Local<v8::External> external = v8::Local<v8::External>::Cast(info.Holder()->GetInternalField(0));
+  WrapperPrivate* wrapper_private = static_cast<WrapperPrivate*>(external->Value());
+  NumericTypesTestInterface* impl = static_cast<NumericTypesTestInterface*>(wrapper_private->wrappable<NumericTypesTestInterface>());
+
+  v8::Local<v8::Value> result_value;
+}
+
+
+void v8cSet_unsignedLongClampProperty(
+  v8::Local<v8::String> property,
+  v8::Local<v8::Value> v8_value,
+  const v8::PropertyCallbackInfo<void>& info)
+{
+  v8::Local<v8::External> external = v8::Local<v8::External>::Cast(info.Holder()->GetInternalField(0));
+  WrapperPrivate* wrapper_private = static_cast<WrapperPrivate*>(external->Value());
+  NumericTypesTestInterface* impl = static_cast<NumericTypesTestInterface*>(wrapper_private->wrappable<NumericTypesTestInterface>());
+
+  TypeTraits<uint32_t>::ConversionType conversion_value;
+  V8cExceptionState exception_state{};
+  FromJSValue(info.GetIsolate(), v8_value, (kConversionFlagClamped), &exception_state, &conversion_value);
+  impl->set_unsigned_long_clamp_property(
+    conversion_value
+  );
+}
+
+
+
+void v8cGet_longLongProperty(
+  v8::Local<v8::String> property,
+  const v8::PropertyCallbackInfo<v8::Value>& info)
+{
+  NOTIMPLEMENTED();
+
+  v8::Local<v8::External> external = v8::Local<v8::External>::Cast(info.Holder()->GetInternalField(0));
+  WrapperPrivate* wrapper_private = static_cast<WrapperPrivate*>(external->Value());
+  NumericTypesTestInterface* impl = static_cast<NumericTypesTestInterface*>(wrapper_private->wrappable<NumericTypesTestInterface>());
+
+  v8::Local<v8::Value> result_value;
+}
+
+
+void v8cSet_longLongProperty(
+  v8::Local<v8::String> property,
+  v8::Local<v8::Value> v8_value,
+  const v8::PropertyCallbackInfo<void>& info)
+{
+  v8::Local<v8::External> external = v8::Local<v8::External>::Cast(info.Holder()->GetInternalField(0));
+  WrapperPrivate* wrapper_private = static_cast<WrapperPrivate*>(external->Value());
+  NumericTypesTestInterface* impl = static_cast<NumericTypesTestInterface*>(wrapper_private->wrappable<NumericTypesTestInterface>());
+
+  TypeTraits<int64_t>::ConversionType conversion_value;
+  V8cExceptionState exception_state{};
+  FromJSValue(info.GetIsolate(), v8_value, kNoConversionFlags, &exception_state, &conversion_value);
+  impl->set_long_long_property(
+    conversion_value
+  );
+}
+
+
+
+void v8cGet_longLongClampProperty(
+  v8::Local<v8::String> property,
+  const v8::PropertyCallbackInfo<v8::Value>& info)
+{
+  NOTIMPLEMENTED();
+
+  v8::Local<v8::External> external = v8::Local<v8::External>::Cast(info.Holder()->GetInternalField(0));
+  WrapperPrivate* wrapper_private = static_cast<WrapperPrivate*>(external->Value());
+  NumericTypesTestInterface* impl = static_cast<NumericTypesTestInterface*>(wrapper_private->wrappable<NumericTypesTestInterface>());
+
+  v8::Local<v8::Value> result_value;
+}
+
+
+void v8cSet_longLongClampProperty(
+  v8::Local<v8::String> property,
+  v8::Local<v8::Value> v8_value,
+  const v8::PropertyCallbackInfo<void>& info)
+{
+  v8::Local<v8::External> external = v8::Local<v8::External>::Cast(info.Holder()->GetInternalField(0));
+  WrapperPrivate* wrapper_private = static_cast<WrapperPrivate*>(external->Value());
+  NumericTypesTestInterface* impl = static_cast<NumericTypesTestInterface*>(wrapper_private->wrappable<NumericTypesTestInterface>());
+
+  TypeTraits<int64_t>::ConversionType conversion_value;
+  V8cExceptionState exception_state{};
+  FromJSValue(info.GetIsolate(), v8_value, (kConversionFlagClamped), &exception_state, &conversion_value);
+  impl->set_long_long_clamp_property(
+    conversion_value
+  );
+}
+
+
+
+void v8cGet_unsignedLongLongProperty(
+  v8::Local<v8::String> property,
+  const v8::PropertyCallbackInfo<v8::Value>& info)
+{
+  NOTIMPLEMENTED();
+
+  v8::Local<v8::External> external = v8::Local<v8::External>::Cast(info.Holder()->GetInternalField(0));
+  WrapperPrivate* wrapper_private = static_cast<WrapperPrivate*>(external->Value());
+  NumericTypesTestInterface* impl = static_cast<NumericTypesTestInterface*>(wrapper_private->wrappable<NumericTypesTestInterface>());
+
+  v8::Local<v8::Value> result_value;
+}
+
+
+void v8cSet_unsignedLongLongProperty(
+  v8::Local<v8::String> property,
+  v8::Local<v8::Value> v8_value,
+  const v8::PropertyCallbackInfo<void>& info)
+{
+  v8::Local<v8::External> external = v8::Local<v8::External>::Cast(info.Holder()->GetInternalField(0));
+  WrapperPrivate* wrapper_private = static_cast<WrapperPrivate*>(external->Value());
+  NumericTypesTestInterface* impl = static_cast<NumericTypesTestInterface*>(wrapper_private->wrappable<NumericTypesTestInterface>());
+
+  TypeTraits<uint64_t>::ConversionType conversion_value;
+  V8cExceptionState exception_state{};
+  FromJSValue(info.GetIsolate(), v8_value, kNoConversionFlags, &exception_state, &conversion_value);
+  impl->set_unsigned_long_long_property(
+    conversion_value
+  );
+}
+
+
+
+void v8cGet_unsignedLongLongClampProperty(
+  v8::Local<v8::String> property,
+  const v8::PropertyCallbackInfo<v8::Value>& info)
+{
+  NOTIMPLEMENTED();
+
+  v8::Local<v8::External> external = v8::Local<v8::External>::Cast(info.Holder()->GetInternalField(0));
+  WrapperPrivate* wrapper_private = static_cast<WrapperPrivate*>(external->Value());
+  NumericTypesTestInterface* impl = static_cast<NumericTypesTestInterface*>(wrapper_private->wrappable<NumericTypesTestInterface>());
+
+  v8::Local<v8::Value> result_value;
+}
+
+
+void v8cSet_unsignedLongLongClampProperty(
+  v8::Local<v8::String> property,
+  v8::Local<v8::Value> v8_value,
+  const v8::PropertyCallbackInfo<void>& info)
+{
+  v8::Local<v8::External> external = v8::Local<v8::External>::Cast(info.Holder()->GetInternalField(0));
+  WrapperPrivate* wrapper_private = static_cast<WrapperPrivate*>(external->Value());
+  NumericTypesTestInterface* impl = static_cast<NumericTypesTestInterface*>(wrapper_private->wrappable<NumericTypesTestInterface>());
+
+  TypeTraits<uint64_t>::ConversionType conversion_value;
+  V8cExceptionState exception_state{};
+  FromJSValue(info.GetIsolate(), v8_value, (kConversionFlagClamped), &exception_state, &conversion_value);
+  impl->set_unsigned_long_long_clamp_property(
+    conversion_value
+  );
+}
+
+
+
+void v8cGet_doubleProperty(
+  v8::Local<v8::String> property,
+  const v8::PropertyCallbackInfo<v8::Value>& info)
+{
+  NOTIMPLEMENTED();
+
+  v8::Local<v8::External> external = v8::Local<v8::External>::Cast(info.Holder()->GetInternalField(0));
+  WrapperPrivate* wrapper_private = static_cast<WrapperPrivate*>(external->Value());
+  NumericTypesTestInterface* impl = static_cast<NumericTypesTestInterface*>(wrapper_private->wrappable<NumericTypesTestInterface>());
+
+  v8::Local<v8::Value> result_value;
+}
+
+
+void v8cSet_doubleProperty(
+  v8::Local<v8::String> property,
+  v8::Local<v8::Value> v8_value,
+  const v8::PropertyCallbackInfo<void>& info)
+{
+  v8::Local<v8::External> external = v8::Local<v8::External>::Cast(info.Holder()->GetInternalField(0));
+  WrapperPrivate* wrapper_private = static_cast<WrapperPrivate*>(external->Value());
+  NumericTypesTestInterface* impl = static_cast<NumericTypesTestInterface*>(wrapper_private->wrappable<NumericTypesTestInterface>());
+
+  TypeTraits<double>::ConversionType conversion_value;
+  V8cExceptionState exception_state{};
+  FromJSValue(info.GetIsolate(), v8_value, (kConversionFlagRestricted), &exception_state, &conversion_value);
+  impl->set_double_property(
+    conversion_value
+  );
+}
+
+
+
+void v8cGet_unrestrictedDoubleProperty(
+  v8::Local<v8::String> property,
+  const v8::PropertyCallbackInfo<v8::Value>& info)
+{
+  NOTIMPLEMENTED();
+
+  v8::Local<v8::External> external = v8::Local<v8::External>::Cast(info.Holder()->GetInternalField(0));
+  WrapperPrivate* wrapper_private = static_cast<WrapperPrivate*>(external->Value());
+  NumericTypesTestInterface* impl = static_cast<NumericTypesTestInterface*>(wrapper_private->wrappable<NumericTypesTestInterface>());
+
+  v8::Local<v8::Value> result_value;
+}
+
+
+void v8cSet_unrestrictedDoubleProperty(
+  v8::Local<v8::String> property,
+  v8::Local<v8::Value> v8_value,
+  const v8::PropertyCallbackInfo<void>& info)
+{
+  v8::Local<v8::External> external = v8::Local<v8::External>::Cast(info.Holder()->GetInternalField(0));
+  WrapperPrivate* wrapper_private = static_cast<WrapperPrivate*>(external->Value());
+  NumericTypesTestInterface* impl = static_cast<NumericTypesTestInterface*>(wrapper_private->wrappable<NumericTypesTestInterface>());
+
+  TypeTraits<double>::ConversionType conversion_value;
+  V8cExceptionState exception_state{};
+  FromJSValue(info.GetIsolate(), v8_value, kNoConversionFlags, &exception_state, &conversion_value);
+  impl->set_unrestricted_double_property(
+    conversion_value
+  );
+}
+
+
+
+void DummyFunction(const v8::FunctionCallbackInfo<v8::Value>& info) {
+  LOG(INFO) << __func__;
+}
+
+void InitializeTemplate(
+  V8cGlobalEnvironment* env,
+  InterfaceData* interface_data) {
+  v8::Isolate* isolate = env->isolate();
+  v8::Local<v8::FunctionTemplate> function_template = v8::FunctionTemplate::New(
+    isolate);
+  function_template->SetClassName(
+    v8::String::NewFromUtf8(isolate, "NumericTypesTestInterface",
+        v8::NewStringType::kInternalized).ToLocalChecked());
+  v8::Local<v8::ObjectTemplate> instance_template = function_template->InstanceTemplate();
+  instance_template->SetInternalFieldCount(1);
+
+  v8::Local<v8::ObjectTemplate> prototype_template = function_template->PrototypeTemplate();
+  prototype_template->SetInternalFieldCount(1);
+
+  instance_template->SetAccessor(
+    v8::String::NewFromUtf8(isolate, "byteProperty",
+                              v8::NewStringType::kInternalized)
+          .ToLocalChecked(),
+    v8cGet_byteProperty
+    ,v8cSet_byteProperty
+  );
+  instance_template->SetAccessor(
+    v8::String::NewFromUtf8(isolate, "byteClampProperty",
+                              v8::NewStringType::kInternalized)
+          .ToLocalChecked(),
+    v8cGet_byteClampProperty
+    ,v8cSet_byteClampProperty
+  );
+  instance_template->SetAccessor(
+    v8::String::NewFromUtf8(isolate, "octetProperty",
+                              v8::NewStringType::kInternalized)
+          .ToLocalChecked(),
+    v8cGet_octetProperty
+    ,v8cSet_octetProperty
+  );
+  instance_template->SetAccessor(
+    v8::String::NewFromUtf8(isolate, "octetClampProperty",
+                              v8::NewStringType::kInternalized)
+          .ToLocalChecked(),
+    v8cGet_octetClampProperty
+    ,v8cSet_octetClampProperty
+  );
+  instance_template->SetAccessor(
+    v8::String::NewFromUtf8(isolate, "shortProperty",
+                              v8::NewStringType::kInternalized)
+          .ToLocalChecked(),
+    v8cGet_shortProperty
+    ,v8cSet_shortProperty
+  );
+  instance_template->SetAccessor(
+    v8::String::NewFromUtf8(isolate, "shortClampProperty",
+                              v8::NewStringType::kInternalized)
+          .ToLocalChecked(),
+    v8cGet_shortClampProperty
+    ,v8cSet_shortClampProperty
+  );
+  instance_template->SetAccessor(
+    v8::String::NewFromUtf8(isolate, "unsignedShortProperty",
+                              v8::NewStringType::kInternalized)
+          .ToLocalChecked(),
+    v8cGet_unsignedShortProperty
+    ,v8cSet_unsignedShortProperty
+  );
+  instance_template->SetAccessor(
+    v8::String::NewFromUtf8(isolate, "unsignedShortClampProperty",
+                              v8::NewStringType::kInternalized)
+          .ToLocalChecked(),
+    v8cGet_unsignedShortClampProperty
+    ,v8cSet_unsignedShortClampProperty
+  );
+  instance_template->SetAccessor(
+    v8::String::NewFromUtf8(isolate, "longProperty",
+                              v8::NewStringType::kInternalized)
+          .ToLocalChecked(),
+    v8cGet_longProperty
+    ,v8cSet_longProperty
+  );
+  instance_template->SetAccessor(
+    v8::String::NewFromUtf8(isolate, "longClampProperty",
+                              v8::NewStringType::kInternalized)
+          .ToLocalChecked(),
+    v8cGet_longClampProperty
+    ,v8cSet_longClampProperty
+  );
+  instance_template->SetAccessor(
+    v8::String::NewFromUtf8(isolate, "unsignedLongProperty",
+                              v8::NewStringType::kInternalized)
+          .ToLocalChecked(),
+    v8cGet_unsignedLongProperty
+    ,v8cSet_unsignedLongProperty
+  );
+  instance_template->SetAccessor(
+    v8::String::NewFromUtf8(isolate, "unsignedLongClampProperty",
+                              v8::NewStringType::kInternalized)
+          .ToLocalChecked(),
+    v8cGet_unsignedLongClampProperty
+    ,v8cSet_unsignedLongClampProperty
+  );
+  instance_template->SetAccessor(
+    v8::String::NewFromUtf8(isolate, "longLongProperty",
+                              v8::NewStringType::kInternalized)
+          .ToLocalChecked(),
+    v8cGet_longLongProperty
+    ,v8cSet_longLongProperty
+  );
+  instance_template->SetAccessor(
+    v8::String::NewFromUtf8(isolate, "longLongClampProperty",
+                              v8::NewStringType::kInternalized)
+          .ToLocalChecked(),
+    v8cGet_longLongClampProperty
+    ,v8cSet_longLongClampProperty
+  );
+  instance_template->SetAccessor(
+    v8::String::NewFromUtf8(isolate, "unsignedLongLongProperty",
+                              v8::NewStringType::kInternalized)
+          .ToLocalChecked(),
+    v8cGet_unsignedLongLongProperty
+    ,v8cSet_unsignedLongLongProperty
+  );
+  instance_template->SetAccessor(
+    v8::String::NewFromUtf8(isolate, "unsignedLongLongClampProperty",
+                              v8::NewStringType::kInternalized)
+          .ToLocalChecked(),
+    v8cGet_unsignedLongLongClampProperty
+    ,v8cSet_unsignedLongLongClampProperty
+  );
+  instance_template->SetAccessor(
+    v8::String::NewFromUtf8(isolate, "doubleProperty",
+                              v8::NewStringType::kInternalized)
+          .ToLocalChecked(),
+    v8cGet_doubleProperty
+    ,v8cSet_doubleProperty
+  );
+  instance_template->SetAccessor(
+    v8::String::NewFromUtf8(isolate, "unrestrictedDoubleProperty",
+                              v8::NewStringType::kInternalized)
+          .ToLocalChecked(),
+    v8cGet_unrestrictedDoubleProperty
+    ,v8cSet_unrestrictedDoubleProperty
+  );
+
+  instance_template->Set(
+      v8::String::NewFromUtf8(
+          isolate,
+          "byteArgumentOperation",
+          v8::NewStringType::kInternalized).ToLocalChecked(),
+      v8::FunctionTemplate::New(isolate, DummyFunction)
+  );
+  instance_template->Set(
+      v8::String::NewFromUtf8(
+          isolate,
+          "byteReturnOperation",
+          v8::NewStringType::kInternalized).ToLocalChecked(),
+      v8::FunctionTemplate::New(isolate, DummyFunction)
+  );
+  instance_template->Set(
+      v8::String::NewFromUtf8(
+          isolate,
+          "doubleArgumentOperation",
+          v8::NewStringType::kInternalized).ToLocalChecked(),
+      v8::FunctionTemplate::New(isolate, DummyFunction)
+  );
+  instance_template->Set(
+      v8::String::NewFromUtf8(
+          isolate,
+          "doubleReturnOperation",
+          v8::NewStringType::kInternalized).ToLocalChecked(),
+      v8::FunctionTemplate::New(isolate, DummyFunction)
+  );
+  instance_template->Set(
+      v8::String::NewFromUtf8(
+          isolate,
+          "longArgumentOperation",
+          v8::NewStringType::kInternalized).ToLocalChecked(),
+      v8::FunctionTemplate::New(isolate, DummyFunction)
+  );
+  instance_template->Set(
+      v8::String::NewFromUtf8(
+          isolate,
+          "longLongArgumentOperation",
+          v8::NewStringType::kInternalized).ToLocalChecked(),
+      v8::FunctionTemplate::New(isolate, DummyFunction)
+  );
+  instance_template->Set(
+      v8::String::NewFromUtf8(
+          isolate,
+          "longLongReturnOperation",
+          v8::NewStringType::kInternalized).ToLocalChecked(),
+      v8::FunctionTemplate::New(isolate, DummyFunction)
+  );
+  instance_template->Set(
+      v8::String::NewFromUtf8(
+          isolate,
+          "longReturnOperation",
+          v8::NewStringType::kInternalized).ToLocalChecked(),
+      v8::FunctionTemplate::New(isolate, DummyFunction)
+  );
+  instance_template->Set(
+      v8::String::NewFromUtf8(
+          isolate,
+          "octetArgumentOperation",
+          v8::NewStringType::kInternalized).ToLocalChecked(),
+      v8::FunctionTemplate::New(isolate, DummyFunction)
+  );
+  instance_template->Set(
+      v8::String::NewFromUtf8(
+          isolate,
+          "octetReturnOperation",
+          v8::NewStringType::kInternalized).ToLocalChecked(),
+      v8::FunctionTemplate::New(isolate, DummyFunction)
+  );
+  instance_template->Set(
+      v8::String::NewFromUtf8(
+          isolate,
+          "shortArgumentOperation",
+          v8::NewStringType::kInternalized).ToLocalChecked(),
+      v8::FunctionTemplate::New(isolate, DummyFunction)
+  );
+  instance_template->Set(
+      v8::String::NewFromUtf8(
+          isolate,
+          "shortReturnOperation",
+          v8::NewStringType::kInternalized).ToLocalChecked(),
+      v8::FunctionTemplate::New(isolate, DummyFunction)
+  );
+  instance_template->Set(
+      v8::String::NewFromUtf8(
+          isolate,
+          "unrestrictedDoubleArgumentOperation",
+          v8::NewStringType::kInternalized).ToLocalChecked(),
+      v8::FunctionTemplate::New(isolate, DummyFunction)
+  );
+  instance_template->Set(
+      v8::String::NewFromUtf8(
+          isolate,
+          "unrestrictedDoubleReturnOperation",
+          v8::NewStringType::kInternalized).ToLocalChecked(),
+      v8::FunctionTemplate::New(isolate, DummyFunction)
+  );
+  instance_template->Set(
+      v8::String::NewFromUtf8(
+          isolate,
+          "unsignedLongArgumentOperation",
+          v8::NewStringType::kInternalized).ToLocalChecked(),
+      v8::FunctionTemplate::New(isolate, DummyFunction)
+  );
+  instance_template->Set(
+      v8::String::NewFromUtf8(
+          isolate,
+          "unsignedLongLongArgumentOperation",
+          v8::NewStringType::kInternalized).ToLocalChecked(),
+      v8::FunctionTemplate::New(isolate, DummyFunction)
+  );
+  instance_template->Set(
+      v8::String::NewFromUtf8(
+          isolate,
+          "unsignedLongLongReturnOperation",
+          v8::NewStringType::kInternalized).ToLocalChecked(),
+      v8::FunctionTemplate::New(isolate, DummyFunction)
+  );
+  instance_template->Set(
+      v8::String::NewFromUtf8(
+          isolate,
+          "unsignedLongReturnOperation",
+          v8::NewStringType::kInternalized).ToLocalChecked(),
+      v8::FunctionTemplate::New(isolate, DummyFunction)
+  );
+  instance_template->Set(
+      v8::String::NewFromUtf8(
+          isolate,
+          "unsignedShortArgumentOperation",
+          v8::NewStringType::kInternalized).ToLocalChecked(),
+      v8::FunctionTemplate::New(isolate, DummyFunction)
+  );
+  instance_template->Set(
+      v8::String::NewFromUtf8(
+          isolate,
+          "unsignedShortReturnOperation",
+          v8::NewStringType::kInternalized).ToLocalChecked(),
+      v8::FunctionTemplate::New(isolate, DummyFunction)
+  );
+
+  interface_data->templ.Set(env->isolate(), function_template);
+}
+
+inline InterfaceData* GetInterfaceData(V8cGlobalEnvironment* env) {
+  const int kInterfaceUniqueId = 37;
+  // By convention, the |V8cGlobalEnvironment| that we are associated with
+  // will hold our |InterfaceData| at index |kInterfaceUniqueId|, as we asked
+  // for it to be there in the first place, and could not have conflicted with
+  // any other interface.
+  return env->GetInterfaceData(kInterfaceUniqueId);
+}
+
+}  // namespace
+
+v8::Local<v8::Object> V8cNumericTypesTestInterface::CreateWrapper(V8cGlobalEnvironment* env, const scoped_refptr<Wrappable>& wrappable) {
+  v8::Isolate* isolate = env->isolate();
+  v8::Isolate::Scope isolate_scope(isolate);
+  v8::EscapableHandleScope handle_scope(isolate);
+  v8::Local<v8::Context> context = env->context();
+  v8::Context::Scope scope(context);
+
+  InterfaceData* interface_data = GetInterfaceData(env);
+  if (interface_data->templ.IsEmpty()) {
+    InitializeTemplate(env, interface_data);
+  }
+  DCHECK(!interface_data->templ.IsEmpty());
+
+  v8::Local<v8::FunctionTemplate> function_template = interface_data->templ.Get(isolate);
+  DCHECK(function_template->InstanceTemplate()->InternalFieldCount() == 1);
+  v8::Local<v8::Object> object = function_template->InstanceTemplate()->NewInstance(context).ToLocalChecked();
+  DCHECK(object->InternalFieldCount() == 1);
+
+  // |WrapperPrivate|'s lifetime will be managed by V8.
+  new WrapperPrivate(isolate, wrappable, object);
+  return handle_scope.Escape(object);
+}
+
+v8::Local<v8::FunctionTemplate> V8cNumericTypesTestInterface::CreateTemplate(V8cGlobalEnvironment* env) {
+  InterfaceData* interface_data = GetInterfaceData(env);
+  if (interface_data->templ.IsEmpty()) {
+    InitializeTemplate(env, interface_data);
+  }
+
+  return interface_data->templ.Get(env->isolate());
+}
+
+
+}  // namespace testing
+}  // namespace bindings
+}  // namespace cobalt
+
+
diff --git a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_numeric_types_test_interface.h b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_numeric_types_test_interface.h
new file mode 100644
index 0000000..4ef91c9
--- /dev/null
+++ b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_numeric_types_test_interface.h
@@ -0,0 +1,50 @@
+
+// Copyright 2017 Google Inc. All Rights Reserved.
+//
+// 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.
+
+// clang-format off
+
+// This file has been auto-generated by bindings/code_generator_cobalt.py. DO NOT MODIFY!
+// Auto-generated from template: bindings/v8c/templates/interface.h.template
+
+#ifndef V8cNumericTypesTestInterface_h
+#define V8cNumericTypesTestInterface_h
+
+#include "base/hash_tables.h"
+#include "base/lazy_instance.h"
+#include "base/memory/ref_counted.h"
+#include "base/threading/thread_checker.h"
+#include "cobalt/base/polymorphic_downcast.h"
+#include "cobalt/script/wrappable.h"
+#include "cobalt/bindings/testing/numeric_types_test_interface.h"
+
+#include "cobalt/script/v8c/v8c_global_environment.h"
+#include "v8/include/v8.h"
+
+namespace cobalt {
+namespace bindings {
+namespace testing {
+
+class V8cNumericTypesTestInterface {
+ public:
+  static v8::Local<v8::Object> CreateWrapper(script::v8c::V8cGlobalEnvironment* env, const scoped_refptr<script::Wrappable>& wrappable);
+  static v8::Local<v8::FunctionTemplate> CreateTemplate(script::v8c::V8cGlobalEnvironment* env);
+  // TODO: Add |GetInterfaceObject|.
+};
+
+}  // namespace testing
+}  // namespace bindings
+}  // namespace cobalt
+
+#endif  // V8cNumericTypesTestInterface_h
diff --git a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_object_type_bindings_interface.cc b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_object_type_bindings_interface.cc
new file mode 100644
index 0000000..f6bae33
--- /dev/null
+++ b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_object_type_bindings_interface.cc
@@ -0,0 +1,323 @@
+
+
+// Copyright 2017 Google Inc. All Rights Reserved.
+//
+// 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.
+
+// clang-format off
+
+// This file has been auto-generated by bindings/code_generator_cobalt.py. DO NOT MODIFY!
+// Auto-generated from template: bindings/v8c/templates/interface.cc.template
+
+#include "cobalt/bindings/testing/v8c_object_type_bindings_interface.h"
+
+#include "base/debug/trace_event.h"
+#include "cobalt/base/polymorphic_downcast.h"
+#include "cobalt/script/global_environment.h"
+#include "cobalt/script/script_value.h"
+#include "cobalt/script/value_handle.h"
+#include "cobalt/bindings/testing/arbitrary_interface.h"
+#include "cobalt/bindings/testing/base_interface.h"
+#include "cobalt/bindings/testing/derived_interface.h"
+#include "cobalt/bindings/testing/v8c_arbitrary_interface.h"
+#include "cobalt/bindings/testing/v8c_base_interface.h"
+#include "cobalt/bindings/testing/v8c_derived_interface.h"
+
+#include "v8c_gen_type_conversion.h"
+
+#include "cobalt/script/callback_interface_traits.h"
+#include "cobalt/script/v8c/callback_function_conversion.h"
+#include "cobalt/script/v8c/conversion_helpers.h"
+#include "cobalt/script/v8c/native_promise.h"
+#include "cobalt/script/v8c/type_traits.h"
+#include "cobalt/script/v8c/v8c_callback_function.h"
+#include "cobalt/script/v8c/v8c_callback_interface_holder.h"
+#include "cobalt/script/v8c/v8c_exception_state.h"
+#include "cobalt/script/v8c/v8c_global_environment.h"
+#include "cobalt/script/v8c/v8c_value_handle.h"
+#include "cobalt/script/v8c/wrapper_private.h"
+#include "v8/include/v8.h"
+
+
+namespace {
+using cobalt::bindings::testing::ObjectTypeBindingsInterface;
+using cobalt::bindings::testing::V8cObjectTypeBindingsInterface;
+using cobalt::bindings::testing::ArbitraryInterface;
+using cobalt::bindings::testing::BaseInterface;
+using cobalt::bindings::testing::DerivedInterface;
+using cobalt::bindings::testing::V8cArbitraryInterface;
+using cobalt::bindings::testing::V8cBaseInterface;
+using cobalt::bindings::testing::V8cDerivedInterface;
+using cobalt::script::CallbackInterfaceTraits;
+using cobalt::script::GlobalEnvironment;
+using cobalt::script::ScriptValue;
+using cobalt::script::ValueHandle;
+using cobalt::script::ValueHandle;
+using cobalt::script::ValueHandleHolder;
+using cobalt::script::Wrappable;
+
+using cobalt::script::v8c::FromJSValue;
+using cobalt::script::v8c::InterfaceData;
+using cobalt::script::v8c::kConversionFlagClamped;
+using cobalt::script::v8c::kConversionFlagNullable;
+using cobalt::script::v8c::kConversionFlagRestricted;
+using cobalt::script::v8c::kConversionFlagTreatNullAsEmptyString;
+using cobalt::script::v8c::kConversionFlagTreatUndefinedAsEmptyString;
+using cobalt::script::v8c::kNoConversionFlags;
+using cobalt::script::v8c::TypeTraits;
+using cobalt::script::v8c::V8cExceptionState;
+using cobalt::script::v8c::V8cGlobalEnvironment;
+using cobalt::script::v8c::WrapperFactory;
+using cobalt::script::v8c::WrapperPrivate;
+
+v8::Local<v8::Object> DummyFunctor(V8cGlobalEnvironment*, const scoped_refptr<Wrappable>&) {
+  NOTIMPLEMENTED();
+  return {};
+}
+
+}  // namespace
+
+namespace cobalt {
+namespace bindings {
+namespace testing {
+
+
+namespace {
+
+void ObjectTypeBindingsInterfaceConstructor(const v8::FunctionCallbackInfo<v8::Value>& args) {
+  NOTIMPLEMENTED();
+  if (!args.IsConstructCall()) {
+    // TODO: Probably throw something here...
+    return;
+  }
+
+  DCHECK(args.This()->InternalFieldCount() == 1);
+  args.This()->SetInternalField(0, v8::External::New(args.GetIsolate(), nullptr));
+  args.GetReturnValue().Set(args.This());
+}
+
+
+void v8cGet_arbitraryObject(
+  v8::Local<v8::String> property,
+  const v8::PropertyCallbackInfo<v8::Value>& info)
+{
+  NOTIMPLEMENTED();
+
+  v8::Local<v8::External> external = v8::Local<v8::External>::Cast(info.Holder()->GetInternalField(0));
+  WrapperPrivate* wrapper_private = static_cast<WrapperPrivate*>(external->Value());
+  ObjectTypeBindingsInterface* impl = static_cast<ObjectTypeBindingsInterface*>(wrapper_private->wrappable<ObjectTypeBindingsInterface>());
+
+  v8::Local<v8::Value> result_value;
+}
+
+
+void v8cSet_arbitraryObject(
+  v8::Local<v8::String> property,
+  v8::Local<v8::Value> v8_value,
+  const v8::PropertyCallbackInfo<void>& info)
+{
+  v8::Local<v8::External> external = v8::Local<v8::External>::Cast(info.Holder()->GetInternalField(0));
+  WrapperPrivate* wrapper_private = static_cast<WrapperPrivate*>(external->Value());
+  ObjectTypeBindingsInterface* impl = static_cast<ObjectTypeBindingsInterface*>(wrapper_private->wrappable<ObjectTypeBindingsInterface>());
+
+  TypeTraits<scoped_refptr<ArbitraryInterface>>::ConversionType conversion_value;
+  V8cExceptionState exception_state{};
+  FromJSValue(info.GetIsolate(), v8_value, kNoConversionFlags, &exception_state, &conversion_value);
+  impl->set_arbitrary_object(
+    conversion_value
+  );
+}
+
+
+
+void v8cGet_baseInterface(
+  v8::Local<v8::String> property,
+  const v8::PropertyCallbackInfo<v8::Value>& info)
+{
+  NOTIMPLEMENTED();
+
+  v8::Local<v8::External> external = v8::Local<v8::External>::Cast(info.Holder()->GetInternalField(0));
+  WrapperPrivate* wrapper_private = static_cast<WrapperPrivate*>(external->Value());
+  ObjectTypeBindingsInterface* impl = static_cast<ObjectTypeBindingsInterface*>(wrapper_private->wrappable<ObjectTypeBindingsInterface>());
+
+  v8::Local<v8::Value> result_value;
+}
+
+
+
+void v8cGet_derivedInterface(
+  v8::Local<v8::String> property,
+  const v8::PropertyCallbackInfo<v8::Value>& info)
+{
+  NOTIMPLEMENTED();
+
+  v8::Local<v8::External> external = v8::Local<v8::External>::Cast(info.Holder()->GetInternalField(0));
+  WrapperPrivate* wrapper_private = static_cast<WrapperPrivate*>(external->Value());
+  ObjectTypeBindingsInterface* impl = static_cast<ObjectTypeBindingsInterface*>(wrapper_private->wrappable<ObjectTypeBindingsInterface>());
+
+  v8::Local<v8::Value> result_value;
+}
+
+
+void v8cSet_derivedInterface(
+  v8::Local<v8::String> property,
+  v8::Local<v8::Value> v8_value,
+  const v8::PropertyCallbackInfo<void>& info)
+{
+  v8::Local<v8::External> external = v8::Local<v8::External>::Cast(info.Holder()->GetInternalField(0));
+  WrapperPrivate* wrapper_private = static_cast<WrapperPrivate*>(external->Value());
+  ObjectTypeBindingsInterface* impl = static_cast<ObjectTypeBindingsInterface*>(wrapper_private->wrappable<ObjectTypeBindingsInterface>());
+
+  TypeTraits<scoped_refptr<DerivedInterface>>::ConversionType conversion_value;
+  V8cExceptionState exception_state{};
+  FromJSValue(info.GetIsolate(), v8_value, kNoConversionFlags, &exception_state, &conversion_value);
+  impl->set_derived_interface(
+    conversion_value
+  );
+}
+
+
+
+void v8cGet_objectProperty(
+  v8::Local<v8::String> property,
+  const v8::PropertyCallbackInfo<v8::Value>& info)
+{
+  NOTIMPLEMENTED();
+
+  v8::Local<v8::External> external = v8::Local<v8::External>::Cast(info.Holder()->GetInternalField(0));
+  WrapperPrivate* wrapper_private = static_cast<WrapperPrivate*>(external->Value());
+  ObjectTypeBindingsInterface* impl = static_cast<ObjectTypeBindingsInterface*>(wrapper_private->wrappable<ObjectTypeBindingsInterface>());
+
+  v8::Local<v8::Value> result_value;
+}
+
+
+void v8cSet_objectProperty(
+  v8::Local<v8::String> property,
+  v8::Local<v8::Value> v8_value,
+  const v8::PropertyCallbackInfo<void>& info)
+{
+  v8::Local<v8::External> external = v8::Local<v8::External>::Cast(info.Holder()->GetInternalField(0));
+  WrapperPrivate* wrapper_private = static_cast<WrapperPrivate*>(external->Value());
+  ObjectTypeBindingsInterface* impl = static_cast<ObjectTypeBindingsInterface*>(wrapper_private->wrappable<ObjectTypeBindingsInterface>());
+
+  TypeTraits<::cobalt::script::ValueHandle>::ConversionType conversion_value;
+  V8cExceptionState exception_state{};
+  FromJSValue(info.GetIsolate(), v8_value, (kConversionFlagNullable | kConversionFlagObjectOnly), &exception_state, &conversion_value);
+  impl->set_object_property(
+    conversion_value
+  );
+}
+
+
+
+void DummyFunction(const v8::FunctionCallbackInfo<v8::Value>& info) {
+  LOG(INFO) << __func__;
+}
+
+void InitializeTemplate(
+  V8cGlobalEnvironment* env,
+  InterfaceData* interface_data) {
+  v8::Isolate* isolate = env->isolate();
+  v8::Local<v8::FunctionTemplate> function_template = v8::FunctionTemplate::New(
+    isolate);
+  function_template->SetClassName(
+    v8::String::NewFromUtf8(isolate, "ObjectTypeBindingsInterface",
+        v8::NewStringType::kInternalized).ToLocalChecked());
+  v8::Local<v8::ObjectTemplate> instance_template = function_template->InstanceTemplate();
+  instance_template->SetInternalFieldCount(1);
+
+  v8::Local<v8::ObjectTemplate> prototype_template = function_template->PrototypeTemplate();
+  prototype_template->SetInternalFieldCount(1);
+
+  instance_template->SetAccessor(
+    v8::String::NewFromUtf8(isolate, "arbitraryObject",
+                              v8::NewStringType::kInternalized)
+          .ToLocalChecked(),
+    v8cGet_arbitraryObject
+    ,v8cSet_arbitraryObject
+  );
+  instance_template->SetAccessor(
+    v8::String::NewFromUtf8(isolate, "baseInterface",
+                              v8::NewStringType::kInternalized)
+          .ToLocalChecked(),
+    v8cGet_baseInterface
+  );
+  instance_template->SetAccessor(
+    v8::String::NewFromUtf8(isolate, "derivedInterface",
+                              v8::NewStringType::kInternalized)
+          .ToLocalChecked(),
+    v8cGet_derivedInterface
+    ,v8cSet_derivedInterface
+  );
+  instance_template->SetAccessor(
+    v8::String::NewFromUtf8(isolate, "objectProperty",
+                              v8::NewStringType::kInternalized)
+          .ToLocalChecked(),
+    v8cGet_objectProperty
+    ,v8cSet_objectProperty
+  );
+
+
+  interface_data->templ.Set(env->isolate(), function_template);
+}
+
+inline InterfaceData* GetInterfaceData(V8cGlobalEnvironment* env) {
+  const int kInterfaceUniqueId = 38;
+  // By convention, the |V8cGlobalEnvironment| that we are associated with
+  // will hold our |InterfaceData| at index |kInterfaceUniqueId|, as we asked
+  // for it to be there in the first place, and could not have conflicted with
+  // any other interface.
+  return env->GetInterfaceData(kInterfaceUniqueId);
+}
+
+}  // namespace
+
+v8::Local<v8::Object> V8cObjectTypeBindingsInterface::CreateWrapper(V8cGlobalEnvironment* env, const scoped_refptr<Wrappable>& wrappable) {
+  v8::Isolate* isolate = env->isolate();
+  v8::Isolate::Scope isolate_scope(isolate);
+  v8::EscapableHandleScope handle_scope(isolate);
+  v8::Local<v8::Context> context = env->context();
+  v8::Context::Scope scope(context);
+
+  InterfaceData* interface_data = GetInterfaceData(env);
+  if (interface_data->templ.IsEmpty()) {
+    InitializeTemplate(env, interface_data);
+  }
+  DCHECK(!interface_data->templ.IsEmpty());
+
+  v8::Local<v8::FunctionTemplate> function_template = interface_data->templ.Get(isolate);
+  DCHECK(function_template->InstanceTemplate()->InternalFieldCount() == 1);
+  v8::Local<v8::Object> object = function_template->InstanceTemplate()->NewInstance(context).ToLocalChecked();
+  DCHECK(object->InternalFieldCount() == 1);
+
+  // |WrapperPrivate|'s lifetime will be managed by V8.
+  new WrapperPrivate(isolate, wrappable, object);
+  return handle_scope.Escape(object);
+}
+
+v8::Local<v8::FunctionTemplate> V8cObjectTypeBindingsInterface::CreateTemplate(V8cGlobalEnvironment* env) {
+  InterfaceData* interface_data = GetInterfaceData(env);
+  if (interface_data->templ.IsEmpty()) {
+    InitializeTemplate(env, interface_data);
+  }
+
+  return interface_data->templ.Get(env->isolate());
+}
+
+
+}  // namespace testing
+}  // namespace bindings
+}  // namespace cobalt
+
+
diff --git a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_object_type_bindings_interface.h b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_object_type_bindings_interface.h
new file mode 100644
index 0000000..7582d43
--- /dev/null
+++ b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_object_type_bindings_interface.h
@@ -0,0 +1,50 @@
+
+// Copyright 2017 Google Inc. All Rights Reserved.
+//
+// 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.
+
+// clang-format off
+
+// This file has been auto-generated by bindings/code_generator_cobalt.py. DO NOT MODIFY!
+// Auto-generated from template: bindings/v8c/templates/interface.h.template
+
+#ifndef V8cObjectTypeBindingsInterface_h
+#define V8cObjectTypeBindingsInterface_h
+
+#include "base/hash_tables.h"
+#include "base/lazy_instance.h"
+#include "base/memory/ref_counted.h"
+#include "base/threading/thread_checker.h"
+#include "cobalt/base/polymorphic_downcast.h"
+#include "cobalt/script/wrappable.h"
+#include "cobalt/bindings/testing/object_type_bindings_interface.h"
+
+#include "cobalt/script/v8c/v8c_global_environment.h"
+#include "v8/include/v8.h"
+
+namespace cobalt {
+namespace bindings {
+namespace testing {
+
+class V8cObjectTypeBindingsInterface {
+ public:
+  static v8::Local<v8::Object> CreateWrapper(script::v8c::V8cGlobalEnvironment* env, const scoped_refptr<script::Wrappable>& wrappable);
+  static v8::Local<v8::FunctionTemplate> CreateTemplate(script::v8c::V8cGlobalEnvironment* env);
+  // TODO: Add |GetInterfaceObject|.
+};
+
+}  // namespace testing
+}  // namespace bindings
+}  // namespace cobalt
+
+#endif  // V8cObjectTypeBindingsInterface_h
diff --git a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_operations_test_interface.cc b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_operations_test_interface.cc
new file mode 100644
index 0000000..4b16a41
--- /dev/null
+++ b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_operations_test_interface.cc
@@ -0,0 +1,272 @@
+
+
+// Copyright 2017 Google Inc. All Rights Reserved.
+//
+// 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.
+
+// clang-format off
+
+// This file has been auto-generated by bindings/code_generator_cobalt.py. DO NOT MODIFY!
+// Auto-generated from template: bindings/v8c/templates/interface.cc.template
+
+#include "cobalt/bindings/testing/v8c_operations_test_interface.h"
+
+#include "base/debug/trace_event.h"
+#include "cobalt/base/polymorphic_downcast.h"
+#include "cobalt/script/global_environment.h"
+#include "cobalt/script/script_value.h"
+#include "cobalt/script/value_handle.h"
+#include "cobalt/bindings/testing/arbitrary_interface.h"
+#include "cobalt/bindings/testing/v8c_arbitrary_interface.h"
+
+#include "v8c_gen_type_conversion.h"
+
+#include "cobalt/script/callback_interface_traits.h"
+#include "cobalt/script/v8c/callback_function_conversion.h"
+#include "cobalt/script/v8c/conversion_helpers.h"
+#include "cobalt/script/v8c/native_promise.h"
+#include "cobalt/script/v8c/type_traits.h"
+#include "cobalt/script/v8c/v8c_callback_function.h"
+#include "cobalt/script/v8c/v8c_callback_interface_holder.h"
+#include "cobalt/script/v8c/v8c_exception_state.h"
+#include "cobalt/script/v8c/v8c_global_environment.h"
+#include "cobalt/script/v8c/v8c_value_handle.h"
+#include "cobalt/script/v8c/wrapper_private.h"
+#include "v8/include/v8.h"
+
+
+namespace {
+using cobalt::bindings::testing::OperationsTestInterface;
+using cobalt::bindings::testing::V8cOperationsTestInterface;
+using cobalt::bindings::testing::ArbitraryInterface;
+using cobalt::bindings::testing::V8cArbitraryInterface;
+using cobalt::script::CallbackInterfaceTraits;
+using cobalt::script::GlobalEnvironment;
+using cobalt::script::ScriptValue;
+using cobalt::script::ValueHandle;
+using cobalt::script::ValueHandle;
+using cobalt::script::ValueHandleHolder;
+using cobalt::script::Wrappable;
+
+using cobalt::script::v8c::FromJSValue;
+using cobalt::script::v8c::InterfaceData;
+using cobalt::script::v8c::kConversionFlagClamped;
+using cobalt::script::v8c::kConversionFlagNullable;
+using cobalt::script::v8c::kConversionFlagRestricted;
+using cobalt::script::v8c::kConversionFlagTreatNullAsEmptyString;
+using cobalt::script::v8c::kConversionFlagTreatUndefinedAsEmptyString;
+using cobalt::script::v8c::kNoConversionFlags;
+using cobalt::script::v8c::TypeTraits;
+using cobalt::script::v8c::V8cExceptionState;
+using cobalt::script::v8c::V8cGlobalEnvironment;
+using cobalt::script::v8c::WrapperFactory;
+using cobalt::script::v8c::WrapperPrivate;
+
+v8::Local<v8::Object> DummyFunctor(V8cGlobalEnvironment*, const scoped_refptr<Wrappable>&) {
+  NOTIMPLEMENTED();
+  return {};
+}
+
+}  // namespace
+
+namespace cobalt {
+namespace bindings {
+namespace testing {
+
+
+namespace {
+
+void OperationsTestInterfaceConstructor(const v8::FunctionCallbackInfo<v8::Value>& args) {
+  NOTIMPLEMENTED();
+  if (!args.IsConstructCall()) {
+    // TODO: Probably throw something here...
+    return;
+  }
+
+  DCHECK(args.This()->InternalFieldCount() == 1);
+  args.This()->SetInternalField(0, v8::External::New(args.GetIsolate(), nullptr));
+  args.GetReturnValue().Set(args.This());
+}
+
+
+void DummyFunction(const v8::FunctionCallbackInfo<v8::Value>& info) {
+  LOG(INFO) << __func__;
+}
+
+void InitializeTemplate(
+  V8cGlobalEnvironment* env,
+  InterfaceData* interface_data) {
+  v8::Isolate* isolate = env->isolate();
+  v8::Local<v8::FunctionTemplate> function_template = v8::FunctionTemplate::New(
+    isolate);
+  function_template->SetClassName(
+    v8::String::NewFromUtf8(isolate, "OperationsTestInterface",
+        v8::NewStringType::kInternalized).ToLocalChecked());
+  v8::Local<v8::ObjectTemplate> instance_template = function_template->InstanceTemplate();
+  instance_template->SetInternalFieldCount(1);
+
+  v8::Local<v8::ObjectTemplate> prototype_template = function_template->PrototypeTemplate();
+  prototype_template->SetInternalFieldCount(1);
+
+
+  instance_template->Set(
+      v8::String::NewFromUtf8(
+          isolate,
+          "longFunctionNoArgs",
+          v8::NewStringType::kInternalized).ToLocalChecked(),
+      v8::FunctionTemplate::New(isolate, DummyFunction)
+  );
+  instance_template->Set(
+      v8::String::NewFromUtf8(
+          isolate,
+          "objectFunctionNoArgs",
+          v8::NewStringType::kInternalized).ToLocalChecked(),
+      v8::FunctionTemplate::New(isolate, DummyFunction)
+  );
+  instance_template->Set(
+      v8::String::NewFromUtf8(
+          isolate,
+          "optionalArgumentWithDefault",
+          v8::NewStringType::kInternalized).ToLocalChecked(),
+      v8::FunctionTemplate::New(isolate, DummyFunction)
+  );
+  instance_template->Set(
+      v8::String::NewFromUtf8(
+          isolate,
+          "optionalArguments",
+          v8::NewStringType::kInternalized).ToLocalChecked(),
+      v8::FunctionTemplate::New(isolate, DummyFunction)
+  );
+  instance_template->Set(
+      v8::String::NewFromUtf8(
+          isolate,
+          "optionalNullableArgumentsWithDefaults",
+          v8::NewStringType::kInternalized).ToLocalChecked(),
+      v8::FunctionTemplate::New(isolate, DummyFunction)
+  );
+  instance_template->Set(
+      v8::String::NewFromUtf8(
+          isolate,
+          "overloadedFunction",
+          v8::NewStringType::kInternalized).ToLocalChecked(),
+      v8::FunctionTemplate::New(isolate, DummyFunction)
+  );
+  instance_template->Set(
+      v8::String::NewFromUtf8(
+          isolate,
+          "overloadedNullable",
+          v8::NewStringType::kInternalized).ToLocalChecked(),
+      v8::FunctionTemplate::New(isolate, DummyFunction)
+  );
+  instance_template->Set(
+      v8::String::NewFromUtf8(
+          isolate,
+          "stringFunctionNoArgs",
+          v8::NewStringType::kInternalized).ToLocalChecked(),
+      v8::FunctionTemplate::New(isolate, DummyFunction)
+  );
+  instance_template->Set(
+      v8::String::NewFromUtf8(
+          isolate,
+          "variadicPrimitiveArguments",
+          v8::NewStringType::kInternalized).ToLocalChecked(),
+      v8::FunctionTemplate::New(isolate, DummyFunction)
+  );
+  instance_template->Set(
+      v8::String::NewFromUtf8(
+          isolate,
+          "variadicStringArgumentsAfterOptionalArgument",
+          v8::NewStringType::kInternalized).ToLocalChecked(),
+      v8::FunctionTemplate::New(isolate, DummyFunction)
+  );
+  instance_template->Set(
+      v8::String::NewFromUtf8(
+          isolate,
+          "voidFunctionLongArg",
+          v8::NewStringType::kInternalized).ToLocalChecked(),
+      v8::FunctionTemplate::New(isolate, DummyFunction)
+  );
+  instance_template->Set(
+      v8::String::NewFromUtf8(
+          isolate,
+          "voidFunctionNoArgs",
+          v8::NewStringType::kInternalized).ToLocalChecked(),
+      v8::FunctionTemplate::New(isolate, DummyFunction)
+  );
+  instance_template->Set(
+      v8::String::NewFromUtf8(
+          isolate,
+          "voidFunctionObjectArg",
+          v8::NewStringType::kInternalized).ToLocalChecked(),
+      v8::FunctionTemplate::New(isolate, DummyFunction)
+  );
+  instance_template->Set(
+      v8::String::NewFromUtf8(
+          isolate,
+          "voidFunctionStringArg",
+          v8::NewStringType::kInternalized).ToLocalChecked(),
+      v8::FunctionTemplate::New(isolate, DummyFunction)
+  );
+
+  interface_data->templ.Set(env->isolate(), function_template);
+}
+
+inline InterfaceData* GetInterfaceData(V8cGlobalEnvironment* env) {
+  const int kInterfaceUniqueId = 39;
+  // By convention, the |V8cGlobalEnvironment| that we are associated with
+  // will hold our |InterfaceData| at index |kInterfaceUniqueId|, as we asked
+  // for it to be there in the first place, and could not have conflicted with
+  // any other interface.
+  return env->GetInterfaceData(kInterfaceUniqueId);
+}
+
+}  // namespace
+
+v8::Local<v8::Object> V8cOperationsTestInterface::CreateWrapper(V8cGlobalEnvironment* env, const scoped_refptr<Wrappable>& wrappable) {
+  v8::Isolate* isolate = env->isolate();
+  v8::Isolate::Scope isolate_scope(isolate);
+  v8::EscapableHandleScope handle_scope(isolate);
+  v8::Local<v8::Context> context = env->context();
+  v8::Context::Scope scope(context);
+
+  InterfaceData* interface_data = GetInterfaceData(env);
+  if (interface_data->templ.IsEmpty()) {
+    InitializeTemplate(env, interface_data);
+  }
+  DCHECK(!interface_data->templ.IsEmpty());
+
+  v8::Local<v8::FunctionTemplate> function_template = interface_data->templ.Get(isolate);
+  DCHECK(function_template->InstanceTemplate()->InternalFieldCount() == 1);
+  v8::Local<v8::Object> object = function_template->InstanceTemplate()->NewInstance(context).ToLocalChecked();
+  DCHECK(object->InternalFieldCount() == 1);
+
+  // |WrapperPrivate|'s lifetime will be managed by V8.
+  new WrapperPrivate(isolate, wrappable, object);
+  return handle_scope.Escape(object);
+}
+
+v8::Local<v8::FunctionTemplate> V8cOperationsTestInterface::CreateTemplate(V8cGlobalEnvironment* env) {
+  InterfaceData* interface_data = GetInterfaceData(env);
+  if (interface_data->templ.IsEmpty()) {
+    InitializeTemplate(env, interface_data);
+  }
+
+  return interface_data->templ.Get(env->isolate());
+}
+
+
+}  // namespace testing
+}  // namespace bindings
+}  // namespace cobalt
+
+
diff --git a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_operations_test_interface.h b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_operations_test_interface.h
new file mode 100644
index 0000000..ead3925
--- /dev/null
+++ b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_operations_test_interface.h
@@ -0,0 +1,50 @@
+
+// Copyright 2017 Google Inc. All Rights Reserved.
+//
+// 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.
+
+// clang-format off
+
+// This file has been auto-generated by bindings/code_generator_cobalt.py. DO NOT MODIFY!
+// Auto-generated from template: bindings/v8c/templates/interface.h.template
+
+#ifndef V8cOperationsTestInterface_h
+#define V8cOperationsTestInterface_h
+
+#include "base/hash_tables.h"
+#include "base/lazy_instance.h"
+#include "base/memory/ref_counted.h"
+#include "base/threading/thread_checker.h"
+#include "cobalt/base/polymorphic_downcast.h"
+#include "cobalt/script/wrappable.h"
+#include "cobalt/bindings/testing/operations_test_interface.h"
+
+#include "cobalt/script/v8c/v8c_global_environment.h"
+#include "v8/include/v8.h"
+
+namespace cobalt {
+namespace bindings {
+namespace testing {
+
+class V8cOperationsTestInterface {
+ public:
+  static v8::Local<v8::Object> CreateWrapper(script::v8c::V8cGlobalEnvironment* env, const scoped_refptr<script::Wrappable>& wrappable);
+  static v8::Local<v8::FunctionTemplate> CreateTemplate(script::v8c::V8cGlobalEnvironment* env);
+  // TODO: Add |GetInterfaceObject|.
+};
+
+}  // namespace testing
+}  // namespace bindings
+}  // namespace cobalt
+
+#endif  // V8cOperationsTestInterface_h
diff --git a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_promise_interface.cc b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_promise_interface.cc
new file mode 100644
index 0000000..51b1549
--- /dev/null
+++ b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_promise_interface.cc
@@ -0,0 +1,205 @@
+
+
+// Copyright 2017 Google Inc. All Rights Reserved.
+//
+// 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.
+
+// clang-format off
+
+// This file has been auto-generated by bindings/code_generator_cobalt.py. DO NOT MODIFY!
+// Auto-generated from template: bindings/v8c/templates/interface.cc.template
+
+#include "cobalt/bindings/testing/v8c_promise_interface.h"
+
+#include "base/debug/trace_event.h"
+#include "cobalt/base/polymorphic_downcast.h"
+#include "cobalt/script/global_environment.h"
+#include "cobalt/script/script_value.h"
+#include "cobalt/script/value_handle.h"
+
+#include "v8c_gen_type_conversion.h"
+
+#include "cobalt/script/callback_interface_traits.h"
+#include "cobalt/script/v8c/callback_function_conversion.h"
+#include "cobalt/script/v8c/conversion_helpers.h"
+#include "cobalt/script/v8c/native_promise.h"
+#include "cobalt/script/v8c/type_traits.h"
+#include "cobalt/script/v8c/v8c_callback_function.h"
+#include "cobalt/script/v8c/v8c_callback_interface_holder.h"
+#include "cobalt/script/v8c/v8c_exception_state.h"
+#include "cobalt/script/v8c/v8c_global_environment.h"
+#include "cobalt/script/v8c/v8c_value_handle.h"
+#include "cobalt/script/v8c/wrapper_private.h"
+#include "v8/include/v8.h"
+
+
+namespace {
+using cobalt::bindings::testing::PromiseInterface;
+using cobalt::bindings::testing::V8cPromiseInterface;
+using cobalt::script::CallbackInterfaceTraits;
+using cobalt::script::GlobalEnvironment;
+using cobalt::script::ScriptValue;
+using cobalt::script::ValueHandle;
+using cobalt::script::ValueHandle;
+using cobalt::script::ValueHandleHolder;
+using cobalt::script::Wrappable;
+
+using cobalt::script::v8c::FromJSValue;
+using cobalt::script::v8c::InterfaceData;
+using cobalt::script::v8c::kConversionFlagClamped;
+using cobalt::script::v8c::kConversionFlagNullable;
+using cobalt::script::v8c::kConversionFlagRestricted;
+using cobalt::script::v8c::kConversionFlagTreatNullAsEmptyString;
+using cobalt::script::v8c::kConversionFlagTreatUndefinedAsEmptyString;
+using cobalt::script::v8c::kNoConversionFlags;
+using cobalt::script::v8c::TypeTraits;
+using cobalt::script::v8c::V8cExceptionState;
+using cobalt::script::v8c::V8cGlobalEnvironment;
+using cobalt::script::v8c::WrapperFactory;
+using cobalt::script::v8c::WrapperPrivate;
+
+v8::Local<v8::Object> DummyFunctor(V8cGlobalEnvironment*, const scoped_refptr<Wrappable>&) {
+  NOTIMPLEMENTED();
+  return {};
+}
+
+}  // namespace
+
+namespace cobalt {
+namespace bindings {
+namespace testing {
+
+
+namespace {
+
+void PromiseInterfaceConstructor(const v8::FunctionCallbackInfo<v8::Value>& args) {
+  NOTIMPLEMENTED();
+  if (!args.IsConstructCall()) {
+    // TODO: Probably throw something here...
+    return;
+  }
+
+  DCHECK(args.This()->InternalFieldCount() == 1);
+  args.This()->SetInternalField(0, v8::External::New(args.GetIsolate(), nullptr));
+  args.GetReturnValue().Set(args.This());
+}
+
+
+void DummyFunction(const v8::FunctionCallbackInfo<v8::Value>& info) {
+  LOG(INFO) << __func__;
+}
+
+void InitializeTemplate(
+  V8cGlobalEnvironment* env,
+  InterfaceData* interface_data) {
+  v8::Isolate* isolate = env->isolate();
+  v8::Local<v8::FunctionTemplate> function_template = v8::FunctionTemplate::New(
+    isolate);
+  function_template->SetClassName(
+    v8::String::NewFromUtf8(isolate, "PromiseInterface",
+        v8::NewStringType::kInternalized).ToLocalChecked());
+  v8::Local<v8::ObjectTemplate> instance_template = function_template->InstanceTemplate();
+  instance_template->SetInternalFieldCount(1);
+
+  v8::Local<v8::ObjectTemplate> prototype_template = function_template->PrototypeTemplate();
+  prototype_template->SetInternalFieldCount(1);
+
+
+  instance_template->Set(
+      v8::String::NewFromUtf8(
+          isolate,
+          "onSuccess",
+          v8::NewStringType::kInternalized).ToLocalChecked(),
+      v8::FunctionTemplate::New(isolate, DummyFunction)
+  );
+  instance_template->Set(
+      v8::String::NewFromUtf8(
+          isolate,
+          "returnBooleanPromise",
+          v8::NewStringType::kInternalized).ToLocalChecked(),
+      v8::FunctionTemplate::New(isolate, DummyFunction)
+  );
+  instance_template->Set(
+      v8::String::NewFromUtf8(
+          isolate,
+          "returnInterfacePromise",
+          v8::NewStringType::kInternalized).ToLocalChecked(),
+      v8::FunctionTemplate::New(isolate, DummyFunction)
+  );
+  instance_template->Set(
+      v8::String::NewFromUtf8(
+          isolate,
+          "returnStringPromise",
+          v8::NewStringType::kInternalized).ToLocalChecked(),
+      v8::FunctionTemplate::New(isolate, DummyFunction)
+  );
+  instance_template->Set(
+      v8::String::NewFromUtf8(
+          isolate,
+          "returnVoidPromise",
+          v8::NewStringType::kInternalized).ToLocalChecked(),
+      v8::FunctionTemplate::New(isolate, DummyFunction)
+  );
+
+  interface_data->templ.Set(env->isolate(), function_template);
+}
+
+inline InterfaceData* GetInterfaceData(V8cGlobalEnvironment* env) {
+  const int kInterfaceUniqueId = 40;
+  // By convention, the |V8cGlobalEnvironment| that we are associated with
+  // will hold our |InterfaceData| at index |kInterfaceUniqueId|, as we asked
+  // for it to be there in the first place, and could not have conflicted with
+  // any other interface.
+  return env->GetInterfaceData(kInterfaceUniqueId);
+}
+
+}  // namespace
+
+v8::Local<v8::Object> V8cPromiseInterface::CreateWrapper(V8cGlobalEnvironment* env, const scoped_refptr<Wrappable>& wrappable) {
+  v8::Isolate* isolate = env->isolate();
+  v8::Isolate::Scope isolate_scope(isolate);
+  v8::EscapableHandleScope handle_scope(isolate);
+  v8::Local<v8::Context> context = env->context();
+  v8::Context::Scope scope(context);
+
+  InterfaceData* interface_data = GetInterfaceData(env);
+  if (interface_data->templ.IsEmpty()) {
+    InitializeTemplate(env, interface_data);
+  }
+  DCHECK(!interface_data->templ.IsEmpty());
+
+  v8::Local<v8::FunctionTemplate> function_template = interface_data->templ.Get(isolate);
+  DCHECK(function_template->InstanceTemplate()->InternalFieldCount() == 1);
+  v8::Local<v8::Object> object = function_template->InstanceTemplate()->NewInstance(context).ToLocalChecked();
+  DCHECK(object->InternalFieldCount() == 1);
+
+  // |WrapperPrivate|'s lifetime will be managed by V8.
+  new WrapperPrivate(isolate, wrappable, object);
+  return handle_scope.Escape(object);
+}
+
+v8::Local<v8::FunctionTemplate> V8cPromiseInterface::CreateTemplate(V8cGlobalEnvironment* env) {
+  InterfaceData* interface_data = GetInterfaceData(env);
+  if (interface_data->templ.IsEmpty()) {
+    InitializeTemplate(env, interface_data);
+  }
+
+  return interface_data->templ.Get(env->isolate());
+}
+
+
+}  // namespace testing
+}  // namespace bindings
+}  // namespace cobalt
+
+
diff --git a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_promise_interface.h b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_promise_interface.h
new file mode 100644
index 0000000..0ea2777
--- /dev/null
+++ b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_promise_interface.h
@@ -0,0 +1,50 @@
+
+// Copyright 2017 Google Inc. All Rights Reserved.
+//
+// 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.
+
+// clang-format off
+
+// This file has been auto-generated by bindings/code_generator_cobalt.py. DO NOT MODIFY!
+// Auto-generated from template: bindings/v8c/templates/interface.h.template
+
+#ifndef V8cPromiseInterface_h
+#define V8cPromiseInterface_h
+
+#include "base/hash_tables.h"
+#include "base/lazy_instance.h"
+#include "base/memory/ref_counted.h"
+#include "base/threading/thread_checker.h"
+#include "cobalt/base/polymorphic_downcast.h"
+#include "cobalt/script/wrappable.h"
+#include "cobalt/bindings/testing/promise_interface.h"
+
+#include "cobalt/script/v8c/v8c_global_environment.h"
+#include "v8/include/v8.h"
+
+namespace cobalt {
+namespace bindings {
+namespace testing {
+
+class V8cPromiseInterface {
+ public:
+  static v8::Local<v8::Object> CreateWrapper(script::v8c::V8cGlobalEnvironment* env, const scoped_refptr<script::Wrappable>& wrappable);
+  static v8::Local<v8::FunctionTemplate> CreateTemplate(script::v8c::V8cGlobalEnvironment* env);
+  // TODO: Add |GetInterfaceObject|.
+};
+
+}  // namespace testing
+}  // namespace bindings
+}  // namespace cobalt
+
+#endif  // V8cPromiseInterface_h
diff --git a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_put_forwards_interface.cc b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_put_forwards_interface.cc
new file mode 100644
index 0000000..0fae660
--- /dev/null
+++ b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_put_forwards_interface.cc
@@ -0,0 +1,209 @@
+
+
+// Copyright 2017 Google Inc. All Rights Reserved.
+//
+// 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.
+
+// clang-format off
+
+// This file has been auto-generated by bindings/code_generator_cobalt.py. DO NOT MODIFY!
+// Auto-generated from template: bindings/v8c/templates/interface.cc.template
+
+#include "cobalt/bindings/testing/v8c_put_forwards_interface.h"
+
+#include "base/debug/trace_event.h"
+#include "cobalt/base/polymorphic_downcast.h"
+#include "cobalt/script/global_environment.h"
+#include "cobalt/script/script_value.h"
+#include "cobalt/script/value_handle.h"
+#include "cobalt/bindings/testing/arbitrary_interface.h"
+#include "cobalt/bindings/testing/v8c_arbitrary_interface.h"
+
+#include "v8c_gen_type_conversion.h"
+
+#include "cobalt/script/callback_interface_traits.h"
+#include "cobalt/script/v8c/callback_function_conversion.h"
+#include "cobalt/script/v8c/conversion_helpers.h"
+#include "cobalt/script/v8c/native_promise.h"
+#include "cobalt/script/v8c/type_traits.h"
+#include "cobalt/script/v8c/v8c_callback_function.h"
+#include "cobalt/script/v8c/v8c_callback_interface_holder.h"
+#include "cobalt/script/v8c/v8c_exception_state.h"
+#include "cobalt/script/v8c/v8c_global_environment.h"
+#include "cobalt/script/v8c/v8c_value_handle.h"
+#include "cobalt/script/v8c/wrapper_private.h"
+#include "v8/include/v8.h"
+
+
+namespace {
+using cobalt::bindings::testing::PutForwardsInterface;
+using cobalt::bindings::testing::V8cPutForwardsInterface;
+using cobalt::bindings::testing::ArbitraryInterface;
+using cobalt::bindings::testing::V8cArbitraryInterface;
+using cobalt::script::CallbackInterfaceTraits;
+using cobalt::script::GlobalEnvironment;
+using cobalt::script::ScriptValue;
+using cobalt::script::ValueHandle;
+using cobalt::script::ValueHandle;
+using cobalt::script::ValueHandleHolder;
+using cobalt::script::Wrappable;
+
+using cobalt::script::v8c::FromJSValue;
+using cobalt::script::v8c::InterfaceData;
+using cobalt::script::v8c::kConversionFlagClamped;
+using cobalt::script::v8c::kConversionFlagNullable;
+using cobalt::script::v8c::kConversionFlagRestricted;
+using cobalt::script::v8c::kConversionFlagTreatNullAsEmptyString;
+using cobalt::script::v8c::kConversionFlagTreatUndefinedAsEmptyString;
+using cobalt::script::v8c::kNoConversionFlags;
+using cobalt::script::v8c::TypeTraits;
+using cobalt::script::v8c::V8cExceptionState;
+using cobalt::script::v8c::V8cGlobalEnvironment;
+using cobalt::script::v8c::WrapperFactory;
+using cobalt::script::v8c::WrapperPrivate;
+
+v8::Local<v8::Object> DummyFunctor(V8cGlobalEnvironment*, const scoped_refptr<Wrappable>&) {
+  NOTIMPLEMENTED();
+  return {};
+}
+
+}  // namespace
+
+namespace cobalt {
+namespace bindings {
+namespace testing {
+
+
+namespace {
+
+void PutForwardsInterfaceConstructor(const v8::FunctionCallbackInfo<v8::Value>& args) {
+  NOTIMPLEMENTED();
+  if (!args.IsConstructCall()) {
+    // TODO: Probably throw something here...
+    return;
+  }
+
+  DCHECK(args.This()->InternalFieldCount() == 1);
+  args.This()->SetInternalField(0, v8::External::New(args.GetIsolate(), nullptr));
+  args.GetReturnValue().Set(args.This());
+}
+
+
+void v8cGet_forwardingAttribute(
+  v8::Local<v8::String> property,
+  const v8::PropertyCallbackInfo<v8::Value>& info)
+{
+  NOTIMPLEMENTED();
+
+  v8::Local<v8::External> external = v8::Local<v8::External>::Cast(info.Holder()->GetInternalField(0));
+  WrapperPrivate* wrapper_private = static_cast<WrapperPrivate*>(external->Value());
+  PutForwardsInterface* impl = static_cast<PutForwardsInterface*>(wrapper_private->wrappable<PutForwardsInterface>());
+
+  NOTIMPLEMENTED();
+}
+
+
+void v8cSet_forwardingAttribute(
+  v8::Local<v8::String> property,
+  v8::Local<v8::Value> v8_value,
+  const v8::PropertyCallbackInfo<void>& info)
+{
+  v8::Local<v8::External> external = v8::Local<v8::External>::Cast(info.Holder()->GetInternalField(0));
+  WrapperPrivate* wrapper_private = static_cast<WrapperPrivate*>(external->Value());
+  PutForwardsInterface* impl = static_cast<PutForwardsInterface*>(wrapper_private->wrappable<PutForwardsInterface>());
+
+  NOTIMPLEMENTED();
+}
+
+
+
+void DummyFunction(const v8::FunctionCallbackInfo<v8::Value>& info) {
+  LOG(INFO) << __func__;
+}
+
+void InitializeTemplate(
+  V8cGlobalEnvironment* env,
+  InterfaceData* interface_data) {
+  v8::Isolate* isolate = env->isolate();
+  v8::Local<v8::FunctionTemplate> function_template = v8::FunctionTemplate::New(
+    isolate);
+  function_template->SetClassName(
+    v8::String::NewFromUtf8(isolate, "PutForwardsInterface",
+        v8::NewStringType::kInternalized).ToLocalChecked());
+  v8::Local<v8::ObjectTemplate> instance_template = function_template->InstanceTemplate();
+  instance_template->SetInternalFieldCount(1);
+
+  v8::Local<v8::ObjectTemplate> prototype_template = function_template->PrototypeTemplate();
+  prototype_template->SetInternalFieldCount(1);
+
+  instance_template->SetAccessor(
+    v8::String::NewFromUtf8(isolate, "forwardingAttribute",
+                              v8::NewStringType::kInternalized)
+          .ToLocalChecked(),
+    v8cGet_forwardingAttribute
+    ,v8cSet_forwardingAttribute
+  );
+
+
+  interface_data->templ.Set(env->isolate(), function_template);
+}
+
+inline InterfaceData* GetInterfaceData(V8cGlobalEnvironment* env) {
+  const int kInterfaceUniqueId = 41;
+  // By convention, the |V8cGlobalEnvironment| that we are associated with
+  // will hold our |InterfaceData| at index |kInterfaceUniqueId|, as we asked
+  // for it to be there in the first place, and could not have conflicted with
+  // any other interface.
+  return env->GetInterfaceData(kInterfaceUniqueId);
+}
+
+}  // namespace
+
+v8::Local<v8::Object> V8cPutForwardsInterface::CreateWrapper(V8cGlobalEnvironment* env, const scoped_refptr<Wrappable>& wrappable) {
+  v8::Isolate* isolate = env->isolate();
+  v8::Isolate::Scope isolate_scope(isolate);
+  v8::EscapableHandleScope handle_scope(isolate);
+  v8::Local<v8::Context> context = env->context();
+  v8::Context::Scope scope(context);
+
+  InterfaceData* interface_data = GetInterfaceData(env);
+  if (interface_data->templ.IsEmpty()) {
+    InitializeTemplate(env, interface_data);
+  }
+  DCHECK(!interface_data->templ.IsEmpty());
+
+  v8::Local<v8::FunctionTemplate> function_template = interface_data->templ.Get(isolate);
+  DCHECK(function_template->InstanceTemplate()->InternalFieldCount() == 1);
+  v8::Local<v8::Object> object = function_template->InstanceTemplate()->NewInstance(context).ToLocalChecked();
+  DCHECK(object->InternalFieldCount() == 1);
+
+  // |WrapperPrivate|'s lifetime will be managed by V8.
+  new WrapperPrivate(isolate, wrappable, object);
+  return handle_scope.Escape(object);
+}
+
+v8::Local<v8::FunctionTemplate> V8cPutForwardsInterface::CreateTemplate(V8cGlobalEnvironment* env) {
+  InterfaceData* interface_data = GetInterfaceData(env);
+  if (interface_data->templ.IsEmpty()) {
+    InitializeTemplate(env, interface_data);
+  }
+
+  return interface_data->templ.Get(env->isolate());
+}
+
+
+}  // namespace testing
+}  // namespace bindings
+}  // namespace cobalt
+
+
diff --git a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_put_forwards_interface.h b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_put_forwards_interface.h
new file mode 100644
index 0000000..a80b5a8
--- /dev/null
+++ b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_put_forwards_interface.h
@@ -0,0 +1,50 @@
+
+// Copyright 2017 Google Inc. All Rights Reserved.
+//
+// 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.
+
+// clang-format off
+
+// This file has been auto-generated by bindings/code_generator_cobalt.py. DO NOT MODIFY!
+// Auto-generated from template: bindings/v8c/templates/interface.h.template
+
+#ifndef V8cPutForwardsInterface_h
+#define V8cPutForwardsInterface_h
+
+#include "base/hash_tables.h"
+#include "base/lazy_instance.h"
+#include "base/memory/ref_counted.h"
+#include "base/threading/thread_checker.h"
+#include "cobalt/base/polymorphic_downcast.h"
+#include "cobalt/script/wrappable.h"
+#include "cobalt/bindings/testing/put_forwards_interface.h"
+
+#include "cobalt/script/v8c/v8c_global_environment.h"
+#include "v8/include/v8.h"
+
+namespace cobalt {
+namespace bindings {
+namespace testing {
+
+class V8cPutForwardsInterface {
+ public:
+  static v8::Local<v8::Object> CreateWrapper(script::v8c::V8cGlobalEnvironment* env, const scoped_refptr<script::Wrappable>& wrappable);
+  static v8::Local<v8::FunctionTemplate> CreateTemplate(script::v8c::V8cGlobalEnvironment* env);
+  // TODO: Add |GetInterfaceObject|.
+};
+
+}  // namespace testing
+}  // namespace bindings
+}  // namespace cobalt
+
+#endif  // V8cPutForwardsInterface_h
diff --git a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_sequence_user.cc b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_sequence_user.cc
new file mode 100644
index 0000000..8700663
--- /dev/null
+++ b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_sequence_user.cc
@@ -0,0 +1,272 @@
+
+
+// Copyright 2017 Google Inc. All Rights Reserved.
+//
+// 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.
+
+// clang-format off
+
+// This file has been auto-generated by bindings/code_generator_cobalt.py. DO NOT MODIFY!
+// Auto-generated from template: bindings/v8c/templates/interface.cc.template
+
+#include "cobalt/bindings/testing/v8c_sequence_user.h"
+
+#include "base/debug/trace_event.h"
+#include "cobalt/base/polymorphic_downcast.h"
+#include "cobalt/script/global_environment.h"
+#include "cobalt/script/script_value.h"
+#include "cobalt/script/value_handle.h"
+#include "cobalt/bindings/testing/arbitrary_interface.h"
+#include "cobalt/bindings/testing/v8c_arbitrary_interface.h"
+
+#include "v8c_gen_type_conversion.h"
+
+#include "cobalt/script/callback_interface_traits.h"
+#include "cobalt/script/v8c/callback_function_conversion.h"
+#include "cobalt/script/v8c/conversion_helpers.h"
+#include "cobalt/script/v8c/native_promise.h"
+#include "cobalt/script/v8c/type_traits.h"
+#include "cobalt/script/v8c/v8c_callback_function.h"
+#include "cobalt/script/v8c/v8c_callback_interface_holder.h"
+#include "cobalt/script/v8c/v8c_exception_state.h"
+#include "cobalt/script/v8c/v8c_global_environment.h"
+#include "cobalt/script/v8c/v8c_value_handle.h"
+#include "cobalt/script/v8c/wrapper_private.h"
+#include "v8/include/v8.h"
+
+
+namespace {
+using cobalt::bindings::testing::SequenceUser;
+using cobalt::bindings::testing::V8cSequenceUser;
+using cobalt::bindings::testing::ArbitraryInterface;
+using cobalt::bindings::testing::V8cArbitraryInterface;
+using cobalt::script::CallbackInterfaceTraits;
+using cobalt::script::GlobalEnvironment;
+using cobalt::script::ScriptValue;
+using cobalt::script::ValueHandle;
+using cobalt::script::ValueHandle;
+using cobalt::script::ValueHandleHolder;
+using cobalt::script::Wrappable;
+
+using cobalt::script::v8c::FromJSValue;
+using cobalt::script::v8c::InterfaceData;
+using cobalt::script::v8c::kConversionFlagClamped;
+using cobalt::script::v8c::kConversionFlagNullable;
+using cobalt::script::v8c::kConversionFlagRestricted;
+using cobalt::script::v8c::kConversionFlagTreatNullAsEmptyString;
+using cobalt::script::v8c::kConversionFlagTreatUndefinedAsEmptyString;
+using cobalt::script::v8c::kNoConversionFlags;
+using cobalt::script::v8c::TypeTraits;
+using cobalt::script::v8c::V8cExceptionState;
+using cobalt::script::v8c::V8cGlobalEnvironment;
+using cobalt::script::v8c::WrapperFactory;
+using cobalt::script::v8c::WrapperPrivate;
+
+v8::Local<v8::Object> DummyFunctor(V8cGlobalEnvironment*, const scoped_refptr<Wrappable>&) {
+  NOTIMPLEMENTED();
+  return {};
+}
+
+}  // namespace
+
+namespace cobalt {
+namespace bindings {
+namespace testing {
+
+
+namespace {
+
+void SequenceUserConstructor(const v8::FunctionCallbackInfo<v8::Value>& args) {
+  NOTIMPLEMENTED();
+  if (!args.IsConstructCall()) {
+    // TODO: Probably throw something here...
+    return;
+  }
+
+  DCHECK(args.This()->InternalFieldCount() == 1);
+  args.This()->SetInternalField(0, v8::External::New(args.GetIsolate(), nullptr));
+  args.GetReturnValue().Set(args.This());
+}
+
+
+void DummyFunction(const v8::FunctionCallbackInfo<v8::Value>& info) {
+  LOG(INFO) << __func__;
+}
+
+void InitializeTemplate(
+  V8cGlobalEnvironment* env,
+  InterfaceData* interface_data) {
+  v8::Isolate* isolate = env->isolate();
+  v8::Local<v8::FunctionTemplate> function_template = v8::FunctionTemplate::New(
+    isolate);
+  function_template->SetClassName(
+    v8::String::NewFromUtf8(isolate, "SequenceUser",
+        v8::NewStringType::kInternalized).ToLocalChecked());
+  v8::Local<v8::ObjectTemplate> instance_template = function_template->InstanceTemplate();
+  instance_template->SetInternalFieldCount(1);
+
+  v8::Local<v8::ObjectTemplate> prototype_template = function_template->PrototypeTemplate();
+  prototype_template->SetInternalFieldCount(1);
+
+
+  instance_template->Set(
+      v8::String::NewFromUtf8(
+          isolate,
+          "getInterfaceSequence",
+          v8::NewStringType::kInternalized).ToLocalChecked(),
+      v8::FunctionTemplate::New(isolate, DummyFunction)
+  );
+  instance_template->Set(
+      v8::String::NewFromUtf8(
+          isolate,
+          "getInterfaceSequenceSequenceSequence",
+          v8::NewStringType::kInternalized).ToLocalChecked(),
+      v8::FunctionTemplate::New(isolate, DummyFunction)
+  );
+  instance_template->Set(
+      v8::String::NewFromUtf8(
+          isolate,
+          "getLongSequence",
+          v8::NewStringType::kInternalized).ToLocalChecked(),
+      v8::FunctionTemplate::New(isolate, DummyFunction)
+  );
+  instance_template->Set(
+      v8::String::NewFromUtf8(
+          isolate,
+          "getStringSequence",
+          v8::NewStringType::kInternalized).ToLocalChecked(),
+      v8::FunctionTemplate::New(isolate, DummyFunction)
+  );
+  instance_template->Set(
+      v8::String::NewFromUtf8(
+          isolate,
+          "getStringSequenceSequence",
+          v8::NewStringType::kInternalized).ToLocalChecked(),
+      v8::FunctionTemplate::New(isolate, DummyFunction)
+  );
+  instance_template->Set(
+      v8::String::NewFromUtf8(
+          isolate,
+          "getUnionOfStringAndStringSequence",
+          v8::NewStringType::kInternalized).ToLocalChecked(),
+      v8::FunctionTemplate::New(isolate, DummyFunction)
+  );
+  instance_template->Set(
+      v8::String::NewFromUtf8(
+          isolate,
+          "getUnionSequence",
+          v8::NewStringType::kInternalized).ToLocalChecked(),
+      v8::FunctionTemplate::New(isolate, DummyFunction)
+  );
+  instance_template->Set(
+      v8::String::NewFromUtf8(
+          isolate,
+          "setInterfaceSequence",
+          v8::NewStringType::kInternalized).ToLocalChecked(),
+      v8::FunctionTemplate::New(isolate, DummyFunction)
+  );
+  instance_template->Set(
+      v8::String::NewFromUtf8(
+          isolate,
+          "setInterfaceSequenceSequenceSequence",
+          v8::NewStringType::kInternalized).ToLocalChecked(),
+      v8::FunctionTemplate::New(isolate, DummyFunction)
+  );
+  instance_template->Set(
+      v8::String::NewFromUtf8(
+          isolate,
+          "setLongSequence",
+          v8::NewStringType::kInternalized).ToLocalChecked(),
+      v8::FunctionTemplate::New(isolate, DummyFunction)
+  );
+  instance_template->Set(
+      v8::String::NewFromUtf8(
+          isolate,
+          "setStringSequence",
+          v8::NewStringType::kInternalized).ToLocalChecked(),
+      v8::FunctionTemplate::New(isolate, DummyFunction)
+  );
+  instance_template->Set(
+      v8::String::NewFromUtf8(
+          isolate,
+          "setStringSequenceSequence",
+          v8::NewStringType::kInternalized).ToLocalChecked(),
+      v8::FunctionTemplate::New(isolate, DummyFunction)
+  );
+  instance_template->Set(
+      v8::String::NewFromUtf8(
+          isolate,
+          "setUnionOfStringAndStringSequence",
+          v8::NewStringType::kInternalized).ToLocalChecked(),
+      v8::FunctionTemplate::New(isolate, DummyFunction)
+  );
+  instance_template->Set(
+      v8::String::NewFromUtf8(
+          isolate,
+          "setUnionSequence",
+          v8::NewStringType::kInternalized).ToLocalChecked(),
+      v8::FunctionTemplate::New(isolate, DummyFunction)
+  );
+
+  interface_data->templ.Set(env->isolate(), function_template);
+}
+
+inline InterfaceData* GetInterfaceData(V8cGlobalEnvironment* env) {
+  const int kInterfaceUniqueId = 42;
+  // By convention, the |V8cGlobalEnvironment| that we are associated with
+  // will hold our |InterfaceData| at index |kInterfaceUniqueId|, as we asked
+  // for it to be there in the first place, and could not have conflicted with
+  // any other interface.
+  return env->GetInterfaceData(kInterfaceUniqueId);
+}
+
+}  // namespace
+
+v8::Local<v8::Object> V8cSequenceUser::CreateWrapper(V8cGlobalEnvironment* env, const scoped_refptr<Wrappable>& wrappable) {
+  v8::Isolate* isolate = env->isolate();
+  v8::Isolate::Scope isolate_scope(isolate);
+  v8::EscapableHandleScope handle_scope(isolate);
+  v8::Local<v8::Context> context = env->context();
+  v8::Context::Scope scope(context);
+
+  InterfaceData* interface_data = GetInterfaceData(env);
+  if (interface_data->templ.IsEmpty()) {
+    InitializeTemplate(env, interface_data);
+  }
+  DCHECK(!interface_data->templ.IsEmpty());
+
+  v8::Local<v8::FunctionTemplate> function_template = interface_data->templ.Get(isolate);
+  DCHECK(function_template->InstanceTemplate()->InternalFieldCount() == 1);
+  v8::Local<v8::Object> object = function_template->InstanceTemplate()->NewInstance(context).ToLocalChecked();
+  DCHECK(object->InternalFieldCount() == 1);
+
+  // |WrapperPrivate|'s lifetime will be managed by V8.
+  new WrapperPrivate(isolate, wrappable, object);
+  return handle_scope.Escape(object);
+}
+
+v8::Local<v8::FunctionTemplate> V8cSequenceUser::CreateTemplate(V8cGlobalEnvironment* env) {
+  InterfaceData* interface_data = GetInterfaceData(env);
+  if (interface_data->templ.IsEmpty()) {
+    InitializeTemplate(env, interface_data);
+  }
+
+  return interface_data->templ.Get(env->isolate());
+}
+
+
+}  // namespace testing
+}  // namespace bindings
+}  // namespace cobalt
+
+
diff --git a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_sequence_user.h b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_sequence_user.h
new file mode 100644
index 0000000..ce5901d
--- /dev/null
+++ b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_sequence_user.h
@@ -0,0 +1,50 @@
+
+// Copyright 2017 Google Inc. All Rights Reserved.
+//
+// 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.
+
+// clang-format off
+
+// This file has been auto-generated by bindings/code_generator_cobalt.py. DO NOT MODIFY!
+// Auto-generated from template: bindings/v8c/templates/interface.h.template
+
+#ifndef V8cSequenceUser_h
+#define V8cSequenceUser_h
+
+#include "base/hash_tables.h"
+#include "base/lazy_instance.h"
+#include "base/memory/ref_counted.h"
+#include "base/threading/thread_checker.h"
+#include "cobalt/base/polymorphic_downcast.h"
+#include "cobalt/script/wrappable.h"
+#include "cobalt/bindings/testing/sequence_user.h"
+
+#include "cobalt/script/v8c/v8c_global_environment.h"
+#include "v8/include/v8.h"
+
+namespace cobalt {
+namespace bindings {
+namespace testing {
+
+class V8cSequenceUser {
+ public:
+  static v8::Local<v8::Object> CreateWrapper(script::v8c::V8cGlobalEnvironment* env, const scoped_refptr<script::Wrappable>& wrappable);
+  static v8::Local<v8::FunctionTemplate> CreateTemplate(script::v8c::V8cGlobalEnvironment* env);
+  // TODO: Add |GetInterfaceObject|.
+};
+
+}  // namespace testing
+}  // namespace bindings
+}  // namespace cobalt
+
+#endif  // V8cSequenceUser_h
diff --git a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_single_operation_interface.cc b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_single_operation_interface.cc
new file mode 100644
index 0000000..8b9908e
--- /dev/null
+++ b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_single_operation_interface.cc
@@ -0,0 +1,60 @@
+// Copyright 2017 Google Inc. All Rights Reserved.
+//
+// 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.
+
+// clang-format off
+
+// This file has been auto-generated by bindings/code_generator_cobalt.py. DO NOT MODIFY!
+// Auto-generated from template: bindings/v8c/templates/callback-interface.cc.template
+
+
+#include "cobalt/bindings/testing/v8c_single_operation_interface.h"
+#include "cobalt/bindings/testing/arbitrary_interface.h"
+#include "cobalt/bindings/testing/v8c_arbitrary_interface.h"
+
+#include "v8c_gen_type_conversion.h"
+
+#include "cobalt/script/logging_exception_state.h"
+#include "cobalt/script/v8c/v8c_callback_interface.h"
+#include "cobalt/script/v8c/v8c_global_environment.h"
+#include "v8/include/v8.h"
+
+namespace {
+using cobalt::bindings::testing::SingleOperationInterface;
+using cobalt::bindings::testing::V8cSingleOperationInterface;
+using cobalt::bindings::testing::ArbitraryInterface;
+using cobalt::bindings::testing::V8cArbitraryInterface;
+
+using cobalt::script::LoggingExceptionState;
+using cobalt::script::v8c::V8cGlobalEnvironment;
+}  // namespace
+
+namespace cobalt {
+namespace bindings {
+namespace testing {
+
+base::optional<int32_t > V8cSingleOperationInterface::HandleCallback(
+    const scoped_refptr<script::Wrappable>& callback_this,
+    const scoped_refptr<ArbitraryInterface>& value,
+    bool* had_exception) const {
+  NOTIMPLEMENTED();
+
+  base::optional<int32_t > cobalt_return_value;
+
+  return cobalt_return_value;
+}
+
+}  // namespace testing
+}  // namespace bindings
+}  // namespace cobalt
+
diff --git a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_single_operation_interface.h b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_single_operation_interface.h
new file mode 100644
index 0000000..8bffefd
--- /dev/null
+++ b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_single_operation_interface.h
@@ -0,0 +1,73 @@
+
+// Copyright 2017 Google Inc. All Rights Reserved.
+//
+// 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.
+
+// clang-format off
+
+// This file has been auto-generated by bindings/code_generator_cobalt.py. DO NOT MODIFY!
+// Auto-generated from template: bindings/v8c/templates/callback-interface.h.template
+
+#ifndef V8cSingleOperationInterface_h
+#define V8cSingleOperationInterface_h
+
+#include "cobalt/script/callback_interface_traits.h"
+// Headers for other bindings wrapper classes
+#include "cobalt/bindings/testing/single_operation_interface.h"
+
+#include "cobalt/script/v8c/weak_heap_object.h"
+
+
+namespace cobalt {
+namespace bindings {
+namespace testing {
+
+class V8cSingleOperationInterface : public SingleOperationInterface {
+ public:
+  typedef SingleOperationInterface BaseType;
+
+  V8cSingleOperationInterface(
+    script::v8c::V8cGlobalEnvironment* env, v8::Local<v8::Value> implementing_object_value)
+    : env_(env), implementing_object_(env, implementing_object_value) {}
+
+  base::optional<int32_t > HandleCallback(
+      const scoped_refptr<script::Wrappable>& callback_this,
+      const scoped_refptr<ArbitraryInterface>& value,
+      bool* had_exception) const override;
+
+  v8::Local<v8::Value> value() const { return implementing_object_.GetValue(); }
+
+ private:
+  script::v8c::V8cGlobalEnvironment* env_;
+  script::v8c::WeakHeapObject implementing_object_;
+};
+
+}  // namespace testing
+}  // namespace bindings
+}  // namespace cobalt
+
+namespace cobalt {
+namespace script {
+
+// Explicit instantiation of CallbackInterfaceTraits struct so we can infer
+// the type of the generated class from the type of the callback interface.
+template<>
+struct CallbackInterfaceTraits<cobalt::bindings::testing::SingleOperationInterface> {
+  typedef cobalt::bindings::testing::V8cSingleOperationInterface V8cCallbackInterfaceClass;
+};
+
+}  // namespace script
+}  // namespace cobalt
+
+
+#endif  // V8cSingleOperationInterface_h
diff --git a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_static_properties_interface.cc b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_static_properties_interface.cc
new file mode 100644
index 0000000..23851cd
--- /dev/null
+++ b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_static_properties_interface.cc
@@ -0,0 +1,174 @@
+
+
+// Copyright 2017 Google Inc. All Rights Reserved.
+//
+// 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.
+
+// clang-format off
+
+// This file has been auto-generated by bindings/code_generator_cobalt.py. DO NOT MODIFY!
+// Auto-generated from template: bindings/v8c/templates/interface.cc.template
+
+#include "cobalt/bindings/testing/v8c_static_properties_interface.h"
+
+#include "base/debug/trace_event.h"
+#include "cobalt/base/polymorphic_downcast.h"
+#include "cobalt/script/global_environment.h"
+#include "cobalt/script/script_value.h"
+#include "cobalt/script/value_handle.h"
+#include "cobalt/bindings/testing/arbitrary_interface.h"
+#include "cobalt/bindings/testing/v8c_arbitrary_interface.h"
+
+#include "v8c_gen_type_conversion.h"
+
+#include "cobalt/script/callback_interface_traits.h"
+#include "cobalt/script/v8c/callback_function_conversion.h"
+#include "cobalt/script/v8c/conversion_helpers.h"
+#include "cobalt/script/v8c/native_promise.h"
+#include "cobalt/script/v8c/type_traits.h"
+#include "cobalt/script/v8c/v8c_callback_function.h"
+#include "cobalt/script/v8c/v8c_callback_interface_holder.h"
+#include "cobalt/script/v8c/v8c_exception_state.h"
+#include "cobalt/script/v8c/v8c_global_environment.h"
+#include "cobalt/script/v8c/v8c_value_handle.h"
+#include "cobalt/script/v8c/wrapper_private.h"
+#include "v8/include/v8.h"
+
+
+namespace {
+using cobalt::bindings::testing::StaticPropertiesInterface;
+using cobalt::bindings::testing::V8cStaticPropertiesInterface;
+using cobalt::bindings::testing::ArbitraryInterface;
+using cobalt::bindings::testing::V8cArbitraryInterface;
+using cobalt::script::CallbackInterfaceTraits;
+using cobalt::script::GlobalEnvironment;
+using cobalt::script::ScriptValue;
+using cobalt::script::ValueHandle;
+using cobalt::script::ValueHandle;
+using cobalt::script::ValueHandleHolder;
+using cobalt::script::Wrappable;
+
+using cobalt::script::v8c::FromJSValue;
+using cobalt::script::v8c::InterfaceData;
+using cobalt::script::v8c::kConversionFlagClamped;
+using cobalt::script::v8c::kConversionFlagNullable;
+using cobalt::script::v8c::kConversionFlagRestricted;
+using cobalt::script::v8c::kConversionFlagTreatNullAsEmptyString;
+using cobalt::script::v8c::kConversionFlagTreatUndefinedAsEmptyString;
+using cobalt::script::v8c::kNoConversionFlags;
+using cobalt::script::v8c::TypeTraits;
+using cobalt::script::v8c::V8cExceptionState;
+using cobalt::script::v8c::V8cGlobalEnvironment;
+using cobalt::script::v8c::WrapperFactory;
+using cobalt::script::v8c::WrapperPrivate;
+
+v8::Local<v8::Object> DummyFunctor(V8cGlobalEnvironment*, const scoped_refptr<Wrappable>&) {
+  NOTIMPLEMENTED();
+  return {};
+}
+
+}  // namespace
+
+namespace cobalt {
+namespace bindings {
+namespace testing {
+
+
+namespace {
+
+void StaticPropertiesInterfaceConstructor(const v8::FunctionCallbackInfo<v8::Value>& args) {
+  NOTIMPLEMENTED();
+  if (!args.IsConstructCall()) {
+    // TODO: Probably throw something here...
+    return;
+  }
+
+  DCHECK(args.This()->InternalFieldCount() == 1);
+  args.This()->SetInternalField(0, v8::External::New(args.GetIsolate(), nullptr));
+  args.GetReturnValue().Set(args.This());
+}
+
+
+void DummyFunction(const v8::FunctionCallbackInfo<v8::Value>& info) {
+  LOG(INFO) << __func__;
+}
+
+void InitializeTemplate(
+  V8cGlobalEnvironment* env,
+  InterfaceData* interface_data) {
+  v8::Isolate* isolate = env->isolate();
+  v8::Local<v8::FunctionTemplate> function_template = v8::FunctionTemplate::New(
+    isolate);
+  function_template->SetClassName(
+    v8::String::NewFromUtf8(isolate, "StaticPropertiesInterface",
+        v8::NewStringType::kInternalized).ToLocalChecked());
+  v8::Local<v8::ObjectTemplate> instance_template = function_template->InstanceTemplate();
+  instance_template->SetInternalFieldCount(1);
+
+  v8::Local<v8::ObjectTemplate> prototype_template = function_template->PrototypeTemplate();
+  prototype_template->SetInternalFieldCount(1);
+
+
+
+  interface_data->templ.Set(env->isolate(), function_template);
+}
+
+inline InterfaceData* GetInterfaceData(V8cGlobalEnvironment* env) {
+  const int kInterfaceUniqueId = 44;
+  // By convention, the |V8cGlobalEnvironment| that we are associated with
+  // will hold our |InterfaceData| at index |kInterfaceUniqueId|, as we asked
+  // for it to be there in the first place, and could not have conflicted with
+  // any other interface.
+  return env->GetInterfaceData(kInterfaceUniqueId);
+}
+
+}  // namespace
+
+v8::Local<v8::Object> V8cStaticPropertiesInterface::CreateWrapper(V8cGlobalEnvironment* env, const scoped_refptr<Wrappable>& wrappable) {
+  v8::Isolate* isolate = env->isolate();
+  v8::Isolate::Scope isolate_scope(isolate);
+  v8::EscapableHandleScope handle_scope(isolate);
+  v8::Local<v8::Context> context = env->context();
+  v8::Context::Scope scope(context);
+
+  InterfaceData* interface_data = GetInterfaceData(env);
+  if (interface_data->templ.IsEmpty()) {
+    InitializeTemplate(env, interface_data);
+  }
+  DCHECK(!interface_data->templ.IsEmpty());
+
+  v8::Local<v8::FunctionTemplate> function_template = interface_data->templ.Get(isolate);
+  DCHECK(function_template->InstanceTemplate()->InternalFieldCount() == 1);
+  v8::Local<v8::Object> object = function_template->InstanceTemplate()->NewInstance(context).ToLocalChecked();
+  DCHECK(object->InternalFieldCount() == 1);
+
+  // |WrapperPrivate|'s lifetime will be managed by V8.
+  new WrapperPrivate(isolate, wrappable, object);
+  return handle_scope.Escape(object);
+}
+
+v8::Local<v8::FunctionTemplate> V8cStaticPropertiesInterface::CreateTemplate(V8cGlobalEnvironment* env) {
+  InterfaceData* interface_data = GetInterfaceData(env);
+  if (interface_data->templ.IsEmpty()) {
+    InitializeTemplate(env, interface_data);
+  }
+
+  return interface_data->templ.Get(env->isolate());
+}
+
+
+}  // namespace testing
+}  // namespace bindings
+}  // namespace cobalt
+
+
diff --git a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_static_properties_interface.h b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_static_properties_interface.h
new file mode 100644
index 0000000..7b1f0d8
--- /dev/null
+++ b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_static_properties_interface.h
@@ -0,0 +1,50 @@
+
+// Copyright 2017 Google Inc. All Rights Reserved.
+//
+// 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.
+
+// clang-format off
+
+// This file has been auto-generated by bindings/code_generator_cobalt.py. DO NOT MODIFY!
+// Auto-generated from template: bindings/v8c/templates/interface.h.template
+
+#ifndef V8cStaticPropertiesInterface_h
+#define V8cStaticPropertiesInterface_h
+
+#include "base/hash_tables.h"
+#include "base/lazy_instance.h"
+#include "base/memory/ref_counted.h"
+#include "base/threading/thread_checker.h"
+#include "cobalt/base/polymorphic_downcast.h"
+#include "cobalt/script/wrappable.h"
+#include "cobalt/bindings/testing/static_properties_interface.h"
+
+#include "cobalt/script/v8c/v8c_global_environment.h"
+#include "v8/include/v8.h"
+
+namespace cobalt {
+namespace bindings {
+namespace testing {
+
+class V8cStaticPropertiesInterface {
+ public:
+  static v8::Local<v8::Object> CreateWrapper(script::v8c::V8cGlobalEnvironment* env, const scoped_refptr<script::Wrappable>& wrappable);
+  static v8::Local<v8::FunctionTemplate> CreateTemplate(script::v8c::V8cGlobalEnvironment* env);
+  // TODO: Add |GetInterfaceObject|.
+};
+
+}  // namespace testing
+}  // namespace bindings
+}  // namespace cobalt
+
+#endif  // V8cStaticPropertiesInterface_h
diff --git a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_stringifier_anonymous_operation_interface.cc b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_stringifier_anonymous_operation_interface.cc
new file mode 100644
index 0000000..5c40926
--- /dev/null
+++ b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_stringifier_anonymous_operation_interface.cc
@@ -0,0 +1,170 @@
+
+
+// Copyright 2017 Google Inc. All Rights Reserved.
+//
+// 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.
+
+// clang-format off
+
+// This file has been auto-generated by bindings/code_generator_cobalt.py. DO NOT MODIFY!
+// Auto-generated from template: bindings/v8c/templates/interface.cc.template
+
+#include "cobalt/bindings/testing/v8c_stringifier_anonymous_operation_interface.h"
+
+#include "base/debug/trace_event.h"
+#include "cobalt/base/polymorphic_downcast.h"
+#include "cobalt/script/global_environment.h"
+#include "cobalt/script/script_value.h"
+#include "cobalt/script/value_handle.h"
+
+#include "v8c_gen_type_conversion.h"
+
+#include "cobalt/script/callback_interface_traits.h"
+#include "cobalt/script/v8c/callback_function_conversion.h"
+#include "cobalt/script/v8c/conversion_helpers.h"
+#include "cobalt/script/v8c/native_promise.h"
+#include "cobalt/script/v8c/type_traits.h"
+#include "cobalt/script/v8c/v8c_callback_function.h"
+#include "cobalt/script/v8c/v8c_callback_interface_holder.h"
+#include "cobalt/script/v8c/v8c_exception_state.h"
+#include "cobalt/script/v8c/v8c_global_environment.h"
+#include "cobalt/script/v8c/v8c_value_handle.h"
+#include "cobalt/script/v8c/wrapper_private.h"
+#include "v8/include/v8.h"
+
+
+namespace {
+using cobalt::bindings::testing::StringifierAnonymousOperationInterface;
+using cobalt::bindings::testing::V8cStringifierAnonymousOperationInterface;
+using cobalt::script::CallbackInterfaceTraits;
+using cobalt::script::GlobalEnvironment;
+using cobalt::script::ScriptValue;
+using cobalt::script::ValueHandle;
+using cobalt::script::ValueHandle;
+using cobalt::script::ValueHandleHolder;
+using cobalt::script::Wrappable;
+
+using cobalt::script::v8c::FromJSValue;
+using cobalt::script::v8c::InterfaceData;
+using cobalt::script::v8c::kConversionFlagClamped;
+using cobalt::script::v8c::kConversionFlagNullable;
+using cobalt::script::v8c::kConversionFlagRestricted;
+using cobalt::script::v8c::kConversionFlagTreatNullAsEmptyString;
+using cobalt::script::v8c::kConversionFlagTreatUndefinedAsEmptyString;
+using cobalt::script::v8c::kNoConversionFlags;
+using cobalt::script::v8c::TypeTraits;
+using cobalt::script::v8c::V8cExceptionState;
+using cobalt::script::v8c::V8cGlobalEnvironment;
+using cobalt::script::v8c::WrapperFactory;
+using cobalt::script::v8c::WrapperPrivate;
+
+v8::Local<v8::Object> DummyFunctor(V8cGlobalEnvironment*, const scoped_refptr<Wrappable>&) {
+  NOTIMPLEMENTED();
+  return {};
+}
+
+}  // namespace
+
+namespace cobalt {
+namespace bindings {
+namespace testing {
+
+
+namespace {
+
+void StringifierAnonymousOperationInterfaceConstructor(const v8::FunctionCallbackInfo<v8::Value>& args) {
+  NOTIMPLEMENTED();
+  if (!args.IsConstructCall()) {
+    // TODO: Probably throw something here...
+    return;
+  }
+
+  DCHECK(args.This()->InternalFieldCount() == 1);
+  args.This()->SetInternalField(0, v8::External::New(args.GetIsolate(), nullptr));
+  args.GetReturnValue().Set(args.This());
+}
+
+
+void DummyFunction(const v8::FunctionCallbackInfo<v8::Value>& info) {
+  LOG(INFO) << __func__;
+}
+
+void InitializeTemplate(
+  V8cGlobalEnvironment* env,
+  InterfaceData* interface_data) {
+  v8::Isolate* isolate = env->isolate();
+  v8::Local<v8::FunctionTemplate> function_template = v8::FunctionTemplate::New(
+    isolate);
+  function_template->SetClassName(
+    v8::String::NewFromUtf8(isolate, "StringifierAnonymousOperationInterface",
+        v8::NewStringType::kInternalized).ToLocalChecked());
+  v8::Local<v8::ObjectTemplate> instance_template = function_template->InstanceTemplate();
+  instance_template->SetInternalFieldCount(1);
+
+  v8::Local<v8::ObjectTemplate> prototype_template = function_template->PrototypeTemplate();
+  prototype_template->SetInternalFieldCount(1);
+
+
+
+  interface_data->templ.Set(env->isolate(), function_template);
+}
+
+inline InterfaceData* GetInterfaceData(V8cGlobalEnvironment* env) {
+  const int kInterfaceUniqueId = 45;
+  // By convention, the |V8cGlobalEnvironment| that we are associated with
+  // will hold our |InterfaceData| at index |kInterfaceUniqueId|, as we asked
+  // for it to be there in the first place, and could not have conflicted with
+  // any other interface.
+  return env->GetInterfaceData(kInterfaceUniqueId);
+}
+
+}  // namespace
+
+v8::Local<v8::Object> V8cStringifierAnonymousOperationInterface::CreateWrapper(V8cGlobalEnvironment* env, const scoped_refptr<Wrappable>& wrappable) {
+  v8::Isolate* isolate = env->isolate();
+  v8::Isolate::Scope isolate_scope(isolate);
+  v8::EscapableHandleScope handle_scope(isolate);
+  v8::Local<v8::Context> context = env->context();
+  v8::Context::Scope scope(context);
+
+  InterfaceData* interface_data = GetInterfaceData(env);
+  if (interface_data->templ.IsEmpty()) {
+    InitializeTemplate(env, interface_data);
+  }
+  DCHECK(!interface_data->templ.IsEmpty());
+
+  v8::Local<v8::FunctionTemplate> function_template = interface_data->templ.Get(isolate);
+  DCHECK(function_template->InstanceTemplate()->InternalFieldCount() == 1);
+  v8::Local<v8::Object> object = function_template->InstanceTemplate()->NewInstance(context).ToLocalChecked();
+  DCHECK(object->InternalFieldCount() == 1);
+
+  // |WrapperPrivate|'s lifetime will be managed by V8.
+  new WrapperPrivate(isolate, wrappable, object);
+  return handle_scope.Escape(object);
+}
+
+v8::Local<v8::FunctionTemplate> V8cStringifierAnonymousOperationInterface::CreateTemplate(V8cGlobalEnvironment* env) {
+  InterfaceData* interface_data = GetInterfaceData(env);
+  if (interface_data->templ.IsEmpty()) {
+    InitializeTemplate(env, interface_data);
+  }
+
+  return interface_data->templ.Get(env->isolate());
+}
+
+
+}  // namespace testing
+}  // namespace bindings
+}  // namespace cobalt
+
+
diff --git a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_stringifier_anonymous_operation_interface.h b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_stringifier_anonymous_operation_interface.h
new file mode 100644
index 0000000..03e7eadd
--- /dev/null
+++ b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_stringifier_anonymous_operation_interface.h
@@ -0,0 +1,50 @@
+
+// Copyright 2017 Google Inc. All Rights Reserved.
+//
+// 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.
+
+// clang-format off
+
+// This file has been auto-generated by bindings/code_generator_cobalt.py. DO NOT MODIFY!
+// Auto-generated from template: bindings/v8c/templates/interface.h.template
+
+#ifndef V8cStringifierAnonymousOperationInterface_h
+#define V8cStringifierAnonymousOperationInterface_h
+
+#include "base/hash_tables.h"
+#include "base/lazy_instance.h"
+#include "base/memory/ref_counted.h"
+#include "base/threading/thread_checker.h"
+#include "cobalt/base/polymorphic_downcast.h"
+#include "cobalt/script/wrappable.h"
+#include "cobalt/bindings/testing/stringifier_anonymous_operation_interface.h"
+
+#include "cobalt/script/v8c/v8c_global_environment.h"
+#include "v8/include/v8.h"
+
+namespace cobalt {
+namespace bindings {
+namespace testing {
+
+class V8cStringifierAnonymousOperationInterface {
+ public:
+  static v8::Local<v8::Object> CreateWrapper(script::v8c::V8cGlobalEnvironment* env, const scoped_refptr<script::Wrappable>& wrappable);
+  static v8::Local<v8::FunctionTemplate> CreateTemplate(script::v8c::V8cGlobalEnvironment* env);
+  // TODO: Add |GetInterfaceObject|.
+};
+
+}  // namespace testing
+}  // namespace bindings
+}  // namespace cobalt
+
+#endif  // V8cStringifierAnonymousOperationInterface_h
diff --git a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_stringifier_attribute_interface.cc b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_stringifier_attribute_interface.cc
new file mode 100644
index 0000000..9db90eb
--- /dev/null
+++ b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_stringifier_attribute_interface.cc
@@ -0,0 +1,210 @@
+
+
+// Copyright 2017 Google Inc. All Rights Reserved.
+//
+// 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.
+
+// clang-format off
+
+// This file has been auto-generated by bindings/code_generator_cobalt.py. DO NOT MODIFY!
+// Auto-generated from template: bindings/v8c/templates/interface.cc.template
+
+#include "cobalt/bindings/testing/v8c_stringifier_attribute_interface.h"
+
+#include "base/debug/trace_event.h"
+#include "cobalt/base/polymorphic_downcast.h"
+#include "cobalt/script/global_environment.h"
+#include "cobalt/script/script_value.h"
+#include "cobalt/script/value_handle.h"
+
+#include "v8c_gen_type_conversion.h"
+
+#include "cobalt/script/callback_interface_traits.h"
+#include "cobalt/script/v8c/callback_function_conversion.h"
+#include "cobalt/script/v8c/conversion_helpers.h"
+#include "cobalt/script/v8c/native_promise.h"
+#include "cobalt/script/v8c/type_traits.h"
+#include "cobalt/script/v8c/v8c_callback_function.h"
+#include "cobalt/script/v8c/v8c_callback_interface_holder.h"
+#include "cobalt/script/v8c/v8c_exception_state.h"
+#include "cobalt/script/v8c/v8c_global_environment.h"
+#include "cobalt/script/v8c/v8c_value_handle.h"
+#include "cobalt/script/v8c/wrapper_private.h"
+#include "v8/include/v8.h"
+
+
+namespace {
+using cobalt::bindings::testing::StringifierAttributeInterface;
+using cobalt::bindings::testing::V8cStringifierAttributeInterface;
+using cobalt::script::CallbackInterfaceTraits;
+using cobalt::script::GlobalEnvironment;
+using cobalt::script::ScriptValue;
+using cobalt::script::ValueHandle;
+using cobalt::script::ValueHandle;
+using cobalt::script::ValueHandleHolder;
+using cobalt::script::Wrappable;
+
+using cobalt::script::v8c::FromJSValue;
+using cobalt::script::v8c::InterfaceData;
+using cobalt::script::v8c::kConversionFlagClamped;
+using cobalt::script::v8c::kConversionFlagNullable;
+using cobalt::script::v8c::kConversionFlagRestricted;
+using cobalt::script::v8c::kConversionFlagTreatNullAsEmptyString;
+using cobalt::script::v8c::kConversionFlagTreatUndefinedAsEmptyString;
+using cobalt::script::v8c::kNoConversionFlags;
+using cobalt::script::v8c::TypeTraits;
+using cobalt::script::v8c::V8cExceptionState;
+using cobalt::script::v8c::V8cGlobalEnvironment;
+using cobalt::script::v8c::WrapperFactory;
+using cobalt::script::v8c::WrapperPrivate;
+
+v8::Local<v8::Object> DummyFunctor(V8cGlobalEnvironment*, const scoped_refptr<Wrappable>&) {
+  NOTIMPLEMENTED();
+  return {};
+}
+
+}  // namespace
+
+namespace cobalt {
+namespace bindings {
+namespace testing {
+
+
+namespace {
+
+void StringifierAttributeInterfaceConstructor(const v8::FunctionCallbackInfo<v8::Value>& args) {
+  NOTIMPLEMENTED();
+  if (!args.IsConstructCall()) {
+    // TODO: Probably throw something here...
+    return;
+  }
+
+  DCHECK(args.This()->InternalFieldCount() == 1);
+  args.This()->SetInternalField(0, v8::External::New(args.GetIsolate(), nullptr));
+  args.GetReturnValue().Set(args.This());
+}
+
+
+void v8cGet_theStringifierAttribute(
+  v8::Local<v8::String> property,
+  const v8::PropertyCallbackInfo<v8::Value>& info)
+{
+  NOTIMPLEMENTED();
+
+  v8::Local<v8::External> external = v8::Local<v8::External>::Cast(info.Holder()->GetInternalField(0));
+  WrapperPrivate* wrapper_private = static_cast<WrapperPrivate*>(external->Value());
+  StringifierAttributeInterface* impl = static_cast<StringifierAttributeInterface*>(wrapper_private->wrappable<StringifierAttributeInterface>());
+
+  v8::Local<v8::Value> result_value;
+}
+
+
+void v8cSet_theStringifierAttribute(
+  v8::Local<v8::String> property,
+  v8::Local<v8::Value> v8_value,
+  const v8::PropertyCallbackInfo<void>& info)
+{
+  v8::Local<v8::External> external = v8::Local<v8::External>::Cast(info.Holder()->GetInternalField(0));
+  WrapperPrivate* wrapper_private = static_cast<WrapperPrivate*>(external->Value());
+  StringifierAttributeInterface* impl = static_cast<StringifierAttributeInterface*>(wrapper_private->wrappable<StringifierAttributeInterface>());
+
+  TypeTraits<std::string>::ConversionType conversion_value;
+  V8cExceptionState exception_state{};
+  FromJSValue(info.GetIsolate(), v8_value, kNoConversionFlags, &exception_state, &conversion_value);
+  impl->set_the_stringifier_attribute(
+    conversion_value
+  );
+}
+
+
+
+void DummyFunction(const v8::FunctionCallbackInfo<v8::Value>& info) {
+  LOG(INFO) << __func__;
+}
+
+void InitializeTemplate(
+  V8cGlobalEnvironment* env,
+  InterfaceData* interface_data) {
+  v8::Isolate* isolate = env->isolate();
+  v8::Local<v8::FunctionTemplate> function_template = v8::FunctionTemplate::New(
+    isolate);
+  function_template->SetClassName(
+    v8::String::NewFromUtf8(isolate, "StringifierAttributeInterface",
+        v8::NewStringType::kInternalized).ToLocalChecked());
+  v8::Local<v8::ObjectTemplate> instance_template = function_template->InstanceTemplate();
+  instance_template->SetInternalFieldCount(1);
+
+  v8::Local<v8::ObjectTemplate> prototype_template = function_template->PrototypeTemplate();
+  prototype_template->SetInternalFieldCount(1);
+
+  instance_template->SetAccessor(
+    v8::String::NewFromUtf8(isolate, "theStringifierAttribute",
+                              v8::NewStringType::kInternalized)
+          .ToLocalChecked(),
+    v8cGet_theStringifierAttribute
+    ,v8cSet_theStringifierAttribute
+  );
+
+
+  interface_data->templ.Set(env->isolate(), function_template);
+}
+
+inline InterfaceData* GetInterfaceData(V8cGlobalEnvironment* env) {
+  const int kInterfaceUniqueId = 46;
+  // By convention, the |V8cGlobalEnvironment| that we are associated with
+  // will hold our |InterfaceData| at index |kInterfaceUniqueId|, as we asked
+  // for it to be there in the first place, and could not have conflicted with
+  // any other interface.
+  return env->GetInterfaceData(kInterfaceUniqueId);
+}
+
+}  // namespace
+
+v8::Local<v8::Object> V8cStringifierAttributeInterface::CreateWrapper(V8cGlobalEnvironment* env, const scoped_refptr<Wrappable>& wrappable) {
+  v8::Isolate* isolate = env->isolate();
+  v8::Isolate::Scope isolate_scope(isolate);
+  v8::EscapableHandleScope handle_scope(isolate);
+  v8::Local<v8::Context> context = env->context();
+  v8::Context::Scope scope(context);
+
+  InterfaceData* interface_data = GetInterfaceData(env);
+  if (interface_data->templ.IsEmpty()) {
+    InitializeTemplate(env, interface_data);
+  }
+  DCHECK(!interface_data->templ.IsEmpty());
+
+  v8::Local<v8::FunctionTemplate> function_template = interface_data->templ.Get(isolate);
+  DCHECK(function_template->InstanceTemplate()->InternalFieldCount() == 1);
+  v8::Local<v8::Object> object = function_template->InstanceTemplate()->NewInstance(context).ToLocalChecked();
+  DCHECK(object->InternalFieldCount() == 1);
+
+  // |WrapperPrivate|'s lifetime will be managed by V8.
+  new WrapperPrivate(isolate, wrappable, object);
+  return handle_scope.Escape(object);
+}
+
+v8::Local<v8::FunctionTemplate> V8cStringifierAttributeInterface::CreateTemplate(V8cGlobalEnvironment* env) {
+  InterfaceData* interface_data = GetInterfaceData(env);
+  if (interface_data->templ.IsEmpty()) {
+    InitializeTemplate(env, interface_data);
+  }
+
+  return interface_data->templ.Get(env->isolate());
+}
+
+
+}  // namespace testing
+}  // namespace bindings
+}  // namespace cobalt
+
+
diff --git a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_stringifier_attribute_interface.h b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_stringifier_attribute_interface.h
new file mode 100644
index 0000000..7e1920d
--- /dev/null
+++ b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_stringifier_attribute_interface.h
@@ -0,0 +1,50 @@
+
+// Copyright 2017 Google Inc. All Rights Reserved.
+//
+// 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.
+
+// clang-format off
+
+// This file has been auto-generated by bindings/code_generator_cobalt.py. DO NOT MODIFY!
+// Auto-generated from template: bindings/v8c/templates/interface.h.template
+
+#ifndef V8cStringifierAttributeInterface_h
+#define V8cStringifierAttributeInterface_h
+
+#include "base/hash_tables.h"
+#include "base/lazy_instance.h"
+#include "base/memory/ref_counted.h"
+#include "base/threading/thread_checker.h"
+#include "cobalt/base/polymorphic_downcast.h"
+#include "cobalt/script/wrappable.h"
+#include "cobalt/bindings/testing/stringifier_attribute_interface.h"
+
+#include "cobalt/script/v8c/v8c_global_environment.h"
+#include "v8/include/v8.h"
+
+namespace cobalt {
+namespace bindings {
+namespace testing {
+
+class V8cStringifierAttributeInterface {
+ public:
+  static v8::Local<v8::Object> CreateWrapper(script::v8c::V8cGlobalEnvironment* env, const scoped_refptr<script::Wrappable>& wrappable);
+  static v8::Local<v8::FunctionTemplate> CreateTemplate(script::v8c::V8cGlobalEnvironment* env);
+  // TODO: Add |GetInterfaceObject|.
+};
+
+}  // namespace testing
+}  // namespace bindings
+}  // namespace cobalt
+
+#endif  // V8cStringifierAttributeInterface_h
diff --git a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_stringifier_operation_interface.cc b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_stringifier_operation_interface.cc
new file mode 100644
index 0000000..1faaa25
--- /dev/null
+++ b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_stringifier_operation_interface.cc
@@ -0,0 +1,177 @@
+
+
+// Copyright 2017 Google Inc. All Rights Reserved.
+//
+// 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.
+
+// clang-format off
+
+// This file has been auto-generated by bindings/code_generator_cobalt.py. DO NOT MODIFY!
+// Auto-generated from template: bindings/v8c/templates/interface.cc.template
+
+#include "cobalt/bindings/testing/v8c_stringifier_operation_interface.h"
+
+#include "base/debug/trace_event.h"
+#include "cobalt/base/polymorphic_downcast.h"
+#include "cobalt/script/global_environment.h"
+#include "cobalt/script/script_value.h"
+#include "cobalt/script/value_handle.h"
+
+#include "v8c_gen_type_conversion.h"
+
+#include "cobalt/script/callback_interface_traits.h"
+#include "cobalt/script/v8c/callback_function_conversion.h"
+#include "cobalt/script/v8c/conversion_helpers.h"
+#include "cobalt/script/v8c/native_promise.h"
+#include "cobalt/script/v8c/type_traits.h"
+#include "cobalt/script/v8c/v8c_callback_function.h"
+#include "cobalt/script/v8c/v8c_callback_interface_holder.h"
+#include "cobalt/script/v8c/v8c_exception_state.h"
+#include "cobalt/script/v8c/v8c_global_environment.h"
+#include "cobalt/script/v8c/v8c_value_handle.h"
+#include "cobalt/script/v8c/wrapper_private.h"
+#include "v8/include/v8.h"
+
+
+namespace {
+using cobalt::bindings::testing::StringifierOperationInterface;
+using cobalt::bindings::testing::V8cStringifierOperationInterface;
+using cobalt::script::CallbackInterfaceTraits;
+using cobalt::script::GlobalEnvironment;
+using cobalt::script::ScriptValue;
+using cobalt::script::ValueHandle;
+using cobalt::script::ValueHandle;
+using cobalt::script::ValueHandleHolder;
+using cobalt::script::Wrappable;
+
+using cobalt::script::v8c::FromJSValue;
+using cobalt::script::v8c::InterfaceData;
+using cobalt::script::v8c::kConversionFlagClamped;
+using cobalt::script::v8c::kConversionFlagNullable;
+using cobalt::script::v8c::kConversionFlagRestricted;
+using cobalt::script::v8c::kConversionFlagTreatNullAsEmptyString;
+using cobalt::script::v8c::kConversionFlagTreatUndefinedAsEmptyString;
+using cobalt::script::v8c::kNoConversionFlags;
+using cobalt::script::v8c::TypeTraits;
+using cobalt::script::v8c::V8cExceptionState;
+using cobalt::script::v8c::V8cGlobalEnvironment;
+using cobalt::script::v8c::WrapperFactory;
+using cobalt::script::v8c::WrapperPrivate;
+
+v8::Local<v8::Object> DummyFunctor(V8cGlobalEnvironment*, const scoped_refptr<Wrappable>&) {
+  NOTIMPLEMENTED();
+  return {};
+}
+
+}  // namespace
+
+namespace cobalt {
+namespace bindings {
+namespace testing {
+
+
+namespace {
+
+void StringifierOperationInterfaceConstructor(const v8::FunctionCallbackInfo<v8::Value>& args) {
+  NOTIMPLEMENTED();
+  if (!args.IsConstructCall()) {
+    // TODO: Probably throw something here...
+    return;
+  }
+
+  DCHECK(args.This()->InternalFieldCount() == 1);
+  args.This()->SetInternalField(0, v8::External::New(args.GetIsolate(), nullptr));
+  args.GetReturnValue().Set(args.This());
+}
+
+
+void DummyFunction(const v8::FunctionCallbackInfo<v8::Value>& info) {
+  LOG(INFO) << __func__;
+}
+
+void InitializeTemplate(
+  V8cGlobalEnvironment* env,
+  InterfaceData* interface_data) {
+  v8::Isolate* isolate = env->isolate();
+  v8::Local<v8::FunctionTemplate> function_template = v8::FunctionTemplate::New(
+    isolate);
+  function_template->SetClassName(
+    v8::String::NewFromUtf8(isolate, "StringifierOperationInterface",
+        v8::NewStringType::kInternalized).ToLocalChecked());
+  v8::Local<v8::ObjectTemplate> instance_template = function_template->InstanceTemplate();
+  instance_template->SetInternalFieldCount(1);
+
+  v8::Local<v8::ObjectTemplate> prototype_template = function_template->PrototypeTemplate();
+  prototype_template->SetInternalFieldCount(1);
+
+
+  instance_template->Set(
+      v8::String::NewFromUtf8(
+          isolate,
+          "theStringifierOperation",
+          v8::NewStringType::kInternalized).ToLocalChecked(),
+      v8::FunctionTemplate::New(isolate, DummyFunction)
+  );
+
+  interface_data->templ.Set(env->isolate(), function_template);
+}
+
+inline InterfaceData* GetInterfaceData(V8cGlobalEnvironment* env) {
+  const int kInterfaceUniqueId = 47;
+  // By convention, the |V8cGlobalEnvironment| that we are associated with
+  // will hold our |InterfaceData| at index |kInterfaceUniqueId|, as we asked
+  // for it to be there in the first place, and could not have conflicted with
+  // any other interface.
+  return env->GetInterfaceData(kInterfaceUniqueId);
+}
+
+}  // namespace
+
+v8::Local<v8::Object> V8cStringifierOperationInterface::CreateWrapper(V8cGlobalEnvironment* env, const scoped_refptr<Wrappable>& wrappable) {
+  v8::Isolate* isolate = env->isolate();
+  v8::Isolate::Scope isolate_scope(isolate);
+  v8::EscapableHandleScope handle_scope(isolate);
+  v8::Local<v8::Context> context = env->context();
+  v8::Context::Scope scope(context);
+
+  InterfaceData* interface_data = GetInterfaceData(env);
+  if (interface_data->templ.IsEmpty()) {
+    InitializeTemplate(env, interface_data);
+  }
+  DCHECK(!interface_data->templ.IsEmpty());
+
+  v8::Local<v8::FunctionTemplate> function_template = interface_data->templ.Get(isolate);
+  DCHECK(function_template->InstanceTemplate()->InternalFieldCount() == 1);
+  v8::Local<v8::Object> object = function_template->InstanceTemplate()->NewInstance(context).ToLocalChecked();
+  DCHECK(object->InternalFieldCount() == 1);
+
+  // |WrapperPrivate|'s lifetime will be managed by V8.
+  new WrapperPrivate(isolate, wrappable, object);
+  return handle_scope.Escape(object);
+}
+
+v8::Local<v8::FunctionTemplate> V8cStringifierOperationInterface::CreateTemplate(V8cGlobalEnvironment* env) {
+  InterfaceData* interface_data = GetInterfaceData(env);
+  if (interface_data->templ.IsEmpty()) {
+    InitializeTemplate(env, interface_data);
+  }
+
+  return interface_data->templ.Get(env->isolate());
+}
+
+
+}  // namespace testing
+}  // namespace bindings
+}  // namespace cobalt
+
+
diff --git a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_stringifier_operation_interface.h b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_stringifier_operation_interface.h
new file mode 100644
index 0000000..df2355a
--- /dev/null
+++ b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_stringifier_operation_interface.h
@@ -0,0 +1,50 @@
+
+// Copyright 2017 Google Inc. All Rights Reserved.
+//
+// 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.
+
+// clang-format off
+
+// This file has been auto-generated by bindings/code_generator_cobalt.py. DO NOT MODIFY!
+// Auto-generated from template: bindings/v8c/templates/interface.h.template
+
+#ifndef V8cStringifierOperationInterface_h
+#define V8cStringifierOperationInterface_h
+
+#include "base/hash_tables.h"
+#include "base/lazy_instance.h"
+#include "base/memory/ref_counted.h"
+#include "base/threading/thread_checker.h"
+#include "cobalt/base/polymorphic_downcast.h"
+#include "cobalt/script/wrappable.h"
+#include "cobalt/bindings/testing/stringifier_operation_interface.h"
+
+#include "cobalt/script/v8c/v8c_global_environment.h"
+#include "v8/include/v8.h"
+
+namespace cobalt {
+namespace bindings {
+namespace testing {
+
+class V8cStringifierOperationInterface {
+ public:
+  static v8::Local<v8::Object> CreateWrapper(script::v8c::V8cGlobalEnvironment* env, const scoped_refptr<script::Wrappable>& wrappable);
+  static v8::Local<v8::FunctionTemplate> CreateTemplate(script::v8c::V8cGlobalEnvironment* env);
+  // TODO: Add |GetInterfaceObject|.
+};
+
+}  // namespace testing
+}  // namespace bindings
+}  // namespace cobalt
+
+#endif  // V8cStringifierOperationInterface_h
diff --git a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_target_interface.cc b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_target_interface.cc
new file mode 100644
index 0000000..5a26c28
--- /dev/null
+++ b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_target_interface.cc
@@ -0,0 +1,184 @@
+
+
+// Copyright 2017 Google Inc. All Rights Reserved.
+//
+// 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.
+
+// clang-format off
+
+// This file has been auto-generated by bindings/code_generator_cobalt.py. DO NOT MODIFY!
+// Auto-generated from template: bindings/v8c/templates/interface.cc.template
+
+#include "cobalt/bindings/testing/v8c_target_interface.h"
+
+#include "base/debug/trace_event.h"
+#include "cobalt/base/polymorphic_downcast.h"
+#include "cobalt/script/global_environment.h"
+#include "cobalt/script/script_value.h"
+#include "cobalt/script/value_handle.h"
+
+#include "v8c_gen_type_conversion.h"
+
+#include "cobalt/script/callback_interface_traits.h"
+#include "cobalt/script/v8c/callback_function_conversion.h"
+#include "cobalt/script/v8c/conversion_helpers.h"
+#include "cobalt/script/v8c/native_promise.h"
+#include "cobalt/script/v8c/type_traits.h"
+#include "cobalt/script/v8c/v8c_callback_function.h"
+#include "cobalt/script/v8c/v8c_callback_interface_holder.h"
+#include "cobalt/script/v8c/v8c_exception_state.h"
+#include "cobalt/script/v8c/v8c_global_environment.h"
+#include "cobalt/script/v8c/v8c_value_handle.h"
+#include "cobalt/script/v8c/wrapper_private.h"
+#include "v8/include/v8.h"
+
+
+namespace {
+using cobalt::bindings::testing::TargetInterface;
+using cobalt::bindings::testing::V8cTargetInterface;
+using cobalt::script::CallbackInterfaceTraits;
+using cobalt::script::GlobalEnvironment;
+using cobalt::script::ScriptValue;
+using cobalt::script::ValueHandle;
+using cobalt::script::ValueHandle;
+using cobalt::script::ValueHandleHolder;
+using cobalt::script::Wrappable;
+
+using cobalt::script::v8c::FromJSValue;
+using cobalt::script::v8c::InterfaceData;
+using cobalt::script::v8c::kConversionFlagClamped;
+using cobalt::script::v8c::kConversionFlagNullable;
+using cobalt::script::v8c::kConversionFlagRestricted;
+using cobalt::script::v8c::kConversionFlagTreatNullAsEmptyString;
+using cobalt::script::v8c::kConversionFlagTreatUndefinedAsEmptyString;
+using cobalt::script::v8c::kNoConversionFlags;
+using cobalt::script::v8c::TypeTraits;
+using cobalt::script::v8c::V8cExceptionState;
+using cobalt::script::v8c::V8cGlobalEnvironment;
+using cobalt::script::v8c::WrapperFactory;
+using cobalt::script::v8c::WrapperPrivate;
+
+v8::Local<v8::Object> DummyFunctor(V8cGlobalEnvironment*, const scoped_refptr<Wrappable>&) {
+  NOTIMPLEMENTED();
+  return {};
+}
+
+}  // namespace
+
+namespace cobalt {
+namespace bindings {
+namespace testing {
+
+
+namespace {
+
+void TargetInterfaceConstructor(const v8::FunctionCallbackInfo<v8::Value>& args) {
+  NOTIMPLEMENTED();
+  if (!args.IsConstructCall()) {
+    // TODO: Probably throw something here...
+    return;
+  }
+
+  DCHECK(args.This()->InternalFieldCount() == 1);
+  args.This()->SetInternalField(0, v8::External::New(args.GetIsolate(), nullptr));
+  args.GetReturnValue().Set(args.This());
+}
+
+
+void DummyFunction(const v8::FunctionCallbackInfo<v8::Value>& info) {
+  LOG(INFO) << __func__;
+}
+
+void InitializeTemplate(
+  V8cGlobalEnvironment* env,
+  InterfaceData* interface_data) {
+  v8::Isolate* isolate = env->isolate();
+  v8::Local<v8::FunctionTemplate> function_template = v8::FunctionTemplate::New(
+    isolate);
+  function_template->SetClassName(
+    v8::String::NewFromUtf8(isolate, "TargetInterface",
+        v8::NewStringType::kInternalized).ToLocalChecked());
+  v8::Local<v8::ObjectTemplate> instance_template = function_template->InstanceTemplate();
+  instance_template->SetInternalFieldCount(1);
+
+  v8::Local<v8::ObjectTemplate> prototype_template = function_template->PrototypeTemplate();
+  prototype_template->SetInternalFieldCount(1);
+
+
+  instance_template->Set(
+      v8::String::NewFromUtf8(
+          isolate,
+          "implementedInterfaceFunction",
+          v8::NewStringType::kInternalized).ToLocalChecked(),
+      v8::FunctionTemplate::New(isolate, DummyFunction)
+  );
+  instance_template->Set(
+      v8::String::NewFromUtf8(
+          isolate,
+          "partialInterfaceFunction",
+          v8::NewStringType::kInternalized).ToLocalChecked(),
+      v8::FunctionTemplate::New(isolate, DummyFunction)
+  );
+
+  interface_data->templ.Set(env->isolate(), function_template);
+}
+
+inline InterfaceData* GetInterfaceData(V8cGlobalEnvironment* env) {
+  const int kInterfaceUniqueId = 48;
+  // By convention, the |V8cGlobalEnvironment| that we are associated with
+  // will hold our |InterfaceData| at index |kInterfaceUniqueId|, as we asked
+  // for it to be there in the first place, and could not have conflicted with
+  // any other interface.
+  return env->GetInterfaceData(kInterfaceUniqueId);
+}
+
+}  // namespace
+
+v8::Local<v8::Object> V8cTargetInterface::CreateWrapper(V8cGlobalEnvironment* env, const scoped_refptr<Wrappable>& wrappable) {
+  v8::Isolate* isolate = env->isolate();
+  v8::Isolate::Scope isolate_scope(isolate);
+  v8::EscapableHandleScope handle_scope(isolate);
+  v8::Local<v8::Context> context = env->context();
+  v8::Context::Scope scope(context);
+
+  InterfaceData* interface_data = GetInterfaceData(env);
+  if (interface_data->templ.IsEmpty()) {
+    InitializeTemplate(env, interface_data);
+  }
+  DCHECK(!interface_data->templ.IsEmpty());
+
+  v8::Local<v8::FunctionTemplate> function_template = interface_data->templ.Get(isolate);
+  DCHECK(function_template->InstanceTemplate()->InternalFieldCount() == 1);
+  v8::Local<v8::Object> object = function_template->InstanceTemplate()->NewInstance(context).ToLocalChecked();
+  DCHECK(object->InternalFieldCount() == 1);
+
+  // |WrapperPrivate|'s lifetime will be managed by V8.
+  new WrapperPrivate(isolate, wrappable, object);
+  return handle_scope.Escape(object);
+}
+
+v8::Local<v8::FunctionTemplate> V8cTargetInterface::CreateTemplate(V8cGlobalEnvironment* env) {
+  InterfaceData* interface_data = GetInterfaceData(env);
+  if (interface_data->templ.IsEmpty()) {
+    InitializeTemplate(env, interface_data);
+  }
+
+  return interface_data->templ.Get(env->isolate());
+}
+
+
+}  // namespace testing
+}  // namespace bindings
+}  // namespace cobalt
+
+
diff --git a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_target_interface.h b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_target_interface.h
new file mode 100644
index 0000000..314bb15
--- /dev/null
+++ b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_target_interface.h
@@ -0,0 +1,50 @@
+
+// Copyright 2017 Google Inc. All Rights Reserved.
+//
+// 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.
+
+// clang-format off
+
+// This file has been auto-generated by bindings/code_generator_cobalt.py. DO NOT MODIFY!
+// Auto-generated from template: bindings/v8c/templates/interface.h.template
+
+#ifndef V8cTargetInterface_h
+#define V8cTargetInterface_h
+
+#include "base/hash_tables.h"
+#include "base/lazy_instance.h"
+#include "base/memory/ref_counted.h"
+#include "base/threading/thread_checker.h"
+#include "cobalt/base/polymorphic_downcast.h"
+#include "cobalt/script/wrappable.h"
+#include "cobalt/bindings/testing/target_interface.h"
+
+#include "cobalt/script/v8c/v8c_global_environment.h"
+#include "v8/include/v8.h"
+
+namespace cobalt {
+namespace bindings {
+namespace testing {
+
+class V8cTargetInterface {
+ public:
+  static v8::Local<v8::Object> CreateWrapper(script::v8c::V8cGlobalEnvironment* env, const scoped_refptr<script::Wrappable>& wrappable);
+  static v8::Local<v8::FunctionTemplate> CreateTemplate(script::v8c::V8cGlobalEnvironment* env);
+  // TODO: Add |GetInterfaceObject|.
+};
+
+}  // namespace testing
+}  // namespace bindings
+}  // namespace cobalt
+
+#endif  // V8cTargetInterface_h
diff --git a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_test_dictionary.cc b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_test_dictionary.cc
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_test_dictionary.cc
diff --git a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_test_enum.cc b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_test_enum.cc
new file mode 100644
index 0000000..48f42a9
--- /dev/null
+++ b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_test_enum.cc
@@ -0,0 +1,51 @@
+
+/*
+ * Copyright 2017 Google Inc. All Rights Reserved.
+ *
+ * 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.
+ */
+
+// clang-format off
+
+// This file has been auto-generated by bindings/code_generator_cobalt.py. DO NOT MODIFY!
+// Auto-generated from template: bindings/v8c/templates/enumeration-conversion.cc.template
+
+#include "cobalt/bindings/testing/test_enum.h"
+
+#include "v8c_gen_type_conversion.h"
+#include "base/logging.h"
+#include "cobalt/script/exception_state.h"
+#include "v8/include/v8.h"
+
+using cobalt::bindings::testing::TestEnum;
+
+namespace cobalt {
+namespace script {
+namespace v8c {
+
+void ToJSValue(
+    v8::Isolate* isolate,
+    TestEnum in_enum,
+    v8::Local<v8::Value> out_value) {
+  NOTIMPLEMENTED();
+}
+
+void FromJSValue(v8::Isolate* isolate, v8::Local<v8::Value> value,
+                 int conversion_flags, ExceptionState* exception_state,
+                 TestEnum* out_enum) {
+  NOTIMPLEMENTED();
+}
+
+}  // namespace v8c
+}  // namespace script
+}  // namespace cobalt
diff --git a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_union_types_interface.cc b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_union_types_interface.cc
new file mode 100644
index 0000000..478aedc
--- /dev/null
+++ b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_union_types_interface.cc
@@ -0,0 +1,338 @@
+
+
+// Copyright 2017 Google Inc. All Rights Reserved.
+//
+// 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.
+
+// clang-format off
+
+// This file has been auto-generated by bindings/code_generator_cobalt.py. DO NOT MODIFY!
+// Auto-generated from template: bindings/v8c/templates/interface.cc.template
+
+#include "cobalt/bindings/testing/v8c_union_types_interface.h"
+
+#include "base/debug/trace_event.h"
+#include "cobalt/base/polymorphic_downcast.h"
+#include "cobalt/script/global_environment.h"
+#include "cobalt/script/script_value.h"
+#include "cobalt/script/value_handle.h"
+#include "cobalt/bindings/testing/arbitrary_interface.h"
+#include "cobalt/bindings/testing/base_interface.h"
+#include "cobalt/bindings/testing/v8c_arbitrary_interface.h"
+#include "cobalt/bindings/testing/v8c_base_interface.h"
+
+#include "v8c_gen_type_conversion.h"
+
+#include "cobalt/script/callback_interface_traits.h"
+#include "cobalt/script/v8c/callback_function_conversion.h"
+#include "cobalt/script/v8c/conversion_helpers.h"
+#include "cobalt/script/v8c/native_promise.h"
+#include "cobalt/script/v8c/type_traits.h"
+#include "cobalt/script/v8c/v8c_callback_function.h"
+#include "cobalt/script/v8c/v8c_callback_interface_holder.h"
+#include "cobalt/script/v8c/v8c_exception_state.h"
+#include "cobalt/script/v8c/v8c_global_environment.h"
+#include "cobalt/script/v8c/v8c_value_handle.h"
+#include "cobalt/script/v8c/wrapper_private.h"
+#include "v8/include/v8.h"
+
+
+namespace {
+using cobalt::bindings::testing::UnionTypesInterface;
+using cobalt::bindings::testing::V8cUnionTypesInterface;
+using cobalt::bindings::testing::ArbitraryInterface;
+using cobalt::bindings::testing::BaseInterface;
+using cobalt::bindings::testing::V8cArbitraryInterface;
+using cobalt::bindings::testing::V8cBaseInterface;
+using cobalt::script::CallbackInterfaceTraits;
+using cobalt::script::GlobalEnvironment;
+using cobalt::script::ScriptValue;
+using cobalt::script::ValueHandle;
+using cobalt::script::ValueHandle;
+using cobalt::script::ValueHandleHolder;
+using cobalt::script::Wrappable;
+
+using cobalt::script::v8c::FromJSValue;
+using cobalt::script::v8c::InterfaceData;
+using cobalt::script::v8c::kConversionFlagClamped;
+using cobalt::script::v8c::kConversionFlagNullable;
+using cobalt::script::v8c::kConversionFlagRestricted;
+using cobalt::script::v8c::kConversionFlagTreatNullAsEmptyString;
+using cobalt::script::v8c::kConversionFlagTreatUndefinedAsEmptyString;
+using cobalt::script::v8c::kNoConversionFlags;
+using cobalt::script::v8c::TypeTraits;
+using cobalt::script::v8c::V8cExceptionState;
+using cobalt::script::v8c::V8cGlobalEnvironment;
+using cobalt::script::v8c::WrapperFactory;
+using cobalt::script::v8c::WrapperPrivate;
+
+v8::Local<v8::Object> DummyFunctor(V8cGlobalEnvironment*, const scoped_refptr<Wrappable>&) {
+  NOTIMPLEMENTED();
+  return {};
+}
+
+}  // namespace
+
+namespace cobalt {
+namespace bindings {
+namespace testing {
+
+
+namespace {
+
+void UnionTypesInterfaceConstructor(const v8::FunctionCallbackInfo<v8::Value>& args) {
+  NOTIMPLEMENTED();
+  if (!args.IsConstructCall()) {
+    // TODO: Probably throw something here...
+    return;
+  }
+
+  DCHECK(args.This()->InternalFieldCount() == 1);
+  args.This()->SetInternalField(0, v8::External::New(args.GetIsolate(), nullptr));
+  args.GetReturnValue().Set(args.This());
+}
+
+
+void v8cGet_unionProperty(
+  v8::Local<v8::String> property,
+  const v8::PropertyCallbackInfo<v8::Value>& info)
+{
+  NOTIMPLEMENTED();
+
+  v8::Local<v8::External> external = v8::Local<v8::External>::Cast(info.Holder()->GetInternalField(0));
+  WrapperPrivate* wrapper_private = static_cast<WrapperPrivate*>(external->Value());
+  UnionTypesInterface* impl = static_cast<UnionTypesInterface*>(wrapper_private->wrappable<UnionTypesInterface>());
+
+  v8::Local<v8::Value> result_value;
+}
+
+
+void v8cSet_unionProperty(
+  v8::Local<v8::String> property,
+  v8::Local<v8::Value> v8_value,
+  const v8::PropertyCallbackInfo<void>& info)
+{
+  v8::Local<v8::External> external = v8::Local<v8::External>::Cast(info.Holder()->GetInternalField(0));
+  WrapperPrivate* wrapper_private = static_cast<WrapperPrivate*>(external->Value());
+  UnionTypesInterface* impl = static_cast<UnionTypesInterface*>(wrapper_private->wrappable<UnionTypesInterface>());
+
+  TypeTraits<::cobalt::script::UnionType4<std::string, bool, scoped_refptr<ArbitraryInterface>, int32_t >>::ConversionType conversion_value;
+  V8cExceptionState exception_state{};
+  FromJSValue(info.GetIsolate(), v8_value, kNoConversionFlags, &exception_state, &conversion_value);
+  impl->set_union_property(
+    conversion_value
+  );
+}
+
+
+
+void v8cGet_unionWithNullableMemberProperty(
+  v8::Local<v8::String> property,
+  const v8::PropertyCallbackInfo<v8::Value>& info)
+{
+  NOTIMPLEMENTED();
+
+  v8::Local<v8::External> external = v8::Local<v8::External>::Cast(info.Holder()->GetInternalField(0));
+  WrapperPrivate* wrapper_private = static_cast<WrapperPrivate*>(external->Value());
+  UnionTypesInterface* impl = static_cast<UnionTypesInterface*>(wrapper_private->wrappable<UnionTypesInterface>());
+
+  v8::Local<v8::Value> result_value;
+}
+
+
+void v8cSet_unionWithNullableMemberProperty(
+  v8::Local<v8::String> property,
+  v8::Local<v8::Value> v8_value,
+  const v8::PropertyCallbackInfo<void>& info)
+{
+  v8::Local<v8::External> external = v8::Local<v8::External>::Cast(info.Holder()->GetInternalField(0));
+  WrapperPrivate* wrapper_private = static_cast<WrapperPrivate*>(external->Value());
+  UnionTypesInterface* impl = static_cast<UnionTypesInterface*>(wrapper_private->wrappable<UnionTypesInterface>());
+
+  TypeTraits<base::optional<::cobalt::script::UnionType2<double, std::string > >>::ConversionType conversion_value;
+  V8cExceptionState exception_state{};
+  FromJSValue(info.GetIsolate(), v8_value, kNoConversionFlags, &exception_state, &conversion_value);
+  impl->set_union_with_nullable_member_property(
+    conversion_value
+  );
+}
+
+
+
+void v8cGet_nullableUnionProperty(
+  v8::Local<v8::String> property,
+  const v8::PropertyCallbackInfo<v8::Value>& info)
+{
+  NOTIMPLEMENTED();
+
+  v8::Local<v8::External> external = v8::Local<v8::External>::Cast(info.Holder()->GetInternalField(0));
+  WrapperPrivate* wrapper_private = static_cast<WrapperPrivate*>(external->Value());
+  UnionTypesInterface* impl = static_cast<UnionTypesInterface*>(wrapper_private->wrappable<UnionTypesInterface>());
+
+  v8::Local<v8::Value> result_value;
+}
+
+
+void v8cSet_nullableUnionProperty(
+  v8::Local<v8::String> property,
+  v8::Local<v8::Value> v8_value,
+  const v8::PropertyCallbackInfo<void>& info)
+{
+  v8::Local<v8::External> external = v8::Local<v8::External>::Cast(info.Holder()->GetInternalField(0));
+  WrapperPrivate* wrapper_private = static_cast<WrapperPrivate*>(external->Value());
+  UnionTypesInterface* impl = static_cast<UnionTypesInterface*>(wrapper_private->wrappable<UnionTypesInterface>());
+
+  TypeTraits<base::optional<::cobalt::script::UnionType2<double, std::string > >>::ConversionType conversion_value;
+  V8cExceptionState exception_state{};
+  FromJSValue(info.GetIsolate(), v8_value, (kConversionFlagNullable), &exception_state, &conversion_value);
+  impl->set_nullable_union_property(
+    conversion_value
+  );
+}
+
+
+
+void v8cGet_unionBaseProperty(
+  v8::Local<v8::String> property,
+  const v8::PropertyCallbackInfo<v8::Value>& info)
+{
+  NOTIMPLEMENTED();
+
+  v8::Local<v8::External> external = v8::Local<v8::External>::Cast(info.Holder()->GetInternalField(0));
+  WrapperPrivate* wrapper_private = static_cast<WrapperPrivate*>(external->Value());
+  UnionTypesInterface* impl = static_cast<UnionTypesInterface*>(wrapper_private->wrappable<UnionTypesInterface>());
+
+  v8::Local<v8::Value> result_value;
+}
+
+
+void v8cSet_unionBaseProperty(
+  v8::Local<v8::String> property,
+  v8::Local<v8::Value> v8_value,
+  const v8::PropertyCallbackInfo<void>& info)
+{
+  v8::Local<v8::External> external = v8::Local<v8::External>::Cast(info.Holder()->GetInternalField(0));
+  WrapperPrivate* wrapper_private = static_cast<WrapperPrivate*>(external->Value());
+  UnionTypesInterface* impl = static_cast<UnionTypesInterface*>(wrapper_private->wrappable<UnionTypesInterface>());
+
+  TypeTraits<::cobalt::script::UnionType2<scoped_refptr<BaseInterface>, std::string >>::ConversionType conversion_value;
+  V8cExceptionState exception_state{};
+  FromJSValue(info.GetIsolate(), v8_value, kNoConversionFlags, &exception_state, &conversion_value);
+  impl->set_union_base_property(
+    conversion_value
+  );
+}
+
+
+
+void DummyFunction(const v8::FunctionCallbackInfo<v8::Value>& info) {
+  LOG(INFO) << __func__;
+}
+
+void InitializeTemplate(
+  V8cGlobalEnvironment* env,
+  InterfaceData* interface_data) {
+  v8::Isolate* isolate = env->isolate();
+  v8::Local<v8::FunctionTemplate> function_template = v8::FunctionTemplate::New(
+    isolate);
+  function_template->SetClassName(
+    v8::String::NewFromUtf8(isolate, "UnionTypesInterface",
+        v8::NewStringType::kInternalized).ToLocalChecked());
+  v8::Local<v8::ObjectTemplate> instance_template = function_template->InstanceTemplate();
+  instance_template->SetInternalFieldCount(1);
+
+  v8::Local<v8::ObjectTemplate> prototype_template = function_template->PrototypeTemplate();
+  prototype_template->SetInternalFieldCount(1);
+
+  instance_template->SetAccessor(
+    v8::String::NewFromUtf8(isolate, "unionProperty",
+                              v8::NewStringType::kInternalized)
+          .ToLocalChecked(),
+    v8cGet_unionProperty
+    ,v8cSet_unionProperty
+  );
+  instance_template->SetAccessor(
+    v8::String::NewFromUtf8(isolate, "unionWithNullableMemberProperty",
+                              v8::NewStringType::kInternalized)
+          .ToLocalChecked(),
+    v8cGet_unionWithNullableMemberProperty
+    ,v8cSet_unionWithNullableMemberProperty
+  );
+  instance_template->SetAccessor(
+    v8::String::NewFromUtf8(isolate, "nullableUnionProperty",
+                              v8::NewStringType::kInternalized)
+          .ToLocalChecked(),
+    v8cGet_nullableUnionProperty
+    ,v8cSet_nullableUnionProperty
+  );
+  instance_template->SetAccessor(
+    v8::String::NewFromUtf8(isolate, "unionBaseProperty",
+                              v8::NewStringType::kInternalized)
+          .ToLocalChecked(),
+    v8cGet_unionBaseProperty
+    ,v8cSet_unionBaseProperty
+  );
+
+
+  interface_data->templ.Set(env->isolate(), function_template);
+}
+
+inline InterfaceData* GetInterfaceData(V8cGlobalEnvironment* env) {
+  const int kInterfaceUniqueId = 50;
+  // By convention, the |V8cGlobalEnvironment| that we are associated with
+  // will hold our |InterfaceData| at index |kInterfaceUniqueId|, as we asked
+  // for it to be there in the first place, and could not have conflicted with
+  // any other interface.
+  return env->GetInterfaceData(kInterfaceUniqueId);
+}
+
+}  // namespace
+
+v8::Local<v8::Object> V8cUnionTypesInterface::CreateWrapper(V8cGlobalEnvironment* env, const scoped_refptr<Wrappable>& wrappable) {
+  v8::Isolate* isolate = env->isolate();
+  v8::Isolate::Scope isolate_scope(isolate);
+  v8::EscapableHandleScope handle_scope(isolate);
+  v8::Local<v8::Context> context = env->context();
+  v8::Context::Scope scope(context);
+
+  InterfaceData* interface_data = GetInterfaceData(env);
+  if (interface_data->templ.IsEmpty()) {
+    InitializeTemplate(env, interface_data);
+  }
+  DCHECK(!interface_data->templ.IsEmpty());
+
+  v8::Local<v8::FunctionTemplate> function_template = interface_data->templ.Get(isolate);
+  DCHECK(function_template->InstanceTemplate()->InternalFieldCount() == 1);
+  v8::Local<v8::Object> object = function_template->InstanceTemplate()->NewInstance(context).ToLocalChecked();
+  DCHECK(object->InternalFieldCount() == 1);
+
+  // |WrapperPrivate|'s lifetime will be managed by V8.
+  new WrapperPrivate(isolate, wrappable, object);
+  return handle_scope.Escape(object);
+}
+
+v8::Local<v8::FunctionTemplate> V8cUnionTypesInterface::CreateTemplate(V8cGlobalEnvironment* env) {
+  InterfaceData* interface_data = GetInterfaceData(env);
+  if (interface_data->templ.IsEmpty()) {
+    InitializeTemplate(env, interface_data);
+  }
+
+  return interface_data->templ.Get(env->isolate());
+}
+
+
+}  // namespace testing
+}  // namespace bindings
+}  // namespace cobalt
+
+
diff --git a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_union_types_interface.h b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_union_types_interface.h
new file mode 100644
index 0000000..3a5cc19
--- /dev/null
+++ b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_union_types_interface.h
@@ -0,0 +1,50 @@
+
+// Copyright 2017 Google Inc. All Rights Reserved.
+//
+// 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.
+
+// clang-format off
+
+// This file has been auto-generated by bindings/code_generator_cobalt.py. DO NOT MODIFY!
+// Auto-generated from template: bindings/v8c/templates/interface.h.template
+
+#ifndef V8cUnionTypesInterface_h
+#define V8cUnionTypesInterface_h
+
+#include "base/hash_tables.h"
+#include "base/lazy_instance.h"
+#include "base/memory/ref_counted.h"
+#include "base/threading/thread_checker.h"
+#include "cobalt/base/polymorphic_downcast.h"
+#include "cobalt/script/wrappable.h"
+#include "cobalt/bindings/testing/union_types_interface.h"
+
+#include "cobalt/script/v8c/v8c_global_environment.h"
+#include "v8/include/v8.h"
+
+namespace cobalt {
+namespace bindings {
+namespace testing {
+
+class V8cUnionTypesInterface {
+ public:
+  static v8::Local<v8::Object> CreateWrapper(script::v8c::V8cGlobalEnvironment* env, const scoped_refptr<script::Wrappable>& wrappable);
+  static v8::Local<v8::FunctionTemplate> CreateTemplate(script::v8c::V8cGlobalEnvironment* env);
+  // TODO: Add |GetInterfaceObject|.
+};
+
+}  // namespace testing
+}  // namespace bindings
+}  // namespace cobalt
+
+#endif  // V8cUnionTypesInterface_h
diff --git a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_window.cc b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_window.cc
new file mode 100644
index 0000000..5556f41
--- /dev/null
+++ b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_window.cc
@@ -0,0 +1,972 @@
+
+
+// Copyright 2017 Google Inc. All Rights Reserved.
+//
+// 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.
+
+// clang-format off
+
+// This file has been auto-generated by bindings/code_generator_cobalt.py. DO NOT MODIFY!
+// Auto-generated from template: bindings/v8c/templates/interface.cc.template
+
+#include "cobalt/bindings/testing/v8c_window.h"
+
+#include "base/debug/trace_event.h"
+#include "cobalt/base/polymorphic_downcast.h"
+#include "cobalt/script/global_environment.h"
+#include "cobalt/script/script_value.h"
+#include "cobalt/script/value_handle.h"
+#include "cobalt/bindings/testing/anonymous_indexed_getter_interface.h"
+#include "cobalt/bindings/testing/anonymous_named_getter_interface.h"
+#include "cobalt/bindings/testing/anonymous_named_indexed_getter_interface.h"
+#include "cobalt/bindings/testing/arbitrary_interface.h"
+#include "cobalt/bindings/testing/base_interface.h"
+#include "cobalt/bindings/testing/boolean_type_test_interface.h"
+#include "cobalt/bindings/testing/callback_function_interface.h"
+#include "cobalt/bindings/testing/callback_interface_interface.h"
+#include "cobalt/bindings/testing/conditional_interface.h"
+#include "cobalt/bindings/testing/constants_interface.h"
+#include "cobalt/bindings/testing/constructor_interface.h"
+#include "cobalt/bindings/testing/constructor_with_arguments_interface.h"
+#include "cobalt/bindings/testing/derived_getter_setter_interface.h"
+#include "cobalt/bindings/testing/derived_interface.h"
+#include "cobalt/bindings/testing/dictionary_interface.h"
+#include "cobalt/bindings/testing/disabled_interface.h"
+#include "cobalt/bindings/testing/dom_string_test_interface.h"
+#include "cobalt/bindings/testing/enumeration_interface.h"
+#include "cobalt/bindings/testing/exception_object_interface.h"
+#include "cobalt/bindings/testing/exceptions_interface.h"
+#include "cobalt/bindings/testing/extended_idl_attributes_interface.h"
+#include "cobalt/bindings/testing/garbage_collection_test_interface.h"
+#include "cobalt/bindings/testing/global_interface_parent.h"
+#include "cobalt/bindings/testing/implemented_interface.h"
+#include "cobalt/bindings/testing/indexed_getter_interface.h"
+#include "cobalt/bindings/testing/interface_with_any.h"
+#include "cobalt/bindings/testing/interface_with_any_dictionary.h"
+#include "cobalt/bindings/testing/interface_with_unsupported_properties.h"
+#include "cobalt/bindings/testing/named_constructor_interface.h"
+#include "cobalt/bindings/testing/named_getter_interface.h"
+#include "cobalt/bindings/testing/named_indexed_getter_interface.h"
+#include "cobalt/bindings/testing/nested_put_forwards_interface.h"
+#include "cobalt/bindings/testing/no_constructor_interface.h"
+#include "cobalt/bindings/testing/no_interface_object_interface.h"
+#include "cobalt/bindings/testing/nullable_types_test_interface.h"
+#include "cobalt/bindings/testing/numeric_types_test_interface.h"
+#include "cobalt/bindings/testing/object_type_bindings_interface.h"
+#include "cobalt/bindings/testing/operations_test_interface.h"
+#include "cobalt/bindings/testing/promise_interface.h"
+#include "cobalt/bindings/testing/put_forwards_interface.h"
+#include "cobalt/bindings/testing/sequence_user.h"
+#include "cobalt/bindings/testing/single_operation_interface.h"
+#include "cobalt/bindings/testing/static_properties_interface.h"
+#include "cobalt/bindings/testing/stringifier_anonymous_operation_interface.h"
+#include "cobalt/bindings/testing/stringifier_attribute_interface.h"
+#include "cobalt/bindings/testing/stringifier_operation_interface.h"
+#include "cobalt/bindings/testing/target_interface.h"
+#include "cobalt/bindings/testing/union_types_interface.h"
+#include "cobalt/bindings/testing/v8c_anonymous_indexed_getter_interface.h"
+#include "cobalt/bindings/testing/v8c_anonymous_named_getter_interface.h"
+#include "cobalt/bindings/testing/v8c_anonymous_named_indexed_getter_interface.h"
+#include "cobalt/bindings/testing/v8c_arbitrary_interface.h"
+#include "cobalt/bindings/testing/v8c_base_interface.h"
+#include "cobalt/bindings/testing/v8c_boolean_type_test_interface.h"
+#include "cobalt/bindings/testing/v8c_callback_function_interface.h"
+#include "cobalt/bindings/testing/v8c_callback_interface_interface.h"
+#include "cobalt/bindings/testing/v8c_conditional_interface.h"
+#include "cobalt/bindings/testing/v8c_constants_interface.h"
+#include "cobalt/bindings/testing/v8c_constructor_interface.h"
+#include "cobalt/bindings/testing/v8c_constructor_with_arguments_interface.h"
+#include "cobalt/bindings/testing/v8c_derived_getter_setter_interface.h"
+#include "cobalt/bindings/testing/v8c_derived_interface.h"
+#include "cobalt/bindings/testing/v8c_dictionary_interface.h"
+#include "cobalt/bindings/testing/v8c_disabled_interface.h"
+#include "cobalt/bindings/testing/v8c_dom_string_test_interface.h"
+#include "cobalt/bindings/testing/v8c_enumeration_interface.h"
+#include "cobalt/bindings/testing/v8c_exception_object_interface.h"
+#include "cobalt/bindings/testing/v8c_exceptions_interface.h"
+#include "cobalt/bindings/testing/v8c_extended_idl_attributes_interface.h"
+#include "cobalt/bindings/testing/v8c_garbage_collection_test_interface.h"
+#include "cobalt/bindings/testing/v8c_global_interface_parent.h"
+#include "cobalt/bindings/testing/v8c_implemented_interface.h"
+#include "cobalt/bindings/testing/v8c_indexed_getter_interface.h"
+#include "cobalt/bindings/testing/v8c_interface_with_any.h"
+#include "cobalt/bindings/testing/v8c_interface_with_any_dictionary.h"
+#include "cobalt/bindings/testing/v8c_interface_with_unsupported_properties.h"
+#include "cobalt/bindings/testing/v8c_named_constructor_interface.h"
+#include "cobalt/bindings/testing/v8c_named_getter_interface.h"
+#include "cobalt/bindings/testing/v8c_named_indexed_getter_interface.h"
+#include "cobalt/bindings/testing/v8c_nested_put_forwards_interface.h"
+#include "cobalt/bindings/testing/v8c_no_constructor_interface.h"
+#include "cobalt/bindings/testing/v8c_no_interface_object_interface.h"
+#include "cobalt/bindings/testing/v8c_nullable_types_test_interface.h"
+#include "cobalt/bindings/testing/v8c_numeric_types_test_interface.h"
+#include "cobalt/bindings/testing/v8c_object_type_bindings_interface.h"
+#include "cobalt/bindings/testing/v8c_operations_test_interface.h"
+#include "cobalt/bindings/testing/v8c_promise_interface.h"
+#include "cobalt/bindings/testing/v8c_put_forwards_interface.h"
+#include "cobalt/bindings/testing/v8c_sequence_user.h"
+#include "cobalt/bindings/testing/v8c_single_operation_interface.h"
+#include "cobalt/bindings/testing/v8c_static_properties_interface.h"
+#include "cobalt/bindings/testing/v8c_stringifier_anonymous_operation_interface.h"
+#include "cobalt/bindings/testing/v8c_stringifier_attribute_interface.h"
+#include "cobalt/bindings/testing/v8c_stringifier_operation_interface.h"
+#include "cobalt/bindings/testing/v8c_target_interface.h"
+#include "cobalt/bindings/testing/v8c_union_types_interface.h"
+#include "cobalt/bindings/testing/v8c_window.h"
+#include "cobalt/bindings/testing/window.h"
+
+#include "v8c_gen_type_conversion.h"
+
+#include "cobalt/script/callback_interface_traits.h"
+#include "cobalt/script/v8c/callback_function_conversion.h"
+#include "cobalt/script/v8c/conversion_helpers.h"
+#include "cobalt/script/v8c/native_promise.h"
+#include "cobalt/script/v8c/type_traits.h"
+#include "cobalt/script/v8c/v8c_callback_function.h"
+#include "cobalt/script/v8c/v8c_callback_interface_holder.h"
+#include "cobalt/script/v8c/v8c_exception_state.h"
+#include "cobalt/script/v8c/v8c_global_environment.h"
+#include "cobalt/script/v8c/v8c_value_handle.h"
+#include "cobalt/script/v8c/wrapper_private.h"
+#include "v8/include/v8.h"
+
+
+namespace {
+using cobalt::bindings::testing::Window;
+using cobalt::bindings::testing::V8cWindow;
+using cobalt::bindings::testing::AnonymousIndexedGetterInterface;
+using cobalt::bindings::testing::AnonymousNamedGetterInterface;
+using cobalt::bindings::testing::AnonymousNamedIndexedGetterInterface;
+using cobalt::bindings::testing::ArbitraryInterface;
+using cobalt::bindings::testing::BaseInterface;
+using cobalt::bindings::testing::BooleanTypeTestInterface;
+using cobalt::bindings::testing::CallbackFunctionInterface;
+using cobalt::bindings::testing::CallbackInterfaceInterface;
+#if defined(ENABLE_CONDITIONAL_INTERFACE)
+using cobalt::bindings::testing::ConditionalInterface;
+#endif  // defined(ENABLE_CONDITIONAL_INTERFACE)
+using cobalt::bindings::testing::ConstantsInterface;
+using cobalt::bindings::testing::ConstructorInterface;
+using cobalt::bindings::testing::ConstructorWithArgumentsInterface;
+using cobalt::bindings::testing::DOMStringTestInterface;
+using cobalt::bindings::testing::DerivedGetterSetterInterface;
+using cobalt::bindings::testing::DerivedInterface;
+using cobalt::bindings::testing::DictionaryInterface;
+#if defined(NO_ENABLE_CONDITIONAL_INTERFACE)
+using cobalt::bindings::testing::DisabledInterface;
+#endif  // defined(NO_ENABLE_CONDITIONAL_INTERFACE)
+using cobalt::bindings::testing::EnumerationInterface;
+using cobalt::bindings::testing::ExceptionObjectInterface;
+using cobalt::bindings::testing::ExceptionsInterface;
+using cobalt::bindings::testing::ExtendedIDLAttributesInterface;
+using cobalt::bindings::testing::GarbageCollectionTestInterface;
+using cobalt::bindings::testing::GlobalInterfaceParent;
+using cobalt::bindings::testing::ImplementedInterface;
+using cobalt::bindings::testing::IndexedGetterInterface;
+using cobalt::bindings::testing::InterfaceWithAny;
+using cobalt::bindings::testing::InterfaceWithAnyDictionary;
+using cobalt::bindings::testing::InterfaceWithUnsupportedProperties;
+using cobalt::bindings::testing::NamedConstructorInterface;
+using cobalt::bindings::testing::NamedGetterInterface;
+using cobalt::bindings::testing::NamedIndexedGetterInterface;
+using cobalt::bindings::testing::NestedPutForwardsInterface;
+using cobalt::bindings::testing::NoConstructorInterface;
+using cobalt::bindings::testing::NoInterfaceObjectInterface;
+using cobalt::bindings::testing::NullableTypesTestInterface;
+using cobalt::bindings::testing::NumericTypesTestInterface;
+using cobalt::bindings::testing::ObjectTypeBindingsInterface;
+using cobalt::bindings::testing::OperationsTestInterface;
+using cobalt::bindings::testing::PromiseInterface;
+using cobalt::bindings::testing::PutForwardsInterface;
+using cobalt::bindings::testing::SequenceUser;
+using cobalt::bindings::testing::SingleOperationInterface;
+using cobalt::bindings::testing::StaticPropertiesInterface;
+using cobalt::bindings::testing::StringifierAnonymousOperationInterface;
+using cobalt::bindings::testing::StringifierAttributeInterface;
+using cobalt::bindings::testing::StringifierOperationInterface;
+using cobalt::bindings::testing::TargetInterface;
+using cobalt::bindings::testing::UnionTypesInterface;
+using cobalt::bindings::testing::V8cAnonymousIndexedGetterInterface;
+using cobalt::bindings::testing::V8cAnonymousNamedGetterInterface;
+using cobalt::bindings::testing::V8cAnonymousNamedIndexedGetterInterface;
+using cobalt::bindings::testing::V8cArbitraryInterface;
+using cobalt::bindings::testing::V8cBaseInterface;
+using cobalt::bindings::testing::V8cBooleanTypeTestInterface;
+using cobalt::bindings::testing::V8cCallbackFunctionInterface;
+using cobalt::bindings::testing::V8cCallbackInterfaceInterface;
+#if defined(ENABLE_CONDITIONAL_INTERFACE)
+using cobalt::bindings::testing::V8cConditionalInterface;
+#endif  // defined(ENABLE_CONDITIONAL_INTERFACE)
+using cobalt::bindings::testing::V8cConstantsInterface;
+using cobalt::bindings::testing::V8cConstructorInterface;
+using cobalt::bindings::testing::V8cConstructorWithArgumentsInterface;
+using cobalt::bindings::testing::V8cDOMStringTestInterface;
+using cobalt::bindings::testing::V8cDerivedGetterSetterInterface;
+using cobalt::bindings::testing::V8cDerivedInterface;
+using cobalt::bindings::testing::V8cDictionaryInterface;
+#if defined(NO_ENABLE_CONDITIONAL_INTERFACE)
+using cobalt::bindings::testing::V8cDisabledInterface;
+#endif  // defined(NO_ENABLE_CONDITIONAL_INTERFACE)
+using cobalt::bindings::testing::V8cEnumerationInterface;
+using cobalt::bindings::testing::V8cExceptionObjectInterface;
+using cobalt::bindings::testing::V8cExceptionsInterface;
+using cobalt::bindings::testing::V8cExtendedIDLAttributesInterface;
+using cobalt::bindings::testing::V8cGarbageCollectionTestInterface;
+using cobalt::bindings::testing::V8cGlobalInterfaceParent;
+using cobalt::bindings::testing::V8cImplementedInterface;
+using cobalt::bindings::testing::V8cIndexedGetterInterface;
+using cobalt::bindings::testing::V8cInterfaceWithAny;
+using cobalt::bindings::testing::V8cInterfaceWithAnyDictionary;
+using cobalt::bindings::testing::V8cInterfaceWithUnsupportedProperties;
+using cobalt::bindings::testing::V8cNamedConstructorInterface;
+using cobalt::bindings::testing::V8cNamedGetterInterface;
+using cobalt::bindings::testing::V8cNamedIndexedGetterInterface;
+using cobalt::bindings::testing::V8cNestedPutForwardsInterface;
+using cobalt::bindings::testing::V8cNoConstructorInterface;
+using cobalt::bindings::testing::V8cNoInterfaceObjectInterface;
+using cobalt::bindings::testing::V8cNullableTypesTestInterface;
+using cobalt::bindings::testing::V8cNumericTypesTestInterface;
+using cobalt::bindings::testing::V8cObjectTypeBindingsInterface;
+using cobalt::bindings::testing::V8cOperationsTestInterface;
+using cobalt::bindings::testing::V8cPromiseInterface;
+using cobalt::bindings::testing::V8cPutForwardsInterface;
+using cobalt::bindings::testing::V8cSequenceUser;
+using cobalt::bindings::testing::V8cSingleOperationInterface;
+using cobalt::bindings::testing::V8cStaticPropertiesInterface;
+using cobalt::bindings::testing::V8cStringifierAnonymousOperationInterface;
+using cobalt::bindings::testing::V8cStringifierAttributeInterface;
+using cobalt::bindings::testing::V8cStringifierOperationInterface;
+using cobalt::bindings::testing::V8cTargetInterface;
+using cobalt::bindings::testing::V8cUnionTypesInterface;
+using cobalt::bindings::testing::V8cWindow;
+using cobalt::bindings::testing::Window;
+using cobalt::script::CallbackInterfaceTraits;
+using cobalt::script::GlobalEnvironment;
+using cobalt::script::ScriptValue;
+using cobalt::script::ValueHandle;
+using cobalt::script::ValueHandle;
+using cobalt::script::ValueHandleHolder;
+using cobalt::script::Wrappable;
+
+using cobalt::script::v8c::FromJSValue;
+using cobalt::script::v8c::InterfaceData;
+using cobalt::script::v8c::kConversionFlagClamped;
+using cobalt::script::v8c::kConversionFlagNullable;
+using cobalt::script::v8c::kConversionFlagRestricted;
+using cobalt::script::v8c::kConversionFlagTreatNullAsEmptyString;
+using cobalt::script::v8c::kConversionFlagTreatUndefinedAsEmptyString;
+using cobalt::script::v8c::kNoConversionFlags;
+using cobalt::script::v8c::TypeTraits;
+using cobalt::script::v8c::V8cExceptionState;
+using cobalt::script::v8c::V8cGlobalEnvironment;
+using cobalt::script::v8c::WrapperFactory;
+using cobalt::script::v8c::WrapperPrivate;
+
+v8::Local<v8::Object> DummyFunctor(V8cGlobalEnvironment*, const scoped_refptr<Wrappable>&) {
+  NOTIMPLEMENTED();
+  return {};
+}
+
+}  // namespace
+
+namespace cobalt {
+namespace bindings {
+namespace testing {
+
+
+namespace {
+
+void WindowConstructor(const v8::FunctionCallbackInfo<v8::Value>& args) {
+  NOTIMPLEMENTED();
+  if (!args.IsConstructCall()) {
+    // TODO: Probably throw something here...
+    return;
+  }
+
+  DCHECK(args.This()->InternalFieldCount() == 1);
+  args.This()->SetInternalField(0, v8::External::New(args.GetIsolate(), nullptr));
+  args.GetReturnValue().Set(args.This());
+}
+
+
+void v8cGet_windowProperty(
+  v8::Local<v8::String> property,
+  const v8::PropertyCallbackInfo<v8::Value>& info)
+{
+  NOTIMPLEMENTED();
+
+  v8::Local<v8::External> external = v8::Local<v8::External>::Cast(info.Holder()->GetInternalField(0));
+  WrapperPrivate* wrapper_private = static_cast<WrapperPrivate*>(external->Value());
+  Window* impl = static_cast<Window*>(wrapper_private->wrappable<Window>());
+
+  v8::Local<v8::Value> result_value;
+}
+
+
+void v8cSet_windowProperty(
+  v8::Local<v8::String> property,
+  v8::Local<v8::Value> v8_value,
+  const v8::PropertyCallbackInfo<void>& info)
+{
+  v8::Local<v8::External> external = v8::Local<v8::External>::Cast(info.Holder()->GetInternalField(0));
+  WrapperPrivate* wrapper_private = static_cast<WrapperPrivate*>(external->Value());
+  Window* impl = static_cast<Window*>(wrapper_private->wrappable<Window>());
+
+  TypeTraits<std::string>::ConversionType conversion_value;
+  V8cExceptionState exception_state{};
+  FromJSValue(info.GetIsolate(), v8_value, kNoConversionFlags, &exception_state, &conversion_value);
+  impl->set_window_property(
+    conversion_value
+  );
+}
+
+
+
+void v8cGet_window(
+  v8::Local<v8::String> property,
+  const v8::PropertyCallbackInfo<v8::Value>& info)
+{
+  NOTIMPLEMENTED();
+
+  v8::Local<v8::External> external = v8::Local<v8::External>::Cast(info.Holder()->GetInternalField(0));
+  WrapperPrivate* wrapper_private = static_cast<WrapperPrivate*>(external->Value());
+  Window* impl = static_cast<Window*>(wrapper_private->wrappable<Window>());
+
+  v8::Local<v8::Value> result_value;
+}
+
+
+
+void v8cGet_onEvent(
+  v8::Local<v8::String> property,
+  const v8::PropertyCallbackInfo<v8::Value>& info)
+{
+  NOTIMPLEMENTED();
+
+  v8::Local<v8::External> external = v8::Local<v8::External>::Cast(info.Holder()->GetInternalField(0));
+  WrapperPrivate* wrapper_private = static_cast<WrapperPrivate*>(external->Value());
+  Window* impl = static_cast<Window*>(wrapper_private->wrappable<Window>());
+
+  v8::Local<v8::Value> result_value;
+}
+
+
+void v8cSet_onEvent(
+  v8::Local<v8::String> property,
+  v8::Local<v8::Value> v8_value,
+  const v8::PropertyCallbackInfo<void>& info)
+{
+  v8::Local<v8::External> external = v8::Local<v8::External>::Cast(info.Holder()->GetInternalField(0));
+  WrapperPrivate* wrapper_private = static_cast<WrapperPrivate*>(external->Value());
+  Window* impl = static_cast<Window*>(wrapper_private->wrappable<Window>());
+
+  TypeTraits<::cobalt::script::CallbackInterfaceTraits<SingleOperationInterface >>::ConversionType conversion_value;
+  V8cExceptionState exception_state{};
+  FromJSValue(info.GetIsolate(), v8_value, (kConversionFlagNullable), &exception_state, &conversion_value);
+  impl->set_on_event(
+    conversion_value
+  );
+}
+
+
+
+void DummyFunction(const v8::FunctionCallbackInfo<v8::Value>& info) {
+  LOG(INFO) << __func__;
+}
+
+void InitializeTemplate(
+  V8cGlobalEnvironment* env,
+  InterfaceData* interface_data) {
+  v8::Isolate* isolate = env->isolate();
+  v8::Local<v8::FunctionTemplate> function_template = v8::FunctionTemplate::New(
+    isolate);
+  function_template->SetClassName(
+    v8::String::NewFromUtf8(isolate, "Window",
+        v8::NewStringType::kInternalized).ToLocalChecked());
+  v8::Local<v8::ObjectTemplate> instance_template = function_template->InstanceTemplate();
+  instance_template->SetInternalFieldCount(1);
+
+  v8::Local<v8::ObjectTemplate> prototype_template = function_template->PrototypeTemplate();
+  prototype_template->SetInternalFieldCount(1);
+
+  instance_template->SetAccessor(
+    v8::String::NewFromUtf8(isolate, "windowProperty",
+                              v8::NewStringType::kInternalized)
+          .ToLocalChecked(),
+    v8cGet_windowProperty
+    ,v8cSet_windowProperty
+  );
+  instance_template->SetAccessor(
+    v8::String::NewFromUtf8(isolate, "window",
+                              v8::NewStringType::kInternalized)
+          .ToLocalChecked(),
+    v8cGet_window
+  );
+  instance_template->SetAccessor(
+    v8::String::NewFromUtf8(isolate, "onEvent",
+                              v8::NewStringType::kInternalized)
+          .ToLocalChecked(),
+    v8cGet_onEvent
+    ,v8cSet_onEvent
+  );
+
+  instance_template->Set(
+      v8::String::NewFromUtf8(
+          isolate,
+          "getStackTrace",
+          v8::NewStringType::kInternalized).ToLocalChecked(),
+      v8::FunctionTemplate::New(isolate, DummyFunction)
+  );
+  instance_template->Set(
+      v8::String::NewFromUtf8(
+          isolate,
+          "setTimeout",
+          v8::NewStringType::kInternalized).ToLocalChecked(),
+      v8::FunctionTemplate::New(isolate, DummyFunction)
+  );
+  instance_template->Set(
+      v8::String::NewFromUtf8(
+          isolate,
+          "windowOperation",
+          v8::NewStringType::kInternalized).ToLocalChecked(),
+      v8::FunctionTemplate::New(isolate, DummyFunction)
+  );
+
+  interface_data->templ.Set(env->isolate(), function_template);
+}
+
+inline InterfaceData* GetInterfaceData(V8cGlobalEnvironment* env) {
+  const int kInterfaceUniqueId = 52;
+  // By convention, the |V8cGlobalEnvironment| that we are associated with
+  // will hold our |InterfaceData| at index |kInterfaceUniqueId|, as we asked
+  // for it to be there in the first place, and could not have conflicted with
+  // any other interface.
+  return env->GetInterfaceData(kInterfaceUniqueId);
+}
+
+}  // namespace
+
+v8::Local<v8::Object> V8cWindow::CreateWrapper(V8cGlobalEnvironment* env, const scoped_refptr<Wrappable>& wrappable) {
+  v8::Isolate* isolate = env->isolate();
+  v8::Isolate::Scope isolate_scope(isolate);
+  v8::EscapableHandleScope handle_scope(isolate);
+  v8::Local<v8::Context> context = env->context();
+  v8::Context::Scope scope(context);
+
+  InterfaceData* interface_data = GetInterfaceData(env);
+  if (interface_data->templ.IsEmpty()) {
+    InitializeTemplate(env, interface_data);
+  }
+  DCHECK(!interface_data->templ.IsEmpty());
+
+  v8::Local<v8::FunctionTemplate> function_template = interface_data->templ.Get(isolate);
+  DCHECK(function_template->InstanceTemplate()->InternalFieldCount() == 1);
+  v8::Local<v8::Object> object = function_template->InstanceTemplate()->NewInstance(context).ToLocalChecked();
+  DCHECK(object->InternalFieldCount() == 1);
+
+  // |WrapperPrivate|'s lifetime will be managed by V8.
+  new WrapperPrivate(isolate, wrappable, object);
+  return handle_scope.Escape(object);
+}
+
+v8::Local<v8::FunctionTemplate> V8cWindow::CreateTemplate(V8cGlobalEnvironment* env) {
+  InterfaceData* interface_data = GetInterfaceData(env);
+  if (interface_data->templ.IsEmpty()) {
+    InitializeTemplate(env, interface_data);
+  }
+
+  return interface_data->templ.Get(env->isolate());
+}
+
+
+}  // namespace testing
+}  // namespace bindings
+}  // namespace cobalt
+
+
+namespace cobalt {
+namespace script {
+namespace v8c {
+
+template <typename GlobalInterface>
+void V8cGlobalEnvironment::CreateGlobalObject(
+    const scoped_refptr<GlobalInterface>& global_interface,
+    EnvironmentSettings* environment_settings) {
+  v8::Isolate::Scope isolate_scope(isolate_);
+  v8::HandleScope handle_scope(isolate_);
+
+  v8::Local<v8::ObjectTemplate> global_object_template = v8::ObjectTemplate::New(isolate_);
+  global_object_template->Set(
+      v8::String::NewFromUtf8(
+          isolate_, "AnonymousIndexedGetterInterface",
+          v8::NewStringType::kInternalized).ToLocalChecked(),
+      V8cAnonymousIndexedGetterInterface::CreateTemplate(this));
+  global_object_template->Set(
+      v8::String::NewFromUtf8(
+          isolate_, "AnonymousNamedGetterInterface",
+          v8::NewStringType::kInternalized).ToLocalChecked(),
+      V8cAnonymousNamedGetterInterface::CreateTemplate(this));
+  global_object_template->Set(
+      v8::String::NewFromUtf8(
+          isolate_, "AnonymousNamedIndexedGetterInterface",
+          v8::NewStringType::kInternalized).ToLocalChecked(),
+      V8cAnonymousNamedIndexedGetterInterface::CreateTemplate(this));
+  global_object_template->Set(
+      v8::String::NewFromUtf8(
+          isolate_, "ArbitraryInterface",
+          v8::NewStringType::kInternalized).ToLocalChecked(),
+      V8cArbitraryInterface::CreateTemplate(this));
+  global_object_template->Set(
+      v8::String::NewFromUtf8(
+          isolate_, "BaseInterface",
+          v8::NewStringType::kInternalized).ToLocalChecked(),
+      V8cBaseInterface::CreateTemplate(this));
+  global_object_template->Set(
+      v8::String::NewFromUtf8(
+          isolate_, "BooleanTypeTestInterface",
+          v8::NewStringType::kInternalized).ToLocalChecked(),
+      V8cBooleanTypeTestInterface::CreateTemplate(this));
+  global_object_template->Set(
+      v8::String::NewFromUtf8(
+          isolate_, "CallbackFunctionInterface",
+          v8::NewStringType::kInternalized).ToLocalChecked(),
+      V8cCallbackFunctionInterface::CreateTemplate(this));
+  global_object_template->Set(
+      v8::String::NewFromUtf8(
+          isolate_, "CallbackInterfaceInterface",
+          v8::NewStringType::kInternalized).ToLocalChecked(),
+      V8cCallbackInterfaceInterface::CreateTemplate(this));
+#if defined(ENABLE_CONDITIONAL_INTERFACE)
+  global_object_template->Set(
+      v8::String::NewFromUtf8(
+          isolate_, "ConditionalInterface",
+          v8::NewStringType::kInternalized).ToLocalChecked(),
+      V8cConditionalInterface::CreateTemplate(this));
+#endif  // defined(ENABLE_CONDITIONAL_INTERFACE)
+  global_object_template->Set(
+      v8::String::NewFromUtf8(
+          isolate_, "ConstantsInterface",
+          v8::NewStringType::kInternalized).ToLocalChecked(),
+      V8cConstantsInterface::CreateTemplate(this));
+  global_object_template->Set(
+      v8::String::NewFromUtf8(
+          isolate_, "ConstructorInterface",
+          v8::NewStringType::kInternalized).ToLocalChecked(),
+      V8cConstructorInterface::CreateTemplate(this));
+  global_object_template->Set(
+      v8::String::NewFromUtf8(
+          isolate_, "ConstructorWithArgumentsInterface",
+          v8::NewStringType::kInternalized).ToLocalChecked(),
+      V8cConstructorWithArgumentsInterface::CreateTemplate(this));
+  global_object_template->Set(
+      v8::String::NewFromUtf8(
+          isolate_, "DOMStringTestInterface",
+          v8::NewStringType::kInternalized).ToLocalChecked(),
+      V8cDOMStringTestInterface::CreateTemplate(this));
+  global_object_template->Set(
+      v8::String::NewFromUtf8(
+          isolate_, "DerivedGetterSetterInterface",
+          v8::NewStringType::kInternalized).ToLocalChecked(),
+      V8cDerivedGetterSetterInterface::CreateTemplate(this));
+  global_object_template->Set(
+      v8::String::NewFromUtf8(
+          isolate_, "DerivedInterface",
+          v8::NewStringType::kInternalized).ToLocalChecked(),
+      V8cDerivedInterface::CreateTemplate(this));
+  global_object_template->Set(
+      v8::String::NewFromUtf8(
+          isolate_, "DictionaryInterface",
+          v8::NewStringType::kInternalized).ToLocalChecked(),
+      V8cDictionaryInterface::CreateTemplate(this));
+#if defined(NO_ENABLE_CONDITIONAL_INTERFACE)
+  global_object_template->Set(
+      v8::String::NewFromUtf8(
+          isolate_, "DisabledInterface",
+          v8::NewStringType::kInternalized).ToLocalChecked(),
+      V8cDisabledInterface::CreateTemplate(this));
+#endif  // defined(NO_ENABLE_CONDITIONAL_INTERFACE)
+  global_object_template->Set(
+      v8::String::NewFromUtf8(
+          isolate_, "EnumerationInterface",
+          v8::NewStringType::kInternalized).ToLocalChecked(),
+      V8cEnumerationInterface::CreateTemplate(this));
+  global_object_template->Set(
+      v8::String::NewFromUtf8(
+          isolate_, "ExceptionObjectInterface",
+          v8::NewStringType::kInternalized).ToLocalChecked(),
+      V8cExceptionObjectInterface::CreateTemplate(this));
+  global_object_template->Set(
+      v8::String::NewFromUtf8(
+          isolate_, "ExceptionsInterface",
+          v8::NewStringType::kInternalized).ToLocalChecked(),
+      V8cExceptionsInterface::CreateTemplate(this));
+  global_object_template->Set(
+      v8::String::NewFromUtf8(
+          isolate_, "ExtendedIDLAttributesInterface",
+          v8::NewStringType::kInternalized).ToLocalChecked(),
+      V8cExtendedIDLAttributesInterface::CreateTemplate(this));
+  global_object_template->Set(
+      v8::String::NewFromUtf8(
+          isolate_, "GarbageCollectionTestInterface",
+          v8::NewStringType::kInternalized).ToLocalChecked(),
+      V8cGarbageCollectionTestInterface::CreateTemplate(this));
+  global_object_template->Set(
+      v8::String::NewFromUtf8(
+          isolate_, "GlobalInterfaceParent",
+          v8::NewStringType::kInternalized).ToLocalChecked(),
+      V8cGlobalInterfaceParent::CreateTemplate(this));
+  global_object_template->Set(
+      v8::String::NewFromUtf8(
+          isolate_, "ImplementedInterface",
+          v8::NewStringType::kInternalized).ToLocalChecked(),
+      V8cImplementedInterface::CreateTemplate(this));
+  global_object_template->Set(
+      v8::String::NewFromUtf8(
+          isolate_, "IndexedGetterInterface",
+          v8::NewStringType::kInternalized).ToLocalChecked(),
+      V8cIndexedGetterInterface::CreateTemplate(this));
+  global_object_template->Set(
+      v8::String::NewFromUtf8(
+          isolate_, "InterfaceWithAny",
+          v8::NewStringType::kInternalized).ToLocalChecked(),
+      V8cInterfaceWithAny::CreateTemplate(this));
+  global_object_template->Set(
+      v8::String::NewFromUtf8(
+          isolate_, "InterfaceWithAnyDictionary",
+          v8::NewStringType::kInternalized).ToLocalChecked(),
+      V8cInterfaceWithAnyDictionary::CreateTemplate(this));
+  global_object_template->Set(
+      v8::String::NewFromUtf8(
+          isolate_, "InterfaceWithUnsupportedProperties",
+          v8::NewStringType::kInternalized).ToLocalChecked(),
+      V8cInterfaceWithUnsupportedProperties::CreateTemplate(this));
+  global_object_template->Set(
+      v8::String::NewFromUtf8(
+          isolate_, "NamedConstructorInterface",
+          v8::NewStringType::kInternalized).ToLocalChecked(),
+      V8cNamedConstructorInterface::CreateTemplate(this));
+  global_object_template->Set(
+      v8::String::NewFromUtf8(
+          isolate_, "NamedGetterInterface",
+          v8::NewStringType::kInternalized).ToLocalChecked(),
+      V8cNamedGetterInterface::CreateTemplate(this));
+  global_object_template->Set(
+      v8::String::NewFromUtf8(
+          isolate_, "NamedIndexedGetterInterface",
+          v8::NewStringType::kInternalized).ToLocalChecked(),
+      V8cNamedIndexedGetterInterface::CreateTemplate(this));
+  global_object_template->Set(
+      v8::String::NewFromUtf8(
+          isolate_, "NestedPutForwardsInterface",
+          v8::NewStringType::kInternalized).ToLocalChecked(),
+      V8cNestedPutForwardsInterface::CreateTemplate(this));
+  global_object_template->Set(
+      v8::String::NewFromUtf8(
+          isolate_, "NoConstructorInterface",
+          v8::NewStringType::kInternalized).ToLocalChecked(),
+      V8cNoConstructorInterface::CreateTemplate(this));
+  global_object_template->Set(
+      v8::String::NewFromUtf8(
+          isolate_, "NoInterfaceObjectInterface",
+          v8::NewStringType::kInternalized).ToLocalChecked(),
+      V8cNoInterfaceObjectInterface::CreateTemplate(this));
+  global_object_template->Set(
+      v8::String::NewFromUtf8(
+          isolate_, "NullableTypesTestInterface",
+          v8::NewStringType::kInternalized).ToLocalChecked(),
+      V8cNullableTypesTestInterface::CreateTemplate(this));
+  global_object_template->Set(
+      v8::String::NewFromUtf8(
+          isolate_, "NumericTypesTestInterface",
+          v8::NewStringType::kInternalized).ToLocalChecked(),
+      V8cNumericTypesTestInterface::CreateTemplate(this));
+  global_object_template->Set(
+      v8::String::NewFromUtf8(
+          isolate_, "ObjectTypeBindingsInterface",
+          v8::NewStringType::kInternalized).ToLocalChecked(),
+      V8cObjectTypeBindingsInterface::CreateTemplate(this));
+  global_object_template->Set(
+      v8::String::NewFromUtf8(
+          isolate_, "OperationsTestInterface",
+          v8::NewStringType::kInternalized).ToLocalChecked(),
+      V8cOperationsTestInterface::CreateTemplate(this));
+  global_object_template->Set(
+      v8::String::NewFromUtf8(
+          isolate_, "PromiseInterface",
+          v8::NewStringType::kInternalized).ToLocalChecked(),
+      V8cPromiseInterface::CreateTemplate(this));
+  global_object_template->Set(
+      v8::String::NewFromUtf8(
+          isolate_, "PutForwardsInterface",
+          v8::NewStringType::kInternalized).ToLocalChecked(),
+      V8cPutForwardsInterface::CreateTemplate(this));
+  global_object_template->Set(
+      v8::String::NewFromUtf8(
+          isolate_, "SequenceUser",
+          v8::NewStringType::kInternalized).ToLocalChecked(),
+      V8cSequenceUser::CreateTemplate(this));
+  global_object_template->Set(
+      v8::String::NewFromUtf8(
+          isolate_, "StaticPropertiesInterface",
+          v8::NewStringType::kInternalized).ToLocalChecked(),
+      V8cStaticPropertiesInterface::CreateTemplate(this));
+  global_object_template->Set(
+      v8::String::NewFromUtf8(
+          isolate_, "StringifierAnonymousOperationInterface",
+          v8::NewStringType::kInternalized).ToLocalChecked(),
+      V8cStringifierAnonymousOperationInterface::CreateTemplate(this));
+  global_object_template->Set(
+      v8::String::NewFromUtf8(
+          isolate_, "StringifierAttributeInterface",
+          v8::NewStringType::kInternalized).ToLocalChecked(),
+      V8cStringifierAttributeInterface::CreateTemplate(this));
+  global_object_template->Set(
+      v8::String::NewFromUtf8(
+          isolate_, "StringifierOperationInterface",
+          v8::NewStringType::kInternalized).ToLocalChecked(),
+      V8cStringifierOperationInterface::CreateTemplate(this));
+  global_object_template->Set(
+      v8::String::NewFromUtf8(
+          isolate_, "TargetInterface",
+          v8::NewStringType::kInternalized).ToLocalChecked(),
+      V8cTargetInterface::CreateTemplate(this));
+  global_object_template->Set(
+      v8::String::NewFromUtf8(
+          isolate_, "UnionTypesInterface",
+          v8::NewStringType::kInternalized).ToLocalChecked(),
+      V8cUnionTypesInterface::CreateTemplate(this));
+  global_object_template->Set(
+      v8::String::NewFromUtf8(
+          isolate_, "Window",
+          v8::NewStringType::kInternalized).ToLocalChecked(),
+      V8cWindow::CreateTemplate(this));
+
+  v8::Local<v8::Context> context =
+      v8::Context::New(isolate_, nullptr, global_object_template);
+  context_.Reset(isolate_, context);
+
+  environment_settings_ = environment_settings;
+  EvaluateAutomatics();
+
+  wrapper_factory_->RegisterWrappableType(
+      AnonymousIndexedGetterInterface::AnonymousIndexedGetterInterfaceWrappableType(),
+      base::Bind(V8cAnonymousIndexedGetterInterface::CreateWrapper),
+      base::Bind(V8cAnonymousIndexedGetterInterface::CreateTemplate));
+  wrapper_factory_->RegisterWrappableType(
+      AnonymousNamedGetterInterface::AnonymousNamedGetterInterfaceWrappableType(),
+      base::Bind(V8cAnonymousNamedGetterInterface::CreateWrapper),
+      base::Bind(V8cAnonymousNamedGetterInterface::CreateTemplate));
+  wrapper_factory_->RegisterWrappableType(
+      AnonymousNamedIndexedGetterInterface::AnonymousNamedIndexedGetterInterfaceWrappableType(),
+      base::Bind(V8cAnonymousNamedIndexedGetterInterface::CreateWrapper),
+      base::Bind(V8cAnonymousNamedIndexedGetterInterface::CreateTemplate));
+  wrapper_factory_->RegisterWrappableType(
+      ArbitraryInterface::ArbitraryInterfaceWrappableType(),
+      base::Bind(V8cArbitraryInterface::CreateWrapper),
+      base::Bind(V8cArbitraryInterface::CreateTemplate));
+  wrapper_factory_->RegisterWrappableType(
+      BaseInterface::BaseInterfaceWrappableType(),
+      base::Bind(V8cBaseInterface::CreateWrapper),
+      base::Bind(V8cBaseInterface::CreateTemplate));
+  wrapper_factory_->RegisterWrappableType(
+      BooleanTypeTestInterface::BooleanTypeTestInterfaceWrappableType(),
+      base::Bind(V8cBooleanTypeTestInterface::CreateWrapper),
+      base::Bind(V8cBooleanTypeTestInterface::CreateTemplate));
+  wrapper_factory_->RegisterWrappableType(
+      CallbackFunctionInterface::CallbackFunctionInterfaceWrappableType(),
+      base::Bind(V8cCallbackFunctionInterface::CreateWrapper),
+      base::Bind(V8cCallbackFunctionInterface::CreateTemplate));
+  wrapper_factory_->RegisterWrappableType(
+      CallbackInterfaceInterface::CallbackInterfaceInterfaceWrappableType(),
+      base::Bind(V8cCallbackInterfaceInterface::CreateWrapper),
+      base::Bind(V8cCallbackInterfaceInterface::CreateTemplate));
+#if defined(ENABLE_CONDITIONAL_INTERFACE)
+  wrapper_factory_->RegisterWrappableType(
+      ConditionalInterface::ConditionalInterfaceWrappableType(),
+      base::Bind(V8cConditionalInterface::CreateWrapper),
+      base::Bind(V8cConditionalInterface::CreateTemplate));
+#endif  // defined(ENABLE_CONDITIONAL_INTERFACE)
+  wrapper_factory_->RegisterWrappableType(
+      ConstantsInterface::ConstantsInterfaceWrappableType(),
+      base::Bind(V8cConstantsInterface::CreateWrapper),
+      base::Bind(V8cConstantsInterface::CreateTemplate));
+  wrapper_factory_->RegisterWrappableType(
+      ConstructorInterface::ConstructorInterfaceWrappableType(),
+      base::Bind(V8cConstructorInterface::CreateWrapper),
+      base::Bind(V8cConstructorInterface::CreateTemplate));
+  wrapper_factory_->RegisterWrappableType(
+      ConstructorWithArgumentsInterface::ConstructorWithArgumentsInterfaceWrappableType(),
+      base::Bind(V8cConstructorWithArgumentsInterface::CreateWrapper),
+      base::Bind(V8cConstructorWithArgumentsInterface::CreateTemplate));
+  wrapper_factory_->RegisterWrappableType(
+      DOMStringTestInterface::DOMStringTestInterfaceWrappableType(),
+      base::Bind(V8cDOMStringTestInterface::CreateWrapper),
+      base::Bind(V8cDOMStringTestInterface::CreateTemplate));
+  wrapper_factory_->RegisterWrappableType(
+      DerivedGetterSetterInterface::DerivedGetterSetterInterfaceWrappableType(),
+      base::Bind(V8cDerivedGetterSetterInterface::CreateWrapper),
+      base::Bind(V8cDerivedGetterSetterInterface::CreateTemplate));
+  wrapper_factory_->RegisterWrappableType(
+      DerivedInterface::DerivedInterfaceWrappableType(),
+      base::Bind(V8cDerivedInterface::CreateWrapper),
+      base::Bind(V8cDerivedInterface::CreateTemplate));
+  wrapper_factory_->RegisterWrappableType(
+      DictionaryInterface::DictionaryInterfaceWrappableType(),
+      base::Bind(V8cDictionaryInterface::CreateWrapper),
+      base::Bind(V8cDictionaryInterface::CreateTemplate));
+#if defined(NO_ENABLE_CONDITIONAL_INTERFACE)
+  wrapper_factory_->RegisterWrappableType(
+      DisabledInterface::DisabledInterfaceWrappableType(),
+      base::Bind(V8cDisabledInterface::CreateWrapper),
+      base::Bind(V8cDisabledInterface::CreateTemplate));
+#endif  // defined(NO_ENABLE_CONDITIONAL_INTERFACE)
+  wrapper_factory_->RegisterWrappableType(
+      EnumerationInterface::EnumerationInterfaceWrappableType(),
+      base::Bind(V8cEnumerationInterface::CreateWrapper),
+      base::Bind(V8cEnumerationInterface::CreateTemplate));
+  wrapper_factory_->RegisterWrappableType(
+      ExceptionObjectInterface::ExceptionObjectInterfaceWrappableType(),
+      base::Bind(V8cExceptionObjectInterface::CreateWrapper),
+      base::Bind(V8cExceptionObjectInterface::CreateTemplate));
+  wrapper_factory_->RegisterWrappableType(
+      ExceptionsInterface::ExceptionsInterfaceWrappableType(),
+      base::Bind(V8cExceptionsInterface::CreateWrapper),
+      base::Bind(V8cExceptionsInterface::CreateTemplate));
+  wrapper_factory_->RegisterWrappableType(
+      ExtendedIDLAttributesInterface::ExtendedIDLAttributesInterfaceWrappableType(),
+      base::Bind(V8cExtendedIDLAttributesInterface::CreateWrapper),
+      base::Bind(V8cExtendedIDLAttributesInterface::CreateTemplate));
+  wrapper_factory_->RegisterWrappableType(
+      GarbageCollectionTestInterface::GarbageCollectionTestInterfaceWrappableType(),
+      base::Bind(V8cGarbageCollectionTestInterface::CreateWrapper),
+      base::Bind(V8cGarbageCollectionTestInterface::CreateTemplate));
+  wrapper_factory_->RegisterWrappableType(
+      GlobalInterfaceParent::GlobalInterfaceParentWrappableType(),
+      base::Bind(V8cGlobalInterfaceParent::CreateWrapper),
+      base::Bind(V8cGlobalInterfaceParent::CreateTemplate));
+  wrapper_factory_->RegisterWrappableType(
+      ImplementedInterface::ImplementedInterfaceWrappableType(),
+      base::Bind(V8cImplementedInterface::CreateWrapper),
+      base::Bind(V8cImplementedInterface::CreateTemplate));
+  wrapper_factory_->RegisterWrappableType(
+      IndexedGetterInterface::IndexedGetterInterfaceWrappableType(),
+      base::Bind(V8cIndexedGetterInterface::CreateWrapper),
+      base::Bind(V8cIndexedGetterInterface::CreateTemplate));
+  wrapper_factory_->RegisterWrappableType(
+      InterfaceWithAny::InterfaceWithAnyWrappableType(),
+      base::Bind(V8cInterfaceWithAny::CreateWrapper),
+      base::Bind(V8cInterfaceWithAny::CreateTemplate));
+  wrapper_factory_->RegisterWrappableType(
+      InterfaceWithAnyDictionary::InterfaceWithAnyDictionaryWrappableType(),
+      base::Bind(V8cInterfaceWithAnyDictionary::CreateWrapper),
+      base::Bind(V8cInterfaceWithAnyDictionary::CreateTemplate));
+  wrapper_factory_->RegisterWrappableType(
+      InterfaceWithUnsupportedProperties::InterfaceWithUnsupportedPropertiesWrappableType(),
+      base::Bind(V8cInterfaceWithUnsupportedProperties::CreateWrapper),
+      base::Bind(V8cInterfaceWithUnsupportedProperties::CreateTemplate));
+  wrapper_factory_->RegisterWrappableType(
+      NamedConstructorInterface::NamedConstructorInterfaceWrappableType(),
+      base::Bind(V8cNamedConstructorInterface::CreateWrapper),
+      base::Bind(V8cNamedConstructorInterface::CreateTemplate));
+  wrapper_factory_->RegisterWrappableType(
+      NamedGetterInterface::NamedGetterInterfaceWrappableType(),
+      base::Bind(V8cNamedGetterInterface::CreateWrapper),
+      base::Bind(V8cNamedGetterInterface::CreateTemplate));
+  wrapper_factory_->RegisterWrappableType(
+      NamedIndexedGetterInterface::NamedIndexedGetterInterfaceWrappableType(),
+      base::Bind(V8cNamedIndexedGetterInterface::CreateWrapper),
+      base::Bind(V8cNamedIndexedGetterInterface::CreateTemplate));
+  wrapper_factory_->RegisterWrappableType(
+      NestedPutForwardsInterface::NestedPutForwardsInterfaceWrappableType(),
+      base::Bind(V8cNestedPutForwardsInterface::CreateWrapper),
+      base::Bind(V8cNestedPutForwardsInterface::CreateTemplate));
+  wrapper_factory_->RegisterWrappableType(
+      NoConstructorInterface::NoConstructorInterfaceWrappableType(),
+      base::Bind(V8cNoConstructorInterface::CreateWrapper),
+      base::Bind(V8cNoConstructorInterface::CreateTemplate));
+  wrapper_factory_->RegisterWrappableType(
+      NoInterfaceObjectInterface::NoInterfaceObjectInterfaceWrappableType(),
+      base::Bind(V8cNoInterfaceObjectInterface::CreateWrapper),
+      base::Bind(V8cNoInterfaceObjectInterface::CreateTemplate));
+  wrapper_factory_->RegisterWrappableType(
+      NullableTypesTestInterface::NullableTypesTestInterfaceWrappableType(),
+      base::Bind(V8cNullableTypesTestInterface::CreateWrapper),
+      base::Bind(V8cNullableTypesTestInterface::CreateTemplate));
+  wrapper_factory_->RegisterWrappableType(
+      NumericTypesTestInterface::NumericTypesTestInterfaceWrappableType(),
+      base::Bind(V8cNumericTypesTestInterface::CreateWrapper),
+      base::Bind(V8cNumericTypesTestInterface::CreateTemplate));
+  wrapper_factory_->RegisterWrappableType(
+      ObjectTypeBindingsInterface::ObjectTypeBindingsInterfaceWrappableType(),
+      base::Bind(V8cObjectTypeBindingsInterface::CreateWrapper),
+      base::Bind(V8cObjectTypeBindingsInterface::CreateTemplate));
+  wrapper_factory_->RegisterWrappableType(
+      OperationsTestInterface::OperationsTestInterfaceWrappableType(),
+      base::Bind(V8cOperationsTestInterface::CreateWrapper),
+      base::Bind(V8cOperationsTestInterface::CreateTemplate));
+  wrapper_factory_->RegisterWrappableType(
+      PromiseInterface::PromiseInterfaceWrappableType(),
+      base::Bind(V8cPromiseInterface::CreateWrapper),
+      base::Bind(V8cPromiseInterface::CreateTemplate));
+  wrapper_factory_->RegisterWrappableType(
+      PutForwardsInterface::PutForwardsInterfaceWrappableType(),
+      base::Bind(V8cPutForwardsInterface::CreateWrapper),
+      base::Bind(V8cPutForwardsInterface::CreateTemplate));
+  wrapper_factory_->RegisterWrappableType(
+      SequenceUser::SequenceUserWrappableType(),
+      base::Bind(V8cSequenceUser::CreateWrapper),
+      base::Bind(V8cSequenceUser::CreateTemplate));
+  wrapper_factory_->RegisterWrappableType(
+      StaticPropertiesInterface::StaticPropertiesInterfaceWrappableType(),
+      base::Bind(V8cStaticPropertiesInterface::CreateWrapper),
+      base::Bind(V8cStaticPropertiesInterface::CreateTemplate));
+  wrapper_factory_->RegisterWrappableType(
+      StringifierAnonymousOperationInterface::StringifierAnonymousOperationInterfaceWrappableType(),
+      base::Bind(V8cStringifierAnonymousOperationInterface::CreateWrapper),
+      base::Bind(V8cStringifierAnonymousOperationInterface::CreateTemplate));
+  wrapper_factory_->RegisterWrappableType(
+      StringifierAttributeInterface::StringifierAttributeInterfaceWrappableType(),
+      base::Bind(V8cStringifierAttributeInterface::CreateWrapper),
+      base::Bind(V8cStringifierAttributeInterface::CreateTemplate));
+  wrapper_factory_->RegisterWrappableType(
+      StringifierOperationInterface::StringifierOperationInterfaceWrappableType(),
+      base::Bind(V8cStringifierOperationInterface::CreateWrapper),
+      base::Bind(V8cStringifierOperationInterface::CreateTemplate));
+  wrapper_factory_->RegisterWrappableType(
+      TargetInterface::TargetInterfaceWrappableType(),
+      base::Bind(V8cTargetInterface::CreateWrapper),
+      base::Bind(V8cTargetInterface::CreateTemplate));
+  wrapper_factory_->RegisterWrappableType(
+      UnionTypesInterface::UnionTypesInterfaceWrappableType(),
+      base::Bind(V8cUnionTypesInterface::CreateWrapper),
+      base::Bind(V8cUnionTypesInterface::CreateTemplate));
+  wrapper_factory_->RegisterWrappableType(
+      Window::WindowWrappableType(),
+      base::Bind(DummyFunctor),
+      base::Bind(V8cWindow::CreateTemplate));
+
+}
+
+}  // namespace v8c
+
+template<>
+void GlobalEnvironment::CreateGlobalObject<Window>(
+    const scoped_refptr<Window>& global_interface,
+    EnvironmentSettings* environment_settings) {
+  base::polymorphic_downcast<v8c::V8cGlobalEnvironment*>(this)->CreateGlobalObject(global_interface, environment_settings);
+}
+
+}  // namespace script
+}  // namespace cobalt
+
+
diff --git a/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_window.h b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_window.h
new file mode 100644
index 0000000..6e077fa
--- /dev/null
+++ b/src/cobalt/bindings/generated/v8c/testing/cobalt/bindings/testing/v8c_window.h
@@ -0,0 +1,51 @@
+
+// Copyright 2017 Google Inc. All Rights Reserved.
+//
+// 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.
+
+// clang-format off
+
+// This file has been auto-generated by bindings/code_generator_cobalt.py. DO NOT MODIFY!
+// Auto-generated from template: bindings/v8c/templates/interface.h.template
+
+#ifndef V8cWindow_h
+#define V8cWindow_h
+
+#include "base/hash_tables.h"
+#include "base/lazy_instance.h"
+#include "base/memory/ref_counted.h"
+#include "base/threading/thread_checker.h"
+#include "cobalt/base/polymorphic_downcast.h"
+#include "cobalt/script/wrappable.h"
+#include "cobalt/bindings/testing/v8c_global_interface_parent.h"
+#include "cobalt/bindings/testing/window.h"
+
+#include "cobalt/script/v8c/v8c_global_environment.h"
+#include "v8/include/v8.h"
+
+namespace cobalt {
+namespace bindings {
+namespace testing {
+
+class V8cWindow {
+ public:
+  static v8::Local<v8::Object> CreateWrapper(script::v8c::V8cGlobalEnvironment* env, const scoped_refptr<script::Wrappable>& wrappable);
+  static v8::Local<v8::FunctionTemplate> CreateTemplate(script::v8c::V8cGlobalEnvironment* env);
+  // TODO: Add |GetInterfaceObject|.
+};
+
+}  // namespace testing
+}  // namespace bindings
+}  // namespace cobalt
+
+#endif  // V8cWindow_h
diff --git a/src/cobalt/bindings/mozjs45/templates/callback-interface.cc.template b/src/cobalt/bindings/mozjs45/templates/callback-interface.cc.template
index 9104deb..bc67afa 100644
--- a/src/cobalt/bindings/mozjs45/templates/callback-interface.cc.template
+++ b/src/cobalt/bindings/mozjs45/templates/callback-interface.cc.template
@@ -44,12 +44,6 @@
 
 {{binding_class}}::{{binding_class}}(
     JSContext* context,
-    JS::HandleObject implementing_object)
-    : context_(context),
-      implementing_object_(context, implementing_object) { }
-
-{{binding_class}}::{{binding_class}}(
-    JSContext* context,
     JS::HandleValue implementing_object_value)
     : context_(context),
       implementing_object_(context, implementing_object_value) { }
diff --git a/src/cobalt/bindings/mozjs45/templates/callback-interface.h.template b/src/cobalt/bindings/mozjs45/templates/callback-interface.h.template
index 848c113..068afb6 100644
--- a/src/cobalt/bindings/mozjs45/templates/callback-interface.h.template
+++ b/src/cobalt/bindings/mozjs45/templates/callback-interface.h.template
@@ -31,8 +31,6 @@
   typedef {{impl_class}} BaseType;
 
   {{binding_class}}(
-      JSContext* context, JS::HandleObject implementing_object);
-  {{binding_class}}(
       JSContext* context, JS::HandleValue implementing_object_value);
 {% for operation in operations %}
 {% for overload in operation.overloads %}
diff --git a/src/cobalt/bindings/mozjs45/templates/interface.cc.template b/src/cobalt/bindings/mozjs45/templates/interface.cc.template
index aa7bbf0..5774145 100644
--- a/src/cobalt/bindings/mozjs45/templates/interface.cc.template
+++ b/src/cobalt/bindings/mozjs45/templates/interface.cc.template
@@ -35,7 +35,6 @@
 #include "cobalt/script/mozjs-45/mozjs_callback_function.h"
 #include "cobalt/script/mozjs-45/mozjs_exception_state.h"
 #include "cobalt/script/mozjs-45/mozjs_global_environment.h"
-#include "cobalt/script/mozjs-45/mozjs_object_handle.h"
 #include "cobalt/script/mozjs-45/mozjs_property_enumerator.h"
 #include "cobalt/script/mozjs-45/mozjs_user_object_holder.h"
 #include "cobalt/script/mozjs-45/mozjs_value_handle.h"
@@ -75,6 +74,7 @@
 using cobalt::script::mozjs::kConversionFlagRestricted;
 using cobalt::script::mozjs::kConversionFlagTreatNullAsEmptyString;
 using cobalt::script::mozjs::kConversionFlagTreatUndefinedAsEmptyString;
+using cobalt::script::mozjs::kConversionFlagObjectOnly;
 using cobalt::script::mozjs::kNoConversionFlags;
 {% endblock using_directives %}
 {% block enumeration_declarations %}
@@ -932,31 +932,37 @@
 }  // namespace
 
 {% endblock implementation %}
+
 {% block create_global_object_impl %}
-  MozjsGlobalEnvironment* mozjs_global_environment =
-      base::polymorphic_downcast<MozjsGlobalEnvironment*>(this);
-  JSContext* context = mozjs_global_environment->context();
 
-  JSAutoRequest auto_request(context);
-  {{binding_class}}::CreateProxy(
-      context, global_interface);
-  mozjs_global_environment->SetEnvironmentSettings(environment_settings);
-  mozjs_global_environment->EvaluateAutomatics();
+namespace cobalt {
+namespace script {
+namespace mozjs {
 
-  WrapperFactory* wrapper_factory =
-      mozjs_global_environment->wrapper_factory();
+template <typename GlobalInterface>
+void MozjsGlobalEnvironment::CreateGlobalObject(
+    const scoped_refptr<GlobalInterface>& global_interface,
+    EnvironmentSettings* environment_settings) {
+  JSAutoRequest auto_request(context_);
+  {{binding_class}}::CreateProxy(context_, global_interface);
+
+  DCHECK(!environment_settings_);
+  DCHECK(environment_settings);
+  environment_settings_ = environment_settings;
+  EvaluateAutomatics();
+
 {% for interface in all_interfaces %}
 {% if interface.conditional %}
 #if defined({{interface.conditional}})
 {% endif %}
   {# Pass in a dummy CreateProxy for global interface #}
   {% if interface.name == impl_class %}
-  wrapper_factory->RegisterWrappableType(
+  wrapper_factory_->RegisterWrappableType(
       {{interface.name}}::{{interface.name}}WrappableType(),
       base::Bind(DummyFunctor),
       base::Bind(Mozjs{{interface.name}}::PrototypeClass));
   {% else %}
-  wrapper_factory->RegisterWrappableType(
+  wrapper_factory_->RegisterWrappableType(
       {{interface.name}}::{{interface.name}}WrappableType(),
       base::Bind(Mozjs{{interface.name}}::CreateProxy),
       base::Bind(Mozjs{{interface.name}}::PrototypeClass));
@@ -966,6 +972,21 @@
 {% endif %}
 {% endfor %}
 
+}
+
+}  // namespace mozjs
+
+template<>
+void GlobalEnvironment::CreateGlobalObject<{{impl_class}}>(
+    const scoped_refptr<{{impl_class}}>& global_interface,
+    EnvironmentSettings* environment_settings) {
+  base::polymorphic_downcast<MozjsGlobalEnvironment*>(this)->CreateGlobalObject(
+      global_interface, environment_settings);
+}
+
+}  // namespace script
+}  // namespace cobalt
+
 {% endblock create_global_object_impl %}
 
 {%  block enumeration_definitions %}
diff --git a/src/cobalt/bindings/run_cobalt_bindings_tests.py b/src/cobalt/bindings/run_cobalt_bindings_tests.py
index acec6d9..9cdaa4f 100644
--- a/src/cobalt/bindings/run_cobalt_bindings_tests.py
+++ b/src/cobalt/bindings/run_cobalt_bindings_tests.py
@@ -29,6 +29,7 @@
 import _env  # pylint: disable=unused-import
 from cobalt.bindings.idl_compiler_cobalt import IdlCompilerCobalt
 from cobalt.bindings.mozjs45.code_generator_mozjs45 import CodeGeneratorMozjs45
+from cobalt.bindings.v8c.code_generator_v8c import CodeGeneratorV8c
 from webkitpy.bindings.bindings_tests import run_bindings_tests
 
 
@@ -41,6 +42,8 @@
 
   if args.engine.lower() == 'mozjs45':
     generator = CodeGeneratorMozjs45
+  elif args.engine.lower() == 'v8c':
+    generator = CodeGeneratorV8c
   else:
     raise RuntimeError('Unsupported JavaScript engine: ' + args.engine)
 
diff --git a/src/cobalt/bindings/run_cobalt_bindings_tests.sh b/src/cobalt/bindings/run_cobalt_bindings_tests.sh
index e56fc43..4c1f37c 100755
--- a/src/cobalt/bindings/run_cobalt_bindings_tests.sh
+++ b/src/cobalt/bindings/run_cobalt_bindings_tests.sh
@@ -20,3 +20,4 @@
 cd "$(dirname "${BASH_SOURCE[0]}")"
 
 python run_cobalt_bindings_tests.py mozjs45 "$@"
+python run_cobalt_bindings_tests.py v8c "$@"
diff --git a/src/cobalt/bindings/templates/interface-base.cc.template b/src/cobalt/bindings/templates/interface-base.cc.template
index cf3ccdf..a0e297e 100644
--- a/src/cobalt/bindings/templates/interface-base.cc.template
+++ b/src/cobalt/bindings/templates/interface-base.cc.template
@@ -42,8 +42,8 @@
 #include "base/debug/trace_event.h"
 #include "cobalt/base/polymorphic_downcast.h"
 #include "cobalt/script/global_environment.h"
-#include "cobalt/script/opaque_handle.h"
 #include "cobalt/script/script_value.h"
+#include "cobalt/script/value_handle.h"
 {% for include in implementation_includes %}
 #include "{{include}}"
 {% endfor %}
@@ -64,10 +64,10 @@
 {% endfor %}
 using cobalt::script::CallbackInterfaceTraits;
 using cobalt::script::GlobalEnvironment;
-using cobalt::script::OpaqueHandle;
-using cobalt::script::OpaqueHandleHolder;
 using cobalt::script::ScriptValue;
 using cobalt::script::ValueHandle;
+using cobalt::script::ValueHandle;
+using cobalt::script::ValueHandleHolder;
 using cobalt::script::Wrappable;
 {% endblock using_directives %}
 {% block top_level_unnamed_namespace %}
@@ -84,22 +84,12 @@
 {% for component in components|reverse %}
 }  // namespace {{component}}
 {% endfor %}
+
 {% if is_global_interface %}
-
-namespace cobalt {
-namespace script {
-
-template<>
-void GlobalEnvironment::CreateGlobalObject<{{impl_class}}>(
-    const scoped_refptr<{{impl_class}}>& global_interface,
-    EnvironmentSettings* environment_settings) {
 {% block create_global_object_impl %}
 {% endblock create_global_object_impl %}
-}
-
-}  // namespace script
-}  // namespace cobalt
 {% endif %}
+
 {% if conditional %}
 #endif  // defined({{conditional}})
 {% endif %}
diff --git a/src/cobalt/bindings/testing/bindings_test_base.h b/src/cobalt/bindings/testing/bindings_test_base.h
index f37639b..e32c87a 100644
--- a/src/cobalt/bindings/testing/bindings_test_base.h
+++ b/src/cobalt/bindings/testing/bindings_test_base.h
@@ -73,13 +73,13 @@
 
   bool EvaluateScript(const std::string& script,
                       const scoped_refptr<script::Wrappable>& owning_object,
-                      base::optional<script::OpaqueHandleHolder::Reference>*
-                          out_opaque_handle = NULL) {
+                      base::optional<script::ValueHandleHolder::Reference>*
+                          out_value_handle = NULL) {
     scoped_refptr<script::SourceCode> source =
         script::SourceCode::CreateSourceCode(
             script, base::SourceLocation("[object BindingsTestBase]", 1, 1));
     return global_environment_->EvaluateScript(
-        source, owning_object, false /*mute_errors*/, out_opaque_handle);
+        source, owning_object, false /*mute_errors*/, out_value_handle);
   }
 
   void CollectGarbage() { engine_->CollectGarbage(); }
diff --git a/src/cobalt/bindings/testing/evaluate_script_test.cc b/src/cobalt/bindings/testing/evaluate_script_test.cc
index e21752f..2cb406d 100644
--- a/src/cobalt/bindings/testing/evaluate_script_test.cc
+++ b/src/cobalt/bindings/testing/evaluate_script_test.cc
@@ -17,7 +17,7 @@
 #include "cobalt/bindings/testing/object_type_bindings_interface.h"
 #include "cobalt/bindings/testing/script_object_owner.h"
 
-using cobalt::script::OpaqueHandleHolder;
+using cobalt::script::ValueHandleHolder;
 using ::testing::_;
 using ::testing::Invoke;
 using ::testing::Return;
@@ -70,12 +70,12 @@
   EXPECT_TRUE(EvaluateScript(script, arbitrary_interface_mock, NULL));
 
   // Call with non-null, but unset optional handle.
-  base::optional<OpaqueHandleHolder::Reference> opaque_handle;
-  EXPECT_TRUE(EvaluateScript(script, arbitrary_interface_mock, &opaque_handle));
-  ASSERT_FALSE(opaque_handle->referenced_value().IsNull());
+  base::optional<ValueHandleHolder::Reference> value_handle;
+  EXPECT_TRUE(EvaluateScript(script, arbitrary_interface_mock, &value_handle));
+  ASSERT_FALSE(value_handle->referenced_value().IsNull());
 
   EXPECT_CALL(test_mock(), object_property())
-      .WillOnce(Return(&opaque_handle->referenced_value()));
+      .WillOnce(Return(&value_handle->referenced_value()));
   std::string result;
   EXPECT_TRUE(EvaluateScript("test.objectProperty == 21;", &result));
   EXPECT_STREQ("true", result.c_str());
diff --git a/src/cobalt/bindings/testing/object_type_bindings_interface.h b/src/cobalt/bindings/testing/object_type_bindings_interface.h
index 23a1cd2..374bd88 100644
--- a/src/cobalt/bindings/testing/object_type_bindings_interface.h
+++ b/src/cobalt/bindings/testing/object_type_bindings_interface.h
@@ -18,7 +18,7 @@
 #include "cobalt/bindings/testing/arbitrary_interface.h"
 #include "cobalt/bindings/testing/base_interface.h"
 #include "cobalt/bindings/testing/derived_interface.h"
-#include "cobalt/script/opaque_handle.h"
+#include "cobalt/script/value_handle.h"
 #include "cobalt/script/wrappable.h"
 #include "testing/gmock/include/gmock/gmock.h"
 
@@ -35,8 +35,8 @@
   MOCK_METHOD0(derived_interface, scoped_refptr<DerivedInterface>());
   MOCK_METHOD1(set_derived_interface,
                void(const scoped_refptr<DerivedInterface>&));
-  MOCK_METHOD0(object_property, const script::OpaqueHandleHolder*());
-  MOCK_METHOD1(set_object_property, void(const script::OpaqueHandleHolder&));
+  MOCK_METHOD0(object_property, const script::ValueHandleHolder*());
+  MOCK_METHOD1(set_object_property, void(const script::ValueHandleHolder&));
 
   DEFINE_WRAPPABLE_TYPE(ObjectTypeBindingsInterface);
 };
diff --git a/src/cobalt/bindings/testing/object_type_bindings_test.cc b/src/cobalt/bindings/testing/object_type_bindings_test.cc
index a6892bd..89e6460 100644
--- a/src/cobalt/bindings/testing/object_type_bindings_test.cc
+++ b/src/cobalt/bindings/testing/object_type_bindings_test.cc
@@ -187,7 +187,7 @@
 }
 
 TEST_F(PlatformObjectBindingsTest, ReturnCorrectWrapperForObjectType) {
-  typedef ScriptObjectOwner<script::OpaqueHandleHolder> ObjectOwner;
+  typedef ScriptObjectOwner<script::ValueHandleHolder> ObjectOwner;
   ObjectOwner object_owner(&test_mock());
 
   // Store the Wrappable object as an opaque handle.
@@ -207,7 +207,7 @@
 }
 
 TEST_F(UserObjectBindingsTest, PassUserObjectforObjectType) {
-  typedef ScriptObjectOwner<script::OpaqueHandleHolder> ObjectOwner;
+  typedef ScriptObjectOwner<script::ValueHandleHolder> ObjectOwner;
   ObjectOwner object_owner(&test_mock());
 
   EXPECT_TRUE(EvaluateScript("var obj = new Object();", NULL));
@@ -222,7 +222,7 @@
 }
 
 TEST_F(UserObjectBindingsTest, NullObject) {
-  typedef ScriptObjectOwner<script::OpaqueHandleHolder> ObjectOwner;
+  typedef ScriptObjectOwner<script::ValueHandleHolder> ObjectOwner;
   ObjectOwner object_owner(&test_mock());
 
   EXPECT_CALL(test_mock(), set_object_property(_))
diff --git a/src/cobalt/bindings/testing/sequence_user.h b/src/cobalt/bindings/testing/sequence_user.h
index 66d158c..fcdedbf 100644
--- a/src/cobalt/bindings/testing/sequence_user.h
+++ b/src/cobalt/bindings/testing/sequence_user.h
@@ -18,9 +18,9 @@
 #include <string>
 
 #include "cobalt/bindings/testing/arbitrary_interface.h"
-#include "cobalt/script/opaque_handle.h"
 #include "cobalt/script/sequence.h"
 #include "cobalt/script/union_type.h"
+#include "cobalt/script/value_handle.h"
 #include "cobalt/script/wrappable.h"
 
 namespace cobalt {
diff --git a/src/cobalt/bindings/v8c/templates/callback-interface.cc.template b/src/cobalt/bindings/v8c/templates/callback-interface.cc.template
index e69de29..975a85f 100644
--- a/src/cobalt/bindings/v8c/templates/callback-interface.cc.template
+++ b/src/cobalt/bindings/v8c/templates/callback-interface.cc.template
@@ -0,0 +1,63 @@
+{#
+ # Copyright 2017 Google Inc. All Rights Reserved.
+ #
+ # 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.
+ #}
+{% extends "callback-interface-base.cc.template" %}
+
+{% block includes %}
+{{ super() }}
+#include "{{generated_conversion_include}}"
+
+#include "cobalt/script/logging_exception_state.h"
+#include "cobalt/script/v8c/v8c_callback_interface.h"
+#include "cobalt/script/v8c/v8c_global_environment.h"
+#include "v8/include/v8.h"
+{% endblock includes %}
+
+{% block using_directives %}
+{{ super() }}
+using cobalt::script::LoggingExceptionState;
+using cobalt::script::v8c::V8cGlobalEnvironment;
+{% endblock using_directives %}
+
+{% block implementation %}
+{% for component in components %}
+namespace {{component}} {
+{% endfor %}
+
+{% for operation in operations %}
+{% for overload in operation.overloads %}
+{{overload.type}} {{binding_class}}::{{overload.name}}(
+    const scoped_refptr<script::Wrappable>& callback_this,
+  {% for arg in overload.arguments %}
+    {{arg.arg_type}} {{arg.name}},
+  {% endfor %}
+    bool* had_exception) const {
+  NOTIMPLEMENTED();
+
+{% if overload.type != 'void' %}
+  {{overload.type}} cobalt_return_value;
+{% endif %}
+
+{% if overload.type != 'void' %}
+  return cobalt_return_value;
+{% endif %}
+}
+{% endfor %}
+{% endfor %}
+
+{% for component in components|reverse %}
+}  // namespace {{component}}
+{% endfor %}
+{% endblock implementation %}
diff --git a/src/cobalt/bindings/v8c/templates/callback-interface.h.template b/src/cobalt/bindings/v8c/templates/callback-interface.h.template
index e69de29..709cd69 100644
--- a/src/cobalt/bindings/v8c/templates/callback-interface.h.template
+++ b/src/cobalt/bindings/v8c/templates/callback-interface.h.template
@@ -0,0 +1,73 @@
+{#
+ # Copyright 2017 Google Inc. All Rights Reserved.
+ #
+ # 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.
+ #}
+
+{% extends "callback-interface-base.h.template" %}
+
+{% block includes %}
+{{ super() }}
+#include "cobalt/script/v8c/weak_heap_object.h"
+{% endblock includes %}
+
+{% block implementation %}
+
+{% for component in components %}
+namespace {{component}} {
+{% endfor %}
+
+class {{binding_class}} : public {{impl_class}} {
+ public:
+  typedef {{impl_class}} BaseType;
+
+  {{binding_class}}(
+    script::v8c::V8cGlobalEnvironment* env, v8::Local<v8::Value> implementing_object_value)
+    : env_(env), implementing_object_(env, implementing_object_value) {}
+
+{% for operation in operations %}
+{% for overload in operation.overloads %}
+  {{overload.type}} {{overload.name}}(
+      const scoped_refptr<script::Wrappable>& callback_this,
+    {% for arg in overload.arguments %}
+      {{arg.arg_type}} {{arg.name}},
+    {% endfor %}
+      bool* had_exception) const override;
+{% endfor %}
+{% endfor %}
+
+  v8::Local<v8::Value> value() const { return implementing_object_.GetValue(); }
+
+ private:
+  script::v8c::V8cGlobalEnvironment* env_;
+  script::v8c::WeakHeapObject implementing_object_;
+};
+
+{% for component in components|reverse %}
+}  // namespace {{component}}
+{% endfor %}
+
+namespace cobalt {
+namespace script {
+
+// Explicit instantiation of CallbackInterfaceTraits struct so we can infer
+// the type of the generated class from the type of the callback interface.
+template<>
+struct CallbackInterfaceTraits<{{fully_qualified_impl_class}}> {
+  typedef {{fully_qualified_binding_class}} V8cCallbackInterfaceClass;
+};
+
+}  // namespace script
+}  // namespace cobalt
+
+{% endblock implementation %}
diff --git a/src/cobalt/bindings/v8c/templates/enumeration-conversion.cc.template b/src/cobalt/bindings/v8c/templates/enumeration-conversion.cc.template
index e69de29..5508dbe 100644
--- a/src/cobalt/bindings/v8c/templates/enumeration-conversion.cc.template
+++ b/src/cobalt/bindings/v8c/templates/enumeration-conversion.cc.template
@@ -0,0 +1,66 @@
+{#
+ # Copyright 2017 Google Inc. All Rights Reserved.
+ #
+ # 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.
+ #}
+
+/*
+ * Copyright {{today.year}} Google Inc. All Rights Reserved.
+ *
+ * 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.
+ */
+
+// clang-format off
+
+// This file has been auto-generated by {{code_generator}}. DO NOT MODIFY!
+// Auto-generated from template: {{template_path}}
+
+#include "{{enum_include}}"
+
+#include "{{generated_conversion_include}}"
+#include "base/logging.h"
+#include "cobalt/script/exception_state.h"
+#include "v8/include/v8.h"
+
+using {{fully_qualified_name}};
+
+namespace cobalt {
+namespace script {
+namespace v8c {
+
+void ToJSValue(
+    v8::Isolate* isolate,
+    {{enumeration_name}} in_enum,
+    v8::Local<v8::Value> out_value) {
+  NOTIMPLEMENTED();
+}
+
+void FromJSValue(v8::Isolate* isolate, v8::Local<v8::Value> value,
+                 int conversion_flags, ExceptionState* exception_state,
+                 {{enumeration_name}}* out_enum) {
+  NOTIMPLEMENTED();
+}
+
+}  // namespace v8c
+}  // namespace script
+}  // namespace cobalt
diff --git a/src/cobalt/bindings/v8c/templates/generated-types.h.template b/src/cobalt/bindings/v8c/templates/generated-types.h.template
index e69de29..28ed5e5 100644
--- a/src/cobalt/bindings/v8c/templates/generated-types.h.template
+++ b/src/cobalt/bindings/v8c/templates/generated-types.h.template
@@ -0,0 +1,93 @@
+{#
+ # Copyright 2017 Google Inc. All Rights Reserved.
+ #
+ # 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.
+ #}
+
+/*
+ * Copyright {{today.year}} Google Inc. All Rights Reserved.
+ *
+ * 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.
+ */
+
+// clang-format off
+
+// This file has been auto-generated by {{code_generator}}. DO NOT MODIFY!
+// Auto-generated from template: {{template_path}}
+
+#ifndef GENERATED_TYPE_CONVERSION_H_
+#define GENERATED_TYPE_CONVERSION_H_
+
+#include "cobalt/script/exception_state.h"
+#include "v8/include/v8.h"
+
+// #includes for generated types.
+{% for path in includes %}
+#include "{{path}}"
+{% endfor %}
+
+namespace cobalt {
+namespace script {
+namespace v8c {
+
+{% for dictionary in dictionaries %}
+// {{dictionary.fully_qualified_name}} -> JSValue
+void ToJSValue(
+    v8::Isolate* isolate,
+    const {{dictionary.fully_qualified_name}}& in_value,
+    v8::Local<v8::Value>* out_value);
+
+// JSValue -> {{dictionary.fully_qualified_name}}
+void FromJSValue(
+    v8::Isolate* isolate,
+    v8::Local<v8::Value> value,
+    int conversion_flags,
+    ExceptionState* exception_state,
+    {{dictionary.fully_qualified_name}}* out_value);
+
+{% endfor %}
+{% for enum in enumerations %}
+// {{enum.fully_qualified_name}} -> JSValue
+void ToJSValue(
+    v8::Isolate* isolate,
+    {{enum.fully_qualified_name}} in_value,
+    v8::Local<v8::Value>* out_value);
+
+// JSValue -> {{enum.fully_qualified_name}}
+void FromJSValue(
+    v8::Isolate* isolate,
+    v8::Local<v8::Value> value,
+    int conversion_flags,
+    ExceptionState* exception_state,
+    {{enum.fully_qualified_name}}* out_value);
+
+{% endfor %}
+}  // namespace v8c
+}  // namespace script
+}  // namespace cobalt
+
+// #include this here so the conversion functions for generated types are
+// visible refer to template types, such as sequence<T>.
+#include "cobalt/script/v8c/conversion_helpers.h"
+
+#endif  // GENERATED_TYPE_CONVERSION_H_
diff --git a/src/cobalt/bindings/v8c/templates/interface.cc.template b/src/cobalt/bindings/v8c/templates/interface.cc.template
index e69de29..72a4108 100644
--- a/src/cobalt/bindings/v8c/templates/interface.cc.template
+++ b/src/cobalt/bindings/v8c/templates/interface.cc.template
@@ -0,0 +1,380 @@
+{#
+ # Copyright 2017 Google Inc. All Rights Reserved.
+ #
+ # 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.
+ #}
+
+{% from 'macros.cc.template' import add_extra_arguments %}
+{% from 'macros.cc.template' import call_cobalt_function %}
+{% from 'macros.cc.template' import check_if_object_implements_interface with context %}
+{% from 'macros.cc.template' import constructor_implementation with context %}
+{% from 'macros.cc.template' import function_implementation with context %}
+{% from 'macros.cc.template' import get_impl_class_instance %}
+{% from 'macros.cc.template' import nonstatic_function_prologue %}
+{% from 'macros.cc.template' import overload_resolution_implementation with context %}
+{% from 'macros.cc.template' import set_attribute_implementation with context %}
+{% from 'macros.cc.template' import static_function_prologue %}
+
+{% extends "interface-base.cc.template" %}
+
+{% block includes %}
+{{ super() }}
+#include "{{generated_conversion_include}}"
+
+#include "cobalt/script/callback_interface_traits.h"
+#include "cobalt/script/v8c/callback_function_conversion.h"
+#include "cobalt/script/v8c/conversion_helpers.h"
+#include "cobalt/script/v8c/native_promise.h"
+#include "cobalt/script/v8c/type_traits.h"
+#include "cobalt/script/v8c/v8c_callback_function.h"
+#include "cobalt/script/v8c/v8c_callback_interface_holder.h"
+#include "cobalt/script/v8c/v8c_exception_state.h"
+#include "cobalt/script/v8c/v8c_global_environment.h"
+#include "cobalt/script/v8c/v8c_value_handle.h"
+#include "cobalt/script/v8c/wrapper_private.h"
+#include "v8/include/v8.h"
+
+{% endblock includes %}
+
+{% block using_directives %}
+{{ super() }}
+using cobalt::script::v8c::FromJSValue;
+using cobalt::script::v8c::InterfaceData;
+using cobalt::script::v8c::kConversionFlagClamped;
+using cobalt::script::v8c::kConversionFlagNullable;
+using cobalt::script::v8c::kConversionFlagRestricted;
+using cobalt::script::v8c::kConversionFlagTreatNullAsEmptyString;
+using cobalt::script::v8c::kConversionFlagTreatUndefinedAsEmptyString;
+using cobalt::script::v8c::kNoConversionFlags;
+using cobalt::script::v8c::TypeTraits;
+using cobalt::script::v8c::V8cExceptionState;
+using cobalt::script::v8c::V8cGlobalEnvironment;
+using cobalt::script::v8c::WrapperFactory;
+using cobalt::script::v8c::WrapperPrivate;
+{% endblock using_directives %}
+
+{% block enumeration_declarations %}
+{% if enumerations|length %}
+// Declare and define these in the same namespace that the other overloads
+// were brought into with the using declaration.
+{% for enumeration in enumerations %}
+void ToJSValue(
+    v8::Isolate* isolate,
+    {{impl_class}}::{{enumeration.name}} in_enum,
+    v8::Local<v8::Value>* out_value);
+void FromJSValue(v8::Isolate* context, v8::Local<v8::Value> value,
+                 int conversion_flags, ExceptionState* exception_state,
+                 {{impl_class}}::{{enumeration.name}}* out_enum);
+{% endfor %}
+{% endif %}
+{% endblock enumeration_declarations %}
+
+{% block top_level_unnamed_namespace %}
+
+v8::Local<v8::Object> DummyFunctor(V8cGlobalEnvironment*, const scoped_refptr<Wrappable>&) {
+  NOTIMPLEMENTED();
+  return {};
+}
+
+{% endblock top_level_unnamed_namespace %}
+
+{% block implementation %}
+
+namespace {
+
+void {{interface.name}}Constructor(const v8::FunctionCallbackInfo<v8::Value>& args) {
+  NOTIMPLEMENTED();
+  if (!args.IsConstructCall()) {
+    // TODO: Probably throw something here...
+    return;
+  }
+
+  DCHECK(args.This()->InternalFieldCount() == 1);
+  args.This()->SetInternalField(0, v8::External::New(args.GetIsolate(), nullptr));
+  args.GetReturnValue().Set(args.This());
+}
+
+{% for attribute in attributes if not attribute.is_constructor_attribute %}
+{% if attribute.conditional %}
+#if defined({{attribute.conditional}})
+{% endif %}
+
+void v8cGet_{{attribute.idl_name}}(
+  v8::Local<v8::String> property,
+  const v8::PropertyCallbackInfo<v8::Value>& info)
+{
+  NOTIMPLEMENTED();
+
+  v8::Local<v8::External> external = v8::Local<v8::External>::Cast(info.Holder()->GetInternalField(0));
+  WrapperPrivate* wrapper_private = static_cast<WrapperPrivate*>(external->Value());
+  {{interface.name}}* impl = static_cast<{{interface.name}}*>(wrapper_private->wrappable<{{interface.name}}>());
+
+{% if attribute.put_forwards %}
+  NOTIMPLEMENTED();
+{% else %}
+  v8::Local<v8::Value> result_value;
+{##}
+{% endif %} {#- attribute.put_forwards #}
+}
+
+{% if attribute.has_setter %}
+
+void v8cSet_{{attribute.idl_name}}(
+  v8::Local<v8::String> property,
+  v8::Local<v8::Value> v8_value,
+  const v8::PropertyCallbackInfo<void>& info)
+{
+  v8::Local<v8::External> external = v8::Local<v8::External>::Cast(info.Holder()->GetInternalField(0));
+  WrapperPrivate* wrapper_private = static_cast<WrapperPrivate*>(external->Value());
+  {{interface.name}}* impl = static_cast<{{interface.name}}*>(wrapper_private->wrappable<{{interface.name}}>());
+
+{% if attribute.put_forwards %}
+  NOTIMPLEMENTED();
+{% else %}
+  TypeTraits<{{attribute.type}}>::ConversionType conversion_value;
+  V8cExceptionState exception_state{};
+  FromJSValue(info.GetIsolate(), v8_value, {{attribute.conversion_flags}}, &exception_state, &conversion_value);
+{% if attribute.raises_exception %}
+  V8cExceptionState exception;
+{% endif %}
+  impl->{{attribute.setter_function_name}}(
+    conversion_value
+{% if attribute.raises_exception %}
+    ,&exception
+{% endif %}
+  );
+{##}
+{% endif %} {#- attribute.put_forwards #}
+}
+
+{% endif %}
+
+{% if attribute.conditional %}
+#endif  // {{attribute.conditional}}
+{% endif %}
+{% endfor %}
+
+void DummyFunction(const v8::FunctionCallbackInfo<v8::Value>& info) {
+  LOG(INFO) << __func__;
+}
+
+void InitializeTemplate(
+  V8cGlobalEnvironment* env,
+  InterfaceData* interface_data) {
+  v8::Isolate* isolate = env->isolate();
+  v8::Local<v8::FunctionTemplate> function_template = v8::FunctionTemplate::New(
+    isolate);
+  function_template->SetClassName(
+    v8::String::NewFromUtf8(isolate, "{{interface_name}}",
+        v8::NewStringType::kInternalized).ToLocalChecked());
+  v8::Local<v8::ObjectTemplate> instance_template = function_template->InstanceTemplate();
+  instance_template->SetInternalFieldCount(1);
+
+  v8::Local<v8::ObjectTemplate> prototype_template = function_template->PrototypeTemplate();
+  prototype_template->SetInternalFieldCount(1);
+
+{% for attribute in attributes if not attribute.is_constructor_attribute %}
+{% if attribute.conditional %}
+#if defined({{attribute.conditional}})
+{% endif %}
+  instance_template->SetAccessor(
+    v8::String::NewFromUtf8(isolate, "{{attribute.idl_name}}",
+                              v8::NewStringType::kInternalized)
+          .ToLocalChecked(),
+    v8cGet_{{attribute.idl_name}}
+{% if attribute.has_setter %}
+    ,v8cSet_{{attribute.idl_name}}
+{% endif %}
+  );
+{% if attribute.conditional %}
+#endif  // {{attribute.conditional}}
+{% endif %}
+{% endfor %}
+
+{% for operation in operations %}
+  instance_template->Set(
+      v8::String::NewFromUtf8(
+          isolate,
+          "{{operation.idl_name}}",
+          v8::NewStringType::kInternalized).ToLocalChecked(),
+      v8::FunctionTemplate::New(isolate, DummyFunction)
+  );
+{% endfor %}
+
+  interface_data->templ.Set(env->isolate(), function_template);
+}
+
+inline InterfaceData* GetInterfaceData(V8cGlobalEnvironment* env) {
+  const int kInterfaceUniqueId = {{unique_id}};
+  // By convention, the |V8cGlobalEnvironment| that we are associated with
+  // will hold our |InterfaceData| at index |kInterfaceUniqueId|, as we asked
+  // for it to be there in the first place, and could not have conflicted with
+  // any other interface.
+  return env->GetInterfaceData(kInterfaceUniqueId);
+}
+
+}  // namespace
+
+v8::Local<v8::Object> {{binding_class}}::CreateWrapper(V8cGlobalEnvironment* env, const scoped_refptr<Wrappable>& wrappable) {
+  v8::Isolate* isolate = env->isolate();
+  v8::Isolate::Scope isolate_scope(isolate);
+  v8::EscapableHandleScope handle_scope(isolate);
+  v8::Local<v8::Context> context = env->context();
+  v8::Context::Scope scope(context);
+
+  InterfaceData* interface_data = GetInterfaceData(env);
+  if (interface_data->templ.IsEmpty()) {
+    InitializeTemplate(env, interface_data);
+  }
+  DCHECK(!interface_data->templ.IsEmpty());
+
+  v8::Local<v8::FunctionTemplate> function_template = interface_data->templ.Get(isolate);
+  DCHECK(function_template->InstanceTemplate()->InternalFieldCount() == 1);
+  v8::Local<v8::Object> object = function_template->InstanceTemplate()->NewInstance(context).ToLocalChecked();
+  DCHECK(object->InternalFieldCount() == 1);
+
+  // |WrapperPrivate|'s lifetime will be managed by V8.
+  new WrapperPrivate(isolate, wrappable, object);
+  return handle_scope.Escape(object);
+}
+
+v8::Local<v8::FunctionTemplate> {{binding_class}}::CreateTemplate(V8cGlobalEnvironment* env) {
+  InterfaceData* interface_data = GetInterfaceData(env);
+  if (interface_data->templ.IsEmpty()) {
+    InitializeTemplate(env, interface_data);
+  }
+
+  return interface_data->templ.Get(env->isolate());
+}
+
+{% endblock implementation %}
+
+{% block create_global_object_impl %}
+
+namespace cobalt {
+namespace script {
+namespace v8c {
+
+template <typename GlobalInterface>
+void V8cGlobalEnvironment::CreateGlobalObject(
+    const scoped_refptr<GlobalInterface>& global_interface,
+    EnvironmentSettings* environment_settings) {
+  v8::Isolate::Scope isolate_scope(isolate_);
+  v8::HandleScope handle_scope(isolate_);
+
+  v8::Local<v8::ObjectTemplate> global_object_template = v8::ObjectTemplate::New(isolate_);
+{% for interface in all_interfaces %}
+{% if interface.conditional %}
+#if defined({{interface.conditional}})
+{% endif %}
+  global_object_template->Set(
+      v8::String::NewFromUtf8(
+          isolate_, "{{interface.name}}",
+          v8::NewStringType::kInternalized).ToLocalChecked(),
+      V8c{{interface.name}}::CreateTemplate(this));
+{% if interface.conditional %}
+#endif  // defined({{interface.conditional}})
+{% endif %}
+{% endfor %}
+
+  v8::Local<v8::Context> context =
+      v8::Context::New(isolate_, nullptr, global_object_template);
+  context_.Reset(isolate_, context);
+
+  environment_settings_ = environment_settings;
+  EvaluateAutomatics();
+
+{% for interface in all_interfaces %}
+{% if interface.conditional %}
+#if defined({{interface.conditional}})
+{% endif %}
+  {# Pass in a dummy CreateProxy for global interface #}
+  {% if interface.name == impl_class %}
+  wrapper_factory_->RegisterWrappableType(
+      {{interface.name}}::{{interface.name}}WrappableType(),
+      base::Bind(DummyFunctor),
+      base::Bind(V8c{{interface.name}}::CreateTemplate));
+  {% else %}
+  wrapper_factory_->RegisterWrappableType(
+      {{interface.name}}::{{interface.name}}WrappableType(),
+      base::Bind(V8c{{interface.name}}::CreateWrapper),
+      base::Bind(V8c{{interface.name}}::CreateTemplate));
+  {% endif %}
+{% if interface.conditional %}
+#endif  // defined({{interface.conditional}})
+{% endif %}
+{% endfor %}
+
+}
+
+}  // namespace v8c
+
+template<>
+void GlobalEnvironment::CreateGlobalObject<{{impl_class}}>(
+    const scoped_refptr<{{impl_class}}>& global_interface,
+    EnvironmentSettings* environment_settings) {
+  base::polymorphic_downcast<v8c::V8cGlobalEnvironment*>(this)->CreateGlobalObject(global_interface, environment_settings);
+}
+
+}  // namespace script
+}  // namespace cobalt
+
+{% endblock create_global_object_impl %}
+
+{%  block enumeration_definitions %}
+// enum block
+{% for enumeration in enumerations %}
+
+inline void ToJSValue(
+    v8::Isolate* isolate,
+    {{impl_class}}::{{enumeration.name}} in_enum,
+    v8::Local<v8::Value>* out_value) {
+  switch (in_enum) {
+{% for value, idl_value in enumeration.value_pairs %}
+    case {{impl_class}}::{{value}}:
+      ToJSValue(isolate, std::string("{{idl_value}}"), out_value);
+      return;
+{% endfor %}
+    default:
+      NOTREACHED();
+      *out_value = v8::Undefined(isolate);
+  }
+}
+
+inline void FromJSValue(v8::Isolate* isolate, v8::Local<v8::Value> value,
+                 int conversion_flags, ExceptionState* exception_state,
+                 {{impl_class}}::{{enumeration.name}}* out_enum) {
+  DCHECK_EQ(0, conversion_flags) << "Unexpected conversion flags.";
+  // Value -> IDL enum algorithm described here:
+  // http://heycam.github.io/webidl/#es-enumeration
+  // 1. Let S be the result of calling ToString(V).
+  v8::Local<v8::String> string = value->ToString();
+
+  bool match = false;
+// 3. Return the enumeration value of type E that is equal to S.
+{% for value, idl_value in enumeration.value_pairs %}
+{{-" else " if not loop.first}}
+  if (string == v8::String::NewFromUtf8(isolate, "{{id_value}}")) {
+    *out_enum = {{impl_class}}::{{value}};
+  }
+{% endfor %}
+  else {
+    // 2. If S is not one of E's enumeration values, then throw a TypeError.
+    exception_state->SetSimpleException(cobalt::script::kConvertToEnumFailed);
+    return;
+  }
+}
+
+{% endfor %}
+
+{% endblock enumeration_definitions %}
diff --git a/src/cobalt/bindings/v8c/templates/interface.h.template b/src/cobalt/bindings/v8c/templates/interface.h.template
index e69de29..579d21d 100644
--- a/src/cobalt/bindings/v8c/templates/interface.h.template
+++ b/src/cobalt/bindings/v8c/templates/interface.h.template
@@ -0,0 +1,34 @@
+{#
+ # Copyright 2017 Google Inc. All Rights Reserved.
+ #
+ # 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.
+ #}
+
+{% extends "interface-base.h.template" %}
+
+{% block includes %}
+{{ super() }}
+#include "cobalt/script/v8c/v8c_global_environment.h"
+#include "v8/include/v8.h"
+{% endblock includes %}
+
+{% block implementation %}
+class {{binding_class}} {
+ public:
+  static v8::Local<v8::Object> CreateWrapper(script::v8c::V8cGlobalEnvironment* env, const scoped_refptr<script::Wrappable>& wrappable);
+  static v8::Local<v8::FunctionTemplate> CreateTemplate(script::v8c::V8cGlobalEnvironment* env);
+{% if has_interface_object %}
+  // TODO: Add |GetInterfaceObject|.
+{% endif %}
+};
+{% endblock implementation %}
diff --git a/src/cobalt/browser/application.cc b/src/cobalt/browser/application.cc
index 3091f7c..6d8e705 100644
--- a/src/cobalt/browser/application.cc
+++ b/src/cobalt/browser/application.cc
@@ -37,6 +37,8 @@
 #include "cobalt/base/init_cobalt.h"
 #include "cobalt/base/language.h"
 #include "cobalt/base/localized_strings.h"
+#include "cobalt/base/on_screen_keyboard_hidden_event.h"
+#include "cobalt/base/on_screen_keyboard_shown_event.h"
 #include "cobalt/base/startup_timer.h"
 #include "cobalt/base/user_log.h"
 #include "cobalt/base/window_size_changed_event.h"
@@ -453,7 +455,6 @@
   // Create the main components of our browser.
   BrowserModule::Options options(web_options);
   options.web_module_options.name = "MainWebModule";
-  options.language = language;
   options.initial_deep_link = GetInitialDeepLink();
   options.network_module_options.preferred_language = language;
   options.command_line_auto_mem_settings =
@@ -474,6 +475,12 @@
     options.web_module_options.javascript_engine_options.disable_jit = true;
   }
 
+  if (command_line->HasSwitch(
+          browser::switches::kRetainRemoteTypefaceCacheDuringSuspend)) {
+    options.web_module_options.should_retain_remote_typeface_cache_on_suspend =
+        true;
+  }
+
 #if defined(ENABLE_DEBUG_COMMAND_LINE_SWITCHES)
   if (command_line->HasSwitch(browser::switches::kNullSavegame)) {
     options.storage_manager_options.savegame_options.factory =
@@ -620,6 +627,17 @@
   event_dispatcher_.AddEventCallback(base::WindowSizeChangedEvent::TypeId(),
                                      window_size_change_event_callback_);
 #endif  // SB_API_VERSION >= SB_WINDOW_SIZE_CHANGED_API_VERSION
+#if SB_HAS(ON_SCREEN_KEYBOARD)
+  on_screen_keyboard_shown_event_callback_ = base::Bind(
+      &Application::OnOnScreenKeyboardShownEvent, base::Unretained(this));
+  event_dispatcher_.AddEventCallback(base::OnScreenKeyboardShownEvent::TypeId(),
+                                     on_screen_keyboard_shown_event_callback_);
+  on_screen_keyboard_hidden_event_callback_ = base::Bind(
+      &Application::OnOnScreenKeyboardHiddenEvent, base::Unretained(this));
+  event_dispatcher_.AddEventCallback(
+      base::OnScreenKeyboardHiddenEvent::TypeId(),
+      on_screen_keyboard_hidden_event_callback_);
+#endif  // SB_HAS(ON_SCREEN_KEYBOARD)
 #if defined(ENABLE_WEBDRIVER)
 #if defined(ENABLE_DEBUG_COMMAND_LINE_SWITCHES)
   bool create_webdriver_module =
@@ -742,6 +760,14 @@
               ->size));
       break;
 #endif  // SB_API_VERSION >= SB_WINDOW_SIZE_CHANGED_API_VERSION
+#if SB_HAS(ON_SCREEN_KEYBOARD)
+    case kSbEventTypeOnScreenKeyboardShown:
+      DispatchEventInternal(new base::OnScreenKeyboardShownEvent());
+      break;
+    case kSbEventTypeOnScreenKeyboardHidden:
+      DispatchEventInternal(new base::OnScreenKeyboardHiddenEvent());
+      break;
+#endif  // SB_HAS(ON_SCREEN_KEYBOARD)
     case kSbEventTypeNetworkConnect:
       DispatchEventInternal(
           new network::NetworkEvent(network::NetworkEvent::kConnection));
@@ -861,6 +887,22 @@
 }
 #endif  // SB_API_VERSION >= SB_WINDOW_SIZE_CHANGED_API_VERSION
 
+#if SB_HAS(ON_SCREEN_KEYBOARD)
+void Application::OnOnScreenKeyboardShownEvent(const base::Event* event) {
+  TRACE_EVENT0("cobalt::browser",
+               "Application::OnOnScreenKeyboardShownEvent()");
+  UNREFERENCED_PARAMETER(event);
+  browser_module_->OnOnScreenKeyboardShown();
+}
+
+void Application::OnOnScreenKeyboardHiddenEvent(const base::Event* event) {
+  TRACE_EVENT0("cobalt::browser",
+               "Application::OnOnScreenKeyboardHiddenEvent()");
+  UNREFERENCED_PARAMETER(event);
+  browser_module_->OnOnScreenKeyboardHidden();
+}
+#endif  // SB_HAS(ON_SCREEN_KEYBOARD)
+
 void Application::WebModuleRecreated() {
   TRACE_EVENT0("cobalt::browser", "Application::WebModuleRecreated()");
 #if defined(ENABLE_WEBDRIVER)
diff --git a/src/cobalt/browser/application.h b/src/cobalt/browser/application.h
index 9000883..7ba157d 100644
--- a/src/cobalt/browser/application.h
+++ b/src/cobalt/browser/application.h
@@ -75,6 +75,11 @@
   void OnWindowSizeChangedEvent(const base::Event* event);
 #endif  // SB_API_VERSION >= SB_WINDOW_SIZE_CHANGED_API_VERSION
 
+#if SB_HAS(ON_SCREEN_KEYBOARD)
+  void OnOnScreenKeyboardShownEvent(const base::Event* event);
+  void OnOnScreenKeyboardHiddenEvent(const base::Event* event);
+#endif  // SB_HAS(ON_SCREEN_KEYBOARD)
+
   // Called when a navigation occurs in the BrowserModule.
   void WebModuleRecreated();
 
@@ -93,6 +98,10 @@
 #if SB_API_VERSION >= SB_WINDOW_SIZE_CHANGED_API_VERSION
   base::EventCallback window_size_change_event_callback_;
 #endif  // SB_API_VERSION >= SB_WINDOW_SIZE_CHANGED_API_VERSION
+#if SB_HAS(ON_SCREEN_KEYBOARD)
+  base::EventCallback on_screen_keyboard_shown_event_callback_;
+  base::EventCallback on_screen_keyboard_hidden_event_callback_;
+#endif  // SB_HAS(ON_SCREEN_KEYBOARD)
 
   // Thread checkers to ensure that callbacks for network and application events
   // always occur on the same thread.
diff --git a/src/cobalt/browser/browser_bindings_gen.gyp b/src/cobalt/browser/browser_bindings_gen.gyp
index eea3ab5..5e40285 100644
--- a/src/cobalt/browser/browser_bindings_gen.gyp
+++ b/src/cobalt/browser/browser_bindings_gen.gyp
@@ -108,6 +108,7 @@
         '../dom/html_title_element.idl',
         '../dom/html_unknown_element.idl',
         '../dom/html_video_element.idl',
+        '../dom/input_event.idl',
         '../dom/keyboard_event.idl',
         '../dom/location.idl',
         '../dom/media_error.idl',
@@ -123,6 +124,7 @@
         '../dom/navigator.idl',
         '../dom/node.idl',
         '../dom/node_list.idl',
+        '../dom/on_screen_keyboard.idl',
         '../dom/performance.idl',
         '../dom/performance_timing.idl',
         '../dom/plugin_array.idl',
@@ -229,6 +231,7 @@
         '../dom/event_init.idl',
         '../dom/event_modifier_init.idl',
         '../dom/focus_event_init.idl',
+        '../dom/input_event_init.idl',
         '../dom/keyboard_event_init.idl',
         '../dom/ui_event_init.idl',
         '../dom/media_source_end_of_stream_error.idl',
@@ -288,6 +291,7 @@
         '../dom/window_cssom_view.idl',
         '../dom/window_event_handlers.idl',
         '../dom/window_local_storage.idl',
+        '../dom/window_on_screen_keyboard.idl',
         '../dom/window_session_storage.idl',
         '../dom/window_timers.idl',
         '../media_session/navigator_media_session.idl',
diff --git a/src/cobalt/browser/browser_module.cc b/src/cobalt/browser/browser_module.cc
index bef9c6a..952de6b 100644
--- a/src/cobalt/browser/browser_module.cc
+++ b/src/cobalt/browser/browser_module.cc
@@ -38,6 +38,8 @@
 #include "cobalt/browser/switches.h"
 #include "cobalt/browser/webapi_extension.h"
 #include "cobalt/dom/csp_delegate_factory.h"
+#include "cobalt/dom/input_event_init.h"
+#include "cobalt/dom/keyboard_event_init.h"
 #include "cobalt/dom/keycode.h"
 #include "cobalt/dom/mutation_observer_task_manager.h"
 #include "cobalt/dom/window.h"
@@ -345,7 +347,8 @@
       &network_module_, GetViewportSize(), GetResourceProvider(),
       kLayoutMaxRefreshFrequencyInHz,
       base::Bind(&BrowserModule::GetDebugServer, base::Unretained(this)),
-      options_.web_module_options.javascript_engine_options));
+      options_.web_module_options.javascript_engine_options,
+      base::Bind(&BrowserModule::GetSbWindow, base::Unretained(this))));
   lifecycle_observers_.AddObserver(debug_console_.get());
 #endif  // defined(ENABLE_DEBUG_CONSOLE)
 
@@ -438,7 +441,8 @@
           &network_module_, viewport_size, GetResourceProvider(),
           kLayoutMaxRefreshFrequencyInHz, fallback_splash_screen_url_, url,
           splash_screen_cache_.get(),
-          base::Bind(&BrowserModule::DestroySplashScreen, weak_this_)));
+          base::Bind(&BrowserModule::DestroySplashScreen, weak_this_),
+          base::Bind(&BrowserModule::GetSbWindow, base::Unretained(this))));
       lifecycle_observers_.AddObserver(splash_screen_.get());
     }
   }
@@ -485,6 +489,7 @@
       base::Bind(&BrowserModule::OnError, base::Unretained(this)),
       base::Bind(&BrowserModule::OnWindowClose, base::Unretained(this)),
       base::Bind(&BrowserModule::OnWindowMinimize, base::Unretained(this)),
+      base::Bind(&BrowserModule::GetSbWindow, base::Unretained(this)),
       can_play_type_handler_.get(), media_module_.get(), &network_module_,
       viewport_size, video_pixel_ratio, GetResourceProvider(),
       kLayoutMaxRefreshFrequencyInHz, options));
@@ -724,6 +729,22 @@
 }
 #endif  // SB_API_VERSION >= SB_WINDOW_SIZE_CHANGED_API_VERSION
 
+#if SB_HAS(ON_SCREEN_KEYBOARD)
+void BrowserModule::OnOnScreenKeyboardShown() {
+  // Only inject shown events to the main WebModule.
+  if (web_module_) {
+    web_module_->InjectOnScreenKeyboardShownEvent();
+  }
+}
+
+void BrowserModule::OnOnScreenKeyboardHidden() {
+  // Only inject hidden events to the main WebModule.
+  if (web_module_) {
+    web_module_->InjectOnScreenKeyboardHiddenEvent();
+  }
+}
+#endif  // SB_HAS(ON_SCREEN_KEYBOARD)
+
 #if defined(ENABLE_DEBUG_CONSOLE)
 void BrowserModule::OnFuzzerToggle(const std::string& message) {
   if (MessageLoop::current() != self_message_loop_) {
@@ -802,6 +823,33 @@
 
 #endif  // defined(ENABLE_DEBUG_CONSOLE)
 
+#if SB_HAS(ON_SCREEN_KEYBOARD)
+void BrowserModule::OnOnScreenKeyboardInputEventProduced(
+    base::Token type, const dom::InputEventInit& event) {
+  TRACE_EVENT0("cobalt::browser",
+               "BrowserModule::OnOnScreenKeyboardInputEventProduced()");
+  if (MessageLoop::current() != self_message_loop_) {
+    self_message_loop_->PostTask(
+        FROM_HERE,
+        base::Bind(&BrowserModule::OnOnScreenKeyboardInputEventProduced,
+                   weak_this_, type, event));
+    return;
+  }
+
+#if defined(ENABLE_DEBUG_CONSOLE)
+  // If the debug console is fully visible, it gets the next chance to handle
+  // input events.
+  if (debug_console_->GetMode() >= debug::DebugHub::kDebugConsoleOn) {
+    if (!debug_console_->InjectOnScreenKeyboardInputEvent(type, event)) {
+      return;
+    }
+  }
+#endif  // defined(ENABLE_DEBUG_CONSOLE)
+
+  InjectOnScreenKeyboardInputEventToMainWebModule(type, event);
+}
+#endif  // SB_HAS(ON_SCREEN_KEYBOARD)
+
 void BrowserModule::OnKeyEventProduced(base::Token type,
                                        const dom::KeyboardEventInit& event) {
   TRACE_EVENT0("cobalt::browser", "BrowserModule::OnKeyEventProduced()");
@@ -875,6 +923,30 @@
   web_module_->InjectKeyboardEvent(type, event);
 }
 
+#if SB_HAS(ON_SCREEN_KEYBOARD)
+void BrowserModule::InjectOnScreenKeyboardInputEventToMainWebModule(
+    base::Token type, const dom::InputEventInit& event) {
+  TRACE_EVENT0(
+      "cobalt::browser",
+      "BrowserModule::InjectOnScreenKeyboardInputEventToMainWebModule()");
+  if (MessageLoop::current() != self_message_loop_) {
+    self_message_loop_->PostTask(
+        FROM_HERE,
+        base::Bind(
+            &BrowserModule::InjectOnScreenKeyboardInputEventToMainWebModule,
+            weak_this_, type, event));
+    return;
+  }
+
+#if defined(ENABLE_DEBUG_CONSOLE)
+  trace_manager_.OnInputEventProduced();
+#endif  // defined(ENABLE_DEBUG_CONSOLE)
+
+  DCHECK(web_module_);
+  web_module_->InjectOnScreenKeyboardInputEvent(type, event);
+}
+#endif  // SB_HAS(ON_SCREEN_KEYBOARD)
+
 void BrowserModule::OnError(const GURL& url, const std::string& error) {
   TRACE_EVENT0("cobalt::browser", "BrowserModule::OnError()");
   if (MessageLoop::current() != self_message_loop_) {
@@ -1228,21 +1300,25 @@
   DCHECK(!system_window_);
   system_window_.reset(new system_window::SystemWindow(
       event_dispatcher_, options_.requested_viewport_size));
-
   auto_mem_.reset(new memory_settings::AutoMem(
       GetViewportSize(), options_.command_line_auto_mem_settings,
       options_.build_auto_mem_settings));
   ApplyAutoMemSettings();
 
-  input_device_manager_ = input::InputDeviceManager::CreateFromWindow(
-                              base::Bind(&BrowserModule::OnKeyEventProduced,
-                                         base::Unretained(this)),
-                              base::Bind(&BrowserModule::OnPointerEventProduced,
-                                         base::Unretained(this)),
-                              base::Bind(&BrowserModule::OnWheelEventProduced,
-                                         base::Unretained(this)),
-                              system_window_.get())
-                              .Pass();
+  input_device_manager_ =
+      input::InputDeviceManager::CreateFromWindow(
+          base::Bind(&BrowserModule::OnKeyEventProduced,
+                     base::Unretained(this)),
+          base::Bind(&BrowserModule::OnPointerEventProduced,
+                     base::Unretained(this)),
+          base::Bind(&BrowserModule::OnWheelEventProduced,
+                     base::Unretained(this)),
+#if SB_HAS(ON_SCREEN_KEYBOARD)
+          base::Bind(&BrowserModule::OnOnScreenKeyboardInputEventProduced,
+                     base::Unretained(this)),
+#endif  // SB_HAS(ON_SCREEN_KEYBOARD)
+          system_window_.get())
+          .Pass();
   InstantiateRendererModule();
 
   media_module_ =
diff --git a/src/cobalt/browser/browser_module.h b/src/cobalt/browser/browser_module.h
index 81a3bc3..a2c84df 100644
--- a/src/cobalt/browser/browser_module.h
+++ b/src/cobalt/browser/browser_module.h
@@ -39,6 +39,7 @@
 #include "cobalt/browser/url_handler.h"
 #include "cobalt/browser/web_module.h"
 #include "cobalt/dom/array_buffer.h"
+#include "cobalt/dom/input_event_init.h"
 #include "cobalt/dom/keyboard_event_init.h"
 #include "cobalt/dom/pointer_event_init.h"
 #include "cobalt/dom/wheel_event_init.h"
@@ -61,6 +62,7 @@
 #include "cobalt/debug/debug_server.h"
 #endif  // ENABLE_DEBUG_CONSOLE
 #include "starboard/configuration.h"
+#include "starboard/window.h"
 
 namespace cobalt {
 namespace browser {
@@ -84,7 +86,6 @@
     storage::StorageManager::Options storage_manager_options;
     WebModule::Options web_module_options;
     media::MediaModule::Options media_module_options;
-    std::string language;
     std::string initial_deep_link;
     base::Closure web_module_recreated_callback;
     memory_settings::AutoMemSettings command_line_auto_mem_settings;
@@ -166,6 +167,11 @@
   void OnWindowSizeChanged(const SbWindowSize& size);
 #endif  // SB_API_VERSION >= SB_WINDOW_SIZE_CHANGED_API_VERSION
 
+#if SB_HAS(ON_SCREEN_KEYBOARD)
+  void OnOnScreenKeyboardShown();
+  void OnOnScreenKeyboardHidden();
+#endif  // SB_HAS(ON_SCREEN_KEYBOARD)
+
  private:
 #if SB_HAS(CORE_DUMP_HANDLER_SUPPORT)
   static void CoreDumpHandler(void* browser_module_as_void);
@@ -204,6 +210,14 @@
   // persist the user's preference.
   void SaveDebugConsoleMode();
 
+#if SB_HAS(ON_SCREEN_KEYBOARD)
+  // Glue function to deal with the production of an input event from an on
+  // screen keyboard input device, and manage handing it off to the web module
+  // for interpretation.
+  void OnOnScreenKeyboardInputEventProduced(base::Token type,
+                                            const dom::InputEventInit& event);
+#endif  // SB_HAS(ON_SCREEN_KEYBOARD)
+
   // Glue function to deal with the production of a keyboard input event from a
   // keyboard input device, and manage handing it off to the web module for
   // interpretation.
@@ -221,6 +235,13 @@
   // interpretation.
   void OnWheelEventProduced(base::Token type, const dom::WheelEventInit& event);
 
+#if SB_HAS(ON_SCREEN_KEYBOARD)
+  // Injects an on screen keyboard input event directly into the main web
+  // module.
+  void InjectOnScreenKeyboardInputEventToMainWebModule(
+      base::Token type, const dom::InputEventInit& event);
+#endif  // SB_HAS(ON_SCREEN_KEYBOARD)
+
   // Injects a key event directly into the main web module, useful for setting
   // up an input fuzzer whose input should be sent directly to the main
   // web module and not filtered into the debug console.
diff --git a/src/cobalt/browser/debug_console.cc b/src/cobalt/browser/debug_console.cc
index 2f99e6f..d66fbf9 100644
--- a/src/cobalt/browser/debug_console.cc
+++ b/src/cobalt/browser/debug_console.cc
@@ -167,7 +167,8 @@
     network::NetworkModule* network_module, const math::Size& window_dimensions,
     render_tree::ResourceProvider* resource_provider, float layout_refresh_rate,
     const debug::Debugger::GetDebugServerCallback& get_debug_server_callback,
-    const script::JavaScriptEngine::Options& javascript_engine_options) {
+    const script::JavaScriptEngine::Options& javascript_engine_options,
+    const dom::Window::GetSbWindowCallback& get_sb_window_callback) {
   mode_ = GetInitialMode();
 
   WebModule::Options web_module_options;
@@ -194,9 +195,10 @@
       base::Bind(&DebugConsole::OnError, base::Unretained(this)),
       WebModule::CloseCallback(), /* window_close_callback */
       base::Closure(),            /* window_minimize_callback */
-      NULL /* can_play_type_handler */, NULL /* web_media_player_factory */,
-      network_module, window_dimensions, 1.f /*video_pixel_ratio*/,
-      resource_provider, layout_refresh_rate, web_module_options));
+      get_sb_window_callback, NULL /* can_play_type_handler */,
+      NULL /* web_media_player_factory */, network_module, window_dimensions,
+      1.f /*video_pixel_ratio*/, resource_provider, layout_refresh_rate,
+      web_module_options));
 }
 
 DebugConsole::~DebugConsole() {}
@@ -209,6 +211,16 @@
   return false;
 }
 
+#if SB_HAS(ON_SCREEN_KEYBOARD)
+bool DebugConsole::InjectOnScreenKeyboardInputEvent(
+    base::Token type, const dom::InputEventInit& event) {
+  // Assume here the full debug console is visible - pass all events to its
+  // web module, and return false to indicate the event has been consumed.
+  web_module_->InjectOnScreenKeyboardInputEvent(type, event);
+  return false;
+}
+#endif  // SB_HAS(ON_SCREEN_KEYBOARD)
+
 void DebugConsole::SetMode(int mode) {
   int mode_to_save;
   {
diff --git a/src/cobalt/browser/debug_console.h b/src/cobalt/browser/debug_console.h
index 7d50520..de4b03b 100644
--- a/src/cobalt/browser/debug_console.h
+++ b/src/cobalt/browser/debug_console.h
@@ -25,7 +25,9 @@
 #include "cobalt/browser/lifecycle_observer.h"
 #include "cobalt/browser/web_module.h"
 #include "cobalt/debug/debug_hub.h"
+#include "cobalt/dom/input_event_init.h"
 #include "cobalt/dom/keyboard_event_init.h"
+#include "cobalt/dom/window.h"
 #include "googleurl/src/gurl.h"
 
 namespace cobalt {
@@ -44,7 +46,8 @@
       render_tree::ResourceProvider* resource_provider,
       float layout_refresh_rate,
       const debug::Debugger::GetDebugServerCallback& get_debug_server_callback,
-      const script::JavaScriptEngine::Options& javascript_engine_options);
+      const script::JavaScriptEngine::Options& javascript_engine_options,
+      const dom::Window::GetSbWindowCallback& get_sb_window_callback);
   ~DebugConsole();
 
   // Filters a key event.
@@ -52,6 +55,14 @@
   // false if it was consumed within this function.
   bool FilterKeyEvent(base::Token type, const dom::KeyboardEventInit& event);
 
+#if SB_HAS(ON_SCREEN_KEYBOARD)
+  // Inject an on screen keyboard input event.
+  // Returns true if the event should be passed on to other handlers,
+  // false if it was consumed within this function.
+  bool InjectOnScreenKeyboardInputEvent(base::Token type,
+                                        const dom::InputEventInit& event);
+#endif  // SB_HAS(ON_SCREEN_KEYBOARD)
+
   const WebModule& web_module() const { return *web_module_; }
   WebModule& web_module() { return *web_module_; }
 
diff --git a/src/cobalt/browser/debug_console/command_input.js b/src/cobalt/browser/debug_console/command_input.js
index 08c18b4..50e1264 100644
--- a/src/cobalt/browser/debug_console/command_input.js
+++ b/src/cobalt/browser/debug_console/command_input.js
@@ -40,13 +40,13 @@
 
 // The blinking cursor is always on the character immediately after the
 // insertion/deletion position.
-CommandInput.prototype.insertCharBehindCursor = function(c) {
+CommandInput.prototype.insertStringBehindCursor = function(c) {
   var cmd = this.currCommand;
   var pos = this.cursorPos;
   this.currCommand = cmd.substring(0, pos);
   this.currCommand += c;
   this.currCommand += cmd.substring(pos, cmd.length);
-  this.cursorPos += 1;
+  this.cursorPos += c.length;
   this.updateText();
 }
 
diff --git a/src/cobalt/browser/debug_console/debug_console.js b/src/cobalt/browser/debug_console/debug_console.js
index ed65b9d..129255e 100644
--- a/src/cobalt/browser/debug_console/debug_console.js
+++ b/src/cobalt/browser/debug_console/debug_console.js
@@ -278,7 +278,7 @@
     var c = event.charCode;
     // If we have a printable character, insert it; otherwise ignore.
     if (c >= 0x20 && c <= 0x7e) {
-      commandInput.insertCharBehindCursor(String.fromCharCode(c));
+      commandInput.insertStringBehindCursor(String.fromCharCode(c));
     }
   }
 }
@@ -294,6 +294,16 @@
   }
 }
 
+function onInput(event) {
+  console.log('In DebugConsole onInput, event.data ' + event.data);
+  var mode = window.debugHub.getDebugConsoleMode();
+  if (mode >= window.debugHub.DEBUG_CONSOLE_ON && event.data) {
+    event.preventDefault();
+    event.stopPropagation();
+    commandInput.insertStringBehindCursor(event.data);
+  }
+}
+
 function start() {
   createCommandInput();
   createMessageLog();
@@ -306,6 +316,10 @@
   document.addEventListener('keypress', onKeypress);
   document.addEventListener('keydown', onKeydown);
   document.addEventListener('keyup', onKeyup);
+  if (typeof window.onScreenKeyboard != 'undefined'
+      && window.onScreenKeyboard) {
+    window.onScreenKeyboard.oninput = onInput;
+  }
   curr = window.performance.now();
   window.requestAnimationFrame(animate);
 }
diff --git a/src/cobalt/browser/lib/cobalt.def b/src/cobalt/browser/lib/cobalt.def
index 845c307..2f36ae8 100644
--- a/src/cobalt/browser/lib/cobalt.def
+++ b/src/cobalt/browser/lib/cobalt.def
@@ -8,6 +8,9 @@
     ; From starboard/shared/lib/exported/starboard_main.h:
     StarboardMain
 
+    ; From cobalt/network/lib/user_agent.h:
+    CbLibUserAgentSetPlatformNameSuffix
+
     ; From cobalt/browser/lib/exported/main.h:
     CbLibMainSetCallbackRegistrationReadyCallback
     CbLibMainSetOnCobaltInitializedCallback
diff --git a/src/cobalt/browser/splash_screen.cc b/src/cobalt/browser/splash_screen.cc
index 0c4026b..e1312d1 100644
--- a/src/cobalt/browser/splash_screen.cc
+++ b/src/cobalt/browser/splash_screen.cc
@@ -22,6 +22,7 @@
 #include "base/threading/platform_thread.h"
 #include "base/time.h"
 #include "cobalt/browser/splash_screen_cache.h"
+#include "cobalt/dom/window.h"
 #include "cobalt/loader/cache_fetcher.h"
 
 namespace cobalt {
@@ -60,7 +61,8 @@
     const GURL& initial_main_web_module_url,
     SplashScreenCache* splash_screen_cache,
     const base::Callback<void(base::TimeDelta)>&
-        on_splash_screen_shutdown_complete)
+        on_splash_screen_shutdown_complete,
+    const dom::Window::GetSbWindowCallback& get_sb_window_callback)
     : render_tree_produced_callback_(render_tree_produced_callback),
       self_message_loop_(MessageLoop::current()),
       on_splash_screen_shutdown_complete_(on_splash_screen_shutdown_complete),
@@ -100,9 +102,10 @@
       *url_to_pass, initial_application_state, render_tree_produced_callback_,
       base::Bind(&OnError), on_window_close,
       base::Closure(),  // window_minimize_callback
-      NULL /* can_play_type_handler */, NULL /* web_media_player_factory */,
-      network_module, window_dimensions, 1.f /*video_pixel_ratio*/,
-      resource_provider, layout_refresh_rate, web_module_options));
+      get_sb_window_callback, NULL /* can_play_type_handler */,
+      NULL /* web_media_player_factory */, network_module, window_dimensions,
+      1.f /*video_pixel_ratio*/, resource_provider, layout_refresh_rate,
+      web_module_options));
 }
 
 SplashScreen::~SplashScreen() {
diff --git a/src/cobalt/browser/splash_screen.h b/src/cobalt/browser/splash_screen.h
index 617338d..1c32170 100644
--- a/src/cobalt/browser/splash_screen.h
+++ b/src/cobalt/browser/splash_screen.h
@@ -23,6 +23,7 @@
 #include "cobalt/browser/lifecycle_observer.h"
 #include "cobalt/browser/splash_screen_cache.h"
 #include "cobalt/browser/web_module.h"
+#include "cobalt/dom/window.h"
 #include "googleurl/src/gurl.h"
 
 namespace cobalt {
@@ -43,7 +44,8 @@
                const GURL& initial_main_web_module_url,
                cobalt::browser::SplashScreenCache* splash_screen_cache,
                const base::Callback<void(base::TimeDelta)>&
-                   on_splash_screen_shutdown_complete);
+                   on_splash_screen_shutdown_complete,
+               const dom::Window::GetSbWindowCallback& get_sb_window_callback);
   ~SplashScreen();
 
   void SetSize(const math::Size& window_dimensions, float video_pixel_ratio) {
diff --git a/src/cobalt/browser/switches.cc b/src/cobalt/browser/switches.cc
index def7e22..9d4701d 100644
--- a/src/cobalt/browser/switches.cc
+++ b/src/cobalt/browser/switches.cc
@@ -155,6 +155,11 @@
 const char kRemoteTypefaceCacheSizeInBytes[] =
     "remote_typeface_cache_size_in_bytes";
 
+// Causes the remote typeface cache to be retained when Cobalt is suspended, so
+// that they don't need to be re-downloaded when Cobalt is resumed.
+const char kRetainRemoteTypefaceCacheDuringSuspend[] =
+    "retain_remote_typeface_cache_during_suspend";
+
 // Determines the capacity of the scratch surface cache.  The scratch surface
 // cache facilitates the reuse of temporary offscreen surfaces within a single
 // frame.  This setting is only relevant when using the hardware-accelerated
diff --git a/src/cobalt/browser/switches.h b/src/cobalt/browser/switches.h
index 812b1bc..9b2037d 100644
--- a/src/cobalt/browser/switches.h
+++ b/src/cobalt/browser/switches.h
@@ -55,6 +55,7 @@
 extern const char kLocalStoragePartitionUrl[];
 extern const char kOffscreenTargetCacheSizeInBytes[];
 extern const char kRemoteTypefaceCacheSizeInBytes[];
+extern const char kRetainRemoteTypefaceCacheDuringSuspend[];
 extern const char kScratchSurfaceCacheSizeInBytes[];
 extern const char kSkiaCacheSizeInBytes[];
 extern const char kSoftwareSurfaceCacheSizeInBytes[];
diff --git a/src/cobalt/browser/web_module.cc b/src/cobalt/browser/web_module.cc
index 6a5599a..6719b92 100644
--- a/src/cobalt/browser/web_module.cc
+++ b/src/cobalt/browser/web_module.cc
@@ -27,8 +27,10 @@
 #include "base/message_loop_proxy.h"
 #include "base/optional.h"
 #include "base/stringprintf.h"
+#include "cobalt/base/language.h"
 #include "cobalt/base/startup_timer.h"
 #include "cobalt/base/tokens.h"
+#include "cobalt/base/type_id.h"
 #include "cobalt/browser/splash_screen_cache.h"
 #include "cobalt/browser/stack_size_constants.h"
 #include "cobalt/browser/switches.h"
@@ -40,7 +42,10 @@
 #include "cobalt/dom/element.h"
 #include "cobalt/dom/event.h"
 #include "cobalt/dom/global_stats.h"
+#include "cobalt/dom/input_event.h"
+#include "cobalt/dom/input_event_init.h"
 #include "cobalt/dom/keyboard_event.h"
+#include "cobalt/dom/keyboard_event_init.h"
 #include "cobalt/dom/local_storage_database.h"
 #include "cobalt/dom/mutation_observer_task_manager.h"
 #include "cobalt/dom/pointer_event.h"
@@ -48,6 +53,7 @@
 #include "cobalt/dom/ui_event.h"
 #include "cobalt/dom/url.h"
 #include "cobalt/dom/wheel_event.h"
+#include "cobalt/dom/window.h"
 #include "cobalt/dom_parser/parser.h"
 #include "cobalt/h5vcc/h5vcc.h"
 #include "cobalt/layout/topmost_event_target.h"
@@ -127,6 +133,23 @@
   }
 #endif  // ENABLE_DEBUG_CONSOLE
 
+#if SB_HAS(ON_SCREEN_KEYBOARD)
+  // Called to inject an on screen keyboard input event into the web module.
+  // Event is directed at a specific element if the element is non-null.
+  // Otherwise, the currently focused element receives the event.
+  // If element is specified, we must be on the WebModule's message loop.
+  void InjectOnScreenKeyboardInputEvent(scoped_refptr<dom::Element> element,
+                                        base::Token type,
+                                        const dom::InputEventInit& event);
+  // Called to inject an on screen keyboard input event into the web module.
+  // Event is directed at the on screen keyboard element.
+  void InjectOnScreenKeyboardShownEvent();
+  // Called to inject an on screen keyboard input event into the web module.
+  // Event is directed at the on screen keyboard element.
+  void InjectOnScreenKeyboardHiddenEvent();
+
+#endif  // SB_HAS(ON_SCREEN_KEYBOARD)
+
   // Called to inject a keyboard event into the web module.
   // Event is directed at a specific element if the element is non-null.
   // Otherwise, the currently focused element receives the event.
@@ -151,7 +174,7 @@
 
   // Called to inject a beforeunload event into the web module. If
   // this event is not handled by the web application,
-  // on_before_unload_fired_but_not_handled will be called. The event
+  // |on_before_unload_fired_but_not_handled_| will be called. The event
   // is not directed at a specific element.
   void InjectBeforeUnloadEvent();
 
@@ -219,7 +242,7 @@
   class DocumentLoadedObserver;
 
   // Purge all resource caches owned by the WebModule.
-  void PurgeResourceCaches();
+  void PurgeResourceCaches(bool should_retain_remote_typeface_cache);
 
   // Disable callbacks in all resource caches owned by the WebModule.
   void DisableCallbacksInResourceCaches();
@@ -273,6 +296,9 @@
 
   // Object that provides renderer resources like images and fonts.
   render_tree::ResourceProvider* resource_provider_;
+  // The type id of resource provider being used by the WebModule. Whenever this
+  // changes, the caches may have obsolete data and must be blown away.
+  base::TypeId resource_provider_type_id_;
 
   // CSS parser.
   scoped_ptr<css_parser::Parser> css_parser_;
@@ -378,7 +404,9 @@
 
   scoped_ptr<layout::TopmostEventTarget> topmost_event_target_;
 
-  base::Closure on_before_unload_fired_but_not_handled;
+  base::Closure on_before_unload_fired_but_not_handled_;
+
+  bool should_retain_remote_typeface_cache_on_suspend_;
 };
 
 class WebModule::Impl::DocumentLoadedObserver : public dom::DocumentObserver {
@@ -403,7 +431,8 @@
 WebModule::Impl::Impl(const ConstructionData& data)
     : name_(data.options.name),
       is_running_(false),
-      resource_provider_(data.resource_provider) {
+      resource_provider_(data.resource_provider),
+      resource_provider_type_id_(data.resource_provider->GetTypeId()) {
   // Currently we rely on a platform to explicitly specify that it supports
   // the map-to-mesh filter via the ENABLE_MAP_TO_MESH define (and the
   // 'enable_map_to_mesh' gyp variable).  When we have better support for
@@ -444,9 +473,12 @@
                    base::Unretained(data.options.splash_screen_cache));
   }
 
-  on_before_unload_fired_but_not_handled =
+  on_before_unload_fired_but_not_handled_ =
       data.options.on_before_unload_fired_but_not_handled;
 
+  should_retain_remote_typeface_cache_on_suspend_ =
+      data.options.should_retain_remote_typeface_cache_on_suspend;
+
   fetcher_factory_.reset(new loader::FetcherFactory(
       data.network_module, data.options.extra_web_file_dir,
       dom::URL::MakeBlobResolverCallback(blob_registry_.get()),
@@ -535,6 +567,9 @@
       web_module_stat_tracker_->dom_stat_tracker(), data.initial_url,
       data.network_module->GetUserAgent(),
       data.network_module->preferred_language(),
+      data.options.font_language_script_override.empty()
+          ? base::GetSystemLanguageScript()
+          : data.options.font_language_script_override,
       data.options.navigation_callback,
       base::Bind(&WebModule::Impl::OnError, base::Unretained(this)),
       data.network_module->cookie_jar(), data.network_module->GetPostSender(),
@@ -543,7 +578,8 @@
       base::Bind(&WebModule::Impl::OnRanAnimationFrameCallbacks,
                  base::Unretained(this)),
       data.window_close_callback, data.window_minimize_callback,
-      data.options.camera_3d, media_session_client_->GetMediaSession(),
+      data.get_sb_window_callback, data.options.camera_3d,
+      media_session_client_->GetMediaSession(),
       data.options.csp_insecure_allowed_token, data.dom_max_element_depth,
       data.options.video_playback_rate_multiplier,
 #if defined(ENABLE_TEST_RUNNER)
@@ -680,6 +716,50 @@
       layout_manager_->IsRenderTreePending());
 }
 
+#if SB_HAS(ON_SCREEN_KEYBOARD)
+void WebModule::Impl::InjectOnScreenKeyboardInputEvent(
+    scoped_refptr<dom::Element> element, base::Token type,
+    const dom::InputEventInit& event) {
+  scoped_refptr<dom::InputEvent> input_event(
+      new dom::InputEvent(type, window_, event));
+  InjectInputEvent(element, input_event);
+}
+
+void WebModule::Impl::InjectOnScreenKeyboardShownEvent() {
+  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK(is_running_);
+  DCHECK(window_);
+  DCHECK(window_->on_screen_keyboard());
+
+  scoped_refptr<dom::Event> event = new dom::Event(base::Tokens::show());
+
+  web_module_stat_tracker_->OnStartInjectEvent(event);
+
+  window_->on_screen_keyboard()->DispatchEvent(event);
+
+  web_module_stat_tracker_->OnEndInjectEvent(
+      window_->HasPendingAnimationFrameCallbacks(),
+      layout_manager_->IsRenderTreePending());
+}
+
+void WebModule::Impl::InjectOnScreenKeyboardHiddenEvent() {
+  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK(is_running_);
+  DCHECK(window_);
+  DCHECK(window_->on_screen_keyboard());
+
+  scoped_refptr<dom::Event> event = new dom::Event(base::Tokens::hide());
+
+  web_module_stat_tracker_->OnStartInjectEvent(event);
+
+  window_->on_screen_keyboard()->DispatchEvent(event);
+
+  web_module_stat_tracker_->OnEndInjectEvent(
+      window_->HasPendingAnimationFrameCallbacks(),
+      layout_manager_->IsRenderTreePending());
+}
+#endif  // SB_HAS(ON_SCREEN_KEYBOARD)
+
 void WebModule::Impl::InjectKeyboardEvent(scoped_refptr<dom::Element> element,
                                           base::Token type,
                                           const dom::KeyboardEventInit& event) {
@@ -878,6 +958,14 @@
     render_tree::ResourceProvider* resource_provider) {
   resource_provider_ = resource_provider;
   if (resource_provider_) {
+    base::TypeId resource_provider_type_id = resource_provider_->GetTypeId();
+    // Check for if the resource provider type id has changed. If it has, then
+    // anything contained within the caches is invalid and must be purged.
+    if (resource_provider_type_id_ != resource_provider_type_id) {
+      PurgeResourceCaches(false);
+    }
+    resource_provider_type_id_ = resource_provider_type_id;
+
     loader_factory_->Resume(resource_provider_);
 
     // Permit render trees to be generated again.  Layout will have been
@@ -912,7 +1000,7 @@
 
   // Purge the resource caches before running any suspend logic. This will force
   // any pending callbacks that the caches are batching to run.
-  PurgeResourceCaches();
+  PurgeResourceCaches(should_retain_remote_typeface_cache_on_suspend_);
 
   // Stop the generation of render trees.
   layout_manager_->Suspend();
@@ -941,7 +1029,7 @@
   // Clear out all resource caches. We need to do this after we abort all
   // in-progress loads, and after we clear all document references, or they will
   // still be referenced and won't be cleared from the cache.
-  PurgeResourceCaches();
+  PurgeResourceCaches(should_retain_remote_typeface_cache_on_suspend_);
 
 #if defined(ENABLE_DEBUG_CONSOLE)
   // The debug overlay may be holding onto a render tree, clear that out.
@@ -969,7 +1057,8 @@
     return;
   }
 
-  PurgeResourceCaches();
+  // Retain the remote typeface cache when reducing memory.
+  PurgeResourceCaches(true /*should_retain_remote_typeface_cache*/);
   window_->document()->PurgeCachedResources();
 
   // Force garbage collection in |javascript_engine_|.
@@ -992,8 +1081,8 @@
   //   JS:50250:file.js(29,80): ka(...) is not iterable
   //   JS:<time millis><js-file-name>(<line>,<column>):<message>
   ss << "JS:" << dt.InMilliseconds() << ":" << file_name << "("
-     << source_location.line_number << ","
-     << source_location.column_number << "): " << error_message << "\n";
+     << source_location.line_number << "," << source_location.column_number
+     << "): " << error_message << "\n";
   SbLogRaw(ss.str().c_str());
 }
 
@@ -1001,14 +1090,19 @@
   DCHECK(thread_checker_.CalledOnValidThread());
   if (window_ && window_->HasEventListener(base::Tokens::beforeunload())) {
     window_->DispatchEvent(new dom::Event(base::Tokens::beforeunload()));
-  } else if (!on_before_unload_fired_but_not_handled.is_null()) {
-    on_before_unload_fired_but_not_handled.Run();
+  } else if (!on_before_unload_fired_but_not_handled_.is_null()) {
+    on_before_unload_fired_but_not_handled_.Run();
   }
 }
 
-void WebModule::Impl::PurgeResourceCaches() {
+void WebModule::Impl::PurgeResourceCaches(
+    bool should_retain_remote_typeface_cache) {
   image_cache_->Purge();
-  remote_typeface_cache_->Purge();
+  if (should_retain_remote_typeface_cache) {
+    remote_typeface_cache_->ProcessPendingCallbacks();
+  } else {
+    remote_typeface_cache_->Purge();
+  }
   mesh_cache_->Purge();
 }
 
@@ -1040,6 +1134,7 @@
       animated_image_decode_thread_priority(base::kThreadPriority_Low),
       video_playback_rate_multiplier(1.f),
       enable_image_animations(true),
+      should_retain_remote_typeface_cache_on_suspend(false),
       can_fetch_cache(false) {}
 
 WebModule::WebModule(
@@ -1048,6 +1143,7 @@
     const OnErrorCallback& error_callback,
     const CloseCallback& window_close_callback,
     const base::Closure& window_minimize_callback,
+    const dom::Window::GetSbWindowCallback& get_sb_window_callback,
     media::CanPlayTypeHandler* can_play_type_handler,
     media::WebMediaPlayerFactory* web_media_player_factory,
     network::NetworkModule* network_module, const math::Size& window_dimensions,
@@ -1057,8 +1153,8 @@
   ConstructionData construction_data(
       initial_url, initial_application_state, render_tree_produced_callback,
       error_callback, window_close_callback, window_minimize_callback,
-      can_play_type_handler, web_media_player_factory, network_module,
-      window_dimensions, video_pixel_ratio, resource_provider,
+      get_sb_window_callback, can_play_type_handler, web_media_player_factory,
+      network_module, window_dimensions, video_pixel_ratio, resource_provider,
       kDOMMaxElementDepth, layout_refresh_rate, options);
 
   // Start the dedicated thread and create the internal implementation
@@ -1108,10 +1204,9 @@
   // No posted tasks will be executed once the thread is stopped.
   DestructionObserver destruction_observer(this);
   message_loop()->PostBlockingTask(
-      FROM_HERE,
-      base::Bind(&MessageLoop::AddDestructionObserver,
-                 base::Unretained(message_loop()),
-                 base::Unretained(&destruction_observer)));
+      FROM_HERE, base::Bind(&MessageLoop::AddDestructionObserver,
+                            base::Unretained(message_loop()),
+                            base::Unretained(&destruction_observer)));
 
   // This will cancel the timers for tasks, which help the thread exit
   ClearAllIntervalsAndTimeouts();
@@ -1125,6 +1220,43 @@
   impl_.reset(new Impl(data));
 }
 
+#if SB_HAS(ON_SCREEN_KEYBOARD)
+
+void WebModule::InjectOnScreenKeyboardInputEvent(
+    base::Token type, const dom::InputEventInit& event) {
+  TRACE_EVENT1("cobalt::browser",
+               "WebModule::InjectOnScreenKeyboardInputEvent()", "type",
+               type.c_str());
+  DCHECK(message_loop());
+  DCHECK(impl_);
+  message_loop()->PostTask(
+      FROM_HERE, base::Bind(&WebModule::Impl::InjectOnScreenKeyboardInputEvent,
+                            base::Unretained(impl_.get()),
+                            scoped_refptr<dom::Element>(), type, event));
+}
+
+void WebModule::InjectOnScreenKeyboardShownEvent() {
+  TRACE_EVENT0("cobalt::browser",
+               "WebModule::InjectOnScreenKeyboardShownEvent()");
+  DCHECK(message_loop());
+  DCHECK(impl_);
+  message_loop()->PostTask(
+      FROM_HERE, base::Bind(&WebModule::Impl::InjectOnScreenKeyboardShownEvent,
+                            base::Unretained(impl_.get())));
+}
+
+void WebModule::InjectOnScreenKeyboardHiddenEvent() {
+  TRACE_EVENT0("cobalt::browser",
+               "WebModule::InjectOnScreenKeyboardHiddenEvent()");
+  DCHECK(message_loop());
+  DCHECK(impl_);
+  message_loop()->PostTask(
+      FROM_HERE, base::Bind(&WebModule::Impl::InjectOnScreenKeyboardHiddenEvent,
+                            base::Unretained(impl_.get())));
+}
+
+#endif  // SB_HAS(ON_SCREEN_KEYBOARD)
+
 void WebModule::InjectKeyboardEvent(base::Token type,
                                     const dom::KeyboardEventInit& event) {
   TRACE_EVENT1("cobalt::browser", "WebModule::InjectKeyboardEvent()", "type",
@@ -1171,8 +1303,7 @@
 }
 
 std::string WebModule::ExecuteJavascript(
-    const std::string& script_utf8,
-    const base::SourceLocation& script_location,
+    const std::string& script_utf8, const base::SourceLocation& script_location,
     bool* out_succeeded) {
   TRACE_EVENT0("cobalt::browser", "WebModule::ExecuteJavascript()");
   DCHECK(message_loop());
@@ -1181,10 +1312,10 @@
   base::WaitableEvent got_result(true, false);
   std::string result;
   message_loop()->PostTask(
-      FROM_HERE, base::Bind(&WebModule::Impl::ExecuteJavascript,
-                            base::Unretained(impl_.get()), script_utf8,
-                            script_location, &got_result, &result,
-                            out_succeeded));
+      FROM_HERE,
+      base::Bind(&WebModule::Impl::ExecuteJavascript,
+                 base::Unretained(impl_.get()), script_utf8, script_location,
+                 &got_result, &result, out_succeeded));
   got_result.Wait();
   return result;
 }
@@ -1222,10 +1353,9 @@
 
   scoped_ptr<webdriver::WindowDriver> window_driver;
   message_loop()->PostBlockingTask(
-      FROM_HERE,
-      base::Bind(&WebModule::Impl::CreateWindowDriver,
-                 base::Unretained(impl_.get()), window_id,
-                 base::Unretained(&window_driver)));
+      FROM_HERE, base::Bind(&WebModule::Impl::CreateWindowDriver,
+                            base::Unretained(impl_.get()), window_id,
+                            base::Unretained(&window_driver)));
 
   return window_driver.Pass();
 }
@@ -1238,9 +1368,8 @@
   DCHECK(impl_);
 
   message_loop()->PostBlockingTask(
-      FROM_HERE,
-      base::Bind(&WebModule::Impl::CreateDebugServerIfNull,
-                 base::Unretained(impl_.get())));
+      FROM_HERE, base::Bind(&WebModule::Impl::CreateDebugServerIfNull,
+                            base::Unretained(impl_.get())));
 
   return impl_->debug_server();
 }
@@ -1349,8 +1478,8 @@
   // We must block here so that the call doesn't return until the web
   // application has had a chance to process the whole event.
   message_loop()->PostBlockingTask(FROM_HERE,
-                   base::Bind(&WebModule::Impl::FinishSuspend,
-                              base::Unretained(impl_.get())));
+                                   base::Bind(&WebModule::Impl::FinishSuspend,
+                                              base::Unretained(impl_.get())));
 }
 
 void WebModule::Resume(render_tree::ResourceProvider* resource_provider) {
@@ -1368,9 +1497,9 @@
 
   // We block here so that we block the Low Memory event handler until we have
   // reduced our memory consumption.
-  message_loop()->PostBlockingTask(
-      FROM_HERE, base::Bind(&WebModule::Impl::ReduceMemory,
-                            base::Unretained(impl_.get())));
+  message_loop()->PostBlockingTask(FROM_HERE,
+                                   base::Bind(&WebModule::Impl::ReduceMemory,
+                                              base::Unretained(impl_.get())));
 }
 
 void WebModule::Impl::HandlePointerEvents() {
diff --git a/src/cobalt/browser/web_module.h b/src/cobalt/browser/web_module.h
index b46056f..5807fad 100644
--- a/src/cobalt/browser/web_module.h
+++ b/src/cobalt/browser/web_module.h
@@ -39,6 +39,7 @@
 #include "cobalt/dom/blob.h"
 #include "cobalt/dom/csp_delegate.h"
 #include "cobalt/dom/dom_settings.h"
+#include "cobalt/dom/input_event_init.h"
 #include "cobalt/dom/keyboard_event_init.h"
 #include "cobalt/dom/local_storage_database.h"
 #include "cobalt/dom/media_source.h"
@@ -180,6 +181,15 @@
     // is true to enable them.
     bool enable_image_animations;
 
+    // Whether or not to retain the remote typeface cache when the app enters
+    // the suspend state.
+    bool should_retain_remote_typeface_cache_on_suspend;
+
+    // The language and script to use with fonts. If left empty, then the
+    // language-script combination provided by base::GetSystemLanguageScript()
+    // is used.
+    std::string font_language_script_override;
+
     // The splash screen cache object, owned by the BrowserModule.
     SplashScreenCache* splash_screen_cache;
 
@@ -208,6 +218,7 @@
             const OnErrorCallback& error_callback,
             const CloseCallback& window_close_callback,
             const base::Closure& window_minimize_callback,
+            const dom::Window::GetSbWindowCallback& get_sb_window_callback,
             media::CanPlayTypeHandler* can_play_type_handler,
             media::WebMediaPlayerFactory* web_media_player_factory,
             network::NetworkModule* network_module,
@@ -216,6 +227,17 @@
             float layout_refresh_rate, const Options& options);
   ~WebModule();
 
+#if SB_HAS(ON_SCREEN_KEYBOARD)
+  // Call this to inject an on screen keyboard input event into the web module.
+  // The value for type represents beforeinput or input.
+  void InjectOnScreenKeyboardInputEvent(base::Token type,
+                                        const dom::InputEventInit& event);
+  // Call this to inject an on screen keyboard shown event into the web module.
+  void InjectOnScreenKeyboardShownEvent();
+  // Call this to inject an on screen keyboard hidden event into the web module.
+  void InjectOnScreenKeyboardHiddenEvent();
+#endif  // SB_HAS(ON_SCREEN_KEYBOARD)
+
   // Call this to inject a keyboard event into the web module. The value for
   // type represents the event name, for example 'keydown' or 'keyup'.
   void InjectKeyboardEvent(base::Token type,
@@ -232,7 +254,7 @@
 
   // Call this to inject a beforeunload event into the web module. If
   // this event is not handled by the web application,
-  // on_before_unload_fired_but_not_handled will be called.
+  // |on_before_unload_fired_but_not_handled_| will be called.
   void InjectBeforeUnloadEvent();
 
   // Call this to execute Javascript code in this web module.  The calling
@@ -291,6 +313,7 @@
         const OnErrorCallback& error_callback,
         const CloseCallback& window_close_callback,
         const base::Closure& window_minimize_callback,
+        const dom::Window::GetSbWindowCallback& get_sb_window_callback,
         media::CanPlayTypeHandler* can_play_type_handler,
         media::WebMediaPlayerFactory* web_media_player_factory,
         network::NetworkModule* network_module,
@@ -304,6 +327,7 @@
           error_callback(error_callback),
           window_close_callback(window_close_callback),
           window_minimize_callback(window_minimize_callback),
+          get_sb_window_callback(get_sb_window_callback),
           can_play_type_handler(can_play_type_handler),
           web_media_player_factory(web_media_player_factory),
           network_module(network_module),
@@ -320,6 +344,7 @@
     OnErrorCallback error_callback;
     const CloseCallback& window_close_callback;
     const base::Closure& window_minimize_callback;
+    const dom::Window::GetSbWindowCallback& get_sb_window_callback;
     media::CanPlayTypeHandler* can_play_type_handler;
     media::WebMediaPlayerFactory* web_media_player_factory;
     network::NetworkModule* network_module;
diff --git a/src/cobalt/build/build.id b/src/cobalt/build/build.id
index ed94c45..7ac4971 100644
--- a/src/cobalt/build/build.id
+++ b/src/cobalt/build/build.id
@@ -1 +1 @@
-111497
\ No newline at end of file
+119169
\ No newline at end of file
diff --git a/src/cobalt/build/config/__init__.py b/src/cobalt/build/config/__init__.py
index e741e5b..f9635b0 100644
--- a/src/cobalt/build/config/__init__.py
+++ b/src/cobalt/build/config/__init__.py
@@ -14,6 +14,14 @@
 # limitations under the License.
 """Initialization for the config package."""
 
+import sys
+
+import _env  # pylint: disable=unused-import
+import base
 from base import GetPlatformConfig
-from base import VALID_BUILD_CONFIGS
-from base import VALID_PLATFORMS
+import starboard
+
+# This bit of voodoo fakes out the config.starboard module so that legacy
+# platforms will still GYP properly.
+sys.modules['config.starboard'] = starboard
+starboard.PlatformConfigStarboard = base.PlatformConfigBase
diff --git a/src/cobalt/build/config/base.gni b/src/cobalt/build/config/base.gni
index bf91956..27e69ef 100644
--- a/src/cobalt/build/config/base.gni
+++ b/src/cobalt/build/config/base.gni
@@ -41,38 +41,31 @@
 # Contains the current font package selection.  This can be used to trade
 # font quality, coverage, and latency for different font package sizes.
 # The font package can be one of the following options:
-#   "expanded" -- The largest package. It includes everything in the
-#                 'standard' package, along with 'bold' weight CJK. It is
-#                 recommended that 'local_font_cache_size_in_bytes' be
-#                 increased to 24MB when using this package to account for
-#                 the extra memory required by bold CJK. This package is
-#                 ~48.7MB.
-#   "standard" -- The default package. It includes all sans-serif, serif,
-#                 and FCC fonts, non-CJK fallback fonts in both 'normal' and
-#                 'bold' weights, and 'normal' weight CJK ('bold' weight CJK
-#                 is synthesized from it). This package is ~29.4MB.
-#   "limited_with_jp" -- A significantly smaller package than 'standard'.
-#                 This package removes all but 'normal' and 'bold' weighted
+#   "standard" -- The default package. It includes all sans-serif, serif, and
+#                 FCC fonts, non-CJK fallback fonts in both 'normal' and 'bold'
+#                 weights, 'normal' weight CJK ('bold' weight CJK is synthesized
+#                 from it), and historic script fonts. This package is ~31.4MB.
+#   "limited_with_jp" -- A significantly smaller package than 'standard'. This
+#                 package removes all but 'normal' and 'bold' weighted
 #                 sans-serif and serif, removes the FCC fonts (which must be
-#                 provided by the system or downloaded from the web),
-#                 removes the 'bold' weighted non-CJK fallback fonts (the
-#                 'normal' weight is still included and is used to
-#                 synthesize bold), and replaces standard CJK with low
-#                 quality CJK. However, higher quality Japanese is still
-#                 included. Because low quality CJK cannot synthesize bold,
-#                 bold glyphs are unavailable in Chinese and Korean. This
-#                 package is ~10.9MB.
-#   "limited"  -- A smaller package than 'limited_with_jp'. The two packages
-#                 are identical with the exception that 'limited' does not
-#                 include the higher quality Japanese font; instead it
-#                 relies on low quality CJK for all CJK characters. Because
-#                 low quality CJK cannot synthesize bold, bold glyphs are
-#                 unavailable in Chinese, Japanese, and Korean. This package
-#                 is ~7.7MB.
-#   "minimal"  -- The smallest possible font package. It only includes
-#                 Roboto's Basic Latin characters. Everything else must be
-#                 provided by the system or downloaded from the web. This
-#                 package is ~16.4KB.
+#                 provided by the system or downloaded from the web), removes
+#                 the 'bold' weighted non-CJK fallback fonts (the 'normal'
+#                 weight is still included and is used to synthesize bold), and
+#                 replaces standard CJK with low quality CJK. However, higher
+#                 quality Japanese is still included. Because low quality CJK
+#                 cannot synthesize bold, bold glyphs are unavailable in Chinese
+#                 and Korean. Historic script fonts are not included. This
+#                 package is ~11.5MB.
+#   "limited"  -- A smaller package than 'limited_with_jp'. The two packages are
+#                 identical with the exception that 'limited' does not include
+#                 the higher quality Japanese font; instead it relies on low
+#                 quality CJK for all CJK characters. Because low quality CJK
+#                 cannot synthesize bold, bold glyphs are unavailable in
+#                 Chinese, Japanese, and Korean. This package is ~8.3MB.
+#   "minimal"  -- The smallest possible font package. It only includes Roboto's
+#                 Basic Latin characters. Everything else must be provided by
+#                 the system or downloaded from the web. This package is
+#                 ~40.0KB.
 # NOTE: When bold is needed, but unavailable, it is typically synthesized,
 #       resulting in lower quality glyphs than those generated directly from
 #       a bold font. However, this does not occur with low quality CJK,
@@ -122,6 +115,9 @@
 if (!defined(cobalt_font_package_override_fallback_lang_jp)) {
   cobalt_font_package_override_fallback_lang_jp = -1
 }
+if (!defined(cobalt_font_package_override_fallback_historic)) {
+  cobalt_font_package_override_fallback_historic = -1
+}
 if (!defined(cobalt_font_package_override_fallback_emoji)) {
   cobalt_font_package_override_fallback_emoji = -1
 }
diff --git a/src/cobalt/build/config/base.gypi b/src/cobalt/build/config/base.gypi
index 0614075..ada573c 100644
--- a/src/cobalt/build/config/base.gypi
+++ b/src/cobalt/build/config/base.gypi
@@ -77,16 +77,11 @@
     # Contains the current font package selection.  This can be used to trade
     # font quality, coverage, and latency for different font package sizes.
     # The font package can be one of the following options:
-    #   'expanded' -- The largest package. It includes everything in the
-    #                 'standard' package, along with 'bold' weight CJK. It is
-    #                 recommended that 'local_font_cache_size_in_bytes' be
-    #                 increased to 24MB when using this package to account for
-    #                 the extra memory required by bold CJK. This package is
-    #                 ~48.7MB.
     #   'standard' -- The default package. It includes all sans-serif, serif,
     #                 and FCC fonts, non-CJK fallback fonts in both 'normal' and
-    #                 'bold' weights, and 'normal' weight CJK ('bold' weight CJK
-    #                 is synthesized from it). This package is ~29.4MB.
+    #                 'bold' weights, 'normal' weight CJK ('bold' weight CJK is
+    #                 synthesized from it), and historic script fonts. This
+    #                 package is ~31.4MB.
     #   'limited_with_jp' -- A significantly smaller package than 'standard'.
     #                 This package removes all but 'normal' and 'bold' weighted
     #                 sans-serif and serif, removes the FCC fonts (which must be
@@ -96,19 +91,20 @@
     #                 synthesize bold), and replaces standard CJK with low
     #                 quality CJK. However, higher quality Japanese is still
     #                 included. Because low quality CJK cannot synthesize bold,
-    #                 bold glyphs are unavailable in Chinese and Korean. This
-    #                 package is ~10.9MB.
+    #                 bold glyphs are unavailable in Chinese and Korean.
+    #                 Historic script fonts are not included. This package is
+    #                 ~11.5MB.
     #   'limited'  -- A smaller package than 'limited_with_jp'. The two packages
     #                 are identical with the exception that 'limited' does not
     #                 include the higher quality Japanese font; instead it
     #                 relies on low quality CJK for all CJK characters. Because
     #                 low quality CJK cannot synthesize bold, bold glyphs are
     #                 unavailable in Chinese, Japanese, and Korean. This package
-    #                 is ~7.7MB.
+    #                 is ~8.3MB.
     #   'minimal'  -- The smallest possible font package. It only includes
     #                 Roboto's Basic Latin characters. Everything else must be
     #                 provided by the system or downloaded from the web. This
-    #                 package is ~16.4KB.
+    #                 package is ~40.0KB.
     # NOTE: When bold is needed, but unavailable, it is typically synthesized,
     #       resulting in lower quality glyphs than those generated directly from
     #       a bold font. However, this does not occur with low quality CJK,
@@ -142,6 +138,7 @@
     'cobalt_font_package_override_fallback_lang_cjk%': -1,
     'cobalt_font_package_override_fallback_lang_cjk_low_quality%': -1,
     'cobalt_font_package_override_fallback_lang_jp%': -1,
+    'cobalt_font_package_override_fallback_historic%': -1,
     'cobalt_font_package_override_fallback_emoji%': -1,
     'cobalt_font_package_override_fallback_symbols%': -1,
 
@@ -221,7 +218,7 @@
     # swapping frames may take some additional processing time, so it may be
     # better to specify a lower delay. For example, '33' instead of '33.33'
     # for 30 Hz refresh.
-    'cobalt_minimum_frame_time_in_milliseconds%': '16.4',
+    'cobalt_minimum_frame_time_in_milliseconds%': '16.0',
 
     # Cobalt will call eglSwapInterval() and specify this value before calling
     # eglSwapBuffers() each frame.
diff --git a/src/cobalt/build/config/base.py b/src/cobalt/build/config/base.py
index 612e547..87cabe5 100644
--- a/src/cobalt/build/config/base.py
+++ b/src/cobalt/build/config/base.py
@@ -20,24 +20,10 @@
 import os
 import sys
 
-import gyp_utils
-
-
-class Configs(object):
-  """Strings representing valid build configurations."""
-  DEBUG = 'debug'
-  DEVEL = 'devel'
-  GOLD = 'gold'
-  QA = 'qa'
-
-
-# Represents all valid build configurations.
-VALID_BUILD_CONFIGS = [Configs.DEBUG, Configs.DEVEL, Configs.QA, Configs.GOLD]
-
-# Represents all supported platforms, uniquified and sorted.
-VALID_PLATFORMS = sorted(gyp_utils.GetAllPlatforms().keys())
-
-_CURRENT_PATH = os.path.abspath(os.path.dirname(__file__))
+import _env  # pylint: disable=unused-import
+import cobalt.tools.webdriver_benchmark_config as wb_config
+from starboard.tools import platform
+from starboard.tools.config import Config
 
 
 class PlatformConfigBase(object):
@@ -46,13 +32,10 @@
   Should be derived by platform specific configurations.
   """
 
-  def __init__(self, platform):
-    self.platform = platform
-    self.config_path = _CURRENT_PATH
-
-  def IsStarboard(self):
-    """Returns whether this platform is a Starboard platform."""
-    return False
+  def __init__(self, platform_name, asan_enabled_by_default=False):
+    self.platform = platform_name
+    self.config_path = os.path.abspath(os.path.dirname(__file__))
+    self.asan_default = 1 if asan_enabled_by_default else 0
 
   def GetBuildFormat(self):
     """Returns the desired build format."""
@@ -70,12 +53,11 @@
     Returns:
         A list containing paths to .gypi files.
     """
-    platforms = gyp_utils.GetAllPlatforms()
-    if self.platform in platforms.keys():
-      return [
-          os.path.join(platforms[self.platform].path, 'gyp_configuration.gypi')
-      ]
-    return [os.path.join(self.config_path, self.platform + '.gypi')]
+    platform_info = platform.Get(self.platform)
+    if not platform_info:
+      return []
+
+    return [os.path.join(platform_info.path, 'gyp_configuration.gypi')]
 
   def GetEnvironmentVariables(self):
     """Returns a dict of environment variables.
@@ -88,16 +70,92 @@
     """
     return {}
 
-  def GetVariables(self, config):
+  def GetVariables(self, config_name, use_clang=0):
     """Returns a dict of GYP variables for the given configuration."""
-    _ = config
+    use_asan = 0
+    use_tsan = 0
+    vr_enabled = 0
+    if use_clang:
+      use_tsan = int(os.environ.get('USE_TSAN', 0))
+      # Enable ASAN by default for debug and devel builds only if USE_TSAN was
+      # not set to 1 in the environment.
+      use_asan_default = self.asan_default if not use_tsan and config_name in (
+          Config.DEBUG, Config.DEVEL) else 0
+      use_asan = int(os.environ.get('USE_ASAN', use_asan_default))
+
+      # Set environmental variable to enable_vr: 'USE_VR'
+      # Terminal: `export {varname}={value}`
+      # Note: must also edit gyp_configuration.gypi per internal instructions.
+      vr_on_by_default = 0
+      vr_enabled = int(os.environ.get('USE_VR', vr_on_by_default))
+
+    if use_asan == 1 and use_tsan == 1:
+      raise RuntimeError('ASAN and TSAN are mutually exclusive')
+
+    if use_asan:
+      logging.info('Using ASan Address Sanitizer')
+    if use_tsan:
+      logging.info('Using TSan Thread Sanitizer')
+
+    variables = {
+        # Cobalt uses OpenSSL on all platforms.
+        'use_openssl': 1,
+        'clang': use_clang,
+        # Whether to build with clang's Address Sanitizer instrumentation.
+        'use_asan': use_asan,
+        # Whether to build with clang's Thread Sanitizer instrumentation.
+        'use_tsan': use_tsan,
+        # Whether to enable VR.
+        'enable_vr': vr_enabled,
+    }
+    return variables
+
+  def GetGeneratorVariables(self, config_name):
+    """Returns a dict of generator variables for the given configuration."""
+    del config_name
     return {}
 
-  def GetGeneratorVariables(self, config):
-    """Returns a dict of generator variables for the given configuration."""
-    _ = config
+  def GetToolchain(self):
+    """Returns the instance of the toolchain implementation class."""
+    return None
+
+  def GetTargetToolchain(self):
+    """Returns a list of target tools."""
+    # TODO: If this method throws |NotImplementedError|, GYP will fall back to
+    #       the legacy toolchain. Once all platforms are migrated to the
+    #       abstract toolchain, this method should be made |@abstractmethod|.
+    raise NotImplementedError()
+
+  def GetHostToolchain(self):
+    """Returns a list of host tools."""
+    # TODO: If this method throws |NotImplementedError|, GYP will fall back to
+    #       the legacy toolchain. Once all platforms are migrated to the
+    #       abstract toolchain, this method should be made |@abstractmethod|.
+    raise NotImplementedError()
+
+  def GetTestEnvVariables(self):
+    """Gets a dict of environment variables needed by unit test binaries."""
     return {}
 
+  def WebdriverBenchmarksEnabled(self):
+    """Determines if webdriver benchmarks are enabled or not.
+
+    Returns:
+      True if webdriver benchmarks can run on this platform, False if not.
+    """
+    return False
+
+  def GetDefaultSampleSize(self):
+    return wb_config.STANDARD_SIZE
+
+  def GetWebdriverBenchmarksTargetParams(self):
+    """Gets command line params to pass to the Cobalt executable."""
+    return []
+
+  def GetWebdriverBenchmarksParams(self):
+    """Gets command line params to pass to the webdriver benchmark script."""
+    return []
+
 
 def _ModuleLoaded(module_name, module_path):
   if module_name not in sys.modules:
@@ -109,7 +167,7 @@
   return extensionless_loaded_path == extensionless_module_path
 
 
-def _LoadPlatformConfig(platform):
+def _LoadPlatformConfig(platform_name):
   """Loads a platform specific configuration.
 
   The function will use the provided platform name to load
@@ -117,24 +175,23 @@
   specific configuration.
 
   Args:
-    platform: Platform name.
+    platform_name: Platform name.
 
   Returns:
     Instance of a class derived from PlatformConfigBase.
   """
   try:
-    logging.debug('Loading platform configuration for "%s".', platform)
-    platforms = gyp_utils.GetAllPlatforms()
-    if platform in platforms.keys():
-      platform_path = platforms[platform].path
+    logging.debug('Loading platform configuration for "%s".', platform_name)
+    if platform.IsValid(platform_name):
+      platform_path = platform.Get(platform_name).path
       module_path = os.path.join(platform_path, 'gyp_configuration.py')
       if not _ModuleLoaded('platform_module', module_path):
         platform_module = imp.load_source('platform_module', module_path)
       else:
         platform_module = sys.modules['platform_module']
     else:
-      module_path = 'config/{}.py'.format(platform)
-      platform_module = importlib.import_module('config.{}'.format(platform))
+      module_path = os.path.join('config', '%s.py' % platform_name)
+      platform_module = importlib.import_module('config.%s' % platform_name)
   except ImportError:
     logging.exception('Unable to import "%s".', module_path)
     return None
@@ -151,21 +208,20 @@
 _PLATFORM_CONFIG_DICT = {}
 
 
-def GetPlatformConfig(platform):
+def GetPlatformConfig(platform_name):
   """Returns a platform specific configuration.
 
   This function will return a cached platform configuration object, loading it
   if it doesn't exist via a call to _LoadPlatformConfig().
 
   Args:
-    platform: Platform name.
+    platform_name: Platform name.
 
   Returns:
     Instance of a class derived from PlatformConfigBase.
   """
 
-  global _PLATFORM_CONFIG_DICT
-  if platform not in _PLATFORM_CONFIG_DICT:
-    _PLATFORM_CONFIG_DICT[platform] = _LoadPlatformConfig(platform)
+  if platform_name not in _PLATFORM_CONFIG_DICT:
+    _PLATFORM_CONFIG_DICT[platform_name] = _LoadPlatformConfig(platform_name)
 
-  return _PLATFORM_CONFIG_DICT[platform]
+  return _PLATFORM_CONFIG_DICT[platform_name]
diff --git a/src/cobalt/build/config/starboard.py b/src/cobalt/build/config/starboard.py
deleted file mode 100644
index 34c5760..0000000
--- a/src/cobalt/build/config/starboard.py
+++ /dev/null
@@ -1,115 +0,0 @@
-# Copyright 2016 Google Inc. All Rights Reserved.
-#
-# 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.
-"""Starboard base platform configuration for gyp_cobalt."""
-
-import logging
-import os
-
-import cobalt.tools.webdriver_benchmark_config as wb_config
-from config.base import Configs
-from config.base import PlatformConfigBase
-
-
-class PlatformConfigStarboard(PlatformConfigBase):
-  """Starboard platform configuration."""
-
-  def __init__(self, platform, asan_enabled_by_default=False):
-    super(PlatformConfigStarboard, self).__init__(platform)
-    self.asan_default = 1 if asan_enabled_by_default else 0
-
-  def IsStarboard(self):
-    return True
-
-  def GetEnvironmentVariables(self):
-    return {}
-
-  def GetToolchain(self):
-    """Returns the instance of the toolchain implementation class."""
-    return None
-
-  def GetTargetToolchain(self):
-    """Returns a list of target tools."""
-    # TODO: If this method throws |NotImplementedError|, GYP will fall back to
-    #       the legacy toolchain. Once all platforms are migrated to the
-    #       abstract toolchain, this method should be made |@abstractmethod|.
-    raise NotImplementedError()
-
-  def GetHostToolchain(self):
-    """Returns a list of host tools."""
-    # TODO: If this method throws |NotImplementedError|, GYP will fall back to
-    #       the legacy toolchain. Once all platforms are migrated to the
-    #       abstract toolchain, this method should be made |@abstractmethod|.
-    raise NotImplementedError()
-
-  def GetVariables(self, config, use_clang=0):
-    use_asan = 0
-    use_tsan = 0
-    vr_enabled = 0
-    if use_clang:
-      use_tsan = int(os.environ.get('USE_TSAN', 0))
-      # Enable ASAN by default for debug and devel builds only if USE_TSAN was
-      # not set to 1 in the environment.
-      use_asan_default = self.asan_default if not use_tsan and config in (
-          Configs.DEBUG, Configs.DEVEL) else 0
-      use_asan = int(os.environ.get('USE_ASAN', use_asan_default))
-
-      # Set environmental variable to enable_vr: 'USE_VR'
-      # Terminal: `export {varname}={value}`
-      # Note: must also edit gyp_configuration.gypi per internal instructions.
-      vr_on_by_default = 0
-      vr_enabled = int(os.environ.get('USE_VR', vr_on_by_default))
-
-    if use_asan == 1 and use_tsan == 1:
-      raise RuntimeError('ASAN and TSAN are mutually exclusive')
-
-    if use_asan:
-      logging.info('Using ASan Address Sanitizer')
-    if use_tsan:
-      logging.info('Using TSan Thread Sanitizer')
-
-    variables = {
-        # Cobalt uses OpenSSL on all platforms.
-        'use_openssl': 1,
-        'clang': use_clang,
-        # Whether to build with clang's Address Sanitizer instrumentation.
-        'use_asan': use_asan,
-        # Whether to build with clang's Thread Sanitizer instrumentation.
-        'use_tsan': use_tsan,
-        # Whether to enable VR.
-        'enable_vr': vr_enabled,
-    }
-    return variables
-
-  def GetTestEnvVariables(self):
-    """Gets a dict of environment variables needed by unit test binaries."""
-    return {}
-
-  def WebdriverBenchmarksEnabled(self):
-    """Determines if webdriver benchmarks are enabled or not.
-
-    Returns:
-      True if webdriver benchmarks can run on this platform, False if not.
-    """
-    return False
-
-  def GetDefaultSampleSize(self):
-    return wb_config.STANDARD_SIZE
-
-  def GetWebdriverBenchmarksTargetParams(self):
-    """Gets command line params to pass to the Cobalt executable."""
-    return []
-
-  def GetWebdriverBenchmarksParams(self):
-    """Gets command line params to pass to the webdriver benchmark script."""
-    return []
diff --git a/src/cobalt/build/get_starboard_path.py b/src/cobalt/build/get_starboard_path.py
index 1d32707..a7c741e 100755
--- a/src/cobalt/build/get_starboard_path.py
+++ b/src/cobalt/build/get_starboard_path.py
@@ -18,13 +18,17 @@
 
 import sys
 
-import gyp_utils
+import _env  # pylint: disable=unused-import
+from starboard.tools import platform
 
 
 def main():
-  platforms = gyp_utils.GetAllPlatforms()
-  print platforms[sys.argv[1]].path
+  platform_info = platform.Get(sys.argv[1])
+  if not platform_info:
+    return 1
+  print platform_info.path
+  return 0
 
 
 if __name__ == '__main__':
-  main()
+  sys.exit(main())
diff --git a/src/cobalt/build/gyp_cobalt b/src/cobalt/build/gyp_cobalt
index 4114b07..609e9e1 100755
--- a/src/cobalt/build/gyp_cobalt
+++ b/src/cobalt/build/gyp_cobalt
@@ -22,20 +22,16 @@
 import textwrap
 
 import _env  # pylint: disable=unused-import
-import cobalt
-from cobalt.build import config
+from cobalt.build import config as build_config
 from cobalt.build import gyp_utils
 from cobalt.tools import paths
+from starboard.tools import build
+from starboard.tools import config
+from starboard.tools import platform
 
 
 SCRIPT_DIR = os.path.abspath(os.path.dirname(__file__))
 
-# Represents all valid build configurations.
-VALID_BUILD_CONFIGS = config.VALID_BUILD_CONFIGS
-
-# Represents all supported platforms.
-VALID_PLATFORMS = config.VALID_PLATFORMS
-
 # Return values used by main().
 RETVAL_SUCCESS = 0
 RETVAL_ERROR = 1
@@ -71,13 +67,15 @@
       formatter_class=argparse.RawDescriptionHelpFormatter,
       description=textwrap.dedent(__doc__))
 
+  default_config, _ = build.GetDefaultConfigAndPlatform()
   parser.add_argument('-C', '--config', dest='build_configs', metavar='CONFIG',
-                      action='append', default=[],
-                      choices=VALID_BUILD_CONFIGS,
+                      action='append',
+                      choices=config.GetAll(),
+                      default=[default_config] if default_config else [],
                       help='Specifies build configurations. Supported '
                       'configurations are %s. Can be specified multiple '
                       'times, creates all configurations if nothing is '
-                      'given.' % _ListAsString(VALID_BUILD_CONFIGS))
+                      'given.' % _ListAsString(config.GetAll()))
 
   gyp_debug_options = gyp_utils.GypDebugOptions()
   parser.add_argument('-D', '--debug', dest='debug', metavar='DEBUGMODE',
@@ -92,10 +90,12 @@
   parser.add_argument('-v', '--verbose', dest='verbose_count',
                       default=0, action='count',
                       help='Verbose level (multiple times for more).')
-  parser.add_argument('platform', choices=VALID_PLATFORMS,
+  # TODO: Figure out how to set a default platform, which probably means making
+  # platform no longer be a positional argument.
+  parser.add_argument('platform', choices=platform.GetAll(),
                       metavar='platform',
                       help='Target platform. Supported platforms are: %s.' % (
-                          _ListAsString(VALID_PLATFORMS)))
+                          _ListAsString(platform.GetAll())))
   parser.add_argument('build_file', nargs='?',
                       default=os.path.join(SCRIPT_DIR, 'all.gyp'),
                       help='GYP build file. Uses all.gyp if nothing is given.')
@@ -106,7 +106,7 @@
     # Get rid of duplicates.
     options.build_configs = list(set(options.build_configs))
   else:
-    options.build_configs = VALID_BUILD_CONFIGS
+    options.build_configs = config.GetAll()
 
   return options
 
@@ -144,7 +144,7 @@
   def __init__(self, options):
     self.options = options
     self.common_args = []
-    self.platform_config = config.GetPlatformConfig(options.platform)
+    self.platform_config = build_config.GetPlatformConfig(options.platform)
     if not self.platform_config:
       raise RuntimeError('Unable to load platform configuration.')
 
@@ -227,23 +227,21 @@
 
     # Append GYP variables
     variables = {
-        'OS': 'lb_shell',
+        'OS': 'starboard',
         'cobalt_fastbuild': os.environ.get('LB_FASTBUILD', 0),
         'cobalt_version': gyp_utils.GetBuildNumber(),
         'host_os': _GetHostOS(),
         'CC_HOST': os.environ.get('CC_HOST', os.environ.get('CC','')),
     }
-    if self.platform_config.IsStarboard():
-      variables['OS'] = 'starboard'
-      platform = self.platform_config.platform
-      platforms = gyp_utils.GetAllPlatforms()
-      if platform in platforms.keys():
-        full_starboard_path = platforms[platform].path
-        assert full_starboard_path[:len(source_tree_dir)] == source_tree_dir
-        starboard_path = full_starboard_path[len(source_tree_dir) + 1:]
-        starboard_path = starboard_path.replace(os.sep, '/')
-        assert starboard_path[0] not in [ os.sep, os.altsep ]
-        variables['starboard_path'] = starboard_path
+
+    platform_name = self.platform_config.platform
+    if platform.IsValid(platform_name):
+      full_starboard_path = platform.Get(platform_name).path
+      assert full_starboard_path[:len(source_tree_dir)] == source_tree_dir
+      starboard_path = full_starboard_path[len(source_tree_dir) + 1:]
+      starboard_path = starboard_path.replace(os.sep, '/')
+      assert starboard_path[0] not in [ os.sep, os.altsep ]
+      variables['starboard_path'] = starboard_path
     _AppendVariables(variables, self.common_args)
 
     # Append generator variables.
diff --git a/src/cobalt/build/gyp_utils.py b/src/cobalt/build/gyp_utils.py
index e9b89b2..9e8d472 100644
--- a/src/cobalt/build/gyp_utils.py
+++ b/src/cobalt/build/gyp_utils.py
@@ -26,7 +26,6 @@
 
 import _env  # pylint: disable=unused-import
 from cobalt.tools import paths
-from starboard.tools import platform
 
 _CLANG_REVISION = '298539-1'
 _CLANG_VERSION = '5.0.0'
@@ -36,13 +35,6 @@
 _VERSION_SERVER_URL = 'https://carbon-airlock-95823.appspot.com/build_version/generate'  # pylint:disable=line-too-long
 _XSSI_PREFIX = ")]}'\n"
 
-# The list of directories, relative to "src/", to search through for ports.
-_PORT_SEARCH_PATH = [
-    'starboard',
-    os.path.join('starboard', 'port'),
-    os.path.join('third_party', 'starboard'),
-]
-
 # The path to the build.id file that preserves a build ID.
 BUILD_ID_PATH = os.path.abspath(os.path.join(_SCRIPT_DIR, 'build.id'))
 
@@ -275,50 +267,3 @@
   expression = match.group(1)
   value = eval(expression)  # pylint:disable=eval-used
   return value
-
-
-def _FindAllPlatforms():
-  """Workhorse for GetAllPlatforms().
-
-  Search through directories listed in _PORT_SEARCH_PATH to find valid
-  ports, so that they can be added to the VALID_PLATFORMS list. This
-  allows gyp_cobalt to register new ports without needing to modify
-  code in src/cobalt/.
-
-  Returns:
-    A dictionary of name->PlatformInfo.
-
-  """
-
-  result = {}
-  search_path = [os.path.realpath(os.path.join(paths.REPOSITORY_ROOT, x))
-                 for x in _PORT_SEARCH_PATH]
-
-  # Ignore search path directories inside other search path directories.
-  exclusion_set = set(search_path)
-
-  for entry in search_path:
-    if not os.path.isdir(entry):
-      continue
-    for platform_info in platform.PlatformInfo.EnumeratePorts(entry,
-                                                              exclusion_set):
-      if platform_info.port_name in result:
-        logging.error('Found duplicate port name "%s" at "%s" and "%s"',
-                      platform_info.port_name, result[platform_info.port_name],
-                      platform_info.path)
-      result[platform_info.port_name] = platform_info
-
-  return result
-
-
-# Global cache of TPP so the filesystem walk is only done once, and the values
-# are always consistent.
-_ALL_PLATFORMS = None
-
-
-def GetAllPlatforms():
-  """Return valid platform definitions found by scanning the source tree."""
-  global _ALL_PLATFORMS
-  if _ALL_PLATFORMS is None:
-    _ALL_PLATFORMS = _FindAllPlatforms()
-  return _ALL_PLATFORMS
diff --git a/src/cobalt/build/sync_to_build_id.py b/src/cobalt/build/sync_to_build_id.py
index 8ff7f50..66282cc 100755
--- a/src/cobalt/build/sync_to_build_id.py
+++ b/src/cobalt/build/sync_to_build_id.py
@@ -86,8 +86,11 @@
       description="Syncs to a given Cobalt build id")
   arg_parser.add_argument("buildid", nargs=1)
   args = arg_parser.parse_args()
-  r = requests.get(_BUILD_ID_QUERY_URL,
-                   params={_BUILD_ID_QUERY_PARAMETER_NAME: args.buildid[0]})
+  r = requests.get(
+      _BUILD_ID_QUERY_URL,
+      params={
+          _BUILD_ID_QUERY_PARAMETER_NAME: args.buildid[0]
+      })
   if not r.ok:
     print(
         "HTTP request failed\n{0} {1}\n{2}".format(r.status_code, r.reason,
@@ -101,10 +104,15 @@
 
   for relpath, rep_hash in hashes.iteritems():
     path = os.path.join(gclient_root, relpath)
-    is_dirty = (bool(
-        _RunGitCommandReturnExitCode(
-            ["diff", "--no-ext-diff", "--quiet"], cwd=path, stderr=dev_null)[0])
-                or bool(
+    if not os.path.exists(path):
+      # No warning in this case, we will attempt to clone the repository in
+      # the next pass through the repos.
+      continue
+    is_dirty = (
+        bool(
+            _RunGitCommandReturnExitCode(
+                ["diff", "--no-ext-diff", "--quiet"], cwd=path,
+                stderr=dev_null)[0]) or bool(
                     _RunGitCommandReturnExitCode(
                         ["diff", "--no-ext-diff", "--quiet", "--cached"],
                         cwd=path,
@@ -116,10 +124,22 @@
 
   for relpath, rep_hash in hashes.iteritems():
     path = os.path.join(gclient_root, relpath)
+
     # repo_hash has a repo path prefix like this:
     # 'https://chromium.googlesource.com/chromium/llvm-project/libcxx.git
     # @48198f9110397fff47fe7c37cbfa296be7d44d3d'
-    requested_hash = rep_hash[rep_hash.rindex("@") + 1:]
+    (requested_repo, requested_hash) = rep_hash.split("@")
+
+    if not os.path.exists(path):
+      print("Missing path {0}, cloning from {1}.".format(path, requested_repo))
+      try:
+        # The clone command will create all missing directories leading to the
+        # path.  If the clone is successful, we continue on as usual and let
+        # the subsequent logic here checkout the appropriate git hash.
+        _RunGitCommand(["clone", "-q", requested_repo, path])
+      except SubprocessFailedException:
+        print("There was an error cloning the repository.")
+        continue
 
     current_hash = _RunGitCommand(["rev-parse", "HEAD"], cwd=path)[0]
 
diff --git a/src/cobalt/content/fonts/README.md b/src/cobalt/content/fonts/README.md
index 1181646..bedae90 100644
--- a/src/cobalt/content/fonts/README.md
+++ b/src/cobalt/content/fonts/README.md
@@ -41,27 +41,10 @@
     }
 
 ### Package Profiles
-*  'expanded' -- The largest package. It includes everything in the 'standard'
-                 package, along with 'bold' weight CJK. It is recommended that
-                 'local_font_cache_size_in_bytes' be increased to 24MB when
-                 using this package to account for the extra memory required by
-                 bold CJK. This package is ~48.7MB.
-
-                 Package category values:
-                   'package_named_sans_serif': 4,
-                   'package_named_serif': 3,
-                   'package_named_fcc_fonts': 2,
-                   'package_fallback_lang_non_cjk': 2,
-                   'package_fallback_lang_cjk': 2,
-                   'package_fallback_lang_cjk_low_quality': 0,
-                   'package_fallback_lang_jp': 0,
-                   'package_fallback_emoji': 1,
-                   'package_fallback_symbols': 1,
-
 *  'standard' -- The default package. It includes all sans-serif, serif, and FCC
                  fonts, non-CJK fallback fonts in both 'normal' and 'bold'
-                 weights, and 'normal' weight CJK ('bold' weight CJK is
-                 synthesized from it). This package is ~29.4MB.
+                 weights, 'normal' weight CJK ('bold' weight CJK is synthesized
+                 from it), and historic script fonts. This package is ~31.4MB.
 
                  Package category values:
                   'package_named_sans_serif': 4,
@@ -71,6 +54,7 @@
                   'package_fallback_lang_cjk': 1,
                   'package_fallback_lang_cjk_low_quality': 0,
                   'package_fallback_lang_jp': 0,
+                  'package_fallback_historic': 1,
                   'package_fallback_emoji': 1,
                   'package_fallback_symbols': 1,
 
@@ -82,8 +66,8 @@
                  and is used to synthesize bold), and replaces standard CJK with
                  low quality CJK. However, higher quality Japanese is still
                  included. Because low quality CJK cannot synthesize bold, bold
-                 glyphs are unavailable in Chinese and Korean. This package is
-                 ~10.9MB.
+                 glyphs are unavailable in Chinese and Korean. Historic script
+                 fonts are not included. This package is ~11.5MB.
 
                  Package category values:
                   'package_named_sans_serif': 2,
@@ -93,6 +77,7 @@
                   'package_fallback_lang_cjk': 0,
                   'package_fallback_lang_cjk_low_quality': 1,
                   'package_fallback_lang_jp': 1,
+                  'package_fallback_historic': 0,
                   'package_fallback_emoji': 1,
                   'package_fallback_symbols': 1,
 
@@ -101,7 +86,7 @@
                  the higher quality Japanese font; instead it relies on low
                  quality CJK for all CJK characters. Because low quality CJK
                  cannot synthesize bold, bold glyphs are unavailable in Chinese,
-                 Japanese, and Korean. This package is ~7.7MB.
+                 Japanese, and Korean. This package is ~8.3MB.
 
                  Package category values:
                   'package_named_sans_serif': 2,
@@ -111,12 +96,13 @@
                   'package_fallback_lang_cjk': 0,
                   'package_fallback_lang_cjk_low_quality': 1,
                   'package_fallback_lang_jp': 0,
+                  'package_fallback_historic': 0,
                   'package_fallback_emoji': 1,
                   'package_fallback_symbols': 1,
 
 *  'minimal'  -- The smallest possible font package. It only includes Roboto's
                  Basic Latin characters. Everything else must be provided by the
-                 system or downloaded from the web. This package is ~16.4KB.
+                 system or downloaded from the web. This package is ~40.0KB.
 
                  Package category values:
                   'package_named_sans_serif': 0,
@@ -126,6 +112,7 @@
                   'package_fallback_lang_cjk': 0,
                   'package_fallback_lang_cjk_low_quality': 0,
                   'package_fallback_lang_jp': 0,
+                  'package_fallback_historic': 0,
                   'package_fallback_emoji': 0,
                   'package_fallback_symbols': 0,
 
@@ -164,6 +151,9 @@
        Higher quality Japanese language-specific fallback fonts. These should
        only be included when 'package_fallback_lang_cjk' has a value of '0'.
 
+  *  'package_fallback_historic':
+       Historic script fallback fonts.
+
   *  'package_fallback_emoji':
        Emoji-related fallback fonts.
 
diff --git a/src/cobalt/content/fonts/config/android/fonts.xml b/src/cobalt/content/fonts/config/android/fonts.xml
index 451441d..2f655fc 100644
--- a/src/cobalt/content/fonts/config/android/fonts.xml
+++ b/src/cobalt/content/fonts/config/android/fonts.xml
@@ -245,6 +245,12 @@
         <font weight="700" style="normal">NotoSansCham-Bold.ttf</font>
     </family>
     <family>
+        <font weight="400" style="normal">NotoSansAdlam-Regular.ttf</font>
+    </family>
+    <family>
+        <font weight="400" style="normal">NotoSansAvestan-Regular.ttf</font>
+    </family>
+    <family>
         <font weight="400" style="normal">NotoSansBalinese-Regular.ttf</font>
     </family>
     <family>
@@ -254,6 +260,9 @@
         <font weight="400" style="normal">NotoSansBatak-Regular.ttf</font>
     </family>
     <family>
+        <font weight="400" style="normal">NotoSansBrahmi-Regular.ttf</font>
+    </family>
+    <family>
         <font weight="400" style="normal">NotoSansBuginese-Regular.ttf</font>
     </family>
     <family>
@@ -263,33 +272,75 @@
         <font weight="400" style="normal">NotoSansCanadianAboriginal-Regular.ttf</font>
     </family>
     <family>
+        <font weight="400" style="normal">NotoSansCarian-Regular.ttf</font>
+    </family>
+    <family>
         <font weight="400" style="normal">NotoSansCherokee-Regular.ttf</font>
     </family>
     <family>
         <font weight="400" style="normal">NotoSansCoptic-Regular.ttf</font>
     </family>
     <family>
+        <font weight="400" style="normal">NotoSansCuneiform-Regular.ttf</font>
+    </family>
+    <family>
+        <font weight="400" style="normal">NotoSansCypriot-Regular.ttf</font>
+    </family>
+    <family>
+        <font weight="400" style="normal">NotoSansDeseret-Regular.ttf</font>
+    </family>
+    <family>
+        <font weight="400" style="normal">NotoSansEgyptianHieroglyphs-Regular.ttf</font>
+    </family>
+    <family>
         <font weight="400" style="normal">NotoSansGlagolitic-Regular.ttf</font>
     </family>
     <family>
+        <font weight="400" style="normal">NotoSansGothic-Regular.ttf</font>
+    </family>
+    <family>
         <font weight="400" style="normal">NotoSansHanunoo-Regular.ttf</font>
     </family>
     <family>
+        <font weight="400" style="normal">NotoSansImperialAramaic-Regular.ttf</font>
+    </family>
+    <family>
+        <font weight="400" style="normal">NotoSansInscriptionalPahlavi-Regular.ttf</font>
+    </family>
+    <family>
+        <font weight="400" style="normal">NotoSansInscriptionalParthian-Regular.ttf</font>
+    </family>
+    <family>
         <font weight="400" style="normal">NotoSansJavanese-Regular.ttf</font>
     </family>
     <family>
+        <font weight="400" style="normal">NotoSansKaithi-Regular.ttf</font>
+    </family>
+    <family>
         <font weight="400" style="normal">NotoSansKayahLi-Regular.ttf</font>
     </family>
     <family>
+        <font weight="400" style="normal">NotoSansKharoshthi-Regular.ttf</font>
+    </family>
+    <family>
         <font weight="400" style="normal">NotoSansLepcha-Regular.ttf</font>
     </family>
     <family>
         <font weight="400" style="normal">NotoSansLimbu-Regular.ttf</font>
     </family>
     <family>
+        <font weight="400" style="normal">NotoSansLinearB-Regular.ttf</font>
+    </family>
+    <family>
         <font weight="400" style="normal">NotoSansLisu-Regular.ttf</font>
     </family>
     <family>
+        <font weight="400" style="normal">NotoSansLycian-Regular.ttf</font>
+    </family>
+    <family>
+        <font weight="400" style="normal">NotoSansLydian-Regular.ttf</font>
+    </family>
+    <family>
         <font weight="400" style="normal">NotoSansMandaic-Regular.ttf</font>
     </family>
     <family>
@@ -302,24 +353,64 @@
         <font weight="400" style="normal">NotoSansNKo-Regular.ttf</font>
     </family>
     <family>
+        <font weight="400" style="normal">NotoSansOgham-Regular.ttf</font>
+    </family>
+    <family>
         <font weight="400" style="normal">NotoSansOlChiki-Regular.ttf</font>
     </family>
     <family>
+        <font weight="400" style="normal">NotoSansOldItalic-Regular.ttf</font>
+    </family>
+    <family>
+        <font weight="400" style="normal">NotoSansOldPersian-Regular.ttf</font>
+    </family>
+    <family>
+        <font weight="400" style="normal">NotoSansOldSouthArabian-Regular.ttf</font>
+    </family>
+    <family>
+        <font weight="400" style="normal">NotoSansOldTurkic-Regular.ttf</font>
+    </family>
+    <family>
+        <font weight="400" style="normal">NotoSansOsmanya-Regular.ttf</font>
+    </family>
+    <family>
+        <font weight="400" style="normal">NotoSansPhoenician-Regular.ttf</font>
+    </family>
+    <family>
         <font weight="400" style="normal">NotoSansRejang-Regular.ttf</font>
     </family>
     <family>
+        <font weight="400" style="normal">NotoSansRunic-Regular.ttf</font>
+    </family>
+    <family>
+        <font weight="400" style="normal">NotoSansSamaritan-Regular.ttf</font>
+    </family>
+    <family>
         <font weight="400" style="normal">NotoSansSaurashtra-Regular.ttf</font>
     </family>
     <family>
+        <font weight="400" style="normal">NotoSansShavian-Regular.ttf</font>
+    </family>
+    <family>
         <font weight="400" style="normal">NotoSansSundanese-Regular.ttf</font>
     </family>
     <family>
         <font weight="400" style="normal">NotoSansSylotiNagri-Regular.ttf</font>
     </family>
+    <!-- Estrangela should precede Eastern and Western Syriac, since it's our default form. -->
     <family>
         <font weight="400" style="normal">NotoSansSyriacEstrangela-Regular.ttf</font>
     </family>
     <family>
+        <font weight="400" style="normal">NotoSansSyriacEastern-Regular.ttf</font>
+    </family>
+    <family>
+        <font weight="400" style="normal">NotoSansSyriacWestern-Regular.ttf</font>
+    </family>
+    <family>
+        <font weight="400" style="normal">NotoSansTagalog-Regular.ttf</font>
+    </family>
+    <family>
         <font weight="400" style="normal">NotoSansTagbanwa-Regular.ttf</font>
     </family>
     <family>
@@ -336,10 +427,10 @@
         <font weight="400" style="normal">NotoSansTifinagh-Regular.ttf</font>
     </family>
     <family>
-        <font weight="400" style="normal">NotoSansVai-Regular.ttf</font>
+        <font weight="400" style="normal">NotoSansUgaritic-Regular.ttf</font>
     </family>
     <family>
-        <font weight="400" style="normal">NotoSansYi-Regular.ttf</font>
+        <font weight="400" style="normal">NotoSansVai-Regular.ttf</font>
     </family>
     <family>
         <font weight="400" style="normal">Lohit-Odia.ttf</font>
@@ -400,13 +491,19 @@
         <font weight="400" style="normal">MTLmr3m.ttf</font>
     </family>
     <!--
-        Tai Le and Mongolian are intentionally kept last, to make sure they don't override
-        the East Asian punctuation for Chinese.
+        Tai Le, Yi, Mongolian, and Phags-pa are intentionally kept last, to make sure they don't
+        override the East Asian punctuation for Chinese.
     -->
     <family>
         <font weight="400" style="normal">NotoSansTaiLe-Regular.ttf</font>
     </family>
     <family>
+        <font weight="400" style="normal">NotoSansYi-Regular.ttf</font>
+    </family>
+    <family>
         <font weight="400" style="normal">NotoSansMongolian-Regular.ttf</font>
     </family>
+    <family>
+        <font weight="400" style="normal">NotoSansPhagsPa-Regular.ttf</font>
+    </family>
 </familyset>
diff --git a/src/cobalt/content/fonts/config/common/fonts.xml b/src/cobalt/content/fonts/config/common/fonts.xml
index b60cc92..afbd1bb 100644
--- a/src/cobalt/content/fonts/config/common/fonts.xml
+++ b/src/cobalt/content/fonts/config/common/fonts.xml
@@ -164,7 +164,7 @@
         <font weight="400" style="normal">NotoSansThaiUI-Regular.ttf</font>
         <font weight="700" style="normal">NotoSansThaiUI-Bold.ttf</font>
     </family>
-    <family pages="0,5,251,254">
+    <family pages="0,5,32,251">
         <font weight="400" style="normal">NotoSansArmenian-Regular.ttf</font>
         <font weight="700" style="normal">NotoSansArmenian-Bold.ttf</font>
     </family>
@@ -234,6 +234,12 @@
         <font weight="400" style="normal">NotoSansCham-Regular.ttf</font>
         <font weight="700" style="normal">NotoSansCham-Bold.ttf</font>
     </family>
+    <family pages="0,6,32,46,489">
+        <font weight="400" style="normal">NotoSansAdlam-Regular.ttf</font>
+    </family>
+    <family pages="0,32,46,254,267">
+        <font weight="400" style="normal">NotoSansAvestan-Regular.ttf</font>
+    </family>
     <family pages="0,27,32,37,254">
         <font weight="400" style="normal">NotoSansBalinese-Regular.ttf</font>
     </family>
@@ -243,6 +249,9 @@
     <family pages="0,27,254">
         <font weight="400" style="normal">NotoSansBatak-Regular.ttf</font>
     </family>
+    <family pages="0,254,272">
+        <font weight="400" style="normal">NotoSansBrahmi-Regular.ttf</font>
+    </family>
     <family pages="0,26,32,37,169,254">
         <font weight="400" style="normal">NotoSansBuginese-Regular.ttf</font>
     </family>
@@ -252,33 +261,75 @@
     <family pages="0-3,20-22,24,254">
         <font weight="400" style="normal">NotoSansCanadianAboriginal-Regular.ttf</font>
     </family>
-    <family pages="0,19,254">
+    <family pages="0,254,258">
+        <font weight="400" style="normal">NotoSansCarian-Regular.ttf</font>
+    </family>
+    <family pages="0,3,19,171">
         <font weight="400" style="normal">NotoSansCherokee-Regular.ttf</font>
     </family>
     <family pages="0,3,29,37,44,254">
         <font weight="400" style="normal">NotoSansCoptic-Regular.ttf</font>
     </family>
+    <family pages="0,254,288-292">
+        <font weight="400" style="normal">NotoSansCuneiform-Regular.ttf</font>
+    </family>
+    <family pages="0,254,264">
+        <font weight="400" style="normal">NotoSansCypriot-Regular.ttf</font>
+    </family>
+    <family pages="0,254,260">
+        <font weight="400" style="normal">NotoSansDeseret-Regular.ttf</font>
+    </family>
+    <family pages="0,254,304-308">
+        <font weight="400" style="normal">NotoSansEgyptianHieroglyphs-Regular.ttf</font>
+    </family>
     <family pages="0,44,254">
         <font weight="400" style="normal">NotoSansGlagolitic-Regular.ttf</font>
     </family>
+    <family pages="0,3,254,259">
+        <font weight="400" style="normal">NotoSansGothic-Regular.ttf</font>
+    </family>
     <family pages="0,23,254">
         <font weight="400" style="normal">NotoSansHanunoo-Regular.ttf</font>
     </family>
+    <family pages="0,254,264">
+        <font weight="400" style="normal">NotoSansImperialAramaic-Regular.ttf</font>
+    </family>
+    <family pages="0,254,267">
+        <font weight="400" style="normal">NotoSansInscriptionalPahlavi-Regular.ttf</font>
+    </family>
+    <family pages="0,254,267">
+        <font weight="400" style="normal">NotoSansInscriptionalParthian-Regular.ttf</font>
+    </family>
     <family pages="0,32,37,169,254">
         <font weight="400" style="normal">NotoSansJavanese-Regular.ttf</font>
     </family>
+    <family pages="0,9,168,254,272">
+        <font weight="400" style="normal">NotoSansKaithi-Regular.ttf</font>
+    </family>
     <family pages="0,169,254">
         <font weight="400" style="normal">NotoSansKayahLi-Regular.ttf</font>
     </family>
+    <family pages="0,254,266">
+        <font weight="400" style="normal">NotoSansKharoshthi-Regular.ttf</font>
+    </family>
     <family pages="0,28,37,254">
         <font weight="400" style="normal">NotoSansLepcha-Regular.ttf</font>
     </family>
     <family pages="0,9,25,254">
         <font weight="400" style="normal">NotoSansLimbu-Regular.ttf</font>
     </family>
+    <family pages="0,254,256-257">
+        <font weight="400" style="normal">NotoSansLinearB-Regular.ttf</font>
+    </family>
     <family pages="0,2,164,254">
         <font weight="400" style="normal">NotoSansLisu-Regular.ttf</font>
     </family>
+    <family pages="0,254,258">
+        <font weight="400" style="normal">NotoSansLycian-Regular.ttf</font>
+    </family>
+    <family pages="0,254,265">
+        <font weight="400" style="normal">NotoSansLydian-Regular.ttf</font>
+    </family>
     <family pages="0,6,8,254">
         <font weight="400" style="normal">NotoSansMandaic-Regular.ttf</font>
     </family>
@@ -291,24 +342,64 @@
     <family pages="0,6-7,32,46,253-254">
         <font weight="400" style="normal">NotoSansNKo-Regular.ttf</font>
     </family>
+    <family pages="0,22,254">
+        <font weight="400" style="normal">NotoSansOgham-Regular.ttf</font>
+    </family>
     <family pages="0,28,254">
         <font weight="400" style="normal">NotoSansOlChiki-Regular.ttf</font>
     </family>
+    <family pages="0,254,259">
+        <font weight="400" style="normal">NotoSansOldItalic-Regular.ttf</font>
+    </family>
+    <family pages="0,254,259">
+        <font weight="400" style="normal">NotoSansOldPersian-Regular.ttf</font>
+    </family>
+    <family pages="0,254,266">
+        <font weight="400" style="normal">NotoSansOldSouthArabian-Regular.ttf</font>
+    </family>
+    <family pages="0,254,268">
+        <font weight="400" style="normal">NotoSansOldTurkic-Regular.ttf</font>
+    </family>
+    <family pages="0,254,260">
+        <font weight="400" style="normal">NotoSansOsmanya-Regular.ttf</font>
+    </family>
+    <family pages="0,254,265">
+        <font weight="400" style="normal">NotoSansPhoenician-Regular.ttf</font>
+    </family>
     <family pages="0,169,254">
         <font weight="400" style="normal">NotoSansRejang-Regular.ttf</font>
     </family>
+    <family pages="0,22,254">
+        <font weight="400" style="normal">NotoSansRunic-Regular.ttf</font>
+    </family>
+    <family pages="0,8,46,254">
+        <font weight="400" style="normal">NotoSansSamaritan-Regular.ttf</font>
+    </family>
     <family pages="0,32,37,168,254">
         <font weight="400" style="normal">NotoSansSaurashtra-Regular.ttf</font>
     </family>
+    <family pages="0,254,260">
+        <font weight="400" style="normal">NotoSansShavian-Regular.ttf</font>
+    </family>
     <family pages="0,27-28,254">
         <font weight="400" style="normal">NotoSansSundanese-Regular.ttf</font>
     </family>
     <family pages="0,9,32,37,168,254">
         <font weight="400" style="normal">NotoSansSylotiNagri-Regular.ttf</font>
     </family>
+    <!-- Estrangela should precede Eastern and Western Syriac, since it's our default form. -->
     <family pages="0,3,6-7,32,34,37-38,254">
         <font weight="400" style="normal">NotoSansSyriacEstrangela-Regular.ttf</font>
     </family>
+    <family pages="0,3,6-7,32,34,37-38,254">
+        <font weight="400" style="normal">NotoSansSyriacEastern-Regular.ttf</font>
+    </family>
+    <family pages="0,3,6-7,32,34,37-38,254">
+        <font weight="400" style="normal">NotoSansSyriacWestern-Regular.ttf</font>
+    </family>
+    <family pages="0,23,254">
+        <font weight="400" style="normal">NotoSansTagalog-Regular.ttf</font>
+    </family>
     <family pages="0,23,254">
         <font weight="400" style="normal">NotoSansTagbanwa-Regular.ttf</font>
     </family>
@@ -325,13 +416,13 @@
     <family pages="0,3,32,45,254">
         <font weight="400" style="normal">NotoSansTifinagh-Regular.ttf</font>
     </family>
+    <family pages="0,254,259">
+        <font weight="400" style="normal">NotoSansUgaritic-Regular.ttf</font>
+    </family>
     <family pages="0,165-166,254">
         <font weight="400" style="normal">NotoSansVai-Regular.ttf</font>
     </family>
-    <family pages="0,48,160-164,254-255">
-        <font weight="400" style="normal">NotoSansYi-Regular.ttf</font>
-    </family>
-    <family pages="32-43,497-498">
+    <family pages="32-43,77,257,464-471,496-498,503">
         <font weight="400" style="normal">NotoSansSymbols-Regular-Subsetted.ttf</font>
     </family>
     <family lang="zh-Hans" pages="0-4,17,30,32-39,41,43,46-159,169,172-215,249-251,254-255,497-498,512-658,660-682,685,687,689,691-696,698-702,704-718,760-761">
@@ -352,7 +443,7 @@
     <family pages="0,32-33,35-39,41,43,48,50,254,496-502,4068,4072">
         <font weight="400" style="normal">NotoEmoji-Regular.ttf</font>
     </family>
-    <family pages="35,37-39,43,496,498">
+    <family pages="35,37-39,43,496-498">
         <font weight="400" style="normal">NotoSansSymbols-Regular-Subsetted2.ttf</font>
     </family>
     <!--
@@ -364,13 +455,19 @@
         <font weight="400" style="normal" disable_synthetic_bolding="true">DroidSansFallback.ttf</font>
     </family>
     <!--
-        Tai Le and Mongolian are intentionally kept last, to make sure they don't override
-        the East Asian punctuation for Chinese.
+        Tai Le, Yi, Mongolian, and Phags-pa are intentionally kept last, to make sure they don't
+        override the East Asian punctuation for Chinese.
     -->
     <family pages="0,3,16,25,48,254">
         <font weight="400" style="normal">NotoSansTaiLe-Regular.ttf</font>
     </family>
+    <family pages="0,48,160-164,254-255">
+        <font weight="400" style="normal">NotoSansYi-Regular.ttf</font>
+    </family>
     <family pages="0,24,32,36-37,48,254">
         <font weight="400" style="normal" >NotoSansMongolian-Regular.ttf</font>
     </family>
+    <family pages="0,24,32,37,48,168,254">
+        <font weight="400" style="normal">NotoSansPhagsPa-Regular.ttf</font>
+    </family>
 </familyset>
diff --git a/src/cobalt/content/fonts/font_files/NotoNaskhArabicUI-Bold.ttf b/src/cobalt/content/fonts/font_files/NotoNaskhArabicUI-Bold.ttf
index 4d4e547..1d84460 100644
--- a/src/cobalt/content/fonts/font_files/NotoNaskhArabicUI-Bold.ttf
+++ b/src/cobalt/content/fonts/font_files/NotoNaskhArabicUI-Bold.ttf
Binary files differ
diff --git a/src/cobalt/content/fonts/font_files/NotoNaskhArabicUI-Regular.ttf b/src/cobalt/content/fonts/font_files/NotoNaskhArabicUI-Regular.ttf
index 27f120e..d7797a5 100644
--- a/src/cobalt/content/fonts/font_files/NotoNaskhArabicUI-Regular.ttf
+++ b/src/cobalt/content/fonts/font_files/NotoNaskhArabicUI-Regular.ttf
Binary files differ
diff --git a/src/cobalt/content/fonts/font_files/NotoSansAdlam-Regular.ttf b/src/cobalt/content/fonts/font_files/NotoSansAdlam-Regular.ttf
new file mode 100644
index 0000000..20ea4ba
--- /dev/null
+++ b/src/cobalt/content/fonts/font_files/NotoSansAdlam-Regular.ttf
Binary files differ
diff --git a/src/cobalt/content/fonts/font_files/NotoSansArmenian-Bold.ttf b/src/cobalt/content/fonts/font_files/NotoSansArmenian-Bold.ttf
index 57f0a78..109e34f 100644
--- a/src/cobalt/content/fonts/font_files/NotoSansArmenian-Bold.ttf
+++ b/src/cobalt/content/fonts/font_files/NotoSansArmenian-Bold.ttf
Binary files differ
diff --git a/src/cobalt/content/fonts/font_files/NotoSansArmenian-Regular.ttf b/src/cobalt/content/fonts/font_files/NotoSansArmenian-Regular.ttf
index ff82fa9..7f26da5 100644
--- a/src/cobalt/content/fonts/font_files/NotoSansArmenian-Regular.ttf
+++ b/src/cobalt/content/fonts/font_files/NotoSansArmenian-Regular.ttf
Binary files differ
diff --git a/src/cobalt/content/fonts/font_files/NotoSansAvestan-Regular.ttf b/src/cobalt/content/fonts/font_files/NotoSansAvestan-Regular.ttf
new file mode 100644
index 0000000..31eeb5a
--- /dev/null
+++ b/src/cobalt/content/fonts/font_files/NotoSansAvestan-Regular.ttf
Binary files differ
diff --git a/src/cobalt/content/fonts/font_files/NotoSansBrahmi-Regular.ttf b/src/cobalt/content/fonts/font_files/NotoSansBrahmi-Regular.ttf
new file mode 100644
index 0000000..eb98a65
--- /dev/null
+++ b/src/cobalt/content/fonts/font_files/NotoSansBrahmi-Regular.ttf
Binary files differ
diff --git a/src/cobalt/content/fonts/font_files/NotoSansCJK-Bold.ttc b/src/cobalt/content/fonts/font_files/NotoSansCJK-Bold.ttc
deleted file mode 100644
index 09707f9..0000000
--- a/src/cobalt/content/fonts/font_files/NotoSansCJK-Bold.ttc
+++ /dev/null
Binary files differ
diff --git a/src/cobalt/content/fonts/font_files/NotoSansCJK-Regular.ttc b/src/cobalt/content/fonts/font_files/NotoSansCJK-Regular.ttc
index d9a2262..23b4dc9 100644
--- a/src/cobalt/content/fonts/font_files/NotoSansCJK-Regular.ttc
+++ b/src/cobalt/content/fonts/font_files/NotoSansCJK-Regular.ttc
Binary files differ
diff --git a/src/cobalt/content/fonts/font_files/NotoSansCanadianAboriginal-Regular.ttf b/src/cobalt/content/fonts/font_files/NotoSansCanadianAboriginal-Regular.ttf
index e6435a8..4961f43 100644
--- a/src/cobalt/content/fonts/font_files/NotoSansCanadianAboriginal-Regular.ttf
+++ b/src/cobalt/content/fonts/font_files/NotoSansCanadianAboriginal-Regular.ttf
Binary files differ
diff --git a/src/cobalt/content/fonts/font_files/NotoSansCarian-Regular.ttf b/src/cobalt/content/fonts/font_files/NotoSansCarian-Regular.ttf
new file mode 100644
index 0000000..8abada1
--- /dev/null
+++ b/src/cobalt/content/fonts/font_files/NotoSansCarian-Regular.ttf
Binary files differ
diff --git a/src/cobalt/content/fonts/font_files/NotoSansCherokee-Regular.ttf b/src/cobalt/content/fonts/font_files/NotoSansCherokee-Regular.ttf
index 73dcbe0..6d44506 100644
--- a/src/cobalt/content/fonts/font_files/NotoSansCherokee-Regular.ttf
+++ b/src/cobalt/content/fonts/font_files/NotoSansCherokee-Regular.ttf
Binary files differ
diff --git a/src/cobalt/content/fonts/font_files/NotoSansCuneiform-Regular.ttf b/src/cobalt/content/fonts/font_files/NotoSansCuneiform-Regular.ttf
new file mode 100644
index 0000000..37a4e9e
--- /dev/null
+++ b/src/cobalt/content/fonts/font_files/NotoSansCuneiform-Regular.ttf
Binary files differ
diff --git a/src/cobalt/content/fonts/font_files/NotoSansCypriot-Regular.ttf b/src/cobalt/content/fonts/font_files/NotoSansCypriot-Regular.ttf
new file mode 100644
index 0000000..bc4083e
--- /dev/null
+++ b/src/cobalt/content/fonts/font_files/NotoSansCypriot-Regular.ttf
Binary files differ
diff --git a/src/cobalt/content/fonts/font_files/NotoSansDeseret-Regular.ttf b/src/cobalt/content/fonts/font_files/NotoSansDeseret-Regular.ttf
new file mode 100644
index 0000000..c043a54
--- /dev/null
+++ b/src/cobalt/content/fonts/font_files/NotoSansDeseret-Regular.ttf
Binary files differ
diff --git a/src/cobalt/content/fonts/font_files/NotoSansEgyptianHieroglyphs-Regular.ttf b/src/cobalt/content/fonts/font_files/NotoSansEgyptianHieroglyphs-Regular.ttf
new file mode 100644
index 0000000..62ee897
--- /dev/null
+++ b/src/cobalt/content/fonts/font_files/NotoSansEgyptianHieroglyphs-Regular.ttf
Binary files differ
diff --git a/src/cobalt/content/fonts/font_files/NotoSansGothic-Regular.ttf b/src/cobalt/content/fonts/font_files/NotoSansGothic-Regular.ttf
new file mode 100644
index 0000000..d653ee1
--- /dev/null
+++ b/src/cobalt/content/fonts/font_files/NotoSansGothic-Regular.ttf
Binary files differ
diff --git a/src/cobalt/content/fonts/font_files/NotoSansImperialAramaic-Regular.ttf b/src/cobalt/content/fonts/font_files/NotoSansImperialAramaic-Regular.ttf
new file mode 100644
index 0000000..10802e3
--- /dev/null
+++ b/src/cobalt/content/fonts/font_files/NotoSansImperialAramaic-Regular.ttf
Binary files differ
diff --git a/src/cobalt/content/fonts/font_files/NotoSansInscriptionalPahlavi-Regular.ttf b/src/cobalt/content/fonts/font_files/NotoSansInscriptionalPahlavi-Regular.ttf
new file mode 100644
index 0000000..44d5296
--- /dev/null
+++ b/src/cobalt/content/fonts/font_files/NotoSansInscriptionalPahlavi-Regular.ttf
Binary files differ
diff --git a/src/cobalt/content/fonts/font_files/NotoSansInscriptionalParthian-Regular.ttf b/src/cobalt/content/fonts/font_files/NotoSansInscriptionalParthian-Regular.ttf
new file mode 100644
index 0000000..bca05aa
--- /dev/null
+++ b/src/cobalt/content/fonts/font_files/NotoSansInscriptionalParthian-Regular.ttf
Binary files differ
diff --git a/src/cobalt/content/fonts/font_files/NotoSansKaithi-Regular.ttf b/src/cobalt/content/fonts/font_files/NotoSansKaithi-Regular.ttf
new file mode 100644
index 0000000..22b8c47
--- /dev/null
+++ b/src/cobalt/content/fonts/font_files/NotoSansKaithi-Regular.ttf
Binary files differ
diff --git a/src/cobalt/content/fonts/font_files/NotoSansKharoshthi-Regular.ttf b/src/cobalt/content/fonts/font_files/NotoSansKharoshthi-Regular.ttf
new file mode 100644
index 0000000..1f4a9a6
--- /dev/null
+++ b/src/cobalt/content/fonts/font_files/NotoSansKharoshthi-Regular.ttf
Binary files differ
diff --git a/src/cobalt/content/fonts/font_files/NotoSansLinearB-Regular.ttf b/src/cobalt/content/fonts/font_files/NotoSansLinearB-Regular.ttf
new file mode 100644
index 0000000..b741507
--- /dev/null
+++ b/src/cobalt/content/fonts/font_files/NotoSansLinearB-Regular.ttf
Binary files differ
diff --git a/src/cobalt/content/fonts/font_files/NotoSansLycian-Regular.ttf b/src/cobalt/content/fonts/font_files/NotoSansLycian-Regular.ttf
new file mode 100644
index 0000000..30310c2
--- /dev/null
+++ b/src/cobalt/content/fonts/font_files/NotoSansLycian-Regular.ttf
Binary files differ
diff --git a/src/cobalt/content/fonts/font_files/NotoSansLydian-Regular.ttf b/src/cobalt/content/fonts/font_files/NotoSansLydian-Regular.ttf
new file mode 100644
index 0000000..fc5bf5f
--- /dev/null
+++ b/src/cobalt/content/fonts/font_files/NotoSansLydian-Regular.ttf
Binary files differ
diff --git a/src/cobalt/content/fonts/font_files/NotoSansOgham-Regular.ttf b/src/cobalt/content/fonts/font_files/NotoSansOgham-Regular.ttf
new file mode 100644
index 0000000..8943189
--- /dev/null
+++ b/src/cobalt/content/fonts/font_files/NotoSansOgham-Regular.ttf
Binary files differ
diff --git a/src/cobalt/content/fonts/font_files/NotoSansOldItalic-Regular.ttf b/src/cobalt/content/fonts/font_files/NotoSansOldItalic-Regular.ttf
new file mode 100644
index 0000000..4a63a5e
--- /dev/null
+++ b/src/cobalt/content/fonts/font_files/NotoSansOldItalic-Regular.ttf
Binary files differ
diff --git a/src/cobalt/content/fonts/font_files/NotoSansOldPersian-Regular.ttf b/src/cobalt/content/fonts/font_files/NotoSansOldPersian-Regular.ttf
new file mode 100644
index 0000000..21166f4
--- /dev/null
+++ b/src/cobalt/content/fonts/font_files/NotoSansOldPersian-Regular.ttf
Binary files differ
diff --git a/src/cobalt/content/fonts/font_files/NotoSansOldSouthArabian-Regular.ttf b/src/cobalt/content/fonts/font_files/NotoSansOldSouthArabian-Regular.ttf
new file mode 100644
index 0000000..5037bd9
--- /dev/null
+++ b/src/cobalt/content/fonts/font_files/NotoSansOldSouthArabian-Regular.ttf
Binary files differ
diff --git a/src/cobalt/content/fonts/font_files/NotoSansOldTurkic-Regular.ttf b/src/cobalt/content/fonts/font_files/NotoSansOldTurkic-Regular.ttf
new file mode 100644
index 0000000..1652ad1
--- /dev/null
+++ b/src/cobalt/content/fonts/font_files/NotoSansOldTurkic-Regular.ttf
Binary files differ
diff --git a/src/cobalt/content/fonts/font_files/NotoSansOsmanya-Regular.ttf b/src/cobalt/content/fonts/font_files/NotoSansOsmanya-Regular.ttf
new file mode 100644
index 0000000..dd0b982
--- /dev/null
+++ b/src/cobalt/content/fonts/font_files/NotoSansOsmanya-Regular.ttf
Binary files differ
diff --git a/src/cobalt/content/fonts/font_files/NotoSansPhagsPa-Regular.ttf b/src/cobalt/content/fonts/font_files/NotoSansPhagsPa-Regular.ttf
new file mode 100644
index 0000000..bd59e32
--- /dev/null
+++ b/src/cobalt/content/fonts/font_files/NotoSansPhagsPa-Regular.ttf
Binary files differ
diff --git a/src/cobalt/content/fonts/font_files/NotoSansPhoenician-Regular.ttf b/src/cobalt/content/fonts/font_files/NotoSansPhoenician-Regular.ttf
new file mode 100644
index 0000000..345a977
--- /dev/null
+++ b/src/cobalt/content/fonts/font_files/NotoSansPhoenician-Regular.ttf
Binary files differ
diff --git a/src/cobalt/content/fonts/font_files/NotoSansRunic-Regular.ttf b/src/cobalt/content/fonts/font_files/NotoSansRunic-Regular.ttf
new file mode 100644
index 0000000..64a18b1
--- /dev/null
+++ b/src/cobalt/content/fonts/font_files/NotoSansRunic-Regular.ttf
Binary files differ
diff --git a/src/cobalt/content/fonts/font_files/NotoSansSamaritan-Regular.ttf b/src/cobalt/content/fonts/font_files/NotoSansSamaritan-Regular.ttf
new file mode 100644
index 0000000..9fe427c
--- /dev/null
+++ b/src/cobalt/content/fonts/font_files/NotoSansSamaritan-Regular.ttf
Binary files differ
diff --git a/src/cobalt/content/fonts/font_files/NotoSansShavian-Regular.ttf b/src/cobalt/content/fonts/font_files/NotoSansShavian-Regular.ttf
new file mode 100644
index 0000000..265c523
--- /dev/null
+++ b/src/cobalt/content/fonts/font_files/NotoSansShavian-Regular.ttf
Binary files differ
diff --git a/src/cobalt/content/fonts/font_files/NotoSansSymbols-Regular-Subsetted.ttf b/src/cobalt/content/fonts/font_files/NotoSansSymbols-Regular-Subsetted.ttf
index 599bfde..ebea59b 100644
--- a/src/cobalt/content/fonts/font_files/NotoSansSymbols-Regular-Subsetted.ttf
+++ b/src/cobalt/content/fonts/font_files/NotoSansSymbols-Regular-Subsetted.ttf
Binary files differ
diff --git a/src/cobalt/content/fonts/font_files/NotoSansSymbols-Regular-Subsetted2.ttf b/src/cobalt/content/fonts/font_files/NotoSansSymbols-Regular-Subsetted2.ttf
index 5b3c354..cc3e29f 100644
--- a/src/cobalt/content/fonts/font_files/NotoSansSymbols-Regular-Subsetted2.ttf
+++ b/src/cobalt/content/fonts/font_files/NotoSansSymbols-Regular-Subsetted2.ttf
Binary files differ
diff --git a/src/cobalt/content/fonts/font_files/NotoSansSyriacEastern-Regular.ttf b/src/cobalt/content/fonts/font_files/NotoSansSyriacEastern-Regular.ttf
new file mode 100644
index 0000000..25ee338
--- /dev/null
+++ b/src/cobalt/content/fonts/font_files/NotoSansSyriacEastern-Regular.ttf
Binary files differ
diff --git a/src/cobalt/content/fonts/font_files/NotoSansSyriacWestern-Regular.ttf b/src/cobalt/content/fonts/font_files/NotoSansSyriacWestern-Regular.ttf
new file mode 100644
index 0000000..f0f9de1
--- /dev/null
+++ b/src/cobalt/content/fonts/font_files/NotoSansSyriacWestern-Regular.ttf
Binary files differ
diff --git a/src/cobalt/content/fonts/font_files/NotoSansTagalog-Regular.ttf b/src/cobalt/content/fonts/font_files/NotoSansTagalog-Regular.ttf
new file mode 100644
index 0000000..0aff411
--- /dev/null
+++ b/src/cobalt/content/fonts/font_files/NotoSansTagalog-Regular.ttf
Binary files differ
diff --git a/src/cobalt/content/fonts/font_files/NotoSansUgaritic-Regular.ttf b/src/cobalt/content/fonts/font_files/NotoSansUgaritic-Regular.ttf
new file mode 100644
index 0000000..dec137d
--- /dev/null
+++ b/src/cobalt/content/fonts/font_files/NotoSansUgaritic-Regular.ttf
Binary files differ
diff --git a/src/cobalt/content/fonts/font_files/NotoSerif-Bold.ttf b/src/cobalt/content/fonts/font_files/NotoSerif-Bold.ttf
index 9d721a8..2ffdf8c 100644
--- a/src/cobalt/content/fonts/font_files/NotoSerif-Bold.ttf
+++ b/src/cobalt/content/fonts/font_files/NotoSerif-Bold.ttf
Binary files differ
diff --git a/src/cobalt/content/fonts/font_files/NotoSerif-BoldItalic.ttf b/src/cobalt/content/fonts/font_files/NotoSerif-BoldItalic.ttf
index 07dd1fb..4a317f8 100644
--- a/src/cobalt/content/fonts/font_files/NotoSerif-BoldItalic.ttf
+++ b/src/cobalt/content/fonts/font_files/NotoSerif-BoldItalic.ttf
Binary files differ
diff --git a/src/cobalt/content/fonts/font_files/NotoSerif-Italic.ttf b/src/cobalt/content/fonts/font_files/NotoSerif-Italic.ttf
index 4d7c1b3..968b46b 100644
--- a/src/cobalt/content/fonts/font_files/NotoSerif-Italic.ttf
+++ b/src/cobalt/content/fonts/font_files/NotoSerif-Italic.ttf
Binary files differ
diff --git a/src/cobalt/content/fonts/font_files/NotoSerif-Regular.ttf b/src/cobalt/content/fonts/font_files/NotoSerif-Regular.ttf
index fb8ba03..9d9a347 100644
--- a/src/cobalt/content/fonts/font_files/NotoSerif-Regular.ttf
+++ b/src/cobalt/content/fonts/font_files/NotoSerif-Regular.ttf
Binary files differ
diff --git a/src/cobalt/content/fonts/font_files/Roboto-Black.ttf b/src/cobalt/content/fonts/font_files/Roboto-Black.ttf
index e8a835a..3ecbdef 100644
--- a/src/cobalt/content/fonts/font_files/Roboto-Black.ttf
+++ b/src/cobalt/content/fonts/font_files/Roboto-Black.ttf
Binary files differ
diff --git a/src/cobalt/content/fonts/font_files/Roboto-BlackItalic.ttf b/src/cobalt/content/fonts/font_files/Roboto-BlackItalic.ttf
index 49bc496..44c086c 100644
--- a/src/cobalt/content/fonts/font_files/Roboto-BlackItalic.ttf
+++ b/src/cobalt/content/fonts/font_files/Roboto-BlackItalic.ttf
Binary files differ
diff --git a/src/cobalt/content/fonts/font_files/Roboto-Bold.ttf b/src/cobalt/content/fonts/font_files/Roboto-Bold.ttf
index 7e9b371..70def3f 100644
--- a/src/cobalt/content/fonts/font_files/Roboto-Bold.ttf
+++ b/src/cobalt/content/fonts/font_files/Roboto-Bold.ttf
Binary files differ
diff --git a/src/cobalt/content/fonts/font_files/Roboto-BoldItalic.ttf b/src/cobalt/content/fonts/font_files/Roboto-BoldItalic.ttf
index c2482d0..216f9ce 100644
--- a/src/cobalt/content/fonts/font_files/Roboto-BoldItalic.ttf
+++ b/src/cobalt/content/fonts/font_files/Roboto-BoldItalic.ttf
Binary files differ
diff --git a/src/cobalt/content/fonts/font_files/Roboto-Italic.ttf b/src/cobalt/content/fonts/font_files/Roboto-Italic.ttf
index 81124d7..f0f33db 100644
--- a/src/cobalt/content/fonts/font_files/Roboto-Italic.ttf
+++ b/src/cobalt/content/fonts/font_files/Roboto-Italic.ttf
Binary files differ
diff --git a/src/cobalt/content/fonts/font_files/Roboto-Light.ttf b/src/cobalt/content/fonts/font_files/Roboto-Light.ttf
index e50ce97..3a03044 100644
--- a/src/cobalt/content/fonts/font_files/Roboto-Light.ttf
+++ b/src/cobalt/content/fonts/font_files/Roboto-Light.ttf
Binary files differ
diff --git a/src/cobalt/content/fonts/font_files/Roboto-LightItalic.ttf b/src/cobalt/content/fonts/font_files/Roboto-LightItalic.ttf
index a2bfefe..983381b 100644
--- a/src/cobalt/content/fonts/font_files/Roboto-LightItalic.ttf
+++ b/src/cobalt/content/fonts/font_files/Roboto-LightItalic.ttf
Binary files differ
diff --git a/src/cobalt/content/fonts/font_files/Roboto-Medium.ttf b/src/cobalt/content/fonts/font_files/Roboto-Medium.ttf
index f144b6d..284b1ba 100644
--- a/src/cobalt/content/fonts/font_files/Roboto-Medium.ttf
+++ b/src/cobalt/content/fonts/font_files/Roboto-Medium.ttf
Binary files differ
diff --git a/src/cobalt/content/fonts/font_files/Roboto-MediumItalic.ttf b/src/cobalt/content/fonts/font_files/Roboto-MediumItalic.ttf
index e6e8319..a0b10d2 100644
--- a/src/cobalt/content/fonts/font_files/Roboto-MediumItalic.ttf
+++ b/src/cobalt/content/fonts/font_files/Roboto-MediumItalic.ttf
Binary files differ
diff --git a/src/cobalt/content/fonts/font_files/Roboto-Regular-Subsetted.ttf b/src/cobalt/content/fonts/font_files/Roboto-Regular-Subsetted.ttf
index 7e86392..99899ad 100644
--- a/src/cobalt/content/fonts/font_files/Roboto-Regular-Subsetted.ttf
+++ b/src/cobalt/content/fonts/font_files/Roboto-Regular-Subsetted.ttf
Binary files differ
diff --git a/src/cobalt/content/fonts/font_files/Roboto-Regular.ttf b/src/cobalt/content/fonts/font_files/Roboto-Regular.ttf
index 88dae90..500b104 100644
--- a/src/cobalt/content/fonts/font_files/Roboto-Regular.ttf
+++ b/src/cobalt/content/fonts/font_files/Roboto-Regular.ttf
Binary files differ
diff --git a/src/cobalt/content/fonts/font_files/Roboto-Thin.ttf b/src/cobalt/content/fonts/font_files/Roboto-Thin.ttf
index 77b470e..0c7d50b 100644
--- a/src/cobalt/content/fonts/font_files/Roboto-Thin.ttf
+++ b/src/cobalt/content/fonts/font_files/Roboto-Thin.ttf
Binary files differ
diff --git a/src/cobalt/content/fonts/font_files/Roboto-ThinItalic.ttf b/src/cobalt/content/fonts/font_files/Roboto-ThinItalic.ttf
index 5562612..277d8cf 100644
--- a/src/cobalt/content/fonts/font_files/Roboto-ThinItalic.ttf
+++ b/src/cobalt/content/fonts/font_files/Roboto-ThinItalic.ttf
Binary files differ
diff --git a/src/cobalt/content/fonts/scripts/Roboto-Regular.ttf b/src/cobalt/content/fonts/scripts/Roboto-Regular.ttf
index 88dae90..500b104 100644
--- a/src/cobalt/content/fonts/scripts/Roboto-Regular.ttf
+++ b/src/cobalt/content/fonts/scripts/Roboto-Regular.ttf
Binary files differ
diff --git a/src/cobalt/debug/component_connector.cc b/src/cobalt/debug/component_connector.cc
index b571adf..e201d4e 100644
--- a/src/cobalt/debug/component_connector.cc
+++ b/src/cobalt/debug/component_connector.cc
@@ -76,7 +76,7 @@
 }
 
 JSONObject ComponentConnector::CreateRemoteObject(
-    const script::OpaqueHandleHolder* object) {
+    const script::ValueHandleHolder* object) {
   // Parameter object for the JavaScript function call uses default values.
   JSONObject params(new base::DictionaryValue());
 
diff --git a/src/cobalt/debug/component_connector.h b/src/cobalt/debug/component_connector.h
index 8fa04ff..03f1929 100644
--- a/src/cobalt/debug/component_connector.h
+++ b/src/cobalt/debug/component_connector.h
@@ -20,8 +20,8 @@
 #include "base/threading/thread_checker.h"
 #include "cobalt/debug/debug_server.h"
 #include "cobalt/debug/json_object.h"
-#include "cobalt/script/opaque_handle.h"
 #include "cobalt/script/script_debugger.h"
+#include "cobalt/script/value_handle.h"
 
 namespace cobalt {
 namespace debug {
@@ -55,8 +55,8 @@
   // JavaScript object created by |script_runner_| with commands.
   bool RunScriptFile(const std::string& filename);
 
-  // Creates a Runtime.Remote object from an OpaqueHandleHolder.
-  JSONObject CreateRemoteObject(const script::OpaqueHandleHolder* object);
+  // Creates a Runtime.Remote object from an ValueHandleHolder.
+  JSONObject CreateRemoteObject(const script::ValueHandleHolder* object);
 
   // Sends an event to the |DebugServer| referenced by this object.
   void SendEvent(const std::string& method, const JSONObject& params);
diff --git a/src/cobalt/debug/debug_script_runner.cc b/src/cobalt/debug/debug_script_runner.cc
index 833d5ca..cb01a64 100644
--- a/src/cobalt/debug/debug_script_runner.cc
+++ b/src/cobalt/debug/debug_script_runner.cc
@@ -43,7 +43,7 @@
 }
 
 base::optional<std::string> DebugScriptRunner::CreateRemoteObject(
-    const script::OpaqueHandleHolder* object, const std::string& params) {
+    const script::ValueHandleHolder* object, const std::string& params) {
   // Callback function should have been set by runtime.js.
   DCHECK(create_remote_object_callback_);
 
diff --git a/src/cobalt/debug/debug_script_runner.h b/src/cobalt/debug/debug_script_runner.h
index 2841be8..59808df 100644
--- a/src/cobalt/debug/debug_script_runner.h
+++ b/src/cobalt/debug/debug_script_runner.h
@@ -22,8 +22,8 @@
 #include "cobalt/dom/csp_delegate.h"
 #include "cobalt/script/callback_function.h"
 #include "cobalt/script/global_environment.h"
-#include "cobalt/script/opaque_handle.h"
 #include "cobalt/script/script_value.h"
+#include "cobalt/script/value_handle.h"
 #include "cobalt/script/wrappable.h"
 
 namespace cobalt {
@@ -47,8 +47,8 @@
 
   // Callback to create a JavaScript Runtime.RemoteObject from an opaque JS
   // object.
-  typedef script::CallbackFunction<std::string(
-      const script::OpaqueHandleHolder*, const std::string&)>
+  typedef script::CallbackFunction<std::string(const script::ValueHandleHolder*,
+                                               const std::string&)>
       CreateRemoteObjectCallback;
   typedef script::ScriptValue<CreateRemoteObjectCallback>
       CreateRemoteObjectCallbackHolder;
@@ -61,7 +61,7 @@
   // calling the |create_remote_object_callback_| script function.
   // https://developer.chrome.com/devtools/docs/protocol/1.1/runtime#type-RemoteObject
   base::optional<std::string> CreateRemoteObject(
-      const script::OpaqueHandleHolder* object, const std::string& params);
+      const script::ValueHandleHolder* object, const std::string& params);
 
   // Runs |command| on the JavaScript |runtimeInspector| object, passing in
   // |json_params| and putting the result in |json_result|.
diff --git a/src/cobalt/debug/debug_server.cc b/src/cobalt/debug/debug_server.cc
index 4680d16..aad30cd 100644
--- a/src/cobalt/debug/debug_server.cc
+++ b/src/cobalt/debug/debug_server.cc
@@ -57,7 +57,7 @@
 }
 
 base::optional<std::string> DebugServer::CreateRemoteObject(
-    const script::OpaqueHandleHolder* object, const std::string& params) {
+    const script::ValueHandleHolder* object, const std::string& params) {
   DCHECK(thread_checker_.CalledOnValidThread());
   return script_runner_->CreateRemoteObject(object, params);
 }
diff --git a/src/cobalt/debug/debug_server.h b/src/cobalt/debug/debug_server.h
index bf68c5e..bd5d2dd 100644
--- a/src/cobalt/debug/debug_server.h
+++ b/src/cobalt/debug/debug_server.h
@@ -33,8 +33,8 @@
 #include "cobalt/debug/json_object.h"
 #include "cobalt/dom/csp_delegate.h"
 #include "cobalt/script/global_environment.h"
-#include "cobalt/script/opaque_handle.h"
 #include "cobalt/script/script_value.h"
+#include "cobalt/script/value_handle.h"
 
 namespace cobalt {
 namespace debug {
@@ -108,7 +108,7 @@
 
   // Creates a Runtime.RemoteObject corresponding to an opaque JS object.
   base::optional<std::string> CreateRemoteObject(
-      const script::OpaqueHandleHolder* object, const std::string& params);
+      const script::ValueHandleHolder* object, const std::string& params);
 
   // Called by the debug components when an event occurs.
   // Serializes the method and params object to a JSON string and
diff --git a/src/cobalt/debug/debugger.h b/src/cobalt/debug/debugger.h
index cf4220f..4babccc 100644
--- a/src/cobalt/debug/debugger.h
+++ b/src/cobalt/debug/debugger.h
@@ -28,8 +28,8 @@
 #include "cobalt/debug/debug_server.h"
 #include "cobalt/debug/debugger_event_target.h"
 #include "cobalt/script/callback_function.h"
-#include "cobalt/script/opaque_handle.h"
 #include "cobalt/script/script_value.h"
+#include "cobalt/script/value_handle.h"
 #include "cobalt/script/wrappable.h"
 
 namespace cobalt {
diff --git a/src/cobalt/debug/javascript_debugger_component.cc b/src/cobalt/debug/javascript_debugger_component.cc
index e02fc2a..3ac5924 100644
--- a/src/cobalt/debug/javascript_debugger_component.cc
+++ b/src/cobalt/debug/javascript_debugger_component.cc
@@ -336,7 +336,7 @@
   call_frame_data->Set(kScopeChain, scope_chain_data.release());
 
   // Add the "this" object data.
-  const script::OpaqueHandleHolder* this_object = call_frame->GetThis();
+  const script::ValueHandleHolder* this_object = call_frame->GetThis();
   if (this_object) {
     JSONObject this_object_data(connector_->CreateRemoteObject(this_object));
     call_frame_data->Set(kThis, this_object_data.release());
@@ -364,7 +364,7 @@
 JSONObject JavaScriptDebuggerComponent::CreateScopeData(
     const scoped_ptr<script::Scope>& scope) {
   DCHECK(scope);
-  const script::OpaqueHandleHolder* scope_object = scope->GetObject();
+  const script::ValueHandleHolder* scope_object = scope->GetObject();
   JSONObject scope_data(new base::DictionaryValue());
   scope_data->Set(kObject,
                   connector_->CreateRemoteObject(scope_object).release());
diff --git a/src/cobalt/dom/custom_event_test.cc b/src/cobalt/dom/custom_event_test.cc
index 3f87356..63344d5 100644
--- a/src/cobalt/dom/custom_event_test.cc
+++ b/src/cobalt/dom/custom_event_test.cc
@@ -35,11 +35,17 @@
 #include "cobalt/script/value_handle.h"
 #include "cobalt/script/wrappable.h"
 #include "nb/pointer_arithmetic.h"
+#include "starboard/window.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace cobalt {
 namespace dom {
+namespace {
+// Return a NULL SbWindow, since we do not need to pass a valid SbWindow to an
+// on screen keyboard.
+SbWindow GetNullSbWindow() { return NULL; }
+}  // namespace
 
 using ::cobalt::script::testing::FakeScriptValue;
 
@@ -63,14 +69,16 @@
             1920, 1080, 1.f, base::kApplicationStateStarted, css_parser_.get(),
             dom_parser_.get(), fetcher_factory_.get(), NULL, NULL, NULL, NULL,
             NULL, NULL, &local_storage_database_, NULL, NULL, NULL, NULL, NULL,
-            NULL, NULL, url_, "", "en-US", base::Callback<void(const GURL&)>(),
+            NULL, NULL, url_, "", "en-US", "en",
+            base::Callback<void(const GURL&)>(),
             base::Bind(&MockErrorCallback::Run,
                        base::Unretained(&mock_error_callback_)),
             NULL, network_bridge::PostSender(), csp::kCSPRequired,
             kCspEnforcementEnable, base::Closure() /* csp_policy_changed */,
             base::Closure() /* ran_animation_frame_callbacks */,
             dom::Window::CloseCallback() /* window_close */,
-            base::Closure() /* window_minimize */, NULL, NULL)) {
+            base::Closure() /* window_minimize */, base::Bind(&GetNullSbWindow),
+            NULL, NULL)) {
     engine_ = script::JavaScriptEngine::CreateEngine();
     global_environment_ = engine_->CreateGlobalEnvironment();
     global_environment_->CreateGlobalObject(window_,
diff --git a/src/cobalt/dom/document.cc b/src/cobalt/dom/document.cc
index dd57f18..51953b4 100644
--- a/src/cobalt/dom/document.cc
+++ b/src/cobalt/dom/document.cc
@@ -123,7 +123,7 @@
       html_element_context_->resource_provider(),
       html_element_context_->remote_typeface_cache(),
       base::Bind(&Document::OnTypefaceLoadEvent, base::Unretained(this)),
-      html_element_context_->language(), location_));
+      html_element_context_->font_language_script(), location_));
 
   if (HasBrowsingContext()) {
     if (html_element_context_->remote_typeface_cache()) {
diff --git a/src/cobalt/dom/dom.gyp b/src/cobalt/dom/dom.gyp
index 27a8f29..29f304d 100644
--- a/src/cobalt/dom/dom.gyp
+++ b/src/cobalt/dom/dom.gyp
@@ -166,6 +166,9 @@
         'html_video_element.h',
         'initial_computed_style.cc',
         'initial_computed_style.h',
+        'input_event.cc',
+        'input_event.h',
+        'input_event_init.h',
         'keyboard_event.cc',
         'keyboard_event.h',
         'keyboard_event_init.h',
@@ -210,6 +213,8 @@
         'node_list.h',
         'node_list_live.cc',
         'node_list_live.h',
+        'on_screen_keyboard.cc',
+        'on_screen_keyboard.h',
         'performance.cc',
         'performance.h',
         'performance_timing.cc',
diff --git a/src/cobalt/dom/eme/media_key_session.cc b/src/cobalt/dom/eme/media_key_session.cc
index fae4417..5af2533 100644
--- a/src/cobalt/dom/eme/media_key_session.cc
+++ b/src/cobalt/dom/eme/media_key_session.cc
@@ -223,6 +223,13 @@
   return promise.Pass();
 }
 
+void MediaKeySession::TraceMembers(script::Tracer* tracer) {
+  EventTarget::TraceMembers(tracer);
+
+  tracer->Trace(key_status_map_);
+  event_queue_.TraceMembers(tracer);
+}
+
 // See
 // https://www.w3.org/TR/encrypted-media/#dom-mediakeysession-generaterequest.
 void MediaKeySession::OnSessionUpdateRequestGenerated(
@@ -297,13 +304,6 @@
 
   // 8.2. Resolve promise.
   promise_reference->value().Resolve();
-
-#if !SB_HAS(DRM_KEY_STATUSES)
-  // When key statuses is not enabled, send a "keystatuseschange" anyway so the
-  // JS app knows that |keyStatuses| will no longer be updated.
-  LOG(INFO) << "Fired 'keystatuseschange' event on MediaKeySession.";
-  event_queue_.Enqueue(new Event(base::Tokens::keystatuseschange()));
-#endif  // !SB_HAS(DRM_KEY_STATUSES)
 }
 
 // See https://www.w3.org/TR/encrypted-media/#dom-mediakeysession-update.
@@ -314,13 +314,6 @@
   //
   // TODO: Introduce Starboard API that allows CDM to propagate error codes.
   promise_reference->value().Reject(new DOMException(DOMException::kNone));
-
-#if !SB_HAS(DRM_KEY_STATUSES)
-  // When key statuses is not enabled, send a "keystatuseschange" anyway so the
-  // JS app knows that |keyStatuses| will no longer be updated.
-  LOG(INFO) << "Fired 'keystatuseschange' event on MediaKeySession.";
-  event_queue_.Enqueue(new Event(base::Tokens::keystatuseschange()));
-#endif  // !SB_HAS(DRM_KEY_STATUSES)
 }
 
 // See https://www.w3.org/TR/encrypted-media/#update-key-statuses.
@@ -370,7 +363,8 @@
 
   // 5. Queue a task to fire a simple event named keystatuseschange at the
   //    session.
-  LOG(INFO) << "Fired 'keystatuseschange' event on MediaKeySession.";
+  LOG(INFO) << "Fired 'keystatuseschange' event on MediaKeySession with "
+            << key_status_map_->size() << " keys.";
   event_queue_.Enqueue(new Event(base::Tokens::keystatuseschange()));
 
   // 6. Queue a task to run the Attempt to Resume Playback If Necessary
diff --git a/src/cobalt/dom/eme/media_key_session.h b/src/cobalt/dom/eme/media_key_session.h
index bda41aa..e96f3b9 100644
--- a/src/cobalt/dom/eme/media_key_session.h
+++ b/src/cobalt/dom/eme/media_key_session.h
@@ -62,6 +62,8 @@
   scoped_ptr<VoidPromiseValue> Update(const BufferSource& response);
   scoped_ptr<VoidPromiseValue> Close();
 
+  void TraceMembers(script::Tracer* tracer) OVERRIDE;
+
   DEFINE_WRAPPABLE_TYPE(MediaKeySession);
 
  private:
diff --git a/src/cobalt/dom/error_event_test.cc b/src/cobalt/dom/error_event_test.cc
index 8134972..d35ba23 100644
--- a/src/cobalt/dom/error_event_test.cc
+++ b/src/cobalt/dom/error_event_test.cc
@@ -35,11 +35,17 @@
 #include "cobalt/script/value_handle.h"
 #include "cobalt/script/wrappable.h"
 #include "nb/pointer_arithmetic.h"
+#include "starboard/window.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace cobalt {
 namespace dom {
+namespace {
+// Return a NULL SbWindow, since we do not need to pass a valid SbWindow to an
+// on screen keyboard.
+SbWindow GetNullSbWindow() { return NULL; }
+}  // namespace
 
 using ::cobalt::script::testing::FakeScriptValue;
 
@@ -63,14 +69,16 @@
             1920, 1080, 1.f, base::kApplicationStateStarted, css_parser_.get(),
             dom_parser_.get(), fetcher_factory_.get(), NULL, NULL, NULL, NULL,
             NULL, NULL, &local_storage_database_, NULL, NULL, NULL, NULL, NULL,
-            NULL, NULL, url_, "", "en-US", base::Callback<void(const GURL&)>(),
+            NULL, NULL, url_, "", "en-US", "en",
+            base::Callback<void(const GURL&)>(),
             base::Bind(&MockErrorCallback::Run,
                        base::Unretained(&mock_error_callback_)),
             NULL, network_bridge::PostSender(), csp::kCSPRequired,
             kCspEnforcementEnable, base::Closure() /* csp_policy_changed */,
             base::Closure() /* ran_animation_frame_callbacks */,
             dom::Window::CloseCallback() /* window_close */,
-            base::Closure() /* window_minimize */, NULL, NULL)) {
+            base::Closure() /* window_minimize */, base::Bind(&GetNullSbWindow),
+            NULL, NULL)) {
     engine_ = script::JavaScriptEngine::CreateEngine();
     global_environment_ = engine_->CreateGlobalEnvironment();
     global_environment_->CreateGlobalObject(window_,
diff --git a/src/cobalt/dom/event.cc b/src/cobalt/dom/event.cc
index 64c1d77..da1a085 100644
--- a/src/cobalt/dom/event.cc
+++ b/src/cobalt/dom/event.cc
@@ -100,5 +100,10 @@
   default_prevented_ = false;
 }
 
+void Event::TraceMembers(script::Tracer* tracer) {
+  tracer->Trace(target_);
+  tracer->Trace(current_target_);
+}
+
 }  // namespace dom
 }  // namespace cobalt
diff --git a/src/cobalt/dom/event.h b/src/cobalt/dom/event.h
index 99c125b..da4386e 100644
--- a/src/cobalt/dom/event.h
+++ b/src/cobalt/dom/event.h
@@ -126,6 +126,8 @@
     return immediate_propagation_stopped_;
   }
 
+  void TraceMembers(script::Tracer* tracer) OVERRIDE;
+
   DEFINE_WRAPPABLE_TYPE(Event);
 
  private:
diff --git a/src/cobalt/dom/event_queue.cc b/src/cobalt/dom/event_queue.cc
index 0090fb8..74d9dfd 100644
--- a/src/cobalt/dom/event_queue.cc
+++ b/src/cobalt/dom/event_queue.cc
@@ -50,9 +50,19 @@
   events_.clear();
 }
 
+void EventQueue::TraceMembers(script::Tracer* tracer) {
+  for (const auto& event : events_) {
+    tracer->Trace(event);
+  }
+}
+
 void EventQueue::DispatchEvents() {
   DCHECK(message_loop_->BelongsToCurrentThread());
 
+  // Make sure that the event_target_ stays alive for the duration of
+  // all event dispatches.
+  scoped_refptr<EventTarget> keep_alive_reference(event_target_);
+
   Events events;
   events.swap(events_);
 
diff --git a/src/cobalt/dom/event_queue.h b/src/cobalt/dom/event_queue.h
index dd5ca0c..22ed4d5 100644
--- a/src/cobalt/dom/event_queue.h
+++ b/src/cobalt/dom/event_queue.h
@@ -44,6 +44,8 @@
   void Enqueue(const scoped_refptr<Event>& event);
   void CancelAllEvents();
 
+  void TraceMembers(script::Tracer* tracer);
+
  private:
   typedef std::vector<scoped_refptr<Event> > Events;
   void DispatchEvents();
diff --git a/src/cobalt/dom/font_cache.cc b/src/cobalt/dom/font_cache.cc
index 4709e95..d44c8d6 100644
--- a/src/cobalt/dom/font_cache.cc
+++ b/src/cobalt/dom/font_cache.cc
@@ -43,13 +43,13 @@
 FontCache::FontCache(render_tree::ResourceProvider** resource_provider,
                      loader::font::RemoteTypefaceCache* remote_typeface_cache,
                      const base::Closure& external_typeface_load_event_callback,
-                     const std::string& language,
+                     const std::string& language_script,
                      scoped_refptr<Location> document_location)
     : resource_provider_(resource_provider),
       remote_typeface_cache_(remote_typeface_cache),
       external_typeface_load_event_callback_(
           external_typeface_load_event_callback),
-      language_(language),
+      language_script_(language_script),
       font_face_map_(new FontFaceMap()),
       last_inactive_process_time_(base::TimeTicks::Now()),
       document_location_(document_location) {}
@@ -194,7 +194,7 @@
   DCHECK(resource_provider());
   return GetCachedLocalTypeface(
       resource_provider()->GetCharacterFallbackTypeface(utf32_character, style,
-                                                        language_));
+                                                        language_script_));
 }
 
 scoped_refptr<render_tree::GlyphBuffer> FontCache::CreateGlyphBuffer(
@@ -202,7 +202,7 @@
     FontList* font_list) {
   DCHECK(resource_provider());
   return resource_provider()->CreateGlyphBuffer(
-      text_buffer, static_cast<size_t>(text_length), language_, is_rtl,
+      text_buffer, static_cast<size_t>(text_length), language_script_, is_rtl,
       font_list);
 }
 
@@ -211,7 +211,7 @@
                               render_tree::FontVector* maybe_used_fonts) {
   DCHECK(resource_provider());
   return resource_provider()->GetTextWidth(
-      text_buffer, static_cast<size_t>(text_length), language_, is_rtl,
+      text_buffer, static_cast<size_t>(text_length), language_script_, is_rtl,
       font_list, maybe_used_fonts);
 }
 
diff --git a/src/cobalt/dom/font_cache.h b/src/cobalt/dom/font_cache.h
index 048e50b..4932bc7 100644
--- a/src/cobalt/dom/font_cache.h
+++ b/src/cobalt/dom/font_cache.h
@@ -174,7 +174,7 @@
   FontCache(render_tree::ResourceProvider** resource_provider,
             loader::font::RemoteTypefaceCache* remote_typeface_cache,
             const base::Closure& external_typeface_load_event_callback,
-            const std::string& language,
+            const std::string& language_script,
             scoped_refptr<Location> document_location);
 
   // Set a new font face map. If it matches the old font face map then nothing
@@ -285,7 +285,7 @@
   // logic into the font cache when the loader interface improves.
   loader::font::RemoteTypefaceCache* const remote_typeface_cache_;
   const base::Closure external_typeface_load_event_callback_;
-  const std::string language_;
+  const std::string language_script_;
 
   // Font-face related
   // The cache contains a map of font faces and handles requesting typefaces by
diff --git a/src/cobalt/dom/font_list.cc b/src/cobalt/dom/font_list.cc
index 04743c0..b5c6d85 100644
--- a/src/cobalt/dom/font_list.cc
+++ b/src/cobalt/dom/font_list.cc
@@ -296,7 +296,9 @@
     render_tree::GlyphIndex space_glyph =
         primary_font->GetGlyphForCharacter(' ');
     space_width_ = primary_font->GetGlyphWidth(space_glyph);
-    DCHECK_GT(space_width_, 0);
+    if (space_width_ == 0) {
+      DLOG(WARNING) << "Font being used with space width of 0!";
+    }
 
     is_space_width_set_ = true;
   }
diff --git a/src/cobalt/dom/html_element_context.cc b/src/cobalt/dom/html_element_context.cc
index d9c502d..60d0e15 100644
--- a/src/cobalt/dom/html_element_context.cc
+++ b/src/cobalt/dom/html_element_context.cc
@@ -55,7 +55,7 @@
         reduced_image_cache_capacity_manager,
     loader::font::RemoteTypefaceCache* remote_typeface_cache,
     loader::mesh::MeshCache* mesh_cache, DomStatTracker* dom_stat_tracker,
-    const std::string& language,
+    const std::string& font_language_script,
     base::ApplicationState initial_application_state,
     float video_playback_rate_multiplier)
     : fetcher_factory_(fetcher_factory),
@@ -74,7 +74,7 @@
       remote_typeface_cache_(remote_typeface_cache),
       mesh_cache_(mesh_cache),
       dom_stat_tracker_(dom_stat_tracker),
-      language_(language),
+      font_language_script_(font_language_script),
       page_visibility_state_(initial_application_state),
       video_playback_rate_multiplier_(video_playback_rate_multiplier),
       sync_load_thread_("Synchronous Load"),
diff --git a/src/cobalt/dom/html_element_context.h b/src/cobalt/dom/html_element_context.h
index 7847423..cab1c71 100644
--- a/src/cobalt/dom/html_element_context.h
+++ b/src/cobalt/dom/html_element_context.h
@@ -63,7 +63,7 @@
           reduced_image_cache_capacity_manager,
       loader::font::RemoteTypefaceCache* remote_typeface_cache,
       loader::mesh::MeshCache* mesh_cache, DomStatTracker* dom_stat_tracker,
-      const std::string& language,
+      const std::string& font_language_script,
       base::ApplicationState initial_application_state,
       float video_playback_rate_multiplier = 1.0);
   ~HTMLElementContext();
@@ -113,7 +113,9 @@
 
   DomStatTracker* dom_stat_tracker() { return dom_stat_tracker_; }
 
-  const std::string& language() const { return language_; }
+  const std::string& font_language_script() const {
+    return font_language_script_;
+  }
 
   float video_playback_rate_multiplier() const {
     return video_playback_rate_multiplier_;
@@ -151,7 +153,7 @@
   loader::font::RemoteTypefaceCache* const remote_typeface_cache_;
   loader::mesh::MeshCache* const mesh_cache_;
   DomStatTracker* const dom_stat_tracker_;
-  const std::string language_;
+  const std::string font_language_script_;
   page_visibility::PageVisibilityState page_visibility_state_;
   const float video_playback_rate_multiplier_;
 
diff --git a/src/cobalt/dom/html_link_element.cc b/src/cobalt/dom/html_link_element.cc
index 90f006c..7c5ca09 100644
--- a/src/cobalt/dom/html_link_element.cc
+++ b/src/cobalt/dom/html_link_element.cc
@@ -48,6 +48,22 @@
   return rel == "stylesheet";
 }
 
+loader::RequestMode GetRequestMode(
+    const base::optional<std::string>& cross_origin_attribute) {
+  // https://html.spec.whatwg.org/#cors-settings-attribute
+  if (cross_origin_attribute) {
+    if (*cross_origin_attribute == "use-credentials") {
+      return loader::kCORSModeIncludeCredentials;
+    } else {
+      // The invalid value default of crossorigin is Anonymous state, leading to
+      // "same-origin" credentials mode.
+      return loader::kCORSModeSameOriginCredentials;
+    }
+  }
+  // crossorigin attribute's missing value default is No CORS state, leading to
+  // "no-cors" request mode.
+  return loader::kNoCORSMode;
+}
 }  // namespace
 
 // static
@@ -66,6 +82,26 @@
   }
 }
 
+base::optional<std::string> HTMLLinkElement::cross_origin() const {
+  base::optional<std::string> cross_origin_attribute =
+      GetAttribute("crossOrigin");
+  if (cross_origin_attribute &&
+      (*cross_origin_attribute != "anonymous" &&
+       *cross_origin_attribute != "use-credentials")) {
+    return std::string();
+  }
+  return cross_origin_attribute;
+}
+
+void HTMLLinkElement::set_cross_origin(
+    const base::optional<std::string>& value) {
+  if (value) {
+    SetAttribute("crossOrigin", *value);
+  } else {
+    RemoveAttribute("crossOrigin");
+  }
+}
+
 void HTMLLinkElement::OnRemovedFromDocument() {
   HTMLElement::OnRemovedFromDocument();
 
@@ -136,11 +172,14 @@
     document->IncreaseLoadingCounter();
   }
 
+  request_mode_ = GetRequestMode(GetAttribute("crossOrigin"));
   loader_ = make_scoped_ptr(new loader::Loader(
       base::Bind(
           &loader::FetcherFactory::CreateSecureFetcher,
           base::Unretained(document->html_element_context()->fetcher_factory()),
-          absolute_url_, csp_callback, loader::kNoCORSMode, loader::Origin()),
+          absolute_url_, csp_callback, request_mode_,
+          document->location() ? document->location()->OriginObject()
+                               : loader::Origin()),
       scoped_ptr<loader::Decoder>(new loader::TextDecoder(
           base::Bind(&HTMLLinkElement::OnLoadingDone, base::Unretained(this)))),
       base::Bind(&HTMLLinkElement::OnLoadingError, base::Unretained(this))));
@@ -224,7 +263,8 @@
   css_style_sheet->SetLocationUrl(absolute_url_);
   // If not loading from network-fetched resources or fetched resource is same
   // origin as the document, set origin-clean flag to true.
-  if (!loader_ || document->url_as_gurl().SchemeIsFile() ||
+  if (request_mode_ != loader::kNoCORSMode || !loader_ ||
+      document->url_as_gurl().SchemeIsFile() ||
       (fetched_last_url_origin_ == document->location()->OriginObject())) {
     css_style_sheet->SetOriginClean(true);
   }
diff --git a/src/cobalt/dom/html_link_element.h b/src/cobalt/dom/html_link_element.h
index f9f41c1..dac23e0 100644
--- a/src/cobalt/dom/html_link_element.h
+++ b/src/cobalt/dom/html_link_element.h
@@ -53,6 +53,9 @@
   std::string href() const { return GetAttribute("href").value_or(""); }
   void set_href(const std::string& value) { SetAttribute("href", value); }
 
+  base::optional<std::string> cross_origin() const;
+  void set_cross_origin(const base::optional<std::string>& value);
+
   // Custom, not in any spec.
   //
   scoped_refptr<HTMLLinkElement> AsHTMLLinkElement() OVERRIDE { return this; }
@@ -93,7 +96,11 @@
   // The style sheet associated with this element.
   scoped_refptr<cssom::StyleSheet> style_sheet_;
 
+  // The origin of fetch request's final destination.
   loader::Origin fetched_last_url_origin_;
+
+  // The request mode for the fetch request.
+  loader::RequestMode request_mode_;
 };
 
 }  // namespace dom
diff --git a/src/cobalt/dom/html_link_element.idl b/src/cobalt/dom/html_link_element.idl
index 724cc2b..931f316 100644
--- a/src/cobalt/dom/html_link_element.idl
+++ b/src/cobalt/dom/html_link_element.idl
@@ -18,4 +18,5 @@
   attribute DOMString href;
   attribute DOMString rel;
   attribute DOMString type;
+  attribute DOMString? crossOrigin;
 };
diff --git a/src/cobalt/dom/html_media_element.cc b/src/cobalt/dom/html_media_element.cc
index 83a3600..6ad12fb 100644
--- a/src/cobalt/dom/html_media_element.cc
+++ b/src/cobalt/dom/html_media_element.cc
@@ -103,6 +103,52 @@
 base::LazyInstance<HTMLMediaElementCountLog> html_media_element_count_log =
     LAZY_INSTANCE_INITIALIZER;
 
+#if !SB_HAS(PLAYER_WITH_URL)
+loader::RequestMode GetRequestMode(
+    const base::optional<std::string>& cross_origin_attribute) {
+  // https://html.spec.whatwg.org/#cors-settings-attribute
+  if (cross_origin_attribute) {
+    if (*cross_origin_attribute == "use-credentials") {
+      return loader::kCORSModeIncludeCredentials;
+    } else {
+      // The invalid value default of crossorigin is Anonymous state, leading to
+      // "same-origin" credentials mode.
+      return loader::kCORSModeSameOriginCredentials;
+    }
+  }
+  // crossorigin attribute's missing value default is No CORS state, leading to
+  // "no-cors" request mode.
+  return loader::kNoCORSMode;
+}
+#endif  // SB_HAS(PLAYER_WITH_URL)
+
+#if defined(COBALT_MEDIA_SOURCE_2016)
+bool OriginIsSafe(loader::RequestMode request_mode, const GURL& resource_url,
+                  const loader::Origin& origin) {
+#if SB_HAS(PLAYER_WITH_URL)
+  UNREFERENCED_PARAMETER(request_mode);
+  UNREFERENCED_PARAMETER(resource_url);
+  UNREFERENCED_PARAMETER(origin);
+  return true;
+#else  // SB_HAS(PLAYER_WITH_URL)
+  if (resource_url.SchemeIs("blob")) {
+    // Blob resources come from application and is same-origin.
+    return true;
+  }
+  if (request_mode != loader::kNoCORSMode) {
+    return true;
+  }
+  if (origin == loader::Origin(resource_url)) {
+    return true;
+  }
+  if (resource_url.SchemeIs("data")) {
+    return true;
+  }
+  return false;
+#endif  // SB_HAS(PLAYER_WITH_URL)
+}
+#endif  // defined(COBALT_MEDIA_SOURCE_2016)
+
 }  // namespace
 
 HTMLMediaElement::HTMLMediaElement(Document* document, base::Token tag_name)
@@ -133,7 +179,8 @@
                         base::GenerateGUID()),
       pending_load_(false),
       sent_stalled_event_(false),
-      sent_end_event_(false) {
+      sent_end_event_(false),
+      request_mode_(loader::kNoCORSMode) {
   TRACE_EVENT0("cobalt::dom", "HTMLMediaElement::HTMLMediaElement()");
   MLOG();
   html_media_element_count_log.Get().count++;
@@ -164,6 +211,26 @@
   ScheduleLoad();
 }
 
+base::optional<std::string> HTMLMediaElement::cross_origin() const {
+  base::optional<std::string> cross_origin_attribute =
+      GetAttribute("crossOrigin");
+  if (cross_origin_attribute &&
+      (*cross_origin_attribute != "anonymous" &&
+       *cross_origin_attribute != "use-credentials")) {
+    return std::string();
+  }
+  return cross_origin_attribute;
+}
+
+void HTMLMediaElement::set_cross_origin(
+    const base::optional<std::string>& value) {
+  if (value) {
+    SetAttribute("crossOrigin", *value);
+  } else {
+    RemoveAttribute("crossOrigin");
+  }
+}
+
 uint16_t HTMLMediaElement::network_state() const {
   MLOG() << network_state_;
   return static_cast<uint16_t>(network_state_);
@@ -684,6 +751,19 @@
   }
 }
 
+void HTMLMediaElement::TraceMembers(script::Tracer* tracer) {
+  HTMLElement::TraceMembers(tracer);
+
+  event_queue_.TraceMembers(tracer);
+
+  tracer->Trace(played_time_ranges_);
+  tracer->Trace(media_source_);
+  tracer->Trace(error_);
+#if defined(COBALT_MEDIA_SOURCE_2016)
+  tracer->Trace(media_keys_);
+#endif  // defined(COBALT_MEDIA_SOURCE_2016)
+}
+
 #if defined(COBALT_MEDIA_SOURCE_2016)
 void HTMLMediaElement::DurationChanged(double duration, bool request_seek) {
   MLOG() << "DurationChanged(" << duration << ", " << request_seek << ")";
@@ -950,7 +1030,7 @@
     return;
   }
 #if SB_HAS(PLAYER_WITH_URL)
-  // TODO: Investigate if we have to support csp for url player.
+  // TODO: Investigate if we have to support csp and sop for url player.
   player_->LoadUrl(url);
 #else   // SB_HAS(PLAYER_WITH_URL)
   if (url.spec() == SourceURL()) {
@@ -959,12 +1039,14 @@
     csp::SecurityCallback csp_callback = base::Bind(
         &CspDelegate::CanLoad,
         base::Unretained(node_document()->csp_delegate()), CspDelegate::kMedia);
+    request_mode_ = GetRequestMode(GetAttribute("crossOrigin"));
+    DCHECK(node_document()->location());
     scoped_ptr<BufferedDataSource> data_source(
         new media::FetcherBufferedDataSource(
             base::MessageLoopProxy::current(), url, csp_callback,
-            html_element_context()->fetcher_factory()->network_module()));
-    player_->LoadProgressive(url, data_source.Pass(),
-                             WebMediaPlayer::kCORSModeUnspecified);
+            html_element_context()->fetcher_factory()->network_module(),
+            request_mode_, node_document()->location()->OriginObject()));
+    player_->LoadProgressive(url, data_source.Pass());
   }
 #endif  // SB_HAS(PLAYER_WITH_URL)
 }
@@ -1614,6 +1696,14 @@
   InvalidateLayoutBoxesOfNodeAndAncestors();
 }
 
+void HTMLMediaElement::ContentSizeChanged() {
+  TRACE_EVENT0("cobalt::dom", "HTMLMediaElement::ContentSizeChanged()");
+  // If the player content size is updated, trigger a re-layout so that we can
+  // setup the video render tree differently with letterboxing.
+  node_document()->OnDOMMutation();
+  InvalidateLayoutBoxesOfNodeAndAncestors();
+}
+
 void HTMLMediaElement::PlaybackStateChanged() {
   if (!player_) {
     return;
@@ -1713,8 +1803,7 @@
 void HTMLMediaElement::EncryptedMediaInitDataEncountered(
     media::EmeInitDataType init_data_type, const unsigned char* init_data,
     unsigned int init_data_length) {
-  // TODO: Implement "4. If the media data is CORS-same-origin and not mixed
-  //       content".
+  // 4. If the media data is CORS-same-origin and not mixed content.
 
   // 5. Queue a task to create an event named encrypted that does not bubble
   //    and is not cancellable using the MediaEncryptedEvent interface [...],
@@ -1723,10 +1812,20 @@
   // TODO: Implement Event.isTrusted as per
   //       https://www.w3.org/TR/dom/#dom-event-istrusted and set it to true.
   eme::MediaEncryptedEventInit media_encrypted_event_init;
-  media_encrypted_event_init.set_init_data_type(
-      ToInitDataTypeString(init_data_type));
-  media_encrypted_event_init.set_init_data(
-      new ArrayBuffer(NULL, init_data, init_data_length));
+  DCHECK(node_document()->location());
+  std::string src = this->src();
+  GURL current_url = GURL(src);
+  if (current_url.is_empty()) {
+    current_url = node_document()->url_as_gurl().Resolve(src);
+  }
+  if (!current_url.SchemeIs("http") &&
+      OriginIsSafe(request_mode_, current_url,
+                   node_document()->location()->OriginObject())) {
+    media_encrypted_event_init.set_init_data_type(
+        ToInitDataTypeString(init_data_type));
+    media_encrypted_event_init.set_init_data(
+        new ArrayBuffer(NULL, init_data, init_data_length));
+  }
   event_queue_.Enqueue(
       new eme::MediaEncryptedEvent("encrypted", media_encrypted_event_init));
 }
diff --git a/src/cobalt/dom/html_media_element.h b/src/cobalt/dom/html_media_element.h
index 31314e3..2801586 100644
--- a/src/cobalt/dom/html_media_element.h
+++ b/src/cobalt/dom/html_media_element.h
@@ -69,6 +69,9 @@
   void set_src(const std::string& src);
   const std::string& current_src() const { return current_src_; }
 
+  base::optional<std::string> cross_origin() const;
+  void set_cross_origin(const base::optional<std::string>& value);
+
   enum NetworkState {
     kNetworkEmpty,
     kNetworkIdle,
@@ -152,6 +155,8 @@
   // From Node
   void OnInsertedIntoDocument() OVERRIDE;
 
+  void TraceMembers(script::Tracer* tracer) OVERRIDE;
+
 #if defined(COBALT_MEDIA_SOURCE_2016)
   // Called by MediaSource
   void DurationChanged(double duration, bool request_seek);
@@ -234,6 +239,7 @@
   void TimeChanged(bool eos_played) OVERRIDE;
   void DurationChanged() OVERRIDE;
   void OutputModeChanged() OVERRIDE;
+  void ContentSizeChanged() OVERRIDE;
   void PlaybackStateChanged() OVERRIDE;
   void SawUnsupportedTracks() OVERRIDE;
   float Volume() const OVERRIDE;
@@ -328,6 +334,8 @@
   scoped_refptr<eme::MediaKeys> media_keys_;
 #endif  // defined(COBALT_MEDIA_SOURCE_2016)
 
+  loader::RequestMode request_mode_;
+
   DISALLOW_COPY_AND_ASSIGN(HTMLMediaElement);
 };
 
diff --git a/src/cobalt/dom/html_media_element.idl b/src/cobalt/dom/html_media_element.idl
index a4b7c04..2140db8 100644
--- a/src/cobalt/dom/html_media_element.idl
+++ b/src/cobalt/dom/html_media_element.idl
@@ -21,6 +21,7 @@
   // network state
   attribute DOMString src;
   readonly attribute DOMString currentSrc;
+  attribute DOMString? crossOrigin;
   const unsigned short NETWORK_EMPTY = 0;
   const unsigned short NETWORK_IDLE = 1;
   const unsigned short NETWORK_LOADING = 2;
diff --git a/src/cobalt/dom/html_script_element.cc b/src/cobalt/dom/html_script_element.cc
index fd4a4b7..8f9bdba 100644
--- a/src/cobalt/dom/html_script_element.cc
+++ b/src/cobalt/dom/html_script_element.cc
@@ -40,6 +40,22 @@
 
 bool PermitAnyURL(const GURL&, bool) { return true; }
 
+loader::RequestMode GetRequestMode(
+    const base::optional<std::string>& cross_origin_attribute) {
+  // https://html.spec.whatwg.org/#cors-settings-attribute
+  if (cross_origin_attribute) {
+    if (*cross_origin_attribute == "use-credentials") {
+      return loader::kCORSModeIncludeCredentials;
+    } else {
+      // The invalid value default of crossorigin is Anonymous state, leading to
+      // "same-origin" credentials mode.
+      return loader::kCORSModeSameOriginCredentials;
+    }
+  }
+  // crossorigin attribute's missing value default is No CORS state, leading to
+  // "no-cors" request mode.
+  return loader::kNoCORSMode;
+}
 }  // namespace
 
 // static
@@ -58,6 +74,26 @@
   DCHECK(document->html_element_context()->script_runner());
 }
 
+base::optional<std::string> HTMLScriptElement::cross_origin() const {
+  base::optional<std::string> cross_origin_attribute =
+      GetAttribute("crossOrigin");
+  if (cross_origin_attribute &&
+      (*cross_origin_attribute != "anonymous" &&
+       *cross_origin_attribute != "use-credentials")) {
+    return std::string();
+  }
+  return cross_origin_attribute;
+}
+
+void HTMLScriptElement::set_cross_origin(
+    const base::optional<std::string>& value) {
+  if (value) {
+    SetAttribute("crossOrigin", *value);
+  } else {
+    RemoveAttribute("crossOrigin");
+  }
+}
+
 void HTMLScriptElement::OnInsertedIntoDocument() {
   HTMLElement::OnInsertedIntoDocument();
   if (!is_parser_inserted_) {
@@ -239,9 +275,12 @@
                    CspDelegate::kScript);
   }
 
-  // Clear origin before start.
+  // Clear fetched resource's origin before start.
   fetched_last_url_origin_ = loader::Origin();
 
+  // Determine request mode from crossorigin attribute.
+  request_mode_ = GetRequestMode(GetAttribute("crossOrigin"));
+
   switch (load_option_) {
     case 2: {
       // If the element has a src attribute, and the element has been flagged as
@@ -257,7 +296,9 @@
           base::Bind(
               &loader::FetcherFactory::CreateSecureFetcher,
               base::Unretained(html_element_context()->fetcher_factory()), url_,
-              csp_callback, loader::kNoCORSMode, loader::Origin()),
+              csp_callback, request_mode_,
+              document_->location() ? document_->location()->OriginObject()
+                                    : loader::Origin()),
           base::Bind(&loader::TextDecoder::Create,
                      base::Bind(&HTMLScriptElement::OnSyncLoadingDone,
                                 base::Unretained(this))),
@@ -298,7 +339,9 @@
           base::Bind(
               &loader::FetcherFactory::CreateSecureFetcher,
               base::Unretained(html_element_context()->fetcher_factory()), url_,
-              csp_callback, loader::kNoCORSMode, loader::Origin()),
+              csp_callback, request_mode_,
+              document_->location() ? document_->location()->OriginObject()
+                                    : loader::Origin()),
           scoped_ptr<loader::Decoder>(new loader::TextDecoder(base::Bind(
               &HTMLScriptElement::OnLoadingDone, base::Unretained(this)))),
           base::Bind(&HTMLScriptElement::OnLoadingError,
@@ -323,7 +366,9 @@
           base::Bind(
               &loader::FetcherFactory::CreateSecureFetcher,
               base::Unretained(html_element_context()->fetcher_factory()), url_,
-              csp_callback, loader::kNoCORSMode, loader::Origin()),
+              csp_callback, request_mode_,
+              document_->location() ? document_->location()->OriginObject()
+                                    : loader::Origin()),
           scoped_ptr<loader::Decoder>(new loader::TextDecoder(base::Bind(
               &HTMLScriptElement::OnLoadingDone, base::Unretained(this)))),
           base::Bind(&HTMLScriptElement::OnLoadingError,
@@ -531,6 +576,7 @@
   // the script settings object of the script element's Document's Window
   // object.
   bool mute_errors =
+      request_mode_ == loader::kNoCORSMode &&
       fetched_last_url_origin_ != document_->location()->OriginObject();
   html_element_context()->script_runner()->Execute(
       content, script_location, mute_errors, NULL /*out_succeeded*/);
diff --git a/src/cobalt/dom/html_script_element.h b/src/cobalt/dom/html_script_element.h
index b444426..efc7252 100644
--- a/src/cobalt/dom/html_script_element.h
+++ b/src/cobalt/dom/html_script_element.h
@@ -51,6 +51,9 @@
   bool async() const { return GetBooleanAttribute("async"); }
   void set_async(bool value) { SetBooleanAttribute("async", value); }
 
+  base::optional<std::string> cross_origin() const;
+  void set_cross_origin(const base::optional<std::string>& value);
+
   std::string nonce() const { return GetAttribute("nonce").value_or(""); }
   void set_nonce(const std::string& value) { SetAttribute("nonce", value); }
 
@@ -142,6 +145,9 @@
   // Whether or not the script should execute at all.
   bool should_execute_;
 
+  // The request mode for the fetch request.
+  loader::RequestMode request_mode_;
+
   // Will be compared with document's origin to derive mute_errors flag
   // javascript parser takes in to record if the error reqort should be muted
   // due to cross-origin fetched script.
diff --git a/src/cobalt/dom/html_script_element.idl b/src/cobalt/dom/html_script_element.idl
index c0511e9..0c2b1ea 100644
--- a/src/cobalt/dom/html_script_element.idl
+++ b/src/cobalt/dom/html_script_element.idl
@@ -19,6 +19,7 @@
   attribute DOMString type;
   attribute DOMString charset;
   attribute boolean async;
+  attribute DOMString? crossOrigin;
   // From Content Security Policy spec.
   attribute DOMString nonce;
 
diff --git a/src/cobalt/dom/html_video_element.cc b/src/cobalt/dom/html_video_element.cc
index 08bd8b5..8b63f37 100644
--- a/src/cobalt/dom/html_video_element.cc
+++ b/src/cobalt/dom/html_video_element.cc
@@ -16,6 +16,7 @@
 
 #include "base/logging.h"
 #include "base/string_number_conversions.h"
+#include "cobalt/math/size_f.h"
 
 namespace cobalt {
 namespace dom {
@@ -96,5 +97,9 @@
   return player() ? player()->GetSetBoundsCB() : WebMediaPlayer::SetBoundsCB();
 }
 
+math::SizeF HTMLVideoElement::GetVideoSize() const {
+  return math::SizeF(video_width(), video_height());
+}
+
 }  // namespace dom
 }  // namespace cobalt
diff --git a/src/cobalt/dom/html_video_element.h b/src/cobalt/dom/html_video_element.h
index 7d0e1df..45396d1 100644
--- a/src/cobalt/dom/html_video_element.h
+++ b/src/cobalt/dom/html_video_element.h
@@ -20,6 +20,7 @@
 #include "cobalt/dom/html_media_element.h"
 #include "cobalt/dom/video_playback_quality.h"
 #include "cobalt/math/rect.h"
+#include "cobalt/math/size_f.h"
 #if !defined(COBALT_MEDIA_SOURCE_2016)
 #include "media/base/shell_video_frame_provider.h"
 #endif  // !defined(COBALT_MEDIA_SOURCE_2016)
@@ -63,6 +64,8 @@
 
   WebMediaPlayer::SetBoundsCB GetSetBoundsCB();
 
+  math::SizeF GetVideoSize() const;
+
   DEFINE_WRAPPABLE_TYPE(HTMLVideoElement);
 
  private:
diff --git a/src/cobalt/dom/input_event.cc b/src/cobalt/dom/input_event.cc
new file mode 100644
index 0000000..71ae36f
--- /dev/null
+++ b/src/cobalt/dom/input_event.cc
@@ -0,0 +1,54 @@
+// Copyright 2017 Google Inc. All Rights Reserved.
+//
+// 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.
+
+#include "cobalt/dom/input_event.h"
+
+#include <string>
+
+#include "base/logging.h"
+#include "base/memory/scoped_ptr.h"
+#include "cobalt/base/token.h"
+#include "cobalt/base/tokens.h"
+
+namespace cobalt {
+namespace dom {
+
+InputEvent::InputEvent(const std::string& type)
+    : UIEvent(base::Token(type), kBubbles, kCancelable, NULL),
+      data_(""),
+      is_composing_(false) {}
+
+InputEvent::InputEvent(const std::string& type, const InputEventInit& init_dict)
+    : UIEvent(base::Token(type), kBubbles, kCancelable, init_dict.view(),
+              init_dict),
+      data_(init_dict.data()),
+      is_composing_(init_dict.is_composing()) {}
+
+InputEvent::InputEvent(base::Token type, const scoped_refptr<Window>& view,
+                       const InputEventInit& init_dict)
+    : UIEvent(type, kBubbles, kCancelable, view, init_dict),
+      data_(init_dict.data()),
+      is_composing_(init_dict.is_composing()) {}
+
+void InputEvent::InitInputEvent(const std::string& type, bool bubbles,
+                                bool cancelable,
+                                const scoped_refptr<Window>& view,
+                                const std::string& data, bool is_composing) {
+  InitUIEvent(type, bubbles, cancelable, view, 0);
+  data_ = data;
+  is_composing_ = is_composing;
+}
+
+}  // namespace dom
+}  // namespace cobalt
diff --git a/src/cobalt/dom/input_event.h b/src/cobalt/dom/input_event.h
new file mode 100644
index 0000000..966fe11
--- /dev/null
+++ b/src/cobalt/dom/input_event.h
@@ -0,0 +1,61 @@
+// Copyright 2017 Google Inc. All Rights Reserved.
+//
+// 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.
+
+#ifndef COBALT_DOM_INPUT_EVENT_H_
+#define COBALT_DOM_INPUT_EVENT_H_
+
+#include <string>
+
+#include "base/memory/scoped_ptr.h"
+#include "cobalt/dom/input_event_init.h"
+#include "cobalt/dom/ui_event_with_key_state.h"
+
+namespace cobalt {
+namespace dom {
+
+// The InputEvent provides specific contextual information associated with
+// input devices.
+// Input events are commonly directed at the element that has the focus.
+//   https://www.w3.org/TR/2016/WD-uievents-20160804/#events-inputevents
+class InputEvent : public UIEvent {
+ public:
+  // Web API: InputEvent
+  //
+  explicit InputEvent(const std::string& type);
+  InputEvent(const std::string& type, const InputEventInit& init_dict);
+  InputEvent(base::Token type, const scoped_refptr<Window>& view,
+             const InputEventInit& init_dict);
+
+  void InitInputEvent(const std::string& type, bool bubbles, bool cancelable,
+                      const scoped_refptr<Window>& view,
+                      const std::string& data, bool is_composing);
+
+  // Returns the data.
+  std::string data() const { return data_; }
+
+  bool is_composing() const { return is_composing_; }
+
+  DEFINE_WRAPPABLE_TYPE(InputEvent);
+
+ private:
+  ~InputEvent() OVERRIDE {}
+
+  std::string data_;
+  bool is_composing_;
+};
+
+}  // namespace dom
+}  // namespace cobalt
+
+#endif  // COBALT_DOM_INPUT_EVENT_H_
diff --git a/src/cobalt/dom/input_event.idl b/src/cobalt/dom/input_event.idl
new file mode 100644
index 0000000..afb6db9
--- /dev/null
+++ b/src/cobalt/dom/input_event.idl
@@ -0,0 +1,21 @@
+// Copyright 2017 Google Inc. All Rights Reserved.
+//
+// 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.
+
+// https://www.w3.org/TR/2016/WD-uievents-20160804/#events-inputevents
+
+[Constructor(DOMString type, optional InputEventInit eventInitDict)]
+interface InputEvent : UIEvent {
+  readonly attribute DOMString data;
+  readonly attribute boolean isComposing;
+};
diff --git a/src/cobalt/dom/input_event_init.idl b/src/cobalt/dom/input_event_init.idl
new file mode 100644
index 0000000..2a5f864
--- /dev/null
+++ b/src/cobalt/dom/input_event_init.idl
@@ -0,0 +1,20 @@
+// Copyright 2017 Google Inc. All Rights Reserved.
+//
+// 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.
+
+// https://www.w3.org/TR/uievents/#dictdef-inputeventinit
+
+dictionary InputEventInit : EventModifierInit {
+  DOMString data = "";
+  boolean isComposing = false;
+};
diff --git a/src/cobalt/dom/media_source.cc b/src/cobalt/dom/media_source.cc
index d8330cb..54cdbe5 100644
--- a/src/cobalt/dom/media_source.cc
+++ b/src/cobalt/dom/media_source.cc
@@ -348,5 +348,12 @@
   }
 }
 
+void MediaSource::TraceMembers(script::Tracer* tracer) {
+  EventTarget::TraceMembers(tracer);
+
+  event_queue_.TraceMembers(tracer);
+  tracer->Trace(source_buffers_);
+}
+
 }  // namespace dom
 }  // namespace cobalt
diff --git a/src/cobalt/dom/media_source.h b/src/cobalt/dom/media_source.h
index d266621..a1b7275 100644
--- a/src/cobalt/dom/media_source.h
+++ b/src/cobalt/dom/media_source.h
@@ -97,6 +97,8 @@
   // Methods used by HTMLMediaElement
   void SetReadyState(MediaSourceReadyState ready_state);
 
+  void TraceMembers(script::Tracer* tracer) OVERRIDE;
+
   DEFINE_WRAPPABLE_TYPE(MediaSource);
 
  private:
diff --git a/src/cobalt/dom/media_source/media_source.cc b/src/cobalt/dom/media_source/media_source.cc
index e90cf46..9cabe97 100644
--- a/src/cobalt/dom/media_source/media_source.cc
+++ b/src/cobalt/dom/media_source/media_source.cc
@@ -516,6 +516,16 @@
   return attached_element_;
 }
 
+void MediaSource::TraceMembers(script::Tracer* tracer) {
+  EventTarget::TraceMembers(tracer);
+
+  event_queue_.TraceMembers(tracer);
+  tracer->Trace(attached_element_);
+  tracer->Trace(source_buffers_);
+  tracer->Trace(active_source_buffers_);
+  tracer->Trace(live_seekable_range_);
+}
+
 void MediaSource::SetReadyState(MediaSourceReadyState ready_state) {
   if (ready_state == kMediaSourceReadyStateClosed) {
     chunk_demuxer_ = NULL;
diff --git a/src/cobalt/dom/media_source/media_source.h b/src/cobalt/dom/media_source/media_source.h
index 234768d..de18f71 100644
--- a/src/cobalt/dom/media_source/media_source.h
+++ b/src/cobalt/dom/media_source/media_source.h
@@ -121,6 +121,8 @@
   void SetSourceBufferActive(SourceBuffer* source_buffer, bool is_active);
   HTMLMediaElement* GetMediaElement() const;
 
+  void TraceMembers(script::Tracer* tracer) OVERRIDE;
+
   DEFINE_WRAPPABLE_TYPE(MediaSource);
 
  private:
diff --git a/src/cobalt/dom/media_source/source_buffer.cc b/src/cobalt/dom/media_source/source_buffer.cc
index 0f1981d..04e26f6 100644
--- a/src/cobalt/dom/media_source/source_buffer.cc
+++ b/src/cobalt/dom/media_source/source_buffer.cc
@@ -341,6 +341,18 @@
   return chunk_demuxer_->GetHighestPresentationTimestamp(id_).InSecondsF();
 }
 
+void SourceBuffer::TraceMembers(script::Tracer* tracer) {
+  EventTarget::TraceMembers(tracer);
+
+  if (event_queue_) {
+    event_queue_->TraceMembers(tracer);
+  }
+  tracer->Trace(media_source_);
+  tracer->Trace(track_defaults_);
+  tracer->Trace(audio_tracks_);
+  tracer->Trace(video_tracks_);
+}
+
 void SourceBuffer::InitSegmentReceived(scoped_ptr<MediaTracks> tracks) {
   UNREFERENCED_PARAMETER(tracks);
 
diff --git a/src/cobalt/dom/media_source/source_buffer.h b/src/cobalt/dom/media_source/source_buffer.h
index 7e508bc..cf1547e 100644
--- a/src/cobalt/dom/media_source/source_buffer.h
+++ b/src/cobalt/dom/media_source/source_buffer.h
@@ -133,6 +133,8 @@
   void OnRemovedFromMediaSource();
   double GetHighestPresentationTimestamp() const;
 
+  void TraceMembers(script::Tracer* tracer) OVERRIDE;
+
   DEFINE_WRAPPABLE_TYPE(SourceBuffer);
 
  private:
diff --git a/src/cobalt/dom/media_source/source_buffer_list.cc b/src/cobalt/dom/media_source/source_buffer_list.cc
index e43f2fe..5bf50c4 100644
--- a/src/cobalt/dom/media_source/source_buffer_list.cc
+++ b/src/cobalt/dom/media_source/source_buffer_list.cc
@@ -122,6 +122,17 @@
   ScheduleEvent(base::Tokens::removesourcebuffer());
 }
 
+void SourceBufferList::TraceMembers(script::Tracer* tracer) {
+  EventTarget::TraceMembers(tracer);
+
+  if (event_queue_) {
+    event_queue_->TraceMembers(tracer);
+  }
+  for (const auto& source_buffer : source_buffers_) {
+    tracer->Trace(source_buffer);
+  }
+}
+
 void SourceBufferList::ScheduleEvent(base::Token event_name) {
   scoped_refptr<Event> event = new Event(event_name);
   event->set_target(this);
diff --git a/src/cobalt/dom/media_source/source_buffer_list.h b/src/cobalt/dom/media_source/source_buffer_list.h
index 8ac639c..8f708c2 100644
--- a/src/cobalt/dom/media_source/source_buffer_list.h
+++ b/src/cobalt/dom/media_source/source_buffer_list.h
@@ -83,6 +83,8 @@
   bool Contains(const scoped_refptr<SourceBuffer>& source_buffer) const;
   void Clear();
 
+  void TraceMembers(script::Tracer* tracer) OVERRIDE;
+
   DEFINE_WRAPPABLE_TYPE(SourceBufferList);
 
  private:
diff --git a/src/cobalt/dom/on_screen_keyboard.cc b/src/cobalt/dom/on_screen_keyboard.cc
new file mode 100644
index 0000000..21570ae
--- /dev/null
+++ b/src/cobalt/dom/on_screen_keyboard.cc
@@ -0,0 +1,93 @@
+// Copyright 2017 Google Inc. All Rights Reserved.
+//
+// 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.
+
+#include "cobalt/dom/on_screen_keyboard.h"
+#include "base/callback.h"
+#include "cobalt/dom/event_target.h"
+#include "cobalt/dom/window.h"
+#include "starboard/log.h"
+#include "starboard/window.h"
+
+namespace cobalt {
+namespace dom {
+OnScreenKeyboard::OnScreenKeyboard(
+    const Window::GetSbWindowCallback& get_sb_window_callback)
+    : get_sb_window_callback_(get_sb_window_callback) {
+  CHECK(!get_sb_window_callback_.is_null());
+}
+
+void OnScreenKeyboard::Show() {
+#if SB_HAS(ON_SCREEN_KEYBOARD)
+  SbWindow sb_window = get_sb_window_callback_.Run();
+
+  if (!sb_window) {
+    LOG(ERROR) << "OnScreenKeyboard::Show invalid without SbWindow.";
+    return;
+  }
+  SbWindowShowOnScreenKeyboard(sb_window, data_.c_str());
+  // Trigger onshow.
+  DispatchEvent(new dom::Event(base::Tokens::show()));
+#endif  // SB_HAS(ON_SCREEN_KEYBOARD)
+}
+
+void OnScreenKeyboard::Hide() {
+#if SB_HAS(ON_SCREEN_KEYBOARD)
+  SbWindow sb_window = get_sb_window_callback_.Run();
+
+  if (!sb_window) {
+    LOG(ERROR) << "OnScreenKeyboard::Hide invalid without SbWindow.";
+    return;
+  }
+  SbWindowHideOnScreenKeyboard(sb_window);
+  // Trigger onhide.
+  DispatchEvent(new dom::Event(base::Tokens::hide()));
+#endif  // SB_HAS(ON_SCREEN_KEYBOARD)
+}
+
+const EventTarget::EventListenerScriptValue* OnScreenKeyboard::onshow() const {
+  return GetAttributeEventListener(base::Tokens::show());
+}
+void OnScreenKeyboard::set_onshow(
+    const EventListenerScriptValue& event_listener) {
+  SetAttributeEventListener(base::Tokens::show(), event_listener);
+}
+
+const EventTarget::EventListenerScriptValue* OnScreenKeyboard::onhide() const {
+  return GetAttributeEventListener(base::Tokens::hide());
+}
+void OnScreenKeyboard::set_onhide(
+    const EventListenerScriptValue& event_listener) {
+  SetAttributeEventListener(base::Tokens::hide(), event_listener);
+}
+
+const EventTarget::EventListenerScriptValue* OnScreenKeyboard::oninput() const {
+  return GetAttributeEventListener(base::Tokens::input());
+}
+
+void OnScreenKeyboard::set_oninput(
+    const EventListenerScriptValue& event_listener) {
+  SetAttributeEventListener(base::Tokens::input(), event_listener);
+}
+
+bool OnScreenKeyboard::shown() const {
+#if SB_HAS(ON_SCREEN_KEYBOARD)
+  SbWindow sb_window = get_sb_window_callback_.Run();
+  return SbWindowIsOnScreenKeyboardShown(sb_window);
+#else   // SB_HAS(ON_SCREEN_KEYBOARD)
+  return false;
+#endif  // SB_HAS(ON_SCREEN_KEYBOARD)
+}
+
+}  // namespace dom
+}  // namespace cobalt
diff --git a/src/cobalt/dom/on_screen_keyboard.h b/src/cobalt/dom/on_screen_keyboard.h
new file mode 100644
index 0000000..fcc95fe
--- /dev/null
+++ b/src/cobalt/dom/on_screen_keyboard.h
@@ -0,0 +1,73 @@
+// Copyright 2017 Google Inc. All Rights Reserved.
+//
+// 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.
+
+#ifndef COBALT_DOM_ON_SCREEN_KEYBOARD_H_
+#define COBALT_DOM_ON_SCREEN_KEYBOARD_H_
+
+#include <string>
+
+#include "base/callback.h"
+#include "cobalt/base/tokens.h"
+#include "cobalt/dom/event_target.h"
+#include "cobalt/dom/window.h"
+#include "cobalt/script/wrappable.h"
+#include "starboard/window.h"
+
+namespace cobalt {
+namespace dom {
+
+class Window;
+
+class OnScreenKeyboard : public EventTarget {
+ public:
+  explicit OnScreenKeyboard(
+      const base::Callback<SbWindow()>& get_sb_window_callback);
+
+  // Shows the on screen keyboard by calling a Starboard function
+  // and dispatches an onshow event.
+  void Show();
+
+  // Hides the on screen keyboard by calling a Starboard function,
+  // and dispatches an onhide event.
+  void Hide();
+
+  std::string data() const { return data_; }
+  void set_data(const std::string& data) { data_ = data; }
+
+  const EventListenerScriptValue* onshow() const;
+  void set_onshow(const EventListenerScriptValue& event_listener);
+
+  const EventListenerScriptValue* onhide() const;
+  void set_onhide(const EventListenerScriptValue& event_listener);
+
+  const EventListenerScriptValue* oninput() const;
+  void set_oninput(const EventListenerScriptValue& event_listener);
+
+  // If the keyboard is shown.
+  bool shown() const;
+
+  DEFINE_WRAPPABLE_TYPE(OnScreenKeyboard);
+
+ private:
+  ~OnScreenKeyboard() OVERRIDE {}
+  const base::Callback<SbWindow()> get_sb_window_callback_;
+
+  std::string data_;
+
+  DISALLOW_COPY_AND_ASSIGN(OnScreenKeyboard);
+};
+}  // namespace dom
+}  // namespace cobalt
+
+#endif  // COBALT_DOM_ON_SCREEN_KEYBOARD_H_
diff --git a/src/cobalt/dom/on_screen_keyboard.idl b/src/cobalt/dom/on_screen_keyboard.idl
new file mode 100644
index 0000000..db1cd4a
--- /dev/null
+++ b/src/cobalt/dom/on_screen_keyboard.idl
@@ -0,0 +1,28 @@
+// Copyright 2017 Google Inc. All Rights Reserved.
+//
+// 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.
+
+// Custom API for hiding, showing, and receiving input from an on
+// screen keyboard.
+
+interface OnScreenKeyboard {
+  void show();
+  void hide();
+  readonly attribute boolean shown;
+
+  attribute DOMString data;
+
+  attribute EventHandler onshow;
+  attribute EventHandler onhide;
+  attribute EventHandler oninput;
+};
diff --git a/src/cobalt/dom/source_buffer.cc b/src/cobalt/dom/source_buffer.cc
index ded4c04..8266328 100644
--- a/src/cobalt/dom/source_buffer.cc
+++ b/src/cobalt/dom/source_buffer.cc
@@ -85,5 +85,11 @@
 
 void SourceBuffer::Close() { media_source_ = NULL; }
 
+void SourceBuffer::TraceMembers(script::Tracer* tracer) {
+  EventTarget::TraceMembers(tracer);
+
+  tracer->Trace(media_source_);
+}
+
 }  // namespace dom
 }  // namespace cobalt
diff --git a/src/cobalt/dom/source_buffer.h b/src/cobalt/dom/source_buffer.h
index c7f5a59..630828d 100644
--- a/src/cobalt/dom/source_buffer.h
+++ b/src/cobalt/dom/source_buffer.h
@@ -64,6 +64,8 @@
   // Detach it from the MediaSource object.
   void Close();
 
+  void TraceMembers(script::Tracer* tracer) OVERRIDE;
+
   DEFINE_WRAPPABLE_TYPE(SourceBuffer);
 
  private:
diff --git a/src/cobalt/dom/source_buffer_list.cc b/src/cobalt/dom/source_buffer_list.cc
index 5a33206..c9ea04d 100644
--- a/src/cobalt/dom/source_buffer_list.cc
+++ b/src/cobalt/dom/source_buffer_list.cc
@@ -89,5 +89,16 @@
   }
 }
 
+void SourceBufferList::TraceMembers(script::Tracer* tracer) {
+  EventTarget::TraceMembers(tracer);
+
+  if (event_queue_) {
+    event_queue_->TraceMembers(tracer);
+  }
+  for (const auto& source_buffer : source_buffers_) {
+    tracer->Trace(source_buffer);
+  }
+}
+
 }  // namespace dom
 }  // namespace cobalt
diff --git a/src/cobalt/dom/source_buffer_list.h b/src/cobalt/dom/source_buffer_list.h
index 672679e..b9e760a 100644
--- a/src/cobalt/dom/source_buffer_list.h
+++ b/src/cobalt/dom/source_buffer_list.h
@@ -57,6 +57,8 @@
   bool Remove(const scoped_refptr<SourceBuffer>& source_buffer);
   void Clear();
 
+  void TraceMembers(script::Tracer* tracer) OVERRIDE;
+
   DEFINE_WRAPPABLE_TYPE(SourceBufferList);
 
  private:
diff --git a/src/cobalt/dom/testing/stub_window.h b/src/cobalt/dom/testing/stub_window.h
index c437133..796094b 100644
--- a/src/cobalt/dom/testing/stub_window.h
+++ b/src/cobalt/dom/testing/stub_window.h
@@ -30,10 +30,16 @@
 #include "cobalt/script/global_environment.h"
 #include "cobalt/script/javascript_engine.h"
 #include "googleurl/src/gurl.h"
+#include "starboard/window.h"
 
 namespace cobalt {
 namespace dom {
 namespace testing {
+namespace {
+// Return a NULL SbWindow, since we do not need to pass a valid SbWindow to an
+// on screen keyboard.
+SbWindow GetNullSbWindow() { return NULL; }
+}  // namespace
 
 // A helper class for tests that brings up a dom::Window with a number of parts
 // stubbed out.
@@ -53,13 +59,14 @@
         1920, 1080, 1.f, base::kApplicationStateStarted, css_parser_.get(),
         dom_parser_.get(), fetcher_factory_.get(), NULL, NULL, NULL, NULL, NULL,
         NULL, &local_storage_database_, NULL, NULL, NULL, NULL, NULL, NULL,
-        dom_stat_tracker_.get(), url_, "", "en-US",
+        dom_stat_tracker_.get(), url_, "", "en-US", "en",
         base::Callback<void(const GURL&)>(), base::Bind(&StubErrorCallback),
         NULL, network_bridge::PostSender(), csp::kCSPRequired,
         dom::kCspEnforcementEnable, base::Closure() /* csp_policy_changed */,
         base::Closure() /* ran_animation_frame_callbacks */,
         dom::Window::CloseCallback() /* window_close */,
-        base::Closure() /* window_minimize */, NULL, NULL);
+        base::Closure() /* window_minimize */, base::Bind(&GetNullSbWindow),
+        NULL, NULL);
     global_environment_->CreateGlobalObject(window_, &environment_settings_);
   }
 
diff --git a/src/cobalt/dom/window.cc b/src/cobalt/dom/window.cc
index 9d0a291..e762e06 100644
--- a/src/cobalt/dom/window.cc
+++ b/src/cobalt/dom/window.cc
@@ -35,6 +35,7 @@
 #include "cobalt/dom/history.h"
 #include "cobalt/dom/html_element.h"
 #include "cobalt/dom/html_element_context.h"
+#include "cobalt/dom/input_event.h"
 #include "cobalt/dom/keyboard_event.h"
 #include "cobalt/dom/location.h"
 #include "cobalt/dom/media_source.h"
@@ -94,6 +95,7 @@
                MediaSource::Registry* media_source_registry,
                DomStatTracker* dom_stat_tracker, const GURL& url,
                const std::string& user_agent, const std::string& language,
+               const std::string& font_language_script,
                const base::Callback<void(const GURL&)> navigation_callback,
                const base::Callback<void(const std::string&)>& error_callback,
                network_bridge::CookieJar* cookie_jar,
@@ -104,6 +106,7 @@
                const base::Closure& ran_animation_frame_callbacks_callback,
                const CloseCallback& window_close_callback,
                const base::Closure& window_minimize_callback,
+               const base::Callback<SbWindow()>& get_sb_window_callback,
                const scoped_refptr<input::Camera3D>& camera_3d,
                const scoped_refptr<MediaSession>& media_session,
                int csp_insecure_allowed_token, int dom_max_element_depth,
@@ -122,8 +125,9 @@
           web_media_player_factory, script_runner, script_value_factory,
           media_source_registry, resource_provider, animated_image_tracker,
           image_cache, reduced_image_cache_capacity_manager,
-          remote_typeface_cache, mesh_cache, dom_stat_tracker, language,
-          initial_application_state, video_playback_rate_multiplier)),
+          remote_typeface_cache, mesh_cache, dom_stat_tracker,
+          font_language_script, initial_application_state,
+          video_playback_rate_multiplier)),
       performance_(new Performance(
 #if defined(ENABLE_TEST_RUNNER)
           clock_type == kClockTypeTestRunner ? test_runner_->GetClock() :
@@ -161,7 +165,13 @@
           ran_animation_frame_callbacks_callback),
       window_close_callback_(window_close_callback),
       window_minimize_callback_(window_minimize_callback),
+#if SB_HAS(ON_SCREEN_KEYBOARD)
+      on_screen_keyboard_(new OnScreenKeyboard(get_sb_window_callback)),
+#endif  // SB_HAS(ON_SCREEN_KEYBOARD)
       splash_screen_cache_callback_(splash_screen_cache_callback) {
+#if !SB_HAS(ON_SCREEN_KEYBOARD)
+  UNREFERENCED_PARAMETER(get_sb_window_callback);
+#endif  // !SB_HAS(ON_SCREEN_KEYBOARD)
 #if !defined(ENABLE_TEST_RUNNER)
   UNREFERENCED_PARAMETER(clock_type);
 #endif
@@ -441,6 +451,11 @@
     } else {
       document_->DispatchEvent(event);
     }
+  } else if (event->GetWrappableType() == base::GetTypeId<InputEvent>()) {
+    // Dispatch any InputEvent directly to the OnScreenKeyboard element.
+    if (on_screen_keyboard_) {
+      on_screen_keyboard_->DispatchEvent(event);
+    }
   } else if (event->GetWrappableType() == base::GetTypeId<PointerEvent>() ||
              event->GetWrappableType() == base::GetTypeId<MouseEvent>() ||
              event->GetWrappableType() == base::GetTypeId<WheelEvent>()) {
@@ -593,6 +608,10 @@
   splash_screen_cache_callback_.Run(location()->url(), content);
 }
 
+const scoped_refptr<OnScreenKeyboard>& Window::on_screen_keyboard() const {
+  return on_screen_keyboard_;
+}
+
 Window::~Window() {
   html_element_context_->page_visibility_state()->RemoveObserver(this);
 }
diff --git a/src/cobalt/dom/window.h b/src/cobalt/dom/window.h
index 93c0e32..c54d44c 100644
--- a/src/cobalt/dom/window.h
+++ b/src/cobalt/dom/window.h
@@ -34,6 +34,7 @@
 #include "cobalt/dom/html_element_context.h"
 #include "cobalt/dom/location.h"
 #include "cobalt/dom/media_query_list.h"
+#include "cobalt/dom/on_screen_keyboard.h"
 #include "cobalt/dom/parser.h"
 #if defined(ENABLE_TEST_RUNNER)
 #include "cobalt/dom/test_runner.h"
@@ -85,6 +86,7 @@
 class Location;
 class MediaSource;
 class Navigator;
+class OnScreenKeyboard;
 class Performance;
 class Screen;
 class Storage;
@@ -111,6 +113,7 @@
   typedef base::Callback<void(base::TimeDelta)> CloseCallback;
   typedef UrlRegistry<MediaSource> MediaSourceRegistry;
   typedef base::Callback<bool(const GURL&, const std::string&)> CacheCallback;
+  typedef base::Callback<SbWindow()> GetSbWindowCallback;
   enum ClockType { kClockTypeTestRunner, kClockTypeSystemTime };
 
   Window(
@@ -134,6 +137,7 @@
       MediaSourceRegistry* media_source_registry,
       DomStatTracker* dom_stat_tracker, const GURL& url,
       const std::string& user_agent, const std::string& language,
+      const std::string& font_language_script,
       const base::Callback<void(const GURL&)> navigation_callback,
       const base::Callback<void(const std::string&)>& error_callback,
       network_bridge::CookieJar* cookie_jar,
@@ -144,6 +148,7 @@
       const base::Closure& ran_animation_frame_callbacks_callback,
       const CloseCallback& window_close_callback,
       const base::Closure& window_minimize_callback,
+      const base::Callback<SbWindow()>& get_sb_window_callback,
       const scoped_refptr<input::Camera3D>& camera_3d,
       const scoped_refptr<cobalt::media_session::MediaSession>& media_session,
       int csp_insecure_allowed_token = 0, int dom_max_element_depth = 0,
@@ -339,6 +344,9 @@
     return preflight_cache_;
   }
 
+  // Custom on screen keyboard.
+  const scoped_refptr<OnScreenKeyboard>& on_screen_keyboard() const;
+
   DEFINE_WRAPPABLE_TYPE(Window);
 
  private:
@@ -400,6 +408,9 @@
   const base::Closure ran_animation_frame_callbacks_callback_;
   const CloseCallback window_close_callback_;
   const base::Closure window_minimize_callback_;
+  const GetSbWindowCallback get_sb_window_callback_;
+
+  scoped_refptr<OnScreenKeyboard> on_screen_keyboard_;
 
   CacheCallback splash_screen_cache_callback_;
 
diff --git a/src/cobalt/dom/window_on_screen_keyboard.idl b/src/cobalt/dom/window_on_screen_keyboard.idl
new file mode 100644
index 0000000..3fdb0a1
--- /dev/null
+++ b/src/cobalt/dom/window_on_screen_keyboard.idl
@@ -0,0 +1,20 @@
+// Copyright 2017 Google Inc. All Rights Reserved.
+//
+// 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.
+
+// Custom API for hiding, showing, and receiving input from an on
+// screen keyboard.
+
+partial interface Window {
+  readonly attribute OnScreenKeyboard onScreenKeyboard;
+};
diff --git a/src/cobalt/dom/window_test.cc b/src/cobalt/dom/window_test.cc
index 04b2ef9..1341c81 100644
--- a/src/cobalt/dom/window_test.cc
+++ b/src/cobalt/dom/window_test.cc
@@ -28,11 +28,17 @@
 #include "cobalt/network/network_module.h"
 #include "cobalt/network_bridge/net_poster.h"
 #include "googleurl/src/gurl.h"
+#include "starboard/window.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace cobalt {
 namespace dom {
+namespace {
+// Return a NULL SbWindow, since we do not need to pass a valid SbWindow to an
+// on screen keyboard.
+SbWindow GetNullSbWindow() { return NULL; }
+}  // namespace
 
 class MockErrorCallback : public base::Callback<void(const std::string&)> {
  public:
@@ -52,14 +58,16 @@
             1920, 1080, 1.f, base::kApplicationStateStarted, css_parser_.get(),
             dom_parser_.get(), fetcher_factory_.get(), NULL, NULL, NULL, NULL,
             NULL, NULL, &local_storage_database_, NULL, NULL, NULL, NULL, NULL,
-            NULL, NULL, url_, "", "en-US", base::Callback<void(const GURL &)>(),
+            NULL, NULL, url_, "", "en-US", "en",
+            base::Callback<void(const GURL &)>(),
             base::Bind(&MockErrorCallback::Run,
                        base::Unretained(&mock_error_callback_)),
             NULL, network_bridge::PostSender(), csp::kCSPRequired,
             kCspEnforcementEnable, base::Closure() /* csp_policy_changed */,
             base::Closure() /* ran_animation_frame_callbacks */,
             dom::Window::CloseCallback() /* window_close */,
-            base::Closure() /* window_minimize */, NULL, NULL)) {}
+            base::Closure() /* window_minimize */, base::Bind(&GetNullSbWindow),
+            NULL, NULL)) {}
 
   ~WindowTest() OVERRIDE {}
 
diff --git a/src/cobalt/input/input_device_manager.h b/src/cobalt/input/input_device_manager.h
index 1fb1f14..0eab3ab 100644
--- a/src/cobalt/input/input_device_manager.h
+++ b/src/cobalt/input/input_device_manager.h
@@ -15,6 +15,7 @@
 #ifndef COBALT_INPUT_INPUT_DEVICE_MANAGER_H_
 #define COBALT_INPUT_INPUT_DEVICE_MANAGER_H_
 
+#include "cobalt/dom/input_event_init.h"
 #include "cobalt/dom/pointer_event_init.h"
 #include "cobalt/dom/wheel_event_init.h"
 #include "cobalt/input/camera_3d.h"
@@ -37,6 +38,11 @@
 typedef base::Callback<void(base::Token type, const dom::WheelEventInit&)>
     WheelEventCallback;
 
+#if SB_HAS(ON_SCREEN_KEYBOARD)
+typedef base::Callback<void(base::Token type, const dom::InputEventInit&)>
+    InputEventCallback;
+#endif  // SB_HAS(ON_SCREEN_KEYBOARD)
+
 // InputDeviceManager listens to events from platform-specific input devices
 // and maps them to platform-independent keyboard key events.
 class InputDeviceManager {
@@ -47,6 +53,9 @@
       const KeyboardEventCallback& keyboard_event_callback,
       const PointerEventCallback& pointer_event_callback,
       const WheelEventCallback& wheel_event_callback,
+#if SB_HAS(ON_SCREEN_KEYBOARD)
+      const InputEventCallback& input_event_callback,
+#endif  // SB_HAS(ON_SCREEN_KEYBOARD)
       system_window::SystemWindow* system_window);
 
   virtual ~InputDeviceManager() {}
diff --git a/src/cobalt/input/input_device_manager_desktop.cc b/src/cobalt/input/input_device_manager_desktop.cc
index 983da10..2904d04 100644
--- a/src/cobalt/input/input_device_manager_desktop.cc
+++ b/src/cobalt/input/input_device_manager_desktop.cc
@@ -19,6 +19,8 @@
 
 #include "cobalt/base/token.h"
 #include "cobalt/base/tokens.h"
+#include "cobalt/dom/input_event.h"
+#include "cobalt/dom/input_event_init.h"
 #include "cobalt/dom/keyboard_event.h"
 #include "cobalt/dom/keyboard_event_init.h"
 #include "cobalt/dom/pointer_event.h"
@@ -36,11 +38,17 @@
     const KeyboardEventCallback& keyboard_event_callback,
     const PointerEventCallback& pointer_event_callback,
     const WheelEventCallback& wheel_event_callback,
+#if SB_HAS(ON_SCREEN_KEYBOARD)
+    const InputEventCallback& input_event_callback,
+#endif  // SB_HAS(ON_SCREEN_KEYBOARD)
     system_window::SystemWindow* system_window)
     : system_window_(system_window),
-      input_event_callback_(
-          base::Bind(&InputDeviceManagerDesktop::HandleInputEvent,
+      system_window_input_event_callback_(
+          base::Bind(&InputDeviceManagerDesktop::HandleSystemWindowInputEvent,
                      base::Unretained(this))),
+#if SB_HAS(ON_SCREEN_KEYBOARD)
+      input_event_callback_(input_event_callback),
+#endif  // SB_HAS(ON_SCREEN_KEYBOARD)
       keypress_generator_filter_(keyboard_event_callback),
       pointer_event_callback_(pointer_event_callback),
       wheel_event_callback_(wheel_event_callback) {
@@ -52,7 +60,8 @@
   if (system_window_) {
     // Add this object's keyboard event callback to the system window.
     system_window_->event_dispatcher()->AddEventCallback(
-        system_window::InputEvent::TypeId(), input_event_callback_);
+        system_window::InputEvent::TypeId(),
+        system_window_input_event_callback_);
   }
 }
 
@@ -60,7 +69,8 @@
   // If we have an associated system window, remove our callback from it.
   if (system_window_) {
     system_window_->event_dispatcher()->RemoveEventCallback(
-        system_window::InputEvent::TypeId(), input_event_callback_);
+        system_window::InputEvent::TypeId(),
+        system_window_input_event_callback_);
   }
 }
 
@@ -249,7 +259,23 @@
   wheel_event_callback_.Run(type, wheel_event);
 }
 
-void InputDeviceManagerDesktop::HandleInputEvent(const base::Event* event) {
+#if SB_HAS(ON_SCREEN_KEYBOARD)
+void InputDeviceManagerDesktop::HandleInputEvent(
+    const system_window::InputEvent* event) {
+  // Note: we currently treat all dom::InputEvents as input (never beforeinput).
+  base::Token type = base::Tokens::input();
+
+  dom::InputEventInit input_event;
+  input_event.set_data(event->input_text());
+  // We do not handle composition sessions currently, so isComposing should
+  // always be false.
+  input_event.set_is_composing(false);
+  input_event_callback_.Run(type, input_event);
+}
+#endif  // SB_HAS(ON_SCREEN_KEYBOARD)
+
+void InputDeviceManagerDesktop::HandleSystemWindowInputEvent(
+    const base::Event* event) {
   // The user has pressed a key on the keyboard.
   const system_window::InputEvent* input_event =
       base::polymorphic_downcast<const system_window::InputEvent*>(event);
@@ -299,9 +325,14 @@
     case system_window::InputEvent::kTouchpadUp:
       HandlePointerEvent(base::Tokens::pointerup(), input_event);
       break;
-    case system_window::InputEvent::kWheel: {
+    case system_window::InputEvent::kWheel:
       HandleWheelEvent(input_event);
-    }
+      break;
+#if SB_HAS(ON_SCREEN_KEYBOARD)
+    case system_window::InputEvent::kInput:
+      HandleInputEvent(input_event);
+      break;
+#endif  // SB_HAS(ON_SCREEN_KEYBOARD)
     default:
       break;
   }
diff --git a/src/cobalt/input/input_device_manager_desktop.h b/src/cobalt/input/input_device_manager_desktop.h
index 13dfbf0..0183a43 100644
--- a/src/cobalt/input/input_device_manager_desktop.h
+++ b/src/cobalt/input/input_device_manager_desktop.h
@@ -28,6 +28,9 @@
       const KeyboardEventCallback& keyboard_event_callback,
       const PointerEventCallback& pointer_event_callback,
       const WheelEventCallback& wheel_event_callback,
+#if SB_HAS(ON_SCREEN_KEYBOARD)
+      const InputEventCallback& input_event_callback,
+#endif  // SB_HAS(ON_SCREEN_KEYBOARD)
       system_window::SystemWindow* system_window);
 
   ~InputDeviceManagerDesktop() OVERRIDE;
@@ -35,12 +38,16 @@
  protected:
   // Called to handle a input event generated by the referenced system
   // window.
-  void HandleInputEvent(const base::Event* event);
+  void HandleSystemWindowInputEvent(const base::Event* event);
 
  private:
   void HandleKeyboardEvent(bool is_key_down,
                            const system_window::InputEvent* input_event,
                            int key_code);
+#if SB_HAS(ON_SCREEN_KEYBOARD)
+  void HandleInputEvent(const system_window::InputEvent* event);
+#endif  // SB_HAS(ON_SCREEN_KEYBOARD)
+
   void HandlePointerEvent(base::Token type,
                           const system_window::InputEvent* input_event);
 
@@ -49,9 +56,15 @@
   // Reference to the system window that will provide keyboard events.
   system_window::SystemWindow* system_window_;
 
-  // Store a callback wrapping the object event handler, HandleInputEvent.
-  // This is so we can remove it again when this object is destroyed.
-  base::EventCallback input_event_callback_;
+  // Store a callback wrapping the object event handler,
+  // HandleSystemWindowInputEvent. This is so we can remove it again when this
+  // object is destroyed.
+  base::EventCallback system_window_input_event_callback_;
+
+#if SB_HAS(ON_SCREEN_KEYBOARD)
+  // Called to handle an input_event.
+  InputEventCallback input_event_callback_;
+#endif  // SB_HAS(ON_SCREEN_KEYBOARD)
 
   // Keyboard event filters to process the events generated.
   KeypressGeneratorFilter keypress_generator_filter_;
diff --git a/src/cobalt/input/input_device_manager_starboard.cc b/src/cobalt/input/input_device_manager_starboard.cc
index 9c21515..06951b7 100644
--- a/src/cobalt/input/input_device_manager_starboard.cc
+++ b/src/cobalt/input/input_device_manager_starboard.cc
@@ -22,9 +22,15 @@
     const KeyboardEventCallback& keyboard_event_callback,
     const PointerEventCallback& pointer_event_callback,
     const WheelEventCallback& wheel_event_callback,
+#if SB_HAS(ON_SCREEN_KEYBOARD)
+    const InputEventCallback& input_event_callback,
+#endif  // SB_HAS(ON_SCREEN_KEYBOARD)
     system_window::SystemWindow* system_window) {
   return scoped_ptr<InputDeviceManager>(new InputDeviceManagerDesktop(
       keyboard_event_callback, pointer_event_callback, wheel_event_callback,
+#if SB_HAS(ON_SCREEN_KEYBOARD)
+      input_event_callback,
+#endif  // SB_HAS(ON_SCREEN_KEYBOARD)
       system_window));
 }
 
diff --git a/src/cobalt/input/input_poller_impl.cc b/src/cobalt/input/input_poller_impl.cc
index f7aa0de..ea10e84 100644
--- a/src/cobalt/input/input_poller_impl.cc
+++ b/src/cobalt/input/input_poller_impl.cc
@@ -93,6 +93,11 @@
           NOTREACHED();
       }
     } break;
+#if SB_HAS(ON_SCREEN_KEYBOARD)
+    case system_window::InputEvent::kInput:
+      // Input events (dom::InputEvent) are ignored here.
+      break;
+#endif  // SB_HAS(ON_SCREEN_KEYBOARD)
     case system_window::InputEvent::kPointerDown:
     case system_window::InputEvent::kPointerUp:
     case system_window::InputEvent::kPointerMove:
diff --git a/src/cobalt/layout/block_level_replaced_box.cc b/src/cobalt/layout/block_level_replaced_box.cc
index dd5f374..71c75d7 100644
--- a/src/cobalt/layout/block_level_replaced_box.cc
+++ b/src/cobalt/layout/block_level_replaced_box.cc
@@ -15,6 +15,7 @@
 #include "cobalt/layout/block_level_replaced_box.h"
 
 #include "cobalt/layout/used_style.h"
+#include "cobalt/math/size_f.h"
 
 namespace cobalt {
 namespace layout {
@@ -28,13 +29,13 @@
     const base::optional<LayoutUnit>& maybe_intrinsic_height,
     const base::optional<float>& maybe_intrinsic_ratio,
     UsedStyleProvider* used_style_provider,
-    base::optional<bool> is_video_punched_out,
+    base::optional<bool> is_video_punched_out, const math::SizeF& content_size,
     LayoutStatTracker* layout_stat_tracker)
     : ReplacedBox(css_computed_style_declaration, replace_image_cb,
                   set_bounds_cb, paragraph, text_position,
                   maybe_intrinsic_width, maybe_intrinsic_height,
                   maybe_intrinsic_ratio, used_style_provider,
-                  is_video_punched_out, layout_stat_tracker) {}
+                  is_video_punched_out, content_size, layout_stat_tracker) {}
 
 Box::Level BlockLevelReplacedBox::GetLevel() const { return kBlockLevel; }
 
diff --git a/src/cobalt/layout/block_level_replaced_box.h b/src/cobalt/layout/block_level_replaced_box.h
index 6fdda9e..bcd59c5 100644
--- a/src/cobalt/layout/block_level_replaced_box.h
+++ b/src/cobalt/layout/block_level_replaced_box.h
@@ -23,6 +23,7 @@
 #include "cobalt/layout/box.h"
 #include "cobalt/layout/paragraph.h"
 #include "cobalt/layout/replaced_box.h"
+#include "cobalt/math/size_f.h"
 
 namespace cobalt {
 namespace layout {
@@ -39,7 +40,7 @@
       const base::optional<float>& maybe_intrinsic_ratio,
       UsedStyleProvider* used_style_provider,
       base::optional<bool> is_video_punched_out,
-      LayoutStatTracker* layout_stat_tracker);
+      const math::SizeF& content_size, LayoutStatTracker* layout_stat_tracker);
 
   // From |Box|.
   Level GetLevel() const OVERRIDE;
diff --git a/src/cobalt/layout/box.cc b/src/cobalt/layout/box.cc
index d1dd5a5..324e609 100644
--- a/src/cobalt/layout/box.cc
+++ b/src/cobalt/layout/box.cc
@@ -1712,16 +1712,22 @@
   // stop at the second transform and not the first (which is this box).
   Vector2dLayoutUnit containing_block_offset_from_root =
       GetContainingBlockOffsetFromRoot(true /*transform_forms_root*/);
-  Vector2dLayoutUnit border_box_offset_from_root =
-      (containing_block_offset_from_root +
-       margin_box_offset_from_containing_block() +
-       GetBorderBoxOffsetFromMarginBox());
+
+  // The transform rect always includes the offset from the containing block.
+  // However, in the case where the action is entering the transform, the full
+  // offset from the root needs to be included in the transform.
+  Vector2dLayoutUnit transform_rect_offset =
+      margin_box_offset_from_containing_block() +
+      GetBorderBoxOffsetFromMarginBox();
+  if (action == kEnterTransform) {
+    transform_rect_offset += containing_block_offset_from_root;
+  }
 
   // Transform the coordinates.
   math::Matrix3F matrix =
       GetCSSTransform(transform, computed_style()->transform_origin(),
-                      math::RectF(border_box_offset_from_root.x().toFloat(),
-                                  border_box_offset_from_root.y().toFloat(),
+                      math::RectF(transform_rect_offset.x().toFloat(),
+                                  transform_rect_offset.y().toFloat(),
                                   GetBorderBoxWidth().toFloat(),
                                   GetBorderBoxHeight().toFloat()));
   if (!matrix.IsIdentity()) {
diff --git a/src/cobalt/layout/box_generator.cc b/src/cobalt/layout/box_generator.cc
index 18bf26b..590e76b 100644
--- a/src/cobalt/layout/box_generator.cc
+++ b/src/cobalt/layout/box_generator.cc
@@ -185,7 +185,8 @@
                        const base::optional<LayoutUnit>& maybe_intrinsic_height,
                        const base::optional<float>& maybe_intrinsic_ratio,
                        const BoxGenerator::Context* context,
-                       base::optional<bool> is_video_punched_out)
+                       base::optional<bool> is_video_punched_out,
+                       math::SizeF content_size)
       : css_computed_style_declaration_(css_computed_style_declaration),
         replace_image_cb_(replace_image_cb),
         set_bounds_cb_(set_bounds_cb),
@@ -195,7 +196,8 @@
         maybe_intrinsic_height_(maybe_intrinsic_height),
         maybe_intrinsic_ratio_(maybe_intrinsic_ratio),
         context_(context),
-        is_video_punched_out_(is_video_punched_out) {}
+        is_video_punched_out_(is_video_punched_out),
+        content_size_(content_size) {}
 
   void VisitKeyword(cssom::KeywordValue* keyword) OVERRIDE;
 
@@ -213,6 +215,7 @@
   const base::optional<float> maybe_intrinsic_ratio_;
   const BoxGenerator::Context* context_;
   base::optional<bool> is_video_punched_out_;
+  math::SizeF content_size_;
 
   scoped_refptr<ReplacedBox> replaced_box_;
 };
@@ -226,7 +229,7 @@
           css_computed_style_declaration_, replace_image_cb_, set_bounds_cb_,
           paragraph_, text_position_, maybe_intrinsic_width_,
           maybe_intrinsic_height_, maybe_intrinsic_ratio_,
-          context_->used_style_provider, is_video_punched_out_,
+          context_->used_style_provider, is_video_punched_out_, content_size_,
           context_->layout_stat_tracker));
       break;
     // Generate an inline-level replaced box. There is no need to distinguish
@@ -239,7 +242,7 @@
           css_computed_style_declaration_, replace_image_cb_, set_bounds_cb_,
           paragraph_, text_position_, maybe_intrinsic_width_,
           maybe_intrinsic_height_, maybe_intrinsic_ratio_,
-          context_->used_style_provider, is_video_punched_out_,
+          context_->used_style_provider, is_video_punched_out_, content_size_,
           context_->layout_stat_tracker));
       break;
     // The element generates no boxes and has no effect on layout.
@@ -333,9 +336,6 @@
     }
   }
 
-  // Unlike in Chromium, we do not set the intrinsic width, height, or ratio
-  // based on the video frame. This allows to avoid relayout while playing
-  // adaptive videos.
   ReplacedBoxGenerator replaced_box_generator(
       video_element->css_computed_style_declaration(),
       video_element->GetVideoFrameProvider()
@@ -343,7 +343,8 @@
                        resource_provider)
           : ReplacedBox::ReplaceImageCB(),
       video_element->GetSetBoundsCB(), *paragraph_, text_position,
-      base::nullopt, base::nullopt, base::nullopt, context_, is_punch_out);
+      base::nullopt, base::nullopt, base::nullopt, context_, is_punch_out,
+      video_element->GetVideoSize());
   video_element->computed_style()->display()->Accept(&replaced_box_generator);
 
   scoped_refptr<ReplacedBox> replaced_box =
diff --git a/src/cobalt/layout/inline_container_box.cc b/src/cobalt/layout/inline_container_box.cc
index 9902ee9..65cf632 100644
--- a/src/cobalt/layout/inline_container_box.cc
+++ b/src/cobalt/layout/inline_container_box.cc
@@ -396,6 +396,10 @@
              child_boxes().rbegin();
          child_box_iterator != child_boxes().rend(); ++child_box_iterator) {
       Box* child_box = *child_box_iterator;
+      // Out-of-flow boxes are not impacted by ellipses.
+      if (child_box->IsAbsolutelyPositioned()) {
+        continue;
+      }
       child_box->TryPlaceEllipsisOrProcessPlacedEllipsis(
           base_direction, desired_offset, is_placement_requirement_met,
           is_placed, placed_offset);
@@ -404,6 +408,10 @@
     for (Boxes::const_iterator child_box_iterator = child_boxes().begin();
          child_box_iterator != child_boxes().end(); ++child_box_iterator) {
       Box* child_box = *child_box_iterator;
+      // Out-of-flow boxes are not impacted by ellipses.
+      if (child_box->IsAbsolutelyPositioned()) {
+        continue;
+      }
       child_box->TryPlaceEllipsisOrProcessPlacedEllipsis(
           base_direction, desired_offset, is_placement_requirement_met,
           is_placed, placed_offset);
diff --git a/src/cobalt/layout/inline_level_replaced_box.cc b/src/cobalt/layout/inline_level_replaced_box.cc
index 0f2bc17..0da6991 100644
--- a/src/cobalt/layout/inline_level_replaced_box.cc
+++ b/src/cobalt/layout/inline_level_replaced_box.cc
@@ -15,6 +15,7 @@
 #include "cobalt/layout/inline_level_replaced_box.h"
 
 #include "cobalt/layout/used_style.h"
+#include "cobalt/math/size_f.h"
 
 namespace cobalt {
 namespace layout {
@@ -28,13 +29,13 @@
     const base::optional<LayoutUnit>& maybe_intrinsic_height,
     const base::optional<float>& maybe_intrinsic_ratio,
     UsedStyleProvider* used_style_provider,
-    base::optional<bool> is_video_punched_out,
+    base::optional<bool> is_video_punched_out, const math::SizeF& content_size,
     LayoutStatTracker* layout_stat_tracker)
     : ReplacedBox(css_computed_style_declaration, replace_image_cb,
                   set_bounds_cb, paragraph, text_position,
                   maybe_intrinsic_width, maybe_intrinsic_height,
                   maybe_intrinsic_ratio, used_style_provider,
-                  is_video_punched_out, layout_stat_tracker),
+                  is_video_punched_out, content_size, layout_stat_tracker),
       is_hidden_by_ellipsis_(false),
       was_hidden_by_ellipsis_(false) {}
 
diff --git a/src/cobalt/layout/inline_level_replaced_box.h b/src/cobalt/layout/inline_level_replaced_box.h
index 14fd995..d280a25 100644
--- a/src/cobalt/layout/inline_level_replaced_box.h
+++ b/src/cobalt/layout/inline_level_replaced_box.h
@@ -23,6 +23,7 @@
 #include "cobalt/layout/box.h"
 #include "cobalt/layout/paragraph.h"
 #include "cobalt/layout/replaced_box.h"
+#include "cobalt/math/size_f.h"
 
 namespace cobalt {
 namespace layout {
@@ -41,7 +42,7 @@
       const base::optional<float>& maybe_intrinsic_ratio,
       UsedStyleProvider* used_style_provider,
       base::optional<bool> is_video_punched_out,
-      LayoutStatTracker* layout_stat_tracker);
+      const math::SizeF& content_size, LayoutStatTracker* layout_stat_tracker);
 
   // From |Box|.
   Level GetLevel() const OVERRIDE;
diff --git a/src/cobalt/layout/line_box.cc b/src/cobalt/layout/line_box.cc
index 452f2b0..fc12a78 100644
--- a/src/cobalt/layout/line_box.cc
+++ b/src/cobalt/layout/line_box.cc
@@ -257,7 +257,6 @@
   last_non_collapsed_child_box->UpdateSize(layout_params_);
   LayoutUnit collapsed_white_space_width =
       child_box_pre_collapse_width - last_non_collapsed_child_box->width();
-  DCHECK(collapsed_white_space_width.GreaterThanOrNaN(LayoutUnit()));
 
   shrink_to_fit_width_ -= collapsed_white_space_width;
 }
@@ -271,7 +270,6 @@
   last_non_collapsed_child_box->UpdateSize(layout_params_);
   LayoutUnit restored_white_space_width =
       last_non_collapsed_child_box->width() - child_box_pre_restore_width;
-  DCHECK(restored_white_space_width.GreaterThanOrNaN(LayoutUnit()));
 
   shrink_to_fit_width_ += restored_white_space_width;
 }
diff --git a/src/cobalt/layout/replaced_box.cc b/src/cobalt/layout/replaced_box.cc
index 6c3e322..0af0b8e 100644
--- a/src/cobalt/layout/replaced_box.cc
+++ b/src/cobalt/layout/replaced_box.cc
@@ -42,7 +42,6 @@
 namespace cobalt {
 namespace layout {
 
-using render_tree::animations::AnimateNode;
 using render_tree::CompositionNode;
 using render_tree::FilterNode;
 using render_tree::ImageNode;
@@ -51,6 +50,7 @@
 using render_tree::PunchThroughVideoNode;
 using render_tree::RectNode;
 using render_tree::SolidColorBrush;
+using render_tree::animations::AnimateNode;
 
 namespace {
 
@@ -102,7 +102,7 @@
     const base::optional<LayoutUnit>& maybe_intrinsic_height,
     const base::optional<float>& maybe_intrinsic_ratio,
     UsedStyleProvider* used_style_provider,
-    base::optional<bool> is_video_punched_out,
+    base::optional<bool> is_video_punched_out, const math::SizeF& content_size,
     LayoutStatTracker* layout_stat_tracker)
     : Box(css_computed_style_declaration, used_style_provider,
           layout_stat_tracker),
@@ -116,7 +116,8 @@
       set_bounds_cb_(set_bounds_cb),
       paragraph_(paragraph),
       text_position_(text_position),
-      is_video_punched_out_(is_video_punched_out) {}
+      is_video_punched_out_(is_video_punched_out),
+      content_size_(content_size) {}
 
 WrapResult ReplacedBox::TryWrapAt(
     WrapAtPolicy /*wrap_at_policy*/,
@@ -230,6 +231,18 @@
   AddLetterboxFillRects(dimensions, composition_node_builder);
 }
 
+void AddLetterboxedPunchThroughVideoNodeToRenderTree(
+    const LetterboxDimensions& dimensions,
+    const ReplacedBox::SetBoundsCB& set_bounds_cb,
+    CompositionNode::Builder* border_node_builder) {
+  if (dimensions.image_rect) {
+    PunchThroughVideoNode::Builder builder(*(dimensions.image_rect),
+                                           set_bounds_cb);
+    border_node_builder->AddChild(new PunchThroughVideoNode(builder));
+  }
+  AddLetterboxFillRects(dimensions, border_node_builder);
+}
+
 void AnimateVideoImage(const ReplacedBox::ReplaceImageCB& replace_image_cb,
                        ImageNode::Builder* image_node_builder) {
   DCHECK(!replace_image_cb.is_null());
@@ -310,33 +323,30 @@
   const cssom::MapToMeshFunction* mtm_filter_function =
       cssom::MapToMeshFunction::ExtractFromFilterList(
           computed_style()->filter());
-  if (*is_video_punched_out_) {
-    DCHECK(!mtm_filter_function)
+
+  if (mtm_filter_function) {
+    DCHECK(!*is_video_punched_out_)
         << "We currently do not support punched out video with map-to-mesh "
            "filters.";
-    // For systems that have their own path to blitting video to the display, we
-    // simply punch a hole through our scene so that the video can appear there.
-    PunchThroughVideoNode::Builder builder(math::RectF(content_box_size()),
-                                           set_bounds_cb_);
-    border_node_builder->AddChild(new PunchThroughVideoNode(builder));
-  } else if (mtm_filter_function) {
     RenderAndAnimateContentWithMapToMesh(border_node_builder,
                                          mtm_filter_function);
   } else {
 #if defined(FORCE_VIDEO_EXTERNAL_MESH)
-    AnimateNode::Builder animate_node_builder;
-    scoped_refptr<ImageNode> image_node = new ImageNode(NULL);
-    animate_node_builder.Add(image_node,
-                             base::Bind(&AnimateVideoImage, replace_image_cb_));
+    if (!*is_video_punched_out_) {
+      AnimateNode::Builder animate_node_builder;
+      scoped_refptr<ImageNode> image_node = new ImageNode(NULL);
+      animate_node_builder.Add(
+          image_node, base::Bind(&AnimateVideoImage, replace_image_cb_));
 
-    // Attach an empty map to mesh filter node to signal the need for an
-    // external mesh.
-    border_node_builder->AddChild(
-        new FilterNode(MapToMeshFilter(render_tree::kMono),
-                       new AnimateNode(animate_node_builder, image_node)));
-#else
-    RenderAndAnimateContentWithLetterboxing(border_node_builder);
+      // Attach an empty map to mesh filter node to signal the need for an
+      // external mesh.
+      border_node_builder->AddChild(
+          new FilterNode(MapToMeshFilter(render_tree::kMono),
+                         new AnimateNode(animate_node_builder, image_node)));
+      return;
+    }
 #endif
+    RenderAndAnimateContentWithLetterboxing(border_node_builder);
   }
 }
 
@@ -702,18 +712,23 @@
   CompositionNode::Builder composition_node_builder(
       math::Vector2dF((border_left_width() + padding_left()).toFloat(),
                       (border_top_width() + padding_top()).toFloat()));
-
   scoped_refptr<CompositionNode> composition_node =
       new CompositionNode(composition_node_builder);
 
-  AnimateNode::Builder animate_node_builder;
+  if (*is_video_punched_out_) {
+    LetterboxDimensions letterbox_dims =
+        GetLetterboxDimensions(content_size_, content_box_size());
+    AddLetterboxedPunchThroughVideoNodeToRenderTree(
+        letterbox_dims, set_bounds_cb_, border_node_builder);
 
-  animate_node_builder.Add(composition_node,
-                           base::Bind(&AnimateVideoWithLetterboxing,
-                                      replace_image_cb_, content_box_size()));
-
-  border_node_builder->AddChild(
-      new AnimateNode(animate_node_builder, composition_node));
+  } else {
+    AnimateNode::Builder animate_node_builder;
+    animate_node_builder.Add(composition_node,
+                             base::Bind(&AnimateVideoWithLetterboxing,
+                                        replace_image_cb_, content_box_size()));
+    border_node_builder->AddChild(
+        new AnimateNode(animate_node_builder, composition_node));
+  }
 }
 
 }  // namespace layout
diff --git a/src/cobalt/layout/replaced_box.h b/src/cobalt/layout/replaced_box.h
index 81a9b16..52e139a 100644
--- a/src/cobalt/layout/replaced_box.h
+++ b/src/cobalt/layout/replaced_box.h
@@ -24,6 +24,7 @@
 #include "cobalt/layout/box.h"
 #include "cobalt/layout/paragraph.h"
 #include "cobalt/math/rect.h"
+#include "cobalt/math/size_f.h"
 #include "cobalt/render_tree/image.h"
 #include "cobalt/render_tree/punch_through_video_node.h"
 
@@ -51,6 +52,7 @@
               const base::optional<float>& maybe_intrinsic_ratio,
               UsedStyleProvider* used_style_provider,
               base::optional<bool> is_video_punched_out,
+              const math::SizeF& content_size,
               LayoutStatTracker* layout_stat_tracker);
 
   // From |Box|.
@@ -118,6 +120,7 @@
   const scoped_refptr<Paragraph> paragraph_;
   int32 text_position_;
   base::optional<bool> is_video_punched_out_;
+  math::SizeF content_size_;
 };
 
 }  // namespace layout
diff --git a/src/cobalt/layout_tests/layout_snapshot.cc b/src/cobalt/layout_tests/layout_snapshot.cc
index 49c1a6f..366c893 100644
--- a/src/cobalt/layout_tests/layout_snapshot.cc
+++ b/src/cobalt/layout_tests/layout_snapshot.cc
@@ -20,8 +20,10 @@
 #include "base/run_loop.h"
 #include "base/synchronization/waitable_event.h"
 #include "cobalt/browser/web_module.h"
+#include "cobalt/dom/window.h"
 #include "cobalt/network/network_module.h"
 #include "cobalt/render_tree/resource_provider.h"
+#include "starboard/window.h"
 
 namespace cobalt {
 namespace layout_tests {
@@ -49,6 +51,10 @@
   LOG(FATAL) << "Error loading document: " << error << ". URL: " << url;
   message_loop->PostTask(FROM_HERE, base::Bind(Quit, run_loop));
 }
+
+// Return a NULL SbWindow, since we do not need to pass a valid SbWindow to an
+// on screen keyboard.
+SbWindow GetNullSbWindow() { return NULL; }
 }  // namespace
 
 browser::WebModule::LayoutResults SnapshotURL(
@@ -83,9 +89,9 @@
       base::Bind(&WebModuleErrorCallback, &run_loop, MessageLoop::current()),
       browser::WebModule::CloseCallback() /* window_close_callback */,
       base::Closure() /* window_minimize_callback */,
-      NULL /* can_play_type_handler */, NULL /* web_media_player_factory */,
-      &network_module, viewport_size, 1.f, resource_provider, 60.0f,
-      web_module_options);
+      base::Bind(&GetNullSbWindow), NULL /* can_play_type_handler */,
+      NULL /* web_media_player_factory */, &network_module, viewport_size, 1.f,
+      resource_provider, 60.0f, web_module_options);
 
   run_loop.Run();
 
diff --git a/src/cobalt/layout_tests/testdata/css3-background/5-0-border-radius-circle-with-irrational-out-of-bounds-radius-expected.png b/src/cobalt/layout_tests/testdata/css3-background/5-0-border-radius-circle-with-irrational-out-of-bounds-radius-expected.png
new file mode 100644
index 0000000..d6b634c
--- /dev/null
+++ b/src/cobalt/layout_tests/testdata/css3-background/5-0-border-radius-circle-with-irrational-out-of-bounds-radius-expected.png
Binary files differ
diff --git a/src/cobalt/layout_tests/testdata/css3-background/5-0-border-radius-circle-with-irrational-out-of-bounds-radius.html b/src/cobalt/layout_tests/testdata/css3-background/5-0-border-radius-circle-with-irrational-out-of-bounds-radius.html
new file mode 100644
index 0000000..464c147
--- /dev/null
+++ b/src/cobalt/layout_tests/testdata/css3-background/5-0-border-radius-circle-with-irrational-out-of-bounds-radius.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<!--
+ | Setting the border radius in a funny way to catch a regression where our
+ | rounded corner normalization logic was returning false on
+ | IsNormalized(my_rounded_rect.Normalize()), because of floating point error.
+ -->
+<html>
+<head>
+  <style>
+    div {
+      border-radius: 66.666666px;
+      background-color: rgb(1, 1, 0);
+      height: 6.141px;
+      width: 6.141px;
+    }
+  </style>
+</head>
+<body>
+  <div></div>
+</body>
+</html>
diff --git a/src/cobalt/layout_tests/testdata/css3-background/5-0-border-radius-circle-with-out-of-bounds-radius-expected.png b/src/cobalt/layout_tests/testdata/css3-background/5-0-border-radius-circle-with-out-of-bounds-radius-expected.png
new file mode 100644
index 0000000..6047df8
--- /dev/null
+++ b/src/cobalt/layout_tests/testdata/css3-background/5-0-border-radius-circle-with-out-of-bounds-radius-expected.png
Binary files differ
diff --git a/src/cobalt/layout_tests/testdata/css3-background/5-0-border-radius-circle-with-out-of-bounds-radius.html b/src/cobalt/layout_tests/testdata/css3-background/5-0-border-radius-circle-with-out-of-bounds-radius.html
new file mode 100644
index 0000000..5c9cd99
--- /dev/null
+++ b/src/cobalt/layout_tests/testdata/css3-background/5-0-border-radius-circle-with-out-of-bounds-radius.html
@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<!--
+ | Setting the border radius that is larger than the maximum
+ | allowed (of 50%).  Makes sure that this is handled correctly.
+ -->
+<html>
+<head>
+  <style>
+    div {
+      border-radius: 100%;
+      background-color: rgb(1, 1, 0);
+      height: 24px;
+      width: 24px;
+    }
+  </style>
+</head>
+<body>
+  <div></div>
+</body>
+</html>
diff --git a/src/cobalt/layout_tests/testdata/css3-background/layout_tests.txt b/src/cobalt/layout_tests/testdata/css3-background/layout_tests.txt
index 9b39a9e..aa70fd5 100644
--- a/src/cobalt/layout_tests/testdata/css3-background/layout_tests.txt
+++ b/src/cobalt/layout_tests/testdata/css3-background/layout_tests.txt
@@ -91,6 +91,8 @@
 5-0-border-radius-4-values-with-border-only
 5-0-border-radius-circle-with-background-color-and-border
 5-0-border-radius-circle-with-background-image-and-border
+5-0-border-radius-circle-with-irrational-out-of-bounds-radius
+5-0-border-radius-circle-with-out-of-bounds-radius
 5-0-border-radius-with-background-color
 5-0-border-radius-with-background-color-and-border
 5-0-border-radius-with-background-image
diff --git a/src/cobalt/layout_tests/testdata/css3-fonts/5-2-use-first-available-listed-font-family-expected.png b/src/cobalt/layout_tests/testdata/css3-fonts/5-2-use-first-available-listed-font-family-expected.png
index 75a84b8..0d6e5bb 100644
--- a/src/cobalt/layout_tests/testdata/css3-fonts/5-2-use-first-available-listed-font-family-expected.png
+++ b/src/cobalt/layout_tests/testdata/css3-fonts/5-2-use-first-available-listed-font-family-expected.png
Binary files differ
diff --git a/src/cobalt/layout_tests/testdata/css3-fonts/5-2-use-specified-font-family-if-available-expected.png b/src/cobalt/layout_tests/testdata/css3-fonts/5-2-use-specified-font-family-if-available-expected.png
index 91b7a87..b603732 100644
--- a/src/cobalt/layout_tests/testdata/css3-fonts/5-2-use-specified-font-family-if-available-expected.png
+++ b/src/cobalt/layout_tests/testdata/css3-fonts/5-2-use-specified-font-family-if-available-expected.png
Binary files differ
diff --git a/src/cobalt/layout_tests/testdata/css3-fonts/synthetic-bolding-should-not-occur-on-bold-font-expected.png b/src/cobalt/layout_tests/testdata/css3-fonts/synthetic-bolding-should-not-occur-on-bold-font-expected.png
index 5c923af..08de62c 100644
--- a/src/cobalt/layout_tests/testdata/css3-fonts/synthetic-bolding-should-not-occur-on-bold-font-expected.png
+++ b/src/cobalt/layout_tests/testdata/css3-fonts/synthetic-bolding-should-not-occur-on-bold-font-expected.png
Binary files differ
diff --git a/src/cobalt/layout_tests/testdata/css3-fonts/synthetic-bolding-should-occur-on-non-bold-font-expected.png b/src/cobalt/layout_tests/testdata/css3-fonts/synthetic-bolding-should-occur-on-non-bold-font-expected.png
index 324f60e..d16282c 100644
--- a/src/cobalt/layout_tests/testdata/css3-fonts/synthetic-bolding-should-occur-on-non-bold-font-expected.png
+++ b/src/cobalt/layout_tests/testdata/css3-fonts/synthetic-bolding-should-occur-on-non-bold-font-expected.png
Binary files differ
diff --git a/src/cobalt/layout_tests/testdata/cssom-view/extensions_to_the_element_interface_get_bounding_client_rect_with_scale_transform-expected.png b/src/cobalt/layout_tests/testdata/cssom-view/extensions_to_the_element_interface_get_bounding_client_rect_with_scale_transform-expected.png
new file mode 100644
index 0000000..9b628dd
--- /dev/null
+++ b/src/cobalt/layout_tests/testdata/cssom-view/extensions_to_the_element_interface_get_bounding_client_rect_with_scale_transform-expected.png
Binary files differ
diff --git a/src/cobalt/layout_tests/testdata/cssom-view/extensions_to_the_element_interface_get_bounding_client_rect_with_scale_transform.html b/src/cobalt/layout_tests/testdata/cssom-view/extensions_to_the_element_interface_get_bounding_client_rect_with_scale_transform.html
new file mode 100644
index 0000000..5adb907
--- /dev/null
+++ b/src/cobalt/layout_tests/testdata/cssom-view/extensions_to_the_element_interface_get_bounding_client_rect_with_scale_transform.html
@@ -0,0 +1,91 @@
+<!DOCTYPE html>
+<!--
+ | Test CSSOM View extensions to the Element Interface, verifying that
+ | getBoundingClientRect() works properly with transforms.
+ -->
+<html>
+<head>
+  <style>
+    body {
+      background-color: #FFFFFF;
+      margin: 0px;
+      font-family: Roboto;
+      font-size: 40px;
+    }
+    .absolute_container {
+      position: absolute;
+      top: 50px;
+      left: 50px;
+    }
+    .absolutely-positioned-1 {
+      position: absolute;
+      transform: scaleX(2.0) scaleY(2.0);
+      top: 120px;
+      left: 120px;
+      width: 100px;
+      height: 100px;
+    }
+    .absolutely-positioned-2 {
+      position: absolute;
+      transform: scaleX(.5) scaleY(.5);
+      top: 45px;
+      left: 45px;
+      width: 100px;
+      height: 100px;
+    }
+  </style>
+  <script>
+    if (window.testRunner) {
+      window.testRunner.waitUntilDone();
+    }
+
+    function verifyGetBoundingClientRectAttributesAreCorrect(id) {
+      var element = document.getElementById(id);
+      if (!element) {
+        document.body.style.backgroundColor = "#F44336";
+      } else {
+        var expected_left = 120;
+        var expected_top = 120;
+
+        bounding_rect = element.getBoundingClientRect();
+        if (bounding_rect["left"] != expected_left) {
+          console.log("getElementById(\'" + id +
+                      "\').getBoundingClientRect()." + "left" + " == " +
+                      bounding_rect["left"] + " != " + expected_left);
+          element.style.backgroundColor = "#F44336";
+        }
+
+        if (bounding_rect["top"] != expected_top) {
+          console.log("getElementById(\'" + id +
+                      "\').getBoundingClientRect()." + "top" + " == " +
+                      bounding_rect["top"] + " != " + expected_top);
+          element.style.backgroundColor = "#F44336";
+        }
+      }
+    }
+
+    function runTest() {
+      verifyGetBoundingClientRectAttributesAreCorrect("div-1");
+      verifyGetBoundingClientRectAttributesAreCorrect("div-2");
+    }
+
+    window.onload = function() {
+      runTest();
+
+      if (window.testRunner) {
+        window.testRunner.notifyDone();
+      }
+    }
+  </script>
+</head>
+<body>
+  <div class="absolute_container">
+    <div id="div-1" class="absolutely-positioned-1">
+      <span>Yes</span>
+    </div>
+    <div id="div-2" class="absolutely-positioned-2">
+      <span>Yes</span>
+    </div>
+  </div>
+</body>
+</html>
diff --git a/src/cobalt/layout_tests/testdata/cssom-view/extensions_to_the_element_interface_get_bounding_client_rect_with_transform-expected.png b/src/cobalt/layout_tests/testdata/cssom-view/extensions_to_the_element_interface_get_bounding_client_rect_with_translate_transform-expected.png
similarity index 100%
rename from src/cobalt/layout_tests/testdata/cssom-view/extensions_to_the_element_interface_get_bounding_client_rect_with_transform-expected.png
rename to src/cobalt/layout_tests/testdata/cssom-view/extensions_to_the_element_interface_get_bounding_client_rect_with_translate_transform-expected.png
Binary files differ
diff --git a/src/cobalt/layout_tests/testdata/cssom-view/extensions_to_the_element_interface_get_bounding_client_rect_with_transform.html b/src/cobalt/layout_tests/testdata/cssom-view/extensions_to_the_element_interface_get_bounding_client_rect_with_translate_transform.html
similarity index 100%
rename from src/cobalt/layout_tests/testdata/cssom-view/extensions_to_the_element_interface_get_bounding_client_rect_with_transform.html
rename to src/cobalt/layout_tests/testdata/cssom-view/extensions_to_the_element_interface_get_bounding_client_rect_with_translate_transform.html
diff --git a/src/cobalt/layout_tests/testdata/cssom-view/layout_tests.txt b/src/cobalt/layout_tests/testdata/cssom-view/layout_tests.txt
index 88679e8..fe73663 100644
--- a/src/cobalt/layout_tests/testdata/cssom-view/layout_tests.txt
+++ b/src/cobalt/layout_tests/testdata/cssom-view/layout_tests.txt
@@ -1,5 +1,6 @@
 extensions_to_the_element_interface_client_top_left_width_height
 extensions_to_the_element_interface_get_bounding_client_rect_with_box_splitting
-extensions_to_the_element_interface_get_bounding_client_rect_with_transform
+extensions_to_the_element_interface_get_bounding_client_rect_with_scale_transform
+extensions_to_the_element_interface_get_bounding_client_rect_with_translate_transform
 extensions_to_the_html_element_interface_offset_top_left_width_height
 extensions_to_the_html_element_interface_offset_width_height_with_box_splitting
diff --git a/src/cobalt/layout_tests/testdata/web-platform-tests/XMLHttpRequest/web_platform_tests.txt b/src/cobalt/layout_tests/testdata/web-platform-tests/XMLHttpRequest/web_platform_tests.txt
index ad81d43..f987b67 100644
--- a/src/cobalt/layout_tests/testdata/web-platform-tests/XMLHttpRequest/web_platform_tests.txt
+++ b/src/cobalt/layout_tests/testdata/web-platform-tests/XMLHttpRequest/web_platform_tests.txt
@@ -128,13 +128,13 @@
 send-after-setting-document-domain.htm,FAIL
 send-authentication-basic-cors.htm,PASS
 # Synchronous
-send-authentication-basic-cors-not-enabled.htm,DISABLE
+send-authentication-basic-cors-not-enabled.htm,FAIL
 send-authentication-basic.htm,FAIL
 send-authentication-basic-repeat-no-args.htm,FAIL
 send-authentication-basic-setrequestheader-existing-session.htm,FAIL
 send-authentication-basic-setrequestheader.htm,FAIL
 send-authentication-competing-names-passwords.htm,FAIL
-send-authentication-cors-basic-setrequestheader.htm,DISABLE
+send-authentication-cors-basic-setrequestheader.htm,FAIL
 # js_error: send-authentication-existing-session-manual.htm,FAIL
 # Synchronous
 send-authentication-prompt-2-manual.htm,FAIL
@@ -170,7 +170,7 @@
 send-redirect-infinite.htm,PASS
 send-redirect-infinite-sync.htm,FAIL
 send-redirect-no-location.htm,PASS
-send-redirect-to-cors.htm,DISABLE
+send-redirect-to-cors.htm,FAIL
 send-redirect-to-non-cors.htm,PASS
 send-response-event-order.htm,FAIL
 send-response-upload-event-loadend.htm,PASS
@@ -183,7 +183,7 @@
 send-sync-no-response-event-order.htm,FAIL
 send-sync-response-event-order.htm,FAIL
 send-sync-timeout.htm,FAIL
-send-timeout-events.htm,DISABLE
+send-timeout-events.htm,PASS
 # Infinite loop?
 send-usp.html,DISABLE
 setrequestheader-after-send.htm,PASS
@@ -231,3 +231,10 @@
 # Synchronous
 XMLHttpRequest-withCredentials.html,FAIL,setting on synchronous XHR
 XMLHttpRequest-withCredentials.html,FAIL,setting withCredentials when in DONE state (synchronous)
+# Updated XMLHttpRequest WPT tests. Directly updating them requires changes in
+# every Cobalt branch. So we are listing them as extra tests.
+cobalt_trunk_send-authentication-basic-cors-not-enabled.htm,PASS
+cobalt_trunk_send-authentication-cors-basic-setrequestheader.htm,PASS
+cobalt_trunk_send-authentication-cors-setrequestheader-no-cred.htm,PASS
+cobalt_trunk_send-redirect-no-location.htm,PASS
+cobalt_trunk_send-redirect-to-cors.htm,PASS
diff --git a/src/cobalt/layout_tests/testdata/web-platform-tests/cobalt_special/web_platform_tests.txt b/src/cobalt/layout_tests/testdata/web-platform-tests/cobalt_special/web_platform_tests.txt
new file mode 100644
index 0000000..e16a414
--- /dev/null
+++ b/src/cobalt/layout_tests/testdata/web-platform-tests/cobalt_special/web_platform_tests.txt
@@ -0,0 +1,3 @@
+# Cobalt's special tests that borrows WPT infrastructures.
+
+origin-clean.htm,PASS
diff --git a/src/cobalt/layout_tests/testdata/web-platform-tests/cors/web_platform_tests.txt b/src/cobalt/layout_tests/testdata/web-platform-tests/cors/web_platform_tests.txt
new file mode 100644
index 0000000..b09222b
--- /dev/null
+++ b/src/cobalt/layout_tests/testdata/web-platform-tests/cors/web_platform_tests.txt
@@ -0,0 +1,26 @@
+# SOP/CORS tests.
+# Anything with multiple windows or workers is disabled.
+#
+
+# Cobalt does not support HTTP cache.
+304.htm,FAIL
+allow-headers.htm,PASS
+basic.htm,PASS
+credentials-flag.htm,PASS
+late-upload-events.htm,PASS
+origin.htm,PASS
+preflight-cache.htm,PASS
+preflight-failure.htm,PASS
+redirect-origin.htm,PASS
+redirect-preflight-2.htm,PASS
+redirect-preflight.htm,PASS
+redirect-userinfo.htm,PASS
+# remote-origin.htm requires iframe support.
+remote-origin.htm,DISABLE
+request-headers.htm,PASS
+response-headers.htm,PASS
+simple-requests.htm,PASS
+status-async.htm,PASS
+status-preflight.htm,PASS
+status.htm,PASS
+
diff --git a/src/cobalt/layout_tests/web_platform_tests.cc b/src/cobalt/layout_tests/web_platform_tests.cc
index 2199ea1..81a0060 100644
--- a/src/cobalt/layout_tests/web_platform_tests.cc
+++ b/src/cobalt/layout_tests/web_platform_tests.cc
@@ -32,6 +32,7 @@
 #include "cobalt/network/network_module.h"
 #include "cobalt/render_tree/resource_provider_stub.h"
 #include "googleurl/src/gurl.h"
+#include "starboard/window.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace cobalt {
@@ -181,6 +182,7 @@
       base::Bind(&WebModuleErrorCallback, &run_loop, MessageLoop::current()),
       browser::WebModule::CloseCallback() /* window_close_callback */,
       base::Closure() /* window_minimize_callback */,
+      base::Callback<SbWindow()>() /* get_sb_window */,
       can_play_type_handler.get(), media_module.get(), &network_module,
       kDefaultViewportSize, 1.f, &resource_provider, 60.0f, web_module_options);
   run_loop.Run();
diff --git a/src/cobalt/loader/fetcher.h b/src/cobalt/loader/fetcher.h
index 9288081..940df3a 100644
--- a/src/cobalt/loader/fetcher.h
+++ b/src/cobalt/loader/fetcher.h
@@ -28,9 +28,13 @@
 
 // https://fetch.spec.whatwg.org/#concept-request-mode
 // Right now Cobalt only needs two modes.
+// We mix credentials mode with request mode for simplicity.
+// https://fetch.spec.whatwg.org/#concept-request-credentials-mode
 enum RequestMode {
   kNoCORSMode,
-  kCORSMode,
+  kCORSModeOmitCredentials,
+  kCORSModeSameOriginCredentials,
+  kCORSModeIncludeCredentials,
 };
 
 class Fetcher {
diff --git a/src/cobalt/loader/image/animated_webp_image.cc b/src/cobalt/loader/image/animated_webp_image.cc
index 0fd10bb..79e1e64 100644
--- a/src/cobalt/loader/image/animated_webp_image.cc
+++ b/src/cobalt/loader/image/animated_webp_image.cc
@@ -16,6 +16,8 @@
 
 #include "cobalt/loader/image/animated_webp_image.h"
 
+#include <string>
+
 #include "cobalt/base/polymorphic_downcast.h"
 #include "cobalt/loader/image/image_decoder.h"
 #include "cobalt/render_tree/brush.h"
@@ -38,11 +40,9 @@
 
 AnimatedWebPImage::AnimatedWebPImage(
     const math::Size& size, bool is_opaque,
-    render_tree::PixelFormat pixel_format,
     render_tree::ResourceProvider* resource_provider)
     : size_(size),
       is_opaque_(is_opaque),
-      pixel_format_(pixel_format),
       demux_(NULL),
       demux_state_(WEBP_DEMUX_PARSING_HEADER),
       received_first_frame_(false),
@@ -365,18 +365,6 @@
   return frame_duration;
 }
 
-scoped_ptr<render_tree::ImageData> AnimatedWebPImage::AllocateImageData(
-    const math::Size& size) {
-  TRACE_EVENT0("cobalt::loader::image",
-               "AnimatedWebPImage::AllocateImageData()");
-  TRACK_MEMORY_SCOPE("Rendering");
-  scoped_ptr<render_tree::ImageData> image_data =
-      resource_provider_->AllocateImageData(
-          size, pixel_format_, render_tree::kAlphaFormatPremultiplied);
-  DCHECK(image_data) << "Failed to allocate image.";
-  return image_data.Pass();
-}
-
 bool AnimatedWebPImage::LoopingFinished() const {
   return loop_count_ == 1 && current_frame_index_ == frame_count_;
 }
diff --git a/src/cobalt/loader/image/animated_webp_image.h b/src/cobalt/loader/image/animated_webp_image.h
index 8714c46..971e92f 100644
--- a/src/cobalt/loader/image/animated_webp_image.h
+++ b/src/cobalt/loader/image/animated_webp_image.h
@@ -39,7 +39,6 @@
 class AnimatedWebPImage : public AnimatedImage {
  public:
   AnimatedWebPImage(const math::Size& size, bool is_opaque,
-                    render_tree::PixelFormat pixel_format,
                     render_tree::ResourceProvider* resource_provider);
 
   const math::Size& GetSize() const OVERRIDE { return size_; }
@@ -75,8 +74,6 @@
   // Decodes the frame with the given index, returns if it succeeded.
   bool DecodeOneFrame(int frame_index);
 
-  scoped_ptr<render_tree::ImageData> AllocateImageData(const math::Size& size);
-
   // If the time is right, updates the index and time info of the current frame.
   bool AdvanceFrame();
 
@@ -88,7 +85,6 @@
 
   const math::Size size_;
   const bool is_opaque_;
-  const render_tree::PixelFormat pixel_format_;
   WebPDemuxer* demux_;
   WebPDemuxState demux_state_;
   bool received_first_frame_;
diff --git a/src/cobalt/loader/image/image_data_decoder.cc b/src/cobalt/loader/image/image_data_decoder.cc
index 0e20ce7..ff5e229 100644
--- a/src/cobalt/loader/image/image_data_decoder.cc
+++ b/src/cobalt/loader/image/image_data_decoder.cc
@@ -122,8 +122,8 @@
       size, pixel_format(), has_alpha ? render_tree::kAlphaFormatPremultiplied
                                       : render_tree::kAlphaFormatOpaque);
   if (!image_data_) {
-    DLOG(WARNING) << "Failed to allocate image data (" << size.width() << "x"
-                  << size.height() << ").";
+    DLOG(ERROR) << "Failed to allocate image data (" << size.width() << "x"
+                << size.height() << ").";
   }
   return image_data_;
 }
diff --git a/src/cobalt/loader/image/webp_image_decoder.cc b/src/cobalt/loader/image/webp_image_decoder.cc
index 09f1bc3..5602ef6 100644
--- a/src/cobalt/loader/image/webp_image_decoder.cc
+++ b/src/cobalt/loader/image/webp_image_decoder.cc
@@ -76,7 +76,7 @@
       has_animation_ = true;
       animated_webp_image_ = new AnimatedWebPImage(
           math::Size(config_.input.width, config_.input.height),
-          !!config_.input.has_alpha, pixel_format(), resource_provider());
+          !!config_.input.has_alpha, resource_provider());
     }
     set_state(kReadLines);
   }
diff --git a/src/cobalt/loader/loader_factory.cc b/src/cobalt/loader/loader_factory.cc
index c5c9890..10c7c2a 100644
--- a/src/cobalt/loader/loader_factory.cc
+++ b/src/cobalt/loader/loader_factory.cc
@@ -67,7 +67,8 @@
   DCHECK(thread_checker_.CalledOnValidThread());
 
   scoped_ptr<Loader> loader(new Loader(
-      MakeFetcherCreator(url, url_security_callback, kCORSMode, origin),
+      MakeFetcherCreator(url, url_security_callback,
+                         kCORSModeSameOriginCredentials, origin),
       scoped_ptr<Decoder>(new font::TypefaceDecoder(
           resource_provider_, success_callback, error_callback)),
       error_callback,
diff --git a/src/cobalt/loader/net_fetcher.cc b/src/cobalt/loader/net_fetcher.cc
index 29a21c5..2fc3295 100644
--- a/src/cobalt/loader/net_fetcher.cc
+++ b/src/cobalt/loader/net_fetcher.cc
@@ -85,11 +85,19 @@
       net::URLFetcher::Create(url, options.request_method, this));
   url_fetcher_->SetRequestContext(network_module->url_request_context_getter());
   url_fetcher_->DiscardResponse();
-  if (request_mode == kCORSMode && !url.SchemeIs("data") &&
+  if (request_mode != kNoCORSMode && !url.SchemeIs("data") &&
       origin != Origin(url)) {
     request_cross_origin_ = true;
     url_fetcher_->AddExtraRequestHeader("Origin:" + origin.SerializedOrigin());
   }
+  if ((request_cross_origin_ &&
+       (request_mode == kCORSModeSameOriginCredentials)) ||
+      request_mode == kCORSModeOmitCredentials) {
+    const uint32 kDisableCookiesLoadFlags =
+        net::LOAD_NORMAL | net::LOAD_DO_NOT_SAVE_COOKIES |
+        net::LOAD_DO_NOT_SEND_COOKIES | net::LOAD_DO_NOT_SEND_AUTH_DATA;
+    url_fetcher_->SetLoadFlags(kDisableCookiesLoadFlags);
+  }
 
   // Delay the actual start until this function is complete. Otherwise we might
   // call handler's callbacks at an unexpected time- e.g. receiving OnError()
diff --git a/src/cobalt/loader/resource_cache.h b/src/cobalt/loader/resource_cache.h
index 805a0c5..fbf958a 100644
--- a/src/cobalt/loader/resource_cache.h
+++ b/src/cobalt/loader/resource_cache.h
@@ -424,6 +424,10 @@
 
   void Purge();
 
+  // Processes all pending callbacks regardless of the state of
+  // |callback_blocking_loading_resource_set_|.
+  void ProcessPendingCallbacks();
+
   void DisableCallbacks();
 
  private:
@@ -465,9 +469,6 @@
   // Calls ProcessPendingCallbacks() if
   // |callback_blocking_loading_resource_set_| is empty.
   void ProcessPendingCallbacksIfUnblocked();
-  // Processes all pending callbacks regardless of the state of
-  // |callback_blocking_loading_resource_set_|.
-  void ProcessPendingCallbacks();
 
   // The name of this resource cache object, useful while debugging.
   const std::string name_;
@@ -641,6 +642,30 @@
 }
 
 template <typename CacheType>
+void ResourceCache<CacheType>::ProcessPendingCallbacks() {
+  DCHECK(resource_cache_thread_checker_.CalledOnValidThread());
+
+  // If callbacks are disabled, simply return.
+  if (are_callbacks_disabled_) {
+    return;
+  }
+
+  is_processing_pending_callbacks_ = true;
+  while (!pending_callback_map_.empty()) {
+    ResourceCallbackInfo& callback_info = pending_callback_map_.front().second;
+
+    // To avoid the last reference of this object getting deleted in the
+    // callbacks.
+    scoped_refptr<CachedResourceType> holder(callback_info.cached_resource);
+    callback_info.cached_resource->RunCallbacks(callback_info.callback_type);
+
+    pending_callback_map_.erase(pending_callback_map_.begin());
+  }
+  is_processing_pending_callbacks_ = false;
+  count_pending_callbacks_ = 0;
+}
+
+template <typename CacheType>
 void ResourceCache<CacheType>::DisableCallbacks() {
   DCHECK(resource_cache_thread_checker_.CalledOnValidThread());
   are_callbacks_disabled_ = true;
@@ -787,30 +812,6 @@
   }
 }
 
-template <typename CacheType>
-void ResourceCache<CacheType>::ProcessPendingCallbacks() {
-  DCHECK(resource_cache_thread_checker_.CalledOnValidThread());
-
-  // If callbacks are disabled, simply return.
-  if (are_callbacks_disabled_) {
-    return;
-  }
-
-  is_processing_pending_callbacks_ = true;
-  while (!pending_callback_map_.empty()) {
-    ResourceCallbackInfo& callback_info = pending_callback_map_.front().second;
-
-    // To avoid the last reference of this object getting deleted in the
-    // callbacks.
-    scoped_refptr<CachedResourceType> holder(callback_info.cached_resource);
-    callback_info.cached_resource->RunCallbacks(callback_info.callback_type);
-
-    pending_callback_map_.erase(pending_callback_map_.begin());
-  }
-  is_processing_pending_callbacks_ = false;
-  count_pending_callbacks_ = 0;
-}
-
 }  // namespace loader
 }  // namespace cobalt
 
diff --git a/src/cobalt/media/base/pipeline.h b/src/cobalt/media/base/pipeline.h
index 7fde2b8..6835195 100644
--- a/src/cobalt/media/base/pipeline.h
+++ b/src/cobalt/media/base/pipeline.h
@@ -31,16 +31,8 @@
 #include "ui/gfx/rect.h"
 #include "ui/gfx/size.h"
 
-#if SB_HAS(PLAYER)
-#define COBALT_USE_SBPLAYER_PIPELINE
-#endif  // SB_HAS(PLAYER)
-
-#if defined(COBALT_USE_SBPLAYER_PIPELINE)
 #include "starboard/window.h"
 typedef SbWindow PipelineWindow;
-#else   // defined(COBALT_USE_SBPLAYER_PIPELINE)
-typedef void* PipelineWindow;
-#endif  // defined(COBALT_USE_SBPLAYER_PIPELINE)
 
 namespace cobalt {
 namespace media {
@@ -133,7 +125,8 @@
                      const PipelineStatusCB& seek_cb,
                      const BufferingStateCB& buffering_state_cb,
                      const base::Closure& duration_change_cb,
-                     const base::Closure& output_mode_change_cb) = 0;
+                     const base::Closure& output_mode_change_cb,
+                     const base::Closure& content_size_change_cb) = 0;
 
   // Asynchronously stops the pipeline, executing |stop_cb| when the pipeline
   // teardown has completed.
diff --git a/src/cobalt/media/base/sbplayer_pipeline.cc b/src/cobalt/media/base/sbplayer_pipeline.cc
index 0cae47c..c9b018e 100644
--- a/src/cobalt/media/base/sbplayer_pipeline.cc
+++ b/src/cobalt/media/base/sbplayer_pipeline.cc
@@ -45,8 +45,6 @@
 namespace cobalt {
 namespace media {
 
-#if SB_HAS(PLAYER)
-
 using base::Time;
 using base::TimeDelta;
 
@@ -66,6 +64,7 @@
   Pipeline::BufferingStateCB buffering_state_cb;
   base::Closure duration_change_cb;
   base::Closure output_mode_change_cb;
+  base::Closure content_size_change_cb;
 #if SB_HAS(PLAYER_WITH_URL)
   std::string source_url;
 #endif  // SB_HAS(PLAYER_WITH_URL)
@@ -99,7 +98,8 @@
              const PipelineStatusCB& seek_cb,
              const BufferingStateCB& buffering_state_cb,
              const base::Closure& duration_change_cb,
-             const base::Closure& output_mode_change_cb) OVERRIDE;
+             const base::Closure& output_mode_change_cb,
+             const base::Closure& content_size_change_cb) OVERRIDE;
 
   void Stop(const base::Closure& stop_cb) OVERRIDE;
   void Seek(TimeDelta time, const PipelineStatusCB& seek_cb);
@@ -221,6 +221,7 @@
   BufferingStateCB buffering_state_cb_;
   base::Closure duration_change_cb_;
   base::Closure output_mode_change_cb_;
+  base::Closure content_size_change_cb_;
   base::optional<bool> decode_to_texture_output_mode_;
 #if SB_HAS(PLAYER_WITH_URL)
   StarboardPlayer::OnEncryptedMediaInitDataEncounteredCB
@@ -337,7 +338,8 @@
     const PipelineStatusCB& ended_cb, const PipelineStatusCB& error_cb,
     const PipelineStatusCB& seek_cb, const BufferingStateCB& buffering_state_cb,
     const base::Closure& duration_change_cb,
-    const base::Closure& output_mode_change_cb) {
+    const base::Closure& output_mode_change_cb,
+    const base::Closure& content_size_change_cb) {
   TRACE_EVENT0("cobalt::media", "SbPlayerPipeline::Start");
 
   DCHECK(!ended_cb.is_null());
@@ -346,6 +348,7 @@
   DCHECK(!buffering_state_cb.is_null());
   DCHECK(!duration_change_cb.is_null());
   DCHECK(!output_mode_change_cb.is_null());
+  DCHECK(!content_size_change_cb.is_null());
 #if SB_HAS(PLAYER_WITH_URL)
   DCHECK(!on_encrypted_media_init_data_encountered_cb.is_null());
 #else   // SB_HAS(PLAYER_WITH_URL)
@@ -360,6 +363,7 @@
   parameters.buffering_state_cb = buffering_state_cb;
   parameters.duration_change_cb = duration_change_cb;
   parameters.output_mode_change_cb = output_mode_change_cb;
+  parameters.content_size_change_cb = content_size_change_cb;
 #if SB_HAS(PLAYER_WITH_URL)
   parameters.source_url = source_url;
   on_encrypted_media_init_data_encountered_cb_ =
@@ -595,6 +599,7 @@
   buffering_state_cb_ = parameters.buffering_state_cb;
   duration_change_cb_ = parameters.duration_change_cb;
   output_mode_change_cb_ = parameters.output_mode_change_cb;
+  content_size_change_cb_ = parameters.content_size_change_cb;
 
 #if SB_HAS(PLAYER_WITH_URL)
   CreatePlayerWithUrl(parameters.source_url);
@@ -843,7 +848,15 @@
     buffering_state_cb_.Run(kHaveMetadata);
 
     bool is_encrypted = audio_stream_->audio_decoder_config().is_encrypted();
+    bool natural_size_changed =
+        (video_stream_->video_decoder_config().natural_size().width() !=
+             natural_size_.width() ||
+         video_stream_->video_decoder_config().natural_size().height() !=
+             natural_size_.height());
     natural_size_ = video_stream_->video_decoder_config().natural_size();
+    if (natural_size_changed) {
+      content_size_change_cb_.Run();
+    }
     is_encrypted |= video_stream_->video_decoder_config().is_encrypted();
     if (is_encrypted) {
       set_drm_system_ready_cb_.Run(
@@ -977,10 +990,19 @@
       break;
     case kSbPlayerStatePrerolling:
       break;
-    case kSbPlayerStatePresenting:
+    case kSbPlayerStatePresenting: {
 #if SB_HAS(PLAYER_WITH_URL)
       duration_ = player_->GetDuration();
       buffering_state_cb_.Run(kHaveMetadata);
+      int frame_width;
+      int frame_height;
+      player_->GetVideoResolution(&frame_width, &frame_height);
+      bool natural_size_changed = (frame_width != natural_size_.width() ||
+                                   frame_height != natural_size_.height());
+      natural_size_ = gfx::Size(frame_width, frame_height);
+      if (natural_size_changed) {
+        content_size_change_cb_.Run();
+      }
 #endif  // SB_HAS(PLAYER_WITH_URL)
       buffering_state_cb_.Run(kPrerollCompleted);
       if (!seek_cb_.is_null()) {
@@ -992,6 +1014,7 @@
         seek_cb.Run(PIPELINE_OK);
       }
       break;
+    }
     case kSbPlayerStateEndOfStream:
       ended_cb_.Run(PIPELINE_OK);
       ended_ = true;
@@ -1013,9 +1036,15 @@
     DCHECK_EQ(stream->type(), DemuxerStream::VIDEO);
     const VideoDecoderConfig& decoder_config = stream->video_decoder_config();
     base::AutoLock auto_lock(lock_);
+    bool natural_size_changed =
+        (decoder_config.natural_size().width() != natural_size_.width() ||
+         decoder_config.natural_size().height() != natural_size_.height());
     natural_size_ = decoder_config.natural_size();
     player_->UpdateVideoResolution(static_cast<int>(natural_size_.width()),
                                    static_cast<int>(natural_size_.height()));
+    if (natural_size_changed) {
+      content_size_change_cb_.Run();
+    }
   }
 }
 
@@ -1059,17 +1088,11 @@
 
 }  // namespace
 
-#endif  // SB_HAS(PLAYER)
-
 scoped_refptr<Pipeline> Pipeline::Create(
     PipelineWindow window,
     const scoped_refptr<base::MessageLoopProxy>& message_loop,
     MediaLog* media_log) {
-#if SB_HAS(PLAYER)
   return new SbPlayerPipeline(window, message_loop, media_log);
-#else
-  return NULL;
-#endif
 }
 
 }  // namespace media
diff --git a/src/cobalt/media/base/sbplayer_set_bounds_helper.cc b/src/cobalt/media/base/sbplayer_set_bounds_helper.cc
index 53187f2..7bec081 100644
--- a/src/cobalt/media/base/sbplayer_set_bounds_helper.cc
+++ b/src/cobalt/media/base/sbplayer_set_bounds_helper.cc
@@ -26,7 +26,7 @@
 }  // namespace
 
 void SbPlayerSetBoundsHelper::SetPlayer(StarboardPlayer* player) {
-  base::Lock lock_;
+  base::AutoLock auto_lock(lock_);
   player_ = player;
 }
 
diff --git a/src/cobalt/media/base/starboard_player.cc b/src/cobalt/media/base/starboard_player.cc
index 920d564..2d93c4c 100644
--- a/src/cobalt/media/base/starboard_player.cc
+++ b/src/cobalt/media/base/starboard_player.cc
@@ -172,6 +172,22 @@
   frame_height_ = frame_height;
 }
 
+void StarboardPlayer::GetVideoResolution(int* frame_width, int* frame_height) {
+  DCHECK(message_loop_->BelongsToCurrentThread());
+
+  DCHECK(frame_width);
+  DCHECK(frame_height);
+  DCHECK(SbPlayerIsValid(player_));
+
+  SbPlayerInfo out_player_info;
+  SbPlayerGetInfo(player_, &out_player_info);
+  frame_width_ = out_player_info.frame_width;
+  frame_height_ = out_player_info.frame_height;
+
+  *frame_width = frame_width_;
+  *frame_height = frame_height_;
+}
+
 #if !SB_HAS(PLAYER_WITH_URL)
 
 void StarboardPlayer::WriteBuffer(DemuxerStream::Type type,
@@ -397,6 +413,11 @@
   preroll_timestamp_ = SbMediaTimeToTimeDelta(info.current_media_pts);
 
   set_bounds_helper_->SetPlayer(NULL);
+  ShellMediaPlatform::Instance()->GetVideoFrameProvider()->SetOutputMode(
+      ShellVideoFrameProvider::kOutputModeInvalid);
+  ShellMediaPlatform::Instance()->GetVideoFrameProvider()
+      ->ResetGetCurrentSbDecodeTargetFunction();
+
   SbPlayerDestroy(player_);
 
   player_ = kSbPlayerInvalid;
diff --git a/src/cobalt/media/base/starboard_player.h b/src/cobalt/media/base/starboard_player.h
index b68dd6a..dda7808 100644
--- a/src/cobalt/media/base/starboard_player.h
+++ b/src/cobalt/media/base/starboard_player.h
@@ -72,6 +72,7 @@
   bool IsValid() const { return SbPlayerIsValid(player_); }
 
   void UpdateVideoResolution(int frame_width, int frame_height);
+  void GetVideoResolution(int* frame_width, int* frame_height);
 
 #if !SB_HAS(PLAYER_WITH_URL)
   void WriteBuffer(DemuxerStream::Type type,
diff --git a/src/cobalt/media/fetcher_buffered_data_source.cc b/src/cobalt/media/fetcher_buffered_data_source.cc
index 9dbdd5f..8f6d58a 100644
--- a/src/cobalt/media/fetcher_buffered_data_source.cc
+++ b/src/cobalt/media/fetcher_buffered_data_source.cc
@@ -20,6 +20,7 @@
 #include "base/bind.h"
 #include "base/callback_helpers.h"
 #include "base/string_number_conversions.h"
+#include "cobalt/loader/cors_preflight.h"
 #include "net/http/http_response_headers.h"
 #include "net/http/http_status_code.h"
 
@@ -39,7 +40,8 @@
 FetcherBufferedDataSource::FetcherBufferedDataSource(
     const scoped_refptr<base::MessageLoopProxy>& message_loop, const GURL& url,
     const csp::SecurityCallback& security_callback,
-    network::NetworkModule* network_module)
+    network::NetworkModule* network_module, loader::RequestMode request_mode,
+    loader::Origin origin)
     : message_loop_(message_loop),
       url_(url),
       network_module_(network_module),
@@ -53,7 +55,10 @@
       pending_read_position_(0),
       pending_read_size_(0),
       pending_read_data_(NULL),
-      security_callback_(security_callback) {
+      security_callback_(security_callback),
+      request_mode_(request_mode),
+      document_origin_(origin),
+      is_origin_safe_(false) {
   DCHECK(message_loop_);
   DCHECK(network_module);
 }
@@ -155,6 +160,20 @@
       source->GetResponseHeaders();
   DCHECK(headers);
 
+  if (!is_origin_safe_) {
+    if (loader::CORSPreflight::CORSCheck(
+            *headers, document_origin_.SerializedOrigin(),
+            request_mode_ == loader::kCORSModeIncludeCredentials)) {
+      is_origin_safe_ = true;
+    } else {
+      error_occured_ = true;
+      if (!pending_read_cb_.is_null()) {
+        base::ResetAndReturn(&pending_read_cb_).Run(-1);
+      }
+      return;
+    }
+  }
+
   uint64 first_byte_offset = 0;
 
   if (headers->response_code() == net::HTTP_PARTIAL_CONTENT) {
@@ -309,6 +328,15 @@
       "Range: bytes=" + base::Uint64ToString(last_request_offset_) + "-" +
       base::Uint64ToString(last_request_offset_ + last_request_size_ - 1);
   fetcher_->AddExtraRequestHeader(range_request);
+  if (!is_origin_safe_) {
+    if (request_mode_ != loader::kNoCORSMode &&
+        document_origin_ != loader::Origin(url_) && !url_.SchemeIs("data")) {
+      fetcher_->AddExtraRequestHeader("Origin:" +
+                                      document_origin_.SerializedOrigin());
+    } else {
+      is_origin_safe_ = true;
+    }
+  }
   fetcher_->Start();
   UpdateDownloadingStatus(/* is_downloading = */ true);
 }
diff --git a/src/cobalt/media/fetcher_buffered_data_source.h b/src/cobalt/media/fetcher_buffered_data_source.h
index 29e7cce..8bb40a6 100644
--- a/src/cobalt/media/fetcher_buffered_data_source.h
+++ b/src/cobalt/media/fetcher_buffered_data_source.h
@@ -25,6 +25,8 @@
 #include "base/optional.h"
 #include "base/synchronization/lock.h"
 #include "cobalt/csp/content_security_policy.h"
+#include "cobalt/loader/fetcher.h"
+#include "cobalt/loader/origin.h"
 #include "cobalt/network/network_module.h"
 #include "googleurl/src/gurl.h"
 #if defined(COBALT_MEDIA_SOURCE_2016)
@@ -70,7 +72,8 @@
   FetcherBufferedDataSource(
       const scoped_refptr<base::MessageLoopProxy>& message_loop,
       const GURL& url, const csp::SecurityCallback& security_callback,
-      network::NetworkModule* network_module);
+      network::NetworkModule* network_module, loader::RequestMode requset_mode,
+      loader::Origin origin);
   ~FetcherBufferedDataSource() OVERRIDE;
 
   // DataSource methods.
@@ -153,6 +156,11 @@
 
   csp::SecurityCallback security_callback_;
   scoped_refptr<CancelableClosure> cancelable_create_fetcher_closure_;
+
+  loader::RequestMode request_mode_;
+  loader::Origin document_origin_;
+  // True if the origin is allowed to fetch resource data.
+  bool is_origin_safe_;
 };
 
 }  // namespace media
diff --git a/src/cobalt/media/filters/source_buffer_stream.cc b/src/cobalt/media/filters/source_buffer_stream.cc
index 2602fd0..4f9ffb0 100644
--- a/src/cobalt/media/filters/source_buffer_stream.cc
+++ b/src/cobalt/media/filters/source_buffer_stream.cc
@@ -394,7 +394,8 @@
 
   DVLOG(1) << __func__ << " " << GetStreamTypeName()
            << ": done. ranges_=" << RangesToString(ranges_);
-  DCHECK(IsRangeListSorted(ranges_));
+  // TODO: Investigate if the following DCHECK should be restored.
+  // DCHECK(IsRangeListSorted(ranges_));
   DCHECK(OnlySelectedRangeIsSeeked());
   return true;
 }
diff --git a/src/cobalt/media/player/web_media_player.h b/src/cobalt/media/player/web_media_player.h
index 613efe7..c913b8c 100644
--- a/src/cobalt/media/player/web_media_player.h
+++ b/src/cobalt/media/player/web_media_player.h
@@ -88,8 +88,7 @@
 #else   // SB_HAS(PLAYER_WITH_URL)
   virtual void LoadMediaSource() = 0;
   virtual void LoadProgressive(const GURL& url,
-                               scoped_ptr<BufferedDataSource> data_source,
-                               CORSMode cors_mode) = 0;
+                               scoped_ptr<BufferedDataSource> data_source) = 0;
 #endif  // SB_HAS(PLAYER_WITH_URL)
 
   virtual void CancelLoad() = 0;
@@ -202,6 +201,7 @@
   virtual void TimeChanged(bool eos_played) = 0;
   virtual void DurationChanged() = 0;
   virtual void OutputModeChanged() = 0;
+  virtual void ContentSizeChanged() = 0;
   virtual void PlaybackStateChanged() = 0;
   // TODO: Revisit the necessity of the following function.
   virtual void SetOpaque(bool /* opaque */) {}
diff --git a/src/cobalt/media/player/web_media_player_impl.cc b/src/cobalt/media/player/web_media_player_impl.cc
index 884212f..0b829ae 100644
--- a/src/cobalt/media/player/web_media_player_impl.cc
+++ b/src/cobalt/media/player/web_media_player_impl.cc
@@ -259,8 +259,7 @@
 }
 
 void WebMediaPlayerImpl::LoadProgressive(
-    const GURL& url, scoped_ptr<BufferedDataSource> data_source,
-    CORSMode cors_mode) {
+    const GURL& url, scoped_ptr<BufferedDataSource> data_source) {
   TRACE_EVENT0("cobalt::media", "WebMediaPlayerImpl::LoadProgressive");
   DCHECK_EQ(main_loop_, MessageLoop::current());
 
@@ -740,7 +739,8 @@
       BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnPipelineSeek),
       BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnPipelineBufferingState),
       BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnDurationChanged),
-      BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnOutputModeChanged));
+      BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnOutputModeChanged),
+      BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnContentSizeChanged));
 }
 #else  // SB_HAS(PLAYER_WITH_URL)
 void WebMediaPlayerImpl::StartPipeline(Demuxer* demuxer) {
@@ -760,7 +760,8 @@
       BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnPipelineSeek),
       BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnPipelineBufferingState),
       BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnDurationChanged),
-      BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnOutputModeChanged));
+      BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnOutputModeChanged),
+      BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnContentSizeChanged));
 }
 #endif  // SB_HAS(PLAYER_WITH_URL)
 
@@ -866,5 +867,9 @@
   GetClient()->OutputModeChanged();
 }
 
+void WebMediaPlayerImpl::OnContentSizeChanged() {
+  GetClient()->ContentSizeChanged();
+}
+
 }  // namespace media
 }  // namespace cobalt
diff --git a/src/cobalt/media/player/web_media_player_impl.h b/src/cobalt/media/player/web_media_player_impl.h
index 5df1690..b4c6236 100644
--- a/src/cobalt/media/player/web_media_player_impl.h
+++ b/src/cobalt/media/player/web_media_player_impl.h
@@ -69,10 +69,8 @@
 
 #if defined(OS_STARBOARD)
 
-#if SB_HAS(PLAYER)
 #define COBALT_USE_PUNCHOUT
 #define COBALT_SKIP_SEEK_REQUEST_NEAR_END
-#endif  // SB_HAS(PLAYER)
 
 #endif  // defined(OS_STARBOARD)
 
@@ -118,8 +116,7 @@
 #else   // SB_HAS(PLAYER_WITH_URL)
   void LoadMediaSource() OVERRIDE;
   void LoadProgressive(const GURL& url,
-                       scoped_ptr<BufferedDataSource> data_source,
-                       CORSMode cors_mode) OVERRIDE;
+                       scoped_ptr<BufferedDataSource> data_source) OVERRIDE;
 #endif  // SB_HAS(PLAYER_WITH_URL)
   void CancelLoad() OVERRIDE;
 
@@ -233,6 +230,7 @@
   // Callbacks that forward duration change from |pipeline_| to |client_|.
   void OnDurationChanged();
   void OnOutputModeChanged();
+  void OnContentSizeChanged();
 
   base::Thread pipeline_thread_;
 
diff --git a/src/cobalt/media/sandbox/demuxer_helper.cc b/src/cobalt/media/sandbox/demuxer_helper.cc
index d791180..45000b7 100644
--- a/src/cobalt/media/sandbox/demuxer_helper.cc
+++ b/src/cobalt/media/sandbox/demuxer_helper.cc
@@ -267,7 +267,8 @@
   scoped_refptr<FetcherBufferedDataSource> data_source(
       new FetcherBufferedDataSource(media_message_loop, video_url,
                                     csp::SecurityCallback(),
-                                    fetcher_factory->network_module()));
+                                    fetcher_factory->network_module(),
+                                    loader::kNoCORSMode, loader::Origin()));
   scoped_refptr<Demuxer> demuxer =
       new ::media::ShellDemuxer(media_message_loop, data_source);
   demuxer->Initialize(
diff --git a/src/cobalt/media/sandbox/web_media_player_helper.cc b/src/cobalt/media/sandbox/web_media_player_helper.cc
index 6b98c90..d2fcc06 100644
--- a/src/cobalt/media/sandbox/web_media_player_helper.cc
+++ b/src/cobalt/media/sandbox/web_media_player_helper.cc
@@ -38,6 +38,7 @@
   void TimeChanged(bool) OVERRIDE {}
   void DurationChanged() OVERRIDE {}
   void OutputModeChanged() OVERRIDE {}
+  void ContentSizeChanged() OVERRIDE {}
   void PlaybackStateChanged() OVERRIDE {}
   void SawUnsupportedTracks() OVERRIDE {}
   float Volume() const OVERRIDE { return 1.f; }
@@ -73,12 +74,12 @@
   player_->SetRate(1.0);
   scoped_ptr<BufferedDataSource> data_source(new FetcherBufferedDataSource(
       base::MessageLoopProxy::current(), video_url, csp::SecurityCallback(),
-      fetcher_factory->network_module()));
+      fetcher_factory->network_module(), loader::kNoCORSMode,
+      loader::Origin()));
 // TODO: Investigate a better way to exclude this when SB_HAS(PLAYER_WITH_URL)
 //       is enabled.
 #if !SB_HAS(PLAYER_WITH_URL)
-  player_->LoadProgressive(video_url, data_source.Pass(),
-                           WebMediaPlayer::kCORSModeUnspecified);
+  player_->LoadProgressive(video_url, data_source.Pass());
 #endif  // !SB_HAS(PLAYER_WITH_URL)
   player_->Play();
 }
diff --git a/src/cobalt/network/lib/README.md b/src/cobalt/network/lib/README.md
new file mode 100644
index 0000000..55af499
--- /dev/null
+++ b/src/cobalt/network/lib/README.md
@@ -0,0 +1,9 @@
+This directory provides an API for clients that build Cobalt into a lib using
+the 'cobalt_enable_lib' flag.
+
+It is highly experimental at this point and is expected to change significantly
+across releases.
+
+As a general convention, functions whose symbols are exported are defined in an
+'exported' subdirectory and functions that are required to be implemented by
+clients are defined in a 'imported' subdirectory.
diff --git a/src/cobalt/network/lib/exported/user_agent.h b/src/cobalt/network/lib/exported/user_agent.h
new file mode 100644
index 0000000..06af638
--- /dev/null
+++ b/src/cobalt/network/lib/exported/user_agent.h
@@ -0,0 +1,38 @@
+// Copyright 2017 Google Inc. All Rights Reserved.
+//
+// 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.
+
+// This file provides a simple API for exposing Starboard as a
+// library to another app.
+
+#ifndef COBALT_NETWORK_LIB_EXPORTED_USER_AGENT_H_
+#define COBALT_NETWORK_LIB_EXPORTED_USER_AGENT_H_
+
+#include "starboard/export.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// Sets a string to be appended to the platform segment of the User Agent
+// string that the Starboard application will report. The maximum length of
+// |suffix| is 128 including null terminator (which is required). Returns false
+// if the suffix could not be set, in which case nothing will be apended to the
+// UA string.
+SB_EXPORT_PLATFORM bool CbLibUserAgentSetPlatformNameSuffix(const char* suffix);
+
+#ifdef __cplusplus
+}  // extern "C"
+#endif
+
+#endif  // COBALT_NETWORK_LIB_EXPORTED_USER_AGENT_H_
diff --git a/src/cobalt/network/network.gyp b/src/cobalt/network/network.gyp
index 5d7efa7..a584ce0 100644
--- a/src/cobalt/network/network.gyp
+++ b/src/cobalt/network/network.gyp
@@ -79,6 +79,9 @@
             'ENABLE_NETWORK_LOGGING',
           ],
         }],
+        ['cobalt_enable_lib == 1', {
+          'defines' : ['COBALT_ENABLE_LIB'],
+        }],
       ],
       'export_dependent_settings': [
         '<(DEPTH)/net/net.gyp:net',
diff --git a/src/cobalt/network/user_agent_string_factory.cc b/src/cobalt/network/user_agent_string_factory.cc
index 8bd7815..1da3e86 100644
--- a/src/cobalt/network/user_agent_string_factory.cc
+++ b/src/cobalt/network/user_agent_string_factory.cc
@@ -18,10 +18,21 @@
 
 #include "base/string_util.h"
 #include "base/stringprintf.h"
+#if defined(COBALT_ENABLE_LIB)
+#include "cobalt/network/lib/exported/user_agent.h"
+#endif
 #include "cobalt/version.h"
 
 #include "cobalt_build_id.h"  // NOLINT(build/include)
 
+#if defined(COBALT_ENABLE_LIB)
+namespace {
+// Max length including null terminator.
+const size_t kUserAgentPlatformMaxSuffixLength = 128;
+char g_user_agent_platform_suffix[kUserAgentPlatformMaxSuffixLength] = {0};
+}  // namespace
+#endif  // defined(COBALT_ENABLE_LIB)
+
 namespace cobalt {
 namespace network {
 
@@ -120,6 +131,13 @@
     platform += architecture_tokens_;
   }
 
+#if defined(COBALT_ENABLE_LIB)
+  if (g_user_agent_platform_suffix[0] != '\0') {
+    platform += "; ";
+    platform += g_user_agent_platform_suffix;
+  }
+#endif  // defined(COBALT_ENABLE_LIB)
+
   return platform;
 }
 
@@ -161,3 +179,18 @@
 
 }  // namespace network
 }  // namespace cobalt
+
+#if defined(COBALT_ENABLE_LIB)
+// Allow host app to append a suffix to the reported platform name.
+bool CbLibUserAgentSetPlatformNameSuffix(const char* suffix) {
+  size_t suffix_length = base::strlcpy(g_user_agent_platform_suffix, suffix,
+                                       kUserAgentPlatformMaxSuffixLength);
+  if (suffix_length >= kUserAgentPlatformMaxSuffixLength) {
+    // If the suffix is too large then nothing is appended to the platform.
+    g_user_agent_platform_suffix[0] = '\0';
+    return false;
+  }
+
+  return true;
+}
+#endif  // defined(COBALT_ENABLE_LIB)
diff --git a/src/cobalt/render_tree/composition_node.h b/src/cobalt/render_tree/composition_node.h
index 92a54ec..dc2a84d 100644
--- a/src/cobalt/render_tree/composition_node.h
+++ b/src/cobalt/render_tree/composition_node.h
@@ -65,6 +65,9 @@
 
     Builder() {}
     explicit Builder(const math::Vector2dF& offset) : offset_(offset) {}
+    Builder(Node* node, const math::Vector2dF& offset) : offset_(offset) {
+      children_.push_back(node);
+    }
 
     Builder(const Builder& other)
         : offset_(other.offset_), children_(other.children_) {}
@@ -113,6 +116,9 @@
   explicit CompositionNode(Builder&& builder)
       : data_(builder.Pass()), cached_bounds_(ComputeBounds()) {}
 
+  CompositionNode(Node* node, const math::Vector2dF& offset)
+      : data_(node, offset), cached_bounds_(ComputeBounds()) {}
+
   void Accept(NodeVisitor* visitor) OVERRIDE;
   math::RectF GetBounds() const OVERRIDE;
 
diff --git a/src/cobalt/render_tree/mock_resource_provider.h b/src/cobalt/render_tree/mock_resource_provider.h
index d30b9fc..f6e0470 100644
--- a/src/cobalt/render_tree/mock_resource_provider.h
+++ b/src/cobalt/render_tree/mock_resource_provider.h
@@ -36,6 +36,10 @@
 
 class MockResourceProvider : public ResourceProvider {
  public:
+  base::TypeId GetTypeId() const OVERRIDE {
+    return base::GetTypeId<MockResourceProvider>();
+  }
+
   MOCK_METHOD0(Finish, void());
   MOCK_METHOD1(PixelFormatSupported, bool(PixelFormat pixel_format));
   MOCK_METHOD1(AlphaFormatSupported, bool(AlphaFormat alpha_format));
diff --git a/src/cobalt/render_tree/resource_provider.h b/src/cobalt/render_tree/resource_provider.h
index acbbb21..8169a7e 100644
--- a/src/cobalt/render_tree/resource_provider.h
+++ b/src/cobalt/render_tree/resource_provider.h
@@ -20,6 +20,7 @@
 
 #include "base/memory/ref_counted.h"
 #include "base/memory/scoped_ptr.h"
+#include "cobalt/base/type_id.h"
 #include "cobalt/render_tree/font.h"
 #include "cobalt/render_tree/font_provider.h"
 #include "cobalt/render_tree/glyph_buffer.h"
@@ -50,6 +51,10 @@
 
   virtual ~ResourceProvider() {}
 
+  // Returns an ID that is unique to the ResourceProvider type.  This can be
+  // used to polymorphically identify what type of ResourceProvider this is.
+  virtual base::TypeId GetTypeId() const = 0;
+
   // Blocks until it can be guaranteed that all resource-related operations have
   // completed.  This might be important if we would like to ensure that memory
   // allocations or deallocations have occurred before proceeding with a memory
diff --git a/src/cobalt/render_tree/resource_provider_stub.h b/src/cobalt/render_tree/resource_provider_stub.h
index 397d8cb..3bdd12f 100644
--- a/src/cobalt/render_tree/resource_provider_stub.h
+++ b/src/cobalt/render_tree/resource_provider_stub.h
@@ -219,6 +219,10 @@
       : release_image_data_(release_image_data) {}
   ~ResourceProviderStub() OVERRIDE {}
 
+  base::TypeId GetTypeId() const OVERRIDE {
+    return base::GetTypeId<ResourceProviderStub>();
+  }
+
   void Finish() OVERRIDE {}
 
   bool PixelFormatSupported(PixelFormat pixel_format) OVERRIDE {
diff --git a/src/cobalt/render_tree/rounded_corners.cc b/src/cobalt/render_tree/rounded_corners.cc
index 8149cd4..ad460fc 100644
--- a/src/cobalt/render_tree/rounded_corners.cc
+++ b/src/cobalt/render_tree/rounded_corners.cc
@@ -29,7 +29,6 @@
 }
 
 RoundedCorners RoundedCorners::Normalize(const math::RectF& rect) const {
-  const float kEpsilon = 0.0001f;
   float scale = 1.0f;
   float size;
 
@@ -39,25 +38,25 @@
   size = top_left.horizontal +
          std::max(top_right.horizontal, bottom_right.horizontal);
   if (size > rect.width()) {
-    scale = (rect.width() - kEpsilon) / size;
+    scale = rect.width() / size;
   }
 
   size = bottom_left.horizontal +
          std::max(bottom_right.horizontal, top_right.horizontal);
   if (size > rect.width()) {
-    scale = std::min((rect.width() - kEpsilon) / size, scale);
+    scale = std::min(rect.width() / size, scale);
   }
 
   size =
       top_left.vertical + std::max(bottom_left.vertical, bottom_right.vertical);
   if (size > rect.height()) {
-    scale = std::min((rect.height() - kEpsilon) / size, scale);
+    scale = std::min(rect.height() / size, scale);
   }
 
   size = top_right.vertical +
          std::max(bottom_right.vertical, bottom_left.vertical);
   if (size > rect.height()) {
-    scale = std::min((rect.height() - kEpsilon) / size, scale);
+    scale = std::min(rect.height() / size, scale);
   }
 
   scale = std::max(scale, 0.0f);
@@ -65,17 +64,23 @@
 }
 
 bool RoundedCorners::IsNormalized(const math::RectF& rect) const {
+  // Introduce a fuzz epsilon so that we are not strict about rounding errors
+  // when computing Normalize().
+  const float kEpsilon = 0.0001f;
+  const float fuzzed_width = rect.width() + kEpsilon;
+  const float fuzzed_height = rect.height() + kEpsilon;
+
   return
       // Adjacent corners must not overlap.
-      top_left.horizontal + top_right.horizontal <= rect.width() &&
-      bottom_left.horizontal + bottom_right.horizontal <= rect.width() &&
-      top_left.vertical + bottom_left.vertical <= rect.height() &&
-      top_right.vertical + bottom_right.vertical <= rect.height() &&
+      top_left.horizontal + top_right.horizontal <= fuzzed_width &&
+      bottom_left.horizontal + bottom_right.horizontal <= fuzzed_width &&
+      top_left.vertical + bottom_left.vertical <= fuzzed_height &&
+      top_right.vertical + bottom_right.vertical <= fuzzed_height &&
       // Opposing corners must not overlap.
-      top_left.horizontal + bottom_right.horizontal <= rect.width() &&
-      bottom_left.horizontal + top_right.horizontal <= rect.width() &&
-      top_left.vertical + bottom_right.vertical <= rect.height() &&
-      top_right.vertical + bottom_left.vertical <= rect.height();
+      top_left.horizontal + bottom_right.horizontal <= fuzzed_width &&
+      bottom_left.horizontal + top_right.horizontal <= fuzzed_width &&
+      top_left.vertical + bottom_right.vertical <= fuzzed_height &&
+      top_right.vertical + bottom_left.vertical <= fuzzed_height;
 }
 
 }  // namespace render_tree
diff --git a/src/cobalt/renderer/backend/blitter/display.cc b/src/cobalt/renderer/backend/blitter/display.cc
index 7bd4d91..fe0d7e4 100644
--- a/src/cobalt/renderer/backend/blitter/display.cc
+++ b/src/cobalt/renderer/backend/blitter/display.cc
@@ -40,6 +40,8 @@
 
   void Flip() OVERRIDE;
 
+  bool CreationError() OVERRIDE { return false; }
+
  private:
   ~DisplayRenderTargetBlitter() OVERRIDE;
 
diff --git a/src/cobalt/renderer/backend/blitter/graphics_context.cc b/src/cobalt/renderer/backend/blitter/graphics_context.cc
index ce86f5d..a0d45ed 100644
--- a/src/cobalt/renderer/backend/blitter/graphics_context.cc
+++ b/src/cobalt/renderer/backend/blitter/graphics_context.cc
@@ -49,8 +49,14 @@
     const math::Size& dimensions) {
   TRACE_EVENT0("cobalt::renderer",
                "GraphicsContextBlitter::CreateOffscreenRenderTarget");
-  return scoped_refptr<RenderTarget>(
+
+  scoped_refptr<RenderTarget> render_target(
       new SurfaceRenderTargetBlitter(device_, dimensions));
+  if (render_target->CreationError()) {
+    return scoped_refptr<RenderTarget>();
+  } else {
+    return render_target;
+  }
 }
 
 scoped_array<uint8_t> GraphicsContextBlitter::DownloadPixelDataAsRGBA(
diff --git a/src/cobalt/renderer/backend/blitter/surface_render_target.cc b/src/cobalt/renderer/backend/blitter/surface_render_target.cc
index 6b71860..25ba88c 100644
--- a/src/cobalt/renderer/backend/blitter/surface_render_target.cc
+++ b/src/cobalt/renderer/backend/blitter/surface_render_target.cc
@@ -27,16 +27,24 @@
   surface_ = SbBlitterCreateRenderTargetSurface(device, dimensions.width(),
                                                 dimensions.height(),
                                                 kSbBlitterSurfaceFormatRGBA8);
-  CHECK(SbBlitterIsSurfaceValid(surface_));
+  if (!SbBlitterIsSurfaceValid(surface_)) {
+    LOG(ERROR) << "Error creating offscreen render target surface.";
+    return;
+  }
 
   render_target_ = SbBlitterGetRenderTargetFromSurface(surface_);
-  CHECK(SbBlitterIsRenderTargetValid(render_target_));
+  if (!SbBlitterIsRenderTargetValid(render_target_)) {
+    LOG(ERROR) << "Error acquiring a render target from the surface.";
+    SbBlitterDestroySurface(surface_);
+    surface_ = kSbBlitterInvalidSurface;
+    return;
+  }
 
   size_ = dimensions;
 }
 
 SurfaceRenderTargetBlitter::~SurfaceRenderTargetBlitter() {
-  if (surface_ != kSbBlitterInvalidSurface) {
+  if (SbBlitterIsSurfaceValid(surface_)) {
     SbBlitterDestroySurface(surface_);
   }
 }
diff --git a/src/cobalt/renderer/backend/blitter/surface_render_target.h b/src/cobalt/renderer/backend/blitter/surface_render_target.h
index 48dc88e..d7df8ed 100644
--- a/src/cobalt/renderer/backend/blitter/surface_render_target.h
+++ b/src/cobalt/renderer/backend/blitter/surface_render_target.h
@@ -47,6 +47,8 @@
 
   void Flip() OVERRIDE {}
 
+  bool CreationError() OVERRIDE { return !SbBlitterIsSurfaceValid(surface_); }
+
  private:
   ~SurfaceRenderTargetBlitter() OVERRIDE;
 
diff --git a/src/cobalt/renderer/backend/egl/display.cc b/src/cobalt/renderer/backend/egl/display.cc
index 5f1c382..a9b6294 100644
--- a/src/cobalt/renderer/backend/egl/display.cc
+++ b/src/cobalt/renderer/backend/egl/display.cc
@@ -33,6 +33,8 @@
 
   bool IsWindowRenderTarget() const OVERRIDE { return true; }
 
+  bool CreationError() OVERRIDE { return false; }
+
  private:
   ~DisplayRenderTargetEGL() OVERRIDE;
 
diff --git a/src/cobalt/renderer/backend/egl/framebuffer.cc b/src/cobalt/renderer/backend/egl/framebuffer.cc
index 068da37..8d2424b 100644
--- a/src/cobalt/renderer/backend/egl/framebuffer.cc
+++ b/src/cobalt/renderer/backend/egl/framebuffer.cc
@@ -29,20 +29,42 @@
 FramebufferEGL::FramebufferEGL(GraphicsContextEGL* graphics_context,
                                const math::Size& size, GLenum color_format,
                                GLenum depth_format)
-    : graphics_context_(graphics_context),
-      size_(size) {
+    : graphics_context_(graphics_context), size_(size), error_(false) {
   GraphicsContextEGL::ScopedMakeCurrent scoped_make_current(graphics_context_);
 
   // Create the framebuffer object.
-  GL_CALL(glGenFramebuffers(1, &framebuffer_handle_));
+  glGenFramebuffers(1, &framebuffer_handle_);
+  if (glGetError() != GL_NO_ERROR) {
+    LOG(ERROR) << "Error creating new framebuffer.";
+    error_ = true;
+    return;
+  }
   GL_CALL(glBindFramebuffer(GL_FRAMEBUFFER, framebuffer_handle_));
 
   // Create and attach a texture for color.
   GLuint color_handle = 0;
-  GL_CALL(glGenTextures(1, &color_handle));
+  glGenTextures(1, &color_handle);
+  if (glGetError() != GL_NO_ERROR) {
+    LOG(ERROR) << "Error creating new texture.";
+    error_ = true;
+    GL_CALL(glBindFramebuffer(GL_FRAMEBUFFER, 0));
+    GL_CALL(glDeleteFramebuffers(1, &framebuffer_handle_));
+    return;
+  }
+
   GL_CALL(glBindTexture(GL_TEXTURE_2D, color_handle));
-  GL_CALL(glTexImage2D(GL_TEXTURE_2D, 0, color_format,
-      size_.width(), size_.height(), 0, color_format, GL_UNSIGNED_BYTE, 0));
+  glTexImage2D(GL_TEXTURE_2D, 0, color_format, size_.width(), size_.height(), 0,
+               color_format, GL_UNSIGNED_BYTE, 0);
+  if (glGetError() != GL_NO_ERROR) {
+    LOG(ERROR) << "Error allocating new texture backing for a framebuffer.";
+    error_ = true;
+    GL_CALL(glBindTexture(GL_TEXTURE_2D, 0));
+    GL_CALL(glDeleteTextures(1, &color_handle));
+    GL_CALL(glBindFramebuffer(GL_FRAMEBUFFER, 0));
+    GL_CALL(glDeleteFramebuffers(1, &framebuffer_handle_));
+    return;
+  }
+
   GL_CALL(glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
   GL_CALL(glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
   GL_CALL(glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
@@ -56,7 +78,14 @@
   // Create and attach a depth buffer if requested.
   depthbuffer_handle_ = 0;
   if (depth_format != GL_NONE) {
-    CreateDepthAttachment(depth_format);
+    if (!CreateDepthAttachment(depth_format)) {
+      LOG(ERROR) << "Error creating depth attachment for framebuffer.";
+      error_ = true;
+      GL_CALL(glBindFramebuffer(GL_FRAMEBUFFER, 0));
+      GL_CALL(glDeleteFramebuffers(1, &framebuffer_handle_));
+      color_texture_.reset();
+      return;
+    }
   }
 
   // Verify the framebuffer object is valid.
@@ -80,21 +109,36 @@
 }
 
 FramebufferEGL::~FramebufferEGL() {
-  GraphicsContextEGL::ScopedMakeCurrent scoped_make_current(graphics_context_);
-  GL_CALL(glDeleteFramebuffers(1, &framebuffer_handle_));
-  if (depthbuffer_handle_ != 0) {
-    GL_CALL(glDeleteRenderbuffers(1, &depthbuffer_handle_));
+  if (!error_) {
+    GraphicsContextEGL::ScopedMakeCurrent scoped_make_current(
+        graphics_context_);
+    GL_CALL(glDeleteFramebuffers(1, &framebuffer_handle_));
+    if (depthbuffer_handle_ != 0) {
+      GL_CALL(glDeleteRenderbuffers(1, &depthbuffer_handle_));
+    }
   }
 }
 
-void FramebufferEGL::CreateDepthAttachment(GLenum depth_format) {
-  GL_CALL(glGenRenderbuffers(1, &depthbuffer_handle_));
+bool FramebufferEGL::CreateDepthAttachment(GLenum depth_format) {
+  glGenRenderbuffers(1, &depthbuffer_handle_);
+  if (glGetError() != GL_NO_ERROR) {
+    LOG(ERROR) << "Error creating depth buffer object.";
+    return false;
+  }
   GL_CALL(glBindRenderbuffer(GL_RENDERBUFFER, depthbuffer_handle_));
-  GL_CALL(glRenderbufferStorage(GL_RENDERBUFFER, depth_format, size_.width(),
-      size_.height()));
+  glRenderbufferStorage(GL_RENDERBUFFER, depth_format, size_.width(),
+                        size_.height());
+  if (glGetError() != GL_NO_ERROR) {
+    LOG(ERROR) << "Error allocating memory for depth buffer.";
+    GL_CALL(glBindRenderbuffer(GL_RENDERBUFFER, 0));
+    GL_CALL(glDeleteRenderbuffers(1, &depthbuffer_handle_));
+    return false;
+  }
   GL_CALL(glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
       GL_RENDERBUFFER, depthbuffer_handle_));
   GL_CALL(glBindRenderbuffer(GL_RENDERBUFFER, 0));
+
+  return true;
 }
 
 }  // namespace backend
diff --git a/src/cobalt/renderer/backend/egl/framebuffer.h b/src/cobalt/renderer/backend/egl/framebuffer.h
index 20ffd68..9dd676d 100644
--- a/src/cobalt/renderer/backend/egl/framebuffer.h
+++ b/src/cobalt/renderer/backend/egl/framebuffer.h
@@ -49,8 +49,12 @@
   // Return the framebuffer object's ID.
   GLuint gl_handle() const { return framebuffer_handle_; }
 
+  // Returns true if an error occurred during construction of this framebuffer
+  // (indicating that this object is invalid).
+  bool CreationError() const { return error_; }
+
  private:
-  void CreateDepthAttachment(GLenum depth_format);
+  bool CreateDepthAttachment(GLenum depth_format);
 
   GraphicsContextEGL* graphics_context_;
   math::Size size_;
@@ -63,6 +67,9 @@
 
   // The color component of the framebuffer object as a texture.
   scoped_ptr<TextureEGL> color_texture_;
+
+  // Did an error occur during construction?
+  bool error_;
 };
 
 }  // namespace backend
diff --git a/src/cobalt/renderer/backend/egl/framebuffer_render_target.h b/src/cobalt/renderer/backend/egl/framebuffer_render_target.h
index 0df7044..3d5a8fd 100644
--- a/src/cobalt/renderer/backend/egl/framebuffer_render_target.h
+++ b/src/cobalt/renderer/backend/egl/framebuffer_render_target.h
@@ -52,6 +52,8 @@
     return framebuffer_.GetColorTexture();
   }
 
+  bool CreationError() OVERRIDE { return framebuffer_.CreationError(); }
+
  private:
   ~FramebufferRenderTargetEGL() OVERRIDE {}
 
diff --git a/src/cobalt/renderer/backend/egl/graphics_context.cc b/src/cobalt/renderer/backend/egl/graphics_context.cc
index c5e6a4c..032f092 100644
--- a/src/cobalt/renderer/backend/egl/graphics_context.cc
+++ b/src/cobalt/renderer/backend/egl/graphics_context.cc
@@ -67,6 +67,7 @@
   // when we need to make OpenGL calls that do not depend on a surface (e.g.
   // creating a texture).
   null_surface_ = new PBufferRenderTargetEGL(display, config, math::Size(0, 0));
+  CHECK(!null_surface_->CreationError());
 
   ScopedMakeCurrent scoped_current_context(this);
 
@@ -364,7 +365,11 @@
   scoped_refptr<RenderTarget> render_target(new PBufferRenderTargetEGL(
       display_, config_, dimensions));
 
-  return render_target;
+  if (render_target->CreationError()) {
+    return scoped_refptr<RenderTarget>();
+  } else {
+    return render_target;
+  }
 }
 
 scoped_refptr<RenderTarget>
@@ -373,7 +378,11 @@
   scoped_refptr<RenderTarget> render_target(new FramebufferRenderTargetEGL(
       this, dimensions));
 
-  return render_target;
+  if (render_target->CreationError()) {
+    return scoped_refptr<RenderTarget>();
+  } else {
+    return render_target;
+  }
 }
 
 void GraphicsContextEGL::InitializeDebugContext() {
diff --git a/src/cobalt/renderer/backend/egl/graphics_system.cc b/src/cobalt/renderer/backend/egl/graphics_system.cc
index 4b317b0..0df35a7 100644
--- a/src/cobalt/renderer/backend/egl/graphics_system.cc
+++ b/src/cobalt/renderer/backend/egl/graphics_system.cc
@@ -151,11 +151,16 @@
 scoped_ptr<TextureDataEGL> GraphicsSystemEGL::AllocateTextureData(
     const math::Size& size, GLenum format) {
 #if defined(GLES3_SUPPORTED)
-  return scoped_ptr<TextureDataEGL>(
+  scoped_ptr<TextureDataEGL> texture_data(
       new TextureDataPBO(&(resource_context_.value()), size, format));
 #else
-  return scoped_ptr<TextureDataEGL>(new TextureDataCPU(size, format));
+  scoped_ptr<TextureDataEGL> texture_data(new TextureDataCPU(size, format));
 #endif
+  if (texture_data->CreationError()) {
+    return scoped_ptr<TextureDataEGL>();
+  } else {
+    return texture_data.Pass();
+  }
 }
 
 scoped_ptr<RawTextureMemoryEGL> GraphicsSystemEGL::AllocateRawTextureMemory(
diff --git a/src/cobalt/renderer/backend/egl/pbuffer_render_target.cc b/src/cobalt/renderer/backend/egl/pbuffer_render_target.cc
index 897968f..27549ba 100644
--- a/src/cobalt/renderer/backend/egl/pbuffer_render_target.cc
+++ b/src/cobalt/renderer/backend/egl/pbuffer_render_target.cc
@@ -44,7 +44,9 @@
 
   surface_ =
     eglCreatePbufferSurface(display_, config_, surface_attrib_list);
-  CHECK_EQ(EGL_SUCCESS, eglGetError());
+  if (eglGetError() != EGL_SUCCESS) {
+    surface_ = EGL_NO_SURFACE;
+  }
 }
 
 const math::Size& PBufferRenderTargetEGL::GetSize() const { return size_; }
@@ -54,7 +56,9 @@
 }
 
 PBufferRenderTargetEGL::~PBufferRenderTargetEGL() {
-  EGL_CALL(eglDestroySurface(display_, surface_));
+  if (surface_ != EGL_NO_SURFACE) {
+    EGL_CALL(eglDestroySurface(display_, surface_));
+  }
 }
 
 }  // namespace backend
diff --git a/src/cobalt/renderer/backend/egl/pbuffer_render_target.h b/src/cobalt/renderer/backend/egl/pbuffer_render_target.h
index 7ae3267..f8404cd 100644
--- a/src/cobalt/renderer/backend/egl/pbuffer_render_target.h
+++ b/src/cobalt/renderer/backend/egl/pbuffer_render_target.h
@@ -38,6 +38,8 @@
   EGLDisplay display() const { return display_; }
   EGLConfig config() const { return config_; }
 
+  bool CreationError() OVERRIDE { return surface_ == EGL_NO_SURFACE; }
+
  private:
   ~PBufferRenderTargetEGL() OVERRIDE;
 
diff --git a/src/cobalt/renderer/backend/egl/texture_data.h b/src/cobalt/renderer/backend/egl/texture_data.h
index 30b458b..0d2bf5e 100644
--- a/src/cobalt/renderer/backend/egl/texture_data.h
+++ b/src/cobalt/renderer/backend/egl/texture_data.h
@@ -47,6 +47,9 @@
   // Returns a pointer to the image data so that one can set pixel data as
   // necessary.
   virtual uint8_t* GetMemory() = 0;
+
+  // Returns true if there was an error during object construction.
+  virtual bool CreationError() = 0;
 };
 
 // Similar to TextureDataEGL::ConvertToTexture(), though this creates a texture
diff --git a/src/cobalt/renderer/backend/egl/texture_data_cpu.cc b/src/cobalt/renderer/backend/egl/texture_data_cpu.cc
index ec86c1c..0c93e08 100644
--- a/src/cobalt/renderer/backend/egl/texture_data_cpu.cc
+++ b/src/cobalt/renderer/backend/egl/texture_data_cpu.cc
@@ -46,8 +46,16 @@
 
   // Copy pixel data over from the user provided source data into the OpenGL
   // driver to be used as a texture from now on.
-  GL_CALL(glTexImage2D(GL_TEXTURE_2D, 0, format, size.width(), size.height(), 0,
-                       format, GL_UNSIGNED_BYTE, data));
+  glTexImage2D(GL_TEXTURE_2D, 0, format, size.width(), size.height(), 0, format,
+               GL_UNSIGNED_BYTE, data);
+  if (glGetError() != GL_NO_ERROR) {
+    LOG(ERROR) << "Error calling glTexImage2D(size = (" << size.width() << ", "
+               << size.height() << "))";
+    GL_CALL(glDeleteTextures(1, &texture_handle));
+    // 0 is considered by GL to be an invalid handle.
+    texture_handle = 0;
+  }
+
   GL_CALL(glBindTexture(GL_TEXTURE_2D, 0));
 
   return texture_handle;
@@ -64,11 +72,14 @@
   GLuint ret =
       UploadPixelDataToNewTexture(graphics_context, GetMemory(), size_, format_,
                                   GetPitchInBytes(), bgra_supported);
+  // Clear out our memory regardless of if the texture creation was successful.
   memory_.reset();
 
   return ret;
 }
 
+bool TextureDataCPU::CreationError() { return memory_.get() == NULL; }
+
 RawTextureMemoryCPU::RawTextureMemoryCPU(size_t size_in_bytes, size_t alignment)
     : size_in_bytes_(size_in_bytes) {
   memory_ = scoped_ptr_malloc<uint8_t, base::ScopedPtrAlignedFree>(
diff --git a/src/cobalt/renderer/backend/egl/texture_data_cpu.h b/src/cobalt/renderer/backend/egl/texture_data_cpu.h
index dd7990e..80d1669 100644
--- a/src/cobalt/renderer/backend/egl/texture_data_cpu.h
+++ b/src/cobalt/renderer/backend/egl/texture_data_cpu.h
@@ -42,6 +42,8 @@
   GLuint ConvertToTexture(GraphicsContextEGL* graphics_context,
                           bool bgra_supported);
 
+  bool CreationError() OVERRIDE;
+
  private:
   math::Size size_;
   GLenum format_;
diff --git a/src/cobalt/renderer/backend/egl/texture_data_pbo.cc b/src/cobalt/renderer/backend/egl/texture_data_pbo.cc
index 970bb86..d14bf55 100644
--- a/src/cobalt/renderer/backend/egl/texture_data_pbo.cc
+++ b/src/cobalt/renderer/backend/egl/texture_data_pbo.cc
@@ -29,7 +29,11 @@
 
 TextureDataPBO::TextureDataPBO(ResourceContext* resource_context,
                                const math::Size& size, GLenum format)
-    : resource_context_(resource_context), size_(size), format_(format) {
+    : resource_context_(resource_context),
+      size_(size),
+      format_(format),
+      mapped_data_(NULL),
+      error_(false) {
   data_size_ = static_cast<int64>(GetPitchInBytes()) * size_.height();
 
   resource_context_->RunSynchronouslyWithinResourceContext(
@@ -41,9 +45,22 @@
 
   // Use the resource context to allocate a GL pixel unpack buffer with the
   // specified size.
-  GL_CALL(glGenBuffers(1, &pixel_buffer_));
+  glGenBuffers(1, &pixel_buffer_);
+  if (glGetError() != GL_NO_ERROR) {
+    LOG(ERROR) << "Error creating new buffer.";
+    error_ = true;
+    return;
+  }
+
   GL_CALL(glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pixel_buffer_));
-  GL_CALL(glBufferData(GL_PIXEL_UNPACK_BUFFER, data_size_, 0, GL_STATIC_DRAW));
+  glBufferData(GL_PIXEL_UNPACK_BUFFER, data_size_, 0, GL_STATIC_DRAW);
+  if (glGetError() != GL_NO_ERROR) {
+    LOG(ERROR) << "Error allocating PBO data for image.";
+    error_ = true;
+    GL_CALL(glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0));
+    GL_CALL(glDeleteBuffers(1, &pixel_buffer_));
+    return;
+  }
 
   // Map the GL pixel buffer data to CPU addressable memory.  We pass the flags
   // MAP_INVALIDATE_BUFFER_BIT | MAP_UNSYNCHRONIZED_BIT to tell GL that it
@@ -55,8 +72,14 @@
       GL_PIXEL_UNPACK_BUFFER, 0, data_size_, GL_MAP_WRITE_BIT |
                                                  GL_MAP_INVALIDATE_BUFFER_BIT |
                                                  GL_MAP_UNSYNCHRONIZED_BIT));
-  CHECK(mapped_data_);
-  DCHECK_EQ(GL_NO_ERROR, glGetError());
+  if (glGetError() != GL_NO_ERROR || !mapped_data_) {
+    LOG(ERROR) << "Error mapping PBO buffer data.";
+    error_ = true;
+    GL_CALL(glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0));
+    GL_CALL(glDeleteBuffers(1, &pixel_buffer_));
+    return;
+  }
+
   GL_CALL(glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0));
 }
 
@@ -108,8 +131,16 @@
   // buffer.
   GL_CALL(glPixelStorei(GL_UNPACK_ROW_LENGTH,
                         GetPitchInBytes() / BytesPerPixelForGLFormat(format_)));
-  GL_CALL(glTexImage2D(GL_TEXTURE_2D, 0, format_, size_.width(), size_.height(),
-                       0, format_, GL_UNSIGNED_BYTE, 0));
+  glTexImage2D(GL_TEXTURE_2D, 0, format_, size_.width(), size_.height(), 0,
+               format_, GL_UNSIGNED_BYTE, 0);
+  if (glGetError() != GL_NO_ERROR) {
+    LOG(ERROR) << "Error calling glTexImage2D(size = (" << size_.width() << ", "
+               << size_.height() << "))";
+    GL_CALL(glDeleteTextures(1, &texture_handle));
+    // 0 is considered by GL to be an invalid handle.
+    texture_handle = 0;
+  }
+
   GL_CALL(glPixelStorei(GL_UNPACK_ROW_LENGTH, 0));
   GL_CALL(glBindTexture(GL_TEXTURE_2D, 0));
   GL_CALL(glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0));
@@ -122,6 +153,8 @@
   return texture_handle;
 }
 
+bool TextureDataPBO::CreationError() { return error_; }
+
 RawTextureMemoryPBO::RawTextureMemoryPBO(ResourceContext* resource_context,
                                          size_t size_in_bytes, size_t alignment)
     : size_in_bytes_(size_in_bytes),
diff --git a/src/cobalt/renderer/backend/egl/texture_data_pbo.h b/src/cobalt/renderer/backend/egl/texture_data_pbo.h
index 92ab5f4..857a8fa 100644
--- a/src/cobalt/renderer/backend/egl/texture_data_pbo.h
+++ b/src/cobalt/renderer/backend/egl/texture_data_pbo.h
@@ -51,6 +51,8 @@
   GLuint ConvertToTexture(GraphicsContextEGL* graphics_context,
                           bool bgra_supported);
 
+  bool CreationError() OVERRIDE;
+
  private:
   // Private methods that are intended to run only on the resource context
   // thread.
@@ -63,6 +65,7 @@
   GLuint pixel_buffer_;
   int64 data_size_;
   GLubyte* mapped_data_;
+  bool error_;
 };
 
 // Similar to TextureDataPBO, but this allows a bit more flexibility and less
diff --git a/src/cobalt/renderer/backend/render_target.h b/src/cobalt/renderer/backend/render_target.h
index 05786a6..9982f21 100644
--- a/src/cobalt/renderer/backend/render_target.h
+++ b/src/cobalt/renderer/backend/render_target.h
@@ -46,6 +46,10 @@
   // Each render is assigned a unique serial number on construction.
   int32_t GetSerialNumber() const { return serial_number_; }
 
+  // Returns true if there was an error constructing this object and it is
+  // therefore in an invalid state.
+  virtual bool CreationError() = 0;
+
  protected:
   // Concrete child classes should declare their destructors as private.
   friend class base::RefCountedThreadSafe<RenderTarget>;
diff --git a/src/cobalt/renderer/backend/render_target_stub.h b/src/cobalt/renderer/backend/render_target_stub.h
index 5a3d8c3..e793194 100644
--- a/src/cobalt/renderer/backend/render_target_stub.h
+++ b/src/cobalt/renderer/backend/render_target_stub.h
@@ -32,6 +32,8 @@
 
   intptr_t GetPlatformHandle() const OVERRIDE { return 0; }
 
+  bool CreationError() OVERRIDE { return false; }
+
  private:
   ~RenderTargetStub() {}
 
diff --git a/src/cobalt/renderer/copy_font_data.gypi b/src/cobalt/renderer/copy_font_data.gypi
index c2ee2d2..bc338ef 100644
--- a/src/cobalt/renderer/copy_font_data.gypi
+++ b/src/cobalt/renderer/copy_font_data.gypi
@@ -21,22 +21,9 @@
     'source_font_files_dir': '<(static_contents_source_dir)/fonts/font_files',
 
     'conditions': [
-      [ 'cobalt_font_package == "expanded"', {
-        'source_font_config_dir': '<(static_contents_source_dir)/fonts/config/common',
-
-        'package_named_sans_serif': 4,
-        'package_named_serif': 3,
-        'package_named_fcc_fonts': 2,
-        'package_fallback_lang_non_cjk': 2,
-        'package_fallback_lang_cjk': 2,
-        'package_fallback_lang_cjk_low_quality': 0,
-        'package_fallback_lang_jp': 0,
-        'package_fallback_emoji': 1,
-        'package_fallback_symbols': 1,
-      }],
-
       # 'unlimited' is deprecated but is mapped to 'standard'
-      [ 'cobalt_font_package == "standard" or cobalt_font_package == "unlimited"', {
+      # 'expanded' also currently maps to 'standard' but this may change in the future
+      [ 'cobalt_font_package == "standard" or cobalt_font_package == "unlimited" or cobalt_font_package == "expanded"', {
         'source_font_config_dir': '<(static_contents_source_dir)/fonts/config/common',
 
         'package_named_sans_serif': 4,
@@ -46,6 +33,7 @@
         'package_fallback_lang_cjk': 1,
         'package_fallback_lang_cjk_low_quality': 0,
         'package_fallback_lang_jp': 0,
+        'package_fallback_historic': 1,
         'package_fallback_emoji': 1,
         'package_fallback_symbols': 1,
       }],
@@ -61,6 +49,7 @@
         'package_fallback_lang_cjk': 0,
         'package_fallback_lang_cjk_low_quality': 1,
         'package_fallback_lang_jp': 1,
+        'package_fallback_historic': 0,
         'package_fallback_emoji': 1,
         'package_fallback_symbols': 1,
       }],
@@ -75,6 +64,7 @@
         'package_fallback_lang_cjk': 0,
         'package_fallback_lang_cjk_low_quality': 1,
         'package_fallback_lang_jp': 0,
+        'package_fallback_historic': 0,
         'package_fallback_emoji': 1,
         'package_fallback_symbols': 1,
       }],
@@ -89,6 +79,7 @@
         'package_fallback_lang_cjk': 0,
         'package_fallback_lang_cjk_low_quality': 0,
         'package_fallback_lang_jp': 0,
+        'package_fallback_historic': 0,
         'package_fallback_emoji': 0,
         'package_fallback_symbols': 0,
       }],
@@ -109,6 +100,7 @@
         'package_fallback_lang_cjk': 0,
         'package_fallback_lang_cjk_low_quality': 0,
         'package_fallback_lang_jp': 0,
+        'package_fallback_historic': 0,
         'package_fallback_emoji': 1,
         'package_fallback_symbols': 0,
       }],
@@ -134,6 +126,9 @@
       [ 'cobalt_font_package_override_fallback_lang_jp >= 0', {
         'package_fallback_lang_jp': '<(cobalt_font_package_override_fallback_lang_jp)',
       }],
+      [ 'cobalt_font_package_override_fallback_historic >= 0', {
+        'package_fallback_historic': '<(cobalt_font_package_override_fallback_historic)',
+      }],
       [ 'cobalt_font_package_override_fallback_emoji >= 0', {
         'package_fallback_emoji': '<(cobalt_font_package_override_fallback_emoji)',
       }],
@@ -221,6 +216,7 @@
         }],
         [ 'package_fallback_lang_non_cjk >= 1', {
           'files+': [
+            '<(source_font_files_dir)/NotoSansAdlam-Regular.ttf',
             '<(source_font_files_dir)/NotoNaskhArabicUI-Regular.ttf',
             '<(source_font_files_dir)/NotoSansArmenian-Regular.ttf',
             '<(source_font_files_dir)/NotoSansBalinese-Regular.ttf',
@@ -263,7 +259,10 @@
             '<(source_font_files_dir)/NotoSansSinhala-Regular.ttf',
             '<(source_font_files_dir)/NotoSansSundanese-Regular.ttf',
             '<(source_font_files_dir)/NotoSansSylotiNagri-Regular.ttf',
+            '<(source_font_files_dir)/NotoSansSyriacEastern-Regular.ttf',
             '<(source_font_files_dir)/NotoSansSyriacEstrangela-Regular.ttf',
+            '<(source_font_files_dir)/NotoSansSyriacWestern-Regular.ttf',
+            '<(source_font_files_dir)/NotoSansTagalog-Regular.ttf',
             '<(source_font_files_dir)/NotoSansTagbanwa-Regular.ttf',
             '<(source_font_files_dir)/NotoSansTaiLe-Regular.ttf',
             '<(source_font_files_dir)/NotoSansTaiTham-Regular.ttf',
@@ -309,11 +308,6 @@
             '<(source_font_files_dir)/NotoSansCJK-Regular.ttc',
           ],
         }],
-        [ 'package_fallback_lang_cjk >= 2', {
-          'files+': [
-            '<(source_font_files_dir)/NotoSansCJK-Bold.ttc',
-          ],
-        }],
         [ 'package_fallback_lang_cjk_low_quality >= 1', {
           'files+': [
             '<(source_font_files_dir)/DroidSansFallback.ttf',
@@ -324,6 +318,38 @@
             '<(source_font_files_dir)/NotoSansJP-Regular.otf',
           ],
         }],
+        [ 'package_fallback_historic >= 1', {
+          'files+': [
+            '<(source_font_files_dir)/NotoSansAvestan-Regular.ttf',
+            '<(source_font_files_dir)/NotoSansBrahmi-Regular.ttf',
+            '<(source_font_files_dir)/NotoSansCarian-Regular.ttf',
+            '<(source_font_files_dir)/NotoSansCuneiform-Regular.ttf',
+            '<(source_font_files_dir)/NotoSansCypriot-Regular.ttf',
+            '<(source_font_files_dir)/NotoSansDeseret-Regular.ttf',
+            '<(source_font_files_dir)/NotoSansEgyptianHieroglyphs-Regular.ttf',
+            '<(source_font_files_dir)/NotoSansGothic-Regular.ttf',
+            '<(source_font_files_dir)/NotoSansImperialAramaic-Regular.ttf',
+            '<(source_font_files_dir)/NotoSansInscriptionalPahlavi-Regular.ttf',
+            '<(source_font_files_dir)/NotoSansInscriptionalParthian-Regular.ttf',
+            '<(source_font_files_dir)/NotoSansKaithi-Regular.ttf',
+            '<(source_font_files_dir)/NotoSansKharoshthi-Regular.ttf',
+            '<(source_font_files_dir)/NotoSansLinearB-Regular.ttf',
+            '<(source_font_files_dir)/NotoSansLycian-Regular.ttf',
+            '<(source_font_files_dir)/NotoSansLydian-Regular.ttf',
+            '<(source_font_files_dir)/NotoSansOgham-Regular.ttf',
+            '<(source_font_files_dir)/NotoSansOldItalic-Regular.ttf',
+            '<(source_font_files_dir)/NotoSansOldPersian-Regular.ttf',
+            '<(source_font_files_dir)/NotoSansOldSouthArabian-Regular.ttf',
+            '<(source_font_files_dir)/NotoSansOldTurkic-Regular.ttf',
+            '<(source_font_files_dir)/NotoSansOsmanya-Regular.ttf',
+            '<(source_font_files_dir)/NotoSansPhagsPa-Regular.ttf',
+            '<(source_font_files_dir)/NotoSansPhoenician-Regular.ttf',
+            '<(source_font_files_dir)/NotoSansRunic-Regular.ttf',
+            '<(source_font_files_dir)/NotoSansSamaritan-Regular.ttf',
+            '<(source_font_files_dir)/NotoSansShavian-Regular.ttf',
+            '<(source_font_files_dir)/NotoSansUgaritic-Regular.ttf',
+          ],
+        }],
         [ 'package_fallback_emoji >= 1', {
           'files+': [
             '<(source_font_files_dir)/NotoEmoji-Regular.ttf',
diff --git a/src/cobalt/renderer/rasterizer/blitter/image.cc b/src/cobalt/renderer/rasterizer/blitter/image.cc
index 21a6b1c..177dc43 100644
--- a/src/cobalt/renderer/rasterizer/blitter/image.cc
+++ b/src/cobalt/renderer/rasterizer/blitter/image.cc
@@ -43,8 +43,7 @@
     descriptor_.emplace(size, pixel_format, alpha_format,
                         SbBlitterGetPixelDataPitchInBytes(pixel_data_));
   } else {
-    LOG(WARNING) << "Failed to allocate pixel data for image.";
-    DCHECK(false);
+    LOG(ERROR) << "Failed to allocate pixel data for image.";
   }
 }
 
diff --git a/src/cobalt/renderer/rasterizer/blitter/resource_provider.h b/src/cobalt/renderer/rasterizer/blitter/resource_provider.h
index 92315fe..64610a1 100644
--- a/src/cobalt/renderer/rasterizer/blitter/resource_provider.h
+++ b/src/cobalt/renderer/rasterizer/blitter/resource_provider.h
@@ -41,6 +41,10 @@
                    SubmitOffscreenCallback submit_offscreen_callback);
   ~ResourceProvider() OVERRIDE {}
 
+  base::TypeId GetTypeId() const OVERRIDE {
+    return base::GetTypeId<ResourceProvider>();
+  }
+
   void Finish() OVERRIDE {}
 
   scoped_refptr<render_tree::Image> CreateImageFromSbDecodeTarget(
diff --git a/src/cobalt/renderer/rasterizer/egl/draw_rect_radial_gradient.cc b/src/cobalt/renderer/rasterizer/egl/draw_rect_radial_gradient.cc
index eac8882..cf03c7b 100644
--- a/src/cobalt/renderer/rasterizer/egl/draw_rect_radial_gradient.cc
+++ b/src/cobalt/renderer/rasterizer/egl/draw_rect_radial_gradient.cc
@@ -68,12 +68,13 @@
   get_scratch_texture.Run(lookup_size, &texture_info);
   lookup_texture_ = texture_info.texture;
   lookup_region_ = texture_info.region;
-  if (texture_info.is_new) {
-    InitializeLookupTexture(brush);
-  }
 
   // Add the geometry if a lookup texture was available.
   if (lookup_texture_) {
+    if (texture_info.is_new) {
+      InitializeLookupTexture(brush);
+    }
+
     attributes_.reserve(kVertexCount);
     math::PointF offset_center(brush.center());
     math::PointF offset_scale(1.0f / std::max(brush.radius_x(), 0.001f),
diff --git a/src/cobalt/renderer/rasterizer/egl/offscreen_target_manager.cc b/src/cobalt/renderer/rasterizer/egl/offscreen_target_manager.cc
index b0babb2..9a648f8 100644
--- a/src/cobalt/renderer/rasterizer/egl/offscreen_target_manager.cc
+++ b/src/cobalt/renderer/rasterizer/egl/offscreen_target_manager.cc
@@ -350,8 +350,15 @@
     }
   }
 
-  if (atlas == nullptr) {
-    atlas = CreateOffscreenAtlas(target_size, true);
+  if (!atlas) {
+    atlas = CreateOffscreenAtlas(target_size, true).release();
+    if (!atlas) {
+      // If there was an error allocating the offscreen atlas, indicate by
+      // marking framebuffer and skia canvas as null and returning early.
+      out_target_info->framebuffer = nullptr;
+      out_target_info->skia_canvas = nullptr;
+      return;
+    }
     uncached_targets_.push_back(atlas);
   }
 
@@ -420,9 +427,12 @@
     DLOG(WARNING) << "More memory was allotted for offscreen render targets"
                   << " than will be used.";
   }
-  offscreen_cache_.reset(CreateOffscreenAtlas(atlas_size, true));
+  offscreen_cache_ = CreateOffscreenAtlas(atlas_size, true);
+  CHECK(offscreen_cache_);
   for (int i = 1; i < num_atlases; ++i) {
-    offscreen_atlases_.push_back(CreateOffscreenAtlas(atlas_size, true));
+    offscreen_atlases_.push_back(
+        CreateOffscreenAtlas(atlas_size, true).release());
+    CHECK(offscreen_atlases_.back());
   }
 
   DLOG(INFO) << "Created " << num_atlases << " offscreen atlases of size "
@@ -435,28 +445,34 @@
       std::min(std::min(16, frame_size.width()), frame_size.height());
   math::Size atlas_size_1d(
       std::max(frame_size.width(), frame_size.height()), kAtlasHeight1D);
-  offscreen_atlases_1d_.push_back(CreateOffscreenAtlas(atlas_size_1d, false));
-  offscreen_cache_1d_.reset(CreateOffscreenAtlas(atlas_size_1d, false));
+  offscreen_atlases_1d_.push_back(
+      CreateOffscreenAtlas(atlas_size_1d, false).release());
+  CHECK(offscreen_atlases_1d_.back());
+  offscreen_cache_1d_ = CreateOffscreenAtlas(atlas_size_1d, false);
+  CHECK(offscreen_cache_1d_);
   DLOG(INFO) << "Created " << offscreen_atlases_1d_.size() + 1
              << " offscreen atlases of size " << atlas_size_1d.width() << " x "
              << atlas_size_1d.height();
 }
 
-OffscreenTargetManager::OffscreenAtlas*
-    OffscreenTargetManager::CreateOffscreenAtlas(const math::Size& size,
-        bool create_canvas) {
-  OffscreenAtlas* atlas = new OffscreenAtlas(size);
+scoped_ptr<OffscreenTargetManager::OffscreenAtlas>
+OffscreenTargetManager::CreateOffscreenAtlas(const math::Size& size,
+                                             bool create_canvas) {
+  scoped_ptr<OffscreenAtlas> atlas(new OffscreenAtlas(size));
 
   // Create a new framebuffer.
   atlas->framebuffer = new backend::FramebufferRenderTargetEGL(
       graphics_context_, size);
+  if (atlas->framebuffer->CreationError()) {
+    return scoped_ptr<OffscreenAtlas>();
+  }
 
   if (create_canvas) {
     // Wrap the framebuffer as a skia surface.
     atlas->skia_surface.reset(create_fallback_surface_.Run(atlas->framebuffer));
   }
 
-  return atlas;
+  return atlas.Pass();
 }
 
 }  // namespace egl
diff --git a/src/cobalt/renderer/rasterizer/egl/offscreen_target_manager.h b/src/cobalt/renderer/rasterizer/egl/offscreen_target_manager.h
index 2c56347..90727df 100644
--- a/src/cobalt/renderer/rasterizer/egl/offscreen_target_manager.h
+++ b/src/cobalt/renderer/rasterizer/egl/offscreen_target_manager.h
@@ -88,7 +88,8 @@
       float size, const ErrorData1D& error_data, TargetInfo* out_target_info);
 
   // Allocate an uncached render target. The contents of the target cannot be
-  // reused in subsequent frames.
+  // reused in subsequent frames.  If there was an error allocating the
+  // render target, out_target_info->framebuffer will be set to nullptr.
   void AllocateUncachedTarget(const math::SizeF& size,
       TargetInfo* out_target_info);
 
@@ -97,8 +98,8 @@
   struct OffscreenAtlas;
 
   void InitializeTargets(const math::Size& frame_size);
-  OffscreenAtlas* CreateOffscreenAtlas(const math::Size& size,
-      bool create_canvas);
+  scoped_ptr<OffscreenAtlas> CreateOffscreenAtlas(const math::Size& size,
+                                                  bool create_canvas);
   void SelectAtlasCache(ScopedVector<OffscreenAtlas>* atlases,
       scoped_ptr<OffscreenAtlas>* cache);
 
diff --git a/src/cobalt/renderer/rasterizer/egl/render_tree_node_visitor.cc b/src/cobalt/renderer/rasterizer/egl/render_tree_node_visitor.cc
index 52fd64e..53a9a8c 100644
--- a/src/cobalt/renderer/rasterizer/egl/render_tree_node_visitor.cc
+++ b/src/cobalt/renderer/rasterizer/egl/render_tree_node_visitor.cc
@@ -808,6 +808,12 @@
   target_size.SetToMin(onscreen_render_target_->GetSize());
   offscreen_target_manager_->AllocateUncachedTarget(target_size, &target_info);
 
+  if (!target_info.framebuffer) {
+    LOG(ERROR) << "Could not allocate framebuffer for offscreen rasterization.";
+    out_content_rect->SetRect(0.0f, 0.0f, 0.0f, 0.0f);
+    return;
+  }
+
   // Only the clipped bounds will be rendered.
   DCHECK_GE(target_info.region.width(), clipped_bounds.width());
   DCHECK_GE(target_info.region.height(), clipped_bounds.height());
diff --git a/src/cobalt/renderer/rasterizer/egl/software_rasterizer.cc b/src/cobalt/renderer/rasterizer/egl/software_rasterizer.cc
index c567846..08bc48a 100644
--- a/src/cobalt/renderer/rasterizer/egl/software_rasterizer.cc
+++ b/src/cobalt/renderer/rasterizer/egl/software_rasterizer.cc
@@ -66,6 +66,7 @@
       context_->system_egl()->AllocateTextureData(
           math::Size(output_image_info.width(), output_image_info.height()),
           gl_format);
+  CHECK(bitmap_pixels);
 
   SkBitmap bitmap;
   bitmap.installPixels(output_image_info, bitmap_pixels->GetMemory(),
diff --git a/src/cobalt/renderer/rasterizer/pixel_test.cc b/src/cobalt/renderer/rasterizer/pixel_test.cc
index d96d361..1125905 100644
--- a/src/cobalt/renderer/rasterizer/pixel_test.cc
+++ b/src/cobalt/renderer/rasterizer/pixel_test.cc
@@ -187,6 +187,18 @@
                         rounded_corners.Pass()));
 }
 
+// These particular rounded corner values were found to cause a crash problem
+// with some rasterizers, this test is added to prevent a regression.
+TEST_F(PixelTest, AlmostCircleViaRoundedCorners) {
+  RoundedCorner rounded_corner(11.9999504f, 11.9999504f);
+  scoped_ptr<RoundedCorners> rounded_corners(
+      new RoundedCorners(rounded_corner));
+  TestTree(new RectNode(
+      RectF(24, 24),
+      scoped_ptr<Brush>(new SolidColorBrush(ColorRGBA(1.0, 1.0, 0.0, 1.0))),
+      rounded_corners.Pass()));
+}
+
 TEST_F(PixelTest, OvalViaRoundedCorners) {
   RoundedCorner top_left(50, 25);
   RoundedCorner top_right(50, 25);
diff --git a/src/cobalt/renderer/rasterizer/skia/hardware_image.cc b/src/cobalt/renderer/rasterizer/skia/hardware_image.cc
index 51a0f84..95a2ac4 100644
--- a/src/cobalt/renderer/rasterizer/skia/hardware_image.cc
+++ b/src/cobalt/renderer/rasterizer/skia/hardware_image.cc
@@ -185,6 +185,7 @@
 
     scoped_refptr<backend::FramebufferRenderTargetEGL> render_target(
         new backend::FramebufferRenderTargetEGL(cobalt_context, size));
+    CHECK(!render_target->CreationError());
 
     // The above call to FramebufferRenderTargetEGL() may have dirtied graphics
     // state, so tell Skia to reset its context.
diff --git a/src/cobalt/renderer/rasterizer/skia/hardware_resource_provider.cc b/src/cobalt/renderer/rasterizer/skia/hardware_resource_provider.cc
index 6581495..8286242 100644
--- a/src/cobalt/renderer/rasterizer/skia/hardware_resource_provider.cc
+++ b/src/cobalt/renderer/rasterizer/skia/hardware_resource_provider.cc
@@ -111,18 +111,28 @@
   DCHECK(AlphaFormatSupported(alpha_format));
 
   if (size.width() > max_texture_size_ || size.height() > max_texture_size_) {
+    LOG(ERROR) << "Could not allocate image data because one of its dimensions "
+               << "(" << size.width() << ", " << size.height() << ") "
+               << "exceeds the maximum texture width (" << max_texture_size_
+               << ")";
     return scoped_ptr<ImageData>(nullptr);
   }
 
-  return scoped_ptr<ImageData>(new HardwareImageData(
+  scoped_ptr<backend::TextureDataEGL> texture_data(
       cobalt_context_->system_egl()->AllocateTextureData(
-          size, ConvertRenderTreeFormatToGL(pixel_format)),
-      pixel_format, alpha_format));
+          size, ConvertRenderTreeFormatToGL(pixel_format)));
+  if (texture_data) {
+    return scoped_ptr<ImageData>(
+        new HardwareImageData(texture_data.Pass(), pixel_format, alpha_format));
+  } else {
+    return scoped_ptr<ImageData>();
+  }
 }
 
 scoped_refptr<render_tree::Image> HardwareResourceProvider::CreateImage(
     scoped_ptr<ImageData> source_data) {
   TRACE_EVENT0("cobalt::renderer", "HardwareResourceProvider::CreateImage()");
+  DCHECK(source_data);
   scoped_ptr<HardwareImageData> skia_hardware_source_data(
       base::polymorphic_downcast<HardwareImageData*>(source_data.release()));
   const render_tree::ImageDataDescriptor& descriptor =
@@ -131,9 +141,11 @@
   DCHECK(descriptor.alpha_format == render_tree::kAlphaFormatPremultiplied ||
          descriptor.alpha_format == render_tree::kAlphaFormatOpaque);
 #if defined(COBALT_BUILD_TYPE_DEBUG)
-  Image::DCheckForPremultipliedAlpha(descriptor.size, descriptor.pitch_in_bytes,
-                                     descriptor.pixel_format,
-                                     skia_hardware_source_data->GetMemory());
+  if (descriptor.alpha_format == render_tree::kAlphaFormatPremultiplied) {
+    Image::DCheckForPremultipliedAlpha(
+        descriptor.size, descriptor.pitch_in_bytes, descriptor.pixel_format,
+        skia_hardware_source_data->GetMemory());
+  }
 #endif
 
   // Construct a frontend image from this data, which internally will send
diff --git a/src/cobalt/renderer/rasterizer/skia/hardware_resource_provider.h b/src/cobalt/renderer/rasterizer/skia/hardware_resource_provider.h
index 5ad0c4a..c13eaa6 100644
--- a/src/cobalt/renderer/rasterizer/skia/hardware_resource_provider.h
+++ b/src/cobalt/renderer/rasterizer/skia/hardware_resource_provider.h
@@ -43,6 +43,10 @@
                            bool purge_skia_font_caches_on_destruction);
   ~HardwareResourceProvider() OVERRIDE;
 
+  base::TypeId GetTypeId() const OVERRIDE {
+    return base::GetTypeId<HardwareResourceProvider>();
+  }
+
   void Finish() OVERRIDE;
 
   bool PixelFormatSupported(render_tree::PixelFormat pixel_format) OVERRIDE;
diff --git a/src/cobalt/renderer/rasterizer/skia/software_resource_provider.h b/src/cobalt/renderer/rasterizer/skia/software_resource_provider.h
index 492d3ab..c05abb5 100644
--- a/src/cobalt/renderer/rasterizer/skia/software_resource_provider.h
+++ b/src/cobalt/renderer/rasterizer/skia/software_resource_provider.h
@@ -34,6 +34,10 @@
   explicit SoftwareResourceProvider(bool purge_skia_font_caches_on_destruction);
   ~SoftwareResourceProvider() OVERRIDE;
 
+  base::TypeId GetTypeId() const OVERRIDE {
+    return base::GetTypeId<SoftwareResourceProvider>();
+  }
+
   void Finish() OVERRIDE{};
 
   bool PixelFormatSupported(render_tree::PixelFormat pixel_format) OVERRIDE;
diff --git a/src/cobalt/renderer/rasterizer/stress_test.cc b/src/cobalt/renderer/rasterizer/stress_test.cc
new file mode 100644
index 0000000..6badad2
--- /dev/null
+++ b/src/cobalt/renderer/rasterizer/stress_test.cc
@@ -0,0 +1,162 @@
+// Copyright 2017 Google Inc. All Rights Reserved.
+//
+// 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.
+
+#include "cobalt/render_tree/brush.h"
+#include "cobalt/render_tree/composition_node.h"
+#include "cobalt/render_tree/filter_node.h"
+#include "cobalt/render_tree/rect_node.h"
+#include "cobalt/renderer/backend/default_graphics_system.h"
+#include "cobalt/renderer/backend/graphics_context.h"
+#include "cobalt/renderer/backend/graphics_system.h"
+#include "cobalt/renderer/backend/render_target.h"
+#include "cobalt/renderer/rasterizer/rasterizer.h"
+#include "cobalt/renderer/renderer_module.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using cobalt::math::RectF;
+using cobalt::math::Size;
+using cobalt::math::SizeF;
+using cobalt::math::Vector2dF;
+using cobalt::render_tree::Brush;
+using cobalt::render_tree::ColorRGBA;
+using cobalt::render_tree::CompositionNode;
+using cobalt::render_tree::FilterNode;
+using cobalt::render_tree::Node;
+using cobalt::render_tree::OpacityFilter;
+using cobalt::render_tree::RectNode;
+using cobalt::render_tree::SolidColorBrush;
+
+namespace cobalt {
+namespace renderer {
+namespace rasterizer {
+
+// The renderer stress tests are intended to simply ensure that no crash occurs.
+// They usually create a lot of a certain object type, or attempt to use very
+// large surfaces.  The final output doesn't really matter, and it is not
+// checked, we just don't want to crash.  For example, some of the tests
+// ensure that we don't crash when we request a rasterization that requires
+// very large framebuffers that the rasterizer is not likely to be able to
+// allocate.
+class StressTest : public testing::Test {
+ public:
+  StressTest();
+
+  void TestTree(const Size& output_size, scoped_refptr<Node> tree);
+
+ protected:
+  scoped_ptr<backend::GraphicsSystem> graphics_system_;
+  scoped_ptr<backend::GraphicsContext> graphics_context_;
+  scoped_ptr<rasterizer::Rasterizer> rasterizer_;
+};
+
+StressTest::StressTest() {
+  graphics_system_ = backend::CreateDefaultGraphicsSystem();
+  graphics_context_ = graphics_system_->CreateGraphicsContext();
+  // Create the rasterizer using the platform default RenderModule options.
+  RendererModule::Options render_module_options;
+  rasterizer_ = render_module_options.create_rasterizer_function.Run(
+      graphics_context_.get(), render_module_options);
+}
+
+void StressTest::TestTree(const Size& output_size, scoped_refptr<Node> tree) {
+  scoped_refptr<cobalt::renderer::backend::RenderTarget> test_surface =
+      graphics_context_->CreateDownloadableOffscreenRenderTarget(output_size);
+
+  if (!test_surface) {
+    LOG(WARNING)
+        << "Failed to create render target, no rasterization will take place.";
+  } else {
+    rasterizer::Rasterizer::Options rasterizer_options;
+    rasterizer_options.flags = rasterizer::Rasterizer::kSubmitFlags_Clear;
+    rasterizer_->Submit(tree, test_surface, rasterizer_options);
+  }
+}
+
+// Test that we can create a large framebuffer, but not so large that it
+// will fail on all platforms.
+TEST_F(StressTest, LargeFramebuffer) {
+  Size kLargeFramebufferSize(8000, 8000);
+  TestTree(kLargeFramebufferSize,
+           new RectNode(RectF(kLargeFramebufferSize),
+                        scoped_ptr<Brush>(new SolidColorBrush(
+                            ColorRGBA(1.0f, 0.0f, 0.0f, 1.0f)))));
+}
+
+// Test that we can create a very large framebuffer that may fail to create
+// on most platforms.
+TEST_F(StressTest, VeryLargeFramebuffer) {
+  Size kLargeFramebufferSize(20000, 20000);
+  TestTree(kLargeFramebufferSize,
+           new RectNode(RectF(kLargeFramebufferSize),
+                        scoped_ptr<Brush>(new SolidColorBrush(
+                            ColorRGBA(1.0f, 0.0f, 0.0f, 1.0f)))));
+}
+
+namespace {
+// Creates a composition of |cascade_amount| render trees layed out in a
+// cascade on top of each other.
+scoped_refptr<Node> CreateCascadedRenderTrees(Node* node, int cascade_amount,
+                                              float offset_amount) {
+  CompositionNode::Builder composition_builder;
+  for (int i = 0; i < cascade_amount; ++i) {
+    composition_builder.AddChild(new CompositionNode(
+        node, Vector2dF(i * offset_amount, i * offset_amount)));
+  }
+
+  return new CompositionNode(composition_builder.Pass());
+}
+
+// Creates and returns a render tree with |num_layers| opacity objects overlaid
+// on top of themselves, each with the specified size.  Each opacity layer
+// contains a set of 3 rectangles, with an opacity filter applied on top of
+// all 3 of them.
+scoped_refptr<Node> CreateOpacityLayers(int num_layers, const Size& size) {
+  const float kCascadeOffset = 25.0f;
+  const int kNumCascadedRects = 3;
+  int rect_size_inset = (kNumCascadedRects - 1) * kCascadeOffset;
+  Size rect_size(size.width() - rect_size_inset,
+                 size.height() - rect_size_inset);
+
+  FilterNode* opacity_layer =
+      new FilterNode(OpacityFilter(0.9f),
+                     CreateCascadedRenderTrees(
+                         new RectNode(RectF(rect_size),
+                                      scoped_ptr<Brush>(new SolidColorBrush(
+                                          ColorRGBA(1.0f, 0.0f, 0.0f, 1.0f)))),
+                         kNumCascadedRects, kCascadeOffset));
+
+  return CreateCascadedRenderTrees(opacity_layer, num_layers, 0.0f);
+}
+}  // namespace
+
+// Test that we can create many (8^3) medium-sized opacity layers (which, in
+// most rasterizers, imply the creation of offscreen surfaces).
+TEST_F(StressTest, ManyOpacityLayers) {
+  Size kFramebufferSize(1920, 1080);
+  TestTree(kFramebufferSize, CreateOpacityLayers(250, Size(200, 200)));
+}
+
+TEST_F(StressTest, FewLargeOpacityLayers) {
+  Size kFramebufferSize(1920, 1080);
+  TestTree(kFramebufferSize, CreateOpacityLayers(50, kFramebufferSize));
+}
+
+TEST_F(StressTest, FewVeryLargeOpacityLayers) {
+  Size kFramebufferSize(1920, 1080);
+  TestTree(kFramebufferSize, CreateOpacityLayers(50, Size(9000, 9000)));
+}
+
+}  // namespace rasterizer
+}  // namespace renderer
+}  // namespace cobalt
diff --git a/src/cobalt/renderer/rasterizer/testdata/AlmostCircleViaRoundedCorners-expected.png b/src/cobalt/renderer/rasterizer/testdata/AlmostCircleViaRoundedCorners-expected.png
new file mode 100644
index 0000000..236616a
--- /dev/null
+++ b/src/cobalt/renderer/rasterizer/testdata/AlmostCircleViaRoundedCorners-expected.png
Binary files differ
diff --git a/src/cobalt/renderer/renderer.gyp b/src/cobalt/renderer/renderer.gyp
index 2b27c3e..ae1e134 100644
--- a/src/cobalt/renderer/renderer.gyp
+++ b/src/cobalt/renderer/renderer.gyp
@@ -87,6 +87,7 @@
         'rasterizer/pixel_test.cc',
         'rasterizer/pixel_test_fixture.cc',
         'rasterizer/pixel_test_fixture.h',
+        'rasterizer/stress_test.cc',
         'resource_provider_test.cc',
         'smoothed_value_test.cc',
         'submission_queue_test.cc',
diff --git a/src/cobalt/renderer/resource_provider_test.cc b/src/cobalt/renderer/resource_provider_test.cc
index 57e1735..48b559a 100644
--- a/src/cobalt/renderer/resource_provider_test.cc
+++ b/src/cobalt/renderer/resource_provider_test.cc
@@ -129,6 +129,43 @@
 };
 }  // namespace
 
+class ResourceProviderTest : public testing::Test {
+ public:
+  ResourceProviderTest();
+  ~ResourceProviderTest();
+
+  // Lets the fixture know that it will run the run loop manually, and the
+  // ResourceProviderTest destructor does not need to run it.
+  void SetWillRunRunLoopManually() { run_run_loop_manually_ = true; }
+
+ protected:
+  MessageLoop message_loop_;
+  base::RunLoop run_loop_;
+  scoped_ptr<backend::GraphicsSystem> graphics_system_;
+  scoped_ptr<backend::GraphicsContext> graphics_context_;
+  scoped_ptr<rasterizer::Rasterizer> rasterizer_;
+
+  bool run_run_loop_manually_;
+};
+
+ResourceProviderTest::ResourceProviderTest()
+    : message_loop_(MessageLoop::TYPE_DEFAULT), run_run_loop_manually_(false) {
+  graphics_system_ = backend::CreateDefaultGraphicsSystem();
+  graphics_context_ = graphics_system_->CreateGraphicsContext();
+
+  // Create the rasterizer using the platform default RenderModule options.
+  RendererModule::Options render_module_options;
+  rasterizer_ = render_module_options.create_rasterizer_function.Run(
+      graphics_context_.get(), render_module_options);
+}
+
+ResourceProviderTest::~ResourceProviderTest() {
+  if (!run_run_loop_manually_) {
+    message_loop_.PostTask(FROM_HERE, run_loop_.QuitClosure());
+    run_loop_.Run();
+  }
+}
+
 // The following test ensures that any thread can successfully create render
 // tree images both at the same time and also while a graphics frame is started.
 // This might be a problem in an OpenGL implementation for instance if we
@@ -137,29 +174,14 @@
 // be upset that it was taken away.  This test is essentially attempting to
 // cause a crash or DCHECK() to be hit, if the test executes without crashing,
 // everything is okay.
-TEST(ResourceProviderTest, TexturesCanBeCreatedFromSecondaryThread) {
-  scoped_ptr<backend::GraphicsSystem> graphics_system =
-      backend::CreateDefaultGraphicsSystem();
-  scoped_ptr<backend::GraphicsContext> graphics_context =
-      graphics_system->CreateGraphicsContext();
-
-  // When creating images from another thread, the rasterizer must be
-  // constructed from a thread with a message loop.  This message loop will
-  // be where all functions that access backend graphics resources are run.
-  MessageLoop message_loop(MessageLoop::TYPE_DEFAULT);
-  base::RunLoop run_loop;
-
-  // Create the rasterizer using the platform default RenderModule options.
-  RendererModule::Options render_module_options;
-  scoped_ptr<rasterizer::Rasterizer> rasterizer =
-      render_module_options.create_rasterizer_function.Run(
-          graphics_context.get(), render_module_options);
+TEST_F(ResourceProviderTest, TexturesCanBeCreatedFromSecondaryThread) {
+  SetWillRunRunLoopManually();
 
   // Create a dummy offscreen surface so that we can have a target when we start
   // a frame with the graphics context.
   const math::Size kDummySurfaceDimensions(1, 1);
   scoped_refptr<backend::RenderTarget> dummy_output_surface =
-      graphics_context->CreateOffscreenRenderTarget(kDummySurfaceDimensions);
+      graphics_context_->CreateOffscreenRenderTarget(kDummySurfaceDimensions);
 
   // Now that we're inside of a new frame, create images from a separate
   // thread.  This should be perfectly legal and cause no problems.
@@ -168,15 +190,15 @@
 
   // Create a thread to create other threads that will create images.
   CreateImagesSpawnerThread spawner_thread(
-      rasterizer->GetResourceProvider(), kNumThreads,
+      rasterizer_->GetResourceProvider(), kNumThreads,
       kNumImagesCreatedPerThread, math::Size(1, 1),
-      base::Bind(&MessageLoop::PostTask, base::Unretained(&message_loop),
-                 FROM_HERE, run_loop.QuitClosure()));
+      base::Bind(&MessageLoop::PostTask, base::Unretained(&message_loop_),
+                 FROM_HERE, run_loop_.QuitClosure()));
   spawner_thread.Start();
 
   // Run our message loop to process backend image creation/destruction
   // requests.
-  run_loop.Run();
+  run_loop_.Run();
 
   spawner_thread.Join();
 }
@@ -190,29 +212,14 @@
 // release them and then expect that it can allocate N more, but if those
 // released frames have a delay on their release, we may have many more than
 // N textures allocated at a time.
-TEST(ResourceProviderTest, ManyTexturesCanBeCreatedAndDestroyedQuickly) {
-  scoped_ptr<backend::GraphicsSystem> graphics_system =
-      backend::CreateDefaultGraphicsSystem();
-  scoped_ptr<backend::GraphicsContext> graphics_context =
-      graphics_system->CreateGraphicsContext();
-
-  // When creating images from another thread, the rasterizer must be
-  // constructed from a thread with a message loop.  This message loop will
-  // be where all functions that access backend graphics resources are run.
-  MessageLoop message_loop(MessageLoop::TYPE_DEFAULT);
-  base::RunLoop run_loop;
-
-  // Create the rasterizer using the platform default RenderModule options.
-  RendererModule::Options render_module_options;
-  scoped_ptr<rasterizer::Rasterizer> rasterizer =
-      render_module_options.create_rasterizer_function.Run(
-          graphics_context.get(), render_module_options);
+TEST_F(ResourceProviderTest, ManyTexturesCanBeCreatedAndDestroyedQuickly) {
+  SetWillRunRunLoopManually();
 
   // Create a dummy offscreen surface so that we can have a target when we start
   // a frame with the graphics context.
   const math::Size kDummySurfaceDimensions(1, 1);
   scoped_refptr<backend::RenderTarget> dummy_output_surface =
-      graphics_context->CreateOffscreenRenderTarget(kDummySurfaceDimensions);
+      graphics_context_->CreateOffscreenRenderTarget(kDummySurfaceDimensions);
 
   // Now that we're inside of a new frame, create images from a separate
   // thread.  This should be perfectly legal and cause no problems.
@@ -221,18 +228,85 @@
 
   // Create a thread to create other threads that will create images.
   CreateImagesSpawnerThread spawner_thread(
-      rasterizer->GetResourceProvider(), kNumThreads,
+      rasterizer_->GetResourceProvider(), kNumThreads,
       kNumImagesCreatedPerThread, math::Size(256, 256),
-      base::Bind(&MessageLoop::PostTask, base::Unretained(&message_loop),
-                 FROM_HERE, run_loop.QuitClosure()));
+      base::Bind(&MessageLoop::PostTask, base::Unretained(&message_loop_),
+                 FROM_HERE, run_loop_.QuitClosure()));
   spawner_thread.Start();
 
   // Run our message loop to process backend image creation/destruction
   // requests.
-  run_loop.Run();
+  run_loop_.Run();
 
   spawner_thread.Join();
 }
 
+// Test that we won't crash even if we attempt to create a very large number
+// of textures.
+TEST_F(ResourceProviderTest, NoCrashWhenManyTexturesAreAllocated) {
+  render_tree::ResourceProvider* resource_provider =
+      rasterizer_->GetResourceProvider();
+
+  const int kNumImages = 5000;
+  const math::Size kImageSize = math::Size(32, 32);
+
+  scoped_ptr<render_tree::ImageData> image_datas[kNumImages];
+  scoped_refptr<render_tree::Image> images[kNumImages];
+
+  for (int i = 0; i < kNumImages; ++i) {
+    image_datas[i] = resource_provider->AllocateImageData(
+        kImageSize, ChoosePixelFormat(resource_provider),
+        render_tree::kAlphaFormatOpaque);
+  }
+
+  for (int i = 0; i < kNumImages; ++i) {
+    if (image_datas[i]) {
+      images[i] = resource_provider->CreateImage(image_datas[i].Pass());
+    }
+  }
+
+  for (int i = 0; i < kNumImages; ++i) {
+    images[i] = NULL;
+  }
+}
+
+// Test that we can attempt to allocate one massive image without crashing.
+// There will likely be an out-of-memory issue when attempting to create the
+// image.
+TEST_F(ResourceProviderTest, NoCrashWhenMassiveTextureIsAllocated) {
+  render_tree::ResourceProvider* resource_provider =
+      rasterizer_->GetResourceProvider();
+
+  const math::Size kImageSize = math::Size(16384, 16384);
+
+  scoped_ptr<render_tree::ImageData> image_data =
+      resource_provider->AllocateImageData(kImageSize,
+                                           ChoosePixelFormat(resource_provider),
+                                           render_tree::kAlphaFormatOpaque);
+  if (image_data) {
+    scoped_refptr<render_tree::Image> image =
+        resource_provider->CreateImage(image_data.Pass());
+  }
+}
+
+// This test is likely not to fail for any out-of-memory reasons, but rather
+// maximum texture size reasons.
+TEST_F(ResourceProviderTest,
+       NoCrashWhenTextureWithOneLargeDimensionIsAllocated) {
+  render_tree::ResourceProvider* resource_provider =
+      rasterizer_->GetResourceProvider();
+
+  const math::Size kImageSize = math::Size(1024 * 1024, 32);
+
+  scoped_ptr<render_tree::ImageData> image_data =
+      resource_provider->AllocateImageData(kImageSize,
+                                           ChoosePixelFormat(resource_provider),
+                                           render_tree::kAlphaFormatOpaque);
+  if (image_data) {
+    scoped_refptr<render_tree::Image> image =
+        resource_provider->CreateImage(image_data.Pass());
+  }
+}
+
 }  // namespace renderer
 }  // namespace cobalt
diff --git a/src/cobalt/script/call_frame.h b/src/cobalt/script/call_frame.h
index 17cdd28..a424dab 100644
--- a/src/cobalt/script/call_frame.h
+++ b/src/cobalt/script/call_frame.h
@@ -11,6 +11,7 @@
 // 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.
+
 #ifndef COBALT_SCRIPT_CALL_FRAME_H_
 #define COBALT_SCRIPT_CALL_FRAME_H_
 
@@ -18,8 +19,8 @@
 
 #include "base/memory/scoped_ptr.h"
 #include "base/optional.h"
-#include "cobalt/script/opaque_handle.h"
 #include "cobalt/script/scope.h"
+#include "cobalt/script/value_handle.h"
 
 namespace cobalt {
 namespace script {
@@ -64,7 +65,7 @@
 
   // An opaque handle to the current JavaScript |this| object.
   // May be NULL if the value of |this| in the call frame is not an object.
-  virtual const OpaqueHandleHolder* GetThis() = 0;
+  virtual const ValueHandleHolder* GetThis() = 0;
 };
 
 }  // namespace script
diff --git a/src/cobalt/script/callback_function.h.pump b/src/cobalt/script/callback_function.h.pump
index d4de8cf..353656a 100644
--- a/src/cobalt/script/callback_function.h.pump
+++ b/src/cobalt/script/callback_function.h.pump
@@ -21,8 +21,8 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-#ifndef SCRIPT_CALLBACK_FUNCTION_H_
-#define SCRIPT_CALLBACK_FUNCTION_H_
+#ifndef COBALT_SCRIPT_CALLBACK_FUNCTION_H_
+#define COBALT_SCRIPT_CALLBACK_FUNCTION_H_
 
 #include "base/callback.h"
 #include "base/callback_internal.h"
@@ -91,4 +91,4 @@
 }  // namespace script
 }  // namespace cobalt
 
-#endif  // SCRIPT_CALLBACK_FUNCTION_H_
+#endif  // COBALT_SCRIPT_CALLBACK_FUNCTION_H_
diff --git a/src/cobalt/script/environment_settings.h b/src/cobalt/script/environment_settings.h
index 2d3b7da..6a96266 100644
--- a/src/cobalt/script/environment_settings.h
+++ b/src/cobalt/script/environment_settings.h
@@ -11,6 +11,7 @@
 // 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.
+
 #ifndef COBALT_SCRIPT_ENVIRONMENT_SETTINGS_H_
 #define COBALT_SCRIPT_ENVIRONMENT_SETTINGS_H_
 
diff --git a/src/cobalt/script/exception_message.h b/src/cobalt/script/exception_message.h
index 8bdafe1..40dfa03 100644
--- a/src/cobalt/script/exception_message.h
+++ b/src/cobalt/script/exception_message.h
@@ -11,6 +11,7 @@
 // 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.
+
 #ifndef COBALT_SCRIPT_EXCEPTION_MESSAGE_H_
 #define COBALT_SCRIPT_EXCEPTION_MESSAGE_H_
 
diff --git a/src/cobalt/script/exception_state.h b/src/cobalt/script/exception_state.h
index d478086..4ba3ea6 100644
--- a/src/cobalt/script/exception_state.h
+++ b/src/cobalt/script/exception_state.h
@@ -11,6 +11,7 @@
 // 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.
+
 #ifndef COBALT_SCRIPT_EXCEPTION_STATE_H_
 #define COBALT_SCRIPT_EXCEPTION_STATE_H_
 
diff --git a/src/cobalt/script/execution_state.h b/src/cobalt/script/execution_state.h
index 0e8542b..b9965c9 100644
--- a/src/cobalt/script/execution_state.h
+++ b/src/cobalt/script/execution_state.h
@@ -11,6 +11,7 @@
 // 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.
+
 #ifndef COBALT_SCRIPT_EXECUTION_STATE_H_
 #define COBALT_SCRIPT_EXECUTION_STATE_H_
 
diff --git a/src/cobalt/script/fake_global_environment.h b/src/cobalt/script/fake_global_environment.h
index 470a7e4..3439f2c 100644
--- a/src/cobalt/script/fake_global_environment.h
+++ b/src/cobalt/script/fake_global_environment.h
@@ -34,7 +34,7 @@
   bool EvaluateScript(
       const scoped_refptr<SourceCode>& /*script_utf8*/,
       const scoped_refptr<Wrappable>& /*owning_object*/, bool /*mute_errors*/,
-      base::optional<OpaqueHandleHolder::Reference>* /*out_opaque_handle*/)
+      base::optional<ValueHandleHolder::Reference>* /*out_value_handle*/)
       OVERRIDE {
     return false;
   }
diff --git a/src/cobalt/script/global_environment.h b/src/cobalt/script/global_environment.h
index ba6fbeb..b2836f2 100644
--- a/src/cobalt/script/global_environment.h
+++ b/src/cobalt/script/global_environment.h
@@ -11,6 +11,7 @@
 // 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.
+
 #ifndef COBALT_SCRIPT_GLOBAL_ENVIRONMENT_H_
 #define COBALT_SCRIPT_GLOBAL_ENVIRONMENT_H_
 
@@ -20,10 +21,10 @@
 #include "base/memory/ref_counted.h"
 #include "base/optional.h"
 #include "cobalt/script/error_report.h"
-#include "cobalt/script/opaque_handle.h"
 #include "cobalt/script/script_value.h"
 #include "cobalt/script/script_value_factory.h"
 #include "cobalt/script/stack_frame.h"
+#include "cobalt/script/value_handle.h"
 #include "cobalt/script/wrappable.h"
 
 namespace cobalt {
@@ -63,25 +64,33 @@
 
   // Evaluate the JavaScript source code. Returns true on success,
   // false if there is an exception.
-  // Set |out_opaque_handle| to be a reference to the result of the evaluation
+  // Set |out_value_handle| to be a reference to the result of the evaluation
   // of the script that is owned by |owner|.
   virtual bool EvaluateScript(
       const scoped_refptr<SourceCode>& script_utf8,
       const scoped_refptr<Wrappable>& owning_object, bool mute_errors,
-      base::optional<OpaqueHandleHolder::Reference>* out_opaque_handle) = 0;
+      base::optional<ValueHandleHolder::Reference>* out_value_handle) = 0;
 
   // Returns the stack trace as a vector of individual frames.
   // Set |max_frames| to 0 to retrieve all available frames. Otherwise
   // return at most |max_frames|.
   virtual std::vector<StackFrame> GetStackTrace(int max_frames) = 0;
+  // Our style guide bans default arguments for virtual functions, however we
+  // ended up taking a dependency on them in our bindings code before it was
+  // caught. Instead, provide a non-virtual overload that wraps virtual
+  // |GetStackTrace(int)| to make everyone happy.
+  std::vector<StackFrame> GetStackTrace() { return GetStackTrace(0); }
 
-  // Prevent this wrappable's associated JS wrapper object from being garbage
-  // collected. AllowGarbageCollection must be called some time afterwards or
-  // else both the JS wrapper object and Wrappable will leak.
+  // Prevent this wrappable's associated JavaScript wrapper object from being
+  // garbage collected. |AllowGarbageCollection| must be called some time
+  // afterwards, or else both the JavaScript wrapper object and Wrappable will
+  // leak. Note that multiple calls to |PreventGarbageCollection| *are*
+  // counted, in that calling (e.g.) prevent, prevent, allow on |wrappable|,
+  // implies that |wrappable| is still garbage collection prevented.
   virtual void PreventGarbageCollection(
       const scoped_refptr<Wrappable>& wrappable) = 0;
 
-  // Allow this wrappable's associated JS wrapper object to be garbage
+  // Allow this wrappable's associated JavaScript wrapper object to be garbage
   // collected.
   virtual void AllowGarbageCollection(
       const scoped_refptr<Wrappable>& wrappable) = 0;
@@ -105,7 +114,7 @@
   virtual void SetReportErrorCallback(
       const ReportErrorCallback& report_error) = 0;
 
-  // Dynamically bind a cpp object to the javascript global object with the
+  // Dynamically bind a cpp object to the JavaScript global object with the
   // supplied identifier.
   // This method is useful for testing and debug purposes, as well as for
   // dynamically injecting an API into a JavaScript environment.
diff --git a/src/cobalt/script/logging_exception_state.h b/src/cobalt/script/logging_exception_state.h
index 0cf0a70..175c15b 100644
--- a/src/cobalt/script/logging_exception_state.h
+++ b/src/cobalt/script/logging_exception_state.h
@@ -11,6 +11,7 @@
 // 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.
+
 #ifndef COBALT_SCRIPT_LOGGING_EXCEPTION_STATE_H_
 #define COBALT_SCRIPT_LOGGING_EXCEPTION_STATE_H_
 
diff --git a/src/cobalt/script/mozjs-45/callback_function_conversion.h b/src/cobalt/script/mozjs-45/callback_function_conversion.h
index 2f56bb5..ebb19b5 100644
--- a/src/cobalt/script/mozjs-45/callback_function_conversion.h
+++ b/src/cobalt/script/mozjs-45/callback_function_conversion.h
@@ -70,18 +70,14 @@
 
   // https://www.w3.org/TR/WebIDL/#es-callback-function
   // 1. If V is not a Function object, throw a TypeError
-  JS::RootedObject object(context);
-  if (value.isObject()) {
-    object = JS::RootedObject(context, &value.toObject());
-  }
-  if (!object || !JS_ObjectIsFunction(context, object)) {
+  if (!value.isObject() || !JS_ObjectIsFunction(context, &value.toObject())) {
     exception_state->SetSimpleException(kNotFunctionValue);
     return;
   }
 
   MozjsGlobalEnvironment* global_environment =
       static_cast<MozjsGlobalEnvironment*>(JS_GetContextPrivate(context));
-  *out_callback_function = MozjsCallbackHolderClass(context, object);
+  *out_callback_function = MozjsCallbackHolderClass(context, value);
 }
 
 }  // namespace mozjs
diff --git a/src/cobalt/script/mozjs-45/conversion_helpers.cc b/src/cobalt/script/mozjs-45/conversion_helpers.cc
index 46a7b25..6b5ef53 100644
--- a/src/cobalt/script/mozjs-45/conversion_helpers.cc
+++ b/src/cobalt/script/mozjs-45/conversion_helpers.cc
@@ -14,9 +14,8 @@
 
 #include "cobalt/script/mozjs-45/conversion_helpers.h"
 
-#include "third_party/mozjs-45/js/src/jsapi.h"
-
 #include "nb/memory_scope.h"
+#include "third_party/mozjs-45/js/src/jsapi.h"
 
 namespace cobalt {
 namespace script {
@@ -59,54 +58,6 @@
   *out_string = utf8_chars;
 }
 
-// OpaqueHandle -> JSValue
-void ToJSValue(JSContext* context,
-               const OpaqueHandleHolder* opaque_handle_holder,
-               JS::MutableHandleValue out_value) {
-  TRACK_MEMORY_SCOPE("Javascript");
-  JS::RootedObject js_object(context);
-  if (opaque_handle_holder) {
-    // Downcast to MozjsObjectHandleHolder so we can get the JS object.
-    const MozjsObjectHandleHolder* mozjs_object_handle_holder =
-        base::polymorphic_downcast<const MozjsObjectHandleHolder*>(
-            opaque_handle_holder);
-    js_object = mozjs_object_handle_holder->js_object();
-  }
-  out_value.setObjectOrNull(js_object);
-}
-
-// JSValue -> OpaqueHandle
-void FromJSValue(JSContext* context, JS::HandleValue value,
-                 int conversion_flags, ExceptionState* exception_state,
-                 MozjsObjectHandleHolder* out_holder) {
-  TRACK_MEMORY_SCOPE("Javascript");
-  DCHECK_EQ(conversion_flags & ~kConversionFlagsObject, 0)
-      << "Unexpected conversion flags found.";
-  // https://www.w3.org/TR/WebIDL/#es-object
-  // 1. If Type(V) is not Object, throw a TypeError
-  // If the condition listed above is true, then the exception that we throw
-  // differs depending on whether the non-object is null or not.  Thus, we
-  // perform this check in two separate steps below.
-  if (!value.isObjectOrNull()) {
-    exception_state->SetSimpleException(kNotObjectType);
-    return;
-  }
-  if (value.isNull()) {
-    // Set an exception if this is not nullable.
-    if (!(conversion_flags & kConversionFlagNullable)) {
-      exception_state->SetSimpleException(kNotNullableType);
-    }
-    // Return here even for the non-exception case.
-    return;
-  }
-
-  JS::RootedObject js_object(context, &value.toObject());
-  DCHECK(js_object);
-  MozjsGlobalEnvironment* global_environment =
-      static_cast<MozjsGlobalEnvironment*>(JS_GetContextPrivate(context));
-  *out_holder = MozjsObjectHandleHolder(context, js_object);
-}
-
 // ValueHandle -> JSValue
 void ToJSValue(JSContext* context, const ValueHandleHolder* value_handle_holder,
                JS::MutableHandleValue out_value) {
@@ -128,11 +79,36 @@
                  int conversion_flags, ExceptionState* exception_state,
                  MozjsValueHandleHolder* out_holder) {
   TRACK_MEMORY_SCOPE("Javascript");
-  DCHECK_EQ(conversion_flags & ~kConversionFlagsObject, 0)
+  DCHECK_EQ(conversion_flags & ~kConversionFlagsValueHandle, 0)
       << "Unexpected conversion flags found.";
-  MozjsGlobalEnvironment* global_environment =
-      static_cast<MozjsGlobalEnvironment*>(JS_GetContextPrivate(context));
-  *out_holder = MozjsValueHandleHolder(context, value);
+
+  // If |value| is expected to be an IDL object, then we are supposed to throw
+  // if we get something that isn't of type Object or null.  Otherwise, we can
+  // just accept anything.
+  if (conversion_flags & kConversionFlagObjectOnly) {
+    // https://www.w3.org/TR/WebIDL/#es-object
+    // 1. If Type(V) is not Object, throw a TypeError
+    // If the condition listed above is true, then the exception that we throw
+    // differs depending on whether the non-object is null or not.  Thus, we
+    // perform this check in two separate steps below.
+    if (!value.isObjectOrNull()) {
+      exception_state->SetSimpleException(kNotObjectType);
+      return;
+    }
+    if (value.isNull()) {
+      // Set an exception if this is not nullable.
+      if (!(conversion_flags & kConversionFlagNullable)) {
+        exception_state->SetSimpleException(kNotNullableType);
+      }
+      // Return here even for the non-exception case.
+      return;
+    }
+
+    DCHECK(value.isObject());
+    *out_holder = MozjsValueHandleHolder(context, value);
+  } else {
+    *out_holder = MozjsValueHandleHolder(context, value);
+  }
 }
 
 }  // namespace mozjs
diff --git a/src/cobalt/script/mozjs-45/conversion_helpers.h b/src/cobalt/script/mozjs-45/conversion_helpers.h
index e7a0065..ff2b0dd 100644
--- a/src/cobalt/script/mozjs-45/conversion_helpers.h
+++ b/src/cobalt/script/mozjs-45/conversion_helpers.h
@@ -29,7 +29,6 @@
 #include "cobalt/script/mozjs-45/mozjs_callback_interface_holder.h"
 #include "cobalt/script/mozjs-45/mozjs_exception_state.h"
 #include "cobalt/script/mozjs-45/mozjs_global_environment.h"
-#include "cobalt/script/mozjs-45/mozjs_object_handle.h"
 #include "cobalt/script/mozjs-45/mozjs_user_object_holder.h"
 #include "cobalt/script/mozjs-45/mozjs_value_handle.h"
 #include "cobalt/script/mozjs-45/type_traits.h"
@@ -58,6 +57,7 @@
   kConversionFlagTreatNullAsEmptyString = 1 << 2,
   kConversionFlagTreatUndefinedAsEmptyString = 1 << 3,
   kConversionFlagClamped = 1 << 4,
+  kConversionFlagObjectOnly = 1 << 5,
 
   // Valid conversion flags for numeric values.
   kConversionFlagsNumeric = kConversionFlagRestricted | kConversionFlagClamped,
@@ -69,6 +69,10 @@
   // Valid conversion flags for objects.
   kConversionFlagsObject = kConversionFlagNullable,
 
+  // Valid conversion flags for ValueHandles.
+  kConversionFlagsValueHandle =
+      kConversionFlagObjectOnly | kConversionFlagNullable,
+
   // Valid conversion flags for callback functions.
   kConversionFlagsCallbackFunction = kConversionFlagNullable,
 
@@ -199,54 +203,55 @@
   }
 }
 
-// JSValue -> signed integers <= 4 bytes
+namespace internal {
+
+// A small helper metafunction for integer-like FromJSValue conversions to
+// pick the right type to feed to SpiderMonkey, which can only be the output
+// types observed here.
 template <typename T>
-inline void FromJSValue(
-    JSContext* context, JS::HandleValue value, int conversion_flags,
-    ExceptionState* exception_state, T* out_number,
-    typename base::enable_if<std::numeric_limits<T>::is_specialized &&
-                                 std::numeric_limits<T>::is_integer &&
-                                 std::numeric_limits<T>::is_signed &&
-                                 (sizeof(T) <= 4),
-                             T>::type* = NULL) {
-  TRACK_MEMORY_SCOPE("Javascript");
-  DCHECK(out_number);
+struct IntegralTypeToJsOutType {
+  static_assert(std::numeric_limits<T>::is_specialized &&
+                    std::numeric_limits<T>::is_integer,
+                "");
+  using type = typename std::conditional<
+      std::numeric_limits<T>::is_signed,
+      typename std::conditional<(sizeof(T) <= 4), int32_t, int64_t>::type,
+      typename std::conditional<(sizeof(T) <= 4), uint32_t,
+                                uint64_t>::type>::type;
+};
 
-  if (UNLIKELY(value.isSymbol())) {
-    exception_state->SetSimpleException(
-        kTypeError, "Cannot convert a Symbol value to a number");
-    return;
-  }
-
-  int32_t out;
-  // Convert a JavaScript value to an integer type as specified by the
-  // ECMAScript standard.
-  // TODO: Consider only creating |value_to_convert| if the conversion flag is
-  // set.
-  JS::RootedValue value_to_convert(context);
-  if (conversion_flags & kConversionFlagClamped) {
-    ClampedValue<T>(context, value, &value_to_convert);
-  } else {
-    value_to_convert.set(value);
-  }
-
-  bool success = JS::ToInt32(context, value_to_convert, &out);
-  DCHECK(success);
-
-  *out_number = static_cast<T>(out);
+// And some overloads to get all these different calls under the same
+// identifier in the single template implementation.
+inline bool JSToIntegral(JSContext* context, JS::HandleValue value,
+                         int32_t* out) {
+  return JS::ToInt32(context, value, out);
+}
+inline bool JSToIntegral(JSContext* context, JS::HandleValue value,
+                         int64_t* out) {
+  return JS::ToInt64(context, value, out);
+}
+inline bool JSToIntegral(JSContext* context, JS::HandleValue value,
+                         uint32_t* out) {
+  return JS::ToUint32(context, value, out);
+}
+inline bool JSToIntegral(JSContext* context, JS::HandleValue value,
+                         uint64_t* out) {
+  return JS::ToUint64(context, value, out);
 }
 
-// JSValue -> signed integers > 4 bytes
+}  // namespace internal
+
+// JSValue -> integer-like
 template <typename T>
 inline void FromJSValue(
     JSContext* context, JS::HandleValue value, int conversion_flags,
     ExceptionState* exception_state, T* out_number,
     typename base::enable_if<std::numeric_limits<T>::is_specialized &&
-                                 std::numeric_limits<T>::is_integer &&
-                                 std::numeric_limits<T>::is_signed &&
-                                 (sizeof(T) > 4),
+                                 std::numeric_limits<T>::is_integer,
                              T>::type* = NULL) {
+  using namespace ::cobalt::script::mozjs::internal;
   TRACK_MEMORY_SCOPE("Javascript");
+  DCHECK(out_number);
 
   if (UNLIKELY(value.isSymbol())) {
     exception_state->SetSimpleException(
@@ -254,28 +259,32 @@
     return;
   }
 
-  double to_number;
-  JS::ToNumber(context, value, &to_number);
-
-  std::string value_str;
-  FromJSValue(context, value, conversion_flags, exception_state, &value_str);
-  DCHECK_EQ(conversion_flags, kNoConversionFlags)
-      << "No conversion flags supported.";
-  DCHECK(out_number);
-  int64_t out;
-  // This produces an IDL long long.
-  // TODO: Consider only creating |value_to_convert| if the conversion flag is
-  // set.
-  JS::RootedValue value_to_convert(context);
-  if (conversion_flags & kConversionFlagClamped) {
+  // Convert a JavaScript value to an integer type as specified by the
+  // ECMAScript standard.
+  typename IntegralTypeToJsOutType<T>::type out;
+  bool success;
+  if (UNLIKELY(conversion_flags & kConversionFlagClamped)) {
+    JS::RootedValue value_to_convert(context);
     ClampedValue<T>(context, value, &value_to_convert);
+    success = JSToIntegral(context, value_to_convert, &out);
   } else {
-    value_to_convert.set(value);
+    success = JSToIntegral(context, value, &out);
   }
-  bool success = JS::ToInt64(context, value_to_convert, &out);
-  DCHECK(success);
+
+  // It is possible for |JS::To{Uint,Int}{32,64}| to fail in certain edge
+  // cases, such as application JavaScript setting up infinite recursion that
+  // gets triggered by the conversion.
   if (!success) {
-    exception_state->SetSimpleException(kNotInt64Type);
+    if (JS_IsExceptionPending(context)) {
+      // If SpiderMonkey already threw something as a result of calling
+      // |JS::To{Uint,Int}{32,64}|, then just use that...
+      base::polymorphic_downcast<MozjsExceptionState*>(exception_state)
+          ->SetExceptionAlreadySet(context);
+    } else {
+      // ...and if not, then just tell them that it isn't the right type.
+      exception_state->SetSimpleException(
+          std::numeric_limits<T>::is_signed ? kNotInt64Type : kNotUint64Type);
+    }
     return;
   }
   *out_number = static_cast<T>(out);
@@ -309,83 +318,6 @@
   out_value.setNumber(static_cast<uint32_t>(in_number));
 }
 
-// JSValue -> unsigned integers <= 4 bytes
-template <typename T>
-inline void FromJSValue(
-    JSContext* context, JS::HandleValue value, int conversion_flags,
-    ExceptionState* exception_state, T* out_number,
-    typename base::enable_if<std::numeric_limits<T>::is_specialized &&
-                                 std::numeric_limits<T>::is_integer &&
-                                 !std::numeric_limits<T>::is_signed &&
-                                 (sizeof(T) <= 4),
-                             T>::type* = NULL) {
-  TRACK_MEMORY_SCOPE("Javascript");
-  DCHECK(out_number);
-
-  if (UNLIKELY(value.isSymbol())) {
-    exception_state->SetSimpleException(
-        kTypeError, "Cannot convert a Symbol value to a number");
-    return;
-  }
-
-  uint32_t out;
-  // Convert a JavaScript value to an integer type as specified by the
-  // ECMAScript standard.
-  // TODO: Consider only creating |value_to_convert| if the conversion flag is
-  // set.
-  JS::RootedValue value_to_convert(context);
-  if (conversion_flags & kConversionFlagClamped) {
-    ClampedValue<T>(context, value, &value_to_convert);
-  } else {
-    value_to_convert.set(value);
-  }
-  bool success = JS::ToUint32(context, value_to_convert, &out);
-  DCHECK(success);
-  if (!success) {
-    exception_state->SetSimpleException(kNotUint64Type);
-    return;
-  }
-  *out_number = static_cast<T>(out);
-}
-
-// JSValue -> unsigned integers > 4 bytes
-template <typename T>
-inline void FromJSValue(
-    JSContext* context, JS::HandleValue value, int conversion_flags,
-    ExceptionState* exception_state, T* out_number,
-    typename base::enable_if<std::numeric_limits<T>::is_specialized &&
-                                 std::numeric_limits<T>::is_integer &&
-                                 !std::numeric_limits<T>::is_signed &&
-                                 (sizeof(T) > 4),
-                             T>::type* = NULL) {
-  TRACK_MEMORY_SCOPE("Javascript");
-  DCHECK(out_number);
-
-  if (UNLIKELY(value.isSymbol())) {
-    exception_state->SetSimpleException(
-        kTypeError, "Cannot convert a Symbol value to a number");
-    return;
-  }
-
-  uint64_t out;
-  // This produces and IDL unsigned long long.
-  // TODO: Consider only creating |value_to_convert| if the conversion flag is
-  // set.
-  JS::RootedValue value_to_convert(context);
-  if (conversion_flags & kConversionFlagClamped) {
-    ClampedValue<T>(context, value, &value_to_convert);
-  } else {
-    value_to_convert.set(value);
-  }
-  bool success = JS::ToUint64(context, value_to_convert, &out);
-  DCHECK(success);
-  if (!success) {
-    exception_state->SetSimpleException(kNotUint64Type);
-    return;
-  }
-  *out_number = static_cast<T>(out);
-}
-
 // unsigned integers > 4 bytes -> JSValue
 template <typename T>
 inline void ToJSValue(
@@ -493,16 +425,6 @@
   }
 }
 
-// OpaqueHandle -> JSValue
-void ToJSValue(JSContext* context,
-               const OpaqueHandleHolder* opaque_handle_holder,
-               JS::MutableHandleValue out_value);
-
-// JSValue -> OpaqueHandle
-void FromJSValue(JSContext* context, JS::HandleValue value,
-                 int conversion_flags, ExceptionState* exception_state,
-                 MozjsObjectHandleHolder* out_holder);
-
 // ValueHandle -> JSValue
 void ToJSValue(JSContext* context, const ValueHandleHolder* value_handle_holder,
                JS::MutableHandleValue out_value);
@@ -644,13 +566,8 @@
     return;
   }
 
-  MozjsGlobalEnvironment* global_environment =
-      static_cast<MozjsGlobalEnvironment*>(JS_GetContextPrivate(context));
-
-  JS::RootedObject implementing_object(context, &value.toObject());
-  DCHECK(implementing_object);
-  *out_callback_interface =
-      MozjsCallbackInterfaceHolder<T>(context, implementing_object);
+  DCHECK(value.isObject());
+  *out_callback_interface = MozjsCallbackInterfaceHolder<T>(context, value);
 }
 
 template <typename T>
diff --git a/src/cobalt/script/mozjs-45/mozjs-45.gyp b/src/cobalt/script/mozjs-45/mozjs-45.gyp
index 2ce1ff4..16d55ad 100644
--- a/src/cobalt/script/mozjs-45/mozjs-45.gyp
+++ b/src/cobalt/script/mozjs-45/mozjs-45.gyp
@@ -18,19 +18,44 @@
       'target_name': 'engine',
       'type': 'static_library',
       'sources': [
+        'callback_function_conversion.h',
         'conversion_helpers.cc',
+        'conversion_helpers.h',
+        'convert_callback_return_value.h',
+        'interface_data.h',
+        'mozjs_callback_function.h',
         'mozjs_callback_interface.cc',
+        'mozjs_callback_interface.h',
+        'mozjs_callback_interface_holder.h',
         'mozjs_engine.cc',
+        'mozjs_engine.h',
         'mozjs_exception_state.cc',
+        'mozjs_exception_state.h',
         'mozjs_global_environment.cc',
+        'mozjs_global_environment.h',
         'mozjs_property_enumerator.cc',
+        'mozjs_property_enumerator.h',
         'mozjs_script_value_factory.cc',
+        'mozjs_script_value_factory.h',
         'mozjs_source_code.cc',
+        'mozjs_source_code.h',
+        'mozjs_user_object_holder.h',
+        'mozjs_value_handle.h',
+        'mozjs_wrapper_handle.h',
+        'native_promise.h',
         'promise_wrapper.cc',
+        'promise_wrapper.h',
         'proxy_handler.cc',
+        'proxy_handler.h',
         'referenced_object_map.cc',
+        'referenced_object_map.h',
+        'type_traits.h',
+        'union_type_conversion_forward.h',
+        'union_type_conversion_impl.h',
         'util/algorithm_helpers.cc',
+        'util/algorithm_helpers.h',
         'util/exception_helpers.cc',
+        'util/exception_helpers.h',
         'util/stack_trace_helpers.cc',
         'util/stack_trace_helpers.h',
         'weak_heap_object.cc',
@@ -38,7 +63,9 @@
         'weak_heap_object_manager.cc',
         'weak_heap_object_manager.h',
         'wrapper_factory.cc',
+        'wrapper_factory.h',
         'wrapper_private.cc',
+        'wrapper_private.h',
         '<(DEPTH)/cobalt/script/shared/stub_script_debugger.cc',
       ],
       'dependencies': [
diff --git a/src/cobalt/script/mozjs-45/mozjs_callback_function.h b/src/cobalt/script/mozjs-45/mozjs_callback_function.h
index a3a841a..87ba670 100644
--- a/src/cobalt/script/mozjs-45/mozjs_callback_function.h
+++ b/src/cobalt/script/mozjs-45/mozjs_callback_function.h
@@ -50,12 +50,6 @@
  public:
   typedef CallbackFunction<R()> BaseType;
 
-  explicit MozjsCallbackFunction(JSContext* context, JS::HandleObject function)
-      : context_(context), weak_function_(context, function) {
-    DCHECK(context_);
-    DCHECK(JS_ObjectIsFunction(context_, function));
-  }
-
   explicit MozjsCallbackFunction(JSContext* context, JS::HandleValue function)
       : context_(context), weak_function_(context, function) {
     DCHECK(context_);
@@ -113,12 +107,6 @@
  public:
   typedef CallbackFunction<R(A1)> BaseType;
 
-  explicit MozjsCallbackFunction(JSContext* context, JS::HandleObject function)
-      : context_(context), weak_function_(context, function) {
-    DCHECK(context_);
-    DCHECK(JS_ObjectIsFunction(context_, function));
-  }
-
   explicit MozjsCallbackFunction(JSContext* context, JS::HandleValue function)
       : context_(context), weak_function_(context, function) {
     DCHECK(context_);
@@ -179,12 +167,6 @@
  public:
   typedef CallbackFunction<R(A1, A2)> BaseType;
 
-  explicit MozjsCallbackFunction(JSContext* context, JS::HandleObject function)
-      : context_(context), weak_function_(context, function) {
-    DCHECK(context_);
-    DCHECK(JS_ObjectIsFunction(context_, function));
-  }
-
   explicit MozjsCallbackFunction(JSContext* context, JS::HandleValue function)
       : context_(context), weak_function_(context, function) {
     DCHECK(context_);
@@ -247,12 +229,6 @@
  public:
   typedef CallbackFunction<R(A1, A2, A3)> BaseType;
 
-  explicit MozjsCallbackFunction(JSContext* context, JS::HandleObject function)
-      : context_(context), weak_function_(context, function) {
-    DCHECK(context_);
-    DCHECK(JS_ObjectIsFunction(context_, function));
-  }
-
   explicit MozjsCallbackFunction(JSContext* context, JS::HandleValue function)
       : context_(context), weak_function_(context, function) {
     DCHECK(context_);
@@ -317,12 +293,6 @@
  public:
   typedef CallbackFunction<R(A1, A2, A3, A4)> BaseType;
 
-  explicit MozjsCallbackFunction(JSContext* context, JS::HandleObject function)
-      : context_(context), weak_function_(context, function) {
-    DCHECK(context_);
-    DCHECK(JS_ObjectIsFunction(context_, function));
-  }
-
   explicit MozjsCallbackFunction(JSContext* context, JS::HandleValue function)
       : context_(context), weak_function_(context, function) {
     DCHECK(context_);
@@ -390,12 +360,6 @@
  public:
   typedef CallbackFunction<R(A1, A2, A3, A4, A5)> BaseType;
 
-  explicit MozjsCallbackFunction(JSContext* context, JS::HandleObject function)
-      : context_(context), weak_function_(context, function) {
-    DCHECK(context_);
-    DCHECK(JS_ObjectIsFunction(context_, function));
-  }
-
   explicit MozjsCallbackFunction(JSContext* context, JS::HandleValue function)
       : context_(context), weak_function_(context, function) {
     DCHECK(context_);
@@ -465,12 +429,6 @@
  public:
   typedef CallbackFunction<R(A1, A2, A3, A4, A5, A6)> BaseType;
 
-  explicit MozjsCallbackFunction(JSContext* context, JS::HandleObject function)
-      : context_(context), weak_function_(context, function) {
-    DCHECK(context_);
-    DCHECK(JS_ObjectIsFunction(context_, function));
-  }
-
   explicit MozjsCallbackFunction(JSContext* context, JS::HandleValue function)
       : context_(context), weak_function_(context, function) {
     DCHECK(context_);
@@ -542,12 +500,6 @@
  public:
   typedef CallbackFunction<R(A1, A2, A3, A4, A5, A6, A7)> BaseType;
 
-  explicit MozjsCallbackFunction(JSContext* context, JS::HandleObject function)
-      : context_(context), weak_function_(context, function) {
-    DCHECK(context_);
-    DCHECK(JS_ObjectIsFunction(context_, function));
-  }
-
   explicit MozjsCallbackFunction(JSContext* context, JS::HandleValue function)
       : context_(context), weak_function_(context, function) {
     DCHECK(context_);
diff --git a/src/cobalt/script/mozjs-45/mozjs_callback_function.h.pump b/src/cobalt/script/mozjs-45/mozjs_callback_function.h.pump
index e8b0804..cda1b77 100644
--- a/src/cobalt/script/mozjs-45/mozjs_callback_function.h.pump
+++ b/src/cobalt/script/mozjs-45/mozjs_callback_function.h.pump
@@ -67,12 +67,6 @@
  public:
   typedef CallbackFunction<R($for ARG , [[A$(ARG)]])> BaseType;
 
-  explicit MozjsCallbackFunction(JSContext* context, JS::HandleObject function)
-      : context_(context), weak_function_(context, function) {
-    DCHECK(context_);
-    DCHECK(JS_ObjectIsFunction(context_, function));
-  }
-
   explicit MozjsCallbackFunction(JSContext* context, JS::HandleValue function)
       : context_(context), weak_function_(context, function) {
     DCHECK(context_);
diff --git a/src/cobalt/script/mozjs-45/mozjs_callback_interface_holder.h b/src/cobalt/script/mozjs-45/mozjs_callback_interface_holder.h
index 998c2b2..11049a5 100644
--- a/src/cobalt/script/mozjs-45/mozjs_callback_interface_holder.h
+++ b/src/cobalt/script/mozjs-45/mozjs_callback_interface_holder.h
@@ -30,8 +30,6 @@
  public:
   typedef MozjsUserObjectHolder<MozjsCallbackInterface> BaseClass;
   MozjsCallbackInterfaceHolder() {}
-  MozjsCallbackInterfaceHolder(JSContext* context, JS::HandleObject object)
-      : BaseClass(context, object) {}
   MozjsCallbackInterfaceHolder(JSContext* context, JS::HandleValue value)
       : BaseClass(context, value) {}
 };
diff --git a/src/cobalt/script/mozjs-45/mozjs_engine.cc b/src/cobalt/script/mozjs-45/mozjs_engine.cc
index f637f47..96f917b 100644
--- a/src/cobalt/script/mozjs-45/mozjs_engine.cc
+++ b/src/cobalt/script/mozjs-45/mozjs_engine.cc
@@ -34,9 +34,6 @@
 namespace mozjs {
 namespace {
 
-// Trigger garbage collection this many seconds after the last one.
-const int kGarbageCollectionIntervalSeconds = 60;
-
 JSSecurityCallbacks security_callbacks = {
     MozjsGlobalEnvironment::CheckEval,  // contentSecurityPolicyAllows
     NULL,  // JSSubsumesOp - Added in SpiderMonkey 31
@@ -190,12 +187,6 @@
   JS_SetErrorReporter(runtime_, ReportErrorHandler);
 
   EngineStats::GetInstance()->EngineCreated();
-
-  if (MessageLoop::current()) {
-    gc_timer_.Start(FROM_HERE, base::TimeDelta::FromSeconds(
-                                   kGarbageCollectionIntervalSeconds),
-                    this, &MozjsEngine::TimerGarbageCollect);
-  }
 }
 
 MozjsEngine::~MozjsEngine() {
@@ -237,11 +228,7 @@
   runtime_->gc.setMaxMallocBytes(static_cast<size_t>(bytes));
 }
 
-void MozjsEngine::TimerGarbageCollect() {
-  TRACE_EVENT0("cobalt::script", "MozjsEngine::TimerGarbageCollect()");
-  CollectGarbage();
-}
-
+// static
 bool MozjsEngine::ContextCallback(JSContext* context, unsigned context_op,
                                   void* data) {
   JSRuntime* runtime = JS_GetRuntime(context);
@@ -257,15 +244,12 @@
   return true;
 }
 
+// static
 void MozjsEngine::GCCallback(JSRuntime* runtime, JSGCStatus status,
                              void* data) {
   MozjsEngine* engine = reinterpret_cast<MozjsEngine*>(data);
   if (status == JSGC_END) {
     engine->accumulated_extra_memory_cost_ = 0;
-    // Reset the GC timer to avoid having the timed GC come soon after this one.
-    if (engine->gc_timer_.IsRunning()) {
-      engine->gc_timer_.Reset();
-    }
   }
   if (!engine->context_) {
     return;
@@ -281,6 +265,7 @@
   }
 }
 
+// static
 void MozjsEngine::FinalizeCallback(JSFreeOp* free_op, JSFinalizeStatus status,
                                    bool is_compartment, void* data) {
   TRACE_EVENT0("cobalt::script", "MozjsEngine::FinalizeCallback()");
diff --git a/src/cobalt/script/mozjs-45/mozjs_engine.h b/src/cobalt/script/mozjs-45/mozjs_engine.h
index a4a2314..55ea33d 100644
--- a/src/cobalt/script/mozjs-45/mozjs_engine.h
+++ b/src/cobalt/script/mozjs-45/mozjs_engine.h
@@ -11,6 +11,7 @@
 // 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.
+
 #ifndef COBALT_SCRIPT_MOZJS_45_MOZJS_ENGINE_H_
 #define COBALT_SCRIPT_MOZJS_45_MOZJS_ENGINE_H_
 
@@ -37,7 +38,6 @@
   void SetGcThreshold(int64_t bytes) OVERRIDE;
 
  private:
-  void TimerGarbageCollect();
   static bool ContextCallback(JSContext* context, unsigned context_op,
                               void* data);
   static void GCCallback(JSRuntime* runtime, JSGCStatus status, void* data);
@@ -58,9 +58,6 @@
   // The amount of externally allocated memory since last forced GC.
   size_t accumulated_extra_memory_cost_;
 
-  // Used to trigger a garbage collection periodically.
-  base::RepeatingTimer<MozjsEngine> gc_timer_;
-
   // Used to handle javascript errors.
   ErrorHandler error_handler_;
 
diff --git a/src/cobalt/script/mozjs-45/mozjs_exception_state.cc b/src/cobalt/script/mozjs-45/mozjs_exception_state.cc
index a722e5d..485383f 100644
--- a/src/cobalt/script/mozjs-45/mozjs_exception_state.cc
+++ b/src/cobalt/script/mozjs-45/mozjs_exception_state.cc
@@ -11,6 +11,7 @@
 // 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.
+
 #include "cobalt/script/mozjs-45/mozjs_exception_state.h"
 
 #include <string>
diff --git a/src/cobalt/script/mozjs-45/mozjs_exception_state.h b/src/cobalt/script/mozjs-45/mozjs_exception_state.h
index 02b5082..56ee317 100644
--- a/src/cobalt/script/mozjs-45/mozjs_exception_state.h
+++ b/src/cobalt/script/mozjs-45/mozjs_exception_state.h
@@ -11,6 +11,7 @@
 // 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.
+
 #ifndef COBALT_SCRIPT_MOZJS_45_MOZJS_EXCEPTION_STATE_H_
 #define COBALT_SCRIPT_MOZJS_45_MOZJS_EXCEPTION_STATE_H_
 
@@ -35,6 +36,19 @@
 
   bool is_exception_set() const { return is_exception_set_; }
 
+  // For when a Cobalt operation that is expected to modify an
+  // |ExceptionState| to communicate failure performs operations that can
+  // potentially cause an exception to be thrown by SpiderMonkey, and we want
+  // to reuse that exception instead of creating our own (which also likely
+  // would not be able to match the descriptiveness of the SpiderMonkey
+  // exception).
+  void SetExceptionAlreadySet(JSContext* context) {
+    DCHECK(thread_checker_.CalledOnValidThread());
+    DCHECK(!is_exception_set_);
+    DCHECK(JS_IsExceptionPending(context));
+    is_exception_set_ = true;
+  }
+
   static JSObject* CreateErrorObject(JSContext* context,
                                      SimpleExceptionType type);
 
diff --git a/src/cobalt/script/mozjs-45/mozjs_global_environment.cc b/src/cobalt/script/mozjs-45/mozjs_global_environment.cc
index 8d03389..22b5162 100644
--- a/src/cobalt/script/mozjs-45/mozjs_global_environment.cc
+++ b/src/cobalt/script/mozjs-45/mozjs_global_environment.cc
@@ -11,6 +11,7 @@
 // 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.
+
 #include "cobalt/script/mozjs-45/mozjs_global_environment.h"
 
 #include <algorithm>
@@ -221,7 +222,7 @@
 bool MozjsGlobalEnvironment::EvaluateScript(
     const scoped_refptr<SourceCode>& source_code,
     const scoped_refptr<Wrappable>& owning_object, bool mute_errors,
-    base::optional<OpaqueHandleHolder::Reference>* out_opaque_handle) {
+    base::optional<ValueHandleHolder::Reference>* out_value_handle) {
   TRACK_MEMORY_SCOPE("Javascript");
   DCHECK(thread_checker_.CalledOnValidThread());
   JSAutoRequest auto_request(context_);
@@ -230,11 +231,9 @@
   JS::RootedValue result_value(context_);
   bool success =
       EvaluateScriptInternal(source_code, mute_errors, &result_value);
-  if (success && out_opaque_handle) {
-    JS::RootedObject js_object(context_);
-    JS_ValueToObject(context_, result_value, &js_object);
-    MozjsObjectHandleHolder mozjs_object_holder(context_, js_object);
-    out_opaque_handle->emplace(owning_object.get(), mozjs_object_holder);
+  if (success && out_value_handle) {
+    MozjsValueHandleHolder mozjs_value_holder(context_, result_value);
+    out_value_handle->emplace(owning_object.get(), mozjs_value_holder);
   }
   return success;
 }
@@ -301,23 +300,32 @@
 void MozjsGlobalEnvironment::PreventGarbageCollection(
     const scoped_refptr<Wrappable>& wrappable) {
   DCHECK(thread_checker_.CalledOnValidThread());
+
   JSAutoRequest auto_request(context_);
   JSAutoCompartment auto_compartment(context_, global_object_proxy_);
   WrapperPrivate* wrapper_private =
       WrapperPrivate::GetFromWrappable(wrappable, context_, wrapper_factory());
-  JS::RootedObject proxy(context_, wrapper_private->js_object_proxy());
-  kept_alive_objects_.insert(CachedWrapperMultiMap::value_type(
-      wrappable.get(), JS::Heap<JSObject*>(proxy)));
+  // Attempt to insert a |Wrappable*| -> wrapper mapping into
+  // |kept_alive_objects_|...
+  auto insert_result = kept_alive_objects_.insert(
+      {wrappable.get(),
+       {JS::Heap<JSObject*>(wrapper_private->js_object_proxy()), 1}});
+  // ...and if it was already there, just increment the count.
+  if (!insert_result.second) {
+    insert_result.first->second.count++;
+  }
 }
 
 void MozjsGlobalEnvironment::AllowGarbageCollection(
     const scoped_refptr<Wrappable>& wrappable) {
   TRACK_MEMORY_SCOPE("Javascript");
   DCHECK(thread_checker_.CalledOnValidThread());
-  CachedWrapperMultiMap::iterator it =
-      kept_alive_objects_.find(wrappable.get());
+
+  auto it = kept_alive_objects_.find(wrappable.get());
   DCHECK(it != kept_alive_objects_.end());
-  if (it != kept_alive_objects_.end()) {
+  it->second.count--;
+  DCHECK(it->second.count >= 0);
+  if (it->second.count == 0) {
     kept_alive_objects_.erase(it);
   }
 }
@@ -522,41 +530,42 @@
   }
 }
 
-void MozjsGlobalEnvironment::TraceFunction(JSTracer* trace, void* data) {
-  MozjsGlobalEnvironment* global_object_environment =
-      reinterpret_cast<MozjsGlobalEnvironment*>(data);
-  if (global_object_environment->global_object_proxy_) {
-    JS_CallObjectTracer(trace, &global_object_environment->global_object_proxy_,
+void MozjsGlobalEnvironment::TraceFunction(JSTracer* tracer, void* data) {
+  MozjsGlobalEnvironment* global_environment =
+      static_cast<MozjsGlobalEnvironment*>(data);
+  if (global_environment->global_object_proxy_) {
+    JS_CallObjectTracer(tracer, &global_environment->global_object_proxy_,
                         "MozjsGlobalEnvironment");
   }
 
-  for (int i = 0; i < global_object_environment->cached_interface_data_.size();
-       i++) {
-    InterfaceData& data = global_object_environment->cached_interface_data_[i];
-    if (data.prototype) {
-      JS_CallObjectTracer(trace, &data.prototype, "MozjsGlobalEnvironment");
+  for (auto& interface_data : global_environment->cached_interface_data_) {
+    if (interface_data.prototype) {
+      JS_CallObjectTracer(tracer, &interface_data.prototype,
+                          "MozjsGlobalEnvironment");
     }
-    if (data.interface_object) {
-      JS_CallObjectTracer(trace, &data.interface_object,
+    if (interface_data.interface_object) {
+      JS_CallObjectTracer(tracer, &interface_data.interface_object,
                           "MozjsGlobalEnvironment");
     }
   }
 
-  for (CachedWrapperMultiMap::iterator it =
-           global_object_environment->kept_alive_objects_.begin();
-       it != global_object_environment->kept_alive_objects_.end(); ++it) {
-    JS_CallObjectTracer(trace, &it->second, "MozjsGlobalEnvironment");
+  auto& kept_alive_objects_ = global_environment->kept_alive_objects_;
+  for (auto& pair : kept_alive_objects_) {
+    auto& counted_heap_object = pair.second;
+    DCHECK(counted_heap_object.count > 0);
+    JS_CallObjectTracer(tracer, &counted_heap_object.heap_object,
+                        "MozjsGlobalEnvironment");
   }
 }
 
 bool MozjsGlobalEnvironment::CheckEval(JSContext* context) {
   TRACK_MEMORY_SCOPE("Javascript");
-  MozjsGlobalEnvironment* global_object_proxy = GetFromContext(context);
-  DCHECK(global_object_proxy);
-  if (!global_object_proxy->report_eval_.is_null()) {
-    global_object_proxy->report_eval_.Run();
+  MozjsGlobalEnvironment* global_environment = GetFromContext(context);
+  DCHECK(global_environment);
+  if (!global_environment->report_eval_.is_null()) {
+    global_environment->report_eval_.Run();
   }
-  return global_object_proxy->eval_enabled_;
+  return global_environment->eval_enabled_;
 }
 
 }  // namespace mozjs
diff --git a/src/cobalt/script/mozjs-45/mozjs_global_environment.h b/src/cobalt/script/mozjs-45/mozjs_global_environment.h
index 643d0ec..43229f1 100644
--- a/src/cobalt/script/mozjs-45/mozjs_global_environment.h
+++ b/src/cobalt/script/mozjs-45/mozjs_global_environment.h
@@ -11,10 +11,12 @@
 // 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.
+
 #ifndef COBALT_SCRIPT_MOZJS_45_MOZJS_GLOBAL_ENVIRONMENT_H_
 #define COBALT_SCRIPT_MOZJS_45_MOZJS_GLOBAL_ENVIRONMENT_H_
 
 #include <string>
+#include <unordered_map>
 #include <vector>
 
 #include "base/hash_tables.h"
@@ -49,17 +51,23 @@
   ~MozjsGlobalEnvironment() OVERRIDE;
 
   void CreateGlobalObject() OVERRIDE;
+  // |script::GlobalEnvironment| will dispatch to this implementation in the
+  // create_global_object_impl block of the bindings interface template.
+  template <typename GlobalInterface>
+  void CreateGlobalObject(
+      const scoped_refptr<GlobalInterface>& global_interface,
+      EnvironmentSettings* environment_settings);
 
   bool EvaluateScript(const scoped_refptr<SourceCode>& script, bool mute_errors,
                       std::string* out_result_utf8) OVERRIDE;
 
-  bool EvaluateScript(const scoped_refptr<SourceCode>& script_utf8,
-                      const scoped_refptr<Wrappable>& owning_object,
-                      bool mute_errors,
-                      base::optional<OpaqueHandleHolder::Reference>*
-                          out_opaque_handle) OVERRIDE;
+  bool EvaluateScript(
+      const scoped_refptr<SourceCode>& script_utf8,
+      const scoped_refptr<Wrappable>& owning_object, bool mute_errors,
+      base::optional<ValueHandleHolder::Reference>* out_value_handle) OVERRIDE;
 
-  std::vector<StackFrame> GetStackTrace(int max_frames = 0) OVERRIDE;
+  std::vector<StackFrame> GetStackTrace(int max_frames) OVERRIDE;
+  using GlobalEnvironment::GetStackTrace;
 
   void PreventGarbageCollection(
       const scoped_refptr<Wrappable>& wrappable) OVERRIDE;
@@ -105,13 +113,6 @@
     return &visited_wrappables_;
   }
 
-  // Used for CallWith=EnvironmentSettings
-  void SetEnvironmentSettings(EnvironmentSettings* environment_settings) {
-    DCHECK(!environment_settings_);
-    DCHECK(environment_settings);
-    environment_settings_ = environment_settings;
-  }
-
   EnvironmentSettings* GetEnvironmentSettings() const {
     return environment_settings_;
   }
@@ -143,6 +144,21 @@
   void ReportError(const char* message, JSErrorReport* report);
 
  private:
+  // Helper struct to ensure the context is destroyed in the correct order
+  // relative to the MozjsGlobalEnvironment's other members.
+  struct ContextDestructor {
+    explicit ContextDestructor(JSContext** context) : context(context) {}
+    ~ContextDestructor() { JS_DestroyContext(*context); }
+    JSContext** const context;
+  };
+
+  struct CountedHeapObject {
+    CountedHeapObject(const JS::Heap<JSObject*>& heap_object, int count)
+        : heap_object(heap_object), count(count) {}
+    JS::Heap<JSObject*> heap_object;
+    int count;
+  };
+
   bool EvaluateScriptInternal(const scoped_refptr<SourceCode>& source_code,
                               bool mute_errors,
                               JS::MutableHandleValue out_result);
@@ -152,22 +168,11 @@
 
   static void TraceFunction(JSTracer* trace, void* data);
 
-  // Helper struct to ensure the context is destroyed in the correct order
-  // relative to the MozjsGlobalEnvironment's other members.
-  struct ContextDestructor {
-    explicit ContextDestructor(JSContext** context) : context(context) {}
-    ~ContextDestructor() { JS_DestroyContext(*context); }
-    JSContext** const context;
-  };
-
-  typedef base::hash_multimap<Wrappable*, JS::Heap<JSObject*> >
-      CachedWrapperMultiMap;
-
   base::ThreadChecker thread_checker_;
   JSContext* context_;
   int garbage_collection_count_;
   WeakHeapObjectManager weak_object_manager_;
-  CachedWrapperMultiMap kept_alive_objects_;
+  std::unordered_map<Wrappable*, CountedHeapObject> kept_alive_objects_;
   scoped_ptr<ReferencedObjectMap> referenced_objects_;
   std::vector<InterfaceData> cached_interface_data_;
 
diff --git a/src/cobalt/script/mozjs-45/mozjs_object_handle.h b/src/cobalt/script/mozjs-45/mozjs_object_handle.h
deleted file mode 100644
index 527f3bd..0000000
--- a/src/cobalt/script/mozjs-45/mozjs_object_handle.h
+++ /dev/null
@@ -1,64 +0,0 @@
-// Copyright 2016 Google Inc. All Rights Reserved.
-//
-// 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.
-#ifndef COBALT_SCRIPT_MOZJS_45_MOZJS_OBJECT_HANDLE_H_
-#define COBALT_SCRIPT_MOZJS_45_MOZJS_OBJECT_HANDLE_H_
-
-#include "base/optional.h"
-#include "cobalt/script/mozjs-45/mozjs_user_object_holder.h"
-#include "cobalt/script/mozjs-45/type_traits.h"
-#include "cobalt/script/mozjs-45/weak_heap_object.h"
-#include "cobalt/script/opaque_handle.h"
-#include "third_party/mozjs-45/js/src/jsapi.h"
-
-namespace cobalt {
-namespace script {
-namespace mozjs {
-
-// A wrapper around a JS::Value that can be passed into Cobalt as an
-// opaque script object.
-// An OpaqueHandle is never passed into Cobalt as-is, but only when wrapped as
-// a ScriptValue<OpaqueHandle>.
-class MozjsObjectHandle : public OpaqueHandle {
- public:
-  typedef OpaqueHandle BaseType;
-  JSObject* handle() const { return handle_.GetObject(); }
-  const JS::Value& value() const { return handle_.GetValue(); }
-  bool WasCollected() const { return handle_.WasCollected(); }
-
- private:
-  MozjsObjectHandle(JSContext* context, JS::HandleObject object)
-      : handle_(context, object) {}
-  MozjsObjectHandle(JSContext* context, JS::HandleValue value)
-      : handle_(context, value) {}
-  ~MozjsObjectHandle() {}
-
-  WeakHeapObject handle_;
-
-  friend class MozjsUserObjectHolder<MozjsObjectHandle>;
-  friend class base::optional<MozjsObjectHandle>;
-};
-
-typedef MozjsUserObjectHolder<MozjsObjectHandle> MozjsObjectHandleHolder;
-
-template <>
-struct TypeTraits<OpaqueHandle> {
-  typedef MozjsObjectHandleHolder ConversionType;
-  typedef const ScriptValue<OpaqueHandle>* ReturnType;
-};
-
-}  // namespace mozjs
-}  // namespace script
-}  // namespace cobalt
-
-#endif  // COBALT_SCRIPT_MOZJS_45_MOZJS_OBJECT_HANDLE_H_
diff --git a/src/cobalt/script/mozjs-45/mozjs_property_enumerator.cc b/src/cobalt/script/mozjs-45/mozjs_property_enumerator.cc
index a02c2b1..acc827a 100644
--- a/src/cobalt/script/mozjs-45/mozjs_property_enumerator.cc
+++ b/src/cobalt/script/mozjs-45/mozjs_property_enumerator.cc
@@ -11,6 +11,7 @@
 // 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.
+
 #include "cobalt/script/mozjs-45/mozjs_property_enumerator.h"
 
 #include "base/logging.h"
diff --git a/src/cobalt/script/mozjs-45/mozjs_property_enumerator.h b/src/cobalt/script/mozjs-45/mozjs_property_enumerator.h
index f1f542b..0880ed9 100644
--- a/src/cobalt/script/mozjs-45/mozjs_property_enumerator.h
+++ b/src/cobalt/script/mozjs-45/mozjs_property_enumerator.h
@@ -11,6 +11,7 @@
 // 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.
+
 #ifndef COBALT_SCRIPT_MOZJS_45_MOZJS_PROPERTY_ENUMERATOR_H_
 #define COBALT_SCRIPT_MOZJS_45_MOZJS_PROPERTY_ENUMERATOR_H_
 
diff --git a/src/cobalt/script/mozjs-45/mozjs_script_value_factory.cc b/src/cobalt/script/mozjs-45/mozjs_script_value_factory.cc
index 181b729..626106e 100644
--- a/src/cobalt/script/mozjs-45/mozjs_script_value_factory.cc
+++ b/src/cobalt/script/mozjs-45/mozjs_script_value_factory.cc
@@ -1,18 +1,16 @@
-/*
- * Copyright 2017 Google Inc. All Rights Reserved.
- *
- * 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.
- */
+// Copyright 2017 Google Inc. All Rights Reserved.
+//
+// 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.
 
 #include "cobalt/script/mozjs-45/mozjs_script_value_factory.h"
 
@@ -21,6 +19,7 @@
 namespace cobalt {
 namespace script {
 namespace mozjs {
+
 MozjsScriptValueFactory::MozjsScriptValueFactory(
     MozjsGlobalEnvironment* global_environment)
     : global_environment_(global_environment) {}
diff --git a/src/cobalt/script/mozjs-45/mozjs_script_value_factory.h b/src/cobalt/script/mozjs-45/mozjs_script_value_factory.h
index 4f7d02e..0780365 100644
--- a/src/cobalt/script/mozjs-45/mozjs_script_value_factory.h
+++ b/src/cobalt/script/mozjs-45/mozjs_script_value_factory.h
@@ -1,18 +1,16 @@
-/*
- * Copyright 2017 Google Inc. All Rights Reserved.
- *
- * 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.
- */
+// Copyright 2017 Google Inc. All Rights Reserved.
+//
+// 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.
 
 #ifndef COBALT_SCRIPT_MOZJS_45_MOZJS_SCRIPT_VALUE_FACTORY_H_
 #define COBALT_SCRIPT_MOZJS_45_MOZJS_SCRIPT_VALUE_FACTORY_H_
@@ -26,6 +24,7 @@
 namespace cobalt {
 namespace script {
 namespace mozjs {
+
 class MozjsScriptValueFactory : public ScriptValueFactory {
  public:
   explicit MozjsScriptValueFactory(MozjsGlobalEnvironment* global_environment);
@@ -42,9 +41,9 @@
     JSAutoRequest auto_request(context);
     JSAutoCompartment auto_compartment(context, global_object);
 
-    JS::RootedObject promise_wrapper(
-        context, PromiseWrapper::Create(context, global_object));
-    DCHECK(promise_wrapper);
+    JS::RootedValue promise_wrapper(context);
+    promise_wrapper.setObjectOrNull(
+        PromiseWrapper::Create(context, global_object));
     scoped_ptr<ScriptPromiseType> promise(
         new MozjsPromiseHolderType(context, promise_wrapper));
     return promise.Pass();
@@ -57,4 +56,5 @@
 }  // namespace mozjs
 }  // namespace script
 }  // namespace cobalt
+
 #endif  // COBALT_SCRIPT_MOZJS_45_MOZJS_SCRIPT_VALUE_FACTORY_H_
diff --git a/src/cobalt/script/mozjs-45/mozjs_source_code.cc b/src/cobalt/script/mozjs-45/mozjs_source_code.cc
index 7554260..85c936a 100644
--- a/src/cobalt/script/mozjs-45/mozjs_source_code.cc
+++ b/src/cobalt/script/mozjs-45/mozjs_source_code.cc
@@ -11,14 +11,17 @@
 // 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.
+
 #include "cobalt/script/mozjs-45/mozjs_source_code.h"
 
 namespace cobalt {
 namespace script {
+
 scoped_refptr<SourceCode> SourceCode::CreateSourceCode(
     const std::string& script_utf8,
     const base::SourceLocation& script_location) {
   return new mozjs::MozjsSourceCode(script_utf8, script_location);
 }
+
 }  // namespace script
 }  // namespace cobalt
diff --git a/src/cobalt/script/mozjs-45/mozjs_source_code.h b/src/cobalt/script/mozjs-45/mozjs_source_code.h
index 058bfdd..566b591 100644
--- a/src/cobalt/script/mozjs-45/mozjs_source_code.h
+++ b/src/cobalt/script/mozjs-45/mozjs_source_code.h
@@ -11,6 +11,7 @@
 // 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.
+
 #ifndef COBALT_SCRIPT_MOZJS_45_MOZJS_SOURCE_CODE_H_
 #define COBALT_SCRIPT_MOZJS_45_MOZJS_SOURCE_CODE_H_
 
diff --git a/src/cobalt/script/mozjs-45/mozjs_user_object_holder.h b/src/cobalt/script/mozjs-45/mozjs_user_object_holder.h
index f1fe6c4..6b8319c 100644
--- a/src/cobalt/script/mozjs-45/mozjs_user_object_holder.h
+++ b/src/cobalt/script/mozjs-45/mozjs_user_object_holder.h
@@ -11,6 +11,7 @@
 // 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.
+
 #ifndef COBALT_SCRIPT_MOZJS_45_MOZJS_USER_OBJECT_HOLDER_H_
 #define COBALT_SCRIPT_MOZJS_45_MOZJS_USER_OBJECT_HOLDER_H_
 
@@ -46,11 +47,6 @@
       : context_(NULL),
         prevent_garbage_collection_count_(0) {}
 
-  MozjsUserObjectHolder(JSContext* context, JS::HandleObject object)
-      : context_(context),
-        handle_(MozjsUserObjectType(context, object)),
-        prevent_garbage_collection_count_(0) {}
-
   MozjsUserObjectHolder(JSContext* context, JS::HandleValue value)
       : context_(context),
         handle_(MozjsUserObjectType(context, value)),
@@ -97,7 +93,7 @@
     }
   }
 
-  void AllowGarbageCollection() {
+  void AllowGarbageCollection() OVERRIDE {
     if (--prevent_garbage_collection_count_ == 0 && handle_) {
       JSAutoRequest auto_request(context_);
       persistent_root_ = base::nullopt;
diff --git a/src/cobalt/script/mozjs-45/mozjs_value_handle.h b/src/cobalt/script/mozjs-45/mozjs_value_handle.h
index fae1ae7..0a30572 100644
--- a/src/cobalt/script/mozjs-45/mozjs_value_handle.h
+++ b/src/cobalt/script/mozjs-45/mozjs_value_handle.h
@@ -26,7 +26,7 @@
 namespace script {
 namespace mozjs {
 
-// A wrapper around a JS::Value that can be passed into Cobalt as an script
+// A wrapper around a JS::Value that can be passed into Cobalt as a script
 // value object.
 //
 // An ValueHandle is never passed into Cobalt as-is, but only when wrapped as a
@@ -39,9 +39,8 @@
   bool WasCollected() const { return handle_.WasCollected(); }
 
  private:
-  MozjsValueHandle(JSContext* context, JS::HandleValue object)
-      : handle_(context, object) {}
-  ~MozjsValueHandle() {}
+  MozjsValueHandle(JSContext* context, JS::HandleValue value)
+      : handle_(context, value) {}
 
   WeakHeapObject handle_;
 
diff --git a/src/cobalt/script/mozjs-45/mozjs_wrapper_handle.h b/src/cobalt/script/mozjs-45/mozjs_wrapper_handle.h
index 7fc5f0f..05b86ad 100644
--- a/src/cobalt/script/mozjs-45/mozjs_wrapper_handle.h
+++ b/src/cobalt/script/mozjs-45/mozjs_wrapper_handle.h
@@ -11,6 +11,7 @@
 // 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.
+
 #ifndef COBALT_SCRIPT_MOZJS_45_MOZJS_WRAPPER_HANDLE_H_
 #define COBALT_SCRIPT_MOZJS_45_MOZJS_WRAPPER_HANDLE_H_
 
diff --git a/src/cobalt/script/mozjs-45/native_promise.h b/src/cobalt/script/mozjs-45/native_promise.h
index fbe330c..081231d 100644
--- a/src/cobalt/script/mozjs-45/native_promise.h
+++ b/src/cobalt/script/mozjs-45/native_promise.h
@@ -1,18 +1,16 @@
-/*
- * Copyright 2017 Google Inc. All Rights Reserved.
- *
- * 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.
- */
+// Copyright 2017 Google Inc. All Rights Reserved.
+//
+// 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.
 
 #ifndef COBALT_SCRIPT_MOZJS_45_NATIVE_PROMISE_H_
 #define COBALT_SCRIPT_MOZJS_45_NATIVE_PROMISE_H_
@@ -80,16 +78,10 @@
   }
 
  protected:
-  NativePromiseBase(JSContext* context, JS::HandleObject resolver_object)
-      : context_(context) {
-    promise_resolver_.emplace(context, resolver_object);
-  }
-
   NativePromiseBase(JSContext* context, JS::HandleValue resolver_value)
       : context_(context) {
     DCHECK(resolver_value.isObject());
-    JS::RootedObject resolver_object(context, &resolver_value.toObject());
-    promise_resolver_.emplace(context, resolver_object);
+    promise_resolver_.emplace(context, resolver_value);
   }
 
   JSContext* context_;
@@ -100,9 +92,6 @@
 template <typename T>
 class NativePromise : public NativePromiseBase<T> {
  public:
-  NativePromise(JSContext* context, JS::HandleObject resolver_object)
-      : NativePromiseBase<T>(context, resolver_object) {}
-
   NativePromise(JSContext* context, JS::HandleValue resolver_value)
       : NativePromiseBase<T>(context, resolver_value) {}
 
@@ -123,9 +112,6 @@
 template <>
 class NativePromise<void> : public NativePromiseBase<void> {
  public:
-  NativePromise(JSContext* context, JS::HandleObject resolver_object)
-      : NativePromiseBase<void>(context, resolver_object) {}
-
   NativePromise(JSContext* context, JS::HandleValue resolver_value)
       : NativePromiseBase<void>(context, resolver_value) {}
 
diff --git a/src/cobalt/script/mozjs-45/promise_wrapper.cc b/src/cobalt/script/mozjs-45/promise_wrapper.cc
index 46af70f..c972ed1 100644
--- a/src/cobalt/script/mozjs-45/promise_wrapper.cc
+++ b/src/cobalt/script/mozjs-45/promise_wrapper.cc
@@ -1,18 +1,16 @@
-/*
- * Copyright 2017 Google Inc. All Rights Reserved.
- *
- * 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.
- */
+// Copyright 2017 Google Inc. All Rights Reserved.
+//
+// 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.
 
 #include "cobalt/script/mozjs-45/promise_wrapper.h"
 
@@ -204,9 +202,10 @@
 }
 
 PromiseWrapper::PromiseWrapper(JSContext* context,
-                               JS::HandleObject promise_wrapper)
+                               JS::HandleValue promise_wrapper)
     : context_(context), weak_promise_wrapper_(context, promise_wrapper) {
-  DCHECK_EQ(JS_GetClass(promise_wrapper), &native_promise_class);
+  DCHECK(promise_wrapper.isObject());
+  DCHECK_EQ(JS_GetClass(&promise_wrapper.toObject()), &native_promise_class);
 }
 
 }  // namespace mozjs
diff --git a/src/cobalt/script/mozjs-45/promise_wrapper.h b/src/cobalt/script/mozjs-45/promise_wrapper.h
index d77d6a9..1f5420d 100644
--- a/src/cobalt/script/mozjs-45/promise_wrapper.h
+++ b/src/cobalt/script/mozjs-45/promise_wrapper.h
@@ -1,18 +1,16 @@
-/*
- * Copyright 2017 Google Inc. All Rights Reserved.
- *
- * 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.
- */
+// Copyright 2017 Google Inc. All Rights Reserved.
+//
+// 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.
 
 #ifndef COBALT_SCRIPT_MOZJS_45_PROMISE_WRAPPER_H_
 #define COBALT_SCRIPT_MOZJS_45_PROMISE_WRAPPER_H_
@@ -34,7 +32,7 @@
   // Promise constructor on |global_object|. Returns NULL on failure.
   static JSObject* Create(JSContext* context, JS::HandleObject global_object);
 
-  PromiseWrapper(JSContext* context, JS::HandleObject promise_wrapper);
+  PromiseWrapper(JSContext* context, JS::HandleValue promise_wrapper);
 
   const WeakHeapObject& get() const { return weak_promise_wrapper_; }
   JSObject* GetPromise() const;
diff --git a/src/cobalt/script/mozjs-45/proxy_handler.h b/src/cobalt/script/mozjs-45/proxy_handler.h
index 8781e4b..4a38ff6 100644
--- a/src/cobalt/script/mozjs-45/proxy_handler.h
+++ b/src/cobalt/script/mozjs-45/proxy_handler.h
@@ -11,6 +11,7 @@
 // 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.
+
 #ifndef COBALT_SCRIPT_MOZJS_45_PROXY_HANDLER_H_
 #define COBALT_SCRIPT_MOZJS_45_PROXY_HANDLER_H_
 
diff --git a/src/cobalt/script/mozjs-45/referenced_object_map.h b/src/cobalt/script/mozjs-45/referenced_object_map.h
index e0df05a..134a221 100644
--- a/src/cobalt/script/mozjs-45/referenced_object_map.h
+++ b/src/cobalt/script/mozjs-45/referenced_object_map.h
@@ -11,6 +11,7 @@
 // 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.
+
 #ifndef COBALT_SCRIPT_MOZJS_45_REFERENCED_OBJECT_MAP_H_
 #define COBALT_SCRIPT_MOZJS_45_REFERENCED_OBJECT_MAP_H_
 
diff --git a/src/cobalt/script/mozjs-45/type_traits.h b/src/cobalt/script/mozjs-45/type_traits.h
index d685fd6..69d1bd0 100644
--- a/src/cobalt/script/mozjs-45/type_traits.h
+++ b/src/cobalt/script/mozjs-45/type_traits.h
@@ -23,7 +23,7 @@
 struct TypeTraits {
   // The type to convert into from a JS Value in the bindings implementation.
   typedef T ConversionType;
-  // Type type returned from a Cobalt implementation of a bound function.
+  // The type returned from a Cobalt implementation of a bound function.
   typedef T ReturnType;
 };
 
diff --git a/src/cobalt/script/mozjs-45/union_type_conversion_forward.h b/src/cobalt/script/mozjs-45/union_type_conversion_forward.h
index 2471c73..17b5674 100644
--- a/src/cobalt/script/mozjs-45/union_type_conversion_forward.h
+++ b/src/cobalt/script/mozjs-45/union_type_conversion_forward.h
@@ -20,8 +20,8 @@
 #define COBALT_SCRIPT_MOZJS_45_UNION_TYPE_CONVERSION_FORWARD_H_
 
 #include "cobalt/script/mozjs-45/mozjs_exception_state.h"
-#include "cobalt/script/mozjs-45/mozjs_object_handle.h"
 #include "cobalt/script/mozjs-45/mozjs_user_object_holder.h"
+#include "cobalt/script/mozjs-45/mozjs_value_handle.h"
 #include "cobalt/script/mozjs-45/type_traits.h"
 #include "cobalt/script/union_type.h"
 
diff --git a/src/cobalt/script/mozjs-45/union_type_conversion_forward.h.pump b/src/cobalt/script/mozjs-45/union_type_conversion_forward.h.pump
index a70a1ef..237cd7d 100644
--- a/src/cobalt/script/mozjs-45/union_type_conversion_forward.h.pump
+++ b/src/cobalt/script/mozjs-45/union_type_conversion_forward.h.pump
@@ -25,8 +25,8 @@
 #define COBALT_SCRIPT_MOZJS_45_UNION_TYPE_CONVERSION_FORWARD_H_
 
 #include "cobalt/script/mozjs-45/mozjs_exception_state.h"
-#include "cobalt/script/mozjs-45/mozjs_object_handle.h"
 #include "cobalt/script/mozjs-45/mozjs_user_object_holder.h"
+#include "cobalt/script/mozjs-45/mozjs_value_handle.h"
 #include "cobalt/script/mozjs-45/type_traits.h"
 #include "cobalt/script/union_type.h"
 
diff --git a/src/cobalt/script/mozjs-45/union_type_conversion_impl.h b/src/cobalt/script/mozjs-45/union_type_conversion_impl.h
index 14e5117..6ba61a9 100644
--- a/src/cobalt/script/mozjs-45/union_type_conversion_impl.h
+++ b/src/cobalt/script/mozjs-45/union_type_conversion_impl.h
@@ -22,8 +22,8 @@
 #include "cobalt/base/type_id.h"
 #include "cobalt/script/mozjs-45/mozjs_exception_state.h"
 #include "cobalt/script/mozjs-45/mozjs_global_environment.h"
-#include "cobalt/script/mozjs-45/mozjs_object_handle.h"
 #include "cobalt/script/mozjs-45/mozjs_user_object_holder.h"
+#include "cobalt/script/mozjs-45/mozjs_value_handle.h"
 #include "cobalt/script/mozjs-45/type_traits.h"
 #include "cobalt/script/union_type.h"
 
diff --git a/src/cobalt/script/mozjs-45/union_type_conversion_impl.h.pump b/src/cobalt/script/mozjs-45/union_type_conversion_impl.h.pump
index 051d476..05f2238 100644
--- a/src/cobalt/script/mozjs-45/union_type_conversion_impl.h.pump
+++ b/src/cobalt/script/mozjs-45/union_type_conversion_impl.h.pump
@@ -27,7 +27,7 @@
 #include "cobalt/base/type_id.h"
 #include "cobalt/script/mozjs-45/mozjs_exception_state.h"
 #include "cobalt/script/mozjs-45/mozjs_global_environment.h"
-#include "cobalt/script/mozjs-45/mozjs_object_handle.h"
+#include "cobalt/script/mozjs-45/mozjs_value_handle.h"
 #include "cobalt/script/mozjs-45/mozjs_user_object_holder.h"
 #include "cobalt/script/mozjs-45/type_traits.h"
 #include "cobalt/script/union_type.h"
diff --git a/src/cobalt/script/mozjs-45/weak_heap_object.cc b/src/cobalt/script/mozjs-45/weak_heap_object.cc
index 8c91931..d6d8ddb 100644
--- a/src/cobalt/script/mozjs-45/weak_heap_object.cc
+++ b/src/cobalt/script/mozjs-45/weak_heap_object.cc
@@ -29,14 +29,6 @@
   Initialize(global_environment->weak_object_manager(), value);
 }
 
-WeakHeapObject::WeakHeapObject(JSContext* context, JS::HandleObject object)
-    : was_collected_(false) {
-  MozjsGlobalEnvironment* global_environment =
-      MozjsGlobalEnvironment::GetFromContext(context);
-  Initialize(global_environment->weak_object_manager(),
-             JS::ObjectValue(*object));
-}
-
 WeakHeapObject::WeakHeapObject(const WeakHeapObject& other)
     : was_collected_(other.was_collected_) {
   Initialize(other.weak_object_manager_, other.value_);
@@ -58,13 +50,10 @@
   return value_.isObject();
 }
 
-bool WeakHeapObject::IsGcThing() const {
-  // We have to check IsNull(), because null is apparently a GC Thing.
-  return (!IsNull() && value_.isGCThing());
-}
+bool WeakHeapObject::IsGcThing() const { return value_.isGCThing(); }
 
 bool WeakHeapObject::WasCollected() const {
-  return (was_collected_ && IsNull());
+  return (was_collected_ && value_.isNullOrUndefined());
 }
 
 WeakHeapObject::~WeakHeapObject() {
@@ -79,16 +68,13 @@
   weak_object_manager_ = weak_heap_object_manager;
   value_ = value;
 
-  // Don't bother registering if not a GC thing.
-  if (IsGcThing()) {
+  // Only register GCThings, however don't bother registering if null or
+  // undefined.
+  if (IsGcThing() && !value_.isNullOrUndefined()) {
     weak_object_manager_->StartTracking(this);
   }
 }
 
-bool WeakHeapObject::IsNull() const {
-  return value_.isNullOrUndefined();
-}
-
 void WeakHeapObject::UpdateWeakPointerAfterGc() {
   if (js::gc::IsAboutToBeFinalizedUnbarriered(value_.unsafeGet())) {
     DCHECK(IsGcThing());
diff --git a/src/cobalt/script/mozjs-45/weak_heap_object.h b/src/cobalt/script/mozjs-45/weak_heap_object.h
index 53ec235..1240e98 100644
--- a/src/cobalt/script/mozjs-45/weak_heap_object.h
+++ b/src/cobalt/script/mozjs-45/weak_heap_object.h
@@ -11,6 +11,7 @@
 // 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.
+
 #ifndef COBALT_SCRIPT_MOZJS_45_WEAK_HEAP_OBJECT_H_
 #define COBALT_SCRIPT_MOZJS_45_WEAK_HEAP_OBJECT_H_
 
@@ -27,7 +28,6 @@
 class WeakHeapObject {
  public:
   WeakHeapObject(JSContext* context, JS::HandleValue value);
-  WeakHeapObject(JSContext* context, JS::HandleObject object);
   WeakHeapObject(const WeakHeapObject& other);
 
   WeakHeapObject& operator=(const WeakHeapObject& rhs);
@@ -49,7 +49,6 @@
   void Initialize(WeakHeapObjectManager* weak_heap_object_manager,
                   const JS::Value& value);
 
-  bool IsNull() const;
   void UpdateWeakPointerAfterGc();
 
   WeakHeapObjectManager* weak_object_manager_;
diff --git a/src/cobalt/script/mozjs-45/weak_heap_object_manager.h b/src/cobalt/script/mozjs-45/weak_heap_object_manager.h
index 4b8558c..159b0de 100644
--- a/src/cobalt/script/mozjs-45/weak_heap_object_manager.h
+++ b/src/cobalt/script/mozjs-45/weak_heap_object_manager.h
@@ -11,6 +11,7 @@
 // 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.
+
 #ifndef COBALT_SCRIPT_MOZJS_45_WEAK_HEAP_OBJECT_MANAGER_H_
 #define COBALT_SCRIPT_MOZJS_45_WEAK_HEAP_OBJECT_MANAGER_H_
 
diff --git a/src/cobalt/script/mozjs-45/wrapper_factory.cc b/src/cobalt/script/mozjs-45/wrapper_factory.cc
index dd429b9..a013dd3 100644
--- a/src/cobalt/script/mozjs-45/wrapper_factory.cc
+++ b/src/cobalt/script/mozjs-45/wrapper_factory.cc
@@ -11,6 +11,7 @@
 // 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.
+
 #include "cobalt/script/mozjs-45/wrapper_factory.h"
 
 #include <utility>
diff --git a/src/cobalt/script/mozjs-45/wrapper_factory.h b/src/cobalt/script/mozjs-45/wrapper_factory.h
index 043b96c..783841b 100644
--- a/src/cobalt/script/mozjs-45/wrapper_factory.h
+++ b/src/cobalt/script/mozjs-45/wrapper_factory.h
@@ -11,6 +11,7 @@
 // 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.
+
 #ifndef COBALT_SCRIPT_MOZJS_45_WRAPPER_FACTORY_H_
 #define COBALT_SCRIPT_MOZJS_45_WRAPPER_FACTORY_H_
 
diff --git a/src/cobalt/script/mozjs-45/wrapper_private.h b/src/cobalt/script/mozjs-45/wrapper_private.h
index 642395a..a4dc740 100644
--- a/src/cobalt/script/mozjs-45/wrapper_private.h
+++ b/src/cobalt/script/mozjs-45/wrapper_private.h
@@ -11,6 +11,7 @@
 // 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.
+
 #ifndef COBALT_SCRIPT_MOZJS_45_WRAPPER_PRIVATE_H_
 #define COBALT_SCRIPT_MOZJS_45_WRAPPER_PRIVATE_H_
 
diff --git a/src/cobalt/script/opaque_handle.h b/src/cobalt/script/opaque_handle.h
deleted file mode 100644
index 57c7f0a..0000000
--- a/src/cobalt/script/opaque_handle.h
+++ /dev/null
@@ -1,36 +0,0 @@
-// Copyright 2014 Google Inc. All Rights Reserved.
-//
-// 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.
-#ifndef COBALT_SCRIPT_OPAQUE_HANDLE_H_
-#define COBALT_SCRIPT_OPAQUE_HANDLE_H_
-
-#include "cobalt/script/script_value.h"
-
-namespace cobalt {
-namespace script {
-
-// A handle to an object that is managed by the JavaScript Engine. There should
-// be no need for Cobalt code to operate on this handle, aside from managing its
-// lifetime.
-class OpaqueHandle {
- protected:
-  OpaqueHandle() {}
-  virtual ~OpaqueHandle() {}
-};
-
-typedef ScriptValue<OpaqueHandle> OpaqueHandleHolder;
-
-}  // namespace script
-}  // namespace cobalt
-
-#endif  // COBALT_SCRIPT_OPAQUE_HANDLE_H_
diff --git a/src/cobalt/script/promise.h b/src/cobalt/script/promise.h
index a3e312c..857c348 100644
--- a/src/cobalt/script/promise.h
+++ b/src/cobalt/script/promise.h
@@ -1,18 +1,16 @@
-/*
- * Copyright 2017 Google Inc. All Rights Reserved.
- *
- * 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.
- */
+// Copyright 2017 Google Inc. All Rights Reserved.
+//
+// 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.
 
 #ifndef COBALT_SCRIPT_PROMISE_H_
 #define COBALT_SCRIPT_PROMISE_H_
@@ -61,4 +59,5 @@
 
 }  // namespace script
 }  // namespace cobalt
+
 #endif  // COBALT_SCRIPT_PROMISE_H_
diff --git a/src/cobalt/script/property_enumerator.h b/src/cobalt/script/property_enumerator.h
index 3bdf8cb..c4c6985 100644
--- a/src/cobalt/script/property_enumerator.h
+++ b/src/cobalt/script/property_enumerator.h
@@ -11,6 +11,7 @@
 // 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.
+
 #ifndef COBALT_SCRIPT_PROPERTY_ENUMERATOR_H_
 #define COBALT_SCRIPT_PROPERTY_ENUMERATOR_H_
 
diff --git a/src/cobalt/script/scope.h b/src/cobalt/script/scope.h
index 62de712..606dd89 100644
--- a/src/cobalt/script/scope.h
+++ b/src/cobalt/script/scope.h
@@ -11,6 +11,7 @@
 // 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.
+
 #ifndef COBALT_SCRIPT_SCOPE_H_
 #define COBALT_SCRIPT_SCOPE_H_
 
@@ -19,7 +20,7 @@
 #include "base/logging.h"
 #include "base/memory/scoped_ptr.h"
 #include "base/optional.h"
-#include "cobalt/script/opaque_handle.h"
+#include "cobalt/script/value_handle.h"
 
 namespace cobalt {
 namespace script {
@@ -42,7 +43,7 @@
 
   // An opaque handle to the underlying JavaScript object encapsulating the
   // scope.
-  virtual const OpaqueHandleHolder* GetObject() = 0;
+  virtual const ValueHandleHolder* GetObject() = 0;
 
   // The type of the scope object. One of the enumerated values in |Type|.
   // Devtools expects a string, which can be obtained from the
diff --git a/src/cobalt/script/script.gyp b/src/cobalt/script/script.gyp
index 34a7c4e..65204ee 100644
--- a/src/cobalt/script/script.gyp
+++ b/src/cobalt/script/script.gyp
@@ -21,21 +21,39 @@
       'type': 'static_library',
       'sources': [
         'call_frame.h',
+        'callback_function.h',
+        'callback_interface_traits.h',
+        'environment_settings.h',
         'error_report.h',
         'exception_message.cc',
         'exception_message.h',
         'execution_state.cc',
         'execution_state.h',
+        'fake_global_environment.h',
+        'fake_script_runner.h',
+        'global_environment.h',
         'global_object_proxy.h',
+        'javascript_engine.h',
+        'logging_exception_state.h',
+        'promise.h',
+        'property_enumerator.h',
         'scope.h',
         'script_debugger.h',
+        'script_exception.h',
         'script_runner.cc',
         'script_runner.h',
+        'script_value.h',
+        'script_value_factory.h',
+        'script_value_factory_instantiations.h',
+        'sequence.h',
         'source_code.h',
         'source_provider.h',
         'stack_frame.cc',
         'stack_frame.h',
+        'union_type.h',
+        'union_type_internal.h',
         'util/stack_trace_helpers.h',
+        'value_handle.h',
         'wrappable.h',
       ],
       'dependencies': [
@@ -48,6 +66,7 @@
       'type': 'static_library',
       'sources': [
         'standalone_javascript_runner.cc',
+        'standalone_javascript_runner.h',
       ],
     },
   ],
diff --git a/src/cobalt/script/script_debugger.h b/src/cobalt/script/script_debugger.h
index 17cfb5c..afa39bf 100644
--- a/src/cobalt/script/script_debugger.h
+++ b/src/cobalt/script/script_debugger.h
@@ -11,6 +11,7 @@
 // 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.
+
 #ifndef COBALT_SCRIPT_SCRIPT_DEBUGGER_H_
 #define COBALT_SCRIPT_SCRIPT_DEBUGGER_H_
 
diff --git a/src/cobalt/script/script_exception.h b/src/cobalt/script/script_exception.h
index 4d85f78..21d4f10 100644
--- a/src/cobalt/script/script_exception.h
+++ b/src/cobalt/script/script_exception.h
@@ -11,6 +11,7 @@
 // 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.
+
 #ifndef COBALT_SCRIPT_SCRIPT_EXCEPTION_H_
 #define COBALT_SCRIPT_SCRIPT_EXCEPTION_H_
 
diff --git a/src/cobalt/script/script_runner.h b/src/cobalt/script/script_runner.h
index fb2eb27..870451b 100644
--- a/src/cobalt/script/script_runner.h
+++ b/src/cobalt/script/script_runner.h
@@ -11,6 +11,7 @@
 // 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.
+
 #ifndef COBALT_SCRIPT_SCRIPT_RUNNER_H_
 #define COBALT_SCRIPT_SCRIPT_RUNNER_H_
 
diff --git a/src/cobalt/script/script_value.h b/src/cobalt/script/script_value.h
index 7b9edac..fcca2c4 100644
--- a/src/cobalt/script/script_value.h
+++ b/src/cobalt/script/script_value.h
@@ -1,18 +1,16 @@
-/*
- * Copyright 2015 Google Inc. All Rights Reserved.
- *
- * 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.
- */
+// Copyright 2015 Google Inc. All Rights Reserved.
+//
+// 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.
 
 #ifndef COBALT_SCRIPT_SCRIPT_VALUE_H_
 #define COBALT_SCRIPT_SCRIPT_VALUE_H_
diff --git a/src/cobalt/script/script_value_factory.h b/src/cobalt/script/script_value_factory.h
index 3c7884b..79437ef 100644
--- a/src/cobalt/script/script_value_factory.h
+++ b/src/cobalt/script/script_value_factory.h
@@ -1,18 +1,16 @@
-/*
- * Copyright 2017 Google Inc. All Rights Reserved.
- *
- * 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.
- */
+// Copyright 2017 Google Inc. All Rights Reserved.
+//
+// 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.
 
 #ifndef COBALT_SCRIPT_SCRIPT_VALUE_FACTORY_H_
 #define COBALT_SCRIPT_SCRIPT_VALUE_FACTORY_H_
@@ -57,4 +55,5 @@
 
 }  // namespace script
 }  // namespace cobalt
+
 #endif  // COBALT_SCRIPT_SCRIPT_VALUE_FACTORY_H_
diff --git a/src/cobalt/script/script_value_factory_instantiations.h b/src/cobalt/script/script_value_factory_instantiations.h
index 3053837..9bd749d 100644
--- a/src/cobalt/script/script_value_factory_instantiations.h
+++ b/src/cobalt/script/script_value_factory_instantiations.h
@@ -1,18 +1,16 @@
-/*
- * Copyright 2017 Google Inc. All Rights Reserved.
- *
- * 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.
- */
+// Copyright 2017 Google Inc. All Rights Reserved.
+//
+// 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.
 
 #ifndef COBALT_SCRIPT_SCRIPT_VALUE_FACTORY_INSTANTIATIONS_H_
 #define COBALT_SCRIPT_SCRIPT_VALUE_FACTORY_INSTANTIATIONS_H_
@@ -50,4 +48,5 @@
 
 }  // namespace script
 }  // namespace cobalt
+
 #endif  // COBALT_SCRIPT_SCRIPT_VALUE_FACTORY_INSTANTIATIONS_H_
diff --git a/src/cobalt/script/source_code.h b/src/cobalt/script/source_code.h
index b37d6a4..08d2cee 100644
--- a/src/cobalt/script/source_code.h
+++ b/src/cobalt/script/source_code.h
@@ -11,6 +11,7 @@
 // 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.
+
 #ifndef COBALT_SCRIPT_SOURCE_CODE_H_
 #define COBALT_SCRIPT_SOURCE_CODE_H_
 
diff --git a/src/cobalt/script/source_provider.h b/src/cobalt/script/source_provider.h
index de3a48a..b3a28c9 100644
--- a/src/cobalt/script/source_provider.h
+++ b/src/cobalt/script/source_provider.h
@@ -11,6 +11,7 @@
 // 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.
+
 #ifndef COBALT_SCRIPT_SOURCE_PROVIDER_H_
 #define COBALT_SCRIPT_SOURCE_PROVIDER_H_
 
diff --git a/src/cobalt/script/standalone_javascript_runner.h b/src/cobalt/script/standalone_javascript_runner.h
index a7ffb7b..826116b 100644
--- a/src/cobalt/script/standalone_javascript_runner.h
+++ b/src/cobalt/script/standalone_javascript_runner.h
@@ -11,6 +11,7 @@
 // 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.
+
 #ifndef COBALT_SCRIPT_STANDALONE_JAVASCRIPT_RUNNER_H_
 #define COBALT_SCRIPT_STANDALONE_JAVASCRIPT_RUNNER_H_
 
diff --git a/src/cobalt/script/union_type.h b/src/cobalt/script/union_type.h
index 6b9b64d..b83773e 100644
--- a/src/cobalt/script/union_type.h
+++ b/src/cobalt/script/union_type.h
@@ -2,6 +2,7 @@
 //     pump.py union_type.h.pump
 // DO NOT EDIT BY HAND!!!
 
+
 // Copyright 2015 Google Inc. All Rights Reserved.
 //
 // Licensed under the Apache License, Version 2.0 (the "License");
@@ -212,6 +213,7 @@
   return stream;
 }
 
+
 template <typename T1, typename T2, typename T3>
 class UnionType3 {
  public:
@@ -403,6 +405,7 @@
   return stream;
 }
 
+
 template <typename T1, typename T2, typename T3, typename T4>
 class UnionType4 {
  public:
diff --git a/src/cobalt/script/union_type.h.pump b/src/cobalt/script/union_type.h.pump
index 535a2db..e9f60bf 100644
--- a/src/cobalt/script/union_type.h.pump
+++ b/src/cobalt/script/union_type.h.pump
@@ -22,8 +22,8 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-#ifndef SCRIPT_UNION_TYPE_H_
-#define SCRIPT_UNION_TYPE_H_
+#ifndef COBALT_SCRIPT_UNION_TYPE_H_
+#define COBALT_SCRIPT_UNION_TYPE_H_
 
 // Implementation of IDL union types.
 // http://heycam.github.io/webidl/#idl-union
@@ -227,4 +227,4 @@
 }  // namespace script
 }  // namespace cobalt
 
-#endif  // SCRIPT_UNION_TYPE_H_
+#endif  // COBALT_SCRIPT_UNION_TYPE_H_
diff --git a/src/cobalt/script/v8c/callback_function_conversion.h b/src/cobalt/script/v8c/callback_function_conversion.h
new file mode 100644
index 0000000..6c509ca
--- /dev/null
+++ b/src/cobalt/script/v8c/callback_function_conversion.h
@@ -0,0 +1,88 @@
+// Copyright 2017 Google Inc. All Rights Reserved.
+//
+// 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.
+
+#ifndef COBALT_SCRIPT_V8C_CALLBACK_FUNCTION_CONVERSION_H_
+#define COBALT_SCRIPT_V8C_CALLBACK_FUNCTION_CONVERSION_H_
+
+#include "base/logging.h"
+#include "cobalt/base/polymorphic_downcast.h"
+#include "cobalt/script/logging_exception_state.h"
+#include "cobalt/script/script_value.h"
+#include "cobalt/script/v8c/conversion_helpers.h"
+#include "cobalt/script/v8c/v8c_callback_function.h"
+#include "v8/include/v8.h"
+
+namespace cobalt {
+namespace script {
+namespace v8c {
+
+// CallbackFunction -> JSValue
+template <typename Signature>
+void ToJSValue(
+    v8::Isolate* isolate,
+    const ScriptValue<CallbackFunction<Signature>>* callback_function,
+    v8::Local<v8::Value>* out_value) {
+  if (!callback_function) {
+    *out_value = v8::Null(isolate);
+    return;
+  }
+
+  // Downcast to V8cUserObjectHolder<T> so we can get the underlying v8::Object.
+  typedef V8cUserObjectHolder<V8cCallbackFunction<Signature>>
+      V8cUserObjectHolderClass;
+  const V8cUserObjectHolderClass* user_object_holder =
+      base::polymorphic_downcast<const V8cUserObjectHolderClass*>(
+          callback_function);
+
+  *out_value = user_object_holder->v8_value();
+}
+
+// JSValue -> CallbackFunction
+template <typename Signature>
+inline void FromJSValue(v8::Isolate* isolate, v8::Local<v8::Value> value,
+                        int conversion_flags, ExceptionState* exception_state,
+                        V8cUserObjectHolder<V8cCallbackFunction<Signature>>*
+                            out_callback_function) {
+  typedef V8cUserObjectHolder<V8cCallbackFunction<Signature>>
+      V8cCallbackHolderClass;
+
+  DCHECK_EQ(conversion_flags & ~kConversionFlagsCallbackFunction, 0)
+      << "Unexpected conversion flags.";
+
+  if (value->IsNull()) {
+    if (!(conversion_flags & kConversionFlagNullable)) {
+      exception_state->SetSimpleException(kNotNullableType);
+    }
+    // If it is a nullable type, just return.
+    return;
+  }
+
+  // https://www.w3.org/TR/WebIDL/#es-callback-function
+  // 1. If V is not a Function object, throw a TypeError
+  if (!value->IsFunction()) {
+    exception_state->SetSimpleException(kNotFunctionValue);
+    return;
+  }
+
+  V8cGlobalEnvironment* env =
+      static_cast<V8cGlobalEnvironment*>(isolate->GetData(0));
+  DCHECK(env);
+  *out_callback_function = V8cCallbackHolderClass(env, value);
+}
+
+}  // namespace v8c
+}  // namespace script
+}  // namespace cobalt
+
+#endif  // COBALT_SCRIPT_V8C_CALLBACK_FUNCTION_CONVERSION_H_
diff --git a/src/cobalt/script/v8c/conversion_helpers.cc b/src/cobalt/script/v8c/conversion_helpers.cc
new file mode 100644
index 0000000..9f6f4ad
--- /dev/null
+++ b/src/cobalt/script/v8c/conversion_helpers.cc
@@ -0,0 +1,46 @@
+// Copyright 2017 Google Inc. All Rights Reserved.
+//
+// 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.
+
+#include "cobalt/script/v8c/conversion_helpers.h"
+#include "nb/memory_scope.h"
+#include "v8/include/v8.h"
+
+namespace cobalt {
+namespace script {
+namespace v8c {
+
+// JSValue -> std::string
+void FromJSValue(v8::Isolate* isolate, v8::Local<v8::Value> value,
+                 int conversion_flags, ExceptionState* exception_state,
+                 std::string* out_string) {
+  NOTIMPLEMENTED();
+}
+
+// ValueHandle -> JSValue
+void ToJSValue(v8::Isolate* isolate,
+               const ValueHandleHolder* value_handle_holder,
+               v8::Local<v8::Value>* out_value) {
+  NOTIMPLEMENTED();
+}
+
+// JSValue -> ValueHandle
+void FromJSValue(v8::Isolate* isolate, v8::Local<v8::Value> value,
+                 int conversion_flags, ExceptionState* exception_state,
+                 V8cValueHandleHolder* out_holder) {
+  NOTIMPLEMENTED();
+}
+
+}  // namespace v8c
+}  // namespace script
+}  // namespace cobalt
diff --git a/src/cobalt/script/v8c/conversion_helpers.h b/src/cobalt/script/v8c/conversion_helpers.h
new file mode 100644
index 0000000..13a0fd4
--- /dev/null
+++ b/src/cobalt/script/v8c/conversion_helpers.h
@@ -0,0 +1,380 @@
+// Copyright 2017 Google Inc. All Rights Reserved.
+//
+// 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.
+
+#ifndef COBALT_SCRIPT_V8C_CONVERSION_HELPERS_H_
+#define COBALT_SCRIPT_V8C_CONVERSION_HELPERS_H_
+
+#include <limits>
+#include <string>
+#include <vector>
+
+#include "base/logging.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/optional.h"
+#include "base/stringprintf.h"
+#include "cobalt/base/compiler.h"
+#include "cobalt/base/enable_if.h"
+#include "cobalt/base/token.h"
+#include "cobalt/script/sequence.h"
+#include "cobalt/script/v8c/type_traits.h"
+#include "cobalt/script/v8c/union_type_conversion_forward.h"
+#include "cobalt/script/v8c/v8c_callback_interface_holder.h"
+#include "cobalt/script/v8c/v8c_global_environment.h"
+#include "cobalt/script/v8c/v8c_user_object_holder.h"
+#include "cobalt/script/v8c/v8c_value_handle.h"
+#include "cobalt/script/value_handle.h"
+#include "nb/memory_scope.h"
+#include "v8/include/v8.h"
+
+namespace cobalt {
+namespace script {
+namespace v8c {
+
+// Flags that can be used as a bitmask for special conversion behaviour.
+enum ConversionFlags {
+  kNoConversionFlags = 0,
+  kConversionFlagRestricted = 1 << 0,
+  kConversionFlagNullable = 1 << 1,
+  kConversionFlagTreatNullAsEmptyString = 1 << 2,
+  kConversionFlagTreatUndefinedAsEmptyString = 1 << 3,
+  kConversionFlagClamped = 1 << 4,
+  kConversionFlagObjectOnly = 1 << 5,
+
+  // Valid conversion flags for numeric values.
+  kConversionFlagsNumeric = kConversionFlagRestricted | kConversionFlagClamped,
+
+  // Valid conversion flags for string types.
+  kConversionFlagsString = kConversionFlagTreatNullAsEmptyString |
+                           kConversionFlagTreatUndefinedAsEmptyString,
+
+  // Valid conversion flags for objects.
+  kConversionFlagsObject = kConversionFlagNullable,
+
+  // Valid conversion flags for ValueHandles.
+  kConversionFlagsValueHandle =
+      kConversionFlagObjectOnly | kConversionFlagNullable,
+
+  // Valid conversion flags for callback functions.
+  kConversionFlagsCallbackFunction = kConversionFlagNullable,
+
+  // Valid conversion flags for callback interfaces.
+  kConversionFlagsCallbackInterface = kConversionFlagNullable,
+};
+
+// std::string -> JSValue
+inline void ToJSValue(v8::Isolate* isolate, const std::string& in_string,
+                      v8::Local<v8::Value>* out_value) {
+  NOTIMPLEMENTED();
+}
+
+// JSValue -> std::string
+void FromJSValue(v8::Isolate* isolate, v8::Local<v8::Value> value,
+                 int conversion_flags, ExceptionState* exception_state,
+                 std::string* out_string);
+
+// std::vector<uint8_t> -> JSValue
+// Note that this conversion is specifically for the Web IDL type ByteString.
+// Ideally, conversion requests would be explicit in what type they wanted to
+// convert to, however it is currently solely based on input type.
+inline void ToJSValue(v8::Isolate* isolate, const std::vector<uint8_t>& in_data,
+                      v8::Local<v8::Value>* out_value) {
+  NOTIMPLEMENTED();
+}
+
+// base::Token -> JSValue
+inline void ToJSValue(v8::Isolate* isolate, const base::Token& token,
+                      v8::Local<v8::Value>* out_value) {
+  NOTIMPLEMENTED();
+}
+
+// bool -> JSValue
+inline void ToJSValue(v8::Isolate* isolate, bool in_boolean,
+                      v8::Local<v8::Value>* out_value) {
+  NOTIMPLEMENTED();
+}
+
+// JSValue -> bool
+inline void FromJSValue(v8::Isolate* isolate, v8::Local<v8::Value> value,
+                        int conversion_flags, ExceptionState* exception_state,
+                        bool* out_boolean) {
+  NOTIMPLEMENTED();
+}
+
+// signed integers <= 4 bytes -> JSValue
+template <typename T>
+inline void ToJSValue(
+    v8::Isolate* isolate, T in_number, v8::Local<v8::Value>* out_value,
+    typename base::enable_if<std::numeric_limits<T>::is_specialized &&
+                                 std::numeric_limits<T>::is_integer &&
+                                 std::numeric_limits<T>::is_signed &&
+                                 (sizeof(T) <= 4),
+                             T>::type* = NULL) {
+  NOTIMPLEMENTED();
+}
+
+template <typename T>
+inline const double UpperBound() {
+  return std::numeric_limits<T>::max();
+}
+
+template <typename T>
+inline const double LowerBound() {
+  return std::numeric_limits<T>::min();
+}
+
+// The below specializations of UpperBound<T> and LowerBound<T> for 64
+// bit integers use the (2^(53) - 1) and similar bounds specified in
+// step 1 of ConvertToInt, see:
+// https://heycam.github.io/webidl/#abstract-opdef-converttoint
+template <>
+inline const double UpperBound<int64_t>() {
+  const double kInt64UpperBound = static_cast<double>((1ll << 53) - 1);
+  return kInt64UpperBound;
+}
+
+template <>
+inline const double LowerBound<int64_t>() {
+  const double kInt64LowerBound = static_cast<double>(-(1ll << 53) + 1);
+  return kInt64LowerBound;
+}
+
+template <>
+inline const double UpperBound<uint64_t>() {
+  const double kUInt64UpperBound = static_cast<double>((1ll << 53) - 1);
+  return kUInt64UpperBound;
+}
+
+template <typename T>
+void ClampedValue(v8::Isolate* isolate, v8::Local<v8::Value> value,
+                  v8::Local<v8::Value>* clamped_value) {
+  NOTIMPLEMENTED();
+}
+
+// JSValue -> signed integers <= 4 bytes
+template <typename T>
+inline void FromJSValue(
+    v8::Isolate* isolate, v8::Local<v8::Value> value, int conversion_flags,
+    ExceptionState* exception_state, T* out_number,
+    typename base::enable_if<std::numeric_limits<T>::is_specialized &&
+                                 std::numeric_limits<T>::is_integer &&
+                                 std::numeric_limits<T>::is_signed &&
+                                 (sizeof(T) <= 4),
+                             T>::type* = NULL) {
+  NOTIMPLEMENTED();
+}
+
+// JSValue -> signed integers > 4 bytes
+template <typename T>
+inline void FromJSValue(
+    v8::Isolate* isolate, v8::Local<v8::Value> value, int conversion_flags,
+    ExceptionState* exception_state, T* out_number,
+    typename base::enable_if<std::numeric_limits<T>::is_specialized &&
+                                 std::numeric_limits<T>::is_integer &&
+                                 std::numeric_limits<T>::is_signed &&
+                                 (sizeof(T) > 4),
+                             T>::type* = NULL) {
+  NOTIMPLEMENTED();
+}
+
+// signed integers > 4 bytes -> JSValue
+template <typename T>
+inline void ToJSValue(
+    v8::Isolate* isolate, T in_number, v8::Local<v8::Value>* out_value,
+    typename base::enable_if<std::numeric_limits<T>::is_specialized &&
+                                 std::numeric_limits<T>::is_integer &&
+                                 std::numeric_limits<T>::is_signed &&
+                                 (sizeof(T) > 4),
+                             T>::type* = NULL) {
+  NOTIMPLEMENTED();
+}
+
+// unsigned integers <= 4 bytes -> JSValue
+template <typename T>
+inline void ToJSValue(
+    v8::Isolate* isolate, T in_number, v8::Local<v8::Value>* out_value,
+    typename base::enable_if<std::numeric_limits<T>::is_specialized &&
+                                 std::numeric_limits<T>::is_integer &&
+                                 !std::numeric_limits<T>::is_signed &&
+                                 (sizeof(T) <= 4),
+                             T>::type* = NULL) {
+  NOTIMPLEMENTED();
+}
+
+// JSValue -> unsigned integers <= 4 bytes
+template <typename T>
+inline void FromJSValue(
+    v8::Isolate* isolate, v8::Local<v8::Value> value, int conversion_flags,
+    ExceptionState* exception_state, T* out_number,
+    typename base::enable_if<std::numeric_limits<T>::is_specialized &&
+                                 std::numeric_limits<T>::is_integer &&
+                                 !std::numeric_limits<T>::is_signed &&
+                                 (sizeof(T) <= 4),
+                             T>::type* = NULL) {
+  NOTIMPLEMENTED();
+}
+
+// JSValue -> unsigned integers > 4 bytes
+template <typename T>
+inline void FromJSValue(
+    v8::Isolate* isolate, v8::Local<v8::Value> value, int conversion_flags,
+    ExceptionState* exception_state, T* out_number,
+    typename base::enable_if<std::numeric_limits<T>::is_specialized &&
+                                 std::numeric_limits<T>::is_integer &&
+                                 !std::numeric_limits<T>::is_signed &&
+                                 (sizeof(T) > 4),
+                             T>::type* = NULL) {
+  NOTIMPLEMENTED();
+}
+
+// unsigned integers > 4 bytes -> JSValue
+template <typename T>
+inline void ToJSValue(
+    v8::Isolate* isolate, T in_number, v8::Local<v8::Value>* out_value,
+    typename base::enable_if<std::numeric_limits<T>::is_specialized &&
+                                 std::numeric_limits<T>::is_integer &&
+                                 !std::numeric_limits<T>::is_signed &&
+                                 (sizeof(T) > 4),
+                             T>::type* = NULL) {
+  NOTIMPLEMENTED();
+}
+
+// double -> JSValue
+template <typename T>
+inline void ToJSValue(
+    v8::Isolate* isolate, T in_number, v8::Local<v8::Value>* out_value,
+    typename base::enable_if<std::numeric_limits<T>::is_specialized &&
+                                 !std::numeric_limits<T>::is_integer,
+                             T>::type* = NULL) {
+  NOTIMPLEMENTED();
+}
+
+// JSValue -> double
+template <typename T>
+inline void FromJSValue(
+    v8::Isolate* isolate, v8::Local<v8::Value> value, int conversion_flags,
+    ExceptionState* exception_state, T* out_number,
+    typename base::enable_if<std::numeric_limits<T>::is_specialized &&
+                                 !std::numeric_limits<T>::is_integer,
+                             T>::type* = NULL) {
+  NOTIMPLEMENTED();
+}
+
+// optional<T> -> JSValue
+template <typename T>
+inline void ToJSValue(v8::Isolate* isolate,
+                      const base::optional<T>& in_optional,
+                      v8::Local<v8::Value>* out_value) {
+  NOTIMPLEMENTED();
+}
+
+// JSValue -> optional<T>
+template <typename T>
+inline void FromJSValue(v8::Isolate* isolate, v8::Local<v8::Value> value,
+                        int conversion_flags, ExceptionState* exception_state,
+                        base::optional<T>* out_optional) {
+  NOTIMPLEMENTED();
+}
+
+// JSValue -> optional<std::string>
+template <>
+inline void FromJSValue(v8::Isolate* isolate, v8::Local<v8::Value> value,
+                        int conversion_flags, ExceptionState* exception_state,
+                        base::optional<std::string>* out_optional) {
+  NOTIMPLEMENTED();
+}
+
+// ValueHandle -> JSValue
+void ToJSValue(v8::Isolate* isolate,
+               const ValueHandleHolder* value_handle_holder,
+               v8::Local<v8::Value>* out_value);
+
+// JSValue -> ValueHandle
+void FromJSValue(v8::Isolate* isolate, v8::Local<v8::Value> value,
+                 int conversion_flags, ExceptionState* exception_state,
+                 V8cValueHandleHolder* out_holder);
+
+// object -> JSValue
+template <typename T>
+inline void ToJSValue(v8::Isolate* isolate, const scoped_refptr<T>& in_object,
+                      v8::Local<v8::Value>* out_value) {
+  NOTIMPLEMENTED();
+}
+
+// raw object pointer -> JSValue
+template <typename T>
+inline void ToJSValue(v8::Isolate* isolate, T* in_object,
+                      v8::Local<v8::Value>* out_value) {
+  ToJSValue(isolate, scoped_refptr<T>(in_object), out_value);
+}
+
+// JSValue -> object
+template <typename T>
+inline void FromJSValue(v8::Isolate* isolate, v8::Local<v8::Value> value,
+                        int conversion_flags, ExceptionState* exception_state,
+                        scoped_refptr<T>* out_object) {
+  DCHECK_EQ(conversion_flags & ~kConversionFlagsObject, 0)
+      << "Unexpected conversion flags found.";
+
+  if (!value->IsObject()) {
+    NOTIMPLEMENTED();
+    return;
+  }
+
+  // TODO: Check if object implements interface and throw TypeError otherwise.
+  v8::Local<v8::Object> object = v8::Local<v8::Object>::Cast(value);
+  DCHECK(object->InternalFieldCount() == 1);
+  v8::Local<v8::External> external =
+      v8::Local<v8::External>::Cast(object->GetInternalField(0));
+
+  *out_object = scoped_refptr<T>(static_cast<T*>(
+      (static_cast<WrapperPrivate*>(external->Value()))->wrappable<T>().get()));
+}
+
+// CallbackInterface -> JSValue
+template <typename T>
+inline void ToJSValue(v8::Isolate* isolate,
+                      const ScriptValue<T>* callback_interface,
+                      v8::Local<v8::Value>* out_value) {
+  NOTIMPLEMENTED();
+}
+
+// JSValue -> CallbackInterface
+template <typename T>
+inline void FromJSValue(v8::Isolate* isolate, v8::Local<v8::Value> value,
+                        int conversion_flags, ExceptionState* out_exception,
+                        V8cCallbackInterfaceHolder<T>* out_callback_interface) {
+  NOTIMPLEMENTED();
+}
+
+template <typename T>
+void ToJSValue(v8::Isolate* isolate, const script::Sequence<T>& sequence,
+               v8::Local<v8::Value>* out_value) {
+  NOTIMPLEMENTED();
+}
+
+template <typename T>
+void FromJSValue(v8::Isolate* isolate, v8::Local<v8::Value> value,
+                 int conversion_flags, ExceptionState* exception_state,
+                 script::Sequence<T>* out_sequence) {
+  NOTIMPLEMENTED();
+}
+
+}  // namespace v8c
+}  // namespace script
+}  // namespace cobalt
+
+// Union type conversion is generated by a pump script.
+#include "cobalt/script/v8c/union_type_conversion_impl.h"
+
+#endif  // COBALT_SCRIPT_V8C_CONVERSION_HELPERS_H_
diff --git a/src/cobalt/script/v8c/interface_data.h b/src/cobalt/script/v8c/interface_data.h
new file mode 100644
index 0000000..48a5f7f
--- /dev/null
+++ b/src/cobalt/script/v8c/interface_data.h
@@ -0,0 +1,33 @@
+// Copyright 2017 Google Inc. All Rights Reserved.
+//
+// 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.
+
+#ifndef COBALT_SCRIPT_V8C_INTERFACE_DATA_H_
+#define COBALT_SCRIPT_V8C_INTERFACE_DATA_H_
+
+#include "v8/include/v8.h"
+
+namespace cobalt {
+namespace script {
+namespace v8c {
+
+// Data that is cached on a per-interface basis.
+struct InterfaceData {
+  v8::Eternal<v8::FunctionTemplate> templ;
+};
+
+}  // namespace v8c
+}  // namespace script
+}  // namespace cobalt
+
+#endif  // COBALT_SCRIPT_V8C_INTERFACE_DATA_H_
diff --git a/src/cobalt/script/v8c/native_promise.h b/src/cobalt/script/v8c/native_promise.h
new file mode 100644
index 0000000..22eaecd
--- /dev/null
+++ b/src/cobalt/script/v8c/native_promise.h
@@ -0,0 +1,96 @@
+// Copyright 2017 Google Inc. All Rights Reserved.
+//
+// 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.
+
+#ifndef COBALT_SCRIPT_V8C_NATIVE_PROMISE_H_
+#define COBALT_SCRIPT_V8C_NATIVE_PROMISE_H_
+
+#include "cobalt/script/promise.h"
+#include "cobalt/script/v8c/type_traits.h"
+#include "cobalt/script/v8c/v8c_user_object_holder.h"
+
+namespace cobalt {
+namespace script {
+namespace v8c {
+
+// Shared functionality for NativePromise<T>. Does not implement the Resolve
+// function, since that needs to be specialized for Promise<T>.
+template <typename T>
+class NativePromiseBase : public Promise<T> {
+ public:
+  // ScriptObject boilerplate.
+  typedef Promise<T> BaseType;
+
+  void Reject() const override { NOTIMPLEMENTED(); }
+  void Reject(SimpleExceptionType exception) const override {
+    NOTIMPLEMENTED();
+  }
+  void Reject(const scoped_refptr<ScriptException>& result) const override {
+    NOTIMPLEMENTED();
+  }
+};
+
+// Implements the Resolve() function for T != void.
+template <typename T>
+class NativePromise : public NativePromiseBase<T> {
+ public:
+  void Resolve(const T& value) const override { NOTIMPLEMENTED(); }
+};
+
+// Implements the Resolve() function for T == void.
+template <>
+class NativePromise<void> : public NativePromiseBase<void> {
+ public:
+  void Resolve() const override { NOTIMPLEMENTED(); }
+};
+
+template <typename T>
+struct TypeTraits<NativePromise<T> > {
+  typedef V8cUserObjectHolder<NativePromise<T> > ConversionType;
+  typedef const ScriptValue<Promise<T> >* ReturnType;
+};
+
+// Promise<T> -> JSValue
+// Note that JSValue -> Promise<T> is not yet supported.
+template <typename T>
+inline void ToJSValue(v8::Isolate* isolate,
+                      const ScriptValue<Promise<T> >* promise_holder,
+                      v8::Local<v8::Value>* out_value) {
+  NOTIMPLEMENTED();
+}
+
+// Explicitly defer to the const version here so that a more generic non-const
+// version of this function does not get called instead, in the case that
+// |promise_holder| is not const.
+template <typename T>
+inline void ToJSValue(v8::Isolate* isolate,
+                      ScriptValue<Promise<T> >* promise_holder,
+                      v8::Local<v8::Value>* out_value) {
+  NOTIMPLEMENTED();
+}
+
+// Destroys |promise_holder| as soon as the conversion is done.
+// This is useful when a wrappable is not interested in retaining a reference
+// to a promise, typically when a promise is resolved or rejected synchronously.
+template <typename T>
+inline void ToJSValue(v8::Isolate* isolate,
+                      scoped_ptr<ScriptValue<Promise<T> > > promise_holder,
+                      v8::Local<v8::Value>* out_value) {
+  NOTIMPLEMENTED();
+}
+
+}  // namespace v8c
+}  // namespace script
+}  // namespace cobalt
+
+#endif  // COBALT_SCRIPT_V8C_NATIVE_PROMISE_H_
diff --git a/src/cobalt/script/v8c/stack_trace_helpers.cc b/src/cobalt/script/v8c/stack_trace_helpers.cc
new file mode 100644
index 0000000..b736972
--- /dev/null
+++ b/src/cobalt/script/v8c/stack_trace_helpers.cc
@@ -0,0 +1,30 @@
+// Copyright 2017 Google Inc. All Rights Reserved.
+//
+// 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.
+
+#include "cobalt/script/util/stack_trace_helpers.h"
+
+#include "base/logging.h"
+
+namespace cobalt {
+namespace script {
+namespace util {
+
+StackTraceGenerator* GetThreadLocalStackTraceGenerator() {
+  NOTIMPLEMENTED();
+  return nullptr;
+}
+
+}  // namespace util
+}  // namespace script
+}  // namespace cobalt
diff --git a/src/cobalt/script/v8c/type_traits.h b/src/cobalt/script/v8c/type_traits.h
new file mode 100644
index 0000000..dc5ce38
--- /dev/null
+++ b/src/cobalt/script/v8c/type_traits.h
@@ -0,0 +1,34 @@
+// Copyright 2017 Google Inc. All Rights Reserved.
+//
+// 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.
+
+#ifndef COBALT_SCRIPT_V8C_TYPE_TRAITS_H_
+#define COBALT_SCRIPT_V8C_TYPE_TRAITS_H_
+
+namespace cobalt {
+namespace script {
+namespace v8c {
+
+template <typename T>
+struct TypeTraits {
+  // The type to convert into from a v8::Value in the bindings implementation.
+  typedef T ConversionType;
+  // The type returned from a Cobalt implementation of a bound function.
+  typedef T ReturnType;
+};
+
+}  // namespace v8c
+}  // namespace script
+}  // namespace cobalt
+
+#endif  // COBALT_SCRIPT_V8C_TYPE_TRAITS_H_
diff --git a/src/cobalt/script/v8c/union_type_conversion_forward.h b/src/cobalt/script/v8c/union_type_conversion_forward.h
new file mode 100644
index 0000000..b53277f
--- /dev/null
+++ b/src/cobalt/script/v8c/union_type_conversion_forward.h
@@ -0,0 +1,68 @@
+// This file was GENERATED by command:
+//     pump.py union_type_conversion_forward.h.pump
+// DO NOT EDIT BY HAND!!!
+
+
+// Copyright 2017 Google Inc. All Rights Reserved.
+//
+// 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.
+
+#ifndef COBALT_SCRIPT_V8C_UNION_TYPE_CONVERSION_FORWARD_H_
+#define COBALT_SCRIPT_V8C_UNION_TYPE_CONVERSION_FORWARD_H_
+
+#include "cobalt/script/union_type.h"
+#include "cobalt/script/v8c/type_traits.h"
+#include "cobalt/script/v8c/v8c_exception_state.h"
+#include "cobalt/script/v8c/v8c_user_object_holder.h"
+#include "cobalt/script/v8c/v8c_value_handle.h"
+
+// Forward declaration for ToJSValue and FromJSValue for IDL union types.
+
+namespace cobalt {
+namespace script {
+namespace v8c {
+
+template <typename T1, typename T2>
+void ToJSValue(v8::Isolate* isolate, const script::UnionType2<T1, T2>& in_union,
+               v8::Local<v8::Value>* out_value);
+
+template <typename T1, typename T2>
+void FromJSValue(v8::Isolate* isolate, v8::Local<v8::Value> value,
+                 int conversion_flags, ExceptionState* exception_state,
+                 script::UnionType2<T1, T2>* out_union);
+
+template <typename T1, typename T2, typename T3>
+void ToJSValue(v8::Isolate* isolate,
+               const script::UnionType3<T1, T2, T3>& in_union,
+               v8::Local<v8::Value>* out_value);
+
+template <typename T1, typename T2, typename T3>
+void FromJSValue(v8::Isolate* isolate, v8::Local<v8::Value> value,
+                 int conversion_flags, ExceptionState* exception_state,
+                 script::UnionType3<T1, T2, T3>* out_union);
+
+template <typename T1, typename T2, typename T3, typename T4>
+void ToJSValue(v8::Isolate* isolate,
+               const script::UnionType4<T1, T2, T3, T4>& in_union,
+               v8::Local<v8::Value>* out_value);
+
+template <typename T1, typename T2, typename T3, typename T4>
+void FromJSValue(v8::Isolate* isolate, v8::Local<v8::Value> value,
+                 int conversion_flags, ExceptionState* exception_state,
+                 script::UnionType4<T1, T2, T3, T4>* out_union);
+
+}  // namespace v8c
+}  // namespace script
+}  // namespace cobalt
+
+#endif  // COBALT_SCRIPT_V8C_UNION_TYPE_CONVERSION_FORWARD_H_
diff --git a/src/cobalt/script/v8c/union_type_conversion_forward.h.pump b/src/cobalt/script/v8c/union_type_conversion_forward.h.pump
new file mode 100644
index 0000000..a8606ef
--- /dev/null
+++ b/src/cobalt/script/v8c/union_type_conversion_forward.h.pump
@@ -0,0 +1,58 @@
+$$ This is a pump file for generating file templates.  Pump is a python
+$$ script that is part of the Google Test suite of utilities.  Description
+$$ can be found here:
+$$
+$$ http://code.google.com/p/googletest/wiki/PumpManual
+$$
+
+$$ Maximum number of different member types in a union.
+$var MAX_MEMBERS = 4
+
+// Copyright 2017 Google Inc. All Rights Reserved.
+//
+// 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.
+
+#ifndef COBALT_SCRIPT_V8C_UNION_TYPE_CONVERSION_FORWARD_H_
+#define COBALT_SCRIPT_V8C_UNION_TYPE_CONVERSION_FORWARD_H_
+
+#include "cobalt/script/union_type.h"
+#include "cobalt/script/v8c/type_traits.h"
+#include "cobalt/script/v8c/v8c_exception_state.h"
+#include "cobalt/script/v8c/v8c_user_object_holder.h"
+#include "cobalt/script/v8c/v8c_value_handle.h"
+
+// Forward declaration for ToJSValue and FromJSValue for IDL union types.
+
+namespace cobalt {
+namespace script {
+namespace v8c {
+
+$range NUM_MEMBERS 2..MAX_MEMBERS
+$for NUM_MEMBERS [[
+$range TYPE 1..NUM_MEMBERS
+
+template <$for TYPE , [[typename T$(TYPE)]]>
+void ToJSValue(v8::Isolate* isolate, const script::UnionType$(NUM_MEMBERS)<$for TYPE , [[T$(TYPE)]]>& in_union, v8::Local<v8::Value>* out_value);
+
+template <$for TYPE , [[typename T$(TYPE)]]>
+void FromJSValue(v8::Isolate* isolate, v8::Local<v8::Value> value,
+                 int conversion_flags, ExceptionState* exception_state,
+                 script::UnionType$(NUM_MEMBERS)<$for TYPE , [[T$(TYPE)]]>* out_union);
+
+]]  $$ for NUM_MEMBERS
+
+}  // namespace v8c
+}  // namespace script
+}  // namespace cobalt
+
+#endif  // COBALT_SCRIPT_V8C_UNION_TYPE_CONVERSION_FORWARD_H_
diff --git a/src/cobalt/script/v8c/union_type_conversion_impl.h b/src/cobalt/script/v8c/union_type_conversion_impl.h
new file mode 100644
index 0000000..17d433e
--- /dev/null
+++ b/src/cobalt/script/v8c/union_type_conversion_impl.h
@@ -0,0 +1,82 @@
+// This file was GENERATED by command:
+//     pump.py union_type_conversion_impl.h.pump
+// DO NOT EDIT BY HAND!!!
+
+
+// Copyright 2017 Google Inc. All Rights Reserved.
+//
+// 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.
+
+#ifndef COBALT_SCRIPT_V8C_UNION_TYPE_CONVERSION_IMPL_H_
+#define COBALT_SCRIPT_V8C_UNION_TYPE_CONVERSION_IMPL_H_
+
+#include "cobalt/base/type_id.h"
+#include "cobalt/script/union_type.h"
+#include "cobalt/script/v8c/type_traits.h"
+#include "cobalt/script/v8c/v8c_exception_state.h"
+#include "cobalt/script/v8c/v8c_global_environment.h"
+#include "cobalt/script/v8c/v8c_user_object_holder.h"
+#include "cobalt/script/v8c/v8c_value_handle.h"
+
+// Conversion to/from Value for IDL union types.
+
+namespace cobalt {
+namespace script {
+namespace v8c {
+
+template <typename T1, typename T2>
+void ToJSValue(v8::Isolate* isolate, const script::UnionType2<T1, T2>& in_union,
+               v8::Local<v8::Value>* out_value) {
+  NOTIMPLEMENTED();
+}
+
+template <typename T1, typename T2>
+void FromJSValue(v8::Isolate* isolate, v8::Local<v8::Value> value,
+                 int conversion_flags, ExceptionState* exception_state,
+                 script::UnionType2<T1, T2>* out_union) {
+  NOTIMPLEMENTED();
+}
+
+template <typename T1, typename T2, typename T3>
+void ToJSValue(v8::Isolate* isolate,
+               const script::UnionType3<T1, T2, T3>& in_union,
+               v8::Local<v8::Value>* out_value) {
+  NOTIMPLEMENTED();
+}
+
+template <typename T1, typename T2, typename T3>
+void FromJSValue(v8::Isolate* isolate, v8::Local<v8::Value> value,
+                 int conversion_flags, ExceptionState* exception_state,
+                 script::UnionType3<T1, T2, T3>* out_union) {
+  NOTIMPLEMENTED();
+}
+
+template <typename T1, typename T2, typename T3, typename T4>
+void ToJSValue(v8::Isolate* isolate,
+               const script::UnionType4<T1, T2, T3, T4>& in_union,
+               v8::Local<v8::Value>* out_value) {
+  NOTIMPLEMENTED();
+}
+
+template <typename T1, typename T2, typename T3, typename T4>
+void FromJSValue(v8::Isolate* isolate, v8::Local<v8::Value> value,
+                 int conversion_flags, ExceptionState* exception_state,
+                 script::UnionType4<T1, T2, T3, T4>* out_union) {
+  NOTIMPLEMENTED();
+}
+
+}  // namespace v8c
+}  // namespace script
+}  // namespace cobalt
+
+#endif  // COBALT_SCRIPT_V8C_UNION_TYPE_CONVERSION_IMPL_H_
diff --git a/src/cobalt/script/v8c/union_type_conversion_impl.h.pump b/src/cobalt/script/v8c/union_type_conversion_impl.h.pump
new file mode 100644
index 0000000..a8fea6f
--- /dev/null
+++ b/src/cobalt/script/v8c/union_type_conversion_impl.h.pump
@@ -0,0 +1,68 @@
+$$ This is a pump file for generating file templates.  Pump is a python
+$$ script that is part of the Google Test suite of utilities.  Description
+$$ can be found here:
+$$
+$$ http://code.google.com/p/googletest/wiki/PumpManual
+$$
+
+$$ Maximum number of different member types in a union.
+$var MAX_MEMBERS = 4
+
+// Copyright 2017 Google Inc. All Rights Reserved.
+//
+// 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.
+
+#ifndef COBALT_SCRIPT_V8C_UNION_TYPE_CONVERSION_IMPL_H_
+#define COBALT_SCRIPT_V8C_UNION_TYPE_CONVERSION_IMPL_H_
+
+#include "cobalt/base/type_id.h"
+#include "cobalt/script/union_type.h"
+#include "cobalt/script/v8c/type_traits.h"
+#include "cobalt/script/v8c/v8c_exception_state.h"
+#include "cobalt/script/v8c/v8c_global_environment.h"
+#include "cobalt/script/v8c/v8c_user_object_holder.h"
+#include "cobalt/script/v8c/v8c_value_handle.h"
+
+// Conversion to/from Value for IDL union types.
+
+namespace cobalt {
+namespace script {
+namespace v8c {
+
+$range NUM_MEMBERS 2..MAX_MEMBERS
+$for NUM_MEMBERS [[
+
+$range TYPE 1..NUM_MEMBERS
+
+template <$for TYPE , [[typename T$(TYPE)]]>
+void ToJSValue(
+    v8::Isolate* isolate,
+    const script::UnionType$(NUM_MEMBERS)<$for TYPE , [[T$(TYPE)]]>& in_union,
+    v8::Local<v8::Value>* out_value) {
+  NOTIMPLEMENTED();
+}
+
+template <$for TYPE , [[typename T$(TYPE)]]>
+void FromJSValue(v8::Isolate* isolate, v8::Local<v8::Value> value,
+                 int conversion_flags, ExceptionState* exception_state,
+                 script::UnionType$(NUM_MEMBERS)<$for TYPE , [[T$(TYPE)]]>* out_union) {
+  NOTIMPLEMENTED();
+}
+
+]]  $$ for NUM_MEMBERS
+
+}  // namespace v8c
+}  // namespace script
+}  // namespace cobalt
+
+#endif  // COBALT_SCRIPT_V8C_UNION_TYPE_CONVERSION_IMPL_H_
diff --git a/src/cobalt/script/v8c/v8c.cc b/src/cobalt/script/v8c/v8c.cc
index 8ef4f6f..10c5b0c 100644
--- a/src/cobalt/script/v8c/v8c.cc
+++ b/src/cobalt/script/v8c/v8c.cc
@@ -62,12 +62,14 @@
   v8::Isolate* isolate = v8c_global_environment->isolate();
   v8::Isolate::Scope isolate_scope(isolate);
   v8::HandleScope handle_scope(isolate);
-  auto context = v8c_global_environment->context();
+  v8::Local<v8::Context> context = v8c_global_environment->context();
   v8::Context::Scope context_scope(context);
-  context->Global()->Set(
+  v8::Maybe<bool> set_result = context->Global()->Set(
+      context,
       v8::String::NewFromUtf8(isolate, "print", v8::NewStringType::kNormal)
           .ToLocalChecked(),
-      v8::Function::New(isolate, Print));
+      v8::Function::New(context, Print).ToLocalChecked());
+  DCHECK(set_result.FromJust());
 }
 
 int V8cMain(int argc, char** argv) {
diff --git a/src/cobalt/script/v8c/v8c.gyp b/src/cobalt/script/v8c/v8c.gyp
index d1deb54..ebd9426 100644
--- a/src/cobalt/script/v8c/v8c.gyp
+++ b/src/cobalt/script/v8c/v8c.gyp
@@ -18,15 +18,26 @@
       'target_name': 'engine',
       'type': 'static_library',
       'sources': [
+        'conversion_helpers.cc',
+        'interface_data.h',
+        'native_promise.h',
+        'stack_trace_helpers.cc',
+        'type_traits.h',
         'v8c_engine.cc',
         'v8c_engine.h',
         'v8c_global_environment.cc',
         'v8c_global_environment.h',
+        'v8c_script_value_factory.cc',
+        'v8c_script_value_factory.h',
         'v8c_source_code.cc',
         'v8c_source_code.h',
+        'v8c_wrapper_handle.h',
+        'wrapper_factory.cc',
+        'wrapper_factory.h',
         '<(DEPTH)/cobalt/script/shared/stub_script_debugger.cc',
       ],
       'dependencies': [
+        '<(DEPTH)/cobalt/script/script.gyp:script',
         '<(DEPTH)/v8/src/v8.gyp:v8',
         '<(DEPTH)/v8/src/v8.gyp:v8_libplatform',
       ],
diff --git a/src/cobalt/script/v8c/v8c_callback_function.h b/src/cobalt/script/v8c/v8c_callback_function.h
new file mode 100644
index 0000000..cf8ab0b
--- /dev/null
+++ b/src/cobalt/script/v8c/v8c_callback_function.h
@@ -0,0 +1,293 @@
+// This file was GENERATED by command:
+//     pump.py v8c_callback_function.h.pump
+// DO NOT EDIT BY HAND!!!
+
+
+// Copyright 2017 Google Inc. All Rights Reserved.
+//
+// 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.
+
+// clang-format off
+
+#ifndef COBALT_SCRIPT_V8C_V8C_CALLBACK_FUNCTION_H_
+#define COBALT_SCRIPT_V8C_V8C_CALLBACK_FUNCTION_H_
+
+#include "base/logging.h"
+#include "cobalt/script/callback_function.h"
+#include "cobalt/script/v8c/conversion_helpers.h"
+#include "cobalt/script/v8c/weak_heap_object.h"
+#include "nb/memory_scope.h"
+#include "v8/include/v8.h"
+
+namespace cobalt {
+namespace script {
+namespace v8c {
+
+// First, we forward declare the Callback class template. This informs the
+// compiler that the template only has 1 type parameter which is the base
+// CallbackFunction template class with parameters.
+//
+// See base/callback.h.pump for further discussion on this pattern.
+template <typename Sig>
+class V8cCallbackFunction;
+
+template <typename R>
+class V8cCallbackFunction<R(void)>
+    : public CallbackFunction<R(void)> {
+ public:
+  typedef CallbackFunction<R()> BaseType;
+
+  V8cCallbackFunction(V8cGlobalEnvironment* env, v8::Local<v8::Value> function)
+    : env_(env), weak_function_(env, function) {
+      DCHECK(env_);
+      DCHECK(function->IsFunction());
+  }
+
+  CallbackResult<R> Run()
+      const OVERRIDE {
+    NOTIMPLEMENTED();
+    CallbackResult<R> callback_result;
+    return callback_result;
+  }
+
+  v8::Local<v8::Value> value() const { return weak_function_.GetValue(); }
+
+ private:
+  V8cGlobalEnvironment* env_;
+  WeakHeapObject weak_function_;
+};
+
+template <typename R, typename A1>
+class V8cCallbackFunction<R(A1)>
+    : public CallbackFunction<R(A1)> {
+ public:
+  typedef CallbackFunction<R(A1)> BaseType;
+
+  V8cCallbackFunction(V8cGlobalEnvironment* env, v8::Local<v8::Value> function)
+    : env_(env), weak_function_(env, function) {
+      DCHECK(env_);
+      DCHECK(function->IsFunction());
+  }
+
+  CallbackResult<R> Run(
+      typename base::internal::CallbackParamTraits<A1>::ForwardType a1)
+      const OVERRIDE {
+    NOTIMPLEMENTED();
+    CallbackResult<R> callback_result;
+    return callback_result;
+  }
+
+  v8::Local<v8::Value> value() const { return weak_function_.GetValue(); }
+
+ private:
+  V8cGlobalEnvironment* env_;
+  WeakHeapObject weak_function_;
+};
+
+template <typename R, typename A1, typename A2>
+class V8cCallbackFunction<R(A1, A2)>
+    : public CallbackFunction<R(A1, A2)> {
+ public:
+  typedef CallbackFunction<R(A1, A2)> BaseType;
+
+  V8cCallbackFunction(V8cGlobalEnvironment* env, v8::Local<v8::Value> function)
+    : env_(env), weak_function_(env, function) {
+      DCHECK(env_);
+      DCHECK(function->IsFunction());
+  }
+
+  CallbackResult<R> Run(
+      typename base::internal::CallbackParamTraits<A1>::ForwardType a1,
+      typename base::internal::CallbackParamTraits<A2>::ForwardType a2)
+      const OVERRIDE {
+    NOTIMPLEMENTED();
+    CallbackResult<R> callback_result;
+    return callback_result;
+  }
+
+  v8::Local<v8::Value> value() const { return weak_function_.GetValue(); }
+
+ private:
+  V8cGlobalEnvironment* env_;
+  WeakHeapObject weak_function_;
+};
+
+template <typename R, typename A1, typename A2, typename A3>
+class V8cCallbackFunction<R(A1, A2, A3)>
+    : public CallbackFunction<R(A1, A2, A3)> {
+ public:
+  typedef CallbackFunction<R(A1, A2, A3)> BaseType;
+
+  V8cCallbackFunction(V8cGlobalEnvironment* env, v8::Local<v8::Value> function)
+    : env_(env), weak_function_(env, function) {
+      DCHECK(env_);
+      DCHECK(function->IsFunction());
+  }
+
+  CallbackResult<R> Run(
+      typename base::internal::CallbackParamTraits<A1>::ForwardType a1,
+      typename base::internal::CallbackParamTraits<A2>::ForwardType a2,
+      typename base::internal::CallbackParamTraits<A3>::ForwardType a3)
+      const OVERRIDE {
+    NOTIMPLEMENTED();
+    CallbackResult<R> callback_result;
+    return callback_result;
+  }
+
+  v8::Local<v8::Value> value() const { return weak_function_.GetValue(); }
+
+ private:
+  V8cGlobalEnvironment* env_;
+  WeakHeapObject weak_function_;
+};
+
+template <typename R, typename A1, typename A2, typename A3, typename A4>
+class V8cCallbackFunction<R(A1, A2, A3, A4)>
+    : public CallbackFunction<R(A1, A2, A3, A4)> {
+ public:
+  typedef CallbackFunction<R(A1, A2, A3, A4)> BaseType;
+
+  V8cCallbackFunction(V8cGlobalEnvironment* env, v8::Local<v8::Value> function)
+    : env_(env), weak_function_(env, function) {
+      DCHECK(env_);
+      DCHECK(function->IsFunction());
+  }
+
+  CallbackResult<R> Run(
+      typename base::internal::CallbackParamTraits<A1>::ForwardType a1,
+      typename base::internal::CallbackParamTraits<A2>::ForwardType a2,
+      typename base::internal::CallbackParamTraits<A3>::ForwardType a3,
+      typename base::internal::CallbackParamTraits<A4>::ForwardType a4)
+      const OVERRIDE {
+    NOTIMPLEMENTED();
+    CallbackResult<R> callback_result;
+    return callback_result;
+  }
+
+  v8::Local<v8::Value> value() const { return weak_function_.GetValue(); }
+
+ private:
+  V8cGlobalEnvironment* env_;
+  WeakHeapObject weak_function_;
+};
+
+template <typename R, typename A1, typename A2, typename A3, typename A4,
+    typename A5>
+class V8cCallbackFunction<R(A1, A2, A3, A4, A5)>
+    : public CallbackFunction<R(A1, A2, A3, A4, A5)> {
+ public:
+  typedef CallbackFunction<R(A1, A2, A3, A4, A5)> BaseType;
+
+  V8cCallbackFunction(V8cGlobalEnvironment* env, v8::Local<v8::Value> function)
+    : env_(env), weak_function_(env, function) {
+      DCHECK(env_);
+      DCHECK(function->IsFunction());
+  }
+
+  CallbackResult<R> Run(
+      typename base::internal::CallbackParamTraits<A1>::ForwardType a1,
+      typename base::internal::CallbackParamTraits<A2>::ForwardType a2,
+      typename base::internal::CallbackParamTraits<A3>::ForwardType a3,
+      typename base::internal::CallbackParamTraits<A4>::ForwardType a4,
+      typename base::internal::CallbackParamTraits<A5>::ForwardType a5)
+      const OVERRIDE {
+    NOTIMPLEMENTED();
+    CallbackResult<R> callback_result;
+    return callback_result;
+  }
+
+  v8::Local<v8::Value> value() const { return weak_function_.GetValue(); }
+
+ private:
+  V8cGlobalEnvironment* env_;
+  WeakHeapObject weak_function_;
+};
+
+template <typename R, typename A1, typename A2, typename A3, typename A4,
+    typename A5, typename A6>
+class V8cCallbackFunction<R(A1, A2, A3, A4, A5, A6)>
+    : public CallbackFunction<R(A1, A2, A3, A4, A5, A6)> {
+ public:
+  typedef CallbackFunction<R(A1, A2, A3, A4, A5, A6)> BaseType;
+
+  V8cCallbackFunction(V8cGlobalEnvironment* env, v8::Local<v8::Value> function)
+    : env_(env), weak_function_(env, function) {
+      DCHECK(env_);
+      DCHECK(function->IsFunction());
+  }
+
+  CallbackResult<R> Run(
+      typename base::internal::CallbackParamTraits<A1>::ForwardType a1,
+      typename base::internal::CallbackParamTraits<A2>::ForwardType a2,
+      typename base::internal::CallbackParamTraits<A3>::ForwardType a3,
+      typename base::internal::CallbackParamTraits<A4>::ForwardType a4,
+      typename base::internal::CallbackParamTraits<A5>::ForwardType a5,
+      typename base::internal::CallbackParamTraits<A6>::ForwardType a6)
+      const OVERRIDE {
+    NOTIMPLEMENTED();
+    CallbackResult<R> callback_result;
+    return callback_result;
+  }
+
+  v8::Local<v8::Value> value() const { return weak_function_.GetValue(); }
+
+ private:
+  V8cGlobalEnvironment* env_;
+  WeakHeapObject weak_function_;
+};
+
+template <typename R, typename A1, typename A2, typename A3, typename A4,
+    typename A5, typename A6, typename A7>
+class V8cCallbackFunction<R(A1, A2, A3, A4, A5, A6, A7)>
+    : public CallbackFunction<R(A1, A2, A3, A4, A5, A6, A7)> {
+ public:
+  typedef CallbackFunction<R(A1, A2, A3, A4, A5, A6, A7)> BaseType;
+
+  V8cCallbackFunction(V8cGlobalEnvironment* env, v8::Local<v8::Value> function)
+    : env_(env), weak_function_(env, function) {
+      DCHECK(env_);
+      DCHECK(function->IsFunction());
+  }
+
+  CallbackResult<R> Run(
+      typename base::internal::CallbackParamTraits<A1>::ForwardType a1,
+      typename base::internal::CallbackParamTraits<A2>::ForwardType a2,
+      typename base::internal::CallbackParamTraits<A3>::ForwardType a3,
+      typename base::internal::CallbackParamTraits<A4>::ForwardType a4,
+      typename base::internal::CallbackParamTraits<A5>::ForwardType a5,
+      typename base::internal::CallbackParamTraits<A6>::ForwardType a6,
+      typename base::internal::CallbackParamTraits<A7>::ForwardType a7)
+      const OVERRIDE {
+    NOTIMPLEMENTED();
+    CallbackResult<R> callback_result;
+    return callback_result;
+  }
+
+  v8::Local<v8::Value> value() const { return weak_function_.GetValue(); }
+
+ private:
+  V8cGlobalEnvironment* env_;
+  WeakHeapObject weak_function_;
+};
+
+template <typename Signature>
+struct TypeTraits<CallbackFunction<Signature> > {
+  typedef V8cUserObjectHolder<V8cCallbackFunction<Signature> > ConversionType;
+  typedef const ScriptValue<CallbackFunction<Signature> >* ReturnType;
+};
+
+}  // namespace v8c
+}  // namespace script
+}  // namespace cobalt
+
+#endif  // COBALT_SCRIPT_V8C_V8C_CALLBACK_FUNCTION_H_
diff --git a/src/cobalt/script/v8c/v8c_callback_function.h.pump b/src/cobalt/script/v8c/v8c_callback_function.h.pump
new file mode 100644
index 0000000..19c7b11
--- /dev/null
+++ b/src/cobalt/script/v8c/v8c_callback_function.h.pump
@@ -0,0 +1,101 @@
+$$ This is a pump file for generating file templates.  Pump is a python
+$$ script that is part of the Google Test suite of utilities.  Description
+$$ can be found here:
+$$
+$$ http://code.google.com/p/googletest/wiki/PumpManual
+$$
+
+$$ This should be no larger than MAX_ARITY in base/bind.h.pump.
+$var MAX_ARITY = 7
+
+// Copyright 2017 Google Inc. All Rights Reserved.
+//
+// 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.
+
+// clang-format off
+
+#ifndef COBALT_SCRIPT_V8C_V8C_CALLBACK_FUNCTION_H_
+#define COBALT_SCRIPT_V8C_V8C_CALLBACK_FUNCTION_H_
+
+#include "base/logging.h"
+#include "cobalt/script/callback_function.h"
+#include "cobalt/script/v8c/conversion_helpers.h"
+#include "cobalt/script/v8c/weak_heap_object.h"
+#include "nb/memory_scope.h"
+#include "v8/include/v8.h"
+
+namespace cobalt {
+namespace script {
+namespace v8c {
+
+// First, we forward declare the Callback class template. This informs the
+// compiler that the template only has 1 type parameter which is the base
+// CallbackFunction template class with parameters.
+//
+// See base/callback.h.pump for further discussion on this pattern.
+template <typename Sig>
+class V8cCallbackFunction;
+
+$range ARITY 0..MAX_ARITY
+$for ARITY [[
+$range ARG 1..ARITY
+
+
+$if ARITY == 0 [[
+template <typename R>
+class V8cCallbackFunction<R(void)>
+    : public CallbackFunction<R(void)> {
+]] $else [[
+template <typename R, $for ARG , [[typename A$(ARG)]]>
+class V8cCallbackFunction<R($for ARG , [[A$(ARG)]])>
+    : public CallbackFunction<R($for ARG , [[A$(ARG)]])> {
+]]
+
+ public:
+  typedef CallbackFunction<R($for ARG , [[A$(ARG)]])> BaseType;
+
+  V8cCallbackFunction(V8cGlobalEnvironment* env, v8::Local<v8::Value> function)
+    : env_(env), weak_function_(env, function) {
+      DCHECK(env_);
+      DCHECK(function->IsFunction());
+  }
+
+  CallbackResult<R> Run($for ARG , [[
+
+      typename base::internal::CallbackParamTraits<A$(ARG)>::ForwardType a$(ARG)]])
+      const OVERRIDE {
+    NOTIMPLEMENTED();
+    CallbackResult<R> callback_result;
+    return callback_result;
+  }
+
+  v8::Local<v8::Value> value() const { return weak_function_.GetValue(); }
+
+ private:
+  V8cGlobalEnvironment* env_;
+  WeakHeapObject weak_function_;
+};
+
+]]
+
+template <typename Signature>
+struct TypeTraits<CallbackFunction<Signature> > {
+  typedef V8cUserObjectHolder<V8cCallbackFunction<Signature> > ConversionType;
+  typedef const ScriptValue<CallbackFunction<Signature> >* ReturnType;
+};
+
+}  // namespace v8c
+}  // namespace script
+}  // namespace cobalt
+
+#endif  // COBALT_SCRIPT_V8C_V8C_CALLBACK_FUNCTION_H_
diff --git a/src/cobalt/script/v8c/v8c_callback_interface.cc b/src/cobalt/script/v8c/v8c_callback_interface.cc
new file mode 100644
index 0000000..965d64a
--- /dev/null
+++ b/src/cobalt/script/v8c/v8c_callback_interface.cc
@@ -0,0 +1,51 @@
+// Copyright 2017 Google Inc. All Rights Reserved.
+//
+// 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.
+
+#include "cobalt/script/v8c/v8c_callback_interface.h"
+
+#include "base/logging.h"
+
+namespace cobalt {
+namespace script {
+namespace v8c {
+
+// Helper class to get the actual callable object from a v8::Object
+// implementing a callback interface.
+// Returns true if a callable was found, and false if not.
+v8::MaybeLocal<v8::Object> GetCallableForCallbackInterface(
+    V8cGlobalEnvironment* env, v8::Local<v8::Object> implementing_object,
+    const char* property_name) {
+  DCHECK(implementing_object);
+  DCHECK(property_name);
+
+  if (implementing_object->IsCallable()) {
+    return implementing_object;
+  }
+  v8::Local<v8::Value> property_value = implementing_object->Get(
+      v8::String::NewFromUtf8(env->isolate(), property_name));
+  if (!property.IsObject()) {
+    return {};
+  }
+  v8::Local<v8::Object> property_object =
+      v8::Local<v8::Object>::Cast(property_value);
+  if (!property_object->IsCallable()) {
+    return {};
+  }
+
+  return property_object;
+}
+
+}  // namespace v8c
+}  // namespace script
+}  // namespace cobalt
diff --git a/src/cobalt/script/v8c/v8c_callback_interface.h b/src/cobalt/script/v8c/v8c_callback_interface.h
new file mode 100644
index 0000000..d7cac20
--- /dev/null
+++ b/src/cobalt/script/v8c/v8c_callback_interface.h
@@ -0,0 +1,36 @@
+// Copyright 2017 Google Inc. All Rights Reserved.
+//
+// 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.
+
+#ifndef COBALT_SCRIPT_V8C_V8C_CALLBACK_INTERFACE_H_
+#define COBALT_SCRIPT_V8C_V8C_CALLBACK_INTERFACE_H_
+
+#include "cobalt/script/callback_interface_traits.h"
+#include "v8/include/v8.h"
+
+namespace cobalt {
+namespace script {
+namespace v8c {
+
+// Helper class to get the actual callable object from a v8::Object
+// implementing a callback interface.
+// Returns true if a callable was found, and false if not.
+v8::MaybeLocal<v8::Object> GetCallableForCallbackInterface(
+    V8cGlobalEnvironment* env, v8::Local<v8::Object> implementing_object,
+    const char* property_name);
+
+}  // namespace v8c
+}  // namespace script
+}  // namespace cobalt
+
+#endif  // COBALT_SCRIPT_V8C_V8C_CALLBACK_INTERFACE_H_
diff --git a/src/cobalt/script/v8c/v8c_callback_interface_holder.h b/src/cobalt/script/v8c/v8c_callback_interface_holder.h
new file mode 100644
index 0000000..c3605d0
--- /dev/null
+++ b/src/cobalt/script/v8c/v8c_callback_interface_holder.h
@@ -0,0 +1,51 @@
+// Copyright 2017 Google Inc. All Rights Reserved.
+//
+// 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.
+
+#ifndef COBALT_SCRIPT_V8C_V8C_CALLBACK_INTERFACE_HOLDER_H_
+#define COBALT_SCRIPT_V8C_V8C_CALLBACK_INTERFACE_HOLDER_H_
+
+#include "base/memory/scoped_ptr.h"
+#include "cobalt/script/callback_interface_traits.h"
+#include "cobalt/script/v8c/type_traits.h"
+#include "cobalt/script/v8c/v8c_user_object_holder.h"
+
+namespace cobalt {
+namespace script {
+namespace v8c {
+
+template <typename V8cCallbackInterface>
+class V8cCallbackInterfaceHolder
+    : public V8cUserObjectHolder<V8cCallbackInterface> {
+ public:
+  typedef V8cUserObjectHolder<V8cCallbackInterface> BaseClass;
+  V8cCallbackInterfaceHolder() {}
+
+  V8cCallbackInterfaceHolder(V8cGlobalEnvironment* env,
+                             v8::Local<v8::Value> value)
+      : BaseClass(env, value) {}
+};
+
+template <typename CallbackInterface>
+struct TypeTraits<CallbackInterfaceTraits<CallbackInterface> > {
+  typedef V8cCallbackInterfaceHolder<typename CallbackInterfaceTraits<
+      CallbackInterface>::V8cCallbackInterfaceClass>
+      ConversionType;
+  typedef const ScriptValue<CallbackInterface>* ReturnType;
+};
+
+}  // namespace v8c
+}  // namespace script
+}  // namespace cobalt
+
+#endif  // COBALT_SCRIPT_V8C_V8C_CALLBACK_INTERFACE_HOLDER_H_
diff --git a/src/cobalt/script/v8c/v8c_engine.cc b/src/cobalt/script/v8c/v8c_engine.cc
index 2c928bc..9f51e3e 100644
--- a/src/cobalt/script/v8c/v8c_engine.cc
+++ b/src/cobalt/script/v8c/v8c_engine.cc
@@ -33,9 +33,6 @@
 namespace v8c {
 namespace {
 
-// Trigger garbage collection this many seconds after the last one.
-const int kGarbageCollectionIntervalSeconds = 60;
-
 SbOnceControl g_js_init_once_control = SB_ONCE_INITIALIZER;
 v8::Platform* g_platform = nullptr;
 v8::ArrayBuffer::Allocator* g_array_buffer_allocator = nullptr;
@@ -78,16 +75,20 @@
   isolate_ = v8::Isolate::New(params);
   CHECK(isolate_);
 
-  if (MessageLoop::current()) {
-    gc_timer_.Start(
-        FROM_HERE,
-        base::TimeDelta::FromSeconds(kGarbageCollectionIntervalSeconds), this,
-        &V8cEngine::TimerGarbageCollect);
-  }
+  DCHECK(v8::Isolate::GetNumberOfDataSlots() >= 1);
 }
 
 V8cEngine::~V8cEngine() {
+  TRACE_EVENT0("cobalt::script", "V8cEngine::~V8cEngine");
   DCHECK(thread_checker_.CalledOnValidThread());
+
+  // Send a low memory notification to V8 in order to force a garbage
+  // collection before shut down.  This is required to run weak callbacks that
+  // are responsible for freeing native objects that live in the internal
+  // fields of V8 objects.  In the future, we should consider investigating if
+  // there are startup performance wins to be made by delaying this work until
+  // later (e.g., does the GC of the splash screen web module dying hurt us?).
+  isolate_->LowMemoryNotification();
   isolate_->Dispose();
   isolate_ = nullptr;
 }
@@ -123,11 +124,6 @@
 
 void V8cEngine::SetGcThreshold(int64_t bytes) { NOTIMPLEMENTED(); }
 
-void V8cEngine::TimerGarbageCollect() {
-  TRACE_EVENT0("cobalt::script", "V8cEngine::TimerGarbageCollect()");
-  CollectGarbage();
-}
-
 }  // namespace v8c
 
 // static
diff --git a/src/cobalt/script/v8c/v8c_engine.h b/src/cobalt/script/v8c/v8c_engine.h
index 2962efb..7232998 100644
--- a/src/cobalt/script/v8c/v8c_engine.h
+++ b/src/cobalt/script/v8c/v8c_engine.h
@@ -41,8 +41,6 @@
   v8::Isolate* isolate() const { return isolate_; }
 
  private:
-  void TimerGarbageCollect();
-
   base::ThreadChecker thread_checker_;
 
   // An isolated instance of the V8 engine.
@@ -51,9 +49,6 @@
   // The amount of externally allocated memory since last forced GC.
   size_t accumulated_extra_memory_cost_;
 
-  // Used to trigger a garbage collection periodically.
-  base::RepeatingTimer<V8cEngine> gc_timer_;
-
   // Used to handle javascript errors.
   ErrorHandler error_handler_;
 
diff --git a/src/cobalt/script/v8c/v8c_exception_state.h b/src/cobalt/script/v8c/v8c_exception_state.h
new file mode 100644
index 0000000..131081d
--- /dev/null
+++ b/src/cobalt/script/v8c/v8c_exception_state.h
@@ -0,0 +1,54 @@
+// Copyright 2017 Google Inc. All Rights Reserved.
+//
+// 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.
+
+#ifndef COBALT_SCRIPT_V8C_V8C_EXCEPTION_STATE_H_
+#define COBALT_SCRIPT_V8C_V8C_EXCEPTION_STATE_H_
+
+#include <string>
+
+#include "base/threading/thread_checker.h"
+#include "cobalt/script/exception_state.h"
+#include "v8/include/v8.h"
+
+namespace cobalt {
+namespace script {
+namespace v8c {
+
+class V8cExceptionState : public ExceptionState {
+ public:
+  V8cExceptionState() : is_exception_set_(false) { NOTIMPLEMENTED(); }
+
+  // ExceptionState interface
+  void SetException(const scoped_refptr<ScriptException>& exception) override {
+    DCHECK(thread_checker_.CalledOnValidThread());
+    NOTIMPLEMENTED();
+  }
+  void SetSimpleExceptionVA(SimpleExceptionType type, const char* format,
+                            va_list arguments) override {
+    DCHECK(thread_checker_.CalledOnValidThread());
+    NOTIMPLEMENTED();
+  }
+
+  bool is_exception_set() const { return is_exception_set_; }
+
+ private:
+  bool is_exception_set_;
+  base::ThreadChecker thread_checker_;
+};
+
+}  // namespace v8c
+}  // namespace script
+}  // namespace cobalt
+
+#endif  // COBALT_SCRIPT_V8C_V8C_EXCEPTION_STATE_H_
diff --git a/src/cobalt/script/v8c/v8c_global_environment.cc b/src/cobalt/script/v8c/v8c_global_environment.cc
index a3c08bc..741442c 100644
--- a/src/cobalt/script/v8c/v8c_global_environment.cc
+++ b/src/cobalt/script/v8c/v8c_global_environment.cc
@@ -21,6 +21,8 @@
 #include "base/stringprintf.h"
 #include "cobalt/base/polymorphic_downcast.h"
 #include "cobalt/script/v8c/v8c_source_code.h"
+#include "cobalt/script/v8c/v8c_user_object_holder.h"
+#include "cobalt/script/v8c/v8c_value_handle.h"
 #include "nb/memory_scope.h"
 
 namespace cobalt {
@@ -34,12 +36,9 @@
       eval_enabled_(false),
       isolate_(isolate) {
   TRACK_MEMORY_SCOPE("Javascript");
-  v8::Isolate::Scope isolate_scope(isolate_);
-  v8::HandleScope handle_scope(isolate_);
-  v8::Local<v8::ObjectTemplate> global_object_template;
-  v8::Local<v8::Context> context =
-      v8::Context::New(isolate_, nullptr, global_object_template);
-  context_.Reset(isolate_, context);
+  wrapper_factory_.reset(new WrapperFactory(this));
+  isolate_->SetData(0, this);
+  DCHECK(isolate_->GetData(0) == this);
 }
 
 V8cGlobalEnvironment::~V8cGlobalEnvironment() {
@@ -49,8 +48,12 @@
 void V8cGlobalEnvironment::CreateGlobalObject() {
   TRACK_MEMORY_SCOPE("Javascript");
   DCHECK(thread_checker_.CalledOnValidThread());
-  // TODO: Global object creation happens with context creation in V8.
-  // Strongly consider removing this from the interface.
+
+  v8::Isolate::Scope isolate_scope(isolate_);
+  v8::HandleScope handle_scope(isolate_);
+  v8::Local<v8::Context> context = v8::Context::New(isolate_);
+  context_.Reset(isolate_, context);
+
   EvaluateAutomatics();
 }
 
@@ -105,12 +108,51 @@
 bool V8cGlobalEnvironment::EvaluateScript(
     const scoped_refptr<SourceCode>& source_code,
     const scoped_refptr<Wrappable>& owning_object, bool mute_errors,
-    base::optional<OpaqueHandleHolder::Reference>* out_opaque_handle) {
+    base::optional<ValueHandleHolder::Reference>* out_value_handle) {
   TRACK_MEMORY_SCOPE("Javascript");
   DCHECK(thread_checker_.CalledOnValidThread());
-  // TODO: Implement this once we have |V8cObjectHandleHolder|.
-  NOTIMPLEMENTED();
-  return false;
+
+  v8::Isolate::Scope isolate_scope(isolate_);
+  v8::HandleScope handle_scope(isolate_);
+  v8::Local<v8::Context> context = context_.Get(isolate_);
+  v8::Context::Scope scope(context);
+
+  V8cSourceCode* v8c_source_code =
+      base::polymorphic_downcast<V8cSourceCode*>(source_code.get());
+  const base::SourceLocation& source_location = v8c_source_code->location();
+
+  v8::TryCatch try_catch(isolate_);
+  v8::ScriptOrigin script_origin(
+      v8::String::NewFromUtf8(isolate_, source_location.file_path.c_str(),
+                              v8::NewStringType::kNormal)
+          .ToLocalChecked(),
+      v8::Integer::New(isolate_, source_location.line_number),
+      v8::Integer::New(isolate_, source_location.column_number),
+      v8::Boolean::New(isolate_, !mute_errors));
+  v8::Local<v8::String> source =
+      v8::String::NewFromUtf8(isolate_, v8c_source_code->source_utf8().c_str(),
+                              v8::NewStringType::kNormal)
+          .ToLocalChecked();
+
+  v8::MaybeLocal<v8::Script> maybe_script =
+      v8::Script::Compile(context, source);
+  v8::Local<v8::Script> script;
+  if (!maybe_script.ToLocal(&script)) {
+    return false;
+  }
+
+  v8::MaybeLocal<v8::Value> maybe_result = script->Run(context);
+  v8::Local<v8::Value> result;
+  if (!maybe_result.ToLocal(&result)) {
+    return false;
+  }
+
+  if (out_value_handle) {
+    V8cValueHandleHolder v8c_value_handle_holder(this, result);
+    out_value_handle->emplace(owning_object.get(), v8c_value_handle_holder);
+  }
+
+  return true;
 }
 
 std::vector<StackFrame> V8cGlobalEnvironment::GetStackTrace(int max_frames) {
@@ -165,7 +207,22 @@
 void V8cGlobalEnvironment::Bind(const std::string& identifier,
                                 const scoped_refptr<Wrappable>& impl) {
   TRACK_MEMORY_SCOPE("Javascript");
-  NOTIMPLEMENTED();
+
+  v8::Isolate::Scope isolate_scope(isolate_);
+  v8::HandleScope handle_scope(isolate_);
+  v8::Local<v8::Context> context = context_.Get(isolate_);
+  v8::Context::Scope scope(context);
+
+  v8::Local<v8::Object> wrapper = wrapper_factory_->GetWrapper(impl);
+  v8::Local<v8::Object> global_object = context->Global();
+
+  v8::Maybe<bool> set_result = global_object->Set(
+      context,
+      v8::String::NewFromUtf8(isolate_, identifier.c_str(),
+                              v8::NewStringType::kInternalized)
+          .ToLocalChecked(),
+      wrapper);
+  DCHECK(set_result.FromJust());
 }
 
 ScriptValueFactory* V8cGlobalEnvironment::script_value_factory() {
diff --git a/src/cobalt/script/v8c/v8c_global_environment.h b/src/cobalt/script/v8c/v8c_global_environment.h
index 224cc4d..a6abbe7 100644
--- a/src/cobalt/script/v8c/v8c_global_environment.h
+++ b/src/cobalt/script/v8c/v8c_global_environment.h
@@ -25,6 +25,9 @@
 #include "base/threading/thread_checker.h"
 #include "cobalt/script/global_environment.h"
 #include "cobalt/script/javascript_engine.h"
+#include "cobalt/script/v8c/interface_data.h"
+#include "cobalt/script/v8c/weak_heap_object_manager.h"
+#include "cobalt/script/v8c/wrapper_factory.h"
 #include "v8/include/libplatform/libplatform.h"
 #include "v8/include/v8.h"
 
@@ -45,17 +48,21 @@
   ~V8cGlobalEnvironment() override;
 
   void CreateGlobalObject() override;
+  template <typename GlobalInterface>
+  void CreateGlobalObject(
+      const scoped_refptr<GlobalInterface>& global_interface,
+      EnvironmentSettings* environment_settings);
 
   bool EvaluateScript(const scoped_refptr<SourceCode>& script, bool mute_errors,
                       std::string* out_result_utf8) override;
 
-  bool EvaluateScript(const scoped_refptr<SourceCode>& script_utf8,
-                      const scoped_refptr<Wrappable>& owning_object,
-                      bool mute_errors,
-                      base::optional<OpaqueHandleHolder::Reference>*
-                          out_opaque_handle) override;
+  bool EvaluateScript(
+      const scoped_refptr<SourceCode>& script_utf8,
+      const scoped_refptr<Wrappable>& owning_object, bool mute_errors,
+      base::optional<ValueHandleHolder::Reference>* out_value_handle) override;
 
-  std::vector<StackFrame> GetStackTrace(int max_frames = 0) override;
+  std::vector<StackFrame> GetStackTrace(int max_frames) override;
+  using GlobalEnvironment::GetStackTrace;
 
   void PreventGarbageCollection(
       const scoped_refptr<Wrappable>& wrappable) override;
@@ -87,6 +94,18 @@
     return v8::Local<v8::Context>::New(isolate_, context_);
   }
 
+  InterfaceData* GetInterfaceData(int key) {
+    DCHECK_GE(key, 0);
+    if (key >= cached_interface_data_.size()) {
+      cached_interface_data_.resize(key + 1);
+    }
+    return &cached_interface_data_[key];
+  }
+
+  WrapperFactory* wrapper_factory() { return wrapper_factory_.get(); }
+
+  WeakHeapObjectManager* weak_object_manager() { return &weak_object_manager_; }
+
  private:
   base::ThreadChecker thread_checker_;
   v8::Isolate* isolate_;
@@ -94,6 +113,11 @@
   int garbage_collection_count_;
 
   v8::Global<v8::Object> global_object_;
+  scoped_ptr<WrapperFactory> wrapper_factory_;
+
+  WeakHeapObjectManager weak_object_manager_;
+
+  std::vector<InterfaceData> cached_interface_data_;
 
   EnvironmentSettings* environment_settings_;
 
diff --git a/src/cobalt/script/v8c/v8c_script_value_factory.cc b/src/cobalt/script/v8c/v8c_script_value_factory.cc
new file mode 100644
index 0000000..62b04e6
--- /dev/null
+++ b/src/cobalt/script/v8c/v8c_script_value_factory.cc
@@ -0,0 +1,34 @@
+// Copyright 2017 Google Inc. All Rights Reserved.
+//
+// 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.
+
+#include "cobalt/script/v8c/v8c_script_value_factory.h"
+
+#include "cobalt/base/polymorphic_downcast.h"
+
+namespace cobalt {
+namespace script {
+
+// Implementation of template function declared in the base class.
+template <typename T>
+scoped_ptr<ScriptValue<Promise<T>>> ScriptValueFactory::CreatePromise() {
+  NOTIMPLEMENTED();
+  return make_scoped_ptr<ScriptValue<Promise<T>>>(nullptr);
+}
+
+}  // namespace script
+}  // namespace cobalt
+
+// Explicit template instantiations must go after the template function
+// implementation.
+#include "cobalt/script/script_value_factory_instantiations.h"
diff --git a/src/cobalt/script/v8c/v8c_script_value_factory.h b/src/cobalt/script/v8c/v8c_script_value_factory.h
new file mode 100644
index 0000000..02ce27d
--- /dev/null
+++ b/src/cobalt/script/v8c/v8c_script_value_factory.h
@@ -0,0 +1,41 @@
+// Copyright 2017 Google Inc. All Rights Reserved.
+//
+// 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.
+
+#ifndef COBALT_SCRIPT_V8C_V8C_SCRIPT_VALUE_FACTORY_H_
+#define COBALT_SCRIPT_V8C_V8C_SCRIPT_VALUE_FACTORY_H_
+
+#include "cobalt/script/script_value_factory.h"
+#include "cobalt/script/v8c/native_promise.h"
+#include "cobalt/script/v8c/v8c_global_environment.h"
+
+namespace cobalt {
+namespace script {
+namespace v8c {
+
+class V8cScriptValueFactory : public ScriptValueFactory {
+ public:
+  template <typename T>
+  scoped_ptr<ScriptValue<Promise<T>>> CreatePromise() {
+    typedef ScriptValue<Promise<T>> ScriptPromiseType;
+    typedef V8cUserObjectHolder<NativePromise<T>> V8cPromiseHolderType;
+    NOTIMPLEMENTED();
+    return make_scoped_ptr<ScriptValue<Promise<T>>>(nullptr);
+  }
+};
+
+}  // namespace v8c
+}  // namespace script
+}  // namespace cobalt
+
+#endif  // COBALT_SCRIPT_V8C_V8C_SCRIPT_VALUE_FACTORY_H_
diff --git a/src/cobalt/script/v8c/v8c_user_object_holder.h b/src/cobalt/script/v8c/v8c_user_object_holder.h
new file mode 100644
index 0000000..9d8d218
--- /dev/null
+++ b/src/cobalt/script/v8c/v8c_user_object_holder.h
@@ -0,0 +1,78 @@
+// Copyright 2017 Google Inc. All Rights Reserved.
+//
+// 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.
+
+#ifndef COBALT_SCRIPT_V8C_V8C_USER_OBJECT_HOLDER_H_
+#define COBALT_SCRIPT_V8C_V8C_USER_OBJECT_HOLDER_H_
+
+#include "cobalt/script/script_value.h"
+#include "cobalt/script/v8c/v8c_global_environment.h"
+#include "cobalt/script/v8c/weak_heap_object.h"
+#include "cobalt/script/v8c/wrapper_private.h"
+#include "v8/include/v8.h"
+
+namespace cobalt {
+namespace script {
+namespace v8c {
+
+// Template class that implements the ScriptValue template class for lifetime
+// management of User Objects passed from the bindings layer into Cobalt. See
+// the definition of ScriptValue for further detail.
+// This class does not root the underlying v8::Object that V8cUserObjectType
+// holds a reference to. The object will be traced when any owning objects are
+// traced.
+template <typename V8cUserObjectType>
+class V8cUserObjectHolder
+    : public ScriptValue<typename V8cUserObjectType::BaseType> {
+ public:
+  typedef ScriptValue<typename V8cUserObjectType::BaseType> BaseClass;
+
+  V8cUserObjectHolder() : env_(nullptr), prevent_garbage_collection_count_(0) {}
+
+  V8cUserObjectHolder(V8cGlobalEnvironment* env, v8::Local<v8::Value> value)
+      : env_(env),
+        handle_(V8cUserObjectType(env, value)),
+        prevent_garbage_collection_count_(0) {}
+
+  void RegisterOwner(Wrappable* owner) override { NOTIMPLEMENTED(); }
+  void DeregisterOwner(Wrappable* owner) override { NOTIMPLEMENTED(); }
+  void PreventGarbageCollection() override { NOTIMPLEMENTED(); }
+  void AllowGarbageCollection() override { NOTIMPLEMENTED(); }
+  scoped_ptr<BaseClass> MakeCopy() const override {
+    DCHECK(handle_);
+    v8::Local<v8::Value> value = handle_->value();
+    return make_scoped_ptr<BaseClass>(new V8cUserObjectHolder(env_, value));
+  }
+  bool EqualTo(const BaseClass& other) const override {
+    NOTIMPLEMENTED();
+    return false;
+  }
+  const typename V8cUserObjectType::BaseType* GetScriptValue() const override {
+    NOTIMPLEMENTED();
+    return nullptr;
+  }
+
+  v8::Local<v8::Value> v8_value() const { return handle_->value(); }
+
+ private:
+  V8cGlobalEnvironment* env_;
+  base::optional<V8cUserObjectType> handle_;
+  int prevent_garbage_collection_count_;
+  v8::Global<v8::Value> persistent_root_;
+};
+
+}  // namespace v8c
+}  // namespace script
+}  // namespace cobalt
+
+#endif  // COBALT_SCRIPT_V8C_V8C_USER_OBJECT_HOLDER_H_
diff --git a/src/cobalt/script/v8c/v8c_value_handle.h b/src/cobalt/script/v8c/v8c_value_handle.h
new file mode 100644
index 0000000..c6722f0
--- /dev/null
+++ b/src/cobalt/script/v8c/v8c_value_handle.h
@@ -0,0 +1,62 @@
+// Copyright 2017 Google Inc. All Rights Reserved.
+//
+// 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.
+
+#ifndef COBALT_SCRIPT_V8C_V8C_VALUE_HANDLE_H_
+#define COBALT_SCRIPT_V8C_V8C_VALUE_HANDLE_H_
+
+#include "base/optional.h"
+#include "cobalt/script/v8c/type_traits.h"
+#include "cobalt/script/v8c/v8c_user_object_holder.h"
+#include "cobalt/script/v8c/weak_heap_object.h"
+#include "cobalt/script/value_handle.h"
+#include "v8/include/v8.h"
+
+namespace cobalt {
+namespace script {
+namespace v8c {
+
+// A wrapper around a v8::Value that can be passed into Cobalt as a script
+// value object.
+//
+// An ValueHandle is never passed into Cobalt as-is, but only when wrapped as a
+// ScriptValue<ValueHandle>.
+class V8cValueHandle : public ValueHandle {
+ public:
+  typedef ValueHandle BaseType;
+
+  v8::Local<v8::Value> value() const { return handle_.GetValue(); }
+
+ private:
+  V8cValueHandle(V8cGlobalEnvironment* env, v8::Local<v8::Value> value)
+      : handle_(env, value) {}
+
+  WeakHeapObject handle_;
+
+  friend class V8cUserObjectHolder<V8cValueHandle>;
+  friend class base::optional<V8cValueHandle>;
+};
+
+typedef V8cUserObjectHolder<V8cValueHandle> V8cValueHandleHolder;
+
+template <>
+struct TypeTraits<ValueHandle> {
+  typedef V8cValueHandleHolder ConversionType;
+  typedef const ScriptValue<ValueHandle>* ReturnType;
+};
+
+}  // namespace v8c
+}  // namespace script
+}  // namespace cobalt
+
+#endif  // COBALT_SCRIPT_V8C_V8C_VALUE_HANDLE_H_
diff --git a/src/cobalt/script/v8c/v8c_wrapper_handle.h b/src/cobalt/script/v8c/v8c_wrapper_handle.h
new file mode 100644
index 0000000..7432de2
--- /dev/null
+++ b/src/cobalt/script/v8c/v8c_wrapper_handle.h
@@ -0,0 +1,56 @@
+// Copyright 2017 Google Inc. All Rights Reserved.
+//
+// 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.
+
+#ifndef COBALT_SCRIPT_V8C_V8C_WRAPPER_HANDLE_H_
+#define COBALT_SCRIPT_V8C_V8C_WRAPPER_HANDLE_H_
+
+#include "base/memory/weak_ptr.h"
+#include "cobalt/base/polymorphic_downcast.h"
+#include "cobalt/script/v8c/wrapper_private.h"
+#include "cobalt/script/wrappable.h"
+
+namespace cobalt {
+namespace script {
+namespace v8c {
+
+// Implements Wrappable::WeakWrapperHandler and thus represents the cached
+// JS wrapper for a given Wrappable. The Wrapper could be garbage collected
+// at any time.
+struct V8cWrapperHandle : public Wrappable::WeakWrapperHandle {
+ public:
+  explicit V8cWrapperHandle(WrapperPrivate* wrapper_private) {
+    DCHECK(wrapper_private);
+    weak_wrapper_private_ = wrapper_private->AsWeakPtr();
+  }
+
+  static v8::MaybeLocal<v8::Object> GetObject(
+      v8::Isolate* isolate, const Wrappable::WeakWrapperHandle* handle) {
+    if (handle) {
+      const V8cWrapperHandle* v8c_handle =
+          base::polymorphic_downcast<const V8cWrapperHandle*>(handle);
+      if (v8c_handle->weak_wrapper_private_) {
+        return v8c_handle->weak_wrapper_private_->wrapper();
+      }
+    }
+    return {};
+  }
+
+  base::WeakPtr<WrapperPrivate> weak_wrapper_private_;
+};
+
+}  // namespace v8c
+}  // namespace script
+}  // namespace cobalt
+
+#endif  // COBALT_SCRIPT_V8C_V8C_WRAPPER_HANDLE_H_
diff --git a/src/cobalt/script/v8c/weak_heap_object.h b/src/cobalt/script/v8c/weak_heap_object.h
new file mode 100644
index 0000000..0c0b67f
--- /dev/null
+++ b/src/cobalt/script/v8c/weak_heap_object.h
@@ -0,0 +1,74 @@
+// Copyright 2017 Google Inc. All Rights Reserved.
+//
+// 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.
+
+#ifndef COBALT_SCRIPT_V8C_WEAK_HEAP_OBJECT_H_
+#define COBALT_SCRIPT_V8C_WEAK_HEAP_OBJECT_H_
+
+#include "cobalt/script/v8c/v8c_global_environment.h"
+#include "cobalt/script/v8c/weak_heap_object_manager.h"
+#include "v8/include/v8.h"
+
+namespace cobalt {
+namespace script {
+namespace v8c {
+
+// This class implements a weak reference to a v8::Value. The v8::Value that
+// an instance of this class is created with may get garbage collected. In
+// that case, subsequent calls to WeakHeapObject::Get() will return a NULL
+// pointer.
+class WeakHeapObject {
+ public:
+  WeakHeapObject(V8cGlobalEnvironment* env, v8::Local<v8::Value> value)
+      : env_(env),
+        weak_object_manager_(env->weak_object_manager()),
+        value_(env->isolate(), value),
+        was_collected_(false) {
+    weak_object_manager_->StartTracking(this);
+  }
+
+  WeakHeapObject(const WeakHeapObject& other)
+      : env_(other.env_),
+        was_collected_(other.was_collected_),
+        weak_object_manager_(other.weak_object_manager_),
+        value_(env_->isolate(), other.value_.Get(env_->isolate())) {
+    weak_object_manager_->StartTracking(this);
+  }
+
+  WeakHeapObject& operator=(const WeakHeapObject& rhs) {
+    env_ = rhs.env_;
+    was_collected_ = rhs.was_collected_;
+    weak_object_manager_ = rhs.weak_object_manager_;
+    value_.Reset(env_->isolate(), rhs.value_.Get(env_->isolate()));
+    weak_object_manager_->StartTracking(this);
+    return *this;
+  }
+
+  ~WeakHeapObject() { weak_object_manager_->StopTracking(this); }
+
+  v8::Local<v8::Value> GetValue() const { return value_.Get(env_->isolate()); }
+
+ private:
+  V8cGlobalEnvironment* env_;
+  WeakHeapObjectManager* weak_object_manager_;
+  v8::Persistent<v8::Value, v8::CopyablePersistentTraits<v8::Value>> value_;
+  bool was_collected_;
+
+  friend class WeakHeapObjectManager;
+};
+
+}  // namespace v8c
+}  // namespace script
+}  // namespace cobalt
+
+#endif  // COBALT_SCRIPT_V8C_WEAK_HEAP_OBJECT_H_
diff --git a/src/cobalt/script/v8c/weak_heap_object_manager.h b/src/cobalt/script/v8c/weak_heap_object_manager.h
new file mode 100644
index 0000000..1555eac
--- /dev/null
+++ b/src/cobalt/script/v8c/weak_heap_object_manager.h
@@ -0,0 +1,76 @@
+// Copyright 2017 Google Inc. All Rights Reserved.
+//
+// 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.
+
+#ifndef COBALT_SCRIPT_V8C_WEAK_HEAP_OBJECT_MANAGER_H_
+#define COBALT_SCRIPT_V8C_WEAK_HEAP_OBJECT_MANAGER_H_
+
+#include <utility>
+#include <vector>
+
+#include "base/hash_tables.h"
+
+namespace cobalt {
+namespace script {
+namespace v8c {
+
+class WeakHeapObject;
+
+// WeakHeapObjectManager holds a reference to all WeakHeapObject instances.
+// The SweepUnmarkedObjects function should be called during garbage
+// collection after the marking phase. The underlying v8::Persistent handle
+// for any unmarked handles will be set to NULL.
+class WeakHeapObjectManager {
+ public:
+  // Iterates over all WeakHeapObjects and sets their v8::Global handles to
+  // NULL if the objects to which they hold a reference are about to be
+  // finalized.
+  void SweepUnmarkedObjects();
+  ~WeakHeapObjectManager() {
+    // TODO: Change this to a DCHECK once it works.
+    if (!weak_objects_.empty()) {
+      LOG(ERROR) << "Expected |weak_heap_objects_| to be empty in "
+                    "~WeakHeapObjectManager.";
+    }
+  }
+
+ private:
+  void StartTracking(WeakHeapObject* weak_object) {
+    std::pair<WeakHeapObjects::iterator, bool> pib =
+        weak_objects_.insert(weak_object);
+    DCHECK(pib.second) << "WeakHeapObject was already being tracked.";
+  }
+  void StopTracking(WeakHeapObject* weak_object) {
+    // The WeakHeapObject may have already been removed from the weak_objects_
+    // set during the sweep phase.
+    WeakHeapObjects::iterator it = weak_objects_.find(weak_object);
+    if (it != weak_objects_.end()) {
+      weak_objects_.erase(it);
+    }
+  }
+
+  // Returns true if the underlying pointer is NULL, which will be the case if
+  // the object has been swept.
+  bool MaybeSweep(WeakHeapObject* weak_object);
+
+  typedef base::hash_set<WeakHeapObject*> WeakHeapObjects;
+  WeakHeapObjects weak_objects_;
+
+  friend class WeakHeapObject;
+};
+
+}  // namespace v8c
+}  // namespace script
+}  // namespace cobalt
+
+#endif  // COBALT_SCRIPT_V8C_WEAK_HEAP_OBJECT_MANAGER_H_
diff --git a/src/cobalt/script/v8c/wrapper_factory.cc b/src/cobalt/script/v8c/wrapper_factory.cc
new file mode 100644
index 0000000..dae2b5c
--- /dev/null
+++ b/src/cobalt/script/v8c/wrapper_factory.cc
@@ -0,0 +1,76 @@
+// Copyright 2017 Google Inc. All Rights Reserved.
+//
+// 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.
+
+#include "cobalt/script/v8c/wrapper_factory.h"
+
+#include <utility>
+
+#include "base/lazy_instance.h"
+#include "cobalt/base/polymorphic_downcast.h"
+#include "cobalt/script/v8c/v8c_global_environment.h"
+#include "cobalt/script/v8c/v8c_wrapper_handle.h"
+#include "cobalt/script/v8c/wrapper_private.h"
+#include "v8/include/v8.h"
+
+namespace cobalt {
+namespace script {
+namespace v8c {
+
+void WrapperFactory::RegisterWrappableType(
+    base::TypeId wrappable_type, const CreateWrapperFunction& create_function,
+    const PrototypeClassFunction& class_function) {
+  std::pair<WrappableTypeFunctionsHashMap::iterator, bool> pib =
+      wrappable_type_functions_.insert(std::make_pair(
+          wrappable_type,
+          WrappableTypeFunctions(create_function, class_function)));
+  DCHECK(pib.second)
+      << "RegisterWrappableType registered for type more than once.";
+}
+
+v8::Local<v8::Object> WrapperFactory::GetWrapper(
+    const scoped_refptr<Wrappable>& wrappable) {
+  v8::Local<v8::Object> wrapper;
+  v8::MaybeLocal<v8::Object> maybe_wrapper = V8cWrapperHandle::GetObject(
+      env_->isolate(), GetCachedWrapper(wrappable.get()));
+  if (!maybe_wrapper.ToLocal(&wrapper)) {
+    scoped_ptr<Wrappable::WeakWrapperHandle> object_handle =
+        CreateWrapper(wrappable);
+    SetCachedWrapper(wrappable.get(), object_handle.Pass());
+    wrapper = V8cWrapperHandle::GetObject(env_->isolate(),
+                                          GetCachedWrapper(wrappable.get()))
+                  .ToLocalChecked();
+  }
+  return wrapper;
+}
+
+scoped_ptr<Wrappable::WeakWrapperHandle> WrapperFactory::CreateWrapper(
+    const scoped_refptr<Wrappable>& wrappable) const {
+  WrappableTypeFunctionsHashMap::const_iterator it =
+      wrappable_type_functions_.find(wrappable->GetWrappableType());
+  if (it == wrappable_type_functions_.end()) {
+    NOTREACHED();
+    return scoped_ptr<Wrappable::WeakWrapperHandle>();
+  }
+  v8::Local<v8::Object> new_object =
+      it->second.create_wrapper.Run(env_, wrappable);
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromWrapperObject(new_object);
+  DCHECK(wrapper_private);
+  return make_scoped_ptr<Wrappable::WeakWrapperHandle>(
+      new V8cWrapperHandle(wrapper_private));
+}
+
+}  // namespace v8c
+}  // namespace script
+}  // namespace cobalt
diff --git a/src/cobalt/script/v8c/wrapper_factory.h b/src/cobalt/script/v8c/wrapper_factory.h
new file mode 100644
index 0000000..5891542
--- /dev/null
+++ b/src/cobalt/script/v8c/wrapper_factory.h
@@ -0,0 +1,72 @@
+// Copyright 2017 Google Inc. All Rights Reserved.
+//
+// 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.
+
+#ifndef COBALT_SCRIPT_V8C_WRAPPER_FACTORY_H_
+#define COBALT_SCRIPT_V8C_WRAPPER_FACTORY_H_
+
+#include "base/hash_tables.h"
+#include "cobalt/script/wrappable.h"
+#include "v8/include/v8.h"
+
+namespace cobalt {
+namespace script {
+namespace v8c {
+
+class V8cGlobalEnvironment;
+
+// Holds a mapping between Wrappable types and base::Callbacks that create new
+// Wrapper objects corresponding to the Wrappable type.
+class WrapperFactory : public Wrappable::CachedWrapperAccessor {
+ public:
+  // Callback to create a new v8::Object that is a wrapper for the Wrappable.
+  typedef base::Callback<v8::Local<v8::Object>(V8cGlobalEnvironment*,
+                                               const scoped_refptr<Wrappable>&)>
+      CreateWrapperFunction;
+
+  // Callback to get v8::FunctionTemplate of prototype.
+  typedef base::Callback<v8::Local<v8::FunctionTemplate>(V8cGlobalEnvironment*)>
+      PrototypeClassFunction;
+
+  explicit WrapperFactory(V8cGlobalEnvironment* env) : env_(env) {}
+
+  void RegisterWrappableType(base::TypeId wrappable_type,
+                             const CreateWrapperFunction& create_function,
+                             const PrototypeClassFunction& class_function);
+
+  v8::Local<v8::Object> GetWrapper(const scoped_refptr<Wrappable>& wrappable);
+
+ private:
+  struct WrappableTypeFunctions {
+    CreateWrapperFunction create_wrapper;
+    PrototypeClassFunction prototype_class;
+    WrappableTypeFunctions(const CreateWrapperFunction& create_wrapper,
+                           const PrototypeClassFunction& prototype_class)
+        : create_wrapper(create_wrapper), prototype_class(prototype_class) {}
+  };
+
+  scoped_ptr<Wrappable::WeakWrapperHandle> CreateWrapper(
+      const scoped_refptr<Wrappable>& wrappable) const;
+
+  typedef base::hash_map<base::TypeId, WrappableTypeFunctions>
+      WrappableTypeFunctionsHashMap;
+
+  V8cGlobalEnvironment* env_;
+  WrappableTypeFunctionsHashMap wrappable_type_functions_;
+};
+
+}  // namespace v8c
+}  // namespace script
+}  // namespace cobalt
+
+#endif  // COBALT_SCRIPT_V8C_WRAPPER_FACTORY_H_
diff --git a/src/cobalt/script/v8c/wrapper_private.h b/src/cobalt/script/v8c/wrapper_private.h
new file mode 100644
index 0000000..9bb57cd
--- /dev/null
+++ b/src/cobalt/script/v8c/wrapper_private.h
@@ -0,0 +1,71 @@
+// Copyright 2017 Google Inc. All Rights Reserved.
+//
+// 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.
+
+#ifndef COBALT_SCRIPT_V8C_WRAPPER_PRIVATE_H_
+#define COBALT_SCRIPT_V8C_WRAPPER_PRIVATE_H_
+
+#include "base/memory/weak_ptr.h"
+#include "cobalt/base/polymorphic_downcast.h"
+#include "v8/include/v8.h"
+
+namespace cobalt {
+namespace script {
+namespace v8c {
+
+// Contains private data associated with a v8::Object representing a
+// JavaScript wrapper for a Cobalt platform object. There should be a one-to-
+// one mapping of such v8::Object and WrapperPrivate instances, and the
+// corresponding WrapperPrivate must be destroyed when its v8::Object is
+// garbage collected.
+struct WrapperPrivate : public base::SupportsWeakPtr<WrapperPrivate> {
+ public:
+  static void Callback(const v8::WeakCallbackInfo<WrapperPrivate>& data) {
+    data.GetParameter()->wrapper_.Reset();
+    delete data.GetParameter();
+  }
+
+  static WrapperPrivate* GetFromWrapperObject(v8::Local<v8::Object> object) {
+    DCHECK(object->InternalFieldCount() == 1);
+    v8::Local<v8::External> external =
+        v8::Local<v8::External>::Cast(object->GetInternalField(0));
+    return static_cast<WrapperPrivate*>(external->Value());
+  }
+
+  WrapperPrivate(v8::Isolate* isolate,
+                 const scoped_refptr<Wrappable>& wrappable,
+                 v8::Local<v8::Object> wrapper)
+      : isolate_(isolate), wrappable_(wrappable), wrapper_(isolate, wrapper) {
+    wrapper->SetInternalField(0, v8::External::New(isolate, this));
+    wrapper_.SetWeak(this, &WrapperPrivate::Callback,
+                     v8::WeakCallbackType::kParameter);
+  }
+
+  template <typename T>
+  scoped_refptr<T> wrappable() const {
+    return base::polymorphic_downcast<T*>(wrappable_.get());
+  }
+
+  v8::Local<v8::Object> wrapper() const { return wrapper_.Get(isolate_); }
+
+ private:
+  v8::Isolate* isolate_;
+  scoped_refptr<Wrappable> wrappable_;
+  v8::Global<v8::Object> wrapper_;
+};
+
+}  // namespace v8c
+}  // namespace script
+}  // namespace cobalt
+
+#endif  // COBALT_SCRIPT_V8C_WRAPPER_PRIVATE_H_
diff --git a/src/cobalt/script/value_handle.h b/src/cobalt/script/value_handle.h
index 373b15f..bb94c60 100644
--- a/src/cobalt/script/value_handle.h
+++ b/src/cobalt/script/value_handle.h
@@ -11,6 +11,7 @@
 // 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.
+
 #ifndef COBALT_SCRIPT_VALUE_HANDLE_H_
 #define COBALT_SCRIPT_VALUE_HANDLE_H_
 
@@ -19,8 +20,9 @@
 namespace cobalt {
 namespace script {
 
-// A handle to a script value that is managed by the JavaScript Engine. This is
-// not required to be a Javascript Object, unlike OpaqueHandle.
+// A handle to a script value that is managed by the JavaScript engine. Note
+// that this can be any JavaScript Value type (null, undefined, Boolean,
+// Number, String, Object, and Symbol), rather than just Object.
 class ValueHandle {
  protected:
   ValueHandle() {}
diff --git a/src/cobalt/script/wrappable.h b/src/cobalt/script/wrappable.h
index e803fe4..86eaa0a 100644
--- a/src/cobalt/script/wrappable.h
+++ b/src/cobalt/script/wrappable.h
@@ -11,6 +11,7 @@
 // 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.
+
 #ifndef COBALT_SCRIPT_WRAPPABLE_H_
 #define COBALT_SCRIPT_WRAPPABLE_H_
 
@@ -44,7 +45,7 @@
     friend class scoped_ptr<WeakWrapperHandle>;
   };
 
-  // A class that creates OpaqueHandles should inherit from this interface
+  // A class that creates ValueHandles should inherit from this interface
   // so that it can get/set the cached wrapper handle.
   class CachedWrapperAccessor {
    protected:
diff --git a/src/cobalt/system_window/input_event.h b/src/cobalt/system_window/input_event.h
index 12eae54..ce7dd5f 100644
--- a/src/cobalt/system_window/input_event.h
+++ b/src/cobalt/system_window/input_event.h
@@ -15,6 +15,8 @@
 #ifndef COBALT_SYSTEM_WINDOW_INPUT_EVENT_H_
 #define COBALT_SYSTEM_WINDOW_INPUT_EVENT_H_
 
+#include <string>
+
 #include "cobalt/base/event.h"
 #include "cobalt/math/point_f.h"
 #include "starboard/event.h"
@@ -28,6 +30,7 @@
     kKeyDown,
     kKeyUp,
     kKeyMove,
+    kInput,
     kPointerDown,
     kPointerUp,
     kPointerMove,
@@ -60,7 +63,11 @@
              float pressure = 0, const math::PointF& size = math::PointF(),
              const math::PointF& tilt = math::PointF()
 #endif
-                 )
+#if SB_HAS(ON_SCREEN_KEYBOARD)
+                 ,
+             const std::string& input_text = ""
+#endif  // SB_HAS(ON_SCREEN_KEYBOARD)
+             )
       : type_(type),
         device_id_(device_id),
         key_code_(key_code),
@@ -74,9 +81,15 @@
         size_(size),
         tilt_(tilt)
 #endif
+#if SB_HAS(ON_SCREEN_KEYBOARD)
+        ,
+        input_text_(input_text)
+#endif  // SB_HAS(ON_SCREEN_KEYBOARD)
   {
   }
 
+  ~InputEvent() {}
+
   Type type() const { return type_; }
   int key_code() const { return key_code_; }
   int device_id() const { return device_id_; }
@@ -89,6 +102,9 @@
   const math::PointF& size() const { return size_; }
   const math::PointF& tilt() const { return tilt_; }
 #endif
+#if SB_HAS(ON_SCREEN_KEYBOARD)
+  const std::string& input_text() const { return input_text_; }
+#endif  // SB_HAS(ON_SCREEN_KEYBOARD)
 
   BASE_EVENT_SUBCLASS(InputEvent);
 
@@ -105,6 +121,9 @@
   math::PointF size_;
   math::PointF tilt_;
 #endif
+#if SB_HAS(ON_SCREEN_KEYBOARD)
+  std::string input_text_;
+#endif  // SB_HAS(ON_SCREEN_KEYBOARD)
 };
 
 // The Starboard Event handler SbHandleEvent should call this function on
diff --git a/src/cobalt/system_window/system_window.cc b/src/cobalt/system_window/system_window.cc
index 61d3b47..181cf09 100644
--- a/src/cobalt/system_window/system_window.cc
+++ b/src/cobalt/system_window/system_window.cc
@@ -126,12 +126,22 @@
     }
   }
 
+#if SB_HAS(ON_SCREEN_KEYBOARD)
+  scoped_ptr<InputEvent> input_event(
+      new InputEvent(type, data.device_id, key_code, modifiers, is_repeat,
+                     math::PointF(data.position.x, data.position.y),
+                     math::PointF(data.delta.x, data.delta.y), pressure,
+                     math::PointF(data.size.x, data.size.y),
+                     math::PointF(data.tilt.x, data.tilt.y),
+                     data.input_text ? data.input_text : ""));
+#else   // SB_HAS(ON_SCREEN_KEYBOARD)
   scoped_ptr<InputEvent> input_event(
       new InputEvent(type, data.device_id, key_code, modifiers, is_repeat,
                      math::PointF(data.position.x, data.position.y),
                      math::PointF(data.delta.x, data.delta.y), pressure,
                      math::PointF(data.size.x, data.size.y),
                      math::PointF(data.tilt.x, data.tilt.y)));
+#endif  // SB_HAS(ON_SCREEN_KEYBOARD)
 #else
   scoped_ptr<InputEvent> input_event(
       new InputEvent(type, data.device_id, key_code, data.key_modifiers,
@@ -181,7 +191,6 @@
 
 void SystemWindow::HandleInputEvent(const SbInputData& data) {
   DCHECK_EQ(window_, data.window);
-
   // Handle supported pointer device types.
   if ((kSbInputDeviceTypeMouse == data.device_type) ||
       (kSbInputDeviceTypeTouchScreen == data.device_type) ||
@@ -206,14 +215,18 @@
       DispatchInputEvent(data, InputEvent::kKeyMove, false /* is_repeat */);
       break;
     }
+#if SB_HAS(ON_SCREEN_KEYBOARD)
+    case kSbInputEventTypeInput: {
+      DispatchInputEvent(data, InputEvent::kInput, false /* is_repeat */);
+      break;
+    }
+#endif  // SB_HAS(ON_SCREEN_KEYBOARD)
     default:
       break;
   }
 }
 
-SystemWindow* SystemWindow::PrimaryWindow() {
-  return g_the_window;
-}
+SystemWindow* SystemWindow::PrimaryWindow() { return g_the_window; }
 
 void HandleInputEvent(const SbEvent* event) {
   if (event->type != kSbEventTypeInput) {
diff --git a/src/cobalt/tools/webdriver_benchmark_config.py b/src/cobalt/tools/webdriver_benchmark_config.py
index 5b920ed..5d0a2f7 100644
--- a/src/cobalt/tools/webdriver_benchmark_config.py
+++ b/src/cobalt/tools/webdriver_benchmark_config.py
@@ -14,8 +14,8 @@
 # limitations under the License.
 """Class for configuring Webdriver Benchmarks."""
 
-
 PERFORMANCE_TEST = 'performance'
+PRELOAD_TEST = 'preload'
 SANITY_TEST = 'sanity'
 
 # WEBDRIVER SCRIPT CONFIGURATION PARAMETERS
@@ -25,11 +25,7 @@
 
 DISABLE_VIDEOS = '--disable_videos'
 
-SAMPLE_SIZES = [
-    MINIMAL_SIZE,
-    REDUCED_SIZE,
-    STANDARD_SIZE
-]
+SAMPLE_SIZES = [MINIMAL_SIZE, REDUCED_SIZE, STANDARD_SIZE]
 
 # COBALT COMMAND LINE PARAMETERS
 DISABLE_SPLASH_SCREEN_ON_RELOADS = '--disable_splash_screen_on_reloads'
diff --git a/src/cobalt/version.h b/src/cobalt/version.h
index 88582da..b28dd7e 100644
--- a/src/cobalt/version.h
+++ b/src/cobalt/version.h
@@ -15,6 +15,6 @@
 #define COBALT_VERSION_H_
 
 // Cobalt release number.
-#define COBALT_VERSION "13"
+#define COBALT_VERSION "14"
 
 #endif  // COBALT_VERSION_H_
diff --git a/src/cobalt/webdriver/script_executor.h b/src/cobalt/webdriver/script_executor.h
index 9cdf810..50dc161 100644
--- a/src/cobalt/webdriver/script_executor.h
+++ b/src/cobalt/webdriver/script_executor.h
@@ -24,8 +24,8 @@
 #include "base/threading/thread_checker.h"
 #include "cobalt/dom/element.h"
 #include "cobalt/script/callback_function.h"
-#include "cobalt/script/opaque_handle.h"
 #include "cobalt/script/script_value.h"
+#include "cobalt/script/value_handle.h"
 #include "cobalt/script/wrappable.h"
 #include "cobalt/webdriver/element_mapping.h"
 #include "cobalt/webdriver/protocol/element_id.h"
diff --git a/src/cobalt/webdriver/script_executor_params.h b/src/cobalt/webdriver/script_executor_params.h
index 57754a3..ae4e02f 100644
--- a/src/cobalt/webdriver/script_executor_params.h
+++ b/src/cobalt/webdriver/script_executor_params.h
@@ -23,7 +23,7 @@
 #include "base/threading/thread_checker.h"
 #include "base/time.h"
 #include "cobalt/script/global_environment.h"
-#include "cobalt/script/opaque_handle.h"
+#include "cobalt/script/value_handle.h"
 #include "cobalt/script/wrappable.h"
 
 namespace cobalt {
@@ -78,7 +78,7 @@
       const std::string& function_body, const std::string& json_args,
       base::optional<base::TimeDelta> async_timeout);
 
-  const script::OpaqueHandleHolder* function_object() {
+  const script::ValueHandleHolder* function_object() {
     return function_object_ ? &function_object_->referenced_value() : NULL;
   }
   const std::string& json_args() { return json_args_; }
@@ -88,7 +88,7 @@
 
  private:
   std::string function_body_;
-  base::optional<script::OpaqueHandleHolder::Reference> function_object_;
+  base::optional<script::ValueHandleHolder::Reference> function_object_;
   std::string json_args_;
   base::optional<int32_t> async_timeout_;
 };
diff --git a/src/glimp/gles/buffer.cc b/src/glimp/gles/buffer.cc
index 5e03c06..b2be59d 100644
--- a/src/glimp/gles/buffer.cc
+++ b/src/glimp/gles/buffer.cc
@@ -40,19 +40,21 @@
 Buffer::Buffer(nb::scoped_ptr<BufferImpl> impl)
     : impl_(impl.Pass()), size_in_bytes_(0) {}
 
-void Buffer::Allocate(GLenum usage, size_t size) {
+bool Buffer::Allocate(GLenum usage, size_t size) {
   size_in_bytes_ = size;
-  impl_->Allocate(GLUsageEnumToUsage(usage), size);
+  return impl_->Allocate(GLUsageEnumToUsage(usage), size);
 }
 
-void Buffer::SetData(GLintptr offset, GLsizeiptr size, const GLvoid* data) {
+bool Buffer::SetData(GLintptr offset, GLsizeiptr size, const GLvoid* data) {
   SB_DCHECK(size_in_bytes_ >= offset + size);
   SB_DCHECK(offset >= 0);
   SB_DCHECK(size >= 0);
   SB_DCHECK(!is_mapped_);
 
   if (size > 0) {
-    impl_->SetData(offset, static_cast<size_t>(size), data);
+    return impl_->SetData(offset, static_cast<size_t>(size), data);
+  } else {
+    return true;
   }
 }
 
diff --git a/src/glimp/gles/buffer.h b/src/glimp/gles/buffer.h
index 85cb462..cd6c491 100644
--- a/src/glimp/gles/buffer.h
+++ b/src/glimp/gles/buffer.h
@@ -30,11 +30,13 @@
  public:
   explicit Buffer(nb::scoped_ptr<BufferImpl> impl);
 
-  // Allocates memory within this Buffer object.
-  void Allocate(GLenum usage, size_t size);
+  // Allocates memory within this Buffer object.  Returns false if there
+  // was an allocation failure.
+  bool Allocate(GLenum usage, size_t size);
 
-  // Implements support for glBufferData() on this buffer object.
-  void SetData(GLintptr offset, GLsizeiptr size, const GLvoid* data);
+  // Implements support for glBufferData() on this buffer object.  Returns
+  // false if there was an allocation failure.
+  bool SetData(GLintptr offset, GLsizeiptr size, const GLvoid* data);
 
   // Maps the buffer's memory to a CPU-accessible pointer and returns it, or
   // NULL on failure.
diff --git a/src/glimp/gles/buffer_impl.h b/src/glimp/gles/buffer_impl.h
index e44502f..2845a02 100644
--- a/src/glimp/gles/buffer_impl.h
+++ b/src/glimp/gles/buffer_impl.h
@@ -40,17 +40,18 @@
   // Sets the size and usage of allocated memory for the buffer.
   // Since no data is available at this point, implementations are free to
   // delay the actual allocation of memory until data is provided.  Called from
-  // glBufferData().
+  // glBufferData().  Returns true on success and false on failure.
   //   https://www.khronos.org/opengles/sdk/docs/man/xhtml/glBufferData.xml
-  virtual void Allocate(Usage usage, size_t size) = 0;
+  virtual bool Allocate(Usage usage, size_t size) = 0;
 
   // Upload the specified data into this buffer.  Allocate() must have
   // previously been called for a call to SetData() to be valid.
   // This method is called by glBufferData() (when data is not NULL) and
-  // glBufferSubData().
+  // glBufferSubData().  Returns true on success and false on an allocation
+  // failure.
   //   https://www.khronos.org/opengles/sdk/docs/man/xhtml/glBufferData.xml
   //   https://www.khronos.org/opengles/sdk/docs/man/xhtml/glBufferSubData.xml
-  virtual void SetData(intptr_t offset, size_t size, const void* data) = 0;
+  virtual bool SetData(intptr_t offset, size_t size, const void* data) = 0;
 
   // Maps the buffer's data to a CPU-addressible memory location and then
   // returns a pointer to that location.  This method is called when
diff --git a/src/glimp/gles/context.cc b/src/glimp/gles/context.cc
index efb5067..027db79 100644
--- a/src/glimp/gles/context.cc
+++ b/src/glimp/gles/context.cc
@@ -788,9 +788,16 @@
     bound_buffer->Unmap();
   }
 
-  bound_buffer->Allocate(usage, size);
+  if (!bound_buffer->Allocate(usage, size)) {
+    SetError(GL_OUT_OF_MEMORY);
+    return;
+  }
+
   if (data) {
-    bound_buffer->SetData(0, size, data);
+    if (!bound_buffer->SetData(0, size, data)) {
+      SetError(GL_OUT_OF_MEMORY);
+      return;
+    }
   }
 }
 
@@ -830,7 +837,10 @@
   // Nothing in the specification says there should be an error if data
   // is NULL.
   if (data) {
-    bound_buffer->SetData(offset, size, data);
+    if (!bound_buffer->SetData(offset, size, data)) {
+      SetError(GL_OUT_OF_MEMORY);
+      return;
+    }
   }
 }
 
@@ -905,7 +915,12 @@
   SB_DCHECK(length == bound_buffer->size_in_bytes())
       << "glimp only supports mapping the entire buffer.";
 
-  return bound_buffer->Map();
+  void* mapped = bound_buffer->Map();
+  if (!mapped) {
+    SetError(GL_OUT_OF_MEMORY);
+  }
+
+  return mapped;
 }
 
 bool Context::UnmapBuffer(GLenum target) {
@@ -1360,6 +1375,13 @@
 
   if (width < 0 || height < 0 || level < 0 || border != 0) {
     SetError(GL_INVALID_VALUE);
+    return;
+  }
+
+  int max_texture_size = impl_->GetMaxTextureSize();
+  if (width > max_texture_size || height > max_texture_size) {
+    SetError(GL_INVALID_VALUE);
+    return;
   }
 
   if (format != internalformat) {
diff --git a/src/starboard/CHANGELOG.md b/src/starboard/CHANGELOG.md
index 0ff2bcf..6b5f87e 100644
--- a/src/starboard/CHANGELOG.md
+++ b/src/starboard/CHANGELOG.md
@@ -10,19 +10,25 @@
 
 ## Version 8
 
-### Add SbPlayerCreateWithUrl(), SbPlayerSetDrmSystem(), SbPlayerOutputModeSupportedWithUrl()
+### Add `SbPlayerCreateWithUrl()`, `SbPlayerSetDrmSystem()`, `SbPlayerOutputModeSupportedWithUrl()`
 
 For platform media players that rely on using a URL (like an m3u playlist URL)
-for playback, add SbPlayerCreateWithUrl() which takes in a URL, no video or audio
+for playback, add `SbPlayerCreateWithUrl()` which takes in a URL, no video or audio
 configs, and no DRM system. Allow the DRM system to be set on a running SbPlayer
 exactly once for SbPlayers created with a URL. Also, since URL players will not
-expose codec information, use a custom SbPlayerOutputModeSupportedWithUrl() to
+expose codec information, use a custom `SbPlayerOutputModeSupportedWithUrl()` to
 query player output mode support.
 
-### Add kSbEventTypeWindowSizeChanged
+### Add `kSbEventTypeWindowSizeChanged`
 
-An event indicating that an SbWindow's size has changed. The event data is
-SbEventWindowSizeChangedData, containing a SbWindow and SbWindowSize.
+An event indicating that an `SbWindow`'s size has changed. The event data is
+`SbEventWindowSizeChangedData`, containing a `SbWindow` and `SbWindowSize`.
+
+### Add `SbWindowShowOnScreenKeyboard()`, `SbWindowHideOnScreenKeyboard()`, `SbWindowIsOnScreenKeyboardShown()`
+
+These methods show and hide a native on screen keyboard and determine if the on
+screen keyboard is shown. The on screen keyboard also handles
+`kSbInputEventTypeInput`, which use a new field `input_text` of `SbInputData`.
 
 ## Version 7
 
diff --git a/src/starboard/__init__.py b/src/starboard/__init__.py
index e69de29..b02f7aa 100644
--- a/src/starboard/__init__.py
+++ b/src/starboard/__init__.py
@@ -0,0 +1,19 @@
+#!/usr/bin/python
+# Copyright 2014 Google Inc. All Rights Reserved.
+#
+# 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.
+"""Initialization for the starboard package."""
+
+# Provide a holder for the config package to insert an adapter for platforms
+# that refer to the deprecated config.starboard.PlatformConfigStarboard.
+PlatformConfigStarboard = None  # pylint: disable=invalid-name
diff --git a/src/starboard/configuration.h b/src/starboard/configuration.h
index df4949d..dcbb897 100644
--- a/src/starboard/configuration.h
+++ b/src/starboard/configuration.h
@@ -70,6 +70,7 @@
 
 #define SB_PLAYER_WITH_URL_API_VERSION SB_EXPERIMENTAL_API_VERSION
 #define SB_WINDOW_SIZE_CHANGED_API_VERSION SB_EXPERIMENTAL_API_VERSION
+#define SB_INPUT_ON_SCREEN_KEYBOARD_API_VERSION SB_EXPERIMENTAL_API_VERSION
 
 // --- Release Candidate Feature Defines -------------------------------------
 
@@ -555,6 +556,11 @@
 #endif  // !defined(SB_HAS_SPEECH_RECOGNIZER)
 #endif  // SB_API_VERSION >= 5
 
+#if SB_HAS(ON_SCREEN_KEYBOARD) && \
+    (SB_API_VERSION < SB_INPUT_ON_SCREEN_KEYBOARD_API_VERSION)
+#error "SB_HAS_ON_SCREEN_KEYBOARD not supported in this API version."
+#endif
+
 // --- Derived Configuration -------------------------------------------------
 
 // Whether the current platform is little endian.
diff --git a/src/starboard/event.h b/src/starboard/event.h
index 6ff7e17..189dcbe 100644
--- a/src/starboard/event.h
+++ b/src/starboard/event.h
@@ -219,6 +219,10 @@
   // SbEventWindowSizeChangedData.
   kSbEventTypeWindowSizeChanged,
 #endif  // SB_API_VERSION >= SB_WINDOW_SIZE_CHANGED_API_VERSION
+#if SB_HAS(ON_SCREEN_KEYBOARD)
+  kSbEventTypeOnScreenKeyboardShown,
+  kSbEventTypeOnScreenKeyboardHidden,
+#endif  // SB_HAS(ON_SCREEN_KEYBOARD)
 } SbEventType;
 
 // Structure representing a Starboard event and its data.
diff --git a/src/starboard/input.h b/src/starboard/input.h
index a32a05a..ebc108b 100644
--- a/src/starboard/input.h
+++ b/src/starboard/input.h
@@ -86,6 +86,13 @@
   //
   // Produces |Move|, |Press|, and |Unpress| events.
   kSbInputDeviceTypeTouchPad,
+
+#if SB_HAS(ON_SCREEN_KEYBOARD)
+  // Keyboard input from an on screen keyboard.
+  //
+  // Produces |Input| events.
+  kSbInputDeviceTypeOnScreenKeyboard,
+#endif  // SB_HAS(ON_SCREEN_KEYBOARD)
 } SbInputDeviceType;
 
 // The action that an input event represents.
@@ -125,6 +132,11 @@
   // Wheel movement. Provides relative movements of the |Mouse| wheel.
   kSbInputEventTypeWheel,
 #endif
+
+#if SB_HAS(ON_SCREEN_KEYBOARD)
+  // https://w3c.github.io/uievents/#event-type-input
+  kSbInputEventTypeInput,
+#endif  // SB_HAS(ON_SCREEN_KEYBOARD)
 } SbInputEventType;
 
 // A 2-dimensional vector used to represent points and motion vectors.
@@ -195,6 +207,10 @@
   // This value is used for input events with device type mouse or touch screen.
   SbInputVector tilt;
 #endif
+#if SB_HAS(ON_SCREEN_KEYBOARD)
+  // The text to input for events of type |Input|.
+  const char* input_text;
+#endif
 } SbInputData;
 
 #ifdef __cplusplus
diff --git a/src/starboard/linux/shared/configuration_public.h b/src/starboard/linux/shared/configuration_public.h
index 40fe9ab..573d4ca 100644
--- a/src/starboard/linux/shared/configuration_public.h
+++ b/src/starboard/linux/shared/configuration_public.h
@@ -259,14 +259,6 @@
 
 // --- Media Configuration ---------------------------------------------------
 
-// Specifies whether this platform has support for a possibly-decrypting
-// elementary stream player for at least H.264/AAC (and AES-128-CTR, if
-// decrypting). A player is responsible for ingesting an audio and video
-// elementary stream, optionally-encrypted, and ultimately producing
-// synchronized audio/video. If a player is defined, it must choose one of the
-// supported composition methods below.
-#define SB_HAS_PLAYER 1
-
 // The maximum audio bitrate the platform can decode.  The following value
 // equals to 5M bytes per seconds which is more than enough for compressed
 // audio.
diff --git a/src/starboard/linux/shared/gyp_configuration.py b/src/starboard/linux/shared/gyp_configuration.py
index 51662ad..a42bd6a 100644
--- a/src/starboard/linux/shared/gyp_configuration.py
+++ b/src/starboard/linux/shared/gyp_configuration.py
@@ -16,12 +16,12 @@
 import imp
 import os
 
-import config.starboard
+import config.base
 import gyp_utils
-import starboard.tools.testing.test_filter as test_filter
+from starboard.tools.testing import test_filter
 
 
-class PlatformConfig(config.starboard.PlatformConfigStarboard):
+class PlatformConfig(config.base.PlatformConfigBase):
   """Starboard Linux platform configuration."""
 
   def __init__(self,
@@ -81,7 +81,7 @@
         test_filter.TestFilter(
             'nplb_blitter_pixel_tests', test_filter.FILTER_ALL),
         test_filter.TestFilter(
-            'web_platform_tests', 'xhr/WebPlatformTest.Run/125', 'debug'),
+            'web_platform_tests', 'xhr/WebPlatformTest.Run/130', 'debug'),
         test_filter.TestFilter(
             'web_platform_tests', 'streams/WebPlatformTest.Run/11', 'debug'),
         test_filter.TestFilter(
diff --git a/src/starboard/linux/shared/launcher.py b/src/starboard/linux/shared/launcher.py
index 2a7808d..86a7ebd 100644
--- a/src/starboard/linux/shared/launcher.py
+++ b/src/starboard/linux/shared/launcher.py
@@ -42,22 +42,34 @@
     env.update(self.env_variables)
     self.full_env = env
 
+    self.proc = None
     self.pid = None
 
   def Run(self):
     """Runs launcher's executable."""
 
-    proc = subprocess.Popen([self.executable] + self.target_command_line_params,
-                            stdout=self.output_file, stderr=self.output_file,
-                            env=self.full_env)
-    self.pid = proc.pid
-    proc.wait()
-    return proc.returncode
+    self.proc = subprocess.Popen(
+        [self.executable] + self.target_command_line_params,
+        stdout=self.output_file,
+        stderr=self.output_file,
+        env=self.full_env)
+    self._CloseOutputFile()
+    self.pid = self.proc.pid
+    self.proc.wait()
+    return self.proc.returncode
 
   def Kill(self):
-    print "\n***Killing Launcher***\n"
+    sys.stderr.write("\n***Killing Launcher***\n")
     if self.pid:
       try:
         os.kill(self.pid, signal.SIGTERM)
       except OSError:
         sys.stderr.write("Cannot kill launcher.  Process already closed.\n")
+
+  def SendResume(self):
+    """Sends continue to the launcher's executable."""
+    sys.stderr.write("\n***Sending continue signal to executable***\n")
+    if self.proc:
+      self.proc.send_signal(signal.SIGCONT)
+    else:
+      sys.stderr.write("Cannot send continue to executable; it is closed.\n")
diff --git a/src/starboard/linux/shared/system_get_path.cc b/src/starboard/linux/shared/system_get_path.cc
index 315903be..223a204 100644
--- a/src/starboard/linux/shared/system_get_path.cc
+++ b/src/starboard/linux/shared/system_get_path.cc
@@ -181,8 +181,13 @@
     case kSbSystemPathExecutableFile:
       return GetExecutablePath(out_path, path_size);
 
+  case kSbSystemPathFontConfigurationDirectory:
+  case kSbSystemPathFontDirectory:
+      return false;
+
     default:
-      SB_NOTIMPLEMENTED();
+      SB_NOTIMPLEMENTED() << "SbSystemGetPath not implemented for "
+                          << path_id;
       return false;
   }
 
diff --git a/src/starboard/linux/x64directfb/gyp_configuration.py b/src/starboard/linux/x64directfb/gyp_configuration.py
index 4f6ddc5..cdb9088 100644
--- a/src/starboard/linux/x64directfb/gyp_configuration.py
+++ b/src/starboard/linux/x64directfb/gyp_configuration.py
@@ -16,8 +16,8 @@
 import logging
 
 # Import the shared Linux platform configuration.
-import starboard.linux.shared.gyp_configuration as gyp_configuration
-import starboard.tools.testing.test_filter as test_filter
+from starboard.linux.shared import gyp_configuration
+from starboard.tools.testing import test_filter
 
 
 def CreatePlatformConfig():
@@ -52,7 +52,7 @@
         test_filter.TestFilter(
             'net_unittests', 'HostResolverImplDnsTest.DnsTaskUnspec'),
         test_filter.TestFilter(
-            'web_platform_tests', 'xhr/WebPlatformTest.Run/125', 'debug'),
+            'web_platform_tests', 'xhr/WebPlatformTest.Run/130', 'debug'),
         test_filter.TestFilter(
             'web_platform_tests', 'streams/WebPlatformTest.Run/11', 'debug'),
         test_filter.TestFilter(
diff --git a/src/starboard/linux/x64x11/gyp_configuration.py b/src/starboard/linux/x64x11/gyp_configuration.py
index 9b4962f..55f6609 100644
--- a/src/starboard/linux/x64x11/gyp_configuration.py
+++ b/src/starboard/linux/x64x11/gyp_configuration.py
@@ -16,7 +16,7 @@
 import logging
 
 from starboard.linux.shared import gyp_configuration
-import starboard.tools.testing.test_filter as test_filter
+from starboard.tools.testing import test_filter
 from starboard.tools.toolchain import ar
 from starboard.tools.toolchain import bash
 from starboard.tools.toolchain import clang
@@ -65,7 +65,7 @@
         test_filter.TestFilter(
             'nplb_blitter_pixel_tests', test_filter.FILTER_ALL),
         test_filter.TestFilter(
-            'web_platform_tests', 'xhr/WebPlatformTest.Run/125', 'debug'),
+            'web_platform_tests', 'xhr/WebPlatformTest.Run/130', 'debug'),
         test_filter.TestFilter(
             'web_platform_tests', 'streams/WebPlatformTest.Run/11', 'debug'),
     ]
diff --git a/src/starboard/linux/x64x11/mock/configuration_public.h b/src/starboard/linux/x64x11/mock/configuration_public.h
index 8753319..c4a5f03 100644
--- a/src/starboard/linux/x64x11/mock/configuration_public.h
+++ b/src/starboard/linux/x64x11/mock/configuration_public.h
@@ -344,14 +344,6 @@
 
 // --- Media Configuration ---------------------------------------------------
 
-// Specifies whether this platform has support for a possibly-decrypting
-// elementary stream player for at least H.264/AAC (and AES-128-CTR, if
-// decrypting). A player is responsible for ingesting an audio and video
-// elementary stream, optionally-encrypted, and ultimately producing
-// synchronized audio/video. If a player is defined, it must choose one of the
-// supported composition methods below.
-#define SB_HAS_PLAYER 1
-
 // After a seek is triggerred, the default behavior is to append video frames
 // from the last key frame before the seek time and append audio frames from the
 // seek time because usually all audio frames are key frames.  On platforms that
diff --git a/src/starboard/linux/x64x11/mock/gyp_configuration.py b/src/starboard/linux/x64x11/mock/gyp_configuration.py
index fa14e09..f21f764 100644
--- a/src/starboard/linux/x64x11/mock/gyp_configuration.py
+++ b/src/starboard/linux/x64x11/mock/gyp_configuration.py
@@ -15,10 +15,11 @@
 
 import logging
 
-import config.starboard
+import config.base
 import gyp_utils
 import starboard.tools.testing.test_filter as test_filter
 
+
 def CreatePlatformConfig():
   try:
     return PlatformConfig('linux-x64x11-mock')
@@ -27,7 +28,7 @@
     return None
 
 
-class PlatformConfig(config.starboard.PlatformConfigStarboard):
+class PlatformConfig(config.base.PlatformConfigBase):
   """Starboard mock platform configuration."""
 
   def __init__(self, platform):
@@ -72,7 +73,7 @@
         test_filter.TestFilter(
             'nplb_blitter_pixel_tests', test_filter.FILTER_ALL),
         test_filter.TestFilter(
-            'web_platform_tests', 'xhr/WebPlatformTest.Run/125', 'debug'),
+            'web_platform_tests', 'xhr/WebPlatformTest.Run/130', 'debug'),
         test_filter.TestFilter(
             'web_platform_tests', 'streams/WebPlatformTest.Run/11', 'debug'),
         test_filter.TestFilter(
diff --git a/src/starboard/linux/x64x11/starboard_platform.gypi b/src/starboard/linux/x64x11/starboard_platform.gypi
index 6e54ebf..af94845 100644
--- a/src/starboard/linux/x64x11/starboard_platform.gypi
+++ b/src/starboard/linux/x64x11/starboard_platform.gypi
@@ -20,6 +20,9 @@
       '<(DEPTH)/starboard/linux/x64x11/sanitizer_options.cc',
       '<(DEPTH)/starboard/linux/x64x11/system_get_property.cc',
       '<(DEPTH)/starboard/shared/starboard/link_receiver.cc',
+      '<(DEPTH)/starboard/shared/stub/window_hide_on_screen_keyboard.cc',
+      '<(DEPTH)/starboard/shared/stub/window_is_on_screen_keyboard_shown.cc',
+      '<(DEPTH)/starboard/shared/stub/window_show_on_screen_keyboard.cc',
       '<(DEPTH)/starboard/shared/x11/application_x11.cc',
       '<(DEPTH)/starboard/shared/x11/window_create.cc',
       '<(DEPTH)/starboard/shared/x11/window_destroy.cc',
diff --git a/src/starboard/linux/x64x11/system_get_property.cc b/src/starboard/linux/x64x11/system_get_property.cc
index b72747d..4337e27 100644
--- a/src/starboard/linux/x64x11/system_get_property.cc
+++ b/src/starboard/linux/x64x11/system_get_property.cc
@@ -14,6 +14,11 @@
 
 #include "starboard/system.h"
 
+#include <netdb.h>
+#include <linux/if.h>  // NOLINT(build/include_alpha)
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+
 #include "starboard/log.h"
 #include "starboard/string.h"
 
@@ -31,6 +36,48 @@
   return true;
 }
 
+bool GetPlatformUuid(char* out_value, int value_length) {
+  struct ifreq interface;
+  struct ifconf config;
+  char buf[1024];
+
+  int fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);
+  if (fd == -1) {
+    return false;
+  }
+  config.ifc_len = sizeof(buf);
+  config.ifc_buf = buf;
+  int result = ioctl(fd, SIOCGIFCONF, &config);
+  if (result == -1) {
+    return false;
+  }
+
+  struct ifreq* cur_interface = config.ifc_req;
+  const struct ifreq* const end = cur_interface +
+      (config.ifc_len / sizeof(struct ifreq));
+
+  for (; cur_interface != end; ++cur_interface) {
+    SbStringCopy(interface.ifr_name,
+        cur_interface->ifr_name,
+        sizeof(cur_interface->ifr_name));
+    if (ioctl(fd, SIOCGIFFLAGS, &interface) == -1) {
+      continue;
+    }
+    if (interface.ifr_flags & IFF_LOOPBACK) {
+      continue;
+    }
+    if (ioctl(fd, SIOCGIFHWADDR, &interface) == -1) {
+      continue;
+    }
+    SbStringFormatF(out_value, value_length, "%x:%x:%x:%x:%x:%x",
+        interface.ifr_addr.sa_data[0], interface.ifr_addr.sa_data[1],
+        interface.ifr_addr.sa_data[2], interface.ifr_addr.sa_data[3],
+        interface.ifr_addr.sa_data[4], interface.ifr_addr.sa_data[5]);
+    return true;
+  }
+  return false;
+}
+
 }  // namespace
 
 bool SbSystemGetProperty(SbSystemPropertyId property_id,
@@ -57,8 +104,7 @@
       return CopyStringAndTestIfSuccess(out_value, value_length, kPlatformName);
 
     case kSbSystemPropertyPlatformUuid:
-      SB_NOTIMPLEMENTED();
-      return CopyStringAndTestIfSuccess(out_value, value_length, "N/A");
+      return GetPlatformUuid(out_value, value_length);
 
     default:
       SB_DLOG(WARNING) << __FUNCTION__
diff --git a/src/starboard/nplb/BUILD.gn b/src/starboard/nplb/BUILD.gn
index ad3a2bd..c6d2869 100644
--- a/src/starboard/nplb/BUILD.gn
+++ b/src/starboard/nplb/BUILD.gn
@@ -12,6 +12,8 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+# TODO: change to //starboard eventually.
+import("//cobalt/build/config/base.gni")
 import("//starboard/build/deploy.gni")
 
 group("all") {
@@ -151,7 +153,7 @@
     "mutex_destroy_test.cc",
     "once_test.cc",
     "optional_test.cc",
-    "player_create_test.cc",
+    "player_create_with_url_test.cc",
     "random_helpers.cc",
     "rwlock_test.cc",
     "semaphore_test.cc",
@@ -261,6 +263,15 @@
     "window_get_platform_handle_test.cc",
     "window_get_size_test.cc",
   ]
+
+  # TODO: find a way to remove this dependence on Cobalt.
+  if (sb_media_platform == "starboard") {
+    sources += [
+      "player_create_test.cc",
+      "player_output_mode_supported_test.cc",
+    ]
+  }
+
   # Include private C headers, if present.
   private_sources = exec_script("//starboard/tools/find_private_files.py",
                                 [
diff --git a/src/starboard/nplb/microphone_create_test.cc b/src/starboard/nplb/microphone_create_test.cc
index c11fd5f..2061684 100644
--- a/src/starboard/nplb/microphone_create_test.cc
+++ b/src/starboard/nplb/microphone_create_test.cc
@@ -14,6 +14,7 @@
 
 #include "starboard/microphone.h"
 #include "starboard/nplb/microphone_helpers.h"
+#include "starboard/types.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace starboard {
@@ -170,9 +171,13 @@
     ASSERT_TRUE(SbMicrophoneIsSampleRateSupported(
         info_array[0].id, info_array[0].max_sample_rate_hz));
     // Create a microphone with 2 gigabytes buffer size.
+    int64_t kBufferSize64 = 2 * 1024 * 1024 * 1024LL;
+    // This should wrap around to a negative value due to int
+    // narrowing.
+    int kBufferSize = static_cast<int>(kBufferSize64);
     SbMicrophone microphone =
         SbMicrophoneCreate(info_array[0].id, info_array[0].max_sample_rate_hz,
-                           2 * 1024 * 1024 * 1024LL);
+                           kBufferSize);
     EXPECT_FALSE(SbMicrophoneIsValid(microphone));
     SbMicrophoneDestroy(microphone);
   }
diff --git a/src/starboard/nplb/nplb.gyp b/src/starboard/nplb/nplb.gyp
index 297019f..e84264e 100644
--- a/src/starboard/nplb/nplb.gyp
+++ b/src/starboard/nplb/nplb.gyp
@@ -147,7 +147,6 @@
         'mutex_destroy_test.cc',
         'once_test.cc',
         'optional_test.cc',
-        'player_create_test.cc',
         'player_create_with_url_test.cc',
         'random_helpers.cc',
         'rwlock_test.cc',
@@ -270,6 +269,14 @@
         '<(DEPTH)/testing/gtest.gyp:gtest',
         '<(DEPTH)/starboard/starboard.gyp:starboard',
       ],
+      'conditions': [
+        ['sb_media_platform=="starboard"', {
+          'sources': [
+            'player_create_test.cc',
+            'player_output_mode_supported_test.cc',
+          ],
+        }],
+      ],
     },
     {
       'target_name': 'nplb_deploy',
diff --git a/src/starboard/nplb/player_create_test.cc b/src/starboard/nplb/player_create_test.cc
index 58e96ad..c5a5410 100644
--- a/src/starboard/nplb/player_create_test.cc
+++ b/src/starboard/nplb/player_create_test.cc
@@ -22,7 +22,6 @@
 namespace nplb {
 namespace {
 
-#if SB_HAS(PLAYER)
 #if SB_HAS(PLAYER_WITH_URL)
 // This test does not apply. See player_create_with_url_test.cc instead.
 #else
@@ -33,8 +32,10 @@
     SbDecodeTargetGlesContextRunnerTarget target_function,
     void* target_function_context) {
   SB_UNREFERENCED_PARAMETER(graphics_context_provider);
-  SB_UNREFERENCED_PARAMETER(target_function);
-  SB_UNREFERENCED_PARAMETER(target_function_context);
+
+  // Just call the function directly in case the player implementation relies
+  // on this function call being made.
+  (*target_function)(target_function_context);
 }
 #endif  // SB_HAS(GLES2)
 
@@ -101,7 +102,6 @@
 }
 
 #endif  // SB_HAS(PLAYER_WITH_URL)
-#endif  // SB_HAS(PLAYER)
 
 }  // namespace
 }  // namespace nplb
diff --git a/src/starboard/nplb/player_create_with_url_test.cc b/src/starboard/nplb/player_create_with_url_test.cc
index 2f82201..1fd48f5 100644
--- a/src/starboard/nplb/player_create_with_url_test.cc
+++ b/src/starboard/nplb/player_create_with_url_test.cc
@@ -22,7 +22,7 @@
 namespace nplb {
 namespace {
 
-#if SB_HAS(PLAYER) && SB_HAS(PLAYER_WITH_URL)
+#if SB_HAS(PLAYER_WITH_URL)
 TEST(SbPlayerUrlTest, SunnyDay) {
   SbWindowOptions window_options;
   SbWindowSetDefaultOptions(&window_options);
@@ -56,7 +56,7 @@
   SbWindowDestroy(window);
 }
 
-#endif  // SB_HAS(PLAYER) && SB_HAS(PLAYER_WITH_URL)
+#endif  // SB_HAS(PLAYER_WITH_URL)
 
 }  // namespace
 }  // namespace nplb
diff --git a/src/starboard/nplb/player_output_mode_supported_test.cc b/src/starboard/nplb/player_output_mode_supported_test.cc
index 29f3e5b..281a85b 100644
--- a/src/starboard/nplb/player_output_mode_supported_test.cc
+++ b/src/starboard/nplb/player_output_mode_supported_test.cc
@@ -21,9 +21,15 @@
 namespace nplb {
 namespace {
 
-#if SB_HAS(PLAYER)
+#if SB_HAS(PLAYER_WITH_URL)
+// This test does not apply. SbPlayerOutputModeWithUrl is defined instead of
+// SbPlayerOutputModeSupported.
+#else  // SB_HAS(PLAYER_WITH_URL)
 
 TEST(SbPlayerOutputModeSupportedTest, SunnyDay) {
+  SbMediaVideoCodec kVideoCodec = kSbMediaVideoCodecH264;
+  SbDrmSystem kDrmSystem = kSbDrmSystemInvalid;
+
   // We should support either decode-to-texture or punch-out mode.
   SbPlayerOutputMode output_mode = kSbPlayerOutputModeInvalid;
   if (SbPlayerOutputModeSupported(kSbPlayerOutputModeDecodeToTexture,
@@ -37,12 +43,15 @@
 }
 
 TEST(SbPlayerOutputModeSupportedTest, RainyDayInvalid) {
+  SbMediaVideoCodec kVideoCodec = kSbMediaVideoCodecH264;
+  SbDrmSystem kDrmSystem = kSbDrmSystemInvalid;
+
   bool result = SbPlayerOutputModeSupported(kSbPlayerOutputModeInvalid,
                                             kVideoCodec, kDrmSystem);
   EXPECT_FALSE(result);
 }
 
-#endif  // SB_HAS(PLAYER)
+#endif  // SB_HAS(PLAYER_WITH_URL)
 
 }  // namespace
 }  // namespace nplb
diff --git a/src/starboard/player.h b/src/starboard/player.h
index dc2b716..0d524ee 100644
--- a/src/starboard/player.h
+++ b/src/starboard/player.h
@@ -21,8 +21,6 @@
 
 #include "starboard/configuration.h"
 
-#if SB_HAS(PLAYER)
-
 #include "starboard/decode_target.h"
 #include "starboard/drm.h"
 #include "starboard/export.h"
@@ -520,6 +518,4 @@
 }  // extern "C"
 #endif
 
-#endif  // SB_HAS(PLAYER)
-
 #endif  // STARBOARD_PLAYER_H_
diff --git a/src/starboard/raspi/0/gyp_configuration.gypi b/src/starboard/raspi/0/gyp_configuration.gypi
index ff3100b..525eef0 100644
--- a/src/starboard/raspi/0/gyp_configuration.gypi
+++ b/src/starboard/raspi/0/gyp_configuration.gypi
@@ -14,8 +14,6 @@
 
 {
   'variables': {
-    'cobalt_minimum_frame_time_in_milliseconds': '33',
-
     # RasPi 1 is ARMv6
     'arm_version': 6,
     'armv7': 0,
diff --git a/src/starboard/raspi/shared/configuration_public.h b/src/starboard/raspi/shared/configuration_public.h
index 84be82d..ae146d4 100644
--- a/src/starboard/raspi/shared/configuration_public.h
+++ b/src/starboard/raspi/shared/configuration_public.h
@@ -255,14 +255,6 @@
 
 // --- Media Configuration ---------------------------------------------------
 
-// Specifies whether this platform has support for a possibly-decrypting
-// elementary stream player for at least H.264/AAC (and AES-128-CTR, if
-// decrypting). A player is responsible for ingesting an audio and video
-// elementary stream, optionally-encrypted, and ultimately producing
-// synchronized audio/video. If a player is defined, it must choose one of the
-// supported composition methods below.
-#define SB_HAS_PLAYER 1
-
 // The maximum audio bitrate the platform can decode.  The following value
 // equals to 5M bytes per seconds which is more than enough for compressed
 // audio.
diff --git a/src/starboard/raspi/shared/gyp_configuration.py b/src/starboard/raspi/shared/gyp_configuration.py
index 685fc8a..1b91e69 100644
--- a/src/starboard/raspi/shared/gyp_configuration.py
+++ b/src/starboard/raspi/shared/gyp_configuration.py
@@ -17,12 +17,12 @@
 import os
 import sys
 
-import config.starboard
+import config.base
 import gyp_utils
-import starboard.tools.testing.test_filter as test_filter
+from starboard.tools.testing import test_filter
 
 
-class RaspiPlatformConfig(config.starboard.PlatformConfigStarboard):
+class RaspiPlatformConfig(config.base.PlatformConfigBase):
   """Starboard Raspberry Pi platform configuration."""
 
   def __init__(self, platform):
diff --git a/src/starboard/shared/alsa/alsa_audio_sink_type.cc b/src/starboard/shared/alsa/alsa_audio_sink_type.cc
index def4105..b9a3548 100644
--- a/src/starboard/shared/alsa/alsa_audio_sink_type.cc
+++ b/src/starboard/shared/alsa/alsa_audio_sink_type.cc
@@ -223,7 +223,11 @@
   playback_handle_ = starboard::shared::alsa::AlsaOpenPlaybackDevice(
       channels_, sampling_frequency_hz_, kFramesPerRequest,
       kALSABufferSizeInFrames, alsa_sample_type);
-  creation_signal_.Signal();
+  {
+    ScopedLock lock(mutex_);
+    creation_signal_.Signal();
+  }
+
   if (!playback_handle_) {
     return;
   }
diff --git a/src/starboard/shared/ffmpeg/ffmpeg_audio_decoder.cc b/src/starboard/shared/ffmpeg/ffmpeg_audio_decoder.cc
index 8e28fd9..2d4b187 100644
--- a/src/starboard/shared/ffmpeg/ffmpeg_audio_decoder.cc
+++ b/src/starboard/shared/ffmpeg/ffmpeg_audio_decoder.cc
@@ -62,10 +62,12 @@
   TeardownCodec();
 }
 
-void AudioDecoder::Initialize(const Closure& output_cb) {
+void AudioDecoder::Initialize(const Closure& output_cb,
+                              const Closure& error_cb) {
   SB_DCHECK(BelongsToCurrentThread());
   SB_DCHECK(output_cb.is_valid());
   SB_DCHECK(!output_cb_.is_valid());
+  SB_UNREFERENCED_PARAMETER(error_cb);
 
   output_cb_ = output_cb;
 }
diff --git a/src/starboard/shared/ffmpeg/ffmpeg_audio_decoder.h b/src/starboard/shared/ffmpeg/ffmpeg_audio_decoder.h
index 7cc62fd..8be4e27 100644
--- a/src/starboard/shared/ffmpeg/ffmpeg_audio_decoder.h
+++ b/src/starboard/shared/ffmpeg/ffmpeg_audio_decoder.h
@@ -37,7 +37,8 @@
                const SbMediaAudioHeader& audio_header);
   ~AudioDecoder() SB_OVERRIDE;
 
-  void Initialize(const Closure& output_cb) SB_OVERRIDE;
+  void Initialize(const Closure& output_cb,
+                  const Closure& error_cb) SB_OVERRIDE;
   void Decode(const scoped_refptr<InputBuffer>& input_buffer,
               const Closure& consumed_cb) SB_OVERRIDE;
   void WriteEndOfStream() SB_OVERRIDE;
diff --git a/src/starboard/shared/libvpx/vpx_video_decoder.cc b/src/starboard/shared/libvpx/vpx_video_decoder.cc
index d6dbf97..bc4286e 100644
--- a/src/starboard/shared/libvpx/vpx_video_decoder.cc
+++ b/src/starboard/shared/libvpx/vpx_video_decoder.cc
@@ -164,12 +164,17 @@
   }
 
   if (output_mode_ == kSbPlayerOutputModeDecodeToTexture) {
-    ScopedLock lock(decode_target_mutex_);
-    if (SbDecodeTargetIsValid(decode_target_)) {
-      DecodeTargetRelease(decode_target_graphics_context_provider_,
-                          decode_target_);
+    SbDecodeTarget decode_target_to_release;
+    {
+      ScopedLock lock(decode_target_mutex_);
+      decode_target_to_release = decode_target_;
       decode_target_ = kSbDecodeTargetInvalid;
     }
+
+    if (SbDecodeTargetIsValid(decode_target_to_release)) {
+      DecodeTargetRelease(decode_target_graphics_context_provider_,
+                          decode_target_to_release);
+    }
   }
 }
 
diff --git a/src/starboard/shared/pthread/condition_variable_broadcast.cc b/src/starboard/shared/pthread/condition_variable_broadcast.cc
index b0faf1d..a478e2e 100644
--- a/src/starboard/shared/pthread/condition_variable_broadcast.cc
+++ b/src/starboard/shared/pthread/condition_variable_broadcast.cc
@@ -17,11 +17,20 @@
 #include <pthread.h>
 
 #include "starboard/shared/pthread/is_success.h"
+#include "starboard/shared/starboard/lazy_initialization_internal.h"
+
+using starboard::shared::starboard::IsInitialized;
 
 bool SbConditionVariableBroadcast(SbConditionVariable* condition) {
   if (!condition) {
     return false;
   }
 
-  return IsSuccess(pthread_cond_broadcast(condition));
+  if (!IsInitialized(&condition->initialized_state)) {
+    // If the condition variable is not initialized yet, then there is nothing
+    // to signal so vacuously return true.
+    return true;
+  }
+
+  return IsSuccess(pthread_cond_broadcast(&condition->condition));
 }
diff --git a/src/starboard/shared/pthread/condition_variable_create.cc b/src/starboard/shared/pthread/condition_variable_create.cc
index f5c75d7..dc9575e 100644
--- a/src/starboard/shared/pthread/condition_variable_create.cc
+++ b/src/starboard/shared/pthread/condition_variable_create.cc
@@ -17,6 +17,30 @@
 #include <pthread.h>
 
 #include "starboard/shared/pthread/is_success.h"
+#include "starboard/shared/starboard/lazy_initialization_internal.h"
+
+using starboard::shared::starboard::SetInitialized;
+
+namespace {
+struct ConditionVariableAttributes {
+ public:
+  ConditionVariableAttributes() {
+    valid_ = IsSuccess(pthread_condattr_init(&attributes_));
+  }
+  ~ConditionVariableAttributes() {
+    if (valid_) {
+      SB_CHECK(IsSuccess(pthread_condattr_destroy(&attributes_)));
+    }
+  }
+
+  bool valid() const { return valid_; }
+  pthread_condattr_t* attributes() { return &attributes_; }
+
+ private:
+  bool valid_;
+  pthread_condattr_t attributes_;
+};
+}  // namespace
 
 bool SbConditionVariableCreate(SbConditionVariable* out_condition,
                                SbMutex* /*opt_mutex*/) {
@@ -24,5 +48,33 @@
     return false;
   }
 
-  return IsSuccess(pthread_cond_init(out_condition, NULL));
+  ConditionVariableAttributes attributes;
+  if (!attributes.valid()) {
+    SB_DLOG(ERROR) << "Failed to call pthread_condattr_init().";
+    return false;
+  }
+
+#if !SB_HAS_QUIRK(NO_CONDATTR_SETCLOCK_SUPPORT)
+  // Always use CLOCK_MONOTONIC so that SbConditionVariableWaitTimed() will
+  // not be based off of the system clock (which can lead to erroneous
+  // behavior if the system clock is changed while a process is running).
+  if (!IsSuccess(pthread_condattr_setclock(
+           attributes.attributes(), CLOCK_MONOTONIC))) {
+    SB_DLOG(ERROR) << "Failed to call pthread_condattr_setclock().";
+    return false;
+  }
+#endif  // !SB_HAS_QUIRK(NO_CONDATTR_SETCLOCK_SUPPORT)
+
+  bool status = IsSuccess(pthread_cond_init(
+                    &out_condition->condition, attributes.attributes()));
+
+  // We mark that we are initialized regardless of whether initialization
+  // was successful or not.
+  SetInitialized(&out_condition->initialized_state);
+
+  if (!status) {
+    SB_DLOG(ERROR) << "Failed to call pthread_cond_init().";
+  }
+
+  return status;
 }
diff --git a/src/starboard/shared/pthread/condition_variable_destroy.cc b/src/starboard/shared/pthread/condition_variable_destroy.cc
index 7a4f974..81a26da 100644
--- a/src/starboard/shared/pthread/condition_variable_destroy.cc
+++ b/src/starboard/shared/pthread/condition_variable_destroy.cc
@@ -17,11 +17,20 @@
 #include <pthread.h>
 
 #include "starboard/shared/pthread/is_success.h"
+#include "starboard/shared/starboard/lazy_initialization_internal.h"
+
+using starboard::shared::starboard::IsInitialized;
 
 bool SbConditionVariableDestroy(SbConditionVariable* condition) {
   if (!condition) {
     return false;
   }
 
-  return IsSuccess(pthread_cond_destroy(condition));
+  if (!IsInitialized(&condition->initialized_state)) {
+    // If the condition variable is not initialized yet, then there is nothing
+    // to destroy so vacuously return true.
+    return true;
+  }
+
+  return IsSuccess(pthread_cond_destroy(&condition->condition));
 }
diff --git a/src/starboard/shared/pthread/condition_variable_signal.cc b/src/starboard/shared/pthread/condition_variable_signal.cc
index c1b8a58..5acc597 100644
--- a/src/starboard/shared/pthread/condition_variable_signal.cc
+++ b/src/starboard/shared/pthread/condition_variable_signal.cc
@@ -17,11 +17,20 @@
 #include <pthread.h>
 
 #include "starboard/shared/pthread/is_success.h"
+#include "starboard/shared/starboard/lazy_initialization_internal.h"
+
+using starboard::shared::starboard::IsInitialized;
 
 bool SbConditionVariableSignal(SbConditionVariable* condition) {
   if (!condition) {
     return false;
   }
 
-  return IsSuccess(pthread_cond_signal(condition));
+  if (!IsInitialized(&condition->initialized_state)) {
+    // If the condition variable is not initialized yet, then there is nothing
+    // to signal so vacuously return true.
+    return true;
+  }
+
+  return IsSuccess(pthread_cond_signal(&condition->condition));
 }
diff --git a/src/starboard/shared/pthread/condition_variable_wait.cc b/src/starboard/shared/pthread/condition_variable_wait.cc
index ccdf677..41ca6bb 100644
--- a/src/starboard/shared/pthread/condition_variable_wait.cc
+++ b/src/starboard/shared/pthread/condition_variable_wait.cc
@@ -17,6 +17,9 @@
 #include <pthread.h>
 
 #include "starboard/shared/pthread/is_success.h"
+#include "starboard/shared/starboard/lazy_initialization_internal.h"
+
+using starboard::shared::starboard::EnsureInitialized;
 
 SbConditionVariableResult SbConditionVariableWait(
     SbConditionVariable* condition,
@@ -25,7 +28,15 @@
     return kSbConditionVariableFailed;
   }
 
-  if (IsSuccess(pthread_cond_wait(condition, mutex))) {
+  if (!EnsureInitialized(&condition->initialized_state)) {
+    // The condition variable is set to SB_CONDITION_VARIABLE_INITIALIZER and
+    // is uninitialized, so call SbConditionVariableCreate() to initialize the
+    // condition variable. SbConditionVariableCreate() is responsible for
+    // marking the variable as initialized.
+    SbConditionVariableCreate(condition, mutex);
+  }
+
+  if (IsSuccess(pthread_cond_wait(&condition->condition, mutex))) {
     return kSbConditionVariableSignaled;
   }
 
diff --git a/src/starboard/shared/pthread/condition_variable_wait_timed.cc b/src/starboard/shared/pthread/condition_variable_wait_timed.cc
index fd63f63..dcabd46 100644
--- a/src/starboard/shared/pthread/condition_variable_wait_timed.cc
+++ b/src/starboard/shared/pthread/condition_variable_wait_timed.cc
@@ -20,8 +20,11 @@
 
 #include "starboard/shared/posix/time_internal.h"
 #include "starboard/shared/pthread/is_success.h"
+#include "starboard/shared/starboard/lazy_initialization_internal.h"
 #include "starboard/time.h"
 
+using starboard::shared::starboard::EnsureInitialized;
+
 SbConditionVariableResult SbConditionVariableWaitTimed(
     SbConditionVariable* condition,
     SbMutex* mutex,
@@ -34,19 +37,33 @@
     timeout = 0;
   }
 
+#if !SB_HAS_QUIRK(NO_CONDATTR_SETCLOCK_SUPPORT)
+  SbTime timeout_time = SbTimeGetMonotonicNow() + timeout;
+#else  // !SB_HAS_QUIRK(NO_CONDATTR_SETCLOCK_SUPPORT)
+  int64_t timeout_time = SbTimeToPosix(SbTimeGetNow()) + timeout;
+#endif  // !SB_HAS_QUIRK(NO_CONDATTR_SETCLOCK_SUPPORT)
+
   // Detect overflow if timeout is near kSbTimeMax. Since timeout can't be
   // negative at this point, if it goes negative after adding now, we know we've
   // gone over. Especially posix now, which has a 400 year advantage over
   // Chromium (Windows) now.
-  int64_t posix_time = SbTimeToPosix(SbTimeGetNow()) + timeout;
-  if (posix_time < 0) {
-    posix_time = kSbInt64Max;
+  if (timeout_time < 0) {
+    timeout_time = kSbInt64Max;
   }
 
   struct timespec timeout_ts;
-  ToTimespec(&timeout_ts, posix_time);
+  ToTimespec(&timeout_ts, timeout_time);
 
-  int result = pthread_cond_timedwait(condition, mutex, &timeout_ts);
+  if (!EnsureInitialized(&condition->initialized_state)) {
+    // The condition variable is set to SB_CONDITION_VARIABLE_INITIALIZER and
+    // is uninitialized, so call SbConditionVariableCreate() to initialize the
+    // condition variable. SbConditionVariableCreate() is responsible for
+    // marking the variable as initialized.
+    SbConditionVariableCreate(condition, mutex);
+  }
+
+  int result =
+      pthread_cond_timedwait(&condition->condition, mutex, &timeout_ts);
   if (IsSuccess(result)) {
     return kSbConditionVariableSignaled;
   }
diff --git a/src/starboard/shared/pthread/types_public.h b/src/starboard/shared/pthread/types_public.h
index 59ee65e..4e19c63 100644
--- a/src/starboard/shared/pthread/types_public.h
+++ b/src/starboard/shared/pthread/types_public.h
@@ -22,13 +22,23 @@
 
 #include <pthread.h>
 
+#include "starboard/shared/starboard/lazy_initialization_public.h"
+
 // --- SbConditionVariable ---
 
 // Transparent Condition Variable handle.
-typedef pthread_cond_t SbConditionVariable;
+// It is customized from the plain pthread_cont_t object because we
+// need to ensure that each condition variable is initialized to use
+// CLOCK_MONOTONIC, which is not the default (and the default is used
+// when PTHREAD_COND_INITIALIZER is set).
+typedef struct SbConditionVariable {
+  InitializedState initialized_state;
+  pthread_cond_t condition;
+} SbConditionVariable;
 
 // Condition Variable static initializer.
-#define SB_CONDITION_VARIABLE_INITIALIZER PTHREAD_COND_INITIALIZER
+#define SB_CONDITION_VARIABLE_INITIALIZER \
+  { INITIALIZED_STATE_UNINITIALIZED, 0 }
 
 // --- SbMutex ---
 
diff --git a/src/starboard/shared/starboard/application.cc b/src/starboard/shared/starboard/application.cc
index 1ee5a85..6a688f4 100644
--- a/src/starboard/shared/starboard/application.cc
+++ b/src/starboard/shared/starboard/application.cc
@@ -160,7 +160,6 @@
   CancelTimedEvent(id);
 }
 
-#if SB_HAS(PLAYER)
 void Application::HandleFrame(SbPlayer player,
                               const scoped_refptr<VideoFrame>& frame,
                               int z_index,
@@ -170,7 +169,6 @@
                               int height) {
   AcceptFrame(player, frame, z_index, x, y, width, height);
 }
-#endif  // SB_HAS(PLAYER)
 
 void Application::SetStartLink(const char* start_link) {
   SB_DCHECK(IsCurrentThread());
diff --git a/src/starboard/shared/starboard/application.h b/src/starboard/shared/starboard/application.h
index 915f15a..3ef9ede 100644
--- a/src/starboard/shared/starboard/application.h
+++ b/src/starboard/shared/starboard/application.h
@@ -231,7 +231,6 @@
   // external thread.
   void Cancel(SbEventId id);
 
-#if SB_HAS(PLAYER)
   // Handles receiving a new video frame of |player| from the media system. Only
   // used when the application needs to composite video frames with punch-out
   // video manually (should be rare). Will be called from an external thread.
@@ -242,7 +241,6 @@
                    int y,
                    int width,
                    int height);
-#endif  // SB_HAS(PLAYER)
 
   // Registers a |callback| function that will be called when |Teardown| is
   // called.
@@ -270,7 +268,6 @@
   // processed the Resume event.
   virtual void OnResume() {}
 
-#if SB_HAS(PLAYER)
   // Subclasses may override this method to accept video frames from the media
   // system. Will be called from an external thread.
   virtual void AcceptFrame(SbPlayer /* player */,
@@ -280,7 +277,6 @@
                            int /* y */,
                            int /* width */,
                            int /* height */) {}
-#endif  // SB_HAS(PLAYER)
 
   // Blocks until the next event is available. Subclasses must implement this
   // method to provide events for the platform. Gives ownership to the caller.
diff --git a/src/starboard/shared/starboard/lazy_initialization_internal.cc b/src/starboard/shared/starboard/lazy_initialization_internal.cc
deleted file mode 100644
index f108899..0000000
--- a/src/starboard/shared/starboard/lazy_initialization_internal.cc
+++ /dev/null
@@ -1,61 +0,0 @@
-// Copyright 2015 Google Inc. All Rights Reserved.
-//
-// 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.
-
-#include "starboard/shared/starboard/lazy_initialization_internal.h"
-
-#include "starboard/log.h"
-#include "starboard/thread.h"
-
-// INITIALIZED_STATE_UNINITIALIZED is defined in the header.
-#define INITIALIZED_STATE_INITIALIZING 2
-#define INITIALIZED_STATE_INITIALIZED 3
-
-namespace starboard {
-namespace shared {
-namespace starboard {
-
-bool EnsureInitialized(InitializedState* state) {
-  // Check what state we're in, and if we find that we are uninitialized,
-  // simultaneously mark us as initializing and return to the caller.
-  InitializedState original = SbAtomicNoBarrier_CompareAndSwap(
-      state, INITIALIZED_STATE_UNINITIALIZED, INITIALIZED_STATE_INITIALIZING);
-  if (original == INITIALIZED_STATE_UNINITIALIZED) {
-    // If we were uninitialized, we are now marked as initializing and so
-    // we relay this information to the caller, so that they may initialize.
-    return false;
-  } else if (original == INITIALIZED_STATE_INITIALIZING) {
-    // If the current state is that we are being initialized, spin until
-    // initialization is complete, then return.
-    do {
-      SbThreadYield();
-    } while (SbAtomicAcquire_Load(state) != INITIALIZED_STATE_INITIALIZED);
-  } else {
-    SB_DCHECK(original == INITIALIZED_STATE_INITIALIZED);
-  }
-
-  return true;
-}
-
-bool IsInitialized(InitializedState* state) {
-  return SbAtomicNoBarrier_Load(state) == INITIALIZED_STATE_INITIALIZED;
-}
-
-void SetInitialized(InitializedState* state) {
-  // Mark that we are initialized now.
-  SbAtomicRelease_Store(state, INITIALIZED_STATE_INITIALIZED);
-}
-
-}  // namespace starboard
-}  // namespace shared
-}  // namespace starboard
diff --git a/src/starboard/shared/starboard/lazy_initialization_internal.h b/src/starboard/shared/starboard/lazy_initialization_internal.h
index f1cd603..f3d8f49 100644
--- a/src/starboard/shared/starboard/lazy_initialization_internal.h
+++ b/src/starboard/shared/starboard/lazy_initialization_internal.h
@@ -16,8 +16,14 @@
 #define STARBOARD_SHARED_STARBOARD_LAZY_INITIALIZATION_INTERNAL_H_
 
 #include "starboard/atomic.h"
+#include "starboard/log.h"
 #include "starboard/shared/internal_only.h"
 #include "starboard/shared/starboard/lazy_initialization_public.h"
+#include "starboard/thread.h"
+
+// INITIALIZED_STATE_UNINITIALIZED is defined in the header.
+#define INITIALIZED_STATE_INITIALIZING 2
+#define INITIALIZED_STATE_INITIALIZED 3
 
 namespace starboard {
 namespace shared {
@@ -30,15 +36,40 @@
 // If false is returned, you must initialize the state (e.g. by eventually
 // calling SetInitialized() or else other threads waiting for initialization
 // to complete will wait forever.)
-bool EnsureInitialized(InitializedState* state);
+static SB_C_INLINE bool EnsureInitialized(InitializedState* state) {
+  // Check what state we're in, and if we find that we are uninitialized,
+  // simultaneously mark us as initializing and return to the caller.
+  InitializedState original = SbAtomicNoBarrier_CompareAndSwap(
+      state, INITIALIZED_STATE_UNINITIALIZED, INITIALIZED_STATE_INITIALIZING);
+  if (original == INITIALIZED_STATE_UNINITIALIZED) {
+    // If we were uninitialized, we are now marked as initializing and so
+    // we relay this information to the caller, so that they may initialize.
+    return false;
+  } else if (original == INITIALIZED_STATE_INITIALIZING) {
+    // If the current state is that we are being initialized, spin until
+    // initialization is complete, then return.
+    do {
+      SbThreadYield();
+    } while (SbAtomicAcquire_Load(state) != INITIALIZED_STATE_INITIALIZED);
+  } else {
+    SB_DCHECK(original == INITIALIZED_STATE_INITIALIZED);
+  }
+
+  return true;
+}
 
 // Returns true if the state is initialized, false otherwise.  Do not
 // use the outcome of this function to make a decision on whether to initialize
 // or not, use EnsureInitialized() for that.
-bool IsInitialized(InitializedState* state);
+static SB_C_INLINE bool IsInitialized(InitializedState* state) {
+  return SbAtomicNoBarrier_Load(state) == INITIALIZED_STATE_INITIALIZED;
+}
 
 // Sets the state as being initialized.
-void SetInitialized(InitializedState* state);
+static SB_C_INLINE void SetInitialized(InitializedState* state) {
+  // Mark that we are initialized now.
+  SbAtomicRelease_Store(state, INITIALIZED_STATE_INITIALIZED);
+}
 
 }  // namespace starboard
 }  // namespace shared
diff --git a/src/starboard/shared/starboard/lazy_initialization_public.h b/src/starboard/shared/starboard/lazy_initialization_public.h
index c4d7f8f..06d11e0 100644
--- a/src/starboard/shared/starboard/lazy_initialization_public.h
+++ b/src/starboard/shared/starboard/lazy_initialization_public.h
@@ -15,7 +15,7 @@
 #ifndef STARBOARD_SHARED_STARBOARD_LAZY_INITIALIZATION_PUBLIC_H_
 #define STARBOARD_SHARED_STARBOARD_LAZY_INITIALIZATION_PUBLIC_H_
 
-#include "starboard/atomic.h"
+#include "starboard/types.h"
 
 // The utility functions defined here use atomics and spin-locks to allow for
 // easy lazy initialization in a thread-safe way.
@@ -23,8 +23,10 @@
 // An InitializedState should be treated as an opaque type that can be
 // initialized to kInitializedStateUninitialized and then passed into the
 // functions in this file to transition it first to a "initializing" state and
-// then an "initialized" state.
-typedef SbAtomic32 InitializedState;
+// then an "initialized" state.  Note that this is intended to be used as a
+// SbAtomic32, however due to technical reasons we can't include
+// "starboard/atomic.h".
+typedef int32_t InitializedState;
 #define INITIALIZED_STATE_UNINITIALIZED 1
 
 #endif  // STARBOARD_SHARED_STARBOARD_LAZY_INITIALIZATION_PUBLIC_H_
diff --git a/src/starboard/shared/starboard/player/filter/audio_decoder_internal.h b/src/starboard/shared/starboard/player/filter/audio_decoder_internal.h
index 81384c7..f4feacd 100644
--- a/src/starboard/shared/starboard/player/filter/audio_decoder_internal.h
+++ b/src/starboard/shared/starboard/player/filter/audio_decoder_internal.h
@@ -44,7 +44,8 @@
   // that a further call of Read() returns valid output until Reset() is called.
   // Note that |output_cb| is always called asynchronously on the calling job
   // queue.
-  virtual void Initialize(const Closure& output_cb) = 0;
+  virtual void Initialize(const Closure& output_cb,
+                          const Closure& error_cb) = 0;
 
   // Decode the encoded audio data stored in |input_buffer|.  Whenever the input
   // is consumed and the decoder is ready to accept a new input, it calls
diff --git a/src/starboard/shared/starboard/player/filter/audio_renderer_impl_internal.cc b/src/starboard/shared/starboard/player/filter/audio_renderer_impl_internal.cc
index 5048b82..1ffc09c 100644
--- a/src/starboard/shared/starboard/player/filter/audio_renderer_impl_internal.cc
+++ b/src/starboard/shared/starboard/player/filter/audio_renderer_impl_internal.cc
@@ -105,8 +105,6 @@
     Schedule(log_frames_consumed_closure_, kSbTimeSecond);
   }
 
-  decoder_->Initialize(Bind(&AudioRendererImpl::OnDecoderOutput, this));
-
   // TODO: Initialize |time_stretcher_| after the first decoded audio output to
   // ensure that implicit HEAAC is properly handled.
   int source_sample_rate = decoder_->GetSamplesPerSecond();
@@ -120,6 +118,11 @@
   SB_DCHECK(BelongsToCurrentThread());
 }
 
+void AudioRendererImpl::Initialize(const Closure& error_cb) {
+  decoder_->Initialize(Bind(&AudioRendererImpl::OnDecoderOutput, this),
+                       error_cb);
+}
+
 void AudioRendererImpl::WriteSample(
     const scoped_refptr<InputBuffer>& input_buffer) {
   SB_DCHECK(BelongsToCurrentThread());
@@ -280,10 +283,10 @@
          frames_played * kSbMediaTimeSecond / samples_per_second;
 }
 
-void AudioRendererImpl::OnUpdateSourceStatus(int* frames_in_buffer,
-                                             int* offset_in_frames,
-                                             bool* is_playing,
-                                             bool* is_eos_reached) {
+void AudioRendererImpl::GetSourceStatus(int* frames_in_buffer,
+                                        int* offset_in_frames,
+                                        bool* is_playing,
+                                        bool* is_eos_reached) {
   *is_eos_reached = eos_state_.load() >= kEOSSentToSink;
 
   *is_playing = !paused_.load() && !seeking_.load();
@@ -297,7 +300,7 @@
   }
 }
 
-void AudioRendererImpl::OnConsumeFrames(int frames_consumed) {
+void AudioRendererImpl::ConsumeFrames(int frames_consumed) {
   frames_consumed_by_sink_.fetch_add(frames_consumed);
   SB_DCHECK(frames_consumed_by_sink_.load() <= frames_sent_to_sink_.load());
   frames_consumed_by_sink_since_last_get_current_time_.fetch_add(
diff --git a/src/starboard/shared/starboard/player/filter/audio_renderer_impl_internal.h b/src/starboard/shared/starboard/player/filter/audio_renderer_impl_internal.h
index 221cb12..aea88f9 100644
--- a/src/starboard/shared/starboard/player/filter/audio_renderer_impl_internal.h
+++ b/src/starboard/shared/starboard/player/filter/audio_renderer_impl_internal.h
@@ -51,6 +51,7 @@
                     const SbMediaAudioHeader& audio_header);
   ~AudioRendererImpl() SB_OVERRIDE;
 
+  void Initialize(const Closure& error_cb) SB_OVERRIDE;
   void WriteSample(const scoped_refptr<InputBuffer>& input_buffer) SB_OVERRIDE;
   void WriteEndOfStream() SB_OVERRIDE;
 
@@ -104,11 +105,11 @@
   static const size_t kFrameAppendUnit = 16384;
 
   // AudioRendererSink methods
-  void OnUpdateSourceStatus(int* frames_in_buffer,
-                            int* offset_in_frames,
-                            bool* is_playing,
-                            bool* is_eos_reached) SB_OVERRIDE;
-  void OnConsumeFrames(int frames_consumed) SB_OVERRIDE;
+  void GetSourceStatus(int* frames_in_buffer,
+                       int* offset_in_frames,
+                       bool* is_playing,
+                       bool* is_eos_reached) SB_OVERRIDE;
+  void ConsumeFrames(int frames_consumed) SB_OVERRIDE;
 
   void CreateAudioSinkAndResampler();
   void LogFramesConsumed();
diff --git a/src/starboard/shared/starboard/player/filter/audio_renderer_impl_internal_test.cc b/src/starboard/shared/starboard/player/filter/audio_renderer_impl_internal_test.cc
index 85c8515..c7bd032 100644
--- a/src/starboard/shared/starboard/player/filter/audio_renderer_impl_internal_test.cc
+++ b/src/starboard/shared/starboard/player/filter/audio_renderer_impl_internal_test.cc
@@ -99,13 +99,14 @@
     EXPECT_CALL(*audio_renderer_sink_, GetNearestSupportedSampleFrequency(_))
         .Times(AnyNumber());
 
-    EXPECT_CALL(*audio_decoder_, Initialize(_))
+    EXPECT_CALL(*audio_decoder_, Initialize(_, _))
         .WillOnce(SaveArg<0>(&output_cb_));
 
     audio_renderer_.reset(new AudioRendererImpl(
         make_scoped_ptr<AudioDecoder>(audio_decoder_),
         make_scoped_ptr<AudioRendererSink>(audio_renderer_sink_),
         GetDefaultAudioHeader()));
+    audio_renderer_->Initialize(Bind(&AudioRendererImplTest::OnError, this));
   }
 
   // Creates audio buffers, decodes them, and passes them onto the renderer,
@@ -190,6 +191,8 @@
     return decoded_audio;
   }
 
+  void OnError() {}
+
   SbMediaAudioSampleType sample_type_;
   SbMediaAudioFrameStorageType storage_type_;
 
@@ -270,8 +273,8 @@
   int offset_in_frames;
   bool is_playing;
   bool is_eos_reached;
-  renderer_callback_->OnUpdateSourceStatus(&frames_in_buffer, &offset_in_frames,
-                                           &is_playing, &is_eos_reached);
+  renderer_callback_->GetSourceStatus(&frames_in_buffer, &offset_in_frames,
+                                      &is_playing, &is_eos_reached);
   EXPECT_GT(frames_in_buffer, 0);
   EXPECT_GE(offset_in_frames, 0);
   EXPECT_TRUE(is_playing);
@@ -284,13 +287,13 @@
 
   EXPECT_FALSE(audio_renderer_->IsEndOfStreamPlayed());
 
-  renderer_callback_->OnConsumeFrames(frames_to_consume);
+  renderer_callback_->ConsumeFrames(frames_to_consume);
   new_media_time = audio_renderer_->GetCurrentTime();
   EXPECT_GT(new_media_time, media_time);
   media_time = new_media_time;
 
   const int remaining_frames = frames_in_buffer - frames_to_consume;
-  renderer_callback_->OnConsumeFrames(remaining_frames);
+  renderer_callback_->ConsumeFrames(remaining_frames);
   new_media_time = audio_renderer_->GetCurrentTime();
   EXPECT_GT(new_media_time, media_time);
 
@@ -335,8 +338,8 @@
   int offset_in_frames;
   bool is_playing;
   bool is_eos_reached;
-  renderer_callback_->OnUpdateSourceStatus(&frames_in_buffer, &offset_in_frames,
-                                           &is_playing, &is_eos_reached);
+  renderer_callback_->GetSourceStatus(&frames_in_buffer, &offset_in_frames,
+                                      &is_playing, &is_eos_reached);
 
   EXPECT_GT(frames_in_buffer, 0);
   EXPECT_GE(offset_in_frames, 0);
@@ -350,13 +353,13 @@
 
   EXPECT_FALSE(audio_renderer_->IsEndOfStreamPlayed());
 
-  renderer_callback_->OnConsumeFrames(frames_to_consume);
+  renderer_callback_->ConsumeFrames(frames_to_consume);
   new_media_time = audio_renderer_->GetCurrentTime();
   EXPECT_GT(new_media_time, media_time);
   media_time = new_media_time;
 
   const int remaining_frames = frames_in_buffer - frames_to_consume;
-  renderer_callback_->OnConsumeFrames(remaining_frames);
+  renderer_callback_->ConsumeFrames(remaining_frames);
   new_media_time = audio_renderer_->GetCurrentTime();
   EXPECT_GT(new_media_time, media_time);
 
@@ -387,8 +390,8 @@
   int offset_in_frames;
   bool is_playing;
   bool is_eos_reached;
-  renderer_callback_->OnUpdateSourceStatus(&frames_in_buffer, &offset_in_frames,
-                                           &is_playing, &is_eos_reached);
+  renderer_callback_->GetSourceStatus(&frames_in_buffer, &offset_in_frames,
+                                      &is_playing, &is_eos_reached);
   EXPECT_GT(frames_in_buffer, 0);
   EXPECT_GE(offset_in_frames, 0);
   EXPECT_TRUE(is_playing);
@@ -401,13 +404,13 @@
 
   EXPECT_FALSE(audio_renderer_->IsEndOfStreamPlayed());
 
-  renderer_callback_->OnConsumeFrames(frames_to_consume);
+  renderer_callback_->ConsumeFrames(frames_to_consume);
   new_media_time = audio_renderer_->GetCurrentTime();
   EXPECT_GE(new_media_time, media_time);
   media_time = new_media_time;
 
   const int remaining_frames = frames_in_buffer - frames_to_consume;
-  renderer_callback_->OnConsumeFrames(remaining_frames);
+  renderer_callback_->ConsumeFrames(remaining_frames);
   new_media_time = audio_renderer_->GetCurrentTime();
   EXPECT_GE(new_media_time, media_time);
 
@@ -523,8 +526,8 @@
   int offset_in_frames;
   bool is_playing;
   bool is_eos_reached;
-  renderer_callback_->OnUpdateSourceStatus(&frames_in_buffer, &offset_in_frames,
-                                           &is_playing, &is_eos_reached);
+  renderer_callback_->GetSourceStatus(&frames_in_buffer, &offset_in_frames,
+                                      &is_playing, &is_eos_reached);
   EXPECT_GT(frames_in_buffer, 0);
   EXPECT_GE(offset_in_frames, 0);
   EXPECT_TRUE(is_playing);
@@ -537,13 +540,13 @@
 
   EXPECT_FALSE(audio_renderer_->IsEndOfStreamPlayed());
 
-  renderer_callback_->OnConsumeFrames(frames_to_consume);
+  renderer_callback_->ConsumeFrames(frames_to_consume);
   new_media_time = audio_renderer_->GetCurrentTime();
   EXPECT_GE(new_media_time, media_time);
   media_time = new_media_time;
 
   const int remaining_frames = frames_in_buffer - frames_to_consume;
-  renderer_callback_->OnConsumeFrames(remaining_frames);
+  renderer_callback_->ConsumeFrames(remaining_frames);
   new_media_time = audio_renderer_->GetCurrentTime();
   EXPECT_GE(new_media_time, media_time);
 
@@ -600,8 +603,8 @@
   int offset_in_frames;
   bool is_playing;
   bool is_eos_reached;
-  renderer_callback_->OnUpdateSourceStatus(&frames_in_buffer, &offset_in_frames,
-                                           &is_playing, &is_eos_reached);
+  renderer_callback_->GetSourceStatus(&frames_in_buffer, &offset_in_frames,
+                                      &is_playing, &is_eos_reached);
   EXPECT_GT(frames_in_buffer, 0);
   EXPECT_GE(offset_in_frames, 0);
   EXPECT_TRUE(is_playing);
@@ -614,13 +617,13 @@
 
   EXPECT_FALSE(audio_renderer_->IsEndOfStreamPlayed());
 
-  renderer_callback_->OnConsumeFrames(frames_to_consume);
+  renderer_callback_->ConsumeFrames(frames_to_consume);
   new_media_time = audio_renderer_->GetCurrentTime();
   EXPECT_GE(new_media_time, media_time);
   media_time = new_media_time;
 
   const int remaining_frames = frames_in_buffer - frames_to_consume;
-  renderer_callback_->OnConsumeFrames(remaining_frames);
+  renderer_callback_->ConsumeFrames(remaining_frames);
   new_media_time = audio_renderer_->GetCurrentTime();
   EXPECT_GE(new_media_time, media_time);
 
@@ -660,8 +663,8 @@
   int offset_in_frames;
   bool is_playing;
   bool is_eos_reached;
-  renderer_callback_->OnUpdateSourceStatus(&frames_in_buffer, &offset_in_frames,
-                                           &is_playing, &is_eos_reached);
+  renderer_callback_->GetSourceStatus(&frames_in_buffer, &offset_in_frames,
+                                      &is_playing, &is_eos_reached);
   EXPECT_GT(frames_in_buffer, 0);
   EXPECT_GE(offset_in_frames, 0);
   EXPECT_TRUE(is_playing);
@@ -675,7 +678,7 @@
 
   EXPECT_FALSE(audio_renderer_->IsEndOfStreamPlayed());
 
-  renderer_callback_->OnConsumeFrames(frames_to_consume);
+  renderer_callback_->ConsumeFrames(frames_to_consume);
   new_media_time = audio_renderer_->GetCurrentTime();
   EXPECT_GE(new_media_time, media_time);
   Seek(seek_time);
@@ -688,14 +691,14 @@
   audio_renderer_->Play();
   SendDecoderOutput(new DecodedAudio);
 
-  renderer_callback_->OnUpdateSourceStatus(&frames_in_buffer, &offset_in_frames,
-                                           &is_playing, &is_eos_reached);
+  renderer_callback_->GetSourceStatus(&frames_in_buffer, &offset_in_frames,
+                                      &is_playing, &is_eos_reached);
   EXPECT_GT(frames_in_buffer, 0);
   EXPECT_GE(offset_in_frames, 0);
   EXPECT_TRUE(is_playing);
   EXPECT_TRUE(is_eos_reached);
   const int remaining_frames = frames_in_buffer - offset_in_frames;
-  renderer_callback_->OnConsumeFrames(remaining_frames);
+  renderer_callback_->ConsumeFrames(remaining_frames);
   new_media_time = audio_renderer_->GetCurrentTime();
   EXPECT_GE(new_media_time, seek_time);
 
diff --git a/src/starboard/shared/starboard/player/filter/audio_renderer_internal.h b/src/starboard/shared/starboard/player/filter/audio_renderer_internal.h
index 7f0ae7f..d362ad5 100644
--- a/src/starboard/shared/starboard/player/filter/audio_renderer_internal.h
+++ b/src/starboard/shared/starboard/player/filter/audio_renderer_internal.h
@@ -16,6 +16,7 @@
 #define STARBOARD_SHARED_STARBOARD_PLAYER_FILTER_AUDIO_RENDERER_INTERNAL_H_
 
 #include "starboard/common/ref_counted.h"
+#include "starboard/configuration.h"
 #include "starboard/media.h"
 #include "starboard/shared/internal_only.h"
 #include "starboard/shared/starboard/player/filter/audio_decoder_internal.h"
@@ -31,6 +32,9 @@
  public:
   virtual ~AudioRenderer() {}
 
+  virtual void Initialize(const Closure& error_cb) {
+    SB_UNREFERENCED_PARAMETER(error_cb);
+  }
   virtual void WriteSample(const scoped_refptr<InputBuffer>& input_buffer) = 0;
   virtual void WriteEndOfStream() = 0;
   virtual void Play() = 0;
diff --git a/src/starboard/shared/starboard/player/filter/audio_renderer_sink.h b/src/starboard/shared/starboard/player/filter/audio_renderer_sink.h
index 31b517f..5f53e28 100644
--- a/src/starboard/shared/starboard/player/filter/audio_renderer_sink.h
+++ b/src/starboard/shared/starboard/player/filter/audio_renderer_sink.h
@@ -28,11 +28,11 @@
  public:
   class RenderCallback {
    public:
-    virtual void OnUpdateSourceStatus(int* frames_in_buffer,
-                                      int* offset_in_frames,
-                                      bool* is_playing,
-                                      bool* is_eos_reached) = 0;
-    virtual void OnConsumeFrames(int frames_consumed) = 0;
+    virtual void GetSourceStatus(int* frames_in_buffer,
+                                 int* offset_in_frames,
+                                 bool* is_playing,
+                                 bool* is_eos_reached) = 0;
+    virtual void ConsumeFrames(int frames_consumed) = 0;
 
    protected:
     ~RenderCallback() {}
diff --git a/src/starboard/shared/starboard/player/filter/audio_renderer_sink_impl.cc b/src/starboard/shared/starboard/player/filter/audio_renderer_sink_impl.cc
index cd4eb6f..accfb4f 100644
--- a/src/starboard/shared/starboard/player/filter/audio_renderer_sink_impl.cc
+++ b/src/starboard/shared/starboard/player/filter/audio_renderer_sink_impl.cc
@@ -127,7 +127,7 @@
   SB_DCHECK(is_playing);
   SB_DCHECK(is_eos_reached);
 
-  audio_renderer_sink->render_callback_->OnUpdateSourceStatus(
+  audio_renderer_sink->render_callback_->GetSourceStatus(
       frames_in_buffer, offset_in_frames, is_playing, is_eos_reached);
 }
 
@@ -139,7 +139,7 @@
   SB_DCHECK(audio_renderer_sink);
   SB_DCHECK(audio_renderer_sink->render_callback_);
 
-  audio_renderer_sink->render_callback_->OnConsumeFrames(frames_consumed);
+  audio_renderer_sink->render_callback_->ConsumeFrames(frames_consumed);
 }
 
 }  // namespace filter
diff --git a/src/starboard/shared/starboard/player/filter/filter_based_player_worker_handler.cc b/src/starboard/shared/starboard/player/filter/filter_based_player_worker_handler.cc
index a04991b..8f89b33 100644
--- a/src/starboard/shared/starboard/player/filter/filter_based_player_worker_handler.cc
+++ b/src/starboard/shared/starboard/player/filter/filter_based_player_worker_handler.cc
@@ -123,6 +123,10 @@
 
   audio_renderer_->SetPlaybackRate(playback_rate_);
   audio_renderer_->SetVolume(volume_);
+  audio_renderer_->Initialize(
+      Bind(&FilterBasedPlayerWorkerHandler::OnError, this));
+  video_renderer_->Initialize(
+      Bind(&FilterBasedPlayerWorkerHandler::OnError, this));
 
   job_queue_->Schedule(update_closure_, kUpdateInterval);
 
@@ -143,8 +147,8 @@
   }
 
   audio_renderer_->Pause();
-  audio_renderer_->Seek(seek_to_pts);
   video_renderer_->Seek(seek_to_pts);
+  audio_renderer_->Seek(seek_to_pts);
   return true;
 }
 
@@ -300,6 +304,15 @@
   return true;
 }
 
+void FilterBasedPlayerWorkerHandler::OnError() {
+  if (!job_queue_->BelongsToCurrentThread()) {
+    job_queue_->Schedule(Bind(&FilterBasedPlayerWorkerHandler::OnError, this));
+    return;
+  }
+
+  (*player_worker_.*update_player_state_cb_)(kSbPlayerStateError);
+}
+
 // TODO: This should be driven by callbacks instead polling.
 void FilterBasedPlayerWorkerHandler::Update() {
   SB_DCHECK(job_queue_->BelongsToCurrentThread());
diff --git a/src/starboard/shared/starboard/player/filter/filter_based_player_worker_handler.h b/src/starboard/shared/starboard/player/filter/filter_based_player_worker_handler.h
index 3e441fa..3480675 100644
--- a/src/starboard/shared/starboard/player/filter/filter_based_player_worker_handler.h
+++ b/src/starboard/shared/starboard/player/filter/filter_based_player_worker_handler.h
@@ -63,6 +63,7 @@
   void Stop() SB_OVERRIDE;
 
   void Update();
+  void OnError();
 
   SbDecodeTarget GetCurrentDecodeTarget() SB_OVERRIDE;
 
diff --git a/src/starboard/shared/starboard/player/filter/mock_audio_decoder.h b/src/starboard/shared/starboard/player/filter/mock_audio_decoder.h
index 4558d8e..23e6cbb 100644
--- a/src/starboard/shared/starboard/player/filter/mock_audio_decoder.h
+++ b/src/starboard/shared/starboard/player/filter/mock_audio_decoder.h
@@ -43,7 +43,7 @@
         storage_type_(storage_type),
         samples_per_second_(sample_per_second) {}
 
-  MOCK_METHOD1(Initialize, void(const Closure&));
+  MOCK_METHOD2(Initialize, void(const Closure&, const Closure&));
   MOCK_METHOD2(Decode, void(const scoped_refptr<InputBuffer>&, const Closure&));
   MOCK_METHOD0(WriteEndOfStream, void());
   MOCK_METHOD0(Read, scoped_refptr<DecodedAudio>());
diff --git a/src/starboard/shared/starboard/player/filter/stub_player_components_impl.cc b/src/starboard/shared/starboard/player/filter/stub_player_components_impl.cc
index 487c1d7..f65ad14 100644
--- a/src/starboard/shared/starboard/player/filter/stub_player_components_impl.cc
+++ b/src/starboard/shared/starboard/player/filter/stub_player_components_impl.cc
@@ -49,7 +49,9 @@
         audio_header_(audio_header),
         stream_ended_(false) {}
 
-  void Initialize(const Closure& output_cb) SB_OVERRIDE {
+  void Initialize(const Closure& output_cb,
+                  const Closure& error_cb) SB_OVERRIDE {
+    SB_UNREFERENCED_PARAMETER(error_cb);
     output_cb_ = output_cb;
   }
 
diff --git a/src/starboard/shared/starboard/player/filter/video_decoder_internal.h b/src/starboard/shared/starboard/player/filter/video_decoder_internal.h
index 215a50f..0377a61 100644
--- a/src/starboard/shared/starboard/player/filter/video_decoder_internal.h
+++ b/src/starboard/shared/starboard/player/filter/video_decoder_internal.h
@@ -16,8 +16,10 @@
 #define STARBOARD_SHARED_STARBOARD_PLAYER_FILTER_VIDEO_DECODER_INTERNAL_H_
 
 #include "starboard/common/ref_counted.h"
+#include "starboard/configuration.h"
 #include "starboard/player.h"
 #include "starboard/shared/internal_only.h"
+#include "starboard/shared/starboard/player/closure.h"
 #include "starboard/shared/starboard/player/input_buffer_internal.h"
 #include "starboard/shared/starboard/player/job_queue.h"
 #include "starboard/shared/starboard/player/video_frame_internal.h"
@@ -31,10 +33,16 @@
 // This class decodes encoded video stream into video frames.
 class VideoDecoder {
  public:
+  typedef ::starboard::shared::starboard::player::Closure Closure;
+
   enum Status { kNeedMoreInput, kBufferFull, kFatalError };
 
   virtual ~VideoDecoder() {}
 
+  virtual void Initialize(const Closure& error_cb) {
+    SB_UNREFERENCED_PARAMETER(error_cb);
+  }
+
   // Send encoded video frame stored in |input_buffer| to decode.
   virtual void WriteInputBuffer(
       const scoped_refptr<InputBuffer>& input_buffer) = 0;
diff --git a/src/starboard/shared/starboard/player/filter/video_renderer_impl_internal.cc b/src/starboard/shared/starboard/player/filter/video_renderer_impl_internal.cc
index 6fd98c6..6fc8d19 100644
--- a/src/starboard/shared/starboard/player/filter/video_renderer_impl_internal.cc
+++ b/src/starboard/shared/starboard/player/filter/video_renderer_impl_internal.cc
@@ -34,6 +34,17 @@
   decoder_->SetHost(this);
 }
 
+VideoRendererImpl::~VideoRendererImpl() {
+  // Be sure to release anything created by the decoder_ before releasing the
+  // decoder_ itself.
+  if (decoder_needs_full_reset_) {
+    decoder_->Reset();
+  }
+  frames_.clear();
+  current_frame_ = nullptr;
+  decoder_.reset();
+}
+
 void VideoRendererImpl::WriteSample(
     const scoped_refptr<InputBuffer>& input_buffer) {
   SB_DCHECK(thread_checker_.CalledOnValidThread());
@@ -90,15 +101,8 @@
     SbMediaTime media_time,
     bool audio_eos_reached) {
   ScopedLock lock(mutex_);
-
-  if (frames_.empty()) {
-    return last_displayed_frame_;
-  }
-
-  AdvanceTime(media_time, audio_eos_reached);
-
-  last_displayed_frame_ = frames_.front();
-  return last_displayed_frame_;
+  AdvanceCurrentFrame(media_time, audio_eos_reached);
+  return current_frame_;
 }
 
 bool VideoRendererImpl::IsEndOfStreamPlayed() const {
@@ -145,10 +149,14 @@
   need_more_input_ = (status == VideoDecoder::kNeedMoreInput);
 }
 
-void VideoRendererImpl::AdvanceTime(
+void VideoRendererImpl::AdvanceCurrentFrame(
     SbMediaTime media_time, bool audio_eos_reached) {
+  if (frames_.empty()) {
+    return;
+  }
+
   while (frames_.size() > 1 && frames_.front()->pts() < media_time) {
-    if (frames_.front() != last_displayed_frame_) {
+    if (frames_.front() != current_frame_) {
       ++dropped_frames_;
     }
     frames_.pop_front();
@@ -159,6 +167,8 @@
       frames_.pop_back();
     }
   }
+
+  current_frame_ = frames_.front();
 }
 
 SbDecodeTarget VideoRendererImpl::GetCurrentDecodeTarget(
@@ -166,7 +176,7 @@
     bool audio_eos_reached) {
   {
     ScopedLock lock(mutex_);
-    AdvanceTime(media_time, audio_eos_reached);
+    AdvanceCurrentFrame(media_time, audio_eos_reached);
   }
 
   if (decoder_) {
diff --git a/src/starboard/shared/starboard/player/filter/video_renderer_impl_internal.h b/src/starboard/shared/starboard/player/filter/video_renderer_impl_internal.h
index 675dea8..e26c156 100644
--- a/src/starboard/shared/starboard/player/filter/video_renderer_impl_internal.h
+++ b/src/starboard/shared/starboard/player/filter/video_renderer_impl_internal.h
@@ -41,6 +41,7 @@
                           private HostedVideoDecoder::Host {
  public:
   explicit VideoRendererImpl(scoped_ptr<HostedVideoDecoder> decoder);
+  ~VideoRendererImpl() SB_OVERRIDE;
 
   int GetDroppedFrames() const SB_OVERRIDE { return dropped_frames_; }
 
@@ -75,7 +76,7 @@
   static const size_t kMaxCachedFrames = 12;
 
   // Advances the clock, potentially dropping any expired frames.
-  void AdvanceTime(SbMediaTime media_time, bool audio_eos_reached);
+  void AdvanceCurrentFrame(SbMediaTime media_time, bool audio_eos_reached);
 
   // VideoDecoder::Host method.
   void OnDecoderStatusUpdate(VideoDecoder::Status status,
@@ -90,9 +91,9 @@
 
   // During seeking, all frames inside |frames_| will be cleared but the app
   // should still display the last frame it is rendering.  This frame will be
-  // kept inside |last_displayed_frame_|.  It is an empty/black frame before the
+  // kept inside |current_frame_|.  It is an empty/black frame before the
   // video is started.
-  scoped_refptr<VideoFrame> last_displayed_frame_;
+  scoped_refptr<VideoFrame> current_frame_;
 
   SbMediaTime seeking_to_pts_;
   bool end_of_stream_written_;
diff --git a/src/starboard/shared/starboard/player/filter/video_renderer_internal.h b/src/starboard/shared/starboard/player/filter/video_renderer_internal.h
index 96b4482..7307c07 100644
--- a/src/starboard/shared/starboard/player/filter/video_renderer_internal.h
+++ b/src/starboard/shared/starboard/player/filter/video_renderer_internal.h
@@ -16,10 +16,12 @@
 #define STARBOARD_SHARED_STARBOARD_PLAYER_FILTER_VIDEO_RENDERER_INTERNAL_H_
 
 #include "starboard/common/ref_counted.h"
+#include "starboard/configuration.h"
 #include "starboard/log.h"
 #include "starboard/media.h"
 #include "starboard/mutex.h"
 #include "starboard/shared/internal_only.h"
+#include "starboard/shared/starboard/player/closure.h"
 #include "starboard/shared/starboard/player/filter/video_decoder_internal.h"
 #include "starboard/shared/starboard/player/input_buffer_internal.h"
 #include "starboard/shared/starboard/player/video_frame_internal.h"
@@ -33,8 +35,15 @@
 
 class VideoRenderer {
  public:
+  typedef ::starboard::shared::starboard::player::Closure Closure;
+
   virtual ~VideoRenderer() {}
 
+  // TODO: Refactor video pipeline error handling once VideoRenderers are
+  // unified.
+  virtual void Initialize(const Closure& error_cb) {
+    SB_UNREFERENCED_PARAMETER(error_cb);
+  }
   virtual int GetDroppedFrames() const = 0;
   virtual void WriteSample(const scoped_refptr<InputBuffer>& input_buffer) = 0;
   virtual void WriteEndOfStream() = 0;
diff --git a/src/starboard/shared/stub/player_create.cc b/src/starboard/shared/stub/player_create.cc
index 35b05fd..aa2b775 100644
--- a/src/starboard/shared/stub/player_create.cc
+++ b/src/starboard/shared/stub/player_create.cc
@@ -14,10 +14,6 @@
 
 #include "starboard/player.h"
 
-#if !SB_HAS(PLAYER)
-#error "SbPlayerCreate requires SB_HAS(PLAYER)."
-#endif
-
 SbPlayer SbPlayerCreate(SbWindow /*window*/,
                         SbMediaVideoCodec /*video_codec*/,
                         SbMediaAudioCodec /*audio_codec*/,
diff --git a/src/starboard/shared/stub/player_create_with_url.cc b/src/starboard/shared/stub/player_create_with_url.cc
index cbad413..ffb34c5 100644
--- a/src/starboard/shared/stub/player_create_with_url.cc
+++ b/src/starboard/shared/stub/player_create_with_url.cc
@@ -14,10 +14,6 @@
 
 #include "starboard/player.h"
 
-#if !SB_HAS(PLAYER)
-#error "SbPlayerCreateWithUrl requires SB_HAS(PLAYER)."
-#endif
-
 #if SB_HAS(PLAYER_WITH_URL)
 
 SbPlayer SbPlayerCreateWithUrl(
diff --git a/src/starboard/shared/stub/player_get_current_frame.cc b/src/starboard/shared/stub/player_get_current_frame.cc
index 8f94d1e..7f68af5 100644
--- a/src/starboard/shared/stub/player_get_current_frame.cc
+++ b/src/starboard/shared/stub/player_get_current_frame.cc
@@ -14,10 +14,6 @@
 
 #include "starboard/player.h"
 
-#if !SB_HAS(PLAYER)
-#error "This file requires SB_HAS(PLAYER)."
-#endif
-
 SbDecodeTarget SbPlayerGetCurrentFrame(SbPlayer /*player*/) {
   return kSbDecodeTargetInvalid;
 }
diff --git a/src/starboard/shared/stub/player_output_mode_supported.cc b/src/starboard/shared/stub/player_output_mode_supported.cc
index f81a7bc..72fa1ac 100644
--- a/src/starboard/shared/stub/player_output_mode_supported.cc
+++ b/src/starboard/shared/stub/player_output_mode_supported.cc
@@ -14,10 +14,6 @@
 
 #include "starboard/player.h"
 
-#if !SB_HAS(PLAYER)
-#error "This file requires SB_HAS(PLAYER)."
-#endif
-
 bool SbPlayerOutputModeSupported(SbPlayerOutputMode /*output_mode*/,
                                  SbMediaVideoCodec /*codec*/,
                                  SbDrmSystem /*drm_system*/) {
diff --git a/src/starboard/shared/stub/player_set_bounds.cc b/src/starboard/shared/stub/player_set_bounds.cc
index 5008bd8..ea9d42d 100644
--- a/src/starboard/shared/stub/player_set_bounds.cc
+++ b/src/starboard/shared/stub/player_set_bounds.cc
@@ -14,10 +14,6 @@
 
 #include "starboard/player.h"
 
-#if !SB_HAS(PLAYER)
-#error "This file requires SB_HAS(PLAYER)."
-#endif
-
 void SbPlayerSetBounds(SbPlayer /*player*/,
                        int /*z_index*/,
                        int /*x*/,
diff --git a/src/starboard/shared/stub/player_set_playback_rate.cc b/src/starboard/shared/stub/player_set_playback_rate.cc
index 6937cb6..1a97b8c 100644
--- a/src/starboard/shared/stub/player_set_playback_rate.cc
+++ b/src/starboard/shared/stub/player_set_playback_rate.cc
@@ -14,10 +14,6 @@
 
 #include "starboard/player.h"
 
-#if !SB_HAS(PLAYER)
-#error "This file requires SB_HAS(PLAYER)."
-#endif
-
 bool SbPlayerSetPlaybackRate(SbPlayer /*player*/, double /*playback_rate*/) {
   return false;
 }
diff --git a/src/starboard/shared/stub/player_write_sample.cc b/src/starboard/shared/stub/player_write_sample.cc
index b5a02eb..d1fecd8 100644
--- a/src/starboard/shared/stub/player_write_sample.cc
+++ b/src/starboard/shared/stub/player_write_sample.cc
@@ -14,10 +14,6 @@
 
 #include "starboard/player.h"
 
-#if !SB_HAS(PLAYER)
-#error "This file requires SB_HAS(PLAYER)."
-#endif
-
 void SbPlayerWriteSample(SbPlayer /*player*/,
                          SbMediaType /*sample_type*/,
 #if SB_API_VERSION >= 6
diff --git a/src/starboard/shared/stub/window_hide_on_screen_keyboard.cc b/src/starboard/shared/stub/window_hide_on_screen_keyboard.cc
new file mode 100644
index 0000000..dd12eb6
--- /dev/null
+++ b/src/starboard/shared/stub/window_hide_on_screen_keyboard.cc
@@ -0,0 +1,22 @@
+// Copyright 2017 Google Inc. All Rights Reserved.
+//
+// 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.
+
+#include "starboard/window.h"
+
+#if SB_HAS(ON_SCREEN_KEYBOARD)
+void SbWindowHideOnScreenKeyboard(SbWindow window) {
+  // Stub.
+  return;
+}
+#endif  // SB_HAS(ON_SCREEN_KEYBOARD)
diff --git a/src/starboard/shared/stub/window_is_on_screen_keyboard_shown.cc b/src/starboard/shared/stub/window_is_on_screen_keyboard_shown.cc
new file mode 100644
index 0000000..4cd091f
--- /dev/null
+++ b/src/starboard/shared/stub/window_is_on_screen_keyboard_shown.cc
@@ -0,0 +1,22 @@
+// Copyright 2017 Google Inc. All Rights Reserved.
+//
+// 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.
+
+#include "starboard/window.h"
+
+#if SB_HAS(ON_SCREEN_KEYBOARD)
+bool SbWindowIsOnScreenKeyboardShown(SbWindow window) {
+  // Stub.
+  return false;
+}
+#endif  // SB_HAS(ON_SCREEN_KEYBOARD)
diff --git a/src/starboard/shared/stub/window_show_on_screen_keyboard.cc b/src/starboard/shared/stub/window_show_on_screen_keyboard.cc
new file mode 100644
index 0000000..8c940cf
--- /dev/null
+++ b/src/starboard/shared/stub/window_show_on_screen_keyboard.cc
@@ -0,0 +1,22 @@
+// Copyright 2017 Google Inc. All Rights Reserved.
+//
+// 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.
+
+#include "starboard/window.h"
+
+#if SB_HAS(ON_SCREEN_KEYBOARD)
+void SbWindowShowOnScreenKeyboard(SbWindow window, const char* input_text) {
+  // Stub.
+  return;
+}
+#endif  // SB_HAS(ON_SCREEN_KEYBOARD)
diff --git a/src/starboard/shared/uwp/media_is_video_supported.cc b/src/starboard/shared/uwp/media_is_video_supported.cc
deleted file mode 100644
index b46802b..0000000
--- a/src/starboard/shared/uwp/media_is_video_supported.cc
+++ /dev/null
@@ -1,163 +0,0 @@
-// Copyright 2017 Google Inc. All Rights Reserved.
-//
-// 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.
-
-#include "starboard/shared/starboard/media/media_support_internal.h"
-
-#include <sstream>
-
-#include "starboard/common/scoped_ptr.h"
-#include "starboard/configuration.h"
-#include "starboard/media.h"
-#include "starboard/once.h"
-#include "starboard/shared/win32/error_utils.h"
-#include "starboard/shared/win32/media_common.h"
-#include "starboard/shared/win32/media_foundation_utils.h"
-#include "starboard/shared/win32/media_transform.h"
-#include "starboard/shared/win32/video_transform.h"
-#include "starboard/shared/win32/wchar_utils.h"
-#include "starboard/system.h"
-#include "starboard/window.h"
-
-// #define ENABLE_VP9_DECODER
-
-using Microsoft::WRL::ComPtr;
-using starboard::scoped_ptr;
-using starboard::ScopedLock;
-using starboard::shared::win32::CheckResult;
-using starboard::shared::win32::kVideoFormat_YV12;
-using starboard::shared::win32::MediaTransform;
-using starboard::shared::win32::TryCreateVP9Transform;
-
-namespace {
-
-class VideoSupported {
- public:
-  static VideoSupported* GetSingleton();
-  bool IsVideoSupported(SbMediaVideoCodec video_codec,
-                        int frame_width,
-                        int frame_height,
-                        int64_t bitrate,
-                        int fps) {
-    // Is resolution out of range?
-    if (frame_width > max_width_ || frame_height > max_height_) {
-      return false;
-    }
-    // Is bitrate in range?
-    if (bitrate > SB_MEDIA_MAX_VIDEO_BITRATE_IN_BITS_PER_SECOND) {
-      return false;
-    }
-    if (fps > 60) {
-      return false;
-    }
-    if (video_codec == kSbMediaVideoCodecH264) {
-      return true;
-    }
-    if (video_codec == kSbMediaVideoCodecVp9) {
-      return IsVp9Supported(frame_width, frame_height);
-    }
-    return false;
-  }
-
- private:
-  bool AllowVp9Decoder() {
-#ifdef ENABLE_VP9_DECODER
-    return platform_supports_vp9_;
-#else
-    return false;
-#endif
-  }
-
-  static bool DetectVp9Supported(int width, int height) {
-    scoped_ptr<MediaTransform> vp9_decoder =
-        TryCreateVP9Transform(kVideoFormat_YV12, width, height);
-    return !!vp9_decoder.get();
-  }
-
-  static bool DetectPlatformIsXbox() {
-    using starboard::shared::win32::platformStringToString;
-    using Windows::Security::ExchangeActiveSyncProvisioning::
-        EasClientDeviceInformation;
-
-    EasClientDeviceInformation^ device_info =
-          ref new EasClientDeviceInformation();
-
-    const std::string product_name =
-        platformStringToString(device_info->SystemProductName);
-
-    return product_name.find("Xbox One") != std::string::npos;
-  }
-
-  bool IsVp9Supported(int width, int height) {
-    if (!AllowVp9Decoder()) {
-      return false;
-    }
-    // When width/height is zero then this is a special value to mean
-    // IsVP9 available at all? Therefore detect the general case by
-    // testing the specific case of 1024 x 768.
-    if ((width == 0) && (height == 0)) {
-      return DetectVp9Supported(1024, 768);
-    }
-
-    Key key = {width, height};
-    ScopedLock lock(mutex_);
-    auto it = vpn_size_cache_.find(key);
-    if (it != vpn_size_cache_.end()) {
-      return it->second;
-    } else {
-      const bool vp9_valid = DetectVp9Supported(width, height);
-      vpn_size_cache_[key] = vp9_valid;
-      return vp9_valid;
-    }
-  }
-
-  VideoSupported() {
-    platform_supports_vp9_ = DetectPlatformIsXbox();
-    SbWindowOptions sb_window_options;
-    SbWindowSetDefaultOptions(&sb_window_options);
-    max_width_ = sb_window_options.size.width;
-    max_height_ = sb_window_options.size.height;
-  }
-
-  struct Key {
-    int width = 0;
-    int height = 0;
-    bool operator<(const Key& other) const {
-      if (width != other.width) {
-        return width < other.width;
-      }
-      return height < other.height;
-    }
-  };
-
-  starboard::Mutex mutex_;
-  using Vp9SizeCache = std::map<Key, bool>;
-  Vp9SizeCache vpn_size_cache_;
-  bool platform_supports_vp9_ = false;
-  int max_width_ = 0;
-  int max_height_ = 0;
-};
-
-SB_ONCE_INITIALIZE_FUNCTION(VideoSupported, VideoSupported::GetSingleton);
-
-}  // namespace.
-
-SB_EXPORT bool SbMediaIsVideoSupported(SbMediaVideoCodec video_codec,
-                                       int frame_width,
-                                       int frame_height,
-                                       int64_t bitrate,
-                                       int fps) {
-  bool supported = VideoSupported::GetSingleton()->IsVideoSupported(
-      video_codec, frame_width, frame_height, bitrate, fps);
-  return supported;
-}
diff --git a/src/starboard/shared/uwp/microphone_impl.cc b/src/starboard/shared/uwp/microphone_impl.cc
new file mode 100644
index 0000000..51206e0
--- /dev/null
+++ b/src/starboard/shared/uwp/microphone_impl.cc
@@ -0,0 +1,528 @@
+// Copyright 2017 Google Inc. All Rights Reserved.
+//
+// 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.
+
+#include "starboard/shared/starboard/microphone/microphone_internal.h"
+
+// Windows headers.
+#include <collection.h>
+#include <MemoryBuffer.h>
+#include <ppltasks.h>
+
+// C++ headers.
+#include <algorithm>
+#include <deque>
+#include <memory>
+#include <sstream>
+#include <vector>
+
+#include "starboard/atomic.h"
+#include "starboard/common/semaphore.h"
+#include "starboard/log.h"
+#include "starboard/mutex.h"
+#include "starboard/shared/uwp/app_accessors.h"
+#include "starboard/shared/uwp/application_uwp.h"
+#include "starboard/shared/uwp/async_utils.h"
+#include "starboard/shared/win32/error_utils.h"
+#include "starboard/shared/win32/simple_thread.h"
+#include "starboard/shared/win32/wchar_utils.h"
+#include "starboard/string.h"
+#include "starboard/time.h"
+#include "starboard/user.h"
+
+#if !SB_HAS(MICROPHONE)
+#error Microphone expected to be enabled when compiling a microphone impl.
+#endif
+
+using concurrency::task_continuation_context;
+using Microsoft::WRL::ComPtr;
+using starboard::Mutex;
+using starboard::scoped_ptr;
+using starboard::ScopedLock;
+using starboard::Semaphore;
+using starboard::shared::uwp::ApplicationUwp;
+using starboard::shared::win32::CheckResult;
+using starboard::shared::win32::platformStringToString;
+using Windows::Devices::Enumeration::DeviceInformation;
+using Windows::Devices::Enumeration::DeviceInformationCollection;
+using Windows::Foundation::EventRegistrationToken;
+using Windows::Foundation::IMemoryBufferByteAccess;
+using Windows::Foundation::IMemoryBufferReference;
+using Windows::Foundation::TypedEventHandler;
+using Windows::Media::Audio::AudioDeviceInputNode;
+using Windows::Media::Audio::AudioDeviceNodeCreationStatus;
+using Windows::Media::Audio::AudioFrameOutputNode;
+using Windows::Media::Audio::AudioGraph;
+using Windows::Media::Audio::AudioGraphCreationStatus;
+using Windows::Media::Audio::AudioGraphSettings;
+using Windows::Media::Audio::CreateAudioDeviceInputNodeResult;
+using Windows::Media::Audio::CreateAudioGraphResult;
+using Windows::Media::Audio::QuantumSizeSelectionMode;
+using Windows::Media::AudioBuffer;
+using Windows::Media::AudioBufferAccessMode;
+using Windows::Media::AudioFrame;
+using Windows::Media::Capture::MediaCategory;
+using Windows::Media::Devices::MediaDevice;
+using Windows::Media::MediaProperties::AudioEncodingProperties;
+using Windows::Media::Render::AudioRenderCategory;
+
+namespace {
+
+// It appears that cobalt will only request 16khz.
+const int kMinSampleRate = 16000;
+const int kMaxSampleRate = 44100;
+const int kNumChannels = 1;
+const int kOutputBytesPerSample = sizeof(int16_t);
+const int kMinReadSizeBytes = 4096;
+const int kMicGain = 1;
+
+// Controls the amount of time that a microphone will record muted audio
+// before it signals a read error. Without this trigger, the app
+// will continuously wait for audio data. This happens with the Kinect
+// device, which when disconnected will still record 0-value samples.
+const SbTime kTimeMutedThreshold = 3 * kSbTimeSecond;
+
+// Maps [-1.0f, 1.0f] -> [-32768, 32767]
+// Values outside of [-1.0f, 1.0] are clamped.
+int16_t To16BitPcm(float val) {
+  static const float kMaxFloatValue = std::numeric_limits<int16_t>::max();
+  static const float kLowFloatValue = std::numeric_limits<int16_t>::lowest();
+  if (val == 0.0f) {
+    return 0;
+  } else if (val > 0.0f) {
+    if (val > 1.0f) {
+      val = 1.0;
+    }
+    return static_cast<int16_t>(val * kMaxFloatValue);
+  } else {
+    if (val < -1.0f) {
+      val = -1.0;
+    }
+    return static_cast<int16_t>(-1.0f * val * kLowFloatValue);
+  }
+}
+
+const char* ToString(AudioDeviceNodeCreationStatus status) {
+  switch (status) {
+    case AudioDeviceNodeCreationStatus::AccessDenied:
+      return "AccessDenied";
+    case AudioDeviceNodeCreationStatus::DeviceNotAvailable:
+      return "DeviceNotAvailable";
+    case AudioDeviceNodeCreationStatus::FormatNotSupported:
+      return "FormatNotSupported";
+    case AudioDeviceNodeCreationStatus::Success:
+      return "Success";
+    case AudioDeviceNodeCreationStatus::UnknownFailure:
+      return "UnknownFailure";
+  }
+  return "Unknown";
+}
+
+bool IsUiThread() {
+  auto dispatcher = starboard::shared::uwp::GetDispatcher();
+  // Is UI thread.
+  return dispatcher->HasThreadAccess;
+}
+
+std::vector<DeviceInformation^> GetAllMicrophoneDevices() {
+  std::vector<DeviceInformation^> output;
+  Platform::String^ audio_str = MediaDevice::GetAudioCaptureSelector();
+  DeviceInformationCollection^ all_devices =
+      starboard::shared::uwp::WaitForResult(
+          DeviceInformation::FindAllAsync(audio_str));
+  for (DeviceInformation^ dev_info : all_devices) {
+    output.push_back(dev_info);
+  }
+
+  return output;
+}
+
+AudioGraph^ CreateAudioGraph(AudioRenderCategory category,
+                             QuantumSizeSelectionMode selection_mode) {
+  AudioGraphSettings^ settings = ref new AudioGraphSettings(category);
+  settings->QuantumSizeSelectionMode = selection_mode;
+  CreateAudioGraphResult^ result =
+      starboard::shared::uwp::WaitForResult(AudioGraph::CreateAsync(settings));
+  SB_DCHECK(result->Status == AudioGraphCreationStatus::Success);
+  AudioGraph^ graph = result->Graph;
+  return graph;
+}
+
+std::vector<AudioDeviceInputNode^> GenerateAudioInputNodes(
+    const std::vector<DeviceInformation^>& microphone_devices,
+    AudioEncodingProperties^ encoding_properties,
+    AudioGraph^ graph) {
+  std::vector<AudioDeviceInputNode^> output;
+  for (DeviceInformation^ mic : microphone_devices) {
+    auto create_microphone_input_task = graph->CreateDeviceInputNodeAsync(
+        MediaCategory::Speech, encoding_properties, mic);
+    CreateAudioDeviceInputNodeResult^ deviceInputNodeResult =
+        starboard::shared::uwp::WaitForResult(create_microphone_input_task);
+
+    auto status = deviceInputNodeResult->Status;
+    AudioDeviceInputNode^ input_node = deviceInputNodeResult->DeviceInputNode;
+
+    if (status != AudioDeviceNodeCreationStatus::Success) {
+      SB_LOG(INFO) << "Failed to create microphone with device name \""
+                   << platformStringToString(mic->Name) << "\" because "
+                   << ToString(status);
+      continue;
+    }
+
+    SB_LOG(INFO) << "Created a microphone with device \""
+                 << platformStringToString(mic->Name) << "\"";
+
+    input_node->ConsumeInput = true;
+    input_node->OutgoingGain = kMicGain;
+    output.push_back(input_node);
+  }
+  return output;
+}
+
+// Reinterprets underlying buffer type to match destination vector.
+void ExtractRawAudioData(AudioFrameOutputNode^ node,
+                         std::vector<float>* destination) {
+  AudioFrame^ audio_frame = node->GetFrame();
+  AudioBuffer^ audio_buffer =
+      audio_frame->LockBuffer(AudioBufferAccessMode::Read);
+  IMemoryBufferReference^ memory_buffer_reference =
+      audio_buffer->CreateReference();
+
+  ComPtr<IMemoryBufferByteAccess> memory_byte_access;
+  HRESULT hr = reinterpret_cast<IInspectable*>(memory_buffer_reference)
+                   ->QueryInterface(IID_PPV_ARGS(&memory_byte_access));
+  CheckResult(hr);
+
+  BYTE* data = nullptr;
+  UINT32 capacity = 0;
+  hr = memory_byte_access->GetBuffer(&data, &capacity);
+  CheckResult(hr);
+
+  // Audio data is float data, so the buffer must be a multiple of 4.
+  SB_DCHECK(capacity % sizeof(float) == 0);
+
+  if (capacity > 0) {
+    float* typed_data = reinterpret_cast<float*>(data);
+    const size_t typed_data_size = capacity / sizeof(float);
+    destination->insert(destination->end(), typed_data,
+                        typed_data + typed_data_size);
+  }
+}
+
+// Timer useful for detecting that the microphone has been muted for a certain
+// amount of time.
+class MutedTrigger {
+ public:
+  void SignalMuted() {
+    if (state_ != kInitialized) {
+      return;
+    }
+    state_ = kIsMuted;
+    time_start_ = SbTimeGetMonotonicNow();
+  }
+
+  void SignalSound() {
+    state_ = kFoundSound;
+  }
+
+  bool IsMuted(SbTimeMonotonic duration_theshold) const {
+    if (state_ != kIsMuted) {
+      return false;
+    }
+    SbTimeMonotonic duration = SbTimeGetMonotonicNow() - time_start_;
+    return duration > duration_theshold;
+  }
+
+ private:
+  enum State {
+    kInitialized,
+    kIsMuted,
+    kFoundSound
+  };
+  State state_ = kInitialized;
+  SbTimeMonotonic time_start_ = 0;
+};
+
+// MicrophoneProcessor encapsulates Microsoft's audio api. All available
+// microphones are queried and instantiated. This class will mix the audio
+// together into one signed 16-bit pcm stream.
+//
+// When the microphone is created it will find all available microphones and
+// immediately start recording. A callback will be created which will process
+// audio data when new samples are available. The Microphone will stop
+// recording when Close() is called.
+ref class MicrophoneProcessor sealed {
+ public:
+  // This will try and create a microphone. This will fail (return null) if
+  // there are not available microphones.
+  static MicrophoneProcessor^ TryCreateAndStartRecording(
+      size_t max_num_samples,
+      int sample_rate) {
+    std::vector<DeviceInformation^> microphone_devices =
+        GetAllMicrophoneDevices();
+    if (microphone_devices.empty()) {  // Unexpected condition.
+      return nullptr;
+    }
+
+    MicrophoneProcessor^ output = ref new MicrophoneProcessor(
+        max_num_samples, sample_rate, microphone_devices);
+
+    if (output->input_nodes_.empty()) {
+      output = nullptr;
+    }
+    return output;
+  }
+
+  virtual ~MicrophoneProcessor() {
+  }
+
+  void Close() {
+    audio_graph_->QuantumStarted -= removal_token_;
+    ScopedLock lock(mutex_);
+    audio_graph_->Stop();
+  }
+
+  // Returns the number of elements that have been written, or -1 if there
+  // was a read error.
+  int Read(int16_t* out_audio_data, size_t out_audio_count) {
+    ScopedLock lock(mutex_);
+    if (muted_timer_.IsMuted(kTimeMutedThreshold)) {
+      return -1;
+    }
+
+    out_audio_count = std::min(out_audio_count,
+                               pcm_audio_data_.size());
+    using iter = std::vector<int16_t>::iterator;
+    iter it_begin = pcm_audio_data_.begin();
+    iter it_end = pcm_audio_data_.begin() + out_audio_count;
+    std::copy(it_begin, it_end, out_audio_data);
+    pcm_audio_data_.erase(it_begin, it_end);
+    return static_cast<int>(out_audio_count);
+  }
+
+ private:
+  explicit MicrophoneProcessor(
+      size_t max_num_samples,
+      int sample_rate,
+      const std::vector<DeviceInformation^>& microphone_devices)
+          : max_num_samples_(max_num_samples) {
+    audio_graph_ = CreateAudioGraph(AudioRenderCategory::Speech,
+                                    QuantumSizeSelectionMode::SystemDefault);
+    wave_encoder_ =
+        AudioEncodingProperties::CreatePcm(sample_rate, kNumChannels,
+                                           16);  // 4-byte float.
+    SB_DCHECK(audio_graph_);
+    input_nodes_ = GenerateAudioInputNodes(microphone_devices, wave_encoder_,
+                                           audio_graph_);
+    for (AudioDeviceInputNode^ input_node : input_nodes_) {
+      AudioFrameOutputNode^ audio_frame_node =
+          audio_graph_->CreateFrameOutputNode(wave_encoder_);
+      audio_frame_node->ConsumeInput = true;
+      input_node->AddOutgoingConnection(audio_frame_node);
+      audio_channel_.emplace_back(new std::vector<float>());
+      audio_frame_nodes_.push_back(audio_frame_node);
+    }
+    // Update the audio data whenever a new audio sample has been finished.
+    removal_token_ =
+        audio_graph_->QuantumStarted +=
+            ref new TypedEventHandler<AudioGraph^, Object^>(
+                this, &MicrophoneProcessor::OnQuantumStarted);
+    audio_graph_->Start();
+  }
+
+  void OnQuantumStarted(AudioGraph^, Object^) {
+    Process();
+  }
+
+  void Process() {
+    ScopedLock lock(mutex_);
+    if (audio_frame_nodes_.empty()) {
+      return;
+    }
+    for (size_t i = 0; i < audio_frame_nodes_.size(); ++i) {
+      ExtractRawAudioData(audio_frame_nodes_[i], audio_channel_[i].get());
+    }
+
+    size_t num_elements = max_num_samples_;
+    for (const auto& audio_datum : audio_channel_) {
+      num_elements = std::min(audio_datum->size(), num_elements);
+    }
+    if (num_elements == 0) {
+      return;
+    }
+
+    bool is_muted = true;
+    // Mix all available audio channels together and convert to output buffer
+    // format. Detect if audio is muted.
+    for (int i = 0; i < num_elements; ++i) {
+      float mixed_sample = 0.0f;
+      for (const auto& audio_datum : audio_channel_) {
+        float sample = (*audio_datum)[i];
+        if (sample != 0.0) {
+          is_muted = false;
+        }
+        mixed_sample += sample;
+      }
+      pcm_audio_data_.push_back(To16BitPcm(mixed_sample));
+    }
+
+    // Trim values from finished pcm_data if the buffer has exceeded it's
+    // allowed size.
+    if (pcm_audio_data_.size() > max_num_samples_) {
+      size_t num_delete = pcm_audio_data_.size() - max_num_samples_;
+      pcm_audio_data_.erase(pcm_audio_data_.begin(),
+                            pcm_audio_data_.begin() + num_delete);
+    }
+
+    if (is_muted) {
+      muted_timer_.SignalMuted();
+    } else {
+      muted_timer_.SignalSound();
+    }
+    // Trim values from source channels that were just transfered to
+    // pcm_audio_data.
+    for (const auto& audio_datum : audio_channel_) {
+      audio_datum->erase(audio_datum->begin(),
+                         audio_datum->begin() + num_elements);
+    }
+  }
+
+  AudioGraph^ audio_graph_ = nullptr;
+  AudioEncodingProperties^ wave_encoder_;
+  std::vector<AudioDeviceInputNode^> input_nodes_;
+  std::vector<AudioFrameOutputNode^> audio_frame_nodes_;
+  std::vector<std::unique_ptr<std::vector<float>>> audio_channel_;
+  std::vector<int16_t> pcm_audio_data_;
+  EventRegistrationToken removal_token_;
+  size_t max_num_samples_ = 0;
+  MutedTrigger muted_timer_;
+  Mutex mutex_;
+};
+
+// Implements the SbMicrophonePrivate interface.
+class MicrophoneImpl : public SbMicrophonePrivate {
+ public:
+  MicrophoneImpl(int sample_rate, int buffer_size_bytes)
+      : buffer_size_bytes_(buffer_size_bytes),
+        sample_rate_(sample_rate) {
+  }
+
+  ~MicrophoneImpl() { Close(); }
+
+  bool Open() override {
+    if (!microphone_.Get()) {
+      if (IsUiThread()) {
+        SB_LOG(INFO) << "Could not open microphone from UI thread.";
+        return false;
+      }
+      microphone_ = MicrophoneProcessor::TryCreateAndStartRecording(
+          buffer_size_bytes_ / kOutputBytesPerSample,
+          sample_rate_);
+    }
+    return microphone_ != nullptr;
+  }
+
+  bool Close() override {
+    microphone_->Close();
+    microphone_ = nullptr;
+    return true;
+  }
+
+  int Read(void* out_audio_data, int audio_data_size) override {
+    if (!microphone_.Get()) {
+      return -1;
+    }
+    int16_t* pcm_buffer = reinterpret_cast<int16*>(out_audio_data);
+    size_t pcm_buffer_count = audio_data_size / kOutputBytesPerSample;
+    int n_samples = microphone_->Read(pcm_buffer, pcm_buffer_count);
+    if (n_samples < 0) {
+      return -1;  // Is error.
+    } else {
+      return n_samples * kOutputBytesPerSample;
+    }
+  }
+
+ private:
+  const int buffer_size_bytes_;
+  const int sample_rate_;
+  Platform::Agile<MicrophoneProcessor> microphone_;
+};
+
+// Singleton access is required by the microphone interface as specified by
+// nplb.
+const SbMicrophoneId kSingletonId =
+    reinterpret_cast<SbMicrophoneId>(0x1);
+starboard::atomic_pointer<MicrophoneImpl*> s_singleton_pointer;
+
+}  // namespace.
+
+int SbMicrophonePrivate::GetAvailableMicrophones(
+    SbMicrophoneInfo* out_info_array,
+    int info_array_size) {
+  if (GetAllMicrophoneDevices().empty()) {
+    return 0;
+  }
+  if (out_info_array && (info_array_size >= 1)) {
+    SbMicrophoneInfo info = {kSingletonId, kSBMicrophoneAnalogHeadset,
+                             kMaxSampleRate, kMinReadSizeBytes};
+    out_info_array[0] = info;
+  }
+  return 1;
+}
+
+bool SbMicrophonePrivate::IsMicrophoneSampleRateSupported(
+    SbMicrophoneId id,
+    int sample_rate_in_hz) {
+  if (!SbMicrophoneIdIsValid(id)) {
+    return false;
+  }
+  return (kMinSampleRate <= sample_rate_in_hz) &&
+         (sample_rate_in_hz <= kMaxSampleRate);
+}
+
+SbMicrophone SbMicrophonePrivate::CreateMicrophone(SbMicrophoneId id,
+                                                   int sample_rate_in_hz,
+                                                   int buffer_size_bytes) {
+  if (!SbMicrophoneIdIsValid(id)) {
+    return kSbMicrophoneInvalid;
+  }
+  if (sample_rate_in_hz < kMinSampleRate) {
+    return kSbMicrophoneInvalid;
+  }
+  if (sample_rate_in_hz > kMaxSampleRate) {
+    return kSbMicrophoneInvalid;
+  }
+  if (buffer_size_bytes <= 0) {
+    return kSbMicrophoneInvalid;
+  }
+  // Required to conform to nplb test.
+  if (buffer_size_bytes >= (std::numeric_limits<int>::max() - 1)) {
+    return kSbMicrophoneInvalid;
+  }
+  // Id will either by 1 or 0. At this time there is only one microphone.
+  SB_DCHECK(id == kSingletonId);
+  if (s_singleton_pointer.load()) {
+    return kSbMicrophoneInvalid;
+  }
+  MicrophoneImpl* new_microphone =
+      new MicrophoneImpl(sample_rate_in_hz, buffer_size_bytes);
+
+  s_singleton_pointer.store(new_microphone);
+  return new_microphone;
+}
+
+void SbMicrophonePrivate::DestroyMicrophone(SbMicrophone microphone) {
+  SB_DCHECK(microphone == s_singleton_pointer.load());
+  s_singleton_pointer.store(nullptr);
+  delete microphone;
+}
diff --git a/src/starboard/shared/uwp/starboard_platform.gypi b/src/starboard/shared/uwp/starboard_platform.gypi
index 7b0c645..4942469 100644
--- a/src/starboard/shared/uwp/starboard_platform.gypi
+++ b/src/starboard/shared/uwp/starboard_platform.gypi
@@ -44,6 +44,27 @@
       'window_internal.h',
       'window_set_default_options.cc',
       'winrt_workaround.h',
+
+      'private/keys.cc',
+      'private/keys.h',
+
+      # Microphone section.
+      '<(DEPTH)/starboard/shared/uwp/microphone_impl.cc',
+      '<(DEPTH)/starboard/shared/starboard/microphone/microphone_get_available.cc',
+      '<(DEPTH)/starboard/shared/starboard/microphone/microphone_get_available.h',
+      '<(DEPTH)/starboard/shared/starboard/microphone/microphone_close.cc',
+      '<(DEPTH)/starboard/shared/starboard/microphone/microphone_close.h',
+      '<(DEPTH)/starboard/shared/starboard/microphone/microphone_create.cc',
+      '<(DEPTH)/starboard/shared/starboard/microphone/microphone_create.h',
+      '<(DEPTH)/starboard/shared/starboard/microphone/microphone_destroy.cc',
+      '<(DEPTH)/starboard/shared/starboard/microphone/microphone_destroy.h',
+      '<(DEPTH)/starboard/shared/starboard/microphone/microphone_get_available.cc',
+      '<(DEPTH)/starboard/shared/starboard/microphone/microphone_get_available.h',
+      '<(DEPTH)/starboard/shared/starboard/microphone/microphone_internal.h',
+      '<(DEPTH)/starboard/shared/starboard/microphone/microphone_is_sample_rate_supported.cc',
+      '<(DEPTH)/starboard/shared/starboard/microphone/microphone_open.cc',
+      '<(DEPTH)/starboard/shared/starboard/microphone/microphone_read.cc',
+
       '<(DEPTH)/starboard/shared/starboard/localized_strings.cc',
       '<(DEPTH)/starboard/shared/starboard/system_request_pause.cc',
       '<(DEPTH)/starboard/shared/starboard/system_request_stop.cc',
diff --git a/src/starboard/shared/uwp/system_get_property.cc b/src/starboard/shared/uwp/system_get_property.cc
index fbe65a3..0ee83a1 100644
--- a/src/starboard/shared/uwp/system_get_property.cc
+++ b/src/starboard/shared/uwp/system_get_property.cc
@@ -18,6 +18,7 @@
 
 #include "starboard/log.h"
 #include "starboard/shared/uwp/application_uwp.h"
+#include "starboard/shared/uwp/private/keys.h"
 #include "starboard/shared/win32/wchar_utils.h"
 #include "starboard/string.h"
 
@@ -78,12 +79,15 @@
   }
 
   using sbwin32::platformStringToString;
+  using starboard::shared::uwp::SpeechApiKey;
 
   switch (property_id) {
     case kSbSystemPropertyChipsetModelNumber:
     case kSbSystemPropertyModelYear:
     case kSbSystemPropertyNetworkOperatorName:
     case kSbSystemPropertySpeechApiKey:
+      CopyStringAndTestIfSuccess(out_value, value_length, SpeechApiKey());
+      return true;
     case kSbSystemPropertyUserAgentAuxField:
       return false;
     case kSbSystemPropertyBrandName: {
diff --git a/src/starboard/shared/win32/audio_decoder.cc b/src/starboard/shared/win32/audio_decoder.cc
index e76b8a0..f3af606 100644
--- a/src/starboard/shared/win32/audio_decoder.cc
+++ b/src/starboard/shared/win32/audio_decoder.cc
@@ -137,8 +137,10 @@
   return decoder_impl_->GetSamplesPerSecond();
 }
 
-void AudioDecoder::Initialize(const Closure& output_cb) {
+void AudioDecoder::Initialize(const Closure& output_cb,
+                              const Closure& error_cb) {
   SB_DCHECK(thread_checker_.CalledOnValidThread());
+  SB_UNREFERENCED_PARAMETER(error_cb);
 
   SB_DCHECK(output_cb.is_valid());
   SB_DCHECK(!output_cb_.is_valid());
diff --git a/src/starboard/shared/win32/audio_decoder.h b/src/starboard/shared/win32/audio_decoder.h
index c0516d7..1ea9583 100644
--- a/src/starboard/shared/win32/audio_decoder.h
+++ b/src/starboard/shared/win32/audio_decoder.h
@@ -51,7 +51,8 @@
   SbMediaAudioSampleType GetSampleType() const SB_OVERRIDE;
   int GetSamplesPerSecond() const SB_OVERRIDE;
 
-  void Initialize(const Closure& output_cb) SB_OVERRIDE;
+  void Initialize(const Closure& output_cb,
+                  const Closure& error_cb) SB_OVERRIDE;
   SbMediaAudioFrameStorageType GetStorageType() const SB_OVERRIDE {
     return kSbMediaAudioFrameStorageTypeInterleaved;
   }
diff --git a/src/starboard/shared/win32/audio_transform.cc b/src/starboard/shared/win32/audio_transform.cc
index 834d612..85c03b1 100644
--- a/src/starboard/shared/win32/audio_transform.cc
+++ b/src/starboard/shared/win32/audio_transform.cc
@@ -16,6 +16,7 @@
 
 #include <vector>
 
+#include "starboard/memory.h"
 #include "starboard/shared/win32/error_utils.h"
 #include "starboard/shared/win32/media_common.h"
 #include "starboard/shared/win32/media_foundation_utils.h"
@@ -49,37 +50,35 @@
 class WinAudioFormat {
  public:
   explicit WinAudioFormat(const SbMediaAudioHeader& audio_header) {
-    WAVEFORMATEX* wave_format = WaveFormatTexPtr();
+    // The WAVEFORMATEX structure has many specializations with varying
+    // data attached at the end.
+    format_buffer_.resize(sizeof(WAVEFORMATEX) +
+                          audio_header.audio_specific_config_size);
+    WAVEFORMATEX* wave_format = WaveFormatData();
+
     wave_format->nAvgBytesPerSec = audio_header.average_bytes_per_second;
     wave_format->nBlockAlign = audio_header.block_alignment;
     wave_format->nChannels = audio_header.number_of_channels;
     wave_format->nSamplesPerSec = audio_header.samples_per_second;
     wave_format->wBitsPerSample = audio_header.bits_per_sample;
     wave_format->wFormatTag = audio_header.format_tag;
+    wave_format->cbSize = audio_header.audio_specific_config_size;
 
-    // TODO: Investigate this more.
-    wave_format->cbSize = kAudioExtraFormatBytes;
-    std::uint8_t* audio_specific_config = AudioSpecificConfigPtr();
-
-    // These are hard-coded audio specif audio configuration.
-    // Use |SbMediaAudioHeader::audio_specific_config| instead.
-    SB_DCHECK(kAudioExtraFormatBytes == 2);
-    // TODO: What do these values do?
-    audio_specific_config[0] = 0x12;
-    audio_specific_config[1] = 0x10;
-  }
-  WAVEFORMATEX* WaveFormatTexPtr() {
-    return reinterpret_cast<WAVEFORMATEX*>(full_structure);
-  }
-  uint8_t* AudioSpecificConfigPtr() {
-    return full_structure + sizeof(WAVEFORMATEX);
+    if (audio_header.audio_specific_config_size > 0) {
+      uint8_t* config_data = format_buffer_.data() + sizeof(WAVEFORMATEX);
+      SbMemoryCopy(config_data,
+                   audio_header.audio_specific_config,
+                   audio_header.audio_specific_config_size);
+    }
   }
 
-  UINT32 Size() const { return sizeof(full_structure); }
+  WAVEFORMATEX* WaveFormatData() {
+    return reinterpret_cast<WAVEFORMATEX*>(format_buffer_.data());
+  }
+  UINT32 Size() const { return static_cast<UINT32>(format_buffer_.size()); }
 
  private:
-  static const UINT32 kAudioExtraFormatBytes = 2;
-  uint8_t full_structure[sizeof(WAVEFORMATEX) + kAudioExtraFormatBytes];
+  std::vector<uint8_t> format_buffer_;
 };
 
 }  // namespace.
@@ -97,7 +96,7 @@
 
   WinAudioFormat audio_fmt(audio);
   hr = MFInitMediaTypeFromWaveFormatEx(
-      input_type.Get(), audio_fmt.WaveFormatTexPtr(), audio_fmt.Size());
+      input_type.Get(), audio_fmt.WaveFormatData(), audio_fmt.Size());
 
   CheckResult(hr);
 
diff --git a/src/starboard/shared/win32/decode_target_internal.cc b/src/starboard/shared/win32/decode_target_internal.cc
index bba1e03..cc06ecb 100644
--- a/src/starboard/shared/win32/decode_target_internal.cc
+++ b/src/starboard/shared/win32/decode_target_internal.cc
@@ -14,53 +14,120 @@
 
 #include "starboard/shared/win32/decode_target_internal.h"
 
-#include <D3D11.h>
-#include <Mfidl.h>
-#include <Mfobjects.h>
-#include <wrl\client.h>  // For ComPtr.
-
 #include "starboard/configuration.h"
-#include "starboard/decode_target.h"
+#include "starboard/log.h"
 #include "starboard/memory.h"
 #include "starboard/shared/win32/error_utils.h"
-#include "starboard/shared/win32/media_common.h"
-#include "starboard/shared/win32/video_texture.h"
 #include "third_party/angle/include/EGL/egl.h"
 #include "third_party/angle/include/EGL/eglext.h"
 #include "third_party/angle/include/GLES2/gl2.h"
 #include "third_party/angle/include/GLES2/gl2ext.h"
 
+namespace {
+
 using Microsoft::WRL::ComPtr;
-using starboard::shared::win32::VideoFramePtr;
-using starboard::shared::win32::VideoTexture;
 using starboard::shared::win32::CheckResult;
 
 // {3C3A43AB-C69B-46C9-AA8D-B0CFFCD4596D}
-static const GUID kCobaltNv12BindChroma = {
+const GUID kCobaltNv12BindChroma = {
     0x3c3a43ab,
     0xc69b,
     0x46c9,
     {0xaa, 0x8d, 0xb0, 0xcf, 0xfc, 0xd4, 0x59, 0x6d}};
 
 // {C62BF18D-B5EE-46B1-9C31-F61BD8AE3B0D}
-static const GUID kCobaltDxgiBuffer = {
+const GUID kCobaltDxgiBuffer = {
     0Xc62bf18d,
     0Xb5ee,
     0X46b1,
     {0X9c, 0X31, 0Xf6, 0X1b, 0Xd8, 0Xae, 0X3b, 0X0d}};
 
-SbDecodeTargetPrivate::SbDecodeTargetPrivate(VideoFramePtr f) : frame(f) {
+ComPtr<ID3D11Texture2D> AllocateTexture(
+    const ComPtr<ID3D11Device>& d3d_device, int width, int height) {
+  ComPtr<ID3D11Texture2D> texture;
+  D3D11_TEXTURE2D_DESC texture_desc = {};
+  texture_desc.Width = width;
+  texture_desc.Height = height;
+  texture_desc.MipLevels = 1;
+  texture_desc.ArraySize = 1;
+  texture_desc.Format = DXGI_FORMAT_NV12;
+  texture_desc.SampleDesc.Count = 1;
+  texture_desc.SampleDesc.Quality = 0;
+  texture_desc.Usage = D3D11_USAGE_DEFAULT;
+  texture_desc.BindFlags =
+      D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE;
+  CheckResult(d3d_device->CreateTexture2D(&texture_desc, nullptr,
+      texture.GetAddressOf()));
+  return texture;
+}
+
+void UpdateTexture(
+    const ComPtr<ID3D11Texture2D>& texture,
+    const ComPtr<ID3D11VideoDevice1>& video_device,
+    const ComPtr<ID3D11VideoContext>& video_context,
+    const ComPtr<ID3D11VideoProcessorEnumerator>& video_enumerator,
+    const ComPtr<ID3D11VideoProcessor>& video_processor,
+    const ComPtr<IMFSample>& video_sample, const RECT& video_area) {
+  ComPtr<IMFMediaBuffer> media_buffer;
+  CheckResult(video_sample->GetBufferByIndex(0, media_buffer.GetAddressOf()));
+
+  ComPtr<IMFDXGIBuffer> dxgi_buffer;
+  CheckResult(media_buffer.As(&dxgi_buffer));
+
+  ComPtr<ID3D11Texture2D> input_texture;
+  CheckResult(dxgi_buffer->GetResource(IID_PPV_ARGS(&input_texture)));
+
+  // The VideoProcessor needs to know what subset of the decoded
+  // frame contains active pixels that should be displayed to the user.
+  video_context->VideoProcessorSetStreamSourceRect(
+      video_processor.Get(), 0, TRUE, &video_area);
+
+  D3D11_VIDEO_PROCESSOR_INPUT_VIEW_DESC input_desc = {};
+  input_desc.ViewDimension = D3D11_VPIV_DIMENSION_TEXTURE2D;
+  input_desc.Texture2D.MipSlice = 0;
+  dxgi_buffer->GetSubresourceIndex(&input_desc.Texture2D.ArraySlice);
+
+  ComPtr<ID3D11VideoProcessorInputView> input_view;
+  CheckResult(video_device->CreateVideoProcessorInputView(
+      input_texture.Get(), video_enumerator.Get(), &input_desc,
+      input_view.GetAddressOf()));
+
+  D3D11_VIDEO_PROCESSOR_OUTPUT_VIEW_DESC output_desc = {};
+  output_desc.ViewDimension = D3D11_VPOV_DIMENSION_TEXTURE2D;
+  output_desc.Texture2D.MipSlice = 0;
+
+  ComPtr<ID3D11VideoProcessorOutputView> output_view;
+  CheckResult(video_device->CreateVideoProcessorOutputView(
+      texture.Get(), video_enumerator.Get(), &output_desc,
+      output_view.GetAddressOf()));
+
+  // We have a single video stream, which is enabled for display.
+  D3D11_VIDEO_PROCESSOR_STREAM stream_info = {};
+  stream_info.Enable = TRUE;
+  stream_info.pInputSurface = input_view.Get();
+  CheckResult(video_context->VideoProcessorBlt(
+      video_processor.Get(), output_view.Get(), 0, 1, &stream_info));
+}
+
+}  // namespace
+
+SbDecodeTargetPrivate::SbDecodeTargetPrivate(
+    const ComPtr<ID3D11Device>& d3d_device,
+    const ComPtr<ID3D11VideoDevice1>& video_device,
+    const ComPtr<ID3D11VideoContext>& video_context,
+    const ComPtr<ID3D11VideoProcessorEnumerator>& video_enumerator,
+    const ComPtr<ID3D11VideoProcessor>& video_processor,
+    const ComPtr<IMFSample>& video_sample, const RECT& video_area)
+    : refcount(1) {
   SbMemorySet(&info, 0, sizeof(info));
-
-  VideoTexture* texture = static_cast<VideoTexture*>(frame->native_texture());
-
-  ComPtr<ID3D11Texture2D> d3texture = texture->GetTexture();
-
   info.format = kSbDecodeTargetFormat2PlaneYUVNV12;
   info.is_opaque = true;
+  info.width = video_area.right;
+  info.height = video_area.bottom;
 
-  info.width = frame->width();
-  info.height = frame->height();
+  d3d_texture = AllocateTexture(d3d_device, info.width, info.height);
+  UpdateTexture(d3d_texture, video_device, video_context, video_enumerator,
+      video_processor, video_sample, video_area);
 
   SbDecodeTargetInfoPlane* planeY = &(info.planes[kSbDecodeTargetPlaneY]);
   SbDecodeTargetInfoPlane* planeUV = &(info.planes[kSbDecodeTargetPlaneUV]);
@@ -69,8 +136,8 @@
   planeY->height = info.height;
   planeY->content_region.left = 0;
   planeY->content_region.top = info.height;
-  planeY->content_region.right = frame->width();
-  planeY->content_region.bottom = info.height - frame->height();
+  planeY->content_region.right = info.width;
+  planeY->content_region.bottom = 0;
 
   planeUV->width = info.width / 2;
   planeUV->height = info.height / 2;
@@ -122,11 +189,11 @@
 
   // This tells ANGLE that the texture it creates should draw
   // the luma channel on R8.
-  HRESULT hr = d3texture->SetPrivateData(kCobaltNv12BindChroma, 0, nullptr);
+  HRESULT hr = d3d_texture->SetPrivateData(kCobaltNv12BindChroma, 0, nullptr);
   SB_DCHECK(SUCCEEDED(hr));
 
   surface[0] = eglCreatePbufferFromClientBuffer(display, EGL_D3D_TEXTURE_ANGLE,
-                                                d3texture.Get(), config,
+                                                d3d_texture.Get(), config,
                                                 luma_texture_attributes);
 
   SB_DCHECK(surface[0] != EGL_NO_SURFACE);
@@ -147,7 +214,7 @@
   // This tells ANGLE that the texture it creates should draw
   // the chroma channel on R8G8.
   bool bind_chroma = true;
-  hr = d3texture->SetPrivateData(kCobaltNv12BindChroma, 1, &bind_chroma);
+  hr = d3d_texture->SetPrivateData(kCobaltNv12BindChroma, 1, &bind_chroma);
   SB_DCHECK(SUCCEEDED(hr));
 
   EGLint chroma_texture_attributes[] = {
@@ -161,7 +228,7 @@
       EGL_TEXTURE_RGBA,
       EGL_NONE};
   surface[1] = eglCreatePbufferFromClientBuffer(display, EGL_D3D_TEXTURE_ANGLE,
-                                                d3texture.Get(), config,
+                                                d3d_texture.Get(), config,
                                                 chroma_texture_attributes);
 
   SB_DCHECK(surface[1] != EGL_NO_SURFACE);
@@ -179,7 +246,7 @@
   planeUV->gl_texture_target = GL_TEXTURE_2D;
   planeUV->gl_texture_format = GL_RG_EXT;
 
-  hr = d3texture->SetPrivateData(kCobaltDxgiBuffer, 0, nullptr);
+  hr = d3d_texture->SetPrivateData(kCobaltDxgiBuffer, 0, nullptr);
   SB_DCHECK(SUCCEEDED(hr));
 }
 
@@ -196,9 +263,49 @@
   eglDestroySurface(display, surface[1]);
 }
 
+bool SbDecodeTargetPrivate::Update(
+    const ComPtr<ID3D11Device>& d3d_device,
+    const ComPtr<ID3D11VideoDevice1>& video_device,
+    const ComPtr<ID3D11VideoContext>& video_context,
+    const ComPtr<ID3D11VideoProcessorEnumerator>& video_enumerator,
+    const ComPtr<ID3D11VideoProcessor>& video_processor,
+    const ComPtr<IMFSample>& video_sample,
+    const RECT& video_area) {
+  // Only allow updating if this is the only reference. Otherwise the update
+  // may change something that's currently being used.
+  if (SbAtomicNoBarrier_Load(&refcount) > 1) {
+    return false;
+  }
+
+  // The decode target info must be compatible.
+  if (info.format != kSbDecodeTargetFormat2PlaneYUVNV12 ||
+      info.is_opaque != true ||
+      info.width != video_area.right ||
+      info.height != video_area.bottom) {
+    return false;
+  }
+
+  SB_UNREFERENCED_PARAMETER(d3d_device);
+  UpdateTexture(d3d_texture, video_device, video_context, video_enumerator,
+      video_processor, video_sample, video_area);
+  return true;
+}
+
+void SbDecodeTargetPrivate::AddRef() {
+  SbAtomicBarrier_Increment(&refcount, 1);
+}
+
+void SbDecodeTargetPrivate::Release() {
+  int new_count = SbAtomicBarrier_Increment(&refcount, -1);
+  SB_DCHECK(new_count >= 0);
+  if (new_count == 0) {
+    delete this;
+  }
+}
+
 void SbDecodeTargetRelease(SbDecodeTarget decode_target) {
   if (SbDecodeTargetIsValid(decode_target)) {
-    delete decode_target;
+    decode_target->Release();
   }
 }
 
diff --git a/src/starboard/shared/win32/decode_target_internal.h b/src/starboard/shared/win32/decode_target_internal.h
index 81aa66e..a0cce17 100644
--- a/src/starboard/shared/win32/decode_target_internal.h
+++ b/src/starboard/shared/win32/decode_target_internal.h
@@ -15,19 +15,53 @@
 #ifndef STARBOARD_SHARED_WIN32_DECODE_TARGET_INTERNAL_H_
 #define STARBOARD_SHARED_WIN32_DECODE_TARGET_INTERNAL_H_
 
-#include "starboard/common/ref_counted.h"
+#include <D3d11_1.h>
+#include <mfidl.h>
+#include <wrl/client.h>
+
+#include "starboard/atomic.h"
 #include "starboard/decode_target.h"
-#include "starboard/shared/win32/media_common.h"
 
 struct SbDecodeTargetPrivate {
+  template <typename T>
+  using ComPtr = Microsoft::WRL::ComPtr<T>;
+
+  SbAtomic32 refcount;
+
   // Publicly accessible information about the decode target.
   SbDecodeTargetInfo info;
-  ::starboard::shared::win32::VideoFramePtr frame;
+
+  ComPtr<ID3D11Texture2D> d3d_texture;
+
   // EGLSurface is defined as void* in "third_party/angle/include/EGL/egl.h".
   // Use void* directly here to avoid `egl.h` being included broadly.
   void* surface[2];
-  explicit SbDecodeTargetPrivate(starboard::shared::win32::VideoFramePtr frame);
+
+  SbDecodeTargetPrivate(
+      const ComPtr<ID3D11Device>& d3d_device,
+      const ComPtr<ID3D11VideoDevice1>& video_device,
+      const ComPtr<ID3D11VideoContext>& video_context,
+      const ComPtr<ID3D11VideoProcessorEnumerator>& video_enumerator,
+      const ComPtr<ID3D11VideoProcessor>& video_processor,
+      const ComPtr<IMFSample>& video_sample,
+      const RECT& video_area);
   ~SbDecodeTargetPrivate();
+
+  // Update the existing texture with the given video_sample's data.
+  // If the current object is not compatible with the new video_sample, then
+  // this will return false, and the caller should just create a new
+  // decode target for the sample.
+  bool Update(
+      const ComPtr<ID3D11Device>& d3d_device,
+      const ComPtr<ID3D11VideoDevice1>& video_device,
+      const ComPtr<ID3D11VideoContext>& video_context,
+      const ComPtr<ID3D11VideoProcessorEnumerator>& video_enumerator,
+      const ComPtr<ID3D11VideoProcessor>& video_processor,
+      const ComPtr<IMFSample>& video_sample,
+      const RECT& video_area);
+
+  void AddRef();
+  void Release();
 };
 
 #endif  // STARBOARD_SHARED_WIN32_DECODE_TARGET_INTERNAL_H_
diff --git a/src/starboard/shared/win32/directory_can_open.cc b/src/starboard/shared/win32/directory_can_open.cc
index b64a410..cb8cb30 100644
--- a/src/starboard/shared/win32/directory_can_open.cc
+++ b/src/starboard/shared/win32/directory_can_open.cc
@@ -15,21 +15,26 @@
 #include "starboard/directory.h"
 
 #include <windows.h>
-
 #include <algorithm>
 
 #include "starboard/shared/win32/directory_internal.h"
+#include "starboard/shared/win32/file_internal.h"
 #include "starboard/shared/win32/wchar_utils.h"
 
 bool SbDirectoryCanOpen(const char* path) {
+  using starboard::shared::win32::IsAbsolutePath;
+  using starboard::shared::win32::IsValidHandle;
+  using starboard::shared::win32::NormalizeWin32Path;
+  using starboard::shared::win32::TrimExtraFileSeparators;
+
   if ((path == nullptr) || (path[0] == '\0')) {
     return false;
   }
 
-  std::wstring path_wstring = starboard::shared::win32::CStringToWString(path);
-  starboard::shared::win32::TrimExtraFileSeparators(&path_wstring);
+  std::wstring path_wstring = NormalizeWin32Path(path);
+  TrimExtraFileSeparators(&path_wstring);
 
-  if (!starboard::shared::win32::IsAbsolutePath(path_wstring)) {
+  if (!IsAbsolutePath(path_wstring)) {
     return false;
   }
 
@@ -38,7 +43,7 @@
   HANDLE search_handle = FindFirstFileExW(
       path_wstring.c_str(), FindExInfoStandard, &find_data,
       FindExSearchNameMatch, NULL, FIND_FIRST_EX_CASE_SENSITIVE);
-  if (!starboard::shared::win32::IsValidHandle(search_handle)) {
+  if (!IsValidHandle(search_handle)) {
     return false;
   }
 
diff --git a/src/starboard/shared/win32/directory_create.cc b/src/starboard/shared/win32/directory_create.cc
index 26b1845..4f99f90 100644
--- a/src/starboard/shared/win32/directory_create.cc
+++ b/src/starboard/shared/win32/directory_create.cc
@@ -17,25 +17,28 @@
 #include <windows.h>
 
 #include "starboard/shared/win32/directory_internal.h"
+#include "starboard/shared/win32/file_internal.h"
 #include "starboard/shared/win32/wchar_utils.h"
 
 bool SbDirectoryCreate(const char* path) {
+  using starboard::shared::win32::DirectoryExists;
+  using starboard::shared::win32::NormalizeWin32Path;
+
   if ((path == nullptr) || (path[0] == '\0')) {
     return false;
   }
 
-  std::wstring path_wstring = starboard::shared::win32::CStringToWString(path);
-
+  std::wstring path_wstring = NormalizeWin32Path(path);
   starboard::shared::win32::TrimExtraFileSeparators(&path_wstring);
 
   if (!starboard::shared::win32::IsAbsolutePath(path_wstring)) {
     return false;
   }
 
+  if (DirectoryExists(path_wstring)) {
+    return true;
+  }
+
   BOOL directory_created = CreateDirectoryW(path_wstring.c_str(), NULL);
-
-  bool directory_exists =
-      directory_created || (GetLastError() == ERROR_ALREADY_EXISTS);
-
-  return directory_exists;
+  return directory_created;
 }
diff --git a/src/starboard/shared/win32/directory_open.cc b/src/starboard/shared/win32/directory_open.cc
index 6dade7e..adad7aa 100644
--- a/src/starboard/shared/win32/directory_open.cc
+++ b/src/starboard/shared/win32/directory_open.cc
@@ -15,9 +15,13 @@
 #include "starboard/directory.h"
 
 #include "starboard/shared/win32/directory_internal.h"
+#include "starboard/shared/win32/file_internal.h"
 #include "starboard/shared/win32/wchar_utils.h"
 
 SbDirectory SbDirectoryOpen(const char* path, SbFileError* out_error) {
+  using starboard::shared::win32::CStringToWString;
+  using starboard::shared::win32::NormalizeWin32Path;
+
   if ((path == nullptr) || (path[0] == '\0')) {
     if (out_error) {
       *out_error = kSbFileErrorNotFound;
@@ -25,7 +29,7 @@
     return kSbDirectoryInvalid;
   }
 
-  std::wstring path_wstring = starboard::shared::win32::CStringToWString(path);
+  std::wstring path_wstring = NormalizeWin32Path(path);
 
   if (!starboard::shared::win32::IsAbsolutePath(path_wstring)) {
     if (out_error) {
diff --git a/src/starboard/shared/win32/drm_system_playready.cc b/src/starboard/shared/win32/drm_system_playready.cc
index c3c7f21..e2d8207 100644
--- a/src/starboard/shared/win32/drm_system_playready.cc
+++ b/src/starboard/shared/win32/drm_system_playready.cc
@@ -103,7 +103,10 @@
       License::Create(initialization_data, initialization_data_size);
   const std::string& challenge = license->license_challenge();
   if (challenge.empty()) {
-    SB_NOTREACHED();
+    // Signal an error with |session_id| as NULL.
+    SB_LOG(ERROR) << "Failed to generate license challenge";
+    session_update_request_callback_(this, context_, ticket, NULL, 0, NULL, 0,
+                                     NULL);
     return;
   }
 
diff --git a/src/starboard/shared/win32/file_delete.cc b/src/starboard/shared/win32/file_delete.cc
index fecbfd1..effa21c 100644
--- a/src/starboard/shared/win32/file_delete.cc
+++ b/src/starboard/shared/win32/file_delete.cc
@@ -20,11 +20,20 @@
 #include "starboard/shared/win32/wchar_utils.h"
 
 bool SbFileDelete(const char* path) {
+  using starboard::shared::win32::CStringToWString;
+  using starboard::shared::win32::NormalizeWin32Path;
+
   if ((path == nullptr) || *path == '\0') {
     return false;
   }
 
-  std::wstring path_wstring = starboard::shared::win32::CStringToWString(path);
+  if (!SbFileExists(path)) {
+    return true;
+  }
 
-  return DeleteFileW(path_wstring.c_str());
+  std::wstring path_wstring = NormalizeWin32Path(path);
+
+  // Remove file or empty directory.
+  return DeleteFileW(path_wstring.c_str()) ||
+         RemoveDirectoryW(path_wstring.c_str());
 }
diff --git a/src/starboard/shared/win32/file_exists.cc b/src/starboard/shared/win32/file_exists.cc
index 160f17d..2757cb2 100644
--- a/src/starboard/shared/win32/file_exists.cc
+++ b/src/starboard/shared/win32/file_exists.cc
@@ -20,22 +20,33 @@
 #include "starboard/shared/win32/wchar_utils.h"
 
 bool SbFileExists(const char* path) {
+  using starboard::shared::win32::CStringToWString;
+  using starboard::shared::win32::IsValidHandle;
+  using starboard::shared::win32::NormalizeWin32Path;
+  using starboard::shared::win32::PathEndsWith;
+
   if ((path == nullptr) || (path[0] == '\0')) {
     return false;
   }
 
-  std::wstring path_wstring = starboard::shared::win32::CStringToWString(path);
+  std::wstring path_wstring = NormalizeWin32Path(path);
+  // Win32 does not like a trailing "\\" on the path names for directories,
+  // so it's needs to be chopped off.
+  if (!path_wstring.empty() && (path_wstring.back() == '\\')) {
+    path_wstring.pop_back();
+  }
+
   WIN32_FIND_DATA find_data = {0};
 
   HANDLE search_handle = FindFirstFileExW(
       path_wstring.c_str(), FindExInfoStandard, &find_data,
       FindExSearchNameMatch, NULL, FIND_FIRST_EX_CASE_SENSITIVE);
 
-  if (!starboard::shared::win32::IsValidHandle(search_handle)) {
+  if (!IsValidHandle(search_handle)) {
     return false;
   }
 
   FindClose(search_handle);
 
-  return starboard::shared::win32::PathEndsWith(path_wstring, find_data.cFileName);
+  return PathEndsWith(path_wstring, find_data.cFileName);
 }
diff --git a/src/starboard/shared/win32/file_get_path_info.cc b/src/starboard/shared/win32/file_get_path_info.cc
index 4ac6928..28f4619 100644
--- a/src/starboard/shared/win32/file_get_path_info.cc
+++ b/src/starboard/shared/win32/file_get_path_info.cc
@@ -22,11 +22,14 @@
 #include "starboard/shared/win32/wchar_utils.h"
 
 bool SbFileGetPathInfo(const char* path, SbFileInfo* out_info) {
+  using starboard::shared::win32::CStringToWString;
+  using starboard::shared::win32::NormalizeWin32Path;
+
   if (!path || path[0] == '\0' || !out_info) {
     return false;
   }
 
-  std::wstring path_wstring = starboard::shared::win32::CStringToWString(path);
+  std::wstring path_wstring = NormalizeWin32Path(path);
 
   WIN32_FILE_ATTRIBUTE_DATA attribute_data = {0};
   if (!GetFileAttributesExW(path_wstring.c_str(), GetFileExInfoStandard,
diff --git a/src/starboard/shared/win32/file_internal.cc b/src/starboard/shared/win32/file_internal.cc
index 816483b..a9e8d78 100644
--- a/src/starboard/shared/win32/file_internal.cc
+++ b/src/starboard/shared/win32/file_internal.cc
@@ -17,6 +17,7 @@
 #include <windows.h>
 
 #include "starboard/log.h"
+#include "starboard/memory.h"
 #include "starboard/shared/win32/error_utils.h"
 #include "starboard/shared/win32/wchar_utils.h"
 
@@ -26,6 +27,58 @@
 namespace shared {
 namespace win32 {
 
+namespace {
+const char kUnixSep[] = "/";
+const char kWin32Sep[] = "\\";
+const wchar_t kUnixSepW[] = L"/";
+const wchar_t kWin32SepW[] = L"\\";
+
+bool IsPathNormalized(const std::string& string) {
+  return string.find(kUnixSep) == std::string::npos;
+}
+
+bool IsPathNormalized(const std::wstring& string) {
+  return string.find(kUnixSepW) == std::wstring::npos;
+}
+
+std::string NormalizePathSeperator(std::string str) {
+  size_t start_pos = 0;
+  while ((start_pos = str.find(kUnixSep, start_pos)) != std::string::npos) {
+    str.replace(start_pos, sizeof(kUnixSep) - 1, kWin32Sep);
+    start_pos += sizeof(kWin32Sep) - 1;
+  }
+  return str;
+}
+
+std::wstring NormalizePathSeperator(std::wstring str) {
+  size_t start_pos = 0;
+  while ((start_pos = str.find(kUnixSepW, start_pos)) != std::wstring::npos) {
+    str.replace(start_pos, sizeof(kUnixSepW) / 2 - 1, kWin32SepW);
+    start_pos += sizeof(kWin32SepW) / 2 - 1;
+  }
+  return str;
+}
+
+bool StringCanNarrow(const std::wstring& str) {
+  for (wchar_t value : str) {
+    char narrow_val = static_cast<char>(value);
+    if (value != narrow_val) {
+      return false;
+    }
+  }
+  return true;
+}
+
+}  // namespace
+
+std::wstring NormalizeWin32Path(std::string str) {
+  return NormalizeWin32Path(CStringToWString(str.c_str()));
+}
+
+std::wstring NormalizeWin32Path(std::wstring str) {
+  return NormalizePathSeperator(str);
+}
+
 HANDLE OpenFileOrDirectory(const char* path,
                            int flags,
                            bool* out_created,
@@ -141,6 +194,19 @@
   return file_handle;
 }
 
+bool DirectoryExists(const std::wstring& dir_path) {
+  if (dir_path.empty()) {
+    return false;
+  }
+  std::wstring norm_dir_path = NormalizeWin32Path(dir_path);
+  WIN32_FILE_ATTRIBUTE_DATA attribute_data = {0};
+  if (!GetFileAttributesExW(norm_dir_path.c_str(), GetFileExInfoStandard,
+                            &attribute_data)) {
+    return false;
+  }
+  return (attribute_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY);
+}
+
 }  // namespace win32
 }  // namespace shared
 }  // namespace starboard
diff --git a/src/starboard/shared/win32/file_internal.h b/src/starboard/shared/win32/file_internal.h
index 56a8a13..7a6bc7d 100644
--- a/src/starboard/shared/win32/file_internal.h
+++ b/src/starboard/shared/win32/file_internal.h
@@ -82,11 +82,18 @@
   return wcscmp(path.c_str() + path_offset, filename) == 0;
 }
 
+// Path's from cobalt use "/" as a path separator. This function will
+// replace all of the "/" with "\".
+std::wstring NormalizeWin32Path(std::string str);
+std::wstring NormalizeWin32Path(std::wstring str);
+
 HANDLE OpenFileOrDirectory(const char* path,
                            int flags,
                            bool* out_created,
                            SbFileError* out_error);
 
+bool DirectoryExists(const std::wstring& dir_path);
+
 }  // namespace win32
 }  // namespace shared
 }  // namespace starboard
diff --git a/src/starboard/shared/win32/gyp_configuration.py b/src/starboard/shared/win32/gyp_configuration.py
index af643cb..07f9739 100644
--- a/src/starboard/shared/win32/gyp_configuration.py
+++ b/src/starboard/shared/win32/gyp_configuration.py
@@ -11,21 +11,23 @@
 # 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.
-import imp
-import logging
+"""Starboard win32 shared platform configuration for gyp_cobalt."""
+
 import os
 import sys
 
-import config.starboard
+import config.base
 
-from starboard.tools.paths import STARBOARD_ROOT
 import starboard.shared.win32.sdk_configuration as sdk_configuration
-import starboard.tools.testing.test_filter as test_filter
+from starboard.tools.paths import STARBOARD_ROOT
+from starboard.tools.testing import test_filter
+
 
 def _QuotePath(path):
   return '"' + path + '"'
 
-class PlatformConfig(config.starboard.PlatformConfigStarboard):
+
+class PlatformConfig(config.base.PlatformConfigBase):
   """Starboard Microsoft Windows platform configuration."""
 
   def __init__(self, platform):
@@ -36,10 +38,10 @@
     sdk = self.sdk
     variables = super(PlatformConfig, self).GetVariables(configuration)
     variables.update({
-      'visual_studio_install_path': sdk.vs_install_dir_with_version,
-      'windows_sdk_path': sdk.windows_sdk_path,
-      'windows_sdk_version': sdk.required_sdk_version,
-      })
+        'visual_studio_install_path': sdk.vs_install_dir_with_version,
+        'windows_sdk_path': sdk.windows_sdk_path,
+        'windows_sdk_version': sdk.required_sdk_version,
+    })
     return variables
 
   def GetEnvironmentVariables(self):
@@ -123,4 +125,3 @@
                                test_filter.FILTER_ALL)
 
     ]
-
diff --git a/src/starboard/shared/win32/media_common.cc b/src/starboard/shared/win32/media_common.cc
index c572ee4..6f4c6e9 100644
--- a/src/starboard/shared/win32/media_common.cc
+++ b/src/starboard/shared/win32/media_common.cc
@@ -104,10 +104,8 @@
 
 HRESULT CreateDecoderTransform(const GUID& decoder_guid,
                                ComPtr<IMFTransform>* transform) {
-  LPVOID* ptr_address = reinterpret_cast<LPVOID*>(transform->GetAddressOf());
-  HRESULT hr = CoCreateInstance(decoder_guid, NULL, CLSCTX_INPROC_SERVER,
-                                IID_IMFTransform, ptr_address);
-  return hr;
+  return CoCreateInstance(decoder_guid, NULL, CLSCTX_INPROC_SERVER,
+                          IID_PPV_ARGS(transform->GetAddressOf()));
 }
 
 }  // namespace win32
diff --git a/src/starboard/shared/win32/media_is_video_supported.cc b/src/starboard/shared/win32/media_is_video_supported.cc
index 8f3824e..9afef3c 100644
--- a/src/starboard/shared/win32/media_is_video_supported.cc
+++ b/src/starboard/shared/win32/media_is_video_supported.cc
@@ -14,133 +14,91 @@
 
 #include "starboard/shared/starboard/media/media_support_internal.h"
 
-#include <sstream>
-
-#include "starboard/common/scoped_ptr.h"
-#include "starboard/configuration.h"
-#include "starboard/media.h"
-#include "starboard/once.h"
-#include "starboard/shared/win32/error_utils.h"
-#include "starboard/shared/win32/media_common.h"
-#include "starboard/shared/win32/media_foundation_utils.h"
-#include "starboard/shared/win32/media_transform.h"
-#include "starboard/shared/win32/video_transform.h"
-#include "starboard/window.h"
-
-// #define ENABLE_VP9_DECODER
-
-using Microsoft::WRL::ComPtr;
-using starboard::scoped_ptr;
-using starboard::ScopedLock;
-using starboard::shared::win32::CheckResult;
-using starboard::shared::win32::kVideoFormat_YV12;
-using starboard::shared::win32::MediaTransform;
-using starboard::shared::win32::TryCreateVP9Transform;
+#include <d3d11.h>
+#include <mfapi.h>
+#include <mfidl.h>
+#include <wrl/client.h>
 
 namespace {
 
-class VideoSupported {
- public:
-  static VideoSupported* GetSingleton();
-  bool IsVideoSupported(SbMediaVideoCodec video_codec,
-                        int frame_width,
-                        int frame_height,
-                        int64_t bitrate,
-                        int fps) {
-    // Is resolution out of range?
-    if (frame_width > max_width_ || frame_height > max_height_) {
-      return false;
-    }
-    // Is bitrate in range?
-    if (bitrate > SB_MEDIA_MAX_VIDEO_BITRATE_IN_BITS_PER_SECOND) {
-      return false;
-    }
-    if (fps > 60) {
-      return false;
-    }
-    if (video_codec == kSbMediaVideoCodecH264) {
-      return true;
-    }
-    if ((video_codec == kSbMediaVideoCodecVp9) && AllowVp9Decoder()) {
-      return IsVp9Supported(frame_width, frame_height);
-    }
-    return false;
-  }
-
- private:
-  static bool AllowVp9Decoder() {
-#ifdef ENABLE_VP9_DECODER
-    return true;
-#else
-    return false;
-#endif
-  }
-
-  static bool DetectVp9Supported(int width, int height) {
-    scoped_ptr<MediaTransform> vp9_decoder =
-        TryCreateVP9Transform(kVideoFormat_YV12, width, height);
-    return !!vp9_decoder.get();
-  }
-
-  bool IsVp9Supported(int width, int height) {
-    // When width/height is zero then this is a special value to mean
-    // IsVP9 available at all? Therefore detect the general case by
-    // testing the specific case of 1024 x 768.
-    if ((width == 0) && (height == 0)) {
-      return DetectVp9Supported(1024, 768);
-    }
-
-    Key key = {width, height};
-    ScopedLock lock(mutex_);
-    auto it = vpn_size_cache_.find(key);
-    if (it != vpn_size_cache_.end()) {
-      return it->second;
-    } else {
-      const bool vp9_valid = DetectVp9Supported(width, height);
-      vpn_size_cache_[key] = vp9_valid;
-      return vp9_valid;
-    }
-  }
-
-  VideoSupported() : max_width_(0), max_height_(0) {
-    Construct();
-  }
-
-  void Construct() {
-    SbWindowOptions sb_window_options;
-    SbWindowSetDefaultOptions(&sb_window_options);
-    max_width_ = sb_window_options.size.width;
-    max_height_ = sb_window_options.size.height;
-  }
-
-  struct Key {
-    int width = 0;
-    int height = 0;
-    bool operator<(const Key& other) const {
-      if (width != other.width) {
-        return width < other.width;
-      }
-      return height < other.height;
-    }
-  };
-
-  starboard::Mutex mutex_;
-  using Vp9SizeCache = std::map<Key, bool>;
-  Vp9SizeCache vpn_size_cache_;
-  int max_width_;
-  int max_height_;
+#if SB_HAS(MEDIA_WEBM_VP9_SUPPORT)
+// Cache the VP9 support status since the check may be expensive.
+enum Vp9Support {
+  kVp9SupportUnknown,
+  kVp9SupportYes,
+  kVp9SupportNo
 };
+Vp9Support s_vp9_support = kVp9SupportUnknown;
 
-SB_ONCE_INITIALIZE_FUNCTION(VideoSupported, VideoSupported::GetSingleton);
+// Check for VP9 support. Since this is used by a starboard function, it
+// cannot depend on other modules (e.g. ANGLE).
+bool IsVp9Supported() {
+  if (s_vp9_support == kVp9SupportUnknown) {
+    // Try initializing the VP9 decoder to determine if it is supported.
+    HRESULT hr;
 
-}  // namespace.
+    Microsoft::WRL::ComPtr<ID3D11Device> d3d_device;
+    hr = D3D11CreateDevice(nullptr, D3D_DRIVER_TYPE_HARDWARE, nullptr, 0,
+                           nullptr, 0, D3D11_SDK_VERSION,
+                           d3d_device.GetAddressOf(), nullptr, nullptr);
+
+    UINT reset_token = 0;
+    Microsoft::WRL::ComPtr<IMFDXGIDeviceManager> device_manager;
+    if (SUCCEEDED(hr)) {
+      hr = MFCreateDXGIDeviceManager(&reset_token,
+                                     device_manager.GetAddressOf());
+    }
+    if (SUCCEEDED(hr)) {
+      hr = device_manager->ResetDevice(d3d_device.Get(), reset_token);
+    }
+
+    Microsoft::WRL::ComPtr<IMFTransform> transform;
+    if (SUCCEEDED(hr)) {
+      hr = CoCreateInstance(CLSID_MSVPxDecoder, nullptr, CLSCTX_INPROC_SERVER,
+                            IID_PPV_ARGS(transform.GetAddressOf()));
+    }
+    if (SUCCEEDED(hr)) {
+      hr = transform->ProcessMessage(MFT_MESSAGE_SET_D3D_MANAGER,
+                                     ULONG_PTR(device_manager.Get()));
+    }
+
+    s_vp9_support = SUCCEEDED(hr) ? kVp9SupportYes : kVp9SupportNo;
+  }
+  return s_vp9_support == kVp9SupportYes;
+}
+#else  // SB_HAS(MEDIA_WEBM_VP9_SUPPORT)
+bool IsVp9Supported() {
+  return false;
+}
+#endif
+
+}  // namespace
 
 SB_EXPORT bool SbMediaIsVideoSupported(SbMediaVideoCodec video_codec,
                                        int frame_width,
                                        int frame_height,
                                        int64_t bitrate,
                                        int fps) {
-  bool supported = VideoSupported::GetSingleton()->IsVideoSupported(
-      video_codec, frame_width, frame_height, bitrate, fps);
-  return supported;
+  // Only certain codecs support 4K resolution.
+  const bool supports_4k = video_codec == kSbMediaVideoCodecVp9;
+  const int max_width = supports_4k ? 3840 : 1920;
+  const int max_height = supports_4k ? 2160 : 1080;
+  if (frame_width > max_width || frame_height > max_height) {
+    return false;
+  }
+
+  // Is bitrate in range?
+  if (bitrate > SB_MEDIA_MAX_VIDEO_BITRATE_IN_BITS_PER_SECOND) {
+    return false;
+  }
+  if (fps > 60) {
+    return false;
+  }
+  if (video_codec == kSbMediaVideoCodecH264) {
+    return true;
+  }
+  if (video_codec == kSbMediaVideoCodecVp9) {
+    return IsVp9Supported();
+  }
+  return false;
 }
diff --git a/src/starboard/shared/win32/media_transform.cc b/src/starboard/shared/win32/media_transform.cc
index b216918..72b7ace 100644
--- a/src/starboard/shared/win32/media_transform.cc
+++ b/src/starboard/shared/win32/media_transform.cc
@@ -20,7 +20,6 @@
 #include "starboard/shared/win32/error_utils.h"
 #include "starboard/shared/win32/media_common.h"
 #include "starboard/shared/win32/media_foundation_utils.h"
-#include "starboard/shared/win32/video_transform.h"
 
 namespace starboard {
 namespace shared {
@@ -46,9 +45,7 @@
       state_(kCanAcceptInput),
       stream_begun_(false),
       discontinuity_(true) {
-  LPVOID* ptr_address = reinterpret_cast<LPVOID*>(transform_.GetAddressOf());
-  HRESULT hr = CoCreateInstance(clsid, NULL, CLSCTX_INPROC_SERVER,
-                                IID_IMFTransform, ptr_address);
+  HRESULT hr = CreateDecoderTransform(clsid, &transform_);
   CheckResult(hr);
 }
 
@@ -81,6 +78,9 @@
     return true;
   }
   if (hr == MF_E_NOTACCEPTING) {
+    // NOTE: Some transforms may never return MF_E_NOTACCEPTING, so TryRead
+    // should be allowed to try retrieving an output sample while |state_| is
+    // kCanAcceptInput.
     state_ = kCanProvideOutput;
     return false;
   }
@@ -92,7 +92,7 @@
   SB_DCHECK(thread_checker_.CalledOnValidThread());
   SB_DCHECK(new_type);
 
-  if (state_ != kCanProvideOutput && state_ != kDraining) {
+  if (state_ == kDrained) {
     return NULL;
   }
 
@@ -276,11 +276,12 @@
 }
 
 void MediaTransform::Reset() {
-  SendMessage(MFT_MESSAGE_COMMAND_FLUSH);
-  thread_checker_.Detach();
+  if (stream_begun_) {
+    SendMessage(MFT_MESSAGE_COMMAND_FLUSH);
+  }
   state_ = kCanAcceptInput;
-  stream_begun_ = false;
   discontinuity_ = true;
+  thread_checker_.Detach();
 }
 
 void MediaTransform::PrepareOutputDataBuffer(
diff --git a/src/starboard/shared/win32/player_components_impl.cc b/src/starboard/shared/win32/player_components_impl.cc
index c57bc8e..56e9be7 100644
--- a/src/starboard/shared/win32/player_components_impl.cc
+++ b/src/starboard/shared/win32/player_components_impl.cc
@@ -19,7 +19,6 @@
 #include "starboard/shared/starboard/player/filter/video_renderer_impl_internal.h"
 #include "starboard/shared/win32/audio_decoder.h"
 #include "starboard/shared/win32/video_decoder.h"
-#include "starboard/shared/win32/video_renderer.h"
 
 namespace starboard {
 namespace shared {
@@ -33,7 +32,6 @@
     const VideoParameters& video_parameters) {
   using AudioDecoderImpl = ::starboard::shared::win32::AudioDecoder;
   using VideoDecoderImpl = ::starboard::shared::win32::VideoDecoder;
-  using VideoRendererImpl = ::starboard::shared::win32::VideoRendererImpl;
 
   AudioDecoderImpl* audio_decoder = new AudioDecoderImpl(
       audio_parameters.audio_codec, audio_parameters.audio_header,
diff --git a/src/starboard/shared/win32/system_get_stack.cc b/src/starboard/shared/win32/system_get_stack.cc
new file mode 100644
index 0000000..dc1f918
--- /dev/null
+++ b/src/starboard/shared/win32/system_get_stack.cc
@@ -0,0 +1,24 @@
+// Copyright 2016 Google Inc. All Rights Reserved.
+//
+// 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.
+
+#include "starboard/system.h"
+
+#include <Windows.h>

+
+__declspec(noinline) int SbSystemGetStack(void** out_stack, int stack_size) {
+  ULONG frames_to_skip = 1;

+  int num_captured = CaptureStackBackTrace(frames_to_skip, stack_size,
+                                           out_stack, nullptr);
+  return num_captured;
+}
diff --git a/src/starboard/shared/win32/video_decoder.cc b/src/starboard/shared/win32/video_decoder.cc
index e13877d..6245704 100644
--- a/src/starboard/shared/win32/video_decoder.cc
+++ b/src/starboard/shared/win32/video_decoder.cc
@@ -14,84 +14,479 @@
 
 #include "starboard/shared/win32/video_decoder.h"
 
-#include "starboard/decode_target.h"
 #include "starboard/log.h"
 #include "starboard/shared/win32/decode_target_internal.h"
+#include "starboard/shared/win32/dx_context_video_decoder.h"
 #include "starboard/shared/win32/error_utils.h"
-#include "starboard/shared/win32/media_common.h"
 
 namespace starboard {
 namespace shared {
 namespace win32 {
 
-VideoDecoder::VideoDecoder(SbMediaVideoCodec video_codec,
-                           SbPlayerOutputMode output_mode,
-                           SbDecodeTargetGraphicsContextProvider*
-                               decode_target_graphics_context_provider,
-                           SbDrmSystem drm_system)
+namespace {
+
+using Microsoft::WRL::ComPtr;
+
+// Limit the number of active output samples to control memory usage.
+// NOTE: Higher numbers may result in increased dropped frames when the video
+// resolution changes during playback.
+const int kMaxOutputSamples = 5;
+
+// This structure is used to facilitate creation of decode targets in the
+// appropriate graphics context.
+struct CreateDecodeTargetContext {
+  VideoDecoder* video_decoder;
+  SbDecodeTarget out_decode_target;
+};
+
+scoped_ptr<MediaTransform> CreateVideoTransform(const GUID& decoder_guid,
+    const GUID& input_guid, const GUID& output_guid,
+    const SbWindowSize& window_size,
+    const IMFDXGIDeviceManager* device_manager) {
+  scoped_ptr<MediaTransform> transform(new MediaTransform(decoder_guid));
+
+  transform->SendMessage(MFT_MESSAGE_SET_D3D_MANAGER,
+                         ULONG_PTR(device_manager));
+
+  ComPtr<IMFMediaType> input_type;
+  CheckResult(MFCreateMediaType(&input_type));
+  CheckResult(input_type->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Video));
+  CheckResult(input_type->SetGUID(MF_MT_SUBTYPE, input_guid));
+  CheckResult(input_type->SetUINT32(MF_MT_INTERLACE_MODE,
+                                    MFVideoInterlace_Progressive));
+  if (input_guid == MFVideoFormat_VP90) {
+    // Set the expected video resolution. Setting the proper resolution can
+    // mitigate a format change, but the decoder will adjust to the real
+    // resolution regardless.
+    CheckResult(MFSetAttributeSize(input_type.Get(), MF_MT_FRAME_SIZE,
+                                   window_size.width, window_size.height));
+  }
+  transform->SetInputType(input_type);
+
+  transform->SetOutputTypeBySubType(output_guid);
+
+  return transform.Pass();
+}
+
+}  // namespace
+
+VideoDecoder::VideoDecoder(
+    SbMediaVideoCodec video_codec,
+    SbPlayerOutputMode output_mode,
+    SbDecodeTargetGraphicsContextProvider* graphics_context_provider,
+    SbDrmSystem drm_system)
     : video_codec_(video_codec),
+      graphics_context_provider_(graphics_context_provider),
       drm_system_(drm_system),
-      host_(NULL),
-      output_mode_(output_mode),
-      decode_target_graphics_context_provider_(
-          decode_target_graphics_context_provider) {
-  impl_ = AbstractWin32VideoDecoder::Create(video_codec_, drm_system_);
-  video_decoder_thread_.reset(new VideoDecoderThread(impl_.get(), this));
+      host_(nullptr),
+      decoder_thread_(kSbThreadInvalid),
+      decoder_thread_stop_requested_(false),
+      decoder_thread_stopped_(false),
+      current_decode_target_(kSbDecodeTargetInvalid),
+      prev_decode_target_(kSbDecodeTargetInvalid) {
+  SB_DCHECK(output_mode == kSbPlayerOutputModeDecodeToTexture);
+
+  HardwareDecoderContext hardware_context = GetDirectXForHardwareDecoding();
+  d3d_device_ = hardware_context.dx_device_out;
+  device_manager_ = hardware_context.dxgi_device_manager_out;
+  CheckResult(d3d_device_.As(&video_device_));
+
+  ComPtr<ID3D11DeviceContext> d3d_context;
+  d3d_device_->GetImmediateContext(d3d_context.GetAddressOf());
+  CheckResult(d3d_context.As(&video_context_));
+
+  InitializeCodec();
 }
 
 VideoDecoder::~VideoDecoder() {
   SB_DCHECK(thread_checker_.CalledOnValidThread());
+  Reset();
+  ShutdownCodec();
 
-  video_decoder_thread_.reset(nullptr);
-  impl_.reset(nullptr);
+  ScopedLock lock(decode_target_lock_);
+  SbDecodeTargetRelease(current_decode_target_);
+  SbDecodeTargetRelease(prev_decode_target_);
 }
 
 void VideoDecoder::SetHost(Host* host) {
   SB_DCHECK(thread_checker_.CalledOnValidThread());
-  SB_DCHECK(host != NULL);
-  SB_DCHECK(host_ == NULL);
+  SB_DCHECK(host != nullptr);
+  SB_DCHECK(host_ == nullptr);
   host_ = host;
 }
 
+void VideoDecoder::Initialize(const Closure& error_cb) {
+  SB_DCHECK(thread_checker_.CalledOnValidThread());
+  SB_DCHECK(!error_cb_.is_valid());
+  SB_DCHECK(error_cb.is_valid());
+  error_cb_ = error_cb;
+}
+
 void VideoDecoder::WriteInputBuffer(
     const scoped_refptr<InputBuffer>& input_buffer) {
   SB_DCHECK(thread_checker_.CalledOnValidThread());
   SB_DCHECK(input_buffer);
-  SB_DCHECK(host_);
-  const bool can_accept_more_input =
-      video_decoder_thread_->QueueInput(input_buffer);
+  SB_DCHECK(host_ != nullptr);
+  EnsureDecoderThreadRunning();
 
-  if (can_accept_more_input) {
-    host_->OnDecoderStatusUpdate(kNeedMoreInput, NULL);
-  }
+  ScopedLock lock(thread_lock_);
+  thread_events_.emplace_back(
+      new Event{ Event::kWriteInputBuffer, input_buffer });
 }
 
 void VideoDecoder::WriteEndOfStream() {
   SB_DCHECK(thread_checker_.CalledOnValidThread());
-  SB_DCHECK(host_);
-  scoped_refptr<InputBuffer> empty;
-  video_decoder_thread_->QueueInput(empty);
+  SB_DCHECK(host_ != nullptr);
+  EnsureDecoderThreadRunning();
+
+  ScopedLock lock(thread_lock_);
+  thread_events_.emplace_back(new Event{ Event::kWriteEndOfStream });
 }
 
 void VideoDecoder::Reset() {
   SB_DCHECK(thread_checker_.CalledOnValidThread());
-  SB_DCHECK(host_);
-  video_decoder_thread_.reset(nullptr);
-  impl_->Reset();
-  decoded_data_.Clear();
-  video_decoder_thread_.reset(new VideoDecoderThread(impl_.get(), this));
+  StopDecoderThread();
+
+  // Make sure all output samples have been released before flushing the
+  // decoder. Be sure to Acquire the mutexes in the same order as
+  // CreateDecodeTarget to avoid possible deadlock.
+  outputs_reset_lock_.Acquire();
+  thread_lock_.Acquire();
+  thread_outputs_.clear();
+  thread_lock_.Release();
+  outputs_reset_lock_.Release();
+
+  decoder_->Reset();
 }
 
-// When in decode-to-texture mode, this returns the current decoded video frame.
 SbDecodeTarget VideoDecoder::GetCurrentDecodeTarget() {
-  SB_NOTIMPLEMENTED()
-      << "VideoRendererImpl::GetCurrentDecodeTarget() should be used instead.";
-  return kSbDecodeTargetInvalid;
+  // Ensure the decode target is created on the render thread.
+  CreateDecodeTargetContext decode_target_context = { this };
+  graphics_context_provider_->gles_context_runner(graphics_context_provider_,
+      &VideoDecoder::CreateDecodeTargetHelper, &decode_target_context);
+
+  ScopedLock lock(decode_target_lock_);
+  if (SbDecodeTargetIsValid(decode_target_context.out_decode_target)) {
+    SbDecodeTargetRelease(prev_decode_target_);
+    prev_decode_target_ = current_decode_target_;
+    current_decode_target_ = decode_target_context.out_decode_target;
+  }
+  if (SbDecodeTargetIsValid(current_decode_target_)) {
+    // Add a reference for the caller.
+    current_decode_target_->AddRef();
+  }
+  return current_decode_target_;
 }
 
-void VideoDecoder::OnVideoDecoded(VideoFramePtr data) {
-  Status sts = (data && data->IsEndOfStream()) ? kBufferFull : kNeedMoreInput;
-  host_->OnDecoderStatusUpdate(sts, data);
+// static
+void VideoDecoder::CreateDecodeTargetHelper(void* context) {
+  CreateDecodeTargetContext* target_context =
+      static_cast<CreateDecodeTargetContext*>(context);
+  target_context->out_decode_target =
+      target_context->video_decoder->CreateDecodeTarget();
+}
+
+SbDecodeTarget VideoDecoder::CreateDecodeTarget() {
+  RECT video_area;
+  ComPtr<IMFSample> video_sample;
+
+  // Don't allow a decoder reset (flush) while an IMFSample is
+  // alive. However, the decoder thread should be allowed to continue
+  // while the SbDecodeTarget is being created.
+  ScopedLock reset_lock(outputs_reset_lock_);
+
+  // Use the oldest output.
+  thread_lock_.Acquire();
+  if (!thread_outputs_.empty()) {
+    // This function should not remove output frames. However, it's possible
+    // for the same frame to be requested multiple times. To avoid re-creating
+    // SbDecodeTargets, release the video_sample once it is used to create
+    // an output frame. The next call to CreateDecodeTarget for the same frame
+    // will return kSbDecodeTargetInvalid, and |current_decode_target_| will
+    // be reused.
+    Output& output = thread_outputs_.front();
+    video_area = output.video_area;
+    video_sample.Swap(output.video_sample);
+  }
+  thread_lock_.Release();
+
+  SbDecodeTarget decode_target = kSbDecodeTargetInvalid;
+  if (video_sample != nullptr) {
+    ScopedLock target_lock(decode_target_lock_);
+
+    // Try reusing the previous decode target to avoid the performance hit of
+    // creating a new texture.
+    if (SbDecodeTargetIsValid(prev_decode_target_) &&
+        prev_decode_target_->Update(d3d_device_, video_device_,
+            video_context_, video_enumerator_, video_processor_,
+            video_sample, video_area)) {
+      decode_target = prev_decode_target_;
+      prev_decode_target_ = kSbDecodeTargetInvalid;
+    } else {
+      decode_target = new SbDecodeTargetPrivate(d3d_device_, video_device_,
+          video_context_, video_enumerator_, video_processor_,
+          video_sample, video_area);
+    }
+
+    // Release the video_sample before releasing the reset lock.
+    video_sample.Reset();
+  }
+  return decode_target;
+}
+
+void VideoDecoder::InitializeCodec() {
+  scoped_ptr<MediaTransform> media_transform;
+  SbWindowOptions window_options;
+  SbWindowSetDefaultOptions(&window_options);
+
+  // If this is updated then media_is_video_supported.cc also needs to be
+  // updated.
+  switch (video_codec_) {
+    case kSbMediaVideoCodecH264: {
+      media_transform = CreateVideoTransform(
+          CLSID_MSH264DecoderMFT, MFVideoFormat_H264, MFVideoFormat_NV12,
+          window_options.size, device_manager_.Get());
+      break;
+    }
+    case kSbMediaVideoCodecVp9: {
+      media_transform = CreateVideoTransform(
+          CLSID_MSVPxDecoder, MFVideoFormat_VP90, MFVideoFormat_NV12,
+          window_options.size, device_manager_.Get());
+      break;
+    }
+    default: { SB_NOTREACHED(); }
+  }
+
+  decoder_.reset(
+      new DecryptingDecoder("video", media_transform.Pass(), drm_system_));
+  MediaTransform* transform = decoder_->GetDecoder();
+
+  DWORD input_stream_count = 0;
+  DWORD output_stream_count = 0;
+  transform->GetStreamCount(&input_stream_count, &output_stream_count);
+  SB_DCHECK(1 == input_stream_count);
+  SB_DCHECK(1 == output_stream_count);
+
+  ComPtr<IMFAttributes> attributes = transform->GetAttributes();
+  CheckResult(attributes->SetUINT32(MF_SA_MINIMUM_OUTPUT_SAMPLE_COUNT,
+      kMaxOutputSamples));
+
+  UpdateVideoArea(transform->GetCurrentOutputType());
+
+  // The transform must output textures that are bound to shader resources,
+  // or we can't draw them later via ANGLE.
+  ComPtr<IMFAttributes> output_attributes =
+      transform->GetOutputStreamAttributes();
+  CheckResult(output_attributes->SetUINT32(MF_SA_D3D11_BINDFLAGS,
+      D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_DECODER));
+
+  // The resolution and framerate will adjust to the actual content data.
+  D3D11_VIDEO_PROCESSOR_CONTENT_DESC content_desc = {};
+  content_desc.InputFrameFormat = D3D11_VIDEO_FRAME_FORMAT_PROGRESSIVE;
+  content_desc.InputFrameRate.Numerator = 60;
+  content_desc.InputFrameRate.Denominator = 1;
+  content_desc.InputWidth = window_options.size.width;
+  content_desc.InputHeight = window_options.size.height;
+  content_desc.OutputFrameRate.Numerator = 60;
+  content_desc.OutputFrameRate.Denominator = 1;
+  content_desc.OutputWidth = window_options.size.width;
+  content_desc.OutputHeight = window_options.size.height;
+  content_desc.Usage = D3D11_VIDEO_USAGE_PLAYBACK_NORMAL;
+  CheckResult(video_device_->CreateVideoProcessorEnumerator(
+      &content_desc, video_enumerator_.GetAddressOf()));
+  CheckResult(video_device_->CreateVideoProcessor(
+      video_enumerator_.Get(), 0, video_processor_.GetAddressOf()));
+  video_context_->VideoProcessorSetStreamFrameFormat(
+      video_processor_.Get(), MediaTransform::kStreamId,
+      D3D11_VIDEO_FRAME_FORMAT_PROGRESSIVE);
+  video_context_->VideoProcessorSetStreamAutoProcessingMode(
+      video_processor_.Get(), 0, false);
+}
+
+void VideoDecoder::ShutdownCodec() {
+  SB_DCHECK(!SbThreadIsValid(decoder_thread_));
+  decoder_.reset();
+  video_processor_.Reset();
+  video_enumerator_.Reset();
+}
+
+void VideoDecoder::EnsureDecoderThreadRunning() {
+  SB_DCHECK(thread_checker_.CalledOnValidThread());
+
+  // NOTE: The video decoder thread will exit after processing the
+  // kWriteEndOfStream event. In this case, Reset must be called (which will
+  // then StopDecoderThread) before WriteInputBuffer or WriteEndOfStream again.
+  SB_DCHECK(!decoder_thread_stopped_);
+
+  if (!SbThreadIsValid(decoder_thread_)) {
+    SB_DCHECK(decoder_ != nullptr);
+    SB_DCHECK(thread_events_.empty());
+    decoder_thread_stop_requested_ = false;
+    decoder_thread_ =
+        SbThreadCreate(0, kSbThreadPriorityHigh, kSbThreadNoAffinity, true,
+                       "VideoDecoder", &VideoDecoder::DecoderThreadEntry, this);
+    SB_DCHECK(SbThreadIsValid(decoder_thread_));
+  }
+}
+
+void VideoDecoder::StopDecoderThread() {
+  SB_DCHECK(thread_checker_.CalledOnValidThread());
+  if (SbThreadIsValid(decoder_thread_)) {
+    decoder_thread_stop_requested_ = true;
+    SbThreadJoin(decoder_thread_, nullptr);
+    SB_DCHECK(decoder_thread_stopped_);
+    decoder_thread_stopped_ = false;
+    decoder_thread_ = kSbThreadInvalid;
+  }
+  thread_events_.clear();
+}
+
+void VideoDecoder::UpdateVideoArea(const ComPtr<IMFMediaType>& media) {
+  MFVideoArea video_area;
+  HRESULT hr = media->GetBlob(MF_MT_MINIMUM_DISPLAY_APERTURE,
+                              reinterpret_cast<UINT8*>(&video_area),
+                              sizeof(video_area), nullptr);
+  if (SUCCEEDED(hr)) {
+    video_area_.left = video_area.OffsetX.value;
+    video_area_.top = video_area.OffsetY.value;
+    video_area_.right = video_area_.left + video_area.Area.cx;
+    video_area_.bottom = video_area_.top + video_area.Area.cy;
+    return;
+  }
+
+  UINT32 width;
+  UINT32 height;
+  hr = MFGetAttributeSize(media.Get(), MF_MT_FRAME_SIZE, &width, &height);
+  if (SUCCEEDED(hr)) {
+    video_area_.left = 0;
+    video_area_.top = 0;
+    video_area_.right = width;
+    video_area_.bottom = height;
+    return;
+  }
+
+  SB_NOTREACHED() << "Could not determine new video output resolution";
+}
+
+scoped_refptr<VideoFrame> VideoDecoder::CreateVideoFrame(
+    const ComPtr<IMFSample>& sample) {
+  // NOTE: All samples must be released before flushing the decoder. Since
+  // the host may hang onto VideoFrames that are created here, make them
+  // weak references to the actual sample.
+  LONGLONG win32_sample_time = 0;
+  CheckResult(sample->GetSampleTime(&win32_sample_time));
+  SbMediaTime sample_time = ConvertToMediaTime(win32_sample_time);
+
+  thread_lock_.Acquire();
+  thread_outputs_.emplace_back(sample_time, video_area_, sample);
+  thread_lock_.Release();
+
+  // The "native texture" for the VideoFrame is actually just the timestamp
+  // for the output sample.
+  return make_scoped_refptr(new VideoFrame(
+      video_area_.right, video_area_.bottom, sample_time,
+      new SbMediaTime(sample_time), this, &VideoDecoder::DeleteVideoFrame));
+}
+
+// static
+void VideoDecoder::DeleteVideoFrame(void* context, void* native_texture) {
+  VideoDecoder* this_ptr = static_cast<VideoDecoder*>(context);
+  SbMediaTime* time_ptr = static_cast<SbMediaTime*>(native_texture);
+  SbMediaTime time = *time_ptr;
+  delete time_ptr;
+
+  ScopedLock lock(this_ptr->thread_lock_);
+  for (auto iter = this_ptr->thread_outputs_.begin();
+       iter != this_ptr->thread_outputs_.end(); ++iter) {
+    if (iter->time == time) {
+      this_ptr->thread_outputs_.erase(iter);
+      break;
+    }
+  }
+}
+
+void VideoDecoder::DecoderThreadRun() {
+  std::unique_ptr<Event> event;
+  bool is_end_of_stream = false;
+
+  while (!decoder_thread_stop_requested_) {
+    int outputs_to_process = 1;
+
+    // Process a new event or re-try the previous event.
+    if (event == nullptr) {
+      ScopedLock lock(thread_lock_);
+      if (!thread_events_.empty()) {
+        event.swap(thread_events_.front());
+        thread_events_.pop_front();
+      }
+    }
+
+    if (event == nullptr) {
+      SbThreadSleep(kSbTimeMillisecond);
+    } else {
+      switch (event->type) {
+        case Event::kWriteInputBuffer:
+          SB_DCHECK(event->input_buffer != nullptr);
+          if (decoder_->TryWriteInputBuffer(event->input_buffer, 0)) {
+            // The event was successfully processed. Discard it.
+            event.reset();
+          } else {
+            // The decoder must be full. Re-try the event on the next
+            // iteration. Additionally, try reading an extra output frame to
+            // start draining the decoder.
+            ++outputs_to_process;
+          }
+          break;
+        case Event::kWriteEndOfStream:
+          event.reset();
+          decoder_->Drain();
+          is_end_of_stream = true;
+          break;
+      }
+    }
+
+    // Process output frame(s).
+    for (int outputs = 0; outputs < outputs_to_process; ++outputs) {
+      // NOTE: IMFTransform::ProcessOutput (called by decoder_->ProcessAndRead)
+      // may stall if the number of active IMFSamples would exceed the value of
+      // MF_SA_MINIMUM_OUTPUT_SAMPLE_COUNT.
+      thread_lock_.Acquire();
+      size_t output_count = thread_outputs_.size();
+      thread_lock_.Release();
+      if (output_count >= kMaxOutputSamples) {
+        // Wait for the active samples to be consumed.
+        host_->OnDecoderStatusUpdate(kBufferFull, nullptr);
+        SbThreadSleep(kSbTimeMillisecond);
+        continue;
+      }
+
+      ComPtr<IMFSample> sample;
+      ComPtr<IMFMediaType> media_type;
+      decoder_->ProcessAndRead(&sample, &media_type);
+      if (media_type) {
+        UpdateVideoArea(media_type);
+      }
+      if (sample) {
+        host_->OnDecoderStatusUpdate(kNeedMoreInput,
+                                     CreateVideoFrame(sample));
+      } else if (is_end_of_stream) {
+        host_->OnDecoderStatusUpdate(kBufferFull,
+                                     VideoFrame::CreateEOSFrame());
+        return;
+      } else {
+        host_->OnDecoderStatusUpdate(kNeedMoreInput, nullptr);
+      }
+    }
+  }
+}
+
+// static
+void* VideoDecoder::DecoderThreadEntry(void* context) {
+  SB_DCHECK(context);
+  VideoDecoder* decoder = static_cast<VideoDecoder*>(context);
+  decoder->DecoderThreadRun();
+  decoder->decoder_thread_stopped_ = true;
+  return nullptr;
 }
 
 }  // namespace win32
diff --git a/src/starboard/shared/win32/video_decoder.h b/src/starboard/shared/win32/video_decoder.h
index f973211..8d0abe5 100644
--- a/src/starboard/shared/win32/video_decoder.h
+++ b/src/starboard/shared/win32/video_decoder.h
@@ -15,65 +15,126 @@
 #ifndef STARBOARD_SHARED_WIN32_VIDEO_DECODER_H_
 #define STARBOARD_SHARED_WIN32_VIDEO_DECODER_H_
 
+#include <D3d11_1.h>
+#include <wrl/client.h>
+
+#include <deque>
+#include <list>
+#include <memory>
+
 #include "starboard/common/ref_counted.h"
 #include "starboard/common/scoped_ptr.h"
 #include "starboard/configuration.h"
-#include "starboard/drm.h"
-#include "starboard/shared/starboard/player/filter/player_components.h"
+#include "starboard/decode_target.h"
+#include "starboard/mutex.h"
 #include "starboard/shared/starboard/player/filter/video_decoder_internal.h"
-#include "starboard/shared/starboard/player/input_buffer_internal.h"
-#include "starboard/shared/starboard/player/job_queue.h"
-#include "starboard/shared/starboard/player/video_frame_internal.h"
 #include "starboard/shared/starboard/thread_checker.h"
-#include "starboard/shared/win32/atomic_queue.h"
-#include "starboard/shared/win32/media_common.h"
-#include "starboard/shared/win32/video_decoder_thread.h"
+#include "starboard/shared/win32/decrypting_decoder.h"
+#include "starboard/thread.h"
 
 namespace starboard {
 namespace shared {
 namespace win32 {
 
 class VideoDecoder
-    : public ::starboard::shared::starboard::player::filter::HostedVideoDecoder,
-      private ::starboard::shared::starboard::player::JobQueue::JobOwner,
-      private VideoDecodedCallback {
+    : public
+        ::starboard::shared::starboard::player::filter::HostedVideoDecoder {
  public:
+  typedef ::starboard::shared::starboard::player::InputBuffer InputBuffer;
+  typedef ::starboard::shared::starboard::player::VideoFrame VideoFrame;
+
   VideoDecoder(SbMediaVideoCodec video_codec,
                SbPlayerOutputMode output_mode,
-               SbDecodeTargetGraphicsContextProvider*
-                   decode_target_graphics_context_provider,
+               SbDecodeTargetGraphicsContextProvider* graphics_context_provider,
                SbDrmSystem drm_system);
   ~VideoDecoder() SB_OVERRIDE;
 
+  // Implement HostedVideoDecoder interface.
   void SetHost(Host* host) SB_OVERRIDE;
+  void Initialize(const Closure& error_cb) SB_OVERRIDE;
   void WriteInputBuffer(const scoped_refptr<InputBuffer>& input_buffer)
       SB_OVERRIDE;
   void WriteEndOfStream() SB_OVERRIDE;
   void Reset() SB_OVERRIDE;
-
   SbDecodeTarget GetCurrentDecodeTarget() SB_OVERRIDE;
 
-  // Implements class VideoDecodedCallback.
-  void OnVideoDecoded(VideoFramePtr data) SB_OVERRIDE;
-
  private:
+  template <typename T>
+  using ComPtr = Microsoft::WRL::ComPtr<T>;
+
+  struct Event {
+    enum Type {
+      kWriteInputBuffer,
+      kWriteEndOfStream,
+    };
+    Type type;
+    scoped_refptr<InputBuffer> input_buffer;
+  };
+
+  struct Output {
+    Output(SbMediaTime time, const RECT& video_area,
+           const ComPtr<IMFSample>& video_sample)
+        : time(time), video_area(video_area), video_sample(video_sample) {}
+    SbMediaTime time;
+    RECT video_area;
+    ComPtr<IMFSample> video_sample;
+  };
+
+  void InitializeCodec();
+  void ShutdownCodec();
+
+  void UpdateVideoArea(const ComPtr<IMFMediaType>& media);
+  scoped_refptr<VideoFrame> CreateVideoFrame(const ComPtr<IMFSample>& sample);
+  static void DeleteVideoFrame(void* context, void* native_texture);
+  static void CreateDecodeTargetHelper(void* context);
+  SbDecodeTarget CreateDecodeTarget();
+
+  void EnsureDecoderThreadRunning();
+  void StopDecoderThread();
+  void DecoderThreadRun();
+  static void* DecoderThreadEntry(void* context);
+
   ::starboard::shared::starboard::ThreadChecker thread_checker_;
 
   // These variables will be initialized inside ctor or SetHost() and will not
   // be changed during the life time of this class.
   const SbMediaVideoCodec video_codec_;
-  SbDrmSystem const drm_system_;
+  Closure error_cb_;
   Host* host_;
+  SbDecodeTargetGraphicsContextProvider* graphics_context_provider_;
+  SbDrmSystem const drm_system_;
 
-  // Decode-to-texture related state.
-  const SbPlayerOutputMode output_mode_;
-  SbDecodeTargetGraphicsContextProvider* const
-      decode_target_graphics_context_provider_;
+  // These are platform-specific objects required to create and use a codec.
+  ComPtr<ID3D11Device> d3d_device_;
+  ComPtr<IMFDXGIDeviceManager> device_manager_;
+  ComPtr<ID3D11VideoDevice1> video_device_;
+  ComPtr<ID3D11VideoContext> video_context_;
+  ComPtr<ID3D11VideoProcessorEnumerator> video_enumerator_;
+  ComPtr<ID3D11VideoProcessor> video_processor_;
 
-  scoped_ptr<AbstractWin32VideoDecoder> impl_;
-  AtomicQueue<VideoFramePtr> decoded_data_;
-  Mutex mutex_;
-  scoped_ptr<VideoDecoderThread> video_decoder_thread_;
+  scoped_ptr<DecryptingDecoder> decoder_;
+  RECT video_area_;
+
+  SbThread decoder_thread_;
+  volatile bool decoder_thread_stop_requested_;
+  bool decoder_thread_stopped_;
+  Mutex thread_lock_;
+  std::deque<std::unique_ptr<Event> > thread_events_;
+
+  // This structure shadows the list of outstanding frames held by the host.
+  // When a new output is added to this structure, the host should be notified
+  // of a new VideoFrame. When the host deletes the VideoFrame, the delete
+  // callback is used to update this structure. The VideoDecoder may need to
+  // delete outputs without notifying the host. In such a situation, the host's
+  // VideoFrames will be invalid if they still require the IMFSample; it's
+  // possible that the VideoFrame was converted to a texture already, so it
+  // will continue to be valid since the IMFSample is no longer needed.
+  Mutex outputs_reset_lock_;
+  std::list<Output> thread_outputs_;
+
+  Mutex decode_target_lock_;
+  SbDecodeTarget current_decode_target_;
+  SbDecodeTarget prev_decode_target_;
 };
 
 }  // namespace win32
diff --git a/src/starboard/shared/win32/video_decoder_thread.cc b/src/starboard/shared/win32/video_decoder_thread.cc
deleted file mode 100644
index fca08be..0000000
--- a/src/starboard/shared/win32/video_decoder_thread.cc
+++ /dev/null
@@ -1,135 +0,0 @@
-// Copyright 2017 Google Inc. All Rights Reserved.
-//
-// 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.
-
-#include "starboard/shared/win32/video_decoder_thread.h"
-
-#include <deque>
-
-namespace starboard {
-namespace shared {
-namespace win32 {
-
-namespace {
-const size_t kMaxSize = 16;
-
-size_t WriteAsMuchAsPossible(
-    std::deque<scoped_refptr<InputBuffer> >* data_queue,
-    AbstractWin32VideoDecoder* video_decoder,
-    bool* is_end_of_stream_reached) {
-  const size_t original_size = data_queue->size();
-  while (!data_queue->empty()) {
-    scoped_refptr<InputBuffer> buff = data_queue->front();
-    data_queue->pop_front();
-
-    if (buff) {
-      const bool write_ok = video_decoder->TryWrite(buff);
-
-      if (!write_ok) {
-        data_queue->push_front(buff);
-        break;
-      }
-    } else {
-      video_decoder->WriteEndOfStream();
-      *is_end_of_stream_reached = true;
-    }
-  }
-  return original_size - data_queue->size();
-}
-
-}  // namespace.
-
-VideoDecoderThread::VideoDecoderThread(AbstractWin32VideoDecoder* decoder_impl,
-                                       VideoDecodedCallback* callback)
-    : SimpleThread("VideoDecoderThread"),
-      win32_video_decoder_(decoder_impl),
-      callback_(callback) {
-  Start();
-}
-
-VideoDecoderThread::~VideoDecoderThread() {
-  Join();
-  SB_DCHECK(join_called());
-}
-
-bool VideoDecoderThread::QueueInput(const scoped_refptr<InputBuffer>& buffer) {
-  {
-    ::starboard::ScopedLock lock(input_buffer_queue_mutex_);
-    input_buffer_queue_.push_back(buffer);
-  }
-
-  // increment() returns the prev value.
-  size_t proc_size = processing_elements_.increment() + 1;
-  semaphore_.Put();
-  return proc_size < kMaxSize;
-}
-
-void VideoDecoderThread::QueueEndOfStream() {
-  scoped_refptr<InputBuffer> empty;
-  QueueInput(empty);
-}
-
-void VideoDecoderThread::TransferPendingInputTo(
-    std::deque<scoped_refptr<InputBuffer> >* output) {
-  // Transfer input buffer to local thread.
-  ::starboard::ScopedLock lock(input_buffer_queue_mutex_);
-  while (!input_buffer_queue_.empty()) {
-    output->push_back(input_buffer_queue_.front());
-    input_buffer_queue_.pop_front();
-  }
-}
-
-void VideoDecoderThread::Run() {
-  std::deque<scoped_refptr<InputBuffer> > local_queue;
-  while (!join_called()) {
-    if (local_queue.empty()) {
-      TransferPendingInputTo(&local_queue);
-    }
-    bool work_done = false;
-    bool is_end_of_stream = false;
-    const size_t number_written =
-        WriteAsMuchAsPossible(&local_queue, win32_video_decoder_,
-                              &is_end_of_stream);
-    if (number_written > 0) {
-      processing_elements_.fetch_sub(static_cast<int32_t>(number_written));
-      work_done = true;
-      callback_->OnVideoDecoded(NULL);
-    }
-
-    bool too_many_outstanding_frames;
-    while (VideoFramePtr decoded_datum = win32_video_decoder_->ProcessAndRead(
-               &too_many_outstanding_frames)) {
-      if (decoded_datum.get()) {
-        callback_->OnVideoDecoded(decoded_datum);
-      }
-      work_done = true;
-    }
-
-    if (is_end_of_stream) {
-      callback_->OnVideoDecoded(VideoFrame::CreateEOSFrame());
-      work_done = true;
-    }
-
-    if (too_many_outstanding_frames) {
-      SbThreadSleep(10 * kSbTimeMillisecond);
-    }
-
-    if (!work_done) {
-      semaphore_.TakeWait(kSbTimeMillisecond);
-    }
-  }
-}
-
-}  // namespace win32
-}  // namespace shared
-}  // namespace starboard
diff --git a/src/starboard/shared/win32/video_decoder_thread.h b/src/starboard/shared/win32/video_decoder_thread.h
deleted file mode 100644
index a53ce5e..0000000
--- a/src/starboard/shared/win32/video_decoder_thread.h
+++ /dev/null
@@ -1,72 +0,0 @@
-// Copyright 2017 Google Inc. All Rights Reserved.
-//
-// 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.
-
-#ifndef STARBOARD_SHARED_WIN32_VIDEO_DECODER_THREAD_H_
-#define STARBOARD_SHARED_WIN32_VIDEO_DECODER_THREAD_H_
-
-#include <deque>
-#include <queue>
-
-#include "starboard/common/ref_counted.h"
-#include "starboard/common/semaphore.h"
-#include "starboard/media.h"
-#include "starboard/shared/internal_only.h"
-#include "starboard/shared/starboard/player/decoded_audio_internal.h"
-#include "starboard/shared/starboard/player/filter/audio_decoder_internal.h"
-#include "starboard/shared/starboard/player/filter/video_decoder_internal.h"
-#include "starboard/shared/starboard/player/job_queue.h"
-#include "starboard/shared/win32/media_common.h"
-#include "starboard/shared/win32/simple_thread.h"
-#include "starboard/shared/win32/win32_video_decoder.h"
-
-namespace starboard {
-namespace shared {
-namespace win32 {
-
-// This class receives decoded video frames.
-class VideoDecodedCallback {
- public:
-  virtual ~VideoDecodedCallback() {}
-  virtual void OnVideoDecoded(VideoFramePtr data) = 0;
-};
-
-// This decoder thread simplifies decoding media. Data is pushed in via
-// QueueInput() and QueueEndOfStream() and output data is pushed via
-// the AudioDecodedCallback.
-class VideoDecoderThread : private SimpleThread {
- public:
-  VideoDecoderThread(AbstractWin32VideoDecoder* decoder_impl,
-                     VideoDecodedCallback* callback);
-  ~VideoDecoderThread() SB_OVERRIDE;
-
-  // Returns true if more input can be pushed to this thread.
-  bool QueueInput(const scoped_refptr<InputBuffer>& buffer);
-  void QueueEndOfStream();
-
- private:
-  void TransferPendingInputTo(std::deque<scoped_refptr<InputBuffer> >* output);
-  void Run() SB_OVERRIDE;
-  AbstractWin32VideoDecoder* win32_video_decoder_;
-  VideoDecodedCallback* callback_;
-  std::deque<scoped_refptr<InputBuffer> > input_buffer_queue_;
-  ::starboard::Mutex input_buffer_queue_mutex_;
-  atomic_int32_t processing_elements_;
-  Semaphore semaphore_;
-};
-
-}  // namespace win32
-}  // namespace shared
-}  // namespace starboard
-
-#endif  // STARBOARD_SHARED_WIN32_VIDEO_DECODER_THREAD_H_
diff --git a/src/starboard/shared/win32/video_renderer.cc b/src/starboard/shared/win32/video_renderer.cc
deleted file mode 100644
index 8cbeecd..0000000
--- a/src/starboard/shared/win32/video_renderer.cc
+++ /dev/null
@@ -1,45 +0,0 @@
-// Copyright 2017 Google Inc. All Rights Reserved.
-//
-// 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.
-
-#include "starboard/shared/win32/video_renderer.h"
-
-#include "starboard/log.h"
-#include "starboard/shared/win32/decode_target_internal.h"
-#include "starboard/shared/win32/error_utils.h"
-#include "third_party/angle/include/EGL/egl.h"
-#include "third_party/angle/include/EGL/eglext.h"
-#include "third_party/angle/include/GLES2/gl2.h"
-
-using starboard::scoped_refptr;
-using Microsoft::WRL::ComPtr;
-using starboard::shared::win32::CheckResult;
-
-namespace starboard {
-namespace shared {
-namespace win32 {
-
-SbDecodeTarget VideoRendererImpl::GetCurrentDecodeTarget(
-    SbMediaTime media_time,
-    bool audio_eos_reached) {
-  VideoFramePtr current_frame =
-      Base::GetCurrentFrame(media_time, audio_eos_reached);
-  if (!current_frame || current_frame->IsEndOfStream()) {
-    return kSbDecodeTargetInvalid;
-  }
-  return new SbDecodeTargetPrivate(current_frame);
-}
-
-}  // namespace win32
-}  // namespace shared
-}  // namespace starboard
diff --git a/src/starboard/shared/win32/video_renderer.h b/src/starboard/shared/win32/video_renderer.h
deleted file mode 100644
index b6448a9..0000000
--- a/src/starboard/shared/win32/video_renderer.h
+++ /dev/null
@@ -1,49 +0,0 @@
-// Copyright 2017 Google Inc. All Rights Reserved.
-//
-// 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.
-
-#ifndef STARBOARD_SHARED_WIN32_VIDEO_RENDERER_H_
-#define STARBOARD_SHARED_WIN32_VIDEO_RENDERER_H_
-
-#include "starboard/mutex.h"
-#include "starboard/shared/starboard/player/filter/video_decoder_internal.h"
-#include "starboard/shared/starboard/player/filter/video_renderer_impl_internal.h"
-#include "starboard/shared/win32/decode_target_internal.h"
-#include "starboard/shared/win32/video_decoder.h"
-
-namespace starboard {
-namespace shared {
-namespace win32 {
-
-class VideoRendererImpl
-    : public ::starboard::shared::starboard::player::filter::VideoRendererImpl {
- public:
-  using Base =
-      ::starboard::shared::starboard::player::filter::VideoRendererImpl;
-  using HostedVideoDecoder =
-      ::starboard::shared::starboard::player::filter::HostedVideoDecoder;
-
-  using VideoDecoder = ::starboard::shared::win32::VideoDecoder;
-
-  explicit VideoRendererImpl(scoped_ptr<VideoDecoder> decoder)
-      : Base(decoder.PassAs<HostedVideoDecoder>()) {}
-
-  SbDecodeTarget GetCurrentDecodeTarget(SbMediaTime media_time,
-                                        bool audio_eos_reached) SB_OVERRIDE;
-};
-
-}  // namespace win32
-}  // namespace shared
-}  // namespace starboard
-
-#endif  // STARBOARD_SHARED_WIN32_VIDEO_RENDERER_H_
diff --git a/src/starboard/shared/win32/video_texture.cc b/src/starboard/shared/win32/video_texture.cc
deleted file mode 100644
index d7870d7..0000000
--- a/src/starboard/shared/win32/video_texture.cc
+++ /dev/null
@@ -1,168 +0,0 @@
-// Copyright 2017 Google Inc. All Rights Reserved.
-//
-// 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.
-
-#include "starboard/shared/win32/video_texture.h"
-
-#include "starboard/shared/win32/error_utils.h"
-
-namespace starboard {
-namespace shared {
-namespace win32 {
-
-namespace {
-
-// Makes a a video output texture for use with VideoProcessorBlt.
-ComPtr<ID3D11Texture2D> MakeOutputTexture(
-    const ComPtr<ID3D11Device>& dx_device, int width, int height) {
-  ComPtr<ID3D11Texture2D> output_texture;
-  D3D11_TEXTURE2D_DESC out_texture_desc = {};
-  out_texture_desc.Width = width;
-  out_texture_desc.Height = height;
-  out_texture_desc.MipLevels = 1;
-  out_texture_desc.ArraySize = 1;
-  out_texture_desc.Format = DXGI_FORMAT_NV12;
-  out_texture_desc.SampleDesc.Count = 1;
-  out_texture_desc.SampleDesc.Quality = 0;
-  // Per https://msdn.microsoft.com/en-us/library/windows/desktop/hh447791(v=vs.85).aspx
-  // This must be USAGE_DEFAULT and BIND_RENDER_TARGET
-  // BIND_SHADER_RESOURCE is required for subsequent ANGLE use.
-  out_texture_desc.Usage = D3D11_USAGE_DEFAULT;
-  out_texture_desc.BindFlags =
-      D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE;
-
-  HRESULT hr = dx_device->CreateTexture2D(
-      &out_texture_desc, nullptr, &output_texture);
-  CheckResult(hr);
-
-  return output_texture;
-}
-class VideoTextureImpl : public VideoTexture {
- public:
-  VideoTextureImpl(
-      const ComPtr<IMFSample>& sample, const RECT& display_aperture,
-      const VideoBltInterfaces& interfaces)
-      : sample_(sample), display_aperture_(display_aperture),
-        video_blt_interfaces_(interfaces) {
-  }
-
-  ComPtr<ID3D11Texture2D> GetTexture() override {
-    // TODO check this is only called on the renderer thread
-
-    // In cases where we display the same frame multiple times,
-    // only VideoProcessorBlt once.
-    if (texture_) {
-      return texture_;
-    }
-    ComPtr<IMFMediaBuffer> media_buffer;
-    HRESULT hr = sample_->GetBufferByIndex(0, &media_buffer);
-    CheckResult(hr);
-
-    ComPtr<IMFDXGIBuffer> dxgi_buffer;
-    hr = media_buffer.As(&dxgi_buffer);
-    CheckResult(hr);
-
-    ComPtr<ID3D11Texture2D> input_texture;
-    hr = dxgi_buffer->GetResource(IID_PPV_ARGS(&input_texture));
-    CheckResult(hr);
-
-    // The VideoProcessor needs to know what subset of the decoded
-    // frame contains active pixels that should be displayed to the user.
-    video_blt_interfaces_.video_context_->VideoProcessorSetStreamSourceRect(
-        video_blt_interfaces_.video_processor_.Get(), 0, TRUE,
-        &display_aperture_);
-
-    D3D11_VIDEO_PROCESSOR_INPUT_VIEW_DESC input_desc = {};
-    input_desc.ViewDimension = D3D11_VPIV_DIMENSION_TEXTURE2D;
-    input_desc.Texture2D.MipSlice = 0;
-    // The DXGI subresource index is the texture array index.
-    dxgi_buffer->GetSubresourceIndex(&input_desc.Texture2D.ArraySlice);
-
-    ComPtr<ID3D11VideoProcessorInputView> input_view;
-    hr = video_blt_interfaces_.video_device_->CreateVideoProcessorInputView(
-        input_texture.Get(), video_blt_interfaces_.video_processor_enum_.Get(),
-        &input_desc, &input_view);
-    CheckResult(hr);
-
-    D3D11_VIDEO_PROCESSOR_OUTPUT_VIEW_DESC output_desc = {};
-    output_desc.ViewDimension = D3D11_VPOV_DIMENSION_TEXTURE2D;
-    output_desc.Texture2D.MipSlice = 0;
-
-    texture_ = MakeOutputTexture(
-        video_blt_interfaces_.dx_device_,
-        display_aperture_.right,
-        display_aperture_.bottom);
-
-    ComPtr<ID3D11VideoProcessorOutputView> output_view;
-    hr = video_blt_interfaces_.video_device_->CreateVideoProcessorOutputView(
-        texture_.Get(), video_blt_interfaces_.video_processor_enum_.Get(),
-        &output_desc, &output_view);
-    CheckResult(hr);
-
-    // We have a single video stream, which is enabled for display.
-    D3D11_VIDEO_PROCESSOR_STREAM stream_info = {};
-    stream_info.Enable = TRUE;
-    stream_info.pInputSurface = input_view.Get();
-
-    hr = video_blt_interfaces_.video_context_->VideoProcessorBlt(
-        video_blt_interfaces_.video_processor_.Get(), output_view.Get(),
-        0, 1, &stream_info);
-    CheckResult(hr);
-
-    return texture_;
-  }
-
- private:
-  ComPtr<IMFSample> sample_;
-  RECT display_aperture_;
-  VideoBltInterfaces video_blt_interfaces_;
-  ComPtr<ID3D11Texture2D> texture_;
-};
-
-}  // namespace
-
-VideoFramePtr VideoFrameFactory::Construct(
-    ComPtr<IMFSample> sample,
-    const RECT& display_aperture,
-    const VideoBltInterfaces& interfaces) {
-  LONGLONG win32_timestamp = 0;
-  HRESULT hr = sample->GetSampleTime(&win32_timestamp);
-  CheckResult(hr);
-
-  VideoFramePtr out(
-      new VideoFrame(display_aperture.right, display_aperture.bottom,
-                     ConvertToMediaTime(win32_timestamp),
-                     new VideoTextureImpl(sample,
-                                          display_aperture,
-                                          interfaces),
-                     nullptr, DeleteVideoTextureImpl));
-  frames_in_flight_.increment();
-  return out;
-}
-
-int VideoFrameFactory::frames_in_flight() {
-  return frames_in_flight_.load();
-}
-
-void VideoFrameFactory::DeleteVideoTextureImpl(void* context, void* arg) {
-  SB_UNREFERENCED_PARAMETER(context);
-  VideoTextureImpl* texture = static_cast<VideoTextureImpl*>(arg);
-  delete texture;
-  frames_in_flight_.decrement();
-}
-
-atomic_int32_t VideoFrameFactory::frames_in_flight_;
-
-}  // namespace win32
-}  // namespace shared
-}  // namespace starboard
diff --git a/src/starboard/shared/win32/video_texture.h b/src/starboard/shared/win32/video_texture.h
deleted file mode 100644
index 6d3edae..0000000
--- a/src/starboard/shared/win32/video_texture.h
+++ /dev/null
@@ -1,63 +0,0 @@
-// Copyright 2017 Google Inc. All Rights Reserved.
-//
-// 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.
-
-#ifndef STARBOARD_SHARED_WIN32_VIDEO_TEXTURE_H_
-#define STARBOARD_SHARED_WIN32_VIDEO_TEXTURE_H_
-
-#include <D3d11_1.h>
-#include <wrl\client.h>  // For ComPtr.
-
-#include "starboard/shared/win32/media_common.h"
-
-namespace starboard {
-namespace shared {
-namespace win32 {
-
-// The contents of VideoFrame->native_texture()
-class VideoTexture {
- public:
-  virtual ~VideoTexture() {}
-  // Retrieves texture associated with video frame.
-  // This method must be called on the rasterizer thread.
-  virtual Microsoft::WRL::ComPtr<ID3D11Texture2D> GetTexture() = 0;
-};
-
-// Contains all ID3D11 interfaces needed to perform a VideoProcessorBlt.
-// For use with passing to VideoTextureImpl instances.
-struct VideoBltInterfaces {
-  Microsoft::WRL::ComPtr<ID3D11Device> dx_device_;
-  Microsoft::WRL::ComPtr<ID3D11VideoProcessorEnumerator> video_processor_enum_;
-  Microsoft::WRL::ComPtr<ID3D11VideoProcessor> video_processor_;
-  Microsoft::WRL::ComPtr<ID3D11VideoDevice1> video_device_;
-  Microsoft::WRL::ComPtr<ID3D11VideoContext> video_context_;
-};
-
-class VideoFrameFactory {
- public:
-  static VideoFramePtr Construct(ComPtr<IMFSample> sample,
-                                 const RECT& display_aperture,
-                                 const VideoBltInterfaces& interfaces);
-  static int frames_in_flight();
-
- private:
-  static void DeleteVideoTextureImpl(void* context, void* arg);
-
-  static atomic_int32_t frames_in_flight_;
-};
-
-}  // namespace win32
-}  // namespace shared
-}  // namespace starboard
-
-#endif  // STARBOARD_SHARED_WIN32_VIDEO_TEXTURE_H_
diff --git a/src/starboard/shared/win32/video_transform.cc b/src/starboard/shared/win32/video_transform.cc
deleted file mode 100644
index 1759620..0000000
--- a/src/starboard/shared/win32/video_transform.cc
+++ /dev/null
@@ -1,108 +0,0 @@
-// Copyright 2017 Google Inc. All Rights Reserved.
-//
-// 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.
-
-#include "starboard/shared/win32/video_transform.h"
-
-#include "starboard/common/scoped_ptr.h"
-#include "starboard/log.h"
-#include "starboard/shared/win32/error_utils.h"
-#include "starboard/shared/win32/media_common.h"
-#include "starboard/shared/win32/media_foundation_utils.h"
-#include "starboard/shared/win32/media_transform.h"
-
-namespace starboard {
-namespace shared {
-namespace win32 {
-
-using Microsoft::WRL::ComPtr;
-
-namespace {
-
-GUID CLSID_VideoDecoderVPX() {
-  GUID output = {0xE3AAF548, 0xC9A4, 0x4C6E, 0x23, 0x4D, 0x5A,
-                 0xDA,       0x37,   0x4B,   0x00, 0x00};
-  return output;
-}
-
-// CLSID_CMSVideoDecoderMFT {62CE7E72-4C71-4D20-B15D-452831A87D9D}
-GUID CLSID_VideoDecoderH264() {
-  GUID output = {0x62CE7E72, 0x4C71, 0x4d20, 0xB1, 0x5D, 0x45,
-                 0x28,       0x31,   0xA8,   0x7D, 0x9D};
-  return output;
-}
-
-ComPtr<IMFMediaType> CreateVideoMediaType(const GUID& media_subtype) {
-  ComPtr<IMFMediaType> input_type;
-  HRESULT hr = MFCreateMediaType(&input_type);
-  CheckResult(hr);
-  hr = input_type->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Video);
-  CheckResult(hr);
-  hr = input_type->SetGUID(MF_MT_SUBTYPE, media_subtype);
-  CheckResult(hr);
-  return input_type;
-}
-
-void ApplyOutputFormat(VideoFormat video_fmt, MediaTransform* target) {
-  switch (video_fmt) {
-    case kVideoFormat_YV12: {
-      target->SetOutputTypeBySubType(MFVideoFormat_YV12);
-      break;
-    }
-  }
-}
-
-}  // namespace.
-
-scoped_ptr<MediaTransform> CreateH264Transform(VideoFormat video_fmt) {
-  ComPtr<IMFTransform> transform;
-  HRESULT hr = CreateDecoderTransform(CLSID_VideoDecoderH264(), &transform);
-  CheckResult(hr);
-  ComPtr<IMFMediaType> input_type = CreateVideoMediaType(MFVideoFormat_H264);
-  hr = input_type->SetUINT32(MF_MT_INTERLACE_MODE,
-                             MFVideoInterlace_Progressive);
-  CheckResult(hr);
-  hr = transform->SetInputType(MediaTransform::kStreamId, input_type.Get(), 0);
-  CheckResult(hr);
-  scoped_ptr<MediaTransform> out(new MediaTransform(transform));
-  ApplyOutputFormat(video_fmt, out.get());
-  return out.Pass();
-}
-
-scoped_ptr<MediaTransform> TryCreateVP9Transform(VideoFormat video_fmt,
-                                                 int width,
-                                                 int height) {
-  ComPtr<IMFTransform> transform;
-  HRESULT hr = CreateDecoderTransform(CLSID_VideoDecoderVPX(), &transform);
-  // VpX decoder could not be created at all.
-  if (!transform) {
-    return scoped_ptr<MediaTransform>(nullptr);
-  }
-  ComPtr<IMFMediaType> input_type = CreateVideoMediaType(MFVideoFormat_VP90);
-  hr = input_type->SetUINT32(MF_MT_INTERLACE_MODE,
-                             MFVideoInterlace_Progressive);
-  CheckResult(hr);
-  hr = MFSetAttributeSize(input_type.Get(), MF_MT_FRAME_SIZE, width, height);
-  CheckResult(hr);
-  hr = transform->SetInputType(MediaTransform::kStreamId, input_type.Get(), 0);
-  if (!SUCCEEDED(hr)) {
-    return scoped_ptr<MediaTransform>(nullptr);
-  }
-  scoped_ptr<MediaTransform> out(new MediaTransform(transform));
-  ApplyOutputFormat(video_fmt, out.get());
-  return out.Pass();
-}
-
-}  // namespace win32
-}  // namespace shared
-}  // namespace starboard
diff --git a/src/starboard/shared/win32/video_transform.h b/src/starboard/shared/win32/video_transform.h
deleted file mode 100644
index f064e46..0000000
--- a/src/starboard/shared/win32/video_transform.h
+++ /dev/null
@@ -1,42 +0,0 @@
-// Copyright 2017 Google Inc. All Rights Reserved.
-//
-// 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.
-
-#ifndef STARBOARD_SHARED_WIN32_VIDEO_TRANSFORM_H_
-#define STARBOARD_SHARED_WIN32_VIDEO_TRANSFORM_H_
-
-#include "starboard/common/scoped_ptr.h"
-#include "starboard/shared/win32/media_transform.h"
-
-namespace starboard {
-namespace shared {
-namespace win32 {
-
-enum VideoFormat {
-  kVideoFormat_YV12,
-};
-
-// Creating an H264 decoder should succeed unconditionally.
-scoped_ptr<MediaTransform> CreateH264Transform(VideoFormat video_fmt);
-
-// VP9 decoders require a width/height variable and may fail construction for
-// certain configurations.
-scoped_ptr<MediaTransform> TryCreateVP9Transform(VideoFormat video_fmt,
-                                                 int width,
-                                                 int height);
-
-}  // namespace win32
-}  // namespace shared
-}  // namespace starboard
-
-#endif  // STARBOARD_SHARED_WIN32_VIDEO_TRANSFORM_H_
diff --git a/src/starboard/shared/win32/win32_video_decoder.cc b/src/starboard/shared/win32/win32_video_decoder.cc
deleted file mode 100644
index 93e717c..0000000
--- a/src/starboard/shared/win32/win32_video_decoder.cc
+++ /dev/null
@@ -1,318 +0,0 @@
-// Copyright 2017 Google Inc. All Rights Reserved.
-//
-// 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.
-
-#include "starboard/shared/win32/win32_video_decoder.h"
-
-#include <Codecapi.h>
-#include <D3d11_1.h>
-
-#include <queue>
-#include <utility>
-
-#include "starboard/shared/starboard/thread_checker.h"
-#include "starboard/shared/win32/atomic_queue.h"
-#include "starboard/shared/win32/decrypting_decoder.h"
-#include "starboard/shared/win32/dx_context_video_decoder.h"
-#include "starboard/shared/win32/error_utils.h"
-#include "starboard/shared/win32/media_common.h"
-#include "starboard/shared/win32/media_foundation_utils.h"
-#include "starboard/shared/win32/video_texture.h"
-#include "starboard/shared/win32/video_transform.h"
-#include "starboard/window.h"
-
-namespace starboard {
-namespace shared {
-namespace win32 {
-
-using Microsoft::WRL::ComPtr;
-using ::starboard::shared::starboard::ThreadChecker;
-using ::starboard::shared::win32::CheckResult;
-
-namespace {
-
-// In MS sample it is set to 5 and we experienced issues when this is set to
-// below 5.  This can be further tuned to balance between playback smoothness
-// and memory consumption.
-const int kSampleAllocatorFramesMax = 12;
-// This is the minimum allocated frames in the output ring buffer.  Can be
-// further tuned to save memory.  Note that use a value that is too small leads
-// to hang when calling ProcessOutput().
-const int kMinimumOutputSampleCount = kSampleAllocatorFramesMax + 5;
-
-// CLSID_CMSVideoDecoderMFT {62CE7E72-4C71-4D20-B15D-452831A87D9D}
-const GUID CLSID_VideoDecoder = {0x62CE7E72, 0x4C71, 0x4d20, 0xB1, 0x5D, 0x45,
-                                 0x28,       0x31,   0xA8,   0x7D, 0x9D};
-
-class AbstractWin32VideoDecoderImpl : public AbstractWin32VideoDecoder {
- public:
-  AbstractWin32VideoDecoderImpl(SbMediaVideoCodec codec, SbDrmSystem drm_system)
-      : thread_checker_(ThreadChecker::kSetThreadIdOnFirstCheck),
-        codec_(codec) {
-    SbMemorySet(&display_aperture_, 0, sizeof(RECT));
-    Configure(drm_system);
-  }
-
-  void Consume(ComPtr<IMFSample> sample) {
-    SB_DCHECK(thread_checker_.CalledOnValidThread());
-    VideoFramePtr frame_output = VideoFrameFactory::Construct(
-        sample, display_aperture_, video_blt_interfaces_);
-    output_queue_.push(frame_output);
-  }
-
-  void OnNewOutputType(const ComPtr<IMFMediaType>& type) {
-    SB_DCHECK(thread_checker_.CalledOnValidThread());
-
-    RECT rect = {};
-    MFVideoArea aperture;
-    HRESULT hr = type->GetBlob(MF_MT_MINIMUM_DISPLAY_APERTURE,
-                               reinterpret_cast<UINT8*>(&aperture),
-                               sizeof(MFVideoArea), nullptr);
-    if (SUCCEEDED(hr)) {
-      display_aperture_.left = aperture.OffsetX.value;
-      display_aperture_.right = rect.left + aperture.Area.cx;
-      display_aperture_.top = aperture.OffsetY.value;
-      display_aperture_.bottom = rect.top + aperture.Area.cy;
-      return;
-    }
-
-    uint32_t width;
-    uint32_t height;
-    hr = MFGetAttributeSize(type.Get(), MF_MT_FRAME_SIZE, &width, &height);
-    if (SUCCEEDED(hr)) {
-      display_aperture_.left = 0;
-      display_aperture_.top = 0;
-      display_aperture_.right = rect.left + width;
-      display_aperture_.bottom = rect.top + height;
-    }
-  }
-
-  void Configure(SbDrmSystem drm_system) {
-    scoped_ptr<MediaTransform> media_transform;
-
-    // If this is updated then media_is_video_supported.cc also needs to be
-    // updated.
-    switch (codec_) {
-      case kSbMediaVideoCodecH264: {
-        media_transform = CreateH264Transform(kVideoFormat_YV12);
-        break;
-      }
-      case kSbMediaVideoCodecVp9: {
-        // VP9 decoder needs a default resolution.
-        media_transform = TryCreateVP9Transform(kVideoFormat_YV12, 1024, 768);
-        break;
-      }
-      default: { SB_NOTREACHED(); }
-    }
-
-    impl_.reset(
-        new DecryptingDecoder("video", media_transform.Pass(), drm_system));
-    MediaTransform* decoder = impl_->GetDecoder();
-
-    dx_decoder_ctx_ = GetDirectXForHardwareDecoding();
-    video_blt_interfaces_.dx_device_ = dx_decoder_ctx_.dx_device_out;
-
-    DWORD input_stream_count = 0;
-    DWORD output_stream_count = 0;
-    decoder->GetStreamCount(&input_stream_count, &output_stream_count);
-    SB_DCHECK(1 == input_stream_count);
-    SB_DCHECK(1 == output_stream_count);
-
-    ComPtr<IMFAttributes> attributes = decoder->GetAttributes();
-
-    HRESULT hr = attributes->SetUINT32(MF_SA_MINIMUM_OUTPUT_SAMPLE_COUNT,
-                                       kMinimumOutputSampleCount);
-    CheckResult(hr);
-
-    UINT32 value = 0;
-    hr = attributes->GetUINT32(MFT_SUPPORT_DYNAMIC_FORMAT_CHANGE, &value);
-    SB_DCHECK(hr == S_OK || hr == MF_E_ATTRIBUTENOTFOUND);
-
-    // TODO: handle the MFT_SUPPORT_DYNAMIC_FORMAT_CHANGE correctly.
-    // SB_DCHECK(value == TRUE);
-
-    // Enables DirectX video acceleration for video decoding.
-    decoder->SendMessage(MFT_MESSAGE_SET_D3D_MANAGER,
-                         reinterpret_cast<ULONG_PTR>(
-                             dx_decoder_ctx_.dxgi_device_manager_out.Get()));
-
-    ComPtr<IMFMediaType> output_type = decoder->GetCurrentOutputType();
-    SB_DCHECK(output_type);
-
-    UINT32 width;
-    UINT32 height;
-    hr = MFGetAttributeSize(output_type.Get(), MF_MT_FRAME_SIZE, &width,
-                            &height);
-
-    display_aperture_.left = 0;
-    display_aperture_.top = 0;
-    display_aperture_.right = width;
-    display_aperture_.bottom = height;
-
-    if (FAILED(hr)) {
-      SB_NOTREACHED() << "could not get width & height, hr = " << hr;
-      return;
-    }
-
-    ComPtr<IMFAttributes> output_attributes =
-        decoder->GetOutputStreamAttributes();
-    // The decoder must output textures that are bound to shader resources,
-    // or we can't draw them later via ANGLE.
-    hr = output_attributes->SetUINT32(
-        MF_SA_D3D11_BINDFLAGS, D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_DECODER);
-    SB_DCHECK(SUCCEEDED(hr));
-
-    dx_decoder_ctx_.dx_device_out.As(&video_blt_interfaces_.video_device_);
-
-    D3D11_VIDEO_PROCESSOR_CONTENT_DESC video_processor_desc = {};
-    video_processor_desc.InputFrameFormat =
-        D3D11_VIDEO_FRAME_FORMAT_PROGRESSIVE;
-    // Presumably changing the input/output frame rate would
-    // allow us to use the VideoProcessor to decide which frames to drop
-    // But we already have common code that does this, so presumably
-    // by setting the input and output frame rate the same, we instruct
-    // the VideoProcessor to give us one output for every input frame.
-    video_processor_desc.InputFrameRate.Numerator = 60;
-    video_processor_desc.InputFrameRate.Denominator = 1;
-    video_processor_desc.OutputFrameRate = video_processor_desc.InputFrameRate;
-
-    SbWindowOptions window_options;
-    SbWindowSetDefaultOptions(&window_options);
-    video_processor_desc.OutputWidth = window_options.size.width;
-    video_processor_desc.OutputHeight = window_options.size.height;
-
-    video_processor_desc.InputWidth = video_processor_desc.OutputWidth;
-    video_processor_desc.InputHeight = video_processor_desc.OutputHeight;
-    video_processor_desc.OutputFrameRate.Numerator = 60;
-    video_processor_desc.OutputFrameRate.Denominator = 1;
-    video_processor_desc.Usage = D3D11_VIDEO_USAGE_PLAYBACK_NORMAL;
-
-    hr = video_blt_interfaces_.video_device_->CreateVideoProcessorEnumerator(
-        &video_processor_desc, &video_blt_interfaces_.video_processor_enum_);
-    CheckResult(hr);
-
-    hr = video_blt_interfaces_.video_device_->CreateVideoProcessor(
-        video_blt_interfaces_.video_processor_enum_.Get(), 0,
-        &video_blt_interfaces_.video_processor_);
-    CheckResult(hr);
-
-    ComPtr<ID3D11DeviceContext> device_context;
-    dx_decoder_ctx_.dx_device_out->GetImmediateContext(&device_context);
-
-    device_context.As(&video_blt_interfaces_.video_context_);
-    video_blt_interfaces_.video_context_->VideoProcessorSetStreamFrameFormat(
-        video_blt_interfaces_.video_processor_.Get(), 0,
-        D3D11_VIDEO_FRAME_FORMAT_PROGRESSIVE);
-
-    // https://msdn.microsoft.com/en-us/library/windows/desktop/hh447754(v=vs.85).aspx
-    // "for example, if you provide your own pixel shader for the video
-    // processor, you might want to disable the driver's automatic
-    // processing."
-    // We do have our own pixel shader, so we do want to disable anything
-    // like this.
-    video_blt_interfaces_.video_context_
-        ->VideoProcessorSetStreamAutoProcessingMode(
-            video_blt_interfaces_.video_processor_.Get(), 0, false);
-  }
-
-  bool TryWrite(const scoped_refptr<InputBuffer>& buff) {
-    SB_DCHECK(thread_checker_.CalledOnValidThread());
-
-    const bool write_ok = impl_->TryWriteInputBuffer(buff, 0);
-    return write_ok;
-  }
-
-  void WriteEndOfStream() SB_OVERRIDE {
-    SB_DCHECK(thread_checker_.CalledOnValidThread());
-
-    impl_->Drain();
-
-    ComPtr<IMFSample> sample;
-    ComPtr<IMFMediaType> media_type;
-    while (VideoFrameFactory::frames_in_flight() < kSampleAllocatorFramesMax &&
-           impl_->ProcessAndRead(&sample, &media_type)) {
-      if (media_type) {
-        OnNewOutputType(media_type);
-      }
-      if (sample) {
-        Consume(sample);
-      }
-    }
-  }
-
-  VideoFramePtr ProcessAndRead(bool* too_many_outstanding_frames) SB_OVERRIDE {
-    SB_DCHECK(thread_checker_.CalledOnValidThread());
-    SB_DCHECK(too_many_outstanding_frames);
-
-    *too_many_outstanding_frames =
-        VideoFrameFactory::frames_in_flight() >= kSampleAllocatorFramesMax;
-
-    if (!*too_many_outstanding_frames) {
-      ComPtr<IMFSample> sample;
-      ComPtr<IMFMediaType> media_type;
-      impl_->ProcessAndRead(&sample, &media_type);
-      if (media_type) {
-        OnNewOutputType(media_type);
-      }
-      if (sample) {
-        Consume(sample);
-      }
-    }
-    if (output_queue_.empty()) {
-      return NULL;
-    }
-    VideoFramePtr output = output_queue_.front();
-    output_queue_.pop();
-    return output;
-  }
-
-  void Reset() SB_OVERRIDE {
-    impl_->Reset();
-    std::queue<VideoFramePtr> empty;
-    output_queue_.swap(empty);
-    thread_checker_.Detach();
-  }
-
-  // The object is single-threaded and is driven by a dedicated thread.
-  // However the thread may gets destroyed and re-created over the life time of
-  // this object.  We enforce that certain member functions can only called
-  // from one thread while still allows this object to be driven by different
-  // threads by:
-  // 1. The |thread_checker_| is initially created without attaching to any
-  //    thread.
-  // 2. When a thread is destroyed, Reset() will be called which in turn calls
-  //    Detach() on the |thread_checker_| to allow the object to attach to a
-  //    new thread.
-  ::starboard::shared::starboard::ThreadChecker thread_checker_;
-  std::queue<VideoFramePtr> output_queue_;
-  const SbMediaVideoCodec codec_;
-  scoped_ptr<DecryptingDecoder> impl_;
-
-  RECT display_aperture_;
-  HardwareDecoderContext dx_decoder_ctx_;
-
-  VideoBltInterfaces video_blt_interfaces_;
-};
-
-}  // anonymous namespace.
-
-scoped_ptr<AbstractWin32VideoDecoder> AbstractWin32VideoDecoder::Create(
-    SbMediaVideoCodec codec,
-    SbDrmSystem drm_system) {
-  return scoped_ptr<AbstractWin32VideoDecoder>(
-      new AbstractWin32VideoDecoderImpl(codec, drm_system));
-}
-
-}  // namespace win32
-}  // namespace shared
-}  // namespace starboard
diff --git a/src/starboard/shared/win32/win32_video_decoder.h b/src/starboard/shared/win32/win32_video_decoder.h
deleted file mode 100644
index 643c34d..0000000
--- a/src/starboard/shared/win32/win32_video_decoder.h
+++ /dev/null
@@ -1,51 +0,0 @@
-// Copyright 2017 Google Inc. All Rights Reserved.
-//
-// 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.
-
-#ifndef STARBOARD_SHARED_WIN32_WIN32_VIDEO_DECODER_H_
-#define STARBOARD_SHARED_WIN32_WIN32_VIDEO_DECODER_H_
-
-#include <deque>
-#include <vector>
-
-#include "starboard/common/ref_counted.h"
-#include "starboard/common/scoped_ptr.h"
-#include "starboard/drm.h"
-#include "starboard/media.h"
-#include "starboard/shared/starboard/player/decoded_audio_internal.h"
-#include "starboard/shared/starboard/player/video_frame_internal.h"
-#include "starboard/shared/win32/media_common.h"
-#include "starboard/types.h"
-
-namespace starboard {
-namespace shared {
-namespace win32 {
-
-// VideoDecoder for Win32.
-class AbstractWin32VideoDecoder {
- public:
-  static scoped_ptr<AbstractWin32VideoDecoder> Create(SbMediaVideoCodec codec,
-                                                      SbDrmSystem drm_system);
-  virtual ~AbstractWin32VideoDecoder() {}
-
-  virtual bool TryWrite(const scoped_refptr<InputBuffer>& buff) = 0;
-  virtual void WriteEndOfStream() = 0;
-  virtual VideoFramePtr ProcessAndRead(bool* too_many_outstanding_frames) = 0;
-  virtual void Reset() = 0;
-};
-
-}  // namespace win32
-}  // namespace shared
-}  // namespace starboard
-
-#endif  // STARBOARD_SHARED_WIN32_WIN32_VIDEO_DECODER_H_
diff --git a/src/starboard/shared/x11/application_x11.cc b/src/starboard/shared/x11/application_x11.cc
index 54b6cc9..f440bbf 100644
--- a/src/starboard/shared/x11/application_x11.cc
+++ b/src/starboard/shared/x11/application_x11.cc
@@ -1241,7 +1241,8 @@
 #if SB_API_VERSION >= SB_WINDOW_SIZE_CHANGED_API_VERSION
       XConfigureEvent* x_configure_event =
           reinterpret_cast<XConfigureEvent*>(x_event);
-      SbEventWindowSizeChangedData* data = new SbEventWindowSizeChangedData();
+      scoped_ptr<SbEventWindowSizeChangedData> data(
+          new SbEventWindowSizeChangedData());
       data->window = FindWindow(x_configure_event->window);
       bool unhandled_resize = data->window->unhandled_resize;
       data->window->BeginComposite();
@@ -1255,7 +1256,8 @@
       SbWindowGetSize(data->window, &window_size);
       data->size = window_size;
       data->window->unhandled_resize = false;
-      return new Event(kSbEventTypeWindowSizeChanged, data, NULL);
+      return new Event(kSbEventTypeWindowSizeChanged, data.release(),
+                       &DeleteDestructor<SbInputData>);
 #else  // SB_API_VERSION >= SB_WINDOW_SIZE_CHANGED_API_VERSION
       return NULL;
 #endif  // SB_API_VERSION >= SB_WINDOW_SIZE_CHANGED_API_VERSION
diff --git a/src/starboard/stub/configuration_public.h b/src/starboard/stub/configuration_public.h
index e7129c6..444143e 100644
--- a/src/starboard/stub/configuration_public.h
+++ b/src/starboard/stub/configuration_public.h
@@ -361,14 +361,6 @@
 
 // --- Media Configuration ---------------------------------------------------
 
-// Specifies whether this platform has support for a possibly-decrypting
-// elementary stream player for at least H.264/AAC (and AES-128-CTR, if
-// decrypting). A player is responsible for ingesting an audio and video
-// elementary stream, optionally-encrypted, and ultimately producing
-// synchronized audio/video. If a player is defined, it must choose one of the
-// supported composition methods below.
-#define SB_HAS_PLAYER 1
-
 // After a seek is triggerred, the default behavior is to append video frames
 // from the last key frame before the seek time and append audio frames from the
 // seek time because usually all audio frames are key frames.  On platforms that
diff --git a/src/starboard/stub/gyp_configuration.py b/src/starboard/stub/gyp_configuration.py
index 70f8340..e97189f 100644
--- a/src/starboard/stub/gyp_configuration.py
+++ b/src/starboard/stub/gyp_configuration.py
@@ -15,7 +15,7 @@
 
 import logging
 
-import config.starboard
+import config.base
 import gyp_utils
 
 
@@ -27,7 +27,7 @@
     return None
 
 
-class PlatformConfig(config.starboard.PlatformConfigStarboard):
+class PlatformConfig(config.base.PlatformConfigBase):
   """Starboard stub platform configuration."""
 
   def __init__(self, platform):
diff --git a/src/starboard/tizen/armv7l/configuration_public.h b/src/starboard/tizen/armv7l/configuration_public.h
index 3c2d612..b5b8830 100644
--- a/src/starboard/tizen/armv7l/configuration_public.h
+++ b/src/starboard/tizen/armv7l/configuration_public.h
@@ -106,14 +106,6 @@
 
 // --- Media Configuration ---------------------------------------------------
 
-// Specifies whether this platform has support for a possibly-decrypting
-// elementary stream player for at least H.264/AAC (and AES-128-CTR, if
-// decrypting). A player is responsible for ingesting an audio and video
-// elementary stream, optionally-encrypted, and ultimately producing
-// synchronized audio/video. If a player is defined, it must choose one of the
-// supported composition methods below.
-#define SB_HAS_PLAYER 1
-
 // The maximum audio bitrate the platform can decode.  The following value
 // equals to 2M bytes per seconds which is more than enough for compressed
 // audio.
diff --git a/src/starboard/tizen/armv7l/gyp_configuration.py b/src/starboard/tizen/armv7l/gyp_configuration.py
index 50bae01..9fac11e 100644
--- a/src/starboard/tizen/armv7l/gyp_configuration.py
+++ b/src/starboard/tizen/armv7l/gyp_configuration.py
@@ -15,7 +15,7 @@
 
 import logging
 
-import config.starboard
+import config.base
 
 
 def CreatePlatformConfig():
@@ -26,7 +26,7 @@
     return None
 
 
-class _PlatformConfig(config.starboard.PlatformConfigStarboard):
+class _PlatformConfig(config.base.PlatformConfigBase):
   """Starboard Tizen Armv7l platform configuration."""
 
   def __init__(self, platform):
diff --git a/src/starboard/tools/abstract_launcher.py b/src/starboard/tools/abstract_launcher.py
index 6d83662..f3f9745 100644
--- a/src/starboard/tools/abstract_launcher.py
+++ b/src/starboard/tools/abstract_launcher.py
@@ -36,9 +36,8 @@
   Raises:
     RuntimeError:  The specified platform does not exist.
   """
-  platform_dict = platform_module.GetAllPorts()
-  if platform in platform_dict:
-    platform_path = platform_dict[platform]
+  if platform_module.IsValid(platform):
+    platform_path = platform_module.Get(platform).path
     if platform_path not in sys.path:
       sys.path.append(platform_path)
     gyp_module = importlib.import_module("gyp_configuration")
@@ -179,6 +178,10 @@
     """Kills the launcher. Must be implemented in subclasses."""
     pass
 
+  def SendResume(self):
+    """Sends resume signal to the launcher's executable."""
+    raise RuntimeError("Resume not supported for this platform.")
+
   def GetStartupTimeout(self):
     """Gets the number of seconds to wait before assuming a launcher timeout."""
     return self.startup_timeout_seconds
@@ -214,3 +217,7 @@
       out_directory = DynamicallyBuildOutDirectory(self.platform, self.config)
 
     return os.path.abspath(os.path.join(out_directory, self.target_name))
+
+  def _CloseOutputFile(self):
+    if self.output_file != sys.stdout and not self.output_file.closed:
+      self.output_file.close()
diff --git a/src/starboard/tools/build.py b/src/starboard/tools/build.py
index cebbbea..a132f91 100644
--- a/src/starboard/tools/build.py
+++ b/src/starboard/tools/build.py
@@ -46,7 +46,7 @@
 
   logging.warning("Environment variable '%s' is '%s', which is invalid.",
                   key, raw_value)
-  logging.warning('Valid platforms: %s', starboard.tools.platform.GetAllNames())
+  logging.warning('Valid platforms: %s', starboard.tools.platform.GetAll())
   return False
 
 
diff --git a/src/starboard/tools/command_line.py b/src/starboard/tools/command_line.py
index 3a08850..4dbe34c 100644
--- a/src/starboard/tools/command_line.py
+++ b/src/starboard/tools/command_line.py
@@ -35,7 +35,7 @@
   arg_parser.add_argument(
       '-p',
       '--platform',
-      choices=starboard.tools.platform.GetAllNames(),
+      choices=starboard.tools.platform.GetAll(),
       default=default_platform,
       required=not default_platform,
       help="Device platform, eg 'linux-x64x11'.")
@@ -51,10 +51,6 @@
       '--device_id',
       help='Devkit or IP address for the target device.')
   arg_parser.add_argument(
-      '-t',
-      '--target_name',
-      help='Name of executable target.')
-  arg_parser.add_argument(
       '--target_params',
       help='Command line arguments to pass to the executable.'
            ' Because different executables could have differing command'
diff --git a/src/starboard/tools/command_line_test.py b/src/starboard/tools/command_line_test.py
index b307ec4..2ffc230 100755
--- a/src/starboard/tools/command_line_test.py
+++ b/src/starboard/tools/command_line_test.py
@@ -26,7 +26,7 @@
 
 
 _A_CONFIG = starboard.tools.config.GetAll()[0]
-_A_PLATFORM = starboard.tools.platform.GetAllNames()[0]
+_A_PLATFORM = starboard.tools.platform.GetAll()[0]
 
 
 def _RestoreMapping(target, source):
diff --git a/src/starboard/tools/config_test.py b/src/starboard/tools/config_test.py
index 4647714..a9ab777 100755
--- a/src/starboard/tools/config_test.py
+++ b/src/starboard/tools/config_test.py
@@ -18,22 +18,23 @@
 
 import unittest
 
-import config as config_module
+import config
 
 
 class ConfigTest(unittest.TestCase):
 
   def testGetAll(self):
-    configs = config_module.GetAll()
-    self.assertNotEqual(0, len(configs))
+    config_names = config.GetAll()
+    self.assertNotEqual(0, len(config_names))
 
   def testIsValid(self):
-    configs = config_module.GetAll()
-    for config in configs:
-      self.assertTrue(config_module.IsValid(config))
-      self.assertTrue(config_module.IsValid(config.lower()))
-      self.assertFalse(config_module.IsValid(config.upper()))
-    self.assertFalse(config_module.IsValid('invalidconfig'))
+    config_names = config.GetAll()
+    for config_name in config_names:
+      self.assertTrue(config.IsValid(config_name))
+      self.assertTrue(config.IsValid(config_name.lower()))
+      self.assertFalse(config.IsValid(config_name.upper()))
+    self.assertFalse(config.IsValid('invalidconfig'))
+
 
 if __name__ == '__main__':
   unittest.main()
diff --git a/src/starboard/tools/doc/abstract_launcher.md b/src/starboard/tools/doc/abstract_launcher.md
new file mode 100644
index 0000000..062ade4
--- /dev/null
+++ b/src/starboard/tools/doc/abstract_launcher.md
@@ -0,0 +1,37 @@
+# App Launchers
+
+The app launcher framework is used to run an executable on a given platform,
+allowing its output/results to be used by other scripts or tools.
+
+## Making an App Launcher
+
+In order to use this framework for your platform, there must be a method called
+"GetLauncher()" in the PlatformConfig class that your platform's
+"gyp_configuration.py" file refers to.  It should load and return a module
+containing a class called "Launcher."  This class must inherit from the
+AbstractLauncher class in [abstract_launcher.py](../../abstract_launcher.py),
+and must implement at minimum the following abstract methods:
+
+- Run(): Runs the executable, logs its output, and returns its return code.
+         Generally, any app installation work is also done in this method.
+- Kill(): Kills the currently running executable and cleans up any leftover
+          resources such as threads, processes, etc.
+
+Once the above steps are implemented, tools that use this framework, such as
+[Starboard's unit test runner](../../testing/test_runner.py), should work
+properly for your platform.  For an example of a Launcher class, see
+[this Linux implementation](../../../linux/shared/launcher.py).  For an example
+of the corresponding "GetLauncher()" method, see
+[this gyp_configuration.py file](../../../linux/shared/gyp_configuration.py).
+
+## Using an App Launcher
+
+In order to use this framework in a Python tool, it must import
+abstract_launcher.py and call "abstract_launcher.LauncherFactory()."  This
+method returns a Launcher object from the platform specified by its "platform"
+argument.  To run the launcher, call its "Run()" method, and to stop it, call
+its "Kill()" method.  If your tools need to access the Launcher's output while
+the executable is still running, have it start "Run()" in a separate thread;
+this will allow the main thread to easily read from the Launcher's output file.
+For an example of creating and using a Launcher, see
+[this example](../../example/app_launcher_client.py).
\ No newline at end of file
diff --git a/src/starboard/tools/testing/README.md b/src/starboard/tools/doc/testing.md
similarity index 84%
rename from src/starboard/tools/testing/README.md
rename to src/starboard/tools/doc/testing.md
index 903d19b..9406417 100644
--- a/src/starboard/tools/testing/README.md
+++ b/src/starboard/tools/doc/testing.md
@@ -5,13 +5,13 @@
 
 ## Components
 
-1.) test_runner.py
+### 1.) test_runner.py
 
-This script is used to run unit test binaries on multiple platforms.  Currently,
-it is only compatible with Linux and Android.  To see a full list of parameters
-that can be supplied to the script, run "python test_runner.py --help".
+This script is used to run unit test binaries on multiple platforms.To see a
+full list of parameters that can be supplied to the script, run
+"python test_runner.py --help".
 
-Running Tests:
+#### Running Tests:
 
 To run all tests for a given platform, execute the "test_runner.py" script and
 provide at minimum the "--platform" and "--config" arguments.  Example:
@@ -25,7 +25,7 @@
   python test_runner.py --platform=android-x86 --config=devel \
     --device_id=emulator-4
 
-Running a Single Test:
+#### Running a Single Test:
 
 If you would like to run a single unit test binary and view its output,
 you can do so by using the "--target_name" parameter and providing a
@@ -34,13 +34,13 @@
   python test_runner.py --platform=android-x86 --config=devel \
     --device_id=emulator-4 --target_name=audio_test
 
-Building Tests:
+#### Building Tests:
 
 You can also use this script to build your unit test binaries before running
 them.  To do this, provide the "-b" command line flag.  If you would like to
 build the tests and then run them, provide the flags "-br".
 
-2.) Master list of test binaries
+### 2.) Master list of test binaries
 
 In your application's "starboard_configuration.py" file, define a variable
 called TEST_TARGETS.  It should be a list containing the names of all of
@@ -61,7 +61,8 @@
 To filter out tests that you do not want to run for a specific platform,
 implement a method within the platform's GYP PlatformConfig class called
 "GetTestFilters()".  The PlatformConfig class lives in a
-gyp_configuration.py file.  See "../../linux/x64x11/shared/gyp_configuration.py"
+gyp_configuration.py file.  See
+[this Linux implementation](../../../linux/x64x11/shared/gyp_configuration.py)
 for an example.
 
 The "GetTestFilters()" function should return a list of TestFilter objects,
@@ -86,9 +87,9 @@
 If a platform requires extra environment variables in order to run tests
 properly, implement a method called "GetTestEnvVariables()" in the same
 PlatformConfig mentioned above.  There is an example of this method in
-"../../linux/x64x11/shared/gyp_configuration.py" as well.  The method should
-return a dictionary that maps test binary names to dictionaries of
-environment variables that they need.  Example:
+the provided Linux implementation.  The method should return a dictionary that
+maps test binary names to dictionaries of environment variables that they need.
+Example:
 
   def GetTestEnvVariables(self):
     return {
diff --git a/src/starboard/tools/example/app_launcher_client.py b/src/starboard/tools/example/app_launcher_client.py
index fb7d3ba..e6ee49e 100644
--- a/src/starboard/tools/example/app_launcher_client.py
+++ b/src/starboard/tools/example/app_launcher_client.py
@@ -24,19 +24,21 @@
 
 def main():
   parser = command_line.CreateParser()
+  parser.add_argument(
+      "-t",
+      "--target_name",
+      required=True,
+      help="Name of executable target.")
   args = parser.parse_args()
-  extra_args = {}
 
-  if not args.device_id:
-    args.device_id = None
-
-  extra_args = {}
+  target_params = []
   if args.target_params:
-    extra_args["target_params"] = args.target_params.split(" ")
+    target_params = args.target_params.split(" ")
 
   launcher = abstract_launcher.LauncherFactory(
       args.platform, args.target_name, args.config,
-      args.device_id, extra_args, out_directory=args.out_directory)
+      device_id=args.device_id, target_params=target_params,
+      out_directory=args.out_directory)
   return launcher.Run()
 
 if __name__ == "__main__":
diff --git a/src/starboard/tools/package.py b/src/starboard/tools/package.py
index 5ee8228..68437be 100644
--- a/src/starboard/tools/package.py
+++ b/src/starboard/tools/package.py
@@ -20,19 +20,47 @@
 import logging
 import os
 
+import _env  # pylint: disable=unused-import
 import starboard
-from starboard.tools import paths
 from starboard.tools import platform
 
 
-def _GetPackageClass(platform_info):
-  # From the relative path to the starboard directory, construct a full
+def _ImportModule(path, root_module, module_name=None):
+  """Load a platform specific python module using importlib.
+
+  Load the python module named |module_name| relative to |root_module|.
+  Args:
+    path: Path to the platform
+    root_module: An already-loaded module
+    module_name: Name of a python module to load. If None, load the platform
+        directory as a python module.
+  Returns:
+    A module loaded with importlib.import_module
+  Throws:
+    ImportError if the module fails to be loaded.
+  """
+  # From the relative path to the |root_module|'s directory, construct a full
   # python package name and attempt to load it.
+  relative_path = os.path.relpath(path, os.path.dirname(root_module.__file__))
+  full_path = os.path.join(root_module.__name__, relative_path)
+
+  # This normpath may collapse out the root module. This is generally OK as long
+  # as we stay within the workspace, as _env will add the workspace root to the
+  # system import path.
+  components = os.path.normpath(full_path).split(os.sep)
+  if module_name:
+    components.append(module_name)
+  full_package_name = '.'.join(components)
+  return importlib.import_module(full_package_name)
+
+
+def _GetPackageClass(platform_info):
+  """Loads the package class associated with the given platform.PlatformInfo."""
   try:
-    module = platform_info.ImportModule(starboard)
+    module = _ImportModule(platform_info.path, starboard)
   except ImportError as e:
     logging.debug('Failed to import module for platform %s with error: %s',
-                  platform_info.port_name, e)
+                  platform_info.name, e)
     return None
 
   if not hasattr(module, 'Package'):
@@ -48,8 +76,8 @@
     A dict of [platform_name, Class] where Class inherits from PackageBase
   """
   packager_modules = {}
-  for platform_info in platform.PlatformInfo.EnumeratePorts(
-      paths.STARBOARD_ROOT):
+  for platform_name in platform.GetAll():
+    platform_info = platform.Get(platform_name)
     # From the relative path to the starboard directory, construct a full
     # python package name and attempt to load it.
     package_class = _GetPackageClass(platform_info)
@@ -58,17 +86,17 @@
     # Populate a mapping from platform name to the module containing the
     # Package class.
     try:
-      for platform_name in package_class.SupportedPlatforms():
-        if platform_name in packager_modules:
+      for supported_name in package_class.SupportedPlatforms():
+        if supported_name in packager_modules:
           logging.warning('Packager for %s is defined in multiple modules.',
-                          platform_name)
+                          supported_name)
         else:
-          packager_modules[platform_name] = platform_info
+          packager_modules[supported_name] = platform_info
     except Exception as e:  # pylint: disable=broad-except
       # Catch all exceptions to avoid an error in one platform's Packager
       # halting the script for other platforms' packagers.
       logging.warning('Exception iterating supported platform for platform '
-                      '%s: %s.', platform_info.port_name, e)
+                      '%s: %s.', platform_info.name, e)
 
   return packager_modules
 
@@ -98,7 +126,7 @@
     This method can be overridden to implement platform-specific steps to
     install the package for that platform.
     """
-    pass
+    del targets
 
   @classmethod
   def AddArguments(cls, arg_parser):
@@ -109,7 +137,7 @@
     Args:
       arg_parser: An ArgumentParser object.
     """
-    pass
+    del cls, arg_parser
 
   @classmethod
   def ExtractArguments(cls, options):
@@ -123,6 +151,7 @@
     Returns:
       A dict of kwargs to be passed to the Package constructor.
     """
+    del cls, options
     return {}
 
 
@@ -139,6 +168,17 @@
   def GetPlatformInfo(self, platform_name):
     return self.platform_infos.get(platform_name, None)
 
+  def GetApplicationPackageInfo(self, platform_name, applciation_name):
+    """Get application-specific packaging information."""
+    platform_info = self.GetPlatformInfo(platform_name)
+    try:
+      return _ImportModule(platform_info.path, starboard,
+                           '%s.package' % applciation_name)
+    except ImportError as e:
+      # No package parameters specified for this platform.
+      logging.debug('Failed to import cobalt.package: %s', e)
+    return None
+
   def BuildPackage(self, platform_name, source_dir, output_dir, **kwargs):
     """Build a package for the specified platform.
 
@@ -160,4 +200,3 @@
   def ExtractPlatformArguments(self, platform_name, options):
     package_class = _GetPackageClass(self.platform_infos[platform_name])
     return package_class.ExtractArguments(options)
-
diff --git a/src/starboard/tools/platform.py b/src/starboard/tools/platform.py
index ca1723d..ed4e081 100644
--- a/src/starboard/tools/platform.py
+++ b/src/starboard/tools/platform.py
@@ -15,7 +15,6 @@
 #
 """Functionality to enumerate and represent starboard ports."""
 
-import importlib
 import logging
 import os
 import re
@@ -24,8 +23,8 @@
 from starboard.tools import environment
 
 # The list of files that must be present in a directory to allow it to be
-# considered a valid port.
-_PORT_FILES = [
+# considered a valid platform.
+_PLATFORM_FILES = [
     'gyp_configuration.gypi',
     'gyp_configuration.py',
     'starboard_platform.gyp',
@@ -35,116 +34,114 @@
 ]
 
 
-# Whether to emit warnings if it finds a directory that almost has a port.
+# Whether to emit warnings if it finds a directory that almost has a platform.
 # TODO: Enable when tree is clean.
-_WARN_ON_ALMOST_PORTS = False
+_WARN_ON_ALMOST = False
 
 
-def _IsValidPortFilenameList(directory, filenames):
+def _IsValidPlatformFilenameList(directory, filenames):
   """Determines if |filenames| contains the required files for a valid port."""
-  missing = set(_PORT_FILES) - set(filenames)
+  missing = set(_PLATFORM_FILES) - set(filenames)
   if missing:
-    if len(missing) < (len(_PORT_FILES) / 2) and _WARN_ON_ALMOST_PORTS:
-      logging.warning('Directory %s contains several files needed for a port, '
-                      'but not all of them. In particular, it is missing: %s',
-                      directory, ', '.join(missing))
+    if len(missing) < (len(_PLATFORM_FILES) / 2) and _WARN_ON_ALMOST:
+      logging.warning('Directory %s contains several files needed for a '
+                      'platform, but not all of them. In particular, it is '
+                      'missing: %s', directory, ', '.join(missing))
   return not missing
 
 
-def _GetPortName(root, directory):
-  """Gets the name of a port found at |directory| off of |root|."""
-
+def _GetPlatformName(root, directory):
+  """Gets the name of a platform found at |directory| off of |root|."""
   assert directory.startswith(root)
   start = len(root) + 1  # Remove the trailing slash from the root.
 
   assert start < len(directory)
 
-  # Calculate the name based on relative path from search root to port.
+  # Calculate the name based on relative path from search root to directory.
   return re.sub(r'[^a-zA-Z0-9_]', r'-', directory[start:])
 
 
-def _GetAllPlatforms(port_root_paths):
-  """Retrieves information about all available Cobalt ports.
+def _EnumeratePlatforms(root_path, exclusion_set=None):
+  """Generator that iterates over Starboard platforms found under |path|."""
+  if not exclusion_set:
+    exclusion_set = set()
 
-  Args:
-    port_root_paths:  List of paths that will be crawled to find ports.
+  for current_path, directories, filenames in os.walk(root_path):
+    # Don't walk into any directories in the exclusion set.
+    directories[:] = (x for x in directories
+                      if os.path.join(current_path, x) not in exclusion_set)
+
+    # Determine if the current directory is a valid port directory.
+    if _IsValidPlatformFilenameList(current_path, filenames):
+      if current_path == root_path:
+        logging.warning('Found platform at search path root: %s', current_path)
+      name = _GetPlatformName(root_path, current_path)
+      yield PlatformInfo(name, current_path)
+
+
+def _FindAllPlatforms():
+  """Search the filesystem for all valid Starboard platforms.
 
   Returns:
-    Dict mapping each available port to its location in the filesystem.
+    A Mapping of name->PlatformInfo.
   """
-  platform_dict = {}
-  for path in port_root_paths:
-    for port in PlatformInfo.EnumeratePorts(path):
-      platform_dict[port.port_name] = port.path
-  return platform_dict
+
+  result = {}
+  search_path = environment.GetStarboardPortRoots()
+
+  # Ignore search path directories inside other search path directories.
+  exclusion_set = set(search_path)
+
+  for entry in search_path:
+    if not os.path.isdir(entry):
+      continue
+    for platform_info in _EnumeratePlatforms(entry, exclusion_set):
+      if platform_info.name in result:
+        logging.error('Found duplicate port name "%s" at "%s" and "%s"',
+                      platform_info.name, result[platform_info.name],
+                      platform_info.path)
+      result[platform_info.name] = platform_info
+
+  return result
 
 
-def GetAllPorts():
-  """Gets all available starboard ports from the host app.
-
-  Returns:
-    Dictionary mapping port names to their path in the filesystem.
-  """
-  port_root_paths = environment.GetStarboardPortRoots()
-  return _GetAllPlatforms(port_root_paths)
+# Cache of name->PlatformInfo mapping.
+_INFO_MAP = None
 
 
-def GetAllNames():
-  """Gets a list of all valid Starboard platform names.
-
-  Returns:
-    List of valid platform names.
-  """
-  return sorted(GetAllPorts().keys())
+def _GetInfoMap():
+  """Gets mapping of platform names to PlatformInfo objects."""
+  global _INFO_MAP
+  if not _INFO_MAP:
+    _INFO_MAP = _FindAllPlatforms()
+  return _INFO_MAP
 
 
-def IsValid(platform):
-  return platform in GetAllNames()
+# Cache of the sorted list of all platform names.
+_ALL = None
+
+
+def GetAll():
+  """Gets a sorted list of all valid Starboard platform names."""
+  global _ALL
+  if not _ALL:
+    _ALL = sorted(_GetInfoMap().keys())
+  return _ALL
+
+
+def Get(platform_name):
+  """Gets the PlatformInfo for the given platform name, or None."""
+  return _GetInfoMap().get(platform_name)
+
+
+def IsValid(platform_name):
+  """Determines whether the given platform name is valid."""
+  return platform_name in _GetInfoMap()
 
 
 class PlatformInfo(object):
-  """Information about a specific starboard port."""
-
-  @classmethod
-  def EnumeratePorts(cls, root_path, exclusion_set=None):
-    """Generator that iterates over starboard ports found under |path|."""
-    if not exclusion_set:
-      exclusion_set = set()
-    for current_path, directories, filenames in os.walk(root_path):
-      # Don't walk into any directories in the exclusion set.
-      directories[:] = (x for x in directories
-                        if os.path.join(current_path, x) not in exclusion_set)
-      # Determine if the current directory is a valid port directory.
-      if _IsValidPortFilenameList(current_path, filenames):
-        if current_path == root_path:
-          logging.warning('Found port at search path root: %s', current_path)
-        port_name = _GetPortName(root_path, current_path)
-        yield PlatformInfo(port_name, current_path)
+  """Information about a specific Starboard platform."""
 
   def __init__(self, name, path):
-    self.port_name = name
+    self.name = name
     self.path = path
-
-  def ImportModule(self, root_module, module_name=None):
-    """Load a platform specific python module using importlib.
-
-    Load the python module named |module_name| relative to |root_module|.
-    Args:
-      root_module: An already-loaded module
-      module_name: Name of a python module to load. If None, load the platform
-          directory as a python module.
-    Returns:
-      A module loaded with importlib.import_module
-    Throws:
-      ImportError if the module fails to be loaded.
-    """
-    # From the relative path to the |root_module|'s directory, construct a full
-    # python package name and attempt to load it.
-    relative_path = os.path.relpath(
-        self.path, os.path.dirname(root_module.__file__))
-    components = os.path.normpath(relative_path).split(os.sep)
-    components = [root_module.__name__] + components
-    if module_name:
-      components.append(module_name)
-    full_package_name = '.'.join(components)
-    return importlib.import_module(full_package_name)
diff --git a/src/starboard/tools/platform_test.py b/src/starboard/tools/platform_test.py
new file mode 100755
index 0000000..35396b9
--- /dev/null
+++ b/src/starboard/tools/platform_test.py
@@ -0,0 +1,48 @@
+#!/usr/bin/env python
+#
+# Copyright 2017 Google Inc. All Rights Reserved.
+#
+# 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.
+#
+"""Tests the platform module."""
+
+import platform
+import unittest
+
+
+class PlatformTest(unittest.TestCase):
+
+  def testGetAll(self):
+    platform_names = platform.GetAll()
+    self.assertNotEqual(0, len(platform_names))
+
+  def testGet(self):
+    platform_names = platform.GetAll()
+    self.assertNotEqual(0, len(platform_names))
+    platform_name = platform_names[0]
+    platform_info = platform.Get(platform_name)
+    self.assertTrue(platform_info)
+    self.assertEqual(platform_name, platform_info.name)
+    self.assertTrue(platform_info.path)
+
+  def testIsValid(self):
+    platform_names = platform.GetAll()
+    for platform_name in platform_names:
+      self.assertTrue(platform.IsValid(platform_name))
+      self.assertTrue(platform.IsValid(platform_name.lower()))
+      self.assertFalse(platform.IsValid(platform_name.upper()))
+    self.assertFalse(platform.IsValid('invalidplatform'))
+
+
+if __name__ == '__main__':
+  unittest.main()
diff --git a/src/starboard/tools/testing/test_runner.py b/src/starboard/tools/testing/test_runner.py
index b931fae..d09aeb3 100644
--- a/src/starboard/tools/testing/test_runner.py
+++ b/src/starboard/tools/testing/test_runner.py
@@ -47,16 +47,11 @@
   in real time instead of dumping the test results all at once later.
   """
 
-  # Both ends of the pipe are provided here because the write end of
-  # the pipe needs to be closed when killing the thread. If it is not,
-  # the read call in _Readlines will block.
-  def __init__(self, read_pipe, write_pipe):
+  def __init__(self, read_pipe):
     self.read_pipe = read_pipe
-    self.write_pipe = write_pipe
     self.output_lines = cStringIO.StringIO()
     self.stop_event = threading.Event()
     self.reader_thread = threading.Thread(target=self._ReadLines)
-    self.reader_thread.start()
 
   def _ReadLines(self):
     """Continuously reads and stores lines of test output."""
@@ -64,23 +59,89 @@
       line = self.read_pipe.readline()
       if line:
         sys.stdout.write(line)
-        self.output_lines.write(line)
+      else:
+        break
+
+      self.output_lines.write(line)
+
+  def Start(self):
+    self.reader_thread.start()
 
   def Kill(self):
-    """Kills the thread reading lines from the launcher's output."""
+    """Kills the thread reading lines from the launcher's output.
+
+    This is only used on a manual exit to ensure that the thread exits cleanly;
+    in the normal case, the thread will exit on its own when no more lines of
+    output are available.
+    """
     self.stop_event.set()
 
-    # Close the write end of the pipe so that the read end gets EOF
-    self.write_pipe.close()
+  def Join(self):
     self.reader_thread.join()
     self.read_pipe.close()
 
   def GetLines(self):
     """Stops file reading, then returns stored output as a list of lines."""
-    self.Kill()
     return self.output_lines.getvalue().split("\n")
 
 
+class TestLauncher(object):
+  """Manages the thread that the test object runs in.
+
+  A separate thread is used to make it easier for the runner and reader to
+  communicate, and for the main thread to shut them down.
+  """
+
+  # The write end of the pipe is provided here because if the launcher
+  # errors out and fails to close it, it needs to be closed anyway.
+  def __init__(self, launcher, write_pipe):
+    self.launcher = launcher
+    self.write_pipe = write_pipe
+    self.runner_thread = threading.Thread(target=self._Run)
+
+    self.return_code_lock = threading.Lock()
+    self.return_code = 1
+
+  def Start(self):
+    self.runner_thread.start()
+
+  def Kill(self):
+    """Kills the running launcher."""
+    try:
+      self.launcher.Kill()
+    except Exception:
+      sys.stderr.write("Error while killing {}:\n".format(
+          self.launcher.target_name))
+      traceback.print_exc(file=sys.stderr)
+      # Close the write end of the pipe if the launcher errored out
+      # before closing it.
+      if not self.write_pipe.closed:
+        self.write_pipe.close()
+
+  def Join(self):
+    self.runner_thread.join()
+
+  def _Run(self):
+    """Runs the launcher, and assigns a return code."""
+    return_code = 1
+    try:
+      return_code = self.launcher.Run()
+    except Exception:
+      sys.stderr.write("Error while running {}:\n".format(
+          self.launcher.target_name))
+      traceback.print_exc(file=sys.stderr)
+
+    self.return_code_lock.acquire()
+    self.return_code = return_code
+    self.return_code_lock.release()
+
+  def GetReturnCode(self):
+    self.return_code_lock.acquire()
+    return_code = self.return_code
+    self.return_code_lock.release()
+    return return_code
+
+
 class TestRunner(object):
   """Runs unit tests."""
 
@@ -93,6 +154,7 @@
     self.out_directory = out_directory
     self._platform_config = abstract_launcher.GetGypModuleForPlatform(
         platform).CreatePlatformConfig()
+    self.threads = []
 
     # If a particular test binary has been provided, configure only that one.
     if single_target:
@@ -174,12 +236,6 @@
     """Gets all environment variables used for tests on the given platform."""
     return self._platform_config.GetTestEnvVariables()
 
-  def _BuildSystemInit(self):
-    """Runs GYP on the target platform/config."""
-    subprocess.check_call([os.path.abspath(os.path.join(
-        os.path.dirname(__file__), os.pardir, os.pardir, os.pardir,
-        "cobalt", "build", "gyp_cobalt")), self.platform])
-
   def _BuildTests(self, ninja_flags):
     """Builds all specified test binaries.
 
@@ -196,9 +252,12 @@
           self.platform, self.config)
 
     args_list = ["ninja", "-C", build_dir]
-    args_list.extend([test_name for test_name in self.test_targets])
+    args_list.extend([
+        "{}_deploy".format(test_name) for test_name in self.test_targets])
     if ninja_flags:
       args_list.append(ninja_flags)
+    if "TEST_RUNNER_BUILD_FLAGS" in os.environ:
+      args_list.append(os.environ["TEST_RUNNER_BUILD_FLAGS"])
     sys.stderr.write("{}\n".format(args_list))
     # We set shell=True because otherwise Windows doesn't recognize
     # PATH properly.
@@ -227,39 +286,38 @@
     write_pipe = os.fdopen(write_fd, "w")
 
     # Filter the specified tests for this platform, if any
+    test_params = []
     if self.test_targets[target_name]:
-      self.target_params.append("--gtest_filter=-{}".format(":".join(
+      test_params.append("--gtest_filter=-{}".format(":".join(
           self.test_targets[target_name])))
+    test_params.extend(self.target_params)
 
     launcher = abstract_launcher.LauncherFactory(
         self.platform, target_name, self.config,
-        device_id=self.device_id, target_params=self.target_params,
+        device_id=self.device_id, target_params=test_params,
         output_file=write_pipe, out_directory=self.out_directory,
         env_variables=env)
 
-    reader = TestLineReader(read_pipe, write_pipe)
-    #  If we need to manually exit the test runner at any point,
-    #  ensure that the launcher is killed properly first.
-    def Abort(signum, frame):
-      del signum, frame  # Unused.
-      launcher.Kill()
-      reader.Kill()
-      sys.stderr.write("TEST RUN STOPPED VIA MANUAL EXIT\n")
-      sys.exit(1)
+    test_reader = TestLineReader(read_pipe)
+    test_launcher = TestLauncher(launcher, write_pipe)
 
-    signal.signal(signal.SIGINT, Abort)
+    self.threads.append(test_launcher)
+    self.threads.append(test_reader)
+
     sys.stdout.write("Starting {}\n".format(target_name))
 
-    return_code = 1
-    try:
-      return_code = launcher.Run()
-    except Exception:  # pylint: disable=broad-except
-      sys.stderr.write("Error while running {}:\n".format(target_name))
-      traceback.print_exc(file=sys.stderr)
-    finally:
-      output = reader.GetLines()
+    test_reader.Start()
+    test_launcher.Start()
 
-    return self._CollectTestResults(output, target_name, return_code)
+    # If there are actives threads during a ctrl+c exit, they will join here.
+    test_launcher.Join()
+    test_reader.Join()
+
+    output = test_reader.GetLines()
+
+    self.threads = []
+    return self._CollectTestResults(output, target_name,
+                                    test_launcher.GetReturnCode())
 
   def _CollectTestResults(self, results, target_name, return_code):
     """Collects passing and failing tests for one test binary.
@@ -391,7 +449,6 @@
     result = True
 
     try:
-      self._BuildSystemInit()
       self._BuildTests(ninja_flags)
     except subprocess.CalledProcessError as e:
       result = False
@@ -430,6 +487,10 @@
       " If both the \"--build\" and \"--run\" flags are not"
       " provided, this is the default.")
   arg_parser.add_argument(
+      "-t",
+      "--target_name",
+      help="Name of executable target.")
+  arg_parser.add_argument(
       "--ninja_flags",
       help="Flags to pass to the ninja build system. Provide them exactly"
       " as you would on the command line between a set of double quotation"
@@ -444,6 +505,15 @@
 
   runner = TestRunner(args.platform, args.config, args.device_id,
                       args.target_name, target_params, args.out_directory)
+
+  def Abort(signum, frame):
+    del signum, frame  # Unused.
+    sys.stderr.write("Killing threads\n")
+    for active_thread in runner.threads:
+      active_thread.Kill()
+    sys.exit(1)
+
+  signal.signal(signal.SIGINT, Abort)
   # If neither build nor run has been specified, assume the client
   # just wants to run.
   if not args.build and not args.run:
diff --git a/src/starboard/tools/toolchain/common.py b/src/starboard/tools/toolchain/common.py
index 2e4faa0..4684652 100644
--- a/src/starboard/tools/toolchain/common.py
+++ b/src/starboard/tools/toolchain/common.py
@@ -96,7 +96,8 @@
     return 1
   elif sys.platform == 'darwin':
     try:
-      avail_bytes = int(subprocess.check_output(['sysctl', '-n', 'hw.memsize']))
+      avail_bytes = int(subprocess.check_output(['sysctl', '-n', 'hw.memsize'],
+                                                shell=True))
       # A static library debug build of Chromium's unit_tests takes ~2.7GB, so
       # 4GB per ld process allows for some more bloat.
       return max(1, avail_bytes / (4 * (2**30)))  # total / 4GB
diff --git a/src/starboard/tools/toolchain_deprecated.py b/src/starboard/tools/toolchain_deprecated.py
index 5400a1d..c8be4c7 100644
--- a/src/starboard/tools/toolchain_deprecated.py
+++ b/src/starboard/tools/toolchain_deprecated.py
@@ -4,40 +4,33 @@
 """Starboard's abstract Toolchain which is implemented for each platform."""
 
 import abc
-import imp
-import logging
-import os
-
-import starboard
-from starboard.tools import paths
-from starboard.tools import platform
 
 
 class ABCMetaSingleton(abc.ABCMeta):
   instances = {}
 
-  def __call__(self, *args, **kwargs):
-    if self not in self.instances:
-      self.instances[self] = super(ABCMetaSingleton, self).__call__(
+  def __call__(cls, *args, **kwargs):
+    if cls not in cls.instances:
+      cls.instances[cls] = super(ABCMetaSingleton, cls).__call__(
           *args, **kwargs)
-    return self.instances[self]
+    return cls.instances[cls]
 
 
 class Toolchain(object):
   """This is an abstract interface of the Toolchain."""
-  """ TODO: move variables / commands
-        AR / _HOST
-        ARFLAGS / _HOST
-        ARTHINFLAGS / _HOST
-        CC / CC_HOST
-        CXX / CXX_HOST
-        LD / LD_HOST
-        RC / RC_HOST
-     And / or implement NinjaWriter.WriteSources & GenerateOutputForConfig body
-     here.
-"""
   __metaclass__ = ABCMetaSingleton
 
+  # TODO: move variables / commands
+  #   AR / _HOST
+  #   ARFLAGS / _HOST
+  #   ARTHINFLAGS / _HOST
+  #   CC / CC_HOST
+  #   CXX / CXX_HOST
+  #   LD / LD_HOST
+  #   RC / RC_HOST
+  # And / or implement NinjaWriter.WriteSources & GenerateOutputForConfig body
+  # here.
+
   @abc.abstractmethod
   def Define(self, d):
     pass
@@ -85,6 +78,7 @@
 
 
 class PrecompiledHeader:
+  """Abstract precompiled header settings class."""
   __metaclass__ = abc.ABCMeta
 
   @abc.abstractmethod
@@ -163,4 +157,4 @@
 
   @abc.abstractmethod
   def ProcessLibraries(self, libraries, config_name):
-    pass
\ No newline at end of file
+    pass
diff --git a/src/starboard/win/shared/configuration_public.h b/src/starboard/win/shared/configuration_public.h
index 44e4ac9..dc4e2e1 100644
--- a/src/starboard/win/shared/configuration_public.h
+++ b/src/starboard/win/shared/configuration_public.h
@@ -116,7 +116,7 @@
 #define SB_HAS_SSIZE_T 0
 
 // Whether the current platform has microphone supported.
-#define SB_HAS_MICROPHONE 0
+#define SB_HAS_MICROPHONE 0 
 
 // Whether the current platform has speech synthesis.
 #define SB_HAS_SPEECH_SYNTHESIS 0
@@ -339,14 +339,6 @@
 
 // --- Media Configuration ---------------------------------------------------
 
-// Specifies whether this platform has support for a possibly-decrypting
-// elementary stream player for at least H.264/AAC (and AES-128-CTR, if
-// decrypting). A player is responsible for ingesting an audio and video
-// elementary stream, optionally-encrypted, and ultimately producing
-// synchronized audio/video. If a player is defined, it must choose one of the
-// supported composition methods below.
-#define SB_HAS_PLAYER 1
-
 // After a seek is triggerred, the default behavior is to append video frames
 // from the last key frame before the seek time and append audio frames from the
 // seek time because usually all audio frames are key frames.  On platforms that
diff --git a/src/starboard/win/shared/gyp_configuration.gypi b/src/starboard/win/shared/gyp_configuration.gypi
index c112351..410cb1c 100644
--- a/src/starboard/win/shared/gyp_configuration.gypi
+++ b/src/starboard/win/shared/gyp_configuration.gypi
@@ -24,6 +24,13 @@
 
     'cobalt_media_source_2016': 1,
 
+    # Note we must not use the default of 16.4 because win32 sleep
+    # rounds up to the next millisecond, and 17.0 is <60fps.
+    # Our rendering will be throttled appropriately by vsync with
+    # ANGLE/DirectX and thus we do not need to manually throttle
+    # our rendering with this.
+    'cobalt_minimum_frame_time_in_milliseconds': 0,
+
     # Platform-specific implementations to compile into cobalt.
     'cobalt_platform_dependencies': [
       '<(DEPTH)/starboard/egl_and_gles/egl_and_gles.gyp:egl_and_gles',
@@ -175,7 +182,7 @@
            },
            'VCLinkerTool': {
              'AdditionalDependencies': ['dbghelp.lib'],
-             'LinkIncremental': '2',  # INCREMENTAL:YES
+             'LinkIncremental': '1',  # INCREMENTAL:NO
            },
          },
        },
@@ -191,7 +198,7 @@
            },
            'VCLinkerTool': {
              'AdditionalDependencies': ['dbghelp.lib'],
-             'LinkIncremental': '2',  # INCREMENTAL:YES
+             'LinkIncremental': '1',  # INCREMENTAL:NO
            },
          },
        },
@@ -343,6 +350,8 @@
       4265,
       # Inconsistent DLL linkage
       4273,
+      # Double -> float truncation. Not enabled on other compilers.
+      4305,
       # cast truncates constant value.
       # We do not care.
       4310,
diff --git a/src/starboard/win/shared/starboard_platform.gypi b/src/starboard/win/shared/starboard_platform.gypi
index 84c3ed2..b2b8eb1 100644
--- a/src/starboard/win/shared/starboard_platform.gypi
+++ b/src/starboard/win/shared/starboard_platform.gypi
@@ -26,7 +26,6 @@
       '<(DEPTH)/starboard/shared/win32/log_file_impl.h',
       '<(DEPTH)/starboard/shared/win32/log_raw.cc',
       '<(DEPTH)/starboard/shared/win32/log_raw_format.cc',
-      '<(DEPTH)/starboard/shared/win32/media_is_video_supported.cc',
       '<(DEPTH)/starboard/shared/win32/playready_license.cc',
       '<(DEPTH)/starboard/shared/win32/starboard_main.cc',
       '<(DEPTH)/starboard/shared/win32/system_clear_platform_error.cc',
@@ -77,6 +76,7 @@
       '<(DEPTH)/starboard/shared/win32/media_foundation_utils.cc',
       '<(DEPTH)/starboard/shared/win32/media_foundation_utils.h',
       '<(DEPTH)/starboard/shared/win32/media_is_audio_supported.cc',
+      '<(DEPTH)/starboard/shared/win32/media_is_video_supported.cc',
       '<(DEPTH)/starboard/shared/win32/media_is_supported.cc',
       '<(DEPTH)/starboard/shared/win32/media_transform.cc',
       '<(DEPTH)/starboard/shared/win32/media_transform.h',
@@ -85,18 +85,8 @@
       '<(DEPTH)/starboard/shared/win32/simple_thread.h',
       '<(DEPTH)/starboard/shared/win32/video_decoder.cc',
       '<(DEPTH)/starboard/shared/win32/video_decoder.h',
-      '<(DEPTH)/starboard/shared/win32/video_decoder_thread.cc',
-      '<(DEPTH)/starboard/shared/win32/video_decoder_thread.h',
-      '<(DEPTH)/starboard/shared/win32/video_renderer.cc',
-      '<(DEPTH)/starboard/shared/win32/video_renderer.h',
-      '<(DEPTH)/starboard/shared/win32/video_texture.cc',
-      '<(DEPTH)/starboard/shared/win32/video_texture.h',
-      '<(DEPTH)/starboard/shared/win32/video_transform.cc',
-      '<(DEPTH)/starboard/shared/win32/video_transform.h',
       '<(DEPTH)/starboard/shared/win32/win32_audio_decoder.cc',
       '<(DEPTH)/starboard/shared/win32/win32_audio_decoder.h',
-      '<(DEPTH)/starboard/shared/win32/win32_video_decoder.cc',
-      '<(DEPTH)/starboard/shared/win32/win32_video_decoder.h',
     ],
     'win32_shared_media_player_files': [
       '<(DEPTH)/starboard/shared/starboard/media/codec_util.cc',
@@ -262,7 +252,6 @@
         '<(DEPTH)/starboard/shared/stub/cryptography_transform.cc',
         '<(DEPTH)/starboard/shared/stub/image_decode.cc',
         '<(DEPTH)/starboard/shared/stub/image_is_decode_supported.cc',
-        '<(DEPTH)/starboard/shared/stub/system_get_stack.cc',
         '<(DEPTH)/starboard/shared/stub/system_get_total_gpu_memory.cc',
         '<(DEPTH)/starboard/shared/stub/system_get_used_gpu_memory.cc',
         '<(DEPTH)/starboard/shared/stub/system_has_capability.cc',
@@ -350,6 +339,7 @@
         '<(DEPTH)/starboard/shared/win32/system_get_connection_type.cc',
         '<(DEPTH)/starboard/shared/win32/system_get_error_string.cc',
         '<(DEPTH)/starboard/shared/win32/system_get_number_of_processors.cc',
+        '<(DEPTH)/starboard/shared/win32/system_get_stack.cc',
         '<(DEPTH)/starboard/shared/win32/socket_set_broadcast.cc',
         '<(DEPTH)/starboard/shared/win32/socket_set_receive_buffer_size.cc',
         '<(DEPTH)/starboard/shared/win32/socket_set_reuse_address.cc',
diff --git a/src/starboard/win/win32/lib/gyp_configuration.gypi b/src/starboard/win/win32/lib/gyp_configuration.gypi
index 4e6657a..1c51d34 100644
--- a/src/starboard/win/win32/lib/gyp_configuration.gypi
+++ b/src/starboard/win/win32/lib/gyp_configuration.gypi
@@ -25,6 +25,7 @@
     'angle_build_winrt': 0,
     'winrt': 0,
     'enable_d3d11_feature_level_11': 1,
+    'cobalt_user_on_exit_strategy': 'noexit',
   },
   'includes': [
     '../../shared/gyp_configuration.gypi',
diff --git a/src/starboard/window.h b/src/starboard/window.h
index 370109e..b49ce58 100644
--- a/src/starboard/window.h
+++ b/src/starboard/window.h
@@ -131,6 +131,25 @@
 // |window|: The SbWindow to retrieve the platform handle for.
 SB_EXPORT void* SbWindowGetPlatformHandle(SbWindow window);
 
+#if SB_HAS(ON_SCREEN_KEYBOARD)
+// Determine if the on screen keyboard is shown.
+SB_EXPORT bool SbWindowIsOnScreenKeyboardShown(SbWindow window);
+
+// Show the on screen keyboard and populate the input with text |input_text|.
+// Fire kSbEventTypeWindowSizeChange if necessary. The passed in |input_text|
+// will never be NULL, but may be an empty string. Calling
+// SbWindowShowOnScreenKeyboard() when the keyboard is already shown is
+// permitted, and the input will be replaced with |input_text|.
+SB_EXPORT void SbWindowShowOnScreenKeyboard(SbWindow window,
+                                            const char* input_text);
+
+// Hide the on screen keyboard. Fire kSbEventTypeWindowSizeChange if necessary.
+// Calling SbWindowHideOnScreenKeyboard() when the keyboard is already hidden
+// is permitted.
+SB_EXPORT void SbWindowHideOnScreenKeyboard(SbWindow window);
+
+#endif  // SB_HAS(ON_SCREEN_KEYBOARD)
+
 #ifdef __cplusplus
 }  // extern "C"
 #endif
diff --git a/src/starboard_configuration.py b/src/starboard_configuration.py
index a6620e9..cf9eaf4 100644
--- a/src/starboard_configuration.py
+++ b/src/starboard_configuration.py
@@ -1,5 +1,3 @@
-#!/usr/bin/python
-#
 # 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
@@ -18,6 +16,7 @@
 # are relative to the location of this file.
 PORT_ROOTS = [
     ["starboard"],
+    ["starboard", "port"],
     ["third_party", "starboard"]
 ]
 
@@ -56,4 +55,4 @@
     'web_platform_tests',
     'webdriver_test',
     'xhr_test',
-]
\ No newline at end of file
+]
diff --git a/src/third_party/freetype2/src/cff/cffgload.c b/src/third_party/freetype2/src/cff/cffgload.c
index f7b5f9d..1b664c3 100644
--- a/src/third_party/freetype2/src/cff/cffgload.c
+++ b/src/third_party/freetype2/src/cff/cffgload.c
@@ -280,9 +280,11 @@
       {

         CFF_Internal  internal = (CFF_Internal)size->root.internal;

 

-

-        builder->hints_globals = (void *)internal->topfont;

-        builder->hints_funcs   = glyph->root.internal->glyph_hints;

+        if (internal)

+        {

+          builder->hints_globals = (void *)internal->topfont;

+          builder->hints_funcs   = glyph->root.internal->glyph_hints;

+        }

       }

     }

 

diff --git a/src/third_party/freetype2/src/psaux/psobjs.c b/src/third_party/freetype2/src/psaux/psobjs.c
index 2322667..3413da5 100644
--- a/src/third_party/freetype2/src/psaux/psobjs.c
+++ b/src/third_party/freetype2/src/psaux/psobjs.c
@@ -1718,6 +1718,14 @@
     first = outline->n_contours <= 1

             ? 0 : outline->contours[outline->n_contours - 2] + 1;

 

+    /* in malformed fonts it can happen that a contour was started */

+    /* but no points were added                                    */

+    if ( outline->n_contours && first == outline->n_points )

+    {

+      outline->n_contours--;

+      return;

+    }

+

     /* We must not include the last point in the path if it */

     /* is located on the first point.                       */

     if ( outline->n_points > 1 )

diff --git a/src/third_party/libwebp/libwebp.gyp b/src/third_party/libwebp/libwebp.gyp
index 353b472..d510bad 100644
--- a/src/third_party/libwebp/libwebp.gyp
+++ b/src/third_party/libwebp/libwebp.gyp
@@ -59,7 +59,8 @@
     {
       'target_name': 'libwebp_dsp_neon',
       'conditions': [
-        ['(target_arch == "arm" and arm_version >= 7) or (target_arch == "arm64")', {
+        # TODO: Fix problems building neon for device on tvOS.
+        ['((target_arch == "arm" and arm_version >= 7) or (target_arch == "arm64")) and (target_os != "tvos")', {
           'type': 'static_library',
           'include_dirs': ['.'],
           'sources': [
diff --git a/src/third_party/libxml/src/HTMLparser.c b/src/third_party/libxml/src/HTMLparser.c
index c7a0658..4421645 100644
--- a/src/third_party/libxml/src/HTMLparser.c
+++ b/src/third_party/libxml/src/HTMLparser.c
@@ -308,6 +308,7 @@
 #define UPP(val) (XML_TOUPPER(ctxt->input->cur[(val)]))
 
 #define CUR_PTR ctxt->input->cur
+#define BASE_PTR ctxt->input->base
 
 #define SHRINK if ((ctxt->input->cur - ctxt->input->base > 2 * INPUT_CHUNK) && \
 		   (ctxt->input->end - ctxt->input->cur < 2 * INPUT_CHUNK)) \
@@ -2480,6 +2481,10 @@
 	       (*in == '_') || (*in == '-') ||
 	       (*in == ':') || (*in == '.'))
 	    in++;
+
+    if (in == ctxt->input->end)
+        return(NULL);
+
 	if ((*in > 0) && (*in < 0x80)) {
 	    count = in - ctxt->input->cur;
 	    ret = xmlDictLookup(ctxt->dict, ctxt->input->cur, count);
@@ -2523,6 +2528,10 @@
 	NEXTL(l);
 	c = CUR_CHAR(l);
     }
+
+    if (ctxt->input->base > ctxt->input->cur - len)
+        return(NULL);
+
     return(xmlDictLookup(ctxt->dict, ctxt->input->cur - len, len));
 }
 
@@ -2774,31 +2783,43 @@
 
 static xmlChar *
 htmlParseSystemLiteral(htmlParserCtxtPtr ctxt) {
-    const xmlChar *q;
+    size_t len = 0, startPosition = 0;
     xmlChar *ret = NULL;
 
     if (CUR == '"') {
         NEXT;
-	q = CUR_PTR;
-	while ((IS_CHAR_CH(CUR)) && (CUR != '"'))
-	    NEXT;
+
+    if (CUR_PTR < BASE_PTR)
+        return(ret);
+    startPosition = CUR_PTR - BASE_PTR;
+
+    while ((IS_CHAR_CH(CUR)) && (CUR != '"')) {
+        NEXT;
+        len++;
+    }
+
 	if (!IS_CHAR_CH(CUR)) {
 	    htmlParseErr(ctxt, XML_ERR_LITERAL_NOT_FINISHED,
 			 "Unfinished SystemLiteral\n", NULL, NULL);
 	} else {
-	    ret = xmlStrndup(q, CUR_PTR - q);
+	    ret = xmlStrndup((BASE_PTR+startPosition), len);
 	    NEXT;
         }
     } else if (CUR == '\'') {
         NEXT;
-	q = CUR_PTR;
-	while ((IS_CHAR_CH(CUR)) && (CUR != '\''))
-	    NEXT;
+	if (CUR_PTR < BASE_PTR)
+        return(ret);
+    startPosition = CUR_PTR - BASE_PTR;
+
+    while ((IS_CHAR_CH(CUR)) && (CUR != '\'')) {
+        NEXT;
+        len++;
+    }
 	if (!IS_CHAR_CH(CUR)) {
 	    htmlParseErr(ctxt, XML_ERR_LITERAL_NOT_FINISHED,
 			 "Unfinished SystemLiteral\n", NULL, NULL);
 	} else {
-	    ret = xmlStrndup(q, CUR_PTR - q);
+	    ret = xmlStrndup((BASE_PTR+startPosition), len);
 	    NEXT;
         }
     } else {
@@ -2822,32 +2843,44 @@
 
 static xmlChar *
 htmlParsePubidLiteral(htmlParserCtxtPtr ctxt) {
-    const xmlChar *q;
+    size_t len = 0, startPosition = 0;
     xmlChar *ret = NULL;
     /*
      * Name ::= (Letter | '_') (NameChar)*
      */
     if (CUR == '"') {
+    NEXT;
+	if (CUR_PTR < BASE_PTR)
+        return(ret);
+    startPosition = CUR_PTR - BASE_PTR;
+
+    while (IS_PUBIDCHAR_CH(CUR)) {
+        len++;
         NEXT;
-	q = CUR_PTR;
-	while (IS_PUBIDCHAR_CH(CUR)) NEXT;
-	if (CUR != '"') {
-	    htmlParseErr(ctxt, XML_ERR_LITERAL_NOT_FINISHED,
-	                 "Unfinished PubidLiteral\n", NULL, NULL);
-	} else {
-	    ret = xmlStrndup(q, CUR_PTR - q);
-	    NEXT;
-	}
+    }
+
+    if (CUR != '"') {
+       htmlParseErr(ctxt, XML_ERR_LITERAL_NOT_FINISHED,
+                    "Unfinished PubidLiteral\n", NULL, NULL);
+    } else {
+       ret = xmlStrndup((BASE_PTR + startPosition), len);
+       NEXT;
+    }
     } else if (CUR == '\'') {
         NEXT;
-	q = CUR_PTR;
-	while ((IS_PUBIDCHAR_CH(CUR)) && (CUR != '\''))
-	    NEXT;
+	if (CUR_PTR < BASE_PTR)
+            return(ret);
+        startPosition = CUR_PTR - BASE_PTR;
+
+        while ((IS_PUBIDCHAR_CH(CUR)) && (CUR != '\'')){
+            len++;
+            NEXT;
+        }
 	if (CUR != '\'') {
 	    htmlParseErr(ctxt, XML_ERR_LITERAL_NOT_FINISHED,
 	                 "Unfinished PubidLiteral\n", NULL, NULL);
 	} else {
-	    ret = xmlStrndup(q, CUR_PTR - q);
+	    ret = xmlStrndup((BASE_PTR + startPosition), len);
 	    NEXT;
 	}
     } else {
diff --git a/src/third_party/libxml/src/buf.c b/src/third_party/libxml/src/buf.c
index 45ce2e8..bea9340 100644
--- a/src/third_party/libxml/src/buf.c
+++ b/src/third_party/libxml/src/buf.c
@@ -31,6 +31,7 @@
 #include <libxml/tree.h>
 #include <libxml/globals.h>
 #include <libxml/tree.h>
+#include <libxml/parserInternals.h> /* for XML_MAX_TEXT_LENGTH */
 #include "buf.h"
 
 #define WITH_BUFFER_COMPAT
@@ -303,7 +304,8 @@
     if ((scheme == XML_BUFFER_ALLOC_DOUBLEIT) ||
         (scheme == XML_BUFFER_ALLOC_EXACT) ||
         (scheme == XML_BUFFER_ALLOC_HYBRID) ||
-        (scheme == XML_BUFFER_ALLOC_IMMUTABLE)) {
+        (scheme == XML_BUFFER_ALLOC_IMMUTABLE) ||
+        (scheme == XML_BUFFER_ALLOC_BOUNDED)) {
 	buf->alloc = scheme;
         if (buf->buffer)
             buf->buffer->alloc = scheme;
@@ -462,6 +464,18 @@
     size = buf->use + len + 100;
 #endif
 
+    if (buf->alloc == XML_BUFFER_ALLOC_BOUNDED) {
+        /*
+    * Used to provide parsing limits
+    */
+    if ((buf->use + len >= XML_MAX_TEXT_LENGTH) ||
+        (buf->size >= XML_MAX_TEXT_LENGTH)) {
+        xmlBufMemoryError(buf, "buffer error: text too long\n");
+    return(0);
+    }
+    if (size >= XML_MAX_TEXT_LENGTH)
+       size = XML_MAX_TEXT_LENGTH;
+    }
     if ((buf->alloc == XML_BUFFER_ALLOC_IO) && (buf->contentIO != NULL)) {
         size_t start_buf = buf->content - buf->contentIO;
 
@@ -745,6 +759,15 @@
     CHECK_COMPAT(buf)
 
     if (buf->alloc == XML_BUFFER_ALLOC_IMMUTABLE) return(0);
+    if (buf->alloc == XML_BUFFER_ALLOC_BOUNDED) {
+    /*
+    * Used to provide parsing limits
+    */
+        if (size >= XML_MAX_TEXT_LENGTH) {
+       xmlBufMemoryError(buf, "buffer error: text too long\n");
+       return(0);
+    }
+    }
 
     /* Don't resize if we don't have to */
     if (size < buf->size)
@@ -873,6 +896,15 @@
 
     needSize = buf->use + len + 2;
     if (needSize > buf->size){
+        if (buf->alloc == XML_BUFFER_ALLOC_BOUNDED) {
+        /*
+        * Used to provide parsing limits
+        */
+        if (needSize >= XML_MAX_TEXT_LENGTH) {
+        xmlBufMemoryError(buf, "buffer error: text too long\n");
+        return(-1);
+        }
+        }
         if (!xmlBufResize(buf, needSize)){
 	    xmlBufMemoryError(buf, "growing buffer");
             return XML_ERR_NO_MEMORY;
@@ -944,6 +976,15 @@
     }
     needSize = buf->use + len + 2;
     if (needSize > buf->size){
+        if (buf->alloc == XML_BUFFER_ALLOC_BOUNDED) {
+            /*
+            * Used to provide parsing limits
+            */
+            if (needSize >= XML_MAX_TEXT_LENGTH) {
+            xmlBufMemoryError(buf, "buffer error: text too long\n");
+            return(-1);
+            }
+        }
         if (!xmlBufResize(buf, needSize)){
 	    xmlBufMemoryError(buf, "growing buffer");
             return XML_ERR_NO_MEMORY;
diff --git a/src/third_party/libxml/src/dict.c b/src/third_party/libxml/src/dict.c
index 9283778..72bf839 100644
--- a/src/third_party/libxml/src/dict.c
+++ b/src/third_party/libxml/src/dict.c
@@ -490,7 +490,10 @@
 	value += 30 * (*prefix);
 
     if (len > 10) {
-        value += name[len - (plen + 1 + 1)];
+        int offset = len - (plen + 1 + 1);
+        if (offset < 0)
+           offset = len - (10 + 1);
+        value += name[offset];
         len = 10;
 	if (plen > 10)
 	    plen = 10;
diff --git a/src/third_party/libxml/src/include/libxml/tree.h b/src/third_party/libxml/src/include/libxml/tree.h
index 53bd316..54c019f 100644
--- a/src/third_party/libxml/src/include/libxml/tree.h
+++ b/src/third_party/libxml/src/include/libxml/tree.h
@@ -76,11 +76,13 @@
  */
 
 typedef enum {
-    XML_BUFFER_ALLOC_DOUBLEIT,	/* double each time one need to grow */
-    XML_BUFFER_ALLOC_EXACT,	/* grow only to the minimal size */
-    XML_BUFFER_ALLOC_IMMUTABLE, /* immutable buffer */
-    XML_BUFFER_ALLOC_IO,	/* special allocation scheme used for I/O */
-    XML_BUFFER_ALLOC_HYBRID	/* exact up to a threshold, and doubleit thereafter */
+  XML_BUFFER_ALLOC_DOUBLEIT,  /* double each time one need to grow */
+  XML_BUFFER_ALLOC_EXACT,     /* grow only to the minimal size */
+  XML_BUFFER_ALLOC_IMMUTABLE, /* immutable buffer */
+  XML_BUFFER_ALLOC_IO,        /* special allocation scheme used for I/O */
+  XML_BUFFER_ALLOC_HYBRID,    /* exact up to a threshold, and doubleit thereafter
+                               */
+  XML_BUFFER_ALLOC_BOUNDED    /* limit the upper size of the buffer */
 } xmlBufferAllocationScheme;
 
 /**
diff --git a/src/third_party/libxml/src/include/libxml/xmlstring.h b/src/third_party/libxml/src/include/libxml/xmlstring.h
index 2036236..eeaacb9 100644
--- a/src/third_party/libxml/src/include/libxml/xmlstring.h
+++ b/src/third_party/libxml/src/include/libxml/xmlstring.h
@@ -97,7 +97,7 @@
 XMLPUBFUN int XMLCALL
                 xmlStrPrintf             (xmlChar *buf,
                                          int len,
-                                         const xmlChar *msg,
+                                         const char *msg,
                                          ...);
 XMLPUBFUN int XMLCALL
                 xmlStrVPrintf                (xmlChar *buf,
diff --git a/src/third_party/libxml/src/parser.c b/src/third_party/libxml/src/parser.c
index b9e55aa..f83e90e 100644
--- a/src/third_party/libxml/src/parser.c
+++ b/src/third_party/libxml/src/parser.c
@@ -100,6 +100,8 @@
 xmlCreateEntityParserCtxtInternal(const xmlChar *URL, const xmlChar *ID,
 	                  const xmlChar *base, xmlParserCtxtPtr pctx);
 
+static void xmlHaltParser(xmlParserCtxtPtr ctxt);
+
 /************************************************************************
  *									*
  *	Arbitrary limits set in the parser. See XML_PARSE_HUGE		*
@@ -348,7 +350,6 @@
 xmlFatalErr(xmlParserCtxtPtr ctxt, xmlParserErrors error, const char *info)
 {
     const char *errmsg;
-    char errstr[129] = "";
 
     if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
         (ctxt->instate == XML_PARSER_EOF))
@@ -535,15 +536,17 @@
         default:
             errmsg = "Unregistered error message";
     }
-    if (info == NULL)
-        XML_SNPRINTF(errstr, 128, "%s\n", errmsg);
-    else
-        XML_SNPRINTF(errstr, 128, "%s: %%s\n", errmsg);
     if (ctxt != NULL)
 	ctxt->errNo = error;
-    __xmlRaiseError(NULL, NULL, NULL, ctxt, NULL, XML_FROM_PARSER, error,
-                    XML_ERR_FATAL, NULL, 0, info, NULL, NULL, 0, 0, &errstr[0],
-                    info);
+    if (info == NULL) {
+        __xmlRaiseError(NULL, NULL, NULL, ctxt, NULL, XML_FROM_PARSER, error,
+                        XML_ERR_FATAL, NULL, 0, info, NULL, NULL, 0, 0, "%s\n",
+                        errmsg);
+    } else {
+        __xmlRaiseError(NULL, NULL, NULL, ctxt, NULL, XML_FROM_PARSER, error,
+                        XML_ERR_FATAL, NULL, 0, info, NULL, NULL, 0, 0, "%s: %s\n",
+                        errmsg, info);
+    }
     if (ctxt != NULL) {
 	ctxt->wellFormed = 0;
 	if (ctxt->recovery == 0)
@@ -559,7 +562,7 @@
  *
  * Handle a fatal parser error, i.e. violating Well-Formedness constraints
  */
-static void
+static void LIBXML_ATTR_FORMAT(3,0)
 xmlFatalErrMsg(xmlParserCtxtPtr ctxt, xmlParserErrors error,
                const char *msg)
 {
@@ -587,7 +590,7 @@
  *
  * Handle a warning.
  */
-static void
+static void LIBXML_ATTR_FORMAT(3,0)
 xmlWarningMsg(xmlParserCtxtPtr ctxt, xmlParserErrors error,
               const char *msg, const xmlChar *str1, const xmlChar *str2)
 {
@@ -625,7 +628,7 @@
  *
  * Handle a validity error.
  */
-static void
+static void LIBXML_ATTR_FORMAT(3,0)
 xmlValidityError(xmlParserCtxtPtr ctxt, xmlParserErrors error,
               const char *msg, const xmlChar *str1, const xmlChar *str2)
 {
@@ -665,7 +668,7 @@
  *
  * Handle a fatal parser error, i.e. violating Well-Formedness constraints
  */
-static void
+static void LIBXML_ATTR_FORMAT(3,0)
 xmlFatalErrMsgInt(xmlParserCtxtPtr ctxt, xmlParserErrors error,
                   const char *msg, int val)
 {
@@ -695,7 +698,7 @@
  *
  * Handle a fatal parser error, i.e. violating Well-Formedness constraints
  */
-static void
+static void LIBXML_ATTR_FORMAT(3,0)
 xmlFatalErrMsgStrIntStr(xmlParserCtxtPtr ctxt, xmlParserErrors error,
                   const char *msg, const xmlChar *str1, int val,
 		  const xmlChar *str2)
@@ -725,7 +728,7 @@
  *
  * Handle a fatal parser error, i.e. violating Well-Formedness constraints
  */
-static void
+static void LIBXML_ATTR_FORMAT(3,0)
 xmlFatalErrMsgStr(xmlParserCtxtPtr ctxt, xmlParserErrors error,
                   const char *msg, const xmlChar * val)
 {
@@ -754,7 +757,7 @@
  *
  * Handle a non fatal parser error
  */
-static void
+static void LIBXML_ATTR_FORMAT(3,0)
 xmlErrMsgStr(xmlParserCtxtPtr ctxt, xmlParserErrors error,
                   const char *msg, const xmlChar * val)
 {
@@ -779,7 +782,7 @@
  *
  * Handle a fatal parser error, i.e. violating Well-Formedness constraints
  */
-static void
+static void LIBXML_ATTR_FORMAT(3,0)
 xmlNsErr(xmlParserCtxtPtr ctxt, xmlParserErrors error,
          const char *msg,
          const xmlChar * info1, const xmlChar * info2,
@@ -808,7 +811,7 @@
  *
  * Handle a namespace warning error
  */
-static void
+static void LIBXML_ATTR_FORMAT(3,0)
 xmlNsWarn(xmlParserCtxtPtr ctxt, xmlParserErrors error,
          const char *msg,
          const xmlChar * info1, const xmlChar * info2,
@@ -2079,9 +2082,16 @@
          ((ctxt->input->buf) && (ctxt->input->buf->readcallback != (xmlInputReadCallback) xmlNop)) &&
         ((ctxt->options & XML_PARSE_HUGE) == 0)) {
         xmlFatalErr(ctxt, XML_ERR_INTERNAL_ERROR, "Huge input lookup");
-        ctxt->instate = XML_PARSER_EOF;
+        xmlHaltParser(ctxt);
+    return;
     }
     xmlParserInputGrow(ctxt->input, INPUT_CHUNK);
+    if ((ctxt->input->cur > ctxt->input->end) ||
+        (ctxt->input->cur < ctxt->input->base)) {
+        xmlHaltParser(ctxt);
+        xmlFatalErr(ctxt, XML_ERR_INTERNAL_ERROR, "cur index out of bound");
+    return;
+    }
     if ((ctxt->input->cur != NULL) && (*ctxt->input->cur == 0) &&
         (xmlParserInputGrow(ctxt->input, INPUT_CHUNK) <= 0))
 	    xmlPopInput(ctxt);
@@ -2812,6 +2822,10 @@
 			                      0, 0, 0);
 		ctxt->depth--;
 
+        if ((ctxt->lastError.code == XML_ERR_ENTITY_LOOP) ||
+            (ctxt->lastError.code == XML_ERR_INTERNAL_ERROR))
+            goto int_error;
+
 		if (rep != NULL) {
 		    current = rep;
 		    while (*current != 0) { /* non input consuming loop */
@@ -5481,7 +5495,7 @@
 	    skipped = SKIP_BLANKS;
 	    if (skipped == 0) {
 		xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
-			       "Space required after '%'\n");
+			       "Space required after '%%'\n");
 	    }
 	    isParameter = 1;
 	}
@@ -5666,6 +5680,7 @@
 	if (RAW != '>') {
 	    xmlFatalErrMsgStr(ctxt, XML_ERR_ENTITY_NOT_FINISHED,
 	            "xmlParseEntityDecl: entity %s not terminated\n", name);
+        xmlStopParser(ctxt);
 	} else {
 	    if (input != ctxt->input) {
 		xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_BOUNDARY,
@@ -6667,6 +6682,7 @@
 	if (!IS_BLANK_CH(CUR)) {
 	    xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
 		           "Space required after 'ELEMENT'\n");
+        return (-1);
 	}
         SKIP_BLANKS;
         name = xmlParseName(ctxt);
@@ -6777,6 +6793,8 @@
 	SKIP_BLANKS;
 	if (RAW != '[') {
 	    xmlFatalErr(ctxt, XML_ERR_CONDSEC_INVALID, NULL);
+        xmlStopParser(ctxt);
+        return;
 	} else {
 	    if (ctxt->input->id != id) {
 		xmlValidityError(ctxt, XML_ERR_ENTITY_BOUNDARY,
@@ -6816,6 +6834,7 @@
 
 	    if ((CUR_PTR == check) && (cons == ctxt->input->consumed)) {
 		xmlFatalErr(ctxt, XML_ERR_EXT_SUBSET_NOT_FINISHED, NULL);
+        xmlHaltParser(ctxt);
 		break;
 	    }
 	}
@@ -6837,6 +6856,8 @@
 	SKIP_BLANKS;
 	if (RAW != '[') {
 	    xmlFatalErr(ctxt, XML_ERR_CONDSEC_INVALID, NULL);
+        xmlStopParser(ctxt);
+        return;
 	} else {
 	    if (ctxt->input->id != id) {
 		xmlValidityError(ctxt, XML_ERR_ENTITY_BOUNDARY,
@@ -6892,6 +6913,8 @@
 
     } else {
 	xmlFatalErr(ctxt, XML_ERR_CONDSEC_INVALID_KEYWORD, NULL);
+    xmlStopParser(ctxt);
+    return;
     }
 
     if (RAW == 0)
@@ -6960,6 +6983,14 @@
 	    xmlParsePI(ctxt);
 	}
     }
+
+    /*
+     * detect requirement to exit there and act accordingly
+     * and avoid having instate overriden later on
+     */
+    if (ctxt->instate == XML_PARSER_EOF)
+        return;
+
     /*
      * This is only for internal subset. On external entities,
      * the replacement is done before parsing stage
@@ -7721,7 +7752,7 @@
      * not contain a <.
      */
     else if ((ctxt->instate == XML_PARSER_ATTRIBUTE_VALUE) &&
-	     (ent != NULL) && 
+	     (ent != NULL) &&
 	     (ent->etype != XML_INTERNAL_PREDEFINED_ENTITY)) {
 	if (((ent->checked & 1) || (ent->checked == 0)) &&
 	     (ent->content != NULL) && (xmlStrchr(ent->content, '<'))) {
@@ -8431,7 +8462,8 @@
      * We should be at the end of the DOCTYPE declaration.
      */
     if (RAW != '>') {
-	xmlFatalErr(ctxt, XML_ERR_DOCTYPE_NOT_FINISHED, NULL);
+        xmlFatalErr(ctxt, XML_ERR_DOCTYPE_NOT_FINISHED, NULL);
+        return;
     }
     NEXT;
 }
@@ -9764,6 +9796,7 @@
 xmlParseEndTag2(xmlParserCtxtPtr ctxt, const xmlChar *prefix,
                 const xmlChar *URI, int line, int nsNr, int tlen) {
     const xmlChar *name;
+    size_t curLength;
 
     GROW;
     if ((RAW != '<') || (NXT(1) != '/')) {
@@ -9772,8 +9805,11 @@
     }
     SKIP(2);
 
-    if ((tlen > 0) && (xmlStrncmp(ctxt->input->cur, ctxt->name, tlen) == 0)) {
-        if (ctxt->input->cur[tlen] == '>') {
+    curLength = ctxt->input->end - ctxt->input->cur;
+    if ((tlen > 0) && (curLength >= (size_t)tlen) &&
+        (xmlStrncmp(ctxt->input->cur, ctxt->name, tlen) == 0)) {
+        if ((curLength >= (size_t)(tlen + 1)) &&
+       (ctxt->input->cur[tlen] == '>')) {
 	    ctxt->input->cur += tlen + 1;
 	    ctxt->input->col += tlen + 1;
 	    goto done;
@@ -10467,7 +10503,11 @@
 
             handler = xmlFindCharEncodingHandler((const char *) encoding);
 	    if (handler != NULL) {
-		xmlSwitchToEncoding(ctxt, handler);
+		if (xmlSwitchToEncoding(ctxt, handler) < 0) {
+           /* failed to convert */
+           ctxt->errNo = XML_ERR_UNSUPPORTED_ENCODING;
+           return(NULL);
+        }
 	    } else {
 		xmlFatalErrMsgStr(ctxt, XML_ERR_UNSUPPORTED_ENCODING,
 			"Unsupported encoding %s\n", encoding);
@@ -10636,7 +10676,8 @@
 	xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED, "Blank needed here\n");
     }
     xmlParseEncodingDecl(ctxt);
-    if (ctxt->errNo == XML_ERR_UNSUPPORTED_ENCODING) {
+    if ((ctxt->errNo == XML_ERR_UNSUPPORTED_ENCODING) ||
+        (ctxt->instate == XML_PARSER_EOF)) {
 	/*
 	 * The XML REC instructs us to stop parsing right here
 	 */
@@ -10760,6 +10801,7 @@
 
     if (CUR == 0) {
 	xmlFatalErr(ctxt, XML_ERR_DOCUMENT_EMPTY, NULL);
+    return(-1);
     }
 
     /*
@@ -10777,7 +10819,8 @@
 	 * Note that we will switch encoding on the fly.
 	 */
 	xmlParseXMLDecl(ctxt);
-	if (ctxt->errNo == XML_ERR_UNSUPPORTED_ENCODING) {
+	if ((ctxt->errNo == XML_ERR_UNSUPPORTED_ENCODING) ||
+        (ctxt->instate == XML_PARSER_EOF)) {
 	    /*
 	     * The XML REC instructs us to stop parsing right here
 	     */
@@ -12586,6 +12629,33 @@
 #endif /* LIBXML_PUSH_ENABLED */
 
 /**
+ * xmlHaltParser:
+ * @ctxt:  an XML parser context
+ *
+ * Blocks further parser processing don't override error
+ * for internal use
+ */
+static void
+xmlHaltParser(xmlParserCtxtPtr ctxt) {
+    if (ctxt == NULL)
+        return;
+    ctxt->instate = XML_PARSER_EOF;
+    ctxt->disableSAX = 1;
+    if (ctxt->input != NULL) {
+        /*
+     * in case there was a specific allocation deallocate before
+     * overriding base
+     */
+        if (ctxt->input->free != NULL) {
+        ctxt->input->free((xmlChar *) ctxt->input->base);
+        ctxt->input->free = NULL;
+    }
+    ctxt->input->cur = BAD_CAST"";
+    ctxt->input->base = ctxt->input->cur;
+    }
+}
+
+/**
  * xmlStopParser:
  * @ctxt:  an XML parser context
  *
@@ -12595,13 +12665,8 @@
 xmlStopParser(xmlParserCtxtPtr ctxt) {
     if (ctxt == NULL)
         return;
-    ctxt->instate = XML_PARSER_EOF;
+    xmlHaltParser(ctxt);
     ctxt->errNo = XML_ERR_USER_STOP;
-    ctxt->disableSAX = 1;
-    if (ctxt->input != NULL) {
-	ctxt->input->cur = BAD_CAST"";
-	ctxt->input->base = ctxt->input->cur;
-    }
 }
 
 /**
diff --git a/src/third_party/libxml/src/parserInternals.c b/src/third_party/libxml/src/parserInternals.c
index f7770d9..43c3fb7 100644
--- a/src/third_party/libxml/src/parserInternals.c
+++ b/src/third_party/libxml/src/parserInternals.c
@@ -944,6 +944,7 @@
 {
     xmlCharEncodingHandlerPtr handler;
     int len = -1;
+    int ret;
 
     if (ctxt == NULL) return(-1);
     switch (enc) {
@@ -1104,7 +1105,15 @@
     if (handler == NULL)
 	return(-1);
     ctxt->charset = XML_CHAR_ENCODING_UTF8;
-    return(xmlSwitchToEncodingInt(ctxt, handler, len));
+    ret = xmlSwitchToEncodingInt(ctxt, handler, len);
+    if ((ret < 0) || (ctxt->errNo == XML_I18N_CONV_FAILED)) {
+        /*
+        * on encoding conversion errors, stop the parser
+        */
+        xmlStopParser(ctxt);
+    ctxt->errNo = XML_I18N_CONV_FAILED;
+    }
+    return(ret);
 }
 
 /**
diff --git a/src/third_party/libxml/src/runtest.c b/src/third_party/libxml/src/runtest.c
index 02fe09a..2170449 100644
--- a/src/third_party/libxml/src/runtest.c
+++ b/src/third_party/libxml/src/runtest.c
@@ -1827,7 +1827,7 @@
     ctxt = xmlCreatePushParserCtxt(NULL, NULL, base + cur, 4, filename);
     xmlCtxtUseOptions(ctxt, options);
     cur += 4;
-    while (cur < size) {
+    do {
         if (cur + 1024 >= size) {
 #ifdef LIBXML_HTML_ENABLED
 	    if (options & XML_PARSE_HTML)
@@ -1845,7 +1845,7 @@
 	    xmlParseChunk(ctxt, base + cur, 1024, 0);
 	    cur += 1024;
 	}
-    }
+    } while (cur < size);
     doc = ctxt->myDoc;
 #ifdef LIBXML_HTML_ENABLED
     if (options & XML_PARSE_HTML)
diff --git a/src/third_party/libxml/src/testModule.c b/src/third_party/libxml/src/testModule.c
index e399f5c..77b7ba1 100644
--- a/src/third_party/libxml/src/testModule.c
+++ b/src/third_party/libxml/src/testModule.c
@@ -47,7 +47,7 @@
 
     /* build the module filename, and confirm the module exists */
     xmlStrPrintf(filename, sizeof(filename),
-                 (const xmlChar*) "%s/testdso%s",
+                 "%s/testdso%s",
                  (const xmlChar*)MODULE_PATH,
 		 (const xmlChar*)LIBXML_MODULE_EXTENSION);
 
diff --git a/src/third_party/libxml/src/xmlIO.c b/src/third_party/libxml/src/xmlIO.c
index 797fb36..78ed0e3 100644
--- a/src/third_party/libxml/src/xmlIO.c
+++ b/src/third_party/libxml/src/xmlIO.c
@@ -1636,7 +1636,7 @@
 	xmlFreeZMemBuff( buff );
 	buff = NULL;
 	xmlStrPrintf(msg, 500,
-		    (const xmlChar *) "xmlCreateZMemBuff:  %s %d\n",
+		    "xmlCreateZMemBuff:  %s %d\n",
 		    "Error initializing compression context.  ZLIB error:",
 		    z_err );
 	xmlIOErr(XML_IO_WRITE, (const char *) msg);
diff --git a/src/third_party/libxml/src/xmlreader.c b/src/third_party/libxml/src/xmlreader.c
index e746519..e4b1e0b 100644
--- a/src/third_party/libxml/src/xmlreader.c
+++ b/src/third_party/libxml/src/xmlreader.c
@@ -2095,6 +2095,9 @@
 		"xmlNewTextReader : malloc failed\n");
 	return(NULL);
     }
+    /* no operation on a reader should require a huge buffer */
+    xmlBufSetAllocationScheme(ret->buffer,
+        XML_BUFFER_ALLOC_BOUNDED);
     ret->sax = (xmlSAXHandler *) xmlMalloc(sizeof(xmlSAXHandler));
     if (ret->sax == NULL) {
 	xmlBufFree(ret->buffer);
@@ -3620,6 +3623,7 @@
 	    return(((xmlNsPtr) node)->href);
         case XML_ATTRIBUTE_NODE:{
 	    xmlAttrPtr attr = (xmlAttrPtr) node;
+        const xmlChar *ret;
 
 	    if ((attr->children != NULL) &&
 	        (attr->children->type == XML_TEXT_NODE) &&
@@ -3633,10 +3637,21 @@
                                         "xmlTextReaderSetup : malloc failed\n");
                         return (NULL);
                     }
+                    xmlBufSetAllocationScheme(reader->buffer,
+                        XML_BUFFER_ALLOC_BOUNDED);
                 } else
                     xmlBufEmpty(reader->buffer);
 	        xmlBufGetNodeContent(reader->buffer, node);
-		return(xmlBufContent(reader->buffer));
+    		ret = xmlBufContent(reader->buffer);
+            if (ret == NULL) {
+               /* error on the buffer best to reallocate */
+               xmlBufFree(reader->buffer);
+               reader->buffer = xmlBufCreateSize(100);
+               xmlBufSetAllocationScheme(reader->buffer,
+                                         XML_BUFFER_ALLOC_BOUNDED);
+               ret = BAD_CAST "";
+            }
+            return(ret);
 	    }
 	    break;
 	}
@@ -5135,6 +5150,9 @@
                         "xmlTextReaderSetup : malloc failed\n");
         return (-1);
     }
+    /* no operation on a reader should require a huge buffer */
+    xmlBufSetAllocationScheme(reader->buffer,
+        XML_BUFFER_ALLOC_BOUNDED);
     if (reader->sax == NULL)
 	reader->sax = (xmlSAXHandler *) xmlMalloc(sizeof(xmlSAXHandler));
     if (reader->sax == NULL) {
diff --git a/src/third_party/libxml/src/xmlstring.c b/src/third_party/libxml/src/xmlstring.c
index 7b612bb..0a268fc 100644
--- a/src/third_party/libxml/src/xmlstring.c
+++ b/src/third_party/libxml/src/xmlstring.c
@@ -542,7 +542,7 @@
  * Returns the number of characters written to @buf or -1 if an error occurs.
  */
 int XMLCDECL
-xmlStrPrintf(xmlChar *buf, int len, const xmlChar *msg, ...) {
+xmlStrPrintf(xmlChar *buf, int len, const char *msg, ...) {
     va_list args;
     int ret;
 
diff --git a/src/third_party/libxml/src/xpath.c b/src/third_party/libxml/src/xpath.c
index 28d59a4..3f86055 100644
--- a/src/third_party/libxml/src/xpath.c
+++ b/src/third_party/libxml/src/xpath.c
@@ -641,7 +641,7 @@
             xmlChar buf[200];
 
             xmlStrPrintf(buf, 200,
-                         BAD_CAST "Memory allocation failed : %s\n",
+                         "Memory allocation failed : %s\n",
                          extra);
             ctxt->lastError.message = (char *) xmlStrdup(buf);
         } else {
diff --git a/src/third_party/openssl/openssl/crypto/asn1/a_type.c b/src/third_party/openssl/openssl/crypto/asn1/a_type.c
index 07164f1..2b84a77 100644
--- a/src/third_party/openssl/openssl/crypto/asn1/a_type.c
+++ b/src/third_party/openssl/openssl/crypto/asn1/a_type.c
@@ -129,9 +129,7 @@
         result = 0;             /* They do not have content. */
         break;
     case V_ASN1_INTEGER:
-    case V_ASN1_NEG_INTEGER:
     case V_ASN1_ENUMERATED:
-    case V_ASN1_NEG_ENUMERATED:
     case V_ASN1_BIT_STRING:
     case V_ASN1_OCTET_STRING:
     case V_ASN1_SEQUENCE:
diff --git a/src/third_party/openssl/openssl/crypto/asn1/tasn_dec.c b/src/third_party/openssl/openssl/crypto/asn1/tasn_dec.c
index 3dce02f..ee69b8f 100644
--- a/src/third_party/openssl/openssl/crypto/asn1/tasn_dec.c
+++ b/src/third_party/openssl/openssl/crypto/asn1/tasn_dec.c
@@ -906,9 +906,7 @@
         break;
 
     case V_ASN1_INTEGER:
-    case V_ASN1_NEG_INTEGER:
     case V_ASN1_ENUMERATED:
-    case V_ASN1_NEG_ENUMERATED:
         tint = (ASN1_INTEGER **)pval;
         if (!c2i_ASN1_INTEGER(tint, &cont, len))
             goto err;
diff --git a/src/third_party/openssl/openssl/crypto/asn1/tasn_enc.c b/src/third_party/openssl/openssl/crypto/asn1/tasn_enc.c
index 3ff086b..b257526 100644
--- a/src/third_party/openssl/openssl/crypto/asn1/tasn_enc.c
+++ b/src/third_party/openssl/openssl/crypto/asn1/tasn_enc.c
@@ -614,9 +614,7 @@
         break;
 
     case V_ASN1_INTEGER:
-    case V_ASN1_NEG_INTEGER:
     case V_ASN1_ENUMERATED:
-    case V_ASN1_NEG_ENUMERATED:
         /*
          * These are all have the same content format as ASN1_INTEGER
          */
diff --git a/src/third_party/openssl/openssl/crypto/bio/b_print.c b/src/third_party/openssl/openssl/crypto/bio/b_print.c
index a038966..5614ba9 100644
--- a/src/third_party/openssl/openssl/crypto/bio/b_print.c
+++ b/src/third_party/openssl/openssl/crypto/bio/b_print.c
@@ -73,9 +73,9 @@
 #include <ctype.h>
 #include <limits.h>
 #include <stdio.h>
-#include <string.h>
 #endif  // !defined(OPENSSL_SYS_STARBOARD)
 #include "cryptlib.h"
+#include <string.h>
 #ifndef NO_SYS_TYPES_H
 # include <sys/types.h>
 #endif
@@ -128,14 +128,14 @@
 # define LLONG long
 #endif
 
-static void fmtstr(char **, char **, size_t *, size_t *,
+static int fmtstr(char **, char **, size_t *, size_t *,
                    const char *, int, int, int);
-static void fmtint(char **, char **, size_t *, size_t *,
+static int fmtint(char **, char **, size_t *, size_t *,
                    LLONG, int, int, int, int);
-static void fmtfp(char **, char **, size_t *, size_t *,
+static int fmtfp(char **, char **, size_t *, size_t *,
                   LDOUBLE, int, int, int);
-static void doapr_outch(char **, char **, size_t *, size_t *, int);
-static void _dopr(char **sbuffer, char **buffer,
+static int doapr_outch(char **, char **, size_t *, size_t *, int);
+static int _dopr(char **sbuffer, char **buffer,
                   size_t *maxlen, size_t *retlen, int *truncated,
                   const char *format, va_list args);
 
@@ -168,7 +168,7 @@
 #define char_to_int(p) (p - '0')
 #define OSSL_MAX(p,q) ((p >= q) ? p : q)
 
-static void
+static int
 _dopr(char **sbuffer,
       char **buffer,
       size_t *maxlen,
@@ -199,7 +199,8 @@
             if (ch == '%')
                 state = DP_S_FLAGS;
             else
-                doapr_outch(sbuffer, buffer, &currlen, maxlen, ch);
+                if(!doapr_outch(sbuffer, buffer, &currlen, maxlen, ch))
+                    return 0;
             ch = *format++;
             break;
         case DP_S_FLAGS:
@@ -305,8 +306,9 @@
                     value = va_arg(args, int);
                     break;
                 }
-                fmtint(sbuffer, buffer, &currlen, maxlen,
-                       value, 10, min, max, flags);
+                if (!fmtint(sbuffer, buffer, &currlen, maxlen, value, 10, min,
+                            max, flags))
+                    return 0;
                 break;
             case 'X':
                 flags |= DP_F_UP;
@@ -329,17 +331,19 @@
                     value = (LLONG) va_arg(args, unsigned int);
                     break;
                 }
-                fmtint(sbuffer, buffer, &currlen, maxlen, value,
-                       ch == 'o' ? 8 : (ch == 'u' ? 10 : 16),
-                       min, max, flags);
+                if (!fmtint(sbuffer, buffer, &currlen, maxlen, value,
+                            ch == 'o' ? 8 : (ch == 'u' ? 10 : 16),
+                            min, max, flags))
+                    return 0;
                 break;
             case 'f':
                 if (cflags == DP_C_LDOUBLE)
                     fvalue = va_arg(args, LDOUBLE);
                 else
                     fvalue = va_arg(args, double);
-                fmtfp(sbuffer, buffer, &currlen, maxlen,
-                      fvalue, min, max, flags);
+                if (!fmtfp(sbuffer, buffer, &currlen, maxlen, fvalue, min, max,
+                           flags))
+                    return 0;
                 break;
             case 'E':
                 flags |= DP_F_UP;
@@ -358,8 +362,9 @@
                     fvalue = va_arg(args, double);
                 break;
             case 'c':
-                doapr_outch(sbuffer, buffer, &currlen, maxlen,
-                            va_arg(args, int));
+                if(!doapr_outch(sbuffer, buffer, &currlen, maxlen,
+                            va_arg(args, int)))
+                    return 0;
                 break;
             case 's':
                 strvalue = va_arg(args, char *);
@@ -369,13 +374,15 @@
                     else
                         max = *maxlen;
                 }
-                fmtstr(sbuffer, buffer, &currlen, maxlen, strvalue,
-                       flags, min, max);
+                if (!fmtstr(sbuffer, buffer, &currlen, maxlen, strvalue,
+                            flags, min, max))
+                    return 0;
                 break;
             case 'p':
                 value = (long)va_arg(args, void *);
-                fmtint(sbuffer, buffer, &currlen, maxlen,
-                       value, 16, min, max, flags | DP_F_NUM);
+                if (!fmtint(sbuffer, buffer, &currlen, maxlen,
+                            value, 16, min, max, flags | DP_F_NUM))
+                    return 0;
                 break;
             case 'n':          /* XXX */
                 if (cflags == DP_C_SHORT) {
@@ -397,7 +404,8 @@
                 }
                 break;
             case '%':
-                doapr_outch(sbuffer, buffer, &currlen, maxlen, ch);
+                if(!doapr_outch(sbuffer, buffer, &currlen, maxlen, ch))
+                    return 0;
                 break;
             case 'w':
                 /* not supported yet, treat as next char */
@@ -421,46 +429,56 @@
     *truncated = (currlen > *maxlen - 1);
     if (*truncated)
         currlen = *maxlen - 1;
-    doapr_outch(sbuffer, buffer, &currlen, maxlen, '\0');
+    if(!doapr_outch(sbuffer, buffer, &currlen, maxlen, '\0'))
+        return 0;
     *retlen = currlen - 1;
-    return;
+    return 1;
 }
 
-static void
+static int
 fmtstr(char **sbuffer,
        char **buffer,
        size_t *currlen,
        size_t *maxlen, const char *value, int flags, int min, int max)
 {
-    int padlen, strln;
+    int padlen;
+    size_t strln;
     int cnt = 0;
 
     if (value == 0)
         value = "<NULL>";
-    for (strln = 0; value[strln]; ++strln) ;
+
+    strln = strlen(value);
+    if (strln > INT_MAX)
+        strln = INT_MAX;
+
     padlen = min - strln;
-    if (padlen < 0)
+    if (min<0 || padlen < 0)
         padlen = 0;
     if (flags & DP_F_MINUS)
         padlen = -padlen;
 
     while ((padlen > 0) && (cnt < max)) {
-        doapr_outch(sbuffer, buffer, currlen, maxlen, ' ');
+        if(!doapr_outch(sbuffer, buffer, currlen, maxlen, ' '))
+            return 0;
         --padlen;
         ++cnt;
     }
     while (*value && (cnt < max)) {
-        doapr_outch(sbuffer, buffer, currlen, maxlen, *value++);
+        if(!doapr_outch(sbuffer, buffer, currlen, maxlen, *value++))
+            return 0;
         ++cnt;
     }
     while ((padlen < 0) && (cnt < max)) {
-        doapr_outch(sbuffer, buffer, currlen, maxlen, ' ');
+        if(!doapr_outch(sbuffer, buffer, currlen, maxlen, ' '))
+            return 0;
         ++padlen;
         ++cnt;
     }
+    return 1;
 }
 
-static void
+static int
 fmtint(char **sbuffer,
        char **buffer,
        size_t *currlen,
@@ -520,37 +538,44 @@
 
     /* spaces */
     while (spadlen > 0) {
-        doapr_outch(sbuffer, buffer, currlen, maxlen, ' ');
+        if(!doapr_outch(sbuffer, buffer, currlen, maxlen, ' '))
+            return 0;
         --spadlen;
     }
 
     /* sign */
     if (signvalue)
-        doapr_outch(sbuffer, buffer, currlen, maxlen, signvalue);
+        if(!doapr_outch(sbuffer, buffer, currlen, maxlen, signvalue))
+            return 0;
 
     /* prefix */
     while (*prefix) {
-        doapr_outch(sbuffer, buffer, currlen, maxlen, *prefix);
+        if(!doapr_outch(sbuffer, buffer, currlen, maxlen, *prefix))
+            return 0;
         prefix++;
     }
 
     /* zeros */
     if (zpadlen > 0) {
         while (zpadlen > 0) {
-            doapr_outch(sbuffer, buffer, currlen, maxlen, '0');
+            if(!doapr_outch(sbuffer, buffer, currlen, maxlen, '0'))
+                return 0;
             --zpadlen;
         }
     }
     /* digits */
-    while (place > 0)
-        doapr_outch(sbuffer, buffer, currlen, maxlen, convert[--place]);
+    while (place > 0) {
+        if (!doapr_outch(sbuffer, buffer, currlen, maxlen, convert[--place]))
+            return 0;
+    }
 
     /* left justified spaces */
     while (spadlen < 0) {
-        doapr_outch(sbuffer, buffer, currlen, maxlen, ' ');
+        if (!doapr_outch(sbuffer, buffer, currlen, maxlen, ' '))
+            return 0;
         ++spadlen;
     }
-    return;
+    return 1;
 }
 
 static LDOUBLE abs_val(LDOUBLE value)
@@ -581,7 +606,7 @@
     return intpart;
 }
 
-static void
+static int
 fmtfp(char **sbuffer,
       char **buffer,
       size_t *currlen,
@@ -660,47 +685,62 @@
 
     if ((flags & DP_F_ZERO) && (padlen > 0)) {
         if (signvalue) {
-            doapr_outch(sbuffer, buffer, currlen, maxlen, signvalue);
+            if (!doapr_outch(sbuffer, buffer, currlen, maxlen, signvalue))
+                return 0;
             --padlen;
             signvalue = 0;
         }
         while (padlen > 0) {
-            doapr_outch(sbuffer, buffer, currlen, maxlen, '0');
+            if (!doapr_outch(sbuffer, buffer, currlen, maxlen, '0'))
+                return 0;
             --padlen;
         }
     }
     while (padlen > 0) {
-        doapr_outch(sbuffer, buffer, currlen, maxlen, ' ');
+        if (!doapr_outch(sbuffer, buffer, currlen, maxlen, ' '))
+            return 0;
         --padlen;
     }
     if (signvalue)
-        doapr_outch(sbuffer, buffer, currlen, maxlen, signvalue);
+        if (!doapr_outch(sbuffer, buffer, currlen, maxlen, signvalue))
+            return 0;
 
-    while (iplace > 0)
-        doapr_outch(sbuffer, buffer, currlen, maxlen, iconvert[--iplace]);
+    while (iplace > 0){
+        if (!doapr_outch(sbuffer, buffer, currlen, maxlen, iconvert[--iplace]))
+            return 0;
+    }
 
     /*
      * Decimal point. This should probably use locale to find the correct
      * char to print out.
      */
     if (max > 0 || (flags & DP_F_NUM)) {
-        doapr_outch(sbuffer, buffer, currlen, maxlen, '.');
+        if (!doapr_outch(sbuffer, buffer, currlen, maxlen, '.'))
+            return 0;
 
-        while (fplace > 0)
-            doapr_outch(sbuffer, buffer, currlen, maxlen, fconvert[--fplace]);
+        while (fplace > 0) {
+            if(!doapr_outch(sbuffer, buffer, currlen, maxlen,
+                            fconvert[--fplace]))
+                return 0;
+        }
     }
     while (zpadlen > 0) {
-        doapr_outch(sbuffer, buffer, currlen, maxlen, '0');
+        if (!doapr_outch(sbuffer, buffer, currlen, maxlen, '0'))
+            return 0;
         --zpadlen;
     }
 
     while (padlen < 0) {
-        doapr_outch(sbuffer, buffer, currlen, maxlen, ' ');
+        if (!doapr_outch(sbuffer, buffer, currlen, maxlen, ' '))
+            return 0;
         ++padlen;
     }
+    return 1;
 }
 
-static void
+#define BUFFER_INC  1024
+
+static int
 doapr_outch(char **sbuffer,
             char **buffer, size_t *currlen, size_t *maxlen, int c)
 {
@@ -711,24 +751,25 @@
     OPENSSL_port_assert(*currlen <= *maxlen);
 
     if (buffer && *currlen == *maxlen) {
-        *maxlen += 1024;
+        if (*maxlen > INT_MAX - BUFFER_INC)
+            return 0;
+
+        *maxlen += BUFFER_INC;
         if (*buffer == NULL) {
             *buffer = OPENSSL_malloc(*maxlen);
-            if (!*buffer) {
-                /* Panic! Can't really do anything sensible. Just return */
-                return;
-            }
+            if (*buffer == NULL)
+                return 0;
             if (*currlen > 0) {
                 OPENSSL_port_assert(*sbuffer != NULL);
                 OPENSSL_port_memcpy(*buffer, *sbuffer, *currlen);
             }
             *sbuffer = NULL;
         } else {
-            *buffer = OPENSSL_realloc(*buffer, *maxlen);
-            if (!*buffer) {
-                /* Panic! Can't really do anything sensible. Just return */
-                return;
-            }
+            char *tmpbuf;
+            tmpbuf = OPENSSL_realloc(*buffer, *maxlen);
+            if (tmpbuf == NULL)
+                return 0;
+            *buffer = tmpbuf;
         }
     }
 
@@ -739,7 +780,7 @@
             (*buffer)[(*currlen)++] = (char)c;
     }
 
-    return;
+    return 1;
 }
 
 /***************************************************************************/
@@ -771,7 +812,11 @@
 
     dynbuf = NULL;
     CRYPTO_push_info("doapr()");
-    _dopr(&hugebufp, &dynbuf, &hugebufsize, &retlen, &ignored, format, args);
+    if (!_dopr(&hugebufp, &dynbuf, &hugebufsize, &retlen, &ignored, format,
+                args)) {
+        OPENSSL_free(dynbuf);
+        return -1;
+    }
     if (dynbuf) {
         ret = BIO_write(bio, dynbuf, (int)retlen);
         OPENSSL_free(dynbuf);
@@ -806,7 +851,8 @@
     size_t retlen;
     int truncated;
 
-    _dopr(&buf, NULL, &n, &retlen, &truncated, format, args);
+    if(!_dopr(&buf, NULL, &n, &retlen, &truncated, format, args))
+        return -1;
 
     if (truncated)
         /*
diff --git a/src/third_party/openssl/openssl/crypto/mdc2/mdc2dgst.c b/src/third_party/openssl/openssl/crypto/mdc2/mdc2dgst.c
index 6615cf8..2dce493 100644
--- a/src/third_party/openssl/openssl/crypto/mdc2/mdc2dgst.c
+++ b/src/third_party/openssl/openssl/crypto/mdc2/mdc2dgst.c
@@ -91,7 +91,7 @@
 
     i = c->num;
     if (i != 0) {
-        if (i + len < MDC2_BLOCK) {
+        if (len < MDC2_BLOCK - i) {
             /* partial block */
             memcpy(&(c->data[i]), in, len);
             c->num += (int)len;
diff --git a/src/third_party/skia/src/gpu/GrAAConvexPathRenderer.cpp b/src/third_party/skia/src/gpu/GrAAConvexPathRenderer.cpp
index dc74459..3551311 100644
--- a/src/third_party/skia/src/gpu/GrAAConvexPathRenderer.cpp
+++ b/src/third_party/skia/src/gpu/GrAAConvexPathRenderer.cpp
@@ -249,7 +249,6 @@
         segments->back().fType = Segment::kQuad;
         segments->back().fPts[0] = pts[1];
         segments->back().fPts[1] = pts[2];
-        SkASSERT(contains_inclusive(*devBounds, pts[0]));
         devBounds->growToInclude(pts + 1, 2);
     }
 }
diff --git a/src/tools/gyp/pylib/gyp/input.py b/src/tools/gyp/pylib/gyp/input.py
index 38b75c9..e60d9ba 100755
--- a/src/tools/gyp/pylib/gyp/input.py
+++ b/src/tools/gyp/pylib/gyp/input.py
@@ -25,6 +25,9 @@
 from gyp.common import GypError
 
 
+_DEBUG_DEPTH = False
+
+
 # A list of types that are treated as linkable.
 linkable_types = ['executable', 'shared_library', 'loadable_module']
 
@@ -212,7 +215,7 @@
 
 
 def LoadOneBuildFile(build_file_path, data, aux_data, variables, includes,
-                     is_target, check):
+                     is_target, depth, check):
   if build_file_path in data:
     return data[build_file_path]
 
@@ -242,10 +245,10 @@
   try:
     if is_target:
       LoadBuildFileIncludesIntoDict(build_file_data, build_file_path, data,
-                                    aux_data, variables, includes, check)
+                                    aux_data, variables, includes, depth, check)
     else:
       LoadBuildFileIncludesIntoDict(build_file_data, build_file_path, data,
-                                    aux_data, variables, None, check)
+                                    aux_data, variables, None, depth, check)
   except Exception, e:
     gyp.common.ExceptionAppend(e,
                                'while reading includes of ' + build_file_path)
@@ -255,7 +258,7 @@
 
 
 def LoadBuildFileIncludesIntoDict(subdict, subdict_path, data, aux_data,
-                                  variables, includes, check):
+                                  variables, includes, depth, check):
   includes_list = []
   if includes != None:
     includes_list.extend(includes)
@@ -280,31 +283,34 @@
 
     gyp.DebugOutput(gyp.DEBUG_INCLUDES, "Loading Included File: '%s'" % include)
 
+    old_depth_source = variables['__DEPTH_SOURCE__']
+    _UpdateDepth(depth, include, variables)
     MergeDicts(subdict,
-               LoadOneBuildFile(include, data, aux_data, variables, None,
-                                False, check),
+               LoadOneBuildFile(include, data, aux_data, variables,
+                                None, False, depth, check),
                subdict_path, include)
+    _UpdateDepth(depth, old_depth_source, variables)
 
   # Recurse into subdictionaries.
   for k, v in subdict.iteritems():
     if v.__class__ == dict:
       LoadBuildFileIncludesIntoDict(v, subdict_path, data, aux_data, variables,
-                                    None, check)
+                                    None, depth, check)
     elif v.__class__ == list:
       LoadBuildFileIncludesIntoList(v, subdict_path, data, aux_data, variables,
-                                    check)
+                                    depth, check)
 
 
 # This recurses into lists so that it can look for dicts.
 def LoadBuildFileIncludesIntoList(sublist, sublist_path, data, aux_data,
-                                  variables, check):
+                                  variables, depth, check):
   for item in sublist:
     if item.__class__ == dict:
       LoadBuildFileIncludesIntoDict(item, sublist_path, data, aux_data,
-                                    variables, None, check)
+                                    variables, None, depth, check)
     elif item.__class__ == list:
       LoadBuildFileIncludesIntoList(item, sublist_path, data, aux_data,
-                                    variables, check)
+                                    variables, depth, check)
 
 # Processes toolsets in all the targets. This recurses into condition entries
 # since they can contain toolsets as well.
@@ -341,11 +347,7 @@
           ProcessToolsetsInDict(condition_dict)
 
 
-# TODO(mark): I don't love this name.  It just means that it's going to load
-# a build file that contains targets and is expected to provide a targets dict
-# that contains the targets...
-def LoadTargetBuildFile(build_file_path, data, aux_data, variables, includes,
-                        depth, check, load_dependencies):
+def _UpdateDepth(depth, build_file_path, variables):
   # If depth is set, predefine the DEPTH variable to be a relative path from
   # this build file's directory to the directory identified by depth.
   if depth:
@@ -357,6 +359,20 @@
       variables['DEPTH'] = '.'
     else:
       variables['DEPTH'] = d.replace('\\', '/')
+    variables['__DEPTH_SOURCE__'] = build_file_path
+    if _DEBUG_DEPTH:
+      print '%s: %s -> DEPTH, %s -> __DEPTH_SOURCE__' % (
+          os.path.basename(build_file_path),
+          variables['DEPTH'],
+          os.path.basename(variables['__DEPTH_SOURCE__']))
+
+
+# TODO(mark): I don't love this name.  It just means that it's going to load
+# a build file that contains targets and is expected to provide a targets dict
+# that contains the targets...
+def LoadTargetBuildFile(build_file_path, data, aux_data, variables, includes,
+                        depth, check, load_dependencies):
+  _UpdateDepth(depth, build_file_path, variables)
 
   # If the generator needs absolue paths, then do so.
   if absolute_build_file_paths:
@@ -371,7 +387,7 @@
                   "Loading Target Build File '%s'" % build_file_path)
 
   build_file_data = LoadOneBuildFile(build_file_path, data, aux_data, variables,
-                                     includes, True, check)
+                                     includes, True, depth, check)
 
   # Store DEPTH for later use in generators.
   build_file_data['_DEPTH'] = depth
@@ -938,7 +954,14 @@
                          ' in ' + build_file)
       else:
         replacement = variables[contents]
-
+    if _DEBUG_DEPTH:
+      if build_file != variables['__DEPTH_SOURCE__']:
+        print '%s != %s' % (build_file, variables['__DEPTH_SOURCE__'])
+      print '%s(%s): %s -> %s' % (
+          os.path.basename(build_file),
+          os.path.basename(variables['__DEPTH_SOURCE__']),
+          contents,
+          replacement)
     if isinstance(replacement, list):
       for item in replacement:
         if (not contents[-1] == '/' and
diff --git a/src/ui/gfx/rect.h b/src/ui/gfx/rect.h
index c2ee999..c2c2538 100644
--- a/src/ui/gfx/rect.h
+++ b/src/ui/gfx/rect.h
@@ -25,6 +25,7 @@
 // Introduce cobalt::math::Rect into namespace gfx as gfx::Rect is used by

 // media.

 using cobalt::math::Rect;

+using cobalt::math::RectF;

 

 }  // namespace gfx