Files
sdk/runtime/lib/invocation_mirror_patch.dart
T
lrn@google.com 4582e5218a Make Invocation.positionalArguments and .namedArguments never be null.
In the cases where they were previously null, they are now an empty list
or map.

The list or map should always be unmodifiable, but the non-empty ones
aren't yet.

BUG= http://dartbug.com/6357
R=floitsch@google.com

Review URL: https://codereview.chromium.org//22918025

git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@26635 260f80e4-7a28-3924-810f-c04153c831b5
2013-08-26 10:57:33 +00:00

144 lines
4.4 KiB
Dart

// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
class _InvocationMirror implements Invocation {
// Constants describing the invocation type.
// _FIELD cannot be generated by regular invocation mirrors.
static const int _METHOD = 0;
static const int _GETTER = 1;
static const int _SETTER = 2;
static const int _FIELD = 3;
static const int _TYPE_SHIFT = 0;
static const int _TYPE_BITS = 2;
static const int _TYPE_MASK = (1 << _TYPE_BITS) - 1;
// These values, except _DYNAMIC, are only used when throwing
// NoSuchMethodError for compile-time resolution failures.
static const int _DYNAMIC = 0;
static const int _STATIC = 1;
static const int _CONSTRUCTOR = 2;
static const int _TOP_LEVEL = 3;
static const int _CALL_SHIFT = _TYPE_BITS;
static const int _CALL_BITS = 2;
static const int _CALL_MASK = (1 << _CALL_BITS) - 1;
// Internal representation of the invocation mirror.
final String _functionName;
final List _argumentsDescriptor;
final List _arguments;
// External representation of the invocation mirror; populated on demand.
Symbol _memberName;
int _type;
List _positionalArguments;
Map<Symbol, dynamic> _namedArguments;
void _setMemberNameAndType() {
if (_functionName.startsWith("get:")) {
_type = _GETTER;
_memberName =
new _collection_dev.Symbol.unvalidated(_functionName.substring(4));
} else if (_functionName.startsWith("set:")) {
_type = _SETTER;
_memberName =
new _collection_dev.Symbol.unvalidated(
_functionName.substring(4) + "=");
} else {
_type = _METHOD;
_memberName = new _collection_dev.Symbol.unvalidated(_functionName);
}
}
Symbol get memberName {
if (_memberName == null) {
_setMemberNameAndType();
}
return _memberName;
}
List get positionalArguments {
if (_positionalArguments == null) {
int numPositionalArguments = _argumentsDescriptor[1];
// Don't count receiver.
if (numPositionalArguments == 1) {
return _positionalArguments = const [];
}
// Exclude receiver.
_positionalArguments = _arguments.sublist(1, numPositionalArguments);
}
return _positionalArguments;
}
Map<Symbol, dynamic> get namedArguments {
if (_namedArguments == null) {
int numArguments = _argumentsDescriptor[0] - 1; // Exclude receiver.
int numPositionalArguments = _argumentsDescriptor[1] - 1;
int numNamedArguments = numArguments - numPositionalArguments;
if (numNamedArguments == 0) {
return _namedArguments = const <Symbol, dynamic>{};
}
_namedArguments = new Map<Symbol, dynamic>();
for (int i = 0; i < numNamedArguments; i++) {
String arg_name = _argumentsDescriptor[2 + 2*i];
var arg_value = _arguments[_argumentsDescriptor[3 + 2*i]];
_namedArguments[new _collection_dev.Symbol.unvalidated(arg_name)] =
arg_value;
}
}
return _namedArguments;
}
bool get isMethod {
if (_type == null) {
_setMemberNameAndType();
}
return _type == _METHOD;
}
bool get isAccessor {
if (_type == null) {
_setMemberNameAndType();
}
return _type != _METHOD;
}
bool get isGetter {
if (_type == null) {
_setMemberNameAndType();
}
return _type == _GETTER;
}
bool get isSetter {
if (_type == null) {
_setMemberNameAndType();
}
return _type == _SETTER;
}
_InvocationMirror(this._functionName,
this._argumentsDescriptor,
this._arguments);
static _allocateInvocationMirror(String functionName,
List argumentsDescriptor,
List arguments) {
return new _InvocationMirror(functionName, argumentsDescriptor, arguments);
}
static _invoke(Object receiver,
String functionName,
List argumentsDescriptor,
List arguments)
native "InvocationMirror_invoke";
_invokeOn(Object receiver) {
return _invoke(receiver, _functionName, _argumentsDescriptor, _arguments);
}
// TODO(ahe): This is a hack. See _LocalInstanceMirrorImpl.delegate
// in mirrors_impl.dart
static final _invokeOnClosure = (x, y) => y._invokeOn(x);
}