| Index: sdk/lib/_internal/lib/isolate_helper.dart
|
| diff --git a/sdk/lib/_internal/lib/isolate_helper.dart b/sdk/lib/_internal/lib/isolate_helper.dart
|
| index 2a8968561340e7783fdd86a0f843c0e3ea400f85..3afb7f1092c2a9f55b2775031532aa445ad6a0c9 100644
|
| --- a/sdk/lib/_internal/lib/isolate_helper.dart
|
| +++ b/sdk/lib/_internal/lib/isolate_helper.dart
|
| @@ -264,7 +264,7 @@ class _IsolateContext implements IsolateContext {
|
|
|
| final Capability pauseCapability = new Capability();
|
|
|
| - // TODO(lrn): Store these in single "pausestate" object, so they don't take
|
| + // TODO(lrn): Store these in single "PauseState" object, so they don't take
|
| // up as much room when not pausing.
|
| bool isPaused = false;
|
| List<_IsolateEvent> delayedEvents = [];
|
| @@ -279,6 +279,7 @@ class _IsolateContext implements IsolateContext {
|
| if (pauseTokens.add(resume) && !isPaused) {
|
| isPaused = true;
|
| }
|
| + _updateGlobalState();
|
| }
|
|
|
| void removePause(Capability resume) {
|
| @@ -291,6 +292,7 @@ class _IsolateContext implements IsolateContext {
|
| }
|
| isPaused = false;
|
| }
|
| + _updateGlobalState();
|
| }
|
|
|
| /**
|
| @@ -354,7 +356,7 @@ class _IsolateContext implements IsolateContext {
|
| }
|
|
|
| _updateGlobalState() {
|
| - if (ports.length - weakPorts.length > 0) {
|
| + if (ports.length - weakPorts.length > 0 || isPaused) {
|
| _globalState.isolates[id] = this; // indicate this isolate is active
|
| } else {
|
| _globalState.isolates.remove(id); // indicate this isolate is not active
|
| @@ -592,10 +594,12 @@ class IsolateNatives {
|
| var args = msg['args'];
|
| var message = _deserializeMessage(msg['msg']);
|
| var isSpawnUri = msg['isSpawnUri'];
|
| + var startPaused = msg['startPaused'];
|
| var replyTo = _deserializeMessage(msg['replyTo']);
|
| var context = new _IsolateContext();
|
| _globalState.topEventLoop.enqueue(context, () {
|
| - _startIsolate(entryPoint, args, message, isSpawnUri, replyTo);
|
| + _startIsolate(entryPoint, args, message,
|
| + isSpawnUri, startPaused, replyTo);
|
| }, 'worker-start');
|
| // Make sure we always have a current context in this worker.
|
| // TODO(7907): This is currently needed because we're using
|
| @@ -609,7 +613,8 @@ class IsolateNatives {
|
| case 'spawn-worker':
|
| _spawnWorker(msg['functionName'], msg['uri'],
|
| msg['args'], msg['msg'],
|
| - msg['isSpawnUri'], msg['replyPort']);
|
| + msg['isSpawnUri'], msg['startPaused'],
|
| + msg['replyPort']);
|
| break;
|
| case 'message':
|
| SendPort port = msg['port'];
|
| @@ -677,17 +682,24 @@ class IsolateNatives {
|
| }
|
|
|
| static Future<List> spawnFunction(void topLevelFunction(message),
|
| - message) {
|
| + var message,
|
| + bool startPaused) {
|
| final name = _getJSFunctionName(topLevelFunction);
|
| if (name == null) {
|
| throw new UnsupportedError(
|
| "only top-level functions can be spawned.");
|
| }
|
| - return spawn(name, null, null, message, false, false);
|
| + bool isLight = false;
|
| + bool isSpawnUri = false;
|
| + return spawn(name, null, null, message, isLight, isSpawnUri, startPaused);
|
| }
|
|
|
| - static Future<List> spawnUri(Uri uri, List<String> args, message) {
|
| - return spawn(null, uri.toString(), args, message, false, true);
|
| + static Future<List> spawnUri(Uri uri, List<String> args, var message,
|
| + bool startPaused) {
|
| + bool isLight = false;
|
| + bool isSpawnUri = true;
|
| + return spawn(null, uri.toString(), args, message,
|
| + isLight, isSpawnUri, startPaused);
|
| }
|
|
|
| // TODO(sigmund): clean up above, after we make the new API the default:
|
| @@ -695,7 +707,7 @@ class IsolateNatives {
|
| /// If [uri] is `null` it is replaced with the current script.
|
| static Future<List> spawn(String functionName, String uri,
|
| List<String> args, message,
|
| - bool isLight, bool isSpawnUri) {
|
| + bool isLight, bool isSpawnUri, bool startPaused) {
|
| // Assume that the compiled version of the Dart file lives just next to the
|
| // dart file.
|
| // TODO(floitsch): support precompiled version of dart2js output.
|
| @@ -710,10 +722,12 @@ class IsolateNatives {
|
| SendPort signalReply = port.sendPort;
|
|
|
| if (_globalState.useWorkers && !isLight) {
|
| - _startWorker(functionName, uri, args, message, isSpawnUri, signalReply);
|
| + _startWorker(functionName, uri, args, message, isSpawnUri, startPaused,
|
| + signalReply);
|
| } else {
|
| _startNonWorker(
|
| - functionName, uri, args, message, isSpawnUri, signalReply);
|
| + functionName, uri, args, message, isSpawnUri, startPaused,
|
| + signalReply);
|
| }
|
| return result;
|
| }
|
| @@ -722,6 +736,7 @@ class IsolateNatives {
|
| String functionName, String uri,
|
| List<String> args, message,
|
| bool isSpawnUri,
|
| + bool startPaused,
|
| SendPort replyPort) {
|
| if (_globalState.isWorker) {
|
| _globalState.mainManager.postMessage(_serializeMessage({
|
| @@ -731,16 +746,19 @@ class IsolateNatives {
|
| 'msg': message,
|
| 'uri': uri,
|
| 'isSpawnUri': isSpawnUri,
|
| + 'startPaused': startPaused,
|
| 'replyPort': replyPort}));
|
| } else {
|
| - _spawnWorker(functionName, uri, args, message, isSpawnUri, replyPort);
|
| + _spawnWorker(functionName, uri, args, message,
|
| + isSpawnUri, startPaused, replyPort);
|
| }
|
| }
|
|
|
| static void _startNonWorker(
|
| String functionName, String uri,
|
| - List<String> args, message,
|
| + List<String> args, var message,
|
| bool isSpawnUri,
|
| + bool startPaused,
|
| SendPort replyPort) {
|
| // TODO(eub): support IE9 using an iframe -- Dart issue 1702.
|
| if (uri != null) {
|
| @@ -749,13 +767,14 @@ class IsolateNatives {
|
| }
|
| _globalState.topEventLoop.enqueue(new _IsolateContext(), () {
|
| final func = _getJSFunctionFromName(functionName);
|
| - _startIsolate(func, args, message, isSpawnUri, replyPort);
|
| + _startIsolate(func, args, message, isSpawnUri, startPaused, replyPort);
|
| }, 'nonworker start');
|
| }
|
|
|
| static void _startIsolate(Function topLevel,
|
| List<String> args, message,
|
| bool isSpawnUri,
|
| + bool startPaused,
|
| SendPort replyTo) {
|
| _IsolateContext context = JS_CURRENT_ISOLATE_CONTEXT();
|
| Primitives.initializeStatics(context.id);
|
| @@ -763,14 +782,25 @@ class IsolateNatives {
|
| replyTo.send([_SPAWNED_SIGNAL,
|
| context.controlPort.sendPort,
|
| context.pauseCapability]);
|
| - if (!isSpawnUri) {
|
| - topLevel(message);
|
| - } else if (topLevel is _MainFunctionArgsMessage) {
|
| - topLevel(args, message);
|
| - } else if (topLevel is _MainFunctionArgs) {
|
| - topLevel(args);
|
| +
|
| + void runStartFunction() {
|
| + if (!isSpawnUri) {
|
| + topLevel(message);
|
| + } else if (topLevel is _MainFunctionArgsMessage) {
|
| + topLevel(args, message);
|
| + } else if (topLevel is _MainFunctionArgs) {
|
| + topLevel(args);
|
| + } else {
|
| + topLevel();
|
| + }
|
| + }
|
| +
|
| + if (startPaused) {
|
| + context.addPause(context.pauseCapability, context.pauseCapability);
|
| + _globalState.topEventLoop.enqueue(context, runStartFunction,
|
| + 'start isolate');
|
| } else {
|
| - topLevel();
|
| + runStartFunction();
|
| }
|
| }
|
|
|
| @@ -781,6 +811,7 @@ class IsolateNatives {
|
| static void _spawnWorker(functionName, String uri,
|
| List<String> args, message,
|
| bool isSpawnUri,
|
| + bool startPaused,
|
| SendPort replyPort) {
|
| if (uri == null) uri = thisScript;
|
| final worker = JS('var', 'new Worker(#)', uri);
|
| @@ -805,6 +836,7 @@ class IsolateNatives {
|
| 'args': args,
|
| 'msg': _serializeMessage(message),
|
| 'isSpawnUri': isSpawnUri,
|
| + 'startPaused': startPaused,
|
| 'functionName': functionName }));
|
| }
|
| }
|
| @@ -844,7 +876,6 @@ class _NativeJsSendPort extends _BaseSendPort implements SendPort {
|
| final isolate = _globalState.isolates[_isolateId];
|
| if (isolate == null) return;
|
| if (_receivePort._isClosed) return;
|
| -
|
| // We force serialization/deserialization as a simple way to ensure
|
| // isolate communication restrictions are respected between isolates that
|
| // live in the same worker. [_NativeJsSendPort] delivers both messages
|
|
|