OLD | NEW |
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 #include "platform/assert.h" | 5 #include "platform/assert.h" |
6 #include "vm/bootstrap_natives.h" | 6 #include "vm/bootstrap_natives.h" |
7 #include "vm/class_finalizer.h" | 7 #include "vm/class_finalizer.h" |
8 #include "vm/dart.h" | 8 #include "vm/dart.h" |
9 #include "vm/dart_api_impl.h" | 9 #include "vm/dart_api_impl.h" |
10 #include "vm/dart_entry.h" | 10 #include "vm/dart_entry.h" |
(...skipping 221 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
232 const String& error_str = String::Handle( | 232 const String& error_str = String::Handle( |
233 String::New("Error starting Isolate, class not loaded : ")); | 233 String::New("Error starting Isolate, class not loaded : ")); |
234 const Error& error = Error::Handle(LanguageError::New(error_str)); | 234 const Error& error = Error::Handle(LanguageError::New(error_str)); |
235 Isolate::Current()->object_store()->set_sticky_error(error); | 235 Isolate::Current()->object_store()->set_sticky_error(error); |
236 return false; | 236 return false; |
237 } | 237 } |
238 return true; // No errors. | 238 return true; // No errors. |
239 } | 239 } |
240 | 240 |
241 | 241 |
242 static char* GetRootScriptUri(Isolate* isolate) { | 242 static char* BuildIsolateName(const char* script_name, |
243 const Library& library = | 243 const char* class_name, |
244 Library::Handle(isolate->object_store()->root_library()); | 244 const char* func_name) { |
245 ASSERT(!library.IsNull()); | 245 // Skip past any slashes in the script name. |
246 const String& script_name = String::Handle(library.url()); | 246 const char* last_slash = strrchr(script_name, '/'); |
247 return isolate->current_zone()->MakeCopyOfString(script_name.ToCString()); | 247 if (last_slash != NULL) { |
248 } | 248 script_name = last_slash + 1; |
| 249 } |
249 | 250 |
250 | 251 char* chars = NULL; |
251 static char* BuildMainName(const char* class_name) { | 252 if (class_name && class_name[0] != '\0') { |
252 intptr_t len = OS::SNPrint(NULL, 0, "%s.main", class_name) + 1; | 253 const char* kFormat = "%s/%s.%s"; |
253 char* chars = reinterpret_cast<char*>( | 254 intptr_t len = OS::SNPrint(NULL, 0, kFormat, script_name, class_name, |
254 Isolate::Current()->current_zone()->Allocate(len)); | 255 func_name) + 1; |
255 OS::SNPrint(chars, len, "%s.main", class_name); | 256 chars = reinterpret_cast<char*>( |
| 257 Isolate::Current()->current_zone()->Allocate(len)); |
| 258 OS::SNPrint(chars, len, kFormat, script_name, class_name, func_name); |
| 259 } else { |
| 260 const char* kFormat = "%s/%s"; |
| 261 intptr_t len = OS::SNPrint(NULL, 0, kFormat, script_name, func_name) + 1; |
| 262 chars = reinterpret_cast<char*>( |
| 263 Isolate::Current()->current_zone()->Allocate(len)); |
| 264 OS::SNPrint(chars, len, kFormat, script_name, func_name); |
| 265 } |
256 return chars; | 266 return chars; |
257 } | 267 } |
258 | 268 |
259 | 269 |
260 DEFINE_NATIVE_ENTRY(IsolateNatives_start, 2) { | 270 DEFINE_NATIVE_ENTRY(IsolateNatives_start, 2) { |
261 Isolate* preserved_isolate = Isolate::Current(); | 271 Isolate* preserved_isolate = Isolate::Current(); |
262 GET_NATIVE_ARGUMENT(Instance, runnable, arguments->At(0)); | 272 GET_NATIVE_ARGUMENT(Instance, runnable, arguments->At(0)); |
263 // arguments->At(1) unused. | 273 // arguments->At(1) unused. |
264 const Class& runnable_class = Class::Handle(runnable.clazz()); | 274 const Class& runnable_class = Class::Handle(runnable.clazz()); |
265 const char* class_name = String::Handle(runnable_class.Name()).ToCString(); | 275 const char* class_name = String::Handle(runnable_class.Name()).ToCString(); |
266 const Library& library = Library::Handle(runnable_class.library()); | 276 const Library& library = Library::Handle(runnable_class.library()); |
267 ASSERT(!library.IsNull()); | 277 ASSERT(!library.IsNull()); |
268 const char* library_url = String::Handle(library.url()).ToCString(); | 278 const char* library_url = String::Handle(library.url()).ToCString(); |
269 intptr_t port_id = 0; | 279 intptr_t port_id = 0; |
270 LongJump jump; | 280 LongJump jump; |
271 bool init_successful = true; | 281 bool init_successful = true; |
272 Isolate* spawned_isolate = NULL; | 282 Isolate* spawned_isolate = NULL; |
273 void* callback_data = preserved_isolate->init_callback_data(); | 283 void* callback_data = preserved_isolate->init_callback_data(); |
274 char* error = NULL; | 284 char* error = NULL; |
275 Dart_IsolateCreateCallback callback = Isolate::CreateCallback(); | 285 Dart_IsolateCreateCallback callback = Isolate::CreateCallback(); |
276 const char* root_script_uri = GetRootScriptUri(preserved_isolate); | 286 const char* isolate_name = BuildIsolateName(library_url, class_name, "main"); |
277 const char* main = BuildMainName(class_name); | |
278 if (callback == NULL) { | 287 if (callback == NULL) { |
279 error = strdup("Null callback specified for isolate creation\n"); | 288 error = strdup("Null callback specified for isolate creation\n"); |
280 } else if (callback(root_script_uri, main, callback_data, &error)) { | 289 } else if (callback(isolate_name, callback_data, &error)) { |
281 spawned_isolate = Isolate::Current(); | 290 spawned_isolate = Isolate::Current(); |
282 ASSERT(spawned_isolate != NULL); | 291 ASSERT(spawned_isolate != NULL); |
283 // Check arguments to see if the specified library and classes are | 292 // Check arguments to see if the specified library and classes are |
284 // loaded, this check will throw an exception if they are not loaded. | 293 // loaded, this check will throw an exception if they are not loaded. |
285 if (init_successful && CheckArguments(library_url, class_name)) { | 294 if (init_successful && CheckArguments(library_url, class_name)) { |
286 port_id = spawned_isolate->main_port(); | 295 port_id = spawned_isolate->main_port(); |
287 spawned_isolate->set_spawn_data( | 296 spawned_isolate->set_spawn_data( |
288 reinterpret_cast<uword>( | 297 reinterpret_cast<uword>( |
289 new IsolateStartData(strdup(library_url), | 298 new IsolateStartData(strdup(library_url), |
290 strdup(class_name), | 299 strdup(class_name), |
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
370 } | 379 } |
371 | 380 |
372 | 381 |
373 static void ThrowIsolateSpawnException(const String& message) { | 382 static void ThrowIsolateSpawnException(const String& message) { |
374 GrowableArray<const Object*> args(1); | 383 GrowableArray<const Object*> args(1); |
375 args.Add(&message); | 384 args.Add(&message); |
376 Exceptions::ThrowByType(Exceptions::kIsolateSpawn, args); | 385 Exceptions::ThrowByType(Exceptions::kIsolateSpawn, args); |
377 } | 386 } |
378 | 387 |
379 | 388 |
380 static bool CanonicalizeUri(Isolate* isolate, | |
381 const Library& library, | |
382 const String& uri, | |
383 char** canonical_uri, | |
384 char** error) { | |
385 Zone* zone = isolate->current_zone(); | |
386 Dart_LibraryTagHandler handler = isolate->library_tag_handler(); | |
387 if (handler == NULL) { | |
388 *error = zone->PrintToString( | |
389 "Unable to canonicalize uri '%s': no library tag handler found.", | |
390 uri.ToCString()); | |
391 return false; | |
392 } | |
393 Dart_Handle result = handler(kCanonicalizeUrl, | |
394 Api::NewHandle(isolate, library.raw()), | |
395 Api::NewHandle(isolate, uri.raw())); | |
396 const Object& obj = Object::Handle(Api::UnwrapHandle(result)); | |
397 if (obj.IsError()) { | |
398 Error& error_obj = Error::Handle(); | |
399 error_obj ^= obj.raw(); | |
400 *error = zone->PrintToString("Unable to canonicalize uri '%s': %s", | |
401 uri.ToCString(), error_obj.ToErrorCString()); | |
402 return false; | |
403 } else if (obj.IsString()) { | |
404 String& string_obj = String::Handle(); | |
405 string_obj ^= obj.raw(); | |
406 *canonical_uri = zone->MakeCopyOfString(string_obj.ToCString()); | |
407 return true; | |
408 } else { | |
409 *error = zone->PrintToString("Unable to canonicalize uri '%s': " | |
410 "library tag handler returned wrong type", | |
411 uri.ToCString()); | |
412 return false; | |
413 } | |
414 } | |
415 | |
416 | |
417 class SpawnState { | 389 class SpawnState { |
418 public: | 390 public: |
419 explicit SpawnState(const Function& func) | 391 explicit SpawnState(const Function& func) |
420 : isolate_(NULL), | 392 : isolate_(NULL), |
421 script_url_(NULL), | |
422 library_url_(NULL), | 393 library_url_(NULL), |
423 function_name_(NULL) { | 394 function_name_(NULL) { |
424 script_url_ = strdup(GetRootScriptUri(Isolate::Current())); | |
425 const Class& cls = Class::Handle(func.owner()); | 395 const Class& cls = Class::Handle(func.owner()); |
426 ASSERT(cls.IsTopLevel()); | 396 ASSERT(cls.IsTopLevel()); |
427 const Library& lib = Library::Handle(cls.library()); | 397 const Library& lib = Library::Handle(cls.library()); |
428 const String& lib_url = String::Handle(lib.url()); | 398 const String& lib_url = String::Handle(lib.url()); |
429 library_url_ = strdup(lib_url.ToCString()); | 399 library_url_ = strdup(lib_url.ToCString()); |
430 | 400 |
431 const String& func_name = String::Handle(func.name()); | 401 const String& func_name = String::Handle(func.name()); |
432 function_name_ = strdup(func_name.ToCString()); | 402 function_name_ = strdup(func_name.ToCString()); |
433 } | 403 } |
434 | 404 |
435 explicit SpawnState(const char* script_url) | |
436 : isolate_(NULL), | |
437 library_url_(NULL), | |
438 function_name_(NULL) { | |
439 script_url_ = strdup(script_url); | |
440 library_url_ = NULL; | |
441 function_name_ = strdup("main"); | |
442 } | |
443 | |
444 ~SpawnState() { | 405 ~SpawnState() { |
445 free(script_url_); | |
446 free(library_url_); | 406 free(library_url_); |
447 free(function_name_); | 407 free(function_name_); |
448 } | 408 } |
449 | 409 |
450 Isolate* isolate() const { return isolate_; } | 410 Isolate* isolate() const { return isolate_; } |
451 void set_isolate(Isolate* value) { isolate_ = value; } | 411 void set_isolate(Isolate* value) { isolate_ = value; } |
452 char* script_url() const { return script_url_; } | |
453 char* library_url() const { return library_url_; } | 412 char* library_url() const { return library_url_; } |
454 char* function_name() const { return function_name_; } | 413 char* function_name() const { return function_name_; } |
455 | 414 |
456 RawObject* ResolveFunction() { | 415 RawFunction* ResolveFunction() { |
457 // Resolve the library. | 416 const String& lib_url = |
458 Library& lib = Library::Handle(); | 417 String::Handle(String::NewSymbol(library_url())); |
459 if (library_url()) { | 418 const String& func_name = |
460 const String& lib_url = String::Handle(String::New(library_url())); | 419 String::Handle(String::NewSymbol(function_name())); |
461 lib = Library::LookupLibrary(lib_url); | 420 |
462 if (lib.IsNull() || lib.IsError()) { | 421 const Library& lib = Library::Handle(Library::LookupLibrary(lib_url)); |
463 const String& msg = String::Handle(String::NewFormatted( | 422 if (lib.IsNull() || lib.IsError()) { |
464 "Unable to find library '%s'.", library_url())); | 423 return Function::null(); |
465 return LanguageError::New(msg); | |
466 } | |
467 } else { | |
468 lib = isolate()->object_store()->root_library(); | |
469 } | 424 } |
470 ASSERT(!lib.IsNull()); | 425 return lib.LookupLocalFunction(func_name); |
471 | |
472 // Resolve the function. | |
473 const String& func_name = | |
474 String::Handle(String::New(function_name())); | |
475 const Function& func = Function::Handle(lib.LookupLocalFunction(func_name)); | |
476 if (func.IsNull()) { | |
477 const String& msg = String::Handle(String::NewFormatted( | |
478 "Unable to resolve function '%s' in library '%s'.", | |
479 function_name(), (library_url() ? library_url() : script_url()))); | |
480 return LanguageError::New(msg); | |
481 } | |
482 return func.raw(); | |
483 } | 426 } |
484 | 427 |
485 void Cleanup() { | 428 void Cleanup() { |
486 SwitchIsolateScope switch_scope(isolate()); | 429 SwitchIsolateScope switch_scope(isolate()); |
487 Dart::ShutdownIsolate(); | 430 Dart::ShutdownIsolate(); |
488 } | 431 } |
489 | 432 |
490 private: | 433 private: |
491 Isolate* isolate_; | 434 Isolate* isolate_; |
492 char* script_url_; | |
493 char* library_url_; | 435 char* library_url_; |
494 char* function_name_; | 436 char* function_name_; |
495 }; | 437 }; |
496 | 438 |
497 | 439 |
498 static bool CreateIsolate(SpawnState* state, char** error) { | 440 static bool CreateIsolate(SpawnState* state, char** error) { |
499 Isolate* parent_isolate = Isolate::Current(); | 441 Isolate* parent_isolate = Isolate::Current(); |
500 | 442 |
501 Dart_IsolateCreateCallback callback = Isolate::CreateCallback(); | 443 Dart_IsolateCreateCallback callback = Isolate::CreateCallback(); |
502 ASSERT(callback != NULL); | 444 ASSERT(callback); |
| 445 const char* isolate_name = BuildIsolateName(state->library_url(), |
| 446 "", |
| 447 state->function_name()); |
503 void* init_data = parent_isolate->init_callback_data(); | 448 void* init_data = parent_isolate->init_callback_data(); |
504 bool retval = (callback)(state->script_url(), | 449 bool retval = (callback)(isolate_name, init_data, error); |
505 state->function_name(), | 450 if (retval) { |
506 init_data, | 451 Isolate* child_isolate = Isolate::Current(); |
507 error); | 452 ASSERT(child_isolate); |
508 if (!retval) { | 453 state->set_isolate(child_isolate); |
509 Isolate::SetCurrent(parent_isolate); | |
510 return false; | |
511 } | |
512 | 454 |
513 Isolate* child_isolate = Isolate::Current(); | 455 // Attempt to resolve the entry function now, so that we fail fast |
514 ASSERT(child_isolate); | 456 // in the case that the embedder's isolate create callback is |
515 state->set_isolate(child_isolate); | 457 // violating its contract. |
516 | 458 // |
517 // Attempt to resolve the entry function now, so that we fail fast | 459 // TODO(turnidge): Revisit this once we have an isolate death api. |
518 // in the case that the function cannot be resolved. | 460 { |
519 // | 461 Zone zone(child_isolate); |
520 // TODO(turnidge): Revisit this once we have an isolate death api. | 462 HandleScope handle_scope(child_isolate); |
521 bool resolve_error = false; | 463 const Function& func = Function::Handle(state->ResolveFunction()); |
522 { | 464 if (func.IsNull()) { |
523 Zone zone(child_isolate); | 465 *error = strdup(zone.PrintToString( |
524 HandleScope handle_scope(child_isolate); | 466 "Internal error while starting isolate '%s': " |
525 const Object& result = Object::Handle(state->ResolveFunction()); | 467 "unable to resolve entry function '%s'.", |
526 if (result.IsError()) { | 468 child_isolate->name(), state->function_name())); |
527 Error& errobj = Error::Handle(); | 469 retval = false; |
528 errobj ^= result.raw(); | 470 } |
529 *error = strdup(errobj.ToErrorCString()); | |
530 resolve_error = true; | |
531 } | 471 } |
532 } | 472 } |
533 if (resolve_error) { | 473 if (!retval) { |
534 Dart::ShutdownIsolate(); | 474 Dart::ShutdownIsolate(); |
535 Isolate::SetCurrent(parent_isolate); | |
536 return false; | |
537 } | 475 } |
538 | |
539 Isolate::SetCurrent(parent_isolate); | 476 Isolate::SetCurrent(parent_isolate); |
540 return true; | 477 return retval; |
541 } | 478 } |
542 | 479 |
543 | 480 |
544 static bool RunIsolate2(uword parameter) { | 481 static bool RunIsolate2(uword parameter) { |
545 Isolate* isolate = reinterpret_cast<Isolate*>(parameter); | 482 Isolate* isolate = reinterpret_cast<Isolate*>(parameter); |
546 SpawnState* state = reinterpret_cast<SpawnState*>(isolate->spawn_data()); | 483 SpawnState* state = reinterpret_cast<SpawnState*>(isolate->spawn_data()); |
547 isolate->set_spawn_data(NULL); | 484 isolate->set_spawn_data(NULL); |
548 { | 485 { |
549 StartIsolateScope start_scope(isolate); | 486 StartIsolateScope start_scope(isolate); |
550 Zone zone(isolate); | 487 Zone zone(isolate); |
551 HandleScope handle_scope(isolate); | 488 HandleScope handle_scope(isolate); |
552 ASSERT(ClassFinalizer::FinalizePendingClasses()); | 489 ASSERT(ClassFinalizer::FinalizePendingClasses()); |
553 Object& result = Object::Handle(); | 490 Object& result = Object::Handle(); |
554 | 491 |
555 result = state->ResolveFunction(); | 492 const Function& func = Function::Handle(state->ResolveFunction()); |
556 delete state; | 493 delete state; |
557 state = NULL; | 494 state = NULL; |
558 if (result.IsError()) { | 495 ASSERT(!func.IsNull()); |
559 StoreError(isolate, result); | 496 |
560 return false; | |
561 } | |
562 ASSERT(result.IsFunction()); | |
563 Function& func = Function::Handle(isolate); | |
564 func ^= result.raw(); | |
565 GrowableArray<const Object*> args(0); | 497 GrowableArray<const Object*> args(0); |
566 const Array& kNoArgNames = Array::Handle(); | 498 const Array& kNoArgNames = Array::Handle(); |
567 result = DartEntry::InvokeStatic(func, args, kNoArgNames); | 499 result = DartEntry::InvokeStatic(func, args, kNoArgNames); |
568 if (result.IsError()) { | 500 if (result.IsError()) { |
569 StoreError(isolate, result); | 501 StoreError(isolate, result); |
570 return false; | 502 return false; |
571 } | 503 } |
572 } | 504 } |
573 return true; | 505 return true; |
574 } | 506 } |
575 | 507 |
576 | 508 |
577 static void Spawn(NativeArguments* arguments, SpawnState* state) { | 509 DEFINE_NATIVE_ENTRY(isolate_spawnFunction, 1) { |
| 510 GET_NATIVE_ARGUMENT(Closure, closure, arguments->At(0)); |
| 511 const Function& func = Function::Handle(closure.function()); |
| 512 const Class& cls = Class::Handle(func.owner()); |
| 513 if (!func.IsClosureFunction() || !func.is_static() || !cls.IsTopLevel()) { |
| 514 const String& msg = String::Handle(String::New( |
| 515 "spawnFunction expects to be passed a closure to a top-level static " |
| 516 "function")); |
| 517 ThrowIllegalArgException(msg); |
| 518 } |
| 519 |
| 520 #if defined(DEBUG) |
| 521 const Context& ctx = Context::Handle(closure.context()); |
| 522 ASSERT(ctx.num_variables() == 0); |
| 523 #endif |
| 524 |
578 // Create a new isolate. | 525 // Create a new isolate. |
579 char* error = NULL; | 526 char* error = NULL; |
| 527 SpawnState* state = new SpawnState(func); |
580 if (!CreateIsolate(state, &error)) { | 528 if (!CreateIsolate(state, &error)) { |
581 delete state; | 529 delete state; |
582 const String& msg = String::Handle(String::New(error)); | 530 const String& msg = String::Handle(String::New(error)); |
583 free(error); | |
584 ThrowIsolateSpawnException(msg); | 531 ThrowIsolateSpawnException(msg); |
585 } | 532 } |
586 | 533 |
587 // Try to create a SendPort for the new isolate. | 534 // Try to create a SendPort for the new isolate. |
588 const Object& port = Object::Handle( | 535 const Object& port = Object::Handle( |
589 DartLibraryCalls::NewSendPort(state->isolate()->main_port())); | 536 DartLibraryCalls::NewSendPort(state->isolate()->main_port())); |
590 if (port.IsError()) { | 537 if (port.IsError()) { |
591 state->Cleanup(); | 538 state->Cleanup(); |
592 delete state; | 539 delete state; |
593 Exceptions::PropagateError(port); | 540 Exceptions::PropagateError(port); |
594 } | 541 } |
595 | 542 |
596 // Start the new isolate. | 543 // Start the new isolate. |
597 state->isolate()->set_spawn_data(reinterpret_cast<uword>(state)); | 544 state->isolate()->set_spawn_data(reinterpret_cast<uword>(state)); |
598 state->isolate()->message_handler()->Run( | 545 state->isolate()->message_handler()->Run( |
599 Dart::thread_pool(), RunIsolate2, ShutdownIsolate, | 546 Dart::thread_pool(), RunIsolate2, ShutdownIsolate, |
600 reinterpret_cast<uword>(state->isolate())); | 547 reinterpret_cast<uword>(state->isolate())); |
601 | 548 |
602 arguments->SetReturn(port); | 549 arguments->SetReturn(port); |
603 } | 550 } |
604 | 551 |
605 | 552 |
606 DEFINE_NATIVE_ENTRY(isolate_spawnFunction, 1) { | |
607 GET_NATIVE_ARGUMENT(Closure, closure, arguments->At(0)); | |
608 const Function& func = Function::Handle(closure.function()); | |
609 const Class& cls = Class::Handle(func.owner()); | |
610 if (!func.IsClosureFunction() || !func.is_static() || !cls.IsTopLevel()) { | |
611 const String& msg = String::Handle(String::New( | |
612 "spawnFunction expects to be passed a closure to a top-level static " | |
613 "function")); | |
614 ThrowIllegalArgException(msg); | |
615 } | |
616 | |
617 #if defined(DEBUG) | |
618 const Context& ctx = Context::Handle(closure.context()); | |
619 ASSERT(ctx.num_variables() == 0); | |
620 #endif | |
621 | |
622 Spawn(arguments, new SpawnState(func)); | |
623 } | |
624 | |
625 | |
626 DEFINE_NATIVE_ENTRY(isolate_spawnUri, 1) { | |
627 GET_NATIVE_ARGUMENT(String, uri, arguments->At(0)); | |
628 | |
629 // Canonicalize the uri with respect to the current isolate. | |
630 char* error = NULL; | |
631 char* canonical_uri = NULL; | |
632 const Library& root_lib = | |
633 Library::Handle(arguments->isolate()->object_store()->root_library()); | |
634 if (!CanonicalizeUri(arguments->isolate(), root_lib, uri, | |
635 &canonical_uri, &error)) { | |
636 const String& msg = String::Handle(String::New(error)); | |
637 free(error); | |
638 ThrowIsolateSpawnException(msg); | |
639 } | |
640 | |
641 Spawn(arguments, new SpawnState(canonical_uri)); | |
642 } | |
643 | |
644 | |
645 DEFINE_NATIVE_ENTRY(isolate_getPortInternal, 0) { | 553 DEFINE_NATIVE_ENTRY(isolate_getPortInternal, 0) { |
646 const Object& port = Object::Handle(ReceivePortCreate(isolate->main_port())); | 554 const Object& port = Object::Handle(ReceivePortCreate(isolate->main_port())); |
647 if (port.IsError()) { | 555 if (port.IsError()) { |
648 Exceptions::PropagateError(port); | 556 Exceptions::PropagateError(port); |
649 } | 557 } |
650 arguments->SetReturn(port); | 558 arguments->SetReturn(port); |
651 } | 559 } |
652 | 560 |
653 } // namespace dart | 561 } // namespace dart |
OLD | NEW |