Chromium Code Reviews| Index: sdk/lib/_internal/pub/asset/dart/transformer_isolate.dart |
| diff --git a/sdk/lib/_internal/pub/lib/src/barback/load_transformers.dart b/sdk/lib/_internal/pub/asset/dart/transformer_isolate.dart |
| similarity index 56% |
| copy from sdk/lib/_internal/pub/lib/src/barback/load_transformers.dart |
| copy to sdk/lib/_internal/pub/asset/dart/transformer_isolate.dart |
| index e385ef34a2c0b47ffbaec04fa4c09887f1d8d266..cbc93b388af2c42575353d62510ed275329ad2fb 100644 |
| --- a/sdk/lib/_internal/pub/lib/src/barback/load_transformers.dart |
| +++ b/sdk/lib/_internal/pub/asset/dart/transformer_isolate.dart |
| @@ -1,33 +1,11 @@ |
| -// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
| +// Copyright (c) 2014, 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. |
| -library pub.load_transformers; |
| +// Explicitly avoid using a library tag because pub will add additional imports |
|
Bob Nystrom
2014/03/17 21:16:07
Wording this as an imperative sentence seems a bit
nweiz
2014/03/17 22:20:40
Done.
|
| +// at the top of the file. |
| import 'dart:async'; |
| -import 'dart:convert'; |
| -import 'dart:isolate'; |
| - |
| -import 'package:barback/barback.dart'; |
| -// TODO(nweiz): don't import from "src" once issue 14966 is fixed. |
| -import 'package:barback/src/internal_asset.dart'; |
| -import 'package:source_maps/source_maps.dart'; |
| -import 'package:stack_trace/stack_trace.dart'; |
| - |
| -import '../barback.dart'; |
| -import '../dart.dart' as dart; |
| -import '../log.dart' as log; |
| -import '../utils.dart'; |
| -import 'build_environment.dart'; |
| -import 'excluding_transformer.dart'; |
| -import 'server.dart'; |
| - |
| -/// A Dart script to run in an isolate. |
| -/// |
| -/// This script serializes one or more transformers defined in a Dart library |
| -/// and marshals calls to and from them with the host isolate. |
| -const _TRANSFORMER_ISOLATE = """ |
| -import 'dart:async'; |
| import 'dart:isolate'; |
| import 'dart:convert'; |
| import 'dart:mirrors'; |
| @@ -144,8 +122,8 @@ ClassMirror get objectMirror => reflectClass(Object); |
| // TODO(nweiz): clean this up when issue 13248 is fixed. |
| MethodMirror getConstructor(ClassMirror classMirror, String constructor) { |
| - var name = new Symbol("\${MirrorSystem.getName(classMirror.simpleName)}" |
| - ".\$constructor"); |
| + var name = new Symbol("${MirrorSystem.getName(classMirror.simpleName)}" |
| + ".$constructor"); |
| var candidate = classMirror.declarations[name]; |
| if (candidate is MethodMirror && candidate.isConstructor) return candidate; |
| return null; |
| @@ -314,16 +292,15 @@ class CrossIsolateException implements Exception { |
| }; |
| } |
| - String toString() => "\$message\\n\$stackTrace"; |
| + String toString() => "$message\n$stackTrace"; |
| } |
| /// An [AssetNotFoundException] that was originally raised in another isolate. |
| class _CrossIsolateAssetNotFoundException extends CrossIsolateException |
| implements AssetNotFoundException { |
| - final TransformInfo transform; |
| final AssetId id; |
| - String get message => "Could not find asset \$id."; |
| + String get message => "Could not find asset $id."; |
| /// Loads a [_CrossIsolateAssetNotFoundException] from a serialized |
| /// representation. |
| @@ -411,264 +388,3 @@ Stream callbackStream(Stream callback()) { |
| sync: true); |
| return controller.stream; |
| } |
| -"""; |
| - |
| -/// Load and return all transformers and groups from the library identified by |
| -/// [id]. |
| -Future<Set> loadTransformers(BuildEnvironment environment, |
| - BarbackServer transformerServer, TransformerId id) { |
| - return id.getAssetId(environment.barback).then((assetId) { |
| - var path = assetId.path.replaceFirst('lib/', ''); |
| - // TODO(nweiz): load from a "package:" URI when issue 12474 is fixed. |
| - |
| - var baseUrl = transformerServer.url; |
| - var uri = '$baseUrl/packages/${id.package}/$path'; |
| - var code = 'import "$uri";\n' + |
| - _TRANSFORMER_ISOLATE.replaceAll('<<URL_BASE>>', baseUrl); |
| - log.fine("Loading transformers from $assetId"); |
| - |
| - var port = new ReceivePort(); |
| - return dart.runInIsolate(code, port.sendPort) |
| - .then((_) => port.first) |
| - .then((sendPort) { |
| - return _call(sendPort, { |
| - 'library': uri, |
| - 'mode': environment.mode.name, |
| - // TODO(nweiz): support non-JSON-encodable configuration maps. |
| - 'configuration': JSON.encode(id.configuration) |
| - }).then((transformers) { |
| - transformers = transformers.map( |
| - (transformer) => _deserializeTransformerOrGroup(transformer, id)) |
| - .toSet(); |
| - log.fine("Transformers from $assetId: $transformers"); |
| - return transformers; |
| - }); |
| - }).catchError((error, stackTrace) { |
| - if (error is! dart.CrossIsolateException) throw error; |
| - if (error.type != 'IsolateSpawnException') throw error; |
| - // TODO(nweiz): don't parse this as a string once issues 12617 and 12689 |
| - // are fixed. |
| - if (!error.message.split('\n')[1].startsWith('import "$uri";')) { |
| - throw error; |
| - } |
| - |
| - // If there was an IsolateSpawnException and the import that actually |
| - // failed was the one we were loading transformers from, throw an |
| - // application exception with a more user-friendly message. |
| - fail('Transformer library "package:${id.package}/$path" not found.', |
| - error, stackTrace); |
| - }); |
| - }); |
| -} |
| - |
| -/// A wrapper for a transformer that's in a different isolate. |
| -class _ForeignTransformer extends Transformer { |
| - /// The port with which we communicate with the child isolate. |
| - /// |
| - /// This port and all messages sent across it are specific to this |
| - /// transformer. |
| - final SendPort _port; |
| - |
| - /// The result of calling [toString] on the transformer in the isolate. |
| - final String _toString; |
| - |
| - _ForeignTransformer(Map map) |
| - : _port = map['port'], |
| - _toString = map['toString']; |
| - |
| - Future<bool> isPrimary(Asset asset) { |
| - return _call(_port, { |
| - 'type': 'isPrimary', |
| - 'asset': serializeAsset(asset) |
| - }); |
| - } |
| - |
| - Future apply(Transform transform) { |
| - return _call(_port, { |
| - 'type': 'apply', |
| - 'transform': _serializeTransform(transform) |
| - }); |
| - } |
| - |
| - String toString() => _toString; |
| -} |
| - |
| -/// A wrapper for a transformer group that's in a different isolate. |
| -class _ForeignGroup implements TransformerGroup { |
| - final Iterable<Iterable> phases; |
| - |
| - /// The result of calling [toString] on the transformer group in the isolate. |
| - final String _toString; |
| - |
| - _ForeignGroup(TransformerId id, Map map) |
| - : phases = map['phases'].map((phase) { |
| - return phase.map((transformer) => _deserializeTransformerOrGroup( |
| - transformer, id)).toList(); |
| - }).toList(), |
| - _toString = map['toString']; |
| - |
| - String toString() => _toString; |
| -} |
| - |
| -/// Converts a serializable map into a [Transformer] or a [TransformerGroup]. |
| -_deserializeTransformerOrGroup(Map map, TransformerId id) { |
| - if (map['type'] == 'Transformer') { |
| - var transformer = new _ForeignTransformer(map); |
| - return ExcludingTransformer.wrap(transformer, id.includes, id.excludes); |
| - } |
| - |
| - assert(map['type'] == 'TransformerGroup'); |
| - return new _ForeignGroup(id, map); |
| -} |
| - |
| -/// Converts [transform] into a serializable map. |
| -Map _serializeTransform(Transform transform) { |
| - var receivePort = new ReceivePort(); |
| - receivePort.listen((wrappedMessage) { |
| - _respond(wrappedMessage, (message) { |
| - if (message['type'] == 'getInput') { |
| - return transform.getInput(_deserializeId(message['id'])) |
| - .then((asset) => serializeAsset(asset)); |
| - } |
| - |
| - if (message['type'] == 'addOutput') { |
| - transform.addOutput(deserializeAsset(message['output'])); |
| - return null; |
| - } |
| - |
| - assert(message['type'] == 'log'); |
| - var method; |
| - if (message['level'] == 'Info') { |
| - method = transform.logger.info; |
| - } else if (message['level'] == 'Fine') { |
| - method = transform.logger.fine; |
| - } else if (message['level'] == 'Warning') { |
| - method = transform.logger.warning; |
| - } else { |
| - assert(message['level'] == 'Error'); |
| - method = transform.logger.error; |
| - } |
| - |
| - var assetId = message['assetId'] == null ? null : |
| - _deserializeId(message['assetId']); |
| - var span = message['span'] == null ? null : |
| - _deserializeSpan(message['span']); |
| - method(message['message'], asset: assetId, span: span); |
| - }); |
| - }); |
| - |
| - return { |
| - 'port': receivePort.sendPort, |
| - 'primaryInput': serializeAsset(transform.primaryInput) |
| - }; |
| -} |
| - |
| -/// Converts a serializable map into an [AssetId]. |
| -AssetId _deserializeId(Map id) => new AssetId(id['package'], id['path']); |
| - |
| -/// Converts a serializable map into a [Span]. |
| -Span _deserializeSpan(Map span) { |
| - assert(span['type'] == 'fixed'); |
| - var location = _deserializeLocation(span['start']); |
| - return new FixedSpan(span['sourceUrl'], location.offset, location.line, |
| - location.column, text: span['text'], isIdentifier: span['isIdentifier']); |
| -} |
| - |
| -/// Converts a serializable map into a [Location]. |
| -Location _deserializeLocation(Map location) { |
| - assert(location['type'] == 'fixed'); |
| - return new FixedLocation(location['offset'], location['sourceUrl'], |
| - location['line'], location['column']); |
| -} |
| - |
| -/// Converts [id] into a serializable map. |
| -Map _serializeId(AssetId id) => {'package': id.package, 'path': id.path}; |
| - |
| -/// Responds to a message sent by [_call]. |
| -/// |
| -/// [wrappedMessage] is the raw message sent by [_call]. This unwraps it and |
| -/// passes the contents of the message to [callback], then sends the return |
| -/// value of [callback] back to [_call]. If [callback] returns a Future or |
| -/// throws an error, that will also be sent. |
| -void _respond(wrappedMessage, callback(message)) { |
| - var replyTo = wrappedMessage['replyTo']; |
| - syncFuture(() => callback(wrappedMessage['message'])) |
| - .then((result) => replyTo.send({'type': 'success', 'value': result})) |
| - .catchError((error, stackTrace) { |
| - replyTo.send({ |
| - 'type': 'error', |
| - 'error': _serializeException(error, stackTrace) |
| - }); |
| - }); |
| -} |
| - |
| -/// Wraps [message] and sends it across [port], then waits for a response which |
| -/// should be sent using [_respond]. |
| -/// |
| -/// The returned Future will complete to the value or error returned by |
| -/// [_respond]. |
| -Future _call(SendPort port, message) { |
| - var receivePort = new ReceivePort(); |
| - port.send({ |
| - 'message': message, |
| - 'replyTo': receivePort.sendPort |
| - }); |
| - |
| - return Chain.track(receivePort.first).then((response) { |
| - if (response['type'] == 'success') return response['value']; |
| - assert(response['type'] == 'error'); |
| - var exception = _deserializeException(response['error']); |
| - return new Future.error(exception, exception.stackTrace); |
| - }); |
| -} |
| - |
| -/// An [AssetNotFoundException] that was originally raised in another isolate. |
| -class _CrossIsolateAssetNotFoundException extends dart.CrossIsolateException |
| - implements AssetNotFoundException { |
| - final AssetId id; |
| - |
| - String get message => "Could not find asset $id."; |
| - |
| - /// Loads a [_CrossIsolateAssetNotFoundException] from a serialized |
| - /// representation. |
| - /// |
| - /// [error] should be the result of |
| - /// [_CrossIsolateAssetNotFoundException.serialize]. |
| - _CrossIsolateAssetNotFoundException.deserialize(Map error) |
| - : id = new AssetId(error['package'], error['path']), |
| - super.deserialize(error); |
| - |
| - /// Serializes [error] to an object that can safely be passed across isolate |
| - /// boundaries. |
| - static Map serialize(AssetNotFoundException error, [StackTrace stack]) { |
| - var map = dart.CrossIsolateException.serialize(error); |
| - map['package'] = error.id.package; |
| - map['path'] = error.id.path; |
| - return map; |
| - } |
| -} |
| - |
| -/// Serializes [error] to an object that can safely be passed across isolate |
| -/// boundaries. |
| -/// |
| -/// This handles [AssetNotFoundException]s specially, ensuring that their |
| -/// metadata is preserved. |
| -Map _serializeException(error, [StackTrace stack]) { |
| - if (error is AssetNotFoundException) { |
| - return _CrossIsolateAssetNotFoundException.serialize(error, stack); |
| - } else { |
| - return dart.CrossIsolateException.serialize(error, stack); |
| - } |
| -} |
| - |
| -/// Loads an exception from a serialized representation. |
| -/// |
| -/// This handles [AssetNotFoundException]s specially, ensuring that their |
| -/// metadata is preserved. |
| -dart.CrossIsolateException _deserializeException(Map error) { |
| - if (error['type'] == 'AssetNotFoundException') { |
| - return new _CrossIsolateAssetNotFoundException.deserialize(error); |
| - } else { |
| - return new dart.CrossIsolateException.deserialize(error); |
| - } |
| -} |