| 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 "DartUtilities.h" | |
| 32 | |
| 33 #include "DartEventListener.h" | |
| 34 #include "DartIsolateState.h" | |
| 35 #include "DartMessagePort.h" | |
| 36 #include "DartNode.h" | |
| 37 #include "DOMWindow.h" | |
| 38 #include "Document.h" | |
| 39 #include "Frame.h" | |
| 40 #include "ScriptCallStack.h" | |
| 41 #include "ScriptArguments.h" | |
| 42 #include "SerializedScriptValue.h" | |
| 43 #include "V8Converter.h" | |
| 44 #include "V8Proxy.h" | |
| 45 | |
| 46 #include <wtf/text/AtomicString.h> | |
| 47 #include <wtf/text/CString.h> | |
| 48 | |
| 49 namespace WebCore { | |
| 50 | |
| 51 const char* DartUtilities::domLibraryName = "dart:dom"; | |
| 52 | |
| 53 PassRefPtr<StringImpl> DartUtilities::toStringImpl(Dart_Handle object, Conversio
nFlag flag, Dart_Handle& exception) | |
| 54 { | |
| 55 if (flag == ConvertNullToEmptyString && Dart_IsNull(object)) | |
| 56 return 0; | |
| 57 | |
| 58 if (!Dart_IsString(object)) { | |
| 59 exception = Dart_NewString("String expected"); | |
| 60 return 0; | |
| 61 } | |
| 62 if (!Dart_IsString16(object)) { | |
| 63 // FIXME: consider convertion to UTF16 in this case. | |
| 64 exception = Dart_NewString("32-bit string met, cannot be used in DOM API
"); | |
| 65 return 0; | |
| 66 } | |
| 67 | |
| 68 if (Dart_IsExternalString(object)) { | |
| 69 void* peer = 0; | |
| 70 Dart_ExternalStringGetPeer(object, &peer); | |
| 71 ASSERT(peer); | |
| 72 StringImpl* stringImpl = reinterpret_cast<StringImpl*>(peer); | |
| 73 return stringImpl; | |
| 74 } | |
| 75 | |
| 76 // Note: hopefully we should never overflow length as the string would be ju
st too long to fit | |
| 77 // into memory. | |
| 78 intptr_t length = 0; | |
| 79 Dart_StringLength(object, &length); | |
| 80 UChar* buffer; | |
| 81 RefPtr<StringImpl> result = StringImpl::createUninitialized(length, buffer); | |
| 82 Dart_StringGet16(object, buffer, &length); | |
| 83 return result.release(); | |
| 84 } | |
| 85 | |
| 86 static void stringFinalizer(void* peer) { | |
| 87 StringImpl* stringImpl = reinterpret_cast<StringImpl*>(peer); | |
| 88 stringImpl->deref(); | |
| 89 } | |
| 90 | |
| 91 static Dart_Handle stringImplToDartString(StringImpl* stringImpl) | |
| 92 { | |
| 93 if (!stringImpl) | |
| 94 return Dart_NewString8(0, 0); | |
| 95 | |
| 96 stringImpl->ref(); | |
| 97 // FIXME: maybe it makes sense only externalize strings longer than certain
threshold, such as 5 symbols. | |
| 98 return Dart_NewExternalString16(stringImpl->characters(), stringImpl->length
(), | |
| 99 stringImpl, stringFinalizer); | |
| 100 } | |
| 101 | |
| 102 Dart_Handle DartUtilities::stringToDartString(const String& str) | |
| 103 { | |
| 104 return stringImplToDartString(str.impl()); | |
| 105 } | |
| 106 | |
| 107 Dart_Handle DartUtilities::stringToDartString(const AtomicString& str) | |
| 108 { | |
| 109 return stringImplToDartString(str.impl()); | |
| 110 } | |
| 111 | |
| 112 template <typename Trait> | |
| 113 typename Trait::nativeType convert(Dart_Handle object, Dart_Handle& exception) | |
| 114 { | |
| 115 typename Trait::nativeType value; | |
| 116 return !Dart_IsError(Trait::convert(object, &value)) ? value : typename Trai
t::nativeType(); | |
| 117 } | |
| 118 | |
| 119 struct IntegerTrait { | |
| 120 typedef int64_t nativeType; | |
| 121 static Dart_Handle convert(Dart_Handle object, int64_t* value) | |
| 122 { | |
| 123 return Dart_IntegerToInt64(object, value); | |
| 124 // FIXME: support bigints. | |
| 125 } | |
| 126 }; | |
| 127 | |
| 128 int64_t DartUtilities::toInteger(Dart_Handle object, Dart_Handle& exception) | |
| 129 { | |
| 130 return convert<IntegerTrait>(object, exception); | |
| 131 } | |
| 132 | |
| 133 int64_t DartUtilities::toInteger(Dart_Handle object) | |
| 134 { | |
| 135 Dart_Handle exception = 0; | |
| 136 int64_t value = DartUtilities::toInteger(object, exception); | |
| 137 ASSERT(!exception); | |
| 138 return value; | |
| 139 } | |
| 140 | |
| 141 struct DoubleTrait { | |
| 142 typedef double nativeType; | |
| 143 static Dart_Handle convert(Dart_Handle object, double* value) | |
| 144 { | |
| 145 if (!Dart_IsNumber(object)) | |
| 146 return Dart_Error("the object !is Number"); | |
| 147 | |
| 148 object = Dart_InvokeDynamic(object, Dart_NewString("toDouble"), 0, 0); | |
| 149 if (Dart_IsError(object)) | |
| 150 return object; | |
| 151 | |
| 152 return Dart_DoubleValue(object, value); | |
| 153 } | |
| 154 }; | |
| 155 | |
| 156 double DartUtilities::toDouble(Dart_Handle object, Dart_Handle& exception) | |
| 157 { | |
| 158 return convert<DoubleTrait>(object, exception); | |
| 159 } | |
| 160 | |
| 161 double DartUtilities::toDouble(Dart_Handle object) | |
| 162 { | |
| 163 Dart_Handle exception = 0; | |
| 164 double value = DartUtilities::toDouble(object, exception); | |
| 165 ASSERT(!exception); | |
| 166 return value; | |
| 167 } | |
| 168 | |
| 169 struct BoolTrait { | |
| 170 typedef bool nativeType; | |
| 171 static Dart_Handle convert(Dart_Handle object, bool* value) { return Dart_Bo
oleanValue(object, value); } | |
| 172 }; | |
| 173 | |
| 174 bool DartUtilities::toBool(Dart_Handle object, Dart_Handle& exception) | |
| 175 { | |
| 176 return convert<BoolTrait>(object, exception); | |
| 177 } | |
| 178 | |
| 179 bool DartUtilities::toBool(Dart_Handle object) | |
| 180 { | |
| 181 Dart_Handle exception = 0; | |
| 182 bool value = DartUtilities::toBool(object, exception); | |
| 183 ASSERT(!exception); | |
| 184 return value; | |
| 185 } | |
| 186 | |
| 187 PassRefPtr<EventListener> DartUtilities::toEventListener(Dart_Handle object, Dar
t_Handle& exception) | |
| 188 { | |
| 189 if (Dart_IsNull(object)) { | |
| 190 exception = Dart_NewString("Null passed where Dart closure is expected")
; | |
| 191 return 0; | |
| 192 } | |
| 193 | |
| 194 if (!Dart_IsClosure(object)) { | |
| 195 exception = Dart_NewString("Not a Dart closure passed"); | |
| 196 return 0; | |
| 197 } | |
| 198 | |
| 199 return DartEventListener::createOrFetch(object); | |
| 200 } | |
| 201 | |
| 202 static v8::Local<v8::Context> currentV8Context() | |
| 203 { | |
| 204 Frame* frame = DartUtilities::domWindowForCurrentIsolate()->frame(); | |
| 205 v8::Local<v8::Context> context = V8Proxy::mainWorldContext(frame); | |
| 206 ASSERT(!context.IsEmpty()); | |
| 207 return context; | |
| 208 } | |
| 209 | |
| 210 PassRefPtr<SerializedScriptValue> DartUtilities::toSerializedScriptValue(Dart_Ha
ndle value, Dart_Handle& exception) | |
| 211 { | |
| 212 v8::HandleScope handleScope; | |
| 213 v8::Context::Scope scope(currentV8Context()); | |
| 214 | |
| 215 v8::Handle<v8::Value> v8Value = V8Converter::toV8(value, exception); | |
| 216 if (exception) | |
| 217 return 0; | |
| 218 return SerializedScriptValue::create(v8Value); | |
| 219 } | |
| 220 | |
| 221 Dart_Handle DartUtilities::fromSerializedScriptValue(SerializedScriptValue* valu
e) | |
| 222 { | |
| 223 v8::HandleScope handleScope; | |
| 224 v8::Context::Scope scope(currentV8Context()); | |
| 225 | |
| 226 // FIXME: better error handling. | |
| 227 Dart_Handle exception = 0; | |
| 228 return V8Converter::toDart(value->deserialize(), exception); | |
| 229 } | |
| 230 | |
| 231 PassRefPtr<EventTarget> DartUtilities::toEventTarget(Dart_Handle object, Dart_Ha
ndle& exception) | |
| 232 { | |
| 233 // FIXME: currently it's too risky to remove, but when Optional=CallWithDefa
ultValue is | |
| 234 // implemented, we should give it a try and unify with the rest of conversio
n. | |
| 235 if (Dart_IsNull(object)) | |
| 236 return 0; | |
| 237 | |
| 238 return DartNode::toNative(object, exception); | |
| 239 } | |
| 240 | |
| 241 // FIXME: this function requires better testing. Currently blocking as new Messa
geChannel hasn't been implemented yet. | |
| 242 void DartUtilities::toMessagePortArray(Dart_Handle value, MessagePortArray& port
Array, Dart_Handle& exception) | |
| 243 { | |
| 244 Dart_Handle dom = Dart_LookupLibrary(Dart_NewString(DartUtilities::domLibrar
yName)); | |
| 245 ASSERT(!Dart_IsError(dom)); | |
| 246 | |
| 247 Dart_Handle asList = Dart_InvokeStatic(dom, Dart_NewString("Utils"), Dart_Ne
wString("convertToList"), 1, &value); | |
| 248 if (Dart_IsError(asList)) { | |
| 249 DartUtilities::reportProblem(DartUtilities::scriptExecutionContext(), as
List); | |
| 250 exception = DartDOMWrapper::exceptionCodeToDartException(INVALID_STATE_E
RR); | |
| 251 return; | |
| 252 } | |
| 253 ASSERT(Dart_IsList(asList)); | |
| 254 | |
| 255 intptr_t length = 0; | |
| 256 Dart_ListLength(asList, &length); | |
| 257 portArray.resize(length); | |
| 258 for (int i = 0; i < length; i++) { | |
| 259 Dart_Handle element = Dart_ListGetAt(asList, i); | |
| 260 if (Dart_IsError(element)) { | |
| 261 exception = DartDOMWrapper::exceptionCodeToDartException(INVALID_STA
TE_ERR); | |
| 262 return; | |
| 263 } | |
| 264 | |
| 265 MessagePort* messagePort = DartMessagePort::toNative(element, exception)
.get(); | |
| 266 if (exception) { | |
| 267 exception = DartDOMWrapper::exceptionCodeToDartException(INVALID_STA
TE_ERR); | |
| 268 return; | |
| 269 } | |
| 270 | |
| 271 ASSERT(messagePort); | |
| 272 portArray[i] = messagePort; | |
| 273 } | |
| 274 } | |
| 275 | |
| 276 class DartDOMData { | |
| 277 public: | |
| 278 DartDOMData() | |
| 279 : m_scriptExecutionContext(0) | |
| 280 , m_domWindow(0) | |
| 281 , m_recursion(0) | |
| 282 { | |
| 283 } | |
| 284 | |
| 285 DartDOMData(ScriptExecutionContext* context) | |
| 286 : m_scriptExecutionContext(context) | |
| 287 , m_recursion(0) | |
| 288 { | |
| 289 ASSERT(context); | |
| 290 ASSERT(context->isDocument()); // WorkerContext is not supported yet. | |
| 291 Document* document = static_cast<Document*>(context); | |
| 292 m_domWindow = document->domWindow(); | |
| 293 } | |
| 294 | |
| 295 ScriptExecutionContext* scriptExecutionContext() { return m_scriptExecutionC
ontext; } | |
| 296 DOMWindow* domWindow() { return m_domWindow; } | |
| 297 DartDOMMap* domMap() { return &m_domMap; } | |
| 298 int* recursion() { return &m_recursion; } | |
| 299 | |
| 300 private: | |
| 301 ScriptExecutionContext* m_scriptExecutionContext; | |
| 302 DOMWindow* m_domWindow; | |
| 303 DartDOMMap m_domMap; | |
| 304 int m_recursion; | |
| 305 }; | |
| 306 | |
| 307 typedef HashMap<Dart_Isolate, DartDOMData*> IsolateToDartDOMDataMap; | |
| 308 | |
| 309 static IsolateToDartDOMDataMap& isolateToDartDOMDataMap() | |
| 310 { | |
| 311 DEFINE_STATIC_LOCAL(IsolateToDartDOMDataMap, map, ()); | |
| 312 return map; | |
| 313 } | |
| 314 | |
| 315 static DartDOMData* domDataForIsolate(Dart_Isolate isolate) | |
| 316 { | |
| 317 IsolateToDartDOMDataMap::iterator it = isolateToDartDOMDataMap().find(isolat
e); | |
| 318 ASSERT(it != isolateToDartDOMDataMap().end()); | |
| 319 return it->second; | |
| 320 } | |
| 321 | |
| 322 static DartDOMData* currentDOMData() | |
| 323 { | |
| 324 return domDataForIsolate(DartIsolateState::current()); | |
| 325 } | |
| 326 | |
| 327 void DartUtilities::registerIsolateContext(Dart_Isolate isolate, ScriptExecution
Context* context) | |
| 328 { | |
| 329 ASSERT(!isolateToDartDOMDataMap().contains(isolate)); | |
| 330 isolateToDartDOMDataMap().set(isolate, new DartDOMData(context)); | |
| 331 } | |
| 332 | |
| 333 ScriptExecutionContext* DartUtilities::isolateContext(Dart_Isolate isolate) | |
| 334 { | |
| 335 return domDataForIsolate(isolate)->scriptExecutionContext(); | |
| 336 } | |
| 337 | |
| 338 void DartUtilities::unregisterIsolateContext(Dart_Isolate isolate) | |
| 339 { | |
| 340 IsolateToDartDOMDataMap::iterator it = isolateToDartDOMDataMap().find(isolat
e); | |
| 341 ASSERT(it != isolateToDartDOMDataMap().end()); | |
| 342 delete it->second; | |
| 343 isolateToDartDOMDataMap().remove(it); | |
| 344 } | |
| 345 | |
| 346 bool DartUtilities::isFullDomIsolate(Dart_Isolate isolate) | |
| 347 { | |
| 348 return isolateToDartDOMDataMap().contains(isolate); | |
| 349 } | |
| 350 | |
| 351 DOMWindow* DartUtilities::domWindowForIsolate(Dart_Isolate isolate) | |
| 352 { | |
| 353 return domDataForIsolate(isolate)->domWindow(); | |
| 354 } | |
| 355 | |
| 356 DOMWindow* DartUtilities::domWindowForCurrentIsolate() | |
| 357 { | |
| 358 return currentDOMData()->domWindow(); | |
| 359 } | |
| 360 | |
| 361 Dart_Handle DartUtilities::domLibraryForCurrentIsolate() | |
| 362 { | |
| 363 // FIXME: Cache this on the isolate. | |
| 364 Dart_Handle library = Dart_LookupLibrary(Dart_NewString(domLibraryName)); | |
| 365 ASSERT(!Dart_IsError(library)); | |
| 366 return library; | |
| 367 } | |
| 368 | |
| 369 DartDOMMap* DartUtilities::domMapForIsolate(Dart_Isolate isolate) | |
| 370 { | |
| 371 return domDataForIsolate(isolate)->domMap(); | |
| 372 } | |
| 373 | |
| 374 DartDOMMap* DartUtilities::domMapForCurrentIsolate() | |
| 375 { | |
| 376 return currentDOMData()->domMap(); | |
| 377 } | |
| 378 | |
| 379 int* DartUtilities::recursionForIsolate(Dart_Isolate isolate) | |
| 380 { | |
| 381 return domDataForIsolate(isolate)->recursion(); | |
| 382 } | |
| 383 | |
| 384 int* DartUtilities::recursionForCurrentIsolate() | |
| 385 { | |
| 386 return currentDOMData()->recursion(); | |
| 387 } | |
| 388 | |
| 389 ScriptExecutionContext* DartUtilities::scriptExecutionContext() | |
| 390 { | |
| 391 return currentDOMData()->scriptExecutionContext(); | |
| 392 } | |
| 393 | |
| 394 bool DartUtilities::processingUserGesture() | |
| 395 { | |
| 396 // FIXME: implement this. | |
| 397 return false; | |
| 398 } | |
| 399 | |
| 400 PassRefPtr<ScriptArguments> DartUtilities::createScriptArguments(Dart_Handle arg
ument, Dart_Handle& exception) | |
| 401 { | |
| 402 v8::Handle<v8::Value> v8Argument = V8Converter::toV8(argument, exception); | |
| 403 if (v8Argument->IsUndefined()) | |
| 404 return 0; | |
| 405 Vector<ScriptValue> arguments; | |
| 406 arguments.append(v8Argument); | |
| 407 ScriptState* scriptState = ScriptState::forContext(currentV8Context()); | |
| 408 return ScriptArguments::create(scriptState, arguments); | |
| 409 } | |
| 410 | |
| 411 PassRefPtr<ScriptCallStack> DartUtilities::createScriptCallStack() | |
| 412 { | |
| 413 // FIXME: wrap current dart call stack as ScriptCallStack. | |
| 414 Vector<ScriptCallFrame> wrappedCallFrames; | |
| 415 wrappedCallFrames.append(ScriptCallFrame("undefined", "undefined", 0)); | |
| 416 return ScriptCallStack::create(wrappedCallFrames); | |
| 417 } | |
| 418 | |
| 419 const uint8_t* DartUtilities::fullSnapshot() | |
| 420 { | |
| 421 static const uint8_t snapshotBuffer[] = { | |
| 422 // DartSnapshot.bytes is generated by build system. | |
| 423 #include "DartSnapshot.bytes" | |
| 424 }; | |
| 425 return snapshotBuffer; | |
| 426 } | |
| 427 | |
| 428 void DartUtilities::reportProblem(ScriptExecutionContext* context, Dart_Handle r
esult) | |
| 429 { | |
| 430 ASSERT(Dart_IsError(result)); | |
| 431 | |
| 432 const String internalErrorPrefix("Internal error: "); | |
| 433 | |
| 434 String errorMessage; | |
| 435 // FIXME: source file info. | |
| 436 String sourceFile = "FIXME"; | |
| 437 // FIXME: line number info. | |
| 438 int lineNumber = 0; | |
| 439 // FIXME: call stack info. | |
| 440 RefPtr<ScriptCallStack> callStack; | |
| 441 | |
| 442 if (!Dart_ErrorHasException(result)) | |
| 443 errorMessage = internalErrorPrefix + Dart_GetError(result); | |
| 444 else { | |
| 445 // Print the exception. | |
| 446 Dart_Handle exception = Dart_ErrorGetException(result); | |
| 447 ASSERT(!Dart_IsError(exception)); | |
| 448 | |
| 449 exception = Dart_ToString(exception); | |
| 450 if (Dart_IsError(exception)) | |
| 451 errorMessage = String("Error converting exception to a string: ") +
Dart_GetError(exception); | |
| 452 else | |
| 453 errorMessage = String("Exception: ") + DartUtilities::dartStringToSt
ring(exception); | |
| 454 | |
| 455 // FIXME: Fill in the callStack, sourceFile, and lineNumber | |
| 456 // and remove the below once the Dart APIs to iterate over the | |
| 457 // trace are available. | |
| 458 | |
| 459 // Print the stack trace. | |
| 460 Dart_Handle stacktrace = Dart_ErrorGetStacktrace(result); | |
| 461 ASSERT(!Dart_IsError(stacktrace)); | |
| 462 | |
| 463 stacktrace = Dart_ToString(stacktrace); | |
| 464 if (Dart_IsError(stacktrace)) | |
| 465 errorMessage += String("\nError converting stack trace to a string:
") + Dart_GetError(stacktrace); | |
| 466 else | |
| 467 errorMessage += String("\nStack Trace: ") + DartUtilities::dartStrin
gToString(stacktrace); | |
| 468 } | |
| 469 | |
| 470 if (context && context->isDocument()) | |
| 471 static_cast<Document*>(context)->reportException(errorMessage, lineNumbe
r, sourceFile, callStack); | |
| 472 } | |
| 473 | |
| 474 } | |
| OLD | NEW |