Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, 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 js_backend; | 5 part of js_backend; |
| 6 | 6 |
| 7 /** | 7 /** |
| 8 * A function element that represents a closure call. The signature is copied | 8 * A function element that represents a closure call. The signature is copied |
| 9 * from the given element. | 9 * from the given element. |
| 10 */ | 10 */ |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 82 } | 82 } |
| 83 | 83 |
| 84 js.Expression constantReference(Constant value) { | 84 js.Expression constantReference(Constant value) { |
| 85 return constantEmitter.reference(value); | 85 return constantEmitter.reference(value); |
| 86 } | 86 } |
| 87 | 87 |
| 88 js.Expression constantInitializerExpression(Constant value) { | 88 js.Expression constantInitializerExpression(Constant value) { |
| 89 return constantEmitter.initializationExpression(value); | 89 return constantEmitter.initializationExpression(value); |
| 90 } | 90 } |
| 91 | 91 |
| 92 // Deprecated. Remove after last use is converted to JS ASTs. | |
| 93 void writeConstantToBuffer(Constant value, CodeBuffer buffer) { | |
| 94 buffer.add(js.prettyPrint(constantReference(value), compiler)); | |
| 95 } | |
| 96 | |
| 97 String get name => 'CodeEmitter'; | 92 String get name => 'CodeEmitter'; |
| 98 | 93 |
| 99 String get defineClassName | 94 String get defineClassName |
| 100 => '${namer.ISOLATE}.\$defineClass'; | 95 => '${namer.ISOLATE}.\$defineClass'; |
| 101 String get finishClassesName | 96 String get finishClassesName |
| 102 => '${namer.ISOLATE}.\$finishClasses'; | 97 => '${namer.ISOLATE}.\$finishClasses'; |
| 103 String get finishIsolateConstructorName | 98 String get finishIsolateConstructorName |
| 104 => '${namer.ISOLATE}.\$finishIsolateConstructor'; | 99 => '${namer.ISOLATE}.\$finishIsolateConstructor'; |
| 105 String get pendingClassesName | 100 String get pendingClassesName |
| 106 => '${namer.ISOLATE}.\$pendingClasses'; | 101 => '${namer.ISOLATE}.\$pendingClasses'; |
| (...skipping 312 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 419 return; | 414 return; |
| 420 } | 415 } |
| 421 ConstantHandler handler = compiler.constantHandler; | 416 ConstantHandler handler = compiler.constantHandler; |
| 422 List<SourceString> names = selector.getOrderedNamedArguments(); | 417 List<SourceString> names = selector.getOrderedNamedArguments(); |
| 423 | 418 |
| 424 String invocationName = | 419 String invocationName = |
| 425 namer.instanceMethodInvocationName(member.getLibrary(), member.name, | 420 namer.instanceMethodInvocationName(member.getLibrary(), member.name, |
| 426 selector); | 421 selector); |
| 427 if (alreadyGenerated.contains(invocationName)) return; | 422 if (alreadyGenerated.contains(invocationName)) return; |
| 428 alreadyGenerated.add(invocationName); | 423 alreadyGenerated.add(invocationName); |
| 429 CodeBuffer buffer = new CodeBuffer(); | |
| 430 buffer.add('function('); | |
| 431 | 424 |
| 432 JavaScriptBackend backend = compiler.backend; | 425 JavaScriptBackend backend = compiler.backend; |
| 433 bool isInterceptorClass = | 426 bool isInterceptorClass = |
| 434 backend.isInterceptorClass(member.getEnclosingClass()); | 427 backend.isInterceptorClass(member.getEnclosingClass()); |
| 435 | 428 |
| 436 // If the method is in an interceptor class, we need to also pass | 429 // If the method is in an interceptor class, we need to also pass |
| 437 // the actual receiver. | 430 // the actual receiver. |
| 438 int extraArgumentCount = isInterceptorClass ? 1 : 0; | 431 int extraArgumentCount = isInterceptorClass ? 1 : 0; |
| 439 // Use '$receiver' to avoid clashes with other parameter names. Using | 432 // Use '$receiver' to avoid clashes with other parameter names. Using |
| 440 // '$receiver' works because [JsNames.getValid] used for getting parameter | 433 // '$receiver' works because [JsNames.getValid] used for getting parameter |
| 441 // names never returns a name beginning with a single '$'. | 434 // names never returns a name beginning with a single '$'. |
| 442 String receiverArgumentName = r'$receiver'; | 435 String receiverArgumentName = r'$receiver'; |
| 443 | 436 |
| 444 // The parameters that this stub takes. | 437 // The parameters that this stub takes. |
| 445 List<String> parametersBuffer = | 438 List<js.Parameter> parametersBuffer = |
| 446 new List<String>(selector.argumentCount + extraArgumentCount); | 439 new List<js.Parameter>(selector.argumentCount + extraArgumentCount); |
| 447 // The arguments that will be passed to the real method. | 440 // The arguments that will be passed to the real method. |
| 448 List<String> argumentsBuffer = | 441 List<js.Expression> argumentsBuffer = |
| 449 new List<String>(parameters.parameterCount + extraArgumentCount); | 442 new List<js.Expression>(parameters.parameterCount + extraArgumentCount); |
| 450 | 443 |
| 451 int count = 0; | 444 int count = 0; |
| 452 if (isInterceptorClass) { | 445 if (isInterceptorClass) { |
| 453 count++; | 446 count++; |
| 454 parametersBuffer[0] = receiverArgumentName; | 447 parametersBuffer[0] = new js.Parameter(receiverArgumentName); |
| 455 argumentsBuffer[0] = receiverArgumentName; | 448 argumentsBuffer[0] = new js.VariableUse(receiverArgumentName); |
| 456 } | 449 } |
| 457 | 450 |
| 458 int indexOfLastOptionalArgumentInParameters = positionalArgumentCount - 1; | 451 int indexOfLastOptionalArgumentInParameters = positionalArgumentCount - 1; |
| 459 TreeElements elements = | 452 TreeElements elements = |
| 460 compiler.enqueuer.resolution.getCachedElements(member); | 453 compiler.enqueuer.resolution.getCachedElements(member); |
| 461 | 454 |
| 462 parameters.orderedForEachParameter((Element element) { | 455 parameters.orderedForEachParameter((Element element) { |
| 463 String jsName = JsNames.getValid(element.name.slowToString()); | 456 String jsName = JsNames.getValid(element.name.slowToString()); |
| 464 assert(jsName != receiverArgumentName); | 457 assert(jsName != receiverArgumentName); |
| 465 if (count < positionalArgumentCount + extraArgumentCount) { | 458 if (count < positionalArgumentCount + extraArgumentCount) { |
| 466 parametersBuffer[count] = jsName; | 459 parametersBuffer[count] = new js.Parameter(jsName); |
| 467 argumentsBuffer[count] = jsName; | 460 argumentsBuffer[count] = new js.VariableUse(jsName); |
| 468 } else { | 461 } else { |
| 469 int index = names.indexOf(element.name); | 462 int index = names.indexOf(element.name); |
| 470 if (index != -1) { | 463 if (index != -1) { |
| 471 indexOfLastOptionalArgumentInParameters = count; | 464 indexOfLastOptionalArgumentInParameters = count; |
| 472 // The order of the named arguments is not the same as the | 465 // The order of the named arguments is not the same as the |
| 473 // one in the real method (which is in Dart source order). | 466 // one in the real method (which is in Dart source order). |
| 474 argumentsBuffer[count] = jsName; | 467 argumentsBuffer[count] = new js.VariableUse(jsName); |
| 475 parametersBuffer[selector.positionalArgumentCount + index] = jsName; | 468 parametersBuffer[selector.positionalArgumentCount + index] = |
| 469 new js.Parameter(jsName); | |
| 476 // Note that [elements] may be null for a synthetized [member]. | 470 // Note that [elements] may be null for a synthetized [member]. |
|
floitsch
2012/11/29 16:49:05
synthesized
sra1
2012/11/29 20:39:10
Done.
| |
| 477 } else if (elements != null && elements.isParameterChecked(element)) { | 471 } else if (elements != null && elements.isParameterChecked(element)) { |
| 478 CodeBuffer argumentBuffer = new CodeBuffer(); | 472 argumentsBuffer[count] = constantReference(SentinelConstant.SENTINEL); |
| 479 writeConstantToBuffer(SentinelConstant.SENTINEL, argumentBuffer); | |
| 480 argumentsBuffer[count] = argumentBuffer.toString(); | |
| 481 } else { | 473 } else { |
| 482 Constant value = handler.initialVariableValues[element]; | 474 Constant value = handler.initialVariableValues[element]; |
| 483 if (value == null) { | 475 if (value == null) { |
| 484 argumentsBuffer[count] = NullConstant.JsNull; | 476 argumentsBuffer[count] = constantReference(new NullConstant()); |
| 485 } else { | 477 } else { |
| 486 if (!value.isNull()) { | 478 if (!value.isNull()) { |
| 487 // If the value is the null constant, we should not pass it | 479 // If the value is the null constant, we should not pass it |
| 488 // down to the native method. | 480 // down to the native method. |
| 489 indexOfLastOptionalArgumentInParameters = count; | 481 indexOfLastOptionalArgumentInParameters = count; |
| 490 } | 482 } |
| 491 CodeBuffer argumentBuffer = new CodeBuffer(); | 483 argumentsBuffer[count] = constantReference(value); |
| 492 writeConstantToBuffer(value, argumentBuffer); | |
| 493 argumentsBuffer[count] = argumentBuffer.toString(); | |
| 494 } | 484 } |
| 495 } | 485 } |
| 496 } | 486 } |
| 497 count++; | 487 count++; |
| 498 }); | 488 }); |
| 499 String parametersString = Strings.join(parametersBuffer, ","); | |
| 500 buffer.add('$parametersString) {\n'); | |
| 501 | 489 |
| 490 List<js.Statement> body; | |
| 502 if (member.isNative()) { | 491 if (member.isNative()) { |
| 503 nativeEmitter.generateParameterStub( | 492 body = nativeEmitter.generateParameterStub( |
| 504 member, invocationName, parametersString, argumentsBuffer, | 493 member, invocationName, parametersBuffer, argumentsBuffer, |
| 505 indexOfLastOptionalArgumentInParameters, buffer); | 494 indexOfLastOptionalArgumentInParameters); |
| 506 } else { | 495 } else { |
| 507 String arguments = Strings.join(argumentsBuffer, ","); | 496 body = <js.Statement>[ |
| 508 buffer.add(' return this.${namer.getName(member)}($arguments)'); | 497 new js.Return( |
| 498 new js.VariableUse('this') | |
| 499 .dot(namer.getName(member)) | |
| 500 .callOn(argumentsBuffer))]; | |
| 509 } | 501 } |
| 510 buffer.add('\n}'); | 502 |
| 503 js.Fun function = new js.Fun(parametersBuffer, new js.Block(body)); | |
| 504 | |
| 505 CodeBuffer buffer = new CodeBuffer(); | |
| 506 buffer.add(js.prettyPrint(function, compiler)); | |
| 511 defineInstanceMember(invocationName, buffer); | 507 defineInstanceMember(invocationName, buffer); |
| 512 } | 508 } |
| 513 | 509 |
| 514 void addParameterStubs(FunctionElement member, | 510 void addParameterStubs(FunctionElement member, |
| 515 DefineMemberFunction defineInstanceMember) { | 511 DefineMemberFunction defineInstanceMember) { |
| 516 // We fill the lists depending on the selector. For example, | 512 // We fill the lists depending on the selector. For example, |
| 517 // take method foo: | 513 // take method foo: |
| 518 // foo(a, b, {c, d}); | 514 // foo(a, b, {c, d}); |
| 519 // | 515 // |
| 520 // We may have multiple ways of calling foo: | 516 // We may have multiple ways of calling foo: |
| (...skipping 1297 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1818 const String HOOKS_API_USAGE = """ | 1814 const String HOOKS_API_USAGE = """ |
| 1819 // Generated by dart2js, the Dart to JavaScript compiler. | 1815 // Generated by dart2js, the Dart to JavaScript compiler. |
| 1820 // The code supports the following hooks: | 1816 // The code supports the following hooks: |
| 1821 // dartPrint(message) - if this function is defined it is called | 1817 // dartPrint(message) - if this function is defined it is called |
| 1822 // instead of the Dart [print] method. | 1818 // instead of the Dart [print] method. |
| 1823 // dartMainRunner(main) - if this function is defined, the Dart [main] | 1819 // dartMainRunner(main) - if this function is defined, the Dart [main] |
| 1824 // method will not be invoked directly. | 1820 // method will not be invoked directly. |
| 1825 // Instead, a closure that will invoke [main] is | 1821 // Instead, a closure that will invoke [main] is |
| 1826 // passed to [dartMainRunner]. | 1822 // passed to [dartMainRunner]. |
| 1827 """; | 1823 """; |
| OLD | NEW |