9484ac8bdf
BUG= R=vsm@google.com Review-Url: https://codereview.chromium.org/2752163002 .
243 lines
6.9 KiB
Dart
243 lines
6.9 KiB
Dart
// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
|
|
// for details. All rights reserved. Use of this source code is governed by a
|
|
// BSD-style license that can be found in the LICENSE file.
|
|
|
|
// Patch file for the dart:isolate library.
|
|
|
|
import 'dart:_js_helper' show patch;
|
|
import 'dart:_isolate_helper'
|
|
show CapabilityImpl, IsolateNatives, ReceivePortImpl, RawReceivePortImpl;
|
|
|
|
typedef _UnaryFunction(arg);
|
|
|
|
@patch
|
|
class Isolate {
|
|
static final _currentIsolateCache = IsolateNatives.currentIsolate;
|
|
|
|
// `current` must be a getter, not just a final field,
|
|
// to match the external declaration.
|
|
@patch
|
|
static Isolate get current => _currentIsolateCache;
|
|
|
|
@patch
|
|
static Future<Uri> get packageRoot {
|
|
throw new UnsupportedError("Isolate.packageRoot");
|
|
}
|
|
|
|
@patch
|
|
static Future<Uri> get packageConfig {
|
|
throw new UnsupportedError("Isolate.packageConfig");
|
|
}
|
|
|
|
static Uri _packageBase = Uri.base.resolve(IsolateNatives.packagesBase);
|
|
|
|
@patch
|
|
static Future<Uri> resolvePackageUri(Uri packageUri) async {
|
|
if (packageUri.scheme != 'package') return packageUri;
|
|
return _packageBase.resolveUri(packageUri.replace(scheme: ''));
|
|
}
|
|
|
|
@patch
|
|
static Future<Isolate> spawn(void entryPoint(message), var message,
|
|
{bool paused: false,
|
|
bool errorsAreFatal,
|
|
SendPort onExit,
|
|
SendPort onError}) {
|
|
bool forcePause =
|
|
(errorsAreFatal != null) || (onExit != null) || (onError != null);
|
|
try {
|
|
// Check for the type of `entryPoint` on the spawning isolate to make
|
|
// error-handling easier.
|
|
if (entryPoint is! _UnaryFunction) {
|
|
throw new ArgumentError(entryPoint);
|
|
}
|
|
// TODO: Consider passing the errorsAreFatal/onExit/onError values
|
|
// as arguments to the internal spawnUri instead of setting
|
|
// them after the isolate has been created.
|
|
return IsolateNatives
|
|
.spawnFunction(entryPoint, message, paused || forcePause)
|
|
.then((msg) {
|
|
var isolate = new Isolate(msg[1],
|
|
pauseCapability: msg[2], terminateCapability: msg[3]);
|
|
if (forcePause) {
|
|
if (errorsAreFatal != null) {
|
|
isolate.setErrorsFatal(errorsAreFatal);
|
|
}
|
|
if (onExit != null) {
|
|
isolate.addOnExitListener(onExit);
|
|
}
|
|
if (onError != null) {
|
|
isolate.addErrorListener(onError);
|
|
}
|
|
if (!paused) {
|
|
isolate.resume(isolate.pauseCapability);
|
|
}
|
|
}
|
|
return isolate;
|
|
});
|
|
} catch (e, st) {
|
|
return new Future<Isolate>.error(e, st);
|
|
}
|
|
}
|
|
|
|
@patch
|
|
static Future<Isolate> spawnUri(Uri uri, List<String> args, var message,
|
|
{bool paused: false,
|
|
SendPort onExit,
|
|
SendPort onError,
|
|
bool errorsAreFatal,
|
|
bool checked,
|
|
Map<String, String> environment,
|
|
Uri packageRoot,
|
|
Uri packageConfig,
|
|
bool automaticPackageResolution: false}) {
|
|
if (environment != null) throw new UnimplementedError("environment");
|
|
if (packageRoot != null) throw new UnimplementedError("packageRoot");
|
|
if (packageConfig != null) throw new UnimplementedError("packageConfig");
|
|
// TODO(lrn): Figure out how to handle the automaticPackageResolution
|
|
// parameter.
|
|
bool forcePause =
|
|
(errorsAreFatal != null) || (onExit != null) || (onError != null);
|
|
try {
|
|
if (args is List<String>) {
|
|
for (int i = 0; i < args.length; i++) {
|
|
if (args[i] is! String) {
|
|
throw new ArgumentError("Args must be a list of Strings $args");
|
|
}
|
|
}
|
|
} else if (args != null) {
|
|
throw new ArgumentError("Args must be a list of Strings $args");
|
|
}
|
|
// TODO: Handle [packageRoot] somehow, possibly by throwing.
|
|
// TODO: Consider passing the errorsAreFatal/onExit/onError values
|
|
// as arguments to the internal spawnUri instead of setting
|
|
// them after the isolate has been created.
|
|
return IsolateNatives
|
|
.spawnUri(uri, args, message, paused || forcePause)
|
|
.then((msg) {
|
|
var isolate = new Isolate(msg[1],
|
|
pauseCapability: msg[2], terminateCapability: msg[3]);
|
|
if (forcePause) {
|
|
if (errorsAreFatal != null) {
|
|
isolate.setErrorsFatal(errorsAreFatal);
|
|
}
|
|
if (onExit != null) {
|
|
isolate.addOnExitListener(onExit);
|
|
}
|
|
if (onError != null) {
|
|
isolate.addErrorListener(onError);
|
|
}
|
|
if (!paused) {
|
|
isolate.resume(isolate.pauseCapability);
|
|
}
|
|
}
|
|
return isolate;
|
|
});
|
|
} catch (e, st) {
|
|
return new Future<Isolate>.error(e, st);
|
|
}
|
|
}
|
|
|
|
@patch
|
|
void _pause(Capability resumeCapability) {
|
|
var message = new List(3)
|
|
..[0] = "pause"
|
|
..[1] = pauseCapability
|
|
..[2] = resumeCapability;
|
|
controlPort.send(message);
|
|
}
|
|
|
|
@patch
|
|
void resume(Capability resumeCapability) {
|
|
var message = new List(2)
|
|
..[0] = "resume"
|
|
..[1] = resumeCapability;
|
|
controlPort.send(message);
|
|
}
|
|
|
|
@patch
|
|
void addOnExitListener(SendPort responsePort, {Object response}) {
|
|
// TODO(lrn): Can we have an internal method that checks if the receiving
|
|
// isolate of a SendPort is still alive?
|
|
var message = new List(3)
|
|
..[0] = "add-ondone"
|
|
..[1] = responsePort
|
|
..[2] = response;
|
|
controlPort.send(message);
|
|
}
|
|
|
|
@patch
|
|
void removeOnExitListener(SendPort responsePort) {
|
|
var message = new List(2)
|
|
..[0] = "remove-ondone"
|
|
..[1] = responsePort;
|
|
controlPort.send(message);
|
|
}
|
|
|
|
@patch
|
|
void setErrorsFatal(bool errorsAreFatal) {
|
|
var message = new List(3)
|
|
..[0] = "set-errors-fatal"
|
|
..[1] = terminateCapability
|
|
..[2] = errorsAreFatal;
|
|
controlPort.send(message);
|
|
}
|
|
|
|
@patch
|
|
void kill({int priority: BEFORE_NEXT_EVENT}) {
|
|
controlPort.send(["kill", terminateCapability, priority]);
|
|
}
|
|
|
|
@patch
|
|
void ping(SendPort responsePort, {Object response, int priority: IMMEDIATE}) {
|
|
var message = new List(4)
|
|
..[0] = "ping"
|
|
..[1] = responsePort
|
|
..[2] = priority
|
|
..[3] = response;
|
|
controlPort.send(message);
|
|
}
|
|
|
|
@patch
|
|
void addErrorListener(SendPort port) {
|
|
var message = new List(2)
|
|
..[0] = "getErrors"
|
|
..[1] = port;
|
|
controlPort.send(message);
|
|
}
|
|
|
|
@patch
|
|
void removeErrorListener(SendPort port) {
|
|
var message = new List(2)
|
|
..[0] = "stopErrors"
|
|
..[1] = port;
|
|
controlPort.send(message);
|
|
}
|
|
}
|
|
|
|
/** Default factory for receive ports. */
|
|
@patch
|
|
class ReceivePort {
|
|
@patch
|
|
factory ReceivePort() = ReceivePortImpl;
|
|
|
|
@patch
|
|
factory ReceivePort.fromRawReceivePort(RawReceivePort rawPort) {
|
|
return new ReceivePortImpl.fromRawReceivePort(rawPort);
|
|
}
|
|
}
|
|
|
|
@patch
|
|
class RawReceivePort {
|
|
@patch
|
|
factory RawReceivePort([void handler(event)]) {
|
|
return new RawReceivePortImpl(handler);
|
|
}
|
|
}
|
|
|
|
@patch
|
|
class Capability {
|
|
@patch
|
|
factory Capability() = CapabilityImpl;
|
|
}
|