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 '../elements/elements.dart'; |
| 8 import '../constants/expressions.dart'; | 8 import '../constants/expressions.dart'; |
| 9 import '../dart_types.dart'; | 9 import '../dart_types.dart'; |
| 10 | 10 |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 81 | 81 |
| 82 /// The name of the encoder kind. Use for error reporting. | 82 /// The name of the encoder kind. Use for error reporting. |
| 83 String get _name; | 83 String get _name; |
| 84 | 84 |
| 85 void _checkKey(K key) { | 85 void _checkKey(K key) { |
| 86 if (_map.containsKey(key)) { | 86 if (_map.containsKey(key)) { |
| 87 throw new StateError("$_name value '$key' already in $_map."); | 87 throw new StateError("$_name value '$key' already in $_map."); |
| 88 } | 88 } |
| 89 } | 89 } |
| 90 | 90 |
| 91 /// Maps the [key] entry to the [value] in the encoded object. | |
| 92 void setValue(K key, Value value) { | |
| 93 _checkKey(key); | |
| 94 _map[key] = value; | |
| 95 } | |
| 96 | |
| 97 | |
| 91 /// Maps the [key] entry to the enum [value] in the encoded object. | 98 /// Maps the [key] entry to the enum [value] in the encoded object. |
| 92 void setEnum(K key, var value) { | 99 void setEnum(K key, var value) { |
| 93 _checkKey(key); | 100 _checkKey(key); |
| 94 _map[key] = new EnumValue(value); | 101 _map[key] = new EnumValue(value); |
| 95 } | 102 } |
| 96 | 103 |
| 97 /// Maps the [key] entry to the [element] in the encoded object. | 104 /// Maps the [key] entry to the [element] in the encoded object. |
| 98 void setElement(K key, Element element) { | 105 void setElement(K key, Element element) { |
| 99 _checkKey(key); | 106 _checkKey(key); |
| 100 _map[key] = _serializer.createElementValue(element); | 107 _map[key] = _serializer.createElementValue(element); |
| (...skipping 470 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 571 final ObjectValue objectValue; | 578 final ObjectValue objectValue; |
| 572 | 579 |
| 573 DataObject(Value id, EnumValue kind) | 580 DataObject(Value id, EnumValue kind) |
| 574 : this.id = id, | 581 : this.id = id, |
| 575 this.objectValue = | 582 this.objectValue = |
| 576 new ObjectValue(<Key, Value>{Key.ID: id, Key.KIND: kind}); | 583 new ObjectValue(<Key, Value>{Key.ID: id, Key.KIND: kind}); |
| 577 | 584 |
| 578 Map<Key, Value> get map => objectValue.map; | 585 Map<Key, Value> get map => objectValue.map; |
| 579 } | 586 } |
| 580 | 587 |
| 588 /// Function used to filter which element serialized. | |
| 589 typedef bool IncludeElementFunction(Element element); | |
|
Siggi Cherem (dart-lang)
2016/03/18 20:00:20
IncludeElementFunction => ElementMatcher
Johnni Winther
2016/03/29 09:05:54
Done.
| |
| 590 | |
| 591 bool includeAllElements(Element element) => true; | |
| 592 | |
| 581 /// Serializer for the transitive closure of a collection of libraries. | 593 /// Serializer for the transitive closure of a collection of libraries. |
| 582 /// | 594 /// |
| 583 /// The serializer creates an [ObjectValue] model of the [Element], [DartType] | 595 /// The serializer creates an [ObjectValue] model of the [Element], [DartType] |
| 584 /// and [ConstantExpression] values in the transitive closure of the serialized | 596 /// and [ConstantExpression] values in the transitive closure of the serialized |
| 585 /// libraries. | 597 /// libraries. |
| 586 /// | 598 /// |
| 587 /// The model layout of the produced [objectValue] is: | 599 /// The model layout of the produced [objectValue] is: |
| 588 /// | 600 /// |
| 589 /// { // Header object | 601 /// { // Header object |
| 590 /// Key.ELEMENTS: [ | 602 /// Key.ELEMENTS: [ |
| 591 /// {...}, // [ObjectValue] of the 0th [Element]. | 603 /// {...}, // [ObjectValue] of the 0th [Element]. |
| 592 /// ... | 604 /// ... |
| 593 /// {...}, // [ObjectValue] of the n-th [Element]. | 605 /// {...}, // [ObjectValue] of the n-th [Element]. |
| 594 /// ], | 606 /// ], |
| 595 /// Key.TYPES: [ | 607 /// Key.TYPES: [ |
| 596 /// {...}, // [ObjectValue] of the 0th [DartType]. | 608 /// {...}, // [ObjectValue] of the 0th [DartType]. |
| 597 /// ... | 609 /// ... |
| 598 /// {...}, // [ObjectValue] of the n-th [DartType]. | 610 /// {...}, // [ObjectValue] of the n-th [DartType]. |
| 599 /// ], | 611 /// ], |
| 600 /// Key.CONSTANTS: [ | 612 /// Key.CONSTANTS: [ |
| 601 /// {...}, // [ObjectValue] of the 0th [ConstantExpression]. | 613 /// {...}, // [ObjectValue] of the 0th [ConstantExpression]. |
| 602 /// ... | 614 /// ... |
| 603 /// {...}, // [ObjectValue] of the n-th [ConstantExpression]. | 615 /// {...}, // [ObjectValue] of the n-th [ConstantExpression]. |
| 604 /// ], | 616 /// ], |
| 605 /// } | 617 /// } |
| 606 /// | 618 /// |
| 607 // TODO(johnniwinther): Support per-library serialization and dependencies | 619 // TODO(johnniwinther): Support dependencies between serialized subcomponent. |
| 608 // between serialized subcomponent. | |
| 609 class Serializer { | 620 class Serializer { |
| 610 final SerializationEncoder _encoder; | |
| 611 List<SerializerPlugin> plugins = <SerializerPlugin>[]; | 621 List<SerializerPlugin> plugins = <SerializerPlugin>[]; |
| 612 | 622 |
| 623 Map<Uri, dynamic> _dependencyMap = <Uri, dynamic>{}; | |
| 613 Map<Element, DataObject> _elementMap = <Element, DataObject>{}; | 624 Map<Element, DataObject> _elementMap = <Element, DataObject>{}; |
| 614 Map<ConstantExpression, DataObject> _constantMap = | 625 Map<ConstantExpression, DataObject> _constantMap = |
| 615 <ConstantExpression, DataObject>{}; | 626 <ConstantExpression, DataObject>{}; |
| 616 Map<DartType, DataObject> _typeMap = <DartType, DataObject>{}; | 627 Map<DartType, DataObject> _typeMap = <DartType, DataObject>{}; |
| 617 List _pendingList = []; | 628 List _pendingList = []; |
| 629 IncludeElementFunction includeElement; | |
|
Siggi Cherem (dart-lang)
2016/03/18 20:00:20
rename to `shouldInclude`:
ElementMatcher shoul
Johnni Winther
2016/03/29 09:05:54
Done.
| |
| 618 | 630 |
| 619 Serializer(this._encoder); | 631 // TODO(johnniwinther): Replace [includeElement] with a general strategy. |
| 632 Serializer({this.includeElement: includeAllElements}); | |
| 620 | 633 |
| 621 /// Add the transitive closure of [library] to this serializer. | 634 /// Add the transitive closure of [library] to this serializer. |
| 622 void serialize(LibraryElement library) { | 635 void serialize(LibraryElement library) { |
| 623 // Call [_getElementDataObject] for its side-effect: To create a | 636 // Call [_getElementId] for its side-effect: To create a |
| 624 // [DataObject] for [library]. If not already created, this will | 637 // [DataObject] for [library]. If not already created, this will |
| 625 // put the serialization of [library] in the work queue. | 638 // put the serialization of [library] in the work queue. |
| 626 _getElementDataObject(library); | 639 _getElementId(library); |
| 627 } | 640 } |
| 628 | 641 |
| 629 void _emptyWorklist() { | 642 void _emptyWorklist() { |
| 630 while (_pendingList.isNotEmpty) { | 643 while (_pendingList.isNotEmpty) { |
| 631 _pendingList.removeLast()(); | 644 _pendingList.removeLast()(); |
| 632 } | 645 } |
| 633 } | 646 } |
| 634 | 647 |
| 635 /// Returns the [DataObject] for [element]. | 648 /// Returns the id [Value] for [element]. |
| 636 /// | 649 /// |
| 637 /// If [constant] has no [DataObject], a new [DataObject] is created and | 650 /// If [element] has no [DataObject], a new [DataObject] is created and |
| 638 /// encoding the [ObjectValue] for [constant] is put into the work queue of | 651 /// encoding the [ObjectValue] for [element] is put into the work queue of |
| 639 /// this serializer. | 652 /// this serializer. |
| 640 DataObject _getElementDataObject(Element element) { | 653 Value _getElementId(Element element) { |
| 641 if (element == null) { | 654 if (element == null) { |
| 642 throw new ArgumentError('Serializer._getElementDataObject(null)'); | 655 throw new ArgumentError('Serializer._getElementDataObject(null)'); |
| 643 } | 656 } |
| 644 DataObject dataObject = _elementMap[element]; | 657 DataObject dataObject = _elementMap[element]; |
| 645 if (dataObject == null) { | 658 if (dataObject == null) { |
| 646 // Run through [ELEMENT_SERIALIZERS] sequentially to find the one that | 659 if (!includeElement(element)) { |
| 647 // deals with [element]. | 660 if (element.isLibrary) { |
| 648 for (ElementSerializer serializer in ELEMENT_SERIALIZERS) { | 661 LibraryElement library = element; |
| 649 SerializedElementKind kind = serializer.getSerializedKind(element); | 662 _elementMap[element] = dataObject = new DataObject( |
| 650 if (kind != null) { | 663 new IntValue(_elementMap.length), |
| 651 dataObject = new DataObject( | 664 new EnumValue(SerializedElementKind.EXTERNAL_LIBRARY)); |
| 652 new IntValue(_elementMap.length), new EnumValue(kind)); | 665 ObjectEncoder encoder = new ObjectEncoder(this, dataObject.map); |
| 653 _elementMap[element] = dataObject; | 666 encoder.setUri(Key.URI, library.canonicalUri, library.canonicalUri); |
| 654 // Delay the serialization of the element itself to avoid loops, and | 667 } else if (element.isStatic) { |
| 655 // to keep the call stack small. | 668 Value classId =_getElementId(element.enclosingClass); |
| 656 _pendingList.add(() { | 669 _elementMap[element] = dataObject = new DataObject( |
| 657 ObjectEncoder encoder = new ObjectEncoder(this, dataObject.map); | 670 new IntValue(_elementMap.length), |
| 658 serializer.serialize(element, encoder, kind); | 671 new EnumValue(SerializedElementKind.EXTERNAL_STATIC_MEMBER)); |
| 672 ObjectEncoder encoder = new ObjectEncoder(this, dataObject.map); | |
| 673 encoder.setValue(Key.CLASS, classId); | |
| 674 encoder.setString(Key.NAME, element.name); | |
| 675 } else if (element.isConstructor) { | |
| 676 Value classId =_getElementId(element.enclosingClass); | |
| 677 _elementMap[element] = dataObject = new DataObject( | |
| 678 new IntValue(_elementMap.length), | |
| 679 new EnumValue(SerializedElementKind.EXTERNAL_CONSTRUCTOR)); | |
| 680 ObjectEncoder encoder = new ObjectEncoder(this, dataObject.map); | |
| 681 encoder.setValue(Key.CLASS, classId); | |
|
Siggi Cherem (dart-lang)
2016/03/18 20:00:20
Just to check: does the classId include the librar
Johnni Winther
2016/03/29 09:05:54
The class will be an EXTERNAL_LIBRARY_MEMBER, whic
| |
| 682 encoder.setString(Key.NAME, element.name); | |
| 683 } else { | |
| 684 Value libraryId =_getElementId(element.library); | |
| 685 _elementMap[element] = dataObject = new DataObject( | |
| 686 new IntValue(_elementMap.length), | |
| 687 new EnumValue(SerializedElementKind.EXTERNAL_LIBRARY_MEMBER)); | |
| 688 ObjectEncoder encoder = new ObjectEncoder(this, dataObject.map); | |
| 689 encoder.setValue(Key.LIBRARY, libraryId); | |
| 690 encoder.setString(Key.NAME, element.name); | |
| 691 } | |
| 692 } else { | |
| 693 // Run through [ELEMENT_SERIALIZERS] sequentially to find the one that | |
| 694 // deals with [element]. | |
| 695 for (ElementSerializer serializer in ELEMENT_SERIALIZERS) { | |
| 696 SerializedElementKind kind = serializer.getSerializedKind(element); | |
| 697 if (kind != null) { | |
| 698 _elementMap[element] = dataObject = new DataObject( | |
| 699 new IntValue(_elementMap.length), new EnumValue(kind)); | |
| 700 // Delay the serialization of the element itself to avoid loops, and | |
| 701 // to keep the call stack small. | |
| 702 _pendingList.add(() { | |
| 703 ObjectEncoder encoder = new ObjectEncoder(this, dataObject.map); | |
| 704 serializer.serialize(element, encoder, kind); | |
| 659 | 705 |
| 660 MapEncoder pluginData; | 706 MapEncoder pluginData; |
| 661 for (SerializerPlugin plugin in plugins) { | 707 for (SerializerPlugin plugin in plugins) { |
| 662 plugin.onElement(element, (String tag) { | 708 plugin.onElement(element, (String tag) { |
| 663 if (pluginData == null) { | 709 if (pluginData == null) { |
| 664 pluginData = encoder.createMap(Key.DATA); | 710 pluginData = encoder.createMap(Key.DATA); |
| 665 } | 711 } |
| 666 return pluginData.createObject(tag); | 712 return pluginData.createObject(tag); |
| 667 }); | 713 }); |
| 668 } | 714 } |
| 669 }); | 715 }); |
| 716 } | |
| 670 } | 717 } |
| 671 } | 718 } |
| 672 } | 719 } |
| 673 if (dataObject == null) { | 720 if (dataObject == null) { |
| 674 throw new UnsupportedError( | 721 throw new UnsupportedError( |
| 675 'Unsupported element: $element (${element.kind})'); | 722 'Unsupported element: $element (${element.kind})'); |
| 676 } | 723 } |
| 677 return dataObject; | 724 return dataObject.id; |
| 678 } | 725 } |
| 679 | 726 |
| 680 /// Creates the [ElementValue] for [element]. | 727 /// Creates the [ElementValue] for [element]. |
| 681 /// | 728 /// |
| 682 /// If [element] has not already been serialized, it is added to the work | 729 /// If [element] has not already been serialized, it is added to the work |
| 683 /// queue of this serializer. | 730 /// queue of this serializer. |
| 684 ElementValue createElementValue(Element element) { | 731 ElementValue createElementValue(Element element) { |
| 685 return new ElementValue(element, _getElementDataObject(element).id); | 732 return new ElementValue(element, _getElementId(element)); |
| 686 } | 733 } |
| 687 | 734 |
| 688 /// Returns the [DataObject] for [constant]. | 735 /// Returns the id [Value] for [constant]. |
| 689 /// | 736 /// |
| 690 /// If [constant] has no [DataObject], a new [DataObject] is created and | 737 /// If [constant] has no [DataObject], a new [DataObject] is created and |
| 691 /// encoding the [ObjectValue] for [constant] is put into the work queue of | 738 /// encoding the [ObjectValue] for [constant] is put into the work queue of |
| 692 /// this serializer. | 739 /// this serializer. |
| 693 DataObject _getConstantDataObject(ConstantExpression constant) { | 740 Value _getConstantId(ConstantExpression constant) { |
| 694 return _constantMap.putIfAbsent(constant, () { | 741 return _constantMap.putIfAbsent(constant, () { |
| 695 DataObject dataObject = new DataObject( | 742 DataObject dataObject = new DataObject( |
| 696 new IntValue(_constantMap.length), new EnumValue(constant.kind)); | 743 new IntValue(_constantMap.length), new EnumValue(constant.kind)); |
| 697 // Delay the serialization of the constant itself to avoid loops, and to | 744 // Delay the serialization of the constant itself to avoid loops, and to |
| 698 // keep the call stack small. | 745 // keep the call stack small. |
| 699 _pendingList.add(() => _encodeConstant(constant, dataObject)); | 746 _pendingList.add(() => _encodeConstant(constant, dataObject)); |
| 700 return dataObject; | 747 return dataObject; |
| 701 }); | 748 }).id; |
| 702 } | 749 } |
| 703 | 750 |
| 704 /// Encodes [constant] into the [ObjectValue] of [dataObject]. | 751 /// Encodes [constant] into the [ObjectValue] of [dataObject]. |
| 705 void _encodeConstant(ConstantExpression constant, DataObject dataObject) { | 752 void _encodeConstant(ConstantExpression constant, DataObject dataObject) { |
| 706 const ConstantSerializer().visit(constant, | 753 const ConstantSerializer().visit(constant, |
| 707 new ObjectEncoder(this, dataObject.map)); | 754 new ObjectEncoder(this, dataObject.map)); |
| 708 } | 755 } |
| 709 | 756 |
| 710 /// Creates the [ConstantValue] for [constant]. | 757 /// Creates the [ConstantValue] for [constant]. |
| 711 /// | 758 /// |
| 712 /// If [constant] has not already been serialized, it is added to the work | 759 /// If [constant] has not already been serialized, it is added to the work |
| 713 /// queue of this serializer. | 760 /// queue of this serializer. |
| 714 ConstantValue createConstantValue(ConstantExpression constant) { | 761 ConstantValue createConstantValue(ConstantExpression constant) { |
| 715 return new ConstantValue(constant, _getConstantDataObject(constant).id); | 762 return new ConstantValue(constant, _getConstantId(constant)); |
| 716 } | 763 } |
| 717 | 764 |
| 718 /// Returns the [DataObject] for [type]. | 765 /// Returns the id [Value] for [type]. |
| 719 /// | 766 /// |
| 720 /// If [type] has no [DataObject], a new [DataObject] is created and | 767 /// If [type] has no [DataObject], a new [DataObject] is created and |
| 721 /// encoding the [ObjectValue] for [type] is put into the work queue of this | 768 /// encoding the [ObjectValue] for [type] is put into the work queue of this |
| 722 /// serializer. | 769 /// serializer. |
| 723 DataObject _getTypeDataObject(DartType type) { | 770 Value _getTypeId(DartType type) { |
| 724 return _typeMap.putIfAbsent(type, () { | 771 DataObject dataObject = _typeMap[type]; |
| 725 DataObject dataObject = new DataObject( | 772 if (dataObject == null) { |
| 773 _typeMap[type] = dataObject = new DataObject( | |
| 726 new IntValue(_typeMap.length), new EnumValue(type.kind)); | 774 new IntValue(_typeMap.length), new EnumValue(type.kind)); |
| 727 // Delay the serialization of the type itself to avoid loops, and to keep | 775 // Delay the serialization of the type itself to avoid loops, and to keep |
| 728 // the call stack small. | 776 // the call stack small. |
| 729 _pendingList.add(() => _encodeType(type, dataObject)); | 777 _pendingList.add(() => _encodeType(type, dataObject)); |
| 730 return dataObject; | 778 } |
| 731 }); | 779 return dataObject.id; |
| 732 } | 780 } |
| 733 | 781 |
| 734 /// Encodes [type] into the [ObjectValue] of [dataObject]. | 782 /// Encodes [type] into the [ObjectValue] of [dataObject]. |
| 735 void _encodeType(DartType type, DataObject dataObject) { | 783 void _encodeType(DartType type, DataObject dataObject) { |
| 736 const TypeSerializer().visit(type, new ObjectEncoder(this, dataObject.map)); | 784 const TypeSerializer().visit(type, new ObjectEncoder(this, dataObject.map)); |
| 737 } | 785 } |
| 738 | 786 |
| 739 /// Creates the [TypeValue] for [type]. | 787 /// Creates the [TypeValue] for [type]. |
| 740 /// | 788 /// |
| 741 /// If [type] has not already been serialized, it is added to the work | 789 /// If [type] has not already been serialized, it is added to the work |
| 742 /// queue of this serializer. | 790 /// queue of this serializer. |
| 743 TypeValue createTypeValue(DartType type) { | 791 TypeValue createTypeValue(DartType type) { |
| 744 return new TypeValue(type, _getTypeDataObject(type).id); | 792 return new TypeValue(type, _getTypeId(type)); |
| 745 } | 793 } |
| 746 | 794 |
| 747 ObjectValue get objectValue { | 795 ObjectValue get objectValue { |
| 748 _emptyWorklist(); | 796 _emptyWorklist(); |
| 749 | 797 |
| 750 Map<Key, Value> map = <Key, Value>{}; | 798 Map<Key, Value> map = <Key, Value>{}; |
| 751 map[Key.ELEMENTS] = | 799 map[Key.ELEMENTS] = |
| 752 new ListValue(_elementMap.values.map((l) => l.objectValue).toList()); | 800 new ListValue(_elementMap.values.map((l) => l.objectValue).toList()); |
| 753 if (_typeMap.isNotEmpty) { | 801 if (_typeMap.isNotEmpty) { |
| 754 map[Key.TYPES] = | 802 map[Key.TYPES] = |
| 755 new ListValue(_typeMap.values.map((l) => l.objectValue).toList()); | 803 new ListValue(_typeMap.values.map((l) => l.objectValue).toList()); |
| 756 } | 804 } |
| 757 if (_constantMap.isNotEmpty) { | 805 if (_constantMap.isNotEmpty) { |
| 758 map[Key.CONSTANTS] = | 806 map[Key.CONSTANTS] = |
| 759 new ListValue(_constantMap.values.map((l) => l.objectValue).toList()); | 807 new ListValue(_constantMap.values.map((l) => l.objectValue).toList()); |
| 760 } | 808 } |
| 761 return new ObjectValue(map); | 809 return new ObjectValue(map); |
| 762 } | 810 } |
| 763 | 811 |
| 764 String toText() { | 812 String toText(SerializationEncoder encoder) { |
| 765 return _encoder.encode(objectValue); | 813 return encoder.encode(objectValue); |
| 766 } | 814 } |
| 767 | 815 |
| 768 String prettyPrint() { | 816 String prettyPrint() { |
| 769 PrettyPrintEncoder encoder = new PrettyPrintEncoder(); | 817 PrettyPrintEncoder encoder = new PrettyPrintEncoder(); |
| 770 return encoder.toText(objectValue); | 818 return encoder.toText(objectValue); |
| 771 } | 819 } |
| 772 } | 820 } |
| 773 | 821 |
| 774 /// Plugin for serializing additional data for an [Element]. | 822 /// Plugin for serializing additional data for an [Element]. |
| 775 class SerializerPlugin { | 823 class SerializerPlugin { |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 786 class DeserializerPlugin { | 834 class DeserializerPlugin { |
| 787 const DeserializerPlugin(); | 835 const DeserializerPlugin(); |
| 788 | 836 |
| 789 /// Called upon the deserialization of [element]. | 837 /// Called upon the deserialization of [element]. |
| 790 /// | 838 /// |
| 791 /// Use [getDecoder] to retrieve the data object with id [tag] stored for | 839 /// Use [getDecoder] to retrieve the data object with id [tag] stored for |
| 792 /// [element]. If not object is stored for [tag], [getDecoder] returns `null`. | 840 /// [element]. If not object is stored for [tag], [getDecoder] returns `null`. |
| 793 void onElement(Element element, ObjectDecoder getDecoder(String tag)) {} | 841 void onElement(Element element, ObjectDecoder getDecoder(String tag)) {} |
| 794 } | 842 } |
| 795 | 843 |
| 844 /// Context for parallel deserialization. | |
| 845 class DeserializationContext { | |
| 846 Map<Uri, LibraryElement> _uriMap = <Uri, LibraryElement>{}; | |
| 847 List<Deserializer> deserializers = <Deserializer>[]; | |
| 848 | |
| 849 LibraryElement lookupLibrary(Uri uri) { | |
| 850 return _uriMap.putIfAbsent(uri, () { | |
| 851 for (Deserializer deserializer in deserializers) { | |
| 852 LibraryElement library = deserializer.lookupLibrary(uri); | |
| 853 if (library != null) { | |
| 854 return library; | |
| 855 } | |
| 856 } | |
| 857 return null; | |
| 858 }); | |
| 859 } | |
| 860 } | |
| 861 | |
| 796 /// Deserializer for a closed collection of libraries. | 862 /// Deserializer for a closed collection of libraries. |
| 797 // TODO(johnniwinther): Support per-library deserialization and dependencies | 863 // TODO(johnniwinther): Support per-library deserialization and dependencies |
| 798 // between deserialized subcomponent. | 864 // between deserialized subcomponent. |
| 799 class Deserializer { | 865 class Deserializer { |
| 866 final DeserializationContext context; | |
| 800 final SerializationDecoder decoder; | 867 final SerializationDecoder decoder; |
| 801 List<DeserializerPlugin> plugins = <DeserializerPlugin>[]; | 868 List<DeserializerPlugin> plugins = <DeserializerPlugin>[]; |
| 802 ObjectDecoder _headerObject; | 869 ObjectDecoder _headerObject; |
| 803 ListDecoder _elementList; | 870 ListDecoder _elementList; |
| 804 ListDecoder _typeList; | 871 ListDecoder _typeList; |
| 805 ListDecoder _constantList; | 872 ListDecoder _constantList; |
| 806 Map<int, Element> _elementMap = {}; | 873 Map<int, Element> _elementMap = {}; |
| 807 Map<int, DartType> _typeMap = {}; | 874 Map<int, DartType> _typeMap = {}; |
| 808 Map<int, ConstantExpression> _constantMap = {}; | 875 Map<int, ConstantExpression> _constantMap = {}; |
| 809 | 876 |
| 810 Deserializer.fromText(String text, this.decoder) { | 877 Deserializer.fromText(this.context, String text, this.decoder) { |
| 811 _headerObject = new ObjectDecoder(this, decoder.decode(text)); | 878 _headerObject = new ObjectDecoder(this, decoder.decode(text)); |
| 879 context.deserializers.add(this); | |
| 812 } | 880 } |
| 813 | 881 |
| 814 /// Returns the [ListDecoder] for the [Element]s in this deserializer. | 882 /// Returns the [ListDecoder] for the [Element]s in this deserializer. |
| 815 ListDecoder get elements { | 883 ListDecoder get elements { |
| 816 if (_elementList == null) { | 884 if (_elementList == null) { |
| 817 _elementList = _headerObject.getList(Key.ELEMENTS); | 885 _elementList = _headerObject.getList(Key.ELEMENTS); |
| 818 } | 886 } |
| 819 return _elementList; | 887 return _elementList; |
| 820 } | 888 } |
| 821 | 889 |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 853 } | 921 } |
| 854 return null; | 922 return null; |
| 855 } | 923 } |
| 856 | 924 |
| 857 /// Returns the deserialized [Element] for [id]. | 925 /// Returns the deserialized [Element] for [id]. |
| 858 Element deserializeElement(int id) { | 926 Element deserializeElement(int id) { |
| 859 if (id == null) throw new ArgumentError('Deserializer.getElement(null)'); | 927 if (id == null) throw new ArgumentError('Deserializer.getElement(null)'); |
| 860 Element element = _elementMap[id]; | 928 Element element = _elementMap[id]; |
| 861 if (element == null) { | 929 if (element == null) { |
| 862 ObjectDecoder decoder = elements.getObject(id); | 930 ObjectDecoder decoder = elements.getObject(id); |
| 863 element = ElementDeserializer.deserialize(decoder); | 931 SerializedElementKind elementKind = |
| 932 decoder.getEnum(Key.KIND, SerializedElementKind.values); | |
| 933 if (elementKind == SerializedElementKind.EXTERNAL_LIBRARY) { | |
| 934 Uri uri = decoder.getUri(Key.URI); | |
| 935 element = context.lookupLibrary(uri); | |
| 936 if (element == null) { | |
| 937 throw new StateError("Missing library for $uri."); | |
| 938 } | |
| 939 } else if (elementKind == SerializedElementKind.EXTERNAL_LIBRARY_MEMBER) { | |
| 940 LibraryElement library = decoder.getElement(Key.LIBRARY); | |
| 941 String name = decoder.getString(Key.NAME); | |
| 942 element = library.find(name); | |
| 943 if (element == null) { | |
| 944 throw new StateError("Missing library member for $name in $library."); | |
| 945 } | |
| 946 } else if (elementKind == SerializedElementKind.EXTERNAL_STATIC_MEMBER) { | |
| 947 ClassElement cls = decoder.getElement(Key.CLASS); | |
| 948 String name = decoder.getString(Key.NAME); | |
| 949 element = cls.lookupLocalMember(name); | |
| 950 if (element == null) { | |
| 951 throw new StateError("Missing static member for $name in $cls."); | |
| 952 } | |
| 953 } else if (elementKind == SerializedElementKind.EXTERNAL_CONSTRUCTOR) { | |
| 954 ClassElement cls = decoder.getElement(Key.CLASS); | |
| 955 String name = decoder.getString(Key.NAME); | |
| 956 element = cls.lookupConstructor(name); | |
| 957 if (element == null) { | |
| 958 throw new StateError("Missing constructor for $name in $cls."); | |
| 959 } | |
| 960 } else { | |
| 961 element = ElementDeserializer.deserialize(decoder, elementKind); | |
| 962 } | |
| 864 _elementMap[id] = element; | 963 _elementMap[id] = element; |
| 865 | 964 |
| 866 MapDecoder pluginData = decoder.getMap(Key.DATA, isOptional: true); | 965 MapDecoder pluginData = decoder.getMap(Key.DATA, isOptional: true); |
| 867 // Call plugins even when there is no data, so they can take action in | 966 // Call plugins even when there is no data, so they can take action in |
| 868 // this case. | 967 // this case. |
| 869 for (DeserializerPlugin plugin in plugins) { | 968 for (DeserializerPlugin plugin in plugins) { |
| 870 plugin.onElement(element, | 969 plugin.onElement(element, |
| 871 (String tag) => pluginData?.getObject(tag, isOptional: true)); | 970 (String tag) => pluginData?.getObject(tag, isOptional: true)); |
| 872 } | 971 } |
| 873 } | 972 } |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 906 | 1005 |
| 907 /// Returns the value used to store [key] as a property in the encoding an | 1006 /// Returns the value used to store [key] as a property in the encoding an |
| 908 /// [ObjectValue]. | 1007 /// [ObjectValue]. |
| 909 /// | 1008 /// |
| 910 /// Different encodings have different restrictions and capabilities as how | 1009 /// Different encodings have different restrictions and capabilities as how |
| 911 /// to store a [Key] value. For instance: A JSON encoding needs to convert | 1010 /// to store a [Key] value. For instance: A JSON encoding needs to convert |
| 912 /// [Key] to a [String] to store it in a JSON object; a Dart encoding can | 1011 /// [Key] to a [String] to store it in a JSON object; a Dart encoding can |
| 913 /// choose to store a [Key] as an [int] or as the [Key] itself. | 1012 /// choose to store a [Key] as an [int] or as the [Key] itself. |
| 914 getObjectPropertyValue(Key key); | 1013 getObjectPropertyValue(Key key); |
| 915 } | 1014 } |
| OLD | NEW |