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', new jsAst.ObjectInitializer(stati cs)); |
floitsch
2015/06/22 17:43:44
long line.
herhut
2015/06/23 13:26:31
Thanks!
| |
329 } | 331 } |
330 | 332 |
331 // TODO(ahe): This method (generateClass) should return a jsAst.Expression. | 333 // TODO(ahe): This method (generateClass) should return a jsAst.Expression. |
332 jsAst.ObjectInitializer propertyValue = | 334 jsAst.ObjectInitializer propertyValue = |
333 classBuilder.toObjectInitializer(); | 335 classBuilder.toObjectInitializer(); |
334 compiler.dumpInfoTask.registerElementAst(classBuilder.element, propertyValue ); | 336 compiler.dumpInfoTask.registerElementAst(classBuilder.element, propertyValue ); |
335 enclosingBuilder.addProperty(className, propertyValue); | 337 enclosingBuilder.addProperty(className, propertyValue); |
336 | 338 |
337 String reflectionName = emitter.getReflectionName(classElement, className); | 339 String reflectionName = emitter.getReflectionName(classElement, className); |
338 if (reflectionName != null) { | 340 if (reflectionName != null) { |
339 if (!backend.isAccessibleByReflection(classElement)) { | 341 if (!backend.isAccessibleByReflection(classElement)) { |
340 enclosingBuilder.addProperty("+$reflectionName", js.number(0)); | 342 // TODO(herhut): Fix use of reflection name here. |
343 enclosingBuilder.addPropertyByName("+$reflectionName", js.number(0)); | |
341 } else { | 344 } else { |
342 List<jsAst.Expression> types = <jsAst.Expression>[]; | 345 List<jsAst.Expression> types = <jsAst.Expression>[]; |
343 if (classElement.supertype != null) { | 346 if (classElement.supertype != null) { |
344 types.add(task.metadataCollector.reifyType(classElement.supertype)); | 347 types.add(task.metadataCollector.reifyType(classElement.supertype)); |
345 } | 348 } |
346 for (DartType interface in classElement.interfaces) { | 349 for (DartType interface in classElement.interfaces) { |
347 types.add(task.metadataCollector.reifyType(interface)); | 350 types.add(task.metadataCollector.reifyType(interface)); |
348 } | 351 } |
349 enclosingBuilder.addProperty("+$reflectionName", | 352 // TODO(herhut): Fix use of reflection name here. |
353 enclosingBuilder.addPropertyByName("+$reflectionName", | |
350 new jsAst.ArrayInitializer(types)); | 354 new jsAst.ArrayInitializer(types)); |
351 } | 355 } |
352 } | 356 } |
353 } | 357 } |
354 | 358 |
355 /** | 359 /** |
356 * Invokes [f] for each of the fields of [element]. | 360 * Invokes [f] for each of the fields of [element]. |
357 * | 361 * |
358 * [element] must be a [ClassElement] or a [LibraryElement]. | 362 * [element] must be a [ClassElement] or a [LibraryElement]. |
359 * | 363 * |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
403 bool needsGetter = false; | 407 bool needsGetter = false; |
404 bool needsSetter = false; | 408 bool needsSetter = false; |
405 if (isLibrary || isMixinNativeField || holder == element) { | 409 if (isLibrary || isMixinNativeField || holder == element) { |
406 needsGetter = fieldNeedsGetter(field); | 410 needsGetter = fieldNeedsGetter(field); |
407 needsSetter = fieldNeedsSetter(field); | 411 needsSetter = fieldNeedsSetter(field); |
408 } | 412 } |
409 | 413 |
410 if ((isInstantiated && !holder.isNative) | 414 if ((isInstantiated && !holder.isNative) |
411 || needsGetter | 415 || needsGetter |
412 || needsSetter) { | 416 || needsSetter) { |
413 String accessorName = namer.fieldAccessorName(field); | 417 jsAst.Name accessorName = namer.fieldAccessorName(field); |
414 String fieldName = namer.fieldPropertyName(field); | 418 jsAst.Name fieldName = namer.fieldPropertyName(field); |
415 bool needsCheckedSetter = false; | 419 bool needsCheckedSetter = false; |
416 if (compiler.enableTypeAssertions | 420 if (compiler.enableTypeAssertions |
417 && needsSetter | 421 && needsSetter |
418 && !canAvoidGeneratedCheckedSetter(field)) { | 422 && !canAvoidGeneratedCheckedSetter(field)) { |
419 needsCheckedSetter = true; | 423 needsCheckedSetter = true; |
420 needsSetter = false; | 424 needsSetter = false; |
421 } | 425 } |
422 // Getters and setters with suffixes will be generated dynamically. | 426 // Getters and setters with suffixes will be generated dynamically. |
423 f(field, fieldName, accessorName, needsGetter, needsSetter, | 427 f(field, fieldName, accessorName, needsGetter, needsSetter, |
424 needsCheckedSetter); | 428 needsCheckedSetter); |
(...skipping 18 matching lines...) Expand all Loading... | |
443 // If a class is not instantiated then we add the field just so we can | 447 // 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 | 448 // generate the field getter/setter dynamically. Since this is only |
445 // allowed on fields that are in [element] we don't need to visit | 449 // allowed on fields that are in [element] we don't need to visit |
446 // superclasses for non-instantiated classes. | 450 // superclasses for non-instantiated classes. |
447 cls.implementation.forEachInstanceField( | 451 cls.implementation.forEachInstanceField( |
448 visitField, includeSuperAndInjectedMembers: isInstantiated); | 452 visitField, includeSuperAndInjectedMembers: isInstantiated); |
449 } | 453 } |
450 } | 454 } |
451 | 455 |
452 void recordMangledField(Element member, | 456 void recordMangledField(Element member, |
453 String accessorName, | 457 jsAst.Name accessorName, |
454 String memberName) { | 458 String memberName) { |
455 if (!backend.shouldRetainGetter(member)) return; | 459 if (!backend.shouldRetainGetter(member)) return; |
456 String previousName; | 460 String previousName; |
457 if (member.isInstanceMember) { | 461 if (member.isInstanceMember) { |
458 previousName = emitter.mangledFieldNames.putIfAbsent( | 462 previousName = emitter.mangledFieldNames.putIfAbsent( |
459 '${namer.getterPrefix}$accessorName', | 463 namer.deriveGetterName(accessorName), |
460 () => memberName); | 464 () => memberName); |
461 } else { | 465 } else { |
462 previousName = emitter.mangledGlobalFieldNames.putIfAbsent( | 466 previousName = emitter.mangledGlobalFieldNames.putIfAbsent( |
463 accessorName, | 467 accessorName, |
464 () => memberName); | 468 () => memberName); |
465 } | 469 } |
466 assert(invariant(member, previousName == memberName, | 470 assert(invariant(member, previousName == memberName, |
467 message: '$previousName != ${memberName}')); | 471 message: '$previousName != ${memberName}')); |
468 } | 472 } |
469 | 473 |
(...skipping 24 matching lines...) Expand all Loading... | |
494 } | 498 } |
495 | 499 |
496 bool canAvoidGeneratedCheckedSetter(VariableElement member) { | 500 bool canAvoidGeneratedCheckedSetter(VariableElement member) { |
497 // We never generate accessors for top-level/static fields. | 501 // We never generate accessors for top-level/static fields. |
498 if (!member.isInstanceMember) return true; | 502 if (!member.isInstanceMember) return true; |
499 DartType type = member.type; | 503 DartType type = member.type; |
500 return type.treatAsDynamic || (type.element == compiler.objectClass); | 504 return type.treatAsDynamic || (type.element == compiler.objectClass); |
501 } | 505 } |
502 | 506 |
503 void generateCheckedSetter(Element member, | 507 void generateCheckedSetter(Element member, |
504 String fieldName, | 508 jsAst.Name fieldName, |
505 String accessorName, | 509 jsAst.Name accessorName, |
506 ClassBuilder builder) { | 510 ClassBuilder builder) { |
507 jsAst.Expression code = backend.generatedCode[member]; | 511 jsAst.Expression code = backend.generatedCode[member]; |
508 assert(code != null); | 512 assert(code != null); |
509 String setterName = namer.deriveSetterName(accessorName); | 513 jsAst.Name setterName = namer.deriveSetterName(accessorName); |
510 compiler.dumpInfoTask.registerElementAst(member, | 514 compiler.dumpInfoTask.registerElementAst(member, |
511 builder.addProperty(setterName, code)); | 515 builder.addProperty(setterName, code)); |
512 generateReflectionDataForFieldGetterOrSetter( | 516 generateReflectionDataForFieldGetterOrSetter( |
513 member, setterName, builder, isGetter: false); | 517 member, setterName, builder, isGetter: false); |
514 } | 518 } |
515 | 519 |
516 void emitGetterForCSP(Element member, String fieldName, String accessorName, | 520 void emitGetterForCSP(Element member, jsAst.Name fieldName, |
521 jsAst.Name accessorName, | |
517 ClassBuilder builder) { | 522 ClassBuilder builder) { |
518 jsAst.Expression function = | 523 jsAst.Expression function = |
519 _stubGenerator.generateGetter(member, fieldName); | 524 _stubGenerator.generateGetter(member, fieldName); |
520 | 525 |
521 String getterName = namer.deriveGetterName(accessorName); | 526 jsAst.Name getterName = namer.deriveGetterName(accessorName); |
522 ClassElement cls = member.enclosingClass; | 527 ClassElement cls = member.enclosingClass; |
523 String className = namer.className(cls); | 528 jsAst.Name className = namer.className(cls); |
524 OutputUnit outputUnit = | 529 OutputUnit outputUnit = |
525 compiler.deferredLoadTask.outputUnitForElement(member); | 530 compiler.deferredLoadTask.outputUnitForElement(member); |
526 emitter.cspPrecompiledFunctionFor(outputUnit).add( | 531 emitter.cspPrecompiledFunctionFor(outputUnit).add( |
527 js('#.prototype.# = #', [className, getterName, function])); | 532 js('#.prototype.# = #', [className, getterName, function])); |
528 if (backend.isAccessibleByReflection(member)) { | 533 if (backend.isAccessibleByReflection(member)) { |
529 emitter.cspPrecompiledFunctionFor(outputUnit).add( | 534 emitter.cspPrecompiledFunctionFor(outputUnit).add( |
530 js('#.prototype.#.${namer.reflectableField} = 1', | 535 js('#.prototype.#.${namer.reflectableField} = 1', |
531 [className, getterName])); | 536 [className, getterName])); |
532 } | 537 } |
533 } | 538 } |
534 | 539 |
535 void emitSetterForCSP(Element member, String fieldName, String accessorName, | 540 void emitSetterForCSP(Element member, jsAst.Name fieldName, |
541 jsAst.Name accessorName, | |
536 ClassBuilder builder) { | 542 ClassBuilder builder) { |
537 jsAst.Expression function = | 543 jsAst.Expression function = |
538 _stubGenerator.generateSetter(member, fieldName); | 544 _stubGenerator.generateSetter(member, fieldName); |
539 | 545 |
540 String setterName = namer.deriveSetterName(accessorName); | 546 jsAst.Name setterName = namer.deriveSetterName(accessorName); |
541 ClassElement cls = member.enclosingClass; | 547 ClassElement cls = member.enclosingClass; |
542 String className = namer.className(cls); | 548 jsAst.Name className = namer.className(cls); |
543 OutputUnit outputUnit = | 549 OutputUnit outputUnit = |
544 compiler.deferredLoadTask.outputUnitForElement(member); | 550 compiler.deferredLoadTask.outputUnitForElement(member); |
545 emitter.cspPrecompiledFunctionFor(outputUnit).add( | 551 emitter.cspPrecompiledFunctionFor(outputUnit).add( |
546 js('#.prototype.# = #', [className, setterName, function])); | 552 js('#.prototype.# = #', [className, setterName, function])); |
547 if (backend.isAccessibleByReflection(member)) { | 553 if (backend.isAccessibleByReflection(member)) { |
548 emitter.cspPrecompiledFunctionFor(outputUnit).add( | 554 emitter.cspPrecompiledFunctionFor(outputUnit).add( |
549 js('#.prototype.#.${namer.reflectableField} = 1', | 555 js('#.prototype.#.${namer.reflectableField} = 1', |
550 [className, setterName])); | 556 [className, setterName])); |
551 } | 557 } |
552 } | 558 } |
553 | 559 |
554 void generateReflectionDataForFieldGetterOrSetter(Element member, | 560 void generateReflectionDataForFieldGetterOrSetter(Element member, |
555 String name, | 561 jsAst.Name name, |
556 ClassBuilder builder, | 562 ClassBuilder builder, |
557 {bool isGetter}) { | 563 {bool isGetter}) { |
558 Selector selector = isGetter | 564 Selector selector = isGetter |
559 ? new Selector.getter(member.name, member.library) | 565 ? new Selector.getter(member.name, member.library) |
560 : new Selector.setter(member.name, member.library); | 566 : new Selector.setter(member.name, member.library); |
561 String reflectionName = emitter.getReflectionName(selector, name); | 567 String reflectionName = emitter.getReflectionName(selector, name); |
562 if (reflectionName != null) { | 568 if (reflectionName != null) { |
563 var reflectable = | 569 var reflectable = |
564 js(backend.isAccessibleByReflection(member) ? '1' : '0'); | 570 js(backend.isAccessibleByReflection(member) ? '1' : '0'); |
565 builder.addProperty('+$reflectionName', reflectable); | 571 builder.addPropertyByName('+$reflectionName', reflectable); |
566 } | 572 } |
567 } | 573 } |
568 } | 574 } |
OLD | NEW |