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

Unified Diff: dart/sdk/lib/_internal/lib/js_mirrors.dart

Issue 27524003: Generate tear-off closures dynamically. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge
Patch Set: Merged with r30954 Created 7 years 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
Index: dart/sdk/lib/_internal/lib/js_mirrors.dart
diff --git a/dart/sdk/lib/_internal/lib/js_mirrors.dart b/dart/sdk/lib/_internal/lib/js_mirrors.dart
index b1fb4c4f94ae2a48e2be001865a4e0549a96756d..0cb1720955cf53e019aea8cf9e8ddf8d3ff6196b 100644
--- a/dart/sdk/lib/_internal/lib/js_mirrors.dart
+++ b/dart/sdk/lib/_internal/lib/js_mirrors.dart
@@ -5,7 +5,10 @@
library dart._js_mirrors;
import 'dart:async';
-import 'dart:collection' show UnmodifiableListView;
+
+import 'dart:collection' show
+ UnmodifiableListView;
+
import 'dart:mirrors';
import 'dart:_foreign_helper' show
@@ -13,7 +16,9 @@ import 'dart:_foreign_helper' show
JS_CURRENT_ISOLATE,
JS_CURRENT_ISOLATE_CONTEXT,
JS_GET_NAME;
+
import 'dart:_collection-dev' as _symbol_dev;
+
import 'dart:_js_helper' show
BoundClosure,
Closure,
@@ -21,17 +26,25 @@ import 'dart:_js_helper' show
JsCache,
Null,
Primitives,
+ ReflectionInfo,
RuntimeError,
+ TypeVariable,
+ UnimplementedNoSuchMethodError,
createRuntimeType,
createUnmangledInvocationMirror,
getMangledTypeName,
- throwInvalidReflectionError,
+ getMetadata,
hasReflectableProperty,
runtimeTypeToString,
- TypeVariable;
+ setRuntimeTypeInfo,
+ throwInvalidReflectionError;
+
import 'dart:_interceptors' show
Interceptor,
- JSExtendableArray;
+ JSArray,
+ JSExtendableArray,
+ getInterceptor;
+
import 'dart:_js_names';
const String METHODS_WITH_OPTIONAL_ARGUMENTS = r'$methodsWithOptionalArguments';
@@ -771,35 +784,34 @@ class JsInstanceMirror extends JsObjectMirror implements InstanceMirror {
String name = n(memberName);
String reflectiveName;
if (namedArguments != null && !namedArguments.isEmpty) {
- var methodsWithOptionalArguments =
- JS('=Object', '#.\$methodsWithOptionalArguments', reflectee);
- String mangledName =
- JS('String|Null', '#[#]', methodsWithOptionalArguments, '*$name');
- if (mangledName == null) {
+ var interceptor = getInterceptor(reflectee);
+
+ var jsFunction = JS('', '#[# + "*"]', interceptor, name);
+ if (jsFunction == null) {
// TODO(ahe): Invoke noSuchMethod.
throw new UnimplementedNoSuchMethodError(
'Invoking noSuchMethod with named arguments not implemented');
}
- var defaultValueIndices =
- JS('List|Null', '#[#].\$defaultValues', reflectee, mangledName);
- var defaultValues =
- defaultValueIndices.map((int i) => getMetadata(i))
- .iterator;
- var defaultArguments = new Map();
- reflectiveName = mangledNames[mangledName];
- var reflectiveNames = reflectiveName.split(':');
- int requiredPositionalArgumentCount =
- int.parse(reflectiveNames.elementAt(1));
+ ReflectionInfo info = new ReflectionInfo(jsFunction);
+ if (jsFunction == null) {
+ // TODO(ahe): Invoke noSuchMethod.
+ throw new UnimplementedNoSuchMethodError(
+ 'Invoking noSuchMethod with named arguments not implemented');
+ }
+
positionalArguments = new List.from(positionalArguments);
// Check the number of positional arguments is valid.
- if (requiredPositionalArgumentCount != positionalArguments.length) {
+ if (info.requiredParameterCount != positionalArguments.length) {
// TODO(ahe): Invoke noSuchMethod.
throw new UnimplementedNoSuchMethodError(
'Invoking noSuchMethod with named arguments not implemented');
}
- for (String parameter in reflectiveNames.skip(3)) {
- defaultValues.moveNext();
- defaultArguments[parameter] = defaultValues.current;
+ var defaultArguments = new Map();
+ for (int i = 0; i < info.optionalParameterCount; i++) {
+ var parameterName = info.parameterName(i + info.requiredParameterCount);
+ var defaultValue =
+ getMetadata(info.defaultValue(i + info.requiredParameterCount));
+ defaultArguments[parameterName] = defaultValue;
}
namedArguments.forEach((Symbol symbol, value) {
String parameter = n(symbol);
@@ -813,6 +825,9 @@ class JsInstanceMirror extends JsObjectMirror implements InstanceMirror {
}
});
positionalArguments.addAll(defaultArguments.values);
+ // TODO(ahe): Handle intercepted methods.
ngeoffray 2013/12/09 11:15:58 Does it crash if it's intercepted?
ahe 2013/12/09 17:06:47 Nope, just bad undefined stuff.
+ return reflect(
+ JS('', '#.apply(#, #)', jsFunction, reflectee, positionalArguments));
} else {
reflectiveName =
JS('String', '# + ":" + # + ":0"', name, positionalArguments.length);
@@ -1201,25 +1216,23 @@ class JsClassMirror extends JsTypeMirror with JsObjectMirror
}
keys = extractKeys(JS('', 'init.statics[#]', _mangledName));
- int length = keys.length;
- for (int i = 0; i < length; i++) {
- String mangledName = keys[i];
+ for (String mangledName in keys) {
if (isReflectiveDataInPrototype(mangledName)) continue;
String unmangledName = mangledName;
var jsFunction = JS('', '#[#]', owner._globalObject, mangledName);
bool isConstructor = false;
- if (i + 1 < length) {
- String reflectionName = keys[i + 1];
- if (reflectionName.startsWith('+')) {
- i++;
- reflectionName = reflectionName.substring(1);
- isConstructor = reflectionName.startsWith('new ');
- if (isConstructor) {
- reflectionName = reflectionName.substring(4).replaceAll(r'$', '.');
- }
+ if (hasReflectableProperty(jsFunction)) {
+ String reflectionName =
+ JS('String|Null', r'#.$reflectionName', jsFunction);
+ if (reflectionName == null) continue;
+ isConstructor = reflectionName.startsWith('new ');
+ if (isConstructor) {
+ reflectionName = reflectionName.substring(4).replaceAll(r'$', '.');
}
unmangledName = reflectionName;
+ } else {
+ continue;
ngeoffray 2013/12/09 11:15:58 This is weird. Why not putting the code below in t
ahe 2013/12/09 17:06:47 Yeah. Historical reasons.
}
bool isStatic = !isConstructor; // Constructors are not static.
JsMethodMirror mirror =
@@ -1357,7 +1370,7 @@ class JsClassMirror extends JsTypeMirror with JsObjectMirror
(m) => m.constructorName == constructorName,
orElse: () {
// TODO(ahe): What receiver to use?
- throw new NoSuchMethodError(
+ throw new NoSuchStaticMethodError.missingConstructor(
this, constructorName, positionalArguments, namedArguments);
});
JsCache.update(_jsConstructorCache, n(constructorName), mirror);
@@ -1617,8 +1630,9 @@ class JsClosureMirror extends JsInstanceMirror implements ClosureMirror {
MethodMirror get function {
String cacheName = Primitives.mirrorFunctionCacheName;
- JsMethodMirror cachedFunction =
- JS('JsMethodMirror|Null', r'#.constructor[#]', reflectee, cacheName);
+ JsMethodMirror cachedFunction;
+ // TODO(ahe): Restore caching.
+ //= JS('JsMethodMirror|Null', r'#.constructor[#]', reflectee, cacheName);
ngeoffray 2013/12/09 11:15:58 Why can't you cache anymore?
ahe 2013/12/09 17:06:47 Because there is only one constructor that is shar
if (cachedFunction != null) return cachedFunction;
disableTreeShaking();
// TODO(ahe): What about optional parameters (named or not).
@@ -1685,7 +1699,7 @@ class JsMethodMirror extends JsDeclarationMirror implements MethodMirror {
final bool isOperator;
DeclarationMirror _owner;
List _metadata;
- var _returnType;
+ TypeMirror _returnType;
UnmodifiableListView<ParameterMirror> _parameters;
JsMethodMirror(Symbol simpleName,
@@ -1741,26 +1755,49 @@ class JsMethodMirror extends JsDeclarationMirror implements MethodMirror {
TypeMirror get returnType {
metadata; // Compute _returnType as a side-effect of extracting metadata.
- return typeMirrorFromRuntimeTypeRepresentation(owner, _returnType);
+ return _returnType;
}
List<InstanceMirror> get metadata {
if (_metadata == null) {
var raw = extractMetadata(_jsFunction);
var formals = new List(_parameterCount);
- if (!raw.isEmpty) {
- _returnType = raw[0];
- int parameterLength = 1 + _parameterCount * 2;
- int formalsCount = 0;
- for (int i = 1; i < parameterLength; i += 2) {
- var name = raw[i];
- var type = raw[i + 1];
- formals[formalsCount++] = new JsParameterMirror(name, this, type);
+ ReflectionInfo info = new ReflectionInfo(_jsFunction);
+ if (info != null) {
+ assert(_parameterCount
+ == info.requiredParameterCount + info.optionalParameterCount);
+ var functionType = info.functionType;
+ var type;
+ if (functionType is int) {
ngeoffray 2013/12/09 11:15:58 Please add a comment what it means to be int.
ahe 2013/12/09 17:06:47 Done.
+ type = new JsFunctionTypeMirror(info.computeFunctionRti(null), this);
+ assert(_parameterCount == type.parameters.length);
+ } else {
+ TypeMirror ownerType = owner;
+ JsClassMirror ownerClass = ownerType.originalDeclaration;
+ type = new JsFunctionTypeMirror(
+ info.computeFunctionRti(ownerClass._jsConstructorOrInterceptor),
+ owner);
}
- raw = raw.sublist(parameterLength);
- } else {
- for (int i = 0; i < _parameterCount; i++) {
- formals[i] = new JsParameterMirror('argument$i', this, null);
+ // Constructors aren't reified with their return type.
+ if (isConstructor) {
+ _returnType = owner;
+ } else {
+ _returnType = type.returnType;
+ }
+ int i = 0;
+ bool isNamed = info.areOptionalParametersNamed;
+ for (JsParameterMirror parameter in type.parameters) {
+ var name = info.parameterName(i);
+ var p;
+ if (i < info.requiredParameterCount) {
+ p = new JsParameterMirror(name, this, parameter._type);
+ } else {
+ var defaultValue = info.defaultValue(i);
+ p = new JsParameterMirror(
+ name, this, parameter._type,
+ isOptional: true, isNamed: isNamed, defaultValue: defaultValue);
+ }
+ formals[i++] = p;
}
}
_parameters = new UnmodifiableListView<ParameterMirror>(formals);
@@ -1843,8 +1880,20 @@ class JsParameterMirror extends JsDeclarationMirror implements ParameterMirror {
// A JS object representing the type.
final _type;
- JsParameterMirror(String unmangledName, this.owner, this._type)
- : super(s(unmangledName));
+ final bool isOptional;
+
+ final bool isNamed;
+
+ final int _defaultValue;
+
+ JsParameterMirror(String unmangledName,
+ this.owner,
+ this._type,
+ {this.isOptional: false,
+ this.isNamed: false,
+ defaultValue})
+ : _defaultValue = defaultValue,
+ super(s(unmangledName));
String get _prettyName => 'ParameterMirror';
@@ -1858,19 +1907,14 @@ class JsParameterMirror extends JsDeclarationMirror implements ParameterMirror {
// TODO(ahe): Implement this.
bool get isFinal => false;
- bool get isConst => false;
-
- // TODO(ahe): Implement this.
- bool get isOptional => false;
-
// TODO(ahe): Implement this.
- bool get isNamed => false;
+ bool get isConst => false;
- // TODO(ahe): Implement this.
- bool get hasDefaultValue => false;
+ bool get hasDefaultValue => _defaultValue != null;
- // TODO(ahe): Implement this.
- get defaultValue => null;
+ get defaultValue {
+ return hasDefaultValue ? reflect(getMetadata(_defaultValue)) : null;
+ }
// TODO(ahe): Implement this.
List<InstanceMirror> get metadata => throw new UnimplementedError();
@@ -1973,7 +2017,7 @@ class JsFunctionTypeMirror extends BrokenClassMirror
if (_isVoid) return _cachedReturnType = JsMirrorSystem._voidType;
if (!_hasReturnType) return _cachedReturnType = JsMirrorSystem._dynamicType;
return _cachedReturnType =
- typeMirrorFromRuntimeTypeRepresentation(this, _returnType);
+ typeMirrorFromRuntimeTypeRepresentation(owner, _returnType);
}
List<ParameterMirror> get parameters {
@@ -2058,23 +2102,25 @@ int findTypeVariableIndex(List<TypeVariableMirror> typeVariables, String name) {
throw new ArgumentError('Type variable not present in list.');
}
-getMetadata(int index) => JS('', 'init.metadata[#]', index);
-
TypeMirror typeMirrorFromRuntimeTypeRepresentation(
DeclarationMirror owner,
var /*int|List|JsFunction*/ type) {
+ // TODO(ahe): This method might benefit from using convertRtiToRuntimeType
+ // instead of working on strings.
ClassMirror ownerClass;
DeclarationMirror context = owner;
- while(context != null) {
+ while (context != null) {
if (context is ClassMirror) {
ownerClass = context;
break;
}
+ // TODO(ahe): Get type parameters and arguments from typedefs.
+ if (context is TypedefMirror) break;
context = context.owner;
}
String representation;
- if (type == null){
+ if (type == null) {
return JsMirrorSystem._dynamicType;
} else if (ownerClass == null) {
representation = runtimeTypeToString(type);
@@ -2134,7 +2180,13 @@ List extractMetadata(victim) {
preserveMetadata();
var metadataFunction = JS('', '#["@"]', victim);
if (metadataFunction != null) return JS('', '#()', metadataFunction);
- if (JS('String', 'typeof #', victim) != 'function') return const [];
+ if (JS('bool', 'typeof # != "function"', victim)) return const [];
+ if (JS('bool', '# in #', r'$metadataIndex', victim)) {
+ return JSArray.markFixedList(
+ JS('JSExtendableArray',
+ r'#.$reflectionInfo.splice(#.$metadataIndex)', victim, victim))
+ .map((int i) => getMetadata(i)).toList();
+ }
String source = JS('String', 'Function.prototype.toString.call(#)', victim);
int index = source.lastIndexOf(new RegExp('"[0-9,]*";?[ \n\r]*}'));
if (index == -1) return const [];
@@ -2214,6 +2266,33 @@ bool isReflectiveDataInPrototype(String key) {
return firstChar == '*' || firstChar == '+';
}
+class NoSuchStaticMethodError extends Error implements NoSuchMethodError {
+ static const int MISSING_CONSTRUCTOR = 0;
+ final ClassMirror _cls;
+ final Symbol _name;
+ final List _positionalArguments;
+ final Map<Symbol, dynamic> _namedArguments;
+ final int _kind;
+
+ NoSuchStaticMethodError.missingConstructor(
+ this._cls,
+ this._name,
+ this._positionalArguments,
+ this._namedArguments)
+ : _kind = MISSING_CONSTRUCTOR;
+
+ String toString() {
+ switch(_kind) {
+ case MISSING_CONSTRUCTOR:
+ return
+ "NoSuchMethodError: No constructor named '${n(_name)}' in class"
+ " '${n(_cls.qualifiedName)}'.";
+ default:
+ return 'NoSuchMethodError';
+ }
+ }
+}
+
// Copied from package "unmodifiable_collection".
// TODO(14314): Move to dart:collection.
class UnmodifiableMapView<K, V> implements Map<K, V> {
@@ -2253,13 +2332,3 @@ class UnmodifiableMapView<K, V> implements Map<K, V> {
void clear() => _throw();
}
-
-// TODO(ahe): Remove this class and call noSuchMethod instead.
-class UnimplementedNoSuchMethodError extends Error
- implements NoSuchMethodError {
- final String _message;
-
- UnimplementedNoSuchMethodError(this._message);
-
- String toString() => "Unsupported operation: $_message";
-}

Powered by Google App Engine
This is Rietveld 408576698