| 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 '../common/backend_api.dart'; |
| 7 import '../elements/elements.dart'; | 8 import '../elements/elements.dart'; |
| 8 import '../constants/expressions.dart'; | 9 import '../constants/expressions.dart'; |
| 9 import '../dart_types.dart'; | 10 import '../dart_types.dart'; |
| 11 import '../universe/world_impact.dart'; |
| 10 | 12 |
| 13 import 'constant_serialization.dart'; |
| 11 import 'element_serialization.dart'; | 14 import 'element_serialization.dart'; |
| 12 import 'constant_serialization.dart'; | 15 import 'impact_serialization.dart'; |
| 16 import 'json_serializer.dart'; |
| 17 import 'keys.dart'; |
| 13 import 'type_serialization.dart'; | 18 import 'type_serialization.dart'; |
| 14 import 'keys.dart'; | |
| 15 import 'json_serializer.dart'; | |
| 16 import 'values.dart'; | 19 import 'values.dart'; |
| 17 | 20 |
| 18 /// An object that supports the encoding an [ObjectValue] for serialization. | 21 /// An object that supports the encoding an [ObjectValue] for serialization. |
| 19 /// | 22 /// |
| 20 /// The [ObjectEncoder] ensures that nominality and circularities of | 23 /// The [ObjectEncoder] ensures that nominality and circularities of |
| 21 /// non-primitive values like [Element], [DartType] and [ConstantExpression] are | 24 /// non-primitive values like [Element], [DartType] and [ConstantExpression] are |
| 22 /// handled. | 25 /// handled. |
| 23 class ObjectEncoder extends AbstractEncoder<Key> { | 26 class ObjectEncoder extends AbstractEncoder<Key> { |
| 24 /// Creates an [ObjectEncoder] in the scope of [serializer] that uses [map] | 27 /// Creates an [ObjectEncoder] in the scope of [serializer] that uses [map] |
| 25 /// as its internal storage. | 28 /// as its internal storage. |
| (...skipping 575 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 601 /// {...}, // [ObjectValue] of the 0th [ConstantExpression]. | 604 /// {...}, // [ObjectValue] of the 0th [ConstantExpression]. |
| 602 /// ... | 605 /// ... |
| 603 /// {...}, // [ObjectValue] of the n-th [ConstantExpression]. | 606 /// {...}, // [ObjectValue] of the n-th [ConstantExpression]. |
| 604 /// ], | 607 /// ], |
| 605 /// } | 608 /// } |
| 606 /// | 609 /// |
| 607 // TODO(johnniwinther): Support per-library serialization and dependencies | 610 // TODO(johnniwinther): Support per-library serialization and dependencies |
| 608 // between serialized subcomponent. | 611 // between serialized subcomponent. |
| 609 class Serializer { | 612 class Serializer { |
| 610 final SerializationEncoder _encoder; | 613 final SerializationEncoder _encoder; |
| 614 List<SerializerPlugin> plugins = <SerializerPlugin>[]; |
| 611 | 615 |
| 612 Map<Element, DataObject> _elementMap = <Element, DataObject>{}; | 616 Map<Element, DataObject> _elementMap = <Element, DataObject>{}; |
| 613 Map<ConstantExpression, DataObject> _constantMap = | 617 Map<ConstantExpression, DataObject> _constantMap = |
| 614 <ConstantExpression, DataObject>{}; | 618 <ConstantExpression, DataObject>{}; |
| 615 Map<DartType, DataObject> _typeMap = <DartType, DataObject>{}; | 619 Map<DartType, DataObject> _typeMap = <DartType, DataObject>{}; |
| 616 List _pendingList = []; | 620 List _pendingList = []; |
| 617 | 621 |
| 618 Serializer(this._encoder); | 622 Serializer(this._encoder); |
| 619 | 623 |
| 620 /// Add the transitive closure of [library] to this serializer. | 624 /// Add the transitive closure of [library] to this serializer. |
| 621 void serialize(LibraryElement library) { | 625 void serialize(LibraryElement library) { |
| 622 // Call [_getElementDataObject] for its side-effect: To create a | 626 // Call [_getElementDataObject] for its side-effect: To create a |
| 623 // [DataObject] for [library]. If not already created, this will | 627 // [DataObject] for [library]. If not already created, this will |
| 624 // put the serialization of [library] in the work queue. | 628 // put the serialization of [library] in the work queue. |
| 625 _getElementDataObject(library); | 629 _getElementDataObject(library); |
| 626 _emptyWorklist(); | |
| 627 } | 630 } |
| 628 | 631 |
| 629 void _emptyWorklist() { | 632 void _emptyWorklist() { |
| 630 while (_pendingList.isNotEmpty) { | 633 while (_pendingList.isNotEmpty) { |
| 631 _pendingList.removeLast()(); | 634 _pendingList.removeLast()(); |
| 632 } | 635 } |
| 633 } | 636 } |
| 634 | 637 |
| 635 /// Returns the [DataObject] for [element]. | 638 /// Returns the [DataObject] for [element]. |
| 636 /// | 639 /// |
| 637 /// If [constant] has no [DataObject], a new [DataObject] is created and | 640 /// If [constant] has no [DataObject], a new [DataObject] is created and |
| 638 /// encoding the [ObjectValue] for [constant] is put into the work queue of | 641 /// encoding the [ObjectValue] for [constant] is put into the work queue of |
| 639 /// this serializer. | 642 /// this serializer. |
| 640 DataObject _getElementDataObject(Element element) { | 643 DataObject _getElementDataObject(Element element) { |
| 641 if (element == null) { | 644 if (element == null) { |
| 642 throw new ArgumentError('Serializer._getElementDataObject(null)'); | 645 throw new ArgumentError('Serializer._getElementDataObject(null)'); |
| 643 } | 646 } |
| 644 return _elementMap.putIfAbsent(element, () { | 647 DataObject dataObject = _elementMap[element]; |
| 648 if (dataObject == null) { |
| 645 // Run through [ELEMENT_SERIALIZERS] sequentially to find the one that | 649 // Run through [ELEMENT_SERIALIZERS] sequentially to find the one that |
| 646 // deals with [element]. | 650 // deals with [element]. |
| 647 for (ElementSerializer serializer in ELEMENT_SERIALIZERS) { | 651 for (ElementSerializer serializer in ELEMENT_SERIALIZERS) { |
| 648 SerializedElementKind kind = serializer.getSerializedKind(element); | 652 SerializedElementKind kind = serializer.getSerializedKind(element); |
| 649 if (kind != null) { | 653 if (kind != null) { |
| 650 DataObject dataObject = new DataObject( | 654 dataObject = new DataObject( |
| 651 new IntValue(_elementMap.length), new EnumValue(kind)); | 655 new IntValue(_elementMap.length), new EnumValue(kind)); |
| 656 _elementMap[element] = dataObject; |
| 652 // Delay the serialization of the element itself to avoid loops, and | 657 // Delay the serialization of the element itself to avoid loops, and |
| 653 // to keep the call stack small. | 658 // to keep the call stack small. |
| 654 _pendingList.add(() { | 659 _pendingList.add(() { |
| 655 serializer.serialize( | 660 ObjectEncoder encoder = new ObjectEncoder(this, dataObject.map); |
| 656 element, new ObjectEncoder(this, dataObject.map), kind); | 661 serializer.serialize(element, encoder, kind); |
| 662 |
| 663 MapEncoder pluginData; |
| 664 for (SerializerPlugin plugin in plugins) { |
| 665 plugin.onElement(element, (String tag) { |
| 666 if (pluginData == null) { |
| 667 pluginData = encoder.createMap(Key.DATA); |
| 668 } |
| 669 return pluginData.createObject(tag); |
| 670 }); |
| 671 } |
| 657 }); | 672 }); |
| 658 return dataObject; | |
| 659 } | 673 } |
| 660 } | 674 } |
| 675 } |
| 676 if (dataObject == null) { |
| 661 throw new UnsupportedError( | 677 throw new UnsupportedError( |
| 662 'Unsupported element: $element (${element.kind})'); | 678 'Unsupported element: $element (${element.kind})'); |
| 663 }); | 679 } |
| 680 return dataObject; |
| 664 } | 681 } |
| 665 | 682 |
| 666 /// Creates the [ElementValue] for [element]. | 683 /// Creates the [ElementValue] for [element]. |
| 667 /// | 684 /// |
| 668 /// If [element] has not already been serialized, it is added to the work | 685 /// If [element] has not already been serialized, it is added to the work |
| 669 /// queue of this serializer. | 686 /// queue of this serializer. |
| 670 ElementValue createElementValue(Element element) { | 687 ElementValue createElementValue(Element element) { |
| 671 return new ElementValue(element, _getElementDataObject(element).id); | 688 return new ElementValue(element, _getElementDataObject(element).id); |
| 672 } | 689 } |
| 673 | 690 |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 724 | 741 |
| 725 /// Creates the [TypeValue] for [type]. | 742 /// Creates the [TypeValue] for [type]. |
| 726 /// | 743 /// |
| 727 /// If [type] has not already been serialized, it is added to the work | 744 /// If [type] has not already been serialized, it is added to the work |
| 728 /// queue of this serializer. | 745 /// queue of this serializer. |
| 729 TypeValue createTypeValue(DartType type) { | 746 TypeValue createTypeValue(DartType type) { |
| 730 return new TypeValue(type, _getTypeDataObject(type).id); | 747 return new TypeValue(type, _getTypeDataObject(type).id); |
| 731 } | 748 } |
| 732 | 749 |
| 733 ObjectValue get objectValue { | 750 ObjectValue get objectValue { |
| 751 _emptyWorklist(); |
| 752 |
| 734 Map<Key, Value> map = <Key, Value>{}; | 753 Map<Key, Value> map = <Key, Value>{}; |
| 735 map[Key.ELEMENTS] = | 754 map[Key.ELEMENTS] = |
| 736 new ListValue(_elementMap.values.map((l) => l.objectValue).toList()); | 755 new ListValue(_elementMap.values.map((l) => l.objectValue).toList()); |
| 737 if (_typeMap.isNotEmpty) { | 756 if (_typeMap.isNotEmpty) { |
| 738 map[Key.TYPES] = | 757 map[Key.TYPES] = |
| 739 new ListValue(_typeMap.values.map((l) => l.objectValue).toList()); | 758 new ListValue(_typeMap.values.map((l) => l.objectValue).toList()); |
| 740 } | 759 } |
| 741 if (_constantMap.isNotEmpty) { | 760 if (_constantMap.isNotEmpty) { |
| 742 map[Key.CONSTANTS] = | 761 map[Key.CONSTANTS] = |
| 743 new ListValue(_constantMap.values.map((l) => l.objectValue).toList()); | 762 new ListValue(_constantMap.values.map((l) => l.objectValue).toList()); |
| 744 } | 763 } |
| 745 return new ObjectValue(map); | 764 return new ObjectValue(map); |
| 746 } | 765 } |
| 747 | 766 |
| 748 String toText() { | 767 String toText() { |
| 749 return _encoder.encode(objectValue); | 768 return _encoder.encode(objectValue); |
| 750 } | 769 } |
| 751 | 770 |
| 752 String prettyPrint() { | 771 String prettyPrint() { |
| 753 PrettyPrintEncoder encoder = new PrettyPrintEncoder(); | 772 PrettyPrintEncoder encoder = new PrettyPrintEncoder(); |
| 754 return encoder.toText(objectValue); | 773 return encoder.toText(objectValue); |
| 755 } | 774 } |
| 756 } | 775 } |
| 757 | 776 |
| 777 /// Plugin for serializing additional data for an [Element]. |
| 778 class SerializerPlugin { |
| 779 const SerializerPlugin(); |
| 780 |
| 781 /// Called upon the serialization of [element]. |
| 782 /// |
| 783 /// Use [creatorEncoder] to create a data object with id [tag] for storing |
| 784 /// additional data for [element]. |
| 785 void onElement(Element element, ObjectEncoder createEncoder(String tag)) {} |
| 786 } |
| 787 |
| 788 /// Plugin for deserializing additional data for an [Element]. |
| 789 class DeserializerPlugin { |
| 790 const DeserializerPlugin(); |
| 791 |
| 792 /// Called upon the deserialization of [element]. |
| 793 /// |
| 794 /// Use [getDecoder] to retrieve the data object with id [tag] stored for |
| 795 /// [element]. If not object is stored for [tag], [getDecoder] returns `null`. |
| 796 void onElement(Element element, ObjectDecoder getDecoder(String tag)) {} |
| 797 } |
| 798 |
| 758 /// Deserializer for a closed collection of libraries. | 799 /// Deserializer for a closed collection of libraries. |
| 759 // TODO(johnniwinther): Support per-library deserialization and dependencies | 800 // TODO(johnniwinther): Support per-library deserialization and dependencies |
| 760 // between deserialized subcomponent. | 801 // between deserialized subcomponent. |
| 761 class Deserializer { | 802 class Deserializer { |
| 762 final SerializationDecoder decoder; | 803 final SerializationDecoder decoder; |
| 804 List<DeserializerPlugin> plugins = <DeserializerPlugin>[]; |
| 763 ObjectDecoder _headerObject; | 805 ObjectDecoder _headerObject; |
| 764 ListDecoder _elementList; | 806 ListDecoder _elementList; |
| 765 ListDecoder _typeList; | 807 ListDecoder _typeList; |
| 766 ListDecoder _constantList; | 808 ListDecoder _constantList; |
| 767 Map<int, Element> _elementMap = {}; | 809 Map<int, Element> _elementMap = {}; |
| 768 Map<int, DartType> _typeMap = {}; | 810 Map<int, DartType> _typeMap = {}; |
| 769 Map<int, ConstantExpression> _constantMap = {}; | 811 Map<int, ConstantExpression> _constantMap = {}; |
| 770 | 812 |
| 771 Deserializer.fromText(String text, this.decoder) { | 813 Deserializer.fromText(String text, this.decoder) { |
| 772 _headerObject = new ObjectDecoder(this, decoder.decode(text)); | 814 _headerObject = new ObjectDecoder(this, decoder.decode(text)); |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 811 return deserializeElement(object.getInt(Key.ID)); | 853 return deserializeElement(object.getInt(Key.ID)); |
| 812 } | 854 } |
| 813 } | 855 } |
| 814 } | 856 } |
| 815 return null; | 857 return null; |
| 816 } | 858 } |
| 817 | 859 |
| 818 /// Returns the deserialized [Element] for [id]. | 860 /// Returns the deserialized [Element] for [id]. |
| 819 Element deserializeElement(int id) { | 861 Element deserializeElement(int id) { |
| 820 if (id == null) throw new ArgumentError('Deserializer.getElement(null)'); | 862 if (id == null) throw new ArgumentError('Deserializer.getElement(null)'); |
| 821 return _elementMap.putIfAbsent(id, () { | 863 Element element = _elementMap[id]; |
| 822 return ElementDeserializer.deserialize(elements.getObject(id)); | 864 if (element == null) { |
| 823 }); | 865 ObjectDecoder decoder = elements.getObject(id); |
| 866 element = ElementDeserializer.deserialize(decoder); |
| 867 _elementMap[id] = element; |
| 868 |
| 869 MapDecoder pluginData = decoder.getMap(Key.DATA, isOptional: true); |
| 870 // Call plugins even when there is no data, so they can take action in |
| 871 // this case. |
| 872 for (DeserializerPlugin plugin in plugins) { |
| 873 plugin.onElement(element, |
| 874 (String tag) => pluginData?.getObject(tag, isOptional: true)); |
| 875 } |
| 876 } |
| 877 return element; |
| 824 } | 878 } |
| 825 | 879 |
| 826 /// Returns the deserialized [DartType] for [id]. | 880 /// Returns the deserialized [DartType] for [id]. |
| 827 DartType deserializeType(int id) { | 881 DartType deserializeType(int id) { |
| 828 if (id == null) throw new ArgumentError('Deserializer.getType(null)'); | 882 if (id == null) throw new ArgumentError('Deserializer.getType(null)'); |
| 829 return _typeMap.putIfAbsent(id, () { | 883 return _typeMap.putIfAbsent(id, () { |
| 830 return TypeDeserializer.deserialize(types.getObject(id)); | 884 return TypeDeserializer.deserialize(types.getObject(id)); |
| 831 }); | 885 }); |
| 832 } | 886 } |
| 833 | 887 |
| (...skipping 21 matching lines...) Expand all Loading... |
| 855 | 909 |
| 856 /// Returns the value used to store [key] as a property in the encoding an | 910 /// Returns the value used to store [key] as a property in the encoding an |
| 857 /// [ObjectValue]. | 911 /// [ObjectValue]. |
| 858 /// | 912 /// |
| 859 /// Different encodings have different restrictions and capabilities as how | 913 /// Different encodings have different restrictions and capabilities as how |
| 860 /// to store a [Key] value. For instance: A JSON encoding needs to convert | 914 /// to store a [Key] value. For instance: A JSON encoding needs to convert |
| 861 /// [Key] to a [String] to store it in a JSON object; a Dart encoding can | 915 /// [Key] to a [String] to store it in a JSON object; a Dart encoding can |
| 862 /// choose to store a [Key] as an [int] or as the [Key] itself. | 916 /// choose to store a [Key] as an [int] or as the [Key] itself. |
| 863 getObjectPropertyValue(Key key); | 917 getObjectPropertyValue(Key key); |
| 864 } | 918 } |
| OLD | NEW |