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 class NativeEmitter { | 5 class NativeEmitter { |
| 6 | 6 |
| 7 Compiler compiler; | 7 Compiler compiler; |
| 8 bool addedDynamicFunction = false; | 8 bool addedDynamicFunction = false; |
| 9 bool addedTypeNameOfFunction = false; | 9 bool addedTypeNameOfFunction = false; |
| 10 bool addedDefPropFunction = false; | 10 bool addedDefPropFunction = false; |
| (...skipping 189 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 200 buffer.add('\n'); | 200 buffer.add('\n'); |
| 201 } | 201 } |
| 202 | 202 |
| 203 void addNativePropertyIfNecessary(StringBuffer buffer) { | 203 void addNativePropertyIfNecessary(StringBuffer buffer) { |
| 204 if (addedNativeProperty) return; | 204 if (addedNativeProperty) return; |
| 205 addedNativeProperty = true; | 205 addedNativeProperty = true; |
| 206 buffer.add(buildNativePropertyCode()); | 206 buffer.add(buildNativePropertyCode()); |
| 207 buffer.add('\n'); | 207 buffer.add('\n'); |
| 208 } | 208 } |
| 209 | 209 |
| 210 void generateNativeLiteral( | |
|
kasperl
2012/03/02 13:11:33
I think we usually put the first parameter on the
ngeoffray
2012/03/05 08:28:00
Done.
| |
| 211 ClassElement classElement, StringBuffer buffer) { | |
| 212 String nativeCode = classElement.nativeName.slowToString(); | |
|
kasperl
2012/03/02 13:11:33
String quotedNative = ...;
String nativeCode = quo
ngeoffray
2012/03/05 08:28:00
Done.
| |
| 213 nativeCode = nativeCode.substring(2, nativeCode.length - 1); | |
| 214 String className = compiler.namer.getName(classElement); | |
| 215 buffer.add(className); | |
| 216 buffer.add(' = '); | |
| 217 buffer.add(nativeCode); | |
| 218 buffer.add(';\n'); | |
| 219 | |
| 220 String attachTo(name) => "$className.$name"; | |
| 221 | |
| 222 for (Element member in classElement.members) { | |
| 223 if (member.isInstanceMember()) { | |
| 224 compiler.emitter.addInstanceMember( | |
| 225 member, attachTo, buffer, isNative: true); | |
| 226 } | |
| 227 } | |
| 228 } | |
| 229 | |
| 230 bool isNativeLiteral(String nativeName) { | |
| 231 return nativeName[1] === '='; | |
| 232 } | |
| 233 | |
| 234 bool isNativeGlobal(String nativeName) { | |
| 235 return nativeName[1] === '@'; | |
| 236 } | |
| 210 | 237 |
| 211 void generateNativeClass(ClassElement classElement, StringBuffer buffer) { | 238 void generateNativeClass(ClassElement classElement, StringBuffer buffer) { |
| 212 nativeClasses.add(classElement); | 239 nativeClasses.add(classElement); |
| 213 | 240 |
| 214 assert(classElement.backendMembers.isEmpty()); | 241 assert(classElement.backendMembers.isEmpty()); |
| 215 String nativeName = classElement.nativeName.slowToString(); | 242 String nativeName = classElement.nativeName.slowToString(); |
| 216 if (nativeName[1] === '@') { | 243 if (isNativeLiteral(nativeName)) { |
| 244 generateNativeLiteral(classElement, buffer); | |
| 245 return; | |
| 246 } else if (isNativeGlobal(nativeName)) { | |
|
kasperl
2012/03/02 13:11:33
I would probably not make this an else if because
ngeoffray
2012/03/05 08:28:00
Done.
| |
| 217 // Global object, just be like the other types for now. | 247 // Global object, just be like the other types for now. |
| 218 nativeName = nativeName.substring(3, nativeName.length - 1); | 248 nativeName = nativeName.substring(3, nativeName.length - 1); |
| 219 } else { | 249 } else { |
| 220 nativeName = nativeName.substring(2, nativeName.length - 1); | 250 nativeName = nativeName.substring(2, nativeName.length - 1); |
| 221 } | 251 } |
| 222 bool hasUsedSelectors = false; | 252 bool hasUsedSelectors = false; |
| 223 | 253 |
| 224 String attachTo(name) => "$dynamicName('$name').$nativeName"; | 254 String attachTo(String name) { |
| 255 hasUsedSelectors = true; | |
| 256 addDynamicFunctionIfNecessary(buffer); | |
| 257 return "$dynamicName('$name').$nativeName"; | |
| 258 } | |
| 225 | 259 |
| 226 for (Element member in classElement.members) { | 260 for (Element member in classElement.members) { |
| 227 if (member.isInstanceMember()) { | 261 if (member.isInstanceMember()) { |
| 228 String memberName = compiler.namer.getName(member); | 262 compiler.emitter.addInstanceMember( |
| 229 if (member.kind === ElementKind.FUNCTION | 263 member, attachTo, buffer, isNative: true); |
| 230 || member.kind === ElementKind.GENERATIVE_CONSTRUCTOR_BODY | |
| 231 || member.kind === ElementKind.GETTER | |
| 232 || member.kind === ElementKind.SETTER) { | |
| 233 String codeBlock = compiler.universe.generatedCode[member]; | |
| 234 if (codeBlock == null) continue; | |
| 235 addDynamicFunctionIfNecessary(buffer); | |
| 236 hasUsedSelectors = true; | |
| 237 buffer.add( | |
| 238 "$dynamicName('$memberName').$nativeName = $codeBlock;\n"); | |
| 239 codeBlock = compiler.universe.generatedBailoutCode[member]; | |
| 240 if (codeBlock !== null) { | |
| 241 String name = compiler.namer.getBailoutName(member); | |
| 242 buffer.add("$dynamicName('$name').$nativeName = $codeBlock;\n"); | |
| 243 } | |
| 244 FunctionElement function = member; | |
| 245 FunctionParameters parameters = function.computeParameters(compiler); | |
| 246 if (!parameters.optionalParameters.isEmpty()) { | |
| 247 compiler.emitter.addParameterStubs( | |
| 248 member, attachTo, buffer, isNative: true); | |
| 249 } | |
| 250 } else if (member.kind === ElementKind.FIELD) { | |
| 251 if (compiler.universe.invokedSetters.contains(member.name)) { | |
| 252 addDynamicFunctionIfNecessary(buffer); | |
| 253 hasUsedSelectors = true; | |
| 254 String setterName = compiler.namer.setterName(member.name); | |
| 255 buffer.add( | |
| 256 "$dynamicName('$setterName').$nativeName = function(v){\n" + | |
| 257 ' this.${member.name.slowToString()} = v;\n};\n'); | |
| 258 } | |
| 259 if (compiler.universe.invokedGetters.contains(member.name)) { | |
| 260 addDynamicFunctionIfNecessary(buffer); | |
| 261 hasUsedSelectors = true; | |
| 262 String getterName = compiler.namer.getterName(member.name); | |
| 263 buffer.add( | |
| 264 "$dynamicName('$getterName').$nativeName = function(){\n" + | |
| 265 ' return this.${member.name.slowToString()};\n};\n'); | |
| 266 } | |
| 267 } else { | |
| 268 compiler.internalError('unexpected kind: "${member.kind}"', | |
| 269 element: member); | |
| 270 } | |
| 271 if (member.kind == ElementKind.GETTER | |
| 272 || member.kind == ElementKind.FIELD) { | |
| 273 Set<Selector> selectors = compiler.universe.invokedNames[member.name]; | |
| 274 if (selectors !== null && !selectors.isEmpty()) { | |
| 275 emitCallStubForGetter(buffer, attachTo, member, selectors); | |
| 276 } | |
| 277 } else if (member.kind == ElementKind.FUNCTION) { | |
| 278 if (compiler.universe.invokedGetters.contains(member.name)) { | |
| 279 emitDynamicFunctionGetter(buffer, attachTo, member); | |
| 280 } | |
| 281 } | |
| 282 } | 264 } |
| 283 } | 265 } |
| 284 | 266 |
| 285 addNativePropertyIfNecessary(buffer); | 267 addNativePropertyIfNecessary(buffer); |
| 286 // Create an object that contains the is checks properties. The | 268 // Create an object that contains the is checks properties. The |
| 287 // object will be used when entering [buildDynamicIsCheckCode]. | 269 // object will be used when entering [buildDynamicIsCheckCode]. |
| 288 buffer.add('${compiler.namer.ISOLATE}.prototype.native.$nativeName = { '); | 270 buffer.add('${compiler.namer.ISOLATE}.prototype.native.$nativeName = { '); |
| 289 List<String> tests = <String>[]; | 271 List<String> tests = <String>[]; |
| 290 | 272 |
| 291 ClassElement objectClass = | 273 ClassElement objectClass = |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 327 // For example, for the following Dart method: | 309 // For example, for the following Dart method: |
| 328 // foo([x, y, z]); | 310 // foo([x, y, z]); |
| 329 // The call: | 311 // The call: |
| 330 // foo(y: 1) | 312 // foo(y: 1) |
| 331 // must be turned into a JS call to: | 313 // must be turned into a JS call to: |
| 332 // foo(null, y). | 314 // foo(null, y). |
| 333 | 315 |
| 334 List<String> nativeArgumentsBuffer = argumentsBuffer.getRange( | 316 List<String> nativeArgumentsBuffer = argumentsBuffer.getRange( |
| 335 0, indexOfLastOptionalArgumentInParameters + 1); | 317 0, indexOfLastOptionalArgumentInParameters + 1); |
| 336 | 318 |
| 319 ClassElement classElement = member.enclosingElement; | |
| 320 String nativeName = classElement.nativeName.slowToString(); | |
| 337 String nativeArguments = Strings.join(nativeArgumentsBuffer, ","); | 321 String nativeArguments = Strings.join(nativeArgumentsBuffer, ","); |
| 338 | 322 |
| 323 if (isNativeLiteral(nativeName)) { | |
| 324 // If it's the native literal, we know there is no subclass, so | |
| 325 // we can call the method directly. | |
| 326 buffer.add(' return this.${member.name.slowToString()}'); | |
| 327 buffer.add('($nativeArguments)'); | |
| 328 return; | |
| 329 } | |
| 330 | |
| 339 buffer.add(' if (Object.getPrototypeOf(this).hasOwnProperty('); | 331 buffer.add(' if (Object.getPrototypeOf(this).hasOwnProperty('); |
| 340 buffer.add("'$invocationName')) {\n"); | 332 buffer.add("'$invocationName')) {\n"); |
| 341 buffer.add(' return this.${member.name.slowToString()}'); | 333 buffer.add(' return this.${member.name.slowToString()}'); |
| 342 buffer.add('($nativeArguments)'); | 334 buffer.add('($nativeArguments)'); |
| 343 buffer.add('\n }\n'); | 335 buffer.add('\n }\n'); |
| 344 buffer.add(' return Object.prototype.$invocationName.call(this'); | 336 buffer.add(' return Object.prototype.$invocationName.call(this'); |
| 345 buffer.add(stubParameters == '' ? '' : ', $stubParameters'); | 337 buffer.add(stubParameters == '' ? '' : ', $stubParameters'); |
| 346 buffer.add(');'); | 338 buffer.add(');'); |
| 347 } | 339 } |
| 348 | 340 |
| (...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 478 entries.add("\n ['$clsName', ${tagDefns[clsName]}]"); | 470 entries.add("\n ['$clsName', ${tagDefns[clsName]}]"); |
| 479 } | 471 } |
| 480 buffer.add(Strings.join(entries, ',')); | 472 buffer.add(Strings.join(entries, ',')); |
| 481 buffer.add('];\n'); | 473 buffer.add('];\n'); |
| 482 buffer.add('$dynamicSetMetadataName(table);\n'); | 474 buffer.add('$dynamicSetMetadataName(table);\n'); |
| 483 | 475 |
| 484 buffer.add('})();\n'); | 476 buffer.add('})();\n'); |
| 485 } | 477 } |
| 486 } | 478 } |
| 487 } | 479 } |
| OLD | NEW |