| 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 /// This class should morph into something that makes it easy to build | 7 /// This class should morph into something that makes it easy to build |
| 8 /// JavaScript representations of libraries, class-sides, and instance-sides. | 8 /// JavaScript representations of libraries, class-sides, and instance-sides. |
| 9 /// Initially, it is just a placeholder for code that is moved from | 9 /// Initially, it is just a placeholder for code that is moved from |
| 10 /// [CodeEmitterTask]. | 10 /// [CodeEmitterTask]. |
| (...skipping 222 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 233 if (!selector.appliesUnnamed(member, compiler.world)) continue; | 233 if (!selector.appliesUnnamed(member, compiler.world)) continue; |
| 234 if (untypedSelectors.add(selector)) { | 234 if (untypedSelectors.add(selector)) { |
| 235 // TODO(ahe): Is the last argument to [addParameterStub] needed? | 235 // TODO(ahe): Is the last argument to [addParameterStub] needed? |
| 236 addParameterStub(member, selector, defineStub, new Set<String>()); | 236 addParameterStub(member, selector, defineStub, new Set<String>()); |
| 237 } | 237 } |
| 238 } | 238 } |
| 239 } | 239 } |
| 240 } | 240 } |
| 241 } | 241 } |
| 242 | 242 |
| 243 /** | |
| 244 * Documentation wanted -- johnniwinther | |
| 245 * | |
| 246 * Invariant: [member] must be a declaration element. | |
| 247 */ | |
| 248 void emitCallStubForGetter(Element member, | |
| 249 Set<Selector> selectors, | |
| 250 AddPropertyFunction addProperty) { | |
| 251 assert(invariant(member, member.isDeclaration)); | |
| 252 LibraryElement memberLibrary = member.library; | |
| 253 // If the method is intercepted, the stub gets the | |
| 254 // receiver explicitely and we need to pass it to the getter call. | |
| 255 bool isInterceptedMethod = backend.isInterceptedMethod(member); | |
| 256 bool isInterceptorClass = | |
| 257 backend.isInterceptorClass(member.enclosingClass); | |
| 258 | |
| 259 const String receiverArgumentName = r'$receiver'; | |
| 260 | |
| 261 jsAst.Expression buildGetter() { | |
| 262 jsAst.Expression receiver = | |
| 263 js(isInterceptorClass ? receiverArgumentName : 'this'); | |
| 264 if (member.isGetter) { | |
| 265 String getterName = namer.getterName(member); | |
| 266 if (isInterceptedMethod) { | |
| 267 return js('this.#(#)', [getterName, receiver]); | |
| 268 } | |
| 269 return js('#.#()', [receiver, getterName]); | |
| 270 } else { | |
| 271 String fieldName = namer.instanceFieldPropertyName(member); | |
| 272 return js('#.#', [receiver, fieldName]); | |
| 273 } | |
| 274 } | |
| 275 | |
| 276 // Two selectors may match but differ only in type. To avoid generating | |
| 277 // identical stubs for each we track untyped selectors which already have | |
| 278 // stubs. | |
| 279 Set<Selector> generatedSelectors = new Set<Selector>(); | |
| 280 for (Selector selector in selectors) { | |
| 281 if (selector.applies(member, compiler.world)) { | |
| 282 selector = selector.asUntyped; | |
| 283 if (generatedSelectors.contains(selector)) continue; | |
| 284 generatedSelectors.add(selector); | |
| 285 | |
| 286 String invocationName = namer.invocationName(selector); | |
| 287 Selector callSelector = new Selector.callClosureFrom(selector); | |
| 288 String closureCallName = namer.invocationName(callSelector); | |
| 289 | |
| 290 List<jsAst.Parameter> parameters = <jsAst.Parameter>[]; | |
| 291 List<jsAst.Expression> arguments = <jsAst.Expression>[]; | |
| 292 if (isInterceptedMethod) { | |
| 293 parameters.add(new jsAst.Parameter(receiverArgumentName)); | |
| 294 } | |
| 295 | |
| 296 for (int i = 0; i < selector.argumentCount; i++) { | |
| 297 String name = 'arg$i'; | |
| 298 parameters.add(new jsAst.Parameter(name)); | |
| 299 arguments.add(js('#', name)); | |
| 300 } | |
| 301 | |
| 302 jsAst.Fun function = js( | |
| 303 'function(#) { return #.#(#); }', | |
| 304 [ parameters, buildGetter(), closureCallName, arguments]); | |
| 305 | |
| 306 compiler.dumpInfoTask.registerElementAst(member, | |
| 307 addProperty(invocationName, function)); | |
| 308 } | |
| 309 } | |
| 310 } | |
| 311 | |
| 312 /** | |
| 313 * Documentation wanted -- johnniwinther | |
| 314 * | |
| 315 * Invariant: [member] must be a declaration element. | |
| 316 */ | |
| 317 void emitExtraAccessors(Element member, ClassBuilder builder) { | |
| 318 assert(invariant(member, member.isDeclaration)); | |
| 319 if (member.isGetter || member.isField) { | |
| 320 Set<Selector> selectors = compiler.codegenWorld.invokedNames[member.name]; | |
| 321 if (selectors != null && !selectors.isEmpty) { | |
| 322 emitCallStubForGetter(member, selectors, builder.addProperty); | |
| 323 } | |
| 324 } | |
| 325 } | |
| 326 | |
| 327 void addMember(Element member, ClassBuilder builder) { | 243 void addMember(Element member, ClassBuilder builder) { |
| 328 assert(invariant(member, member.isDeclaration)); | 244 assert(invariant(member, member.isDeclaration)); |
| 329 | 245 |
| 330 if (member.isField) { | 246 if (member.isField) { |
| 331 addMemberField(member, builder); | 247 addMemberField(member, builder); |
| 332 } else if (member.isFunction || | 248 } else if (member.isFunction || |
| 333 member.isGenerativeConstructorBody || | 249 member.isGenerativeConstructorBody || |
| 334 member.isGenerativeConstructor || | 250 member.isGenerativeConstructor || |
| 335 member.isAccessor) { | 251 member.isAccessor) { |
| 336 addMemberMethod(member, builder); | 252 addMemberMethod(member, builder); |
| 337 } else { | 253 } else { |
| 338 compiler.internalError(member, | 254 compiler.internalError(member, |
| 339 'Unexpected kind: "${member.kind}".'); | 255 'Unexpected kind: "${member.kind}".'); |
| 340 } | 256 } |
| 341 if (member.isInstanceMember) emitExtraAccessors(member, builder); | |
| 342 } | 257 } |
| 343 | 258 |
| 344 void addMemberMethod(FunctionElement member, ClassBuilder builder) { | 259 void addMemberMethod(FunctionElement member, ClassBuilder builder) { |
| 345 MemberInfo info = analyzeMemberMethod(member); | 260 MemberInfo info = analyzeMemberMethod(member); |
| 346 if (info != null) { | 261 if (info != null) { |
| 347 addMemberMethodFromInfo(info, builder); | 262 addMemberMethodFromInfo(info, builder); |
| 348 } | 263 } |
| 349 } | 264 } |
| 350 | 265 |
| 351 MemberInfo analyzeMemberMethod(FunctionElement member) { | 266 MemberInfo analyzeMemberMethod(FunctionElement member) { |
| (...skipping 314 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 666 assert(needsStubs != null); | 581 assert(needsStubs != null); |
| 667 assert(canTearOff != null); | 582 assert(canTearOff != null); |
| 668 assert(isClosure != null); | 583 assert(isClosure != null); |
| 669 assert(tearOffName != null || !canTearOff); | 584 assert(tearOffName != null || !canTearOff); |
| 670 assert(canBeReflected != null); | 585 assert(canBeReflected != null); |
| 671 assert(canBeApplied != null); | 586 assert(canBeApplied != null); |
| 672 assert(hasSuperAlias != null); | 587 assert(hasSuperAlias != null); |
| 673 assert(needStructuredInfo != null); | 588 assert(needStructuredInfo != null); |
| 674 } | 589 } |
| 675 } | 590 } |
| OLD | NEW |