summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Source/JavaScriptCore/API/JSStringRef.cpp2
-rw-r--r--Source/WTF/wtf/text/StringImpl.cpp38
-rw-r--r--Source/WTF/wtf/text/StringImpl.h42
-rw-r--r--Source/WTF/wtf/text/WTFString.cpp10
-rw-r--r--Source/WTF/wtf/text/WTFString.h1
-rw-r--r--Source/WebCore/platform/sql/SQLiteFileSystem.cpp6
-rw-r--r--Source/WebCore/platform/sql/SQLiteFileSystem.h4
-rw-r--r--Source/WebCore/platform/sql/SQLiteStatement.cpp46
-rw-r--r--Tools/TestWebKitAPI/Tests/WTF/AtomicString.cpp2
-rw-r--r--Tools/TestWebKitAPI/Tests/WTF/StringImpl.cpp3
-rw-r--r--Tools/TestWebKitAPI/Tests/WTF/WTFString.cpp2
11 files changed, 111 insertions, 45 deletions
diff --git a/Source/JavaScriptCore/API/JSStringRef.cpp b/Source/JavaScriptCore/API/JSStringRef.cpp
index a03afed5b..812f3d413 100644
--- a/Source/JavaScriptCore/API/JSStringRef.cpp
+++ b/Source/JavaScriptCore/API/JSStringRef.cpp
@@ -62,7 +62,7 @@ JSStringRef JSStringCreateWithUTF8CString(const char* string)
JSStringRef JSStringCreateWithCharactersNoCopy(const JSChar* chars, size_t numChars)
{
initializeThreading();
- return OpaqueJSString::create(StringImpl::createWithoutCopying(chars, numChars)).leakRef();
+ return OpaqueJSString::create(StringImpl::createWithoutCopying(chars, numChars, WTF::DoesNotHaveTerminatingNullCharacter)).leakRef();
}
JSStringRef JSStringRetain(JSStringRef string)
diff --git a/Source/WTF/wtf/text/StringImpl.cpp b/Source/WTF/wtf/text/StringImpl.cpp
index d1a3b56e8..5e6533e64 100644
--- a/Source/WTF/wtf/text/StringImpl.cpp
+++ b/Source/WTF/wtf/text/StringImpl.cpp
@@ -158,7 +158,7 @@ PassRefPtr<StringImpl> StringImpl::createFromLiteral(const char* characters, uns
{
ASSERT_WITH_MESSAGE(length, "Use StringImpl::empty() to create an empty string");
ASSERT(charactersAreAllASCII<LChar>(reinterpret_cast<const LChar*>(characters), length));
- return adoptRef(new StringImpl(reinterpret_cast<const LChar*>(characters), length, ConstructWithoutCopying));
+ return adoptRef(new StringImpl(reinterpret_cast<const LChar*>(characters), length, DoesHaveTerminatingNullCharacter, ConstructWithoutCopying));
}
PassRefPtr<StringImpl> StringImpl::createFromLiteral(const char* characters)
@@ -166,20 +166,20 @@ PassRefPtr<StringImpl> StringImpl::createFromLiteral(const char* characters)
return createFromLiteral(characters, strlen(characters));
}
-PassRefPtr<StringImpl> StringImpl::createWithoutCopying(const UChar* characters, unsigned length)
+PassRefPtr<StringImpl> StringImpl::createWithoutCopying(const UChar* characters, unsigned length, HasTerminatingNullCharacter hasTerminatingNullCharacter)
{
if (!length)
return empty();
- return adoptRef(new StringImpl(characters, length, ConstructWithoutCopying));
+ return adoptRef(new StringImpl(characters, length, hasTerminatingNullCharacter, ConstructWithoutCopying));
}
-PassRefPtr<StringImpl> StringImpl::createWithoutCopying(const LChar* characters, unsigned length)
+PassRefPtr<StringImpl> StringImpl::createWithoutCopying(const LChar* characters, unsigned length, HasTerminatingNullCharacter hasTerminatingNullCharacter)
{
if (!length)
return empty();
- return adoptRef(new StringImpl(characters, length, ConstructWithoutCopying));
+ return adoptRef(new StringImpl(characters, length, hasTerminatingNullCharacter, ConstructWithoutCopying));
}
template <typename CharType>
@@ -315,6 +315,8 @@ const UChar* StringImpl::getData16SlowCase() const
STRING_STATS_ADD_UPCONVERTED_STRING(m_length);
unsigned len = length();
+ if (hasTerminatingNullCharacter())
+ ++len;
m_copyData16 = static_cast<UChar*>(fastMalloc(len * sizeof(UChar)));
@@ -1935,6 +1937,30 @@ PassRefPtr<StringImpl> StringImpl::adopt(QStringData* qStringData)
}
#endif
+PassRefPtr<StringImpl> StringImpl::createWithTerminatingNullCharacter(const StringImpl& string)
+{
+ // Use createUninitialized instead of 'new StringImpl' so that the string and its buffer
+ // get allocated in a single memory block.
+ unsigned length = string.m_length;
+ if (length >= numeric_limits<unsigned>::max())
+ CRASH();
+ RefPtr<StringImpl> terminatedString;
+ if (string.is8Bit()) {
+ LChar* data;
+ terminatedString = createUninitialized(length + 1, data);
+ memcpy(data, string.m_data8, length * sizeof(LChar));
+ data[length] = 0;
+ } else {
+ UChar* data;
+ terminatedString = createUninitialized(length + 1, data);
+ memcpy(data, string.m_data16, length * sizeof(UChar));
+ data[length] = 0;
+ }
+ --(terminatedString->m_length);
+ terminatedString->m_hashAndFlags = (string.m_hashAndFlags & (~s_flagMask | s_hashFlag8BitBuffer)) | s_hashFlagHasTerminatingNullCharacter;
+ return terminatedString.release();
+}
+
size_t StringImpl::sizeInBytes() const
{
// FIXME: support substrings
@@ -1942,6 +1968,8 @@ size_t StringImpl::sizeInBytes() const
if (is8Bit()) {
if (has16BitShadow()) {
size += 2 * size;
+ if (hasTerminatingNullCharacter())
+ size += 2;
}
} else
size *= 2;
diff --git a/Source/WTF/wtf/text/StringImpl.h b/Source/WTF/wtf/text/StringImpl.h
index 0d6c358a4..a0dd3021c 100644
--- a/Source/WTF/wtf/text/StringImpl.h
+++ b/Source/WTF/wtf/text/StringImpl.h
@@ -73,6 +73,12 @@ enum TextCaseSensitivity {
TextCaseInsensitive
};
+enum HasTerminatingNullCharacter {
+ DoesNotHaveTerminatingNullCharacter,
+ DoesHaveTerminatingNullCharacter,
+};
+
+
typedef bool (*CharacterMatchFunctionPtr)(UChar);
typedef bool (*IsWhiteSpaceFunctionPtr)(UChar);
@@ -243,28 +249,30 @@ private:
}
enum ConstructWithoutCopyingTag { ConstructWithoutCopying };
- StringImpl(const UChar* characters, unsigned length, ConstructWithoutCopyingTag)
+ StringImpl(const UChar* characters, unsigned length, HasTerminatingNullCharacter hasTerminatingNullCharacter, ConstructWithoutCopyingTag)
: m_refCount(s_refCountIncrement)
, m_length(length)
, m_data16(characters)
, m_buffer(0)
- , m_hashAndFlags(BufferInternal)
+ , m_hashAndFlags(BufferInternal | (hasTerminatingNullCharacter ? s_hashFlagHasTerminatingNullCharacter : 0))
{
ASSERT(m_data16);
ASSERT(m_length);
+ ASSERT(!(m_hashAndFlags & s_hashFlagHasTerminatingNullCharacter) || !characters[length]);
STRING_STATS_ADD_16BIT_STRING(0);
}
- StringImpl(const LChar* characters, unsigned length, ConstructWithoutCopyingTag)
+ StringImpl(const LChar* characters, unsigned length, HasTerminatingNullCharacter hasTerminatingNullCharacter, ConstructWithoutCopyingTag)
: m_refCount(s_refCountIncrement)
, m_length(length)
, m_data8(characters)
, m_buffer(0)
- , m_hashAndFlags(s_hashFlag8BitBuffer | BufferInternal)
+ , m_hashAndFlags(s_hashFlag8BitBuffer | BufferInternal | (hasTerminatingNullCharacter ? s_hashFlagHasTerminatingNullCharacter : 0))
{
ASSERT(m_data8);
ASSERT(m_length);
+ ASSERT(!(m_hashAndFlags & s_hashFlagHasTerminatingNullCharacter) || !characters[length]);
STRING_STATS_ADD_8BIT_STRING(0);
}
@@ -413,15 +421,15 @@ public:
COMPILE_ASSERT(charactersCount > 1, StringImplFromLiteralNotEmpty);
COMPILE_ASSERT((charactersCount - 1 <= ((unsigned(~0) - sizeof(StringImpl)) / sizeof(LChar))), StringImplFromLiteralCannotOverflow);
- return createWithoutCopying(reinterpret_cast<const LChar*>(characters), charactersCount - 1);
+ return createWithoutCopying(reinterpret_cast<const LChar*>(characters), charactersCount - 1, DoesHaveTerminatingNullCharacter);
}
// FIXME: Transition off of these functions to createWithoutCopying instead.
WTF_EXPORT_STRING_API static PassRefPtr<StringImpl> createFromLiteral(const char* characters, unsigned length);
WTF_EXPORT_STRING_API static PassRefPtr<StringImpl> createFromLiteral(const char* characters);
- WTF_EXPORT_STRING_API static PassRefPtr<StringImpl> createWithoutCopying(const UChar* characters, unsigned length);
- WTF_EXPORT_STRING_API static PassRefPtr<StringImpl> createWithoutCopying(const LChar* characters, unsigned length);
+ WTF_EXPORT_STRING_API static PassRefPtr<StringImpl> createWithoutCopying(const UChar* characters, unsigned length, HasTerminatingNullCharacter);
+ WTF_EXPORT_STRING_API static PassRefPtr<StringImpl> createWithoutCopying(const LChar* characters, unsigned length, HasTerminatingNullCharacter);
WTF_EXPORT_STRING_API static PassRefPtr<StringImpl> createUninitialized(unsigned length, LChar*& data);
WTF_EXPORT_STRING_API static PassRefPtr<StringImpl> createUninitialized(unsigned length, UChar*& data);
@@ -460,6 +468,7 @@ public:
static unsigned flagsOffset() { return OBJECT_OFFSETOF(StringImpl, m_hashAndFlags); }
static unsigned flagIs8Bit() { return s_hashFlag8BitBuffer; }
static unsigned dataOffset() { return OBJECT_OFFSETOF(StringImpl, m_data8); }
+ static PassRefPtr<StringImpl> createWithTerminatingNullCharacter(const StringImpl&);
template<typename CharType, size_t inlineCapacity, typename OverflowHandler>
static PassRefPtr<StringImpl> adopt(Vector<CharType, inlineCapacity, OverflowHandler>& vector)
@@ -529,6 +538,8 @@ public:
return !length() && !isStatic();
}
+ bool hasTerminatingNullCharacter() const { return m_hashAndFlags & s_hashFlagHasTerminatingNullCharacter; }
+
bool isAtomic() const { return m_hashAndFlags & s_hashFlagIsAtomic; }
void setIsAtomic(bool isAtomic)
{
@@ -778,13 +789,14 @@ private:
static const unsigned s_refCountFlagIsStaticString = 0x1;
static const unsigned s_refCountIncrement = 0x2; // This allows us to ref / deref without disturbing the static string flag.
- // The bottom 7 bits in the hash are flags.
- static const unsigned s_flagCount = 7;
+ // The bottom 8 bits in the hash are flags.
+ static const unsigned s_flagCount = 8;
static const unsigned s_flagMask = (1u << s_flagCount) - 1;
- COMPILE_ASSERT(s_flagCount <= StringHasher::flagCount, StringHasher_reserves_enough_bits_for_StringImpl_flags);
+ COMPILE_ASSERT(s_flagCount == StringHasher::flagCount, StringHasher_reserves_enough_bits_for_StringImpl_flags);
- static const unsigned s_hashFlagHas16BitShadow = 1u << 6;
- static const unsigned s_hashFlag8BitBuffer = 1u << 5;
+ static const unsigned s_hashFlagHas16BitShadow = 1u << 7;
+ static const unsigned s_hashFlag8BitBuffer = 1u << 6;
+ static const unsigned s_hashFlagHasTerminatingNullCharacter = 1u << 5;
static const unsigned s_hashFlagIsAtomic = 1u << 4;
static const unsigned s_hashFlagDidReportCost = 1u << 3;
static const unsigned s_hashFlagIsIdentifier = 1u << 2;
@@ -805,7 +817,7 @@ public:
// These values mimic ConstructFromLiteral.
static const unsigned s_initialRefCount = s_refCountIncrement;
- static const unsigned s_initialFlags = s_hashFlag8BitBuffer | BufferInternal;
+ static const unsigned s_initialFlags = s_hashFlag8BitBuffer | BufferInternal | s_hashFlagHasTerminatingNullCharacter;
static const unsigned s_hashShift = s_flagCount;
};
@@ -1330,8 +1342,8 @@ inline PassRefPtr<StringImpl> StringImpl::isolatedCopy() const
{
if (!requiresCopy()) {
if (is8Bit())
- return StringImpl::createWithoutCopying(m_data8, m_length);
- return StringImpl::createWithoutCopying(m_data16, m_length);
+ return StringImpl::createWithoutCopying(m_data8, m_length, hasTerminatingNullCharacter() ? DoesHaveTerminatingNullCharacter : DoesNotHaveTerminatingNullCharacter);
+ return StringImpl::createWithoutCopying(m_data16, m_length, hasTerminatingNullCharacter() ? DoesHaveTerminatingNullCharacter : DoesNotHaveTerminatingNullCharacter);
}
if (is8Bit())
diff --git a/Source/WTF/wtf/text/WTFString.cpp b/Source/WTF/wtf/text/WTFString.cpp
index 29c13c10d..a61fe103f 100644
--- a/Source/WTF/wtf/text/WTFString.cpp
+++ b/Source/WTF/wtf/text/WTFString.cpp
@@ -409,6 +409,16 @@ Vector<UChar> String::charactersWithNullTermination() const
return result;
}
+const UChar* String::deprecatedCharactersWithNullTermination()
+{
+ if (!m_impl)
+ return 0;
+ if (m_impl->hasTerminatingNullCharacter())
+ return m_impl->characters();
+ m_impl = StringImpl::createWithTerminatingNullCharacter(*m_impl);
+ return m_impl->characters();
+}
+
String String::format(const char *format, ...)
{
#if PLATFORM(QT)
diff --git a/Source/WTF/wtf/text/WTFString.h b/Source/WTF/wtf/text/WTFString.h
index 1c8e9097e..63feb0fa1 100644
--- a/Source/WTF/wtf/text/WTFString.h
+++ b/Source/WTF/wtf/text/WTFString.h
@@ -282,6 +282,7 @@ public:
{ return caseSensitive ? reverseFind(str, start) : reverseFindIgnoringCase(str, start); }
WTF_EXPORT_STRING_API Vector<UChar> charactersWithNullTermination() const;
+ WTF_EXPORT_STRING_API const UChar* deprecatedCharactersWithNullTermination();
WTF_EXPORT_STRING_API UChar32 characterStartingAt(unsigned) const; // Ditto.
diff --git a/Source/WebCore/platform/sql/SQLiteFileSystem.cpp b/Source/WebCore/platform/sql/SQLiteFileSystem.cpp
index 735f0b41f..cbf8883ed 100644
--- a/Source/WebCore/platform/sql/SQLiteFileSystem.cpp
+++ b/Source/WebCore/platform/sql/SQLiteFileSystem.cpp
@@ -44,9 +44,11 @@ SQLiteFileSystem::SQLiteFileSystem()
{
}
-int SQLiteFileSystem::openDatabase(const String& filename, sqlite3** database, bool)
+int SQLiteFileSystem::openDatabase(const String& fileName, sqlite3** database, bool)
{
- return sqlite3_open(filename.utf8().data(), database);
+ // SQLite expects a null terminator on its UTF-16 strings.
+ String path = fileName;
+ return sqlite3_open16(path.deprecatedCharactersWithNullTermination(), database);
}
String SQLiteFileSystem::getFileNameForNewDatabase(const String& dbDir, const String&,
diff --git a/Source/WebCore/platform/sql/SQLiteFileSystem.h b/Source/WebCore/platform/sql/SQLiteFileSystem.h
index 14085b929..9800f7e54 100644
--- a/Source/WebCore/platform/sql/SQLiteFileSystem.h
+++ b/Source/WebCore/platform/sql/SQLiteFileSystem.h
@@ -46,13 +46,13 @@ class SQLiteFileSystem {
public:
// Opens a database file.
//
- // filemame - The name of the database file.
+ // fileName - The name of the database file.
// database - The SQLite structure that represents the database stored
// in the given file.
// forWebSQLDatabase - True, if and only if we're opening a Web SQL Database file.
// Used by Chromium to determine if the DB file needs to be opened
// using a custom VFS.
- static int openDatabase(const String& filename, sqlite3** database, bool forWebSQLDatabase);
+ static int openDatabase(const String& fileName, sqlite3** database, bool forWebSQLDatabase);
// Returns the file name for a database.
//
diff --git a/Source/WebCore/platform/sql/SQLiteStatement.cpp b/Source/WebCore/platform/sql/SQLiteStatement.cpp
index 1203e84ee..fd2af3286 100644
--- a/Source/WebCore/platform/sql/SQLiteStatement.cpp
+++ b/Source/WebCore/platform/sql/SQLiteStatement.cpp
@@ -32,14 +32,18 @@
#include <wtf/Assertions.h>
#include <wtf/text/StringImpl.h>
-// SQLite 3.6.16 makes sqlite3_prepare_v2 automatically retry preparing the statement
-// once if the database scheme has changed. We rely on this behavior.
-#if SQLITE_VERSION_NUMBER < 3006016
-#error SQLite version 3.6.16 or newer is required
-#endif
-
namespace WebCore {
+#if SQLITE_VERSION_NUMBER < 3003009
+
+// FIXME: This overload helps us compile with older versions of SQLite 3, but things like quotas will not work.
+static inline int sqlite3_prepare16_v2(sqlite3* db, const void* zSql, int nBytes, sqlite3_stmt** ppStmt, const void** pzTail)
+{
+ return sqlite3_prepare16(db, zSql, nBytes, ppStmt, pzTail);
+}
+
+#endif
+
SQLiteStatement::SQLiteStatement(SQLiteDatabase& db, const String& sql)
: m_database(db)
, m_query(sql)
@@ -63,23 +67,25 @@ int SQLiteStatement::prepare()
if (m_database.isInterrupted())
return SQLITE_INTERRUPT;
- CString query = m_query.stripWhiteSpace().utf8();
-
- LOG(SQLDatabase, "SQL - prepare - %s", query.data());
-
- // Pass the length of the string including the null character to sqlite3_prepare_v2;
- // this lets SQLite avoid an extra string copy.
- size_t lengthIncludingNullCharacter = query.length() + 1;
-
- const char* tail;
- int error = sqlite3_prepare_v2(m_database.sqlite3Handle(), query.data(), lengthIncludingNullCharacter, &m_statement, &tail);
+ const void* tail = 0;
+ LOG(SQLDatabase, "SQL - prepare - %s", m_query.ascii().data());
+ String strippedQuery = m_query.stripWhiteSpace();
+ const UChar* nullTermed = strippedQuery.deprecatedCharactersWithNullTermination();
+ int error = sqlite3_prepare16_v2(m_database.sqlite3Handle(), nullTermed, -1, &m_statement, &tail);
+
+ // Starting with version 3.6.16, sqlite has a patch (http://www.sqlite.org/src/ci/256ec3c6af)
+ // that should make sure sqlite3_prepare16_v2 doesn't return a SQLITE_SCHEMA error.
+ // If we're using an older sqlite version, try to emulate the patch.
+ if (error == SQLITE_SCHEMA) {
+ sqlite3_finalize(m_statement);
+ error = sqlite3_prepare16_v2(m_database.sqlite3Handle(), m_query.deprecatedCharactersWithNullTermination(), -1, &m_statement, &tail);
+ }
if (error != SQLITE_OK)
- LOG(SQLDatabase, "sqlite3_prepare16 failed (%i)\n%s\n%s", error, query.data(), sqlite3_errmsg(m_database.sqlite3Handle()));
-
- if (tail && *tail)
+ LOG(SQLDatabase, "sqlite3_prepare16 failed (%i)\n%s\n%s", error, m_query.ascii().data(), sqlite3_errmsg(m_database.sqlite3Handle()));
+ const UChar* ch = static_cast<const UChar*>(tail);
+ if (ch && *ch)
error = SQLITE_ERROR;
-
#ifndef NDEBUG
m_isPrepared = error == SQLITE_OK;
#endif
diff --git a/Tools/TestWebKitAPI/Tests/WTF/AtomicString.cpp b/Tools/TestWebKitAPI/Tests/WTF/AtomicString.cpp
index 9df71ce44..bddf22c23 100644
--- a/Tools/TestWebKitAPI/Tests/WTF/AtomicString.cpp
+++ b/Tools/TestWebKitAPI/Tests/WTF/AtomicString.cpp
@@ -35,12 +35,14 @@ TEST(WTF, AtomicStringCreationFromLiteral)
ASSERT_EQ(strlen("Template Literal"), stringWithTemplate.length());
ASSERT_TRUE(stringWithTemplate == "Template Literal");
ASSERT_TRUE(stringWithTemplate.string().is8Bit());
+ ASSERT_TRUE(stringWithTemplate.impl()->hasTerminatingNullCharacter());
const char* programmaticStringData = "Explicit Size Literal";
AtomicString programmaticString(programmaticStringData, strlen(programmaticStringData), AtomicString::ConstructFromLiteral);
ASSERT_EQ(strlen(programmaticStringData), programmaticString.length());
ASSERT_TRUE(programmaticStringData == programmaticStringData);
ASSERT_TRUE(programmaticString.string().is8Bit());
+ ASSERT_TRUE(programmaticString.impl()->hasTerminatingNullCharacter());
ASSERT_EQ(programmaticStringData, reinterpret_cast<const char*>(programmaticString.string().characters8()));
}
diff --git a/Tools/TestWebKitAPI/Tests/WTF/StringImpl.cpp b/Tools/TestWebKitAPI/Tests/WTF/StringImpl.cpp
index 10ab9e2cb..35d64844c 100644
--- a/Tools/TestWebKitAPI/Tests/WTF/StringImpl.cpp
+++ b/Tools/TestWebKitAPI/Tests/WTF/StringImpl.cpp
@@ -37,6 +37,7 @@ TEST(WTF, StringImplCreationFromLiteral)
ASSERT_EQ(strlen("Template Literal"), stringWithTemplate->length());
ASSERT_TRUE(equal(stringWithTemplate.get(), "Template Literal"));
ASSERT_TRUE(stringWithTemplate->is8Bit());
+ ASSERT_TRUE(stringWithTemplate->hasTerminatingNullCharacter());
// Constructor taking the size explicitely.
const char* programmaticStringData = "Explicit Size Literal";
@@ -45,6 +46,7 @@ TEST(WTF, StringImplCreationFromLiteral)
ASSERT_TRUE(equal(programmaticString.get(), programmaticStringData));
ASSERT_EQ(programmaticStringData, reinterpret_cast<const char*>(programmaticString->characters8()));
ASSERT_TRUE(programmaticString->is8Bit());
+ ASSERT_TRUE(programmaticString->hasTerminatingNullCharacter());
// Constructor without explicit size.
const char* stringWithoutLengthLiteral = "No Size Literal";
@@ -53,6 +55,7 @@ TEST(WTF, StringImplCreationFromLiteral)
ASSERT_TRUE(equal(programmaticStringNoLength.get(), stringWithoutLengthLiteral));
ASSERT_EQ(stringWithoutLengthLiteral, reinterpret_cast<const char*>(programmaticStringNoLength->characters8()));
ASSERT_TRUE(programmaticStringNoLength->is8Bit());
+ ASSERT_TRUE(programmaticStringNoLength->hasTerminatingNullCharacter());
}
TEST(WTF, StringImplFromLiteralLoop16BitConversion)
diff --git a/Tools/TestWebKitAPI/Tests/WTF/WTFString.cpp b/Tools/TestWebKitAPI/Tests/WTF/WTFString.cpp
index 3da40ff83..4a92cd4e8 100644
--- a/Tools/TestWebKitAPI/Tests/WTF/WTFString.cpp
+++ b/Tools/TestWebKitAPI/Tests/WTF/WTFString.cpp
@@ -38,12 +38,14 @@ TEST(WTF, StringCreationFromLiteral)
ASSERT_EQ(strlen("Explicit construction syntax"), stringFromLiteral.length());
ASSERT_TRUE(stringFromLiteral == "Explicit construction syntax");
ASSERT_TRUE(stringFromLiteral.is8Bit());
+ ASSERT_TRUE(stringFromLiteral.impl()->hasTerminatingNullCharacter());
ASSERT_TRUE(String("Explicit construction syntax") == stringFromLiteral);
String stringWithTemplate("Template Literal", String::ConstructFromLiteral);
ASSERT_EQ(strlen("Template Literal"), stringWithTemplate.length());
ASSERT_TRUE(stringWithTemplate == "Template Literal");
ASSERT_TRUE(stringWithTemplate.is8Bit());
+ ASSERT_TRUE(stringWithTemplate.impl()->hasTerminatingNullCharacter());
ASSERT_TRUE(String("Template Literal") == stringWithTemplate);
}