| Index: lib/src/codegen/js_codegen.dart
|
| diff --git a/lib/src/codegen/js_codegen.dart b/lib/src/codegen/js_codegen.dart
|
| index 3ba321bf2cf8936668f328652fe4584bbd0bc3b7..1001919b230e95cf381b9b78c332f55e610cef53 100644
|
| --- a/lib/src/codegen/js_codegen.dart
|
| +++ b/lib/src/codegen/js_codegen.dart
|
| @@ -669,7 +669,12 @@ class JSCodegenVisitor extends GeneralizingAstVisitor with ConversionVisitor {
|
| // Generate optional/named argument value assignment. These can not have
|
| // side effects, and may be used by the constructor's initializers, so it's
|
| // nice to do them first.
|
| + // Also for const constructors we need to ensure default values are
|
| + // available for use by top-level constant initializers.
|
| + ClassDeclaration cls = node.parent;
|
| + if (node.constKeyword != null) _loader.startTopLevel(cls.element);
|
| var init = _emitArgumentInitializers(node, constructor: true);
|
| + if (node.constKeyword != null) _loader.finishTopLevel(cls.element);
|
| if (init != null) body.add(init);
|
|
|
| // Redirecting constructors: these are not allowed to have initializers,
|
| @@ -688,7 +693,7 @@ class JSCodegenVisitor extends GeneralizingAstVisitor with ConversionVisitor {
|
| // These are expanded into each non-redirecting constructor.
|
| // In the future we may want to create an initializer function if we have
|
| // multiple constructors, but it needs to be balanced against readability.
|
| - body.add(_initializeFields(node, fields));
|
| + body.add(_initializeFields(node.parent, fields, node));
|
|
|
| var superCall = node.initializers.firstWhere(
|
| (i) => i is SuperConstructorInvocation, orElse: () => null);
|
| @@ -753,9 +758,12 @@ class JSCodegenVisitor extends GeneralizingAstVisitor with ConversionVisitor {
|
| /// 3. constructor field initializers,
|
| /// 4. initialize fields not covered in 1-3
|
| JS.Statement _initializeFields(
|
| - AstNode node, List<FieldDeclaration> fieldDecls) {
|
| - var unit = node.getAncestor((a) => a is CompilationUnit);
|
| + ClassDeclaration cls, List<FieldDeclaration> fieldDecls,
|
| + [ConstructorDeclaration ctor]) {
|
| + var unit = cls.getAncestor((a) => a is CompilationUnit);
|
| var constField = new ConstFieldVisitor(types, unit);
|
| + bool isConst = ctor != null && ctor.constKeyword != null;
|
| + if (isConst) _loader.startTopLevel(cls.element);
|
|
|
| // Run field initializers if they can have side-effects.
|
| var fields = new Map<FieldElement, JS.Expression>();
|
| @@ -772,11 +780,8 @@ class JSCodegenVisitor extends GeneralizingAstVisitor with ConversionVisitor {
|
| }
|
|
|
| // Initialize fields from `this.fieldName` parameters.
|
| - if (node is ConstructorDeclaration) {
|
| - var parameters = node.parameters;
|
| - var initializers = node.initializers;
|
| -
|
| - for (var p in parameters.parameters) {
|
| + if (ctor != null) {
|
| + for (var p in ctor.parameters.parameters) {
|
| var element = p.element;
|
| if (element is FieldFormalParameterElement) {
|
| fields[element.field] = _visit(p);
|
| @@ -784,7 +789,7 @@ class JSCodegenVisitor extends GeneralizingAstVisitor with ConversionVisitor {
|
| }
|
|
|
| // Run constructor field initializers such as `: foo = bar.baz`
|
| - for (var init in initializers) {
|
| + for (var init in ctor.initializers) {
|
| if (init is ConstructorFieldInitializer) {
|
| fields[init.fieldName.staticElement] = _visit(init.expression);
|
| }
|
| @@ -813,6 +818,8 @@ class JSCodegenVisitor extends GeneralizingAstVisitor with ConversionVisitor {
|
| var access = _emitMemberName(e.name, type: e.enclosingElement.type);
|
| body.add(js.statement('this.# = #;', [access, initialValue]));
|
| });
|
| +
|
| + if (isConst) _loader.finishTopLevel(cls.element);
|
| return _statement(body);
|
| }
|
|
|
| @@ -1890,7 +1897,11 @@ class JSCodegenVisitor extends GeneralizingAstVisitor with ConversionVisitor {
|
| /// Shared code for [PrefixedIdentifier] and [PropertyAccess].
|
| JS.Expression _emitGet(Expression target, SimpleIdentifier memberId) {
|
| var member = memberId.staticElement;
|
| - bool isStatic = member is ExecutableElement && member.isStatic;
|
| + if (member is PropertyAccessorElement) member = member.variable;
|
| + bool isStatic = member is ClassMemberElement && member.isStatic;
|
| + if (isStatic) {
|
| + _loader.declareBeforeUse(member);
|
| + }
|
| var name = _emitMemberName(memberId.name,
|
| type: getStaticType(target), isStatic: isStatic);
|
| if (rules.isDynamicTarget(target)) {
|
|
|