Skip to content

Commit 77f53f6

Browse files
author
Jennifer Messerly
committed
fixes #27385, implement virtual fields in DDC
If a field is marked @virtual in Analyzer, DDC will allow it to be overridden as well also fixes #28114, abstract getters/setters broke generation of forwarding getters/setters [email protected] Review-Url: https://codereview.chromium.org/2571363002 .
1 parent 9506cb9 commit 77f53f6

21 files changed

+229
-178
lines changed

pkg/dev_compiler/lib/js/amd/dart_sdk.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -521,8 +521,8 @@ define([], function() {
521521
let CompleterOfString = () => (CompleterOfString = dart.constFn(async.Completer$(core.String)))();
522522
let CompleterOfMetadata = () => (CompleterOfMetadata = dart.constFn(async.Completer$(html$.Metadata)))();
523523
let CompleterOfListOfEntry = () => (CompleterOfListOfEntry = dart.constFn(async.Completer$(ListOfEntry())))();
524-
let ListOfStyleSheet = () => (ListOfStyleSheet = dart.constFn(core.List$(html$.StyleSheet)))();
525524
let EventStreamProviderOfSecurityPolicyViolationEvent = () => (EventStreamProviderOfSecurityPolicyViolationEvent = dart.constFn(html$.EventStreamProvider$(html$.SecurityPolicyViolationEvent)))();
525+
let ListOfStyleSheet = () => (ListOfStyleSheet = dart.constFn(core.List$(html$.StyleSheet)))();
526526
let ImmutableListMixin = () => (ImmutableListMixin = dart.constFn(html$.ImmutableListMixin$()))();
527527
let ElementAndElementToint = () => (ElementAndElementToint = dart.constFn(dart.functionType(core.int, [html$.Element, html$.Element])))();
528528
let ElementTobool = () => (ElementTobool = dart.constFn(dart.functionType(core.bool, [html$.Element])))();

pkg/dev_compiler/lib/js/common/dart_sdk.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -521,8 +521,8 @@
521521
let CompleterOfString = () => (CompleterOfString = dart.constFn(async.Completer$(core.String)))();
522522
let CompleterOfMetadata = () => (CompleterOfMetadata = dart.constFn(async.Completer$(html$.Metadata)))();
523523
let CompleterOfListOfEntry = () => (CompleterOfListOfEntry = dart.constFn(async.Completer$(ListOfEntry())))();
524-
let ListOfStyleSheet = () => (ListOfStyleSheet = dart.constFn(core.List$(html$.StyleSheet)))();
525524
let EventStreamProviderOfSecurityPolicyViolationEvent = () => (EventStreamProviderOfSecurityPolicyViolationEvent = dart.constFn(html$.EventStreamProvider$(html$.SecurityPolicyViolationEvent)))();
525+
let ListOfStyleSheet = () => (ListOfStyleSheet = dart.constFn(core.List$(html$.StyleSheet)))();
526526
let ImmutableListMixin = () => (ImmutableListMixin = dart.constFn(html$.ImmutableListMixin$()))();
527527
let ElementAndElementToint = () => (ElementAndElementToint = dart.constFn(dart.functionType(core.int, [html$.Element, html$.Element])))();
528528
let ElementTobool = () => (ElementTobool = dart.constFn(dart.functionType(core.bool, [html$.Element])))();

pkg/dev_compiler/lib/js/es6/dart_sdk.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -519,8 +519,8 @@ let ListOfFile = () => (ListOfFile = dart.constFn(core.List$(html.File)))();
519519
let CompleterOfString = () => (CompleterOfString = dart.constFn(async.Completer$(core.String)))();
520520
let CompleterOfMetadata = () => (CompleterOfMetadata = dart.constFn(async.Completer$(html.Metadata)))();
521521
let CompleterOfListOfEntry = () => (CompleterOfListOfEntry = dart.constFn(async.Completer$(ListOfEntry())))();
522-
let ListOfStyleSheet = () => (ListOfStyleSheet = dart.constFn(core.List$(html.StyleSheet)))();
523522
let EventStreamProviderOfSecurityPolicyViolationEvent = () => (EventStreamProviderOfSecurityPolicyViolationEvent = dart.constFn(html.EventStreamProvider$(html.SecurityPolicyViolationEvent)))();
523+
let ListOfStyleSheet = () => (ListOfStyleSheet = dart.constFn(core.List$(html.StyleSheet)))();
524524
let ImmutableListMixin = () => (ImmutableListMixin = dart.constFn(html.ImmutableListMixin$()))();
525525
let ElementAndElementToint = () => (ElementAndElementToint = dart.constFn(dart.functionType(core.int, [html.Element, html.Element])))();
526526
let ElementTobool = () => (ElementTobool = dart.constFn(dart.functionType(core.bool, [html.Element])))();

pkg/dev_compiler/lib/js/legacy/dart_sdk.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -522,8 +522,8 @@ dart_library.library('dart_sdk', null, /* Imports */[
522522
let CompleterOfString = () => (CompleterOfString = dart.constFn(async.Completer$(core.String)))();
523523
let CompleterOfMetadata = () => (CompleterOfMetadata = dart.constFn(async.Completer$(html$.Metadata)))();
524524
let CompleterOfListOfEntry = () => (CompleterOfListOfEntry = dart.constFn(async.Completer$(ListOfEntry())))();
525-
let ListOfStyleSheet = () => (ListOfStyleSheet = dart.constFn(core.List$(html$.StyleSheet)))();
526525
let EventStreamProviderOfSecurityPolicyViolationEvent = () => (EventStreamProviderOfSecurityPolicyViolationEvent = dart.constFn(html$.EventStreamProvider$(html$.SecurityPolicyViolationEvent)))();
526+
let ListOfStyleSheet = () => (ListOfStyleSheet = dart.constFn(core.List$(html$.StyleSheet)))();
527527
let ImmutableListMixin = () => (ImmutableListMixin = dart.constFn(html$.ImmutableListMixin$()))();
528528
let ElementAndElementToint = () => (ElementAndElementToint = dart.constFn(dart.functionType(core.int, [html$.Element, html$.Element])))();
529529
let ElementTobool = () => (ElementTobool = dart.constFn(dart.functionType(core.bool, [html$.Element])))();
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
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 'dart:collection' show HashSet;
6+
7+
import 'package:analyzer/dart/ast/ast.dart' show Identifier;
8+
import 'package:analyzer/dart/element/element.dart';
9+
import 'package:analyzer/src/dart/element/element.dart' show FieldElementImpl;
10+
11+
import '../js_ast/js_ast.dart' as JS;
12+
import 'element_helpers.dart';
13+
import 'js_names.dart' as JS;
14+
15+
/// Tracks how fields, getters and setters are represented when emitting JS.
16+
///
17+
/// Dart classes have implicit features that must be made explicit:
18+
///
19+
/// - virtual fields induce a getter and setter pair.
20+
/// - getters and setters are independent.
21+
/// - getters and setters can be overridden.
22+
///
23+
class ClassPropertyModel {
24+
/// Fields that are virtual, that is, they must be generated as a property
25+
/// pair in JavaScript.
26+
///
27+
/// The value property stores the symbol used for the field's storage slot.
28+
final virtualFields = <FieldElement, JS.TemporaryId>{};
29+
30+
/// Static fields that are overridden, this does not matter for Dart but in
31+
/// JS we need to take care initializing these because JS classes inherit
32+
/// statics.
33+
final staticFieldOverrides = new HashSet<FieldElement>();
34+
35+
/// The set of inherited getters, used because JS getters/setters are paired,
36+
/// so if we're generating a setter we may need to emit a getter that calls
37+
/// super.
38+
final inheritedGetters = new HashSet<String>();
39+
40+
/// The set of inherited setters, used because JS getters/setters are paired,
41+
/// so if we're generating a getter we may need to emit a setter that calls
42+
/// super.
43+
final inheritedSetters = new HashSet<String>();
44+
45+
ClassPropertyModel.build(
46+
ClassElement classElem, Iterable<ExecutableElement> extensionMembers) {
47+
// Visit superclasses to collect information about their fields/accessors.
48+
// This is expensive so we try to collect everything in one pass.
49+
for (var base in getSuperclasses(classElem)) {
50+
for (var accessor in base.accessors) {
51+
// For getter/setter pairs only process them once.
52+
if (accessor.correspondingGetter != null) continue;
53+
54+
var field = accessor.variable;
55+
var name = field.name;
56+
// Ignore private names from other libraries.
57+
if (Identifier.isPrivateName(name) &&
58+
accessor.library != classElem.library) {
59+
continue;
60+
}
61+
62+
if (field.getter?.isAbstract == false) inheritedGetters.add(name);
63+
if (field.setter?.isAbstract == false) inheritedSetters.add(name);
64+
}
65+
}
66+
67+
var extensionNames =
68+
new HashSet<String>.from(extensionMembers.map((e) => e.name));
69+
70+
// Visit accessors in the current class, and see if they need to be
71+
// generated differently based on the inherited fields/accessors.
72+
for (var accessor in classElem.accessors) {
73+
// For getter/setter pairs only process them once.
74+
if (accessor.correspondingGetter != null) continue;
75+
// Also ignore abstract fields.
76+
if (accessor.isAbstract) continue;
77+
78+
var field = accessor.variable;
79+
var name = field.name;
80+
// Is it a field?
81+
if (!field.isSynthetic && field is FieldElementImpl) {
82+
if (inheritedGetters.contains(name) ||
83+
inheritedSetters.contains(name) ||
84+
extensionNames.contains(name) ||
85+
field.isVirtual) {
86+
if (field.isStatic) {
87+
staticFieldOverrides.add(field);
88+
} else {
89+
virtualFields[field] = new JS.TemporaryId(name);
90+
}
91+
}
92+
}
93+
}
94+
}
95+
}

0 commit comments

Comments
 (0)