| OLD | NEW | 
 | (Empty) | 
|    1 // Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file |  | 
|    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. |  | 
|    4  |  | 
|    5 part of dart2js.js_emitter; |  | 
|    6  |  | 
|    7 class InterceptorEmitter extends CodeEmitterHelper { |  | 
|    8   final Set<String> interceptorInvocationNames = new Set<String>(); |  | 
|    9  |  | 
|   10   void recordMangledNameOfMemberMethod(FunctionElement member, String name) { |  | 
|   11     if (backend.isInterceptedMethod(member)) { |  | 
|   12       interceptorInvocationNames.add(name); |  | 
|   13     } |  | 
|   14   } |  | 
|   15  |  | 
|   16   void emitGetInterceptorMethod(CodeBuffer buffer, |  | 
|   17                                 String key, |  | 
|   18                                 Set<ClassElement> classes) { |  | 
|   19     InterceptorStubGenerator stubGenerator = |  | 
|   20         new InterceptorStubGenerator(compiler, namer, backend); |  | 
|   21     jsAst.Expression function = |  | 
|   22         stubGenerator.generateGetInterceptorMethod(classes); |  | 
|   23  |  | 
|   24     buffer.write(jsAst.prettyPrint( |  | 
|   25         js('${namer.globalObjectFor(backend.interceptorsLibrary)}.# = #', |  | 
|   26            [key, function]), |  | 
|   27         compiler)); |  | 
|   28     buffer.write(N); |  | 
|   29   } |  | 
|   30  |  | 
|   31   /** |  | 
|   32    * Emit all versions of the [:getInterceptor:] method. |  | 
|   33    */ |  | 
|   34   void emitGetInterceptorMethods(CodeBuffer buffer) { |  | 
|   35     emitter.addComment('getInterceptor methods', buffer); |  | 
|   36     Map<String, Set<ClassElement>> specializedGetInterceptors = |  | 
|   37         backend.specializedGetInterceptors; |  | 
|   38     for (String name in specializedGetInterceptors.keys.toList()..sort()) { |  | 
|   39       Set<ClassElement> classes = specializedGetInterceptors[name]; |  | 
|   40       emitGetInterceptorMethod(buffer, name, classes); |  | 
|   41     } |  | 
|   42   } |  | 
|   43  |  | 
|   44   void emitOneShotInterceptors(CodeBuffer buffer) { |  | 
|   45     List<String> names = backend.oneShotInterceptors.keys.toList(); |  | 
|   46     names.sort(); |  | 
|   47  |  | 
|   48     InterceptorStubGenerator stubGenerator = |  | 
|   49         new InterceptorStubGenerator(compiler, namer, backend); |  | 
|   50     String globalObject = namer.globalObjectFor(backend.interceptorsLibrary); |  | 
|   51     for (String name in names) { |  | 
|   52       jsAst.Expression function = |  | 
|   53           stubGenerator.generateOneShotInterceptor(name); |  | 
|   54       jsAst.Expression assignment = |  | 
|   55           js('${globalObject}.# = #', [name, function]); |  | 
|   56  |  | 
|   57       buffer.write(jsAst.prettyPrint(assignment, compiler)); |  | 
|   58       buffer.write(N); |  | 
|   59     } |  | 
|   60   } |  | 
|   61  |  | 
|   62   /** |  | 
|   63    * If [JSInvocationMirror._invokeOn] has been compiled, emit all the |  | 
|   64    * possible selector names that are intercepted into the |  | 
|   65    * [interceptedNames] top-level variable. The implementation of |  | 
|   66    * [_invokeOn] will use it to determine whether it should call the |  | 
|   67    * method with an extra parameter. |  | 
|   68    */ |  | 
|   69   void emitInterceptedNames(CodeBuffer buffer) { |  | 
|   70     // TODO(ahe): We should not generate the list of intercepted names at |  | 
|   71     // compile time, it can be generated automatically at runtime given |  | 
|   72     // subclasses of Interceptor (which can easily be identified). |  | 
|   73     if (!compiler.enabledInvokeOn) return; |  | 
|   74  |  | 
|   75     // TODO(ahe): We should roll this into |  | 
|   76     // [emitStaticNonFinalFieldInitializations]. |  | 
|   77     String name = backend.namer.getNameOfGlobalField(backend.interceptedNames); |  | 
|   78  |  | 
|   79     int index = 0; |  | 
|   80     var invocationNames = interceptorInvocationNames.toList()..sort(); |  | 
|   81     List<jsAst.ArrayElement> elements = invocationNames.map( |  | 
|   82       (String invocationName) { |  | 
|   83         jsAst.Literal str = js.string(invocationName); |  | 
|   84         return new jsAst.ArrayElement(index++, str); |  | 
|   85       }).toList(); |  | 
|   86     jsAst.ArrayInitializer array = |  | 
|   87         new jsAst.ArrayInitializer(invocationNames.length, elements); |  | 
|   88  |  | 
|   89     jsAst.Expression assignment = |  | 
|   90         js('${emitter.isolateProperties}.# = #', [name, array]); |  | 
|   91  |  | 
|   92     buffer.write(jsAst.prettyPrint(assignment, compiler)); |  | 
|   93     buffer.write(N); |  | 
|   94   } |  | 
|   95  |  | 
|   96   /** |  | 
|   97    * Emit initializer for [mapTypeToInterceptor] data structure used by |  | 
|   98    * [findInterceptorForType].  See declaration of [mapTypeToInterceptor] in |  | 
|   99    * `interceptors.dart`. |  | 
|  100    */ |  | 
|  101   void emitMapTypeToInterceptor(CodeBuffer buffer) { |  | 
|  102     // TODO(sra): Perhaps inject a constant instead? |  | 
|  103     CustomElementsAnalysis analysis = backend.customElementsAnalysis; |  | 
|  104     if (!analysis.needsTable) return; |  | 
|  105  |  | 
|  106     List<jsAst.Expression> elements = <jsAst.Expression>[]; |  | 
|  107     JavaScriptConstantCompiler handler = backend.constants; |  | 
|  108     List<ConstantValue> constants = |  | 
|  109         handler.getConstantsForEmission(emitter.compareConstants); |  | 
|  110     for (ConstantValue constant in constants) { |  | 
|  111       if (constant is TypeConstantValue) { |  | 
|  112         TypeConstantValue typeConstant = constant; |  | 
|  113         Element element = typeConstant.representedType.element; |  | 
|  114         if (element is ClassElement) { |  | 
|  115           ClassElement classElement = element; |  | 
|  116           if (!analysis.needsClass(classElement)) continue; |  | 
|  117  |  | 
|  118           elements.add(emitter.constantReference(constant)); |  | 
|  119           elements.add(namer.elementAccess(classElement)); |  | 
|  120  |  | 
|  121           // Create JavaScript Object map for by-name lookup of generative |  | 
|  122           // constructors.  For example, the class A has three generative |  | 
|  123           // constructors |  | 
|  124           // |  | 
|  125           //     class A { |  | 
|  126           //       A() {} |  | 
|  127           //       A.foo() {} |  | 
|  128           //       A.bar() {} |  | 
|  129           //     } |  | 
|  130           // |  | 
|  131           // Which are described by the map |  | 
|  132           // |  | 
|  133           //     {"": A.A$, "foo": A.A$foo, "bar": A.A$bar} |  | 
|  134           // |  | 
|  135           // We expect most of the time the map will be a singleton. |  | 
|  136           var properties = []; |  | 
|  137           for (Element member in analysis.constructors(classElement)) { |  | 
|  138             properties.add( |  | 
|  139                 new jsAst.Property( |  | 
|  140                     js.string(member.name), |  | 
|  141                     backend.namer.elementAccess(member))); |  | 
|  142           } |  | 
|  143  |  | 
|  144           var map = new jsAst.ObjectInitializer(properties); |  | 
|  145           elements.add(map); |  | 
|  146         } |  | 
|  147       } |  | 
|  148     } |  | 
|  149  |  | 
|  150     jsAst.ArrayInitializer array = new jsAst.ArrayInitializer.from(elements); |  | 
|  151     String name = |  | 
|  152         backend.namer.getNameOfGlobalField(backend.mapTypeToInterceptor); |  | 
|  153     jsAst.Expression assignment = |  | 
|  154         js('${emitter.isolateProperties}.# = #', [name, array]); |  | 
|  155  |  | 
|  156     buffer.write(jsAst.prettyPrint(assignment, compiler)); |  | 
|  157     buffer.write(N); |  | 
|  158   } |  | 
|  159 } |  | 
| OLD | NEW |