OLD | NEW |
(Empty) | |
| 1 // Copyright 2011, Google Inc. |
| 2 // All rights reserved. |
| 3 // |
| 4 // Redistribution and use in source and binary forms, with or without |
| 5 // modification, are permitted provided that the following conditions are |
| 6 // met: |
| 7 // |
| 8 // * Redistributions of source code must retain the above copyright |
| 9 // notice, this list of conditions and the following disclaimer. |
| 10 // * Redistributions in binary form must reproduce the above |
| 11 // copyright notice, this list of conditions and the following disclaimer |
| 12 // in the documentation and/or other materials provided with the |
| 13 // distribution. |
| 14 // * Neither the name of Google Inc. nor the names of its |
| 15 // contributors may be used to endorse or promote products derived from |
| 16 // this software without specific prior written permission. |
| 17 // |
| 18 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
| 19 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
| 20 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
| 21 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
| 22 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
| 23 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
| 24 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| 25 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| 26 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| 27 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| 28 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 29 |
| 30 #include "config.h" |
| 31 #include "bindings/core/dart/DartUtilities.h" |
| 32 |
| 33 #if OS(ANDROID) |
| 34 #include <sys/system_properties.h> |
| 35 #endif |
| 36 |
| 37 #include "core/FetchInitiatorTypeNames.h" |
| 38 #include "bindings/core/dart/DartController.h" |
| 39 #include "bindings/core/dart/DartDOMData.h" |
| 40 #include "bindings/core/dart/DartScriptDebugServer.h" |
| 41 #include "bindings/core/dart/DartScriptState.h" |
| 42 #include "bindings/core/dart/V8Converter.h" |
| 43 #include "bindings/core/v8/ScriptController.h" |
| 44 #include "bindings/core/v8/SerializedScriptValue.h" |
| 45 #include "bindings/core/v8/V8Binding.h" |
| 46 #include "bindings/core/v8/V8ExceptionState.h" |
| 47 #include "bindings/core/v8/V8PerIsolateData.h" |
| 48 #include "core/dom/Document.h" |
| 49 #include "core/events/ErrorEvent.h" |
| 50 #include "core/fetch/ResourceFetcher.h" |
| 51 #include "core/frame/LocalDOMWindow.h" |
| 52 #include "core/frame/LocalFrame.h" |
| 53 #include "core/html/canvas/DataView.h" |
| 54 #include "core/inspector/ScriptArguments.h" |
| 55 #include "core/inspector/ScriptCallStack.h" |
| 56 #include "core/loader/FrameLoader.h" |
| 57 #include "modules/webdatabase/sqlite/SQLValue.h" |
| 58 #include "platform/SharedBuffer.h" |
| 59 #include "platform/network/ResourceRequest.h" |
| 60 |
| 61 #include "wtf/ArrayBufferView.h" |
| 62 #include "wtf/Float32Array.h" |
| 63 #include "wtf/Float64Array.h" |
| 64 #include "wtf/Int16Array.h" |
| 65 #include "wtf/Int32Array.h" |
| 66 #include "wtf/Int8Array.h" |
| 67 #include "wtf/RefCounted.h" |
| 68 #include "wtf/Uint16Array.h" |
| 69 #include "wtf/Uint32Array.h" |
| 70 #include "wtf/Uint8Array.h" |
| 71 #include "wtf/Uint8ClampedArray.h" |
| 72 #include "wtf/text/AtomicString.h" |
| 73 #include "wtf/text/CString.h" |
| 74 #include "wtf/text/WTFString.h" |
| 75 |
| 76 namespace blink { |
| 77 |
| 78 V8Scope::V8Scope(DartDOMData* dartDOMData, v8::Handle<v8::Context> context) |
| 79 : m_v8Isolate(v8::Isolate::GetCurrent()) |
| 80 , m_dartDOMData(dartDOMData) |
| 81 , m_handleScope(m_v8Isolate) |
| 82 , m_contextScope(context) |
| 83 , m_recursionScope(m_v8Isolate) |
| 84 { |
| 85 if (m_dartDOMData) |
| 86 (*m_dartDOMData->recursion())++; |
| 87 } |
| 88 |
| 89 V8Scope::V8Scope(DartDOMData* dartDOMData) |
| 90 : m_v8Isolate(v8::Isolate::GetCurrent()) |
| 91 , m_dartDOMData(dartDOMData) |
| 92 , m_handleScope(m_v8Isolate) |
| 93 , m_contextScope(DartUtilities::currentV8Context()) |
| 94 , m_recursionScope(m_v8Isolate) |
| 95 { |
| 96 if (m_dartDOMData) |
| 97 (*m_dartDOMData->recursion())++; |
| 98 } |
| 99 |
| 100 V8Scope::~V8Scope() |
| 101 { |
| 102 if (m_dartDOMData) |
| 103 (*m_dartDOMData->recursion())--; |
| 104 } |
| 105 |
| 106 DartStringPeer* DartStringPeer::nullString() |
| 107 { |
| 108 DEFINE_STATIC_LOCAL(DartStringPeer, empty, ()); |
| 109 return ∅ |
| 110 } |
| 111 |
| 112 DartStringPeer* DartStringPeer::emptyString() |
| 113 { |
| 114 DEFINE_STATIC_LOCAL(DartStringPeer, empty, (StringImpl::empty())); |
| 115 return ∅ |
| 116 } |
| 117 |
| 118 |
| 119 static void stringFinalizer(void* peer) |
| 120 { |
| 121 ASSERT(reinterpret_cast<DartStringPeer*>(peer) != DartStringPeer::nullString
()); |
| 122 delete reinterpret_cast<DartStringPeer*>(peer); |
| 123 } |
| 124 |
| 125 template <typename T> DartStringPeer* convertAndExternalize(Dart_Handle string,
intptr_t length) |
| 126 { |
| 127 if (!length) |
| 128 return new DartStringPeer(StringImpl::empty()); |
| 129 #ifndef NDEBUG |
| 130 { |
| 131 intptr_t storageSize = 0; |
| 132 Dart_StringStorageSize(string, &storageSize); |
| 133 ASSERT(length * intptr_t(sizeof(T)) == storageSize); |
| 134 } |
| 135 #endif |
| 136 T* buffer = 0; |
| 137 DartStringPeer* peer = new DartStringPeer(StringImpl::createUninitialized(le
ngth, buffer)); |
| 138 Dart_Handle ALLOW_UNUSED r = Dart_MakeExternalString(string, buffer, length
* sizeof(T), peer, stringFinalizer); |
| 139 ASSERT(!Dart_IsError(r)); |
| 140 return peer; |
| 141 } |
| 142 |
| 143 DartStringPeer* DartUtilities::toStringImpl(Dart_Handle object, intptr_t charsiz
e, intptr_t strlength) |
| 144 { |
| 145 ASSERT(Dart_IsString(object) && !Dart_IsExternalString(object)); |
| 146 return (charsize == 1) ? convertAndExternalize<LChar>(object, strlength) : c
onvertAndExternalize<UChar>(object, strlength); |
| 147 } |
| 148 |
| 149 |
| 150 Dart_Handle DartUtilities::stringImplToDartString(StringImpl* stringImpl) |
| 151 { |
| 152 if (!stringImpl) { |
| 153 DartDOMData* domData = DartDOMData::current(); |
| 154 return domData->emptyString(); |
| 155 } |
| 156 |
| 157 DartStringPeer* peer = new DartStringPeer(stringImpl); |
| 158 if (stringImpl->is8Bit()) { |
| 159 // FIXME: maybe it makes sense only externalize strings longer than cert
ain threshold, such as 5 symbols. |
| 160 return Dart_NewExternalLatin1String(reinterpret_cast<const uint8_t*>(str
ingImpl->characters8()), |
| 161 stringImpl->length(), peer, stringFinalizer); |
| 162 } else { |
| 163 // FIXME: maybe it makes sense only externalize strings longer than cert
ain threshold, such as 5 symbols. |
| 164 return Dart_NewExternalUTF16String(reinterpret_cast<const uint16_t*>(str
ingImpl->characters16()), |
| 165 stringImpl->length(), peer, stringFinalizer); |
| 166 } |
| 167 } |
| 168 |
| 169 Dart_Handle DartUtilities::stringToDartString(const String& str) |
| 170 { |
| 171 return stringImplToDartString(str.impl()); |
| 172 } |
| 173 |
| 174 Dart_Handle DartUtilities::stringToDartString(const AtomicString& str) |
| 175 { |
| 176 return stringImplToDartString(str.impl()); |
| 177 } |
| 178 |
| 179 |
| 180 Dart_Handle DartUtilities::safeStringImplToDartString(StringImpl* stringImpl) |
| 181 { |
| 182 if (!stringImpl) { |
| 183 DartDOMData* domData = DartDOMData::current(); |
| 184 return domData->emptyString(); |
| 185 } |
| 186 |
| 187 if (stringImpl->is8Bit()) { |
| 188 return Dart_NewStringFromUTF8( |
| 189 reinterpret_cast<const uint8_t*>(stringImpl->characters8()), |
| 190 stringImpl->length()); |
| 191 } else { |
| 192 return Dart_NewStringFromUTF16( |
| 193 reinterpret_cast<const uint16_t*>(stringImpl->characters16()), |
| 194 stringImpl->length()); |
| 195 } |
| 196 } |
| 197 |
| 198 Dart_Handle DartUtilities::safeStringToDartString(const String& str) |
| 199 { |
| 200 return safeStringImplToDartString(str.impl()); |
| 201 } |
| 202 |
| 203 Dart_Handle DartUtilities::safeStringToDartString(const AtomicString& str) |
| 204 { |
| 205 return safeStringImplToDartString(str.impl()); |
| 206 } |
| 207 |
| 208 template <typename Trait> |
| 209 typename Trait::nativeType convert(Dart_Handle object, Dart_Handle& exception) |
| 210 { |
| 211 typename Trait::nativeType value; |
| 212 Dart_Handle result = Trait::convert(object, &value); |
| 213 if (Dart_IsError(result)) { |
| 214 exception = Dart_NewStringFromCString(Dart_GetError(result)); |
| 215 return typename Trait::nativeType(); |
| 216 } |
| 217 return value; |
| 218 } |
| 219 |
| 220 struct IntegerTrait { |
| 221 typedef int64_t nativeType; |
| 222 static Dart_Handle convert(Dart_Handle object, int64_t* value) |
| 223 { |
| 224 return Dart_IntegerToInt64(object, value); |
| 225 // FIXME: support bigints. |
| 226 } |
| 227 }; |
| 228 |
| 229 int64_t DartUtilities::toInteger(Dart_Handle object, Dart_Handle& exception) |
| 230 { |
| 231 return convert<IntegerTrait>(object, exception); |
| 232 } |
| 233 |
| 234 String DartUtilities::toString(Dart_Handle object) |
| 235 { |
| 236 Dart_Handle exception = 0; |
| 237 String string = dartToString(object, exception); |
| 238 ASSERT(!exception); |
| 239 return string; |
| 240 } |
| 241 |
| 242 struct DoubleTrait { |
| 243 typedef double nativeType; |
| 244 static Dart_Handle convert(Dart_Handle object, double* value) |
| 245 { |
| 246 if (Dart_IsDouble(object)) |
| 247 return Dart_DoubleValue(object, value); |
| 248 |
| 249 if (Dart_IsInteger(object)) { |
| 250 int64_t v = 0; |
| 251 Dart_Handle result = Dart_IntegerToInt64(object, &v); |
| 252 if (!Dart_IsError(result)) { |
| 253 *value = static_cast<double>(v); |
| 254 return result; |
| 255 } |
| 256 } |
| 257 |
| 258 if (Dart_IsNumber(object)) { |
| 259 object = Dart_Invoke(object, Dart_NewStringFromCString("toDouble"),
0, 0); |
| 260 if (Dart_IsError(object)) |
| 261 return object; |
| 262 } |
| 263 |
| 264 // For non-Number objects, use the error message returned by Dart_Double
Value. |
| 265 return Dart_DoubleValue(object, value); |
| 266 } |
| 267 }; |
| 268 |
| 269 double DartUtilities::dartToDouble(Dart_Handle object, Dart_Handle& exception) |
| 270 { |
| 271 return convert<DoubleTrait>(object, exception); |
| 272 } |
| 273 |
| 274 struct BoolTrait { |
| 275 typedef bool nativeType; |
| 276 static Dart_Handle convert(Dart_Handle object, bool* value) |
| 277 { |
| 278 if (Dart_IsNull(object)) { |
| 279 *value = false; |
| 280 return Dart_Null(); |
| 281 } |
| 282 return Dart_BooleanValue(object, value); |
| 283 } |
| 284 }; |
| 285 |
| 286 bool DartUtilities::dartToBool(Dart_Handle object, Dart_Handle& exception) |
| 287 { |
| 288 return convert<BoolTrait>(object, exception); |
| 289 } |
| 290 |
| 291 DartStringAdapter DartUtilities::dartToStringImpl(Dart_Handle object, Dart_Handl
e& exception, bool autoDartScope) |
| 292 { |
| 293 if (!Dart_IsError(object) && !Dart_IsNull(object)) { |
| 294 ASSERT(Dart_IsString(object) && !Dart_IsExternalString(object)); |
| 295 intptr_t charsize = Dart_IsStringLatin1(object) ? 1 : 2; |
| 296 intptr_t strlength; |
| 297 Dart_StringLength(object, &strlength); |
| 298 if (autoDartScope) |
| 299 return DartStringAdapter(toStringImpl(object, charsize, strlength)); |
| 300 DartApiScope apiScope; |
| 301 return DartStringAdapter(toStringImpl(object, charsize, strlength)); |
| 302 } |
| 303 if (!autoDartScope) { |
| 304 DartApiScope apiScope; |
| 305 DartDOMData* domData = DartDOMData::current(); |
| 306 Dart_Handle excp = Dart_NewStringFromCString("String expected"); |
| 307 Dart_SetPersistentHandle(domData->currentException(), excp); |
| 308 exception = domData->currentException(); |
| 309 } else { |
| 310 exception = Dart_NewStringFromCString("String expected"); |
| 311 } |
| 312 return DartStringAdapter(DartStringPeer::nullString()); |
| 313 } |
| 314 |
| 315 void DartUtilities::extractMapElements(Dart_Handle map, Dart_Handle& exception,
HashMap<String, Dart_Handle>& elements) |
| 316 { |
| 317 ASSERT(elements.isEmpty()); |
| 318 Dart_Handle list = DartUtilities::invokeUtilsMethod("convertMapToList", 1, &
map); |
| 319 if (!DartUtilities::checkResult(list, exception)) |
| 320 return; |
| 321 ASSERT(Dart_IsList(list)); |
| 322 |
| 323 intptr_t length = 0; |
| 324 Dart_ListLength(list, &length); |
| 325 ASSERT(length % 2 == 0); |
| 326 |
| 327 for (intptr_t i = 0; i < length; i += 2) { |
| 328 Dart_Handle key = Dart_ListGetAt(list, i); |
| 329 ASSERT(!Dart_IsError(key) && Dart_IsString(key)); |
| 330 Dart_Handle value = Dart_ListGetAt(list, i+1); |
| 331 ASSERT(!Dart_IsError(value)); |
| 332 String keyString = DartUtilities::dartToString(key, exception); |
| 333 if (exception) |
| 334 return; |
| 335 elements.add(keyString, value); |
| 336 } |
| 337 } |
| 338 |
| 339 Dart_Handle DartUtilities::toList(const Vector<Dart_Handle>& elements, Dart_Hand
le& exception) |
| 340 { |
| 341 Dart_Handle ret = Dart_NewList(elements.size()); |
| 342 if (Dart_IsError(ret)) { |
| 343 exception = ret; |
| 344 return Dart_Null(); |
| 345 } |
| 346 for (size_t i = 0; i < elements.size(); i++) { |
| 347 Dart_ListSetAt(ret, i, elements[i]); |
| 348 } |
| 349 return ret; |
| 350 } |
| 351 |
| 352 void DartUtilities::extractListElements(Dart_Handle list, Dart_Handle& exception
, Vector<Dart_Handle>& elements) |
| 353 { |
| 354 ASSERT(elements.isEmpty()); |
| 355 list = DartUtilities::invokeUtilsMethod("convertToList", 1, &list); |
| 356 if (!DartUtilities::checkResult(list, exception)) |
| 357 return; |
| 358 ASSERT(Dart_IsList(list)); |
| 359 |
| 360 intptr_t length = 0; |
| 361 Dart_ListLength(list, &length); |
| 362 elements.reserveCapacity(length); |
| 363 for (intptr_t i = 0; i < length; i++) { |
| 364 Dart_Handle element = Dart_ListGetAt(list, i); |
| 365 ASSERT(!Dart_IsError(element)); |
| 366 elements.append(element); |
| 367 } |
| 368 } |
| 369 |
| 370 v8::Local<v8::Context> DartUtilities::currentV8Context() |
| 371 { |
| 372 LocalFrame* frame = DartUtilities::domWindowForCurrentIsolate()->frame(); |
| 373 v8::Local<v8::Context> context = toV8Context(frame, DOMWrapperWorld::mainWor
ld()); |
| 374 ASSERT(!context.IsEmpty()); |
| 375 return context; |
| 376 } |
| 377 |
| 378 int DartUtilities::dartToInt(Dart_Handle object, Dart_Handle& exception) |
| 379 { |
| 380 int64_t value = toInteger(object, exception); |
| 381 if (exception) |
| 382 return 0; |
| 383 if (value < INT_MIN || value > INT_MAX) { |
| 384 exception = Dart_NewStringFromCString("value out of range"); |
| 385 return 0; |
| 386 } |
| 387 return value; |
| 388 } |
| 389 |
| 390 unsigned DartUtilities::dartToUnsigned(Dart_Handle object, Dart_Handle& exceptio
n) |
| 391 { |
| 392 int64_t value = toInteger(object, exception); |
| 393 if (exception) |
| 394 return 0; |
| 395 if (value < 0 || value > UINT_MAX) { |
| 396 exception = Dart_NewStringFromCString("value out of range"); |
| 397 return 0; |
| 398 } |
| 399 return value; |
| 400 } |
| 401 |
| 402 long long DartUtilities::dartToLongLong(Dart_Handle object, Dart_Handle& excepti
on) |
| 403 { |
| 404 // FIXME: proper processing of longer integer values. |
| 405 return toInteger(object, exception); |
| 406 } |
| 407 |
| 408 unsigned long long DartUtilities::dartToUnsignedLongLong(Dart_Handle object, Dar
t_Handle& exception) |
| 409 { |
| 410 // FIXME: proper processing of longer integer values. |
| 411 int64_t value = toInteger(object, exception); |
| 412 if (exception) |
| 413 return 0; |
| 414 if (value < 0) { |
| 415 exception = Dart_NewStringFromCString("value out of range"); |
| 416 return 0; |
| 417 } |
| 418 return value; |
| 419 } |
| 420 |
| 421 Dart_Handle DartUtilities::numberToDart(double value) |
| 422 { |
| 423 // JS can store integer values that are no greater than 2^53 - 1. |
| 424 if (-kJSMaxInteger <= value && value <= kJSMaxInteger) { |
| 425 int64_t intValue = static_cast<int64_t>(value); |
| 426 if (value == intValue) |
| 427 return intToDart(intValue); |
| 428 } |
| 429 return doubleToDart(value); |
| 430 } |
| 431 |
| 432 ScriptValue DartUtilities::dartToScriptValue(Dart_Handle object) |
| 433 { |
| 434 return ScriptValue(DartScriptValue::create(currentScriptState(), object)); |
| 435 } |
| 436 |
| 437 PassRefPtr<SerializedScriptValue> DartUtilities::toSerializedScriptValue(Dart_Ha
ndle value, MessagePortArray* ports, ArrayBufferArray* arrayBuffers, Dart_Handle
& exception) |
| 438 { |
| 439 v8::Handle<v8::Value> v8Value = V8Converter::toV8(value, exception); |
| 440 if (exception) |
| 441 return nullptr; |
| 442 |
| 443 V8TrackExceptionState exceptionState; |
| 444 RefPtr<SerializedScriptValue> message = SerializedScriptValue::create(v8Valu
e, ports, arrayBuffers, exceptionState, v8::Isolate::GetCurrent()); |
| 445 if (exceptionState.hadException()) { |
| 446 // FIXME: better exception here. We should match the exception v8 would
throw. |
| 447 exception = Dart_NewStringFromCString("Failed to create SerializedScript
Value"); |
| 448 return nullptr; |
| 449 } |
| 450 |
| 451 return message.release(); |
| 452 } |
| 453 |
| 454 Dart_Handle DartUtilities::dateToDart(double date) |
| 455 { |
| 456 Dart_Handle asDouble = DartUtilities::doubleToDart(date); |
| 457 ASSERT(!Dart_IsError(asDouble)); |
| 458 return DartUtilities::invokeUtilsMethod("doubleToDateTime", 1, &asDouble); |
| 459 } |
| 460 |
| 461 double DartUtilities::dartToDate(Dart_Handle date, Dart_Handle& exception) |
| 462 { |
| 463 Dart_Handle asDouble = DartUtilities::invokeUtilsMethod("dateTimeToDouble",
1, &date); |
| 464 if (!DartUtilities::checkResult(asDouble, exception)) |
| 465 return 0.0; |
| 466 |
| 467 return DartUtilities::dartToDouble(asDouble, exception); |
| 468 } |
| 469 |
| 470 double DartUtilities::dartToDate(Dart_NativeArguments args, int idx, Dart_Handle
& exception) |
| 471 { |
| 472 Dart_Handle object = Dart_GetNativeArgument(args, idx); |
| 473 return dartToDate(object, exception); |
| 474 } |
| 475 |
| 476 bool DartUtilities::isDateTime(DartDOMData* domData, Dart_Handle handle) |
| 477 { |
| 478 Dart_Handle dartType = DartUtilities::getDartType("dart:core", "DateTime"); |
| 479 return objectIsType(handle, dartType); |
| 480 } |
| 481 |
| 482 bool DartUtilities::objectIsType(Dart_Handle handle, Dart_Handle type) |
| 483 { |
| 484 bool isType = false; |
| 485 Dart_Handle result = Dart_ObjectIsType(handle, type, &isType); |
| 486 if (Dart_IsError(result)) |
| 487 return false; |
| 488 return isType; |
| 489 } |
| 490 |
| 491 bool DartUtilities::isTypeSubclassOf(Dart_Handle type, Dart_Handle library, cons
t char* typeName) |
| 492 { |
| 493 Dart_Handle other = Dart_GetType(library, Dart_NewStringFromCString(typeName
), 0, 0); |
| 494 ASSERT(!Dart_IsError(other)); |
| 495 |
| 496 Dart_Handle args[2] = { type, other }; |
| 497 Dart_Handle result = DartUtilities::invokeUtilsMethod("isTypeSubclassOf", 2,
args); |
| 498 if (Dart_IsError(result)) { |
| 499 ASSERT_NOT_REACHED(); |
| 500 return false; |
| 501 } |
| 502 |
| 503 Dart_Handle exception = 0; |
| 504 bool boolResult = dartToBool(result, exception); |
| 505 if (exception) |
| 506 return false; |
| 507 return boolResult; |
| 508 } |
| 509 |
| 510 Dart_Handle DartUtilities::getAndValidateNativeType(Dart_Handle type, const Stri
ng& tagName) |
| 511 { |
| 512 Dart_Handle args[2] = { type, stringToDartString(tagName) }; |
| 513 Dart_Handle result = DartUtilities::invokeUtilsMethod("getAndValidateNativeT
ype", 2, args); |
| 514 ASSERT(!Dart_IsError(result)); |
| 515 if (Dart_IsError(result)) { |
| 516 ASSERT_NOT_REACHED(); |
| 517 return Dart_Null(); |
| 518 } |
| 519 return result; |
| 520 } |
| 521 |
| 522 bool DartUtilities::isFunction(DartDOMData* domData, Dart_Handle handle) |
| 523 { |
| 524 return DartUtilities::objectIsType(handle, domData->functionType()); |
| 525 } |
| 526 |
| 527 Dart_Handle DartUtilities::getDartType(const char* libraryName, const char* type
Name) |
| 528 { |
| 529 Dart_Handle library = Dart_LookupLibrary(Dart_NewStringFromCString(libraryNa
me)); |
| 530 ASSERT(!Dart_IsError(library)); |
| 531 |
| 532 Dart_Handle dartType = Dart_GetType(library, Dart_NewStringFromCString(typeN
ame), 0, 0); |
| 533 ASSERT(!Dart_IsError(dartType)); |
| 534 |
| 535 return dartType; |
| 536 } |
| 537 |
| 538 Dart_Handle DartUtilities::getDartHtmlType(const char* typeName) |
| 539 { |
| 540 Dart_Handle dartType = Dart_GetType(DartDOMData::current()->htmlLibrary(), |
| 541 Dart_NewStringFromCString(typeName), 0, 0); |
| 542 ASSERT(!Dart_IsError(dartType)); |
| 543 |
| 544 return dartType; |
| 545 } |
| 546 |
| 547 bool DartUtilities::isNode(Dart_Handle handle) |
| 548 { |
| 549 Dart_Handle dartType = DartUtilities::getDartHtmlType("Node"); |
| 550 return objectIsType(handle, dartType); |
| 551 } |
| 552 |
| 553 Node* DartUtilities::dartNodeToNativeNode(void* value) |
| 554 { |
| 555 return static_cast<Node*>(value); |
| 556 } |
| 557 |
| 558 bool DartUtilities::isMessagePort(Dart_Handle handle) |
| 559 { |
| 560 Dart_Handle dartType = DartUtilities::getDartHtmlType("MessagePort"); |
| 561 return objectIsType(handle, dartType); |
| 562 } |
| 563 |
| 564 MessagePort* DartUtilities::dartMessagePortToNativeMessagePort(void* value) |
| 565 { |
| 566 return static_cast<MessagePort*>(value); |
| 567 } |
| 568 |
| 569 static Dart_TypedData_Type typedDataTypeFromViewType(ArrayBufferView::ViewType t
ype) |
| 570 { |
| 571 switch (type) { |
| 572 case ArrayBufferView::TypeInt8: |
| 573 return Dart_TypedData_kInt8; |
| 574 case ArrayBufferView::TypeUint8: |
| 575 return Dart_TypedData_kUint8; |
| 576 case ArrayBufferView::TypeUint8Clamped: |
| 577 return Dart_TypedData_kUint8Clamped; |
| 578 case ArrayBufferView::TypeInt16: |
| 579 return Dart_TypedData_kInt16; |
| 580 case ArrayBufferView::TypeUint16: |
| 581 return Dart_TypedData_kUint16; |
| 582 case ArrayBufferView::TypeInt32: |
| 583 return Dart_TypedData_kInt32; |
| 584 case ArrayBufferView::TypeUint32: |
| 585 return Dart_TypedData_kUint32; |
| 586 case ArrayBufferView::TypeFloat32: |
| 587 return Dart_TypedData_kFloat32; |
| 588 case ArrayBufferView::TypeFloat64: |
| 589 return Dart_TypedData_kFloat64; |
| 590 case ArrayBufferView::TypeDataView: |
| 591 return Dart_TypedData_kByteData; |
| 592 } |
| 593 ASSERT_NOT_REACHED(); |
| 594 return Dart_TypedData_kInvalid; |
| 595 } |
| 596 |
| 597 static unsigned elementSizeFromViewType(Dart_TypedData_Type type) |
| 598 { |
| 599 switch (type) { |
| 600 case Dart_TypedData_kByteData: |
| 601 return sizeof(uint8_t); |
| 602 case Dart_TypedData_kInt8: |
| 603 return sizeof(int8_t); |
| 604 case Dart_TypedData_kUint8: |
| 605 return sizeof(uint8_t); |
| 606 case Dart_TypedData_kUint8Clamped: |
| 607 return sizeof(uint8_t); |
| 608 case Dart_TypedData_kInt16: |
| 609 return sizeof(int16_t); |
| 610 case Dart_TypedData_kUint16: |
| 611 return sizeof(uint16_t); |
| 612 case Dart_TypedData_kInt32: |
| 613 return sizeof(int32_t); |
| 614 case Dart_TypedData_kUint32: |
| 615 return sizeof(uint32_t); |
| 616 case Dart_TypedData_kFloat32: |
| 617 return sizeof(float); |
| 618 case Dart_TypedData_kFloat64: |
| 619 return sizeof(double); |
| 620 case Dart_TypedData_kFloat32x4: |
| 621 return 4 * sizeof(float); |
| 622 default: |
| 623 break; |
| 624 } |
| 625 ASSERT_NOT_REACHED(); |
| 626 return 0; |
| 627 } |
| 628 |
| 629 static unsigned elementSizeFromViewType(ArrayBufferView::ViewType type) |
| 630 { |
| 631 return elementSizeFromViewType(typedDataTypeFromViewType(type)); |
| 632 } |
| 633 |
| 634 class TypedDataPeer { |
| 635 public: |
| 636 virtual ~TypedDataPeer() { }; |
| 637 virtual bool isViewPeer() = 0; |
| 638 }; |
| 639 |
| 640 class TypedBufferPeer : public TypedDataPeer { |
| 641 public: |
| 642 TypedBufferPeer(PassRefPtr<ArrayBuffer> buffer) : m_buffer(buffer) { } |
| 643 virtual ~TypedBufferPeer() { } |
| 644 |
| 645 PassRefPtr<ArrayBuffer> buffer() |
| 646 { |
| 647 return m_buffer; |
| 648 } |
| 649 |
| 650 virtual bool isViewPeer() |
| 651 { |
| 652 return false; |
| 653 } |
| 654 |
| 655 private: |
| 656 RefPtr<ArrayBuffer> m_buffer; |
| 657 }; |
| 658 |
| 659 class TypedViewPeer : public TypedDataPeer { |
| 660 public: |
| 661 TypedViewPeer(PassRefPtr<ArrayBufferView> view) : m_view(view) { } |
| 662 virtual ~TypedViewPeer() { } |
| 663 |
| 664 PassRefPtr<ArrayBufferView> view() |
| 665 { |
| 666 return m_view; |
| 667 } |
| 668 |
| 669 virtual bool isViewPeer() |
| 670 { |
| 671 return true; |
| 672 } |
| 673 |
| 674 private: |
| 675 RefPtr<ArrayBufferView> m_view; |
| 676 }; |
| 677 |
| 678 static void externalArrayBufferCallback(void* isolateCallbackData, Dart_WeakPers
istentHandle handle, void* peer) |
| 679 { |
| 680 delete reinterpret_cast<TypedDataPeer*>(peer); |
| 681 } |
| 682 |
| 683 static Dart_Handle createExternalTypedData(Dart_TypedData_Type type, void* data,
intptr_t numberOfElements, TypedDataPeer* peer, intptr_t peerSize, Dart_WeakPer
sistentHandleFinalizer callback) |
| 684 { |
| 685 Dart_Handle newInstance = Dart_NewExternalTypedData(type, data, numberOfElem
ents); |
| 686 Dart_Handle result = Dart_SetPeer(newInstance, peer); |
| 687 if (Dart_IsError(result)) |
| 688 return result; |
| 689 Dart_NewWeakPersistentHandle(newInstance, peer, peerSize, callback); |
| 690 return newInstance; |
| 691 } |
| 692 |
| 693 Dart_Handle DartUtilities::arrayBufferToDart(WTF::ArrayBuffer* buffer) |
| 694 { |
| 695 void* data = buffer->data(); |
| 696 unsigned byteLength = buffer->byteLength(); |
| 697 TypedBufferPeer* peer = new TypedBufferPeer(buffer); |
| 698 Dart_Handle typedData = createExternalTypedData(Dart_TypedData_kUint8, data
, byteLength, peer, byteLength, externalArrayBufferCallback); |
| 699 ASSERT(!Dart_IsError(typedData)); |
| 700 return Dart_NewByteBuffer(typedData); |
| 701 } |
| 702 |
| 703 static bool externalTypedDataGetPeer(Dart_Handle handle, void** peer) |
| 704 { |
| 705 *peer = 0; |
| 706 Dart_Handle getPeerResult = Dart_GetPeer(handle, peer); |
| 707 if (!Dart_IsError(getPeerResult) && *peer) { |
| 708 return true; |
| 709 } |
| 710 return false; |
| 711 } |
| 712 |
| 713 static PassRefPtr<WTF::ArrayBuffer> dartToArrayBufferHelper(Dart_Handle array, D
art_Handle& exception, bool externalize) |
| 714 { |
| 715 void* data = 0; |
| 716 |
| 717 // If a ByteBuffer is passed in extract the typed data first. |
| 718 if (Dart_IsByteBuffer(array)) { |
| 719 array = Dart_GetDataFromByteBuffer(array); |
| 720 } |
| 721 |
| 722 // Check if the Dart array buffer object is external and has an |
| 723 // ArrayBuffer peer. |
| 724 if (externalTypedDataGetPeer(array, &data) && !reinterpret_cast<TypedDataPee
r*>(data)->isViewPeer()) { |
| 725 return reinterpret_cast<TypedBufferPeer*>(data)->buffer(); |
| 726 } |
| 727 |
| 728 Dart_TypedData_Type type; |
| 729 intptr_t elementLength = 0; |
| 730 intptr_t byteLength = 0; |
| 731 |
| 732 // Check if the Dart object is a typed data object by acquiring its data. |
| 733 // If it is, create a thin ArrayBuffer wrapper around the data in the dart |
| 734 // heap. |
| 735 Dart_Handle result = Dart_TypedDataAcquireData(array, &type, &data, &element
Length); |
| 736 if (Dart_IsError(result)) { |
| 737 exception = Dart_NewStringFromCString("Typed data object expected"); |
| 738 return nullptr; |
| 739 } |
| 740 // FIXME: we really shouldn't release the data until we are done with it. |
| 741 Dart_TypedDataReleaseData(array); |
| 742 byteLength = elementLength * elementSizeFromViewType(type); |
| 743 return externalize ? ArrayBuffer::create(data, byteLength) : ArrayBuffer::cr
eateNoCopy(data, byteLength); |
| 744 } |
| 745 |
| 746 PassRefPtr<WTF::ArrayBuffer> DartUtilities::dartToArrayBuffer(Dart_Handle array,
Dart_Handle& exception) |
| 747 { |
| 748 return dartToArrayBufferHelper(array, exception, false); |
| 749 } |
| 750 |
| 751 PassRefPtr<WTF::ArrayBuffer> DartUtilities::dartToExternalizedArrayBuffer(Dart_H
andle array, Dart_Handle& exception) |
| 752 { |
| 753 return dartToArrayBufferHelper(array, exception, true); |
| 754 } |
| 755 |
| 756 // FIXME: This mapping to dart objects loses object identity for |
| 757 // the buffer part of views. If we have two views on the same buffer |
| 758 // in C++ and we create dart wrappers we will get two different dart |
| 759 // buffer objects. Additionally, this means that neutering will not work. |
| 760 Dart_Handle DartUtilities::arrayBufferViewToDart(WTF::ArrayBufferView* view) |
| 761 { |
| 762 ArrayBufferView::ViewType type = view->type(); |
| 763 void* address = view->baseAddress(); |
| 764 unsigned byteLength = view->byteLength(); |
| 765 unsigned length = byteLength / elementSizeFromViewType(type); |
| 766 TypedViewPeer* peer = new TypedViewPeer(view); |
| 767 return createExternalTypedData(typedDataTypeFromViewType(type), address, len
gth, peer, byteLength, externalArrayBufferCallback); |
| 768 } |
| 769 |
| 770 |
| 771 // FIXME: Again, this breaks the view-buffer relationship. |
| 772 static PassRefPtr<WTF::ArrayBufferView> dartToArrayBufferViewHelper(Dart_Handle
array, Dart_Handle& exception, bool externalize) |
| 773 { |
| 774 void* data = 0; |
| 775 |
| 776 // Check if the array is external and has an ArrayBufferView peer. |
| 777 if (externalTypedDataGetPeer(array, &data)) { |
| 778 if (!reinterpret_cast<TypedDataPeer*>(data)->isViewPeer()) { |
| 779 exception = Dart_NewStringFromCString("Typed data view expected"); |
| 780 return nullptr; |
| 781 } |
| 782 return reinterpret_cast<TypedViewPeer*>(data)->view(); |
| 783 } |
| 784 |
| 785 // Check if the dart object is an internal typed data object and get |
| 786 // the data from it. |
| 787 Dart_TypedData_Type type; |
| 788 intptr_t elementLength = 0; |
| 789 Dart_Handle result = Dart_TypedDataAcquireData(array, &type, &data, &element
Length); |
| 790 if (Dart_IsError(result)) { |
| 791 exception = Dart_NewStringFromCString("Typed data object expected"); |
| 792 return nullptr; |
| 793 } |
| 794 intptr_t byteLength = elementLength * elementSizeFromViewType(type); |
| 795 // FIXME: we really shouldn't release the data until we are done with it. |
| 796 Dart_TypedDataReleaseData(array); |
| 797 RefPtr<ArrayBuffer> buffer = externalize ? ArrayBuffer::create(data, byteLen
gth) : ArrayBuffer::createNoCopy(data, byteLength); |
| 798 |
| 799 switch (type) { |
| 800 case Dart_TypedData_kByteData: |
| 801 return DataView::create(buffer, 0, elementLength); |
| 802 case Dart_TypedData_kInt8: |
| 803 return Int8Array::create(buffer, 0, elementLength); |
| 804 case Dart_TypedData_kUint8: |
| 805 return Uint8Array::create(buffer, 0, elementLength); |
| 806 case Dart_TypedData_kUint8Clamped: |
| 807 return Uint8ClampedArray::create(buffer, 0, elementLength); |
| 808 case Dart_TypedData_kInt16: |
| 809 return Uint16Array::create(buffer, 0, elementLength); |
| 810 case Dart_TypedData_kUint16: |
| 811 return Uint16Array::create(buffer, 0, elementLength); |
| 812 case Dart_TypedData_kInt32: |
| 813 return Int32Array::create(buffer, 0, elementLength); |
| 814 case Dart_TypedData_kUint32: |
| 815 return Uint32Array::create(buffer, 0, elementLength); |
| 816 case Dart_TypedData_kFloat32: |
| 817 return Float32Array::create(buffer, 0, elementLength); |
| 818 case Dart_TypedData_kFloat64: |
| 819 return Float64Array::create(buffer, 0, elementLength); |
| 820 case Dart_TypedData_kFloat32x4: |
| 821 return Float32Array::create(buffer, 0, elementLength * sizeof(float)); |
| 822 default: |
| 823 break; |
| 824 } |
| 825 ASSERT_NOT_REACHED(); |
| 826 return nullptr; |
| 827 } |
| 828 |
| 829 PassRefPtr<WTF::ArrayBufferView> DartUtilities::dartToArrayBufferView(Dart_Handl
e array, Dart_Handle& exception) |
| 830 { |
| 831 return dartToArrayBufferViewHelper(array, exception, false); |
| 832 } |
| 833 |
| 834 PassRefPtr<WTF::ArrayBufferView> DartUtilities::dartToExternalizedArrayBufferVie
w(Dart_Handle array, Dart_Handle& exception) |
| 835 { |
| 836 return dartToArrayBufferViewHelper(array, exception, true); |
| 837 } |
| 838 |
| 839 PassRefPtr<WTF::Int8Array> DartUtilities::dartToInt8ArrayWithNullCheck(Dart_Hand
le handle, Dart_Handle& exception) |
| 840 { |
| 841 return Dart_IsNull(handle) ? nullptr : dartToInt8Array(handle, exception); |
| 842 } |
| 843 |
| 844 PassRefPtr<WTF::Int8Array> DartUtilities::dartToInt8Array(Dart_Handle handle, Da
rt_Handle& exception) |
| 845 { |
| 846 RefPtr<ArrayBufferView> view = DartUtilities::dartToArrayBufferView(handle,
exception); |
| 847 if (exception) |
| 848 return nullptr; |
| 849 if (view->type() == ArrayBufferView::TypeInt8) |
| 850 return reinterpret_cast<Int8Array*>(view.get()); |
| 851 exception = Dart_NewStringFromCString("Int8List expected"); |
| 852 return nullptr; |
| 853 } |
| 854 |
| 855 PassRefPtr<WTF::Int8Array> DartUtilities::dartToInt8ArrayWithNullCheck(Dart_Nati
veArguments args, int idx, Dart_Handle& exception) |
| 856 { |
| 857 Dart_Handle object = Dart_GetNativeArgument(args, idx); |
| 858 return dartToInt8ArrayWithNullCheck(object, exception); |
| 859 } |
| 860 |
| 861 PassRefPtr<WTF::Int8Array> DartUtilities::dartToInt8Array(Dart_NativeArguments a
rgs, int idx, Dart_Handle& exception) |
| 862 { |
| 863 Dart_Handle object = Dart_GetNativeArgument(args, idx); |
| 864 return dartToInt8Array(object, exception); |
| 865 } |
| 866 |
| 867 PassRefPtr<WTF::Int32Array> DartUtilities::dartToInt32ArrayWithNullCheck(Dart_Ha
ndle handle, Dart_Handle& exception) |
| 868 { |
| 869 return Dart_IsNull(handle) ? nullptr : dartToInt32Array(handle, exception); |
| 870 } |
| 871 |
| 872 PassRefPtr<WTF::Int32Array> DartUtilities::dartToInt32Array(Dart_Handle handle,
Dart_Handle& exception) |
| 873 { |
| 874 RefPtr<ArrayBufferView> view = DartUtilities::dartToArrayBufferView(handle,
exception); |
| 875 if (exception) |
| 876 return nullptr; |
| 877 if (view->type() == ArrayBufferView::TypeInt32) |
| 878 return reinterpret_cast<Int32Array*>(view.get()); |
| 879 exception = Dart_NewStringFromCString("Int32List expected"); |
| 880 return nullptr; |
| 881 } |
| 882 |
| 883 PassRefPtr<WTF::Int32Array> DartUtilities::dartToInt32ArrayWithNullCheck(Dart_Na
tiveArguments args, int idx, Dart_Handle& exception) |
| 884 { |
| 885 Dart_Handle object = Dart_GetNativeArgument(args, idx); |
| 886 return dartToInt32ArrayWithNullCheck(object, exception); |
| 887 } |
| 888 |
| 889 PassRefPtr<WTF::Int32Array> DartUtilities::dartToInt32Array(Dart_NativeArguments
args, int idx, Dart_Handle& exception) |
| 890 { |
| 891 Dart_Handle object = Dart_GetNativeArgument(args, idx); |
| 892 return dartToInt32Array(object, exception); |
| 893 } |
| 894 |
| 895 PassRefPtr<WTF::Uint8ClampedArray> DartUtilities::dartToUint8ClampedArrayWithNul
lCheck(Dart_Handle handle, Dart_Handle& exception) |
| 896 { |
| 897 return Dart_IsNull(handle) ? nullptr : dartToUint8ClampedArray(handle, excep
tion); |
| 898 } |
| 899 |
| 900 PassRefPtr<WTF::Uint8ClampedArray> DartUtilities::dartToUint8ClampedArray(Dart_H
andle handle, Dart_Handle& exception) |
| 901 { |
| 902 RefPtr<ArrayBufferView> view = DartUtilities::dartToArrayBufferView(handle,
exception); |
| 903 if (exception) |
| 904 return nullptr; |
| 905 if (view->type() == ArrayBufferView::TypeUint8Clamped) |
| 906 return reinterpret_cast<Uint8ClampedArray*>(view.get()); |
| 907 exception = Dart_NewStringFromCString("Uint8ClampedList expected"); |
| 908 return nullptr; |
| 909 } |
| 910 |
| 911 PassRefPtr<WTF::Uint8ClampedArray> DartUtilities::dartToUint8ClampedArrayWithNul
lCheck(Dart_NativeArguments args, int idx, Dart_Handle& exception) |
| 912 { |
| 913 Dart_Handle object = Dart_GetNativeArgument(args, idx); |
| 914 return dartToUint8ClampedArrayWithNullCheck(object, exception); |
| 915 } |
| 916 |
| 917 PassRefPtr<WTF::Uint8ClampedArray> DartUtilities::dartToUint8ClampedArray(Dart_N
ativeArguments args, int idx, Dart_Handle& exception) |
| 918 { |
| 919 Dart_Handle object = Dart_GetNativeArgument(args, idx); |
| 920 return dartToUint8ClampedArray(object, exception); |
| 921 } |
| 922 |
| 923 PassRefPtr<WTF::Uint8Array> DartUtilities::dartToUint8ArrayWithNullCheck(Dart_Ha
ndle handle, Dart_Handle& exception) |
| 924 { |
| 925 return Dart_IsNull(handle) ? nullptr : dartToUint8Array(handle, exception); |
| 926 } |
| 927 |
| 928 PassRefPtr<WTF::Uint8Array> DartUtilities::dartToUint8Array(Dart_Handle handle,
Dart_Handle& exception) |
| 929 { |
| 930 RefPtr<ArrayBufferView> view = DartUtilities::dartToArrayBufferView(handle,
exception); |
| 931 if (exception) |
| 932 return nullptr; |
| 933 if (view->type() == ArrayBufferView::TypeUint8) |
| 934 return reinterpret_cast<Uint8Array*>(view.get()); |
| 935 exception = Dart_NewStringFromCString("Uint8List expected"); |
| 936 return nullptr; |
| 937 } |
| 938 |
| 939 PassRefPtr<WTF::Uint8Array> DartUtilities::dartToUint8ArrayWithNullCheck(Dart_Na
tiveArguments args, int idx, Dart_Handle& exception) |
| 940 { |
| 941 Dart_Handle object = Dart_GetNativeArgument(args, idx); |
| 942 return dartToUint8ArrayWithNullCheck(object, exception); |
| 943 } |
| 944 |
| 945 PassRefPtr<WTF::Uint8Array> DartUtilities::dartToUint8Array(Dart_NativeArguments
args, int idx, Dart_Handle& exception) |
| 946 { |
| 947 Dart_Handle object = Dart_GetNativeArgument(args, idx); |
| 948 return dartToUint8Array(object, exception); |
| 949 } |
| 950 |
| 951 PassRefPtr<WTF::Float32Array> DartUtilities::dartToFloat32ArrayWithNullCheck(Dar
t_Handle handle, Dart_Handle& exception) |
| 952 { |
| 953 return Dart_IsNull(handle) ? nullptr : dartToFloat32Array(handle, exception)
; |
| 954 } |
| 955 |
| 956 PassRefPtr<WTF::Float32Array> DartUtilities::dartToFloat32Array(Dart_Handle hand
le, Dart_Handle& exception) |
| 957 { |
| 958 RefPtr<ArrayBufferView> view = DartUtilities::dartToArrayBufferView(handle,
exception); |
| 959 if (exception) |
| 960 return nullptr; |
| 961 if (view->type() == ArrayBufferView::TypeFloat32) |
| 962 return reinterpret_cast<Float32Array*>(view.get()); |
| 963 exception = Dart_NewStringFromCString("Float32List expected"); |
| 964 return nullptr; |
| 965 } |
| 966 |
| 967 PassRefPtr<WTF::Float32Array> DartUtilities::dartToFloat32ArrayWithNullCheck(Dar
t_NativeArguments args, int idx, Dart_Handle& exception) |
| 968 { |
| 969 Dart_Handle object = Dart_GetNativeArgument(args, idx); |
| 970 return dartToFloat32ArrayWithNullCheck(object, exception); |
| 971 } |
| 972 |
| 973 PassRefPtr<WTF::Float32Array> DartUtilities::dartToFloat32Array(Dart_NativeArgum
ents args, int idx, Dart_Handle& exception) |
| 974 { |
| 975 Dart_Handle object = Dart_GetNativeArgument(args, idx); |
| 976 return dartToFloat32Array(object, exception); |
| 977 } |
| 978 |
| 979 bool DartUtilities::isUint8Array(Dart_Handle object) |
| 980 { |
| 981 return Dart_GetTypeOfTypedData(object) == Dart_TypedData_kUint8; |
| 982 } |
| 983 |
| 984 bool DartUtilities::isUint8ClampedArray(Dart_Handle object) |
| 985 { |
| 986 return Dart_GetTypeOfTypedData(object) == Dart_TypedData_kUint8Clamped; |
| 987 } |
| 988 |
| 989 SQLValue DartUtilities::toSQLValue(Dart_Handle object, Dart_Handle& exception) |
| 990 { |
| 991 if (Dart_IsNull(object)) |
| 992 return SQLValue(); |
| 993 |
| 994 if (Dart_IsNumber(object)) |
| 995 return SQLValue(DartUtilities::dartToDouble(object, exception)); |
| 996 |
| 997 return SQLValue(DartUtilities::dartToString(object, exception)); |
| 998 } |
| 999 |
| 1000 PassRefPtr<SerializedScriptValue> DartUtilities::dartToSerializedScriptValue(Dar
t_Handle object, Dart_Handle& exception) |
| 1001 { |
| 1002 return toSerializedScriptValue(object, 0, 0, exception); |
| 1003 } |
| 1004 |
| 1005 Dart_Handle DartUtilities::serializedScriptValueToDart(PassRefPtr<SerializedScri
ptValue> value) |
| 1006 { |
| 1007 // FIXME: better error handling. |
| 1008 Dart_Handle exception = 0; |
| 1009 return V8Converter::toDart(value->deserialize(), exception); |
| 1010 } |
| 1011 |
| 1012 // FIXME: this function requires better testing. Currently blocking as new Messa
geChannel hasn't been implemented yet. |
| 1013 void DartUtilities::toMessagePortArray(Dart_Handle value, MessagePortArray& port
s, ArrayBufferArray& arrayBuffers, Dart_Handle& exception) |
| 1014 { |
| 1015 Vector<Dart_Handle> elements; |
| 1016 DartUtilities::extractListElements(value, exception, elements); |
| 1017 if (exception) |
| 1018 return; |
| 1019 |
| 1020 for (size_t i = 0; i < elements.size(); i++) { |
| 1021 Dart_Handle element = elements[i]; |
| 1022 if (DartUtilities::isMessagePort(element)) { |
| 1023 MessagePort* messagePort = DartUtilities::dartMessagePortToNativeMes
sagePort(element); |
| 1024 ASSERT(messagePort); |
| 1025 ports.append(messagePort); |
| 1026 continue; |
| 1027 } |
| 1028 |
| 1029 if (Dart_IsByteBuffer(element)) { |
| 1030 element = Dart_GetDataFromByteBuffer(element); |
| 1031 RefPtr<ArrayBuffer> arrayBuffer = DartUtilities::dartToExternalizedA
rrayBuffer(element, exception); |
| 1032 ASSERT(!exception); |
| 1033 ASSERT(arrayBuffer); |
| 1034 arrayBuffers.append(arrayBuffer); |
| 1035 continue; |
| 1036 } |
| 1037 |
| 1038 exception = Dart_NewStringFromCString("TransferArray argument must conta
in only Transferables"); |
| 1039 return; |
| 1040 } |
| 1041 } |
| 1042 |
| 1043 Dictionary DartUtilities::dartToDictionary(Dart_Handle object, Dart_Handle& exce
ption) |
| 1044 { |
| 1045 v8::Isolate* v8Isolate = v8::Isolate::GetCurrent(); |
| 1046 v8::Local<v8::Value> value = v8::Local<v8::Value>::New(v8Isolate, V8Converte
r::toV8(object, exception)); |
| 1047 if (exception) |
| 1048 return Dictionary(); |
| 1049 return Dictionary(value, v8Isolate); |
| 1050 } |
| 1051 |
| 1052 Dictionary DartUtilities::dartToDictionaryWithNullCheck(Dart_Handle object, Dart
_Handle& exception) |
| 1053 { |
| 1054 if (Dart_IsNull(object)) |
| 1055 return Dictionary(); |
| 1056 return dartToDictionary(object, exception); |
| 1057 } |
| 1058 |
| 1059 Dictionary DartUtilities::dartToDictionary(Dart_NativeArguments args, int idx, D
art_Handle& exception) |
| 1060 { |
| 1061 Dart_Handle object = Dart_GetNativeArgument(args, idx); |
| 1062 return dartToDictionary(object, exception); |
| 1063 } |
| 1064 |
| 1065 Dictionary DartUtilities::dartToDictionaryWithNullCheck(Dart_NativeArguments arg
s, int idx, Dart_Handle& exception) |
| 1066 { |
| 1067 Dart_Handle object = Dart_GetNativeArgument(args, idx); |
| 1068 return dartToDictionaryWithNullCheck(object, exception); |
| 1069 } |
| 1070 |
| 1071 LocalDOMWindow* DartUtilities::domWindowForCurrentIsolate() |
| 1072 { |
| 1073 DartDOMData* domData = DartDOMData::current(); |
| 1074 ASSERT(domData->scriptExecutionContext()->isDocument()); |
| 1075 Document* document = static_cast<Document*>(domData->scriptExecutionContext(
)); |
| 1076 return document->domWindow(); |
| 1077 } |
| 1078 |
| 1079 V8ScriptState* DartUtilities::v8ScriptStateForCurrentIsolate() |
| 1080 { |
| 1081 return V8ScriptState::forMainWorld(domWindowForCurrentIsolate()->frame()); |
| 1082 } |
| 1083 |
| 1084 ExecutionContext* DartUtilities::scriptExecutionContext() |
| 1085 { |
| 1086 if (Dart_CurrentIsolate()) |
| 1087 return DartDOMData::current()->scriptExecutionContext(); |
| 1088 return 0; |
| 1089 } |
| 1090 |
| 1091 bool DartUtilities::processingUserGesture() |
| 1092 { |
| 1093 // FIXME: implement this. |
| 1094 return false; |
| 1095 } |
| 1096 |
| 1097 intptr_t DartUtilities::libraryHandleToLibraryId(Dart_Handle library) |
| 1098 { |
| 1099 intptr_t libraryId = -1; |
| 1100 Dart_Handle ALLOW_UNUSED result = Dart_LibraryId(library, &libraryId); |
| 1101 ASSERT(!Dart_IsError(result)); |
| 1102 return libraryId; |
| 1103 } |
| 1104 |
| 1105 DartScriptState* DartUtilities::currentScriptState() |
| 1106 { |
| 1107 DartDOMData* dartDOMData = DartDOMData::current(); |
| 1108 if (!dartDOMData->rootScriptState()) { |
| 1109 DartController* controller = DartController::retrieve(dartDOMData->scrip
tExecutionContext()); |
| 1110 intptr_t libraryId = DartUtilities::libraryHandleToLibraryId(Dart_RootLi
brary()); |
| 1111 DartScriptState* scriptState = controller->lookupScriptState(Dart_Curren
tIsolate(), currentV8Context(), libraryId); |
| 1112 dartDOMData->setRootScriptState(scriptState); |
| 1113 return scriptState; |
| 1114 } |
| 1115 return dartDOMData->rootScriptState(); |
| 1116 } |
| 1117 |
| 1118 PassRefPtr<ScriptArguments> DartUtilities::createScriptArguments(Dart_Handle arg
ument, Dart_Handle& exception) |
| 1119 { |
| 1120 Vector<ScriptValue> arguments; |
| 1121 arguments.append(DartUtilities::dartToScriptValue(argument)); |
| 1122 return ScriptArguments::create(DartUtilities::currentScriptState(), argument
s); |
| 1123 } |
| 1124 |
| 1125 static PassRefPtr<ScriptCallStack> createScriptCallStackFromStackTrace(Dart_Stac
kTrace stackTrace) |
| 1126 { |
| 1127 uintptr_t frameCount = 0; |
| 1128 Dart_Handle result = Dart_StackTraceLength(stackTrace, reinterpret_cast<intp
tr_t*>(&frameCount)); |
| 1129 if (Dart_IsError(result)) |
| 1130 return nullptr; |
| 1131 |
| 1132 if (frameCount > ScriptCallStack::maxCallStackSizeToCapture) |
| 1133 frameCount = ScriptCallStack::maxCallStackSizeToCapture; |
| 1134 |
| 1135 Dart_Isolate isolate = Dart_CurrentIsolate(); |
| 1136 Vector<ScriptCallFrame> scriptCallStackFrames; |
| 1137 for (uintptr_t frameIndex = 0; frameIndex < frameCount; frameIndex++) { |
| 1138 Dart_ActivationFrame frame = 0; |
| 1139 result = Dart_GetActivationFrame(stackTrace, frameIndex, &frame); |
| 1140 if (Dart_IsError(result)) { |
| 1141 return nullptr; |
| 1142 } |
| 1143 ASSERT(frame); |
| 1144 |
| 1145 Dart_Handle dartFunctionName; |
| 1146 Dart_Handle dartScriptUrl; |
| 1147 intptr_t lineNumber = 0; |
| 1148 intptr_t columnNumber = 0; |
| 1149 result = Dart_ActivationFrameInfo(frame, &dartFunctionName, &dartScriptU
rl, &lineNumber, &columnNumber); |
| 1150 if (Dart_IsError(result)) { |
| 1151 return nullptr; |
| 1152 } |
| 1153 |
| 1154 // This skips frames where source is unavailable. WebKit code for the |
| 1155 // console assumes that console.log et al. are implemented directly |
| 1156 // as natives, i.e. that the top-of-stack will be the caller of |
| 1157 // console.log. The Dart implementation involves intermediate Dart |
| 1158 // calls, which are skipped by this clause. |
| 1159 if (columnNumber == -1) |
| 1160 continue; |
| 1161 |
| 1162 String functionName = DartUtilities::toString(dartFunctionName); |
| 1163 String scriptUrl = DartUtilities::toString(dartScriptUrl); |
| 1164 |
| 1165 scriptCallStackFrames.append(ScriptCallFrame(functionName, DartScriptDeb
ugServer::shared().getScriptId(scriptUrl, isolate), scriptUrl, lineNumber, colum
nNumber)); |
| 1166 } |
| 1167 if (scriptCallStackFrames.isEmpty()) |
| 1168 scriptCallStackFrames.append(ScriptCallFrame("undefined", "undefined", "
undefined", 0, 0)); |
| 1169 |
| 1170 return ScriptCallStack::create(scriptCallStackFrames); |
| 1171 } |
| 1172 |
| 1173 ScriptCallFrame DartUtilities::getTopFrame(Dart_StackTrace stackTrace, Dart_Hand
le& exception) |
| 1174 { |
| 1175 { |
| 1176 uintptr_t frameCount = 0; |
| 1177 Dart_Handle result = Dart_StackTraceLength(stackTrace, reinterpret_cast<
intptr_t*>(&frameCount)); |
| 1178 if (Dart_IsError(result)) { |
| 1179 exception = result; |
| 1180 goto fail; |
| 1181 } |
| 1182 if (!frameCount) { |
| 1183 exception = Dart_NewStringFromCString("Empty stack trace"); |
| 1184 goto fail; |
| 1185 } |
| 1186 Dart_ActivationFrame frame = 0; |
| 1187 result = Dart_GetActivationFrame(stackTrace, 0, &frame); |
| 1188 if (Dart_IsError(result)) { |
| 1189 exception = result; |
| 1190 goto fail; |
| 1191 } |
| 1192 ASSERT(frame); |
| 1193 return toScriptCallFrame(frame, exception); |
| 1194 } |
| 1195 fail: |
| 1196 return ScriptCallFrame("undefined", "undefined", "undefined", 0, 0); |
| 1197 } |
| 1198 |
| 1199 ScriptCallFrame DartUtilities::toScriptCallFrame(Dart_ActivationFrame frame, Dar
t_Handle& exception) |
| 1200 { |
| 1201 ASSERT(frame); |
| 1202 Dart_Handle functionName; |
| 1203 Dart_Handle scriptUrl; |
| 1204 intptr_t lineNumber = 0; |
| 1205 intptr_t columnNumber = 0; |
| 1206 Dart_Handle result = Dart_ActivationFrameInfo(frame, &functionName, &scriptU
rl, &lineNumber, &columnNumber); |
| 1207 if (Dart_IsError(result)) { |
| 1208 exception = result; |
| 1209 return ScriptCallFrame("undefined", "undefined", "undefined", 0, 0); |
| 1210 } |
| 1211 return ScriptCallFrame(DartUtilities::toString(functionName), "undefined", D
artUtilities::toString(scriptUrl), lineNumber, columnNumber); |
| 1212 } |
| 1213 |
| 1214 PassRefPtr<ScriptCallStack> DartUtilities::createScriptCallStack() |
| 1215 { |
| 1216 Dart_StackTrace trace = 0; |
| 1217 Dart_Handle ALLOW_UNUSED result = Dart_GetStackTrace(&trace); |
| 1218 ASSERT(!Dart_IsError(result)); |
| 1219 ASSERT(!Dart_IsNull(result)); |
| 1220 ASSERT(trace); |
| 1221 return createScriptCallStackFromStackTrace(trace); |
| 1222 } |
| 1223 |
| 1224 static const uint8_t* snapshotBuffer(int index) |
| 1225 { |
| 1226 // DartSnapshot.bytes is generated by build system. |
| 1227 #include "bindings/dart/DartSnapshot.bytes" |
| 1228 ASSERT(index == DartUtilities::VmIsolateSnapshotId || index == DartUtilities
::IsolateSnapshotId); |
| 1229 if (index == DartUtilities::VmIsolateSnapshotId) { |
| 1230 return vmIsolateSnapshotBuffer; |
| 1231 } |
| 1232 return isolateSnapshotBuffer; |
| 1233 } |
| 1234 |
| 1235 const uint8_t* DartUtilities::vmIsolateSnapshot() |
| 1236 { |
| 1237 return snapshotBuffer(VmIsolateSnapshotId); |
| 1238 } |
| 1239 |
| 1240 const uint8_t* DartUtilities::isolateSnapshot() |
| 1241 { |
| 1242 return snapshotBuffer(IsolateSnapshotId); |
| 1243 } |
| 1244 |
| 1245 Dart_Handle DartUtilities::canonicalizeUrl(Dart_Handle library, Dart_Handle urlH
andle, String url) |
| 1246 { |
| 1247 DEFINE_STATIC_LOCAL(String, dartPrefix, ("dart:")); |
| 1248 DEFINE_STATIC_LOCAL(String, packagePrefix, ("package:")); |
| 1249 |
| 1250 if (url.startsWith(dartPrefix) || url.startsWith(packagePrefix)) |
| 1251 // Not a relative URL. |
| 1252 return urlHandle; |
| 1253 |
| 1254 Dart_Handle libraryURLHandle = Dart_LibraryUrl(library); |
| 1255 ASSERT(!Dart_IsError(libraryURLHandle)); |
| 1256 String libraryURL = DartUtilities::toString(libraryURLHandle); |
| 1257 |
| 1258 String result; |
| 1259 if (libraryURL.startsWith(packagePrefix) && !libraryURL.startsWith("package:
//")) { |
| 1260 // KURL expects a URL with an authority. If the library URL is |
| 1261 // "package:<path>", we convert to "package://_/<path>" for resolution |
| 1262 // and convert back. |
| 1263 DEFINE_STATIC_LOCAL(String, resolvePrefix, ("package://_/")); |
| 1264 |
| 1265 libraryURL = resolvePrefix + libraryURL.substring(packagePrefix.length()
); |
| 1266 result = KURL(KURL(KURL(), libraryURL), url).string(); |
| 1267 if (result.startsWith(resolvePrefix)) |
| 1268 result = packagePrefix + result.substring(resolvePrefix.length()); |
| 1269 } else { |
| 1270 result = KURL(KURL(KURL(), libraryURL), url).string(); |
| 1271 } |
| 1272 |
| 1273 return DartUtilities::stringToDartString(result); |
| 1274 } |
| 1275 |
| 1276 void DartUtilities::reportProblem(ExecutionContext* context, const String& error
, int line, int col) |
| 1277 { |
| 1278 String sourceURL = context->url().string(); |
| 1279 |
| 1280 // FIXME: Pass in stack trace. |
| 1281 if (context && context->isDocument()) { |
| 1282 int scriptId = 0; |
| 1283 static_cast<Document*>(context)->reportException(ErrorEvent::create(erro
r, sourceURL, line, col, 0), scriptId, nullptr, NotSharableCrossOrigin); |
| 1284 } |
| 1285 } |
| 1286 |
| 1287 void DartUtilities::reportProblem(ExecutionContext* context, Dart_Handle result) |
| 1288 { |
| 1289 // FIXME: provide sourceURL. |
| 1290 String sourceURL = "FIXME"; |
| 1291 reportProblem(context, result, sourceURL); |
| 1292 } |
| 1293 |
| 1294 void DartUtilities::reportProblem(ExecutionContext* context, Dart_Handle result,
const String& sourceURL) |
| 1295 { |
| 1296 ASSERT(Dart_IsError(result)); |
| 1297 ASSERT(!sourceURL.isEmpty()); |
| 1298 |
| 1299 const String internalErrorPrefix("Internal error: "); |
| 1300 |
| 1301 String errorMessage; |
| 1302 // FIXME: line number info. |
| 1303 int lineNumber = 0; |
| 1304 // FIXME: call stack info. |
| 1305 RefPtr<ScriptCallStack> callStack; |
| 1306 |
| 1307 if (!Dart_ErrorHasException(result)) { |
| 1308 errorMessage = internalErrorPrefix + Dart_GetError(result); |
| 1309 } else { |
| 1310 // Print the exception. |
| 1311 Dart_Handle exception = Dart_ErrorGetException(result); |
| 1312 ASSERT(!Dart_IsError(exception)); |
| 1313 |
| 1314 exception = Dart_ToString(exception); |
| 1315 if (Dart_IsError(exception)) |
| 1316 errorMessage = String("Error: ") + Dart_GetError(exception); |
| 1317 else |
| 1318 errorMessage = String("Exception: ") + DartUtilities::toString(excep
tion); |
| 1319 |
| 1320 // Print the stack trace. |
| 1321 Dart_StackTrace stacktrace; |
| 1322 Dart_Handle ALLOW_UNUSED traceResult = Dart_GetStackTraceFromError(resul
t, &stacktrace); |
| 1323 ASSERT(!Dart_IsError(traceResult)); |
| 1324 callStack = createScriptCallStackFromStackTrace(stacktrace); |
| 1325 } |
| 1326 |
| 1327 if (context && context->isDocument()) { |
| 1328 int scriptId = 0; |
| 1329 static_cast<Document*>(context)->reportException(ErrorEvent::create(erro
rMessage, sourceURL, lineNumber, 0, 0), scriptId, callStack, NotSharableCrossOri
gin); |
| 1330 } |
| 1331 } |
| 1332 |
| 1333 Dart_Handle DartUtilities::toDartCoreException(const String& className, const St
ring& message) |
| 1334 { |
| 1335 DartApiScope apiScope; |
| 1336 DartDOMData* domData = DartDOMData::current(); |
| 1337 Dart_Handle coreLib = Dart_LookupLibrary(Dart_NewStringFromCString("dart:cor
e")); |
| 1338 Dart_Handle errorClass = Dart_GetType(coreLib, stringToDart(className), 0, 0
); |
| 1339 Dart_Handle dartMessage = stringToDart(message); |
| 1340 Dart_Handle error = Dart_New(errorClass, Dart_NewStringFromCString(""), 1, &
dartMessage); |
| 1341 Dart_SetPersistentHandle(domData->currentException(), error); |
| 1342 return domData->currentException(); |
| 1343 } |
| 1344 |
| 1345 Dart_Handle DartUtilities::coreArgumentErrorException(const String& message) |
| 1346 { |
| 1347 return DartUtilities::toDartCoreException("ArgumentError", message); |
| 1348 } |
| 1349 |
| 1350 Dart_Handle DartUtilities::notImplementedException(const char* fileName, int lin
eNumber) |
| 1351 { |
| 1352 Dart_Handle args[2] = { Dart_NewStringFromCString(fileName), Dart_NewInteger
(lineNumber) }; |
| 1353 Dart_Handle result = DartUtilities::invokeUtilsMethod("makeUnimplementedErro
r", 2, args); |
| 1354 ASSERT(!Dart_IsError(result)); |
| 1355 return result; |
| 1356 } |
| 1357 |
| 1358 Dart_Handle DartUtilities::newResolvedPromise(Dart_Handle value) |
| 1359 { |
| 1360 Dart_Handle asyncLib = Dart_LookupLibrary(Dart_NewStringFromCString("dart:as
ync")); |
| 1361 Dart_Handle futureClass = Dart_GetType(asyncLib, Dart_NewStringFromCString("
Future"), 0, 0); |
| 1362 return Dart_New(futureClass, Dart_NewStringFromCString("value"), 1, &value); |
| 1363 } |
| 1364 |
| 1365 Dart_Handle DartUtilities::newSmashedPromise(Dart_Handle error) |
| 1366 { |
| 1367 Dart_Handle asyncLib = Dart_LookupLibrary(Dart_NewStringFromCString("dart:as
ync")); |
| 1368 Dart_Handle futureClass = Dart_GetType(asyncLib, Dart_NewStringFromCString("
Future"), 0, 0); |
| 1369 return Dart_New(futureClass, Dart_NewStringFromCString("error"), 1, &error); |
| 1370 } |
| 1371 |
| 1372 Dart_Handle DartUtilities::newResolver() |
| 1373 { |
| 1374 Dart_Handle asyncLib = Dart_LookupLibrary(Dart_NewStringFromCString("dart:as
ync")); |
| 1375 Dart_Handle futureClass = Dart_GetType(asyncLib, Dart_NewStringFromCString("
Completer"), 0, 0); |
| 1376 return Dart_New(futureClass, Dart_EmptyString(), 0, 0); |
| 1377 } |
| 1378 |
| 1379 Dart_Handle DartUtilities::newArgumentError(const String& message) |
| 1380 { |
| 1381 Dart_Handle asyncLib = Dart_LookupLibrary(Dart_NewStringFromCString("dart:co
re")); |
| 1382 Dart_Handle futureClass = Dart_GetType(asyncLib, Dart_NewStringFromCString("
ArgumentError"), 0, 0); |
| 1383 Dart_Handle dartMessage = stringToDart(message); |
| 1384 return Dart_New(futureClass, Dart_EmptyString(), 1, &dartMessage); |
| 1385 } |
| 1386 |
| 1387 Dart_Handle DartUtilities::invokeUtilsMethod(const char* methodName, int argCoun
t, Dart_Handle* args) |
| 1388 { |
| 1389 DartDOMData* domData = DartDOMData::current(); |
| 1390 ASSERT(domData); |
| 1391 Dart_PersistentHandle library = domData->htmlLibrary(); |
| 1392 ASSERT(!Dart_IsError(library)); |
| 1393 |
| 1394 Dart_Handle utilsClass = Dart_GetType(library, Dart_NewStringFromCString("_U
tils"), 0, 0); |
| 1395 ASSERT(!Dart_IsError(utilsClass)); |
| 1396 |
| 1397 return Dart_Invoke(utilsClass, Dart_NewStringFromCString(methodName), argCou
nt, args); |
| 1398 } |
| 1399 |
| 1400 |
| 1401 int DartUtilities::getProp(const char* name, char* value, int valueLen) |
| 1402 { |
| 1403 #if OS(ANDROID) |
| 1404 return __system_property_get(name, value); |
| 1405 #else |
| 1406 char* v = getenv(name); |
| 1407 if (!v) { |
| 1408 return 0; |
| 1409 } |
| 1410 ASSERT(valueLen > 0 && static_cast<size_t>(valueLen) > strlen(v)); |
| 1411 strncpy(value, v, valueLen); |
| 1412 value[valueLen - 1] = '\0'; |
| 1413 return strlen(value); |
| 1414 #endif |
| 1415 } |
| 1416 } |
OLD | NEW |