Skip to content

Commit d109467

Browse files
Use lazy static fields when overriding static getters or setters.
Fixes #522 [email protected] Review URL: https://codereview.chromium.org/1927353002 .
1 parent 8c745c6 commit d109467

File tree

5 files changed

+87
-19
lines changed

5 files changed

+87
-19
lines changed

pkg/dev_compiler/lib/src/compiler/code_generator.dart

Lines changed: 31 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -546,13 +546,14 @@ class CodeGenerator extends GeneralizingAstVisitor
546546
className = _emitTopLevelName(classElem);
547547
}
548548

549+
var allFields = new List.from(fields)..addAll(staticFields);
549550
var superclasses = getSuperclasses(classElem);
550551
var virtualFields = <FieldElement, JS.TemporaryId>{};
551552
var virtualFieldSymbols = <JS.Statement>[];
552-
_registerVirtualFields(classElem, className, superclasses, fields,
553-
virtualFields, virtualFieldSymbols);
553+
var staticFieldOverrides = new HashSet<FieldElement>();
554+
_registerPropertyOverrides(classElem, className, superclasses, allFields,
555+
virtualFields, virtualFieldSymbols, staticFieldOverrides);
554556

555-
var allFields = new List.from(fields)..addAll(staticFields);
556557
var classExpr = _emitClassExpression(classElem,
557558
_emitClassMethods(node, ctors, fields, superclasses, virtualFields),
558559
fields: allFields);
@@ -579,30 +580,35 @@ class CodeGenerator extends GeneralizingAstVisitor
579580
}
580581

581582
body = <JS.Statement>[classDef];
582-
_emitStaticFields(staticFields, classElem, body);
583+
_emitStaticFields(staticFields, staticFieldOverrides, classElem, body);
583584
_registerExtensionType(classElem, body);
584585
return _statement(body);
585586
}
586587

587-
void _registerVirtualFields(
588+
void _registerPropertyOverrides(
588589
ClassElement classElem,
589590
JS.Expression className,
590591
List<ClassElement> superclasses,
591592
List<FieldDeclaration> fields,
592593
Map<FieldElement, JS.TemporaryId> virtualFields,
593-
List<JS.Statement> virtualFieldSymbols) {
594+
List<JS.Statement> virtualFieldSymbols,
595+
Set<FieldElement> staticFieldOverrides) {
594596
for (var field in fields) {
595597
for (VariableDeclaration field in field.fields.variables) {
596598
var overrideInfo = checkForPropertyOverride(
597599
field.element, superclasses, _extensionTypes);
598600
if (overrideInfo.foundGetter || overrideInfo.foundSetter) {
599-
var fieldName =
600-
_emitMemberName(field.element.name, type: classElem.type);
601-
var virtualField = new JS.TemporaryId(field.element.name);
602-
virtualFields[field.element] = virtualField;
603-
virtualFieldSymbols.add(js.statement(
604-
'const # = Symbol(#.name + "." + #.toString());',
605-
[virtualField, className, fieldName]));
601+
if (field.element.isStatic) {
602+
staticFieldOverrides.add(field.element);
603+
} else {
604+
var fieldName =
605+
_emitMemberName(field.element.name, type: classElem.type);
606+
var virtualField = new JS.TemporaryId(field.element.name);
607+
virtualFields[field.element] = virtualField;
608+
virtualFieldSymbols.add(js.statement(
609+
'const # = Symbol(#.name + "." + #.toString());',
610+
[virtualField, className, fieldName]));
611+
}
606612
}
607613
}
608614
}
@@ -1012,12 +1018,16 @@ class CodeGenerator extends GeneralizingAstVisitor
10121018

10131019
/// Emits static fields for a class, and initialize them eagerly if possible,
10141020
/// otherwise define them as lazy properties.
1015-
void _emitStaticFields(List<FieldDeclaration> staticFields,
1016-
ClassElement classElem, List<JS.Statement> body) {
1021+
void _emitStaticFields(
1022+
List<FieldDeclaration> staticFields,
1023+
Set<FieldElement> staticFieldOverrides,
1024+
ClassElement classElem,
1025+
List<JS.Statement> body) {
10171026
var lazyStatics = <VariableDeclaration>[];
10181027
for (FieldDeclaration member in staticFields) {
10191028
for (VariableDeclaration field in member.fields.variables) {
1020-
JS.Statement eagerField = _emitConstantStaticField(classElem, field);
1029+
JS.Statement eagerField =
1030+
_emitConstantStaticField(classElem, field, staticFieldOverrides);
10211031
if (eagerField != null) {
10221032
body.add(eagerField);
10231033
} else {
@@ -2573,8 +2583,8 @@ class CodeGenerator extends GeneralizingAstVisitor
25732583
/// Otherwise, we'll need to generate a lazy-static field. That ensures
25742584
/// correct visible behavior, as well as avoiding referencing something that
25752585
/// isn't defined yet (because it is defined later in the module).
2576-
JS.Statement _emitConstantStaticField(
2577-
ClassElement classElem, VariableDeclaration field) {
2586+
JS.Statement _emitConstantStaticField(ClassElement classElem,
2587+
VariableDeclaration field, Set<FieldElement> staticFieldOverrides) {
25782588
PropertyInducingElement element = field.element;
25792589
assert(element.isStatic);
25802590

@@ -2586,7 +2596,9 @@ class CodeGenerator extends GeneralizingAstVisitor
25862596
isLoaded && (field.isConst || _constField.isFieldInitConstant(field));
25872597

25882598
var fieldName = field.name.name;
2589-
if (eagerInit && !JS.invalidStaticFieldName(fieldName)) {
2599+
if (eagerInit &&
2600+
!JS.invalidStaticFieldName(fieldName) &&
2601+
!staticFieldOverrides.contains(element)) {
25902602
return annotate(
25912603
js.statement('#.# = #;', [
25922604
_emitTopLevelName(classElem),

pkg/dev_compiler/lib/src/compiler/js_field_storage.dart

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,10 @@ PropertyOverrideResult checkForPropertyOverride(FieldElement field,
2828
var superprop = getProperty(superclass, field.library, field.name);
2929
if (superprop == null) continue;
3030

31+
// Static fields can override superclass static fields. However, we need to
32+
// handle the case where they override a getter or setter.
33+
if (field.isStatic && !superprop.isSynthetic) continue;
34+
3135
var getter = superprop.getter;
3236
bool hasGetter = getter != null && !getter.isAbstract;
3337
if (hasGetter) foundGetter = true;
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file
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.
4+
5+
import 'package:expect/expect.dart';
6+
7+
class Foo {
8+
static int get x => 42;
9+
}
10+
11+
class Bar extends Foo {
12+
static int x = 12;
13+
}
14+
15+
void main() {
16+
Expect.equals(12, Bar.x);
17+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file
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.
4+
5+
import 'package:expect/expect.dart';
6+
7+
class Foo {
8+
static int get x => 42;
9+
static void set x(value) {}
10+
}
11+
12+
class Bar extends Foo {
13+
static int x = 12;
14+
}
15+
16+
void main() {
17+
Expect.equals(12, Bar.x);
18+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file
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.
4+
5+
import 'package:expect/expect.dart';
6+
7+
class Foo {
8+
static int x = 42;
9+
}
10+
11+
class Bar extends Foo {
12+
static int x = 12;
13+
}
14+
15+
void main() {
16+
Expect.equals(12, Bar.x);
17+
}

0 commit comments

Comments
 (0)