Chromium Code Reviews| 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 '../common.dart'; |
| 8 import '../constants/expressions.dart'; | 8 import '../constants/expressions.dart'; |
| 9 import '../dart_types.dart'; | 9 import '../dart_types.dart'; |
| 10 import '../elements/elements.dart'; | |
| 10 import '../util/enumset.dart'; | 11 import '../util/enumset.dart'; |
| 11 | 12 |
| 12 import 'constant_serialization.dart'; | 13 import 'constant_serialization.dart'; |
| 13 import 'element_serialization.dart'; | 14 import 'element_serialization.dart'; |
| 14 import 'json_serializer.dart'; | 15 import 'json_serializer.dart'; |
| 15 import 'keys.dart'; | 16 import 'keys.dart'; |
| 16 import 'type_serialization.dart'; | 17 import 'type_serialization.dart'; |
| 17 import 'values.dart'; | 18 import 'values.dart'; |
| 18 | 19 |
| 19 export 'task.dart' show LibraryDeserializer; | 20 export 'task.dart' show LibraryDeserializer; |
| (...skipping 659 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 679 /// encoding the [ObjectValue] for [element] is put into the work queue of | 680 /// encoding the [ObjectValue] for [element] is put into the work queue of |
| 680 /// this serializer. | 681 /// this serializer. |
| 681 Value _getElementId(Element element) { | 682 Value _getElementId(Element element) { |
| 682 if (element == null) { | 683 if (element == null) { |
| 683 throw new ArgumentError('Serializer._getElementDataObject(null)'); | 684 throw new ArgumentError('Serializer._getElementDataObject(null)'); |
| 684 } | 685 } |
| 685 element = element.declaration; | 686 element = element.declaration; |
| 686 DataObject dataObject = _elementMap[element]; | 687 DataObject dataObject = _elementMap[element]; |
| 687 if (dataObject == null) { | 688 if (dataObject == null) { |
| 688 if (!shouldInclude(element)) { | 689 if (!shouldInclude(element)) { |
| 690 | |
| 691 /// Helper used to check that external references are serialized by | |
| 692 /// the right kind. | |
| 693 bool verifyElement(var found, var expected) { | |
| 694 found = found.declaration; | |
| 695 if (found == expected) return true; | |
| 696 if (found.isAbstractField && expected.isGetter) { | |
| 697 return found.getter == expected; | |
| 698 } | |
| 699 if (found.isAbstractField && expected.isSetter) { | |
| 700 return found.setter == expected; | |
| 701 } | |
| 702 return false; | |
| 703 } | |
| 704 | |
| 689 if (element.isLibrary) { | 705 if (element.isLibrary) { |
| 690 LibraryElement library = element; | 706 LibraryElement library = element; |
| 691 _elementMap[element] = dataObject = new DataObject( | 707 _elementMap[element] = dataObject = new DataObject( |
| 692 new IntValue(_elementMap.length), | 708 new IntValue(_elementMap.length), |
| 693 new EnumValue(SerializedElementKind.EXTERNAL_LIBRARY)); | 709 new EnumValue(SerializedElementKind.EXTERNAL_LIBRARY)); |
| 694 ObjectEncoder encoder = new ObjectEncoder(this, dataObject.map); | 710 ObjectEncoder encoder = new ObjectEncoder(this, dataObject.map); |
| 695 encoder.setUri(Key.URI, library.canonicalUri, library.canonicalUri); | 711 encoder.setUri(Key.URI, library.canonicalUri, library.canonicalUri); |
| 696 } else if (element.isStatic) { | |
| 697 Value classId = _getElementId(element.enclosingClass); | |
| 698 _elementMap[element] = dataObject = new DataObject( | |
| 699 new IntValue(_elementMap.length), | |
| 700 new EnumValue(SerializedElementKind.EXTERNAL_STATIC_MEMBER)); | |
| 701 ObjectEncoder encoder = new ObjectEncoder(this, dataObject.map); | |
| 702 encoder.setValue(Key.CLASS, classId); | |
| 703 encoder.setString(Key.NAME, element.name); | |
| 704 } else if (element.isConstructor) { | 712 } else if (element.isConstructor) { |
| 713 assert(invariant(element, | |
| 714 verifyElement( | |
| 715 element.enclosingClass.implementation.lookupConstructor( | |
| 716 element.name), | |
| 717 element), | |
| 718 message: "Element $element is not found as a " | |
| 719 "constructor of ${element.enclosingClass.implementation}.")); | |
| 705 Value classId = _getElementId(element.enclosingClass); | 720 Value classId = _getElementId(element.enclosingClass); |
| 706 _elementMap[element] = dataObject = new DataObject( | 721 _elementMap[element] = dataObject = new DataObject( |
| 707 new IntValue(_elementMap.length), | 722 new IntValue(_elementMap.length), |
| 708 new EnumValue(SerializedElementKind.EXTERNAL_CONSTRUCTOR)); | 723 new EnumValue(SerializedElementKind.EXTERNAL_CONSTRUCTOR)); |
| 709 ObjectEncoder encoder = new ObjectEncoder(this, dataObject.map); | 724 ObjectEncoder encoder = new ObjectEncoder(this, dataObject.map); |
| 710 encoder.setValue(Key.CLASS, classId); | 725 encoder.setValue(Key.CLASS, classId); |
| 711 encoder.setString(Key.NAME, element.name); | 726 encoder.setString(Key.NAME, element.name); |
| 727 } else if (element.isClassMember) { | |
| 728 assert(invariant(element, | |
| 729 verifyElement( | |
| 730 element.enclosingClass.lookupLocalMember(element.name), | |
| 731 element), | |
| 732 message: "Element $element is not found as a " | |
| 733 "class member of ${element.enclosingClass}.")); | |
| 734 Value classId = _getElementId(element.enclosingClass); | |
| 735 _elementMap[element] = dataObject = new DataObject( | |
| 736 new IntValue(_elementMap.length), | |
| 737 new EnumValue(SerializedElementKind.EXTERNAL_CLASS_MEMBER)); | |
| 738 ObjectEncoder encoder = new ObjectEncoder(this, dataObject.map); | |
| 739 encoder.setValue(Key.CLASS, classId); | |
| 740 encoder.setString(Key.NAME, element.name); | |
| 741 if (element.isAccessor) { | |
| 742 encoder.setBool(Key.GETTER, element.isGetter); | |
| 743 } | |
| 712 } else { | 744 } else { |
| 745 assert(invariant(element, | |
| 746 verifyElement( | |
| 747 element.library.implementation.find(element.name), element), | |
| 748 message: "Element $element is not found as a " | |
| 749 "library member of ${element.library.implementation}.")); | |
| 713 Value libraryId = _getElementId(element.library); | 750 Value libraryId = _getElementId(element.library); |
| 714 _elementMap[element] = dataObject = new DataObject( | 751 _elementMap[element] = dataObject = new DataObject( |
| 715 new IntValue(_elementMap.length), | 752 new IntValue(_elementMap.length), |
| 716 new EnumValue(SerializedElementKind.EXTERNAL_LIBRARY_MEMBER)); | 753 new EnumValue(SerializedElementKind.EXTERNAL_LIBRARY_MEMBER)); |
| 717 ObjectEncoder encoder = new ObjectEncoder(this, dataObject.map); | 754 ObjectEncoder encoder = new ObjectEncoder(this, dataObject.map); |
| 718 encoder.setValue(Key.LIBRARY, libraryId); | 755 encoder.setValue(Key.LIBRARY, libraryId); |
| 719 encoder.setString(Key.NAME, element.name); | 756 encoder.setString(Key.NAME, element.name); |
| 757 if (element.isAccessor) { | |
|
Siggi Cherem (dart-lang)
2016/05/24 18:08:15
are the changes about Key.GETTER needed for suppor
Johnni Winther
2016/05/25 07:54:46
These are needed. It turned out that because of th
| |
| 758 encoder.setBool(Key.GETTER, element.isGetter); | |
| 759 } | |
| 720 } | 760 } |
| 721 } else { | 761 } else { |
| 722 // Run through [ELEMENT_SERIALIZERS] sequentially to find the one that | 762 // Run through [ELEMENT_SERIALIZERS] sequentially to find the one that |
| 723 // deals with [element]. | 763 // deals with [element]. |
| 724 for (ElementSerializer serializer in ELEMENT_SERIALIZERS) { | 764 for (ElementSerializer serializer in ELEMENT_SERIALIZERS) { |
| 725 SerializedElementKind kind = serializer.getSerializedKind(element); | 765 SerializedElementKind kind = serializer.getSerializedKind(element); |
| 726 if (kind != null) { | 766 if (kind != null) { |
| 727 _elementMap[element] = dataObject = new DataObject( | 767 _elementMap[element] = dataObject = new DataObject( |
| 728 new IntValue(_elementMap.length), new EnumValue(kind)); | 768 new IntValue(_elementMap.length), new EnumValue(kind)); |
| 729 // Delay the serialization of the element itself to avoid loops, and | 769 // Delay the serialization of the element itself to avoid loops, and |
| (...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 871 /// Use [getDecoder] to retrieve the data object with id [tag] stored for | 911 /// Use [getDecoder] to retrieve the data object with id [tag] stored for |
| 872 /// [element]. If not object is stored for [tag], [getDecoder] returns `null`. | 912 /// [element]. If not object is stored for [tag], [getDecoder] returns `null`. |
| 873 void onElement(Element element, ObjectDecoder getDecoder(String tag)) {} | 913 void onElement(Element element, ObjectDecoder getDecoder(String tag)) {} |
| 874 | 914 |
| 875 /// Called to deserialize custom data from [decoder]. | 915 /// Called to deserialize custom data from [decoder]. |
| 876 dynamic onData(ObjectDecoder decoder) {} | 916 dynamic onData(ObjectDecoder decoder) {} |
| 877 } | 917 } |
| 878 | 918 |
| 879 /// Context for parallel deserialization. | 919 /// Context for parallel deserialization. |
| 880 class DeserializationContext { | 920 class DeserializationContext { |
| 921 final DiagnosticReporter reporter; | |
| 881 Map<Uri, LibraryElement> _uriMap = <Uri, LibraryElement>{}; | 922 Map<Uri, LibraryElement> _uriMap = <Uri, LibraryElement>{}; |
| 882 List<Deserializer> deserializers = <Deserializer>[]; | 923 List<Deserializer> deserializers = <Deserializer>[]; |
| 883 List<DeserializerPlugin> plugins = <DeserializerPlugin>[]; | 924 List<DeserializerPlugin> plugins = <DeserializerPlugin>[]; |
| 884 | 925 |
| 926 DeserializationContext(this.reporter); | |
| 927 | |
| 885 LibraryElement lookupLibrary(Uri uri) { | 928 LibraryElement lookupLibrary(Uri uri) { |
| 886 return _uriMap.putIfAbsent(uri, () { | 929 return _uriMap.putIfAbsent(uri, () { |
| 930 Uri foundUri; | |
| 931 LibraryElement foundLibrary; | |
| 887 for (Deserializer deserializer in deserializers) { | 932 for (Deserializer deserializer in deserializers) { |
| 888 LibraryElement library = deserializer.lookupLibrary(uri); | 933 LibraryElement library = deserializer.lookupLibrary(uri); |
| 889 if (library != null) { | 934 if (library != null) { |
| 890 return library; | 935 if (foundLibrary != null) { |
| 936 reporter.reportErrorMessage(NO_LOCATION_SPANNABLE, | |
| 937 MessageKind.DUPLICATE_SERIALIZED_LIBRARY, | |
| 938 {'libraryUri': uri, 'sourceUri1': foundUri, 'sourceUri2': deseri alizer.sourceUri}); | |
|
Siggi Cherem (dart-lang)
2016/05/24 18:08:15
dartfmt
Johnni Winther
2016/05/25 07:54:46
Done.
| |
| 939 } | |
| 940 foundUri = deserializer.sourceUri; | |
| 941 foundLibrary = library; | |
| 891 } | 942 } |
| 892 } | 943 } |
| 893 return null; | 944 return foundLibrary; |
| 894 }); | 945 }); |
| 895 } | 946 } |
| 896 } | 947 } |
| 897 | 948 |
| 898 /// Deserializer for a closed collection of libraries. | 949 /// Deserializer for a closed collection of libraries. |
| 899 // TODO(johnniwinther): Support per-library deserialization and dependencies | 950 // TODO(johnniwinther): Support per-library deserialization and dependencies |
| 900 // between deserialized subcomponent. | 951 // between deserialized subcomponent. |
| 901 class Deserializer { | 952 class Deserializer { |
| 902 final DeserializationContext context; | 953 final DeserializationContext context; |
| 903 final SerializationDecoder decoder; | 954 final SerializationDecoder decoder; |
| 955 final Uri sourceUri; | |
| 904 ObjectDecoder _headerObject; | 956 ObjectDecoder _headerObject; |
| 905 ListDecoder _elementList; | 957 ListDecoder _elementList; |
| 906 ListDecoder _typeList; | 958 ListDecoder _typeList; |
| 907 ListDecoder _constantList; | 959 ListDecoder _constantList; |
| 908 Map<int, Element> _elementMap = {}; | 960 Map<int, Element> _elementMap = {}; |
| 909 Map<int, DartType> _typeMap = {}; | 961 Map<int, DartType> _typeMap = {}; |
| 910 Map<int, ConstantExpression> _constantMap = {}; | 962 Map<int, ConstantExpression> _constantMap = {}; |
| 911 | 963 |
| 912 Deserializer.fromText(this.context, String text, this.decoder) { | 964 Deserializer.fromText( |
| 965 this.context, this.sourceUri, String text, this.decoder) { | |
| 913 _headerObject = new ObjectDecoder(this, decoder.decode(text)); | 966 _headerObject = new ObjectDecoder(this, decoder.decode(text)); |
| 914 } | 967 } |
| 915 | 968 |
| 916 /// Returns the [ListDecoder] for the [Element]s in this deserializer. | 969 /// Returns the [ListDecoder] for the [Element]s in this deserializer. |
| 917 ListDecoder get elements { | 970 ListDecoder get elements { |
| 918 if (_elementList == null) { | 971 if (_elementList == null) { |
| 919 _elementList = _headerObject.getList(Key.ELEMENTS); | 972 _elementList = _headerObject.getList(Key.ELEMENTS); |
| 920 } | 973 } |
| 921 return _elementList; | 974 return _elementList; |
| 922 } | 975 } |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 966 decoder.getEnum(Key.KIND, SerializedElementKind.values); | 1019 decoder.getEnum(Key.KIND, SerializedElementKind.values); |
| 967 if (elementKind == SerializedElementKind.EXTERNAL_LIBRARY) { | 1020 if (elementKind == SerializedElementKind.EXTERNAL_LIBRARY) { |
| 968 Uri uri = decoder.getUri(Key.URI); | 1021 Uri uri = decoder.getUri(Key.URI); |
| 969 element = context.lookupLibrary(uri); | 1022 element = context.lookupLibrary(uri); |
| 970 if (element == null) { | 1023 if (element == null) { |
| 971 throw new StateError("Missing library for $uri."); | 1024 throw new StateError("Missing library for $uri."); |
| 972 } | 1025 } |
| 973 } else if (elementKind == SerializedElementKind.EXTERNAL_LIBRARY_MEMBER) { | 1026 } else if (elementKind == SerializedElementKind.EXTERNAL_LIBRARY_MEMBER) { |
| 974 LibraryElement library = decoder.getElement(Key.LIBRARY); | 1027 LibraryElement library = decoder.getElement(Key.LIBRARY); |
| 975 String name = decoder.getString(Key.NAME); | 1028 String name = decoder.getString(Key.NAME); |
| 1029 bool isGetter = decoder.getBool(Key.GETTER, isOptional: true); | |
| 976 element = library.find(name); | 1030 element = library.find(name); |
| 977 if (element == null) { | 1031 if (element == null) { |
| 978 throw new StateError("Missing library member for $name in $library."); | 1032 throw new StateError("Missing library member for $name in $library."); |
| 979 } | 1033 } |
| 980 } else if (elementKind == SerializedElementKind.EXTERNAL_STATIC_MEMBER) { | 1034 if (isGetter != null) { |
| 1035 AbstractFieldElement abstractField = element; | |
| 1036 element = isGetter ? abstractField.getter : abstractField.setter; | |
| 1037 if (element == null) { | |
| 1038 throw new StateError( | |
| 1039 "Missing ${isGetter ? 'getter' : 'setter'} for " | |
| 1040 "$name in $library."); | |
| 1041 } | |
| 1042 } | |
| 1043 } else if (elementKind == SerializedElementKind.EXTERNAL_CLASS_MEMBER) { | |
| 981 ClassElement cls = decoder.getElement(Key.CLASS); | 1044 ClassElement cls = decoder.getElement(Key.CLASS); |
| 982 String name = decoder.getString(Key.NAME); | 1045 String name = decoder.getString(Key.NAME); |
| 1046 bool isGetter = decoder.getBool(Key.GETTER, isOptional: true); | |
| 983 element = cls.lookupLocalMember(name); | 1047 element = cls.lookupLocalMember(name); |
| 984 if (element == null) { | 1048 if (element == null) { |
| 985 throw new StateError("Missing static member for $name in $cls."); | 1049 throw new StateError("Missing class member for $name in $cls."); |
| 1050 } | |
| 1051 if (isGetter != null) { | |
| 1052 AbstractFieldElement abstractField = element; | |
| 1053 element = isGetter ? abstractField.getter : abstractField.setter; | |
| 1054 if (element == null) { | |
| 1055 throw new StateError( | |
| 1056 "Missing ${isGetter ? 'getter' : 'setter'} for $name in $cls."); | |
| 1057 } | |
| 986 } | 1058 } |
| 987 } else if (elementKind == SerializedElementKind.EXTERNAL_CONSTRUCTOR) { | 1059 } else if (elementKind == SerializedElementKind.EXTERNAL_CONSTRUCTOR) { |
| 988 ClassElement cls = decoder.getElement(Key.CLASS); | 1060 ClassElement cls = decoder.getElement(Key.CLASS); |
| 989 String name = decoder.getString(Key.NAME); | 1061 String name = decoder.getString(Key.NAME); |
| 990 element = cls.lookupConstructor(name); | 1062 element = cls.lookupConstructor(name); |
| 991 if (element == null) { | 1063 if (element == null) { |
| 992 throw new StateError("Missing constructor for $name in $cls."); | 1064 throw new StateError("Missing constructor for $name in $cls."); |
| 993 } | 1065 } |
| 994 } else { | 1066 } else { |
| 995 element = ElementDeserializer.deserialize(decoder, elementKind); | 1067 element = ElementDeserializer.deserialize(decoder, elementKind); |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1039 | 1111 |
| 1040 /// Returns the value used to store [key] as a property in the encoding an | 1112 /// Returns the value used to store [key] as a property in the encoding an |
| 1041 /// [ObjectValue]. | 1113 /// [ObjectValue]. |
| 1042 /// | 1114 /// |
| 1043 /// Different encodings have different restrictions and capabilities as how | 1115 /// Different encodings have different restrictions and capabilities as how |
| 1044 /// to store a [Key] value. For instance: A JSON encoding needs to convert | 1116 /// to store a [Key] value. For instance: A JSON encoding needs to convert |
| 1045 /// [Key] to a [String] to store it in a JSON object; a Dart encoding can | 1117 /// [Key] to a [String] to store it in a JSON object; a Dart encoding can |
| 1046 /// choose to store a [Key] as an [int] or as the [Key] itself. | 1118 /// choose to store a [Key] as an [int] or as the [Key] itself. |
| 1047 getObjectPropertyValue(Key key); | 1119 getObjectPropertyValue(Key key); |
| 1048 } | 1120 } |
| OLD | NEW |