| OLD | NEW |
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 part of dart2js.js_emitter; | 5 part of dart2js.js_emitter; |
| 6 | 6 |
| 7 class ClassEmitter extends CodeEmitterHelper { | 7 class ClassEmitter extends CodeEmitterHelper { |
| 8 /** | 8 /** |
| 9 * Documentation wanted -- johnniwinther | 9 * Documentation wanted -- johnniwinther |
| 10 * | 10 * |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 63 (Element member, | 63 (Element member, |
| 64 String name, | 64 String name, |
| 65 String accessorName, | 65 String accessorName, |
| 66 bool needsGetter, | 66 bool needsGetter, |
| 67 bool needsSetter, | 67 bool needsSetter, |
| 68 bool needsCheckedSetter) { | 68 bool needsCheckedSetter) { |
| 69 fields.add(name); | 69 fields.add(name); |
| 70 }); | 70 }); |
| 71 } | 71 } |
| 72 String constructorName = namer.getNameOfClass(classElement); | 72 String constructorName = namer.getNameOfClass(classElement); |
| 73 task.precompiledFunction.add(new jsAst.FunctionDeclaration( | 73 |
| 74 new jsAst.VariableDeclaration(constructorName), | 74 // TODO(sra): Implement placeholders in VariableDeclaration position: |
| 75 js.fun(fields, fields.map( | 75 // task.precompiledFunction.add(js.statement('function #(#) { #; }', |
| 76 (name) => js('this.$name = $name')).toList()))); | 76 // [ constructorName, fields, |
| 77 // fields.map( |
| 78 // (name) => js('this.# = #', [name, name]))])); |
| 79 task.precompiledFunction.add( |
| 80 new jsAst.FunctionDeclaration( |
| 81 new jsAst.VariableDeclaration(constructorName), |
| 82 js('function(#) { #; }', |
| 83 [fields, |
| 84 fields.map((name) => js('this.# = #', [name, name]))]))); |
| 77 if (runtimeName == null) { | 85 if (runtimeName == null) { |
| 78 runtimeName = constructorName; | 86 runtimeName = constructorName; |
| 79 } | 87 } |
| 80 task.precompiledFunction.addAll([ | |
| 81 js('$constructorName.builtin\$cls = "$runtimeName"'), | |
| 82 js.if_('!"name" in $constructorName', | |
| 83 js('$constructorName.name = "$constructorName"')), | |
| 84 js('\$desc=\$collectedClasses.$constructorName'), | |
| 85 js.if_('\$desc instanceof Array', js('\$desc = \$desc[1]')), | |
| 86 js('$constructorName.prototype = \$desc'), | |
| 87 ]); | |
| 88 | 88 |
| 89 task.precompiledConstructorNames.add(js(constructorName)); | 89 task.precompiledFunction.add( |
| 90 js.statement(r'''{ |
| 91 #.builtin$cls = #; |
| 92 if (!"name" in #) |
| 93 #.name = #; |
| 94 $desc=$collectedClasses.#; |
| 95 if ($desc instanceof Array) $desc = $desc[1]; |
| 96 #.prototype = $desc; |
| 97 }''', |
| 98 [ constructorName, js.string(runtimeName), |
| 99 constructorName, |
| 100 constructorName, js.string(constructorName), |
| 101 constructorName, |
| 102 constructorName |
| 103 ])); |
| 104 |
| 105 task.precompiledConstructorNames.add(js('#', constructorName)); |
| 90 } | 106 } |
| 91 | 107 |
| 92 /// Returns `true` if fields added. | 108 /// Returns `true` if fields added. |
| 93 bool emitFields(Element element, | 109 bool emitFields(Element element, |
| 94 ClassBuilder builder, | 110 ClassBuilder builder, |
| 95 String superName, | 111 String superName, |
| 96 { bool classIsNative: false, | 112 { bool classIsNative: false, |
| 97 bool emitStatics: false, | 113 bool emitStatics: false, |
| 98 bool onlyForRti: false }) { | 114 bool onlyForRti: false }) { |
| 99 assert(!emitStatics || !onlyForRti); | 115 assert(!emitStatics || !onlyForRti); |
| (...skipping 195 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 295 ClassBuilder classBuilder, | 311 ClassBuilder classBuilder, |
| 296 ClassBuilder enclosingBuilder) { | 312 ClassBuilder enclosingBuilder) { |
| 297 var metadata = task.metadataEmitter.buildMetadataFunction(classElement); | 313 var metadata = task.metadataEmitter.buildMetadataFunction(classElement); |
| 298 if (metadata != null) { | 314 if (metadata != null) { |
| 299 classBuilder.addProperty("@", metadata); | 315 classBuilder.addProperty("@", metadata); |
| 300 } | 316 } |
| 301 | 317 |
| 302 if (backend.isNeededForReflection(classElement)) { | 318 if (backend.isNeededForReflection(classElement)) { |
| 303 Link typeVars = classElement.typeVariables; | 319 Link typeVars = classElement.typeVariables; |
| 304 Iterable typeVariableProperties = task.typeVariableHandler | 320 Iterable typeVariableProperties = task.typeVariableHandler |
| 305 .typeVariablesOf(classElement).map(js.toExpression); | 321 .typeVariablesOf(classElement).map(js.number); |
| 306 | 322 |
| 307 ClassElement superclass = classElement.superclass; | 323 ClassElement superclass = classElement.superclass; |
| 308 bool hasSuper = superclass != null; | 324 bool hasSuper = superclass != null; |
| 309 if ((!typeVariableProperties.isEmpty && !hasSuper) || | 325 if ((!typeVariableProperties.isEmpty && !hasSuper) || |
| 310 (hasSuper && superclass.typeVariables != typeVars)) { | 326 (hasSuper && superclass.typeVariables != typeVars)) { |
| 311 classBuilder.addProperty('<>', | 327 classBuilder.addProperty('<>', |
| 312 new jsAst.ArrayInitializer.from(typeVariableProperties)); | 328 new jsAst.ArrayInitializer.from(typeVariableProperties)); |
| 313 } | 329 } |
| 314 } | 330 } |
| 315 | 331 |
| (...skipping 197 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 513 } | 529 } |
| 514 | 530 |
| 515 void generateGetter(Element member, String fieldName, String accessorName, | 531 void generateGetter(Element member, String fieldName, String accessorName, |
| 516 ClassBuilder builder) { | 532 ClassBuilder builder) { |
| 517 String getterName = namer.getterNameFromAccessorName(accessorName); | 533 String getterName = namer.getterNameFromAccessorName(accessorName); |
| 518 ClassElement cls = member.getEnclosingClass(); | 534 ClassElement cls = member.getEnclosingClass(); |
| 519 String className = namer.getNameOfClass(cls); | 535 String className = namer.getNameOfClass(cls); |
| 520 String receiver = backend.isInterceptorClass(cls) ? 'receiver' : 'this'; | 536 String receiver = backend.isInterceptorClass(cls) ? 'receiver' : 'this'; |
| 521 List<String> args = backend.isInterceptedMethod(member) ? ['receiver'] : []; | 537 List<String> args = backend.isInterceptedMethod(member) ? ['receiver'] : []; |
| 522 task.precompiledFunction.add( | 538 task.precompiledFunction.add( |
| 523 js('$className.prototype.$getterName = #', | 539 js('#.prototype.# = function(#) { return #.# }', |
| 524 js.fun(args, js.return_(js('$receiver.$fieldName'))))); | 540 [className, getterName, args, receiver, fieldName])); |
| 525 if (backend.isNeededForReflection(member)) { | 541 if (backend.isNeededForReflection(member)) { |
| 526 task.precompiledFunction.add( | 542 task.precompiledFunction.add( |
| 527 js('$className.prototype.$getterName.${namer.reflectableField} = 1')); | 543 js('#.prototype.#.${namer.reflectableField} = 1', |
| 544 [className, getterName])); |
| 528 } | 545 } |
| 529 } | 546 } |
| 530 | 547 |
| 531 void generateSetter(Element member, String fieldName, String accessorName, | 548 void generateSetter(Element member, String fieldName, String accessorName, |
| 532 ClassBuilder builder) { | 549 ClassBuilder builder) { |
| 533 String setterName = namer.setterNameFromAccessorName(accessorName); | 550 String setterName = namer.setterNameFromAccessorName(accessorName); |
| 534 ClassElement cls = member.getEnclosingClass(); | 551 ClassElement cls = member.getEnclosingClass(); |
| 535 String className = namer.getNameOfClass(cls); | 552 String className = namer.getNameOfClass(cls); |
| 536 String receiver = backend.isInterceptorClass(cls) ? 'receiver' : 'this'; | 553 String receiver = backend.isInterceptorClass(cls) ? 'receiver' : 'this'; |
| 537 List<String> args = | 554 List<String> args = backend.isInterceptedMethod(member) ? ['receiver'] : []; |
| 538 backend.isInterceptedMethod(member) ? ['receiver', 'v'] : ['v']; | |
| 539 task.precompiledFunction.add( | 555 task.precompiledFunction.add( |
| 540 js('$className.prototype.$setterName = #', | 556 // TODO: remove 'return'? |
| 541 js.fun(args, js.return_(js('$receiver.$fieldName = v'))))); | 557 js('#.prototype.# = function(#, v) { return #.# = v; }', |
| 558 [className, setterName, args, receiver, fieldName])); |
| 542 if (backend.isNeededForReflection(member)) { | 559 if (backend.isNeededForReflection(member)) { |
| 543 task.precompiledFunction.add( | 560 task.precompiledFunction.add( |
| 544 js('$className.prototype.$setterName.${namer.reflectableField} = 1')); | 561 js('#.prototype.#.${namer.reflectableField} = 1', |
| 562 [className, setterName])); |
| 545 } | 563 } |
| 546 } | 564 } |
| 547 | 565 |
| 548 void generateReflectionDataForFieldGetterOrSetter(Element member, | 566 void generateReflectionDataForFieldGetterOrSetter(Element member, |
| 549 String name, | 567 String name, |
| 550 ClassBuilder builder, | 568 ClassBuilder builder, |
| 551 {bool isGetter}) { | 569 {bool isGetter}) { |
| 552 Selector selector = isGetter | 570 Selector selector = isGetter |
| 553 ? new Selector.getter(member.name, member.getLibrary()) | 571 ? new Selector.getter(member.name, member.getLibrary()) |
| 554 : new Selector.setter(member.name, member.getLibrary()); | 572 : new Selector.setter(member.name, member.getLibrary()); |
| (...skipping 16 matching lines...) Expand all Loading... |
| 571 } | 589 } |
| 572 superclass = superclass.superclass; | 590 superclass = superclass.superclass; |
| 573 } | 591 } |
| 574 } | 592 } |
| 575 | 593 |
| 576 void emitTypeVariableReader(ClassElement cls, | 594 void emitTypeVariableReader(ClassElement cls, |
| 577 ClassBuilder builder, | 595 ClassBuilder builder, |
| 578 TypeVariableElement element) { | 596 TypeVariableElement element) { |
| 579 String name = namer.readTypeVariableName(element); | 597 String name = namer.readTypeVariableName(element); |
| 580 jsAst.Expression index = | 598 jsAst.Expression index = |
| 581 js.toExpression(RuntimeTypes.getTypeVariableIndex(element)); | 599 js.number(RuntimeTypes.getTypeVariableIndex(element)); |
| 582 jsAst.Expression computeTypeVariable; | 600 jsAst.Expression computeTypeVariable; |
| 583 | 601 |
| 584 Substitution substitution = | 602 Substitution substitution = |
| 585 backend.rti.computeSubstitution( | 603 backend.rti.computeSubstitution( |
| 586 cls, element.enclosingElement, alwaysGenerateFunction: true); | 604 cls, element.enclosingElement, alwaysGenerateFunction: true); |
| 587 if (substitution != null) { | 605 if (substitution != null) { |
| 588 jsAst.Expression typeArguments = | 606 jsAst.Expression typeArguments = |
| 589 substitution.getCode(backend.rti, true)['apply']( | 607 js(r'#.apply(null, this.$builtinTypeInfo)', |
| 590 ['null', r'this.$builtinTypeInfo']); | 608 substitution.getCode(backend.rti, true)); |
| 591 computeTypeVariable = typeArguments[index]; | 609 computeTypeVariable = js('#[#]', [typeArguments, index]); |
| 592 } else { | 610 } else { |
| 593 // TODO(ahe): These can be generated dynamically. | 611 // TODO(ahe): These can be generated dynamically. |
| 594 computeTypeVariable = | 612 computeTypeVariable = |
| 595 js(r'this.$builtinTypeInfo && this.$builtinTypeInfo[#]', index); | 613 js(r'this.$builtinTypeInfo && this.$builtinTypeInfo[#]', index); |
| 596 } | 614 } |
| 597 jsAst.Expression convertRtiToRuntimeType = | 615 jsAst.Expression convertRtiToRuntimeType = |
| 598 namer.elementAccess(compiler.findHelper('convertRtiToRuntimeType')); | 616 namer.elementAccess(compiler.findHelper('convertRtiToRuntimeType')); |
| 599 builder.addProperty( | 617 builder.addProperty(name, |
| 600 name, js.fun( | 618 js('function () { return #(#) }', |
| 601 [], [js.return_(convertRtiToRuntimeType(computeTypeVariable))])); | 619 [convertRtiToRuntimeType, computeTypeVariable])); |
| 602 } | 620 } |
| 603 } | 621 } |
| OLD | NEW |