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