| OLD | NEW |
| 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 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. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 library dart2js.js_emitter.class_stub_generator; | 5 library dart2js.js_emitter.class_stub_generator; |
| 6 | 6 |
| 7 import '../common/names.dart' show Identifiers; | 7 import '../common/names.dart' show Identifiers; |
| 8 import '../compiler.dart' show Compiler; | 8 import '../common_elements.dart' show CommonElements; |
| 9 import '../elements/entities.dart'; | 9 import '../elements/entities.dart'; |
| 10 import '../js/js.dart' as jsAst; | 10 import '../js/js.dart' as jsAst; |
| 11 import '../js/js.dart' show js; | 11 import '../js/js.dart' show js; |
| 12 import '../js_backend/js_backend.dart' show JavaScriptBackend, Namer; | 12 import '../js_backend/namer.dart' show Namer; |
| 13 import '../js_backend/interceptor_data.dart' show InterceptorData; |
| 14 import '../options.dart'; |
| 13 import '../universe/selector.dart' show Selector; | 15 import '../universe/selector.dart' show Selector; |
| 14 import '../universe/world_builder.dart' | 16 import '../universe/world_builder.dart' |
| 15 show CodegenWorldBuilder, SelectorConstraints; | 17 show CodegenWorldBuilder, SelectorConstraints; |
| 16 import '../world.dart' show ClosedWorld; | 18 import '../world.dart' show ClosedWorld; |
| 17 | 19 |
| 20 import 'code_emitter_task.dart'; |
| 18 import 'model.dart'; | 21 import 'model.dart'; |
| 19 | 22 |
| 20 class ClassStubGenerator { | 23 class ClassStubGenerator { |
| 21 final Namer namer; | 24 final Namer _namer; |
| 22 final JavaScriptBackend backend; | 25 final CodegenWorldBuilder _worldBuilder; |
| 23 final CodegenWorldBuilder worldBuilder; | 26 final ClosedWorld _closedWorld; |
| 24 final ClosedWorld closedWorld; | 27 final InterceptorData _interceptorData; |
| 25 final bool enableMinification; | 28 final bool enableMinification; |
| 29 final Emitter _emitter; |
| 30 final CommonElements _commonElements; |
| 26 | 31 |
| 27 ClassStubGenerator( | 32 ClassStubGenerator(this._emitter, this._commonElements, this._namer, |
| 28 this.namer, this.backend, this.worldBuilder, this.closedWorld, | 33 this._worldBuilder, this._interceptorData, this._closedWorld, |
| 29 {this.enableMinification}); | 34 {this.enableMinification}); |
| 30 | 35 |
| 31 jsAst.Expression generateClassConstructor( | 36 jsAst.Expression generateClassConstructor( |
| 32 ClassEntity classElement, Iterable<jsAst.Name> fields, bool hasRtiField) { | 37 ClassEntity classElement, Iterable<jsAst.Name> fields, bool hasRtiField) { |
| 33 // TODO(sra): Implement placeholders in VariableDeclaration position: | 38 // TODO(sra): Implement placeholders in VariableDeclaration position: |
| 34 // | 39 // |
| 35 // String constructorName = namer.getNameOfClass(classElement); | 40 // String constructorName = namer.getNameOfClass(classElement); |
| 36 // return js.statement('function #(#) { #; }', | 41 // return js.statement('function #(#) { #; }', |
| 37 // [ constructorName, fields, | 42 // [ constructorName, fields, |
| 38 // fields.map( | 43 // fields.map( |
| 39 // (name) => js('this.# = #', [name, name]))])); | 44 // (name) => js('this.# = #', [name, name]))])); |
| 40 var typeParameters = const <jsAst.Parameter>[]; | 45 var typeParameters = const <jsAst.Parameter>[]; |
| 41 var typeInits = const <jsAst.Expression>[]; | 46 var typeInits = const <jsAst.Expression>[]; |
| 42 if (hasRtiField) { | 47 if (hasRtiField) { |
| 43 var rtiName = namer.rtiFieldJsName; | 48 var rtiName = _namer.rtiFieldJsName; |
| 44 typeParameters = rtiName; | 49 typeParameters = rtiName; |
| 45 typeInits = js('this.# = #', [rtiName, rtiName]); | 50 typeInits = js('this.# = #', [rtiName, rtiName]); |
| 46 } | 51 } |
| 47 return js('function(#, #) { #; #; this.#();}', [ | 52 return js('function(#, #) { #; #; this.#();}', [ |
| 48 fields, | 53 fields, |
| 49 typeParameters, | 54 typeParameters, |
| 50 fields.map((name) => js('this.# = #', [name, name])), | 55 fields.map((name) => js('this.# = #', [name, name])), |
| 51 typeInits, | 56 typeInits, |
| 52 namer.deferredAction | 57 _namer.deferredAction |
| 53 ]); | 58 ]); |
| 54 } | 59 } |
| 55 | 60 |
| 56 jsAst.Expression generateGetter(MemberEntity member, jsAst.Name fieldName) { | 61 jsAst.Expression generateGetter(MemberEntity member, jsAst.Name fieldName) { |
| 57 ClassEntity cls = member.enclosingClass; | 62 ClassEntity cls = member.enclosingClass; |
| 58 String receiver = | 63 String receiver = |
| 59 backend.interceptorData.isInterceptedClass(cls) ? 'receiver' : 'this'; | 64 _interceptorData.isInterceptedClass(cls) ? 'receiver' : 'this'; |
| 60 List<String> args = | 65 List<String> args = |
| 61 backend.interceptorData.isInterceptedMethod(member) ? ['receiver'] : []; | 66 _interceptorData.isInterceptedMethod(member) ? ['receiver'] : []; |
| 62 return js('function(#) { return #.# }', [args, receiver, fieldName]); | 67 return js('function(#) { return #.# }', [args, receiver, fieldName]); |
| 63 } | 68 } |
| 64 | 69 |
| 65 jsAst.Expression generateSetter(MemberEntity member, jsAst.Name fieldName) { | 70 jsAst.Expression generateSetter(MemberEntity member, jsAst.Name fieldName) { |
| 66 ClassEntity cls = member.enclosingClass; | 71 ClassEntity cls = member.enclosingClass; |
| 67 String receiver = | 72 String receiver = |
| 68 backend.interceptorData.isInterceptedClass(cls) ? 'receiver' : 'this'; | 73 _interceptorData.isInterceptedClass(cls) ? 'receiver' : 'this'; |
| 69 List<String> args = | 74 List<String> args = |
| 70 backend.interceptorData.isInterceptedMethod(member) ? ['receiver'] : []; | 75 _interceptorData.isInterceptedMethod(member) ? ['receiver'] : []; |
| 71 // TODO(floitsch): remove 'return'? | 76 // TODO(floitsch): remove 'return'? |
| 72 return js( | 77 return js( |
| 73 'function(#, v) { return #.# = v; }', [args, receiver, fieldName]); | 78 'function(#, v) { return #.# = v; }', [args, receiver, fieldName]); |
| 74 } | 79 } |
| 75 | 80 |
| 76 /** | 81 /** |
| 77 * Documentation wanted -- johnniwinther | 82 * Documentation wanted -- johnniwinther |
| 78 * | 83 * |
| 79 * Invariant: [member] must be a declaration element. | 84 * Invariant: [member] must be a declaration element. |
| 80 */ | 85 */ |
| 81 Map<jsAst.Name, jsAst.Expression> generateCallStubsForGetter( | 86 Map<jsAst.Name, jsAst.Expression> generateCallStubsForGetter( |
| 82 MemberEntity member, Map<Selector, SelectorConstraints> selectors) { | 87 MemberEntity member, Map<Selector, SelectorConstraints> selectors) { |
| 83 // If the method is intercepted, the stub gets the | 88 // If the method is intercepted, the stub gets the |
| 84 // receiver explicitely and we need to pass it to the getter call. | 89 // receiver explicitely and we need to pass it to the getter call. |
| 85 bool isInterceptedMethod = | 90 bool isInterceptedMethod = _interceptorData.isInterceptedMethod(member); |
| 86 backend.interceptorData.isInterceptedMethod(member); | |
| 87 bool isInterceptedClass = | 91 bool isInterceptedClass = |
| 88 backend.interceptorData.isInterceptedClass(member.enclosingClass); | 92 _interceptorData.isInterceptedClass(member.enclosingClass); |
| 89 | 93 |
| 90 const String receiverArgumentName = r'$receiver'; | 94 const String receiverArgumentName = r'$receiver'; |
| 91 | 95 |
| 92 jsAst.Expression buildGetter() { | 96 jsAst.Expression buildGetter() { |
| 93 jsAst.Expression receiver = | 97 jsAst.Expression receiver = |
| 94 js(isInterceptedClass ? receiverArgumentName : 'this'); | 98 js(isInterceptedClass ? receiverArgumentName : 'this'); |
| 95 if (member.isGetter) { | 99 if (member.isGetter) { |
| 96 jsAst.Name getterName = namer.getterForElement(member); | 100 jsAst.Name getterName = _namer.getterForElement(member); |
| 97 if (isInterceptedMethod) { | 101 if (isInterceptedMethod) { |
| 98 return js('this.#(#)', [getterName, receiver]); | 102 return js('this.#(#)', [getterName, receiver]); |
| 99 } | 103 } |
| 100 return js('#.#()', [receiver, getterName]); | 104 return js('#.#()', [receiver, getterName]); |
| 101 } else { | 105 } else { |
| 102 jsAst.Name fieldName = namer.instanceFieldPropertyName(member); | 106 jsAst.Name fieldName = _namer.instanceFieldPropertyName(member); |
| 103 return js('#.#', [receiver, fieldName]); | 107 return js('#.#', [receiver, fieldName]); |
| 104 } | 108 } |
| 105 } | 109 } |
| 106 | 110 |
| 107 Map<jsAst.Name, jsAst.Expression> generatedStubs = | 111 Map<jsAst.Name, jsAst.Expression> generatedStubs = |
| 108 <jsAst.Name, jsAst.Expression>{}; | 112 <jsAst.Name, jsAst.Expression>{}; |
| 109 | 113 |
| 110 // Two selectors may match but differ only in type. To avoid generating | 114 // Two selectors may match but differ only in type. To avoid generating |
| 111 // identical stubs for each we track untyped selectors which already have | 115 // identical stubs for each we track untyped selectors which already have |
| 112 // stubs. | 116 // stubs. |
| 113 Set<Selector> generatedSelectors = new Set<Selector>(); | 117 Set<Selector> generatedSelectors = new Set<Selector>(); |
| 114 for (Selector selector in selectors.keys) { | 118 for (Selector selector in selectors.keys) { |
| 115 if (generatedSelectors.contains(selector)) continue; | 119 if (generatedSelectors.contains(selector)) continue; |
| 116 if (!selector.appliesUnnamed(member)) continue; | 120 if (!selector.appliesUnnamed(member)) continue; |
| 117 if (selectors[selector].applies(member, selector, closedWorld)) { | 121 if (selectors[selector].applies(member, selector, _closedWorld)) { |
| 118 generatedSelectors.add(selector); | 122 generatedSelectors.add(selector); |
| 119 | 123 |
| 120 jsAst.Name invocationName = namer.invocationName(selector); | 124 jsAst.Name invocationName = _namer.invocationName(selector); |
| 121 Selector callSelector = new Selector.callClosureFrom(selector); | 125 Selector callSelector = new Selector.callClosureFrom(selector); |
| 122 jsAst.Name closureCallName = namer.invocationName(callSelector); | 126 jsAst.Name closureCallName = _namer.invocationName(callSelector); |
| 123 | 127 |
| 124 List<jsAst.Parameter> parameters = <jsAst.Parameter>[]; | 128 List<jsAst.Parameter> parameters = <jsAst.Parameter>[]; |
| 125 List<jsAst.Expression> arguments = <jsAst.Expression>[]; | 129 List<jsAst.Expression> arguments = <jsAst.Expression>[]; |
| 126 if (isInterceptedMethod) { | 130 if (isInterceptedMethod) { |
| 127 parameters.add(new jsAst.Parameter(receiverArgumentName)); | 131 parameters.add(new jsAst.Parameter(receiverArgumentName)); |
| 128 } | 132 } |
| 129 | 133 |
| 130 for (int i = 0; i < selector.argumentCount; i++) { | 134 for (int i = 0; i < selector.argumentCount; i++) { |
| 131 String name = 'arg$i'; | 135 String name = 'arg$i'; |
| 132 parameters.add(new jsAst.Parameter(name)); | 136 parameters.add(new jsAst.Parameter(name)); |
| 133 arguments.add(js('#', name)); | 137 arguments.add(js('#', name)); |
| 134 } | 138 } |
| 135 | 139 |
| 136 jsAst.Fun function = js('function(#) { return #.#(#); }', | 140 jsAst.Fun function = js('function(#) { return #.#(#); }', |
| 137 [parameters, buildGetter(), closureCallName, arguments]); | 141 [parameters, buildGetter(), closureCallName, arguments]); |
| 138 | 142 |
| 139 generatedStubs[invocationName] = function; | 143 generatedStubs[invocationName] = function; |
| 140 } | 144 } |
| 141 } | 145 } |
| 142 | 146 |
| 143 return generatedStubs; | 147 return generatedStubs; |
| 144 } | 148 } |
| 145 | 149 |
| 146 Map<jsAst.Name, Selector> computeSelectorsForNsmHandlers() { | 150 Map<jsAst.Name, Selector> computeSelectorsForNsmHandlers() { |
| 147 Map<jsAst.Name, Selector> jsNames = <jsAst.Name, Selector>{}; | 151 Map<jsAst.Name, Selector> jsNames = <jsAst.Name, Selector>{}; |
| 148 | 152 |
| 149 // Do not generate no such method handlers if there is no class. | 153 // Do not generate no such method handlers if there is no class. |
| 150 if (worldBuilder.directlyInstantiatedClasses.isEmpty) { | 154 if (_worldBuilder.directlyInstantiatedClasses.isEmpty) { |
| 151 return jsNames; | 155 return jsNames; |
| 152 } | 156 } |
| 153 | 157 |
| 154 void addNoSuchMethodHandlers( | 158 void addNoSuchMethodHandlers( |
| 155 String ignore, Map<Selector, SelectorConstraints> selectors) { | 159 String ignore, Map<Selector, SelectorConstraints> selectors) { |
| 156 for (Selector selector in selectors.keys) { | 160 for (Selector selector in selectors.keys) { |
| 157 SelectorConstraints maskSet = selectors[selector]; | 161 SelectorConstraints maskSet = selectors[selector]; |
| 158 if (maskSet.needsNoSuchMethodHandling(selector, closedWorld)) { | 162 if (maskSet.needsNoSuchMethodHandling(selector, _closedWorld)) { |
| 159 jsAst.Name jsName = namer.invocationMirrorInternalName(selector); | 163 jsAst.Name jsName = _namer.invocationMirrorInternalName(selector); |
| 160 jsNames[jsName] = selector; | 164 jsNames[jsName] = selector; |
| 161 } | 165 } |
| 162 } | 166 } |
| 163 } | 167 } |
| 164 | 168 |
| 165 worldBuilder.forEachInvokedName(addNoSuchMethodHandlers); | 169 _worldBuilder.forEachInvokedName(addNoSuchMethodHandlers); |
| 166 worldBuilder.forEachInvokedGetter(addNoSuchMethodHandlers); | 170 _worldBuilder.forEachInvokedGetter(addNoSuchMethodHandlers); |
| 167 worldBuilder.forEachInvokedSetter(addNoSuchMethodHandlers); | 171 _worldBuilder.forEachInvokedSetter(addNoSuchMethodHandlers); |
| 168 return jsNames; | 172 return jsNames; |
| 169 } | 173 } |
| 170 | 174 |
| 171 StubMethod generateStubForNoSuchMethod(jsAst.Name name, Selector selector) { | 175 StubMethod generateStubForNoSuchMethod(jsAst.Name name, Selector selector) { |
| 172 // Values match JSInvocationMirror in js-helper library. | 176 // Values match JSInvocationMirror in js-helper library. |
| 173 int type = selector.invocationMirrorKind; | 177 int type = selector.invocationMirrorKind; |
| 174 List<String> parameterNames = | 178 List<String> parameterNames = |
| 175 new List.generate(selector.argumentCount, (i) => '\$$i'); | 179 new List.generate(selector.argumentCount, (i) => '\$$i'); |
| 176 | 180 |
| 177 List<jsAst.Expression> argNames = selector.callStructure | 181 List<jsAst.Expression> argNames = selector.callStructure |
| 178 .getOrderedNamedArguments() | 182 .getOrderedNamedArguments() |
| 179 .map((String name) => js.string(name)) | 183 .map((String name) => js.string(name)) |
| 180 .toList(); | 184 .toList(); |
| 181 | 185 |
| 182 jsAst.Name methodName = namer.asName(selector.invocationMirrorMemberName); | 186 jsAst.Name methodName = _namer.asName(selector.invocationMirrorMemberName); |
| 183 jsAst.Name internalName = namer.invocationMirrorInternalName(selector); | 187 jsAst.Name internalName = _namer.invocationMirrorInternalName(selector); |
| 184 | 188 |
| 185 assert( | 189 assert(_interceptorData.isInterceptedName(Identifiers.noSuchMethod_)); |
| 186 backend.interceptorData.isInterceptedName(Identifiers.noSuchMethod_)); | 190 bool isIntercepted = _interceptorData.isInterceptedName(selector.name); |
| 187 bool isIntercepted = | |
| 188 backend.interceptorData.isInterceptedName(selector.name); | |
| 189 jsAst.Expression expression = js( | 191 jsAst.Expression expression = js( |
| 190 '''this.#noSuchMethodName(#receiver, | 192 '''this.#noSuchMethodName(#receiver, |
| 191 #createInvocationMirror(#methodName, | 193 #createInvocationMirror(#methodName, |
| 192 #internalName, | 194 #internalName, |
| 193 #type, | 195 #type, |
| 194 #arguments, | 196 #arguments, |
| 195 #namedArguments))''', | 197 #namedArguments))''', |
| 196 { | 198 { |
| 197 'receiver': isIntercepted ? r'$receiver' : 'this', | 199 'receiver': isIntercepted ? r'$receiver' : 'this', |
| 198 'noSuchMethodName': namer.noSuchMethodName, | 200 'noSuchMethodName': _namer.noSuchMethodName, |
| 199 'createInvocationMirror': backend.emitter.staticFunctionAccess( | 201 'createInvocationMirror': _emitter |
| 200 backend.commonElements.createInvocationMirror), | 202 .staticFunctionAccess(_commonElements.createInvocationMirror), |
| 201 'methodName': | 203 'methodName': |
| 202 js.quoteName(enableMinification ? internalName : methodName), | 204 js.quoteName(enableMinification ? internalName : methodName), |
| 203 'internalName': js.quoteName(internalName), | 205 'internalName': js.quoteName(internalName), |
| 204 'type': js.number(type), | 206 'type': js.number(type), |
| 205 'arguments': | 207 'arguments': |
| 206 new jsAst.ArrayInitializer(parameterNames.map(js).toList()), | 208 new jsAst.ArrayInitializer(parameterNames.map(js).toList()), |
| 207 'namedArguments': new jsAst.ArrayInitializer(argNames) | 209 'namedArguments': new jsAst.ArrayInitializer(argNames) |
| 208 }); | 210 }); |
| 209 | 211 |
| 210 jsAst.Expression function; | 212 jsAst.Expression function; |
| (...skipping 14 matching lines...) Expand all Loading... |
| 225 /// `tearOff` takes the following arguments: | 227 /// `tearOff` takes the following arguments: |
| 226 /// * `funcs`: a list of functions. These are the functions representing the | 228 /// * `funcs`: a list of functions. These are the functions representing the |
| 227 /// member that is torn off. There can be more than one, since a member | 229 /// member that is torn off. There can be more than one, since a member |
| 228 /// can have several stubs. | 230 /// can have several stubs. |
| 229 /// Each function must have the `$callName` property set. | 231 /// Each function must have the `$callName` property set. |
| 230 /// * `reflectionInfo`: contains reflective information, and the function | 232 /// * `reflectionInfo`: contains reflective information, and the function |
| 231 /// type. TODO(floitsch): point to where this is specified. | 233 /// type. TODO(floitsch): point to where this is specified. |
| 232 /// * `isStatic`. | 234 /// * `isStatic`. |
| 233 /// * `name`. | 235 /// * `name`. |
| 234 /// * `isIntercepted. | 236 /// * `isIntercepted. |
| 235 List<jsAst.Statement> buildTearOffCode(JavaScriptBackend backend) { | 237 List<jsAst.Statement> buildTearOffCode(CompilerOptions options, Emitter emitter, |
| 236 Namer namer = backend.namer; | 238 Namer namer, CommonElements commonElements) { |
| 237 Compiler compiler = backend.compiler; | 239 FunctionEntity closureFromTearOff = commonElements.closureFromTearOff; |
| 238 | |
| 239 FunctionEntity closureFromTearOff = backend.commonElements.closureFromTearOff; | |
| 240 jsAst.Expression tearOffAccessExpression; | 240 jsAst.Expression tearOffAccessExpression; |
| 241 jsAst.Expression tearOffGlobalObjectString; | 241 jsAst.Expression tearOffGlobalObjectString; |
| 242 jsAst.Expression tearOffGlobalObject; | 242 jsAst.Expression tearOffGlobalObject; |
| 243 if (closureFromTearOff != null) { | 243 if (closureFromTearOff != null) { |
| 244 tearOffAccessExpression = | 244 tearOffAccessExpression = emitter.staticFunctionAccess(closureFromTearOff); |
| 245 backend.emitter.staticFunctionAccess(closureFromTearOff); | |
| 246 tearOffGlobalObject = | 245 tearOffGlobalObject = |
| 247 js.stringPart(namer.globalObjectForMethod(closureFromTearOff)); | 246 js.stringPart(namer.globalObjectForMethod(closureFromTearOff)); |
| 248 tearOffGlobalObjectString = | 247 tearOffGlobalObjectString = |
| 249 js.string(namer.globalObjectForMethod(closureFromTearOff)); | 248 js.string(namer.globalObjectForMethod(closureFromTearOff)); |
| 250 } else { | 249 } else { |
| 251 // Default values for mocked-up test libraries. | 250 // Default values for mocked-up test libraries. |
| 252 tearOffAccessExpression = | 251 tearOffAccessExpression = |
| 253 js(r'''function() { throw "Helper 'closureFromTearOff' missing." }'''); | 252 js(r'''function() { throw "Helper 'closureFromTearOff' missing." }'''); |
| 254 tearOffGlobalObjectString = js.string('MissingHelperFunction'); | 253 tearOffGlobalObjectString = js.string('MissingHelperFunction'); |
| 255 tearOffGlobalObject = js( | 254 tearOffGlobalObject = js( |
| 256 r'''(function() { throw "Helper 'closureFromTearOff' missing." })()'''); | 255 r'''(function() { throw "Helper 'closureFromTearOff' missing." })()'''); |
| 257 } | 256 } |
| 258 | 257 |
| 259 jsAst.Statement tearOffGetter; | 258 jsAst.Statement tearOffGetter; |
| 260 if (!compiler.options.useContentSecurityPolicy) { | 259 if (!options.useContentSecurityPolicy) { |
| 261 jsAst.Expression tearOffAccessText = new jsAst.UnparsedNode( | 260 jsAst.Expression tearOffAccessText = |
| 262 tearOffAccessExpression, compiler.options, false); | 261 new jsAst.UnparsedNode(tearOffAccessExpression, options, false); |
| 263 tearOffGetter = js.statement( | 262 tearOffGetter = js.statement( |
| 264 ''' | 263 ''' |
| 265 function tearOffGetter(funcs, reflectionInfo, name, isIntercepted) { | 264 function tearOffGetter(funcs, reflectionInfo, name, isIntercepted) { |
| 266 return isIntercepted | 265 return isIntercepted |
| 267 ? new Function("funcs", "reflectionInfo", "name", | 266 ? new Function("funcs", "reflectionInfo", "name", |
| 268 #tearOffGlobalObjectString, "c", | 267 #tearOffGlobalObjectString, "c", |
| 269 "return function tearOff_" + name + (functionCounter++) + "(x) {" + | 268 "return function tearOff_" + name + (functionCounter++) + "(x) {" + |
| 270 "if (c === null) c = " + #tearOffAccessText + "(" + | 269 "if (c === null) c = " + #tearOffAccessText + "(" + |
| 271 "this, funcs, reflectionInfo, false, [x], name);" + | 270 "this, funcs, reflectionInfo, false, [x], name);" + |
| 272 "return new c(this, funcs[0], x, name);" + | 271 "return new c(this, funcs[0], x, name);" + |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 313 if (cache === void 0) cache = #tearOff( | 312 if (cache === void 0) cache = #tearOff( |
| 314 this, funcs, reflectionInfo, true, [], name).prototype; | 313 this, funcs, reflectionInfo, true, [], name).prototype; |
| 315 return cache; | 314 return cache; |
| 316 } | 315 } |
| 317 : tearOffGetter(funcs, reflectionInfo, name, isIntercepted); | 316 : tearOffGetter(funcs, reflectionInfo, name, isIntercepted); |
| 318 }''', | 317 }''', |
| 319 {'tearOff': tearOffAccessExpression}); | 318 {'tearOff': tearOffAccessExpression}); |
| 320 | 319 |
| 321 return <jsAst.Statement>[tearOffGetter, tearOff]; | 320 return <jsAst.Statement>[tearOffGetter, tearOff]; |
| 322 } | 321 } |
| OLD | NEW |