Import Cobalt 2.10060 2016-08-29
diff --git a/codereview.settings b/codereview.settings
new file mode 100644
index 0000000..1950c32
--- /dev/null
+++ b/codereview.settings
@@ -0,0 +1,3 @@
+GERRIT_HOST: cobalt-review.googlesource.com
+GERRIT_AUTODETECT_BRANCH: true
+CODE_REVIEW_SERVER: cobalt-review.googlesource.com
diff --git a/src/CONTRIBUTING.md b/src/CONTRIBUTING.md
new file mode 100644
index 0000000..bd99ed6
--- /dev/null
+++ b/src/CONTRIBUTING.md
@@ -0,0 +1,62 @@
+# Contributing to Cobalt
+
+We'd love to hear about how you would like to contribute to Cobalt! It's worth
+reading through this modest document first, to understand the process and to
+make sure you know what to expect.
+
+
+## Before You Contribute
+
+### As an Individual
+
+Before Cobalt can use your code, as an unaffiliated individual, you must sign
+the [Google Individual Contributor License Agreement](https://cla.developers.google.com/about/google-individual) (CLA), which you can do online.
+
+### As a Company
+
+If you are a company that wishes to have one or more employees contribute to
+Cobalt on-the-clock, that is covered by a different agreement, the
+[Software Grant and Corporate Contributor License Agreement](https://cla.developers.google.com/about/google-corporate).
+
+### What is a CLA?
+
+The Contributor License Agreement is necessary mainly because you own the
+copyright to your changes, even after your contribution becomes part of our
+codebase, so we need your permission to use and distribute your code. We also
+need to be sure of various other things — for instance that you'll tell us if
+you know that your code infringes on other people's patents. You don't have to
+sign the CLA until after you've submitted your code for review and a member has
+approved it, but you must do it before we can put your code into our codebase.
+Before you start working on a larger contribution, you should get in touch with
+us first with your idea so that we can help out and possibly guide
+you. Coordinating up front makes it much easier to avoid frustration later on.
+
+
+### Code Reviews
+
+All submissions, including submissions by project members, require review. We
+currently use [Gerrit Code Review](https://www.gerritcodereview.com/) for this
+purpose. Currently, team-member submissions go through private reviews, and
+external submissions go through public reviews.
+
+
+## Submission Process
+
+We admit that this submission process is currently not completely optimized to
+make contributions easy, and we hope to make improvements to it in the
+future. It will always include some form of signing the CLA and submitting the
+code for review before merging changes into the Cobalt master tree.
+
+  1. Ensure you or your company have signed the appropriate CLA (see "Before You
+     Contribute" above).
+  1. Rebase your changes down into a single git commit.
+  1. Run `git cl upload` to upload the review to
+     [Cobalt's Gerrit instance](https://cobalt-review.googlesource.com/).
+  1. Someone from the maintainers team will review the code, putting up comments
+     on any things that need to change for submission.
+  1. If you need to make changes, make them locally, test them, then `git commit
+     --amend` to add them to the *existing* commit. Then return to step 2.
+  1. If you do not need to make any more changes, a maintainer will integrate
+     the change into our private repository, and it will get pushed out to the
+     public repository after some time.
+
diff --git a/src/README.cobalt.txt b/src/README.cobalt.txt
deleted file mode 100644
index bc2d9c7..0000000
--- a/src/README.cobalt.txt
+++ /dev/null
@@ -1,2 +0,0 @@
-This is a fork of the chromium repository at http://git.chromium.org/git/chromium.git
-
diff --git a/src/README.md b/src/README.md
index fb912c9..025610b 100644
--- a/src/README.md
+++ b/src/README.md
@@ -241,12 +241,12 @@
 optimized, with the most debug information at the top (debug) to the fastest,
 most optimized, and with the least debug information at the bottom (gold):
 
- | Type  | Optimizations | Logging | Asserts | Debug Info | Console  |
- | :---- | :------------ | :------ | :------ | :--------- | :------- |
- | debug | None          | Full    | Full    | Full       | Enabled  |
- | devel | Full          | Full    | Full    | Full       | Enabled  |
- | qa    | Full          | Limited | None    | None       | Enabled  |
- | gold  | Full          | None    | None    | None       | Disabled |
+ Type  | Optimizations | Logging | Asserts | Debug Info | Console
+ :---- | :------------ | :------ | :------ | :--------- | :-------
+ debug | None          | Full    | Full    | Full       | Enabled
+ devel | Full          | Full    | Full    | Full       | Enabled
+ qa    | Full          | Limited | None    | None       | Enabled
+ gold  | Full          | None    | None    | None       | Disabled
 
 When building for release, you should always use a gold build for the final
 product.
@@ -254,3 +254,9 @@
     $ cobalt/build/gyp_cobalt -C gold linux-x64x11
     $ ninja -C out/linux-x64x11_gold cobalt
     $ out/linux-x64x11_gold/cobalt
+
+
+## Origin of this Repository
+
+This is a fork of the chromium repository at http://git.chromium.org/git/chromium.git
+
diff --git a/src/base/debug/leak_annotations.h b/src/base/debug/leak_annotations.h
index 97be127..35a7bec 100644
--- a/src/base/debug/leak_annotations.h
+++ b/src/base/debug/leak_annotations.h
@@ -7,6 +7,17 @@
 
 #include "build/build_config.h"
 
+// By default, Leak Sanitizer and Address Sanitizer is expected
+// to exist together. However, this is not true for all
+// platforms (e.g. PS4).
+// HAS_LEAK_SANTIZIER=0 explicitly removes the Leak Sanitizer from code.
+#ifdef ADDRESS_SANITIZER
+#ifndef HAS_LEAK_SANITIZER
+// Default is that Leak Sanitizer exists whenever Address Sanitizer does.
+#define HAS_LEAK_SANITIZER 1
+#endif
+#endif
+
 #if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_NACL) && \
     defined(USE_HEAPCHECKER)
 
@@ -29,7 +40,7 @@
 #define ANNOTATE_LEAKING_OBJECT_PTR(X) \
     HeapLeakChecker::IgnoreObject(X)
 
-#elif defined(ADDRESS_SANITIZER)
+#elif defined(ADDRESS_SANITIZER) && HAS_LEAK_SANITIZER
 #include <sanitizer/lsan_interface.h>
 
 class ScopedLeakSanitizerDisabler {
diff --git a/src/base/synchronization/condition_variable_unittest.cc b/src/base/synchronization/condition_variable_unittest.cc
index bc8201f..49d138b 100644
--- a/src/base/synchronization/condition_variable_unittest.cc
+++ b/src/base/synchronization/condition_variable_unittest.cc
@@ -350,6 +350,9 @@
   // Game consoles don't support that many threads. We have a max threads
   // macro in pthread.h. Leave a few to system and test with the rest.
   const int kThreadCount = SHELL_MAX_THREADS - 8;
+#elif defined(ADDRESS_SANITIZER)
+  // AddressSanitizer adds additional stack space to the threads.
+  const int kThreadCount = 50;
 #elif defined(OS_STARBOARD)
   const int kThreadCount = SB_MAX_THREADS - 8;
 #else
diff --git a/src/cobalt/account/starboard/account_manager.cc b/src/cobalt/account/starboard/account_manager.cc
index e6b4834..3a546bb 100644
--- a/src/cobalt/account/starboard/account_manager.cc
+++ b/src/cobalt/account/starboard/account_manager.cc
@@ -18,6 +18,7 @@
 
 #include "base/basictypes.h"
 #include "base/compiler_specific.h"
+#include "base/logging.h"
 #include "base/memory/scoped_ptr.h"
 #include "cobalt/base/event_dispatcher.h"
 #include "starboard/user.h"
@@ -88,16 +89,13 @@
   return GetCurrentUserProperty(kSbUserPropertyUserId);
 }
 
-void AccountManagerStarboard::StartSignIn() { SbUserStartSignIn(); }
+void AccountManagerStarboard::StartSignIn() {
+  NOTREACHED() << "Should be handled internally by platform.";
+}
 
 bool AccountManagerStarboard::IsAgeRestricted() {
-  SbUser user = SbUserGetCurrent();
-
-  if (!SbUserIsValid(user)) {
-    return false;
-  }
-
-  return SbUserIsAgeRestricted(user);
+  NOTREACHED() << "Should be handled internally by platform.";
+  return false;
 }
 
 }  // namespace account
diff --git a/src/cobalt/audio/audio_device.cc b/src/cobalt/audio/audio_device.cc
index 9a9e092..5f8d205 100644
--- a/src/cobalt/audio/audio_device.cc
+++ b/src/cobalt/audio/audio_device.cc
@@ -45,6 +45,38 @@
 
 #if defined(SB_USE_SB_AUDIO_SINK)
 
+namespace {
+// Helper function to compute the size of the two valid starboard audio sample
+// types.
+size_t GetSampleSize(SbMediaAudioSampleType sample_type) {
+  switch (sample_type) {
+    case kSbMediaAudioSampleTypeFloat32:
+      return sizeof(float);
+    case kSbMediaAudioSampleTypeInt16:
+      return sizeof(int16);
+  }
+  NOTREACHED();
+  return 0u;
+}
+
+const float kMaxInt16AsFloat32 = 32767.0f;
+
+template <typename SourceType, typename DestType>
+DestType ConvertSample(SourceType sample);
+
+template <>
+int16 ConvertSample<float, int16>(float sample) {
+  DCHECK(-1.0 <= sample && sample <= 1.0)
+      << "Sample of type float32 must lie on interval [-1.0, 1.0]";
+  return static_cast<int16>(sample * kMaxInt16AsFloat32);
+}
+
+template <>
+float ConvertSample<float, float>(float sample) {
+  return sample;
+}
+}  // namespace
+
 class AudioDevice::Impl {
  public:
   Impl(int number_of_channels, RenderCallback* callback);
@@ -62,7 +94,11 @@
 
   void FillOutputAudioBus();
 
+  template <typename OutputType>
+  inline void FillOutputAudioBusForType();
+
   int number_of_channels_;
+  SbMediaAudioSampleType output_sample_type_;
   RenderCallback* render_callback_;
 
   // The |render_callback_| returns audio data in planar form.  So we read it
@@ -70,11 +106,14 @@
   // |output_frame_buffer_|.
   ShellAudioBus input_audio_bus_;
 
-  std::vector<float> output_frame_buffer_;
+  scoped_array<uint8> output_frame_buffer_;
+
   void* frame_buffers_[1];
   int64 frames_rendered_;  // Frames retrieved from |render_callback_|.
   int64 frames_consumed_;  // Accumulated frames consumed reported by the sink.
 
+  bool was_silence_last_update_;
+
   SbAudioSink audio_sink_;
 
   DISALLOW_COPY_AND_ASSIGN(Impl);
@@ -83,13 +122,19 @@
 // AudioDevice::Impl.
 AudioDevice::Impl::Impl(int number_of_channels, RenderCallback* callback)
     : number_of_channels_(number_of_channels),
+      output_sample_type_(
+          SbAudioSinkIsAudioSampleTypeSupported(kSbMediaAudioSampleTypeFloat32)
+              ? kSbMediaAudioSampleTypeFloat32
+              : kSbMediaAudioSampleTypeInt16),
       render_callback_(callback),
       input_audio_bus_(static_cast<size_t>(number_of_channels),
                        static_cast<size_t>(kRenderBufferSizeFrames),
                        ShellAudioBus::kFloat32, ShellAudioBus::kPlanar),
-      output_frame_buffer_(kFramesPerChannel * number_of_channels),
+      output_frame_buffer_(new uint8[kFramesPerChannel * number_of_channels_ *
+                                       GetSampleSize(output_sample_type_)]),
       frames_rendered_(0),
       frames_consumed_(0),
+      was_silence_last_update_(false),
       audio_sink_(kSbAudioSinkInvalid) {
   DCHECK(number_of_channels_ == 1 || number_of_channels_ == 2)
       << "Invalid number of channels: " << number_of_channels_;
@@ -97,15 +142,14 @@
   DCHECK(SbAudioSinkIsAudioFrameStorageTypeSupported(
       kSbMediaAudioFrameStorageTypeInterleaved))
       << "Only interleaved frame storage is supported.";
-  DCHECK(SbAudioSinkIsAudioSampleTypeSupported(kSbMediaAudioSampleTypeFloat32))
-      << "Only float sample is supported.";
+  DCHECK(SbAudioSinkIsAudioSampleTypeSupported(output_sample_type_))
+      << "Output sample type " << output_sample_type_ << " is not supported";
 
-  frame_buffers_[0] = &output_frame_buffer_[0];
+  frame_buffers_[0] = output_frame_buffer_.get();
   audio_sink_ = SbAudioSinkCreate(
-      number_of_channels_, kStandardOutputSampleRate,
-      kSbMediaAudioSampleTypeFloat32, kSbMediaAudioFrameStorageTypeInterleaved,
-      frame_buffers_, kFramesPerChannel,
-      &AudioDevice::Impl::UpdateSourceStatusFunc,
+      number_of_channels_, kStandardOutputSampleRate, output_sample_type_,
+      kSbMediaAudioFrameStorageTypeInterleaved, frame_buffers_,
+      kFramesPerChannel, &AudioDevice::Impl::UpdateSourceStatusFunc,
       &AudioDevice::Impl::ConsumeFramesFunc, this);
   DCHECK(SbAudioSinkIsValid(audio_sink_));
 }
@@ -155,7 +199,12 @@
   if ((kFramesPerChannel - *frames_in_buffer) >= kRenderBufferSizeFrames) {
     bool silence = false;
 
-    input_audio_bus_.ZeroAllFrames();
+    // If there was silence last time we were called, then the buffer has
+    // already been zeroed out and we don't need to do it again.
+    if (!was_silence_last_update_) {
+      input_audio_bus_.ZeroAllFrames();
+    }
+
     // Fill our temporary buffer with planar PCM float samples.
     render_callback_->FillAudioBus(&input_audio_bus_, &silence);
 
@@ -165,31 +214,46 @@
       frames_rendered_ += kRenderBufferSizeFrames;
       *frames_in_buffer += kRenderBufferSizeFrames;
     }
+
+    was_silence_last_update_ = silence;
   }
 
   *offset_in_frames = frames_consumed_ % kFramesPerChannel;
+  *is_playing = (frames_rendered_ != frames_consumed_);
 }
 
 void AudioDevice::Impl::ConsumeFrames(int frames_consumed) {
   frames_consumed_ += frames_consumed;
 }
 
-void AudioDevice::Impl::FillOutputAudioBus() {
+template <typename OutputType>
+inline void AudioDevice::Impl::FillOutputAudioBusForType() {
   // Determine the offset into the audio bus that represents the tail of
   // buffered data.
   uint64 channel_offset = frames_rendered_ % kFramesPerChannel;
 
-  float* output_buffer = &output_frame_buffer_[0];
+  OutputType* output_buffer =
+      reinterpret_cast<OutputType*>(output_frame_buffer_.get());
   output_buffer += channel_offset * number_of_channels_;
-
   for (size_t frame = 0; frame < kRenderBufferSizeFrames; ++frame) {
     for (size_t channel = 0; channel < input_audio_bus_.channels(); ++channel) {
-      *output_buffer = input_audio_bus_.GetFloat32Sample(channel, frame);
+      *output_buffer = ConvertSample<float, OutputType>(
+          input_audio_bus_.GetFloat32Sample(channel, frame));
       ++output_buffer;
     }
   }
 }
 
+void AudioDevice::Impl::FillOutputAudioBus() {
+  if (output_sample_type_ == kSbMediaAudioSampleTypeFloat32) {
+    FillOutputAudioBusForType<float>();
+  } else if (output_sample_type_ == kSbMediaAudioSampleTypeInt16) {
+    FillOutputAudioBusForType<int16>();
+  } else {
+    NOTREACHED();
+  }
+}
+
 #else  // defined(SB_USE_SB_AUDIO_SINK)
 
 class AudioDevice::Impl : public ::media::ShellAudioStream {
diff --git a/src/cobalt/base/c_val.cc b/src/cobalt/base/c_val.cc
index e719bb5..812433b 100644
--- a/src/cobalt/base/c_val.cc
+++ b/src/cobalt/base/c_val.cc
@@ -29,15 +29,15 @@
   // and so this allows its size to be more consistent (and avoids compiler
   // warnings on some platforms).
   registered_vars_ = new NameVarMap();
-#if defined(ENABLE_DEBUG_CONSOLE)
+#if defined(ENABLE_DEBUG_C_VAL)
   on_changed_hook_set_ = new base::hash_set<OnChangedHook*>();
-#endif  // ENABLE_DEBUG_CONSOLE
+#endif  // ENABLE_DEBUG_C_VAL
 }
 
 CValManager::~CValManager() {
-#if defined(ENABLE_DEBUG_CONSOLE)
+#if defined(ENABLE_DEBUG_C_VAL)
   delete on_changed_hook_set_;
-#endif  // ENABLE_DEBUG_CONSOLE
+#endif  // ENABLE_DEBUG_C_VAL
   delete registered_vars_;
 }
 
@@ -62,7 +62,7 @@
   }
 }
 
-#if defined(ENABLE_DEBUG_CONSOLE)
+#if defined(ENABLE_DEBUG_C_VAL)
 void CValManager::PushValueChangedEvent(const CValDetail::CValBase* cval,
                                         const CValGenericValue& value) {
   base::AutoLock auto_lock(hooks_lock_);
@@ -92,7 +92,7 @@
   size_t values_erased ALLOW_UNUSED = cvm->on_changed_hook_set_->erase(this);
   DCHECK_EQ(values_erased, 1);
 }
-#endif  // ENABLE_DEBUG_CONSOLE
+#endif  // ENABLE_DEBUG_C_VAL
 
 std::set<std::string> CValManager::GetOrderedCValNames() {
   std::set<std::string> ret;
diff --git a/src/cobalt/base/c_val.h b/src/cobalt/base/c_val.h
index 767fdb6..787f51a 100644
--- a/src/cobalt/base/c_val.h
+++ b/src/cobalt/base/c_val.h
@@ -217,7 +217,7 @@
 
 }  // namespace CValDetail
 
-#if defined(ENABLE_DEBUG_CONSOLE)
+#if defined(ENABLE_DEBUG_C_VAL)
 // This class is passed back to the CVal modified event handlers so that they
 // can examine the new CVal value.  This class knows its type, which can be
 // checked through GetType, and then the actual value can be retrieved by
@@ -281,7 +281,7 @@
 };
 
 }  // namespace CValDetail
-#endif  // ENABLE_DEBUG_CONSOLE
+#endif  // ENABLE_DEBUG_C_VAL
 
 // Manager class required for the CVal tracking system to function.
 // This class is designed to be a singleton, instanced only through the methods
@@ -292,7 +292,7 @@
   // Method to get the singleton instance of this class.
   static CValManager* GetInstance();
 
-#if defined(ENABLE_DEBUG_CONSOLE)
+#if defined(ENABLE_DEBUG_C_VAL)
   // In order for a system to receive notifications when a tracked CVal changes,
   // it should create a subclass of OnChangedHook with OnValueChanged. When
   // instantiated, OnChangedHook will be called whenever a CVal changes.
@@ -304,7 +304,7 @@
     virtual void OnValueChanged(const std::string& name,
                                 const CValGenericValue& value) = 0;
   };
-#endif  // ENABLE_DEBUG_CONSOLE
+#endif  // ENABLE_DEBUG_C_VAL
 
   friend struct StaticMemorySingletonTraits<CValManager>;
 
@@ -332,22 +332,22 @@
   void RegisterCVal(const CValDetail::CValBase* cval);
   void UnregisterCVal(const CValDetail::CValBase* cval);
 
-#if defined(ENABLE_DEBUG_CONSOLE)
+#if defined(ENABLE_DEBUG_C_VAL)
   // Called whenever a CVal is modified, and does the work of notifying all
   // hooks.
   void PushValueChangedEvent(const CValDetail::CValBase* cval,
                              const CValGenericValue& value);
-#endif  // ENABLE_DEBUG_CONSOLE
+#endif  // ENABLE_DEBUG_C_VAL
 
   // Helper function to remove code duplication between GetValueAsString
   // and GetValueAsPrettyString.
   optional<std::string> GetCValStringValue(const std::string& name,
                                            bool pretty);
 
-#if defined(ENABLE_DEBUG_CONSOLE)
+#if defined(ENABLE_DEBUG_C_VAL)
   // Lock that protects against changes to hooks.
   base::Lock hooks_lock_;
-#endif  // ENABLE_DEBUG_CONSOLE
+#endif  // ENABLE_DEBUG_C_VAL
 
   // Lock that protects against CVals being registered/deregistered.
   base::Lock cvals_lock_;
@@ -359,11 +359,11 @@
   typedef base::hash_map<std::string, const CValDetail::CValBase*> NameVarMap;
   NameVarMap* registered_vars_;
 
-#if defined(ENABLE_DEBUG_CONSOLE)
+#if defined(ENABLE_DEBUG_C_VAL)
   // The set of hooks that we should notify whenever a CVal is modified.
   typedef base::hash_set<OnChangedHook*> OnChangeHookSet;
   OnChangeHookSet* on_changed_hook_set_;
-#endif  // ENABLE_DEBUG_CONSOLE
+#endif  // ENABLE_DEBUG_C_VAL
 
   template <typename T>
   friend class CValDetail::CValImpl;
@@ -427,11 +427,11 @@
         value_ = rhs;
       }
     }
-#if defined(ENABLE_DEBUG_CONSOLE)
+#if defined(ENABLE_DEBUG_C_VAL)
     if (value_changed) {
       OnValueChanged();
     }
-#endif  // ENABLE_DEBUG_CONSOLE
+#endif  // ENABLE_DEBUG_C_VAL
     return *this;
   }
 
@@ -440,9 +440,9 @@
       base::AutoLock auto_lock(CValManager::GetInstance()->values_lock_);
       value_ += rhs;
     }
-#if defined(ENABLE_DEBUG_CONSOLE)
+#if defined(ENABLE_DEBUG_C_VAL)
     OnValueChanged();
-#endif  // ENABLE_DEBUG_CONSOLE
+#endif  // ENABLE_DEBUG_C_VAL
     return *this;
   }
 
@@ -451,9 +451,9 @@
       base::AutoLock auto_lock(CValManager::GetInstance()->values_lock_);
       value_ -= rhs;
     }
-#if defined(ENABLE_DEBUG_CONSOLE)
+#if defined(ENABLE_DEBUG_C_VAL)
     OnValueChanged();
-#endif  // ENABLE_DEBUG_CONSOLE
+#endif  // ENABLE_DEBUG_C_VAL
     return *this;
   }
 
@@ -462,9 +462,9 @@
       base::AutoLock auto_lock(CValManager::GetInstance()->values_lock_);
       ++value_;
     }
-#if defined(ENABLE_DEBUG_CONSOLE)
+#if defined(ENABLE_DEBUG_C_VAL)
     OnValueChanged();
-#endif  // ENABLE_DEBUG_CONSOLE
+#endif  // ENABLE_DEBUG_C_VAL
     return *this;
   }
 
@@ -473,9 +473,9 @@
       base::AutoLock auto_lock(CValManager::GetInstance()->values_lock_);
       --value_;
     }
-#if defined(ENABLE_DEBUG_CONSOLE)
+#if defined(ENABLE_DEBUG_C_VAL)
     OnValueChanged();
-#endif  // ENABLE_DEBUG_CONSOLE
+#endif  // ENABLE_DEBUG_C_VAL
     return *this;
   }
 
@@ -505,13 +505,13 @@
     }
   }
 
-#if defined(ENABLE_DEBUG_CONSOLE)
+#if defined(ENABLE_DEBUG_C_VAL)
   void OnValueChanged() {
     // Push the value changed event to all listeners.
     CValManager::GetInstance()->PushValueChangedEvent(
         this, CValSpecificValue<T>(value_));
   }
-#endif  // ENABLE_DEBUG_CONSOLE
+#endif  // ENABLE_DEBUG_C_VAL
 
   T value_;
   mutable bool registered_;
diff --git a/src/cobalt/bindings/IDLExtendedAttributes.txt b/src/cobalt/bindings/IDLExtendedAttributes.txt
index 56b0590..7918baa 100644
--- a/src/cobalt/bindings/IDLExtendedAttributes.txt
+++ b/src/cobalt/bindings/IDLExtendedAttributes.txt
@@ -73,7 +73,9 @@
 
 # Call the Cobalt function this property is bound to with the corresponding
 # object added to the head of the function's parameters.
-CallWith=EnvironmentSettings
+# StackTrace is a custom addition to CallWith for the purpose of testing
+# GetStackTrace, and is not specified in the spec.
+CallWith=EnvironmentSettings|StackTrace
 ConstructorCallWith=EnvironmentSettings
 
 # The constructor/attribute/operation may raise an exception. A pointer to an
diff --git a/src/cobalt/bindings/generated/jsc/testing/JSCWindow.cc b/src/cobalt/bindings/generated/jsc/testing/JSCWindow.cc
index 32f9f26..1fb9cf2 100644
--- a/src/cobalt/bindings/generated/jsc/testing/JSCWindow.cc
+++ b/src/cobalt/bindings/generated/jsc/testing/JSCWindow.cc
@@ -287,6 +287,11 @@
     JSC::ExecState* exec,
     JSC::JSObject* this_object,
     JSC::JSValue value);
+JSC::JSValue getJSwindow(
+    JSC::ExecState* exec_state,
+    JSC::JSValue slot_base,
+    JSC::PropertyName property_name);
+JSC::EncodedJSValue functionJSgetStackTrace(JSC::ExecState*);
 JSC::EncodedJSValue functionJSwindowOperation(JSC::ExecState*);
 
 // These are declared unconditionally, but only defined if needed by the
@@ -603,6 +608,18 @@
         reinterpret_cast<intptr_t>(setJSwindowProperty),
         JSC::NoIntrinsic
     },
+    { "window",
+        JSC::DontDelete | JSC::ReadOnly,
+        reinterpret_cast<intptr_t>(getJSwindow),
+        0,
+        JSC::NoIntrinsic
+    },
+    { "getStackTrace",
+        JSC::DontDelete | JSC::Function,
+        reinterpret_cast<intptr_t>(functionJSgetStackTrace),
+        static_cast<intptr_t>(0),
+        JSC::NoIntrinsic
+    },
     { "windowOperation",
         JSC::DontDelete | JSC::Function,
         reinterpret_cast<intptr_t>(functionJSwindowOperation),
@@ -614,8 +631,8 @@
 
 // static
 const JSC::HashTable JSCWindow::property_table_prototype = {
-    9,  // compactSize
-    7,  // compactSizeMask
+    19,  // compactSize
+    15,  // compactSizeMask
     property_table_values,
     NULL  // table allocated at runtime
 };  // JSCWindow::property_table_prototype
@@ -1019,6 +1036,44 @@
   }
 }
 
+JSC::JSValue getJSwindow(
+    JSC::ExecState* exec_state,
+    JSC::JSValue slot_base,
+    JSC::PropertyName property_name) {
+  TRACE_EVENT0("JSCWindow", "get window");
+  JSCGlobalObject* global_object =
+      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
+  Window* impl =
+      GetWrappableOrSetException<Window>(exec_state, slot_base);
+  if (!impl) {
+    return exec_state->exception();
+  }
+
+  JSC::JSValue result = ToJSValue(
+      global_object,
+      impl->window());
+  return result;
+}
+
+JSC::EncodedJSValue functionJSgetStackTrace(
+    JSC::ExecState* exec_state) {
+  TRACE_EVENT0("JSCWindow", "call getStackTrace");
+  JSCGlobalObject* global_object =
+      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
+  JSCExceptionState exception_state(global_object);
+  JSC::JSObject* this_object =
+      exec_state->hostThisValue().toThisObject(exec_state);
+  Window* impl =
+      GetWrappableOrSetException<Window>(exec_state, this_object);
+  if (!impl) {
+    return JSC::JSValue::encode(exec_state->exception());
+  }
+
+  TypeTraits<std::string >::ReturnType return_value = impl->GetStackTrace(global_object->GetStackTrace());
+  return JSC::JSValue::encode(ToJSValue(global_object, return_value));
+
+}
+
 JSC::EncodedJSValue functionJSwindowOperation(
     JSC::ExecState* exec_state) {
   TRACE_EVENT0("JSCWindow", "call windowOperation");
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsAnonymousIndexedGetterInterface.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsAnonymousIndexedGetterInterface.cc
index d314658..546197c 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsAnonymousIndexedGetterInterface.cc
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsAnonymousIndexedGetterInterface.cc
@@ -205,6 +205,26 @@
 static base::LazyInstance<MozjsAnonymousIndexedGetterInterfaceHandler>
     proxy_handler;
 
+JSBool HasInstance(JSContext *context, JS::HandleObject type,
+                   JS::MutableHandleValue vp, JSBool *success) {
+  JS::RootedObject global_object(
+      context, JS_GetGlobalForObject(context, type));
+  DCHECK(global_object);
+
+  JS::RootedObject prototype(
+      context, MozjsAnonymousIndexedGetterInterface::GetPrototype(context, global_object));
+
+  // |IsDelegate| walks the prototype chain of an object returning true if
+  // .prototype is found.
+  bool is_delegate;
+  if (!IsDelegate(context, prototype, vp, &is_delegate)) {
+    *success = false;
+    return false;
+  }
+
+  *success = is_delegate;
+  return true;
+}
 
 InterfaceData* CreateCachedInterfaceData() {
   InterfaceData* interface_data = new InterfaceData();
@@ -253,6 +273,7 @@
   interface_object_class->enumerate = JS_EnumerateStub;
   interface_object_class->resolve = JS_ResolveStub;
   interface_object_class->convert = JS_ConvertStub;
+  interface_object_class->hasInstance = &HasInstance;
   return interface_data;
 }
 
@@ -306,14 +327,12 @@
 };
 
 void InitializePrototypeAndInterfaceObject(
-    InterfaceData* interface_data, JSContext* context) {
+    InterfaceData* interface_data, JSContext* context,
+    JS::HandleObject global_object) {
   DCHECK(!interface_data->prototype);
   DCHECK(!interface_data->interface_object);
+  DCHECK(JS_IsGlobalObject(global_object));
 
-  MozjsGlobalObjectProxy* global_object_proxy =
-      static_cast<MozjsGlobalObjectProxy*>(JS_GetContextPrivate(context));
-  JS::RootedObject global_object(context, global_object_proxy->global_object());
-  DCHECK(global_object);
   JS::RootedObject parent_prototype(
       context, JS_GetObjectPrototype(context, global_object));
   DCHECK(parent_prototype);
@@ -392,8 +411,11 @@
 // static
 JSObject* MozjsAnonymousIndexedGetterInterface::CreateProxy(
     JSContext* context, const scoped_refptr<Wrappable>& wrappable) {
+  JS::RootedObject global_object(context, JS_GetGlobalForScopeChain(context));
+  DCHECK(global_object);
+
   InterfaceData* interface_data = GetInterfaceData(context);
-  JS::RootedObject prototype(context, GetPrototype(context));
+  JS::RootedObject prototype(context, GetPrototype(context, global_object));
   DCHECK(prototype);
   JS::RootedObject new_object(context, JS_NewObjectWithGivenProto(
       context, &interface_data->instance_class_definition, prototype, NULL));
@@ -401,34 +423,45 @@
   JS::RootedObject proxy(context,
       ProxyHandler::NewProxy(context, new_object, prototype, NULL,
                              proxy_handler.Pointer()));
-  WrapperPrivate::AddPrivateData(proxy, wrappable);
+  WrapperPrivate::AddPrivateData(context, proxy, wrappable);
   return proxy;
 }
 
 //static
 const JSClass* MozjsAnonymousIndexedGetterInterface::PrototypeClass(
       JSContext* context) {
-  JS::RootedObject prototype(context, GetPrototype(context));
+  JS::RootedObject global_object(context, JS_GetGlobalForScopeChain(context));
+  DCHECK(global_object);
+
+  JS::RootedObject prototype(context, GetPrototype(context, global_object));
   JSClass* proto_class = JS_GetClass(*prototype.address());
   return proto_class;
 }
 
 // static
-JSObject* MozjsAnonymousIndexedGetterInterface::GetPrototype(JSContext* context) {
+JSObject* MozjsAnonymousIndexedGetterInterface::GetPrototype(
+    JSContext* context, JS::HandleObject global_object) {
+  DCHECK(JS_IsGlobalObject(global_object));
+
   InterfaceData* interface_data = GetInterfaceData(context);
   if (!interface_data->prototype) {
     // Create new prototype that has all the props and methods
-    InitializePrototypeAndInterfaceObject(interface_data, context);
+    InitializePrototypeAndInterfaceObject(
+        interface_data, context, global_object);
   }
   DCHECK(interface_data->prototype);
   return interface_data->prototype;
 }
 
 // static
-JSObject* MozjsAnonymousIndexedGetterInterface::GetInterfaceObject(JSContext* context) {
+JSObject* MozjsAnonymousIndexedGetterInterface::GetInterfaceObject(
+    JSContext* context, JS::HandleObject global_object) {
+  DCHECK(JS_IsGlobalObject(global_object));
+
   InterfaceData* interface_data = GetInterfaceData(context);
   if (!interface_data->interface_object) {
-    InitializePrototypeAndInterfaceObject(interface_data, context);
+    InitializePrototypeAndInterfaceObject(
+        interface_data, context, global_object);
   }
   DCHECK(interface_data->interface_object);
   return interface_data->interface_object;
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsAnonymousIndexedGetterInterface.h b/src/cobalt/bindings/generated/mozjs/testing/MozjsAnonymousIndexedGetterInterface.h
index 56a2226..1f01c81 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsAnonymousIndexedGetterInterface.h
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsAnonymousIndexedGetterInterface.h
@@ -41,8 +41,10 @@
   static JSObject* CreateProxy(JSContext* context,
       const scoped_refptr<script::Wrappable>& wrappable);
   static const JSClass* PrototypeClass(JSContext* context);
-  static JSObject* GetPrototype(JSContext* context);
-  static JSObject* GetInterfaceObject(JSContext* context);
+  static JSObject* GetPrototype(JSContext* context,
+                                JS::HandleObject global_object);
+  static JSObject* GetInterfaceObject(JSContext* context,
+                                      JS::HandleObject global_object);
 };
 
 }  // namespace bindings
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsAnonymousNamedGetterInterface.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsAnonymousNamedGetterInterface.cc
index 7cc34a6..9cb9a00 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsAnonymousNamedGetterInterface.cc
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsAnonymousNamedGetterInterface.cc
@@ -205,6 +205,26 @@
 static base::LazyInstance<MozjsAnonymousNamedGetterInterfaceHandler>
     proxy_handler;
 
+JSBool HasInstance(JSContext *context, JS::HandleObject type,
+                   JS::MutableHandleValue vp, JSBool *success) {
+  JS::RootedObject global_object(
+      context, JS_GetGlobalForObject(context, type));
+  DCHECK(global_object);
+
+  JS::RootedObject prototype(
+      context, MozjsAnonymousNamedGetterInterface::GetPrototype(context, global_object));
+
+  // |IsDelegate| walks the prototype chain of an object returning true if
+  // .prototype is found.
+  bool is_delegate;
+  if (!IsDelegate(context, prototype, vp, &is_delegate)) {
+    *success = false;
+    return false;
+  }
+
+  *success = is_delegate;
+  return true;
+}
 
 InterfaceData* CreateCachedInterfaceData() {
   InterfaceData* interface_data = new InterfaceData();
@@ -253,6 +273,7 @@
   interface_object_class->enumerate = JS_EnumerateStub;
   interface_object_class->resolve = JS_ResolveStub;
   interface_object_class->convert = JS_ConvertStub;
+  interface_object_class->hasInstance = &HasInstance;
   return interface_data;
 }
 
@@ -278,14 +299,12 @@
 };
 
 void InitializePrototypeAndInterfaceObject(
-    InterfaceData* interface_data, JSContext* context) {
+    InterfaceData* interface_data, JSContext* context,
+    JS::HandleObject global_object) {
   DCHECK(!interface_data->prototype);
   DCHECK(!interface_data->interface_object);
+  DCHECK(JS_IsGlobalObject(global_object));
 
-  MozjsGlobalObjectProxy* global_object_proxy =
-      static_cast<MozjsGlobalObjectProxy*>(JS_GetContextPrivate(context));
-  JS::RootedObject global_object(context, global_object_proxy->global_object());
-  DCHECK(global_object);
   JS::RootedObject parent_prototype(
       context, JS_GetObjectPrototype(context, global_object));
   DCHECK(parent_prototype);
@@ -364,8 +383,11 @@
 // static
 JSObject* MozjsAnonymousNamedGetterInterface::CreateProxy(
     JSContext* context, const scoped_refptr<Wrappable>& wrappable) {
+  JS::RootedObject global_object(context, JS_GetGlobalForScopeChain(context));
+  DCHECK(global_object);
+
   InterfaceData* interface_data = GetInterfaceData(context);
-  JS::RootedObject prototype(context, GetPrototype(context));
+  JS::RootedObject prototype(context, GetPrototype(context, global_object));
   DCHECK(prototype);
   JS::RootedObject new_object(context, JS_NewObjectWithGivenProto(
       context, &interface_data->instance_class_definition, prototype, NULL));
@@ -373,34 +395,45 @@
   JS::RootedObject proxy(context,
       ProxyHandler::NewProxy(context, new_object, prototype, NULL,
                              proxy_handler.Pointer()));
-  WrapperPrivate::AddPrivateData(proxy, wrappable);
+  WrapperPrivate::AddPrivateData(context, proxy, wrappable);
   return proxy;
 }
 
 //static
 const JSClass* MozjsAnonymousNamedGetterInterface::PrototypeClass(
       JSContext* context) {
-  JS::RootedObject prototype(context, GetPrototype(context));
+  JS::RootedObject global_object(context, JS_GetGlobalForScopeChain(context));
+  DCHECK(global_object);
+
+  JS::RootedObject prototype(context, GetPrototype(context, global_object));
   JSClass* proto_class = JS_GetClass(*prototype.address());
   return proto_class;
 }
 
 // static
-JSObject* MozjsAnonymousNamedGetterInterface::GetPrototype(JSContext* context) {
+JSObject* MozjsAnonymousNamedGetterInterface::GetPrototype(
+    JSContext* context, JS::HandleObject global_object) {
+  DCHECK(JS_IsGlobalObject(global_object));
+
   InterfaceData* interface_data = GetInterfaceData(context);
   if (!interface_data->prototype) {
     // Create new prototype that has all the props and methods
-    InitializePrototypeAndInterfaceObject(interface_data, context);
+    InitializePrototypeAndInterfaceObject(
+        interface_data, context, global_object);
   }
   DCHECK(interface_data->prototype);
   return interface_data->prototype;
 }
 
 // static
-JSObject* MozjsAnonymousNamedGetterInterface::GetInterfaceObject(JSContext* context) {
+JSObject* MozjsAnonymousNamedGetterInterface::GetInterfaceObject(
+    JSContext* context, JS::HandleObject global_object) {
+  DCHECK(JS_IsGlobalObject(global_object));
+
   InterfaceData* interface_data = GetInterfaceData(context);
   if (!interface_data->interface_object) {
-    InitializePrototypeAndInterfaceObject(interface_data, context);
+    InitializePrototypeAndInterfaceObject(
+        interface_data, context, global_object);
   }
   DCHECK(interface_data->interface_object);
   return interface_data->interface_object;
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsAnonymousNamedGetterInterface.h b/src/cobalt/bindings/generated/mozjs/testing/MozjsAnonymousNamedGetterInterface.h
index 36537ae..3b02269 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsAnonymousNamedGetterInterface.h
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsAnonymousNamedGetterInterface.h
@@ -41,8 +41,10 @@
   static JSObject* CreateProxy(JSContext* context,
       const scoped_refptr<script::Wrappable>& wrappable);
   static const JSClass* PrototypeClass(JSContext* context);
-  static JSObject* GetPrototype(JSContext* context);
-  static JSObject* GetInterfaceObject(JSContext* context);
+  static JSObject* GetPrototype(JSContext* context,
+                                JS::HandleObject global_object);
+  static JSObject* GetInterfaceObject(JSContext* context,
+                                      JS::HandleObject global_object);
 };
 
 }  // namespace bindings
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsAnonymousNamedIndexedGetterInterface.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsAnonymousNamedIndexedGetterInterface.cc
index 519c86f..0b1e79d 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsAnonymousNamedIndexedGetterInterface.cc
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsAnonymousNamedIndexedGetterInterface.cc
@@ -296,6 +296,26 @@
 static base::LazyInstance<MozjsAnonymousNamedIndexedGetterInterfaceHandler>
     proxy_handler;
 
+JSBool HasInstance(JSContext *context, JS::HandleObject type,
+                   JS::MutableHandleValue vp, JSBool *success) {
+  JS::RootedObject global_object(
+      context, JS_GetGlobalForObject(context, type));
+  DCHECK(global_object);
+
+  JS::RootedObject prototype(
+      context, MozjsAnonymousNamedIndexedGetterInterface::GetPrototype(context, global_object));
+
+  // |IsDelegate| walks the prototype chain of an object returning true if
+  // .prototype is found.
+  bool is_delegate;
+  if (!IsDelegate(context, prototype, vp, &is_delegate)) {
+    *success = false;
+    return false;
+  }
+
+  *success = is_delegate;
+  return true;
+}
 
 InterfaceData* CreateCachedInterfaceData() {
   InterfaceData* interface_data = new InterfaceData();
@@ -344,6 +364,7 @@
   interface_object_class->enumerate = JS_EnumerateStub;
   interface_object_class->resolve = JS_ResolveStub;
   interface_object_class->convert = JS_ConvertStub;
+  interface_object_class->hasInstance = &HasInstance;
   return interface_data;
 }
 
@@ -397,14 +418,12 @@
 };
 
 void InitializePrototypeAndInterfaceObject(
-    InterfaceData* interface_data, JSContext* context) {
+    InterfaceData* interface_data, JSContext* context,
+    JS::HandleObject global_object) {
   DCHECK(!interface_data->prototype);
   DCHECK(!interface_data->interface_object);
+  DCHECK(JS_IsGlobalObject(global_object));
 
-  MozjsGlobalObjectProxy* global_object_proxy =
-      static_cast<MozjsGlobalObjectProxy*>(JS_GetContextPrivate(context));
-  JS::RootedObject global_object(context, global_object_proxy->global_object());
-  DCHECK(global_object);
   JS::RootedObject parent_prototype(
       context, JS_GetObjectPrototype(context, global_object));
   DCHECK(parent_prototype);
@@ -483,8 +502,11 @@
 // static
 JSObject* MozjsAnonymousNamedIndexedGetterInterface::CreateProxy(
     JSContext* context, const scoped_refptr<Wrappable>& wrappable) {
+  JS::RootedObject global_object(context, JS_GetGlobalForScopeChain(context));
+  DCHECK(global_object);
+
   InterfaceData* interface_data = GetInterfaceData(context);
-  JS::RootedObject prototype(context, GetPrototype(context));
+  JS::RootedObject prototype(context, GetPrototype(context, global_object));
   DCHECK(prototype);
   JS::RootedObject new_object(context, JS_NewObjectWithGivenProto(
       context, &interface_data->instance_class_definition, prototype, NULL));
@@ -492,34 +514,45 @@
   JS::RootedObject proxy(context,
       ProxyHandler::NewProxy(context, new_object, prototype, NULL,
                              proxy_handler.Pointer()));
-  WrapperPrivate::AddPrivateData(proxy, wrappable);
+  WrapperPrivate::AddPrivateData(context, proxy, wrappable);
   return proxy;
 }
 
 //static
 const JSClass* MozjsAnonymousNamedIndexedGetterInterface::PrototypeClass(
       JSContext* context) {
-  JS::RootedObject prototype(context, GetPrototype(context));
+  JS::RootedObject global_object(context, JS_GetGlobalForScopeChain(context));
+  DCHECK(global_object);
+
+  JS::RootedObject prototype(context, GetPrototype(context, global_object));
   JSClass* proto_class = JS_GetClass(*prototype.address());
   return proto_class;
 }
 
 // static
-JSObject* MozjsAnonymousNamedIndexedGetterInterface::GetPrototype(JSContext* context) {
+JSObject* MozjsAnonymousNamedIndexedGetterInterface::GetPrototype(
+    JSContext* context, JS::HandleObject global_object) {
+  DCHECK(JS_IsGlobalObject(global_object));
+
   InterfaceData* interface_data = GetInterfaceData(context);
   if (!interface_data->prototype) {
     // Create new prototype that has all the props and methods
-    InitializePrototypeAndInterfaceObject(interface_data, context);
+    InitializePrototypeAndInterfaceObject(
+        interface_data, context, global_object);
   }
   DCHECK(interface_data->prototype);
   return interface_data->prototype;
 }
 
 // static
-JSObject* MozjsAnonymousNamedIndexedGetterInterface::GetInterfaceObject(JSContext* context) {
+JSObject* MozjsAnonymousNamedIndexedGetterInterface::GetInterfaceObject(
+    JSContext* context, JS::HandleObject global_object) {
+  DCHECK(JS_IsGlobalObject(global_object));
+
   InterfaceData* interface_data = GetInterfaceData(context);
   if (!interface_data->interface_object) {
-    InitializePrototypeAndInterfaceObject(interface_data, context);
+    InitializePrototypeAndInterfaceObject(
+        interface_data, context, global_object);
   }
   DCHECK(interface_data->interface_object);
   return interface_data->interface_object;
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsAnonymousNamedIndexedGetterInterface.h b/src/cobalt/bindings/generated/mozjs/testing/MozjsAnonymousNamedIndexedGetterInterface.h
index 6665fe1..3c53111 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsAnonymousNamedIndexedGetterInterface.h
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsAnonymousNamedIndexedGetterInterface.h
@@ -41,8 +41,10 @@
   static JSObject* CreateProxy(JSContext* context,
       const scoped_refptr<script::Wrappable>& wrappable);
   static const JSClass* PrototypeClass(JSContext* context);
-  static JSObject* GetPrototype(JSContext* context);
-  static JSObject* GetInterfaceObject(JSContext* context);
+  static JSObject* GetPrototype(JSContext* context,
+                                JS::HandleObject global_object);
+  static JSObject* GetInterfaceObject(JSContext* context,
+                                      JS::HandleObject global_object);
 };
 
 }  // namespace bindings
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsArbitraryInterface.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsArbitraryInterface.cc
index eb16ae9..4073689 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsArbitraryInterface.cc
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsArbitraryInterface.cc
@@ -115,6 +115,26 @@
     proxy_handler;
 
 JSBool Constructor(JSContext* context, unsigned int argc, JS::Value* vp);
+JSBool HasInstance(JSContext *context, JS::HandleObject type,
+                   JS::MutableHandleValue vp, JSBool *success) {
+  JS::RootedObject global_object(
+      context, JS_GetGlobalForObject(context, type));
+  DCHECK(global_object);
+
+  JS::RootedObject prototype(
+      context, MozjsArbitraryInterface::GetPrototype(context, global_object));
+
+  // |IsDelegate| walks the prototype chain of an object returning true if
+  // .prototype is found.
+  bool is_delegate;
+  if (!IsDelegate(context, prototype, vp, &is_delegate)) {
+    *success = false;
+    return false;
+  }
+
+  *success = is_delegate;
+  return true;
+}
 
 InterfaceData* CreateCachedInterfaceData() {
   InterfaceData* interface_data = new InterfaceData();
@@ -163,6 +183,7 @@
   interface_object_class->enumerate = JS_EnumerateStub;
   interface_object_class->resolve = JS_ResolveStub;
   interface_object_class->convert = JS_ConvertStub;
+  interface_object_class->hasInstance = &HasInstance;
   interface_object_class->construct = Constructor;
   return interface_data;
 }
@@ -274,14 +295,12 @@
 };
 
 void InitializePrototypeAndInterfaceObject(
-    InterfaceData* interface_data, JSContext* context) {
+    InterfaceData* interface_data, JSContext* context,
+    JS::HandleObject global_object) {
   DCHECK(!interface_data->prototype);
   DCHECK(!interface_data->interface_object);
+  DCHECK(JS_IsGlobalObject(global_object));
 
-  MozjsGlobalObjectProxy* global_object_proxy =
-      static_cast<MozjsGlobalObjectProxy*>(JS_GetContextPrivate(context));
-  JS::RootedObject global_object(context, global_object_proxy->global_object());
-  DCHECK(global_object);
   JS::RootedObject parent_prototype(
       context, JS_GetObjectPrototype(context, global_object));
   DCHECK(parent_prototype);
@@ -370,8 +389,11 @@
 // static
 JSObject* MozjsArbitraryInterface::CreateProxy(
     JSContext* context, const scoped_refptr<Wrappable>& wrappable) {
+  JS::RootedObject global_object(context, JS_GetGlobalForScopeChain(context));
+  DCHECK(global_object);
+
   InterfaceData* interface_data = GetInterfaceData(context);
-  JS::RootedObject prototype(context, GetPrototype(context));
+  JS::RootedObject prototype(context, GetPrototype(context, global_object));
   DCHECK(prototype);
   JS::RootedObject new_object(context, JS_NewObjectWithGivenProto(
       context, &interface_data->instance_class_definition, prototype, NULL));
@@ -379,34 +401,45 @@
   JS::RootedObject proxy(context,
       ProxyHandler::NewProxy(context, new_object, prototype, NULL,
                              proxy_handler.Pointer()));
-  WrapperPrivate::AddPrivateData(proxy, wrappable);
+  WrapperPrivate::AddPrivateData(context, proxy, wrappable);
   return proxy;
 }
 
 //static
 const JSClass* MozjsArbitraryInterface::PrototypeClass(
       JSContext* context) {
-  JS::RootedObject prototype(context, GetPrototype(context));
+  JS::RootedObject global_object(context, JS_GetGlobalForScopeChain(context));
+  DCHECK(global_object);
+
+  JS::RootedObject prototype(context, GetPrototype(context, global_object));
   JSClass* proto_class = JS_GetClass(*prototype.address());
   return proto_class;
 }
 
 // static
-JSObject* MozjsArbitraryInterface::GetPrototype(JSContext* context) {
+JSObject* MozjsArbitraryInterface::GetPrototype(
+    JSContext* context, JS::HandleObject global_object) {
+  DCHECK(JS_IsGlobalObject(global_object));
+
   InterfaceData* interface_data = GetInterfaceData(context);
   if (!interface_data->prototype) {
     // Create new prototype that has all the props and methods
-    InitializePrototypeAndInterfaceObject(interface_data, context);
+    InitializePrototypeAndInterfaceObject(
+        interface_data, context, global_object);
   }
   DCHECK(interface_data->prototype);
   return interface_data->prototype;
 }
 
 // static
-JSObject* MozjsArbitraryInterface::GetInterfaceObject(JSContext* context) {
+JSObject* MozjsArbitraryInterface::GetInterfaceObject(
+    JSContext* context, JS::HandleObject global_object) {
+  DCHECK(JS_IsGlobalObject(global_object));
+
   InterfaceData* interface_data = GetInterfaceData(context);
   if (!interface_data->interface_object) {
-    InitializePrototypeAndInterfaceObject(interface_data, context);
+    InitializePrototypeAndInterfaceObject(
+        interface_data, context, global_object);
   }
   DCHECK(interface_data->interface_object);
   return interface_data->interface_object;
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsArbitraryInterface.h b/src/cobalt/bindings/generated/mozjs/testing/MozjsArbitraryInterface.h
index 1ca5d0d..d1f6fa5 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsArbitraryInterface.h
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsArbitraryInterface.h
@@ -41,8 +41,10 @@
   static JSObject* CreateProxy(JSContext* context,
       const scoped_refptr<script::Wrappable>& wrappable);
   static const JSClass* PrototypeClass(JSContext* context);
-  static JSObject* GetPrototype(JSContext* context);
-  static JSObject* GetInterfaceObject(JSContext* context);
+  static JSObject* GetPrototype(JSContext* context,
+                                JS::HandleObject global_object);
+  static JSObject* GetInterfaceObject(JSContext* context,
+                                      JS::HandleObject global_object);
 };
 
 }  // namespace bindings
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsBaseInterface.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsBaseInterface.cc
index 1213bf6..f0e5922 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsBaseInterface.cc
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsBaseInterface.cc
@@ -115,6 +115,26 @@
     proxy_handler;
 
 JSBool Constructor(JSContext* context, unsigned int argc, JS::Value* vp);
+JSBool HasInstance(JSContext *context, JS::HandleObject type,
+                   JS::MutableHandleValue vp, JSBool *success) {
+  JS::RootedObject global_object(
+      context, JS_GetGlobalForObject(context, type));
+  DCHECK(global_object);
+
+  JS::RootedObject prototype(
+      context, MozjsBaseInterface::GetPrototype(context, global_object));
+
+  // |IsDelegate| walks the prototype chain of an object returning true if
+  // .prototype is found.
+  bool is_delegate;
+  if (!IsDelegate(context, prototype, vp, &is_delegate)) {
+    *success = false;
+    return false;
+  }
+
+  *success = is_delegate;
+  return true;
+}
 
 InterfaceData* CreateCachedInterfaceData() {
   InterfaceData* interface_data = new InterfaceData();
@@ -163,6 +183,7 @@
   interface_object_class->enumerate = JS_EnumerateStub;
   interface_object_class->resolve = JS_ResolveStub;
   interface_object_class->convert = JS_ConvertStub;
+  interface_object_class->hasInstance = &HasInstance;
   interface_object_class->construct = Constructor;
   return interface_data;
 }
@@ -252,14 +273,12 @@
 };
 
 void InitializePrototypeAndInterfaceObject(
-    InterfaceData* interface_data, JSContext* context) {
+    InterfaceData* interface_data, JSContext* context,
+    JS::HandleObject global_object) {
   DCHECK(!interface_data->prototype);
   DCHECK(!interface_data->interface_object);
+  DCHECK(JS_IsGlobalObject(global_object));
 
-  MozjsGlobalObjectProxy* global_object_proxy =
-      static_cast<MozjsGlobalObjectProxy*>(JS_GetContextPrivate(context));
-  JS::RootedObject global_object(context, global_object_proxy->global_object());
-  DCHECK(global_object);
   JS::RootedObject parent_prototype(
       context, JS_GetObjectPrototype(context, global_object));
   DCHECK(parent_prototype);
@@ -348,8 +367,11 @@
 // static
 JSObject* MozjsBaseInterface::CreateProxy(
     JSContext* context, const scoped_refptr<Wrappable>& wrappable) {
+  JS::RootedObject global_object(context, JS_GetGlobalForScopeChain(context));
+  DCHECK(global_object);
+
   InterfaceData* interface_data = GetInterfaceData(context);
-  JS::RootedObject prototype(context, GetPrototype(context));
+  JS::RootedObject prototype(context, GetPrototype(context, global_object));
   DCHECK(prototype);
   JS::RootedObject new_object(context, JS_NewObjectWithGivenProto(
       context, &interface_data->instance_class_definition, prototype, NULL));
@@ -357,34 +379,45 @@
   JS::RootedObject proxy(context,
       ProxyHandler::NewProxy(context, new_object, prototype, NULL,
                              proxy_handler.Pointer()));
-  WrapperPrivate::AddPrivateData(proxy, wrappable);
+  WrapperPrivate::AddPrivateData(context, proxy, wrappable);
   return proxy;
 }
 
 //static
 const JSClass* MozjsBaseInterface::PrototypeClass(
       JSContext* context) {
-  JS::RootedObject prototype(context, GetPrototype(context));
+  JS::RootedObject global_object(context, JS_GetGlobalForScopeChain(context));
+  DCHECK(global_object);
+
+  JS::RootedObject prototype(context, GetPrototype(context, global_object));
   JSClass* proto_class = JS_GetClass(*prototype.address());
   return proto_class;
 }
 
 // static
-JSObject* MozjsBaseInterface::GetPrototype(JSContext* context) {
+JSObject* MozjsBaseInterface::GetPrototype(
+    JSContext* context, JS::HandleObject global_object) {
+  DCHECK(JS_IsGlobalObject(global_object));
+
   InterfaceData* interface_data = GetInterfaceData(context);
   if (!interface_data->prototype) {
     // Create new prototype that has all the props and methods
-    InitializePrototypeAndInterfaceObject(interface_data, context);
+    InitializePrototypeAndInterfaceObject(
+        interface_data, context, global_object);
   }
   DCHECK(interface_data->prototype);
   return interface_data->prototype;
 }
 
 // static
-JSObject* MozjsBaseInterface::GetInterfaceObject(JSContext* context) {
+JSObject* MozjsBaseInterface::GetInterfaceObject(
+    JSContext* context, JS::HandleObject global_object) {
+  DCHECK(JS_IsGlobalObject(global_object));
+
   InterfaceData* interface_data = GetInterfaceData(context);
   if (!interface_data->interface_object) {
-    InitializePrototypeAndInterfaceObject(interface_data, context);
+    InitializePrototypeAndInterfaceObject(
+        interface_data, context, global_object);
   }
   DCHECK(interface_data->interface_object);
   return interface_data->interface_object;
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsBaseInterface.h b/src/cobalt/bindings/generated/mozjs/testing/MozjsBaseInterface.h
index 6a9f2c0..2312b77 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsBaseInterface.h
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsBaseInterface.h
@@ -41,8 +41,10 @@
   static JSObject* CreateProxy(JSContext* context,
       const scoped_refptr<script::Wrappable>& wrappable);
   static const JSClass* PrototypeClass(JSContext* context);
-  static JSObject* GetPrototype(JSContext* context);
-  static JSObject* GetInterfaceObject(JSContext* context);
+  static JSObject* GetPrototype(JSContext* context,
+                                JS::HandleObject global_object);
+  static JSObject* GetInterfaceObject(JSContext* context,
+                                      JS::HandleObject global_object);
 };
 
 }  // namespace bindings
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsBooleanTypeTestInterface.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsBooleanTypeTestInterface.cc
index b334f88..86e82f3 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsBooleanTypeTestInterface.cc
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsBooleanTypeTestInterface.cc
@@ -114,6 +114,26 @@
 static base::LazyInstance<MozjsBooleanTypeTestInterfaceHandler>
     proxy_handler;
 
+JSBool HasInstance(JSContext *context, JS::HandleObject type,
+                   JS::MutableHandleValue vp, JSBool *success) {
+  JS::RootedObject global_object(
+      context, JS_GetGlobalForObject(context, type));
+  DCHECK(global_object);
+
+  JS::RootedObject prototype(
+      context, MozjsBooleanTypeTestInterface::GetPrototype(context, global_object));
+
+  // |IsDelegate| walks the prototype chain of an object returning true if
+  // .prototype is found.
+  bool is_delegate;
+  if (!IsDelegate(context, prototype, vp, &is_delegate)) {
+    *success = false;
+    return false;
+  }
+
+  *success = is_delegate;
+  return true;
+}
 
 InterfaceData* CreateCachedInterfaceData() {
   InterfaceData* interface_data = new InterfaceData();
@@ -162,6 +182,7 @@
   interface_object_class->enumerate = JS_EnumerateStub;
   interface_object_class->resolve = JS_ResolveStub;
   interface_object_class->convert = JS_ConvertStub;
+  interface_object_class->hasInstance = &HasInstance;
   return interface_data;
 }
 
@@ -332,14 +353,12 @@
 };
 
 void InitializePrototypeAndInterfaceObject(
-    InterfaceData* interface_data, JSContext* context) {
+    InterfaceData* interface_data, JSContext* context,
+    JS::HandleObject global_object) {
   DCHECK(!interface_data->prototype);
   DCHECK(!interface_data->interface_object);
+  DCHECK(JS_IsGlobalObject(global_object));
 
-  MozjsGlobalObjectProxy* global_object_proxy =
-      static_cast<MozjsGlobalObjectProxy*>(JS_GetContextPrivate(context));
-  JS::RootedObject global_object(context, global_object_proxy->global_object());
-  DCHECK(global_object);
   JS::RootedObject parent_prototype(
       context, JS_GetObjectPrototype(context, global_object));
   DCHECK(parent_prototype);
@@ -418,8 +437,11 @@
 // static
 JSObject* MozjsBooleanTypeTestInterface::CreateProxy(
     JSContext* context, const scoped_refptr<Wrappable>& wrappable) {
+  JS::RootedObject global_object(context, JS_GetGlobalForScopeChain(context));
+  DCHECK(global_object);
+
   InterfaceData* interface_data = GetInterfaceData(context);
-  JS::RootedObject prototype(context, GetPrototype(context));
+  JS::RootedObject prototype(context, GetPrototype(context, global_object));
   DCHECK(prototype);
   JS::RootedObject new_object(context, JS_NewObjectWithGivenProto(
       context, &interface_data->instance_class_definition, prototype, NULL));
@@ -427,34 +449,45 @@
   JS::RootedObject proxy(context,
       ProxyHandler::NewProxy(context, new_object, prototype, NULL,
                              proxy_handler.Pointer()));
-  WrapperPrivate::AddPrivateData(proxy, wrappable);
+  WrapperPrivate::AddPrivateData(context, proxy, wrappable);
   return proxy;
 }
 
 //static
 const JSClass* MozjsBooleanTypeTestInterface::PrototypeClass(
       JSContext* context) {
-  JS::RootedObject prototype(context, GetPrototype(context));
+  JS::RootedObject global_object(context, JS_GetGlobalForScopeChain(context));
+  DCHECK(global_object);
+
+  JS::RootedObject prototype(context, GetPrototype(context, global_object));
   JSClass* proto_class = JS_GetClass(*prototype.address());
   return proto_class;
 }
 
 // static
-JSObject* MozjsBooleanTypeTestInterface::GetPrototype(JSContext* context) {
+JSObject* MozjsBooleanTypeTestInterface::GetPrototype(
+    JSContext* context, JS::HandleObject global_object) {
+  DCHECK(JS_IsGlobalObject(global_object));
+
   InterfaceData* interface_data = GetInterfaceData(context);
   if (!interface_data->prototype) {
     // Create new prototype that has all the props and methods
-    InitializePrototypeAndInterfaceObject(interface_data, context);
+    InitializePrototypeAndInterfaceObject(
+        interface_data, context, global_object);
   }
   DCHECK(interface_data->prototype);
   return interface_data->prototype;
 }
 
 // static
-JSObject* MozjsBooleanTypeTestInterface::GetInterfaceObject(JSContext* context) {
+JSObject* MozjsBooleanTypeTestInterface::GetInterfaceObject(
+    JSContext* context, JS::HandleObject global_object) {
+  DCHECK(JS_IsGlobalObject(global_object));
+
   InterfaceData* interface_data = GetInterfaceData(context);
   if (!interface_data->interface_object) {
-    InitializePrototypeAndInterfaceObject(interface_data, context);
+    InitializePrototypeAndInterfaceObject(
+        interface_data, context, global_object);
   }
   DCHECK(interface_data->interface_object);
   return interface_data->interface_object;
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsBooleanTypeTestInterface.h b/src/cobalt/bindings/generated/mozjs/testing/MozjsBooleanTypeTestInterface.h
index d240a38..fa3f0e3 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsBooleanTypeTestInterface.h
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsBooleanTypeTestInterface.h
@@ -41,8 +41,10 @@
   static JSObject* CreateProxy(JSContext* context,
       const scoped_refptr<script::Wrappable>& wrappable);
   static const JSClass* PrototypeClass(JSContext* context);
-  static JSObject* GetPrototype(JSContext* context);
-  static JSObject* GetInterfaceObject(JSContext* context);
+  static JSObject* GetPrototype(JSContext* context,
+                                JS::HandleObject global_object);
+  static JSObject* GetInterfaceObject(JSContext* context,
+                                      JS::HandleObject global_object);
 };
 
 }  // namespace bindings
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsCallbackFunctionInterface.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsCallbackFunctionInterface.cc
index a6360ce..379afa8 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsCallbackFunctionInterface.cc
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsCallbackFunctionInterface.cc
@@ -118,6 +118,26 @@
 static base::LazyInstance<MozjsCallbackFunctionInterfaceHandler>
     proxy_handler;
 
+JSBool HasInstance(JSContext *context, JS::HandleObject type,
+                   JS::MutableHandleValue vp, JSBool *success) {
+  JS::RootedObject global_object(
+      context, JS_GetGlobalForObject(context, type));
+  DCHECK(global_object);
+
+  JS::RootedObject prototype(
+      context, MozjsCallbackFunctionInterface::GetPrototype(context, global_object));
+
+  // |IsDelegate| walks the prototype chain of an object returning true if
+  // .prototype is found.
+  bool is_delegate;
+  if (!IsDelegate(context, prototype, vp, &is_delegate)) {
+    *success = false;
+    return false;
+  }
+
+  *success = is_delegate;
+  return true;
+}
 
 InterfaceData* CreateCachedInterfaceData() {
   InterfaceData* interface_data = new InterfaceData();
@@ -166,6 +186,7 @@
   interface_object_class->enumerate = JS_EnumerateStub;
   interface_object_class->resolve = JS_ResolveStub;
   interface_object_class->convert = JS_ConvertStub;
+  interface_object_class->hasInstance = &HasInstance;
   return interface_data;
 }
 
@@ -561,14 +582,12 @@
 };
 
 void InitializePrototypeAndInterfaceObject(
-    InterfaceData* interface_data, JSContext* context) {
+    InterfaceData* interface_data, JSContext* context,
+    JS::HandleObject global_object) {
   DCHECK(!interface_data->prototype);
   DCHECK(!interface_data->interface_object);
+  DCHECK(JS_IsGlobalObject(global_object));
 
-  MozjsGlobalObjectProxy* global_object_proxy =
-      static_cast<MozjsGlobalObjectProxy*>(JS_GetContextPrivate(context));
-  JS::RootedObject global_object(context, global_object_proxy->global_object());
-  DCHECK(global_object);
   JS::RootedObject parent_prototype(
       context, JS_GetObjectPrototype(context, global_object));
   DCHECK(parent_prototype);
@@ -647,8 +666,11 @@
 // static
 JSObject* MozjsCallbackFunctionInterface::CreateProxy(
     JSContext* context, const scoped_refptr<Wrappable>& wrappable) {
+  JS::RootedObject global_object(context, JS_GetGlobalForScopeChain(context));
+  DCHECK(global_object);
+
   InterfaceData* interface_data = GetInterfaceData(context);
-  JS::RootedObject prototype(context, GetPrototype(context));
+  JS::RootedObject prototype(context, GetPrototype(context, global_object));
   DCHECK(prototype);
   JS::RootedObject new_object(context, JS_NewObjectWithGivenProto(
       context, &interface_data->instance_class_definition, prototype, NULL));
@@ -656,34 +678,45 @@
   JS::RootedObject proxy(context,
       ProxyHandler::NewProxy(context, new_object, prototype, NULL,
                              proxy_handler.Pointer()));
-  WrapperPrivate::AddPrivateData(proxy, wrappable);
+  WrapperPrivate::AddPrivateData(context, proxy, wrappable);
   return proxy;
 }
 
 //static
 const JSClass* MozjsCallbackFunctionInterface::PrototypeClass(
       JSContext* context) {
-  JS::RootedObject prototype(context, GetPrototype(context));
+  JS::RootedObject global_object(context, JS_GetGlobalForScopeChain(context));
+  DCHECK(global_object);
+
+  JS::RootedObject prototype(context, GetPrototype(context, global_object));
   JSClass* proto_class = JS_GetClass(*prototype.address());
   return proto_class;
 }
 
 // static
-JSObject* MozjsCallbackFunctionInterface::GetPrototype(JSContext* context) {
+JSObject* MozjsCallbackFunctionInterface::GetPrototype(
+    JSContext* context, JS::HandleObject global_object) {
+  DCHECK(JS_IsGlobalObject(global_object));
+
   InterfaceData* interface_data = GetInterfaceData(context);
   if (!interface_data->prototype) {
     // Create new prototype that has all the props and methods
-    InitializePrototypeAndInterfaceObject(interface_data, context);
+    InitializePrototypeAndInterfaceObject(
+        interface_data, context, global_object);
   }
   DCHECK(interface_data->prototype);
   return interface_data->prototype;
 }
 
 // static
-JSObject* MozjsCallbackFunctionInterface::GetInterfaceObject(JSContext* context) {
+JSObject* MozjsCallbackFunctionInterface::GetInterfaceObject(
+    JSContext* context, JS::HandleObject global_object) {
+  DCHECK(JS_IsGlobalObject(global_object));
+
   InterfaceData* interface_data = GetInterfaceData(context);
   if (!interface_data->interface_object) {
-    InitializePrototypeAndInterfaceObject(interface_data, context);
+    InitializePrototypeAndInterfaceObject(
+        interface_data, context, global_object);
   }
   DCHECK(interface_data->interface_object);
   return interface_data->interface_object;
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsCallbackFunctionInterface.h b/src/cobalt/bindings/generated/mozjs/testing/MozjsCallbackFunctionInterface.h
index e85e0f2..dea49b2 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsCallbackFunctionInterface.h
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsCallbackFunctionInterface.h
@@ -41,8 +41,10 @@
   static JSObject* CreateProxy(JSContext* context,
       const scoped_refptr<script::Wrappable>& wrappable);
   static const JSClass* PrototypeClass(JSContext* context);
-  static JSObject* GetPrototype(JSContext* context);
-  static JSObject* GetInterfaceObject(JSContext* context);
+  static JSObject* GetPrototype(JSContext* context,
+                                JS::HandleObject global_object);
+  static JSObject* GetInterfaceObject(JSContext* context,
+                                      JS::HandleObject global_object);
 };
 
 }  // namespace bindings
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsCallbackInterfaceInterface.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsCallbackInterfaceInterface.cc
index 3a9b54c..b387cf6 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsCallbackInterfaceInterface.cc
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsCallbackInterfaceInterface.cc
@@ -118,6 +118,26 @@
 static base::LazyInstance<MozjsCallbackInterfaceInterfaceHandler>
     proxy_handler;
 
+JSBool HasInstance(JSContext *context, JS::HandleObject type,
+                   JS::MutableHandleValue vp, JSBool *success) {
+  JS::RootedObject global_object(
+      context, JS_GetGlobalForObject(context, type));
+  DCHECK(global_object);
+
+  JS::RootedObject prototype(
+      context, MozjsCallbackInterfaceInterface::GetPrototype(context, global_object));
+
+  // |IsDelegate| walks the prototype chain of an object returning true if
+  // .prototype is found.
+  bool is_delegate;
+  if (!IsDelegate(context, prototype, vp, &is_delegate)) {
+    *success = false;
+    return false;
+  }
+
+  *success = is_delegate;
+  return true;
+}
 
 InterfaceData* CreateCachedInterfaceData() {
   InterfaceData* interface_data = new InterfaceData();
@@ -166,6 +186,7 @@
   interface_object_class->enumerate = JS_EnumerateStub;
   interface_object_class->resolve = JS_ResolveStub;
   interface_object_class->convert = JS_ConvertStub;
+  interface_object_class->hasInstance = &HasInstance;
   return interface_data;
 }
 
@@ -330,14 +351,12 @@
 };
 
 void InitializePrototypeAndInterfaceObject(
-    InterfaceData* interface_data, JSContext* context) {
+    InterfaceData* interface_data, JSContext* context,
+    JS::HandleObject global_object) {
   DCHECK(!interface_data->prototype);
   DCHECK(!interface_data->interface_object);
+  DCHECK(JS_IsGlobalObject(global_object));
 
-  MozjsGlobalObjectProxy* global_object_proxy =
-      static_cast<MozjsGlobalObjectProxy*>(JS_GetContextPrivate(context));
-  JS::RootedObject global_object(context, global_object_proxy->global_object());
-  DCHECK(global_object);
   JS::RootedObject parent_prototype(
       context, JS_GetObjectPrototype(context, global_object));
   DCHECK(parent_prototype);
@@ -416,8 +435,11 @@
 // static
 JSObject* MozjsCallbackInterfaceInterface::CreateProxy(
     JSContext* context, const scoped_refptr<Wrappable>& wrappable) {
+  JS::RootedObject global_object(context, JS_GetGlobalForScopeChain(context));
+  DCHECK(global_object);
+
   InterfaceData* interface_data = GetInterfaceData(context);
-  JS::RootedObject prototype(context, GetPrototype(context));
+  JS::RootedObject prototype(context, GetPrototype(context, global_object));
   DCHECK(prototype);
   JS::RootedObject new_object(context, JS_NewObjectWithGivenProto(
       context, &interface_data->instance_class_definition, prototype, NULL));
@@ -425,34 +447,45 @@
   JS::RootedObject proxy(context,
       ProxyHandler::NewProxy(context, new_object, prototype, NULL,
                              proxy_handler.Pointer()));
-  WrapperPrivate::AddPrivateData(proxy, wrappable);
+  WrapperPrivate::AddPrivateData(context, proxy, wrappable);
   return proxy;
 }
 
 //static
 const JSClass* MozjsCallbackInterfaceInterface::PrototypeClass(
       JSContext* context) {
-  JS::RootedObject prototype(context, GetPrototype(context));
+  JS::RootedObject global_object(context, JS_GetGlobalForScopeChain(context));
+  DCHECK(global_object);
+
+  JS::RootedObject prototype(context, GetPrototype(context, global_object));
   JSClass* proto_class = JS_GetClass(*prototype.address());
   return proto_class;
 }
 
 // static
-JSObject* MozjsCallbackInterfaceInterface::GetPrototype(JSContext* context) {
+JSObject* MozjsCallbackInterfaceInterface::GetPrototype(
+    JSContext* context, JS::HandleObject global_object) {
+  DCHECK(JS_IsGlobalObject(global_object));
+
   InterfaceData* interface_data = GetInterfaceData(context);
   if (!interface_data->prototype) {
     // Create new prototype that has all the props and methods
-    InitializePrototypeAndInterfaceObject(interface_data, context);
+    InitializePrototypeAndInterfaceObject(
+        interface_data, context, global_object);
   }
   DCHECK(interface_data->prototype);
   return interface_data->prototype;
 }
 
 // static
-JSObject* MozjsCallbackInterfaceInterface::GetInterfaceObject(JSContext* context) {
+JSObject* MozjsCallbackInterfaceInterface::GetInterfaceObject(
+    JSContext* context, JS::HandleObject global_object) {
+  DCHECK(JS_IsGlobalObject(global_object));
+
   InterfaceData* interface_data = GetInterfaceData(context);
   if (!interface_data->interface_object) {
-    InitializePrototypeAndInterfaceObject(interface_data, context);
+    InitializePrototypeAndInterfaceObject(
+        interface_data, context, global_object);
   }
   DCHECK(interface_data->interface_object);
   return interface_data->interface_object;
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsCallbackInterfaceInterface.h b/src/cobalt/bindings/generated/mozjs/testing/MozjsCallbackInterfaceInterface.h
index ea10dca..788a86f 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsCallbackInterfaceInterface.h
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsCallbackInterfaceInterface.h
@@ -41,8 +41,10 @@
   static JSObject* CreateProxy(JSContext* context,
       const scoped_refptr<script::Wrappable>& wrappable);
   static const JSClass* PrototypeClass(JSContext* context);
-  static JSObject* GetPrototype(JSContext* context);
-  static JSObject* GetInterfaceObject(JSContext* context);
+  static JSObject* GetPrototype(JSContext* context,
+                                JS::HandleObject global_object);
+  static JSObject* GetInterfaceObject(JSContext* context,
+                                      JS::HandleObject global_object);
 };
 
 }  // namespace bindings
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsConditionalInterface.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsConditionalInterface.cc
index eae8530..dcf4ed6 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsConditionalInterface.cc
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsConditionalInterface.cc
@@ -116,6 +116,26 @@
 static base::LazyInstance<MozjsConditionalInterfaceHandler>
     proxy_handler;
 
+JSBool HasInstance(JSContext *context, JS::HandleObject type,
+                   JS::MutableHandleValue vp, JSBool *success) {
+  JS::RootedObject global_object(
+      context, JS_GetGlobalForObject(context, type));
+  DCHECK(global_object);
+
+  JS::RootedObject prototype(
+      context, MozjsConditionalInterface::GetPrototype(context, global_object));
+
+  // |IsDelegate| walks the prototype chain of an object returning true if
+  // .prototype is found.
+  bool is_delegate;
+  if (!IsDelegate(context, prototype, vp, &is_delegate)) {
+    *success = false;
+    return false;
+  }
+
+  *success = is_delegate;
+  return true;
+}
 
 InterfaceData* CreateCachedInterfaceData() {
   InterfaceData* interface_data = new InterfaceData();
@@ -164,6 +184,7 @@
   interface_object_class->enumerate = JS_EnumerateStub;
   interface_object_class->resolve = JS_ResolveStub;
   interface_object_class->convert = JS_ConvertStub;
+  interface_object_class->hasInstance = &HasInstance;
   return interface_data;
 }
 
@@ -375,14 +396,12 @@
 };
 
 void InitializePrototypeAndInterfaceObject(
-    InterfaceData* interface_data, JSContext* context) {
+    InterfaceData* interface_data, JSContext* context,
+    JS::HandleObject global_object) {
   DCHECK(!interface_data->prototype);
   DCHECK(!interface_data->interface_object);
+  DCHECK(JS_IsGlobalObject(global_object));
 
-  MozjsGlobalObjectProxy* global_object_proxy =
-      static_cast<MozjsGlobalObjectProxy*>(JS_GetContextPrivate(context));
-  JS::RootedObject global_object(context, global_object_proxy->global_object());
-  DCHECK(global_object);
   JS::RootedObject parent_prototype(
       context, JS_GetObjectPrototype(context, global_object));
   DCHECK(parent_prototype);
@@ -461,8 +480,11 @@
 // static
 JSObject* MozjsConditionalInterface::CreateProxy(
     JSContext* context, const scoped_refptr<Wrappable>& wrappable) {
+  JS::RootedObject global_object(context, JS_GetGlobalForScopeChain(context));
+  DCHECK(global_object);
+
   InterfaceData* interface_data = GetInterfaceData(context);
-  JS::RootedObject prototype(context, GetPrototype(context));
+  JS::RootedObject prototype(context, GetPrototype(context, global_object));
   DCHECK(prototype);
   JS::RootedObject new_object(context, JS_NewObjectWithGivenProto(
       context, &interface_data->instance_class_definition, prototype, NULL));
@@ -470,34 +492,45 @@
   JS::RootedObject proxy(context,
       ProxyHandler::NewProxy(context, new_object, prototype, NULL,
                              proxy_handler.Pointer()));
-  WrapperPrivate::AddPrivateData(proxy, wrappable);
+  WrapperPrivate::AddPrivateData(context, proxy, wrappable);
   return proxy;
 }
 
 //static
 const JSClass* MozjsConditionalInterface::PrototypeClass(
       JSContext* context) {
-  JS::RootedObject prototype(context, GetPrototype(context));
+  JS::RootedObject global_object(context, JS_GetGlobalForScopeChain(context));
+  DCHECK(global_object);
+
+  JS::RootedObject prototype(context, GetPrototype(context, global_object));
   JSClass* proto_class = JS_GetClass(*prototype.address());
   return proto_class;
 }
 
 // static
-JSObject* MozjsConditionalInterface::GetPrototype(JSContext* context) {
+JSObject* MozjsConditionalInterface::GetPrototype(
+    JSContext* context, JS::HandleObject global_object) {
+  DCHECK(JS_IsGlobalObject(global_object));
+
   InterfaceData* interface_data = GetInterfaceData(context);
   if (!interface_data->prototype) {
     // Create new prototype that has all the props and methods
-    InitializePrototypeAndInterfaceObject(interface_data, context);
+    InitializePrototypeAndInterfaceObject(
+        interface_data, context, global_object);
   }
   DCHECK(interface_data->prototype);
   return interface_data->prototype;
 }
 
 // static
-JSObject* MozjsConditionalInterface::GetInterfaceObject(JSContext* context) {
+JSObject* MozjsConditionalInterface::GetInterfaceObject(
+    JSContext* context, JS::HandleObject global_object) {
+  DCHECK(JS_IsGlobalObject(global_object));
+
   InterfaceData* interface_data = GetInterfaceData(context);
   if (!interface_data->interface_object) {
-    InitializePrototypeAndInterfaceObject(interface_data, context);
+    InitializePrototypeAndInterfaceObject(
+        interface_data, context, global_object);
   }
   DCHECK(interface_data->interface_object);
   return interface_data->interface_object;
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsConditionalInterface.h b/src/cobalt/bindings/generated/mozjs/testing/MozjsConditionalInterface.h
index 76eae81..ea935c1 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsConditionalInterface.h
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsConditionalInterface.h
@@ -43,8 +43,10 @@
   static JSObject* CreateProxy(JSContext* context,
       const scoped_refptr<script::Wrappable>& wrappable);
   static const JSClass* PrototypeClass(JSContext* context);
-  static JSObject* GetPrototype(JSContext* context);
-  static JSObject* GetInterfaceObject(JSContext* context);
+  static JSObject* GetPrototype(JSContext* context,
+                                JS::HandleObject global_object);
+  static JSObject* GetInterfaceObject(JSContext* context,
+                                      JS::HandleObject global_object);
 };
 
 }  // namespace bindings
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsConstantsInterface.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsConstantsInterface.cc
index 06ca83e..467b6de 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsConstantsInterface.cc
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsConstantsInterface.cc
@@ -143,6 +143,26 @@
   return !exception_state.is_exception_set();
 }
 
+JSBool HasInstance(JSContext *context, JS::HandleObject type,
+                   JS::MutableHandleValue vp, JSBool *success) {
+  JS::RootedObject global_object(
+      context, JS_GetGlobalForObject(context, type));
+  DCHECK(global_object);
+
+  JS::RootedObject prototype(
+      context, MozjsConstantsInterface::GetPrototype(context, global_object));
+
+  // |IsDelegate| walks the prototype chain of an object returning true if
+  // .prototype is found.
+  bool is_delegate;
+  if (!IsDelegate(context, prototype, vp, &is_delegate)) {
+    *success = false;
+    return false;
+  }
+
+  *success = is_delegate;
+  return true;
+}
 
 InterfaceData* CreateCachedInterfaceData() {
   InterfaceData* interface_data = new InterfaceData();
@@ -191,6 +211,7 @@
   interface_object_class->enumerate = JS_EnumerateStub;
   interface_object_class->resolve = JS_ResolveStub;
   interface_object_class->convert = JS_ConvertStub;
+  interface_object_class->hasInstance = &HasInstance;
   return interface_data;
 }
 
@@ -240,14 +261,12 @@
 };
 
 void InitializePrototypeAndInterfaceObject(
-    InterfaceData* interface_data, JSContext* context) {
+    InterfaceData* interface_data, JSContext* context,
+    JS::HandleObject global_object) {
   DCHECK(!interface_data->prototype);
   DCHECK(!interface_data->interface_object);
+  DCHECK(JS_IsGlobalObject(global_object));
 
-  MozjsGlobalObjectProxy* global_object_proxy =
-      static_cast<MozjsGlobalObjectProxy*>(JS_GetContextPrivate(context));
-  JS::RootedObject global_object(context, global_object_proxy->global_object());
-  DCHECK(global_object);
   JS::RootedObject parent_prototype(
       context, JS_GetObjectPrototype(context, global_object));
   DCHECK(parent_prototype);
@@ -326,8 +345,11 @@
 // static
 JSObject* MozjsConstantsInterface::CreateProxy(
     JSContext* context, const scoped_refptr<Wrappable>& wrappable) {
+  JS::RootedObject global_object(context, JS_GetGlobalForScopeChain(context));
+  DCHECK(global_object);
+
   InterfaceData* interface_data = GetInterfaceData(context);
-  JS::RootedObject prototype(context, GetPrototype(context));
+  JS::RootedObject prototype(context, GetPrototype(context, global_object));
   DCHECK(prototype);
   JS::RootedObject new_object(context, JS_NewObjectWithGivenProto(
       context, &interface_data->instance_class_definition, prototype, NULL));
@@ -335,34 +357,45 @@
   JS::RootedObject proxy(context,
       ProxyHandler::NewProxy(context, new_object, prototype, NULL,
                              proxy_handler.Pointer()));
-  WrapperPrivate::AddPrivateData(proxy, wrappable);
+  WrapperPrivate::AddPrivateData(context, proxy, wrappable);
   return proxy;
 }
 
 //static
 const JSClass* MozjsConstantsInterface::PrototypeClass(
       JSContext* context) {
-  JS::RootedObject prototype(context, GetPrototype(context));
+  JS::RootedObject global_object(context, JS_GetGlobalForScopeChain(context));
+  DCHECK(global_object);
+
+  JS::RootedObject prototype(context, GetPrototype(context, global_object));
   JSClass* proto_class = JS_GetClass(*prototype.address());
   return proto_class;
 }
 
 // static
-JSObject* MozjsConstantsInterface::GetPrototype(JSContext* context) {
+JSObject* MozjsConstantsInterface::GetPrototype(
+    JSContext* context, JS::HandleObject global_object) {
+  DCHECK(JS_IsGlobalObject(global_object));
+
   InterfaceData* interface_data = GetInterfaceData(context);
   if (!interface_data->prototype) {
     // Create new prototype that has all the props and methods
-    InitializePrototypeAndInterfaceObject(interface_data, context);
+    InitializePrototypeAndInterfaceObject(
+        interface_data, context, global_object);
   }
   DCHECK(interface_data->prototype);
   return interface_data->prototype;
 }
 
 // static
-JSObject* MozjsConstantsInterface::GetInterfaceObject(JSContext* context) {
+JSObject* MozjsConstantsInterface::GetInterfaceObject(
+    JSContext* context, JS::HandleObject global_object) {
+  DCHECK(JS_IsGlobalObject(global_object));
+
   InterfaceData* interface_data = GetInterfaceData(context);
   if (!interface_data->interface_object) {
-    InitializePrototypeAndInterfaceObject(interface_data, context);
+    InitializePrototypeAndInterfaceObject(
+        interface_data, context, global_object);
   }
   DCHECK(interface_data->interface_object);
   return interface_data->interface_object;
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsConstantsInterface.h b/src/cobalt/bindings/generated/mozjs/testing/MozjsConstantsInterface.h
index fe793ef..3501f0f 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsConstantsInterface.h
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsConstantsInterface.h
@@ -41,8 +41,10 @@
   static JSObject* CreateProxy(JSContext* context,
       const scoped_refptr<script::Wrappable>& wrappable);
   static const JSClass* PrototypeClass(JSContext* context);
-  static JSObject* GetPrototype(JSContext* context);
-  static JSObject* GetInterfaceObject(JSContext* context);
+  static JSObject* GetPrototype(JSContext* context,
+                                JS::HandleObject global_object);
+  static JSObject* GetInterfaceObject(JSContext* context,
+                                      JS::HandleObject global_object);
 };
 
 }  // namespace bindings
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsConstructorInterface.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsConstructorInterface.cc
index 7ca19b8..8367aeb 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsConstructorInterface.cc
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsConstructorInterface.cc
@@ -115,6 +115,26 @@
     proxy_handler;
 
 JSBool Constructor(JSContext* context, unsigned int argc, JS::Value* vp);
+JSBool HasInstance(JSContext *context, JS::HandleObject type,
+                   JS::MutableHandleValue vp, JSBool *success) {
+  JS::RootedObject global_object(
+      context, JS_GetGlobalForObject(context, type));
+  DCHECK(global_object);
+
+  JS::RootedObject prototype(
+      context, MozjsConstructorInterface::GetPrototype(context, global_object));
+
+  // |IsDelegate| walks the prototype chain of an object returning true if
+  // .prototype is found.
+  bool is_delegate;
+  if (!IsDelegate(context, prototype, vp, &is_delegate)) {
+    *success = false;
+    return false;
+  }
+
+  *success = is_delegate;
+  return true;
+}
 
 InterfaceData* CreateCachedInterfaceData() {
   InterfaceData* interface_data = new InterfaceData();
@@ -163,6 +183,7 @@
   interface_object_class->enumerate = JS_EnumerateStub;
   interface_object_class->resolve = JS_ResolveStub;
   interface_object_class->convert = JS_ConvertStub;
+  interface_object_class->hasInstance = &HasInstance;
   interface_object_class->construct = Constructor;
   return interface_data;
 }
@@ -189,14 +210,12 @@
 };
 
 void InitializePrototypeAndInterfaceObject(
-    InterfaceData* interface_data, JSContext* context) {
+    InterfaceData* interface_data, JSContext* context,
+    JS::HandleObject global_object) {
   DCHECK(!interface_data->prototype);
   DCHECK(!interface_data->interface_object);
+  DCHECK(JS_IsGlobalObject(global_object));
 
-  MozjsGlobalObjectProxy* global_object_proxy =
-      static_cast<MozjsGlobalObjectProxy*>(JS_GetContextPrivate(context));
-  JS::RootedObject global_object(context, global_object_proxy->global_object());
-  DCHECK(global_object);
   JS::RootedObject parent_prototype(
       context, JS_GetObjectPrototype(context, global_object));
   DCHECK(parent_prototype);
@@ -285,8 +304,11 @@
 // static
 JSObject* MozjsConstructorInterface::CreateProxy(
     JSContext* context, const scoped_refptr<Wrappable>& wrappable) {
+  JS::RootedObject global_object(context, JS_GetGlobalForScopeChain(context));
+  DCHECK(global_object);
+
   InterfaceData* interface_data = GetInterfaceData(context);
-  JS::RootedObject prototype(context, GetPrototype(context));
+  JS::RootedObject prototype(context, GetPrototype(context, global_object));
   DCHECK(prototype);
   JS::RootedObject new_object(context, JS_NewObjectWithGivenProto(
       context, &interface_data->instance_class_definition, prototype, NULL));
@@ -294,34 +316,45 @@
   JS::RootedObject proxy(context,
       ProxyHandler::NewProxy(context, new_object, prototype, NULL,
                              proxy_handler.Pointer()));
-  WrapperPrivate::AddPrivateData(proxy, wrappable);
+  WrapperPrivate::AddPrivateData(context, proxy, wrappable);
   return proxy;
 }
 
 //static
 const JSClass* MozjsConstructorInterface::PrototypeClass(
       JSContext* context) {
-  JS::RootedObject prototype(context, GetPrototype(context));
+  JS::RootedObject global_object(context, JS_GetGlobalForScopeChain(context));
+  DCHECK(global_object);
+
+  JS::RootedObject prototype(context, GetPrototype(context, global_object));
   JSClass* proto_class = JS_GetClass(*prototype.address());
   return proto_class;
 }
 
 // static
-JSObject* MozjsConstructorInterface::GetPrototype(JSContext* context) {
+JSObject* MozjsConstructorInterface::GetPrototype(
+    JSContext* context, JS::HandleObject global_object) {
+  DCHECK(JS_IsGlobalObject(global_object));
+
   InterfaceData* interface_data = GetInterfaceData(context);
   if (!interface_data->prototype) {
     // Create new prototype that has all the props and methods
-    InitializePrototypeAndInterfaceObject(interface_data, context);
+    InitializePrototypeAndInterfaceObject(
+        interface_data, context, global_object);
   }
   DCHECK(interface_data->prototype);
   return interface_data->prototype;
 }
 
 // static
-JSObject* MozjsConstructorInterface::GetInterfaceObject(JSContext* context) {
+JSObject* MozjsConstructorInterface::GetInterfaceObject(
+    JSContext* context, JS::HandleObject global_object) {
+  DCHECK(JS_IsGlobalObject(global_object));
+
   InterfaceData* interface_data = GetInterfaceData(context);
   if (!interface_data->interface_object) {
-    InitializePrototypeAndInterfaceObject(interface_data, context);
+    InitializePrototypeAndInterfaceObject(
+        interface_data, context, global_object);
   }
   DCHECK(interface_data->interface_object);
   return interface_data->interface_object;
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsConstructorInterface.h b/src/cobalt/bindings/generated/mozjs/testing/MozjsConstructorInterface.h
index d04a69f..ccf6f57 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsConstructorInterface.h
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsConstructorInterface.h
@@ -41,8 +41,10 @@
   static JSObject* CreateProxy(JSContext* context,
       const scoped_refptr<script::Wrappable>& wrappable);
   static const JSClass* PrototypeClass(JSContext* context);
-  static JSObject* GetPrototype(JSContext* context);
-  static JSObject* GetInterfaceObject(JSContext* context);
+  static JSObject* GetPrototype(JSContext* context,
+                                JS::HandleObject global_object);
+  static JSObject* GetInterfaceObject(JSContext* context,
+                                      JS::HandleObject global_object);
 };
 
 }  // namespace bindings
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsConstructorWithArgumentsInterface.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsConstructorWithArgumentsInterface.cc
index cdc6b94..bcf7385 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsConstructorWithArgumentsInterface.cc
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsConstructorWithArgumentsInterface.cc
@@ -115,6 +115,26 @@
     proxy_handler;
 
 JSBool Constructor(JSContext* context, unsigned int argc, JS::Value* vp);
+JSBool HasInstance(JSContext *context, JS::HandleObject type,
+                   JS::MutableHandleValue vp, JSBool *success) {
+  JS::RootedObject global_object(
+      context, JS_GetGlobalForObject(context, type));
+  DCHECK(global_object);
+
+  JS::RootedObject prototype(
+      context, MozjsConstructorWithArgumentsInterface::GetPrototype(context, global_object));
+
+  // |IsDelegate| walks the prototype chain of an object returning true if
+  // .prototype is found.
+  bool is_delegate;
+  if (!IsDelegate(context, prototype, vp, &is_delegate)) {
+    *success = false;
+    return false;
+  }
+
+  *success = is_delegate;
+  return true;
+}
 
 InterfaceData* CreateCachedInterfaceData() {
   InterfaceData* interface_data = new InterfaceData();
@@ -163,6 +183,7 @@
   interface_object_class->enumerate = JS_EnumerateStub;
   interface_object_class->resolve = JS_ResolveStub;
   interface_object_class->convert = JS_ConvertStub;
+  interface_object_class->hasInstance = &HasInstance;
   interface_object_class->construct = Constructor;
   return interface_data;
 }
@@ -273,14 +294,12 @@
 };
 
 void InitializePrototypeAndInterfaceObject(
-    InterfaceData* interface_data, JSContext* context) {
+    InterfaceData* interface_data, JSContext* context,
+    JS::HandleObject global_object) {
   DCHECK(!interface_data->prototype);
   DCHECK(!interface_data->interface_object);
+  DCHECK(JS_IsGlobalObject(global_object));
 
-  MozjsGlobalObjectProxy* global_object_proxy =
-      static_cast<MozjsGlobalObjectProxy*>(JS_GetContextPrivate(context));
-  JS::RootedObject global_object(context, global_object_proxy->global_object());
-  DCHECK(global_object);
   JS::RootedObject parent_prototype(
       context, JS_GetObjectPrototype(context, global_object));
   DCHECK(parent_prototype);
@@ -369,8 +388,11 @@
 // static
 JSObject* MozjsConstructorWithArgumentsInterface::CreateProxy(
     JSContext* context, const scoped_refptr<Wrappable>& wrappable) {
+  JS::RootedObject global_object(context, JS_GetGlobalForScopeChain(context));
+  DCHECK(global_object);
+
   InterfaceData* interface_data = GetInterfaceData(context);
-  JS::RootedObject prototype(context, GetPrototype(context));
+  JS::RootedObject prototype(context, GetPrototype(context, global_object));
   DCHECK(prototype);
   JS::RootedObject new_object(context, JS_NewObjectWithGivenProto(
       context, &interface_data->instance_class_definition, prototype, NULL));
@@ -378,34 +400,45 @@
   JS::RootedObject proxy(context,
       ProxyHandler::NewProxy(context, new_object, prototype, NULL,
                              proxy_handler.Pointer()));
-  WrapperPrivate::AddPrivateData(proxy, wrappable);
+  WrapperPrivate::AddPrivateData(context, proxy, wrappable);
   return proxy;
 }
 
 //static
 const JSClass* MozjsConstructorWithArgumentsInterface::PrototypeClass(
       JSContext* context) {
-  JS::RootedObject prototype(context, GetPrototype(context));
+  JS::RootedObject global_object(context, JS_GetGlobalForScopeChain(context));
+  DCHECK(global_object);
+
+  JS::RootedObject prototype(context, GetPrototype(context, global_object));
   JSClass* proto_class = JS_GetClass(*prototype.address());
   return proto_class;
 }
 
 // static
-JSObject* MozjsConstructorWithArgumentsInterface::GetPrototype(JSContext* context) {
+JSObject* MozjsConstructorWithArgumentsInterface::GetPrototype(
+    JSContext* context, JS::HandleObject global_object) {
+  DCHECK(JS_IsGlobalObject(global_object));
+
   InterfaceData* interface_data = GetInterfaceData(context);
   if (!interface_data->prototype) {
     // Create new prototype that has all the props and methods
-    InitializePrototypeAndInterfaceObject(interface_data, context);
+    InitializePrototypeAndInterfaceObject(
+        interface_data, context, global_object);
   }
   DCHECK(interface_data->prototype);
   return interface_data->prototype;
 }
 
 // static
-JSObject* MozjsConstructorWithArgumentsInterface::GetInterfaceObject(JSContext* context) {
+JSObject* MozjsConstructorWithArgumentsInterface::GetInterfaceObject(
+    JSContext* context, JS::HandleObject global_object) {
+  DCHECK(JS_IsGlobalObject(global_object));
+
   InterfaceData* interface_data = GetInterfaceData(context);
   if (!interface_data->interface_object) {
-    InitializePrototypeAndInterfaceObject(interface_data, context);
+    InitializePrototypeAndInterfaceObject(
+        interface_data, context, global_object);
   }
   DCHECK(interface_data->interface_object);
   return interface_data->interface_object;
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsConstructorWithArgumentsInterface.h b/src/cobalt/bindings/generated/mozjs/testing/MozjsConstructorWithArgumentsInterface.h
index 44d36d4..76c43fc 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsConstructorWithArgumentsInterface.h
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsConstructorWithArgumentsInterface.h
@@ -41,8 +41,10 @@
   static JSObject* CreateProxy(JSContext* context,
       const scoped_refptr<script::Wrappable>& wrappable);
   static const JSClass* PrototypeClass(JSContext* context);
-  static JSObject* GetPrototype(JSContext* context);
-  static JSObject* GetInterfaceObject(JSContext* context);
+  static JSObject* GetPrototype(JSContext* context,
+                                JS::HandleObject global_object);
+  static JSObject* GetInterfaceObject(JSContext* context,
+                                      JS::HandleObject global_object);
 };
 
 }  // namespace bindings
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsDOMStringTestInterface.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsDOMStringTestInterface.cc
index bc6eb8b..18dd40a 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsDOMStringTestInterface.cc
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsDOMStringTestInterface.cc
@@ -114,6 +114,26 @@
 static base::LazyInstance<MozjsDOMStringTestInterfaceHandler>
     proxy_handler;
 
+JSBool HasInstance(JSContext *context, JS::HandleObject type,
+                   JS::MutableHandleValue vp, JSBool *success) {
+  JS::RootedObject global_object(
+      context, JS_GetGlobalForObject(context, type));
+  DCHECK(global_object);
+
+  JS::RootedObject prototype(
+      context, MozjsDOMStringTestInterface::GetPrototype(context, global_object));
+
+  // |IsDelegate| walks the prototype chain of an object returning true if
+  // .prototype is found.
+  bool is_delegate;
+  if (!IsDelegate(context, prototype, vp, &is_delegate)) {
+    *success = false;
+    return false;
+  }
+
+  *success = is_delegate;
+  return true;
+}
 
 InterfaceData* CreateCachedInterfaceData() {
   InterfaceData* interface_data = new InterfaceData();
@@ -162,6 +182,7 @@
   interface_object_class->enumerate = JS_EnumerateStub;
   interface_object_class->resolve = JS_ResolveStub;
   interface_object_class->convert = JS_ConvertStub;
+  interface_object_class->hasInstance = &HasInstance;
   return interface_data;
 }
 
@@ -443,14 +464,12 @@
 };
 
 void InitializePrototypeAndInterfaceObject(
-    InterfaceData* interface_data, JSContext* context) {
+    InterfaceData* interface_data, JSContext* context,
+    JS::HandleObject global_object) {
   DCHECK(!interface_data->prototype);
   DCHECK(!interface_data->interface_object);
+  DCHECK(JS_IsGlobalObject(global_object));
 
-  MozjsGlobalObjectProxy* global_object_proxy =
-      static_cast<MozjsGlobalObjectProxy*>(JS_GetContextPrivate(context));
-  JS::RootedObject global_object(context, global_object_proxy->global_object());
-  DCHECK(global_object);
   JS::RootedObject parent_prototype(
       context, JS_GetObjectPrototype(context, global_object));
   DCHECK(parent_prototype);
@@ -529,8 +548,11 @@
 // static
 JSObject* MozjsDOMStringTestInterface::CreateProxy(
     JSContext* context, const scoped_refptr<Wrappable>& wrappable) {
+  JS::RootedObject global_object(context, JS_GetGlobalForScopeChain(context));
+  DCHECK(global_object);
+
   InterfaceData* interface_data = GetInterfaceData(context);
-  JS::RootedObject prototype(context, GetPrototype(context));
+  JS::RootedObject prototype(context, GetPrototype(context, global_object));
   DCHECK(prototype);
   JS::RootedObject new_object(context, JS_NewObjectWithGivenProto(
       context, &interface_data->instance_class_definition, prototype, NULL));
@@ -538,34 +560,45 @@
   JS::RootedObject proxy(context,
       ProxyHandler::NewProxy(context, new_object, prototype, NULL,
                              proxy_handler.Pointer()));
-  WrapperPrivate::AddPrivateData(proxy, wrappable);
+  WrapperPrivate::AddPrivateData(context, proxy, wrappable);
   return proxy;
 }
 
 //static
 const JSClass* MozjsDOMStringTestInterface::PrototypeClass(
       JSContext* context) {
-  JS::RootedObject prototype(context, GetPrototype(context));
+  JS::RootedObject global_object(context, JS_GetGlobalForScopeChain(context));
+  DCHECK(global_object);
+
+  JS::RootedObject prototype(context, GetPrototype(context, global_object));
   JSClass* proto_class = JS_GetClass(*prototype.address());
   return proto_class;
 }
 
 // static
-JSObject* MozjsDOMStringTestInterface::GetPrototype(JSContext* context) {
+JSObject* MozjsDOMStringTestInterface::GetPrototype(
+    JSContext* context, JS::HandleObject global_object) {
+  DCHECK(JS_IsGlobalObject(global_object));
+
   InterfaceData* interface_data = GetInterfaceData(context);
   if (!interface_data->prototype) {
     // Create new prototype that has all the props and methods
-    InitializePrototypeAndInterfaceObject(interface_data, context);
+    InitializePrototypeAndInterfaceObject(
+        interface_data, context, global_object);
   }
   DCHECK(interface_data->prototype);
   return interface_data->prototype;
 }
 
 // static
-JSObject* MozjsDOMStringTestInterface::GetInterfaceObject(JSContext* context) {
+JSObject* MozjsDOMStringTestInterface::GetInterfaceObject(
+    JSContext* context, JS::HandleObject global_object) {
+  DCHECK(JS_IsGlobalObject(global_object));
+
   InterfaceData* interface_data = GetInterfaceData(context);
   if (!interface_data->interface_object) {
-    InitializePrototypeAndInterfaceObject(interface_data, context);
+    InitializePrototypeAndInterfaceObject(
+        interface_data, context, global_object);
   }
   DCHECK(interface_data->interface_object);
   return interface_data->interface_object;
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsDOMStringTestInterface.h b/src/cobalt/bindings/generated/mozjs/testing/MozjsDOMStringTestInterface.h
index 0cde0d8..875490c 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsDOMStringTestInterface.h
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsDOMStringTestInterface.h
@@ -41,8 +41,10 @@
   static JSObject* CreateProxy(JSContext* context,
       const scoped_refptr<script::Wrappable>& wrappable);
   static const JSClass* PrototypeClass(JSContext* context);
-  static JSObject* GetPrototype(JSContext* context);
-  static JSObject* GetInterfaceObject(JSContext* context);
+  static JSObject* GetPrototype(JSContext* context,
+                                JS::HandleObject global_object);
+  static JSObject* GetInterfaceObject(JSContext* context,
+                                      JS::HandleObject global_object);
 };
 
 }  // namespace bindings
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsDerivedGetterSetterInterface.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsDerivedGetterSetterInterface.cc
index 7770e5c..e84fa83 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsDerivedGetterSetterInterface.cc
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsDerivedGetterSetterInterface.cc
@@ -296,6 +296,26 @@
 static base::LazyInstance<MozjsDerivedGetterSetterInterfaceHandler>
     proxy_handler;
 
+JSBool HasInstance(JSContext *context, JS::HandleObject type,
+                   JS::MutableHandleValue vp, JSBool *success) {
+  JS::RootedObject global_object(
+      context, JS_GetGlobalForObject(context, type));
+  DCHECK(global_object);
+
+  JS::RootedObject prototype(
+      context, MozjsDerivedGetterSetterInterface::GetPrototype(context, global_object));
+
+  // |IsDelegate| walks the prototype chain of an object returning true if
+  // .prototype is found.
+  bool is_delegate;
+  if (!IsDelegate(context, prototype, vp, &is_delegate)) {
+    *success = false;
+    return false;
+  }
+
+  *success = is_delegate;
+  return true;
+}
 
 InterfaceData* CreateCachedInterfaceData() {
   InterfaceData* interface_data = new InterfaceData();
@@ -344,6 +364,7 @@
   interface_object_class->enumerate = JS_EnumerateStub;
   interface_object_class->resolve = JS_ResolveStub;
   interface_object_class->convert = JS_ConvertStub;
+  interface_object_class->hasInstance = &HasInstance;
   return interface_data;
 }
 
@@ -608,16 +629,14 @@
 };
 
 void InitializePrototypeAndInterfaceObject(
-    InterfaceData* interface_data, JSContext* context) {
+    InterfaceData* interface_data, JSContext* context,
+    JS::HandleObject global_object) {
   DCHECK(!interface_data->prototype);
   DCHECK(!interface_data->interface_object);
+  DCHECK(JS_IsGlobalObject(global_object));
 
-  MozjsGlobalObjectProxy* global_object_proxy =
-      static_cast<MozjsGlobalObjectProxy*>(JS_GetContextPrivate(context));
-  JS::RootedObject global_object(context, global_object_proxy->global_object());
-  DCHECK(global_object);
   JS::RootedObject parent_prototype(
-      context, bindings::testing::MozjsNamedIndexedGetterInterface::GetPrototype(context));
+      context, bindings::testing::MozjsNamedIndexedGetterInterface::GetPrototype(context, global_object));
   DCHECK(parent_prototype);
 
   // Create the Prototype object.
@@ -694,8 +713,11 @@
 // static
 JSObject* MozjsDerivedGetterSetterInterface::CreateProxy(
     JSContext* context, const scoped_refptr<Wrappable>& wrappable) {
+  JS::RootedObject global_object(context, JS_GetGlobalForScopeChain(context));
+  DCHECK(global_object);
+
   InterfaceData* interface_data = GetInterfaceData(context);
-  JS::RootedObject prototype(context, GetPrototype(context));
+  JS::RootedObject prototype(context, GetPrototype(context, global_object));
   DCHECK(prototype);
   JS::RootedObject new_object(context, JS_NewObjectWithGivenProto(
       context, &interface_data->instance_class_definition, prototype, NULL));
@@ -703,34 +725,45 @@
   JS::RootedObject proxy(context,
       ProxyHandler::NewProxy(context, new_object, prototype, NULL,
                              proxy_handler.Pointer()));
-  WrapperPrivate::AddPrivateData(proxy, wrappable);
+  WrapperPrivate::AddPrivateData(context, proxy, wrappable);
   return proxy;
 }
 
 //static
 const JSClass* MozjsDerivedGetterSetterInterface::PrototypeClass(
       JSContext* context) {
-  JS::RootedObject prototype(context, GetPrototype(context));
+  JS::RootedObject global_object(context, JS_GetGlobalForScopeChain(context));
+  DCHECK(global_object);
+
+  JS::RootedObject prototype(context, GetPrototype(context, global_object));
   JSClass* proto_class = JS_GetClass(*prototype.address());
   return proto_class;
 }
 
 // static
-JSObject* MozjsDerivedGetterSetterInterface::GetPrototype(JSContext* context) {
+JSObject* MozjsDerivedGetterSetterInterface::GetPrototype(
+    JSContext* context, JS::HandleObject global_object) {
+  DCHECK(JS_IsGlobalObject(global_object));
+
   InterfaceData* interface_data = GetInterfaceData(context);
   if (!interface_data->prototype) {
     // Create new prototype that has all the props and methods
-    InitializePrototypeAndInterfaceObject(interface_data, context);
+    InitializePrototypeAndInterfaceObject(
+        interface_data, context, global_object);
   }
   DCHECK(interface_data->prototype);
   return interface_data->prototype;
 }
 
 // static
-JSObject* MozjsDerivedGetterSetterInterface::GetInterfaceObject(JSContext* context) {
+JSObject* MozjsDerivedGetterSetterInterface::GetInterfaceObject(
+    JSContext* context, JS::HandleObject global_object) {
+  DCHECK(JS_IsGlobalObject(global_object));
+
   InterfaceData* interface_data = GetInterfaceData(context);
   if (!interface_data->interface_object) {
-    InitializePrototypeAndInterfaceObject(interface_data, context);
+    InitializePrototypeAndInterfaceObject(
+        interface_data, context, global_object);
   }
   DCHECK(interface_data->interface_object);
   return interface_data->interface_object;
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsDerivedGetterSetterInterface.h b/src/cobalt/bindings/generated/mozjs/testing/MozjsDerivedGetterSetterInterface.h
index 6913c19..b0164cab 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsDerivedGetterSetterInterface.h
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsDerivedGetterSetterInterface.h
@@ -42,8 +42,10 @@
   static JSObject* CreateProxy(JSContext* context,
       const scoped_refptr<script::Wrappable>& wrappable);
   static const JSClass* PrototypeClass(JSContext* context);
-  static JSObject* GetPrototype(JSContext* context);
-  static JSObject* GetInterfaceObject(JSContext* context);
+  static JSObject* GetPrototype(JSContext* context,
+                                JS::HandleObject global_object);
+  static JSObject* GetInterfaceObject(JSContext* context,
+                                      JS::HandleObject global_object);
 };
 
 }  // namespace bindings
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsDerivedInterface.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsDerivedInterface.cc
index 96a27ce..3edab69 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsDerivedInterface.cc
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsDerivedInterface.cc
@@ -115,6 +115,26 @@
     proxy_handler;
 
 JSBool Constructor(JSContext* context, unsigned int argc, JS::Value* vp);
+JSBool HasInstance(JSContext *context, JS::HandleObject type,
+                   JS::MutableHandleValue vp, JSBool *success) {
+  JS::RootedObject global_object(
+      context, JS_GetGlobalForObject(context, type));
+  DCHECK(global_object);
+
+  JS::RootedObject prototype(
+      context, MozjsDerivedInterface::GetPrototype(context, global_object));
+
+  // |IsDelegate| walks the prototype chain of an object returning true if
+  // .prototype is found.
+  bool is_delegate;
+  if (!IsDelegate(context, prototype, vp, &is_delegate)) {
+    *success = false;
+    return false;
+  }
+
+  *success = is_delegate;
+  return true;
+}
 
 InterfaceData* CreateCachedInterfaceData() {
   InterfaceData* interface_data = new InterfaceData();
@@ -163,6 +183,7 @@
   interface_object_class->enumerate = JS_EnumerateStub;
   interface_object_class->resolve = JS_ResolveStub;
   interface_object_class->convert = JS_ConvertStub;
+  interface_object_class->hasInstance = &HasInstance;
   interface_object_class->construct = Constructor;
   return interface_data;
 }
@@ -252,16 +273,14 @@
 };
 
 void InitializePrototypeAndInterfaceObject(
-    InterfaceData* interface_data, JSContext* context) {
+    InterfaceData* interface_data, JSContext* context,
+    JS::HandleObject global_object) {
   DCHECK(!interface_data->prototype);
   DCHECK(!interface_data->interface_object);
+  DCHECK(JS_IsGlobalObject(global_object));
 
-  MozjsGlobalObjectProxy* global_object_proxy =
-      static_cast<MozjsGlobalObjectProxy*>(JS_GetContextPrivate(context));
-  JS::RootedObject global_object(context, global_object_proxy->global_object());
-  DCHECK(global_object);
   JS::RootedObject parent_prototype(
-      context, bindings::testing::MozjsBaseInterface::GetPrototype(context));
+      context, bindings::testing::MozjsBaseInterface::GetPrototype(context, global_object));
   DCHECK(parent_prototype);
 
   // Create the Prototype object.
@@ -348,8 +367,11 @@
 // static
 JSObject* MozjsDerivedInterface::CreateProxy(
     JSContext* context, const scoped_refptr<Wrappable>& wrappable) {
+  JS::RootedObject global_object(context, JS_GetGlobalForScopeChain(context));
+  DCHECK(global_object);
+
   InterfaceData* interface_data = GetInterfaceData(context);
-  JS::RootedObject prototype(context, GetPrototype(context));
+  JS::RootedObject prototype(context, GetPrototype(context, global_object));
   DCHECK(prototype);
   JS::RootedObject new_object(context, JS_NewObjectWithGivenProto(
       context, &interface_data->instance_class_definition, prototype, NULL));
@@ -357,34 +379,45 @@
   JS::RootedObject proxy(context,
       ProxyHandler::NewProxy(context, new_object, prototype, NULL,
                              proxy_handler.Pointer()));
-  WrapperPrivate::AddPrivateData(proxy, wrappable);
+  WrapperPrivate::AddPrivateData(context, proxy, wrappable);
   return proxy;
 }
 
 //static
 const JSClass* MozjsDerivedInterface::PrototypeClass(
       JSContext* context) {
-  JS::RootedObject prototype(context, GetPrototype(context));
+  JS::RootedObject global_object(context, JS_GetGlobalForScopeChain(context));
+  DCHECK(global_object);
+
+  JS::RootedObject prototype(context, GetPrototype(context, global_object));
   JSClass* proto_class = JS_GetClass(*prototype.address());
   return proto_class;
 }
 
 // static
-JSObject* MozjsDerivedInterface::GetPrototype(JSContext* context) {
+JSObject* MozjsDerivedInterface::GetPrototype(
+    JSContext* context, JS::HandleObject global_object) {
+  DCHECK(JS_IsGlobalObject(global_object));
+
   InterfaceData* interface_data = GetInterfaceData(context);
   if (!interface_data->prototype) {
     // Create new prototype that has all the props and methods
-    InitializePrototypeAndInterfaceObject(interface_data, context);
+    InitializePrototypeAndInterfaceObject(
+        interface_data, context, global_object);
   }
   DCHECK(interface_data->prototype);
   return interface_data->prototype;
 }
 
 // static
-JSObject* MozjsDerivedInterface::GetInterfaceObject(JSContext* context) {
+JSObject* MozjsDerivedInterface::GetInterfaceObject(
+    JSContext* context, JS::HandleObject global_object) {
+  DCHECK(JS_IsGlobalObject(global_object));
+
   InterfaceData* interface_data = GetInterfaceData(context);
   if (!interface_data->interface_object) {
-    InitializePrototypeAndInterfaceObject(interface_data, context);
+    InitializePrototypeAndInterfaceObject(
+        interface_data, context, global_object);
   }
   DCHECK(interface_data->interface_object);
   return interface_data->interface_object;
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsDerivedInterface.h b/src/cobalt/bindings/generated/mozjs/testing/MozjsDerivedInterface.h
index 59beb06..ac9780c 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsDerivedInterface.h
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsDerivedInterface.h
@@ -42,8 +42,10 @@
   static JSObject* CreateProxy(JSContext* context,
       const scoped_refptr<script::Wrappable>& wrappable);
   static const JSClass* PrototypeClass(JSContext* context);
-  static JSObject* GetPrototype(JSContext* context);
-  static JSObject* GetInterfaceObject(JSContext* context);
+  static JSObject* GetPrototype(JSContext* context,
+                                JS::HandleObject global_object);
+  static JSObject* GetInterfaceObject(JSContext* context,
+                                      JS::HandleObject global_object);
 };
 
 }  // namespace bindings
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsDisabledInterface.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsDisabledInterface.cc
index baf4573..54c8308 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsDisabledInterface.cc
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsDisabledInterface.cc
@@ -116,6 +116,26 @@
 static base::LazyInstance<MozjsDisabledInterfaceHandler>
     proxy_handler;
 
+JSBool HasInstance(JSContext *context, JS::HandleObject type,
+                   JS::MutableHandleValue vp, JSBool *success) {
+  JS::RootedObject global_object(
+      context, JS_GetGlobalForObject(context, type));
+  DCHECK(global_object);
+
+  JS::RootedObject prototype(
+      context, MozjsDisabledInterface::GetPrototype(context, global_object));
+
+  // |IsDelegate| walks the prototype chain of an object returning true if
+  // .prototype is found.
+  bool is_delegate;
+  if (!IsDelegate(context, prototype, vp, &is_delegate)) {
+    *success = false;
+    return false;
+  }
+
+  *success = is_delegate;
+  return true;
+}
 
 InterfaceData* CreateCachedInterfaceData() {
   InterfaceData* interface_data = new InterfaceData();
@@ -164,6 +184,7 @@
   interface_object_class->enumerate = JS_EnumerateStub;
   interface_object_class->resolve = JS_ResolveStub;
   interface_object_class->convert = JS_ConvertStub;
+  interface_object_class->hasInstance = &HasInstance;
   return interface_data;
 }
 
@@ -274,14 +295,12 @@
 };
 
 void InitializePrototypeAndInterfaceObject(
-    InterfaceData* interface_data, JSContext* context) {
+    InterfaceData* interface_data, JSContext* context,
+    JS::HandleObject global_object) {
   DCHECK(!interface_data->prototype);
   DCHECK(!interface_data->interface_object);
+  DCHECK(JS_IsGlobalObject(global_object));
 
-  MozjsGlobalObjectProxy* global_object_proxy =
-      static_cast<MozjsGlobalObjectProxy*>(JS_GetContextPrivate(context));
-  JS::RootedObject global_object(context, global_object_proxy->global_object());
-  DCHECK(global_object);
   JS::RootedObject parent_prototype(
       context, JS_GetObjectPrototype(context, global_object));
   DCHECK(parent_prototype);
@@ -360,8 +379,11 @@
 // static
 JSObject* MozjsDisabledInterface::CreateProxy(
     JSContext* context, const scoped_refptr<Wrappable>& wrappable) {
+  JS::RootedObject global_object(context, JS_GetGlobalForScopeChain(context));
+  DCHECK(global_object);
+
   InterfaceData* interface_data = GetInterfaceData(context);
-  JS::RootedObject prototype(context, GetPrototype(context));
+  JS::RootedObject prototype(context, GetPrototype(context, global_object));
   DCHECK(prototype);
   JS::RootedObject new_object(context, JS_NewObjectWithGivenProto(
       context, &interface_data->instance_class_definition, prototype, NULL));
@@ -369,34 +391,45 @@
   JS::RootedObject proxy(context,
       ProxyHandler::NewProxy(context, new_object, prototype, NULL,
                              proxy_handler.Pointer()));
-  WrapperPrivate::AddPrivateData(proxy, wrappable);
+  WrapperPrivate::AddPrivateData(context, proxy, wrappable);
   return proxy;
 }
 
 //static
 const JSClass* MozjsDisabledInterface::PrototypeClass(
       JSContext* context) {
-  JS::RootedObject prototype(context, GetPrototype(context));
+  JS::RootedObject global_object(context, JS_GetGlobalForScopeChain(context));
+  DCHECK(global_object);
+
+  JS::RootedObject prototype(context, GetPrototype(context, global_object));
   JSClass* proto_class = JS_GetClass(*prototype.address());
   return proto_class;
 }
 
 // static
-JSObject* MozjsDisabledInterface::GetPrototype(JSContext* context) {
+JSObject* MozjsDisabledInterface::GetPrototype(
+    JSContext* context, JS::HandleObject global_object) {
+  DCHECK(JS_IsGlobalObject(global_object));
+
   InterfaceData* interface_data = GetInterfaceData(context);
   if (!interface_data->prototype) {
     // Create new prototype that has all the props and methods
-    InitializePrototypeAndInterfaceObject(interface_data, context);
+    InitializePrototypeAndInterfaceObject(
+        interface_data, context, global_object);
   }
   DCHECK(interface_data->prototype);
   return interface_data->prototype;
 }
 
 // static
-JSObject* MozjsDisabledInterface::GetInterfaceObject(JSContext* context) {
+JSObject* MozjsDisabledInterface::GetInterfaceObject(
+    JSContext* context, JS::HandleObject global_object) {
+  DCHECK(JS_IsGlobalObject(global_object));
+
   InterfaceData* interface_data = GetInterfaceData(context);
   if (!interface_data->interface_object) {
-    InitializePrototypeAndInterfaceObject(interface_data, context);
+    InitializePrototypeAndInterfaceObject(
+        interface_data, context, global_object);
   }
   DCHECK(interface_data->interface_object);
   return interface_data->interface_object;
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsDisabledInterface.h b/src/cobalt/bindings/generated/mozjs/testing/MozjsDisabledInterface.h
index 360c946..bbef7b3 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsDisabledInterface.h
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsDisabledInterface.h
@@ -43,8 +43,10 @@
   static JSObject* CreateProxy(JSContext* context,
       const scoped_refptr<script::Wrappable>& wrappable);
   static const JSClass* PrototypeClass(JSContext* context);
-  static JSObject* GetPrototype(JSContext* context);
-  static JSObject* GetInterfaceObject(JSContext* context);
+  static JSObject* GetPrototype(JSContext* context,
+                                JS::HandleObject global_object);
+  static JSObject* GetInterfaceObject(JSContext* context,
+                                      JS::HandleObject global_object);
 };
 
 }  // namespace bindings
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsEnumerationInterface.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsEnumerationInterface.cc
index 2ed75aa..1ec0bac 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsEnumerationInterface.cc
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsEnumerationInterface.cc
@@ -124,6 +124,26 @@
     proxy_handler;
 
 JSBool Constructor(JSContext* context, unsigned int argc, JS::Value* vp);
+JSBool HasInstance(JSContext *context, JS::HandleObject type,
+                   JS::MutableHandleValue vp, JSBool *success) {
+  JS::RootedObject global_object(
+      context, JS_GetGlobalForObject(context, type));
+  DCHECK(global_object);
+
+  JS::RootedObject prototype(
+      context, MozjsEnumerationInterface::GetPrototype(context, global_object));
+
+  // |IsDelegate| walks the prototype chain of an object returning true if
+  // .prototype is found.
+  bool is_delegate;
+  if (!IsDelegate(context, prototype, vp, &is_delegate)) {
+    *success = false;
+    return false;
+  }
+
+  *success = is_delegate;
+  return true;
+}
 
 InterfaceData* CreateCachedInterfaceData() {
   InterfaceData* interface_data = new InterfaceData();
@@ -172,6 +192,7 @@
   interface_object_class->enumerate = JS_EnumerateStub;
   interface_object_class->resolve = JS_ResolveStub;
   interface_object_class->convert = JS_ConvertStub;
+  interface_object_class->hasInstance = &HasInstance;
   interface_object_class->construct = Constructor;
   return interface_data;
 }
@@ -248,14 +269,12 @@
 };
 
 void InitializePrototypeAndInterfaceObject(
-    InterfaceData* interface_data, JSContext* context) {
+    InterfaceData* interface_data, JSContext* context,
+    JS::HandleObject global_object) {
   DCHECK(!interface_data->prototype);
   DCHECK(!interface_data->interface_object);
+  DCHECK(JS_IsGlobalObject(global_object));
 
-  MozjsGlobalObjectProxy* global_object_proxy =
-      static_cast<MozjsGlobalObjectProxy*>(JS_GetContextPrivate(context));
-  JS::RootedObject global_object(context, global_object_proxy->global_object());
-  DCHECK(global_object);
   JS::RootedObject parent_prototype(
       context, JS_GetObjectPrototype(context, global_object));
   DCHECK(parent_prototype);
@@ -344,8 +363,11 @@
 // static
 JSObject* MozjsEnumerationInterface::CreateProxy(
     JSContext* context, const scoped_refptr<Wrappable>& wrappable) {
+  JS::RootedObject global_object(context, JS_GetGlobalForScopeChain(context));
+  DCHECK(global_object);
+
   InterfaceData* interface_data = GetInterfaceData(context);
-  JS::RootedObject prototype(context, GetPrototype(context));
+  JS::RootedObject prototype(context, GetPrototype(context, global_object));
   DCHECK(prototype);
   JS::RootedObject new_object(context, JS_NewObjectWithGivenProto(
       context, &interface_data->instance_class_definition, prototype, NULL));
@@ -353,34 +375,45 @@
   JS::RootedObject proxy(context,
       ProxyHandler::NewProxy(context, new_object, prototype, NULL,
                              proxy_handler.Pointer()));
-  WrapperPrivate::AddPrivateData(proxy, wrappable);
+  WrapperPrivate::AddPrivateData(context, proxy, wrappable);
   return proxy;
 }
 
 //static
 const JSClass* MozjsEnumerationInterface::PrototypeClass(
       JSContext* context) {
-  JS::RootedObject prototype(context, GetPrototype(context));
+  JS::RootedObject global_object(context, JS_GetGlobalForScopeChain(context));
+  DCHECK(global_object);
+
+  JS::RootedObject prototype(context, GetPrototype(context, global_object));
   JSClass* proto_class = JS_GetClass(*prototype.address());
   return proto_class;
 }
 
 // static
-JSObject* MozjsEnumerationInterface::GetPrototype(JSContext* context) {
+JSObject* MozjsEnumerationInterface::GetPrototype(
+    JSContext* context, JS::HandleObject global_object) {
+  DCHECK(JS_IsGlobalObject(global_object));
+
   InterfaceData* interface_data = GetInterfaceData(context);
   if (!interface_data->prototype) {
     // Create new prototype that has all the props and methods
-    InitializePrototypeAndInterfaceObject(interface_data, context);
+    InitializePrototypeAndInterfaceObject(
+        interface_data, context, global_object);
   }
   DCHECK(interface_data->prototype);
   return interface_data->prototype;
 }
 
 // static
-JSObject* MozjsEnumerationInterface::GetInterfaceObject(JSContext* context) {
+JSObject* MozjsEnumerationInterface::GetInterfaceObject(
+    JSContext* context, JS::HandleObject global_object) {
+  DCHECK(JS_IsGlobalObject(global_object));
+
   InterfaceData* interface_data = GetInterfaceData(context);
   if (!interface_data->interface_object) {
-    InitializePrototypeAndInterfaceObject(interface_data, context);
+    InitializePrototypeAndInterfaceObject(
+        interface_data, context, global_object);
   }
   DCHECK(interface_data->interface_object);
   return interface_data->interface_object;
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsEnumerationInterface.h b/src/cobalt/bindings/generated/mozjs/testing/MozjsEnumerationInterface.h
index b4b3e19..34f404e 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsEnumerationInterface.h
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsEnumerationInterface.h
@@ -41,8 +41,10 @@
   static JSObject* CreateProxy(JSContext* context,
       const scoped_refptr<script::Wrappable>& wrappable);
   static const JSClass* PrototypeClass(JSContext* context);
-  static JSObject* GetPrototype(JSContext* context);
-  static JSObject* GetInterfaceObject(JSContext* context);
+  static JSObject* GetPrototype(JSContext* context,
+                                JS::HandleObject global_object);
+  static JSObject* GetInterfaceObject(JSContext* context,
+                                      JS::HandleObject global_object);
 };
 
 }  // namespace bindings
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsExceptionObjectInterface.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsExceptionObjectInterface.cc
index 498e223..8a5b4b0 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsExceptionObjectInterface.cc
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsExceptionObjectInterface.cc
@@ -43,6 +43,7 @@
 #include "cobalt/script/mozjs/wrapper_private.h"
 #include "cobalt/script/property_enumerator.h"
 #include "third_party/mozjs/js/src/jsapi.h"
+#include "third_party/mozjs/js/src/jsexn.h"
 #include "third_party/mozjs/js/src/jsfriendapi.h"
 
 namespace {
@@ -114,6 +115,26 @@
 static base::LazyInstance<MozjsExceptionObjectInterfaceHandler>
     proxy_handler;
 
+JSBool HasInstance(JSContext *context, JS::HandleObject type,
+                   JS::MutableHandleValue vp, JSBool *success) {
+  JS::RootedObject global_object(
+      context, JS_GetGlobalForObject(context, type));
+  DCHECK(global_object);
+
+  JS::RootedObject prototype(
+      context, MozjsExceptionObjectInterface::GetPrototype(context, global_object));
+
+  // |IsDelegate| walks the prototype chain of an object returning true if
+  // .prototype is found.
+  bool is_delegate;
+  if (!IsDelegate(context, prototype, vp, &is_delegate)) {
+    *success = false;
+    return false;
+  }
+
+  *success = is_delegate;
+  return true;
+}
 
 InterfaceData* CreateCachedInterfaceData() {
   InterfaceData* interface_data = new InterfaceData();
@@ -162,6 +183,7 @@
   interface_object_class->enumerate = JS_EnumerateStub;
   interface_object_class->resolve = JS_ResolveStub;
   interface_object_class->convert = JS_ConvertStub;
+  interface_object_class->hasInstance = &HasInstance;
   return interface_data;
 }
 
@@ -243,22 +265,22 @@
 };
 
 void InitializePrototypeAndInterfaceObject(
-    InterfaceData* interface_data, JSContext* context) {
+    InterfaceData* interface_data, JSContext* context,
+    JS::HandleObject global_object) {
   DCHECK(!interface_data->prototype);
   DCHECK(!interface_data->interface_object);
+  DCHECK(JS_IsGlobalObject(global_object));
 
-  MozjsGlobalObjectProxy* global_object_proxy =
-      static_cast<MozjsGlobalObjectProxy*>(JS_GetContextPrivate(context));
-  JS::RootedObject global_object(context, global_object_proxy->global_object());
-  DCHECK(global_object);
   JS::RootedObject parent_prototype(
       context, JS_GetObjectPrototype(context, global_object));
   DCHECK(parent_prototype);
 
-  // Create the Prototype object.
-  interface_data->prototype = JS_NewObjectWithGivenProto(
-      context, &interface_data->prototype_class_definition, parent_prototype,
-      NULL);
+  JS::RootedObject prototype(context);
+  // Get Error prototype.
+  bool success_check = js_GetClassPrototype(
+      context, GetExceptionProtoKey(JSEXN_ERR), &prototype);
+  DCHECK(success_check);
+  interface_data->prototype = prototype;
   bool success = JS_DefineProperties(
       context, interface_data->prototype, prototype_properties);
   DCHECK(success);
@@ -329,8 +351,11 @@
 // static
 JSObject* MozjsExceptionObjectInterface::CreateProxy(
     JSContext* context, const scoped_refptr<Wrappable>& wrappable) {
+  JS::RootedObject global_object(context, JS_GetGlobalForScopeChain(context));
+  DCHECK(global_object);
+
   InterfaceData* interface_data = GetInterfaceData(context);
-  JS::RootedObject prototype(context, GetPrototype(context));
+  JS::RootedObject prototype(context, GetPrototype(context, global_object));
   DCHECK(prototype);
   JS::RootedObject new_object(context, JS_NewObjectWithGivenProto(
       context, &interface_data->instance_class_definition, prototype, NULL));
@@ -338,34 +363,45 @@
   JS::RootedObject proxy(context,
       ProxyHandler::NewProxy(context, new_object, prototype, NULL,
                              proxy_handler.Pointer()));
-  WrapperPrivate::AddPrivateData(proxy, wrappable);
+  WrapperPrivate::AddPrivateData(context, proxy, wrappable);
   return proxy;
 }
 
 //static
 const JSClass* MozjsExceptionObjectInterface::PrototypeClass(
       JSContext* context) {
-  JS::RootedObject prototype(context, GetPrototype(context));
+  JS::RootedObject global_object(context, JS_GetGlobalForScopeChain(context));
+  DCHECK(global_object);
+
+  JS::RootedObject prototype(context, GetPrototype(context, global_object));
   JSClass* proto_class = JS_GetClass(*prototype.address());
   return proto_class;
 }
 
 // static
-JSObject* MozjsExceptionObjectInterface::GetPrototype(JSContext* context) {
+JSObject* MozjsExceptionObjectInterface::GetPrototype(
+    JSContext* context, JS::HandleObject global_object) {
+  DCHECK(JS_IsGlobalObject(global_object));
+
   InterfaceData* interface_data = GetInterfaceData(context);
   if (!interface_data->prototype) {
     // Create new prototype that has all the props and methods
-    InitializePrototypeAndInterfaceObject(interface_data, context);
+    InitializePrototypeAndInterfaceObject(
+        interface_data, context, global_object);
   }
   DCHECK(interface_data->prototype);
   return interface_data->prototype;
 }
 
 // static
-JSObject* MozjsExceptionObjectInterface::GetInterfaceObject(JSContext* context) {
+JSObject* MozjsExceptionObjectInterface::GetInterfaceObject(
+    JSContext* context, JS::HandleObject global_object) {
+  DCHECK(JS_IsGlobalObject(global_object));
+
   InterfaceData* interface_data = GetInterfaceData(context);
   if (!interface_data->interface_object) {
-    InitializePrototypeAndInterfaceObject(interface_data, context);
+    InitializePrototypeAndInterfaceObject(
+        interface_data, context, global_object);
   }
   DCHECK(interface_data->interface_object);
   return interface_data->interface_object;
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsExceptionObjectInterface.h b/src/cobalt/bindings/generated/mozjs/testing/MozjsExceptionObjectInterface.h
index 0ba0055..4c8282d 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsExceptionObjectInterface.h
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsExceptionObjectInterface.h
@@ -41,8 +41,10 @@
   static JSObject* CreateProxy(JSContext* context,
       const scoped_refptr<script::Wrappable>& wrappable);
   static const JSClass* PrototypeClass(JSContext* context);
-  static JSObject* GetPrototype(JSContext* context);
-  static JSObject* GetInterfaceObject(JSContext* context);
+  static JSObject* GetPrototype(JSContext* context,
+                                JS::HandleObject global_object);
+  static JSObject* GetInterfaceObject(JSContext* context,
+                                      JS::HandleObject global_object);
 };
 
 }  // namespace bindings
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsExceptionsInterface.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsExceptionsInterface.cc
index 21cbe31..c58594c 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsExceptionsInterface.cc
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsExceptionsInterface.cc
@@ -115,6 +115,26 @@
     proxy_handler;
 
 JSBool Constructor(JSContext* context, unsigned int argc, JS::Value* vp);
+JSBool HasInstance(JSContext *context, JS::HandleObject type,
+                   JS::MutableHandleValue vp, JSBool *success) {
+  JS::RootedObject global_object(
+      context, JS_GetGlobalForObject(context, type));
+  DCHECK(global_object);
+
+  JS::RootedObject prototype(
+      context, MozjsExceptionsInterface::GetPrototype(context, global_object));
+
+  // |IsDelegate| walks the prototype chain of an object returning true if
+  // .prototype is found.
+  bool is_delegate;
+  if (!IsDelegate(context, prototype, vp, &is_delegate)) {
+    *success = false;
+    return false;
+  }
+
+  *success = is_delegate;
+  return true;
+}
 
 InterfaceData* CreateCachedInterfaceData() {
   InterfaceData* interface_data = new InterfaceData();
@@ -163,6 +183,7 @@
   interface_object_class->enumerate = JS_EnumerateStub;
   interface_object_class->resolve = JS_ResolveStub;
   interface_object_class->convert = JS_ConvertStub;
+  interface_object_class->hasInstance = &HasInstance;
   interface_object_class->construct = Constructor;
   return interface_data;
 }
@@ -274,14 +295,12 @@
 };
 
 void InitializePrototypeAndInterfaceObject(
-    InterfaceData* interface_data, JSContext* context) {
+    InterfaceData* interface_data, JSContext* context,
+    JS::HandleObject global_object) {
   DCHECK(!interface_data->prototype);
   DCHECK(!interface_data->interface_object);
+  DCHECK(JS_IsGlobalObject(global_object));
 
-  MozjsGlobalObjectProxy* global_object_proxy =
-      static_cast<MozjsGlobalObjectProxy*>(JS_GetContextPrivate(context));
-  JS::RootedObject global_object(context, global_object_proxy->global_object());
-  DCHECK(global_object);
   JS::RootedObject parent_prototype(
       context, JS_GetObjectPrototype(context, global_object));
   DCHECK(parent_prototype);
@@ -370,8 +389,11 @@
 // static
 JSObject* MozjsExceptionsInterface::CreateProxy(
     JSContext* context, const scoped_refptr<Wrappable>& wrappable) {
+  JS::RootedObject global_object(context, JS_GetGlobalForScopeChain(context));
+  DCHECK(global_object);
+
   InterfaceData* interface_data = GetInterfaceData(context);
-  JS::RootedObject prototype(context, GetPrototype(context));
+  JS::RootedObject prototype(context, GetPrototype(context, global_object));
   DCHECK(prototype);
   JS::RootedObject new_object(context, JS_NewObjectWithGivenProto(
       context, &interface_data->instance_class_definition, prototype, NULL));
@@ -379,34 +401,45 @@
   JS::RootedObject proxy(context,
       ProxyHandler::NewProxy(context, new_object, prototype, NULL,
                              proxy_handler.Pointer()));
-  WrapperPrivate::AddPrivateData(proxy, wrappable);
+  WrapperPrivate::AddPrivateData(context, proxy, wrappable);
   return proxy;
 }
 
 //static
 const JSClass* MozjsExceptionsInterface::PrototypeClass(
       JSContext* context) {
-  JS::RootedObject prototype(context, GetPrototype(context));
+  JS::RootedObject global_object(context, JS_GetGlobalForScopeChain(context));
+  DCHECK(global_object);
+
+  JS::RootedObject prototype(context, GetPrototype(context, global_object));
   JSClass* proto_class = JS_GetClass(*prototype.address());
   return proto_class;
 }
 
 // static
-JSObject* MozjsExceptionsInterface::GetPrototype(JSContext* context) {
+JSObject* MozjsExceptionsInterface::GetPrototype(
+    JSContext* context, JS::HandleObject global_object) {
+  DCHECK(JS_IsGlobalObject(global_object));
+
   InterfaceData* interface_data = GetInterfaceData(context);
   if (!interface_data->prototype) {
     // Create new prototype that has all the props and methods
-    InitializePrototypeAndInterfaceObject(interface_data, context);
+    InitializePrototypeAndInterfaceObject(
+        interface_data, context, global_object);
   }
   DCHECK(interface_data->prototype);
   return interface_data->prototype;
 }
 
 // static
-JSObject* MozjsExceptionsInterface::GetInterfaceObject(JSContext* context) {
+JSObject* MozjsExceptionsInterface::GetInterfaceObject(
+    JSContext* context, JS::HandleObject global_object) {
+  DCHECK(JS_IsGlobalObject(global_object));
+
   InterfaceData* interface_data = GetInterfaceData(context);
   if (!interface_data->interface_object) {
-    InitializePrototypeAndInterfaceObject(interface_data, context);
+    InitializePrototypeAndInterfaceObject(
+        interface_data, context, global_object);
   }
   DCHECK(interface_data->interface_object);
   return interface_data->interface_object;
@@ -420,6 +453,10 @@
 
   scoped_refptr<ExceptionsInterface> new_object =
       new ExceptionsInterface(&exception_state);
+  // In case that an exception is thrown from constructor.
+  if (exception_state.is_exception_set()) {
+    return false;
+  }
   JS::RootedValue result_value(context);
   ToJSValue(context, new_object, &result_value);
   DCHECK(result_value.isObject());
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsExceptionsInterface.h b/src/cobalt/bindings/generated/mozjs/testing/MozjsExceptionsInterface.h
index b5fe100..fa0457d 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsExceptionsInterface.h
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsExceptionsInterface.h
@@ -41,8 +41,10 @@
   static JSObject* CreateProxy(JSContext* context,
       const scoped_refptr<script::Wrappable>& wrappable);
   static const JSClass* PrototypeClass(JSContext* context);
-  static JSObject* GetPrototype(JSContext* context);
-  static JSObject* GetInterfaceObject(JSContext* context);
+  static JSObject* GetPrototype(JSContext* context,
+                                JS::HandleObject global_object);
+  static JSObject* GetInterfaceObject(JSContext* context,
+                                      JS::HandleObject global_object);
 };
 
 }  // namespace bindings
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsExtendedIDLAttributesInterface.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsExtendedIDLAttributesInterface.cc
index 06bcf72..3753f38 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsExtendedIDLAttributesInterface.cc
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsExtendedIDLAttributesInterface.cc
@@ -114,6 +114,26 @@
 static base::LazyInstance<MozjsExtendedIDLAttributesInterfaceHandler>
     proxy_handler;
 
+JSBool HasInstance(JSContext *context, JS::HandleObject type,
+                   JS::MutableHandleValue vp, JSBool *success) {
+  JS::RootedObject global_object(
+      context, JS_GetGlobalForObject(context, type));
+  DCHECK(global_object);
+
+  JS::RootedObject prototype(
+      context, MozjsExtendedIDLAttributesInterface::GetPrototype(context, global_object));
+
+  // |IsDelegate| walks the prototype chain of an object returning true if
+  // .prototype is found.
+  bool is_delegate;
+  if (!IsDelegate(context, prototype, vp, &is_delegate)) {
+    *success = false;
+    return false;
+  }
+
+  *success = is_delegate;
+  return true;
+}
 
 InterfaceData* CreateCachedInterfaceData() {
   InterfaceData* interface_data = new InterfaceData();
@@ -162,6 +182,7 @@
   interface_object_class->enumerate = JS_EnumerateStub;
   interface_object_class->resolve = JS_ResolveStub;
   interface_object_class->convert = JS_ConvertStub;
+  interface_object_class->hasInstance = &HasInstance;
   return interface_data;
 }
 
@@ -224,14 +245,12 @@
 };
 
 void InitializePrototypeAndInterfaceObject(
-    InterfaceData* interface_data, JSContext* context) {
+    InterfaceData* interface_data, JSContext* context,
+    JS::HandleObject global_object) {
   DCHECK(!interface_data->prototype);
   DCHECK(!interface_data->interface_object);
+  DCHECK(JS_IsGlobalObject(global_object));
 
-  MozjsGlobalObjectProxy* global_object_proxy =
-      static_cast<MozjsGlobalObjectProxy*>(JS_GetContextPrivate(context));
-  JS::RootedObject global_object(context, global_object_proxy->global_object());
-  DCHECK(global_object);
   JS::RootedObject parent_prototype(
       context, JS_GetObjectPrototype(context, global_object));
   DCHECK(parent_prototype);
@@ -310,8 +329,11 @@
 // static
 JSObject* MozjsExtendedIDLAttributesInterface::CreateProxy(
     JSContext* context, const scoped_refptr<Wrappable>& wrappable) {
+  JS::RootedObject global_object(context, JS_GetGlobalForScopeChain(context));
+  DCHECK(global_object);
+
   InterfaceData* interface_data = GetInterfaceData(context);
-  JS::RootedObject prototype(context, GetPrototype(context));
+  JS::RootedObject prototype(context, GetPrototype(context, global_object));
   DCHECK(prototype);
   JS::RootedObject new_object(context, JS_NewObjectWithGivenProto(
       context, &interface_data->instance_class_definition, prototype, NULL));
@@ -319,34 +341,45 @@
   JS::RootedObject proxy(context,
       ProxyHandler::NewProxy(context, new_object, prototype, NULL,
                              proxy_handler.Pointer()));
-  WrapperPrivate::AddPrivateData(proxy, wrappable);
+  WrapperPrivate::AddPrivateData(context, proxy, wrappable);
   return proxy;
 }
 
 //static
 const JSClass* MozjsExtendedIDLAttributesInterface::PrototypeClass(
       JSContext* context) {
-  JS::RootedObject prototype(context, GetPrototype(context));
+  JS::RootedObject global_object(context, JS_GetGlobalForScopeChain(context));
+  DCHECK(global_object);
+
+  JS::RootedObject prototype(context, GetPrototype(context, global_object));
   JSClass* proto_class = JS_GetClass(*prototype.address());
   return proto_class;
 }
 
 // static
-JSObject* MozjsExtendedIDLAttributesInterface::GetPrototype(JSContext* context) {
+JSObject* MozjsExtendedIDLAttributesInterface::GetPrototype(
+    JSContext* context, JS::HandleObject global_object) {
+  DCHECK(JS_IsGlobalObject(global_object));
+
   InterfaceData* interface_data = GetInterfaceData(context);
   if (!interface_data->prototype) {
     // Create new prototype that has all the props and methods
-    InitializePrototypeAndInterfaceObject(interface_data, context);
+    InitializePrototypeAndInterfaceObject(
+        interface_data, context, global_object);
   }
   DCHECK(interface_data->prototype);
   return interface_data->prototype;
 }
 
 // static
-JSObject* MozjsExtendedIDLAttributesInterface::GetInterfaceObject(JSContext* context) {
+JSObject* MozjsExtendedIDLAttributesInterface::GetInterfaceObject(
+    JSContext* context, JS::HandleObject global_object) {
+  DCHECK(JS_IsGlobalObject(global_object));
+
   InterfaceData* interface_data = GetInterfaceData(context);
   if (!interface_data->interface_object) {
-    InitializePrototypeAndInterfaceObject(interface_data, context);
+    InitializePrototypeAndInterfaceObject(
+        interface_data, context, global_object);
   }
   DCHECK(interface_data->interface_object);
   return interface_data->interface_object;
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsExtendedIDLAttributesInterface.h b/src/cobalt/bindings/generated/mozjs/testing/MozjsExtendedIDLAttributesInterface.h
index 68909d5..b99f5b7 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsExtendedIDLAttributesInterface.h
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsExtendedIDLAttributesInterface.h
@@ -41,8 +41,10 @@
   static JSObject* CreateProxy(JSContext* context,
       const scoped_refptr<script::Wrappable>& wrappable);
   static const JSClass* PrototypeClass(JSContext* context);
-  static JSObject* GetPrototype(JSContext* context);
-  static JSObject* GetInterfaceObject(JSContext* context);
+  static JSObject* GetPrototype(JSContext* context,
+                                JS::HandleObject global_object);
+  static JSObject* GetInterfaceObject(JSContext* context,
+                                      JS::HandleObject global_object);
 };
 
 }  // namespace bindings
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsGetOpaqueRootInterface.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsGetOpaqueRootInterface.cc
index fbfc60a..1a71dae 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsGetOpaqueRootInterface.cc
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsGetOpaqueRootInterface.cc
@@ -115,6 +115,26 @@
     proxy_handler;
 
 JSBool Constructor(JSContext* context, unsigned int argc, JS::Value* vp);
+JSBool HasInstance(JSContext *context, JS::HandleObject type,
+                   JS::MutableHandleValue vp, JSBool *success) {
+  JS::RootedObject global_object(
+      context, JS_GetGlobalForObject(context, type));
+  DCHECK(global_object);
+
+  JS::RootedObject prototype(
+      context, MozjsGetOpaqueRootInterface::GetPrototype(context, global_object));
+
+  // |IsDelegate| walks the prototype chain of an object returning true if
+  // .prototype is found.
+  bool is_delegate;
+  if (!IsDelegate(context, prototype, vp, &is_delegate)) {
+    *success = false;
+    return false;
+  }
+
+  *success = is_delegate;
+  return true;
+}
 
 InterfaceData* CreateCachedInterfaceData() {
   InterfaceData* interface_data = new InterfaceData();
@@ -163,6 +183,7 @@
   interface_object_class->enumerate = JS_EnumerateStub;
   interface_object_class->resolve = JS_ResolveStub;
   interface_object_class->convert = JS_ConvertStub;
+  interface_object_class->hasInstance = &HasInstance;
   interface_object_class->construct = Constructor;
   return interface_data;
 }
@@ -189,14 +210,12 @@
 };
 
 void InitializePrototypeAndInterfaceObject(
-    InterfaceData* interface_data, JSContext* context) {
+    InterfaceData* interface_data, JSContext* context,
+    JS::HandleObject global_object) {
   DCHECK(!interface_data->prototype);
   DCHECK(!interface_data->interface_object);
+  DCHECK(JS_IsGlobalObject(global_object));
 
-  MozjsGlobalObjectProxy* global_object_proxy =
-      static_cast<MozjsGlobalObjectProxy*>(JS_GetContextPrivate(context));
-  JS::RootedObject global_object(context, global_object_proxy->global_object());
-  DCHECK(global_object);
   JS::RootedObject parent_prototype(
       context, JS_GetObjectPrototype(context, global_object));
   DCHECK(parent_prototype);
@@ -285,8 +304,11 @@
 // static
 JSObject* MozjsGetOpaqueRootInterface::CreateProxy(
     JSContext* context, const scoped_refptr<Wrappable>& wrappable) {
+  JS::RootedObject global_object(context, JS_GetGlobalForScopeChain(context));
+  DCHECK(global_object);
+
   InterfaceData* interface_data = GetInterfaceData(context);
-  JS::RootedObject prototype(context, GetPrototype(context));
+  JS::RootedObject prototype(context, GetPrototype(context, global_object));
   DCHECK(prototype);
   JS::RootedObject new_object(context, JS_NewObjectWithGivenProto(
       context, &interface_data->instance_class_definition, prototype, NULL));
@@ -294,34 +316,45 @@
   JS::RootedObject proxy(context,
       ProxyHandler::NewProxy(context, new_object, prototype, NULL,
                              proxy_handler.Pointer()));
-  WrapperPrivate::AddPrivateData(proxy, wrappable);
+  WrapperPrivate::AddPrivateData(context, proxy, wrappable);
   return proxy;
 }
 
 //static
 const JSClass* MozjsGetOpaqueRootInterface::PrototypeClass(
       JSContext* context) {
-  JS::RootedObject prototype(context, GetPrototype(context));
+  JS::RootedObject global_object(context, JS_GetGlobalForScopeChain(context));
+  DCHECK(global_object);
+
+  JS::RootedObject prototype(context, GetPrototype(context, global_object));
   JSClass* proto_class = JS_GetClass(*prototype.address());
   return proto_class;
 }
 
 // static
-JSObject* MozjsGetOpaqueRootInterface::GetPrototype(JSContext* context) {
+JSObject* MozjsGetOpaqueRootInterface::GetPrototype(
+    JSContext* context, JS::HandleObject global_object) {
+  DCHECK(JS_IsGlobalObject(global_object));
+
   InterfaceData* interface_data = GetInterfaceData(context);
   if (!interface_data->prototype) {
     // Create new prototype that has all the props and methods
-    InitializePrototypeAndInterfaceObject(interface_data, context);
+    InitializePrototypeAndInterfaceObject(
+        interface_data, context, global_object);
   }
   DCHECK(interface_data->prototype);
   return interface_data->prototype;
 }
 
 // static
-JSObject* MozjsGetOpaqueRootInterface::GetInterfaceObject(JSContext* context) {
+JSObject* MozjsGetOpaqueRootInterface::GetInterfaceObject(
+    JSContext* context, JS::HandleObject global_object) {
+  DCHECK(JS_IsGlobalObject(global_object));
+
   InterfaceData* interface_data = GetInterfaceData(context);
   if (!interface_data->interface_object) {
-    InitializePrototypeAndInterfaceObject(interface_data, context);
+    InitializePrototypeAndInterfaceObject(
+        interface_data, context, global_object);
   }
   DCHECK(interface_data->interface_object);
   return interface_data->interface_object;
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsGetOpaqueRootInterface.h b/src/cobalt/bindings/generated/mozjs/testing/MozjsGetOpaqueRootInterface.h
index 343e465..cfc9474 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsGetOpaqueRootInterface.h
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsGetOpaqueRootInterface.h
@@ -41,8 +41,10 @@
   static JSObject* CreateProxy(JSContext* context,
       const scoped_refptr<script::Wrappable>& wrappable);
   static const JSClass* PrototypeClass(JSContext* context);
-  static JSObject* GetPrototype(JSContext* context);
-  static JSObject* GetInterfaceObject(JSContext* context);
+  static JSObject* GetPrototype(JSContext* context,
+                                JS::HandleObject global_object);
+  static JSObject* GetInterfaceObject(JSContext* context,
+                                      JS::HandleObject global_object);
 };
 
 }  // namespace bindings
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsGlobalInterfaceParent.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsGlobalInterfaceParent.cc
index 27e94db..e02ee9c 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsGlobalInterfaceParent.cc
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsGlobalInterfaceParent.cc
@@ -114,6 +114,26 @@
 static base::LazyInstance<MozjsGlobalInterfaceParentHandler>
     proxy_handler;
 
+JSBool HasInstance(JSContext *context, JS::HandleObject type,
+                   JS::MutableHandleValue vp, JSBool *success) {
+  JS::RootedObject global_object(
+      context, JS_GetGlobalForObject(context, type));
+  DCHECK(global_object);
+
+  JS::RootedObject prototype(
+      context, MozjsGlobalInterfaceParent::GetPrototype(context, global_object));
+
+  // |IsDelegate| walks the prototype chain of an object returning true if
+  // .prototype is found.
+  bool is_delegate;
+  if (!IsDelegate(context, prototype, vp, &is_delegate)) {
+    *success = false;
+    return false;
+  }
+
+  *success = is_delegate;
+  return true;
+}
 
 InterfaceData* CreateCachedInterfaceData() {
   InterfaceData* interface_data = new InterfaceData();
@@ -162,6 +182,7 @@
   interface_object_class->enumerate = JS_EnumerateStub;
   interface_object_class->resolve = JS_ResolveStub;
   interface_object_class->convert = JS_ConvertStub;
+  interface_object_class->hasInstance = &HasInstance;
   return interface_data;
 }
 
@@ -222,14 +243,12 @@
 };
 
 void InitializePrototypeAndInterfaceObject(
-    InterfaceData* interface_data, JSContext* context) {
+    InterfaceData* interface_data, JSContext* context,
+    JS::HandleObject global_object) {
   DCHECK(!interface_data->prototype);
   DCHECK(!interface_data->interface_object);
+  DCHECK(JS_IsGlobalObject(global_object));
 
-  MozjsGlobalObjectProxy* global_object_proxy =
-      static_cast<MozjsGlobalObjectProxy*>(JS_GetContextPrivate(context));
-  JS::RootedObject global_object(context, global_object_proxy->global_object());
-  DCHECK(global_object);
   JS::RootedObject parent_prototype(
       context, JS_GetObjectPrototype(context, global_object));
   DCHECK(parent_prototype);
@@ -308,8 +327,11 @@
 // static
 JSObject* MozjsGlobalInterfaceParent::CreateProxy(
     JSContext* context, const scoped_refptr<Wrappable>& wrappable) {
+  JS::RootedObject global_object(context, JS_GetGlobalForScopeChain(context));
+  DCHECK(global_object);
+
   InterfaceData* interface_data = GetInterfaceData(context);
-  JS::RootedObject prototype(context, GetPrototype(context));
+  JS::RootedObject prototype(context, GetPrototype(context, global_object));
   DCHECK(prototype);
   JS::RootedObject new_object(context, JS_NewObjectWithGivenProto(
       context, &interface_data->instance_class_definition, prototype, NULL));
@@ -317,34 +339,45 @@
   JS::RootedObject proxy(context,
       ProxyHandler::NewProxy(context, new_object, prototype, NULL,
                              proxy_handler.Pointer()));
-  WrapperPrivate::AddPrivateData(proxy, wrappable);
+  WrapperPrivate::AddPrivateData(context, proxy, wrappable);
   return proxy;
 }
 
 //static
 const JSClass* MozjsGlobalInterfaceParent::PrototypeClass(
       JSContext* context) {
-  JS::RootedObject prototype(context, GetPrototype(context));
+  JS::RootedObject global_object(context, JS_GetGlobalForScopeChain(context));
+  DCHECK(global_object);
+
+  JS::RootedObject prototype(context, GetPrototype(context, global_object));
   JSClass* proto_class = JS_GetClass(*prototype.address());
   return proto_class;
 }
 
 // static
-JSObject* MozjsGlobalInterfaceParent::GetPrototype(JSContext* context) {
+JSObject* MozjsGlobalInterfaceParent::GetPrototype(
+    JSContext* context, JS::HandleObject global_object) {
+  DCHECK(JS_IsGlobalObject(global_object));
+
   InterfaceData* interface_data = GetInterfaceData(context);
   if (!interface_data->prototype) {
     // Create new prototype that has all the props and methods
-    InitializePrototypeAndInterfaceObject(interface_data, context);
+    InitializePrototypeAndInterfaceObject(
+        interface_data, context, global_object);
   }
   DCHECK(interface_data->prototype);
   return interface_data->prototype;
 }
 
 // static
-JSObject* MozjsGlobalInterfaceParent::GetInterfaceObject(JSContext* context) {
+JSObject* MozjsGlobalInterfaceParent::GetInterfaceObject(
+    JSContext* context, JS::HandleObject global_object) {
+  DCHECK(JS_IsGlobalObject(global_object));
+
   InterfaceData* interface_data = GetInterfaceData(context);
   if (!interface_data->interface_object) {
-    InitializePrototypeAndInterfaceObject(interface_data, context);
+    InitializePrototypeAndInterfaceObject(
+        interface_data, context, global_object);
   }
   DCHECK(interface_data->interface_object);
   return interface_data->interface_object;
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsGlobalInterfaceParent.h b/src/cobalt/bindings/generated/mozjs/testing/MozjsGlobalInterfaceParent.h
index 0ed43cb..2747058 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsGlobalInterfaceParent.h
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsGlobalInterfaceParent.h
@@ -41,8 +41,10 @@
   static JSObject* CreateProxy(JSContext* context,
       const scoped_refptr<script::Wrappable>& wrappable);
   static const JSClass* PrototypeClass(JSContext* context);
-  static JSObject* GetPrototype(JSContext* context);
-  static JSObject* GetInterfaceObject(JSContext* context);
+  static JSObject* GetPrototype(JSContext* context,
+                                JS::HandleObject global_object);
+  static JSObject* GetInterfaceObject(JSContext* context,
+                                      JS::HandleObject global_object);
 };
 
 }  // namespace bindings
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsIndexedGetterInterface.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsIndexedGetterInterface.cc
index e67543f..a392376 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsIndexedGetterInterface.cc
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsIndexedGetterInterface.cc
@@ -220,6 +220,26 @@
 static base::LazyInstance<MozjsIndexedGetterInterfaceHandler>
     proxy_handler;
 
+JSBool HasInstance(JSContext *context, JS::HandleObject type,
+                   JS::MutableHandleValue vp, JSBool *success) {
+  JS::RootedObject global_object(
+      context, JS_GetGlobalForObject(context, type));
+  DCHECK(global_object);
+
+  JS::RootedObject prototype(
+      context, MozjsIndexedGetterInterface::GetPrototype(context, global_object));
+
+  // |IsDelegate| walks the prototype chain of an object returning true if
+  // .prototype is found.
+  bool is_delegate;
+  if (!IsDelegate(context, prototype, vp, &is_delegate)) {
+    *success = false;
+    return false;
+  }
+
+  *success = is_delegate;
+  return true;
+}
 
 InterfaceData* CreateCachedInterfaceData() {
   InterfaceData* interface_data = new InterfaceData();
@@ -268,6 +288,7 @@
   interface_object_class->enumerate = JS_EnumerateStub;
   interface_object_class->resolve = JS_ResolveStub;
   interface_object_class->convert = JS_ConvertStub;
+  interface_object_class->hasInstance = &HasInstance;
   return interface_data;
 }
 
@@ -501,14 +522,12 @@
 };
 
 void InitializePrototypeAndInterfaceObject(
-    InterfaceData* interface_data, JSContext* context) {
+    InterfaceData* interface_data, JSContext* context,
+    JS::HandleObject global_object) {
   DCHECK(!interface_data->prototype);
   DCHECK(!interface_data->interface_object);
+  DCHECK(JS_IsGlobalObject(global_object));
 
-  MozjsGlobalObjectProxy* global_object_proxy =
-      static_cast<MozjsGlobalObjectProxy*>(JS_GetContextPrivate(context));
-  JS::RootedObject global_object(context, global_object_proxy->global_object());
-  DCHECK(global_object);
   JS::RootedObject parent_prototype(
       context, JS_GetObjectPrototype(context, global_object));
   DCHECK(parent_prototype);
@@ -587,8 +606,11 @@
 // static
 JSObject* MozjsIndexedGetterInterface::CreateProxy(
     JSContext* context, const scoped_refptr<Wrappable>& wrappable) {
+  JS::RootedObject global_object(context, JS_GetGlobalForScopeChain(context));
+  DCHECK(global_object);
+
   InterfaceData* interface_data = GetInterfaceData(context);
-  JS::RootedObject prototype(context, GetPrototype(context));
+  JS::RootedObject prototype(context, GetPrototype(context, global_object));
   DCHECK(prototype);
   JS::RootedObject new_object(context, JS_NewObjectWithGivenProto(
       context, &interface_data->instance_class_definition, prototype, NULL));
@@ -596,34 +618,45 @@
   JS::RootedObject proxy(context,
       ProxyHandler::NewProxy(context, new_object, prototype, NULL,
                              proxy_handler.Pointer()));
-  WrapperPrivate::AddPrivateData(proxy, wrappable);
+  WrapperPrivate::AddPrivateData(context, proxy, wrappable);
   return proxy;
 }
 
 //static
 const JSClass* MozjsIndexedGetterInterface::PrototypeClass(
       JSContext* context) {
-  JS::RootedObject prototype(context, GetPrototype(context));
+  JS::RootedObject global_object(context, JS_GetGlobalForScopeChain(context));
+  DCHECK(global_object);
+
+  JS::RootedObject prototype(context, GetPrototype(context, global_object));
   JSClass* proto_class = JS_GetClass(*prototype.address());
   return proto_class;
 }
 
 // static
-JSObject* MozjsIndexedGetterInterface::GetPrototype(JSContext* context) {
+JSObject* MozjsIndexedGetterInterface::GetPrototype(
+    JSContext* context, JS::HandleObject global_object) {
+  DCHECK(JS_IsGlobalObject(global_object));
+
   InterfaceData* interface_data = GetInterfaceData(context);
   if (!interface_data->prototype) {
     // Create new prototype that has all the props and methods
-    InitializePrototypeAndInterfaceObject(interface_data, context);
+    InitializePrototypeAndInterfaceObject(
+        interface_data, context, global_object);
   }
   DCHECK(interface_data->prototype);
   return interface_data->prototype;
 }
 
 // static
-JSObject* MozjsIndexedGetterInterface::GetInterfaceObject(JSContext* context) {
+JSObject* MozjsIndexedGetterInterface::GetInterfaceObject(
+    JSContext* context, JS::HandleObject global_object) {
+  DCHECK(JS_IsGlobalObject(global_object));
+
   InterfaceData* interface_data = GetInterfaceData(context);
   if (!interface_data->interface_object) {
-    InitializePrototypeAndInterfaceObject(interface_data, context);
+    InitializePrototypeAndInterfaceObject(
+        interface_data, context, global_object);
   }
   DCHECK(interface_data->interface_object);
   return interface_data->interface_object;
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsIndexedGetterInterface.h b/src/cobalt/bindings/generated/mozjs/testing/MozjsIndexedGetterInterface.h
index a61619c..28984fe 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsIndexedGetterInterface.h
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsIndexedGetterInterface.h
@@ -41,8 +41,10 @@
   static JSObject* CreateProxy(JSContext* context,
       const scoped_refptr<script::Wrappable>& wrappable);
   static const JSClass* PrototypeClass(JSContext* context);
-  static JSObject* GetPrototype(JSContext* context);
-  static JSObject* GetInterfaceObject(JSContext* context);
+  static JSObject* GetPrototype(JSContext* context,
+                                JS::HandleObject global_object);
+  static JSObject* GetInterfaceObject(JSContext* context,
+                                      JS::HandleObject global_object);
 };
 
 }  // namespace bindings
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsInterfaceWithUnsupportedProperties.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsInterfaceWithUnsupportedProperties.cc
index 5831dae..d629315 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsInterfaceWithUnsupportedProperties.cc
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsInterfaceWithUnsupportedProperties.cc
@@ -114,6 +114,26 @@
 static base::LazyInstance<MozjsInterfaceWithUnsupportedPropertiesHandler>
     proxy_handler;
 
+JSBool HasInstance(JSContext *context, JS::HandleObject type,
+                   JS::MutableHandleValue vp, JSBool *success) {
+  JS::RootedObject global_object(
+      context, JS_GetGlobalForObject(context, type));
+  DCHECK(global_object);
+
+  JS::RootedObject prototype(
+      context, MozjsInterfaceWithUnsupportedProperties::GetPrototype(context, global_object));
+
+  // |IsDelegate| walks the prototype chain of an object returning true if
+  // .prototype is found.
+  bool is_delegate;
+  if (!IsDelegate(context, prototype, vp, &is_delegate)) {
+    *success = false;
+    return false;
+  }
+
+  *success = is_delegate;
+  return true;
+}
 
 InterfaceData* CreateCachedInterfaceData() {
   InterfaceData* interface_data = new InterfaceData();
@@ -162,6 +182,7 @@
   interface_object_class->enumerate = JS_EnumerateStub;
   interface_object_class->resolve = JS_ResolveStub;
   interface_object_class->convert = JS_ConvertStub;
+  interface_object_class->hasInstance = &HasInstance;
   return interface_data;
 }
 
@@ -215,14 +236,12 @@
 };
 
 void InitializePrototypeAndInterfaceObject(
-    InterfaceData* interface_data, JSContext* context) {
+    InterfaceData* interface_data, JSContext* context,
+    JS::HandleObject global_object) {
   DCHECK(!interface_data->prototype);
   DCHECK(!interface_data->interface_object);
+  DCHECK(JS_IsGlobalObject(global_object));
 
-  MozjsGlobalObjectProxy* global_object_proxy =
-      static_cast<MozjsGlobalObjectProxy*>(JS_GetContextPrivate(context));
-  JS::RootedObject global_object(context, global_object_proxy->global_object());
-  DCHECK(global_object);
   JS::RootedObject parent_prototype(
       context, JS_GetObjectPrototype(context, global_object));
   DCHECK(parent_prototype);
@@ -301,8 +320,11 @@
 // static
 JSObject* MozjsInterfaceWithUnsupportedProperties::CreateProxy(
     JSContext* context, const scoped_refptr<Wrappable>& wrappable) {
+  JS::RootedObject global_object(context, JS_GetGlobalForScopeChain(context));
+  DCHECK(global_object);
+
   InterfaceData* interface_data = GetInterfaceData(context);
-  JS::RootedObject prototype(context, GetPrototype(context));
+  JS::RootedObject prototype(context, GetPrototype(context, global_object));
   DCHECK(prototype);
   JS::RootedObject new_object(context, JS_NewObjectWithGivenProto(
       context, &interface_data->instance_class_definition, prototype, NULL));
@@ -310,34 +332,45 @@
   JS::RootedObject proxy(context,
       ProxyHandler::NewProxy(context, new_object, prototype, NULL,
                              proxy_handler.Pointer()));
-  WrapperPrivate::AddPrivateData(proxy, wrappable);
+  WrapperPrivate::AddPrivateData(context, proxy, wrappable);
   return proxy;
 }
 
 //static
 const JSClass* MozjsInterfaceWithUnsupportedProperties::PrototypeClass(
       JSContext* context) {
-  JS::RootedObject prototype(context, GetPrototype(context));
+  JS::RootedObject global_object(context, JS_GetGlobalForScopeChain(context));
+  DCHECK(global_object);
+
+  JS::RootedObject prototype(context, GetPrototype(context, global_object));
   JSClass* proto_class = JS_GetClass(*prototype.address());
   return proto_class;
 }
 
 // static
-JSObject* MozjsInterfaceWithUnsupportedProperties::GetPrototype(JSContext* context) {
+JSObject* MozjsInterfaceWithUnsupportedProperties::GetPrototype(
+    JSContext* context, JS::HandleObject global_object) {
+  DCHECK(JS_IsGlobalObject(global_object));
+
   InterfaceData* interface_data = GetInterfaceData(context);
   if (!interface_data->prototype) {
     // Create new prototype that has all the props and methods
-    InitializePrototypeAndInterfaceObject(interface_data, context);
+    InitializePrototypeAndInterfaceObject(
+        interface_data, context, global_object);
   }
   DCHECK(interface_data->prototype);
   return interface_data->prototype;
 }
 
 // static
-JSObject* MozjsInterfaceWithUnsupportedProperties::GetInterfaceObject(JSContext* context) {
+JSObject* MozjsInterfaceWithUnsupportedProperties::GetInterfaceObject(
+    JSContext* context, JS::HandleObject global_object) {
+  DCHECK(JS_IsGlobalObject(global_object));
+
   InterfaceData* interface_data = GetInterfaceData(context);
   if (!interface_data->interface_object) {
-    InitializePrototypeAndInterfaceObject(interface_data, context);
+    InitializePrototypeAndInterfaceObject(
+        interface_data, context, global_object);
   }
   DCHECK(interface_data->interface_object);
   return interface_data->interface_object;
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsInterfaceWithUnsupportedProperties.h b/src/cobalt/bindings/generated/mozjs/testing/MozjsInterfaceWithUnsupportedProperties.h
index 417e204..24c2964 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsInterfaceWithUnsupportedProperties.h
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsInterfaceWithUnsupportedProperties.h
@@ -41,8 +41,10 @@
   static JSObject* CreateProxy(JSContext* context,
       const scoped_refptr<script::Wrappable>& wrappable);
   static const JSClass* PrototypeClass(JSContext* context);
-  static JSObject* GetPrototype(JSContext* context);
-  static JSObject* GetInterfaceObject(JSContext* context);
+  static JSObject* GetPrototype(JSContext* context,
+                                JS::HandleObject global_object);
+  static JSObject* GetInterfaceObject(JSContext* context,
+                                      JS::HandleObject global_object);
 };
 
 }  // namespace bindings
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsNamedConstructorInterface.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsNamedConstructorInterface.cc
index f0a1359..bdb7519 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsNamedConstructorInterface.cc
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsNamedConstructorInterface.cc
@@ -115,6 +115,26 @@
     proxy_handler;
 
 JSBool Constructor(JSContext* context, unsigned int argc, JS::Value* vp);
+JSBool HasInstance(JSContext *context, JS::HandleObject type,
+                   JS::MutableHandleValue vp, JSBool *success) {
+  JS::RootedObject global_object(
+      context, JS_GetGlobalForObject(context, type));
+  DCHECK(global_object);
+
+  JS::RootedObject prototype(
+      context, MozjsNamedConstructorInterface::GetPrototype(context, global_object));
+
+  // |IsDelegate| walks the prototype chain of an object returning true if
+  // .prototype is found.
+  bool is_delegate;
+  if (!IsDelegate(context, prototype, vp, &is_delegate)) {
+    *success = false;
+    return false;
+  }
+
+  *success = is_delegate;
+  return true;
+}
 
 InterfaceData* CreateCachedInterfaceData() {
   InterfaceData* interface_data = new InterfaceData();
@@ -163,6 +183,7 @@
   interface_object_class->enumerate = JS_EnumerateStub;
   interface_object_class->resolve = JS_ResolveStub;
   interface_object_class->convert = JS_ConvertStub;
+  interface_object_class->hasInstance = &HasInstance;
   interface_object_class->construct = Constructor;
   return interface_data;
 }
@@ -189,14 +210,12 @@
 };
 
 void InitializePrototypeAndInterfaceObject(
-    InterfaceData* interface_data, JSContext* context) {
+    InterfaceData* interface_data, JSContext* context,
+    JS::HandleObject global_object) {
   DCHECK(!interface_data->prototype);
   DCHECK(!interface_data->interface_object);
+  DCHECK(JS_IsGlobalObject(global_object));
 
-  MozjsGlobalObjectProxy* global_object_proxy =
-      static_cast<MozjsGlobalObjectProxy*>(JS_GetContextPrivate(context));
-  JS::RootedObject global_object(context, global_object_proxy->global_object());
-  DCHECK(global_object);
   JS::RootedObject parent_prototype(
       context, JS_GetObjectPrototype(context, global_object));
   DCHECK(parent_prototype);
@@ -285,8 +304,11 @@
 // static
 JSObject* MozjsNamedConstructorInterface::CreateProxy(
     JSContext* context, const scoped_refptr<Wrappable>& wrappable) {
+  JS::RootedObject global_object(context, JS_GetGlobalForScopeChain(context));
+  DCHECK(global_object);
+
   InterfaceData* interface_data = GetInterfaceData(context);
-  JS::RootedObject prototype(context, GetPrototype(context));
+  JS::RootedObject prototype(context, GetPrototype(context, global_object));
   DCHECK(prototype);
   JS::RootedObject new_object(context, JS_NewObjectWithGivenProto(
       context, &interface_data->instance_class_definition, prototype, NULL));
@@ -294,34 +316,45 @@
   JS::RootedObject proxy(context,
       ProxyHandler::NewProxy(context, new_object, prototype, NULL,
                              proxy_handler.Pointer()));
-  WrapperPrivate::AddPrivateData(proxy, wrappable);
+  WrapperPrivate::AddPrivateData(context, proxy, wrappable);
   return proxy;
 }
 
 //static
 const JSClass* MozjsNamedConstructorInterface::PrototypeClass(
       JSContext* context) {
-  JS::RootedObject prototype(context, GetPrototype(context));
+  JS::RootedObject global_object(context, JS_GetGlobalForScopeChain(context));
+  DCHECK(global_object);
+
+  JS::RootedObject prototype(context, GetPrototype(context, global_object));
   JSClass* proto_class = JS_GetClass(*prototype.address());
   return proto_class;
 }
 
 // static
-JSObject* MozjsNamedConstructorInterface::GetPrototype(JSContext* context) {
+JSObject* MozjsNamedConstructorInterface::GetPrototype(
+    JSContext* context, JS::HandleObject global_object) {
+  DCHECK(JS_IsGlobalObject(global_object));
+
   InterfaceData* interface_data = GetInterfaceData(context);
   if (!interface_data->prototype) {
     // Create new prototype that has all the props and methods
-    InitializePrototypeAndInterfaceObject(interface_data, context);
+    InitializePrototypeAndInterfaceObject(
+        interface_data, context, global_object);
   }
   DCHECK(interface_data->prototype);
   return interface_data->prototype;
 }
 
 // static
-JSObject* MozjsNamedConstructorInterface::GetInterfaceObject(JSContext* context) {
+JSObject* MozjsNamedConstructorInterface::GetInterfaceObject(
+    JSContext* context, JS::HandleObject global_object) {
+  DCHECK(JS_IsGlobalObject(global_object));
+
   InterfaceData* interface_data = GetInterfaceData(context);
   if (!interface_data->interface_object) {
-    InitializePrototypeAndInterfaceObject(interface_data, context);
+    InitializePrototypeAndInterfaceObject(
+        interface_data, context, global_object);
   }
   DCHECK(interface_data->interface_object);
   return interface_data->interface_object;
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsNamedConstructorInterface.h b/src/cobalt/bindings/generated/mozjs/testing/MozjsNamedConstructorInterface.h
index 670e6fc..bee4c6b 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsNamedConstructorInterface.h
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsNamedConstructorInterface.h
@@ -41,8 +41,10 @@
   static JSObject* CreateProxy(JSContext* context,
       const scoped_refptr<script::Wrappable>& wrappable);
   static const JSClass* PrototypeClass(JSContext* context);
-  static JSObject* GetPrototype(JSContext* context);
-  static JSObject* GetInterfaceObject(JSContext* context);
+  static JSObject* GetPrototype(JSContext* context,
+                                JS::HandleObject global_object);
+  static JSObject* GetInterfaceObject(JSContext* context,
+                                      JS::HandleObject global_object);
 };
 
 }  // namespace bindings
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsNamedGetterInterface.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsNamedGetterInterface.cc
index d9debc4..f77d8de 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsNamedGetterInterface.cc
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsNamedGetterInterface.cc
@@ -220,6 +220,26 @@
 static base::LazyInstance<MozjsNamedGetterInterfaceHandler>
     proxy_handler;
 
+JSBool HasInstance(JSContext *context, JS::HandleObject type,
+                   JS::MutableHandleValue vp, JSBool *success) {
+  JS::RootedObject global_object(
+      context, JS_GetGlobalForObject(context, type));
+  DCHECK(global_object);
+
+  JS::RootedObject prototype(
+      context, MozjsNamedGetterInterface::GetPrototype(context, global_object));
+
+  // |IsDelegate| walks the prototype chain of an object returning true if
+  // .prototype is found.
+  bool is_delegate;
+  if (!IsDelegate(context, prototype, vp, &is_delegate)) {
+    *success = false;
+    return false;
+  }
+
+  *success = is_delegate;
+  return true;
+}
 
 InterfaceData* CreateCachedInterfaceData() {
   InterfaceData* interface_data = new InterfaceData();
@@ -268,6 +288,7 @@
   interface_object_class->enumerate = JS_EnumerateStub;
   interface_object_class->resolve = JS_ResolveStub;
   interface_object_class->convert = JS_ConvertStub;
+  interface_object_class->hasInstance = &HasInstance;
   return interface_data;
 }
 
@@ -473,14 +494,12 @@
 };
 
 void InitializePrototypeAndInterfaceObject(
-    InterfaceData* interface_data, JSContext* context) {
+    InterfaceData* interface_data, JSContext* context,
+    JS::HandleObject global_object) {
   DCHECK(!interface_data->prototype);
   DCHECK(!interface_data->interface_object);
+  DCHECK(JS_IsGlobalObject(global_object));
 
-  MozjsGlobalObjectProxy* global_object_proxy =
-      static_cast<MozjsGlobalObjectProxy*>(JS_GetContextPrivate(context));
-  JS::RootedObject global_object(context, global_object_proxy->global_object());
-  DCHECK(global_object);
   JS::RootedObject parent_prototype(
       context, JS_GetObjectPrototype(context, global_object));
   DCHECK(parent_prototype);
@@ -559,8 +578,11 @@
 // static
 JSObject* MozjsNamedGetterInterface::CreateProxy(
     JSContext* context, const scoped_refptr<Wrappable>& wrappable) {
+  JS::RootedObject global_object(context, JS_GetGlobalForScopeChain(context));
+  DCHECK(global_object);
+
   InterfaceData* interface_data = GetInterfaceData(context);
-  JS::RootedObject prototype(context, GetPrototype(context));
+  JS::RootedObject prototype(context, GetPrototype(context, global_object));
   DCHECK(prototype);
   JS::RootedObject new_object(context, JS_NewObjectWithGivenProto(
       context, &interface_data->instance_class_definition, prototype, NULL));
@@ -568,34 +590,45 @@
   JS::RootedObject proxy(context,
       ProxyHandler::NewProxy(context, new_object, prototype, NULL,
                              proxy_handler.Pointer()));
-  WrapperPrivate::AddPrivateData(proxy, wrappable);
+  WrapperPrivate::AddPrivateData(context, proxy, wrappable);
   return proxy;
 }
 
 //static
 const JSClass* MozjsNamedGetterInterface::PrototypeClass(
       JSContext* context) {
-  JS::RootedObject prototype(context, GetPrototype(context));
+  JS::RootedObject global_object(context, JS_GetGlobalForScopeChain(context));
+  DCHECK(global_object);
+
+  JS::RootedObject prototype(context, GetPrototype(context, global_object));
   JSClass* proto_class = JS_GetClass(*prototype.address());
   return proto_class;
 }
 
 // static
-JSObject* MozjsNamedGetterInterface::GetPrototype(JSContext* context) {
+JSObject* MozjsNamedGetterInterface::GetPrototype(
+    JSContext* context, JS::HandleObject global_object) {
+  DCHECK(JS_IsGlobalObject(global_object));
+
   InterfaceData* interface_data = GetInterfaceData(context);
   if (!interface_data->prototype) {
     // Create new prototype that has all the props and methods
-    InitializePrototypeAndInterfaceObject(interface_data, context);
+    InitializePrototypeAndInterfaceObject(
+        interface_data, context, global_object);
   }
   DCHECK(interface_data->prototype);
   return interface_data->prototype;
 }
 
 // static
-JSObject* MozjsNamedGetterInterface::GetInterfaceObject(JSContext* context) {
+JSObject* MozjsNamedGetterInterface::GetInterfaceObject(
+    JSContext* context, JS::HandleObject global_object) {
+  DCHECK(JS_IsGlobalObject(global_object));
+
   InterfaceData* interface_data = GetInterfaceData(context);
   if (!interface_data->interface_object) {
-    InitializePrototypeAndInterfaceObject(interface_data, context);
+    InitializePrototypeAndInterfaceObject(
+        interface_data, context, global_object);
   }
   DCHECK(interface_data->interface_object);
   return interface_data->interface_object;
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsNamedGetterInterface.h b/src/cobalt/bindings/generated/mozjs/testing/MozjsNamedGetterInterface.h
index 613c1b9..0d06347 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsNamedGetterInterface.h
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsNamedGetterInterface.h
@@ -41,8 +41,10 @@
   static JSObject* CreateProxy(JSContext* context,
       const scoped_refptr<script::Wrappable>& wrappable);
   static const JSClass* PrototypeClass(JSContext* context);
-  static JSObject* GetPrototype(JSContext* context);
-  static JSObject* GetInterfaceObject(JSContext* context);
+  static JSObject* GetPrototype(JSContext* context,
+                                JS::HandleObject global_object);
+  static JSObject* GetInterfaceObject(JSContext* context,
+                                      JS::HandleObject global_object);
 };
 
 }  // namespace bindings
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsNamedIndexedGetterInterface.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsNamedIndexedGetterInterface.cc
index e63ec48..bc60f6a 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsNamedIndexedGetterInterface.cc
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsNamedIndexedGetterInterface.cc
@@ -296,6 +296,26 @@
 static base::LazyInstance<MozjsNamedIndexedGetterInterfaceHandler>
     proxy_handler;
 
+JSBool HasInstance(JSContext *context, JS::HandleObject type,
+                   JS::MutableHandleValue vp, JSBool *success) {
+  JS::RootedObject global_object(
+      context, JS_GetGlobalForObject(context, type));
+  DCHECK(global_object);
+
+  JS::RootedObject prototype(
+      context, MozjsNamedIndexedGetterInterface::GetPrototype(context, global_object));
+
+  // |IsDelegate| walks the prototype chain of an object returning true if
+  // .prototype is found.
+  bool is_delegate;
+  if (!IsDelegate(context, prototype, vp, &is_delegate)) {
+    *success = false;
+    return false;
+  }
+
+  *success = is_delegate;
+  return true;
+}
 
 InterfaceData* CreateCachedInterfaceData() {
   InterfaceData* interface_data = new InterfaceData();
@@ -344,6 +364,7 @@
   interface_object_class->enumerate = JS_EnumerateStub;
   interface_object_class->resolve = JS_ResolveStub;
   interface_object_class->convert = JS_ConvertStub;
+  interface_object_class->hasInstance = &HasInstance;
   return interface_data;
 }
 
@@ -734,14 +755,12 @@
 };
 
 void InitializePrototypeAndInterfaceObject(
-    InterfaceData* interface_data, JSContext* context) {
+    InterfaceData* interface_data, JSContext* context,
+    JS::HandleObject global_object) {
   DCHECK(!interface_data->prototype);
   DCHECK(!interface_data->interface_object);
+  DCHECK(JS_IsGlobalObject(global_object));
 
-  MozjsGlobalObjectProxy* global_object_proxy =
-      static_cast<MozjsGlobalObjectProxy*>(JS_GetContextPrivate(context));
-  JS::RootedObject global_object(context, global_object_proxy->global_object());
-  DCHECK(global_object);
   JS::RootedObject parent_prototype(
       context, JS_GetObjectPrototype(context, global_object));
   DCHECK(parent_prototype);
@@ -820,8 +839,11 @@
 // static
 JSObject* MozjsNamedIndexedGetterInterface::CreateProxy(
     JSContext* context, const scoped_refptr<Wrappable>& wrappable) {
+  JS::RootedObject global_object(context, JS_GetGlobalForScopeChain(context));
+  DCHECK(global_object);
+
   InterfaceData* interface_data = GetInterfaceData(context);
-  JS::RootedObject prototype(context, GetPrototype(context));
+  JS::RootedObject prototype(context, GetPrototype(context, global_object));
   DCHECK(prototype);
   JS::RootedObject new_object(context, JS_NewObjectWithGivenProto(
       context, &interface_data->instance_class_definition, prototype, NULL));
@@ -829,34 +851,45 @@
   JS::RootedObject proxy(context,
       ProxyHandler::NewProxy(context, new_object, prototype, NULL,
                              proxy_handler.Pointer()));
-  WrapperPrivate::AddPrivateData(proxy, wrappable);
+  WrapperPrivate::AddPrivateData(context, proxy, wrappable);
   return proxy;
 }
 
 //static
 const JSClass* MozjsNamedIndexedGetterInterface::PrototypeClass(
       JSContext* context) {
-  JS::RootedObject prototype(context, GetPrototype(context));
+  JS::RootedObject global_object(context, JS_GetGlobalForScopeChain(context));
+  DCHECK(global_object);
+
+  JS::RootedObject prototype(context, GetPrototype(context, global_object));
   JSClass* proto_class = JS_GetClass(*prototype.address());
   return proto_class;
 }
 
 // static
-JSObject* MozjsNamedIndexedGetterInterface::GetPrototype(JSContext* context) {
+JSObject* MozjsNamedIndexedGetterInterface::GetPrototype(
+    JSContext* context, JS::HandleObject global_object) {
+  DCHECK(JS_IsGlobalObject(global_object));
+
   InterfaceData* interface_data = GetInterfaceData(context);
   if (!interface_data->prototype) {
     // Create new prototype that has all the props and methods
-    InitializePrototypeAndInterfaceObject(interface_data, context);
+    InitializePrototypeAndInterfaceObject(
+        interface_data, context, global_object);
   }
   DCHECK(interface_data->prototype);
   return interface_data->prototype;
 }
 
 // static
-JSObject* MozjsNamedIndexedGetterInterface::GetInterfaceObject(JSContext* context) {
+JSObject* MozjsNamedIndexedGetterInterface::GetInterfaceObject(
+    JSContext* context, JS::HandleObject global_object) {
+  DCHECK(JS_IsGlobalObject(global_object));
+
   InterfaceData* interface_data = GetInterfaceData(context);
   if (!interface_data->interface_object) {
-    InitializePrototypeAndInterfaceObject(interface_data, context);
+    InitializePrototypeAndInterfaceObject(
+        interface_data, context, global_object);
   }
   DCHECK(interface_data->interface_object);
   return interface_data->interface_object;
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsNamedIndexedGetterInterface.h b/src/cobalt/bindings/generated/mozjs/testing/MozjsNamedIndexedGetterInterface.h
index d0cc78a..ef5bbfa 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsNamedIndexedGetterInterface.h
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsNamedIndexedGetterInterface.h
@@ -41,8 +41,10 @@
   static JSObject* CreateProxy(JSContext* context,
       const scoped_refptr<script::Wrappable>& wrappable);
   static const JSClass* PrototypeClass(JSContext* context);
-  static JSObject* GetPrototype(JSContext* context);
-  static JSObject* GetInterfaceObject(JSContext* context);
+  static JSObject* GetPrototype(JSContext* context,
+                                JS::HandleObject global_object);
+  static JSObject* GetInterfaceObject(JSContext* context,
+                                      JS::HandleObject global_object);
 };
 
 }  // namespace bindings
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsNestedPutForwardsInterface.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsNestedPutForwardsInterface.cc
index e665fea..d30656e 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsNestedPutForwardsInterface.cc
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsNestedPutForwardsInterface.cc
@@ -118,6 +118,26 @@
 static base::LazyInstance<MozjsNestedPutForwardsInterfaceHandler>
     proxy_handler;
 
+JSBool HasInstance(JSContext *context, JS::HandleObject type,
+                   JS::MutableHandleValue vp, JSBool *success) {
+  JS::RootedObject global_object(
+      context, JS_GetGlobalForObject(context, type));
+  DCHECK(global_object);
+
+  JS::RootedObject prototype(
+      context, MozjsNestedPutForwardsInterface::GetPrototype(context, global_object));
+
+  // |IsDelegate| walks the prototype chain of an object returning true if
+  // .prototype is found.
+  bool is_delegate;
+  if (!IsDelegate(context, prototype, vp, &is_delegate)) {
+    *success = false;
+    return false;
+  }
+
+  *success = is_delegate;
+  return true;
+}
 
 InterfaceData* CreateCachedInterfaceData() {
   InterfaceData* interface_data = new InterfaceData();
@@ -166,6 +186,7 @@
   interface_object_class->enumerate = JS_EnumerateStub;
   interface_object_class->resolve = JS_ResolveStub;
   interface_object_class->convert = JS_ConvertStub;
+  interface_object_class->hasInstance = &HasInstance;
   return interface_data;
 }
 
@@ -263,14 +284,12 @@
 };
 
 void InitializePrototypeAndInterfaceObject(
-    InterfaceData* interface_data, JSContext* context) {
+    InterfaceData* interface_data, JSContext* context,
+    JS::HandleObject global_object) {
   DCHECK(!interface_data->prototype);
   DCHECK(!interface_data->interface_object);
+  DCHECK(JS_IsGlobalObject(global_object));
 
-  MozjsGlobalObjectProxy* global_object_proxy =
-      static_cast<MozjsGlobalObjectProxy*>(JS_GetContextPrivate(context));
-  JS::RootedObject global_object(context, global_object_proxy->global_object());
-  DCHECK(global_object);
   JS::RootedObject parent_prototype(
       context, JS_GetObjectPrototype(context, global_object));
   DCHECK(parent_prototype);
@@ -349,8 +368,11 @@
 // static
 JSObject* MozjsNestedPutForwardsInterface::CreateProxy(
     JSContext* context, const scoped_refptr<Wrappable>& wrappable) {
+  JS::RootedObject global_object(context, JS_GetGlobalForScopeChain(context));
+  DCHECK(global_object);
+
   InterfaceData* interface_data = GetInterfaceData(context);
-  JS::RootedObject prototype(context, GetPrototype(context));
+  JS::RootedObject prototype(context, GetPrototype(context, global_object));
   DCHECK(prototype);
   JS::RootedObject new_object(context, JS_NewObjectWithGivenProto(
       context, &interface_data->instance_class_definition, prototype, NULL));
@@ -358,34 +380,45 @@
   JS::RootedObject proxy(context,
       ProxyHandler::NewProxy(context, new_object, prototype, NULL,
                              proxy_handler.Pointer()));
-  WrapperPrivate::AddPrivateData(proxy, wrappable);
+  WrapperPrivate::AddPrivateData(context, proxy, wrappable);
   return proxy;
 }
 
 //static
 const JSClass* MozjsNestedPutForwardsInterface::PrototypeClass(
       JSContext* context) {
-  JS::RootedObject prototype(context, GetPrototype(context));
+  JS::RootedObject global_object(context, JS_GetGlobalForScopeChain(context));
+  DCHECK(global_object);
+
+  JS::RootedObject prototype(context, GetPrototype(context, global_object));
   JSClass* proto_class = JS_GetClass(*prototype.address());
   return proto_class;
 }
 
 // static
-JSObject* MozjsNestedPutForwardsInterface::GetPrototype(JSContext* context) {
+JSObject* MozjsNestedPutForwardsInterface::GetPrototype(
+    JSContext* context, JS::HandleObject global_object) {
+  DCHECK(JS_IsGlobalObject(global_object));
+
   InterfaceData* interface_data = GetInterfaceData(context);
   if (!interface_data->prototype) {
     // Create new prototype that has all the props and methods
-    InitializePrototypeAndInterfaceObject(interface_data, context);
+    InitializePrototypeAndInterfaceObject(
+        interface_data, context, global_object);
   }
   DCHECK(interface_data->prototype);
   return interface_data->prototype;
 }
 
 // static
-JSObject* MozjsNestedPutForwardsInterface::GetInterfaceObject(JSContext* context) {
+JSObject* MozjsNestedPutForwardsInterface::GetInterfaceObject(
+    JSContext* context, JS::HandleObject global_object) {
+  DCHECK(JS_IsGlobalObject(global_object));
+
   InterfaceData* interface_data = GetInterfaceData(context);
   if (!interface_data->interface_object) {
-    InitializePrototypeAndInterfaceObject(interface_data, context);
+    InitializePrototypeAndInterfaceObject(
+        interface_data, context, global_object);
   }
   DCHECK(interface_data->interface_object);
   return interface_data->interface_object;
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsNestedPutForwardsInterface.h b/src/cobalt/bindings/generated/mozjs/testing/MozjsNestedPutForwardsInterface.h
index 47b1965..50e0e3c 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsNestedPutForwardsInterface.h
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsNestedPutForwardsInterface.h
@@ -41,8 +41,10 @@
   static JSObject* CreateProxy(JSContext* context,
       const scoped_refptr<script::Wrappable>& wrappable);
   static const JSClass* PrototypeClass(JSContext* context);
-  static JSObject* GetPrototype(JSContext* context);
-  static JSObject* GetInterfaceObject(JSContext* context);
+  static JSObject* GetPrototype(JSContext* context,
+                                JS::HandleObject global_object);
+  static JSObject* GetInterfaceObject(JSContext* context,
+                                      JS::HandleObject global_object);
 };
 
 }  // namespace bindings
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsNoConstructorInterface.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsNoConstructorInterface.cc
index ecf9e98..1848abb 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsNoConstructorInterface.cc
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsNoConstructorInterface.cc
@@ -114,6 +114,26 @@
 static base::LazyInstance<MozjsNoConstructorInterfaceHandler>
     proxy_handler;
 
+JSBool HasInstance(JSContext *context, JS::HandleObject type,
+                   JS::MutableHandleValue vp, JSBool *success) {
+  JS::RootedObject global_object(
+      context, JS_GetGlobalForObject(context, type));
+  DCHECK(global_object);
+
+  JS::RootedObject prototype(
+      context, MozjsNoConstructorInterface::GetPrototype(context, global_object));
+
+  // |IsDelegate| walks the prototype chain of an object returning true if
+  // .prototype is found.
+  bool is_delegate;
+  if (!IsDelegate(context, prototype, vp, &is_delegate)) {
+    *success = false;
+    return false;
+  }
+
+  *success = is_delegate;
+  return true;
+}
 
 InterfaceData* CreateCachedInterfaceData() {
   InterfaceData* interface_data = new InterfaceData();
@@ -162,6 +182,7 @@
   interface_object_class->enumerate = JS_EnumerateStub;
   interface_object_class->resolve = JS_ResolveStub;
   interface_object_class->convert = JS_ConvertStub;
+  interface_object_class->hasInstance = &HasInstance;
   return interface_data;
 }
 
@@ -187,14 +208,12 @@
 };
 
 void InitializePrototypeAndInterfaceObject(
-    InterfaceData* interface_data, JSContext* context) {
+    InterfaceData* interface_data, JSContext* context,
+    JS::HandleObject global_object) {
   DCHECK(!interface_data->prototype);
   DCHECK(!interface_data->interface_object);
+  DCHECK(JS_IsGlobalObject(global_object));
 
-  MozjsGlobalObjectProxy* global_object_proxy =
-      static_cast<MozjsGlobalObjectProxy*>(JS_GetContextPrivate(context));
-  JS::RootedObject global_object(context, global_object_proxy->global_object());
-  DCHECK(global_object);
   JS::RootedObject parent_prototype(
       context, JS_GetObjectPrototype(context, global_object));
   DCHECK(parent_prototype);
@@ -273,8 +292,11 @@
 // static
 JSObject* MozjsNoConstructorInterface::CreateProxy(
     JSContext* context, const scoped_refptr<Wrappable>& wrappable) {
+  JS::RootedObject global_object(context, JS_GetGlobalForScopeChain(context));
+  DCHECK(global_object);
+
   InterfaceData* interface_data = GetInterfaceData(context);
-  JS::RootedObject prototype(context, GetPrototype(context));
+  JS::RootedObject prototype(context, GetPrototype(context, global_object));
   DCHECK(prototype);
   JS::RootedObject new_object(context, JS_NewObjectWithGivenProto(
       context, &interface_data->instance_class_definition, prototype, NULL));
@@ -282,34 +304,45 @@
   JS::RootedObject proxy(context,
       ProxyHandler::NewProxy(context, new_object, prototype, NULL,
                              proxy_handler.Pointer()));
-  WrapperPrivate::AddPrivateData(proxy, wrappable);
+  WrapperPrivate::AddPrivateData(context, proxy, wrappable);
   return proxy;
 }
 
 //static
 const JSClass* MozjsNoConstructorInterface::PrototypeClass(
       JSContext* context) {
-  JS::RootedObject prototype(context, GetPrototype(context));
+  JS::RootedObject global_object(context, JS_GetGlobalForScopeChain(context));
+  DCHECK(global_object);
+
+  JS::RootedObject prototype(context, GetPrototype(context, global_object));
   JSClass* proto_class = JS_GetClass(*prototype.address());
   return proto_class;
 }
 
 // static
-JSObject* MozjsNoConstructorInterface::GetPrototype(JSContext* context) {
+JSObject* MozjsNoConstructorInterface::GetPrototype(
+    JSContext* context, JS::HandleObject global_object) {
+  DCHECK(JS_IsGlobalObject(global_object));
+
   InterfaceData* interface_data = GetInterfaceData(context);
   if (!interface_data->prototype) {
     // Create new prototype that has all the props and methods
-    InitializePrototypeAndInterfaceObject(interface_data, context);
+    InitializePrototypeAndInterfaceObject(
+        interface_data, context, global_object);
   }
   DCHECK(interface_data->prototype);
   return interface_data->prototype;
 }
 
 // static
-JSObject* MozjsNoConstructorInterface::GetInterfaceObject(JSContext* context) {
+JSObject* MozjsNoConstructorInterface::GetInterfaceObject(
+    JSContext* context, JS::HandleObject global_object) {
+  DCHECK(JS_IsGlobalObject(global_object));
+
   InterfaceData* interface_data = GetInterfaceData(context);
   if (!interface_data->interface_object) {
-    InitializePrototypeAndInterfaceObject(interface_data, context);
+    InitializePrototypeAndInterfaceObject(
+        interface_data, context, global_object);
   }
   DCHECK(interface_data->interface_object);
   return interface_data->interface_object;
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsNoConstructorInterface.h b/src/cobalt/bindings/generated/mozjs/testing/MozjsNoConstructorInterface.h
index 1c2a1c8..8fe1474 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsNoConstructorInterface.h
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsNoConstructorInterface.h
@@ -41,8 +41,10 @@
   static JSObject* CreateProxy(JSContext* context,
       const scoped_refptr<script::Wrappable>& wrappable);
   static const JSClass* PrototypeClass(JSContext* context);
-  static JSObject* GetPrototype(JSContext* context);
-  static JSObject* GetInterfaceObject(JSContext* context);
+  static JSObject* GetPrototype(JSContext* context,
+                                JS::HandleObject global_object);
+  static JSObject* GetInterfaceObject(JSContext* context,
+                                      JS::HandleObject global_object);
 };
 
 }  // namespace bindings
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsNoInterfaceObjectInterface.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsNoInterfaceObjectInterface.cc
index 27d50a2..1ad2cbb 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsNoInterfaceObjectInterface.cc
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsNoInterfaceObjectInterface.cc
@@ -114,6 +114,26 @@
 static base::LazyInstance<MozjsNoInterfaceObjectInterfaceHandler>
     proxy_handler;
 
+JSBool HasInstance(JSContext *context, JS::HandleObject type,
+                   JS::MutableHandleValue vp, JSBool *success) {
+  JS::RootedObject global_object(
+      context, JS_GetGlobalForObject(context, type));
+  DCHECK(global_object);
+
+  JS::RootedObject prototype(
+      context, MozjsNoInterfaceObjectInterface::GetPrototype(context, global_object));
+
+  // |IsDelegate| walks the prototype chain of an object returning true if
+  // .prototype is found.
+  bool is_delegate;
+  if (!IsDelegate(context, prototype, vp, &is_delegate)) {
+    *success = false;
+    return false;
+  }
+
+  *success = is_delegate;
+  return true;
+}
 
 InterfaceData* CreateCachedInterfaceData() {
   InterfaceData* interface_data = new InterfaceData();
@@ -162,6 +182,7 @@
   interface_object_class->enumerate = JS_EnumerateStub;
   interface_object_class->resolve = JS_ResolveStub;
   interface_object_class->convert = JS_ConvertStub;
+  interface_object_class->hasInstance = &HasInstance;
   return interface_data;
 }
 
@@ -187,14 +208,12 @@
 };
 
 void InitializePrototypeAndInterfaceObject(
-    InterfaceData* interface_data, JSContext* context) {
+    InterfaceData* interface_data, JSContext* context,
+    JS::HandleObject global_object) {
   DCHECK(!interface_data->prototype);
   DCHECK(!interface_data->interface_object);
+  DCHECK(JS_IsGlobalObject(global_object));
 
-  MozjsGlobalObjectProxy* global_object_proxy =
-      static_cast<MozjsGlobalObjectProxy*>(JS_GetContextPrivate(context));
-  JS::RootedObject global_object(context, global_object_proxy->global_object());
-  DCHECK(global_object);
   JS::RootedObject parent_prototype(
       context, JS_GetObjectPrototype(context, global_object));
   DCHECK(parent_prototype);
@@ -233,8 +252,11 @@
 // static
 JSObject* MozjsNoInterfaceObjectInterface::CreateProxy(
     JSContext* context, const scoped_refptr<Wrappable>& wrappable) {
+  JS::RootedObject global_object(context, JS_GetGlobalForScopeChain(context));
+  DCHECK(global_object);
+
   InterfaceData* interface_data = GetInterfaceData(context);
-  JS::RootedObject prototype(context, GetPrototype(context));
+  JS::RootedObject prototype(context, GetPrototype(context, global_object));
   DCHECK(prototype);
   JS::RootedObject new_object(context, JS_NewObjectWithGivenProto(
       context, &interface_data->instance_class_definition, prototype, NULL));
@@ -242,24 +264,31 @@
   JS::RootedObject proxy(context,
       ProxyHandler::NewProxy(context, new_object, prototype, NULL,
                              proxy_handler.Pointer()));
-  WrapperPrivate::AddPrivateData(proxy, wrappable);
+  WrapperPrivate::AddPrivateData(context, proxy, wrappable);
   return proxy;
 }
 
 //static
 const JSClass* MozjsNoInterfaceObjectInterface::PrototypeClass(
       JSContext* context) {
-  JS::RootedObject prototype(context, GetPrototype(context));
+  JS::RootedObject global_object(context, JS_GetGlobalForScopeChain(context));
+  DCHECK(global_object);
+
+  JS::RootedObject prototype(context, GetPrototype(context, global_object));
   JSClass* proto_class = JS_GetClass(*prototype.address());
   return proto_class;
 }
 
 // static
-JSObject* MozjsNoInterfaceObjectInterface::GetPrototype(JSContext* context) {
+JSObject* MozjsNoInterfaceObjectInterface::GetPrototype(
+    JSContext* context, JS::HandleObject global_object) {
+  DCHECK(JS_IsGlobalObject(global_object));
+
   InterfaceData* interface_data = GetInterfaceData(context);
   if (!interface_data->prototype) {
     // Create new prototype that has all the props and methods
-    InitializePrototypeAndInterfaceObject(interface_data, context);
+    InitializePrototypeAndInterfaceObject(
+        interface_data, context, global_object);
   }
   DCHECK(interface_data->prototype);
   return interface_data->prototype;
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsNoInterfaceObjectInterface.h b/src/cobalt/bindings/generated/mozjs/testing/MozjsNoInterfaceObjectInterface.h
index 8d5c0f1..1d0061f 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsNoInterfaceObjectInterface.h
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsNoInterfaceObjectInterface.h
@@ -41,7 +41,8 @@
   static JSObject* CreateProxy(JSContext* context,
       const scoped_refptr<script::Wrappable>& wrappable);
   static const JSClass* PrototypeClass(JSContext* context);
-  static JSObject* GetPrototype(JSContext* context);
+  static JSObject* GetPrototype(JSContext* context,
+                                JS::HandleObject global_object);
 };
 
 }  // namespace bindings
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsNullableTypesTestInterface.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsNullableTypesTestInterface.cc
index 3176045..04c7ec4 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsNullableTypesTestInterface.cc
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsNullableTypesTestInterface.cc
@@ -118,6 +118,26 @@
 static base::LazyInstance<MozjsNullableTypesTestInterfaceHandler>
     proxy_handler;
 
+JSBool HasInstance(JSContext *context, JS::HandleObject type,
+                   JS::MutableHandleValue vp, JSBool *success) {
+  JS::RootedObject global_object(
+      context, JS_GetGlobalForObject(context, type));
+  DCHECK(global_object);
+
+  JS::RootedObject prototype(
+      context, MozjsNullableTypesTestInterface::GetPrototype(context, global_object));
+
+  // |IsDelegate| walks the prototype chain of an object returning true if
+  // .prototype is found.
+  bool is_delegate;
+  if (!IsDelegate(context, prototype, vp, &is_delegate)) {
+    *success = false;
+    return false;
+  }
+
+  *success = is_delegate;
+  return true;
+}
 
 InterfaceData* CreateCachedInterfaceData() {
   InterfaceData* interface_data = new InterfaceData();
@@ -166,6 +186,7 @@
   interface_object_class->enumerate = JS_EnumerateStub;
   interface_object_class->resolve = JS_ResolveStub;
   interface_object_class->convert = JS_ConvertStub;
+  interface_object_class->hasInstance = &HasInstance;
   return interface_data;
 }
 
@@ -771,14 +792,12 @@
 };
 
 void InitializePrototypeAndInterfaceObject(
-    InterfaceData* interface_data, JSContext* context) {
+    InterfaceData* interface_data, JSContext* context,
+    JS::HandleObject global_object) {
   DCHECK(!interface_data->prototype);
   DCHECK(!interface_data->interface_object);
+  DCHECK(JS_IsGlobalObject(global_object));
 
-  MozjsGlobalObjectProxy* global_object_proxy =
-      static_cast<MozjsGlobalObjectProxy*>(JS_GetContextPrivate(context));
-  JS::RootedObject global_object(context, global_object_proxy->global_object());
-  DCHECK(global_object);
   JS::RootedObject parent_prototype(
       context, JS_GetObjectPrototype(context, global_object));
   DCHECK(parent_prototype);
@@ -857,8 +876,11 @@
 // static
 JSObject* MozjsNullableTypesTestInterface::CreateProxy(
     JSContext* context, const scoped_refptr<Wrappable>& wrappable) {
+  JS::RootedObject global_object(context, JS_GetGlobalForScopeChain(context));
+  DCHECK(global_object);
+
   InterfaceData* interface_data = GetInterfaceData(context);
-  JS::RootedObject prototype(context, GetPrototype(context));
+  JS::RootedObject prototype(context, GetPrototype(context, global_object));
   DCHECK(prototype);
   JS::RootedObject new_object(context, JS_NewObjectWithGivenProto(
       context, &interface_data->instance_class_definition, prototype, NULL));
@@ -866,34 +888,45 @@
   JS::RootedObject proxy(context,
       ProxyHandler::NewProxy(context, new_object, prototype, NULL,
                              proxy_handler.Pointer()));
-  WrapperPrivate::AddPrivateData(proxy, wrappable);
+  WrapperPrivate::AddPrivateData(context, proxy, wrappable);
   return proxy;
 }
 
 //static
 const JSClass* MozjsNullableTypesTestInterface::PrototypeClass(
       JSContext* context) {
-  JS::RootedObject prototype(context, GetPrototype(context));
+  JS::RootedObject global_object(context, JS_GetGlobalForScopeChain(context));
+  DCHECK(global_object);
+
+  JS::RootedObject prototype(context, GetPrototype(context, global_object));
   JSClass* proto_class = JS_GetClass(*prototype.address());
   return proto_class;
 }
 
 // static
-JSObject* MozjsNullableTypesTestInterface::GetPrototype(JSContext* context) {
+JSObject* MozjsNullableTypesTestInterface::GetPrototype(
+    JSContext* context, JS::HandleObject global_object) {
+  DCHECK(JS_IsGlobalObject(global_object));
+
   InterfaceData* interface_data = GetInterfaceData(context);
   if (!interface_data->prototype) {
     // Create new prototype that has all the props and methods
-    InitializePrototypeAndInterfaceObject(interface_data, context);
+    InitializePrototypeAndInterfaceObject(
+        interface_data, context, global_object);
   }
   DCHECK(interface_data->prototype);
   return interface_data->prototype;
 }
 
 // static
-JSObject* MozjsNullableTypesTestInterface::GetInterfaceObject(JSContext* context) {
+JSObject* MozjsNullableTypesTestInterface::GetInterfaceObject(
+    JSContext* context, JS::HandleObject global_object) {
+  DCHECK(JS_IsGlobalObject(global_object));
+
   InterfaceData* interface_data = GetInterfaceData(context);
   if (!interface_data->interface_object) {
-    InitializePrototypeAndInterfaceObject(interface_data, context);
+    InitializePrototypeAndInterfaceObject(
+        interface_data, context, global_object);
   }
   DCHECK(interface_data->interface_object);
   return interface_data->interface_object;
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsNullableTypesTestInterface.h b/src/cobalt/bindings/generated/mozjs/testing/MozjsNullableTypesTestInterface.h
index 69bfddd..7b7bcb2 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsNullableTypesTestInterface.h
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsNullableTypesTestInterface.h
@@ -41,8 +41,10 @@
   static JSObject* CreateProxy(JSContext* context,
       const scoped_refptr<script::Wrappable>& wrappable);
   static const JSClass* PrototypeClass(JSContext* context);
-  static JSObject* GetPrototype(JSContext* context);
-  static JSObject* GetInterfaceObject(JSContext* context);
+  static JSObject* GetPrototype(JSContext* context,
+                                JS::HandleObject global_object);
+  static JSObject* GetInterfaceObject(JSContext* context,
+                                      JS::HandleObject global_object);
 };
 
 }  // namespace bindings
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsNumericTypesTestInterface.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsNumericTypesTestInterface.cc
index bfa31b4..546ed1a 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsNumericTypesTestInterface.cc
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsNumericTypesTestInterface.cc
@@ -114,6 +114,26 @@
 static base::LazyInstance<MozjsNumericTypesTestInterfaceHandler>
     proxy_handler;
 
+JSBool HasInstance(JSContext *context, JS::HandleObject type,
+                   JS::MutableHandleValue vp, JSBool *success) {
+  JS::RootedObject global_object(
+      context, JS_GetGlobalForObject(context, type));
+  DCHECK(global_object);
+
+  JS::RootedObject prototype(
+      context, MozjsNumericTypesTestInterface::GetPrototype(context, global_object));
+
+  // |IsDelegate| walks the prototype chain of an object returning true if
+  // .prototype is found.
+  bool is_delegate;
+  if (!IsDelegate(context, prototype, vp, &is_delegate)) {
+    *success = false;
+    return false;
+  }
+
+  *success = is_delegate;
+  return true;
+}
 
 InterfaceData* CreateCachedInterfaceData() {
   InterfaceData* interface_data = new InterfaceData();
@@ -162,6 +182,7 @@
   interface_object_class->enumerate = JS_EnumerateStub;
   interface_object_class->resolve = JS_ResolveStub;
   interface_object_class->convert = JS_ConvertStub;
+  interface_object_class->hasInstance = &HasInstance;
   return interface_data;
 }
 
@@ -1637,14 +1658,12 @@
 };
 
 void InitializePrototypeAndInterfaceObject(
-    InterfaceData* interface_data, JSContext* context) {
+    InterfaceData* interface_data, JSContext* context,
+    JS::HandleObject global_object) {
   DCHECK(!interface_data->prototype);
   DCHECK(!interface_data->interface_object);
+  DCHECK(JS_IsGlobalObject(global_object));
 
-  MozjsGlobalObjectProxy* global_object_proxy =
-      static_cast<MozjsGlobalObjectProxy*>(JS_GetContextPrivate(context));
-  JS::RootedObject global_object(context, global_object_proxy->global_object());
-  DCHECK(global_object);
   JS::RootedObject parent_prototype(
       context, JS_GetObjectPrototype(context, global_object));
   DCHECK(parent_prototype);
@@ -1723,8 +1742,11 @@
 // static
 JSObject* MozjsNumericTypesTestInterface::CreateProxy(
     JSContext* context, const scoped_refptr<Wrappable>& wrappable) {
+  JS::RootedObject global_object(context, JS_GetGlobalForScopeChain(context));
+  DCHECK(global_object);
+
   InterfaceData* interface_data = GetInterfaceData(context);
-  JS::RootedObject prototype(context, GetPrototype(context));
+  JS::RootedObject prototype(context, GetPrototype(context, global_object));
   DCHECK(prototype);
   JS::RootedObject new_object(context, JS_NewObjectWithGivenProto(
       context, &interface_data->instance_class_definition, prototype, NULL));
@@ -1732,34 +1754,45 @@
   JS::RootedObject proxy(context,
       ProxyHandler::NewProxy(context, new_object, prototype, NULL,
                              proxy_handler.Pointer()));
-  WrapperPrivate::AddPrivateData(proxy, wrappable);
+  WrapperPrivate::AddPrivateData(context, proxy, wrappable);
   return proxy;
 }
 
 //static
 const JSClass* MozjsNumericTypesTestInterface::PrototypeClass(
       JSContext* context) {
-  JS::RootedObject prototype(context, GetPrototype(context));
+  JS::RootedObject global_object(context, JS_GetGlobalForScopeChain(context));
+  DCHECK(global_object);
+
+  JS::RootedObject prototype(context, GetPrototype(context, global_object));
   JSClass* proto_class = JS_GetClass(*prototype.address());
   return proto_class;
 }
 
 // static
-JSObject* MozjsNumericTypesTestInterface::GetPrototype(JSContext* context) {
+JSObject* MozjsNumericTypesTestInterface::GetPrototype(
+    JSContext* context, JS::HandleObject global_object) {
+  DCHECK(JS_IsGlobalObject(global_object));
+
   InterfaceData* interface_data = GetInterfaceData(context);
   if (!interface_data->prototype) {
     // Create new prototype that has all the props and methods
-    InitializePrototypeAndInterfaceObject(interface_data, context);
+    InitializePrototypeAndInterfaceObject(
+        interface_data, context, global_object);
   }
   DCHECK(interface_data->prototype);
   return interface_data->prototype;
 }
 
 // static
-JSObject* MozjsNumericTypesTestInterface::GetInterfaceObject(JSContext* context) {
+JSObject* MozjsNumericTypesTestInterface::GetInterfaceObject(
+    JSContext* context, JS::HandleObject global_object) {
+  DCHECK(JS_IsGlobalObject(global_object));
+
   InterfaceData* interface_data = GetInterfaceData(context);
   if (!interface_data->interface_object) {
-    InitializePrototypeAndInterfaceObject(interface_data, context);
+    InitializePrototypeAndInterfaceObject(
+        interface_data, context, global_object);
   }
   DCHECK(interface_data->interface_object);
   return interface_data->interface_object;
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsNumericTypesTestInterface.h b/src/cobalt/bindings/generated/mozjs/testing/MozjsNumericTypesTestInterface.h
index f33342b..e02d41a 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsNumericTypesTestInterface.h
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsNumericTypesTestInterface.h
@@ -41,8 +41,10 @@
   static JSObject* CreateProxy(JSContext* context,
       const scoped_refptr<script::Wrappable>& wrappable);
   static const JSClass* PrototypeClass(JSContext* context);
-  static JSObject* GetPrototype(JSContext* context);
-  static JSObject* GetInterfaceObject(JSContext* context);
+  static JSObject* GetPrototype(JSContext* context,
+                                JS::HandleObject global_object);
+  static JSObject* GetInterfaceObject(JSContext* context,
+                                      JS::HandleObject global_object);
 };
 
 }  // namespace bindings
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsObjectTypeBindingsInterface.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsObjectTypeBindingsInterface.cc
index 5e32d87..4dbc0b3 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsObjectTypeBindingsInterface.cc
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsObjectTypeBindingsInterface.cc
@@ -126,6 +126,26 @@
 static base::LazyInstance<MozjsObjectTypeBindingsInterfaceHandler>
     proxy_handler;
 
+JSBool HasInstance(JSContext *context, JS::HandleObject type,
+                   JS::MutableHandleValue vp, JSBool *success) {
+  JS::RootedObject global_object(
+      context, JS_GetGlobalForObject(context, type));
+  DCHECK(global_object);
+
+  JS::RootedObject prototype(
+      context, MozjsObjectTypeBindingsInterface::GetPrototype(context, global_object));
+
+  // |IsDelegate| walks the prototype chain of an object returning true if
+  // .prototype is found.
+  bool is_delegate;
+  if (!IsDelegate(context, prototype, vp, &is_delegate)) {
+    *success = false;
+    return false;
+  }
+
+  *success = is_delegate;
+  return true;
+}
 
 InterfaceData* CreateCachedInterfaceData() {
   InterfaceData* interface_data = new InterfaceData();
@@ -174,6 +194,7 @@
   interface_object_class->enumerate = JS_EnumerateStub;
   interface_object_class->resolve = JS_ResolveStub;
   interface_object_class->convert = JS_ConvertStub;
+  interface_object_class->hasInstance = &HasInstance;
   return interface_data;
 }
 
@@ -377,14 +398,12 @@
 };
 
 void InitializePrototypeAndInterfaceObject(
-    InterfaceData* interface_data, JSContext* context) {
+    InterfaceData* interface_data, JSContext* context,
+    JS::HandleObject global_object) {
   DCHECK(!interface_data->prototype);
   DCHECK(!interface_data->interface_object);
+  DCHECK(JS_IsGlobalObject(global_object));
 
-  MozjsGlobalObjectProxy* global_object_proxy =
-      static_cast<MozjsGlobalObjectProxy*>(JS_GetContextPrivate(context));
-  JS::RootedObject global_object(context, global_object_proxy->global_object());
-  DCHECK(global_object);
   JS::RootedObject parent_prototype(
       context, JS_GetObjectPrototype(context, global_object));
   DCHECK(parent_prototype);
@@ -463,8 +482,11 @@
 // static
 JSObject* MozjsObjectTypeBindingsInterface::CreateProxy(
     JSContext* context, const scoped_refptr<Wrappable>& wrappable) {
+  JS::RootedObject global_object(context, JS_GetGlobalForScopeChain(context));
+  DCHECK(global_object);
+
   InterfaceData* interface_data = GetInterfaceData(context);
-  JS::RootedObject prototype(context, GetPrototype(context));
+  JS::RootedObject prototype(context, GetPrototype(context, global_object));
   DCHECK(prototype);
   JS::RootedObject new_object(context, JS_NewObjectWithGivenProto(
       context, &interface_data->instance_class_definition, prototype, NULL));
@@ -472,34 +494,45 @@
   JS::RootedObject proxy(context,
       ProxyHandler::NewProxy(context, new_object, prototype, NULL,
                              proxy_handler.Pointer()));
-  WrapperPrivate::AddPrivateData(proxy, wrappable);
+  WrapperPrivate::AddPrivateData(context, proxy, wrappable);
   return proxy;
 }
 
 //static
 const JSClass* MozjsObjectTypeBindingsInterface::PrototypeClass(
       JSContext* context) {
-  JS::RootedObject prototype(context, GetPrototype(context));
+  JS::RootedObject global_object(context, JS_GetGlobalForScopeChain(context));
+  DCHECK(global_object);
+
+  JS::RootedObject prototype(context, GetPrototype(context, global_object));
   JSClass* proto_class = JS_GetClass(*prototype.address());
   return proto_class;
 }
 
 // static
-JSObject* MozjsObjectTypeBindingsInterface::GetPrototype(JSContext* context) {
+JSObject* MozjsObjectTypeBindingsInterface::GetPrototype(
+    JSContext* context, JS::HandleObject global_object) {
+  DCHECK(JS_IsGlobalObject(global_object));
+
   InterfaceData* interface_data = GetInterfaceData(context);
   if (!interface_data->prototype) {
     // Create new prototype that has all the props and methods
-    InitializePrototypeAndInterfaceObject(interface_data, context);
+    InitializePrototypeAndInterfaceObject(
+        interface_data, context, global_object);
   }
   DCHECK(interface_data->prototype);
   return interface_data->prototype;
 }
 
 // static
-JSObject* MozjsObjectTypeBindingsInterface::GetInterfaceObject(JSContext* context) {
+JSObject* MozjsObjectTypeBindingsInterface::GetInterfaceObject(
+    JSContext* context, JS::HandleObject global_object) {
+  DCHECK(JS_IsGlobalObject(global_object));
+
   InterfaceData* interface_data = GetInterfaceData(context);
   if (!interface_data->interface_object) {
-    InitializePrototypeAndInterfaceObject(interface_data, context);
+    InitializePrototypeAndInterfaceObject(
+        interface_data, context, global_object);
   }
   DCHECK(interface_data->interface_object);
   return interface_data->interface_object;
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsObjectTypeBindingsInterface.h b/src/cobalt/bindings/generated/mozjs/testing/MozjsObjectTypeBindingsInterface.h
index 27aa23c..8ae6e03 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsObjectTypeBindingsInterface.h
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsObjectTypeBindingsInterface.h
@@ -41,8 +41,10 @@
   static JSObject* CreateProxy(JSContext* context,
       const scoped_refptr<script::Wrappable>& wrappable);
   static const JSClass* PrototypeClass(JSContext* context);
-  static JSObject* GetPrototype(JSContext* context);
-  static JSObject* GetInterfaceObject(JSContext* context);
+  static JSObject* GetPrototype(JSContext* context,
+                                JS::HandleObject global_object);
+  static JSObject* GetInterfaceObject(JSContext* context,
+                                      JS::HandleObject global_object);
 };
 
 }  // namespace bindings
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsOperationsTestInterface.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsOperationsTestInterface.cc
index 473b292..7d9c1b0 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsOperationsTestInterface.cc
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsOperationsTestInterface.cc
@@ -118,6 +118,26 @@
 static base::LazyInstance<MozjsOperationsTestInterfaceHandler>
     proxy_handler;
 
+JSBool HasInstance(JSContext *context, JS::HandleObject type,
+                   JS::MutableHandleValue vp, JSBool *success) {
+  JS::RootedObject global_object(
+      context, JS_GetGlobalForObject(context, type));
+  DCHECK(global_object);
+
+  JS::RootedObject prototype(
+      context, MozjsOperationsTestInterface::GetPrototype(context, global_object));
+
+  // |IsDelegate| walks the prototype chain of an object returning true if
+  // .prototype is found.
+  bool is_delegate;
+  if (!IsDelegate(context, prototype, vp, &is_delegate)) {
+    *success = false;
+    return false;
+  }
+
+  *success = is_delegate;
+  return true;
+}
 
 InterfaceData* CreateCachedInterfaceData() {
   InterfaceData* interface_data = new InterfaceData();
@@ -166,6 +186,7 @@
   interface_object_class->enumerate = JS_EnumerateStub;
   interface_object_class->resolve = JS_ResolveStub;
   interface_object_class->convert = JS_ConvertStub;
+  interface_object_class->hasInstance = &HasInstance;
   return interface_data;
 }
 
@@ -1460,14 +1481,12 @@
 };
 
 void InitializePrototypeAndInterfaceObject(
-    InterfaceData* interface_data, JSContext* context) {
+    InterfaceData* interface_data, JSContext* context,
+    JS::HandleObject global_object) {
   DCHECK(!interface_data->prototype);
   DCHECK(!interface_data->interface_object);
+  DCHECK(JS_IsGlobalObject(global_object));
 
-  MozjsGlobalObjectProxy* global_object_proxy =
-      static_cast<MozjsGlobalObjectProxy*>(JS_GetContextPrivate(context));
-  JS::RootedObject global_object(context, global_object_proxy->global_object());
-  DCHECK(global_object);
   JS::RootedObject parent_prototype(
       context, JS_GetObjectPrototype(context, global_object));
   DCHECK(parent_prototype);
@@ -1546,8 +1565,11 @@
 // static
 JSObject* MozjsOperationsTestInterface::CreateProxy(
     JSContext* context, const scoped_refptr<Wrappable>& wrappable) {
+  JS::RootedObject global_object(context, JS_GetGlobalForScopeChain(context));
+  DCHECK(global_object);
+
   InterfaceData* interface_data = GetInterfaceData(context);
-  JS::RootedObject prototype(context, GetPrototype(context));
+  JS::RootedObject prototype(context, GetPrototype(context, global_object));
   DCHECK(prototype);
   JS::RootedObject new_object(context, JS_NewObjectWithGivenProto(
       context, &interface_data->instance_class_definition, prototype, NULL));
@@ -1555,34 +1577,45 @@
   JS::RootedObject proxy(context,
       ProxyHandler::NewProxy(context, new_object, prototype, NULL,
                              proxy_handler.Pointer()));
-  WrapperPrivate::AddPrivateData(proxy, wrappable);
+  WrapperPrivate::AddPrivateData(context, proxy, wrappable);
   return proxy;
 }
 
 //static
 const JSClass* MozjsOperationsTestInterface::PrototypeClass(
       JSContext* context) {
-  JS::RootedObject prototype(context, GetPrototype(context));
+  JS::RootedObject global_object(context, JS_GetGlobalForScopeChain(context));
+  DCHECK(global_object);
+
+  JS::RootedObject prototype(context, GetPrototype(context, global_object));
   JSClass* proto_class = JS_GetClass(*prototype.address());
   return proto_class;
 }
 
 // static
-JSObject* MozjsOperationsTestInterface::GetPrototype(JSContext* context) {
+JSObject* MozjsOperationsTestInterface::GetPrototype(
+    JSContext* context, JS::HandleObject global_object) {
+  DCHECK(JS_IsGlobalObject(global_object));
+
   InterfaceData* interface_data = GetInterfaceData(context);
   if (!interface_data->prototype) {
     // Create new prototype that has all the props and methods
-    InitializePrototypeAndInterfaceObject(interface_data, context);
+    InitializePrototypeAndInterfaceObject(
+        interface_data, context, global_object);
   }
   DCHECK(interface_data->prototype);
   return interface_data->prototype;
 }
 
 // static
-JSObject* MozjsOperationsTestInterface::GetInterfaceObject(JSContext* context) {
+JSObject* MozjsOperationsTestInterface::GetInterfaceObject(
+    JSContext* context, JS::HandleObject global_object) {
+  DCHECK(JS_IsGlobalObject(global_object));
+
   InterfaceData* interface_data = GetInterfaceData(context);
   if (!interface_data->interface_object) {
-    InitializePrototypeAndInterfaceObject(interface_data, context);
+    InitializePrototypeAndInterfaceObject(
+        interface_data, context, global_object);
   }
   DCHECK(interface_data->interface_object);
   return interface_data->interface_object;
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsOperationsTestInterface.h b/src/cobalt/bindings/generated/mozjs/testing/MozjsOperationsTestInterface.h
index d0e54e1..3968437 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsOperationsTestInterface.h
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsOperationsTestInterface.h
@@ -41,8 +41,10 @@
   static JSObject* CreateProxy(JSContext* context,
       const scoped_refptr<script::Wrappable>& wrappable);
   static const JSClass* PrototypeClass(JSContext* context);
-  static JSObject* GetPrototype(JSContext* context);
-  static JSObject* GetInterfaceObject(JSContext* context);
+  static JSObject* GetPrototype(JSContext* context,
+                                JS::HandleObject global_object);
+  static JSObject* GetInterfaceObject(JSContext* context,
+                                      JS::HandleObject global_object);
 };
 
 }  // namespace bindings
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsPutForwardsInterface.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsPutForwardsInterface.cc
index b977879..c632988 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsPutForwardsInterface.cc
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsPutForwardsInterface.cc
@@ -118,6 +118,26 @@
 static base::LazyInstance<MozjsPutForwardsInterfaceHandler>
     proxy_handler;
 
+JSBool HasInstance(JSContext *context, JS::HandleObject type,
+                   JS::MutableHandleValue vp, JSBool *success) {
+  JS::RootedObject global_object(
+      context, JS_GetGlobalForObject(context, type));
+  DCHECK(global_object);
+
+  JS::RootedObject prototype(
+      context, MozjsPutForwardsInterface::GetPrototype(context, global_object));
+
+  // |IsDelegate| walks the prototype chain of an object returning true if
+  // .prototype is found.
+  bool is_delegate;
+  if (!IsDelegate(context, prototype, vp, &is_delegate)) {
+    *success = false;
+    return false;
+  }
+
+  *success = is_delegate;
+  return true;
+}
 
 InterfaceData* CreateCachedInterfaceData() {
   InterfaceData* interface_data = new InterfaceData();
@@ -166,6 +186,7 @@
   interface_object_class->enumerate = JS_EnumerateStub;
   interface_object_class->resolve = JS_ResolveStub;
   interface_object_class->convert = JS_ConvertStub;
+  interface_object_class->hasInstance = &HasInstance;
   return interface_data;
 }
 
@@ -304,14 +325,12 @@
 };
 
 void InitializePrototypeAndInterfaceObject(
-    InterfaceData* interface_data, JSContext* context) {
+    InterfaceData* interface_data, JSContext* context,
+    JS::HandleObject global_object) {
   DCHECK(!interface_data->prototype);
   DCHECK(!interface_data->interface_object);
+  DCHECK(JS_IsGlobalObject(global_object));
 
-  MozjsGlobalObjectProxy* global_object_proxy =
-      static_cast<MozjsGlobalObjectProxy*>(JS_GetContextPrivate(context));
-  JS::RootedObject global_object(context, global_object_proxy->global_object());
-  DCHECK(global_object);
   JS::RootedObject parent_prototype(
       context, JS_GetObjectPrototype(context, global_object));
   DCHECK(parent_prototype);
@@ -390,8 +409,11 @@
 // static
 JSObject* MozjsPutForwardsInterface::CreateProxy(
     JSContext* context, const scoped_refptr<Wrappable>& wrappable) {
+  JS::RootedObject global_object(context, JS_GetGlobalForScopeChain(context));
+  DCHECK(global_object);
+
   InterfaceData* interface_data = GetInterfaceData(context);
-  JS::RootedObject prototype(context, GetPrototype(context));
+  JS::RootedObject prototype(context, GetPrototype(context, global_object));
   DCHECK(prototype);
   JS::RootedObject new_object(context, JS_NewObjectWithGivenProto(
       context, &interface_data->instance_class_definition, prototype, NULL));
@@ -399,34 +421,45 @@
   JS::RootedObject proxy(context,
       ProxyHandler::NewProxy(context, new_object, prototype, NULL,
                              proxy_handler.Pointer()));
-  WrapperPrivate::AddPrivateData(proxy, wrappable);
+  WrapperPrivate::AddPrivateData(context, proxy, wrappable);
   return proxy;
 }
 
 //static
 const JSClass* MozjsPutForwardsInterface::PrototypeClass(
       JSContext* context) {
-  JS::RootedObject prototype(context, GetPrototype(context));
+  JS::RootedObject global_object(context, JS_GetGlobalForScopeChain(context));
+  DCHECK(global_object);
+
+  JS::RootedObject prototype(context, GetPrototype(context, global_object));
   JSClass* proto_class = JS_GetClass(*prototype.address());
   return proto_class;
 }
 
 // static
-JSObject* MozjsPutForwardsInterface::GetPrototype(JSContext* context) {
+JSObject* MozjsPutForwardsInterface::GetPrototype(
+    JSContext* context, JS::HandleObject global_object) {
+  DCHECK(JS_IsGlobalObject(global_object));
+
   InterfaceData* interface_data = GetInterfaceData(context);
   if (!interface_data->prototype) {
     // Create new prototype that has all the props and methods
-    InitializePrototypeAndInterfaceObject(interface_data, context);
+    InitializePrototypeAndInterfaceObject(
+        interface_data, context, global_object);
   }
   DCHECK(interface_data->prototype);
   return interface_data->prototype;
 }
 
 // static
-JSObject* MozjsPutForwardsInterface::GetInterfaceObject(JSContext* context) {
+JSObject* MozjsPutForwardsInterface::GetInterfaceObject(
+    JSContext* context, JS::HandleObject global_object) {
+  DCHECK(JS_IsGlobalObject(global_object));
+
   InterfaceData* interface_data = GetInterfaceData(context);
   if (!interface_data->interface_object) {
-    InitializePrototypeAndInterfaceObject(interface_data, context);
+    InitializePrototypeAndInterfaceObject(
+        interface_data, context, global_object);
   }
   DCHECK(interface_data->interface_object);
   return interface_data->interface_object;
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsPutForwardsInterface.h b/src/cobalt/bindings/generated/mozjs/testing/MozjsPutForwardsInterface.h
index 06a6435..f0f5881 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsPutForwardsInterface.h
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsPutForwardsInterface.h
@@ -41,8 +41,10 @@
   static JSObject* CreateProxy(JSContext* context,
       const scoped_refptr<script::Wrappable>& wrappable);
   static const JSClass* PrototypeClass(JSContext* context);
-  static JSObject* GetPrototype(JSContext* context);
-  static JSObject* GetInterfaceObject(JSContext* context);
+  static JSObject* GetPrototype(JSContext* context,
+                                JS::HandleObject global_object);
+  static JSObject* GetInterfaceObject(JSContext* context,
+                                      JS::HandleObject global_object);
 };
 
 }  // namespace bindings
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsStaticPropertiesInterface.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsStaticPropertiesInterface.cc
index 210586c..7cd708f 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsStaticPropertiesInterface.cc
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsStaticPropertiesInterface.cc
@@ -118,6 +118,26 @@
 static base::LazyInstance<MozjsStaticPropertiesInterfaceHandler>
     proxy_handler;
 
+JSBool HasInstance(JSContext *context, JS::HandleObject type,
+                   JS::MutableHandleValue vp, JSBool *success) {
+  JS::RootedObject global_object(
+      context, JS_GetGlobalForObject(context, type));
+  DCHECK(global_object);
+
+  JS::RootedObject prototype(
+      context, MozjsStaticPropertiesInterface::GetPrototype(context, global_object));
+
+  // |IsDelegate| walks the prototype chain of an object returning true if
+  // .prototype is found.
+  bool is_delegate;
+  if (!IsDelegate(context, prototype, vp, &is_delegate)) {
+    *success = false;
+    return false;
+  }
+
+  *success = is_delegate;
+  return true;
+}
 
 InterfaceData* CreateCachedInterfaceData() {
   InterfaceData* interface_data = new InterfaceData();
@@ -166,6 +186,7 @@
   interface_object_class->enumerate = JS_EnumerateStub;
   interface_object_class->resolve = JS_ResolveStub;
   interface_object_class->convert = JS_ConvertStub;
+  interface_object_class->hasInstance = &HasInstance;
   return interface_data;
 }
 
@@ -486,14 +507,12 @@
 };
 
 void InitializePrototypeAndInterfaceObject(
-    InterfaceData* interface_data, JSContext* context) {
+    InterfaceData* interface_data, JSContext* context,
+    JS::HandleObject global_object) {
   DCHECK(!interface_data->prototype);
   DCHECK(!interface_data->interface_object);
+  DCHECK(JS_IsGlobalObject(global_object));
 
-  MozjsGlobalObjectProxy* global_object_proxy =
-      static_cast<MozjsGlobalObjectProxy*>(JS_GetContextPrivate(context));
-  JS::RootedObject global_object(context, global_object_proxy->global_object());
-  DCHECK(global_object);
   JS::RootedObject parent_prototype(
       context, JS_GetObjectPrototype(context, global_object));
   DCHECK(parent_prototype);
@@ -572,8 +591,11 @@
 // static
 JSObject* MozjsStaticPropertiesInterface::CreateProxy(
     JSContext* context, const scoped_refptr<Wrappable>& wrappable) {
+  JS::RootedObject global_object(context, JS_GetGlobalForScopeChain(context));
+  DCHECK(global_object);
+
   InterfaceData* interface_data = GetInterfaceData(context);
-  JS::RootedObject prototype(context, GetPrototype(context));
+  JS::RootedObject prototype(context, GetPrototype(context, global_object));
   DCHECK(prototype);
   JS::RootedObject new_object(context, JS_NewObjectWithGivenProto(
       context, &interface_data->instance_class_definition, prototype, NULL));
@@ -581,34 +603,45 @@
   JS::RootedObject proxy(context,
       ProxyHandler::NewProxy(context, new_object, prototype, NULL,
                              proxy_handler.Pointer()));
-  WrapperPrivate::AddPrivateData(proxy, wrappable);
+  WrapperPrivate::AddPrivateData(context, proxy, wrappable);
   return proxy;
 }
 
 //static
 const JSClass* MozjsStaticPropertiesInterface::PrototypeClass(
       JSContext* context) {
-  JS::RootedObject prototype(context, GetPrototype(context));
+  JS::RootedObject global_object(context, JS_GetGlobalForScopeChain(context));
+  DCHECK(global_object);
+
+  JS::RootedObject prototype(context, GetPrototype(context, global_object));
   JSClass* proto_class = JS_GetClass(*prototype.address());
   return proto_class;
 }
 
 // static
-JSObject* MozjsStaticPropertiesInterface::GetPrototype(JSContext* context) {
+JSObject* MozjsStaticPropertiesInterface::GetPrototype(
+    JSContext* context, JS::HandleObject global_object) {
+  DCHECK(JS_IsGlobalObject(global_object));
+
   InterfaceData* interface_data = GetInterfaceData(context);
   if (!interface_data->prototype) {
     // Create new prototype that has all the props and methods
-    InitializePrototypeAndInterfaceObject(interface_data, context);
+    InitializePrototypeAndInterfaceObject(
+        interface_data, context, global_object);
   }
   DCHECK(interface_data->prototype);
   return interface_data->prototype;
 }
 
 // static
-JSObject* MozjsStaticPropertiesInterface::GetInterfaceObject(JSContext* context) {
+JSObject* MozjsStaticPropertiesInterface::GetInterfaceObject(
+    JSContext* context, JS::HandleObject global_object) {
+  DCHECK(JS_IsGlobalObject(global_object));
+
   InterfaceData* interface_data = GetInterfaceData(context);
   if (!interface_data->interface_object) {
-    InitializePrototypeAndInterfaceObject(interface_data, context);
+    InitializePrototypeAndInterfaceObject(
+        interface_data, context, global_object);
   }
   DCHECK(interface_data->interface_object);
   return interface_data->interface_object;
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsStaticPropertiesInterface.h b/src/cobalt/bindings/generated/mozjs/testing/MozjsStaticPropertiesInterface.h
index db46890..27cb5e2 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsStaticPropertiesInterface.h
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsStaticPropertiesInterface.h
@@ -41,8 +41,10 @@
   static JSObject* CreateProxy(JSContext* context,
       const scoped_refptr<script::Wrappable>& wrappable);
   static const JSClass* PrototypeClass(JSContext* context);
-  static JSObject* GetPrototype(JSContext* context);
-  static JSObject* GetInterfaceObject(JSContext* context);
+  static JSObject* GetPrototype(JSContext* context,
+                                JS::HandleObject global_object);
+  static JSObject* GetInterfaceObject(JSContext* context,
+                                      JS::HandleObject global_object);
 };
 
 }  // namespace bindings
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsStringifierAnonymousOperationInterface.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsStringifierAnonymousOperationInterface.cc
index d77b60e..2471dfc 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsStringifierAnonymousOperationInterface.cc
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsStringifierAnonymousOperationInterface.cc
@@ -114,6 +114,26 @@
 static base::LazyInstance<MozjsStringifierAnonymousOperationInterfaceHandler>
     proxy_handler;
 
+JSBool HasInstance(JSContext *context, JS::HandleObject type,
+                   JS::MutableHandleValue vp, JSBool *success) {
+  JS::RootedObject global_object(
+      context, JS_GetGlobalForObject(context, type));
+  DCHECK(global_object);
+
+  JS::RootedObject prototype(
+      context, MozjsStringifierAnonymousOperationInterface::GetPrototype(context, global_object));
+
+  // |IsDelegate| walks the prototype chain of an object returning true if
+  // .prototype is found.
+  bool is_delegate;
+  if (!IsDelegate(context, prototype, vp, &is_delegate)) {
+    *success = false;
+    return false;
+  }
+
+  *success = is_delegate;
+  return true;
+}
 
 InterfaceData* CreateCachedInterfaceData() {
   InterfaceData* interface_data = new InterfaceData();
@@ -162,6 +182,7 @@
   interface_object_class->enumerate = JS_EnumerateStub;
   interface_object_class->resolve = JS_ResolveStub;
   interface_object_class->convert = JS_ConvertStub;
+  interface_object_class->hasInstance = &HasInstance;
   return interface_data;
 }
 
@@ -226,14 +247,12 @@
 };
 
 void InitializePrototypeAndInterfaceObject(
-    InterfaceData* interface_data, JSContext* context) {
+    InterfaceData* interface_data, JSContext* context,
+    JS::HandleObject global_object) {
   DCHECK(!interface_data->prototype);
   DCHECK(!interface_data->interface_object);
+  DCHECK(JS_IsGlobalObject(global_object));
 
-  MozjsGlobalObjectProxy* global_object_proxy =
-      static_cast<MozjsGlobalObjectProxy*>(JS_GetContextPrivate(context));
-  JS::RootedObject global_object(context, global_object_proxy->global_object());
-  DCHECK(global_object);
   JS::RootedObject parent_prototype(
       context, JS_GetObjectPrototype(context, global_object));
   DCHECK(parent_prototype);
@@ -312,8 +331,11 @@
 // static
 JSObject* MozjsStringifierAnonymousOperationInterface::CreateProxy(
     JSContext* context, const scoped_refptr<Wrappable>& wrappable) {
+  JS::RootedObject global_object(context, JS_GetGlobalForScopeChain(context));
+  DCHECK(global_object);
+
   InterfaceData* interface_data = GetInterfaceData(context);
-  JS::RootedObject prototype(context, GetPrototype(context));
+  JS::RootedObject prototype(context, GetPrototype(context, global_object));
   DCHECK(prototype);
   JS::RootedObject new_object(context, JS_NewObjectWithGivenProto(
       context, &interface_data->instance_class_definition, prototype, NULL));
@@ -321,34 +343,45 @@
   JS::RootedObject proxy(context,
       ProxyHandler::NewProxy(context, new_object, prototype, NULL,
                              proxy_handler.Pointer()));
-  WrapperPrivate::AddPrivateData(proxy, wrappable);
+  WrapperPrivate::AddPrivateData(context, proxy, wrappable);
   return proxy;
 }
 
 //static
 const JSClass* MozjsStringifierAnonymousOperationInterface::PrototypeClass(
       JSContext* context) {
-  JS::RootedObject prototype(context, GetPrototype(context));
+  JS::RootedObject global_object(context, JS_GetGlobalForScopeChain(context));
+  DCHECK(global_object);
+
+  JS::RootedObject prototype(context, GetPrototype(context, global_object));
   JSClass* proto_class = JS_GetClass(*prototype.address());
   return proto_class;
 }
 
 // static
-JSObject* MozjsStringifierAnonymousOperationInterface::GetPrototype(JSContext* context) {
+JSObject* MozjsStringifierAnonymousOperationInterface::GetPrototype(
+    JSContext* context, JS::HandleObject global_object) {
+  DCHECK(JS_IsGlobalObject(global_object));
+
   InterfaceData* interface_data = GetInterfaceData(context);
   if (!interface_data->prototype) {
     // Create new prototype that has all the props and methods
-    InitializePrototypeAndInterfaceObject(interface_data, context);
+    InitializePrototypeAndInterfaceObject(
+        interface_data, context, global_object);
   }
   DCHECK(interface_data->prototype);
   return interface_data->prototype;
 }
 
 // static
-JSObject* MozjsStringifierAnonymousOperationInterface::GetInterfaceObject(JSContext* context) {
+JSObject* MozjsStringifierAnonymousOperationInterface::GetInterfaceObject(
+    JSContext* context, JS::HandleObject global_object) {
+  DCHECK(JS_IsGlobalObject(global_object));
+
   InterfaceData* interface_data = GetInterfaceData(context);
   if (!interface_data->interface_object) {
-    InitializePrototypeAndInterfaceObject(interface_data, context);
+    InitializePrototypeAndInterfaceObject(
+        interface_data, context, global_object);
   }
   DCHECK(interface_data->interface_object);
   return interface_data->interface_object;
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsStringifierAnonymousOperationInterface.h b/src/cobalt/bindings/generated/mozjs/testing/MozjsStringifierAnonymousOperationInterface.h
index 0115c6a..b18e5a5 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsStringifierAnonymousOperationInterface.h
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsStringifierAnonymousOperationInterface.h
@@ -41,8 +41,10 @@
   static JSObject* CreateProxy(JSContext* context,
       const scoped_refptr<script::Wrappable>& wrappable);
   static const JSClass* PrototypeClass(JSContext* context);
-  static JSObject* GetPrototype(JSContext* context);
-  static JSObject* GetInterfaceObject(JSContext* context);
+  static JSObject* GetPrototype(JSContext* context,
+                                JS::HandleObject global_object);
+  static JSObject* GetInterfaceObject(JSContext* context,
+                                      JS::HandleObject global_object);
 };
 
 }  // namespace bindings
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsStringifierAttributeInterface.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsStringifierAttributeInterface.cc
index d652475..f97b025 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsStringifierAttributeInterface.cc
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsStringifierAttributeInterface.cc
@@ -114,6 +114,26 @@
 static base::LazyInstance<MozjsStringifierAttributeInterfaceHandler>
     proxy_handler;
 
+JSBool HasInstance(JSContext *context, JS::HandleObject type,
+                   JS::MutableHandleValue vp, JSBool *success) {
+  JS::RootedObject global_object(
+      context, JS_GetGlobalForObject(context, type));
+  DCHECK(global_object);
+
+  JS::RootedObject prototype(
+      context, MozjsStringifierAttributeInterface::GetPrototype(context, global_object));
+
+  // |IsDelegate| walks the prototype chain of an object returning true if
+  // .prototype is found.
+  bool is_delegate;
+  if (!IsDelegate(context, prototype, vp, &is_delegate)) {
+    *success = false;
+    return false;
+  }
+
+  *success = is_delegate;
+  return true;
+}
 
 InterfaceData* CreateCachedInterfaceData() {
   InterfaceData* interface_data = new InterfaceData();
@@ -162,6 +182,7 @@
   interface_object_class->enumerate = JS_EnumerateStub;
   interface_object_class->resolve = JS_ResolveStub;
   interface_object_class->convert = JS_ConvertStub;
+  interface_object_class->hasInstance = &HasInstance;
   return interface_data;
 }
 
@@ -276,14 +297,12 @@
 };
 
 void InitializePrototypeAndInterfaceObject(
-    InterfaceData* interface_data, JSContext* context) {
+    InterfaceData* interface_data, JSContext* context,
+    JS::HandleObject global_object) {
   DCHECK(!interface_data->prototype);
   DCHECK(!interface_data->interface_object);
+  DCHECK(JS_IsGlobalObject(global_object));
 
-  MozjsGlobalObjectProxy* global_object_proxy =
-      static_cast<MozjsGlobalObjectProxy*>(JS_GetContextPrivate(context));
-  JS::RootedObject global_object(context, global_object_proxy->global_object());
-  DCHECK(global_object);
   JS::RootedObject parent_prototype(
       context, JS_GetObjectPrototype(context, global_object));
   DCHECK(parent_prototype);
@@ -362,8 +381,11 @@
 // static
 JSObject* MozjsStringifierAttributeInterface::CreateProxy(
     JSContext* context, const scoped_refptr<Wrappable>& wrappable) {
+  JS::RootedObject global_object(context, JS_GetGlobalForScopeChain(context));
+  DCHECK(global_object);
+
   InterfaceData* interface_data = GetInterfaceData(context);
-  JS::RootedObject prototype(context, GetPrototype(context));
+  JS::RootedObject prototype(context, GetPrototype(context, global_object));
   DCHECK(prototype);
   JS::RootedObject new_object(context, JS_NewObjectWithGivenProto(
       context, &interface_data->instance_class_definition, prototype, NULL));
@@ -371,34 +393,45 @@
   JS::RootedObject proxy(context,
       ProxyHandler::NewProxy(context, new_object, prototype, NULL,
                              proxy_handler.Pointer()));
-  WrapperPrivate::AddPrivateData(proxy, wrappable);
+  WrapperPrivate::AddPrivateData(context, proxy, wrappable);
   return proxy;
 }
 
 //static
 const JSClass* MozjsStringifierAttributeInterface::PrototypeClass(
       JSContext* context) {
-  JS::RootedObject prototype(context, GetPrototype(context));
+  JS::RootedObject global_object(context, JS_GetGlobalForScopeChain(context));
+  DCHECK(global_object);
+
+  JS::RootedObject prototype(context, GetPrototype(context, global_object));
   JSClass* proto_class = JS_GetClass(*prototype.address());
   return proto_class;
 }
 
 // static
-JSObject* MozjsStringifierAttributeInterface::GetPrototype(JSContext* context) {
+JSObject* MozjsStringifierAttributeInterface::GetPrototype(
+    JSContext* context, JS::HandleObject global_object) {
+  DCHECK(JS_IsGlobalObject(global_object));
+
   InterfaceData* interface_data = GetInterfaceData(context);
   if (!interface_data->prototype) {
     // Create new prototype that has all the props and methods
-    InitializePrototypeAndInterfaceObject(interface_data, context);
+    InitializePrototypeAndInterfaceObject(
+        interface_data, context, global_object);
   }
   DCHECK(interface_data->prototype);
   return interface_data->prototype;
 }
 
 // static
-JSObject* MozjsStringifierAttributeInterface::GetInterfaceObject(JSContext* context) {
+JSObject* MozjsStringifierAttributeInterface::GetInterfaceObject(
+    JSContext* context, JS::HandleObject global_object) {
+  DCHECK(JS_IsGlobalObject(global_object));
+
   InterfaceData* interface_data = GetInterfaceData(context);
   if (!interface_data->interface_object) {
-    InitializePrototypeAndInterfaceObject(interface_data, context);
+    InitializePrototypeAndInterfaceObject(
+        interface_data, context, global_object);
   }
   DCHECK(interface_data->interface_object);
   return interface_data->interface_object;
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsStringifierAttributeInterface.h b/src/cobalt/bindings/generated/mozjs/testing/MozjsStringifierAttributeInterface.h
index 813ec74..fcf8292 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsStringifierAttributeInterface.h
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsStringifierAttributeInterface.h
@@ -41,8 +41,10 @@
   static JSObject* CreateProxy(JSContext* context,
       const scoped_refptr<script::Wrappable>& wrappable);
   static const JSClass* PrototypeClass(JSContext* context);
-  static JSObject* GetPrototype(JSContext* context);
-  static JSObject* GetInterfaceObject(JSContext* context);
+  static JSObject* GetPrototype(JSContext* context,
+                                JS::HandleObject global_object);
+  static JSObject* GetInterfaceObject(JSContext* context,
+                                      JS::HandleObject global_object);
 };
 
 }  // namespace bindings
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsStringifierOperationInterface.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsStringifierOperationInterface.cc
index 30a5d06..3a96a4b 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsStringifierOperationInterface.cc
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsStringifierOperationInterface.cc
@@ -114,6 +114,26 @@
 static base::LazyInstance<MozjsStringifierOperationInterfaceHandler>
     proxy_handler;
 
+JSBool HasInstance(JSContext *context, JS::HandleObject type,
+                   JS::MutableHandleValue vp, JSBool *success) {
+  JS::RootedObject global_object(
+      context, JS_GetGlobalForObject(context, type));
+  DCHECK(global_object);
+
+  JS::RootedObject prototype(
+      context, MozjsStringifierOperationInterface::GetPrototype(context, global_object));
+
+  // |IsDelegate| walks the prototype chain of an object returning true if
+  // .prototype is found.
+  bool is_delegate;
+  if (!IsDelegate(context, prototype, vp, &is_delegate)) {
+    *success = false;
+    return false;
+  }
+
+  *success = is_delegate;
+  return true;
+}
 
 InterfaceData* CreateCachedInterfaceData() {
   InterfaceData* interface_data = new InterfaceData();
@@ -162,6 +182,7 @@
   interface_object_class->enumerate = JS_EnumerateStub;
   interface_object_class->resolve = JS_ResolveStub;
   interface_object_class->convert = JS_ConvertStub;
+  interface_object_class->hasInstance = &HasInstance;
   return interface_data;
 }
 
@@ -267,14 +288,12 @@
 };
 
 void InitializePrototypeAndInterfaceObject(
-    InterfaceData* interface_data, JSContext* context) {
+    InterfaceData* interface_data, JSContext* context,
+    JS::HandleObject global_object) {
   DCHECK(!interface_data->prototype);
   DCHECK(!interface_data->interface_object);
+  DCHECK(JS_IsGlobalObject(global_object));
 
-  MozjsGlobalObjectProxy* global_object_proxy =
-      static_cast<MozjsGlobalObjectProxy*>(JS_GetContextPrivate(context));
-  JS::RootedObject global_object(context, global_object_proxy->global_object());
-  DCHECK(global_object);
   JS::RootedObject parent_prototype(
       context, JS_GetObjectPrototype(context, global_object));
   DCHECK(parent_prototype);
@@ -353,8 +372,11 @@
 // static
 JSObject* MozjsStringifierOperationInterface::CreateProxy(
     JSContext* context, const scoped_refptr<Wrappable>& wrappable) {
+  JS::RootedObject global_object(context, JS_GetGlobalForScopeChain(context));
+  DCHECK(global_object);
+
   InterfaceData* interface_data = GetInterfaceData(context);
-  JS::RootedObject prototype(context, GetPrototype(context));
+  JS::RootedObject prototype(context, GetPrototype(context, global_object));
   DCHECK(prototype);
   JS::RootedObject new_object(context, JS_NewObjectWithGivenProto(
       context, &interface_data->instance_class_definition, prototype, NULL));
@@ -362,34 +384,45 @@
   JS::RootedObject proxy(context,
       ProxyHandler::NewProxy(context, new_object, prototype, NULL,
                              proxy_handler.Pointer()));
-  WrapperPrivate::AddPrivateData(proxy, wrappable);
+  WrapperPrivate::AddPrivateData(context, proxy, wrappable);
   return proxy;
 }
 
 //static
 const JSClass* MozjsStringifierOperationInterface::PrototypeClass(
       JSContext* context) {
-  JS::RootedObject prototype(context, GetPrototype(context));
+  JS::RootedObject global_object(context, JS_GetGlobalForScopeChain(context));
+  DCHECK(global_object);
+
+  JS::RootedObject prototype(context, GetPrototype(context, global_object));
   JSClass* proto_class = JS_GetClass(*prototype.address());
   return proto_class;
 }
 
 // static
-JSObject* MozjsStringifierOperationInterface::GetPrototype(JSContext* context) {
+JSObject* MozjsStringifierOperationInterface::GetPrototype(
+    JSContext* context, JS::HandleObject global_object) {
+  DCHECK(JS_IsGlobalObject(global_object));
+
   InterfaceData* interface_data = GetInterfaceData(context);
   if (!interface_data->prototype) {
     // Create new prototype that has all the props and methods
-    InitializePrototypeAndInterfaceObject(interface_data, context);
+    InitializePrototypeAndInterfaceObject(
+        interface_data, context, global_object);
   }
   DCHECK(interface_data->prototype);
   return interface_data->prototype;
 }
 
 // static
-JSObject* MozjsStringifierOperationInterface::GetInterfaceObject(JSContext* context) {
+JSObject* MozjsStringifierOperationInterface::GetInterfaceObject(
+    JSContext* context, JS::HandleObject global_object) {
+  DCHECK(JS_IsGlobalObject(global_object));
+
   InterfaceData* interface_data = GetInterfaceData(context);
   if (!interface_data->interface_object) {
-    InitializePrototypeAndInterfaceObject(interface_data, context);
+    InitializePrototypeAndInterfaceObject(
+        interface_data, context, global_object);
   }
   DCHECK(interface_data->interface_object);
   return interface_data->interface_object;
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsStringifierOperationInterface.h b/src/cobalt/bindings/generated/mozjs/testing/MozjsStringifierOperationInterface.h
index 135e07a..a5f76d1 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsStringifierOperationInterface.h
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsStringifierOperationInterface.h
@@ -41,8 +41,10 @@
   static JSObject* CreateProxy(JSContext* context,
       const scoped_refptr<script::Wrappable>& wrappable);
   static const JSClass* PrototypeClass(JSContext* context);
-  static JSObject* GetPrototype(JSContext* context);
-  static JSObject* GetInterfaceObject(JSContext* context);
+  static JSObject* GetPrototype(JSContext* context,
+                                JS::HandleObject global_object);
+  static JSObject* GetInterfaceObject(JSContext* context,
+                                      JS::HandleObject global_object);
 };
 
 }  // namespace bindings
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsTargetInterface.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsTargetInterface.cc
index b7d73d0..49786d1 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsTargetInterface.cc
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsTargetInterface.cc
@@ -114,6 +114,26 @@
 static base::LazyInstance<MozjsTargetInterfaceHandler>
     proxy_handler;
 
+JSBool HasInstance(JSContext *context, JS::HandleObject type,
+                   JS::MutableHandleValue vp, JSBool *success) {
+  JS::RootedObject global_object(
+      context, JS_GetGlobalForObject(context, type));
+  DCHECK(global_object);
+
+  JS::RootedObject prototype(
+      context, MozjsTargetInterface::GetPrototype(context, global_object));
+
+  // |IsDelegate| walks the prototype chain of an object returning true if
+  // .prototype is found.
+  bool is_delegate;
+  if (!IsDelegate(context, prototype, vp, &is_delegate)) {
+    *success = false;
+    return false;
+  }
+
+  *success = is_delegate;
+  return true;
+}
 
 InterfaceData* CreateCachedInterfaceData() {
   InterfaceData* interface_data = new InterfaceData();
@@ -162,6 +182,7 @@
   interface_object_class->enumerate = JS_EnumerateStub;
   interface_object_class->resolve = JS_ResolveStub;
   interface_object_class->convert = JS_ConvertStub;
+  interface_object_class->hasInstance = &HasInstance;
   return interface_data;
 }
 
@@ -257,14 +278,12 @@
 };
 
 void InitializePrototypeAndInterfaceObject(
-    InterfaceData* interface_data, JSContext* context) {
+    InterfaceData* interface_data, JSContext* context,
+    JS::HandleObject global_object) {
   DCHECK(!interface_data->prototype);
   DCHECK(!interface_data->interface_object);
+  DCHECK(JS_IsGlobalObject(global_object));
 
-  MozjsGlobalObjectProxy* global_object_proxy =
-      static_cast<MozjsGlobalObjectProxy*>(JS_GetContextPrivate(context));
-  JS::RootedObject global_object(context, global_object_proxy->global_object());
-  DCHECK(global_object);
   JS::RootedObject parent_prototype(
       context, JS_GetObjectPrototype(context, global_object));
   DCHECK(parent_prototype);
@@ -343,8 +362,11 @@
 // static
 JSObject* MozjsTargetInterface::CreateProxy(
     JSContext* context, const scoped_refptr<Wrappable>& wrappable) {
+  JS::RootedObject global_object(context, JS_GetGlobalForScopeChain(context));
+  DCHECK(global_object);
+
   InterfaceData* interface_data = GetInterfaceData(context);
-  JS::RootedObject prototype(context, GetPrototype(context));
+  JS::RootedObject prototype(context, GetPrototype(context, global_object));
   DCHECK(prototype);
   JS::RootedObject new_object(context, JS_NewObjectWithGivenProto(
       context, &interface_data->instance_class_definition, prototype, NULL));
@@ -352,34 +374,45 @@
   JS::RootedObject proxy(context,
       ProxyHandler::NewProxy(context, new_object, prototype, NULL,
                              proxy_handler.Pointer()));
-  WrapperPrivate::AddPrivateData(proxy, wrappable);
+  WrapperPrivate::AddPrivateData(context, proxy, wrappable);
   return proxy;
 }
 
 //static
 const JSClass* MozjsTargetInterface::PrototypeClass(
       JSContext* context) {
-  JS::RootedObject prototype(context, GetPrototype(context));
+  JS::RootedObject global_object(context, JS_GetGlobalForScopeChain(context));
+  DCHECK(global_object);
+
+  JS::RootedObject prototype(context, GetPrototype(context, global_object));
   JSClass* proto_class = JS_GetClass(*prototype.address());
   return proto_class;
 }
 
 // static
-JSObject* MozjsTargetInterface::GetPrototype(JSContext* context) {
+JSObject* MozjsTargetInterface::GetPrototype(
+    JSContext* context, JS::HandleObject global_object) {
+  DCHECK(JS_IsGlobalObject(global_object));
+
   InterfaceData* interface_data = GetInterfaceData(context);
   if (!interface_data->prototype) {
     // Create new prototype that has all the props and methods
-    InitializePrototypeAndInterfaceObject(interface_data, context);
+    InitializePrototypeAndInterfaceObject(
+        interface_data, context, global_object);
   }
   DCHECK(interface_data->prototype);
   return interface_data->prototype;
 }
 
 // static
-JSObject* MozjsTargetInterface::GetInterfaceObject(JSContext* context) {
+JSObject* MozjsTargetInterface::GetInterfaceObject(
+    JSContext* context, JS::HandleObject global_object) {
+  DCHECK(JS_IsGlobalObject(global_object));
+
   InterfaceData* interface_data = GetInterfaceData(context);
   if (!interface_data->interface_object) {
-    InitializePrototypeAndInterfaceObject(interface_data, context);
+    InitializePrototypeAndInterfaceObject(
+        interface_data, context, global_object);
   }
   DCHECK(interface_data->interface_object);
   return interface_data->interface_object;
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsTargetInterface.h b/src/cobalt/bindings/generated/mozjs/testing/MozjsTargetInterface.h
index 71f1e20..34254e0 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsTargetInterface.h
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsTargetInterface.h
@@ -41,8 +41,10 @@
   static JSObject* CreateProxy(JSContext* context,
       const scoped_refptr<script::Wrappable>& wrappable);
   static const JSClass* PrototypeClass(JSContext* context);
-  static JSObject* GetPrototype(JSContext* context);
-  static JSObject* GetInterfaceObject(JSContext* context);
+  static JSObject* GetPrototype(JSContext* context,
+                                JS::HandleObject global_object);
+  static JSObject* GetInterfaceObject(JSContext* context,
+                                      JS::HandleObject global_object);
 };
 
 }  // namespace bindings
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsUnionTypesInterface.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsUnionTypesInterface.cc
index 8d181ac..bc19f25 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsUnionTypesInterface.cc
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsUnionTypesInterface.cc
@@ -122,6 +122,26 @@
 static base::LazyInstance<MozjsUnionTypesInterfaceHandler>
     proxy_handler;
 
+JSBool HasInstance(JSContext *context, JS::HandleObject type,
+                   JS::MutableHandleValue vp, JSBool *success) {
+  JS::RootedObject global_object(
+      context, JS_GetGlobalForObject(context, type));
+  DCHECK(global_object);
+
+  JS::RootedObject prototype(
+      context, MozjsUnionTypesInterface::GetPrototype(context, global_object));
+
+  // |IsDelegate| walks the prototype chain of an object returning true if
+  // .prototype is found.
+  bool is_delegate;
+  if (!IsDelegate(context, prototype, vp, &is_delegate)) {
+    *success = false;
+    return false;
+  }
+
+  *success = is_delegate;
+  return true;
+}
 
 InterfaceData* CreateCachedInterfaceData() {
   InterfaceData* interface_data = new InterfaceData();
@@ -170,6 +190,7 @@
   interface_object_class->enumerate = JS_EnumerateStub;
   interface_object_class->resolve = JS_ResolveStub;
   interface_object_class->convert = JS_ConvertStub;
+  interface_object_class->hasInstance = &HasInstance;
   return interface_data;
 }
 
@@ -395,14 +416,12 @@
 };
 
 void InitializePrototypeAndInterfaceObject(
-    InterfaceData* interface_data, JSContext* context) {
+    InterfaceData* interface_data, JSContext* context,
+    JS::HandleObject global_object) {
   DCHECK(!interface_data->prototype);
   DCHECK(!interface_data->interface_object);
+  DCHECK(JS_IsGlobalObject(global_object));
 
-  MozjsGlobalObjectProxy* global_object_proxy =
-      static_cast<MozjsGlobalObjectProxy*>(JS_GetContextPrivate(context));
-  JS::RootedObject global_object(context, global_object_proxy->global_object());
-  DCHECK(global_object);
   JS::RootedObject parent_prototype(
       context, JS_GetObjectPrototype(context, global_object));
   DCHECK(parent_prototype);
@@ -481,8 +500,11 @@
 // static
 JSObject* MozjsUnionTypesInterface::CreateProxy(
     JSContext* context, const scoped_refptr<Wrappable>& wrappable) {
+  JS::RootedObject global_object(context, JS_GetGlobalForScopeChain(context));
+  DCHECK(global_object);
+
   InterfaceData* interface_data = GetInterfaceData(context);
-  JS::RootedObject prototype(context, GetPrototype(context));
+  JS::RootedObject prototype(context, GetPrototype(context, global_object));
   DCHECK(prototype);
   JS::RootedObject new_object(context, JS_NewObjectWithGivenProto(
       context, &interface_data->instance_class_definition, prototype, NULL));
@@ -490,34 +512,45 @@
   JS::RootedObject proxy(context,
       ProxyHandler::NewProxy(context, new_object, prototype, NULL,
                              proxy_handler.Pointer()));
-  WrapperPrivate::AddPrivateData(proxy, wrappable);
+  WrapperPrivate::AddPrivateData(context, proxy, wrappable);
   return proxy;
 }
 
 //static
 const JSClass* MozjsUnionTypesInterface::PrototypeClass(
       JSContext* context) {
-  JS::RootedObject prototype(context, GetPrototype(context));
+  JS::RootedObject global_object(context, JS_GetGlobalForScopeChain(context));
+  DCHECK(global_object);
+
+  JS::RootedObject prototype(context, GetPrototype(context, global_object));
   JSClass* proto_class = JS_GetClass(*prototype.address());
   return proto_class;
 }
 
 // static
-JSObject* MozjsUnionTypesInterface::GetPrototype(JSContext* context) {
+JSObject* MozjsUnionTypesInterface::GetPrototype(
+    JSContext* context, JS::HandleObject global_object) {
+  DCHECK(JS_IsGlobalObject(global_object));
+
   InterfaceData* interface_data = GetInterfaceData(context);
   if (!interface_data->prototype) {
     // Create new prototype that has all the props and methods
-    InitializePrototypeAndInterfaceObject(interface_data, context);
+    InitializePrototypeAndInterfaceObject(
+        interface_data, context, global_object);
   }
   DCHECK(interface_data->prototype);
   return interface_data->prototype;
 }
 
 // static
-JSObject* MozjsUnionTypesInterface::GetInterfaceObject(JSContext* context) {
+JSObject* MozjsUnionTypesInterface::GetInterfaceObject(
+    JSContext* context, JS::HandleObject global_object) {
+  DCHECK(JS_IsGlobalObject(global_object));
+
   InterfaceData* interface_data = GetInterfaceData(context);
   if (!interface_data->interface_object) {
-    InitializePrototypeAndInterfaceObject(interface_data, context);
+    InitializePrototypeAndInterfaceObject(
+        interface_data, context, global_object);
   }
   DCHECK(interface_data->interface_object);
   return interface_data->interface_object;
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsUnionTypesInterface.h b/src/cobalt/bindings/generated/mozjs/testing/MozjsUnionTypesInterface.h
index eba6b2f..7de2382 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsUnionTypesInterface.h
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsUnionTypesInterface.h
@@ -41,8 +41,10 @@
   static JSObject* CreateProxy(JSContext* context,
       const scoped_refptr<script::Wrappable>& wrappable);
   static const JSClass* PrototypeClass(JSContext* context);
-  static JSObject* GetPrototype(JSContext* context);
-  static JSObject* GetInterfaceObject(JSContext* context);
+  static JSObject* GetPrototype(JSContext* context,
+                                JS::HandleObject global_object);
+  static JSObject* GetInterfaceObject(JSContext* context,
+                                      JS::HandleObject global_object);
 };
 
 }  // namespace bindings
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsWindow.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsWindow.cc
index b626b88..f52bcf2 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsWindow.cc
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsWindow.cc
@@ -298,6 +298,26 @@
 static base::LazyInstance<MozjsWindowHandler>
     proxy_handler;
 
+JSBool HasInstance(JSContext *context, JS::HandleObject type,
+                   JS::MutableHandleValue vp, JSBool *success) {
+  JS::RootedObject global_object(
+      context, JS_GetGlobalForObject(context, type));
+  DCHECK(global_object);
+
+  JS::RootedObject prototype(
+      context, MozjsWindow::GetPrototype(context, global_object));
+
+  // |IsDelegate| walks the prototype chain of an object returning true if
+  // .prototype is found.
+  bool is_delegate;
+  if (!IsDelegate(context, prototype, vp, &is_delegate)) {
+    *success = false;
+    return false;
+  }
+
+  *success = is_delegate;
+  return true;
+}
 
 InterfaceData* CreateCachedInterfaceData() {
   InterfaceData* interface_data = new InterfaceData();
@@ -346,6 +366,7 @@
   interface_object_class->enumerate = JS_EnumerateStub;
   interface_object_class->resolve = JS_ResolveStub;
   interface_object_class->convert = JS_ConvertStub;
+  interface_object_class->hasInstance = &HasInstance;
   return interface_data;
 }
 
@@ -393,6 +414,64 @@
   return !exception_state.is_exception_set();
 }
 
+JSBool get_window(
+    JSContext* context, JS::HandleObject object, JS::HandleId id,
+    JS::MutableHandleValue vp) {
+  MozjsExceptionState exception_state(context);
+  JS::RootedValue result_value(context);
+
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
+  Window* impl =
+      wrapper_private->wrappable<Window>().get();
+
+  if (!exception_state.is_exception_set()) {
+    ToJSValue(context,
+              impl->window(),
+              &result_value);
+  }
+  if (!exception_state.is_exception_set()) {
+    vp.set(result_value);
+  }
+  return !exception_state.is_exception_set();
+}
+
+JSBool fcn_getStackTrace(
+    JSContext* context, uint32_t argc, JS::Value *vp) {
+  JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+  // Compute the 'this' value.
+  JS::RootedValue this_value(context, JS_ComputeThis(context, vp));
+  // 'this' should be an object.
+  JS::RootedObject object(context);
+  if (JS_TypeOfValue(context, this_value) != JSTYPE_OBJECT) {
+    NOTREACHED();
+    return false;
+  }
+  if (!JS_ValueToObject(context, this_value, object.address())) {
+    NOTREACHED();
+    return false;
+  }
+  MozjsExceptionState exception_state(context);
+  JS::RootedValue result_value(context);
+
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
+  Window* impl =
+      wrapper_private->wrappable<Window>().get();
+  MozjsGlobalObjectProxy* global_object_proxy =
+      static_cast<MozjsGlobalObjectProxy*>(JS_GetContextPrivate(context));
+
+  if (!exception_state.is_exception_set()) {
+    ToJSValue(context,
+              impl->GetStackTrace(global_object_proxy->GetStackTrace()),
+              &result_value);
+  }
+  if (!exception_state.is_exception_set()) {
+    args.rval().set(result_value);
+  }
+  return !exception_state.is_exception_set();
+}
+
 JSBool fcn_windowOperation(
     JSContext* context, uint32_t argc, JS::Value *vp) {
   JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
@@ -429,11 +508,24 @@
       JSOP_WRAPPER(&get_windowProperty),
       JSOP_WRAPPER(&set_windowProperty),
   },
+  {  // Readonly attribute
+      "window", 0,
+      JSPROP_SHARED | JSPROP_ENUMERATE | JSPROP_READONLY,
+      JSOP_WRAPPER(&get_window),
+      JSOP_NULLWRAPPER,
+  },
   JS_PS_END
 };
 
 const JSFunctionSpec prototype_functions[] = {
   {
+      "getStackTrace",
+      JSOP_WRAPPER(&fcn_getStackTrace),
+      0,
+      JSPROP_ENUMERATE,
+      NULL,
+  },
+  {
       "windowOperation",
       JSOP_WRAPPER(&fcn_windowOperation),
       0,
@@ -456,16 +548,14 @@
 };
 
 void InitializePrototypeAndInterfaceObject(
-    InterfaceData* interface_data, JSContext* context) {
+    InterfaceData* interface_data, JSContext* context,
+    JS::HandleObject global_object) {
   DCHECK(!interface_data->prototype);
   DCHECK(!interface_data->interface_object);
+  DCHECK(JS_IsGlobalObject(global_object));
 
-  MozjsGlobalObjectProxy* global_object_proxy =
-      static_cast<MozjsGlobalObjectProxy*>(JS_GetContextPrivate(context));
-  JS::RootedObject global_object(context, global_object_proxy->global_object());
-  DCHECK(global_object);
   JS::RootedObject parent_prototype(
-      context, bindings::testing::MozjsGlobalInterfaceParent::GetPrototype(context));
+      context, bindings::testing::MozjsGlobalInterfaceParent::GetPrototype(context, global_object));
   DCHECK(parent_prototype);
 
   // Create the Prototype object.
@@ -556,13 +646,8 @@
   JS::RootedObject parent_prototype(
       context, JS_GetObjectPrototype(context, global_object));
 
-  // Set the global object pointer, so we can access the standard classes such
-  // as the base Object prototype when looking up our prototype.
-  MozjsGlobalObjectProxy* global_object_proxy =
-      static_cast<MozjsGlobalObjectProxy*>(JS_GetContextPrivate(context));
-  global_object_proxy->SetGlobalObject(global_object);
-
-  JS::RootedObject prototype(context, MozjsWindow::GetPrototype(context));
+  JS::RootedObject prototype(
+      context, MozjsWindow::GetPrototype(context, global_object));
   DCHECK(prototype);
   JS_SetPrototype(context, global_object, prototype);
 
@@ -573,34 +658,51 @@
   JS::RootedObject proxy(context,
       ProxyHandler::NewProxy(context, global_object, prototype, NULL,
                              proxy_handler.Pointer()));
-  WrapperPrivate::AddPrivateData(proxy, wrappable);
+  WrapperPrivate::AddPrivateData(context, proxy, wrappable);
+
+  // Set the global object proxy pointer, so we can access the standard classes
+  // such as the base Object prototype when looking up our prototype.
+  MozjsGlobalObjectProxy* global_object_proxy =
+      static_cast<MozjsGlobalObjectProxy*>(JS_GetContextPrivate(context));
+  global_object_proxy->SetGlobalObjectProxyAndWrapper(proxy, wrappable);
   return proxy;
 }
 
 //static
 const JSClass* MozjsWindow::PrototypeClass(
       JSContext* context) {
-  JS::RootedObject prototype(context, GetPrototype(context));
+  JS::RootedObject global_object(context, JS_GetGlobalForScopeChain(context));
+  DCHECK(global_object);
+
+  JS::RootedObject prototype(context, GetPrototype(context, global_object));
   JSClass* proto_class = JS_GetClass(*prototype.address());
   return proto_class;
 }
 
 // static
-JSObject* MozjsWindow::GetPrototype(JSContext* context) {
+JSObject* MozjsWindow::GetPrototype(
+    JSContext* context, JS::HandleObject global_object) {
+  DCHECK(JS_IsGlobalObject(global_object));
+
   InterfaceData* interface_data = GetInterfaceData(context);
   if (!interface_data->prototype) {
     // Create new prototype that has all the props and methods
-    InitializePrototypeAndInterfaceObject(interface_data, context);
+    InitializePrototypeAndInterfaceObject(
+        interface_data, context, global_object);
   }
   DCHECK(interface_data->prototype);
   return interface_data->prototype;
 }
 
 // static
-JSObject* MozjsWindow::GetInterfaceObject(JSContext* context) {
+JSObject* MozjsWindow::GetInterfaceObject(
+    JSContext* context, JS::HandleObject global_object) {
+  DCHECK(JS_IsGlobalObject(global_object));
+
   InterfaceData* interface_data = GetInterfaceData(context);
   if (!interface_data->interface_object) {
-    InitializePrototypeAndInterfaceObject(interface_data, context);
+    InitializePrototypeAndInterfaceObject(
+        interface_data, context, global_object);
   }
   DCHECK(interface_data->interface_object);
   return interface_data->interface_object;
@@ -629,7 +731,8 @@
       context, global_interface);
   mozjs_global_object_proxy->SetEnvironmentSettings(environment_settings);
 
-  WrapperFactory* wrapper_factory = mozjs_global_object_proxy->wrapper_factory();
+  WrapperFactory* wrapper_factory =
+      mozjs_global_object_proxy->wrapper_factory();
   wrapper_factory->RegisterWrappableType(
       AnonymousIndexedGetterInterface::AnonymousIndexedGetterInterfaceWrappableType(),
       base::Bind(MozjsAnonymousIndexedGetterInterface::CreateProxy),
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsWindow.h b/src/cobalt/bindings/generated/mozjs/testing/MozjsWindow.h
index c7e508c..50db9dd 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsWindow.h
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsWindow.h
@@ -42,8 +42,10 @@
   static JSObject* CreateProxy(JSContext* context,
       const scoped_refptr<script::Wrappable>& wrappable);
   static const JSClass* PrototypeClass(JSContext* context);
-  static JSObject* GetPrototype(JSContext* context);
-  static JSObject* GetInterfaceObject(JSContext* context);
+  static JSObject* GetPrototype(JSContext* context,
+                                JS::HandleObject global_object);
+  static JSObject* GetInterfaceObject(JSContext* context,
+                                      JS::HandleObject global_object);
 };
 
 }  // namespace bindings
diff --git a/src/cobalt/bindings/mozjs/templates/interface.cc.template b/src/cobalt/bindings/mozjs/templates/interface.cc.template
index ad65ba4..16134d5 100644
--- a/src/cobalt/bindings/mozjs/templates/interface.cc.template
+++ b/src/cobalt/bindings/mozjs/templates/interface.cc.template
@@ -41,6 +41,9 @@
 #include "cobalt/script/mozjs/wrapper_private.h"
 #include "cobalt/script/property_enumerator.h"
 #include "third_party/mozjs/js/src/jsapi.h"
+{% if is_exception_interface %}
+#include "third_party/mozjs/js/src/jsexn.h"
+{% endif %}
 #include "third_party/mozjs/js/src/jsfriendapi.h"
 {% endblock includes %}
 {% block using_directives %}
@@ -317,6 +320,26 @@
 }
 
 {% endfor %}
+JSBool HasInstance(JSContext *context, JS::HandleObject type,
+                   JS::MutableHandleValue vp, JSBool *success) {
+  JS::RootedObject global_object(
+      context, JS_GetGlobalForObject(context, type));
+  DCHECK(global_object);
+
+  JS::RootedObject prototype(
+      context, {{binding_class}}::GetPrototype(context, global_object));
+
+  // |IsDelegate| walks the prototype chain of an object returning true if
+  // .prototype is found.
+  bool is_delegate;
+  if (!IsDelegate(context, prototype, vp, &is_delegate)) {
+    *success = false;
+    return false;
+  }
+
+  *success = is_delegate;
+  return true;
+}
 
 InterfaceData* CreateCachedInterfaceData() {
   InterfaceData* interface_data = new InterfaceData();
@@ -366,6 +389,7 @@
   interface_object_class->enumerate = JS_EnumerateStub;
   interface_object_class->resolve = JS_ResolveStub;
   interface_object_class->convert = JS_ConvertStub;
+  interface_object_class->hasInstance = &HasInstance;
 {% if constructor %}
   interface_object_class->construct = Constructor;
 {% endif %}
@@ -380,8 +404,13 @@
 JSBool get_{{attribute.idl_name}}(
     JSContext* context, JS::HandleObject object, JS::HandleId id,
     JS::MutableHandleValue vp) {
+  JS::RootedObject global_object(
+      context, JS_GetGlobalForObject(context, object));
+  DCHECK(global_object);
+
   JS::RootedObject interface_object(context,
-      Mozjs{{attribute.interface_name}}::GetInterfaceObject(context));
+      Mozjs{{attribute.interface_name}}::GetInterfaceObject(
+          context, global_object));
   vp.set(JS::ObjectValue(*interface_object));
   return true;
 }
@@ -626,27 +655,34 @@
 };
 
 void InitializePrototypeAndInterfaceObject(
-    InterfaceData* interface_data, JSContext* context) {
+    InterfaceData* interface_data, JSContext* context,
+    JS::HandleObject global_object) {
   DCHECK(!interface_data->prototype);
   DCHECK(!interface_data->interface_object);
+  DCHECK(JS_IsGlobalObject(global_object));
 
-  MozjsGlobalObjectProxy* global_object_proxy =
-      static_cast<MozjsGlobalObjectProxy*>(JS_GetContextPrivate(context));
-  JS::RootedObject global_object(context, global_object_proxy->global_object());
-  DCHECK(global_object);
   {% if parent_interface %}
   JS::RootedObject parent_prototype(
-      context, {{parent_interface}}::GetPrototype(context));
+      context, {{parent_interface}}::GetPrototype(context, global_object));
   {% else %}
   JS::RootedObject parent_prototype(
       context, JS_GetObjectPrototype(context, global_object));
   {% endif %}
   DCHECK(parent_prototype);
 
+{% if is_exception_interface %}
+  JS::RootedObject prototype(context);
+  // Get Error prototype.
+  bool success_check = js_GetClassPrototype(
+      context, GetExceptionProtoKey(JSEXN_ERR), &prototype);
+  DCHECK(success_check);
+  interface_data->prototype = prototype;
+{% else %}
   // Create the Prototype object.
   interface_data->prototype = JS_NewObjectWithGivenProto(
       context, &interface_data->prototype_class_definition, parent_prototype,
       NULL);
+{% endif %}
   bool success = JS_DefineProperties(
       context, interface_data->prototype, prototype_properties);
   DCHECK(success);
@@ -746,13 +782,8 @@
   JS::RootedObject parent_prototype(
       context, JS_GetObjectPrototype(context, global_object));
 
-  // Set the global object pointer, so we can access the standard classes such
-  // as the base Object prototype when looking up our prototype.
-  MozjsGlobalObjectProxy* global_object_proxy =
-      static_cast<MozjsGlobalObjectProxy*>(JS_GetContextPrivate(context));
-  global_object_proxy->SetGlobalObject(global_object);
-
-  JS::RootedObject prototype(context, {{binding_class}}::GetPrototype(context));
+  JS::RootedObject prototype(
+      context, {{binding_class}}::GetPrototype(context, global_object));
   DCHECK(prototype);
   JS_SetPrototype(context, global_object, prototype);
 
@@ -763,7 +794,13 @@
   JS::RootedObject proxy(context,
       ProxyHandler::NewProxy(context, global_object, prototype, NULL,
                              proxy_handler.Pointer()));
-  WrapperPrivate::AddPrivateData(proxy, wrappable);
+  WrapperPrivate::AddPrivateData(context, proxy, wrappable);
+
+  // Set the global object proxy pointer, so we can access the standard classes
+  // such as the base Object prototype when looking up our prototype.
+  MozjsGlobalObjectProxy* global_object_proxy =
+      static_cast<MozjsGlobalObjectProxy*>(JS_GetContextPrivate(context));
+  global_object_proxy->SetGlobalObjectProxyAndWrapper(proxy, wrappable);
   return proxy;
 }
 
@@ -771,8 +808,11 @@
 // static
 JSObject* {{binding_class}}::CreateProxy(
     JSContext* context, const scoped_refptr<Wrappable>& wrappable) {
+  JS::RootedObject global_object(context, JS_GetGlobalForScopeChain(context));
+  DCHECK(global_object);
+
   InterfaceData* interface_data = GetInterfaceData(context);
-  JS::RootedObject prototype(context, GetPrototype(context));
+  JS::RootedObject prototype(context, GetPrototype(context, global_object));
   DCHECK(prototype);
   JS::RootedObject new_object(context, JS_NewObjectWithGivenProto(
       context, &interface_data->instance_class_definition, prototype, NULL));
@@ -780,7 +820,7 @@
   JS::RootedObject proxy(context,
       ProxyHandler::NewProxy(context, new_object, prototype, NULL,
                              proxy_handler.Pointer()));
-  WrapperPrivate::AddPrivateData(proxy, wrappable);
+  WrapperPrivate::AddPrivateData(context, proxy, wrappable);
   return proxy;
 }
 
@@ -788,17 +828,24 @@
 //static
 const JSClass* {{binding_class}}::PrototypeClass(
       JSContext* context) {
-  JS::RootedObject prototype(context, GetPrototype(context));
+  JS::RootedObject global_object(context, JS_GetGlobalForScopeChain(context));
+  DCHECK(global_object);
+
+  JS::RootedObject prototype(context, GetPrototype(context, global_object));
   JSClass* proto_class = JS_GetClass(*prototype.address());
   return proto_class;
 }
 
 // static
-JSObject* {{binding_class}}::GetPrototype(JSContext* context) {
+JSObject* {{binding_class}}::GetPrototype(
+    JSContext* context, JS::HandleObject global_object) {
+  DCHECK(JS_IsGlobalObject(global_object));
+
   InterfaceData* interface_data = GetInterfaceData(context);
   if (!interface_data->prototype) {
     // Create new prototype that has all the props and methods
-    InitializePrototypeAndInterfaceObject(interface_data, context);
+    InitializePrototypeAndInterfaceObject(
+        interface_data, context, global_object);
   }
   DCHECK(interface_data->prototype);
   return interface_data->prototype;
@@ -806,10 +853,14 @@
 
 {% if has_interface_object %}
 // static
-JSObject* {{binding_class}}::GetInterfaceObject(JSContext* context) {
+JSObject* {{binding_class}}::GetInterfaceObject(
+    JSContext* context, JS::HandleObject global_object) {
+  DCHECK(JS_IsGlobalObject(global_object));
+
   InterfaceData* interface_data = GetInterfaceData(context);
   if (!interface_data->interface_object) {
-    InitializePrototypeAndInterfaceObject(interface_data, context);
+    InitializePrototypeAndInterfaceObject(
+        interface_data, context, global_object);
   }
   DCHECK(interface_data->interface_object);
   return interface_data->interface_object;
@@ -847,7 +898,8 @@
       context, global_interface);
   mozjs_global_object_proxy->SetEnvironmentSettings(environment_settings);
 
-  WrapperFactory* wrapper_factory = mozjs_global_object_proxy->wrapper_factory();
+  WrapperFactory* wrapper_factory =
+      mozjs_global_object_proxy->wrapper_factory();
 {% for interface in all_interfaces %}
 {% if interface.conditional %}
 #if defined({{interface.conditional}})
diff --git a/src/cobalt/bindings/mozjs/templates/interface.h.template b/src/cobalt/bindings/mozjs/templates/interface.h.template
index f7ca8b6..fbef85c 100644
--- a/src/cobalt/bindings/mozjs/templates/interface.h.template
+++ b/src/cobalt/bindings/mozjs/templates/interface.h.template
@@ -24,9 +24,11 @@
   static JSObject* CreateProxy(JSContext* context,
       const scoped_refptr<script::Wrappable>& wrappable);
   static const JSClass* PrototypeClass(JSContext* context);
-  static JSObject* GetPrototype(JSContext* context);
+  static JSObject* GetPrototype(JSContext* context,
+                                JS::HandleObject global_object);
 {% if has_interface_object %}
-  static JSObject* GetInterfaceObject(JSContext* context);
+  static JSObject* GetInterfaceObject(JSContext* context,
+                                      JS::HandleObject global_object);
 {% endif %}
 };
 {% endblock implementation %}
diff --git a/src/cobalt/bindings/mozjs/templates/macros.cc.template b/src/cobalt/bindings/mozjs/templates/macros.cc.template
index 36770e2..dd3bdca 100644
--- a/src/cobalt/bindings/mozjs/templates/macros.cc.template
+++ b/src/cobalt/bindings/mozjs/templates/macros.cc.template
@@ -336,6 +336,12 @@
                        constructor.call_with) }}
   scoped_refptr<{{impl_class}}> new_object =
       new {{impl_class}}({{arguments_list|join(', ')}});
+{% if constructor.raises_exception %}
+  // In case that an exception is thrown from constructor.
+  if (exception_state.is_exception_set()) {
+    return false;
+  }
+{% endif %}
   JS::RootedValue result_value(context);
   ToJSValue(context, new_object, &result_value);
   DCHECK(result_value.isObject());
diff --git a/src/cobalt/bindings/testing/Window.idl b/src/cobalt/bindings/testing/Window.idl
index 9967ccf..161266f 100644
--- a/src/cobalt/bindings/testing/Window.idl
+++ b/src/cobalt/bindings/testing/Window.idl
@@ -17,4 +17,6 @@
 interface Window : GlobalInterfaceParent {
   void windowOperation();
   attribute DOMString windowProperty;
+  readonly attribute Window window;
+  [CallWith=StackTrace] DOMString getStackTrace();
 };
diff --git a/src/cobalt/bindings/testing/exceptions_bindings_test.cc b/src/cobalt/bindings/testing/exceptions_bindings_test.cc
index 0010125..13d6d0e 100644
--- a/src/cobalt/bindings/testing/exceptions_bindings_test.cc
+++ b/src/cobalt/bindings/testing/exceptions_bindings_test.cc
@@ -24,7 +24,7 @@
 using ::testing::InSequence;
 using ::testing::Invoke;
 using ::testing::Return;
-using ::testing::StrictMock;
+using ::testing::NiceMock;
 using ::testing::WithArg;
 
 #define EXPECT_SUBSTRING(needle, haystack) \
@@ -54,8 +54,7 @@
  public:
   explicit ExceptionObjectSetter(
       const scoped_refptr<ExceptionObjectInterface>& exception)
-      : exception_object_(
-            make_scoped_refptr<script::ScriptException>(exception.get())) {}
+      : exception_object_(exception) {}
   void FireException(script::ExceptionState* exception) {
     exception->SetException(exception_object_);
   }
@@ -117,13 +116,12 @@
 
 TEST_F(ExceptionsBindingsTest, ThrowExceptionObject) {
   scoped_refptr<ExceptionObjectInterface> exception_object =
-      make_scoped_refptr(new StrictMock<ExceptionObjectInterface>());
+      make_scoped_refptr(new NiceMock<ExceptionObjectInterface>());
   ExceptionObjectSetter exception_setter(exception_object);
 
   InSequence in_sequence_dummy;
   EXPECT_CALL(test_mock(), FunctionThrowsException(_)).WillOnce(
       Invoke(&exception_setter, &ExceptionObjectSetter::FireException));
-  EXPECT_CALL(*exception_object, message()).WillOnce(Return("the message"));
   EXPECT_TRUE(EvaluateScript(
       "var error = null;"
       "try { test.functionThrowsException(); }"
diff --git a/src/cobalt/bindings/testing/global_interface_bindings_test.cc b/src/cobalt/bindings/testing/global_interface_bindings_test.cc
index 175426e..5f8b90c 100644
--- a/src/cobalt/bindings/testing/global_interface_bindings_test.cc
+++ b/src/cobalt/bindings/testing/global_interface_bindings_test.cc
@@ -37,6 +37,10 @@
 };
 }  // namespace
 
+TEST_F(GlobalInterfaceBindingsTest, GlobalWindowIsThis) {
+  EXPECT_TRUE(EvaluateScript("window === this;", NULL));
+}
+
 TEST_F(GlobalInterfaceBindingsTest, GlobalOperation) {
   EXPECT_CALL(test_mock(), WindowOperation());
   EXPECT_TRUE(EvaluateScript("windowOperation();", NULL));
diff --git a/src/cobalt/bindings/testing/stack_trace_test.cc b/src/cobalt/bindings/testing/stack_trace_test.cc
new file mode 100644
index 0000000..c9e39a8
--- /dev/null
+++ b/src/cobalt/bindings/testing/stack_trace_test.cc
@@ -0,0 +1,69 @@
+/*
+ * 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 "cobalt/bindings/testing/bindings_test_base.h"
+
+namespace cobalt {
+namespace bindings {
+namespace testing {
+
+namespace {
+class StackTraceTest : public BindingsTestBase {};
+}  // namespace
+
+TEST_F(StackTraceTest, GetStackTrace) {
+  std::string result;
+
+  // We expect the to be in bar (line 2), called from foo (line 6),
+  // called from foo (line 8) 4 times, called outside of a function (line
+  // 11).
+  std::string script =
+      "function bar() {\n"
+      "return getStackTrace();\n"
+      "}\n"
+      "function foo(depth) {\n"
+      "  if  (depth <= 0) {\n"
+      "    return bar();\n"
+      "  } else {\n"
+      "    return foo(depth - 1);\n"
+      "  }\n"
+      "}\n"
+      "foo(4)";
+  EXPECT_TRUE(EvaluateScript(script, &result));
+
+  // Expect that bar is on top.
+  std::string match_line = "bar @ [object BindingsTestBase]:2\n";
+  size_t position = result.find(match_line);
+  EXPECT_TRUE(position != std::string::npos);
+  // Expect a foo at line 6.
+  match_line = "foo @ [object BindingsTestBase]:6\n";
+  position = result.find(match_line, ++position);
+  EXPECT_TRUE(position != std::string::npos);
+  // Expect 4 subsequent foos at line 8.
+  match_line = "foo @ [object BindingsTestBase]:8\n";
+  for (int i = 0; i < 4; ++i) {
+    position = result.find(match_line, ++position);
+    EXPECT_TRUE(position != std::string::npos);
+  }
+  // Expect global code at line 11.
+  match_line = "global code @ [object BindingsTestBase]:11";
+  position = result.find(match_line, ++position);
+  EXPECT_TRUE(position != std::string::npos);
+}
+
+}  // namespace testing
+}  // namespace bindings
+}  // namespace cobalt
diff --git a/src/cobalt/bindings/testing/testing.gyp b/src/cobalt/bindings/testing/testing.gyp
index 49c20e4..b820608 100644
--- a/src/cobalt/bindings/testing/testing.gyp
+++ b/src/cobalt/bindings/testing/testing.gyp
@@ -139,6 +139,7 @@
         'operations_bindings_test.cc',
         'optional_arguments_bindings_test.cc',
         'put_forwards_test.cc',
+        'stack_trace_test.cc',
         'static_properties_bindings_test.cc',
         'stringifier_bindings_test.cc',
         'union_type_bindings_test.cc',
diff --git a/src/cobalt/bindings/testing/window.h b/src/cobalt/bindings/testing/window.h
index 8c6dded..0bc8115 100644
--- a/src/cobalt/bindings/testing/window.h
+++ b/src/cobalt/bindings/testing/window.h
@@ -17,7 +17,12 @@
 #ifndef COBALT_BINDINGS_TESTING_WINDOW_H_
 #define COBALT_BINDINGS_TESTING_WINDOW_H_
 
+#include <string>
+#include <vector>
+
 #include "cobalt/bindings/testing/global_interface_parent.h"
+#include "cobalt/script/environment_settings.h"
+#include "cobalt/script/global_object_proxy.h"
 
 namespace cobalt {
 namespace bindings {
@@ -29,6 +34,12 @@
   virtual std::string window_property() { return ""; }
   virtual void set_window_property(const std::string&) {}
 
+  std::string GetStackTrace(
+      const std::vector<script::StackFrame>& stack_frame) {
+    return StackTraceToString(stack_frame);
+  }
+  scoped_refptr<Window> window() { return this; }
+
   DEFINE_WRAPPABLE_TYPE(Window);
 };
 
diff --git a/src/cobalt/browser/application.cc b/src/cobalt/browser/application.cc
index 5ec73ec..4327e96 100644
--- a/src/cobalt/browser/application.cc
+++ b/src/cobalt/browser/application.cc
@@ -36,7 +36,7 @@
 #include "cobalt/loader/image/image_decoder.h"
 #include "cobalt/math/size.h"
 #include "cobalt/network/network_event.h"
-#if defined(ENABLE_COMMAND_LINE_SWITCHES)
+#if defined(ENABLE_DEBUG_COMMAND_LINE_SWITCHES)
 #include "cobalt/storage/savegame_fake.h"
 #endif
 #include "cobalt/system_window/application_event.h"
@@ -45,7 +45,7 @@
 #if defined(__LB_SHELL__)
 #if !defined(__LB_SHELL__FOR_RELEASE__)
 #include "lbshell/src/lb_memory_manager.h"
-#endif  // defined(ENABLE_DEBUG_CONSOLE)
+#endif  // defined(__LB_SHELL__FOR_RELEASE__)
 #include "lbshell/src/lb_memory_pages.h"
 #endif  // defined(__LB_SHELL__)
 
@@ -64,7 +64,7 @@
 int GetRemoteDebuggingPort() {
   const int kDefaultRemoteDebuggingPort = 9222;
   int remote_debugging_port = kDefaultRemoteDebuggingPort;
-#if defined(ENABLE_COMMAND_LINE_SWITCHES)
+#if defined(ENABLE_DEBUG_COMMAND_LINE_SWITCHES)
   CommandLine* command_line = CommandLine::ForCurrentProcess();
   if (command_line->HasSwitch(switches::kRemoteDebuggingPort)) {
     const std::string switchValue =
@@ -76,13 +76,13 @@
       remote_debugging_port = kDefaultRemoteDebuggingPort;
     }
   }
-#endif  // ENABLE_COMMAND_LINE_SWITCHES
+#endif  // ENABLE_DEBUG_COMMAND_LINE_SWITCHES
   return remote_debugging_port;
 }
 #endif  // ENABLE_REMOTE_DEBUGGING
 
 #if defined(ENABLE_WEBDRIVER)
-#if defined(ENABLE_COMMAND_LINE_SWITCHES)
+#if defined(ENABLE_DEBUG_COMMAND_LINE_SWITCHES)
 int GetWebDriverPort() {
   // The default port on which the webdriver server should listen for incoming
   // connections.
@@ -101,11 +101,11 @@
   }
   return webdriver_port;
 }
-#endif  // ENABLE_COMMAND_LINE_SWITCHES
+#endif  // ENABLE_DEBUG_COMMAND_LINE_SWITCHES
 #endif  // ENABLE_WEBDRIVER
 
 GURL GetInitialURL() {
-#if defined(ENABLE_COMMAND_LINE_SWITCHES)
+#if defined(ENABLE_DEBUG_COMMAND_LINE_SWITCHES)
   // Allow the user to override the default URL via a command line parameter.
   CommandLine* command_line = CommandLine::ForCurrentProcess();
   if (command_line->HasSwitch(switches::kInitialURL)) {
@@ -116,13 +116,13 @@
       DLOG(INFO) << "URL from parameter is not valid, using default URL.";
     }
   }
-#endif  // ENABLE_COMMAND_LINE_SWITCHES
+#endif  // ENABLE_DEBUG_COMMAND_LINE_SWITCHES
 
   return GURL(kDefaultURL);
 }
 
 base::TimeDelta GetTimedTraceDuration() {
-#if defined(ENABLE_COMMAND_LINE_SWITCHES)
+#if defined(ENABLE_DEBUG_COMMAND_LINE_SWITCHES)
   CommandLine* command_line = CommandLine::ForCurrentProcess();
   int duration_in_seconds = 0;
   if (command_line->HasSwitch(switches::kTimedTrace) &&
@@ -131,7 +131,7 @@
           &duration_in_seconds)) {
     return base::TimeDelta::FromSeconds(duration_in_seconds);
   }
-#endif  // ENABLE_COMMAND_LINE_SWITCHES
+#endif  // ENABLE_DEBUG_COMMAND_LINE_SWITCHES
 
   return base::TimeDelta();
 }
@@ -140,7 +140,7 @@
   // Default is empty, command line can override.
   FilePath result;
 
-#if defined(ENABLE_COMMAND_LINE_SWITCHES)
+#if defined(ENABLE_DEBUG_COMMAND_LINE_SWITCHES)
   CommandLine* command_line = CommandLine::ForCurrentProcess();
   if (command_line->HasSwitch(switches::kExtraWebFileDir)) {
     result =
@@ -153,18 +153,19 @@
     }
     DLOG(INFO) << "Extra web file dir: " << result.value();
   }
-#endif  // ENABLE_COMMAND_LINE_SWITCHES
+#endif  // ENABLE_DEBUG_COMMAND_LINE_SWITCHES
 
   return result;
 }
 
-#if defined(ENABLE_COMMAND_LINE_SWITCHES)
+#if defined(ENABLE_DEBUG_COMMAND_LINE_SWITCHES)
 void EnableUsingStubImageDecoderIfRequired() {
   CommandLine* command_line = CommandLine::ForCurrentProcess();
   if (command_line->HasSwitch(switches::kStubImageDecoder)) {
     loader::image::ImageDecoder::UseStubImageDecoder();
   }
 }
+#endif  // ENABLE_DEBUG_COMMAND_LINE_SWITCHES
 
 void SetIntegerIfSwitchIsSet(const char* switch_name, int* output) {
   if (CommandLine::ForCurrentProcess()->HasSwitch(switch_name)) {
@@ -190,7 +191,13 @@
   SetIntegerIfSwitchIsSet(browser::switches::kSkiaCacheSizeInBytes,
                           &options->skia_cache_size_in_bytes);
 }
-#endif  // ENABLE_COMMAND_LINE_SWITCHES
+
+void ApplyCommandLineSettingsToWebModuleOptions(WebModule::Options* options) {
+  SetIntegerIfSwitchIsSet(browser::switches::kImageCacheSizeInBytes,
+                          &options->image_cache_capacity);
+  SetIntegerIfSwitchIsSet(browser::switches::kRemoteTypefaceCacheSizeInBytes,
+                          &options->remote_typeface_cache_capacity);
+}
 
 // Restrict navigation to a couple of whitelisted URLs by default.
 const char kYouTubeTvLocationPolicy[] =
@@ -288,11 +295,13 @@
   options.language = language;
   options.network_module_options.preferred_language = language;
 
-#if defined(ENABLE_COMMAND_LINE_SWITCHES)
   ApplyCommandLineSettingsToRendererOptions(&options.renderer_module_options);
+  ApplyCommandLineSettingsToWebModuleOptions(&options.web_module_options);
 
-  if (CommandLine::ForCurrentProcess()->HasSwitch(
-          browser::switches::kNullSavegame)) {
+  CommandLine* command_line = CommandLine::ForCurrentProcess();
+
+#if defined(ENABLE_DEBUG_COMMAND_LINE_SWITCHES)
+  if (command_line->HasSwitch(browser::switches::kNullSavegame)) {
     options.storage_manager_options.savegame_options.factory =
         &storage::SavegameFake::Create;
   }
@@ -311,8 +320,7 @@
 
   math::Size viewport_size(kDefaultViewportWidth, kDefaultViewportHeight);
 
-#if defined(ENABLE_COMMAND_LINE_SWITCHES)
-  CommandLine* command_line = CommandLine::ForCurrentProcess();
+#if defined(ENABLE_DEBUG_COMMAND_LINE_SWITCHES)
   if (command_line->HasSwitch(browser::switches::kProxy)) {
     options.network_module_options.custom_proxy =
         command_line->GetSwitchValueASCII(browser::switches::kProxy);
@@ -344,6 +352,20 @@
 
   EnableUsingStubImageDecoderIfRequired();
 
+  if (command_line->HasSwitch(switches::kAudioDecoderStub)) {
+    DLOG(INFO) << "Use ShellRawAudioDecoderStub";
+    options.media_module_options.use_audio_decoder_stub = true;
+  }
+  if (command_line->HasSwitch(switches::kNullAudioStreamer)) {
+    DLOG(INFO) << "Use null audio";
+    options.media_module_options.use_null_audio_streamer = true;
+  }
+  if (command_line->HasSwitch(switches::kVideoDecoderStub)) {
+    DLOG(INFO) << "Use ShellRawVideoDecoderStub";
+    options.media_module_options.use_video_decoder_stub = true;
+  }
+#endif  // ENABLE_DEBUG_COMMAND_LINE_SWITCHES
+
   if (command_line->HasSwitch(browser::switches::kViewport)) {
     const std::string switchValue =
         command_line->GetSwitchValueASCII(browser::switches::kViewport);
@@ -381,19 +403,6 @@
       }
     }
   }
-  if (command_line->HasSwitch(switches::kAudioDecoderStub)) {
-    DLOG(INFO) << "Use ShellRawAudioDecoderStub";
-    options.media_module_options.use_audio_decoder_stub = true;
-  }
-  if (command_line->HasSwitch(switches::kNullAudioStreamer)) {
-    DLOG(INFO) << "Use null audio";
-    options.media_module_options.use_null_audio_streamer = true;
-  }
-  if (command_line->HasSwitch(switches::kVideoDecoderStub)) {
-    DLOG(INFO) << "Use ShellRawVideoDecoderStub";
-    options.media_module_options.use_video_decoder_stub = true;
-  }
-#endif  // ENABLE_COMMAND_LINE_SWITCHES
 
   system_window_ =
       system_window::CreateSystemWindow(&event_dispatcher_, viewport_size);
@@ -419,7 +428,7 @@
                                      application_event_callback_);
 
 #if defined(ENABLE_WEBDRIVER)
-#if defined(ENABLE_COMMAND_LINE_SWITCHES)
+#if defined(ENABLE_DEBUG_COMMAND_LINE_SWITCHES)
   if (command_line->HasSwitch(switches::kEnableWebDriver)) {
     int webdriver_port = GetWebDriverPort();
     web_driver_module_.reset(new webdriver::WebDriverModule(
@@ -431,7 +440,7 @@
                    base::Unretained(browser_module_.get())),
         base::Bind(&Application::Quit, base::Unretained(this))));
   }
-#endif  // ENABLE_COMMAND_LINE_SWITCHES
+#endif  // ENABLE_DEBUG_COMMAND_LINE_SWITCHES
 #endif  // ENABLE_WEBDRIVER
 
 #if defined(ENABLE_REMOTE_DEBUGGING)
@@ -442,7 +451,7 @@
                  base::Unretained(browser_module_.get()))));
 #endif  // ENABLE_REMOTE_DEBUGGING
 
-#if defined(ENABLE_COMMAND_LINE_SWITCHES)
+#if defined(ENABLE_DEBUG_COMMAND_LINE_SWITCHES)
   int duration_in_seconds = 0;
   if (command_line->HasSwitch(switches::kShutdownAfter) &&
       base::StringToInt(
@@ -455,7 +464,7 @@
         FROM_HERE, quit_closure_,
         base::TimeDelta::FromSeconds(duration_in_seconds));
   }
-#endif  // ENABLE_COMMAND_LINE_SWITCHES
+#endif  // ENABLE_DEBUG_COMMAND_LINE_SWITCHES
 }
 
 Application::~Application() {
@@ -526,25 +535,15 @@
   if (app_event->type() == system_window::ApplicationEvent::kQuit) {
     DLOG(INFO) << "Got quit event.";
     app_status_ = kWillQuitAppStatus;
-#if !defined(OS_STARBOARD)
-    browser_module_->SetWillQuit();
-    browser_module_->SetPaused(false);
-#endif  // !defined(OS_STARBOARD)
     Quit();
   } else if (app_event->type() == system_window::ApplicationEvent::kSuspend) {
     DLOG(INFO) << "Got suspend event.";
     app_status_ = kPausedAppStatus;
     ++app_suspend_count_;
-#if !defined(OS_STARBOARD)
-    browser_module_->SetPaused(true);
-#endif  // !defined(OS_STARBOARD)
   } else if (app_event->type() == system_window::ApplicationEvent::kResume) {
     DLOG(INFO) << "Got resume event.";
     app_status_ = kRunningAppStatus;
     ++app_resume_count_;
-#if !defined(OS_STARBOARD)
-    browser_module_->SetPaused(false);
-#endif  // !defined(OS_STARBOARD)
   }
 }
 
@@ -629,7 +628,7 @@
         static_cast<size_t>(memory_info.application_memory);
     c_val_stats_.exe_memory = static_cast<size_t>(memory_info.executable_size);
   }
-#endif  // defined(ENABLE_DEBUG_CONSOLE)
+#endif  // defined(__LB_SHELL__FOR_RELEASE__)
   // If the memory stats have not been updated yet, then simply use the
   // unallocated memory as the available memory.
   if (!memory_stats_updated) {
diff --git a/src/cobalt/browser/browser.gyp b/src/cobalt/browser/browser.gyp
index 58aa11b..36effe7 100644
--- a/src/cobalt/browser/browser.gyp
+++ b/src/cobalt/browser/browser.gyp
@@ -46,6 +46,10 @@
         'web_module_stat_tracker.cc',
         'web_module_stat_tracker.h',
       ],
+      'defines': [
+        'COBALT_IMAGE_CACHE_SIZE_IN_BYTES=<(image_cache_size_in_bytes)',
+        'COBALT_REMOTE_TYPEFACE_CACHE_SIZE_IN_BYTES=<(remote_typeface_cache_size_in_bytes)',
+      ],
       'dependencies': [
         '<(DEPTH)/cobalt/account/account.gyp:account',
         '<(DEPTH)/cobalt/audio/audio.gyp:audio',
diff --git a/src/cobalt/browser/browser_bindings.gyp b/src/cobalt/browser/browser_bindings.gyp
index 45d7061..80049c1 100644
--- a/src/cobalt/browser/browser_bindings.gyp
+++ b/src/cobalt/browser/browser_bindings.gyp
@@ -23,6 +23,7 @@
 
     'bindings_dependencies': [
       '../h5vcc/h5vcc.gyp:h5vcc',
+      '../webdriver/webdriver.gyp:webdriver',
     ],
 
     # Bindings for the interfaces in this list will be generated, and there must
@@ -139,6 +140,7 @@
         '../dom/Uint32Array.idl',
         '../dom/Uint8Array.idl',
         '../dom/URL.idl',
+        '../dom/VideoPlaybackQuality.idl',
         '../dom/Window.idl',
         '../dom/XMLDocument.idl',
         '../dom/XMLSerializer.idl',
diff --git a/src/cobalt/browser/browser_module.cc b/src/cobalt/browser/browser_module.cc
index f5abd88..668f3c7 100644
--- a/src/cobalt/browser/browser_module.cc
+++ b/src/cobalt/browser/browser_module.cc
@@ -109,6 +109,9 @@
           weak_this_(weak_ptr_factory_.GetWeakPtr())),
       self_message_loop_(MessageLoop::current()),
       storage_manager_(options.storage_manager_options),
+#if defined(OS_STARBOARD)
+      is_rendered_(false),
+#endif  // OS_STARBOARD
       renderer_module_(system_window, options.renderer_module_options),
 #if defined(ENABLE_GPU_ARRAY_BUFFER_ALLOCATOR)
       array_buffer_allocator_(new ResourceProviderArrayBufferAllocator(
@@ -156,12 +159,12 @@
   web_module_options_.injected_window_attributes["h5vcc"] =
       base::Bind(&CreateH5VCC, h5vcc_settings);
 
-#if defined(ENABLE_DEBUG_CONSOLE) && defined(ENABLE_COMMAND_LINE_SWITCHES)
+#if defined(ENABLE_DEBUG_CONSOLE) && defined(ENABLE_DEBUG_COMMAND_LINE_SWITCHES)
   CommandLine* command_line = CommandLine::ForCurrentProcess();
   if (command_line->HasSwitch(switches::kInputFuzzer)) {
     OnFuzzerToggle(std::string());
   }
-#endif  // ENABLE_DEBUG_CONSOLE && ENABLE_COMMAND_LINE_SWITCHES
+#endif  // ENABLE_DEBUG_CONSOLE && ENABLE_DEBUG_COMMAND_LINE_SWITCHES
 
   input_device_manager_ = input::InputDeviceManager::CreateFromWindow(
       base::Bind(&BrowserModule::OnKeyEventProduced, base::Unretained(this)),
@@ -266,49 +269,6 @@
   return web_module_loaded_.TimedWait(timeout);
 }
 
-void BrowserModule::SetPaused(bool paused) {
-  // This method should not be called on the browser's own thread, as
-  // we will be unable to signal the |has_resumed_| event when the
-  // |Pause| method blocks the thread.
-  DCHECK_NE(MessageLoop::current(), self_message_loop_);
-
-  if (paused) {
-    has_resumed_.Reset();
-    self_message_loop_->PostTask(
-        FROM_HERE, base::Bind(&BrowserModule::Pause, base::Unretained(this)));
-  } else {
-    has_resumed_.Signal();
-  }
-}
-
-void BrowserModule::SetWillQuit() {
-  base::AutoLock lock(quit_lock_);
-  will_quit_ = true;
-}
-
-bool BrowserModule::WillQuit() {
-  base::AutoLock lock(quit_lock_);
-  return will_quit_;
-}
-
-void BrowserModule::Pause() {
-  // This method must be called on the browser's own thread.
-  DCHECK_EQ(MessageLoop::current(), self_message_loop_);
-
-  media_module_->PauseAllPlayers();
-
-  // Block the thread until the browser has been resumed.
-  DLOG(INFO) << "Pausing browser loop with " << self_message_loop_->Size()
-             << " items in queue.";
-  has_resumed_.Wait();
-  DLOG(INFO) << "Resuming browser loop with " << self_message_loop_->Size()
-             << " items in queue.";
-
-  if (!WillQuit()) {
-    media_module_->ResumeAllPlayers();
-  }
-}
-
 #if defined(ENABLE_SCREENSHOT)
 void BrowserModule::RequestScreenshotToFile(const FilePath& path,
                                             const base::Closure& done_cb) {
@@ -325,14 +285,17 @@
 void BrowserModule::OnRenderTreeProduced(
     const browser::WebModule::LayoutResults& layout_results) {
   TRACE_EVENT0("cobalt::browser", "BrowserModule::OnRenderTreeProduced()");
-  render_tree_combiner_.UpdateMainRenderTree(renderer::Submission(
-      layout_results.render_tree, layout_results.animations,
-      layout_results.layout_time));
+  renderer::Submission renderer_submission(layout_results.render_tree,
+                                           layout_results.layout_time);
+#if defined(OS_STARBOARD)
+  renderer_submission.on_rasterized_callback = base::Bind(
+      &BrowserModule::OnRendererSubmissionRasterized, base::Unretained(this));
+#endif  // OS_STARBOARD
+  render_tree_combiner_.UpdateMainRenderTree(renderer_submission);
 
 #if defined(ENABLE_SCREENSHOT)
   screen_shot_writer_->SetLastPipelineSubmission(renderer::Submission(
-      layout_results.render_tree, layout_results.animations,
-      layout_results.layout_time));
+      layout_results.render_tree, layout_results.layout_time));
 #endif
 }
 
@@ -361,8 +324,7 @@
   TRACE_EVENT0("cobalt::browser",
                "BrowserModule::OnDebugConsoleRenderTreeProduced()");
   render_tree_combiner_.UpdateDebugConsoleRenderTree(renderer::Submission(
-      layout_results.render_tree, layout_results.animations,
-      layout_results.layout_time));
+      layout_results.render_tree, layout_results.layout_time));
 }
 
 #endif  // defined(ENABLE_DEBUG_CONSOLE)
@@ -550,5 +512,15 @@
   network_module_.SetProxy(proxy_rules);
 }
 
+#if defined(OS_STARBOARD)
+void BrowserModule::OnRendererSubmissionRasterized() {
+  if (!is_rendered_) {
+    // Hide the system splash screen when the first render has completed.
+    is_rendered_ = true;
+    SbSystemHideSplashScreen();
+  }
+}
+#endif  // OS_STARBOARD
+
 }  // namespace browser
 }  // namespace cobalt
diff --git a/src/cobalt/browser/browser_module.h b/src/cobalt/browser/browser_module.h
index aadc0af..4ae4fb4 100644
--- a/src/cobalt/browser/browser_module.h
+++ b/src/cobalt/browser/browser_module.h
@@ -86,17 +86,6 @@
   void AddURLHandler(const URLHandler::URLHandlerCallback& callback);
   void RemoveURLHandler(const URLHandler::URLHandlerCallback& callback);
 
-  // Pauses/resumes all media players and blocks the browser thread. Should
-  // be called on a thread other than |self_message_loop_|.
-  void SetPaused(bool paused);
-
-  // Lets the web browser know that the application is about to quit. We use
-  // this not to start the web players when the thread is unpaused.
-  void SetWillQuit();
-
-  // Whether |SetWillQuit| has been called.
-  bool WillQuit();
-
 #if defined(ENABLE_SCREENSHOT)
   // Request a screenshot to be written to the specified path. Callback will
   // be fired after the screenshot has been written to disk.
@@ -172,10 +161,6 @@
   // Destroys the splash screen, if currently displayed.
   void DestroySplashScreen();
 
-  // Pauses all active web players and blocks the main thread until the
-  // |has_resumed_| event is signalled. Must be called on |self_message_loop_|.
-  void Pause();
-
 #if defined(ENABLE_DEBUG_CONSOLE)
   // Toggles the input fuzzer on/off.  Ignores the parameter.
   void OnFuzzerToggle(const std::string&);
@@ -195,6 +180,12 @@
       scoped_ptr<webdriver::WindowDriver>* out_window_driver);
 #endif
 
+#if defined(OS_STARBOARD)
+  // Called when a renderer submission has been rasterized. Used to hide the
+  // system splash screen after the first render has completed.
+  void OnRendererSubmissionRasterized();
+#endif  // OS_STARBOARD
+
   // TODO:
   //     WeakPtr usage here can be avoided if BrowserModule has a thread to
   //     own where it can ensure that its tasks are all resolved when it is
@@ -222,6 +213,12 @@
 
   storage::StorageManager storage_manager_;
 
+#if defined(OS_STARBOARD)
+  // Whether the browser module has yet rendered anything. On the very first
+  // render, we hide the system splash screen.
+  bool is_rendered_;
+#endif  // OS_STARBOARD
+
   // Sets up everything to do with graphics, from backend objects like the
   // display and graphics context to the rasterizer and rendering pipeline.
   renderer::RendererModule renderer_module_;
diff --git a/src/cobalt/browser/debug_console.cc b/src/cobalt/browser/debug_console.cc
index 0fce499..a293be3 100644
--- a/src/cobalt/browser/debug_console.cc
+++ b/src/cobalt/browser/debug_console.cc
@@ -77,14 +77,14 @@
 // Returns the debug console mode as specified by the command line.
 // If unspecified by the command line, base::nullopt is returned.
 base::optional<int> GetDebugConsoleModeFromCommandLine() {
-#if defined(ENABLE_COMMAND_LINE_SWITCHES)
+#if defined(ENABLE_DEBUG_COMMAND_LINE_SWITCHES)
   CommandLine* command_line = CommandLine::ForCurrentProcess();
   if (command_line->HasSwitch(switches::kDebugConsoleMode)) {
     const std::string debug_console_mode_string =
         command_line->GetSwitchValueASCII(switches::kDebugConsoleMode);
     return DebugConsoleModeStringToInt(debug_console_mode_string);
   }
-#endif  // ENABLE_COMMAND_LINE_SWITCHES
+#endif  // ENABLE_DEBUG_COMMAND_LINE_SWITCHES
 
   return base::nullopt;
 }
diff --git a/src/cobalt/browser/starboard/event_handler.cc b/src/cobalt/browser/starboard/event_handler.cc
index 4ef7069..00808d7 100644
--- a/src/cobalt/browser/starboard/event_handler.cc
+++ b/src/cobalt/browser/starboard/event_handler.cc
@@ -18,6 +18,7 @@
 
 #include "base/logging.h"
 #include "base/memory/scoped_ptr.h"
+#include "cobalt/network/network_event.h"
 #include "cobalt/system_window/application_event.h"
 #include "cobalt/system_window/starboard/system_window.h"
 
@@ -58,6 +59,12 @@
   } else if (starboard_event->type == kSbEventTypeSuspend) {
     cobalt_event.reset(new system_window::ApplicationEvent(
         system_window::ApplicationEvent::kSuspend));
+  } else if (starboard_event->type == kSbEventTypeNetworkConnect) {
+    cobalt_event.reset(
+        new network::NetworkEvent(network::NetworkEvent::kConnection));
+  } else if (starboard_event->type == kSbEventTypeNetworkDisconnect) {
+    cobalt_event.reset(
+        new network::NetworkEvent(network::NetworkEvent::kDisconnection));
   }
 
   // Dispatch the Cobalt event, if created.
diff --git a/src/cobalt/browser/switches.cc b/src/cobalt/browser/switches.cc
index 9258a4f..d9d0abf 100644
--- a/src/cobalt/browser/switches.cc
+++ b/src/cobalt/browser/switches.cc
@@ -20,7 +20,7 @@
 namespace browser {
 namespace switches {
 
-#if defined(ENABLE_COMMAND_LINE_SWITCHES)
+#if defined(ENABLE_DEBUG_COMMAND_LINE_SWITCHES)
 // Allow insecure HTTP network connections.
 const char kAllowHttp[] = "allow_http";
 
@@ -71,32 +71,13 @@
 // Creates a remote debugging server and listens on the specified port.
 const char kRemoteDebuggingPort[] = "remote_debugging_port";
 
-// 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
-// Skia rasterizer.
-const char kScratchSurfaceCacheSizeInBytes[] =
-    "scratch_surface_cache_size_in_bytes";
-
 // If this flag is set, Cobalt will automatically shutdown after the specified
 // number of seconds have passed.
 const char kShutdownAfter[] = "shutdown_after";
 
-// Determines the capacity of the skia cache.  The Skia cache is maintained
-// within Skia and is used to cache the results of complicated effects such as
-// shadows, so that Skia draw calls that are used repeatedly across frames can
-// be cached into surfaces.  This setting is only relevant when using the
-// hardware-accelerated Skia rasterizer.
-const char kSkiaCacheSizeInBytes[] = "skia_cache_size_in_bytes";
-
 // Decode all images using StubImageDecoder.
 const char kStubImageDecoder[] = "stub_image_decoder";
 
-// Determines the capacity of the surface cache.  The surface cache tracks which
-// render tree nodes are being re-used across frames and stores the nodes that
-// are most CPU-expensive to render into surfaces.
-const char kSurfaceCacheSizeInBytes[] = "surface_cache_size_in_bytes";
-
 // If this is set, then a trace (see base/debug/trace_eventh.h) is started on
 // Cobalt startup.  A value must also be specified for this switch, which is
 // the duration in seconds of how long the trace will be done for before ending
@@ -104,16 +85,48 @@
 // "timed_trace.json" in the log output directory.
 const char kTimedTrace[] = "timed_trace";
 
-// Specifies the viewport size: width ['x' height]
-const char kViewport[] = "viewport";
-
 // Decode video data using ShellRawVideoDecoderStub.
 extern const char kVideoDecoderStub[] = "video_decoder_stub";
 
 // Port that the WebDriver server should be listening on.
 const char kWebDriverPort[] = "webdriver_port";
 
-#endif  // ENABLE_COMMAND_LINE_SWITCHES
+#endif  // ENABLE_DEBUG_COMMAND_LINE_SWITCHES
+
+// Determines the capacity of the image cache which manages image surfaces
+// downloaded from a web page.  While it depends on the platform, often (and
+// ideally) these images are cached within GPU memory.
+const char kImageCacheSizeInBytes[] = "image_cache_size_in_bytes";
+
+// Determines the capacity of the remote typefaces cache which manages all
+// typefaces downloaded from a web page.
+const char kRemoteTypefaceCacheSizeInBytes[] =
+    "remote_typeface_cache_size_in_bytes";
+
+// 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
+// Skia rasterizer.  While it depends on the platform, this setting may affect
+// GPU memory usage.
+const char kScratchSurfaceCacheSizeInBytes[] =
+    "scratch_surface_cache_size_in_bytes";
+
+// Determines the capacity of the skia cache.  The Skia cache is maintained
+// within Skia and is used to cache the results of complicated effects such as
+// shadows, so that Skia draw calls that are used repeatedly across frames can
+// be cached into surfaces.  This setting is only relevant when using the
+// hardware-accelerated Skia rasterizer.  While it depends on the platform, this
+// setting may affect GPU memory usage.
+const char kSkiaCacheSizeInBytes[] = "skia_cache_size_in_bytes";
+
+// Determines the capacity of the surface cache.  The surface cache tracks which
+// render tree nodes are being re-used across frames and stores the nodes that
+// are most CPU-expensive to render into surfaces.  While it depends on the
+// platform, this setting may affect GPU memory usage.
+const char kSurfaceCacheSizeInBytes[] = "surface_cache_size_in_bytes";
+
+// Specifies the viewport size: width ['x' height]
+const char kViewport[] = "viewport";
 
 }  // namespace switches
 }  // namespace browser
diff --git a/src/cobalt/browser/switches.h b/src/cobalt/browser/switches.h
index 4c66e0c..75dc57d 100644
--- a/src/cobalt/browser/switches.h
+++ b/src/cobalt/browser/switches.h
@@ -21,7 +21,7 @@
 namespace browser {
 namespace switches {
 
-#if defined(ENABLE_COMMAND_LINE_SWITCHES)
+#if defined(ENABLE_DEBUG_COMMAND_LINE_SWITCHES)
 extern const char kAllowHttp[];
 extern const char kAudioDecoderStub[];
 extern const char kCspMode[];
@@ -39,13 +39,16 @@
 extern const char kShutdownAfter[];
 extern const char kStubImageDecoder[];
 extern const char kTimedTrace[];
-extern const char kViewport[];
 extern const char kVideoDecoderStub[];
 extern const char kWebDriverPort[];
-extern const char kSurfaceCacheSizeInBytes[];
+#endif  // ENABLE_DEBUG_COMMAND_LINE_SWITCHES
+
+extern const char kImageCacheSizeInBytes[];
+extern const char kRemoteTypefaceCacheSizeInBytes[];
 extern const char kScratchSurfaceCacheSizeInBytes[];
 extern const char kSkiaCacheSizeInBytes[];
-#endif  // ENABLE_COMMAND_LINE_SWITCHES
+extern const char kSurfaceCacheSizeInBytes[];
+extern const char kViewport[];
 
 }  // namespace switches
 }  // namespace browser
diff --git a/src/cobalt/browser/web_module.cc b/src/cobalt/browser/web_module.cc
index 88b5286..828380d 100644
--- a/src/cobalt/browser/web_module.cc
+++ b/src/cobalt/browser/web_module.cc
@@ -246,16 +246,18 @@
       data.network_module, data.options.extra_web_file_dir));
   DCHECK(fetcher_factory_);
 
+  DCHECK_LE(0, data.options.image_cache_capacity);
   image_cache_ = loader::image::CreateImageCache(
       base::StringPrintf("Memory.%s.ImageCache", name_.c_str()),
-      data.options.image_cache_capacity, data.resource_provider,
-      fetcher_factory_.get());
+      static_cast<uint32>(data.options.image_cache_capacity),
+      data.resource_provider, fetcher_factory_.get());
   DCHECK(image_cache_);
 
+  DCHECK_LE(0, data.options.remote_typeface_cache_capacity);
   remote_typeface_cache_ = loader::font::CreateRemoteTypefaceCache(
       base::StringPrintf("Memory.%s.RemoteTypefaceCache", name_.c_str()),
-      kRemoteTypefaceCacheCapacity, data.resource_provider,
-      fetcher_factory_.get());
+      static_cast<uint32>(data.options.remote_typeface_cache_capacity),
+      data.resource_provider, fetcher_factory_.get());
   DCHECK(remote_typeface_cache_);
 
   local_storage_database_.reset(
@@ -512,6 +514,16 @@
   web_module_->impl_.reset();
 }
 
+WebModule::Options::Options()
+    : name("WebModule"),
+      layout_trigger(layout::LayoutManager::kOnDocumentMutation),
+      image_cache_capacity(COBALT_IMAGE_CACHE_SIZE_IN_BYTES),
+      remote_typeface_cache_capacity(
+          COBALT_REMOTE_TYPEFACE_CACHE_SIZE_IN_BYTES),
+      csp_enforcement_mode(dom::kCspEnforcementEnable),
+      csp_insecure_allowed_token(0),
+      track_event_stats(false) {}
+
 WebModule::WebModule(
     const GURL& initial_url,
     const OnRenderTreeProducedCallback& render_tree_produced_callback,
diff --git a/src/cobalt/browser/web_module.h b/src/cobalt/browser/web_module.h
index 83cfa49..826df99 100644
--- a/src/cobalt/browser/web_module.h
+++ b/src/cobalt/browser/web_module.h
@@ -74,11 +74,6 @@
 // accessed from only one thread.
 class WebModule {
  public:
-  // TODO: These numbers should be adjusted according to the size of
-  // client memory.
-  static const uint32 kImageCacheCapacity = 64U * 1024 * 1024;
-  static const uint32 kRemoteTypefaceCacheCapacity = 5U * 1024 * 1024;
-
   struct Options {
     typedef base::Callback<scoped_refptr<script::Wrappable>()>
         CreateObjectFunction;
@@ -86,15 +81,8 @@
         InjectedWindowAttributes;
 
     // All optional parameters defined in this structure should have their
-    // values
-    // initialized in the default constructor to useful defaults.
-    Options()
-        : name("WebModule"),
-          layout_trigger(layout::LayoutManager::kOnDocumentMutation),
-          image_cache_capacity(kImageCacheCapacity),
-          csp_enforcement_mode(dom::kCspEnforcementEnable),
-          csp_insecure_allowed_token(0),
-          track_event_stats(false) {}
+    // values initialized in the default constructor to useful defaults.
+    Options();
 
     // The name of the WebModule.  This is useful for debugging purposes as in
     // the case where multiple WebModule objects exist, it can be used to
@@ -133,7 +121,10 @@
     std::string location_policy;
 
     // Image cache capaticy in bytes.
-    uint32 image_cache_capacity;
+    int image_cache_capacity;
+
+    // Typeface cache capacity in bytes.
+    int remote_typeface_cache_capacity;
 
     // Content Security Policy enforcement mode for this web module.
     dom::CspEnforcementType csp_enforcement_mode;
diff --git a/src/cobalt/build/build.id b/src/cobalt/build/build.id
index 4db8c83..29fb020 100644
--- a/src/cobalt/build/build.id
+++ b/src/cobalt/build/build.id
@@ -1 +1 @@
-9617
\ No newline at end of file
+10060
\ No newline at end of file
diff --git a/src/cobalt/build/config/base.gypi b/src/cobalt/build/config/base.gypi
index ae3ac78..04a0d5e 100644
--- a/src/cobalt/build/config/base.gypi
+++ b/src/cobalt/build/config/base.gypi
@@ -106,11 +106,27 @@
     #   "cobalt/renderer/egl_and_gles/egl_and_gles_<gl_type>.gyp not found"
     'gl_type%': 'system_gles2',
 
+    # Cache parameters
+
+    # The following set of parameters define how much memory is reserved for
+    # different Cobalt caches.  These caches affect CPU *and* GPU memory usage.
+    #
+    # The sum of the following caches effectively describes the maximum GPU
+    # texture memory usage (though it doesn't consider video textures and
+    # display color buffers):
+    #   - skia_cache_size_in_bytes (GLES2 rasterizer only)
+    #   - scratch_surface_cache_size_in_bytes
+    #   - surface_cache_size_in_bytes
+    #   - image_cache_size_in_bytes
+    #
+    # The other caches affect CPU memory usage.
+
     # Determines the capacity of the skia cache.  The Skia cache is maintained
     # within Skia and is used to cache the results of complicated effects such
     # as shadows, so that Skia draw calls that are used repeatedly across
     # frames can be cached into surfaces.  This setting is only relevant when
-    # using the hardware-accelerated Skia rasterizer.
+    # using the hardware-accelerated Skia rasterizer (e.g. as opposed to the
+    # Blitter API).
     'skia_cache_size_in_bytes%': 4 * 1024 * 1024,
 
     # Determines the capacity of the scratch surface cache.  The scratch
@@ -124,6 +140,15 @@
     # nodes that are most CPU-expensive to render into surfaces.
     'surface_cache_size_in_bytes%': 0,
 
+    # Determines the capacity of the image cache which manages image surfaces
+    # downloaded from a web page.  While it depends on the platform, often (and
+    # ideally) these images are cached within GPU memory.
+    'image_cache_size_in_bytes%': 64 * 1024 * 1024,
+
+    # Determines the capacity of the remote typefaces cache which manages all
+    # typefaces downloaded from a web page.
+    'remote_typeface_cache_size_in_bytes%': 5 * 1024 * 1024,
+
     # Compiler configuration.
 
     # The following variables are used to specify compiler and linker
@@ -166,6 +191,11 @@
     # as expected, rather than requiring it to be set for each platform.
     #'javascript_engine%': 'javascriptcore',
 
+    # Enable jit by default. It can be set to 0 to run in interpreter-only mode.
+    # Setting this to 1 on a platform or engine for which there is no JIT
+    # implementation is a no-op.
+    'cobalt_enable_jit%': 1,
+
     # Customize variables used by Chromium's build/common.gypi.
 
     # Disable a check that looks for an official google api key.
@@ -287,7 +317,7 @@
           'COBALT_BOX_DUMP_ENABLED',
           'COBALT_BUILD_TYPE_DEBUG',
           '_DEBUG',
-          'ENABLE_COMMAND_LINE_SWITCHES',
+          'ENABLE_DEBUG_COMMAND_LINE_SWITCHES',
           'ENABLE_DEBUG_C_VAL',
           'ENABLE_DEBUG_CONSOLE',
           'ENABLE_DIR_SOURCE_ROOT_ACCESS',
@@ -310,7 +340,7 @@
           '_DEBUG',
           'ALLOCATOR_STATS_TRACKING',
           'COBALT_BUILD_TYPE_DEVEL',
-          'ENABLE_COMMAND_LINE_SWITCHES',
+          'ENABLE_DEBUG_COMMAND_LINE_SWITCHES',
           'ENABLE_DEBUG_C_VAL',
           'ENABLE_DEBUG_CONSOLE',
           'ENABLE_DIR_SOURCE_ROOT_ACCESS',
@@ -332,7 +362,7 @@
         'defines': [
           'ALLOCATOR_STATS_TRACKING',
           'COBALT_BUILD_TYPE_QA',
-          'ENABLE_COMMAND_LINE_SWITCHES',
+          'ENABLE_DEBUG_COMMAND_LINE_SWITCHES',
           'ENABLE_DEBUG_C_VAL',
           'ENABLE_DEBUG_CONSOLE',
           'ENABLE_DIR_SOURCE_ROOT_ACCESS',
diff --git a/src/cobalt/codereview.settings b/src/cobalt/codereview.settings
deleted file mode 100644
index a4b341a..0000000
--- a/src/cobalt/codereview.settings
+++ /dev/null
@@ -1,4 +0,0 @@
-# This file is used by gcl to get repository specific information.
-GERRIT_HOST: lbshell-internal-review.googlesource.com
-GERRIT_AUTODETECT_BRANCH: true
-CODE_REVIEW_SERVER: lbshell-internal-review.googlesource.com
diff --git a/src/cobalt/cssom/animation_set.cc b/src/cobalt/cssom/animation_set.cc
index 37cea7d..a2459bb 100644
--- a/src/cobalt/cssom/animation_set.cc
+++ b/src/cobalt/cssom/animation_set.cc
@@ -99,7 +99,7 @@
 }
 }  // namespace
 
-void AnimationSet::Update(const base::TimeDelta& current_time,
+bool AnimationSet::Update(const base::TimeDelta& current_time,
                           const CSSComputedStyleData& style,
                           const CSSKeyframesRule::NameMap& keyframes_map) {
   const std::vector<scoped_refptr<PropertyValue> >& names =
@@ -115,9 +115,12 @@
       names[0] == KeywordValue::GetNone()) {
     // If we have no current animations playing and no animations were
     // specified, there is nothing to do so we can return immediately.
-    return;
+    return false;
   }
 
+  // Whether or not the animations have been modified by this update.
+  bool animations_modified = false;
+
   // Build a set of all animations in the new declared animation set, so that
   // we can later use this to decide which old animations are no longer active.
   std::set<std::string> declared_animation_set;
@@ -172,6 +175,8 @@
     if (event_handler_) {
       event_handler_->OnAnimationStarted(inserted->second);
     }
+
+    animations_modified = true;
   }
 
   // Finally check for any animations that are now ended.
@@ -189,10 +194,16 @@
       animations_to_end.push_back(iter->first);
     }
   }
-  for (std::vector<std::string>::iterator iter = animations_to_end.begin();
-       iter != animations_to_end.end(); ++iter) {
-    animations_.erase(*iter);
+  if (!animations_to_end.empty()) {
+    for (std::vector<std::string>::iterator iter = animations_to_end.begin();
+         iter != animations_to_end.end(); ++iter) {
+      animations_.erase(*iter);
+    }
+
+    animations_modified = true;
   }
+
+  return animations_modified;
 }
 
 }  // namespace cssom
diff --git a/src/cobalt/cssom/animation_set.h b/src/cobalt/cssom/animation_set.h
index 5ef8cf1..160377b 100644
--- a/src/cobalt/cssom/animation_set.h
+++ b/src/cobalt/cssom/animation_set.h
@@ -48,7 +48,8 @@
   // Update the internal state of animations based on our previous state and the
   // passed in computed style.  Animations may be started or ended when this
   // method is called.
-  void Update(const base::TimeDelta& current_time,
+  // Returns whether or not the update modified the animations.
+  bool Update(const base::TimeDelta& current_time,
               const CSSComputedStyleData& style,
               const CSSKeyframesRule::NameMap& keyframes_map);
 
diff --git a/src/cobalt/cssom/cascaded_style.cc b/src/cobalt/cssom/cascaded_style.cc
index 99511a2..7776979 100644
--- a/src/cobalt/cssom/cascaded_style.cc
+++ b/src/cobalt/cssom/cascaded_style.cc
@@ -69,7 +69,7 @@
   scoped_refptr<CSSComputedStyleData> cascaded_style(
       new CSSComputedStyleData());
 
-  // A sparce vector of CascadePrecedence values for all possible property
+  // A sparse vector of CascadePrecedence values for all possible property
   // values.
   base::optional<CascadePrecedence>
       cascade_precedences[static_cast<size_t>(kNumLonghandProperties)];
diff --git a/src/cobalt/cssom/computed_style.cc b/src/cobalt/cssom/computed_style.cc
index 30d4986..48d8223 100644
--- a/src/cobalt/cssom/computed_style.cc
+++ b/src/cobalt/cssom/computed_style.cc
@@ -23,6 +23,7 @@
 #include "cobalt/cssom/absolute_url_value.h"
 #include "cobalt/cssom/calc_value.h"
 #include "cobalt/cssom/css_computed_style_data.h"
+#include "cobalt/cssom/css_computed_style_declaration.h"
 #include "cobalt/cssom/font_weight_value.h"
 #include "cobalt/cssom/keyword_value.h"
 #include "cobalt/cssom/length_value.h"
@@ -2484,16 +2485,18 @@
  public:
   CalculateComputedStyleContext(
       CSSComputedStyleData* cascaded_style,
-      const scoped_refptr<const CSSComputedStyleData>& parent_computed_style,
+      const scoped_refptr<CSSComputedStyleDeclaration>&
+          parent_computed_style_declaration,
       const scoped_refptr<const CSSComputedStyleData>& root_computed_style,
       const math::Size& viewport_size,
       GURLMap* const property_key_to_base_url_map)
       : cascaded_style_(cascaded_style),
-        parent_computed_style_(*parent_computed_style),
+        parent_computed_style_(*parent_computed_style_declaration->data()),
         root_computed_style_(*root_computed_style),
         viewport_size_(viewport_size),
         property_key_to_base_url_map_(property_key_to_base_url_map) {
-    cascaded_style_->SetParentComputedStyle(parent_computed_style);
+    cascaded_style_->SetParentComputedStyleDeclaration(
+        parent_computed_style_declaration);
   }
 
   // Updates the property specified by the iterator to its computed value.
@@ -2689,6 +2692,11 @@
 bool CalculateComputedStyleContext::HandleInheritOrInitial(
     PropertyKey key, scoped_refptr<PropertyValue>* value) {
   if (*value == KeywordValue::GetInherit()) {
+    // Add this property to the list of those that inherited their declared
+    // value from the parent. This allows the computed style to later determine
+    // if a value that was explicitly inherited from the parent is no longer
+    // valid.
+    cascaded_style_->AddDeclaredPropertyInheritedFromParent(key);
     *value = parent_computed_style_.GetPropertyValue(key);
     return true;
   } else if (*value == KeywordValue::GetInitial()) {
@@ -3067,22 +3075,39 @@
 
 void PromoteToComputedStyle(
     const scoped_refptr<CSSComputedStyleData>& cascaded_style,
-    const scoped_refptr<const CSSComputedStyleData>& parent_computed_style,
+    const scoped_refptr<CSSComputedStyleDeclaration>&
+        parent_computed_style_declaration,
     const scoped_refptr<const CSSComputedStyleData>& root_computed_style,
     const math::Size& viewport_size,
     GURLMap* const property_key_to_base_url_map) {
   DCHECK(cascaded_style);
-  DCHECK(parent_computed_style);
+  DCHECK(parent_computed_style_declaration);
   DCHECK(root_computed_style);
 
   // Create a context for calculating the computed style.  This object is useful
   // because it can cache computed style values that are depended upon by other
   // properties' computed style calculations.
   CalculateComputedStyleContext calculate_computed_style_context(
-      cascaded_style.get(), parent_computed_style, root_computed_style,
-      viewport_size, property_key_to_base_url_map);
+      cascaded_style.get(), parent_computed_style_declaration,
+      root_computed_style, viewport_size, property_key_to_base_url_map);
 
-  // Go through all values declared values and calculate their computed values.
+  // For each inherited, animatable property, set the property value to
+  // inherited if it is not already declared. This causes the value to be
+  // explicitly set within the CSSComputedStyleData and ensures that the
+  // original value will be available for transitions (which need to know the
+  // before and after state of the property) even when the property is inherited
+  // from a parent that has changed.
+  const PropertyKeyVector& inherited_animatable_properties =
+      GetInheritedAnimatableProperties();
+  for (PropertyKeyVector::const_iterator iter =
+           inherited_animatable_properties.begin();
+       iter != inherited_animatable_properties.end(); ++iter) {
+    if (!cascaded_style->IsDeclared(*iter)) {
+      cascaded_style->SetPropertyValue(*iter, KeywordValue::GetInherit());
+    }
+  }
+
+  // Go through all declared values and calculate their computed values.
   CSSComputedStyleData::PropertyValues* declared_property_values =
       cascaded_style->declared_property_values();
   for (CSSComputedStyleData::PropertyValues::iterator property_value_iterator =
@@ -3095,11 +3120,13 @@
 }
 
 scoped_refptr<CSSComputedStyleData> GetComputedStyleOfAnonymousBox(
-    const scoped_refptr<const CSSComputedStyleData>& parent_computed_style) {
+    const scoped_refptr<CSSComputedStyleDeclaration>&
+        parent_computed_style_declaration) {
   scoped_refptr<CSSComputedStyleData> computed_style =
       new CSSComputedStyleData();
-  PromoteToComputedStyle(computed_style, parent_computed_style,
-                         parent_computed_style, math::Size(), NULL);
+  PromoteToComputedStyle(computed_style, parent_computed_style_declaration,
+                         parent_computed_style_declaration->data(),
+                         math::Size(), NULL);
   return computed_style;
 }
 
diff --git a/src/cobalt/cssom/computed_style.h b/src/cobalt/cssom/computed_style.h
index 9d356df..da9c9da 100644
--- a/src/cobalt/cssom/computed_style.h
+++ b/src/cobalt/cssom/computed_style.h
@@ -25,6 +25,7 @@
 namespace cssom {
 
 class CSSComputedStyleData;
+class CSSComputedStyleDeclaration;
 
 // The computed value is the result of resolving the specified value,
 // generally absolutizing it. The computed value is the value that is
@@ -32,11 +33,12 @@
 //   https://www.w3.org/TR/css-cascade-3/#computed
 
 // Converts specified values into computed values in place.
-// parent_computed_style and root_computed_style cannot be NULL.
+// parent_computed_style_declaration and root_computed_style cannot be NULL.
 // property_key_to_base_url_map can be NULL.
 void PromoteToComputedStyle(
     const scoped_refptr<CSSComputedStyleData>& specified_style,
-    const scoped_refptr<const CSSComputedStyleData>& parent_computed_style,
+    const scoped_refptr<CSSComputedStyleDeclaration>&
+        parent_computed_style_declaration,
     const scoped_refptr<const CSSComputedStyleData>& root_computed_style,
     const math::Size& viewport_size,
     GURLMap* const property_key_to_base_url_map);
@@ -49,7 +51,8 @@
 //   https://www.w3.org/TR/CSS21/visuren.html#anonymous-block-level
 //   https://www.w3.org/TR/CSS21/visuren.html#anonymous
 scoped_refptr<CSSComputedStyleData> GetComputedStyleOfAnonymousBox(
-    const scoped_refptr<const CSSComputedStyleData>& parent_computed_style);
+    const scoped_refptr<CSSComputedStyleDeclaration>&
+        parent_computed_style_declaration);
 
 }  // namespace cssom
 }  // namespace cobalt
diff --git a/src/cobalt/cssom/computed_style_test.cc b/src/cobalt/cssom/computed_style_test.cc
index bd71ff9..d499787 100644
--- a/src/cobalt/cssom/computed_style_test.cc
+++ b/src/cobalt/cssom/computed_style_test.cc
@@ -23,6 +23,7 @@
 #include "cobalt/cssom/calc_value.h"
 #include "cobalt/cssom/css_computed_style_data.h"
 #include "cobalt/cssom/css_computed_style_declaration.h"
+#include "cobalt/cssom/font_style_value.h"
 #include "cobalt/cssom/font_weight_value.h"
 #include "cobalt/cssom/keyword_value.h"
 #include "cobalt/cssom/length_value.h"
@@ -39,15 +40,25 @@
 namespace cobalt {
 namespace cssom {
 
+scoped_refptr<CSSComputedStyleDeclaration> CreateComputedStyleDeclaration(
+    scoped_refptr<CSSComputedStyleData> computed_style) {
+  scoped_refptr<CSSComputedStyleDeclaration> computed_style_declaration(
+      new CSSComputedStyleDeclaration());
+  computed_style_declaration->SetData(computed_style);
+  return computed_style_declaration;
+}
+
 TEST(PromoteToComputedStyle, FontWeightShouldBeBoldAsSpecified) {
   scoped_refptr<CSSComputedStyleData> computed_style(
       new CSSComputedStyleData());
   computed_style->set_font_weight(FontWeightValue::GetBoldAka700());
 
-  scoped_refptr<const CSSComputedStyleData> parent_computed_style(
+  scoped_refptr<CSSComputedStyleData> parent_computed_style(
       new CSSComputedStyleData());
+  scoped_refptr<CSSComputedStyleDeclaration> parent_computed_style_declaration(
+      CreateComputedStyleDeclaration(parent_computed_style));
 
-  PromoteToComputedStyle(computed_style, parent_computed_style,
+  PromoteToComputedStyle(computed_style, parent_computed_style_declaration,
                          parent_computed_style, math::Size(), NULL);
 
   EXPECT_EQ(FontWeightValue::GetBoldAka700(),
@@ -62,8 +73,10 @@
   scoped_refptr<CSSComputedStyleData> parent_computed_style(
       new CSSComputedStyleData());
   parent_computed_style->set_font_size(new LengthValue(100, kPixelsUnit));
+  scoped_refptr<CSSComputedStyleDeclaration> parent_computed_style_declaration(
+      CreateComputedStyleDeclaration(parent_computed_style));
 
-  PromoteToComputedStyle(computed_style, parent_computed_style,
+  PromoteToComputedStyle(computed_style, parent_computed_style_declaration,
                          parent_computed_style, math::Size(), NULL);
 
   LengthValue* computed_font_size = base::polymorphic_downcast<LengthValue*>(
@@ -81,12 +94,14 @@
   scoped_refptr<CSSComputedStyleData> parent_computed_style(
       new CSSComputedStyleData());
   parent_computed_style->set_font_size(new LengthValue(100, kPixelsUnit));
+  scoped_refptr<CSSComputedStyleDeclaration> parent_computed_style_declaration(
+      CreateComputedStyleDeclaration(parent_computed_style));
 
   scoped_refptr<CSSComputedStyleData> root_computed_style(
       new CSSComputedStyleData());
   root_computed_style->set_font_size(new LengthValue(200, kPixelsUnit));
 
-  PromoteToComputedStyle(computed_style, parent_computed_style,
+  PromoteToComputedStyle(computed_style, parent_computed_style_declaration,
                          root_computed_style, math::Size(), NULL);
 
   LengthValue* computed_font_size = base::polymorphic_downcast<LengthValue*>(
@@ -105,8 +120,10 @@
 
   scoped_refptr<CSSComputedStyleData> parent_computed_style(
       new CSSComputedStyleData());
+  scoped_refptr<CSSComputedStyleDeclaration> parent_computed_style_declaration(
+      CreateComputedStyleDeclaration(parent_computed_style));
 
-  PromoteToComputedStyle(computed_style, parent_computed_style,
+  PromoteToComputedStyle(computed_style, parent_computed_style_declaration,
                          parent_computed_style, math::Size(360, 240), NULL);
 
   LengthValue* computed_font_size = base::polymorphic_downcast<LengthValue*>(
@@ -125,10 +142,12 @@
       new CSSComputedStyleData());
   computed_style->set_font_size(new LengthValue(50, kPixelsUnit));
 
-  scoped_refptr<const CSSComputedStyleData> parent_computed_style(
+  scoped_refptr<CSSComputedStyleData> parent_computed_style(
       new CSSComputedStyleData());
+  scoped_refptr<CSSComputedStyleDeclaration> parent_computed_style_declaration(
+      CreateComputedStyleDeclaration(parent_computed_style));
 
-  PromoteToComputedStyle(computed_style, parent_computed_style,
+  PromoteToComputedStyle(computed_style, parent_computed_style_declaration,
                          parent_computed_style, math::Size(), NULL);
 
   LengthValue* computed_font_size = base::polymorphic_downcast<LengthValue*>(
@@ -142,10 +161,12 @@
       new CSSComputedStyleData());
   computed_style->set_line_height(KeywordValue::GetNormal());
 
-  scoped_refptr<const CSSComputedStyleData> parent_computed_style(
+  scoped_refptr<CSSComputedStyleData> parent_computed_style(
       new CSSComputedStyleData());
+  scoped_refptr<CSSComputedStyleDeclaration> parent_computed_style_declaration(
+      CreateComputedStyleDeclaration(parent_computed_style));
 
-  PromoteToComputedStyle(computed_style, parent_computed_style,
+  PromoteToComputedStyle(computed_style, parent_computed_style_declaration,
                          parent_computed_style, math::Size(), NULL);
 
   EXPECT_EQ(KeywordValue::GetNormal(), computed_style->line_height());
@@ -160,8 +181,10 @@
   scoped_refptr<CSSComputedStyleData> parent_computed_style(
       new CSSComputedStyleData());
   parent_computed_style->set_font_size(new LengthValue(100, kPixelsUnit));
+  scoped_refptr<CSSComputedStyleDeclaration> parent_computed_style_declaration(
+      CreateComputedStyleDeclaration(parent_computed_style));
 
-  PromoteToComputedStyle(computed_style, parent_computed_style,
+  PromoteToComputedStyle(computed_style, parent_computed_style_declaration,
                          parent_computed_style, math::Size(), NULL);
 
   LengthValue* computed_line_height = base::polymorphic_downcast<LengthValue*>(
@@ -179,8 +202,10 @@
   scoped_refptr<CSSComputedStyleData> parent_computed_style(
       new CSSComputedStyleData());
   parent_computed_style->set_font_size(new LengthValue(100, kPixelsUnit));
+  scoped_refptr<CSSComputedStyleDeclaration> parent_computed_style_declaration(
+      CreateComputedStyleDeclaration(parent_computed_style));
 
-  PromoteToComputedStyle(computed_style, parent_computed_style,
+  PromoteToComputedStyle(computed_style, parent_computed_style_declaration,
                          parent_computed_style, math::Size(), NULL);
 
   LengthValue* computed_text_indent = base::polymorphic_downcast<LengthValue*>(
@@ -202,12 +227,14 @@
 
   scoped_refptr<CSSComputedStyleData> parent_computed_style(
       new CSSComputedStyleData());
+  scoped_refptr<CSSComputedStyleDeclaration> parent_computed_style_declaration(
+      CreateComputedStyleDeclaration(parent_computed_style));
 
   GURLMap property_key_to_base_url_map;
   property_key_to_base_url_map[kBackgroundImageProperty] =
       GURL("file:///computed_style_test/style_sheet.css");
 
-  PromoteToComputedStyle(computed_style, parent_computed_style,
+  PromoteToComputedStyle(computed_style, parent_computed_style_declaration,
                          parent_computed_style, math::Size(),
                          &property_key_to_base_url_map);
 
@@ -237,12 +264,14 @@
 
   scoped_refptr<CSSComputedStyleData> parent_computed_style(
       new CSSComputedStyleData());
+  scoped_refptr<CSSComputedStyleDeclaration> parent_computed_style_declaration(
+      CreateComputedStyleDeclaration(parent_computed_style));
 
   GURLMap property_key_to_base_url_map;
   property_key_to_base_url_map[kBackgroundImageProperty] =
       GURL("file:///computed_style_test/document.html");
 
-  PromoteToComputedStyle(computed_style, parent_computed_style,
+  PromoteToComputedStyle(computed_style, parent_computed_style_declaration,
                          parent_computed_style, math::Size(),
                          &property_key_to_base_url_map);
 
@@ -263,9 +292,12 @@
       GetPropertyInitialValue(kBackgroundPositionProperty));
   computed_style->set_background_position(background_position);
 
-  scoped_refptr<const CSSComputedStyleData> parent_computed_style(
+  scoped_refptr<CSSComputedStyleData> parent_computed_style(
       new CSSComputedStyleData());
-  PromoteToComputedStyle(computed_style, parent_computed_style,
+  scoped_refptr<CSSComputedStyleDeclaration> parent_computed_style_declaration(
+      CreateComputedStyleDeclaration(parent_computed_style));
+
+  PromoteToComputedStyle(computed_style, parent_computed_style_declaration,
                          parent_computed_style, math::Size(), NULL);
 
   scoped_refptr<PropertyListValue> background_position_list =
@@ -302,9 +334,12 @@
       new PropertyListValue(background_position_builder.Pass()));
   computed_style->set_background_position(background_position);
 
-  scoped_refptr<const CSSComputedStyleData> parent_computed_style(
+  scoped_refptr<CSSComputedStyleData> parent_computed_style(
       new CSSComputedStyleData());
-  PromoteToComputedStyle(computed_style, parent_computed_style,
+  scoped_refptr<CSSComputedStyleDeclaration> parent_computed_style_declaration(
+      CreateComputedStyleDeclaration(parent_computed_style));
+
+  PromoteToComputedStyle(computed_style, parent_computed_style_declaration,
                          parent_computed_style, math::Size(), NULL);
 
   scoped_refptr<PropertyListValue> background_position_list =
@@ -340,9 +375,12 @@
       new PropertyListValue(background_position_builder.Pass()));
   computed_style->set_background_position(background_position);
 
-  scoped_refptr<const CSSComputedStyleData> parent_computed_style(
+  scoped_refptr<CSSComputedStyleData> parent_computed_style(
       new CSSComputedStyleData());
-  PromoteToComputedStyle(computed_style, parent_computed_style,
+  scoped_refptr<CSSComputedStyleDeclaration> parent_computed_style_declaration(
+      CreateComputedStyleDeclaration(parent_computed_style));
+
+  PromoteToComputedStyle(computed_style, parent_computed_style_declaration,
                          parent_computed_style, math::Size(), NULL);
 
   scoped_refptr<PropertyListValue> background_position_list =
@@ -380,9 +418,12 @@
       new PropertyListValue(background_position_builder.Pass()));
   computed_style->set_background_position(background_position);
 
-  scoped_refptr<const CSSComputedStyleData> parent_computed_style(
+  scoped_refptr<CSSComputedStyleData> parent_computed_style(
       new CSSComputedStyleData());
-  PromoteToComputedStyle(computed_style, parent_computed_style,
+  scoped_refptr<CSSComputedStyleDeclaration> parent_computed_style_declaration(
+      CreateComputedStyleDeclaration(parent_computed_style));
+
+  PromoteToComputedStyle(computed_style, parent_computed_style_declaration,
                          parent_computed_style, math::Size(), NULL);
 
   scoped_refptr<PropertyListValue> background_position_list =
@@ -419,9 +460,12 @@
       new PropertyListValue(background_position_builder.Pass()));
   computed_style->set_background_position(background_position);
 
-  scoped_refptr<const CSSComputedStyleData> parent_computed_style(
+  scoped_refptr<CSSComputedStyleData> parent_computed_style(
       new CSSComputedStyleData());
-  PromoteToComputedStyle(computed_style, parent_computed_style,
+  scoped_refptr<CSSComputedStyleDeclaration> parent_computed_style_declaration(
+      CreateComputedStyleDeclaration(parent_computed_style));
+
+  PromoteToComputedStyle(computed_style, parent_computed_style_declaration,
                          parent_computed_style, math::Size(), NULL);
 
   scoped_refptr<PropertyListValue> background_position_list =
@@ -458,9 +502,12 @@
       new PropertyListValue(background_position_builder.Pass()));
   computed_style->set_background_position(background_position);
 
-  scoped_refptr<const CSSComputedStyleData> parent_computed_style(
+  scoped_refptr<CSSComputedStyleData> parent_computed_style(
       new CSSComputedStyleData());
-  PromoteToComputedStyle(computed_style, parent_computed_style,
+  scoped_refptr<CSSComputedStyleDeclaration> parent_computed_style_declaration(
+      CreateComputedStyleDeclaration(parent_computed_style));
+
+  PromoteToComputedStyle(computed_style, parent_computed_style_declaration,
                          parent_computed_style, math::Size(), NULL);
 
   scoped_refptr<PropertyListValue> background_position_list =
@@ -497,9 +544,12 @@
       new PropertyListValue(background_position_builder.Pass()));
   computed_style->set_background_position(background_position);
 
-  scoped_refptr<const CSSComputedStyleData> parent_computed_style(
+  scoped_refptr<CSSComputedStyleData> parent_computed_style(
       new CSSComputedStyleData());
-  PromoteToComputedStyle(computed_style, parent_computed_style,
+  scoped_refptr<CSSComputedStyleDeclaration> parent_computed_style_declaration(
+      CreateComputedStyleDeclaration(parent_computed_style));
+
+  PromoteToComputedStyle(computed_style, parent_computed_style_declaration,
                          parent_computed_style, math::Size(), NULL);
 
   scoped_refptr<PropertyListValue> background_position_list =
@@ -537,9 +587,12 @@
       new PropertyListValue(background_position_builder.Pass()));
   computed_style->set_background_position(background_position);
 
-  scoped_refptr<const CSSComputedStyleData> parent_computed_style(
+  scoped_refptr<CSSComputedStyleData> parent_computed_style(
       new CSSComputedStyleData());
-  PromoteToComputedStyle(computed_style, parent_computed_style,
+  scoped_refptr<CSSComputedStyleDeclaration> parent_computed_style_declaration(
+      CreateComputedStyleDeclaration(parent_computed_style));
+
+  PromoteToComputedStyle(computed_style, parent_computed_style_declaration,
                          parent_computed_style, math::Size(), NULL);
 
   scoped_refptr<PropertyListValue> background_position_list =
@@ -577,9 +630,12 @@
       new PropertyListValue(background_position_builder.Pass()));
   computed_style->set_background_position(background_position);
 
-  scoped_refptr<const CSSComputedStyleData> parent_computed_style(
+  scoped_refptr<CSSComputedStyleData> parent_computed_style(
       new CSSComputedStyleData());
-  PromoteToComputedStyle(computed_style, parent_computed_style,
+  scoped_refptr<CSSComputedStyleDeclaration> parent_computed_style_declaration(
+      CreateComputedStyleDeclaration(parent_computed_style));
+
+  PromoteToComputedStyle(computed_style, parent_computed_style_declaration,
                          parent_computed_style, math::Size(), NULL);
 
   scoped_refptr<PropertyListValue> background_position_list =
@@ -618,9 +674,12 @@
       new PropertyListValue(background_position_builder.Pass()));
   computed_style->set_background_position(background_position);
 
-  scoped_refptr<const CSSComputedStyleData> parent_computed_style(
+  scoped_refptr<CSSComputedStyleData> parent_computed_style(
       new CSSComputedStyleData());
-  PromoteToComputedStyle(computed_style, parent_computed_style,
+  scoped_refptr<CSSComputedStyleDeclaration> parent_computed_style_declaration(
+      CreateComputedStyleDeclaration(parent_computed_style));
+
+  PromoteToComputedStyle(computed_style, parent_computed_style_declaration,
                          parent_computed_style, math::Size(), NULL);
 
   scoped_refptr<PropertyListValue> background_position_list =
@@ -656,9 +715,12 @@
       new PropertyListValue(background_size_builder.Pass()));
   computed_style->set_background_size(background_size);
 
-  scoped_refptr<const CSSComputedStyleData> parent_computed_style(
+  scoped_refptr<CSSComputedStyleData> parent_computed_style(
       new CSSComputedStyleData());
-  PromoteToComputedStyle(computed_style, parent_computed_style,
+  scoped_refptr<CSSComputedStyleDeclaration> parent_computed_style_declaration(
+      CreateComputedStyleDeclaration(parent_computed_style));
+
+  PromoteToComputedStyle(computed_style, parent_computed_style_declaration,
                          parent_computed_style, math::Size(), NULL);
 
   scoped_refptr<PropertyListValue> background_size_list =
@@ -682,9 +744,12 @@
       new CSSComputedStyleData());
   computed_style->set_background_size(KeywordValue::GetContain());
 
-  scoped_refptr<const CSSComputedStyleData> parent_computed_style(
+  scoped_refptr<CSSComputedStyleData> parent_computed_style(
       new CSSComputedStyleData());
-  PromoteToComputedStyle(computed_style, parent_computed_style,
+  scoped_refptr<CSSComputedStyleDeclaration> parent_computed_style_declaration(
+      CreateComputedStyleDeclaration(parent_computed_style));
+
+  PromoteToComputedStyle(computed_style, parent_computed_style_declaration,
                          parent_computed_style, math::Size(), NULL);
 
   EXPECT_EQ(KeywordValue::GetContain(), computed_style->background_size());
@@ -695,9 +760,12 @@
       new CSSComputedStyleData());
   computed_style->set_border_radius(new LengthValue(3, kFontSizesAkaEmUnit));
 
-  scoped_refptr<const CSSComputedStyleData> parent_computed_style(
+  scoped_refptr<CSSComputedStyleData> parent_computed_style(
       new CSSComputedStyleData());
-  PromoteToComputedStyle(computed_style, parent_computed_style,
+  scoped_refptr<CSSComputedStyleDeclaration> parent_computed_style_declaration(
+      CreateComputedStyleDeclaration(parent_computed_style));
+
+  PromoteToComputedStyle(computed_style, parent_computed_style_declaration,
                          parent_computed_style, math::Size(), NULL);
 
   LengthValue* border_radius = base::polymorphic_downcast<LengthValue*>(
@@ -712,9 +780,12 @@
   computed_style->set_border_left_color(KeywordValue::GetCurrentColor());
   computed_style->set_color(RGBAColorValue::GetAqua());
 
-  scoped_refptr<const CSSComputedStyleData> parent_computed_style(
+  scoped_refptr<CSSComputedStyleData> parent_computed_style(
       new CSSComputedStyleData());
-  PromoteToComputedStyle(computed_style, parent_computed_style,
+  scoped_refptr<CSSComputedStyleDeclaration> parent_computed_style_declaration(
+      CreateComputedStyleDeclaration(parent_computed_style));
+
+  PromoteToComputedStyle(computed_style, parent_computed_style_declaration,
                          parent_computed_style, math::Size(), NULL);
 
   scoped_refptr<RGBAColorValue> border_color =
@@ -729,9 +800,12 @@
   computed_style->set_border_top_style(KeywordValue::GetNone());
   computed_style->set_border_top_width(new LengthValue(2, kFontSizesAkaEmUnit));
 
-  scoped_refptr<const CSSComputedStyleData> parent_computed_style(
+  scoped_refptr<CSSComputedStyleData> parent_computed_style(
       new CSSComputedStyleData());
-  PromoteToComputedStyle(computed_style, parent_computed_style,
+  scoped_refptr<CSSComputedStyleDeclaration> parent_computed_style_declaration(
+      CreateComputedStyleDeclaration(parent_computed_style));
+
+  PromoteToComputedStyle(computed_style, parent_computed_style_declaration,
                          parent_computed_style, math::Size(), NULL);
 
   scoped_refptr<LengthValue> border_top_width =
@@ -752,7 +826,10 @@
   scoped_refptr<CSSComputedStyleData> parent_computed_style(
       new CSSComputedStyleData());
   parent_computed_style->set_font_size(new LengthValue(100, kPixelsUnit));
-  PromoteToComputedStyle(computed_style, parent_computed_style,
+  scoped_refptr<CSSComputedStyleDeclaration> parent_computed_style_declaration(
+      CreateComputedStyleDeclaration(parent_computed_style));
+
+  PromoteToComputedStyle(computed_style, parent_computed_style_declaration,
                          parent_computed_style, math::Size(), NULL);
 
   scoped_refptr<LengthValue> border_left_width =
@@ -781,7 +858,10 @@
   scoped_refptr<CSSComputedStyleData> parent_computed_style(
       new CSSComputedStyleData());
   parent_computed_style->set_font_size(new LengthValue(50, kPixelsUnit));
-  PromoteToComputedStyle(computed_style, parent_computed_style,
+  scoped_refptr<CSSComputedStyleDeclaration> parent_computed_style_declaration(
+      CreateComputedStyleDeclaration(parent_computed_style));
+
+  PromoteToComputedStyle(computed_style, parent_computed_style_declaration,
                          parent_computed_style, math::Size(), NULL);
 
   scoped_refptr<PropertyListValue> box_shadow_list =
@@ -824,7 +904,10 @@
 
   scoped_refptr<CSSComputedStyleData> parent_computed_style(
       new CSSComputedStyleData());
-  PromoteToComputedStyle(computed_style, parent_computed_style,
+  scoped_refptr<CSSComputedStyleDeclaration> parent_computed_style_declaration(
+      CreateComputedStyleDeclaration(parent_computed_style));
+
+  PromoteToComputedStyle(computed_style, parent_computed_style_declaration,
                          parent_computed_style, math::Size(), NULL);
 
   scoped_refptr<PropertyListValue> box_shadow_list =
@@ -867,7 +950,10 @@
   scoped_refptr<CSSComputedStyleData> parent_computed_style(
       new CSSComputedStyleData());
   parent_computed_style->set_color(new RGBAColorValue(0x0047abff));
-  PromoteToComputedStyle(computed_style, parent_computed_style,
+  scoped_refptr<CSSComputedStyleDeclaration> parent_computed_style_declaration(
+      CreateComputedStyleDeclaration(parent_computed_style));
+
+  PromoteToComputedStyle(computed_style, parent_computed_style_declaration,
                          parent_computed_style, math::Size(), NULL);
 
   scoped_refptr<PropertyListValue> box_shadow_list =
@@ -918,7 +1004,10 @@
       new CSSComputedStyleData());
   parent_computed_style->set_font_size(new LengthValue(50, kPixelsUnit));
   parent_computed_style->set_color(new RGBAColorValue(0x0047ABFF));
-  PromoteToComputedStyle(computed_style, parent_computed_style,
+  scoped_refptr<CSSComputedStyleDeclaration> parent_computed_style_declaration(
+      CreateComputedStyleDeclaration(parent_computed_style));
+
+  PromoteToComputedStyle(computed_style, parent_computed_style_declaration,
                          parent_computed_style, math::Size(), NULL);
 
   scoped_refptr<PropertyListValue> box_shadow_list =
@@ -970,7 +1059,10 @@
 
   scoped_refptr<CSSComputedStyleData> parent_computed_style(
       new CSSComputedStyleData());
-  PromoteToComputedStyle(computed_style, parent_computed_style,
+  scoped_refptr<CSSComputedStyleDeclaration> parent_computed_style_declaration(
+      CreateComputedStyleDeclaration(parent_computed_style));
+
+  PromoteToComputedStyle(computed_style, parent_computed_style_declaration,
                          parent_computed_style, math::Size(), NULL);
 
   EXPECT_EQ(KeywordValue::GetNone(), computed_style->box_shadow());
@@ -982,9 +1074,12 @@
   computed_style->set_text_decoration_color(KeywordValue::GetCurrentColor());
   computed_style->set_color(RGBAColorValue::GetAqua());
 
-  scoped_refptr<const CSSComputedStyleData> parent_computed_style(
+  scoped_refptr<CSSComputedStyleData> parent_computed_style(
       new CSSComputedStyleData());
-  PromoteToComputedStyle(computed_style, parent_computed_style,
+  scoped_refptr<CSSComputedStyleDeclaration> parent_computed_style_declaration(
+      CreateComputedStyleDeclaration(parent_computed_style));
+
+  PromoteToComputedStyle(computed_style, parent_computed_style_declaration,
                          parent_computed_style, math::Size(), NULL);
 
   scoped_refptr<RGBAColorValue> text_decoration_color =
@@ -1014,7 +1109,10 @@
   scoped_refptr<CSSComputedStyleData> parent_computed_style(
       new CSSComputedStyleData());
   parent_computed_style->set_font_size(new LengthValue(50, kPixelsUnit));
-  PromoteToComputedStyle(computed_style, parent_computed_style,
+  scoped_refptr<CSSComputedStyleDeclaration> parent_computed_style_declaration(
+      CreateComputedStyleDeclaration(parent_computed_style));
+
+  PromoteToComputedStyle(computed_style, parent_computed_style_declaration,
                          parent_computed_style, math::Size(), NULL);
 
   scoped_refptr<PropertyListValue> text_shadow_list =
@@ -1055,7 +1153,10 @@
   scoped_refptr<CSSComputedStyleData> parent_computed_style(
       new CSSComputedStyleData());
   parent_computed_style->set_color(new RGBAColorValue(0x0047abff));
-  PromoteToComputedStyle(computed_style, parent_computed_style,
+  scoped_refptr<CSSComputedStyleDeclaration> parent_computed_style_declaration(
+      CreateComputedStyleDeclaration(parent_computed_style));
+
+  PromoteToComputedStyle(computed_style, parent_computed_style_declaration,
                          parent_computed_style, math::Size(), NULL);
 
   scoped_refptr<PropertyListValue> text_shadow_list =
@@ -1105,7 +1206,10 @@
       new CSSComputedStyleData());
   parent_computed_style->set_font_size(new LengthValue(50, kPixelsUnit));
   parent_computed_style->set_color(new RGBAColorValue(0x0047ABFF));
-  PromoteToComputedStyle(computed_style, parent_computed_style,
+  scoped_refptr<CSSComputedStyleDeclaration> parent_computed_style_declaration(
+      CreateComputedStyleDeclaration(parent_computed_style));
+
+  PromoteToComputedStyle(computed_style, parent_computed_style_declaration,
                          parent_computed_style, math::Size(), NULL);
 
   scoped_refptr<PropertyListValue> text_shadow_list =
@@ -1156,7 +1260,10 @@
 
   scoped_refptr<CSSComputedStyleData> parent_computed_style(
       new CSSComputedStyleData());
-  PromoteToComputedStyle(computed_style, parent_computed_style,
+  scoped_refptr<CSSComputedStyleDeclaration> parent_computed_style_declaration(
+      CreateComputedStyleDeclaration(parent_computed_style));
+
+  PromoteToComputedStyle(computed_style, parent_computed_style_declaration,
                          parent_computed_style, math::Size(), NULL);
 
   EXPECT_EQ(KeywordValue::GetNone(), computed_style->text_shadow());
@@ -1171,10 +1278,13 @@
       new CSSComputedStyleData());
   computed_style->set_height(new PercentageValue(0.50f));
 
-  scoped_refptr<const CSSComputedStyleData> parent_computed_style(
+  scoped_refptr<CSSComputedStyleData> parent_computed_style(
       new CSSComputedStyleData());
   EXPECT_EQ(KeywordValue::GetAuto(), parent_computed_style->height());
-  PromoteToComputedStyle(computed_style, parent_computed_style,
+  scoped_refptr<CSSComputedStyleDeclaration> parent_computed_style_declaration(
+      CreateComputedStyleDeclaration(parent_computed_style));
+
+  PromoteToComputedStyle(computed_style, parent_computed_style_declaration,
                          parent_computed_style, math::Size(), NULL);
 
   EXPECT_EQ(KeywordValue::GetAuto(), computed_style->height());
@@ -1190,10 +1300,13 @@
       new CSSComputedStyleData());
   computed_style->set_max_height(new PercentageValue(0.50f));
 
-  scoped_refptr<const CSSComputedStyleData> parent_computed_style(
+  scoped_refptr<CSSComputedStyleData> parent_computed_style(
       new CSSComputedStyleData());
   EXPECT_EQ(KeywordValue::GetAuto(), parent_computed_style->height());
-  PromoteToComputedStyle(computed_style, parent_computed_style,
+  scoped_refptr<CSSComputedStyleDeclaration> parent_computed_style_declaration(
+      CreateComputedStyleDeclaration(parent_computed_style));
+
+  PromoteToComputedStyle(computed_style, parent_computed_style_declaration,
                          parent_computed_style, math::Size(), NULL);
 
   EXPECT_EQ(KeywordValue::GetNone(), computed_style->max_height());
@@ -1209,10 +1322,13 @@
       new CSSComputedStyleData());
   computed_style->set_min_height(new PercentageValue(0.50f));
 
-  scoped_refptr<const CSSComputedStyleData> parent_computed_style(
+  scoped_refptr<CSSComputedStyleData> parent_computed_style(
       new CSSComputedStyleData());
   EXPECT_EQ(KeywordValue::GetAuto(), parent_computed_style->height());
-  PromoteToComputedStyle(computed_style, parent_computed_style,
+  scoped_refptr<CSSComputedStyleDeclaration> parent_computed_style_declaration(
+      CreateComputedStyleDeclaration(parent_computed_style));
+
+  PromoteToComputedStyle(computed_style, parent_computed_style_declaration,
                          parent_computed_style, math::Size(), NULL);
 
   LengthValue* computed_min_height = base::polymorphic_downcast<LengthValue*>(
@@ -1229,15 +1345,22 @@
       new CSSComputedStyleData());
   computed_style->set_max_width(new PercentageValue(0.50f));
 
-  scoped_refptr<const CSSComputedStyleData> grandparent_computed_style(
+  scoped_refptr<CSSComputedStyleData> grandparent_computed_style(
       new CSSComputedStyleData());
+  scoped_refptr<CSSComputedStyleDeclaration>
+      grandparent_computed_style_declaration(
+          CreateComputedStyleDeclaration(grandparent_computed_style));
 
   scoped_refptr<CSSComputedStyleData> parent_computed_style(
       new CSSComputedStyleData());
   parent_computed_style->set_width(new LengthValue(-16, kPixelsUnit));
-  PromoteToComputedStyle(parent_computed_style, grandparent_computed_style,
+  scoped_refptr<CSSComputedStyleDeclaration> parent_computed_style_declaration(
+      CreateComputedStyleDeclaration(parent_computed_style));
+
+  PromoteToComputedStyle(parent_computed_style,
+                         grandparent_computed_style_declaration,
                          grandparent_computed_style, math::Size(), NULL);
-  PromoteToComputedStyle(computed_style, parent_computed_style,
+  PromoteToComputedStyle(computed_style, parent_computed_style_declaration,
                          grandparent_computed_style, math::Size(), NULL);
 
   LengthValue* computed_max_width = base::polymorphic_downcast<LengthValue*>(
@@ -1254,15 +1377,22 @@
       new CSSComputedStyleData());
   computed_style->set_min_width(new PercentageValue(0.50f));
 
-  scoped_refptr<const CSSComputedStyleData> grandparent_computed_style(
+  scoped_refptr<CSSComputedStyleData> grandparent_computed_style(
       new CSSComputedStyleData());
+  scoped_refptr<CSSComputedStyleDeclaration>
+      grandparent_computed_style_declaration(
+          CreateComputedStyleDeclaration(grandparent_computed_style));
 
   scoped_refptr<CSSComputedStyleData> parent_computed_style(
       new CSSComputedStyleData());
   parent_computed_style->set_width(new LengthValue(-16, kPixelsUnit));
-  PromoteToComputedStyle(parent_computed_style, grandparent_computed_style,
+  scoped_refptr<CSSComputedStyleDeclaration> parent_computed_style_declaration(
+      CreateComputedStyleDeclaration(parent_computed_style));
+
+  PromoteToComputedStyle(parent_computed_style,
+                         grandparent_computed_style_declaration,
                          grandparent_computed_style, math::Size(), NULL);
-  PromoteToComputedStyle(computed_style, parent_computed_style,
+  PromoteToComputedStyle(computed_style, parent_computed_style_declaration,
                          grandparent_computed_style, math::Size(), NULL);
 
   LengthValue* computed_min_width = base::polymorphic_downcast<LengthValue*>(
@@ -1280,10 +1410,12 @@
   computed_style->set_font_size(new LengthValue(100, kPixelsUnit));
   computed_style->set_line_height(new PercentageValue(0.75f));
 
-  scoped_refptr<const CSSComputedStyleData> parent_computed_style(
+  scoped_refptr<CSSComputedStyleData> parent_computed_style(
       new CSSComputedStyleData());
+  scoped_refptr<CSSComputedStyleDeclaration> parent_computed_style_declaration(
+      CreateComputedStyleDeclaration(parent_computed_style));
 
-  PromoteToComputedStyle(computed_style, parent_computed_style,
+  PromoteToComputedStyle(computed_style, parent_computed_style_declaration,
                          parent_computed_style, math::Size(), NULL);
 
   LengthValue* computed_line_height = base::polymorphic_downcast<LengthValue*>(
@@ -1304,9 +1436,12 @@
       new PropertyListValue(transform_origin_builder.Pass()));
   computed_style->set_transform_origin(transform_origin);
 
-  scoped_refptr<const CSSComputedStyleData> parent_computed_style(
+  scoped_refptr<CSSComputedStyleData> parent_computed_style(
       new CSSComputedStyleData());
-  PromoteToComputedStyle(computed_style, parent_computed_style,
+  scoped_refptr<CSSComputedStyleDeclaration> parent_computed_style_declaration(
+      CreateComputedStyleDeclaration(parent_computed_style));
+
+  PromoteToComputedStyle(computed_style, parent_computed_style_declaration,
                          parent_computed_style, math::Size(), NULL);
 
   scoped_refptr<PropertyListValue> transform_origin_list =
@@ -1347,9 +1482,12 @@
       new PropertyListValue(transform_origin_builder.Pass()));
   computed_style->set_transform_origin(transform_origin);
 
-  scoped_refptr<const CSSComputedStyleData> parent_computed_style(
+  scoped_refptr<CSSComputedStyleData> parent_computed_style(
       new CSSComputedStyleData());
-  PromoteToComputedStyle(computed_style, parent_computed_style,
+  scoped_refptr<CSSComputedStyleDeclaration> parent_computed_style_declaration(
+      CreateComputedStyleDeclaration(parent_computed_style));
+
+  PromoteToComputedStyle(computed_style, parent_computed_style_declaration,
                          parent_computed_style, math::Size(), NULL);
 
   scoped_refptr<PropertyListValue> transform_origin_list =
@@ -1391,9 +1529,12 @@
       new PropertyListValue(transform_origin_builder.Pass()));
   computed_style->set_transform_origin(transform_origin);
 
-  scoped_refptr<const CSSComputedStyleData> parent_computed_style(
+  scoped_refptr<CSSComputedStyleData> parent_computed_style(
       new CSSComputedStyleData());
-  PromoteToComputedStyle(computed_style, parent_computed_style,
+  scoped_refptr<CSSComputedStyleDeclaration> parent_computed_style_declaration(
+      CreateComputedStyleDeclaration(parent_computed_style));
+
+  PromoteToComputedStyle(computed_style, parent_computed_style_declaration,
                          parent_computed_style, math::Size(), NULL);
 
   scoped_refptr<PropertyListValue> transform_origin_list =
@@ -1435,9 +1576,12 @@
       new PropertyListValue(transform_origin_builder.Pass()));
   computed_style->set_transform_origin(transform_origin);
 
-  scoped_refptr<const CSSComputedStyleData> parent_computed_style(
+  scoped_refptr<CSSComputedStyleData> parent_computed_style(
       new CSSComputedStyleData());
-  PromoteToComputedStyle(computed_style, parent_computed_style,
+  scoped_refptr<CSSComputedStyleDeclaration> parent_computed_style_declaration(
+      CreateComputedStyleDeclaration(parent_computed_style));
+
+  PromoteToComputedStyle(computed_style, parent_computed_style_declaration,
                          parent_computed_style, math::Size(), NULL);
 
   scoped_refptr<PropertyListValue> transform_origin_list =
@@ -1479,9 +1623,12 @@
       new PropertyListValue(transform_origin_builder.Pass()));
   computed_style->set_transform_origin(transform_origin);
 
-  scoped_refptr<const CSSComputedStyleData> parent_computed_style(
+  scoped_refptr<CSSComputedStyleData> parent_computed_style(
       new CSSComputedStyleData());
-  PromoteToComputedStyle(computed_style, parent_computed_style,
+  scoped_refptr<CSSComputedStyleDeclaration> parent_computed_style_declaration(
+      CreateComputedStyleDeclaration(parent_computed_style));
+
+  PromoteToComputedStyle(computed_style, parent_computed_style_declaration,
                          parent_computed_style, math::Size(), NULL);
 
   scoped_refptr<PropertyListValue> transform_origin_list =
@@ -1523,9 +1670,12 @@
       new PropertyListValue(transform_origin_builder.Pass()));
   computed_style->set_transform_origin(transform_origin);
 
-  scoped_refptr<const CSSComputedStyleData> parent_computed_style(
+  scoped_refptr<CSSComputedStyleData> parent_computed_style(
       new CSSComputedStyleData());
-  PromoteToComputedStyle(computed_style, parent_computed_style,
+  scoped_refptr<CSSComputedStyleDeclaration> parent_computed_style_declaration(
+      CreateComputedStyleDeclaration(parent_computed_style));
+
+  PromoteToComputedStyle(computed_style, parent_computed_style_declaration,
                          parent_computed_style, math::Size(), NULL);
 
   scoped_refptr<PropertyListValue> transform_origin_list =
@@ -1568,9 +1718,12 @@
       new PropertyListValue(transform_origin_builder.Pass()));
   computed_style->set_transform_origin(transform_origin);
 
-  scoped_refptr<const CSSComputedStyleData> parent_computed_style(
+  scoped_refptr<CSSComputedStyleData> parent_computed_style(
       new CSSComputedStyleData());
-  PromoteToComputedStyle(computed_style, parent_computed_style,
+  scoped_refptr<CSSComputedStyleDeclaration> parent_computed_style_declaration(
+      CreateComputedStyleDeclaration(parent_computed_style));
+
+  PromoteToComputedStyle(computed_style, parent_computed_style_declaration,
                          parent_computed_style, math::Size(), NULL);
 
   scoped_refptr<PropertyListValue> transform_origin_list =
@@ -1614,7 +1767,10 @@
   scoped_refptr<CSSComputedStyleData> parent_computed_style(
       new CSSComputedStyleData());
   parent_computed_style->set_font_size(new LengthValue(100, kPixelsUnit));
-  PromoteToComputedStyle(computed_style, parent_computed_style,
+  scoped_refptr<CSSComputedStyleDeclaration> parent_computed_style_declaration(
+      CreateComputedStyleDeclaration(parent_computed_style));
+
+  PromoteToComputedStyle(computed_style, parent_computed_style_declaration,
                          parent_computed_style, math::Size(), NULL);
 
   scoped_refptr<TransformFunctionListValue> computed_transform =
@@ -1631,5 +1787,238 @@
   EXPECT_EQ(kPixelsUnit, computed_function->offset_as_length()->unit());
 }
 
+TEST(PromoteToComputedStyle,
+     InheritedAnimatablePropertyShouldAlwaysBeDeclared) {
+  scoped_refptr<CSSComputedStyleData> computed_style(
+      new CSSComputedStyleData());
+
+  scoped_refptr<CSSComputedStyleData> parent_computed_style(
+      new CSSComputedStyleData());
+  parent_computed_style->set_color(RGBAColorValue::GetAqua());
+  scoped_refptr<CSSComputedStyleDeclaration> parent_computed_style_declaration(
+      CreateComputedStyleDeclaration(parent_computed_style));
+
+  // Verify that we're testing an inherited and animatable property.
+  ASSERT_TRUE(GetPropertyInheritance(kColorProperty) &&
+              GetPropertyAnimatable(kColorProperty));
+
+  // For each inherited, animatable property, the property value should be set
+  // to inherited if it is not already declared in PromoteToComputedStyle().
+  // This causes the value to be  explicitly set within the CSSComputedStyleData
+  // and ensures that the original value will be available for transitions
+  // (which need to know the before and after state of the property) even when
+  // the property is inherited from a parent that has changed.
+  PromoteToComputedStyle(computed_style, parent_computed_style_declaration,
+                         parent_computed_style, math::Size(), NULL);
+
+  // Verify that the color is declared in the child even though it was not
+  // explicitly declared.
+  ASSERT_TRUE(computed_style->IsDeclared(kColorProperty));
+}
+
+TEST(PromoteToComputedStyle,
+     DeclaredPropertiesInheritedFromParentShouldRemainValidWhenSetToSameValue) {
+  scoped_refptr<CSSComputedStyleData> computed_style(
+      new CSSComputedStyleData());
+
+  scoped_refptr<CSSComputedStyleData> parent_computed_style(
+      new CSSComputedStyleData());
+  parent_computed_style->set_color(
+      new RGBAColorValue(uint8(10), uint8(10), uint8(10), uint8(10)));
+  scoped_refptr<CSSComputedStyleDeclaration> parent_computed_style_declaration(
+      CreateComputedStyleDeclaration(parent_computed_style));
+
+  // Verify that we're testing an inherited and animatable property.
+  ASSERT_TRUE(GetPropertyInheritance(kColorProperty) &&
+              GetPropertyAnimatable(kColorProperty));
+
+  PromoteToComputedStyle(computed_style, parent_computed_style_declaration,
+                         parent_computed_style, math::Size(), NULL);
+
+  // Verify that the declared properties inherited from the parent are valid.
+  ASSERT_TRUE(computed_style->AreDeclaredPropertiesInheritedFromParentValid());
+
+  parent_computed_style = new CSSComputedStyleData();
+  parent_computed_style->set_color(
+      new RGBAColorValue(uint8(10), uint8(10), uint8(10), uint8(10)));
+  parent_computed_style_declaration->SetData(parent_computed_style);
+
+  // Verify that the declared properties inherited from the parent are still
+  // valid.
+  ASSERT_TRUE(computed_style->AreDeclaredPropertiesInheritedFromParentValid());
+}
+
+TEST(PromoteToComputedStyle,
+     InheritedAnimatablePropertyShouldRetainValueAfterParentValueChanges) {
+  scoped_refptr<CSSComputedStyleData> computed_style(
+      new CSSComputedStyleData());
+
+  scoped_refptr<CSSComputedStyleData> parent_computed_style(
+      new CSSComputedStyleData());
+  parent_computed_style->set_color(RGBAColorValue::GetAqua());
+  scoped_refptr<CSSComputedStyleDeclaration> parent_computed_style_declaration(
+      CreateComputedStyleDeclaration(parent_computed_style));
+
+  // Verify that we're testing an inherited and animatable property.
+  ASSERT_TRUE(GetPropertyInheritance(kColorProperty) &&
+              GetPropertyAnimatable(kColorProperty));
+
+  PromoteToComputedStyle(computed_style, parent_computed_style_declaration,
+                         parent_computed_style, math::Size(), NULL);
+
+  // Verify that the child's color is Aqua and matches the parent's color.
+  EXPECT_EQ(RGBAColorValue::GetAqua(), computed_style->color());
+  EXPECT_EQ(parent_computed_style->color(), computed_style->color());
+
+  // Verify that the declared properties inherited from the parent are valid.
+  ASSERT_TRUE(computed_style->AreDeclaredPropertiesInheritedFromParentValid());
+
+  parent_computed_style = new CSSComputedStyleData();
+  parent_computed_style->set_color(RGBAColorValue::GetNavy());
+  parent_computed_style_declaration->SetData(parent_computed_style);
+
+  // Verify that the color is still Aqua but that it no longer matches the
+  // parent's color.
+  EXPECT_EQ(RGBAColorValue::GetAqua(), computed_style->color());
+  EXPECT_NE(parent_computed_style->color(), computed_style->color());
+
+  // Verify that the declared properties inherited from the parent are no
+  // longer valid.
+  ASSERT_FALSE(computed_style->AreDeclaredPropertiesInheritedFromParentValid());
+}
+
+TEST(UpdateInheritedData,
+     UpdateInheritedDataShouldFixInheritedDataAfterItIsAdded) {
+  scoped_refptr<CSSComputedStyleData> grandparent_computed_style(
+      new CSSComputedStyleData());
+  scoped_refptr<CSSComputedStyleDeclaration>
+      grandparent_computed_style_declaration(
+          CreateComputedStyleDeclaration(grandparent_computed_style));
+
+  scoped_refptr<CSSComputedStyleData> parent_computed_style(
+      new CSSComputedStyleData());
+  // The parent should initially have the default value of normal.
+  EXPECT_EQ(FontStyleValue::GetNormal(), parent_computed_style->font_style());
+
+  PromoteToComputedStyle(parent_computed_style,
+                         grandparent_computed_style_declaration,
+                         grandparent_computed_style, math::Size(), NULL);
+  // The parent should still have the default value of normal.
+  EXPECT_EQ(FontStyleValue::GetNormal(), parent_computed_style->font_style());
+
+  scoped_refptr<CSSComputedStyleDeclaration> parent_computed_style_declaration(
+      CreateComputedStyleDeclaration(parent_computed_style));
+  scoped_refptr<CSSComputedStyleData> computed_style(
+      new CSSComputedStyleData());
+
+  PromoteToComputedStyle(computed_style, parent_computed_style_declaration,
+                         grandparent_computed_style, math::Size(), NULL);
+
+  // The child should have the default value of normal.
+  EXPECT_EQ(FontStyleValue::GetNormal(), computed_style->font_style());
+
+  grandparent_computed_style = new CSSComputedStyleData();
+  grandparent_computed_style->set_font_style(FontStyleValue::GetOblique());
+  grandparent_computed_style_declaration->SetData(grandparent_computed_style);
+
+  // Even though the grandparent has changed, the child should have the original
+  // default value of normal until UpdateInheritedData() is called.
+  EXPECT_EQ(FontStyleValue::GetNormal(), computed_style->font_style());
+  parent_computed_style_declaration->UpdateInheritedData();
+
+  // Now that UpdateInheritedData() has been called, the child should have the
+  // new inherited value of oblique.
+  EXPECT_EQ(FontStyleValue::GetOblique(), computed_style->font_style());
+}
+
+TEST(UpdateInheritedData,
+     UpdateInheritedDataShouldFixInheritedDataAfterItIsRemoved) {
+  scoped_refptr<CSSComputedStyleData> grandparent_computed_style(
+      new CSSComputedStyleData());
+  grandparent_computed_style->set_font_style(FontStyleValue::GetItalic());
+  scoped_refptr<CSSComputedStyleDeclaration>
+      grandparent_computed_style_declaration(
+          CreateComputedStyleDeclaration(grandparent_computed_style));
+
+  scoped_refptr<CSSComputedStyleData> parent_computed_style(
+      new CSSComputedStyleData());
+  // The parent should initially have the default value of normal.
+  EXPECT_EQ(FontStyleValue::GetNormal(), parent_computed_style->font_style());
+
+  PromoteToComputedStyle(parent_computed_style,
+                         grandparent_computed_style_declaration,
+                         grandparent_computed_style, math::Size(), NULL);
+  // The parent should now have the inherited value of italic.
+  EXPECT_EQ(FontStyleValue::GetItalic(), parent_computed_style->font_style());
+
+  scoped_refptr<CSSComputedStyleDeclaration> parent_computed_style_declaration(
+      CreateComputedStyleDeclaration(parent_computed_style));
+  scoped_refptr<CSSComputedStyleData> computed_style(
+      new CSSComputedStyleData());
+
+  PromoteToComputedStyle(computed_style, parent_computed_style_declaration,
+                         grandparent_computed_style, math::Size(), NULL);
+
+  // The child should have the inherited value of italic.
+  EXPECT_EQ(FontStyleValue::GetItalic(), computed_style->font_style());
+
+  grandparent_computed_style = new CSSComputedStyleData();
+  grandparent_computed_style_declaration->SetData(grandparent_computed_style);
+
+  // Even though the grandparent has changed, the child should have the original
+  // inherited value of italic until UpdateInheritedData() is called.
+  EXPECT_EQ(FontStyleValue::GetItalic(), computed_style->font_style());
+  parent_computed_style_declaration->UpdateInheritedData();
+
+  // Now that UpdateInheritedData() has been called, the child should have the
+  // default value of normal.
+  EXPECT_EQ(FontStyleValue::GetNormal(), computed_style->font_style());
+}
+
+TEST(UpdateInheritedData,
+     UpdateInheritedDataShouldFixInheritedDataAfterItChanges) {
+  scoped_refptr<CSSComputedStyleData> grandparent_computed_style(
+      new CSSComputedStyleData());
+  grandparent_computed_style->set_font_style(FontStyleValue::GetItalic());
+  scoped_refptr<CSSComputedStyleDeclaration>
+      grandparent_computed_style_declaration(
+          CreateComputedStyleDeclaration(grandparent_computed_style));
+
+  scoped_refptr<CSSComputedStyleData> parent_computed_style(
+      new CSSComputedStyleData());
+  // The parent should initially have the default value of normal.
+  EXPECT_EQ(FontStyleValue::GetNormal(), parent_computed_style->font_style());
+
+  PromoteToComputedStyle(parent_computed_style,
+                         grandparent_computed_style_declaration,
+                         grandparent_computed_style, math::Size(), NULL);
+  // The parent should now have the inherited value of italic.
+  EXPECT_EQ(FontStyleValue::GetItalic(), parent_computed_style->font_style());
+
+  scoped_refptr<CSSComputedStyleDeclaration> parent_computed_style_declaration(
+      CreateComputedStyleDeclaration(parent_computed_style));
+  scoped_refptr<CSSComputedStyleData> computed_style(
+      new CSSComputedStyleData());
+
+  PromoteToComputedStyle(computed_style, parent_computed_style_declaration,
+                         grandparent_computed_style, math::Size(), NULL);
+
+  // The child should have the inherited value of italic.
+  EXPECT_EQ(FontStyleValue::GetItalic(), computed_style->font_style());
+
+  grandparent_computed_style = new CSSComputedStyleData();
+  grandparent_computed_style->set_font_style(FontStyleValue::GetOblique());
+  grandparent_computed_style_declaration->SetData(grandparent_computed_style);
+
+  // Even though the grandparent has changed, the child should have the original
+  // inherited value of italic until UpdateInheritedData() is called.
+  EXPECT_EQ(FontStyleValue::GetItalic(), computed_style->font_style());
+  parent_computed_style_declaration->UpdateInheritedData();
+
+  // Now that UpdateInheritedData() has been called, the child should have the
+  // new inherited value of oblique.
+  EXPECT_EQ(FontStyleValue::GetOblique(), computed_style->font_style());
+}
+
 }  // namespace cssom
 }  // namespace cobalt
diff --git a/src/cobalt/cssom/css_computed_style_data.cc b/src/cobalt/cssom/css_computed_style_data.cc
index c2a4689..590ea05 100644
--- a/src/cobalt/cssom/css_computed_style_data.cc
+++ b/src/cobalt/cssom/css_computed_style_data.cc
@@ -20,6 +20,7 @@
 
 #include "base/lazy_instance.h"
 #include "base/string_util.h"
+#include "cobalt/cssom/css_computed_style_declaration.h"
 #include "cobalt/cssom/keyword_value.h"
 #include "cobalt/cssom/length_value.h"
 
@@ -62,7 +63,9 @@
 }
 
 CSSComputedStyleData::CSSComputedStyleData()
-    : has_inherited_properties_(false) {}
+    : has_declared_inherited_properties_(false) {}
+
+CSSComputedStyleData::~CSSComputedStyleData() {}
 
 unsigned int CSSComputedStyleData::length() const {
   // Computed style declarations have all known longhand properties.
@@ -79,12 +82,18 @@
   DCHECK_GT(key, kNoneProperty);
   DCHECK_LE(key, kMaxLonghandPropertyKey);
 
+  // If the property's value is explicitly declared, then simply return it.
   if (declared_properties_[key]) {
     return declared_property_values_.find(key)->second;
   }
-  if (ancestor_computed_style_ &&
-      GetPropertyInheritance(key) == kInheritedYes) {
-    return ancestor_computed_style_->GetPropertyValueReference(key);
+
+  // Otherwise, if the property is inherited and the parent has inherited
+  // properties, then retrieve the parent's value for the property.
+  if (parent_computed_style_declaration_ &&
+      GetPropertyInheritance(key) == kInheritedYes &&
+      parent_computed_style_declaration_->HasInheritedProperties()) {
+    return parent_computed_style_declaration_
+        ->GetInheritedPropertyValueReference(key);
   }
 
   // For the root element, which has no parent element, the inherited value is
@@ -270,8 +279,18 @@
   if (value) {
     declared_properties_.set(key, true);
     declared_property_values_[key] = value;
-    has_inherited_properties_ = has_inherited_properties_ ||
-                                GetPropertyInheritance(key) == kInheritedYes;
+    // Only set |has_declared_inherited_properties_| if the property is
+    // inherited and the the value isn't explicitly set to "inherit". If it is
+    // set to "inherit", then the value is simply a copy of the parent's value,
+    // which doesn't necessitate the node being included in the inheritance
+    // tree, as it doesn't provide new information.
+    // NOTE: Declaring a value of "inherit" on an inherited property is used for
+    // transitions, which need to know the original value of the property (which
+    // would otherwise be lost when the parent changed).
+    has_declared_inherited_properties_ =
+        has_declared_inherited_properties_ ||
+        (GetPropertyInheritance(key) == kInheritedYes &&
+         value != KeywordValue::GetInherit());
   } else if (declared_properties_[key]) {
     declared_properties_.set(key, false);
     declared_property_values_.erase(key);
@@ -281,7 +300,10 @@
 void CSSComputedStyleData::AssignFrom(const CSSComputedStyleData& rhs) {
   declared_properties_ = rhs.declared_properties_;
   declared_property_values_ = rhs.declared_property_values_;
-  has_inherited_properties_ = rhs.has_inherited_properties_;
+  has_declared_inherited_properties_ = rhs.has_declared_inherited_properties_;
+  declared_properties_inherited_from_parent_ =
+      rhs.declared_properties_inherited_from_parent_;
+  parent_computed_style_declaration_ = rhs.parent_computed_style_declaration_;
 }
 
 std::string CSSComputedStyleData::SerializeCSSDeclarationBlock() const {
@@ -305,18 +327,84 @@
   return serialized_text;
 }
 
-void CSSComputedStyleData::SetParentComputedStyle(
-    const scoped_refptr<const CSSComputedStyleData>& parent_computed_style) {
-  if (parent_computed_style->has_inherited_properties_) {
-    ancestor_computed_style_ = parent_computed_style;
-  } else {
-    // If the parent style does not have any inherited properties, we will never
-    // need to refer to it for inherited properties, so we refer to the parent
-    // style's ancestor instead. This gives the number of ancestor dereferences
-    // needed to find the value of an inherited property an upper bound equal to
-    // the total number of inheritable properties.
-    ancestor_computed_style_ = parent_computed_style->ancestor_computed_style_;
+void CSSComputedStyleData::AddDeclaredPropertyInheritedFromParent(
+    PropertyKey key) {
+  declared_properties_inherited_from_parent_.push_back(key);
+}
+
+bool CSSComputedStyleData::AreDeclaredPropertiesInheritedFromParentValid()
+    const {
+  // If there are no declared properties inherited from the parent, then it's
+  // impossible for them to be invalid.
+  if (declared_properties_inherited_from_parent_.size() == 0) {
+    return true;
   }
+
+  if (!parent_computed_style_declaration_) {
+    return false;
+  }
+
+  const scoped_refptr<const CSSComputedStyleData>& parent_computed_style_data =
+      parent_computed_style_declaration_->data();
+  if (!parent_computed_style_data) {
+    return false;
+  }
+
+  // Verify that the parent's data is valid.
+  DCHECK(parent_computed_style_data
+             ->AreDeclaredPropertiesInheritedFromParentValid());
+
+  // Walk the declared properties inherited from the parent. They're invalid if
+  // any no longer match the parent's value.
+  for (PropertyKeyVector::const_iterator iter =
+           declared_properties_inherited_from_parent_.begin();
+       iter != declared_properties_inherited_from_parent_.end(); ++iter) {
+    if (!GetPropertyValueReference(*iter)->Equals(
+            *parent_computed_style_data->GetPropertyValueReference(*iter))) {
+      return false;
+    }
+  }
+  return true;
+}
+
+bool CSSComputedStyleData::DoDeclaredPropertiesMatch(
+    const scoped_refptr<const CSSComputedStyleData>& other) const {
+  // If the bitsets don't match, then there's no need to check the values;
+  // the declared properties are guaranteed to not match.
+  if (declared_properties_ != other->declared_properties_) {
+    return false;
+  }
+
+  // Verify that the same number of declared property values exist within the
+  // two CSSComputedStyleData objects. This should be guaranteed by the
+  // bitsets matching.
+  DCHECK_EQ(declared_property_values_.size(),
+            other->declared_property_values_.size());
+
+  // Walk the two lists of declared property values looking for any keys or
+  // values that don't match.
+  PropertyValues::const_iterator iter1 = declared_property_values_.begin();
+  PropertyValues::const_iterator iter2 =
+      other->declared_property_values_.begin();
+  for (; iter1 != declared_property_values_.end(); ++iter1, ++iter2) {
+    if (iter1->first != iter2->first ||
+        !iter1->second->Equals(*iter2->second)) {
+      return false;
+    }
+  }
+
+  return true;
+}
+
+void CSSComputedStyleData::SetParentComputedStyleDeclaration(
+    const scoped_refptr<CSSComputedStyleDeclaration>&
+        parent_computed_style_declaration) {
+  parent_computed_style_declaration_ = parent_computed_style_declaration;
+}
+
+const scoped_refptr<CSSComputedStyleDeclaration>&
+CSSComputedStyleData::GetParentComputedStyleDeclaration() const {
+  return parent_computed_style_declaration_;
 }
 
 }  // namespace cssom
diff --git a/src/cobalt/cssom/css_computed_style_data.h b/src/cobalt/cssom/css_computed_style_data.h
index 80c93b7..e303868 100644
--- a/src/cobalt/cssom/css_computed_style_data.h
+++ b/src/cobalt/cssom/css_computed_style_data.h
@@ -31,12 +31,11 @@
 namespace cobalt {
 namespace cssom {
 
+class CSSComputedStyleDeclaration;
+
 // CSSComputedStyleData which has PropertyValue type properties only used
-// internally and it is not exposed to JavaScript.  It derives from
-// RefCountedThreadSafe instead of RefCounted so that it can be passed forward
-// to another thread for animating before rendering a scene.
-class CSSComputedStyleData
-    : public base::RefCountedThreadSafe<CSSComputedStyleData> {
+// internally and it is not exposed to JavaScript.
+class CSSComputedStyleData : public base::RefCounted<CSSComputedStyleData> {
  public:
   // This class provides the ability to determine whether the properties of two
   // CSSComputedStyleData objects match for a given set of property keys.
@@ -61,6 +60,7 @@
                          16, std::equal_to<PropertyKey> > PropertyValues;
 
   CSSComputedStyleData();
+  ~CSSComputedStyleData();
 
   // The length attribute must return the number of CSS declarations in the
   // declarations.
@@ -661,25 +661,54 @@
 
   void AssignFrom(const CSSComputedStyleData& rhs);
 
+  // This returns the result of serializing a CSS declaration block.
+  // The current implementation does not handle shorthands.
+  //   https://www.w3.org/TR/cssom/#serialize-a-css-declaration-block
+  std::string SerializeCSSDeclarationBlock() const;
+
   // Returns true if the property is explicitly declared in this style, as
   // opposed to implicitly inheriting from its parent or the initial value.
   bool IsDeclared(const PropertyKey key) const {
     return declared_properties_[key];
   }
 
-  // This returns the result of serializing a CSS declaration block.
-  // The current implementation does not handle shorthands.
-  //   https://www.w3.org/TR/cssom/#serialize-a-css-declaration-block
-  std::string SerializeCSSDeclarationBlock() const;
+  // Whether or not any inherited properties have been declared.
+  // NOTE: Inherited properties that are set to a value "inherit" do not impact
+  // this flag, as they will have the same value as the parent and can be
+  // skipped by descendants retrieving their inherited value without impacting
+  // the returned value.
+  bool has_declared_inherited_properties() const {
+    return has_declared_inherited_properties_;
+  }
 
-  // Set the parent computed style for tracking inherited properties.
-  void SetParentComputedStyle(
-      const scoped_refptr<const CSSComputedStyleData>& parent_computed_style);
+  // Adds a declared property that was inherited from the parent to an
+  // internal list. This facilitates tracking of whether or not a value that was
+  // initially set to a parent's value continues to match the parent's value.
+  void AddDeclaredPropertyInheritedFromParent(PropertyKey key);
+
+  // Returns true if all of the declared properties that were inherited from the
+  // parent are still valid. They become invalid when the parent's value
+  // changes.
+  bool AreDeclaredPropertiesInheritedFromParentValid() const;
 
   PropertyValues* declared_property_values() {
     return &declared_property_values_;
   }
 
+  // Returns whether or not the declared properties in the passed in
+  // CSSComputedStyleData matches those declared within this one.
+  bool DoDeclaredPropertiesMatch(
+      const scoped_refptr<const CSSComputedStyleData>& other) const;
+
+  // Set the parent computed style for tracking inherited properties.
+  void SetParentComputedStyleDeclaration(
+      const scoped_refptr<CSSComputedStyleDeclaration>&
+          parent_computed_style_declaration);
+
+  // Returns the parent computed style used for tracking inherited properties.
+  const scoped_refptr<CSSComputedStyleDeclaration>&
+  GetParentComputedStyleDeclaration() const;
+
  private:
   // Helper function that returns the computed value if the initial property
   // value is not computed or returns the initial value if it is computed.
@@ -691,10 +720,25 @@
   LonghandPropertiesBitset declared_properties_;
   PropertyValues declared_property_values_;
 
-  scoped_refptr<const CSSComputedStyleData> ancestor_computed_style_;
+  // True if this style has any inherited properties declared.
+  // NOTE: Inherited properties that are set to a value "inherit" do not impact
+  // this flag, as they will have the same value as the parent and can be
+  // skipped by descendants retrieving their inherited value without impacting
+  // the returned value.
+  bool has_declared_inherited_properties_;
 
-  // True if this style has any inheritable properties defined.
-  bool has_inherited_properties_;
+  // Properties that were initially set to a value of "inherit" before being
+  // updated with the parent's value. This is used to determine whether the
+  // declared properties inherited from the parent have subsequently changed.
+  PropertyKeyVector declared_properties_inherited_from_parent_;
+
+  // The parent used for inherited properties.
+  // NOTE: The parent is a CSSComputedStyleDeclaration, rather than a
+  // CSSComputedStyleData, in order to allow for the replacement of ancestor
+  // CSSComputedStyleData objects without requiring all of its descendants to
+  // also be replaced. The descendant's inherited property value will instead
+  // dynamically update.
+  scoped_refptr<CSSComputedStyleDeclaration> parent_computed_style_declaration_;
 };
 
 }  // namespace cssom
diff --git a/src/cobalt/cssom/css_computed_style_data_test.cc b/src/cobalt/cssom/css_computed_style_data_test.cc
index 3dd7f71..2fcb1ea 100644
--- a/src/cobalt/cssom/css_computed_style_data_test.cc
+++ b/src/cobalt/cssom/css_computed_style_data_test.cc
@@ -1128,5 +1128,68 @@
   EXPECT_EQ(KeywordValue::GetBlock(), style->display());
 }
 
+TEST(CSSComputedStyleDataTest,
+     DoDeclaredPropertiesMatchWorksWithUnequalNumberOfDeclaredProperties) {
+  scoped_refptr<CSSComputedStyleData> style1 = new CSSComputedStyleData();
+  style1->set_font_size(new LengthValue(50, kPixelsUnit));
+
+  scoped_refptr<CSSComputedStyleData> style2 = new CSSComputedStyleData();
+
+  ASSERT_FALSE(style1->DoDeclaredPropertiesMatch(style2));
+  ASSERT_FALSE(style2->DoDeclaredPropertiesMatch(style1));
+}
+
+TEST(CSSComputedStyleDataTest,
+     DoDeclaredPropertiesMatchWorksWithSingleUnequalProperty) {
+  scoped_refptr<CSSComputedStyleData> style1 = new CSSComputedStyleData();
+  style1->set_font_size(new LengthValue(50, kPixelsUnit));
+
+  scoped_refptr<CSSComputedStyleData> style2 = new CSSComputedStyleData();
+  style2->set_font_size(new LengthValue(30, kPixelsUnit));
+
+  ASSERT_FALSE(style1->DoDeclaredPropertiesMatch(style2));
+  ASSERT_FALSE(style2->DoDeclaredPropertiesMatch(style1));
+}
+
+TEST(CSSComputedStyleDataTest,
+     DoDeclaredPropertiesMatchWorksWithSingleEqualProperty) {
+  scoped_refptr<CSSComputedStyleData> style1 = new CSSComputedStyleData();
+  style1->set_font_size(new LengthValue(50, kPixelsUnit));
+
+  scoped_refptr<CSSComputedStyleData> style2 = new CSSComputedStyleData();
+  style2->set_font_size(new LengthValue(50, kPixelsUnit));
+
+  ASSERT_TRUE(style1->DoDeclaredPropertiesMatch(style2));
+  ASSERT_TRUE(style2->DoDeclaredPropertiesMatch(style1));
+}
+
+TEST(CSSComputedStyleDataTest,
+     DoDeclaredPropertiesMatchWorksWithMultipleUnequalProperties) {
+  scoped_refptr<CSSComputedStyleData> style1 = new CSSComputedStyleData();
+  style1->set_position(KeywordValue::GetAbsolute());
+  style1->set_font_size(new LengthValue(50, kPixelsUnit));
+
+  scoped_refptr<CSSComputedStyleData> style2 = new CSSComputedStyleData();
+  style2->set_position(KeywordValue::GetAbsolute());
+  style2->set_font_size(new LengthValue(30, kPixelsUnit));
+
+  ASSERT_FALSE(style1->DoDeclaredPropertiesMatch(style2));
+  ASSERT_FALSE(style2->DoDeclaredPropertiesMatch(style1));
+}
+
+TEST(CSSComputedStyleDataTest,
+     DoDeclaredPropertiesMatchWorksWithMultipleEqualProperty) {
+  scoped_refptr<CSSComputedStyleData> style1 = new CSSComputedStyleData();
+  style1->set_position(KeywordValue::GetAbsolute());
+  style1->set_font_size(new LengthValue(50, kPixelsUnit));
+
+  scoped_refptr<CSSComputedStyleData> style2 = new CSSComputedStyleData();
+  style2->set_position(KeywordValue::GetAbsolute());
+  style2->set_font_size(new LengthValue(50, kPixelsUnit));
+
+  ASSERT_TRUE(style1->DoDeclaredPropertiesMatch(style2));
+  ASSERT_TRUE(style2->DoDeclaredPropertiesMatch(style1));
+}
+
 }  // namespace cssom
 }  // namespace cobalt
diff --git a/src/cobalt/cssom/css_computed_style_declaration.cc b/src/cobalt/cssom/css_computed_style_declaration.cc
index 0d477a4..11c7dbb 100644
--- a/src/cobalt/cssom/css_computed_style_declaration.cc
+++ b/src/cobalt/cssom/css_computed_style_declaration.cc
@@ -72,5 +72,45 @@
                            exception_state);
 }
 
+void CSSComputedStyleDeclaration::SetData(
+    const scoped_refptr<const CSSComputedStyleData>& data) {
+  data_ = data;
+  // After setting |data_|, |data_with_inherited_properties_| needs to be
+  // updated. It may have changed.
+  UpdateInheritedData();
+}
+
+void CSSComputedStyleDeclaration::UpdateInheritedData() {
+  if (!data_) {
+    // If there's no data, then there can be no data with inherited properties.
+    data_with_inherited_properties_ = NULL;
+  } else if (data_->has_declared_inherited_properties()) {
+    // Otherwise, if the data has inherited properties, then it's also the first
+    // data with inherited properties.
+    data_with_inherited_properties_ = data_;
+  } else {
+    // Otherwise, |data_with_inherited_properties_| should be set to the parent
+    // computed style's |data_with_inherited_properties_|. This is because the
+    // updates always cascade down the tree and the parent is guaranteed to
+    // have already been updated when the child is updated.
+    const scoped_refptr<CSSComputedStyleDeclaration>&
+        parent_computed_style_declaration =
+            data_->GetParentComputedStyleDeclaration();
+    if (parent_computed_style_declaration) {
+      data_with_inherited_properties_ =
+          parent_computed_style_declaration->data_with_inherited_properties_;
+    } else {
+      data_with_inherited_properties_ = NULL;
+    }
+  }
+}
+
+const scoped_refptr<PropertyValue>&
+CSSComputedStyleDeclaration::GetInheritedPropertyValueReference(
+    PropertyKey key) const {
+  DCHECK(data_with_inherited_properties_);
+  return data_with_inherited_properties_->GetPropertyValueReference(key);
+}
+
 }  // namespace cssom
 }  // namespace cobalt
diff --git a/src/cobalt/cssom/css_computed_style_declaration.h b/src/cobalt/cssom/css_computed_style_declaration.h
index 36a4947..e166979 100644
--- a/src/cobalt/cssom/css_computed_style_declaration.h
+++ b/src/cobalt/cssom/css_computed_style_declaration.h
@@ -58,10 +58,23 @@
   const scoped_refptr<const CSSComputedStyleData>& data() const {
     return data_;
   }
-  void set_data(const scoped_refptr<const CSSComputedStyleData>& data) {
-    data_ = data;
+  void SetData(const scoped_refptr<const CSSComputedStyleData>& data);
+
+  // Updates the pointer to the nearest CSSComputedStyleData ancestor,
+  // inclusive, which has inherited properties declared.
+  void UpdateInheritedData();
+
+  // Returns whether or not this object or any ancestors have inherited
+  // properties declared.
+  bool HasInheritedProperties() const {
+    return data_with_inherited_properties_ != NULL;
   }
 
+  // Returns the reference to the property value for an inherited property.
+  // Should only be called if HasInheritedProperties() returns true.
+  const scoped_refptr<PropertyValue>& GetInheritedPropertyValueReference(
+      PropertyKey key) const;
+
   const scoped_refptr<const web_animations::AnimationSet>& animations() const {
     return animations_;
   }
@@ -74,9 +87,15 @@
   // From CSSStyleDeclaration.
   std::string GetDeclaredPropertyValueStringByKey(
       const PropertyKey key) const OVERRIDE;
+
+  // The CSSComputedStyleData owned by this object.
   scoped_refptr<const CSSComputedStyleData> data_;
 
-  // All animation that applies to  the above computed style.
+  // The nearest CSSComputedStyleData ancestor, inclusive, which has inherited
+  // properties declared.
+  scoped_refptr<const CSSComputedStyleData> data_with_inherited_properties_;
+
+  // All animation that applies to the above computed style.
   scoped_refptr<const web_animations::AnimationSet> animations_;
 
   DISALLOW_COPY_AND_ASSIGN(CSSComputedStyleDeclaration);
diff --git a/src/cobalt/cssom/css_transition_set.cc b/src/cobalt/cssom/css_transition_set.cc
index 4292a94..6edeae6 100644
--- a/src/cobalt/cssom/css_transition_set.cc
+++ b/src/cobalt/cssom/css_transition_set.cc
@@ -84,10 +84,8 @@
   // For each animatable property, check to see if there are any transitions
   // assigned to it.  If so, check to see if there are any existing transitions
   // that must be updated, otherwise introduce new transitions.
-  const AnimatablePropertyList& animatable_properties =
-      GetAnimatableProperties();
-  for (AnimatablePropertyList::const_iterator iter =
-           animatable_properties.begin();
+  const PropertyKeyVector& animatable_properties = GetAnimatableProperties();
+  for (PropertyKeyVector::const_iterator iter = animatable_properties.begin();
        iter != animatable_properties.end(); ++iter) {
     UpdateTransitionForProperty(
         *iter, current_time, source_computed_style.GetPropertyValue(*iter),
@@ -216,7 +214,7 @@
 
       if (existing_transition &&
           current_time < existing_transition->EndTime()) {
-        // A transition is already ocurring, so we handle this case a bit
+        // A transition is already occurring, so we handle this case a bit
         // differently depending on if we're reversing the previous transition
         // or starting a completely different one.
         transitions_.UpdateTransitionForProperty(
diff --git a/src/cobalt/cssom/cssom.gyp b/src/cobalt/cssom/cssom.gyp
index ab8852c..63be9ea 100644
--- a/src/cobalt/cssom/cssom.gyp
+++ b/src/cobalt/cssom/cssom.gyp
@@ -227,6 +227,7 @@
       ],
       'dependencies': [
         '<(DEPTH)/cobalt/base/base.gyp:base',
+        '<(DEPTH)/cobalt/dom/dom_exception.gyp:dom_exception',
         '<(DEPTH)/cobalt/math/math.gyp:math',
         '<(DEPTH)/googleurl/googleurl.gyp:googleurl',
         'embed_resources_as_header_files',
diff --git a/src/cobalt/cssom/property_definitions.cc b/src/cobalt/cssom/property_definitions.cc
index d589181..8133992 100644
--- a/src/cobalt/cssom/property_definitions.cc
+++ b/src/cobalt/cssom/property_definitions.cc
@@ -49,6 +49,7 @@
       : name(NULL),
         inherited(kInheritedNo),
         animatable(kAnimatableNo),
+        impacts_child_declared_style(kImpactsChildDeclaredStyleNo),
         impacts_box_generation(kImpactsBoxGenerationNo),
         impacts_box_sizes(kImpactsBoxSizesNo),
         impacts_box_cross_references(kImpactsBoxCrossReferencesNo) {}
@@ -56,6 +57,7 @@
   const char* name;
   Inherited inherited;
   Animatable animatable;
+  ImpactsChildDeclaredStyle impacts_child_declared_style;
   ImpactsBoxGeneration impacts_box_generation;
   ImpactsBoxSizes impacts_box_sizes;
   ImpactsBoxCrossReferences impacts_box_cross_references;
@@ -68,11 +70,14 @@
 
   std::vector<PropertyKey> lexicographical_longhand_keys;
   PropertyDefinition properties[kMaxEveryPropertyKey + 1];
-  AnimatablePropertyList animatable_properties;
+  PropertyKeyVector animatable_properties;
+  PropertyKeyVector inherited_animatable_properties;
 
   void SetPropertyDefinition(
       PropertyKey key, const char* name, Inherited inherited,
-      Animatable animatable, ImpactsBoxGeneration impacts_box_generation,
+      Animatable animatable,
+      ImpactsChildDeclaredStyle impacts_child_declared_style,
+      ImpactsBoxGeneration impacts_box_generation,
       ImpactsBoxSizes impacts_box_sizes,
       ImpactsBoxCrossReferences impacts_box_cross_references,
       const scoped_refptr<PropertyValue>& initial_value) {
@@ -82,6 +87,7 @@
     definition.name = name;
     definition.inherited = inherited;
     definition.animatable = animatable;
+    definition.impacts_child_declared_style = impacts_child_declared_style;
     definition.impacts_box_generation = impacts_box_generation;
     definition.impacts_box_sizes = impacts_box_sizes;
     definition.impacts_box_cross_references = impacts_box_cross_references;
@@ -151,61 +157,65 @@
 
 NonTrivialGlobalVariables::NonTrivialGlobalVariables() {
   // https://www.w3.org/TR/css3-animations/#animation-delay-property
-  SetPropertyDefinition(kAnimationDelayProperty, "animation-delay",
-                        kInheritedNo, kAnimatableNo, kImpactsBoxGenerationNo,
-                        kImpactsBoxSizesNo, kImpactsBoxCrossReferencesNo,
-                        CreateTimeListWithZeroSeconds());
+  SetPropertyDefinition(
+      kAnimationDelayProperty, "animation-delay", kInheritedNo, kAnimatableNo,
+      kImpactsChildDeclaredStyleNo, kImpactsBoxGenerationNo, kImpactsBoxSizesNo,
+      kImpactsBoxCrossReferencesNo, CreateTimeListWithZeroSeconds());
 
   // https://www.w3.org/TR/css3-animations/#animation-direction-property
   SetPropertyDefinition(
       kAnimationDirectionProperty, "animation-direction", kInheritedNo,
-      kAnimatableNo, kImpactsBoxGenerationNo, kImpactsBoxSizesNo,
-      kImpactsBoxCrossReferencesNo,
+      kAnimatableNo, kImpactsChildDeclaredStyleNo, kImpactsBoxGenerationNo,
+      kImpactsBoxSizesNo, kImpactsBoxCrossReferencesNo,
       CreateSinglePropertyListWithValue(KeywordValue::GetNormal()));
 
   // https://www.w3.org/TR/css3-animations/#animation-duration-property
   SetPropertyDefinition(kAnimationDurationProperty, "animation-duration",
-                        kInheritedNo, kAnimatableNo, kImpactsBoxGenerationNo,
+                        kInheritedNo, kAnimatableNo,
+                        kImpactsChildDeclaredStyleNo, kImpactsBoxGenerationNo,
                         kImpactsBoxSizesNo, kImpactsBoxCrossReferencesNo,
                         CreateTimeListWithZeroSeconds());
 
   // https://www.w3.org/TR/css3-animations/#animation-fill-mode-property
   SetPropertyDefinition(
       kAnimationFillModeProperty, "animation-fill-mode", kInheritedNo,
-      kAnimatableNo, kImpactsBoxGenerationNo, kImpactsBoxSizesNo,
-      kImpactsBoxCrossReferencesNo,
+      kAnimatableNo, kImpactsChildDeclaredStyleNo, kImpactsBoxGenerationNo,
+      kImpactsBoxSizesNo, kImpactsBoxCrossReferencesNo,
       CreateSinglePropertyListWithValue(KeywordValue::GetNone()));
 
   // https://www.w3.org/TR/css3-animations/#animation-iteration-count-property
   SetPropertyDefinition(
       kAnimationIterationCountProperty, "animation-iteration-count",
-      kInheritedNo, kAnimatableNo, kImpactsBoxGenerationNo, kImpactsBoxSizesNo,
-      kImpactsBoxCrossReferencesNo,
+      kInheritedNo, kAnimatableNo, kImpactsChildDeclaredStyleNo,
+      kImpactsBoxGenerationNo, kImpactsBoxSizesNo, kImpactsBoxCrossReferencesNo,
       CreateSinglePropertyListWithValue(new NumberValue(1.0f)));
 
   // https://www.w3.org/TR/css3-animations/#animation-name-property
   SetPropertyDefinition(
       kAnimationNameProperty, "animation-name", kInheritedNo, kAnimatableNo,
-      kImpactsBoxGenerationNo, kImpactsBoxSizesNo, kImpactsBoxCrossReferencesNo,
+      kImpactsChildDeclaredStyleNo, kImpactsBoxGenerationNo, kImpactsBoxSizesNo,
+      kImpactsBoxCrossReferencesNo,
       CreateSinglePropertyListWithValue(KeywordValue::GetNone()));
 
   // https://www.w3.org/TR/css3-animations/#animation-timing-function-property
-  SetPropertyDefinition(kAnimationTimingFunctionProperty,
-                        "animation-timing-function", kInheritedNo,
-                        kAnimatableNo, kImpactsBoxGenerationNo,
-                        kImpactsBoxSizesNo, kImpactsBoxCrossReferencesNo,
-                        CreateTransitionTimingFunctionListWithEase());
+  SetPropertyDefinition(
+      kAnimationTimingFunctionProperty, "animation-timing-function",
+      kInheritedNo, kAnimatableNo, kImpactsChildDeclaredStyleNo,
+      kImpactsBoxGenerationNo, kImpactsBoxSizesNo, kImpactsBoxCrossReferencesNo,
+      CreateTransitionTimingFunctionListWithEase());
 
   // https://www.w3.org/TR/css3-background/#the-background-color
   SetPropertyDefinition(kBackgroundColorProperty, "background-color",
-                        kInheritedNo, kAnimatableYes, kImpactsBoxGenerationNo,
+                        kInheritedNo, kAnimatableYes,
+                        kImpactsChildDeclaredStyleNo, kImpactsBoxGenerationNo,
                         kImpactsBoxSizesNo, kImpactsBoxCrossReferencesNo,
                         new RGBAColorValue(0x00000000));
 
   // https://www.w3.org/TR/css3-background/#background-image
   SetPropertyDefinition(
       kBackgroundImageProperty, "background-image", kInheritedNo, kAnimatableNo,
-      kImpactsBoxGenerationNo, kImpactsBoxSizesNo, kImpactsBoxCrossReferencesNo,
+      kImpactsChildDeclaredStyleNo, kImpactsBoxGenerationNo, kImpactsBoxSizesNo,
+      kImpactsBoxCrossReferencesNo,
       CreateSinglePropertyListWithValue(KeywordValue::GetNone()));
 
   // https://www.w3.org/TR/css3-background/#the-background-position
@@ -219,7 +229,8 @@
   scoped_refptr<PropertyListValue> background_position_list(
       new PropertyListValue(background_position_builder.Pass()));
   SetPropertyDefinition(kBackgroundPositionProperty, "background-position",
-                        kInheritedNo, kAnimatableNo, kImpactsBoxGenerationNo,
+                        kInheritedNo, kAnimatableNo,
+                        kImpactsChildDeclaredStyleNo, kImpactsBoxGenerationNo,
                         kImpactsBoxSizesNo, kImpactsBoxCrossReferencesNo,
                         background_position_list);
 
@@ -234,10 +245,10 @@
   background_repeat_builder->push_back(KeywordValue::GetRepeat());
   scoped_refptr<PropertyListValue> background_repeat_list(
       new PropertyListValue(background_repeat_builder.Pass()));
-  SetPropertyDefinition(kBackgroundRepeatProperty, "background-repeat",
-                        kInheritedNo, kAnimatableNo, kImpactsBoxGenerationNo,
-                        kImpactsBoxSizesNo, kImpactsBoxCrossReferencesNo,
-                        background_repeat_list);
+  SetPropertyDefinition(
+      kBackgroundRepeatProperty, "background-repeat", kInheritedNo,
+      kAnimatableNo, kImpactsChildDeclaredStyleNo, kImpactsBoxGenerationNo,
+      kImpactsBoxSizesNo, kImpactsBoxCrossReferencesNo, background_repeat_list);
 
   // The first value gives the width of the corresponding image, and the second
   // value gives its height. If only one value is given, the second is assumed
@@ -250,52 +261,59 @@
   background_size_builder->push_back(KeywordValue::GetAuto());
   scoped_refptr<PropertyListValue> background_size_list(
       new PropertyListValue(background_size_builder.Pass()));
-  SetPropertyDefinition(kBackgroundSizeProperty, "background-size",
-                        kInheritedNo, kAnimatableNo, kImpactsBoxGenerationNo,
-                        kImpactsBoxSizesNo, kImpactsBoxCrossReferencesNo,
-                        background_size_list);
+  SetPropertyDefinition(
+      kBackgroundSizeProperty, "background-size", kInheritedNo, kAnimatableNo,
+      kImpactsChildDeclaredStyleNo, kImpactsBoxGenerationNo, kImpactsBoxSizesNo,
+      kImpactsBoxCrossReferencesNo, background_size_list);
 
   // This sets the foreground color of the border specified by the border-style
   // property.
   //   https://www.w3.org/TR/css3-background/#border-color
-  SetPropertyDefinition(kBorderTopColorProperty, "border-top-color",
-                        kInheritedNo, kAnimatableYes, kImpactsBoxGenerationNo,
-                        kImpactsBoxSizesNo, kImpactsBoxCrossReferencesNo,
-                        KeywordValue::GetCurrentColor());
+  SetPropertyDefinition(
+      kBorderTopColorProperty, "border-top-color", kInheritedNo, kAnimatableYes,
+      kImpactsChildDeclaredStyleNo, kImpactsBoxGenerationNo, kImpactsBoxSizesNo,
+      kImpactsBoxCrossReferencesNo, KeywordValue::GetCurrentColor());
 
   SetPropertyDefinition(kBorderRightColorProperty, "border-right-color",
-                        kInheritedNo, kAnimatableYes, kImpactsBoxGenerationNo,
+                        kInheritedNo, kAnimatableYes,
+                        kImpactsChildDeclaredStyleNo, kImpactsBoxGenerationNo,
                         kImpactsBoxSizesNo, kImpactsBoxCrossReferencesNo,
                         KeywordValue::GetCurrentColor());
 
   SetPropertyDefinition(kBorderBottomColorProperty, "border-bottom-color",
-                        kInheritedNo, kAnimatableYes, kImpactsBoxGenerationNo,
+                        kInheritedNo, kAnimatableYes,
+                        kImpactsChildDeclaredStyleNo, kImpactsBoxGenerationNo,
                         kImpactsBoxSizesNo, kImpactsBoxCrossReferencesNo,
                         KeywordValue::GetCurrentColor());
 
   SetPropertyDefinition(kBorderLeftColorProperty, "border-left-color",
-                        kInheritedNo, kAnimatableYes, kImpactsBoxGenerationNo,
+                        kInheritedNo, kAnimatableYes,
+                        kImpactsChildDeclaredStyleNo, kImpactsBoxGenerationNo,
                         kImpactsBoxSizesNo, kImpactsBoxCrossReferencesNo,
                         KeywordValue::GetCurrentColor());
 
   //   https://www.w3.org/TR/css3-background/#border-style
   SetPropertyDefinition(kBorderTopStyleProperty, "border-top-style",
-                        kInheritedNo, kAnimatableNo, kImpactsBoxGenerationNo,
+                        kInheritedNo, kAnimatableNo,
+                        kImpactsChildDeclaredStyleNo, kImpactsBoxGenerationNo,
                         kImpactsBoxSizesYes, kImpactsBoxCrossReferencesNo,
                         KeywordValue::GetNone());
 
   SetPropertyDefinition(kBorderRightStyleProperty, "border-right-style",
-                        kInheritedNo, kAnimatableNo, kImpactsBoxGenerationNo,
+                        kInheritedNo, kAnimatableNo,
+                        kImpactsChildDeclaredStyleNo, kImpactsBoxGenerationNo,
                         kImpactsBoxSizesYes, kImpactsBoxCrossReferencesNo,
                         KeywordValue::GetNone());
 
   SetPropertyDefinition(kBorderBottomStyleProperty, "border-bottom-style",
-                        kInheritedNo, kAnimatableNo, kImpactsBoxGenerationNo,
+                        kInheritedNo, kAnimatableNo,
+                        kImpactsChildDeclaredStyleNo, kImpactsBoxGenerationNo,
                         kImpactsBoxSizesYes, kImpactsBoxCrossReferencesNo,
                         KeywordValue::GetNone());
 
   SetPropertyDefinition(kBorderLeftStyleProperty, "border-left-style",
-                        kInheritedNo, kAnimatableNo, kImpactsBoxGenerationNo,
+                        kInheritedNo, kAnimatableNo,
+                        kImpactsChildDeclaredStyleNo, kImpactsBoxGenerationNo,
                         kImpactsBoxSizesYes, kImpactsBoxCrossReferencesNo,
                         KeywordValue::GetNone());
 
@@ -305,259 +323,290 @@
   // 'medium' font size is 17 px or less.
   //   https://www.w3.org/TR/css3-background/#border-width
   SetPropertyDefinition(kBorderTopWidthProperty, "border-top-width",
-                        kInheritedNo, kAnimatableNo, kImpactsBoxGenerationNo,
+                        kInheritedNo, kAnimatableNo,
+                        kImpactsChildDeclaredStyleNo, kImpactsBoxGenerationNo,
                         kImpactsBoxSizesYes, kImpactsBoxCrossReferencesNo,
                         new LengthValue(3, kPixelsUnit));
 
   SetPropertyDefinition(kBorderRightWidthProperty, "border-right-width",
-                        kInheritedNo, kAnimatableNo, kImpactsBoxGenerationNo,
+                        kInheritedNo, kAnimatableNo,
+                        kImpactsChildDeclaredStyleNo, kImpactsBoxGenerationNo,
                         kImpactsBoxSizesYes, kImpactsBoxCrossReferencesNo,
                         new LengthValue(3, kPixelsUnit));
 
   SetPropertyDefinition(kBorderBottomWidthProperty, "border-bottom-width",
-                        kInheritedNo, kAnimatableNo, kImpactsBoxGenerationNo,
+                        kInheritedNo, kAnimatableNo,
+                        kImpactsChildDeclaredStyleNo, kImpactsBoxGenerationNo,
                         kImpactsBoxSizesYes, kImpactsBoxCrossReferencesNo,
                         new LengthValue(3, kPixelsUnit));
 
   SetPropertyDefinition(kBorderLeftWidthProperty, "border-left-width",
-                        kInheritedNo, kAnimatableNo, kImpactsBoxGenerationNo,
+                        kInheritedNo, kAnimatableNo,
+                        kImpactsChildDeclaredStyleNo, kImpactsBoxGenerationNo,
                         kImpactsBoxSizesYes, kImpactsBoxCrossReferencesNo,
                         new LengthValue(3, kPixelsUnit));
 
   // Cobalt only support a single length value that applies to all borders.
   //   https://www.w3.org/TR/css3-background/#the-border-radius
-  SetPropertyDefinition(kBorderRadiusProperty, "border-radius", kInheritedNo,
-                        kAnimatableNo, kImpactsBoxGenerationNo,
-                        kImpactsBoxSizesNo, kImpactsBoxCrossReferencesNo,
-                        new LengthValue(0, kPixelsUnit));
+  SetPropertyDefinition(
+      kBorderRadiusProperty, "border-radius", kInheritedNo, kAnimatableNo,
+      kImpactsChildDeclaredStyleNo, kImpactsBoxGenerationNo, kImpactsBoxSizesNo,
+      kImpactsBoxCrossReferencesNo, new LengthValue(0, kPixelsUnit));
 
   // https://www.w3.org/TR/CSS2/visuren.html#propdef-bottom
   SetPropertyDefinition(kBottomProperty, "bottom", kInheritedNo, kAnimatableNo,
-                        kImpactsBoxGenerationNo, kImpactsBoxSizesYes,
-                        kImpactsBoxCrossReferencesNo, KeywordValue::GetAuto());
+                        kImpactsChildDeclaredStyleNo, kImpactsBoxGenerationNo,
+                        kImpactsBoxSizesYes, kImpactsBoxCrossReferencesNo,
+                        KeywordValue::GetAuto());
 
   // https://www.w3.org/TR/css3-background/#the-box-shadow
   SetPropertyDefinition(kBoxShadowProperty, "box-shadow", kInheritedNo,
-                        kAnimatableNo, kImpactsBoxGenerationNo,
-                        kImpactsBoxSizesNo, kImpactsBoxCrossReferencesNo,
-                        KeywordValue::GetNone());
+                        kAnimatableNo, kImpactsChildDeclaredStyleNo,
+                        kImpactsBoxGenerationNo, kImpactsBoxSizesNo,
+                        kImpactsBoxCrossReferencesNo, KeywordValue::GetNone());
 
   // Opaque black in Chromium and Cobalt.
   //   https://www.w3.org/TR/css3-color/#foreground
   SetPropertyDefinition(kColorProperty, "color", kInheritedYes, kAnimatableYes,
-                        kImpactsBoxGenerationYes, kImpactsBoxSizesNo,
-                        kImpactsBoxCrossReferencesNo,
+                        kImpactsChildDeclaredStyleYes, kImpactsBoxGenerationYes,
+                        kImpactsBoxSizesNo, kImpactsBoxCrossReferencesNo,
                         new RGBAColorValue(0x000000ff));
 
   // https://www.w3.org/TR/CSS21/generate.html#content
   SetPropertyDefinition(kContentProperty, "content", kInheritedNo,
-                        kAnimatableNo, kImpactsBoxGenerationYes,
-                        kImpactsBoxSizesNo, kImpactsBoxCrossReferencesNo,
+                        kAnimatableNo, kImpactsChildDeclaredStyleNo,
+                        kImpactsBoxGenerationYes, kImpactsBoxSizesNo,
+                        kImpactsBoxCrossReferencesNo,
                         KeywordValue::GetNormal());
 
   // https://www.w3.org/TR/CSS21/visuren.html#display-prop
   SetPropertyDefinition(kDisplayProperty, "display", kInheritedNo,
-                        kAnimatableNo, kImpactsBoxGenerationYes,
-                        kImpactsBoxSizesNo, kImpactsBoxCrossReferencesNo,
+                        kAnimatableNo, kImpactsChildDeclaredStyleNo,
+                        kImpactsBoxGenerationYes, kImpactsBoxSizesNo,
+                        kImpactsBoxCrossReferencesNo,
                         KeywordValue::GetInline());
 
   // Varies by platform in Chromium, Roboto in Cobalt.
   //   https://www.w3.org/TR/css3-fonts/#font-family-prop
   SetPropertyDefinition(
       kFontFamilyProperty, "font-family", kInheritedYes, kAnimatableNo,
-      kImpactsBoxGenerationYes, kImpactsBoxSizesYes,
-      kImpactsBoxCrossReferencesNo,
+      kImpactsChildDeclaredStyleNo, kImpactsBoxGenerationYes,
+      kImpactsBoxSizesYes, kImpactsBoxCrossReferencesNo,
       CreateSinglePropertyListWithValue(new StringValue("Roboto")));
 
   // "medium" translates to 16px in Chromium.
   // Cobalt does not support keyword sizes, so we simply hardcode 16px.
   //   https://www.w3.org/TR/css3-fonts/#font-size-prop
   SetPropertyDefinition(kFontSizeProperty, "font-size", kInheritedYes,
-                        kAnimatableNo, kImpactsBoxGenerationYes,
-                        kImpactsBoxSizesYes, kImpactsBoxCrossReferencesNo,
+                        kAnimatableNo, kImpactsChildDeclaredStyleYes,
+                        kImpactsBoxGenerationYes, kImpactsBoxSizesYes,
+                        kImpactsBoxCrossReferencesNo,
                         new LengthValue(16, kPixelsUnit));
 
   // https://www.w3.org/TR/css3-fonts/#font-style-prop
   SetPropertyDefinition(kFontStyleProperty, "font-style", kInheritedYes,
-                        kAnimatableNo, kImpactsBoxGenerationYes,
-                        kImpactsBoxSizesYes, kImpactsBoxCrossReferencesNo,
+                        kAnimatableNo, kImpactsChildDeclaredStyleNo,
+                        kImpactsBoxGenerationYes, kImpactsBoxSizesYes,
+                        kImpactsBoxCrossReferencesNo,
                         FontStyleValue::GetNormal());
 
   // https://www.w3.org/TR/css3-fonts/#font-weight-prop
   SetPropertyDefinition(kFontWeightProperty, "font-weight", kInheritedYes,
-                        kAnimatableNo, kImpactsBoxGenerationYes,
-                        kImpactsBoxSizesYes, kImpactsBoxCrossReferencesNo,
+                        kAnimatableNo, kImpactsChildDeclaredStyleNo,
+                        kImpactsBoxGenerationYes, kImpactsBoxSizesYes,
+                        kImpactsBoxCrossReferencesNo,
                         FontWeightValue::GetNormalAka400());
 
   // https://www.w3.org/TR/CSS21/visudet.html#the-height-property
   SetPropertyDefinition(kHeightProperty, "height", kInheritedNo, kAnimatableNo,
-                        kImpactsBoxGenerationNo, kImpactsBoxSizesYes,
-                        kImpactsBoxCrossReferencesNo, KeywordValue::GetAuto());
+                        kImpactsChildDeclaredStyleYes, kImpactsBoxGenerationNo,
+                        kImpactsBoxSizesYes, kImpactsBoxCrossReferencesNo,
+                        KeywordValue::GetAuto());
 
   // https://www.w3.org/TR/CSS2/visuren.html#propdef-left
   SetPropertyDefinition(kLeftProperty, "left", kInheritedNo, kAnimatableNo,
-                        kImpactsBoxGenerationNo, kImpactsBoxSizesYes,
-                        kImpactsBoxCrossReferencesNo, KeywordValue::GetAuto());
+                        kImpactsChildDeclaredStyleNo, kImpactsBoxGenerationNo,
+                        kImpactsBoxSizesYes, kImpactsBoxCrossReferencesNo,
+                        KeywordValue::GetAuto());
 
   // https://www.w3.org/TR/CSS21/visudet.html#line-height
   SetPropertyDefinition(kLineHeightProperty, "line-height", kInheritedYes,
-                        kAnimatableNo, kImpactsBoxGenerationNo,
-                        kImpactsBoxSizesYes, kImpactsBoxCrossReferencesNo,
+                        kAnimatableNo, kImpactsChildDeclaredStyleNo,
+                        kImpactsBoxGenerationNo, kImpactsBoxSizesYes,
+                        kImpactsBoxCrossReferencesNo,
                         KeywordValue::GetNormal());
 
   // https://www.w3.org/TR/CSS21/box.html#margin-properties
   SetPropertyDefinition(kMarginBottomProperty, "margin-bottom", kInheritedNo,
-                        kAnimatableNo, kImpactsBoxGenerationNo,
-                        kImpactsBoxSizesYes, kImpactsBoxCrossReferencesNo,
+                        kAnimatableNo, kImpactsChildDeclaredStyleNo,
+                        kImpactsBoxGenerationNo, kImpactsBoxSizesYes,
+                        kImpactsBoxCrossReferencesNo,
                         new LengthValue(0, kPixelsUnit));
 
   // https://www.w3.org/TR/CSS21/box.html#margin-properties
   SetPropertyDefinition(kMarginLeftProperty, "margin-left", kInheritedNo,
-                        kAnimatableNo, kImpactsBoxGenerationNo,
-                        kImpactsBoxSizesYes, kImpactsBoxCrossReferencesNo,
+                        kAnimatableNo, kImpactsChildDeclaredStyleNo,
+                        kImpactsBoxGenerationNo, kImpactsBoxSizesYes,
+                        kImpactsBoxCrossReferencesNo,
                         new LengthValue(0, kPixelsUnit));
 
   // https://www.w3.org/TR/CSS21/box.html#margin-properties
   SetPropertyDefinition(kMarginRightProperty, "margin-right", kInheritedNo,
-                        kAnimatableNo, kImpactsBoxGenerationNo,
-                        kImpactsBoxSizesYes, kImpactsBoxCrossReferencesNo,
+                        kAnimatableNo, kImpactsChildDeclaredStyleNo,
+                        kImpactsBoxGenerationNo, kImpactsBoxSizesYes,
+                        kImpactsBoxCrossReferencesNo,
                         new LengthValue(0, kPixelsUnit));
 
   // https://www.w3.org/TR/CSS21/box.html#margin-properties
   SetPropertyDefinition(kMarginTopProperty, "margin-top", kInheritedNo,
-                        kAnimatableNo, kImpactsBoxGenerationNo,
-                        kImpactsBoxSizesYes, kImpactsBoxCrossReferencesNo,
+                        kAnimatableNo, kImpactsChildDeclaredStyleNo,
+                        kImpactsBoxGenerationNo, kImpactsBoxSizesYes,
+                        kImpactsBoxCrossReferencesNo,
                         new LengthValue(0, kPixelsUnit));
 
   // https://www.w3.org/TR/CSS2/visudet.html#propdef-max-height
   SetPropertyDefinition(kMaxHeightProperty, "max-height", kInheritedNo,
-                        kAnimatableNo, kImpactsBoxGenerationNo,
-                        kImpactsBoxSizesYes, kImpactsBoxCrossReferencesNo,
-                        KeywordValue::GetNone());
+                        kAnimatableNo, kImpactsChildDeclaredStyleNo,
+                        kImpactsBoxGenerationNo, kImpactsBoxSizesYes,
+                        kImpactsBoxCrossReferencesNo, KeywordValue::GetNone());
 
   // https://www.w3.org/TR/CSS2/visudet.html#propdef-max-width
   SetPropertyDefinition(kMaxWidthProperty, "max-width", kInheritedNo,
-                        kAnimatableNo, kImpactsBoxGenerationNo,
-                        kImpactsBoxSizesYes, kImpactsBoxCrossReferencesNo,
-                        KeywordValue::GetNone());
+                        kAnimatableNo, kImpactsChildDeclaredStyleNo,
+                        kImpactsBoxGenerationNo, kImpactsBoxSizesYes,
+                        kImpactsBoxCrossReferencesNo, KeywordValue::GetNone());
 
   // https://www.w3.org/TR/CSS2/visudet.html#propdef-min-height
   SetPropertyDefinition(kMinHeightProperty, "min-height", kInheritedNo,
-                        kAnimatableNo, kImpactsBoxGenerationNo,
-                        kImpactsBoxSizesYes, kImpactsBoxCrossReferencesNo,
+                        kAnimatableNo, kImpactsChildDeclaredStyleNo,
+                        kImpactsBoxGenerationNo, kImpactsBoxSizesYes,
+                        kImpactsBoxCrossReferencesNo,
                         new LengthValue(0, kPixelsUnit));
 
   // https://www.w3.org/TR/CSS2/visudet.html#propdef-min-width
   SetPropertyDefinition(kMinWidthProperty, "min-width", kInheritedNo,
-                        kAnimatableNo, kImpactsBoxGenerationNo,
-                        kImpactsBoxSizesYes, kImpactsBoxCrossReferencesNo,
+                        kAnimatableNo, kImpactsChildDeclaredStyleNo,
+                        kImpactsBoxGenerationNo, kImpactsBoxSizesYes,
+                        kImpactsBoxCrossReferencesNo,
                         new LengthValue(0, kPixelsUnit));
 
   // https://www.w3.org/TR/css3-color/#opacity
   SetPropertyDefinition(kOpacityProperty, "opacity", kInheritedNo,
-                        kAnimatableYes, kImpactsBoxGenerationNo,
-                        kImpactsBoxSizesNo, kImpactsBoxCrossReferencesYes,
-                        new NumberValue(1.0f));
+                        kAnimatableYes, kImpactsChildDeclaredStyleNo,
+                        kImpactsBoxGenerationNo, kImpactsBoxSizesNo,
+                        kImpactsBoxCrossReferencesYes, new NumberValue(1.0f));
 
   // https://www.w3.org/TR/css-overflow-3/#overflow-properties
   SetPropertyDefinition(kOverflowProperty, "overflow", kInheritedNo,
-                        kAnimatableNo, kImpactsBoxGenerationNo,
-                        kImpactsBoxSizesNo, kImpactsBoxCrossReferencesNo,
+                        kAnimatableNo, kImpactsChildDeclaredStyleNo,
+                        kImpactsBoxGenerationNo, kImpactsBoxSizesYes,
+                        kImpactsBoxCrossReferencesNo,
                         KeywordValue::GetVisible());
 
   // https://www.w3.org/TR/css-text-3/#overflow-wrap
   SetPropertyDefinition(kOverflowWrapProperty, "overflow-wrap", kInheritedYes,
-                        kAnimatableNo, kImpactsBoxGenerationNo,
-                        kImpactsBoxSizesYes, kImpactsBoxCrossReferencesNo,
+                        kAnimatableNo, kImpactsChildDeclaredStyleNo,
+                        kImpactsBoxGenerationNo, kImpactsBoxSizesYes,
+                        kImpactsBoxCrossReferencesNo,
                         KeywordValue::GetNormal());
 
   // https://www.w3.org/TR/CSS21/box.html#padding-properties
   SetPropertyDefinition(kPaddingBottomProperty, "padding-bottom", kInheritedNo,
-                        kAnimatableNo, kImpactsBoxGenerationNo,
-                        kImpactsBoxSizesYes, kImpactsBoxCrossReferencesNo,
+                        kAnimatableNo, kImpactsChildDeclaredStyleNo,
+                        kImpactsBoxGenerationNo, kImpactsBoxSizesYes,
+                        kImpactsBoxCrossReferencesNo,
                         new LengthValue(0, kPixelsUnit));
 
   // https://www.w3.org/TR/CSS21/box.html#padding-properties
   SetPropertyDefinition(kPaddingLeftProperty, "padding-left", kInheritedNo,
-                        kAnimatableNo, kImpactsBoxGenerationNo,
-                        kImpactsBoxSizesYes, kImpactsBoxCrossReferencesNo,
+                        kAnimatableNo, kImpactsChildDeclaredStyleNo,
+                        kImpactsBoxGenerationNo, kImpactsBoxSizesYes,
+                        kImpactsBoxCrossReferencesNo,
                         new LengthValue(0, kPixelsUnit));
 
   // https://www.w3.org/TR/CSS21/box.html#padding-properties
   SetPropertyDefinition(kPaddingRightProperty, "padding-right", kInheritedNo,
-                        kAnimatableNo, kImpactsBoxGenerationNo,
-                        kImpactsBoxSizesYes, kImpactsBoxCrossReferencesNo,
+                        kAnimatableNo, kImpactsChildDeclaredStyleNo,
+                        kImpactsBoxGenerationNo, kImpactsBoxSizesYes,
+                        kImpactsBoxCrossReferencesNo,
                         new LengthValue(0, kPixelsUnit));
 
   // https://www.w3.org/TR/CSS21/box.html#padding-properties
   SetPropertyDefinition(kPaddingTopProperty, "padding-top", kInheritedNo,
-                        kAnimatableNo, kImpactsBoxGenerationNo,
-                        kImpactsBoxSizesYes, kImpactsBoxCrossReferencesNo,
+                        kAnimatableNo, kImpactsChildDeclaredStyleNo,
+                        kImpactsBoxGenerationNo, kImpactsBoxSizesYes,
+                        kImpactsBoxCrossReferencesNo,
                         new LengthValue(0, kPixelsUnit));
 
   // https://www.w3.org/TR/css3-positioning/#position-property
   SetPropertyDefinition(kPositionProperty, "position", kInheritedNo,
-                        kAnimatableNo, kImpactsBoxGenerationYes,
-                        kImpactsBoxSizesYes, kImpactsBoxCrossReferencesYes,
+                        kAnimatableNo, kImpactsChildDeclaredStyleNo,
+                        kImpactsBoxGenerationYes, kImpactsBoxSizesYes,
+                        kImpactsBoxCrossReferencesYes,
                         KeywordValue::GetStatic());
 
   // https://www.w3.org/TR/CSS2/visuren.html#propdef-right
   SetPropertyDefinition(kRightProperty, "right", kInheritedNo, kAnimatableNo,
-                        kImpactsBoxGenerationNo, kImpactsBoxSizesYes,
-                        kImpactsBoxCrossReferencesNo, KeywordValue::GetAuto());
+                        kImpactsChildDeclaredStyleNo, kImpactsBoxGenerationNo,
+                        kImpactsBoxSizesYes, kImpactsBoxCrossReferencesNo,
+                        KeywordValue::GetAuto());
 
   //   https://www.w3.org/TR/css-text-3/#text-align
   SetPropertyDefinition(kTextAlignProperty, "text-align", kInheritedYes,
-                        kAnimatableNo, kImpactsBoxGenerationNo,
-                        kImpactsBoxSizesYes, kImpactsBoxCrossReferencesNo,
-                        KeywordValue::GetStart());
+                        kAnimatableNo, kImpactsChildDeclaredStyleNo,
+                        kImpactsBoxGenerationNo, kImpactsBoxSizesYes,
+                        kImpactsBoxCrossReferencesNo, KeywordValue::GetStart());
 
   //   https://www.w3.org/TR/css-text-decor-3/#text-decoration-color
   SetPropertyDefinition(kTextDecorationColorProperty, "text-decoration-color",
-                        kInheritedNo, kAnimatableYes, kImpactsBoxGenerationNo,
+                        kInheritedNo, kAnimatableYes,
+                        kImpactsChildDeclaredStyleNo, kImpactsBoxGenerationNo,
                         kImpactsBoxSizesNo, kImpactsBoxCrossReferencesNo,
                         KeywordValue::GetCurrentColor());
 
   //   https://www.w3.org/TR/css-text-decor-3/#text-decoration-line
   SetPropertyDefinition(kTextDecorationLineProperty, "text-decoration-line",
-                        kInheritedNo, kAnimatableNo, kImpactsBoxGenerationNo,
+                        kInheritedNo, kAnimatableNo,
+                        kImpactsChildDeclaredStyleNo, kImpactsBoxGenerationNo,
                         kImpactsBoxSizesNo, kImpactsBoxCrossReferencesNo,
                         KeywordValue::GetNone());
 
   // https://www.w3.org/TR/CSS21/text.html#propdef-text-indent
   SetPropertyDefinition(kTextIndentProperty, "text-indent", kInheritedYes,
-                        kAnimatableNo, kImpactsBoxGenerationNo,
-                        kImpactsBoxSizesYes, kImpactsBoxCrossReferencesNo,
+                        kAnimatableNo, kImpactsChildDeclaredStyleNo,
+                        kImpactsBoxGenerationNo, kImpactsBoxSizesYes,
+                        kImpactsBoxCrossReferencesNo,
                         new LengthValue(0, kPixelsUnit));
 
   // https://www.w3.org/TR/css3-ui/#propdef-text-overflow
   SetPropertyDefinition(kTextOverflowProperty, "text-overflow", kInheritedNo,
-                        kAnimatableNo, kImpactsBoxGenerationNo,
-                        kImpactsBoxSizesNo, kImpactsBoxCrossReferencesNo,
-                        KeywordValue::GetClip());
+                        kAnimatableNo, kImpactsChildDeclaredStyleNo,
+                        kImpactsBoxGenerationNo, kImpactsBoxSizesYes,
+                        kImpactsBoxCrossReferencesNo, KeywordValue::GetClip());
 
   // https://www.w3.org/TR/css-text-decor-3/#text-shadow-property
   SetPropertyDefinition(kTextShadowProperty, "text-shadow", kInheritedYes,
-                        kAnimatableNo, kImpactsBoxGenerationNo,
-                        kImpactsBoxSizesNo, kImpactsBoxCrossReferencesNo,
-                        KeywordValue::GetNone());
+                        kAnimatableNo, kImpactsChildDeclaredStyleNo,
+                        kImpactsBoxGenerationNo, kImpactsBoxSizesNo,
+                        kImpactsBoxCrossReferencesNo, KeywordValue::GetNone());
 
   // https://www.w3.org/TR/css3-text/#text-transform-property
   SetPropertyDefinition(kTextTransformProperty, "text-transform", kInheritedYes,
-                        kAnimatableNo, kImpactsBoxGenerationYes,
-                        kImpactsBoxSizesNo, kImpactsBoxCrossReferencesNo,
-                        KeywordValue::GetNone());
+                        kAnimatableNo, kImpactsChildDeclaredStyleNo,
+                        kImpactsBoxGenerationYes, kImpactsBoxSizesNo,
+                        kImpactsBoxCrossReferencesNo, KeywordValue::GetNone());
 
   // https://www.w3.org/TR/CSS2/visuren.html#propdef-top
   SetPropertyDefinition(kTopProperty, "top", kInheritedNo, kAnimatableNo,
-                        kImpactsBoxGenerationNo, kImpactsBoxSizesYes,
-                        kImpactsBoxCrossReferencesNo, KeywordValue::GetAuto());
+                        kImpactsChildDeclaredStyleNo, kImpactsBoxGenerationNo,
+                        kImpactsBoxSizesYes, kImpactsBoxCrossReferencesNo,
+                        KeywordValue::GetAuto());
 
   // https://www.w3.org/TR/css3-transforms/#transform-property
   SetPropertyDefinition(kTransformProperty, "transform", kInheritedNo,
-                        kAnimatableYes, kImpactsBoxGenerationNo,
-                        kImpactsBoxSizesYes, kImpactsBoxCrossReferencesYes,
-                        KeywordValue::GetNone());
+                        kAnimatableYes, kImpactsChildDeclaredStyleNo,
+                        kImpactsBoxGenerationNo, kImpactsBoxSizesYes,
+                        kImpactsBoxCrossReferencesYes, KeywordValue::GetNone());
 
   // https://www.w3.org/TR/css3-transforms/#propdef-transform-origin
   scoped_ptr<PropertyListValue::Builder> transform_origin_builder(
@@ -568,88 +617,94 @@
   transform_origin_builder->push_back(new LengthValue(0.0f, kPixelsUnit));
   scoped_refptr<PropertyListValue> transform_origin_list(
       new PropertyListValue(transform_origin_builder.Pass()));
-  SetPropertyDefinition(kTransformOriginProperty, "transform-origin",
-                        kInheritedNo, kAnimatableNo, kImpactsBoxGenerationNo,
-                        kImpactsBoxSizesNo, kImpactsBoxCrossReferencesNo,
-                        transform_origin_list);
+  SetPropertyDefinition(
+      kTransformOriginProperty, "transform-origin", kInheritedNo, kAnimatableNo,
+      kImpactsChildDeclaredStyleNo, kImpactsBoxGenerationNo, kImpactsBoxSizesNo,
+      kImpactsBoxCrossReferencesNo, transform_origin_list);
 
   // https://www.w3.org/TR/css3-transitions/#transition-delay-property
-  SetPropertyDefinition(kTransitionDelayProperty, "transition-delay",
-                        kInheritedNo, kAnimatableNo, kImpactsBoxGenerationNo,
-                        kImpactsBoxSizesNo, kImpactsBoxCrossReferencesNo,
-                        CreateTimeListWithZeroSeconds());
+  SetPropertyDefinition(
+      kTransitionDelayProperty, "transition-delay", kInheritedNo, kAnimatableNo,
+      kImpactsChildDeclaredStyleNo, kImpactsBoxGenerationNo, kImpactsBoxSizesNo,
+      kImpactsBoxCrossReferencesNo, CreateTimeListWithZeroSeconds());
 
   // https://www.w3.org/TR/css3-transitions/#transition-duration-property
   SetPropertyDefinition(kTransitionDurationProperty, "transition-duration",
-                        kInheritedNo, kAnimatableNo, kImpactsBoxGenerationNo,
+                        kInheritedNo, kAnimatableNo,
+                        kImpactsChildDeclaredStyleNo, kImpactsBoxGenerationNo,
                         kImpactsBoxSizesNo, kImpactsBoxCrossReferencesNo,
                         CreateTimeListWithZeroSeconds());
 
   // https://www.w3.org/TR/css3-transitions/#transition-property-property
   SetPropertyDefinition(kTransitionPropertyProperty, "transition-property",
-                        kInheritedNo, kAnimatableNo, kImpactsBoxGenerationNo,
+                        kInheritedNo, kAnimatableNo,
+                        kImpactsChildDeclaredStyleNo, kImpactsBoxGenerationNo,
                         kImpactsBoxSizesNo, kImpactsBoxCrossReferencesNo,
                         CreatePropertyKeyListWithAll());
 
   // https://www.w3.org/TR/css3-transitions/#transition-timing-function-property
-  SetPropertyDefinition(kTransitionTimingFunctionProperty,
-                        "transition-timing-function", kInheritedNo,
-                        kAnimatableNo, kImpactsBoxGenerationNo,
-                        kImpactsBoxSizesNo, kImpactsBoxCrossReferencesNo,
-                        CreateTransitionTimingFunctionListWithEase());
+  SetPropertyDefinition(
+      kTransitionTimingFunctionProperty, "transition-timing-function",
+      kInheritedNo, kAnimatableNo, kImpactsChildDeclaredStyleNo,
+      kImpactsBoxGenerationNo, kImpactsBoxSizesNo, kImpactsBoxCrossReferencesNo,
+      CreateTransitionTimingFunctionListWithEase());
 
   // https://www.w3.org/TR/CSS21/visudet.html#propdef-vertical-align
-  SetPropertyDefinition(kVerticalAlignProperty, "vertical-align", kInheritedNo,
-                        kAnimatableNo, kImpactsBoxGenerationNo,
-                        kImpactsBoxSizesNo, kImpactsBoxCrossReferencesNo,
-                        KeywordValue::GetBaseline());
+  SetPropertyDefinition(
+      kVerticalAlignProperty, "vertical-align", kInheritedNo, kAnimatableNo,
+      kImpactsChildDeclaredStyleNo, kImpactsBoxGenerationNo, kImpactsBoxSizesNo,
+      kImpactsBoxCrossReferencesNo, KeywordValue::GetBaseline());
 
   // https://www.w3.org/TR/CSS21/visufx.html#propdef-visibility
-  SetPropertyDefinition(kVisibilityProperty, "visibility", kInheritedYes,
-                        kAnimatableNo, kImpactsBoxGenerationNo,
-                        kImpactsBoxSizesNo, kImpactsBoxCrossReferencesNo,
-                        KeywordValue::GetVisible());
+  SetPropertyDefinition(
+      kVisibilityProperty, "visibility", kInheritedYes, kAnimatableNo,
+      kImpactsChildDeclaredStyleNo, kImpactsBoxGenerationNo, kImpactsBoxSizesNo,
+      kImpactsBoxCrossReferencesNo, KeywordValue::GetVisible());
 
   // https://www.w3.org/TR/css3-text/#white-space-property
   SetPropertyDefinition(kWhiteSpaceProperty, "white-space", kInheritedYes,
-                        kAnimatableNo, kImpactsBoxGenerationYes,
-                        kImpactsBoxSizesYes, kImpactsBoxCrossReferencesNo,
+                        kAnimatableNo, kImpactsChildDeclaredStyleNo,
+                        kImpactsBoxGenerationYes, kImpactsBoxSizesYes,
+                        kImpactsBoxCrossReferencesNo,
                         KeywordValue::GetNormal());
 
   // https://www.w3.org/TR/CSS21/visudet.html#the-width-property
   SetPropertyDefinition(kWidthProperty, "width", kInheritedNo, kAnimatableNo,
-                        kImpactsBoxGenerationNo, kImpactsBoxSizesYes,
-                        kImpactsBoxCrossReferencesNo, KeywordValue::GetAuto());
+                        kImpactsChildDeclaredStyleYes, kImpactsBoxGenerationNo,
+                        kImpactsBoxSizesYes, kImpactsBoxCrossReferencesNo,
+                        KeywordValue::GetAuto());
 
   // https://www.w3.org/TR/CSS21/visuren.html#z-index
   SetPropertyDefinition(kZIndexProperty, "z-index", kInheritedNo, kAnimatableNo,
-                        kImpactsBoxGenerationNo, kImpactsBoxSizesNo,
-                        kImpactsBoxCrossReferencesYes, KeywordValue::GetAuto());
+                        kImpactsChildDeclaredStyleNo, kImpactsBoxGenerationNo,
+                        kImpactsBoxSizesNo, kImpactsBoxCrossReferencesYes,
+                        KeywordValue::GetAuto());
 
   // This property name can appear as a keyword for the transition-property
   // property.
   //   https://www.w3.org/TR/2013/WD-css3-transitions-20131119/#transition-property-property
   SetPropertyDefinition(kAllProperty, "all", kInheritedNo, kAnimatableNo,
-                        kImpactsBoxGenerationNo, kImpactsBoxSizesNo,
-                        kImpactsBoxCrossReferencesNo, NULL);
+                        kImpactsChildDeclaredStyleNo, kImpactsBoxGenerationNo,
+                        kImpactsBoxSizesNo, kImpactsBoxCrossReferencesNo, NULL);
 
   // This is a descriptor for @font-face at-rules.
   //   https://www.w3.org/TR/css3-fonts/#descdef-src
   SetPropertyDefinition(kSrcProperty, "src", kInheritedNo, kAnimatableNo,
-                        kImpactsBoxGenerationNo, kImpactsBoxSizesNo,
-                        kImpactsBoxCrossReferencesNo, NULL);
+                        kImpactsChildDeclaredStyleNo, kImpactsBoxGenerationNo,
+                        kImpactsBoxSizesNo, kImpactsBoxCrossReferencesNo, NULL);
 
   //   https://www.w3.org/TR/css3-fonts/#unicode-range-desc
-  SetPropertyDefinition(kUnicodeRangeProperty, "unicode-range", kInheritedNo,
-                        kAnimatableNo, kImpactsBoxGenerationNo,
-                        kImpactsBoxSizesNo, kImpactsBoxCrossReferencesNo,
-                        new UnicodeRangeValue(0, 0x10FFFF));
+  SetPropertyDefinition(
+      kUnicodeRangeProperty, "unicode-range", kInheritedNo, kAnimatableNo,
+      kImpactsChildDeclaredStyleNo, kImpactsBoxGenerationNo, kImpactsBoxSizesNo,
+      kImpactsBoxCrossReferencesNo, new UnicodeRangeValue(0, 0x10FFFF));
 
   // This is an alias for kOverflowWrap
   //   https://www.w3.org/TR/css-text-3/#overflow-wrap
   SetPropertyDefinition(kWordWrapProperty, "word-wrap", kInheritedYes,
-                        kAnimatableNo, kImpactsBoxGenerationNo,
-                        kImpactsBoxSizesYes, kImpactsBoxCrossReferencesNo,
+                        kAnimatableNo, kImpactsChildDeclaredStyleNo,
+                        kImpactsBoxGenerationNo, kImpactsBoxSizesYes,
+                        kImpactsBoxCrossReferencesNo,
                         KeywordValue::GetNormal());
 
   // Shorthand properties.
@@ -790,6 +845,9 @@
   for (int i = 0; i < kMaxEveryPropertyKey + 1; ++i) {
     if (properties[i].animatable == kAnimatableYes) {
       animatable_properties.push_back(static_cast<PropertyKey>(i));
+      if (properties[i].inherited == kInheritedYes) {
+        inherited_animatable_properties.push_back(static_cast<PropertyKey>(i));
+      }
     }
   }
 }
@@ -842,6 +900,16 @@
   return non_trivial_global_variables.Get().properties[key].animatable;
 }
 
+ImpactsChildDeclaredStyle GetPropertyImpactsChildDeclaredStyle(
+    PropertyKey key) {
+  DCHECK(!IsShorthandProperty(key));
+  DCHECK_GT(key, kNoneProperty);
+  DCHECK_LE(key, kMaxEveryPropertyKey);
+  return non_trivial_global_variables.Get()
+      .properties[key]
+      .impacts_child_declared_style;
+}
+
 ImpactsBoxGeneration GetPropertyImpactsBoxGeneration(PropertyKey key) {
   DCHECK(!IsShorthandProperty(key));
   DCHECK_GT(key, kNoneProperty);
@@ -877,10 +945,14 @@
   return non_trivial_global_variables.Get().properties[key].longhand_properties;
 }
 
-const AnimatablePropertyList& GetAnimatableProperties() {
+const PropertyKeyVector& GetAnimatableProperties() {
   return non_trivial_global_variables.Get().animatable_properties;
 }
 
+const PropertyKeyVector& GetInheritedAnimatableProperties() {
+  return non_trivial_global_variables.Get().inherited_animatable_properties;
+}
+
 PropertyKey GetLexicographicalLonghandPropertyKey(const size_t index) {
   DCHECK_LE(
       index,
diff --git a/src/cobalt/cssom/property_definitions.h b/src/cobalt/cssom/property_definitions.h
index bbaf9a3..14a1c39 100644
--- a/src/cobalt/cssom/property_definitions.h
+++ b/src/cobalt/cssom/property_definitions.h
@@ -157,16 +157,33 @@
   kAnimatableYes,
 };
 
+// Any property that is referenced when calculating the declared property values
+// of children should have this set to true.
+// NOTE: This currently occurs within CalculateComputedStyleContext.
+enum ImpactsChildDeclaredStyle {
+  kImpactsChildDeclaredStyleNo,
+  kImpactsChildDeclaredStyleYes,
+};
+
+// Any property that is referenced during box generation should have this set to
+// true.
+// NOTE: This currently occurs within BoxGenerator.
 enum ImpactsBoxGeneration {
   kImpactsBoxGenerationNo,
   kImpactsBoxGenerationYes,
 };
 
+// Any property that is referenced when updating the size of boxes should have
+// this set to true.
+// NOTE: This currently occurs within Box::UpdateSize().
 enum ImpactsBoxSizes {
   kImpactsBoxSizesNo,
   kImpactsBoxSizesYes,
 };
 
+// Any property that is referenced when generating cross references should have
+// this set to true.
+// NOTE: This currently occurs within ContainerBox::UpdateCrossReferences().
 enum ImpactsBoxCrossReferences {
   kImpactsBoxCrossReferencesNo,
   kImpactsBoxCrossReferencesYes,
@@ -183,12 +200,14 @@
 
 Inherited GetPropertyInheritance(PropertyKey key);
 Animatable GetPropertyAnimatable(PropertyKey key);
+ImpactsChildDeclaredStyle GetPropertyImpactsChildDeclaredStyle(PropertyKey key);
 ImpactsBoxGeneration GetPropertyImpactsBoxGeneration(PropertyKey key);
 ImpactsBoxSizes GetPropertyImpactsBoxSizes(PropertyKey key);
 ImpactsBoxCrossReferences GetPropertyImpactsBoxCrossReferences(PropertyKey key);
 
-typedef std::vector<PropertyKey> AnimatablePropertyList;
-const AnimatablePropertyList& GetAnimatableProperties();
+typedef std::vector<PropertyKey> PropertyKeyVector;
+const PropertyKeyVector& GetAnimatableProperties();
+const PropertyKeyVector& GetInheritedAnimatableProperties();
 
 PropertyKey GetLexicographicalLonghandPropertyKey(const size_t index);
 
@@ -203,7 +222,6 @@
 const LonghandPropertySet& ExpandShorthandProperty(PropertyKey key);
 
 typedef std::bitset<kNumLonghandProperties> LonghandPropertiesBitset;
-typedef std::vector<PropertyKey> PropertyKeyVector;
 
 }  // namespace cssom
 }  // namespace cobalt
diff --git a/src/cobalt/debug/render_overlay.cc b/src/cobalt/debug/render_overlay.cc
index 85d03b0..5a60043 100644
--- a/src/cobalt/debug/render_overlay.cc
+++ b/src/cobalt/debug/render_overlay.cc
@@ -25,7 +25,7 @@
 RenderOverlay::RenderOverlay(
     const OnRenderTreeProducedCallback& render_tree_produced_callback)
     : render_tree_produced_callback_(render_tree_produced_callback),
-      input_layout_(NULL, NULL, base::TimeDelta()) {}
+      input_layout_(NULL, base::TimeDelta()) {}
 
 void RenderOverlay::OnRenderTreeProduced(const LayoutResults& layout_results) {
   input_layout_ = layout_results;
@@ -56,10 +56,10 @@
           new render_tree::CompositionNode(builder);
 
       render_tree_produced_callback_.Run(
-          LayoutResults(combined_tree, input_layout_.animations, layout_time));
+          LayoutResults(combined_tree, layout_time));
     } else {
-      render_tree_produced_callback_.Run(LayoutResults(
-          input_layout_.render_tree, input_layout_.animations, layout_time));
+      render_tree_produced_callback_.Run(
+          LayoutResults(input_layout_.render_tree, layout_time));
     }
   }
 }
diff --git a/src/cobalt/dom/Document.idl b/src/cobalt/dom/Document.idl
index 73fa7e6..d33334d 100644
--- a/src/cobalt/dom/Document.idl
+++ b/src/cobalt/dom/Document.idl
@@ -22,6 +22,10 @@
   readonly attribute DOMString documentURI;
   readonly attribute Element? documentElement;
 
+  // Non-standard return type, should be WindowProxy.
+  // https://www.w3.org/TR/html5/single-page.html#dom-document-defaultview
+  readonly attribute Window? defaultView;
+
   HTMLCollection getElementsByTagName(DOMString localName);
   HTMLCollection getElementsByClassName(DOMString classNames);
   [NewObject] Element createElement(DOMString localName);
diff --git a/src/cobalt/dom/HTMLVideoElement.idl b/src/cobalt/dom/HTMLVideoElement.idl
index 3793eab..7f44060 100644
--- a/src/cobalt/dom/HTMLVideoElement.idl
+++ b/src/cobalt/dom/HTMLVideoElement.idl
@@ -21,4 +21,7 @@
   attribute unsigned long height;
   readonly attribute unsigned long videoWidth;
   readonly attribute unsigned long videoHeight;
+
+  // https://www.w3.org/TR/media-source/#widl-HTMLVideoElement-getVideoPlaybackQuality-VideoPlaybackQuality
+  VideoPlaybackQuality getVideoPlaybackQuality();
 };
diff --git a/src/cobalt/dom/VideoPlaybackQuality.idl b/src/cobalt/dom/VideoPlaybackQuality.idl
new file mode 100644
index 0000000..8263a07
--- /dev/null
+++ b/src/cobalt/dom/VideoPlaybackQuality.idl
@@ -0,0 +1,27 @@
+/*
+ * 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.
+ */
+
+// https://www.w3.org/TR/media-source/#idl-def-VideoPlaybackQuality
+
+interface VideoPlaybackQuality {
+  readonly attribute DOMHighResTimeStamp creationTime;
+  readonly attribute unsigned long totalVideoFrames;
+  readonly attribute unsigned long droppedVideoFrames;
+  readonly attribute unsigned long corruptedVideoFrames;
+  readonly attribute double totalFrameDelay;
+};
+
+typedef double DOMHighResTimeStamp;
diff --git a/src/cobalt/dom/document.cc b/src/cobalt/dom/document.cc
index cc586b7..0d2b543 100644
--- a/src/cobalt/dom/document.cc
+++ b/src/cobalt/dom/document.cc
@@ -53,6 +53,7 @@
 #include "cobalt/dom/node_descendants_iterator.h"
 #include "cobalt/dom/text.h"
 #include "cobalt/dom/ui_event.h"
+#include "cobalt/dom/window.h"
 
 namespace cobalt {
 namespace dom {
@@ -61,6 +62,7 @@
                    const Options& options)
     : ALLOW_THIS_IN_INITIALIZER_LIST(Node(this)),
       html_element_context_(html_element_context),
+      window_(options.window),
       implementation_(new DOMImplementation()),
       ALLOW_THIS_IN_INITIALIZER_LIST(
           style_sheets_(new cssom::StyleSheetList(this))),
@@ -81,7 +83,9 @@
       navigation_start_clock_(options.navigation_start_clock),
       ALLOW_THIS_IN_INITIALIZER_LIST(
           default_timeline_(new DocumentTimeline(this, 0))),
-      user_agent_style_sheet_(options.user_agent_style_sheet) {
+      user_agent_style_sheet_(options.user_agent_style_sheet),
+      initial_computed_style_declaration_(
+          new cssom::CSSComputedStyleDeclaration()) {
   DCHECK(options.url.is_empty() || options.url.is_valid());
 
   if (options.viewport_size) {
@@ -141,6 +145,8 @@
   return first_element_child();
 }
 
+scoped_refptr<Window> Document::default_view() const { return window_; }
+
 std::string Document::title() const {
   const char kTitleTag[] = "title";
   if (head()) {
@@ -543,14 +549,14 @@
     scoped_refptr<HTMLElement> root = html();
     if (root) {
       // First update the computed style for root element.
-      root->UpdateComputedStyle(initial_computed_style_,
-                                initial_computed_style_,
+      root->UpdateComputedStyle(initial_computed_style_declaration_,
+                                initial_computed_style_data_,
                                 style_change_event_time);
 
       // Then update the computed styles for the other elements.
-      root->UpdateComputedStyleRecursively(root->computed_style(),
-                                           root->computed_style(),
-                                           style_change_event_time, true);
+      root->UpdateComputedStyleRecursively(
+          root->css_computed_style_declaration(), root->computed_style(),
+          style_change_event_time, true);
     }
 
     is_computed_style_dirty_ = false;
@@ -589,9 +595,16 @@
 
 void Document::SetViewport(const math::Size& viewport_size) {
   viewport_size_ = viewport_size;
-  initial_computed_style_ = CreateInitialComputedStyle(*viewport_size_);
+  initial_computed_style_data_ = CreateInitialComputedStyle(*viewport_size_);
+  initial_computed_style_declaration_->SetData(initial_computed_style_data_);
+
   is_computed_style_dirty_ = true;
   is_selector_tree_dirty_ = true;
+
+  scoped_refptr<HTMLHtmlElement> current_html = html();
+  if (current_html) {
+    current_html->InvalidateComputedStylesRecursively();
+  }
 }
 
 Document::~Document() {
@@ -682,6 +695,13 @@
     keyframes_map_updater.ProcessCSSStyleSheet(user_agent_style_sheet_);
     keyframes_map_updater.ProcessStyleSheetList(style_sheets());
     are_keyframes_dirty_ = false;
+
+    // This should eventually be altered to only invalidate the tree when the
+    // the keyframes map changed.
+    scoped_refptr<HTMLHtmlElement> current_html = html();
+    if (current_html) {
+      current_html->InvalidateComputedStylesRecursively();
+    }
   }
 }
 
diff --git a/src/cobalt/dom/document.h b/src/cobalt/dom/document.h
index a312b1a..4d45315 100644
--- a/src/cobalt/dom/document.h
+++ b/src/cobalt/dom/document.h
@@ -27,7 +27,7 @@
 #include "base/optional.h"
 #include "base/string_piece.h"
 #include "cobalt/base/clock.h"
-#include "cobalt/cssom/css_computed_style_data.h"
+#include "cobalt/cssom/css_computed_style_declaration.h"
 #include "cobalt/cssom/css_keyframes_rule.h"
 #include "cobalt/cssom/css_style_sheet.h"
 #include "cobalt/cssom/mutation_observer.h"
@@ -61,6 +61,7 @@
 class HTMLScriptElement;
 class Location;
 class Text;
+class Window;
 
 class DocumentObserver {
  public:
@@ -88,9 +89,11 @@
     Options() : cookie_jar(NULL), csp_enforcement_mode(kCspEnforcementEnable) {}
     explicit Options(const GURL& url_value)
         : url(url_value),
+          window(NULL),
           cookie_jar(NULL),
           csp_enforcement_mode(kCspEnforcementEnable) {}
-    Options(const GURL& url_value, const base::Closure& hashchange_callback,
+    Options(const GURL& url_value, Window* window,
+            const base::Closure& hashchange_callback,
             const scoped_refptr<base::Clock>& navigation_start_clock_value,
             const base::Callback<void(const GURL&)>& navigation_callback,
             const scoped_refptr<cssom::CSSStyleSheet> user_agent_style_sheet,
@@ -102,6 +105,7 @@
             const base::Closure& csp_policy_changed_callback,
             int csp_insecure_allowed_token = 0)
         : url(url_value),
+          window(window),
           hashchange_callback(hashchange_callback),
           navigation_start_clock(navigation_start_clock_value),
           navigation_callback(navigation_callback),
@@ -115,6 +119,7 @@
           csp_insecure_allowed_token(csp_insecure_allowed_token) {}
 
     GURL url;
+    Window* window;
     base::Closure hashchange_callback;
     scoped_refptr<base::Clock> navigation_start_clock;
     base::Callback<void(const GURL&)> navigation_callback;
@@ -145,6 +150,8 @@
   scoped_refptr<Element> document_element() const;
   std::string title() const;
 
+  scoped_refptr<Window> default_view() const;
+
   scoped_refptr<HTMLCollection> GetElementsByTagName(
       const std::string& local_name) const;
   scoped_refptr<HTMLCollection> GetElementsByClassName(
@@ -298,9 +305,13 @@
   math::Size viewport_size() { return viewport_size_.value_or(math::Size()); }
   void SetViewport(const math::Size& viewport_size);
 
-  const scoped_refptr<cssom::CSSComputedStyleData>& initial_computed_style()
-      const {
-    return initial_computed_style_;
+  const scoped_refptr<cssom::CSSComputedStyleDeclaration>&
+  initial_computed_style_declaration() const {
+    return initial_computed_style_declaration_;
+  }
+  const scoped_refptr<cssom::CSSComputedStyleData>&
+  initial_computed_style_data() const {
+    return initial_computed_style_data_;
   }
 
   void NotifyUrlChanged(const GURL& url);
@@ -334,6 +345,9 @@
 
   // Reference to HTML element context.
   HTMLElementContext* const html_element_context_;
+  // Reference to the Window object. We cannot hold a strong reference,
+  // otherwise we create a reference loop.
+  Window* window_;
   // Associated DOM implementation object.
   scoped_refptr<DOMImplementation> implementation_;
   // Associated location object.
@@ -387,7 +401,9 @@
 
   // Computed style of the initial containing block, width and height come from
   // the viewport size.
-  scoped_refptr<cssom::CSSComputedStyleData> initial_computed_style_;
+  scoped_refptr<cssom::CSSComputedStyleDeclaration>
+      initial_computed_style_declaration_;
+  scoped_refptr<cssom::CSSComputedStyleData> initial_computed_style_data_;
 };
 
 }  // namespace dom
diff --git a/src/cobalt/dom/dom.gyp b/src/cobalt/dom/dom.gyp
index d171fd3..5438684 100644
--- a/src/cobalt/dom/dom.gyp
+++ b/src/cobalt/dom/dom.gyp
@@ -64,8 +64,6 @@
         'document_type.h',
         'dom_animatable.cc',
         'dom_animatable.h',
-        'dom_exception.cc',
-        'dom_exception.h',
         'dom_implementation.cc',
         'dom_implementation.h',
         'dom_parser.cc',
@@ -248,6 +246,7 @@
         '<(DEPTH)/cobalt/base/base.gyp:base',
         '<(DEPTH)/cobalt/csp/csp.gyp:csp',
         '<(DEPTH)/cobalt/cssom/cssom.gyp:cssom',
+        '<(DEPTH)/cobalt/dom/dom_exception.gyp:dom_exception',
         '<(DEPTH)/cobalt/loader/loader.gyp:loader',
         '<(DEPTH)/cobalt/media/media.gyp:media',
         # Interface layer to avoid directly depending on network.
diff --git a/src/cobalt/dom/dom_exception.gyp b/src/cobalt/dom/dom_exception.gyp
new file mode 100644
index 0000000..ba6dcf6
--- /dev/null
+++ b/src/cobalt/dom/dom_exception.gyp
@@ -0,0 +1,32 @@
+# 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.
+
+{
+  'variables': {
+    'cobalt_code': 1,
+  },
+  'targets': [
+    {
+      'target_name': 'dom_exception',
+      'type': 'static_library',
+      'sources': [
+        'dom_exception.cc',
+        'dom_exception.h',
+      ],
+      'dependencies': [
+        '<(DEPTH)/cobalt/script/script.gyp:script',
+      ],
+    },
+  ],
+}
diff --git a/src/cobalt/dom/html_element.cc b/src/cobalt/dom/html_element.cc
index 29cbf3e..f63dbbf 100644
--- a/src/cobalt/dom/html_element.cc
+++ b/src/cobalt/dom/html_element.cc
@@ -77,18 +77,22 @@
 
 struct NonTrivialStaticFields {
   NonTrivialStaticFields() {
+    cssom::PropertyKeyVector computed_style_invalidation_properties;
     cssom::PropertyKeyVector layout_box_invalidation_properties;
     cssom::PropertyKeyVector size_invalidation_properties;
     cssom::PropertyKeyVector cross_references_invalidation_properties;
 
     for (int i = 0; i <= cssom::kMaxLonghandPropertyKey; ++i) {
       cssom::PropertyKey property_key = static_cast<cssom::PropertyKey>(i);
-      // TODO: Only invalidate layout boxes when a property that is used
-      // for box generation is modified. We currently have to also invalidate
-      // when any inheritable property is modified, because AnonymousBlockBox
-      // and TextBox use GetComputedStyleOfAnonymousBox() to store a copy of
-      // them that won't automatically get updated when the style() in a
-      // CSSComputedStyleDeclaration gets updated.
+
+      if (cssom::GetPropertyImpactsChildDeclaredStyle(property_key) ==
+          cssom::kImpactsChildDeclaredStyleYes) {
+        computed_style_invalidation_properties.push_back(property_key);
+      }
+
+      // TODO: Revisit inherited property handling. Currently, all boxes are
+      // invalidated if an inherited property changes, but now that inherited
+      // properties dynamically update, this is likely no longer necessary.
       if (cssom::GetPropertyInheritance(property_key) == cssom::kInheritedYes ||
           cssom::GetPropertyImpactsBoxGeneration(property_key) ==
               cssom::kImpactsBoxGenerationYes) {
@@ -105,6 +109,9 @@
       }
     }
 
+    computed_style_invalidation_property_checker =
+        cssom::CSSComputedStyleData::PropertySetMatcher(
+            computed_style_invalidation_properties);
     layout_box_invalidation_property_checker =
         cssom::CSSComputedStyleData::PropertySetMatcher(
             layout_box_invalidation_properties);
@@ -117,6 +124,8 @@
   }
 
   cssom::CSSComputedStyleData::PropertySetMatcher
+      computed_style_invalidation_property_checker;
+  cssom::CSSComputedStyleData::PropertySetMatcher
       layout_box_invalidation_property_checker;
   cssom::CSSComputedStyleData::PropertySetMatcher
       size_invalidation_property_checker;
@@ -570,9 +579,13 @@
   }
 
   matching_rules_valid_ = false;
-  computed_style_valid_ = false;
 
-  matching_rules_.clear();
+  // Move |matching_rules_| into |old_matching_rules_|. This is used for
+  // determining whether or not the matching rules actually changed when they
+  // are updated.
+  old_matching_rules_.swap(matching_rules_);
+
+  matching_rules_->clear();
   rule_matching_state_.matching_nodes.clear();
   rule_matching_state_.descendant_potential_nodes.clear();
   rule_matching_state_.following_sibling_potential_nodes.clear();
@@ -603,17 +616,28 @@
   }
 }
 
+void HTMLElement::InvalidateComputedStylesRecursively() {
+  computed_style_valid_ = false;
+
+  for (Element* element = first_element_child(); element;
+       element = element->next_element_sibling()) {
+    HTMLElement* html_element = element->AsHTMLElement();
+    DCHECK(html_element);
+    html_element->InvalidateComputedStylesRecursively();
+  }
+}
+
 void HTMLElement::UpdateComputedStyleRecursively(
-    const scoped_refptr<const cssom::CSSComputedStyleData>&
-        parent_computed_style,
+    const scoped_refptr<cssom::CSSComputedStyleDeclaration>&
+        parent_computed_style_declaration,
     const scoped_refptr<const cssom::CSSComputedStyleData>& root_computed_style,
     const base::TimeDelta& style_change_event_time, bool ancestors_were_valid) {
   // Update computed style for this element.
-  bool is_valid = ancestors_were_valid && computed_style_valid_;
+  bool is_valid =
+      ancestors_were_valid && matching_rules_valid_ && computed_style_valid_;
   if (!is_valid) {
-    UpdateComputedStyle(parent_computed_style, root_computed_style,
+    UpdateComputedStyle(parent_computed_style_declaration, root_computed_style,
                         style_change_event_time);
-    computed_style_valid_ = true;
   }
 
   // Do not update computed style for descendants of "display: none" elements,
@@ -630,8 +654,8 @@
     HTMLElement* html_element = element->AsHTMLElement();
     DCHECK(html_element);
     html_element->UpdateComputedStyleRecursively(
-        computed_style(), root_computed_style, style_change_event_time,
-        is_valid);
+        css_computed_style_declaration(), root_computed_style,
+        style_change_event_time, is_valid);
   }
 }
 
@@ -657,6 +681,12 @@
   }
 }
 
+void HTMLElement::InvalidateRenderTreeNodesFromNode() {
+  if (layout_boxes_) {
+    layout_boxes_->InvalidateRenderTreeNodes();
+  }
+}
+
 HTMLElement::HTMLElement(Document* document, base::Token tag_name)
     : Element(document, tag_name),
       directionality_(kNoExplicitDirectionality),
@@ -670,6 +700,8 @@
       ALLOW_THIS_IN_INITIALIZER_LIST(
           animations_adapter_(new DOMAnimatable(this))),
       css_animations_(&animations_adapter_),
+      old_matching_rules_(new cssom::RulesWithCascadePrecedence()),
+      matching_rules_(new cssom::RulesWithCascadePrecedence()),
       matching_rules_valid_(false),
       dom_stat_tracker_(document->html_element_context()->dom_stat_tracker()) {
   css_computed_style_declaration_->set_animations(animations());
@@ -729,16 +761,16 @@
     cssom::RulesWithCascadePrecedence* matching_rules,
     cssom::GURLMap* property_key_to_base_url_map,
     const scoped_refptr<const cssom::CSSDeclaredStyleData>& inline_style,
-    const scoped_refptr<const cssom::CSSComputedStyleData>&
-        parent_computed_style,
+    const scoped_refptr<cssom::CSSComputedStyleDeclaration>&
+        parent_computed_style_declaration,
     const scoped_refptr<const cssom::CSSComputedStyleData>& root_computed_style,
     const math::Size& viewport_size,
     const base::TimeDelta& style_change_event_time,
-    cssom::TransitionSet* css_transitions,
     const scoped_refptr<const cssom::CSSComputedStyleData>&
         previous_computed_style,
-    cssom::AnimationSet* css_animations,
-    const cssom::CSSKeyframesRule::NameMap& keyframes_map) {
+    cssom::TransitionSet* css_transitions, cssom::AnimationSet* css_animations,
+    const cssom::CSSKeyframesRule::NameMap& keyframes_map,
+    bool* animations_modified) {
   // Select the winning value for each property by performing the cascade,
   // that is, apply values from matching rules on top of inline style, taking
   // into account rule specificity and location in the source file, as well as
@@ -754,9 +786,9 @@
   // properties, like "font-family", computed value is the same as specified
   // value. Declarations that cannot be absolutized easily, like "width: auto;",
   // will be resolved during layout.
-  cssom::PromoteToComputedStyle(computed_style, parent_computed_style,
-                                root_computed_style, viewport_size,
-                                property_key_to_base_url_map);
+  cssom::PromoteToComputedStyle(
+      computed_style, parent_computed_style_declaration, root_computed_style,
+      viewport_size, property_key_to_base_url_map);
 
   if (previous_computed_style) {
     // Now that we have updated our computed style, compare it to the previous
@@ -764,13 +796,39 @@
     css_transitions->UpdateTransitions(
         style_change_event_time, *previous_computed_style, *computed_style);
   }
-  // Update the set of currently running animations.
-  css_animations->Update(style_change_event_time, *computed_style,
-                         keyframes_map);
+  // Update the set of currently running animations and track whether or not the
+  // animations changed.
+  *animations_modified = css_animations->Update(style_change_event_time,
+                                                *computed_style, keyframes_map);
 
   return computed_style;
 }
 
+// Flags tracking which cached values must be invalidated.
+struct UpdateComputedStyleInvalidationFlags {
+  UpdateComputedStyleInvalidationFlags()
+      : invalidate_descendant_computed_styles(false),
+        invalidate_layout_boxes(false),
+        invalidate_sizes(false),
+        invalidate_cross_references(false),
+        invalidate_render_tree_nodes(false) {}
+
+  bool invalidate_descendant_computed_styles;
+  bool invalidate_layout_boxes;
+  bool invalidate_sizes;
+  bool invalidate_cross_references;
+  bool invalidate_render_tree_nodes;
+};
+
+bool NewComputedStyleInvalidatesDescendantComputedStyles(
+    const scoped_refptr<const cssom::CSSComputedStyleData>& old_computed_style,
+    const scoped_refptr<cssom::CSSComputedStyleData>& new_computed_style) {
+  return !non_trivial_static_fields.Get()
+              .computed_style_invalidation_property_checker
+              .DoDeclaredPropertiesMatch(old_computed_style,
+                                         new_computed_style);
+}
+
 bool NewComputedStyleInvalidatesLayoutBoxes(
     const scoped_refptr<const cssom::CSSComputedStyleData>& old_computed_style,
     const scoped_refptr<cssom::CSSComputedStyleData>& new_computed_style) {
@@ -797,24 +855,82 @@
                                          new_computed_style);
 }
 
+void UpdateInvalidationFlagsForNewComputedStyle(
+    const scoped_refptr<const cssom::CSSComputedStyleData>& old_computed_style,
+    const scoped_refptr<cssom::CSSComputedStyleData>& new_computed_style,
+    bool animations_modified, UpdateComputedStyleInvalidationFlags* flags) {
+  if (old_computed_style) {
+    if (!flags->invalidate_descendant_computed_styles &&
+        NewComputedStyleInvalidatesDescendantComputedStyles(
+            old_computed_style, new_computed_style)) {
+      flags->invalidate_descendant_computed_styles = true;
+      flags->invalidate_layout_boxes = true;
+    } else if (!flags->invalidate_layout_boxes) {
+      if (NewComputedStyleInvalidatesLayoutBoxes(old_computed_style,
+                                                 new_computed_style)) {
+        flags->invalidate_layout_boxes = true;
+      } else {
+        if (!flags->invalidate_sizes &&
+            NewComputedStyleInvalidatesSizes(old_computed_style,
+                                             new_computed_style)) {
+          flags->invalidate_sizes = true;
+          flags->invalidate_render_tree_nodes = true;
+        }
+        if (!flags->invalidate_cross_references &&
+            NewComputedStyleInvalidatesCrossReferences(old_computed_style,
+                                                       new_computed_style)) {
+          flags->invalidate_cross_references = true;
+          flags->invalidate_render_tree_nodes = true;
+        }
+
+        flags->invalidate_render_tree_nodes =
+            flags->invalidate_render_tree_nodes || animations_modified ||
+            !new_computed_style->DoDeclaredPropertiesMatch(old_computed_style);
+      }
+    }
+  }
+}
+
 }  // namespace
 
 void HTMLElement::UpdateComputedStyle(
-    const scoped_refptr<const cssom::CSSComputedStyleData>&
-        parent_computed_style,
+    const scoped_refptr<cssom::CSSComputedStyleDeclaration>&
+        parent_computed_style_declaration,
     const scoped_refptr<const cssom::CSSComputedStyleData>& root_computed_style,
     const base::TimeDelta& style_change_event_time) {
   Document* document = node_document();
   DCHECK(document) << "Element should be attached to document in order to "
                       "participate in layout.";
 
+  // If there is no previous computed style, there should also be no layout
+  // boxes.
+  DCHECK(computed_style() || NULL == layout_boxes());
+
   dom_stat_tracker_->OnUpdateComputedStyle();
 
+  // The computed style must be generated if either the computed style is
+  // invalid or no computed style has been created yet.
+  bool generate_computed_style = !computed_style_valid_ || !computed_style();
+
   // Update matching rules if necessary.
   if (!matching_rules_valid_) {
     dom_stat_tracker_->OnUpdateMatchingRules();
     UpdateMatchingRules(this);
     matching_rules_valid_ = true;
+
+    // Check for whether the matching rules have changed. If they have, then a
+    // new computed style must be generated from them.
+    if (!generate_computed_style && *old_matching_rules_ != *matching_rules_) {
+      generate_computed_style = true;
+    }
+  }
+
+  // If any declared properties inherited from the parent are no longer valid,
+  // then a new computed style must be generated with the updated inherited
+  // values.
+  if (!generate_computed_style &&
+      !computed_style()->AreDeclaredPropertiesInheritedFromParentValid()) {
+    generate_computed_style = true;
   }
 
   // TODO: It maybe helpful to generalize this mapping framework in the
@@ -824,95 +940,88 @@
   property_key_to_base_url_map[cssom::kBackgroundImageProperty] =
       document->url_as_gurl();
 
-  scoped_refptr<cssom::CSSComputedStyleData> new_computed_style =
-      PromoteMatchingRulesToComputedStyle(
-          matching_rules(), &property_key_to_base_url_map, style_->data(),
-          parent_computed_style, root_computed_style, document->viewport_size(),
-          style_change_event_time, &css_transitions_, computed_style(),
-          &css_animations_, document->keyframes_map());
+  // Flags tracking which cached values must be invalidated.
+  UpdateComputedStyleInvalidationFlags invalidation_flags;
 
-  // If there is no previous computed style, there should also be no layout
-  // boxes, and nothing has to be invalidated.
-  bool invalidate_layout_boxes = false;
-  bool invalidate_sizes = false;
-  bool invalidate_cross_references = false;
+  if (generate_computed_style) {
+    bool animations_modified = false;
 
-  DCHECK(computed_style() || NULL == layout_boxes());
-  if (computed_style()) {
-    if (NewComputedStyleInvalidatesLayoutBoxes(computed_style(),
-                                               new_computed_style)) {
-      invalidate_layout_boxes = true;
-    } else {
-      if (NewComputedStyleInvalidatesSizes(computed_style(),
-                                           new_computed_style)) {
-        invalidate_sizes = true;
-      }
-      if (NewComputedStyleInvalidatesCrossReferences(computed_style(),
-                                                     new_computed_style)) {
-        invalidate_cross_references = true;
-      }
-    }
+    scoped_refptr<cssom::CSSComputedStyleData> new_computed_style =
+        PromoteMatchingRulesToComputedStyle(
+            matching_rules(), &property_key_to_base_url_map, style_->data(),
+            parent_computed_style_declaration, root_computed_style,
+            document->viewport_size(), style_change_event_time,
+            computed_style(), &css_transitions_, &css_animations_,
+            document->keyframes_map(), &animations_modified);
+
+    UpdateInvalidationFlagsForNewComputedStyle(
+        computed_style(), new_computed_style, animations_modified,
+        &invalidation_flags);
+
+    css_computed_style_declaration_->SetData(new_computed_style);
+
+    // Update cached background images after resolving the urls in
+    // background_image CSS property of the computed style, so we have all the
+    // information to get the cached background images.
+    UpdateCachedBackgroundImagesFromComputedStyle();
+  } else {
+    // Update the inherited data if a new style was not generated. The ancestor
+    // data with inherited properties may have changed.
+    css_computed_style_declaration_->UpdateInheritedData();
   }
 
-  set_computed_style(new_computed_style);
-
-  // Update cached background images after resolving the urls in
-  // background_image CSS property of the computed style, so we have all the
-  // information to get the cached background images.
-  UpdateCachedBackgroundImagesFromComputedStyle();
+  // NOTE: Currently, pseudo elements computed styles are always generated. If
+  // this becomes a performance bottleneck, change the logic so that it only
+  // occurs when needed.
 
   // Promote the matching rules for all known pseudo elements.
   for (int pseudo_element_type = 0; pseudo_element_type < kMaxPseudoElementType;
        ++pseudo_element_type) {
     if (pseudo_elements_[pseudo_element_type]) {
+      bool animations_modified = false;
+
       scoped_refptr<cssom::CSSComputedStyleData> pseudo_element_computed_style =
           PromoteMatchingRulesToComputedStyle(
               pseudo_elements_[pseudo_element_type]->matching_rules(),
-              &property_key_to_base_url_map, style_->data(), computed_style(),
-              root_computed_style, document->viewport_size(),
-              style_change_event_time,
-              pseudo_elements_[pseudo_element_type]->css_transitions(),
+              &property_key_to_base_url_map, style_->data(),
+              css_computed_style_declaration(), root_computed_style,
+              document->viewport_size(), style_change_event_time,
               pseudo_elements_[pseudo_element_type]->computed_style(),
+              pseudo_elements_[pseudo_element_type]->css_transitions(),
               pseudo_elements_[pseudo_element_type]->css_animations(),
-              document->keyframes_map());
+              document->keyframes_map(), &animations_modified);
 
-      if (!invalidate_layout_boxes &&
-          pseudo_elements_[pseudo_element_type]->computed_style()) {
-        if (NewComputedStyleInvalidatesLayoutBoxes(
-                pseudo_elements_[pseudo_element_type]->computed_style(),
-                pseudo_element_computed_style)) {
-          invalidate_layout_boxes = true;
-        } else {
-          if (!invalidate_sizes &&
-              NewComputedStyleInvalidatesSizes(
-                  pseudo_elements_[pseudo_element_type]->computed_style(),
-                  pseudo_element_computed_style)) {
-            invalidate_sizes = true;
-          }
-          if (!invalidate_cross_references &&
-              NewComputedStyleInvalidatesCrossReferences(
-                  pseudo_elements_[pseudo_element_type]->computed_style(),
-                  pseudo_element_computed_style)) {
-            invalidate_cross_references = true;
-          }
-        }
-      }
-      pseudo_elements_[pseudo_element_type]->set_computed_style(
-          pseudo_element_computed_style);
+      UpdateInvalidationFlagsForNewComputedStyle(
+          pseudo_elements_[pseudo_element_type]->computed_style(),
+          pseudo_element_computed_style, animations_modified,
+          &invalidation_flags);
+
+      pseudo_elements_[pseudo_element_type]
+          ->css_computed_style_declaration()
+          ->SetData(pseudo_element_computed_style);
     }
   }
 
-  if (invalidate_layout_boxes) {
+  if (invalidation_flags.invalidate_descendant_computed_styles) {
+    InvalidateComputedStylesRecursively();
+  }
+
+  if (invalidation_flags.invalidate_layout_boxes) {
     InvalidateLayoutBoxesFromNodeAndAncestors();
     InvalidateLayoutBoxesFromNodeAndDescendants();
   } else {
-    if (invalidate_sizes) {
+    if (invalidation_flags.invalidate_sizes) {
       InvalidateLayoutBoxSizesFromNode();
     }
-    if (invalidate_cross_references) {
+    if (invalidation_flags.invalidate_cross_references) {
       InvalidateLayoutBoxCrossReferencesFromNode();
     }
+    if (invalidation_flags.invalidate_render_tree_nodes) {
+      InvalidateRenderTreeNodesFromNode();
+    }
   }
+
+  computed_style_valid_ = true;
 }
 
 void HTMLElement::UpdateCachedBackgroundImagesFromComputedStyle() {
diff --git a/src/cobalt/dom/html_element.h b/src/cobalt/dom/html_element.h
index eb6995f..11837a8 100644
--- a/src/cobalt/dom/html_element.h
+++ b/src/cobalt/dom/html_element.h
@@ -178,7 +178,7 @@
   //
   // Returns the cached matching rules of this element.
   cssom::RulesWithCascadePrecedence* matching_rules() {
-    return &matching_rules_;
+    return matching_rules_.get();
   }
   // Returns the rule matching state of this element.
   RuleMatchingState* rule_matching_state() { return &rule_matching_state_; }
@@ -199,13 +199,12 @@
       const {
     return css_computed_style_declaration_->data();
   }
-  void set_computed_style(
-      const scoped_refptr<cssom::CSSComputedStyleData>& computed_style) {
-    css_computed_style_declaration_->set_data(computed_style);
-  }
+
+  // Invalidates the cached computed style of this element and its descendants.
+  void InvalidateComputedStylesRecursively();
   // Updates the cached computed style of this element and its descendants.
   void UpdateComputedStyleRecursively(
-      const scoped_refptr<const cssom::CSSComputedStyleData>&
+      const scoped_refptr<cssom::CSSComputedStyleDeclaration>&
           parent_computed_style,
       const scoped_refptr<const cssom::CSSComputedStyleData>&
           root_computed_style,
@@ -213,8 +212,8 @@
       bool ancestors_were_valid);
   // Updates the cached computed style of this element.
   void UpdateComputedStyle(
-      const scoped_refptr<const cssom::CSSComputedStyleData>&
-          parent_computed_style,
+      const scoped_refptr<cssom::CSSComputedStyleDeclaration>&
+          parent_computed_style_declaration,
       const scoped_refptr<const cssom::CSSComputedStyleData>&
           root_computed_style,
       const base::TimeDelta& style_change_event_time);
@@ -233,6 +232,7 @@
   void InvalidateLayoutBoxesFromNodeAndDescendants() OVERRIDE;
   void InvalidateLayoutBoxSizesFromNode() OVERRIDE;
   void InvalidateLayoutBoxCrossReferencesFromNode() OVERRIDE;
+  void InvalidateRenderTreeNodesFromNode() OVERRIDE;
 
   // Determines whether this element is focusable.
   bool IsFocusable() const { return HasAttribute("tabindex"); }
@@ -313,7 +313,8 @@
   cssom::AnimationSet css_animations_;
 
   // The following fields are used in rule matching.
-  cssom::RulesWithCascadePrecedence matching_rules_;
+  scoped_ptr<cssom::RulesWithCascadePrecedence> old_matching_rules_;
+  scoped_ptr<cssom::RulesWithCascadePrecedence> matching_rules_;
   RuleMatchingState rule_matching_state_;
 
   // This contains information about the boxes generated from the element.
diff --git a/src/cobalt/dom/html_element_test.cc b/src/cobalt/dom/html_element_test.cc
index ce2a589..1e8bceb 100644
--- a/src/cobalt/dom/html_element_test.cc
+++ b/src/cobalt/dom/html_element_test.cc
@@ -86,6 +86,7 @@
 
   MOCK_METHOD0(InvalidateSizes, void());
   MOCK_METHOD0(InvalidateCrossReferences, void());
+  MOCK_METHOD0(InvalidateRenderTreeNodes, void());
 };
 
 // Takes the fist child of the given element repeatedly to the given depth.
@@ -136,7 +137,7 @@
         document_->CreateElement(*null_terminated_element_names)
             ->AsHTMLElement());
     DCHECK(child_html_element);
-    child_html_element->set_computed_style(
+    child_html_element->css_computed_style_declaration()->SetData(
         make_scoped_refptr(new cssom::CSSComputedStyleData()));
 
     if (parent_html_element) {
@@ -442,7 +443,8 @@
       make_scoped_refptr(new cssom::CSSComputedStyleData());
   computed_style_relative->set_position(cssom::KeywordValue::GetRelative());
   GetFirstChildAtDepth(root_html_element, 2)
-      ->set_computed_style(computed_style_relative);
+      ->css_computed_style_declaration()
+      ->SetData(computed_style_relative);
 
   // Return ancestor if it is the HTML body element.
   EXPECT_EQ(GetFirstChildAtDepth(root_html_element, 2)->offset_parent(),
@@ -454,7 +456,8 @@
       make_scoped_refptr(new cssom::CSSComputedStyleData());
   computed_style_fixed->set_position(cssom::KeywordValue::GetFixed());
   GetFirstChildAtDepth(root_html_element, 3)
-      ->set_computed_style(computed_style_fixed);
+      ->css_computed_style_declaration()
+      ->SetData(computed_style_fixed);
   EXPECT_FALSE(GetFirstChildAtDepth(root_html_element, 3)->offset_parent());
 
   // Return ancestor if its computed value of the 'position' property is not
diff --git a/src/cobalt/dom/html_video_element.cc b/src/cobalt/dom/html_video_element.cc
index b7e4751..89d0f1e 100644
--- a/src/cobalt/dom/html_video_element.cc
+++ b/src/cobalt/dom/html_video_element.cc
@@ -71,6 +71,17 @@
   return static_cast<uint32>(player()->GetNaturalSize().height());
 }
 
+scoped_refptr<VideoPlaybackQuality> HTMLVideoElement::GetVideoPlaybackQuality()
+    const {
+  // TODO: Provide all attributes with valid values.
+  return new VideoPlaybackQuality(
+      0.,   // creation_time
+      player() ? static_cast<uint32>(player()->GetDecodedFrameCount()) : 0,
+      player() ? static_cast<uint32>(player()->GetDroppedFrameCount()) : 0,
+      0,    // corrupted_video_frames
+      0.);  // total_frame_delay
+}
+
 scoped_refptr<ShellVideoFrameProvider>
 HTMLVideoElement::GetVideoFrameProvider() {
   DCHECK(thread_checker_.CalledOnValidThread());
diff --git a/src/cobalt/dom/html_video_element.h b/src/cobalt/dom/html_video_element.h
index 0f83f04..2ac5c3f 100644
--- a/src/cobalt/dom/html_video_element.h
+++ b/src/cobalt/dom/html_video_element.h
@@ -20,6 +20,7 @@
 #include <string>
 
 #include "cobalt/dom/html_media_element.h"
+#include "cobalt/dom/video_playback_quality.h"
 #include "media/base/shell_video_frame_provider.h"
 
 namespace cobalt {
@@ -43,6 +44,7 @@
   void set_height(uint32 height);
   uint32 video_width() const;
   uint32 video_height() const;
+  scoped_refptr<VideoPlaybackQuality> GetVideoPlaybackQuality() const;
 
   // Custom, not in any spec
   //
diff --git a/src/cobalt/dom/layout_boxes.h b/src/cobalt/dom/layout_boxes.h
index 350a7cc..98eccce 100644
--- a/src/cobalt/dom/layout_boxes.h
+++ b/src/cobalt/dom/layout_boxes.h
@@ -81,6 +81,8 @@
   // Invalidate the cross references, which relates to both positioned children
   // of containing blocks and z-index children of stacking contexts.
   virtual void InvalidateCrossReferences() = 0;
+  // Invalidate the layout box's render tree nodes.
+  virtual void InvalidateRenderTreeNodes() = 0;
 
  protected:
   LayoutBoxes() {}
diff --git a/src/cobalt/dom/node.h b/src/cobalt/dom/node.h
index ceee672..0b2ca54 100644
--- a/src/cobalt/dom/node.h
+++ b/src/cobalt/dom/node.h
@@ -239,6 +239,8 @@
   virtual void InvalidateLayoutBoxSizesFromNode() {}
   // Invalidate the cross references within the layout boxes of this node.
   virtual void InvalidateLayoutBoxCrossReferencesFromNode() {}
+  // Invalidate the render tree nodes within the layout boxes of this node.
+  virtual void InvalidateRenderTreeNodesFromNode() {}
 
   // Triggers a generation update in this node and all its ancestor nodes.
   void UpdateGenerationForNodeAndAncestors();
diff --git a/src/cobalt/dom/pseudo_element.h b/src/cobalt/dom/pseudo_element.h
index 0531421..18e94d7 100644
--- a/src/cobalt/dom/pseudo_element.h
+++ b/src/cobalt/dom/pseudo_element.h
@@ -58,10 +58,6 @@
   scoped_refptr<const cssom::CSSComputedStyleData> computed_style() const {
     return css_computed_style_declaration_->data();
   }
-  void set_computed_style(
-      const scoped_refptr<const cssom::CSSComputedStyleData>& computed_style) {
-    css_computed_style_declaration_->set_data(computed_style);
-  }
 
   cssom::RulesWithCascadePrecedence* matching_rules() {
     return &matching_rules_;
diff --git a/src/cobalt/dom/video_playback_quality.h b/src/cobalt/dom/video_playback_quality.h
new file mode 100644
index 0000000..e5e88e3
--- /dev/null
+++ b/src/cobalt/dom/video_playback_quality.h
@@ -0,0 +1,61 @@
+/*
+ * 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_DOM_VIDEO_PLAYBACK_QUALITY_H_
+#define COBALT_DOM_VIDEO_PLAYBACK_QUALITY_H_
+
+#include "base/basictypes.h"
+#include "cobalt/script/wrappable.h"
+
+namespace cobalt {
+namespace dom {
+
+// The VideoPlaybackQuality interface exposes data to describe the video
+// playback quality.
+//   https://www.w3.org/TR/media-source/#idl-def-VideoPlaybackQuality
+class VideoPlaybackQuality : public script::Wrappable {
+ public:
+  VideoPlaybackQuality(double creation_time, uint32 total_video_frames,
+                       uint32 dropped_video_frames,
+                       uint32 corrupted_video_frames, double total_frame_delay)
+      : creation_time_(creation_time),
+        total_video_frames_(total_video_frames),
+        dropped_video_frames_(dropped_video_frames),
+        corrupted_video_frames_(corrupted_video_frames),
+        total_frame_delay_(total_frame_delay) {}
+
+  // Web API: VideoPlaybackQuality
+  //
+  double creation_time() const { return creation_time_; }
+  uint32 total_video_frames() const { return total_video_frames_; }
+  uint32 dropped_video_frames() const { return dropped_video_frames_; }
+  uint32 corrupted_video_frames() const { return corrupted_video_frames_; }
+  double total_frame_delay() const { return total_frame_delay_; }
+
+  DEFINE_WRAPPABLE_TYPE(VideoPlaybackQuality);
+
+ private:
+  double creation_time_;
+  uint32 total_video_frames_;
+  uint32 dropped_video_frames_;
+  uint32 corrupted_video_frames_;
+  double total_frame_delay_;
+};
+
+}  // namespace dom
+}  // namespace cobalt
+
+#endif  // COBALT_DOM_VIDEO_PLAYBACK_QUALITY_H_
diff --git a/src/cobalt/dom/window.cc b/src/cobalt/dom/window.cc
index e1f7bce..cdab450 100644
--- a/src/cobalt/dom/window.cc
+++ b/src/cobalt/dom/window.cc
@@ -90,7 +90,7 @@
       ALLOW_THIS_IN_INITIALIZER_LIST(document_(new Document(
           html_element_context_.get(),
           Document::Options(
-              url,
+              url, this,
               base::Bind(&Window::FireHashChangeEvent, base::Unretained(this)),
               performance_->timing()->GetNavigationStartClock(),
               navigation_callback, ParseUserAgentStyleSheet(css_parser),
diff --git a/src/cobalt/dom/window_timers.cc b/src/cobalt/dom/window_timers.cc
index 04e58b8..df784cd 100644
--- a/src/cobalt/dom/window_timers.cc
+++ b/src/cobalt/dom/window_timers.cc
@@ -73,7 +73,10 @@
 void WindowTimers::RunTimerCallback(int handle) {
   Timers::iterator timer = timers_.find(handle);
   DCHECK(timer != timers_.end());
-  timer->second->callback_reference().value().Run();
+  // Keep a |TimerInfo| reference, so it won't be released when running the
+  // callback.
+  scoped_refptr<TimerInfo> timer_info = timer->second;
+  timer_info->callback_reference().value().Run();
   // After running the callback, double check whether the timer is still there
   // since it might be deleted inside the callback.
   timer = timers_.find(handle);
diff --git a/src/cobalt/layout/anonymous_block_box.cc b/src/cobalt/layout/anonymous_block_box.cc
index b20e597..281cc70 100644
--- a/src/cobalt/layout/anonymous_block_box.cc
+++ b/src/cobalt/layout/anonymous_block_box.cc
@@ -62,11 +62,8 @@
 }
 
 void AnonymousBlockBox::RenderAndAnimateContent(
-    render_tree::CompositionNode::Builder* border_node_builder,
-    render_tree::animations::NodeAnimationsMap::Builder*
-        node_animations_map_builder) const {
-  ContainerBox::RenderAndAnimateContent(border_node_builder,
-                                        node_animations_map_builder);
+    render_tree::CompositionNode::Builder* border_node_builder) const {
+  ContainerBox::RenderAndAnimateContent(border_node_builder);
 
   if (computed_style()->visibility() != cssom::KeywordValue::GetVisible()) {
     return;
@@ -125,24 +122,20 @@
 
 scoped_ptr<FormattingContext> AnonymousBlockBox::UpdateRectOfInFlowChildBoxes(
     const LayoutParams& child_layout_params) {
-  // Check to see if ellipses are enabled:
-  // If they are, then retrieve the ellipsis width for the font and reset the
-  // ellipsis boxes on all child boxes because they are no longer valid.
-  // Otherwise, set the width to 0, which indicates that ellipses are not being
-  // used. In this case, child boxes do not need to have ellipses reset, as they
-  // could not have previously been set.
-  float ellipsis_width;
-  if (AreEllipsesEnabled()) {
-    ellipsis_width = used_font_->GetEllipsisWidth();
-
-    for (Boxes::const_iterator child_box_iterator = child_boxes().begin();
-         child_box_iterator != child_boxes().end(); ++child_box_iterator) {
-      (*child_box_iterator)->ResetEllipses();
-    }
-  } else {
-    ellipsis_width = 0;
+  // Do any processing needed prior to ellipsis placement on all of the
+  // children.
+  for (Boxes::const_iterator child_ellipsis_iterator = child_boxes().begin();
+       child_ellipsis_iterator != child_boxes().end();
+       ++child_ellipsis_iterator) {
+    (*child_ellipsis_iterator)->DoPreEllipsisPlacementProcessing();
   }
 
+  // If ellipses are enabled then retrieve the ellipsis width for the font;
+  // otherwise, set the width to 0, which indicates that ellipses are not being
+  // used.
+  float ellipsis_width =
+      AreEllipsesEnabled() ? used_font_->GetEllipsisWidth() : 0;
+
   // Lay out child boxes in the normal flow.
   //   https://www.w3.org/TR/CSS21/visuren.html#normal-flow
   scoped_ptr<InlineFormattingContext> inline_formatting_context(
@@ -204,6 +197,15 @@
   }
   inline_formatting_context->EndUpdates();
   ellipses_coordinates_ = inline_formatting_context->GetEllipsesCoordinates();
+
+  // Do any processing needed following ellipsis placement on all of the
+  // children.
+  for (Boxes::const_iterator child_ellipsis_iterator = child_boxes().begin();
+       child_ellipsis_iterator != child_boxes().end();
+       ++child_ellipsis_iterator) {
+    (*child_ellipsis_iterator)->DoPostEllipsisPlacementProcessing();
+  }
+
   return inline_formatting_context.PassAs<FormattingContext>();
 }
 
diff --git a/src/cobalt/layout/anonymous_block_box.h b/src/cobalt/layout/anonymous_block_box.h
index 54c1673..bda736f 100644
--- a/src/cobalt/layout/anonymous_block_box.h
+++ b/src/cobalt/layout/anonymous_block_box.h
@@ -47,10 +47,8 @@
 
   bool HasTrailingLineBreak() const OVERRIDE;
 
-  void RenderAndAnimateContent(
-      render_tree::CompositionNode::Builder* border_node_builder,
-      render_tree::animations::NodeAnimationsMap::Builder*
-          node_animations_map_builder) const OVERRIDE;
+  void RenderAndAnimateContent(render_tree::CompositionNode::Builder*
+                                   border_node_builder) const OVERRIDE;
 
   // From |ContainerBox|.
 
diff --git a/src/cobalt/layout/block_formatting_block_container_box.cc b/src/cobalt/layout/block_formatting_block_container_box.cc
index b4023d8..1c85502 100644
--- a/src/cobalt/layout/block_formatting_block_container_box.cc
+++ b/src/cobalt/layout/block_formatting_block_container_box.cc
@@ -96,14 +96,14 @@
     // TODO: Determine which animations to propagate to the anonymous block box,
     //       instead of none at all.
     scoped_refptr<cssom::CSSComputedStyleDeclaration>
-        css_computed_style_declaration =
+        new_computed_style_declaration =
             new cssom::CSSComputedStyleDeclaration();
-    css_computed_style_declaration->set_data(
-        GetComputedStyleOfAnonymousBox(computed_style()));
-    css_computed_style_declaration->set_animations(
+    new_computed_style_declaration->SetData(
+        GetComputedStyleOfAnonymousBox(css_computed_style_declaration()));
+    new_computed_style_declaration->set_animations(
         new web_animations::AnimationSet());
     scoped_refptr<AnonymousBlockBox> new_anonymous_block_box(
-        new AnonymousBlockBox(css_computed_style_declaration,
+        new AnonymousBlockBox(new_computed_style_declaration,
                               GetBaseDirection(), used_style_provider(),
                               layout_stat_tracker()));
     anonymous_block_box = new_anonymous_block_box.get();
@@ -144,7 +144,8 @@
                                        layout_stat_tracker),
       paragraph_(paragraph),
       text_position_(text_position),
-      is_hidden_by_ellipsis_(false) {}
+      is_hidden_by_ellipsis_(false),
+      was_hidden_by_ellipsis_(false) {}
 
 InlineLevelBlockContainerBox::~InlineLevelBlockContainerBox() {}
 
@@ -216,10 +217,17 @@
   return true;
 }
 
-void InlineLevelBlockContainerBox::ResetEllipses() {
+void InlineLevelBlockContainerBox::DoPreEllipsisPlacementProcessing() {
+  was_hidden_by_ellipsis_ = is_hidden_by_ellipsis_;
   is_hidden_by_ellipsis_ = false;
 }
 
+void InlineLevelBlockContainerBox::DoPostEllipsisPlacementProcessing() {
+  if (was_hidden_by_ellipsis_ != is_hidden_by_ellipsis_) {
+    InvalidateRenderTreeNodesOfBoxAndAncestors();
+  }
+}
+
 bool InlineLevelBlockContainerBox::IsHiddenByEllipsis() const {
   return is_hidden_by_ellipsis_;
 }
diff --git a/src/cobalt/layout/block_formatting_block_container_box.h b/src/cobalt/layout/block_formatting_block_container_box.h
index 197960b..a4a5bd9 100644
--- a/src/cobalt/layout/block_formatting_block_container_box.h
+++ b/src/cobalt/layout/block_formatting_block_container_box.h
@@ -117,7 +117,8 @@
   base::optional<int> GetBidiLevel() const OVERRIDE;
 
   bool DoesFulfillEllipsisPlacementRequirement() const OVERRIDE;
-  void ResetEllipses() OVERRIDE;
+  void DoPreEllipsisPlacementProcessing() OVERRIDE;
+  void DoPostEllipsisPlacementProcessing() OVERRIDE;
   bool IsHiddenByEllipsis() const OVERRIDE;
 
  protected:
@@ -143,6 +144,11 @@
   // the applicable edge(s) of the line as necessary to fit the ellipsis."
   //   https://www.w3.org/TR/css3-ui/#propdef-text-overflow
   bool is_hidden_by_ellipsis_;
+  // Tracking of the previous value of |is_hidden_by_ellipsis_|, which allows
+  // for determination of whether or not the value changed during ellipsis
+  // placement. When this occurs, the cached render tree nodes of this box and
+  // its ancestors are invalidated.
+  bool was_hidden_by_ellipsis_;
 };
 
 }  // namespace layout
diff --git a/src/cobalt/layout/box.cc b/src/cobalt/layout/box.cc
index 82cbeb3..c8739ee 100644
--- a/src/cobalt/layout/box.cc
+++ b/src/cobalt/layout/box.cc
@@ -53,7 +53,7 @@
 using cobalt::render_tree::RoundedCorners;
 using cobalt::render_tree::ViewportFilter;
 using cobalt::render_tree::animations::Animation;
-using cobalt::render_tree::animations::NodeAnimationsMap;
+using cobalt::render_tree::animations::AnimateNode;
 
 namespace cobalt {
 namespace layout {
@@ -110,6 +110,10 @@
   UpdateBorders();
   UpdatePaddings(layout_params);
   UpdateContentSizeAndMargins(layout_params);
+
+  // After a size update, this portion of the render tree must be updated, so
+  // invalidate any cached render tree nodes.
+  InvalidateRenderTreeNodesOfBoxAndAncestors();
 }
 
 bool Box::ValidateUpdateSizeInputs(const LayoutParams& params) {
@@ -190,6 +194,13 @@
   }
 }
 
+void Box::InvalidateRenderTreeNodesOfBoxAndAncestors() {
+  cached_render_tree_node_info_ = base::nullopt;
+  if (parent_) {
+    parent_->InvalidateRenderTreeNodesOfBoxAndAncestors();
+  }
+}
+
 LayoutUnit Box::GetMarginBoxWidth() const {
   return margin_left() + GetBorderBoxWidth() + margin_right();
 }
@@ -385,8 +396,25 @@
 
 void Box::RenderAndAnimate(
     CompositionNode::Builder* parent_content_node_builder,
-    NodeAnimationsMap::Builder* node_animations_map_builder,
-    const math::Vector2dF& offset_from_parent_node) const {
+    const math::Vector2dF& offset_from_parent_node) {
+  math::Vector2dF border_box_offset(left().toFloat() + margin_left().toFloat(),
+                                    top().toFloat() + margin_top().toFloat());
+  border_box_offset += offset_from_parent_node;
+
+  // If there's a pre-existing cached render tree node that is located at the
+  // border box offset, then simply use it. There's no more work to do.
+  if (cached_render_tree_node_info_ &&
+      cached_render_tree_node_info_->offset_ == border_box_offset) {
+    if (cached_render_tree_node_info_->node_) {
+      parent_content_node_builder->AddChild(
+          cached_render_tree_node_info_->node_);
+    }
+    return;
+  }
+
+  // Initialize the cached render tree node with the border box offset.
+  cached_render_tree_node_info_ = CachedRenderTreeNodeInfo(border_box_offset);
+
   float opacity = base::polymorphic_downcast<const cssom::NumberValue*>(
                       computed_style()->opacity().get())
                       ->value();
@@ -406,10 +434,8 @@
     return;
   }
 
-  math::Vector2dF border_box_offset(left().toFloat() + margin_left().toFloat(),
-                                    top().toFloat() + margin_top().toFloat());
-  border_box_offset += offset_from_parent_node;
   render_tree::CompositionNode::Builder border_node_builder(border_box_offset);
+  AnimateNode::Builder animate_node_builder;
 
   UsedBorderRadiusProvider border_radius_provider(GetBorderBoxSize());
   computed_style()->border_radius()->Accept(&border_radius_provider);
@@ -446,17 +472,14 @@
   // 'visibility: visible'.
   //   https://www.w3.org/TR/CSS21/visufx.html#propdef-visibility
   if (computed_style()->visibility() == cssom::KeywordValue::GetVisible()) {
-    RenderAndAnimateBackgroundColor(padding_rounded_corners,
-                                    &border_node_builder,
-                                    node_animations_map_builder);
-    RenderAndAnimateBackgroundImage(padding_rounded_corners,
-                                    &border_node_builder,
-                                    node_animations_map_builder);
+    RenderAndAnimateBackgroundColor(
+        padding_rounded_corners, &border_node_builder, &animate_node_builder);
+    RenderAndAnimateBackgroundImage(
+        padding_rounded_corners, &border_node_builder, &animate_node_builder);
     RenderAndAnimateBorder(border_radius_provider.rounded_corners(),
-                           &border_node_builder, node_animations_map_builder);
+                           &border_node_builder, &animate_node_builder);
     RenderAndAnimateBoxShadow(border_radius_provider.rounded_corners(),
-                              &border_node_builder,
-                              node_animations_map_builder);
+                              &border_node_builder, &animate_node_builder);
   }
 
   const bool overflow_hidden =
@@ -472,17 +495,17 @@
        border_insets_.zero())) {
     // If there's no reason to distinguish between content and background,
     // just add them all to the same composition node.
-    RenderAndAnimateContent(&border_node_builder, node_animations_map_builder);
+    RenderAndAnimateContent(&border_node_builder);
   } else {
     CompositionNode::Builder content_node_builder;
     // Otherwise, deal with content specifically so that we can apply overflow:
     // hidden to the content but not the background.
-    RenderAndAnimateContent(&content_node_builder, node_animations_map_builder);
+    RenderAndAnimateContent(&content_node_builder);
     if (!content_node_builder.children().empty()) {
       border_node_builder.AddChild(RenderAndAnimateOverflow(
           padding_rounded_corners,
           new CompositionNode(content_node_builder.Pass()),
-          node_animations_map_builder, math::Vector2dF(0, 0)));
+          &animate_node_builder, math::Vector2dF(0, 0)));
     }
     // We've already applied overflow hidden, no need to apply it again later.
     overflow_hidden_needs_to_be_applied = false;
@@ -492,16 +515,22 @@
     scoped_refptr<render_tree::Node> border_node =
         new CompositionNode(border_node_builder.Pass());
     if (overflow_hidden_needs_to_be_applied) {
-      border_node = RenderAndAnimateOverflow(
-          padding_rounded_corners, border_node, node_animations_map_builder,
-          border_box_offset);
+      border_node =
+          RenderAndAnimateOverflow(padding_rounded_corners, border_node,
+                                   &animate_node_builder, border_box_offset);
     }
-    border_node = RenderAndAnimateOpacity(
-        border_node, node_animations_map_builder, opacity, opacity_animated);
-    border_node = RenderAndAnimateTransform(
-        border_node, node_animations_map_builder, border_box_offset);
+    border_node = RenderAndAnimateOpacity(border_node, &animate_node_builder,
+                                          opacity, opacity_animated);
+    border_node = RenderAndAnimateTransform(border_node, &animate_node_builder,
+                                            border_box_offset);
 
-    parent_content_node_builder->AddChild(border_node);
+    cached_render_tree_node_info_->node_ =
+        animate_node_builder.empty()
+            ? border_node
+            : scoped_refptr<render_tree::Node>(
+                  new AnimateNode(animate_node_builder, border_node));
+
+    parent_content_node_builder->AddChild(cached_render_tree_node_info_->node_);
   }
 }
 
@@ -536,6 +565,14 @@
 #endif  // COBALT_BOX_DUMP_ENABLED
 
 namespace {
+void PopulateBaseStyleForBackgroundNode(
+    const scoped_refptr<const cssom::CSSComputedStyleData>& source_style,
+    const scoped_refptr<cssom::CSSComputedStyleData>& destination_style) {
+  // NOTE: Properties set by PopulateBaseStyleForBackgroundNode() should match
+  // the properties used by SetupBackgroundNodeFromStyle().
+  destination_style->set_background_color(source_style->background_color());
+}
+
 void SetupBackgroundNodeFromStyle(
     const base::optional<RoundedCorners>& rounded_corners,
     const scoped_refptr<const cssom::CSSComputedStyleData>& style,
@@ -596,6 +633,36 @@
   return Border(left, right, top, bottom);
 }
 
+void PopulateBaseStyleForBorderNode(
+    const scoped_refptr<const cssom::CSSComputedStyleData>& source_style,
+    const scoped_refptr<cssom::CSSComputedStyleData>& destination_style) {
+  // NOTE: Properties set by PopulateBaseStyleForBorderNode() should match the
+  // properties used by SetupBorderNodeFromStyle().
+
+  // Left
+  destination_style->set_border_left_width(source_style->border_left_width());
+  destination_style->set_border_left_style(source_style->border_left_style());
+  destination_style->set_border_left_color(source_style->border_left_color());
+
+  // Right
+  destination_style->set_border_right_width(source_style->border_right_width());
+  destination_style->set_border_right_style(source_style->border_right_style());
+  destination_style->set_border_right_color(source_style->border_right_color());
+
+  // Top
+  destination_style->set_border_top_width(source_style->border_top_width());
+  destination_style->set_border_top_style(source_style->border_top_style());
+  destination_style->set_border_top_color(source_style->border_top_color());
+
+  // Bottom
+  destination_style->set_border_bottom_width(
+      source_style->border_bottom_width());
+  destination_style->set_border_bottom_style(
+      source_style->border_bottom_style());
+  destination_style->set_border_bottom_color(
+      source_style->border_bottom_color());
+}
+
 void SetupBorderNodeFromStyle(
     const base::optional<RoundedCorners>& rounded_corners,
     const scoped_refptr<const cssom::CSSComputedStyleData>& style,
@@ -774,7 +841,7 @@
 // CSS transform style property.  If the object does not have a transform
 // style property set, this will be the identity matrix.  Otherwise, it is
 // calculated from the property value and returned.  The transform-origin
-// style property will also be taken into account, and therefore the layed
+// style property will also be taken into account, and therefore the laid
 // out size of the object is also required in order to resolve a
 // percentage-based transform-origin.
 math::Matrix3F GetCSSTransform(
@@ -797,10 +864,20 @@
          math::TranslateMatrix(-origin.x(), -origin.y());
 }
 
-// Used within the animation callback for CSS transforms.  This will
-// set the transform of a single-child composition node to that specified by
-// the CSS transform of the provided CSS Style Declaration.
-void SetupCompositionNodeFromCSSSStyleTransform(
+void PopulateBaseStyleForMatrixTransformNode(
+    const scoped_refptr<const cssom::CSSComputedStyleData>& source_style,
+    const scoped_refptr<cssom::CSSComputedStyleData>& destination_style) {
+  // NOTE: Properties set by PopulateBaseStyleForMatrixTransformNode() should
+  // match the properties used by
+  // SetupMatrixTransformNodeFromCSSSStyleTransform().
+  destination_style->set_transform(source_style->transform());
+  destination_style->set_transform_origin(source_style->transform_origin());
+}
+
+// Used within the animation callback for CSS transforms.  This will set the
+// transform of a single-child matrix transform node to that specified by the
+// CSS transform of the provided CSS Style Declaration.
+void SetupMatrixTransformNodeFromCSSSStyleTransform(
     const math::RectF& used_rect,
     const scoped_refptr<const cssom::CSSComputedStyleData>& style,
     MatrixTransformNode::Builder* transform_node_builder) {
@@ -808,6 +885,14 @@
       GetCSSTransform(style->transform(), style->transform_origin(), used_rect);
 }
 
+void PopulateBaseStyleForFilterNode(
+    const scoped_refptr<const cssom::CSSComputedStyleData>& source_style,
+    const scoped_refptr<cssom::CSSComputedStyleData>& destination_style) {
+  // NOTE: Properties set by PopulateBaseStyleForFilterNode() should match the
+  // properties used by SetupFilterNodeFromStyle().
+  destination_style->set_opacity(source_style->opacity());
+}
+
 void SetupFilterNodeFromStyle(
     const scoped_refptr<const cssom::CSSComputedStyleData>& style,
     FilterNode::Builder* filter_node_builder) {
@@ -843,8 +928,8 @@
 void Box::RenderAndAnimateBoxShadow(
     const base::optional<RoundedCorners>& rounded_corners,
     CompositionNode::Builder* border_node_builder,
-    NodeAnimationsMap::Builder* node_animations_map_builder) const {
-  UNREFERENCED_PARAMETER(node_animations_map_builder);
+    AnimateNode::Builder* animate_node_builder) {
+  UNREFERENCED_PARAMETER(animate_node_builder);
 
   if (computed_style()->box_shadow() != cssom::KeywordValue::GetNone()) {
     const cssom::PropertyListValue* box_shadow_list =
@@ -907,7 +992,7 @@
 void Box::RenderAndAnimateBorder(
     const base::optional<RoundedCorners>& rounded_corners,
     CompositionNode::Builder* border_node_builder,
-    NodeAnimationsMap::Builder* node_animations_map_builder) const {
+    AnimateNode::Builder* animate_node_builder) {
   // If the border is absent or all borders are transparent, there is no need
   // to render border.
   if (border_insets_.zero() || AreAllBordersTransparent(computed_style())) {
@@ -924,16 +1009,16 @@
 
   if (HasAnimatedBorder(animations())) {
     AddAnimations<RectNode>(
+        base::Bind(&PopulateBaseStyleForBorderNode),
         base::Bind(&SetupBorderNodeFromStyle, rounded_corners),
-        *css_computed_style_declaration(), border_node,
-        node_animations_map_builder);
+        *css_computed_style_declaration(), border_node, animate_node_builder);
   }
 }
 
 void Box::RenderAndAnimateBackgroundColor(
     const base::optional<RoundedCorners>& rounded_corners,
     render_tree::CompositionNode::Builder* border_node_builder,
-    NodeAnimationsMap::Builder* node_animations_map_builder) const {
+    AnimateNode::Builder* animate_node_builder) {
   // Only create the RectNode if the background color is not the initial value
   // (which we know is transparent) and not transparent.  If it's animated,
   // add it no matter what since its value may change over time to be
@@ -958,9 +1043,9 @@
       // instead here.
       if (background_color_animated) {
         AddAnimations<RectNode>(
+            base::Bind(&PopulateBaseStyleForBackgroundNode),
             base::Bind(&SetupBackgroundNodeFromStyle, rounded_corners),
-            *css_computed_style_declaration(), rect_node,
-            node_animations_map_builder);
+            *css_computed_style_declaration(), rect_node, animate_node_builder);
       }
     }
   }
@@ -969,8 +1054,8 @@
 void Box::RenderAndAnimateBackgroundImage(
     const base::optional<RoundedCorners>& rounded_corners,
     CompositionNode::Builder* border_node_builder,
-    NodeAnimationsMap::Builder* node_animations_map_builder) const {
-  UNREFERENCED_PARAMETER(node_animations_map_builder);
+    AnimateNode::Builder* animate_node_builder) {
+  UNREFERENCED_PARAMETER(animate_node_builder);
 
   math::RectF image_frame(
       math::PointF(border_left_width().toFloat(), border_top_width().toFloat()),
@@ -1012,9 +1097,8 @@
 
 scoped_refptr<render_tree::Node> Box::RenderAndAnimateOpacity(
     const scoped_refptr<render_tree::Node>& border_node,
-    render_tree::animations::NodeAnimationsMap::Builder*
-        node_animations_map_builder,
-    float opacity, bool opacity_animated) const {
+    AnimateNode::Builder* animate_node_builder, float opacity,
+    bool opacity_animated) {
   if (opacity < 1.0f || opacity_animated) {
     FilterNode::Builder filter_node_builder(border_node);
 
@@ -1026,9 +1110,10 @@
 
     if (opacity_animated) {
       // Possibly setup an animation for opacity.
-      AddAnimations<FilterNode>(base::Bind(&SetupFilterNodeFromStyle),
+      AddAnimations<FilterNode>(base::Bind(&PopulateBaseStyleForFilterNode),
+                                base::Bind(&SetupFilterNodeFromStyle),
                                 *css_computed_style_declaration(), filter_node,
-                                node_animations_map_builder);
+                                animate_node_builder);
     }
     return filter_node;
   }
@@ -1038,10 +1123,9 @@
 
 scoped_refptr<render_tree::Node> Box::RenderAndAnimateOverflow(
     const base::optional<render_tree::RoundedCorners>& rounded_corners,
-    const scoped_refptr<render_tree::Node>& content_node,
-    render_tree::animations::NodeAnimationsMap::Builder*
-    /* node_animations_map_builder */,
-    const math::Vector2dF& border_node_offset) const {
+    const scoped_refptr<render_tree::Node>& content_node, AnimateNode::Builder*
+    /* animate_node_builder */,
+    const math::Vector2dF& border_node_offset) {
   bool overflow_hidden =
       computed_style()->overflow().get() == cssom::KeywordValue::GetHidden();
 
@@ -1069,24 +1153,25 @@
 
 scoped_refptr<render_tree::Node> Box::RenderAndAnimateTransform(
     const scoped_refptr<render_tree::Node>& border_node,
-    render_tree::animations::NodeAnimationsMap::Builder*
-        node_animations_map_builder,
-    const math::Vector2dF& border_node_offset) const {
+    AnimateNode::Builder* animate_node_builder,
+    const math::Vector2dF& border_node_offset) {
   if (IsTransformable() &&
       animations()->IsPropertyAnimated(cssom::kTransformProperty)) {
     // If the CSS transform is animated, we cannot flatten it into the layout
-    // transform, thus we create a new composition node to separate it and
+    // transform, thus we create a new matrix transform node to separate it and
     // animate that node only.
     scoped_refptr<MatrixTransformNode> css_transform_node =
         new MatrixTransformNode(border_node, math::Matrix3F::Identity());
 
-    // Specifically animate only the composition node with the CSS transform.
+    // Specifically animate only the matrix transform node with the CSS
+    // transform.
     AddAnimations<MatrixTransformNode>(
-        base::Bind(&SetupCompositionNodeFromCSSSStyleTransform,
+        base::Bind(&PopulateBaseStyleForMatrixTransformNode),
+        base::Bind(&SetupMatrixTransformNodeFromCSSSStyleTransform,
                    math::RectF(PointAtOffsetFromOrigin(border_node_offset),
                                GetBorderBoxSize())),
         *css_computed_style_declaration(), css_transform_node,
-        node_animations_map_builder);
+        animate_node_builder);
 
     return css_transform_node;
   }
diff --git a/src/cobalt/layout/box.h b/src/cobalt/layout/box.h
index a85dfc5..676b04d 100644
--- a/src/cobalt/layout/box.h
+++ b/src/cobalt/layout/box.h
@@ -37,7 +37,7 @@
 #include "cobalt/layout/vector2d_layout_unit.h"
 #include "cobalt/math/point_f.h"
 #include "cobalt/math/rect_f.h"
-#include "cobalt/render_tree/animations/node_animations_map.h"
+#include "cobalt/render_tree/animations/animate_node.h"
 #include "cobalt/render_tree/composition_node.h"
 #include "cobalt/web_animations/animation_set.h"
 
@@ -314,8 +314,15 @@
   // element on a line."
   //   https://www.w3.org/TR/css3-ui/#propdef-text-overflow
   virtual bool DoesFulfillEllipsisPlacementRequirement() const { return false; }
-  // Reset all ellipses-related state within the box.
-  virtual void ResetEllipses() {}
+  // Do any processing needed prior to ellipsis placement. This involves caching
+  // the old value and resetting the current value so it can be determined
+  // whether or not the ellipsis state within a box changed as a a result of
+  // ellipsis placement.
+  virtual void DoPreEllipsisPlacementProcessing() {}
+  // Do any processing needed following ellipsis placement. This involves
+  // checking the old value against the new value and resetting the cached
+  // render tree node if the ellipsis state changed.
+  virtual void DoPostEllipsisPlacementProcessing() {}
   // Whether or not the box is fully hidden by an ellipsis. This applies to
   // atomic inline-level elements that have had an ellipsis placed before them
   // on a line. https://www.w3.org/TR/css3-ui/#propdef-text-overflow
@@ -401,14 +408,16 @@
   // time they are needed.
   virtual void InvalidateCrossReferencesOfBoxAndAncestors();
 
+  // Invalidating the render tree nodes causes them to be re-generated the next
+  // time they are needed.
+  void InvalidateRenderTreeNodesOfBoxAndAncestors();
+
   // Converts a layout subtree into a render subtree.
   // This method defines the overall strategy of the conversion and relies
   // on the subclasses to provide the actual content.
   void RenderAndAnimate(
       render_tree::CompositionNode::Builder* parent_content_node_builder,
-      render_tree::animations::NodeAnimationsMap::Builder*
-          node_animations_map_builder,
-      const math::Vector2dF& offset_from_parent_node) const;
+      const math::Vector2dF& offset_from_parent_node);
 
   // Poor man's reflection.
   virtual AnonymousBlockBox* AsAnonymousBlockBox();
@@ -528,9 +537,7 @@
 
   // Renders the content of the box.
   virtual void RenderAndAnimateContent(
-      render_tree::CompositionNode::Builder* border_node_builder,
-      render_tree::animations::NodeAnimationsMap::Builder*
-          node_animations_map_builder) const = 0;
+      render_tree::CompositionNode::Builder* border_node_builder) const = 0;
 
   // A transformable element is an element whose layout is governed by the CSS
   // box model which is either a block-level or atomic inline-level element.
@@ -564,6 +571,14 @@
       const base::optional<LayoutUnit>& possibly_overconstrained_margin_right);
 
  private:
+  struct CachedRenderTreeNodeInfo {
+    explicit CachedRenderTreeNodeInfo(const math::Vector2dF& offset)
+        : offset_(offset) {}
+
+    math::Vector2dF offset_;
+    scoped_refptr<render_tree::Node> node_;
+  };
+
   // Updates used values of "border" properties.
   void UpdateBorders();
   // Updates used values of "padding" properties.
@@ -583,47 +598,40 @@
   void RenderAndAnimateBorder(
       const base::optional<render_tree::RoundedCorners>& rounded_corners,
       render_tree::CompositionNode::Builder* border_node_builder,
-      render_tree::animations::NodeAnimationsMap::Builder*
-          node_animations_map_builder) const;
+      render_tree::animations::AnimateNode::Builder* animate_node_builder);
   void RenderAndAnimateBackgroundColor(
       const base::optional<render_tree::RoundedCorners>& rounded_corners,
       render_tree::CompositionNode::Builder* border_node_builder,
-      render_tree::animations::NodeAnimationsMap::Builder*
-          node_animations_map_builder) const;
+      render_tree::animations::AnimateNode::Builder* animate_node_builder);
   void RenderAndAnimateBackgroundImage(
       const base::optional<render_tree::RoundedCorners>& rounded_corners,
       render_tree::CompositionNode::Builder* border_node_builder,
-      render_tree::animations::NodeAnimationsMap::Builder*
-          node_animations_map_builder) const;
+      render_tree::animations::AnimateNode::Builder* animate_node_builder);
   void RenderAndAnimateBoxShadow(
       const base::optional<render_tree::RoundedCorners>& rounded_corners,
       render_tree::CompositionNode::Builder* border_node_builder,
-      render_tree::animations::NodeAnimationsMap::Builder*
-          node_animations_map_builder) const;
+      render_tree::animations::AnimateNode::Builder* animate_node_builder);
 
   // If opacity is animated or other than 1, wraps a border node into a filter
   // node. Otherwise returns the original border node.
   scoped_refptr<render_tree::Node> RenderAndAnimateOpacity(
       const scoped_refptr<render_tree::Node>& border_node,
-      render_tree::animations::NodeAnimationsMap::Builder*
-          node_animations_map_builder,
-      float opacity, bool opacity_animated) const;
+      render_tree::animations::AnimateNode::Builder* animate_node_builder,
+      float opacity, bool opacity_animated);
 
   scoped_refptr<render_tree::Node> RenderAndAnimateOverflow(
       const base::optional<render_tree::RoundedCorners>& rounded_corners,
       const scoped_refptr<render_tree::Node>& border_node,
-      render_tree::animations::NodeAnimationsMap::Builder*
-          node_animations_map_builder,
-      const math::Vector2dF& border_node_offset) const;
+      render_tree::animations::AnimateNode::Builder* animate_node_builder,
+      const math::Vector2dF& border_node_offset);
 
   // If transform is not "none", wraps a border node in a MatrixTransformNode.
   // If transform is "none", returns the original border node and leaves
   // |border_node_transform| intact.
   scoped_refptr<render_tree::Node> RenderAndAnimateTransform(
       const scoped_refptr<render_tree::Node>& border_node,
-      render_tree::animations::NodeAnimationsMap::Builder*
-          node_animations_map_builder,
-      const math::Vector2dF& border_node_offset) const;
+      render_tree::animations::AnimateNode::Builder* animate_node_builder,
+      const math::Vector2dF& border_node_offset);
 
   // The css_computed_style_declaration_ member references the
   // cssom::CSSComputedStyleDeclaration object owned by the HTML Element from
@@ -681,6 +689,10 @@
   // parameters we were passed during in last call to UpdateSizes().
   base::optional<LayoutParams> last_update_size_params_;
 
+  // Render tree node caching is used to prevent the node from needing to be
+  // recalculated during each call to RenderAndAnimateContent.
+  base::optional<CachedRenderTreeNodeInfo> cached_render_tree_node_info_;
+
   // For write access to parent/containing_block members.
   friend class ContainerBox;
   friend class LayoutBoxes;
diff --git a/src/cobalt/layout/box_generator.cc b/src/cobalt/layout/box_generator.cc
index a2affb9..1f2d803 100644
--- a/src/cobalt/layout/box_generator.cc
+++ b/src/cobalt/layout/box_generator.cc
@@ -317,8 +317,8 @@
 
   scoped_refptr<cssom::CSSComputedStyleDeclaration>
       css_computed_style_declaration = new cssom::CSSComputedStyleDeclaration();
-  css_computed_style_declaration->set_data(
-      GetComputedStyleOfAnonymousBox(br_element->computed_style()));
+  css_computed_style_declaration->SetData(GetComputedStyleOfAnonymousBox(
+      br_element->css_computed_style_declaration()));
 
   css_computed_style_declaration->set_animations(br_element->animations());
 
@@ -802,7 +802,7 @@
   new_data->AssignFrom(*style->data());
   new_data->SetPropertyValue(cssom::kBackgroundColorProperty, NULL);
   new_data->SetPropertyValue(cssom::kBackgroundImageProperty, NULL);
-  new_style->set_data(new_data);
+  new_style->SetData(new_data);
 
   return new_style;
 }
@@ -880,8 +880,8 @@
 void BoxGenerator::Visit(dom::Text* text) {
   scoped_refptr<cssom::CSSComputedStyleDeclaration>
       css_computed_style_declaration = new cssom::CSSComputedStyleDeclaration();
-  css_computed_style_declaration->set_data(GetComputedStyleOfAnonymousBox(
-      parent_css_computed_style_declaration_->data()));
+  css_computed_style_declaration->SetData(
+      GetComputedStyleOfAnonymousBox(parent_css_computed_style_declaration_));
 
   // Copy the animations from the parent.
   css_computed_style_declaration->set_animations(parent_animations_);
diff --git a/src/cobalt/layout/container_box.cc b/src/cobalt/layout/container_box.cc
index 24f72b1..4ee4b0b 100644
--- a/src/cobalt/layout/container_box.cc
+++ b/src/cobalt/layout/container_box.cc
@@ -93,6 +93,9 @@
     split_sibling->GetStackingContext()->are_cross_references_valid_ = false;
   }
 
+  // Invalidate the render tree nodes now that the children have changed.
+  InvalidateRenderTreeNodesOfBoxAndAncestors();
+
   return split_sibling_position;
 }
 
@@ -138,6 +141,9 @@
       !non_negative_z_index_child_.empty()) {
     are_cross_references_valid_ = false;
   }
+
+  // Invalidate the render tree nodes now that the children have changed.
+  InvalidateRenderTreeNodesOfBoxAndAncestors();
 }
 
 // Returns true if the given style allows a container box to act as a containing
@@ -471,8 +477,6 @@
 void ContainerBox::RenderAndAnimateStackingContextChildren(
     const ZIndexSortedList& z_index_child_list,
     render_tree::CompositionNode::Builder* content_node_builder,
-    render_tree::animations::NodeAnimationsMap::Builder*
-        node_animations_map_builder,
     const Vector2dLayoutUnit& offset_from_parent_node) const {
   // Render all children of the passed in list in sorted order.
   for (ZIndexSortedList::const_iterator iter = z_index_child_list.begin();
@@ -484,8 +488,7 @@
         GetOffsetFromStackingContextToContainingBlock(child_box) +
         offset_from_parent_node;
 
-    child_box->RenderAndAnimate(content_node_builder,
-                                node_animations_map_builder, position_offset);
+    child_box->RenderAndAnimate(content_node_builder, position_offset);
   }
 }
 
@@ -552,9 +555,7 @@
 }
 
 void ContainerBox::RenderAndAnimateContent(
-    render_tree::CompositionNode::Builder* border_node_builder,
-    render_tree::animations::NodeAnimationsMap::Builder*
-        node_animations_map_builder) const {
+    render_tree::CompositionNode::Builder* border_node_builder) const {
   // Ensure that the cross references are up to date.
   const_cast<ContainerBox*>(this)->UpdateCrossReferences();
 
@@ -564,22 +565,19 @@
   // z-index values.
   //   https://www.w3.org/TR/CSS21/visuren.html#z-index
   RenderAndAnimateStackingContextChildren(
-      negative_z_index_child_, border_node_builder, node_animations_map_builder,
-      content_box_offset);
+      negative_z_index_child_, border_node_builder, content_box_offset);
   // Render laid out child boxes.
   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;
     if (!child_box->IsPositioned() && !child_box->IsTransformed()) {
-      child_box->RenderAndAnimate(
-          border_node_builder, node_animations_map_builder, content_box_offset);
+      child_box->RenderAndAnimate(border_node_builder, content_box_offset);
     }
   }
   // Render all positioned children with non-negative z-index values.
   //   https://www.w3.org/TR/CSS21/visuren.html#z-index
   RenderAndAnimateStackingContextChildren(
-      non_negative_z_index_child_, border_node_builder,
-      node_animations_map_builder, content_box_offset);
+      non_negative_z_index_child_, border_node_builder, content_box_offset);
 }
 
 #ifdef COBALT_BOX_DUMP_ENABLED
diff --git a/src/cobalt/layout/container_box.h b/src/cobalt/layout/container_box.h
index 31aba2b..2a13c91 100644
--- a/src/cobalt/layout/container_box.h
+++ b/src/cobalt/layout/container_box.h
@@ -62,10 +62,8 @@
   ContainerBox* AsContainerBox() OVERRIDE;
   const ContainerBox* AsContainerBox() const OVERRIDE;
 
-  void RenderAndAnimateContent(
-      render_tree::CompositionNode::Builder* border_node_builder,
-      render_tree::animations::NodeAnimationsMap::Builder*
-          node_animations_map_builder) const OVERRIDE;
+  void RenderAndAnimateContent(render_tree::CompositionNode::Builder*
+                                   border_node_builder) const OVERRIDE;
 
 #ifdef COBALT_BOX_DUMP_ENABLED
   void DumpChildrenWithIndent(std::ostream* stream, int indent) const OVERRIDE;
@@ -167,8 +165,6 @@
   void RenderAndAnimateStackingContextChildren(
       const ZIndexSortedList& z_index_child_list,
       render_tree::CompositionNode::Builder* border_node_builder,
-      render_tree::animations::NodeAnimationsMap::Builder*
-          node_animations_map_builder,
       const Vector2dLayoutUnit& offset_from_parent_node) const;
 
   // A list of our direct children.  If a box is one of our child boxes, we
diff --git a/src/cobalt/layout/initial_containing_block.cc b/src/cobalt/layout/initial_containing_block.cc
index 7c22f89..6bf5891 100644
--- a/src/cobalt/layout/initial_containing_block.cc
+++ b/src/cobalt/layout/initial_containing_block.cc
@@ -98,7 +98,7 @@
 
   scoped_refptr<cssom::CSSComputedStyleDeclaration> initial_style_state =
       new cssom::CSSComputedStyleDeclaration();
-  initial_style_state->set_data(initial_containing_block_style);
+  initial_style_state->SetData(initial_containing_block_style);
   initial_style_state->set_animations(new web_animations::AnimationSet());
 
   results.box = make_scoped_refptr(new BlockLevelBlockContainerBox(
diff --git a/src/cobalt/layout/inline_container_box.cc b/src/cobalt/layout/inline_container_box.cc
index 062bc6e..4ce8255 100644
--- a/src/cobalt/layout/inline_container_box.cc
+++ b/src/cobalt/layout/inline_container_box.cc
@@ -222,10 +222,17 @@
   return false;
 }
 
-void InlineContainerBox::ResetEllipses() {
+void InlineContainerBox::DoPreEllipsisPlacementProcessing() {
   for (Boxes::const_iterator child_box_iterator = child_boxes().begin();
        child_box_iterator != child_boxes().end(); ++child_box_iterator) {
-    (*child_box_iterator)->ResetEllipses();
+    (*child_box_iterator)->DoPreEllipsisPlacementProcessing();
+  }
+}
+
+void InlineContainerBox::DoPostEllipsisPlacementProcessing() {
+  for (Boxes::const_iterator child_box_iterator = child_boxes().begin();
+       child_box_iterator != child_boxes().end(); ++child_box_iterator) {
+    (*child_box_iterator)->DoPostEllipsisPlacementProcessing();
   }
 }
 
diff --git a/src/cobalt/layout/inline_container_box.h b/src/cobalt/layout/inline_container_box.h
index 8c873a0..6444c0e 100644
--- a/src/cobalt/layout/inline_container_box.h
+++ b/src/cobalt/layout/inline_container_box.h
@@ -58,7 +58,8 @@
   Box* GetSplitSibling() const OVERRIDE;
 
   bool DoesFulfillEllipsisPlacementRequirement() const OVERRIDE;
-  void ResetEllipses() OVERRIDE;
+  void DoPreEllipsisPlacementProcessing() OVERRIDE;
+  void DoPostEllipsisPlacementProcessing() OVERRIDE;
 
   bool TrySplitAtSecondBidiLevelRun() OVERRIDE;
   base::optional<int> GetBidiLevel() const OVERRIDE;
diff --git a/src/cobalt/layout/inline_level_replaced_box.cc b/src/cobalt/layout/inline_level_replaced_box.cc
index 8603e7d..9d6072c 100644
--- a/src/cobalt/layout/inline_level_replaced_box.cc
+++ b/src/cobalt/layout/inline_level_replaced_box.cc
@@ -35,7 +35,8 @@
                   text_position, maybe_intrinsic_width, maybe_intrinsic_height,
                   maybe_intrinsic_ratio, used_style_provider,
                   layout_stat_tracker),
-      is_hidden_by_ellipsis_(false) {}
+      is_hidden_by_ellipsis_(false),
+      was_hidden_by_ellipsis_(false) {}
 
 Box::Level InlineLevelReplacedBox::GetLevel() const { return kInlineLevel; }
 
@@ -46,7 +47,16 @@
   return true;
 }
 
-void InlineLevelReplacedBox::ResetEllipses() { is_hidden_by_ellipsis_ = false; }
+void InlineLevelReplacedBox::DoPreEllipsisPlacementProcessing() {
+  was_hidden_by_ellipsis_ = is_hidden_by_ellipsis_;
+  is_hidden_by_ellipsis_ = false;
+}
+
+void InlineLevelReplacedBox::DoPostEllipsisPlacementProcessing() {
+  if (was_hidden_by_ellipsis_ != is_hidden_by_ellipsis_) {
+    InvalidateRenderTreeNodesOfBoxAndAncestors();
+  }
+}
 
 bool InlineLevelReplacedBox::IsHiddenByEllipsis() const {
   return is_hidden_by_ellipsis_;
diff --git a/src/cobalt/layout/inline_level_replaced_box.h b/src/cobalt/layout/inline_level_replaced_box.h
index a53c1f6..b0f1a25 100644
--- a/src/cobalt/layout/inline_level_replaced_box.h
+++ b/src/cobalt/layout/inline_level_replaced_box.h
@@ -48,7 +48,8 @@
   Level GetLevel() const OVERRIDE;
 
   bool DoesFulfillEllipsisPlacementRequirement() const OVERRIDE;
-  void ResetEllipses() OVERRIDE;
+  void DoPreEllipsisPlacementProcessing() OVERRIDE;
+  void DoPostEllipsisPlacementProcessing() OVERRIDE;
   bool IsHiddenByEllipsis() const OVERRIDE;
 
  protected:
@@ -76,6 +77,11 @@
   // the applicable edge(s) of the line as necessary to fit the ellipsis."
   //   https://www.w3.org/TR/css3-ui/#propdef-text-overflow
   bool is_hidden_by_ellipsis_;
+  // Tracking of the previous value of |is_hidden_by_ellipsis_|, which allows
+  // for determination of whether or not the value changed during ellipsis
+  // placement. When this occurs, the cached render tree nodes of this box and
+  // its ancestors are invalidated.
+  bool was_hidden_by_ellipsis_;
 };
 
 }  // namespace layout
diff --git a/src/cobalt/layout/layout.cc b/src/cobalt/layout/layout.cc
index 9acfffb..d517a4f 100644
--- a/src/cobalt/layout/layout.cc
+++ b/src/cobalt/layout/layout.cc
@@ -28,7 +28,7 @@
 #include "cobalt/layout/box_generator.h"
 #include "cobalt/layout/initial_containing_block.h"
 #include "cobalt/layout/used_style.h"
-#include "cobalt/render_tree/animations/node_animations_map.h"
+#include "cobalt/render_tree/animations/animate_node.h"
 
 namespace cobalt {
 namespace layout {
@@ -73,8 +73,8 @@
   // Create initial containing block.
   InitialContainingBlockCreationResults
       initial_containing_block_creation_results = CreateInitialContainingBlock(
-          document->initial_computed_style(), document, used_style_provider,
-          layout_stat_tracker);
+          document->initial_computed_style_data(), document,
+          used_style_provider, layout_stat_tracker);
   *initial_containing_block = initial_containing_block_creation_results.box;
 
   // Generate boxes.
@@ -128,7 +128,7 @@
   }
 }
 
-RenderTreeWithAnimations Layout(
+scoped_refptr<render_tree::Node> Layout(
     const icu::Locale& locale, const scoped_refptr<dom::Document>& document,
     UsedStyleProvider* used_style_provider,
     LayoutStatTracker* layout_stat_tracker,
@@ -141,8 +141,6 @@
       line_break_iterator, character_break_iterator, initial_containing_block);
 
   // Add to render tree.
-  render_tree::animations::NodeAnimationsMap::Builder
-      node_animations_map_builder;
   render_tree::CompositionNode::Builder render_tree_root_builder;
   {
     TRACE_EVENT0("cobalt::layout", kBenchmarkStatRenderAndAnimate);
@@ -151,14 +149,18 @@
         base::StopWatch::kAutoStartOn, layout_stat_tracker);
 
     (*initial_containing_block)
-        ->RenderAndAnimate(&render_tree_root_builder,
-                           &node_animations_map_builder, math::Vector2dF(0, 0));
+        ->RenderAndAnimate(&render_tree_root_builder, math::Vector2dF(0, 0));
   }
 
-  return RenderTreeWithAnimations(
-      new render_tree::CompositionNode(render_tree_root_builder.Pass()),
-      new render_tree::animations::NodeAnimationsMap(
-          node_animations_map_builder.Pass()));
+  render_tree::CompositionNode* static_root_node =
+      new render_tree::CompositionNode(render_tree_root_builder.Pass());
+
+  // Make it easy to animate the entire tree by placing an AnimateNode at the
+  // root to merge any sub-AnimateNodes.
+  render_tree::animations::AnimateNode* animate_node =
+      new render_tree::animations::AnimateNode(static_root_node);
+
+  return animate_node;
 }
 
 }  // namespace layout
diff --git a/src/cobalt/layout/layout.h b/src/cobalt/layout/layout.h
index 9b8bf8e..d9cdf7a 100644
--- a/src/cobalt/layout/layout.h
+++ b/src/cobalt/layout/layout.h
@@ -21,7 +21,7 @@
 #include "cobalt/layout/block_formatting_block_container_box.h"
 #include "cobalt/loader/image/image_cache.h"
 #include "cobalt/math/size_f.h"
-#include "cobalt/render_tree/animations/node_animations_map.h"
+#include "cobalt/render_tree/animations/animate_node.h"
 #include "cobalt/render_tree/node.h"
 #include "cobalt/render_tree/resource_provider.h"
 #include "third_party/icu/public/common/unicode/brkiter.h"
@@ -40,17 +40,6 @@
 // (https://www.w3.org/TR/CSS2/visuren.html) as recommended by a newer draft
 // (http://dev.w3.org/csswg/css-box/) which is undergoing active changes.
 
-struct RenderTreeWithAnimations {
-  RenderTreeWithAnimations(
-      const scoped_refptr<render_tree::Node>& render_tree,
-      const scoped_refptr<render_tree::animations::NodeAnimationsMap>&
-          animations)
-      : render_tree(render_tree), animations(animations) {}
-
-  scoped_refptr<render_tree::Node> render_tree;
-  scoped_refptr<render_tree::animations::NodeAnimationsMap> animations;
-};
-
 // Update the computed styles, then generate and layout the box tree.
 void UpdateComputedStylesAndLayoutBoxTree(
     const icu::Locale& locale, const scoped_refptr<dom::Document>& document,
@@ -63,7 +52,7 @@
 // Main entry point to the layout engine.
 // Produces the render tree (along with corresponding animations) which is a
 // result of recursive layout of the given HTML element.
-RenderTreeWithAnimations Layout(
+scoped_refptr<render_tree::Node> Layout(
     const icu::Locale& locale, const scoped_refptr<dom::Document>& document,
     UsedStyleProvider* used_style_provider,
     LayoutStatTracker* layout_stat_tracker,
diff --git a/src/cobalt/layout/layout_boxes.cc b/src/cobalt/layout/layout_boxes.cc
index 2c65d99..8a95115 100644
--- a/src/cobalt/layout/layout_boxes.cc
+++ b/src/cobalt/layout/layout_boxes.cc
@@ -159,6 +159,17 @@
   }
 }
 
+void LayoutBoxes::InvalidateRenderTreeNodes() {
+  for (Boxes::const_iterator box_iterator = boxes_.begin();
+       box_iterator != boxes_.end(); ++box_iterator) {
+    Box* box = *box_iterator;
+    do {
+      box->InvalidateRenderTreeNodesOfBoxAndAncestors();
+      box = box->GetSplitSibling();
+    } while (box != NULL);
+  }
+}
+
 math::RectF LayoutBoxes::GetBoundingBorderRectangle() const {
   // In the CSSOM View extensions to the HTMLElement interface, at
   // https://www.w3.org/TR/2013/WD-cssom-view-20131217/#extensions-to-the-htmlelement-interface,
diff --git a/src/cobalt/layout/layout_boxes.h b/src/cobalt/layout/layout_boxes.h
index 28708a8..055d1e0 100644
--- a/src/cobalt/layout/layout_boxes.h
+++ b/src/cobalt/layout/layout_boxes.h
@@ -58,6 +58,7 @@
 
   void InvalidateSizes() OVERRIDE;
   void InvalidateCrossReferences() OVERRIDE;
+  void InvalidateRenderTreeNodes() OVERRIDE;
 
   // Other
   //
diff --git a/src/cobalt/layout/layout_manager.cc b/src/cobalt/layout/layout_manager.cc
index b92c47b..c0fb5c6 100644
--- a/src/cobalt/layout/layout_manager.cc
+++ b/src/cobalt/layout/layout_manager.cc
@@ -239,7 +239,7 @@
       TRACE_EVENT_BEGIN0("cobalt::layout", kBenchmarkStatLayout);
     }
 
-    RenderTreeWithAnimations render_tree_with_animations = layout::Layout(
+    scoped_refptr<render_tree::Node> render_tree_root = layout::Layout(
         locale_, window_->document(), used_style_provider_.get(),
         layout_stat_tracker_, line_break_iterator_.get(),
         character_break_iterator_.get(), &initial_containing_block_);
@@ -251,11 +251,9 @@
     }
 #endif  // ENABLE_TEST_RUNNER
     if (run_on_render_tree_produced_callback) {
-      on_render_tree_produced_callback_.Run(
-          LayoutResults(render_tree_with_animations.render_tree,
-                        render_tree_with_animations.animations,
-                        base::TimeDelta::FromMillisecondsD(
-                            *document->timeline()->current_time())));
+      on_render_tree_produced_callback_.Run(LayoutResults(
+          render_tree_root, base::TimeDelta::FromMillisecondsD(
+                                *document->timeline()->current_time())));
     }
 
     layout_dirty_ = false;
diff --git a/src/cobalt/layout/layout_manager.h b/src/cobalt/layout/layout_manager.h
index 4a9b405..39e4eb7 100644
--- a/src/cobalt/layout/layout_manager.h
+++ b/src/cobalt/layout/layout_manager.h
@@ -25,7 +25,6 @@
 #include "cobalt/dom/window.h"
 #include "cobalt/layout/layout_stat_tracker.h"
 #include "cobalt/loader/image/image_cache.h"
-#include "cobalt/render_tree/animations/node_animations_map.h"
 #include "cobalt/render_tree/node.h"
 #include "cobalt/render_tree/resource_provider.h"
 
@@ -37,19 +36,15 @@
  public:
   struct LayoutResults {
     LayoutResults(const scoped_refptr<render_tree::Node>& render_tree,
-                  const scoped_refptr<
-                      render_tree::animations::NodeAnimationsMap>& animations,
                   const base::TimeDelta& layout_time)
         : render_tree(render_tree),
-          animations(animations),
           layout_time(layout_time) {}
 
     // The render tree produced by a layout.
     scoped_refptr<render_tree::Node> render_tree;
-    // Animations that are to be applied to the layout's render tree.
-    scoped_refptr<render_tree::animations::NodeAnimationsMap> animations;
+
     // The time that the render tree was created, which will be used as a
-    // reference point for updating the animations specified above.
+    // reference point for updating the animations in the above render tree.
     base::TimeDelta layout_time;
   };
 
diff --git a/src/cobalt/layout/render_tree_animations.h b/src/cobalt/layout/render_tree_animations.h
index 07121eb..0c8a862 100644
--- a/src/cobalt/layout/render_tree_animations.h
+++ b/src/cobalt/layout/render_tree_animations.h
@@ -33,6 +33,15 @@
 // a convenience function that can be used by code that creates render tree
 // nodes (e.g. layout box tree processing).
 
+// This callback function defines a function that is expected to populate a
+// given CSS style object for a render tree node type.
+class PopulateBaseStyleForRenderTreeNode {
+ public:
+  typedef base::Callback<void(
+      const scoped_refptr<const cssom::CSSComputedStyleData>&,
+      const scoped_refptr<cssom::CSSComputedStyleData>&)> Function;
+};
+
 // This callback function defines a function that is expected to apply a given
 // CSS style to a render tree node builder object.  A function meeting this
 // specification can be passed into AddAnimations() in order to
@@ -47,16 +56,16 @@
       typename T::Builder*)> Function;
 };
 
-// Helper function that applies a animation set to a base style to produce
+// Helper function that applies an animation set to a base style to produce
 // an animated style that is then passed into the provided
 // ApplyStyleToRenderTreeNode<T>::Function callback function.
 template <typename T>
-void AnimateNode(const typename ApplyStyleToRenderTreeNode<T>::Function&
-                     apply_style_function,
-                 const web_animations::BakedAnimationSet& animations,
-                 const scoped_refptr<cssom::CSSComputedStyleData>& base_style,
-                 typename T::Builder* node_builder,
-                 base::TimeDelta time_elapsed) {
+void ApplyAnimation(
+    const typename ApplyStyleToRenderTreeNode<T>::Function&
+        apply_style_function,
+    const web_animations::BakedAnimationSet& animations,
+    const scoped_refptr<cssom::CSSComputedStyleData>& base_style,
+    typename T::Builder* node_builder, base::TimeDelta time_elapsed) {
   scoped_refptr<cssom::CSSComputedStyleData> animated_style =
       new cssom::CSSComputedStyleData();
   animated_style->AssignFrom(*base_style);
@@ -65,26 +74,30 @@
 }
 
 // If animations exist, this function will add an animation which represents
-// the animations to the passed in NodeAnimationsMap.  The animation will
+// the animations to the passed in ApplyAnimation.  The animation will
 // target the passed in render tree node.
 template <typename T>
 void AddAnimations(
+    const typename PopulateBaseStyleForRenderTreeNode::Function&
+        populate_base_style_function,
     const typename ApplyStyleToRenderTreeNode<T>::Function&
         apply_style_function,
     const cssom::CSSComputedStyleDeclaration& css_computed_style_declaration,
     const scoped_refptr<T>& target_node,
-    render_tree::animations::NodeAnimationsMap::Builder*
-        node_animation_map_builder) {
+    render_tree::animations::AnimateNode::Builder* node_animation_map_builder) {
   DCHECK(!css_computed_style_declaration.animations()->IsEmpty());
-  scoped_refptr<cssom::CSSComputedStyleData> base_style_copy =
+
+  // Populate the base style.
+  scoped_refptr<cssom::CSSComputedStyleData> base_style =
       new cssom::CSSComputedStyleData();
-  base_style_copy->AssignFrom(*css_computed_style_declaration.data());
+  populate_base_style_function.Run(css_computed_style_declaration.data(),
+                                   base_style);
 
   node_animation_map_builder->Add(
-      target_node, base::Bind(&AnimateNode<T>, apply_style_function,
+      target_node, base::Bind(&ApplyAnimation<T>, apply_style_function,
                               web_animations::BakedAnimationSet(
                                   *css_computed_style_declaration.animations()),
-                              base_style_copy));
+                              base_style));
 }
 
 }  // namespace layout
diff --git a/src/cobalt/layout/replaced_box.cc b/src/cobalt/layout/replaced_box.cc
index 62b771f..15f0d6a 100644
--- a/src/cobalt/layout/replaced_box.cc
+++ b/src/cobalt/layout/replaced_box.cc
@@ -46,7 +46,7 @@
 namespace cobalt {
 namespace layout {
 
-using render_tree::animations::NodeAnimationsMap;
+using render_tree::animations::AnimateNode;
 using render_tree::CompositionNode;
 using render_tree::ImageNode;
 using render_tree::PunchThroughVideoNode;
@@ -239,8 +239,7 @@
 }  // namespace
 
 void ReplacedBox::RenderAndAnimateContent(
-    CompositionNode::Builder* border_node_builder,
-    NodeAnimationsMap::Builder* node_animations_map_builder) const {
+    CompositionNode::Builder* border_node_builder) const {
   if (computed_style()->visibility() != cssom::KeywordValue::GetVisible()) {
     return;
   }
@@ -257,11 +256,13 @@
   scoped_refptr<CompositionNode> composition_node =
       new CompositionNode(composition_node_builder);
 
-  node_animations_map_builder->Add(
+  AnimateNode::Builder animate_node_builder;
+  animate_node_builder.Add(
       composition_node,
       base::Bind(AnimateCB, replace_image_cb_, content_box_size()));
 
-  border_node_builder->AddChild(composition_node);
+  border_node_builder->AddChild(
+      new AnimateNode(animate_node_builder, composition_node));
 }
 
 void ReplacedBox::UpdateContentSizeAndMargins(
diff --git a/src/cobalt/layout/replaced_box.h b/src/cobalt/layout/replaced_box.h
index f503db3..259b2d0 100644
--- a/src/cobalt/layout/replaced_box.h
+++ b/src/cobalt/layout/replaced_box.h
@@ -76,10 +76,8 @@
   // From |Box|.
   void UpdateContentSizeAndMargins(const LayoutParams& layout_params) OVERRIDE;
 
-  void RenderAndAnimateContent(
-      render_tree::CompositionNode::Builder* border_node_builder,
-      render_tree::animations::NodeAnimationsMap::Builder*
-          node_animations_map_builder) const OVERRIDE;
+  void RenderAndAnimateContent(render_tree::CompositionNode::Builder*
+                                   border_node_builder) const OVERRIDE;
 
   bool IsTransformable() const OVERRIDE { return true; }
 
diff --git a/src/cobalt/layout/text_box.cc b/src/cobalt/layout/text_box.cc
index 84e5823..1b4e96e 100644
--- a/src/cobalt/layout/text_box.cc
+++ b/src/cobalt/layout/text_box.cc
@@ -46,6 +46,7 @@
       text_start_position_(text_start_position),
       text_end_position_(text_end_position),
       truncated_text_end_position_(text_end_position),
+      previous_truncated_text_end_position_(text_end_position),
       truncated_text_offset_from_left_(0),
       used_font_(used_style_provider->GetUsedFontList(
           css_computed_style_declaration->data()->font_family(),
@@ -225,10 +226,17 @@
   return GetNonCollapsedTextStartPosition() < GetNonCollapsedTextEndPosition();
 }
 
-void TextBox::ResetEllipses() {
+void TextBox::DoPreEllipsisPlacementProcessing() {
+  previous_truncated_text_end_position_ = truncated_text_end_position_;
   truncated_text_end_position_ = text_end_position_;
 }
 
+void TextBox::DoPostEllipsisPlacementProcessing() {
+  if (previous_truncated_text_end_position_ != truncated_text_end_position_) {
+    InvalidateRenderTreeNodesOfBoxAndAncestors();
+  }
+}
+
 void TextBox::SplitBidiLevelRuns() {}
 
 bool TextBox::TrySplitAtSecondBidiLevelRun() {
@@ -299,6 +307,14 @@
 }
 
 namespace {
+void PopulateBaseStyleForTextNode(
+    const scoped_refptr<const cssom::CSSComputedStyleData>& source_style,
+    const scoped_refptr<cssom::CSSComputedStyleData>& destination_style) {
+  // NOTE: Properties set by PopulateBaseStyleForTextNode() should match the
+  // properties used by SetupTextNodeFromStyle().
+  destination_style->set_color(source_style->color());
+}
+
 void SetupTextNodeFromStyle(
     const scoped_refptr<const cssom::CSSComputedStyleData>& style,
     render_tree::TextNode::Builder* text_node_builder) {
@@ -340,11 +356,7 @@
 }  // namespace
 
 void TextBox::RenderAndAnimateContent(
-    render_tree::CompositionNode::Builder* border_node_builder,
-    render_tree::animations::NodeAnimationsMap::Builder*
-        node_animations_map_builder) const {
-  UNREFERENCED_PARAMETER(node_animations_map_builder);
-
+    render_tree::CompositionNode::Builder* border_node_builder) const {
   if (computed_style()->visibility() != cssom::KeywordValue::GetVisible()) {
     return;
   }
@@ -376,23 +388,15 @@
         text_shadow != cssom::KeywordValue::GetNone()) {
       int32 text_start_position = GetNonCollapsedTextStartPosition();
       int32 text_length = GetVisibleTextLength();
-      // Generate the glyph buffer if it does not already exist or the position
-      // it covers has changed. Otherwise, just use the cached glyph buffer.
-      if (!cached_glyph_buffer_info_.glyph_buffer ||
-          text_start_position != cached_glyph_buffer_info_.start_position ||
-          text_length != cached_glyph_buffer_info_.length) {
-        cached_glyph_buffer_info_.start_position = text_start_position;
-        cached_glyph_buffer_info_.length = text_length;
-        cached_glyph_buffer_info_.glyph_buffer = used_font_->CreateGlyphBuffer(
-            paragraph_->GetTextBuffer() +
-                cached_glyph_buffer_info_.start_position,
-            cached_glyph_buffer_info_.length,
-            paragraph_->IsRTL(text_start_position));
-      }
+
+      scoped_refptr<render_tree::GlyphBuffer> glyph_buffer =
+          used_font_->CreateGlyphBuffer(
+              paragraph_->GetTextBuffer() + text_start_position, text_length,
+              paragraph_->IsRTL(text_start_position));
 
       render_tree::TextNode::Builder text_node_builder(
           math::Vector2dF(truncated_text_offset_from_left_, ascent_),
-          cached_glyph_buffer_info_.glyph_buffer, used_color);
+          glyph_buffer, used_color);
 
       if (text_shadow != cssom::KeywordValue::GetNone()) {
         cssom::PropertyListValue* shadow_list =
@@ -407,13 +411,20 @@
 
       // The render tree API considers text coordinates to be a position
       // of a baseline, offset the text node accordingly.
-      border_node_builder->AddChild(text_node);
+      scoped_refptr<render_tree::Node> node_to_add;
       if (is_color_animated) {
+        render_tree::animations::AnimateNode::Builder animate_node_builder;
         AddAnimations<render_tree::TextNode>(
+            base::Bind(&PopulateBaseStyleForTextNode),
             base::Bind(&SetupTextNodeFromStyle),
             *css_computed_style_declaration(), text_node,
-            node_animations_map_builder);
+            &animate_node_builder);
+        node_to_add = new render_tree::animations::AnimateNode(
+            animate_node_builder, text_node);
+      } else {
+        node_to_add = text_node;
       }
+      border_node_builder->AddChild(node_to_add);
     }
   }
 }
diff --git a/src/cobalt/layout/text_box.h b/src/cobalt/layout/text_box.h
index 792e5a7..dc55439 100644
--- a/src/cobalt/layout/text_box.h
+++ b/src/cobalt/layout/text_box.h
@@ -57,7 +57,8 @@
   Box* GetSplitSibling() const OVERRIDE;
 
   bool DoesFulfillEllipsisPlacementRequirement() const OVERRIDE;
-  void ResetEllipses() OVERRIDE;
+  void DoPreEllipsisPlacementProcessing() OVERRIDE;
+  void DoPostEllipsisPlacementProcessing() OVERRIDE;
 
   void SplitBidiLevelRuns() OVERRIDE;
   bool TrySplitAtSecondBidiLevelRun() OVERRIDE;
@@ -82,10 +83,8 @@
 
  protected:
   // From |Box|.
-  void RenderAndAnimateContent(
-      render_tree::CompositionNode::Builder* border_node_builder,
-      render_tree::animations::NodeAnimationsMap::Builder*
-          node_animations_map_builder) const OVERRIDE;
+  void RenderAndAnimateContent(render_tree::CompositionNode::Builder*
+                                   border_node_builder) const OVERRIDE;
   bool IsTransformable() const OVERRIDE;
 
 #ifdef COBALT_BOX_DUMP_ENABLED
@@ -95,14 +94,6 @@
 #endif  // COBALT_BOX_DUMP_ENABLED
 
  private:
-  struct CachedGlyphBufferInfo {
-    CachedGlyphBufferInfo() : start_position(-1), length(0) {}
-
-    scoped_refptr<render_tree::GlyphBuffer> glyph_buffer;
-    int32 start_position;
-    int32 length;
-  };
-
   // From |Box|.
   void DoPlaceEllipsisOrProcessPlacedEllipsis(
       BaseDirection base_direction, LayoutUnit desired_offset,
@@ -162,6 +153,11 @@
   // the applicable edge(s) of the line as necessary to fit the ellipsis."
   //   https://www.w3.org/TR/css3-ui/#propdef-text-overflow
   int32 truncated_text_end_position_;
+  // Tracking of the previous value of |truncated_text_end_position_|, which
+  // allows for determination of whether or not the value changed during
+  // ellipsis placement. When this occurs, the cached render tree nodes of this
+  // box and its ancestors are invalidated.
+  int32 previous_truncated_text_end_position_;
   // The horizontal offset to apply to rendered text as a result of an ellipsis
   // truncating the text. This value can be non-zero when the text box is in a
   // line with a right-to-left base direction. In this case, when an ellipsis is
@@ -197,11 +193,6 @@
   // The width of the portion of the text that is unaffected by whitespace
   // collapsing.
   base::optional<LayoutUnit> non_collapsible_text_width_;
-
-  // Glyph buffer caching is used to prevent it from needing to be recalculated
-