Rename JSDOMWrapper to JSDOMObject and JSDOMWrapperWithImplementation to JSDOMWrapper
[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 #ifndef JSDOMBinding_h
25 #define JSDOMBinding_h
26
27 #include "JSDOMGlobalObject.h"
28 #include "JSDOMWrapper.h"
29 #include "DOMWrapperWorld.h"
30 #include "ScriptWrappable.h"
31 #include "ScriptWrappableInlines.h"
32 #include "WebCoreTypedArrayController.h"
33 #include <cstddef>
34 #include <heap/SlotVisitorInlines.h>
35 #include <heap/Weak.h>
36 #include <heap/WeakInlines.h>
37 #include <runtime/Error.h>
38 #include <runtime/IteratorOperations.h>
39 #include <runtime/JSArray.h>
40 #include <runtime/JSArrayBuffer.h>
41 #include <runtime/JSCJSValueInlines.h>
42 #include <runtime/JSCellInlines.h>
43 #include <runtime/JSTypedArrays.h>
44 #include <runtime/Lookup.h>
45 #include <runtime/StructureInlines.h>
46 #include <runtime/TypedArrayInlines.h>
47 #include <runtime/TypedArrays.h>
48 #include <runtime/WriteBarrier.h>
49 #include <wtf/Forward.h>
50 #include <wtf/GetPtr.h>
51 #include <wtf/Noncopyable.h>
52 #include <wtf/Vector.h>
53
54 namespace JSC {
55 class HashEntry;
56 class JSFunction;
57 }
58
59 namespace WebCore {
60
61 class CachedScript;
62 class DOMStringList;
63 class DOMWindow;
64 class Frame;
65 class URL;
66 class Node;
67
68 typedef int ExceptionCode;
69
70 DOMWindow& activeDOMWindow(JSC::ExecState*);
71 DOMWindow& firstDOMWindow(JSC::ExecState*);
72
73 WEBCORE_EXPORT JSC::EncodedJSValue reportDeprecatedGetterError(JSC::ExecState&, const char* interfaceName, const char* attributeName);
74 WEBCORE_EXPORT void reportDeprecatedSetterError(JSC::ExecState&, const char* interfaceName, const char* attributeName);
75
76 void throwArrayElementTypeError(JSC::ExecState&);
77 void throwAttributeTypeError(JSC::ExecState&, const char* interfaceName, const char* attributeName, const char* expectedType);
78 WEBCORE_EXPORT void throwSequenceTypeError(JSC::ExecState&);
79 WEBCORE_EXPORT void throwSetterTypeError(JSC::ExecState&, const char* interfaceName, const char* attributeName);
80
81 WEBCORE_EXPORT JSC::EncodedJSValue throwArgumentMustBeEnumError(JSC::ExecState&, unsigned argumentIndex, const char* argumentName, const char* functionInterfaceName, const char* functionName, const char* expectedValues);
82 JSC::EncodedJSValue throwArgumentMustBeFunctionError(JSC::ExecState&, unsigned argumentIndex, const char* argumentName, const char* functionInterfaceName, const char* functionName);
83 JSC::EncodedJSValue throwArgumentTypeError(JSC::ExecState&, unsigned argumentIndex, const char* argumentName, const char* functionInterfaceName, const char* functionName, const char* expectedType);
84 JSC::EncodedJSValue throwConstructorDocumentUnavailableError(JSC::ExecState&, const char* interfaceName);
85 WEBCORE_EXPORT JSC::EncodedJSValue throwGetterTypeError(JSC::ExecState&, const char* interfaceName, const char* attributeName);
86 WEBCORE_EXPORT JSC::EncodedJSValue throwThisTypeError(JSC::ExecState&, const char* interfaceName, const char* functionName);
87
88 // Base class for all constructor objects in the JSC bindings.
89 class DOMConstructorObject : public JSDOMObject {
90 public:
91     typedef JSDOMObject Base;
92     static const unsigned StructureFlags = Base::StructureFlags | JSC::ImplementsHasInstance;
93
94     static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype)
95     {
96         return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), info());
97     }
98
99 protected:
100     DOMConstructorObject(JSC::Structure* structure, JSDOMGlobalObject& globalObject)
101         : JSDOMObject(structure, globalObject)
102     {
103     }
104 };
105
106 class DOMConstructorJSBuiltinObject : public DOMConstructorObject {
107 public:
108     typedef DOMConstructorObject Base;
109
110 protected:
111     DOMConstructorJSBuiltinObject(JSC::Structure* structure, JSDOMGlobalObject& globalObject)
112         : DOMConstructorObject(structure, globalObject) { }
113
114     static void visitChildren(JSC::JSCell*, JSC::SlotVisitor&);
115
116     JSC::JSFunction* initializeFunction() { return m_initializeFunction.get(); }
117     void setInitializeFunction(JSC::VM& vm, JSC::JSFunction& function) { m_initializeFunction.set(vm, this, &function); }
118
119 private:
120     JSC::WriteBarrier<JSC::JSFunction> m_initializeFunction;
121 };
122
123 WEBCORE_EXPORT JSC::Structure* getCachedDOMStructure(JSDOMGlobalObject&, const JSC::ClassInfo*);
124 WEBCORE_EXPORT JSC::Structure* cacheDOMStructure(JSDOMGlobalObject&, JSC::Structure*, const JSC::ClassInfo*);
125
126 inline JSDOMGlobalObject* deprecatedGlobalObjectForPrototype(JSC::ExecState* exec)
127 {
128     // FIXME: Callers to this function should be using the global object
129     // from which the object is being created, instead of assuming the lexical one.
130     // e.g. subframe.document.body should use the subframe's global object, not the lexical one.
131     return JSC::jsCast<JSDOMGlobalObject*>(exec->lexicalGlobalObject());
132 }
133
134 template<typename WrapperClass> inline JSC::Structure* getDOMStructure(JSC::VM& vm, JSDOMGlobalObject& globalObject)
135 {
136     if (JSC::Structure* structure = getCachedDOMStructure(globalObject, WrapperClass::info()))
137         return structure;
138     return cacheDOMStructure(globalObject, WrapperClass::createStructure(vm, &globalObject, WrapperClass::createPrototype(vm, &globalObject)), WrapperClass::info());
139 }
140
141 template<typename WrapperClass> inline JSC::Structure* deprecatedGetDOMStructure(JSC::ExecState* exec)
142 {
143     // FIXME: This function is wrong. It uses the wrong global object for creating the prototype structure.
144     return getDOMStructure<WrapperClass>(exec->vm(), *deprecatedGlobalObjectForPrototype(exec));
145 }
146
147 template<typename WrapperClass> inline JSC::JSObject* getDOMPrototype(JSC::VM& vm, JSC::JSGlobalObject* globalObject)
148 {
149     return JSC::jsCast<JSC::JSObject*>(asObject(getDOMStructure<WrapperClass>(vm, *JSC::jsCast<JSDOMGlobalObject*>(globalObject))->storedPrototype()));
150 }
151
152 void callFunctionWithCurrentArguments(JSC::ExecState&, JSC::JSObject& thisObject, JSC::JSFunction&);
153
154 template<typename JSClass> inline JSC::EncodedJSValue createJSBuiltin(JSC::ExecState& state, JSC::JSFunction& initializeFunction, JSDOMGlobalObject& globalObject)
155 {
156     JSC::JSObject* object = JSClass::create(getDOMStructure<JSClass>(globalObject.vm(), globalObject), &globalObject);
157     callFunctionWithCurrentArguments(state, *object, initializeFunction);
158     return JSC::JSValue::encode(object);
159 }
160
161 inline JSC::WeakHandleOwner* wrapperOwner(DOMWrapperWorld& world, JSC::ArrayBuffer*)
162 {
163     return static_cast<WebCoreTypedArrayController*>(world.vm().m_typedArrayController.get())->wrapperOwner();
164 }
165
166 inline JSDOMObject* getInlineCachedWrapper(DOMWrapperWorld&, void*) { return nullptr; }
167 inline bool setInlineCachedWrapper(DOMWrapperWorld&, void*, JSDOMObject*, JSC::WeakHandleOwner*) { return false; }
168 inline bool clearInlineCachedWrapper(DOMWrapperWorld&, void*, JSDOMObject*) { return false; }
169
170 inline JSDOMObject* getInlineCachedWrapper(DOMWrapperWorld& world, ScriptWrappable* domObject)
171 {
172     if (!world.isNormal())
173         return nullptr;
174     return domObject->wrapper();
175 }
176
177 inline JSC::JSArrayBuffer* getInlineCachedWrapper(DOMWrapperWorld& world, JSC::ArrayBuffer* buffer)
178 {
179     if (!world.isNormal())
180         return nullptr;
181     return buffer->m_wrapper.get();
182 }
183
184 inline bool setInlineCachedWrapper(DOMWrapperWorld& world, ScriptWrappable* domObject, JSDOMObject* wrapper, JSC::WeakHandleOwner* wrapperOwner)
185 {
186     if (!world.isNormal())
187         return false;
188     domObject->setWrapper(wrapper, wrapperOwner, &world);
189     return true;
190 }
191
192 inline bool setInlineCachedWrapper(DOMWrapperWorld& world, JSC::ArrayBuffer* domObject, JSC::JSArrayBuffer* wrapper, JSC::WeakHandleOwner* wrapperOwner)
193 {
194     if (!world.isNormal())
195         return false;
196     domObject->m_wrapper = JSC::Weak<JSC::JSArrayBuffer>(wrapper, wrapperOwner, &world);
197     return true;
198 }
199
200 inline bool clearInlineCachedWrapper(DOMWrapperWorld& world, ScriptWrappable* domObject, JSDOMObject* wrapper)
201 {
202     if (!world.isNormal())
203         return false;
204     domObject->clearWrapper(wrapper);
205     return true;
206 }
207
208 inline bool clearInlineCachedWrapper(DOMWrapperWorld& world, JSC::ArrayBuffer* domObject, JSC::JSArrayBuffer* wrapper)
209 {
210     if (!world.isNormal())
211         return false;
212     weakClear(domObject->m_wrapper, wrapper);
213     return true;
214 }
215
216 template<typename DOMClass> inline JSC::JSObject* getCachedWrapper(DOMWrapperWorld& world, DOMClass* domObject)
217 {
218     if (JSC::JSObject* wrapper = getInlineCachedWrapper(world, domObject))
219         return wrapper;
220     return world.m_wrappers.get(domObject);
221 }
222
223 template<typename DOMClass, typename WrapperClass> inline void cacheWrapper(DOMWrapperWorld& world, DOMClass* domObject, WrapperClass* wrapper)
224 {
225     JSC::WeakHandleOwner* owner = wrapperOwner(world, domObject);
226     if (setInlineCachedWrapper(world, domObject, wrapper, owner))
227         return;
228     weakAdd(world.m_wrappers, (void*)domObject, JSC::Weak<JSC::JSObject>(wrapper, owner, &world));
229 }
230
231 template<typename DOMClass, typename WrapperClass> inline void uncacheWrapper(DOMWrapperWorld& world, DOMClass* domObject, WrapperClass* wrapper)
232 {
233     if (clearInlineCachedWrapper(world, domObject, wrapper))
234         return;
235     weakRemove(world.m_wrappers, (void*)domObject, wrapper);
236 }
237
238 #define CREATE_DOM_WRAPPER(globalObject, className, object) createWrapper<JS##className>(globalObject, static_cast<className*>(object))
239 template<typename WrapperClass, typename DOMClass> inline JSDOMObject* createWrapper(JSDOMGlobalObject* globalObject, DOMClass* node)
240 {
241     ASSERT(node);
242     ASSERT(!getCachedWrapper(globalObject->world(), node));
243     WrapperClass* wrapper = WrapperClass::create(getDOMStructure<WrapperClass>(globalObject->vm(), *globalObject), globalObject, Ref<DOMClass>(*node));
244     cacheWrapper(globalObject->world(), node, wrapper);
245     return wrapper;
246 }
247
248 template<typename WrapperClass, typename DOMClass> inline JSC::JSValue wrap(JSDOMGlobalObject* globalObject, DOMClass* domObject)
249 {
250     if (!domObject)
251         return JSC::jsNull();
252     if (JSC::JSObject* wrapper = getCachedWrapper(globalObject->world(), domObject))
253         return wrapper;
254     return createWrapper<WrapperClass>(globalObject, domObject);
255 }
256
257 template<typename WrapperClass, typename DOMClass> inline JSC::JSValue getExistingWrapper(JSDOMGlobalObject* globalObject, DOMClass* domObject)
258 {
259     ASSERT(domObject);
260     return getCachedWrapper(globalObject->world(), domObject);
261 }
262
263 template<typename WrapperClass, typename DOMClass> inline JSC::JSValue createNewWrapper(JSDOMGlobalObject* globalObject, DOMClass* domObject)
264 {
265     ASSERT(domObject);
266     ASSERT(!getCachedWrapper(globalObject->world(), domObject));
267     return createWrapper<WrapperClass>(globalObject, domObject);
268 }
269
270 void addImpureProperty(const AtomicString&);
271
272 const JSC::HashTable& getHashTableForGlobalData(JSC::VM&, const JSC::HashTable& staticTable);
273
274 WEBCORE_EXPORT void reportException(JSC::ExecState*, JSC::JSValue exception, CachedScript* = nullptr);
275 WEBCORE_EXPORT void reportException(JSC::ExecState*, JSC::Exception*, CachedScript* = nullptr);
276 void reportCurrentException(JSC::ExecState*);
277
278 JSC::JSValue createDOMException(JSC::ExecState*, ExceptionCode);
279 // Convert a DOM implementation exception code into a JavaScript exception in the execution state.
280 WEBCORE_EXPORT void setDOMException(JSC::ExecState*, ExceptionCode);
281
282 JSC::JSValue jsString(JSC::ExecState*, const URL&); // empty if the URL is null
283
284 JSC::JSValue jsStringOrNull(JSC::ExecState*, const String&); // null if the string is null
285 JSC::JSValue jsStringOrNull(JSC::ExecState*, const URL&); // null if the URL is null
286
287 JSC::JSValue jsStringOrUndefined(JSC::ExecState*, const String&); // undefined if the string is null
288 JSC::JSValue jsStringOrUndefined(JSC::ExecState*, const URL&); // undefined if the URL is null
289
290 // See JavaScriptCore for explanation: Should be used for any string that is already owned by another
291 // object, to let the engine know that collecting the JSString wrapper is unlikely to save memory.
292 JSC::JSValue jsOwnedStringOrNull(JSC::ExecState*, const String&);
293
294 String propertyNameToString(JSC::PropertyName);
295
296 AtomicString propertyNameToAtomicString(JSC::PropertyName);
297
298 String valueToStringWithNullCheck(JSC::ExecState*, JSC::JSValue); // null if the value is null
299 String valueToStringWithUndefinedOrNullCheck(JSC::ExecState*, JSC::JSValue); // null if the value is null or undefined
300
301 inline int32_t finiteInt32Value(JSC::JSValue value, JSC::ExecState* exec, bool& okay)
302 {
303     double number = value.toNumber(exec);
304     okay = std::isfinite(number);
305     return JSC::toInt32(number);
306 }
307
308 enum IntegerConversionConfiguration {
309     NormalConversion,
310     EnforceRange,
311     // FIXME: Implement Clamp
312 };
313
314 WEBCORE_EXPORT int32_t toInt32EnforceRange(JSC::ExecState*, JSC::JSValue);
315 WEBCORE_EXPORT uint32_t toUInt32EnforceRange(JSC::ExecState*, JSC::JSValue);
316
317 WEBCORE_EXPORT int8_t toInt8(JSC::ExecState*, JSC::JSValue, IntegerConversionConfiguration);
318 WEBCORE_EXPORT uint8_t toUInt8(JSC::ExecState*, JSC::JSValue, IntegerConversionConfiguration);
319
320 WEBCORE_EXPORT int16_t toInt16(JSC::ExecState*, JSC::JSValue, IntegerConversionConfiguration);
321 WEBCORE_EXPORT uint16_t toUInt16(JSC::ExecState*, JSC::JSValue, IntegerConversionConfiguration);
322
323 /*
324     Convert a value to an integer as per <http://www.w3.org/TR/WebIDL/>.
325     The conversion fails if the value cannot be converted to a number or,
326     if EnforceRange is specified, the value is outside the range of the
327     destination integer type.
328 */
329 inline int32_t toInt32(JSC::ExecState* exec, JSC::JSValue value, IntegerConversionConfiguration configuration)
330 {
331     if (configuration == EnforceRange)
332         return toInt32EnforceRange(exec, value);
333     return value.toInt32(exec);
334 }
335
336 inline uint32_t toUInt32(JSC::ExecState* exec, JSC::JSValue value, IntegerConversionConfiguration configuration)
337 {
338     if (configuration == EnforceRange)
339         return toUInt32EnforceRange(exec, value);
340     return value.toUInt32(exec);
341 }
342
343 WEBCORE_EXPORT int64_t toInt64(JSC::ExecState*, JSC::JSValue, IntegerConversionConfiguration);
344 WEBCORE_EXPORT uint64_t toUInt64(JSC::ExecState*, JSC::JSValue, IntegerConversionConfiguration);
345
346 // Returns a Date instnace for the specified value, or NaN if the date is not a number.
347 JSC::JSValue jsDateOrNaN(JSC::ExecState*, double);
348 // Returns a Date instance for the specified value, or null if the value is NaN or infinity.
349 JSC::JSValue jsDateOrNull(JSC::ExecState*, double);
350 // NaN if the value can't be converted to a date.
351 double valueToDate(JSC::ExecState*, JSC::JSValue);
352
353 // Validates that the passed object is a sequence type per section 4.1.13 of the WebIDL spec.
354 inline JSC::JSObject* toJSSequence(JSC::ExecState* exec, JSC::JSValue value, unsigned& length)
355 {
356     JSC::JSObject* object = value.getObject();
357     if (!object) {
358         throwSequenceTypeError(*exec);
359         return nullptr;
360     }
361
362     JSC::JSValue lengthValue = object->get(exec, exec->propertyNames().length);
363     if (exec->hadException())
364         return nullptr;
365
366     if (lengthValue.isUndefinedOrNull()) {
367         throwSequenceTypeError(*exec);
368         return nullptr;
369     }
370
371     length = lengthValue.toUInt32(exec);
372     if (exec->hadException())
373         return nullptr;
374
375     return object;
376 }
377
378 inline JSC::JSValue toJS(JSC::ExecState* exec, JSDOMGlobalObject* globalObject, JSC::ArrayBuffer* buffer)
379 {
380     if (!buffer)
381         return JSC::jsNull();
382     if (JSC::JSValue result = getExistingWrapper<JSC::JSArrayBuffer>(globalObject, buffer))
383         return result;
384     buffer->ref();
385     JSC::JSArrayBuffer* wrapper = JSC::JSArrayBuffer::create(exec->vm(), globalObject->arrayBufferStructure(), buffer);
386     cacheWrapper(globalObject->world(), buffer, wrapper);
387     return wrapper;
388 }
389
390 inline JSC::JSValue toJS(JSC::ExecState* exec, JSDOMGlobalObject* globalObject, JSC::ArrayBufferView* view)
391 {
392     if (!view)
393         return JSC::jsNull();
394     return view->wrap(exec, globalObject);
395 }
396
397 template<typename T> inline JSC::JSValue toJS(JSC::ExecState* exec, JSDOMGlobalObject* globalObject, RefPtr<T> ptr)
398 {
399     return toJS(exec, globalObject, ptr.get());
400 }
401
402 template<typename T> inline JSC::JSValue toJS(JSC::ExecState* exec, JSDOMGlobalObject* globalObject, PassRefPtr<T> ptr)
403 {
404     return toJS(exec, globalObject, ptr.get());
405 }
406
407 template<typename T> inline JSC::JSValue toJS(JSC::ExecState* exec, JSDOMGlobalObject* globalObject, const Vector<T>& vector)
408 {
409     JSC::JSArray* array = constructEmptyArray(exec, nullptr, vector.size());
410     for (size_t i = 0; i < vector.size(); ++i)
411         array->putDirectIndex(exec, i, toJS(exec, globalObject, vector[i]));
412     return array;
413 }
414
415 template<typename T> inline JSC::JSValue toJS(JSC::ExecState* exec, JSDOMGlobalObject* globalObject, const Vector<RefPtr<T>>& vector)
416 {
417     JSC::JSArray* array = constructEmptyArray(exec, nullptr, vector.size());
418     for (size_t i = 0; i < vector.size(); ++i)
419         array->putDirectIndex(exec, i, toJS(exec, globalObject, vector[i].get()));
420     return array;
421 }
422
423 inline JSC::JSValue toJS(JSC::ExecState* exec, JSDOMGlobalObject*, const String& value)
424 {
425     return jsStringOrNull(exec, value);
426 }
427
428 inline JSC::JSValue toJSIterator(JSC::ExecState& state, JSDOMGlobalObject&, JSC::JSValue value)
429 {
430     return createIteratorResultObject(&state, value, false);
431 }
432
433 template<typename T> inline JSC::JSValue toJSIterator(JSC::ExecState& state, JSDOMGlobalObject& globalObject, const T& value)
434 {
435     return createIteratorResultObject(&state, toJS(&state, &globalObject, value), false);
436 }
437
438 inline JSC::JSValue toJSIteratorEnd(JSC::ExecState& state)
439 {
440     return createIteratorResultObject(&state, JSC::jsUndefined(), true);
441 }
442
443 template<typename T> struct JSValueTraits {
444     static JSC::JSValue arrayJSValue(JSC::ExecState* exec, JSDOMGlobalObject* globalObject, const T& value)
445     {
446         return toJS(exec, globalObject, WTF::getPtr(value));
447     }
448 };
449
450 template<> struct JSValueTraits<String> {
451     static JSC::JSValue arrayJSValue(JSC::ExecState* exec, JSDOMGlobalObject*, const String& value)
452     {
453         return JSC::jsStringWithCache(exec, value);
454     }
455 };
456
457 template<> struct JSValueTraits<double> {
458     static JSC::JSValue arrayJSValue(JSC::ExecState*, JSDOMGlobalObject*, const double& value)
459     {
460         return JSC::jsNumber(value);
461     }
462 };
463
464 template<> struct JSValueTraits<float> {
465     static JSC::JSValue arrayJSValue(JSC::ExecState*, JSDOMGlobalObject*, const float& value)
466     {
467         return JSC::jsNumber(value);
468     }
469 };
470
471 template<> struct JSValueTraits<unsigned long> {
472     static JSC::JSValue arrayJSValue(JSC::ExecState*, JSDOMGlobalObject*, const unsigned long& value)
473     {
474         return JSC::jsNumber(value);
475     }
476 };
477
478 template<typename T, size_t inlineCapacity> JSC::JSValue jsArray(JSC::ExecState* exec, JSDOMGlobalObject* globalObject, const Vector<T, inlineCapacity>& vector)
479 {
480     JSC::MarkedArgumentBuffer list;
481     for (auto& element : vector)
482         list.append(JSValueTraits<T>::arrayJSValue(exec, globalObject, element));
483     return JSC::constructArray(exec, nullptr, globalObject, list);
484 }
485
486 template<typename T, size_t inlineCapacity> inline JSC::JSValue jsArray(JSC::ExecState* exec, JSDOMGlobalObject* globalObject, const Vector<T, inlineCapacity>* vector)
487 {
488     if (!vector)
489         return JSC::constructEmptyArray(exec, nullptr, globalObject, 0);
490     return jsArray(exec, globalObject, *vector);
491 }
492
493 WEBCORE_EXPORT JSC::JSValue jsArray(JSC::ExecState*, JSDOMGlobalObject*, PassRefPtr<DOMStringList>);
494
495 inline PassRefPtr<JSC::ArrayBufferView> toArrayBufferView(JSC::JSValue value)
496 {
497     JSC::JSArrayBufferView* wrapper = JSC::jsDynamicCast<JSC::JSArrayBufferView*>(value);
498     if (!wrapper)
499         return nullptr;
500     return wrapper->impl();
501 }
502
503 inline RefPtr<JSC::Int8Array> toInt8Array(JSC::JSValue value) { return JSC::toNativeTypedView<JSC::Int8Adaptor>(value); }
504 inline RefPtr<JSC::Int16Array> toInt16Array(JSC::JSValue value) { return JSC::toNativeTypedView<JSC::Int16Adaptor>(value); }
505 inline RefPtr<JSC::Int32Array> toInt32Array(JSC::JSValue value) { return JSC::toNativeTypedView<JSC::Int32Adaptor>(value); }
506 inline RefPtr<JSC::Uint8Array> toUint8Array(JSC::JSValue value) { return JSC::toNativeTypedView<JSC::Uint8Adaptor>(value); }
507 inline RefPtr<JSC::Uint8ClampedArray> toUint8ClampedArray(JSC::JSValue value) { return JSC::toNativeTypedView<JSC::Uint8ClampedAdaptor>(value); }
508 inline RefPtr<JSC::Uint16Array> toUint16Array(JSC::JSValue value) { return JSC::toNativeTypedView<JSC::Uint16Adaptor>(value); }
509 inline RefPtr<JSC::Uint32Array> toUint32Array(JSC::JSValue value) { return JSC::toNativeTypedView<JSC::Uint32Adaptor>(value); }
510 inline RefPtr<JSC::Float32Array> toFloat32Array(JSC::JSValue value) { return JSC::toNativeTypedView<JSC::Float32Adaptor>(value); }
511 inline RefPtr<JSC::Float64Array> toFloat64Array(JSC::JSValue value) { return JSC::toNativeTypedView<JSC::Float64Adaptor>(value); }
512
513 template<typename T> struct NativeValueTraits;
514
515 template<> struct NativeValueTraits<String> {
516     static inline bool nativeValue(JSC::ExecState* exec, JSC::JSValue jsValue, String& indexedValue)
517     {
518         indexedValue = jsValue.toString(exec)->value(exec);
519         return true;
520     }
521 };
522
523 template<> struct NativeValueTraits<unsigned> {
524     static inline bool nativeValue(JSC::ExecState* exec, JSC::JSValue jsValue, unsigned& indexedValue)
525     {
526         if (!jsValue.isNumber())
527             return false;
528
529         indexedValue = jsValue.toUInt32(exec);
530         if (exec->hadException())
531             return false;
532
533         return true;
534     }
535 };
536
537 template<> struct NativeValueTraits<float> {
538     static inline bool nativeValue(JSC::ExecState* exec, JSC::JSValue jsValue, float& indexedValue)
539     {
540         indexedValue = jsValue.toFloat(exec);
541         return !exec->hadException();
542     }
543 };
544
545 template<> struct NativeValueTraits<double> {
546     static inline bool nativeValue(JSC::ExecState* exec, JSC::JSValue jsValue, double& indexedValue)
547     {
548         indexedValue = jsValue.toNumber(exec);
549         return !exec->hadException();
550     }
551 };
552
553 template<typename T, typename JST> Vector<RefPtr<T>> toRefPtrNativeArray(JSC::ExecState* exec, JSC::JSValue value, T* (*toT)(JSC::JSValue value))
554 {
555     if (!isJSArray(value))
556         return Vector<RefPtr<T>>();
557
558     Vector<RefPtr<T>> result;
559     JSC::JSArray* array = asArray(value);
560     size_t size = array->length();
561     result.reserveInitialCapacity(size);
562     for (size_t i = 0; i < size; ++i) {
563         JSC::JSValue element = array->getIndex(exec, i);
564         if (element.inherits(JST::info()))
565             result.uncheckedAppend((*toT)(element));
566         else {
567             throwArrayElementTypeError(*exec);
568             return Vector<RefPtr<T>>();
569         }
570     }
571     return result;
572 }
573
574 template<typename T> Vector<T> toNativeArray(JSC::ExecState* exec, JSC::JSValue value)
575 {
576     JSC::JSObject* object = value.getObject();
577     if (!object)
578         return Vector<T>();
579
580     unsigned length = 0;
581     if (isJSArray(value)) {
582         JSC::JSArray* array = asArray(value);
583         length = array->length();
584     } else
585         toJSSequence(exec, value, length);
586
587     Vector<T> result;
588     result.reserveInitialCapacity(length);
589     typedef NativeValueTraits<T> TraitsType;
590
591     for (unsigned i = 0; i < length; ++i) {
592         T indexValue;
593         if (!TraitsType::nativeValue(exec, object->get(exec, i), indexValue))
594             return Vector<T>();
595         result.uncheckedAppend(indexValue);
596     }
597     return result;
598 }
599
600 template<typename T> Vector<T> toNativeArguments(JSC::ExecState* exec, size_t startIndex = 0)
601 {
602     size_t length = exec->argumentCount();
603     ASSERT(startIndex <= length);
604
605     Vector<T> result;
606     result.reserveInitialCapacity(length - startIndex);
607     typedef NativeValueTraits<T> TraitsType;
608
609     for (size_t i = startIndex; i < length; ++i) {
610         T indexValue;
611         if (!TraitsType::nativeValue(exec, exec->argument(i), indexValue))
612             return Vector<T>();
613         result.uncheckedAppend(indexValue);
614     }
615     return result;
616 }
617
618 bool shouldAllowAccessToNode(JSC::ExecState*, Node*);
619 bool shouldAllowAccessToFrame(JSC::ExecState*, Frame*);
620 bool shouldAllowAccessToFrame(JSC::ExecState*, Frame*, String& message);
621 bool shouldAllowAccessToDOMWindow(JSC::ExecState*, DOMWindow&, String& message);
622
623 void printErrorMessageForFrame(Frame*, const String& message);
624 JSC::EncodedJSValue objectToStringFunctionGetter(JSC::ExecState*, JSC::JSObject*, JSC::EncodedJSValue, JSC::PropertyName);
625
626 inline String propertyNameToString(JSC::PropertyName propertyName)
627 {
628     ASSERT(!propertyName.isSymbol());
629     return propertyName.uid() ? propertyName.uid() : propertyName.publicName();
630 }
631
632 inline AtomicString propertyNameToAtomicString(JSC::PropertyName propertyName)
633 {
634     return AtomicString(propertyName.uid() ? propertyName.uid() : propertyName.publicName());
635 }
636
637 template<typename DOMClass> inline const JSC::HashTableValue* getStaticValueSlotEntryWithoutCaching(JSC::ExecState* exec, JSC::PropertyName propertyName)
638 {
639     const JSC::HashTable* table = DOMClass::info()->staticPropHashTable;
640     if (!table)
641         return getStaticValueSlotEntryWithoutCaching<typename DOMClass::Base>(exec, propertyName);
642     const JSC::HashTableValue* entry = table->entry(propertyName);
643     if (!entry) // not found, forward to parent
644         return getStaticValueSlotEntryWithoutCaching<typename DOMClass::Base>(exec, propertyName);
645     return entry;
646 }
647
648 template<> inline const JSC::HashTableValue* getStaticValueSlotEntryWithoutCaching<JSDOMObject>(JSC::ExecState*, JSC::PropertyName)
649 {
650     return nullptr;
651 }
652
653 template<JSC::NativeFunction nativeFunction, int length>
654 JSC::EncodedJSValue nonCachingStaticFunctionGetter(JSC::ExecState* exec, JSC::JSObject*, JSC::EncodedJSValue, JSC::PropertyName propertyName)
655 {
656     return JSC::JSValue::encode(JSC::JSFunction::create(exec->vm(), exec->lexicalGlobalObject(), length, propertyName.publicName(), nativeFunction));
657 }
658
659 enum SecurityReportingOption {
660     DoNotReportSecurityError,
661     ReportSecurityError,
662 };
663
664 class BindingSecurity {
665 public:
666     static bool shouldAllowAccessToNode(JSC::ExecState*, Node*);
667     static bool shouldAllowAccessToDOMWindow(JSC::ExecState*, DOMWindow&, SecurityReportingOption = ReportSecurityError);
668     static bool shouldAllowAccessToFrame(JSC::ExecState*, Frame*, SecurityReportingOption = ReportSecurityError);
669 };
670
671 inline JSC::JSValue getPropertyFromObject(JSC::ExecState& exec, JSC::JSObject& object, const char* identifier)
672 {
673     return object.get(&exec, JSC::Identifier::fromString(&exec, identifier));
674 }
675
676 inline void setPropertyToObject(JSC::ExecState& exec, JSC::JSObject& object, const char* name, JSC::JSValue value)
677 {
678     JSC::PutPropertySlot propertySlot(&object);
679     JSC::JSObject::put(&object, &exec, JSC::Identifier::fromString(&exec, name), value, propertySlot);
680 }
681     
682 } // namespace WebCore
683
684 #endif // JSDOMBinding_h