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 - // during each call to RenderAndAnimateContent. It is mutable as a result of - // RenderAndAnimateContent being const. - mutable CachedGlyphBufferInfo cached_glyph_buffer_info_; }; } // namespace layout
diff --git a/src/cobalt/layout_tests/layout_benchmarks.cc b/src/cobalt/layout_tests/layout_benchmarks.cc index 99e088d..164741c 100644 --- a/src/cobalt/layout_tests/layout_benchmarks.cc +++ b/src/cobalt/layout_tests/layout_benchmarks.cc
@@ -62,9 +62,8 @@ samples_to_gather_ = samples_to_gather; done_gathering_samples_.Reset(); - renderer::Submission submission_with_callback( - layout_results.render_tree, layout_results.animations, - layout_results.layout_time); + renderer::Submission submission_with_callback(layout_results.render_tree, + layout_results.layout_time); submission_with_callback.on_rasterized_callback = base::Bind( &RendererBenchmarkRunner::OnSubmitComplete, base::Unretained(this)); @@ -156,7 +155,7 @@ layout_samples_[layout::kBenchmarkStatUpdateCrossReferences]; layout_samples_[layout::kBenchmarkStatUpdateUsedSizes]; layout_samples_[layout::kBenchmarkStatRenderAndAnimate]; - renderer_samples_["NodeAnimationsMap::Apply()"]; + renderer_samples_["AnimateNode::Apply()"]; renderer_samples_["VisitRenderTree"]; renderer_samples_["Skia Flush"]; }
diff --git a/src/cobalt/layout_tests/layout_snapshot.cc b/src/cobalt/layout_tests/layout_snapshot.cc index b07abfc..97b7689 100644 --- a/src/cobalt/layout_tests/layout_snapshot.cc +++ b/src/cobalt/layout_tests/layout_snapshot.cc
@@ -41,8 +41,7 @@ base::optional<browser::WebModule::LayoutResults>* out_results, base::RunLoop* run_loop, MessageLoop* message_loop, const browser::WebModule::LayoutResults& results) { - out_results->emplace(results.render_tree, results.animations, - results.layout_time); + out_results->emplace(results.render_tree, results.layout_time); message_loop->PostTask(FROM_HERE, base::Bind(Quit, run_loop)); }
diff --git a/src/cobalt/layout_tests/layout_tests.cc b/src/cobalt/layout_tests/layout_tests.cc index 5a822d1..9ceb258 100644 --- a/src/cobalt/layout_tests/layout_tests.cc +++ b/src/cobalt/layout_tests/layout_tests.cc
@@ -24,6 +24,7 @@ #include "cobalt/layout_tests/layout_snapshot.h" #include "cobalt/layout_tests/test_parser.h" #include "cobalt/math/size.h" +#include "cobalt/render_tree/animations/animate_node.h" #include "cobalt/renderer/render_tree_pixel_tester.h" #include "googleurl/src/gurl.h" #include "testing/gtest/include/gtest/gtest.h" @@ -88,8 +89,13 @@ browser::WebModule::LayoutResults layout_results = SnapshotURL( GetParam().url, viewport_size, pixel_tester.GetResourceProvider()); - bool results = pixel_tester.TestTree(layout_results.render_tree, - GetParam().base_file_path); + render_tree::animations::AnimateNode* animated_node = + base::polymorphic_downcast<render_tree::animations::AnimateNode*>( + layout_results.render_tree.get()); + + bool results = + pixel_tester.TestTree(animated_node->Apply(layout_results.layout_time), + GetParam().base_file_path); EXPECT_TRUE(results); if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kRebaseline) ||
diff --git a/src/cobalt/layout_tests/web_platform_tests.cc b/src/cobalt/layout_tests/web_platform_tests.cc index 42dbc90..0c28e1a 100644 --- a/src/cobalt/layout_tests/web_platform_tests.cc +++ b/src/cobalt/layout_tests/web_platform_tests.cc
@@ -123,8 +123,7 @@ base::optional<browser::WebModule::LayoutResults>* out_results, base::RunLoop* run_loop, MessageLoop* message_loop, const browser::WebModule::LayoutResults& results) { - out_results->emplace(results.render_tree, results.animations, - results.layout_time); + out_results->emplace(results.render_tree, results.layout_time); message_loop->PostTask(FROM_HERE, base::Bind(Quit, run_loop)); }
diff --git a/src/cobalt/media/sandbox/media_sandbox.cc b/src/cobalt/media/sandbox/media_sandbox.cc index e3859b0..4f3a1a3 100644 --- a/src/cobalt/media/sandbox/media_sandbox.cc +++ b/src/cobalt/media/sandbox/media_sandbox.cc
@@ -24,7 +24,7 @@ #include "cobalt/math/size.h" #include "cobalt/math/size_f.h" #include "cobalt/network/network_module.h" -#include "cobalt/render_tree/animations/node_animations_map.h" +#include "cobalt/render_tree/animations/animate_node.h" #include "cobalt/render_tree/image_node.h" #include "cobalt/render_tree/resource_provider.h" #include "cobalt/renderer/pipeline.h" @@ -85,7 +85,7 @@ renderer_module_.reset( new renderer::RendererModule(system_window_.get(), renderer_options)); MediaModule::Options media_module_options; -#if defined(ENABLE_COMMAND_LINE_SWITCHES) +#if defined(ENABLE_DEBUG_COMMAND_LINE_SWITCHES) CommandLine* command_line = CommandLine::ForCurrentProcess(); // Use string literals directly to avoid dependency on browser::switches. if (command_line->HasSwitch("audio_decoder_stub")) { @@ -97,7 +97,7 @@ if (command_line->HasSwitch("video_decoder_stub")) { media_module_options.use_video_decoder_stub = true; } -#endif // defined(ENABLE_COMMAND_LINE_SWITCHES) +#endif // defined(ENABLE_DEBUG_COMMAND_LINE_SWITCHES) media_module_ = MediaModule::Create(renderer_module_->render_target()->GetSize(), @@ -124,16 +124,15 @@ void MediaSandbox::Impl::SetupAndSubmitScene() { scoped_refptr<render_tree::ImageNode> image_node = new render_tree::ImageNode(NULL); - render_tree::animations::NodeAnimationsMap::Builder - node_animations_map_builder; + render_tree::animations::AnimateNode::Builder animate_node_builder; - node_animations_map_builder.Add( + animate_node_builder.Add( image_node, base::Bind(&Impl::AnimateCB, base::Unretained(this))); - renderer_module_->pipeline()->Submit(renderer::Submission( - image_node, new render_tree::animations::NodeAnimationsMap( - node_animations_map_builder.Pass()), - base::TimeDelta())); + renderer_module_->pipeline()->Submit( + renderer::Submission(new render_tree::animations::AnimateNode( + animate_node_builder, image_node), + base::TimeDelta())); } MediaSandbox::MediaSandbox(int argc, char** argv,
diff --git a/src/cobalt/media/sandbox/raw_video_decoder_fuzzer.cc b/src/cobalt/media/sandbox/raw_video_decoder_fuzzer.cc index b5ab128..724287e 100644 --- a/src/cobalt/media/sandbox/raw_video_decoder_fuzzer.cc +++ b/src/cobalt/media/sandbox/raw_video_decoder_fuzzer.cc
@@ -192,9 +192,11 @@ scoped_ptr<ShellRawVideoDecoder> decoder = media_sandbox_->GetMediaModule()->GetRawVideoDecoderFactory()->Create( demuxer->config(), NULL, false); - DCHECK(decoder); - VideoDecoderFuzzer decoder_fuzzer(fuzzing_content, demuxer, decoder.get()); - decoder_fuzzer.Fuzz(); + if (decoder) { + VideoDecoderFuzzer decoder_fuzzer(fuzzing_content, demuxer, + decoder.get()); + decoder_fuzzer.Fuzz(); + } } private:
diff --git a/src/cobalt/media/shell_media_platform_starboard.cc b/src/cobalt/media/shell_media_platform_starboard.cc index 6278203..096b670 100644 --- a/src/cobalt/media/shell_media_platform_starboard.cc +++ b/src/cobalt/media/shell_media_platform_starboard.cc
@@ -57,7 +57,8 @@ kGPUMemoryBufferBudget); gpu_memory_pool_.reset(new nb::MemoryPool( gpu_memory_buffer_space_->GetMemory(), - gpu_memory_buffer_space_->GetSizeInBytes(), true /* thread_safe */)); + gpu_memory_buffer_space_->GetSizeInBytes(), true, /* thread_safe */ + true /* verify_full_capacity */)); } DCHECK_LE(0, kMainMemoryBufferBudget > 0); @@ -66,7 +67,8 @@ DCHECK(main_memory_buffer_space_); main_memory_pool_.reset(new nb::MemoryPool(main_memory_buffer_space_.get(), kMainMemoryBufferBudget, - true /* thread_safe */)); + true, /* thread_safe */ + true /* verify_full_capacity */)); ShellBufferFactory::Initialize(); ShellAudioStreamer::Initialize();
diff --git a/src/cobalt/media/shell_video_data_allocator_common.cc b/src/cobalt/media/shell_video_data_allocator_common.cc index be0107b..de8af74 100644 --- a/src/cobalt/media/shell_video_data_allocator_common.cc +++ b/src/cobalt/media/shell_video_data_allocator_common.cc
@@ -89,29 +89,30 @@ // TODO: Ensure it work with visible_rect with non-zero left and // top. Note that simply add offset to the image buffer may cause alignment // issues. - gfx::Size visible_size(param.visible_rect().size()); + gfx::Size plane_size(param.visible_rect().size()); // Create image data descriptor for the frame in I420. MultiPlaneImageDataDescriptor descriptor( kMultiPlaneImageFormatYUV3PlaneBT709); descriptor.AddPlane( param.y_data() - frame_buffer->data(), - ImageDataDescriptor(visible_size, kPixelFormatY8, + ImageDataDescriptor(plane_size, kPixelFormatY8, kAlphaFormatUnpremultiplied, param.y_pitch())); - visible_size.SetSize(visible_size.width() / 2, visible_size.height() / 2); + plane_size.SetSize(plane_size.width() / 2, plane_size.height() / 2); descriptor.AddPlane( param.u_data() - frame_buffer->data(), - ImageDataDescriptor(visible_size, kPixelFormatU8, + ImageDataDescriptor(plane_size, kPixelFormatU8, kAlphaFormatUnpremultiplied, param.uv_pitch())); descriptor.AddPlane( param.v_data() - frame_buffer->data(), - ImageDataDescriptor(visible_size, kPixelFormatV8, + ImageDataDescriptor(plane_size, kPixelFormatV8, kAlphaFormatUnpremultiplied, param.uv_pitch())); scoped_refptr<Image> image = resource_provider_->CreateMultiPlaneImageFromRawMemory( frame_buffer_common->DetachRawImageMemory(), descriptor); + gfx::Size visible_size(param.visible_rect().size()); // The reference of the image is held by the closure that binds ReleaseImage, // so it won't be freed before the ReleaseImage is called. scoped_refptr<VideoFrame> video_frame = VideoFrame::WrapNativeTexture( @@ -130,7 +131,7 @@ // TODO: Ensure it work with visible_rect with non-zero left and // top. Note that simply add offset to the image buffer may cause alignment // issues. - gfx::Size visible_size(param.visible_rect().size()); + gfx::Size plane_size(param.visible_rect().size()); intptr_t offset = 0; int pitch_in_bytes = param.y_pitch(); @@ -141,12 +142,12 @@ MultiPlaneImageDataDescriptor descriptor( kMultiPlaneImageFormatYUV2PlaneBT709); descriptor.AddPlane( - offset, ImageDataDescriptor(visible_size, kPixelFormatY8, + offset, ImageDataDescriptor(plane_size, kPixelFormatY8, kAlphaFormatPremultiplied, pitch_in_bytes)); offset += pitch_in_bytes * param.decoded_height(); - visible_size.SetSize(visible_size.width() / 2, visible_size.height() / 2); + plane_size.SetSize(plane_size.width() / 2, plane_size.height() / 2); descriptor.AddPlane( - offset, ImageDataDescriptor(visible_size, kPixelFormatUV8, + offset, ImageDataDescriptor(plane_size, kPixelFormatUV8, kAlphaFormatPremultiplied, pitch_in_bytes)); offset += pitch_in_bytes * param.decoded_height() / 2; DCHECK_EQ(offset, pitch_in_bytes * param.decoded_height() * 3 / 2); @@ -155,6 +156,7 @@ resource_provider_->CreateMultiPlaneImageFromRawMemory( frame_buffer_common->DetachRawImageMemory(), descriptor); + gfx::Size visible_size(param.visible_rect().size()); // The reference of the image is held by the closure that binds ReleaseImage, // so it won't be freed before the ReleaseImage is called. scoped_refptr<VideoFrame> video_frame = VideoFrame::WrapNativeTexture(
diff --git a/src/cobalt/media/shell_video_data_allocator_common.h b/src/cobalt/media/shell_video_data_allocator_common.h index 03cdbfa..9673ded 100644 --- a/src/cobalt/media/shell_video_data_allocator_common.h +++ b/src/cobalt/media/shell_video_data_allocator_common.h
@@ -53,9 +53,13 @@ public: explicit FrameBufferCommon(scoped_ptr<RawImageMemory> raw_image_memory); - uint8* data() const OVERRIDE { return raw_image_memory_->GetMemory(); } + uint8* data() const OVERRIDE { + return raw_image_memory_ ? raw_image_memory_->GetMemory() : NULL; + } - size_t size() const OVERRIDE { return raw_image_memory_->GetSizeInBytes(); } + size_t size() const OVERRIDE { + return raw_image_memory_ ? raw_image_memory_->GetSizeInBytes() : 0; + } // Disown the image_data_. scoped_ptr<RawImageMemory> DetachRawImageMemory();
diff --git a/src/cobalt/network/switches.cc b/src/cobalt/network/switches.cc index 83bb9a7..158833f 100644 --- a/src/cobalt/network/switches.cc +++ b/src/cobalt/network/switches.cc
@@ -20,7 +20,7 @@ namespace network { namespace switches { -#if defined(ENABLE_COMMAND_LINE_SWITCHES) +#if defined(ENABLE_DEBUG_COMMAND_LINE_SWITCHES) // Log network events using Chromium's network logger. If a parameter is // specified, the parameter shall be interpreted as a file path and the network // log will be written into the file. Otherwise, logging will be written to @@ -30,7 +30,7 @@ // Corresponds to the levels described in the NetLog::LogLevel enum defined in // net/base/net_log.h const char kNetLogLevel[] = "net_log_level"; -#endif // ENABLE_COMMAND_LINE_SWITCHES +#endif // ENABLE_DEBUG_COMMAND_LINE_SWITCHES } // namespace switches } // namespace network
diff --git a/src/cobalt/network/switches.h b/src/cobalt/network/switches.h index 996c1d5..e95a70d 100644 --- a/src/cobalt/network/switches.h +++ b/src/cobalt/network/switches.h
@@ -21,10 +21,10 @@ namespace network { namespace switches { -#if defined(ENABLE_COMMAND_LINE_SWITCHES) +#if defined(ENABLE_DEBUG_COMMAND_LINE_SWITCHES) extern const char kNetLog[]; extern const char kNetLogLevel[]; -#endif // ENABLE_COMMAND_LINE_SWITCHES +#endif // ENABLE_DEBUG_COMMAND_LINE_SWITCHES } // namespace switches } // namespace network
diff --git a/src/cobalt/render_tree/animations/animate_node.cc b/src/cobalt/render_tree/animations/animate_node.cc new file mode 100644 index 0000000..d51732a --- /dev/null +++ b/src/cobalt/render_tree/animations/animate_node.cc
@@ -0,0 +1,401 @@ +/* + * 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/render_tree/animations/animate_node.h" + +#include "base/debug/trace_event.h" +#include "cobalt/base/enable_if.h" +#include "cobalt/base/polymorphic_downcast.h" +#include "cobalt/render_tree/child_iterator.h" +#include "cobalt/render_tree/node_visitor.h" + +namespace cobalt { +namespace render_tree { +namespace animations { + +void AnimateNode::Builder::AddInternal( + const scoped_refptr<Node>& target_node, + const scoped_refptr<AnimationListBase>& animation_list) { + DCHECK(node_animation_map_.find(target_node) == node_animation_map_.end()) + << "The target render tree node already has an associated animation " + "list."; + + node_animation_map_[target_node.get()] = animation_list; + node_refs_.push_back(target_node); +} + +void AnimateNode::Builder::Merge(const AnimateNode::Builder& other) { +#if !defined(NDEBUG) + for (InternalMap::const_iterator iter = node_animation_map_.begin(); + iter != node_animation_map_.end(); ++iter) { + DCHECK(other.node_animation_map_.find(iter->first) == + other.node_animation_map_.end()) + << "Only mutually exclusive AnimateNode::Builders can be merged!"; + } +#endif + node_animation_map_.insert(other.node_animation_map_.begin(), + other.node_animation_map_.end()); + node_refs_.insert(node_refs_.end(), other.node_refs_.begin(), + other.node_refs_.end()); +} + +// A helper render tree visitor class used to compile sub render-tree +// animations. The same instance of the TraverseListBuilder class is reused for +// traversing all nodes in a tree. After visiting a render tree, +// |traverse_list_| will contain a post-order traversal of animated nodes where +// children are visited from right to left, and this should be reversed to +// obtain a pre-order traversal of animated nodes where children are visited +// from left to right, which is much more natural. +class AnimateNode::TraverseListBuilder : public NodeVisitor { + public: + TraverseListBuilder(const AnimateNode::Builder::InternalMap& animation_map, + TraverseList* traverse_list) + : animation_map_(animation_map), traverse_list_(traverse_list) {} + + void Visit(animations::AnimateNode* animate) OVERRIDE; + void Visit(CompositionNode* composition) OVERRIDE { VisitNode(composition); } + void Visit(FilterNode* text) OVERRIDE { VisitNode(text); } + void Visit(ImageNode* image) OVERRIDE { VisitNode(image); } + void Visit(MatrixTransformNode* transform) OVERRIDE { VisitNode(transform); } + void Visit(PunchThroughVideoNode* punch_through) OVERRIDE { + VisitNode(punch_through); + } + void Visit(RectNode* rect) OVERRIDE { VisitNode(rect); } + void Visit(RectShadowNode* rect) OVERRIDE { VisitNode(rect); } + void Visit(TextNode* text) OVERRIDE { VisitNode(text); } + + private: + template <typename T> + typename base::enable_if<!ChildIterator<T>::has_children>::type VisitNode( + T* node); + + template <typename T> + typename base::enable_if<ChildIterator<T>::has_children>::type VisitNode( + T* node); + void ProcessNode(Node* node, bool animated_children); + + // Adds a node to |traverse_list_|, indicating that it or its descendants are + // involved in animation. + void AddToTraverseList( + Node* node, AnimateNode::Builder::InternalMap::const_iterator found); + + // A reference to the mapping from render tree node to animations. + const AnimateNode::Builder::InternalMap& animation_map_; + + // A list of nodes that, if reversed, gives a pre-order traversal of only + // animated nodes. + // |traverse_list_| is the primary output of this visitor class. + TraverseList* traverse_list_; + + // Signals to the caller of Visit() that this node was animated and so any + // parent nodes should also be added to the traversal list. + bool animated_; + + // If non-null, references a node that this visitor's parent should replace + // this visitor's associated node with in its list of child nodes. + scoped_refptr<Node> replace_with_; + + friend class AnimateNode; +}; + +void AnimateNode::TraverseListBuilder::Visit(animations::AnimateNode* animate) { + if (!animate->traverse_list_.empty()) { + // We merge all the information from this AnimateNode into the one we are + // constructing now. Simply append the sub-AnimateNode to |traverse_list_|, + // but reverse it so its finalized pre-order, left to right traversal is + // switched to the intermediate format of a post-order, right to left + // traversal. + size_t start_size = traverse_list_->size(); + traverse_list_->insert(traverse_list_->end(), + animate->traverse_list_.begin(), + animate->traverse_list_.end()); + std::reverse(traverse_list_->begin() + static_cast<int64>(start_size), + traverse_list_->end()); + animated_ = true; + } else { + animated_ = false; + } + + // Now that we have merged the sub-AnimateNode's information with the one + // under construction, remove this AnimateNode from the tree in order to + // maintain the invariant that an AnimateNode does not contain any + // AnimateNode descendants. + replace_with_ = animate->source_; +} + +template <typename T> +typename base::enable_if<!ChildIterator<T>::has_children>::type +AnimateNode::TraverseListBuilder::VisitNode(T* node) { + // If we are dealing with a render tree node that has no children, all we + // need to do is call ProcessNode(). + animated_ = false; + replace_with_ = NULL; + ProcessNode(node, false); +} + +template <typename T> +typename base::enable_if<ChildIterator<T>::has_children>::type +AnimateNode::TraverseListBuilder::VisitNode(T* node) { + ChildIterator<T> child_iterator(node, kChildIteratorDirectionBackwards); + bool modified_children = false; + bool animated_children = false; + while (Node* child = child_iterator.GetCurrent()) { + child->Accept(this); + + // Mark us as animated if any of our children are animated, so that we make + // sure to add ourselves to |traverse_list_|. + animated_children |= animated_; + + if (replace_with_) { + // If the child node wishes to replace itself with a new node, then + // replace it within its parent's child list. + child_iterator.ReplaceCurrent(replace_with_); + modified_children = true; + } + + child_iterator.Next(); + } + + if (modified_children) { + replace_with_ = new T(child_iterator.TakeReplacedChildrenBuilder()); + } else { + replace_with_ = NULL; + } + + // Finally, add this node to |traverse_list_| if it is animated either + // directly or indirectly (i.e. because its children are animated). + animated_ = false; + ProcessNode(node, animated_children); +} + +void AnimateNode::TraverseListBuilder::ProcessNode(Node* node, + bool animated_children) { + // If this node is animated, add it to the |traverse_list_|. + AnimateNode::Builder::InternalMap::const_iterator found = + animation_map_.find(node); + if (animated_children || found != animation_map_.end()) { + AddToTraverseList(replace_with_ ? replace_with_.get() : node, found); + } +} + +// Adds a node to |traverse_list_| so that it can be quickly +// found in the future. +void AnimateNode::TraverseListBuilder::AddToTraverseList( + Node* node, AnimateNode::Builder::InternalMap::const_iterator found) { + if (found != animation_map_.end()) { + traverse_list_->push_back(TraverseListEntry(node, found->second)); + } else { + traverse_list_->push_back(TraverseListEntry(node)); + } + animated_ = true; +} + +// A helper render tree visitor class used to apply compiled sub render-tree +// animations. Only one of these visitors is needed to visit an entire render +// tree. +class AnimateNode::ApplyVisitor : public NodeVisitor { + public: + ApplyVisitor(const TraverseList& traverse_list, base::TimeDelta time_offset); + + void Visit(animations::AnimateNode* /* animate */) OVERRIDE { + // An invariant of AnimateNodes is that they should never contain descendant + // AnimateNodes. + NOTREACHED(); + } + // Immediately switch to a templated visitor function. + void Visit(CompositionNode* composition) OVERRIDE { VisitNode(composition); } + void Visit(FilterNode* text) OVERRIDE { VisitNode(text); } + void Visit(ImageNode* image) OVERRIDE { VisitNode(image); } + void Visit(MatrixTransformNode* transform) OVERRIDE { VisitNode(transform); } + void Visit(PunchThroughVideoNode* punch_through) OVERRIDE { + VisitNode(punch_through); + } + void Visit(RectNode* rect) OVERRIDE { VisitNode(rect); } + void Visit(RectShadowNode* rect) OVERRIDE { VisitNode(rect); } + void Visit(TextNode* text) OVERRIDE { VisitNode(text); } + + // Returns the animated version of the node last visited. This is how the + // final animated result can be pulled from this visitor. + const scoped_refptr<Node>& animated() const { return animated_; } + + private: + template <typename T> + typename base::enable_if<!ChildIterator<T>::has_children>::type VisitNode( + T* node); + template <typename T> + typename base::enable_if<ChildIterator<T>::has_children>::type VisitNode( + T* node); + template <typename T> + void ApplyAnimations(const TraverseListEntry& entry, + typename T::Builder* builder); + TraverseListEntry AdvanceIterator(Node* node); + + // The time offset to be passed in to individual animations. + base::TimeDelta time_offset_; + // The animated version of the last node visited. + scoped_refptr<Node> animated_; + // A list of nodes that we are allowed to traverse into (i.e. a traversal that + // guides us to animated nodes). It assumes that a pre-order traversal will + // be taken. + const TraverseList& traverse_list_; + // An iterator pointing to the next valid render tree node to visit. + TraverseList::const_iterator iterator_; +}; + +AnimateNode::ApplyVisitor::ApplyVisitor(const TraverseList& traverse_list, + base::TimeDelta time_offset) + : time_offset_(time_offset), traverse_list_(traverse_list) { + iterator_ = traverse_list_.begin(); +} + +template <typename T> +typename base::enable_if<!ChildIterator<T>::has_children>::type +AnimateNode::ApplyVisitor::VisitNode(T* node) { + TraverseListEntry current_entry = AdvanceIterator(node); + // If we don't have any children, then for this node to be visited, we must + // have animations. + DCHECK(current_entry.animations); + typename T::Builder builder(node->data()); + ApplyAnimations<T>(current_entry, &builder); + animated_ = new T(builder); +} + +template <typename T> +typename base::enable_if<ChildIterator<T>::has_children>::type +AnimateNode::ApplyVisitor::VisitNode(T* node) { + TraverseListEntry current_entry = AdvanceIterator(node); + + // Traverse the child nodes, but only the ones that are on the + // |traverse_list_|. In particular, the next node we are allowed to visit + // is the one in the traverse list pointed to by |iterator_->node|. + ChildIterator<T> child_iterator(node); + bool children_modified = false; + while (Node* child = child_iterator.GetCurrent()) { + if (iterator_ == traverse_list_.end()) { + // If we've reached the end of |traverse_list_| then we are done + // iterating and it's time to return. + break; + } + + if (child == iterator_->node) { + // If one of our children is next up on the path to animation, traverse + // into it. + child->Accept(this); + // Traversing into the child means that it was animated, and so replaced + // by an animated node while it was visited. Thus, replace it in the + // current node's child list with its animated version. + child_iterator.ReplaceCurrent(animated_); + children_modified = true; + } + + child_iterator.Next(); + } + + if (current_entry.animations) { + base::optional<typename T::Builder> builder; + if (children_modified) { + // Reuse the modified Builder object from child traversal if one of + // our children was animated. + builder.emplace(child_iterator.TakeReplacedChildrenBuilder()); + } else { + // Create a fresh copy of the Builder object for this animated node, to + // be passed into the animations. + builder.emplace(node->data()); + } + ApplyAnimations<T>(current_entry, &(*builder)); + animated_ = new T(*builder); + } else { + // If there were no animations targeting this node directly, then its + // children must have been modified since otherwise it wouldn't be in + // the traverse list. + DCHECK(children_modified); + animated_ = new T(child_iterator.TakeReplacedChildrenBuilder()); + } +} + +template <typename T> +void AnimateNode::ApplyVisitor::ApplyAnimations(const TraverseListEntry& entry, + typename T::Builder* builder) { + TRACE_EVENT0("cobalt::renderer", + "AnimateNode::ApplyVisitor::ApplyAnimations()"); + // Cast to the specific type we expect these animations to have. + const AnimationList<T>* typed_node_animations = + base::polymorphic_downcast<const AnimationList<T>*>( + entry.animations.get()); + + // Iterate through each animation applying them one at a time. + for (typename AnimationList<T>::InternalList::const_iterator iter = + typed_node_animations->data().animations.begin(); + iter != typed_node_animations->data().animations.end(); ++iter) { + iter->Run(builder, time_offset_); + } +} + +AnimateNode::TraverseListEntry AnimateNode::ApplyVisitor::AdvanceIterator( + Node* node) { + // Check that the iterator that we are advancing past is indeed the one we + // expect it to be. + DCHECK_EQ(node, iterator_->node); + return *(iterator_++); +} + +AnimateNode::AnimateNode(const Builder& builder, + const scoped_refptr<Node>& source) { + TRACE_EVENT0("cobalt::renderer", "AnimateNode::AnimateNode(builder, source)"); + CommonInit(builder.node_animation_map_, source); +} + +AnimateNode::AnimateNode(const scoped_refptr<Node>& source) { + TRACE_EVENT0("cobalt::renderer", "AnimateNode::AnimateNode(source)"); + CommonInit(Builder::InternalMap(), source); +} + +scoped_refptr<Node> AnimateNode::Apply(base::TimeDelta time_offset) { + TRACE_EVENT0("cobalt::renderer", "AnimateNode::Apply()"); + if (traverse_list_.empty()) { + return source_; + } else { + ApplyVisitor apply_visitor(traverse_list_, time_offset); + source_->Accept(&apply_visitor); + return apply_visitor.animated(); + } +} + +void AnimateNode::CommonInit(const Builder::InternalMap& node_animation_map, + const scoped_refptr<Node>& source) { + TraverseListBuilder traverse_list_builder(node_animation_map, + &traverse_list_); + source->Accept(&traverse_list_builder); + + if (traverse_list_builder.replace_with_) { + source_ = traverse_list_builder.replace_with_; + } else { + source_ = source; + } + + if (!traverse_list_.empty()) { + // We must adjust the resulting |traverse_list_| from an awkward + // intermediate format of post-order right to left traversal to the more + // natural pre-order left to right traversal expected by ApplyVisitor. + // This can be done by simply reversing the list. + std::reverse(traverse_list_.begin(), traverse_list_.end()); + DCHECK(source_.get() == traverse_list_.begin()->node); + } +} + +} // namespace animations +} // namespace render_tree +} // namespace cobalt
diff --git a/src/cobalt/render_tree/animations/animate_node.h b/src/cobalt/render_tree/animations/animate_node.h new file mode 100644 index 0000000..4b9bfae --- /dev/null +++ b/src/cobalt/render_tree/animations/animate_node.h
@@ -0,0 +1,177 @@ +/* + * 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_RENDER_TREE_ANIMATIONS_ANIMATE_NODE_H_ +#define COBALT_RENDER_TREE_ANIMATIONS_ANIMATE_NODE_H_ + +#include <map> +#include <vector> + +#include "base/containers/small_map.h" +#include "base/memory/ref_counted.h" +#include "cobalt/render_tree/animations/animation_list.h" +#include "cobalt/render_tree/movable.h" +#include "cobalt/render_tree/node.h" +#include "cobalt/render_tree/node_visitor.h" + +namespace cobalt { +namespace render_tree { +namespace animations { + +// An AnimateNode describes a set of animations that affect the subtree attached +// to the AnimateNode. In order to create an AnimateNode, one must first +// populate an AnimateNode::Builder with a mapping of render tree node +// references to corresponding animations that should be applied to them. +// Construction of an AnimateNode object requires a populated +// AnimateNode::Builder instance as well as the sub-tree that the animations +// apply to. Upon construction, AnimateNode will compile the set of animated +// nodes into a format specialized to the associated subtree such that it is +// much faster to apply the animations. Once an AnimateNode is constructed, +// it can generate static render trees representing frames of animation via +// calls to AnimateNode::Apply(), which returns a static render tree. +// When AnimateNodes are constructed they maintain an invariant that +// AnimateNodes never have other AnimateNodes as descendants. It does this +// by traversing the subtree on construction and if another AnimateNode is +// encountered, its information is merged into this root AnimateNode, and the +// sub-AnimateNode is removed from the tree. +class AnimateNode : public Node { + public: + // Manages a mapping of render tree nodes to corresponding animations. Users + // of AnimateNode should populate the Builder with animations and then use + // that to construct the AnimateNode. + class Builder { + public: + DECLARE_AS_MOVABLE(Builder); + + Builder() {} + explicit Builder(Moved moved) { + node_animation_map_ = moved->node_animation_map_; + node_refs_.swap(moved->node_refs_); + } + + // This method is a template so that we can ensure that animations are not + // mismatched with render tree nodes of the wrong type. + template <typename T> + void Add(const scoped_refptr<T>& target_node, + const scoped_refptr<AnimationList<T> >& animation_list) { + AddInternal(target_node, animation_list); + } + + // Convenience method to attach a single animation to a target node. + template <typename T> + void Add(const scoped_refptr<T>& target_node, + const typename Animation<T>::Function& single_animation) { + AddInternal(target_node, scoped_refptr<AnimationListBase>( + new AnimationList<T>(single_animation))); + } + + // Merge all mappings from another AnimateNode::Builder into this one. + // There cannot be any keys that are in both the merge target and source. + void Merge(const Builder& other); + + // Returns true if there are no animations added to this + // AnimateNode::Builder. + bool empty() const { return node_animation_map_.empty(); } + + private: + // A non-template function that contains the logic for storing a target + // node and animation list pair. + void AddInternal(const scoped_refptr<Node>& target_node, + const scoped_refptr<AnimationListBase>& animation_list); + + // The primary internal data structure used to organize and store the + // mapping between target render tree node and animation list. + // In many cases there are not many active animations, and so we use a + // base::SmallMap for this. std::map was found to be more performant than + // base::hash_map, so it is used as the fallback map. + typedef base::SmallMap<std::map<Node*, scoped_refptr<AnimationListBase> >, + 4> InternalMap; + InternalMap node_animation_map_; + std::vector<scoped_refptr<Node> > node_refs_; + + friend class AnimateNode; + }; + + AnimateNode(const Builder& builder, const scoped_refptr<Node>& source); + + // This will create an AnimateNode with no animations. It is useful because + // construction of AnimateNodes maintain an invariant that there are no + // sub-AnimateNodes underneath them. Thus, adding a AnimateNode, even if it + // has no animations, to an existing tree will result in existing AnimateNodes + // being merged into the new root AnimateNode, which can simplify the + // underlying tree. + explicit AnimateNode(const scoped_refptr<Node>& source); + + // Cannot visit this node. + void Accept(NodeVisitor* visitor) OVERRIDE { visitor->Visit(this); } + + // Since we don't have any bounds on the animations contained in this tree, + // we cannot know the bounds of the tree over all time. Indeed animations + // may not have any bounds as time goes to infinity. Despite this, we return + // the bounds of the initial render tree to enable AnimateNodes to be setup + // as children of CompositionNodes. + math::RectF GetBounds() const OVERRIDE { return source_->GetBounds(); } + + base::TypeId GetTypeId() const OVERRIDE { + return base::GetTypeId<AnimateNode>(); + } + + // Apply the animations to the sub render tree with the given |time_offset|. + // An animated sub-tree is returned, which is guaranteed to not contain any + // AnimateNodes. + scoped_refptr<Node> Apply(base::TimeDelta time_offset); + + // Returns the sub-tree for which the animations apply to. + const scoped_refptr<Node> source() const { return source_; } + + private: + // A helper render tree visitor class used to compile sub render-tree + // animations. + class TraverseListBuilder; + // A helper render tree visitor class used to apply compiled sub render-tree + // animations. This class follows the traversal generated by + // TraverseListBuilder. + class ApplyVisitor; + + void CommonInit(const Builder::InternalMap& node_animation_map, + const scoped_refptr<Node>& source); + + // The compiled node animation list is a sequence of nodes that are either + // animated themselves, or on the path to an animated node. Only nodes in + // this sequence need to be traversed. TraverseListEntry is an entry in this + // list, complete with animations to be applied to the given node, if any. + struct TraverseListEntry { + TraverseListEntry(Node* node, + const scoped_refptr<AnimationListBase>& animations) + : node(node), animations(animations) {} + explicit TraverseListEntry(Node* node) : node(node) {} + + Node* node; + scoped_refptr<AnimationListBase> animations; + }; + typedef std::vector<TraverseListEntry> TraverseList; + + // The compiled traversal list through the sub-tree represented by |source_| + // that guides us towards all nodes that need to be animated. + TraverseList traverse_list_; + scoped_refptr<Node> source_; +}; + +} // namespace animations +} // namespace render_tree +} // namespace cobalt + +#endif // COBALT_RENDER_TREE_ANIMATIONS_ANIMATE_NODE_H_
diff --git a/src/cobalt/render_tree/animations/node_animations_map_test.cc b/src/cobalt/render_tree/animations/animate_node_test.cc similarity index 67% rename from src/cobalt/render_tree/animations/node_animations_map_test.cc rename to src/cobalt/render_tree/animations/animate_node_test.cc index 5e45af5..f46e63e 100644 --- a/src/cobalt/render_tree/animations/node_animations_map_test.cc +++ b/src/cobalt/render_tree/animations/animate_node_test.cc
@@ -1,5 +1,5 @@ /* - * Copyright 2015 Google Inc. All Rights Reserved. + * 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. @@ -21,7 +21,7 @@ #include "cobalt/math/rect_f.h" #include "cobalt/math/size_f.h" #include "cobalt/math/transform_2d.h" -#include "cobalt/render_tree/animations/node_animations_map.h" +#include "cobalt/render_tree/animations/animate_node.h" #include "cobalt/render_tree/brush.h" #include "cobalt/render_tree/color_rgba.h" #include "cobalt/render_tree/composition_node.h" @@ -46,12 +46,12 @@ // Helper function to create an animation set for a render tree that consists // of only one animation targeting only one node in the render tree. template <typename T> -scoped_refptr<NodeAnimationsMap> CreateSingleAnimation( +scoped_refptr<AnimateNode> CreateSingleAnimation( const scoped_refptr<T>& target, typename Animation<T>::Function anim_function) { - NodeAnimationsMap::Builder animations_builder; + AnimateNode::Builder animations_builder; animations_builder.Add(target, anim_function); - return new NodeAnimationsMap(animations_builder.Pass()); + return new AnimateNode(animations_builder, target); } class ImageFake : public Image { @@ -68,16 +68,16 @@ UNREFERENCED_PARAMETER(time_elapsed); text_node->color = ColorRGBA(.5f, .5f, .5f); } -TEST(NodeAnimationsMapTest, EnsureSingleTextNodeAnimates) { +TEST(AnimateNodeTest, EnsureSingleTextNodeAnimates) { scoped_refptr<TextNode> text_node( new TextNode(math::Vector2dF(0, 0), new GlyphBuffer(RectF(0, 0, 1, 1)), ColorRGBA(1.0f, 1.0f, 1.0f))); - scoped_refptr<NodeAnimationsMap> animations = + scoped_refptr<AnimateNode> with_animations = CreateSingleAnimation(text_node, base::Bind(&AnimateText)); scoped_refptr<Node> animated_render_tree = - animations->Apply(text_node, base::TimeDelta::FromSeconds(1)); + with_animations->Apply(base::TimeDelta::FromSeconds(1)); TextNode* animated_text_node = dynamic_cast<TextNode*>(animated_render_tree.get()); EXPECT_TRUE(animated_text_node); @@ -89,15 +89,15 @@ UNREFERENCED_PARAMETER(time_elapsed); image_node->destination_rect = RectF(2.0f, 2.0f); } -TEST(NodeAnimationsMapTest, EnsureSingleImageNodeAnimates) { +TEST(AnimateNodeTest, EnsureSingleImageNodeAnimates) { scoped_refptr<ImageNode> image_node( new ImageNode(make_scoped_refptr(new ImageFake()), RectF(1.0f, 1.0f))); - scoped_refptr<NodeAnimationsMap> animations = + scoped_refptr<AnimateNode> with_animations = CreateSingleAnimation(image_node, base::Bind(&AnimateImage)); scoped_refptr<Node> animated_render_tree = - animations->Apply(image_node, base::TimeDelta::FromSeconds(1)); + with_animations->Apply(base::TimeDelta::FromSeconds(1)); ImageNode* animated_image_node = dynamic_cast<ImageNode*>(animated_render_tree.get()); EXPECT_TRUE(animated_image_node); @@ -109,16 +109,16 @@ UNREFERENCED_PARAMETER(time_elapsed); rect_node->rect = RectF(2.0f, 2.0f); } -TEST(NodeAnimationsMapTest, EnsureSingleRectNodeAnimates) { +TEST(AnimateNodeTest, EnsureSingleRectNodeAnimates) { scoped_refptr<RectNode> rect_node(new RectNode( RectF(1.0f, 1.0f), scoped_ptr<Brush>(new SolidColorBrush(ColorRGBA(1.0f, 1.0f, 1.0f))))); - scoped_refptr<NodeAnimationsMap> animations = + scoped_refptr<AnimateNode> with_animations = CreateSingleAnimation(rect_node, base::Bind(&AnimateRect)); scoped_refptr<Node> animated_render_tree = - animations->Apply(rect_node, base::TimeDelta::FromSeconds(1)); + with_animations->Apply(base::TimeDelta::FromSeconds(1)); RectNode* animated_rect_node = dynamic_cast<RectNode*>(animated_render_tree.get()); EXPECT_TRUE(animated_rect_node); @@ -135,33 +135,32 @@ static_cast<float>(time_elapsed.InSecondsF()), static_cast<float>(time_elapsed.InSecondsF())); } -TEST(NodeAnimationsMapTest, - SingleImageNodeAnimatesOverTimeRepeatedlyCorrectly) { +TEST(AnimateNodeTest, SingleImageNodeAnimatesOverTimeRepeatedlyCorrectly) { scoped_refptr<ImageNode> image_node( new ImageNode(make_scoped_refptr(new ImageFake()), RectF(1.0f, 1.0f))); - scoped_refptr<NodeAnimationsMap> animations = + scoped_refptr<AnimateNode> with_animations = CreateSingleAnimation(image_node, base::Bind(&AnimateImageAddWithTime)); scoped_refptr<Node> animated_render_tree; ImageNode* animated_image_node; animated_render_tree = - animations->Apply(image_node, base::TimeDelta::FromSeconds(1)); + with_animations->Apply(base::TimeDelta::FromSeconds(1)); animated_image_node = dynamic_cast<ImageNode*>(animated_render_tree.get()); EXPECT_TRUE(animated_image_node); EXPECT_TRUE(animated_image_node); EXPECT_FLOAT_EQ(3.0f, animated_image_node->data().destination_rect.width()); animated_render_tree = - animations->Apply(image_node, base::TimeDelta::FromSeconds(2)); + with_animations->Apply(base::TimeDelta::FromSeconds(2)); animated_image_node = dynamic_cast<ImageNode*>(animated_render_tree.get()); EXPECT_TRUE(animated_image_node); EXPECT_TRUE(animated_image_node); EXPECT_FLOAT_EQ(5.0f, animated_image_node->data().destination_rect.width()); animated_render_tree = - animations->Apply(image_node, base::TimeDelta::FromSeconds(4)); + with_animations->Apply(base::TimeDelta::FromSeconds(4)); animated_image_node = dynamic_cast<ImageNode*>(animated_render_tree.get()); EXPECT_TRUE(animated_image_node); EXPECT_TRUE(animated_image_node); @@ -177,8 +176,7 @@ static_cast<float>(time_elapsed.InSecondsF())); image_node->destination_rect.set_size(image_size); } -TEST(NodeAnimationsMapTest, - MultipleAnimationsTargetingOneNodeApplyInCorrectOrder) { +TEST(AnimateNodeTest, MultipleAnimationsTargetingOneNodeApplyInCorrectOrder) { scoped_refptr<ImageNode> image_node( new ImageNode(make_scoped_refptr(new ImageFake()), RectF(1.0f, 1.0f))); @@ -192,15 +190,15 @@ animation_list_builder.animations.push_back( base::Bind(&AnimateImageScaleWithTime)); - NodeAnimationsMap::Builder animations_builder; + AnimateNode::Builder animations_builder; animations_builder.Add(image_node, make_scoped_refptr(new AnimationList<ImageNode>( animation_list_builder.Pass()))); - scoped_refptr<NodeAnimationsMap> animations( - new NodeAnimationsMap(animations_builder.Pass())); + scoped_refptr<AnimateNode> with_animations( + new AnimateNode(animations_builder, image_node)); scoped_refptr<Node> animated_render_tree = - animations->Apply(image_node, base::TimeDelta::FromSeconds(3)); + with_animations->Apply(base::TimeDelta::FromSeconds(3)); ImageNode* animated_image_node = dynamic_cast<ImageNode*>(animated_render_tree.get()); @@ -216,22 +214,21 @@ UNREFERENCED_PARAMETER(time_elapsed); transform_node->transform = math::TranslateMatrix(2.0f, 2.0f); } -TEST(NodeAnimationsMapTest, AnimatingTransformNodeDoesNotAffectSourceChild) { +TEST(AnimateNodeTest, AnimatingTransformNodeDoesNotAffectSourceChild) { scoped_refptr<ImageNode> image_node( new ImageNode(make_scoped_refptr(new ImageFake()), RectF(1.0f, 1.0f))); scoped_refptr<MatrixTransformNode> transform_node( new MatrixTransformNode(image_node, math::Matrix3F::Identity())); - scoped_refptr<NodeAnimationsMap> animations = + scoped_refptr<AnimateNode> with_animations = CreateSingleAnimation(transform_node, base::Bind(&AnimateTransform)); scoped_refptr<Node> animated_render_tree = - animations->Apply(transform_node, base::TimeDelta::FromSeconds(1)); + with_animations->Apply(base::TimeDelta::FromSeconds(1)); MatrixTransformNode* animated_transform_node = dynamic_cast<MatrixTransformNode*>(animated_render_tree.get()); EXPECT_TRUE(animated_transform_node); - EXPECT_TRUE(animated_transform_node); EXPECT_EQ(math::TranslateMatrix(2.0f, 2.0f), animated_transform_node->data().transform); @@ -241,7 +238,7 @@ // Test that animating a child correctly adjusts sub-node parameters but // not parent node parameters, though both child and parent are different nodes // now. The animated child's sibling should be left untouched. -TEST(NodeAnimationsMapTest, +TEST(AnimateNodeTest, AnimatingCompositionChildNodeAffectsParentAsWellButNotSibling) { scoped_refptr<ImageNode> image_node_a( new ImageNode(make_scoped_refptr(new ImageFake()), RectF(1.0f, 1.0f))); @@ -253,11 +250,13 @@ scoped_refptr<CompositionNode> composition_node( new CompositionNode(composition_node_builder.Pass())); - scoped_refptr<NodeAnimationsMap> animations = - CreateSingleAnimation(image_node_a, base::Bind(&AnimateImage)); + AnimateNode::Builder animation_builder; + animation_builder.Add(image_node_a, base::Bind(&AnimateImage)); + scoped_refptr<AnimateNode> with_animations = + new AnimateNode(animation_builder, composition_node); scoped_refptr<Node> animated_render_tree = - animations->Apply(composition_node, base::TimeDelta::FromSeconds(1)); + with_animations->Apply(base::TimeDelta::FromSeconds(1)); CompositionNode* animated_composition_node = dynamic_cast<CompositionNode*>(animated_render_tree.get()); @@ -273,6 +272,76 @@ EXPECT_EQ(image_node_b.get(), animated_image_node_b); } +TEST(AnimateNodeTest, SimpleSubAnimateNode) { + // Test that we can properly animate trees that built upon multiple + // AnimateNodes. + scoped_refptr<ImageNode> image_node( + new ImageNode(make_scoped_refptr(new ImageFake()), RectF(1.0f, 1.0f))); + scoped_refptr<AnimateNode> image_animation = + CreateSingleAnimation(image_node, base::Bind(&AnimateImage)); + + scoped_refptr<MatrixTransformNode> transform_node( + new MatrixTransformNode(image_animation, math::Matrix3F::Identity())); + + scoped_refptr<AnimateNode> with_animations = + CreateSingleAnimation(transform_node, base::Bind(&AnimateTransform)); + + scoped_refptr<Node> animated_render_tree = + with_animations->Apply(base::TimeDelta::FromSeconds(1)); + + MatrixTransformNode* animated_transform_node = + dynamic_cast<MatrixTransformNode*>(animated_render_tree.get()); + EXPECT_TRUE(animated_transform_node); + + // Check that the matrix transform node is animated. + EXPECT_EQ(math::TranslateMatrix(2.0f, 2.0f), + animated_transform_node->data().transform); + + // Check also that the image node is animated. + ImageNode* animated_image_node = + dynamic_cast<ImageNode*>(animated_transform_node->data().source.get()); + EXPECT_TRUE(animated_image_node); + EXPECT_EQ(RectF(2.0f, 2.0f), animated_image_node->data().destination_rect); +} + +TEST(AnimateNodeTest, SubAnimateNodeWithTwoAncestors) { + // Test that we can properly animate trees that built upon multiple + // AnimateNodes. + scoped_refptr<ImageNode> image_node( + new ImageNode(make_scoped_refptr(new ImageFake()), RectF(1.0f, 1.0f))); + scoped_refptr<AnimateNode> image_animation = + CreateSingleAnimation(image_node, base::Bind(&AnimateImage)); + + // This node is used to make it so there is more than one node on the path + // between the two AnimateNodes. + scoped_refptr<MatrixTransformNode> transform_node_a( + new MatrixTransformNode(image_animation, math::Matrix3F::Identity())); + + scoped_refptr<MatrixTransformNode> transform_node_b( + new MatrixTransformNode(transform_node_a, math::Matrix3F::Identity())); + + scoped_refptr<AnimateNode> with_animations = + new AnimateNode(transform_node_b); + + scoped_refptr<Node> animated_render_tree = + with_animations->Apply(base::TimeDelta::FromSeconds(1)); + + MatrixTransformNode* animated_transform_node = + dynamic_cast<MatrixTransformNode*>(animated_render_tree.get()); + EXPECT_TRUE(animated_transform_node); + + // Check that the image node is animated. + MatrixTransformNode* animated_dummy_transform_node = + dynamic_cast<MatrixTransformNode*>( + animated_transform_node->data().source.get()); + EXPECT_TRUE(animated_dummy_transform_node); + + ImageNode* animated_image_node = dynamic_cast<ImageNode*>( + animated_dummy_transform_node->data().source.get()); + EXPECT_TRUE(animated_image_node); + EXPECT_EQ(RectF(2.0f, 2.0f), animated_image_node->data().destination_rect); +} + } // namespace animations } // namespace render_tree } // namespace cobalt
diff --git a/src/cobalt/render_tree/animations/animation_list.h b/src/cobalt/render_tree/animations/animation_list.h index 8c83f36..a37bd3f 100644 --- a/src/cobalt/render_tree/animations/animation_list.h +++ b/src/cobalt/render_tree/animations/animation_list.h
@@ -67,7 +67,7 @@ // base::TimeDelta::FromSeconds(1))); // // You can now create an AnimationList object from the AnimationList::Builder - // and ultimately add that to a NodeAnimationsMap object so that it can be + // and ultimately add that to a AnimateNode::Builder object so that it can be // mapped to a specific TextNode that it should be applied to. typedef base::Callback<void(typename T::Builder*, base::TimeDelta)> Function; };
diff --git a/src/cobalt/render_tree/animations/node_animations_map.cc b/src/cobalt/render_tree/animations/node_animations_map.cc deleted file mode 100644 index c123536..0000000 --- a/src/cobalt/render_tree/animations/node_animations_map.cc +++ /dev/null
@@ -1,314 +0,0 @@ -/* - * Copyright 2015 Google Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "cobalt/render_tree/animations/node_animations_map.h" - -#include "base/debug/trace_event.h" -#include "base/optional.h" -#include "cobalt/base/polymorphic_downcast.h" -#include "cobalt/render_tree/composition_node.h" -#include "cobalt/render_tree/filter_node.h" -#include "cobalt/render_tree/image_node.h" -#include "cobalt/render_tree/matrix_transform_node.h" -#include "cobalt/render_tree/node_visitor.h" -#include "cobalt/render_tree/punch_through_video_node.h" -#include "cobalt/render_tree/rect_node.h" -#include "cobalt/render_tree/rect_shadow_node.h" -#include "cobalt/render_tree/text_node.h" - -namespace cobalt { -namespace render_tree { -namespace animations { - -void NodeAnimationsMap::Builder::AddInternal( - const scoped_refptr<Node>& target_node, - const scoped_refptr<AnimationListBase>& animation_list) { - DCHECK(node_animation_map_.find(target_node) == node_animation_map_.end()) - << "The target render tree node already has an associated animation " - "list."; - - node_animation_map_[target_node.get()] = animation_list; - node_refs_.push_back(target_node); -} - -void NodeAnimationsMap::Builder::Merge( - const NodeAnimationsMap::Builder& other) { -#if !defined(NDEBUG) - for (InternalMap::const_iterator iter = node_animation_map_.begin(); - iter != node_animation_map_.end(); ++iter) { - DCHECK(other.node_animation_map_.find(iter->first) == - other.node_animation_map_.end()) << - "Only mutually exclusive NodeAnimationMaps can be merged!"; - } -#endif - node_animation_map_.insert( - other.node_animation_map_.begin(), other.node_animation_map_.end()); - node_refs_.insert( - node_refs_.end(), other.node_refs_.begin(), other.node_refs_.end()); -} - -AnimationListBase* NodeAnimationsMap::GetAnimationsForNode(Node* target) const { - Builder::InternalMap::const_iterator found = - data_.node_animation_map_.find(target); - if (found == data_.node_animation_map_.end()) return NULL; - return found->second.get(); -} - -// This visitor object contains the logic for how to apply animation to each -// render tree node. Things are most interesting for node types that may -// contain child render tree nodes, like CompositionNode. In this case, -// they will need to be animated not only if animations directly affect them, -// but also if any of their children have been animated. -class NodeAnimationsMap::NodeVisitor : public render_tree::NodeVisitor { - public: - explicit NodeVisitor(const NodeAnimationsMap& animations, - const base::TimeDelta& time_elapsed); - - void Visit(CompositionNode* composition_node) OVERRIDE; - void Visit(FilterNode* image_node) OVERRIDE; - void Visit(ImageNode* image_node) OVERRIDE; - void Visit(MatrixTransformNode* matrix_transform_node) OVERRIDE; - void Visit(PunchThroughVideoNode* punch_through_video_node) OVERRIDE; - void Visit(RectNode* rect_node) OVERRIDE; - void Visit(RectShadowNode* rect_shadow_node) OVERRIDE; - void Visit(TextNode* text_node) OVERRIDE; - - bool has_animated_node() const { return !!animated_node_; } - - // NodeVisitor objects are intended to be "one-shot" - // visit objects. The "return value" (e.g. the animated node) can be - // retrieved by calling animated_node() after Visit() has been called. - const scoped_refptr<Node>& animated_node() { return *animated_node_; } - - // Helper function to apply all animations in a AnimationList to a specific - // node builder. - template <typename T> - static void ApplyAnimations(typename T::Builder* builder, - const AnimationListBase* node_animations, - base::TimeDelta time_elapsed); - - // Helper function for applying animations to simple nodes that don't have any - // children or special cases. - template <typename T> - static base::optional<scoped_refptr<Node> > - MaybeCloneLeafNodeAndApplyAnimations( - T* node, const NodeAnimationsMap& animations, - base::TimeDelta time_elapsed); - - private: - const NodeAnimationsMap& animations_; - const base::TimeDelta& time_elapsed_; - - base::optional<scoped_refptr<Node> > animated_node_; -}; - -NodeAnimationsMap::NodeVisitor::NodeVisitor(const NodeAnimationsMap& animations, - const base::TimeDelta& time_elapsed) - : animations_(animations), time_elapsed_(time_elapsed) {} - -template <typename T> -void NodeAnimationsMap::NodeVisitor::ApplyAnimations( - typename T::Builder* builder, const AnimationListBase* node_animations, - base::TimeDelta time_elapsed) { - // Cast to the specific type we expect these animations to have. - const AnimationList<T>* typed_node_animations = - base::polymorphic_downcast<const AnimationList<T>*>(node_animations); - - // Iterate through each animation applying them one at a time. - for (typename AnimationList<T>::InternalList::const_iterator iter = - typed_node_animations->data().animations.begin(); - iter != typed_node_animations->data().animations.end(); ++iter) { - iter->Run(builder, time_elapsed); - } -} - -template <typename T> -base::optional<scoped_refptr<Node> > -NodeAnimationsMap::NodeVisitor::MaybeCloneLeafNodeAndApplyAnimations( - T* node, const NodeAnimationsMap& animations, - base::TimeDelta time_elapsed) { - const AnimationListBase* node_animations = - animations.GetAnimationsForNode(node); - if (node_animations != NULL) { - typename T::Builder builder(node->data()); - - ApplyAnimations<T>(&builder, node_animations, time_elapsed); - - return scoped_refptr<Node>(new T(builder)); - } else { - // No animations were applied to this node, return NULL to signify this. - return base::nullopt; - } -} - -void NodeAnimationsMap::NodeVisitor::Visit(CompositionNode* composition_node) { - // We declare the builder as an optional because we may not need one if we - // have no animations and none of our children are animated. - base::optional<CompositionNode::Builder> builder; - - const CompositionNode::Children& original_children = - composition_node->data().children(); - - // Iterate through our children and visit them to apply animations. After - // each one, check to see if it actually was animated, and if so, replace - // this composition node's reference to that child with the newly animated - // one. - for (size_t i = 0; i < original_children.size(); ++i) { - NodeVisitor child_visitor(animations_, time_elapsed_); - original_children[i]->Accept(&child_visitor); - - // If a child was animated, then we must adjust our child node reference to - // the newly animated one. - if (child_visitor.has_animated_node()) { - if (!builder) { - builder.emplace(composition_node->data()); - } - *builder->GetChild(static_cast<int>(i)) = child_visitor.animated_node(); - } - } - - // Check if any animations apply directly to us, and if so, apply them. - const AnimationListBase* animations = - animations_.GetAnimationsForNode(composition_node); - if (animations != NULL) { - if (!builder) { - builder.emplace(composition_node->data()); - } - ApplyAnimations<CompositionNode>(&builder.value(), animations, - time_elapsed_); - } - - // Return the animated node. If no animations took place, leave - // animated_node_ as NULL to signify that no animations took place. - if (builder) { - animated_node_ = scoped_refptr<Node>(new CompositionNode(builder->Pass())); - } -} - -void NodeAnimationsMap::NodeVisitor::Visit(FilterNode* filter_node) { - base::optional<FilterNode::Builder> builder; - - // First check to see if our source node has any animations, and if so, - // animate it. - NodeVisitor child_visitor(animations_, time_elapsed_); - filter_node->data().source->Accept(&child_visitor); - - if (child_visitor.has_animated_node()) { - // If our source node was animated, then so must we be, so create a - // builder and set it up to point to our animated source node. - builder.emplace(filter_node->data()); - builder->source = child_visitor.animated_node(); - } - - // Apply any animations to the filter node itself. - const AnimationListBase* animations = - animations_.GetAnimationsForNode(filter_node); - if (animations != NULL) { - if (!builder) { - builder.emplace(filter_node->data()); - } - ApplyAnimations<FilterNode>(&builder.value(), animations, time_elapsed_); - } - - // Return the animated node. If no animations took place, leave - // animated_node_ as NULL to signify that no animations took place. - if (builder) { - animated_node_ = scoped_refptr<Node>(new FilterNode(*builder)); - } -} - -void NodeAnimationsMap::NodeVisitor::Visit(ImageNode* image_node) { - animated_node_ = MaybeCloneLeafNodeAndApplyAnimations( - image_node, animations_, time_elapsed_); -} - -void NodeAnimationsMap::NodeVisitor::Visit( - MatrixTransformNode* matrix_transform_node) { - base::optional<MatrixTransformNode::Builder> builder; - - // First check to see if our source node has any animations, and if so, - // animate it. - NodeVisitor child_visitor(animations_, time_elapsed_); - matrix_transform_node->data().source->Accept(&child_visitor); - - if (child_visitor.has_animated_node()) { - // If our source node was animated, then so must we be, so create a - // builder and set it up to point to our animated source node. - builder.emplace(matrix_transform_node->data()); - builder->source = child_visitor.animated_node(); - } - - // Apply any animations to the filter node itself. - const AnimationListBase* animations = - animations_.GetAnimationsForNode(matrix_transform_node); - if (animations != NULL) { - if (!builder) { - builder.emplace(matrix_transform_node->data()); - } - ApplyAnimations<MatrixTransformNode>(&builder.value(), animations, - time_elapsed_); - } - - // Return the animated node. If no animations took place, leave - // animated_node_ as NULL to signify that no animations took place. - if (builder) { - animated_node_ = scoped_refptr<Node>(new MatrixTransformNode(*builder)); - } -} - -void NodeAnimationsMap::NodeVisitor::Visit( - PunchThroughVideoNode* punch_through_video_node) { - animated_node_ = MaybeCloneLeafNodeAndApplyAnimations( - punch_through_video_node, animations_, time_elapsed_); -} - -void NodeAnimationsMap::NodeVisitor::Visit(RectNode* rect_node) { - // We do not use MaybeCloneLeafNodeAndApplyAnimations() here so that we can - // construct our RectNode via a move of the RectNode::Builder object, instead - // of a copy. - const AnimationListBase* node_animations = - animations_.GetAnimationsForNode(rect_node); - if (node_animations != NULL) { - RectNode::Builder builder(rect_node->data()); - - ApplyAnimations<RectNode>(&builder, node_animations, time_elapsed_); - - // Move construct our RectNode from the RectNode::Builder object. - animated_node_ = scoped_refptr<Node>(new RectNode(builder.Pass())); - } -} - -void NodeAnimationsMap::NodeVisitor::Visit(RectShadowNode* rect_shadow_node) { - animated_node_ = MaybeCloneLeafNodeAndApplyAnimations( - rect_shadow_node, animations_, time_elapsed_); -} - -void NodeAnimationsMap::NodeVisitor::Visit(TextNode* text_node) { - animated_node_ = MaybeCloneLeafNodeAndApplyAnimations( - text_node, animations_, time_elapsed_); -} - -scoped_refptr<Node> NodeAnimationsMap::Apply(const scoped_refptr<Node>& root, - base::TimeDelta time_elapsed) { - TRACE_EVENT0("cobalt::renderer", "NodeAnimationsMap::Apply()"); - NodeVisitor root_visitor(*this, time_elapsed); - root->Accept(&root_visitor); - return root_visitor.has_animated_node() ? root_visitor.animated_node() : root; -} - -} // namespace animations -} // namespace render_tree -} // namespace cobalt
diff --git a/src/cobalt/render_tree/animations/node_animations_map.h b/src/cobalt/render_tree/animations/node_animations_map.h deleted file mode 100644 index 669cd61..0000000 --- a/src/cobalt/render_tree/animations/node_animations_map.h +++ /dev/null
@@ -1,130 +0,0 @@ -/* - * Copyright 2015 Google Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef COBALT_RENDER_TREE_ANIMATIONS_NODE_ANIMATIONS_MAP_H_ -#define COBALT_RENDER_TREE_ANIMATIONS_NODE_ANIMATIONS_MAP_H_ - -#include <map> -#include <vector> - -#include "base/containers/small_map.h" -#include "base/memory/ref_counted.h" -#include "cobalt/render_tree/animations/animation_list.h" -#include "cobalt/render_tree/movable.h" -#include "cobalt/render_tree/node.h" - -namespace cobalt { -namespace render_tree { -namespace animations { - -// A NodeAnimationsMap object represents a reference counted and immutable (so -// they can be easily shared between threads) set of animations, along with -// references to the render tree Nodes that they target. NodeAnimationsMap -// objects contain animation information about corresponding render trees and -// are intended to be passed alongside them to modules that would like to -// animate render trees. -// NodeAnimationsMap objects essentially organize their collections of -// animations as an unordered map from render tree Node objects to -// AnimationLists. Thus, animation can be applied to a render tree by traversing -// it and for each element checking to see if any animations exist for them, and -// if so, apply them. Indeed, the NodeAnimationsMap object's primary method, -// Apply(), does just this. -class NodeAnimationsMap : public base::RefCountedThreadSafe<NodeAnimationsMap> { - public: - // Use this NodeAnimationsMap::Builder object to construct your collection of - // animations and corresponding render_tree Nodes. When setup is complete, - // construct a NodeAnimationsMap object with the Builder. - class Builder { - public: - DECLARE_AS_MOVABLE(Builder); - - Builder() {} - explicit Builder(Moved moved) { - node_animation_map_ = moved->node_animation_map_; - node_refs_.swap(moved->node_refs_); - } - - // This method is a template so that we can ensure that animations are not - // mismatched with render tree nodes of the wrong type. - template <typename T> - void Add(const scoped_refptr<T>& target_node, - const scoped_refptr<AnimationList<T> >& animation_list) { - AddInternal(target_node, animation_list); - } - - // Convenience method to attach a single animation to a target node. - template <typename T> - void Add(const scoped_refptr<T>& target_node, - const typename Animation<T>::Function& single_animation) { - AddInternal(target_node, scoped_refptr<AnimationListBase>( - new AnimationList<T>(single_animation))); - } - - // Merge all mappings from another NodeAnimationsMap into this one. There - // cannot be any keys that are in both the merge target and source. - void Merge(const NodeAnimationsMap& other) { Merge(other.data_); } - void Merge(const NodeAnimationsMap::Builder& other); - - private: - // A non-template function that contains the logic for storing a target - // node and animation list pair. - void AddInternal(const scoped_refptr<Node>& target_node, - const scoped_refptr<AnimationListBase>& animation_list); - - // The primary internal data structure used to organize and store the - // mapping between target render tree node and animation list. - // In many cases there are not many active animations, and so we use a - // base::SmallMap for this. std::map was found to be more performant than - // base::hash_map, so it is used as the fallback map. - typedef base::SmallMap< - std::map<Node*, scoped_refptr<AnimationListBase> >, 4> InternalMap; - InternalMap node_animation_map_; - std::vector<scoped_refptr<Node> > node_refs_; - - friend class NodeAnimationsMap; - }; - - // Since Builder objects are heavy-weight, this constructor allows them to - // be move constructed into the NodeAnimationsMap object. - explicit NodeAnimationsMap(Builder::Moved builder) : data_(builder) {} - - // Given the passed in current time, this method will apply all contained - // animations to the passed in render tree, returning a new render tree that - // has animations applied. Nodes will only be newly created if they are - // animated or one of their descendants are animated, otherwise the original - // input node will be used and returned. - scoped_refptr<Node> Apply(const scoped_refptr<Node>& root, - base::TimeDelta time_elapsed); - - private: - ~NodeAnimationsMap() {} - - // Returns NULL if no animations exist for target node. - AnimationListBase* GetAnimationsForNode(Node* target) const; - - const Builder data_; - - class NodeVisitor; - friend class NodeVisitor; - - friend class base::RefCountedThreadSafe<NodeAnimationsMap>; -}; - -} // namespace animations -} // namespace render_tree -} // namespace cobalt - -#endif // COBALT_RENDER_TREE_ANIMATIONS_NODE_ANIMATIONS_MAP_H_
diff --git a/src/cobalt/render_tree/child_iterator.h b/src/cobalt/render_tree/child_iterator.h new file mode 100644 index 0000000..d5567c5 --- /dev/null +++ b/src/cobalt/render_tree/child_iterator.h
@@ -0,0 +1,226 @@ +/* + * 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_RENDER_TREE_CHILD_ITERATOR_H_ +#define COBALT_RENDER_TREE_CHILD_ITERATOR_H_ + +#include "cobalt/render_tree/composition_node.h" +#include "cobalt/render_tree/filter_node.h" +#include "cobalt/render_tree/image_node.h" +#include "cobalt/render_tree/matrix_transform_node.h" +#include "cobalt/render_tree/node.h" +#include "cobalt/render_tree/punch_through_video_node.h" +#include "cobalt/render_tree/rect_node.h" +#include "cobalt/render_tree/rect_shadow_node.h" +#include "cobalt/render_tree/text_node.h" + +namespace cobalt { +namespace render_tree { + +class ImageNode; +class PunchThroughVideoNode; +class RectNode; +class RectShadowNode; +class TextNode; + +// The ChildIterator template provides a way to iterate over the children of +// a node without concern for what type of node it is (though since it is a +// template, the compiler must know the type). Thus, render_tree::NodeVisitor +// subclasses can forward visits to a ChildIterator if they want to traverse +// the tree without writing traversal code for specific render tree node types. +// Additionally, ReplaceCurrent() can be used to modify the list of children +// at a given node, allowing render tree modifications to be made by code that +// does not care about what type of render tree nodes it is dealing with. +// Note that child-related methods like GetCurrent(), Next(), and +// ReplaceCurrent() are only enabled for nodes that have children. This can +// be checked via |ChildIterator<T>::has_children|. +// +// Example usage: +// +// void Visit(CompositionNode* node) { VisitNode(node); } +// void Visit(ImageNode* node) { VisitNode(node); } +// ... +// +// template <typename T> +// typename base::enable_if<!ChildIterator<T>::has_children>::type +// VisitNode(T* node) { +// ProcessNode(); +// } +// +// template <typename T> +// typename base::enable_if<ChildIterator<T>::has_children>::type VisitNode( +// T* node) { +// ProcessNode(); +// +// // Visit children +// ChildIterator<T> child_iterator(node); +// while (Node* child = child_iterator.GetCurrent()) { +// Visit(child); +// child_iterator.Next(); +// } +// } +// +// void ProcessNode(Node* node) { +// // Called on every node +// ... +// } +// + +template <typename T, typename = void> +class ChildIterator { + public: + // This default class is used for all nodes that have no children. + static const bool has_children = false; +}; + +enum ChildIteratorDirection { + // Decides whether we start at the first or last child. + kChildIteratorDirectionForwards, + kChildIteratorDirectionBackwards, +}; + +// CompositionNodes may have multiple children, so we setup ChildIterator +// to iterate through each of them. +template <> +class ChildIterator<CompositionNode> { + public: + static const bool has_children = true; + + explicit ChildIterator( + CompositionNode* composition, + ChildIteratorDirection direction = kChildIteratorDirectionForwards) + : composition_node_(composition), + children_(composition_node_->data().children()), + child_number_(0), + direction_(direction) {} + + Node* GetCurrent() const { + return done() ? NULL : children_[child_index()].get(); + } + void Next() { ++child_number_; } + + void ReplaceCurrent(const scoped_refptr<Node>& new_child) { + DCHECK(!done()); + if (!modified_children_builder_) { + // If we haven't replaced any children yet, we start by constructing a new + // modifiable version of this CompositionNode's data so that we can + // modify its children. + modified_children_builder_ = composition_node_->data(); + } + // Update the modified children list with the newly replaced child. + *modified_children_builder_->GetChild(static_cast<int>(child_index())) = + new_child; + } + CompositionNode::Builder::Moved TakeReplacedChildrenBuilder() { + return modified_children_builder_->Pass(); + } + + private: + size_t child_index() const { + DCHECK(!done()); + return direction_ == kChildIteratorDirectionForwards + ? child_number_ + : children_.size() - child_number_ - 1; + } + bool done() const { return child_number_ >= children_.size(); } + + // The node whose children we are iterating through. + CompositionNode* composition_node_; + // A quick reference to the node's children. + const CompositionNode::Children& children_; + // The current child index we are at with our iteration. + size_t child_number_; + + ChildIteratorDirection direction_; + + // The builder to use if we are modifying the children. If constructed, it + // starts as a copy of the origin CompositionNode's data. + base::optional<CompositionNode::Builder> modified_children_builder_; +}; + +// FilterNodes can have up to 1 child. +template <> +class ChildIterator<FilterNode> { + public: + static const bool has_children = true; + + explicit ChildIterator( + FilterNode* filter, + ChildIteratorDirection direction = kChildIteratorDirectionForwards) + : filter_node_(filter), source_(filter->data().source.get()) { + UNREFERENCED_PARAMETER(direction); + } + + Node* GetCurrent() const { return source_; } + void Next() { source_ = NULL; } + + void ReplaceCurrent(const scoped_refptr<Node>& new_child) { + DCHECK(GetCurrent()); + if (!modified_children_builder_) { + modified_children_builder_ = filter_node_->data(); + } + modified_children_builder_->source = new_child; + } + FilterNode::Builder TakeReplacedChildrenBuilder() { + return *modified_children_builder_; + } + + private: + FilterNode* filter_node_; + Node* source_; + + base::optional<FilterNode::Builder> modified_children_builder_; +}; + +// MatrixTransformNodes can have up to 1 child. +template <> +class ChildIterator<MatrixTransformNode> { + public: + static const bool has_children = true; + + explicit ChildIterator( + MatrixTransformNode* matrix_transform, + ChildIteratorDirection direction = kChildIteratorDirectionForwards) + : matrix_transform_node_(matrix_transform), + source_(matrix_transform->data().source.get()) { + UNREFERENCED_PARAMETER(direction); + } + + Node* GetCurrent() const { return source_; } + void Next() { source_ = NULL; } + + void ReplaceCurrent(const scoped_refptr<Node>& new_child) { + DCHECK(GetCurrent()); + if (!modified_children_builder_) { + modified_children_builder_ = matrix_transform_node_->data(); + } + modified_children_builder_->source = new_child; + } + MatrixTransformNode::Builder TakeReplacedChildrenBuilder() { + return *modified_children_builder_; + } + + private: + MatrixTransformNode* matrix_transform_node_; + Node* source_; + + base::optional<MatrixTransformNode::Builder> modified_children_builder_; +}; + +} // namespace render_tree +} // namespace cobalt + +#endif // COBALT_RENDER_TREE_CHILD_ITERATOR_H_
diff --git a/src/cobalt/render_tree/dump_render_tree_to_string.cc b/src/cobalt/render_tree/dump_render_tree_to_string.cc index adee88e..6fdc38e 100644 --- a/src/cobalt/render_tree/dump_render_tree_to_string.cc +++ b/src/cobalt/render_tree/dump_render_tree_to_string.cc
@@ -31,6 +31,10 @@ namespace cobalt { namespace render_tree { +namespace animations { +class AnimateNode; +} // namespace animations + namespace { // A render tree visitor that accumulates node dumps to text within a @@ -39,6 +43,7 @@ public: DebugTreePrinter() : indent_(0) {} + void Visit(animations::AnimateNode* /* animate */) OVERRIDE { NOTREACHED(); } void Visit(CompositionNode* composition) OVERRIDE; void Visit(FilterNode* text) OVERRIDE; void Visit(ImageNode* image) OVERRIDE;
diff --git a/src/cobalt/render_tree/node_visitor.h b/src/cobalt/render_tree/node_visitor.h index 73b9c21..de6c026 100644 --- a/src/cobalt/render_tree/node_visitor.h +++ b/src/cobalt/render_tree/node_visitor.h
@@ -29,11 +29,16 @@ class RectShadowNode; class TextNode; +namespace animations { +class AnimateNode; +} // namespace animations + // Type-safe branching on a class hierarchy of render tree nodes, // implemented after a classical GoF pattern (see // http://en.wikipedia.org/wiki/Visitor_pattern#Java_example). class NodeVisitor { public: + virtual void Visit(animations::AnimateNode* animate) = 0; virtual void Visit(CompositionNode* composition) = 0; virtual void Visit(FilterNode* text) = 0; virtual void Visit(ImageNode* image) = 0;
diff --git a/src/cobalt/render_tree/node_visitor_test.cc b/src/cobalt/render_tree/node_visitor_test.cc index 502a749..7a24cc4 100644 --- a/src/cobalt/render_tree/node_visitor_test.cc +++ b/src/cobalt/render_tree/node_visitor_test.cc
@@ -20,6 +20,7 @@ #include "cobalt/math/rect_f.h" #include "cobalt/math/size.h" +#include "cobalt/render_tree/animations/animate_node.h" #include "cobalt/render_tree/composition_node.h" #include "cobalt/render_tree/filter_node.h" #include "cobalt/render_tree/font.h" @@ -33,6 +34,7 @@ #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" +using cobalt::render_tree::animations::AnimateNode; using cobalt::render_tree::Brush; using cobalt::render_tree::BrushVisitor; using cobalt::render_tree::ColorRGBA; @@ -53,6 +55,7 @@ class MockNodeVisitor : public NodeVisitor { public: + MOCK_METHOD1(Visit, void(AnimateNode* animate)); MOCK_METHOD1(Visit, void(CompositionNode* composition)); MOCK_METHOD1(Visit, void(FilterNode* image)); MOCK_METHOD1(Visit, void(ImageNode* image)); @@ -99,6 +102,15 @@ } // namespace +TEST(NodeVisitorTest, VisitsAnimate) { + scoped_refptr<DummyImage> dummy_image = make_scoped_refptr(new DummyImage()); + scoped_refptr<ImageNode> dummy_image_node(new ImageNode(dummy_image)); + scoped_refptr<AnimateNode> animate_node(new AnimateNode(dummy_image_node)); + MockNodeVisitor mock_visitor; + EXPECT_CALL(mock_visitor, Visit(animate_node.get())); + animate_node->Accept(&mock_visitor); +} + TEST(NodeVisitorTest, VisitsImage) { scoped_refptr<DummyImage> image = make_scoped_refptr(new DummyImage()); scoped_refptr<ImageNode> image_node(new ImageNode(image));
diff --git a/src/cobalt/render_tree/render_tree.gyp b/src/cobalt/render_tree/render_tree.gyp index 5af25ff..6e7c6a7 100644 --- a/src/cobalt/render_tree/render_tree.gyp +++ b/src/cobalt/render_tree/render_tree.gyp
@@ -30,6 +30,7 @@ 'brush.cc', 'brush.h', 'brush_visitor.h', + 'child_iterator.h', 'color_rgba.h', 'composition_node.cc', 'composition_node.h', @@ -73,8 +74,8 @@ 'target_name': 'animations', 'type': 'static_library', 'sources': [ - 'animations/node_animations_map.cc', - 'animations/node_animations_map.h', + 'animations/animate_node.cc', + 'animations/animate_node.h', ], 'dependencies': [ 'render_tree', @@ -86,7 +87,7 @@ 'target_name': 'render_tree_test', 'type': '<(gtest_target_type)', 'sources': [ - 'animations/node_animations_map_test.cc', + 'animations/animate_node_test.cc', 'brush_visitor_test.cc', 'color_rgba_test.cc', 'node_visitor_test.cc',
diff --git a/src/cobalt/renderer/animations_test.cc b/src/cobalt/renderer/animations_test.cc index 8c488a5..033a78f 100644 --- a/src/cobalt/renderer/animations_test.cc +++ b/src/cobalt/renderer/animations_test.cc
@@ -16,6 +16,7 @@ #include "base/synchronization/waitable_event.h" #include "base/threading/simple_thread.h" +#include "cobalt/render_tree/animations/animate_node.h" #include "cobalt/render_tree/image.h" #include "cobalt/render_tree/image_node.h" #include "cobalt/render_tree/resource_provider.h" @@ -29,10 +30,10 @@ #include "testing/gtest/include/gtest/gtest.h" +using cobalt::render_tree::animations::AnimateNode; using cobalt::render_tree::Image; using cobalt::render_tree::ImageNode; using cobalt::render_tree::ResourceProvider; -using cobalt::render_tree::animations::NodeAnimationsMap; namespace cobalt { namespace renderer { @@ -179,7 +180,7 @@ // Animate the ImageNode and pass in our callback function to be executed // upon render_tree animation. - NodeAnimationsMap::Builder animations; + AnimateNode::Builder animations; bool first_animate = true; animations.Add(test_node, base::Bind(&AnimateImageNode, &animate_has_started, @@ -194,9 +195,8 @@ // Submit the render tree and animation to the rendering pipeline for // rasterization (and the execution of our animation callback). - pipeline.Submit(Submission( - test_node, new NodeAnimationsMap(animations.Pass()), - base::Time::Now() - base::Time::UnixEpoch())); + pipeline.Submit(Submission(new AnimateNode(animations, test_node), + base::Time::Now() - base::Time::UnixEpoch())); // Wait for all events that we have planned to occur. animate_has_started.Wait();
diff --git a/src/cobalt/renderer/pipeline.cc b/src/cobalt/renderer/pipeline.cc index 66ea9a2..a5f38e7 100644 --- a/src/cobalt/renderer/pipeline.cc +++ b/src/cobalt/renderer/pipeline.cc
@@ -22,10 +22,11 @@ #include "base/file_util.h" #include "base/path_service.h" #include "cobalt/base/cobalt_paths.h" +#include "cobalt/base/polymorphic_downcast.h" #include "cobalt/render_tree/dump_render_tree_to_string.h" using cobalt::render_tree::Node; -using cobalt::render_tree::animations::NodeAnimationsMap; +using cobalt::render_tree::animations::AnimateNode; namespace cobalt { namespace renderer { @@ -134,10 +135,11 @@ void Pipeline::Submit(const Submission& render_tree_submission) { TRACE_EVENT0("cobalt::renderer", "Pipeline::Submit()"); + // Execute the actual set of the new render tree on the rasterizer tree. rasterizer_thread_.message_loop()->PostTask( FROM_HERE, base::Bind(&Pipeline::SetNewRenderTree, base::Unretained(this), - render_tree_submission)); + CollectAnimations(render_tree_submission))); } void Pipeline::Clear() { @@ -160,7 +162,7 @@ rasterizer_thread_.message_loop()->PostTask( FROM_HERE, base::Bind(&Pipeline::RasterizeToRGBAPixels, base::Unretained(this), - render_tree_submission, complete)); + CollectAnimations(render_tree_submission), complete)); return; } // Create a new target that is the same dimensions as the display target. @@ -231,8 +233,11 @@ TRACE_EVENT0("cobalt::renderer", "Pipeline::RasterizeSubmissionToRenderTarget()"); // Animate the render tree using the submitted animations. - scoped_refptr<Node> animated_render_tree = submission.animations->Apply( - submission.render_tree, submission.time_offset); + render_tree::animations::AnimateNode* animate_node = + base::polymorphic_downcast<render_tree::animations::AnimateNode*>( + submission.render_tree.get()); + scoped_refptr<Node> animated_render_tree = + animate_node->Apply(submission.time_offset); // Rasterize the animated render tree. rasterizer_->Submit(animated_render_tree, render_target); @@ -311,8 +316,11 @@ Submission submission = submission_queue_->GetCurrentSubmission(base::TimeTicks::Now()); - scoped_refptr<Node> animated_render_tree = submission.animations->Apply( - submission.render_tree, submission.time_offset); + render_tree::animations::AnimateNode* animate_node = + base::polymorphic_downcast<render_tree::animations::AnimateNode*>( + submission.render_tree.get()); + scoped_refptr<Node> animated_render_tree = + animate_node->Apply(submission.time_offset); std::string tree_dump = render_tree::DumpRenderTreeToString(animated_render_tree); @@ -330,5 +338,16 @@ } #endif // #if defined(ENABLE_DEBUG_CONSOLE) +Submission Pipeline::CollectAnimations( + const Submission& render_tree_submission) { + // Constructing an AnimateNode will result in the tree being traversed to + // collect all sub-AnimateNodes into the new one, in order to maintain the + // invariant that a sub-tree of an AnimateNode has no AnimateNodes. + Submission collected_submission = render_tree_submission; + collected_submission.render_tree = new render_tree::animations::AnimateNode( + render_tree_submission.render_tree); + return collected_submission; +} + } // namespace renderer } // namespace cobalt
diff --git a/src/cobalt/renderer/pipeline.h b/src/cobalt/renderer/pipeline.h index 98f3f1c..ad05b29 100644 --- a/src/cobalt/renderer/pipeline.h +++ b/src/cobalt/renderer/pipeline.h
@@ -27,7 +27,7 @@ #include "base/threading/thread_checker.h" #include "base/timer.h" #include "cobalt/base/c_val_time_interval_timer.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/renderer/backend/graphics_context.h" #include "cobalt/renderer/rasterizer/rasterizer.h" @@ -125,6 +125,13 @@ void OnDumpCurrentRenderTree(const std::string&); #endif // defined(ENABLE_DEBUG_CONSOLE) + // Render trees may contain a number of AnimateNodes (or none). In order + // to optimize for applying the animations on the rasterizer thread, this + // function searches the tree for AnimateNodes and collects all of their + // information into a single AnimateNode at the root of the returned + // render tree. + Submission CollectAnimations(const Submission& render_tree_submission); + base::WaitableEvent rasterizer_created_event_; // The render_target that all submitted render trees will be rasterized to.
diff --git a/src/cobalt/renderer/rasterizer/benchmark.cc b/src/cobalt/renderer/rasterizer/benchmark.cc index aefb362..097d0bf 100644 --- a/src/cobalt/renderer/rasterizer/benchmark.cc +++ b/src/cobalt/renderer/rasterizer/benchmark.cc
@@ -14,6 +14,7 @@ * limitations under the License. */ +#include "cobalt/base/polymorphic_downcast.h" #include "cobalt/math/size.h" #include "cobalt/renderer/backend/default_graphics_system.h" #include "cobalt/renderer/backend/graphics_context.h" @@ -28,19 +29,20 @@ using cobalt::math::Size; using cobalt::math::SizeF; using cobalt::render_tree::AlphaFormat; +using cobalt::render_tree::animations::AnimateNode; using cobalt::render_tree::ImageData; +using cobalt::render_tree::Node; using cobalt::render_tree::PixelFormat; using cobalt::render_tree::ResourceProvider; -using cobalt::renderer::rasterizer::Rasterizer; -using cobalt::renderer::RendererModule; using cobalt::renderer::backend::Display; using cobalt::renderer::backend::GraphicsContext; using cobalt::renderer::backend::GraphicsSystem; using cobalt::renderer::backend::RenderTarget; using cobalt::renderer::backend::SurfaceInfo; +using cobalt::renderer::rasterizer::Rasterizer; +using cobalt::renderer::RendererModule; using cobalt::renderer::test::scenes::AddBlankBackgroundToScene; using cobalt::renderer::test::scenes::CreateAllScenesCombinedScene; -using cobalt::renderer::test::scenes::RenderTreeWithAnimations; using cobalt::system_window::SystemWindow; namespace { @@ -63,7 +65,7 @@ kOutputSurfaceTypeOffscreen, }; -typedef base::Callback<RenderTreeWithAnimations( +typedef base::Callback<scoped_refptr<Node>( ResourceProvider*, const SizeF&, base::TimeDelta)> SceneCreateFunction; // RunRenderTreeSceneBenchmark serves as a framework for render tree scene @@ -105,15 +107,16 @@ DLOG(FATAL) << "Unknown output surface type."; } - RenderTreeWithAnimations scene = + scoped_refptr<Node> scene = scene_create_function.Run(rasterizer->GetResourceProvider(), test_surface->GetSize(), base::TimeDelta()); const int kRenderIterationCount = 100; const float kFixedTimeStepInSecondsPerFrame = 0.016f; for (int i = 0; i < kRenderIterationCount; ++i) { - scoped_refptr<cobalt::render_tree::Node> animated = scene.animations->Apply( - scene.render_tree, + AnimateNode* animate_node = + base::polymorphic_downcast<AnimateNode*>(scene.get()); + scoped_refptr<Node> animated = animate_node->Apply( base::TimeDelta::FromSecondsD(i * kFixedTimeStepInSecondsPerFrame)); // Submit the render tree to be rendered. @@ -133,7 +136,7 @@ #define RENDER_TREE_BUILDER_BENCHMARK(test_name) \ TRACE_EVENT_BENCHMARK5( \ test_name, "BuildRenderTree", cobalt::trace_event::IN_SCOPE_DURATION, \ - "NodeAnimationsMap::Apply()", cobalt::trace_event::IN_SCOPE_DURATION, \ + "AnimateNode::Apply()", cobalt::trace_event::IN_SCOPE_DURATION, \ "Rasterizer::Submit()", cobalt::trace_event::FLOW_DURATION, \ "Rasterizer::Submit()", cobalt::trace_event::TIME_BETWEEN_EVENT_STARTS, \ "VisitRenderTree", cobalt::trace_event::IN_SCOPE_DURATION)
diff --git a/src/cobalt/renderer/rasterizer/blitter/hardware_rasterizer.cc b/src/cobalt/renderer/rasterizer/blitter/hardware_rasterizer.cc index 2f73a29..2868926 100644 --- a/src/cobalt/renderer/rasterizer/blitter/hardware_rasterizer.cc +++ b/src/cobalt/renderer/rasterizer/blitter/hardware_rasterizer.cc
@@ -38,6 +38,7 @@ class HardwareRasterizer::Impl { public: explicit Impl(backend::GraphicsContext* graphics_context, + int scratch_surface_size_in_bytes, int surface_cache_size_in_bytes); ~Impl(); @@ -57,16 +58,21 @@ int64 submit_count_; + ScratchSurfaceCache scratch_surface_cache_; base::optional<SurfaceCacheDelegate> surface_cache_delegate_; base::optional<common::SurfaceCache> surface_cache_; }; HardwareRasterizer::Impl::Impl(backend::GraphicsContext* graphics_context, + int scratch_surface_size_in_bytes, int surface_cache_size_in_bytes) : context_(base::polymorphic_downcast<backend::GraphicsContextBlitter*>( graphics_context)), software_rasterizer_(0), - submit_count_(0) { + submit_count_(0), + scratch_surface_cache_(context_->GetSbBlitterDevice(), + context_->GetSbBlitterContext(), + scratch_surface_size_in_bytes) { resource_provider_ = scoped_ptr<render_tree::ResourceProvider>( new ResourceProvider(context_->GetSbBlitterDevice(), software_rasterizer_.GetResourceProvider())); @@ -126,7 +132,7 @@ RenderState(render_target_blitter->GetSbRenderTarget(), Transform(), BoundsStack(context_->GetSbBlitterContext(), math::Rect(render_target_blitter->GetSize()))), - &software_rasterizer_, + &software_rasterizer_, &scratch_surface_cache_, surface_cache_delegate_ ? &surface_cache_delegate_.value() : NULL, surface_cache_ ? &surface_cache_.value() : NULL); render_tree->Accept(&visitor); @@ -144,8 +150,10 @@ } HardwareRasterizer::HardwareRasterizer( - backend::GraphicsContext* graphics_context, int surface_cache_size_in_bytes) - : impl_(new Impl(graphics_context, surface_cache_size_in_bytes)) {} + backend::GraphicsContext* graphics_context, + int scratch_surface_size_in_bytes, int surface_cache_size_in_bytes) + : impl_(new Impl(graphics_context, scratch_surface_size_in_bytes, + surface_cache_size_in_bytes)) {} HardwareRasterizer::~HardwareRasterizer() {}
diff --git a/src/cobalt/renderer/rasterizer/blitter/hardware_rasterizer.h b/src/cobalt/renderer/rasterizer/blitter/hardware_rasterizer.h index 7562d32..abf4d4e 100644 --- a/src/cobalt/renderer/rasterizer/blitter/hardware_rasterizer.h +++ b/src/cobalt/renderer/rasterizer/blitter/hardware_rasterizer.h
@@ -21,6 +21,7 @@ #include "cobalt/render_tree/resource_provider.h" #include "cobalt/renderer/backend/graphics_context.h" #include "cobalt/renderer/backend/render_target.h" +#include "cobalt/renderer/rasterizer/blitter/scratch_surface_cache.h" #include "cobalt/renderer/rasterizer/rasterizer.h" #if SB_HAS(BLITTER) @@ -37,6 +38,7 @@ class HardwareRasterizer : public Rasterizer { public: explicit HardwareRasterizer(backend::GraphicsContext* graphics_context, + int scratch_surface_size_in_bytes, int surface_cache_size_in_bytes); virtual ~HardwareRasterizer();
diff --git a/src/cobalt/renderer/rasterizer/blitter/rasterizer.gyp b/src/cobalt/renderer/rasterizer/blitter/rasterizer.gyp index 0f7f474..8c75fd1 100644 --- a/src/cobalt/renderer/rasterizer/blitter/rasterizer.gyp +++ b/src/cobalt/renderer/rasterizer/blitter/rasterizer.gyp
@@ -45,6 +45,7 @@ 'render_tree_blitter_conversions.cc', 'render_tree_node_visitor.cc', 'resource_provider.cc', + 'scratch_surface_cache.cc', 'surface_cache_delegate.cc', ],
diff --git a/src/cobalt/renderer/rasterizer/blitter/render_tree_node_visitor.cc b/src/cobalt/renderer/rasterizer/blitter/render_tree_node_visitor.cc index 9af227b..3f37aeb 100644 --- a/src/cobalt/renderer/rasterizer/blitter/render_tree_node_visitor.cc +++ b/src/cobalt/renderer/rasterizer/blitter/render_tree_node_visitor.cc
@@ -54,12 +54,14 @@ SbBlitterDevice device, SbBlitterContext context, const RenderState& render_state, skia::SoftwareRasterizer* software_rasterizer, + ScratchSurfaceCache* scratch_surface_cache, SurfaceCacheDelegate* surface_cache_delegate, common::SurfaceCache* surface_cache) : software_rasterizer_(software_rasterizer), device_(device), context_(context), render_state_(render_state), + scratch_surface_cache_(scratch_surface_cache), surface_cache_delegate_(surface_cache_delegate), surface_cache_(surface_cache) { DCHECK_EQ(surface_cache_delegate_ == NULL, surface_cache_ == NULL); @@ -135,16 +137,16 @@ // Render our source subtree to an offscreen surface, and then we will // re-render it to our main render target with an alpha value applied to it. - OffscreenRender offscreen_render = RenderToOffscreenSurface(source); - if (!SbBlitterIsSurfaceValid(offscreen_render.surface)) { + scoped_ptr<OffscreenRender> offscreen_render = + RenderToOffscreenSurface(source); + if (!offscreen_render) { // This can happen if the output area of the source node is 0, in which // case we're trivially done. return; } - SbBlitterSurfaceInfo offscreen_surface_info; - CHECK(SbBlitterGetSurfaceInfo(offscreen_render.surface, - &offscreen_surface_info)); + SbBlitterSurface offscreen_surface = + offscreen_render->scratch_surface->GetSurface(); // Now blit our offscreen surface to our main render target with opacity // applied. @@ -154,15 +156,10 @@ context_, SbBlitterColorFromRGBA(255, 255, 255, static_cast<int>(255 * opacity))); SbBlitterBlitRectToRect( - context_, offscreen_render.surface, - SbBlitterMakeRect(0, 0, offscreen_surface_info.width, - offscreen_surface_info.height), - SbBlitterMakeRect( - offscreen_render.position.x(), offscreen_render.position.y(), - offscreen_surface_info.width, offscreen_surface_info.height)); - - // Destroy our temporary offscreeen surface now that we are done with it. - SbBlitterDestroySurface(offscreen_render.surface); + context_, offscreen_surface, + SbBlitterMakeRect(0, 0, offscreen_render->destination_rect.width(), + offscreen_render->destination_rect.height()), + RectFToBlitterRect(offscreen_render->destination_rect)); } } @@ -456,7 +453,7 @@ SbBlitterDestroySurface(surface); } -RenderTreeNodeVisitor::OffscreenRender +scoped_ptr<RenderTreeNodeVisitor::OffscreenRender> RenderTreeNodeVisitor::RenderToOffscreenSurface(render_tree::Node* node) { common::OffscreenRenderCoordinateMapping coord_mapping = common::GetOffscreenRenderCoordinateMapping( @@ -464,9 +461,7 @@ render_state_.bounds_stack.Top()); if (coord_mapping.output_bounds.IsEmpty()) { // There's nothing to render if the bounds are 0. - OffscreenRender ret; - ret.surface = kSbBlitterInvalidSurface; - return ret; + return scoped_ptr<OffscreenRender>(); } DCHECK_GE(0.001f, std::abs(1.0f - render_state_.transform.scale().x() * @@ -475,28 +470,22 @@ render_state_.transform.scale().y() * coord_mapping.output_post_scale.y())); - SbBlitterSurface surface = SbBlitterCreateRenderTargetSurface( - device_, coord_mapping.output_bounds.width(), - coord_mapping.output_bounds.height(), kSbBlitterSurfaceFormatRGBA8); + scoped_ptr<CachedScratchSurface> scratch_surface(new CachedScratchSurface( + scratch_surface_cache_, coord_mapping.output_bounds.size())); + SbBlitterSurface surface = scratch_surface->GetSurface(); SbBlitterRenderTarget render_target = SbBlitterGetRenderTargetFromSurface(surface); SbBlitterSetRenderTarget(context_, render_target); - // Clear the background to fully transparent before we begin rendering the - // subtree. - SbBlitterSetBlending(context_, false); - SbBlitterSetColor(context_, SbBlitterColorFromRGBA(0, 0, 0, 0)); - SbBlitterFillRect( - context_, RectToBlitterRect(Rect(coord_mapping.output_bounds.size()))); - // Render to the sub-surface. RenderTreeNodeVisitor sub_visitor( device_, context_, RenderState( render_target, Transform(coord_mapping.sub_render_transform), BoundsStack(context_, Rect(coord_mapping.output_bounds.size()))), - software_rasterizer_, surface_cache_delegate_, surface_cache_); + software_rasterizer_, scratch_surface_cache_, surface_cache_delegate_, + surface_cache_); node->Accept(&sub_visitor); // Restore our original render target. @@ -509,11 +498,12 @@ coord_mapping.output_pre_translate + render_state_.transform.translate(); - OffscreenRender ret; - ret.position.SetPoint(output_point.x(), output_point.y()); - ret.surface = surface; + scoped_ptr<OffscreenRender> ret(new OffscreenRender()); + ret->destination_rect = + math::RectF(output_point, coord_mapping.output_bounds.size()); + ret->scratch_surface = scratch_surface.Pass(); - return ret; + return ret.Pass(); } } // namespace blitter
diff --git a/src/cobalt/renderer/rasterizer/blitter/render_tree_node_visitor.h b/src/cobalt/renderer/rasterizer/blitter/render_tree_node_visitor.h index 3370321..4677308 100644 --- a/src/cobalt/renderer/rasterizer/blitter/render_tree_node_visitor.h +++ b/src/cobalt/renderer/rasterizer/blitter/render_tree_node_visitor.h
@@ -33,6 +33,7 @@ #include "cobalt/render_tree/rect_shadow_node.h" #include "cobalt/render_tree/text_node.h" #include "cobalt/renderer/rasterizer/blitter/render_state.h" +#include "cobalt/renderer/rasterizer/blitter/scratch_surface_cache.h" #include "cobalt/renderer/rasterizer/blitter/surface_cache_delegate.h" #include "cobalt/renderer/rasterizer/common/surface_cache.h" #include "cobalt/renderer/rasterizer/skia/software_rasterizer.h" @@ -42,6 +43,13 @@ #if SB_HAS(BLITTER) namespace cobalt { + +namespace render_tree { +namespace animations { +class AnimateNode; +} // namespace animations +} // namespace render_tree + namespace renderer { namespace rasterizer { namespace blitter { @@ -55,9 +63,13 @@ RenderTreeNodeVisitor(SbBlitterDevice device, SbBlitterContext context, const RenderState& render_state, skia::SoftwareRasterizer* software_rasterizer, + ScratchSurfaceCache* scratch_surface_cache, SurfaceCacheDelegate* surface_cache_delegate, common::SurfaceCache* surface_cache); + void Visit(render_tree::animations::AnimateNode* animate_node) OVERRIDE { + NOTREACHED(); + } void Visit(render_tree::CompositionNode* composition_node) OVERRIDE; void Visit(render_tree::FilterNode* filter_node) OVERRIDE; void Visit(render_tree::ImageNode* image_node) OVERRIDE; @@ -82,10 +94,10 @@ // Uses a Blitter API sub-visitor to render the provided render tree to a // offscreen SbBlitterSurface which is then returned. struct OffscreenRender { - math::Point position; - SbBlitterSurface surface; + math::RectF destination_rect; + scoped_ptr<CachedScratchSurface> scratch_surface; }; - OffscreenRender RenderToOffscreenSurface(render_tree::Node* node); + scoped_ptr<OffscreenRender> RenderToOffscreenSurface(render_tree::Node* node); // We maintain an instance of a software skia rasterizer which is used to // render anything that we cannot render via the Blitter API directly. @@ -97,6 +109,10 @@ // Keeps track of our current render target, transform and clip stack. RenderState render_state_; + // Manager for scratch surfaces used for intermediate rendering during render + // tree traversal. + ScratchSurfaceCache* scratch_surface_cache_; + SurfaceCacheDelegate* surface_cache_delegate_; common::SurfaceCache* surface_cache_; base::optional<SurfaceCacheDelegate::ScopedContext>
diff --git a/src/cobalt/renderer/rasterizer/blitter/scratch_surface_cache.cc b/src/cobalt/renderer/rasterizer/blitter/scratch_surface_cache.cc new file mode 100644 index 0000000..d9b3790 --- /dev/null +++ b/src/cobalt/renderer/rasterizer/blitter/scratch_surface_cache.cc
@@ -0,0 +1,93 @@ +/* + * 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/renderer/rasterizer/blitter/scratch_surface_cache.h" + +#include "cobalt/base/polymorphic_downcast.h" +#include "starboard/blitter.h" + +#if SB_HAS(BLITTER) + +namespace cobalt { +namespace renderer { +namespace rasterizer { +namespace blitter { + +namespace { + +class BlitterSurface : public common::ScratchSurfaceCache::Surface { + public: + BlitterSurface(SbBlitterSurface surface, const math::Size& size) + : surface_(surface), size_(size) {} + ~BlitterSurface() OVERRIDE { SbBlitterDestroySurface(surface_); } + + math::Size GetSize() const OVERRIDE { return size_; } + + SbBlitterSurface blitter_surface() { return surface_; } + + private: + SbBlitterSurface surface_; + math::Size size_; +}; +} // namespace + +ScratchSurfaceCache::ScratchSurfaceCache(SbBlitterDevice device, + SbBlitterContext context, + int cache_capacity_in_bytes) + : delegate_(device, context), cache_(&delegate_, cache_capacity_in_bytes) {} + +ScratchSurfaceCache::Delegate::Delegate(SbBlitterDevice device, + SbBlitterContext context) + : device_(device), context_(context) {} + +common::ScratchSurfaceCache::Surface* +ScratchSurfaceCache::Delegate::CreateSurface(const math::Size& size) { + return new BlitterSurface( + SbBlitterCreateRenderTargetSurface(device_, size.width(), size.height(), + kSbBlitterSurfaceFormatRGBA8), + size); +} + +void ScratchSurfaceCache::Delegate::DestroySurface( + common::ScratchSurfaceCache::Surface* surface) { + delete surface; +} + +void ScratchSurfaceCache::Delegate::PrepareForUse( + common::ScratchSurfaceCache::Surface* surface, const math::Size& area) { + SbBlitterSurface blitter_surface = + base::polymorphic_downcast<BlitterSurface*>(surface)->blitter_surface(); + + SbBlitterSetRenderTarget( + context_, SbBlitterGetRenderTargetFromSurface(blitter_surface)); + SbBlitterSetBlending(context_, false); + SbBlitterSetColor(context_, SbBlitterColorFromRGBA(0, 0, 0, 0)); + SbBlitterFillRect(context_, + SbBlitterMakeRect(0, 0, area.width(), area.height())); +} + +SbBlitterSurface CachedScratchSurface::GetSurface() { + return base::polymorphic_downcast<BlitterSurface*>( + common_scratch_surface_.GetSurface()) + ->blitter_surface(); +} + +} // namespace blitter +} // namespace rasterizer +} // namespace renderer +} // namespace cobalt + +#endif // SB_HAS(BLITTER)
diff --git a/src/cobalt/renderer/rasterizer/blitter/scratch_surface_cache.h b/src/cobalt/renderer/rasterizer/blitter/scratch_surface_cache.h new file mode 100644 index 0000000..675a498 --- /dev/null +++ b/src/cobalt/renderer/rasterizer/blitter/scratch_surface_cache.h
@@ -0,0 +1,89 @@ +/* + * 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_RENDERER_RASTERIZER_BLITTER_SCRATCH_SURFACE_CACHE_H_ +#define COBALT_RENDERER_RASTERIZER_BLITTER_SCRATCH_SURFACE_CACHE_H_ + +#include "cobalt/math/size.h" +#include "cobalt/renderer/rasterizer/common/scratch_surface_cache.h" +#include "starboard/blitter.h" + +#if SB_HAS(BLITTER) + +namespace cobalt { +namespace renderer { +namespace rasterizer { +namespace blitter { + +// We define a blitter::ScratchSurfaceCache class here that decorates +// common::ScratchSurfaceCache by customizing it to be Blitter API specific. +// A Blitter API renderer can use this class to request temporary scratch +// SbBlitterSurfaces that can be automatically re-used over the course of a +// frame. CachedScratchSurface objects must be created in order to actually +// interact with ScratchSurfaceCache. +class ScratchSurfaceCache { + public: + // |device| specifies the |device| from which surfaces should be allocated + // from and |context| specifies which context to use when draw commands need + // to be issued (e.g. to clear a surface so it is ready for use). + ScratchSurfaceCache(SbBlitterDevice device, SbBlitterContext context, + int cache_capacity_in_bytes); + + private: + class Delegate : public common::ScratchSurfaceCache::Delegate { + public: + Delegate(SbBlitterDevice device, SbBlitterContext context); + + common::ScratchSurfaceCache::Surface* CreateSurface( + const math::Size& size) OVERRIDE; + void DestroySurface(common::ScratchSurfaceCache::Surface* surface) OVERRIDE; + void PrepareForUse(common::ScratchSurfaceCache::Surface* surface, + const math::Size& area) OVERRIDE; + + private: + SbBlitterDevice device_; + SbBlitterContext context_; + }; + + Delegate delegate_; + common::ScratchSurfaceCache cache_; + + friend class CachedScratchSurface; +}; + +// This class acts as the interface to ScratchSurfaceCache. It does so by +// decorating common::CachedScratchSurface and adding methods to obtain +// a reference to the Blitter API-specific SbBlitterSurface object. +class CachedScratchSurface { + public: + CachedScratchSurface(ScratchSurfaceCache* cache, const math::Size& size) + : common_scratch_surface_(&cache->cache_, size) {} + + // Returns a pointer to the Blitter surface. + SbBlitterSurface GetSurface(); + + private: + common::CachedScratchSurface common_scratch_surface_; +}; + +} // namespace blitter +} // namespace rasterizer +} // namespace renderer +} // namespace cobalt + +#endif // SB_HAS(BLITTER) + +#endif // COBALT_RENDERER_RASTERIZER_BLITTER_SCRATCH_SURFACE_CACHE_H_
diff --git a/src/cobalt/renderer/rasterizer/common/common.gyp b/src/cobalt/renderer/rasterizer/common/common.gyp index b03b34a..3db2828 100644 --- a/src/cobalt/renderer/rasterizer/common/common.gyp +++ b/src/cobalt/renderer/rasterizer/common/common.gyp
@@ -20,8 +20,13 @@ 'sources': [ 'offscreen_render_coordinate_mapping.cc', + 'offscreen_render_coordinate_mapping.h', + 'scratch_surface_cache.cc', + 'scratch_surface_cache.h', 'streaming_best_fit_line.cc', + 'streaming_best_fit_line.h', 'surface_cache.cc', + 'surface_cache.h', ], 'dependencies': [
diff --git a/src/cobalt/renderer/rasterizer/common/scratch_surface_cache.cc b/src/cobalt/renderer/rasterizer/common/scratch_surface_cache.cc new file mode 100644 index 0000000..dac975b --- /dev/null +++ b/src/cobalt/renderer/rasterizer/common/scratch_surface_cache.cc
@@ -0,0 +1,180 @@ +/* + * 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/renderer/rasterizer/common/scratch_surface_cache.h" + +#include <limits> + +#include "base/debug/trace_event.h" + +namespace cobalt { +namespace renderer { +namespace rasterizer { +namespace common { + +namespace { + +// Approximate the memory usage of a given surface size. +size_t ApproximateSurfaceMemory(const math::Size& size) { + // Here we assume that we use 4 bytes per pixel. + return size.width() * size.height() * 4; +} + +} // namespace + +ScratchSurfaceCache::ScratchSurfaceCache(Delegate* delegate, + int cache_capacity_in_bytes) + : delegate_(delegate), + cache_capacity_in_bytes_(cache_capacity_in_bytes), + surface_memory_(0) {} + +ScratchSurfaceCache::~ScratchSurfaceCache() { + DCHECK(surface_stack_.empty()); + for (std::vector<Surface*>::iterator iter = unused_surfaces_.begin(); + iter != unused_surfaces_.end(); ++iter) { + delegate_->DestroySurface(*iter); + } +} + +ScratchSurfaceCache::Surface* ScratchSurfaceCache::AcquireScratchSurface( + const math::Size& size) { + TRACE_EVENT2("cobalt::renderer", + "ScratchSurfaceCache::AcquireScratchSurface()", "width", + size.width(), "height", size.height()); + + // First check if we can find a suitable surface in our cache that is at + // least the size requested. + Surface* surface = FindBestCachedSurface(size); + + // If we didn't have any suitable surfaces in our cache, create a new one. + if (!surface) { + // Increase our total memory used on surfaces, and then initiate a purge + // to reduce memory to below our cache limit, if necessary. + surface_memory_ += ApproximateSurfaceMemory(size); + Purge(); + + // Create the surface. + surface = delegate_->CreateSurface(size); + + if (!surface) { + // We were unable to allocate a scratch surface, either because we are + // low on memory or because the requested surface has large dimensions. + // Return null. + surface_memory_ -= ApproximateSurfaceMemory(size); + return NULL; + } + } + + DCHECK(surface); + + // Track that we have handed out this surface. + surface_stack_.push_back(surface); + + delegate_->PrepareForUse(surface, size); + + return surface; +} + +void ScratchSurfaceCache::ReleaseScratchSurface(Surface* surface) { + TRACE_EVENT2("cobalt::renderer", + "ScratchSurfaceCache::ReleaseScratchSurface()", "width", + surface->GetSize().width(), "height", + surface->GetSize().height()); + + DCHECK_EQ(surface_stack_.back(), surface); + surface_stack_.pop_back(); + + // Add this surface to the end (where most recently used surfaces go) of the + // unused surfaces list, so that it can be returned by later calls to acquire + // a surface. + unused_surfaces_.push_back(surface); +} + +namespace { + +float GetMatchScoreForSurfaceAndSize(ScratchSurfaceCache::Surface* surface, + const math::Size& size) { + math::Size surface_size = surface->GetSize(); + + // We use the negated sum of the squared differences between the requested + // width/height and the surface width/height as the score. + // This promotes returning the smallest surface possible that has a similar + // ratio. + int width_diff = surface_size.width() - size.width(); + int height_diff = surface_size.height() - size.height(); + + return -width_diff * width_diff - height_diff * height_diff; +} + +} // namespace + +ScratchSurfaceCache::Surface* ScratchSurfaceCache::FindBestCachedSurface( + const math::Size& size) { + // Iterate through all cached surfaces to find the one that is the best match + // for the given size. The function GetMatchScoreForSurfaceAndSize() is + // responsible for assigning a score to a Surface/math::Size pair. + float max_surface_score = -std::numeric_limits<float>::infinity(); + std::vector<Surface*>::iterator max_iter = unused_surfaces_.end(); + for (std::vector<Surface*>::iterator iter = unused_surfaces_.begin(); + iter != unused_surfaces_.end(); ++iter) { + Surface* current_surface = *iter; + math::Size surface_size = current_surface->GetSize(); + if (surface_size.width() >= size.width() && + surface_size.height() >= size.height()) { + float surface_score = + GetMatchScoreForSurfaceAndSize(current_surface, size); + + if (surface_score > max_surface_score) { + max_surface_score = surface_score; + max_iter = iter; + } + } + } + + // If any of the cached unused surfaces had at least the specified + // width/height, return the one that had the highest score. + if (max_iter != unused_surfaces_.end()) { + Surface* surface = *max_iter; + // Remove this surface from the list of unused surfaces. + unused_surfaces_.erase(max_iter); + // Return the cached surface. + return surface; + } else { + // Otherwise return NULL to indicate that we do not have any suitable cached + // surfaces. + return NULL; + } +} + +void ScratchSurfaceCache::Purge() { + // Delete surfaces from the front (least recently used) of |unused_surfaces_| + // until we have deleted all surfaces or lowered our memory usage to under + // |cache_capacity_in_bytes_|. + while (!unused_surfaces_.empty() && + surface_memory_ > cache_capacity_in_bytes_) { + Surface* to_free = unused_surfaces_.front(); + math::Size surface_size = to_free->GetSize(); + surface_memory_ -= ApproximateSurfaceMemory( + math::Size(surface_size.width(), surface_size.height())); + delegate_->DestroySurface(to_free); + unused_surfaces_.erase(unused_surfaces_.begin()); + } +} + +} // namespace common +} // namespace rasterizer +} // namespace renderer +} // namespace cobalt
diff --git a/src/cobalt/renderer/rasterizer/common/scratch_surface_cache.h b/src/cobalt/renderer/rasterizer/common/scratch_surface_cache.h new file mode 100644 index 0000000..a482ffc --- /dev/null +++ b/src/cobalt/renderer/rasterizer/common/scratch_surface_cache.h
@@ -0,0 +1,130 @@ +/* + * 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_RENDERER_RASTERIZER_COMMON_SCRATCH_SURFACE_CACHE_H_ +#define COBALT_RENDERER_RASTERIZER_COMMON_SCRATCH_SURFACE_CACHE_H_ + +#include <vector> + +#include "base/callback.h" +#include "base/logging.h" +#include "cobalt/math/size.h" + +namespace cobalt { +namespace renderer { +namespace rasterizer { +namespace common { + +// The ScratchSurfaceCache manages a set of platform-specific surface objects +// that can be used for offscreen rendering (e.g. by a RenderTreeNodeVisitor). +// In order to acquire surfaces from ScratchSurfaceCache, one should construct +// a CachedScratchSurface object, from which they can get a pointer to the +// Surface object. +// It is unique because it caters to RenderTreeNodeVisitor's scratch +// surface allocation pattern. In particular, we don't mind handing out very +// large scratch surfaces when very small surfaces are requested, because +// typically only one surface is ever needed at a time. When multiple surfaces +// are necessary, the subsequent ones tend to be smaller than the previous +// (because rendering is now happening within the previous ones), and so handing +// out textures in large to small order makes sense. +class ScratchSurfaceCache { + public: + class Surface { + public: + virtual ~Surface() {} + virtual math::Size GetSize() const = 0; + }; + class Delegate { + public: + virtual Surface* CreateSurface(const math::Size& size) = 0; + virtual void DestroySurface(Surface* surface) = 0; + virtual void PrepareForUse(Surface* surface, const math::Size& area) = 0; + }; + + ScratchSurfaceCache(Delegate* delegate, int cache_capacity_in_bytes); + ~ScratchSurfaceCache(); + + private: + // Acquire (either via cache lookup or by creation if that fails) a scratch + // surface. + Surface* AcquireScratchSurface(const math::Size& size); + void ReleaseScratchSurface(Surface* surface); + + // Searches through |unused_surfaces_| for one the one that best matches the + // requested size, among all those cached surfaces that have at least the + // requested size. + Surface* FindBestCachedSurface(const math::Size& size); + + // Removes elements from the cache until we are below the cache limit. + void Purge(); + + // Allocate a new Surface and return it. + Surface* CreateScratchSurface(const math::Size& size); + + // Implementation-specific details about how to create/destroy surfaces. + Delegate* delegate_; + + // The maximum number of surface bytes that can be stored in the cache. + int cache_capacity_in_bytes_; + + // We keep track of all surfaces we've handed out using |surface_stack_|. + // This is mostly for debug checks to verify that surfaces returned to us + // actually did come from us, and that they are returned in the expected + // order. + std::vector<Surface*> surface_stack_; + + // |unused_surfaces_| is the heart of the cache, as it stores the surfaces + // that are unused but allocated and available to be handed out upon request. + // Most recently used surfaces are found at the end of this vector. + std::vector<Surface*> unused_surfaces_; + + // Tracks how much total memory we've allocated towards surfaces. + size_t surface_memory_; + + friend class CachedScratchSurface; +}; + +// The primary interface to ScratchSurfaceCache is through CachedScratchSurface +// objects. These effectively scope the acquisition of a cached surface, RAII +// style. +class CachedScratchSurface { + public: + CachedScratchSurface(ScratchSurfaceCache* cache, const math::Size& size) + : cache_(cache) { + surface_ = cache_->AcquireScratchSurface(size); + } + + ~CachedScratchSurface() { + if (surface_) { + cache_->ReleaseScratchSurface(surface_); + } + } + + // Returns a pointer to the platform-specific surface. The platform can then + // downcast to the expected surface type. + ScratchSurfaceCache::Surface* GetSurface() { return surface_; } + + private: + ScratchSurfaceCache* cache_; + ScratchSurfaceCache::Surface* surface_; +}; + +} // namespace common +} // namespace rasterizer +} // namespace renderer +} // namespace cobalt + +#endif // COBALT_RENDERER_RASTERIZER_COMMON_SCRATCH_SURFACE_CACHE_H_
diff --git a/src/cobalt/renderer/rasterizer/rasterizer_benchmark.cc b/src/cobalt/renderer/rasterizer/rasterizer_benchmark.cc index 943cb95..ca2cc73 100644 --- a/src/cobalt/renderer/rasterizer/rasterizer_benchmark.cc +++ b/src/cobalt/renderer/rasterizer/rasterizer_benchmark.cc
@@ -134,14 +134,13 @@ // Setup a quick macro so that we can measure the same events for each // render tree builder benchmark. -#define RENDER_TREE_BUILDER_BENCHMARK(test_name)\ -TRACE_EVENT_BENCHMARK5(\ - test_name, \ - "BuildRenderTree", cobalt::trace_event::IN_SCOPE_DURATION, \ - "NodeAnimationsMap::Apply()", cobalt::trace_event::IN_SCOPE_DURATION, \ - "Rasterizer::Submit()", cobalt::trace_event::FLOW_DURATION, \ - "Rasterizer::Submit()", cobalt::trace_event::TIME_BETWEEN_EVENT_STARTS, \ - "VisitRenderTree", cobalt::trace_event::IN_SCOPE_DURATION) +#define RENDER_TREE_BUILDER_BENCHMARK(test_name) \ + TRACE_EVENT_BENCHMARK5( \ + test_name, "BuildRenderTree", cobalt::trace_event::IN_SCOPE_DURATION, \ + "AnimateNode::Apply()", cobalt::trace_event::IN_SCOPE_DURATION, \ + "Rasterizer::Submit()", cobalt::trace_event::FLOW_DURATION, \ + "Rasterizer::Submit()", cobalt::trace_event::TIME_BETWEEN_EVENT_STARTS, \ + "VisitRenderTree", cobalt::trace_event::IN_SCOPE_DURATION) // A catch-all test that excercises every different render tree node at the // same time. This is the same render tree builder used by the renderer
diff --git a/src/cobalt/renderer/rasterizer/skia/render_tree_node_visitor.h b/src/cobalt/renderer/rasterizer/skia/render_tree_node_visitor.h index 74f4be2..b325107 100644 --- a/src/cobalt/renderer/rasterizer/skia/render_tree_node_visitor.h +++ b/src/cobalt/renderer/rasterizer/skia/render_tree_node_visitor.h
@@ -33,6 +33,13 @@ #include "third_party/skia/include/core/SkCanvas.h" namespace cobalt { + +namespace render_tree { +namespace animations { +class AnimateNode; +} // namespace animations +} // namespace render_tree + namespace renderer { namespace rasterizer { namespace skia { @@ -68,6 +75,9 @@ SurfaceCacheDelegate* surface_cache_delegate, common::SurfaceCache* surface_cache, Type visitor_type = kType_Normal); + void Visit(render_tree::animations::AnimateNode* animate_node) OVERRIDE { + NOTREACHED(); + } void Visit(render_tree::CompositionNode* composition_node) OVERRIDE; void Visit(render_tree::FilterNode* filter_node) OVERRIDE; void Visit(render_tree::ImageNode* image_node) OVERRIDE;
diff --git a/src/cobalt/renderer/rasterizer/skia/scratch_surface_cache.cc b/src/cobalt/renderer/rasterizer/skia/scratch_surface_cache.cc index 1b62b9c..409c787 100644 --- a/src/cobalt/renderer/rasterizer/skia/scratch_surface_cache.cc +++ b/src/cobalt/renderer/rasterizer/skia/scratch_surface_cache.cc
@@ -16,10 +16,7 @@ #include "cobalt/renderer/rasterizer/skia/scratch_surface_cache.h" -#include <limits> - -#include "base/debug/trace_event.h" - +#include "cobalt/base/polymorphic_downcast.h" #include "third_party/skia/include/core/SkCanvas.h" namespace cobalt { @@ -29,160 +26,68 @@ namespace { -// Approximate the memory usage of a given surface size. -size_t ApproximateSurfaceMemory(const math::Size& size) { - // Here we assume that we use 4 bytes per pixel. - return size.width() * size.height() * 4; -} +class SkiaSurface : public common::ScratchSurfaceCache::Surface { + public: + SkiaSurface(SkSurface* surface, const math::Size& size) + : surface_(surface), size_(size) {} + math::Size GetSize() const OVERRIDE { return size_; } + + SkSurface* sk_surface() { return surface_.get(); } + + private: + SkAutoTUnref<SkSurface> surface_; + math::Size size_; +}; } // namespace ScratchSurfaceCache::ScratchSurfaceCache( - const CreateSkSurfaceFunction& create_sk_surface_function, + CreateSkSurfaceFunction create_sk_surface_function, int cache_capacity_in_bytes) - : create_sk_surface_function_(create_sk_surface_function), - cache_capacity_in_bytes_(cache_capacity_in_bytes), - surface_memory_(0) {} + : delegate_(create_sk_surface_function), + cache_(&delegate_, cache_capacity_in_bytes) {} -ScratchSurfaceCache::~ScratchSurfaceCache() { - DCHECK(surface_stack_.empty()); - for (std::vector<SkSurface*>::iterator iter = unused_surfaces_.begin(); - iter != unused_surfaces_.end(); ++iter) { - (*iter)->unref(); - } +ScratchSurfaceCache::Delegate::Delegate( + CreateSkSurfaceFunction create_sk_surface_function) + : create_sk_surface_function_(create_sk_surface_function) {} + +common::ScratchSurfaceCache::Surface* +ScratchSurfaceCache::Delegate::CreateSurface(const math::Size& size) { + return new SkiaSurface(create_sk_surface_function_.Run(size), size); } -SkSurface* ScratchSurfaceCache::AcquireScratchSurface(const math::Size& size) { - TRACE_EVENT2("cobalt::renderer", - "ScratchSurfaceCache::AcquireScratchSurface()", "width", - size.width(), "height", size.height()); +void ScratchSurfaceCache::Delegate::DestroySurface( + common::ScratchSurfaceCache::Surface* surface) { + delete surface; +} - // First check if we can find a suitable surface in our cache that is at - // least the size requested. - SkSurface* surface = FindBestCachedSurface(size); +void ScratchSurfaceCache::Delegate::PrepareForUse( + common::ScratchSurfaceCache::Surface* surface, const math::Size& area) { + SkSurface* sk_surface = + base::polymorphic_downcast<SkiaSurface*>(surface)->sk_surface(); - // If we didn't have any suitable surfaces in our cache, create a new one. - if (!surface) { - // Increase our total memory used on surfaces, and then initiate a purge - // to reduce memory to below our cache limit, if necessary. - surface_memory_ += ApproximateSurfaceMemory(size); - Purge(); - - // Create the surface. - surface = create_sk_surface_function_.Run(size); - - if (!surface) { - // We were unable to allocate a scratch surface, either because we are - // low on memory or because the requested surface has large dimensions. - // Return null. - surface_memory_ -= ApproximateSurfaceMemory(size); - return NULL; - } - } - - DCHECK(surface); - - // Track that we have handed out this surface. - surface_stack_.push_back(surface); - - // Reset the surface's canvas settings such as transform matrix and clip. - SkCanvas* canvas = surface->getCanvas(); + // Reset the sk_surface's canvas settings such as transform matrix and clip. + SkCanvas* canvas = sk_surface->getCanvas(); canvas->restoreToCount(1); // Setup a save marker on the reset canvas so that we can restore this reset - // state when re-using the surface. + // state when re-using the sk_surface. canvas->save(); - // Setup a clip rect on the surface to the requested size. This can save - // us from drawing to pixels outside of the requested size, since the actual - // surface returned may be larger than the requested size. - canvas->clipRect(SkRect::MakeWH(size.width(), size.height()), + // Setup a clip rect on the sk_surface to the requested area. This can save + // us from drawing to pixels outside of the requested area, since the actual + // sk_surface returned may be larger than the requested area. + canvas->clipRect(SkRect::MakeWH(area.width(), area.height()), SkRegion::kReplace_Op); // Clear the draw area to RGBA(0, 0, 0, 0), as expected for a fresh scratch - // surface, before returning. + // sk_surface, before returning. canvas->drawARGB(0, 0, 0, 0, SkXfermode::kClear_Mode); - - return surface; } -void ScratchSurfaceCache::ReleaseScratchSurface(SkSurface* surface) { - TRACE_EVENT2("cobalt::renderer", - "ScratchSurfaceCache::ReleaseScratchSurface()", "width", - surface->width(), "height", surface->height()); - - DCHECK_EQ(surface_stack_.back(), surface); - surface_stack_.pop_back(); - - // Add this surface to the end (where most recently used surfaces go) of the - // unused surfaces list, so that it can be returned by later calls to acquire - // a surface. - unused_surfaces_.push_back(surface); -} - -namespace { - -float GetMatchScoreForSurfaceAndSize(SkSurface* surface, - const math::Size& size) { - // We use the negated sum of the squared differences between the requested - // width/height and the surface width/height as the score. - // This promotes returning the smallest surface possible that has a similar - // ratio. - int width_diff = surface->width() - size.width(); - int height_diff = surface->height() - size.height(); - - return -width_diff * width_diff - height_diff * height_diff; -} - -} // namespace - -SkSurface* ScratchSurfaceCache::FindBestCachedSurface(const math::Size& size) { - // Iterate through all cached surfaces to find the one that is the best match - // for the given size. The function GetMatchScoreForSurfaceAndSize() is - // responsible for assigning a score to a SkSurface/math::Size pair. - float max_surface_score = -std::numeric_limits<float>::infinity(); - std::vector<SkSurface*>::iterator max_iter = unused_surfaces_.end(); - for (std::vector<SkSurface*>::iterator iter = unused_surfaces_.begin(); - iter != unused_surfaces_.end(); ++iter) { - SkSurface* current_surface = *iter; - if (current_surface->width() >= size.width() && - current_surface->height() >= size.height()) { - float surface_score = - GetMatchScoreForSurfaceAndSize(current_surface, size); - - if (surface_score > max_surface_score) { - max_surface_score = surface_score; - max_iter = iter; - } - } - } - - // If any of the cached unused surfaces had at least the specified - // width/height, return the one that had the highest score. - if (max_iter != unused_surfaces_.end()) { - SkSurface* surface = *max_iter; - // Remove this surface from the list of unused surfaces. - unused_surfaces_.erase(max_iter); - // Return the cached surface. - return surface; - } else { - // Otherwise return NULL to indicate that we do not have any suitable cached - // surfaces. - return NULL; - } -} - -void ScratchSurfaceCache::Purge() { - // Delete surfaces from the front (least recently used) of |unused_surfaces_| - // until we have deleted all surfaces or lowered our memory usage to under - // |cache_capacity_in_bytes_|. - while (!unused_surfaces_.empty() && - surface_memory_ > cache_capacity_in_bytes_) { - SkSurface* to_free = unused_surfaces_.front(); - surface_memory_ -= ApproximateSurfaceMemory( - math::Size(to_free->width(), to_free->height())); - to_free->unref(); - unused_surfaces_.erase(unused_surfaces_.begin()); - } +SkSurface* CachedScratchSurface::GetSurface() { + return base::polymorphic_downcast<SkiaSurface*>( + common_scratch_surface_.GetSurface()) + ->sk_surface(); } } // namespace skia
diff --git a/src/cobalt/renderer/rasterizer/skia/scratch_surface_cache.h b/src/cobalt/renderer/rasterizer/skia/scratch_surface_cache.h index 374cc66..eaf7ea5 100644 --- a/src/cobalt/renderer/rasterizer/skia/scratch_surface_cache.h +++ b/src/cobalt/renderer/rasterizer/skia/scratch_surface_cache.h
@@ -22,96 +22,52 @@ #include "base/callback.h" #include "base/logging.h" #include "cobalt/math/size.h" +#include "cobalt/renderer/rasterizer/common/scratch_surface_cache.h" #include "third_party/skia/include/core/SkSurface.h" -#include "third_party/skia/include/core/SkSurfaceProps.h" namespace cobalt { namespace renderer { namespace rasterizer { namespace skia { -// The ScratchSurfaceCache manages a set of Skia SkSurface objects that can -// be used for offscreen rendering (mainly by SkiaRenderTreeNodeVisitor). -// In order to acquire surfaces from ScratchSurfaceCache, one should construct -// a CachedScratchSurface object, from which they can get a pointer to the -// SkSurface object. -// It is unique because it caters to SkiaRenderTreeNodeVisitor's scratch -// surface allocation pattern. In particular, we don't mind handing out very -// large scratch surfaces when very small surfaces are requested, because -// typically only one surface is ever needed at a time. When multiple surfaces -// are necessary, the subsequent ones tend to be smaller than the previous -// (because rendering is now happening within the previous ones), and so handing -// out textures in large to small order makes sense. class ScratchSurfaceCache { public: typedef base::Callback<SkSurface*(const math::Size&)> CreateSkSurfaceFunction; - ScratchSurfaceCache(const CreateSkSurfaceFunction& create_sk_surface_function, + ScratchSurfaceCache(CreateSkSurfaceFunction create_sk_surface_function, int cache_capacity_in_bytes); - ~ScratchSurfaceCache(); private: - // Acquire (either via cache lookup or by creation if that fails) a scratch - // surface. - SkSurface* AcquireScratchSurface(const math::Size& size); - void ReleaseScratchSurface(SkSurface* surface); + class Delegate : public common::ScratchSurfaceCache::Delegate { + public: + explicit Delegate(CreateSkSurfaceFunction create_sk_surface_function); - // Searches through |unused_surfaces_| for one the one that best matches the - // requested size, among all those cached surfaces that have at least the - // requested size. - SkSurface* FindBestCachedSurface(const math::Size& size); + common::ScratchSurfaceCache::Surface* CreateSurface( + const math::Size& size) OVERRIDE; + void DestroySurface(common::ScratchSurfaceCache::Surface* surface) OVERRIDE; + void PrepareForUse(common::ScratchSurfaceCache::Surface* surface, + const math::Size& area) OVERRIDE; - // Removes elements from the cache until we are below the cache limit. - void Purge(); + private: + CreateSkSurfaceFunction create_sk_surface_function_; + }; - // Allocate a new SkSurface and return it. - SkSurface* CreateScratchSurface(const math::Size& size); - - // Called to allocate new SkSurfaces. - CreateSkSurfaceFunction create_sk_surface_function_; - - // The maximum number of surface bytes that can be stored in the cache. - int cache_capacity_in_bytes_; - - // We keep track of all surfaces we've handed out using |surface_stack_|. - // This is mostly for debug checks to verify that surfaces returned to us - // actually did come from us, and that they are returned in the expected - // order. - std::vector<SkSurface*> surface_stack_; - - // |unused_surfaces_| is the heart of the cache, as it stores the surfaces - // that are unused but allocated and available to be handed out upon request. - // Most recently used surfaces are found at the end of this vector. - std::vector<SkSurface*> unused_surfaces_; - - // Tracks how much total memory we've allocated towards surfaces. - size_t surface_memory_; + Delegate delegate_; + common::ScratchSurfaceCache cache_; friend class CachedScratchSurface; }; -// The primary interface to ScratchSurfaceCache is through CachedScratchSurface -// objects. These effectively scope the acquisition of a cached surface, RAII -// style. class CachedScratchSurface { public: CachedScratchSurface(ScratchSurfaceCache* cache, const math::Size& size) - : cache_(cache) { - surface_ = cache_->AcquireScratchSurface(size); - } - - ~CachedScratchSurface() { - if (surface_) { - cache_->ReleaseScratchSurface(surface_); - } - } + : common_scratch_surface_(&cache->cache_, size) {} // Returns a pointer to the Skia SkSurface. - SkSurface* GetSurface() { return surface_; } + SkSurface* GetSurface(); private: - ScratchSurfaceCache* cache_; - SkSurface* surface_; + common::CachedScratchSurface common_scratch_surface_; }; } // namespace skia
diff --git a/src/cobalt/renderer/renderer_module_default_options_starboard.cc b/src/cobalt/renderer/renderer_module_default_options_starboard.cc index 50a38f0..db5086b 100644 --- a/src/cobalt/renderer/renderer_module_default_options_starboard.cc +++ b/src/cobalt/renderer/renderer_module_default_options_starboard.cc
@@ -53,7 +53,8 @@ #else return scoped_ptr<rasterizer::Rasterizer>( new rasterizer::blitter::HardwareRasterizer( - graphics_context, options.surface_cache_size_in_bytes)); + graphics_context, options.scratch_surface_cache_size_in_bytes, + options.surface_cache_size_in_bytes)); #endif // COBALT_FORCE_SOFTWARE_RASTERIZER #else #error "Either GLES2 or the Starboard Blitter API must be available."
diff --git a/src/cobalt/renderer/sandbox/renderer_sandbox_main.cc b/src/cobalt/renderer/sandbox/renderer_sandbox_main.cc index dc54939..3fddb14 100644 --- a/src/cobalt/renderer/sandbox/renderer_sandbox_main.cc +++ b/src/cobalt/renderer/sandbox/renderer_sandbox_main.cc
@@ -30,7 +30,6 @@ using cobalt::render_tree::ResourceProvider; using cobalt::renderer::test::scenes::AddBlankBackgroundToScene; using cobalt::renderer::test::scenes::CreateAllScenesCombinedScene; -using cobalt::renderer::test::scenes::RenderTreeWithAnimations; using cobalt::system_window::SystemWindow; namespace { @@ -67,7 +66,7 @@ // Construct our render tree and associated animations to be passed into // the renderer pipeline for display. base::TimeDelta start_time = base::Time::Now() - base::Time::UnixEpoch(); - RenderTreeWithAnimations scene = AddBlankBackgroundToScene( + scoped_refptr<cobalt::render_tree::Node> scene = AddBlankBackgroundToScene( CreateAllScenesCombinedScene( renderer_module_->pipeline()->GetResourceProvider(), output_dimensions, start_time), @@ -75,8 +74,8 @@ // Pass the render tree along with associated animations into the renderer // module to be displayed. - renderer_module_->pipeline()->Submit(cobalt::renderer::Submission( - scene.render_tree, scene.animations, start_time)); + renderer_module_->pipeline()->Submit( + cobalt::renderer::Submission(scene, start_time)); } RendererSandbox* g_renderer_sandbox = NULL;
diff --git a/src/cobalt/renderer/sandbox/scaling_text_sandbox_main.cc b/src/cobalt/renderer/sandbox/scaling_text_sandbox_main.cc index 20f2685..71d2f04 100644 --- a/src/cobalt/renderer/sandbox/scaling_text_sandbox_main.cc +++ b/src/cobalt/renderer/sandbox/scaling_text_sandbox_main.cc
@@ -30,7 +30,6 @@ using cobalt::render_tree::ResourceProvider; using cobalt::renderer::test::scenes::AddBlankBackgroundToScene; using cobalt::renderer::test::scenes::CreateScalingTextScene; -using cobalt::renderer::test::scenes::RenderTreeWithAnimations; using cobalt::system_window::SystemWindow; namespace { @@ -62,15 +61,15 @@ // Construct our render tree and associated animations to be passed into // the renderer pipeline for display. base::TimeDelta start_time = base::Time::Now() - base::Time::UnixEpoch(); - RenderTreeWithAnimations scene = AddBlankBackgroundToScene( + scoped_refptr<cobalt::render_tree::Node> scene = AddBlankBackgroundToScene( CreateScalingTextScene(renderer_module.pipeline()->GetResourceProvider(), output_dimensions, start_time), output_dimensions); // Pass the render tree along with associated animations into the renderer // module to be displayed. - renderer_module.pipeline()->Submit(cobalt::renderer::Submission( - scene.render_tree, scene.animations, start_time)); + renderer_module.pipeline()->Submit( + cobalt::renderer::Submission(scene, start_time)); base::PlatformThread::Sleep(base::TimeDelta::FromSeconds(30));
diff --git a/src/cobalt/renderer/submission.h b/src/cobalt/renderer/submission.h index 7cc86f2..2652e35 100644 --- a/src/cobalt/renderer/submission.h +++ b/src/cobalt/renderer/submission.h
@@ -21,7 +21,7 @@ #include "base/debug/trace_event.h" #include "base/memory/ref_counted.h" #include "base/time.h" -#include "cobalt/render_tree/animations/node_animations_map.h" +#include "cobalt/render_tree/animations/animate_node.h" #include "cobalt/render_tree/node.h" namespace cobalt { @@ -32,20 +32,14 @@ // Convenience constructor that assumes there are no animations and sets up // an empty animation map. explicit Submission(scoped_refptr<render_tree::Node> render_tree) - : render_tree(render_tree), - animations(new render_tree::animations::NodeAnimationsMap( - render_tree::animations::NodeAnimationsMap::Builder().Pass())) {} + : render_tree(render_tree) {} // Submit a render tree as well as associated animations. The // time_offset parameter indicates a time that will be used to offset all // times passed into animation functions. - Submission( - scoped_refptr<render_tree::Node> render_tree, - scoped_refptr<render_tree::animations::NodeAnimationsMap> animations, - base::TimeDelta time_offset) - : render_tree(render_tree), - animations(animations), - time_offset(time_offset) {} + Submission(scoped_refptr<render_tree::Node> render_tree, + base::TimeDelta time_offset) + : render_tree(render_tree), time_offset(time_offset) {} ~Submission() { TRACE_EVENT0("cobalt::renderer", "~Submission()"); @@ -53,17 +47,11 @@ // Explicitly dereference the render tree and animation under the scope of // the above trace event. render_tree = NULL; - animations = NULL; } // Maintains the current render tree that is to be rendered next frame. scoped_refptr<render_tree::Node> render_tree; - // Maintains the current animations that are to be in effect (i.e. applied - // to current_tree_) for all rasterizations until specifically updated by a - // call to Submit(). - scoped_refptr<render_tree::animations::NodeAnimationsMap> animations; - // The time from some origin that the associated render tree animations were // created. This permits the render thread to compute times relative // to the same origin when updating the animations, as well as hinting
diff --git a/src/cobalt/renderer/test/scenes/all_scenes_combined_scene.cc b/src/cobalt/renderer/test/scenes/all_scenes_combined_scene.cc index ff5045a..133aa88 100644 --- a/src/cobalt/renderer/test/scenes/all_scenes_combined_scene.cc +++ b/src/cobalt/renderer/test/scenes/all_scenes_combined_scene.cc
@@ -29,48 +29,41 @@ using cobalt::math::SizeF; using cobalt::render_tree::CompositionNode; using cobalt::render_tree::ResourceProvider; -using cobalt::render_tree::animations::NodeAnimationsMap; +using cobalt::render_tree::animations::AnimateNode; namespace cobalt { namespace renderer { namespace test { namespace scenes { -RenderTreeWithAnimations CreateAllScenesCombinedScene( +scoped_refptr<render_tree::Node> CreateAllScenesCombinedScene( ResourceProvider* resource_provider, const SizeF& output_dimensions, base::TimeDelta start_time) { TRACE_EVENT0("cobalt::renderer_sandbox", "CreateAllScenesCombinedScene()"); CompositionNode::Builder all_scenes_combined_scene_builder; - NodeAnimationsMap::Builder animations; // Compose all the render trees representing the sub-scenes through a // composition node, and merge the animations into one large set. - RenderTreeWithAnimations growing_rect_scene = + scoped_refptr<render_tree::Node> growing_rect_scene = CreateGrowingRectScene(output_dimensions, start_time); - all_scenes_combined_scene_builder.AddChild(growing_rect_scene.render_tree); - animations.Merge(*growing_rect_scene.animations); + all_scenes_combined_scene_builder.AddChild(growing_rect_scene); - RenderTreeWithAnimations spinning_sprites_scene = - CreateSpinningSpritesScene( - resource_provider, output_dimensions, start_time); - all_scenes_combined_scene_builder.AddChild( - spinning_sprites_scene.render_tree); - animations.Merge(*spinning_sprites_scene.animations); + scoped_refptr<render_tree::Node> spinning_sprites_scene = + CreateSpinningSpritesScene(resource_provider, output_dimensions, + start_time); + all_scenes_combined_scene_builder.AddChild(spinning_sprites_scene); - RenderTreeWithAnimations image_wrap_scene = + scoped_refptr<render_tree::Node> image_wrap_scene = CreateImageWrapScene(resource_provider, output_dimensions, start_time); - all_scenes_combined_scene_builder.AddChild(image_wrap_scene.render_tree); - animations.Merge(*image_wrap_scene.animations); + all_scenes_combined_scene_builder.AddChild(image_wrap_scene); - RenderTreeWithAnimations marquee_scene = + scoped_refptr<render_tree::Node> marquee_scene = CreateMarqueeScene(resource_provider, output_dimensions, start_time); - all_scenes_combined_scene_builder.AddChild(marquee_scene.render_tree); - animations.Merge(*marquee_scene.animations); + all_scenes_combined_scene_builder.AddChild(marquee_scene); - return RenderTreeWithAnimations( - new CompositionNode(all_scenes_combined_scene_builder.Pass()), - new NodeAnimationsMap(animations.Pass())); + return new AnimateNode( + new CompositionNode(all_scenes_combined_scene_builder.Pass())); } } // namespace scenes
diff --git a/src/cobalt/renderer/test/scenes/all_scenes_combined_scene.h b/src/cobalt/renderer/test/scenes/all_scenes_combined_scene.h index 2d098fc..e5c1eec 100644 --- a/src/cobalt/renderer/test/scenes/all_scenes_combined_scene.h +++ b/src/cobalt/renderer/test/scenes/all_scenes_combined_scene.h
@@ -29,7 +29,7 @@ // This scene will simply composite all other scene types together into one // mega scene. -RenderTreeWithAnimations CreateAllScenesCombinedScene( +scoped_refptr<render_tree::Node> CreateAllScenesCombinedScene( render_tree::ResourceProvider* resource_provider, const math::SizeF& output_dimensions, base::TimeDelta start_time);
diff --git a/src/cobalt/renderer/test/scenes/growing_rect_scene.cc b/src/cobalt/renderer/test/scenes/growing_rect_scene.cc index 54edd16..1f06a4b 100644 --- a/src/cobalt/renderer/test/scenes/growing_rect_scene.cc +++ b/src/cobalt/renderer/test/scenes/growing_rect_scene.cc
@@ -27,15 +27,15 @@ using cobalt::math::ScaleMatrix; using cobalt::math::SizeF; using cobalt::math::TranslateMatrix; +using cobalt::render_tree::animations::AnimateNode; +using cobalt::render_tree::animations::Animation; +using cobalt::render_tree::animations::AnimationList; using cobalt::render_tree::Brush; using cobalt::render_tree::ColorRGBA; using cobalt::render_tree::MatrixTransformNode; using cobalt::render_tree::Node; using cobalt::render_tree::RectNode; using cobalt::render_tree::SolidColorBrush; -using cobalt::render_tree::animations::Animation; -using cobalt::render_tree::animations::AnimationList; -using cobalt::render_tree::animations::NodeAnimationsMap; namespace cobalt { namespace renderer { @@ -62,13 +62,13 @@ } // namespace -RenderTreeWithAnimations CreateGrowingRectScene( +scoped_refptr<render_tree::Node> CreateGrowingRectScene( const math::SizeF& output_dimensions, base::TimeDelta start_time) { // Create a centered, sawtoothed-growing black rectangle. We need a // composition node for this so that the rectangle's position can be set // and animated. We also use the composition node to animate the RectNode's // size. - NodeAnimationsMap::Builder animations; + AnimateNode::Builder animations; scoped_refptr<RectNode> growing_rect_node(new RectNode( math::RectF(output_dimensions), @@ -81,8 +81,7 @@ base::Bind(&AnimateGrowingRectComposition, start_time, output_dimensions)); - return RenderTreeWithAnimations(transformed_growing_rect, - new NodeAnimationsMap(animations.Pass())); + return new AnimateNode(animations, transformed_growing_rect); } } // namespace scenes
diff --git a/src/cobalt/renderer/test/scenes/growing_rect_scene.h b/src/cobalt/renderer/test/scenes/growing_rect_scene.h index d57c5b7..9ffabbc 100644 --- a/src/cobalt/renderer/test/scenes/growing_rect_scene.h +++ b/src/cobalt/renderer/test/scenes/growing_rect_scene.h
@@ -28,7 +28,7 @@ // This scene gives a gray rectangle centered in the screen that slowly grows // to fill the screen. -RenderTreeWithAnimations CreateGrowingRectScene( +scoped_refptr<render_tree::Node> CreateGrowingRectScene( const math::SizeF& output_dimensions, base::TimeDelta start_time); } // namespace scenes
diff --git a/src/cobalt/renderer/test/scenes/image_wrap_scene.cc b/src/cobalt/renderer/test/scenes/image_wrap_scene.cc index ee70281..1add5b4 100644 --- a/src/cobalt/renderer/test/scenes/image_wrap_scene.cc +++ b/src/cobalt/renderer/test/scenes/image_wrap_scene.cc
@@ -34,15 +34,15 @@ using cobalt::math::Matrix3F; using cobalt::math::SizeF; +using cobalt::render_tree::animations::AnimateNode; +using cobalt::render_tree::animations::Animation; +using cobalt::render_tree::animations::AnimationList; using cobalt::render_tree::CompositionNode; using cobalt::render_tree::Image; using cobalt::render_tree::ImageNode; using cobalt::render_tree::MatrixTransformNode; using cobalt::render_tree::Node; using cobalt::render_tree::ResourceProvider; -using cobalt::render_tree::animations::Animation; -using cobalt::render_tree::animations::AnimationList; -using cobalt::render_tree::animations::NodeAnimationsMap; using cobalt::renderer::test::png_utils::DecodePNGToRenderTreeImage; namespace cobalt { @@ -89,10 +89,10 @@ } // namespace -RenderTreeWithAnimations CreateImageWrapScene( +scoped_refptr<render_tree::Node> CreateImageWrapScene( ResourceProvider* resource_provider, const math::SizeF& output_dimensions, base::TimeDelta start_time) { - NodeAnimationsMap::Builder animations; + AnimateNode::Builder animations; // Create an image node that will have its local_transform animated to // demonstrate what local_transform allows one to do. @@ -107,8 +107,7 @@ animations.Add(image_node, base::Bind(&AnimateImage, start_time)); - return RenderTreeWithAnimations( - image_wrap_scene, new NodeAnimationsMap(animations.Pass())); + return new AnimateNode(animations, image_wrap_scene); } } // namespace scenes
diff --git a/src/cobalt/renderer/test/scenes/image_wrap_scene.h b/src/cobalt/renderer/test/scenes/image_wrap_scene.h index 4c2d631..27726ff 100644 --- a/src/cobalt/renderer/test/scenes/image_wrap_scene.h +++ b/src/cobalt/renderer/test/scenes/image_wrap_scene.h
@@ -31,7 +31,7 @@ // shrunk, and so the texture repeats to fill the size of the image node. // The texture is also spinning. This scene effectively shows off // ImageNode's local_matrix parameter. -RenderTreeWithAnimations CreateImageWrapScene( +scoped_refptr<render_tree::Node> CreateImageWrapScene( render_tree::ResourceProvider* resource_provider, const math::SizeF& output_dimensions, base::TimeDelta start_time);
diff --git a/src/cobalt/renderer/test/scenes/marquee_scene.cc b/src/cobalt/renderer/test/scenes/marquee_scene.cc index f2630ce..3d44382 100644 --- a/src/cobalt/renderer/test/scenes/marquee_scene.cc +++ b/src/cobalt/renderer/test/scenes/marquee_scene.cc
@@ -33,6 +33,9 @@ using cobalt::math::RectF; using cobalt::math::SizeF; using cobalt::math::TranslateMatrix; +using cobalt::render_tree::animations::AnimateNode; +using cobalt::render_tree::animations::Animation; +using cobalt::render_tree::animations::AnimationList; using cobalt::render_tree::Brush; using cobalt::render_tree::ColorRGBA; using cobalt::render_tree::CompositionNode; @@ -45,9 +48,6 @@ using cobalt::render_tree::ResourceProvider; using cobalt::render_tree::SolidColorBrush; using cobalt::render_tree::TextNode; -using cobalt::render_tree::animations::Animation; -using cobalt::render_tree::animations::AnimationList; -using cobalt::render_tree::animations::NodeAnimationsMap; namespace cobalt { namespace renderer { @@ -85,11 +85,11 @@ } // namespace -RenderTreeWithAnimations CreateMarqueeScene( +scoped_refptr<render_tree::Node> CreateMarqueeScene( ResourceProvider* resource_provider, const math::SizeF& output_dimensions, base::TimeDelta start_time) { CompositionNode::Builder marquee_scene_builder; - NodeAnimationsMap::Builder animations; + AnimateNode::Builder animations; const std::string kMarqueeText("YouTube"); @@ -130,8 +130,7 @@ animations.Add(marquee_node, base::Bind(&AnimateMarqueeElement, start_time, text_bounds, output_dimensions)); - return RenderTreeWithAnimations(marquee_node, - new NodeAnimationsMap(animations.Pass())); + return new AnimateNode(animations, marquee_node); } } // namespace scenes
diff --git a/src/cobalt/renderer/test/scenes/marquee_scene.h b/src/cobalt/renderer/test/scenes/marquee_scene.h index 0d15965..5b2055a 100644 --- a/src/cobalt/renderer/test/scenes/marquee_scene.h +++ b/src/cobalt/renderer/test/scenes/marquee_scene.h
@@ -29,7 +29,7 @@ // This render tree builder will create a scene containing highlighted // text scrolling smoothly from left to right. -RenderTreeWithAnimations CreateMarqueeScene( +scoped_refptr<render_tree::Node> CreateMarqueeScene( render_tree::ResourceProvider* resource_provider, const math::SizeF& output_dimensions, base::TimeDelta start_time);
diff --git a/src/cobalt/renderer/test/scenes/scaling_text_scene.cc b/src/cobalt/renderer/test/scenes/scaling_text_scene.cc index 4ac33b5..952b03b 100644 --- a/src/cobalt/renderer/test/scenes/scaling_text_scene.cc +++ b/src/cobalt/renderer/test/scenes/scaling_text_scene.cc
@@ -45,7 +45,7 @@ using cobalt::render_tree::TextNode; using cobalt::render_tree::animations::Animation; using cobalt::render_tree::animations::AnimationList; -using cobalt::render_tree::animations::NodeAnimationsMap; +using cobalt::render_tree::animations::AnimateNode; namespace cobalt { namespace renderer { @@ -62,7 +62,7 @@ } // namespace -RenderTreeWithAnimations CreateScalingTextScene( +scoped_refptr<render_tree::Node> CreateScalingTextScene( ResourceProvider* resource_provider, const math::SizeF& output_dimensions, base::TimeDelta start_time) { const std::string kText( @@ -91,11 +91,10 @@ Matrix3F::Identity())); // Setup the scaling animation on the text - NodeAnimationsMap::Builder animations; + AnimateNode::Builder animations; animations.Add(scaling_text_node, base::Bind(&ScaleText)); - return RenderTreeWithAnimations(scaling_text_node, - new NodeAnimationsMap(animations.Pass())); + return new AnimateNode(animations, scaling_text_node); } } // namespace scenes
diff --git a/src/cobalt/renderer/test/scenes/scaling_text_scene.h b/src/cobalt/renderer/test/scenes/scaling_text_scene.h index c6d8771..4b3226d 100644 --- a/src/cobalt/renderer/test/scenes/scaling_text_scene.h +++ b/src/cobalt/renderer/test/scenes/scaling_text_scene.h
@@ -31,7 +31,7 @@ // scale being applied to it, and the scale of all text is animated. // This is very useful for investigating issues with text scaling, which // internally can be quite non-trivial. -RenderTreeWithAnimations CreateScalingTextScene( +scoped_refptr<render_tree::Node> CreateScalingTextScene( render_tree::ResourceProvider* resource_provider, const math::SizeF& output_dimensions, base::TimeDelta start_time);
diff --git a/src/cobalt/renderer/test/scenes/scene_helpers.cc b/src/cobalt/renderer/test/scenes/scene_helpers.cc index 724142c..39aa8d5 100644 --- a/src/cobalt/renderer/test/scenes/scene_helpers.cc +++ b/src/cobalt/renderer/test/scenes/scene_helpers.cc
@@ -36,8 +36,8 @@ namespace test { namespace scenes { -RenderTreeWithAnimations AddBlankBackgroundToScene( - const RenderTreeWithAnimations& scene, +scoped_refptr<render_tree::Node> AddBlankBackgroundToScene( + const scoped_refptr<render_tree::Node>& scene, const SizeF& output_dimensions) { // Declare a rectangle that fills the background to effectively clear the // screen. @@ -45,10 +45,10 @@ with_background_scene_builder.AddChild(make_scoped_refptr(new RectNode( RectF(output_dimensions), scoped_ptr<Brush>(new SolidColorBrush(ColorRGBA(1.0f, 1.0f, 1.0f)))))); - with_background_scene_builder.AddChild(scene.render_tree); + with_background_scene_builder.AddChild(scene); - return RenderTreeWithAnimations(new CompositionNode( - with_background_scene_builder.Pass()), scene.animations); + return new render_tree::animations::AnimateNode( + new CompositionNode(with_background_scene_builder.Pass())); } } // namespace scenes
diff --git a/src/cobalt/renderer/test/scenes/scene_helpers.h b/src/cobalt/renderer/test/scenes/scene_helpers.h index 67b6ab1..7c84d41 100644 --- a/src/cobalt/renderer/test/scenes/scene_helpers.h +++ b/src/cobalt/renderer/test/scenes/scene_helpers.h
@@ -18,7 +18,7 @@ #define COBALT_RENDERER_TEST_SCENES_SCENE_HELPERS_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" namespace cobalt { @@ -30,18 +30,8 @@ // animations. inline float Sawtooth(float x) { return x - static_cast<int>(x); } -struct RenderTreeWithAnimations { - RenderTreeWithAnimations( - scoped_refptr<render_tree::Node> render_tree, - 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; -}; - -RenderTreeWithAnimations AddBlankBackgroundToScene( - const RenderTreeWithAnimations& scene, +scoped_refptr<render_tree::Node> AddBlankBackgroundToScene( + const scoped_refptr<render_tree::Node>& scene, const math::SizeF& output_dimensions); } // namespace scenes
diff --git a/src/cobalt/renderer/test/scenes/spinning_sprites_scene.cc b/src/cobalt/renderer/test/scenes/spinning_sprites_scene.cc index c338454..e54d4b0 100644 --- a/src/cobalt/renderer/test/scenes/spinning_sprites_scene.cc +++ b/src/cobalt/renderer/test/scenes/spinning_sprites_scene.cc
@@ -35,20 +35,20 @@ using cobalt::math::Matrix3F; using cobalt::math::PointF; -using cobalt::math::RotateMatrix; using cobalt::math::RectF; +using cobalt::math::RotateMatrix; using cobalt::math::ScaleMatrix; using cobalt::math::SizeF; using cobalt::math::TranslateMatrix; +using cobalt::render_tree::animations::AnimateNode; +using cobalt::render_tree::animations::Animation; +using cobalt::render_tree::animations::AnimationList; using cobalt::render_tree::CompositionNode; using cobalt::render_tree::Image; using cobalt::render_tree::ImageNode; using cobalt::render_tree::MatrixTransformNode; using cobalt::render_tree::Node; using cobalt::render_tree::ResourceProvider; -using cobalt::render_tree::animations::Animation; -using cobalt::render_tree::animations::AnimationList; -using cobalt::render_tree::animations::NodeAnimationsMap; using cobalt::renderer::test::png_utils::DecodePNGToRenderTreeImage; namespace cobalt { @@ -118,14 +118,14 @@ } // namespace -RenderTreeWithAnimations CreateSpinningSpritesScene( +scoped_refptr<render_tree::Node> CreateSpinningSpritesScene( ResourceProvider* resource_provider, const math::SizeF& output_dimensions, base::TimeDelta start_time) { // Create an image for each SpriteInfo we have in our sprite_infos vector. // They will be positioned and scaled according to their SpriteInfo settings, // and rotated according to time. CompositionNode::Builder spinning_sprites_scene_builder; - NodeAnimationsMap::Builder animations; + AnimateNode::Builder animations; // Now, setup a plurality of spinning images that contain the test image. std::vector<SpriteInfo> sprite_infos = CreateSpriteInfos(); @@ -154,8 +154,7 @@ scoped_refptr<CompositionNode> spinning_sprites_composition( new CompositionNode(spinning_sprites_scene_builder.Pass())); - return RenderTreeWithAnimations(spinning_sprites_composition, - new NodeAnimationsMap(animations.Pass())); + return new AnimateNode(animations, spinning_sprites_composition); } } // namespace scenes
diff --git a/src/cobalt/renderer/test/scenes/spinning_sprites_scene.h b/src/cobalt/renderer/test/scenes/spinning_sprites_scene.h index 9e56e63..56595ab 100644 --- a/src/cobalt/renderer/test/scenes/spinning_sprites_scene.h +++ b/src/cobalt/renderer/test/scenes/spinning_sprites_scene.h
@@ -29,7 +29,7 @@ // This scene will create a plurality of randomly positioned and sized sprites // that are all spinning at different rates. -RenderTreeWithAnimations CreateSpinningSpritesScene( +scoped_refptr<render_tree::Node> CreateSpinningSpritesScene( render_tree::ResourceProvider* resource_provider, const math::SizeF& output_dimensions, base::TimeDelta start_time);
diff --git a/src/cobalt/script/javascriptcore/jsc_global_object.cc b/src/cobalt/script/javascriptcore/jsc_global_object.cc index 6596d1b..9122348 100644 --- a/src/cobalt/script/javascriptcore/jsc_global_object.cc +++ b/src/cobalt/script/javascriptcore/jsc_global_object.cc
@@ -17,6 +17,7 @@ #include "cobalt/script/javascriptcore/jsc_global_object.h" #include "base/logging.h" +#include "cobalt/script/javascriptcore/util/exception_helpers.h" namespace cobalt { namespace script { @@ -57,6 +58,10 @@ script_object_registry_(script_object_registry), environment_settings_(environment_settings) {} +std::vector<script::StackFrame> JSCGlobalObject::GetStackTrace(int max_frames) { + return util::GetStackTrace(globalExec(), max_frames); +} + } // namespace javascriptcore } // namespace script } // namespace cobalt
diff --git a/src/cobalt/script/javascriptcore/jsc_global_object.h b/src/cobalt/script/javascriptcore/jsc_global_object.h index 9671b44..89f0dc6 100644 --- a/src/cobalt/script/javascriptcore/jsc_global_object.h +++ b/src/cobalt/script/javascriptcore/jsc_global_object.h
@@ -26,6 +26,7 @@ #include "cobalt/script/javascriptcore/js_object_cache.h" #include "cobalt/script/javascriptcore/script_object_registry.h" #include "cobalt/script/javascriptcore/wrapper_factory.h" +#include "cobalt/script/stack_frame.h" #include "cobalt/script/wrappable.h" #include "third_party/WebKit/Source/JavaScriptCore/config.h" #include "third_party/WebKit/Source/JavaScriptCore/runtime/JSGlobalData.h" @@ -59,6 +60,7 @@ EnvironmentSettings* GetEnvironmentSettings() { return environment_settings_; } + std::vector<StackFrame> GetStackTrace(int max_frames = 0); // JavaScriptCore stuff DECLARE_CLASSINFO();
diff --git a/src/cobalt/script/mozjs/mozjs.cc b/src/cobalt/script/mozjs/mozjs.cc index 0de17d2..6625ed2 100644 --- a/src/cobalt/script/mozjs/mozjs.cc +++ b/src/cobalt/script/mozjs/mozjs.cc
@@ -21,8 +21,10 @@ #include "base/string_util.h" #include "cobalt/base/wrap_main.h" #include "cobalt/script/mozjs/mozjs_global_object_proxy.h" +#include "cobalt/script/source_code.h" #include "cobalt/script/standalone_javascript_runner.h" #include "third_party/mozjs/js/src/jsapi.h" +#include "third_party/mozjs/js/src/jsproxy.h" namespace cobalt { namespace script { @@ -50,6 +52,8 @@ } void SetupBindings(JSContext* context, JSObject* global_object) { + DCHECK(JS_IsGlobalObject(global_object)); + JSAutoRequest auto_request(context); JSAutoCompartment auto_comparment(context, global_object); JS_DefineFunction(context, global_object, "print", &Print, 0, @@ -58,18 +62,43 @@ int MozjsMain(int argc, char** argv) { cobalt::script::StandaloneJavascriptRunner standalone_runner; - MozjsGlobalObjectProxy* global_object_proxy = + MozjsGlobalObjectProxy* global_object_environment = static_cast<MozjsGlobalObjectProxy*>( standalone_runner.global_object_proxy().get()); - SetupBindings(global_object_proxy->context(), - global_object_proxy->global_object()); + SetupBindings(global_object_environment->context(), + global_object_environment->global_object()); - CommandLine command_line(argc, argv); - CommandLine::StringVector args = command_line.GetArgs(); - if (!args.empty()) { - FilePath source_file(args[0]); - standalone_runner.ExecuteFile(source_file); + if (argc > 1) { + // Command line arguments will be flag-value pairs of the form + // -f filename + // and + // -e "inline script" + // and will be evaluated in order. + for (int i = 1; (i + 1) < argc; ++i) { + if (std::string(argv[i]) == "-f") { + std::string filename = std::string(argv[i + 1]); + // Execute source file. + FilePath source_file(filename); + standalone_runner.ExecuteFile(source_file); + ++i; + } else if (std::string(argv[i]) == "-e") { + // Execute inline script. + scoped_refptr<SourceCode> source = SourceCode::CreateSourceCode( + argv[i + 1], base::SourceLocation("[stdin]", 1, 1)); + + // Execute the script and get the results of execution. + std::string result; + bool success = + global_object_environment->EvaluateScript(source, &result); + // Echo the results to stdout. + if (!success) { + std::cout << "Exception: "; + } + std::cout << result << std::endl; + ++i; + } + } } else { standalone_runner.RunInteractive(); }
diff --git a/src/cobalt/script/mozjs/mozjs.gyp b/src/cobalt/script/mozjs/mozjs.gyp index 58728de..49f8313 100644 --- a/src/cobalt/script/mozjs/mozjs.gyp +++ b/src/cobalt/script/mozjs/mozjs.gyp
@@ -27,6 +27,7 @@ 'mozjs_property_enumerator.cc', 'mozjs_source_code.cc', 'proxy_handler.cc', + 'util/exception_helpers.cc', 'wrapper_factory.cc', 'wrapper_private.cc', ], @@ -41,6 +42,11 @@ 'ENGINE_SUPPORTS_INDEXED_DELETERS', 'ENGINE_SUPPORTS_INT64', ], }, + 'conditions' :[ + ['cobalt_enable_jit == 1', { + 'defines': [ 'ENGINE_SUPPORTS_JIT', ], + }], + ], }, {
diff --git a/src/cobalt/script/mozjs/mozjs_exception_state.cc b/src/cobalt/script/mozjs/mozjs_exception_state.cc index a4c575b..e7839c4 100644 --- a/src/cobalt/script/mozjs/mozjs_exception_state.cc +++ b/src/cobalt/script/mozjs/mozjs_exception_state.cc
@@ -49,7 +49,18 @@ void MozjsExceptionState::SetException( const scoped_refptr<ScriptException>& exception) { DCHECK(thread_checker_.CalledOnValidThread()); - NOTIMPLEMENTED(); + DCHECK(!is_exception_set_); + + MozjsGlobalObjectProxy* global_object_proxy = + static_cast<MozjsGlobalObjectProxy*>(JS_GetContextPrivate(context_)); + + JS::RootedObject exception_object( + context_, + global_object_proxy->wrapper_factory()->GetWrapperProxy(exception)); + JS::RootedValue exception_value(context_, OBJECT_TO_JSVAL(exception_object)); + JS_SetPendingException(context_, exception_value); + + is_exception_set_ = true; } void MozjsExceptionState::SetSimpleException(
diff --git a/src/cobalt/script/mozjs/mozjs_global_object_proxy.cc b/src/cobalt/script/mozjs/mozjs_global_object_proxy.cc index 43c45bc..8622146 100644 --- a/src/cobalt/script/mozjs/mozjs_global_object_proxy.cc +++ b/src/cobalt/script/mozjs/mozjs_global_object_proxy.cc
@@ -15,13 +15,18 @@ */ #include "cobalt/script/mozjs/mozjs_global_object_proxy.h" +#include <algorithm> #include <utility> +#include "base/lazy_instance.h" #include "base/stringprintf.h" #include "cobalt/base/polymorphic_downcast.h" #include "cobalt/script/mozjs/conversion_helpers.h" #include "cobalt/script/mozjs/mozjs_exception_state.h" #include "cobalt/script/mozjs/mozjs_source_code.h" +#include "cobalt/script/mozjs/mozjs_wrapper_handle.h" +#include "cobalt/script/mozjs/proxy_handler.h" +#include "cobalt/script/mozjs/util/exception_helpers.h" #include "third_party/mozjs/js/src/jsfriendapi.h" #include "third_party/mozjs/js/src/jsfun.h" #include "third_party/mozjs/js/src/jsobj.h" @@ -66,6 +71,52 @@ // This is the default in the spidermonkey shell. const uint32_t kMaxCodeCacheBytes = 16 * 1024 * 1024; + +// DOM proxies have an extra slot for the expando object at index +// kJSProxySlotExpando. +// The expando object is a plain JSObject whose properties correspond to +// "expandos" (custom properties set by the script author). +// The exact value stored in the kJSProxySlotExpando slot depends on whether +// the interface is annotated with the [OverrideBuiltins] extended attribute. +const uint32_t kJSProxySlotExpando = 0; + +// The DOMProxyShadowsCheck function will be called to check if the property for +// id should be gotten from the prototype, or if there is an own property that +// shadows it. +js::DOMProxyShadowsResult DOMProxyShadowsCheck(JSContext* context, + JS::HandleObject proxy, + JS::HandleId id) { + DCHECK(IsProxy(proxy)); + JS::Value value = js::GetProxyExtra(proxy, kJSProxySlotExpando); + DCHECK(value.isUndefined() || value.isObject()); + + // [OverrideBuiltins] extended attribute is not supported. + NOTIMPLEMENTED(); + + // If DoesntShadow is returned then the slot at listBaseExpandoSlot should + // either be undefined or point to an expando object that would contain the + // own property. + return js::DoesntShadow; +} + +class MozjsStubHandler : public ProxyHandler { + public: + MozjsStubHandler() + : ProxyHandler(indexed_property_hooks, named_property_hooks) {} + + private: + static NamedPropertyHooks named_property_hooks; + static IndexedPropertyHooks indexed_property_hooks; +}; + +ProxyHandler::NamedPropertyHooks MozjsStubHandler::named_property_hooks = { + NULL, NULL, NULL, NULL, NULL, +}; +ProxyHandler::IndexedPropertyHooks MozjsStubHandler::indexed_property_hooks = { + NULL, NULL, NULL, NULL, NULL, +}; + +static base::LazyInstance<MozjsStubHandler> proxy_handler; } // namespace MozjsGlobalObjectProxy::MozjsGlobalObjectProxy(JSRuntime* runtime) @@ -82,16 +133,18 @@ JS_SetGCParameterForThread(context_, JSGC_MAX_CODE_CACHE_BYTES, kMaxCodeCacheBytes); - uint32_t options = JSOPTION_TYPE_INFERENCE | JSOPTION_VAROBJFIX | // Recommended to enable this in the API docs. JSOPTION_COMPILE_N_GO | // Compiled scripts will be run only once. JSOPTION_UNROOTED_GLOBAL; // Global handle must be visited to ensure it // is not GC'd. -#if SB_CAN(MAP_EXECUTABLE_MEMORY) +#if ENGINE_SUPPORTS_JIT options |= JSOPTION_BASELINE | // Enable baseline compiler. JSOPTION_ION; // Enable IonMonkey + // This is required by baseline and IonMonkey. + js::SetDOMProxyInformation(0 /*domProxyHandlerFamily*/, kJSProxySlotExpando, + DOMProxyShadowsCheck); #endif #if !defined(COBALT_BUILD_TYPE_GOLD) && !defined(COBALT_BUILD_TYPE_QA) options |= JSOPTION_EXTRA_WARNINGS; @@ -101,6 +154,7 @@ JS_SetErrorReporter(context_, &MozjsGlobalObjectProxy::ReportErrorHandler); wrapper_factory_.reset(new WrapperFactory(context_)); + JS_AddExtraGCRootsTracer(runtime, TraceFunction, this); } @@ -111,7 +165,7 @@ void MozjsGlobalObjectProxy::CreateGlobalObject() { DCHECK(thread_checker_.CalledOnValidThread()); - DCHECK(!global_object_); + DCHECK(!global_object_proxy_); // The global object is automatically rooted unless the // JSOPTION_UNROOTED_GLOBAL option is set. @@ -128,7 +182,11 @@ JSAutoCompartment auto_compartment(context_, global_object); bool success = JS_InitStandardClasses(context_, global_object); DCHECK(success); - SetGlobalObject(global_object); + + JS::RootedObject proxy( + context_, ProxyHandler::NewProxy(context_, global_object, NULL, NULL, + proxy_handler.Pointer())); + global_object_proxy_ = proxy; } bool MozjsGlobalObjectProxy::EvaluateScript( @@ -142,12 +200,14 @@ const base::SourceLocation location = mozjs_source_code->location(); JSAutoRequest auto_request(context_); - JSAutoCompartment auto_comparment(context_, global_object_); + JSAutoCompartment auto_comparment(context_, global_object_proxy_); JS::RootedValue result_value(context_); std::string error_message; last_error_message_ = &error_message; + JS::RootedObject global_object( + context_, js::GetProxyTargetObject(global_object_proxy_)); bool success = JS_EvaluateScript( - context_, global_object_, script.c_str(), script.size(), + context_, global_object, script.c_str(), script.size(), location.file_path.c_str(), location.line_number, result_value.address()); if (out_result_utf8) { if (success) { @@ -162,6 +222,11 @@ return success; } +std::vector<StackFrame> MozjsGlobalObjectProxy::GetStackTrace(int max_frames) { + DCHECK(thread_checker_.CalledOnValidThread()); + return util::GetStackTrace(context_, max_frames); +} + void MozjsGlobalObjectProxy::DisableEval(const std::string& message) { DCHECK(thread_checker_.CalledOnValidThread()); eval_disabled_message_.emplace(message); @@ -183,11 +248,14 @@ void MozjsGlobalObjectProxy::Bind(const std::string& identifier, const scoped_refptr<Wrappable>& impl) { JSAutoRequest auto_request(context_); - JSAutoCompartment auto_comparment(context_, global_object_); + JSAutoCompartment auto_comparment(context_, global_object_proxy_); + JS::RootedObject wrapper_proxy(context_, wrapper_factory_->GetWrapperProxy(impl)); + JS::RootedObject global_object( + context_, js::GetProxyTargetObject(global_object_proxy_)); JS::Value wrapper_value = OBJECT_TO_JSVAL(wrapper_proxy); - bool success = JS_SetProperty(context_, global_object_, identifier.c_str(), + bool success = JS_SetProperty(context_, global_object, identifier.c_str(), &wrapper_value); DCHECK(success); } @@ -208,6 +276,28 @@ return global_proxy; } +void MozjsGlobalObjectProxy::SetGlobalObjectProxyAndWrapper( + JS::HandleObject global_object_proxy, + const scoped_refptr<Wrappable>& wrappable) { + DCHECK(!global_object_proxy_); + DCHECK(global_object_proxy); + DCHECK(JS_IsGlobalObject(js::GetProxyTargetObject(global_object_proxy))); + DCHECK(IsObjectProxy(global_object_proxy)); + + global_object_proxy_ = global_object_proxy; + + // Global object cached wrapper is not set as usual object. + // Set the global object cached wrapper, so we can get the object proxy + // through wrapper handle. + WrapperPrivate* wrapper_private = + WrapperPrivate::GetFromProxyObject(context_, global_object_proxy_); + DCHECK(wrapper_private); + + scoped_ptr<Wrappable::WeakWrapperHandle> object_handle( + new MozjsWrapperHandle(wrapper_private)); + SetCachedWrapper(wrappable.get(), object_handle.Pass()); +} + void MozjsGlobalObjectProxy::CacheInterfaceData(intptr_t key, InterfaceData* interface_data) { std::pair<CachedInterfaceData::iterator, bool> pib = @@ -235,15 +325,16 @@ } void MozjsGlobalObjectProxy::TraceFunction(JSTracer* trace, void* data) { - MozjsGlobalObjectProxy* global_object_proxy = + MozjsGlobalObjectProxy* global_object_environment = reinterpret_cast<MozjsGlobalObjectProxy*>(data); - if (global_object_proxy->global_object_) { - JS_CallHeapObjectTracer(trace, &global_object_proxy->global_object_, + if (global_object_environment->global_object_proxy_) { + JS_CallHeapObjectTracer(trace, + &global_object_environment->global_object_proxy_, "MozjsGlobalObjectProxy"); } for (CachedInterfaceData::iterator it = - global_object_proxy->cached_interface_data_.begin(); - it != global_object_proxy->cached_interface_data_.end(); ++it) { + global_object_environment->cached_interface_data_.begin(); + it != global_object_environment->cached_interface_data_.end(); ++it) { InterfaceData* data = it->second; JS_CallHeapObjectTracer(trace, &data->prototype, "MozjsGlobalObjectProxy"); JS_CallHeapObjectTracer(trace, &data->interface_object,
diff --git a/src/cobalt/script/mozjs/mozjs_global_object_proxy.h b/src/cobalt/script/mozjs/mozjs_global_object_proxy.h index decac4e..0355d37 100644 --- a/src/cobalt/script/mozjs/mozjs_global_object_proxy.h +++ b/src/cobalt/script/mozjs/mozjs_global_object_proxy.h
@@ -26,8 +26,10 @@ #include "base/threading/thread_checker.h" #include "cobalt/script/global_object_proxy.h" #include "cobalt/script/mozjs/interface_data.h" +#include "cobalt/script/mozjs/util/exception_helpers.h" #include "cobalt/script/mozjs/wrapper_factory.h" #include "third_party/mozjs/js/src/jsapi.h" +#include "third_party/mozjs/js/src/jsproxy.h" namespace cobalt { namespace script { @@ -35,7 +37,8 @@ // Manages a handle to a JavaScript engine's global object. The lifetime of // the global object is not necessarily tied to the lifetime of the proxy. -class MozjsGlobalObjectProxy : public GlobalObjectProxy { +class MozjsGlobalObjectProxy : public GlobalObjectProxy, + public Wrappable::CachedWrapperAccessor { public: explicit MozjsGlobalObjectProxy(JSRuntime* runtime); ~MozjsGlobalObjectProxy() OVERRIDE; @@ -53,10 +56,7 @@ return false; } - std::vector<StackFrame> GetStackTrace(int max_frames) OVERRIDE { - NOTIMPLEMENTED(); - return std::vector<StackFrame>(); - } + std::vector<StackFrame> GetStackTrace(int max_frames = 0) OVERRIDE; void PreventGarbageCollection( const scoped_refptr<Wrappable>& wrappable) OVERRIDE { @@ -79,7 +79,10 @@ JSContext* context() const { return context_; } - JSObject* global_object() const { return global_object_; } + JSObject* global_object_proxy() const { return global_object_proxy_; } + JSObject* global_object() const { + return js::GetProxyTargetObject(global_object_proxy_); + } WrapperFactory* wrapper_factory() { return wrapper_factory_.get(); } @@ -94,11 +97,9 @@ return environment_settings_; } - void SetGlobalObject(JS::HandleObject global_object) { - DCHECK(!global_object_); - DCHECK(global_object); - global_object_ = global_object; - } + void SetGlobalObjectProxyAndWrapper( + JS::HandleObject global_object_proxy, + const scoped_refptr<Wrappable>& wrappable); // Any tracked InterfaceData will have it's GC handles visited and marked as // roots. The MozjsGlobalObjectProxy takes ownership of the InterfaceData @@ -135,7 +136,7 @@ STLValueDeleter<CachedInterfaceData> cached_interface_data_deleter_; ContextDestructor context_destructor_; scoped_ptr<WrapperFactory> wrapper_factory_; - JS::Heap<JSObject*> global_object_; + JS::Heap<JSObject*> global_object_proxy_; EnvironmentSettings* environment_settings_; // If non-NULL, the error message from the ReportErrorHandler will get
diff --git a/src/cobalt/script/mozjs/mozjs_user_object_holder.h b/src/cobalt/script/mozjs/mozjs_user_object_holder.h index 0551bff..de47435 100644 --- a/src/cobalt/script/mozjs/mozjs_user_object_holder.h +++ b/src/cobalt/script/mozjs/mozjs_user_object_holder.h
@@ -16,6 +16,8 @@ #ifndef COBALT_SCRIPT_MOZJS_MOZJS_USER_OBJECT_HOLDER_H_ #define COBALT_SCRIPT_MOZJS_MOZJS_USER_OBJECT_HOLDER_H_ +#include "base/hash_tables.h" +#include "base/memory/weak_ptr.h" #include "cobalt/base/polymorphic_downcast.h" #include "cobalt/script/mozjs/wrapper_factory.h" #include "cobalt/script/mozjs/wrapper_private.h" @@ -50,14 +52,21 @@ JS::RootedObject owned_object(context_, js_object()); WrapperPrivate* wrapper_private = WrapperPrivate::GetFromWrappable(owner, context_, wrapper_factory_); + wrappable_and_private_hash_map_.insert( + std::make_pair(owner, wrapper_private->AsWeakPtr())); wrapper_private->AddReferencedObject(owned_object); } void DeregisterOwner(Wrappable* owner) OVERRIDE { JS::RootedObject owned_object(context_, js_object()); - WrapperPrivate* wrapper_private = - WrapperPrivate::GetFromWrappable(owner, context_, wrapper_factory_); - wrapper_private->RemoveReferencedObject(owned_object); + WrappableAndPrivateHashMap::iterator it = + wrappable_and_private_hash_map_.find(owner); + if (it != wrappable_and_private_hash_map_.end() && it->second) { + JS::RootedObject object_proxy(context_, it->second->js_object_proxy()); + if (object_proxy) { + it->second->RemoveReferencedObject(owned_object); + } + } } const typename MozjsUserObjectType::BaseType* GetScriptObject() @@ -89,9 +98,13 @@ } private: + typedef base::hash_map<const Wrappable*, base::WeakPtr<WrapperPrivate> > + WrappableAndPrivateHashMap; + JSContext* context_; base::optional<MozjsUserObjectType> object_handle_; WrapperFactory* wrapper_factory_; + WrappableAndPrivateHashMap wrappable_and_private_hash_map_; }; } // namespace mozjs
diff --git a/src/cobalt/script/mozjs/util/exception_helpers.cc b/src/cobalt/script/mozjs/util/exception_helpers.cc new file mode 100644 index 0000000..9ef7f2c --- /dev/null +++ b/src/cobalt/script/mozjs/util/exception_helpers.cc
@@ -0,0 +1,65 @@ +/* + * 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/script/mozjs/util/exception_helpers.h" + +#include <algorithm> + +#include "cobalt/script/mozjs/conversion_helpers.h" +#include "cobalt/script/mozjs/mozjs_exception_state.h" +#include "third_party/mozjs/js/src/jsdbgapi.h" +#include "third_party/mozjs/js/src/jsscript.h" + +namespace cobalt { +namespace script { +namespace mozjs { +namespace util { +std::vector<StackFrame> GetStackTrace(JSContext* context, int max_frames) { + JS::StackDescription* stack_description = + JS::DescribeStack(context, max_frames); + if (max_frames == 0) { + max_frames = static_cast<int>(stack_description->nframes); + } else { + max_frames = + std::min(max_frames, static_cast<int>(stack_description->nframes)); + } + JS::FrameDescription* stack_trace = stack_description->frames; + std::vector<StackFrame> stack_frames(max_frames); + for (int i = 0; i < max_frames; ++i) { + StackFrame sf; + sf.line_number = stack_trace[i].lineno; + sf.column_number = 0; + sf.function_name = "global code"; + if (stack_trace[i].fun) { + JS::RootedString rooted_string(context, + JS_GetFunctionId(stack_trace[i].fun)); + JS::RootedValue rooted_value(context, STRING_TO_JSVAL(rooted_string)); + MozjsExceptionState exception_state(context); + FromJSValue(context, rooted_value, kNoConversionFlags, &exception_state, + &sf.function_name); + } + if (stack_trace[i].script) { + sf.source_url = stack_trace[i].script->filename(); + } + stack_frames[i] = sf; + } + JS::FreeStackDescription(context, stack_description); + return stack_frames; +} +} // namespace util +} // namespace mozjs +} // namespace script +} // namespace cobalt
diff --git a/src/cobalt/script/mozjs/util/exception_helpers.h b/src/cobalt/script/mozjs/util/exception_helpers.h new file mode 100644 index 0000000..75dff27 --- /dev/null +++ b/src/cobalt/script/mozjs/util/exception_helpers.h
@@ -0,0 +1,33 @@ +/* + * Copyright 2016 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef COBALT_SCRIPT_MOZJS_UTIL_EXCEPTION_HELPERS_H_ +#define COBALT_SCRIPT_MOZJS_UTIL_EXCEPTION_HELPERS_H_ + +#include <vector> + +#include "cobalt/script/stack_frame.h" +#include "third_party/mozjs/js/src/jsapi.h" + +namespace cobalt { +namespace script { +namespace mozjs { +namespace util { +std::vector<StackFrame> GetStackTrace(JSContext* context, int max_frames); +} // namespace util +} // namespace mozjs +} // namespace script +} // namespace cobalt +#endif // COBALT_SCRIPT_MOZJS_UTIL_EXCEPTION_HELPERS_H_
diff --git a/src/cobalt/script/mozjs/wrapper_private.cc b/src/cobalt/script/mozjs/wrapper_private.cc index b7b3443..e129678 100644 --- a/src/cobalt/script/mozjs/wrapper_private.cc +++ b/src/cobalt/script/mozjs/wrapper_private.cc
@@ -39,11 +39,13 @@ } // static -void WrapperPrivate::AddPrivateData(JS::HandleObject wrapper_proxy, +void WrapperPrivate::AddPrivateData(JSContext* context, + JS::HandleObject wrapper_proxy, const scoped_refptr<Wrappable>& wrappable) { DCHECK(js::IsProxy(wrapper_proxy)); WrapperPrivate* private_data = new WrapperPrivate(wrappable, wrapper_proxy); - JSObject* target_object = js::GetProxyTargetObject(wrapper_proxy); + JS::RootedObject target_object(context, + js::GetProxyTargetObject(wrapper_proxy)); JS_SetPrivate(target_object, private_data); DCHECK_EQ(JS_GetPrivate(target_object), private_data); } @@ -114,6 +116,8 @@ DCHECK(js::IsProxy(wrapper_proxy)); } +WrapperPrivate::~WrapperPrivate() { wrapper_proxy_ = NULL; } + } // namespace mozjs } // namespace script } // namespace cobalt
diff --git a/src/cobalt/script/mozjs/wrapper_private.h b/src/cobalt/script/mozjs/wrapper_private.h index 9bb4219..e80ec75 100644 --- a/src/cobalt/script/mozjs/wrapper_private.h +++ b/src/cobalt/script/mozjs/wrapper_private.h
@@ -47,7 +47,7 @@ void RemoveReferencedObject(JS::HandleObject referee); // Create a new WrapperPrivate instance and associate it with the wrapper. - static void AddPrivateData(JS::HandleObject wrapper_proxy, + static void AddPrivateData(JSContext* context, JS::HandleObject wrapper_proxy, const scoped_refptr<Wrappable>& wrappable); // Get the WrapperPrivate associated with the given Wrappable. A new JSObject @@ -78,6 +78,7 @@ typedef ScopedVector<JS::Heap<JSObject*> > ReferencedObjectVector; WrapperPrivate(const scoped_refptr<Wrappable>& wrappable, JS::HandleObject wrapper_proxy); + ~WrapperPrivate(); scoped_refptr<Wrappable> wrappable_; JS::Heap<JSObject*> wrapper_proxy_;
diff --git a/src/cobalt/webdriver/window_driver.cc b/src/cobalt/webdriver/window_driver.cc index cb14bb9..b896311 100644 --- a/src/cobalt/webdriver/window_driver.cc +++ b/src/cobalt/webdriver/window_driver.cc
@@ -164,7 +164,13 @@ get_global_object_proxy_(get_global_object_proxy_function), window_message_loop_(message_loop), element_driver_map_deleter_(&element_drivers_), - next_element_id_(0) {} + next_element_id_(0) { + // The WindowDriver may have been created on some arbitrary thread (i.e. the + // thread that owns the Window). Detach the thread checker so it can be + // re-bound to the next thread that calls a webdriver API, which should be + // the WebDriver thread. + thread_checker_.DetachFromThread(); +} WindowDriver::~WindowDriver() { DCHECK(thread_checker_.CalledOnValidThread());
diff --git a/src/codereview.settings b/src/codereview.settings deleted file mode 100644 index a4b341a..0000000 --- a/src/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/glimp/codereview.settings b/src/glimp/codereview.settings deleted file mode 100644 index a4b341a..0000000 --- a/src/glimp/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/glimp/gles/pixel_format.cc b/src/glimp/gles/pixel_format.cc index 5c0f76b..ac1672e 100644 --- a/src/glimp/gles/pixel_format.cc +++ b/src/glimp/gles/pixel_format.cc
@@ -36,6 +36,14 @@ int BytesPerPixel(PixelFormat format) { SB_COMPILE_ASSERT(SB_ARRAY_SIZE(kBytesPerPixel) == kPixelFormatNumFormats, kBytesPerPixel_has_entries_for_each_enum_PixelFormat); + if (kPixelFormatInvalid == format) { + return 0; // Invalid formats have 0 bytes per pixel. + } + + if (format < 0 || format >= kPixelFormatNumFormats) { + SB_DCHECK(false) << "Invalid PixelFormat: " << format; + return 0; + } return kBytesPerPixel[format]; }
diff --git a/src/googleurl/codereview.settings b/src/googleurl/codereview.settings deleted file mode 100644 index a4b341a..0000000 --- a/src/googleurl/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/media/base/sbplayer_pipeline.cc b/src/media/base/sbplayer_pipeline.cc index 5a9ce70..7248c25 100644 --- a/src/media/base/sbplayer_pipeline.cc +++ b/src/media/base/sbplayer_pipeline.cc
@@ -649,7 +649,7 @@ bool is_encrypted = IsEncrypted(stream); SbDrmSampleInfo drm_info; - if (is_encrypted) { + if (is_encrypted && !buffer->IsEndOfStream()) { FillDrmSampleInfo(buffer, &drm_info); }
diff --git a/src/media/base/shell_video_frame_provider.cc b/src/media/base/shell_video_frame_provider.cc index e4910d2..589f886 100644 --- a/src/media/base/shell_video_frame_provider.cc +++ b/src/media/base/shell_video_frame_provider.cc
@@ -22,9 +22,8 @@ ShellVideoFrameProvider::ShellVideoFrameProvider( scoped_refptr<VideoFrame> punch_out) - : punch_out_(punch_out), has_consumed_frames_(false) { + : punch_out_(punch_out), has_consumed_frames_(false), dropped_frames_(0) { #if !defined(__LB_SHELL__FOR_RELEASE__) - dropped_frames_ = 0; max_delay_in_microseconds_ = 0; #endif // !defined(__LB_SHELL__FOR_RELEASE__) } @@ -67,24 +66,26 @@ frame_time + kEpsilonInMicroseconds >= media_time.InMicroseconds()) break; -#if !defined(__LB_SHELL__FOR_RELEASE__) - const bool kLogFrameDrops ALLOW_UNUSED = false; if (current_frame_ != frames_[0]) { ++dropped_frames_; + +#if !defined(__LB_SHELL__FOR_RELEASE__) if (media_time.InMicroseconds() - frame_time > max_delay_in_microseconds_) max_delay_in_microseconds_ = media_time.InMicroseconds() - frame_time; + const bool kLogFrameDrops ALLOW_UNUSED = false; LOG_IF(WARNING, kLogFrameDrops) << "dropped one frame with timestamp " << frames_[0]->GetTimestamp().InMicroseconds() << " at media time " << media_time.InMicroseconds() << " total dropped " << dropped_frames_ << " frames with a max delay of " << max_delay_in_microseconds_ << " ms"; - } #endif // !defined(__LB_SHELL__FOR_RELEASE__) + } if (frames_.size() == 1) { current_frame_ = frames_[0]; } + frames_.erase(frames_.begin()); has_consumed_frames_ = true; } @@ -108,6 +109,7 @@ base::AutoLock auto_lock(frames_lock_); frames_.clear(); current_frame_ = NULL; + dropped_frames_ = 0; } size_t ShellVideoFrameProvider::GetNumOfFramesCached() const { @@ -127,4 +129,11 @@ return previous_value; } +int ShellVideoFrameProvider::ResetAndReturnDroppedFrames() { + base::AutoLock auto_lock(frames_lock_); + int dropped_frames = dropped_frames_; + dropped_frames_ = 0; + return dropped_frames; +} + } // namespace media
diff --git a/src/media/base/shell_video_frame_provider.h b/src/media/base/shell_video_frame_provider.h index a26a2db..47ab8da 100644 --- a/src/media/base/shell_video_frame_provider.h +++ b/src/media/base/shell_video_frame_provider.h
@@ -64,6 +64,9 @@ // queue since the last time this was called. bool QueryAndResetHasConsumedFrames(); + // Return the value of |dropped_frames_| and reset it to 0. + int ResetAndReturnDroppedFrames(); + private: base::TimeDelta GetMediaTime_Locked() const; @@ -74,9 +77,9 @@ std::vector<scoped_refptr<VideoFrame> > frames_; scoped_refptr<VideoFrame> current_frame_; bool has_consumed_frames_; + int dropped_frames_; #if !defined(__LB_SHELL__FOR_RELEASE__) - int dropped_frames_; int max_delay_in_microseconds_; #endif // !defined(__LB_SHELL__FOR_RELEASE__)
diff --git a/src/media/filters/shell_demuxer.cc b/src/media/filters/shell_demuxer.cc index 3da9455..6671985 100644 --- a/src/media/filters/shell_demuxer.cc +++ b/src/media/filters/shell_demuxer.cc
@@ -232,27 +232,33 @@ base::Bind(&ShellDemuxer::ParseConfigDone, this, status_cb)); } -bool ShellDemuxer::ParseConfigBlocking(const PipelineStatusCB& status_cb) { +PipelineStatus ShellDemuxer::ParseConfigBlocking( + const PipelineStatusCB& status_cb) { DCHECK(blocking_thread_.message_loop_proxy()->BelongsToCurrentThread()); DCHECK(!parser_); // construct stream parser with error callback - parser_ = ShellParser::Construct(reader_, status_cb); + PipelineStatus status = ShellParser::Construct(reader_, &parser_); // if we can't construct a parser for this stream it's a fatal error, return // false so ParseConfigDone will notify the caller to Initialize() via // status_cb. - if (!parser_) { - return false; + if (!parser_ || status != PIPELINE_OK) { + DCHECK(!parser_); + DCHECK_NE(status, PIPELINE_OK); + if (status == PIPELINE_OK) { + status = DEMUXER_ERROR_COULD_NOT_PARSE; + } + return status; } // instruct the parser to extract audio and video config from the file if (!parser_->ParseConfig()) { - return false; + return DEMUXER_ERROR_COULD_NOT_PARSE; } // make sure we got a valid and complete configuration if (!parser_->IsConfigComplete()) { - return false; + return DEMUXER_ERROR_COULD_NOT_PARSE; } // IsConfigComplete() should guarantee we know the duration @@ -265,18 +271,19 @@ } // successful parse of config data, inform the nonblocking demuxer thread - return true; + DCHECK_EQ(status, PIPELINE_OK); + return PIPELINE_OK; } void ShellDemuxer::ParseConfigDone(const PipelineStatusCB& status_cb, - bool result) { + PipelineStatus status) { DCHECK(MessageLoopBelongsToCurrentThread()); // if the blocking parser thread cannot parse config we're done. - if (!result) { - status_cb.Run(DEMUXER_ERROR_COULD_NOT_PARSE); + if (status != PIPELINE_OK) { + status_cb.Run(status); return; } - + DCHECK(parser_); // start downloading data Request(DemuxerStream::AUDIO);
diff --git a/src/media/filters/shell_demuxer.h b/src/media/filters/shell_demuxer.h index c49c28e..886f7fc 100644 --- a/src/media/filters/shell_demuxer.h +++ b/src/media/filters/shell_demuxer.h
@@ -121,14 +121,15 @@ void BufferAllocated(scoped_refptr<DecoderBuffer> buffer); private: - void ParseConfigDone(const PipelineStatusCB& status_cb, bool result); + void ParseConfigDone(const PipelineStatusCB& status_cb, + PipelineStatus status); void DataSourceStopped(const base::Closure& callback); // methods that perform blocking I/O, and are therefore run on the // blocking_thread_ // download enough of the stream to parse the configuration. returns // false on error. - bool ParseConfigBlocking(const PipelineStatusCB& status_cb); + PipelineStatus ParseConfigBlocking(const PipelineStatusCB& status_cb); void RequestTask(DemuxerStream::Type type); void DownloadTask(scoped_refptr<DecoderBuffer> buffer); void IssueNextRequestTask();
diff --git a/src/media/filters/shell_flv_parser.cc b/src/media/filters/shell_flv_parser.cc index 5d517ad..4492a49 100644 --- a/src/media/filters/shell_flv_parser.cc +++ b/src/media/filters/shell_flv_parser.cc
@@ -70,28 +70,33 @@ static const int kAMF0NumberLength = 9; // static -scoped_refptr<ShellParser> ShellFLVParser::Construct( +PipelineStatus ShellFLVParser::Construct( scoped_refptr<ShellDataSourceReader> reader, const uint8* construction_header, - const PipelineStatusCB& status_cb) { + scoped_refptr<ShellParser>* parser) { + DCHECK(parser); + *parser = NULL; + // look for "FLV" string at top of file, mask off LSB uint32 FLV = endian_util::load_uint32_big_endian(construction_header) >> 8; if (FLV != kFLV) { - return NULL; + // Not an flv. + return DEMUXER_ERROR_COULD_NOT_PARSE; } // Check for availability of both an audio and video stream. Audio stream is // third bit, video stream is first bit in 5th byte of file header if ((construction_header[4] & 0x05) != 0x05) { - status_cb.Run(DEMUXER_ERROR_NO_SUPPORTED_STREAMS); - return NULL; + return DEMUXER_ERROR_NO_SUPPORTED_STREAMS; } // offset of first data tag in stream is next 4 bytes uint32 data_offset = endian_util::load_uint32_big_endian(construction_header + 5); // add four bytes to skip over PreviousTagSize0 data_offset += 4; - // construct and return an FLV parser - return scoped_refptr<ShellParser>(new ShellFLVParser(reader, data_offset)); + + // construct an FLV parser + *parser = new ShellFLVParser(reader, data_offset); + return PIPELINE_OK; } ShellFLVParser::ShellFLVParser(scoped_refptr<ShellDataSourceReader> reader,
diff --git a/src/media/filters/shell_flv_parser.h b/src/media/filters/shell_flv_parser.h index 992bee9..1f512c0 100644 --- a/src/media/filters/shell_flv_parser.h +++ b/src/media/filters/shell_flv_parser.h
@@ -28,12 +28,12 @@ class ShellFLVParser : public ShellAVCParser { public: // Attempts to make sense of the provided bytes of the top of a file as an - // flv, and if it does make sense returns a ShellFLVParser initialized with - // some basic state. If it doesn't make sense this returns NULL. - static scoped_refptr<ShellParser> Construct( - scoped_refptr<ShellDataSourceReader> reader, - const uint8* construction_header, - const PipelineStatusCB& status_cb); + // flv, and if it does make sense returns PIPELINE_OK and |*parser| contains a + // ShellFLVParser initialized with some basic state. If it doesn't make sense + // this returns an error status and |*parser| contains NULL. + static PipelineStatus Construct(scoped_refptr<ShellDataSourceReader> reader, + const uint8* construction_header, + scoped_refptr<ShellParser>* parser); ShellFLVParser(scoped_refptr<ShellDataSourceReader> reader, uint32 tag_start_offset); virtual ~ShellFLVParser();
diff --git a/src/media/filters/shell_mp4_parser.cc b/src/media/filters/shell_mp4_parser.cc index 20ea082..0360858 100644 --- a/src/media/filters/shell_mp4_parser.cc +++ b/src/media/filters/shell_mp4_parser.cc
@@ -72,34 +72,36 @@ static const int kMapTableAtomCacheEntries_ctts = 51543 / kEntrySize_ctts; // static -scoped_refptr<ShellParser> ShellMP4Parser::Construct( +PipelineStatus ShellMP4Parser::Construct( scoped_refptr<ShellDataSourceReader> reader, const uint8* construction_header, - const PipelineStatusCB& status_cb) { + scoped_refptr<ShellParser>* parser) { + DCHECK(parser); + *parser = NULL; + // detect mp4 stream by looking for ftyp atom at top of file uint32 ftyp = endian_util::load_uint32_big_endian(construction_header + 4); if (ftyp != kAtomType_ftyp) { // not an mp4 - return NULL; + return DEMUXER_ERROR_COULD_NOT_PARSE; } // first 4 bytes will be the size of the ftyp atom uint32 ftyp_atom_size = endian_util::load_uint32_big_endian(construction_header); if (ftyp_atom_size < kAtomMinSize) { - status_cb.Run(DEMUXER_ERROR_COULD_NOT_PARSE); - return NULL; + return DEMUXER_ERROR_COULD_NOT_PARSE; } - // construct and return new mp4 parser - return scoped_refptr<ShellParser>(new ShellMP4Parser(reader, ftyp_atom_size)); + // construct new mp4 parser + *parser = new ShellMP4Parser(reader, ftyp_atom_size); + return PIPELINE_OK; } ShellMP4Parser::ShellMP4Parser(scoped_refptr<ShellDataSourceReader> reader, uint32 ftyp_atom_size) : ShellAVCParser(reader), - atom_offset_(ftyp_atom_size) // start at next atom, skipping over ftyp - , + atom_offset_(ftyp_atom_size), // start at next atom, skipping over ftyp current_trak_is_video_(false), current_trak_is_audio_(false), current_trak_time_scale_(0),
diff --git a/src/media/filters/shell_mp4_parser.h b/src/media/filters/shell_mp4_parser.h index a890c2c..bf7ea68 100644 --- a/src/media/filters/shell_mp4_parser.h +++ b/src/media/filters/shell_mp4_parser.h
@@ -67,13 +67,13 @@ class ShellMP4Parser : public ShellAVCParser { public: - // attempts to make sense of the provided bytes of the top of a file as an - // mp4, and if it does make sense returns a ShellMP4Parser initialized with - // some basic state. If it doesn't make sense this returns NULL - static scoped_refptr<ShellParser> Construct( - scoped_refptr<ShellDataSourceReader> reader, - const uint8* construction_header, - const PipelineStatusCB& status_cb); + // Attempts to make sense of the provided bytes of the top of a file as an + // flv, and if it does make sense returns PIPELINE_OK and |*parser| contains a + // ShellMP4Parser initialized with some basic state. If it doesn't make sense + // this returns an error status and |*parser| contains NULL. + static PipelineStatus Construct(scoped_refptr<ShellDataSourceReader> reader, + const uint8* construction_header, + scoped_refptr<ShellParser>* parser); ShellMP4Parser(scoped_refptr<ShellDataSourceReader> reader, uint32 ftyp_atom_size); virtual ~ShellMP4Parser();
diff --git a/src/media/filters/shell_parser.cc b/src/media/filters/shell_parser.cc index b8b5c1c..f1d4958 100644 --- a/src/media/filters/shell_parser.cc +++ b/src/media/filters/shell_parser.cc
@@ -16,6 +16,7 @@ #include "media/filters/shell_parser.h" +#include "base/logging.h" #include "media/filters/shell_flv_parser.h" #include "media/filters/shell_mp4_parser.h" @@ -27,33 +28,27 @@ const int ShellParser::kInitialHeaderSize = 9; // static -scoped_refptr<ShellParser> ShellParser::Construct( +PipelineStatus ShellParser::Construct( scoped_refptr<ShellDataSourceReader> reader, - const PipelineStatusCB& status_cb) { - scoped_refptr<ShellParser> parser; + scoped_refptr<ShellParser>* parser) { + DCHECK(parser); + *parser = NULL; // download first 16 bytes of stream to determine file type and extract basic // container-specific stream configuration information uint8 header[kInitialHeaderSize]; int bytes_read = reader->BlockingRead(0, kInitialHeaderSize, header); if (bytes_read != kInitialHeaderSize) { - status_cb.Run(DEMUXER_ERROR_COULD_NOT_OPEN); - return NULL; + return DEMUXER_ERROR_COULD_NOT_PARSE; } // attempt to construct mp4 parser from this header - parser = ShellMP4Parser::Construct(reader, header, status_cb); + PipelineStatus status = ShellMP4Parser::Construct(reader, header, parser); + if (status == PIPELINE_OK) { + return status; + } // ok, attempt FLV - if (!parser) { - parser = ShellFLVParser::Construct(reader, header, status_cb); - } - // no additional supported container formats, set error and return - if (!parser) { - status_cb.Run(DEMUXER_ERROR_NO_SUPPORTED_STREAMS); - return NULL; - } - - return parser; + return ShellFLVParser::Construct(reader, header, parser); } ShellParser::ShellParser(scoped_refptr<ShellDataSourceReader> reader)
diff --git a/src/media/filters/shell_parser.h b/src/media/filters/shell_parser.h index 057cbae..6d349b0 100644 --- a/src/media/filters/shell_parser.h +++ b/src/media/filters/shell_parser.h
@@ -32,10 +32,10 @@ class ShellParser : public base::RefCountedThreadSafe<ShellParser> { public: static const int kInitialHeaderSize; - // Determine stream type, construct appropriate parser object, and return. - static scoped_refptr<ShellParser> Construct( - scoped_refptr<ShellDataSourceReader> reader, - const PipelineStatusCB& status_cb); + // Determine stream type, construct appropriate parser object, and returns + // PIPELINE_OK on success or error code. + static PipelineStatus Construct(scoped_refptr<ShellDataSourceReader> reader, + scoped_refptr<ShellParser>* parser); explicit ShellParser(scoped_refptr<ShellDataSourceReader> reader); // Seek through the file looking for audio and video configuration info,
diff --git a/src/media/filters/video_renderer_base.cc b/src/media/filters/video_renderer_base.cc index f1fa6fc..80d1f3d 100644 --- a/src/media/filters/video_renderer_base.cc +++ b/src/media/filters/video_renderer_base.cc
@@ -300,14 +300,17 @@ uint32 frames_dropped = 0; for (;;) { - if (frames_dropped > 0) { #if defined(__LB_SHELL__) || defined(COBALT) + frames_dropped = + static_cast<uint32>(frame_provider_->ResetAndReturnDroppedFrames()); + if (frames_dropped > 0) { SCOPED_MEDIA_STATISTICS(STAT_TYPE_VIDEO_FRAME_DROP); + } #endif // defined(__LB_SHELL__) || defined(COBALT) + if (frames_dropped > 0) { PipelineStatistics statistics; statistics.video_frames_dropped = frames_dropped; statistics_cb_.Run(statistics); - frames_dropped = 0; }
diff --git a/src/nb/codereview.settings b/src/nb/codereview.settings deleted file mode 100644 index a4b341a..0000000 --- a/src/nb/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/nb/memory_pool.cc b/src/nb/memory_pool.cc index a420420..840042c 100644 --- a/src/nb/memory_pool.cc +++ b/src/nb/memory_pool.cc
@@ -20,13 +20,22 @@ namespace nb { -MemoryPool::MemoryPool(void* buffer, std::size_t size, bool thread_safe) +MemoryPool::MemoryPool(void* buffer, + std::size_t size, + bool thread_safe, + bool verify_full_capacity) : no_free_allocator_(buffer, size), reuse_allocator_( scoped_ptr<Allocator>(new ReuseAllocator(&no_free_allocator_)), thread_safe) { SB_DCHECK(buffer); SB_DCHECK(size != 0U); + + if (verify_full_capacity) { + void* p = Allocate(size); + SB_DCHECK(p); + Free(p); + } } void MemoryPool::PrintAllocations() const {
diff --git a/src/nb/memory_pool.h b/src/nb/memory_pool.h index c6245b9..cef03db 100644 --- a/src/nb/memory_pool.h +++ b/src/nb/memory_pool.h
@@ -29,7 +29,22 @@ // as necessary. class MemoryPool : public Allocator { public: - MemoryPool(void* buffer, std::size_t size, bool thread_safe); + // When |verify_full_capacity| is true, the ctor tries to allocate the whole + // budget and free it immediately. This can: + // 1. Ensure the |size| is accurate after accounting for all implicit + // alignment enforced by the underlying allocators. + // 2. The |reuse_allocator_| contains a free block of the whole budget. As + // the |reuse_allocator_| doesn't support extending of free block, an + // allocation that is larger than the both biggest free block in the + // |reuse_allocator_| and the remaining memory inside the + // |no_free_allocator_| will fail even if the combination of both can + // fulfill the allocation. + // Note that when |verify_full_capacity| is true, GetHighWaterMark() always + // return the budget, which makes memory usage tracking useless. + MemoryPool(void* buffer, + std::size_t size, + bool thread_safe, + bool verify_full_capacity = false); void* Allocate(std::size_t size) { return reuse_allocator_.Allocate(size); } void* Allocate(std::size_t size, std::size_t alignment) {
diff --git a/src/nb/reuse_allocator.cc b/src/nb/reuse_allocator.cc index 8fc07cf..61a40a6 100644 --- a/src/nb/reuse_allocator.cc +++ b/src/nb/reuse_allocator.cc
@@ -98,7 +98,7 @@ } void* ReuseAllocator::Allocate(std::size_t size) { - return Allocate(size, 0); + return Allocate(size, 1); } void* ReuseAllocator::AllocateForAlignment(std::size_t size, @@ -107,6 +107,10 @@ } void* ReuseAllocator::Allocate(std::size_t size, std::size_t alignment) { + if (alignment == 0) { + alignment = 1; + } + // Try to satisfy request from free list. // First look for a block that is appropriately aligned. // If we can't, look for a block that is big enough that we can
diff --git a/src/starboard/audio_sink.h b/src/starboard/audio_sink.h index efedf24..59f507b 100644 --- a/src/starboard/audio_sink.h +++ b/src/starboard/audio_sink.h
@@ -42,6 +42,14 @@ // audio frame buffer passed to SbAudioSinkCreate as |frame_buffers|. As // |frame_buffers| is a circular buffer, |offset_in_frames| can be used to // calculate the number of continuous frames towards the end of the buffer. +// The audio sink can play the frames only when |is_playing| is true. It should +// pause the playback when |is_playing| is false. +// The audio sink may cache certain amount of audio frames before start +// playback. It will start playback immediately when |is_eos_reached| is true +// even if the amount of cached audio frames are not enough as no more frames +// will be appended into the buffer when |is_eos_reached| is true. +// It is possible for a host to set |is_eos_reached| to false after setting it +// to true, usually this is caused by a seek. // All parameters except |context| cannot be NULL. // Note that this function only reports the status of the source, it doesn't // remove audio data from the source frame buffer.
diff --git a/src/starboard/codereview.settings b/src/starboard/codereview.settings deleted file mode 100644 index a4b341a..0000000 --- a/src/starboard/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/starboard/configuration.h b/src/starboard/configuration.h index a106891..cff8fa8 100644 --- a/src/starboard/configuration.h +++ b/src/starboard/configuration.h
@@ -58,7 +58,8 @@ #define SB_IS(SB_FEATURE) (defined(SB_IS_##SB_FEATURE) && SB_IS_##SB_FEATURE) // Determines at compile-time whether this platform has a quirk. -#define SB_HAS_QUIRK(SB_FEATURE) (defined(SB_HAS_QUIRK_##SB_FEATURE) && SB_HAS_QUIRK_##SB_FEATURE) +#define SB_HAS_QUIRK(SB_FEATURE) \ + (defined(SB_HAS_QUIRK_##SB_FEATURE) && SB_HAS_QUIRK_##SB_FEATURE) // Determines at compile-time if this platform implements a given Starboard API // version number (or above). @@ -335,10 +336,6 @@ #error "Your platform must define SB_MAX_THREAD_NAME_LENGTH." #endif -#if !SB_HAS(DECODER) && !SB_HAS(PLAYER) -#error "Your platform must have either a decoder or a player (or both)." -#endif - #if SB_HAS(PLAYER) #if !SB_IS(PLAYER_COMPOSITED) && !SB_IS(PLAYER_PUNCHED_OUT) && \ !SB_IS(PLAYER_PRODUCING_TEXTURE) @@ -356,17 +353,15 @@ SB_IS(PLAYER_PRODUCING_TEXTURE) #error "Your player can't have a composition method if it doesn't exist." #endif - -#if !SB_HAS(DECODER) -#error "Your platform must have either a decoder or a player." -#endif #endif // SB_HAS(PLAYER) -#if (SB_HAS(MANY_CORES) && \ - (SB_HAS(2_CORES) || SB_HAS(4_CORES) || SB_HAS(6_CORES))) || \ - (SB_HAS(2_CORES) && (SB_HAS(4_CORES) || SB_HAS(6_CORES))) || \ +#if (SB_HAS(MANY_CORES) && (SB_HAS(1_CORE) || SB_HAS(2_CORES) || \ + SB_HAS(4_CORES) || SB_HAS(6_CORES))) || \ + (SB_HAS(1_CORE) && \ + (SB_HAS(2_CORES) || SB_HAS(4_CORES) || SB_HAS(6_CORES))) || \ + (SB_HAS(2_CORES) && (SB_HAS(4_CORES) || SB_HAS(6_CORES))) || \ (SB_HAS(4_CORES) && SB_HAS(6_CORES)) -#error "Only one of SB_HAS_{MANY, 2, 4, 6}_CORES can be defined per platform." +#error "Only one SB_HAS_{MANY, 1, 2, 4, 6}_CORE[S] can be defined per platform." #endif #if !defined(SB_PREFERRED_RGBA_BYTE_ORDER)
diff --git a/src/starboard/event.h b/src/starboard/event.h index c9f5614..5c1db49 100644 --- a/src/starboard/event.h +++ b/src/starboard/event.h
@@ -78,6 +78,19 @@ // No data argument. kSbEventTypeVerticalSync, + // The platform has detected a network disconnection. The platform should make + // a best effort to send an event of this type when the network disconnects, + // but there are likely to be cases where the platform cannot detect the + // disconnection (e.g. if the connection is via a powered hub which becomes + // disconnected), so the current network state cannot always be inferred from + // the sequence of Connect/Disconnect events. + kSbEventTypeNetworkDisconnect, + + // The platform has detected a network connection. This event may be sent at + // application start-up, and should always be sent if the network reconnects + // since a disconnection event was sent. + kSbEventTypeNetworkConnect, + // An event type reserved for scheduled callbacks. It will only be sent in // response to an application call to SbEventSchedule(), and it will call the // callback directly, so SbEventHandle should never receive this event
diff --git a/src/starboard/linux/shared/configuration_public.h b/src/starboard/linux/shared/configuration_public.h index 4a161d9..624909f 100644 --- a/src/starboard/linux/shared/configuration_public.h +++ b/src/starboard/linux/shared/configuration_public.h
@@ -234,18 +234,12 @@ // --- Media Configuration --------------------------------------------------- -// Specifies whether this platform has support for direct access to a decoder -// for at least H.264/AAC. The decoder is likely to be faster-than-realtime, and -// it is up to the client to retain decoded frames and display them synchronized -// with the audio. The decoder must be wired up to the DRM system such that it -// accepts encrypted samples. -#define SB_HAS_DECODER 0 - -// Specifies whether this platform has support for a decrypting elementary -// stream player for at least AES128-CTR/H.264/AAC. A player is responsible for -// ingesting an audio and video elementary stream, optionally-encrypted, and -// ultimately producing synchronized audio/video. If a player is defined, it -// must choose one of the supported composition methods below. +// Specifies whether this platform has support for a possibly-decrypting +// elementary stream player for at least H.264/AAC (and AES-128-CTR, if +// decrypting). A player is responsible for ingesting an audio and video +// elementary stream, optionally-encrypted, and ultimately producing +// synchronized audio/video. If a player is defined, it must choose one of the +// supported composition methods below. #define SB_HAS_PLAYER 1 // Specifies whether this platform's player will produce an OpenGL texture that
diff --git a/src/starboard/linux/x64directfb/starboard_platform.gyp b/src/starboard/linux/x64directfb/starboard_platform.gyp index 279c8d9..e692647 100644 --- a/src/starboard/linux/x64directfb/starboard_platform.gyp +++ b/src/starboard/linux/x64directfb/starboard_platform.gyp
@@ -150,8 +150,6 @@ '<(DEPTH)/starboard/shared/nouser/user_get_property.cc', '<(DEPTH)/starboard/shared/nouser/user_get_signed_in.cc', '<(DEPTH)/starboard/shared/nouser/user_internal.cc', - '<(DEPTH)/starboard/shared/nouser/user_is_age_restricted.cc', - '<(DEPTH)/starboard/shared/nouser/user_start_sign_in.cc', '<(DEPTH)/starboard/shared/posix/directory_create.cc', '<(DEPTH)/starboard/shared/posix/file_can_open.cc', '<(DEPTH)/starboard/shared/posix/file_close.cc', @@ -301,6 +299,7 @@ '<(DEPTH)/starboard/shared/stub/drm_update_session.cc', '<(DEPTH)/starboard/shared/stub/media_is_supported.cc', '<(DEPTH)/starboard/shared/stub/system_clear_platform_error.cc', + '<(DEPTH)/starboard/shared/stub/system_hide_splash_screen.cc', '<(DEPTH)/starboard/shared/stub/system_raise_platform_error.cc', ], 'include_dirs': [
diff --git a/src/starboard/linux/x64x11/configuration_public.h b/src/starboard/linux/x64x11/configuration_public.h index f11107c..2291350 100644 --- a/src/starboard/linux/x64x11/configuration_public.h +++ b/src/starboard/linux/x64x11/configuration_public.h
@@ -83,6 +83,9 @@ // wildly varying number of cores. #define SB_HAS_MANY_CORES 1 +// Whether the current platform is expected to have exactly 1 core. +#define SB_HAS_1_CORE 0 + // Whether the current platform is expected to have exactly 2 cores. #define SB_HAS_2_CORES 0
diff --git a/src/starboard/linux/x64x11/starboard_platform.gyp b/src/starboard/linux/x64x11/starboard_platform.gyp index 46ea9aa..1609af2 100644 --- a/src/starboard/linux/x64x11/starboard_platform.gyp +++ b/src/starboard/linux/x64x11/starboard_platform.gyp
@@ -113,8 +113,6 @@ '<(DEPTH)/starboard/shared/nouser/user_get_property.cc', '<(DEPTH)/starboard/shared/nouser/user_get_signed_in.cc', '<(DEPTH)/starboard/shared/nouser/user_internal.cc', - '<(DEPTH)/starboard/shared/nouser/user_is_age_restricted.cc', - '<(DEPTH)/starboard/shared/nouser/user_start_sign_in.cc', '<(DEPTH)/starboard/shared/posix/directory_create.cc', '<(DEPTH)/starboard/shared/posix/file_can_open.cc', '<(DEPTH)/starboard/shared/posix/file_close.cc', @@ -262,6 +260,7 @@ '<(DEPTH)/starboard/shared/stub/drm_update_session.cc', '<(DEPTH)/starboard/shared/stub/media_is_supported.cc', '<(DEPTH)/starboard/shared/stub/system_clear_platform_error.cc', + '<(DEPTH)/starboard/shared/stub/system_hide_splash_screen.cc', '<(DEPTH)/starboard/shared/stub/system_raise_platform_error.cc', '<(DEPTH)/starboard/shared/x11/application_x11.cc', '<(DEPTH)/starboard/shared/x11/window_create.cc',
diff --git a/src/starboard/log.h b/src/starboard/log.h index 5f3aa9f..3693925 100644 --- a/src/starboard/log.h +++ b/src/starboard/log.h
@@ -141,6 +141,7 @@ const SbLogPriority SB_LOG_WARNING = kSbLogPriorityWarning; const SbLogPriority SB_LOG_ERROR = kSbLogPriorityError; const SbLogPriority SB_LOG_FATAL = kSbLogPriorityFatal; +const SbLogPriority SB_LOG_0 = SB_LOG_ERROR; class SB_EXPORT LogMessage { public: @@ -185,6 +186,10 @@ ::starboard::logging::LogMessage(__FILE__, __LINE__, \ ::starboard::logging::SB_LOG_FATAL) +// Compatibility with base/logging.h which defines ERROR to be 0 to workaround +// some system header defines that do the same thing. +#define SB_LOG_MESSAGE_0 SB_LOG_MESSAGE_ERROR + #define SB_LOG_STREAM(severity) SB_LOG_MESSAGE_##severity.stream() #define SB_LAZY_STREAM(stream, condition) \ !(condition) ? (void)0 : ::starboard::logging::LogMessageVoidify() & (stream)
diff --git a/src/starboard/nplb/nplb.gyp b/src/starboard/nplb/nplb.gyp index 0835148..3761520 100644 --- a/src/starboard/nplb/nplb.gyp +++ b/src/starboard/nplb/nplb.gyp
@@ -190,6 +190,7 @@ 'system_get_stack_test.cc', 'system_get_total_memory_test.cc', 'system_has_capability_test.cc', + 'system_hide_splash_screen_test.cc', 'system_is_debugger_attached_test.cc', 'system_sort_test.cc', 'system_symbolize_test.cc',
diff --git a/src/starboard/nplb/system_hide_splash_screen_test.cc b/src/starboard/nplb/system_hide_splash_screen_test.cc new file mode 100644 index 0000000..a97392e --- /dev/null +++ b/src/starboard/nplb/system_hide_splash_screen_test.cc
@@ -0,0 +1,35 @@ +// 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. + +// Here we are not trying to do anything fancy, just to really sanity check that +// this is hooked up to something. + +#include "starboard/system.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace starboard { +namespace nplb { +namespace { + +TEST(SbSystemHideSplashScreenTest, SunnyDay) { + // Function returns no result, and correct execution cannot be determined + // programatically, but we should at least be able to call it twice without + // crashing. + SbSystemHideSplashScreen(); + SbSystemHideSplashScreen(); +} + +} // namespace +} // namespace nplb +} // namespace starboard
diff --git a/src/starboard/raspi/1/configuration_public.h b/src/starboard/raspi/1/configuration_public.h index df2d8bf..3cedc59 100644 --- a/src/starboard/raspi/1/configuration_public.h +++ b/src/starboard/raspi/1/configuration_public.h
@@ -71,7 +71,10 @@ // Whether the current platform is expected to have many cores (> 6), or a // wildly varying number of cores. -#define SB_HAS_MANY_CORES 1 +#define SB_HAS_MANY_CORES 0 + +// Whether the current platform is expected to have exactly 1 core. +#define SB_HAS_1_CORE 1 // Whether the current platform is expected to have exactly 2 cores. #define SB_HAS_2_CORES 0
diff --git a/src/starboard/raspi/1/starboard_platform.gyp b/src/starboard/raspi/1/starboard_platform.gyp index 1b80d83..7206d0c 100644 --- a/src/starboard/raspi/1/starboard_platform.gyp +++ b/src/starboard/raspi/1/starboard_platform.gyp
@@ -120,8 +120,6 @@ '<(DEPTH)/starboard/shared/nouser/user_get_property.cc', '<(DEPTH)/starboard/shared/nouser/user_get_signed_in.cc', '<(DEPTH)/starboard/shared/nouser/user_internal.cc', - '<(DEPTH)/starboard/shared/nouser/user_is_age_restricted.cc', - '<(DEPTH)/starboard/shared/nouser/user_start_sign_in.cc', '<(DEPTH)/starboard/shared/posix/directory_create.cc', '<(DEPTH)/starboard/shared/posix/file_can_open.cc', '<(DEPTH)/starboard/shared/posix/file_close.cc', @@ -269,6 +267,7 @@ '<(DEPTH)/starboard/shared/stub/drm_update_session.cc', '<(DEPTH)/starboard/shared/stub/media_is_supported.cc', '<(DEPTH)/starboard/shared/stub/system_clear_platform_error.cc', + '<(DEPTH)/starboard/shared/stub/system_hide_splash_screen.cc', '<(DEPTH)/starboard/shared/stub/system_raise_platform_error.cc', ], 'defines': [
diff --git a/src/starboard/raspi/shared/configuration_public.h b/src/starboard/raspi/shared/configuration_public.h index de26224..b7ba3a6 100644 --- a/src/starboard/raspi/shared/configuration_public.h +++ b/src/starboard/raspi/shared/configuration_public.h
@@ -229,18 +229,12 @@ // --- Media Configuration --------------------------------------------------- -// Specifies whether this platform has support for direct access to a decoder -// for at least H.264/AAC. The decoder is likely to be faster-than-realtime, and -// it is up to the client to retain decoded frames and display them synchronized -// with the audio. The decoder must be wired up to the DRM system such that it -// accepts encrypted samples. -#define SB_HAS_DECODER 0 - -// Specifies whether this platform has support for a decrypting elementary -// stream player for at least AES128-CTR/H.264/AAC. A player is responsible for -// ingesting an audio and video elementary stream, optionally-encrypted, and -// ultimately producing synchronized audio/video. If a player is defined, it -// must choose one of the supported composition methods below. +// Specifies whether this platform has support for a possibly-decrypting +// elementary stream player for at least H.264/AAC (and AES-128-CTR, if +// decrypting). A player is responsible for ingesting an audio and video +// elementary stream, optionally-encrypted, and ultimately producing +// synchronized audio/video. If a player is defined, it must choose one of the +// supported composition methods below. #define SB_HAS_PLAYER 1 // Specifies whether this platform's player will produce an OpenGL texture that
diff --git a/src/starboard/shared/alsa/alsa_audio_sink_type.cc b/src/starboard/shared/alsa/alsa_audio_sink_type.cc index 5a89222..8f2ce61 100644 --- a/src/starboard/shared/alsa/alsa_audio_sink_type.cc +++ b/src/starboard/shared/alsa/alsa_audio_sink_type.cc
@@ -14,10 +14,13 @@ #include "starboard/shared/alsa/alsa_audio_sink_type.h" +#include <alsa/asoundlib.h> + #include <algorithm> #include <vector> #include "starboard/condition_variable.h" +#include "starboard/memory.h" #include "starboard/mutex.h" #include "starboard/shared/alsa/alsa_util.h" #include "starboard/thread.h" @@ -49,6 +52,23 @@ // that is too large can waste some memory as the extra buffer is never used. const int kALSABufferSizeInFrames = 8192; +// 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_t); + } + SB_NOTREACHED(); + return 0u; +} + +void* IncrementPointerByBytes(void* pointer, size_t offset) { + return static_cast<void*>(static_cast<uint8_t*>(pointer) + offset); +} + // This class is an ALSA based audio sink with the following features: // 1. It doesn't cache any data internally and maintains minimum data inside // the ALSA buffer. It relies on pulling data from its source in high @@ -61,6 +81,7 @@ AlsaAudioSink(Type* type, int channels, int sampling_frequency_hz, + SbMediaAudioSampleType sample_type, SbAudioSinkFrameBuffers frame_buffers, int frames_per_channel, SbAudioSinkUpdateSourceStatusFunc update_source_status_func, @@ -95,6 +116,7 @@ int channels_; int sampling_frequency_hz_; + SbMediaAudioSampleType sample_type_; SbThread audio_out_thread_; starboard::Mutex mutex_; @@ -104,9 +126,9 @@ bool destroying_; - float* frame_buffer_; + void* frame_buffer_; int frames_per_channel_; - std::vector<float> silence_frames_; + void* silence_frames_; void* playback_handle_; }; @@ -115,6 +137,7 @@ Type* type, int channels, int sampling_frequency_hz, + SbMediaAudioSampleType sample_type, SbAudioSinkFrameBuffers frame_buffers, int frames_per_channel, SbAudioSinkUpdateSourceStatusFunc update_source_status_func, @@ -123,6 +146,7 @@ : type_(type), channels_(channels), sampling_frequency_hz_(sampling_frequency_hz), + sample_type_(sample_type), update_source_status_func_(update_source_status_func), consume_frame_func_(consume_frame_func), context_(context), @@ -131,19 +155,23 @@ time_to_wait_(kFramesPerRequest * kSbTimeSecond / sampling_frequency_hz / 2), destroying_(false), - frame_buffer_(reinterpret_cast<float*>(frame_buffers[0])), + frame_buffer_(frame_buffers[0]), frames_per_channel_(frames_per_channel), - silence_frames_(channels * kFramesPerRequest), + silence_frames_(new uint8_t[channels * kFramesPerRequest * + GetSampleSize(sample_type)]), playback_handle_(NULL) { SB_DCHECK(update_source_status_func_); SB_DCHECK(consume_frame_func_); SB_DCHECK(frame_buffer_); + SB_DCHECK(SbAudioSinkIsAudioSampleTypeSupported(sample_type_)); ScopedLock lock(mutex_); audio_out_thread_ = SbThreadCreate(0, kSbThreadPriorityRealTime, kSbThreadNoAffinity, true, "alsa_audio_out", &AlsaAudioSink::ThreadEntryPoint, this); SB_DCHECK(SbThreadIsValid(audio_out_thread_)); + SbMemorySet(silence_frames_, 0, + channels * kFramesPerRequest * GetSampleSize(sample_type)); creation_signal_.Wait(); } @@ -153,6 +181,8 @@ destroying_ = true; } SbThreadJoin(audio_out_thread_, NULL); + + delete[] static_cast<uint8_t*>(silence_frames_); } // static @@ -165,9 +195,13 @@ } void AlsaAudioSink::AudioThreadFunc() { + snd_pcm_format_t alsa_sample_type = + sample_type_ == kSbMediaAudioSampleTypeFloat32 ? SND_PCM_FORMAT_FLOAT_LE + : SND_PCM_FORMAT_S16; + playback_handle_ = starboard::shared::alsa::AlsaOpenPlaybackDevice( channels_, sampling_frequency_hz_, kFramesPerRequest, - kALSABufferSizeInFrames); + kALSABufferSizeInFrames, alsa_sample_type); creation_signal_.Signal(); if (!playback_handle_) { return; @@ -206,7 +240,7 @@ } int delayed_frame = AlsaGetBufferedFrames(playback_handle_); if (delayed_frame < kMinimumFramesInALSA) { - AlsaWriteFrames(playback_handle_, &silence_frames_[0], kFramesPerRequest); + AlsaWriteFrames(playback_handle_, silence_frames_, kFramesPerRequest); } else { SbThreadSleep(time_to_wait_); } @@ -255,9 +289,11 @@ int frames_to_buffer_end = frames_per_channel_ - offset_in_frames; if (frames_to_write > frames_to_buffer_end) { - int consumed = AlsaWriteFrames(playback_handle_, - frame_buffer_ + offset_in_frames * channels_, - frames_to_buffer_end); + int consumed = AlsaWriteFrames( + playback_handle_, + IncrementPointerByBytes(frame_buffer_, offset_in_frames * channels_ * + GetSampleSize(sample_type_)), + frames_to_buffer_end); consume_frame_func_(consumed, context_); if (consumed != frames_to_buffer_end) { return; @@ -267,9 +303,11 @@ offset_in_frames = 0; } - int consumed = AlsaWriteFrames(playback_handle_, - frame_buffer_ + offset_in_frames * channels_, - frames_to_write); + int consumed = AlsaWriteFrames( + playback_handle_, + IncrementPointerByBytes(frame_buffer_, offset_in_frames * channels_ * + GetSampleSize(sample_type_)), + frames_to_write); consume_frame_func_(consumed, context_); } @@ -286,8 +324,9 @@ SbAudioSinkConsumeFramesFunc consume_frames_func, void* context) { AlsaAudioSink* audio_sink = new AlsaAudioSink( - this, channels, sampling_frequency_hz, frame_buffers, frames_per_channel, - update_source_status_func, consume_frames_func, context); + this, channels, sampling_frequency_hz, audio_sample_type, frame_buffers, + frames_per_channel, update_source_status_func, consume_frames_func, + context); if (!audio_sink->is_valid()) { delete audio_sink; return kSbAudioSinkInvalid;
diff --git a/src/starboard/shared/alsa/alsa_util.cc b/src/starboard/shared/alsa/alsa_util.cc index 6638e81..c713015 100644 --- a/src/starboard/shared/alsa/alsa_util.cc +++ b/src/starboard/shared/alsa/alsa_util.cc
@@ -92,7 +92,11 @@ void* AlsaOpenPlaybackDevice(int channel, int sample_rate, int frames_per_request, - int buffer_size_in_frames) { + int buffer_size_in_frames, + snd_pcm_format_t sample_type) { + SB_DCHECK(sample_type == SND_PCM_FORMAT_FLOAT_LE || + sample_type == SND_PCM_FORMAT_S16); + PcmHandle playback_handle; int error = snd_pcm_open(&playback_handle, "default", SND_PCM_STREAM_PLAYBACK, 0); @@ -111,8 +115,7 @@ SND_PCM_ACCESS_RW_INTERLEAVED); ALSA_CHECK(error, snd_pcm_hw_params_set_access, NULL); - error = snd_pcm_hw_params_set_format(playback_handle, hw_params, - SND_PCM_FORMAT_FLOAT_LE); + error = snd_pcm_hw_params_set_format(playback_handle, hw_params, sample_type); ALSA_CHECK(error, snd_pcm_hw_params_set_format, NULL); error = @@ -159,7 +162,7 @@ } int AlsaWriteFrames(void* playback_handle, - const float* buffer, + const void* buffer, int frames_to_write) { if (frames_to_write == 0) { return 0;
diff --git a/src/starboard/shared/alsa/alsa_util.h b/src/starboard/shared/alsa/alsa_util.h index 9cfe472..bbbe04f 100644 --- a/src/starboard/shared/alsa/alsa_util.h +++ b/src/starboard/shared/alsa/alsa_util.h
@@ -15,6 +15,8 @@ #ifndef STARBOARD_SHARED_ALSA_ALSA_UTIL_H_ #define STARBOARD_SHARED_ALSA_ALSA_UTIL_H_ +#include <alsa/asoundlib.h> + #include "starboard/shared/internal_only.h" namespace starboard { @@ -26,10 +28,11 @@ void* AlsaOpenPlaybackDevice(int channel, int sample_rate, int frames_per_request, - int buffer_size_in_frames); + int buffer_size_in_frames, + snd_pcm_format_t sample_type); bool AlsaStartPlay(void* playback_handle); int AlsaWriteFrames(void* playback_handle, - const float* buffer, + const void* buffer, int frames_to_write); int AlsaGetBufferedFrames(void* playback_handle); void AlsaCloseDevice(void* playback_handle);
diff --git a/src/starboard/shared/linux/page_internal.cc b/src/starboard/shared/linux/page_internal.cc index 5aec2ed..8b84135 100644 --- a/src/starboard/shared/linux/page_internal.cc +++ b/src/starboard/shared/linux/page_internal.cc
@@ -44,10 +44,12 @@ mmap_protect |= PROT_WRITE; flag_set = true; } +#if SB_CAN(MAP_EXECUTABLE_MEMORY) if (sb_flags & kSbMemoryMapProtectExec) { mmap_protect |= PROT_EXEC; flag_set = true; } +#endif if (!flag_set) { mmap_protect = PROT_NONE; }
diff --git a/src/starboard/shared/pthread/thread_create.cc b/src/starboard/shared/pthread/thread_create.cc index 813d3ac..70a1fdb 100644 --- a/src/starboard/shared/pthread/thread_create.cc +++ b/src/starboard/shared/pthread/thread_create.cc
@@ -63,6 +63,14 @@ return kSbThreadInvalid; } +#if defined(ADDRESS_SANITIZER) + // Set a big thread stack size when in ADDRESS_SANITIZER mode. + // This eliminates buffer overflows for deeply nested callstacks. + if (stack_size == 0) { + stack_size = 4096 * 1024; // 4MB + } +#endif + pthread_attr_t attributes; int result = pthread_attr_init(&attributes); if (!IsSuccess(result)) {
diff --git a/src/starboard/shared/signal/crash_signals.cc b/src/starboard/shared/signal/crash_signals.cc index 2ea26a7..5c20870 100644 --- a/src/starboard/shared/signal/crash_signals.cc +++ b/src/starboard/shared/signal/crash_signals.cc
@@ -61,13 +61,13 @@ void InstallCrashSignalHandlers() { for (int i = 0; i < SB_ARRAY_SIZE_INT(kSignalsToTrap); ++i) { - ::signal(i, &DumpStackSignalSafe); + ::signal(kSignalsToTrap[i], &DumpStackSignalSafe); } } void UninstallCrashSignalHandlers() { for (int i = 0; i < SB_ARRAY_SIZE_INT(kSignalsToTrap); ++i) { - ::signal(i, SIG_DFL); + ::signal(kSignalsToTrap[i], SIG_DFL); } }
diff --git a/src/starboard/shared/stub/user_start_sign_in.cc b/src/starboard/shared/stub/system_hide_splash_screen.cc similarity index 90% rename from src/starboard/shared/stub/user_start_sign_in.cc rename to src/starboard/shared/stub/system_hide_splash_screen.cc index 9a99a99..cccc8d5 100644 --- a/src/starboard/shared/stub/user_start_sign_in.cc +++ b/src/starboard/shared/stub/system_hide_splash_screen.cc
@@ -12,7 +12,6 @@ // See the License for the specific language governing permissions and // limitations under the License. -#include "starboard/user.h" +#include "starboard/system.h" -void SbUserStartSignIn() { -} +void SbSystemHideSplashScreen() {}
diff --git a/src/starboard/shared/stub/user_is_age_restricted.cc b/src/starboard/shared/stub/user_is_age_restricted.cc deleted file mode 100644 index a875b2a..0000000 --- a/src/starboard/shared/stub/user_is_age_restricted.cc +++ /dev/null
@@ -1,19 +0,0 @@ -// Copyright 2016 Google Inc. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "starboard/user.h" - -bool SbUserIsAgeRestricted(SbUser /*user*/) { - return false; -}
diff --git a/src/starboard/stub/configuration_public.h b/src/starboard/stub/configuration_public.h index 744c7d5..af9c671 100644 --- a/src/starboard/stub/configuration_public.h +++ b/src/starboard/stub/configuration_public.h
@@ -73,6 +73,9 @@ // wildly varying number of cores. #define SB_HAS_MANY_CORES 1 +// Whether the current platform is expected to have exactly 1 core. +#define SB_HAS_1_CORE 0 + // Whether the current platform is expected to have exactly 2 cores. #define SB_HAS_2_CORES 0 @@ -299,18 +302,12 @@ // --- Media Configuration --------------------------------------------------- -// Specifies whether this platform has support for direct access to a decoder -// for at least H.264/AAC. The decoder is likely to be faster-than-realtime, and -// it is up to the client to retain decoded frames and display them synchronized -// with the audio. The decoder must be wired up to the DRM system such that it -// accepts encrypted samples. -#define SB_HAS_DECODER 0 - -// Specifies whether this platform has support for a decrypting elementary -// stream player for at least AES128-CTR/H.264/AAC. A player is responsible for -// ingesting an audio and video elementary stream, optionally-encrypted, and -// ultimately producing synchronized audio/video. If a player is defined, it -// must choose one of the supported composition methods below. +// Specifies whether this platform has support for a possibly-decrypting +// elementary stream player for at least H.264/AAC (and AES-128-CTR, if +// decrypting). A player is responsible for ingesting an audio and video +// elementary stream, optionally-encrypted, and ultimately producing +// synchronized audio/video. If a player is defined, it must choose one of the +// supported composition methods below. #define SB_HAS_PLAYER 1 // Specifies whether this platform's player will produce an OpenGL texture that
diff --git a/src/starboard/stub/starboard_platform.gyp b/src/starboard/stub/starboard_platform.gyp index 1279317..e871191 100644 --- a/src/starboard/stub/starboard_platform.gyp +++ b/src/starboard/stub/starboard_platform.gyp
@@ -184,6 +184,7 @@ '<(DEPTH)/starboard/shared/stub/system_get_stack.cc', '<(DEPTH)/starboard/shared/stub/system_get_total_memory.cc', '<(DEPTH)/starboard/shared/stub/system_has_capability.cc', + '<(DEPTH)/starboard/shared/stub/system_hide_splash_screen.cc', '<(DEPTH)/starboard/shared/stub/system_is_debugger_attached.cc', '<(DEPTH)/starboard/shared/stub/system_raise_platform_error.cc', '<(DEPTH)/starboard/shared/stub/system_request_stop.cc', @@ -212,8 +213,6 @@ '<(DEPTH)/starboard/shared/stub/user_get_current.cc', '<(DEPTH)/starboard/shared/stub/user_get_property.cc', '<(DEPTH)/starboard/shared/stub/user_get_signed_in.cc', - '<(DEPTH)/starboard/shared/stub/user_is_age_restricted.cc', - '<(DEPTH)/starboard/shared/stub/user_start_sign_in.cc', '<(DEPTH)/starboard/shared/stub/window_create.cc', '<(DEPTH)/starboard/shared/stub/window_destroy.cc', '<(DEPTH)/starboard/shared/stub/window_get_platform_handle.cc',
diff --git a/src/starboard/system.h b/src/starboard/system.h index 616d421..5cdad66 100644 --- a/src/starboard/system.h +++ b/src/starboard/system.h
@@ -365,6 +365,11 @@ size_t element_width, SbSystemComparator comparator); +// Hides the system splash screen, on systems that support a splash screen that +// is displayed while the application is loading. This function may be called +// from any thread and must be idempotent. +SB_EXPORT void SbSystemHideSplashScreen(); + #ifdef __cplusplus } // extern "C" #endif
diff --git a/src/starboard/user.h b/src/starboard/user.h index 9dd1e1a..bf9a5d4 100644 --- a/src/starboard/user.h +++ b/src/starboard/user.h
@@ -96,10 +96,6 @@ // will persist for the lifetime of the app. SB_EXPORT SbUser SbUserGetCurrent(); -// Returns whether |user| is age-restricted according to the platform's age -// policies. -SB_EXPORT bool SbUserIsAgeRestricted(SbUser user); - // Gets the size of the value of |property_id| for |user|, INCLUDING the // terminating null character. Returns 0 if if |user| is invalid, |property_id| // isn't recognized, supported, or set for |user|. @@ -113,10 +109,6 @@ char* out_value, int value_size); -// Begins the user sign-in flow for the given platform, which may result in a -// user changed event being dispatched. -SB_EXPORT void SbUserStartSignIn(); - #if SB_HAS(USER_APPLICATION_LINKING_SUPPORT) // Initiates a process to link |user| with a per-application authentication // token. On success, |out_token| is populated with the authentication token
diff --git a/src/testing/gmock/codereview.settings b/src/testing/gmock/codereview.settings deleted file mode 100644 index a4b341a..0000000 --- a/src/testing/gmock/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/testing/gtest-parallel/LICENSE b/src/testing/gtest-parallel/LICENSE new file mode 100644 index 0000000..d645695 --- /dev/null +++ b/src/testing/gtest-parallel/LICENSE
@@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + 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.
diff --git a/src/testing/gtest-parallel/README.cobalt b/src/testing/gtest-parallel/README.cobalt new file mode 100644 index 0000000..0d388eb --- /dev/null +++ b/src/testing/gtest-parallel/README.cobalt
@@ -0,0 +1,59 @@ +Name: gtest-parallel +URL: https://github.com/google/gtest-parallel +Version: 0 +License: Apache 2.0 +Security Critical: no + +Description + This directory contains the source code of a python project that helps run + gtest binaries in parallel using multiple processes. + +How to use + Pre-reqs: Python (2) + 1. ./gtest-parallel <name-of-gtest-binary> + + for additional options, see ./gtest-parallel --help + + If all the tests pass, you will be see one line on the screen get updated. + If a test fails, it will print out the test result and scroll a little bit. + + Example: $ ./gtest-parallel ~/cobalt/src/out/linux-x64x11_debug/layout_tests + [436/436] BidiLayoutTests/LayoutTest.LayoutTest/1 (1285 ms) + +Troubleshooting + 1. Make sure that the gtest-parallel script is executable: + chmod +x ./gtest-parallel + +Source +1. a) The external repo was imported into our git server on lbshell-internal, + repo name is gtest-parallel + b) A new branch was created with the date of last commit + c) Then it was pushed to the COBALT branch + + Steps for step 1.b: + $ git clone https://lbshell-internal.googlesource.com/testing/gtest-parallel + $ cd gtest-parallel/ + $ git remote add upstream https://github.com/google/gtest-parallel.git + $ git fetch upstream + $ git checkout -b 20160803 upstream/master + $ git push origin + + You will likely need admin permissions on the repo to execute the git push. + +2. A patch was applied since gtest now prints some things to stderr instead of + stdout. + + $ patch < patches/stderr_out.patch + +FAQ +1. Do the tests need to be thread safe? + + No, the script first asks the binary for the list of tests, and then splits + them across multiple processes. + +Patches +1. patches/stderr_out.patch + + Starboard redirects some output from stdout to stderr. + Therefore, we needed to modify the the gtest-parallel script to parse stderr + instead of stdout.
diff --git a/src/testing/gtest-parallel/gtest-parallel b/src/testing/gtest-parallel/gtest-parallel new file mode 100755 index 0000000..a258a87 --- /dev/null +++ b/src/testing/gtest-parallel/gtest-parallel
@@ -0,0 +1,411 @@ +#!/usr/bin/env python2 +# Copyright 2013 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. +import cPickle +import errno +import gzip +import multiprocessing +import optparse +import os +import signal +import subprocess +import sys +import tempfile +import thread +import threading +import time +import zlib + +# An object that catches SIGINT sent to the Python process and notices +# if processes passed to wait() die by SIGINT (we need to look for +# both of those cases, because pressing Ctrl+C can result in either +# the main process or one of the subprocesses getting the signal). +# +# Before a SIGINT is seen, wait(p) will simply call p.wait() and +# return the result. Once a SIGINT has been seen (in the main process +# or a subprocess, including the one the current call is waiting for), +# wait(p) will call p.terminate() and raise ProcessWasInterrupted. +class SigintHandler(object): + class ProcessWasInterrupted(Exception): pass + sigint_returncodes = {-signal.SIGINT, # Unix + -1073741510, # Windows + } + def __init__(self): + self.__lock = threading.Lock() + self.__processes = set() + self.__got_sigint = False + signal.signal(signal.SIGINT, self.__sigint_handler) + def __on_sigint(self): + self.__got_sigint = True + while self.__processes: + try: + self.__processes.pop().terminate() + except OSError: + pass + def __sigint_handler(self, signal_num, frame): + with self.__lock: + self.__on_sigint() + def got_sigint(self): + with self.__lock: + return self.__got_sigint + def wait(self, p): + with self.__lock: + if self.__got_sigint: + p.terminate() + self.__processes.add(p) + code = p.wait() + with self.__lock: + self.__processes.discard(p) + if code in self.sigint_returncodes: + self.__on_sigint() + if self.__got_sigint: + raise self.ProcessWasInterrupted + return code +sigint_handler = SigintHandler() + +# Return the width of the terminal, or None if it couldn't be +# determined (e.g. because we're not being run interactively). +def term_width(out): + if not out.isatty(): + return None + try: + p = subprocess.Popen(["stty", "size"], + stdout=subprocess.PIPE, stderr=subprocess.PIPE) + (out, err) = p.communicate() + if p.returncode != 0 or err: + return None + return int(out.split()[1]) + except (IndexError, OSError, ValueError): + return None + +# Output transient and permanent lines of text. If several transient +# lines are written in sequence, the new will overwrite the old. We +# use this to ensure that lots of unimportant info (tests passing) +# won't drown out important info (tests failing). +class Outputter(object): + def __init__(self, out_file): + self.__out_file = out_file + self.__previous_line_was_transient = False + self.__width = term_width(out_file) # Line width, or None if not a tty. + def transient_line(self, msg): + if self.__width is None: + self.__out_file.write(msg + "\n") + else: + self.__out_file.write("\r" + msg[:self.__width].ljust(self.__width)) + self.__previous_line_was_transient = True + def flush_transient_output(self): + if self.__previous_line_was_transient: + self.__out_file.write("\n") + self.__previous_line_was_transient = False + def permanent_line(self, msg): + self.flush_transient_output() + self.__out_file.write(msg + "\n") + +stdout_lock = threading.Lock() + +class FilterFormat: + if sys.stdout.isatty(): + # stdout needs to be unbuffered since the output is interactive. + sys.stdout = os.fdopen(sys.stdout.fileno(), 'w', 0) + + out = Outputter(sys.stdout) + total_tests = 0 + finished_tests = 0 + + tests = {} + outputs = {} + failures = [] + + def print_test_status(self, last_finished_test, time_ms): + self.out.transient_line("[%d/%d] %s (%d ms)" + % (self.finished_tests, self.total_tests, + last_finished_test, time_ms)) + + def handle_meta(self, job_id, args): + (command, arg) = args.split(' ', 1) + if command == "TEST": + (binary, test) = arg.split(' ', 1) + self.tests[job_id] = (binary, test.strip()) + elif command == "EXIT": + (exit_code, time_ms) = [int(x) for x in arg.split(' ', 1)] + self.finished_tests += 1 + (binary, test) = self.tests[job_id] + self.print_test_status(test, time_ms) + if exit_code != 0: + self.failures.append(self.tests[job_id]) + with open(self.outputs[job_id]) as f: + for line in f.readlines(): + self.out.permanent_line(line.rstrip()) + self.out.permanent_line( + "[%d/%d] %s returned/aborted with exit code %d (%d ms)" + % (self.finished_tests, self.total_tests, test, exit_code, time_ms)) + elif command == "TESTCNT": + self.total_tests = int(arg.split(' ', 1)[1]) + self.out.transient_line("[0/%d] Running tests..." % self.total_tests) + + def logfile(self, job_id, name): + self.outputs[job_id] = name + + def log(self, line): + stdout_lock.acquire() + (prefix, output) = line.split(' ', 1) + + assert prefix[-1] == ':' + self.handle_meta(int(prefix[:-1]), output) + stdout_lock.release() + + def end(self): + if self.failures: + self.out.permanent_line("FAILED TESTS (%d/%d):" + % (len(self.failures), self.total_tests)) + for (binary, test) in self.failures: + self.out.permanent_line(" " + binary + ": " + test) + self.out.flush_transient_output() + +class RawFormat: + def log(self, line): + stdout_lock.acquire() + sys.stdout.write(line + "\n") + sys.stdout.flush() + stdout_lock.release() + def logfile(self, job_id, name): + with open(name) as f: + for line in f.readlines(): + self.log(str(job_id) + '> ' + line.rstrip()) + def end(self): + pass + +# Record of test runtimes. Has built-in locking. +class TestTimes(object): + def __init__(self, save_file): + "Create new object seeded with saved test times from the given file." + self.__times = {} # (test binary, test name) -> runtime in ms + + # Protects calls to record_test_time(); other calls are not + # expected to be made concurrently. + self.__lock = threading.Lock() + + try: + with gzip.GzipFile(save_file, "rb") as f: + times = cPickle.load(f) + except (EOFError, IOError, cPickle.UnpicklingError, zlib.error): + # File doesn't exist, isn't readable, is malformed---whatever. + # Just ignore it. + return + + # Discard saved times if the format isn't right. + if type(times) is not dict: + return + for ((test_binary, test_name), runtime) in times.items(): + if (type(test_binary) is not str or type(test_name) is not str + or type(runtime) not in {int, long, type(None)}): + return + + self.__times = times + + def get_test_time(self, binary, testname): + """Return the last duration for the given test as an integer number of + milliseconds, or None if the test failed or if there's no record for it.""" + return self.__times.get((binary, testname), None) + + def record_test_time(self, binary, testname, runtime_ms): + """Record that the given test ran in the specified number of + milliseconds. If the test failed, runtime_ms should be None.""" + with self.__lock: + self.__times[(binary, testname)] = runtime_ms + + def write_to_file(self, save_file): + "Write all the times to file." + try: + with open(save_file, "wb") as f: + with gzip.GzipFile("", "wb", 9, f) as gzf: + cPickle.dump(self.__times, gzf, cPickle.HIGHEST_PROTOCOL) + except IOError: + pass # ignore errors---saving the times isn't that important + +# Remove additional arguments (anything after --). +additional_args = [] + +for i in range(len(sys.argv)): + if sys.argv[i] == '--': + additional_args = sys.argv[i+1:] + sys.argv = sys.argv[:i] + break + +parser = optparse.OptionParser( + usage = 'usage: %prog [options] binary [binary ...] -- [additional args]') + +parser.add_option('-d', '--output_dir', type='string', + default=os.path.join(tempfile.gettempdir(), "gtest-parallel"), + help='output directory for test logs') +parser.add_option('-r', '--repeat', type='int', default=1, + help='repeat tests') +parser.add_option('--failed', action='store_true', default=False, + help='run only failed and new tests') +parser.add_option('-w', '--workers', type='int', + default=multiprocessing.cpu_count(), + help='number of workers to spawn') +parser.add_option('--gtest_color', type='string', default='yes', + help='color output') +parser.add_option('--gtest_filter', type='string', default='', + help='test filter') +parser.add_option('--gtest_also_run_disabled_tests', action='store_true', + default=False, help='run disabled tests too') +parser.add_option('--format', type='string', default='filter', + help='output format (raw,filter)') +parser.add_option('--print_test_times', action='store_true', default=False, + help='When done, list the run time of each test') + +(options, binaries) = parser.parse_args() + +if binaries == []: + parser.print_usage() + sys.exit(1) + +logger = RawFormat() +if options.format == 'raw': + pass +elif options.format == 'filter': + logger = FilterFormat() +else: + sys.exit("Unknown output format: " + options.format) + +# Find tests. +save_file = os.path.join(os.path.expanduser("~"), ".gtest-parallel-times") +times = TestTimes(save_file) +tests = [] +for test_binary in binaries: + command = [test_binary] + if options.gtest_also_run_disabled_tests: + command += ['--gtest_also_run_disabled_tests'] + + list_command = list(command) + if options.gtest_filter != '': + list_command += ['--gtest_filter=' + options.gtest_filter] + + try: + test_list = subprocess.Popen(list_command + ['--gtest_list_tests'], + stderr=subprocess.PIPE).communicate()[1] + except OSError as e: + sys.exit("%s: %s" % (test_binary, str(e))) + + command += additional_args + + test_group = '' + for line in test_list.split('\n'): + if not line.strip(): + continue + if line[0] != " ": + # Remove comments for typed tests and strip whitespace. + test_group = line.split('#')[0].strip() + continue + # Remove comments for parameterized tests and strip whitespace. + line = line.split('#')[0].strip() + if not line: + continue + + test = test_group + line + if not options.gtest_also_run_disabled_tests and 'DISABLED_' in test: + continue + tests.append((times.get_test_time(test_binary, test), + test_binary, test, command)) + +if options.failed: + # The first element of each entry is the runtime of the most recent + # run if it was successful, or None if the test is new or the most + # recent run failed. + tests = [x for x in tests if x[0] is None] + +# Sort tests by falling runtime (with None, which is what we get for +# new and failing tests, being considered larger than any real +# runtime). +tests.sort(reverse=True, key=lambda x: ((1 if x[0] is None else 0), x)) + +# Repeat tests (-r flag). +tests *= options.repeat +test_lock = threading.Lock() +job_id = 0 +logger.log(str(-1) + ': TESTCNT ' + ' ' + str(len(tests))) + +exit_code = 0 + +# Create directory for test log output. +try: + os.makedirs(options.output_dir) +except OSError as e: + # Ignore errors if this directory already exists. + if e.errno != errno.EEXIST or not os.path.isdir(options.output_dir): + raise e +# Remove files from old test runs. +for logfile in os.listdir(options.output_dir): + os.remove(os.path.join(options.output_dir, logfile)) + +# Run the specified job. Return the elapsed time in milliseconds if +# the job succeeds, or None if the job fails. (This ensures that +# failing tests will run first the next time.) +def run_job((command, job_id, test)): + begin = time.time() + + with tempfile.NamedTemporaryFile(dir=options.output_dir, delete=False) as log: + sub = subprocess.Popen(command + ['--gtest_filter=' + test] + + ['--gtest_color=' + options.gtest_color], + stdout=log.file, + stderr=log.file) + try: + code = sigint_handler.wait(sub) + except sigint_handler.ProcessWasInterrupted: + thread.exit() + runtime_ms = int(1000 * (time.time() - begin)) + logger.logfile(job_id, log.name) + + logger.log("%s: EXIT %s %d" % (job_id, code, runtime_ms)) + if code == 0: + return runtime_ms + global exit_code + exit_code = code + return None + +def worker(): + global job_id + while True: + job = None + test_lock.acquire() + if job_id < len(tests): + (_, test_binary, test, command) = tests[job_id] + logger.log(str(job_id) + ': TEST ' + test_binary + ' ' + test) + job = (command, job_id, test) + job_id += 1 + test_lock.release() + if job is None: + return + times.record_test_time(test_binary, test, run_job(job)) + +def start_daemon(func): + t = threading.Thread(target=func) + t.daemon = True + t.start() + return t + +workers = [start_daemon(worker) for i in range(options.workers)] + +[t.join() for t in workers] +logger.end() +times.write_to_file(save_file) +if options.print_test_times: + ts = sorted((times.get_test_time(test_binary, test), test_binary, test) + for (_, test_binary, test, _) in tests + if times.get_test_time(test_binary, test) is not None) + for (time_ms, test_binary, test) in ts: + print "%8s %s" % ("%dms" % time_ms, test) +sys.exit(-signal.SIGINT if sigint_handler.got_sigint() else exit_code)
diff --git a/src/testing/gtest-parallel/patches/stderr_out.patch b/src/testing/gtest-parallel/patches/stderr_out.patch new file mode 100644 index 0000000..ddaf9df --- /dev/null +++ b/src/testing/gtest-parallel/patches/stderr_out.patch
@@ -0,0 +1,19 @@ +commit 0dec4f46db1b072591cb6703c68a2ebb0279026d +Author: Navreet Gill <navreetgill@google.com> +Date: Wed Aug 24 11:32:47 2016 -0700 + + test + +diff --git a/gtest-parallel b/gtest-parallel +index 4e80928..a258a87 100755 +--- a/gtest-parallel ++++ b/gtest-parallel +@@ -296,7 +296,7 @@ for test_binary in binaries: + + try: + test_list = subprocess.Popen(list_command + ['--gtest_list_tests'], +- stdout=subprocess.PIPE).communicate()[0] ++ stderr=subprocess.PIPE).communicate()[1] + except OSError as e: + sys.exit("%s: %s" % (test_binary, str(e))) +
diff --git a/src/testing/gtest/codereview.settings b/src/testing/gtest/codereview.settings deleted file mode 100644 index a4b341a..0000000 --- a/src/testing/gtest/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/third_party/WebKit/codereview.settings b/src/third_party/WebKit/codereview.settings deleted file mode 100644 index a4b341a..0000000 --- a/src/third_party/WebKit/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/third_party/angle/codereview.settings b/src/third_party/angle/codereview.settings deleted file mode 100644 index 1295fd9..0000000 --- a/src/third_party/angle/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/third_party/dlmalloc/codereview.settings b/src/third_party/dlmalloc/codereview.settings deleted file mode 100644 index a4b341a..0000000 --- a/src/third_party/dlmalloc/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/third_party/freetype2/codereview.settings b/src/third_party/freetype2/codereview.settings deleted file mode 100644 index a4b341a..0000000 --- a/src/third_party/freetype2/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/third_party/icu/codereview.settings b/src/third_party/icu/codereview.settings deleted file mode 100644 index a4b341a..0000000 --- a/src/third_party/icu/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/third_party/libvpx/codereview.settings b/src/third_party/libvpx/codereview.settings deleted file mode 100644 index d7c8d39..0000000 --- a/src/third_party/libvpx/codereview.settings +++ /dev/null
@@ -1,4 +0,0 @@ -# This file is used by gcl to get repository specific information. -GERRIT_HOST: chromium-review.googlesource.com -GERRIT_PORT: 29418 -CODE_REVIEW_SERVER: chromium-review.googlesource.com
diff --git a/src/third_party/mozjs/codereview.settings b/src/third_party/mozjs/codereview.settings deleted file mode 100644 index a4b341a..0000000 --- a/src/third_party/mozjs/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/third_party/mozjs/js/src/assembler/wtf/Platform.h b/src/third_party/mozjs/js/src/assembler/wtf/Platform.h index 2e440e3..05b1155 100644 --- a/src/third_party/mozjs/js/src/assembler/wtf/Platform.h +++ b/src/third_party/mozjs/js/src/assembler/wtf/Platform.h
@@ -1033,14 +1033,6 @@ #define ENABLE_REPAINT_THROTTLING 0 #endif -#if defined(WTF_OS_STARBOARD) -#if SB_CAN(MAP_EXECUTABLE_MEMORY) -#define ENABLE_JIT 1 -#else -#define ENABLE_JIT 0 -#endif -#endif - /* Disable the JIT on versions of GCC prior to 4.1 */ #if !defined(ENABLE_JIT) && WTF_COMPILER_GCC && !GCC_VERSION_AT_LEAST(4, 1, 0) #define ENABLE_JIT 0 @@ -1050,7 +1042,7 @@ #if !defined(ENABLE_JIT) \ && (WTF_CPU_X86 || WTF_CPU_X86_64 || WTF_CPU_ARM || WTF_CPU_SPARC32 || WTF_CPU_MIPS) \ && (WTF_OS_DARWIN || !WTF_COMPILER_GCC || GCC_VERSION_AT_LEAST(4, 1, 0)) \ - && !WTF_OS_WINCE + && !WTF_OS_WINCE && !defined(WTF_OS_STARBOARD) #define ENABLE_JIT 1 #endif
diff --git a/src/third_party/mozjs/js/src/jit/CodeGenerator.cpp b/src/third_party/mozjs/js/src/jit/CodeGenerator.cpp index 294a955..ab8ea02 100644 --- a/src/third_party/mozjs/js/src/jit/CodeGenerator.cpp +++ b/src/third_party/mozjs/js/src/jit/CodeGenerator.cpp
@@ -715,6 +715,12 @@ } bool +CodeGenerator::visitMop(LMop *lir) +{ + return true; +} + +bool CodeGenerator::visitOsiPoint(LOsiPoint *lir) { // Note: markOsiPoint ensures enough space exists between the last @@ -4254,6 +4260,13 @@ masm.add32(Imm32(min), temp); if (!bailoutIf(Assembler::Overflow, lir->snapshot())) return false; + } + + masm.cmp32(temp, Imm32(0)); + if (!bailoutIf(Assembler::LessThan, lir->snapshot())) + return false; + + if (min != 0) { int32_t diff; if (SafeSub(max, min, &diff)) max = diff; @@ -4261,9 +4274,6 @@ masm.sub32(Imm32(min), temp); } - masm.cmp32(temp, Imm32(0)); - if (!bailoutIf(Assembler::LessThan, lir->snapshot())) - return false; } // Compute the maximum possible index. No overflow check is needed when
diff --git a/src/third_party/mozjs/js/src/jit/CodeGenerator.h b/src/third_party/mozjs/js/src/jit/CodeGenerator.h index 873d7f2..94854d4 100644 --- a/src/third_party/mozjs/js/src/jit/CodeGenerator.h +++ b/src/third_party/mozjs/js/src/jit/CodeGenerator.h
@@ -51,6 +51,7 @@ bool visitLabel(LLabel *lir); bool visitNop(LNop *lir); + bool visitMop(LMop *lir); bool visitOsiPoint(LOsiPoint *lir); bool visitGoto(LGoto *lir); bool visitTableSwitch(LTableSwitch *ins);
diff --git a/src/third_party/mozjs/js/src/jit/IonCaches.cpp b/src/third_party/mozjs/js/src/jit/IonCaches.cpp index 30d3711..f833d0f 100644 --- a/src/third_party/mozjs/js/src/jit/IonCaches.cpp +++ b/src/third_party/mozjs/js/src/jit/IonCaches.cpp
@@ -2522,6 +2522,9 @@ cache.getScriptedLocation(&script, &pc); RootedValue lval(cx, ObjectValue(*obj)); + // Override the return value if the script is invalidated (bug 728188). + AutoDetectInvalidation adi(cx, res.address(), ion); + if (cache.isDisabled()) { if (!GetElementOperation(cx, JSOp(*pc), &lval, idval, res)) return false; @@ -2529,9 +2532,7 @@ return true; } - // Override the return value if we are invalidated (bug 728188). - AutoFlushCache afc ("GetElementCache"); - AutoDetectInvalidation adi(cx, res.address(), ion); + AutoFlushCache afc("GetElementCache"); RootedId id(cx); if (!ValueToId<CanGC>(cx, idval, &id))
diff --git a/src/third_party/mozjs/js/src/jit/LIR-Common.h b/src/third_party/mozjs/js/src/jit/LIR-Common.h index 5a87e04..fb43cfc 100644 --- a/src/third_party/mozjs/js/src/jit/LIR-Common.h +++ b/src/third_party/mozjs/js/src/jit/LIR-Common.h
@@ -46,6 +46,12 @@ LIR_HEADER(Nop) }; +class LMop : public LInstructionHelper<0, 0, 0> +{ + public: + LIR_HEADER(Mop) +}; + // An LOsiPoint captures a snapshot after a call and ensures enough space to // patch in a call to the invalidation mechanism. //
diff --git a/src/third_party/mozjs/js/src/jit/LOpcodes.h b/src/third_party/mozjs/js/src/jit/LOpcodes.h index 1520829..dfbd53a 100644 --- a/src/third_party/mozjs/js/src/jit/LOpcodes.h +++ b/src/third_party/mozjs/js/src/jit/LOpcodes.h
@@ -10,6 +10,7 @@ #define LIR_COMMON_OPCODE_LIST(_) \ _(Label) \ _(Nop) \ + _(Mop) \ _(OsiPoint) \ _(MoveGroup) \ _(Integer) \
diff --git a/src/third_party/mozjs/js/src/jit/Lowering.cpp b/src/third_party/mozjs/js/src/jit/Lowering.cpp index fd1dc57..19e7425 100644 --- a/src/third_party/mozjs/js/src/jit/Lowering.cpp +++ b/src/third_party/mozjs/js/src/jit/Lowering.cpp
@@ -2836,13 +2836,25 @@ ins->setInWorklistUnchecked(); #endif + // If we added a Nop for this instruction, we'll also add a Mop, so that + // that live-ranges for fixed register defs, which with LSRA extend through + // the Nop so that they can extend through the OsiPoint don't, with their + // one-extra extension, extend into a position where they use the input + // move group for the following instruction. + bool needsMop = !current->instructions().empty() && current->rbegin()->isNop(); + // If no safepoint was created, there's no need for an OSI point. if (LOsiPoint *osiPoint = popOsiPoint()) { if (!add(osiPoint)) return false; } - return true; + if (needsMop) { + if (!add(new LMop())) + return false; + } + + return true; } bool
diff --git a/src/third_party/mozjs/js/src/jit/RangeAnalysis.cpp b/src/third_party/mozjs/js/src/jit/RangeAnalysis.cpp index fd68f91..c8cbc20 100644 --- a/src/third_party/mozjs/js/src/jit/RangeAnalysis.cpp +++ b/src/third_party/mozjs/js/src/jit/RangeAnalysis.cpp
@@ -339,7 +339,9 @@ // Instead, we should use it to eliminate the dead block. // (Bug 765127) if (r->upper_ < r->lower_) { - *emptyRange = true; + // If both ranges can be NaN, the result can still be NaN. + if (!lhs->isInfinite() || !rhs->isInfinite()) + *emptyRange = true; r->makeRangeInfinite(); }
diff --git a/src/third_party/mozjs/js/src/jit/arm/MacroAssembler-arm.h b/src/third_party/mozjs/js/src/jit/arm/MacroAssembler-arm.h index 04d68af..c46883a 100644 --- a/src/third_party/mozjs/js/src/jit/arm/MacroAssembler-arm.h +++ b/src/third_party/mozjs/js/src/jit/arm/MacroAssembler-arm.h
@@ -763,8 +763,9 @@ if (lhs.getTag() == Operand::OP2) { branch32(cond, lhs.toReg(), rhs, label); } else { - ma_ldr(lhs, ScratchRegister); - branch32(cond, ScratchRegister, rhs, label); + // branch32 will use ScratchRegister. + ma_ldr(lhs, secondScratchReg_); + branch32(cond, secondScratchReg_, rhs, label); } } void branch32(Condition cond, const Address &lhs, Register rhs, Label *label) { @@ -772,8 +773,9 @@ branch32(cond, ScratchRegister, rhs, label); } void branch32(Condition cond, const Address &lhs, Imm32 rhs, Label *label) { - load32(lhs, ScratchRegister); - branch32(cond, ScratchRegister, rhs, label); + // branch32 will use ScratchRegister. + load32(lhs, secondScratchReg_); + branch32(cond, secondScratchReg_, rhs, label); } void branchPtr(Condition cond, const Address &lhs, Register rhs, Label *label) { branch32(cond, lhs, rhs, label); @@ -856,8 +858,9 @@ ma_b(label, cond); } void branchTest32(Condition cond, const Address &address, Imm32 imm, Label *label) { - ma_ldr(Operand(address.base, address.offset), ScratchRegister); - branchTest32(cond, ScratchRegister, imm, label); + // branchTest32 will use ScratchRegister. + load32(address, secondScratchReg_); + branchTest32(cond, secondScratchReg_, imm, label); } void branchTestPtr(Condition cond, const Register &lhs, const Register &rhs, Label *label) { branchTest32(cond, lhs, rhs, label);
diff --git a/src/third_party/mozjs/js/src/jit/shared/IonAssemblerBufferWithConstantPools.h b/src/third_party/mozjs/js/src/jit/shared/IonAssemblerBufferWithConstantPools.h index ec0886c..eed3ffd 100644 --- a/src/third_party/mozjs/js/src/jit/shared/IonAssemblerBufferWithConstantPools.h +++ b/src/third_party/mozjs/js/src/jit/shared/IonAssemblerBufferWithConstantPools.h
@@ -216,8 +216,6 @@ isBranch[idx >> 3] |= 1 << (idx & 0x7); } bool isNextBranch() { - if (this->nodeSize == InstBaseSize) - return false; int idx = this->nodeSize / InstBaseSize; return (isBranch[idx >> 3] >> (idx & 0x7)) & 1; }
diff --git a/src/third_party/mozjs/js/src/jsbool.cpp b/src/third_party/mozjs/js/src/jsbool.cpp index 3b97d25..1df3511 100644 --- a/src/third_party/mozjs/js/src/jsbool.cpp +++ b/src/third_party/mozjs/js/src/jsbool.cpp
@@ -200,7 +200,8 @@ bool js::BooleanGetPrimitiveValueSlow(HandleObject wrappedBool, JSContext *cx) { - JSObject *obj = GetProxyTargetObject(wrappedBool); - JS_ASSERT(obj); + JSObject *obj = CheckedUnwrap(wrappedBool); + if (!obj || !obj->is<BooleanObject>()) + return false; return obj->as<BooleanObject>().unbox(); }
diff --git a/src/third_party/mozjs/js/src/jsobj.cpp b/src/third_party/mozjs/js/src/jsobj.cpp index d922358..c8fc252 100644 --- a/src/third_party/mozjs/js/src/jsobj.cpp +++ b/src/third_party/mozjs/js/src/jsobj.cpp
@@ -279,11 +279,18 @@ if (pobj->isNative()) { desc->attrs = GetShapeAttributes(shape); if (desc->attrs & (JSPROP_GETTER | JSPROP_SETTER)) { + MOZ_ASSERT(desc.isShared()); doGet = false; if (desc->attrs & JSPROP_GETTER) desc->getter = CastAsPropertyOp(shape->getterObject()); if (desc->attrs & JSPROP_SETTER) desc->setter = CastAsStrictPropertyOp(shape->setterObject()); + } else { + // This is either a straight-up data property or (rarely) a + // property with a JSPropertyOp getter/setter. The latter must be + // reported to the caller as a plain data property, so don't + // populate desc.getter/setter, and mask away the SHARED bit. + desc->attrs &= ~JSPROP_SHARED; } } else { if (!JSObject::getGenericAttributes(cx, pobj, id, &desc->attrs)) @@ -5337,4 +5344,3 @@ #endif } } -
diff --git a/src/third_party/mozjs/js/src/jsproxy.cpp b/src/third_party/mozjs/js/src/jsproxy.cpp index 2dbad14..eddf34f 100644 --- a/src/third_party/mozjs/js/src/jsproxy.cpp +++ b/src/third_party/mozjs/js/src/jsproxy.cpp
@@ -2328,7 +2328,9 @@ AutoEnterPolicy policy(cx, handler, proxy, id, BaseProxyHandler::GET, true); if (!policy.allowed()) return policy.returnValue(); - return handler->getOwnPropertyDescriptor(cx, proxy, id, desc, flags); + bool ok = handler->getOwnPropertyDescriptor(cx, proxy, id, desc, flags); + MOZ_ASSERT_IF(ok && desc.isShared(), desc.hasGetterOrSetterObject()); + return ok; } bool
diff --git a/src/third_party/mozjs/mozjs.gyp b/src/third_party/mozjs/mozjs.gyp index c3ed096..c646032 100644 --- a/src/third_party/mozjs/mozjs.gyp +++ b/src/third_party/mozjs/mozjs.gyp
@@ -17,10 +17,11 @@ ], 'variables': { 'common_jit_defines': [ + 'ENABLE_JIT=1', + 'ENABLE_YARR_JIT=1', 'JS_ION=1', 'JS_METHODJIT=1', 'JS_METHODJIT_TYPED_ARRAY=1', - 'ENABLE_YARR_JIT=1', ], }, 'target_defaults': { @@ -47,20 +48,22 @@ 'defines': [ 'JS_CPU_X64=1', 'JS_PUNBOX64=1', - '<@(common_jit_defines)', ], }], [ 'target_arch == "x86"', { 'defines': [ 'JS_CPU_X86=1', 'JS_NUNBOX32=1', - '<@(common_jit_defines)', ], }], [ 'target_arch == "arm"', { 'defines': [ 'JS_CPU_ARM=1', 'JS_NUNBOX32=1', + ], + }], + [ 'cobalt_enable_jit == 1', { + 'defines': [ '<@(common_jit_defines)', ], }], @@ -98,7 +101,7 @@ 'js-confdefs.h', ], 'conditions': [ - [ 'target_arch == "x64"', { + [ 'target_arch == "x64" and cobalt_enable_jit == 1', { 'sources': [ 'js/src/assembler/assembler/MacroAssemblerX86Common.cpp', 'js/src/jit/shared/Assembler-x86-shared.cpp', @@ -119,7 +122,7 @@ '<@(mozjs_jit_sources)', ], }], - [ 'target_arch == "x86"', { + [ 'target_arch == "x86" and cobalt_enable_jit == 1', { 'sources': [ 'js/src/assembler/assembler/MacroAssemblerX86Common.cpp', 'js/src/jit/shared/Assembler-x86-shared.cpp', @@ -140,7 +143,7 @@ '<@(mozjs_jit_sources)', ], }], - [ 'target_arch == "arm"', { + [ 'target_arch == "arm" and cobalt_enable_jit == 1', { 'sources': [ 'js/src/assembler/assembler/ARMAssembler.cpp', 'js/src/assembler/assembler/MacroAssemblerARM.cpp',
diff --git a/src/third_party/openssl/README.chromium b/src/third_party/openssl/README.chromium index fbae0aa..6c8889b 100644 --- a/src/third_party/openssl/README.chromium +++ b/src/third_party/openssl/README.chromium
@@ -1,6 +1,6 @@ Name: openssl URL: http://openssl.org/source/ -Version: 1.0.1c +Version: 1.0.1p License: BSDish License File: openssl/LICENSE License Android Compatible: yes
diff --git a/src/third_party/openssl/codereview.settings b/src/third_party/openssl/codereview.settings deleted file mode 100644 index a4b341a..0000000 --- a/src/third_party/openssl/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/third_party/ots/codereview.settings b/src/third_party/ots/codereview.settings deleted file mode 100644 index acbc431..0000000 --- a/src/third_party/ots/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 \ No newline at end of file
diff --git a/src/third_party/ots/include/opentype-sanitiser.h b/src/third_party/ots/include/opentype-sanitiser.h index fc76b90..1380ac7 100644 --- a/src/third_party/ots/include/opentype-sanitiser.h +++ b/src/third_party/ots/include/opentype-sanitiser.h
@@ -82,8 +82,10 @@ } while (length >= 4) { - chksum_ += ntohl(*reinterpret_cast<const uint32_t*>( - reinterpret_cast<const uint8_t*>(data) + offset)); + uint32_t tmp; + std::memcpy(&tmp, reinterpret_cast<const uint8_t *>(data) + offset, + sizeof(uint32_t)); + chksum_ += ntohl(tmp); length -= 4; offset += 4; }
diff --git a/src/third_party/skia/codereview.settings b/src/third_party/skia/codereview.settings deleted file mode 100644 index a4b341a..0000000 --- a/src/third_party/skia/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/tools/gyp/codereview.settings b/src/tools/gyp/codereview.settings deleted file mode 100644 index a4b341a..0000000 --- a/src/tools/gyp/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