eb27e2c4efdcf0af4532e8f60316c0525da48490
[WebKit-https.git] / Source / WebCore / bindings / js / JSDOMBinding.h
1 /*
2  *  Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
3  *  Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009, 2013 Apple Inc. All rights reserved.
4  *  Copyright (C) 2007 Samuel Weinig <sam@webkit.org>
5  *  Copyright (C) 2009 Google, Inc. All rights reserved.
6  *  Copyright (C) 2012 Ericsson AB. All rights reserved.
7  *  Copyright (C) 2013 Michael Pruett <michael@68k.org>
8  *
9  *  This library is free software; you can redistribute it and/or
10  *  modify it under the terms of the GNU Lesser General Public
11  *  License as published by the Free Software Foundation; either
12  *  version 2 of the License, or (at your option) any later version.
13  *
14  *  This library is distributed in the hope that it will be useful,
15  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
16  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17  *  Lesser General Public License for more details.
18  *
19  *  You should have received a copy of the GNU Lesser General Public
20  *  License along with this library; if not, write to the Free Software
21  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
22  */
23
24 #pragma once
25
26 #include "DOMWrapperWorld.h"
27 #include "ExceptionCode.h"
28 #include "ExceptionOr.h"
29 #include "JSDOMGlobalObject.h"
30 #include "JSDOMWrapper.h"
31 #include "ScriptWrappable.h"
32 #include "ScriptWrappableInlines.h"
33 #include "WebCoreTypedArrayController.h"
34 #include <cstddef>
35 #include <heap/HeapInlines.h>
36 #include <heap/SlotVisitorInlines.h>
37 #include <heap/Weak.h>
38 #include <heap/WeakInlines.h>
39 #include <runtime/AuxiliaryBarrierInlines.h>
40 #include <runtime/Error.h>
41 #include <runtime/IteratorOperations.h>
42 #include <runtime/JSArray.h>
43 #include <runtime/JSArrayBuffer.h>
44 #include <runtime/JSCJSValueInlines.h>
45 #include <runtime/JSCellInlines.h>
46 #include <runtime/JSObjectInlines.h>
47 #include <runtime/JSTypedArrays.h>
48 #include <runtime/Lookup.h>
49 #include <runtime/ObjectConstructor.h>
50 #include <runtime/StructureInlines.h>
51 #include <runtime/TypedArrayInlines.h>
52 #include <runtime/TypedArrays.h>
53 #include <runtime/WriteBarrier.h>
54 #include <wtf/Forward.h>
55 #include <wtf/GetPtr.h>
56 #include <wtf/Noncopyable.h>
57 #include <wtf/Vector.h>
58
59 // FIXME: We could make this file a lot easier to read by putting all function declarations at the top,
60 // and function definitions below, even for template and inline functions.
61
62 namespace JSC {
63 class JSFunction;
64 }
65
66 namespace WebCore {
67
68 class CachedScript;
69 class DOMWindow;
70 class Frame;
71 class URL;
72 class Node;
73
74 struct ExceptionDetails {
75     String message;
76     int lineNumber { 0 };
77     int columnNumber { 0 };
78     String sourceURL;
79 };
80
81 // Base class for all constructor objects in the JSC bindings.
82 class DOMConstructorObject : public JSDOMObject {
83 public:
84     typedef JSDOMObject Base;
85     static const unsigned StructureFlags = Base::StructureFlags | JSC::ImplementsHasInstance | JSC::ImplementsDefaultHasInstance | JSC::TypeOfShouldCallGetCallData;
86     static JSC::Structure* createStructure(JSC::VM&, JSC::JSGlobalObject*, JSC::JSValue);
87
88 protected:
89     DOMConstructorObject(JSC::Structure*, JSDOMGlobalObject&);
90
91     static String className(const JSObject*);
92     static JSC::CallType getCallData(JSCell*, JSC::CallData&);
93 };
94
95 class DOMConstructorJSBuiltinObject : public DOMConstructorObject {
96 public:
97     typedef DOMConstructorObject Base;
98
99 protected:
100     DOMConstructorJSBuiltinObject(JSC::Structure*, JSDOMGlobalObject&);
101     static void visitChildren(JSC::JSCell*, JSC::SlotVisitor&);
102
103     JSC::JSFunction* initializeFunction();
104     void setInitializeFunction(JSC::VM&, JSC::JSFunction&);
105
106 private:
107     JSC::WriteBarrier<JSC::JSFunction> m_initializeFunction;
108 };
109
110 DOMWindow& callerDOMWindow(JSC::ExecState*);
111 DOMWindow& activeDOMWindow(JSC::ExecState*);
112 DOMWindow& firstDOMWindow(JSC::ExecState*);
113
114 WEBCORE_EXPORT JSC::EncodedJSValue reportDeprecatedGetterError(JSC::ExecState&, const char* interfaceName, const char* attributeName);
115 WEBCORE_EXPORT void reportDeprecatedSetterError(JSC::ExecState&, const char* interfaceName, const char* attributeName);
116
117 void throwNotSupportedError(JSC::ExecState&, JSC::ThrowScope&, const char* message);
118 void throwInvalidStateError(JSC::ExecState&, JSC::ThrowScope&, const char* message);
119 void throwArrayElementTypeError(JSC::ExecState&, JSC::ThrowScope&);
120 void throwAttributeTypeError(JSC::ExecState&, JSC::ThrowScope&, const char* interfaceName, const char* attributeName, const char* expectedType);
121 WEBCORE_EXPORT void throwSequenceTypeError(JSC::ExecState&, JSC::ThrowScope&);
122 WEBCORE_EXPORT bool throwSetterTypeError(JSC::ExecState&, JSC::ThrowScope&, const char* interfaceName, const char* attributeName);
123 WEBCORE_EXPORT void throwNonFiniteTypeError(JSC::ExecState&, JSC::ThrowScope&);
124 void throwSecurityError(JSC::ExecState&, JSC::ThrowScope&, const String& message);
125
126 WEBCORE_EXPORT JSC::EncodedJSValue throwArgumentMustBeEnumError(JSC::ExecState&, JSC::ThrowScope&, unsigned argumentIndex, const char* argumentName, const char* functionInterfaceName, const char* functionName, const char* expectedValues);
127 JSC::EncodedJSValue throwArgumentMustBeFunctionError(JSC::ExecState&, JSC::ThrowScope&, unsigned argumentIndex, const char* argumentName, const char* functionInterfaceName, const char* functionName);
128 WEBCORE_EXPORT JSC::EncodedJSValue throwArgumentTypeError(JSC::ExecState&, JSC::ThrowScope&, unsigned argumentIndex, const char* argumentName, const char* functionInterfaceName, const char* functionName, const char* expectedType);
129 JSC::EncodedJSValue throwConstructorScriptExecutionContextUnavailableError(JSC::ExecState&, JSC::ThrowScope&, const char* interfaceName);
130
131 String makeGetterTypeErrorMessage(const char* interfaceName, const char* attributeName);
132 String makeThisTypeErrorMessage(const char* interfaceName, const char* attributeName);
133
134 WEBCORE_EXPORT JSC::EncodedJSValue throwGetterTypeError(JSC::ExecState&, JSC::ThrowScope&, const char* interfaceName, const char* attributeName);
135 WEBCORE_EXPORT JSC::EncodedJSValue throwThisTypeError(JSC::ExecState&, JSC::ThrowScope&, const char* interfaceName, const char* functionName);
136
137 JSC::EncodedJSValue rejectPromiseWithGetterTypeError(JSC::ExecState&, const char* interfaceName, const char* attributeName);
138
139 WEBCORE_EXPORT JSC::Structure* getCachedDOMStructure(JSDOMGlobalObject&, const JSC::ClassInfo*);
140 WEBCORE_EXPORT JSC::Structure* cacheDOMStructure(JSDOMGlobalObject&, JSC::Structure*, const JSC::ClassInfo*);
141
142 template<typename WrapperClass> JSC::Structure* getDOMStructure(JSC::VM&, JSDOMGlobalObject&);
143 template<typename WrapperClass> JSC::Structure* deprecatedGetDOMStructure(JSC::ExecState*);
144 template<typename WrapperClass> JSC::JSObject* getDOMPrototype(JSC::VM&, JSC::JSGlobalObject*);
145
146 void callFunctionWithCurrentArguments(JSC::ExecState&, JSC::JSObject& thisObject, JSC::JSFunction&);
147
148 template<typename JSClass> JSC::EncodedJSValue createJSBuiltin(JSC::ExecState&, JSC::JSFunction& initializeFunction, JSDOMGlobalObject&);
149
150 JSC::WeakHandleOwner* wrapperOwner(DOMWrapperWorld&, JSC::ArrayBuffer*);
151 void* wrapperKey(JSC::ArrayBuffer*);
152
153 JSDOMObject* getInlineCachedWrapper(DOMWrapperWorld&, void*);
154 JSDOMObject* getInlineCachedWrapper(DOMWrapperWorld&, ScriptWrappable*);
155 JSC::JSArrayBuffer* getInlineCachedWrapper(DOMWrapperWorld&, JSC::ArrayBuffer*);
156
157 bool setInlineCachedWrapper(DOMWrapperWorld&, void*, JSDOMObject*, JSC::WeakHandleOwner*);
158 bool setInlineCachedWrapper(DOMWrapperWorld&, ScriptWrappable*, JSDOMObject* wrapper, JSC::WeakHandleOwner* wrapperOwner);
159 bool setInlineCachedWrapper(DOMWrapperWorld&, JSC::ArrayBuffer*, JSC::JSArrayBuffer* wrapper, JSC::WeakHandleOwner* wrapperOwner);
160
161 bool clearInlineCachedWrapper(DOMWrapperWorld&, void*, JSDOMObject*);
162 bool clearInlineCachedWrapper(DOMWrapperWorld&, ScriptWrappable*, JSDOMObject* wrapper);
163 bool clearInlineCachedWrapper(DOMWrapperWorld&, JSC::ArrayBuffer*, JSC::JSArrayBuffer* wrapper);
164
165 template<typename DOMClass> JSC::JSObject* getCachedWrapper(DOMWrapperWorld&, DOMClass&);
166 template<typename DOMClass> inline JSC::JSObject* getCachedWrapper(DOMWrapperWorld& world, Ref<DOMClass>& object) { return getCachedWrapper(world, object.get()); }
167 template<typename DOMClass, typename WrapperClass> void cacheWrapper(DOMWrapperWorld&, DOMClass*, WrapperClass*);
168 template<typename DOMClass, typename WrapperClass> void uncacheWrapper(DOMWrapperWorld&, DOMClass*, WrapperClass*);
169 template<typename DOMClass, typename T> auto createWrapper(JSDOMGlobalObject*, Ref<T>&&) -> typename std::enable_if<std::is_same<DOMClass, T>::value, typename JSDOMWrapperConverterTraits<DOMClass>::WrapperClass*>::type;
170 template<typename DOMClass, typename T> auto createWrapper(JSDOMGlobalObject*, Ref<T>&&) -> typename std::enable_if<!std::is_same<DOMClass, T>::value, typename JSDOMWrapperConverterTraits<DOMClass>::WrapperClass*>::type;
171
172 template<typename DOMClass> JSC::JSValue wrap(JSC::ExecState*, JSDOMGlobalObject*, DOMClass&);
173
174 template<typename JSClass> JSClass& castThisValue(JSC::ExecState&);
175
176 void addImpureProperty(const AtomicString&);
177
178 const JSC::HashTable& getHashTableForGlobalData(JSC::VM&, const JSC::HashTable& staticTable);
179
180 WEBCORE_EXPORT void reportException(JSC::ExecState*, JSC::JSValue exception, CachedScript* = nullptr);
181 WEBCORE_EXPORT void reportException(JSC::ExecState*, JSC::Exception*, CachedScript* = nullptr, ExceptionDetails* = nullptr);
182 void reportCurrentException(JSC::ExecState*);
183
184 JSC::JSValue createDOMException(JSC::ExecState&, Exception&&);
185 JSC::JSValue createDOMException(JSC::ExecState*, ExceptionCode, const String&);
186
187 // Convert a DOM implementation exception into a JavaScript exception in the execution state.
188 void propagateException(JSC::ExecState&, JSC::ThrowScope&, Exception&&);
189 void setDOMException(JSC::ExecState*, JSC::ThrowScope&, ExceptionCode);
190
191 // Slower versions of the above for use when the caller doesn't have a ThrowScope.
192 void propagateException(JSC::ExecState&, Exception&&);
193 WEBCORE_EXPORT void setDOMException(JSC::ExecState*, ExceptionCode);
194
195 // Implementation details of the above.
196 void propagateExceptionSlowPath(JSC::ExecState&, JSC::ThrowScope&, Exception&&);
197 WEBCORE_EXPORT void setDOMExceptionSlow(JSC::ExecState*, JSC::ThrowScope&, ExceptionCode);
198
199 JSC::JSValue jsString(JSC::ExecState*, const URL&); // empty if the URL is null
200
201 JSC::JSValue jsStringOrNull(JSC::ExecState*, const String&); // null if the string is null
202 JSC::JSValue jsStringOrNull(JSC::ExecState*, const URL&); // null if the URL is null
203
204 JSC::JSValue jsStringOrUndefined(JSC::ExecState*, const String&); // undefined if the string is null
205 JSC::JSValue jsStringOrUndefined(JSC::ExecState*, const URL&); // undefined if the URL is null
206
207 // See JavaScriptCore for explanation: Should be used for any string that is already owned by another
208 // object, to let the engine know that collecting the JSString wrapper is unlikely to save memory.
209 JSC::JSValue jsOwnedStringOrNull(JSC::ExecState*, const String&);
210
211 String propertyNameToString(JSC::PropertyName);
212
213 AtomicString propertyNameToAtomicString(JSC::PropertyName);
214
215 String valueToStringTreatingNullAsEmptyString(JSC::ExecState*, JSC::JSValue);
216 String valueToStringWithUndefinedOrNullCheck(JSC::ExecState*, JSC::JSValue); // null if the value is null or undefined
217
218 WEBCORE_EXPORT String valueToUSVString(JSC::ExecState*, JSC::JSValue);
219 String valueToUSVStringTreatingNullAsEmptyString(JSC::ExecState*, JSC::JSValue);
220 String valueToUSVStringWithUndefinedOrNullCheck(JSC::ExecState*, JSC::JSValue);
221
222 template<typename T> JSC::JSValue toNullableJSNumber(Optional<T>); // null if the optional is null
223
224 int32_t finiteInt32Value(JSC::JSValue, JSC::ExecState*, bool& okay);
225
226 // The following functions convert values to integers as per the WebIDL specification.
227 // The conversion fails if the value cannot be converted to a number or, if EnforceRange is specified,
228 // the value is outside the range of the destination integer type.
229
230 enum IntegerConversionConfiguration { NormalConversion, EnforceRange, Clamp };
231
232 WEBCORE_EXPORT int8_t toInt8EnforceRange(JSC::ExecState&, JSC::JSValue);
233 WEBCORE_EXPORT uint8_t toUInt8EnforceRange(JSC::ExecState&, JSC::JSValue);
234 WEBCORE_EXPORT int16_t toInt16EnforceRange(JSC::ExecState&, JSC::JSValue);
235 WEBCORE_EXPORT uint16_t toUInt16EnforceRange(JSC::ExecState&, JSC::JSValue);
236 WEBCORE_EXPORT int32_t toInt32EnforceRange(JSC::ExecState&, JSC::JSValue);
237 WEBCORE_EXPORT uint32_t toUInt32EnforceRange(JSC::ExecState&, JSC::JSValue);
238 WEBCORE_EXPORT int64_t toInt64EnforceRange(JSC::ExecState&, JSC::JSValue);
239 WEBCORE_EXPORT uint64_t toUInt64EnforceRange(JSC::ExecState&, JSC::JSValue);
240
241 WEBCORE_EXPORT int8_t toInt8Clamp(JSC::ExecState&, JSC::JSValue);
242 WEBCORE_EXPORT uint8_t toUInt8Clamp(JSC::ExecState&, JSC::JSValue);
243 WEBCORE_EXPORT int16_t toInt16Clamp(JSC::ExecState&, JSC::JSValue);
244 WEBCORE_EXPORT uint16_t toUInt16Clamp(JSC::ExecState&, JSC::JSValue);
245 WEBCORE_EXPORT int32_t toInt32Clamp(JSC::ExecState&, JSC::JSValue);
246 WEBCORE_EXPORT uint32_t toUInt32Clamp(JSC::ExecState&, JSC::JSValue);
247 WEBCORE_EXPORT int64_t toInt64Clamp(JSC::ExecState&, JSC::JSValue);
248 WEBCORE_EXPORT uint64_t toUInt64Clamp(JSC::ExecState&, JSC::JSValue);
249
250 WEBCORE_EXPORT int8_t toInt8(JSC::ExecState&, JSC::JSValue);
251 WEBCORE_EXPORT uint8_t toUInt8(JSC::ExecState&, JSC::JSValue);
252 WEBCORE_EXPORT int16_t toInt16(JSC::ExecState&, JSC::JSValue);
253 WEBCORE_EXPORT uint16_t toUInt16(JSC::ExecState&, JSC::JSValue);
254 WEBCORE_EXPORT int64_t toInt64(JSC::ExecState&, JSC::JSValue);
255 WEBCORE_EXPORT uint64_t toUInt64(JSC::ExecState&, JSC::JSValue);
256
257 JSC::JSValue jsDate(JSC::ExecState*, double value);
258 JSC::JSValue jsDateOrNull(JSC::ExecState*, double value);
259
260 // NaN if the value can't be converted to a date.
261 double valueToDate(JSC::ExecState*, JSC::JSValue);
262
263 // Validates that the passed object is a sequence type per section 4.1.13 of the WebIDL spec.
264 JSC::JSObject* toJSSequence(JSC::ExecState&, JSC::JSValue, unsigned& length);
265
266 JSC::JSValue toJS(JSC::ExecState*, JSDOMGlobalObject*, JSC::ArrayBuffer*);
267 JSC::JSValue toJS(JSC::ExecState*, JSDOMGlobalObject*, JSC::ArrayBufferView*);
268 JSC::JSValue toJS(JSC::ExecState*, JSC::JSGlobalObject*, JSC::ArrayBufferView*);
269 template<typename T> JSC::JSValue toJS(JSC::ExecState*, JSDOMGlobalObject*, Ref<T>&&);
270 template<typename T> JSC::JSValue toJS(JSC::ExecState*, JSDOMGlobalObject*, RefPtr<T>&&);
271 template<typename T> JSC::JSValue toJS(JSC::ExecState*, JSDOMGlobalObject*, const Vector<T>&);
272 template<typename T> JSC::JSValue toJS(JSC::ExecState*, JSDOMGlobalObject*, const Vector<RefPtr<T>>&);
273 JSC::JSValue toJS(JSC::ExecState*, JSDOMGlobalObject*, const String&);
274 JSC::JSValue toJS(JSC::ExecState*, JSDOMGlobalObject*, const JSC::PrivateName&);
275
276 JSC::JSValue toJSIterator(JSC::ExecState&, JSDOMGlobalObject&, JSC::JSValue);
277 template<typename T> JSC::JSValue toJSIterator(JSC::ExecState&, JSDOMGlobalObject&, const T&);
278
279 JSC::JSValue toJSIteratorEnd(JSC::ExecState&);
280
281 template<typename T, size_t inlineCapacity> JSC::JSValue jsArray(JSC::ExecState*, JSDOMGlobalObject*, const Vector<T, inlineCapacity>&);
282 template<typename T, size_t inlineCapacity> JSC::JSValue jsArray(JSC::ExecState*, JSDOMGlobalObject*, const Vector<T, inlineCapacity>*);
283 template<typename T, size_t inlineCapacity> JSC::JSValue jsFrozenArray(JSC::ExecState*, JSDOMGlobalObject*, const Vector<T, inlineCapacity>&);
284
285 JSC::JSValue jsPair(JSC::ExecState&, JSDOMGlobalObject*, JSC::JSValue, JSC::JSValue);
286 template<typename FirstType, typename SecondType> JSC::JSValue jsPair(JSC::ExecState&, JSDOMGlobalObject*, const FirstType&, const SecondType&);
287
288 RefPtr<JSC::ArrayBufferView> toArrayBufferView(JSC::JSValue);
289 RefPtr<JSC::Int8Array> toInt8Array(JSC::JSValue);
290 RefPtr<JSC::Int16Array> toInt16Array(JSC::JSValue);
291 RefPtr<JSC::Int32Array> toInt32Array(JSC::JSValue);
292 RefPtr<JSC::Uint8Array> toUint8Array(JSC::JSValue);
293 RefPtr<JSC::Uint8ClampedArray> toUint8ClampedArray(JSC::JSValue);
294 RefPtr<JSC::Uint16Array> toUint16Array(JSC::JSValue);
295 RefPtr<JSC::Uint32Array> toUint32Array(JSC::JSValue);
296 RefPtr<JSC::Float32Array> toFloat32Array(JSC::JSValue);
297 RefPtr<JSC::Float64Array> toFloat64Array(JSC::JSValue);
298
299 template<typename T, typename JSType> Vector<Ref<T>> toRefNativeArray(JSC::ExecState&, JSC::JSValue);
300 template<typename T, typename JSType> Vector<RefPtr<T>> toRefPtrNativeArray(JSC::ExecState&, JSC::JSValue);
301 template<typename T> Vector<T> toNativeArray(JSC::ExecState&, JSC::JSValue);
302 bool hasIteratorMethod(JSC::ExecState&, JSC::JSValue);
303
304 bool shouldAllowAccessToNode(JSC::ExecState*, Node*);
305 bool shouldAllowAccessToFrame(JSC::ExecState*, Frame*);
306 bool shouldAllowAccessToFrame(JSC::ExecState*, Frame*, String& message);
307 bool shouldAllowAccessToDOMWindow(JSC::ExecState*, DOMWindow&, String& message);
308
309 enum SecurityReportingOption {
310     DoNotReportSecurityError,
311     LogSecurityError, // Legacy behavior.
312     ThrowSecurityError
313 };
314
315 class BindingSecurity {
316 public:
317     static bool shouldAllowAccessToNode(JSC::ExecState*, Node*);
318     static bool shouldAllowAccessToDOMWindow(JSC::ExecState*, DOMWindow&, SecurityReportingOption = LogSecurityError);
319     static bool shouldAllowAccessToFrame(JSC::ExecState*, Frame*, SecurityReportingOption = LogSecurityError);
320 };
321
322 void printErrorMessageForFrame(Frame*, const String& message);
323
324 String propertyNameToString(JSC::PropertyName);
325 AtomicString propertyNameToAtomicString(JSC::PropertyName);
326
327 template<JSC::NativeFunction, int length> JSC::EncodedJSValue nonCachingStaticFunctionGetter(JSC::ExecState*, JSC::EncodedJSValue, JSC::PropertyName);
328
329 template<typename T> struct NativeValueTraits;
330
331
332 enum class CastedThisErrorBehavior { Throw, ReturnEarly, RejectPromise };
333
334 template<typename JSClass>
335 struct BindingCaller {
336     using AttributeGetterFunction = JSC::JSValue(JSC::ExecState*, JSClass*, JSC::ThrowScope&);
337
338     template<AttributeGetterFunction getter, CastedThisErrorBehavior shouldThrow = CastedThisErrorBehavior::Throw>
339     static JSC::EncodedJSValue attribute(JSC::ExecState* state, JSC::EncodedJSValue thisValue, const char* attributeName)
340     {
341         ASSERT(state);
342         auto throwScope = DECLARE_THROW_SCOPE(state->vm());
343         auto* thisObject = JSClass::castForAttribute(state, thisValue);
344         if (UNLIKELY(!thisObject)) {
345             ASSERT(JSClass::info());
346             if (shouldThrow == CastedThisErrorBehavior::Throw)
347                 return throwGetterTypeError(*state, throwScope, JSClass::info()->className, attributeName);
348             if (shouldThrow == CastedThisErrorBehavior::RejectPromise)
349                 return rejectPromiseWithGetterTypeError(*state, JSClass::info()->className, attributeName);
350             return JSC::JSValue::encode(JSC::jsUndefined());
351         }
352         // FIXME: We should refactor the binding generated code to use references for state and thisObject.
353         return JSC::JSValue::encode(getter(state, thisObject, throwScope));
354     }
355 };
356
357 // ExceptionOr handling.
358 void propagateException(JSC::ExecState&, JSC::ThrowScope&, ExceptionOr<void>&&);
359 template<typename T> JSC::JSValue toJS(JSC::ExecState&, JSDOMGlobalObject&, JSC::ThrowScope&, ExceptionOr<T>&&);
360 JSC::JSValue toJSBoolean(JSC::ExecState&, JSC::ThrowScope&, ExceptionOr<bool>&&);
361 JSC::JSValue toJSDate(JSC::ExecState&, JSC::ThrowScope&, ExceptionOr<double>&&);
362 JSC::JSValue toJSNullableDate(JSC::ExecState&, JSC::ThrowScope&, ExceptionOr<Optional<double>>&&);
363 JSC::JSValue toJSNullableString(JSC::ExecState&, JSC::ThrowScope&, ExceptionOr<String>&&);
364 template<typename T> JSC::JSValue toJSNewlyCreated(JSC::ExecState&, JSDOMGlobalObject&, JSC::ThrowScope&, ExceptionOr<T>&& value);
365 template<typename T> JSC::JSValue toJSNumber(JSC::ExecState&, JSC::ThrowScope&, ExceptionOr<T>&& value);
366 template<typename T> JSC::JSValue toJSNullableNumber(JSC::ExecState&, JSC::ThrowScope&, ExceptionOr<T>&& value);
367 JSC::JSValue toJSString(JSC::ExecState&, JSC::ThrowScope&, ExceptionOr<String>&&);
368
369 // Inline functions and template definitions.
370
371 inline JSC::Structure* DOMConstructorObject::createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype)
372 {
373     return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), info());
374 }
375
376 inline DOMConstructorObject::DOMConstructorObject(JSC::Structure* structure, JSDOMGlobalObject& globalObject)
377     : JSDOMObject(structure, globalObject)
378 {
379 }
380
381 inline String DOMConstructorObject::className(const JSObject*)
382 {
383     return ASCIILiteral("Function");
384 }
385
386 inline DOMConstructorJSBuiltinObject::DOMConstructorJSBuiltinObject(JSC::Structure* structure, JSDOMGlobalObject& globalObject)
387     : DOMConstructorObject(structure, globalObject)
388 {
389 }
390
391 inline JSC::JSFunction* DOMConstructorJSBuiltinObject::initializeFunction()
392 {
393     return m_initializeFunction.get();
394 }
395
396 inline void DOMConstructorJSBuiltinObject::setInitializeFunction(JSC::VM& vm, JSC::JSFunction& function)
397 {
398     m_initializeFunction.set(vm, this, &function);
399 }
400
401 inline JSDOMGlobalObject* deprecatedGlobalObjectForPrototype(JSC::ExecState* exec)
402 {
403     // FIXME: Callers to this function should be using the global object
404     // from which the object is being created, instead of assuming the lexical one.
405     // e.g. subframe.document.body should use the subframe's global object, not the lexical one.
406     return JSC::jsCast<JSDOMGlobalObject*>(exec->lexicalGlobalObject());
407 }
408
409 template<typename WrapperClass> inline JSC::Structure* getDOMStructure(JSC::VM& vm, JSDOMGlobalObject& globalObject)
410 {
411     if (JSC::Structure* structure = getCachedDOMStructure(globalObject, WrapperClass::info()))
412         return structure;
413     return cacheDOMStructure(globalObject, WrapperClass::createStructure(vm, &globalObject, WrapperClass::createPrototype(vm, &globalObject)), WrapperClass::info());
414 }
415
416 template<typename WrapperClass> inline JSC::Structure* deprecatedGetDOMStructure(JSC::ExecState* exec)
417 {
418     // FIXME: This function is wrong. It uses the wrong global object for creating the prototype structure.
419     return getDOMStructure<WrapperClass>(exec->vm(), *deprecatedGlobalObjectForPrototype(exec));
420 }
421
422 template<typename WrapperClass> inline JSC::JSObject* getDOMPrototype(JSC::VM& vm, JSC::JSGlobalObject* globalObject)
423 {
424     return JSC::jsCast<JSC::JSObject*>(asObject(getDOMStructure<WrapperClass>(vm, *JSC::jsCast<JSDOMGlobalObject*>(globalObject))->storedPrototype()));
425 }
426
427 template<typename JSClass> inline JSC::EncodedJSValue createJSBuiltin(JSC::ExecState& state, JSC::JSFunction& initializeFunction, JSDOMGlobalObject& globalObject)
428 {
429     JSC::JSObject* object = JSClass::create(getDOMStructure<JSClass>(globalObject.vm(), globalObject), &globalObject);
430     callFunctionWithCurrentArguments(state, *object, initializeFunction);
431     return JSC::JSValue::encode(object);
432 }
433
434 inline JSC::WeakHandleOwner* wrapperOwner(DOMWrapperWorld& world, JSC::ArrayBuffer*)
435 {
436     return static_cast<WebCoreTypedArrayController*>(world.vm().m_typedArrayController.get())->wrapperOwner();
437 }
438
439 inline void* wrapperKey(JSC::ArrayBuffer* domObject)
440 {
441     return domObject;
442 }
443
444 inline JSDOMObject* getInlineCachedWrapper(DOMWrapperWorld&, void*) { return nullptr; }
445 inline bool setInlineCachedWrapper(DOMWrapperWorld&, void*, JSDOMObject*, JSC::WeakHandleOwner*) { return false; }
446 inline bool clearInlineCachedWrapper(DOMWrapperWorld&, void*, JSDOMObject*) { return false; }
447
448 inline JSDOMObject* getInlineCachedWrapper(DOMWrapperWorld& world, ScriptWrappable* domObject)
449 {
450     if (!world.isNormal())
451         return nullptr;
452     return domObject->wrapper();
453 }
454
455 inline JSC::JSArrayBuffer* getInlineCachedWrapper(DOMWrapperWorld& world, JSC::ArrayBuffer* buffer)
456 {
457     if (!world.isNormal())
458         return nullptr;
459     return buffer->m_wrapper.get();
460 }
461
462 inline bool setInlineCachedWrapper(DOMWrapperWorld& world, ScriptWrappable* domObject, JSDOMObject* wrapper, JSC::WeakHandleOwner* wrapperOwner)
463 {
464     if (!world.isNormal())
465         return false;
466     domObject->setWrapper(wrapper, wrapperOwner, &world);
467     return true;
468 }
469
470 inline bool setInlineCachedWrapper(DOMWrapperWorld& world, JSC::ArrayBuffer* domObject, JSC::JSArrayBuffer* wrapper, JSC::WeakHandleOwner* wrapperOwner)
471 {
472     if (!world.isNormal())
473         return false;
474     domObject->m_wrapper = JSC::Weak<JSC::JSArrayBuffer>(wrapper, wrapperOwner, &world);
475     return true;
476 }
477
478 inline bool clearInlineCachedWrapper(DOMWrapperWorld& world, ScriptWrappable* domObject, JSDOMObject* wrapper)
479 {
480     if (!world.isNormal())
481         return false;
482     domObject->clearWrapper(wrapper);
483     return true;
484 }
485
486 inline bool clearInlineCachedWrapper(DOMWrapperWorld& world, JSC::ArrayBuffer* domObject, JSC::JSArrayBuffer* wrapper)
487 {
488     if (!world.isNormal())
489         return false;
490     weakClear(domObject->m_wrapper, wrapper);
491     return true;
492 }
493
494 template<typename DOMClass> inline JSC::JSObject* getCachedWrapper(DOMWrapperWorld& world, DOMClass& domObject)
495 {
496     if (auto* wrapper = getInlineCachedWrapper(world, &domObject))
497         return wrapper;
498     return world.m_wrappers.get(wrapperKey(&domObject));
499 }
500
501 template<typename DOMClass, typename WrapperClass> inline void cacheWrapper(DOMWrapperWorld& world, DOMClass* domObject, WrapperClass* wrapper)
502 {
503     JSC::WeakHandleOwner* owner = wrapperOwner(world, domObject);
504     if (setInlineCachedWrapper(world, domObject, wrapper, owner))
505         return;
506     weakAdd(world.m_wrappers, wrapperKey(domObject), JSC::Weak<JSC::JSObject>(wrapper, owner, &world));
507 }
508
509 template<typename DOMClass, typename WrapperClass> inline void uncacheWrapper(DOMWrapperWorld& world, DOMClass* domObject, WrapperClass* wrapper)
510 {
511     if (clearInlineCachedWrapper(world, domObject, wrapper))
512         return;
513     weakRemove(world.m_wrappers, wrapperKey(domObject), wrapper);
514 }
515
516 template<typename DOMClass, typename T> inline auto createWrapper(JSDOMGlobalObject* globalObject, Ref<T>&& domObject) -> typename std::enable_if<std::is_same<DOMClass, T>::value, typename JSDOMWrapperConverterTraits<DOMClass>::WrapperClass*>::type
517 {
518     using WrapperClass = typename JSDOMWrapperConverterTraits<DOMClass>::WrapperClass;
519
520     ASSERT(!getCachedWrapper(globalObject->world(), domObject));
521     auto* domObjectPtr = domObject.ptr();
522     auto* wrapper = WrapperClass::create(getDOMStructure<WrapperClass>(globalObject->vm(), *globalObject), globalObject, WTFMove(domObject));
523     cacheWrapper(globalObject->world(), domObjectPtr, wrapper);
524     return wrapper;
525 }
526
527 template<typename DOMClass, typename T> inline auto createWrapper(JSDOMGlobalObject* globalObject, Ref<T>&& domObject) -> typename std::enable_if<!std::is_same<DOMClass, T>::value, typename JSDOMWrapperConverterTraits<DOMClass>::WrapperClass*>::type
528 {
529     return createWrapper<DOMClass>(globalObject, static_reference_cast<DOMClass>(WTFMove(domObject)));
530 }
531
532 template<typename DOMClass> inline JSC::JSValue wrap(JSC::ExecState* state, JSDOMGlobalObject* globalObject, DOMClass& domObject)
533 {
534     if (auto* wrapper = getCachedWrapper(globalObject->world(), domObject))
535         return wrapper;
536     return toJSNewlyCreated(state, globalObject, Ref<DOMClass>(domObject));
537 }
538
539 template<typename JSClass> inline JSClass& castThisValue(JSC::ExecState& state)
540 {
541     auto thisValue = state.thisValue();
542     auto castedThis = JSC::jsDynamicCast<JSClass*>(thisValue);
543     ASSERT(castedThis);
544     return *castedThis;
545 }
546
547 inline int32_t finiteInt32Value(JSC::JSValue value, JSC::ExecState* exec, bool& okay)
548 {
549     double number = value.toNumber(exec);
550     okay = std::isfinite(number);
551     return JSC::toInt32(number);
552 }
553
554 // Validates that the passed object is a sequence type per section 4.1.13 of the WebIDL spec.
555 inline JSC::JSObject* toJSSequence(JSC::ExecState& exec, JSC::JSValue value, unsigned& length)
556 {
557     JSC::VM& vm = exec.vm();
558     auto scope = DECLARE_THROW_SCOPE(vm);
559
560     JSC::JSObject* object = value.getObject();
561     if (!object) {
562         throwSequenceTypeError(exec, scope);
563         return nullptr;
564     }
565
566     JSC::JSValue lengthValue = object->get(&exec, exec.propertyNames().length);
567     RETURN_IF_EXCEPTION(scope, nullptr);
568
569     if (lengthValue.isUndefinedOrNull()) {
570         throwSequenceTypeError(exec, scope);
571         return nullptr;
572     }
573
574     length = lengthValue.toUInt32(&exec);
575     RETURN_IF_EXCEPTION(scope, nullptr);
576
577     return object;
578 }
579
580 inline JSC::JSValue toJS(JSC::ExecState* exec, JSDOMGlobalObject* globalObject, JSC::ArrayBuffer* buffer)
581 {
582     if (!buffer)
583         return JSC::jsNull();
584     if (JSC::JSValue result = getCachedWrapper(globalObject->world(), *buffer))
585         return result;
586
587     // The JSArrayBuffer::create function will register the wrapper in finishCreation.
588     return JSC::JSArrayBuffer::create(exec->vm(), globalObject->arrayBufferStructure(), buffer);
589 }
590
591 inline JSC::JSValue toJS(JSC::ExecState* exec, JSDOMGlobalObject* globalObject, JSC::ArrayBufferView* view)
592 {
593     if (!view)
594         return JSC::jsNull();
595     return view->wrap(exec, globalObject);
596 }
597
598 inline JSC::JSValue toJS(JSC::ExecState* exec, JSC::JSGlobalObject* globalObject, JSC::ArrayBufferView* view)
599 {
600     if (!view)
601         return JSC::jsNull();
602     return view->wrap(exec, globalObject);
603 }
604
605 template<typename T> inline JSC::JSValue toJS(JSC::ExecState* exec, JSDOMGlobalObject* globalObject, Ref<T>&& ptr)
606 {
607     return toJS(exec, globalObject, ptr.get());
608 }
609
610 template<typename T> inline JSC::JSValue toJS(JSC::ExecState* exec, JSDOMGlobalObject* globalObject, RefPtr<T>&& ptr)
611 {
612     return toJS(exec, globalObject, ptr.get());
613 }
614
615 template<typename T> inline JSC::JSValue toJS(JSC::ExecState* exec, JSDOMGlobalObject* globalObject, const Vector<T>& vector)
616 {
617     JSC::VM& vm = globalObject->vm();
618     auto scope = DECLARE_THROW_SCOPE(vm);
619
620     JSC::JSArray* array = constructEmptyArray(exec, nullptr, vector.size());
621     RETURN_IF_EXCEPTION(scope, JSC::JSValue());
622     for (size_t i = 0; i < vector.size(); ++i)
623         array->putDirectIndex(exec, i, toJS(exec, globalObject, vector[i]));
624     return array;
625 }
626
627 template<typename T> inline JSC::JSValue toJS(JSC::ExecState* exec, JSDOMGlobalObject* globalObject, const Vector<RefPtr<T>>& vector)
628 {
629     JSC::VM& vm = globalObject->vm();
630     auto scope = DECLARE_THROW_SCOPE(vm);
631
632     JSC::JSArray* array = constructEmptyArray(exec, nullptr, vector.size());
633     RETURN_IF_EXCEPTION(scope, JSC::JSValue());
634     for (size_t i = 0; i < vector.size(); ++i)
635         array->putDirectIndex(exec, i, toJS(exec, globalObject, vector[i].get()));
636     return array;
637 }
638
639 inline JSC::JSValue toJS(JSC::ExecState* exec, JSDOMGlobalObject*, const String& value)
640 {
641     return jsStringOrNull(exec, value);
642 }
643
644 inline JSC::JSValue toJS(JSC::ExecState* exec, JSDOMGlobalObject*, const JSC::PrivateName& privateName)
645 {
646     return JSC::Symbol::create(exec->vm(), privateName.uid());
647 }
648
649 inline JSC::JSValue toJSIterator(JSC::ExecState& state, JSDOMGlobalObject&, JSC::JSValue value)
650 {
651     return createIteratorResultObject(&state, value, false);
652 }
653
654 template<typename T> inline JSC::JSValue toJSIterator(JSC::ExecState& state, JSDOMGlobalObject& globalObject, const T& value)
655 {
656     return createIteratorResultObject(&state, toJS(&state, &globalObject, value), false);
657 }
658
659 inline JSC::JSValue toJSIteratorEnd(JSC::ExecState& state)
660 {
661     return createIteratorResultObject(&state, JSC::jsUndefined(), true);
662 }
663
664 template<typename T> struct JSValueTraits {
665     static JSC::JSValue arrayJSValue(JSC::ExecState* exec, JSDOMGlobalObject* globalObject, const T& value)
666     {
667         return toJS(exec, globalObject, WTF::getPtr(value));
668     }
669 };
670
671 template<> struct JSValueTraits<String> {
672     static JSC::JSValue arrayJSValue(JSC::ExecState* exec, JSDOMGlobalObject*, const String& value)
673     {
674         return JSC::jsStringWithCache(exec, value);
675     }
676 };
677
678 template<> struct JSValueTraits<double> {
679     static JSC::JSValue arrayJSValue(JSC::ExecState*, JSDOMGlobalObject*, const double& value)
680     {
681         return JSC::jsNumber(value);
682     }
683 };
684
685 template<> struct JSValueTraits<float> {
686     static JSC::JSValue arrayJSValue(JSC::ExecState*, JSDOMGlobalObject*, const float& value)
687     {
688         return JSC::jsNumber(value);
689     }
690 };
691
692 template<> struct JSValueTraits<unsigned long> {
693     static JSC::JSValue arrayJSValue(JSC::ExecState*, JSDOMGlobalObject*, const unsigned long& value)
694     {
695         return JSC::jsNumber(value);
696     }
697 };
698
699 template<typename T, size_t inlineCapacity> JSC::JSValue jsArray(JSC::ExecState* exec, JSDOMGlobalObject* globalObject, const Vector<T, inlineCapacity>& vector)
700 {
701     JSC::MarkedArgumentBuffer list;
702     for (auto& element : vector)
703         list.append(JSValueTraits<T>::arrayJSValue(exec, globalObject, element));
704     return JSC::constructArray(exec, nullptr, globalObject, list);
705 }
706
707 template<typename T, size_t inlineCapacity> inline JSC::JSValue jsArray(JSC::ExecState* exec, JSDOMGlobalObject* globalObject, const Vector<T, inlineCapacity>* vector)
708 {
709     if (!vector)
710         return JSC::constructEmptyArray(exec, nullptr, globalObject, 0);
711     return jsArray(exec, globalObject, *vector);
712 }
713
714 template<typename T, size_t inlineCapacity> JSC::JSValue jsFrozenArray(JSC::ExecState* exec, JSDOMGlobalObject* globalObject, const Vector<T, inlineCapacity>& vector)
715 {
716     JSC::VM& vm = globalObject->vm();
717     auto scope = DECLARE_THROW_SCOPE(vm);
718
719     JSC::MarkedArgumentBuffer list;
720     for (auto& element : vector) {
721         list.append(JSValueTraits<T>::arrayJSValue(exec, globalObject, element));
722         RETURN_IF_EXCEPTION(scope, JSC::JSValue());
723     }
724     auto* array = JSC::constructArray(exec, nullptr, globalObject, list);
725     RETURN_IF_EXCEPTION(scope, JSC::JSValue());
726     return JSC::objectConstructorFreeze(exec, array);
727 }
728
729 inline JSC::JSValue jsPair(JSC::ExecState& state, JSDOMGlobalObject* globalObject, JSC::JSValue value1, JSC::JSValue value2)
730 {
731     JSC::MarkedArgumentBuffer args;
732     args.append(value1);
733     args.append(value2);
734     return constructArray(&state, 0, globalObject, args);
735 }
736
737 template<typename FirstType, typename SecondType> inline JSC::JSValue jsPair(JSC::ExecState& state, JSDOMGlobalObject* globalObject, const FirstType& value1, const SecondType& value2)
738 {
739     return jsPair(state, globalObject, toJS(&state, globalObject, value1), toJS(&state, globalObject, value2));
740 }
741
742 inline RefPtr<JSC::ArrayBufferView> toArrayBufferView(JSC::JSValue value)
743 {
744     auto* wrapper = JSC::jsDynamicCast<JSC::JSArrayBufferView*>(value);
745     if (!wrapper)
746         return nullptr;
747     return wrapper->impl();
748 }
749
750 inline RefPtr<JSC::Int8Array> toInt8Array(JSC::JSValue value) { return JSC::toNativeTypedView<JSC::Int8Adaptor>(value); }
751 inline RefPtr<JSC::Int16Array> toInt16Array(JSC::JSValue value) { return JSC::toNativeTypedView<JSC::Int16Adaptor>(value); }
752 inline RefPtr<JSC::Int32Array> toInt32Array(JSC::JSValue value) { return JSC::toNativeTypedView<JSC::Int32Adaptor>(value); }
753 inline RefPtr<JSC::Uint8Array> toUint8Array(JSC::JSValue value) { return JSC::toNativeTypedView<JSC::Uint8Adaptor>(value); }
754 inline RefPtr<JSC::Uint8ClampedArray> toUint8ClampedArray(JSC::JSValue value) { return JSC::toNativeTypedView<JSC::Uint8ClampedAdaptor>(value); }
755 inline RefPtr<JSC::Uint16Array> toUint16Array(JSC::JSValue value) { return JSC::toNativeTypedView<JSC::Uint16Adaptor>(value); }
756 inline RefPtr<JSC::Uint32Array> toUint32Array(JSC::JSValue value) { return JSC::toNativeTypedView<JSC::Uint32Adaptor>(value); }
757 inline RefPtr<JSC::Float32Array> toFloat32Array(JSC::JSValue value) { return JSC::toNativeTypedView<JSC::Float32Adaptor>(value); }
758 inline RefPtr<JSC::Float64Array> toFloat64Array(JSC::JSValue value) { return JSC::toNativeTypedView<JSC::Float64Adaptor>(value); }
759
760 template<> struct NativeValueTraits<String> {
761     static inline bool nativeValue(JSC::ExecState& exec, JSC::JSValue jsValue, String& indexedValue)
762     {
763         JSC::VM& vm = exec.vm();
764         auto scope = DECLARE_THROW_SCOPE(vm);
765         indexedValue = jsValue.toWTFString(&exec);
766         return !scope.exception();
767     }
768 };
769
770 template<> struct NativeValueTraits<unsigned> {
771     static inline bool nativeValue(JSC::ExecState& exec, JSC::JSValue jsValue, unsigned& indexedValue)
772     {
773         JSC::VM& vm = exec.vm();
774         auto scope = DECLARE_THROW_SCOPE(vm);
775         indexedValue = jsValue.toUInt32(&exec);
776         return !scope.exception();
777     }
778 };
779
780 template<> struct NativeValueTraits<float> {
781     static inline bool nativeValue(JSC::ExecState& exec, JSC::JSValue jsValue, float& indexedValue)
782     {
783         JSC::VM& vm = exec.vm();
784         auto scope = DECLARE_THROW_SCOPE(vm);
785         indexedValue = jsValue.toFloat(&exec);
786         return !scope.exception();
787     }
788 };
789
790 template<> struct NativeValueTraits<double> {
791     static inline bool nativeValue(JSC::ExecState& exec, JSC::JSValue jsValue, double& indexedValue)
792     {
793         JSC::VM& vm = exec.vm();
794         auto scope = DECLARE_THROW_SCOPE(vm);
795         indexedValue = jsValue.toNumber(&exec);
796         return !scope.exception();
797     }
798 };
799
800 template<typename T, typename JST> inline Vector<Ref<T>> toRefNativeArray(JSC::ExecState& state, JSC::JSValue value)
801 {
802     JSC::VM& vm = state.vm();
803     auto scope = DECLARE_THROW_SCOPE(vm);
804
805     if (!value.isObject()) {
806         throwSequenceTypeError(state, scope);
807         return { };
808     }
809
810     Vector<Ref<T>> result;
811     forEachInIterable(&state, value, [&result](JSC::VM& vm, JSC::ExecState* state, JSC::JSValue jsValue) {
812         auto scope = DECLARE_THROW_SCOPE(vm);
813
814         if (jsValue.inherits(JST::info())) {
815             auto* object = JST::toWrapped(jsValue);
816             ASSERT(object);
817             result.append(*object);
818         } else
819             throwArrayElementTypeError(*state, scope);
820     });
821     return result;
822 }
823
824 template<typename T, typename JST> Vector<RefPtr<T>> toRefPtrNativeArray(JSC::ExecState& exec, JSC::JSValue value)
825 {
826     JSC::VM& vm = exec.vm();
827     auto scope = DECLARE_THROW_SCOPE(vm);
828
829     if (!value.isObject()) {
830         throwSequenceTypeError(exec, scope);
831         return { };
832     }
833
834     Vector<RefPtr<T>> result;
835     forEachInIterable(&exec, value, [&result](JSC::VM& vm, JSC::ExecState* state, JSC::JSValue jsValue) {
836         auto scope = DECLARE_THROW_SCOPE(vm);
837
838         if (jsValue.inherits(JST::info()))
839             result.append(JST::toWrapped(jsValue));
840         else
841             throwArrayElementTypeError(*state, scope);
842     });
843     return result;
844 }
845
846 template<typename T> Vector<T> toNativeArray(JSC::ExecState& exec, JSC::JSValue value)
847 {
848     JSC::VM& vm = exec.vm();
849     auto scope = DECLARE_THROW_SCOPE(vm);
850
851     if (!value.isObject()) {
852         throwSequenceTypeError(exec, scope);
853         return Vector<T>();
854     }
855
856     Vector<T> result;
857     forEachInIterable(&exec, value, [&result](JSC::VM& vm, JSC::ExecState* state, JSC::JSValue jsValue) {
858         auto scope = DECLARE_THROW_SCOPE(vm);
859         T convertedValue;
860         bool success = NativeValueTraits<T>::nativeValue(*state, jsValue, convertedValue);
861         ASSERT_UNUSED(scope, scope.exception() || success);
862         if (!success)
863             return;
864         result.append(convertedValue);
865     });
866     return result;
867 }
868
869 inline String propertyNameToString(JSC::PropertyName propertyName)
870 {
871     ASSERT(!propertyName.isSymbol());
872     return propertyName.uid() ? propertyName.uid() : propertyName.publicName();
873 }
874
875 inline AtomicString propertyNameToAtomicString(JSC::PropertyName propertyName)
876 {
877     return AtomicString(propertyName.uid() ? propertyName.uid() : propertyName.publicName());
878 }
879
880 template<JSC::NativeFunction nativeFunction, int length> JSC::EncodedJSValue nonCachingStaticFunctionGetter(JSC::ExecState* exec, JSC::EncodedJSValue, JSC::PropertyName propertyName)
881 {
882     return JSC::JSValue::encode(JSC::JSFunction::create(exec->vm(), exec->lexicalGlobalObject(), length, propertyName.publicName(), nativeFunction));
883 }
884
885 template<typename T> inline JSC::JSValue toNullableJSNumber(Optional<T> optionalNumber)
886 {
887     return optionalNumber ? JSC::jsNumber(optionalNumber.value()) : JSC::jsNull();
888 }
889
890 ALWAYS_INLINE void propagateException(JSC::ExecState& state, JSC::ThrowScope& throwScope, Exception&& exception)
891 {
892     if (throwScope.exception())
893         return;
894     propagateExceptionSlowPath(state, throwScope, WTFMove(exception));
895 }
896
897 ALWAYS_INLINE void setDOMException(JSC::ExecState* exec, JSC::ThrowScope& throwScope, ExceptionCode ec)
898 {
899     if (LIKELY(!ec || throwScope.exception()))
900         return;
901     setDOMExceptionSlow(exec, throwScope, ec);
902 }
903
904 inline void propagateException(JSC::ExecState& state, JSC::ThrowScope& throwScope, ExceptionOr<void>&& value)
905 {
906     if (UNLIKELY(value.hasException()))
907         propagateException(state, throwScope, value.releaseException());
908 }
909
910 template<typename T> inline JSC::JSValue toJS(JSC::ExecState& state, JSDOMGlobalObject& globalObject, JSC::ThrowScope& throwScope, ExceptionOr<T>&& value)
911 {
912     if (UNLIKELY(value.hasException())) {
913         propagateException(state, throwScope, value.releaseException());
914         return { };
915     }
916     return toJS(&state, &globalObject, value.releaseReturnValue());
917 }
918
919 inline JSC::JSValue toJSBoolean(JSC::ExecState& state, JSC::ThrowScope& throwScope, ExceptionOr<bool>&& value)
920 {
921     if (UNLIKELY(value.hasException())) {
922         propagateException(state, throwScope, value.releaseException());
923         return { };
924     }
925     return JSC::jsBoolean(value.releaseReturnValue());
926 }
927
928 template<typename T> inline JSC::JSValue toJSNewlyCreated(JSC::ExecState& state, JSDOMGlobalObject& globalObject, JSC::ThrowScope& throwScope, ExceptionOr<T>&& value)
929 {
930     if (UNLIKELY(value.hasException())) {
931         propagateException(state, throwScope, value.releaseException());
932         return { };
933     }
934     return toJSNewlyCreated(&state, &globalObject, value.releaseReturnValue());
935 }
936
937 template<typename T> inline JSC::JSValue toJSNumber(JSC::ExecState& state, JSC::ThrowScope& throwScope, ExceptionOr<T>&& value)
938 {
939     if (UNLIKELY(value.hasException())) {
940         propagateException(state, throwScope, value.releaseException());
941         return { };
942     }
943     return JSC::jsNumber(value.releaseReturnValue());
944 }
945
946 } // namespace WebCore