Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(3)

Side by Side Diff: sdk/lib/_internal/compiler/implementation/js_emitter/container_builder.dart

Issue 266913017: Convert property methods into getters. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Rebased Created 6 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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 98 matching lines...) Expand 10 before | Expand all | Expand 10 after
109 indexOfLastOptionalArgumentInParameters = count; 109 indexOfLastOptionalArgumentInParameters = count;
110 } 110 }
111 argumentsBuffer[count] = task.constantReference(value); 111 argumentsBuffer[count] = task.constantReference(value);
112 } 112 }
113 } 113 }
114 } 114 }
115 count++; 115 count++;
116 }); 116 });
117 117
118 var body; // List or jsAst.Statement. 118 var body; // List or jsAst.Statement.
119 if (member.hasFixedBackendName()) { 119 if (member.hasFixedBackendName) {
120 body = task.nativeEmitter.generateParameterStubStatements( 120 body = task.nativeEmitter.generateParameterStubStatements(
121 member, isInterceptedMethod, invocationName, 121 member, isInterceptedMethod, invocationName,
122 parametersBuffer, argumentsBuffer, 122 parametersBuffer, argumentsBuffer,
123 indexOfLastOptionalArgumentInParameters); 123 indexOfLastOptionalArgumentInParameters);
124 } else if (member.isInstanceMember()) { 124 } else if (member.isInstanceMember) {
125 if (needsSuperGetter(member)) { 125 if (needsSuperGetter(member)) {
126 ClassElement superClass = member.getEnclosingClass(); 126 ClassElement superClass = member.enclosingClass;
127 String methodName = namer.getNameOfInstanceMember(member); 127 String methodName = namer.getNameOfInstanceMember(member);
128 // When redirecting, we must ensure that we don't end up in a subclass. 128 // When redirecting, we must ensure that we don't end up in a subclass.
129 // We thus can't just invoke `this.foo$1.call(filledInArguments)`. 129 // We thus can't just invoke `this.foo$1.call(filledInArguments)`.
130 // Instead we need to call the statically resolved target. 130 // Instead we need to call the statically resolved target.
131 // `<class>.prototype.bar$1.call(this, argument0, ...)`. 131 // `<class>.prototype.bar$1.call(this, argument0, ...)`.
132 body = js.statement( 132 body = js.statement(
133 'return #.prototype.#.call(this, #);', 133 'return #.prototype.#.call(this, #);',
134 [backend.namer.elementAccess(superClass), methodName, 134 [backend.namer.elementAccess(superClass), methodName,
135 argumentsBuffer]); 135 argumentsBuffer]);
136 } else { 136 } else {
137 body = js.statement( 137 body = js.statement(
138 'return this.#(#);', 138 'return this.#(#);',
139 [namer.getNameOfInstanceMember(member), argumentsBuffer]); 139 [namer.getNameOfInstanceMember(member), argumentsBuffer]);
140 } 140 }
141 } else { 141 } else {
142 body = js.statement('return #(#)', 142 body = js.statement('return #(#)',
143 [namer.elementAccess(member), argumentsBuffer]); 143 [namer.elementAccess(member), argumentsBuffer]);
144 } 144 }
145 145
146 jsAst.Fun function = js('function(#) { #; }', [parametersBuffer, body]); 146 jsAst.Fun function = js('function(#) { #; }', [parametersBuffer, body]);
147 147
148 addStub(selector, function); 148 addStub(selector, function);
149 } 149 }
150 150
151 void addParameterStubs(FunctionElement member, AddStubFunction defineStub, 151 void addParameterStubs(FunctionElement member, AddStubFunction defineStub,
152 [bool canTearOff = false]) { 152 [bool canTearOff = false]) {
153 if (member.enclosingElement.isClosure()) { 153 if (member.enclosingElement.isClosure) {
154 ClosureClassElement cls = member.enclosingElement; 154 ClosureClassElement cls = member.enclosingElement;
155 if (cls.supertype.element == compiler.boundClosureClass) { 155 if (cls.supertype.element == compiler.boundClosureClass) {
156 compiler.internalError(cls.methodElement, 'Bound closure1.'); 156 compiler.internalError(cls.methodElement, 'Bound closure1.');
157 } 157 }
158 if (cls.methodElement.isInstanceMember()) { 158 if (cls.methodElement.isInstanceMember) {
159 compiler.internalError(cls.methodElement, 'Bound closure2.'); 159 compiler.internalError(cls.methodElement, 'Bound closure2.');
160 } 160 }
161 } 161 }
162 162
163 // We fill the lists depending on the selector. For example, 163 // We fill the lists depending on the selector. For example,
164 // take method foo: 164 // take method foo:
165 // foo(a, b, {c, d}); 165 // foo(a, b, {c, d});
166 // 166 //
167 // We may have multiple ways of calling foo: 167 // We may have multiple ways of calling foo:
168 // (1) foo(1, 2); 168 // (1) foo(1, 2);
(...skipping 16 matching lines...) Expand all
185 // (4) No stub generated, call is direct. 185 // (4) No stub generated, call is direct.
186 // (5) No stub generated, call is direct. 186 // (5) No stub generated, call is direct.
187 // 187 //
188 // We need to pay attention if this stub is for a function that has been 188 // We need to pay attention if this stub is for a function that has been
189 // invoked from a subclass. Then we cannot just redirect, since that 189 // invoked from a subclass. Then we cannot just redirect, since that
190 // would invoke the methods of the subclass. We have to compile to: 190 // would invoke the methods of the subclass. We have to compile to:
191 // (1) foo$2(a, b) => MyClass.foo$4$c$d.call(this, a, b, null, null) 191 // (1) foo$2(a, b) => MyClass.foo$4$c$d.call(this, a, b, null, null)
192 // (2) foo$3$c(a, b, c) => MyClass.foo$4$c$d(this, a, b, c, null); 192 // (2) foo$3$c(a, b, c) => MyClass.foo$4$c$d(this, a, b, c, null);
193 // (3) foo$3$d(a, b, d) => MyClass.foo$4$c$d(this, a, b, null, d); 193 // (3) foo$3$d(a, b, d) => MyClass.foo$4$c$d(this, a, b, null, d);
194 194
195 Set<Selector> selectors = member.isInstanceMember() 195 Set<Selector> selectors = member.isInstanceMember
196 ? compiler.codegenWorld.invokedNames[member.name] 196 ? compiler.codegenWorld.invokedNames[member.name]
197 : null; // No stubs needed for static methods. 197 : null; // No stubs needed for static methods.
198 198
199 /// Returns all closure call selectors renamed to match this member. 199 /// Returns all closure call selectors renamed to match this member.
200 Set<Selector> callSelectorsAsNamed() { 200 Set<Selector> callSelectorsAsNamed() {
201 if (!canTearOff) return null; 201 if (!canTearOff) return null;
202 Set<Selector> callSelectors = compiler.codegenWorld.invokedNames[ 202 Set<Selector> callSelectors = compiler.codegenWorld.invokedNames[
203 namer.closureInvocationSelectorName]; 203 namer.closureInvocationSelectorName];
204 if (callSelectors == null) return null; 204 if (callSelectors == null) return null;
205 return callSelectors.map((Selector callSelector) { 205 return callSelectors.map((Selector callSelector) {
206 return new Selector.call( 206 return new Selector.call(
207 member.name, member.getLibrary(), 207 member.name, member.library,
208 callSelector.argumentCount, callSelector.namedArguments); 208 callSelector.argumentCount, callSelector.namedArguments);
209 }).toSet(); 209 }).toSet();
210 } 210 }
211 if (selectors == null) { 211 if (selectors == null) {
212 selectors = callSelectorsAsNamed(); 212 selectors = callSelectorsAsNamed();
213 if (selectors == null) return; 213 if (selectors == null) return;
214 } else { 214 } else {
215 Set<Selector> callSelectors = callSelectorsAsNamed(); 215 Set<Selector> callSelectors = callSelectorsAsNamed();
216 if (callSelectors != null) { 216 if (callSelectors != null) {
217 selectors = selectors.union(callSelectors); 217 selectors = selectors.union(callSelectors);
218 } 218 }
219 } 219 }
220 Set<Selector> untypedSelectors = new Set<Selector>(); 220 Set<Selector> untypedSelectors = new Set<Selector>();
221 if (selectors != null) { 221 if (selectors != null) {
222 for (Selector selector in selectors) { 222 for (Selector selector in selectors) {
223 if (!selector.appliesUnnamed(member, compiler)) continue; 223 if (!selector.appliesUnnamed(member, compiler)) continue;
224 if (untypedSelectors.add(selector.asUntyped)) { 224 if (untypedSelectors.add(selector.asUntyped)) {
225 // TODO(ahe): Is the last argument to [addParameterStub] needed? 225 // TODO(ahe): Is the last argument to [addParameterStub] needed?
226 addParameterStub(member, selector, defineStub, new Set<String>()); 226 addParameterStub(member, selector, defineStub, new Set<String>());
227 } 227 }
228 } 228 }
229 } 229 }
230 if (canTearOff) { 230 if (canTearOff) {
231 selectors = compiler.codegenWorld.invokedNames[ 231 selectors = compiler.codegenWorld.invokedNames[
232 namer.closureInvocationSelectorName]; 232 namer.closureInvocationSelectorName];
233 if (selectors != null) { 233 if (selectors != null) {
234 for (Selector selector in selectors) { 234 for (Selector selector in selectors) {
235 selector = new Selector.call( 235 selector = new Selector.call(
236 member.name, member.getLibrary(), 236 member.name, member.library,
237 selector.argumentCount, selector.namedArguments); 237 selector.argumentCount, selector.namedArguments);
238 if (!selector.appliesUnnamed(member, compiler)) continue; 238 if (!selector.appliesUnnamed(member, compiler)) continue;
239 if (untypedSelectors.add(selector)) { 239 if (untypedSelectors.add(selector)) {
240 // TODO(ahe): Is the last argument to [addParameterStub] needed? 240 // TODO(ahe): Is the last argument to [addParameterStub] needed?
241 addParameterStub(member, selector, defineStub, new Set<String>()); 241 addParameterStub(member, selector, defineStub, new Set<String>());
242 } 242 }
243 } 243 }
244 } 244 }
245 } 245 }
246 } 246 }
247 247
248 /** 248 /**
249 * Documentation wanted -- johnniwinther 249 * Documentation wanted -- johnniwinther
250 * 250 *
251 * Invariant: [member] must be a declaration element. 251 * Invariant: [member] must be a declaration element.
252 */ 252 */
253 void emitCallStubForGetter(Element member, 253 void emitCallStubForGetter(Element member,
254 Set<Selector> selectors, 254 Set<Selector> selectors,
255 AddPropertyFunction addProperty) { 255 AddPropertyFunction addProperty) {
256 assert(invariant(member, member.isDeclaration)); 256 assert(invariant(member, member.isDeclaration));
257 LibraryElement memberLibrary = member.getLibrary(); 257 LibraryElement memberLibrary = member.library;
258 // If the method is intercepted, the stub gets the 258 // If the method is intercepted, the stub gets the
259 // receiver explicitely and we need to pass it to the getter call. 259 // receiver explicitely and we need to pass it to the getter call.
260 bool isInterceptedMethod = backend.isInterceptedMethod(member); 260 bool isInterceptedMethod = backend.isInterceptedMethod(member);
261 bool isInterceptorClass = 261 bool isInterceptorClass =
262 backend.isInterceptorClass(member.getEnclosingClass()); 262 backend.isInterceptorClass(member.enclosingClass);
263 263
264 const String receiverArgumentName = r'$receiver'; 264 const String receiverArgumentName = r'$receiver';
265 265
266 jsAst.Expression buildGetter() { 266 jsAst.Expression buildGetter() {
267 jsAst.Expression receiver = 267 jsAst.Expression receiver =
268 js(isInterceptorClass ? receiverArgumentName : 'this'); 268 js(isInterceptorClass ? receiverArgumentName : 'this');
269 if (member.isGetter()) { 269 if (member.isGetter) {
270 String getterName = namer.getterName(member); 270 String getterName = namer.getterName(member);
271 if (isInterceptedMethod) { 271 if (isInterceptedMethod) {
272 return js('this.#(#)', [getterName, receiver]); 272 return js('this.#(#)', [getterName, receiver]);
273 } 273 }
274 return js('#.#()', [receiver, getterName]); 274 return js('#.#()', [receiver, getterName]);
275 } else { 275 } else {
276 String fieldName = namer.instanceFieldPropertyName(member); 276 String fieldName = namer.instanceFieldPropertyName(member);
277 return js('#.#', [receiver, fieldName]); 277 return js('#.#', [receiver, fieldName]);
278 } 278 }
279 } 279 }
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
313 } 313 }
314 } 314 }
315 315
316 /** 316 /**
317 * Documentation wanted -- johnniwinther 317 * Documentation wanted -- johnniwinther
318 * 318 *
319 * Invariant: [member] must be a declaration element. 319 * Invariant: [member] must be a declaration element.
320 */ 320 */
321 void emitExtraAccessors(Element member, ClassBuilder builder) { 321 void emitExtraAccessors(Element member, ClassBuilder builder) {
322 assert(invariant(member, member.isDeclaration)); 322 assert(invariant(member, member.isDeclaration));
323 if (member.isGetter() || member.isField()) { 323 if (member.isGetter || member.isField) {
324 Set<Selector> selectors = compiler.codegenWorld.invokedNames[member.name]; 324 Set<Selector> selectors = compiler.codegenWorld.invokedNames[member.name];
325 if (selectors != null && !selectors.isEmpty) { 325 if (selectors != null && !selectors.isEmpty) {
326 emitCallStubForGetter(member, selectors, builder.addProperty); 326 emitCallStubForGetter(member, selectors, builder.addProperty);
327 } 327 }
328 } 328 }
329 } 329 }
330 330
331 void addMember(Element member, ClassBuilder builder) { 331 void addMember(Element member, ClassBuilder builder) {
332 assert(invariant(member, member.isDeclaration)); 332 assert(invariant(member, member.isDeclaration));
333 333
334 if (member.isField()) { 334 if (member.isField) {
335 addMemberField(member, builder); 335 addMemberField(member, builder);
336 } else if (member.isFunction() || 336 } else if (member.isFunction ||
337 member.isGenerativeConstructorBody() || 337 member.isGenerativeConstructorBody ||
338 member.isGenerativeConstructor() || 338 member.isGenerativeConstructor ||
339 member.isAccessor()) { 339 member.isAccessor) {
340 addMemberMethod(member, builder); 340 addMemberMethod(member, builder);
341 } else { 341 } else {
342 compiler.internalError(member, 342 compiler.internalError(member,
343 'Unexpected kind: "${member.kind}".'); 343 'Unexpected kind: "${member.kind}".');
344 } 344 }
345 if (member.isInstanceMember()) emitExtraAccessors(member, builder); 345 if (member.isInstanceMember) emitExtraAccessors(member, builder);
346 } 346 }
347 347
348 void addMemberMethod(FunctionElement member, ClassBuilder builder) { 348 void addMemberMethod(FunctionElement member, ClassBuilder builder) {
349 if (member.isAbstract) return; 349 if (member.isAbstract) return;
350 jsAst.Expression code = backend.generatedCode[member]; 350 jsAst.Expression code = backend.generatedCode[member];
351 if (code == null) return; 351 if (code == null) return;
352 String name = namer.getNameOfMember(member); 352 String name = namer.getNameOfMember(member);
353 task.interceptorEmitter.recordMangledNameOfMemberMethod(member, name); 353 task.interceptorEmitter.recordMangledNameOfMemberMethod(member, name);
354 FunctionSignature parameters = member.functionSignature; 354 FunctionSignature parameters = member.functionSignature;
355 bool needsStubs = !parameters.optionalParameters.isEmpty; 355 bool needsStubs = !parameters.optionalParameters.isEmpty;
356 bool canTearOff = false; 356 bool canTearOff = false;
357 bool isClosure = false; 357 bool isClosure = false;
358 bool isNotApplyTarget = !member.isFunction() || 358 bool isNotApplyTarget = !member.isFunction ||
359 member.isConstructor() || 359 member.isConstructor ||
360 member.isAccessor(); 360 member.isAccessor;
361 String tearOffName; 361 String tearOffName;
362 if (isNotApplyTarget) { 362 if (isNotApplyTarget) {
363 canTearOff = false; 363 canTearOff = false;
364 } else if (member.isInstanceMember()) { 364 } else if (member.isInstanceMember) {
365 if (member.getEnclosingClass().isClosure()) { 365 if (member.enclosingClass.isClosure) {
366 canTearOff = false; 366 canTearOff = false;
367 isClosure = true; 367 isClosure = true;
368 } else { 368 } else {
369 // Careful with operators. 369 // Careful with operators.
370 canTearOff = compiler.codegenWorld.hasInvokedGetter(member, compiler); 370 canTearOff = compiler.codegenWorld.hasInvokedGetter(member, compiler);
371 assert(!needsSuperGetter(member) || canTearOff); 371 assert(!needsSuperGetter(member) || canTearOff);
372 tearOffName = namer.getterName(member); 372 tearOffName = namer.getterName(member);
373 } 373 }
374 } else { 374 } else {
375 canTearOff = 375 canTearOff =
(...skipping 12 matching lines...) Expand all
388 addParameterStubs( 388 addParameterStubs(
389 member, 389 member,
390 (Selector selector, jsAst.Fun function) { 390 (Selector selector, jsAst.Fun function) {
391 builder.addProperty(namer.invocationName(selector), function); 391 builder.addProperty(namer.invocationName(selector), function);
392 }); 392 });
393 } 393 }
394 return; 394 return;
395 } 395 }
396 396
397 if (canTearOff) { 397 if (canTearOff) {
398 assert(invariant(member, !member.isGenerativeConstructor())); 398 assert(invariant(member, !member.isGenerativeConstructor));
399 assert(invariant(member, !member.isGenerativeConstructorBody())); 399 assert(invariant(member, !member.isGenerativeConstructorBody));
400 assert(invariant(member, !member.isConstructor())); 400 assert(invariant(member, !member.isConstructor));
401 } 401 }
402 402
403 // This element is needed for reflection or needs additional stubs. So we 403 // This element is needed for reflection or needs additional stubs. So we
404 // need to retain additional information. 404 // need to retain additional information.
405 405
406 // The information is stored in an array with this format: 406 // The information is stored in an array with this format:
407 // 407 //
408 // 1. The JS function for this member. 408 // 1. The JS function for this member.
409 // 2. First stub. 409 // 2. First stub.
410 // 3. Name of first stub. 410 // 3. Name of first stub.
411 // ... 411 // ...
412 // M. Call name of this member. 412 // M. Call name of this member.
413 // M+1. Call name of first stub. 413 // M+1. Call name of first stub.
414 // ... 414 // ...
415 // N. Getter name for tearOff. 415 // N. Getter name for tearOff.
416 // N+1. (Required parameter count << 1) + (member.isAccessor() ? 1 : 0). 416 // N+1. (Required parameter count << 1) + (member.isAccessor ? 1 : 0).
417 // N+2. (Optional parameter count << 1) + 417 // N+2. (Optional parameter count << 1) +
418 // (parameters.optionalParametersAreNamed ? 1 : 0). 418 // (parameters.optionalParametersAreNamed ? 1 : 0).
419 // N+3. Index to function type in constant pool. 419 // N+3. Index to function type in constant pool.
420 // N+4. First default argument. 420 // N+4. First default argument.
421 // ... 421 // ...
422 // O. First parameter name (if needed for reflection or Function.apply). 422 // O. First parameter name (if needed for reflection or Function.apply).
423 // ... 423 // ...
424 // P. Unmangled name (if reflectable). 424 // P. Unmangled name (if reflectable).
425 // P+1. First metadata (if reflectable). 425 // P+1. First metadata (if reflectable).
426 // ... 426 // ...
427 // TODO(ahe): Consider one of the parameter counts can be replaced by the 427 // TODO(ahe): Consider one of the parameter counts can be replaced by the
428 // length property of the JavaScript function object. 428 // length property of the JavaScript function object.
429 429
430 List<jsAst.Expression> expressions = <jsAst.Expression>[]; 430 List<jsAst.Expression> expressions = <jsAst.Expression>[];
431 431
432 String callSelectorString = 'null'; 432 String callSelectorString = 'null';
433 if (member.isFunction()) { 433 if (member.isFunction) {
434 Selector callSelector = 434 Selector callSelector =
435 new Selector.fromElement(member, compiler).toCallSelector(); 435 new Selector.fromElement(member, compiler).toCallSelector();
436 callSelectorString = '"${namer.invocationName(callSelector)}"'; 436 callSelectorString = '"${namer.invocationName(callSelector)}"';
437 } 437 }
438 438
439 // On [requiredParameterCount], the lower bit is set if this method can be 439 // On [requiredParameterCount], the lower bit is set if this method can be
440 // called reflectively. 440 // called reflectively.
441 int requiredParameterCount = parameters.requiredParameterCount << 1; 441 int requiredParameterCount = parameters.requiredParameterCount << 1;
442 if (member.isAccessor()) requiredParameterCount++; 442 if (member.isAccessor) requiredParameterCount++;
443 443
444 int optionalParameterCount = parameters.optionalParameterCount << 1; 444 int optionalParameterCount = parameters.optionalParameterCount << 1;
445 if (parameters.optionalParametersAreNamed) optionalParameterCount++; 445 if (parameters.optionalParametersAreNamed) optionalParameterCount++;
446 446
447 expressions.add(code); 447 expressions.add(code);
448 448
449 // TODO(sra): Don't use LiteralString for non-strings. 449 // TODO(sra): Don't use LiteralString for non-strings.
450 List tearOffInfo = [new jsAst.LiteralString(callSelectorString)]; 450 List tearOffInfo = [new jsAst.LiteralString(callSelectorString)];
451 451
452 if (needsStubs || canTearOff) { 452 if (needsStubs || canTearOff) {
453 addParameterStubs(member, (Selector selector, jsAst.Fun function) { 453 addParameterStubs(member, (Selector selector, jsAst.Fun function) {
454 expressions.add(function); 454 expressions.add(function);
455 if (member.isInstanceMember()) { 455 if (member.isInstanceMember) {
456 Set invokedSelectors = 456 Set invokedSelectors =
457 compiler.codegenWorld.invokedNames[member.name]; 457 compiler.codegenWorld.invokedNames[member.name];
458 expressions.add(js.string(namer.invocationName(selector))); 458 expressions.add(js.string(namer.invocationName(selector)));
459 } else { 459 } else {
460 expressions.add(js('null')); 460 expressions.add(js('null'));
461 // TOOD(ahe): Since we know when reading static data versus instance 461 // TOOD(ahe): Since we know when reading static data versus instance
462 // data, we can eliminate this element. 462 // data, we can eliminate this element.
463 } 463 }
464 Set<Selector> callSelectors = compiler.codegenWorld.invokedNames[ 464 Set<Selector> callSelectors = compiler.codegenWorld.invokedNames[
465 namer.closureInvocationSelectorName]; 465 namer.closureInvocationSelectorName];
466 Selector callSelector = selector.toCallSelector(); 466 Selector callSelector = selector.toCallSelector();
467 String callSelectorString = 'null'; 467 String callSelectorString = 'null';
468 if (canTearOff && callSelectors != null && 468 if (canTearOff && callSelectors != null &&
469 callSelectors.contains(callSelector)) { 469 callSelectors.contains(callSelector)) {
470 callSelectorString = '"${namer.invocationName(callSelector)}"'; 470 callSelectorString = '"${namer.invocationName(callSelector)}"';
471 } 471 }
472 tearOffInfo.add(new jsAst.LiteralString(callSelectorString)); 472 tearOffInfo.add(new jsAst.LiteralString(callSelectorString));
473 }, canTearOff); 473 }, canTearOff);
474 } 474 }
475 475
476 jsAst.Expression memberTypeExpression; 476 jsAst.Expression memberTypeExpression;
477 if (canTearOff || canBeReflected) { 477 if (canTearOff || canBeReflected) {
478 DartType memberType; 478 DartType memberType;
479 if (member.isGenerativeConstructorBody()) { 479 if (member.isGenerativeConstructorBody) {
480 var body = member; 480 var body = member;
481 memberType = body.constructor.type; 481 memberType = body.constructor.type;
482 } else { 482 } else {
483 memberType = member.type; 483 memberType = member.type;
484 } 484 }
485 if (memberType.containsTypeVariables) { 485 if (memberType.containsTypeVariables) {
486 jsAst.Expression thisAccess = js(r'this.$receiver'); 486 jsAst.Expression thisAccess = js(r'this.$receiver');
487 memberTypeExpression = 487 memberTypeExpression =
488 backend.rti.getSignatureEncoding(memberType, thisAccess); 488 backend.rti.getSignatureEncoding(memberType, thisAccess);
489 } else { 489 } else {
490 memberTypeExpression = 490 memberTypeExpression =
491 js.number(task.metadataEmitter.reifyType(memberType)); 491 js.number(task.metadataEmitter.reifyType(memberType));
492 } 492 }
493 } else { 493 } else {
494 memberTypeExpression = js('null'); 494 memberTypeExpression = js('null');
495 } 495 }
496 496
497 expressions 497 expressions
498 ..addAll(tearOffInfo) 498 ..addAll(tearOffInfo)
499 ..add((tearOffName == null || member.isAccessor()) 499 ..add((tearOffName == null || member.isAccessor)
500 ? js("null") : js.string(tearOffName)) 500 ? js("null") : js.string(tearOffName))
501 ..add(js.number(requiredParameterCount)) 501 ..add(js.number(requiredParameterCount))
502 ..add(js.number(optionalParameterCount)) 502 ..add(js.number(optionalParameterCount))
503 ..add(memberTypeExpression) 503 ..add(memberTypeExpression)
504 ..addAll( 504 ..addAll(
505 task.metadataEmitter.reifyDefaultArguments(member).map(js.number)); 505 task.metadataEmitter.reifyDefaultArguments(member).map(js.number));
506 506
507 if (canBeReflected || canBeApplied) { 507 if (canBeReflected || canBeApplied) {
508 parameters.forEachParameter((Element parameter) { 508 parameters.forEachParameter((Element parameter) {
509 expressions.add( 509 expressions.add(
510 js.number(task.metadataEmitter.reifyName(parameter.name))); 510 js.number(task.metadataEmitter.reifyName(parameter.name)));
511 if (backend.mustRetainMetadata) { 511 if (backend.mustRetainMetadata) {
512 List<MetadataAnnotation> annotations = parameter.metadata.toList(); 512 List<MetadataAnnotation> annotations = parameter.metadata.toList();
513 Iterable<int> metadataIndices = 513 Iterable<int> metadataIndices =
514 annotations.map((MetadataAnnotation annotation) { 514 annotations.map((MetadataAnnotation annotation) {
515 Constant constant = 515 Constant constant =
516 backend.constants.getConstantForMetadata(annotation); 516 backend.constants.getConstantForMetadata(annotation);
517 backend.constants.addCompileTimeConstantForEmission(constant); 517 backend.constants.addCompileTimeConstantForEmission(constant);
518 return task.metadataEmitter.reifyMetadata(annotation); 518 return task.metadataEmitter.reifyMetadata(annotation);
519 }); 519 });
520 expressions.add( 520 expressions.add(
521 new jsAst.ArrayInitializer.from(metadataIndices.map(js.number))); 521 new jsAst.ArrayInitializer.from(metadataIndices.map(js.number)));
522 } 522 }
523 }); 523 });
524 } 524 }
525 if (canBeReflected) { 525 if (canBeReflected) {
526 jsAst.LiteralString reflectionName; 526 jsAst.LiteralString reflectionName;
527 if (member.isConstructor()) { 527 if (member.isConstructor) {
528 String reflectionNameString = task.getReflectionName(member, name); 528 String reflectionNameString = task.getReflectionName(member, name);
529 reflectionName = 529 reflectionName =
530 new jsAst.LiteralString( 530 new jsAst.LiteralString(
531 '"new ${Elements.reconstructConstructorName(member)}"'); 531 '"new ${Elements.reconstructConstructorName(member)}"');
532 } else { 532 } else {
533 reflectionName = js.string(member.name); 533 reflectionName = js.string(member.name);
534 } 534 }
535 expressions 535 expressions
536 ..add(reflectionName) 536 ..add(reflectionName)
537 ..addAll(task.metadataEmitter.computeMetadata(member).map(js.number)); 537 ..addAll(task.metadataEmitter.computeMetadata(member).map(js.number));
538 } else if (isClosure && canBeApplied) { 538 } else if (isClosure && canBeApplied) {
539 expressions.add(js.string(member.name)); 539 expressions.add(js.string(member.name));
540 } 540 }
541 builder.addProperty(name, new jsAst.ArrayInitializer.from(expressions)); 541 builder.addProperty(name, new jsAst.ArrayInitializer.from(expressions));
542 } 542 }
543 543
544 void addMemberField(VariableElement member, ClassBuilder builder) { 544 void addMemberField(VariableElement member, ClassBuilder builder) {
545 // For now, do nothing. 545 // For now, do nothing.
546 } 546 }
547 } 547 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698