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 |