Chromium Code Reviews| 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 /** | 5 /** |
| 6 * A function element that represents a closure call. The signature is copied | 6 * A function element that represents a closure call. The signature is copied |
| 7 * from the given element. | 7 * from the given element. |
| 8 */ | 8 */ |
| 9 class ClosureInvocationElement extends FunctionElement { | 9 class ClosureInvocationElement extends FunctionElement { |
| 10 ClosureInvocationElement(SourceString name, | 10 ClosureInvocationElement(SourceString name, |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 46 String get finishClassesName() | 46 String get finishClassesName() |
| 47 => '${namer.ISOLATE}.\$finishClasses'; | 47 => '${namer.ISOLATE}.\$finishClasses'; |
| 48 String get finishIsolateConstructorName() | 48 String get finishIsolateConstructorName() |
| 49 => '${namer.ISOLATE}.\$finishIsolateConstructor'; | 49 => '${namer.ISOLATE}.\$finishIsolateConstructor'; |
| 50 String get pendingClassesName() | 50 String get pendingClassesName() |
| 51 => '${namer.ISOLATE}.\$pendingClasses'; | 51 => '${namer.ISOLATE}.\$pendingClasses'; |
| 52 String get isolatePropertiesName() | 52 String get isolatePropertiesName() |
| 53 => '${namer.ISOLATE}.${namer.ISOLATE_PROPERTIES}'; | 53 => '${namer.ISOLATE}.${namer.ISOLATE_PROPERTIES}'; |
| 54 | 54 |
| 55 String get defineClassFunction() { | 55 String get defineClassFunction() { |
| 56 // First the class name, then the super class name, followed by the fields | |
| 57 // (in an array) and the members (inside an Object literal). | |
| 58 // The caller can also pass in the constructor as a function if needed. | |
|
ngeoffray
2012/05/07 09:42:30
Who needs that?
floitsch
2012/05/07 12:42:08
This is in preparation for a future CL. The idea i
| |
| 59 // | |
| 56 // Example: | 60 // Example: |
| 57 // defineClass("A", "B", | 61 // defineClass("A", "B", ["x", "y"], { |
| 58 // function(x) { /* The JavaScript constructor. */ | |
| 59 // this.x = x; | |
| 60 // }, { /* The members inside an Object literal. */ | |
| 61 // foo$1: function(y) { | 62 // foo$1: function(y) { |
| 62 // print(this.x + y); | 63 // print(this.x + y); |
| 63 // }, | 64 // }, |
| 64 // bar$2: function(t, v) { | 65 // bar$2: function(t, v) { |
| 65 // this.x = t - v; | 66 // this.x = t - v; |
| 66 // }, | 67 // }, |
| 67 // }); | 68 // }); |
| 68 return """ | 69 return """ |
| 69 function(cls, superclass, constructor, prototype) { | 70 function(cls, superclass, fields, prototype) { |
| 71 var constructor; | |
| 72 if (typeof fields == 'function') { | |
|
ngeoffray
2012/05/07 09:42:30
Since we control the emission, why do we need to s
floitsch
2012/05/07 12:42:08
If you prefer I can remove the code for now. (it's
ngeoffray
2012/05/07 12:54:25
It's fine if you keep it but make sure you'll use
| |
| 73 constructor = fields; | |
| 74 } else { | |
| 75 var str = "(function " + cls + "("; | |
| 76 var body = ""; | |
| 77 for (var i = 0; i < fields.length; i++) { | |
| 78 if (i != 0) str += ", "; | |
| 79 str += fields[i]; | |
| 80 body += "this." + fields[i] + " = " + fields[i] + ";\\n"; | |
| 81 } | |
| 82 str += ") {" + body + "})"; | |
| 83 constructor = eval(str); | |
| 84 } | |
| 70 $isolatePropertiesName[cls] = constructor; | 85 $isolatePropertiesName[cls] = constructor; |
| 71 constructor.prototype = prototype; | 86 constructor.prototype = prototype; |
| 72 if (superclass !== "") { | 87 if (superclass !== "") { |
| 73 $pendingClassesName[cls] = superclass; | 88 $pendingClassesName[cls] = superclass; |
| 74 } | 89 } |
| 75 }"""; | 90 }"""; |
| 76 } | 91 } |
| 77 | 92 |
| 78 String get finishClassesFunction() { | 93 String get finishClassesFunction() { |
| 79 // 'defineClass' does not require the classes to be constructed in order. | 94 // 'defineClass' does not require the classes to be constructed in order. |
| (...skipping 270 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 350 : namer.getName(member); | 365 : namer.getName(member); |
| 351 defineInstanceMember(getterName, "function() { return this.$name; }"); | 366 defineInstanceMember(getterName, "function() { return this.$name; }"); |
| 352 } | 367 } |
| 353 } else { | 368 } else { |
| 354 compiler.internalError('unexpected kind: "${member.kind}"', | 369 compiler.internalError('unexpected kind: "${member.kind}"', |
| 355 element: member); | 370 element: member); |
| 356 } | 371 } |
| 357 emitExtraAccessors(member, defineInstanceMember); | 372 emitExtraAccessors(member, defineInstanceMember); |
| 358 } | 373 } |
| 359 | 374 |
| 360 bool generateFieldInits(ClassElement classElement, | 375 List<String> generateFieldList(ClassElement classElement) { |
| 361 StringBuffer argumentsBuffer, | 376 List<String> result = <String>[]; |
| 362 StringBuffer bodyBuffer) { | 377 void addField(ClassElement enclosingClass, Element member) { |
| 363 bool isFirst = true; | 378 result.add(namer.instanceFieldName(member.getLibrary(), member.name)); |
| 364 void generateFieldInit(ClassElement enclosingClass, Element member) { | |
| 365 // TODO(floitsch): make sure there are no name clashes. | |
| 366 String className = namer.getName(enclosingClass); | |
| 367 if (!isFirst) argumentsBuffer.add(', '); | |
| 368 isFirst = false; | |
| 369 String memberName = namer.instanceFieldName(member.getLibrary(), | |
| 370 member.name); | |
| 371 String parameter; | |
| 372 if (classElement === enclosingClass) { | |
| 373 parameter = memberName; | |
| 374 } else { | |
| 375 parameter = '${className}_$memberName'; | |
| 376 } | |
| 377 argumentsBuffer.add(parameter); | |
| 378 bodyBuffer.add(' this.$memberName = $parameter;\n'); | |
| 379 } | 379 } |
| 380 | 380 |
| 381 classElement.forEachInstanceField(generateFieldInit, | 381 classElement.forEachInstanceField(addField, |
| 382 includeBackendMembers: true, | 382 includeBackendMembers: true, |
| 383 includeSuperMembers: true); | 383 includeSuperMembers: true); |
| 384 return result; | |
| 384 } | 385 } |
| 385 | 386 |
| 386 void generateClass(ClassElement classElement, StringBuffer buffer) { | 387 void generateClass(ClassElement classElement, StringBuffer buffer) { |
| 387 needsDefineClass = true; | 388 needsDefineClass = true; |
| 388 | 389 |
| 389 if (classElement.isNative()) { | 390 if (classElement.isNative()) { |
| 390 nativeEmitter.generateNativeClass(classElement); | 391 nativeEmitter.generateNativeClass(classElement); |
| 391 return; | 392 return; |
| 392 } else { | 393 } else { |
| 393 // TODO(ngeoffray): Instead of switching between buffer, we | 394 // TODO(ngeoffray): Instead of switching between buffer, we |
| 394 // should create code sections, and decide where to emit them at | 395 // should create code sections, and decide where to emit them at |
| 395 // the end. | 396 // the end. |
| 396 buffer = mainBuffer; | 397 buffer = mainBuffer; |
| 397 } | 398 } |
| 398 | 399 |
| 399 String className = namer.getName(classElement); | 400 String className = namer.getName(classElement); |
| 400 ClassElement superclass = classElement.superclass; | 401 ClassElement superclass = classElement.superclass; |
| 401 String superName = ""; | 402 String superName = ""; |
| 402 if (superclass !== null) { | 403 if (superclass !== null) { |
| 403 superName = namer.getName(superclass); | 404 superName = namer.getName(superclass); |
| 404 } | 405 } |
| 405 String constructorName = namer.safeName(classElement.name.slowToString()); | 406 String constructorName = namer.safeName(classElement.name.slowToString()); |
| 406 buffer.add('$defineClassName("$className", "$superName", '); | 407 buffer.add('$defineClassName("$className", "$superName", '); |
| 407 buffer.add('function $constructorName('); | |
| 408 StringBuffer bodyBuffer = new StringBuffer(); | |
| 409 // If the class is never instantiated we still need to set it up for | 408 // If the class is never instantiated we still need to set it up for |
| 410 // inheritance purposes, but we can leave its JavaScript constructor empty. | 409 // inheritance purposes, but we can simplify its JavaScript constructor. |
| 411 if (compiler.universe.instantiatedClasses.contains(classElement)) { | 410 if (!compiler.universe.instantiatedClasses.contains(classElement)) { |
| 412 generateFieldInits(classElement, buffer, bodyBuffer); | 411 buffer.add("[]"); |
| 412 } else { | |
| 413 List<String> fields = generateFieldList(classElement); | |
| 414 buffer.add('['); | |
| 415 for (int i = 0; i < fields.length; i++) { | |
| 416 if (i != 0) buffer.add(", "); | |
| 417 buffer.add('"${fields[i]}"'); | |
| 418 } | |
| 419 buffer.add(']'); | |
| 413 } | 420 } |
| 414 buffer.add(') {\n'); | 421 buffer.add(', {\n'); |
| 415 buffer.add(bodyBuffer); | |
| 416 buffer.add(' }, '); | |
| 417 | |
| 418 buffer.add('{\n'); | |
| 419 | 422 |
| 420 void defineInstanceMember(String name, String value) { | 423 void defineInstanceMember(String name, String value) { |
| 421 buffer.add(' $name: $value,\n'); | 424 buffer.add(' $name: $value,\n'); |
| 422 } | 425 } |
| 423 | 426 |
| 424 classElement.forEachMember(includeBackendMembers: true, | 427 classElement.forEachMember(includeBackendMembers: true, |
| 425 f: (ClassElement enclosing, Element member) { | 428 f: (ClassElement enclosing, Element member) { |
| 426 if (member.isInstanceMember()) { | 429 if (member.isInstanceMember()) { |
| 427 addInstanceMember(member, defineInstanceMember); | 430 addInstanceMember(member, defineInstanceMember); |
| 428 } | 431 } |
| (...skipping 464 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 893 mainBuffer.add('function init() {\n'); | 896 mainBuffer.add('function init() {\n'); |
| 894 mainBuffer.add(' $isolateProperties = {};\n'); | 897 mainBuffer.add(' $isolateProperties = {};\n'); |
| 895 addDefineClassAndFinishClassFunctionsIfNecessary(mainBuffer); | 898 addDefineClassAndFinishClassFunctionsIfNecessary(mainBuffer); |
| 896 emitFinishIsolateConstructor(mainBuffer); | 899 emitFinishIsolateConstructor(mainBuffer); |
| 897 mainBuffer.add('}\n'); | 900 mainBuffer.add('}\n'); |
| 898 compiler.assembledCode = mainBuffer.toString(); | 901 compiler.assembledCode = mainBuffer.toString(); |
| 899 }); | 902 }); |
| 900 return compiler.assembledCode; | 903 return compiler.assembledCode; |
| 901 } | 904 } |
| 902 } | 905 } |
| OLD | NEW |