| 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 * Generates the code for all used classes in the program. Static fields (even | 6 * Generates the code for all used classes in the program. Static fields (even |
| 7 * in classes) are ignored, since they can be treated as non-class elements. | 7 * in classes) are ignored, since they can be treated as non-class elements. |
| 8 * | 8 * |
| 9 * The code for the containing (used) methods must exist in the [:universe:]. | 9 * The code for the containing (used) methods must exist in the [:universe:]. |
| 10 */ | 10 */ |
| 11 class CodeEmitterTask extends CompilerTask { | 11 class CodeEmitterTask extends CompilerTask { |
| 12 static final String INHERIT_FUNCTION = ''' | 12 static final String INHERIT_FUNCTION = ''' |
| 13 function(child, parent) { | 13 function(child, parent) { |
| 14 if (child.prototype.__proto__) { | 14 if (child.prototype.__proto__) { |
| 15 child.prototype.__proto__ = parent.prototype; | 15 child.prototype.__proto__ = parent.prototype; |
| 16 } else { | 16 } else { |
| 17 function tmp() {}; | 17 function tmp() {}; |
| 18 tmp.prototype = parent.prototype; | 18 tmp.prototype = parent.prototype; |
| 19 child.prototype = new tmp(); | 19 child.prototype = new tmp(); |
| 20 child.prototype.constructor = child; | 20 child.prototype.constructor = child; |
| 21 } | 21 } |
| 22 }'''; | 22 }'''; |
| 23 | 23 |
| 24 /** |
| 25 * Code for finding the type name of a JavaScript object. |
| 26 */ |
| 27 static final String TYPE_NAME_OF_FUNCTION = ''' |
| 28 function(obj) { |
| 29 var constructor = obj.constructor; |
| 30 if (typeof(constructor) == 'function') { |
| 31 // The constructor isn't null or undefined at this point. Try |
| 32 // to grab hold of its name. |
| 33 var name = constructor.name; |
| 34 // If the name is a non-empty string, we use that as the type |
| 35 // name of this object. On Firefox, we often get 'Object' as |
| 36 // the constructor name even for more specialized objects so |
| 37 // we have to fall through to the toString() based implementation |
| 38 // below in that case. |
| 39 if (name && typeof(name) == 'string' && name != 'Object') return name; |
| 40 } |
| 41 var string = Object.prototype.toString.call(obj); |
| 42 var name = string.substring(8, string.length - 1); |
| 43 if (name == 'Window') { |
| 44 name = 'DOMWindow'; |
| 45 } else if (name == 'Document') { |
| 46 name = 'HTMLDocument'; |
| 47 } |
| 48 return name; |
| 49 } |
| 50 '''; |
| 51 |
| 52 /** |
| 53 * Code for defining a property in a JavaScript object that will not |
| 54 * be visible through for-in (aka enumerable is false). |
| 55 */ |
| 56 static final String DEF_PROP_FUNCTION = ''' |
| 57 function(obj, prop, value) { |
| 58 Object.defineProperty(obj, prop, |
| 59 {value: value, enumerable: false, writable: true, configurable: true}); |
| 60 }'''; |
| 61 |
| 62 /** |
| 63 * Code for doing the dynamic dispatch on JavaScript prototypes that are not |
| 64 * available at compile-time. Each property of a native Dart class |
| 65 * is registered through this function, which is called with the |
| 66 * following pattern: |
| 67 * |
| 68 * $dynamic('propertyName').prototypeName = // JS code |
| 69 * |
| 70 * What this function does is: |
| 71 * - Creates a map of { prototypeName: JS code }. |
| 72 * - Attaches 'propertyName' to the JS Object prototype that will |
| 73 * intercept at runtime all calls to propertyName. |
| 74 * - Sets the value of 'propertyName' to a function that queries the |
| 75 * map with the prototype of 'this', patches the prototype of |
| 76 * 'this' with the found JS code, and invokes the JS code. |
| 77 * |
| 78 */ |
| 79 String buildDynamicFunctionCode() => ''' |
| 80 function(name) { |
| 81 var f = Object.prototype[name]; |
| 82 if (f && f.methods) return f.methods; |
| 83 |
| 84 var methods = {}; |
| 85 if (f) methods.Object = f; |
| 86 function dynamicBind() { |
| 87 // Find the target method |
| 88 var obj = this; |
| 89 var tag = $typeNameOfName(obj); |
| 90 var method = methods[tag]; |
| 91 if (!method) { |
| 92 var table = $dynamicMetadataName; |
| 93 for (var i = 0; i < table.length; i++) { |
| 94 var entry = table[i]; |
| 95 if (entry.map.hasOwnProperty(tag)) { |
| 96 method = methods[entry.tag]; |
| 97 if (method) break; |
| 98 } |
| 99 } |
| 100 } |
| 101 method = method || methods.Object; |
| 102 var proto = Object.getPrototypeOf(obj); |
| 103 if (!proto.hasOwnProperty(name)) { |
| 104 $defPropName(proto, name, method); |
| 105 } |
| 106 |
| 107 return method.apply(this, Array.prototype.slice.call(arguments)); |
| 108 }; |
| 109 dynamicBind.methods = methods; |
| 110 $defPropName(Object.prototype, name, dynamicBind); |
| 111 return methods; |
| 112 } |
| 113 '''; |
| 114 |
| 115 String buildDynamicMetadataCode() => ''' |
| 116 if (typeof $dynamicMetadataName == 'undefined') $dynamicMetadataName = []; |
| 117 '''; |
| 118 |
| 24 bool addedInheritFunction = false; | 119 bool addedInheritFunction = false; |
| 120 bool addedDynamicFunction = false; |
| 25 final Namer namer; | 121 final Namer namer; |
| 26 | 122 |
| 27 CodeEmitterTask(Compiler compiler) : namer = compiler.namer, super(compiler); | 123 CodeEmitterTask(Compiler compiler) : namer = compiler.namer, super(compiler); |
| 28 String get name() => 'CodeEmitter'; | 124 String get name() => 'CodeEmitter'; |
| 29 | 125 |
| 30 String get inheritsName() => '${compiler.namer.ISOLATE}.\$inherits'; | 126 String get inheritsName() => '${compiler.namer.ISOLATE}.\$inherits'; |
| 127 String get dynamicName() => '${compiler.namer.ISOLATE}.\$dynamic'; |
| 128 String get defPropName() => '${compiler.namer.ISOLATE}.\$defProp'; |
| 129 String get typeNameOfName() => '${compiler.namer.ISOLATE}.\$typeNameOf'; |
| 130 String get dynamicMetadataName() => |
| 131 '${compiler.namer.ISOLATE}.\$dynamicMetatada'; |
| 31 | 132 |
| 32 void addInheritFunctionIfNecessary(StringBuffer buffer) { | 133 void addInheritFunctionIfNecessary(StringBuffer buffer) { |
| 33 if (addedInheritFunction) return; | 134 if (addedInheritFunction) return; |
| 34 addedInheritFunction = true; | 135 addedInheritFunction = true; |
| 35 buffer.add('$inheritsName = '); | 136 buffer.add('$inheritsName = '); |
| 36 buffer.add(INHERIT_FUNCTION); | 137 buffer.add(INHERIT_FUNCTION); |
| 37 buffer.add(';\n'); | 138 buffer.add(';\n'); |
| 38 } | 139 } |
| 39 | 140 |
| 141 void addDynamicFunctionIfNecessary(StringBuffer buffer) { |
| 142 if (addedDynamicFunction) return; |
| 143 addedDynamicFunction = true; |
| 144 buffer.add('$defPropName = '); |
| 145 buffer.add(DEF_PROP_FUNCTION); |
| 146 buffer.add('\n'); |
| 147 buffer.add('$typeNameOfName = '); |
| 148 buffer.add(TYPE_NAME_OF_FUNCTION); |
| 149 buffer.add('\n'); |
| 150 buffer.add('$dynamicName = '); |
| 151 buffer.add(buildDynamicFunctionCode()); |
| 152 buffer.add('\n'); |
| 153 buffer.add(buildDynamicMetadataCode()); |
| 154 buffer.add('\n'); |
| 155 } |
| 156 |
| 40 void addParameterStub(FunctionElement member, | 157 void addParameterStub(FunctionElement member, |
| 41 String prototype, | 158 String attachTo(String invocationName), |
| 42 StringBuffer buffer, | 159 StringBuffer buffer, |
| 43 Selector selector) { | 160 Selector selector) { |
| 44 FunctionParameters parameters = member.computeParameters(compiler); | 161 FunctionParameters parameters = member.computeParameters(compiler); |
| 45 int positionalArgumentCount = selector.positionalArgumentCount; | 162 int positionalArgumentCount = selector.positionalArgumentCount; |
| 46 if (positionalArgumentCount == parameters.parameterCount) { | 163 if (positionalArgumentCount == parameters.parameterCount) { |
| 47 assert(selector.namedArgumentCount == 0); | 164 assert(selector.namedArgumentCount == 0); |
| 48 return; | 165 return; |
| 49 } | 166 } |
| 50 CompileTimeConstantHandler constants = compiler.compileTimeConstantHandler; | 167 CompileTimeConstantHandler constants = compiler.compileTimeConstantHandler; |
| 51 List<SourceString> names = selector.getOrderedNamedArguments(); | 168 List<SourceString> names = selector.getOrderedNamedArguments(); |
| 52 | 169 |
| 53 String invocationName = | 170 String invocationName = |
| 54 namer.instanceMethodInvocationName(member.name, selector); | 171 namer.instanceMethodInvocationName(member.name, selector); |
| 55 buffer.add('$prototype.$invocationName = function('); | 172 buffer.add('${attachTo(invocationName)} = function('); |
| 56 | 173 |
| 57 // The parameters that this stub takes. | 174 // The parameters that this stub takes. |
| 58 List<String> parametersBuffer = new List<String>(selector.argumentCount); | 175 List<String> parametersBuffer = new List<String>(selector.argumentCount); |
| 59 // The arguments that will be passed to the real method. | 176 // The arguments that will be passed to the real method. |
| 60 List<String> argumentsBuffer = new List<String>(parameters.parameterCount); | 177 List<String> argumentsBuffer = new List<String>(parameters.parameterCount); |
| 61 | 178 |
| 62 // We fill the lists depending on the selector. For example, | 179 // We fill the lists depending on the selector. For example, |
| 63 // take method foo: | 180 // take method foo: |
| 64 // foo(a, b, [c, d]); | 181 // foo(a, b, [c, d]); |
| 65 // | 182 // |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 114 } | 231 } |
| 115 count++; | 232 count++; |
| 116 }); | 233 }); |
| 117 | 234 |
| 118 buffer.add('${Strings.join(parametersBuffer, ",")}) {\n'); | 235 buffer.add('${Strings.join(parametersBuffer, ",")}) {\n'); |
| 119 buffer.add(' return this.${namer.getName(member)}'); | 236 buffer.add(' return this.${namer.getName(member)}'); |
| 120 buffer.add('(${Strings.join(argumentsBuffer, ",")})\n}\n'); | 237 buffer.add('(${Strings.join(argumentsBuffer, ",")})\n}\n'); |
| 121 } | 238 } |
| 122 | 239 |
| 123 void addParameterStubs(FunctionElement member, | 240 void addParameterStubs(FunctionElement member, |
| 124 String prototype, | 241 String attachTo(String invocationName), |
| 125 StringBuffer buffer) { | 242 StringBuffer buffer) { |
| 126 Set<Selector> selectors = compiler.universe.invokedNames[member.name]; | 243 Set<Selector> selectors = compiler.universe.invokedNames[member.name]; |
| 127 if (selectors == null) return; | 244 if (selectors == null) return; |
| 128 for (Selector selector in selectors) { | 245 for (Selector selector in selectors) { |
| 129 if (!selector.applies(compiler, member)) continue; | 246 if (!selector.applies(compiler, member)) continue; |
| 130 addParameterStub(member, prototype, buffer, selector); | 247 addParameterStub(member, attachTo, buffer, selector); |
| 131 } | 248 } |
| 132 } | 249 } |
| 133 | 250 |
| 134 void addInstanceMember(Element member, | 251 void addInstanceMember(Element member, |
| 135 String prototype, | 252 String prototype, |
| 136 StringBuffer buffer) { | 253 StringBuffer buffer) { |
| 137 assert(member.isInstanceMember()); | 254 assert(member.isInstanceMember()); |
| 138 if (member.kind === ElementKind.FUNCTION | 255 if (member.kind === ElementKind.FUNCTION |
| 139 || member.kind === ElementKind.GENERATIVE_CONSTRUCTOR_BODY | 256 || member.kind === ElementKind.GENERATIVE_CONSTRUCTOR_BODY |
| 140 || member.kind === ElementKind.GETTER | 257 || member.kind === ElementKind.GETTER |
| 141 || member.kind === ElementKind.SETTER) { | 258 || member.kind === ElementKind.SETTER) { |
| 142 String codeBlock = compiler.universe.generatedCode[member]; | 259 String codeBlock = compiler.universe.generatedCode[member]; |
| 143 if (codeBlock !== null) { | 260 if (codeBlock == null) return; |
| 144 buffer.add('$prototype.${namer.getName(member)} = $codeBlock;\n'); | 261 buffer.add('$prototype.${namer.getName(member)} = $codeBlock;\n'); |
| 145 } | |
| 146 codeBlock = compiler.universe.generatedBailoutCode[member]; | 262 codeBlock = compiler.universe.generatedBailoutCode[member]; |
| 147 if (codeBlock !== null) { | 263 if (codeBlock !== null) { |
| 148 String name = namer.getBailoutName(member); | 264 String name = namer.getBailoutName(member); |
| 149 buffer.add('$prototype.$name = $codeBlock;\n'); | 265 buffer.add('$prototype.$name = $codeBlock;\n'); |
| 150 } | 266 } |
| 151 FunctionElement function = member; | 267 FunctionElement function = member; |
| 152 if (!function.computeParameters(compiler).optionalParameters.isEmpty()) { | 268 if (!function.computeParameters(compiler).optionalParameters.isEmpty()) { |
| 153 addParameterStubs(member, prototype, buffer); | 269 addParameterStubs(member, (name) => '$prototype.$name', buffer); |
| 154 } | 270 } |
| 155 } else if (member.kind === ElementKind.FIELD) { | 271 } else if (member.kind === ElementKind.FIELD) { |
| 156 // TODO(ngeoffray): Have another class generate the code for the | 272 // TODO(ngeoffray): Have another class generate the code for the |
| 157 // fields. | 273 // fields. |
| 158 if (compiler.universe.invokedSetters.contains(member.name)) { | 274 if (compiler.universe.invokedSetters.contains(member.name)) { |
| 159 String setterName = namer.setterName(member.name); | 275 String setterName = namer.setterName(member.name); |
| 160 buffer.add('$prototype.$setterName = function(v){\n' + | 276 buffer.add('$prototype.$setterName = function(v){\n' + |
| 161 ' this.${namer.getName(member)} = v;\n};\n'); | 277 ' this.${namer.getName(member)} = v;\n};\n'); |
| 162 } | 278 } |
| 163 if (compiler.universe.invokedGetters.contains(member.name)) { | 279 if (compiler.universe.invokedGetters.contains(member.name)) { |
| (...skipping 15 matching lines...) Expand all Loading... |
| 179 // TODO(floitsch): make sure there are no name clashes. | 295 // TODO(floitsch): make sure there are no name clashes. |
| 180 String className = namer.getName(classElement); | 296 String className = namer.getName(classElement); |
| 181 | 297 |
| 182 void generateFieldInit(Element member) { | 298 void generateFieldInit(Element member) { |
| 183 if (member.isInstanceMember() && member.kind == ElementKind.FIELD) { | 299 if (member.isInstanceMember() && member.kind == ElementKind.FIELD) { |
| 184 if (!isFirst) argumentsBuffer.add(', '); | 300 if (!isFirst) argumentsBuffer.add(', '); |
| 185 isFirst = false; | 301 isFirst = false; |
| 186 String memberName = namer.instanceFieldName(member.name); | 302 String memberName = namer.instanceFieldName(member.name); |
| 187 argumentsBuffer.add('${className}_$memberName'); | 303 argumentsBuffer.add('${className}_$memberName'); |
| 188 bodyBuffer.add(' this.$memberName = ${className}_$memberName;\n'); | 304 bodyBuffer.add(' this.$memberName = ${className}_$memberName;\n'); |
| 189 } | 305 } |
| 190 } | 306 } |
| 191 | 307 |
| 192 for (Element element in classElement.members) { | 308 for (Element element in classElement.members) { |
| 193 generateFieldInit(element); | 309 generateFieldInit(element); |
| 194 } | 310 } |
| 195 for (Element element in classElement.backendMembers) { | 311 for (Element element in classElement.backendMembers) { |
| 196 generateFieldInit(element); | 312 generateFieldInit(element); |
| 197 } | 313 } |
| 198 | 314 |
| 199 classElement = classElement.superclass; | 315 classElement = classElement.superclass; |
| 200 } while(classElement !== null); | 316 } while(classElement !== null); |
| 201 } | 317 } |
| 202 | 318 |
| 319 void generateNativeClass(ClassElement classElement, StringBuffer buffer) { |
| 320 addDynamicFunctionIfNecessary(buffer); |
| 321 assert(classElement.backendMembers.isEmpty()); |
| 322 String nativeName = classElement.nativeName.stringValue; |
| 323 nativeName = nativeName.substring(2, nativeName.length - 1); |
| 324 for (Element member in classElement.members) { |
| 325 if (member.isInstanceMember()) { |
| 326 String memberName = namer.getName(member); |
| 327 if (member.kind === ElementKind.FUNCTION |
| 328 || member.kind === ElementKind.GENERATIVE_CONSTRUCTOR_BODY |
| 329 || member.kind === ElementKind.GETTER |
| 330 || member.kind === ElementKind.SETTER) { |
| 331 String codeBlock = compiler.universe.generatedCode[member]; |
| 332 if (codeBlock == null) continue; |
| 333 buffer.add( |
| 334 "$dynamicName('$memberName').$nativeName = $codeBlock;\n"); |
| 335 codeBlock = compiler.universe.generatedBailoutCode[member]; |
| 336 if (codeBlock !== null) { |
| 337 String name = namer.getBailoutName(member); |
| 338 buffer.add("$dynamicName('$name').$nativeName = $codeBlock;\n"); |
| 339 } |
| 340 FunctionElement function = member; |
| 341 FunctionParameters parameters = function.computeParameters(compiler); |
| 342 if (!parameters.optionalParameters.isEmpty()) { |
| 343 addParameterStubs( |
| 344 member, (name) => "$dynamicName('$name').$nativeName", buffer); |
| 345 } |
| 346 } else if (member.kind === ElementKind.FIELD) { |
| 347 if (compiler.universe.invokedSetters.contains(member.name)) { |
| 348 String setterName = namer.setterName(member.name); |
| 349 buffer.add( |
| 350 "$dynamicName('$setterName').$nativeName = function(v){\n" + |
| 351 ' this.${member.name} = v;\n};\n'); |
| 352 } |
| 353 if (compiler.universe.invokedGetters.contains(member.name)) { |
| 354 String getterName = namer.getterName(member.name); |
| 355 buffer.add( |
| 356 "$dynamicName('$getterName').$nativeName = function(){\n" + |
| 357 ' return this.${member.name};\n};\n'); |
| 358 } |
| 359 } else { |
| 360 compiler.internalError('unexpected kind: "${member.kind}"', |
| 361 element: member); |
| 362 } |
| 363 } |
| 364 } |
| 365 } |
| 366 |
| 203 void generateClass(ClassElement classElement, | 367 void generateClass(ClassElement classElement, |
| 204 StringBuffer buffer, | 368 StringBuffer buffer, |
| 205 Set<ClassElement> seenClasses) { | 369 Set<ClassElement> seenClasses) { |
| 206 if (seenClasses.contains(classElement)) return; | 370 if (seenClasses.contains(classElement)) return; |
| 207 seenClasses.add(classElement); | 371 seenClasses.add(classElement); |
| 208 ClassElement superclass = classElement.superclass; | 372 ClassElement superclass = classElement.superclass; |
| 209 if (superclass !== null) { | 373 if (superclass !== null) { |
| 210 generateClass(classElement.superclass, buffer, seenClasses); | 374 generateClass(classElement.superclass, buffer, seenClasses); |
| 211 } | 375 } |
| 212 | 376 |
| 377 if (classElement.isNative()) { |
| 378 generateNativeClass(classElement, buffer); |
| 379 return; |
| 380 } |
| 381 |
| 213 String className = namer.isolatePropertyAccess(classElement); | 382 String className = namer.isolatePropertyAccess(classElement); |
| 214 buffer.add('$className = function ${classElement.name}('); | 383 buffer.add('$className = function ${classElement.name}('); |
| 215 StringBuffer bodyBuffer = new StringBuffer(); | 384 StringBuffer bodyBuffer = new StringBuffer(); |
| 216 // If the class is never instantiated we still need to set it up for | 385 // If the class is never instantiated we still need to set it up for |
| 217 // inheritance purposes, but we can leave its JavaScript constructor empty. | 386 // inheritance purposes, but we can leave its JavaScript constructor empty. |
| 218 if (compiler.universe.instantiatedClasses.contains(classElement)) { | 387 if (compiler.universe.instantiatedClasses.contains(classElement)) { |
| 219 generateFieldInits(classElement, buffer, bodyBuffer); | 388 generateFieldInits(classElement, buffer, bodyBuffer); |
| 220 } | 389 } |
| 221 buffer.add(') {\n'); | 390 buffer.add(') {\n'); |
| 222 buffer.add(bodyBuffer); | 391 buffer.add(bodyBuffer); |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 294 // of static functions) and will not have any enclosingElement. | 463 // of static functions) and will not have any enclosingElement. |
| 295 FunctionElement callElement = | 464 FunctionElement callElement = |
| 296 new FunctionElement.from(Namer.CLOSURE_INVOCATION_NAME, | 465 new FunctionElement.from(Namer.CLOSURE_INVOCATION_NAME, |
| 297 element, | 466 element, |
| 298 null); | 467 null); |
| 299 String staticName = namer.isolatePropertyAccess(element); | 468 String staticName = namer.isolatePropertyAccess(element); |
| 300 int parameterCount = element.parameterCount(compiler); | 469 int parameterCount = element.parameterCount(compiler); |
| 301 String invocationName = | 470 String invocationName = |
| 302 namer.instanceMethodName(callElement.name, parameterCount); | 471 namer.instanceMethodName(callElement.name, parameterCount); |
| 303 buffer.add("$staticName.$invocationName = $staticName;\n"); | 472 buffer.add("$staticName.$invocationName = $staticName;\n"); |
| 304 addParameterStubs(callElement, staticName, buffer); | 473 addParameterStubs(callElement, (name) => '$staticName.$name', buffer); |
| 305 } | 474 } |
| 306 } | 475 } |
| 307 | 476 |
| 308 void emitDynamicFunctionGetter(StringBuffer buffer, | 477 void emitDynamicFunctionGetter(StringBuffer buffer, |
| 309 ClassElement enclosingClass, | 478 ClassElement enclosingClass, |
| 310 FunctionElement member) { | 479 FunctionElement member) { |
| 311 // For every method that has the same name as a property-get we create a | 480 // For every method that has the same name as a property-get we create a |
| 312 // getter that returns a bound closure. Say we have a class 'A' with method | 481 // getter that returns a bound closure. Say we have a class 'A' with method |
| 313 // 'foo' and somewhere in the code there is a dynamic property get of | 482 // 'foo' and somewhere in the code there is a dynamic property get of |
| 314 // 'foo'. Then we generate the following code (in pseudo Dart): | 483 // 'foo'. Then we generate the following code (in pseudo Dart): |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 347 namer.instanceMethodName(callElement.name, parameterCount); | 516 namer.instanceMethodName(callElement.name, parameterCount); |
| 348 String targetName = namer.instanceMethodName(member.name, parameterCount); | 517 String targetName = namer.instanceMethodName(member.name, parameterCount); |
| 349 List<String> arguments = new List<String>(parameterCount); | 518 List<String> arguments = new List<String>(parameterCount); |
| 350 for (int i = 0; i < parameterCount; i++) { | 519 for (int i = 0; i < parameterCount; i++) { |
| 351 arguments[i] = "arg$i"; | 520 arguments[i] = "arg$i"; |
| 352 } | 521 } |
| 353 String joinedArgs = Strings.join(arguments, ", "); | 522 String joinedArgs = Strings.join(arguments, ", "); |
| 354 buffer.add("$prototype.$invocationName = function($joinedArgs) {\n"); | 523 buffer.add("$prototype.$invocationName = function($joinedArgs) {\n"); |
| 355 buffer.add(" return this.self.$targetName($joinedArgs);\n"); | 524 buffer.add(" return this.self.$targetName($joinedArgs);\n"); |
| 356 buffer.add("};\n"); | 525 buffer.add("};\n"); |
| 357 addParameterStubs(callElement, prototype, buffer); | 526 addParameterStubs(callElement, (name) => '$prototype.$name', buffer); |
| 358 | 527 |
| 359 // And finally the getter. | 528 // And finally the getter. |
| 360 String enclosingClassAccess = namer.isolatePropertyAccess(enclosingClass); | 529 String enclosingClassAccess = namer.isolatePropertyAccess(enclosingClass); |
| 361 String enclosingClassPrototype = "$enclosingClassAccess.prototype"; | 530 String enclosingClassPrototype = "$enclosingClassAccess.prototype"; |
| 362 String getterName = namer.getterName(member.name); | 531 String getterName = namer.getterName(member.name); |
| 363 String closureClass = namer.isolateAccess(closureClassElement); | 532 String closureClass = namer.isolateAccess(closureClassElement); |
| 364 buffer.add("$enclosingClassPrototype.$getterName = function() {\n"); | 533 buffer.add("$enclosingClassPrototype.$getterName = function() {\n"); |
| 365 buffer.add(" return new $closureClass(this);\n"); | 534 buffer.add(" return new $closureClass(this);\n"); |
| 366 buffer.add("};\n"); | 535 buffer.add("};\n"); |
| 367 } | 536 } |
| (...skipping 163 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 531 emitCallStubForGetters(buffer); | 700 emitCallStubForGetters(buffer); |
| 532 emitStaticFinalFieldInitializations(buffer); | 701 emitStaticFinalFieldInitializations(buffer); |
| 533 buffer.add('var ${namer.CURRENT_ISOLATE} = new ${namer.ISOLATE}();\n'); | 702 buffer.add('var ${namer.CURRENT_ISOLATE} = new ${namer.ISOLATE}();\n'); |
| 534 Element main = compiler.mainApp.find(Compiler.MAIN); | 703 Element main = compiler.mainApp.find(Compiler.MAIN); |
| 535 buffer.add('${namer.isolateAccess(main)}();\n'); | 704 buffer.add('${namer.isolateAccess(main)}();\n'); |
| 536 compiler.assembledCode = buffer.toString(); | 705 compiler.assembledCode = buffer.toString(); |
| 537 }); | 706 }); |
| 538 return compiler.assembledCode; | 707 return compiler.assembledCode; |
| 539 } | 708 } |
| 540 } | 709 } |
| OLD | NEW |