| OLD | NEW | 
 | (Empty) | 
|    1 // Copyright (c) 2011, 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 class MessageTraverser { |  | 
|    6   static bool isPrimitive(x) { |  | 
|    7     return (x === null) || (x is String) || (x is num) || (x is bool); |  | 
|    8   } |  | 
|    9  |  | 
|   10   MessageTraverser(); |  | 
|   11  |  | 
|   12   traverse(var x) { |  | 
|   13     if (isPrimitive(x)) return visitPrimitive(x); |  | 
|   14     _taggedObjects = new List(); |  | 
|   15     var result; |  | 
|   16     try { |  | 
|   17       result = _dispatch(x); |  | 
|   18     } finally { |  | 
|   19       _cleanup(); |  | 
|   20     } |  | 
|   21     return result; |  | 
|   22   } |  | 
|   23  |  | 
|   24   void _cleanup() { |  | 
|   25     int len = _taggedObjects.length; |  | 
|   26     for (int i = 0; i < len; i++) { |  | 
|   27       _clearAttachedInfo(_taggedObjects[i]); |  | 
|   28     } |  | 
|   29     _taggedObjects = null; |  | 
|   30   } |  | 
|   31  |  | 
|   32   void _attachInfo(var o, var info) { |  | 
|   33     _taggedObjects.add(o); |  | 
|   34     _setAttachedInfo(o, info); |  | 
|   35   } |  | 
|   36  |  | 
|   37   _getInfo(var o) { |  | 
|   38     return _getAttachedInfo(o); |  | 
|   39   } |  | 
|   40  |  | 
|   41   _dispatch(var x) { |  | 
|   42     if (isPrimitive(x)) return visitPrimitive(x); |  | 
|   43     if (x is List) return visitList(x); |  | 
|   44     if (x is Map) return visitMap(x); |  | 
|   45     if (x is SendPortImpl) return visitSendPort(x); |  | 
|   46     if (x is ReceivePortImpl) return visitReceivePort(x); |  | 
|   47     if (x is ReceivePortSingleShotImpl) return visitReceivePortSingleShot(x); |  | 
|   48     // TODO(floitsch): make this a real exception. (which one)? |  | 
|   49     throw new Exception("Message serialization: Illegal value $x passed"); |  | 
|   50   } |  | 
|   51  |  | 
|   52   abstract visitPrimitive(x); |  | 
|   53   abstract visitList(List x); |  | 
|   54   abstract visitMap(Map x); |  | 
|   55   abstract visitSendPort(SendPortImpl x); |  | 
|   56   abstract visitReceivePort(ReceivePortImpl x); |  | 
|   57   abstract visitReceivePortSingleShot(ReceivePortSingleShotImpl x); |  | 
|   58  |  | 
|   59   List _taggedObjects; |  | 
|   60  |  | 
|   61   _clearAttachedInfo(var obj) native; |  | 
|   62   _setAttachedInfo(var o, var info) native; |  | 
|   63   _getAttachedInfo(var o) native; |  | 
|   64 } |  | 
|   65  |  | 
|   66 class Copier extends MessageTraverser { |  | 
|   67   Copier() : super(); |  | 
|   68  |  | 
|   69   visitPrimitive(x) => x; |  | 
|   70  |  | 
|   71   List visitList(List list) { |  | 
|   72     List copy = _getInfo(list); |  | 
|   73     if (copy !== null) return copy; |  | 
|   74  |  | 
|   75     int len = list.length; |  | 
|   76     // TODO(floitsch): we loose the generic type of the List. |  | 
|   77     copy = new List(len); |  | 
|   78     _attachInfo(list, copy); |  | 
|   79     for (int i = 0; i < len; i++) { |  | 
|   80       copy[i] = _dispatch(list[i]); |  | 
|   81     } |  | 
|   82     return copy; |  | 
|   83   } |  | 
|   84  |  | 
|   85   Map visitMap(Map map) { |  | 
|   86     Map copy = _getInfo(map); |  | 
|   87     if (copy !== null) return copy; |  | 
|   88  |  | 
|   89     // TODO(floitsch): we loose the generic type of the map. |  | 
|   90     copy = new Map(); |  | 
|   91     _attachInfo(map, copy); |  | 
|   92     map.forEach((key, val) { |  | 
|   93       copy[_dispatch(key)] = _dispatch(val); |  | 
|   94     }); |  | 
|   95     return copy; |  | 
|   96   } |  | 
|   97  |  | 
|   98   SendPort visitSendPort(SendPortImpl port) { |  | 
|   99     return new SendPortImpl(port._workerId, |  | 
|  100                             port._isolateId, |  | 
|  101                             port._receivePortId); |  | 
|  102   } |  | 
|  103  |  | 
|  104   SendPort visitReceivePort(ReceivePortImpl port) { |  | 
|  105     return port._toNewSendPort(); |  | 
|  106   } |  | 
|  107  |  | 
|  108   SendPort visitReceivePortSingleShot(ReceivePortSingleShotImpl port) { |  | 
|  109     return port._toNewSendPort(); |  | 
|  110   } |  | 
|  111 } |  | 
|  112  |  | 
|  113 class Serializer extends MessageTraverser { |  | 
|  114   Serializer() : super(); |  | 
|  115  |  | 
|  116   visitPrimitive(x) => x; |  | 
|  117  |  | 
|  118   visitList(List list) { |  | 
|  119     int copyId = _getInfo(list); |  | 
|  120     if (copyId !== null) return _makeRef(copyId); |  | 
|  121  |  | 
|  122     int id = _nextFreeRefId++; |  | 
|  123     _attachInfo(list, id); |  | 
|  124     var jsArray = _serializeDartListIntoNewJsArray(list); |  | 
|  125     // TODO(floitsch): we are losing the generic type. |  | 
|  126     return _dartListToJsArrayNoCopy(['list', id, jsArray]); |  | 
|  127   } |  | 
|  128  |  | 
|  129   visitMap(Map map) { |  | 
|  130     int copyId = _getInfo(map); |  | 
|  131     if (copyId !== null) return _makeRef(copyId); |  | 
|  132  |  | 
|  133     int id = _nextFreeRefId++; |  | 
|  134     _attachInfo(map, id); |  | 
|  135     var keys = _serializeDartListIntoNewJsArray(map.getKeys()); |  | 
|  136     var values = _serializeDartListIntoNewJsArray(map.getValues()); |  | 
|  137     // TODO(floitsch): we are losing the generic type. |  | 
|  138     return _dartListToJsArrayNoCopy(['map', id, keys, values]); |  | 
|  139   } |  | 
|  140  |  | 
|  141   visitSendPort(SendPortImpl port) { |  | 
|  142     return _dartListToJsArrayNoCopy(['sendport', |  | 
|  143                                      port._workerId, |  | 
|  144                                      port._isolateId, |  | 
|  145                                      port._receivePortId]); |  | 
|  146   } |  | 
|  147  |  | 
|  148   visitReceivePort(ReceivePortImpl port) { |  | 
|  149     return visitSendPort(port.toSendPort());; |  | 
|  150   } |  | 
|  151  |  | 
|  152   visitReceivePortSingleShot(ReceivePortSingleShotImpl port) { |  | 
|  153     return visitSendPort(port.toSendPort()); |  | 
|  154   } |  | 
|  155  |  | 
|  156   _serializeDartListIntoNewJsArray(List list) { |  | 
|  157     int len = list.length; |  | 
|  158     var jsArray = _newJsArray(len); |  | 
|  159     for (int i = 0; i < len; i++) { |  | 
|  160       _jsArrayIndexSet(jsArray, i, _dispatch(list[i])); |  | 
|  161     } |  | 
|  162     return jsArray; |  | 
|  163   } |  | 
|  164  |  | 
|  165   _makeRef(int id) { |  | 
|  166     return _dartListToJsArrayNoCopy(['ref', id]); |  | 
|  167   } |  | 
|  168  |  | 
|  169   int _nextFreeRefId = 0; |  | 
|  170  |  | 
|  171   static _newJsArray(int len) native; |  | 
|  172   static _jsArrayIndexSet(jsArray, int index, val) native; |  | 
|  173   static _dartListToJsArrayNoCopy(List list) native; |  | 
|  174 } |  | 
|  175  |  | 
|  176 class Deserializer { |  | 
|  177   Deserializer(); |  | 
|  178  |  | 
|  179   static bool isPrimitive(x) { |  | 
|  180     return (x === null) || (x is String) || (x is num) || (x is bool); |  | 
|  181   } |  | 
|  182  |  | 
|  183   deserialize(x) { |  | 
|  184     if (isPrimitive(x)) return x; |  | 
|  185     // TODO(floitsch): this should be new HashMap<int, var|Dynamic>() |  | 
|  186     _deserialized = new HashMap(); |  | 
|  187     return _deserializeHelper(x); |  | 
|  188   } |  | 
|  189  |  | 
|  190   _deserializeHelper(x) { |  | 
|  191     if (isPrimitive(x)) return x; |  | 
|  192     assert(_isJsArray(x)); |  | 
|  193     switch (_jsArrayIndex(x, 0)) { |  | 
|  194       case 'ref': return _deserializeRef(x); |  | 
|  195       case 'list': return _deserializeList(x); |  | 
|  196       case 'map': return _deserializeMap(x); |  | 
|  197       case 'sendport': return _deserializeSendPort(x); |  | 
|  198       // TODO(floitsch): Use real exception (which one?). |  | 
|  199       default: throw "Unexpected serialized object"; |  | 
|  200     } |  | 
|  201   } |  | 
|  202  |  | 
|  203   _deserializeRef(x) { |  | 
|  204     int id = _jsArrayIndex(x, 1); |  | 
|  205     var result = _deserialized[id]; |  | 
|  206     assert(result !== null); |  | 
|  207     return result; |  | 
|  208   } |  | 
|  209  |  | 
|  210   List _deserializeList(x) { |  | 
|  211     int id = _jsArrayIndex(x, 1); |  | 
|  212     var jsArray = _jsArrayIndex(x, 2); |  | 
|  213     assert(_isJsArray(jsArray)); |  | 
|  214     List dartList = _jsArrayToDartListNoCopy(jsArray); |  | 
|  215     _deserialized[id] = dartList; |  | 
|  216     int len = dartList.length; |  | 
|  217     for (int i = 0; i < len; i++) { |  | 
|  218       dartList[i] = _deserializeHelper(dartList[i]); |  | 
|  219     } |  | 
|  220     return dartList; |  | 
|  221   } |  | 
|  222  |  | 
|  223   Map _deserializeMap(x) { |  | 
|  224     Map result = new Map(); |  | 
|  225     int id = _jsArrayIndex(x, 1); |  | 
|  226     _deserialized[id] = result; |  | 
|  227     var keys = _jsArrayIndex(x, 2); |  | 
|  228     var values = _jsArrayIndex(x, 3); |  | 
|  229     assert(_isJsArray(keys)); |  | 
|  230     assert(_isJsArray(values)); |  | 
|  231     int len = _jsArrayLength(keys); |  | 
|  232     assert(len == _jsArrayLength(values)); |  | 
|  233     for (int i = 0; i < len; i++) { |  | 
|  234       var key = _deserializeHelper(_jsArrayIndex(keys, i)); |  | 
|  235       var value = _deserializeHelper(_jsArrayIndex(values, i)); |  | 
|  236       result[key] = value; |  | 
|  237     } |  | 
|  238     return result; |  | 
|  239   } |  | 
|  240  |  | 
|  241   SendPort _deserializeSendPort(x) { |  | 
|  242     int workerId = _jsArrayIndex(x, 1); |  | 
|  243     int isolateId = _jsArrayIndex(x, 2); |  | 
|  244     int receivePortId = _jsArrayIndex(x, 3); |  | 
|  245     return new SendPortImpl(workerId, isolateId, receivePortId); |  | 
|  246   } |  | 
|  247  |  | 
|  248   List _jsArrayToDartListNoCopy(a) { |  | 
|  249     // We rely on the fact that Dart-lists are directly mapped to Js-arrays. |  | 
|  250     // TODO(floitsch): can we do better here? |  | 
|  251     assert(a is List); |  | 
|  252     return a; |  | 
|  253   } |  | 
|  254  |  | 
|  255   // TODO(floitsch): this should by Map<int, var> or Map<int, Dynamic>. |  | 
|  256   Map _deserialized; |  | 
|  257  |  | 
|  258   static bool _isJsArray(x) native; |  | 
|  259   static _jsArrayIndex(x, int index) native; |  | 
|  260   static int _jsArrayLength(x) native; |  | 
|  261 } |  | 
| OLD | NEW |