| Index: pkg/compiler/lib/src/js_backend/backend.dart
|
| diff --git a/pkg/compiler/lib/src/js_backend/backend.dart b/pkg/compiler/lib/src/js_backend/backend.dart
|
| index ce801a9b8414fb83ec11b204a952f63a9ed69dcb..6495dd70d5e82a67dd8aa601a405b4f57dd82817 100644
|
| --- a/pkg/compiler/lib/src/js_backend/backend.dart
|
| +++ b/pkg/compiler/lib/src/js_backend/backend.dart
|
| @@ -233,6 +233,8 @@ class JavaScriptBackend extends Backend {
|
| new Uri(scheme: 'dart', path: '_js_embedded_names');
|
| static final Uri DART_ISOLATE_HELPER =
|
| new Uri(scheme: 'dart', path: '_isolate_helper');
|
| + static final Uri PACKAGE_JS =
|
| + new Uri(scheme: 'package', path: 'js/js.dart');
|
|
|
| static const String INVOKE_ON = '_getCachedInvocation';
|
| static const String START_ROOT_ISOLATE = 'startRootIsolate';
|
| @@ -289,6 +291,8 @@ class JavaScriptBackend extends Backend {
|
| ClassElement jsBoolClass;
|
| ClassElement jsPlainJavaScriptObjectClass;
|
| ClassElement jsUnknownJavaScriptObjectClass;
|
| + ClassElement jsJavaScriptFunctionClass;
|
| + ClassElement jsJavaScriptObjectClass;
|
|
|
| ClassElement jsIndexableClass;
|
| ClassElement jsMutableIndexableClass;
|
| @@ -326,6 +330,8 @@ class JavaScriptBackend extends Backend {
|
| ClassElement forceInlineClass;
|
| ClassElement irRepresentationClass;
|
|
|
| + ClassElement jsAnnotationClass;
|
| +
|
| Element getInterceptorMethod;
|
|
|
| ClassElement jsInvocationMirrorClass;
|
| @@ -660,7 +666,7 @@ class JavaScriptBackend extends Backend {
|
| }
|
|
|
| FunctionElement resolveExternalFunction(FunctionElement element) {
|
| - if (isForeign(element)) return element;
|
| + if (isForeign(element) || element.isJsInterop) return element;
|
| return patchResolverTask.measure(() {
|
| return patchResolverTask.resolveExternalFunction(element);
|
| });
|
| @@ -888,6 +894,28 @@ class JavaScriptBackend extends Backend {
|
| ClassElement cls, Enqueuer enqueuer) {
|
| if (enqueuer.isResolutionQueue) {
|
| cls.ensureResolved(compiler);
|
| + if (cls.isJsInterop) {
|
| + if (!cls.implementsInterface(jsJavaScriptObjectClass)) {
|
| + compiler.reportError(
|
| + cls,
|
| + MessageKind.JS_INTEROP_CLASS_CANNOT_EXTEND_DART_CLASS,
|
| + {'cls': cls.name});
|
| + return;
|
| + }
|
| +
|
| + cls.forEachMember((ClassElement classElement, Element member) {
|
| + if (member.isSynthesized) return;
|
| + if (cls.isJsInterop && member is FunctionElement) {
|
| + FunctionElement fn = member;
|
| + if (!fn.isExternal && !fn.isAbstract) {
|
| + compiler.reportError(
|
| + fn,
|
| + MessageKind.JS_INTEROP_CLASS_NON_EXTERNAL_MEMBER,
|
| + {'cls': cls.name, 'member': member.name});
|
| + }
|
| + }
|
| + });
|
| + }
|
| cls.forEachMember((ClassElement classElement, Element member) {
|
| if (member.name == Identifiers.call) {
|
| compiler.reportError(
|
| @@ -1038,7 +1066,9 @@ class JavaScriptBackend extends Backend {
|
| } else if (Elements.isNativeOrExtendsNative(cls)) {
|
| enqueue(enqueuer, getNativeInterceptorMethod, registry);
|
| enqueueClass(enqueuer, jsInterceptorClass, compiler.globalDependencies);
|
| + enqueueClass(enqueuer, jsJavaScriptObjectClass, registry);
|
| enqueueClass(enqueuer, jsPlainJavaScriptObjectClass, registry);
|
| + enqueueClass(enqueuer, jsJavaScriptFunctionClass, registry);
|
| } else if (cls == mapLiteralClass) {
|
| // For map literals, the dependency between the implementation class
|
| // and [Map] is not visible, so we have to add it manually.
|
| @@ -1115,10 +1145,14 @@ class JavaScriptBackend extends Backend {
|
| addInterceptors(jsUInt31Class, enqueuer, registry);
|
| addInterceptors(jsDoubleClass, enqueuer, registry);
|
| addInterceptors(jsNumberClass, enqueuer, registry);
|
| + } else if (cls == jsJavaScriptObjectClass) {
|
| + addInterceptors(jsJavaScriptObjectClass, enqueuer, registry);
|
| } else if (cls == jsPlainJavaScriptObjectClass) {
|
| addInterceptors(jsPlainJavaScriptObjectClass, enqueuer, registry);
|
| } else if (cls == jsUnknownJavaScriptObjectClass) {
|
| addInterceptors(jsUnknownJavaScriptObjectClass, enqueuer, registry);
|
| + } else if (cls == jsJavaScriptFunctionClass) {
|
| + addInterceptors(jsJavaScriptFunctionClass, enqueuer, registry);
|
| } else if (Elements.isNativeOrExtendsNative(cls)) {
|
| addInterceptorsForNativeClassMembers(cls, enqueuer);
|
| } else if (cls == jsIndexingBehaviorInterface) {
|
| @@ -1136,7 +1170,9 @@ class JavaScriptBackend extends Backend {
|
| if (!enqueuer.nativeEnqueuer.hasInstantiatedNativeClasses()) return;
|
| Registry registry = compiler.globalDependencies;
|
| enqueue(enqueuer, getNativeInterceptorMethod, registry);
|
| + enqueueClass(enqueuer, jsJavaScriptObjectClass, registry);
|
| enqueueClass(enqueuer, jsPlainJavaScriptObjectClass, registry);
|
| + enqueueClass(enqueuer, jsJavaScriptFunctionClass, registry);
|
| needToInitializeIsolateAffinityTag = true;
|
| needToInitializeDispatchProperty = true;
|
| }
|
| @@ -1467,6 +1503,7 @@ class JavaScriptBackend extends Backend {
|
| }
|
|
|
| ClassElement defaultSuperclass(ClassElement element) {
|
| + if (element.isJsInterop) return jsJavaScriptObjectClass;
|
| // Native classes inherit from Interceptor.
|
| return element.isNative ? jsInterceptorClass : compiler.objectClass;
|
| }
|
| @@ -2099,6 +2136,8 @@ class JavaScriptBackend extends Backend {
|
| jsExtendableArrayClass = findClass('JSExtendableArray');
|
| jsUnmodifiableArrayClass = findClass('JSUnmodifiableArray');
|
| jsPlainJavaScriptObjectClass = findClass('PlainJavaScriptObject');
|
| + jsJavaScriptObjectClass = findClass('JavaScriptObject');
|
| + jsJavaScriptFunctionClass = findClass('JavaScriptFunction');
|
| jsUnknownJavaScriptObjectClass = findClass('UnknownJavaScriptObject');
|
| jsIndexableClass = findClass('JSIndexable');
|
| jsMutableIndexableClass = findClass('JSMutableIndexable');
|
| @@ -2133,6 +2172,8 @@ class JavaScriptBackend extends Backend {
|
| jsBuiltinEnum = find(library, 'JsBuiltin');
|
| } else if (uri == Uris.dart_html) {
|
| htmlLibraryIsLoaded = true;
|
| + } else if (uri == PACKAGE_JS) {
|
| + jsAnnotationClass = find(library, 'Js');
|
| }
|
| annotations.onLibraryScanned(library);
|
| });
|
| @@ -2528,6 +2569,11 @@ class JavaScriptBackend extends Backend {
|
| customElementsAnalysis.onQueueEmpty(enqueuer);
|
| if (!enqueuer.queueIsEmpty) return false;
|
|
|
| + // XXXX this is a bad hack.
|
| + // We are validating way too many times.
|
| + compiler.libraryLoader.libraries.forEach(processJsInteropAnnotationsInLibrary);
|
| +
|
| +
|
| noSuchMethodRegistry.onQueueEmpty();
|
| if (!enabledNoSuchMethod &&
|
| (noSuchMethodRegistry.hasThrowingNoSuchMethod ||
|
| @@ -2577,6 +2623,13 @@ class JavaScriptBackend extends Backend {
|
| return true;
|
| }
|
|
|
| + void processJsInteropAnnotationsInLibrary(LibraryElement library) {
|
| + checkJsInteropAnnotation(compiler, library);
|
| + library.implementation.forEachLocalMember((Element element) {
|
| + checkJsInteropAnnotation(compiler, element);
|
| + });
|
| + }
|
| +
|
| void onElementResolved(Element element, TreeElements elements) {
|
| if ((element.isFunction || element.isGenerativeConstructor) &&
|
| annotations.noInline(element)) {
|
|
|