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 |