@@ -1693,6 +1693,64 @@ TEST(StringEquals) {
1693
1693
CHECK (!bar_str->StringEquals (foo_str2));
1694
1694
}
1695
1695
1696
+ class OneByteStringResource : public v8 ::String::ExternalOneByteStringResource {
1697
+ public:
1698
+ // Takes ownership of |data|.
1699
+ OneByteStringResource (char * data, size_t length)
1700
+ : data_(data), length_(length) {}
1701
+ ~OneByteStringResource () override { delete[] data_; }
1702
+ const char * data () const override { return data_; }
1703
+ size_t length () const override { return length_; }
1704
+
1705
+ private:
1706
+ char * data_;
1707
+ size_t length_;
1708
+ };
1709
+
1710
+ TEST (Regress876759) {
1711
+ v8::V8::Initialize ();
1712
+ Isolate* isolate = CcTest::i_isolate ();
1713
+ Factory* factory = isolate->factory ();
1714
+
1715
+ HandleScope handle_scope (isolate);
1716
+
1717
+ const int kLength = 30 ;
1718
+ uc16 two_byte_buf[kLength ];
1719
+ char * external_one_byte_buf = new char [kLength ];
1720
+ for (int j = 0 ; j < kLength ; j++) {
1721
+ char c = ' 0' + (j % 10 );
1722
+ two_byte_buf[j] = c;
1723
+ external_one_byte_buf[j] = c;
1724
+ }
1725
+
1726
+ Handle <String> parent;
1727
+ {
1728
+ Handle <SeqTwoByteString> raw =
1729
+ factory->NewRawTwoByteString (kLength ).ToHandleChecked ();
1730
+ CopyChars (raw->GetChars (), two_byte_buf, kLength );
1731
+ parent = raw;
1732
+ }
1733
+ CHECK (parent->IsTwoByteRepresentation ());
1734
+ Handle <String> sliced = factory->NewSubString (parent, 1 , 20 );
1735
+ CHECK (sliced->IsSlicedString ());
1736
+ factory->InternalizeString (parent);
1737
+ CHECK (parent->IsThinString ());
1738
+ Handle <String> grandparent =
1739
+ handle (ThinString::cast (*parent)->actual (), isolate);
1740
+ CHECK_EQ (*parent, SlicedString::cast (*sliced)->parent ());
1741
+ OneByteStringResource* resource =
1742
+ new OneByteStringResource (external_one_byte_buf, kLength );
1743
+ grandparent->MakeExternal (resource);
1744
+ // The grandparent string becomes one-byte, but the child strings are still
1745
+ // two-byte.
1746
+ CHECK (grandparent->IsOneByteRepresentation ());
1747
+ CHECK (parent->IsTwoByteRepresentation ());
1748
+ CHECK (sliced->IsTwoByteRepresentation ());
1749
+ // The *Underneath versions return the correct representation.
1750
+ CHECK (sliced->IsOneByteRepresentationUnderneath ());
1751
+ CHECK (!sliced->IsTwoByteRepresentationUnderneath ());
1752
+ }
1753
+
1696
1754
} // namespace test_strings
1697
1755
} // namespace internal
1698
1756
} // namespace v8
0 commit comments