[dartdevc] fix #36275, emit members whose names are from other libraries
Dart interfaces can contain private member names that aren't accessible
in the current library. This is represented in Kernel as a stub that
throws (similar to the stubs used when noSuchMethod is present on a
class, typically used for mocks). DDC's Kernel backend did not
understsand that private members could belong to a different library.
This CL addresses it.
Note, this fix does not fix private names across modules. That is
covered by issue #36252 and will be addressed on top of this fix.
Change-Id: Id77d5de15d8d7ec5e44fc0f1264ced5e786636ae
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/97441
Reviewed-by: Nicholas Shahan <nshahan@google.com>
Reviewed-by: Jake Macdonald <jakemac@google.com>
Commit-Queue: Jenny Messerly <jmesserly@google.com>
diff --git a/pkg/dev_compiler/lib/src/compiler/shared_compiler.dart b/pkg/dev_compiler/lib/src/compiler/shared_compiler.dart
index b6d91c6..7b6aae5 100644
--- a/pkg/dev_compiler/lib/src/compiler/shared_compiler.dart
+++ b/pkg/dev_compiler/lib/src/compiler/shared_compiler.dart
@@ -185,6 +185,18 @@
/// of their library.
@protected
JS.TemporaryId emitPrivateNameSymbol(Library library, String name) {
+ // TODO(jmesserly): fix this to support referring to private symbols from
+ // libraries that aren't in the current module.
+ //
+ // This is needed for several uses cases:
+ // - const instances of classes (which directly initialize fields via an
+ // object literal).
+ // - noSuchMethod stubs created when an interface is implemented that had
+ // private members from another library.
+ // - stateful hot reload, where we need the ability to patch private
+ // class members.
+ //
+ // See https://github.com/dart-lang/sdk/issues/36252
return _privateNames.putIfAbsent(library, () => HashMap()).putIfAbsent(name,
() {
var idName = name;
diff --git a/pkg/dev_compiler/lib/src/kernel/compiler.dart b/pkg/dev_compiler/lib/src/kernel/compiler.dart
index bf0899a..36e9d0c 100644
--- a/pkg/dev_compiler/lib/src/kernel/compiler.dart
+++ b/pkg/dev_compiler/lib/src/kernel/compiler.dart
@@ -2215,11 +2215,15 @@
}
}
+ memberClass ??= member?.enclosingClass;
if (name.startsWith('_')) {
- return emitPrivateNameSymbol(_currentLibrary, name);
+ // Use the library that this private member's name is scoped to.
+ var memberLibrary = member?.name?.library ??
+ memberClass?.enclosingLibrary ??
+ _currentLibrary;
+ return emitPrivateNameSymbol(memberLibrary, name);
}
- memberClass ??= member?.enclosingClass;
useExtension ??= _isSymbolizedMember(memberClass, name);
name = JS.memberNameForDartMember(
name, member is Procedure && member.isExternal);
@@ -5157,11 +5161,8 @@
var field = entry.key.asField.name.name;
var constant = entry.value.accept(this);
var member = entry.key.asField;
- var prevLibrary = _currentLibrary;
- _currentLibrary = member.enclosingLibrary;
var result =
JS.Property(_emitMemberName(field, member: member), constant);
- _currentLibrary = prevLibrary;
return result;
}