/ API / OpaqueJSString.cpp
OpaqueJSString.cpp
  1  /*
  2   * Copyright (C) 2008-2019 Apple Inc. All rights reserved.
  3   *
  4   * Redistribution and use in source and binary forms, with or without
  5   * modification, are permitted provided that the following conditions
  6   * are met:
  7   * 1. Redistributions of source code must retain the above copyright
  8   *    notice, this list of conditions and the following disclaimer.
  9   * 2. Redistributions in binary form must reproduce the above copyright
 10   *    notice, this list of conditions and the following disclaimer in the
 11   *    documentation and/or other materials provided with the distribution.
 12   *
 13   * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
 14   * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 15   * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 16   * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
 17   * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 18   * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 19   * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 20   * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 21   * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 22   * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 23   * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
 24   */
 25  
 26  #include "config.h"
 27  #include "OpaqueJSString.h"
 28  
 29  #include "Identifier.h"
 30  #include "IdentifierInlines.h"
 31  #include <wtf/text/StringView.h>
 32  
 33  using namespace JSC;
 34  
 35  RefPtr<OpaqueJSString> OpaqueJSString::tryCreate(const String& string)
 36  {
 37      if (string.isNull())
 38          return nullptr;
 39  
 40      return adoptRef(new OpaqueJSString(string));
 41  }
 42  
 43  RefPtr<OpaqueJSString> OpaqueJSString::tryCreate(String&& string)
 44  {
 45      if (string.isNull())
 46          return nullptr;
 47  
 48      return adoptRef(new OpaqueJSString(WTFMove(string)));
 49  }
 50  
 51  OpaqueJSString::~OpaqueJSString()
 52  {
 53      // m_characters is put in a local here to avoid an extra atomic load.
 54      UChar* characters = m_characters;
 55      if (!characters)
 56          return;
 57  
 58      if (!m_string.is8Bit() && m_string.characters16() == characters)
 59          return;
 60  
 61      fastFree(characters);
 62  }
 63  
 64  String OpaqueJSString::string() const
 65  {
 66      // Return a copy of the wrapped string, because the caller may make it an Identifier.
 67      return m_string.isolatedCopy();
 68  }
 69  
 70  Identifier OpaqueJSString::identifier(VM* vm) const
 71  {
 72      if (m_string.isNull())
 73          return Identifier();
 74  
 75      if (m_string.isEmpty())
 76          return Identifier(Identifier::EmptyIdentifier);
 77  
 78      if (m_string.is8Bit())
 79          return Identifier::fromString(*vm, m_string.characters8(), m_string.length());
 80  
 81      return Identifier::fromString(*vm, m_string.characters16(), m_string.length());
 82  }
 83  
 84  const UChar* OpaqueJSString::characters()
 85  {
 86      // m_characters is put in a local here to avoid an extra atomic load.
 87      UChar* characters = m_characters;
 88      if (characters)
 89          return characters;
 90  
 91      if (m_string.isNull())
 92          return nullptr;
 93  
 94      unsigned length = m_string.length();
 95      UChar* newCharacters = static_cast<UChar*>(fastMalloc(length * sizeof(UChar)));
 96      StringView(m_string).getCharactersWithUpconvert(newCharacters);
 97  
 98      if (!m_characters.compare_exchange_strong(characters, newCharacters)) {
 99          fastFree(newCharacters);
100          return characters;
101      }
102  
103      return newCharacters;
104  }
105  
106  bool OpaqueJSString::equal(const OpaqueJSString* a, const OpaqueJSString* b)
107  {
108      if (a == b)
109          return true;
110  
111      if (!a || !b)
112          return false;
113  
114      return a->m_string == b->m_string;
115  }