| OLD | NEW |
| 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2014, 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.js_emitter.program_builder; | 5 library dart2js.js_emitter.program_builder; |
| 6 | 6 |
| 7 import 'dart:io'; | 7 import 'dart:io'; |
| 8 import 'dart:convert' show JSON; | 8 import 'dart:convert' show JSON; |
| 9 | 9 |
| 10 import '../../closure.dart' show ClosureTask, ClosureFieldElement; | 10 import '../../closure.dart' show ClosureTask, ClosureFieldElement; |
| (...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 146 this._namer, | 146 this._namer, |
| 147 this._task, | 147 this._task, |
| 148 this._closedWorld, | 148 this._closedWorld, |
| 149 Set<ClassEntity> rtiNeededClasses, | 149 Set<ClassEntity> rtiNeededClasses, |
| 150 this._mainFunction, | 150 this._mainFunction, |
| 151 {bool isMockCompilation}) | 151 {bool isMockCompilation}) |
| 152 : this._isMockCompilation = isMockCompilation, | 152 : this._isMockCompilation = isMockCompilation, |
| 153 this.collector = new Collector( | 153 this.collector = new Collector( |
| 154 _options, | 154 _options, |
| 155 _commonElements, | 155 _commonElements, |
| 156 _elementEnvironment, |
| 156 _deferredLoadTask, | 157 _deferredLoadTask, |
| 157 _worldBuilder, | 158 _worldBuilder, |
| 158 _namer, | 159 _namer, |
| 159 _task.emitter, | 160 _task.emitter, |
| 160 _constantHandler, | 161 _constantHandler, |
| 161 _nativeData, | 162 _nativeData, |
| 162 _interceptorData, | 163 _interceptorData, |
| 163 _oneShotInterceptorData, | 164 _oneShotInterceptorData, |
| 164 _mirrorsData, | 165 _mirrorsData, |
| 165 _closedWorld, | 166 _closedWorld, |
| (...skipping 462 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 628 } | 629 } |
| 629 } | 630 } |
| 630 }); | 631 }); |
| 631 } | 632 } |
| 632 } | 633 } |
| 633 }); | 634 }); |
| 634 } | 635 } |
| 635 | 636 |
| 636 // Note that a library-element may have multiple [Library]s, if it is split | 637 // Note that a library-element may have multiple [Library]s, if it is split |
| 637 // into multiple output units. | 638 // into multiple output units. |
| 638 Library _buildLibrary(LibraryElement library, List<ClassEntity> classElements, | 639 Library _buildLibrary(LibraryEntity library, List<ClassEntity> classElements, |
| 639 List<MemberEntity> memberElements) { | 640 List<MemberEntity> memberElements) { |
| 640 String uri = library.canonicalUri.toString(); | 641 String uri = library.canonicalUri.toString(); |
| 641 | 642 |
| 642 List<StaticMethod> statics = memberElements | 643 List<StaticMethod> statics = memberElements |
| 643 .where((e) => e is MethodElement) | 644 .where((e) => !e.isField) |
| 644 .map(_buildStaticMethod) | 645 .map(_buildStaticMethod) |
| 645 .toList(); | 646 .toList(); |
| 646 | 647 |
| 647 if (library == _commonElements.interceptorsLibrary) { | 648 if (library == _commonElements.interceptorsLibrary) { |
| 648 statics.addAll(_generateGetInterceptorMethods()); | 649 statics.addAll(_generateGetInterceptorMethods()); |
| 649 statics.addAll(_generateOneShotInterceptors()); | 650 statics.addAll(_generateOneShotInterceptors()); |
| 650 } | 651 } |
| 651 | 652 |
| 652 List<Class> classes = classElements | 653 List<Class> classes = classElements |
| 653 .map((ClassElement classElement) => _classes[classElement]) | 654 .map((ClassEntity classElement) => _classes[classElement]) |
| 654 .where((Class cls) => | 655 .where((Class cls) => |
| 655 !cls.isNative || !_unneededNativeClasses.contains(cls)) | 656 !cls.isNative || !_unneededNativeClasses.contains(cls)) |
| 656 .toList(growable: false); | 657 .toList(growable: false); |
| 657 | 658 |
| 658 bool visitStatics = true; | 659 bool visitStatics = true; |
| 659 List<Field> staticFieldsForReflection = | 660 List<Field> staticFieldsForReflection = |
| 660 _buildFields(library, visitStatics: visitStatics); | 661 _buildFields(library: library, visitStatics: visitStatics); |
| 661 | 662 |
| 662 return new Library( | 663 return new Library( |
| 663 library, uri, statics, classes, staticFieldsForReflection); | 664 library, uri, statics, classes, staticFieldsForReflection); |
| 664 } | 665 } |
| 665 | 666 |
| 666 bool _isSoftDeferred(ClassElement element) { | 667 bool _isSoftDeferred(ClassElement element) { |
| 667 return _notSoftDeferred != null && !_notSoftDeferred.contains(element); | 668 return _notSoftDeferred != null && !_notSoftDeferred.contains(element); |
| 668 } | 669 } |
| 669 | 670 |
| 670 Class _buildClass(ClassElement element) { | 671 Class _buildClass(ClassElement element) { |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 744 ClassElement implementation = element.implementation; | 745 ClassElement implementation = element.implementation; |
| 745 | 746 |
| 746 // MixinApplications run through the members of their mixin. Here, we are | 747 // MixinApplications run through the members of their mixin. Here, we are |
| 747 // only interested in direct members. | 748 // only interested in direct members. |
| 748 if (!onlyForRti && !element.isMixinApplication) { | 749 if (!onlyForRti && !element.isMixinApplication) { |
| 749 implementation.forEachMember(visitMember, includeBackendMembers: true); | 750 implementation.forEachMember(visitMember, includeBackendMembers: true); |
| 750 } | 751 } |
| 751 bool isInterceptedClass = _interceptorData.isInterceptedClass(element); | 752 bool isInterceptedClass = _interceptorData.isInterceptedClass(element); |
| 752 List<Field> instanceFields = onlyForRti | 753 List<Field> instanceFields = onlyForRti |
| 753 ? const <Field>[] | 754 ? const <Field>[] |
| 754 : _buildFields(element, | 755 : _buildFields( |
| 755 visitStatics: false, isHolderInterceptedClass: isInterceptedClass); | 756 cls: element, |
| 757 visitStatics: false, |
| 758 isHolderInterceptedClass: isInterceptedClass); |
| 756 List<Field> staticFieldsForReflection = onlyForRti | 759 List<Field> staticFieldsForReflection = onlyForRti |
| 757 ? const <Field>[] | 760 ? const <Field>[] |
| 758 : _buildFields(element, | 761 : _buildFields( |
| 759 visitStatics: true, isHolderInterceptedClass: isInterceptedClass); | 762 cls: element, |
| 763 visitStatics: true, |
| 764 isHolderInterceptedClass: isInterceptedClass); |
| 760 | 765 |
| 761 TypeTestProperties typeTests = runtimeTypeGenerator.generateIsTests(element, | 766 TypeTestProperties typeTests = runtimeTypeGenerator.generateIsTests(element, |
| 762 storeFunctionTypeInMetadata: _storeFunctionTypesInMetadata); | 767 storeFunctionTypeInMetadata: _storeFunctionTypesInMetadata); |
| 763 | 768 |
| 764 List<StubMethod> checkedSetters = <StubMethod>[]; | 769 List<StubMethod> checkedSetters = <StubMethod>[]; |
| 765 List<StubMethod> isChecks = <StubMethod>[]; | 770 List<StubMethod> isChecks = <StubMethod>[]; |
| 766 if (_nativeData.isJsInteropClass(element)) { | 771 if (_nativeData.isJsInteropClass(element)) { |
| 767 typeTests.properties.forEach((js.Name name, js.Node code) { | 772 typeTests.properties.forEach((js.Name name, js.Node code) { |
| 768 _classes[_commonElements.jsInterceptorClass] | 773 _classes[_commonElements.jsInterceptorClass] |
| 769 .isChecks | 774 .isChecks |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 830 hasRtiField: hasRtiField, | 835 hasRtiField: hasRtiField, |
| 831 onlyForRti: onlyForRti, | 836 onlyForRti: onlyForRti, |
| 832 isNative: _nativeData.isNativeClass(element), | 837 isNative: _nativeData.isNativeClass(element), |
| 833 isClosureBaseClass: isClosureBaseClass, | 838 isClosureBaseClass: isClosureBaseClass, |
| 834 isSoftDeferred: _isSoftDeferred(element)); | 839 isSoftDeferred: _isSoftDeferred(element)); |
| 835 } | 840 } |
| 836 _classes[element] = result; | 841 _classes[element] = result; |
| 837 return result; | 842 return result; |
| 838 } | 843 } |
| 839 | 844 |
| 840 bool _methodNeedsStubs(FunctionElement method) { | 845 bool _methodNeedsStubs(FunctionEntity method) { |
| 841 return !method.functionSignature.optionalParameters.isEmpty; | 846 return method.parameterStructure.optionalParameters != 0; |
| 842 } | 847 } |
| 843 | 848 |
| 844 bool _methodCanBeReflected(MethodElement method) { | 849 bool _methodCanBeReflected(FunctionEntity method) { |
| 845 return _mirrorsData.isMemberAccessibleByReflection(method); | 850 return _mirrorsData.isMemberAccessibleByReflection(method); |
| 846 } | 851 } |
| 847 | 852 |
| 848 bool _methodCanBeApplied(FunctionElement method) { | 853 bool _methodCanBeApplied(FunctionEntity method) { |
| 849 return _backendUsage.isFunctionApplyUsed && | 854 return _backendUsage.isFunctionApplyUsed && |
| 850 _closedWorld.getMightBePassedToApply(method); | 855 _closedWorld.getMightBePassedToApply(method); |
| 851 } | 856 } |
| 852 | 857 |
| 853 /* Map | List */ _computeParameterDefaultValues(FunctionSignature signature) { | 858 /* Map | List */ _computeParameterDefaultValues(FunctionSignature signature) { |
| 854 var /* Map | List */ optionalParameterDefaultValues; | 859 var /* Map | List */ optionalParameterDefaultValues; |
| 855 if (signature.optionalParametersAreNamed) { | 860 if (signature.optionalParametersAreNamed) { |
| 856 optionalParameterDefaultValues = new Map<String, ConstantValue>(); | 861 optionalParameterDefaultValues = new Map<String, ConstantValue>(); |
| 857 signature.forEachOptionalParameter((ParameterElement parameter) { | 862 signature.forEachOptionalParameter((ParameterElement parameter) { |
| 858 ConstantValue def = | 863 ConstantValue def = |
| (...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 952 isClosureCallMethod: isClosureCallMethod, | 957 isClosureCallMethod: isClosureCallMethod, |
| 953 aliasName: aliasName, | 958 aliasName: aliasName, |
| 954 canBeApplied: canBeApplied, | 959 canBeApplied: canBeApplied, |
| 955 canBeReflected: canBeReflected, | 960 canBeReflected: canBeReflected, |
| 956 requiredParameterCount: requiredParameterCount, | 961 requiredParameterCount: requiredParameterCount, |
| 957 optionalParameterDefaultValues: optionalParameterDefaultValues, | 962 optionalParameterDefaultValues: optionalParameterDefaultValues, |
| 958 functionType: functionType); | 963 functionType: functionType); |
| 959 } | 964 } |
| 960 | 965 |
| 961 js.Expression _generateFunctionType( | 966 js.Expression _generateFunctionType( |
| 962 ResolutionDartType type, OutputUnit outputUnit) { | 967 ResolutionFunctionType type, OutputUnit outputUnit) { |
| 963 if (type.containsTypeVariables) { | 968 if (type.containsTypeVariables) { |
| 964 js.Expression thisAccess = js.js(r'this.$receiver'); | 969 js.Expression thisAccess = js.js(r'this.$receiver'); |
| 965 return _rtiEncoder.getSignatureEncoding(_task.emitter, type, thisAccess); | 970 return _rtiEncoder.getSignatureEncoding(_task.emitter, type, thisAccess); |
| 966 } else { | 971 } else { |
| 967 return _task.metadataCollector.reifyTypeForOutputUnit(type, outputUnit); | 972 return _task.metadataCollector.reifyTypeForOutputUnit(type, outputUnit); |
| 968 } | 973 } |
| 969 } | 974 } |
| 970 | 975 |
| 971 List<ParameterStubMethod> _generateParameterStubs( | 976 List<ParameterStubMethod> _generateParameterStubs( |
| 972 MethodElement element, bool canTearOff) { | 977 FunctionEntity element, bool canTearOff) { |
| 973 if (!_methodNeedsStubs(element)) return const <ParameterStubMethod>[]; | 978 if (!_methodNeedsStubs(element)) return const <ParameterStubMethod>[]; |
| 974 | 979 |
| 975 ParameterStubGenerator generator = new ParameterStubGenerator( | 980 ParameterStubGenerator generator = new ParameterStubGenerator( |
| 976 _commonElements, | 981 _commonElements, |
| 977 _task, | 982 _task, |
| 978 _constantHandler, | 983 _constantHandler, |
| 979 _namer, | 984 _namer, |
| 980 _nativeData, | 985 _nativeData, |
| 981 _interceptorData, | 986 _interceptorData, |
| 982 _worldBuilder, | 987 _worldBuilder, |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1030 Iterable<js.Name> names = | 1035 Iterable<js.Name> names = |
| 1031 _oneShotInterceptorData.specializedGetInterceptorNames; | 1036 _oneShotInterceptorData.specializedGetInterceptorNames; |
| 1032 return names.map((js.Name name) { | 1037 return names.map((js.Name name) { |
| 1033 Set<ClassEntity> classes = | 1038 Set<ClassEntity> classes = |
| 1034 _oneShotInterceptorData.getSpecializedGetInterceptorsFor(name); | 1039 _oneShotInterceptorData.getSpecializedGetInterceptorsFor(name); |
| 1035 js.Expression code = stubGenerator.generateGetInterceptorMethod(classes); | 1040 js.Expression code = stubGenerator.generateGetInterceptorMethod(classes); |
| 1036 return new StaticStubMethod(name, holder, code); | 1041 return new StaticStubMethod(name, holder, code); |
| 1037 }); | 1042 }); |
| 1038 } | 1043 } |
| 1039 | 1044 |
| 1040 List<Field> _buildFields(Element holder, | 1045 List<Field> _buildFields( |
| 1041 {bool visitStatics, bool isHolderInterceptedClass: false}) { | 1046 {bool visitStatics: false, |
| 1047 bool isHolderInterceptedClass: false, |
| 1048 LibraryEntity library, |
| 1049 ClassEntity cls}) { |
| 1042 List<Field> fields = <Field>[]; | 1050 List<Field> fields = <Field>[]; |
| 1043 new FieldVisitor(_options, _worldBuilder, _nativeData, _mirrorsData, _namer, | 1051 |
| 1044 _closedWorld) | 1052 void visitField(FieldElement field, js.Name name, js.Name accessorName, |
| 1045 .visitFields(holder, visitStatics, (FieldElement field, | 1053 bool needsGetter, bool needsSetter, bool needsCheckedSetter) { |
| 1046 js.Name name, | |
| 1047 js.Name accessorName, | |
| 1048 bool needsGetter, | |
| 1049 bool needsSetter, | |
| 1050 bool needsCheckedSetter) { | |
| 1051 assert(field.isDeclaration, failedAt(field)); | 1054 assert(field.isDeclaration, failedAt(field)); |
| 1052 | 1055 |
| 1053 int getterFlags = 0; | 1056 int getterFlags = 0; |
| 1054 if (needsGetter) { | 1057 if (needsGetter) { |
| 1055 if (visitStatics || | 1058 if (visitStatics || |
| 1056 !_interceptorData.fieldHasInterceptedGetter(field)) { | 1059 !_interceptorData.fieldHasInterceptedGetter(field)) { |
| 1057 getterFlags = 1; | 1060 getterFlags = 1; |
| 1058 } else { | 1061 } else { |
| 1059 getterFlags += 2; | 1062 getterFlags += 2; |
| 1060 // TODO(sra): 'isInterceptedClass' might not be the correct test | 1063 // TODO(sra): 'isInterceptedClass' might not be the correct test |
| (...skipping 13 matching lines...) Expand all Loading... |
| 1074 } else { | 1077 } else { |
| 1075 setterFlags += 2; | 1078 setterFlags += 2; |
| 1076 if (!isHolderInterceptedClass) { | 1079 if (!isHolderInterceptedClass) { |
| 1077 setterFlags += 1; | 1080 setterFlags += 1; |
| 1078 } | 1081 } |
| 1079 } | 1082 } |
| 1080 } | 1083 } |
| 1081 | 1084 |
| 1082 fields.add(new Field(field, name, accessorName, getterFlags, setterFlags, | 1085 fields.add(new Field(field, name, accessorName, getterFlags, setterFlags, |
| 1083 needsCheckedSetter)); | 1086 needsCheckedSetter)); |
| 1084 }); | 1087 } |
| 1088 |
| 1089 FieldVisitor visitor = new FieldVisitor(_options, _elementEnvironment, |
| 1090 _worldBuilder, _nativeData, _mirrorsData, _namer, _closedWorld); |
| 1091 visitor.visitFields(visitField, |
| 1092 visitStatics: visitStatics, library: library, cls: cls); |
| 1085 | 1093 |
| 1086 return fields; | 1094 return fields; |
| 1087 } | 1095 } |
| 1088 | 1096 |
| 1089 Iterable<StaticStubMethod> _generateOneShotInterceptors() { | 1097 Iterable<StaticStubMethod> _generateOneShotInterceptors() { |
| 1090 InterceptorStubGenerator stubGenerator = new InterceptorStubGenerator( | 1098 InterceptorStubGenerator stubGenerator = new InterceptorStubGenerator( |
| 1091 _options, | 1099 _options, |
| 1092 _commonElements, | 1100 _commonElements, |
| 1093 _task, | 1101 _task, |
| 1094 _nativeCodegenEnqueuer, | 1102 _nativeCodegenEnqueuer, |
| (...skipping 10 matching lines...) Expand all Loading... |
| 1105 // generating the interceptor methods. | 1113 // generating the interceptor methods. |
| 1106 Holder holder = _registry.registerHolder(holderName); | 1114 Holder holder = _registry.registerHolder(holderName); |
| 1107 | 1115 |
| 1108 List<js.Name> names = _oneShotInterceptorData.oneShotInterceptorNames; | 1116 List<js.Name> names = _oneShotInterceptorData.oneShotInterceptorNames; |
| 1109 return names.map((js.Name name) { | 1117 return names.map((js.Name name) { |
| 1110 js.Expression code = stubGenerator.generateOneShotInterceptor(name); | 1118 js.Expression code = stubGenerator.generateOneShotInterceptor(name); |
| 1111 return new StaticStubMethod(name, holder, code); | 1119 return new StaticStubMethod(name, holder, code); |
| 1112 }); | 1120 }); |
| 1113 } | 1121 } |
| 1114 | 1122 |
| 1115 StaticDartMethod _buildStaticMethod(MethodElement element) { | 1123 StaticDartMethod _buildStaticMethod(FunctionEntity element) { |
| 1116 js.Name name = _namer.methodPropertyName(element); | 1124 js.Name name = _namer.methodPropertyName(element); |
| 1117 String holder = _namer.globalObjectForMember(element); | 1125 String holder = _namer.globalObjectForMember(element); |
| 1118 js.Expression code = _generatedCode[element]; | 1126 js.Expression code = _generatedCode[element]; |
| 1119 | 1127 |
| 1120 bool isApplyTarget = !element.isConstructor && !element.isAccessor; | 1128 bool isApplyTarget = |
| 1129 !element.isConstructor && !element.isGetter && !element.isSetter; |
| 1121 bool canBeApplied = _methodCanBeApplied(element); | 1130 bool canBeApplied = _methodCanBeApplied(element); |
| 1122 bool canBeReflected = _methodCanBeReflected(element); | 1131 bool canBeReflected = _methodCanBeReflected(element); |
| 1123 | 1132 |
| 1124 bool needsTearOff = isApplyTarget && | 1133 bool needsTearOff = isApplyTarget && |
| 1125 (canBeReflected || | 1134 (canBeReflected || |
| 1126 _worldBuilder.staticFunctionsNeedingGetter.contains(element)); | 1135 _worldBuilder.staticFunctionsNeedingGetter.contains(element)); |
| 1127 | 1136 |
| 1128 js.Name tearOffName = | 1137 js.Name tearOffName = |
| 1129 needsTearOff ? _namer.staticClosureName(element) : null; | 1138 needsTearOff ? _namer.staticClosureName(element) : null; |
| 1130 | 1139 |
| 1131 js.Name callName = null; | 1140 js.Name callName = null; |
| 1132 if (needsTearOff) { | 1141 if (needsTearOff) { |
| 1133 Selector callSelector = | 1142 Selector callSelector = |
| 1134 new Selector.fromElement(element).toCallSelector(); | 1143 new Selector.fromElement(element).toCallSelector(); |
| 1135 callName = _namer.invocationName(callSelector); | 1144 callName = _namer.invocationName(callSelector); |
| 1136 } | 1145 } |
| 1137 js.Expression functionType; | 1146 js.Expression functionType; |
| 1138 ResolutionDartType type = element.type; | 1147 DartType type = _elementEnvironment.getFunctionType(element); |
| 1139 if (needsTearOff || canBeReflected) { | 1148 if (needsTearOff || canBeReflected) { |
| 1140 OutputUnit outputUnit = _deferredLoadTask.outputUnitForElement(element); | 1149 OutputUnit outputUnit = _deferredLoadTask.outputUnitForMember(element); |
| 1141 functionType = _generateFunctionType(type, outputUnit); | 1150 functionType = _generateFunctionType(type, outputUnit); |
| 1142 } | 1151 } |
| 1143 | 1152 |
| 1144 int requiredParameterCount; | 1153 int requiredParameterCount; |
| 1145 var /* List | Map */ optionalParameterDefaultValues; | 1154 var /* List | Map */ optionalParameterDefaultValues; |
| 1146 if (canBeApplied || canBeReflected) { | 1155 if (canBeApplied || canBeReflected) { |
| 1147 FunctionSignature signature = element.functionSignature; | 1156 // TODO(johnniwinther): Support entities; |
| 1157 MethodElement method = element; |
| 1158 FunctionSignature signature = method.functionSignature; |
| 1148 requiredParameterCount = signature.requiredParameterCount; | 1159 requiredParameterCount = signature.requiredParameterCount; |
| 1149 optionalParameterDefaultValues = | 1160 optionalParameterDefaultValues = |
| 1150 _computeParameterDefaultValues(signature); | 1161 _computeParameterDefaultValues(signature); |
| 1151 } | 1162 } |
| 1152 | 1163 |
| 1153 // TODO(floitsch): we shouldn't update the registry in the middle of | 1164 // TODO(floitsch): we shouldn't update the registry in the middle of |
| 1154 // building a static method. | 1165 // building a static method. |
| 1155 return new StaticDartMethod(element, name, _registry.registerHolder(holder), | 1166 return new StaticDartMethod(element, name, _registry.registerHolder(holder), |
| 1156 code, _generateParameterStubs(element, needsTearOff), callName, | 1167 code, _generateParameterStubs(element, needsTearOff), callName, |
| 1157 needsTearOff: needsTearOff, | 1168 needsTearOff: needsTearOff, |
| (...skipping 19 matching lines...) Expand all Loading... |
| 1177 Constant constant = new Constant(name, holder, constantValue); | 1188 Constant constant = new Constant(name, holder, constantValue); |
| 1178 _constants[constantValue] = constant; | 1189 _constants[constantValue] = constant; |
| 1179 } | 1190 } |
| 1180 } | 1191 } |
| 1181 | 1192 |
| 1182 Holder _registerStaticStateHolder() { | 1193 Holder _registerStaticStateHolder() { |
| 1183 return _registry.registerHolder(_namer.staticStateHolder, | 1194 return _registry.registerHolder(_namer.staticStateHolder, |
| 1184 isStaticStateHolder: true); | 1195 isStaticStateHolder: true); |
| 1185 } | 1196 } |
| 1186 } | 1197 } |
| OLD | NEW |