Index: pkg/compiler/lib/src/js_backend/js_interop_analysis.dart |
diff --git a/pkg/compiler/lib/src/js_backend/js_interop_analysis.dart b/pkg/compiler/lib/src/js_backend/js_interop_analysis.dart |
index 480b75d87ad4ac7a31951aa895749aafdc75a3c9..b4f0c76a502dc05dc87e7f9ec477df2dfdfb4c76 100644 |
--- a/pkg/compiler/lib/src/js_backend/js_interop_analysis.dart |
+++ b/pkg/compiler/lib/src/js_backend/js_interop_analysis.dart |
@@ -5,22 +5,8 @@ |
/// Analysis to determine how to generate code for typed JavaScript interop. |
library compiler.src.js_backend.js_interop_analysis; |
-import '../common.dart'; |
-import '../constants/values.dart' |
- show ConstantValue, ConstructedConstantValue, StringConstantValue; |
import '../elements/resolution_types.dart' |
show ResolutionDartType, ResolutionDynamicType, ResolutionFunctionType; |
-import '../diagnostics/messages.dart' show MessageKind; |
-import '../elements/elements.dart' |
- show |
- ClassElement, |
- Element, |
- FieldElement, |
- LibraryElement, |
- ParameterElement, |
- MemberElement, |
- MethodElement, |
- MetadataAnnotation; |
import '../js/js.dart' as jsAst; |
import '../js/js.dart' show js; |
import '../universe/selector.dart' show Selector; |
@@ -30,167 +16,10 @@ import 'js_backend.dart' show JavaScriptBackend; |
class JsInteropAnalysis { |
final JavaScriptBackend backend; |
- /// The resolved [FieldElement] for `Js.name`. |
- FieldElement nameField; |
- bool enabledJsInterop = false; |
- |
- /// Whether the backend is currently processing the codegen queue. |
- bool _inCodegen = false; |
- |
JsInteropAnalysis(this.backend); |
- void onQueueClosed() { |
- if (_inCodegen) return; |
- |
- if (backend.compiler.commonElements.jsAnnotationClass != null) { |
- ClassElement cls = backend.compiler.commonElements.jsAnnotationClass; |
- nameField = cls.lookupMember('name'); |
- backend.compiler.libraryLoader.libraries |
- .forEach(processJsInteropAnnotationsInLibrary); |
- } |
- } |
- |
- void onCodegenStart() { |
- _inCodegen = true; |
- } |
- |
- /// Resolves the metadata of [element] and returns the name of the `JS(...)` |
- /// annotation for js interop, if found. |
- String processJsInteropAnnotation(Element element) { |
- for (MetadataAnnotation annotation in element.implementation.metadata) { |
- // TODO(johnniwinther): Avoid processing unresolved elements. |
- if (annotation.constant == null) continue; |
- ConstantValue constant = |
- backend.compiler.constants.getConstantValue(annotation.constant); |
- if (constant == null || constant is! ConstructedConstantValue) continue; |
- ConstructedConstantValue constructedConstant = constant; |
- if (constructedConstant.type.element == |
- backend.compiler.commonElements.jsAnnotationClass) { |
- ConstantValue value = constructedConstant.fields[nameField]; |
- String name; |
- if (value.isString) { |
- StringConstantValue stringValue = value; |
- name = stringValue.primitiveValue.slowToString(); |
- } else { |
- // TODO(jacobr): report a warning if the value is not a String. |
- name = ''; |
- } |
- enabledJsInterop = true; |
- return name; |
- } |
- } |
- return null; |
- } |
- |
- bool hasAnonymousAnnotation(Element element) { |
- if (backend.compiler.commonElements.jsAnonymousClass == null) return false; |
- return element.metadata.any((MetadataAnnotation annotation) { |
- ConstantValue constant = |
- backend.compiler.constants.getConstantValue(annotation.constant); |
- if (constant == null || constant is! ConstructedConstantValue) |
- return false; |
- ConstructedConstantValue constructedConstant = constant; |
- return constructedConstant.type.element == |
- backend.compiler.commonElements.jsAnonymousClass; |
- }); |
- } |
- |
- void _checkFunctionParameters(MethodElement fn) { |
- if (fn.hasFunctionSignature && |
- fn.functionSignature.optionalParametersAreNamed) { |
- backend.reporter.reportErrorMessage( |
- fn, |
- MessageKind.JS_INTEROP_METHOD_WITH_NAMED_ARGUMENTS, |
- {'method': fn.name}); |
- } |
- } |
- |
- void processJsInteropAnnotationsInLibrary(LibraryElement library) { |
- String libraryName = processJsInteropAnnotation(library); |
- if (libraryName != null) { |
- backend.nativeDataBuilder.setJsInteropLibraryName(library, libraryName); |
- } |
- library.implementation.forEachLocalMember((Element element) { |
- if (element is MemberElement) { |
- String memberName = processJsInteropAnnotation(element); |
- if (memberName != null) { |
- backend.nativeDataBuilder.setJsInteropMemberName(element, memberName); |
- } |
- |
- if (element is MethodElement) { |
- if (!backend.nativeData.isJsInteropMember(element)) return; |
- _checkFunctionParameters(element); |
- } |
- } |
- |
- if (!element.isClass) return; |
- |
- ClassElement classElement = element; |
- String className = processJsInteropAnnotation(classElement); |
- if (className != null) { |
- backend.nativeDataBuilder |
- .setJsInteropClassName(classElement, className); |
- } |
- if (!backend.nativeData.isJsInteropClass(classElement)) return; |
- |
- // Skip classes that are completely unreachable. This should only happen |
- // when all of jsinterop types are unreachable from main. |
- if (!backend.compiler.resolutionWorldBuilder |
- .isImplemented(classElement)) { |
- return; |
- } |
- |
- if (!classElement.implementsInterface( |
- backend.compiler.commonElements.jsJavaScriptObjectClass)) { |
- backend.reporter.reportErrorMessage(classElement, |
- MessageKind.JS_INTEROP_CLASS_CANNOT_EXTEND_DART_CLASS, { |
- 'cls': classElement.name, |
- 'superclass': classElement.superclass.name |
- }); |
- } |
- |
- classElement |
- .forEachMember((ClassElement classElement, MemberElement member) { |
- String memberName = processJsInteropAnnotation(member); |
- if (memberName != null) { |
- backend.nativeDataBuilder.setJsInteropMemberName(member, memberName); |
- } |
- |
- if (!member.isSynthesized && |
- backend.nativeData.isJsInteropClass(classElement) && |
- member is MethodElement) { |
- MethodElement fn = member; |
- if (!fn.isExternal && |
- !fn.isAbstract && |
- !fn.isConstructor && |
- !fn.isStatic) { |
- backend.reporter.reportErrorMessage( |
- fn, |
- MessageKind.JS_INTEROP_CLASS_NON_EXTERNAL_MEMBER, |
- {'cls': classElement.name, 'member': member.name}); |
- } |
- |
- if (fn.isFactoryConstructor && hasAnonymousAnnotation(classElement)) { |
- fn.functionSignature |
- .orderedForEachParameter((ParameterElement parameter) { |
- if (!parameter.isNamed) { |
- backend.reporter.reportErrorMessage( |
- parameter, |
- MessageKind |
- .JS_OBJECT_LITERAL_CONSTRUCTOR_WITH_POSITIONAL_ARGUMENTS, |
- {'parameter': parameter.name, 'cls': classElement.name}); |
- } |
- }); |
- } else { |
- _checkFunctionParameters(fn); |
- } |
- } |
- }); |
- }); |
- } |
- |
jsAst.Statement buildJsInteropBootstrap() { |
- if (!enabledJsInterop) return null; |
+ if (!backend.nativeBasicData.isJsInteropUsed) return null; |
List<jsAst.Statement> statements = <jsAst.Statement>[]; |
backend.compiler.codegenWorldBuilder.forEachInvokedName( |
(String name, Map<Selector, SelectorConstraints> selectors) { |