Move some string methods in the interceptor, and support for optional parameters in intercepted methods.

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

git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@14881 260f80e4-7a28-3924-810f-c04153c831b5
This commit is contained in:
ngeoffray@google.com 2012-11-14 12:03:59 +00:00
parent fff76e072a
commit c51c9d54c5
3 changed files with 90 additions and 104 deletions

View file

@ -394,19 +394,40 @@ function(prototype, staticName, fieldName, getterName, lazyValue) {
CodeBuffer buffer = new CodeBuffer();
buffer.add('function(');
JavaScriptBackend backend = compiler.backend;
bool isInterceptorClass =
backend.isInterceptorClass(member.getEnclosingClass());
// If the method is in an interceptor class, we need to also pass
// the actual receiver.
int extraArgumentCount = isInterceptorClass ? 1 : 0;
// Use '$' to avoid clashes with other parameter names. Using '$'
// works because [JsNames.getValid] used for getting parameter
// names never returns '$'.
String extraArgumentName = r'$';
// The parameters that this stub takes.
List<String> parametersBuffer = new List<String>(selector.argumentCount);
List<String> parametersBuffer =
new List<String>(selector.argumentCount + extraArgumentCount);
// The arguments that will be passed to the real method.
List<String> argumentsBuffer = new List<String>(parameters.parameterCount);
List<String> argumentsBuffer =
new List<String>(parameters.parameterCount + extraArgumentCount);
int count = 0;
if (isInterceptorClass) {
count++;
parametersBuffer[0] = extraArgumentName;
argumentsBuffer[0] = extraArgumentName;
}
int indexOfLastOptionalArgumentInParameters = positionalArgumentCount - 1;
TreeElements elements =
compiler.enqueuer.resolution.getCachedElements(member);
parameters.orderedForEachParameter((Element element) {
String jsName = JsNames.getValid(element.name.slowToString());
if (count < positionalArgumentCount) {
assert(jsName != extraArgumentName);
if (count < positionalArgumentCount + extraArgumentCount) {
parametersBuffer[count] = jsName;
argumentsBuffer[count] = jsName;
} else {

View file

@ -22,6 +22,72 @@ class JSString implements String {
return JS('int', r'#.charCodeAt(#)', this, index);
}
Iterable<Match> allMatches(String str) {
checkString(str);
return allMatchesInStringUnchecked(this, str);
}
String concat(String other) {
if (other is !String) throw new ArgumentError(other);
return JS('String', r'# + #', this, other);
}
bool endsWith(String other) {
checkString(other);
int otherLength = other.length;
if (otherLength > length) return false;
return other == substring(length - otherLength);
}
String replaceAll(Pattern from, String to) {
checkString(to);
return stringReplaceAllUnchecked(this, from, to);
}
String replaceFirst(Pattern from, String to) {
checkString(to);
return stringReplaceFirstUnchecked(this, from, to);
}
List<String> split(Pattern pattern) {
checkNull(pattern);
return stringSplitUnchecked(this, pattern);
}
List<String> splitChars() {
return JS('List', r'#.split("")', this);
}
bool startsWith(String other) {
checkString(other);
int otherLength = other.length;
if (otherLength > length) return false;
return JS('bool', r'# == #', other,
JS('String', r'#.substring(0, #)', this, otherLength));
}
String substring(int startIndex, [int endIndex]) {
checkNum(startIndex);
if (endIndex == null) endIndex = length;
checkNum(endIndex);
if (startIndex < 0 ) throw new RangeError.value(startIndex);
if (startIndex > endIndex) throw new RangeError.value(startIndex);
if (endIndex > length) throw new RangeError.value(endIndex);
return JS('String', r'#.substring(#, #)', this, startIndex, endIndex);
}
String toLowerCase() {
return JS('String', r'#.toLowerCase()', this);
}
String toUpperCase() {
return JS('String', r'#.toUpperCase()', this);
}
String trim() {
return JS('String', r'#.trim()', this);
}
List<int> get charCodes {
List<int> result = new List<int>(length);
for (int i = 0; i < length; i++) {
@ -534,19 +600,6 @@ toRadixString(receiver, radix) {
return JS('String', r'#.toString(#)', receiver, radix);
}
allMatches(receiver, str) {
if (receiver is !String) return UNINTERCEPTED(receiver.allMatches(str));
checkString(str);
return allMatchesInStringUnchecked(receiver, str);
}
concat(receiver, other) {
if (receiver is !String) return UNINTERCEPTED(receiver.concat(other));
if (other is !String) throw new ArgumentError(other);
return JS('String', r'# + #', receiver, other);
}
contains$1(receiver, other) {
if (receiver is String) {
return contains$2(receiver, other, 0);
@ -567,91 +620,6 @@ contains$2(receiver, other, startIndex) {
return stringContainsUnchecked(receiver, other, startIndex);
}
endsWith(receiver, other) {
if (receiver is !String) return UNINTERCEPTED(receiver.endsWith(other));
checkString(other);
int receiverLength = receiver.length;
int otherLength = other.length;
if (otherLength > receiverLength) return false;
return other == receiver.substring(receiverLength - otherLength);
}
replaceAll(receiver, from, to) {
if (receiver is !String) return UNINTERCEPTED(receiver.replaceAll(from, to));
checkString(to);
return stringReplaceAllUnchecked(receiver, from, to);
}
replaceFirst(receiver, from, to) {
if (receiver is !String) {
return UNINTERCEPTED(receiver.replaceFirst(from, to));
}
checkString(to);
return stringReplaceFirstUnchecked(receiver, from, to);
}
split(receiver, pattern) {
if (receiver is !String) return UNINTERCEPTED(receiver.split(pattern));
checkNull(pattern);
return stringSplitUnchecked(receiver, pattern);
}
splitChars(receiver) {
if (receiver is !String) return UNINTERCEPTED(receiver.splitChars());
return JS('List', r'#.split("")', receiver);
}
startsWith(receiver, other) {
if (receiver is !String) return UNINTERCEPTED(receiver.startsWith(other));
checkString(other);
int length = other.length;
if (length > receiver.length) return false;
return JS('bool', r'# == #', other,
JS('String', r'#.substring(0, #)', receiver, length));
}
substring$1(receiver, startIndex) {
if (receiver is !String) return UNINTERCEPTED(receiver.substring(startIndex));
return substring$2(receiver, startIndex, null);
}
substring$2(receiver, startIndex, endIndex) {
if (receiver is !String) {
return UNINTERCEPTED(receiver.substring(startIndex, endIndex));
}
checkNum(startIndex);
var length = receiver.length;
if (endIndex == null) endIndex = length;
checkNum(endIndex);
if (startIndex < 0 ) throw new RangeError.value(startIndex);
if (startIndex > endIndex) throw new RangeError.value(startIndex);
if (endIndex > length) throw new RangeError.value(endIndex);
return substringUnchecked(receiver, startIndex, endIndex);
}
toLowerCase(receiver) {
if (receiver is !String) return UNINTERCEPTED(receiver.toLowerCase());
return JS('String', r'#.toLowerCase()', receiver);
}
toUpperCase(receiver) {
if (receiver is !String) return UNINTERCEPTED(receiver.toUpperCase());
return JS('String', r'#.toUpperCase()', receiver);
}
trim(receiver) {
if (receiver is !String) return UNINTERCEPTED(receiver.trim());
return JS('String', r'#.trim()', receiver);
}
/**
* This is the [Jenkins hash function][1] but using masking to keep
* values in SMI range.

View file

@ -812,9 +812,6 @@ checkString(value) {
return value;
}
substringUnchecked(receiver, startIndex, endIndex)
=> JS('String', r'#.substring(#, #)', receiver, startIndex, endIndex);
class MathNatives {
static int parseInt(str) {
checkString(str);