| 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 */ |
| 11 class ClosureInvocationElement extends FunctionElement { | 11 class ClosureInvocationElement extends FunctionElement { |
| 12 ClosureInvocationElement(SourceString name, | 12 ClosureInvocationElement(SourceString name, |
| 13 FunctionElement other) | 13 FunctionElement other) |
| 14 : super.from(name, other, other.enclosingElement), | 14 : super.from(name, other, other.enclosingElement), |
| 15 methodElement = other; | 15 methodElement = other; |
| 16 | 16 |
| 17 isInstanceMember() => true; | 17 isInstanceMember() => true; |
| 18 | 18 |
| 19 Element getOutermostEnclosingMemberOrTopLevel() => methodElement; | 19 Element getOutermostEnclosingMemberOrTopLevel() => methodElement; |
| 20 | 20 |
| 21 /** | 21 /** |
| 22 * The [member] this invocation refers to. | 22 * The [member] this invocation refers to. |
| 23 */ | 23 */ |
| 24 Element methodElement; | 24 Element methodElement; |
| 25 } | 25 } |
| 26 | 26 |
| 27 /** | 27 /** |
| 28 * A convenient type alias for some functions that emit keyed values. |
| 29 */ |
| 30 typedef void DefineStubFunction(String invocationName, js.Expression value); |
| 31 |
| 32 /** |
| 33 * A data structure for collecting fragments of a class definition. |
| 34 */ |
| 35 class ClassBuilder { |
| 36 final List<js.Property> properties = <js.Property>[]; |
| 37 |
| 38 // Has the same signature as [DefineStubFunction]. |
| 39 void addProperty(String name, js.Expression value) { |
| 40 properties.add(new js.Property(js.string(name), value)); |
| 41 } |
| 42 |
| 43 js.Expression toObjectInitializer() => new js.ObjectInitializer(properties); |
| 44 } |
| 45 |
| 46 /** |
| 28 * Generates the code for all used classes in the program. Static fields (even | 47 * Generates the code for all used classes in the program. Static fields (even |
| 29 * in classes) are ignored, since they can be treated as non-class elements. | 48 * in classes) are ignored, since they can be treated as non-class elements. |
| 30 * | 49 * |
| 31 * The code for the containing (used) methods must exist in the [:universe:]. | 50 * The code for the containing (used) methods must exist in the [:universe:]. |
| 32 */ | 51 */ |
| 33 class CodeEmitterTask extends CompilerTask { | 52 class CodeEmitterTask extends CompilerTask { |
| 34 bool needsInheritFunction = false; | 53 bool needsInheritFunction = false; |
| 35 bool needsDefineClass = false; | 54 bool needsDefineClass = false; |
| 36 bool needsClosureClass = false; | 55 bool needsClosureClass = false; |
| 37 bool needsLazyInitializer = false; | 56 bool needsLazyInitializer = false; |
| (...skipping 382 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 420 /** | 439 /** |
| 421 * Generate stubs to handle invocation of methods with optional | 440 * Generate stubs to handle invocation of methods with optional |
| 422 * arguments. | 441 * arguments. |
| 423 * | 442 * |
| 424 * A method like [: foo([x]) :] may be invoked by the following | 443 * A method like [: foo([x]) :] may be invoked by the following |
| 425 * calls: [: foo(), foo(1), foo(x: 1) :]. See the sources of this | 444 * calls: [: foo(), foo(1), foo(x: 1) :]. See the sources of this |
| 426 * function for detailed examples. | 445 * function for detailed examples. |
| 427 */ | 446 */ |
| 428 void addParameterStub(FunctionElement member, | 447 void addParameterStub(FunctionElement member, |
| 429 Selector selector, | 448 Selector selector, |
| 430 DefineMemberFunction defineInstanceMember, | 449 DefineStubFunction defineStub, |
| 431 Set<String> alreadyGenerated) { | 450 Set<String> alreadyGenerated) { |
| 432 FunctionSignature parameters = member.computeSignature(compiler); | 451 FunctionSignature parameters = member.computeSignature(compiler); |
| 433 int positionalArgumentCount = selector.positionalArgumentCount; | 452 int positionalArgumentCount = selector.positionalArgumentCount; |
| 434 if (positionalArgumentCount == parameters.parameterCount) { | 453 if (positionalArgumentCount == parameters.parameterCount) { |
| 435 assert(selector.namedArgumentCount == 0); | 454 assert(selector.namedArgumentCount == 0); |
| 436 return; | 455 return; |
| 437 } | 456 } |
| 438 if (parameters.optionalParametersAreNamed | 457 if (parameters.optionalParametersAreNamed |
| 439 && selector.namedArgumentCount == parameters.optionalParameterCount) { | 458 && selector.namedArgumentCount == parameters.optionalParameterCount) { |
| 440 // If the selector has the same number of named arguments as | 459 // If the selector has the same number of named arguments as |
| (...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 524 } else { | 543 } else { |
| 525 body = <js.Statement>[ | 544 body = <js.Statement>[ |
| 526 new js.Return( | 545 new js.Return( |
| 527 new js.VariableUse('this') | 546 new js.VariableUse('this') |
| 528 .dot(namer.getName(member)) | 547 .dot(namer.getName(member)) |
| 529 .callWith(argumentsBuffer))]; | 548 .callWith(argumentsBuffer))]; |
| 530 } | 549 } |
| 531 | 550 |
| 532 js.Fun function = new js.Fun(parametersBuffer, new js.Block(body)); | 551 js.Fun function = new js.Fun(parametersBuffer, new js.Block(body)); |
| 533 | 552 |
| 534 CodeBuffer buffer = new CodeBuffer(); | 553 defineStub(invocationName, function); |
| 535 buffer.add(js.prettyPrint(function, compiler)); | |
| 536 defineInstanceMember(invocationName, buffer); | |
| 537 } | 554 } |
| 538 | 555 |
| 539 void addParameterStubs(FunctionElement member, | 556 void addParameterStubs(FunctionElement member, |
| 540 DefineMemberFunction defineInstanceMember) { | 557 DefineStubFunction defineStub) { |
| 541 // We fill the lists depending on the selector. For example, | 558 // We fill the lists depending on the selector. For example, |
| 542 // take method foo: | 559 // take method foo: |
| 543 // foo(a, b, {c, d}); | 560 // foo(a, b, {c, d}); |
| 544 // | 561 // |
| 545 // We may have multiple ways of calling foo: | 562 // We may have multiple ways of calling foo: |
| 546 // (1) foo(1, 2); | 563 // (1) foo(1, 2); |
| 547 // (2) foo(1, 2, c: 3); | 564 // (2) foo(1, 2, c: 3); |
| 548 // (3) foo(1, 2, d: 4); | 565 // (3) foo(1, 2, d: 4); |
| 549 // (4) foo(1, 2, c: 3, d: 4); | 566 // (4) foo(1, 2, c: 3, d: 4); |
| 550 // (5) foo(1, 2, d: 4, c: 3); | 567 // (5) foo(1, 2, d: 4, c: 3); |
| (...skipping 19 matching lines...) Expand all Loading... |
| 570 Set<String> generatedStubNames = new Set<String>(); | 587 Set<String> generatedStubNames = new Set<String>(); |
| 571 if (compiler.enabledFunctionApply | 588 if (compiler.enabledFunctionApply |
| 572 && member.name == namer.closureInvocationSelectorName) { | 589 && member.name == namer.closureInvocationSelectorName) { |
| 573 // If [Function.apply] is called, we pessimistically compile all | 590 // If [Function.apply] is called, we pessimistically compile all |
| 574 // possible stubs for this closure. | 591 // possible stubs for this closure. |
| 575 FunctionSignature signature = member.computeSignature(compiler); | 592 FunctionSignature signature = member.computeSignature(compiler); |
| 576 Set<Selector> selectors = signature.optionalParametersAreNamed | 593 Set<Selector> selectors = signature.optionalParametersAreNamed |
| 577 ? computeNamedSelectors(signature, member) | 594 ? computeNamedSelectors(signature, member) |
| 578 : computeOptionalSelectors(signature, member); | 595 : computeOptionalSelectors(signature, member); |
| 579 for (Selector selector in selectors) { | 596 for (Selector selector in selectors) { |
| 580 addParameterStub( | 597 addParameterStub(member, selector, defineStub, generatedStubNames); |
| 581 member, selector, defineInstanceMember, generatedStubNames); | |
| 582 } | 598 } |
| 583 } else { | 599 } else { |
| 584 Set<Selector> selectors = compiler.codegenWorld.invokedNames[member.name]; | 600 Set<Selector> selectors = compiler.codegenWorld.invokedNames[member.name]; |
| 585 if (selectors == null) return; | 601 if (selectors == null) return; |
| 586 for (Selector selector in selectors) { | 602 for (Selector selector in selectors) { |
| 587 if (!selector.applies(member, compiler)) continue; | 603 if (!selector.applies(member, compiler)) continue; |
| 588 addParameterStub( | 604 addParameterStub(member, selector, defineStub, generatedStubNames); |
| 589 member, selector, defineInstanceMember, generatedStubNames); | |
| 590 } | 605 } |
| 591 } | 606 } |
| 592 } | 607 } |
| 593 | 608 |
| 594 /** | 609 /** |
| 595 * Compute the set of possible selectors in the presence of named | 610 * Compute the set of possible selectors in the presence of named |
| 596 * parameters. | 611 * parameters. |
| 597 */ | 612 */ |
| 598 Set<Selector> computeNamedSelectors(FunctionSignature signature, | 613 Set<Selector> computeNamedSelectors(FunctionSignature signature, |
| 599 FunctionElement element) { | 614 FunctionElement element) { |
| (...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 666 return member.hasFixedBackendName() | 681 return member.hasFixedBackendName() |
| 667 ? member.fixedBackendName() | 682 ? member.fixedBackendName() |
| 668 : namer.getName(member); | 683 : namer.getName(member); |
| 669 } | 684 } |
| 670 | 685 |
| 671 /** | 686 /** |
| 672 * Documentation wanted -- johnniwinther | 687 * Documentation wanted -- johnniwinther |
| 673 * | 688 * |
| 674 * Invariant: [member] must be a declaration element. | 689 * Invariant: [member] must be a declaration element. |
| 675 */ | 690 */ |
| 676 void addInstanceMember(Element member, | 691 void addInstanceMember(Element member, ClassBuilder builder) { |
| 677 DefineMemberFunction defineInstanceMember) { | |
| 678 assert(invariant(member, member.isDeclaration)); | 692 assert(invariant(member, member.isDeclaration)); |
| 679 // TODO(floitsch): we don't need to deal with members of | 693 // TODO(floitsch): we don't need to deal with members of |
| 680 // uninstantiated classes, that have been overwritten by subclasses. | 694 // uninstantiated classes, that have been overwritten by subclasses. |
| 681 | 695 |
| 682 if (member.isFunction() | 696 if (member.isFunction() |
| 683 || member.isGenerativeConstructorBody() | 697 || member.isGenerativeConstructorBody() |
| 684 || member.isAccessor()) { | 698 || member.isAccessor()) { |
| 685 if (member.isAbstract(compiler)) return; | 699 if (member.isAbstract(compiler)) return; |
| 686 CodeBuffer codeBuffer = compiler.codegenWorld.generatedCode[member]; | 700 js.Expression code = compiler.codegenWorld.generatedCode[member]; |
| 687 if (codeBuffer == null) return; | 701 if (code == null) return; |
| 688 defineInstanceMember(namer.getName(member), codeBuffer); | 702 builder.addProperty(namer.getName(member), code); |
| 689 codeBuffer = compiler.codegenWorld.generatedBailoutCode[member]; | 703 code = compiler.codegenWorld.generatedBailoutCode[member]; |
| 690 if (codeBuffer != null) { | 704 if (code != null) { |
| 691 defineInstanceMember(namer.getBailoutName(member), codeBuffer); | 705 builder.addProperty(namer.getBailoutName(member), code); |
| 692 } | 706 } |
| 693 FunctionElement function = member; | 707 FunctionElement function = member; |
| 694 FunctionSignature parameters = function.computeSignature(compiler); | 708 FunctionSignature parameters = function.computeSignature(compiler); |
| 695 if (!parameters.optionalParameters.isEmpty) { | 709 if (!parameters.optionalParameters.isEmpty) { |
| 696 addParameterStubs(member, defineInstanceMember); | 710 addParameterStubs(member, builder.addProperty); |
| 697 } | 711 } |
| 698 } else if (!member.isField()) { | 712 } else if (!member.isField()) { |
| 699 compiler.internalError('unexpected kind: "${member.kind}"', | 713 compiler.internalError('unexpected kind: "${member.kind}"', |
| 700 element: member); | 714 element: member); |
| 701 } | 715 } |
| 702 emitExtraAccessors(member, defineInstanceMember); | 716 emitExtraAccessors(member, builder); |
| 703 } | 717 } |
| 704 | 718 |
| 705 /** | 719 /** |
| 706 * Documentation wanted -- johnniwinther | 720 * Documentation wanted -- johnniwinther |
| 707 * | 721 * |
| 708 * Invariant: [classElement] must be a declaration element. | 722 * Invariant: [classElement] must be a declaration element. |
| 709 */ | 723 */ |
| 710 void emitInstanceMembers(ClassElement classElement, | 724 void emitInstanceMembers(ClassElement classElement, |
| 711 CodeBuffer buffer, | 725 ClassBuilder builder) { |
| 712 bool emitLeadingComma) { | |
| 713 assert(invariant(classElement, classElement.isDeclaration)); | 726 assert(invariant(classElement, classElement.isDeclaration)); |
| 714 void defineInstanceMember(String name, StringBuffer memberBuffer) { | |
| 715 if (emitLeadingComma) buffer.add(','); | |
| 716 emitLeadingComma = true; | |
| 717 buffer.add('\n'); | |
| 718 buffer.add('$_$name:$_'); | |
| 719 buffer.add(memberBuffer); | |
| 720 } | |
| 721 | |
| 722 JavaScriptBackend backend = compiler.backend; | 727 JavaScriptBackend backend = compiler.backend; |
| 723 if (classElement == backend.objectInterceptorClass) { | 728 if (classElement == backend.objectInterceptorClass) { |
| 724 emitInterceptorMethods(defineInstanceMember); | 729 emitInterceptorMethods(builder); |
| 725 // The ObjectInterceptor does not have any instance methods. | 730 // The ObjectInterceptor does not have any instance methods. |
| 726 return; | 731 return; |
| 727 } | 732 } |
| 728 | 733 |
| 729 classElement.implementation.forEachMember( | 734 classElement.implementation.forEachMember( |
| 730 (ClassElement enclosing, Element member) { | 735 (ClassElement enclosing, Element member) { |
| 731 assert(invariant(classElement, member.isDeclaration)); | 736 assert(invariant(classElement, member.isDeclaration)); |
| 732 if (member.isInstanceMember()) { | 737 if (member.isInstanceMember()) { |
| 733 addInstanceMember(member, defineInstanceMember); | 738 addInstanceMember(member, builder); |
| 734 } | 739 } |
| 735 }, | 740 }, |
| 736 includeBackendMembers: true); | 741 includeBackendMembers: true); |
| 737 | 742 |
| 738 generateIsTestsOn(classElement, (Element other) { | 743 generateIsTestsOn(classElement, (Element other) { |
| 739 String code; | 744 js.Expression code; |
| 740 if (compiler.objectClass == other) return; | 745 if (compiler.objectClass == other) return; |
| 741 if (nativeEmitter.requiresNativeIsCheck(other)) { | 746 if (nativeEmitter.requiresNativeIsCheck(other)) { |
| 742 code = 'function()$_{${_}return true;$_}'; | 747 code = js.fun([], js.block1(js.return_(new js.LiteralBool(true)))); |
| 743 } else { | 748 } else { |
| 744 code = 'true'; | 749 code = new js.LiteralBool(true); |
| 745 } | 750 } |
| 746 CodeBuffer typeTestBuffer = new CodeBuffer(); | 751 builder.addProperty(namer.operatorIs(other), code); |
| 747 typeTestBuffer.add(code); | |
| 748 defineInstanceMember(namer.operatorIs(other), typeTestBuffer); | |
| 749 }); | 752 }); |
| 750 | 753 |
| 751 if (identical(classElement, compiler.objectClass) | 754 if (identical(classElement, compiler.objectClass) |
| 752 && compiler.enabledNoSuchMethod) { | 755 && compiler.enabledNoSuchMethod) { |
| 753 // Emit the noSuchMethod handlers on the Object prototype now, | 756 // Emit the noSuchMethod handlers on the Object prototype now, |
| 754 // so that the code in the dynamicFunction helper can find | 757 // so that the code in the dynamicFunction helper can find |
| 755 // them. Note that this helper is invoked before analyzing the | 758 // them. Note that this helper is invoked before analyzing the |
| 756 // full JS script. | 759 // full JS script. |
| 757 if (!nativeEmitter.handleNoSuchMethod) { | 760 if (!nativeEmitter.handleNoSuchMethod) { |
| 758 emitNoSuchMethodHandlers(defineInstanceMember); | 761 emitNoSuchMethodHandlers(builder.addProperty); |
| 759 } | 762 } |
| 760 } | 763 } |
| 761 } | 764 } |
| 762 | 765 |
| 763 void emitRuntimeClassesAndTests(CodeBuffer buffer) { | 766 void emitRuntimeClassesAndTests(CodeBuffer buffer) { |
| 764 JavaScriptBackend backend = compiler.backend; | 767 JavaScriptBackend backend = compiler.backend; |
| 765 RuntimeTypeInformation rti = backend.rti; | 768 RuntimeTypeInformation rti = backend.rti; |
| 766 | 769 |
| 767 TypeChecks typeChecks = rti.computeRequiredChecks(); | 770 TypeChecks typeChecks = rti.computeRequiredChecks(); |
| 768 | 771 |
| (...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 872 // generate the field getter/setter dynamically. Since this is only | 875 // generate the field getter/setter dynamically. Since this is only |
| 873 // allowed on fields that are in [classElement] we don't need to visit | 876 // allowed on fields that are in [classElement] we don't need to visit |
| 874 // superclasses for non-instantiated classes. | 877 // superclasses for non-instantiated classes. |
| 875 classElement.implementation.forEachInstanceField( | 878 classElement.implementation.forEachInstanceField( |
| 876 visitField, | 879 visitField, |
| 877 includeBackendMembers: true, | 880 includeBackendMembers: true, |
| 878 includeSuperMembers: isInstantiated && !classElement.isNative()); | 881 includeSuperMembers: isInstantiated && !classElement.isNative()); |
| 879 } | 882 } |
| 880 | 883 |
| 881 void generateGetter(Element member, String fieldName, String accessorName, | 884 void generateGetter(Element member, String fieldName, String accessorName, |
| 882 CodeBuffer buffer) { | 885 ClassBuilder builder) { |
| 883 String getterName = namer.getterNameFromAccessorName(accessorName); | 886 String getterName = namer.getterNameFromAccessorName(accessorName); |
| 884 buffer.add("$getterName: function() { return this.$fieldName; }"); | 887 builder.addProperty(getterName, |
| 888 js.fun([], js.block1(js.return_(js.use('this').dot(fieldName))))); |
| 885 } | 889 } |
| 886 | 890 |
| 887 void generateSetter(Element member, String fieldName, String accessorName, | 891 void generateSetter(Element member, String fieldName, String accessorName, |
| 888 CodeBuffer buffer) { | 892 ClassBuilder builder) { |
| 889 String setterName = namer.setterNameFromAccessorName(accessorName); | 893 String setterName = namer.setterNameFromAccessorName(accessorName); |
| 890 buffer.add("$setterName: function(v) { this.$fieldName = v; }"); | 894 builder.addProperty(setterName, |
| 895 js.fun(['v'], |
| 896 js.block1( |
| 897 new js.ExpressionStatement( |
| 898 js.assign(js.use('this').dot(fieldName), js.use('v')))))); |
| 891 } | 899 } |
| 892 | 900 |
| 893 bool canGenerateCheckedSetter(Element member) { | 901 bool canGenerateCheckedSetter(Element member) { |
| 894 DartType type = member.computeType(compiler); | 902 DartType type = member.computeType(compiler); |
| 895 if (type.element.isTypeVariable() | 903 if (type.element.isTypeVariable() |
| 896 || type.element == compiler.dynamicClass | 904 || type.element == compiler.dynamicClass |
| 897 || type.element == compiler.objectClass) { | 905 || type.element == compiler.objectClass) { |
| 898 // TODO(ngeoffray): Support type checks on type parameters. | 906 // TODO(ngeoffray): Support type checks on type parameters. |
| 899 return false; | 907 return false; |
| 900 } | 908 } |
| 901 return true; | 909 return true; |
| 902 } | 910 } |
| 903 | 911 |
| 904 void generateCheckedSetter(Element member, | 912 void generateCheckedSetter(Element member, |
| 905 String fieldName, | 913 String fieldName, |
| 906 String accessorName, | 914 String accessorName, |
| 907 CodeBuffer buffer) { | 915 ClassBuilder builder) { |
| 908 assert(canGenerateCheckedSetter(member)); | 916 assert(canGenerateCheckedSetter(member)); |
| 909 DartType type = member.computeType(compiler); | 917 DartType type = member.computeType(compiler); |
| 910 SourceString helper = compiler.backend.getCheckedModeHelper(type); | 918 SourceString helper = compiler.backend.getCheckedModeHelper(type); |
| 911 FunctionElement helperElement = compiler.findHelper(helper); | 919 FunctionElement helperElement = compiler.findHelper(helper); |
| 912 String helperName = namer.isolateAccess(helperElement); | 920 String helperName = namer.isolateAccess(helperElement); |
| 913 String additionalArgument = ''; | 921 List<js.Expression> arguments = <js.Expression>[js.use('v')]; |
| 914 if (helperElement.computeSignature(compiler).parameterCount != 1) { | 922 if (helperElement.computeSignature(compiler).parameterCount != 1) { |
| 915 additionalArgument = ",$_'${namer.operatorIs(type.element)}'"; | 923 arguments.add(js.string(namer.operatorIs(type.element))); |
| 916 } | 924 } |
| 925 |
| 917 String setterName = namer.setterNameFromAccessorName(accessorName); | 926 String setterName = namer.setterNameFromAccessorName(accessorName); |
| 918 buffer.add("$setterName:${_}function(v)$_{$_" | 927 builder.addProperty(setterName, |
| 919 "this.$fieldName$_=$_$helperName(v$additionalArgument);}"); | 928 js.fun(['v'], |
| 929 js.block1( |
| 930 new js.ExpressionStatement( |
| 931 js.assign( |
| 932 js.use('this').dot(fieldName), |
| 933 js.call(js.use(helperName), arguments)))))); |
| 920 } | 934 } |
| 921 | 935 |
| 922 void emitClassConstructor(ClassElement classElement, CodeBuffer buffer) { | 936 void emitClassConstructor(ClassElement classElement, ClassBuilder builder) { |
| 923 /* Do nothing. */ | 937 /* Do nothing. */ |
| 924 } | 938 } |
| 925 | 939 |
| 926 void emitSuper(String superName, CodeBuffer buffer) { | 940 void emitSuper(String superName, ClassBuilder builder) { |
| 927 /* Do nothing. */ | 941 /* Do nothing. */ |
| 928 } | 942 } |
| 929 | 943 |
| 930 void emitClassFields(ClassElement classElement, | 944 void emitClassFields(ClassElement classElement, |
| 931 CodeBuffer buffer, | 945 ClassBuilder builder, |
| 932 bool emitEndingComma, | |
| 933 { String superClass: "", | 946 { String superClass: "", |
| 934 bool classIsNative: false}) { | 947 bool classIsNative: false}) { |
| 935 bool isFirstField = true; | 948 bool isFirstField = true; |
| 936 bool isAnythingOutput = false; | 949 StringBuffer buffer = new StringBuffer(); |
| 937 if (!classIsNative) { | 950 if (!classIsNative) { |
| 938 buffer.add('"":"$superClass;'); | 951 buffer.add('$superClass;'); |
| 939 isAnythingOutput = true; | |
| 940 } | 952 } |
| 941 visitClassFields(classElement, (Element member, | 953 visitClassFields(classElement, (Element member, |
| 942 String name, | 954 String name, |
| 943 String accessorName, | 955 String accessorName, |
| 944 bool needsGetter, | 956 bool needsGetter, |
| 945 bool needsSetter, | 957 bool needsSetter, |
| 946 bool needsCheckedSetter) { | 958 bool needsCheckedSetter) { |
| 947 // Ignore needsCheckedSetter - that is handled below. | 959 // Ignore needsCheckedSetter - that is handled below. |
| 948 bool needsAccessor = (needsGetter || needsSetter); | 960 bool needsAccessor = (needsGetter || needsSetter); |
| 949 // We need to output the fields for non-native classes so we can auto- | 961 // We need to output the fields for non-native classes so we can auto- |
| 950 // generate the constructor. For native classes there are no | 962 // generate the constructor. For native classes there are no |
| 951 // constructors, so we don't need the fields unless we are generating | 963 // constructors, so we don't need the fields unless we are generating |
| 952 // accessors at runtime. | 964 // accessors at runtime. |
| 953 if (!classIsNative || needsAccessor) { | 965 if (!classIsNative || needsAccessor) { |
| 954 // Emit correct commas. | 966 // Emit correct commas. |
| 955 if (isFirstField) { | 967 if (isFirstField) { |
| 956 isFirstField = false; | 968 isFirstField = false; |
| 957 if (!isAnythingOutput) { | |
| 958 buffer.add('"":"'); | |
| 959 isAnythingOutput = true; | |
| 960 } | |
| 961 } else { | 969 } else { |
| 962 buffer.add(","); | 970 buffer.add(','); |
| 963 } | 971 } |
| 964 int flag = 0; | 972 int flag = 0; |
| 965 if (!needsAccessor) { | 973 if (!needsAccessor) { |
| 966 // Emit field for constructor generation. | 974 // Emit field for constructor generation. |
| 967 assert(!classIsNative); | 975 assert(!classIsNative); |
| 968 buffer.add(name); | 976 buffer.add(name); |
| 969 } else { | 977 } else { |
| 970 // Emit (possibly renaming) field name so we can add accessors at | 978 // Emit (possibly renaming) field name so we can add accessors at |
| 971 // runtime. | 979 // runtime. |
| 972 buffer.add(accessorName); | 980 buffer.add(accessorName); |
| 973 if (name != accessorName) { | 981 if (name != accessorName) { |
| 974 buffer.add(':$name'); | 982 buffer.add(':$name'); |
| 975 // Only the native classes can have renaming accessors. | 983 // Only the native classes can have renaming accessors. |
| 976 assert(classIsNative); | 984 assert(classIsNative); |
| 977 flag = RENAMING_FLAG; | 985 flag = RENAMING_FLAG; |
| 978 } | 986 } |
| 979 } | 987 } |
| 980 if (needsGetter && needsSetter) { | 988 if (needsGetter && needsSetter) { |
| 981 buffer.addCharCode(GETTER_SETTER_CODE + flag); | 989 buffer.addCharCode(GETTER_SETTER_CODE + flag); |
| 982 } else if (needsGetter) { | 990 } else if (needsGetter) { |
| 983 buffer.addCharCode(GETTER_CODE + flag); | 991 buffer.addCharCode(GETTER_CODE + flag); |
| 984 } else if (needsSetter) { | 992 } else if (needsSetter) { |
| 985 buffer.addCharCode(SETTER_CODE + flag); | 993 buffer.addCharCode(SETTER_CODE + flag); |
| 986 } | 994 } |
| 987 } | 995 } |
| 988 }); | 996 }); |
| 989 if (isAnythingOutput) { | 997 |
| 990 buffer.add('"'); | 998 String compactClassData = buffer.toString(); |
| 991 if (emitEndingComma) { | 999 if (compactClassData.length > 0) { |
| 992 buffer.add(','); | 1000 builder.addProperty('', js.string(compactClassData)); |
| 993 } | |
| 994 } | 1001 } |
| 995 } | 1002 } |
| 996 | 1003 |
| 997 /** Each getter/setter must be prefixed with a ",\n ". */ | |
| 998 void emitClassGettersSetters(ClassElement classElement, | 1004 void emitClassGettersSetters(ClassElement classElement, |
| 999 CodeBuffer buffer, | 1005 ClassBuilder builder) { |
| 1000 bool emitLeadingComma) { | |
| 1001 emitComma() { | |
| 1002 if (emitLeadingComma) { | |
| 1003 buffer.add(",\n$_"); | |
| 1004 } else { | |
| 1005 emitLeadingComma = true; | |
| 1006 } | |
| 1007 } | |
| 1008 | 1006 |
| 1009 visitClassFields(classElement, (Element member, | 1007 visitClassFields(classElement, (Element member, |
| 1010 String name, | 1008 String name, |
| 1011 String accessorName, | 1009 String accessorName, |
| 1012 bool needsGetter, | 1010 bool needsGetter, |
| 1013 bool needsSetter, | 1011 bool needsSetter, |
| 1014 bool needsCheckedSetter) { | 1012 bool needsCheckedSetter) { |
| 1015 if (needsCheckedSetter) { | 1013 if (needsCheckedSetter) { |
| 1016 assert(!needsSetter); | 1014 assert(!needsSetter); |
| 1017 emitComma(); | 1015 generateCheckedSetter(member, name, accessorName, builder); |
| 1018 generateCheckedSetter(member, name, accessorName, buffer); | |
| 1019 } | 1016 } |
| 1020 if (!getterAndSetterCanBeImplementedByFieldSpec) { | 1017 if (!getterAndSetterCanBeImplementedByFieldSpec) { |
| 1021 if (needsGetter) { | 1018 if (needsGetter) { |
| 1022 emitComma(); | 1019 generateGetter(member, name, accessorName, builder); |
| 1023 generateGetter(member, name, accessorName, buffer); | |
| 1024 } | 1020 } |
| 1025 if (needsSetter) { | 1021 if (needsSetter) { |
| 1026 emitComma(); | 1022 generateSetter(member, name, accessorName, builder); |
| 1027 generateSetter(member, name, accessorName, buffer); | |
| 1028 } | 1023 } |
| 1029 } | 1024 } |
| 1030 }); | 1025 }); |
| 1031 } | 1026 } |
| 1032 | 1027 |
| 1033 /** | 1028 /** |
| 1034 * Documentation wanted -- johnniwinther | 1029 * Documentation wanted -- johnniwinther |
| 1035 * | 1030 * |
| 1036 * Invariant: [classElement] must be a declaration element. | 1031 * Invariant: [classElement] must be a declaration element. |
| 1037 */ | 1032 */ |
| (...skipping 10 matching lines...) Expand all Loading... |
| 1048 } | 1043 } |
| 1049 | 1044 |
| 1050 needsDefineClass = true; | 1045 needsDefineClass = true; |
| 1051 String className = namer.getName(classElement); | 1046 String className = namer.getName(classElement); |
| 1052 ClassElement superclass = classElement.superclass; | 1047 ClassElement superclass = classElement.superclass; |
| 1053 String superName = ""; | 1048 String superName = ""; |
| 1054 if (superclass != null) { | 1049 if (superclass != null) { |
| 1055 superName = namer.getName(superclass); | 1050 superName = namer.getName(superclass); |
| 1056 } | 1051 } |
| 1057 | 1052 |
| 1058 buffer.add('$classesCollector.$className$_=$_{'); | 1053 ClassBuilder builder = new ClassBuilder(); |
| 1059 emitClassConstructor(classElement, buffer); | 1054 |
| 1060 emitSuper(superName, buffer); | 1055 emitClassConstructor(classElement, builder); |
| 1061 emitClassFields(classElement, buffer, false, | 1056 emitSuper(superName, builder); |
| 1057 emitClassFields(classElement, builder, |
| 1062 superClass: superName, classIsNative: false); | 1058 superClass: superName, classIsNative: false); |
| 1063 // TODO(floitsch): the emitInstanceMember should simply always emit a ',\n'. | 1059 emitClassGettersSetters(classElement, builder); |
| 1064 // That does currently not work because the native classes have a different | 1060 emitInstanceMembers(classElement, builder); |
| 1065 // syntax. | 1061 |
| 1066 emitClassGettersSetters(classElement, buffer, true); | 1062 js.Expression init = |
| 1067 emitInstanceMembers(classElement, buffer, true); | 1063 js.assign( |
| 1068 buffer.add('$n}$N$n'); | 1064 js.use(classesCollector).dot(className), |
| 1065 builder.toObjectInitializer()); |
| 1066 buffer.add(js.prettyPrint(init, compiler)); |
| 1067 buffer.add('$N$n'); |
| 1069 } | 1068 } |
| 1070 | 1069 |
| 1071 bool get getterAndSetterCanBeImplementedByFieldSpec => true; | 1070 bool get getterAndSetterCanBeImplementedByFieldSpec => true; |
| 1072 | 1071 |
| 1073 void emitInterceptorMethods( | 1072 void emitInterceptorMethods(ClassBuilder builder) { |
| 1074 void defineInstanceMember(String name, StringBuffer memberBuffer)) { | |
| 1075 JavaScriptBackend backend = compiler.backend; | 1073 JavaScriptBackend backend = compiler.backend; |
| 1076 // Emit forwarders for the ObjectInterceptor class. We need to | 1074 // Emit forwarders for the ObjectInterceptor class. We need to |
| 1077 // emit all possible sends on intercepted methods. | 1075 // emit all possible sends on intercepted methods. |
| 1078 for (Selector selector in backend.usedInterceptors) { | 1076 for (Selector selector in backend.usedInterceptors) { |
| 1079 | 1077 |
| 1080 List<js.Parameter> parameters = <js.Parameter>[]; | 1078 List<js.Parameter> parameters = <js.Parameter>[]; |
| 1081 List<js.Expression> arguments = <js.Expression>[]; | 1079 List<js.Expression> arguments = <js.Expression>[]; |
| 1082 parameters.add(new js.Parameter('receiver')); | 1080 parameters.add(new js.Parameter('receiver')); |
| 1083 | 1081 |
| 1084 String name; | 1082 String name; |
| (...skipping 13 matching lines...) Expand all Loading... |
| 1098 } | 1096 } |
| 1099 } | 1097 } |
| 1100 js.Fun function = | 1098 js.Fun function = |
| 1101 new js.Fun(parameters, | 1099 new js.Fun(parameters, |
| 1102 new js.Block( | 1100 new js.Block( |
| 1103 <js.Statement>[ | 1101 <js.Statement>[ |
| 1104 new js.Return( | 1102 new js.Return( |
| 1105 new js.VariableUse('receiver') | 1103 new js.VariableUse('receiver') |
| 1106 .dot(name) | 1104 .dot(name) |
| 1107 .callWith(arguments))])); | 1105 .callWith(arguments))])); |
| 1108 | 1106 builder.addProperty(name, function); |
| 1109 CodeBuffer code = new CodeBuffer(); | |
| 1110 code.add(js.prettyPrint(function, compiler)); | |
| 1111 defineInstanceMember(name, code); | |
| 1112 } | 1107 } |
| 1113 } | 1108 } |
| 1114 | 1109 |
| 1115 Collection<Element> getTypedefChecksOn(DartType type) { | 1110 Collection<Element> getTypedefChecksOn(DartType type) { |
| 1116 return checkedTypedefs.filter((TypedefElement typedef) { | 1111 return checkedTypedefs.filter((TypedefElement typedef) { |
| 1117 FunctionType typedefType = | 1112 FunctionType typedefType = |
| 1118 typedef.computeType(compiler).unalias(compiler); | 1113 typedef.computeType(compiler).unalias(compiler); |
| 1119 return compiler.types.isSubtype(type, typedefType); | 1114 return compiler.types.isSubtype(type, typedefType); |
| 1120 }); | 1115 }); |
| 1121 } | 1116 } |
| (...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1267 } | 1262 } |
| 1268 | 1263 |
| 1269 void emitFinishClassesInvocationIfNecessary(CodeBuffer buffer) { | 1264 void emitFinishClassesInvocationIfNecessary(CodeBuffer buffer) { |
| 1270 if (needsDefineClass) { | 1265 if (needsDefineClass) { |
| 1271 buffer.add("$finishClassesName($classesCollector)$N"); | 1266 buffer.add("$finishClassesName($classesCollector)$N"); |
| 1272 // Reset the map. | 1267 // Reset the map. |
| 1273 buffer.add("$classesCollector$_=$_{}$N"); | 1268 buffer.add("$classesCollector$_=$_{}$N"); |
| 1274 } | 1269 } |
| 1275 } | 1270 } |
| 1276 | 1271 |
| 1277 void emitStaticFunctionWithNamer(CodeBuffer buffer, | 1272 void emitStaticFunction(CodeBuffer buffer, |
| 1278 Element element, | 1273 String name, |
| 1279 CodeBuffer functionBuffer, | 1274 js.Expression functionExpression) { |
| 1280 String functionNamer(Element element)) { | 1275 js.Expression assignment = |
| 1281 String functionName = functionNamer(element); | 1276 js.assign(js.use(isolateProperties).dot(name), functionExpression); |
| 1282 buffer.add('$isolateProperties.$functionName$_=$_'); | 1277 buffer.add(js.prettyPrint(assignment, compiler)); |
| 1283 buffer.add(functionBuffer); | |
| 1284 buffer.add('$N$n'); | 1278 buffer.add('$N$n'); |
| 1285 } | 1279 } |
| 1286 | 1280 |
| 1287 void emitStaticFunctions(CodeBuffer buffer) { | 1281 void emitStaticFunctions(CodeBuffer buffer) { |
| 1288 bool isStaticFunction(Element element) => | 1282 bool isStaticFunction(Element element) => |
| 1289 !element.isInstanceMember() && !element.isField(); | 1283 !element.isInstanceMember() && !element.isField(); |
| 1290 | 1284 |
| 1291 Collection<Element> elements = | 1285 Collection<Element> elements = |
| 1292 compiler.codegenWorld.generatedCode.keys.filter(isStaticFunction); | 1286 compiler.codegenWorld.generatedCode.keys.filter(isStaticFunction); |
| 1293 Set<Element> pendingElementsWithBailouts = | 1287 Set<Element> pendingElementsWithBailouts = |
| 1294 new Set<Element>.from( | 1288 new Set<Element>.from( |
| 1295 compiler.codegenWorld.generatedBailoutCode.keys.filter( | 1289 compiler.codegenWorld.generatedBailoutCode.keys.filter( |
| 1296 isStaticFunction)); | 1290 isStaticFunction)); |
| 1297 | 1291 |
| 1298 for (Element element in Elements.sortedByPosition(elements)) { | 1292 for (Element element in Elements.sortedByPosition(elements)) { |
| 1299 CodeBuffer code = compiler.codegenWorld.generatedCode[element]; | 1293 js.Expression code = compiler.codegenWorld.generatedCode[element]; |
| 1300 emitStaticFunctionWithNamer(buffer, element, code, namer.getName); | 1294 emitStaticFunction(buffer, namer.getName(element), code); |
| 1301 CodeBuffer bailoutCode = | 1295 js.Expression bailoutCode = |
| 1302 compiler.codegenWorld.generatedBailoutCode[element]; | 1296 compiler.codegenWorld.generatedBailoutCode[element]; |
| 1303 if (bailoutCode != null) { | 1297 if (bailoutCode != null) { |
| 1304 pendingElementsWithBailouts.remove(element); | 1298 pendingElementsWithBailouts.remove(element); |
| 1305 emitStaticFunctionWithNamer( | 1299 emitStaticFunction(buffer, namer.getBailoutName(element), bailoutCode); |
| 1306 buffer, element, bailoutCode, namer.getBailoutName); | |
| 1307 } | 1300 } |
| 1308 } | 1301 } |
| 1309 | 1302 |
| 1310 // Is it possible the primary function was inlined but the bailout was not? | 1303 // Is it possible the primary function was inlined but the bailout was not? |
| 1311 for (Element element in | 1304 for (Element element in |
| 1312 Elements.sortedByPosition(pendingElementsWithBailouts)) { | 1305 Elements.sortedByPosition(pendingElementsWithBailouts)) { |
| 1313 CodeBuffer bailoutCode = | 1306 CodeBuffer bailoutCode = |
| 1314 compiler.codegenWorld.generatedBailoutCode[element]; | 1307 compiler.codegenWorld.generatedBailoutCode[element]; |
| 1315 emitStaticFunctionWithNamer( | 1308 emitStaticFunction(buffer, namer.getBailoutName(element), bailoutCode); |
| 1316 buffer, element, bailoutCode, namer.getBailoutName); | |
| 1317 } | 1309 } |
| 1318 } | 1310 } |
| 1319 | 1311 |
| 1320 void emitStaticFunctionGetters(CodeBuffer buffer) { | 1312 void emitStaticFunctionGetters(CodeBuffer buffer) { |
| 1321 Set<FunctionElement> functionsNeedingGetter = | 1313 Set<FunctionElement> functionsNeedingGetter = |
| 1322 compiler.codegenWorld.staticFunctionsNeedingGetter; | 1314 compiler.codegenWorld.staticFunctionsNeedingGetter; |
| 1323 for (FunctionElement element in | 1315 for (FunctionElement element in functionsNeedingGetter) { |
| 1324 Elements.sortedByPosition(functionsNeedingGetter)) { | |
| 1325 // The static function does not have the correct name. Since | 1316 // The static function does not have the correct name. Since |
| 1326 // [addParameterStubs] use the name to create its stubs we simply | 1317 // [addParameterStubs] use the name to create its stubs we simply |
| 1327 // create a fake element with the correct name. | 1318 // create a fake element with the correct name. |
| 1328 // Note: the callElement will not have any enclosingElement. | 1319 // Note: the callElement will not have any enclosingElement. |
| 1329 FunctionElement callElement = | 1320 FunctionElement callElement = |
| 1330 new ClosureInvocationElement(namer.closureInvocationSelectorName, | 1321 new ClosureInvocationElement(namer.closureInvocationSelectorName, |
| 1331 element); | 1322 element); |
| 1332 String staticName = namer.getName(element); | 1323 String staticName = namer.getName(element); |
| 1333 String invocationName = namer.instanceMethodName(callElement); | 1324 String invocationName = namer.instanceMethodName(callElement); |
| 1334 String fieldAccess = '$isolateProperties.$staticName'; | 1325 String fieldAccess = '$isolateProperties.$staticName'; |
| 1335 buffer.add("$fieldAccess.$invocationName$_=$_$fieldAccess$N"); | 1326 buffer.add("$fieldAccess.$invocationName$_=$_$fieldAccess$N"); |
| 1336 addParameterStubs(callElement, (String name, CodeBuffer value) { | 1327 |
| 1337 buffer.add('$fieldAccess.$name$_=$_$value$N'); | 1328 addParameterStubs(callElement, (String name, js.Expression value) { |
| 1329 js.Expression assignment = |
| 1330 js.assign( |
| 1331 js.use(isolateProperties).dot(staticName).dot(name), |
| 1332 value); |
| 1333 buffer.add( |
| 1334 js.prettyPrint(new js.ExpressionStatement(assignment), compiler)); |
| 1335 buffer.add('$N'); |
| 1338 }); | 1336 }); |
| 1337 |
| 1339 // If a static function is used as a closure we need to add its name | 1338 // If a static function is used as a closure we need to add its name |
| 1340 // in case it is used in spawnFunction. | 1339 // in case it is used in spawnFunction. |
| 1341 String fieldName = namer.STATIC_CLOSURE_NAME_NAME; | 1340 String fieldName = namer.STATIC_CLOSURE_NAME_NAME; |
| 1342 buffer.add('$fieldAccess.$fieldName$_=$_"$staticName"$N'); | 1341 buffer.add('$fieldAccess.$fieldName$_=$_"$staticName"$N'); |
| 1343 getTypedefChecksOn(element.computeType(compiler)).forEach( | 1342 getTypedefChecksOn(element.computeType(compiler)).forEach( |
| 1344 (Element typedef) { | 1343 (Element typedef) { |
| 1345 String operator = namer.operatorIs(typedef); | 1344 String operator = namer.operatorIs(typedef); |
| 1346 buffer.add('$fieldAccess.$operator$_=${_}true$N'); | 1345 buffer.add('$fieldAccess.$operator$_=${_}true$N'); |
| 1347 } | 1346 } |
| 1348 ); | 1347 ); |
| 1349 } | 1348 } |
| 1350 } | 1349 } |
| 1351 | 1350 |
| 1352 void emitBoundClosureClassHeader(String mangledName, | 1351 void emitBoundClosureClassHeader(String mangledName, |
| 1353 String superName, | 1352 String superName, |
| 1354 List<String> fieldNames, | 1353 List<String> fieldNames, |
| 1355 CodeBuffer buffer) { | 1354 ClassBuilder builder) { |
| 1356 buffer.add('$classesCollector.$mangledName$_=$_' | 1355 builder.addProperty('', |
| 1357 '{"":"$superName;${Strings.join(fieldNames,',')}",'); | 1356 js.string("$superName;${Strings.join(fieldNames,',')}")); |
| 1358 } | 1357 } |
| 1359 | 1358 |
| 1360 /** | 1359 /** |
| 1361 * Documentation wanted -- johnniwinther | 1360 * Documentation wanted -- johnniwinther |
| 1362 * | 1361 * |
| 1363 * Invariant: [member] must be a declaration element. | 1362 * Invariant: [member] must be a declaration element. |
| 1364 */ | 1363 */ |
| 1365 void emitDynamicFunctionGetter(FunctionElement member, | 1364 void emitDynamicFunctionGetter(FunctionElement member, |
| 1366 DefineMemberFunction defineInstanceMember) { | 1365 DefineStubFunction defineStub) { |
| 1367 assert(invariant(member, member.isDeclaration)); | 1366 assert(invariant(member, member.isDeclaration)); |
| 1368 // For every method that has the same name as a property-get we create a | 1367 // For every method that has the same name as a property-get we create a |
| 1369 // getter that returns a bound closure. Say we have a class 'A' with method | 1368 // getter that returns a bound closure. Say we have a class 'A' with method |
| 1370 // 'foo' and somewhere in the code there is a dynamic property get of | 1369 // 'foo' and somewhere in the code there is a dynamic property get of |
| 1371 // 'foo'. Then we generate the following code (in pseudo Dart/JavaScript): | 1370 // 'foo'. Then we generate the following code (in pseudo Dart/JavaScript): |
| 1372 // | 1371 // |
| 1373 // class A { | 1372 // class A { |
| 1374 // foo(x, y, z) { ... } // Original function. | 1373 // foo(x, y, z) { ... } // Original function. |
| 1375 // get foo { return new BoundClosure499(this, "foo"); } | 1374 // get foo { return new BoundClosure499(this, "foo"); } |
| 1376 // } | 1375 // } |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1419 // Create a new closure class. | 1418 // Create a new closure class. |
| 1420 SourceString name = const SourceString("BoundClosure"); | 1419 SourceString name = const SourceString("BoundClosure"); |
| 1421 ClassElement closureClassElement = new ClosureClassElement( | 1420 ClassElement closureClassElement = new ClosureClassElement( |
| 1422 name, compiler, member, member.getCompilationUnit()); | 1421 name, compiler, member, member.getCompilationUnit()); |
| 1423 String mangledName = namer.getName(closureClassElement); | 1422 String mangledName = namer.getName(closureClassElement); |
| 1424 String superName = namer.getName(closureClassElement.superclass); | 1423 String superName = namer.getName(closureClassElement.superclass); |
| 1425 needsClosureClass = true; | 1424 needsClosureClass = true; |
| 1426 | 1425 |
| 1427 // Define the constructor with a name so that Object.toString can | 1426 // Define the constructor with a name so that Object.toString can |
| 1428 // find the class name of the closure class. | 1427 // find the class name of the closure class. |
| 1428 ClassBuilder boundClosureBuilder = new ClassBuilder(); |
| 1429 emitBoundClosureClassHeader( | 1429 emitBoundClosureClassHeader( |
| 1430 mangledName, superName, fieldNames, boundClosureBuffer); | 1430 mangledName, superName, fieldNames, boundClosureBuilder); |
| 1431 // Now add the methods on the closure class. The instance method does not | 1431 // Now add the methods on the closure class. The instance method does not |
| 1432 // have the correct name. Since [addParameterStubs] use the name to create | 1432 // have the correct name. Since [addParameterStubs] use the name to create |
| 1433 // its stubs we simply create a fake element with the correct name. | 1433 // its stubs we simply create a fake element with the correct name. |
| 1434 // Note: the callElement will not have any enclosingElement. | 1434 // Note: the callElement will not have any enclosingElement. |
| 1435 FunctionElement callElement = | 1435 FunctionElement callElement = |
| 1436 new ClosureInvocationElement(namer.closureInvocationSelectorName, | 1436 new ClosureInvocationElement(namer.closureInvocationSelectorName, |
| 1437 member); | 1437 member); |
| 1438 | 1438 |
| 1439 String invocationName = namer.instanceMethodName(callElement); | 1439 String invocationName = namer.instanceMethodName(callElement); |
| 1440 | 1440 |
| (...skipping 10 matching lines...) Expand all Loading... |
| 1451 | 1451 |
| 1452 js.Expression fun = | 1452 js.Expression fun = |
| 1453 new js.Fun(parameters, | 1453 new js.Fun(parameters, |
| 1454 new js.Block( | 1454 new js.Block( |
| 1455 <js.Statement>[ | 1455 <js.Statement>[ |
| 1456 new js.Return( | 1456 new js.Return( |
| 1457 new js.PropertyAccess( | 1457 new js.PropertyAccess( |
| 1458 new js.This().dot(fieldNames[0]), | 1458 new js.This().dot(fieldNames[0]), |
| 1459 new js.This().dot(fieldNames[1])) | 1459 new js.This().dot(fieldNames[1])) |
| 1460 .callWith(arguments))])); | 1460 .callWith(arguments))])); |
| 1461 boundClosureBuilder.addProperty(invocationName, fun); |
| 1461 | 1462 |
| 1462 boundClosureBuffer.add( | 1463 addParameterStubs(callElement, boundClosureBuilder.addProperty); |
| 1463 '$_$invocationName:$_${js.prettyPrint(fun,compiler)}'); | 1464 typedefChecks.forEach((Element typedef) { |
| 1464 | 1465 String operator = namer.operatorIs(typedef); |
| 1465 addParameterStubs(callElement, (String stubName, CodeBuffer memberValue) { | 1466 boundClosureBuilder.addProperty(operator, new js.LiteralBool(true)); |
| 1466 boundClosureBuffer.add(',\n$_$stubName:$_$memberValue'); | |
| 1467 }); | 1467 }); |
| 1468 | 1468 |
| 1469 typedefChecks.forEach((Element typedef) { | 1469 js.Expression init = |
| 1470 String operator = namer.operatorIs(typedef); | 1470 js.assign( |
| 1471 boundClosureBuffer.add(',\n$_$operator$_:${_}true'); | 1471 js.use(classesCollector).dot(mangledName), |
| 1472 }); | 1472 boundClosureBuilder.toObjectInitializer()); |
| 1473 | 1473 boundClosureBuffer.add(js.prettyPrint(init, compiler)); |
| 1474 boundClosureBuffer.add("$n}$N"); | 1474 boundClosureBuffer.add("$N"); |
| 1475 | 1475 |
| 1476 closureClass = namer.isolateAccess(closureClassElement); | 1476 closureClass = namer.isolateAccess(closureClassElement); |
| 1477 | 1477 |
| 1478 // Cache it. | 1478 // Cache it. |
| 1479 if (canBeShared) { | 1479 if (canBeShared) { |
| 1480 cache[parameterCount] = closureClass; | 1480 cache[parameterCount] = closureClass; |
| 1481 } | 1481 } |
| 1482 } | 1482 } |
| 1483 | 1483 |
| 1484 // And finally the getter. | 1484 // And finally the getter. |
| 1485 String getterName = namer.getterName(member.getLibrary(), member.name); | 1485 String getterName = namer.getterName(member.getLibrary(), member.name); |
| 1486 String targetName = namer.instanceMethodName(member); | 1486 String targetName = namer.instanceMethodName(member); |
| 1487 | 1487 |
| 1488 List<js.Parameter> parameters = <js.Parameter>[]; | 1488 List<js.Parameter> parameters = <js.Parameter>[]; |
| 1489 List<js.Expression> arguments = <js.Expression>[]; | 1489 List<js.Expression> arguments = <js.Expression>[]; |
| 1490 arguments.add(new js.This()); | 1490 arguments.add(new js.This()); |
| 1491 arguments.add(new js.LiteralString("'$targetName'")); | 1491 arguments.add(js.string(targetName)); |
| 1492 if (inInterceptor) { | 1492 if (inInterceptor) { |
| 1493 parameters.add(new js.Parameter(extraArg)); | 1493 parameters.add(new js.Parameter(extraArg)); |
| 1494 arguments.add(new js.VariableUse(extraArg)); | 1494 arguments.add(new js.VariableUse(extraArg)); |
| 1495 } | 1495 } |
| 1496 | 1496 |
| 1497 js.Expression getterFunction = | 1497 js.Expression getterFunction = |
| 1498 new js.Fun(parameters, | 1498 new js.Fun(parameters, |
| 1499 new js.Block( | 1499 new js.Block( |
| 1500 <js.Statement>[ | 1500 <js.Statement>[ |
| 1501 new js.Return( | 1501 new js.Return( |
| 1502 new js.New( | 1502 new js.New( |
| 1503 new js.VariableUse(closureClass), | 1503 new js.VariableUse(closureClass), |
| 1504 arguments))])); | 1504 arguments))])); |
| 1505 | 1505 |
| 1506 CodeBuffer getterBuffer = new CodeBuffer(); | 1506 defineStub(getterName, getterFunction); |
| 1507 getterBuffer.add(js.prettyPrint(getterFunction, compiler)); | |
| 1508 defineInstanceMember(getterName, getterBuffer); | |
| 1509 } | 1507 } |
| 1510 | 1508 |
| 1511 /** | 1509 /** |
| 1512 * Documentation wanted -- johnniwinther | 1510 * Documentation wanted -- johnniwinther |
| 1513 * | 1511 * |
| 1514 * Invariant: [member] must be a declaration element. | 1512 * Invariant: [member] must be a declaration element. |
| 1515 */ | 1513 */ |
| 1516 void emitCallStubForGetter(Element member, | 1514 void emitCallStubForGetter(Element member, |
| 1517 Set<Selector> selectors, | 1515 Set<Selector> selectors, |
| 1518 DefineMemberFunction defineInstanceMember) { | 1516 DefineStubFunction defineStub) { |
| 1519 assert(invariant(member, member.isDeclaration)); | 1517 assert(invariant(member, member.isDeclaration)); |
| 1520 LibraryElement memberLibrary = member.getLibrary(); | 1518 LibraryElement memberLibrary = member.getLibrary(); |
| 1521 JavaScriptBackend backend = compiler.backend; | 1519 JavaScriptBackend backend = compiler.backend; |
| 1522 // If the class is an interceptor class, the stub gets the | 1520 // If the class is an interceptor class, the stub gets the |
| 1523 // receiver explicitely and we need to pass it to the getter call. | 1521 // receiver explicitely and we need to pass it to the getter call. |
| 1524 bool isInterceptorClass = | 1522 bool isInterceptorClass = |
| 1525 backend.isInterceptorClass(member.getEnclosingClass()); | 1523 backend.isInterceptorClass(member.getEnclosingClass()); |
| 1526 | 1524 |
| 1527 const String receiverArgumentName = r'$receiver'; | 1525 const String receiverArgumentName = r'$receiver'; |
| 1528 | 1526 |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1564 } | 1562 } |
| 1565 | 1563 |
| 1566 js.Fun function = | 1564 js.Fun function = |
| 1567 new js.Fun(parameters, | 1565 new js.Fun(parameters, |
| 1568 new js.Block( | 1566 new js.Block( |
| 1569 <js.Statement>[ | 1567 <js.Statement>[ |
| 1570 new js.Return( | 1568 new js.Return( |
| 1571 buildGetter().dot(closureCallName) | 1569 buildGetter().dot(closureCallName) |
| 1572 .callWith(arguments))])); | 1570 .callWith(arguments))])); |
| 1573 | 1571 |
| 1574 CodeBuffer getterBuffer = new CodeBuffer(); | 1572 defineStub(invocationName, function); |
| 1575 getterBuffer.add(js.prettyPrint(function, compiler)); | |
| 1576 defineInstanceMember(invocationName, getterBuffer); | |
| 1577 } | 1573 } |
| 1578 } | 1574 } |
| 1579 } | 1575 } |
| 1580 | 1576 |
| 1581 void emitStaticNonFinalFieldInitializations(CodeBuffer buffer) { | 1577 void emitStaticNonFinalFieldInitializations(CodeBuffer buffer) { |
| 1582 ConstantHandler handler = compiler.constantHandler; | 1578 ConstantHandler handler = compiler.constantHandler; |
| 1583 List<VariableElement> staticNonFinalFields = | 1579 List<VariableElement> staticNonFinalFields = |
| 1584 handler.getStaticNonFinalFieldsForEmission(); | 1580 handler.getStaticNonFinalFieldsForEmission(); |
| 1585 for (Element element in staticNonFinalFields) { | 1581 for (Element element in staticNonFinalFields) { |
| 1586 compiler.withCurrentElement(element, () { | 1582 compiler.withCurrentElement(element, () { |
| (...skipping 11 matching lines...) Expand all Loading... |
| 1598 } | 1594 } |
| 1599 | 1595 |
| 1600 void emitLazilyInitializedStaticFields(CodeBuffer buffer) { | 1596 void emitLazilyInitializedStaticFields(CodeBuffer buffer) { |
| 1601 ConstantHandler handler = compiler.constantHandler; | 1597 ConstantHandler handler = compiler.constantHandler; |
| 1602 List<VariableElement> lazyFields = | 1598 List<VariableElement> lazyFields = |
| 1603 handler.getLazilyInitializedFieldsForEmission(); | 1599 handler.getLazilyInitializedFieldsForEmission(); |
| 1604 if (!lazyFields.isEmpty) { | 1600 if (!lazyFields.isEmpty) { |
| 1605 needsLazyInitializer = true; | 1601 needsLazyInitializer = true; |
| 1606 for (VariableElement element in lazyFields) { | 1602 for (VariableElement element in lazyFields) { |
| 1607 assert(compiler.codegenWorld.generatedBailoutCode[element] == null); | 1603 assert(compiler.codegenWorld.generatedBailoutCode[element] == null); |
| 1608 StringBuffer code = compiler.codegenWorld.generatedCode[element]; | 1604 js.Expression code = compiler.codegenWorld.generatedCode[element]; |
| 1609 assert(code != null); | 1605 assert(code != null); |
| 1610 // The code only computes the initial value. We build the lazy-check | 1606 // The code only computes the initial value. We build the lazy-check |
| 1611 // here: | 1607 // here: |
| 1612 // lazyInitializer(prototype, 'name', fieldName, getterName, initial); | 1608 // lazyInitializer(prototype, 'name', fieldName, getterName, initial); |
| 1613 // The name is used for error reporting. The 'initial' must be a | 1609 // The name is used for error reporting. The 'initial' must be a |
| 1614 // closure that constructs the initial value. | 1610 // closure that constructs the initial value. |
| 1615 buffer.add("$lazyInitializerName("); | 1611 buffer.add("$lazyInitializerName("); |
| 1616 buffer.add(isolateProperties); | 1612 buffer.add(isolateProperties); |
| 1617 buffer.add(",$_'"); | 1613 buffer.add(",$_'"); |
| 1618 buffer.add(element.name.slowToString()); | 1614 buffer.add(element.name.slowToString()); |
| 1619 buffer.add("',$_'"); | 1615 buffer.add("',$_'"); |
| 1620 buffer.add(namer.getName(element)); | 1616 buffer.add(namer.getName(element)); |
| 1621 buffer.add("',$_'"); | 1617 buffer.add("',$_'"); |
| 1622 buffer.add(namer.getLazyInitializerName(element)); | 1618 buffer.add(namer.getLazyInitializerName(element)); |
| 1623 buffer.add("',$_"); | 1619 buffer.add("',$_"); |
| 1624 buffer.add(code); | 1620 buffer.add(js.prettyPrint(code, compiler)); |
| 1625 emitLazyInitializedGetter(element, buffer); | 1621 emitLazyInitializedGetter(element, buffer); |
| 1626 buffer.add(")$N"); | 1622 buffer.add(")$N"); |
| 1627 } | 1623 } |
| 1628 } | 1624 } |
| 1629 } | 1625 } |
| 1630 | 1626 |
| 1631 void emitLazyInitializedGetter(VariableElement element, CodeBuffer buffer) { | 1627 void emitLazyInitializedGetter(VariableElement element, CodeBuffer buffer) { |
| 1632 // Nothing to do, the 'lazy' function will create the getter. | 1628 // Nothing to do, the 'lazy' function will create the getter. |
| 1633 } | 1629 } |
| 1634 | 1630 |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1670 return list; | 1666 return list; |
| 1671 }; | 1667 }; |
| 1672 '''); | 1668 '''); |
| 1673 } | 1669 } |
| 1674 | 1670 |
| 1675 /** | 1671 /** |
| 1676 * Documentation wanted -- johnniwinther | 1672 * Documentation wanted -- johnniwinther |
| 1677 * | 1673 * |
| 1678 * Invariant: [member] must be a declaration element. | 1674 * Invariant: [member] must be a declaration element. |
| 1679 */ | 1675 */ |
| 1680 void emitExtraAccessors(Element member, | 1676 void emitExtraAccessors(Element member, ClassBuilder builder) { |
| 1681 DefineMemberFunction defineInstanceMember) { | |
| 1682 assert(invariant(member, member.isDeclaration)); | 1677 assert(invariant(member, member.isDeclaration)); |
| 1683 if (member.isGetter() || member.isField()) { | 1678 if (member.isGetter() || member.isField()) { |
| 1684 Set<Selector> selectors = compiler.codegenWorld.invokedNames[member.name]; | 1679 Set<Selector> selectors = compiler.codegenWorld.invokedNames[member.name]; |
| 1685 if (selectors != null && !selectors.isEmpty) { | 1680 if (selectors != null && !selectors.isEmpty) { |
| 1686 emitCallStubForGetter(member, selectors, defineInstanceMember); | 1681 emitCallStubForGetter(member, selectors, builder.addProperty); |
| 1687 } | 1682 } |
| 1688 } else if (member.isFunction()) { | 1683 } else if (member.isFunction()) { |
| 1689 if (compiler.codegenWorld.hasInvokedGetter(member, compiler)) { | 1684 if (compiler.codegenWorld.hasInvokedGetter(member, compiler)) { |
| 1690 emitDynamicFunctionGetter(member, defineInstanceMember); | 1685 emitDynamicFunctionGetter(member, builder.addProperty); |
| 1691 } | 1686 } |
| 1692 } | 1687 } |
| 1693 } | 1688 } |
| 1694 | 1689 |
| 1695 void emitNoSuchMethodHandlers(DefineMemberFunction defineInstanceMember) { | 1690 void emitNoSuchMethodHandlers(DefineStubFunction defineStub) { |
| 1696 // Do not generate no such method handlers if there is no class. | 1691 // Do not generate no such method handlers if there is no class. |
| 1697 if (compiler.codegenWorld.instantiatedClasses.isEmpty) return; | 1692 if (compiler.codegenWorld.instantiatedClasses.isEmpty) return; |
| 1698 | 1693 |
| 1699 String noSuchMethodName = namer.publicInstanceMethodNameByArity( | 1694 String noSuchMethodName = namer.publicInstanceMethodNameByArity( |
| 1700 Compiler.NO_SUCH_METHOD, Compiler.NO_SUCH_METHOD_ARG_COUNT); | 1695 Compiler.NO_SUCH_METHOD, Compiler.NO_SUCH_METHOD_ARG_COUNT); |
| 1701 | 1696 |
| 1702 Element createInvocationMirrorElement = | 1697 Element createInvocationMirrorElement = |
| 1703 compiler.findHelper(const SourceString("createInvocationMirror")); | 1698 compiler.findHelper(const SourceString("createInvocationMirror")); |
| 1704 String createInvocationMirrorName = | 1699 String createInvocationMirrorName = |
| 1705 namer.getName(createInvocationMirrorElement); | 1700 namer.getName(createInvocationMirrorElement); |
| (...skipping 25 matching lines...) Expand all Loading... |
| 1731 int type = selector.invocationMirrorKind; | 1726 int type = selector.invocationMirrorKind; |
| 1732 String methodName = selector.invocationMirrorMemberName; | 1727 String methodName = selector.invocationMirrorMemberName; |
| 1733 List<js.Parameter> parameters = <js.Parameter>[]; | 1728 List<js.Parameter> parameters = <js.Parameter>[]; |
| 1734 CodeBuffer args = new CodeBuffer(); | 1729 CodeBuffer args = new CodeBuffer(); |
| 1735 for (int i = 0; i < selector.argumentCount; i++) { | 1730 for (int i = 0; i < selector.argumentCount; i++) { |
| 1736 parameters.add(new js.Parameter('\$$i')); | 1731 parameters.add(new js.Parameter('\$$i')); |
| 1737 } | 1732 } |
| 1738 | 1733 |
| 1739 List<js.Expression> argNames = | 1734 List<js.Expression> argNames = |
| 1740 selector.getOrderedNamedArguments().map((SourceString name) => | 1735 selector.getOrderedNamedArguments().map((SourceString name) => |
| 1741 new js.LiteralString('"${name.slowToString()}"')); | 1736 js.string(name.slowToString())); |
| 1742 | 1737 |
| 1743 String internalName = namer.invocationMirrorInternalName(selector); | 1738 String internalName = namer.invocationMirrorInternalName(selector); |
| 1744 | 1739 |
| 1745 String createInvocationMirror = namer.getName( | 1740 String createInvocationMirror = namer.getName( |
| 1746 compiler.createInvocationMirrorElement); | 1741 compiler.createInvocationMirrorElement); |
| 1747 | 1742 |
| 1748 js.Expression expression = | 1743 js.Expression expression = |
| 1749 new js.This() | 1744 new js.This() |
| 1750 .dot(noSuchMethodName) | 1745 .dot(noSuchMethodName) |
| 1751 .callWith( | 1746 .callWith( |
| 1752 <js.Expression>[ | 1747 <js.Expression>[ |
| 1753 new js.VariableUse(namer.CURRENT_ISOLATE) | 1748 new js.VariableUse(namer.CURRENT_ISOLATE) |
| 1754 .dot(createInvocationMirror) | 1749 .dot(createInvocationMirror) |
| 1755 .callWith( | 1750 .callWith( |
| 1756 <js.Expression>[ | 1751 <js.Expression>[ |
| 1757 new js.LiteralString('"$methodName"'), | 1752 js.string(methodName), |
| 1758 new js.LiteralString('"$internalName"'), | 1753 js.string(internalName), |
| 1759 new js.LiteralNumber('$type'), | 1754 new js.LiteralNumber('$type'), |
| 1760 new js.ArrayInitializer.from( | 1755 new js.ArrayInitializer.from( |
| 1761 parameters.map((param) => | 1756 parameters.map((param) => js.use(param.name))), |
| 1762 new js.VariableUse(param.name))), | |
| 1763 new js.ArrayInitializer.from(argNames)])]); | 1757 new js.ArrayInitializer.from(argNames)])]); |
| 1764 js.Expression function = | 1758 js.Expression function = |
| 1765 new js.Fun(parameters, | 1759 new js.Fun(parameters, |
| 1766 new js.Block(<js.Statement>[new js.Return(expression)])); | 1760 new js.Block(<js.Statement>[new js.Return(expression)])); |
| 1767 return function; | 1761 return function; |
| 1768 } | 1762 } |
| 1769 | 1763 |
| 1770 void addNoSuchMethodHandlers(SourceString ignore, Set<Selector> selectors) { | 1764 void addNoSuchMethodHandlers(SourceString ignore, Set<Selector> selectors) { |
| 1771 // Cache the object class and type. | 1765 // Cache the object class and type. |
| 1772 ClassElement objectClass = compiler.objectClass; | 1766 ClassElement objectClass = compiler.objectClass; |
| (...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1850 // bar through inheritance. | 1844 // bar through inheritance. |
| 1851 // | 1845 // |
| 1852 // If we're calling bar on an object of type A we do need the | 1846 // If we're calling bar on an object of type A we do need the |
| 1853 // handler because we may have to call B.noSuchMethod since B | 1847 // handler because we may have to call B.noSuchMethod since B |
| 1854 // does not implement bar. | 1848 // does not implement bar. |
| 1855 Set<ClassElement> holders = noSuchMethodHoldersFor(receiverType); | 1849 Set<ClassElement> holders = noSuchMethodHoldersFor(receiverType); |
| 1856 if (holders.every(hasMatchingMember)) continue; | 1850 if (holders.every(hasMatchingMember)) continue; |
| 1857 String jsName = namer.invocationMirrorInternalName(selector); | 1851 String jsName = namer.invocationMirrorInternalName(selector); |
| 1858 if (!addedJsNames.contains(jsName)) { | 1852 if (!addedJsNames.contains(jsName)) { |
| 1859 js.Expression method = generateMethod(jsName, selector); | 1853 js.Expression method = generateMethod(jsName, selector); |
| 1860 CodeBuffer jsCode = new CodeBuffer(); | 1854 defineStub(jsName, method); |
| 1861 jsCode.add(js.prettyPrint(method, compiler)); | |
| 1862 defineInstanceMember(jsName, jsCode); | |
| 1863 addedJsNames.add(jsName); | 1855 addedJsNames.add(jsName); |
| 1864 } | 1856 } |
| 1865 } | 1857 } |
| 1866 } | 1858 } |
| 1867 | 1859 |
| 1868 compiler.codegenWorld.invokedNames.forEach(addNoSuchMethodHandlers); | 1860 compiler.codegenWorld.invokedNames.forEach(addNoSuchMethodHandlers); |
| 1869 compiler.codegenWorld.invokedGetters.forEach(addNoSuchMethodHandlers); | 1861 compiler.codegenWorld.invokedGetters.forEach(addNoSuchMethodHandlers); |
| 1870 compiler.codegenWorld.invokedSetters.forEach(addNoSuchMethodHandlers); | 1862 compiler.codegenWorld.invokedSetters.forEach(addNoSuchMethodHandlers); |
| 1871 } | 1863 } |
| 1872 | 1864 |
| (...skipping 281 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2154 '${_}new ${namer.isolateName}()$N'); | 2146 '${_}new ${namer.isolateName}()$N'); |
| 2155 | 2147 |
| 2156 nativeEmitter.assembleCode(mainBuffer); | 2148 nativeEmitter.assembleCode(mainBuffer); |
| 2157 emitMain(mainBuffer); | 2149 emitMain(mainBuffer); |
| 2158 mainBuffer.add('function init()$_{\n'); | 2150 mainBuffer.add('function init()$_{\n'); |
| 2159 mainBuffer.add('$isolateProperties$_=$_{}$N'); | 2151 mainBuffer.add('$isolateProperties$_=$_{}$N'); |
| 2160 addDefineClassAndFinishClassFunctionsIfNecessary(mainBuffer); | 2152 addDefineClassAndFinishClassFunctionsIfNecessary(mainBuffer); |
| 2161 addLazyInitializerFunctionIfNecessary(mainBuffer); | 2153 addLazyInitializerFunctionIfNecessary(mainBuffer); |
| 2162 emitFinishIsolateConstructor(mainBuffer); | 2154 emitFinishIsolateConstructor(mainBuffer); |
| 2163 mainBuffer.add('}\n'); | 2155 mainBuffer.add('}\n'); |
| 2164 compiler.assembledCode = mainBuffer.toString(); | 2156 compiler.assembledCode = mainBuffer.getText(); |
| 2165 | 2157 |
| 2166 if (generateSourceMap) { | 2158 if (generateSourceMap) { |
| 2167 SourceFile compiledFile = new SourceFile(null, compiler.assembledCode); | 2159 SourceFile compiledFile = new SourceFile(null, compiler.assembledCode); |
| 2168 String sourceMap = buildSourceMap(mainBuffer, compiledFile); | 2160 String sourceMap = buildSourceMap(mainBuffer, compiledFile); |
| 2169 // TODO(podivilov): We should find a better way to return source maps to | 2161 // TODO(podivilov): We should find a better way to return source maps to |
| 2170 // compiler. Using diagnostic handler for that purpose is a temporary | 2162 // compiler. Using diagnostic handler for that purpose is a temporary |
| 2171 // hack. | 2163 // hack. |
| 2172 compiler.reportDiagnostic( | 2164 compiler.reportDiagnostic( |
| 2173 null, sourceMap, new api.Diagnostic(-1, 'source map')); | 2165 null, sourceMap, new api.Diagnostic(-1, 'source map')); |
| 2174 } | 2166 } |
| 2175 }); | 2167 }); |
| 2176 return compiler.assembledCode; | 2168 return compiler.assembledCode; |
| 2177 } | 2169 } |
| 2178 | 2170 |
| 2179 String buildSourceMap(CodeBuffer buffer, SourceFile compiledFile) { | 2171 String buildSourceMap(CodeBuffer buffer, SourceFile compiledFile) { |
| 2180 SourceMapBuilder sourceMapBuilder = new SourceMapBuilder(); | 2172 SourceMapBuilder sourceMapBuilder = new SourceMapBuilder(); |
| 2181 buffer.forEachSourceLocation(sourceMapBuilder.addMapping); | 2173 buffer.forEachSourceLocation(sourceMapBuilder.addMapping); |
| 2182 return sourceMapBuilder.build(compiledFile); | 2174 return sourceMapBuilder.build(compiledFile); |
| 2183 } | 2175 } |
| 2184 } | 2176 } |
| 2185 | 2177 |
| 2186 typedef void DefineMemberFunction(String invocationName, CodeBuffer definition); | |
| 2187 | |
| 2188 const String GENERATED_BY = """ | 2178 const String GENERATED_BY = """ |
| 2189 // Generated by dart2js, the Dart to JavaScript compiler. | 2179 // Generated by dart2js, the Dart to JavaScript compiler. |
| 2190 """; | 2180 """; |
| 2191 const String HOOKS_API_USAGE = """ | 2181 const String HOOKS_API_USAGE = """ |
| 2192 // The code supports the following hooks: | 2182 // The code supports the following hooks: |
| 2193 // dartPrint(message) - if this function is defined it is called | 2183 // dartPrint(message) - if this function is defined it is called |
| 2194 // instead of the Dart [print] method. | 2184 // instead of the Dart [print] method. |
| 2195 // dartMainRunner(main) - if this function is defined, the Dart [main] | 2185 // dartMainRunner(main) - if this function is defined, the Dart [main] |
| 2196 // method will not be invoked directly. | 2186 // method will not be invoked directly. |
| 2197 // Instead, a closure that will invoke [main] is | 2187 // Instead, a closure that will invoke [main] is |
| 2198 // passed to [dartMainRunner]. | 2188 // passed to [dartMainRunner]. |
| 2199 """; | 2189 """; |
| OLD | NEW |