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