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