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