| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (C) 2013 Google Inc. All rights reserved. | 2 * Copyright (C) 2013 Google Inc. All rights reserved. |
| 3 * | 3 * |
| 4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
| 5 * modification, are permitted provided that the following conditions are | 5 * modification, are permitted provided that the following conditions are |
| 6 * met: | 6 * met: |
| 7 * | 7 * |
| 8 * * Redistributions of source code must retain the above copyright | 8 * * Redistributions of source code must retain the above copyright |
| 9 * notice, this list of conditions and the following disclaimer. | 9 * notice, this list of conditions and the following disclaimer. |
| 10 * * Redistributions in binary form must reproduce the above | 10 * * Redistributions in binary form must reproduce the above |
| (...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 140 " else return new blob(makeSafeArg(array), options);" | 140 " else return new blob(makeSafeArg(array), options);" |
| 141 " };" | 141 " };" |
| 142 | 142 |
| 143 // Need to make sure that Array.isArray returns true for Dart lists. | 143 // Need to make sure that Array.isArray returns true for Dart lists. |
| 144 " Array.isArray = function(arr) {" | 144 " Array.isArray = function(arr) {" |
| 145 " return isArray(arr) || (arr instanceof $DartList);" | 145 " return isArray(arr) || (arr instanceof $DartList);" |
| 146 " };" | 146 " };" |
| 147 "})();"; | 147 "})();"; |
| 148 | 148 |
| 149 static v8::Local<v8::FunctionTemplate> dartFunctionTemplate(); | 149 static v8::Local<v8::FunctionTemplate> dartFunctionTemplate(); |
| 150 static v8::Local<v8::FunctionTemplate> dartFunctionTemplateNoWrap(); |
| 150 static v8::Local<v8::FunctionTemplate> dartObjectTemplate(); | 151 static v8::Local<v8::FunctionTemplate> dartObjectTemplate(); |
| 151 static v8::Local<v8::FunctionTemplate> dartListTemplate(); | 152 static v8::Local<v8::FunctionTemplate> dartListTemplate(); |
| 152 | 153 |
| 153 // TODO(jacobr): we should really be using this method everywhere instead of | 154 // TODO(jacobr): we should really be using this method everywhere instead of |
| 154 // sticking interop methods in the dart:html _Utils class. | 155 // sticking interop methods in the dart:html _Utils class. |
| 155 static Dart_Handle invokeTopLevelJsInteropMethod(DartDOMData* domData, const cha
r* methodName, int argCount, Dart_Handle* args) | 156 static Dart_Handle invokeTopLevelJsInteropMethod(DartDOMData* domData, const cha
r* methodName, int argCount, Dart_Handle* args) |
| 156 { | 157 { |
| 157 Dart_PersistentHandle library = domData->jsLibrary(); | 158 Dart_PersistentHandle library = domData->jsLibrary(); |
| 158 ASSERT(!Dart_IsError(library)); | 159 ASSERT(!Dart_IsError(library)); |
| 159 return Dart_Invoke(library, Dart_NewStringFromCString(methodName), argCount,
args); | 160 return Dart_Invoke(library, Dart_NewStringFromCString(methodName), argCount,
args); |
| (...skipping 23 matching lines...) Expand all Loading... |
| 183 DartDOMData* domData = DartDOMData::current(); | 184 DartDOMData* domData = DartDOMData::current(); |
| 184 ASSERT(domData); | 185 ASSERT(domData); |
| 185 ASSERT(DartUtilities::isFunction(domData, handle)); | 186 ASSERT(DartUtilities::isFunction(domData, handle)); |
| 186 | 187 |
| 187 Vector<Dart_Handle> dartFunctionArgs; | 188 Vector<Dart_Handle> dartFunctionArgs; |
| 188 ASSERT(args.Length() == 1 || args.Length() == 2); | 189 ASSERT(args.Length() == 1 || args.Length() == 2); |
| 189 // If there is 1 argument, we assume it is a v8:Array or arguments, if | 190 // If there is 1 argument, we assume it is a v8:Array or arguments, if |
| 190 // there are 2 arguments, the first argument is "this" and the second | 191 // there are 2 arguments, the first argument is "this" and the second |
| 191 // argument is an array of arguments. | 192 // argument is an array of arguments. |
| 192 if (args.Length() > 1) { | 193 if (args.Length() > 1) { |
| 193 dartFunctionArgs.append(JsInterop::toDart(args[0])); | 194 dartFunctionArgs.append(JsInterop::toDart(args[0], true)); |
| 194 } | 195 } |
| 195 | 196 |
| 196 v8::Local<v8::Array> argsList = args[args.Length()-1].As<v8::Array>(); | 197 v8::Local<v8::Array> argsList = args[args.Length()-1].As<v8::Array>(); |
| 197 uint32_t argsListLength = argsList->Length(); | 198 uint32_t argsListLength = argsList->Length(); |
| 198 for (uint32_t i = 0; i < argsListLength; i++) { | 199 for (uint32_t i = 0; i < argsListLength; i++) { |
| 199 dartFunctionArgs.append(JsInterop::toDart(argsList->Get(i))); | 200 dartFunctionArgs.append(JsInterop::toDart(argsList->Get(i), true)); |
| 200 } | 201 } |
| 201 | 202 |
| 202 setJsReturnValue(domData, args, Dart_InvokeClosure(handle, dartFunctionArgs.
size(), dartFunctionArgs.data())); | 203 setJsReturnValue(domData, args, Dart_InvokeClosure(handle, dartFunctionArgs.
size(), dartFunctionArgs.data())); |
| 203 } | 204 } |
| 204 | 205 |
| 206 static void functionInvocationCallbackNoWrap(const v8::FunctionCallbackInfo<v8::
Value>& args) |
| 207 { |
| 208 DartScopes scopes(args.Holder()); |
| 209 Dart_Handle handle = scopes.handle; |
| 210 DartDOMData* domData = DartDOMData::current(); |
| 211 ASSERT(domData); |
| 212 ASSERT(DartUtilities::isFunction(domData, handle)); |
| 213 |
| 214 Vector<Dart_Handle> dartFunctionArgs; |
| 215 ASSERT(args.Length() == 1 || args.Length() == 2); |
| 216 // If there is 1 argument, we assume it is a v8:Array or arguments, if |
| 217 // there are 2 arguments, the first argument is "this" and the second |
| 218 // argument is an array of arguments. |
| 219 if (args.Length() > 1) { |
| 220 dartFunctionArgs.append(JsInterop::toDart(args[0], false)); |
| 221 } |
| 222 |
| 223 v8::Local<v8::Array> argsList = args[args.Length()-1].As<v8::Array>(); |
| 224 uint32_t argsListLength = argsList->Length(); |
| 225 for (uint32_t i = 0; i < argsListLength; i++) { |
| 226 dartFunctionArgs.append(JsInterop::toDart(argsList->Get(i), false)); |
| 227 } |
| 228 |
| 229 setJsReturnValue(domData, args, Dart_InvokeClosure(handle, dartFunctionArgs.
size(), dartFunctionArgs.data())); |
| 230 } |
| 205 static v8::Local<v8::ObjectTemplate> setupInstanceTemplate(v8::Local<v8::Functio
nTemplate> proxyTemplate) | 231 static v8::Local<v8::ObjectTemplate> setupInstanceTemplate(v8::Local<v8::Functio
nTemplate> proxyTemplate) |
| 206 { | 232 { |
| 207 v8::Local<v8::ObjectTemplate> instanceTemplate = proxyTemplate->InstanceTemp
late(); | 233 v8::Local<v8::ObjectTemplate> instanceTemplate = proxyTemplate->InstanceTemp
late(); |
| 208 instanceTemplate->SetInternalFieldCount(1); | 234 instanceTemplate->SetInternalFieldCount(1); |
| 209 return instanceTemplate; | 235 return instanceTemplate; |
| 210 } | 236 } |
| 211 | 237 |
| 238 |
| 212 static v8::Local<v8::FunctionTemplate> dartFunctionTemplate() | 239 static v8::Local<v8::FunctionTemplate> dartFunctionTemplate() |
| 213 { | 240 { |
| 214 DEFINE_STATIC_LOCAL(v8::Persistent<v8::FunctionTemplate>, proxyTemplate, ())
; | 241 DEFINE_STATIC_LOCAL(v8::Persistent<v8::FunctionTemplate>, proxyTemplate, ())
; |
| 215 v8::Local<v8::FunctionTemplate> proxyTemplateLocal; | 242 v8::Local<v8::FunctionTemplate> proxyTemplateLocal; |
| 216 v8::Isolate* v8Isolate = v8::Isolate::GetCurrent(); | 243 v8::Isolate* v8Isolate = v8::Isolate::GetCurrent(); |
| 217 if (proxyTemplate.IsEmpty()) { | 244 if (proxyTemplate.IsEmpty()) { |
| 218 proxyTemplate.Reset(v8::Isolate::GetCurrent(), v8::FunctionTemplate::New
(v8Isolate)); | 245 proxyTemplate.Reset(v8::Isolate::GetCurrent(), v8::FunctionTemplate::New
(v8Isolate)); |
| 219 proxyTemplateLocal = v8::Local<v8::FunctionTemplate>::New(v8Isolate, pro
xyTemplate); | 246 proxyTemplateLocal = v8::Local<v8::FunctionTemplate>::New(v8Isolate, pro
xyTemplate); |
| 220 v8::Local<v8::ObjectTemplate> instanceTemplate = setupInstanceTemplate(p
roxyTemplateLocal); | 247 v8::Local<v8::ObjectTemplate> instanceTemplate = setupInstanceTemplate(p
roxyTemplateLocal); |
| 221 | 248 |
| 222 instanceTemplate->SetCallAsFunctionHandler(&functionInvocationCallback); | 249 instanceTemplate->SetCallAsFunctionHandler(&functionInvocationCallback); |
| 223 } else { | 250 } else { |
| 224 proxyTemplateLocal = v8::Local<v8::FunctionTemplate>::New(v8Isolate, pro
xyTemplate); | 251 proxyTemplateLocal = v8::Local<v8::FunctionTemplate>::New(v8Isolate, pro
xyTemplate); |
| 225 } | 252 } |
| 226 return proxyTemplateLocal; | 253 return proxyTemplateLocal; |
| 227 } | 254 } |
| 228 | 255 |
| 229 static v8::Local<v8::FunctionTemplate> dartObjectTemplate() | 256 static v8::Local<v8::FunctionTemplate> dartFunctionTemplateNoWrap() |
| 230 { | 257 { |
| 231 DEFINE_STATIC_LOCAL(v8::Persistent<v8::FunctionTemplate>, proxyTemplate, ())
; | 258 DEFINE_STATIC_LOCAL(v8::Persistent<v8::FunctionTemplate>, proxyTemplate, ())
; |
| 232 v8::Local<v8::FunctionTemplate> proxyTemplateLocal; | 259 v8::Local<v8::FunctionTemplate> proxyTemplateLocal; |
| 233 v8::Isolate* v8Isolate = v8::Isolate::GetCurrent(); | 260 v8::Isolate* v8Isolate = v8::Isolate::GetCurrent(); |
| 234 if (proxyTemplate.IsEmpty()) { | 261 if (proxyTemplate.IsEmpty()) { |
| 235 proxyTemplate.Reset(v8Isolate, v8::FunctionTemplate::New(v8Isolate)); | 262 proxyTemplate.Reset(v8::Isolate::GetCurrent(), v8::FunctionTemplate::New
(v8Isolate)); |
| 236 proxyTemplateLocal = v8::Local<v8::FunctionTemplate>::New(v8Isolate, pro
xyTemplate); | 263 proxyTemplateLocal = v8::Local<v8::FunctionTemplate>::New(v8Isolate, pro
xyTemplate); |
| 237 proxyTemplateLocal->SetClassName(v8::String::NewFromUtf8(v8Isolate, "Dar
tObject")); | 264 v8::Local<v8::ObjectTemplate> instanceTemplate = setupInstanceTemplate(p
roxyTemplateLocal); |
| 238 setupInstanceTemplate(proxyTemplateLocal); | 265 |
| 266 instanceTemplate->SetCallAsFunctionHandler(&functionInvocationCallbackNo
Wrap); |
| 239 } else { | 267 } else { |
| 240 proxyTemplateLocal = v8::Local<v8::FunctionTemplate>::New(v8Isolate, pro
xyTemplate); | 268 proxyTemplateLocal = v8::Local<v8::FunctionTemplate>::New(v8Isolate, pro
xyTemplate); |
| 241 } | 269 } |
| 242 return proxyTemplateLocal; | 270 return proxyTemplateLocal; |
| 243 } | 271 } |
| 244 | 272 |
| 245 /** | 273 /** |
| 246 * Helper class to manage scopes needed for JSInterop code. | 274 * Helper class to manage scopes needed for JSInterop code. |
| 247 */ | 275 */ |
| 248 class JsInteropScopes { | 276 class JsInteropScopes { |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 284 | 312 |
| 285 void setReturnValue(Dart_Handle ret) | 313 void setReturnValue(Dart_Handle ret) |
| 286 { | 314 { |
| 287 ASSERT(!tryCatch.HasCaught()); | 315 ASSERT(!tryCatch.HasCaught()); |
| 288 Dart_SetReturnValue(args, ret); | 316 Dart_SetReturnValue(args, ret); |
| 289 } | 317 } |
| 290 | 318 |
| 291 void setReturnValue(v8::Local<v8::Value> ret) | 319 void setReturnValue(v8::Local<v8::Value> ret) |
| 292 { | 320 { |
| 293 ASSERT(!tryCatch.HasCaught()); | 321 ASSERT(!tryCatch.HasCaught()); |
| 294 Dart_SetReturnValue(args, JsInterop::toDart(ret)); | 322 Dart_SetReturnValue(args, JsInterop::toDart(ret, false)); |
| 295 ASSERT(!tryCatch.HasCaught()); | 323 ASSERT(!tryCatch.HasCaught()); |
| 296 } | 324 } |
| 297 | 325 |
| 298 void setReturnValueInteger(int64_t ret) | 326 void setReturnValueInteger(int64_t ret) |
| 299 { | 327 { |
| 300 ASSERT(!tryCatch.HasCaught()); | 328 ASSERT(!tryCatch.HasCaught()); |
| 301 Dart_SetIntegerReturnValue(args, ret); | 329 Dart_SetIntegerReturnValue(args, ret); |
| 302 } | 330 } |
| 303 }; | 331 }; |
| 304 | 332 |
| 305 PassRefPtr<JsObject> JsObject::create(v8::Local<v8::Object> v8Handle) | 333 PassRefPtr<JsObject> JsObject::create(v8::Local<v8::Object> v8Handle) |
| 306 { | 334 { |
| 307 return adoptRef(new JsObject(v8Handle)); | 335 return adoptRef(new JsObject(v8Handle)); |
| 308 } | 336 } |
| 309 | 337 |
| 310 v8::Local<v8::Value> JsInterop::fromDart(DartDOMData* domData, Dart_Handle handl
e, Dart_Handle& exception) | 338 v8::Local<v8::Value> JsInterop::fromDart(DartDOMData* domData, Dart_Handle handl
e, Dart_Handle& exception) |
| 311 { | 339 { |
| 312 v8::Handle<v8::Value> value = V8Converter::toV8IfPrimitive(domData, handle,
exception); | 340 v8::Handle<v8::Value> value = V8Converter::toV8IfPrimitive(domData, handle,
exception); |
| 313 if (!value.IsEmpty() || exception) | 341 if (!value.IsEmpty() || exception) |
| 314 return value; | 342 return value; |
| 343 |
| 344 Dart_Handle jso = invokeTopLevelJsInteropMethod(domData, "unwrap_jso", 1, &h
andle); |
| 345 ASSERT(!Dart_IsError(jso)); |
| 346 if (DartDOMWrapper::subtypeOf(jso, JsObject::dartClassId)) { |
| 347 JsObject* object = DartDOMWrapper::unwrapDartWrapper<JsObject>(domData,
jso, exception); |
| 348 if (exception) |
| 349 return v8::Local<v8::Value>(); |
| 350 return object->localV8Object(); |
| 351 } |
| 315 // TODO(terry): START of uncommented block by Jacob, I've re-enabled for cla
mped arrays... | 352 // TODO(terry): START of uncommented block by Jacob, I've re-enabled for cla
mped arrays... |
| 316 value = V8Converter::toV8IfBrowserNative(domData, handle, exception); | 353 value = V8Converter::toV8IfBrowserNative(domData, handle, exception); |
| 317 if (!value.IsEmpty() || exception) | 354 if (!value.IsEmpty() || exception) |
| 318 return value; | 355 return value; |
| 319 // TODO(terry): END of uncommented block by Jacob. | |
| 320 if (DartDOMWrapper::subtypeOf(handle, JsObject::dartClassId)) { | |
| 321 JsObject* object = DartDOMWrapper::unwrapDartWrapper<JsObject>(domData,
handle, exception); | |
| 322 if (exception) | |
| 323 return v8::Local<v8::Value>(); | |
| 324 return object->localV8Object(); | |
| 325 } | |
| 326 | 356 |
| 327 if (DartUtilities::isFunction(domData, handle)) { | 357 if (DartUtilities::isFunction(domData, handle)) { |
| 328 v8::Local<v8::Object> functionProxy = dartFunctionTemplate()->InstanceTe
mplate()->NewInstance(); | 358 v8::Local<v8::Object> functionProxy = dartFunctionTemplate()->InstanceTe
mplate()->NewInstance(); |
| 329 DartHandleProxy::writePointerToProxy(functionProxy, handle); | 359 DartHandleProxy::writePointerToProxy(functionProxy, handle); |
| 330 // The raw functionProxy doesn't behave enough like a true JS function | 360 // The raw functionProxy doesn't behave enough like a true JS function |
| 331 // so we wrap it in a true JS function. | 361 // so we wrap it in a true JS function. |
| 332 return domData->jsInteropData()->wrapDartFunction()->Call(functionProxy,
0, 0); | 362 return domData->jsInteropData()->wrapDartFunction()->Call(functionProxy,
0, 0); |
| 333 } | 363 } |
| 334 | 364 |
| 335 v8::Local<v8::Object> proxy; | 365 v8::Local<v8::Object> proxy; |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 388 v8::Isolate* isolate = v8::Isolate::GetCurrent(); | 418 v8::Isolate* isolate = v8::Isolate::GetCurrent(); |
| 389 v8::Persistent<v8::Object> persistentHandle; | 419 v8::Persistent<v8::Object> persistentHandle; |
| 390 v8Object.Reset(isolate, v8Handle); | 420 v8Object.Reset(isolate, v8Handle); |
| 391 } | 421 } |
| 392 | 422 |
| 393 v8::Local<v8::Object> JsObject::localV8Object() | 423 v8::Local<v8::Object> JsObject::localV8Object() |
| 394 { | 424 { |
| 395 return v8::Local<v8::Object>::New(v8::Isolate::GetCurrent(), v8Object); | 425 return v8::Local<v8::Object>::New(v8::Isolate::GetCurrent(), v8Object); |
| 396 } | 426 } |
| 397 | 427 |
| 398 Dart_Handle JsInterop::toDart(v8::Local<v8::Value> v8Handle) | 428 Dart_Handle JsInterop::toDart(v8::Local<v8::Value> v8Handle, bool sometimesUseHt
ml) |
| 399 { | 429 { |
| 400 Dart_Handle handle = V8Converter::toDartIfPrimitive(v8Handle); | 430 Dart_Handle handle = V8Converter::toDartIfPrimitive(v8Handle); |
| 401 if (handle) | 431 if (handle) |
| 402 return handle; | 432 return handle; |
| 403 | 433 |
| 404 ASSERT(v8Handle->IsObject()); | 434 ASSERT(v8Handle->IsObject()); |
| 405 v8::Handle<v8::Object> object = v8Handle.As<v8::Object>(); | 435 v8::Handle<v8::Object> object = v8Handle.As<v8::Object>(); |
| 406 // TODO(terry): START of uncommented block by Jacob, I've re-enabled for cla
mped arrays... | 436 // TODO(terry): START of uncommented block by Jacob, I've re-enabled for cla
mped arrays... |
| 407 Dart_Handle exception = 0; | 437 Dart_Handle exception = 0; |
| 408 handle = V8Converter::toDartIfBrowserNative(object, object->CreationContext(
)->GetIsolate(), exception); | 438 handle = V8Converter::toDartIfBrowserNative(object, object->CreationContext(
)->GetIsolate(), exception); |
| (...skipping 10 matching lines...) Expand all Loading... |
| 419 DartPersistentValue* scriptValue = DartHandleProxy::readPointerFromProxy
(v8Handle); | 449 DartPersistentValue* scriptValue = DartHandleProxy::readPointerFromProxy
(v8Handle); |
| 420 ASSERT(scriptValue->isIsolateAlive()); | 450 ASSERT(scriptValue->isIsolateAlive()); |
| 421 // If the isolate does not match we fall back to using the existing JS | 451 // If the isolate does not match we fall back to using the existing JS |
| 422 // wrapper for the Dart object so that simple cases that would work in | 452 // wrapper for the Dart object so that simple cases that would work in |
| 423 // Dart2Js work. We could alternately throw an exception here. | 453 // Dart2Js work. We could alternately throw an exception here. |
| 424 if (scriptValue->isolate() == Dart_CurrentIsolate()) { | 454 if (scriptValue->isolate() == Dart_CurrentIsolate()) { |
| 425 return scriptValue->value(); | 455 return scriptValue->value(); |
| 426 } | 456 } |
| 427 } | 457 } |
| 428 | 458 |
| 429 return JsObject::toDart(object); | 459 return JsObject::toDart(object, sometimesUseHtml); |
| 430 } | 460 } |
| 431 | 461 |
| 432 Dart_Handle JsObject::toDart(v8::Local<v8::Object> object) | 462 Dart_Handle JsObject::toDart(v8::Local<v8::Object> object, bool sometimesUseHtml
) |
| 433 { | 463 { |
| 434 // FIXME: perform caching so that === can be used. | 464 Dart_Handle wrapper; |
| 465 v8::Isolate* v8Isolate = v8::Isolate::GetCurrent(); |
| 466 DartDOMData* domData = DartDOMData::current(); |
| 467 DartJsInteropData* interopData = domData->jsInteropData(); |
| 468 v8::Local<v8::String> existingDartWrapperKey = interopData->existingDartWrap
perHiddenField(v8Isolate); |
| 469 |
| 470 // TODO(alanknight): This will fail for multiple isolates referencing the sa
me JS object. |
| 471 // We probably need to use a different property name for different isolates. |
| 472 v8::Local<v8::Value> hiddenValue = object->GetHiddenValue(existingDartWrappe
rKey); |
| 473 |
| 474 if (*hiddenValue && hiddenValue->IsObject()) { |
| 475 DartPersistentValue* scriptValue = DartHandleProxy::readPointerFromProxy
(hiddenValue.As<v8::Object>()); |
| 476 ASSERT(scriptValue->isIsolateAlive()); |
| 477 // If the isolate does not match we fall back to using the existing JS |
| 478 // wrapper for the Dart object so that simple cases that would work in |
| 479 // Dart2Js work. We could alternately throw an exception here. |
| 480 if (scriptValue->isolate() == Dart_CurrentIsolate()) { |
| 481 Dart_Handle wrapper = scriptValue->value(); |
| 482 if (sometimesUseHtml) { |
| 483 wrapper = invokeTopLevelJsInteropMethod(domData, "_maybeWrap", 1
, &wrapper); |
| 484 } |
| 485 return wrapper; |
| 486 } |
| 487 } |
| 488 |
| 489 Dart_Handle ret = 0; |
| 435 if (object->IsFunction()) { | 490 if (object->IsFunction()) { |
| 436 RefPtr<JsFunction> jsFunction = JsFunction::create(object.As<v8::Functio
n>()); | 491 RefPtr<JsFunction> jsFunction = JsFunction::create(object.As<v8::Functio
n>()); |
| 437 return JsFunction::toDart(jsFunction); | 492 wrapper = JsFunction::toDart(jsFunction); |
| 493 } else if (object->IsArray() |
| 494 // Check for Dart List objects from different Dart isolates. |
| 495 // In dart2js the List from a different isolate would just be a regular |
| 496 // JS Array so it can be treated as a JS Array. |
| 497 || dartListTemplate()->HasInstance(object)) { |
| 498 RefPtr<JsArray> jsArray = JsArray::create(object); |
| 499 wrapper = JsArray::toDart(jsArray); |
| 500 } else { |
| 501 RefPtr<JsObject> jsObject = JsObject::create(object); |
| 502 wrapper = JsObject::toDart(jsObject); |
| 503 if (sometimesUseHtml) { |
| 504 ret = invokeTopLevelJsInteropMethod(DartDOMData::current(), "_maybeW
rap", 1, &wrapper); |
| 505 } |
| 438 } | 506 } |
| 439 | 507 |
| 440 if (object->IsArray()) { | 508 v8::Local<v8::Object> proxy; |
| 441 RefPtr<JsArray> jsArray = JsArray::create(object.As<v8::Array>()); | 509 |
| 442 return JsArray::toDart(jsArray); | 510 // Prevent creation of cross frame dart:html objects for classes other than
Window. |
| 511 // Verify that the object is from the same context using the same check |
| 512 // we used to use in V8Converter. |
| 513 if (!object->CreationContext()->Global()->StrictEquals(DartUtilities::curren
tV8Context()->Global())) { |
| 514 // Short circuit creating dart:html wrappers for cross frame objects |
| 515 // other than window. |
| 516 // TODO(jacobr): handle cross frame Window objects differently to more |
| 517 // exactly match existing dart:html semantics. |
| 518 if (!object->CreationContext()->Global()->StrictEquals(object)) { |
| 519 Dart_SetField(wrapper, Dart_NewStringFromCString("_dartHtmlWrapper")
, wrapper); |
| 520 } |
| 443 } | 521 } |
| 444 | 522 ASSERT(Dart_IsInstance(wrapper)); |
| 445 RefPtr<JsObject> jsObject = JsObject::create(object); | 523 // Simulate the behavior of the Dart dev compiler where new List() is |
| 446 return JsObject::toDart(jsObject); | 524 // equivalent to a JavaScript array. We accomplish this by creating a |
| 525 // JavaScript object that fakes that it is a JavaScript array but is |
| 526 // actually backed by a Dart list. This is not a breaking change as |
| 527 // existing Dart-JS interop passed arrays as opaque Dart handles. |
| 528 // The jsify method can still be called if you wish to create a copy |
| 529 // of a json like Dart data structure. |
| 530 proxy = dartObjectTemplate()->InstanceTemplate()->NewInstance(); |
| 531 DartHandleProxy::writePointerToProxy(proxy, wrapper); |
| 532 object->SetHiddenValue(existingDartWrapperKey, proxy); |
| 533 return ret != 0 ? ret : wrapper; |
| 447 } | 534 } |
| 448 | 535 |
| 449 static void maybeCreateJsObjectImplClass(DartDOMData* domData) | 536 void JsInterop::buildInteropPatchFiles(DartDOMData* domData, Vector<InteropPatch
File>* patches, Dart_Handle& exception) |
| 537 { |
| 538 // Build patch files implementing all external methods specified with new |
| 539 // style JS interop and JsObjectImpl, JsFunctionImpl, and JsArrayImpl |
| 540 // classes that implement all Dart types annoted with @Js. |
| 541 // The sole purpose of these classes is to ensure that checked mode |
| 542 // allows casting a JsObject to all types implemented by a JsObject. |
| 543 Dart_Handle externals = invokeTopLevelJsInteropMethod(domData, "_generateInt
eropPatchFiles", 0, 0); |
| 544 if (Dart_IsError(externals)) { |
| 545 exception = externals; |
| 546 return; |
| 547 } |
| 548 ASSERT(Dart_IsList(externals)); |
| 549 intptr_t externalsLength = 0; |
| 550 Dart_ListLength(externals, &externalsLength); |
| 551 ASSERT(externalsLength % 3 == 0); |
| 552 |
| 553 for (intptr_t i = 0; i < externalsLength; i += 3) { |
| 554 InteropPatchFile patch; |
| 555 |
| 556 Dart_Handle libraryUri = Dart_ListGetAt(externals, i); |
| 557 Dart_Handle patchFileUri = Dart_ListGetAt(externals, i + 1); |
| 558 Dart_Handle source = Dart_ListGetAt(externals, i + 2); |
| 559 ASSERT(Dart_IsString(libraryUri)); |
| 560 ASSERT(Dart_IsString(patchFileUri)); |
| 561 ASSERT(Dart_IsString(source)); |
| 562 patch.libraryUri = DartUtilities::toString(libraryUri); |
| 563 patch.patchFileUri = DartUtilities::toString(patchFileUri); |
| 564 patch.source = DartUtilities::toString(source); |
| 565 patches->append(patch); |
| 566 } |
| 567 } |
| 568 |
| 569 void JsInterop::initializeJsInterop(DartDOMData* domData, const Vector<InteropPa
tchFile>& patches, Dart_Handle& exception) |
| 450 { | 570 { |
| 451 DartJsInteropData* interopData = domData->jsInteropData(); | 571 DartJsInteropData* interopData = domData->jsInteropData(); |
| 452 // Skip if the JSObjectImpl class has already been defined. | 572 // Skip if the JSObjectImpl class has already been defined. |
| 453 if (interopData->jsObjectImplDefined()) { | 573 if (interopData->jsObjectImplDefined()) { |
| 454 return; | 574 return; |
| 455 } | 575 } |
| 456 // Helper method that generates boilerplate source code for | 576 // Helper method that generates boilerplate source code for |
| 457 // JsObjectImpl, JsFunctionImpl, and JsArrayImpl classes that implement | 577 // JsObjectImpl, JsFunctionImpl, and JsArrayImpl classes that implement |
| 458 // all Dart types that have been passed to the dart:js registerJsInterfaces | 578 // all Dart types that have been passed to the dart:js registerJsInterfaces |
| 459 // method. The sole purpose of these classes is to ensure that checked mode | 579 // method. The sole purpose of these classes is to ensure that checked mode |
| 460 // allows casting a JsObject to all types implemented by a JsObject. | 580 // allows casting a JsObject to all types implemented by a JsObject. |
| 461 Dart_Handle source = invokeTopLevelJsInteropMethod(domData, "_generateJsObje
ctImplPart", 0, 0); | |
| 462 ASSERT(Dart_IsString(source)); | |
| 463 | 581 |
| 464 Dart_Handle ret = Dart_LibraryLoadPatch(domData->jsLibrary(), Dart_NewString
FromCString("JsInteropImpl.dart"), source); | 582 Dart_Handle ret; |
| 465 ALLOW_UNUSED_LOCAL(ret); | 583 for (size_t i = 0; i < patches.size(); ++i) { |
| 466 ASSERT(!Dart_IsError(ret)); | 584 const InteropPatchFile& patch = patches[i]; |
| 585 Dart_Handle library = Dart_LookupLibrary(DartUtilities::safeStringToDart
String(patch.libraryUri)); |
| 586 ASSERT(Dart_IsLibrary(library)); |
| 587 Dart_Handle patchFileUri = DartUtilities::safeStringToDartString(patch.p
atchFileUri); |
| 588 Dart_Handle source = DartUtilities::safeStringToDartString(patch.source)
; |
| 589 ret = Dart_LibraryLoadPatch(library, patchFileUri, source); |
| 590 if (Dart_IsError(ret)) { |
| 591 exception = ret; |
| 592 return; |
| 593 } |
| 594 } |
| 467 ret = Dart_FinalizeLoading(false); | 595 ret = Dart_FinalizeLoading(false); |
| 468 ASSERT(!Dart_IsError(ret)); | 596 if (Dart_IsError(ret)) { |
| 597 exception = ret; |
| 598 return; |
| 599 } |
| 469 | 600 |
| 470 interopData->setJsObjectImplDefined(); | 601 interopData->setJsObjectImplDefined(); |
| 471 | 602 |
| 472 // Start of polyfill work to make Dart List proxies behave like JavaScript | 603 if (domData->isDOMEnabled()) { |
| 473 // Arrays by monkey patching JavaScript Array and the List JavaScript | 604 // Start of polyfill work to make Dart List proxies behave like JavaScri
pt |
| 474 // proxies as needed. | 605 // Arrays by monkey patching JavaScript Array and the List JavaScript |
| 475 v8::Context::Scope scope(DartUtilities::currentV8Context()); | 606 // proxies as needed. |
| 607 v8::Context::Scope scope(DartUtilities::currentV8Context()); |
| 476 | 608 |
| 477 v8::Isolate* v8Isolate = v8::Isolate::GetCurrent(); | 609 v8::Isolate* v8Isolate = v8::Isolate::GetCurrent(); |
| 478 | 610 |
| 479 v8::Local<v8::Function> dartArrayConstructor = dartListTemplate()->GetFuncti
on(); | 611 v8::Local<v8::Function> dartArrayConstructor = dartListTemplate()->GetFu
nction(); |
| 480 | 612 |
| 481 DartUtilities::currentV8Context()->Global()->Set(v8::String::NewFromUtf8(v8I
solate, "$DartList"), | 613 DartUtilities::currentV8Context()->Global()->Set(v8::String::NewFromUtf8
(v8Isolate, "$DartList"), |
| 482 dartArrayConstructor); | 614 dartArrayConstructor); |
| 483 V8ScriptRunner::compileAndRunInternalScript(v8::String::NewFromUtf8(v8Isolat
e, dartArrayPolyfill), v8Isolate); | 615 V8ScriptRunner::compileAndRunInternalScript(v8::String::NewFromUtf8(v8Is
olate, dartArrayPolyfill), v8Isolate); |
| 616 |
| 617 ret = Dart_Invoke(domData->jsLibrary(), Dart_NewStringFromCString("_regi
sterAllJsInterfaces"), 0, 0); |
| 618 if (Dart_IsError(ret)) { |
| 619 exception = ret; |
| 620 return; |
| 621 } |
| 622 } |
| 484 } | 623 } |
| 485 | 624 |
| 486 Dart_Handle JsObject::toDart(PassRefPtr<JsObject> jsObject) | 625 Dart_Handle JsObject::toDart(PassRefPtr<JsObject> jsObject) |
| 487 { | 626 { |
| 488 DartDOMData* domData = DartDOMData::current(); | 627 DartDOMData* domData = DartDOMData::current(); |
| 489 // We need to ensure JsObjectImpl exists before creating the wrapper. | 628 // We need to ensure JsObjectImpl exists before creating the wrapper. |
| 490 maybeCreateJsObjectImplClass(domData); | |
| 491 return DartDOMWrapper::createWrapper<JsObject>(domData, jsObject.get(), JsOb
ject::dartClassId); | 629 return DartDOMWrapper::createWrapper<JsObject>(domData, jsObject.get(), JsOb
ject::dartClassId); |
| 492 } | 630 } |
| 493 | 631 |
| 494 JsObject::~JsObject() | 632 JsObject::~JsObject() |
| 495 { | 633 { |
| 496 v8Object.Reset(); | 634 v8Object.Reset(); |
| 497 } | 635 } |
| 498 | 636 |
| 499 Dart_Handle JsFunction::toDart(PassRefPtr<JsFunction> jsFunction) | 637 Dart_Handle JsFunction::toDart(PassRefPtr<JsFunction> jsFunction) |
| 500 { | 638 { |
| 501 DartDOMData* domData = DartDOMData::current(); | 639 DartDOMData* domData = DartDOMData::current(); |
| 502 // We need to ensure JsObjectImpl exists before creating the wrapper. | 640 // We need to ensure JsObjectImpl exists before creating the wrapper. |
| 503 maybeCreateJsObjectImplClass(domData); | |
| 504 return DartDOMWrapper::createWrapper<JsFunction>(domData, jsFunction.get(),
JsFunction::dartClassId); | 641 return DartDOMWrapper::createWrapper<JsFunction>(domData, jsFunction.get(),
JsFunction::dartClassId); |
| 505 } | 642 } |
| 506 | 643 |
| 507 JsFunction::JsFunction(v8::Local<v8::Function> v8Handle) : JsObject(v8Handle) {
} | 644 JsFunction::JsFunction(v8::Local<v8::Function> v8Handle) : JsObject(v8Handle) {
} |
| 508 | 645 |
| 509 PassRefPtr<JsFunction> JsFunction::create(v8::Local<v8::Function> v8Handle) | 646 PassRefPtr<JsFunction> JsFunction::create(v8::Local<v8::Function> v8Handle) |
| 510 { | 647 { |
| 511 return adoptRef(new JsFunction(v8Handle)); | 648 return adoptRef(new JsFunction(v8Handle)); |
| 512 } | 649 } |
| 513 | 650 |
| 514 v8::Local<v8::Function> JsFunction::localV8Function() | 651 v8::Local<v8::Function> JsFunction::localV8Function() |
| 515 { | 652 { |
| 516 return localV8Object().As<v8::Function>(); | 653 return localV8Object().As<v8::Function>(); |
| 517 } | 654 } |
| 518 | 655 |
| 519 Dart_Handle JsArray::toDart(PassRefPtr<JsArray> jsArray) | 656 Dart_Handle JsArray::toDart(PassRefPtr<JsArray> jsArray) |
| 520 { | 657 { |
| 521 DartDOMData* domData = DartDOMData::current(); | 658 DartDOMData* domData = DartDOMData::current(); |
| 522 // We need to ensure JsArrayImpl exists before creating the wrapper. | 659 // We need to ensure JsArrayImpl exists before creating the wrapper. |
| 523 maybeCreateJsObjectImplClass(domData); | |
| 524 return DartDOMWrapper::createWrapper<JsArray>(domData, jsArray.get(), JsArra
y::dartClassId); | 660 return DartDOMWrapper::createWrapper<JsArray>(domData, jsArray.get(), JsArra
y::dartClassId); |
| 525 } | 661 } |
| 526 | 662 |
| 527 JsArray::JsArray(v8::Local<v8::Array> v8Handle) : JsObject(v8Handle) { } | 663 JsArray::JsArray(v8::Local<v8::Object> v8Handle) : JsObject(v8Handle) { } |
| 528 | 664 |
| 529 PassRefPtr<JsArray> JsArray::create(v8::Local<v8::Array> v8Handle) | 665 PassRefPtr<JsArray> JsArray::create(v8::Local<v8::Object> v8Handle) |
| 530 { | 666 { |
| 531 return adoptRef(new JsArray(v8Handle)); | 667 return adoptRef(new JsArray(v8Handle)); |
| 532 } | 668 } |
| 533 | 669 |
| 534 v8::Local<v8::Array> JsArray::localV8Array() | |
| 535 { | |
| 536 return localV8Object().As<v8::Array>(); | |
| 537 } | |
| 538 | |
| 539 namespace JsInteropInternal { | 670 namespace JsInteropInternal { |
| 540 | 671 |
| 541 typedef HashMap<Dart_Handle, v8::Handle<v8::Value> > DartHandleToV8Map; | 672 typedef HashMap<Dart_Handle, v8::Handle<v8::Value> > DartHandleToV8Map; |
| 542 v8::Handle<v8::Value> jsifyHelper(DartDOMData*, Dart_Handle value, DartHandleToV
8Map&, Dart_Handle& exception); | 673 v8::Handle<v8::Value> jsifyHelper(DartDOMData*, Dart_Handle value, DartHandleToV
8Map&, Dart_Handle& exception); |
| 543 | 674 |
| 544 void argsListToV8(DartDOMData* domData, Dart_Handle args, Vector<v8::Local<v8::V
alue> >* v8Args, Dart_Handle& exception) | 675 void argsListToV8(DartDOMData* domData, Dart_Handle args, Vector<v8::Local<v8::V
alue> >* v8Args, Dart_Handle& exception) |
| 545 { | 676 { |
| 546 if (Dart_IsNull(args)) | 677 if (Dart_IsNull(args)) |
| 547 return; | 678 return; |
| 548 | 679 |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 598 v8::Local<v8::Value> ret = constructorArg.As<v8::Function>()->CallAsCons
tructor(v8Args.size(), v8Args.data()); | 729 v8::Local<v8::Value> ret = constructorArg.As<v8::Function>()->CallAsCons
tructor(v8Args.size(), v8Args.data()); |
| 599 crashIfV8IsDead(); | 730 crashIfV8IsDead(); |
| 600 | 731 |
| 601 if (scopes.handleJsException(&exception)) | 732 if (scopes.handleJsException(&exception)) |
| 602 goto fail; | 733 goto fail; |
| 603 | 734 |
| 604 // Intentionally skip auto-conversion in this case as the user expects | 735 // Intentionally skip auto-conversion in this case as the user expects |
| 605 // a JSObject. FIXME: evaluate if this is the right solution. | 736 // a JSObject. FIXME: evaluate if this is the right solution. |
| 606 // Alternately, we could throw an exception. | 737 // Alternately, we could throw an exception. |
| 607 if (ret->IsObject()) { | 738 if (ret->IsObject()) { |
| 608 scopes.setReturnValue(JsObject::toDart(ret.As<v8::Object>())); | 739 scopes.setReturnValue(JsObject::toDart(ret.As<v8::Object>(), false))
; |
| 609 } else { | 740 } else { |
| 610 // This will throw an exception in Dart checked mode. | 741 // This will throw an exception in Dart checked mode. |
| 611 scopes.setReturnValue(ret); | 742 scopes.setReturnValue(ret); |
| 612 } | 743 } |
| 613 return; | 744 return; |
| 614 } | 745 } |
| 615 | 746 |
| 616 fail: | 747 fail: |
| 617 Dart_ThrowException(exception); | 748 Dart_ThrowException(exception); |
| 618 ASSERT_NOT_REACHED(); | 749 ASSERT_NOT_REACHED(); |
| (...skipping 246 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 865 } | 996 } |
| 866 | 997 |
| 867 fail: | 998 fail: |
| 868 Dart_ThrowException(exception); | 999 Dart_ThrowException(exception); |
| 869 ASSERT_NOT_REACHED(); | 1000 ASSERT_NOT_REACHED(); |
| 870 } | 1001 } |
| 871 | 1002 |
| 872 static void newJsArrayCallback(Dart_NativeArguments args) | 1003 static void newJsArrayCallback(Dart_NativeArguments args) |
| 873 { | 1004 { |
| 874 JsInteropScopes scopes(args); | 1005 JsInteropScopes scopes(args); |
| 875 scopes.setReturnValue(JsObject::toDart(v8::Array::New(v8::Isolate::GetCurren
t()))); | 1006 scopes.setReturnValue(JsObject::toDart(v8::Array::New(v8::Isolate::GetCurren
t()), false)); |
| 876 return; | 1007 return; |
| 877 } | 1008 } |
| 878 | 1009 |
| 879 static void newJsArrayFromSafeListCallback(Dart_NativeArguments args) | 1010 static void newJsArrayFromSafeListCallback(Dart_NativeArguments args) |
| 880 { | 1011 { |
| 881 Dart_Handle exception = 0; | 1012 Dart_Handle exception = 0; |
| 882 { | 1013 { |
| 883 JsInteropScopes scopes(args); | 1014 JsInteropScopes scopes(args); |
| 884 DartDOMData* domData = static_cast<DartDOMData*>(Dart_GetNativeIsolateDa
ta(args)); | 1015 DartDOMData* domData = static_cast<DartDOMData*>(Dart_GetNativeIsolateDa
ta(args)); |
| 885 Dart_Handle list = Dart_GetNativeArgument(args, 0); | 1016 Dart_Handle list = Dart_GetNativeArgument(args, 0); |
| (...skipping 23 matching lines...) Expand all Loading... |
| 909 ASSERT_NOT_REACHED(); | 1040 ASSERT_NOT_REACHED(); |
| 910 } | 1041 } |
| 911 | 1042 |
| 912 | 1043 |
| 913 static void jsArrayLengthCallback(Dart_NativeArguments args) | 1044 static void jsArrayLengthCallback(Dart_NativeArguments args) |
| 914 { | 1045 { |
| 915 Dart_Handle exception = 0; | 1046 Dart_Handle exception = 0; |
| 916 { | 1047 { |
| 917 JsInteropScopes scopes(args); | 1048 JsInteropScopes scopes(args); |
| 918 JsArray* receiver = DartDOMWrapper::receiver<JsArray>(args); | 1049 JsArray* receiver = DartDOMWrapper::receiver<JsArray>(args); |
| 919 uint32_t length = receiver->localV8Array()->Length(); | 1050 v8::Local<v8::Value> length = receiver->localV8Object()->Get(v8::String:
:NewFromUtf8(v8::Isolate::GetCurrent(), "length")); |
| 920 if (scopes.handleJsException(&exception)) | 1051 if (scopes.handleJsException(&exception)) |
| 921 goto fail; | 1052 goto fail; |
| 922 scopes.setReturnValueInteger(length); | 1053 scopes.setReturnValue(length); |
| 923 return; | 1054 return; |
| 924 } | 1055 } |
| 925 | 1056 |
| 926 fail: | 1057 fail: |
| 927 Dart_ThrowException(exception); | 1058 Dart_ThrowException(exception); |
| 928 ASSERT_NOT_REACHED(); | 1059 ASSERT_NOT_REACHED(); |
| 929 } | 1060 } |
| 930 | 1061 |
| 931 static void fromBrowserObjectCallback(Dart_NativeArguments args) | 1062 static void fromBrowserObjectCallback(Dart_NativeArguments args) |
| 932 { | 1063 { |
| 933 Dart_Handle exception = 0; | 1064 Dart_Handle exception = 0; |
| 934 { | 1065 { |
| 935 JsInteropScopes scopes(args); | 1066 JsInteropScopes scopes(args); |
| 936 DartDOMData* domData = static_cast<DartDOMData*>(Dart_GetNativeIsolateDa
ta(args)); | 1067 DartDOMData* domData = static_cast<DartDOMData*>(Dart_GetNativeIsolateDa
ta(args)); |
| 937 | 1068 |
| 938 v8::Local<v8::Value> ret = V8Converter::toV8IfBrowserNative(domData, Dar
t_GetNativeArgument(args, 0), exception); | 1069 v8::Local<v8::Value> ret = V8Converter::toV8IfBrowserNative(domData, Dar
t_GetNativeArgument(args, 0), exception); |
| 939 if (ret.IsEmpty()) { | 1070 if (ret.IsEmpty()) { |
| 940 exception = Dart_NewStringFromCString("object must be an Node, Array
Buffer, Blob, ImageData, or IDBKeyRange"); | 1071 exception = Dart_NewStringFromCString("object must be an Node, Array
Buffer, Blob, ImageData, or IDBKeyRange"); |
| 941 goto fail; | 1072 goto fail; |
| 942 } | 1073 } |
| 943 if (exception) | 1074 if (exception) |
| 944 goto fail; | 1075 goto fail; |
| 945 ASSERT(ret->IsObject()); | 1076 ASSERT(ret->IsObject()); |
| 946 if (scopes.handleJsException(&exception)) | 1077 if (scopes.handleJsException(&exception)) |
| 947 goto fail; | 1078 goto fail; |
| 948 scopes.setReturnValue(JsObject::toDart(ret.As<v8::Object>())); | 1079 scopes.setReturnValue(JsObject::toDart(ret.As<v8::Object>(), false)); |
| 949 return; | 1080 return; |
| 950 } | 1081 } |
| 951 | 1082 |
| 952 fail: | 1083 fail: |
| 953 Dart_ThrowException(exception); | 1084 Dart_ThrowException(exception); |
| 954 ASSERT_NOT_REACHED(); | 1085 ASSERT_NOT_REACHED(); |
| 955 } | 1086 } |
| 956 | 1087 |
| 957 static void applyCallback(Dart_NativeArguments args) | 1088 static void applyCallback(Dart_NativeArguments args) |
| 958 { | 1089 { |
| 959 Dart_Handle exception = 0; | 1090 Dart_Handle exception = 0; |
| 960 { | 1091 { |
| 961 JsInteropScopes scopes(args); | 1092 JsInteropScopes scopes(args); |
| 962 DartDOMData* domData = static_cast<DartDOMData*>(Dart_GetNativeIsolateDa
ta(args)); | 1093 DartDOMData* domData = static_cast<DartDOMData*>(Dart_GetNativeIsolateDa
ta(args)); |
| 963 JsFunction* receiver = DartDOMWrapper::receiver<JsFunction>(args); | 1094 JsFunction* receiver = DartDOMWrapper::receiver<JsFunction>(args); |
| 964 | 1095 |
| 965 Vector<v8::Local<v8::Value> > v8Args; | 1096 Vector<v8::Local<v8::Value> > v8Args; |
| 966 argsListToV8(domData, Dart_GetNativeArgument(args, 1), &v8Args, exceptio
n); | 1097 argsListToV8(domData, Dart_GetNativeArgument(args, 1), &v8Args, exceptio
n); |
| 967 if (exception) | 1098 if (exception) |
| 968 goto fail; | 1099 goto fail; |
| 969 | 1100 |
| 970 v8::Local<v8::Value> thisArg; | 1101 v8::Local<v8::Value> thisArg; |
| 971 Dart_Handle thisArgDart = Dart_GetNativeArgument(args, 2); | 1102 Dart_Handle thisArgDart = Dart_GetNativeArgument(args, 2); |
| 972 if (Dart_IsNull(thisArgDart)) { | 1103 if (Dart_IsNull(thisArgDart)) { |
| 973 // Use the global v8 object if no Dart thisArg was passed in. | 1104 // Use the global v8 object if no Dart thisArg was passed in. |
| 974 thisArg = DartUtilities::currentV8Context()->Global(); | 1105 thisArg = DartUtilities::currentV8Context()->Global(); |
| 975 } else { | 1106 } else { |
| 976 Dart_Handle jso = Dart_GetField(thisArgDart, Dart_NewStringFromCStri
ng("blink_jsObject")); | 1107 thisArg = JsInterop::fromDart(domData, thisArgDart, exception); |
| 977 if (!Dart_IsError(jso) && DartDOMWrapper::subtypeOf(jso, JsObject::d
artClassId)) { | 1108 if (exception) |
| 978 // Use the blink JS Interop object. | 1109 goto fail; |
| 979 JsObject* object = DartDOMWrapper::unwrapDartWrapper<JsObject>(d
omData, jso, exception); | |
| 980 if (exception) | |
| 981 thisArg = v8::Local<v8::Value>(); | |
| 982 thisArg = object->localV8Object(); | |
| 983 } else { | |
| 984 thisArg = JsInterop::fromDart(domData, thisArgDart, exception); | |
| 985 if (exception) | |
| 986 goto fail; | |
| 987 } | |
| 988 if (!thisArg->IsObject()) { | 1110 if (!thisArg->IsObject()) { |
| 989 exception = Dart_NewStringFromCString("thisArg is not an object"
); | 1111 exception = Dart_NewStringFromCString("thisArg is not an object"
); |
| 990 goto fail; | 1112 goto fail; |
| 991 } | 1113 } |
| 992 } | 1114 } |
| 993 | 1115 |
| 994 v8::Local<v8::Value> ret = V8ScriptRunner::callFunction(receiver->localV
8Function(), | 1116 v8::Local<v8::Value> ret = V8ScriptRunner::callFunction(receiver->localV
8Function(), |
| 995 DartUtilities::scriptExecutionContext(), | 1117 DartUtilities::scriptExecutionContext(), |
| 996 thisArg.As<v8::Object>(), | 1118 thisArg.As<v8::Object>(), |
| 997 v8Args.size(), | 1119 v8Args.size(), |
| (...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1075 } | 1197 } |
| 1076 fail: | 1198 fail: |
| 1077 Dart_ThrowException(exception); | 1199 Dart_ThrowException(exception); |
| 1078 ASSERT_NOT_REACHED(); | 1200 ASSERT_NOT_REACHED(); |
| 1079 } | 1201 } |
| 1080 | 1202 |
| 1081 static void contextCallback(Dart_NativeArguments args) | 1203 static void contextCallback(Dart_NativeArguments args) |
| 1082 { | 1204 { |
| 1083 v8::Local<v8::Context> v8Context = DartUtilities::currentV8Context(); | 1205 v8::Local<v8::Context> v8Context = DartUtilities::currentV8Context(); |
| 1084 v8::Context::Scope scope(v8Context); | 1206 v8::Context::Scope scope(v8Context); |
| 1085 Dart_SetReturnValue(args, JsObject::toDart(v8Context->Global())); | 1207 Dart_SetReturnValue(args, JsObject::toDart(v8Context->Global(), false)); |
| 1086 } | 1208 } |
| 1087 | 1209 |
| 1088 static void finalizeJsInterfacesCallback(Dart_NativeArguments args) | 1210 static void finalizeJsInterfacesCallback(Dart_NativeArguments args) |
| 1089 { | 1211 { |
| 1090 DartDOMData* domData = static_cast<DartDOMData*>(Dart_GetNativeIsolateData(a
rgs)); | 1212 // Obsolete. |
| 1091 maybeCreateJsObjectImplClass(domData); | |
| 1092 } | 1213 } |
| 1093 | 1214 |
| 1094 static void interfacesFinalizedCallback(Dart_NativeArguments args) | 1215 static void interfacesFinalizedCallback(Dart_NativeArguments args) |
| 1095 { | 1216 { |
| 1096 DartDOMData* domData = static_cast<DartDOMData*>(Dart_GetNativeIsolateData(a
rgs)); | 1217 DartDOMData* domData = static_cast<DartDOMData*>(Dart_GetNativeIsolateData(a
rgs)); |
| 1097 DartJsInteropData* interopData = domData->jsInteropData(); | 1218 DartJsInteropData* interopData = domData->jsInteropData(); |
| 1098 // Skip if the JSObjectImpl class has already been defined. | 1219 // Skip if the JSObjectImpl class has already been defined. |
| 1099 Dart_SetBooleanReturnValue(args, interopData->jsObjectImplDefined()); | 1220 Dart_SetBooleanReturnValue(args, interopData->jsObjectImplDefined()); |
| 1100 } | 1221 } |
| 1101 | 1222 |
| (...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1190 v8::Local<v8::Value> ret = jsifyHelper(domData, value, map, exception); | 1311 v8::Local<v8::Value> ret = jsifyHelper(domData, value, map, exception); |
| 1191 if (exception) | 1312 if (exception) |
| 1192 goto fail; | 1313 goto fail; |
| 1193 | 1314 |
| 1194 if (scopes.handleJsException(&exception)) | 1315 if (scopes.handleJsException(&exception)) |
| 1195 goto fail; | 1316 goto fail; |
| 1196 // Intentionally skip auto-conversion in this case as the user expects | 1317 // Intentionally skip auto-conversion in this case as the user expects |
| 1197 // a JSObject. FIXME: evaluate if this is the right solution. | 1318 // a JSObject. FIXME: evaluate if this is the right solution. |
| 1198 // Alternately, we could throw an exception. | 1319 // Alternately, we could throw an exception. |
| 1199 if (ret->IsObject()) { | 1320 if (ret->IsObject()) { |
| 1200 scopes.setReturnValue(JsObject::toDart(ret.As<v8::Object>())); | 1321 scopes.setReturnValue(JsObject::toDart(ret.As<v8::Object>(), false))
; |
| 1201 } else { | 1322 } else { |
| 1202 // This will throw an exception in Dart checked mode. | 1323 // This will throw an exception in Dart checked mode. |
| 1203 scopes.setReturnValue(ret); | 1324 scopes.setReturnValue(ret); |
| 1204 } | 1325 } |
| 1205 return; | 1326 return; |
| 1206 } | 1327 } |
| 1207 fail: | 1328 fail: |
| 1208 Dart_ThrowException(exception); | 1329 Dart_ThrowException(exception); |
| 1209 ASSERT_NOT_REACHED(); | 1330 ASSERT_NOT_REACHED(); |
| 1210 } | 1331 } |
| (...skipping 15 matching lines...) Expand all Loading... |
| 1226 if (scopes.handleJsException(&exception)) | 1347 if (scopes.handleJsException(&exception)) |
| 1227 goto fail; | 1348 goto fail; |
| 1228 scopes.setReturnValue(ret); | 1349 scopes.setReturnValue(ret); |
| 1229 return; | 1350 return; |
| 1230 } | 1351 } |
| 1231 fail: | 1352 fail: |
| 1232 Dart_ThrowException(exception); | 1353 Dart_ThrowException(exception); |
| 1233 ASSERT_NOT_REACHED(); | 1354 ASSERT_NOT_REACHED(); |
| 1234 } | 1355 } |
| 1235 | 1356 |
| 1357 |
| 1358 static void withThisCallbackNoWrap(Dart_NativeArguments args) |
| 1359 { |
| 1360 Dart_Handle exception = 0; |
| 1361 { |
| 1362 JsInteropScopes scopes(args); |
| 1363 Dart_Handle function = Dart_GetNativeArgument(args, 0); |
| 1364 DartDOMData* domData = static_cast<DartDOMData*>(Dart_GetNativeIsolateDa
ta(args)); |
| 1365 ASSERT(DartUtilities::isFunction(domData, function)); |
| 1366 |
| 1367 v8::Local<v8::Object> proxy = dartFunctionTemplateNoWrap()->InstanceTemp
late()->NewInstance(); |
| 1368 DartHandleProxy::writePointerToProxy(proxy, function); |
| 1369 |
| 1370 v8::Local<v8::Function> ret = v8::Local<v8::Function>::Cast(domData->jsI
nteropData()->captureThisFunction()->Call(proxy, 0, 0)); |
| 1371 |
| 1372 if (scopes.handleJsException(&exception)) |
| 1373 goto fail; |
| 1374 scopes.setReturnValue(ret); |
| 1375 return; |
| 1376 } |
| 1377 fail: |
| 1378 Dart_ThrowException(exception); |
| 1379 ASSERT_NOT_REACHED(); |
| 1380 } |
| 1381 |
| 1236 } | 1382 } |
| 1237 | 1383 |
| 1238 static DartNativeEntry nativeEntries[] = { | 1384 static DartNativeEntry nativeEntries[] = { |
| 1239 { JsInteropInternal::jsObjectConstructorCallback, 2, "JsObject_constructorCa
llback" }, | 1385 { JsInteropInternal::jsObjectConstructorCallback, 2, "JsObject_constructorCa
llback" }, |
| 1240 { JsInterop::jsInteropContextCallback, 0, "Js_context_Callback" }, | 1386 { JsInterop::jsInteropContextCallback, 0, "Js_context_Callback" }, |
| 1241 { JsInteropInternal::finalizeJsInterfacesCallback, 0, "Js_finalizeJsInterfac
es" }, | 1387 { JsInteropInternal::finalizeJsInterfacesCallback, 0, "Js_finalizeJsInterfac
es" }, |
| 1242 { JsInteropInternal::interfacesFinalizedCallback, 0, "Js_interfacesFinalized
_Callback" }, | 1388 { JsInteropInternal::interfacesFinalizedCallback, 0, "Js_interfacesFinalized
_Callback" }, |
| 1243 { JsInteropInternal::jsifyCallback, 1, "JsObject_jsify" }, | 1389 { JsInteropInternal::jsifyCallback, 1, "JsObject_jsify" }, |
| 1244 { JsInteropInternal::withThisCallback, 1, "JsFunction_withThis" }, | 1390 { JsInteropInternal::withThisCallback, 1, "JsFunction_withThis" }, |
| 1391 { JsInteropInternal::withThisCallbackNoWrap, 1, "JsFunction_withThisNoWrap"
}, |
| 1245 { JsInterop::jsInteropGetterCallback, 2, "JsObject_[]" }, | 1392 { JsInterop::jsInteropGetterCallback, 2, "JsObject_[]" }, |
| 1246 { JsInteropInternal::setterCallback, 3, "JsObject_[]=" }, | 1393 { JsInteropInternal::setterCallback, 3, "JsObject_[]=" }, |
| 1247 { JsInteropInternal::hashCodeCallback, 1, "JsObject_hashCode" }, | 1394 { JsInteropInternal::hashCodeCallback, 1, "JsObject_hashCode" }, |
| 1248 { JsInterop::jsInteropCallMethodCallback, 3, "JsObject_callMethod" }, | 1395 { JsInterop::jsInteropCallMethodCallback, 3, "JsObject_callMethod" }, |
| 1249 { JsInteropInternal::toStringCallback, 1, "JsObject_toString" }, | 1396 { JsInteropInternal::toStringCallback, 1, "JsObject_toString" }, |
| 1250 { JsInteropInternal::identityEqualityCallback, 2, "JsObject_identityEquality
" }, | 1397 { JsInteropInternal::identityEqualityCallback, 2, "JsObject_identityEquality
" }, |
| 1251 { JsInteropInternal::hasPropertyCallback, 2, "JsObject_hasProperty" }, | 1398 { JsInteropInternal::hasPropertyCallback, 2, "JsObject_hasProperty" }, |
| 1252 { JsInteropInternal::deletePropertyCallback, 2, "JsObject_deleteProperty" }, | 1399 { JsInteropInternal::deletePropertyCallback, 2, "JsObject_deleteProperty" }, |
| 1253 { JsInteropInternal::instanceofCallback, 2, "JsObject_instanceof" }, | 1400 { JsInteropInternal::instanceofCallback, 2, "JsObject_instanceof" }, |
| 1254 { JsInteropInternal::applyCallback, 3, "JsFunction_apply" }, | 1401 { JsInteropInternal::applyCallback, 3, "JsFunction_apply" }, |
| (...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1417 if (handleNonDartProxyThis(info, jsMethodName)) { | 1564 if (handleNonDartProxyThis(info, jsMethodName)) { |
| 1418 return; | 1565 return; |
| 1419 } | 1566 } |
| 1420 DartScopes scopes(info.Holder()); | 1567 DartScopes scopes(info.Holder()); |
| 1421 DartDOMData* domData = DartDOMData::current(); | 1568 DartDOMData* domData = DartDOMData::current(); |
| 1422 Dart_Handle handle = scopes.handle; | 1569 Dart_Handle handle = scopes.handle; |
| 1423 Dart_Handle e; | 1570 Dart_Handle e; |
| 1424 if (info.Length() == 0) { | 1571 if (info.Length() == 0) { |
| 1425 e = Dart_Null(); | 1572 e = Dart_Null(); |
| 1426 } else { | 1573 } else { |
| 1427 e = JsInterop::toDart(info[0]); | 1574 e = JsInterop::toDart(info[0], false); |
| 1428 } | 1575 } |
| 1429 Dart_Handle args[2] = { handle, e }; | 1576 Dart_Handle args[2] = { handle, e }; |
| 1430 Dart_Handle ret = Dart_Invoke(domData->jsLibrary(), Dart_NewStringFromCStrin
g(methodName), 2, args); | 1577 Dart_Handle ret = Dart_Invoke(domData->jsLibrary(), Dart_NewStringFromCStrin
g(methodName), 2, args); |
| 1431 setJsReturnValue(domData, info, ret); | 1578 setJsReturnValue(domData, info, ret); |
| 1432 } | 1579 } |
| 1433 | 1580 |
| 1434 void arrayHelperWithArgsAsList(const v8::FunctionCallbackInfo<v8::Value>& info,
const char* methodName, const char* jsMethodName) | 1581 void arrayHelperWithArgsAsList(const v8::FunctionCallbackInfo<v8::Value>& info,
const char* methodName, const char* jsMethodName) |
| 1435 { | 1582 { |
| 1436 if (handleNonDartProxyThis(info, jsMethodName)) { | 1583 if (handleNonDartProxyThis(info, jsMethodName)) { |
| 1437 return; | 1584 return; |
| 1438 } | 1585 } |
| 1439 DartScopes scopes(info.Holder()); | 1586 DartScopes scopes(info.Holder()); |
| 1440 DartDOMData* domData = DartDOMData::current(); | 1587 DartDOMData* domData = DartDOMData::current(); |
| 1441 Dart_Handle handle = scopes.handle; | 1588 Dart_Handle handle = scopes.handle; |
| 1442 int length = info.Length(); | 1589 int length = info.Length(); |
| 1443 Dart_Handle argsList = Dart_NewList(length); | 1590 Dart_Handle argsList = Dart_NewList(length); |
| 1444 for (int i = 0; i < length; ++i) { | 1591 for (int i = 0; i < length; ++i) { |
| 1445 Dart_ListSetAt(argsList, i, JsInterop::toDart(info[i])); | 1592 Dart_ListSetAt(argsList, i, JsInterop::toDart(info[i], false)); |
| 1446 } | 1593 } |
| 1447 // Note: this is also just info.Holder(). | 1594 // Note: this is also just info.Holder(). |
| 1448 Dart_Handle args[2] = { handle, argsList }; | 1595 Dart_Handle args[2] = { handle, argsList }; |
| 1449 setJsReturnValue(domData, info, Dart_Invoke(domData->jsLibrary(), Dart_NewSt
ringFromCString(methodName), 2, args)); | 1596 setJsReturnValue(domData, info, Dart_Invoke(domData->jsLibrary(), Dart_NewSt
ringFromCString(methodName), 2, args)); |
| 1450 } | 1597 } |
| 1451 | 1598 |
| 1452 static void arrayNamedPropertyGetter(v8::Local<v8::String> name, const v8::Prope
rtyCallbackInfo<v8::Value>& info) | 1599 static void arrayNamedPropertyGetter(v8::Local<v8::String> name, const v8::Prope
rtyCallbackInfo<v8::Value>& info) |
| 1453 { | 1600 { |
| 1454 if (!DartHandleProxy::isDartProxy(info.Holder())) { | 1601 if (!DartHandleProxy::isDartProxy(info.Holder())) { |
| 1455 // I don't think this case can occur but avoid crashing if there is an | 1602 // I don't think this case can occur but avoid crashing if there is an |
| (...skipping 22 matching lines...) Expand all Loading... |
| 1478 } | 1625 } |
| 1479 | 1626 |
| 1480 v8::Isolate* v8Isolate = v8::Isolate::GetCurrent(); | 1627 v8::Isolate* v8Isolate = v8::Isolate::GetCurrent(); |
| 1481 if (!property->Equals(v8::String::NewFromUtf8(v8Isolate, "length"))) { | 1628 if (!property->Equals(v8::String::NewFromUtf8(v8Isolate, "length"))) { |
| 1482 return; | 1629 return; |
| 1483 } | 1630 } |
| 1484 | 1631 |
| 1485 DartScopes scopes(info.Holder()); | 1632 DartScopes scopes(info.Holder()); |
| 1486 Dart_Handle handle = scopes.handle; | 1633 Dart_Handle handle = scopes.handle; |
| 1487 DartDOMData* domData = DartDOMData::current(); | 1634 DartDOMData* domData = DartDOMData::current(); |
| 1488 Dart_Handle args[2] = { handle, JsInterop::toDart(value) }; | 1635 Dart_Handle args[2] = { handle, JsInterop::toDart(value, true) }; |
| 1489 Dart_Handle ret = Dart_Invoke(domData->jsLibrary(), Dart_NewStringFromCStrin
g("_setListLength"), 2, args); | 1636 Dart_Handle ret = Dart_Invoke(domData->jsLibrary(), Dart_NewStringFromCStrin
g("_setListLength"), 2, args); |
| 1490 setJsReturnValue(domData, info, ret); | 1637 setJsReturnValue(domData, info, ret); |
| 1491 } | 1638 } |
| 1492 | 1639 |
| 1493 static void arrayQueryProperty(v8::Local<v8::String> name, const v8::PropertyCal
lbackInfo<v8::Integer>& info) | 1640 static void arrayQueryProperty(v8::Local<v8::String> name, const v8::PropertyCal
lbackInfo<v8::Integer>& info) |
| 1494 { | 1641 { |
| 1495 v8::Isolate* v8Isolate = v8::Isolate::GetCurrent(); | 1642 v8::Isolate* v8Isolate = v8::Isolate::GetCurrent(); |
| 1496 if (name->Equals(v8::String::NewFromUtf8(v8Isolate, "length"))) { | 1643 if (name->Equals(v8::String::NewFromUtf8(v8Isolate, "length"))) { |
| 1497 v8SetReturnValueInt(info, v8::DontEnum | v8::DontDelete); | 1644 v8SetReturnValueInt(info, v8::DontEnum | v8::DontDelete); |
| 1498 } | 1645 } |
| (...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1611 | 1758 |
| 1612 v8::Local<v8::ObjectTemplate> instanceTemplate = setupInstanceTemplate(p
roxyTemplateLocal); | 1759 v8::Local<v8::ObjectTemplate> instanceTemplate = setupInstanceTemplate(p
roxyTemplateLocal); |
| 1613 instanceTemplate->SetIndexedPropertyHandler(&indexedGetterArray, &indexe
dSetterArray, 0, 0, &indexedEnumeratorArray); | 1760 instanceTemplate->SetIndexedPropertyHandler(&indexedGetterArray, &indexe
dSetterArray, 0, 0, &indexedEnumeratorArray); |
| 1614 instanceTemplate->SetNamedPropertyHandler(&arrayNamedPropertyGetter, &ar
rayNamedPropertySetter, &arrayQueryProperty, &arrayDeleteProperty, 0); | 1761 instanceTemplate->SetNamedPropertyHandler(&arrayNamedPropertyGetter, &ar
rayNamedPropertySetter, &arrayQueryProperty, &arrayDeleteProperty, 0); |
| 1615 } else { | 1762 } else { |
| 1616 proxyTemplateLocal = v8::Local<v8::FunctionTemplate>::New(v8Isolate, pro
xyTemplate); | 1763 proxyTemplateLocal = v8::Local<v8::FunctionTemplate>::New(v8Isolate, pro
xyTemplate); |
| 1617 } | 1764 } |
| 1618 return proxyTemplateLocal; | 1765 return proxyTemplateLocal; |
| 1619 } | 1766 } |
| 1620 | 1767 |
| 1768 void dartObjectToStringCallback(const v8::FunctionCallbackInfo<v8::Value>& info) |
| 1769 { |
| 1770 if (handleNonDartProxyThis(info, "toString")) { |
| 1771 return; |
| 1772 } |
| 1773 DartScopes scopes(info.Holder()); |
| 1774 DartDOMData* domData = DartDOMData::current(); |
| 1775 Dart_Handle handle = scopes.handle; |
| 1776 setJsReturnValue(domData, info, Dart_ToString(handle)); |
| 1777 } |
| 1778 |
| 1779 static v8::Local<v8::FunctionTemplate> dartObjectTemplate() |
| 1780 { |
| 1781 DEFINE_STATIC_LOCAL(v8::Persistent<v8::FunctionTemplate>, proxyTemplate, ())
; |
| 1782 v8::Local<v8::FunctionTemplate> proxyTemplateLocal; |
| 1783 v8::Isolate* v8Isolate = v8::Isolate::GetCurrent(); |
| 1784 if (proxyTemplate.IsEmpty()) { |
| 1785 proxyTemplate.Reset(v8Isolate, v8::FunctionTemplate::New(v8Isolate)); |
| 1786 proxyTemplateLocal = v8::Local<v8::FunctionTemplate>::New(v8Isolate, pro
xyTemplate); |
| 1787 v8::Local<v8::ObjectTemplate> protoTemplate = proxyTemplateLocal->Proto
typeTemplate(); |
| 1788 protoTemplate->Set(v8::String::NewFromUtf8(v8Isolate, "toString"), v8::F
unctionTemplate::New(v8Isolate, dartObjectToStringCallback)); |
| 1789 |
| 1790 proxyTemplateLocal->SetClassName(v8::String::NewFromUtf8(v8Isolate, "Dar
tObject")); |
| 1791 setupInstanceTemplate(proxyTemplateLocal); |
| 1792 } else { |
| 1793 proxyTemplateLocal = v8::Local<v8::FunctionTemplate>::New(v8Isolate, pro
xyTemplate); |
| 1794 } |
| 1795 return proxyTemplateLocal; |
| 1796 } |
| 1797 |
| 1621 void JsInterop::jsInteropGetterCallback(Dart_NativeArguments args) | 1798 void JsInterop::jsInteropGetterCallback(Dart_NativeArguments args) |
| 1622 { | 1799 { |
| 1623 JsInteropInternal::getterCallback(args); | 1800 JsInteropInternal::getterCallback(args); |
| 1624 } | 1801 } |
| 1625 | 1802 |
| 1626 void JsInterop::jsInteropCallMethodCallback(Dart_NativeArguments args) | 1803 void JsInterop::jsInteropCallMethodCallback(Dart_NativeArguments args) |
| 1627 { | 1804 { |
| 1628 JsInteropInternal::callMethodCallback(args); | 1805 JsInteropInternal::callMethodCallback(args); |
| 1629 } | 1806 } |
| 1630 | 1807 |
| 1631 void JsInterop::jsInteropContextCallback(Dart_NativeArguments args) | 1808 void JsInterop::jsInteropContextCallback(Dart_NativeArguments args) |
| 1632 { | 1809 { |
| 1633 return JsInteropInternal::contextCallback(args); | 1810 return JsInteropInternal::contextCallback(args); |
| 1634 } | 1811 } |
| 1635 | 1812 |
| 1636 } | 1813 } |
| OLD | NEW |