| 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 |