| Index: pkg/dev_compiler/lib/src/compiler/code_generator.dart
|
| diff --git a/pkg/dev_compiler/lib/src/compiler/code_generator.dart b/pkg/dev_compiler/lib/src/compiler/code_generator.dart
|
| index 9843eb0b3be33f42817b135b573bae128b498e44..8109eac8b73e06af0bc9eb9d8603a35eb6b11615 100644
|
| --- a/pkg/dev_compiler/lib/src/compiler/code_generator.dart
|
| +++ b/pkg/dev_compiler/lib/src/compiler/code_generator.dart
|
| @@ -1303,11 +1303,10 @@ class CodeGenerator extends Object
|
| // TODO(jacobr): make field readonly when that is supported.
|
| var tInstanceFields = <JS.Property>[
|
| new JS.Property(
|
| - _emitMemberName('index'), _emitAnnotatedType(intClass.type, null))
|
| - ];
|
| - var sigFields = <JS.Property>[
|
| - _buildSignatureField('fields', tInstanceFields)
|
| + _emitMemberName('index'), _emitFieldSignature(types.intType))
|
| ];
|
| + var sigFields = <JS.Property>[];
|
| + _buildSignatureField(sigFields, 'fields', tInstanceFields);
|
| var sig = new JS.ObjectInitializer(sigFields);
|
|
|
| var result = [
|
| @@ -1846,11 +1845,13 @@ class CodeGenerator extends Object
|
| emitExtensions(className, _classProperties.extensionMembers);
|
| }
|
|
|
| - JS.Property _buildSignatureField(String name, List<JS.Property> elements) {
|
| + void _buildSignatureField(
|
| + List<JS.Property> sigFields, String name, List<JS.Property> elements) {
|
| + if (elements.isEmpty) return;
|
| var o = new JS.ObjectInitializer(elements, multiline: elements.length > 1);
|
| // TODO(vsm): Remove
|
| var e = js.call('() => #', o);
|
| - return new JS.Property(_propertyName(name), e);
|
| + sigFields.add(new JS.Property(_propertyName(name), e));
|
| }
|
|
|
| /// Emit the signature on the class recording the runtime type information
|
| @@ -1884,15 +1885,23 @@ class CodeGenerator extends Object
|
| if (node.isAbstract) {
|
| continue;
|
| }
|
| - if (node.isStatic &&
|
| - !options.emitMetadata &&
|
| + // Static getters/setters cannot be called with dynamic dispatch, nor
|
| + // can they be torn off.
|
| + // TODO(jmesserly): can we attach static method type info at the tearoff
|
| + // point, and avoid saving the information otherwise? Same trick would
|
| + // work for top-level functions.
|
| + if (!options.emitMetadata &&
|
| + node.isStatic &&
|
| (node.isGetter || node.isSetter)) {
|
| continue;
|
| }
|
| List<JS.Property> tMember;
|
| + // TODO(jmesserly): these 3 variables should be typed.
|
| Function getOverride;
|
| Function lookup;
|
| Function elementToType;
|
| + // TODO(jmesserly): we could reduce work by not saving a full function
|
| + // type for getters/setters. These only need 1 type to be saved.
|
| if (node.isGetter) {
|
| elementToType = (ExecutableElement element) => element.type;
|
| getOverride = classElem.lookUpInheritedConcreteGetter;
|
| @@ -1935,7 +1944,7 @@ class CodeGenerator extends Object
|
| var memberName = _declareMemberName(element);
|
| var property = new JS.Property(memberName, type);
|
| tMember.add(property);
|
| - // We record the names of static methods seperately so we can
|
| + // We record the names of static methods separately so we can
|
| // attach metadata to them individually.
|
| // TODO(leafp): Revisit this.
|
| if (node.isStatic && !node.isGetter && !node.isSetter) {
|
| @@ -1947,13 +1956,17 @@ class CodeGenerator extends Object
|
| var tInstanceFields = <JS.Property>[];
|
| var tStaticFields = <JS.Property>[];
|
| for (FieldDeclaration node in fields) {
|
| - if (!node.isStatic || options.emitMetadata) {
|
| + // Only instance fields need to be saved for dynamic dispatch.
|
| + var isStatic = node.isStatic;
|
| + if (options.emitMetadata || !isStatic) {
|
| for (VariableDeclaration field in node.fields.variables) {
|
| var element = field.element as FieldElement;
|
| + var fieldList = isStatic ? tStaticFields : tInstanceFields;
|
| +
|
| var memberName = _declareMemberName(element.getter);
|
| - var type = _emitAnnotatedType(element.type, node.metadata);
|
| - var property = new JS.Property(memberName, type);
|
| - (node.isStatic ? tStaticFields : tInstanceFields).add(property);
|
| + var fieldSig = _emitFieldSignature(element.type,
|
| + metadata: node.metadata, isFinal: element.isFinal);
|
| + fieldList.add(new JS.Property(memberName, fieldSig));
|
| }
|
| }
|
| }
|
| @@ -1974,38 +1987,21 @@ class CodeGenerator extends Object
|
| }
|
| }
|
| var sigFields = <JS.Property>[];
|
| - if (!tCtors.isEmpty) {
|
| - sigFields.add(_buildSignatureField('constructors', tCtors));
|
| - }
|
| - if (!tInstanceFields.isEmpty) {
|
| - sigFields.add(_buildSignatureField('fields', tInstanceFields));
|
| - }
|
| - if (!tInstanceGetters.isEmpty) {
|
| - sigFields.add(_buildSignatureField('getters', tInstanceGetters));
|
| - }
|
| - if (!tInstanceSetters.isEmpty) {
|
| - sigFields.add(_buildSignatureField('setters', tInstanceSetters));
|
| - }
|
| - if (!tInstanceMethods.isEmpty) {
|
| - sigFields.add(_buildSignatureField('methods', tInstanceMethods));
|
| - }
|
| - if (!tStaticFields.isEmpty) {
|
| - sigFields.add(_buildSignatureField('sfields', tStaticFields));
|
| - }
|
| - if (!tStaticGetters.isEmpty) {
|
| - sigFields.add(_buildSignatureField('sgetters', tStaticGetters));
|
| - }
|
| - if (!tStaticSetters.isEmpty) {
|
| - sigFields.add(_buildSignatureField('ssetters', tStaticSetters));
|
| - }
|
| + _buildSignatureField(sigFields, 'constructors', tCtors);
|
| + _buildSignatureField(sigFields, 'fields', tInstanceFields);
|
| + _buildSignatureField(sigFields, 'getters', tInstanceGetters);
|
| + _buildSignatureField(sigFields, 'setters', tInstanceSetters);
|
| + _buildSignatureField(sigFields, 'methods', tInstanceMethods);
|
| + _buildSignatureField(sigFields, 'sfields', tStaticFields);
|
| + _buildSignatureField(sigFields, 'sgetters', tStaticGetters);
|
| + _buildSignatureField(sigFields, 'ssetters', tStaticSetters);
|
| + _buildSignatureField(sigFields, 'statics', tStaticMethods);
|
| if (!tStaticMethods.isEmpty) {
|
| assert(!sNames.isEmpty);
|
| // Emit names so that we can lazily attach metadata to statics
|
| // TODO(leafp): revisit this strategy
|
| - var aNames = new JS.Property(
|
| - _propertyName('names'), new JS.ArrayInitializer(sNames));
|
| - sigFields.add(_buildSignatureField('statics', tStaticMethods));
|
| - sigFields.add(aNames);
|
| + sigFields.add(new JS.Property(
|
| + _propertyName('names'), new JS.ArrayInitializer(sNames)));
|
| }
|
| // We set signature here, even if empty, to simplify the work of
|
| // defineExtensionMembers at runtime. See _defineExtensionMembers.
|
| @@ -2955,6 +2951,16 @@ class CodeGenerator extends Object
|
| return _emitAnnotatedResult(typeName, metadata);
|
| }
|
|
|
| + JS.Expression _emitFieldSignature(DartType type,
|
| + {List<Annotation> metadata, bool isFinal: true}) {
|
| + var args = [_emitType(type)];
|
| + if (options.emitMetadata && metadata != null && metadata.isNotEmpty) {
|
| + args.add(new JS.ArrayInitializer(
|
| + metadata.map(_instantiateAnnotation).toList()));
|
| + }
|
| + return _callHelper(isFinal ? 'finalFieldType(#)' : 'fieldType(#)', args);
|
| + }
|
| +
|
| JS.ArrayInitializer _emitTypeNames(
|
| List<DartType> types, List<FormalParameter> parameters,
|
| {bool nameType: true, bool hoistType: true}) {
|
|
|