| OLD | NEW |
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 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 | 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 part of dart2js.js_emitter; | 5 part of dart2js.js_emitter; |
| 6 | 6 |
| 7 /// This class should morph into something that makes it easy to build | 7 /// This class should morph into something that makes it easy to build |
| 8 /// JavaScript representations of libraries, class-sides, and instance-sides. | 8 /// JavaScript representations of libraries, class-sides, and instance-sides. |
| 9 /// Initially, it is just a placeholder for code that is moved from | 9 /// Initially, it is just a placeholder for code that is moved from |
| 10 /// [CodeEmitterTask]. | 10 /// [CodeEmitterTask]. |
| 11 class ContainerBuilder extends CodeEmitterHelper { | 11 class ContainerBuilder extends CodeEmitterHelper { |
| 12 bool needsSuperGetter(FunctionElement element) => | 12 bool needsSuperGetter(FunctionElement element) => |
| 13 compiler.codegenWorld.methodsNeedingSuperGetter.contains(element); | 13 compiler.codegenWorld.methodsNeedingSuperGetter.contains(element); |
| 14 | 14 |
| 15 /** | 15 /** |
| 16 * Generate stubs to handle invocation of methods with optional | 16 * Generate stubs to handle invocation of methods with optional |
| 17 * arguments. | 17 * arguments. |
| 18 * | 18 * |
| 19 * A method like [: foo([x]) :] may be invoked by the following | 19 * A method like [: foo([x]) :] may be invoked by the following |
| 20 * calls: [: foo(), foo(1), foo(x: 1) :]. See the sources of this | 20 * calls: [: foo(), foo(1), foo(x: 1) :]. See the sources of this |
| 21 * function for detailed examples. | 21 * function for detailed examples. |
| 22 */ | 22 */ |
| 23 void addParameterStub(FunctionElement member, | 23 void addParameterStub(FunctionElement member, |
| 24 Selector selector, | 24 Selector selector, |
| 25 AddStubFunction addStub, | 25 AddStubFunction addStub) { |
| 26 Set<String> alreadyGenerated) { | |
| 27 FunctionSignature parameters = member.functionSignature; | 26 FunctionSignature parameters = member.functionSignature; |
| 28 int positionalArgumentCount = selector.positionalArgumentCount; | 27 int positionalArgumentCount = selector.positionalArgumentCount; |
| 29 if (positionalArgumentCount == parameters.parameterCount) { | 28 if (positionalArgumentCount == parameters.parameterCount) { |
| 30 assert(selector.namedArgumentCount == 0); | 29 assert(selector.namedArgumentCount == 0); |
| 31 return; | 30 return; |
| 32 } | 31 } |
| 33 if (parameters.optionalParametersAreNamed | 32 if (parameters.optionalParametersAreNamed |
| 34 && selector.namedArgumentCount == parameters.optionalParameterCount) { | 33 && selector.namedArgumentCount == parameters.optionalParameterCount) { |
| 35 // If the selector has the same number of named arguments as the element, | 34 // If the selector has the same number of named arguments as the element, |
| 36 // we don't need to add a stub. The call site will hit the method | 35 // we don't need to add a stub. The call site will hit the method |
| 37 // directly. | 36 // directly. |
| 38 return; | 37 return; |
| 39 } | 38 } |
| 40 JavaScriptConstantCompiler handler = backend.constants; | 39 JavaScriptConstantCompiler handler = backend.constants; |
| 41 List<String> names = selector.getOrderedNamedArguments(); | 40 List<String> names = selector.getOrderedNamedArguments(); |
| 42 | 41 |
| 43 String invocationName = namer.invocationName(selector); | |
| 44 if (alreadyGenerated.contains(invocationName)) return; | |
| 45 alreadyGenerated.add(invocationName); | |
| 46 | |
| 47 bool isInterceptedMethod = backend.isInterceptedMethod(member); | 42 bool isInterceptedMethod = backend.isInterceptedMethod(member); |
| 48 | 43 |
| 49 // If the method is intercepted, we need to also pass the actual receiver. | 44 // If the method is intercepted, we need to also pass the actual receiver. |
| 50 int extraArgumentCount = isInterceptedMethod ? 1 : 0; | 45 int extraArgumentCount = isInterceptedMethod ? 1 : 0; |
| 51 // Use '$receiver' to avoid clashes with other parameter names. Using | 46 // Use '$receiver' to avoid clashes with other parameter names. Using |
| 52 // '$receiver' works because [:namer.safeName:] used for getting parameter | 47 // '$receiver' works because [:namer.safeName:] used for getting parameter |
| 53 // names never returns a name beginning with a single '$'. | 48 // names never returns a name beginning with a single '$'. |
| 54 String receiverArgumentName = r'$receiver'; | 49 String receiverArgumentName = r'$receiver'; |
| 55 | 50 |
| 56 // The parameters that this stub takes. | 51 // The parameters that this stub takes. |
| 57 List<jsAst.Parameter> parametersBuffer = | 52 List<jsAst.Parameter> parametersBuffer = |
| 58 new List<jsAst.Parameter>(selector.argumentCount + extraArgumentCount); | 53 new List<jsAst.Parameter>(selector.argumentCount + extraArgumentCount); |
| 59 // The arguments that will be passed to the real method. | 54 // The arguments that will be passed to the real method. |
| 60 List<jsAst.Expression> argumentsBuffer = | 55 List<jsAst.Expression> argumentsBuffer = |
| 61 new List<jsAst.Expression>( | 56 new List<jsAst.Expression>( |
| 62 parameters.parameterCount + extraArgumentCount); | 57 parameters.parameterCount + extraArgumentCount); |
| 58 String invocationName = namer.invocationName(selector); |
| 63 | 59 |
| 64 int count = 0; | 60 int count = 0; |
| 65 if (isInterceptedMethod) { | 61 if (isInterceptedMethod) { |
| 66 count++; | 62 count++; |
| 67 parametersBuffer[0] = new jsAst.Parameter(receiverArgumentName); | 63 parametersBuffer[0] = new jsAst.Parameter(receiverArgumentName); |
| 68 argumentsBuffer[0] = js('#', receiverArgumentName); | 64 argumentsBuffer[0] = js('#', receiverArgumentName); |
| 69 emitter.interceptorEmitter.interceptorInvocationNames.add(invocationName); | 65 emitter.interceptorEmitter.interceptorInvocationNames.add(invocationName); |
| 70 } | 66 } |
| 71 | 67 |
| 72 int optionalParameterStart = positionalArgumentCount + extraArgumentCount; | 68 int optionalParameterStart = positionalArgumentCount + extraArgumentCount; |
| (...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 210 Set<Selector> callSelectors = callSelectorsAsNamed(); | 206 Set<Selector> callSelectors = callSelectorsAsNamed(); |
| 211 if (callSelectors != null) { | 207 if (callSelectors != null) { |
| 212 selectors = selectors.union(callSelectors); | 208 selectors = selectors.union(callSelectors); |
| 213 } | 209 } |
| 214 } | 210 } |
| 215 Set<Selector> untypedSelectors = new Set<Selector>(); | 211 Set<Selector> untypedSelectors = new Set<Selector>(); |
| 216 if (selectors != null) { | 212 if (selectors != null) { |
| 217 for (Selector selector in selectors) { | 213 for (Selector selector in selectors) { |
| 218 if (!selector.appliesUnnamed(member, compiler.world)) continue; | 214 if (!selector.appliesUnnamed(member, compiler.world)) continue; |
| 219 if (untypedSelectors.add(selector.asUntyped)) { | 215 if (untypedSelectors.add(selector.asUntyped)) { |
| 220 // TODO(ahe): Is the last argument to [addParameterStub] needed? | 216 addParameterStub(member, selector, defineStub); |
| 221 addParameterStub(member, selector, defineStub, new Set<String>()); | |
| 222 } | 217 } |
| 223 } | 218 } |
| 224 } | 219 } |
| 225 if (canTearOff) { | 220 if (canTearOff) { |
| 226 selectors = compiler.codegenWorld.invokedNames[ | 221 selectors = compiler.codegenWorld.invokedNames[ |
| 227 namer.closureInvocationSelectorName]; | 222 namer.closureInvocationSelectorName]; |
| 228 if (selectors != null) { | 223 if (selectors != null) { |
| 229 for (Selector selector in selectors) { | 224 for (Selector selector in selectors) { |
| 230 selector = new Selector.call( | 225 selector = new Selector.call( |
| 231 member.name, member.library, | 226 member.name, member.library, |
| 232 selector.argumentCount, selector.namedArguments); | 227 selector.argumentCount, selector.namedArguments); |
| 233 if (!selector.appliesUnnamed(member, compiler.world)) continue; | 228 if (!selector.appliesUnnamed(member, compiler.world)) continue; |
| 234 if (untypedSelectors.add(selector)) { | 229 if (untypedSelectors.add(selector)) { |
| 235 // TODO(ahe): Is the last argument to [addParameterStub] needed? | 230 addParameterStub(member, selector, defineStub); |
| 236 addParameterStub(member, selector, defineStub, new Set<String>()); | |
| 237 } | 231 } |
| 238 } | 232 } |
| 239 } | 233 } |
| 240 } | 234 } |
| 241 } | 235 } |
| 242 | 236 |
| 243 void addMember(Element member, ClassBuilder builder) { | 237 void addMember(Element member, ClassBuilder builder) { |
| 244 assert(invariant(member, member.isDeclaration)); | 238 assert(invariant(member, member.isDeclaration)); |
| 245 | 239 |
| 246 if (member.isField) { | 240 if (member.isField) { |
| (...skipping 334 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 581 assert(needsStubs != null); | 575 assert(needsStubs != null); |
| 582 assert(canTearOff != null); | 576 assert(canTearOff != null); |
| 583 assert(isClosure != null); | 577 assert(isClosure != null); |
| 584 assert(tearOffName != null || !canTearOff); | 578 assert(tearOffName != null || !canTearOff); |
| 585 assert(canBeReflected != null); | 579 assert(canBeReflected != null); |
| 586 assert(canBeApplied != null); | 580 assert(canBeApplied != null); |
| 587 assert(hasSuperAlias != null); | 581 assert(hasSuperAlias != null); |
| 588 assert(needStructuredInfo != null); | 582 assert(needStructuredInfo != null); |
| 589 } | 583 } |
| 590 } | 584 } |
| OLD | NEW |