Rename StringBuilder::append(UChar32) to StringBuilder::appendCharacter(UChar32)...
[WebKit-https.git] / Source / WebCore / bindings / js / JSDOMConvertStrings.cpp
1 /*
2  *  Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
3  *  Copyright (C) 2004-2011, 2013, 2016 Apple Inc. All rights reserved.
4  *  Copyright (C) 2007 Samuel Weinig <sam@webkit.org>
5  *  Copyright (C) 2013 Michael Pruett <michael@68k.org>
6  *
7  *  This library is free software; you can redistribute it and/or
8  *  modify it under the terms of the GNU Lesser General Public
9  *  License as published by the Free Software Foundation; either
10  *  version 2 of the License, or (at your option) any later version.
11  *
12  *  This library is distributed in the hope that it will be useful,
13  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  *  Lesser General Public License for more details.
16  *
17  *  You should have received a copy of the GNU Lesser General Public
18  *  License along with this library; if not, write to the Free Software
19  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
20  */
21
22 #include "config.h"
23 #include "JSDOMConvertStrings.h"
24
25 #include "JSDOMExceptionHandling.h"
26 #include <JavaScriptCore/HeapInlines.h>
27 #include <JavaScriptCore/JSCJSValueInlines.h>
28 #include <wtf/text/StringBuilder.h>
29 #include <wtf/unicode/CharacterNames.h>
30
31
32 namespace WebCore {
33 using namespace JSC;
34
35 static inline String stringToByteString(ExecState& state, JSC::ThrowScope& scope, String&& string)
36 {
37     if (!string.isAllLatin1()) {
38         throwTypeError(&state, scope);
39         return { };
40     }
41
42     return WTFMove(string);
43 }
44
45 String identifierToByteString(ExecState& state, const Identifier& identifier)
46 {
47     VM& vm = state.vm();
48     auto scope = DECLARE_THROW_SCOPE(vm);
49
50     auto string = identifier.string();
51     return stringToByteString(state, scope, WTFMove(string));
52 }
53
54 String valueToByteString(ExecState& state, JSValue value)
55 {
56     VM& vm = state.vm();
57     auto scope = DECLARE_THROW_SCOPE(vm);
58
59     auto string = value.toWTFString(&state);
60     RETURN_IF_EXCEPTION(scope, { });
61
62     return stringToByteString(state, scope, WTFMove(string));
63 }
64
65 static inline bool hasUnpairedSurrogate(StringView string)
66 {
67     // Fast path for 8-bit strings; they can't have any surrogates.
68     if (string.is8Bit())
69         return false;
70     for (auto codePoint : string.codePoints()) {
71         if (U_IS_SURROGATE(codePoint))
72             return true;
73     }
74     return false;
75 }
76
77 static inline String stringToUSVString(String&& string)
78 {
79     // Fast path for the case where there are no unpaired surrogates.
80     if (!hasUnpairedSurrogate(string))
81         return WTFMove(string);
82
83     // Slow path: http://heycam.github.io/webidl/#dfn-obtain-unicode
84     // Replaces unpaired surrogates with the replacement character.
85     StringBuilder result;
86     result.reserveCapacity(string.length());
87     StringView view { string };
88     for (auto codePoint : view.codePoints()) {
89         if (U_IS_SURROGATE(codePoint))
90             result.append(replacementCharacter);
91         else
92             result.appendCharacter(codePoint);
93     }
94     return result.toString();
95 }
96
97 String identifierToUSVString(ExecState&, const Identifier& identifier)
98 {
99     auto string = identifier.string();
100     return stringToUSVString(WTFMove(string));
101 }
102
103 String valueToUSVString(ExecState& state, JSValue value)
104 {
105     VM& vm = state.vm();
106     auto scope = DECLARE_THROW_SCOPE(vm);
107
108     auto string = value.toWTFString(&state);
109     RETURN_IF_EXCEPTION(scope, { });
110
111     return stringToUSVString(WTFMove(string));
112 }
113
114 } // namespace WebCore