| /* | 
 |  * Copyright (C) 2010 Google Inc. All rights reserved. | 
 |  * | 
 |  * Redistribution and use in source and binary forms, with or without | 
 |  * modification, are permitted provided that the following conditions are | 
 |  * met: | 
 |  * | 
 |  *     * Redistributions of source code must retain the above copyright | 
 |  * notice, this list of conditions and the following disclaimer. | 
 |  *     * Redistributions in binary form must reproduce the above | 
 |  * copyright notice, this list of conditions and the following disclaimer | 
 |  * in the documentation and/or other materials provided with the | 
 |  * distribution. | 
 |  *     * Neither the name of Google Inc. nor the names of its | 
 |  * contributors may be used to endorse or promote products derived from | 
 |  * this software without specific prior written permission. | 
 |  * | 
 |  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | 
 |  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | 
 |  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | 
 |  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | 
 |  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | 
 |  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | 
 |  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | 
 |  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 
 |  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 
 |  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 
 |  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 
 |  */ | 
 |  | 
 | #ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_BINDINGS_SCRIPT_WRAPPABLE_H_ | 
 | #define THIRD_PARTY_BLINK_RENDERER_PLATFORM_BINDINGS_SCRIPT_WRAPPABLE_H_ | 
 |  | 
 | #include "build/build_config.h" | 
 | #include "third_party/blink/renderer/platform/bindings/trace_wrapper_v8_reference.h" | 
 | #include "third_party/blink/renderer/platform/bindings/wrapper_type_info.h" | 
 | #include "third_party/blink/renderer/platform/heap/garbage_collected.h" | 
 | #include "third_party/blink/renderer/platform/platform_export.h" | 
 | #include "third_party/blink/renderer/platform/wtf/type_traits.h" | 
 | #include "v8/include/v8.h" | 
 |  | 
 | namespace blink { | 
 |  | 
 | class DOMDataStore; | 
 | class ScriptState; | 
 |  | 
 | // ScriptWrappable provides a way to map from/to C++ DOM implementation to/from | 
 | // JavaScript object (platform object).  ToV8() converts a ScriptWrappable to | 
 | // a v8::Object and ToScriptWrappable() converts a v8::Object back to | 
 | // a ScriptWrappable.  v8::Object as platform object is called "wrapper object". | 
 | // The wrapper object for the main world is stored in ScriptWrappable.  Wrapper | 
 | // objects for other worlds are stored in DOMDataStore. | 
 | class PLATFORM_EXPORT ScriptWrappable : public v8::Object::Wrappable { | 
 |  public: | 
 |   // This is a type dispatcher from ScriptWrappable* to a subtype, optimized for | 
 |   // use cases that perform downcasts multiple times. | 
 |   class TypeDispatcher final { | 
 |     STACK_ALLOCATED(); | 
 |  | 
 |    public: | 
 |     // The input parameter `script_wrappable` must not be null. | 
 |     explicit TypeDispatcher(ScriptWrappable* script_wrappable) | 
 |         : script_wrappable_(script_wrappable), | 
 |           wrapper_type_info_(ToWrapperTypeInfo(script_wrappable)) {} | 
 |     ~TypeDispatcher() = default; | 
 |  | 
 |     TypeDispatcher(const TypeDispatcher&) = delete; | 
 |     TypeDispatcher& operator=(const TypeDispatcher&) = delete; | 
 |  | 
 |     // Downcasts the ScriptWrappable to the given template parameter type or | 
 |     // nullptr if the ScriptWrappable doesn't implement the given type. The | 
 |     // inheritance is checked with WrapperTypeInfo, i.e. the check is based on | 
 |     // the IDL definitions in *.idl files, not based on C++ class inheritance. | 
 |     template <typename T> | 
 |     T* DowncastTo() { | 
 |       if (wrapper_type_info_->IsSubclass(T::GetStaticWrapperTypeInfo())) | 
 |         return static_cast<T*>(script_wrappable_); | 
 |       return nullptr; | 
 |     } | 
 |  | 
 |     // Downcasts the ScriptWrappable to the given template parameter type iff | 
 |     // the ScriptWrappable implements the type as the most derived class (i.e. | 
 |     // the ScriptWrappable does _not_ implement a subtype of the given type). | 
 |     // Otherwise, returns nullptr. The inheritance is checked with | 
 |     // WrapperTypeInfo, i.e. the check is based on the IDL definitions in *.idl | 
 |     // files, not based on C++ class inheritance. | 
 |     template <typename T> | 
 |     T* ToMostDerived() { | 
 |       if (wrapper_type_info_ == T::GetStaticWrapperTypeInfo()) | 
 |         return static_cast<T*>(script_wrappable_); | 
 |       return nullptr; | 
 |     } | 
 |  | 
 |    private: | 
 |     ScriptWrappable* script_wrappable_ = nullptr; | 
 |     const WrapperTypeInfo* wrapper_type_info_ = nullptr; | 
 |   }; | 
 |  | 
 |   ScriptWrappable(const ScriptWrappable&) = delete; | 
 |   ScriptWrappable& operator=(const ScriptWrappable&) = delete; | 
 |   ~ScriptWrappable() override = default; | 
 |  | 
 |   const char* GetHumanReadableName() const override; | 
 |  | 
 |   void Trace(Visitor*) const override; | 
 |  | 
 |   // Returns a wrapper object, creating it if needed. | 
 |   v8::Local<v8::Value> ToV8(ScriptState*); | 
 |  | 
 |   // This overload is used for the case when a `ToV8()` caller does not have | 
 |   // `script_state` but does have a receiver object (a creation context object) | 
 |   // which is needed to create a wrapper. If a wrapper object corresponding to | 
 |   // the receiver object exists, `ToV8()` can return it without a call to | 
 |   // `ScriptState::ForRelevantRealm`, which is slow. | 
 |   v8::Local<v8::Value> ToV8(v8::Isolate*, | 
 |                             v8::Local<v8::Object> creation_context_object); | 
 |  | 
 |   // Creates and returns a new wrapper object. This DCHECKs that a wrapper does | 
 |   // not exist yet. Use ToV8() if a wrapper might already exist. | 
 |   virtual v8::Local<v8::Value> Wrap(ScriptState*); | 
 |  | 
 |   // Associates the instance with the given |wrapper| if this instance is not | 
 |   // yet associated with any wrapper.  Returns the wrapper already associated | 
 |   // or |wrapper| if not yet associated. | 
 |   // The caller should always use the returned value rather than |wrapper|. | 
 |   [[nodiscard]] virtual v8::Local<v8::Object> AssociateWithWrapper( | 
 |       v8::Isolate*, | 
 |       const WrapperTypeInfo*, | 
 |       v8::Local<v8::Object> wrapper); | 
 |  | 
 |  protected: | 
 |   ScriptWrappable() = default; | 
 |  | 
 |  private: | 
 |   static_assert( | 
 |       std::is_trivially_destructible< | 
 |           TraceWrapperV8Reference<v8::Object>>::value, | 
 |       "TraceWrapperV8Reference<v8::Object> should be trivially destructible."); | 
 |  | 
 |   // Inline storage for the a single wrapper reference. Only | 
 |   // `DOMDataStore::UncheckedInlineStorageForWrappable()` should access this | 
 |   // field. | 
 |   TraceWrapperV8Reference<v8::Object> wrapper_; | 
 |   friend class DOMDataStore; | 
 | }; | 
 |  | 
 | template <typename T> | 
 |   requires std::derived_from<T, ScriptWrappable> | 
 | T* ToScriptWrappable(v8::Isolate* isolate, v8::Local<v8::Object> wrapper) { | 
 |   const WrapperTypeInfo* wrapper_type_info = T::GetStaticWrapperTypeInfo(); | 
 |   return static_cast<T*>(v8::Object::Unwrap<ScriptWrappable>( | 
 |       isolate, wrapper, | 
 |       v8::CppHeapPointerTagRange(wrapper_type_info->this_tag, | 
 |                                  wrapper_type_info->max_subclass_tag))); | 
 | } | 
 |  | 
 | // Defines |GetWrapperTypeInfo| virtual method which returns the WrapperTypeInfo | 
 | // of the instance. Also declares a static member of type WrapperTypeInfo, of | 
 | // which the definition is given by the IDL code generator. | 
 | // | 
 | // All the derived classes of ScriptWrappable, regardless of directly or | 
 | // indirectly, must write this macro in the class definition as long as the | 
 | // class has a corresponding .idl file. | 
 | #define DEFINE_WRAPPERTYPEINFO()                               \ | 
 |  public:                                                       \ | 
 |   const WrapperTypeInfo* GetWrapperTypeInfo() const override { \ | 
 |     return &wrapper_type_info_;                                \ | 
 |   }                                                            \ | 
 |   static const WrapperTypeInfo* GetStaticWrapperTypeInfo() {   \ | 
 |     return &wrapper_type_info_;                                \ | 
 |   }                                                            \ | 
 |                                                                \ | 
 |  private:                                                      \ | 
 |   static const WrapperTypeInfo& wrapper_type_info_ | 
 |  | 
 | }  // namespace blink | 
 |  | 
 | #endif  // THIRD_PARTY_BLINK_RENDERER_PLATFORM_BINDINGS_SCRIPT_WRAPPABLE_H_ |