| Index: sdk/lib/_internal/compiler/implementation/js_backend/native_emitter.dart
|
| diff --git a/sdk/lib/_internal/compiler/implementation/js_backend/native_emitter.dart b/sdk/lib/_internal/compiler/implementation/js_backend/native_emitter.dart
|
| index c2e6b0de6c53aec4e63794dc5b5cc5eab9600da6..c2542ef768db514920b37b0537583c57d667b6bb 100644
|
| --- a/sdk/lib/_internal/compiler/implementation/js_backend/native_emitter.dart
|
| +++ b/sdk/lib/_internal/compiler/implementation/js_backend/native_emitter.dart
|
| @@ -31,6 +31,9 @@ class NativeEmitter {
|
| // Caches the methods that have a native body.
|
| Set<FunctionElement> nativeMethods;
|
|
|
| + // Caches the methods that redirect to a JS method.
|
| + Map<FunctionElement, String> redirectingMethods;
|
| +
|
| // Do we need the native emitter to take care of handling
|
| // noSuchMethod for us? This flag is set to true in the emitter if
|
| // it finds any native class that needs noSuchMethod handling.
|
| @@ -43,11 +46,16 @@ class NativeEmitter {
|
| directSubtypes = new Map<ClassElement, List<ClassElement>>(),
|
| overriddenMethods = new Set<FunctionElement>(),
|
| nativeMethods = new Set<FunctionElement>(),
|
| + redirectingMethods = new Map<FunctionElement, String>(),
|
| nativeBuffer = new CodeBuffer();
|
|
|
| Compiler get compiler => emitter.compiler;
|
| JavaScriptBackend get backend => compiler.backend;
|
|
|
| + void addRedirectingMethod(FunctionElement element, String name) {
|
| + redirectingMethods[element] = name;
|
| + }
|
| +
|
| String get dynamicName {
|
| Element element = compiler.findHelper(
|
| const SourceString('dynamicFunction'));
|
| @@ -107,7 +115,7 @@ function(cls, desc) {
|
| }
|
|
|
| void generateNativeLiteral(ClassElement classElement) {
|
| - String quotedNative = classElement.nativeTagInfo.slowToString();
|
| + String quotedNative = classElement.nativeName.slowToString();
|
| String nativeCode = quotedNative.substring(2, quotedNative.length - 1);
|
| String className = backend.namer.getName(classElement);
|
| nativeBuffer.add(className);
|
| @@ -134,8 +142,8 @@ function(cls, desc) {
|
| return identical(quotedName[1], '@');
|
| }
|
|
|
| - String toNativeTag(ClassElement cls) {
|
| - String quotedName = cls.nativeTagInfo.slowToString();
|
| + String toNativeName(ClassElement cls) {
|
| + String quotedName = cls.nativeName.slowToString();
|
| if (isNativeGlobal(quotedName)) {
|
| // Global object, just be like the other types for now.
|
| return quotedName.substring(3, quotedName.length - 1);
|
| @@ -148,7 +156,7 @@ function(cls, desc) {
|
| nativeClasses.add(classElement);
|
|
|
| assert(classElement.backendMembers.isEmpty);
|
| - String quotedName = classElement.nativeTagInfo.slowToString();
|
| + String quotedName = classElement.nativeName.slowToString();
|
| if (isNativeLiteral(quotedName)) {
|
| generateNativeLiteral(classElement);
|
| // The native literal kind needs to be dealt with specially when
|
| @@ -170,8 +178,8 @@ function(cls, desc) {
|
| return;
|
| }
|
|
|
| - String nativeTag = toNativeTag(classElement);
|
| - nativeBuffer.add("$defineNativeClassName('$nativeTag', ");
|
| + String nativeName = toNativeName(classElement);
|
| + nativeBuffer.add("$defineNativeClassName('$nativeName', ");
|
| nativeBuffer.add('{');
|
| bool firstInMap = true;
|
| if (!fieldBuffer.isEmpty) {
|
| @@ -239,7 +247,7 @@ function(cls, desc) {
|
| 0, indexOfLastOptionalArgumentInParameters + 1);
|
|
|
| ClassElement classElement = member.enclosingElement;
|
| - String nativeTagInfo = classElement.nativeTagInfo.slowToString();
|
| + String nativeName = classElement.nativeName.slowToString();
|
| String nativeArguments = Strings.join(nativeArgumentsBuffer, ",");
|
|
|
| CodeBuffer code = new CodeBuffer();
|
| @@ -252,11 +260,12 @@ function(cls, desc) {
|
| code.add(' return this.${backend.namer.getName(member)}($arguments)');
|
| } else {
|
| // When calling a JS method, we call it with the native name.
|
| - String name = member.nativeName();
|
| + String name = redirectingMethods[member];
|
| + if (name == null) name = member.name.slowToString();
|
| code.add(' return this.$name($nativeArguments);');
|
| }
|
|
|
| - if (isNativeLiteral(nativeTagInfo) || !overriddenMethods.contains(member)) {
|
| + if (isNativeLiteral(nativeName) || !overriddenMethods.contains(member)) {
|
| // Call the method directly.
|
| buffer.add(code.toString());
|
| } else {
|
| @@ -318,14 +327,14 @@ function(cls, desc) {
|
| // Expression fragments for this set of cls keys.
|
| List<js.Expression> expressions = <js.Expression>[];
|
| // TODO: Remove if cls is abstract.
|
| - List<String> subtags = [toNativeTag(classElement)];
|
| + List<String> subtags = [toNativeName(classElement)];
|
| void walk(ClassElement cls) {
|
| for (final ClassElement subclass in getDirectSubclasses(cls)) {
|
| ClassElement tag = subclass;
|
| js.Expression existing = tagDefns[tag];
|
| if (existing == null) {
|
| // [subclass] is still within the subtree between dispatch classes.
|
| - subtags.add(toNativeTag(tag));
|
| + subtags.add(toNativeName(tag));
|
| walk(subclass);
|
| } else {
|
| // [subclass] is one of the preorderDispatchClasses, so CSE this
|
| @@ -395,7 +404,7 @@ function(cls, desc) {
|
| new js.ArrayInitializer.from(
|
| preorderDispatchClasses.map((cls) =>
|
| new js.ArrayInitializer.from([
|
| - new js.LiteralString("'${toNativeTag(cls)}'"),
|
| + new js.LiteralString("'${toNativeName(cls)}'"),
|
| tagDefns[cls]])));
|
|
|
| // $.dynamicSetMetadata(table);
|
|
|