/* * Copyright (C) 1999-2001 Harri Porten (porten@kde.org) * Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009, 2013 Apple Inc. All rights reserved. * Copyright (C) 2007 Samuel Weinig * Copyright (C) 2009 Google, Inc. All rights reserved. * Copyright (C) 2012 Ericsson AB. All rights reserved. * Copyright (C) 2013 Michael Pruett * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef JSDOMBinding_h #define JSDOMBinding_h #include "JSDOMGlobalObject.h" #include "JSDOMWrapper.h" #include "DOMWrapperWorld.h" #include "ScriptWrappable.h" #include "ScriptWrappableInlines.h" #include "WebCoreTypedArrayController.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include // FIXME: We could make this file a lot easier to read by putting all function declarations at the top, // and function definitions below, even for template and inline functions. namespace JSC { class HashEntry; class JSFunction; } namespace WebCore { class CachedScript; class DOMStringList; class DOMWindow; class Frame; class URL; class Node; struct ExceptionCodeWithMessage; struct ExceptionDetails { String message; int lineNumber { 0 }; int columnNumber { 0 }; String sourceURL; }; typedef int ExceptionCode; DOMWindow& callerDOMWindow(JSC::ExecState*); DOMWindow& activeDOMWindow(JSC::ExecState*); DOMWindow& firstDOMWindow(JSC::ExecState*); WEBCORE_EXPORT JSC::EncodedJSValue reportDeprecatedGetterError(JSC::ExecState&, const char* interfaceName, const char* attributeName); WEBCORE_EXPORT void reportDeprecatedSetterError(JSC::ExecState&, const char* interfaceName, const char* attributeName); void throwArrayElementTypeError(JSC::ExecState&); void throwAttributeTypeError(JSC::ExecState&, const char* interfaceName, const char* attributeName, const char* expectedType); WEBCORE_EXPORT void throwSequenceTypeError(JSC::ExecState&); WEBCORE_EXPORT void throwSetterTypeError(JSC::ExecState&, const char* interfaceName, const char* attributeName); WEBCORE_EXPORT JSC::EncodedJSValue throwArgumentMustBeEnumError(JSC::ExecState&, unsigned argumentIndex, const char* argumentName, const char* functionInterfaceName, const char* functionName, const char* expectedValues); JSC::EncodedJSValue throwArgumentMustBeFunctionError(JSC::ExecState&, unsigned argumentIndex, const char* argumentName, const char* functionInterfaceName, const char* functionName); JSC::EncodedJSValue throwArgumentTypeError(JSC::ExecState&, unsigned argumentIndex, const char* argumentName, const char* functionInterfaceName, const char* functionName, const char* expectedType); JSC::EncodedJSValue throwConstructorDocumentUnavailableError(JSC::ExecState&, const char* interfaceName); WEBCORE_EXPORT JSC::EncodedJSValue throwGetterTypeError(JSC::ExecState&, const char* interfaceName, const char* attributeName); WEBCORE_EXPORT JSC::EncodedJSValue throwThisTypeError(JSC::ExecState&, const char* interfaceName, const char* functionName); // Base class for all constructor objects in the JSC bindings. class DOMConstructorObject : public JSDOMObject { public: typedef JSDOMObject Base; static const unsigned StructureFlags = Base::StructureFlags | JSC::ImplementsHasInstance | JSC::ImplementsDefaultHasInstance | JSC::TypeOfShouldCallGetCallData; static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype) { return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), info()); } protected: DOMConstructorObject(JSC::Structure* structure, JSDOMGlobalObject& globalObject) : JSDOMObject(structure, globalObject) { } static String className(const JSObject*) { return ASCIILiteral("Function"); } static JSC::CallType getCallData(JSCell*, JSC::CallData&); }; class DOMConstructorJSBuiltinObject : public DOMConstructorObject { public: typedef DOMConstructorObject Base; protected: DOMConstructorJSBuiltinObject(JSC::Structure* structure, JSDOMGlobalObject& globalObject) : DOMConstructorObject(structure, globalObject) { } static void visitChildren(JSC::JSCell*, JSC::SlotVisitor&); JSC::JSFunction* initializeFunction() { return m_initializeFunction.get(); } void setInitializeFunction(JSC::VM& vm, JSC::JSFunction& function) { m_initializeFunction.set(vm, this, &function); } private: JSC::WriteBarrier m_initializeFunction; }; WEBCORE_EXPORT JSC::Structure* getCachedDOMStructure(JSDOMGlobalObject&, const JSC::ClassInfo*); WEBCORE_EXPORT JSC::Structure* cacheDOMStructure(JSDOMGlobalObject&, JSC::Structure*, const JSC::ClassInfo*); inline JSDOMGlobalObject* deprecatedGlobalObjectForPrototype(JSC::ExecState* exec) { // FIXME: Callers to this function should be using the global object // from which the object is being created, instead of assuming the lexical one. // e.g. subframe.document.body should use the subframe's global object, not the lexical one. return JSC::jsCast(exec->lexicalGlobalObject()); } template inline JSC::Structure* getDOMStructure(JSC::VM& vm, JSDOMGlobalObject& globalObject) { if (JSC::Structure* structure = getCachedDOMStructure(globalObject, WrapperClass::info())) return structure; return cacheDOMStructure(globalObject, WrapperClass::createStructure(vm, &globalObject, WrapperClass::createPrototype(vm, &globalObject)), WrapperClass::info()); } template inline JSC::Structure* deprecatedGetDOMStructure(JSC::ExecState* exec) { // FIXME: This function is wrong. It uses the wrong global object for creating the prototype structure. return getDOMStructure(exec->vm(), *deprecatedGlobalObjectForPrototype(exec)); } template inline JSC::JSObject* getDOMPrototype(JSC::VM& vm, JSC::JSGlobalObject* globalObject) { return JSC::jsCast(asObject(getDOMStructure(vm, *JSC::jsCast(globalObject))->storedPrototype())); } void callFunctionWithCurrentArguments(JSC::ExecState&, JSC::JSObject& thisObject, JSC::JSFunction&); template inline JSC::EncodedJSValue createJSBuiltin(JSC::ExecState& state, JSC::JSFunction& initializeFunction, JSDOMGlobalObject& globalObject) { JSC::JSObject* object = JSClass::create(getDOMStructure(globalObject.vm(), globalObject), &globalObject); callFunctionWithCurrentArguments(state, *object, initializeFunction); return JSC::JSValue::encode(object); } inline JSC::WeakHandleOwner* wrapperOwner(DOMWrapperWorld& world, JSC::ArrayBuffer*) { return static_cast(world.vm().m_typedArrayController.get())->wrapperOwner(); } inline void* wrapperKey(JSC::ArrayBuffer* domObject) { return domObject; } inline JSDOMObject* getInlineCachedWrapper(DOMWrapperWorld&, void*) { return nullptr; } inline bool setInlineCachedWrapper(DOMWrapperWorld&, void*, JSDOMObject*, JSC::WeakHandleOwner*) { return false; } inline bool clearInlineCachedWrapper(DOMWrapperWorld&, void*, JSDOMObject*) { return false; } inline JSDOMObject* getInlineCachedWrapper(DOMWrapperWorld& world, ScriptWrappable* domObject) { if (!world.isNormal()) return nullptr; return domObject->wrapper(); } inline JSC::JSArrayBuffer* getInlineCachedWrapper(DOMWrapperWorld& world, JSC::ArrayBuffer* buffer) { if (!world.isNormal()) return nullptr; return buffer->m_wrapper.get(); } inline bool setInlineCachedWrapper(DOMWrapperWorld& world, ScriptWrappable* domObject, JSDOMObject* wrapper, JSC::WeakHandleOwner* wrapperOwner) { if (!world.isNormal()) return false; domObject->setWrapper(wrapper, wrapperOwner, &world); return true; } inline bool setInlineCachedWrapper(DOMWrapperWorld& world, JSC::ArrayBuffer* domObject, JSC::JSArrayBuffer* wrapper, JSC::WeakHandleOwner* wrapperOwner) { if (!world.isNormal()) return false; domObject->m_wrapper = JSC::Weak(wrapper, wrapperOwner, &world); return true; } inline bool clearInlineCachedWrapper(DOMWrapperWorld& world, ScriptWrappable* domObject, JSDOMObject* wrapper) { if (!world.isNormal()) return false; domObject->clearWrapper(wrapper); return true; } inline bool clearInlineCachedWrapper(DOMWrapperWorld& world, JSC::ArrayBuffer* domObject, JSC::JSArrayBuffer* wrapper) { if (!world.isNormal()) return false; weakClear(domObject->m_wrapper, wrapper); return true; } template inline JSC::JSObject* getCachedWrapper(DOMWrapperWorld& world, DOMClass* domObject) { if (JSC::JSObject* wrapper = getInlineCachedWrapper(world, domObject)) return wrapper; return world.m_wrappers.get(wrapperKey(domObject)); } template inline void cacheWrapper(DOMWrapperWorld& world, DOMClass* domObject, WrapperClass* wrapper) { JSC::WeakHandleOwner* owner = wrapperOwner(world, domObject); if (setInlineCachedWrapper(world, domObject, wrapper, owner)) return; weakAdd(world.m_wrappers, wrapperKey(domObject), JSC::Weak(wrapper, owner, &world)); } template inline void uncacheWrapper(DOMWrapperWorld& world, DOMClass* domObject, WrapperClass* wrapper) { if (clearInlineCachedWrapper(world, domObject, wrapper)) return; weakRemove(world.m_wrappers, wrapperKey(domObject), wrapper); } #define CREATE_DOM_WRAPPER(globalObject, className, object) createWrapper(globalObject, static_cast(object)) template inline JSDOMObject* createWrapper(JSDOMGlobalObject* globalObject, DOMClass* node) { ASSERT(node); ASSERT(!getCachedWrapper(globalObject->world(), node)); WrapperClass* wrapper = WrapperClass::create(getDOMStructure(globalObject->vm(), *globalObject), globalObject, Ref(*node)); cacheWrapper(globalObject->world(), node, wrapper); return wrapper; } template inline JSC::JSValue wrap(JSDOMGlobalObject* globalObject, DOMClass* domObject) { if (!domObject) return JSC::jsNull(); if (JSC::JSObject* wrapper = getCachedWrapper(globalObject->world(), domObject)) return wrapper; return createWrapper(globalObject, domObject); } template inline JSC::JSValue getExistingWrapper(JSDOMGlobalObject* globalObject, DOMClass* domObject) { ASSERT(domObject); return getCachedWrapper(globalObject->world(), domObject); } template inline JSC::JSValue createNewWrapper(JSDOMGlobalObject* globalObject, DOMClass* domObject) { ASSERT(domObject); ASSERT(!getCachedWrapper(globalObject->world(), domObject)); return createWrapper(globalObject, domObject); } void addImpureProperty(const AtomicString&); const JSC::HashTable& getHashTableForGlobalData(JSC::VM&, const JSC::HashTable& staticTable); WEBCORE_EXPORT void reportException(JSC::ExecState*, JSC::JSValue exception, CachedScript* = nullptr); WEBCORE_EXPORT void reportException(JSC::ExecState*, JSC::Exception*, CachedScript* = nullptr, ExceptionDetails* = nullptr); void reportCurrentException(JSC::ExecState*); JSC::JSValue createDOMException(JSC::ExecState*, ExceptionCode); // Convert a DOM implementation exception code into a JavaScript exception in the execution state. WEBCORE_EXPORT void setDOMException(JSC::ExecState*, ExceptionCode); void setDOMException(JSC::ExecState*, const ExceptionCodeWithMessage&); JSC::JSValue jsString(JSC::ExecState*, const URL&); // empty if the URL is null JSC::JSValue jsStringOrNull(JSC::ExecState*, const String&); // null if the string is null JSC::JSValue jsStringOrNull(JSC::ExecState*, const URL&); // null if the URL is null JSC::JSValue jsStringOrUndefined(JSC::ExecState*, const String&); // undefined if the string is null JSC::JSValue jsStringOrUndefined(JSC::ExecState*, const URL&); // undefined if the URL is null // See JavaScriptCore for explanation: Should be used for any string that is already owned by another // object, to let the engine know that collecting the JSString wrapper is unlikely to save memory. JSC::JSValue jsOwnedStringOrNull(JSC::ExecState*, const String&); String propertyNameToString(JSC::PropertyName); AtomicString propertyNameToAtomicString(JSC::PropertyName); String valueToStringWithNullCheck(JSC::ExecState*, JSC::JSValue); // null if the value is null String valueToStringWithUndefinedOrNullCheck(JSC::ExecState*, JSC::JSValue); // null if the value is null or undefined template JSC::JSValue toNullableJSNumber(Optional); // null if the optional is null inline int32_t finiteInt32Value(JSC::JSValue value, JSC::ExecState* exec, bool& okay) { double number = value.toNumber(exec); okay = std::isfinite(number); return JSC::toInt32(number); } enum IntegerConversionConfiguration { NormalConversion, EnforceRange, // FIXME: Implement Clamp }; WEBCORE_EXPORT int32_t toInt32EnforceRange(JSC::ExecState*, JSC::JSValue); WEBCORE_EXPORT uint32_t toUInt32EnforceRange(JSC::ExecState*, JSC::JSValue); WEBCORE_EXPORT int8_t toInt8(JSC::ExecState*, JSC::JSValue, IntegerConversionConfiguration); WEBCORE_EXPORT uint8_t toUInt8(JSC::ExecState*, JSC::JSValue, IntegerConversionConfiguration); WEBCORE_EXPORT int16_t toInt16(JSC::ExecState*, JSC::JSValue, IntegerConversionConfiguration); WEBCORE_EXPORT uint16_t toUInt16(JSC::ExecState*, JSC::JSValue, IntegerConversionConfiguration); /* Convert a value to an integer as per . The conversion fails if the value cannot be converted to a number or, if EnforceRange is specified, the value is outside the range of the destination integer type. */ inline int32_t toInt32(JSC::ExecState* exec, JSC::JSValue value, IntegerConversionConfiguration configuration) { if (configuration == EnforceRange) return toInt32EnforceRange(exec, value); return value.toInt32(exec); } inline uint32_t toUInt32(JSC::ExecState* exec, JSC::JSValue value, IntegerConversionConfiguration configuration) { if (configuration == EnforceRange) return toUInt32EnforceRange(exec, value); return value.toUInt32(exec); } WEBCORE_EXPORT int64_t toInt64(JSC::ExecState*, JSC::JSValue, IntegerConversionConfiguration); WEBCORE_EXPORT uint64_t toUInt64(JSC::ExecState*, JSC::JSValue, IntegerConversionConfiguration); // Returns a Date instance for the specified value, or NaN if the date is not a number. JSC::JSValue jsDateOrNaN(JSC::ExecState*, double); // Returns a Date instance for the specified value, or null if the value is NaN or infinity. JSC::JSValue jsDateOrNull(JSC::ExecState*, double); // NaN if the value can't be converted to a date. double valueToDate(JSC::ExecState*, JSC::JSValue); // Validates that the passed object is a sequence type per section 4.1.13 of the WebIDL spec. inline JSC::JSObject* toJSSequence(JSC::ExecState* exec, JSC::JSValue value, unsigned& length) { JSC::JSObject* object = value.getObject(); if (!object) { throwSequenceTypeError(*exec); return nullptr; } JSC::JSValue lengthValue = object->get(exec, exec->propertyNames().length); if (exec->hadException()) return nullptr; if (lengthValue.isUndefinedOrNull()) { throwSequenceTypeError(*exec); return nullptr; } length = lengthValue.toUInt32(exec); if (exec->hadException()) return nullptr; return object; } inline JSC::JSValue toJS(JSC::ExecState* exec, JSDOMGlobalObject* globalObject, JSC::ArrayBuffer* buffer) { if (!buffer) return JSC::jsNull(); if (JSC::JSValue result = getExistingWrapper(globalObject, buffer)) return result; buffer->ref(); JSC::JSArrayBuffer* wrapper = JSC::JSArrayBuffer::create(exec->vm(), globalObject->arrayBufferStructure(), buffer); cacheWrapper(globalObject->world(), buffer, wrapper); return wrapper; } inline JSC::JSValue toJS(JSC::ExecState* exec, JSDOMGlobalObject* globalObject, JSC::ArrayBufferView* view) { if (!view) return JSC::jsNull(); return view->wrap(exec, globalObject); } inline JSC::JSValue toJS(JSC::ExecState* exec, JSC::JSGlobalObject* globalObject, JSC::ArrayBufferView* view) { if (!view) return JSC::jsNull(); return view->wrap(exec, globalObject); } template inline JSC::JSValue toJS(JSC::ExecState* exec, JSDOMGlobalObject* globalObject, RefPtr ptr) { return toJS(exec, globalObject, ptr.get()); } template inline JSC::JSValue toJS(JSC::ExecState* exec, JSDOMGlobalObject* globalObject, PassRefPtr ptr) { return toJS(exec, globalObject, ptr.get()); } template inline JSC::JSValue toJS(JSC::ExecState* exec, JSDOMGlobalObject* globalObject, const Vector& vector) { JSC::JSArray* array = constructEmptyArray(exec, nullptr, vector.size()); for (size_t i = 0; i < vector.size(); ++i) array->putDirectIndex(exec, i, toJS(exec, globalObject, vector[i])); return array; } template inline JSC::JSValue toJS(JSC::ExecState* exec, JSDOMGlobalObject* globalObject, const Vector>& vector) { JSC::JSArray* array = constructEmptyArray(exec, nullptr, vector.size()); for (size_t i = 0; i < vector.size(); ++i) array->putDirectIndex(exec, i, toJS(exec, globalObject, vector[i].get())); return array; } inline JSC::JSValue toJS(JSC::ExecState* exec, JSDOMGlobalObject*, const String& value) { return jsStringOrNull(exec, value); } inline JSC::JSValue toJSIterator(JSC::ExecState& state, JSDOMGlobalObject&, JSC::JSValue value) { return createIteratorResultObject(&state, value, false); } template inline JSC::JSValue toJSIterator(JSC::ExecState& state, JSDOMGlobalObject& globalObject, const T& value) { return createIteratorResultObject(&state, toJS(&state, &globalObject, value), false); } inline JSC::JSValue toJSIteratorEnd(JSC::ExecState& state) { return createIteratorResultObject(&state, JSC::jsUndefined(), true); } template struct JSValueTraits { static JSC::JSValue arrayJSValue(JSC::ExecState* exec, JSDOMGlobalObject* globalObject, const T& value) { return toJS(exec, globalObject, WTF::getPtr(value)); } }; template<> struct JSValueTraits { static JSC::JSValue arrayJSValue(JSC::ExecState* exec, JSDOMGlobalObject*, const String& value) { return JSC::jsStringWithCache(exec, value); } }; template<> struct JSValueTraits { static JSC::JSValue arrayJSValue(JSC::ExecState*, JSDOMGlobalObject*, const double& value) { return JSC::jsNumber(value); } }; template<> struct JSValueTraits { static JSC::JSValue arrayJSValue(JSC::ExecState*, JSDOMGlobalObject*, const float& value) { return JSC::jsNumber(value); } }; template<> struct JSValueTraits { static JSC::JSValue arrayJSValue(JSC::ExecState*, JSDOMGlobalObject*, const unsigned long& value) { return JSC::jsNumber(value); } }; template JSC::JSValue jsArray(JSC::ExecState* exec, JSDOMGlobalObject* globalObject, const Vector& vector) { JSC::MarkedArgumentBuffer list; for (auto& element : vector) list.append(JSValueTraits::arrayJSValue(exec, globalObject, element)); return JSC::constructArray(exec, nullptr, globalObject, list); } template inline JSC::JSValue jsArray(JSC::ExecState* exec, JSDOMGlobalObject* globalObject, const Vector* vector) { if (!vector) return JSC::constructEmptyArray(exec, nullptr, globalObject, 0); return jsArray(exec, globalObject, *vector); } template inline JSC::JSValue jsPair(JSC::ExecState& state, JSDOMGlobalObject* globalObject, const Value1& value1, const Value2& value2) { JSC::MarkedArgumentBuffer args; args.append(toJS(&state, globalObject, value1)); args.append(toJS(&state, globalObject, value2)); return constructArray(&state, 0, globalObject, args); } WEBCORE_EXPORT JSC::JSValue jsArray(JSC::ExecState*, JSDOMGlobalObject*, PassRefPtr); inline PassRefPtr toArrayBufferView(JSC::JSValue value) { JSC::JSArrayBufferView* wrapper = JSC::jsDynamicCast(value); if (!wrapper) return nullptr; return wrapper->impl(); } inline RefPtr toInt8Array(JSC::JSValue value) { return JSC::toNativeTypedView(value); } inline RefPtr toInt16Array(JSC::JSValue value) { return JSC::toNativeTypedView(value); } inline RefPtr toInt32Array(JSC::JSValue value) { return JSC::toNativeTypedView(value); } inline RefPtr toUint8Array(JSC::JSValue value) { return JSC::toNativeTypedView(value); } inline RefPtr toUint8ClampedArray(JSC::JSValue value) { return JSC::toNativeTypedView(value); } inline RefPtr toUint16Array(JSC::JSValue value) { return JSC::toNativeTypedView(value); } inline RefPtr toUint32Array(JSC::JSValue value) { return JSC::toNativeTypedView(value); } inline RefPtr toFloat32Array(JSC::JSValue value) { return JSC::toNativeTypedView(value); } inline RefPtr toFloat64Array(JSC::JSValue value) { return JSC::toNativeTypedView(value); } template struct NativeValueTraits; template<> struct NativeValueTraits { static inline bool nativeValue(JSC::ExecState* exec, JSC::JSValue jsValue, String& indexedValue) { indexedValue = jsValue.toString(exec)->value(exec); return true; } }; template<> struct NativeValueTraits { static inline bool nativeValue(JSC::ExecState* exec, JSC::JSValue jsValue, unsigned& indexedValue) { if (!jsValue.isNumber()) return false; indexedValue = jsValue.toUInt32(exec); if (exec->hadException()) return false; return true; } }; template<> struct NativeValueTraits { static inline bool nativeValue(JSC::ExecState* exec, JSC::JSValue jsValue, float& indexedValue) { indexedValue = jsValue.toFloat(exec); return !exec->hadException(); } }; template<> struct NativeValueTraits { static inline bool nativeValue(JSC::ExecState* exec, JSC::JSValue jsValue, double& indexedValue) { indexedValue = jsValue.toNumber(exec); return !exec->hadException(); } }; template Vector> toRefPtrNativeArray(JSC::ExecState* exec, JSC::JSValue value, T* (*toT)(JSC::JSValue value)) { if (!isJSArray(value)) return Vector>(); Vector> result; JSC::JSArray* array = asArray(value); size_t size = array->length(); result.reserveInitialCapacity(size); for (size_t i = 0; i < size; ++i) { JSC::JSValue element = array->getIndex(exec, i); if (element.inherits(JST::info())) result.uncheckedAppend((*toT)(element)); else { throwArrayElementTypeError(*exec); return Vector>(); } } return result; } template Vector toNativeArray(JSC::ExecState* exec, JSC::JSValue value) { JSC::JSObject* object = value.getObject(); if (!object) return Vector(); unsigned length = 0; if (isJSArray(value)) { JSC::JSArray* array = asArray(value); length = array->length(); } else toJSSequence(exec, value, length); Vector result; result.reserveInitialCapacity(length); typedef NativeValueTraits TraitsType; for (unsigned i = 0; i < length; ++i) { T indexValue; if (!TraitsType::nativeValue(exec, object->get(exec, i), indexValue)) return Vector(); result.uncheckedAppend(indexValue); } return result; } template Vector toNativeArguments(JSC::ExecState* exec, size_t startIndex = 0) { size_t length = exec->argumentCount(); ASSERT(startIndex <= length); Vector result; result.reserveInitialCapacity(length - startIndex); typedef NativeValueTraits TraitsType; for (size_t i = startIndex; i < length; ++i) { T indexValue; if (!TraitsType::nativeValue(exec, exec->argument(i), indexValue)) return Vector(); result.uncheckedAppend(indexValue); } return result; } bool shouldAllowAccessToNode(JSC::ExecState*, Node*); bool shouldAllowAccessToFrame(JSC::ExecState*, Frame*); bool shouldAllowAccessToFrame(JSC::ExecState*, Frame*, String& message); bool shouldAllowAccessToDOMWindow(JSC::ExecState*, DOMWindow&, String& message); void printErrorMessageForFrame(Frame*, const String& message); inline String propertyNameToString(JSC::PropertyName propertyName) { ASSERT(!propertyName.isSymbol()); return propertyName.uid() ? propertyName.uid() : propertyName.publicName(); } inline AtomicString propertyNameToAtomicString(JSC::PropertyName propertyName) { return AtomicString(propertyName.uid() ? propertyName.uid() : propertyName.publicName()); } template inline const JSC::HashTableValue* getStaticValueSlotEntryWithoutCaching(JSC::ExecState* exec, JSC::PropertyName propertyName) { if (DOMClass::hasStaticPropertyTable) { if (auto* entry = DOMClass::info()->staticPropHashTable->entry(propertyName)) return entry; } return getStaticValueSlotEntryWithoutCaching(exec, propertyName); } template<> inline const JSC::HashTableValue* getStaticValueSlotEntryWithoutCaching(JSC::ExecState*, JSC::PropertyName) { return nullptr; } template JSC::EncodedJSValue nonCachingStaticFunctionGetter(JSC::ExecState* exec, JSC::EncodedJSValue, JSC::PropertyName propertyName) { return JSC::JSValue::encode(JSC::JSFunction::create(exec->vm(), exec->lexicalGlobalObject(), length, propertyName.publicName(), nativeFunction)); } enum SecurityReportingOption { DoNotReportSecurityError, ReportSecurityError, }; class BindingSecurity { public: static bool shouldAllowAccessToNode(JSC::ExecState*, Node*); static bool shouldAllowAccessToDOMWindow(JSC::ExecState*, DOMWindow&, SecurityReportingOption = ReportSecurityError); static bool shouldAllowAccessToFrame(JSC::ExecState*, Frame*, SecurityReportingOption = ReportSecurityError); }; inline JSC::JSValue getPropertyFromObject(JSC::ExecState& exec, JSC::JSObject& object, const char* identifier) { return object.get(&exec, JSC::Identifier::fromString(&exec, identifier)); } inline void setPropertyToObject(JSC::ExecState& exec, JSC::JSObject& object, const char* name, JSC::JSValue value) { JSC::PutPropertySlot propertySlot(&object); JSC::JSObject::put(&object, &exec, JSC::Identifier::fromString(&exec, name), value, propertySlot); } template inline JSC::JSValue toNullableJSNumber(Optional optionalNumber) { return optionalNumber ? JSC::jsNumber(optionalNumber.value()) : JSC::jsNull(); } } // namespace WebCore #endif // JSDOMBinding_h