| // Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file | |
| // for details. All rights reserved. Use of this source code is governed by a | |
| // BSD-style license that can be found in the LICENSE file. | |
| library; | |
| import 'package:kernel/ast.dart' as ir show LocalFunction; | |
| import '../common/names.dart' show Names; | |
| import '../elements/entities.dart'; | |
| import '../elements/entity_map.dart'; | |
| import '../elements/names.dart'; | |
| import '../elements/types.dart'; | |
| import '../serialization/serialization.dart'; | |
| import '../universe/class_set.dart' show ClassHierarchyNodesMapKey; | |
| import '../universe/selector.dart'; | |
| import 'closure.dart'; | |
| import 'records.dart' show JRecordClass, JRecordGetter; | |
| const String jsElementPrefix = 'j:'; | |
| class JLibrary with EntityMapKey implements LibraryEntity { | |
| /// Tag used for identifying serialized [JLibrary] objects in a | |
| /// debugging data stream. | |
| static const String tag = 'library'; | |
| @override | |
| final String name; | |
| @override | |
| final Uri canonicalUri; | |
| JLibrary(this.name, this.canonicalUri); | |
| /// Deserializes a [JLibrary] object from [source]. | |
| factory JLibrary.readFromDataSource(DataSourceReader source) { | |
| source.begin(tag); | |
| String name = source.readString(); | |
| Uri canonicalUri = source.readUri(); | |
| source.end(tag); | |
| return JLibrary(name, canonicalUri); | |
| } | |
| /// Serializes this [JLibrary] to [sink]. | |
| void writeToDataSink(DataSinkWriter sink) { | |
| sink.begin(tag); | |
| sink.writeString(name); | |
| sink.writeUri(canonicalUri); | |
| sink.end(tag); | |
| } | |
| @override | |
| String toString() => '${jsElementPrefix}library($name)'; | |
| } | |
| /// Enum used for identifying [JClass] subclasses in serialization. | |
| enum JClassKind { node, closure, context, record } | |
| class JClass | |
| with ClassHierarchyNodesMapKey, EntityMapKey | |
| implements ClassEntity { | |
| /// Tag used for identifying serialized [JClass] objects in a | |
| /// debugging data stream. | |
| static const String tag = 'class'; | |
| @override | |
| final JLibrary library; | |
| @override | |
| final String name; | |
| @override | |
| final bool isAbstract; | |
| JClass(this.library, this.name, {required this.isAbstract}); | |
| /// Deserializes a [JClass] object from [source]. | |
| factory JClass.readFromDataSource(DataSourceReader source) { | |
| JClassKind kind = source.readEnum(JClassKind.values); | |
| switch (kind) { | |
| case JClassKind.node: | |
| source.begin(tag); | |
| final library = source.readLibrary() as JLibrary; | |
| String name = source.readString(); | |
| bool isAbstract = source.readBool(); | |
| source.end(tag); | |
| return JClass(library, name, isAbstract: isAbstract); | |
| case JClassKind.closure: | |
| return JClosureClass.readFromDataSource(source); | |
| case JClassKind.context: | |
| return JContext.readFromDataSource(source); | |
| case JClassKind.record: | |
| return JRecordClass.readFromDataSource(source); | |
| } | |
| } | |
| /// Serializes this [JClass] to [sink]. | |
| void writeToDataSink(DataSinkWriter sink) { | |
| sink.writeEnum(JClassKind.node); | |
| sink.begin(tag); | |
| sink.writeLibrary(library); | |
| sink.writeString(name); | |
| sink.writeBool(isAbstract); | |
| sink.end(tag); | |
| } | |
| @override | |
| bool get isClosure => false; | |
| @override | |
| String toString() => '${jsElementPrefix}class($name)'; | |
| } | |
| /// Enum used for identifying [JMember] subclasses in serialization. | |
| enum JMemberKind { | |
| generativeConstructor, | |
| factoryConstructor, | |
| constructorBody, | |
| field, | |
| getter, | |
| setter, | |
| method, | |
| closureField, | |
| closureCallMethod, | |
| generatorBody, | |
| signatureMethod, | |
| contextField, | |
| recordGetter, | |
| parameterStub, | |
| } | |
| String _membertoString(JMember member) => | |
| '$jsElementPrefix${member._kind}' | |
| '(${member.enclosingClass != null ? '${member.enclosingClass!.name}.' : ''}' | |
| '${member.name})'; | |
| abstract class JMember with EntityMapKey implements MemberEntity { | |
| @override | |
| final JLibrary library; | |
| @override | |
| final JClass? enclosingClass; | |
| final Name _name; | |
| final bool _isStatic; | |
| JMember( | |
| this.library, | |
| this.enclosingClass, | |
| this._name, { | |
| this._isStatic = false, | |
| }); | |
| /// Deserializes a [JMember] object from [source]. | |
| factory JMember.readFromDataSource(DataSourceReader source) { | |
| JMemberKind kind = source.readEnum(JMemberKind.values); | |
| switch (kind) { | |
| case JMemberKind.generativeConstructor: | |
| return JGenerativeConstructor.readFromDataSource(source); | |
| case JMemberKind.factoryConstructor: | |
| return JFactoryConstructor.readFromDataSource(source); | |
| case JMemberKind.constructorBody: | |
| return JConstructorBody.readFromDataSource(source); | |
| case JMemberKind.field: | |
| return JField.readFromDataSource(source); | |
| case JMemberKind.getter: | |
| return JGetter.readFromDataSource(source); | |
| case JMemberKind.setter: | |
| return JSetter.readFromDataSource(source); | |
| case JMemberKind.method: | |
| return JMethod.readFromDataSource(source); | |
| case JMemberKind.closureField: | |
| return JClosureField.readFromDataSource(source); | |
| case JMemberKind.closureCallMethod: | |
| return JClosureCallMethod.readFromDataSource(source); | |
| case JMemberKind.generatorBody: | |
| return JGeneratorBody.readFromDataSource(source); | |
| case JMemberKind.signatureMethod: | |
| return JSignatureMethod.readFromDataSource(source); | |
| case JMemberKind.contextField: | |
| return JContextField.readFromDataSource(source); | |
| case JMemberKind.recordGetter: | |
| return JRecordGetter.readFromDataSource(source); | |
| case JMemberKind.parameterStub: | |
| return JParameterStub.readFromDataSource(source); | |
| } | |
| } | |
| /// Serializes this [JMember] to [sink]. | |
| void writeToDataSink(DataSinkWriter sink); | |
| @override | |
| String get name => _name.text; | |
| @override | |
| Name get memberName => _name; | |
| @override | |
| bool get isAssignable => false; | |
| @override | |
| bool get isConst => false; | |
| @override | |
| bool get isAbstract => false; | |
| @override | |
| bool get isSetter => false; | |
| @override | |
| bool get isGetter => false; | |
| @override | |
| bool get isFunction => false; | |
| @override | |
| bool get isInstanceMember => enclosingClass != null && !_isStatic; | |
| @override | |
| bool get isStatic => enclosingClass != null && _isStatic; | |
| @override | |
| bool get isTopLevel => enclosingClass == null; | |
| String get _kind; | |
| @override | |
| String toString() => _membertoString(this); | |
| } | |
| abstract class JFunction extends JMember implements FunctionEntity { | |
| @override | |
| final ParameterStructure parameterStructure; | |
| @override | |
| final bool isExternal; | |
| @override | |
| final AsyncMarker asyncMarker; | |
| JFunction( | |
| super.library, | |
| super.enclosingClass, | |
| super.name, | |
| this.parameterStructure, | |
| this.asyncMarker, { | |
| super.isStatic, | |
| this.isExternal = false, | |
| }); | |
| } | |
| abstract class JConstructor extends JFunction implements ConstructorEntity { | |
| @override | |
| final bool isConst; | |
| JConstructor( | |
| JClass enclosingClass, | |
| Name name, | |
| ParameterStructure parameterStructure, { | |
| required super.isExternal, | |
| required this.isConst, | |
| }) : super( | |
| enclosingClass.library, | |
| enclosingClass, | |
| name, | |
| parameterStructure, | |
| AsyncMarker.sync, | |
| ); | |
| @override | |
| JClass get enclosingClass => super.enclosingClass!; | |
| @override | |
| bool get isInstanceMember => false; | |
| @override | |
| bool get isStatic => false; | |
| @override | |
| bool get isTopLevel => false; | |
| @override | |
| bool get isFromEnvironmentConstructor => false; | |
| @override | |
| String get _kind => 'constructor'; | |
| } | |
| class JGenerativeConstructor extends JConstructor { | |
| /// Tag used for identifying serialized [JGenerativeConstructor] objects in a | |
| /// debugging data stream. | |
| static const String tag = 'generative-constructor'; | |
| JGenerativeConstructor( | |
| super.enclosingClass, | |
| super.name, | |
| super.parameterStructure, { | |
| required super.isExternal, | |
| required super.isConst, | |
| }); | |
| factory JGenerativeConstructor.readFromDataSource(DataSourceReader source) { | |
| source.begin(tag); | |
| final enclosingClass = source.readClass() as JClass; | |
| String name = source.readString(); | |
| ParameterStructure parameterStructure = | |
| ParameterStructure.readFromDataSource(source); | |
| bool isExternal = source.readBool(); | |
| bool isConst = source.readBool(); | |
| source.end(tag); | |
| return JGenerativeConstructor( | |
| enclosingClass, | |
| Name(name, enclosingClass.library.canonicalUri), | |
| parameterStructure, | |
| isExternal: isExternal, | |
| isConst: isConst, | |
| ); | |
| } | |
| @override | |
| void writeToDataSink(DataSinkWriter sink) { | |
| sink.writeEnum(JMemberKind.generativeConstructor); | |
| sink.begin(tag); | |
| sink.writeClass(enclosingClass); | |
| sink.writeString(name); | |
| parameterStructure.writeToDataSink(sink); | |
| sink.writeBool(isExternal); | |
| sink.writeBool(isConst); | |
| sink.end(tag); | |
| } | |
| @override | |
| bool get isFactoryConstructor => false; | |
| @override | |
| bool get isGenerativeConstructor => true; | |
| } | |
| class JFactoryConstructor extends JConstructor { | |
| /// Tag used for identifying serialized [JFactoryConstructor] objects in a | |
| /// debugging data stream. | |
| static const String tag = 'factory-constructor'; | |
| @override | |
| final bool isFromEnvironmentConstructor; | |
| JFactoryConstructor( | |
| super.enclosingClass, | |
| super.name, | |
| super.parameterStructure, { | |
| required super.isExternal, | |
| required super.isConst, | |
| required this.isFromEnvironmentConstructor, | |
| }); | |
| factory JFactoryConstructor.readFromDataSource(DataSourceReader source) { | |
| source.begin(tag); | |
| final enclosingClass = source.readClass() as JClass; | |
| String name = source.readString(); | |
| ParameterStructure parameterStructure = | |
| ParameterStructure.readFromDataSource(source); | |
| bool isExternal = source.readBool(); | |
| bool isConst = source.readBool(); | |
| bool isFromEnvironmentConstructor = source.readBool(); | |
| source.end(tag); | |
| return JFactoryConstructor( | |
| enclosingClass, | |
| Name(name, enclosingClass.library.canonicalUri), | |
| parameterStructure, | |
| isExternal: isExternal, | |
| isConst: isConst, | |
| isFromEnvironmentConstructor: isFromEnvironmentConstructor, | |
| ); | |
| } | |
| @override | |
| void writeToDataSink(DataSinkWriter sink) { | |
| sink.writeEnum(JMemberKind.factoryConstructor); | |
| sink.begin(tag); | |
| sink.writeClass(enclosingClass); | |
| sink.writeString(name); | |
| parameterStructure.writeToDataSink(sink); | |
| sink.writeBool(isExternal); | |
| sink.writeBool(isConst); | |
| sink.writeBool(isFromEnvironmentConstructor); | |
| sink.end(tag); | |
| } | |
| @override | |
| bool get isFactoryConstructor => true; | |
| @override | |
| bool get isGenerativeConstructor => false; | |
| } | |
| class JConstructorBody extends JFunction implements ConstructorBodyEntity { | |
| /// Tag used for identifying serialized [JConstructorBody] objects in a | |
| /// debugging data stream. | |
| static const String tag = 'constructor-body'; | |
| @override | |
| final JConstructor constructor; | |
| JConstructorBody(this.constructor, ParameterStructure parameterStructure) | |
| : super( | |
| constructor.library, | |
| constructor.enclosingClass, | |
| constructor.memberName, | |
| parameterStructure, | |
| AsyncMarker.sync, | |
| isStatic: false, | |
| isExternal: constructor.isExternal, | |
| ); | |
| factory JConstructorBody.readFromDataSource(DataSourceReader source) { | |
| source.begin(tag); | |
| final constructor = source.readMember() as JConstructor; | |
| ParameterStructure parameterStructure = | |
| ParameterStructure.readFromDataSource(source); | |
| source.end(tag); | |
| return JConstructorBody(constructor, parameterStructure); | |
| } | |
| @override | |
| void writeToDataSink(DataSinkWriter sink) { | |
| sink.writeEnum(JMemberKind.constructorBody); | |
| sink.begin(tag); | |
| sink.writeMember(constructor); | |
| parameterStructure.writeToDataSink(sink); | |
| sink.end(tag); | |
| } | |
| @override | |
| String get _kind => 'constructor_body'; | |
| /// These lazy member bodies implement `==` since different SSA shards can | |
| /// create different copies of the same constructor body. Upon deserialization | |
| /// we should consider the different copies equivalent. | |
| @override | |
| bool operator ==(Object other) { | |
| return other is JConstructorBody && constructor == other.constructor; | |
| } | |
| @override | |
| int get hashCode => constructor.hashCode + 7; | |
| } | |
| class JParameterStub with EntityMapKey implements JMethod { | |
| static const String kind = 'parameter-stub'; | |
| final JFunction target; | |
| @override | |
| final ParameterStructure parameterStructure; | |
| final Selector? callSelector; | |
| final bool needsSuper; | |
| JParameterStub( | |
| this.target, | |
| this.parameterStructure, { | |
| required this.callSelector, | |
| required this.needsSuper, | |
| }); | |
| @override | |
| String toString() => _membertoString(this); | |
| @override | |
| String get _kind => 'parameter_stub'; | |
| @override | |
| bool get _isStatic => target._isStatic; | |
| @override | |
| Name get _name => target._name; | |
| @override | |
| AsyncMarker get asyncMarker => target.asyncMarker; | |
| @override | |
| JClass? get enclosingClass => target.enclosingClass; | |
| @override | |
| bool get isAbstract => target.isAbstract; | |
| @override | |
| bool get isAssignable => target.isAssignable; | |
| @override | |
| bool get isConst => target.isConst; | |
| @override | |
| bool get isExternal => target.isExternal; | |
| @override | |
| bool get isFunction => target.isFunction; | |
| @override | |
| bool get isGetter => target.isGetter; | |
| @override | |
| bool get isInstanceMember => target.isInstanceMember; | |
| @override | |
| bool get isSetter => target.isSetter; | |
| @override | |
| bool get isStatic => target.isStatic; | |
| @override | |
| bool get isTopLevel => target.isTopLevel; | |
| @override | |
| JLibrary get library => target.library; | |
| @override | |
| Name get memberName => target.memberName; | |
| @override | |
| String get name => target.name; | |
| @override | |
| void writeToDataSink(DataSinkWriter sink) { | |
| sink.writeEnum(JMemberKind.parameterStub); | |
| sink.begin(kind); | |
| sink.writeMember(target); | |
| parameterStructure.writeToDataSink(sink); | |
| sink.writeValueOrNull(callSelector, (value) => value.writeToDataSink(sink)); | |
| sink.writeBool(needsSuper); | |
| sink.end(kind); | |
| } | |
| factory JParameterStub.readFromDataSource(DataSourceReader source) { | |
| source.begin(kind); | |
| final target = source.readMember() as JFunction; | |
| final parameterStructure = ParameterStructure.readFromDataSource(source); | |
| final callSelector = source.readValueOrNull( | |
| () => Selector.readFromDataSource(source), | |
| ); | |
| final needsSuper = source.readBool(); | |
| source.end(kind); | |
| return JParameterStub( | |
| target, | |
| parameterStructure, | |
| callSelector: callSelector, | |
| needsSuper: needsSuper, | |
| ); | |
| } | |
| } | |
| class JMethod extends JFunction { | |
| /// Tag used for identifying serialized [JMethod] objects in a | |
| /// debugging data stream. | |
| static const String tag = 'method'; | |
| @override | |
| final bool isAbstract; | |
| JMethod( | |
| super.library, | |
| super.enclosingClass, | |
| super.name, | |
| super.parameterStructure, | |
| super.asyncMarker, { | |
| required super.isStatic, | |
| required super.isExternal, | |
| required this.isAbstract, | |
| }); | |
| factory JMethod.readFromDataSource(DataSourceReader source) { | |
| source.begin(tag); | |
| MemberContextKind kind = source.readEnum(MemberContextKind.values); | |
| late final JLibrary library; | |
| JClass? enclosingClass; | |
| switch (kind) { | |
| case MemberContextKind.library: | |
| library = source.readLibrary() as JLibrary; | |
| break; | |
| case MemberContextKind.cls: | |
| enclosingClass = source.readClass() as JClass; | |
| library = enclosingClass.library; | |
| break; | |
| } | |
| Name memberName = source.readMemberName(); | |
| ParameterStructure parameterStructure = | |
| ParameterStructure.readFromDataSource(source); | |
| AsyncMarker asyncMarker = source.readEnum(AsyncMarker.values); | |
| bool isStatic = source.readBool(); | |
| bool isExternal = source.readBool(); | |
| bool isAbstract = source.readBool(); | |
| source.end(tag); | |
| return JMethod( | |
| library, | |
| enclosingClass, | |
| memberName, | |
| parameterStructure, | |
| asyncMarker, | |
| isStatic: isStatic, | |
| isExternal: isExternal, | |
| isAbstract: isAbstract, | |
| ); | |
| } | |
| @override | |
| void writeToDataSink(DataSinkWriter sink) { | |
| sink.writeEnum(JMemberKind.method); | |
| sink.begin(tag); | |
| if (enclosingClass != null) { | |
| sink.writeEnum(MemberContextKind.cls); | |
| sink.writeClass(enclosingClass!); | |
| } else { | |
| sink.writeEnum(MemberContextKind.library); | |
| sink.writeLibrary(library); | |
| } | |
| sink.writeMemberName(memberName); | |
| parameterStructure.writeToDataSink(sink); | |
| sink.writeEnum(asyncMarker); | |
| sink.writeBool(isStatic); | |
| sink.writeBool(isExternal); | |
| sink.writeBool(isAbstract); | |
| sink.end(tag); | |
| } | |
| @override | |
| bool get isFunction => true; | |
| @override | |
| String get _kind => 'method'; | |
| } | |
| class JGeneratorBody extends JFunction { | |
| /// Tag used for identifying serialized [JGeneratorBody] objects in a | |
| /// debugging data stream. | |
| static const String tag = 'generator-body'; | |
| final JFunction function; | |
| final DartType elementType; | |
| @override | |
| final int hashCode; | |
| JGeneratorBody(this.function, this.elementType) | |
| : hashCode = function.hashCode + 1, // Hack stabilize sort order. | |
| super( | |
| function.library, | |
| function.enclosingClass, | |
| function.memberName, | |
| function.parameterStructure, | |
| function.asyncMarker, | |
| isStatic: function.isStatic, | |
| isExternal: false, | |
| ); | |
| factory JGeneratorBody.readFromDataSource(DataSourceReader source) { | |
| source.begin(tag); | |
| final function = source.readMember() as JFunction; | |
| DartType elementType = source.readDartType(); | |
| source.end(tag); | |
| return JGeneratorBody(function, elementType); | |
| } | |
| @override | |
| void writeToDataSink(DataSinkWriter sink) { | |
| sink.writeEnum(JMemberKind.generatorBody); | |
| sink.begin(tag); | |
| sink.writeMember(function); | |
| sink.writeDartType(elementType); | |
| sink.end(tag); | |
| } | |
| @override | |
| String get _kind => 'generator_body'; | |
| /// These lazy member bodies implement `==` since different SSA shards can | |
| /// create different copies of the same constructor body. Upon deserialization | |
| /// we should consider the different copies equivalent. | |
| @override | |
| bool operator ==(Object other) { | |
| return other is JGeneratorBody && function == other.function; | |
| } | |
| } | |
| class JGetter extends JFunction { | |
| /// Tag used for identifying serialized [JGetter] objects in a | |
| /// debugging data stream. | |
| static const String tag = 'getter'; | |
| @override | |
| final bool isAbstract; | |
| JGetter( | |
| JLibrary library, | |
| JClass? enclosingClass, | |
| Name name, | |
| AsyncMarker asyncMarker, { | |
| required super.isStatic, | |
| required super.isExternal, | |
| required this.isAbstract, | |
| }) : super( | |
| library, | |
| enclosingClass, | |
| name, | |
| ParameterStructure.getter, | |
| asyncMarker, | |
| ); | |
| factory JGetter.readFromDataSource(DataSourceReader source) { | |
| source.begin(tag); | |
| MemberContextKind kind = source.readEnum(MemberContextKind.values); | |
| late final JLibrary library; | |
| JClass? enclosingClass; | |
| switch (kind) { | |
| case MemberContextKind.library: | |
| library = source.readLibrary() as JLibrary; | |
| break; | |
| case MemberContextKind.cls: | |
| enclosingClass = source.readClass() as JClass; | |
| library = enclosingClass.library; | |
| break; | |
| } | |
| Name memberName = source.readMemberName(); | |
| AsyncMarker asyncMarker = source.readEnum(AsyncMarker.values); | |
| bool isStatic = source.readBool(); | |
| bool isExternal = source.readBool(); | |
| bool isAbstract = source.readBool(); | |
| source.end(tag); | |
| return JGetter( | |
| library, | |
| enclosingClass, | |
| memberName, | |
| asyncMarker, | |
| isStatic: isStatic, | |
| isExternal: isExternal, | |
| isAbstract: isAbstract, | |
| ); | |
| } | |
| @override | |
| void writeToDataSink(DataSinkWriter sink) { | |
| sink.writeEnum(JMemberKind.getter); | |
| sink.begin(tag); | |
| if (enclosingClass != null) { | |
| sink.writeEnum(MemberContextKind.cls); | |
| sink.writeClass(enclosingClass!); | |
| } else { | |
| sink.writeEnum(MemberContextKind.library); | |
| sink.writeLibrary(library); | |
| } | |
| sink.writeMemberName(memberName); | |
| sink.writeEnum(asyncMarker); | |
| sink.writeBool(isStatic); | |
| sink.writeBool(isExternal); | |
| sink.writeBool(isAbstract); | |
| sink.end(tag); | |
| } | |
| @override | |
| bool get isGetter => true; | |
| @override | |
| String get _kind => 'getter'; | |
| } | |
| class JSetter extends JFunction { | |
| /// Tag used for identifying serialized [JSetter] objects in a | |
| /// debugging data stream. | |
| static const String tag = 'setter'; | |
| @override | |
| final bool isAbstract; | |
| JSetter( | |
| JLibrary library, | |
| JClass? enclosingClass, | |
| Name name, { | |
| required super.isStatic, | |
| required super.isExternal, | |
| required this.isAbstract, | |
| }) : super( | |
| library, | |
| enclosingClass, | |
| name, | |
| ParameterStructure.setter, | |
| AsyncMarker.sync, | |
| ); | |
| factory JSetter.readFromDataSource(DataSourceReader source) { | |
| source.begin(tag); | |
| MemberContextKind kind = source.readEnum(MemberContextKind.values); | |
| late final JLibrary library; | |
| JClass? enclosingClass; | |
| switch (kind) { | |
| case MemberContextKind.library: | |
| library = source.readLibrary() as JLibrary; | |
| break; | |
| case MemberContextKind.cls: | |
| enclosingClass = source.readClass() as JClass; | |
| library = enclosingClass.library; | |
| break; | |
| } | |
| Name memberName = source.readMemberName(); | |
| bool isStatic = source.readBool(); | |
| bool isExternal = source.readBool(); | |
| bool isAbstract = source.readBool(); | |
| source.end(tag); | |
| return JSetter( | |
| library, | |
| enclosingClass, | |
| memberName, | |
| isStatic: isStatic, | |
| isExternal: isExternal, | |
| isAbstract: isAbstract, | |
| ); | |
| } | |
| @override | |
| void writeToDataSink(DataSinkWriter sink) { | |
| sink.writeEnum(JMemberKind.setter); | |
| sink.begin(tag); | |
| if (enclosingClass != null) { | |
| sink.writeEnum(MemberContextKind.cls); | |
| sink.writeClass(enclosingClass!); | |
| } else { | |
| sink.writeEnum(MemberContextKind.library); | |
| sink.writeLibrary(library); | |
| } | |
| sink.writeMemberName(memberName); | |
| sink.writeBool(isStatic); | |
| sink.writeBool(isExternal); | |
| sink.writeBool(isAbstract); | |
| sink.end(tag); | |
| } | |
| @override | |
| bool get isAssignable => true; | |
| @override | |
| bool get isSetter => true; | |
| @override | |
| String get _kind => 'setter'; | |
| } | |
| class JField extends JMember implements FieldEntity { | |
| /// Tag used for identifying serialized [JField] objects in a | |
| /// debugging data stream. | |
| static const String tag = 'field'; | |
| @override | |
| final bool isAssignable; | |
| @override | |
| final bool isConst; | |
| JField( | |
| super.library, | |
| super.enclosingClass, | |
| super.name, { | |
| required super.isStatic, | |
| required this.isAssignable, | |
| required this.isConst, | |
| }); | |
| factory JField.readFromDataSource(DataSourceReader source) { | |
| source.begin(tag); | |
| MemberContextKind kind = source.readEnum(MemberContextKind.values); | |
| late final JLibrary library; | |
| JClass? enclosingClass; | |
| switch (kind) { | |
| case MemberContextKind.library: | |
| library = source.readLibrary() as JLibrary; | |
| break; | |
| case MemberContextKind.cls: | |
| enclosingClass = source.readClass() as JClass; | |
| library = enclosingClass.library; | |
| break; | |
| } | |
| Name memberName = source.readMemberName(); | |
| bool isStatic = source.readBool(); | |
| bool isAssignable = source.readBool(); | |
| bool isConst = source.readBool(); | |
| source.end(tag); | |
| return JField( | |
| library, | |
| enclosingClass, | |
| memberName, | |
| isStatic: isStatic, | |
| isAssignable: isAssignable, | |
| isConst: isConst, | |
| ); | |
| } | |
| @override | |
| void writeToDataSink(DataSinkWriter sink) { | |
| sink.writeEnum(JMemberKind.field); | |
| sink.begin(tag); | |
| if (enclosingClass != null) { | |
| sink.writeEnum(MemberContextKind.cls); | |
| sink.writeClass(enclosingClass!); | |
| } else { | |
| sink.writeEnum(MemberContextKind.library); | |
| sink.writeLibrary(library); | |
| } | |
| sink.writeMemberName(memberName); | |
| sink.writeBool(isStatic); | |
| sink.writeBool(isAssignable); | |
| sink.writeBool(isConst); | |
| sink.end(tag); | |
| } | |
| @override | |
| String get _kind => 'field'; | |
| } | |
| class JClosureCallMethod extends JMethod { | |
| /// Tag used for identifying serialized [JClosureCallMethod] objects in a | |
| /// debugging data stream. | |
| static const String tag = 'closure-call-method'; | |
| JClosureCallMethod( | |
| ClassEntity enclosingClass, | |
| ParameterStructure parameterStructure, | |
| AsyncMarker asyncMarker, | |
| ) : super( | |
| enclosingClass.library as JLibrary, | |
| enclosingClass as JClass, | |
| Names.call, | |
| parameterStructure, | |
| asyncMarker, | |
| isStatic: false, | |
| isExternal: false, | |
| isAbstract: false, | |
| ); | |
| factory JClosureCallMethod.readFromDataSource(DataSourceReader source) { | |
| source.begin(tag); | |
| final enclosingClass = source.readClass() as JClass; | |
| ParameterStructure parameterStructure = | |
| ParameterStructure.readFromDataSource(source); | |
| AsyncMarker asyncMarker = source.readEnum(AsyncMarker.values); | |
| source.end(tag); | |
| return JClosureCallMethod(enclosingClass, parameterStructure, asyncMarker); | |
| } | |
| @override | |
| void writeToDataSink(DataSinkWriter sink) { | |
| sink.writeEnum(JMemberKind.closureCallMethod); | |
| sink.begin(tag); | |
| sink.writeClass(enclosingClass!); | |
| parameterStructure.writeToDataSink(sink); | |
| sink.writeEnum(asyncMarker); | |
| sink.end(tag); | |
| } | |
| @override | |
| String get _kind => 'closure_call'; | |
| } | |
| /// A method that returns the signature of the Dart closure/tearoff that this | |
| /// method's parent class is representing. | |
| class JSignatureMethod extends JMethod { | |
| /// Tag used for identifying serialized [JSignatureMethod] objects in a | |
| /// debugging data stream. | |
| static const String tag = 'signature-method'; | |
| JSignatureMethod(ClassEntity enclosingClass) | |
| : super( | |
| enclosingClass.library as JLibrary, | |
| enclosingClass as JClass, | |
| Names.signature, | |
| ParameterStructure.zeroArguments, | |
| AsyncMarker.sync, | |
| isStatic: false, | |
| isExternal: false, | |
| isAbstract: false, | |
| ); | |
| factory JSignatureMethod.readFromDataSource(DataSourceReader source) { | |
| source.begin(tag); | |
| final cls = source.readClass() as JClass; | |
| source.end(tag); | |
| return JSignatureMethod(cls); | |
| } | |
| @override | |
| void writeToDataSink(DataSinkWriter sink) { | |
| sink.writeEnum(JMemberKind.signatureMethod); | |
| sink.begin(tag); | |
| sink.writeClass(enclosingClass!); | |
| sink.end(tag); | |
| } | |
| @override | |
| String get _kind => 'signature'; | |
| } | |
| /// Enum used for identifying [JTypeVariable] variants in serialization. | |
| /// | |
| /// [JLocalTypeVariable] in the K-world can contain a [Local] as its | |
| /// `typeDeclaration` but those are never serialized. When converted to the | |
| /// J-world they use a [JClosureCallMethod] as [JTypeVariable.typeDeclaration]. | |
| enum JTypeVariableKind { cls, member } | |
| class JTypeVariable with EntityMapKey implements TypeVariableEntity { | |
| /// Tag used for identifying serialized [JTypeVariable] objects in a | |
| /// debugging data stream. | |
| static const String tag = 'type-variable'; | |
| @override | |
| final Entity typeDeclaration; | |
| @override | |
| final String name; | |
| @override | |
| final int index; | |
| JTypeVariable(this.typeDeclaration, this.name, this.index) { | |
| assert(typeDeclaration is ClassEntity || typeDeclaration is MemberEntity); | |
| } | |
| /// Deserializes a [JTypeVariable] object from [source]. | |
| factory JTypeVariable.readFromDataSource(DataSourceReader source) { | |
| source.begin(tag); | |
| JTypeVariableKind kind = source.readEnum(JTypeVariableKind.values); | |
| Entity typeDeclaration; | |
| switch (kind) { | |
| case JTypeVariableKind.cls: | |
| typeDeclaration = source.readClass(); | |
| break; | |
| case JTypeVariableKind.member: | |
| typeDeclaration = source.readMember(); | |
| break; | |
| } | |
| String name = source.readString(); | |
| int index = source.readInt(); | |
| source.end(tag); | |
| return JTypeVariable(typeDeclaration, name, index); | |
| } | |
| /// Serializes this [JTypeVariable] to [sink]. | |
| void writeToDataSink(DataSinkWriter sink) { | |
| sink.begin(tag); | |
| final declaration = typeDeclaration; | |
| if (declaration is ClassEntity) { | |
| sink.writeEnum(JTypeVariableKind.cls); | |
| sink.writeClass(declaration); | |
| } else if (declaration is MemberEntity) { | |
| sink.writeEnum(JTypeVariableKind.member); | |
| sink.writeMember(declaration); | |
| } else { | |
| throw UnsupportedError( | |
| "Unexpected type variable declarer $typeDeclaration.", | |
| ); | |
| } | |
| sink.writeString(name); | |
| sink.writeInt(index); | |
| sink.end(tag); | |
| } | |
| @override | |
| String toString() => | |
| '${jsElementPrefix}type_variable(${typeDeclaration.name}.$name)'; | |
| } | |
| class JLocalFunction implements Local { | |
| @override | |
| final String? name; | |
| final MemberEntity memberContext; | |
| final Entity executableContext; | |
| final ir.LocalFunction node; | |
| late final FunctionType functionType; | |
| JLocalFunction( | |
| this.name, | |
| this.memberContext, | |
| this.executableContext, | |
| this.node, | |
| ); | |
| @override | |
| String toString() => | |
| '${jsElementPrefix}local_function' | |
| '(${memberContext.name}.${name ?? '<anonymous>'})'; | |
| } | |
| class JLocalTypeVariable implements TypeVariableEntity { | |
| @override | |
| final JLocalFunction typeDeclaration; | |
| @override | |
| final String name; | |
| @override | |
| final int index; | |
| late final DartType bound; | |
| late final DartType defaultType; | |
| JLocalTypeVariable(this.typeDeclaration, this.name, this.index); | |
| @override | |
| String toString() => | |
| '${jsElementPrefix}local_type_variable(${typeDeclaration.name}.$name)'; | |
| } |