Index: pkg/dev_compiler/tool/input_sdk/private/js_string.dart |
diff --git a/pkg/dev_compiler/tool/input_sdk/private/js_string.dart b/pkg/dev_compiler/tool/input_sdk/private/js_string.dart |
index d6b7550e5ac6544ba68052fbd7ab923c561680d6..bb9ddc7d7db5315318971aaf354212f5ea2a8596 100644 |
--- a/pkg/dev_compiler/tool/input_sdk/private/js_string.dart |
+++ b/pkg/dev_compiler/tool/input_sdk/private/js_string.dart |
@@ -15,9 +15,13 @@ class JSString extends Interceptor implements String, JSIndexable<String> { |
const JSString(); |
int codeUnitAt(int index) { |
- if (index is! int) throw diagnoseIndexError(this, index); |
- if (index < 0) throw diagnoseIndexError(this, index); |
- if (index >= length) throw diagnoseIndexError(this, index); |
+ // Suppress 2nd null check on index and null check on length |
+ // (JS String.length cannot be null). |
+ if (index == null || |
+ JS('int', '#', index) < 0 || |
+ JS('int', '#', index) >= JS('int', '#.length', this)) { |
+ throw diagnoseIndexError(this, index); |
+ } |
return JS('int', r'#.charCodeAt(#)', this, index); |
} |
@@ -134,14 +138,16 @@ class JSString extends Interceptor implements String, JSIndexable<String> { |
} |
bool startsWith(Pattern pattern, [int index = 0]) { |
- checkInt(index); |
- if (index < 0 || index > this.length) { |
+ // Suppress null check on length and all but the first |
+ // reference to index. |
+ int length = JS('int', '#.length', this); |
+ if (index < 0 || JS('int', '#', index) > length) { |
throw new RangeError.range(index, 0, this.length); |
} |
if (pattern is String) { |
String other = pattern; |
- int otherLength = other.length; |
- int endIndex = index + otherLength; |
+ int otherLength = JS('int', '#.length', other); |
+ int endIndex = JS('int', '#', index) + otherLength; |
if (endIndex > length) return false; |
return other == JS('String', r'#.substring(#, #)', this, index, endIndex); |
} |
@@ -427,12 +433,12 @@ class JSString extends Interceptor implements String, JSIndexable<String> { |
return stringContainsUnchecked(this, other, startIndex); |
} |
- bool get isEmpty => length == 0; |
+ bool get isEmpty => JS('int', '#.length', this) == 0; |
bool get isNotEmpty => !isEmpty; |
int compareTo(String other) { |
- if (other is! String) throw argumentErrorValue(other); |
+ if (other == null) throw argumentErrorValue(other); |
return this == other ? 0 : JS('bool', r'# < #', this, other) ? -1 : 1; |
} |
@@ -449,6 +455,7 @@ class JSString extends Interceptor implements String, JSIndexable<String> { |
// TODO(ahe): This method shouldn't have to use JS. Update when our |
// optimizations are smarter. |
int hash = 0; |
+ int length = JS('int', '#.length', this); |
for (int i = 0; i < length; i++) { |
hash = 0x1fffffff & (hash + JS('int', r'#.charCodeAt(#)', this, i)); |
hash = 0x1fffffff & (hash + ((0x0007ffff & hash) << 10)); |
@@ -464,8 +471,11 @@ class JSString extends Interceptor implements String, JSIndexable<String> { |
int get length => JS('int', r'#.length', this); |
String operator [](int index) { |
- if (index is! int) throw diagnoseIndexError(this, index); |
- if (index >= length || index < 0) throw diagnoseIndexError(this, index); |
+ if (index == null || |
+ JS('int', '#', index) >= JS('int', '#.length', this) || |
+ JS('int', '#', index) < 0) { |
+ throw diagnoseIndexError(this, index); |
+ } |
return JS('String', '#[#]', this, index); |
} |
} |