Rename AtomicString to AtomString
[WebKit-https.git] / Source / JavaScriptCore / runtime / Identifier.h
index f5e168f..104a147 100644 (file)
  *
  */
 
-#ifndef Identifier_h
-#define Identifier_h
+#pragma once
 
+#include "PrivateName.h"
 #include "VM.h"
 #include <wtf/Optional.h>
-#include <wtf/ThreadSpecific.h>
-#include <wtf/WTFThreadData.h>
 #include <wtf/text/CString.h>
+#include <wtf/text/UniquedStringImpl.h>
 #include <wtf/text/WTFString.h>
 
 namespace JSC {
@@ -42,38 +41,38 @@ ALWAYS_INLINE Optional<uint32_t> parseIndex(const CharType* characters, unsigned
 {
     // An empty string is not a number.
     if (!length)
-        return Nullopt;
+        return WTF::nullopt;
 
     // Get the first character, turning it into a digit.
     uint32_t value = characters[0] - '0';
     if (value > 9)
-        return Nullopt;
+        return WTF::nullopt;
 
     // Check for leading zeros. If the first characher is 0, then the
     // length of the string must be one - e.g. "042" is not equal to "42".
     if (!value && length > 1)
-        return Nullopt;
+        return WTF::nullopt;
 
     while (--length) {
         // Multiply value by 10, checking for overflow out of 32 bits.
         if (value > 0xFFFFFFFFU / 10)
-            return Nullopt;
+            return WTF::nullopt;
         value *= 10;
 
         // Get the next character, turning it into a digit.
         uint32_t newValue = *(++characters) - '0';
         if (newValue > 9)
-            return Nullopt;
+            return WTF::nullopt;
 
         // Add in the old value, checking for overflow out of 32 bits.
         newValue += value;
         if (newValue < value)
-            return Nullopt;
+            return WTF::nullopt;
         value = newValue;
     }
 
     if (!isIndex(value))
-        return Nullopt;
+        return WTF::nullopt;
     return value;
 }
 
@@ -89,10 +88,10 @@ class Identifier {
 public:
     Identifier() { }
     enum EmptyIdentifierFlag { EmptyIdentifier };
-    Identifier(EmptyIdentifierFlag) : m_string(StringImpl::empty()) { ASSERT(m_string.impl()->isAtomic()); }
+    Identifier(EmptyIdentifierFlag) : m_string(StringImpl::empty()) { ASSERT(m_string.impl()->isAtom()); }
 
     const String& string() const { return m_string; }
-    AtomicStringImpl* impl() const { return static_cast<AtomicStringImpl*>(m_string.impl()); }
+    UniquedStringImpl* impl() const { return static_cast<UniquedStringImpl*>(m_string.impl()); }
 
     int length() const { return m_string.length(); }
 
@@ -118,14 +117,16 @@ public:
     static Identifier fromString(VM*, const LChar*, int length);
     static Identifier fromString(VM*, const UChar*, int length);
     static Identifier fromString(VM*, const String&);
-    static Identifier fromString(ExecState*, AtomicStringImpl*);
-    static Identifier fromString(ExecState*, const AtomicString&);
+    static Identifier fromString(ExecState*, AtomStringImpl*);
+    static Identifier fromString(ExecState*, const AtomString&);
     static Identifier fromString(ExecState*, const String&);
     static Identifier fromString(ExecState*, const char*);
+    static Identifier fromString(VM* vm, const Vector<LChar>& characters) { return fromString(vm, characters.data(), characters.size()); }
 
-    static Identifier fromUid(VM*, StringImpl* uid);
-    static Identifier fromUid(ExecState*, StringImpl* uid);
+    static Identifier fromUid(VM*, UniquedStringImpl* uid);
+    static Identifier fromUid(ExecState*, UniquedStringImpl* uid);
     static Identifier fromUid(const PrivateName&);
+    static Identifier fromUid(SymbolImpl&);
 
     static Identifier createLCharFromUChar(VM* vm, const UChar* s, int length) { return Identifier(vm, add8(vm, s, length)); }
 
@@ -139,6 +140,7 @@ public:
     bool isNull() const { return m_string.isNull(); }
     bool isEmpty() const { return m_string.isEmpty(); }
     bool isSymbol() const { return !isNull() && impl()->isSymbol(); }
+    bool isPrivateName() const { return isSymbol() && static_cast<const SymbolImpl*>(impl())->isPrivate(); }
 
     friend bool operator==(const Identifier&, const Identifier&);
     friend bool operator!=(const Identifier&, const Identifier&);
@@ -165,17 +167,19 @@ private:
 
     // Only to be used with string literals.
     template<unsigned charactersCount>
-    Identifier(VM* vm, const char (&characters)[charactersCount]) : m_string(add(vm, characters)) { ASSERT(m_string.impl()->isAtomic()); }
-
-    Identifier(VM* vm, const LChar* s, int length) : m_string(add(vm, s, length)) { ASSERT(m_string.impl()->isAtomic()); }
-    Identifier(VM* vm, const UChar* s, int length) : m_string(add(vm, s, length)) { ASSERT(m_string.impl()->isAtomic()); }
-    Identifier(ExecState*, AtomicStringImpl*);
-    Identifier(ExecState*, const AtomicString&);
-    Identifier(VM* vm, const String& string) : m_string(add(vm, string.impl())) { ASSERT(m_string.impl()->isAtomic()); }
-    Identifier(VM* vm, StringImpl* rep) : m_string(add(vm, rep)) { ASSERT(m_string.impl()->isAtomic()); }
-
-    enum UniqueIdentifierFlag { UniqueIdentifier };
-    Identifier(UniqueIdentifierFlag, StringImpl* uid) : m_string(uid) { ASSERT(m_string.impl()->isSymbol()); }
+    Identifier(VM* vm, const char (&characters)[charactersCount]) : m_string(add(vm, characters)) { ASSERT(m_string.impl()->isAtom()); }
+
+    Identifier(VM* vm, const LChar* s, int length) : m_string(add(vm, s, length)) { ASSERT(m_string.impl()->isAtom()); }
+    Identifier(VM* vm, const UChar* s, int length) : m_string(add(vm, s, length)) { ASSERT(m_string.impl()->isAtom()); }
+    Identifier(ExecState*, AtomStringImpl*);
+    Identifier(ExecState*, const AtomString&);
+    Identifier(VM* vm, const String& string) : m_string(add(vm, string.impl())) { ASSERT(m_string.impl()->isAtom()); }
+    Identifier(VM* vm, StringImpl* rep) : m_string(add(vm, rep)) { ASSERT(m_string.impl()->isAtom()); }
+
+    Identifier(SymbolImpl& uid)
+        : m_string(&uid)
+    {
+    }
 
     template <typename CharType>
     ALWAYS_INLINE static uint32_t toUInt32FromCharacters(const CharType* characters, unsigned length, bool& ok);
@@ -191,11 +195,11 @@ private:
     static Ref<StringImpl> add(VM*, StringImpl*);
 
 #ifndef NDEBUG
-    JS_EXPORT_PRIVATE static void checkCurrentAtomicStringTable(ExecState*);
-    JS_EXPORT_PRIVATE static void checkCurrentAtomicStringTable(VM*);
+    JS_EXPORT_PRIVATE static void checkCurrentAtomStringTable(ExecState*);
+    JS_EXPORT_PRIVATE static void checkCurrentAtomStringTable(VM*);
 #else
-    JS_EXPORT_PRIVATE NO_RETURN_DUE_TO_CRASH static void checkCurrentAtomicStringTable(ExecState*);
-    JS_EXPORT_PRIVATE NO_RETURN_DUE_TO_CRASH static void checkCurrentAtomicStringTable(VM*);
+    JS_EXPORT_PRIVATE NO_RETURN_DUE_TO_CRASH static void checkCurrentAtomStringTable(ExecState*);
+    JS_EXPORT_PRIVATE NO_RETURN_DUE_TO_CRASH static void checkCurrentAtomStringTable(VM*);
 #endif
 };
 
@@ -216,12 +220,12 @@ Ref<StringImpl> Identifier::add(VM* vm, const T* s, int length)
     if (length == 1) {
         T c = s[0];
         if (canUseSingleCharacterString(c))
-            return *vm->smallStrings.singleCharacterStringRep(c);
+            return vm->smallStrings.singleCharacterStringRep(c);
     }
     if (!length)
         return *StringImpl::empty();
 
-    return *AtomicString::add(s, length);
+    return *AtomStringImpl::add(s, length);
 }
 
 inline bool operator==(const Identifier& a, const Identifier& b)
@@ -271,17 +275,26 @@ inline bool Identifier::equal(const StringImpl* r, const UChar* s, unsigned leng
 
 ALWAYS_INLINE Optional<uint32_t> parseIndex(const Identifier& identifier)
 {
-    AtomicStringImpl* uid = identifier.impl();
+    auto uid = identifier.impl();
     if (!uid)
-        return Nullopt;
+        return WTF::nullopt;
     if (uid->isSymbol())
-        return Nullopt;
+        return WTF::nullopt;
     return parseIndex(*uid);
 }
 
-struct IdentifierRepHash : PtrHash<RefPtr<StringImpl>> {
-    static unsigned hash(const RefPtr<StringImpl>& key) { return key->existingHash(); }
-    static unsigned hash(StringImpl* key) { return key->existingHash(); }
+JSValue identifierToJSValue(VM&, const Identifier&);
+// This will stringify private symbols. When leaking JSValues to
+// non-internal code, make sure to use this function and not the above one.
+JSValue identifierToSafePublicJSValue(VM&, const Identifier&);
+
+// FIXME: It may be better for this to just be a typedef for PtrHash, since PtrHash may be cheaper to
+// compute than loading the StringImpl's hash from memory. That change would also reduce the likelihood of
+// crashes in code that somehow dangled a StringImpl.
+// https://bugs.webkit.org/show_bug.cgi?id=150137
+struct IdentifierRepHash : PtrHash<RefPtr<UniquedStringImpl>> {
+    static unsigned hash(const RefPtr<UniquedStringImpl>& key) { return key->existingSymbolAwareHash(); }
+    static unsigned hash(UniquedStringImpl* key) { return key->existingSymbolAwareHash(); }
 };
 
 struct IdentifierMapIndexHashTraits : HashTraits<int> {
@@ -289,8 +302,9 @@ struct IdentifierMapIndexHashTraits : HashTraits<int> {
     static const bool emptyValueIsZero = false;
 };
 
-typedef HashMap<RefPtr<StringImpl>, int, IdentifierRepHash, HashTraits<RefPtr<StringImpl>>, IdentifierMapIndexHashTraits> IdentifierMap;
-typedef HashMap<StringImpl*, int, IdentifierRepHash, HashTraits<StringImpl*>, IdentifierMapIndexHashTraits> BorrowedIdentifierMap;
+typedef HashSet<RefPtr<UniquedStringImpl>, IdentifierRepHash> IdentifierSet;
+typedef HashMap<RefPtr<UniquedStringImpl>, int, IdentifierRepHash, HashTraits<RefPtr<UniquedStringImpl>>, IdentifierMapIndexHashTraits> IdentifierMap;
+typedef HashMap<UniquedStringImpl*, int, IdentifierRepHash, HashTraits<UniquedStringImpl*>, IdentifierMapIndexHashTraits> BorrowedIdentifierMap;
 
 } // namespace JSC
 
@@ -299,5 +313,3 @@ namespace WTF {
 template <> struct VectorTraits<JSC::Identifier> : SimpleClassVectorTraits { };
 
 } // namespace WTF
-
-#endif // Identifier_h