| OLD | NEW |
| (Empty) |
| 1 /* | |
| 2 * Copyright (C) 2013 Google Inc. 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 | |
| 32 #include "bindings/core/dart/DartJsInterop.h" | |
| 33 | |
| 34 #include "bindings/core/dart/DartDOMWrapper.h" | |
| 35 #include "bindings/core/dart/DartHandleProxy.h" | |
| 36 #include "bindings/core/dart/DartJsInteropData.h" | |
| 37 #include "bindings/core/dart/DartPersistentValue.h" | |
| 38 #include "bindings/core/dart/DartUtilities.h" | |
| 39 #include "bindings/core/dart/V8Converter.h" | |
| 40 #include "bindings/core/v8/V8Binding.h" | |
| 41 #include "bindings/core/v8/V8RecursionScope.h" | |
| 42 #include "bindings/core/v8/V8ScriptRunner.h" | |
| 43 | |
| 44 #include "wtf/StdLibExtras.h" | |
| 45 | |
| 46 #include <dart_api.h> | |
| 47 #include <limits> | |
| 48 | |
| 49 namespace blink { | |
| 50 | |
| 51 const int JsObject::dartClassId = _JsObjectClassId; | |
| 52 const int JsFunction::dartClassId = _JsFunctionClassId; | |
| 53 const int JsArray::dartClassId = _JsArrayClassId; | |
| 54 | |
| 55 static v8::Local<v8::FunctionTemplate> dartFunctionTemplate(); | |
| 56 static v8::Local<v8::FunctionTemplate> dartObjectTemplate(); | |
| 57 | |
| 58 template<typename CallbackInfo> | |
| 59 void setJsReturnValue(DartDOMData* domData, CallbackInfo info, Dart_Handle resul
t) | |
| 60 { | |
| 61 if (Dart_IsError(result)) { | |
| 62 v8::Isolate* v8Isolate = v8::Isolate::GetCurrent(); | |
| 63 V8ThrowException::throwException(v8::String::NewFromUtf8(v8Isolate, Dart
_GetError(result)), v8Isolate); | |
| 64 } else { | |
| 65 Dart_Handle exception = 0; | |
| 66 v8::Local<v8::Value> ret = JsInterop::fromDart(domData, result, exceptio
n); | |
| 67 if (exception) { | |
| 68 V8ThrowException::throwException(V8Converter::stringToV8(Dart_ToStri
ng(exception)), v8::Isolate::GetCurrent()); | |
| 69 return; | |
| 70 } | |
| 71 v8SetReturnValue(info, ret); | |
| 72 } | |
| 73 } | |
| 74 | |
| 75 static void functionInvocationCallback(const v8::FunctionCallbackInfo<v8::Value>
& args) | |
| 76 { | |
| 77 DartScopes scopes(args.Holder()); | |
| 78 Dart_Handle handle = scopes.handle; | |
| 79 DartDOMData* domData = DartDOMData::current(); | |
| 80 ASSERT(domData); | |
| 81 ASSERT(DartUtilities::isFunction(domData, handle)); | |
| 82 | |
| 83 Vector<Dart_Handle> dartFunctionArgs; | |
| 84 ASSERT(args.Length() == 1 || args.Length() == 2); | |
| 85 // If there is 1 argument, we assume it is a v8:Array or arguments, if | |
| 86 // there are 2 arguments, the first argument is "this" and the second | |
| 87 // argument is an array of arguments. | |
| 88 if (args.Length() > 1) { | |
| 89 dartFunctionArgs.append(JsInterop::toDart(args[0])); | |
| 90 } | |
| 91 | |
| 92 v8::Local<v8::Array> argsList = args[args.Length()-1].As<v8::Array>(); | |
| 93 uint32_t argsListLength = argsList->Length(); | |
| 94 for (uint32_t i = 0; i < argsListLength; i++) { | |
| 95 dartFunctionArgs.append(JsInterop::toDart(argsList->Get(i))); | |
| 96 } | |
| 97 | |
| 98 setJsReturnValue(domData, args, Dart_InvokeClosure(handle, dartFunctionArgs.
size(), dartFunctionArgs.data())); | |
| 99 } | |
| 100 | |
| 101 static v8::Local<v8::ObjectTemplate> setupInstanceTemplate(v8::Local<v8::Functio
nTemplate> proxyTemplate) | |
| 102 { | |
| 103 v8::Local<v8::ObjectTemplate> instanceTemplate = proxyTemplate->InstanceTemp
late(); | |
| 104 instanceTemplate->SetInternalFieldCount(1); | |
| 105 return instanceTemplate; | |
| 106 } | |
| 107 | |
| 108 static v8::Local<v8::FunctionTemplate> dartFunctionTemplate() | |
| 109 { | |
| 110 DEFINE_STATIC_LOCAL(v8::Persistent<v8::FunctionTemplate>, proxyTemplate, ())
; | |
| 111 v8::Local<v8::FunctionTemplate> proxyTemplateLocal; | |
| 112 v8::Isolate* v8Isolate = v8::Isolate::GetCurrent(); | |
| 113 if (proxyTemplate.IsEmpty()) { | |
| 114 proxyTemplate.Reset(v8::Isolate::GetCurrent(), v8::FunctionTemplate::New
(v8Isolate)); | |
| 115 proxyTemplateLocal = v8::Local<v8::FunctionTemplate>::New(v8Isolate, pro
xyTemplate); | |
| 116 v8::Local<v8::ObjectTemplate> instanceTemplate = setupInstanceTemplate(p
roxyTemplateLocal); | |
| 117 | |
| 118 instanceTemplate->SetCallAsFunctionHandler(&functionInvocationCallback); | |
| 119 } else { | |
| 120 proxyTemplateLocal = v8::Local<v8::FunctionTemplate>::New(v8Isolate, pro
xyTemplate); | |
| 121 } | |
| 122 return proxyTemplateLocal; | |
| 123 } | |
| 124 | |
| 125 static v8::Local<v8::FunctionTemplate> dartObjectTemplate() | |
| 126 { | |
| 127 DEFINE_STATIC_LOCAL(v8::Persistent<v8::FunctionTemplate>, proxyTemplate, ())
; | |
| 128 v8::Local<v8::FunctionTemplate> proxyTemplateLocal; | |
| 129 v8::Isolate* v8Isolate = v8::Isolate::GetCurrent(); | |
| 130 if (proxyTemplate.IsEmpty()) { | |
| 131 proxyTemplate.Reset(v8Isolate, v8::FunctionTemplate::New(v8Isolate)); | |
| 132 proxyTemplateLocal = v8::Local<v8::FunctionTemplate>::New(v8Isolate, pro
xyTemplate); | |
| 133 proxyTemplateLocal->SetClassName(v8::String::NewFromUtf8(v8Isolate, "Dar
tObject")); | |
| 134 setupInstanceTemplate(proxyTemplateLocal); | |
| 135 } else { | |
| 136 proxyTemplateLocal = v8::Local<v8::FunctionTemplate>::New(v8Isolate, pro
xyTemplate); | |
| 137 } | |
| 138 return proxyTemplateLocal; | |
| 139 } | |
| 140 | |
| 141 /** | |
| 142 * Helper class to manage scopes needed for JSInterop code. | |
| 143 */ | |
| 144 class JsInteropScopes { | |
| 145 public: | |
| 146 Dart_NativeArguments args; | |
| 147 v8::Context::Scope v8Scope; | |
| 148 v8::TryCatch tryCatch; | |
| 149 | |
| 150 JsInteropScopes(Dart_NativeArguments args) | |
| 151 : args(args) | |
| 152 , v8Scope(DartUtilities::currentV8Context()) | |
| 153 { | |
| 154 ASSERT(v8::Isolate::GetCurrent()); | |
| 155 } | |
| 156 | |
| 157 ~JsInteropScopes() | |
| 158 { | |
| 159 // The user is expected to call handleJsException before the scope is | |
| 160 // closed so that V8 exceptions are properly sent back to Dart. | |
| 161 ASSERT(!tryCatch.HasCaught()); | |
| 162 } | |
| 163 | |
| 164 bool handleJsException(Dart_Handle* exception) | |
| 165 { | |
| 166 if (!tryCatch.HasCaught()) | |
| 167 return false; | |
| 168 // FIXME: terminate v8 if tryCatch.CanContinue() is false. | |
| 169 ASSERT(tryCatch.CanContinue()); | |
| 170 ASSERT(exception); | |
| 171 v8::Handle<v8::Value> ex(tryCatch.Exception()->ToString()); | |
| 172 if (ex.IsEmpty()) { | |
| 173 *exception = Dart_NewStringFromCString("Empty JavaScript exception")
; | |
| 174 } else { | |
| 175 *exception = V8Converter::stringToDart(ex); | |
| 176 } | |
| 177 tryCatch.Reset(); | |
| 178 return true; | |
| 179 } | |
| 180 | |
| 181 void setReturnValue(Dart_Handle ret) | |
| 182 { | |
| 183 ASSERT(!tryCatch.HasCaught()); | |
| 184 Dart_SetReturnValue(args, ret); | |
| 185 } | |
| 186 | |
| 187 void setReturnValue(v8::Local<v8::Value> ret) | |
| 188 { | |
| 189 ASSERT(!tryCatch.HasCaught()); | |
| 190 Dart_SetReturnValue(args, JsInterop::toDart(ret)); | |
| 191 ASSERT(!tryCatch.HasCaught()); | |
| 192 } | |
| 193 | |
| 194 void setReturnValueInteger(int64_t ret) | |
| 195 { | |
| 196 ASSERT(!tryCatch.HasCaught()); | |
| 197 Dart_SetIntegerReturnValue(args, ret); | |
| 198 } | |
| 199 }; | |
| 200 | |
| 201 PassRefPtr<JsObject> JsObject::create(v8::Local<v8::Object> v8Handle) | |
| 202 { | |
| 203 return adoptRef(new JsObject(v8Handle)); | |
| 204 } | |
| 205 | |
| 206 v8::Local<v8::Value> JsInterop::fromDart(DartDOMData* domData, Dart_Handle handl
e, Dart_Handle& exception) | |
| 207 { | |
| 208 v8::Handle<v8::Value> value = V8Converter::toV8IfPrimitive(domData, handle,
exception); | |
| 209 if (!value.IsEmpty() || exception) | |
| 210 return value; | |
| 211 | |
| 212 value = V8Converter::toV8IfBrowserNative(domData, handle, exception); | |
| 213 if (!value.IsEmpty() || exception) | |
| 214 return value; | |
| 215 | |
| 216 if (DartDOMWrapper::subtypeOf(handle, JsObject::dartClassId)) { | |
| 217 JsObject* object = DartDOMWrapper::unwrapDartWrapper<JsObject>(domData,
handle, exception); | |
| 218 if (exception) | |
| 219 return v8::Local<v8::Value>(); | |
| 220 return object->localV8Object(); | |
| 221 } | |
| 222 | |
| 223 if (DartUtilities::isFunction(domData, handle)) { | |
| 224 v8::Local<v8::Object> functionProxy = dartFunctionTemplate()->InstanceTe
mplate()->NewInstance(); | |
| 225 DartHandleProxy::writePointerToProxy(functionProxy, handle); | |
| 226 // The raw functionProxy doesn't behave enough like a true JS function | |
| 227 // so we wrap it in a true JS function. | |
| 228 return domData->jsInteropData()->wrapDartFunction()->Call(functionProxy,
0, 0); | |
| 229 } | |
| 230 | |
| 231 v8::Local<v8::Object> proxy; | |
| 232 ASSERT(Dart_IsInstance(handle)); | |
| 233 proxy = dartObjectTemplate()->InstanceTemplate()->NewInstance(); | |
| 234 DartHandleProxy::writePointerToProxy(proxy, handle); | |
| 235 v8::Isolate* v8Isolate = v8::Isolate::GetCurrent(); | |
| 236 proxy->SetHiddenValue(v8::String::NewFromUtf8(v8Isolate, "dartProxy"), v8::B
oolean::New(v8Isolate, true)); | |
| 237 | |
| 238 return proxy; | |
| 239 } | |
| 240 | |
| 241 JsObject::JsObject(v8::Local<v8::Object> v8Handle) | |
| 242 { | |
| 243 v8::Isolate* isolate = v8::Isolate::GetCurrent(); | |
| 244 v8::Persistent<v8::Object> persistentHandle; | |
| 245 v8Object.Reset(isolate, v8Handle); | |
| 246 } | |
| 247 | |
| 248 v8::Local<v8::Object> JsObject::localV8Object() | |
| 249 { | |
| 250 return v8::Local<v8::Object>::New(v8::Isolate::GetCurrent(), v8Object); | |
| 251 } | |
| 252 | |
| 253 Dart_Handle JsInterop::toDart(v8::Local<v8::Value> v8Handle) | |
| 254 { | |
| 255 Dart_Handle handle = V8Converter::toDartIfPrimitive(v8Handle); | |
| 256 if (handle) | |
| 257 return handle; | |
| 258 | |
| 259 ASSERT(v8Handle->IsObject()); | |
| 260 v8::Handle<v8::Object> object = v8Handle.As<v8::Object>(); | |
| 261 Dart_Handle exception = 0; | |
| 262 handle = V8Converter::toDartIfBrowserNative(object, object->CreationContext(
)->GetIsolate(), exception); | |
| 263 ASSERT(!exception); | |
| 264 if (handle) | |
| 265 return handle; | |
| 266 | |
| 267 // Unwrap objects passed from Dart to JS that are being passed back to | |
| 268 // Dart. FIXME: we do not yet handle unwrapping JS functions passed | |
| 269 // from Dart to JS as we have to wrap them with true JS Function objects. | |
| 270 // If this use case is important we can support it at the cost of hanging | |
| 271 // an extra expando off the JS function wrapping the Dart function. | |
| 272 if (DartHandleProxy::isDartProxy(v8Handle)) { | |
| 273 DartPersistentValue* scriptValue = DartHandleProxy::readPointerFromProxy
(v8Handle); | |
| 274 ASSERT(scriptValue->isIsolateAlive()); | |
| 275 return scriptValue->value(); | |
| 276 } | |
| 277 | |
| 278 return JsObject::toDart(object); | |
| 279 } | |
| 280 | |
| 281 Dart_Handle JsObject::toDart(v8::Local<v8::Object> object) | |
| 282 { | |
| 283 // FIXME: perform caching so that === can be used. | |
| 284 if (object->IsFunction()) { | |
| 285 RefPtr<JsFunction> jsFunction = JsFunction::create(object.As<v8::Functio
n>()); | |
| 286 return JsFunction::toDart(jsFunction); | |
| 287 } | |
| 288 | |
| 289 if (object->IsArray()) { | |
| 290 RefPtr<JsArray> jsArray = JsArray::create(object.As<v8::Array>()); | |
| 291 return JsArray::toDart(jsArray); | |
| 292 } | |
| 293 | |
| 294 RefPtr<JsObject> jsObject = JsObject::create(object); | |
| 295 return JsObject::toDart(jsObject); | |
| 296 } | |
| 297 | |
| 298 Dart_Handle JsObject::toDart(PassRefPtr<JsObject> jsObject) | |
| 299 { | |
| 300 return DartDOMWrapper::createWrapper<JsObject>(DartDOMData::current(), jsObj
ect.get(), JsObject::dartClassId); | |
| 301 } | |
| 302 | |
| 303 JsObject::~JsObject() | |
| 304 { | |
| 305 v8Object.Reset(); | |
| 306 } | |
| 307 | |
| 308 Dart_Handle JsFunction::toDart(PassRefPtr<JsFunction> jsFunction) | |
| 309 { | |
| 310 return DartDOMWrapper::createWrapper<JsFunction>(DartDOMData::current(), jsF
unction.get(), JsFunction::dartClassId); | |
| 311 } | |
| 312 | |
| 313 JsFunction::JsFunction(v8::Local<v8::Function> v8Handle) : JsObject(v8Handle) {
} | |
| 314 | |
| 315 PassRefPtr<JsFunction> JsFunction::create(v8::Local<v8::Function> v8Handle) | |
| 316 { | |
| 317 return adoptRef(new JsFunction(v8Handle)); | |
| 318 } | |
| 319 | |
| 320 v8::Local<v8::Function> JsFunction::localV8Function() | |
| 321 { | |
| 322 return localV8Object().As<v8::Function>(); | |
| 323 } | |
| 324 | |
| 325 Dart_Handle JsArray::toDart(PassRefPtr<JsArray> jsArray) | |
| 326 { | |
| 327 return DartDOMWrapper::createWrapper<JsArray>(DartDOMData::current(), jsArra
y.get(), JsArray::dartClassId); | |
| 328 } | |
| 329 | |
| 330 JsArray::JsArray(v8::Local<v8::Array> v8Handle) : JsObject(v8Handle) { } | |
| 331 | |
| 332 PassRefPtr<JsArray> JsArray::create(v8::Local<v8::Array> v8Handle) | |
| 333 { | |
| 334 return adoptRef(new JsArray(v8Handle)); | |
| 335 } | |
| 336 | |
| 337 v8::Local<v8::Array> JsArray::localV8Array() | |
| 338 { | |
| 339 return localV8Object().As<v8::Array>(); | |
| 340 } | |
| 341 | |
| 342 namespace JsInteropInternal { | |
| 343 | |
| 344 typedef HashMap<Dart_Handle, v8::Handle<v8::Value> > DartHandleToV8Map; | |
| 345 v8::Handle<v8::Value> jsifyHelper(DartDOMData*, Dart_Handle value, DartHandleToV
8Map&, Dart_Handle& exception); | |
| 346 | |
| 347 void argsListToV8(DartDOMData* domData, Dart_Handle args, Vector<v8::Local<v8::V
alue> >* v8Args, Dart_Handle& exception) | |
| 348 { | |
| 349 if (Dart_IsNull(args)) | |
| 350 return; | |
| 351 | |
| 352 if (!Dart_IsList(args)) { | |
| 353 exception = Dart_NewStringFromCString("args not type list"); | |
| 354 return; | |
| 355 } | |
| 356 | |
| 357 intptr_t argsLength = 0; | |
| 358 Dart_ListLength(args, &argsLength); | |
| 359 for (intptr_t i = 0; i < argsLength; i++) { | |
| 360 v8Args->append(JsInterop::fromDart(domData, Dart_ListGetAt(args, i), exc
eption)); | |
| 361 if (exception) | |
| 362 return; | |
| 363 } | |
| 364 } | |
| 365 | |
| 366 void argsListToV8DebuggerOnly(DartDOMData* domData, Dart_Handle args, Vector<v8:
:Local<v8::Value> >* v8Args, Dart_Handle& exception) | |
| 367 { | |
| 368 if (Dart_IsNull(args)) | |
| 369 return; | |
| 370 | |
| 371 if (!Dart_IsList(args)) { | |
| 372 exception = Dart_NewStringFromCString("args not type list"); | |
| 373 return; | |
| 374 } | |
| 375 | |
| 376 intptr_t argsLength = 0; | |
| 377 Dart_ListLength(args, &argsLength); | |
| 378 for (intptr_t i = 0; i < argsLength; i++) { | |
| 379 v8Args->append(DartHandleProxy::create(Dart_ListGetAt(args, i))); | |
| 380 } | |
| 381 } | |
| 382 | |
| 383 static void jsObjectConstructorCallback(Dart_NativeArguments args) | |
| 384 { | |
| 385 Dart_Handle exception = 0; | |
| 386 { | |
| 387 JsInteropScopes scopes(args); | |
| 388 DartDOMData* domData = static_cast<DartDOMData*>(Dart_GetNativeIsolateDa
ta(args)); | |
| 389 v8::Local<v8::Value> constructorArg = JsInterop::fromDart(domData, Dart_
GetNativeArgument(args, 0), exception); | |
| 390 if (exception) | |
| 391 goto fail; | |
| 392 | |
| 393 if (!constructorArg->IsFunction()) { | |
| 394 exception = Dart_NewStringFromCString("constructor not a function"); | |
| 395 goto fail; | |
| 396 } | |
| 397 | |
| 398 Vector<v8::Local<v8::Value> > v8Args; | |
| 399 argsListToV8(domData, Dart_GetNativeArgument(args, 1), &v8Args, exceptio
n); | |
| 400 | |
| 401 v8::Local<v8::Value> ret = constructorArg.As<v8::Function>()->CallAsCons
tructor(v8Args.size(), v8Args.data()); | |
| 402 crashIfV8IsDead(); | |
| 403 | |
| 404 if (scopes.handleJsException(&exception)) | |
| 405 goto fail; | |
| 406 | |
| 407 // Intentionally skip auto-conversion in this case as the user expects | |
| 408 // a JSObject. FIXME: evaluate if this is the right solution. | |
| 409 // Alternately, we could throw an exception. | |
| 410 if (ret->IsObject()) { | |
| 411 scopes.setReturnValue(JsObject::toDart(ret.As<v8::Object>())); | |
| 412 } else { | |
| 413 // This will throw an exception in Dart checked mode. | |
| 414 scopes.setReturnValue(ret); | |
| 415 } | |
| 416 return; | |
| 417 } | |
| 418 | |
| 419 fail: | |
| 420 Dart_ThrowException(exception); | |
| 421 ASSERT_NOT_REACHED(); | |
| 422 } | |
| 423 | |
| 424 static void identityEqualityCallback(Dart_NativeArguments args) | |
| 425 { | |
| 426 Dart_Handle exception = 0; | |
| 427 { | |
| 428 JsInteropScopes scopes(args); | |
| 429 DartDOMData* domData = static_cast<DartDOMData*>(Dart_GetNativeIsolateDa
ta(args)); | |
| 430 v8::Local<v8::Value> a = JsInterop::fromDart(domData, Dart_GetNativeArgu
ment(args, 0), exception); | |
| 431 if (exception) | |
| 432 goto fail; | |
| 433 v8::Local<v8::Value> b = JsInterop::fromDart(domData, Dart_GetNativeArgu
ment(args, 1), exception); | |
| 434 if (exception) | |
| 435 goto fail; | |
| 436 | |
| 437 bool strictEquals = a->StrictEquals(b); | |
| 438 | |
| 439 if (scopes.handleJsException(&exception)) | |
| 440 goto fail; | |
| 441 scopes.setReturnValue(DartUtilities::boolToDart(strictEquals)); | |
| 442 return; | |
| 443 } | |
| 444 | |
| 445 fail: | |
| 446 Dart_ThrowException(exception); | |
| 447 ASSERT_NOT_REACHED(); | |
| 448 } | |
| 449 | |
| 450 static void getterCallback(Dart_NativeArguments args) | |
| 451 { | |
| 452 Dart_Handle exception = 0; | |
| 453 { | |
| 454 JsInteropScopes scopes(args); | |
| 455 JsObject* receiver = DartDOMWrapper::receiver<JsObject>(args); | |
| 456 v8::Local<v8::Object> v8Receiver = receiver->localV8Object(); | |
| 457 Dart_Handle index = Dart_GetNativeArgument(args, 1); | |
| 458 uint64_t intIndex = 0; | |
| 459 v8::Local<v8::Value> ret; | |
| 460 | |
| 461 if (Dart_IsInteger(index)) { | |
| 462 bool isUint64 = false; | |
| 463 Dart_IntegerFitsIntoUint64(index, &isUint64); | |
| 464 if (isUint64) { | |
| 465 Dart_Handle ALLOW_UNUSED result = Dart_IntegerToUint64(index, &i
ntIndex); | |
| 466 if (intIndex <= std::numeric_limits<uint32_t>::max()) { | |
| 467 ASSERT(!Dart_IsError(result)); | |
| 468 ret = v8Receiver->Get((uint32_t)intIndex); | |
| 469 } else { | |
| 470 ret = v8Receiver->Get(V8Converter::numberToV8(index)); | |
| 471 } | |
| 472 } else { | |
| 473 ret = v8Receiver->Get(V8Converter::numberToV8(index)); | |
| 474 } | |
| 475 } else if (Dart_IsString(index)) { | |
| 476 ret = v8Receiver->Get(V8Converter::stringToV8(index)); | |
| 477 } else if (Dart_IsNumber(index)) { | |
| 478 ret = v8Receiver->Get(V8Converter::numberToV8(index)); | |
| 479 } else { | |
| 480 ret = v8Receiver->Get(V8Converter::stringToV8(Dart_ToString(index)))
; | |
| 481 } | |
| 482 | |
| 483 if (scopes.handleJsException(&exception)) | |
| 484 goto fail; | |
| 485 scopes.setReturnValue(ret); | |
| 486 return; | |
| 487 } | |
| 488 | |
| 489 fail: | |
| 490 Dart_ThrowException(exception); | |
| 491 ASSERT_NOT_REACHED(); | |
| 492 } | |
| 493 | |
| 494 static void hasPropertyCallback(Dart_NativeArguments args) | |
| 495 { | |
| 496 Dart_Handle exception = 0; | |
| 497 { | |
| 498 JsInteropScopes scopes(args); | |
| 499 JsObject* receiver = DartDOMWrapper::receiver<JsObject>(args); | |
| 500 v8::Local<v8::Object> v8Receiver = receiver->localV8Object(); | |
| 501 Dart_Handle property = Dart_GetNativeArgument(args, 1); | |
| 502 | |
| 503 if (!Dart_IsString(property)) | |
| 504 property = Dart_ToString(property); | |
| 505 | |
| 506 bool hasProperty = v8Receiver->Has(V8Converter::stringToV8(property)); | |
| 507 if (scopes.handleJsException(&exception)) | |
| 508 goto fail; | |
| 509 scopes.setReturnValue(DartUtilities::boolToDart(hasProperty)); | |
| 510 return; | |
| 511 } | |
| 512 | |
| 513 fail: | |
| 514 Dart_ThrowException(exception); | |
| 515 ASSERT_NOT_REACHED(); | |
| 516 } | |
| 517 | |
| 518 static void deletePropertyCallback(Dart_NativeArguments args) | |
| 519 { | |
| 520 Dart_Handle exception = 0; | |
| 521 { | |
| 522 JsInteropScopes scopes(args); | |
| 523 JsObject* receiver = DartDOMWrapper::receiver<JsObject>(args); | |
| 524 v8::Local<v8::Object> v8Receiver = receiver->localV8Object(); | |
| 525 Dart_Handle property = Dart_GetNativeArgument(args, 1); | |
| 526 if (!Dart_IsString(property)) | |
| 527 property = Dart_ToString(property); | |
| 528 | |
| 529 v8Receiver->Delete(V8Converter::stringToV8(property)); | |
| 530 if (scopes.handleJsException(&exception)) | |
| 531 goto fail; | |
| 532 return; | |
| 533 } | |
| 534 | |
| 535 fail: | |
| 536 Dart_ThrowException(exception); | |
| 537 ASSERT_NOT_REACHED(); | |
| 538 } | |
| 539 | |
| 540 static void instanceofCallback(Dart_NativeArguments args) | |
| 541 { | |
| 542 Dart_Handle exception = 0; | |
| 543 { | |
| 544 JsInteropScopes scopes(args); | |
| 545 DartDOMData* domData = static_cast<DartDOMData*>(Dart_GetNativeIsolateDa
ta(args)); | |
| 546 JsObject* receiver = DartDOMWrapper::receiver<JsObject>(args); | |
| 547 v8::Local<v8::Object> v8Receiver = receiver->localV8Object(); | |
| 548 v8::Local<v8::Value> type = JsInterop::fromDart(domData, Dart_GetNativeA
rgument(args, 1), exception); | |
| 549 | |
| 550 // FIXME: we could optimize the following lines slightly as the return | |
| 551 // type is bool. | |
| 552 v8::Local<v8::Value> ret = domData->jsInteropData()->instanceofFunction(
)->Call(v8Receiver, 1, &type); | |
| 553 if (scopes.handleJsException(&exception)) | |
| 554 goto fail; | |
| 555 scopes.setReturnValue(ret); | |
| 556 return; | |
| 557 } | |
| 558 | |
| 559 fail: | |
| 560 Dart_ThrowException(exception); | |
| 561 ASSERT_NOT_REACHED(); | |
| 562 } | |
| 563 | |
| 564 static void setterCallback(Dart_NativeArguments args) | |
| 565 { | |
| 566 Dart_Handle exception = 0; | |
| 567 { | |
| 568 JsInteropScopes scopes(args); | |
| 569 DartDOMData* domData = static_cast<DartDOMData*>(Dart_GetNativeIsolateDa
ta(args)); | |
| 570 JsObject* receiver = DartDOMWrapper::receiver<JsObject>(args); | |
| 571 v8::Local<v8::Object> v8Receiver = receiver->localV8Object(); | |
| 572 Dart_Handle index = Dart_GetNativeArgument(args, 1); | |
| 573 v8::Local<v8::Value> value = JsInterop::fromDart(domData, Dart_GetNative
Argument(args, 2), exception); | |
| 574 if (exception) | |
| 575 goto fail; | |
| 576 uint64_t intIndex = 0; | |
| 577 bool ret = false; | |
| 578 if (Dart_IsInteger(index)) { | |
| 579 bool isUint64 = false; | |
| 580 Dart_IntegerFitsIntoUint64(index, &isUint64); | |
| 581 if (isUint64) { | |
| 582 Dart_Handle ALLOW_UNUSED result = Dart_IntegerToUint64(index, &i
ntIndex); | |
| 583 if (intIndex <= std::numeric_limits<uint32_t>::max()) { | |
| 584 ASSERT(!Dart_IsError(result)); | |
| 585 ret = v8Receiver->Set((uint32_t)intIndex, value); | |
| 586 } else { | |
| 587 ret = v8Receiver->Set(V8Converter::numberToV8(index), value)
; | |
| 588 } | |
| 589 } else { | |
| 590 ret = v8Receiver->Set(V8Converter::numberToV8(index), value); | |
| 591 } | |
| 592 } else if (Dart_IsString(index)) { | |
| 593 ret = v8Receiver->Set(V8Converter::stringToV8(index), value); | |
| 594 } else if (Dart_IsNumber(index)) { | |
| 595 ret = v8Receiver->Set(V8Converter::numberToV8(index), value); | |
| 596 } else { | |
| 597 ret = v8Receiver->Set(V8Converter::stringToV8(Dart_ToString(index)),
value); | |
| 598 } | |
| 599 | |
| 600 if (scopes.handleJsException(&exception)) | |
| 601 goto fail; | |
| 602 scopes.setReturnValue(DartUtilities::boolToDart(ret)); | |
| 603 return; | |
| 604 } | |
| 605 | |
| 606 fail: | |
| 607 Dart_ThrowException(exception); | |
| 608 ASSERT_NOT_REACHED(); | |
| 609 } | |
| 610 | |
| 611 static void hashCodeCallback(Dart_NativeArguments args) | |
| 612 { | |
| 613 Dart_Handle exception = 0; | |
| 614 { | |
| 615 JsInteropScopes scopes(args); | |
| 616 JsObject* receiver = DartDOMWrapper::receiver<JsObject>(args); | |
| 617 int hashCode = receiver->localV8Object()->GetIdentityHash(); | |
| 618 // FIXME: salt the v8 hashcode so we don't leak information about v8 | |
| 619 // memory allocation. | |
| 620 if (scopes.handleJsException(&exception)) | |
| 621 goto fail; | |
| 622 scopes.setReturnValueInteger(hashCode); | |
| 623 return; | |
| 624 } | |
| 625 | |
| 626 fail: | |
| 627 Dart_ThrowException(exception); | |
| 628 ASSERT_NOT_REACHED(); | |
| 629 } | |
| 630 | |
| 631 static void callMethodCallback(Dart_NativeArguments args) | |
| 632 { | |
| 633 Dart_Handle exception = 0; | |
| 634 { | |
| 635 JsInteropScopes scopes(args); | |
| 636 DartDOMData* domData = static_cast<DartDOMData*>(Dart_GetNativeIsolateDa
ta(args)); | |
| 637 JsObject* receiver = DartDOMWrapper::receiver<JsObject>(args); | |
| 638 v8::Local<v8::Object> v8Receiver = receiver->localV8Object(); | |
| 639 | |
| 640 Dart_Handle name = Dart_GetNativeArgument(args, 1); | |
| 641 Vector<v8::Local<v8::Value> > v8Args; | |
| 642 argsListToV8(domData, Dart_GetNativeArgument(args, 2), &v8Args, exceptio
n); | |
| 643 if (exception) | |
| 644 goto fail; | |
| 645 if (!Dart_IsString(name)) | |
| 646 name = Dart_ToString(name); | |
| 647 | |
| 648 v8::Local<v8::Value> value = v8Receiver->Get(V8Converter::stringToV8(nam
e)); | |
| 649 v8::Local<v8::Value> ret; | |
| 650 if (value->IsFunction()) { | |
| 651 ret = V8ScriptRunner::callFunction(value.As<v8::Function>(), DartUti
lities::scriptExecutionContext(), receiver->localV8Object(), v8Args.size(), v8Ar
gs.data(), v8::Isolate::GetCurrent()); | |
| 652 } else if (value->IsObject()) { | |
| 653 ret = V8ScriptRunner::callAsFunction(v8::Isolate::GetCurrent(), valu
e.As<v8::Object>(), receiver->localV8Object(), v8Args.size(), v8Args.data()); | |
| 654 } else { | |
| 655 // FIXME: we currently convert this exception to a NoSuchMethod | |
| 656 // exception in the Dart code that wraps this native method. | |
| 657 // Consider throwing a NoSuchMethod exception directly instead. | |
| 658 exception = Dart_NewStringFromCString("property is not a function"); | |
| 659 goto fail; | |
| 660 } | |
| 661 | |
| 662 if (scopes.handleJsException(&exception)) | |
| 663 goto fail; | |
| 664 scopes.setReturnValue(ret); | |
| 665 return; | |
| 666 } | |
| 667 | |
| 668 fail: | |
| 669 Dart_ThrowException(exception); | |
| 670 ASSERT_NOT_REACHED(); | |
| 671 } | |
| 672 | |
| 673 static void newJsArrayCallback(Dart_NativeArguments args) | |
| 674 { | |
| 675 JsInteropScopes scopes(args); | |
| 676 scopes.setReturnValue(JsObject::toDart(v8::Array::New(v8::Isolate::GetCurren
t()))); | |
| 677 return; | |
| 678 } | |
| 679 | |
| 680 static void newJsArrayFromSafeListCallback(Dart_NativeArguments args) | |
| 681 { | |
| 682 Dart_Handle exception = 0; | |
| 683 { | |
| 684 JsInteropScopes scopes(args); | |
| 685 DartDOMData* domData = static_cast<DartDOMData*>(Dart_GetNativeIsolateDa
ta(args)); | |
| 686 Dart_Handle list = Dart_GetNativeArgument(args, 0); | |
| 687 // Code on the Dart side insures this arg is a native Dart list. | |
| 688 ASSERT(Dart_IsList(list)); | |
| 689 | |
| 690 intptr_t length = 0; | |
| 691 Dart_Handle result = Dart_ListLength(list, &length); | |
| 692 ASSERT(!Dart_IsError(result)); | |
| 693 v8::Local<v8::Array> array = v8::Array::New(v8::Isolate::GetCurrent(), l
ength); | |
| 694 | |
| 695 for (intptr_t i = 0; i < length; ++i) { | |
| 696 result = Dart_ListGetAt(list, i); | |
| 697 ASSERT(!Dart_IsError(result)); | |
| 698 v8::Handle<v8::Value> v8value = JsInterop::fromDart(domData, result,
exception); | |
| 699 if (exception) | |
| 700 goto fail; | |
| 701 | |
| 702 array->Set(i, v8value); | |
| 703 } | |
| 704 scopes.setReturnValue(array); | |
| 705 return; | |
| 706 } | |
| 707 | |
| 708 fail: | |
| 709 Dart_ThrowException(exception); | |
| 710 ASSERT_NOT_REACHED(); | |
| 711 } | |
| 712 | |
| 713 | |
| 714 static void jsArrayLengthCallback(Dart_NativeArguments args) | |
| 715 { | |
| 716 Dart_Handle exception = 0; | |
| 717 { | |
| 718 JsInteropScopes scopes(args); | |
| 719 JsArray* receiver = DartDOMWrapper::receiver<JsArray>(args); | |
| 720 uint32_t length = receiver->localV8Array()->Length(); | |
| 721 if (scopes.handleJsException(&exception)) | |
| 722 goto fail; | |
| 723 scopes.setReturnValueInteger(length); | |
| 724 return; | |
| 725 } | |
| 726 | |
| 727 fail: | |
| 728 Dart_ThrowException(exception); | |
| 729 ASSERT_NOT_REACHED(); | |
| 730 } | |
| 731 | |
| 732 static void fromBrowserObjectCallback(Dart_NativeArguments args) | |
| 733 { | |
| 734 Dart_Handle exception = 0; | |
| 735 { | |
| 736 JsInteropScopes scopes(args); | |
| 737 DartDOMData* domData = static_cast<DartDOMData*>(Dart_GetNativeIsolateDa
ta(args)); | |
| 738 | |
| 739 v8::Local<v8::Value> ret = V8Converter::toV8IfBrowserNative(domData, Dar
t_GetNativeArgument(args, 0), exception); | |
| 740 if (ret.IsEmpty()) { | |
| 741 exception = Dart_NewStringFromCString("object must be an Node, Array
Buffer, Blob, ImageData, or IDBKeyRange"); | |
| 742 goto fail; | |
| 743 } | |
| 744 if (exception) | |
| 745 goto fail; | |
| 746 ASSERT(ret->IsObject()); | |
| 747 if (scopes.handleJsException(&exception)) | |
| 748 goto fail; | |
| 749 scopes.setReturnValue(JsObject::toDart(ret.As<v8::Object>())); | |
| 750 return; | |
| 751 } | |
| 752 | |
| 753 fail: | |
| 754 Dart_ThrowException(exception); | |
| 755 ASSERT_NOT_REACHED(); | |
| 756 } | |
| 757 | |
| 758 static void applyCallback(Dart_NativeArguments args) | |
| 759 { | |
| 760 Dart_Handle exception = 0; | |
| 761 { | |
| 762 JsInteropScopes scopes(args); | |
| 763 DartDOMData* domData = static_cast<DartDOMData*>(Dart_GetNativeIsolateDa
ta(args)); | |
| 764 JsFunction* receiver = DartDOMWrapper::receiver<JsFunction>(args); | |
| 765 | |
| 766 Vector<v8::Local<v8::Value> > v8Args; | |
| 767 argsListToV8(domData, Dart_GetNativeArgument(args, 1), &v8Args, exceptio
n); | |
| 768 if (exception) | |
| 769 goto fail; | |
| 770 | |
| 771 v8::Local<v8::Value> thisArg; | |
| 772 Dart_Handle thisArgDart = Dart_GetNativeArgument(args, 2); | |
| 773 if (Dart_IsNull(thisArgDart)) { | |
| 774 // Use the global v8 object if no Dart thisArg was passed in. | |
| 775 thisArg = DartUtilities::currentV8Context()->Global(); | |
| 776 } else { | |
| 777 thisArg = JsInterop::fromDart(domData, thisArgDart, exception); | |
| 778 if (exception) | |
| 779 goto fail; | |
| 780 if (!thisArg->IsObject()) { | |
| 781 exception = Dart_NewStringFromCString("thisArg is not an object"
); | |
| 782 goto fail; | |
| 783 } | |
| 784 } | |
| 785 | |
| 786 v8::Local<v8::Value> ret = V8ScriptRunner::callFunction(receiver->localV
8Function(), DartUtilities::scriptExecutionContext(), thisArg.As<v8::Object>(),
v8Args.size(), v8Args.data(), v8::Isolate::GetCurrent()); | |
| 787 if (scopes.handleJsException(&exception)) | |
| 788 goto fail; | |
| 789 scopes.setReturnValue(ret); | |
| 790 return; | |
| 791 } | |
| 792 | |
| 793 fail: | |
| 794 Dart_ThrowException(exception); | |
| 795 ASSERT_NOT_REACHED(); | |
| 796 } | |
| 797 | |
| 798 static void applyDebuggerOnlyCallback(Dart_NativeArguments args) | |
| 799 { | |
| 800 Dart_Handle exception = 0; | |
| 801 { | |
| 802 JsInteropScopes scopes(args); | |
| 803 DartDOMData* domData = static_cast<DartDOMData*>(Dart_GetNativeIsolateDa
ta(args)); | |
| 804 JsFunction* receiver = DartDOMWrapper::receiver<JsFunction>(args); | |
| 805 | |
| 806 Vector<v8::Local<v8::Value> > v8Args; | |
| 807 argsListToV8DebuggerOnly(domData, Dart_GetNativeArgument(args, 1), &v8Ar
gs, exception); | |
| 808 if (exception) | |
| 809 goto fail; | |
| 810 | |
| 811 v8::Local<v8::Value> thisArg; | |
| 812 Dart_Handle thisArgDart = Dart_GetNativeArgument(args, 2); | |
| 813 if (Dart_IsNull(thisArgDart)) { | |
| 814 // Use the global v8 object if no Dart thisArg was passed in. | |
| 815 thisArg = DartUtilities::currentV8Context()->Global(); | |
| 816 } else { | |
| 817 thisArg = JsInterop::fromDart(domData, thisArgDart, exception); | |
| 818 if (exception) | |
| 819 goto fail; | |
| 820 if (!thisArg->IsObject()) { | |
| 821 exception = Dart_NewStringFromCString("thisArg is not an object"
); | |
| 822 goto fail; | |
| 823 } | |
| 824 } | |
| 825 | |
| 826 v8::Local<v8::Value> ret = V8ScriptRunner::callFunction(receiver->localV
8Function(), DartUtilities::scriptExecutionContext(), thisArg.As<v8::Object>(),
v8Args.size(), v8Args.data(), v8::Isolate::GetCurrent()); | |
| 827 if (scopes.handleJsException(&exception)) | |
| 828 goto fail; | |
| 829 scopes.setReturnValue(ret); | |
| 830 return; | |
| 831 } | |
| 832 | |
| 833 fail: | |
| 834 Dart_ThrowException(exception); | |
| 835 ASSERT_NOT_REACHED(); | |
| 836 } | |
| 837 | |
| 838 static void toStringCallback(Dart_NativeArguments args) | |
| 839 { | |
| 840 Dart_Handle exception = 0; | |
| 841 { | |
| 842 JsInteropScopes scopes(args); | |
| 843 JsObject* receiver = DartDOMWrapper::receiver<JsObject>(args); | |
| 844 v8::Local<v8::Object> v8Object = receiver->localV8Object(); | |
| 845 if (scopes.handleJsException(&exception)) | |
| 846 goto fail; | |
| 847 if (v8Object.IsEmpty()) { | |
| 848 exception = Dart_NewStringFromCString("Invalid v8 handle"); | |
| 849 goto fail; | |
| 850 } | |
| 851 | |
| 852 v8::Local<v8::String> v8String = v8Object->ToString(); | |
| 853 if (scopes.handleJsException(&exception)) | |
| 854 goto fail; | |
| 855 scopes.setReturnValue(v8String); | |
| 856 return; | |
| 857 } | |
| 858 fail: | |
| 859 Dart_ThrowException(exception); | |
| 860 ASSERT_NOT_REACHED(); | |
| 861 } | |
| 862 | |
| 863 static void contextCallback(Dart_NativeArguments args) | |
| 864 { | |
| 865 v8::Local<v8::Context> v8Context = DartUtilities::currentV8Context(); | |
| 866 v8::Context::Scope scope(v8Context); | |
| 867 Dart_SetReturnValue(args, JsObject::toDart(v8Context->Global())); | |
| 868 } | |
| 869 | |
| 870 v8::Handle<v8::Value> mapToV8(DartDOMData* domData, Dart_Handle value, DartHandl
eToV8Map& map, Dart_Handle& exception) | |
| 871 { | |
| 872 Dart_Handle asList = DartUtilities::invokeUtilsMethod("convertMapToList", 1,
&value); | |
| 873 if (!DartUtilities::checkResult(asList, exception)) | |
| 874 return v8::Handle<v8::Value>(); | |
| 875 ASSERT(Dart_IsList(asList)); | |
| 876 | |
| 877 // Now we have a list [key, value, key, value, ....], create a v8 object and
set necesary | |
| 878 // properties on it. | |
| 879 v8::Handle<v8::Object> object = v8::Object::New(v8::Isolate::GetCurrent()); | |
| 880 map.set(value, object); | |
| 881 | |
| 882 // We converted to internal Dart list, methods shouldn't throw exceptions no
w. | |
| 883 intptr_t length = 0; | |
| 884 Dart_Handle ALLOW_UNUSED result = Dart_ListLength(asList, &length); | |
| 885 ASSERT(!Dart_IsError(result)); | |
| 886 ASSERT(!(length % 2)); | |
| 887 for (intptr_t i = 0; i < length; i += 2) { | |
| 888 v8::Handle<v8::Value> key = jsifyHelper(domData, Dart_ListGetAt(asList,
i), map, exception); | |
| 889 if (exception) | |
| 890 return v8::Handle<v8::Value>(); | |
| 891 v8::Handle<v8::Value> value = jsifyHelper(domData, Dart_ListGetAt(asList
, i + 1), map, exception); | |
| 892 if (exception) | |
| 893 return v8::Handle<v8::Value>(); | |
| 894 | |
| 895 object->Set(key, value); | |
| 896 } | |
| 897 | |
| 898 return object; | |
| 899 } | |
| 900 | |
| 901 v8::Handle<v8::Value> listToV8(DartDOMData* domData, Dart_Handle value, DartHand
leToV8Map& map, Dart_Handle& exception) | |
| 902 { | |
| 903 ASSERT(Dart_IsList(value)); | |
| 904 | |
| 905 intptr_t length = 0; | |
| 906 Dart_Handle result = Dart_ListLength(value, &length); | |
| 907 if (!DartUtilities::checkResult(result, exception)) | |
| 908 return v8::Handle<v8::Value>(); | |
| 909 | |
| 910 v8::Local<v8::Array> array = v8::Array::New(v8::Isolate::GetCurrent(), lengt
h); | |
| 911 map.set(value, array); | |
| 912 | |
| 913 for (intptr_t i = 0; i < length; ++i) { | |
| 914 result = Dart_ListGetAt(value, i); | |
| 915 if (!DartUtilities::checkResult(result, exception)) | |
| 916 return v8::Handle<v8::Value>(); | |
| 917 v8::Handle<v8::Value> v8value = jsifyHelper(domData, result, map, except
ion); | |
| 918 if (exception) | |
| 919 return v8::Handle<v8::Value>(); | |
| 920 array->Set(i, v8value); | |
| 921 } | |
| 922 | |
| 923 return array; | |
| 924 } | |
| 925 | |
| 926 v8::Handle<v8::Value> jsifyHelper(DartDOMData* domData, Dart_Handle value, DartH
andleToV8Map& map, Dart_Handle& exception) | |
| 927 { | |
| 928 DartHandleToV8Map::iterator iter = map.find(value); | |
| 929 if (iter != map.end()) | |
| 930 return iter->value; | |
| 931 | |
| 932 if (Dart_IsList(value)) | |
| 933 return listToV8(domData, value, map, exception); | |
| 934 | |
| 935 bool isMap = DartUtilities::dartToBool(DartUtilities::invokeUtilsMethod("isM
ap", 1, &value), exception); | |
| 936 ASSERT(!exception); | |
| 937 if (isMap) | |
| 938 return mapToV8(domData, value, map, exception); | |
| 939 | |
| 940 Dart_Handle maybeList = DartUtilities::invokeUtilsMethod("toListIfIterable",
1, &value); | |
| 941 if (Dart_IsList(maybeList)) | |
| 942 return listToV8(domData, maybeList, map, exception); | |
| 943 | |
| 944 v8::Handle<v8::Value> ret = JsInterop::fromDart(domData, value, exception); | |
| 945 map.set(value, ret); | |
| 946 return ret; | |
| 947 } | |
| 948 | |
| 949 static void jsifyCallback(Dart_NativeArguments args) | |
| 950 { | |
| 951 Dart_Handle exception = 0; | |
| 952 { | |
| 953 JsInteropScopes scopes(args); | |
| 954 Dart_Handle value = Dart_GetNativeArgument(args, 0); | |
| 955 DartDOMData* domData = static_cast<DartDOMData*>(Dart_GetNativeIsolateDa
ta(args)); | |
| 956 DartHandleToV8Map map; | |
| 957 v8::Local<v8::Value> ret = jsifyHelper(domData, value, map, exception); | |
| 958 if (exception) | |
| 959 goto fail; | |
| 960 | |
| 961 if (scopes.handleJsException(&exception)) | |
| 962 goto fail; | |
| 963 // Intentionally skip auto-conversion in this case as the user expects | |
| 964 // a JSObject. FIXME: evaluate if this is the right solution. | |
| 965 // Alternately, we could throw an exception. | |
| 966 if (ret->IsObject()) { | |
| 967 scopes.setReturnValue(JsObject::toDart(ret.As<v8::Object>())); | |
| 968 } else { | |
| 969 // This will throw an exception in Dart checked mode. | |
| 970 scopes.setReturnValue(ret); | |
| 971 } | |
| 972 return; | |
| 973 } | |
| 974 fail: | |
| 975 Dart_ThrowException(exception); | |
| 976 ASSERT_NOT_REACHED(); | |
| 977 } | |
| 978 | |
| 979 static void withThisCallback(Dart_NativeArguments args) | |
| 980 { | |
| 981 Dart_Handle exception = 0; | |
| 982 { | |
| 983 JsInteropScopes scopes(args); | |
| 984 Dart_Handle function = Dart_GetNativeArgument(args, 0); | |
| 985 DartDOMData* domData = static_cast<DartDOMData*>(Dart_GetNativeIsolateDa
ta(args)); | |
| 986 ASSERT(DartUtilities::isFunction(domData, function)); | |
| 987 | |
| 988 v8::Local<v8::Object> proxy = dartFunctionTemplate()->InstanceTemplate()
->NewInstance(); | |
| 989 DartHandleProxy::writePointerToProxy(proxy, function); | |
| 990 | |
| 991 v8::Local<v8::Function> ret = v8::Local<v8::Function>::Cast(domData->jsI
nteropData()->captureThisFunction()->Call(proxy, 0, 0)); | |
| 992 | |
| 993 if (scopes.handleJsException(&exception)) | |
| 994 goto fail; | |
| 995 scopes.setReturnValue(ret); | |
| 996 return; | |
| 997 } | |
| 998 fail: | |
| 999 Dart_ThrowException(exception); | |
| 1000 ASSERT_NOT_REACHED(); | |
| 1001 } | |
| 1002 | |
| 1003 } | |
| 1004 | |
| 1005 static DartNativeEntry nativeEntries[] = { | |
| 1006 { JsInteropInternal::jsObjectConstructorCallback, 2, "JsObject_constructorCa
llback" }, | |
| 1007 { JsInteropInternal::contextCallback, 0, "Js_context_Callback" }, | |
| 1008 { JsInteropInternal::jsifyCallback, 1, "JsObject_jsify" }, | |
| 1009 { JsInteropInternal::withThisCallback, 1, "JsFunction_withThis" }, | |
| 1010 { JsInteropInternal::getterCallback, 2, "JsObject_[]" }, | |
| 1011 { JsInteropInternal::setterCallback, 3, "JsObject_[]=" }, | |
| 1012 { JsInteropInternal::hashCodeCallback, 1, "JsObject_hashCode" }, | |
| 1013 { JsInteropInternal::callMethodCallback, 3, "JsObject_callMethod" }, | |
| 1014 { JsInteropInternal::toStringCallback, 1, "JsObject_toString" }, | |
| 1015 { JsInteropInternal::identityEqualityCallback, 2, "JsObject_identityEquality
" }, | |
| 1016 { JsInteropInternal::hasPropertyCallback, 2, "JsObject_hasProperty" }, | |
| 1017 { JsInteropInternal::deletePropertyCallback, 2, "JsObject_deleteProperty" }, | |
| 1018 { JsInteropInternal::instanceofCallback, 2, "JsObject_instanceof" }, | |
| 1019 { JsInteropInternal::applyCallback, 3, "JsFunction_apply" }, | |
| 1020 { JsInteropInternal::applyDebuggerOnlyCallback, 3, "JsFunction_applyDebugger
Only" }, | |
| 1021 { JsInteropInternal::newJsArrayCallback, 0, "JsArray_newJsArray" }, | |
| 1022 { JsInteropInternal::newJsArrayFromSafeListCallback, 1, "JsArray_newJsArrayF
romSafeList" }, | |
| 1023 { JsInteropInternal::jsArrayLengthCallback, 1, "JsArray_length" }, | |
| 1024 { JsInteropInternal::fromBrowserObjectCallback, 1, "JsObject_fromBrowserObje
ct" }, | |
| 1025 { 0, 0, 0 }, | |
| 1026 }; | |
| 1027 | |
| 1028 Dart_NativeFunction JsInterop::resolver(Dart_Handle nameHandle, int argumentCoun
t, bool* autoSetupScope) | |
| 1029 { | |
| 1030 ASSERT(autoSetupScope); | |
| 1031 *autoSetupScope = true; | |
| 1032 String name = DartUtilities::toString(nameHandle); | |
| 1033 | |
| 1034 for (intptr_t i = 0; nativeEntries[i].nativeFunction != 0; i++) { | |
| 1035 if (argumentCount == nativeEntries[i].argumentCount && name == nativeEnt
ries[i].name) { | |
| 1036 return nativeEntries[i].nativeFunction; | |
| 1037 } | |
| 1038 } | |
| 1039 | |
| 1040 return 0; | |
| 1041 } | |
| 1042 | |
| 1043 const uint8_t* JsInterop::symbolizer(Dart_NativeFunction nf) | |
| 1044 { | |
| 1045 for (intptr_t i = 0; nativeEntries[i].nativeFunction != 0; i++) { | |
| 1046 if (nf == nativeEntries[i].nativeFunction) { | |
| 1047 return reinterpret_cast<const uint8_t*>(nativeEntries[i].name); | |
| 1048 } | |
| 1049 } | |
| 1050 return 0; | |
| 1051 } | |
| 1052 | |
| 1053 } | |
| OLD | NEW |