| 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) {
|
|
|