| /* | 
 |  * Copyright (C) 2009 Google Inc. All rights reserved. | 
 |  * Copyright (C) 2012 Ericsson AB. 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 V8Binding_h | 
 | #define V8Binding_h | 
 |  | 
 | #include "platform/PlatformExport.h" | 
 | #include "platform/bindings/DOMDataStore.h" | 
 | #include "platform/bindings/DOMWrapperWorld.h" | 
 | #include "platform/bindings/ScriptWrappable.h" | 
 | #include "platform/bindings/StringResource.h" | 
 | #include "platform/bindings/V8BindingMacros.h" | 
 | #include "platform/bindings/V8PerIsolateData.h" | 
 | #include "platform/bindings/V8ValueCache.h" | 
 | #include "platform/heap/Handle.h" | 
 | #include "platform/wtf/text/AtomicString.h" | 
 | #include "platform/wtf/text/StringView.h" | 
 | #include "v8/include/v8.h" | 
 |  | 
 | namespace blink { | 
 |  | 
 | // This file contains bindings helper functions that do not have dependencies | 
 | // to core/ or bindings/core. For core-specific helper functions, see | 
 | // bindings/core/v8/V8BindingForCore.h. | 
 |  | 
 | template <typename T> | 
 | struct V8TypeOf { | 
 |   STATIC_ONLY(V8TypeOf); | 
 |   // |Type| provides C++ -> V8 type conversion for DOM wrappers. | 
 |   // The Blink binding code generator will generate specialized version of | 
 |   // V8TypeOf for each wrapper class. | 
 |   typedef void Type; | 
 | }; | 
 |  | 
 | template <typename CallbackInfo, typename S> | 
 | inline void V8SetReturnValue(const CallbackInfo& info, | 
 |                              const v8::Persistent<S>& handle) { | 
 |   info.GetReturnValue().Set(handle); | 
 | } | 
 |  | 
 | template <typename CallbackInfo, typename S> | 
 | inline void V8SetReturnValue(const CallbackInfo& info, | 
 |                              const v8::Local<S> handle) { | 
 |   info.GetReturnValue().Set(handle); | 
 | } | 
 |  | 
 | template <typename CallbackInfo, typename S> | 
 | inline void V8SetReturnValue(const CallbackInfo& info, | 
 |                              v8::MaybeLocal<S> maybe) { | 
 |   if (LIKELY(!maybe.IsEmpty())) | 
 |     info.GetReturnValue().Set(maybe.ToLocalChecked()); | 
 | } | 
 |  | 
 | template <typename CallbackInfo> | 
 | inline void V8SetReturnValue(const CallbackInfo& info, bool value) { | 
 |   info.GetReturnValue().Set(value); | 
 | } | 
 |  | 
 | template <typename CallbackInfo> | 
 | inline void V8SetReturnValue(const CallbackInfo& info, double value) { | 
 |   info.GetReturnValue().Set(value); | 
 | } | 
 |  | 
 | template <typename CallbackInfo> | 
 | inline void V8SetReturnValue(const CallbackInfo& info, int32_t value) { | 
 |   info.GetReturnValue().Set(value); | 
 | } | 
 |  | 
 | template <typename CallbackInfo> | 
 | inline void V8SetReturnValue(const CallbackInfo& info, uint32_t value) { | 
 |   info.GetReturnValue().Set(value); | 
 | } | 
 |  | 
 | template <typename CallbackInfo> | 
 | inline void V8SetReturnValueBool(const CallbackInfo& info, bool v) { | 
 |   info.GetReturnValue().Set(v); | 
 | } | 
 |  | 
 | template <typename CallbackInfo> | 
 | inline void V8SetReturnValueInt(const CallbackInfo& info, int v) { | 
 |   info.GetReturnValue().Set(v); | 
 | } | 
 |  | 
 | template <typename CallbackInfo> | 
 | inline void V8SetReturnValueUnsigned(const CallbackInfo& info, unsigned v) { | 
 |   info.GetReturnValue().Set(v); | 
 | } | 
 |  | 
 | template <typename CallbackInfo> | 
 | inline void V8SetReturnValueNull(const CallbackInfo& info) { | 
 |   info.GetReturnValue().SetNull(); | 
 | } | 
 |  | 
 | template <typename CallbackInfo> | 
 | inline void V8SetReturnValueUndefined(const CallbackInfo& info) { | 
 |   info.GetReturnValue().SetUndefined(); | 
 | } | 
 |  | 
 | template <typename CallbackInfo> | 
 | inline void V8SetReturnValueEmptyString(const CallbackInfo& info) { | 
 |   info.GetReturnValue().SetEmptyString(); | 
 | } | 
 |  | 
 | template <typename CallbackInfo> | 
 | inline void V8SetReturnValueString(const CallbackInfo& info, | 
 |                                    const String& string, | 
 |                                    v8::Isolate* isolate) { | 
 |   if (string.IsNull()) { | 
 |     V8SetReturnValueEmptyString(info); | 
 |     return; | 
 |   } | 
 |   V8PerIsolateData::From(isolate)->GetStringCache()->SetReturnValueFromString( | 
 |       info.GetReturnValue(), string.Impl()); | 
 | } | 
 |  | 
 | template <typename CallbackInfo> | 
 | inline void V8SetReturnValueStringOrNull(const CallbackInfo& info, | 
 |                                          const String& string, | 
 |                                          v8::Isolate* isolate) { | 
 |   if (string.IsNull()) { | 
 |     V8SetReturnValueNull(info); | 
 |     return; | 
 |   } | 
 |   V8PerIsolateData::From(isolate)->GetStringCache()->SetReturnValueFromString( | 
 |       info.GetReturnValue(), string.Impl()); | 
 | } | 
 |  | 
 | template <typename CallbackInfo> | 
 | inline void V8SetReturnValue(const CallbackInfo& callback_info, | 
 |                              ScriptWrappable* impl, | 
 |                              v8::Local<v8::Object> creation_context) { | 
 |   if (UNLIKELY(!impl)) { | 
 |     V8SetReturnValueNull(callback_info); | 
 |     return; | 
 |   } | 
 |   if (DOMDataStore::SetReturnValue(callback_info.GetReturnValue(), impl)) | 
 |     return; | 
 |   v8::Local<v8::Object> wrapper = | 
 |       impl->Wrap(callback_info.GetIsolate(), creation_context); | 
 |   V8SetReturnValue(callback_info, wrapper); | 
 | } | 
 |  | 
 | template <typename CallbackInfo> | 
 | inline void V8SetReturnValue(const CallbackInfo& callback_info, | 
 |                              ScriptWrappable* impl) { | 
 |   V8SetReturnValue(callback_info, impl, callback_info.Holder()); | 
 | } | 
 |  | 
 | template <typename CallbackInfo> | 
 | inline void V8SetReturnValueForMainWorld(const CallbackInfo& callback_info, | 
 |                                          ScriptWrappable* impl) { | 
 |   DCHECK(DOMWrapperWorld::Current(callback_info.GetIsolate()).IsMainWorld()); | 
 |   if (UNLIKELY(!impl)) { | 
 |     V8SetReturnValueNull(callback_info); | 
 |     return; | 
 |   } | 
 |   if (DOMDataStore::SetReturnValueForMainWorld(callback_info.GetReturnValue(), | 
 |                                                impl)) | 
 |     return; | 
 |   v8::Local<v8::Object> wrapper = | 
 |       impl->Wrap(callback_info.GetIsolate(), callback_info.Holder()); | 
 |   V8SetReturnValue(callback_info, wrapper); | 
 | } | 
 |  | 
 | template <typename CallbackInfo> | 
 | inline void V8SetReturnValueFast(const CallbackInfo& callback_info, | 
 |                                  ScriptWrappable* impl, | 
 |                                  const ScriptWrappable* wrappable) { | 
 |   if (UNLIKELY(!impl)) { | 
 |     V8SetReturnValueNull(callback_info); | 
 |     return; | 
 |   } | 
 |   if (DOMDataStore::SetReturnValueFast(callback_info.GetReturnValue(), impl, | 
 |                                        callback_info.Holder(), wrappable)) | 
 |     return; | 
 |   v8::Local<v8::Object> wrapper = | 
 |       impl->Wrap(callback_info.GetIsolate(), callback_info.Holder()); | 
 |   V8SetReturnValue(callback_info, wrapper); | 
 | } | 
 |  | 
 | template <typename CallbackInfo, typename T> | 
 | inline void V8SetReturnValueFast(const CallbackInfo& callback_info, | 
 |                                  const v8::Local<T> handle, | 
 |                                  const ScriptWrappable*) { | 
 |   V8SetReturnValue(callback_info, handle); | 
 | } | 
 |  | 
 | // Convert v8::String to a WTF::String. If the V8 string is not already | 
 | // an external string then it is transformed into an external string at this | 
 | // point to avoid repeated conversions. | 
 | inline String ToCoreString(v8::Local<v8::String> value) { | 
 |   return V8StringToWebCoreString<String>(value, kExternalize); | 
 | } | 
 |  | 
 | inline String ToCoreStringWithNullCheck(v8::Local<v8::String> value) { | 
 |   if (value.IsEmpty() || value->IsNull()) | 
 |     return String(); | 
 |   return ToCoreString(value); | 
 | } | 
 |  | 
 | inline String ToCoreStringWithUndefinedOrNullCheck( | 
 |     v8::Local<v8::String> value) { | 
 |   if (value.IsEmpty()) | 
 |     return String(); | 
 |   return ToCoreString(value); | 
 | } | 
 |  | 
 | inline AtomicString ToCoreAtomicString(v8::Local<v8::String> value) { | 
 |   return V8StringToWebCoreString<AtomicString>(value, kExternalize); | 
 | } | 
 |  | 
 | // This method will return a null String if the v8::Value does not contain a | 
 | // v8::String.  It will not call ToString() on the v8::Value. If you want | 
 | // ToString() to be called, please use the TONATIVE_FOR_V8STRINGRESOURCE_*() | 
 | // macros instead. | 
 | inline String ToCoreStringWithUndefinedOrNullCheck(v8::Local<v8::Value> value) { | 
 |   if (value.IsEmpty() || !value->IsString()) | 
 |     return String(); | 
 |   return ToCoreString(value.As<v8::String>()); | 
 | } | 
 |  | 
 | // Convert a string to a V8 string. | 
 |  | 
 | inline v8::Local<v8::String> V8String(v8::Isolate* isolate, | 
 |                                       const StringView& string) { | 
 |   DCHECK(isolate); | 
 |   if (string.IsNull()) | 
 |     return v8::String::Empty(isolate); | 
 |   if (StringImpl* impl = string.SharedImpl()) { | 
 |     return V8PerIsolateData::From(isolate)->GetStringCache()->V8ExternalString( | 
 |         isolate, impl); | 
 |   } | 
 |   if (string.Is8Bit()) { | 
 |     return v8::String::NewFromOneByte( | 
 |                isolate, reinterpret_cast<const uint8_t*>(string.Characters8()), | 
 |                v8::NewStringType::kNormal, static_cast<int>(string.length())) | 
 |         .ToLocalChecked(); | 
 |   } | 
 |   return v8::String::NewFromTwoByte( | 
 |              isolate, reinterpret_cast<const uint16_t*>(string.Characters16()), | 
 |              v8::NewStringType::kNormal, static_cast<int>(string.length())) | 
 |       .ToLocalChecked(); | 
 | } | 
 |  | 
 | // As above, for string literals. The compiler doesn't optimize away the is8Bit | 
 | // and sharedImpl checks for string literals in the StringView version. | 
 | inline v8::Local<v8::String> V8String(v8::Isolate* isolate, | 
 |                                       const char* string) { | 
 |   DCHECK(isolate); | 
 |   if (!string || string[0] == '\0') | 
 |     return v8::String::Empty(isolate); | 
 |   return v8::String::NewFromOneByte(isolate, | 
 |                                     reinterpret_cast<const uint8_t*>(string), | 
 |                                     v8::NewStringType::kNormal, strlen(string)) | 
 |       .ToLocalChecked(); | 
 | } | 
 |  | 
 | inline v8::Local<v8::Value> V8StringOrNull(v8::Isolate* isolate, | 
 |                                            const AtomicString& string) { | 
 |   if (string.IsNull()) | 
 |     return v8::Null(isolate); | 
 |   return V8PerIsolateData::From(isolate)->GetStringCache()->V8ExternalString( | 
 |       isolate, string.Impl()); | 
 | } | 
 |  | 
 | inline v8::Local<v8::String> V8AtomicString(v8::Isolate* isolate, | 
 |                                             const StringView& string) { | 
 |   DCHECK(isolate); | 
 |   if (string.Is8Bit()) { | 
 |     return v8::String::NewFromOneByte( | 
 |                isolate, reinterpret_cast<const uint8_t*>(string.Characters8()), | 
 |                v8::NewStringType::kInternalized, | 
 |                static_cast<int>(string.length())) | 
 |         .ToLocalChecked(); | 
 |   } | 
 |   return v8::String::NewFromTwoByte( | 
 |              isolate, reinterpret_cast<const uint16_t*>(string.Characters16()), | 
 |              v8::NewStringType::kInternalized, | 
 |              static_cast<int>(string.length())) | 
 |       .ToLocalChecked(); | 
 | } | 
 |  | 
 | // As above, for string literals. The compiler doesn't optimize away the is8Bit | 
 | // check for string literals in the StringView version. | 
 | inline v8::Local<v8::String> V8AtomicString(v8::Isolate* isolate, | 
 |                                             const char* string) { | 
 |   DCHECK(isolate); | 
 |   if (!string || string[0] == '\0') | 
 |     return v8::String::Empty(isolate); | 
 |   return v8::String::NewFromOneByte( | 
 |              isolate, reinterpret_cast<const uint8_t*>(string), | 
 |              v8::NewStringType::kInternalized, strlen(string)) | 
 |       .ToLocalChecked(); | 
 | } | 
 |  | 
 | inline v8::Local<v8::String> V8StringFromUtf8(v8::Isolate* isolate, | 
 |                                               const char* bytes, | 
 |                                               int length) { | 
 |   DCHECK(isolate); | 
 |   return v8::String::NewFromUtf8(isolate, bytes, v8::NewStringType::kNormal, | 
 |                                  length) | 
 |       .ToLocalChecked(); | 
 | } | 
 |  | 
 | inline v8::Local<v8::Value> V8Undefined() { | 
 |   return v8::Local<v8::Value>(); | 
 | } | 
 |  | 
 | inline v8::MaybeLocal<v8::Value> V8DateOrNaN(v8::Isolate* isolate, | 
 |                                              double value) { | 
 |   DCHECK(isolate); | 
 |   return v8::Date::New(isolate->GetCurrentContext(), value); | 
 | } | 
 |  | 
 | inline bool IsUndefinedOrNull(v8::Local<v8::Value> value) { | 
 |   return value.IsEmpty() || value->IsNullOrUndefined(); | 
 | } | 
 | PLATFORM_EXPORT v8::Local<v8::Function> GetBoundFunction( | 
 |     v8::Local<v8::Function>); | 
 |  | 
 | // FIXME: This will be soon embedded in the generated code. | 
 | template <typename Collection> | 
 | static void IndexedPropertyEnumerator( | 
 |     const v8::PropertyCallbackInfo<v8::Array>& info) { | 
 |   Collection* collection = | 
 |       ToScriptWrappable(info.Holder())->ToImpl<Collection>(); | 
 |   int length = collection->length(); | 
 |   v8::Local<v8::Array> properties = v8::Array::New(info.GetIsolate(), length); | 
 |   v8::Local<v8::Context> context = info.GetIsolate()->GetCurrentContext(); | 
 |   for (int i = 0; i < length; ++i) { | 
 |     v8::Local<v8::Integer> integer = v8::Integer::New(info.GetIsolate(), i); | 
 |     if (!V8CallBoolean(properties->CreateDataProperty(context, i, integer))) | 
 |       return; | 
 |   } | 
 |   V8SetReturnValue(info, properties); | 
 | } | 
 |  | 
 | // These methods store hidden values into an array that is stored in the | 
 | // internal field of a DOM wrapper. | 
 | PLATFORM_EXPORT bool AddHiddenValueToArray(v8::Isolate*, | 
 |                                            v8::Local<v8::Object>, | 
 |                                            v8::Local<v8::Value>, | 
 |                                            int cache_index); | 
 | PLATFORM_EXPORT void RemoveHiddenValueFromArray(v8::Isolate*, | 
 |                                                 v8::Local<v8::Object>, | 
 |                                                 v8::Local<v8::Value>, | 
 |                                                 int cache_index); | 
 |  | 
 | // Freeze a V8 object. The type of the first parameter and the return value is | 
 | // intentionally v8::Value so that this function can wrap ToV8(). | 
 | // If the argument isn't an object, this will crash. | 
 | PLATFORM_EXPORT v8::Local<v8::Value> FreezeV8Object(v8::Local<v8::Value>, | 
 |                                                     v8::Isolate*); | 
 |  | 
 | }  // namespace blink | 
 |  | 
 | #endif  // V8Binding_h |