| OLD | NEW |
| (Empty) |
| 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | |
| 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. | |
| 4 | |
| 5 library pub.asset.serialize; | |
| 6 | |
| 7 import 'dart:async'; | |
| 8 import 'dart:isolate'; | |
| 9 | |
| 10 import 'package:barback/barback.dart'; | |
| 11 | |
| 12 //# if source_maps >=0.9.0 <0.10.0 | |
| 13 //> import 'package:source_maps/span.dart'; | |
| 14 //# end | |
| 15 | |
| 16 //# if source_span | |
| 17 import 'package:source_span/source_span.dart'; | |
| 18 //# end | |
| 19 | |
| 20 import 'serialize/exception.dart'; | |
| 21 import 'utils.dart'; | |
| 22 | |
| 23 export 'serialize/aggregate_transform.dart'; | |
| 24 export 'serialize/exception.dart'; | |
| 25 export 'serialize/transform.dart'; | |
| 26 export 'serialize/transformer.dart'; | |
| 27 | |
| 28 /// Converts [id] into a serializable map. | |
| 29 Map serializeId(AssetId id) => {'package': id.package, 'path': id.path}; | |
| 30 | |
| 31 /// Converts a serializable map into an [AssetId]. | |
| 32 AssetId deserializeId(Map id) => new AssetId(id['package'], id['path']); | |
| 33 | |
| 34 /// Converts [span] into a serializable map. | |
| 35 /// | |
| 36 /// [span] may be a [SourceSpan] or a [Span]. | |
| 37 Map serializeSpan(span) { | |
| 38 // TODO(nweiz): convert FileSpans to FileSpans. | |
| 39 // Handily, this code works for both source_map and source_span spans. | |
| 40 return { | |
| 41 'sourceUrl': span.sourceUrl.toString(), | |
| 42 'start': serializeLocation(span.start), | |
| 43 'end': serializeLocation(span.end), | |
| 44 'text': span.text, | |
| 45 }; | |
| 46 } | |
| 47 | |
| 48 /// Converts a serializable map into a [SourceSpan]. | |
| 49 SourceSpan deserializeSpan(Map span) { | |
| 50 return new SourceSpan( | |
| 51 deserializeLocation(span['start']), | |
| 52 deserializeLocation(span['end']), | |
| 53 span['text']); | |
| 54 } | |
| 55 | |
| 56 /// Converts [location] into a serializable map. | |
| 57 /// | |
| 58 /// [location] may be a [SourceLocation] or a [SourceLocation]. | |
| 59 Map serializeLocation(location) { | |
| 60 //# if source_maps >=0.9.0 <0.10.0 | |
| 61 //> if (location is Location) { | |
| 62 //> return { | |
| 63 //> 'sourceUrl': location.sourceUrl, | |
| 64 //> 'offset': location.offset, | |
| 65 //> 'line': location.line, | |
| 66 //> 'column': location.column | |
| 67 //> }; | |
| 68 //> } | |
| 69 //# end | |
| 70 | |
| 71 //# if source_span | |
| 72 // TODO(nweiz): convert FileLocations to FileLocations. | |
| 73 if (location is SourceLocation) { | |
| 74 return { | |
| 75 'sourceUrl': location.sourceUrl.toString(), | |
| 76 'offset': location.offset, | |
| 77 'line': location.line, | |
| 78 'column': location.column | |
| 79 }; | |
| 80 } | |
| 81 //# end | |
| 82 | |
| 83 throw new ArgumentError("Unknown type ${location.runtimeType} for location."); | |
| 84 } | |
| 85 | |
| 86 /// Converts a serializable map into a [Location]. | |
| 87 SourceLocation deserializeLocation(Map location) { | |
| 88 return new SourceLocation(location['offset'], | |
| 89 sourceUrl: location['sourceUrl'], | |
| 90 line: location['line'], | |
| 91 column: location['column']); | |
| 92 } | |
| 93 | |
| 94 /// Converts [stream] into a serializable map. | |
| 95 /// | |
| 96 /// [serializeEvent] is used to serialize each event from the stream. | |
| 97 Map serializeStream(Stream stream, serializeEvent(event)) { | |
| 98 var receivePort = new ReceivePort(); | |
| 99 var map = {'replyTo': receivePort.sendPort}; | |
| 100 | |
| 101 receivePort.first.then((message) { | |
| 102 var sendPort = message['replyTo']; | |
| 103 stream.listen((event) { | |
| 104 sendPort.send({ | |
| 105 'type': 'event', | |
| 106 'value': serializeEvent(event) | |
| 107 }); | |
| 108 }, onError: (error, stackTrace) { | |
| 109 sendPort.send({ | |
| 110 'type': 'error', | |
| 111 'error': serializeException(error, stackTrace) | |
| 112 }); | |
| 113 }, onDone: () => sendPort.send({'type': 'done'})); | |
| 114 }); | |
| 115 | |
| 116 return map; | |
| 117 } | |
| 118 | |
| 119 /// Converts a serializable map into a [Stream]. | |
| 120 /// | |
| 121 /// [deserializeEvent] is used to deserialize each event from the stream. | |
| 122 Stream deserializeStream(Map stream, deserializeEvent(event)) { | |
| 123 return callbackStream(() { | |
| 124 var receivePort = new ReceivePort(); | |
| 125 stream['replyTo'].send({'replyTo': receivePort.sendPort}); | |
| 126 | |
| 127 var controller = new StreamController(sync: true); | |
| 128 receivePort.listen((event) { | |
| 129 switch (event['type']) { | |
| 130 case 'event': | |
| 131 controller.add(deserializeEvent(event['value'])); | |
| 132 break; | |
| 133 case 'error': | |
| 134 var exception = deserializeException(event['error']); | |
| 135 controller.addError(exception, exception.stackTrace); | |
| 136 break; | |
| 137 case 'done': | |
| 138 controller.close(); | |
| 139 receivePort.close(); | |
| 140 break; | |
| 141 } | |
| 142 }); | |
| 143 | |
| 144 return controller.stream; | |
| 145 }); | |
| 146 } | |
| 147 | |
| 148 /// Wraps [message] and sends it across [port], then waits for a response which | |
| 149 /// should be sent using [respond]. | |
| 150 /// | |
| 151 /// The returned Future will complete to the value or error returned by | |
| 152 /// [respond]. | |
| 153 Future call(SendPort port, message) { | |
| 154 var receivePort = new ReceivePort(); | |
| 155 port.send({ | |
| 156 'message': message, | |
| 157 'replyTo': receivePort.sendPort | |
| 158 }); | |
| 159 | |
| 160 return receivePort.first.then((response) { | |
| 161 if (response['type'] == 'success') return response['value']; | |
| 162 assert(response['type'] == 'error'); | |
| 163 var exception = deserializeException(response['error']); | |
| 164 return new Future.error(exception, exception.stackTrace); | |
| 165 }); | |
| 166 } | |
| 167 | |
| 168 /// Responds to a message sent by [call]. | |
| 169 /// | |
| 170 /// [wrappedMessage] is the raw message sent by [call]. This unwraps it and | |
| 171 /// passes the contents of the message to [callback], then sends the return | |
| 172 /// value of [callback] back to [call]. If [callback] returns a Future or | |
| 173 /// throws an error, that will also be sent. | |
| 174 void respond(wrappedMessage, callback(message)) { | |
| 175 var replyTo = wrappedMessage['replyTo']; | |
| 176 new Future.sync(() => callback(wrappedMessage['message'])) | |
| 177 .then((result) => replyTo.send({'type': 'success', 'value': result})) | |
| 178 .catchError((error, stackTrace) { | |
| 179 replyTo.send({ | |
| 180 'type': 'error', | |
| 181 'error': serializeException(error, stackTrace) | |
| 182 }); | |
| 183 }); | |
| 184 } | |
| OLD | NEW |