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 |