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