Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(22)

Side by Side Diff: frog/lib/isolate.dart

Issue 9358010: isolates in frog: playing with API improvements (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: '' Created 8 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « frog/lib/corelib.dart ('k') | frog/lib/isolate_serialization.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2011, 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 /** 5 /**
6 * A native object that is shared across isolates. This object is visible to all 6 * A native object that is shared across isolates. This object is visible to all
7 * isolates running on the same worker (either UI or background web worker). 7 * isolates running on the same worker (either UI or background web worker).
8 * 8 *
9 * This is code that is intended to 'escape' the isolate boundaries in order to 9 * This is code that is intended to 'escape' the isolate boundaries in order to
10 * implement the semantics of friendly isolates in JavaScript. Without this we 10 * implement the semantics of friendly isolates in JavaScript. Without this we
11 * would have been forced to implement more code (including the top-level event 11 * would have been forced to implement more code (including the top-level event
(...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after
155 155
156 _deserializeMessage(message) { 156 _deserializeMessage(message) {
157 if (_globalState.needSerialization) { 157 if (_globalState.needSerialization) {
158 return new Deserializer().deserialize(message); 158 return new Deserializer().deserialize(message);
159 } else { 159 } else {
160 // Nothing more to do. 160 // Nothing more to do.
161 return message; 161 return message;
162 } 162 }
163 } 163 }
164 164
165 /** Wait until all ports in a message are resolved. */
166 _waitForPendingPorts(var message, void callback()) {
167 final finder = new PendingSendPortFinder();
168 finder.traverse(message);
169 Futures.wait(finder.ports).then((_) => callback());
170 }
171
165 /** Default worker. */ 172 /** Default worker. */
166 class MainWorker { 173 class MainWorker {
167 int id = 0; 174 int id = 0;
168 void postMessage(msg) native "return \$globalThis.postMessage(msg);"; 175 void postMessage(msg) native "return \$globalThis.postMessage(msg);";
169 void set onmessage(f) native "\$globalThis.onmessage = f;"; 176 void set onmessage(f) native "\$globalThis.onmessage = f;";
170 void terminate() {} 177 void terminate() {}
171 } 178 }
172 179
173 /** 180 /**
174 * A web worker. This type is also defined in 'dart:dom', but we define it here 181 * A web worker. This type is also defined in 'dart:dom', but we define it here
(...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after
333 340
334 BaseSendPort(this._isolateId); 341 BaseSendPort(this._isolateId);
335 342
336 ReceivePortSingleShotImpl call(var message) { 343 ReceivePortSingleShotImpl call(var message) {
337 final result = new ReceivePortSingleShotImpl(); 344 final result = new ReceivePortSingleShotImpl();
338 this.send(message, result.toSendPort()); 345 this.send(message, result.toSendPort());
339 return result; 346 return result;
340 } 347 }
341 348
342 static void checkReplyTo(SendPort replyTo) { 349 static void checkReplyTo(SendPort replyTo) {
343 if (replyTo !== null && replyTo is! NativeJsSendPort 350 if (replyTo !== null
344 && replyTo is! WorkerSendPort) { 351 && replyTo is! NativeJsSendPort
345 throw "SendPort.send: Illegal replyTo port type."; 352 && replyTo is! WorkerSendPort
353 && replyTo is! BufferingSendPort) {
354 throw new Exception("SendPort.send: Illegal replyTo port type");
346 } 355 }
347 } 356 }
348 357
349 // TODO(sigmund): replace the current SendPort.call with the following: 358 // TODO(sigmund): replace the current SendPort.call with the following:
350 //Future call(var message) { 359 //Future call(var message) {
351 //  final completer = new Completer(); 360 //  final completer = new Completer();
352 //  final port = new ReceivePort.singleShot(); 361 //  final port = new ReceivePort.singleShot();
353 //  send(message, port.toSendPort()); 362 //  send(message, port.toSendPort());
354 //  port.receive((value, ignoreReplyTo) { 363 //  port.receive((value, ignoreReplyTo) {
355 //    if (value is Exception) { 364 //    if (value is Exception) {
(...skipping 10 matching lines...) Expand all
366 abstract int hashCode(); 375 abstract int hashCode();
367 } 376 }
368 377
369 /** A send port that delivers messages in-memory via native JavaScript calls. */ 378 /** A send port that delivers messages in-memory via native JavaScript calls. */
370 class NativeJsSendPort extends BaseSendPort implements SendPort { 379 class NativeJsSendPort extends BaseSendPort implements SendPort {
371 final ReceivePortImpl _receivePort; 380 final ReceivePortImpl _receivePort;
372 381
373 const NativeJsSendPort(this._receivePort, int isolateId) : super(isolateId); 382 const NativeJsSendPort(this._receivePort, int isolateId) : super(isolateId);
374 383
375 void send(var message, [SendPort replyTo = null]) { 384 void send(var message, [SendPort replyTo = null]) {
376 checkReplyTo(replyTo); 385 _waitForPendingPorts([message, replyTo], () {
377 // Check that the isolate still runs and the port is still open 386 checkReplyTo(replyTo);
378 final isolate = _globalState.isolates[_isolateId]; 387 // Check that the isolate still runs and the port is still open
379 if (isolate == null) return; 388 final isolate = _globalState.isolates[_isolateId];
380 if (_receivePort._callback == null) return; 389 if (isolate == null) return;
390 if (_receivePort._callback == null) return;
381 391
382 // We force serialization/deserialization as a simple way to ensure isolate 392 // We force serialization/deserialization as a simple way to ensure
383 // communication restrictions are respected between isolates that live in 393 // isolate communication restrictions are respected between isolates that
384 // the same worker. NativeJsSendPort delivers both messages from the same 394 // live in the same worker. NativeJsSendPort delivers both messages from
385 // worker and messages from other workers. In particular, messages sent from 395 // the same worker and messages from other workers. In particular,
386 // a worker via a WorkerSendPort are received at [_processWorkerMessage] and 396 // messages sent from a worker via a WorkerSendPort are received at
387 // forwarded to a native port. In such cases, here we'll see 397 // [_processWorkerMessage] and forwarded to a native port. In such cases,
388 // [_globalState.currentContext == null]. 398 // here we'll see [_globalState.currentContext == null].
389 final shouldSerialize = _globalState.currentContext != null 399 final shouldSerialize = _globalState.currentContext != null
390 && _globalState.currentContext.id != _isolateId; 400 && _globalState.currentContext.id != _isolateId;
391 var msg = message; 401 var msg = message;
392 var reply = replyTo; 402 var reply = replyTo;
393 if (shouldSerialize) { 403 if (shouldSerialize) {
394 msg = _serializeMessage(msg); 404 msg = _serializeMessage(msg);
395 reply = _serializeMessage(reply); 405 reply = _serializeMessage(reply);
396 } 406 }
397 _globalState.topEventLoop.enqueue(isolate, () { 407 _globalState.topEventLoop.enqueue(isolate, () {
398 if (_receivePort._callback != null) { 408 if (_receivePort._callback != null) {
399 if (shouldSerialize) { 409 if (shouldSerialize) {
400 msg = _deserializeMessage(msg); 410 msg = _deserializeMessage(msg);
401 reply = _deserializeMessage(reply); 411 reply = _deserializeMessage(reply);
412 }
413 _receivePort._callback(msg, reply);
402 } 414 }
403 _receivePort._callback(msg, reply); 415 }, 'receive ' + message);
404 } 416 });
405 }, 'receive ' + message);
406 } 417 }
407 418
408 bool operator ==(var other) => (other is NativeJsSendPort) && 419 bool operator ==(var other) => (other is NativeJsSendPort) &&
409 (_receivePort == other._receivePort); 420 (_receivePort == other._receivePort);
410 421
411 int hashCode() => _receivePort._id; 422 int hashCode() => _receivePort._id;
412 } 423 }
413 424
414 /** A send port that delivers messages via worker.postMessage. */ 425 /** A send port that delivers messages via worker.postMessage. */
415 class WorkerSendPort extends BaseSendPort implements SendPort { 426 class WorkerSendPort extends BaseSendPort implements SendPort {
416 final int _workerId; 427 final int _workerId;
417 final int _receivePortId; 428 final int _receivePortId;
418 429
419 const WorkerSendPort(this._workerId, int isolateId, this._receivePortId) 430 const WorkerSendPort(this._workerId, int isolateId, this._receivePortId)
420 : super(isolateId); 431 : super(isolateId);
421 432
422 void send(var message, [SendPort replyTo = null]) { 433 void send(var message, [SendPort replyTo = null]) {
423 checkReplyTo(replyTo); 434 _waitForPendingPorts([message, replyTo], () {
424 final workerMessage = _serializeMessage({ 435 checkReplyTo(replyTo);
425 'command': 'message', 436 final workerMessage = _serializeMessage({
426 'port': this, 437 'command': 'message',
427 'msg': message, 438 'port': this,
428 'replyTo': replyTo}); 439 'msg': message,
440 'replyTo': replyTo});
429 441
430 if (_globalState.isWorker) { 442 if (_globalState.isWorker) {
431 // communication from one worker to another go through the main worker: 443 // communication from one worker to another go through the main worker:
432 _globalState.mainWorker.postMessage(workerMessage); 444 _globalState.mainWorker.postMessage(workerMessage);
433 } else { 445 } else {
434 _globalState.workers[_workerId].postMessage(workerMessage); 446 _globalState.workers[_workerId].postMessage(workerMessage);
435 } 447 }
448 });
436 } 449 }
437 450
438 bool operator ==(var other) { 451 bool operator ==(var other) {
439 return (other is WorkerSendPort) && 452 return (other is WorkerSendPort) &&
440 (_workerId == other._workerId) && 453 (_workerId == other._workerId) &&
441 (_isolateId == other._isolateId) && 454 (_isolateId == other._isolateId) &&
442 (_receivePortId == other._receivePortId); 455 (_receivePortId == other._receivePortId);
443 } 456 }
444 457
445 int hashCode() { 458 int hashCode() {
446 // TODO(sigmund): use a standard hash when we get one available in corelib. 459 // TODO(sigmund): use a standard hash when we get one available in corelib.
447 return (_workerId << 16) ^ (_isolateId << 8) ^ _receivePortId; 460 return (_workerId << 16) ^ (_isolateId << 8) ^ _receivePortId;
448 } 461 }
449 } 462 }
450 463
464 /** A port that buffers messages until an underlying port gets resolved. */
465 class BufferingSendPort extends BaseSendPort implements SendPort {
466 /** Internal counter to assign unique ids to each port. */
467 static int _idCount = 0;
468
469 /** For implementing equals and hashcode. */
470 final int _id;
471
472 /** Underlying port, when resolved. */
473 SendPort _port;
474
475 /**
476 * Future of the underlying port, so that we can detect when this port can be
477 * sent on messages.
478 */
479 Future<SendPort> _futurePort;
480
481 /** Pending messages (and reply ports). */
482 List pending;
483
484 BufferingSendPort(isolateId, this._futurePort)
485 : super(isolateId), _id = _idCount, pending = [] {
486 _idCount++;
487 _futurePort.then((p) {
488 _port = p;
489 for (final item in pending) {
490 p.send(item['message'], item['replyTo']);
491 }
492 pending = null;
493 });
494 }
495
496 BufferingSendPort.fromPort(isolateId, this._port)
497 : super(isolateId), _id = _idCount {
498 _idCount++;
499 }
500
501 void send(var message, [SendPort replyTo]) {
502 if (_port != null) {
503 _port.send(message, replyTo);
504 } else {
505 pending.add({'message': message, 'replyTo': replyTo});
506 }
507 }
508
509 bool operator ==(var other) => other is BufferingSendPort && _id == other._id;
510 int hashCode() => _id;
511 }
512
451 /** Default factory for receive ports. */ 513 /** Default factory for receive ports. */
452 class ReceivePortFactory { 514 class ReceivePortFactory {
453 515
454 factory ReceivePort() { 516 factory ReceivePort() {
455 return new ReceivePortImpl(); 517 return new ReceivePortImpl();
456 } 518 }
457 519
458 factory ReceivePort.singleShot() { 520 factory ReceivePort.singleShot() {
459 return new ReceivePortSingleShotImpl(); 521 return new ReceivePortSingleShotImpl();
460 } 522 }
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
529 591
530 return completer.future; 592 return completer.future;
531 } 593 }
532 594
533 static SendPort _startWorker(Isolate runnable, SendPort replyPort) { 595 static SendPort _startWorker(Isolate runnable, SendPort replyPort) {
534 var factoryName = _getJSConstructorName(runnable); 596 var factoryName = _getJSConstructorName(runnable);
535 if (_globalState.isWorker) { 597 if (_globalState.isWorker) {
536 _globalState.mainWorker.postMessage(_serializeMessage({ 598 _globalState.mainWorker.postMessage(_serializeMessage({
537 'command': 'spawn-worker', 599 'command': 'spawn-worker',
538 'factoryName': factoryName, 600 'factoryName': factoryName,
539 'replyPort': replyPort})); 601 'replyPort': _serializeMessage(replyPort)}));
540 } else { 602 } else {
541 _spawnWorker(factoryName, _serializeMessage(replyPort)); 603 _spawnWorker(factoryName, _serializeMessage(replyPort));
542 } 604 }
543 } 605 }
544 606
545
546 /** 607 /**
547 * The src url for the script tag that loaded this code. Used to create 608 * The src url for the script tag that loaded this code. Used to create
548 * JavaScript workers. 609 * JavaScript workers.
549 */ 610 */
550 static String get _thisScript() => 611 static String get _thisScript() =>
551 _thisScriptCache != null ? _thisScriptCache : _computeThisScript(); 612 _thisScriptCache != null ? _thisScriptCache : _computeThisScript();
552 613
553 static String _thisScriptCache; 614 static String _thisScriptCache;
554 615
555 // TODO(sigmund): fix - this code should be run synchronously when loading the 616 // TODO(sigmund): fix - this code should be run synchronously when loading the
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
601 */ 662 */
602 static _getEventData(e) native "return e.data"; 663 static _getEventData(e) native "return e.data";
603 664
604 /** 665 /**
605 * Process messages on a worker, either to control the worker instance or to 666 * Process messages on a worker, either to control the worker instance or to
606 * pass messages along to the isolate running in the worker. 667 * pass messages along to the isolate running in the worker.
607 */ 668 */
608 static void _processWorkerMessage(sender, e) { 669 static void _processWorkerMessage(sender, e) {
609 var msg = _deserializeMessage(_getEventData(e)); 670 var msg = _deserializeMessage(_getEventData(e));
610 switch (msg['command']) { 671 switch (msg['command']) {
672 // TODO(sigmund): delete after we migrate to Isolate2
611 case 'start': 673 case 'start':
612 _globalState.currentWorkerId = msg['id']; 674 _globalState.currentWorkerId = msg['id'];
613 var runnerObject = 675 var runnerObject =
614 _allocate(_getJSConstructorFromName(msg['factoryName'])); 676 _allocate(_getJSConstructorFromName(msg['factoryName']));
615 var serializedReplyTo = msg['replyTo']; 677 var serializedReplyTo = msg['replyTo'];
616 _globalState.topEventLoop.enqueue(new IsolateContext(), function() { 678 _globalState.topEventLoop.enqueue(new IsolateContext(), function() {
617 var replyTo = _deserializeMessage(serializedReplyTo); 679 var replyTo = _deserializeMessage(serializedReplyTo);
618 IsolateNatives._startIsolate(runnerObject, replyTo); 680 _startIsolate(runnerObject, replyTo);
619 }, 'worker-start'); 681 }, 'worker-start');
620 _globalState.topEventLoop.run(); 682 _globalState.topEventLoop.run();
621 break; 683 break;
684 case 'start2':
685 _globalState.currentWorkerId = msg['id'];
686 Function entryPoint = _getJSFunctionFromName(msg['functionName']);
687 var replyTo = _deserializeMessage(msg['replyTo']);
688 _globalState.topEventLoop.enqueue(new IsolateContext(), function() {
689 _startIsolate2(entryPoint, replyTo);
690 }, 'worker-start');
691 _globalState.topEventLoop.run();
692 break;
693 // TODO(sigmund): delete after we migrate to Isolate2
622 case 'spawn-worker': 694 case 'spawn-worker':
623 _spawnWorker(msg['factoryName'], msg['replyPort']); 695 _spawnWorker(msg['factoryName'], msg['replyPort']);
624 break; 696 break;
697 case 'spawn-worker2':
698 _spawnWorker2(msg['functionName'], msg['uri'], msg['replyPort']);
699 break;
625 case 'message': 700 case 'message':
626 msg['port'].send(msg['msg'], msg['replyTo']); 701 msg['port'].send(msg['msg'], msg['replyTo']);
627 _globalState.topEventLoop.run(); 702 _globalState.topEventLoop.run();
628 break; 703 break;
629 case 'close': 704 case 'close':
630 _log("Closing Worker"); 705 _log("Closing Worker");
631 _globalState.workers.remove(sender.id); 706 _globalState.workers.remove(sender.id);
632 sender.terminate(); 707 sender.terminate();
633 _globalState.topEventLoop.run(); 708 _globalState.topEventLoop.run();
634 break; 709 break;
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
677 // TODO(sigmund): find a browser-generic way to support this. 752 // TODO(sigmund): find a browser-generic way to support this.
678 static var _getJSConstructorName(Isolate runnable) native """ 753 static var _getJSConstructorName(Isolate runnable) native """
679 return runnable.constructor.name; 754 return runnable.constructor.name;
680 """; 755 """;
681 756
682 /** Find a constructor given it's name. */ 757 /** Find a constructor given it's name. */
683 static var _getJSConstructorFromName(String factoryName) native """ 758 static var _getJSConstructorFromName(String factoryName) native """
684 return \$globalThis[factoryName]; 759 return \$globalThis[factoryName];
685 """; 760 """;
686 761
762 static var _getJSFunctionFromName(String functionName) native """
763 return \$globalThis[functionName];
764 """;
765
766 static String _getJSFunctionName(Function f) native "return f.name || null;";
767
687 /** Create a new JavasSript object instance given it's constructor. */ 768 /** Create a new JavasSript object instance given it's constructor. */
688 static var _allocate(var ctor) native "return new ctor();"; 769 static var _allocate(var ctor) native "return new ctor();";
689 770
690 /** Starts a non-worker isolate. */ 771 /** Starts a non-worker isolate. */
691 static SendPort _startNonWorker(Isolate runnable, SendPort replyTo) { 772 static SendPort _startNonWorker(Isolate runnable, SendPort replyTo) {
692 // Spawn a new isolate and create the receive port in it. 773 // Spawn a new isolate and create the receive port in it.
693 final spawned = new IsolateContext(); 774 final spawned = new IsolateContext();
694 775
695 // Instead of just running the provided runnable, we create a 776 // Instead of just running the provided runnable, we create a
696 // new cloned instance of it with a fresh state in the spawned 777 // new cloned instance of it with a fresh state in the spawned
697 // isolate. This way, we do not get cross-isolate references 778 // isolate. This way, we do not get cross-isolate references
698 // through the runnable. 779 // through the runnable.
699 final ctor = _getJSConstructor(runnable); 780 final ctor = _getJSConstructor(runnable);
700 _globalState.topEventLoop.enqueue(spawned, function() { 781 _globalState.topEventLoop.enqueue(spawned, function() {
701 _startIsolate(_allocate(ctor), replyTo); 782 _startIsolate(_allocate(ctor), replyTo);
702 }, 'nonworker start'); 783 }, 'nonworker start');
703 } 784 }
704 785
705 /** Given a ready-to-start runnable, start running it. */ 786 /** Given a ready-to-start runnable, start running it. */
706 static void _startIsolate(Isolate isolate, SendPort replyTo) { 787 static void _startIsolate(Isolate isolate, SendPort replyTo) {
707 _fillStatics(_globalState.currentContext); 788 _fillStatics(_globalState.currentContext);
708 ReceivePort port = new ReceivePort(); 789 ReceivePort port = new ReceivePort();
709 replyTo.send(_SPAWNED_SIGNAL, port.toSendPort()); 790 replyTo.send(_SPAWNED_SIGNAL, port.toSendPort());
710 isolate._run(port); 791 isolate._run(port);
711 } 792 }
793
794 // TODO(sigmund): clean up above, after we make the new API the default:
795
796 static _spawn2(String functionName, String uri, bool isLight) {
797 Completer<SendPort> completer = new Completer<SendPort>();
798 ReceivePort port = new ReceivePort.singleShot();
799 port.receive((msg, SendPort replyPort) {
800 assert(msg == _SPAWNED_SIGNAL);
801 completer.complete(replyPort);
802 });
803
804 SendPort signalReply = port.toSendPort();
805
806 if (_globalState.useWorkers && !isLight) {
807 _startWorker2(functionName, uri, signalReply);
808 } else {
809 _startNonWorker2(functionName, uri, signalReply);
810 }
811 return new BufferingSendPort(
812 _globalState.currentContext.id, completer.future);
813 }
814
815 static SendPort _startWorker2(
816 String functionName, String uri, SendPort replyPort) {
817 if (_globalState.isWorker) {
818 _globalState.mainWorker.postMessage(_serializeMessage({
819 'command': 'spawn-worker2',
820 'functionName': functionName,
821 'uri': uri,
822 'replyPort': replyPort}));
823 } else {
824 _spawnWorker2(functionName, uri, replyPort);
825 }
826 }
827
828 static SendPort _startNonWorker2(
829 String functionName, String uri, SendPort replyPort) {
830 _globalState.topEventLoop.enqueue(new IsolateContext(), function() {
831 final func = _getJSFunctionFromName(functionName);
832 _startIsolate2(func, replyPort);
833 }, 'nonworker start');
834 }
835
836 static void _startIsolate2(Function topLevel, SendPort replyTo) {
837 _fillStatics(_globalState.currentContext);
838 final port = new ReceivePort();
839 replyTo.send(_SPAWNED_SIGNAL, port.toSendPort());
840 topLevel(port);
841 }
842
843 /**
844 * Spawns an isolate in a worker. [factoryName] is the Javascript constructor
845 * name for the isolate entry point class.
846 */
847 static void _spawnWorker2(functionName, uri, replyPort) {
848 if (uri == null) uri = _thisScript;
849 final worker = _newWorker(uri);
850 worker.onmessage = (e) { _processWorkerMessage(worker, e); };
851 var workerId = _globalState.nextWorkerId++;
852 // We also store the id on the worker itself so that we can unregister it.
853 worker.id = workerId;
854 _globalState.workers[workerId] = worker;
855 worker.postMessage(_serializeMessage({
856 'command': 'start2',
857 'id': workerId,
858 // Note: we serialize replyPort twice because the child worker needs to
859 // first deserialize the worker id, before it can correctly deserialize
860 // the port (port deserialization is sensitive to what is the current
861 // workerId).
862 'replyTo': _serializeMessage(replyPort),
863 'functionName': functionName }));
864 }
712 } 865 }
866
867 class Isolate2Impl implements Isolate2 {
868 SendPort sendPort;
869
870 Isolate2Impl(this.sendPort);
871
872 void stop() {}
873 }
874
875 class IsolateFactory implements Isolate2 {
876
877 factory Isolate2.fromCode(Function topLevelFunction) {
878 final name = IsolateNatives._getJSFunctionName(topLevelFunction);
879 if (name == null) {
880 throw new UnsupportedOperationException(
881 "only top-level functions can be spawned.");
882 }
883 return new Isolate2Impl(IsolateNatives._spawn2(name, null, false));
884 }
885
886 factory Isolate2.fromUri(String uri) {
887 return new Isolate2Impl(IsolateNatives._spawn2(null, uri, false));
888 }
889 }
OLDNEW
« no previous file with comments | « frog/lib/corelib.dart ('k') | frog/lib/isolate_serialization.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698