Index: Source/bindings/core/dart/DartUtilities.cpp |
diff --git a/Source/bindings/core/dart/DartUtilities.cpp b/Source/bindings/core/dart/DartUtilities.cpp |
new file mode 100644 |
index 0000000000000000000000000000000000000000..4cb56574ed676fdb174a0dc92423374cf910f709 |
--- /dev/null |
+++ b/Source/bindings/core/dart/DartUtilities.cpp |
@@ -0,0 +1,1416 @@ |
+// Copyright 2011, 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. |
+ |
+#include "config.h" |
+#include "bindings/core/dart/DartUtilities.h" |
+ |
+#if OS(ANDROID) |
+#include <sys/system_properties.h> |
+#endif |
+ |
+#include "core/FetchInitiatorTypeNames.h" |
+#include "bindings/core/dart/DartController.h" |
+#include "bindings/core/dart/DartDOMData.h" |
+#include "bindings/core/dart/DartScriptDebugServer.h" |
+#include "bindings/core/dart/DartScriptState.h" |
+#include "bindings/core/dart/V8Converter.h" |
+#include "bindings/core/v8/ScriptController.h" |
+#include "bindings/core/v8/SerializedScriptValue.h" |
+#include "bindings/core/v8/V8Binding.h" |
+#include "bindings/core/v8/V8ExceptionState.h" |
+#include "bindings/core/v8/V8PerIsolateData.h" |
+#include "core/dom/Document.h" |
+#include "core/events/ErrorEvent.h" |
+#include "core/fetch/ResourceFetcher.h" |
+#include "core/frame/LocalDOMWindow.h" |
+#include "core/frame/LocalFrame.h" |
+#include "core/html/canvas/DataView.h" |
+#include "core/inspector/ScriptArguments.h" |
+#include "core/inspector/ScriptCallStack.h" |
+#include "core/loader/FrameLoader.h" |
+#include "modules/webdatabase/sqlite/SQLValue.h" |
+#include "platform/SharedBuffer.h" |
+#include "platform/network/ResourceRequest.h" |
+ |
+#include "wtf/ArrayBufferView.h" |
+#include "wtf/Float32Array.h" |
+#include "wtf/Float64Array.h" |
+#include "wtf/Int16Array.h" |
+#include "wtf/Int32Array.h" |
+#include "wtf/Int8Array.h" |
+#include "wtf/RefCounted.h" |
+#include "wtf/Uint16Array.h" |
+#include "wtf/Uint32Array.h" |
+#include "wtf/Uint8Array.h" |
+#include "wtf/Uint8ClampedArray.h" |
+#include "wtf/text/AtomicString.h" |
+#include "wtf/text/CString.h" |
+#include "wtf/text/WTFString.h" |
+ |
+namespace blink { |
+ |
+V8Scope::V8Scope(DartDOMData* dartDOMData, v8::Handle<v8::Context> context) |
+ : m_v8Isolate(v8::Isolate::GetCurrent()) |
+ , m_dartDOMData(dartDOMData) |
+ , m_handleScope(m_v8Isolate) |
+ , m_contextScope(context) |
+ , m_recursionScope(m_v8Isolate) |
+{ |
+ if (m_dartDOMData) |
+ (*m_dartDOMData->recursion())++; |
+} |
+ |
+V8Scope::V8Scope(DartDOMData* dartDOMData) |
+ : m_v8Isolate(v8::Isolate::GetCurrent()) |
+ , m_dartDOMData(dartDOMData) |
+ , m_handleScope(m_v8Isolate) |
+ , m_contextScope(DartUtilities::currentV8Context()) |
+ , m_recursionScope(m_v8Isolate) |
+{ |
+ if (m_dartDOMData) |
+ (*m_dartDOMData->recursion())++; |
+} |
+ |
+V8Scope::~V8Scope() |
+{ |
+ if (m_dartDOMData) |
+ (*m_dartDOMData->recursion())--; |
+} |
+ |
+DartStringPeer* DartStringPeer::nullString() |
+{ |
+ DEFINE_STATIC_LOCAL(DartStringPeer, empty, ()); |
+ return ∅ |
+} |
+ |
+DartStringPeer* DartStringPeer::emptyString() |
+{ |
+ DEFINE_STATIC_LOCAL(DartStringPeer, empty, (StringImpl::empty())); |
+ return ∅ |
+} |
+ |
+ |
+static void stringFinalizer(void* peer) |
+{ |
+ ASSERT(reinterpret_cast<DartStringPeer*>(peer) != DartStringPeer::nullString()); |
+ delete reinterpret_cast<DartStringPeer*>(peer); |
+} |
+ |
+template <typename T> DartStringPeer* convertAndExternalize(Dart_Handle string, intptr_t length) |
+{ |
+ if (!length) |
+ return new DartStringPeer(StringImpl::empty()); |
+#ifndef NDEBUG |
+ { |
+ intptr_t storageSize = 0; |
+ Dart_StringStorageSize(string, &storageSize); |
+ ASSERT(length * intptr_t(sizeof(T)) == storageSize); |
+ } |
+#endif |
+ T* buffer = 0; |
+ DartStringPeer* peer = new DartStringPeer(StringImpl::createUninitialized(length, buffer)); |
+ Dart_Handle ALLOW_UNUSED r = Dart_MakeExternalString(string, buffer, length * sizeof(T), peer, stringFinalizer); |
+ ASSERT(!Dart_IsError(r)); |
+ return peer; |
+} |
+ |
+DartStringPeer* DartUtilities::toStringImpl(Dart_Handle object, intptr_t charsize, intptr_t strlength) |
+{ |
+ ASSERT(Dart_IsString(object) && !Dart_IsExternalString(object)); |
+ return (charsize == 1) ? convertAndExternalize<LChar>(object, strlength) : convertAndExternalize<UChar>(object, strlength); |
+} |
+ |
+ |
+Dart_Handle DartUtilities::stringImplToDartString(StringImpl* stringImpl) |
+{ |
+ if (!stringImpl) { |
+ DartDOMData* domData = DartDOMData::current(); |
+ return domData->emptyString(); |
+ } |
+ |
+ DartStringPeer* peer = new DartStringPeer(stringImpl); |
+ if (stringImpl->is8Bit()) { |
+ // FIXME: maybe it makes sense only externalize strings longer than certain threshold, such as 5 symbols. |
+ return Dart_NewExternalLatin1String(reinterpret_cast<const uint8_t*>(stringImpl->characters8()), |
+ stringImpl->length(), peer, stringFinalizer); |
+ } else { |
+ // FIXME: maybe it makes sense only externalize strings longer than certain threshold, such as 5 symbols. |
+ return Dart_NewExternalUTF16String(reinterpret_cast<const uint16_t*>(stringImpl->characters16()), |
+ stringImpl->length(), peer, stringFinalizer); |
+ } |
+} |
+ |
+Dart_Handle DartUtilities::stringToDartString(const String& str) |
+{ |
+ return stringImplToDartString(str.impl()); |
+} |
+ |
+Dart_Handle DartUtilities::stringToDartString(const AtomicString& str) |
+{ |
+ return stringImplToDartString(str.impl()); |
+} |
+ |
+ |
+Dart_Handle DartUtilities::safeStringImplToDartString(StringImpl* stringImpl) |
+{ |
+ if (!stringImpl) { |
+ DartDOMData* domData = DartDOMData::current(); |
+ return domData->emptyString(); |
+ } |
+ |
+ if (stringImpl->is8Bit()) { |
+ return Dart_NewStringFromUTF8( |
+ reinterpret_cast<const uint8_t*>(stringImpl->characters8()), |
+ stringImpl->length()); |
+ } else { |
+ return Dart_NewStringFromUTF16( |
+ reinterpret_cast<const uint16_t*>(stringImpl->characters16()), |
+ stringImpl->length()); |
+ } |
+} |
+ |
+Dart_Handle DartUtilities::safeStringToDartString(const String& str) |
+{ |
+ return safeStringImplToDartString(str.impl()); |
+} |
+ |
+Dart_Handle DartUtilities::safeStringToDartString(const AtomicString& str) |
+{ |
+ return safeStringImplToDartString(str.impl()); |
+} |
+ |
+template <typename Trait> |
+typename Trait::nativeType convert(Dart_Handle object, Dart_Handle& exception) |
+{ |
+ typename Trait::nativeType value; |
+ Dart_Handle result = Trait::convert(object, &value); |
+ if (Dart_IsError(result)) { |
+ exception = Dart_NewStringFromCString(Dart_GetError(result)); |
+ return typename Trait::nativeType(); |
+ } |
+ return value; |
+} |
+ |
+struct IntegerTrait { |
+ typedef int64_t nativeType; |
+ static Dart_Handle convert(Dart_Handle object, int64_t* value) |
+ { |
+ return Dart_IntegerToInt64(object, value); |
+ // FIXME: support bigints. |
+ } |
+}; |
+ |
+int64_t DartUtilities::toInteger(Dart_Handle object, Dart_Handle& exception) |
+{ |
+ return convert<IntegerTrait>(object, exception); |
+} |
+ |
+String DartUtilities::toString(Dart_Handle object) |
+{ |
+ Dart_Handle exception = 0; |
+ String string = dartToString(object, exception); |
+ ASSERT(!exception); |
+ return string; |
+} |
+ |
+struct DoubleTrait { |
+ typedef double nativeType; |
+ static Dart_Handle convert(Dart_Handle object, double* value) |
+ { |
+ if (Dart_IsDouble(object)) |
+ return Dart_DoubleValue(object, value); |
+ |
+ if (Dart_IsInteger(object)) { |
+ int64_t v = 0; |
+ Dart_Handle result = Dart_IntegerToInt64(object, &v); |
+ if (!Dart_IsError(result)) { |
+ *value = static_cast<double>(v); |
+ return result; |
+ } |
+ } |
+ |
+ if (Dart_IsNumber(object)) { |
+ object = Dart_Invoke(object, Dart_NewStringFromCString("toDouble"), 0, 0); |
+ if (Dart_IsError(object)) |
+ return object; |
+ } |
+ |
+ // For non-Number objects, use the error message returned by Dart_DoubleValue. |
+ return Dart_DoubleValue(object, value); |
+ } |
+}; |
+ |
+double DartUtilities::dartToDouble(Dart_Handle object, Dart_Handle& exception) |
+{ |
+ return convert<DoubleTrait>(object, exception); |
+} |
+ |
+struct BoolTrait { |
+ typedef bool nativeType; |
+ static Dart_Handle convert(Dart_Handle object, bool* value) |
+ { |
+ if (Dart_IsNull(object)) { |
+ *value = false; |
+ return Dart_Null(); |
+ } |
+ return Dart_BooleanValue(object, value); |
+ } |
+}; |
+ |
+bool DartUtilities::dartToBool(Dart_Handle object, Dart_Handle& exception) |
+{ |
+ return convert<BoolTrait>(object, exception); |
+} |
+ |
+DartStringAdapter DartUtilities::dartToStringImpl(Dart_Handle object, Dart_Handle& exception, bool autoDartScope) |
+{ |
+ if (!Dart_IsError(object) && !Dart_IsNull(object)) { |
+ ASSERT(Dart_IsString(object) && !Dart_IsExternalString(object)); |
+ intptr_t charsize = Dart_IsStringLatin1(object) ? 1 : 2; |
+ intptr_t strlength; |
+ Dart_StringLength(object, &strlength); |
+ if (autoDartScope) |
+ return DartStringAdapter(toStringImpl(object, charsize, strlength)); |
+ DartApiScope apiScope; |
+ return DartStringAdapter(toStringImpl(object, charsize, strlength)); |
+ } |
+ if (!autoDartScope) { |
+ DartApiScope apiScope; |
+ DartDOMData* domData = DartDOMData::current(); |
+ Dart_Handle excp = Dart_NewStringFromCString("String expected"); |
+ Dart_SetPersistentHandle(domData->currentException(), excp); |
+ exception = domData->currentException(); |
+ } else { |
+ exception = Dart_NewStringFromCString("String expected"); |
+ } |
+ return DartStringAdapter(DartStringPeer::nullString()); |
+} |
+ |
+void DartUtilities::extractMapElements(Dart_Handle map, Dart_Handle& exception, HashMap<String, Dart_Handle>& elements) |
+{ |
+ ASSERT(elements.isEmpty()); |
+ Dart_Handle list = DartUtilities::invokeUtilsMethod("convertMapToList", 1, &map); |
+ if (!DartUtilities::checkResult(list, exception)) |
+ return; |
+ ASSERT(Dart_IsList(list)); |
+ |
+ intptr_t length = 0; |
+ Dart_ListLength(list, &length); |
+ ASSERT(length % 2 == 0); |
+ |
+ for (intptr_t i = 0; i < length; i += 2) { |
+ Dart_Handle key = Dart_ListGetAt(list, i); |
+ ASSERT(!Dart_IsError(key) && Dart_IsString(key)); |
+ Dart_Handle value = Dart_ListGetAt(list, i+1); |
+ ASSERT(!Dart_IsError(value)); |
+ String keyString = DartUtilities::dartToString(key, exception); |
+ if (exception) |
+ return; |
+ elements.add(keyString, value); |
+ } |
+} |
+ |
+Dart_Handle DartUtilities::toList(const Vector<Dart_Handle>& elements, Dart_Handle& exception) |
+{ |
+ Dart_Handle ret = Dart_NewList(elements.size()); |
+ if (Dart_IsError(ret)) { |
+ exception = ret; |
+ return Dart_Null(); |
+ } |
+ for (size_t i = 0; i < elements.size(); i++) { |
+ Dart_ListSetAt(ret, i, elements[i]); |
+ } |
+ return ret; |
+} |
+ |
+void DartUtilities::extractListElements(Dart_Handle list, Dart_Handle& exception, Vector<Dart_Handle>& elements) |
+{ |
+ ASSERT(elements.isEmpty()); |
+ list = DartUtilities::invokeUtilsMethod("convertToList", 1, &list); |
+ if (!DartUtilities::checkResult(list, exception)) |
+ return; |
+ ASSERT(Dart_IsList(list)); |
+ |
+ intptr_t length = 0; |
+ Dart_ListLength(list, &length); |
+ elements.reserveCapacity(length); |
+ for (intptr_t i = 0; i < length; i++) { |
+ Dart_Handle element = Dart_ListGetAt(list, i); |
+ ASSERT(!Dart_IsError(element)); |
+ elements.append(element); |
+ } |
+} |
+ |
+v8::Local<v8::Context> DartUtilities::currentV8Context() |
+{ |
+ LocalFrame* frame = DartUtilities::domWindowForCurrentIsolate()->frame(); |
+ v8::Local<v8::Context> context = toV8Context(frame, DOMWrapperWorld::mainWorld()); |
+ ASSERT(!context.IsEmpty()); |
+ return context; |
+} |
+ |
+int DartUtilities::dartToInt(Dart_Handle object, Dart_Handle& exception) |
+{ |
+ int64_t value = toInteger(object, exception); |
+ if (exception) |
+ return 0; |
+ if (value < INT_MIN || value > INT_MAX) { |
+ exception = Dart_NewStringFromCString("value out of range"); |
+ return 0; |
+ } |
+ return value; |
+} |
+ |
+unsigned DartUtilities::dartToUnsigned(Dart_Handle object, Dart_Handle& exception) |
+{ |
+ int64_t value = toInteger(object, exception); |
+ if (exception) |
+ return 0; |
+ if (value < 0 || value > UINT_MAX) { |
+ exception = Dart_NewStringFromCString("value out of range"); |
+ return 0; |
+ } |
+ return value; |
+} |
+ |
+long long DartUtilities::dartToLongLong(Dart_Handle object, Dart_Handle& exception) |
+{ |
+ // FIXME: proper processing of longer integer values. |
+ return toInteger(object, exception); |
+} |
+ |
+unsigned long long DartUtilities::dartToUnsignedLongLong(Dart_Handle object, Dart_Handle& exception) |
+{ |
+ // FIXME: proper processing of longer integer values. |
+ int64_t value = toInteger(object, exception); |
+ if (exception) |
+ return 0; |
+ if (value < 0) { |
+ exception = Dart_NewStringFromCString("value out of range"); |
+ return 0; |
+ } |
+ return value; |
+} |
+ |
+Dart_Handle DartUtilities::numberToDart(double value) |
+{ |
+ // JS can store integer values that are no greater than 2^53 - 1. |
+ if (-kJSMaxInteger <= value && value <= kJSMaxInteger) { |
+ int64_t intValue = static_cast<int64_t>(value); |
+ if (value == intValue) |
+ return intToDart(intValue); |
+ } |
+ return doubleToDart(value); |
+} |
+ |
+ScriptValue DartUtilities::dartToScriptValue(Dart_Handle object) |
+{ |
+ return ScriptValue(DartScriptValue::create(currentScriptState(), object)); |
+} |
+ |
+PassRefPtr<SerializedScriptValue> DartUtilities::toSerializedScriptValue(Dart_Handle value, MessagePortArray* ports, ArrayBufferArray* arrayBuffers, Dart_Handle& exception) |
+{ |
+ v8::Handle<v8::Value> v8Value = V8Converter::toV8(value, exception); |
+ if (exception) |
+ return nullptr; |
+ |
+ V8TrackExceptionState exceptionState; |
+ RefPtr<SerializedScriptValue> message = SerializedScriptValue::create(v8Value, ports, arrayBuffers, exceptionState, v8::Isolate::GetCurrent()); |
+ if (exceptionState.hadException()) { |
+ // FIXME: better exception here. We should match the exception v8 would throw. |
+ exception = Dart_NewStringFromCString("Failed to create SerializedScriptValue"); |
+ return nullptr; |
+ } |
+ |
+ return message.release(); |
+} |
+ |
+Dart_Handle DartUtilities::dateToDart(double date) |
+{ |
+ Dart_Handle asDouble = DartUtilities::doubleToDart(date); |
+ ASSERT(!Dart_IsError(asDouble)); |
+ return DartUtilities::invokeUtilsMethod("doubleToDateTime", 1, &asDouble); |
+} |
+ |
+double DartUtilities::dartToDate(Dart_Handle date, Dart_Handle& exception) |
+{ |
+ Dart_Handle asDouble = DartUtilities::invokeUtilsMethod("dateTimeToDouble", 1, &date); |
+ if (!DartUtilities::checkResult(asDouble, exception)) |
+ return 0.0; |
+ |
+ return DartUtilities::dartToDouble(asDouble, exception); |
+} |
+ |
+double DartUtilities::dartToDate(Dart_NativeArguments args, int idx, Dart_Handle& exception) |
+{ |
+ Dart_Handle object = Dart_GetNativeArgument(args, idx); |
+ return dartToDate(object, exception); |
+} |
+ |
+bool DartUtilities::isDateTime(DartDOMData* domData, Dart_Handle handle) |
+{ |
+ Dart_Handle dartType = DartUtilities::getDartType("dart:core", "DateTime"); |
+ return objectIsType(handle, dartType); |
+} |
+ |
+bool DartUtilities::objectIsType(Dart_Handle handle, Dart_Handle type) |
+{ |
+ bool isType = false; |
+ Dart_Handle result = Dart_ObjectIsType(handle, type, &isType); |
+ if (Dart_IsError(result)) |
+ return false; |
+ return isType; |
+} |
+ |
+bool DartUtilities::isTypeSubclassOf(Dart_Handle type, Dart_Handle library, const char* typeName) |
+{ |
+ Dart_Handle other = Dart_GetType(library, Dart_NewStringFromCString(typeName), 0, 0); |
+ ASSERT(!Dart_IsError(other)); |
+ |
+ Dart_Handle args[2] = { type, other }; |
+ Dart_Handle result = DartUtilities::invokeUtilsMethod("isTypeSubclassOf", 2, args); |
+ if (Dart_IsError(result)) { |
+ ASSERT_NOT_REACHED(); |
+ return false; |
+ } |
+ |
+ Dart_Handle exception = 0; |
+ bool boolResult = dartToBool(result, exception); |
+ if (exception) |
+ return false; |
+ return boolResult; |
+} |
+ |
+Dart_Handle DartUtilities::getAndValidateNativeType(Dart_Handle type, const String& tagName) |
+{ |
+ Dart_Handle args[2] = { type, stringToDartString(tagName) }; |
+ Dart_Handle result = DartUtilities::invokeUtilsMethod("getAndValidateNativeType", 2, args); |
+ ASSERT(!Dart_IsError(result)); |
+ if (Dart_IsError(result)) { |
+ ASSERT_NOT_REACHED(); |
+ return Dart_Null(); |
+ } |
+ return result; |
+} |
+ |
+bool DartUtilities::isFunction(DartDOMData* domData, Dart_Handle handle) |
+{ |
+ return DartUtilities::objectIsType(handle, domData->functionType()); |
+} |
+ |
+Dart_Handle DartUtilities::getDartType(const char* libraryName, const char* typeName) |
+{ |
+ Dart_Handle library = Dart_LookupLibrary(Dart_NewStringFromCString(libraryName)); |
+ ASSERT(!Dart_IsError(library)); |
+ |
+ Dart_Handle dartType = Dart_GetType(library, Dart_NewStringFromCString(typeName), 0, 0); |
+ ASSERT(!Dart_IsError(dartType)); |
+ |
+ return dartType; |
+} |
+ |
+Dart_Handle DartUtilities::getDartHtmlType(const char* typeName) |
+{ |
+ Dart_Handle dartType = Dart_GetType(DartDOMData::current()->htmlLibrary(), |
+ Dart_NewStringFromCString(typeName), 0, 0); |
+ ASSERT(!Dart_IsError(dartType)); |
+ |
+ return dartType; |
+} |
+ |
+bool DartUtilities::isNode(Dart_Handle handle) |
+{ |
+ Dart_Handle dartType = DartUtilities::getDartHtmlType("Node"); |
+ return objectIsType(handle, dartType); |
+} |
+ |
+Node* DartUtilities::dartNodeToNativeNode(void* value) |
+{ |
+ return static_cast<Node*>(value); |
+} |
+ |
+bool DartUtilities::isMessagePort(Dart_Handle handle) |
+{ |
+ Dart_Handle dartType = DartUtilities::getDartHtmlType("MessagePort"); |
+ return objectIsType(handle, dartType); |
+} |
+ |
+MessagePort* DartUtilities::dartMessagePortToNativeMessagePort(void* value) |
+{ |
+ return static_cast<MessagePort*>(value); |
+} |
+ |
+static Dart_TypedData_Type typedDataTypeFromViewType(ArrayBufferView::ViewType type) |
+{ |
+ switch (type) { |
+ case ArrayBufferView::TypeInt8: |
+ return Dart_TypedData_kInt8; |
+ case ArrayBufferView::TypeUint8: |
+ return Dart_TypedData_kUint8; |
+ case ArrayBufferView::TypeUint8Clamped: |
+ return Dart_TypedData_kUint8Clamped; |
+ case ArrayBufferView::TypeInt16: |
+ return Dart_TypedData_kInt16; |
+ case ArrayBufferView::TypeUint16: |
+ return Dart_TypedData_kUint16; |
+ case ArrayBufferView::TypeInt32: |
+ return Dart_TypedData_kInt32; |
+ case ArrayBufferView::TypeUint32: |
+ return Dart_TypedData_kUint32; |
+ case ArrayBufferView::TypeFloat32: |
+ return Dart_TypedData_kFloat32; |
+ case ArrayBufferView::TypeFloat64: |
+ return Dart_TypedData_kFloat64; |
+ case ArrayBufferView::TypeDataView: |
+ return Dart_TypedData_kByteData; |
+ } |
+ ASSERT_NOT_REACHED(); |
+ return Dart_TypedData_kInvalid; |
+} |
+ |
+static unsigned elementSizeFromViewType(Dart_TypedData_Type type) |
+{ |
+ switch (type) { |
+ case Dart_TypedData_kByteData: |
+ return sizeof(uint8_t); |
+ case Dart_TypedData_kInt8: |
+ return sizeof(int8_t); |
+ case Dart_TypedData_kUint8: |
+ return sizeof(uint8_t); |
+ case Dart_TypedData_kUint8Clamped: |
+ return sizeof(uint8_t); |
+ case Dart_TypedData_kInt16: |
+ return sizeof(int16_t); |
+ case Dart_TypedData_kUint16: |
+ return sizeof(uint16_t); |
+ case Dart_TypedData_kInt32: |
+ return sizeof(int32_t); |
+ case Dart_TypedData_kUint32: |
+ return sizeof(uint32_t); |
+ case Dart_TypedData_kFloat32: |
+ return sizeof(float); |
+ case Dart_TypedData_kFloat64: |
+ return sizeof(double); |
+ case Dart_TypedData_kFloat32x4: |
+ return 4 * sizeof(float); |
+ default: |
+ break; |
+ } |
+ ASSERT_NOT_REACHED(); |
+ return 0; |
+} |
+ |
+static unsigned elementSizeFromViewType(ArrayBufferView::ViewType type) |
+{ |
+ return elementSizeFromViewType(typedDataTypeFromViewType(type)); |
+} |
+ |
+class TypedDataPeer { |
+public: |
+ virtual ~TypedDataPeer() { }; |
+ virtual bool isViewPeer() = 0; |
+}; |
+ |
+class TypedBufferPeer : public TypedDataPeer { |
+public: |
+ TypedBufferPeer(PassRefPtr<ArrayBuffer> buffer) : m_buffer(buffer) { } |
+ virtual ~TypedBufferPeer() { } |
+ |
+ PassRefPtr<ArrayBuffer> buffer() |
+ { |
+ return m_buffer; |
+ } |
+ |
+ virtual bool isViewPeer() |
+ { |
+ return false; |
+ } |
+ |
+private: |
+ RefPtr<ArrayBuffer> m_buffer; |
+}; |
+ |
+class TypedViewPeer : public TypedDataPeer { |
+public: |
+ TypedViewPeer(PassRefPtr<ArrayBufferView> view) : m_view(view) { } |
+ virtual ~TypedViewPeer() { } |
+ |
+ PassRefPtr<ArrayBufferView> view() |
+ { |
+ return m_view; |
+ } |
+ |
+ virtual bool isViewPeer() |
+ { |
+ return true; |
+ } |
+ |
+private: |
+ RefPtr<ArrayBufferView> m_view; |
+}; |
+ |
+static void externalArrayBufferCallback(void* isolateCallbackData, Dart_WeakPersistentHandle handle, void* peer) |
+{ |
+ delete reinterpret_cast<TypedDataPeer*>(peer); |
+} |
+ |
+static Dart_Handle createExternalTypedData(Dart_TypedData_Type type, void* data, intptr_t numberOfElements, TypedDataPeer* peer, intptr_t peerSize, Dart_WeakPersistentHandleFinalizer callback) |
+{ |
+ Dart_Handle newInstance = Dart_NewExternalTypedData(type, data, numberOfElements); |
+ Dart_Handle result = Dart_SetPeer(newInstance, peer); |
+ if (Dart_IsError(result)) |
+ return result; |
+ Dart_NewWeakPersistentHandle(newInstance, peer, peerSize, callback); |
+ return newInstance; |
+} |
+ |
+Dart_Handle DartUtilities::arrayBufferToDart(WTF::ArrayBuffer* buffer) |
+{ |
+ void* data = buffer->data(); |
+ unsigned byteLength = buffer->byteLength(); |
+ TypedBufferPeer* peer = new TypedBufferPeer(buffer); |
+ Dart_Handle typedData = createExternalTypedData(Dart_TypedData_kUint8, data, byteLength, peer, byteLength, externalArrayBufferCallback); |
+ ASSERT(!Dart_IsError(typedData)); |
+ return Dart_NewByteBuffer(typedData); |
+} |
+ |
+static bool externalTypedDataGetPeer(Dart_Handle handle, void** peer) |
+{ |
+ *peer = 0; |
+ Dart_Handle getPeerResult = Dart_GetPeer(handle, peer); |
+ if (!Dart_IsError(getPeerResult) && *peer) { |
+ return true; |
+ } |
+ return false; |
+} |
+ |
+static PassRefPtr<WTF::ArrayBuffer> dartToArrayBufferHelper(Dart_Handle array, Dart_Handle& exception, bool externalize) |
+{ |
+ void* data = 0; |
+ |
+ // If a ByteBuffer is passed in extract the typed data first. |
+ if (Dart_IsByteBuffer(array)) { |
+ array = Dart_GetDataFromByteBuffer(array); |
+ } |
+ |
+ // Check if the Dart array buffer object is external and has an |
+ // ArrayBuffer peer. |
+ if (externalTypedDataGetPeer(array, &data) && !reinterpret_cast<TypedDataPeer*>(data)->isViewPeer()) { |
+ return reinterpret_cast<TypedBufferPeer*>(data)->buffer(); |
+ } |
+ |
+ Dart_TypedData_Type type; |
+ intptr_t elementLength = 0; |
+ intptr_t byteLength = 0; |
+ |
+ // Check if the Dart object is a typed data object by acquiring its data. |
+ // If it is, create a thin ArrayBuffer wrapper around the data in the dart |
+ // heap. |
+ Dart_Handle result = Dart_TypedDataAcquireData(array, &type, &data, &elementLength); |
+ if (Dart_IsError(result)) { |
+ exception = Dart_NewStringFromCString("Typed data object expected"); |
+ return nullptr; |
+ } |
+ // FIXME: we really shouldn't release the data until we are done with it. |
+ Dart_TypedDataReleaseData(array); |
+ byteLength = elementLength * elementSizeFromViewType(type); |
+ return externalize ? ArrayBuffer::create(data, byteLength) : ArrayBuffer::createNoCopy(data, byteLength); |
+} |
+ |
+PassRefPtr<WTF::ArrayBuffer> DartUtilities::dartToArrayBuffer(Dart_Handle array, Dart_Handle& exception) |
+{ |
+ return dartToArrayBufferHelper(array, exception, false); |
+} |
+ |
+PassRefPtr<WTF::ArrayBuffer> DartUtilities::dartToExternalizedArrayBuffer(Dart_Handle array, Dart_Handle& exception) |
+{ |
+ return dartToArrayBufferHelper(array, exception, true); |
+} |
+ |
+// FIXME: This mapping to dart objects loses object identity for |
+// the buffer part of views. If we have two views on the same buffer |
+// in C++ and we create dart wrappers we will get two different dart |
+// buffer objects. Additionally, this means that neutering will not work. |
+Dart_Handle DartUtilities::arrayBufferViewToDart(WTF::ArrayBufferView* view) |
+{ |
+ ArrayBufferView::ViewType type = view->type(); |
+ void* address = view->baseAddress(); |
+ unsigned byteLength = view->byteLength(); |
+ unsigned length = byteLength / elementSizeFromViewType(type); |
+ TypedViewPeer* peer = new TypedViewPeer(view); |
+ return createExternalTypedData(typedDataTypeFromViewType(type), address, length, peer, byteLength, externalArrayBufferCallback); |
+} |
+ |
+ |
+// FIXME: Again, this breaks the view-buffer relationship. |
+static PassRefPtr<WTF::ArrayBufferView> dartToArrayBufferViewHelper(Dart_Handle array, Dart_Handle& exception, bool externalize) |
+{ |
+ void* data = 0; |
+ |
+ // Check if the array is external and has an ArrayBufferView peer. |
+ if (externalTypedDataGetPeer(array, &data)) { |
+ if (!reinterpret_cast<TypedDataPeer*>(data)->isViewPeer()) { |
+ exception = Dart_NewStringFromCString("Typed data view expected"); |
+ return nullptr; |
+ } |
+ return reinterpret_cast<TypedViewPeer*>(data)->view(); |
+ } |
+ |
+ // Check if the dart object is an internal typed data object and get |
+ // the data from it. |
+ Dart_TypedData_Type type; |
+ intptr_t elementLength = 0; |
+ Dart_Handle result = Dart_TypedDataAcquireData(array, &type, &data, &elementLength); |
+ if (Dart_IsError(result)) { |
+ exception = Dart_NewStringFromCString("Typed data object expected"); |
+ return nullptr; |
+ } |
+ intptr_t byteLength = elementLength * elementSizeFromViewType(type); |
+ // FIXME: we really shouldn't release the data until we are done with it. |
+ Dart_TypedDataReleaseData(array); |
+ RefPtr<ArrayBuffer> buffer = externalize ? ArrayBuffer::create(data, byteLength) : ArrayBuffer::createNoCopy(data, byteLength); |
+ |
+ switch (type) { |
+ case Dart_TypedData_kByteData: |
+ return DataView::create(buffer, 0, elementLength); |
+ case Dart_TypedData_kInt8: |
+ return Int8Array::create(buffer, 0, elementLength); |
+ case Dart_TypedData_kUint8: |
+ return Uint8Array::create(buffer, 0, elementLength); |
+ case Dart_TypedData_kUint8Clamped: |
+ return Uint8ClampedArray::create(buffer, 0, elementLength); |
+ case Dart_TypedData_kInt16: |
+ return Uint16Array::create(buffer, 0, elementLength); |
+ case Dart_TypedData_kUint16: |
+ return Uint16Array::create(buffer, 0, elementLength); |
+ case Dart_TypedData_kInt32: |
+ return Int32Array::create(buffer, 0, elementLength); |
+ case Dart_TypedData_kUint32: |
+ return Uint32Array::create(buffer, 0, elementLength); |
+ case Dart_TypedData_kFloat32: |
+ return Float32Array::create(buffer, 0, elementLength); |
+ case Dart_TypedData_kFloat64: |
+ return Float64Array::create(buffer, 0, elementLength); |
+ case Dart_TypedData_kFloat32x4: |
+ return Float32Array::create(buffer, 0, elementLength * sizeof(float)); |
+ default: |
+ break; |
+ } |
+ ASSERT_NOT_REACHED(); |
+ return nullptr; |
+} |
+ |
+PassRefPtr<WTF::ArrayBufferView> DartUtilities::dartToArrayBufferView(Dart_Handle array, Dart_Handle& exception) |
+{ |
+ return dartToArrayBufferViewHelper(array, exception, false); |
+} |
+ |
+PassRefPtr<WTF::ArrayBufferView> DartUtilities::dartToExternalizedArrayBufferView(Dart_Handle array, Dart_Handle& exception) |
+{ |
+ return dartToArrayBufferViewHelper(array, exception, true); |
+} |
+ |
+PassRefPtr<WTF::Int8Array> DartUtilities::dartToInt8ArrayWithNullCheck(Dart_Handle handle, Dart_Handle& exception) |
+{ |
+ return Dart_IsNull(handle) ? nullptr : dartToInt8Array(handle, exception); |
+} |
+ |
+PassRefPtr<WTF::Int8Array> DartUtilities::dartToInt8Array(Dart_Handle handle, Dart_Handle& exception) |
+{ |
+ RefPtr<ArrayBufferView> view = DartUtilities::dartToArrayBufferView(handle, exception); |
+ if (exception) |
+ return nullptr; |
+ if (view->type() == ArrayBufferView::TypeInt8) |
+ return reinterpret_cast<Int8Array*>(view.get()); |
+ exception = Dart_NewStringFromCString("Int8List expected"); |
+ return nullptr; |
+} |
+ |
+PassRefPtr<WTF::Int8Array> DartUtilities::dartToInt8ArrayWithNullCheck(Dart_NativeArguments args, int idx, Dart_Handle& exception) |
+{ |
+ Dart_Handle object = Dart_GetNativeArgument(args, idx); |
+ return dartToInt8ArrayWithNullCheck(object, exception); |
+} |
+ |
+PassRefPtr<WTF::Int8Array> DartUtilities::dartToInt8Array(Dart_NativeArguments args, int idx, Dart_Handle& exception) |
+{ |
+ Dart_Handle object = Dart_GetNativeArgument(args, idx); |
+ return dartToInt8Array(object, exception); |
+} |
+ |
+PassRefPtr<WTF::Int32Array> DartUtilities::dartToInt32ArrayWithNullCheck(Dart_Handle handle, Dart_Handle& exception) |
+{ |
+ return Dart_IsNull(handle) ? nullptr : dartToInt32Array(handle, exception); |
+} |
+ |
+PassRefPtr<WTF::Int32Array> DartUtilities::dartToInt32Array(Dart_Handle handle, Dart_Handle& exception) |
+{ |
+ RefPtr<ArrayBufferView> view = DartUtilities::dartToArrayBufferView(handle, exception); |
+ if (exception) |
+ return nullptr; |
+ if (view->type() == ArrayBufferView::TypeInt32) |
+ return reinterpret_cast<Int32Array*>(view.get()); |
+ exception = Dart_NewStringFromCString("Int32List expected"); |
+ return nullptr; |
+} |
+ |
+PassRefPtr<WTF::Int32Array> DartUtilities::dartToInt32ArrayWithNullCheck(Dart_NativeArguments args, int idx, Dart_Handle& exception) |
+{ |
+ Dart_Handle object = Dart_GetNativeArgument(args, idx); |
+ return dartToInt32ArrayWithNullCheck(object, exception); |
+} |
+ |
+PassRefPtr<WTF::Int32Array> DartUtilities::dartToInt32Array(Dart_NativeArguments args, int idx, Dart_Handle& exception) |
+{ |
+ Dart_Handle object = Dart_GetNativeArgument(args, idx); |
+ return dartToInt32Array(object, exception); |
+} |
+ |
+PassRefPtr<WTF::Uint8ClampedArray> DartUtilities::dartToUint8ClampedArrayWithNullCheck(Dart_Handle handle, Dart_Handle& exception) |
+{ |
+ return Dart_IsNull(handle) ? nullptr : dartToUint8ClampedArray(handle, exception); |
+} |
+ |
+PassRefPtr<WTF::Uint8ClampedArray> DartUtilities::dartToUint8ClampedArray(Dart_Handle handle, Dart_Handle& exception) |
+{ |
+ RefPtr<ArrayBufferView> view = DartUtilities::dartToArrayBufferView(handle, exception); |
+ if (exception) |
+ return nullptr; |
+ if (view->type() == ArrayBufferView::TypeUint8Clamped) |
+ return reinterpret_cast<Uint8ClampedArray*>(view.get()); |
+ exception = Dart_NewStringFromCString("Uint8ClampedList expected"); |
+ return nullptr; |
+} |
+ |
+PassRefPtr<WTF::Uint8ClampedArray> DartUtilities::dartToUint8ClampedArrayWithNullCheck(Dart_NativeArguments args, int idx, Dart_Handle& exception) |
+{ |
+ Dart_Handle object = Dart_GetNativeArgument(args, idx); |
+ return dartToUint8ClampedArrayWithNullCheck(object, exception); |
+} |
+ |
+PassRefPtr<WTF::Uint8ClampedArray> DartUtilities::dartToUint8ClampedArray(Dart_NativeArguments args, int idx, Dart_Handle& exception) |
+{ |
+ Dart_Handle object = Dart_GetNativeArgument(args, idx); |
+ return dartToUint8ClampedArray(object, exception); |
+} |
+ |
+PassRefPtr<WTF::Uint8Array> DartUtilities::dartToUint8ArrayWithNullCheck(Dart_Handle handle, Dart_Handle& exception) |
+{ |
+ return Dart_IsNull(handle) ? nullptr : dartToUint8Array(handle, exception); |
+} |
+ |
+PassRefPtr<WTF::Uint8Array> DartUtilities::dartToUint8Array(Dart_Handle handle, Dart_Handle& exception) |
+{ |
+ RefPtr<ArrayBufferView> view = DartUtilities::dartToArrayBufferView(handle, exception); |
+ if (exception) |
+ return nullptr; |
+ if (view->type() == ArrayBufferView::TypeUint8) |
+ return reinterpret_cast<Uint8Array*>(view.get()); |
+ exception = Dart_NewStringFromCString("Uint8List expected"); |
+ return nullptr; |
+} |
+ |
+PassRefPtr<WTF::Uint8Array> DartUtilities::dartToUint8ArrayWithNullCheck(Dart_NativeArguments args, int idx, Dart_Handle& exception) |
+{ |
+ Dart_Handle object = Dart_GetNativeArgument(args, idx); |
+ return dartToUint8ArrayWithNullCheck(object, exception); |
+} |
+ |
+PassRefPtr<WTF::Uint8Array> DartUtilities::dartToUint8Array(Dart_NativeArguments args, int idx, Dart_Handle& exception) |
+{ |
+ Dart_Handle object = Dart_GetNativeArgument(args, idx); |
+ return dartToUint8Array(object, exception); |
+} |
+ |
+PassRefPtr<WTF::Float32Array> DartUtilities::dartToFloat32ArrayWithNullCheck(Dart_Handle handle, Dart_Handle& exception) |
+{ |
+ return Dart_IsNull(handle) ? nullptr : dartToFloat32Array(handle, exception); |
+} |
+ |
+PassRefPtr<WTF::Float32Array> DartUtilities::dartToFloat32Array(Dart_Handle handle, Dart_Handle& exception) |
+{ |
+ RefPtr<ArrayBufferView> view = DartUtilities::dartToArrayBufferView(handle, exception); |
+ if (exception) |
+ return nullptr; |
+ if (view->type() == ArrayBufferView::TypeFloat32) |
+ return reinterpret_cast<Float32Array*>(view.get()); |
+ exception = Dart_NewStringFromCString("Float32List expected"); |
+ return nullptr; |
+} |
+ |
+PassRefPtr<WTF::Float32Array> DartUtilities::dartToFloat32ArrayWithNullCheck(Dart_NativeArguments args, int idx, Dart_Handle& exception) |
+{ |
+ Dart_Handle object = Dart_GetNativeArgument(args, idx); |
+ return dartToFloat32ArrayWithNullCheck(object, exception); |
+} |
+ |
+PassRefPtr<WTF::Float32Array> DartUtilities::dartToFloat32Array(Dart_NativeArguments args, int idx, Dart_Handle& exception) |
+{ |
+ Dart_Handle object = Dart_GetNativeArgument(args, idx); |
+ return dartToFloat32Array(object, exception); |
+} |
+ |
+bool DartUtilities::isUint8Array(Dart_Handle object) |
+{ |
+ return Dart_GetTypeOfTypedData(object) == Dart_TypedData_kUint8; |
+} |
+ |
+bool DartUtilities::isUint8ClampedArray(Dart_Handle object) |
+{ |
+ return Dart_GetTypeOfTypedData(object) == Dart_TypedData_kUint8Clamped; |
+} |
+ |
+SQLValue DartUtilities::toSQLValue(Dart_Handle object, Dart_Handle& exception) |
+{ |
+ if (Dart_IsNull(object)) |
+ return SQLValue(); |
+ |
+ if (Dart_IsNumber(object)) |
+ return SQLValue(DartUtilities::dartToDouble(object, exception)); |
+ |
+ return SQLValue(DartUtilities::dartToString(object, exception)); |
+} |
+ |
+PassRefPtr<SerializedScriptValue> DartUtilities::dartToSerializedScriptValue(Dart_Handle object, Dart_Handle& exception) |
+{ |
+ return toSerializedScriptValue(object, 0, 0, exception); |
+} |
+ |
+Dart_Handle DartUtilities::serializedScriptValueToDart(PassRefPtr<SerializedScriptValue> value) |
+{ |
+ // FIXME: better error handling. |
+ Dart_Handle exception = 0; |
+ return V8Converter::toDart(value->deserialize(), exception); |
+} |
+ |
+// FIXME: this function requires better testing. Currently blocking as new MessageChannel hasn't been implemented yet. |
+void DartUtilities::toMessagePortArray(Dart_Handle value, MessagePortArray& ports, ArrayBufferArray& arrayBuffers, Dart_Handle& exception) |
+{ |
+ Vector<Dart_Handle> elements; |
+ DartUtilities::extractListElements(value, exception, elements); |
+ if (exception) |
+ return; |
+ |
+ for (size_t i = 0; i < elements.size(); i++) { |
+ Dart_Handle element = elements[i]; |
+ if (DartUtilities::isMessagePort(element)) { |
+ MessagePort* messagePort = DartUtilities::dartMessagePortToNativeMessagePort(element); |
+ ASSERT(messagePort); |
+ ports.append(messagePort); |
+ continue; |
+ } |
+ |
+ if (Dart_IsByteBuffer(element)) { |
+ element = Dart_GetDataFromByteBuffer(element); |
+ RefPtr<ArrayBuffer> arrayBuffer = DartUtilities::dartToExternalizedArrayBuffer(element, exception); |
+ ASSERT(!exception); |
+ ASSERT(arrayBuffer); |
+ arrayBuffers.append(arrayBuffer); |
+ continue; |
+ } |
+ |
+ exception = Dart_NewStringFromCString("TransferArray argument must contain only Transferables"); |
+ return; |
+ } |
+} |
+ |
+Dictionary DartUtilities::dartToDictionary(Dart_Handle object, Dart_Handle& exception) |
+{ |
+ v8::Isolate* v8Isolate = v8::Isolate::GetCurrent(); |
+ v8::Local<v8::Value> value = v8::Local<v8::Value>::New(v8Isolate, V8Converter::toV8(object, exception)); |
+ if (exception) |
+ return Dictionary(); |
+ return Dictionary(value, v8Isolate); |
+} |
+ |
+Dictionary DartUtilities::dartToDictionaryWithNullCheck(Dart_Handle object, Dart_Handle& exception) |
+{ |
+ if (Dart_IsNull(object)) |
+ return Dictionary(); |
+ return dartToDictionary(object, exception); |
+} |
+ |
+Dictionary DartUtilities::dartToDictionary(Dart_NativeArguments args, int idx, Dart_Handle& exception) |
+{ |
+ Dart_Handle object = Dart_GetNativeArgument(args, idx); |
+ return dartToDictionary(object, exception); |
+} |
+ |
+Dictionary DartUtilities::dartToDictionaryWithNullCheck(Dart_NativeArguments args, int idx, Dart_Handle& exception) |
+{ |
+ Dart_Handle object = Dart_GetNativeArgument(args, idx); |
+ return dartToDictionaryWithNullCheck(object, exception); |
+} |
+ |
+LocalDOMWindow* DartUtilities::domWindowForCurrentIsolate() |
+{ |
+ DartDOMData* domData = DartDOMData::current(); |
+ ASSERT(domData->scriptExecutionContext()->isDocument()); |
+ Document* document = static_cast<Document*>(domData->scriptExecutionContext()); |
+ return document->domWindow(); |
+} |
+ |
+V8ScriptState* DartUtilities::v8ScriptStateForCurrentIsolate() |
+{ |
+ return V8ScriptState::forMainWorld(domWindowForCurrentIsolate()->frame()); |
+} |
+ |
+ExecutionContext* DartUtilities::scriptExecutionContext() |
+{ |
+ if (Dart_CurrentIsolate()) |
+ return DartDOMData::current()->scriptExecutionContext(); |
+ return 0; |
+} |
+ |
+bool DartUtilities::processingUserGesture() |
+{ |
+ // FIXME: implement this. |
+ return false; |
+} |
+ |
+intptr_t DartUtilities::libraryHandleToLibraryId(Dart_Handle library) |
+{ |
+ intptr_t libraryId = -1; |
+ Dart_Handle ALLOW_UNUSED result = Dart_LibraryId(library, &libraryId); |
+ ASSERT(!Dart_IsError(result)); |
+ return libraryId; |
+} |
+ |
+DartScriptState* DartUtilities::currentScriptState() |
+{ |
+ DartDOMData* dartDOMData = DartDOMData::current(); |
+ if (!dartDOMData->rootScriptState()) { |
+ DartController* controller = DartController::retrieve(dartDOMData->scriptExecutionContext()); |
+ intptr_t libraryId = DartUtilities::libraryHandleToLibraryId(Dart_RootLibrary()); |
+ DartScriptState* scriptState = controller->lookupScriptState(Dart_CurrentIsolate(), currentV8Context(), libraryId); |
+ dartDOMData->setRootScriptState(scriptState); |
+ return scriptState; |
+ } |
+ return dartDOMData->rootScriptState(); |
+} |
+ |
+PassRefPtr<ScriptArguments> DartUtilities::createScriptArguments(Dart_Handle argument, Dart_Handle& exception) |
+{ |
+ Vector<ScriptValue> arguments; |
+ arguments.append(DartUtilities::dartToScriptValue(argument)); |
+ return ScriptArguments::create(DartUtilities::currentScriptState(), arguments); |
+} |
+ |
+static PassRefPtr<ScriptCallStack> createScriptCallStackFromStackTrace(Dart_StackTrace stackTrace) |
+{ |
+ uintptr_t frameCount = 0; |
+ Dart_Handle result = Dart_StackTraceLength(stackTrace, reinterpret_cast<intptr_t*>(&frameCount)); |
+ if (Dart_IsError(result)) |
+ return nullptr; |
+ |
+ if (frameCount > ScriptCallStack::maxCallStackSizeToCapture) |
+ frameCount = ScriptCallStack::maxCallStackSizeToCapture; |
+ |
+ Dart_Isolate isolate = Dart_CurrentIsolate(); |
+ Vector<ScriptCallFrame> scriptCallStackFrames; |
+ for (uintptr_t frameIndex = 0; frameIndex < frameCount; frameIndex++) { |
+ Dart_ActivationFrame frame = 0; |
+ result = Dart_GetActivationFrame(stackTrace, frameIndex, &frame); |
+ if (Dart_IsError(result)) { |
+ return nullptr; |
+ } |
+ ASSERT(frame); |
+ |
+ Dart_Handle dartFunctionName; |
+ Dart_Handle dartScriptUrl; |
+ intptr_t lineNumber = 0; |
+ intptr_t columnNumber = 0; |
+ result = Dart_ActivationFrameInfo(frame, &dartFunctionName, &dartScriptUrl, &lineNumber, &columnNumber); |
+ if (Dart_IsError(result)) { |
+ return nullptr; |
+ } |
+ |
+ // This skips frames where source is unavailable. WebKit code for the |
+ // console assumes that console.log et al. are implemented directly |
+ // as natives, i.e. that the top-of-stack will be the caller of |
+ // console.log. The Dart implementation involves intermediate Dart |
+ // calls, which are skipped by this clause. |
+ if (columnNumber == -1) |
+ continue; |
+ |
+ String functionName = DartUtilities::toString(dartFunctionName); |
+ String scriptUrl = DartUtilities::toString(dartScriptUrl); |
+ |
+ scriptCallStackFrames.append(ScriptCallFrame(functionName, DartScriptDebugServer::shared().getScriptId(scriptUrl, isolate), scriptUrl, lineNumber, columnNumber)); |
+ } |
+ if (scriptCallStackFrames.isEmpty()) |
+ scriptCallStackFrames.append(ScriptCallFrame("undefined", "undefined", "undefined", 0, 0)); |
+ |
+ return ScriptCallStack::create(scriptCallStackFrames); |
+} |
+ |
+ScriptCallFrame DartUtilities::getTopFrame(Dart_StackTrace stackTrace, Dart_Handle& exception) |
+{ |
+ { |
+ uintptr_t frameCount = 0; |
+ Dart_Handle result = Dart_StackTraceLength(stackTrace, reinterpret_cast<intptr_t*>(&frameCount)); |
+ if (Dart_IsError(result)) { |
+ exception = result; |
+ goto fail; |
+ } |
+ if (!frameCount) { |
+ exception = Dart_NewStringFromCString("Empty stack trace"); |
+ goto fail; |
+ } |
+ Dart_ActivationFrame frame = 0; |
+ result = Dart_GetActivationFrame(stackTrace, 0, &frame); |
+ if (Dart_IsError(result)) { |
+ exception = result; |
+ goto fail; |
+ } |
+ ASSERT(frame); |
+ return toScriptCallFrame(frame, exception); |
+ } |
+fail: |
+ return ScriptCallFrame("undefined", "undefined", "undefined", 0, 0); |
+} |
+ |
+ScriptCallFrame DartUtilities::toScriptCallFrame(Dart_ActivationFrame frame, Dart_Handle& exception) |
+{ |
+ ASSERT(frame); |
+ Dart_Handle functionName; |
+ Dart_Handle scriptUrl; |
+ intptr_t lineNumber = 0; |
+ intptr_t columnNumber = 0; |
+ Dart_Handle result = Dart_ActivationFrameInfo(frame, &functionName, &scriptUrl, &lineNumber, &columnNumber); |
+ if (Dart_IsError(result)) { |
+ exception = result; |
+ return ScriptCallFrame("undefined", "undefined", "undefined", 0, 0); |
+ } |
+ return ScriptCallFrame(DartUtilities::toString(functionName), "undefined", DartUtilities::toString(scriptUrl), lineNumber, columnNumber); |
+} |
+ |
+PassRefPtr<ScriptCallStack> DartUtilities::createScriptCallStack() |
+{ |
+ Dart_StackTrace trace = 0; |
+ Dart_Handle ALLOW_UNUSED result = Dart_GetStackTrace(&trace); |
+ ASSERT(!Dart_IsError(result)); |
+ ASSERT(!Dart_IsNull(result)); |
+ ASSERT(trace); |
+ return createScriptCallStackFromStackTrace(trace); |
+} |
+ |
+static const uint8_t* snapshotBuffer(int index) |
+{ |
+// DartSnapshot.bytes is generated by build system. |
+#include "bindings/dart/DartSnapshot.bytes" |
+ ASSERT(index == DartUtilities::VmIsolateSnapshotId || index == DartUtilities::IsolateSnapshotId); |
+ if (index == DartUtilities::VmIsolateSnapshotId) { |
+ return vmIsolateSnapshotBuffer; |
+ } |
+ return isolateSnapshotBuffer; |
+} |
+ |
+const uint8_t* DartUtilities::vmIsolateSnapshot() |
+{ |
+ return snapshotBuffer(VmIsolateSnapshotId); |
+} |
+ |
+const uint8_t* DartUtilities::isolateSnapshot() |
+{ |
+ return snapshotBuffer(IsolateSnapshotId); |
+} |
+ |
+Dart_Handle DartUtilities::canonicalizeUrl(Dart_Handle library, Dart_Handle urlHandle, String url) |
+{ |
+ DEFINE_STATIC_LOCAL(String, dartPrefix, ("dart:")); |
+ DEFINE_STATIC_LOCAL(String, packagePrefix, ("package:")); |
+ |
+ if (url.startsWith(dartPrefix) || url.startsWith(packagePrefix)) |
+ // Not a relative URL. |
+ return urlHandle; |
+ |
+ Dart_Handle libraryURLHandle = Dart_LibraryUrl(library); |
+ ASSERT(!Dart_IsError(libraryURLHandle)); |
+ String libraryURL = DartUtilities::toString(libraryURLHandle); |
+ |
+ String result; |
+ if (libraryURL.startsWith(packagePrefix) && !libraryURL.startsWith("package://")) { |
+ // KURL expects a URL with an authority. If the library URL is |
+ // "package:<path>", we convert to "package://_/<path>" for resolution |
+ // and convert back. |
+ DEFINE_STATIC_LOCAL(String, resolvePrefix, ("package://_/")); |
+ |
+ libraryURL = resolvePrefix + libraryURL.substring(packagePrefix.length()); |
+ result = KURL(KURL(KURL(), libraryURL), url).string(); |
+ if (result.startsWith(resolvePrefix)) |
+ result = packagePrefix + result.substring(resolvePrefix.length()); |
+ } else { |
+ result = KURL(KURL(KURL(), libraryURL), url).string(); |
+ } |
+ |
+ return DartUtilities::stringToDartString(result); |
+} |
+ |
+void DartUtilities::reportProblem(ExecutionContext* context, const String& error, int line, int col) |
+{ |
+ String sourceURL = context->url().string(); |
+ |
+ // FIXME: Pass in stack trace. |
+ if (context && context->isDocument()) { |
+ int scriptId = 0; |
+ static_cast<Document*>(context)->reportException(ErrorEvent::create(error, sourceURL, line, col, 0), scriptId, nullptr, NotSharableCrossOrigin); |
+ } |
+} |
+ |
+void DartUtilities::reportProblem(ExecutionContext* context, Dart_Handle result) |
+{ |
+ // FIXME: provide sourceURL. |
+ String sourceURL = "FIXME"; |
+ reportProblem(context, result, sourceURL); |
+} |
+ |
+void DartUtilities::reportProblem(ExecutionContext* context, Dart_Handle result, const String& sourceURL) |
+{ |
+ ASSERT(Dart_IsError(result)); |
+ ASSERT(!sourceURL.isEmpty()); |
+ |
+ const String internalErrorPrefix("Internal error: "); |
+ |
+ String errorMessage; |
+ // FIXME: line number info. |
+ int lineNumber = 0; |
+ // FIXME: call stack info. |
+ RefPtr<ScriptCallStack> callStack; |
+ |
+ if (!Dart_ErrorHasException(result)) { |
+ errorMessage = internalErrorPrefix + Dart_GetError(result); |
+ } else { |
+ // Print the exception. |
+ Dart_Handle exception = Dart_ErrorGetException(result); |
+ ASSERT(!Dart_IsError(exception)); |
+ |
+ exception = Dart_ToString(exception); |
+ if (Dart_IsError(exception)) |
+ errorMessage = String("Error: ") + Dart_GetError(exception); |
+ else |
+ errorMessage = String("Exception: ") + DartUtilities::toString(exception); |
+ |
+ // Print the stack trace. |
+ Dart_StackTrace stacktrace; |
+ Dart_Handle ALLOW_UNUSED traceResult = Dart_GetStackTraceFromError(result, &stacktrace); |
+ ASSERT(!Dart_IsError(traceResult)); |
+ callStack = createScriptCallStackFromStackTrace(stacktrace); |
+ } |
+ |
+ if (context && context->isDocument()) { |
+ int scriptId = 0; |
+ static_cast<Document*>(context)->reportException(ErrorEvent::create(errorMessage, sourceURL, lineNumber, 0, 0), scriptId, callStack, NotSharableCrossOrigin); |
+ } |
+} |
+ |
+Dart_Handle DartUtilities::toDartCoreException(const String& className, const String& message) |
+{ |
+ DartApiScope apiScope; |
+ DartDOMData* domData = DartDOMData::current(); |
+ Dart_Handle coreLib = Dart_LookupLibrary(Dart_NewStringFromCString("dart:core")); |
+ Dart_Handle errorClass = Dart_GetType(coreLib, stringToDart(className), 0, 0); |
+ Dart_Handle dartMessage = stringToDart(message); |
+ Dart_Handle error = Dart_New(errorClass, Dart_NewStringFromCString(""), 1, &dartMessage); |
+ Dart_SetPersistentHandle(domData->currentException(), error); |
+ return domData->currentException(); |
+} |
+ |
+Dart_Handle DartUtilities::coreArgumentErrorException(const String& message) |
+{ |
+ return DartUtilities::toDartCoreException("ArgumentError", message); |
+} |
+ |
+Dart_Handle DartUtilities::notImplementedException(const char* fileName, int lineNumber) |
+{ |
+ Dart_Handle args[2] = { Dart_NewStringFromCString(fileName), Dart_NewInteger(lineNumber) }; |
+ Dart_Handle result = DartUtilities::invokeUtilsMethod("makeUnimplementedError", 2, args); |
+ ASSERT(!Dart_IsError(result)); |
+ return result; |
+} |
+ |
+Dart_Handle DartUtilities::newResolvedPromise(Dart_Handle value) |
+{ |
+ Dart_Handle asyncLib = Dart_LookupLibrary(Dart_NewStringFromCString("dart:async")); |
+ Dart_Handle futureClass = Dart_GetType(asyncLib, Dart_NewStringFromCString("Future"), 0, 0); |
+ return Dart_New(futureClass, Dart_NewStringFromCString("value"), 1, &value); |
+} |
+ |
+Dart_Handle DartUtilities::newSmashedPromise(Dart_Handle error) |
+{ |
+ Dart_Handle asyncLib = Dart_LookupLibrary(Dart_NewStringFromCString("dart:async")); |
+ Dart_Handle futureClass = Dart_GetType(asyncLib, Dart_NewStringFromCString("Future"), 0, 0); |
+ return Dart_New(futureClass, Dart_NewStringFromCString("error"), 1, &error); |
+} |
+ |
+Dart_Handle DartUtilities::newResolver() |
+{ |
+ Dart_Handle asyncLib = Dart_LookupLibrary(Dart_NewStringFromCString("dart:async")); |
+ Dart_Handle futureClass = Dart_GetType(asyncLib, Dart_NewStringFromCString("Completer"), 0, 0); |
+ return Dart_New(futureClass, Dart_EmptyString(), 0, 0); |
+} |
+ |
+Dart_Handle DartUtilities::newArgumentError(const String& message) |
+{ |
+ Dart_Handle asyncLib = Dart_LookupLibrary(Dart_NewStringFromCString("dart:core")); |
+ Dart_Handle futureClass = Dart_GetType(asyncLib, Dart_NewStringFromCString("ArgumentError"), 0, 0); |
+ Dart_Handle dartMessage = stringToDart(message); |
+ return Dart_New(futureClass, Dart_EmptyString(), 1, &dartMessage); |
+} |
+ |
+Dart_Handle DartUtilities::invokeUtilsMethod(const char* methodName, int argCount, Dart_Handle* args) |
+{ |
+ DartDOMData* domData = DartDOMData::current(); |
+ ASSERT(domData); |
+ Dart_PersistentHandle library = domData->htmlLibrary(); |
+ ASSERT(!Dart_IsError(library)); |
+ |
+ Dart_Handle utilsClass = Dart_GetType(library, Dart_NewStringFromCString("_Utils"), 0, 0); |
+ ASSERT(!Dart_IsError(utilsClass)); |
+ |
+ return Dart_Invoke(utilsClass, Dart_NewStringFromCString(methodName), argCount, args); |
+} |
+ |
+ |
+int DartUtilities::getProp(const char* name, char* value, int valueLen) |
+{ |
+#if OS(ANDROID) |
+ return __system_property_get(name, value); |
+#else |
+ char* v = getenv(name); |
+ if (!v) { |
+ return 0; |
+ } |
+ ASSERT(valueLen > 0 && static_cast<size_t>(valueLen) > strlen(v)); |
+ strncpy(value, v, valueLen); |
+ value[valueLen - 1] = '\0'; |
+ return strlen(value); |
+#endif |
+} |
+} |