| OLD | NEW |
| 1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 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. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 library dart2js.serialization; | 5 library dart2js.serialization; |
| 6 | 6 |
| 7 import '../elements/elements.dart'; | 7 import '../elements/elements.dart'; |
| 8 import '../constants/expressions.dart'; | 8 import '../constants/expressions.dart'; |
| 9 import '../dart_types.dart'; | 9 import '../dart_types.dart'; |
| 10 import '../util/enumset.dart'; | 10 import '../util/enumset.dart'; |
| 11 | 11 |
| 12 import 'constant_serialization.dart'; | 12 import 'constant_serialization.dart'; |
| 13 import 'element_serialization.dart'; | 13 import 'element_serialization.dart'; |
| 14 import 'json_serializer.dart'; | 14 import 'json_serializer.dart'; |
| 15 import 'keys.dart'; | 15 import 'keys.dart'; |
| 16 import 'type_serialization.dart'; | 16 import 'type_serialization.dart'; |
| 17 import 'values.dart'; | 17 import 'values.dart'; |
| 18 | 18 |
| 19 export 'task.dart' show LibraryDeserializer; | 19 export 'task.dart' show LibraryDeserializer; |
| 20 | 20 |
| 21 /// An object that supports the encoding an [ObjectValue] for serialization. | 21 /// An object that supports the encoding an [ObjectValue] for serialization. |
| 22 /// | 22 /// |
| 23 /// The [ObjectEncoder] ensures that nominality and circularities of | 23 /// The [ObjectEncoder] ensures that nominality and circularities of |
| 24 /// non-primitive values like [Element], [DartType] and [ConstantExpression] are | 24 /// non-primitive values like [Element], [DartType] and [ConstantExpression] are |
| 25 /// handled. | 25 /// handled. |
| 26 class ObjectEncoder extends AbstractEncoder<Key> { | 26 class ObjectEncoder extends AbstractEncoder<Key> { |
| 27 /// Creates an [ObjectEncoder] in the scope of [serializer] that uses [map] | 27 /// Creates an [ObjectEncoder] in the scope of [serializer] that uses [map] |
| 28 /// as its internal storage. | 28 /// as its internal storage. |
| 29 ObjectEncoder(Serializer serializer, Map<dynamic, Value> map) | 29 ObjectEncoder(Serializer serializer, Map<dynamic, Value> map) |
| 30 : super(serializer, map); | 30 : super(serializer, map); |
| 31 | 31 |
| 32 String get _name => 'Object'; | 32 String get _name => 'Object'; |
| 33 } | 33 } |
| 34 | 34 |
| 35 /// An object that supports the encoding a [MapValue] for serialization. | 35 /// An object that supports the encoding a [MapValue] for serialization. |
| 36 /// | 36 /// |
| 37 /// The [MapEncoder] ensures that nominality and circularities of | 37 /// The [MapEncoder] ensures that nominality and circularities of |
| 38 /// non-primitive values like [Element], [DartType] and [ConstantExpression] are | 38 /// non-primitive values like [Element], [DartType] and [ConstantExpression] are |
| 39 /// handled. | 39 /// handled. |
| 40 class MapEncoder extends AbstractEncoder<String> { | 40 class MapEncoder extends AbstractEncoder<String> { |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 90 throw new StateError("$_name value '$key' already in $_map."); | 90 throw new StateError("$_name value '$key' already in $_map."); |
| 91 } | 91 } |
| 92 } | 92 } |
| 93 | 93 |
| 94 /// Maps the [key] entry to the [value] in the encoded object. | 94 /// Maps the [key] entry to the [value] in the encoded object. |
| 95 void setValue(K key, Value value) { | 95 void setValue(K key, Value value) { |
| 96 _checkKey(key); | 96 _checkKey(key); |
| 97 _map[key] = value; | 97 _map[key] = value; |
| 98 } | 98 } |
| 99 | 99 |
| 100 | |
| 101 /// Maps the [key] entry to the enum [value] in the encoded object. | 100 /// Maps the [key] entry to the enum [value] in the encoded object. |
| 102 void setEnum(K key, var value) { | 101 void setEnum(K key, var value) { |
| 103 _checkKey(key); | 102 _checkKey(key); |
| 104 _map[key] = new EnumValue(value); | 103 _map[key] = new EnumValue(value); |
| 105 } | 104 } |
| 106 | 105 |
| 107 /// Maps the [key] entry to the set of enum [values] in the encoded object. | 106 /// Maps the [key] entry to the set of enum [values] in the encoded object. |
| 108 void setEnums(K key, Iterable values) { | 107 void setEnums(K key, Iterable values) { |
| 109 setEnumSet(key, new EnumSet.fromValues(values)); | 108 setEnumSet(key, new EnumSet.fromValues(values)); |
| 110 } | 109 } |
| 111 | 110 |
| 112 /// Maps the [key] entry to the enum [set] in the encoded object. | 111 /// Maps the [key] entry to the enum [set] in the encoded object. |
| 113 void setEnumSet(K key, EnumSet set) { | 112 void setEnumSet(K key, EnumSet set) { |
| 114 _checkKey(key); | 113 _checkKey(key); |
| 115 _map[key] = new IntValue(set.value); | 114 _map[key] = new IntValue(set.value); |
| 116 } | 115 } |
| 117 | 116 |
| 118 /// Maps the [key] entry to the [element] in the encoded object. | 117 /// Maps the [key] entry to the [element] in the encoded object. |
| 119 void setElement(K key, Element element) { | 118 void setElement(K key, Element element) { |
| 120 _checkKey(key); | 119 _checkKey(key); |
| 121 _map[key] = _serializer.createElementValue(element); | 120 _map[key] = _serializer.createElementValue(element); |
| 122 } | 121 } |
| 123 | 122 |
| 124 /// Maps the [key] entry to the [elements] in the encoded object. | 123 /// Maps the [key] entry to the [elements] in the encoded object. |
| 125 /// | 124 /// |
| 126 /// If [elements] is empty, it is skipped. | 125 /// If [elements] is empty, it is skipped. |
| 127 void setElements(K key, Iterable<Element> elements) { | 126 void setElements(K key, Iterable<Element> elements) { |
| 128 _checkKey(key); | 127 _checkKey(key); |
| 129 if (elements.isNotEmpty) { | 128 if (elements.isNotEmpty) { |
| 130 _map[key] = new ListValue( | 129 _map[key] = |
| 131 elements.map(_serializer.createElementValue).toList()); | 130 new ListValue(elements.map(_serializer.createElementValue).toList()); |
| 132 } | 131 } |
| 133 } | 132 } |
| 134 | 133 |
| 135 /// Maps the [key] entry to the [constant] in the encoded object. | 134 /// Maps the [key] entry to the [constant] in the encoded object. |
| 136 void setConstant(K key, ConstantExpression constant) { | 135 void setConstant(K key, ConstantExpression constant) { |
| 137 _checkKey(key); | 136 _checkKey(key); |
| 138 _map[key] = _serializer.createConstantValue(constant); | 137 _map[key] = _serializer.createConstantValue(constant); |
| 139 } | 138 } |
| 140 | 139 |
| 141 /// Maps the [key] entry to the [constants] in the encoded object. | 140 /// Maps the [key] entry to the [constants] in the encoded object. |
| (...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 245 } | 244 } |
| 246 | 245 |
| 247 String toString() => _map.toString(); | 246 String toString() => _map.toString(); |
| 248 } | 247 } |
| 249 | 248 |
| 250 /// [ObjectDecoder] reads serialized values from a [Map] encoded from an | 249 /// [ObjectDecoder] reads serialized values from a [Map] encoded from an |
| 251 /// [ObjectValue] where properties are stored using [Key] values as keys. | 250 /// [ObjectValue] where properties are stored using [Key] values as keys. |
| 252 class ObjectDecoder extends AbstractDecoder<Key> { | 251 class ObjectDecoder extends AbstractDecoder<Key> { |
| 253 /// Creates an [ObjectDecoder] that decodes [map] into deserialized values | 252 /// Creates an [ObjectDecoder] that decodes [map] into deserialized values |
| 254 /// using [deserializer] to create canonicalized values. | 253 /// using [deserializer] to create canonicalized values. |
| 255 ObjectDecoder(Deserializer deserializer, Map map) | 254 ObjectDecoder(Deserializer deserializer, Map map) : super(deserializer, map); |
| 256 : super(deserializer, map); | |
| 257 | 255 |
| 258 @override | 256 @override |
| 259 _getKeyValue(Key key) => _deserializer.decoder.getObjectPropertyValue(key); | 257 _getKeyValue(Key key) => _deserializer.decoder.getObjectPropertyValue(key); |
| 260 } | 258 } |
| 261 | 259 |
| 262 /// [MapDecoder] reads serialized values from a [Map] encoded from an | 260 /// [MapDecoder] reads serialized values from a [Map] encoded from an |
| 263 /// [MapValue] where entries are stored using [String] values as keys. | 261 /// [MapValue] where entries are stored using [String] values as keys. |
| 264 class MapDecoder extends AbstractDecoder<String> { | 262 class MapDecoder extends AbstractDecoder<String> { |
| 265 /// Creates an [MapDecoder] that decodes [map] into deserialized values | 263 /// Creates an [MapDecoder] that decodes [map] into deserialized values |
| 266 /// using [deserializer] to create canonicalized values. | 264 /// using [deserializer] to create canonicalized values. |
| (...skipping 421 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 688 if (dataObject == null) { | 686 if (dataObject == null) { |
| 689 if (!shouldInclude(element)) { | 687 if (!shouldInclude(element)) { |
| 690 if (element.isLibrary) { | 688 if (element.isLibrary) { |
| 691 LibraryElement library = element; | 689 LibraryElement library = element; |
| 692 _elementMap[element] = dataObject = new DataObject( | 690 _elementMap[element] = dataObject = new DataObject( |
| 693 new IntValue(_elementMap.length), | 691 new IntValue(_elementMap.length), |
| 694 new EnumValue(SerializedElementKind.EXTERNAL_LIBRARY)); | 692 new EnumValue(SerializedElementKind.EXTERNAL_LIBRARY)); |
| 695 ObjectEncoder encoder = new ObjectEncoder(this, dataObject.map); | 693 ObjectEncoder encoder = new ObjectEncoder(this, dataObject.map); |
| 696 encoder.setUri(Key.URI, library.canonicalUri, library.canonicalUri); | 694 encoder.setUri(Key.URI, library.canonicalUri, library.canonicalUri); |
| 697 } else if (element.isStatic) { | 695 } else if (element.isStatic) { |
| 698 Value classId =_getElementId(element.enclosingClass); | 696 Value classId = _getElementId(element.enclosingClass); |
| 699 _elementMap[element] = dataObject = new DataObject( | 697 _elementMap[element] = dataObject = new DataObject( |
| 700 new IntValue(_elementMap.length), | 698 new IntValue(_elementMap.length), |
| 701 new EnumValue(SerializedElementKind.EXTERNAL_STATIC_MEMBER)); | 699 new EnumValue(SerializedElementKind.EXTERNAL_STATIC_MEMBER)); |
| 702 ObjectEncoder encoder = new ObjectEncoder(this, dataObject.map); | 700 ObjectEncoder encoder = new ObjectEncoder(this, dataObject.map); |
| 703 encoder.setValue(Key.CLASS, classId); | 701 encoder.setValue(Key.CLASS, classId); |
| 704 encoder.setString(Key.NAME, element.name); | 702 encoder.setString(Key.NAME, element.name); |
| 705 } else if (element.isConstructor) { | 703 } else if (element.isConstructor) { |
| 706 Value classId =_getElementId(element.enclosingClass); | 704 Value classId = _getElementId(element.enclosingClass); |
| 707 _elementMap[element] = dataObject = new DataObject( | 705 _elementMap[element] = dataObject = new DataObject( |
| 708 new IntValue(_elementMap.length), | 706 new IntValue(_elementMap.length), |
| 709 new EnumValue(SerializedElementKind.EXTERNAL_CONSTRUCTOR)); | 707 new EnumValue(SerializedElementKind.EXTERNAL_CONSTRUCTOR)); |
| 710 ObjectEncoder encoder = new ObjectEncoder(this, dataObject.map); | 708 ObjectEncoder encoder = new ObjectEncoder(this, dataObject.map); |
| 711 encoder.setValue(Key.CLASS, classId); | 709 encoder.setValue(Key.CLASS, classId); |
| 712 encoder.setString(Key.NAME, element.name); | 710 encoder.setString(Key.NAME, element.name); |
| 713 } else { | 711 } else { |
| 714 Value libraryId =_getElementId(element.library); | 712 Value libraryId = _getElementId(element.library); |
| 715 _elementMap[element] = dataObject = new DataObject( | 713 _elementMap[element] = dataObject = new DataObject( |
| 716 new IntValue(_elementMap.length), | 714 new IntValue(_elementMap.length), |
| 717 new EnumValue(SerializedElementKind.EXTERNAL_LIBRARY_MEMBER)); | 715 new EnumValue(SerializedElementKind.EXTERNAL_LIBRARY_MEMBER)); |
| 718 ObjectEncoder encoder = new ObjectEncoder(this, dataObject.map); | 716 ObjectEncoder encoder = new ObjectEncoder(this, dataObject.map); |
| 719 encoder.setValue(Key.LIBRARY, libraryId); | 717 encoder.setValue(Key.LIBRARY, libraryId); |
| 720 encoder.setString(Key.NAME, element.name); | 718 encoder.setString(Key.NAME, element.name); |
| 721 } | 719 } |
| 722 } else { | 720 } else { |
| 723 // Run through [ELEMENT_SERIALIZERS] sequentially to find the one that | 721 // Run through [ELEMENT_SERIALIZERS] sequentially to find the one that |
| 724 // deals with [element]. | 722 // deals with [element]. |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 773 new IntValue(_constantMap.length), new EnumValue(constant.kind)); | 771 new IntValue(_constantMap.length), new EnumValue(constant.kind)); |
| 774 // Delay the serialization of the constant itself to avoid loops, and to | 772 // Delay the serialization of the constant itself to avoid loops, and to |
| 775 // keep the call stack small. | 773 // keep the call stack small. |
| 776 _pendingList.add(() => _encodeConstant(constant, dataObject)); | 774 _pendingList.add(() => _encodeConstant(constant, dataObject)); |
| 777 return dataObject; | 775 return dataObject; |
| 778 }).id; | 776 }).id; |
| 779 } | 777 } |
| 780 | 778 |
| 781 /// Encodes [constant] into the [ObjectValue] of [dataObject]. | 779 /// Encodes [constant] into the [ObjectValue] of [dataObject]. |
| 782 void _encodeConstant(ConstantExpression constant, DataObject dataObject) { | 780 void _encodeConstant(ConstantExpression constant, DataObject dataObject) { |
| 783 const ConstantSerializer().visit(constant, | 781 const ConstantSerializer() |
| 784 new ObjectEncoder(this, dataObject.map)); | 782 .visit(constant, new ObjectEncoder(this, dataObject.map)); |
| 785 } | 783 } |
| 786 | 784 |
| 787 /// Creates the [ConstantValue] for [constant]. | 785 /// Creates the [ConstantValue] for [constant]. |
| 788 /// | 786 /// |
| 789 /// If [constant] has not already been serialized, it is added to the work | 787 /// If [constant] has not already been serialized, it is added to the work |
| 790 /// queue of this serializer. | 788 /// queue of this serializer. |
| 791 ConstantValue createConstantValue(ConstantExpression constant) { | 789 ConstantValue createConstantValue(ConstantExpression constant) { |
| 792 return new ConstantValue(constant, _getConstantId(constant)); | 790 return new ConstantValue(constant, _getConstantId(constant)); |
| 793 } | 791 } |
| 794 | 792 |
| (...skipping 195 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 990 } else { | 988 } else { |
| 991 element = ElementDeserializer.deserialize(decoder, elementKind); | 989 element = ElementDeserializer.deserialize(decoder, elementKind); |
| 992 } | 990 } |
| 993 _elementMap[id] = element; | 991 _elementMap[id] = element; |
| 994 | 992 |
| 995 MapDecoder pluginData = decoder.getMap(Key.DATA, isOptional: true); | 993 MapDecoder pluginData = decoder.getMap(Key.DATA, isOptional: true); |
| 996 // Call plugins even when there is no data, so they can take action in | 994 // Call plugins even when there is no data, so they can take action in |
| 997 // this case. | 995 // this case. |
| 998 for (DeserializerPlugin plugin in plugins) { | 996 for (DeserializerPlugin plugin in plugins) { |
| 999 plugin.onElement(element, | 997 plugin.onElement(element, |
| 1000 (String tag) => pluginData?.getObject(tag, isOptional: true)); | 998 (String tag) => pluginData?.getObject(tag, isOptional: true)); |
| 1001 } | 999 } |
| 1002 } | 1000 } |
| 1003 return element; | 1001 return element; |
| 1004 } | 1002 } |
| 1005 | 1003 |
| 1006 /// Returns the deserialized [DartType] for [id]. | 1004 /// Returns the deserialized [DartType] for [id]. |
| 1007 DartType deserializeType(int id) { | 1005 DartType deserializeType(int id) { |
| 1008 if (id == null) throw new ArgumentError('Deserializer.getType(null)'); | 1006 if (id == null) throw new ArgumentError('Deserializer.getType(null)'); |
| 1009 return _typeMap.putIfAbsent(id, () { | 1007 return _typeMap.putIfAbsent(id, () { |
| 1010 return TypeDeserializer.deserialize(types.getObject(id)); | 1008 return TypeDeserializer.deserialize(types.getObject(id)); |
| (...skipping 24 matching lines...) Expand all Loading... |
| 1035 | 1033 |
| 1036 /// Returns the value used to store [key] as a property in the encoding an | 1034 /// Returns the value used to store [key] as a property in the encoding an |
| 1037 /// [ObjectValue]. | 1035 /// [ObjectValue]. |
| 1038 /// | 1036 /// |
| 1039 /// Different encodings have different restrictions and capabilities as how | 1037 /// Different encodings have different restrictions and capabilities as how |
| 1040 /// to store a [Key] value. For instance: A JSON encoding needs to convert | 1038 /// to store a [Key] value. For instance: A JSON encoding needs to convert |
| 1041 /// [Key] to a [String] to store it in a JSON object; a Dart encoding can | 1039 /// [Key] to a [String] to store it in a JSON object; a Dart encoding can |
| 1042 /// choose to store a [Key] as an [int] or as the [Key] itself. | 1040 /// choose to store a [Key] as an [int] or as the [Key] itself. |
| 1043 getObjectPropertyValue(Key key); | 1041 getObjectPropertyValue(Key key); |
| 1044 } | 1042 } |
| OLD | NEW |