Refactor binding generated casted-this checks for attribute setters
[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 AttributeSetterFunction = bool(JSC::ExecState*, JSClass*, JSC::JSValue, JSC::ThrowScope&);
337     using AttributeGetterFunction = JSC::JSValue(JSC::ExecState*, JSClass*, JSC::ThrowScope&);
338
339     template<AttributeSetterFunction setter, CastedThisErrorBehavior shouldThrow = CastedThisErrorBehavior::Throw>
340     static bool setAttribute(JSC::ExecState* state, JSC::EncodedJSValue thisValue, JSC::EncodedJSValue encodedValue, const char* attributeName)
341     {
342         ASSERT(state);
343         auto throwScope = DECLARE_THROW_SCOPE(state->vm());
344         auto* thisObject = JSClass::castForAttribute(state, thisValue);
345         if (UNLIKELY(!thisObject)) {
346             ASSERT(JSClass::info());
347             return (shouldThrow == CastedThisErrorBehavior::Throw) ? throwSetterTypeError(*state, throwScope, JSClass::info()->className, attributeName) : false;
348         }
349         // FIXME: We should refactor the binding generated code to use references for state and thisObject.
350         return setter(state, thisObject, JSC::JSValue::decode(encodedValue), throwScope);
351     }
352
353     template<AttributeGetterFunction getter, CastedThisErrorBehavior shouldThrow = CastedThisErrorBehavior::Throw>
354     static JSC::EncodedJSValue attribute(JSC::ExecState* state, JSC::EncodedJSValue thisValue, const char* attributeName)
355     {
356         ASSERT(state);
357         auto throwScope = DECLARE_THROW_SCOPE(state->vm());
358         auto* thisObject = JSClass::castForAttribute(state, thisValue);
359         if (UNLIKELY(!thisObject)) {
360             ASSERT(JSClass::info());
361             if (shouldThrow == CastedThisErrorBehavior::Throw)
362                 return throwGetterTypeError(*state, throwScope, JSClass::info()->className, attributeName);
363             if (shouldThrow == CastedThisErrorBehavior::RejectPromise)
364                 return rejectPromiseWithGetterTypeError(*state, JSClass::info()->className, attributeName);
365             return JSC::JSValue::encode(JSC::jsUndefined());
366         }
367         // FIXME: We should refactor the binding generated code to use references for state and thisObject.
368         return JSC::JSValue::encode(getter(state, thisObject, throwScope));
369     }
370 };
371
372 // ExceptionOr handling.
373 void propagateException(JSC::ExecState&, JSC::ThrowScope&, ExceptionOr<void>&&);
374 template<typename T> JSC::JSValue toJS(JSC::ExecState&, JSDOMGlobalObject&, JSC::ThrowScope&, ExceptionOr<T>&&);
375 JSC::JSValue toJSBoolean(JSC::ExecState&, JSC::ThrowScope&, ExceptionOr<bool>&&);
376 JSC::JSValue toJSDate(JSC::ExecState&, JSC::ThrowScope&, ExceptionOr<double>&&);
377 JSC::JSValue toJSNullableDate(JSC::ExecState&, JSC::ThrowScope&, ExceptionOr<Optional<double>>&&);
378 JSC::JSValue toJSNullableString(JSC::ExecState&, JSC::ThrowScope&, ExceptionOr<String>&&);
379 template<typename T> JSC::JSValue toJSNewlyCreated(JSC::ExecState&, JSDOMGlobalObject&, JSC::ThrowScope&, ExceptionOr<T>&& value);
380 template<typename T> JSC::JSValue toJSNumber(JSC::ExecState&, JSC::ThrowScope&, ExceptionOr<T>&& value);
381 template<typename T> JSC::JSValue toJSNullableNumber(JSC::ExecState&, JSC::ThrowScope&, ExceptionOr<T>&& value);
382 JSC::JSValue toJSString(JSC::ExecState&, JSC::ThrowScope&, ExceptionOr<String>&&);
383
384 // Inline functions and template definitions.
385
386 inline JSC::Structure* DOMConstructorObject::createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype)
387 {
388     return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), info());
389 }
390
391 inline DOMConstructorObject::DOMConstructorObject(JSC::Structure* structure, JSDOMGlobalObject& globalObject)
392     : JSDOMObject(structure, globalObject)
393 {
394 }
395
396 inline String DOMConstructorObject::className(const JSObject*)
397 {
398     return ASCIILiteral("Function");
399 }
400
401 inline DOMConstructorJSBuiltinObject::DOMConstructorJSBuiltinObject(JSC::Structure* structure, JSDOMGlobalObject& globalObject)
402     : DOMConstructorObject(structure, globalObject)
403 {
404 }
405
406 inline JSC::JSFunction* DOMConstructorJSBuiltinObject::initializeFunction()
407 {
408     return m_initializeFunction.get();
409 }
410
411 inline void DOMConstructorJSBuiltinObject::setInitializeFunction(JSC::VM& vm, JSC::JSFunction& function)
412 {
413     m_initializeFunction.set(vm, this, &function);
414 }
415
416 inline JSDOMGlobalObject* deprecatedGlobalObjectForPrototype(JSC::ExecState* exec)
417 {
418     // FIXME: Callers to this function should be using the global object
419     // from which the object is being created, instead of assuming the lexical one.
420     // e.g. subframe.document.body should use the subframe's global object, not the lexical one.
421     return JSC::jsCast<JSDOMGlobalObject*>(exec->lexicalGlobalObject());
422 }
423
424 template<typename WrapperClass> inline JSC::Structure* getDOMStructure(JSC::VM& vm, JSDOMGlobalObject& globalObject)
425 {
426     if (JSC::Structure* structure = getCachedDOMStructure(globalObject, WrapperClass::info()))
427         return structure;
428     return cacheDOMStructure(globalObject, WrapperClass::createStructure(vm, &globalObject, WrapperClass::createPrototype(vm, &globalObject)), WrapperClass::info());
429 }
430
431 template<typename WrapperClass> inline JSC::Structure* deprecatedGetDOMStructure(JSC::ExecState* exec)
432 {
433     // FIXME: This function is wrong. It uses the wrong global object for creating the prototype structure.
434     return getDOMStructure<WrapperClass>(exec->vm(), *deprecatedGlobalObjectForPrototype(exec));
435 }
436
437 template<typename WrapperClass> inline JSC::JSObject* getDOMPrototype(JSC::VM& vm, JSC::JSGlobalObject* globalObject)
438 {
439     return JSC::jsCast<JSC::JSObject*>(asObject(getDOMStructure<WrapperClass>(vm, *JSC::jsCast<JSDOMGlobalObject*>(globalObject))->storedPrototype()));
440 }
441
442 template<typename JSClass> inline JSC::EncodedJSValue createJSBuiltin(JSC::ExecState& state, JSC::JSFunction& initializeFunction, JSDOMGlobalObject& globalObject)
443 {
444     JSC::JSObject* object = JSClass::create(getDOMStructure<JSClass>(globalObject.vm(), globalObject), &globalObject);
445     callFunctionWithCurrentArguments(state, *object, initializeFunction);
446     return JSC::JSValue::encode(object);
447 }
448
449 inline JSC::WeakHandleOwner* wrapperOwner(DOMWrapperWorld& world, JSC::ArrayBuffer*)
450 {
451     return static_cast<WebCoreTypedArrayController*>(world.vm().m_typedArrayController.get())->wrapperOwner();
452 }
453
454 inline void* wrapperKey(JSC::ArrayBuffer* domObject)
455 {
456     return domObject;
457 }
458
459 inline JSDOMObject* getInlineCachedWrapper(DOMWrapperWorld&, void*) { return nullptr; }
460 inline bool setInlineCachedWrapper(DOMWrapperWorld&, void*, JSDOMObject*, JSC::WeakHandleOwner*) { return false; }
461 inline bool clearInlineCachedWrapper(DOMWrapperWorld&, void*, JSDOMObject*) { return false; }
462
463 inline JSDOMObject* getInlineCachedWrapper(DOMWrapperWorld& world, ScriptWrappable* domObject)
464 {
465     if (!world.isNormal())
466         return nullptr;
467     return domObject->wrapper();
468 }
469
470 inline JSC::JSArrayBuffer* getInlineCachedWrapper(DOMWrapperWorld& world, JSC::ArrayBuffer* buffer)
471 {
472     if (!world.isNormal())
473         return nullptr;
474     return buffer->m_wrapper.get();
475 }
476
477 inline bool setInlineCachedWrapper(DOMWrapperWorld& world, ScriptWrappable* domObject, JSDOMObject* wrapper, JSC::WeakHandleOwner* wrapperOwner)
478 {
479     if (!world.isNormal())
480         return false;
481     domObject->setWrapper(wrapper, wrapperOwner, &world);
482     return true;
483 }
484
485 inline bool setInlineCachedWrapper(DOMWrapperWorld& world, JSC::ArrayBuffer* domObject, JSC::JSArrayBuffer* wrapper, JSC::WeakHandleOwner* wrapperOwner)
486 {
487     if (!world.isNormal())
488         return false;
489     domObject->m_wrapper = JSC::Weak<JSC::JSArrayBuffer>(wrapper, wrapperOwner, &world);
490     return true;
491 }
492
493 inline bool clearInlineCachedWrapper(DOMWrapperWorld& world, ScriptWrappable* domObject, JSDOMObject* wrapper)
494 {
495     if (!world.isNormal())
496         return false;
497     domObject->clearWrapper(wrapper);
498     return true;
499 }
500
501 inline bool clearInlineCachedWrapper(DOMWrapperWorld& world, JSC::ArrayBuffer* domObject, JSC::JSArrayBuffer* wrapper)
502 {
503     if (!world.isNormal())
504         return false;
505     weakClear(domObject->m_wrapper, wrapper);
506     return true;
507 }
508
509 template<typename DOMClass> inline JSC::JSObject* getCachedWrapper(DOMWrapperWorld& world, DOMClass& domObject)
510 {
511     if (auto* wrapper = getInlineCachedWrapper(world, &domObject))
512         return wrapper;
513     return world.m_wrappers.get(wrapperKey(&domObject));
514 }
515
516 template<typename DOMClass, typename WrapperClass> inline void cacheWrapper(DOMWrapperWorld& world, DOMClass* domObject, WrapperClass* wrapper)
517 {
518     JSC::WeakHandleOwner* owner = wrapperOwner(world, domObject);
519     if (setInlineCachedWrapper(world, domObject, wrapper, owner))
520         return;
521     weakAdd(world.m_wrappers, wrapperKey(domObject), JSC::Weak<JSC::JSObject>(wrapper, owner, &world));
522 }
523
524 template<typename DOMClass, typename WrapperClass> inline void uncacheWrapper(DOMWrapperWorld& world, DOMClass* domObject, WrapperClass* wrapper)
525 {
526     if (clearInlineCachedWrapper(world, domObject, wrapper))
527         return;
528     weakRemove(world.m_wrappers, wrapperKey(domObject), wrapper);
529 }
530
531 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
532 {
533     using WrapperClass = typename JSDOMWrapperConverterTraits<DOMClass>::WrapperClass;
534
535     ASSERT(!getCachedWrapper(globalObject->world(), domObject));
536     auto* domObjectPtr = domObject.ptr();
537     auto* wrapper = WrapperClass::create(getDOMStructure<WrapperClass>(globalObject->vm(), *globalObject), globalObject, WTFMove(domObject));
538     cacheWrapper(globalObject->world(), domObjectPtr, wrapper);
539     return wrapper;
540 }
541
542 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
543 {
544     return createWrapper<DOMClass>(globalObject, static_reference_cast<DOMClass>(WTFMove(domObject)));
545 }
546
547 template<typename DOMClass> inline JSC::JSValue wrap(JSC::ExecState* state, JSDOMGlobalObject* globalObject, DOMClass& domObject)
548 {
549     if (auto* wrapper = getCachedWrapper(globalObject->world(), domObject))
550         return wrapper;
551     return toJSNewlyCreated(state, globalObject, Ref<DOMClass>(domObject));
552 }
553
554 template<typename JSClass> inline JSClass& castThisValue(JSC::ExecState& state)
555 {
556     auto thisValue = state.thisValue();
557     auto castedThis = JSC::jsDynamicCast<JSClass*>(thisValue);
558     ASSERT(castedThis);
559     return *castedThis;
560 }
561
562 inline int32_t finiteInt32Value(JSC::JSValue value, JSC::ExecState* exec, bool& okay)
563 {
564     double number = value.toNumber(exec);
565     okay = std::isfinite(number);
566     return JSC::toInt32(number);
567 }
568
569 // Validates that the passed object is a sequence type per section 4.1.13 of the WebIDL spec.
570 inline JSC::JSObject* toJSSequence(JSC::ExecState& exec, JSC::JSValue value, unsigned& length)
571 {
572     JSC::VM& vm = exec.vm();
573     auto scope = DECLARE_THROW_SCOPE(vm);
574
575     JSC::JSObject* object = value.getObject();
576     if (!object) {
577         throwSequenceTypeError(exec, scope);
578         return nullptr;
579     }
580
581     JSC::JSValue lengthValue = object->get(&exec, exec.propertyNames().length);
582     RETURN_IF_EXCEPTION(scope, nullptr);
583
584     if (lengthValue.isUndefinedOrNull()) {
585         throwSequenceTypeError(exec, scope);
586         return nullptr;
587     }
588
589     length = lengthValue.toUInt32(&exec);
590     RETURN_IF_EXCEPTION(scope, nullptr);
591
592     return object;
593 }
594
595 inline JSC::JSValue toJS(JSC::ExecState* exec, JSDOMGlobalObject* globalObject, JSC::ArrayBuffer* buffer)
596 {
597     if (!buffer)
598         return JSC::jsNull();
599     if (JSC::JSValue result = getCachedWrapper(globalObject->world(), *buffer))
600         return result;
601
602     // The JSArrayBuffer::create function will register the wrapper in finishCreation.
603     return JSC::JSArrayBuffer::create(exec->vm(), globalObject->arrayBufferStructure(), buffer);
604 }
605
606 inline JSC::JSValue toJS(JSC::ExecState* exec, JSDOMGlobalObject* globalObject, JSC::ArrayBufferView* view)
607 {
608     if (!view)
609         return JSC::jsNull();
610     return view->wrap(exec, globalObject);
611 }
612
613 inline JSC::JSValue toJS(JSC::ExecState* exec, JSC::JSGlobalObject* globalObject, JSC::ArrayBufferView* view)
614 {
615     if (!view)
616         return JSC::jsNull();
617     return view->wrap(exec, globalObject);
618 }
619
620 template<typename T> inline JSC::JSValue toJS(JSC::ExecState* exec, JSDOMGlobalObject* globalObject, Ref<T>&& ptr)
621 {
622     return toJS(exec, globalObject, ptr.get());
623 }
624
625 template<typename T> inline JSC::JSValue toJS(JSC::ExecState* exec, JSDOMGlobalObject* globalObject, RefPtr<T>&& ptr)
626 {
627     return toJS(exec, globalObject, ptr.get());
628 }
629
630 template<typename T> inline JSC::JSValue toJS(JSC::ExecState* exec, JSDOMGlobalObject* globalObject, const Vector<T>& vector)
631 {
632     JSC::VM& vm = globalObject->vm();
633     auto scope = DECLARE_THROW_SCOPE(vm);
634
635     JSC::JSArray* array = constructEmptyArray(exec, nullptr, vector.size());
636     RETURN_IF_EXCEPTION(scope, JSC::JSValue());
637     for (size_t i = 0; i < vector.size(); ++i)
638         array->putDirectIndex(exec, i, toJS(exec, globalObject, vector[i]));
639     return array;
640 }
641
642 template<typename T> inline JSC::JSValue toJS(JSC::ExecState* exec, JSDOMGlobalObject* globalObject, const Vector<RefPtr<T>>& vector)
643 {
644     JSC::VM& vm = globalObject->vm();
645     auto scope = DECLARE_THROW_SCOPE(vm);
646
647     JSC::JSArray* array = constructEmptyArray(exec, nullptr, vector.size());
648     RETURN_IF_EXCEPTION(scope, JSC::JSValue());
649     for (size_t i = 0; i < vector.size(); ++i)
650         array->putDirectIndex(exec, i, toJS(exec, globalObject, vector[i].get()));
651     return array;
652 }
653
654 inline JSC::JSValue toJS(JSC::ExecState* exec, JSDOMGlobalObject*, const String& value)
655 {
656     return jsStringOrNull(exec, value);
657 }
658
659 inline JSC::JSValue toJS(JSC::ExecState* exec, JSDOMGlobalObject*, const JSC::PrivateName& privateName)
660 {
661     return JSC::Symbol::create(exec->vm(), privateName.uid());
662 }
663
664 inline JSC::JSValue toJSIterator(JSC::ExecState& state, JSDOMGlobalObject&, JSC::JSValue value)
665 {
666     return createIteratorResultObject(&state, value, false);
667 }
668
669 template<typename T> inline JSC::JSValue toJSIterator(JSC::ExecState& state, JSDOMGlobalObject& globalObject, const T& value)
670 {
671     return createIteratorResultObject(&state, toJS(&state, &globalObject, value), false);
672 }
673
674 inline JSC::JSValue toJSIteratorEnd(JSC::ExecState& state)
675 {
676     return createIteratorResultObject(&state, JSC::jsUndefined(), true);
677 }
678
679 template<typename T> struct JSValueTraits {
680     static JSC::JSValue arrayJSValue(JSC::ExecState* exec, JSDOMGlobalObject* globalObject, const T& value)
681     {
682         return toJS(exec, globalObject, WTF::getPtr(value));
683     }
684 };
685
686 template<> struct JSValueTraits<String> {
687     static JSC::JSValue arrayJSValue(JSC::ExecState* exec, JSDOMGlobalObject*, const String& value)
688     {
689         return JSC::jsStringWithCache(exec, value);
690     }
691 };
692
693 template<> struct JSValueTraits<double> {
694     static JSC::JSValue arrayJSValue(JSC::ExecState*, JSDOMGlobalObject*, const double& value)
695     {
696         return JSC::jsNumber(value);
697     }
698 };
699
700 template<> struct JSValueTraits<float> {
701     static JSC::JSValue arrayJSValue(JSC::ExecState*, JSDOMGlobalObject*, const float& value)
702     {
703         return JSC::jsNumber(value);
704     }
705 };
706
707 template<> struct JSValueTraits<unsigned long> {
708     static JSC::JSValue arrayJSValue(JSC::ExecState*, JSDOMGlobalObject*, const unsigned long& value)
709     {
710         return JSC::jsNumber(value);
711     }
712 };
713
714 template<typename T, size_t inlineCapacity> JSC::JSValue jsArray(JSC::ExecState* exec, JSDOMGlobalObject* globalObject, const Vector<T, inlineCapacity>& vector)
715 {
716     JSC::MarkedArgumentBuffer list;
717     for (auto& element : vector)
718         list.append(JSValueTraits<T>::arrayJSValue(exec, globalObject, element));
719     return JSC::constructArray(exec, nullptr, globalObject, list);
720 }
721
722 template<typename T, size_t inlineCapacity> inline JSC::JSValue jsArray(JSC::ExecState* exec, JSDOMGlobalObject* globalObject, const Vector<T, inlineCapacity>* vector)
723 {
724     if (!vector)
725         return JSC::constructEmptyArray(exec, nullptr, globalObject, 0);
726     return jsArray(exec, globalObject, *vector);
727 }
728
729 template<typename T, size_t inlineCapacity> JSC::JSValue jsFrozenArray(JSC::ExecState* exec, JSDOMGlobalObject* globalObject, const Vector<T, inlineCapacity>& vector)
730 {
731     JSC::VM& vm = globalObject->vm();
732     auto scope = DECLARE_THROW_SCOPE(vm);
733
734     JSC::MarkedArgumentBuffer list;
735     for (auto& element : vector) {
736         list.append(JSValueTraits<T>::arrayJSValue(exec, globalObject, element));
737         RETURN_IF_EXCEPTION(scope, JSC::JSValue());
738     }
739     auto* array = JSC::constructArray(exec, nullptr, globalObject, list);
740     RETURN_IF_EXCEPTION(scope, JSC::JSValue());
741     return JSC::objectConstructorFreeze(exec, array);
742 }
743
744 inline JSC::JSValue jsPair(JSC::ExecState& state, JSDOMGlobalObject* globalObject, JSC::JSValue value1, JSC::JSValue value2)
745 {
746     JSC::MarkedArgumentBuffer args;
747     args.append(value1);
748     args.append(value2);
749     return constructArray(&state, 0, globalObject, args);
750 }
751
752 template<typename FirstType, typename SecondType> inline JSC::JSValue jsPair(JSC::ExecState& state, JSDOMGlobalObject* globalObject, const FirstType& value1, const SecondType& value2)
753 {
754     return jsPair(state, globalObject, toJS(&state, globalObject, value1), toJS(&state, globalObject, value2));
755 }
756
757 inline RefPtr<JSC::ArrayBufferView> toArrayBufferView(JSC::JSValue value)
758 {
759     auto* wrapper = JSC::jsDynamicCast<JSC::JSArrayBufferView*>(value);
760     if (!wrapper)
761         return nullptr;
762     return wrapper->impl();
763 }
764
765 inline RefPtr<JSC::Int8Array> toInt8Array(JSC::JSValue value) { return JSC::toNativeTypedView<JSC::Int8Adaptor>(value); }
766 inline RefPtr<JSC::Int16Array> toInt16Array(JSC::JSValue value) { return JSC::toNativeTypedView<JSC::Int16Adaptor>(value); }
767 inline RefPtr<JSC::Int32Array> toInt32Array(JSC::JSValue value) { return JSC::toNativeTypedView<JSC::Int32Adaptor>(value); }
768 inline RefPtr<JSC::Uint8Array> toUint8Array(JSC::JSValue value) { return JSC::toNativeTypedView<JSC::Uint8Adaptor>(value); }
769 inline RefPtr<JSC::Uint8ClampedArray> toUint8ClampedArray(JSC::JSValue value) { return JSC::toNativeTypedView<JSC::Uint8ClampedAdaptor>(value); }
770 inline RefPtr<JSC::Uint16Array> toUint16Array(JSC::JSValue value) { return JSC::toNativeTypedView<JSC::Uint16Adaptor>(value); }
771 inline RefPtr<JSC::Uint32Array> toUint32Array(JSC::JSValue value) { return JSC::toNativeTypedView<JSC::Uint32Adaptor>(value); }
772 inline RefPtr<JSC::Float32Array> toFloat32Array(JSC::JSValue value) { return JSC::toNativeTypedView<JSC::Float32Adaptor>(value); }
773 inline RefPtr<JSC::Float64Array> toFloat64Array(JSC::JSValue value) { return JSC::toNativeTypedView<JSC::Float64Adaptor>(value); }
774
775 template<> struct NativeValueTraits<String> {
776     static inline bool nativeValue(JSC::ExecState& exec, JSC::JSValue jsValue, String& indexedValue)
777     {
778         JSC::VM& vm = exec.vm();
779         auto scope = DECLARE_THROW_SCOPE(vm);
780         indexedValue = jsValue.toWTFString(&exec);
781         return !scope.exception();
782     }
783 };
784
785 template<> struct NativeValueTraits<unsigned> {
786     static inline bool nativeValue(JSC::ExecState& exec, JSC::JSValue jsValue, unsigned& indexedValue)
787     {
788         JSC::VM& vm = exec.vm();
789         auto scope = DECLARE_THROW_SCOPE(vm);
790         indexedValue = jsValue.toUInt32(&exec);
791         return !scope.exception();
792     }
793 };
794
795 template<> struct NativeValueTraits<float> {
796     static inline bool nativeValue(JSC::ExecState& exec, JSC::JSValue jsValue, float& indexedValue)
797     {
798         JSC::VM& vm = exec.vm();
799         auto scope = DECLARE_THROW_SCOPE(vm);
800         indexedValue = jsValue.toFloat(&exec);
801         return !scope.exception();
802     }
803 };
804
805 template<> struct NativeValueTraits<double> {
806     static inline bool nativeValue(JSC::ExecState& exec, JSC::JSValue jsValue, double& indexedValue)
807     {
808         JSC::VM& vm = exec.vm();
809         auto scope = DECLARE_THROW_SCOPE(vm);
810         indexedValue = jsValue.toNumber(&exec);
811         return !scope.exception();
812     }
813 };
814
815 template<typename T, typename JST> inline Vector<Ref<T>> toRefNativeArray(JSC::ExecState& state, JSC::JSValue value)
816 {
817     JSC::VM& vm = state.vm();
818     auto scope = DECLARE_THROW_SCOPE(vm);
819
820     if (!value.isObject()) {
821         throwSequenceTypeError(state, scope);
822         return { };
823     }
824
825     Vector<Ref<T>> result;
826     forEachInIterable(&state, value, [&result](JSC::VM& vm, JSC::ExecState* state, JSC::JSValue jsValue) {
827         auto scope = DECLARE_THROW_SCOPE(vm);
828
829         if (jsValue.inherits(JST::info())) {
830             auto* object = JST::toWrapped(jsValue);
831             ASSERT(object);
832             result.append(*object);
833         } else
834             throwArrayElementTypeError(*state, scope);
835     });
836     return result;
837 }
838
839 template<typename T, typename JST> Vector<RefPtr<T>> toRefPtrNativeArray(JSC::ExecState& exec, JSC::JSValue value)
840 {
841     JSC::VM& vm = exec.vm();
842     auto scope = DECLARE_THROW_SCOPE(vm);
843
844     if (!value.isObject()) {
845         throwSequenceTypeError(exec, scope);
846         return { };
847     }
848
849     Vector<RefPtr<T>> result;
850     forEachInIterable(&exec, value, [&result](JSC::VM& vm, JSC::ExecState* state, JSC::JSValue jsValue) {
851         auto scope = DECLARE_THROW_SCOPE(vm);
852
853         if (jsValue.inherits(JST::info()))
854             result.append(JST::toWrapped(jsValue));
855         else
856             throwArrayElementTypeError(*state, scope);
857     });
858     return result;
859 }
860
861 template<typename T> Vector<T> toNativeArray(JSC::ExecState& exec, JSC::JSValue value)
862 {
863     JSC::VM& vm = exec.vm();
864     auto scope = DECLARE_THROW_SCOPE(vm);
865
866     if (!value.isObject()) {
867         throwSequenceTypeError(exec, scope);
868         return Vector<T>();
869     }
870
871     Vector<T> result;
872     forEachInIterable(&exec, value, [&result](JSC::VM& vm, JSC::ExecState* state, JSC::JSValue jsValue) {
873         auto scope = DECLARE_THROW_SCOPE(vm);
874         T convertedValue;
875         bool success = NativeValueTraits<T>::nativeValue(*state, jsValue, convertedValue);
876         ASSERT_UNUSED(scope, scope.exception() || success);
877         if (!success)
878             return;
879         result.append(convertedValue);
880     });
881     return result;
882 }
883
884 inline String propertyNameToString(JSC::PropertyName propertyName)
885 {
886     ASSERT(!propertyName.isSymbol());
887     return propertyName.uid() ? propertyName.uid() : propertyName.publicName();
888 }
889
890 inline AtomicString propertyNameToAtomicString(JSC::PropertyName propertyName)
891 {
892     return AtomicString(propertyName.uid() ? propertyName.uid() : propertyName.publicName());
893 }
894
895 template<JSC::NativeFunction nativeFunction, int length> JSC::EncodedJSValue nonCachingStaticFunctionGetter(JSC::ExecState* exec, JSC::EncodedJSValue, JSC::PropertyName propertyName)
896 {
897     return JSC::JSValue::encode(JSC::JSFunction::create(exec->vm(), exec->lexicalGlobalObject(), length, propertyName.publicName(), nativeFunction));
898 }
899
900 template<typename T> inline JSC::JSValue toNullableJSNumber(Optional<T> optionalNumber)
901 {
902     return optionalNumber ? JSC::jsNumber(optionalNumber.value()) : JSC::jsNull();
903 }
904
905 ALWAYS_INLINE void propagateException(JSC::ExecState& state, JSC::ThrowScope& throwScope, Exception&& exception)
906 {
907     if (throwScope.exception())
908         return;
909     propagateExceptionSlowPath(state, throwScope, WTFMove(exception));
910 }
911
912 ALWAYS_INLINE void setDOMException(JSC::ExecState* exec, JSC::ThrowScope& throwScope, ExceptionCode ec)
913 {
914     if (LIKELY(!ec || throwScope.exception()))
915         return;
916     setDOMExceptionSlow(exec, throwScope, ec);
917 }
918
919 inline void propagateException(JSC::ExecState& state, JSC::ThrowScope& throwScope, ExceptionOr<void>&& value)
920 {
921     if (UNLIKELY(value.hasException()))
922         propagateException(state, throwScope, value.releaseException());
923 }
924
925 template<typename T> inline JSC::JSValue toJS(JSC::ExecState& state, JSDOMGlobalObject& globalObject, JSC::ThrowScope& throwScope, ExceptionOr<T>&& value)
926 {
927     if (UNLIKELY(value.hasException())) {
928         propagateException(state, throwScope, value.releaseException());
929         return { };
930     }
931     return toJS(&state, &globalObject, value.releaseReturnValue());
932 }
933
934 inline JSC::JSValue toJSBoolean(JSC::ExecState& state, JSC::ThrowScope& throwScope, ExceptionOr<bool>&& value)
935 {
936     if (UNLIKELY(value.hasException())) {
937         propagateException(state, throwScope, value.releaseException());
938         return { };
939     }
940     return JSC::jsBoolean(value.releaseReturnValue());
941 }
942
943 template<typename T> inline JSC::JSValue toJSNewlyCreated(JSC::ExecState& state, JSDOMGlobalObject& globalObject, JSC::ThrowScope& throwScope, ExceptionOr<T>&& value)
944 {
945     if (UNLIKELY(value.hasException())) {
946         propagateException(state, throwScope, value.releaseException());
947         return { };
948     }
949     return toJSNewlyCreated(&state, &globalObject, value.releaseReturnValue());
950 }
951
952 template<typename T> inline JSC::JSValue toJSNumber(JSC::ExecState& state, JSC::ThrowScope& throwScope, ExceptionOr<T>&& value)
953 {
954     if (UNLIKELY(value.hasException())) {
955         propagateException(state, throwScope, value.releaseException());
956         return { };
957     }
958     return JSC::jsNumber(value.releaseReturnValue());
959 }
960
961 } // namespace WebCore