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