Skip to content

Commit a6cc7b9

Browse files
vsmenoncommit-bot@chromium.org
authored andcommitted
Reland "[dartdevc] fix for const / overridden fields"
This reverts commit 43cacaf. Patchset 1 is the original CL. Compare PS 1 to 4 to see additional fix. It undoes an optimization that assumes private fields are not overridden in the SDK. This patterns happens in dart:ui and would be difficult to enforce now that flutter web also adds to the SDK. As a result, all private SDK fields are virtualized, adding 0.7% to the size of dart_sdk.js. Fixes #38455 Change-Id: If969dddcb7143316ac8c771df1ed83def21412b2 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/118362 Commit-Queue: Vijay Menon <[email protected]> Reviewed-by: Nate Bosch <[email protected]>
1 parent 4167867 commit a6cc7b9

File tree

4 files changed

+54
-11
lines changed

4 files changed

+54
-11
lines changed

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

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -252,6 +252,7 @@ abstract class SharedCompiler<Library, Class, InterfaceType, FunctionNode> {
252252
/// runtime call.
253253
js_ast.TemporaryId initPrivateNameSymbol() {
254254
var idName = name.endsWith('=') ? name.replaceAll('=', '_') : name;
255+
idName = idName.replaceAll('.', '_');
255256
var id = js_ast.TemporaryId(idName);
256257
moduleItems.add(js.statement('const # = #.privateName(#, #)',
257258
[id, runtimeModule, emitLibraryName(library), js.string(name)]));
@@ -262,6 +263,17 @@ abstract class SharedCompiler<Library, Class, InterfaceType, FunctionNode> {
262263
return privateNames.putIfAbsent(name, initPrivateNameSymbol);
263264
}
264265

266+
/// Emits a private name JS Symbol for [memberName] unique to a Dart
267+
/// class [className].
268+
///
269+
/// This is now required for fields of constant objects that may be
270+
/// overridden within the same library.
271+
@protected
272+
js_ast.TemporaryId emitClassPrivateNameSymbol(
273+
Library library, String className, String memberName) {
274+
return emitPrivateNameSymbol(library, '$className.$memberName');
275+
}
276+
265277
/// Emits an expression to set the property [nameExpr] on the class [className],
266278
/// with [value].
267279
///

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

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2796,10 +2796,9 @@ class ProgramCompiler extends ComputeOnceConstantVisitor<js_ast.Expression>
27962796

27972797
void _emitVirtualFieldSymbols(Class c, List<js_ast.Statement> body) {
27982798
_classProperties.virtualFields.forEach((field, virtualField) {
2799-
body.add(js.statement('const # = Symbol(#);', [
2800-
virtualField,
2801-
js.string('${getLocalClassName(c)}.${field.name.name}')
2802-
]));
2799+
var symbol = emitClassPrivateNameSymbol(
2800+
c.enclosingLibrary, getLocalClassName(c), field.name.name);
2801+
body.add(js.statement('const # = #;', [virtualField, symbol]));
28032802
});
28042803
}
28052804

@@ -5413,8 +5412,15 @@ class ProgramCompiler extends ComputeOnceConstantVisitor<js_ast.Expression>
54135412
entryToProperty(MapEntry<Reference, Constant> entry) {
54145413
var constant = visitConstant(entry.value);
54155414
var member = entry.key.asField;
5416-
return js_ast.Property(
5417-
_emitMemberName(member.name.name, member: member), constant);
5415+
var cls = member.enclosingClass;
5416+
// Enums cannot be overridden, so we can safely use the field name
5417+
// directly. Otherwise, use a private symbol in case the field
5418+
// was overridden.
5419+
var symbol = cls.isEnum
5420+
? _emitMemberName(member.name.name, member: member)
5421+
: emitClassPrivateNameSymbol(
5422+
cls.enclosingLibrary, getLocalClassName(cls), member.name.name);
5423+
return js_ast.Property(symbol, constant);
54185424
}
54195425

54205426
var type = visitInterfaceType(node.getType(_types) as InterfaceType);

pkg/dev_compiler/lib/src/kernel/property_model.dart

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -147,11 +147,6 @@ class _LibraryVirtualFieldModel {
147147
// Enums are not extensible.
148148
return false;
149149
}
150-
var libraryUri = class_.enclosingLibrary.importUri;
151-
if (libraryUri.scheme == 'dart' && libraryUri.path.startsWith('_')) {
152-
// There should be no extensible fields in private SDK libraries.
153-
return false;
154-
}
155150

156151
if (!field.name.isPrivate) {
157152
// Public fields in public classes (or extensible private classes)
@@ -161,6 +156,13 @@ class _LibraryVirtualFieldModel {
161156
if (_extensiblePrivateClasses.contains(class_)) return true;
162157
}
163158

159+
if (class_.constructors.any((c) => c.isConst)) {
160+
// Always virtualize fields of a (might be) non-enum (see above) const
161+
// class. The way these are lowered by the CFE, they need to be
162+
// writable from different modules even if overridden.
163+
return true;
164+
}
165+
164166
// Otherwise, the field is effectively private and we only need to make it
165167
// virtual if it's overridden.
166168
return _overriddenPrivateFields.contains(field);
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
// Copyright (c) 2019, 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+
// Dart test checking that static/instance field shadowing do not conflict.
5+
6+
import 'package:expect/expect.dart';
7+
8+
class A {
9+
final field;
10+
const A(this.field);
11+
}
12+
13+
class B extends A {
14+
final field;
15+
const B(this.field, fieldA) : super(fieldA);
16+
get fieldA => super.field;
17+
}
18+
19+
main() {
20+
const b = B(1, 2);
21+
Expect.equals(1, b.field);
22+
Expect.equals(2, b.fieldA);
23+
}

0 commit comments

Comments
 (0)