| Index: test/cctest/test-api.cc
 | 
| ===================================================================
 | 
| --- test/cctest/test-api.cc	(revision 9658)
 | 
| +++ test/cctest/test-api.cc	(working copy)
 | 
| @@ -5438,67 +5438,109 @@
 | 
|  
 | 
|  
 | 
|  THREADED_TEST(StringWrite) {
 | 
| +  LocalContext context;
 | 
|    v8::HandleScope scope;
 | 
|    v8::Handle<String> str = v8_str("abcde");
 | 
|    // abc<Icelandic eth><Unicode snowman>.
 | 
|    v8::Handle<String> str2 = v8_str("abc\303\260\342\230\203");
 | 
| +  const int kStride = 4;  // Must match stride in for loops in JS below.
 | 
| +  CompileRun(
 | 
| +      "var left = '';"
 | 
| +      "for (var i = 0; i < 0xd800; i += 4) {"
 | 
| +      "  left = left + String.fromCharCode(i);"
 | 
| +      "}");
 | 
| +  CompileRun(
 | 
| +      "var right = '';"
 | 
| +      "for (var i = 0; i < 0xd800; i += 4) {"
 | 
| +      "  right = String.fromCharCode(i) + right;"
 | 
| +      "}");
 | 
| +  v8::Handle<v8::Object> global = Context::GetCurrent()->Global();
 | 
| +  Handle<String> left_tree = global->Get(v8_str("left")).As<String>();
 | 
| +  Handle<String> right_tree = global->Get(v8_str("right")).As<String>();
 | 
|  
 | 
|    CHECK_EQ(5, str2->Length());
 | 
| +  CHECK_EQ(0xd800 / kStride, left_tree->Length());
 | 
| +  CHECK_EQ(0xd800 / kStride, right_tree->Length());
 | 
|  
 | 
|    char buf[100];
 | 
| -  char utf8buf[100];
 | 
| +  char utf8buf[0xd800 * 3];
 | 
|    uint16_t wbuf[100];
 | 
|    int len;
 | 
|    int charlen;
 | 
|  
 | 
| -  memset(utf8buf, 0x1, sizeof(utf8buf));
 | 
| +  memset(utf8buf, 0x1, 1000);
 | 
|    len = str2->WriteUtf8(utf8buf, sizeof(utf8buf), &charlen);
 | 
|    CHECK_EQ(9, len);
 | 
|    CHECK_EQ(5, charlen);
 | 
|    CHECK_EQ(0, strcmp(utf8buf, "abc\303\260\342\230\203"));
 | 
|  
 | 
| -  memset(utf8buf, 0x1, sizeof(utf8buf));
 | 
| +  memset(utf8buf, 0x1, 1000);
 | 
|    len = str2->WriteUtf8(utf8buf, 8, &charlen);
 | 
|    CHECK_EQ(8, len);
 | 
|    CHECK_EQ(5, charlen);
 | 
|    CHECK_EQ(0, strncmp(utf8buf, "abc\303\260\342\230\203\1", 9));
 | 
|  
 | 
| -  memset(utf8buf, 0x1, sizeof(utf8buf));
 | 
| +  memset(utf8buf, 0x1, 1000);
 | 
|    len = str2->WriteUtf8(utf8buf, 7, &charlen);
 | 
|    CHECK_EQ(5, len);
 | 
|    CHECK_EQ(4, charlen);
 | 
|    CHECK_EQ(0, strncmp(utf8buf, "abc\303\260\1", 5));
 | 
|  
 | 
| -  memset(utf8buf, 0x1, sizeof(utf8buf));
 | 
| +  memset(utf8buf, 0x1, 1000);
 | 
|    len = str2->WriteUtf8(utf8buf, 6, &charlen);
 | 
|    CHECK_EQ(5, len);
 | 
|    CHECK_EQ(4, charlen);
 | 
|    CHECK_EQ(0, strncmp(utf8buf, "abc\303\260\1", 5));
 | 
|  
 | 
| -  memset(utf8buf, 0x1, sizeof(utf8buf));
 | 
| +  memset(utf8buf, 0x1, 1000);
 | 
|    len = str2->WriteUtf8(utf8buf, 5, &charlen);
 | 
|    CHECK_EQ(5, len);
 | 
|    CHECK_EQ(4, charlen);
 | 
|    CHECK_EQ(0, strncmp(utf8buf, "abc\303\260\1", 5));
 | 
|  
 | 
| -  memset(utf8buf, 0x1, sizeof(utf8buf));
 | 
| +  memset(utf8buf, 0x1, 1000);
 | 
|    len = str2->WriteUtf8(utf8buf, 4, &charlen);
 | 
|    CHECK_EQ(3, len);
 | 
|    CHECK_EQ(3, charlen);
 | 
|    CHECK_EQ(0, strncmp(utf8buf, "abc\1", 4));
 | 
|  
 | 
| -  memset(utf8buf, 0x1, sizeof(utf8buf));
 | 
| +  memset(utf8buf, 0x1, 1000);
 | 
|    len = str2->WriteUtf8(utf8buf, 3, &charlen);
 | 
|    CHECK_EQ(3, len);
 | 
|    CHECK_EQ(3, charlen);
 | 
|    CHECK_EQ(0, strncmp(utf8buf, "abc\1", 4));
 | 
|  
 | 
| -  memset(utf8buf, 0x1, sizeof(utf8buf));
 | 
| +  memset(utf8buf, 0x1, 1000);
 | 
|    len = str2->WriteUtf8(utf8buf, 2, &charlen);
 | 
|    CHECK_EQ(2, len);
 | 
|    CHECK_EQ(2, charlen);
 | 
|    CHECK_EQ(0, strncmp(utf8buf, "ab\1", 3));
 | 
|  
 | 
| +  memset(utf8buf, 0x1, sizeof(utf8buf));
 | 
| +  len = left_tree->Utf8Length();
 | 
| +  int utf8_expected =
 | 
| +      (0x80 + (0x800 - 0x80) * 2 + (0xd800 - 0x800) * 3) / kStride;
 | 
| +  CHECK_EQ(utf8_expected, len);
 | 
| +  len = left_tree->WriteUtf8(utf8buf, utf8_expected, &charlen);
 | 
| +  CHECK_EQ(utf8_expected, len);
 | 
| +  CHECK_EQ(0xd800 / kStride, charlen);
 | 
| +  CHECK_EQ(0xed, static_cast<unsigned char>(utf8buf[utf8_expected - 3]));
 | 
| +  CHECK_EQ(0x9f, static_cast<unsigned char>(utf8buf[utf8_expected - 2]));
 | 
| +  CHECK_EQ(0xc0 - kStride,
 | 
| +           static_cast<unsigned char>(utf8buf[utf8_expected - 1]));
 | 
| +  CHECK_EQ(1, utf8buf[utf8_expected]);
 | 
| +
 | 
| +  memset(utf8buf, 0x1, sizeof(utf8buf));
 | 
| +  len = right_tree->Utf8Length();
 | 
| +  CHECK_EQ(utf8_expected, len);
 | 
| +  len = right_tree->WriteUtf8(utf8buf, utf8_expected, &charlen);
 | 
| +  CHECK_EQ(utf8_expected, len);
 | 
| +  CHECK_EQ(0xd800 / kStride, charlen);
 | 
| +  CHECK_EQ(0xed, static_cast<unsigned char>(utf8buf[0]));
 | 
| +  CHECK_EQ(0x9f, static_cast<unsigned char>(utf8buf[1]));
 | 
| +  CHECK_EQ(0xc0 - kStride, static_cast<unsigned char>(utf8buf[2]));
 | 
| +  CHECK_EQ(1, utf8buf[utf8_expected]);
 | 
| +
 | 
|    memset(buf, 0x1, sizeof(buf));
 | 
|    memset(wbuf, 0x1, sizeof(wbuf));
 | 
|    len = str->WriteAscii(buf);
 | 
| @@ -11440,6 +11482,7 @@
 | 
|  // Test that we can still flatten a string if the components it is built up
 | 
|  // from have been turned into 16 bit strings in the mean time.
 | 
|  THREADED_TEST(MorphCompositeStringTest) {
 | 
| +  char utf_buffer[129];
 | 
|    const char* c_string = "Now is the time for all good men"
 | 
|                           " to come to the aid of the party";
 | 
|    uint16_t* two_byte_string = AsciiToTwoByteString(c_string);
 | 
| @@ -11468,6 +11511,17 @@
 | 
|      MorphAString(*v8::Utils::OpenHandle(*lhs), &ascii_resource, &uc16_resource);
 | 
|      MorphAString(*v8::Utils::OpenHandle(*rhs), &ascii_resource, &uc16_resource);
 | 
|  
 | 
| +    // This should UTF-8 without flattening, since everything is ASCII.
 | 
| +    Handle<String> cons = v8_compile("cons")->Run().As<String>();
 | 
| +    CHECK_EQ(128, cons->Utf8Length());
 | 
| +    int nchars = -1;
 | 
| +    CHECK_EQ(129, cons->WriteUtf8(utf_buffer, -1, &nchars));
 | 
| +    CHECK_EQ(128, nchars);
 | 
| +    CHECK_EQ(0, strcmp(
 | 
| +        utf_buffer,
 | 
| +        "Now is the time for all good men to come to the aid of the party"
 | 
| +        "Now is the time for all good men to come to the aid of the party"));
 | 
| +
 | 
|      // Now do some stuff to make sure the strings are flattened, etc.
 | 
|      CompileRun(
 | 
|          "/[^a-z]/.test(cons);"
 | 
| 
 |