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 class ClassEmitter extends CodeEmitterHelper { | 7 class ClassEmitter extends CodeEmitterHelper { |
8 | 8 |
9 ClassStubGenerator get _stubGenerator => | 9 ClassStubGenerator get _stubGenerator => |
10 new ClassStubGenerator(compiler, namer, backend); | 10 new ClassStubGenerator(compiler, namer, backend); |
11 | 11 |
12 /** | 12 /** |
13 * Documentation wanted -- johnniwinther | 13 * Documentation wanted -- johnniwinther |
14 */ | 14 */ |
15 void emitClass(Class cls, ClassBuilder enclosingBuilder, Fragment fragment) { | 15 void emitClass(Class cls, ClassBuilder enclosingBuilder, Fragment fragment) { |
16 ClassElement classElement = cls.element; | 16 ClassElement classElement = cls.element; |
17 | 17 |
18 assert(invariant(classElement, classElement.isDeclaration)); | 18 assert(invariant(classElement, classElement.isDeclaration)); |
19 | 19 |
20 emitter.needsClassSupport = true; | 20 emitter.needsClassSupport = true; |
21 | 21 |
22 ClassElement superclass = classElement.superclass; | 22 ClassElement superclass = classElement.superclass; |
23 String superName = ""; | 23 jsAst.Name superName; |
24 if (superclass != null) { | 24 if (superclass != null) { |
25 superName = namer.className(superclass); | 25 superName = namer.className(superclass); |
26 } | 26 } |
27 | 27 |
28 if (cls.isMixinApplication) { | 28 if (cls.isMixinApplication) { |
29 MixinApplication mixinApplication = cls; | 29 MixinApplication mixinApplication = cls; |
30 String mixinName = mixinApplication.mixinClass.name; | 30 jsAst.Name mixinName = mixinApplication.mixinClass.name; |
31 superName = '$superName+$mixinName'; | 31 superName = |
| 32 new CompoundName([superName, Namer.literalPlus, mixinName]); |
32 emitter.needsMixinSupport = true; | 33 emitter.needsMixinSupport = true; |
33 } | 34 } |
34 | 35 |
35 ClassBuilder builder = new ClassBuilder(classElement, namer); | 36 ClassBuilder builder = new ClassBuilder.forClass(classElement, namer); |
36 builder.superName = superName; | 37 builder.superName = superName; |
37 emitConstructorsForCSP(cls); | 38 emitConstructorsForCSP(cls); |
38 emitFields(cls, builder); | 39 emitFields(cls, builder); |
39 emitCheckedClassSetters(cls, builder); | 40 emitCheckedClassSetters(cls, builder); |
40 emitClassGettersSettersForCSP(cls, builder); | 41 emitClassGettersSettersForCSP(cls, builder); |
41 emitInstanceMembers(cls, builder); | 42 emitInstanceMembers(cls, builder); |
42 emitStubs(cls.callStubs, builder); | 43 emitStubs(cls.callStubs, builder); |
43 emitStubs(cls.typeVariableReaderStubs, builder); | 44 emitStubs(cls.typeVariableReaderStubs, builder); |
44 emitRuntimeTypeInformation(cls, builder); | 45 emitRuntimeTypeInformation(cls, builder); |
45 emitNativeInfo(cls, builder); | 46 emitNativeInfo(cls, builder); |
46 | 47 |
47 if (classElement == backend.closureClass) { | 48 if (classElement == backend.closureClass) { |
48 // We add a special getter here to allow for tearing off a closure from | 49 // We add a special getter here to allow for tearing off a closure from |
49 // itself. | 50 // itself. |
50 jsAst.Fun function = js('function() { return this; }'); | 51 jsAst.Fun function = js('function() { return this; }'); |
51 String name = namer.getterForMember(Selector.CALL_NAME); | 52 jsAst.Name name = namer.getterForMember(Selector.CALL_NAME); |
52 builder.addProperty(name, function); | 53 builder.addProperty(name, function); |
53 } | 54 } |
54 | 55 |
55 emitClassBuilderWithReflectionData(cls, builder, enclosingBuilder, | 56 emitClassBuilderWithReflectionData(cls, builder, enclosingBuilder, |
56 fragment); | 57 fragment); |
57 } | 58 } |
58 /** | 59 /** |
59 * Emits the precompiled constructor when in CSP mode. | 60 * Emits the precompiled constructor when in CSP mode. |
60 */ | 61 */ |
61 void emitConstructorsForCSP(Class cls) { | 62 void emitConstructorsForCSP(Class cls) { |
62 List<String> fieldNames = <String>[]; | 63 List<String> fieldNames = <String>[]; |
63 | 64 |
64 if (!compiler.useContentSecurityPolicy) return; | 65 if (!compiler.useContentSecurityPolicy) return; |
65 | 66 |
66 if (!cls.onlyForRti && !cls.isNative) { | 67 if (!cls.onlyForRti && !cls.isNative) { |
67 fieldNames = cls.fields.map((Field field) => field.name).toList(); | 68 fieldNames = cls.fields.map((Field field) => field.name).toList(); |
68 } | 69 } |
69 | 70 |
70 ClassElement classElement = cls.element; | 71 ClassElement classElement = cls.element; |
71 | 72 |
72 jsAst.Expression constructorAst = | 73 jsAst.Expression constructorAst = |
73 _stubGenerator.generateClassConstructor(classElement, fieldNames); | 74 _stubGenerator.generateClassConstructor(classElement, fieldNames); |
74 | 75 |
75 String constructorName = namer.className(classElement); | 76 jsAst.Name constructorName = namer.className(classElement); |
76 OutputUnit outputUnit = | 77 OutputUnit outputUnit = |
77 compiler.deferredLoadTask.outputUnitForElement(classElement); | 78 compiler.deferredLoadTask.outputUnitForElement(classElement); |
78 emitter.assemblePrecompiledConstructor( | 79 emitter.assemblePrecompiledConstructor( |
79 outputUnit, constructorName, constructorAst, fieldNames); | 80 outputUnit, constructorName, constructorAst, fieldNames); |
80 } | 81 } |
81 | 82 |
82 /// Returns `true` if fields added. | 83 /// Returns `true` if fields added. |
83 bool emitFields(FieldContainer container, | 84 bool emitFields(FieldContainer container, |
84 ClassBuilder builder, | 85 ClassBuilder builder, |
85 { bool classIsNative: false, | 86 { bool classIsNative: false, |
(...skipping 12 matching lines...) Expand all Loading... |
98 assert(emitStatics); | 99 assert(emitStatics); |
99 fields = container.staticFieldsForReflection; | 100 fields = container.staticFieldsForReflection; |
100 } | 101 } |
101 | 102 |
102 var fieldMetadata = []; | 103 var fieldMetadata = []; |
103 bool hasMetadata = false; | 104 bool hasMetadata = false; |
104 bool fieldsAdded = false; | 105 bool fieldsAdded = false; |
105 | 106 |
106 for (Field field in fields) { | 107 for (Field field in fields) { |
107 FieldElement fieldElement = field.element; | 108 FieldElement fieldElement = field.element; |
108 String name = field.name; | 109 jsAst.Name name = field.name; |
109 String accessorName = field.accessorName; | 110 jsAst.Name accessorName = field.accessorName; |
110 bool needsGetter = field.needsGetter; | 111 bool needsGetter = field.needsGetter; |
111 bool needsSetter = field.needsUncheckedSetter; | 112 bool needsSetter = field.needsUncheckedSetter; |
112 | 113 |
113 // Ignore needsCheckedSetter - that is handled below. | 114 // Ignore needsCheckedSetter - that is handled below. |
114 bool needsAccessor = (needsGetter || needsSetter); | 115 bool needsAccessor = (needsGetter || needsSetter); |
115 // We need to output the fields for non-native classes so we can auto- | 116 // We need to output the fields for non-native classes so we can auto- |
116 // generate the constructor. For native classes there are no | 117 // generate the constructor. For native classes there are no |
117 // constructors, so we don't need the fields unless we are generating | 118 // constructors, so we don't need the fields unless we are generating |
118 // accessors at runtime. | 119 // accessors at runtime. |
119 bool needsFieldsForConstructor = !emitStatics && !classIsNative; | 120 bool needsFieldsForConstructor = !emitStatics && !classIsNative; |
120 if (needsFieldsForConstructor || needsAccessor) { | 121 if (needsFieldsForConstructor || needsAccessor) { |
121 var metadata = | 122 var metadata = |
122 task.metadataCollector.buildMetadataFunction(fieldElement); | 123 task.metadataCollector.buildMetadataFunction(fieldElement); |
123 if (metadata != null) { | 124 if (metadata != null) { |
124 hasMetadata = true; | 125 hasMetadata = true; |
125 } else { | 126 } else { |
126 metadata = new jsAst.LiteralNull(); | 127 metadata = new jsAst.LiteralNull(); |
127 } | 128 } |
128 fieldMetadata.add(metadata); | 129 fieldMetadata.add(metadata); |
129 recordMangledField(fieldElement, accessorName, | 130 recordMangledField(fieldElement, accessorName, |
130 namer.privateName(fieldElement.memberName)); | 131 namer.privateName(fieldElement.memberName)); |
131 List<jsAst.Literal> fieldNameParts = <jsAst.Literal>[]; | 132 List<jsAst.Literal> fieldNameParts = <jsAst.Literal>[]; |
132 if (!needsAccessor) { | 133 if (!needsAccessor) { |
133 // Emit field for constructor generation. | 134 // Emit field for constructor generation. |
134 assert(!classIsNative); | 135 assert(!classIsNative); |
135 fieldNameParts.add(js.stringPart(name)); | 136 fieldNameParts.add(name); |
136 } else { | 137 } else { |
137 // Emit (possibly renaming) field name so we can add accessors at | 138 // Emit (possibly renaming) field name so we can add accessors at |
138 // runtime. | 139 // runtime. |
139 if (name != accessorName) { | 140 if (name != accessorName) { |
140 fieldNameParts.add(js.stringPart(accessorName)); | 141 fieldNameParts.add(accessorName); |
141 fieldNameParts.add(js.stringPart(':')); | 142 fieldNameParts.add(js.stringPart(':')); |
142 } | 143 } |
143 fieldNameParts.add(js.stringPart(name)); | 144 fieldNameParts.add(name); |
144 if (field.needsInterceptedGetter) { | 145 if (field.needsInterceptedGetter) { |
145 emitter.interceptorEmitter.interceptorInvocationNames.add( | 146 emitter.interceptorEmitter.interceptorInvocationNames.add( |
146 namer.getterForElement(fieldElement)); | 147 namer.getterForElement(fieldElement)); |
147 } | 148 } |
148 // TODO(16168): The setter creator only looks at the getter-name. | 149 // TODO(16168): The setter creator only looks at the getter-name. |
149 // Even though the setter could avoid the interceptor convention we | 150 // Even though the setter could avoid the interceptor convention we |
150 // currently still need to add the additional argument. | 151 // currently still need to add the additional argument. |
151 if (field.needsInterceptedGetter || field.needsInterceptedSetter) { | 152 if (field.needsInterceptedGetter || field.needsInterceptedSetter) { |
152 emitter.interceptorEmitter.interceptorInvocationNames.add( | 153 emitter.interceptorEmitter.interceptorInvocationNames.add( |
153 namer.setterForElement(fieldElement)); | 154 namer.setterForElement(fieldElement)); |
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
268 builder.functionType = cls.functionTypeIndex; | 269 builder.functionType = cls.functionTypeIndex; |
269 } | 270 } |
270 | 271 |
271 for (Method method in cls.isChecks) { | 272 for (Method method in cls.isChecks) { |
272 builder.addProperty(method.name, method.code); | 273 builder.addProperty(method.name, method.code); |
273 } | 274 } |
274 } | 275 } |
275 | 276 |
276 void emitNativeInfo(Class cls, ClassBuilder builder) { | 277 void emitNativeInfo(Class cls, ClassBuilder builder) { |
277 if (cls.nativeInfo != null) { | 278 if (cls.nativeInfo != null) { |
278 builder.addProperty(namer.nativeSpecProperty, js.string(cls.nativeInfo)); | 279 builder.addPropertyByName(namer.nativeSpecProperty, cls.nativeInfo); |
279 } | 280 } |
280 } | 281 } |
281 | 282 |
282 void emitClassBuilderWithReflectionData(Class cls, | 283 void emitClassBuilderWithReflectionData(Class cls, |
283 ClassBuilder classBuilder, | 284 ClassBuilder classBuilder, |
284 ClassBuilder enclosingBuilder, | 285 ClassBuilder enclosingBuilder, |
285 Fragment fragment) { | 286 Fragment fragment) { |
286 ClassElement classElement = cls.element; | 287 ClassElement classElement = cls.element; |
287 String className = cls.name; | 288 jsAst.Name className = cls.name; |
288 | 289 |
289 var metadata = task.metadataCollector.buildMetadataFunction(classElement); | 290 var metadata = task.metadataCollector.buildMetadataFunction(classElement); |
290 if (metadata != null) { | 291 if (metadata != null) { |
291 classBuilder.addProperty("@", metadata); | 292 classBuilder.addPropertyByName("@", metadata); |
292 } | 293 } |
293 | 294 |
294 if (backend.isAccessibleByReflection(classElement)) { | 295 if (backend.isAccessibleByReflection(classElement)) { |
295 List<DartType> typeVars = classElement.typeVariables; | 296 List<DartType> typeVars = classElement.typeVariables; |
296 Iterable typeVariableProperties = emitter.typeVariableHandler | 297 Iterable typeVariableProperties = emitter.typeVariableHandler |
297 .typeVariablesOf(classElement); | 298 .typeVariablesOf(classElement); |
298 | 299 |
299 ClassElement superclass = classElement.superclass; | 300 ClassElement superclass = classElement.superclass; |
300 bool hasSuper = superclass != null; | 301 bool hasSuper = superclass != null; |
301 if ((!typeVariableProperties.isEmpty && !hasSuper) || | 302 if ((!typeVariableProperties.isEmpty && !hasSuper) || |
302 (hasSuper && !equalElements(superclass.typeVariables, typeVars))) { | 303 (hasSuper && !equalElements(superclass.typeVariables, typeVars))) { |
303 classBuilder.addProperty('<>', | 304 classBuilder.addPropertyByName('<>', |
304 new jsAst.ArrayInitializer(typeVariableProperties.toList())); | 305 new jsAst.ArrayInitializer(typeVariableProperties.toList())); |
305 } | 306 } |
306 } | 307 } |
307 | 308 |
308 List<jsAst.Property> statics = new List<jsAst.Property>(); | 309 List<jsAst.Property> statics = new List<jsAst.Property>(); |
309 ClassBuilder staticsBuilder = new ClassBuilder(classElement, namer); | 310 ClassBuilder staticsBuilder = |
| 311 new ClassBuilder.forStatics(classElement, namer); |
310 if (emitFields(cls, staticsBuilder, emitStatics: true)) { | 312 if (emitFields(cls, staticsBuilder, emitStatics: true)) { |
311 jsAst.ObjectInitializer initializer = | 313 jsAst.ObjectInitializer initializer = |
312 staticsBuilder.toObjectInitializer(); | 314 staticsBuilder.toObjectInitializer(); |
313 compiler.dumpInfoTask.registerElementAst(classElement, | 315 compiler.dumpInfoTask.registerElementAst(classElement, |
314 initializer); | 316 initializer); |
315 jsAst.Node property = initializer.properties.single; | 317 jsAst.Node property = initializer.properties.single; |
316 compiler.dumpInfoTask.registerElementAst(classElement, property); | 318 compiler.dumpInfoTask.registerElementAst(classElement, property); |
317 statics.add(property); | 319 statics.add(property); |
318 } | 320 } |
319 | 321 |
320 // TODO(herhut): Do not grab statics out of the properties. | 322 // TODO(herhut): Do not grab statics out of the properties. |
321 ClassBuilder classProperties = | 323 ClassBuilder classProperties = |
322 emitter.elementDescriptors[fragment].remove(classElement); | 324 emitter.elementDescriptors[fragment].remove(classElement); |
323 if (classProperties != null) { | 325 if (classProperties != null) { |
324 statics.addAll(classProperties.properties); | 326 statics.addAll(classProperties.properties); |
325 } | 327 } |
326 | 328 |
327 if (!statics.isEmpty) { | 329 if (!statics.isEmpty) { |
328 classBuilder.addProperty('static', new jsAst.ObjectInitializer(statics)); | 330 classBuilder.addPropertyByName('static', |
| 331 new jsAst.ObjectInitializer(statics)); |
329 } | 332 } |
330 | 333 |
331 // TODO(ahe): This method (generateClass) should return a jsAst.Expression. | 334 // TODO(ahe): This method (generateClass) should return a jsAst.Expression. |
332 jsAst.ObjectInitializer propertyValue = | 335 jsAst.ObjectInitializer propertyValue = |
333 classBuilder.toObjectInitializer(); | 336 classBuilder.toObjectInitializer(); |
334 compiler.dumpInfoTask.registerElementAst(classBuilder.element, propertyValue
); | 337 compiler.dumpInfoTask.registerElementAst(classBuilder.element, propertyValue
); |
335 enclosingBuilder.addProperty(className, propertyValue); | 338 enclosingBuilder.addProperty(className, propertyValue); |
336 | 339 |
337 String reflectionName = emitter.getReflectionName(classElement, className); | 340 String reflectionName = emitter.getReflectionName(classElement, className); |
338 if (reflectionName != null) { | 341 if (reflectionName != null) { |
339 if (!backend.isAccessibleByReflection(classElement)) { | 342 if (!backend.isAccessibleByReflection(classElement)) { |
340 enclosingBuilder.addProperty("+$reflectionName", js.number(0)); | 343 // TODO(herhut): Fix use of reflection name here. |
| 344 enclosingBuilder.addPropertyByName("+$reflectionName", js.number(0)); |
341 } else { | 345 } else { |
342 List<jsAst.Expression> types = <jsAst.Expression>[]; | 346 List<jsAst.Expression> types = <jsAst.Expression>[]; |
343 if (classElement.supertype != null) { | 347 if (classElement.supertype != null) { |
344 types.add(task.metadataCollector.reifyType(classElement.supertype)); | 348 types.add(task.metadataCollector.reifyType(classElement.supertype)); |
345 } | 349 } |
346 for (DartType interface in classElement.interfaces) { | 350 for (DartType interface in classElement.interfaces) { |
347 types.add(task.metadataCollector.reifyType(interface)); | 351 types.add(task.metadataCollector.reifyType(interface)); |
348 } | 352 } |
349 enclosingBuilder.addProperty("+$reflectionName", | 353 // TODO(herhut): Fix use of reflection name here. |
| 354 enclosingBuilder.addPropertyByName("+$reflectionName", |
350 new jsAst.ArrayInitializer(types)); | 355 new jsAst.ArrayInitializer(types)); |
351 } | 356 } |
352 } | 357 } |
353 } | 358 } |
354 | 359 |
355 /** | 360 /** |
356 * Invokes [f] for each of the fields of [element]. | 361 * Invokes [f] for each of the fields of [element]. |
357 * | 362 * |
358 * [element] must be a [ClassElement] or a [LibraryElement]. | 363 * [element] must be a [ClassElement] or a [LibraryElement]. |
359 * | 364 * |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
403 bool needsGetter = false; | 408 bool needsGetter = false; |
404 bool needsSetter = false; | 409 bool needsSetter = false; |
405 if (isLibrary || isMixinNativeField || holder == element) { | 410 if (isLibrary || isMixinNativeField || holder == element) { |
406 needsGetter = fieldNeedsGetter(field); | 411 needsGetter = fieldNeedsGetter(field); |
407 needsSetter = fieldNeedsSetter(field); | 412 needsSetter = fieldNeedsSetter(field); |
408 } | 413 } |
409 | 414 |
410 if ((isInstantiated && !holder.isNative) | 415 if ((isInstantiated && !holder.isNative) |
411 || needsGetter | 416 || needsGetter |
412 || needsSetter) { | 417 || needsSetter) { |
413 String accessorName = namer.fieldAccessorName(field); | 418 jsAst.Name accessorName = namer.fieldAccessorName(field); |
414 String fieldName = namer.fieldPropertyName(field); | 419 jsAst.Name fieldName = namer.fieldPropertyName(field); |
415 bool needsCheckedSetter = false; | 420 bool needsCheckedSetter = false; |
416 if (compiler.enableTypeAssertions | 421 if (compiler.enableTypeAssertions |
417 && needsSetter | 422 && needsSetter |
418 && !canAvoidGeneratedCheckedSetter(field)) { | 423 && !canAvoidGeneratedCheckedSetter(field)) { |
419 needsCheckedSetter = true; | 424 needsCheckedSetter = true; |
420 needsSetter = false; | 425 needsSetter = false; |
421 } | 426 } |
422 // Getters and setters with suffixes will be generated dynamically. | 427 // Getters and setters with suffixes will be generated dynamically. |
423 f(field, fieldName, accessorName, needsGetter, needsSetter, | 428 f(field, fieldName, accessorName, needsGetter, needsSetter, |
424 needsCheckedSetter); | 429 needsCheckedSetter); |
(...skipping 18 matching lines...) Expand all Loading... |
443 // If a class is not instantiated then we add the field just so we can | 448 // If a class is not instantiated then we add the field just so we can |
444 // generate the field getter/setter dynamically. Since this is only | 449 // generate the field getter/setter dynamically. Since this is only |
445 // allowed on fields that are in [element] we don't need to visit | 450 // allowed on fields that are in [element] we don't need to visit |
446 // superclasses for non-instantiated classes. | 451 // superclasses for non-instantiated classes. |
447 cls.implementation.forEachInstanceField( | 452 cls.implementation.forEachInstanceField( |
448 visitField, includeSuperAndInjectedMembers: isInstantiated); | 453 visitField, includeSuperAndInjectedMembers: isInstantiated); |
449 } | 454 } |
450 } | 455 } |
451 | 456 |
452 void recordMangledField(Element member, | 457 void recordMangledField(Element member, |
453 String accessorName, | 458 jsAst.Name accessorName, |
454 String memberName) { | 459 String memberName) { |
455 if (!backend.shouldRetainGetter(member)) return; | 460 if (!backend.shouldRetainGetter(member)) return; |
456 String previousName; | 461 String previousName; |
457 if (member.isInstanceMember) { | 462 if (member.isInstanceMember) { |
458 previousName = emitter.mangledFieldNames.putIfAbsent( | 463 previousName = emitter.mangledFieldNames.putIfAbsent( |
459 '${namer.getterPrefix}$accessorName', | 464 namer.deriveGetterName(accessorName), |
460 () => memberName); | 465 () => memberName); |
461 } else { | 466 } else { |
462 previousName = emitter.mangledGlobalFieldNames.putIfAbsent( | 467 previousName = emitter.mangledGlobalFieldNames.putIfAbsent( |
463 accessorName, | 468 accessorName, |
464 () => memberName); | 469 () => memberName); |
465 } | 470 } |
466 assert(invariant(member, previousName == memberName, | 471 assert(invariant(member, previousName == memberName, |
467 message: '$previousName != ${memberName}')); | 472 message: '$previousName != ${memberName}')); |
468 } | 473 } |
469 | 474 |
(...skipping 24 matching lines...) Expand all Loading... |
494 } | 499 } |
495 | 500 |
496 bool canAvoidGeneratedCheckedSetter(VariableElement member) { | 501 bool canAvoidGeneratedCheckedSetter(VariableElement member) { |
497 // We never generate accessors for top-level/static fields. | 502 // We never generate accessors for top-level/static fields. |
498 if (!member.isInstanceMember) return true; | 503 if (!member.isInstanceMember) return true; |
499 DartType type = member.type; | 504 DartType type = member.type; |
500 return type.treatAsDynamic || (type.element == compiler.objectClass); | 505 return type.treatAsDynamic || (type.element == compiler.objectClass); |
501 } | 506 } |
502 | 507 |
503 void generateCheckedSetter(Element member, | 508 void generateCheckedSetter(Element member, |
504 String fieldName, | 509 jsAst.Name fieldName, |
505 String accessorName, | 510 jsAst.Name accessorName, |
506 ClassBuilder builder) { | 511 ClassBuilder builder) { |
507 jsAst.Expression code = backend.generatedCode[member]; | 512 jsAst.Expression code = backend.generatedCode[member]; |
508 assert(code != null); | 513 assert(code != null); |
509 String setterName = namer.deriveSetterName(accessorName); | 514 jsAst.Name setterName = namer.deriveSetterName(accessorName); |
510 compiler.dumpInfoTask.registerElementAst(member, | 515 compiler.dumpInfoTask.registerElementAst(member, |
511 builder.addProperty(setterName, code)); | 516 builder.addProperty(setterName, code)); |
512 generateReflectionDataForFieldGetterOrSetter( | 517 generateReflectionDataForFieldGetterOrSetter( |
513 member, setterName, builder, isGetter: false); | 518 member, setterName, builder, isGetter: false); |
514 } | 519 } |
515 | 520 |
516 void emitGetterForCSP(Element member, String fieldName, String accessorName, | 521 void emitGetterForCSP(Element member, jsAst.Name fieldName, |
| 522 jsAst.Name accessorName, |
517 ClassBuilder builder) { | 523 ClassBuilder builder) { |
518 jsAst.Expression function = | 524 jsAst.Expression function = |
519 _stubGenerator.generateGetter(member, fieldName); | 525 _stubGenerator.generateGetter(member, fieldName); |
520 | 526 |
521 String getterName = namer.deriveGetterName(accessorName); | 527 jsAst.Name getterName = namer.deriveGetterName(accessorName); |
522 ClassElement cls = member.enclosingClass; | 528 ClassElement cls = member.enclosingClass; |
523 String className = namer.className(cls); | 529 jsAst.Name className = namer.className(cls); |
524 OutputUnit outputUnit = | 530 OutputUnit outputUnit = |
525 compiler.deferredLoadTask.outputUnitForElement(member); | 531 compiler.deferredLoadTask.outputUnitForElement(member); |
526 emitter.cspPrecompiledFunctionFor(outputUnit).add( | 532 emitter.cspPrecompiledFunctionFor(outputUnit).add( |
527 js('#.prototype.# = #', [className, getterName, function])); | 533 js('#.prototype.# = #', [className, getterName, function])); |
528 if (backend.isAccessibleByReflection(member)) { | 534 if (backend.isAccessibleByReflection(member)) { |
529 emitter.cspPrecompiledFunctionFor(outputUnit).add( | 535 emitter.cspPrecompiledFunctionFor(outputUnit).add( |
530 js('#.prototype.#.${namer.reflectableField} = 1', | 536 js('#.prototype.#.${namer.reflectableField} = 1', |
531 [className, getterName])); | 537 [className, getterName])); |
532 } | 538 } |
533 } | 539 } |
534 | 540 |
535 void emitSetterForCSP(Element member, String fieldName, String accessorName, | 541 void emitSetterForCSP(Element member, jsAst.Name fieldName, |
| 542 jsAst.Name accessorName, |
536 ClassBuilder builder) { | 543 ClassBuilder builder) { |
537 jsAst.Expression function = | 544 jsAst.Expression function = |
538 _stubGenerator.generateSetter(member, fieldName); | 545 _stubGenerator.generateSetter(member, fieldName); |
539 | 546 |
540 String setterName = namer.deriveSetterName(accessorName); | 547 jsAst.Name setterName = namer.deriveSetterName(accessorName); |
541 ClassElement cls = member.enclosingClass; | 548 ClassElement cls = member.enclosingClass; |
542 String className = namer.className(cls); | 549 jsAst.Name className = namer.className(cls); |
543 OutputUnit outputUnit = | 550 OutputUnit outputUnit = |
544 compiler.deferredLoadTask.outputUnitForElement(member); | 551 compiler.deferredLoadTask.outputUnitForElement(member); |
545 emitter.cspPrecompiledFunctionFor(outputUnit).add( | 552 emitter.cspPrecompiledFunctionFor(outputUnit).add( |
546 js('#.prototype.# = #', [className, setterName, function])); | 553 js('#.prototype.# = #', [className, setterName, function])); |
547 if (backend.isAccessibleByReflection(member)) { | 554 if (backend.isAccessibleByReflection(member)) { |
548 emitter.cspPrecompiledFunctionFor(outputUnit).add( | 555 emitter.cspPrecompiledFunctionFor(outputUnit).add( |
549 js('#.prototype.#.${namer.reflectableField} = 1', | 556 js('#.prototype.#.${namer.reflectableField} = 1', |
550 [className, setterName])); | 557 [className, setterName])); |
551 } | 558 } |
552 } | 559 } |
553 | 560 |
554 void generateReflectionDataForFieldGetterOrSetter(Element member, | 561 void generateReflectionDataForFieldGetterOrSetter(Element member, |
555 String name, | 562 jsAst.Name name, |
556 ClassBuilder builder, | 563 ClassBuilder builder, |
557 {bool isGetter}) { | 564 {bool isGetter}) { |
558 Selector selector = isGetter | 565 Selector selector = isGetter |
559 ? new Selector.getter(member.name, member.library) | 566 ? new Selector.getter(member.name, member.library) |
560 : new Selector.setter(member.name, member.library); | 567 : new Selector.setter(member.name, member.library); |
561 String reflectionName = emitter.getReflectionName(selector, name); | 568 String reflectionName = emitter.getReflectionName(selector, name); |
562 if (reflectionName != null) { | 569 if (reflectionName != null) { |
563 var reflectable = | 570 var reflectable = |
564 js(backend.isAccessibleByReflection(member) ? '1' : '0'); | 571 js(backend.isAccessibleByReflection(member) ? '1' : '0'); |
565 builder.addProperty('+$reflectionName', reflectable); | 572 builder.addPropertyByName('+$reflectionName', reflectable); |
566 } | 573 } |
567 } | 574 } |
568 } | 575 } |
OLD | NEW |