Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(336)

Unified Diff: pkg/dev_compiler/tool/input_sdk/private/js_mirrors.dart

Issue 2410453002: Handle private members in dart:mirrors (Closed)
Patch Set: Address comments, merge Created 4 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « pkg/dev_compiler/test/browser/language_tests.js ('k') | pkg/dev_compiler/tool/sdk_expected_errors.txt » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: pkg/dev_compiler/tool/input_sdk/private/js_mirrors.dart
diff --git a/pkg/dev_compiler/tool/input_sdk/private/js_mirrors.dart b/pkg/dev_compiler/tool/input_sdk/private/js_mirrors.dart
index 84e51430724074a80011a74c0db161f005feffaf..f87c4c9d41d72ab0459ebd47ec4da36559ae6be5 100644
--- a/pkg/dev_compiler/tool/input_sdk/private/js_mirrors.dart
+++ b/pkg/dev_compiler/tool/input_sdk/private/js_mirrors.dart
@@ -73,58 +73,71 @@ dynamic _defaultConstructorType(type) {
typedef T _Lazy<T>();
+String _getNameForESSymbol(member) {
+ // Convert private JS symbol "Symbol(_foo)" to string "_foo".
+ var str = member.toString();
+ assert(str.startsWith('Symbol(') && str.endsWith(')'));
+ return str.substring(7, str.length - 1);
+}
+
+Map _toDartMap(data) {
+ if (data == null) return {};
+ var map = JS('Map', '#.map(#)', _dart, data);
+ // Note: we recorded a map from fields/methods to their type and metadata.
+ // The key is a string name for public members but an ES6 symbol for private
+ // ones. That's works nicely for dynamic operations, but dart:mirrors expects
+ // strings, so we convert back here.
+ var privateMembers = JS('', 'Object.getOwnPropertySymbols(#)', data);
+ for (var member in privateMembers) {
+ var name = _getNameForESSymbol(member);
+ map[name] = JS('', '#[#]', data, member);
+ }
+ return map;
+}
+
Map _getConstructors(obj) {
List sig = JS('', '#.getConstructorSig(#)', _dart, obj);
- if (sig == null) return {};
- return JS('', '#.map(#)', _dart, sig);
+ return _toDartMap(sig);
}
Map _getFields(obj) {
List sig = JS('', '#.getFieldSig(#)', _dart, obj);
- if (sig == null) return {};
- return JS('', '#.map(#)', _dart, sig);
+ return _toDartMap(sig);
}
Map _getMethods(obj) {
List sig = JS('', '#.getMethodSig(#)', _dart, obj);
- if (sig == null) return {};
- return JS('', '#.map(#)', _dart, sig);
+ return _toDartMap(sig);
}
Map _getGetters(obj) {
List sig = JS('', '#.getGetterSig(#)', _dart, obj);
- if (sig == null) return {};
- return JS('', '#.map(#)', _dart, sig);
+ return _toDartMap(sig);
}
Map _getSetters(obj) {
List sig = JS('', '#.getSetterSig(#)', _dart, obj);
- if (sig == null) return {};
- return JS('', '#.map(#)', _dart, sig);
+ return _toDartMap(sig);
}
Map _getStaticFields(obj) {
List sig = JS('', '#.getStaticFieldSig(#)', _dart, obj);
- if (sig == null) return {};
- return JS('', '#.map(#)', _dart, sig);
+ return _toDartMap(sig);
}
Map _getStatics(obj) {
List sig = JS('', '#.getStaticSig(#)', _dart, obj);
- if (sig == null) return {};
- return JS('', '#.map(#)', _dart, sig);
+ return _toDartMap(sig);
}
Map _getStaticGetters(obj) {
List sig = JS('', '#.getStaticGetterSig(#)', _dart, obj);
- if (sig == null) return {};
- return JS('', '#.map(#)', _dart, sig);
+ return _toDartMap(sig);
}
Map _getStaticSetters(obj) {
List sig = JS('', '#.getStaticSetterSig(#)', _dart, obj);
- if (sig == null) return {};
- return JS('', '#.map(#)', _dart, sig);
+ return _toDartMap(sig);
}
// TODO(vsm): These methods need to validate whether we really have a
@@ -135,7 +148,15 @@ dynamic _unwrap(obj) => JS('', '#.unwrapType(#)', _dart, obj);
dynamic _wrap(obj) => JS('', '#.wrapType(#)', _dart, obj);
_unimplemented(Type t, Invocation i) {
- throw new UnimplementedError('$t.${i.memberName} unimplemented');
+ throw new UnimplementedError('$t.${getName(i.memberName)} unimplemented');
+}
+
+dynamic _toJsMap(Map<Symbol, dynamic> map) {
+ var obj = JS('', '{}');
+ map.forEach((Symbol key, value) {
+ JS('', '#[#] = #', obj, getName(key), value);
+ });
+ return obj;
}
class JsMirror implements Mirror {
@@ -184,21 +205,41 @@ class JsInstanceMirror extends JsObjectMirror implements InstanceMirror {
return identityHashCode(reflectee) ^ 0x36363636;
}
- InstanceMirror getField(Symbol symbol) {
+ // Returns a String for public members or an ES6 symbol for private members.
+ _getAccessor(dynamic reflectee, Symbol symbol, [List<dynamic> args,
+ Map<Symbol, dynamic> namedArgs]) {
var name = getName(symbol);
+ if (!name.startsWith('_')) return name;
+
+ // TODO(vsm): Ideally, we'd record ES6 symbols properly during codegen if
+ // mirrors is enabled. Here, we're trying to recover it from the receiver
+ // instead.
+ //
+ // Get private fields and members. Members are on proto.
+ var privateMembers = JS('', 'Object.getOwnPropertySymbols(#)', reflectee)
+ ..addAll(JS('', 'Object.getOwnPropertySymbols(#.__proto__)', reflectee));
+ for (var member in privateMembers) {
+ var privateName = _getNameForESSymbol(member);
+ if (name == privateName) return member;
+ }
+ return new NoSuchMethodError(reflectee, symbol, args, namedArgs);
+ }
+
+ InstanceMirror getField(Symbol symbol) {
+ var name = _getAccessor(reflectee, symbol);
var field = _dload(reflectee, name);
return reflect(field);
}
InstanceMirror setField(Symbol symbol, Object value) {
- var name = getName(symbol);
+ var name = _getAccessor(reflectee, symbol);
_dput(reflectee, name, value);
return reflect(value);
}
InstanceMirror invoke(Symbol symbol, List<dynamic> args,
[Map<Symbol, dynamic> namedArgs]) {
- var name = getName(symbol);
+ var name = _getAccessor(reflectee, symbol, args, namedArgs);
if (namedArgs != null) {
args = new List.from(args);
args.add(_toJsMap(namedArgs));
@@ -207,13 +248,7 @@ class JsInstanceMirror extends JsObjectMirror implements InstanceMirror {
return reflect(result);
}
- dynamic _toJsMap(Map<Symbol, dynamic> map) {
- var obj = JS('', '{}');
- map.forEach((Symbol key, value) {
- JS('', '#[#] = #', obj, getName(key), value);
- });
- return obj;
- }
+ String toString() => "InstanceMirror on '$reflectee'";
}
class JsClosureMirror extends JsInstanceMirror implements ClosureMirror {
@@ -352,6 +387,32 @@ class JsClassMirror extends JsMirror implements ClassMirror {
return reflect(instance);
}
+ // TODO(vsm): Need to check for NSM, types on accessors below. Unlike the
+ // InstanceMirror case, there is no dynamic helper to delegate to - we never
+ // need a dload, etc. on a static.
+
+ InstanceMirror getField(Symbol symbol) {
+ var name = getName(symbol);
+ return reflect(JS('', '#[#]', _unwrap(_cls), name));
+ }
+
+ InstanceMirror setField(Symbol symbol, Object value) {
+ var name = getName(symbol);
+ JS('', '#[#] = #', _unwrap(_cls), name, value);
+ return reflect(value);
+ }
+
+ InstanceMirror invoke(Symbol symbol, List<dynamic> args,
+ [Map<Symbol, dynamic> namedArgs]) {
+ var name = getName(symbol);
+ if (namedArgs != null) {
+ args = new List.from(args);
+ args.add(_toJsMap(namedArgs));
+ }
+ var result = JS('', '#.#(...#)', _unwrap(_cls), name, args);
+ return reflect(result);
+ }
+
List<ClassMirror> get superinterfaces {
_Lazy<List<Type>> interfaceThunk = JS('', '#[dart.implements]', _unwrap(_cls));
if (interfaceThunk == null) {
@@ -385,6 +446,8 @@ class JsClassMirror extends JsMirror implements ClassMirror {
return reflectType(_wrap(JS('Type', '#.__proto__', _unwrap(_cls))));
}
}
+
+ String toString() => "ClassMirror on '$_cls'";
}
class JsVariableMirror extends JsMirror implements VariableMirror {
@@ -403,11 +466,15 @@ class JsVariableMirror extends JsMirror implements VariableMirror {
: type = reflectType(t),
metadata = new List<InstanceMirror>.unmodifiable(
annotations.map((a) => reflect(a)));
+
+ String toString() => "VariableMirror on '$_name'";
}
class JsParameterMirror extends JsVariableMirror implements ParameterMirror {
JsParameterMirror._(String name, Type t, List annotations)
: super._(name, t, annotations);
+
+ String toString() => "ParameterMirror on '$_name'";
}
class JsMethodMirror extends JsMirror implements MethodMirror {
@@ -485,4 +552,6 @@ class JsMethodMirror extends JsMirror implements MethodMirror {
_params = new List.unmodifiable(params);
}
+
+ String toString() => "MethodMirror on '$_name'";
}
« no previous file with comments | « pkg/dev_compiler/test/browser/language_tests.js ('k') | pkg/dev_compiler/tool/sdk_expected_errors.txt » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698