Make StringCharCodeAt runtime function do what it name implies and not
just indexed string access. The difference is that String.prototype.charCodeAt accepts any number as an index, whereas string[] only accepts array indices. Review URL: http://codereview.chromium.org/2467006 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@4790 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
parent
ebc21fc958
commit
3ec0b86495
@ -1638,22 +1638,6 @@ static Object* Runtime_SetCode(Arguments args) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static Object* CharCodeAt(String* subject, Object* index) {
|
|
||||||
uint32_t i = 0;
|
|
||||||
if (!index->ToArrayIndex(&i)) return Heap::nan_value();
|
|
||||||
// Flatten the string. If someone wants to get a char at an index
|
|
||||||
// in a cons string, it is likely that more indices will be
|
|
||||||
// accessed.
|
|
||||||
Object* flat = subject->TryFlatten();
|
|
||||||
if (flat->IsFailure()) return flat;
|
|
||||||
subject = String::cast(flat);
|
|
||||||
if (i >= static_cast<uint32_t>(subject->length())) {
|
|
||||||
return Heap::nan_value();
|
|
||||||
}
|
|
||||||
return Smi::FromInt(subject->Get(i));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static Object* CharFromCode(Object* char_code) {
|
static Object* CharFromCode(Object* char_code) {
|
||||||
uint32_t code;
|
uint32_t code;
|
||||||
if (char_code->ToArrayIndex(&code)) {
|
if (char_code->ToArrayIndex(&code)) {
|
||||||
@ -1671,21 +1655,31 @@ static Object* Runtime_StringCharCodeAt(Arguments args) {
|
|||||||
|
|
||||||
CONVERT_CHECKED(String, subject, args[0]);
|
CONVERT_CHECKED(String, subject, args[0]);
|
||||||
Object* index = args[1];
|
Object* index = args[1];
|
||||||
return CharCodeAt(subject, index);
|
RUNTIME_ASSERT(index->IsNumber());
|
||||||
}
|
|
||||||
|
|
||||||
|
uint32_t i = 0;
|
||||||
static Object* Runtime_StringCharAt(Arguments args) {
|
if (index->IsSmi()) {
|
||||||
NoHandleAllocation ha;
|
int value = Smi::cast(index)->value();
|
||||||
ASSERT(args.length() == 2);
|
if (value < 0) return Heap::nan_value();
|
||||||
|
i = value;
|
||||||
CONVERT_CHECKED(String, subject, args[0]);
|
} else {
|
||||||
Object* index = args[1];
|
ASSERT(index->IsHeapNumber());
|
||||||
Object* code = CharCodeAt(subject, index);
|
double value = HeapNumber::cast(index)->value();
|
||||||
if (code == Heap::nan_value()) {
|
i = static_cast<uint32_t>(value);
|
||||||
return Heap::undefined_value();
|
|
||||||
}
|
}
|
||||||
return CharFromCode(code);
|
|
||||||
|
// Flatten the string. If someone wants to get a char at an index
|
||||||
|
// in a cons string, it is likely that more indices will be
|
||||||
|
// accessed.
|
||||||
|
Object* flat = subject->TryFlatten();
|
||||||
|
if (flat->IsFailure()) return flat;
|
||||||
|
subject = String::cast(flat);
|
||||||
|
|
||||||
|
if (i >= static_cast<uint32_t>(subject->length())) {
|
||||||
|
return Heap::nan_value();
|
||||||
|
}
|
||||||
|
|
||||||
|
return Smi::FromInt(subject->Get(i));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -5344,6 +5338,9 @@ static Object* Runtime_NumberToInteger(Arguments args) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static Object* Runtime_NumberToIntegerMapMinusZero(Arguments args) {
|
static Object* Runtime_NumberToIntegerMapMinusZero(Arguments args) {
|
||||||
NoHandleAllocation ha;
|
NoHandleAllocation ha;
|
||||||
ASSERT(args.length() == 1);
|
ASSERT(args.length() == 1);
|
||||||
|
@ -162,7 +162,6 @@ namespace internal {
|
|||||||
\
|
\
|
||||||
/* Strings */ \
|
/* Strings */ \
|
||||||
F(StringCharCodeAt, 2, 1) \
|
F(StringCharCodeAt, 2, 1) \
|
||||||
F(StringCharAt, 2, 1) \
|
|
||||||
F(StringIndexOf, 3, 1) \
|
F(StringIndexOf, 3, 1) \
|
||||||
F(StringLastIndexOf, 3, 1) \
|
F(StringLastIndexOf, 3, 1) \
|
||||||
F(StringLocaleCompare, 2, 1) \
|
F(StringLocaleCompare, 2, 1) \
|
||||||
|
@ -27,52 +27,56 @@
|
|||||||
|
|
||||||
var s = "test";
|
var s = "test";
|
||||||
|
|
||||||
|
function getTwoByteString() { return "\u1234t"; }
|
||||||
|
function getCons() { return "testtesttesttest" + getTwoByteString() }
|
||||||
|
|
||||||
var slowIndex1 = { valueOf: function() { return 1; } };
|
var slowIndex1 = { valueOf: function() { return 1; } };
|
||||||
var slowIndex2 = { toString: function() { return "2"; } };
|
var slowIndex2 = { toString: function() { return "2"; } };
|
||||||
var slowIndexOutOfRange = { valueOf: function() { return -1; } };
|
var slowIndexOutOfRange = { valueOf: function() { return -1; } };
|
||||||
|
|
||||||
function basicTest() {
|
function basicTest(s, len) {
|
||||||
assertEquals("t", s.charAt());
|
assertEquals("t", s().charAt());
|
||||||
assertEquals("t", s.charAt("string"));
|
assertEquals("t", s().charAt("string"));
|
||||||
assertEquals("t", s.charAt(null));
|
assertEquals("t", s().charAt(null));
|
||||||
assertEquals("t", s.charAt(void 0));
|
assertEquals("t", s().charAt(void 0));
|
||||||
assertEquals("t", s.charAt(false));
|
assertEquals("t", s().charAt(false));
|
||||||
assertEquals("e", s.charAt(true));
|
assertEquals("e", s().charAt(true));
|
||||||
assertEquals("", s.charAt(-1));
|
assertEquals("", s().charAt(-1));
|
||||||
assertEquals("", s.charAt(4));
|
assertEquals("", s().charAt(len));
|
||||||
assertEquals("", s.charAt(slowIndexOutOfRange));
|
assertEquals("", s().charAt(slowIndexOutOfRange));
|
||||||
assertEquals("", s.charAt(1/0));
|
assertEquals("", s().charAt(1/0));
|
||||||
assertEquals("", s.charAt(-1/0));
|
assertEquals("", s().charAt(-1/0));
|
||||||
assertEquals("t", s.charAt(0));
|
assertEquals("t", s().charAt(0));
|
||||||
assertEquals("t", s.charAt(-0.0));
|
assertEquals("t", s().charAt(-0.0));
|
||||||
assertEquals("t", s.charAt(0.4));
|
assertEquals("t", s().charAt(0.4));
|
||||||
assertEquals("e", s.charAt(slowIndex1));
|
assertEquals("e", s().charAt(slowIndex1));
|
||||||
assertEquals("s", s.charAt(slowIndex2));
|
assertEquals("s", s().charAt(slowIndex2));
|
||||||
assertEquals("t", s.charAt(3));
|
assertEquals("t", s().charAt(3));
|
||||||
assertEquals("t", s.charAt(3.4));
|
assertEquals("t", s().charAt(3.4));
|
||||||
assertEquals("t", s.charAt(NaN));
|
assertEquals("t", s().charAt(NaN));
|
||||||
|
|
||||||
assertEquals(116, s.charCodeAt());
|
assertEquals(116, s().charCodeAt());
|
||||||
assertEquals(116, s.charCodeAt("string"));
|
assertEquals(116, s().charCodeAt("string"));
|
||||||
assertEquals(116, s.charCodeAt(null));
|
assertEquals(116, s().charCodeAt(null));
|
||||||
assertEquals(116, s.charCodeAt(void 0));
|
assertEquals(116, s().charCodeAt(void 0));
|
||||||
assertEquals(116, s.charCodeAt(false));
|
assertEquals(116, s().charCodeAt(false));
|
||||||
assertEquals(101, s.charCodeAt(true));
|
assertEquals(101, s().charCodeAt(true));
|
||||||
assertEquals(116, s.charCodeAt(0));
|
assertEquals(116, s().charCodeAt(0));
|
||||||
assertEquals(116, s.charCodeAt(-0.0));
|
assertEquals(116, s().charCodeAt(-0.0));
|
||||||
assertEquals(116, s.charCodeAt(0.4));
|
assertEquals(116, s().charCodeAt(0.4));
|
||||||
assertEquals(101, s.charCodeAt(slowIndex1));
|
assertEquals(101, s().charCodeAt(slowIndex1));
|
||||||
assertEquals(115, s.charCodeAt(slowIndex2));
|
assertEquals(115, s().charCodeAt(slowIndex2));
|
||||||
assertEquals(116, s.charCodeAt(3));
|
assertEquals(116, s().charCodeAt(3));
|
||||||
assertEquals(116, s.charCodeAt(3.4));
|
assertEquals(116, s().charCodeAt(3.4));
|
||||||
assertEquals(116, s.charCodeAt(NaN));
|
assertEquals(116, s().charCodeAt(NaN));
|
||||||
assertTrue(isNaN(s.charCodeAt(-1)));
|
assertTrue(isNaN(s().charCodeAt(-1)));
|
||||||
assertTrue(isNaN(s.charCodeAt(4)));
|
assertTrue(isNaN(s().charCodeAt(len)));
|
||||||
assertTrue(isNaN(s.charCodeAt(slowIndexOutOfRange)));
|
assertTrue(isNaN(s().charCodeAt(slowIndexOutOfRange)));
|
||||||
assertTrue(isNaN(s.charCodeAt(1/0)));
|
assertTrue(isNaN(s().charCodeAt(1/0)));
|
||||||
assertTrue(isNaN(s.charCodeAt(-1/0)));
|
assertTrue(isNaN(s().charCodeAt(-1/0)));
|
||||||
}
|
}
|
||||||
basicTest();
|
basicTest(function() { return s; }, s.length);
|
||||||
|
basicTest(getCons, getCons().length);
|
||||||
|
|
||||||
// Make sure enough of the one-char string cache is filled.
|
// Make sure enough of the one-char string cache is filled.
|
||||||
var alpha = ['@'];
|
var alpha = ['@'];
|
||||||
@ -122,7 +126,8 @@ stealTest();
|
|||||||
|
|
||||||
// Test custom string IC-s.
|
// Test custom string IC-s.
|
||||||
for (var i = 0; i < 20; i++) {
|
for (var i = 0; i < 20; i++) {
|
||||||
basicTest();
|
basicTest(function() { return s; }, s.length);
|
||||||
|
basicTest(getCons, getCons().length);
|
||||||
stealTest();
|
stealTest();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -153,6 +153,10 @@ TestStringType(Slice16End, true);
|
|||||||
TestStringType(Flat16, true);
|
TestStringType(Flat16, true);
|
||||||
TestStringType(NotAString16, true);
|
TestStringType(NotAString16, true);
|
||||||
|
|
||||||
|
for (var i = 0; i != 10; i++) {
|
||||||
|
assertEquals(101, Cons16().charCodeAt(1.1));
|
||||||
|
assertEquals('e', Cons16().charAt(1.1));
|
||||||
|
}
|
||||||
|
|
||||||
function StupidThing() {
|
function StupidThing() {
|
||||||
// Doesn't return a string from toString!
|
// Doesn't return a string from toString!
|
||||||
|
Loading…
Reference in New Issue
Block a user