diff options
Diffstat (limited to 'Source/WebCore/bindings')
343 files changed, 25120 insertions, 23701 deletions
diff --git a/Source/WebCore/bindings/IDLTypes.h b/Source/WebCore/bindings/IDLTypes.h new file mode 100644 index 000000000..d2c1767b9 --- /dev/null +++ b/Source/WebCore/bindings/IDLTypes.h @@ -0,0 +1,246 @@ +/* + * Copyright (C) 2016 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +#include <heap/HandleTypes.h> +#include <wtf/Brigand.h> +#include <wtf/HashMap.h> +#include <wtf/StdLibExtras.h> +#include <wtf/text/WTFString.h> + +#if ENABLE(WEBGL) +#include "WebGLAny.h" +#endif + +namespace JSC { +class ArrayBuffer; +class ArrayBufferView; +class JSValue; +class JSObject; +template<typename> class Strong; +} + +namespace WebCore { + +class IDBKey; +class IDBKeyData; +class IDBValue; +template<typename> class DOMPromise; + +template<typename T> +struct IDLType { + using ImplementationType = T; + using ParameterType = T; + + using NullableType = std::optional<ImplementationType>; + static NullableType nullValue() { return std::nullopt; } + static bool isNullValue(const NullableType& value) { return !value; } + static ImplementationType extractValueFromNullable(const NullableType& value) { return value.value(); } +}; + +// IDLUnsupportedType is a special type that serves as a base class for currently unsupported types. +struct IDLUnsupportedType : IDLType<void> { }; + +// IDLNull is a special type for use as a subtype in an IDLUnion that is nullable. +struct IDLNull : IDLType<std::nullptr_t> { }; + +struct IDLAny : IDLType<JSC::Strong<JSC::Unknown>> { + using ParameterType = JSC::JSValue; + + using NullableType = JSC::Strong<JSC::Unknown>; + static inline std::nullptr_t nullValue() { return nullptr; } + template<typename U> static inline bool isNullValue(U&& value) { return !value; } + template<typename U> static inline U&& extractValueFromNullable(U&& value) { return std::forward<U>(value); } +}; + +struct IDLBoolean : IDLType<bool> { }; + +template<typename NumericType> struct IDLNumber : IDLType<NumericType> { }; + +template<typename IntegerType> struct IDLInteger : IDLNumber<IntegerType> { }; +struct IDLByte : IDLInteger<int8_t> { }; +struct IDLOctet : IDLInteger<uint8_t> { }; +struct IDLShort : IDLInteger<int16_t> { }; +struct IDLUnsignedShort : IDLInteger<uint16_t> { }; +struct IDLLong : IDLInteger<int32_t> { }; +struct IDLUnsignedLong : IDLInteger<uint32_t> { }; +struct IDLLongLong : IDLInteger<int64_t> { }; +struct IDLUnsignedLongLong : IDLInteger<uint64_t> { }; + +template<typename FloatingPointType> struct IDLFloatingPoint : IDLNumber<FloatingPointType> { }; +struct IDLFloat : IDLFloatingPoint<float> { }; +struct IDLUnrestrictedFloat : IDLFloatingPoint<float> { }; +struct IDLDouble : IDLFloatingPoint<double> { }; +struct IDLUnrestrictedDouble : IDLFloatingPoint<double> { }; + +struct IDLString : IDLType<String> { + using ParameterType = const String&; + + using NullableType = String; + static String nullValue() { return String(); } + static bool isNullValue(const String& value) { return value.isNull(); } + template <typename U> static U&& extractValueFromNullable(U&& value) { return std::forward<U>(value); } +}; +struct IDLDOMString : IDLString { }; +struct IDLByteString : IDLString { }; +struct IDLUSVString : IDLString { }; + +struct IDLObject : IDLType<JSC::Strong<JSC::JSObject>> { + using NullableType = JSC::Strong<JSC::JSObject>; + + static inline std::nullptr_t nullValue() { return nullptr; } + template<typename U> static inline bool isNullValue(U&& value) { return !value; } + template<typename U> static inline U&& extractValueFromNullable(U&& value) { return std::forward<U>(value); } +}; + +template<typename T> struct IDLWrapper : IDLType<RefPtr<T>> { + using RawType = T; + + using ParameterType = T&; + + using NullableType = RefPtr<T>; + static inline std::nullptr_t nullValue() { return nullptr; } + template<typename U> static inline bool isNullValue(U&& value) { return !value; } + template<typename U> static inline U&& extractValueFromNullable(U&& value) { return std::forward<U>(value); } +}; + +template<typename T> struct IDLInterface : IDLWrapper<T> { }; +template<typename T> struct IDLCallbackInterface : IDLWrapper<T> { }; +template<typename T> struct IDLCallbackFunction : IDLWrapper<T> { }; + +template<typename T> struct IDLDictionary : IDLType<T> { + using ParameterType = const T&; +}; + +template<typename T> struct IDLEnumeration : IDLType<T> { }; + +template<typename T> struct IDLNullable : IDLType<typename T::NullableType> { + using InnerType = T; + + using NullableType = typename T::NullableType; + static inline auto nullValue() -> decltype(T::nullValue()) { return T::nullValue(); } + template<typename U> static inline bool isNullValue(U&& value) { return T::isNullValue(std::forward<U>(value)); } + template<typename U> static inline auto extractValueFromNullable(U&& value) -> decltype(T::extractValueFromNullable(std::forward<U>(value))) { return T::extractValueFromNullable(std::forward<U>(value)); } +}; + +template<typename T> struct IDLSequence : IDLType<Vector<typename T::ImplementationType>> { + using InnerType = T; + + using ParameterType = const Vector<typename T::ImplementationType>&; +}; + +template<typename T> struct IDLFrozenArray : IDLType<Vector<typename T::ImplementationType>> { + using InnerType = T; + + using ParameterType = const Vector<typename T::ImplementationType>&; +}; + +template<typename K, typename V> struct IDLRecord : IDLType<Vector<WTF::KeyValuePair<typename K::ImplementationType, typename V::ImplementationType>>> { + using KeyType = K; + using ValueType = V; + + using ParameterType = const Vector<WTF::KeyValuePair<typename K::ImplementationType, typename V::ImplementationType>>&; +}; + +template<typename T> struct IDLPromise : IDLType<DOMPromise<T>> { + using InnerType = T; +}; + +struct IDLError : IDLUnsupportedType { }; +struct IDLDOMException : IDLUnsupportedType { }; + +template<typename... Ts> +struct IDLUnion : IDLType<Variant<typename Ts::ImplementationType...>> { + using TypeList = brigand::list<Ts...>; + + using ParameterType = const Variant<typename Ts::ImplementationType...>&; +}; + +// Non-WebIDL extensions + +struct IDLDate : IDLType<double> { + using NullableType = double; + static double nullValue() { return std::numeric_limits<double>::quiet_NaN(); } + static bool isNullValue(double value) { return std::isnan(value); } + static double extractValueFromNullable(double value) { return value; } +}; + +struct IDLJSON : IDLType<String> { + using ParameterType = const String&; + + using NullableType = String; + static String nullValue() { return String(); } + static bool isNullValue(const String& value) { return value.isNull(); } + template <typename U> static U&& extractValueFromNullable(U&& value) { return std::forward<U>(value); } +}; + +template<typename T> struct IDLSerializedScriptValue : IDLWrapper<T> { }; +template<typename T> struct IDLEventListener : IDLWrapper<T> { }; +template<typename T> struct IDLXPathNSResolver : IDLWrapper<T> { }; + +struct IDLIDBKey : IDLWrapper<IDBKey> { }; +struct IDLIDBKeyData : IDLWrapper<IDBKeyData> { }; +struct IDLIDBValue : IDLWrapper<IDBValue> { }; + +#if ENABLE(WEBGL) +struct IDLWebGLAny : IDLType<WebGLAny> { }; +#endif + +// Non-WebIDL convenience type aliases + +using IDLBufferSource = IDLUnion<IDLInterface<JSC::ArrayBufferView>, IDLInterface<JSC::ArrayBuffer>>; + + +// Helper predicates + +template<typename T> +struct IsIDLInterface : public std::integral_constant<bool, WTF::IsTemplate<T, IDLInterface>::value> { }; + +template<typename T> +struct IsIDLDictionary : public std::integral_constant<bool, WTF::IsTemplate<T, IDLDictionary>::value> { }; + +template<typename T> +struct IsIDLEnumeration : public std::integral_constant<bool, WTF::IsTemplate<T, IDLEnumeration>::value> { }; + +template<typename T> +struct IsIDLSequence : public std::integral_constant<bool, WTF::IsTemplate<T, IDLSequence>::value> { }; + +template<typename T> +struct IsIDLFrozenArray : public std::integral_constant<bool, WTF::IsTemplate<T, IDLFrozenArray>::value> { }; + +template<typename T> +struct IsIDLRecord : public std::integral_constant<bool, WTF::IsTemplate<T, IDLRecord>::value> { }; + +template<typename T> +struct IsIDLNumber : public std::integral_constant<bool, WTF::IsBaseOfTemplate<IDLNumber, T>::value> { }; + +template<typename T> +struct IsIDLInteger : public std::integral_constant<bool, WTF::IsBaseOfTemplate<IDLInteger, T>::value> { }; + +template<typename T> +struct IsIDLFloatingPoint : public std::integral_constant<bool, WTF::IsBaseOfTemplate<IDLFloatingPoint, T>::value> { }; + +} // namespace WebCore diff --git a/Source/WebCore/bindings/generic/ActiveDOMCallback.cpp b/Source/WebCore/bindings/generic/ActiveDOMCallback.cpp deleted file mode 100644 index 81a10c14b..000000000 --- a/Source/WebCore/bindings/generic/ActiveDOMCallback.cpp +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright (C) 2010. 2012 Google Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" -#include "ActiveDOMCallback.h" - -#include "ActiveDOMObject.h" -#include "ScriptExecutionContext.h" -#include "WorkerGlobalScope.h" - -namespace WebCore { - -ActiveDOMCallback::ActiveDOMCallback(ScriptExecutionContext* context) - : ContextDestructionObserver(context) -{ -} - -ActiveDOMCallback::~ActiveDOMCallback() -{ -} - -bool ActiveDOMCallback::canInvokeCallback() const -{ - ScriptExecutionContext* context = scriptExecutionContext(); - return context && !context->activeDOMObjectsAreSuspended() && !context->activeDOMObjectsAreStopped(); -} - -} // namespace WebCore diff --git a/Source/WebCore/bindings/generic/ActiveDOMCallback.h b/Source/WebCore/bindings/generic/ActiveDOMCallback.h deleted file mode 100644 index 821e59c9b..000000000 --- a/Source/WebCore/bindings/generic/ActiveDOMCallback.h +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright (C) 2010, 2012 Google Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef ActiveDOMCallback_h -#define ActiveDOMCallback_h - -#include "ContextDestructionObserver.h" -#include <wtf/OwnPtr.h> - -namespace WebCore { - -class ScriptExecutionContext; - -// A base class that prevents binding callbacks from executing when -// active dom objects are stopped or suspended. -// -// Should only be created, used, and destroyed on the script execution -// context thread. -class ActiveDOMCallback : public ContextDestructionObserver { -public: - ActiveDOMCallback(ScriptExecutionContext* context); - virtual ~ActiveDOMCallback(); - - bool canInvokeCallback() const; -}; - -} // namespace WebCore - -#endif // ActiveDOMCallback_h diff --git a/Source/WebCore/bindings/generic/RuntimeEnabledFeatures.cpp b/Source/WebCore/bindings/generic/RuntimeEnabledFeatures.cpp deleted file mode 100644 index 82b98863a..000000000 --- a/Source/WebCore/bindings/generic/RuntimeEnabledFeatures.cpp +++ /dev/null @@ -1,180 +0,0 @@ -/* - * Copyright (C) 2009 Google Inc. All rights reserved. - * Copyright (C) 2013 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" -#include "RuntimeEnabledFeatures.h" - -#include "DatabaseManager.h" -#include "MediaPlayer.h" -#include "SharedWorkerRepository.h" -#include "WebSocket.h" -#include <wtf/NeverDestroyed.h> - -namespace WebCore { - -RuntimeEnabledFeatures::RuntimeEnabledFeatures() - : m_isLocalStorageEnabled(true) - , m_isSessionStorageEnabled(true) - , m_isWebkitNotificationsEnabled(false) - , m_isApplicationCacheEnabled(true) - , m_isDataTransferItemsEnabled(true) - , m_isGeolocationEnabled(true) - , m_isIndexedDBEnabled(false) - , m_isTouchEnabled(true) - , m_isDeviceMotionEnabled(true) - , m_isDeviceOrientationEnabled(true) - , m_isSpeechInputEnabled(true) - , m_isCSSExclusionsEnabled(true) - , m_isCSSShapesEnabled(true) - , m_isCSSRegionsEnabled(false) - , m_isCSSCompositingEnabled(false) - , m_isLangAttributeAwareFormControlUIEnabled(false) -#if ENABLE(SCRIPTED_SPEECH) - , m_isScriptedSpeechEnabled(false) -#endif -#if ENABLE(MEDIA_STREAM) - , m_isMediaStreamEnabled(true) - , m_isPeerConnectionEnabled(true) -#endif -#if ENABLE(LEGACY_CSS_VENDOR_PREFIXES) - , m_isLegacyCSSVendorPrefixesEnabled(false) -#endif -#if ENABLE(JAVASCRIPT_I18N_API) - , m_isJavaScriptI18NAPIEnabled(false) -#endif -#if ENABLE(VIDEO_TRACK) - , m_isVideoTrackEnabled(true) -#endif -#if ENABLE(SHADOW_DOM) - , m_isShadowDOMEnabled(false) - , m_isAuthorShadowDOMForAnyElementEnabled(false) -#endif -#if ENABLE(INPUT_TYPE_DATE) - , m_isInputTypeDateEnabled(true) -#endif -#if ENABLE(INPUT_TYPE_DATETIME_INCOMPLETE) - , m_isInputTypeDateTimeEnabled(false) -#endif -#if ENABLE(INPUT_TYPE_DATETIMELOCAL) - , m_isInputTypeDateTimeLocalEnabled(true) -#endif -#if ENABLE(INPUT_TYPE_MONTH) - , m_isInputTypeMonthEnabled(true) -#endif -#if ENABLE(INPUT_TYPE_TIME) - , m_isInputTypeTimeEnabled(true) -#endif -#if ENABLE(INPUT_TYPE_WEEK) - , m_isInputTypeWeekEnabled(true) -#endif -#if ENABLE(CSP_NEXT) - , m_areExperimentalContentSecurityPolicyFeaturesEnabled(false) -#endif -#if ENABLE(IFRAME_SEAMLESS) - , m_areSeamlessIFramesEnabled(false) -#endif -#if ENABLE(FONT_LOAD_EVENTS) - , m_isFontLoadEventsEnabled(false) -#endif -{ -} - -RuntimeEnabledFeatures& RuntimeEnabledFeatures::sharedFeatures() -{ - static NeverDestroyed<RuntimeEnabledFeatures> runtimeEnabledFeatures; - - return runtimeEnabledFeatures; -} - -#if ENABLE(JAVASCRIPT_I18N_API) -bool RuntimeEnabledFeatures::javaScriptI18NAPIEnabled() -{ - return m_isJavaScriptI18NAPIEnabled; -} -#endif - -#if ENABLE(VIDEO) -bool RuntimeEnabledFeatures::audioEnabled() const -{ - return MediaPlayer::isAvailable(); -} - -bool RuntimeEnabledFeatures::htmlMediaElementEnabled() const -{ - return MediaPlayer::isAvailable(); -} - -bool RuntimeEnabledFeatures::htmlAudioElementEnabled() const -{ - return MediaPlayer::isAvailable(); -} - -bool RuntimeEnabledFeatures::htmlVideoElementEnabled() const -{ - return MediaPlayer::isAvailable(); -} - -bool RuntimeEnabledFeatures::htmlSourceElementEnabled() const -{ - return MediaPlayer::isAvailable(); -} - -bool RuntimeEnabledFeatures::mediaControllerEnabled() const -{ - return MediaPlayer::isAvailable(); -} - -bool RuntimeEnabledFeatures::mediaErrorEnabled() const -{ - return MediaPlayer::isAvailable(); -} - -bool RuntimeEnabledFeatures::timeRangesEnabled() const -{ - return MediaPlayer::isAvailable(); -} -#endif - -#if ENABLE(SHARED_WORKERS) -bool RuntimeEnabledFeatures::sharedWorkerEnabled() const -{ - return SharedWorkerRepository::isAvailable(); -} -#endif - -#if ENABLE(WEB_SOCKETS) -bool RuntimeEnabledFeatures::webSocketEnabled() const -{ - return WebSocket::isAvailable(); -} -#endif - -} // namespace WebCore diff --git a/Source/WebCore/bindings/generic/RuntimeEnabledFeatures.h b/Source/WebCore/bindings/generic/RuntimeEnabledFeatures.h deleted file mode 100644 index 2720901e5..000000000 --- a/Source/WebCore/bindings/generic/RuntimeEnabledFeatures.h +++ /dev/null @@ -1,332 +0,0 @@ -/* - * Copyright (C) 2009 Google Inc. All rights reserved. - * Copyright (C) 2013 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef RuntimeEnabledFeatures_h -#define RuntimeEnabledFeatures_h - -#include "PlatformExportMacros.h" -#include <wtf/NeverDestroyed.h> - -namespace WebCore { - -// A class that stores static enablers for all experimental features. Note that -// the method names must line up with the JavaScript method they enable for code -// generation to work properly. - -class RuntimeEnabledFeatures { - WTF_MAKE_NONCOPYABLE(RuntimeEnabledFeatures); -public: - void setLocalStorageEnabled(bool isEnabled) { m_isLocalStorageEnabled = isEnabled; } - bool localStorageEnabled() const { return m_isLocalStorageEnabled; } - - void setSessionStorageEnabled(bool isEnabled) { m_isSessionStorageEnabled = isEnabled; } - bool sessionStorageEnabled() const { return m_isSessionStorageEnabled; } - - void setWebkitNotificationsEnabled(bool isEnabled) { m_isWebkitNotificationsEnabled = isEnabled; } - bool webkitNotificationsEnabled() const { return m_isWebkitNotificationsEnabled; } - - void setApplicationCacheEnabled(bool isEnabled) { m_isApplicationCacheEnabled = isEnabled; } - bool applicationCacheEnabled() const { return m_isApplicationCacheEnabled; } - - void setDataTransferItemsEnabled(bool isEnabled) { m_isDataTransferItemsEnabled = isEnabled; } - bool dataTransferItemsEnabled() const { return m_isDataTransferItemsEnabled; } - - void setGeolocationEnabled(bool isEnabled) { m_isGeolocationEnabled = isEnabled; } - bool geolocationEnabled() const { return m_isGeolocationEnabled; } - - void setWebkitIndexedDBEnabled(bool isEnabled) { m_isIndexedDBEnabled = isEnabled; } - bool webkitIndexedDBEnabled() const { return m_isIndexedDBEnabled; } - bool indexedDBEnabled() const { return m_isIndexedDBEnabled; } - -#if ENABLE(CSS_EXCLUSIONS) - void setCSSExclusionsEnabled(bool isEnabled) { m_isCSSExclusionsEnabled = isEnabled; } - bool cssExclusionsEnabled() const { return m_isCSSExclusionsEnabled; } -#else - void setCSSExclusionsEnabled(bool) { } - bool cssExclusionsEnabled() const { return false; } -#endif - -#if ENABLE(CSS_SHAPES) - void setCSSShapesEnabled(bool isEnabled) { m_isCSSShapesEnabled = isEnabled; } - bool cssShapesEnabled() const { return m_isCSSShapesEnabled; } -#else - void setCSSShapesEnabled(bool) { } - bool cssShapesEnabled() const { return false; } -#endif - -#if ENABLE(CSS_REGIONS) - void setCSSRegionsEnabled(bool isEnabled) { m_isCSSRegionsEnabled = isEnabled; } - bool cssRegionsEnabled() const { return m_isCSSRegionsEnabled; } -#else - void setCSSRegionsEnabled(bool) { } - bool cssRegionsEnabled() const { return false; } -#endif - - void setCSSCompositingEnabled(bool isEnabled) { m_isCSSCompositingEnabled = isEnabled; } - bool cssCompositingEnabled() const { return m_isCSSCompositingEnabled; } - -#if ENABLE(FONT_LOAD_EVENTS) - void setFontLoadEventsEnabled(bool isEnabled) { m_isFontLoadEventsEnabled = isEnabled; } - bool fontLoadEventsEnabled() const { return m_isFontLoadEventsEnabled; } -#else - void setFontLoadEventsEnabled(bool) { } - bool fontLoadEventsEnabled() { return false; } -#endif - -#if ENABLE(VIDEO) - bool audioEnabled() const; - bool htmlMediaElementEnabled() const; - bool htmlAudioElementEnabled() const; - bool htmlVideoElementEnabled() const; - bool htmlSourceElementEnabled() const; - bool mediaControllerEnabled() const; - bool mediaErrorEnabled() const; - bool timeRangesEnabled() const; -#endif - -#if ENABLE(SHARED_WORKERS) - bool sharedWorkerEnabled() const; -#endif - -#if ENABLE(WEB_SOCKETS) - bool webSocketEnabled() const; -#endif - -#if ENABLE(TOUCH_EVENTS) - bool touchEnabled() const { return m_isTouchEnabled; } - void setTouchEnabled(bool isEnabled) { m_isTouchEnabled = isEnabled; } -#endif - - void setDeviceMotionEnabled(bool isEnabled) { m_isDeviceMotionEnabled = isEnabled; } - bool deviceMotionEnabled() const { return m_isDeviceMotionEnabled; } - bool deviceMotionEventEnabled() const { return m_isDeviceMotionEnabled; } - bool ondevicemotionEnabled() const { return m_isDeviceMotionEnabled; } - - void setDeviceOrientationEnabled(bool isEnabled) { m_isDeviceOrientationEnabled = isEnabled; } - bool deviceOrientationEnabled() const { return m_isDeviceOrientationEnabled; } - bool deviceOrientationEventEnabled() const { return m_isDeviceOrientationEnabled; } - bool ondeviceorientationEnabled() const { return m_isDeviceOrientationEnabled; } - - void setSpeechInputEnabled(bool isEnabled) { m_isSpeechInputEnabled = isEnabled; } - bool speechInputEnabled() const { return m_isSpeechInputEnabled; } - bool webkitSpeechEnabled() const { return m_isSpeechInputEnabled; } - bool webkitGrammarEnabled() const { return m_isSpeechInputEnabled; } - -#if ENABLE(SCRIPTED_SPEECH) - void setScriptedSpeechEnabled(bool isEnabled) { m_isScriptedSpeechEnabled = isEnabled; } - bool scriptedSpeechEnabled() const { return m_isScriptedSpeechEnabled; } - bool webkitSpeechRecognitionEnabled() const { return m_isScriptedSpeechEnabled; } - bool webkitSpeechRecognitionErrorEnabled() const { return m_isScriptedSpeechEnabled; } - bool webkitSpeechRecognitionEventEnabled() const { return m_isScriptedSpeechEnabled; } - bool webkitSpeechGrammarEnabled() const { return m_isScriptedSpeechEnabled; } - bool webkitSpeechGrammarListEnabled() const { return m_isScriptedSpeechEnabled; } -#endif - -#if ENABLE(JAVASCRIPT_I18N_API) - bool javaScriptI18NAPIEnabled() const; - void setJavaScriptI18NAPIEnabled(bool isEnabled) { m_isJavaScriptI18NAPIEnabled = isEnabled; } -#endif - -#if ENABLE(MEDIA_STREAM) - bool mediaStreamEnabled() const { return m_isMediaStreamEnabled; } - void setMediaStreamEnabled(bool isEnabled) { m_isMediaStreamEnabled = isEnabled; } - bool webkitGetUserMediaEnabled() const { return m_isMediaStreamEnabled; } - bool webkitMediaStreamEnabled() const { return m_isMediaStreamEnabled; } - - bool peerConnectionEnabled() const { return m_isMediaStreamEnabled && m_isPeerConnectionEnabled; } - void setPeerConnectionEnabled(bool isEnabled) { m_isPeerConnectionEnabled = isEnabled; } - bool webkitRTCPeerConnectionEnabled() const { return peerConnectionEnabled(); } -#endif - -#if ENABLE(LEGACY_CSS_VENDOR_PREFIXES) - void setLegacyCSSVendorPrefixesEnabled(bool isEnabled) { m_isLegacyCSSVendorPrefixesEnabled = isEnabled; } - bool legacyCSSVendorPrefixesEnabled() const { return m_isLegacyCSSVendorPrefixesEnabled; } -#endif - -#if ENABLE(VIDEO_TRACK) - bool webkitVideoTrackEnabled() const { return m_isVideoTrackEnabled; } - void setWebkitVideoTrackEnabled(bool isEnabled) { m_isVideoTrackEnabled = isEnabled; } -#endif - -#if ENABLE(SHADOW_DOM) - bool shadowDOMEnabled() const { return m_isShadowDOMEnabled; } - void setShadowDOMEnabled(bool isEnabled) { m_isShadowDOMEnabled = isEnabled; } - - bool authorShadowDOMForAnyElementEnabled() const { return m_isAuthorShadowDOMForAnyElementEnabled; } - void setAuthorShadowDOMForAnyElementEnabled(bool isEnabled) { m_isAuthorShadowDOMForAnyElementEnabled = isEnabled; } -#endif - -#if ENABLE(INPUT_TYPE_DATE) - bool inputTypeDateEnabled() const { return m_isInputTypeDateEnabled; } - void setInputTypeDateEnabled(bool isEnabled) { m_isInputTypeDateEnabled = isEnabled; } -#endif - -#if ENABLE(INPUT_TYPE_DATETIME_INCOMPLETE) - bool inputTypeDateTimeEnabled() const { return m_isInputTypeDateTimeEnabled; } - void setInputTypeDateTimeEnabled(bool isEnabled) { m_isInputTypeDateTimeEnabled = isEnabled; } -#endif - -#if ENABLE(INPUT_TYPE_DATETIMELOCAL) - bool inputTypeDateTimeLocalEnabled() const { return m_isInputTypeDateTimeLocalEnabled; } - void setInputTypeDateTimeLocalEnabled(bool isEnabled) { m_isInputTypeDateTimeLocalEnabled = isEnabled; } -#endif - -#if ENABLE(INPUT_TYPE_MONTH) - bool inputTypeMonthEnabled() const { return m_isInputTypeMonthEnabled; } - void setInputTypeMonthEnabled(bool isEnabled) { m_isInputTypeMonthEnabled = isEnabled; } -#endif - -#if ENABLE(INPUT_TYPE_TIME) - bool inputTypeTimeEnabled() const { return m_isInputTypeTimeEnabled; } - void setInputTypeTimeEnabled(bool isEnabled) { m_isInputTypeTimeEnabled = isEnabled; } -#endif - -#if ENABLE(INPUT_TYPE_WEEK) - bool inputTypeWeekEnabled() const { return m_isInputTypeWeekEnabled; } - void setInputTypeWeekEnabled(bool isEnabled) { m_isInputTypeWeekEnabled = isEnabled; } -#endif - -#if ENABLE(CSP_NEXT) - bool experimentalContentSecurityPolicyFeaturesEnabled() const { return m_areExperimentalContentSecurityPolicyFeaturesEnabled; } - void setExperimentalContentSecurityPolicyFeaturesEnabled(bool isEnabled) { m_areExperimentalContentSecurityPolicyFeaturesEnabled = isEnabled; } -#endif - -#if ENABLE(IFRAME_SEAMLESS) - bool seamlessIFramesEnabled() const { return m_areSeamlessIFramesEnabled; } - void setSeamlessIFramesEnabled(bool isEnabled) { m_areSeamlessIFramesEnabled = isEnabled; } -#endif - - bool langAttributeAwareFormControlUIEnabled() const { return m_isLangAttributeAwareFormControlUIEnabled; } - // The lang attribute support is incomplete and should only be turned on for tests. - void setLangAttributeAwareFormControlUIEnabled(bool isEnabled) { m_isLangAttributeAwareFormControlUIEnabled = isEnabled; } - - void setPluginReplacementEnabled(bool isEnabled) { m_isPluginReplacementEnabled = isEnabled; } - bool pluginReplacementEnabled() const { return m_isPluginReplacementEnabled; } - - static RuntimeEnabledFeatures& sharedFeatures(); - -private: - // Never instantiate. - RuntimeEnabledFeatures(); - - bool m_isLocalStorageEnabled; - bool m_isSessionStorageEnabled; - bool m_isWebkitNotificationsEnabled; - bool m_isApplicationCacheEnabled; - bool m_isDataTransferItemsEnabled; - bool m_isGeolocationEnabled; - bool m_isIndexedDBEnabled; - bool m_isTouchEnabled; - bool m_isDeviceMotionEnabled; - bool m_isDeviceOrientationEnabled; - bool m_isSpeechInputEnabled; - bool m_isCSSExclusionsEnabled; - bool m_isCSSShapesEnabled; - bool m_isCSSRegionsEnabled; - bool m_isCSSCompositingEnabled; - bool m_isLangAttributeAwareFormControlUIEnabled; - bool m_isPluginReplacementEnabled; - -#if ENABLE(SCRIPTED_SPEECH) - bool m_isScriptedSpeechEnabled; -#endif - -#if ENABLE(JAVASCRIPT_I18N_API) - bool m_isJavaScriptI18NAPIEnabled; -#endif - -#if ENABLE(MEDIA_STREAM) - bool m_isMediaStreamEnabled; - bool m_isPeerConnectionEnabled; -#endif - -#if ENABLE(LEGACY_CSS_VENDOR_PREFIXES) - bool m_isLegacyCSSVendorPrefixesEnabled; -#endif - -#if ENABLE(VIDEO_TRACK) - bool m_isVideoTrackEnabled; -#endif - -#if ENABLE(SHADOW_DOM) - bool m_isShadowDOMEnabled; - bool m_isAuthorShadowDOMForAnyElementEnabled; -#endif - -#if ENABLE(INPUT_TYPE_DATE) - bool m_isInputTypeDateEnabled; -#endif - -#if ENABLE(INPUT_TYPE_DATETIME_INCOMPLETE) - bool m_isInputTypeDateTimeEnabled; -#endif - -#if ENABLE(INPUT_TYPE_DATETIMELOCAL) - bool m_isInputTypeDateTimeLocalEnabled; -#endif - -#if ENABLE(INPUT_TYPE_MONTH) - bool m_isInputTypeMonthEnabled; -#endif - -#if ENABLE(INPUT_TYPE_TIME) - bool m_isInputTypeTimeEnabled; -#endif - -#if ENABLE(INPUT_TYPE_WEEK) - bool m_isInputTypeWeekEnabled; -#endif - -#if ENABLE(CSP_NEXT) - bool m_areExperimentalContentSecurityPolicyFeaturesEnabled; -#endif - -#if ENABLE(IFRAME_SEAMLESS) - bool m_areSeamlessIFramesEnabled; -#endif - -#if ENABLE(FONT_LOAD_EVENTS) - bool m_isFontLoadEventsEnabled; -#endif - -#ifndef CLASS_IF_GCC -#if COMPILER(GCC) -#define CLASS_IF_GCC class -#else -#define CLASS_IF_GCC -#endif -#endif - friend CLASS_IF_GCC NeverDestroyed<RuntimeEnabledFeatures>; -}; - -} // namespace WebCore - -#endif // RuntimeEnabledFeatures_h diff --git a/Source/WebCore/bindings/gobject/ConvertToUTF8String.cpp b/Source/WebCore/bindings/gobject/ConvertToUTF8String.cpp deleted file mode 100644 index 14df3a69d..000000000 --- a/Source/WebCore/bindings/gobject/ConvertToUTF8String.cpp +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright (C) 2008 Luke Kenneth Casson Leighton <lkcl@lkcl.net> - * Copyright (C) 2010 Igalia S.L. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public License - * along with this library; see the file COPYING.LIB. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#include "config.h" -#include "ConvertToUTF8String.h" - -#include "URL.h" -#include <wtf/text/CString.h> -#include <wtf/text/WTFString.h> - -#include <glib.h> - -gchar* convertToUTF8String(WTF::String const& s) -{ - return g_strdup(s.utf8().data()); -} - -gchar* convertToUTF8String(WebCore::URL const& s) -{ - return g_strdup(s.string().utf8().data()); -} - diff --git a/Source/WebCore/bindings/gobject/ConvertToUTF8String.h b/Source/WebCore/bindings/gobject/ConvertToUTF8String.h deleted file mode 100644 index e494113a3..000000000 --- a/Source/WebCore/bindings/gobject/ConvertToUTF8String.h +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright (C) 2008 Luke Kenneth Casson Leighton <lkcl@lkcl.net> - * Copyright (C) 2010 Igalia S.L. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public License - * along with this library; see the file COPYING.LIB. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#ifndef ConvertToUTF8String_h -#define ConvertToUTF8String_h - -#include <wtf/Forward.h> - -namespace WebCore { -class URL; -} - -typedef char gchar; - -gchar* convertToUTF8String(WTF::String const& s); -gchar* convertToUTF8String(WebCore::URL const& s); - -#endif /* ConvertToUTF8String_h */ diff --git a/Source/WebCore/bindings/gobject/DOMObjectCache.cpp b/Source/WebCore/bindings/gobject/DOMObjectCache.cpp deleted file mode 100644 index 0ae90a143..000000000 --- a/Source/WebCore/bindings/gobject/DOMObjectCache.cpp +++ /dev/null @@ -1,228 +0,0 @@ -/* - * Copyright (C) 2010, 2015 Igalia S.L. - * - * 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 - */ - -#include "config.h" -#include "DOMObjectCache.h" - -#include "DOMWindowProperty.h" -#include "Document.h" -#include "Frame.h" -#include "FrameDestructionObserver.h" -#include "Node.h" -#include <glib-object.h> -#include <wtf/HashMap.h> -#include <wtf/NeverDestroyed.h> -#include <wtf/Vector.h> -#include <wtf/gobject/GRefPtr.h> - -namespace WebKit { - -struct DOMObjectCacheData { - DOMObjectCacheData(GObject* wrapper) - : object(wrapper) - , cacheReferences(1) - { - } - - void clearObject() - { - ASSERT(object); - ASSERT(cacheReferences >= 1); - ASSERT(object->ref_count >= 1); - - // Make sure we don't unref more than the references the object actually has. It can happen that user - // unreffed a reference owned by the cache. - cacheReferences = std::min(static_cast<unsigned>(object->ref_count), cacheReferences); - GRefPtr<GObject> protect(object); - do { - g_object_unref(object); - } while (--cacheReferences); - object = nullptr; - } - - void* refObject() - { - ASSERT(object); - - cacheReferences++; - return g_object_ref(object); - } - - GObject* object; - unsigned cacheReferences; -}; - -class DOMObjectCacheFrameObserver; -typedef HashMap<WebCore::Frame*, std::unique_ptr<DOMObjectCacheFrameObserver>> DOMObjectCacheFrameObserverMap; - -static DOMObjectCacheFrameObserverMap& domObjectCacheFrameObservers() -{ - static NeverDestroyed<DOMObjectCacheFrameObserverMap> map; - return map; -} - -static DOMObjectCacheFrameObserver& getOrCreateDOMObjectCacheFrameObserver(WebCore::Frame& frame) -{ - DOMObjectCacheFrameObserverMap::AddResult result = domObjectCacheFrameObservers().add(&frame, nullptr); - if (result.isNewEntry) - result.iterator->value = std::make_unique<DOMObjectCacheFrameObserver>(frame); - return *result.iterator->value; -} - -class DOMObjectCacheFrameObserver final: public WebCore::FrameDestructionObserver { -public: - DOMObjectCacheFrameObserver(WebCore::Frame& frame) - : FrameDestructionObserver(&frame) - { - } - - ~DOMObjectCacheFrameObserver() - { - ASSERT(m_objects.isEmpty()); - } - - void addObjectCacheData(DOMObjectCacheData& data) - { - ASSERT(!m_objects.contains(&data)); - - WebCore::DOMWindow* domWindow = m_frame->document()->domWindow(); - if (domWindow && (!m_domWindowObserver || m_domWindowObserver->domWindow() != domWindow)) { - // New DOMWindow, clear the cache and create a new DOMWindowObserver. - clear(); - m_domWindowObserver = std::make_unique<DOMWindowObserver>(*m_frame, *this, domWindow); - } - - m_objects.append(&data); - g_object_weak_ref(data.object, DOMObjectCacheFrameObserver::objectFinalizedCallback, this); - } - -private: - class DOMWindowObserver final: public WebCore::DOMWindowProperty { - WTF_MAKE_FAST_ALLOCATED; - public: - DOMWindowObserver(WebCore::Frame& frame, DOMObjectCacheFrameObserver& frameObserver, WebCore::DOMWindow* window) - : DOMWindowProperty(&frame) - , m_frameObserver(frameObserver) - , m_domWindow(window) - { - ASSERT(m_domWindow); - } - - virtual ~DOMWindowObserver() - { - } - - WebCore::DOMWindow* domWindow() const { return m_domWindow; } - - private: - virtual void willDetachGlobalObjectFromFrame() override - { - // Clear the DOMWindowProperty first, and then notify the Frame observer. - DOMWindowProperty::willDetachGlobalObjectFromFrame(); - m_frameObserver.willDetachGlobalObjectFromFrame(); - } - - DOMObjectCacheFrameObserver& m_frameObserver; - WebCore::DOMWindow* m_domWindow; - }; - - static void objectFinalizedCallback(gpointer userData, GObject* finalizedObject) - { - DOMObjectCacheFrameObserver* observer = static_cast<DOMObjectCacheFrameObserver*>(userData); - for (size_t i = 0; i < observer->m_objects.size(); ++i) { - if (observer->m_objects[i]->object == finalizedObject) { - observer->m_objects.remove(i); - break; - } - } - } - - void clear() - { - if (m_objects.isEmpty()) - return; - - auto objects = std::move(m_objects); - for (auto* data : objects) { - g_object_weak_unref(data->object, DOMObjectCacheFrameObserver::objectFinalizedCallback, this); - data->clearObject(); - } - } - - virtual void willDetachPage() override - { - clear(); - } - - virtual void frameDestroyed() override - { - clear(); - WebCore::Frame* frame = m_frame; - FrameDestructionObserver::frameDestroyed(); - domObjectCacheFrameObservers().remove(frame); - } - - void willDetachGlobalObjectFromFrame() - { - clear(); - m_domWindowObserver = nullptr; - } - - Vector<DOMObjectCacheData*, 8> m_objects; - std::unique_ptr<DOMWindowObserver> m_domWindowObserver; -}; - -typedef HashMap<void*, std::unique_ptr<DOMObjectCacheData>> DOMObjectMap; - -static DOMObjectMap& domObjects() -{ - static NeverDestroyed<DOMObjectMap> staticDOMObjects; - return staticDOMObjects; -} - -void DOMObjectCache::forget(void* objectHandle) -{ - ASSERT(domObjects().contains(objectHandle)); - domObjects().remove(objectHandle); -} - -void* DOMObjectCache::get(void* objectHandle) -{ - DOMObjectCacheData* data = domObjects().get(objectHandle); - return data ? data->refObject() : nullptr; -} - -void DOMObjectCache::put(void* objectHandle, void* wrapper) -{ - DOMObjectMap::AddResult result = domObjects().add(objectHandle, nullptr); - if (result.isNewEntry) - result.iterator->value = std::make_unique<DOMObjectCacheData>(G_OBJECT(wrapper)); -} - -void DOMObjectCache::put(WebCore::Node* objectHandle, void* wrapper) -{ - DOMObjectMap::AddResult result = domObjects().add(objectHandle, nullptr); - if (!result.isNewEntry) - return; - - result.iterator->value = std::make_unique<DOMObjectCacheData>(G_OBJECT(wrapper)); - if (WebCore::Frame* frame = objectHandle->document().frame()) - getOrCreateDOMObjectCacheFrameObserver(*frame).addObjectCacheData(*result.iterator->value); -} - -} diff --git a/Source/WebCore/bindings/gobject/GNUmakefile.am b/Source/WebCore/bindings/gobject/GNUmakefile.am deleted file mode 100644 index 3d5e9dc6f..000000000 --- a/Source/WebCore/bindings/gobject/GNUmakefile.am +++ /dev/null @@ -1,605 +0,0 @@ -webkitgtk_gdom_built_sources += \ - DerivedSources/webkitdom/WebKitDOMAttr.cpp \ - DerivedSources/webkitdom/WebKitDOMAttrPrivate.h \ - DerivedSources/webkitdom/WebKitDOMBarProp.cpp \ - DerivedSources/webkitdom/WebKitDOMBarPropPrivate.h \ - DerivedSources/webkitdom/WebKitDOMBatteryManager.cpp \ - DerivedSources/webkitdom/WebKitDOMBatteryManagerPrivate.h \ - DerivedSources/webkitdom/WebKitDOMBlob.cpp \ - DerivedSources/webkitdom/WebKitDOMBlobPrivate.h \ - DerivedSources/webkitdom/WebKitDOMCDATASection.cpp \ - DerivedSources/webkitdom/WebKitDOMCDATASectionPrivate.h \ - DerivedSources/webkitdom/WebKitDOMCharacterData.cpp \ - DerivedSources/webkitdom/WebKitDOMCharacterDataPrivate.h \ - DerivedSources/webkitdom/WebKitDOMComment.cpp \ - DerivedSources/webkitdom/WebKitDOMCommentPrivate.h \ - DerivedSources/webkitdom/WebKitDOMConsole.cpp \ - DerivedSources/webkitdom/WebKitDOMConsolePrivate.h \ - DerivedSources/webkitdom/WebKitDOMCSSRule.cpp \ - DerivedSources/webkitdom/WebKitDOMCSSRuleList.cpp \ - DerivedSources/webkitdom/WebKitDOMCSSRuleListPrivate.h \ - DerivedSources/webkitdom/WebKitDOMCSSRulePrivate.h \ - DerivedSources/webkitdom/WebKitDOMCSSStyleDeclaration.cpp \ - DerivedSources/webkitdom/WebKitDOMCSSStyleDeclarationPrivate.h \ - DerivedSources/webkitdom/WebKitDOMCSSStyleSheet.cpp \ - DerivedSources/webkitdom/WebKitDOMCSSStyleSheetPrivate.h \ - DerivedSources/webkitdom/WebKitDOMCSSValue.cpp \ - DerivedSources/webkitdom/WebKitDOMCSSValuePrivate.h \ - DerivedSources/webkitdom/WebKitDOMDatabase.cpp \ - DerivedSources/webkitdom/WebKitDOMDatabasePrivate.h \ - DerivedSources/webkitdom/WebKitDOMDocument.cpp \ - DerivedSources/webkitdom/WebKitDOMDocumentFragment.cpp \ - DerivedSources/webkitdom/WebKitDOMDocumentFragmentPrivate.h \ - DerivedSources/webkitdom/WebKitDOMDocumentPrivate.h \ - DerivedSources/webkitdom/WebKitDOMDocumentType.cpp \ - DerivedSources/webkitdom/WebKitDOMDocumentTypePrivate.h \ - DerivedSources/webkitdom/WebKitDOMDOMApplicationCache.cpp \ - DerivedSources/webkitdom/WebKitDOMDOMApplicationCachePrivate.h \ - DerivedSources/webkitdom/WebKitDOMDOMImplementation.cpp \ - DerivedSources/webkitdom/WebKitDOMDOMImplementationPrivate.h \ - DerivedSources/webkitdom/WebKitDOMDOMMimeTypeArray.cpp \ - DerivedSources/webkitdom/WebKitDOMDOMMimeTypeArrayPrivate.h \ - DerivedSources/webkitdom/WebKitDOMDOMMimeType.cpp \ - DerivedSources/webkitdom/WebKitDOMDOMMimeTypePrivate.h \ - DerivedSources/webkitdom/WebKitDOMDOMNamedFlowCollection.cpp \ - DerivedSources/webkitdom/WebKitDOMDOMPluginArray.cpp \ - DerivedSources/webkitdom/WebKitDOMDOMPluginArrayPrivate.h \ - DerivedSources/webkitdom/WebKitDOMDOMPlugin.cpp \ - DerivedSources/webkitdom/WebKitDOMDOMPluginPrivate.h \ - DerivedSources/webkitdom/WebKitDOMDOMSecurityPolicy.cpp \ - DerivedSources/webkitdom/WebKitDOMDOMSecurityPolicyPrivate.h \ - DerivedSources/webkitdom/WebKitDOMDOMSelection.cpp \ - DerivedSources/webkitdom/WebKitDOMDOMSelectionPrivate.h \ - DerivedSources/webkitdom/WebKitDOMDOMStringList.cpp \ - DerivedSources/webkitdom/WebKitDOMDOMStringListPrivate.h \ - DerivedSources/webkitdom/WebKitDOMDOMStringMap.cpp \ - DerivedSources/webkitdom/WebKitDOMDOMStringMapPrivate.h \ - DerivedSources/webkitdom/WebKitDOMDOMSettableTokenList.cpp \ - DerivedSources/webkitdom/WebKitDOMDOMSettableTokenListPrivate.h \ - DerivedSources/webkitdom/WebKitDOMDOMTokenList.cpp \ - DerivedSources/webkitdom/WebKitDOMDOMTokenListPrivate.h \ - DerivedSources/webkitdom/WebKitDOMDOMWindow.cpp \ - DerivedSources/webkitdom/WebKitDOMDOMWindowCSS.cpp \ - DerivedSources/webkitdom/WebKitDOMDOMWindowCSSPrivate.h \ - DerivedSources/webkitdom/WebKitDOMDOMWindowPrivate.h \ - DerivedSources/webkitdom/WebKitDOMElement.cpp \ - DerivedSources/webkitdom/WebKitDOMElementPrivate.h \ - DerivedSources/webkitdom/WebKitDOMEntityReference.cpp \ - DerivedSources/webkitdom/WebKitDOMEntityReferencePrivate.h \ - DerivedSources/webkitdom/WebKitDOMEvent.cpp \ - DerivedSources/webkitdom/WebKitDOMEventPrivate.h \ - DerivedSources/webkitdom/WebKitDOMEventTargetPrivate.h \ - DerivedSources/webkitdom/WebKitDOMFile.cpp \ - DerivedSources/webkitdom/WebKitDOMFileList.cpp \ - DerivedSources/webkitdom/WebKitDOMFileListPrivate.h \ - DerivedSources/webkitdom/WebKitDOMFilePrivate.h \ - DerivedSources/webkitdom/WebKitDOMGamepad.cpp \ - DerivedSources/webkitdom/WebKitDOMGamepadList.cpp \ - DerivedSources/webkitdom/WebKitDOMGamepadListPrivate.h \ - DerivedSources/webkitdom/WebKitDOMGamepadPrivate.h \ - DerivedSources/webkitdom/WebKitDOMGeolocation.cpp \ - DerivedSources/webkitdom/WebKitDOMGeolocationPrivate.h \ - DerivedSources/webkitdom/WebKitDOMHistory.cpp \ - DerivedSources/webkitdom/WebKitDOMHistoryPrivate.h \ - DerivedSources/webkitdom/WebKitDOMHTMLAnchorElement.cpp \ - DerivedSources/webkitdom/WebKitDOMHTMLAnchorElementPrivate.h \ - DerivedSources/webkitdom/WebKitDOMHTMLAppletElement.cpp \ - DerivedSources/webkitdom/WebKitDOMHTMLAppletElementPrivate.h \ - DerivedSources/webkitdom/WebKitDOMHTMLAreaElement.cpp \ - DerivedSources/webkitdom/WebKitDOMHTMLAreaElementPrivate.h \ - DerivedSources/webkitdom/WebKitDOMHTMLBaseElement.cpp \ - DerivedSources/webkitdom/WebKitDOMHTMLBaseElementPrivate.h \ - DerivedSources/webkitdom/WebKitDOMHTMLBaseFontElement.cpp \ - DerivedSources/webkitdom/WebKitDOMHTMLBaseFontElementPrivate.h \ - DerivedSources/webkitdom/WebKitDOMHTMLBodyElement.cpp \ - DerivedSources/webkitdom/WebKitDOMHTMLBodyElementPrivate.h \ - DerivedSources/webkitdom/WebKitDOMHTMLBRElement.cpp \ - DerivedSources/webkitdom/WebKitDOMHTMLBRElementPrivate.h \ - DerivedSources/webkitdom/WebKitDOMHTMLButtonElement.cpp \ - DerivedSources/webkitdom/WebKitDOMHTMLButtonElementPrivate.h \ - DerivedSources/webkitdom/WebKitDOMHTMLCanvasElement.cpp \ - DerivedSources/webkitdom/WebKitDOMHTMLCanvasElementPrivate.h \ - DerivedSources/webkitdom/WebKitDOMHTMLCollection.cpp \ - DerivedSources/webkitdom/WebKitDOMHTMLCollectionPrivate.h \ - DerivedSources/webkitdom/WebKitDOMHTMLDetailsElement.cpp \ - DerivedSources/webkitdom/WebKitDOMHTMLDetailsElementPrivate.h \ - DerivedSources/webkitdom/WebKitDOMHTMLDirectoryElement.cpp \ - DerivedSources/webkitdom/WebKitDOMHTMLDirectoryElementPrivate.h \ - DerivedSources/webkitdom/WebKitDOMHTMLDivElement.cpp \ - DerivedSources/webkitdom/WebKitDOMHTMLDivElementPrivate.h \ - DerivedSources/webkitdom/WebKitDOMHTMLDListElement.cpp \ - DerivedSources/webkitdom/WebKitDOMHTMLDListElementPrivate.h \ - DerivedSources/webkitdom/WebKitDOMHTMLDocument.cpp \ - DerivedSources/webkitdom/WebKitDOMHTMLDocumentPrivate.h \ - DerivedSources/webkitdom/WebKitDOMHTMLElement.cpp \ - DerivedSources/webkitdom/WebKitDOMHTMLElementPrivate.h \ - DerivedSources/webkitdom/WebKitDOMHTMLEmbedElement.cpp \ - DerivedSources/webkitdom/WebKitDOMHTMLEmbedElementPrivate.h \ - DerivedSources/webkitdom/WebKitDOMHTMLFieldSetElement.cpp \ - DerivedSources/webkitdom/WebKitDOMHTMLFieldSetElementPrivate.h \ - DerivedSources/webkitdom/WebKitDOMHTMLFontElement.cpp \ - DerivedSources/webkitdom/WebKitDOMHTMLFontElementPrivate.h \ - DerivedSources/webkitdom/WebKitDOMHTMLFormElement.cpp \ - DerivedSources/webkitdom/WebKitDOMHTMLFormElementPrivate.h \ - DerivedSources/webkitdom/WebKitDOMHTMLFrameElement.cpp \ - DerivedSources/webkitdom/WebKitDOMHTMLFrameElementPrivate.h \ - DerivedSources/webkitdom/WebKitDOMHTMLFrameSetElement.cpp \ - DerivedSources/webkitdom/WebKitDOMHTMLFrameSetElementPrivate.h \ - DerivedSources/webkitdom/WebKitDOMHTMLHeadElement.cpp \ - DerivedSources/webkitdom/WebKitDOMHTMLHeadElementPrivate.h \ - DerivedSources/webkitdom/WebKitDOMHTMLHeadingElement.cpp \ - DerivedSources/webkitdom/WebKitDOMHTMLHeadingElementPrivate.h \ - DerivedSources/webkitdom/WebKitDOMHTMLHRElement.cpp \ - DerivedSources/webkitdom/WebKitDOMHTMLHRElementPrivate.h \ - DerivedSources/webkitdom/WebKitDOMHTMLHtmlElement.cpp \ - DerivedSources/webkitdom/WebKitDOMHTMLHtmlElementPrivate.h \ - DerivedSources/webkitdom/WebKitDOMHTMLIFrameElement.cpp \ - DerivedSources/webkitdom/WebKitDOMHTMLIFrameElementPrivate.h \ - DerivedSources/webkitdom/WebKitDOMHTMLImageElement.cpp \ - DerivedSources/webkitdom/WebKitDOMHTMLImageElementPrivate.h \ - DerivedSources/webkitdom/WebKitDOMHTMLInputElement.cpp \ - DerivedSources/webkitdom/WebKitDOMHTMLInputElementPrivate.h \ - DerivedSources/webkitdom/WebKitDOMHTMLKeygenElement.cpp \ - DerivedSources/webkitdom/WebKitDOMHTMLKeygenElementPrivate.h \ - DerivedSources/webkitdom/WebKitDOMHTMLLabelElement.cpp \ - DerivedSources/webkitdom/WebKitDOMHTMLLabelElementPrivate.h \ - DerivedSources/webkitdom/WebKitDOMHTMLLegendElement.cpp \ - DerivedSources/webkitdom/WebKitDOMHTMLLegendElementPrivate.h \ - DerivedSources/webkitdom/WebKitDOMHTMLLIElement.cpp \ - DerivedSources/webkitdom/WebKitDOMHTMLLIElementPrivate.h \ - DerivedSources/webkitdom/WebKitDOMHTMLLinkElement.cpp \ - DerivedSources/webkitdom/WebKitDOMHTMLLinkElementPrivate.h \ - DerivedSources/webkitdom/WebKitDOMHTMLMapElement.cpp \ - DerivedSources/webkitdom/WebKitDOMHTMLMapElementPrivate.h \ - DerivedSources/webkitdom/WebKitDOMHTMLMarqueeElement.cpp \ - DerivedSources/webkitdom/WebKitDOMHTMLMarqueeElementPrivate.h \ - DerivedSources/webkitdom/WebKitDOMHTMLMediaElement.cpp \ - DerivedSources/webkitdom/WebKitDOMHTMLMediaElementPrivate.h \ - DerivedSources/webkitdom/WebKitDOMHTMLMenuElement.cpp \ - DerivedSources/webkitdom/WebKitDOMHTMLMenuElementPrivate.h \ - DerivedSources/webkitdom/WebKitDOMHTMLMetaElement.cpp \ - DerivedSources/webkitdom/WebKitDOMHTMLMetaElementPrivate.h \ - DerivedSources/webkitdom/WebKitDOMHTMLModElement.cpp \ - DerivedSources/webkitdom/WebKitDOMHTMLModElementPrivate.h \ - DerivedSources/webkitdom/WebKitDOMHTMLObjectElement.cpp \ - DerivedSources/webkitdom/WebKitDOMHTMLObjectElementPrivate.h \ - DerivedSources/webkitdom/WebKitDOMHTMLOListElement.cpp \ - DerivedSources/webkitdom/WebKitDOMHTMLOListElementPrivate.h \ - DerivedSources/webkitdom/WebKitDOMHTMLOptGroupElement.cpp \ - DerivedSources/webkitdom/WebKitDOMHTMLOptGroupElementPrivate.h \ - DerivedSources/webkitdom/WebKitDOMHTMLOptionElement.cpp \ - DerivedSources/webkitdom/WebKitDOMHTMLOptionElementPrivate.h \ - DerivedSources/webkitdom/WebKitDOMHTMLOptionsCollection.cpp \ - DerivedSources/webkitdom/WebKitDOMHTMLOptionsCollectionPrivate.h \ - DerivedSources/webkitdom/WebKitDOMHTMLParagraphElement.cpp \ - DerivedSources/webkitdom/WebKitDOMHTMLParagraphElementPrivate.h \ - DerivedSources/webkitdom/WebKitDOMHTMLParamElement.cpp \ - DerivedSources/webkitdom/WebKitDOMHTMLParamElementPrivate.h \ - DerivedSources/webkitdom/WebKitDOMHTMLPreElement.cpp \ - DerivedSources/webkitdom/WebKitDOMHTMLPreElementPrivate.h \ - DerivedSources/webkitdom/WebKitDOMHTMLQuoteElement.cpp \ - DerivedSources/webkitdom/WebKitDOMHTMLQuoteElementPrivate.h \ - DerivedSources/webkitdom/WebKitDOMHTMLScriptElement.cpp \ - DerivedSources/webkitdom/WebKitDOMHTMLScriptElementPrivate.h \ - DerivedSources/webkitdom/WebKitDOMHTMLSelectElement.cpp \ - DerivedSources/webkitdom/WebKitDOMHTMLSelectElementPrivate.h \ - DerivedSources/webkitdom/WebKitDOMHTMLStyleElement.cpp \ - DerivedSources/webkitdom/WebKitDOMHTMLStyleElementPrivate.h \ - DerivedSources/webkitdom/WebKitDOMHTMLTableCaptionElement.cpp \ - DerivedSources/webkitdom/WebKitDOMHTMLTableCaptionElementPrivate.h \ - DerivedSources/webkitdom/WebKitDOMHTMLTableCellElement.cpp \ - DerivedSources/webkitdom/WebKitDOMHTMLTableCellElementPrivate.h \ - DerivedSources/webkitdom/WebKitDOMHTMLTableColElement.cpp \ - DerivedSources/webkitdom/WebKitDOMHTMLTableColElementPrivate.h \ - DerivedSources/webkitdom/WebKitDOMHTMLTableElement.cpp \ - DerivedSources/webkitdom/WebKitDOMHTMLTableElementPrivate.h \ - DerivedSources/webkitdom/WebKitDOMHTMLTableRowElement.cpp \ - DerivedSources/webkitdom/WebKitDOMHTMLTableRowElementPrivate.h \ - DerivedSources/webkitdom/WebKitDOMHTMLTableSectionElement.cpp \ - DerivedSources/webkitdom/WebKitDOMHTMLTableSectionElementPrivate.h \ - DerivedSources/webkitdom/WebKitDOMHTMLTextAreaElement.cpp \ - DerivedSources/webkitdom/WebKitDOMHTMLTextAreaElementPrivate.h \ - DerivedSources/webkitdom/WebKitDOMHTMLTitleElement.cpp \ - DerivedSources/webkitdom/WebKitDOMHTMLTitleElementPrivate.h \ - DerivedSources/webkitdom/WebKitDOMHTMLUListElement.cpp \ - DerivedSources/webkitdom/WebKitDOMHTMLUListElementPrivate.h \ - DerivedSources/webkitdom/WebKitDOMKeyboardEvent.cpp \ - DerivedSources/webkitdom/WebKitDOMKeyboardEventPrivate.h \ - DerivedSources/webkitdom/WebKitDOMLocation.cpp \ - DerivedSources/webkitdom/WebKitDOMLocationPrivate.h \ - DerivedSources/webkitdom/WebKitDOMMediaController.cpp \ - DerivedSources/webkitdom/WebKitDOMMediaControllerPrivate.h \ - DerivedSources/webkitdom/WebKitDOMMediaError.cpp \ - DerivedSources/webkitdom/WebKitDOMMediaErrorPrivate.h \ - DerivedSources/webkitdom/WebKitDOMMediaList.cpp \ - DerivedSources/webkitdom/WebKitDOMMediaListPrivate.h \ - DerivedSources/webkitdom/WebKitDOMMediaQueryList.cpp \ - DerivedSources/webkitdom/WebKitDOMMediaQueryListPrivate.h \ - DerivedSources/webkitdom/WebKitDOMMessagePort.cpp \ - DerivedSources/webkitdom/WebKitDOMMessagePortPrivate.h \ - DerivedSources/webkitdom/WebKitDOMMouseEvent.cpp \ - DerivedSources/webkitdom/WebKitDOMMouseEventPrivate.h \ - DerivedSources/webkitdom/WebKitDOMNamedNodeMap.cpp \ - DerivedSources/webkitdom/WebKitDOMNamedNodeMapPrivate.h \ - DerivedSources/webkitdom/WebKitDOMNavigator.cpp \ - DerivedSources/webkitdom/WebKitDOMNavigatorPrivate.h \ - DerivedSources/webkitdom/WebKitDOMNode.cpp \ - DerivedSources/webkitdom/WebKitDOMNodeFilter.cpp \ - DerivedSources/webkitdom/WebKitDOMNodeFilterPrivate.h \ - DerivedSources/webkitdom/WebKitDOMNodeIterator.cpp \ - DerivedSources/webkitdom/WebKitDOMNodeIteratorPrivate.h \ - DerivedSources/webkitdom/WebKitDOMNodeList.cpp \ - DerivedSources/webkitdom/WebKitDOMNodeListPrivate.h \ - DerivedSources/webkitdom/WebKitDOMNodePrivate.h \ - DerivedSources/webkitdom/WebKitDOMPerformance.cpp \ - DerivedSources/webkitdom/WebKitDOMPerformanceEntry.cpp \ - DerivedSources/webkitdom/WebKitDOMPerformanceEntryList.cpp \ - DerivedSources/webkitdom/WebKitDOMPerformanceEntryPrivate.h \ - DerivedSources/webkitdom/WebKitDOMPerformancePrivate.h \ - DerivedSources/webkitdom/WebKitDOMPerformanceNavigation.cpp \ - DerivedSources/webkitdom/WebKitDOMPerformanceNavigationPrivate.h \ - DerivedSources/webkitdom/WebKitDOMPerformanceTiming.cpp \ - DerivedSources/webkitdom/WebKitDOMPerformanceTimingPrivate.h \ - DerivedSources/webkitdom/WebKitDOMProcessingInstruction.cpp \ - DerivedSources/webkitdom/WebKitDOMProcessingInstructionPrivate.h \ - DerivedSources/webkitdom/WebKitDOMRange.cpp \ - DerivedSources/webkitdom/WebKitDOMRangePrivate.h \ - DerivedSources/webkitdom/WebKitDOMScreen.cpp \ - DerivedSources/webkitdom/WebKitDOMScreenPrivate.h \ - DerivedSources/webkitdom/WebKitDOMShadowRoot.cpp \ - DerivedSources/webkitdom/WebKitDOMShadowRootPrivate.h \ - DerivedSources/webkitdom/WebKitDOMStorage.cpp \ - DerivedSources/webkitdom/WebKitDOMStorageInfo.cpp \ - DerivedSources/webkitdom/WebKitDOMStorageInfoPrivate.h \ - DerivedSources/webkitdom/WebKitDOMStoragePrivate.h \ - DerivedSources/webkitdom/WebKitDOMStorageQuota.cpp \ - DerivedSources/webkitdom/WebKitDOMStorageQuotaPrivate.h \ - DerivedSources/webkitdom/WebKitDOMStyleMedia.cpp \ - DerivedSources/webkitdom/WebKitDOMStyleMediaPrivate.h \ - DerivedSources/webkitdom/WebKitDOMStyleSheet.cpp \ - DerivedSources/webkitdom/WebKitDOMStyleSheetList.cpp \ - DerivedSources/webkitdom/WebKitDOMStyleSheetListPrivate.h \ - DerivedSources/webkitdom/WebKitDOMStyleSheetPrivate.h \ - DerivedSources/webkitdom/WebKitDOMText.cpp \ - DerivedSources/webkitdom/WebKitDOMTextPrivate.h \ - DerivedSources/webkitdom/WebKitDOMTouch.cpp \ - DerivedSources/webkitdom/WebKitDOMTouchPrivate.h \ - DerivedSources/webkitdom/WebKitDOMTimeRanges.cpp \ - DerivedSources/webkitdom/WebKitDOMTimeRangesPrivate.h \ - DerivedSources/webkitdom/WebKitDOMTreeWalker.cpp \ - DerivedSources/webkitdom/WebKitDOMTreeWalkerPrivate.h \ - DerivedSources/webkitdom/WebKitDOMUIEvent.cpp \ - DerivedSources/webkitdom/WebKitDOMUIEventPrivate.h \ - DerivedSources/webkitdom/WebKitDOMValidityState.cpp \ - DerivedSources/webkitdom/WebKitDOMValidityStatePrivate.h \ - DerivedSources/webkitdom/WebKitDOMWebKitPoint.cpp \ - DerivedSources/webkitdom/WebKitDOMWebKitPointPrivate.h \ - DerivedSources/webkitdom/WebKitDOMWebKitNamedFlow.cpp \ - DerivedSources/webkitdom/WebKitDOMWheelEvent.cpp \ - DerivedSources/webkitdom/WebKitDOMWheelEventPrivate.h \ - DerivedSources/webkitdom/WebKitDOMXPathExpression.cpp \ - DerivedSources/webkitdom/WebKitDOMXPathExpressionPrivate.h \ - DerivedSources/webkitdom/WebKitDOMXPathNSResolver.cpp \ - DerivedSources/webkitdom/WebKitDOMXPathNSResolverPrivate.h \ - DerivedSources/webkitdom/WebKitDOMXPathResult.cpp \ - DerivedSources/webkitdom/WebKitDOMXPathResultPrivate.h - -webkitgtk_gdom_built_h_api += \ - DerivedSources/webkitdom/WebKitDOMBatteryManager.h \ - DerivedSources/webkitdom/WebKitDOMCSSRule.h \ - DerivedSources/webkitdom/WebKitDOMCSSRuleList.h \ - DerivedSources/webkitdom/WebKitDOMCSSStyleDeclaration.h \ - DerivedSources/webkitdom/WebKitDOMCSSStyleSheet.h \ - DerivedSources/webkitdom/WebKitDOMCSSValue.h \ - DerivedSources/webkitdom/WebKitDOMMediaController.h \ - DerivedSources/webkitdom/WebKitDOMMediaList.h \ - DerivedSources/webkitdom/WebKitDOMMediaQueryList.h \ - DerivedSources/webkitdom/WebKitDOMStyleMedia.h \ - DerivedSources/webkitdom/WebKitDOMStyleSheet.h \ - DerivedSources/webkitdom/WebKitDOMStyleSheetList.h \ - DerivedSources/webkitdom/WebKitDOMAttr.h \ - DerivedSources/webkitdom/WebKitDOMCDATASection.h \ - DerivedSources/webkitdom/WebKitDOMCharacterData.h \ - DerivedSources/webkitdom/WebKitDOMComment.h \ - DerivedSources/webkitdom/WebKitDOMDocument.h \ - DerivedSources/webkitdom/WebKitDOMDocumentFragment.h \ - DerivedSources/webkitdom/WebKitDOMDocumentType.h \ - DerivedSources/webkitdom/WebKitDOMDOMImplementation.h \ - DerivedSources/webkitdom/WebKitDOMDOMNamedFlowCollection.h \ - DerivedSources/webkitdom/WebKitDOMDOMSettableTokenList.h \ - DerivedSources/webkitdom/WebKitDOMDOMSecurityPolicy.h \ - DerivedSources/webkitdom/WebKitDOMDOMStringList.h \ - DerivedSources/webkitdom/WebKitDOMDOMStringMap.h \ - DerivedSources/webkitdom/WebKitDOMDOMTokenList.h \ - DerivedSources/webkitdom/WebKitDOMElement.h \ - DerivedSources/webkitdom/WebKitDOMEntityReference.h \ - DerivedSources/webkitdom/WebKitDOMEvent.h \ - DerivedSources/webkitdom/WebKitDOMKeyboardEvent.h \ - DerivedSources/webkitdom/WebKitDOMMessagePort.h \ - DerivedSources/webkitdom/WebKitDOMMouseEvent.h \ - DerivedSources/webkitdom/WebKitDOMNamedNodeMap.h \ - DerivedSources/webkitdom/WebKitDOMNode.h \ - DerivedSources/webkitdom/WebKitDOMNodeFilter.h \ - DerivedSources/webkitdom/WebKitDOMNodeIterator.h \ - DerivedSources/webkitdom/WebKitDOMNodeList.h \ - DerivedSources/webkitdom/WebKitDOMProcessingInstruction.h \ - DerivedSources/webkitdom/WebKitDOMRange.h \ - DerivedSources/webkitdom/WebKitDOMText.h \ - DerivedSources/webkitdom/WebKitDOMTouch.h \ - DerivedSources/webkitdom/WebKitDOMTreeWalker.h \ - DerivedSources/webkitdom/WebKitDOMUIEvent.h \ - DerivedSources/webkitdom/WebKitDOMBlob.h \ - DerivedSources/webkitdom/WebKitDOMFile.h \ - DerivedSources/webkitdom/WebKitDOMFileList.h \ - DerivedSources/webkitdom/WebKitDOMGamepad.h \ - DerivedSources/webkitdom/WebKitDOMGamepadList.h \ - DerivedSources/webkitdom/WebKitDOMGeolocation.h \ - DerivedSources/webkitdom/WebKitDOMHTMLAnchorElement.h \ - DerivedSources/webkitdom/WebKitDOMHTMLAppletElement.h \ - DerivedSources/webkitdom/WebKitDOMHTMLAreaElement.h \ - DerivedSources/webkitdom/WebKitDOMHTMLBaseElement.h \ - DerivedSources/webkitdom/WebKitDOMHTMLBaseFontElement.h \ - DerivedSources/webkitdom/WebKitDOMHTMLBodyElement.h \ - DerivedSources/webkitdom/WebKitDOMHTMLBRElement.h \ - DerivedSources/webkitdom/WebKitDOMHTMLButtonElement.h \ - DerivedSources/webkitdom/WebKitDOMHTMLCanvasElement.h \ - DerivedSources/webkitdom/WebKitDOMHTMLCollection.h \ - DerivedSources/webkitdom/WebKitDOMHTMLDirectoryElement.h \ - DerivedSources/webkitdom/WebKitDOMHTMLDivElement.h \ - DerivedSources/webkitdom/WebKitDOMHTMLDListElement.h \ - DerivedSources/webkitdom/WebKitDOMHTMLDocument.h \ - DerivedSources/webkitdom/WebKitDOMHTMLDetailsElement.h \ - DerivedSources/webkitdom/WebKitDOMHTMLElement.h \ - DerivedSources/webkitdom/WebKitDOMHTMLEmbedElement.h \ - DerivedSources/webkitdom/WebKitDOMHTMLFieldSetElement.h \ - DerivedSources/webkitdom/WebKitDOMHTMLFontElement.h \ - DerivedSources/webkitdom/WebKitDOMHTMLFormElement.h \ - DerivedSources/webkitdom/WebKitDOMHTMLFrameElement.h \ - DerivedSources/webkitdom/WebKitDOMHTMLFrameSetElement.h \ - DerivedSources/webkitdom/WebKitDOMHTMLHeadElement.h \ - DerivedSources/webkitdom/WebKitDOMHTMLHeadingElement.h \ - DerivedSources/webkitdom/WebKitDOMHTMLHRElement.h \ - DerivedSources/webkitdom/WebKitDOMHTMLHtmlElement.h \ - DerivedSources/webkitdom/WebKitDOMHTMLIFrameElement.h \ - DerivedSources/webkitdom/WebKitDOMHTMLImageElement.h \ - DerivedSources/webkitdom/WebKitDOMHTMLInputElement.h \ - DerivedSources/webkitdom/WebKitDOMHTMLKeygenElement.h \ - DerivedSources/webkitdom/WebKitDOMHTMLLabelElement.h \ - DerivedSources/webkitdom/WebKitDOMHTMLLegendElement.h \ - DerivedSources/webkitdom/WebKitDOMHTMLLIElement.h \ - DerivedSources/webkitdom/WebKitDOMHTMLLinkElement.h \ - DerivedSources/webkitdom/WebKitDOMHTMLMapElement.h \ - DerivedSources/webkitdom/WebKitDOMHTMLMarqueeElement.h \ - DerivedSources/webkitdom/WebKitDOMHTMLMediaElement.h \ - DerivedSources/webkitdom/WebKitDOMHTMLMenuElement.h \ - DerivedSources/webkitdom/WebKitDOMHTMLMetaElement.h \ - DerivedSources/webkitdom/WebKitDOMHTMLModElement.h \ - DerivedSources/webkitdom/WebKitDOMHTMLObjectElement.h \ - DerivedSources/webkitdom/WebKitDOMHTMLOListElement.h \ - DerivedSources/webkitdom/WebKitDOMHTMLOptGroupElement.h \ - DerivedSources/webkitdom/WebKitDOMHTMLOptionElement.h \ - DerivedSources/webkitdom/WebKitDOMHTMLOptionsCollection.h \ - DerivedSources/webkitdom/WebKitDOMHTMLParagraphElement.h \ - DerivedSources/webkitdom/WebKitDOMHTMLParamElement.h \ - DerivedSources/webkitdom/WebKitDOMHTMLPreElement.h \ - DerivedSources/webkitdom/WebKitDOMHTMLQuoteElement.h \ - DerivedSources/webkitdom/WebKitDOMHTMLScriptElement.h \ - DerivedSources/webkitdom/WebKitDOMHTMLSelectElement.h \ - DerivedSources/webkitdom/WebKitDOMHTMLStyleElement.h \ - DerivedSources/webkitdom/WebKitDOMHTMLTableElement.h \ - DerivedSources/webkitdom/WebKitDOMHTMLTableCaptionElement.h \ - DerivedSources/webkitdom/WebKitDOMHTMLTableColElement.h \ - DerivedSources/webkitdom/WebKitDOMHTMLTableSectionElement.h \ - DerivedSources/webkitdom/WebKitDOMHTMLTableCellElement.h \ - DerivedSources/webkitdom/WebKitDOMHTMLTextAreaElement.h \ - DerivedSources/webkitdom/WebKitDOMHTMLTitleElement.h \ - DerivedSources/webkitdom/WebKitDOMHTMLTableRowElement.h \ - DerivedSources/webkitdom/WebKitDOMHTMLUListElement.h \ - DerivedSources/webkitdom/WebKitDOMMediaError.h \ - DerivedSources/webkitdom/WebKitDOMTimeRanges.h \ - DerivedSources/webkitdom/WebKitDOMValidityState.h \ - DerivedSources/webkitdom/WebKitDOMDOMApplicationCache.h \ - DerivedSources/webkitdom/WebKitDOMBarProp.h \ - DerivedSources/webkitdom/WebKitDOMConsole.h \ - DerivedSources/webkitdom/WebKitDOMCustom.h \ - DerivedSources/webkitdom/WebKitDOMDeprecated.h \ - DerivedSources/webkitdom/WebKitDOMDOMWindowCSS.h \ - DerivedSources/webkitdom/WebKitDOMDOMWindow.h \ - DerivedSources/webkitdom/WebKitDOMDOMSelection.h \ - DerivedSources/webkitdom/WebKitDOMEventTarget.h \ - DerivedSources/webkitdom/WebKitDOMHistory.h \ - DerivedSources/webkitdom/WebKitDOMLocation.h \ - DerivedSources/webkitdom/WebKitDOMObject.h \ - DerivedSources/webkitdom/WebKitDOMNavigator.h \ - DerivedSources/webkitdom/WebKitDOMScreen.h \ - DerivedSources/webkitdom/WebKitDOMShadowRoot.h \ - DerivedSources/webkitdom/WebKitDOMWebKitPoint.h \ - DerivedSources/webkitdom/WebKitDOMWebKitNamedFlow.h \ - DerivedSources/webkitdom/WebKitDOMDOMMimeType.h \ - DerivedSources/webkitdom/WebKitDOMDOMMimeTypeArray.h \ - DerivedSources/webkitdom/WebKitDOMDOMPlugin.h \ - DerivedSources/webkitdom/WebKitDOMDOMPluginArray.h \ - DerivedSources/webkitdom/WebKitDOMDatabase.h \ - DerivedSources/webkitdom/WebKitDOMStorage.h \ - DerivedSources/webkitdom/WebKitDOMStorageInfo.h \ - DerivedSources/webkitdom/WebKitDOMStorageQuota.h \ - DerivedSources/webkitdom/WebKitDOMXPathExpression.h \ - DerivedSources/webkitdom/WebKitDOMXPathNSResolver.h \ - DerivedSources/webkitdom/WebKitDOMXPathResult.h \ - DerivedSources/webkitdom/WebKitDOMPerformance.h \ - DerivedSources/webkitdom/WebKitDOMPerformanceEntry.h \ - DerivedSources/webkitdom/WebKitDOMPerformanceEntryList.h \ - DerivedSources/webkitdom/WebKitDOMPerformanceNavigation.h \ - DerivedSources/webkitdom/WebKitDOMPerformanceTiming.h \ - DerivedSources/webkitdom/WebKitDOMWheelEvent.h \ - DerivedSources/webkitdom/webkitdom.h \ - DerivedSources/webkitdom/webkitdomdefines.h - -if ENABLE_VIDEO -webkitgtk_gdom_built_h_api += \ - DerivedSources/webkitdom/WebKitDOMAudioTrack.h \ - DerivedSources/webkitdom/WebKitDOMAudioTrackList.h \ - DerivedSources/webkitdom/WebKitDOMHTMLAudioElement.h \ - DerivedSources/webkitdom/WebKitDOMHTMLVideoElement.h \ - DerivedSources/webkitdom/WebKitDOMTextTrack.h \ - DerivedSources/webkitdom/WebKitDOMTextTrackList.h \ - DerivedSources/webkitdom/WebKitDOMTextTrackCue.h \ - DerivedSources/webkitdom/WebKitDOMTextTrackCueList.h \ - DerivedSources/webkitdom/WebKitDOMTrackEvent.h \ - DerivedSources/webkitdom/WebKitDOMVideoPlaybackQuality.h \ - DerivedSources/webkitdom/WebKitDOMVideoTrack.h \ - DerivedSources/webkitdom/WebKitDOMVideoTrackList.h -webkitgtk_gdom_built_sources += \ - DerivedSources/webkitdom/WebKitDOMHTMLAudioElement.cpp \ - DerivedSources/webkitdom/WebKitDOMHTMLAudioElementPrivate.h \ - DerivedSources/webkitdom/WebKitDOMHTMLVideoElement.cpp \ - DerivedSources/webkitdom/WebKitDOMHTMLVideoElementPrivate.h \ - DerivedSources/webkitdom/WebKitDOMAudioTrack.cpp \ - DerivedSources/webkitdom/WebKitDOMAudioTrackList.cpp \ - DerivedSources/webkitdom/WebKitDOMTextTrack.cpp \ - DerivedSources/webkitdom/WebKitDOMTextTrackPrivate.h \ - DerivedSources/webkitdom/WebKitDOMTextTrackList.cpp \ - DerivedSources/webkitdom/WebKitDOMTextTrackListPrivate.h \ - DerivedSources/webkitdom/WebKitDOMTextTrackCue.cpp \ - DerivedSources/webkitdom/WebKitDOMTextTrackCuePrivate.h \ - DerivedSources/webkitdom/WebKitDOMTextTrackCueList.cpp \ - DerivedSources/webkitdom/WebKitDOMTextTrackCueListPrivate.h \ - DerivedSources/webkitdom/WebKitDOMVideoPlaybackQuality.cpp \ - DerivedSources/webkitdom/WebKitDOMVideoTrack.cpp \ - DerivedSources/webkitdom/WebKitDOMVideoTrackList.cpp \ - DerivedSources/webkitdom/WebKitDOMTrackEvent.cpp \ - DerivedSources/webkitdom/WebKitDOMTrackEventPrivate.h -endif - -BUILT_SOURCES += \ - $(webkitgtk_gdom_built_h_api) \ - $(webkitgtk_gdom_built_sources) - -gdom_class_list := $(subst WebKitDOM,, $(filter-out %Private, $(basename $(notdir $(webkitgtk_gdom_built_sources))))) -gdom_class_list += Custom EventTarget Object Deprecated -DerivedSources/webkitdom/webkitdom.h: $(WebCore)/bindings/scripts/gobject-generate-headers.pl $(WebCore)/bindings/gobject/GNUmakefile.am - $(AM_V_GEN)echo $(gdom_class_list) | $(PERL) $< gdom > $@ - -DerivedSources/webkitdom/webkitdomdefines.h: $(WebCore)/bindings/scripts/gobject-generate-headers.pl $(WebCore)/bindings/gobject/GNUmakefile.am - $(AM_V_GEN)echo $(gdom_class_list) | $(PERL) $< defines > $@ - -gdom_symbol_files += $(patsubst %.h,%.symbols, $(filter DerivedSources/webkitdom/WebKitDOM%.h, $(webkitgtk_gdom_built_h_api))) - -$(top_builddir)/DerivedSources/webkitdom/WebKitDOMObject.symbols: $(WebCore)/bindings/gobject/WebKitDOMObject.symbols - $(AM_V_GEN)cp -f $< $@ - -$(top_builddir)/DerivedSources/webkitdom/WebKitDOMEventTarget.symbols: $(WebCore)/bindings/gobject/WebKitDOMEventTarget.symbols - $(AM_V_GEN)cp -f $< $@ - -$(top_builddir)/DerivedSources/webkitdom/WebKitDOMCustom.symbols: $(WebCore)/bindings/gobject/WebKitDOMCustom.symbols - $(AM_V_GEN)cp -f $< $@ - -$(top_builddir)/DerivedSources/webkitdom/WebKitDOMDeprecated.symbols: $(WebCore)/bindings/gobject/WebKitDOMDeprecated.symbols - $(AM_V_GEN)cp -f $< $@ - -DerivedSources/webkitdom/WebKitDOM%.symbols: DerivedSources/webkitdom/WebKitDOM%.h - @true - -EXTRA_DIST += \ - $(WebCore)/bindings/gobject/WebKitDOMCustom.symbols \ - $(WebCore)/bindings/gobject/WebKitDOMDeprecated.symbols \ - $(WebCore)/bindings/gobject/WebKitDOMEventTarget.symbols \ - $(WebCore)/bindings/gobject/WebKitDOMObject.symbols \ - $(WebCore)/bindings/gobject/webkitdom.symbols - -CLEAN_FILES = \ - $(gdom_symbol_files) - -# Because WebCore/bindings/gobject/WebKitDOMObject.h is static source but is also a distributed header -# required by other distributed headers (both static and auto-generated), need to move this to the -# DerivedSources/webkitdom directory. The reason is that we want all header files distributed in the -# include/webkit-x.y/webkitdom directory, but do not want to name the WebCore/bindings/gobject directory -# "webkitdom", as that's a bit presumptuous for a GTK binding. -$(top_builddir)/DerivedSources/webkitdom/WebKitDOMObject.h: $(WebCore)/bindings/gobject/WebKitDOMObject.h - $(AM_V_GEN)cp -f $< $@ - -$(top_builddir)/DerivedSources/webkitdom/WebKitDOMEventTarget.h: $(WebCore)/bindings/gobject/WebKitDOMEventTarget.h - $(AM_V_GEN)cp -f $< $@ - -$(top_builddir)/DerivedSources/webkitdom/WebKitDOMEventTargetPrivate.h: $(WebCore)/bindings/gobject/WebKitDOMEventTargetPrivate.h - $(AM_V_GEN)cp -f $< $@ - -$(top_builddir)/DerivedSources/webkitdom/WebKitDOMCustom.h: $(WebCore)/bindings/gobject/WebKitDOMCustom.h - $(AM_V_GEN)cp -f $< $@ - -$(top_builddir)/DerivedSources/webkitdom/WebKitDOMDeprecated.h: $(WebCore)/bindings/gobject/WebKitDOMDeprecated.h - $(AM_V_GEN)cp -f $< $@ - -# Filter out SVG and IndexedDB for now -gdom_feature_defines := $(filter-out ENABLE_INDEXED_DATABASE=1, $(filter-out ENABLE_SVG%, $(feature_defines))) ENABLE_INDEXED_DATABASE=0 -DerivedSources/webkitdom/WebKitDOM%.cpp DerivedSources/webkitdom/WebKitDOM%.h DerivedSources/webkitdom/WebKitDOM%Private.h: %.idl $(SCRIPTS_FOR_GENERATE_BINDINGS) $(WebCore)/bindings/scripts/CodeGeneratorGObject.pm $(WebCore)/bindings/gobject/GNUmakefile.am $(supplemental_dependency_file) - $(AM_V_GEN)$(PERL) -I$(WebCore)/bindings/scripts $(WebCore)/bindings/scripts/generate-bindings.pl --include $(WebCore)/Modules --include $(WebCore)/dom --include $(WebCore)/html --include $(WebCore)/css --include $(WebCore)/page --include $(WebCore)/fileapi --include $(WebCore)/xml --include $(WebCore)/svg --outputDir "$(GENSOURCES_WEBKITDOM)" --defines "LANGUAGE_GOBJECT=1 $(gdom_feature_defines)" --generator GObject --supplementalDependencyFile $(supplemental_dependency_file) $< - -libwebkitdomincludedir = $(libwebkitgtkincludedir)/webkitdom -nodist_libwebkitdominclude_HEADERS = \ - $(webkitgtk_gdom_built_h_api) - -noinst_LTLIBRARIES += \ - libGObjectDOMBindings.la - -nodist_libGObjectDOMBindings_la_SOURCES = \ - $(webkitgtk_gdom_built_sources) - -libGObjectDOMBindings_la_SOURCES = \ - Source/WebCore/bindings/gobject/ConvertToUTF8String.cpp \ - Source/WebCore/bindings/gobject/ConvertToUTF8String.h \ - Source/WebCore/bindings/gobject/DOMObjectCache.cpp \ - Source/WebCore/bindings/gobject/DOMObjectCache.h \ - Source/WebCore/bindings/gobject/GObjectEventListener.cpp \ - Source/WebCore/bindings/gobject/GObjectEventListener.h \ - Source/WebCore/bindings/gobject/WebKitDOMCustom.cpp \ - Source/WebCore/bindings/gobject/WebKitDOMCustom.h \ - Source/WebCore/bindings/gobject/WebKitDOMDeprecated.cpp \ - Source/WebCore/bindings/gobject/WebKitDOMDeprecated.h \ - Source/WebCore/bindings/gobject/WebKitDOMEventTarget.cpp \ - Source/WebCore/bindings/gobject/WebKitDOMEventTarget.h \ - Source/WebCore/bindings/gobject/WebKitDOMEventTargetPrivate.h \ - Source/WebCore/bindings/gobject/WebKitDOMHTMLPrivate.cpp \ - Source/WebCore/bindings/gobject/WebKitDOMHTMLPrivate.h \ - Source/WebCore/bindings/gobject/WebKitDOMObject.cpp \ - Source/WebCore/bindings/gobject/WebKitDOMObject.h \ - Source/WebCore/bindings/gobject/WebKitDOMPrivate.cpp \ - Source/WebCore/bindings/gobject/WebKitDOMPrivate.h - -libGObjectDOMBindings_la_CXXFLAGS = \ - -fvisibility-inlines-hidden \ - $(global_cxxflags) - -libGObjectDOMBindings_la_CFLAGS = \ - -fvisibility=hidden \ - $(global_cflags) - -webkitgtk_gdom_include_dirs = \ - -I$(WebCore)/bindings \ - -I$(WebCore)/bindings/gobject \ - -I$(GENSOURCES_WEBKITDOM) - -libGObjectDOMBindings_la_CPPFLAGS = \ - -DBUILDING_WebCore \ - -DBUILDING_WEBKIT \ - $(webkitgtk_gdom_include_dirs) \ - $(global_cppflags) \ - $(platform_cppflags) \ - $(platformgtk_cppflags) \ - $(webcore_cppflags) \ - $(webcoregtk_cppflags) \ - $(javascriptcore_cppflags) \ - $(CAIRO_CFLAGS) \ - $(FREETYPE_CFLAGS) \ - $(GLIB_CFLAGS) \ - $(LIBSOUP_CFLAGS) - -gtkdoc-webkitdom.cfg: $(WebCore)/bindings/gobject/GNUmakefile.am $(srcdir)/Tools/gtk/GNUmakefile.am - $(AM_V_GEN)echo "[webkitdomgtk]" > $@ && \ - echo "pkgconfig_file=$(webkitdom_pkgconfig_file)" >> $@ && \ - echo "namespace=webkit_dom" >> $@ && \ - echo "doc_dir=DerivedSources/webkitdom/docs" >> $@ && \ - echo -e "cflags=-I$(srcdir)/Source $(webkitgtk_gdom_include_dirs)" >> $@ && \ - echo "source_dirs=$(top_builddir)/DerivedSources/webkitdom $(srcdir)/Source/WebCore/bindings/gobject" >> $@ && \ - echo "headers=$(webkitgtk_gdom_built_h_api) DerivedSources/webkitdom/WebKitDOMDeprecated.h" >> $@ -BUILT_SOURCES += gtkdoc-webkitdom.cfg diff --git a/Source/WebCore/bindings/gobject/GObjectEventListener.cpp b/Source/WebCore/bindings/gobject/GObjectEventListener.cpp deleted file mode 100644 index e695213d3..000000000 --- a/Source/WebCore/bindings/gobject/GObjectEventListener.cpp +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Copyright (C) 2010, 2011 Igalia S.L. - * - * 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 - */ - -#include "config.h" -#include "GObjectEventListener.h" - -#include "Event.h" -#include "WebKitDOMEvent.h" -#include "WebKitDOMEventPrivate.h" -#include "WebKitDOMEventTarget.h" -#include <wtf/HashMap.h> - -namespace WebCore { - -GObjectEventListener::GObjectEventListener(GObject* target, EventTarget* coreTarget, const char* domEventName, GClosure* handler, bool capture) - : EventListener(GObjectEventListenerType) - , m_target(target) - , m_coreTarget(coreTarget) - , m_domEventName(domEventName) - , m_handler(handler) - , m_capture(capture) -{ - ASSERT(m_coreTarget); - if (G_CLOSURE_NEEDS_MARSHAL(m_handler.get())) - g_closure_set_marshal(m_handler.get(), g_cclosure_marshal_generic); - g_object_weak_ref(m_target, reinterpret_cast<GWeakNotify>(GObjectEventListener::gobjectDestroyedCallback), this); -} - -GObjectEventListener::~GObjectEventListener() -{ - if (!m_coreTarget) - return; - g_object_weak_unref(m_target, reinterpret_cast<GWeakNotify>(GObjectEventListener::gobjectDestroyedCallback), this); -} - -void GObjectEventListener::gobjectDestroyed() -{ - ASSERT(m_coreTarget); - - // Protect 'this' class in case the 'm_coreTarget' holds the last reference, - // which may cause, inside removeEventListener(), free of this object - // and later use-after-free with the m_handler = 0; assignment. - RefPtr<GObjectEventListener> protect(this); - - m_coreTarget->removeEventListener(m_domEventName.data(), this, m_capture); - m_coreTarget = 0; - m_handler = 0; -} - -void GObjectEventListener::handleEvent(ScriptExecutionContext*, Event* event) -{ - GValue parameters[2] = { G_VALUE_INIT, G_VALUE_INIT }; - g_value_init(¶meters[0], WEBKIT_TYPE_DOM_EVENT_TARGET); - g_value_set_object(¶meters[0], m_target); - - GRefPtr<WebKitDOMEvent> domEvent = adoptGRef(WebKit::kit(event)); - g_value_init(¶meters[1], WEBKIT_TYPE_DOM_EVENT); - g_value_set_object(¶meters[1], domEvent.get()); - - g_closure_invoke(m_handler.get(), 0, 2, parameters, NULL); - g_value_unset(parameters + 0); - g_value_unset(parameters + 1); -} - -bool GObjectEventListener::operator==(const EventListener& listener) -{ - if (const GObjectEventListener* gobjectEventListener = GObjectEventListener::cast(&listener)) - return m_target == gobjectEventListener->m_target - && reinterpret_cast<GCClosure*>(m_handler.get())->callback == reinterpret_cast<GCClosure*>(gobjectEventListener->m_handler.get())->callback; - - return false; -} - -} diff --git a/Source/WebCore/bindings/gobject/GObjectEventListener.h b/Source/WebCore/bindings/gobject/GObjectEventListener.h deleted file mode 100644 index 58436fd8a..000000000 --- a/Source/WebCore/bindings/gobject/GObjectEventListener.h +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Copyright (C) 2010, 2011 Igalia S.L. - * - * 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 GObjectEventListener_h -#define GObjectEventListener_h - -#include "EventListener.h" -#include "EventTarget.h" -#include <wtf/RefPtr.h> -#include <wtf/gobject/GRefPtr.h> -#include <wtf/text/CString.h> - -typedef struct _GObject GObject; -typedef struct _GClosure GClosure; - -namespace WebCore { - -class GObjectEventListener : public EventListener { -public: - - static bool addEventListener(GObject* target, EventTarget* coreTarget, const char* domEventName, GClosure* handler, bool useCapture) - { - RefPtr<GObjectEventListener> listener(adoptRef(new GObjectEventListener(target, coreTarget, domEventName, handler, useCapture))); - return coreTarget->addEventListener(domEventName, listener.release(), useCapture); - } - - static bool removeEventListener(GObject* target, EventTarget* coreTarget, const char* domEventName, GClosure* handler, bool useCapture) - { - GObjectEventListener key(target, coreTarget, domEventName, handler, useCapture); - return coreTarget->removeEventListener(domEventName, &key, useCapture); - } - - static void gobjectDestroyedCallback(GObjectEventListener* listener, GObject*) - { - listener->gobjectDestroyed(); - } - - static const GObjectEventListener* cast(const EventListener* listener) - { - return listener->type() == GObjectEventListenerType - ? static_cast<const GObjectEventListener*>(listener) - : 0; - } - - virtual bool operator==(const EventListener& other); - -private: - GObjectEventListener(GObject*, EventTarget*, const char* domEventName, GClosure*, bool capture); - ~GObjectEventListener(); - void gobjectDestroyed(); - - virtual void handleEvent(ScriptExecutionContext*, Event*); - - GObject* m_target; - // We do not need to keep a reference to the m_coreTarget, because - // we only use it when the GObject and thus the m_coreTarget object is alive. - EventTarget* m_coreTarget; - CString m_domEventName; - GRefPtr<GClosure> m_handler; - bool m_capture; -}; -} // namespace WebCore - -#endif diff --git a/Source/WebCore/bindings/gobject/WebKitDOMCustom.cpp b/Source/WebCore/bindings/gobject/WebKitDOMCustom.cpp deleted file mode 100644 index 0c40d77f3..000000000 --- a/Source/WebCore/bindings/gobject/WebKitDOMCustom.cpp +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright (C) 2011 Igalia S.L. - * - * 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 - */ - -#include "config.h" -#include "WebKitDOMCustom.h" - -#include "JSMainThreadExecState.h" -#include "WebKitDOMHTMLInputElement.h" -#include "WebKitDOMHTMLInputElementPrivate.h" -#include "WebKitDOMHTMLMediaElementPrivate.h" -#include "WebKitDOMHTMLTextAreaElement.h" -#include "WebKitDOMHTMLTextAreaElementPrivate.h" -#include "WebKitDOMPrivate.h" -#include "gobject/ConvertToUTF8String.h" - -using namespace WebKit; - -gboolean webkit_dom_html_text_area_element_is_edited(WebKitDOMHTMLTextAreaElement* area) -{ - g_return_val_if_fail(WEBKIT_DOM_IS_HTML_TEXT_AREA_ELEMENT(area), FALSE); - - return core(area)->lastChangeWasUserEdit(); -} - -gboolean webkit_dom_html_input_element_is_edited(WebKitDOMHTMLInputElement* input) -{ - g_return_val_if_fail(WEBKIT_DOM_IS_HTML_INPUT_ELEMENT(input), FALSE); - - return core(input)->lastChangeWasUserEdit(); -} - -void webkit_dom_html_media_element_set_current_time(WebKitDOMHTMLMediaElement* self, gdouble value, GError**) -{ -#if ENABLE(VIDEO) - WebCore::JSMainThreadNullState state; - g_return_if_fail(WEBKIT_DOM_IS_HTML_MEDIA_ELEMENT(self)); - WebCore::HTMLMediaElement* item = WebKit::core(self); - item->setCurrentTime(value); -#else - WEBKIT_WARN_FEATURE_NOT_PRESENT("Video") -#endif /* ENABLE(VIDEO) */ -} - - diff --git a/Source/WebCore/bindings/gobject/WebKitDOMCustom.h b/Source/WebCore/bindings/gobject/WebKitDOMCustom.h deleted file mode 100644 index aed512963..000000000 --- a/Source/WebCore/bindings/gobject/WebKitDOMCustom.h +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright (C) 2011 Igalia S.L. - * - * 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 WebKitDOMCustom_h -#define WebKitDOMCustom_h - -#include <glib-object.h> -#include <glib.h> -#include <webkitdom/webkitdomdefines.h> - -G_BEGIN_DECLS - -/** - * webkit_dom_html_text_area_element_is_edited: - * @input: A #WebKitDOMHTMLTextAreaElement - * - * Returns: A #gboolean - */ -WEBKIT_API gboolean webkit_dom_html_text_area_element_is_edited(WebKitDOMHTMLTextAreaElement* input); - -/** - * webkit_dom_html_media_element_set_current_time: - * @self: A #WebKitDOMHTMLMediaElement - * @value: A #gdouble - * @error: #GError - * - */ -WEBKIT_API void webkit_dom_html_media_element_set_current_time(WebKitDOMHTMLMediaElement* self, gdouble value, GError** error); - -/** - * webkit_dom_html_input_element_is_edited: - * @input: A #WebKitDOMHTMLInputElement - * - * Returns: A #gboolean - */ -WEBKIT_API gboolean webkit_dom_html_input_element_is_edited(WebKitDOMHTMLInputElement* input); - -G_END_DECLS - -#endif diff --git a/Source/WebCore/bindings/gobject/WebKitDOMCustom.symbols b/Source/WebCore/bindings/gobject/WebKitDOMCustom.symbols deleted file mode 100644 index 92029b470..000000000 --- a/Source/WebCore/bindings/gobject/WebKitDOMCustom.symbols +++ /dev/null @@ -1,3 +0,0 @@ -gboolean webkit_dom_html_text_area_element_is_edited(WebKitDOMHTMLTextAreaElement*) -gboolean webkit_dom_html_input_element_is_edited(WebKitDOMHTMLInputElement*) -void webkit_dom_html_media_element_set_current_time(WebKitDOMHTMLMediaElement*, gdouble, GError**) diff --git a/Source/WebCore/bindings/gobject/WebKitDOMDeprecated.cpp b/Source/WebCore/bindings/gobject/WebKitDOMDeprecated.cpp deleted file mode 100644 index d403cfc29..000000000 --- a/Source/WebCore/bindings/gobject/WebKitDOMDeprecated.cpp +++ /dev/null @@ -1,562 +0,0 @@ -/* - * Copyright (C) 2011 Igalia S.L. - * - * 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 - */ - -#include "config.h" -#include "WebKitDOMDeprecated.h" - -#include "WebKitDOMBlob.h" -#include "WebKitDOMDOMStringList.h" -#include "WebKitDOMHTMLCollection.h" -#include "WebKitDOMHTMLFormElement.h" -#include "WebKitDOMHTMLHeadElement.h" -#include "WebKitDOMNodeList.h" -#include "WebKitDOMObject.h" -#include "WebKitDOMPrivate.h" -#include "WebKitDOMProcessingInstruction.h" -#include "WebKitDOMWebKitNamedFlow.h" - -using namespace WebKit; - -WebKitDOMBlob* webkit_dom_blob_webkit_slice(WebKitDOMBlob* self, gint64 start, gint64 end, const gchar* content_type) -{ - return webkit_dom_blob_slice(self, start, end, content_type); -} - -gchar* webkit_dom_html_element_get_id(WebKitDOMHTMLElement* element) -{ - g_warning("The get_id method on WebKitDOMHTMLElement is deprecated. Use the one in WebKitDOMElement instead."); - return webkit_dom_element_get_id(WEBKIT_DOM_ELEMENT(element)); -} - -void webkit_dom_html_element_set_id(WebKitDOMHTMLElement* element, const gchar* value) -{ - g_warning("The set_id method on WebKitDOMHTMLElement is deprecated. Use the one in WebKitDOMElement instead."); - webkit_dom_element_set_id(WEBKIT_DOM_ELEMENT(element), value); -} - -gchar* webkit_dom_html_element_get_class_name(WebKitDOMHTMLElement* element) -{ - return webkit_dom_element_get_class_name(WEBKIT_DOM_ELEMENT(element)); -} - -void webkit_dom_html_element_set_class_name(WebKitDOMHTMLElement* element, const gchar* value) -{ - webkit_dom_element_set_class_name(WEBKIT_DOM_ELEMENT(element), value); -} - -WebKitDOMDOMTokenList* webkit_dom_html_element_get_class_list(WebKitDOMHTMLElement* element) -{ - return webkit_dom_element_get_class_list(WEBKIT_DOM_ELEMENT(element)); -} - -void webkit_dom_html_form_element_dispatch_form_change(WebKitDOMHTMLFormElement* self) -{ - g_warning("The onformchange functionality has been removed from the DOM spec, this function does nothing."); -} - -void webkit_dom_html_form_element_dispatch_form_input(WebKitDOMHTMLFormElement* self) -{ - g_warning("The onforminput functionality has been removed from the DOM spec, this function does nothing."); -} - -gboolean webkit_dom_webkit_named_flow_get_overflow(WebKitDOMWebKitNamedFlow* flow) -{ - g_warning("The WebKitDOMWebKitNamedFlow::overflow property has been renamed to WebKitDOMWebKitNamedFlow::overset. Please update your code to use the new name."); - return webkit_dom_webkit_named_flow_get_overset(flow); -} - -gchar* webkit_dom_element_get_webkit_region_overflow(WebKitDOMElement* element) -{ - return webkit_dom_element_get_webkit_region_overset(element); -} - -WebKitDOMNodeList* webkit_dom_webkit_named_flow_get_content_nodes(WebKitDOMWebKitNamedFlow* namedFlow) -{ - return webkit_dom_webkit_named_flow_get_content(namedFlow); - -} - -WebKitDOMNodeList* webkit_dom_webkit_named_flow_get_regions_by_content_node(WebKitDOMWebKitNamedFlow* namedFlow, WebKitDOMNode* contentNode) -{ - return webkit_dom_webkit_named_flow_get_regions_by_content(namedFlow, contentNode); -} - -// WebKitDOMBarInfo - -typedef struct _WebKitDOMBarInfo { - WebKitDOMObject parent_instance; -} WebKitDOMBarInfo; - -typedef struct _WebKitDOMBarInfoClass { - WebKitDOMObjectClass parent_class; -} WebKitDOMBarInfoClass; - -G_DEFINE_TYPE(WebKitDOMBarInfo, webkit_dom_bar_info, WEBKIT_TYPE_DOM_OBJECT) - -typedef enum { - PROP_0, - PROP_VISIBLE, -} WebKitDOMBarInfoProperties; - -static void webkit_dom_bar_info_get_property(GObject* object, guint propertyId, GValue* value, GParamSpec* pspec) -{ - switch (propertyId) { - case PROP_VISIBLE: { - WEBKIT_WARN_FEATURE_NOT_PRESENT("BarInfo") - g_value_set_boolean(value, FALSE); - break; - } - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, propertyId, pspec); - break; - } -} - -static void webkit_dom_bar_info_class_init(WebKitDOMBarInfoClass* requestClass) -{ - GObjectClass* gobjectClass = G_OBJECT_CLASS(requestClass); - gobjectClass->get_property = webkit_dom_bar_info_get_property; - - g_object_class_install_property(gobjectClass, - PROP_VISIBLE, - g_param_spec_boolean("visible", - "bar_info_visible - removed from WebKit, does nothing", - "read-only gboolean BarInfo.visible - removed from WebKit, does nothing", - FALSE, - WEBKIT_PARAM_READABLE)); -} - -static void webkit_dom_bar_info_init(WebKitDOMBarInfo*) -{ -} - -gboolean webkit_dom_bar_info_get_visible(void*) -{ - g_warning("The BarInfo type has been removed from the DOM spec, this function does nothing."); - return FALSE; -} - -// WebKitDOMConsole - -void* webkit_dom_console_get_memory(WebKitDOMConsole*) -{ - g_warning("%s: this functionality has been removed from WebKit, this function does nothing.", __func__); - return 0; -} - -// WebKitDOMCSSStyleDeclaration - -WebKitDOMCSSValue* webkit_dom_css_style_declaration_get_property_css_value(WebKitDOMCSSStyleDeclaration*, const gchar*) -{ - g_warning("%s: this functionality has been removed from WebKit, this function does nothing.", __func__); - return 0; -} - -// WebKitDOMDocument - -gboolean webkit_dom_document_get_webkit_hidden(WebKitDOMDocument*) -{ - g_warning("%s: this functionality has been removed from WebKit, this function does nothing.", __func__); - return FALSE; -} - -gchar* webkit_dom_document_get_webkit_visibility_state(WebKitDOMDocument*) -{ - g_warning("%s: this functionality has been removed from WebKit, this function does nothing.", __func__); - return g_strdup(""); -} - -// WebKitDOMHTMLDocument - -void webkit_dom_html_document_open(WebKitDOMHTMLDocument*) -{ - g_warning("%s: this functionality has been removed from WebKit, this function does nothing.", __func__); -} - -// WebKitDOMHTMLElement - -void webkit_dom_html_element_set_item_id(WebKitDOMHTMLElement*, const gchar*) -{ - g_warning("%s: this functionality has been removed from WebKit, this function does nothing.", __func__); -} - -gchar* webkit_dom_html_element_get_item_id(WebKitDOMHTMLElement*) -{ - g_warning("%s: this functionality has been removed from WebKit, this function does nothing.", __func__); - return g_strdup(""); -} - -WebKitDOMDOMSettableTokenList* webkit_dom_html_element_get_item_ref(WebKitDOMHTMLElement*) -{ - g_warning("%s: this functionality has been removed from WebKit, this function does nothing.", __func__); - return 0; -} - -WebKitDOMDOMSettableTokenList* webkit_dom_html_element_get_item_prop(WebKitDOMHTMLElement*) -{ - g_warning("%s: this functionality has been removed from WebKit, this function does nothing.", __func__); - return 0; -} - -void webkit_dom_html_element_set_item_scope(WebKitDOMHTMLElement*, gboolean) -{ - g_warning("%s: this functionality has been removed from WebKit, this function does nothing.", __func__); -} - -gboolean webkit_dom_html_element_get_item_scope(WebKitDOMHTMLElement*) -{ - g_warning("%s: this functionality has been removed from WebKit, this function does nothing.", __func__); - return FALSE; -} - -void* webkit_dom_html_element_get_item_type(WebKitDOMHTMLElement*) -{ - g_warning("%s: this functionality has been removed from WebKit, this function does nothing.", __func__); - return 0; -} - -// WebKitDOMHTMLStyleElement - -void webkit_dom_html_style_element_set_scoped(WebKitDOMHTMLStyleElement*, gboolean) -{ - g_warning("%s: this functionality has been removed from WebKit, this function does nothing.", __func__); -} - -gboolean webkit_dom_html_style_element_get_scoped(WebKitDOMHTMLStyleElement*) -{ - g_warning("%s: this functionality has been removed from WebKit, this function does nothing.", __func__); - return FALSE; -} - -// WebKitDOMHTMLPropertiesCollection - -typedef struct _WebKitDOMHTMLPropertiesCollection { - WebKitDOMHTMLCollection parent_instance; -} WebKitDOMHTMLPropertiesCollection; - -typedef struct _WebKitDOMHTMLPropertiesCollectionClass { - WebKitDOMHTMLCollectionClass parent_class; -} WebKitDOMHTMLPropertiesCollectionClass; - -G_DEFINE_TYPE(WebKitDOMHTMLPropertiesCollection, webkit_dom_html_properties_collection, WEBKIT_TYPE_DOM_HTML_COLLECTION) - -enum { - HTML_PROPERTIES_COLLECTION_PROP_0, - HTML_PROPERTIES_COLLECTION_PROP_LENGTH, - HTML_PROPERTIES_COLLECTION_PROP_NAMES, -}; - -static void webkit_dom_html_properties_collection_get_property(GObject* object, guint propertyId, GValue* value, GParamSpec* pspec) -{ - switch (propertyId) { - case HTML_PROPERTIES_COLLECTION_PROP_LENGTH: { - WEBKIT_WARN_FEATURE_NOT_PRESENT("Microdata") - break; - } - case HTML_PROPERTIES_COLLECTION_PROP_NAMES: { - WEBKIT_WARN_FEATURE_NOT_PRESENT("Microdata") - break; - } - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, propertyId, pspec); - break; - } -} - -static void webkit_dom_html_properties_collection_class_init(WebKitDOMHTMLPropertiesCollectionClass* requestClass) -{ - GObjectClass* gobjectClass = G_OBJECT_CLASS(requestClass); - gobjectClass->get_property = webkit_dom_html_properties_collection_get_property; - - g_object_class_install_property(gobjectClass, - HTML_PROPERTIES_COLLECTION_PROP_LENGTH, - g_param_spec_ulong("length", - "html_properties_collection_length - removed from WebKit, does nothing", - "read-only gulong HTMLPropertiesCollection.length - removed from WebKit, does nothing", - 0, - G_MAXULONG, - 0, - WEBKIT_PARAM_READABLE)); - - g_object_class_install_property(gobjectClass, - HTML_PROPERTIES_COLLECTION_PROP_NAMES, - g_param_spec_object("names", - "html_properties_collection_names - removed from WebKit, does nothing", - "read-only WebKitDOMDOMStringList* HTMLPropertiesCollection.names - removed from WebKit, does nothing", - WEBKIT_TYPE_DOM_DOM_STRING_LIST, - WEBKIT_PARAM_READABLE)); -} - -static void webkit_dom_html_properties_collection_init(WebKitDOMHTMLPropertiesCollection* request) -{ -} - -WebKitDOMNode* webkit_dom_html_properties_collection_item(void*, gulong) -{ - g_warning("%s: the PropertiesCollection object has been removed from WebKit, this function does nothing.", __func__); - return 0; -} - -void* webkit_dom_html_properties_collection_named_item(void*, const gchar*) -{ - g_warning("%s: the PropertiesCollection object has been removed from WebKit, this function does nothing.", __func__); - return 0; -} - -gulong webkit_dom_html_properties_collection_get_length(void*) -{ - g_warning("%s: the PropertiesCollection object has been removed from WebKit, this function does nothing.", __func__); - return 0; -} - -WebKitDOMDOMStringList* webkit_dom_html_properties_collection_get_names(void*) -{ - g_warning("%s: the PropertiesCollection object has been removed from WebKit, this function does nothing.", __func__); - return 0; -} - -// WebKitDOMNode - -WebKitDOMNamedNodeMap* webkit_dom_node_get_attributes(WebKitDOMNode*) -{ - g_warning("%s: this functionality has been removed from WebKit, this function does nothing.", __func__); - return 0; -} - -gboolean webkit_dom_node_has_attributes(WebKitDOMNode*) -{ - g_warning("%s: this functionality has been removed from WebKit, this function does nothing.", __func__); - return FALSE; -} - -// WebKitDOMMemoryInfo - -typedef struct _WebKitDOMMemoryInfo { - WebKitDOMObject parent_instance; -} WebKitDOMMemoryInfo; - -typedef struct _WebKitDOMMemoryInfoClass { - WebKitDOMObjectClass parent_class; -} WebKitDOMMemoryInfoClass; - - -G_DEFINE_TYPE(WebKitDOMMemoryInfo, webkit_dom_memory_info, WEBKIT_TYPE_DOM_OBJECT) - -enum { - DOM_MEMORY_PROP_0, - DOM_MEMORY_PROP_TOTAL_JS_HEAP_SIZE, - DOM_MEMORY_PROP_USED_JS_HEAP_SIZE, - DOM_MEMORY_PROP_JS_HEAP_SIZE_LIMIT, -}; - -static void webkit_dom_memory_info_get_property(GObject* object, guint propertyId, GValue* value, GParamSpec* pspec) -{ - switch (propertyId) { - case DOM_MEMORY_PROP_TOTAL_JS_HEAP_SIZE: { - g_value_set_ulong(value, 0); - WEBKIT_WARN_FEATURE_NOT_PRESENT("MemoryInfo") - break; - } - case DOM_MEMORY_PROP_USED_JS_HEAP_SIZE: { - g_value_set_ulong(value, 0); - WEBKIT_WARN_FEATURE_NOT_PRESENT("MemoryInfo") - break; - } - case DOM_MEMORY_PROP_JS_HEAP_SIZE_LIMIT: { - g_value_set_ulong(value, 0); - WEBKIT_WARN_FEATURE_NOT_PRESENT("MemoryInfo") - break; - } - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, propertyId, pspec); - break; - } -} - -static void webkit_dom_memory_info_class_init(WebKitDOMMemoryInfoClass* requestClass) -{ - GObjectClass* gobjectClass = G_OBJECT_CLASS(requestClass); - gobjectClass->get_property = webkit_dom_memory_info_get_property; - - g_object_class_install_property(gobjectClass, - DOM_MEMORY_PROP_TOTAL_JS_HEAP_SIZE, - g_param_spec_ulong("total-js-heap-size", - "memory_info_total-js-heap-size - removed from WebKit, does nothing", - "read-only gulong MemoryInfo.total-js-heap-size - removed from WebKit, does nothing", - 0, - G_MAXULONG, - 0, - WEBKIT_PARAM_READABLE)); - g_object_class_install_property(gobjectClass, - DOM_MEMORY_PROP_USED_JS_HEAP_SIZE, - g_param_spec_ulong("used-js-heap-size", - "memory_info_used-js-heap-size - removed from WebKit, does nothing", - "read-only gulong MemoryInfo.used-js-heap-size - removed from WebKit, does nothing", - 0, - G_MAXULONG, - 0, - WEBKIT_PARAM_READABLE)); - g_object_class_install_property(gobjectClass, - DOM_MEMORY_PROP_JS_HEAP_SIZE_LIMIT, - g_param_spec_ulong("js-heap-size-limit", - "memory_info_js-heap-size-limit - removed from WebKit, does nothing", - "read-only gulong MemoryInfo.js-heap-size-limit - removed from WebKit, does nothing", - 0, - G_MAXULONG, - 0, - WEBKIT_PARAM_READABLE)); -} - -static void webkit_dom_memory_info_init(WebKitDOMMemoryInfo*) -{ -} - -gulong webkit_dom_memory_info_get_total_js_heap_size(void*) -{ - g_warning("%s: the MemoryInfo object has been removed from WebKit, this function does nothing.", __func__); - return 0; -} - -gulong webkit_dom_memory_info_get_used_js_heap_size(void*) -{ - g_warning("%s: the MemoryInfo object has been removed from WebKit, this function does nothing.", __func__); - return 0; -} - -gulong webkit_dom_memory_info_get_js_heap_size_limit(void*) -{ - g_warning("%s: the MemoryInfo object has been removed from WebKit, this function does nothing.", __func__); - return 0; -} - -// WebKitDOMMicroDataItemValue - -typedef struct _WebKitDOMMicroDataItemValue { - WebKitDOMObject parent_instance; -} WebKitDOMMicroDataItemValue; - -typedef struct _WebKitDOMMicroDataItemValueClass { - WebKitDOMObjectClass parent_class; -} WebKitDOMMicroDataItemValueClass; - -G_DEFINE_TYPE(WebKitDOMMicroDataItemValue, webkit_dom_micro_data_item_value, WEBKIT_TYPE_DOM_OBJECT) - -static void webkit_dom_micro_data_item_value_class_init(WebKitDOMMicroDataItemValueClass*) -{ -} - -static void webkit_dom_micro_data_item_value_init(WebKitDOMMicroDataItemValue*) -{ -} - -// WebKitDOMPerformance - -void* webkit_dom_performance_get_memory(WebKitDOMPerformance*) -{ - g_warning("%s: this functionality has been removed from WebKit, this function does nothing.", __func__); - return 0; -} - -// WebKitDOMPropertyNodeList - -typedef struct _WebKitDOMPropertyNodeList { - WebKitDOMNodeList parent_instance; -} WebKitDOMPropertyNodeList; - -typedef struct _WebKitDOMPropertyNodeListClass { - WebKitDOMNodeListClass parent_class; -} WebKitDOMPropertyNodeListClass; - -G_DEFINE_TYPE(WebKitDOMPropertyNodeList, webkit_dom_property_node_list, WEBKIT_TYPE_DOM_NODE_LIST) - -enum { - PROPERTY_NODE_LIST_PROP_0, - PROPERTY_NODE_LIST_PROP_LENGTH, -}; - -static void webkit_dom_property_node_list_get_property(GObject* object, guint propertyId, GValue* value, GParamSpec* pspec) -{ - switch (propertyId) { - case PROPERTY_NODE_LIST_PROP_LENGTH: { - g_value_set_ulong(value, 0); - WEBKIT_WARN_FEATURE_NOT_PRESENT("Microdata") - break; - } - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, propertyId, pspec); - break; - } -} - -static void webkit_dom_property_node_list_class_init(WebKitDOMPropertyNodeListClass* requestClass) -{ - GObjectClass* gobjectClass = G_OBJECT_CLASS(requestClass); - gobjectClass->get_property = webkit_dom_property_node_list_get_property; - - g_object_class_install_property(gobjectClass, - PROPERTY_NODE_LIST_PROP_LENGTH, - g_param_spec_ulong("length", - "property_node_list_length - removed from WebKit, does nothing", - "read-only gulong PropertyNodeList.length - removed from WebKit, does nothing", - 0, - G_MAXULONG, - 0, - WEBKIT_PARAM_READABLE)); -} - -static void webkit_dom_property_node_list_init(WebKitDOMPropertyNodeList*) -{ -} - -WebKitDOMNode* webkit_dom_property_node_list_item(void*, gulong) -{ - g_warning("%s: the PropertyNodeList object has been removed from WebKit, this function does nothing.", __func__); - return 0; -} - -gulong webkit_dom_property_node_list_get_length(void*) -{ - g_warning("%s: the PropertyNodeList object has been removed from WebKit, this function does nothing.", __func__); - return 0; -} - -gdouble webkit_dom_html_media_element_get_start_time(WebKitDOMHTMLMediaElement*) -{ - g_warning("%s: the HTMLMediaElement:start-time property has been removed from WebKit, this function does nothing.", __func__); - return 0; -} - -gdouble webkit_dom_html_media_element_get_initial_time(WebKitDOMHTMLMediaElement*) -{ - g_warning("%s: the HTMLMediaElement:initial-time property has been removed from WebKit, this function does nothing.", __func__); - return 0; -} - -// WebKitDOMProcessingInstruction - -gchar* webkit_dom_processing_instruction_get_data(WebKitDOMProcessingInstruction* self) -{ - g_warning("%s: this functionality has been removed from WebKit, this function does nothing.", __func__); - return g_strdup(""); -} - -void webkit_dom_processing_instruction_set_data(WebKitDOMProcessingInstruction* self, const gchar* value, GError** error) -{ - g_warning("%s: this functionality has been removed from WebKit, this function does nothing.", __func__); -} - diff --git a/Source/WebCore/bindings/gobject/WebKitDOMDeprecated.h b/Source/WebCore/bindings/gobject/WebKitDOMDeprecated.h deleted file mode 100644 index c03a9c58c..000000000 --- a/Source/WebCore/bindings/gobject/WebKitDOMDeprecated.h +++ /dev/null @@ -1,584 +0,0 @@ -/* - * Copyright (C) 2011 Igalia S.L. - * - * 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 WebKitDOMDeprecated_h -#define WebKitDOMDeprecated_h - -#if !defined(WEBKIT_DISABLE_DEPRECATED) - -#include <glib-object.h> -#include <glib.h> -#include <webkitdom/webkitdomdefines.h> - -G_BEGIN_DECLS - -/** - * webkit_dom_blob_webkit_slice: - * @self: A #WebKitDOMBlob - * @start: A #gint64 - * @end: A #gint64 - * @content_type: A #gchar - * - * Returns: (transfer none): a #WebKitDOMBlob - * - * Deprecated: 1.10: Use webkit_dom_blob_slice() instead. - */ -WEBKIT_DEPRECATED_FOR(webkit_dom_blob_slice) WebKitDOMBlob* -webkit_dom_blob_webkit_slice(WebKitDOMBlob* self, gint64 start, gint64 end, const gchar* content_type); - -/** - * webkit_dom_html_element_get_id: - * @self: A #WebKitDOMHTMLElement - * - * Returns: A #gchar - * - * Deprecated: 2.2: Use webkit_dom_element_get_id() instead. - */ -WEBKIT_DEPRECATED_FOR(webkit_dom_element_get_id) gchar* -webkit_dom_html_element_get_id(WebKitDOMHTMLElement* self); - -/** - * webkit_dom_html_element_set_id: - * @self: A #WebKitDOMHTMLElement - * @value: A #gchar - * - * Deprecated: 2.2: Use webkit_dom_element_set_id() instead. - */ -WEBKIT_DEPRECATED_FOR(webkit_dom_element_set_id) void -webkit_dom_html_element_set_id(WebKitDOMHTMLElement* self, const gchar* value); - -/** - * webkit_dom_html_element_get_class_name: - * @element: A #WebKitDOMHTMLElement - * - * Returns: A #gchar - * - * Deprecated: 1.10: Use webkit_dom_element_get_class_name() instead. - */ -WEBKIT_DEPRECATED_FOR(webkit_dom_element_get_class_name) gchar* -webkit_dom_html_element_get_class_name(WebKitDOMHTMLElement* element); - -/** - * webkit_dom_html_element_set_class_name: - * @element: A #WebKitDOMHTMLElement - * @value: A #gchar - * - * - * Deprecated: 1.10: Use webkit_dom_element_set_class_name() instead. - */ -WEBKIT_DEPRECATED_FOR(webkit_dom_element_set_class_name) void -webkit_dom_html_element_set_class_name(WebKitDOMHTMLElement* element, const gchar* value); - -/** - * webkit_dom_html_element_get_class_list: - * @element: A #WebKitDOMHTMLElement - * - * Returns: (transfer none): a #WebKitDOMDOMTokenList - * - * Deprecated: 1.10: Use webkit_dom_element_get_class_list() instead. - */ -WEBKIT_DEPRECATED_FOR(webkit_dom_element_get_class_list) WebKitDOMDOMTokenList* -webkit_dom_html_element_get_class_list(WebKitDOMHTMLElement* element); - -/** - * webkit_dom_html_form_element_dispatch_form_change: - * @self: A #WebKitDOMHTMLFormElement - * - * Deprecated: 1.6 - */ -WEBKIT_DEPRECATED void -webkit_dom_html_form_element_dispatch_form_change(WebKitDOMHTMLFormElement* self); - -/** - * webkit_dom_html_form_element_dispatch_form_input: - * @self: A #WebKitDOMHTMLFormElement - * - * Deprecated: 1.6 - */ -WEBKIT_DEPRECATED void -webkit_dom_html_form_element_dispatch_form_input(WebKitDOMHTMLFormElement* self); - -/** - * webkit_dom_webkit_named_flow_get_overflow: - * @flow: A #WebKitDOMWebKitNamedFlow - * - * Returns: A #gboolean - * - * Deprecated: 1.10: Use webkit_dom_webkit_named_flow_get_overset() instead. - */ -WEBKIT_DEPRECATED_FOR(webkit_dom_webkit_named_flow_get_overset) gboolean -webkit_dom_webkit_named_flow_get_overflow(WebKitDOMWebKitNamedFlow* flow); - -/** - * webkit_dom_element_get_webkit_region_overflow: - * @element: A #WebKitDOMElement - * - * Returns: A #gchar - * - * Deprecated: 1.10: Use webkit_dom_element_get_webkit_region_overset() instead. - */ -WEBKIT_DEPRECATED_FOR(webkit_dom_element_get_webkit_region_overset) gchar* -webkit_dom_element_get_webkit_region_overflow(WebKitDOMElement* element); - -/** - * webkit_dom_webkit_named_flow_get_content_nodes: - * @flow: A #WebKitDOMWebKitNamedFlow - * - * Returns: (transfer none): a #WebKitDOMNodeList - * - * Deprecated: 1.10: Use webkit_dom_webkit_named_flow_get_content() instead. - */ -WEBKIT_DEPRECATED_FOR(webkit_dom_webkit_named_flow_get_content) WebKitDOMNodeList* -webkit_dom_webkit_named_flow_get_content_nodes(WebKitDOMWebKitNamedFlow* flow); - -/** - * webkit_dom_webkit_named_flow_get_regions_by_content_node: - * @flow: A #WebKitDOMWebKitNamedFlow - * @content_node: A #WebKitDOMNode - * - * Returns: (transfer none): a #WebKitDOMNodeList - * - * Deprecated: 1.10: Use webkit_dom_webkit_named_flow_get_regions_by_content() instead. - */ -WEBKIT_DEPRECATED_FOR(webkit_dom_webkit_named_flow_get_regions_by_content) WebKitDOMNodeList* -webkit_dom_webkit_named_flow_get_regions_by_content_node(WebKitDOMWebKitNamedFlow* flow, WebKitDOMNode* content_node); - -WEBKIT_DEPRECATED GType -webkit_dom_bar_info_get_type(void); - -/** - * webkit_dom_bar_info_get_visible: - * @self: A #WebKitDOMBarInfo - * - * The BarInfo type has been removed from the DOM spec, this function does nothing. - * - * Returns: A #gboolean - * - * Deprecated: 2.2 - */ -WEBKIT_DEPRECATED gboolean -webkit_dom_bar_info_get_visible(void* self); - -/** - * webkit_dom_console_get_memory: - * @self: A #WebKitDOMConsole - * - * This functionality has been removed from WebKit, this function does nothing. - * - * Returns: (transfer none): - * - * Deprecated: 2.2 - */ -WEBKIT_DEPRECATED void* -webkit_dom_console_get_memory(WebKitDOMConsole* self); - -/** - * webkit_dom_css_style_declaration_get_property_css_value: - * @self: A #WebKitDOMCSSStyleDeclaration - * @propertyName: A #gchar - * - * This functionality has been removed from WebKit, this function does nothing. - * - * Returns: (transfer none): a #WebKitDOMCSSValue - * - * Deprecated: 2.2 - */ -WEBKIT_DEPRECATED WebKitDOMCSSValue* -webkit_dom_css_style_declaration_get_property_css_value(WebKitDOMCSSStyleDeclaration* self, const gchar* propertyName); - -/** - * webkit_dom_document_get_webkit_hidden: - * @self: A #WebKitDOMDocument - * - * This functionality has been removed from WebKit, this function does nothing. - * - * Returns: A #gboolean - * - * Deprecated: 2.2 - */ -WEBKIT_DEPRECATED gboolean -webkit_dom_document_get_webkit_hidden(WebKitDOMDocument* self); - -/** - * webkit_dom_document_get_webkit_visibility_state: - * @self: A #WebKitDOMDocument - * - * This functionality has been removed from WebKit, this function does nothing. - * - * Returns: A #gchar - * - * Deprecated: 2.2 - */ -WEBKIT_DEPRECATED gchar* -webkit_dom_document_get_webkit_visibility_state(WebKitDOMDocument* self); - -/** - * webkit_dom_html_document_open: - * @self: A #WebKitDOMHTMLDocument - * - * This functionality has been removed from WebKit, this function does nothing. - * - * Deprecated: 2.2 - */ -WEBKIT_DEPRECATED void -webkit_dom_html_document_open(WebKitDOMHTMLDocument* self); - -/** - * webkit_dom_html_element_set_item_id: - * @self: A #WebKitDOMHTMLElement - * @value: A #gchar - * - * This functionality has been removed from WebKit, this function does nothing. - * - * Deprecated: 2.2 - */ -WEBKIT_DEPRECATED void -webkit_dom_html_element_set_item_id(WebKitDOMHTMLElement* self, const gchar* value); - -/** - * webkit_dom_html_element_get_item_id: - * @self: A #WebKitDOMHTMLElement - * - * This functionality has been removed from WebKit, this function does nothing. - * - * Returns: A #gchar - * - * Deprecated: 2.2 - */ -WEBKIT_DEPRECATED gchar* -webkit_dom_html_element_get_item_id(WebKitDOMHTMLElement* self); - -/** - * webkit_dom_html_element_get_item_ref: - * @self: A #WebKitDOMHTMLElement - * - * This functionality has been removed from WebKit, this function does nothing. - * - * Returns: (transfer none): a #WebKitDOMDOMSettableTokenList - * - * Deprecated: 2.2 - */ -WEBKIT_DEPRECATED WebKitDOMDOMSettableTokenList* -webkit_dom_html_element_get_item_ref(WebKitDOMHTMLElement* self); - -/** - * webkit_dom_html_element_get_item_prop: - * @self: A #WebKitDOMHTMLElement - * - * This functionality has been removed from WebKit, this function does nothing. - * - * Returns: (transfer none): a #WebKitDOMDOMSettableTokenList - * - * Deprecated: 2.2 - */ -WEBKIT_DEPRECATED WebKitDOMDOMSettableTokenList* -webkit_dom_html_element_get_item_prop(WebKitDOMHTMLElement* self); - -/** - * webkit_dom_html_element_set_item_scope: - * @self: A #WebKitDOMHTMLElement - * @value: A #gboolean - * - * This functionality has been removed from WebKit, this function does nothing. - * - * Deprecated: 2.2 - */ -WEBKIT_DEPRECATED void -webkit_dom_html_element_set_item_scope(WebKitDOMHTMLElement* self, gboolean value); - -/** - * webkit_dom_html_element_get_item_scope: - * @self: A #WebKitDOMHTMLElement - * - * This functionality has been removed from WebKit, this function does nothing. - * - * Returns: A #gboolean - * - * Deprecated: 2.2 - */ -WEBKIT_DEPRECATED gboolean -webkit_dom_html_element_get_item_scope(WebKitDOMHTMLElement* self); - -/** - * webkit_dom_html_element_get_item_type: - * @self: A #WebKitDOMHTMLElement - * - * This functionality has been removed from WebKit, this function does nothing. - * - * Returns: (transfer none): - * - * Deprecated: 2.2 - */ -WEBKIT_DEPRECATED void* -webkit_dom_html_element_get_item_type(WebKitDOMHTMLElement* self); - - -/** - * webkit_dom_html_style_element_set_scoped: - * @self: A #WebKitDOMHTMLStyleElement - * @value: A #gboolean - * - * This functionality has been removed from WebKit, this function does nothing. - * - * Deprecated: 2.2 - */ -WEBKIT_DEPRECATED void -webkit_dom_html_style_element_set_scoped(WebKitDOMHTMLStyleElement* self, gboolean value); - -/** - * webkit_dom_html_style_element_get_scoped: - * @self: A #WebKitDOMHTMLStyleElement - * - * This functionality has been removed from WebKit, this function does nothing. - * - * Returns: A #gboolean - * - * Deprecated: 2.2 - */ -WEBKIT_DEPRECATED gboolean -webkit_dom_html_style_element_get_scoped(WebKitDOMHTMLStyleElement* self); - - -WEBKIT_DEPRECATED GType -webkit_dom_html_properties_collection_get_type(void); - -/** - * webkit_dom_html_properties_collection_item: - * @self: A #WebKitDOMHTMLPropertiesCollection - * @index: A #gulong - * - * The PropertiesCollection object has been removed from WebKit, this function does nothing. - * - * Returns: (transfer none): a #WebKitDOMNode - * - * Deprecated: 2.2 - */ -WEBKIT_DEPRECATED WebKitDOMNode* -webkit_dom_html_properties_collection_item(void* self, gulong index); - -/** - * webkit_dom_html_properties_collection_named_item: - * @self: A #WebKitDOMHTMLPropertiesCollection - * @name: A #gchar - * - * The PropertiesCollection object has been removed from WebKit, this function does nothing. - * - * Returns: (transfer none): - * - * Deprecated: 2.2 - */ -WEBKIT_DEPRECATED void* -webkit_dom_html_properties_collection_named_item(void* self, const gchar* name); - -/** - * webkit_dom_html_properties_collection_get_length: - * @self: A #WebKitDOMHTMLPropertiesCollection - * - * The PropertiesCollection object has been removed from WebKit, this function does nothing. - * - * Returns: A #gulong - * - * Deprecated: 2.2 - */ -WEBKIT_DEPRECATED gulong -webkit_dom_html_properties_collection_get_length(void* self); - -/** - * webkit_dom_html_properties_collection_get_names: - * @self: A #WebKitDOMHTMLPropertiesCollection - * - * The PropertiesCollection object has been removed from WebKit, this function does nothing. - * - * Returns: (transfer none): a #WebKitDOMDOMStringList - * - * Deprecated: 2.2 - */ -WEBKIT_DEPRECATED WebKitDOMDOMStringList* -webkit_dom_html_properties_collection_get_names(void* self); - -/** - * webkit_dom_node_get_attributes: - * @self: A #WebKitDOMNode - * - * This functionality has been removed from WebKit, this function does nothing. - * - * Returns: (transfer none): a #WebKitDOMNamedNodeMap - * - * Deprecated: 2.2 - */ -WEBKIT_DEPRECATED WebKitDOMNamedNodeMap* -webkit_dom_node_get_attributes(WebKitDOMNode* self); - -/** - * webkit_dom_node_has_attributes: - * @self: A #WebKitDOMNode - * - * This functionality has been removed from WebKit, this function does nothing. - * - * Returns: A #gboolean - * - * Deprecated: 2.2 - */ -WEBKIT_DEPRECATED gboolean -webkit_dom_node_has_attributes(WebKitDOMNode* self); - -WEBKIT_DEPRECATED GType -webkit_dom_memory_info_get_type(void); - -/** - * webkit_dom_memory_info_get_total_js_heap_size: - * @self: A #WebKitDOMMemoryInfo - * - * The MemoryInfo object has been removed from WebKit, this function does nothing. - * - * Returns: A #gulong - * - * Deprecated: 2.2 - */ -WEBKIT_DEPRECATED gulong -webkit_dom_memory_info_get_total_js_heap_size(void* self); - -/** - * webkit_dom_memory_info_get_used_js_heap_size: - * @self: A #WebKitDOMMemoryInfo - * - * The MemoryInfo object has been removed from WebKit, this function does nothing. - * - * Returns: A #gulong - * - * Deprecated: 2.2 - */ -WEBKIT_DEPRECATED gulong -webkit_dom_memory_info_get_used_js_heap_size(void* self); - -/** - * webkit_dom_memory_info_get_js_heap_size_limit: - * @self: A #WebKitDOMMemoryInfo - * - * The MemoryInfo object has been removed from WebKit, this function does nothing. - * - * Returns: A #gulong - * - * Deprecated: 2.2 - */ -WEBKIT_DEPRECATED gulong -webkit_dom_memory_info_get_js_heap_size_limit(void* self); - -WEBKIT_DEPRECATED GType -webkit_dom_micro_data_item_value_get_type(void); - -/** - * webkit_dom_performance_get_memory: - * @self: A #WebKitDOMPerformance - * - * This functionality has been removed from WebKit, this function does nothing. - * - * Returns: (transfer none): - * - * Deprecated: 2.2 - */ -WEBKIT_DEPRECATED void* -webkit_dom_performance_get_memory(WebKitDOMPerformance* self); - -WEBKIT_DEPRECATED GType -webkit_dom_property_node_list_get_type(void); - -/** - * webkit_dom_property_node_list_item: - * @self: A #WebKitDOMPropertyNodeList - * @index: A #gulong - * - * The PropertyNodeList object has been removed from WebKit, this function does nothing. - * - * Returns: (transfer none): a #WebKitDOMNode - * - * Deprecated: 2.2 - */ -WEBKIT_DEPRECATED WebKitDOMNode* -webkit_dom_property_node_list_item(void* self, gulong index); - -/** - * webkit_dom_property_node_list_get_length: - * @self: A #WebKitDOMPropertyNodeList - * - * The PropertyNodeList object has been removed from WebKit, this function does nothing. - * - * Returns: A #gulong - * - * Deprecated: 2.2 - */ -WEBKIT_DEPRECATED gulong -webkit_dom_property_node_list_get_length(void* self); - -/** - * webkit_dom_html_media_element_get_start_time: - * @self: A #HTMLMediaElement - * - * The HTMLMediaElement:start-time property has been removed from WebKit, this function does nothing. - * - * Returns: A #gdouble - * - * Deprecated: 2.2 - */ -WEBKIT_DEPRECATED gdouble -webkit_dom_html_media_element_get_start_time(WebKitDOMHTMLMediaElement* self); - -/** - * webkit_dom_html_media_element_get_initial_time: - * @self: A #HTMLMediaElement - * - * The HTMLMediaElement:initial-time property has been removed from WebKit, this function does nothing. - * - * Returns: A #gdouble - * - * Deprecated: 2.2 - */ -WEBKIT_DEPRECATED gdouble -webkit_dom_html_media_element_get_initial_time(WebKitDOMHTMLMediaElement* self); - -/** - * webkit_dom_processing_instruction_get_data: - * @self: A #WebKitDOMProcessingInstruction - * - * This functionality has been removed from WebKit, this function does nothing. - * - * Returns: a #gchar - * - * Deprecated: 2.4 - */ -WEBKIT_DEPRECATED gchar* -webkit_dom_processing_instruction_get_data(WebKitDOMProcessingInstruction* self); - -/** - * webkit_dom_processing_instruction_set_data: - * @self: A #WebKitDOMProcessingInstruction - * @value: A #gchar - * @error: #GError - * - * This functionality has been removed from WebKit, this function does nothing. - * - * Deprecated: 2.4 - */ -WEBKIT_DEPRECATED void -webkit_dom_processing_instruction_set_data(WebKitDOMProcessingInstruction* self, const gchar* value, GError** error); - -G_END_DECLS - -#endif /* WEBKIT_DISABLE_DEPRECATED */ - -#endif diff --git a/Source/WebCore/bindings/gobject/WebKitDOMDeprecated.symbols b/Source/WebCore/bindings/gobject/WebKitDOMDeprecated.symbols deleted file mode 100644 index 7a05ff22a..000000000 --- a/Source/WebCore/bindings/gobject/WebKitDOMDeprecated.symbols +++ /dev/null @@ -1,48 +0,0 @@ -WebKitDOMBlob* webkit_dom_blob_webkit_slice(WebKitDOMBlob*, gint64, gint64, const gchar*) -gchar* webkit_dom_html_element_get_id(WebKitDOMHTMLElement*) -void webkit_dom_html_element_set_id(WebKitDOMHTMLElement*, const gchar*) -gchar* webkit_dom_html_element_get_class_name(WebKitDOMHTMLElement*) -void webkit_dom_html_element_set_class_name(WebKitDOMHTMLElement*, const gchar*) -WebKitDOMDOMTokenList* webkit_dom_html_element_get_class_list(WebKitDOMHTMLElement*) -void webkit_dom_html_form_element_dispatch_form_change(WebKitDOMHTMLFormElement*) -void webkit_dom_html_form_element_dispatch_form_input(WebKitDOMHTMLFormElement*) -gboolean webkit_dom_webkit_named_flow_get_overflow(WebKitDOMWebKitNamedFlow*) -gchar* webkit_dom_element_get_webkit_region_overflow(WebKitDOMElement*) -WebKitDOMNodeList* webkit_dom_webkit_named_flow_get_content_nodes(WebKitDOMWebKitNamedFlow*) -WebKitDOMNodeList* webkit_dom_webkit_named_flow_get_regions_by_content_node(WebKitDOMWebKitNamedFlow*, WebKitDOMNode*) -GType webkit_dom_bar_info_get_type(void) -gboolean webkit_dom_bar_info_get_visible(void*) -void* webkit_dom_console_get_memory(WebKitDOMConsole*) -WebKitDOMCSSValue* webkit_dom_css_style_declaration_get_property_css_value(WebKitDOMCSSStyleDeclaration*, const gchar*) -gboolean webkit_dom_document_get_webkit_hidden(WebKitDOMDocument*) -gchar* webkit_dom_document_get_webkit_visibility_state(WebKitDOMDocument*) -void webkit_dom_html_document_open(WebKitDOMHTMLDocument*) -void webkit_dom_html_element_set_item_id(WebKitDOMHTMLElement*, const gchar*) -gchar* webkit_dom_html_element_get_item_id(WebKitDOMHTMLElement*) -WebKitDOMDOMSettableTokenList* webkit_dom_html_element_get_item_ref(WebKitDOMHTMLElement*) -WebKitDOMDOMSettableTokenList* webkit_dom_html_element_get_item_prop(WebKitDOMHTMLElement*) -void webkit_dom_html_element_set_item_scope(WebKitDOMHTMLElement*, gboolean) -gboolean webkit_dom_html_element_get_item_scope(WebKitDOMHTMLElement*) -void* webkit_dom_html_element_get_item_type(WebKitDOMHTMLElement*) -void webkit_dom_html_style_element_set_scoped(WebKitDOMHTMLStyleElement*, gboolean) -gboolean webkit_dom_html_style_element_get_scoped(WebKitDOMHTMLStyleElement*) -GType webkit_dom_html_properties_collection_get_type(void) -WebKitDOMNode* webkit_dom_html_properties_collection_item(void*, gulong) -void* webkit_dom_html_properties_collection_named_item(void*, const gchar*) -gulong webkit_dom_html_properties_collection_get_length(void*) -WebKitDOMDOMStringList* webkit_dom_html_properties_collection_get_names(void*) -WebKitDOMNamedNodeMap* webkit_dom_node_get_attributes(WebKitDOMNode*) -gboolean webkit_dom_node_has_attributes(WebKitDOMNode*) -GType webkit_dom_memory_info_get_type(void) -gulong webkit_dom_memory_info_get_total_js_heap_size(void*) -gulong webkit_dom_memory_info_get_used_js_heap_size(void*) -gulong webkit_dom_memory_info_get_js_heap_size_limit(void*) -GType webkit_dom_micro_data_item_value_get_type(void) -void* webkit_dom_performance_get_memory(WebKitDOMPerformance*) -GType webkit_dom_property_node_list_get_type(void) -WebKitDOMNode* webkit_dom_property_node_list_item(void*, gulong) -gulong webkit_dom_property_node_list_get_length(void*) -gdouble webkit_dom_html_media_element_get_start_time(WebKitDOMHTMLMediaElement*) -gdouble webkit_dom_html_media_element_get_initial_time(WebKitDOMHTMLMediaElement*) -gchar* webkit_dom_processing_instruction_get_data(WebKitDOMProcessingInstruction*) -void webkit_dom_processing_instruction_set_data(WebKitDOMProcessingInstruction*, const gchar*, GError**) diff --git a/Source/WebCore/bindings/gobject/WebKitDOMEventTarget.cpp b/Source/WebCore/bindings/gobject/WebKitDOMEventTarget.cpp deleted file mode 100644 index a8fae2ac8..000000000 --- a/Source/WebCore/bindings/gobject/WebKitDOMEventTarget.cpp +++ /dev/null @@ -1,114 +0,0 @@ -/* - * Copyright (C) 2010 Igalia S.L. - * - * This file is derived by hand from an automatically generated file. - * Keeping it up-to-date could potentially be done by adding - * a make_names.pl generator, or by writing a separate - * generater which takes JSHTMLElementWrapperFactory.h as input. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" -#include "WebKitDOMEventTarget.h" - -#include "DOMObjectCache.h" -#include "EventTarget.h" -#include "WebKitDOMEvent.h" -#include "WebKitDOMEventTargetPrivate.h" -#include "WebKitDOMPrivate.h" -#include <wtf/gobject/GRefPtr.h> - -typedef WebKitDOMEventTargetIface WebKitDOMEventTargetInterface; - -G_DEFINE_INTERFACE(WebKitDOMEventTarget, webkit_dom_event_target, G_TYPE_OBJECT) - -static void webkit_dom_event_target_default_init(WebKitDOMEventTargetIface*) -{ -} - -gboolean webkit_dom_event_target_dispatch_event(WebKitDOMEventTarget* target, WebKitDOMEvent* event, GError** error) -{ - g_return_val_if_fail(WEBKIT_DOM_IS_EVENT_TARGET(target), FALSE); - g_return_val_if_fail(WEBKIT_DOM_IS_EVENT(event), FALSE); - g_return_val_if_fail(!error || !*error, FALSE); - - return WEBKIT_DOM_EVENT_TARGET_GET_IFACE(target)->dispatch_event(target, event, error); -} - -gboolean webkit_dom_event_target_add_event_listener(WebKitDOMEventTarget* target, const char* eventName, GCallback handler, gboolean useCapture, gpointer userData) -{ - - g_return_val_if_fail(WEBKIT_DOM_IS_EVENT_TARGET(target), FALSE); - g_return_val_if_fail(eventName, FALSE); - - GRefPtr<GClosure> closure = adoptGRef(g_cclosure_new(handler, userData, 0)); - return WEBKIT_DOM_EVENT_TARGET_GET_IFACE(target)->add_event_listener(target, eventName, closure.get(), useCapture); -} - -gboolean webkit_dom_event_target_remove_event_listener(WebKitDOMEventTarget* target, const char* eventName, GCallback handler, gboolean useCapture) -{ - g_return_val_if_fail(WEBKIT_DOM_IS_EVENT_TARGET(target), FALSE); - g_return_val_if_fail(eventName, FALSE); - - GRefPtr<GClosure> closure = adoptGRef(g_cclosure_new(handler, 0, 0)); - return WEBKIT_DOM_EVENT_TARGET_GET_IFACE(target)->remove_event_listener(target, eventName, closure.get(), useCapture); -} - -gboolean webkit_dom_event_target_add_event_listener_with_closure(WebKitDOMEventTarget* target, const char* eventName, GClosure* handler, gboolean useCapture) -{ - g_return_val_if_fail(WEBKIT_DOM_IS_EVENT_TARGET(target), FALSE); - g_return_val_if_fail(eventName, FALSE); - g_return_val_if_fail(handler, FALSE); - - return WEBKIT_DOM_EVENT_TARGET_GET_IFACE(target)->add_event_listener(target, eventName, handler, useCapture); -} - -gboolean webkit_dom_event_target_remove_event_listener_with_closure(WebKitDOMEventTarget* target, const char* eventName, GClosure* handler, gboolean useCapture) -{ - g_return_val_if_fail(WEBKIT_DOM_IS_EVENT_TARGET(target), FALSE); - g_return_val_if_fail(eventName, FALSE); - g_return_val_if_fail(handler, FALSE); - - return WEBKIT_DOM_EVENT_TARGET_GET_IFACE(target)->remove_event_listener(target, eventName, handler, useCapture); -} - -namespace WebKit { - -WebKitDOMEventTarget* kit(WebCore::EventTarget* obj) -{ - if (!obj) - return 0; - - if (gpointer ret = DOMObjectCache::get(obj)) - return WEBKIT_DOM_EVENT_TARGET(ret); - - return wrap(obj); -} - -WebCore::EventTarget* core(WebKitDOMEventTarget* request) -{ - return request ? static_cast<WebCore::EventTarget*>(WEBKIT_DOM_OBJECT(request)->coreObject) : 0; -} - -} // namespace WebKit - diff --git a/Source/WebCore/bindings/gobject/WebKitDOMEventTarget.h b/Source/WebCore/bindings/gobject/WebKitDOMEventTarget.h deleted file mode 100644 index 3d3d6609b..000000000 --- a/Source/WebCore/bindings/gobject/WebKitDOMEventTarget.h +++ /dev/null @@ -1,135 +0,0 @@ -/* - * Copyright (C) 2010 Igalia S.L. - * - * 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 WebKitDOMEventTarget_h -#define WebKitDOMEventTarget_h - -#include <glib-object.h> -#include <webkitdom/webkitdomdefines.h> - -G_BEGIN_DECLS - -#define WEBKIT_TYPE_DOM_EVENT_TARGET (webkit_dom_event_target_get_type ()) -#define WEBKIT_DOM_EVENT_TARGET(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), WEBKIT_TYPE_DOM_EVENT_TARGET, WebKitDOMEventTarget)) -#define WEBKIT_DOM_EVENT_TARGET_CLASS(obj) (G_TYPE_CHECK_CLASS_CAST ((obj), WEBKIT_TYPE_DOM_EVENT_TARGET, WebKitDOMEventTargetIface)) -#define WEBKIT_DOM_IS_EVENT_TARGET(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), WEBKIT_TYPE_DOM_EVENT_TARGET)) -#define WEBKIT_DOM_EVENT_TARGET_GET_IFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), WEBKIT_TYPE_DOM_EVENT_TARGET, WebKitDOMEventTargetIface)) - -typedef struct _WebKitDOMEventTargetIface WebKitDOMEventTargetIface; - -struct _WebKitDOMEventTargetIface { - GTypeInterface gIface; - - /* virtual table */ - gboolean (* dispatch_event)(WebKitDOMEventTarget *target, - WebKitDOMEvent *event, - GError **error); - - gboolean (* add_event_listener)(WebKitDOMEventTarget *target, - const char *event_name, - GClosure *handler, - gboolean use_capture); - gboolean (* remove_event_listener)(WebKitDOMEventTarget *target, - const char *event_name, - GClosure *handler, - gboolean use_capture); -}; - - -WEBKIT_API GType webkit_dom_event_target_get_type(void) G_GNUC_CONST; - -/** - * webkit_dom_event_target_dispatch_event: - * @target: A #WebKitDOMEventTarget - * @event: A #WebKitDOMEvent - * @error: return location for an error or %NULL - * - * Returns: a #gboolean - */ -WEBKIT_API gboolean webkit_dom_event_target_dispatch_event(WebKitDOMEventTarget *target, - WebKitDOMEvent *event, - GError **error); - -/** - * webkit_dom_event_target_add_event_listener: - * @target: A #WebKitDOMEventTarget - * @event_name: A #gchar - * @handler: (scope async): A #GCallback - * @use_capture: A #gboolean - * @user_data: A #gpointer - * - * Returns: a #gboolean - */ -WEBKIT_API gboolean webkit_dom_event_target_add_event_listener(WebKitDOMEventTarget *target, - const char *event_name, - GCallback handler, - gboolean use_capture, - gpointer user_data); - -/** - * webkit_dom_event_target_remove_event_listener: - * @target: A #WebKitDOMEventTarget - * @event_name: A #gchar - * @handler: (scope call): A #GCallback - * @use_capture: A #gboolean - * - * Returns: a #gboolean - */ -WEBKIT_API gboolean webkit_dom_event_target_remove_event_listener(WebKitDOMEventTarget *target, - const char *event_name, - GCallback handler, - gboolean use_capture); - -/** - * webkit_dom_event_target_add_event_listener_with_closure: (rename-to webkit_dom_event_target_add_event_listener) - * @target: A #WebKitDOMEventTarget - * @event_name: A #gchar - * @handler: A #GClosure - * @use_capture: A #gboolean - * - * Version of webkit_dom_event_target_add_event_listener() using a closure - * instead of a callbacks for easier binding in other languages. - * - * Returns: a #gboolean - */ -WEBKIT_API gboolean webkit_dom_event_target_add_event_listener_with_closure(WebKitDOMEventTarget *target, - const char *event_name, - GClosure *handler, - gboolean use_capture); - -/** - * webkit_dom_event_target_remove_event_listener_with_closure: (rename-to webkit_dom_event_target_remove_event_listener) - * @target: A #WebKitDOMEventTarget - * @event_name: A #gchar - * @handler: A #GClosure - * @use_capture: A #gboolean - * - * Version of webkit_dom_event_target_remove_event_listener() using a closure - * instead of a callbacks for easier binding in other languages. - * - * Returns: a #gboolean - */ -WEBKIT_API gboolean webkit_dom_event_target_remove_event_listener_with_closure(WebKitDOMEventTarget *target, - const char *event_name, - GClosure *handler, - gboolean use_capture); - - -G_END_DECLS - -#endif /* WebKitDOMEventTarget_h */ diff --git a/Source/WebCore/bindings/gobject/WebKitDOMEventTarget.symbols b/Source/WebCore/bindings/gobject/WebKitDOMEventTarget.symbols deleted file mode 100644 index 7c575585f..000000000 --- a/Source/WebCore/bindings/gobject/WebKitDOMEventTarget.symbols +++ /dev/null @@ -1,6 +0,0 @@ -GType webkit_dom_event_target_get_type(void) -void webkit_dom_event_target_dispatch_event(WebKitDOMEventTarget*, WebKitDOMEvent* event, GError**) -gboolean webkit_dom_event_target_add_event_listener(WebKitDOMEventTarget* target, const char*, GCallback, gboolean, gpointer) -gboolean webkit_dom_event_target_remove_event_listener(WebKitDOMEventTarget*, const char*, GCallback, gboolean) -gboolean webkit_dom_event_target_add_event_listener_with_closure(WebKitDOMEventTarget*, const char*, GClosure*, gboolean) -gboolean webkit_dom_event_target_remove_event_listener_with_closure(WebKitDOMEventTarget*, const char*, GClosure*, gboolean) diff --git a/Source/WebCore/bindings/gobject/WebKitDOMEventTargetPrivate.h b/Source/WebCore/bindings/gobject/WebKitDOMEventTargetPrivate.h deleted file mode 100644 index e79be3845..000000000 --- a/Source/WebCore/bindings/gobject/WebKitDOMEventTargetPrivate.h +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright (C) 2010 Igalia S.L. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public License - * along with this library; see the file COPYING.LIB. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#ifndef WebKitDOMEventTargetPrivate_h -#define WebKitDOMEventTargetPrivate_h - -#include <webkitdom/WebKitDOMEventTarget.h> - -namespace WebCore { -class EventTarget; -} - -namespace WebKit { -WebKitDOMEventTarget* kit(WebCore::EventTarget*); -WebCore::EventTarget* core(WebKitDOMEventTarget*); -} // namespace WebKit - -#endif /* WebKitDOMEventTargetPrivate_h */ diff --git a/Source/WebCore/bindings/gobject/WebKitDOMHTMLPrivate.cpp b/Source/WebCore/bindings/gobject/WebKitDOMHTMLPrivate.cpp deleted file mode 100644 index cf32d9ad7..000000000 --- a/Source/WebCore/bindings/gobject/WebKitDOMHTMLPrivate.cpp +++ /dev/null @@ -1,267 +0,0 @@ -/* - * Copyright (C) 2013 Igalia S.L. - * - * This file is derived by hand from an automatically generated file. - * Keeping it up-to-date could potentially be done by adding - * a make_names.pl generator, or by writing a separate - * generater which takes JSHTMLElementWrapperFactory.h as input. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" -#include "WebKitDOMHTMLPrivate.h" - -#include "HTMLAnchorElement.h" -#include "HTMLAppletElement.h" -#include "HTMLAreaElement.h" -#include "HTMLAudioElement.h" -#include "HTMLBRElement.h" -#include "HTMLBaseElement.h" -#include "HTMLBaseFontElement.h" -#include "HTMLBodyElement.h" -#include "HTMLButtonElement.h" -#include "HTMLCanvasElement.h" -#include "HTMLDListElement.h" -#include "HTMLDirectoryElement.h" -#include "HTMLDivElement.h" -#include "HTMLElement.h" -#include "HTMLEmbedElement.h" -#include "HTMLFieldSetElement.h" -#include "HTMLFontElement.h" -#include "HTMLFormElement.h" -#include "HTMLFrameElement.h" -#include "HTMLFrameSetElement.h" -#include "HTMLHRElement.h" -#include "HTMLHeadElement.h" -#include "HTMLHeadingElement.h" -#include "HTMLHtmlElement.h" -#include "HTMLIFrameElement.h" -#include "HTMLImageElement.h" -#include "HTMLInputElement.h" -#include "HTMLKeygenElement.h" -#include "HTMLLIElement.h" -#include "HTMLLabelElement.h" -#include "HTMLLegendElement.h" -#include "HTMLLinkElement.h" -#include "HTMLMapElement.h" -#include "HTMLMarqueeElement.h" -#include "HTMLMenuElement.h" -#include "HTMLMetaElement.h" -#include "HTMLModElement.h" -#include "HTMLNames.h" -#include "HTMLOListElement.h" -#include "HTMLObjectElement.h" -#include "HTMLOptGroupElement.h" -#include "HTMLOptionElement.h" -#include "HTMLParagraphElement.h" -#include "HTMLParamElement.h" -#include "HTMLPreElement.h" -#include "HTMLQuoteElement.h" -#include "HTMLScriptElement.h" -#include "HTMLSelectElement.h" -#include "HTMLStyleElement.h" -#include "HTMLTableCaptionElement.h" -#include "HTMLTableCellElement.h" -#include "HTMLTableColElement.h" -#include "HTMLTableElement.h" -#include "HTMLTableRowElement.h" -#include "HTMLTableSectionElement.h" -#include "HTMLTextAreaElement.h" -#include "HTMLTitleElement.h" -#include "HTMLUListElement.h" -#include "HTMLVideoElement.h" -#include "WebKitDOMHTMLAnchorElementPrivate.h" -#include "WebKitDOMHTMLAppletElementPrivate.h" -#include "WebKitDOMHTMLAreaElementPrivate.h" -#include "WebKitDOMHTMLBRElementPrivate.h" -#include "WebKitDOMHTMLBaseElementPrivate.h" -#include "WebKitDOMHTMLBaseFontElementPrivate.h" -#include "WebKitDOMHTMLBodyElementPrivate.h" -#include "WebKitDOMHTMLButtonElementPrivate.h" -#include "WebKitDOMHTMLCanvasElementPrivate.h" -#include "WebKitDOMHTMLDListElementPrivate.h" -#include "WebKitDOMHTMLDirectoryElementPrivate.h" -#include "WebKitDOMHTMLDivElementPrivate.h" -#include "WebKitDOMHTMLElementPrivate.h" -#include "WebKitDOMHTMLEmbedElementPrivate.h" -#include "WebKitDOMHTMLFieldSetElementPrivate.h" -#include "WebKitDOMHTMLFontElementPrivate.h" -#include "WebKitDOMHTMLFormElementPrivate.h" -#include "WebKitDOMHTMLFrameElementPrivate.h" -#include "WebKitDOMHTMLFrameSetElementPrivate.h" -#include "WebKitDOMHTMLHRElementPrivate.h" -#include "WebKitDOMHTMLHeadElementPrivate.h" -#include "WebKitDOMHTMLHeadingElementPrivate.h" -#include "WebKitDOMHTMLHtmlElementPrivate.h" -#include "WebKitDOMHTMLIFrameElementPrivate.h" -#include "WebKitDOMHTMLImageElementPrivate.h" -#include "WebKitDOMHTMLInputElementPrivate.h" -#include "WebKitDOMHTMLKeygenElementPrivate.h" -#include "WebKitDOMHTMLLIElementPrivate.h" -#include "WebKitDOMHTMLLabelElementPrivate.h" -#include "WebKitDOMHTMLLegendElementPrivate.h" -#include "WebKitDOMHTMLLinkElementPrivate.h" -#include "WebKitDOMHTMLMapElementPrivate.h" -#include "WebKitDOMHTMLMarqueeElementPrivate.h" -#include "WebKitDOMHTMLMenuElementPrivate.h" -#include "WebKitDOMHTMLMetaElementPrivate.h" -#include "WebKitDOMHTMLModElementPrivate.h" -#include "WebKitDOMHTMLOListElementPrivate.h" -#include "WebKitDOMHTMLObjectElementPrivate.h" -#include "WebKitDOMHTMLOptGroupElementPrivate.h" -#include "WebKitDOMHTMLOptionElementPrivate.h" -#include "WebKitDOMHTMLParagraphElementPrivate.h" -#include "WebKitDOMHTMLParamElementPrivate.h" -#include "WebKitDOMHTMLPreElementPrivate.h" -#include "WebKitDOMHTMLQuoteElementPrivate.h" -#include "WebKitDOMHTMLScriptElementPrivate.h" -#include "WebKitDOMHTMLSelectElementPrivate.h" -#include "WebKitDOMHTMLStyleElementPrivate.h" -#include "WebKitDOMHTMLTableCaptionElementPrivate.h" -#include "WebKitDOMHTMLTableCellElementPrivate.h" -#include "WebKitDOMHTMLTableColElementPrivate.h" -#include "WebKitDOMHTMLTableElementPrivate.h" -#include "WebKitDOMHTMLTableRowElementPrivate.h" -#include "WebKitDOMHTMLTableSectionElementPrivate.h" -#include "WebKitDOMHTMLTextAreaElementPrivate.h" -#include "WebKitDOMHTMLTitleElementPrivate.h" -#include "WebKitDOMHTMLUListElementPrivate.h" - -#if ENABLE(VIDEO) -#include "WebKitDOMHTMLAudioElementPrivate.h" -#include "WebKitDOMHTMLVideoElementPrivate.h" -#endif - -namespace WebKit { - -using namespace WebCore; -using namespace WebCore::HTMLNames; - -// macro(TagName, ElementName) - -#if ENABLE(VIDEO) -#define FOR_EACH_HTML_VIDEO_TAG(macro) \ - macro(audio, Audio) \ - macro(video, Video) -#else -#define FOR_EACH_HTML_VIDEO_TAG(macro) -#endif - -#define FOR_EACH_HTML_TAG(macro) \ - FOR_EACH_HTML_VIDEO_TAG(macro) \ - macro(a, Anchor) \ - macro(applet, Applet) \ - macro(area, Area) \ - macro(base, Base) \ - macro(basefont, BaseFont) \ - macro(blockquote, Quote) \ - macro(body, Body) \ - macro(br, BR) \ - macro(button, Button) \ - macro(canvas, Canvas) \ - macro(caption, TableCaption) \ - macro(col, TableCol) \ - macro(del, Mod) \ - macro(dir, Directory) \ - macro(div, Div) \ - macro(dl, DList) \ - macro(embed, Embed) \ - macro(fieldset, FieldSet) \ - macro(font, Font) \ - macro(form, Form) \ - macro(frame, Frame) \ - macro(frameset, FrameSet) \ - macro(h1, Heading) \ - macro(head, Head) \ - macro(hr, HR) \ - macro(html, Html) \ - macro(iframe, IFrame) \ - macro(img, Image) \ - macro(input, Input) \ - macro(label, Label) \ - macro(legend, Legend) \ - macro(li, LI) \ - macro(link, Link) \ - macro(map, Map) \ - macro(marquee, Marquee) \ - macro(menu, Menu) \ - macro(meta, Meta) \ - macro(object, Object) \ - macro(ol, OList) \ - macro(optgroup, OptGroup) \ - macro(option, Option) \ - macro(p, Paragraph) \ - macro(param, Param) \ - macro(pre, Pre) \ - macro(q, Quote) \ - macro(script, Script) \ - macro(select, Select) \ - macro(style, Style) \ - macro(table, Table) \ - macro(tbody, TableSection) \ - macro(td, TableCell) \ - macro(textarea, TextArea) \ - macro(title, Title) \ - macro(tr, TableRow) \ - macro(ul, UList) \ - macro(colgroup, TableCol) \ - macro(h2, Heading) \ - macro(h3, Heading) \ - macro(h4, Heading) \ - macro(h5, Heading) \ - macro(h6, Heading) \ - macro(image, Image) \ - macro(ins, Mod) \ - macro(keygen, Keygen) \ - macro(listing, Pre) \ - macro(tfoot, TableSection) \ - macro(th, TableCell) \ - macro(thead, TableSection) \ - macro(xmp, Pre) - -#define DEFINE_HTML_WRAPPER(TagName, ElementName) \ - static WebKitDOMHTMLElement* TagName##Wrapper(HTMLElement* element) \ - { \ - return WEBKIT_DOM_HTML_ELEMENT(wrapHTML##ElementName##Element(static_cast<HTML##ElementName##Element*>(element))); \ - } - FOR_EACH_HTML_TAG(DEFINE_HTML_WRAPPER) -#undef DEFINE_HTML_WRAPPER - -typedef WebKitDOMHTMLElement* (*HTMLElementWrapFunction)(HTMLElement*); - -WebKitDOMHTMLElement* wrap(HTMLElement* element) -{ - static HashMap<const QualifiedName::QualifiedNameImpl*, HTMLElementWrapFunction> map; - if (map.isEmpty()) { -#define ADD_HTML_WRAPPER(TagName, ElementName) map.set(TagName##Tag.impl(), TagName##Wrapper); - FOR_EACH_HTML_TAG(ADD_HTML_WRAPPER) -#undef ADD_HTML_WRAPPER - } - - if (HTMLElementWrapFunction wrapFunction = map.get(element->tagQName().impl())) - return wrapFunction(element); - - return wrapHTMLElement(element); -} - -} diff --git a/Source/WebCore/bindings/gobject/WebKitDOMObject.cpp b/Source/WebCore/bindings/gobject/WebKitDOMObject.cpp deleted file mode 100644 index 22aed1f91..000000000 --- a/Source/WebCore/bindings/gobject/WebKitDOMObject.cpp +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright (C) 2008 Luke Kenneth Casson Leighton <lkcl@lkcl.net> - * Copyright (C) 2008 Martin Soto <soto@freedesktop.org> - * Copyright (C) 2008 Alp Toker <alp@atoker.com> - * Copyright (C) 2008 Apple Inc. - * Copyright (C) 2009 Igalia S.L. - */ -#include "config.h" -#include "WebKitDOMObject.h" - -enum { - PROP_0, - PROP_CORE_OBJECT -}; - -G_DEFINE_TYPE(WebKitDOMObject, webkit_dom_object, G_TYPE_OBJECT) - -static void webkit_dom_object_init(WebKitDOMObject* object) -{ -} - -static void webkit_dom_object_get_property(GObject* object, guint prop_id, GValue* value, GParamSpec* pspec) -{ - switch (prop_id) { - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); - break; - } -} - -static void webkit_dom_object_set_property(GObject* object, guint prop_id, const GValue* value, GParamSpec* pspec) -{ - switch (prop_id) { - case PROP_CORE_OBJECT: - WEBKIT_DOM_OBJECT(object)->coreObject = g_value_get_pointer(value); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); - break; - } -} - -static void webkit_dom_object_class_init(WebKitDOMObjectClass* klass) -{ - GObjectClass* gobjectClass = G_OBJECT_CLASS(klass); - gobjectClass->set_property = webkit_dom_object_set_property; - gobjectClass->get_property = webkit_dom_object_get_property; - - g_object_class_install_property(gobjectClass, - PROP_CORE_OBJECT, - g_param_spec_pointer("core-object", - "Core Object", - "The WebCore object the WebKitDOMObject wraps", - static_cast<GParamFlags>(G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY))); -} - diff --git a/Source/WebCore/bindings/gobject/WebKitDOMObject.h b/Source/WebCore/bindings/gobject/WebKitDOMObject.h deleted file mode 100644 index 3556b79e4..000000000 --- a/Source/WebCore/bindings/gobject/WebKitDOMObject.h +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright (C) 2008 Luke Kenneth Casson Leighton <lkcl@lkcl.net> - * Copyright (C) 2008 Martin Soto <soto@freedesktop.org> - * Copyright (C) 2008 Alp Toker <alp@atoker.com> - * Copyright (C) 2008 Apple Inc. - * Copyright (C) 2009 Igalia S.L. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public License - * along with this library; see the file COPYING.LIB. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - - -#ifndef WebKitDOMObject_h -#define WebKitDOMObject_h - -#include <glib-object.h> -#include <webkitdom/webkitdomdefines.h> - -G_BEGIN_DECLS - -#define WEBKIT_TYPE_DOM_OBJECT (webkit_dom_object_get_type()) -#define WEBKIT_DOM_OBJECT(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), WEBKIT_TYPE_DOM_OBJECT, WebKitDOMObject)) -#define WEBKIT_DOM_OBJECT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), WEBKIT_TYPE_DOM_OBJECT, WebKitDOMObjectClass)) -#define WEBKIT_IS_DOM_OBJECT(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), WEBKIT_TYPE_DOM_OBJECT)) -#define WEBKIT_IS_DOM_OBJECT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), WEBKIT_TYPE_DOM_OBJECT)) -#define WEBKIT_DOM_OBJECT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), WEBKIT_TYPE_DOM_OBJECT, WebKitDOMObjectClass)) - -typedef struct _WebKitDOMObjectPrivate WebKitDOMObjectPrivate; - -struct _WebKitDOMObject { - GObject parentInstance; - - gpointer coreObject; -}; - -struct _WebKitDOMObjectClass { - GObjectClass parentClass; -}; - -WEBKIT_API GType -webkit_dom_object_get_type(void); - -G_END_DECLS - -#endif /* WebKitDOMObject_h */ diff --git a/Source/WebCore/bindings/gobject/WebKitDOMObject.symbols b/Source/WebCore/bindings/gobject/WebKitDOMObject.symbols deleted file mode 100644 index 2f46d276f..000000000 --- a/Source/WebCore/bindings/gobject/WebKitDOMObject.symbols +++ /dev/null @@ -1 +0,0 @@ -GType webkit_dom_object_get_type(void) diff --git a/Source/WebCore/bindings/gobject/WebKitDOMPrivate.cpp b/Source/WebCore/bindings/gobject/WebKitDOMPrivate.cpp deleted file mode 100644 index 86d0aae4f..000000000 --- a/Source/WebCore/bindings/gobject/WebKitDOMPrivate.cpp +++ /dev/null @@ -1,171 +0,0 @@ -/* - * Copyright (C) 1999-2001 Harri Porten (porten@kde.org) - * Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved. - * Copyright (C) 2007 Samuel Weinig <sam@webkit.org> - * Copyright (C) 2008 Luke Kenneth Casson Leighton <lkcl@lkcl.net> - * Copyright (C) 2008 Martin Soto <soto@freedesktop.org> - * Copyright (C) 2009-2013 Igalia S.L. - * - * 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 - */ - -#include "config.h" -#include "WebKitDOMPrivate.h" - -#include "Blob.h" -#include "DOMObjectCache.h" -#include "Element.h" -#include "Event.h" -#include "EventException.h" -#include "EventTarget.h" -#include "File.h" -#include "HTMLElement.h" -#include "HTMLNames.h" -#include "KeyboardEvent.h" -#include "MouseEvent.h" -#include "StyleSheet.h" -#include "UIEvent.h" -#include "WebKitDOMAttrPrivate.h" -#include "WebKitDOMBlobPrivate.h" -#include "WebKitDOMCDATASectionPrivate.h" -#include "WebKitDOMCSSStyleSheetPrivate.h" -#include "WebKitDOMCommentPrivate.h" -#include "WebKitDOMDOMWindowPrivate.h" -#include "WebKitDOMDocumentFragmentPrivate.h" -#include "WebKitDOMDocumentPrivate.h" -#include "WebKitDOMDocumentTypePrivate.h" -#include "WebKitDOMElementPrivate.h" -#include "WebKitDOMEntityReferencePrivate.h" -#include "WebKitDOMEventPrivate.h" -#include "WebKitDOMEventTargetPrivate.h" -#include "WebKitDOMFilePrivate.h" -#include "WebKitDOMHTMLCollectionPrivate.h" -#include "WebKitDOMHTMLDocumentPrivate.h" -#include "WebKitDOMHTMLOptionsCollectionPrivate.h" -#include "WebKitDOMHTMLPrivate.h" -#include "WebKitDOMKeyboardEventPrivate.h" -#include "WebKitDOMMouseEventPrivate.h" -#include "WebKitDOMNodePrivate.h" -#include "WebKitDOMProcessingInstructionPrivate.h" -#include "WebKitDOMStyleSheetPrivate.h" -#include "WebKitDOMTextPrivate.h" -#include "WebKitDOMUIEventPrivate.h" -#include "WebKitDOMWheelEventPrivate.h" - -namespace WebKit { - -using namespace WebCore; -using namespace WebCore::HTMLNames; - -WebKitDOMNode* wrap(Node* node) -{ - ASSERT(node); - ASSERT(node->nodeType()); - - switch (node->nodeType()) { - case Node::ELEMENT_NODE: - if (node->isHTMLElement()) - return WEBKIT_DOM_NODE(wrap(toHTMLElement(node))); - return WEBKIT_DOM_NODE(wrapElement(toElement(node))); - case Node::ATTRIBUTE_NODE: - return WEBKIT_DOM_NODE(wrapAttr(static_cast<Attr*>(node))); - case Node::TEXT_NODE: - return WEBKIT_DOM_NODE(wrapText(toText(node))); - case Node::CDATA_SECTION_NODE: - return WEBKIT_DOM_NODE(wrapCDATASection(static_cast<CDATASection*>(node))); - case Node::ENTITY_REFERENCE_NODE: - return WEBKIT_DOM_NODE(wrapEntityReference(static_cast<EntityReference*>(node))); - case Node::PROCESSING_INSTRUCTION_NODE: - return WEBKIT_DOM_NODE(wrapProcessingInstruction(static_cast<ProcessingInstruction*>(node))); - case Node::COMMENT_NODE: - return WEBKIT_DOM_NODE(wrapComment(static_cast<Comment*>(node))); - case Node::DOCUMENT_NODE: - if (static_cast<Document*>(node)->isHTMLDocument()) - return WEBKIT_DOM_NODE(wrapHTMLDocument(static_cast<HTMLDocument*>(node))); - return WEBKIT_DOM_NODE(wrapDocument(static_cast<Document*>(node))); - case Node::DOCUMENT_TYPE_NODE: - return WEBKIT_DOM_NODE(wrapDocumentType(static_cast<DocumentType*>(node))); - case Node::DOCUMENT_FRAGMENT_NODE: - return WEBKIT_DOM_NODE(wrapDocumentFragment(static_cast<DocumentFragment*>(node))); - case Node::ENTITY_NODE: - case Node::NOTATION_NODE: - case Node::XPATH_NAMESPACE_NODE: - break; - } - - return wrapNode(node); -} - -WebKitDOMEvent* wrap(Event* event) -{ - ASSERT(event); - - if (event->isUIEvent()) { - if (event->isMouseEvent()) - return WEBKIT_DOM_EVENT(wrapMouseEvent(static_cast<MouseEvent*>(event))); - - if (event->isKeyboardEvent()) - return WEBKIT_DOM_EVENT(wrapKeyboardEvent(static_cast<KeyboardEvent*>(event))); - - if (event->eventInterface() == WheelEventInterfaceType) - return WEBKIT_DOM_EVENT(wrapWheelEvent(static_cast<WheelEvent*>(event))); - - return WEBKIT_DOM_EVENT(wrapUIEvent(static_cast<UIEvent*>(event))); - } - - return wrapEvent(event); -} - -WebKitDOMStyleSheet* wrap(StyleSheet* styleSheet) -{ - ASSERT(styleSheet); - - if (styleSheet->isCSSStyleSheet()) - return WEBKIT_DOM_STYLE_SHEET(wrapCSSStyleSheet(static_cast<CSSStyleSheet*>(styleSheet))); - return wrapStyleSheet(styleSheet); -} - -WebKitDOMHTMLCollection* wrap(HTMLCollection* collection) -{ - ASSERT(collection); - - if (collection->type() == WebCore::SelectOptions) - return WEBKIT_DOM_HTML_COLLECTION(wrapHTMLOptionsCollection(static_cast<HTMLOptionsCollection*>(collection))); - return wrapHTMLCollection(collection); -} - -WebKitDOMEventTarget* wrap(EventTarget* eventTarget) -{ - ASSERT(eventTarget); - - if (Node* node = eventTarget->toNode()) - return WEBKIT_DOM_EVENT_TARGET(kit(node)); - - if (DOMWindow* window = eventTarget->toDOMWindow()) - return WEBKIT_DOM_EVENT_TARGET(kit(window)); - - return 0; -} - -WebKitDOMBlob* wrap(Blob* blob) -{ - ASSERT(blob); - - if (blob->isFile()) - return WEBKIT_DOM_BLOB(wrapFile(static_cast<File*>(blob))); - return wrapBlob(blob); -} - -} // namespace WebKit diff --git a/Source/WebCore/bindings/gobject/WebKitDOMPrivate.h b/Source/WebCore/bindings/gobject/WebKitDOMPrivate.h deleted file mode 100644 index 2e14942cb..000000000 --- a/Source/WebCore/bindings/gobject/WebKitDOMPrivate.h +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (C) 1999-2001 Harri Porten (porten@kde.org) - * Copyright (C) 2003, 2004, 2005, 2006, 2008 Apple Inc. All rights reserved. - * Copyright (C) 2007 Samuel Weinig <sam@webkit.org> - * Copyright (C) 2008 Luke Kenneth Casson Leighton <lkcl@lkcl.net> - * Copyright (C) 2008 Martin Soto <soto@freedesktop.org> - * Copyright (C) 2009-2013 Igalia S.L. - * - * 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 WebKitDOMPrivate_h -#define WebKitDOMPrivate_h - -#include <webkitdom/webkitdomdefines.h> - -#define WEBKIT_PARAM_READABLE ((GParamFlags)(G_PARAM_READABLE | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)) -#define WEBKIT_PARAM_READWRITE ((GParamFlags)(G_PARAM_READWRITE | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)) -#define WEBKIT_WARN_FEATURE_NOT_PRESENT(Feature) g_warning("WebKitGTK+ was not compiled with support for " Feature); - -namespace WebCore { -class Node; -class Event; -class StyleSheet; -class HTMLCollection; -class EventTarget; -class Blob; -} // namespace WebCore - -namespace WebKit { -WebKitDOMNode* wrap(WebCore::Node*); -WebKitDOMEvent* wrap(WebCore::Event*); -WebKitDOMStyleSheet* wrap(WebCore::StyleSheet*); -WebKitDOMHTMLCollection* wrap(WebCore::HTMLCollection*); -WebKitDOMEventTarget* wrap(WebCore::EventTarget*); -WebKitDOMBlob* wrap(WebCore::Blob*); -} // namespace WebKit - -#endif // WebKitDOMPrivate_h diff --git a/Source/WebCore/bindings/gobject/webkitdom.symbols b/Source/WebCore/bindings/gobject/webkitdom.symbols deleted file mode 100644 index 2e54c2aab..000000000 --- a/Source/WebCore/bindings/gobject/webkitdom.symbols +++ /dev/null @@ -1,1763 +0,0 @@ -gboolean webkit_dom_battery_manager_dispatch_event(WebKitDOMBatteryManager*, WebKitDOMEvent*, GError**) -gboolean webkit_dom_battery_manager_get_charging(WebKitDOMBatteryManager*) -gdouble webkit_dom_battery_manager_get_charging_time(WebKitDOMBatteryManager*) -gdouble webkit_dom_battery_manager_get_discharging_time(WebKitDOMBatteryManager*) -gdouble webkit_dom_battery_manager_get_level(WebKitDOMBatteryManager*) -gchar* webkit_dom_css_rule_get_css_text(WebKitDOMCSSRule*) -void webkit_dom_css_rule_set_css_text(WebKitDOMCSSRule*, const gchar*, GError**) -WebKitDOMCSSStyleSheet* webkit_dom_css_rule_get_parent_style_sheet(WebKitDOMCSSRule*) -WebKitDOMCSSRule* webkit_dom_css_rule_get_parent_rule(WebKitDOMCSSRule*) -WebKitDOMCSSRule* webkit_dom_css_rule_list_item(WebKitDOMCSSRuleList*, gulong) -gulong webkit_dom_css_rule_list_get_length(WebKitDOMCSSRuleList*) -gchar* webkit_dom_css_style_declaration_get_property_value(WebKitDOMCSSStyleDeclaration*, const gchar*) -gchar* webkit_dom_css_style_declaration_remove_property(WebKitDOMCSSStyleDeclaration*, const gchar*, GError**) -gchar* webkit_dom_css_style_declaration_get_property_priority(WebKitDOMCSSStyleDeclaration*, const gchar*) -void webkit_dom_css_style_declaration_set_property(WebKitDOMCSSStyleDeclaration*, const gchar*, const gchar*, const gchar*, GError**) -gchar* webkit_dom_css_style_declaration_item(WebKitDOMCSSStyleDeclaration*, gulong) -gchar* webkit_dom_css_style_declaration_get_property_shorthand(WebKitDOMCSSStyleDeclaration*, const gchar*) -gboolean webkit_dom_css_style_declaration_is_property_implicit(WebKitDOMCSSStyleDeclaration*, const gchar*) -gchar* webkit_dom_css_style_declaration_get_css_text(WebKitDOMCSSStyleDeclaration*) -void webkit_dom_css_style_declaration_set_css_text(WebKitDOMCSSStyleDeclaration*, const gchar*, GError**) -gulong webkit_dom_css_style_declaration_get_length(WebKitDOMCSSStyleDeclaration*) -WebKitDOMCSSRule* webkit_dom_css_style_declaration_get_parent_rule(WebKitDOMCSSStyleDeclaration*) -gulong webkit_dom_css_style_sheet_insert_rule(WebKitDOMCSSStyleSheet*, const gchar*, gulong, GError**) -void webkit_dom_css_style_sheet_delete_rule(WebKitDOMCSSStyleSheet*, gulong, GError**) -glong webkit_dom_css_style_sheet_add_rule(WebKitDOMCSSStyleSheet*, const gchar*, const gchar*, gulong, GError**) -void webkit_dom_css_style_sheet_remove_rule(WebKitDOMCSSStyleSheet*, gulong, GError**) -WebKitDOMCSSRule* webkit_dom_css_style_sheet_get_owner_rule(WebKitDOMCSSStyleSheet*) -WebKitDOMCSSRuleList* webkit_dom_css_style_sheet_get_css_rules(WebKitDOMCSSStyleSheet*) -WebKitDOMCSSRuleList* webkit_dom_css_style_sheet_get_rules(WebKitDOMCSSStyleSheet*) -gchar* webkit_dom_css_value_get_css_text(WebKitDOMCSSValue*) -void webkit_dom_css_value_set_css_text(WebKitDOMCSSValue*, const gchar*, GError**) -gushort webkit_dom_css_value_get_css_value_type(WebKitDOMCSSValue*) -void webkit_dom_media_controller_play(WebKitDOMMediaController*) -void webkit_dom_media_controller_pause(WebKitDOMMediaController*) -void webkit_dom_media_controller_unpause(WebKitDOMMediaController*) -WebKitDOMTimeRanges* webkit_dom_media_controller_get_buffered(WebKitDOMMediaController*) -WebKitDOMTimeRanges* webkit_dom_media_controller_get_seekable(WebKitDOMMediaController*) -gdouble webkit_dom_media_controller_get_duration(WebKitDOMMediaController*) -gdouble webkit_dom_media_controller_get_current_time(WebKitDOMMediaController*) -void webkit_dom_media_controller_set_current_time(WebKitDOMMediaController*, gdouble) -gboolean webkit_dom_media_controller_get_paused(WebKitDOMMediaController*) -WebKitDOMTimeRanges* webkit_dom_media_controller_get_played(WebKitDOMMediaController*) -gchar* webkit_dom_media_controller_get_playback_state(WebKitDOMMediaController*) -gdouble webkit_dom_media_controller_get_default_playback_rate(WebKitDOMMediaController*) -void webkit_dom_media_controller_set_default_playback_rate(WebKitDOMMediaController*, gdouble) -gdouble webkit_dom_media_controller_get_playback_rate(WebKitDOMMediaController*) -void webkit_dom_media_controller_set_playback_rate(WebKitDOMMediaController*, gdouble) -gdouble webkit_dom_media_controller_get_volume(WebKitDOMMediaController*) -void webkit_dom_media_controller_set_volume(WebKitDOMMediaController*, gdouble, GError**) -gboolean webkit_dom_media_controller_get_muted(WebKitDOMMediaController*) -void webkit_dom_media_controller_set_muted(WebKitDOMMediaController*, gboolean) -gchar* webkit_dom_media_list_item(WebKitDOMMediaList*, gulong) -void webkit_dom_media_list_delete_medium(WebKitDOMMediaList*, const gchar*, GError**) -void webkit_dom_media_list_append_medium(WebKitDOMMediaList*, const gchar*, GError**) -gchar* webkit_dom_media_list_get_media_text(WebKitDOMMediaList*) -void webkit_dom_media_list_set_media_text(WebKitDOMMediaList*, const gchar*, GError**) -gulong webkit_dom_media_list_get_length(WebKitDOMMediaList*) -gchar* webkit_dom_media_query_list_get_media(WebKitDOMMediaQueryList*) -gboolean webkit_dom_media_query_list_get_matches(WebKitDOMMediaQueryList*) -gboolean webkit_dom_style_media_match_medium(WebKitDOMStyleMedia*, const gchar*) -gboolean webkit_dom_style_sheet_get_disabled(WebKitDOMStyleSheet*) -void webkit_dom_style_sheet_set_disabled(WebKitDOMStyleSheet*, gboolean) -WebKitDOMNode* webkit_dom_style_sheet_get_owner_node(WebKitDOMStyleSheet*) -WebKitDOMStyleSheet* webkit_dom_style_sheet_get_parent_style_sheet(WebKitDOMStyleSheet*) -gchar* webkit_dom_style_sheet_get_href(WebKitDOMStyleSheet*) -gchar* webkit_dom_style_sheet_get_title(WebKitDOMStyleSheet*) -WebKitDOMMediaList* webkit_dom_style_sheet_get_media(WebKitDOMStyleSheet*) -WebKitDOMStyleSheet* webkit_dom_style_sheet_list_item(WebKitDOMStyleSheetList*, gulong) -gulong webkit_dom_style_sheet_list_get_length(WebKitDOMStyleSheetList*) -gchar* webkit_dom_attr_get_name(WebKitDOMAttr*) -gboolean webkit_dom_attr_get_specified(WebKitDOMAttr*) -gchar* webkit_dom_attr_get_value(WebKitDOMAttr*) -void webkit_dom_attr_set_value(WebKitDOMAttr*, const gchar*, GError**) -WebKitDOMElement* webkit_dom_attr_get_owner_element(WebKitDOMAttr*) -gboolean webkit_dom_attr_get_is_id(WebKitDOMAttr*) -gchar* webkit_dom_character_data_substring_data(WebKitDOMCharacterData*, gulong, gulong, GError**) -void webkit_dom_character_data_append_data(WebKitDOMCharacterData*, const gchar*, GError**) -void webkit_dom_character_data_insert_data(WebKitDOMCharacterData*, gulong, const gchar*, GError**) -void webkit_dom_character_data_delete_data(WebKitDOMCharacterData*, gulong, gulong, GError**) -void webkit_dom_character_data_replace_data(WebKitDOMCharacterData*, gulong, gulong, const gchar*, GError**) -void webkit_dom_character_data_remove(WebKitDOMCharacterData*, GError**) -gchar* webkit_dom_character_data_get_data(WebKitDOMCharacterData*) -void webkit_dom_character_data_set_data(WebKitDOMCharacterData*, const gchar*, GError**) -gulong webkit_dom_character_data_get_length(WebKitDOMCharacterData*) -WebKitDOMElement* webkit_dom_document_create_element(WebKitDOMDocument*, const gchar*, GError**) -WebKitDOMDocumentFragment* webkit_dom_document_create_document_fragment(WebKitDOMDocument*) -WebKitDOMText* webkit_dom_document_create_text_node(WebKitDOMDocument*, const gchar*) -WebKitDOMComment* webkit_dom_document_create_comment(WebKitDOMDocument*, const gchar*) -WebKitDOMCDATASection* webkit_dom_document_create_cdata_section(WebKitDOMDocument*, const gchar*, GError**) -WebKitDOMProcessingInstruction* webkit_dom_document_create_processing_instruction(WebKitDOMDocument*, const gchar*, const gchar*, GError**) -WebKitDOMAttr* webkit_dom_document_create_attribute(WebKitDOMDocument*, const gchar*, GError**) -WebKitDOMEntityReference* webkit_dom_document_create_entity_reference(WebKitDOMDocument*, const gchar*, GError**) -WebKitDOMNodeList* webkit_dom_document_get_elements_by_tag_name(WebKitDOMDocument*, const gchar*) -WebKitDOMNode* webkit_dom_document_import_node(WebKitDOMDocument*, WebKitDOMNode*, gboolean, GError**) -WebKitDOMElement* webkit_dom_document_create_element_ns(WebKitDOMDocument*, const gchar*, const gchar*, GError**) -WebKitDOMAttr* webkit_dom_document_create_attribute_ns(WebKitDOMDocument*, const gchar*, const gchar*, GError**) -WebKitDOMNodeList* webkit_dom_document_get_elements_by_tag_name_ns(WebKitDOMDocument*, const gchar*, const gchar*) -WebKitDOMElement* webkit_dom_document_get_element_by_id(WebKitDOMDocument*, const gchar*) -WebKitDOMNode* webkit_dom_document_adopt_node(WebKitDOMDocument*, WebKitDOMNode*, GError**) -WebKitDOMEvent* webkit_dom_document_create_event(WebKitDOMDocument*, const gchar*, GError**) -WebKitDOMRange* webkit_dom_document_create_range(WebKitDOMDocument*) -WebKitDOMNodeIterator* webkit_dom_document_create_node_iterator(WebKitDOMDocument*, WebKitDOMNode*, gulong, WebKitDOMNodeFilter*, gboolean, GError**) -WebKitDOMTreeWalker* webkit_dom_document_create_tree_walker(WebKitDOMDocument*, WebKitDOMNode*, gulong, WebKitDOMNodeFilter*, gboolean, GError**) -WebKitDOMCSSStyleDeclaration* webkit_dom_document_get_override_style(WebKitDOMDocument*, WebKitDOMElement*, const gchar*) -WebKitDOMXPathExpression* webkit_dom_document_create_expression(WebKitDOMDocument*, const gchar*, WebKitDOMXPathNSResolver*, GError**) -WebKitDOMXPathNSResolver* webkit_dom_document_create_ns_resolver(WebKitDOMDocument*, WebKitDOMNode*) -WebKitDOMTouch* webkit_dom_document_create_touch(WebKitDOMDocument*, WebKitDOMDOMWindow*, WebKitDOMEventTarget*, glong, glong, glong, glong, glong, glong, glong, gfloat, gfloat, GError**) -WebKitDOMXPathResult* webkit_dom_document_evaluate(WebKitDOMDocument*, const gchar*, WebKitDOMNode*, WebKitDOMXPathNSResolver*, gushort, WebKitDOMXPathResult*, GError**) -gboolean webkit_dom_document_exec_command(WebKitDOMDocument*, const gchar*, gboolean, const gchar*) -gboolean webkit_dom_document_query_command_enabled(WebKitDOMDocument*, const gchar*) -gboolean webkit_dom_document_query_command_indeterm(WebKitDOMDocument*, const gchar*) -gboolean webkit_dom_document_query_command_state(WebKitDOMDocument*, const gchar*) -gboolean webkit_dom_document_query_command_supported(WebKitDOMDocument*, const gchar*) -gchar* webkit_dom_document_query_command_value(WebKitDOMDocument*, const gchar*) -WebKitDOMNodeList* webkit_dom_document_get_elements_by_name(WebKitDOMDocument*, const gchar*) -WebKitDOMElement* webkit_dom_document_element_from_point(WebKitDOMDocument*, glong, glong) -WebKitDOMRange* webkit_dom_document_caret_range_from_point(WebKitDOMDocument*, glong, glong) -WebKitDOMCSSStyleDeclaration* webkit_dom_document_create_css_style_declaration(WebKitDOMDocument*) -WebKitDOMNodeList* webkit_dom_document_get_elements_by_class_name(WebKitDOMDocument*, const gchar*) -WebKitDOMElement* webkit_dom_document_query_selector(WebKitDOMDocument*, const gchar*, GError**) -WebKitDOMNodeList* webkit_dom_document_query_selector_all(WebKitDOMDocument*, const gchar*, GError**) -void webkit_dom_document_webkit_cancel_full_screen(WebKitDOMDocument*) -void webkit_dom_document_webkit_exit_fullscreen(WebKitDOMDocument*) -void webkit_dom_document_webkit_exit_pointer_lock(WebKitDOMDocument*) -WebKitDOMDOMNamedFlowCollection* webkit_dom_document_webkit_get_named_flows(WebKitDOMDocument*) -WebKitDOMDocumentType* webkit_dom_document_get_doctype(WebKitDOMDocument*) -WebKitDOMDOMImplementation* webkit_dom_document_get_implementation(WebKitDOMDocument*) -WebKitDOMElement* webkit_dom_document_get_document_element(WebKitDOMDocument*) -gchar* webkit_dom_document_get_input_encoding(WebKitDOMDocument*) -gchar* webkit_dom_document_get_xml_encoding(WebKitDOMDocument*) -gchar* webkit_dom_document_get_xml_version(WebKitDOMDocument*) -void webkit_dom_document_set_xml_version(WebKitDOMDocument*, const gchar*, GError**) -gboolean webkit_dom_document_get_xml_standalone(WebKitDOMDocument*) -void webkit_dom_document_set_xml_standalone(WebKitDOMDocument*, gboolean, GError**) -gchar* webkit_dom_document_get_document_uri(WebKitDOMDocument*) -void webkit_dom_document_set_document_uri(WebKitDOMDocument*, const gchar*) -WebKitDOMDOMWindow* webkit_dom_document_get_default_view(WebKitDOMDocument*) -WebKitDOMStyleSheetList* webkit_dom_document_get_style_sheets(WebKitDOMDocument*) -gchar* webkit_dom_document_get_title(WebKitDOMDocument*) -void webkit_dom_document_set_title(WebKitDOMDocument*, const gchar*) -gchar* webkit_dom_document_get_referrer(WebKitDOMDocument*) -gchar* webkit_dom_document_get_domain(WebKitDOMDocument*) -gchar* webkit_dom_document_get_url(WebKitDOMDocument*) -gchar* webkit_dom_document_get_cookie(WebKitDOMDocument*, GError**) -void webkit_dom_document_set_cookie(WebKitDOMDocument*, const gchar*, GError**) -WebKitDOMHTMLElement* webkit_dom_document_get_body(WebKitDOMDocument*) -void webkit_dom_document_set_body(WebKitDOMDocument*, WebKitDOMHTMLElement*, GError**) -WebKitDOMHTMLHeadElement* webkit_dom_document_get_head(WebKitDOMDocument*) -WebKitDOMHTMLCollection* webkit_dom_document_get_images(WebKitDOMDocument*) -WebKitDOMHTMLCollection* webkit_dom_document_get_applets(WebKitDOMDocument*) -WebKitDOMHTMLCollection* webkit_dom_document_get_links(WebKitDOMDocument*) -WebKitDOMHTMLCollection* webkit_dom_document_get_forms(WebKitDOMDocument*) -WebKitDOMHTMLCollection* webkit_dom_document_get_anchors(WebKitDOMDocument*) -gchar* webkit_dom_document_get_last_modified(WebKitDOMDocument*) -gchar* webkit_dom_document_get_charset(WebKitDOMDocument*) -void webkit_dom_document_set_charset(WebKitDOMDocument*, const gchar*) -gchar* webkit_dom_document_get_default_charset(WebKitDOMDocument*) -gchar* webkit_dom_document_get_ready_state(WebKitDOMDocument*) -gchar* webkit_dom_document_get_character_set(WebKitDOMDocument*) -gchar* webkit_dom_document_get_preferred_stylesheet_set(WebKitDOMDocument*) -gchar* webkit_dom_document_get_selected_stylesheet_set(WebKitDOMDocument*) -void webkit_dom_document_set_selected_stylesheet_set(WebKitDOMDocument*, const gchar*) -gchar* webkit_dom_document_get_compat_mode(WebKitDOMDocument*) -gboolean webkit_dom_document_get_webkit_is_full_screen(WebKitDOMDocument*) -gboolean webkit_dom_document_get_webkit_full_screen_keyboard_input_allowed(WebKitDOMDocument*) -WebKitDOMElement* webkit_dom_document_get_webkit_current_full_screen_element(WebKitDOMDocument*) -gboolean webkit_dom_document_get_webkit_fullscreen_enabled(WebKitDOMDocument*) -WebKitDOMElement* webkit_dom_document_get_webkit_fullscreen_element(WebKitDOMDocument*) -WebKitDOMElement* webkit_dom_document_get_webkit_pointer_lock_element(WebKitDOMDocument*) -gchar* webkit_dom_document_get_visibility_state(WebKitDOMDocument*) -gboolean webkit_dom_document_get_hidden(WebKitDOMDocument*) -WebKitDOMDOMSecurityPolicy* webkit_dom_document_get_security_policy(WebKitDOMDocument*) -WebKitDOMHTMLScriptElement* webkit_dom_document_get_current_script(WebKitDOMDocument*) -WebKitDOMElement* webkit_dom_document_fragment_query_selector(WebKitDOMDocumentFragment*, const gchar*, GError**) -WebKitDOMNodeList* webkit_dom_document_fragment_query_selector_all(WebKitDOMDocumentFragment*, const gchar*, GError**) -void webkit_dom_document_type_remove(WebKitDOMDocumentType*, GError**) -gchar* webkit_dom_document_type_get_name(WebKitDOMDocumentType*) -WebKitDOMNamedNodeMap* webkit_dom_document_type_get_entities(WebKitDOMDocumentType*) -WebKitDOMNamedNodeMap* webkit_dom_document_type_get_notations(WebKitDOMDocumentType*) -gchar* webkit_dom_document_type_get_public_id(WebKitDOMDocumentType*) -gchar* webkit_dom_document_type_get_system_id(WebKitDOMDocumentType*) -gchar* webkit_dom_document_type_get_internal_subset(WebKitDOMDocumentType*) -gboolean webkit_dom_dom_implementation_has_feature(WebKitDOMDOMImplementation*, const gchar*, const gchar*) -WebKitDOMDocumentType* webkit_dom_dom_implementation_create_document_type(WebKitDOMDOMImplementation*, const gchar*, const gchar*, const gchar*, GError**) -WebKitDOMDocument* webkit_dom_dom_implementation_create_document(WebKitDOMDOMImplementation*, const gchar*, const gchar*, WebKitDOMDocumentType*, GError**) -WebKitDOMCSSStyleSheet* webkit_dom_dom_implementation_create_css_style_sheet(WebKitDOMDOMImplementation*, const gchar*, const gchar*, GError**) -WebKitDOMHTMLDocument* webkit_dom_dom_implementation_create_html_document(WebKitDOMDOMImplementation*, const gchar*) -WebKitDOMWebKitNamedFlow* webkit_dom_dom_named_flow_collection_item(WebKitDOMDOMNamedFlowCollection*, gulong) -WebKitDOMWebKitNamedFlow* webkit_dom_dom_named_flow_collection_named_item(WebKitDOMDOMNamedFlowCollection*, const gchar*) -gulong webkit_dom_dom_named_flow_collection_get_length(WebKitDOMDOMNamedFlowCollection*) -gchar* webkit_dom_dom_settable_token_list_get_value(WebKitDOMDOMSettableTokenList*) -void webkit_dom_dom_settable_token_list_set_value(WebKitDOMDOMSettableTokenList*, const gchar*) -gboolean webkit_dom_dom_security_policy_allows_connection_to(WebKitDOMDOMSecurityPolicy*, const gchar*) -gboolean webkit_dom_dom_security_policy_allows_font_from(WebKitDOMDOMSecurityPolicy*, const gchar*) -gboolean webkit_dom_dom_security_policy_allows_form_action(WebKitDOMDOMSecurityPolicy*, const gchar*) -gboolean webkit_dom_dom_security_policy_allows_frame_from(WebKitDOMDOMSecurityPolicy*, const gchar*) -gboolean webkit_dom_dom_security_policy_allows_image_from(WebKitDOMDOMSecurityPolicy*, const gchar*) -gboolean webkit_dom_dom_security_policy_allows_media_from(WebKitDOMDOMSecurityPolicy*, const gchar*) -gboolean webkit_dom_dom_security_policy_allows_object_from(WebKitDOMDOMSecurityPolicy*, const gchar*) -gboolean webkit_dom_dom_security_policy_allows_plugin_type(WebKitDOMDOMSecurityPolicy*, const gchar*) -gboolean webkit_dom_dom_security_policy_allows_script_from(WebKitDOMDOMSecurityPolicy*, const gchar*) -gboolean webkit_dom_dom_security_policy_allows_style_from(WebKitDOMDOMSecurityPolicy*, const gchar*) -gboolean webkit_dom_dom_security_policy_get_allows_eval(WebKitDOMDOMSecurityPolicy*) -gboolean webkit_dom_dom_security_policy_get_allows_inline_script(WebKitDOMDOMSecurityPolicy*) -gboolean webkit_dom_dom_security_policy_get_allows_inline_style(WebKitDOMDOMSecurityPolicy*) -gboolean webkit_dom_dom_security_policy_get_is_active(WebKitDOMDOMSecurityPolicy*) -WebKitDOMDOMStringList* webkit_dom_dom_security_policy_get_report_ur_is(WebKitDOMDOMSecurityPolicy*) -gchar* webkit_dom_dom_string_list_item(WebKitDOMDOMStringList*, gulong) -gboolean webkit_dom_dom_string_list_contains(WebKitDOMDOMStringList*, const gchar*) -gulong webkit_dom_dom_string_list_get_length(WebKitDOMDOMStringList*) -gchar* webkit_dom_dom_token_list_item(WebKitDOMDOMTokenList*, gulong) -gboolean webkit_dom_dom_token_list_contains(WebKitDOMDOMTokenList*, const gchar*, GError**) -void webkit_dom_dom_token_list_add(WebKitDOMDOMTokenList*, const gchar*, GError**) -void webkit_dom_dom_token_list_remove(WebKitDOMDOMTokenList*, const gchar*, GError**) -gboolean webkit_dom_dom_token_list_toggle(WebKitDOMDOMTokenList*, const gchar*, gboolean, GError**) -gulong webkit_dom_dom_token_list_get_length(WebKitDOMDOMTokenList*) -gchar* webkit_dom_element_get_attribute(WebKitDOMElement*, const gchar*) -void webkit_dom_element_set_attribute(WebKitDOMElement*, const gchar*, const gchar*, GError**) -void webkit_dom_element_remove_attribute(WebKitDOMElement*, const gchar*) -WebKitDOMAttr* webkit_dom_element_get_attribute_node(WebKitDOMElement*, const gchar*) -WebKitDOMAttr* webkit_dom_element_set_attribute_node(WebKitDOMElement*, WebKitDOMAttr*, GError**) -WebKitDOMAttr* webkit_dom_element_remove_attribute_node(WebKitDOMElement*, WebKitDOMAttr*, GError**) -WebKitDOMNodeList* webkit_dom_element_get_elements_by_tag_name(WebKitDOMElement*, const gchar*) -gboolean webkit_dom_element_has_attributes(WebKitDOMElement*) -gchar* webkit_dom_element_get_attribute_ns(WebKitDOMElement*, const gchar*, const gchar*) -void webkit_dom_element_set_attribute_ns(WebKitDOMElement*, const gchar*, const gchar*, const gchar*, GError**) -void webkit_dom_element_remove_attribute_ns(WebKitDOMElement*, const gchar*, const gchar*) -WebKitDOMNodeList* webkit_dom_element_get_elements_by_tag_name_ns(WebKitDOMElement*, const gchar*, const gchar*) -WebKitDOMAttr* webkit_dom_element_get_attribute_node_ns(WebKitDOMElement*, const gchar*, const gchar*) -WebKitDOMAttr* webkit_dom_element_set_attribute_node_ns(WebKitDOMElement*, WebKitDOMAttr*, GError**) -gboolean webkit_dom_element_has_attribute(WebKitDOMElement*, const gchar*) -gboolean webkit_dom_element_has_attribute_ns(WebKitDOMElement*, const gchar*, const gchar*) -void webkit_dom_element_focus(WebKitDOMElement*) -void webkit_dom_element_blur(WebKitDOMElement*) -void webkit_dom_element_scroll_into_view(WebKitDOMElement*, gboolean) -void webkit_dom_element_scroll_into_view_if_needed(WebKitDOMElement*, gboolean) -void webkit_dom_element_scroll_by_lines(WebKitDOMElement*, glong) -void webkit_dom_element_scroll_by_pages(WebKitDOMElement*, glong) -WebKitDOMNodeList* webkit_dom_element_get_elements_by_class_name(WebKitDOMElement*, const gchar*) -WebKitDOMElement* webkit_dom_element_query_selector(WebKitDOMElement*, const gchar*, GError**) -WebKitDOMNodeList* webkit_dom_element_query_selector_all(WebKitDOMElement*, const gchar*, GError**) -gboolean webkit_dom_element_webkit_matches_selector(WebKitDOMElement*, const gchar*, GError**) -void webkit_dom_element_webkit_request_full_screen(WebKitDOMElement*, gushort) -void webkit_dom_element_webkit_request_fullscreen(WebKitDOMElement*) -void webkit_dom_element_webkit_request_pointer_lock(WebKitDOMElement*) -void webkit_dom_element_remove(WebKitDOMElement*, GError**) -gchar* webkit_dom_element_get_tag_name(WebKitDOMElement*) -WebKitDOMNamedNodeMap* webkit_dom_element_get_attributes(WebKitDOMElement*) -WebKitDOMCSSStyleDeclaration* webkit_dom_element_get_style(WebKitDOMElement*) -gchar* webkit_dom_element_get_id(WebKitDOMElement*) -void webkit_dom_element_set_id(WebKitDOMElement*, const gchar*) -glong webkit_dom_element_get_offset_left(WebKitDOMElement*) -glong webkit_dom_element_get_offset_top(WebKitDOMElement*) -glong webkit_dom_element_get_offset_width(WebKitDOMElement*) -glong webkit_dom_element_get_offset_height(WebKitDOMElement*) -WebKitDOMElement* webkit_dom_element_get_offset_parent(WebKitDOMElement*) -glong webkit_dom_element_get_client_left(WebKitDOMElement*) -glong webkit_dom_element_get_client_top(WebKitDOMElement*) -glong webkit_dom_element_get_client_width(WebKitDOMElement*) -glong webkit_dom_element_get_client_height(WebKitDOMElement*) -glong webkit_dom_element_get_scroll_left(WebKitDOMElement*) -void webkit_dom_element_set_scroll_left(WebKitDOMElement*, glong) -glong webkit_dom_element_get_scroll_top(WebKitDOMElement*) -void webkit_dom_element_set_scroll_top(WebKitDOMElement*, glong) -glong webkit_dom_element_get_scroll_width(WebKitDOMElement*) -glong webkit_dom_element_get_scroll_height(WebKitDOMElement*) -gchar* webkit_dom_element_get_class_name(WebKitDOMElement*) -void webkit_dom_element_set_class_name(WebKitDOMElement*, const gchar*) -WebKitDOMDOMTokenList* webkit_dom_element_get_class_list(WebKitDOMElement*) -WebKitDOMElement* webkit_dom_element_get_first_element_child(WebKitDOMElement*) -WebKitDOMElement* webkit_dom_element_get_last_element_child(WebKitDOMElement*) -WebKitDOMElement* webkit_dom_element_get_previous_element_sibling(WebKitDOMElement*) -WebKitDOMElement* webkit_dom_element_get_next_element_sibling(WebKitDOMElement*) -gulong webkit_dom_element_get_child_element_count(WebKitDOMElement*) -gchar* webkit_dom_element_get_webkit_region_overset(WebKitDOMElement*) -void webkit_dom_event_stop_propagation(WebKitDOMEvent*) -void webkit_dom_event_prevent_default(WebKitDOMEvent*) -void webkit_dom_event_init_event(WebKitDOMEvent*, const gchar*, gboolean, gboolean) -void webkit_dom_event_stop_immediate_propagation(WebKitDOMEvent*) -WebKitDOMEventTarget* webkit_dom_event_get_target(WebKitDOMEvent*) -WebKitDOMEventTarget* webkit_dom_event_get_current_target(WebKitDOMEvent*) -gushort webkit_dom_event_get_event_phase(WebKitDOMEvent*) -gboolean webkit_dom_event_get_bubbles(WebKitDOMEvent*) -gboolean webkit_dom_event_get_cancelable(WebKitDOMEvent*) -guint32 webkit_dom_event_get_time_stamp(WebKitDOMEvent*) -gboolean webkit_dom_event_get_default_prevented(WebKitDOMEvent*) -WebKitDOMEventTarget* webkit_dom_event_get_src_element(WebKitDOMEvent*) -gboolean webkit_dom_event_get_return_value(WebKitDOMEvent*) -void webkit_dom_event_set_return_value(WebKitDOMEvent*, gboolean) -gboolean webkit_dom_event_get_cancel_bubble(WebKitDOMEvent*) -void webkit_dom_event_set_cancel_bubble(WebKitDOMEvent*, gboolean) -gboolean webkit_dom_keyboard_event_get_modifier_state(WebKitDOMKeyboardEvent*, const gchar*) -void webkit_dom_keyboard_event_init_keyboard_event(WebKitDOMKeyboardEvent*, const gchar*, gboolean, gboolean, WebKitDOMDOMWindow*, const gchar*, gulong, gboolean, gboolean, gboolean, gboolean, gboolean) -gchar* webkit_dom_keyboard_event_get_key_identifier(WebKitDOMKeyboardEvent*) -gulong webkit_dom_keyboard_event_get_key_location(WebKitDOMKeyboardEvent*) -gboolean webkit_dom_keyboard_event_get_ctrl_key(WebKitDOMKeyboardEvent*) -gboolean webkit_dom_keyboard_event_get_shift_key(WebKitDOMKeyboardEvent*) -gboolean webkit_dom_keyboard_event_get_alt_key(WebKitDOMKeyboardEvent*) -gboolean webkit_dom_keyboard_event_get_meta_key(WebKitDOMKeyboardEvent*) -gboolean webkit_dom_keyboard_event_get_alt_graph_key(WebKitDOMKeyboardEvent*) -void webkit_dom_mouse_event_init_mouse_event(WebKitDOMMouseEvent*, const gchar*, gboolean, gboolean, WebKitDOMDOMWindow*, glong, glong, glong, glong, glong, gboolean, gboolean, gboolean, gboolean, gushort, WebKitDOMEventTarget*) -glong webkit_dom_mouse_event_get_screen_x(WebKitDOMMouseEvent*) -glong webkit_dom_mouse_event_get_screen_y(WebKitDOMMouseEvent*) -glong webkit_dom_mouse_event_get_client_x(WebKitDOMMouseEvent*) -glong webkit_dom_mouse_event_get_client_y(WebKitDOMMouseEvent*) -gboolean webkit_dom_mouse_event_get_ctrl_key(WebKitDOMMouseEvent*) -gboolean webkit_dom_mouse_event_get_shift_key(WebKitDOMMouseEvent*) -gboolean webkit_dom_mouse_event_get_alt_key(WebKitDOMMouseEvent*) -gboolean webkit_dom_mouse_event_get_meta_key(WebKitDOMMouseEvent*) -gushort webkit_dom_mouse_event_get_button(WebKitDOMMouseEvent*) -WebKitDOMEventTarget* webkit_dom_mouse_event_get_related_target(WebKitDOMMouseEvent*) -glong webkit_dom_mouse_event_get_webkit_movement_x(WebKitDOMMouseEvent*) -glong webkit_dom_mouse_event_get_webkit_movement_y(WebKitDOMMouseEvent*) -glong webkit_dom_mouse_event_get_offset_x(WebKitDOMMouseEvent*) -glong webkit_dom_mouse_event_get_offset_y(WebKitDOMMouseEvent*) -glong webkit_dom_mouse_event_get_x(WebKitDOMMouseEvent*) -glong webkit_dom_mouse_event_get_y(WebKitDOMMouseEvent*) -WebKitDOMNode* webkit_dom_mouse_event_get_from_element(WebKitDOMMouseEvent*) -WebKitDOMNode* webkit_dom_mouse_event_get_to_element(WebKitDOMMouseEvent*) -WebKitDOMNode* webkit_dom_named_node_map_get_named_item(WebKitDOMNamedNodeMap*, const gchar*) -WebKitDOMNode* webkit_dom_named_node_map_set_named_item(WebKitDOMNamedNodeMap*, WebKitDOMNode*, GError**) -WebKitDOMNode* webkit_dom_named_node_map_remove_named_item(WebKitDOMNamedNodeMap*, const gchar*, GError**) -WebKitDOMNode* webkit_dom_named_node_map_item(WebKitDOMNamedNodeMap*, gulong) -WebKitDOMNode* webkit_dom_named_node_map_get_named_item_ns(WebKitDOMNamedNodeMap*, const gchar*, const gchar*) -WebKitDOMNode* webkit_dom_named_node_map_set_named_item_ns(WebKitDOMNamedNodeMap*, WebKitDOMNode*, GError**) -WebKitDOMNode* webkit_dom_named_node_map_remove_named_item_ns(WebKitDOMNamedNodeMap*, const gchar*, const gchar*, GError**) -gulong webkit_dom_named_node_map_get_length(WebKitDOMNamedNodeMap*) -WebKitDOMNode* webkit_dom_node_insert_before(WebKitDOMNode*, WebKitDOMNode*, WebKitDOMNode*, GError**) -WebKitDOMNode* webkit_dom_node_replace_child(WebKitDOMNode*, WebKitDOMNode*, WebKitDOMNode*, GError**) -WebKitDOMNode* webkit_dom_node_remove_child(WebKitDOMNode*, WebKitDOMNode*, GError**) -WebKitDOMNode* webkit_dom_node_append_child(WebKitDOMNode*, WebKitDOMNode*, GError**) -gboolean webkit_dom_node_has_child_nodes(WebKitDOMNode*) -WebKitDOMNode* webkit_dom_node_clone_node(WebKitDOMNode*, gboolean) -void webkit_dom_node_normalize(WebKitDOMNode*) -gboolean webkit_dom_node_is_supported(WebKitDOMNode*, const gchar*, const gchar*) -gboolean webkit_dom_node_is_same_node(WebKitDOMNode*, WebKitDOMNode*) -gboolean webkit_dom_node_is_equal_node(WebKitDOMNode*, WebKitDOMNode*) -gchar* webkit_dom_node_lookup_prefix(WebKitDOMNode*, const gchar*) -gboolean webkit_dom_node_is_default_namespace(WebKitDOMNode*, const gchar*) -gchar* webkit_dom_node_lookup_namespace_uri(WebKitDOMNode*, const gchar*) -gushort webkit_dom_node_compare_document_position(WebKitDOMNode*, WebKitDOMNode*) -gboolean webkit_dom_node_contains(WebKitDOMNode*, WebKitDOMNode*) -gboolean webkit_dom_node_dispatch_event(WebKitDOMNode*, WebKitDOMEvent*, GError**) -gchar* webkit_dom_node_get_node_name(WebKitDOMNode*) -gchar* webkit_dom_node_get_node_value(WebKitDOMNode*) -void webkit_dom_node_set_node_value(WebKitDOMNode*, const gchar*, GError**) -gushort webkit_dom_node_get_node_type(WebKitDOMNode*) -WebKitDOMNode* webkit_dom_node_get_parent_node(WebKitDOMNode*) -WebKitDOMNodeList* webkit_dom_node_get_child_nodes(WebKitDOMNode*) -WebKitDOMNode* webkit_dom_node_get_first_child(WebKitDOMNode*) -WebKitDOMNode* webkit_dom_node_get_last_child(WebKitDOMNode*) -WebKitDOMNode* webkit_dom_node_get_previous_sibling(WebKitDOMNode*) -WebKitDOMNode* webkit_dom_node_get_next_sibling(WebKitDOMNode*) -WebKitDOMDocument* webkit_dom_node_get_owner_document(WebKitDOMNode*) -gchar* webkit_dom_node_get_namespace_uri(WebKitDOMNode*) -gchar* webkit_dom_node_get_prefix(WebKitDOMNode*) -void webkit_dom_node_set_prefix(WebKitDOMNode*, const gchar*, GError**) -gchar* webkit_dom_node_get_local_name(WebKitDOMNode*) -gchar* webkit_dom_node_get_base_uri(WebKitDOMNode*) -gchar* webkit_dom_node_get_text_content(WebKitDOMNode*) -void webkit_dom_node_set_text_content(WebKitDOMNode*, const gchar*, GError**) -WebKitDOMElement* webkit_dom_node_get_parent_element(WebKitDOMNode*) -gshort webkit_dom_node_filter_accept_node(WebKitDOMNodeFilter*, WebKitDOMNode*) -WebKitDOMNode* webkit_dom_node_iterator_next_node(WebKitDOMNodeIterator*, GError**) -WebKitDOMNode* webkit_dom_node_iterator_previous_node(WebKitDOMNodeIterator*, GError**) -void webkit_dom_node_iterator_detach(WebKitDOMNodeIterator*) -WebKitDOMNode* webkit_dom_node_iterator_get_root(WebKitDOMNodeIterator*) -gulong webkit_dom_node_iterator_get_what_to_show(WebKitDOMNodeIterator*) -WebKitDOMNodeFilter* webkit_dom_node_iterator_get_filter(WebKitDOMNodeIterator*) -gboolean webkit_dom_node_iterator_get_expand_entity_references(WebKitDOMNodeIterator*) -WebKitDOMNode* webkit_dom_node_iterator_get_reference_node(WebKitDOMNodeIterator*) -gboolean webkit_dom_node_iterator_get_pointer_before_reference_node(WebKitDOMNodeIterator*) -WebKitDOMNode* webkit_dom_node_list_item(WebKitDOMNodeList*, gulong) -gulong webkit_dom_node_list_get_length(WebKitDOMNodeList*) -gchar* webkit_dom_processing_instruction_get_target(WebKitDOMProcessingInstruction*) -WebKitDOMStyleSheet* webkit_dom_processing_instruction_get_sheet(WebKitDOMProcessingInstruction*) -void webkit_dom_range_set_start(WebKitDOMRange*, WebKitDOMNode*, glong, GError**) -void webkit_dom_range_set_end(WebKitDOMRange*, WebKitDOMNode*, glong, GError**) -void webkit_dom_range_set_start_before(WebKitDOMRange*, WebKitDOMNode*, GError**) -void webkit_dom_range_set_start_after(WebKitDOMRange*, WebKitDOMNode*, GError**) -void webkit_dom_range_set_end_before(WebKitDOMRange*, WebKitDOMNode*, GError**) -void webkit_dom_range_set_end_after(WebKitDOMRange*, WebKitDOMNode*, GError**) -void webkit_dom_range_collapse(WebKitDOMRange*, gboolean, GError**) -void webkit_dom_range_select_node(WebKitDOMRange*, WebKitDOMNode*, GError**) -void webkit_dom_range_select_node_contents(WebKitDOMRange*, WebKitDOMNode*, GError**) -gshort webkit_dom_range_compare_boundary_points(WebKitDOMRange*, gushort, WebKitDOMRange*, GError**) -void webkit_dom_range_delete_contents(WebKitDOMRange*, GError**) -WebKitDOMDocumentFragment* webkit_dom_range_extract_contents(WebKitDOMRange*, GError**) -WebKitDOMDocumentFragment* webkit_dom_range_clone_contents(WebKitDOMRange*, GError**) -void webkit_dom_range_insert_node(WebKitDOMRange*, WebKitDOMNode*, GError**) -void webkit_dom_range_surround_contents(WebKitDOMRange*, WebKitDOMNode*, GError**) -WebKitDOMRange* webkit_dom_range_clone_range(WebKitDOMRange*, GError**) -gchar* webkit_dom_range_to_string(WebKitDOMRange*, GError**) -void webkit_dom_range_detach(WebKitDOMRange*, GError**) -WebKitDOMDocumentFragment* webkit_dom_range_create_contextual_fragment(WebKitDOMRange*, const gchar*, GError**) -gboolean webkit_dom_range_intersects_node(WebKitDOMRange*, WebKitDOMNode*, GError**) -gshort webkit_dom_range_compare_node(WebKitDOMRange*, WebKitDOMNode*, GError**) -gshort webkit_dom_range_compare_point(WebKitDOMRange*, WebKitDOMNode*, glong, GError**) -gboolean webkit_dom_range_is_point_in_range(WebKitDOMRange*, WebKitDOMNode*, glong, GError**) -void webkit_dom_range_expand(WebKitDOMRange*, const gchar*, GError**) -WebKitDOMNode* webkit_dom_range_get_start_container(WebKitDOMRange*, GError**) -glong webkit_dom_range_get_start_offset(WebKitDOMRange*, GError**) -WebKitDOMNode* webkit_dom_range_get_end_container(WebKitDOMRange*, GError**) -glong webkit_dom_range_get_end_offset(WebKitDOMRange*, GError**) -gboolean webkit_dom_range_get_collapsed(WebKitDOMRange*, GError**) -WebKitDOMNode* webkit_dom_range_get_common_ancestor_container(WebKitDOMRange*, GError**) -gchar* webkit_dom_range_get_text(WebKitDOMRange*) -WebKitDOMText* webkit_dom_text_split_text(WebKitDOMText*, gulong, GError**) -WebKitDOMText* webkit_dom_text_replace_whole_text(WebKitDOMText*, const gchar*, GError**) -gchar* webkit_dom_text_get_whole_text(WebKitDOMText*) -WebKitDOMNode* webkit_dom_tree_walker_parent_node(WebKitDOMTreeWalker*) -WebKitDOMNode* webkit_dom_tree_walker_first_child(WebKitDOMTreeWalker*) -WebKitDOMNode* webkit_dom_tree_walker_last_child(WebKitDOMTreeWalker*) -WebKitDOMNode* webkit_dom_tree_walker_previous_sibling(WebKitDOMTreeWalker*) -WebKitDOMNode* webkit_dom_tree_walker_next_sibling(WebKitDOMTreeWalker*) -WebKitDOMNode* webkit_dom_tree_walker_previous_node(WebKitDOMTreeWalker*) -WebKitDOMNode* webkit_dom_tree_walker_next_node(WebKitDOMTreeWalker*) -WebKitDOMNode* webkit_dom_tree_walker_get_root(WebKitDOMTreeWalker*) -gulong webkit_dom_tree_walker_get_what_to_show(WebKitDOMTreeWalker*) -WebKitDOMNodeFilter* webkit_dom_tree_walker_get_filter(WebKitDOMTreeWalker*) -gboolean webkit_dom_tree_walker_get_expand_entity_references(WebKitDOMTreeWalker*) -WebKitDOMNode* webkit_dom_tree_walker_get_current_node(WebKitDOMTreeWalker*) -void webkit_dom_tree_walker_set_current_node(WebKitDOMTreeWalker*, WebKitDOMNode*, GError**) -void webkit_dom_ui_event_init_ui_event(WebKitDOMUIEvent*, const gchar*, gboolean, gboolean, WebKitDOMDOMWindow*, glong) -WebKitDOMDOMWindow* webkit_dom_ui_event_get_view(WebKitDOMUIEvent*) -glong webkit_dom_ui_event_get_detail(WebKitDOMUIEvent*) -glong webkit_dom_ui_event_get_key_code(WebKitDOMUIEvent*) -glong webkit_dom_ui_event_get_char_code(WebKitDOMUIEvent*) -glong webkit_dom_ui_event_get_layer_x(WebKitDOMUIEvent*) -glong webkit_dom_ui_event_get_layer_y(WebKitDOMUIEvent*) -glong webkit_dom_ui_event_get_page_x(WebKitDOMUIEvent*) -glong webkit_dom_ui_event_get_page_y(WebKitDOMUIEvent*) -glong webkit_dom_ui_event_get_which(WebKitDOMUIEvent*) -WebKitDOMBlob* webkit_dom_blob_slice(WebKitDOMBlob*, gint64, gint64, const gchar*) -guint64 webkit_dom_blob_get_size(WebKitDOMBlob*) -gchar* webkit_dom_file_get_name(WebKitDOMFile*) -gchar* webkit_dom_file_get_webkit_relative_path(WebKitDOMFile*) -WebKitDOMFile* webkit_dom_file_list_item(WebKitDOMFileList*, gulong) -gulong webkit_dom_file_list_get_length(WebKitDOMFileList*) -gchar* webkit_dom_gamepad_get_id(WebKitDOMGamepad*) -gulong webkit_dom_gamepad_get_index(WebKitDOMGamepad*) -guint64 webkit_dom_gamepad_get_timestamp(WebKitDOMGamepad*) -WebKitDOMGamepad* webkit_dom_gamepad_list_item(WebKitDOMGamepadList*, gulong) -gulong webkit_dom_gamepad_list_get_length(WebKitDOMGamepadList*) -void webkit_dom_geolocation_clear_watch(WebKitDOMGeolocation*, glong) -gchar* webkit_dom_html_anchor_element_get_charset(WebKitDOMHTMLAnchorElement*) -void webkit_dom_html_anchor_element_set_charset(WebKitDOMHTMLAnchorElement*, const gchar*) -gchar* webkit_dom_html_anchor_element_get_coords(WebKitDOMHTMLAnchorElement*) -void webkit_dom_html_anchor_element_set_coords(WebKitDOMHTMLAnchorElement*, const gchar*) -gchar* webkit_dom_html_anchor_element_get_download(WebKitDOMHTMLAnchorElement*) -void webkit_dom_html_anchor_element_set_download(WebKitDOMHTMLAnchorElement*, const gchar*) -gchar* webkit_dom_html_anchor_element_get_href(WebKitDOMHTMLAnchorElement*) -void webkit_dom_html_anchor_element_set_href(WebKitDOMHTMLAnchorElement*, const gchar*) -gchar* webkit_dom_html_anchor_element_get_hreflang(WebKitDOMHTMLAnchorElement*) -void webkit_dom_html_anchor_element_set_hreflang(WebKitDOMHTMLAnchorElement*, const gchar*) -gchar* webkit_dom_html_anchor_element_get_name(WebKitDOMHTMLAnchorElement*) -void webkit_dom_html_anchor_element_set_name(WebKitDOMHTMLAnchorElement*, const gchar*) -gchar* webkit_dom_html_anchor_element_get_ping(WebKitDOMHTMLAnchorElement*) -void webkit_dom_html_anchor_element_set_ping(WebKitDOMHTMLAnchorElement*, const gchar*) -gchar* webkit_dom_html_anchor_element_get_rel(WebKitDOMHTMLAnchorElement*) -void webkit_dom_html_anchor_element_set_rel(WebKitDOMHTMLAnchorElement*, const gchar*) -gchar* webkit_dom_html_anchor_element_get_rev(WebKitDOMHTMLAnchorElement*) -void webkit_dom_html_anchor_element_set_rev(WebKitDOMHTMLAnchorElement*, const gchar*) -gchar* webkit_dom_html_anchor_element_get_shape(WebKitDOMHTMLAnchorElement*) -void webkit_dom_html_anchor_element_set_shape(WebKitDOMHTMLAnchorElement*, const gchar*) -gchar* webkit_dom_html_anchor_element_get_target(WebKitDOMHTMLAnchorElement*) -void webkit_dom_html_anchor_element_set_target(WebKitDOMHTMLAnchorElement*, const gchar*) -gchar* webkit_dom_html_anchor_element_get_hash(WebKitDOMHTMLAnchorElement*) -void webkit_dom_html_anchor_element_set_hash(WebKitDOMHTMLAnchorElement*, const gchar*) -gchar* webkit_dom_html_anchor_element_get_host(WebKitDOMHTMLAnchorElement*) -void webkit_dom_html_anchor_element_set_host(WebKitDOMHTMLAnchorElement*, const gchar*) -gchar* webkit_dom_html_anchor_element_get_hostname(WebKitDOMHTMLAnchorElement*) -void webkit_dom_html_anchor_element_set_hostname(WebKitDOMHTMLAnchorElement*, const gchar*) -gchar* webkit_dom_html_anchor_element_get_pathname(WebKitDOMHTMLAnchorElement*) -void webkit_dom_html_anchor_element_set_pathname(WebKitDOMHTMLAnchorElement*, const gchar*) -gchar* webkit_dom_html_anchor_element_get_port(WebKitDOMHTMLAnchorElement*) -void webkit_dom_html_anchor_element_set_port(WebKitDOMHTMLAnchorElement*, const gchar*) -gchar* webkit_dom_html_anchor_element_get_protocol(WebKitDOMHTMLAnchorElement*) -void webkit_dom_html_anchor_element_set_protocol(WebKitDOMHTMLAnchorElement*, const gchar*) -gchar* webkit_dom_html_anchor_element_get_search(WebKitDOMHTMLAnchorElement*) -void webkit_dom_html_anchor_element_set_search(WebKitDOMHTMLAnchorElement*, const gchar*) -gchar* webkit_dom_html_anchor_element_get_origin(WebKitDOMHTMLAnchorElement*) -gchar* webkit_dom_html_anchor_element_get_text(WebKitDOMHTMLAnchorElement*) -gchar* webkit_dom_html_applet_element_get_align(WebKitDOMHTMLAppletElement*) -void webkit_dom_html_applet_element_set_align(WebKitDOMHTMLAppletElement*, const gchar*) -gchar* webkit_dom_html_applet_element_get_alt(WebKitDOMHTMLAppletElement*) -void webkit_dom_html_applet_element_set_alt(WebKitDOMHTMLAppletElement*, const gchar*) -gchar* webkit_dom_html_applet_element_get_archive(WebKitDOMHTMLAppletElement*) -void webkit_dom_html_applet_element_set_archive(WebKitDOMHTMLAppletElement*, const gchar*) -gchar* webkit_dom_html_applet_element_get_code(WebKitDOMHTMLAppletElement*) -void webkit_dom_html_applet_element_set_code(WebKitDOMHTMLAppletElement*, const gchar*) -gchar* webkit_dom_html_applet_element_get_code_base(WebKitDOMHTMLAppletElement*) -void webkit_dom_html_applet_element_set_code_base(WebKitDOMHTMLAppletElement*, const gchar*) -gchar* webkit_dom_html_applet_element_get_height(WebKitDOMHTMLAppletElement*) -void webkit_dom_html_applet_element_set_height(WebKitDOMHTMLAppletElement*, const gchar*) -glong webkit_dom_html_applet_element_get_hspace(WebKitDOMHTMLAppletElement*) -void webkit_dom_html_applet_element_set_hspace(WebKitDOMHTMLAppletElement*, glong) -gchar* webkit_dom_html_applet_element_get_name(WebKitDOMHTMLAppletElement*) -void webkit_dom_html_applet_element_set_name(WebKitDOMHTMLAppletElement*, const gchar*) -gchar* webkit_dom_html_applet_element_get_object(WebKitDOMHTMLAppletElement*) -void webkit_dom_html_applet_element_set_object(WebKitDOMHTMLAppletElement*, const gchar*) -glong webkit_dom_html_applet_element_get_vspace(WebKitDOMHTMLAppletElement*) -void webkit_dom_html_applet_element_set_vspace(WebKitDOMHTMLAppletElement*, glong) -gchar* webkit_dom_html_applet_element_get_width(WebKitDOMHTMLAppletElement*) -void webkit_dom_html_applet_element_set_width(WebKitDOMHTMLAppletElement*, const gchar*) -gchar* webkit_dom_html_area_element_get_alt(WebKitDOMHTMLAreaElement*) -void webkit_dom_html_area_element_set_alt(WebKitDOMHTMLAreaElement*, const gchar*) -gchar* webkit_dom_html_area_element_get_coords(WebKitDOMHTMLAreaElement*) -void webkit_dom_html_area_element_set_coords(WebKitDOMHTMLAreaElement*, const gchar*) -gchar* webkit_dom_html_area_element_get_href(WebKitDOMHTMLAreaElement*) -void webkit_dom_html_area_element_set_href(WebKitDOMHTMLAreaElement*, const gchar*) -gboolean webkit_dom_html_area_element_get_no_href(WebKitDOMHTMLAreaElement*) -void webkit_dom_html_area_element_set_no_href(WebKitDOMHTMLAreaElement*, gboolean) -gchar* webkit_dom_html_area_element_get_ping(WebKitDOMHTMLAreaElement*) -void webkit_dom_html_area_element_set_ping(WebKitDOMHTMLAreaElement*, const gchar*) -gchar* webkit_dom_html_area_element_get_shape(WebKitDOMHTMLAreaElement*) -void webkit_dom_html_area_element_set_shape(WebKitDOMHTMLAreaElement*, const gchar*) -gchar* webkit_dom_html_area_element_get_target(WebKitDOMHTMLAreaElement*) -void webkit_dom_html_area_element_set_target(WebKitDOMHTMLAreaElement*, const gchar*) -gchar* webkit_dom_html_area_element_get_hash(WebKitDOMHTMLAreaElement*) -gchar* webkit_dom_html_area_element_get_host(WebKitDOMHTMLAreaElement*) -gchar* webkit_dom_html_area_element_get_hostname(WebKitDOMHTMLAreaElement*) -gchar* webkit_dom_html_area_element_get_pathname(WebKitDOMHTMLAreaElement*) -gchar* webkit_dom_html_area_element_get_port(WebKitDOMHTMLAreaElement*) -gchar* webkit_dom_html_area_element_get_protocol(WebKitDOMHTMLAreaElement*) -gchar* webkit_dom_html_area_element_get_search(WebKitDOMHTMLAreaElement*) -gchar* webkit_dom_html_base_element_get_href(WebKitDOMHTMLBaseElement*) -void webkit_dom_html_base_element_set_href(WebKitDOMHTMLBaseElement*, const gchar*) -gchar* webkit_dom_html_base_element_get_target(WebKitDOMHTMLBaseElement*) -void webkit_dom_html_base_element_set_target(WebKitDOMHTMLBaseElement*, const gchar*) -gchar* webkit_dom_html_base_font_element_get_color(WebKitDOMHTMLBaseFontElement*) -void webkit_dom_html_base_font_element_set_color(WebKitDOMHTMLBaseFontElement*, const gchar*) -gchar* webkit_dom_html_base_font_element_get_face(WebKitDOMHTMLBaseFontElement*) -void webkit_dom_html_base_font_element_set_face(WebKitDOMHTMLBaseFontElement*, const gchar*) -glong webkit_dom_html_base_font_element_get_size(WebKitDOMHTMLBaseFontElement*) -void webkit_dom_html_base_font_element_set_size(WebKitDOMHTMLBaseFontElement*, glong) -gchar* webkit_dom_html_body_element_get_a_link(WebKitDOMHTMLBodyElement*) -void webkit_dom_html_body_element_set_a_link(WebKitDOMHTMLBodyElement*, const gchar*) -gchar* webkit_dom_html_body_element_get_background(WebKitDOMHTMLBodyElement*) -void webkit_dom_html_body_element_set_background(WebKitDOMHTMLBodyElement*, const gchar*) -gchar* webkit_dom_html_body_element_get_bg_color(WebKitDOMHTMLBodyElement*) -void webkit_dom_html_body_element_set_bg_color(WebKitDOMHTMLBodyElement*, const gchar*) -gchar* webkit_dom_html_body_element_get_link(WebKitDOMHTMLBodyElement*) -void webkit_dom_html_body_element_set_link(WebKitDOMHTMLBodyElement*, const gchar*) -gchar* webkit_dom_html_body_element_get_text(WebKitDOMHTMLBodyElement*) -void webkit_dom_html_body_element_set_text(WebKitDOMHTMLBodyElement*, const gchar*) -gchar* webkit_dom_html_body_element_get_v_link(WebKitDOMHTMLBodyElement*) -void webkit_dom_html_body_element_set_v_link(WebKitDOMHTMLBodyElement*, const gchar*) -gchar* webkit_dom_htmlbr_element_get_clear(WebKitDOMHTMLBRElement*) -void webkit_dom_htmlbr_element_set_clear(WebKitDOMHTMLBRElement*, const gchar*) -gboolean webkit_dom_html_button_element_check_validity(WebKitDOMHTMLButtonElement*) -void webkit_dom_html_button_element_set_custom_validity(WebKitDOMHTMLButtonElement*, const gchar*) -gboolean webkit_dom_html_button_element_get_autofocus(WebKitDOMHTMLButtonElement*) -void webkit_dom_html_button_element_set_autofocus(WebKitDOMHTMLButtonElement*, gboolean) -gboolean webkit_dom_html_button_element_get_disabled(WebKitDOMHTMLButtonElement*) -void webkit_dom_html_button_element_set_disabled(WebKitDOMHTMLButtonElement*, gboolean) -WebKitDOMHTMLFormElement* webkit_dom_html_button_element_get_form(WebKitDOMHTMLButtonElement*) -gchar* webkit_dom_html_button_element_get_form_action(WebKitDOMHTMLButtonElement*) -void webkit_dom_html_button_element_set_form_action(WebKitDOMHTMLButtonElement*, const gchar*) -gchar* webkit_dom_html_button_element_get_form_enctype(WebKitDOMHTMLButtonElement*) -void webkit_dom_html_button_element_set_form_enctype(WebKitDOMHTMLButtonElement*, const gchar*) -gchar* webkit_dom_html_button_element_get_form_method(WebKitDOMHTMLButtonElement*) -void webkit_dom_html_button_element_set_form_method(WebKitDOMHTMLButtonElement*, const gchar*) -gboolean webkit_dom_html_button_element_get_form_no_validate(WebKitDOMHTMLButtonElement*) -void webkit_dom_html_button_element_set_form_no_validate(WebKitDOMHTMLButtonElement*, gboolean) -gchar* webkit_dom_html_button_element_get_form_target(WebKitDOMHTMLButtonElement*) -void webkit_dom_html_button_element_set_form_target(WebKitDOMHTMLButtonElement*, const gchar*) -gchar* webkit_dom_html_button_element_get_name(WebKitDOMHTMLButtonElement*) -void webkit_dom_html_button_element_set_name(WebKitDOMHTMLButtonElement*, const gchar*) -gchar* webkit_dom_html_button_element_get_value(WebKitDOMHTMLButtonElement*) -void webkit_dom_html_button_element_set_value(WebKitDOMHTMLButtonElement*, const gchar*) -gboolean webkit_dom_html_button_element_get_will_validate(WebKitDOMHTMLButtonElement*) -WebKitDOMValidityState* webkit_dom_html_button_element_get_validity(WebKitDOMHTMLButtonElement*) -gchar* webkit_dom_html_button_element_get_validation_message(WebKitDOMHTMLButtonElement*) -WebKitDOMNodeList* webkit_dom_html_button_element_get_labels(WebKitDOMHTMLButtonElement*) -glong webkit_dom_html_canvas_element_get_width(WebKitDOMHTMLCanvasElement*) -void webkit_dom_html_canvas_element_set_width(WebKitDOMHTMLCanvasElement*, glong) -glong webkit_dom_html_canvas_element_get_height(WebKitDOMHTMLCanvasElement*) -void webkit_dom_html_canvas_element_set_height(WebKitDOMHTMLCanvasElement*, glong) -WebKitDOMNode* webkit_dom_html_collection_item(WebKitDOMHTMLCollection*, gulong) -WebKitDOMNode* webkit_dom_html_collection_named_item(WebKitDOMHTMLCollection*, const gchar*) -gulong webkit_dom_html_collection_get_length(WebKitDOMHTMLCollection*) -gboolean webkit_dom_html_directory_element_get_compact(WebKitDOMHTMLDirectoryElement*) -void webkit_dom_html_directory_element_set_compact(WebKitDOMHTMLDirectoryElement*, gboolean) -gchar* webkit_dom_html_div_element_get_align(WebKitDOMHTMLDivElement*) -void webkit_dom_html_div_element_set_align(WebKitDOMHTMLDivElement*, const gchar*) -gboolean webkit_dom_htmld_list_element_get_compact(WebKitDOMHTMLDListElement*) -void webkit_dom_htmld_list_element_set_compact(WebKitDOMHTMLDListElement*, gboolean) -void webkit_dom_html_document_close(WebKitDOMHTMLDocument*) -void webkit_dom_html_document_clear(WebKitDOMHTMLDocument*) -void webkit_dom_html_document_capture_events(WebKitDOMHTMLDocument*) -void webkit_dom_html_document_release_events(WebKitDOMHTMLDocument*) -gboolean webkit_dom_html_document_has_focus(WebKitDOMHTMLDocument*) -WebKitDOMHTMLCollection* webkit_dom_html_document_get_embeds(WebKitDOMHTMLDocument*) -WebKitDOMHTMLCollection* webkit_dom_html_document_get_plugins(WebKitDOMHTMLDocument*) -WebKitDOMHTMLCollection* webkit_dom_html_document_get_scripts(WebKitDOMHTMLDocument*) -glong webkit_dom_html_document_get_width(WebKitDOMHTMLDocument*) -glong webkit_dom_html_document_get_height(WebKitDOMHTMLDocument*) -gchar* webkit_dom_html_document_get_dir(WebKitDOMHTMLDocument*) -void webkit_dom_html_document_set_dir(WebKitDOMHTMLDocument*, const gchar*) -gchar* webkit_dom_html_document_get_design_mode(WebKitDOMHTMLDocument*) -void webkit_dom_html_document_set_design_mode(WebKitDOMHTMLDocument*, const gchar*) -gchar* webkit_dom_html_document_get_compat_mode(WebKitDOMHTMLDocument*) -WebKitDOMElement* webkit_dom_html_document_get_active_element(WebKitDOMHTMLDocument*) -gchar* webkit_dom_html_document_get_bg_color(WebKitDOMHTMLDocument*) -void webkit_dom_html_document_set_bg_color(WebKitDOMHTMLDocument*, const gchar*) -gchar* webkit_dom_html_document_get_fg_color(WebKitDOMHTMLDocument*) -void webkit_dom_html_document_set_fg_color(WebKitDOMHTMLDocument*, const gchar*) -gchar* webkit_dom_html_document_get_alink_color(WebKitDOMHTMLDocument*) -void webkit_dom_html_document_set_alink_color(WebKitDOMHTMLDocument*, const gchar*) -gchar* webkit_dom_html_document_get_link_color(WebKitDOMHTMLDocument*) -void webkit_dom_html_document_set_link_color(WebKitDOMHTMLDocument*, const gchar*) -gchar* webkit_dom_html_document_get_vlink_color(WebKitDOMHTMLDocument*) -void webkit_dom_html_document_set_vlink_color(WebKitDOMHTMLDocument*, const gchar*) -gboolean webkit_dom_html_details_element_get_open(WebKitDOMHTMLDetailsElement*) -void webkit_dom_html_details_element_set_open(WebKitDOMHTMLDetailsElement*, gboolean) -WebKitDOMElement* webkit_dom_html_element_insert_adjacent_element(WebKitDOMHTMLElement*, const gchar*, WebKitDOMElement*, GError**) -void webkit_dom_html_element_insert_adjacent_html(WebKitDOMHTMLElement*, const gchar*, const gchar*, GError**) -void webkit_dom_html_element_insert_adjacent_text(WebKitDOMHTMLElement*, const gchar*, const gchar*, GError**) -void webkit_dom_html_element_click(WebKitDOMHTMLElement*) -gchar* webkit_dom_html_element_get_title(WebKitDOMHTMLElement*) -void webkit_dom_html_element_set_title(WebKitDOMHTMLElement*, const gchar*) -gchar* webkit_dom_html_element_get_lang(WebKitDOMHTMLElement*) -void webkit_dom_html_element_set_lang(WebKitDOMHTMLElement*, const gchar*) -gboolean webkit_dom_html_element_get_translate(WebKitDOMHTMLElement*) -void webkit_dom_html_element_set_translate(WebKitDOMHTMLElement*, gboolean) -gchar* webkit_dom_html_element_get_dir(WebKitDOMHTMLElement*) -void webkit_dom_html_element_set_dir(WebKitDOMHTMLElement*, const gchar*) -glong webkit_dom_html_element_get_tab_index(WebKitDOMHTMLElement*) -void webkit_dom_html_element_set_tab_index(WebKitDOMHTMLElement*, glong) -gboolean webkit_dom_html_element_get_draggable(WebKitDOMHTMLElement*) -void webkit_dom_html_element_set_draggable(WebKitDOMHTMLElement*, gboolean) -gchar* webkit_dom_html_element_get_webkitdropzone(WebKitDOMHTMLElement*) -void webkit_dom_html_element_set_webkitdropzone(WebKitDOMHTMLElement*, const gchar*) -gboolean webkit_dom_html_element_get_hidden(WebKitDOMHTMLElement*) -void webkit_dom_html_element_set_hidden(WebKitDOMHTMLElement*, gboolean) -gchar* webkit_dom_html_element_get_access_key(WebKitDOMHTMLElement*) -void webkit_dom_html_element_set_access_key(WebKitDOMHTMLElement*, const gchar*) -gchar* webkit_dom_html_element_get_inner_html(WebKitDOMHTMLElement*) -void webkit_dom_html_element_set_inner_html(WebKitDOMHTMLElement*, const gchar*, GError**) -gchar* webkit_dom_html_element_get_inner_text(WebKitDOMHTMLElement*) -void webkit_dom_html_element_set_inner_text(WebKitDOMHTMLElement*, const gchar*, GError**) -gchar* webkit_dom_html_element_get_outer_html(WebKitDOMHTMLElement*) -void webkit_dom_html_element_set_outer_html(WebKitDOMHTMLElement*, const gchar*, GError**) -gchar* webkit_dom_html_element_get_outer_text(WebKitDOMHTMLElement*) -void webkit_dom_html_element_set_outer_text(WebKitDOMHTMLElement*, const gchar*, GError**) -WebKitDOMHTMLCollection* webkit_dom_html_element_get_children(WebKitDOMHTMLElement*) -gchar* webkit_dom_html_element_get_content_editable(WebKitDOMHTMLElement*) -void webkit_dom_html_element_set_content_editable(WebKitDOMHTMLElement*, const gchar*, GError**) -gboolean webkit_dom_html_element_get_is_content_editable(WebKitDOMHTMLElement*) -gboolean webkit_dom_html_element_get_spellcheck(WebKitDOMHTMLElement*) -void webkit_dom_html_element_set_spellcheck(WebKitDOMHTMLElement*, gboolean) -gchar* webkit_dom_html_embed_element_get_align(WebKitDOMHTMLEmbedElement*) -void webkit_dom_html_embed_element_set_align(WebKitDOMHTMLEmbedElement*, const gchar*) -glong webkit_dom_html_embed_element_get_height(WebKitDOMHTMLEmbedElement*) -void webkit_dom_html_embed_element_set_height(WebKitDOMHTMLEmbedElement*, glong) -gchar* webkit_dom_html_embed_element_get_name(WebKitDOMHTMLEmbedElement*) -void webkit_dom_html_embed_element_set_name(WebKitDOMHTMLEmbedElement*, const gchar*) -gchar* webkit_dom_html_embed_element_get_src(WebKitDOMHTMLEmbedElement*) -void webkit_dom_html_embed_element_set_src(WebKitDOMHTMLEmbedElement*, const gchar*) -glong webkit_dom_html_embed_element_get_width(WebKitDOMHTMLEmbedElement*) -void webkit_dom_html_embed_element_set_width(WebKitDOMHTMLEmbedElement*, glong) -gboolean webkit_dom_html_field_set_element_check_validity(WebKitDOMHTMLFieldSetElement*) -void webkit_dom_html_field_set_element_set_custom_validity(WebKitDOMHTMLFieldSetElement*, const gchar*) -gboolean webkit_dom_html_field_set_element_get_disabled(WebKitDOMHTMLFieldSetElement*) -void webkit_dom_html_field_set_element_set_disabled(WebKitDOMHTMLFieldSetElement*, gboolean) -WebKitDOMHTMLFormElement* webkit_dom_html_field_set_element_get_form(WebKitDOMHTMLFieldSetElement*) -gchar* webkit_dom_html_field_set_element_get_name(WebKitDOMHTMLFieldSetElement*) -void webkit_dom_html_field_set_element_set_name(WebKitDOMHTMLFieldSetElement*, const gchar*) -WebKitDOMHTMLCollection* webkit_dom_html_field_set_element_get_elements(WebKitDOMHTMLFieldSetElement*) -gboolean webkit_dom_html_field_set_element_get_will_validate(WebKitDOMHTMLFieldSetElement*) -WebKitDOMValidityState* webkit_dom_html_field_set_element_get_validity(WebKitDOMHTMLFieldSetElement*) -gchar* webkit_dom_html_field_set_element_get_validation_message(WebKitDOMHTMLFieldSetElement*) -gchar* webkit_dom_html_font_element_get_color(WebKitDOMHTMLFontElement*) -void webkit_dom_html_font_element_set_color(WebKitDOMHTMLFontElement*, const gchar*) -gchar* webkit_dom_html_font_element_get_face(WebKitDOMHTMLFontElement*) -void webkit_dom_html_font_element_set_face(WebKitDOMHTMLFontElement*, const gchar*) -gchar* webkit_dom_html_font_element_get_size(WebKitDOMHTMLFontElement*) -void webkit_dom_html_font_element_set_size(WebKitDOMHTMLFontElement*, const gchar*) -void webkit_dom_html_form_element_submit(WebKitDOMHTMLFormElement*) -void webkit_dom_html_form_element_reset(WebKitDOMHTMLFormElement*) -gboolean webkit_dom_html_form_element_check_validity(WebKitDOMHTMLFormElement*) -gchar* webkit_dom_html_form_element_get_accept_charset(WebKitDOMHTMLFormElement*) -void webkit_dom_html_form_element_set_accept_charset(WebKitDOMHTMLFormElement*, const gchar*) -gchar* webkit_dom_html_form_element_get_action(WebKitDOMHTMLFormElement*) -void webkit_dom_html_form_element_set_action(WebKitDOMHTMLFormElement*, const gchar*) -gchar* webkit_dom_html_form_element_get_autocomplete(WebKitDOMHTMLFormElement*) -void webkit_dom_html_form_element_set_autocomplete(WebKitDOMHTMLFormElement*, const gchar*) -gchar* webkit_dom_html_form_element_get_enctype(WebKitDOMHTMLFormElement*) -void webkit_dom_html_form_element_set_enctype(WebKitDOMHTMLFormElement*, const gchar*) -gchar* webkit_dom_html_form_element_get_encoding(WebKitDOMHTMLFormElement*) -void webkit_dom_html_form_element_set_encoding(WebKitDOMHTMLFormElement*, const gchar*) -gchar* webkit_dom_html_form_element_get_method(WebKitDOMHTMLFormElement*) -void webkit_dom_html_form_element_set_method(WebKitDOMHTMLFormElement*, const gchar*) -gchar* webkit_dom_html_form_element_get_name(WebKitDOMHTMLFormElement*) -void webkit_dom_html_form_element_set_name(WebKitDOMHTMLFormElement*, const gchar*) -gboolean webkit_dom_html_form_element_get_no_validate(WebKitDOMHTMLFormElement*) -void webkit_dom_html_form_element_set_no_validate(WebKitDOMHTMLFormElement*, gboolean) -gchar* webkit_dom_html_form_element_get_target(WebKitDOMHTMLFormElement*) -void webkit_dom_html_form_element_set_target(WebKitDOMHTMLFormElement*, const gchar*) -WebKitDOMHTMLCollection* webkit_dom_html_form_element_get_elements(WebKitDOMHTMLFormElement*) -glong webkit_dom_html_form_element_get_length(WebKitDOMHTMLFormElement*) -gboolean webkit_dom_html_form_element_get_autocorrect(WebKitDOMHTMLFormElement*) -void webkit_dom_html_form_element_set_autocorrect(WebKitDOMHTMLFormElement*, gboolean) -gchar* webkit_dom_html_form_element_get_autocapitalize(WebKitDOMHTMLFormElement*) -void webkit_dom_html_form_element_set_autocapitalize(WebKitDOMHTMLFormElement*, const gchar*) -gchar* webkit_dom_html_frame_element_get_frame_border(WebKitDOMHTMLFrameElement*) -void webkit_dom_html_frame_element_set_frame_border(WebKitDOMHTMLFrameElement*, const gchar*) -gchar* webkit_dom_html_frame_element_get_long_desc(WebKitDOMHTMLFrameElement*) -void webkit_dom_html_frame_element_set_long_desc(WebKitDOMHTMLFrameElement*, const gchar*) -gchar* webkit_dom_html_frame_element_get_margin_height(WebKitDOMHTMLFrameElement*) -void webkit_dom_html_frame_element_set_margin_height(WebKitDOMHTMLFrameElement*, const gchar*) -gchar* webkit_dom_html_frame_element_get_margin_width(WebKitDOMHTMLFrameElement*) -void webkit_dom_html_frame_element_set_margin_width(WebKitDOMHTMLFrameElement*, const gchar*) -gchar* webkit_dom_html_frame_element_get_name(WebKitDOMHTMLFrameElement*) -void webkit_dom_html_frame_element_set_name(WebKitDOMHTMLFrameElement*, const gchar*) -gboolean webkit_dom_html_frame_element_get_no_resize(WebKitDOMHTMLFrameElement*) -void webkit_dom_html_frame_element_set_no_resize(WebKitDOMHTMLFrameElement*, gboolean) -gchar* webkit_dom_html_frame_element_get_scrolling(WebKitDOMHTMLFrameElement*) -void webkit_dom_html_frame_element_set_scrolling(WebKitDOMHTMLFrameElement*, const gchar*) -gchar* webkit_dom_html_frame_element_get_src(WebKitDOMHTMLFrameElement*) -void webkit_dom_html_frame_element_set_src(WebKitDOMHTMLFrameElement*, const gchar*) -WebKitDOMDocument* webkit_dom_html_frame_element_get_content_document(WebKitDOMHTMLFrameElement*) -WebKitDOMDOMWindow* webkit_dom_html_frame_element_get_content_window(WebKitDOMHTMLFrameElement*) -glong webkit_dom_html_frame_element_get_width(WebKitDOMHTMLFrameElement*) -glong webkit_dom_html_frame_element_get_height(WebKitDOMHTMLFrameElement*) -gchar* webkit_dom_html_frame_set_element_get_cols(WebKitDOMHTMLFrameSetElement*) -void webkit_dom_html_frame_set_element_set_cols(WebKitDOMHTMLFrameSetElement*, const gchar*) -gchar* webkit_dom_html_frame_set_element_get_rows(WebKitDOMHTMLFrameSetElement*) -void webkit_dom_html_frame_set_element_set_rows(WebKitDOMHTMLFrameSetElement*, const gchar*) -gchar* webkit_dom_html_head_element_get_profile(WebKitDOMHTMLHeadElement*) -void webkit_dom_html_head_element_set_profile(WebKitDOMHTMLHeadElement*, const gchar*) -gchar* webkit_dom_html_heading_element_get_align(WebKitDOMHTMLHeadingElement*) -void webkit_dom_html_heading_element_set_align(WebKitDOMHTMLHeadingElement*, const gchar*) -gchar* webkit_dom_htmlhr_element_get_align(WebKitDOMHTMLHRElement*) -void webkit_dom_htmlhr_element_set_align(WebKitDOMHTMLHRElement*, const gchar*) -gboolean webkit_dom_htmlhr_element_get_no_shade(WebKitDOMHTMLHRElement*) -void webkit_dom_htmlhr_element_set_no_shade(WebKitDOMHTMLHRElement*, gboolean) -gchar* webkit_dom_htmlhr_element_get_size(WebKitDOMHTMLHRElement*) -void webkit_dom_htmlhr_element_set_size(WebKitDOMHTMLHRElement*, const gchar*) -gchar* webkit_dom_htmlhr_element_get_width(WebKitDOMHTMLHRElement*) -void webkit_dom_htmlhr_element_set_width(WebKitDOMHTMLHRElement*, const gchar*) -gchar* webkit_dom_html_html_element_get_version(WebKitDOMHTMLHtmlElement*) -void webkit_dom_html_html_element_set_version(WebKitDOMHTMLHtmlElement*, const gchar*) -gchar* webkit_dom_html_html_element_get_manifest(WebKitDOMHTMLHtmlElement*) -void webkit_dom_html_html_element_set_manifest(WebKitDOMHTMLHtmlElement*, const gchar*) -gchar* webkit_dom_html_iframe_element_get_align(WebKitDOMHTMLIFrameElement*) -void webkit_dom_html_iframe_element_set_align(WebKitDOMHTMLIFrameElement*, const gchar*) -gchar* webkit_dom_html_iframe_element_get_frame_border(WebKitDOMHTMLIFrameElement*) -void webkit_dom_html_iframe_element_set_frame_border(WebKitDOMHTMLIFrameElement*, const gchar*) -gchar* webkit_dom_html_iframe_element_get_height(WebKitDOMHTMLIFrameElement*) -void webkit_dom_html_iframe_element_set_height(WebKitDOMHTMLIFrameElement*, const gchar*) -gchar* webkit_dom_html_iframe_element_get_long_desc(WebKitDOMHTMLIFrameElement*) -void webkit_dom_html_iframe_element_set_long_desc(WebKitDOMHTMLIFrameElement*, const gchar*) -gchar* webkit_dom_html_iframe_element_get_margin_height(WebKitDOMHTMLIFrameElement*) -void webkit_dom_html_iframe_element_set_margin_height(WebKitDOMHTMLIFrameElement*, const gchar*) -gchar* webkit_dom_html_iframe_element_get_margin_width(WebKitDOMHTMLIFrameElement*) -void webkit_dom_html_iframe_element_set_margin_width(WebKitDOMHTMLIFrameElement*, const gchar*) -gchar* webkit_dom_html_iframe_element_get_name(WebKitDOMHTMLIFrameElement*) -void webkit_dom_html_iframe_element_set_name(WebKitDOMHTMLIFrameElement*, const gchar*) -gchar* webkit_dom_html_iframe_element_get_sandbox(WebKitDOMHTMLIFrameElement*) -void webkit_dom_html_iframe_element_set_sandbox(WebKitDOMHTMLIFrameElement*, const gchar*) -gboolean webkit_dom_html_iframe_element_get_seamless(WebKitDOMHTMLIFrameElement*) -void webkit_dom_html_iframe_element_set_seamless(WebKitDOMHTMLIFrameElement*, gboolean) -gchar* webkit_dom_html_iframe_element_get_scrolling(WebKitDOMHTMLIFrameElement*) -void webkit_dom_html_iframe_element_set_scrolling(WebKitDOMHTMLIFrameElement*, const gchar*) -gchar* webkit_dom_html_iframe_element_get_src(WebKitDOMHTMLIFrameElement*) -void webkit_dom_html_iframe_element_set_src(WebKitDOMHTMLIFrameElement*, const gchar*) -gchar* webkit_dom_html_iframe_element_get_srcdoc(WebKitDOMHTMLIFrameElement*) -void webkit_dom_html_iframe_element_set_srcdoc(WebKitDOMHTMLIFrameElement*, const gchar*) -gchar* webkit_dom_html_iframe_element_get_width(WebKitDOMHTMLIFrameElement*) -void webkit_dom_html_iframe_element_set_width(WebKitDOMHTMLIFrameElement*, const gchar*) -WebKitDOMDocument* webkit_dom_html_iframe_element_get_content_document(WebKitDOMHTMLIFrameElement*) -WebKitDOMDOMWindow* webkit_dom_html_iframe_element_get_content_window(WebKitDOMHTMLIFrameElement*) -gchar* webkit_dom_html_image_element_get_name(WebKitDOMHTMLImageElement*) -void webkit_dom_html_image_element_set_name(WebKitDOMHTMLImageElement*, const gchar*) -gchar* webkit_dom_html_image_element_get_align(WebKitDOMHTMLImageElement*) -void webkit_dom_html_image_element_set_align(WebKitDOMHTMLImageElement*, const gchar*) -gchar* webkit_dom_html_image_element_get_alt(WebKitDOMHTMLImageElement*) -void webkit_dom_html_image_element_set_alt(WebKitDOMHTMLImageElement*, const gchar*) -gchar* webkit_dom_html_image_element_get_border(WebKitDOMHTMLImageElement*) -void webkit_dom_html_image_element_set_border(WebKitDOMHTMLImageElement*, const gchar*) -gchar* webkit_dom_html_image_element_get_cross_origin(WebKitDOMHTMLImageElement*) -void webkit_dom_html_image_element_set_cross_origin(WebKitDOMHTMLImageElement*, const gchar*) -glong webkit_dom_html_image_element_get_height(WebKitDOMHTMLImageElement*) -void webkit_dom_html_image_element_set_height(WebKitDOMHTMLImageElement*, glong) -glong webkit_dom_html_image_element_get_hspace(WebKitDOMHTMLImageElement*) -void webkit_dom_html_image_element_set_hspace(WebKitDOMHTMLImageElement*, glong) -gboolean webkit_dom_html_image_element_get_is_map(WebKitDOMHTMLImageElement*) -void webkit_dom_html_image_element_set_is_map(WebKitDOMHTMLImageElement*, gboolean) -gchar* webkit_dom_html_image_element_get_long_desc(WebKitDOMHTMLImageElement*) -void webkit_dom_html_image_element_set_long_desc(WebKitDOMHTMLImageElement*, const gchar*) -gchar* webkit_dom_html_image_element_get_src(WebKitDOMHTMLImageElement*) -void webkit_dom_html_image_element_set_src(WebKitDOMHTMLImageElement*, const gchar*) -gchar* webkit_dom_html_image_element_get_srcset(WebKitDOMHTMLImageElement*) -void webkit_dom_html_image_element_set_srcset(WebKitDOMHTMLImageElement*, const gchar*) -gchar* webkit_dom_html_image_element_get_use_map(WebKitDOMHTMLImageElement*) -void webkit_dom_html_image_element_set_use_map(WebKitDOMHTMLImageElement*, const gchar*) -glong webkit_dom_html_image_element_get_vspace(WebKitDOMHTMLImageElement*) -void webkit_dom_html_image_element_set_vspace(WebKitDOMHTMLImageElement*, glong) -glong webkit_dom_html_image_element_get_width(WebKitDOMHTMLImageElement*) -void webkit_dom_html_image_element_set_width(WebKitDOMHTMLImageElement*, glong) -gboolean webkit_dom_html_image_element_get_complete(WebKitDOMHTMLImageElement*) -gchar* webkit_dom_html_image_element_get_lowsrc(WebKitDOMHTMLImageElement*) -void webkit_dom_html_image_element_set_lowsrc(WebKitDOMHTMLImageElement*, const gchar*) -glong webkit_dom_html_image_element_get_natural_height(WebKitDOMHTMLImageElement*) -glong webkit_dom_html_image_element_get_natural_width(WebKitDOMHTMLImageElement*) -glong webkit_dom_html_image_element_get_x(WebKitDOMHTMLImageElement*) -glong webkit_dom_html_image_element_get_y(WebKitDOMHTMLImageElement*) -void webkit_dom_html_input_element_step_up(WebKitDOMHTMLInputElement*, glong, GError**) -void webkit_dom_html_input_element_step_down(WebKitDOMHTMLInputElement*, glong, GError**) -gboolean webkit_dom_html_input_element_check_validity(WebKitDOMHTMLInputElement*) -void webkit_dom_html_input_element_set_custom_validity(WebKitDOMHTMLInputElement*, const gchar*) -void webkit_dom_html_input_element_select(WebKitDOMHTMLInputElement*) -void webkit_dom_html_input_element_set_range_text(WebKitDOMHTMLInputElement*, const gchar*, gulong, gulong, const gchar*, GError**) -void webkit_dom_html_input_element_set_value_for_user(WebKitDOMHTMLInputElement*, const gchar*) -gchar* webkit_dom_html_input_element_get_accept(WebKitDOMHTMLInputElement*) -void webkit_dom_html_input_element_set_accept(WebKitDOMHTMLInputElement*, const gchar*) -gchar* webkit_dom_html_input_element_get_alt(WebKitDOMHTMLInputElement*) -void webkit_dom_html_input_element_set_alt(WebKitDOMHTMLInputElement*, const gchar*) -gchar* webkit_dom_html_input_element_get_autocomplete(WebKitDOMHTMLInputElement*) -void webkit_dom_html_input_element_set_autocomplete(WebKitDOMHTMLInputElement*, const gchar*) -gboolean webkit_dom_html_input_element_get_autofocus(WebKitDOMHTMLInputElement*) -void webkit_dom_html_input_element_set_autofocus(WebKitDOMHTMLInputElement*, gboolean) -gboolean webkit_dom_html_input_element_get_default_checked(WebKitDOMHTMLInputElement*) -void webkit_dom_html_input_element_set_default_checked(WebKitDOMHTMLInputElement*, gboolean) -gboolean webkit_dom_html_input_element_get_checked(WebKitDOMHTMLInputElement*) -void webkit_dom_html_input_element_set_checked(WebKitDOMHTMLInputElement*, gboolean) -gchar* webkit_dom_html_input_element_get_dir_name(WebKitDOMHTMLInputElement*) -void webkit_dom_html_input_element_set_dir_name(WebKitDOMHTMLInputElement*, const gchar*) -gboolean webkit_dom_html_input_element_get_disabled(WebKitDOMHTMLInputElement*) -void webkit_dom_html_input_element_set_disabled(WebKitDOMHTMLInputElement*, gboolean) -WebKitDOMHTMLFormElement* webkit_dom_html_input_element_get_form(WebKitDOMHTMLInputElement*) -WebKitDOMFileList* webkit_dom_html_input_element_get_files(WebKitDOMHTMLInputElement*) -void webkit_dom_html_input_element_set_files(WebKitDOMHTMLInputElement*, WebKitDOMFileList*) -gchar* webkit_dom_html_input_element_get_form_action(WebKitDOMHTMLInputElement*) -void webkit_dom_html_input_element_set_form_action(WebKitDOMHTMLInputElement*, const gchar*) -gchar* webkit_dom_html_input_element_get_form_enctype(WebKitDOMHTMLInputElement*) -void webkit_dom_html_input_element_set_form_enctype(WebKitDOMHTMLInputElement*, const gchar*) -gchar* webkit_dom_html_input_element_get_form_method(WebKitDOMHTMLInputElement*) -void webkit_dom_html_input_element_set_form_method(WebKitDOMHTMLInputElement*, const gchar*) -gboolean webkit_dom_html_input_element_get_form_no_validate(WebKitDOMHTMLInputElement*) -void webkit_dom_html_input_element_set_form_no_validate(WebKitDOMHTMLInputElement*, gboolean) -gchar* webkit_dom_html_input_element_get_form_target(WebKitDOMHTMLInputElement*) -void webkit_dom_html_input_element_set_form_target(WebKitDOMHTMLInputElement*, const gchar*) -gulong webkit_dom_html_input_element_get_height(WebKitDOMHTMLInputElement*) -void webkit_dom_html_input_element_set_height(WebKitDOMHTMLInputElement*, gulong) -gboolean webkit_dom_html_input_element_get_indeterminate(WebKitDOMHTMLInputElement*) -void webkit_dom_html_input_element_set_indeterminate(WebKitDOMHTMLInputElement*, gboolean) -WebKitDOMHTMLElement* webkit_dom_html_input_element_get_list(WebKitDOMHTMLInputElement*) -gchar* webkit_dom_html_input_element_get_max(WebKitDOMHTMLInputElement*) -void webkit_dom_html_input_element_set_max(WebKitDOMHTMLInputElement*, const gchar*) -glong webkit_dom_html_input_element_get_max_length(WebKitDOMHTMLInputElement*) -void webkit_dom_html_input_element_set_max_length(WebKitDOMHTMLInputElement*, glong, GError**) -gchar* webkit_dom_html_input_element_get_min(WebKitDOMHTMLInputElement*) -void webkit_dom_html_input_element_set_min(WebKitDOMHTMLInputElement*, const gchar*) -gboolean webkit_dom_html_input_element_get_multiple(WebKitDOMHTMLInputElement*) -void webkit_dom_html_input_element_set_multiple(WebKitDOMHTMLInputElement*, gboolean) -gchar* webkit_dom_html_input_element_get_name(WebKitDOMHTMLInputElement*) -void webkit_dom_html_input_element_set_name(WebKitDOMHTMLInputElement*, const gchar*) -gchar* webkit_dom_html_input_element_get_pattern(WebKitDOMHTMLInputElement*) -void webkit_dom_html_input_element_set_pattern(WebKitDOMHTMLInputElement*, const gchar*) -gchar* webkit_dom_html_input_element_get_placeholder(WebKitDOMHTMLInputElement*) -void webkit_dom_html_input_element_set_placeholder(WebKitDOMHTMLInputElement*, const gchar*) -gboolean webkit_dom_html_input_element_get_read_only(WebKitDOMHTMLInputElement*) -void webkit_dom_html_input_element_set_read_only(WebKitDOMHTMLInputElement*, gboolean) -gboolean webkit_dom_html_input_element_get_required(WebKitDOMHTMLInputElement*) -void webkit_dom_html_input_element_set_required(WebKitDOMHTMLInputElement*, gboolean) -gulong webkit_dom_html_input_element_get_size(WebKitDOMHTMLInputElement*) -void webkit_dom_html_input_element_set_size(WebKitDOMHTMLInputElement*, gulong, GError**) -gchar* webkit_dom_html_input_element_get_src(WebKitDOMHTMLInputElement*) -void webkit_dom_html_input_element_set_src(WebKitDOMHTMLInputElement*, const gchar*) -gchar* webkit_dom_html_input_element_get_step(WebKitDOMHTMLInputElement*) -void webkit_dom_html_input_element_set_step(WebKitDOMHTMLInputElement*, const gchar*) -gchar* webkit_dom_html_input_element_get_default_value(WebKitDOMHTMLInputElement*) -void webkit_dom_html_input_element_set_default_value(WebKitDOMHTMLInputElement*, const gchar*) -gchar* webkit_dom_html_input_element_get_value(WebKitDOMHTMLInputElement*) -void webkit_dom_html_input_element_set_value(WebKitDOMHTMLInputElement*, const gchar*) -gdouble webkit_dom_html_input_element_get_value_as_number(WebKitDOMHTMLInputElement*) -void webkit_dom_html_input_element_set_value_as_number(WebKitDOMHTMLInputElement*, gdouble, GError**) -gulong webkit_dom_html_input_element_get_width(WebKitDOMHTMLInputElement*) -void webkit_dom_html_input_element_set_width(WebKitDOMHTMLInputElement*, gulong) -gboolean webkit_dom_html_input_element_get_will_validate(WebKitDOMHTMLInputElement*) -WebKitDOMValidityState* webkit_dom_html_input_element_get_validity(WebKitDOMHTMLInputElement*) -gchar* webkit_dom_html_input_element_get_validation_message(WebKitDOMHTMLInputElement*) -WebKitDOMNodeList* webkit_dom_html_input_element_get_labels(WebKitDOMHTMLInputElement*) -gchar* webkit_dom_html_input_element_get_align(WebKitDOMHTMLInputElement*) -void webkit_dom_html_input_element_set_align(WebKitDOMHTMLInputElement*, const gchar*) -gboolean webkit_dom_html_input_element_get_webkitdirectory(WebKitDOMHTMLInputElement*) -void webkit_dom_html_input_element_set_webkitdirectory(WebKitDOMHTMLInputElement*, gboolean) -gchar* webkit_dom_html_input_element_get_use_map(WebKitDOMHTMLInputElement*) -void webkit_dom_html_input_element_set_use_map(WebKitDOMHTMLInputElement*, const gchar*) -gboolean webkit_dom_html_input_element_get_incremental(WebKitDOMHTMLInputElement*) -void webkit_dom_html_input_element_set_incremental(WebKitDOMHTMLInputElement*, gboolean) -gboolean webkit_dom_html_input_element_get_webkit_speech(WebKitDOMHTMLInputElement*) -void webkit_dom_html_input_element_set_webkit_speech(WebKitDOMHTMLInputElement*, gboolean) -gboolean webkit_dom_html_input_element_get_webkit_grammar(WebKitDOMHTMLInputElement*) -void webkit_dom_html_input_element_set_webkit_grammar(WebKitDOMHTMLInputElement*, gboolean) -gboolean webkit_dom_html_input_element_get_autocorrect(WebKitDOMHTMLInputElement*) -void webkit_dom_html_input_element_set_autocorrect(WebKitDOMHTMLInputElement*, gboolean) -gchar* webkit_dom_html_input_element_get_autocapitalize(WebKitDOMHTMLInputElement*) -void webkit_dom_html_input_element_set_autocapitalize(WebKitDOMHTMLInputElement*, const gchar*) -gchar* webkit_dom_html_input_element_get_capture(WebKitDOMHTMLInputElement*) -void webkit_dom_html_input_element_set_capture(WebKitDOMHTMLInputElement*, const gchar*) -gboolean webkit_dom_html_keygen_element_check_validity(WebKitDOMHTMLKeygenElement*) -void webkit_dom_html_keygen_element_set_custom_validity(WebKitDOMHTMLKeygenElement*, const gchar*) -gboolean webkit_dom_html_keygen_element_get_autofocus(WebKitDOMHTMLKeygenElement*) -void webkit_dom_html_keygen_element_set_autofocus(WebKitDOMHTMLKeygenElement*, gboolean) -gchar* webkit_dom_html_keygen_element_get_challenge(WebKitDOMHTMLKeygenElement*) -void webkit_dom_html_keygen_element_set_challenge(WebKitDOMHTMLKeygenElement*, const gchar*) -gboolean webkit_dom_html_keygen_element_get_disabled(WebKitDOMHTMLKeygenElement*) -void webkit_dom_html_keygen_element_set_disabled(WebKitDOMHTMLKeygenElement*, gboolean) -WebKitDOMHTMLFormElement* webkit_dom_html_keygen_element_get_form(WebKitDOMHTMLKeygenElement*) -gchar* webkit_dom_html_keygen_element_get_keytype(WebKitDOMHTMLKeygenElement*) -void webkit_dom_html_keygen_element_set_keytype(WebKitDOMHTMLKeygenElement*, const gchar*) -gchar* webkit_dom_html_keygen_element_get_name(WebKitDOMHTMLKeygenElement*) -void webkit_dom_html_keygen_element_set_name(WebKitDOMHTMLKeygenElement*, const gchar*) -gboolean webkit_dom_html_keygen_element_get_will_validate(WebKitDOMHTMLKeygenElement*) -WebKitDOMValidityState* webkit_dom_html_keygen_element_get_validity(WebKitDOMHTMLKeygenElement*) -gchar* webkit_dom_html_keygen_element_get_validation_message(WebKitDOMHTMLKeygenElement*) -WebKitDOMNodeList* webkit_dom_html_keygen_element_get_labels(WebKitDOMHTMLKeygenElement*) -WebKitDOMHTMLFormElement* webkit_dom_html_label_element_get_form(WebKitDOMHTMLLabelElement*) -gchar* webkit_dom_html_label_element_get_html_for(WebKitDOMHTMLLabelElement*) -void webkit_dom_html_label_element_set_html_for(WebKitDOMHTMLLabelElement*, const gchar*) -WebKitDOMHTMLElement* webkit_dom_html_label_element_get_control(WebKitDOMHTMLLabelElement*) -WebKitDOMHTMLFormElement* webkit_dom_html_legend_element_get_form(WebKitDOMHTMLLegendElement*) -gchar* webkit_dom_html_legend_element_get_align(WebKitDOMHTMLLegendElement*) -void webkit_dom_html_legend_element_set_align(WebKitDOMHTMLLegendElement*, const gchar*) -glong webkit_dom_htmlli_element_get_value(WebKitDOMHTMLLIElement*) -void webkit_dom_htmlli_element_set_value(WebKitDOMHTMLLIElement*, glong) -gboolean webkit_dom_html_link_element_get_disabled(WebKitDOMHTMLLinkElement*) -void webkit_dom_html_link_element_set_disabled(WebKitDOMHTMLLinkElement*, gboolean) -gchar* webkit_dom_html_link_element_get_charset(WebKitDOMHTMLLinkElement*) -void webkit_dom_html_link_element_set_charset(WebKitDOMHTMLLinkElement*, const gchar*) -gchar* webkit_dom_html_link_element_get_href(WebKitDOMHTMLLinkElement*) -void webkit_dom_html_link_element_set_href(WebKitDOMHTMLLinkElement*, const gchar*) -gchar* webkit_dom_html_link_element_get_hreflang(WebKitDOMHTMLLinkElement*) -void webkit_dom_html_link_element_set_hreflang(WebKitDOMHTMLLinkElement*, const gchar*) -gchar* webkit_dom_html_link_element_get_media(WebKitDOMHTMLLinkElement*) -void webkit_dom_html_link_element_set_media(WebKitDOMHTMLLinkElement*, const gchar*) -gchar* webkit_dom_html_link_element_get_rel(WebKitDOMHTMLLinkElement*) -void webkit_dom_html_link_element_set_rel(WebKitDOMHTMLLinkElement*, const gchar*) -gchar* webkit_dom_html_link_element_get_rev(WebKitDOMHTMLLinkElement*) -void webkit_dom_html_link_element_set_rev(WebKitDOMHTMLLinkElement*, const gchar*) -gchar* webkit_dom_html_link_element_get_target(WebKitDOMHTMLLinkElement*) -void webkit_dom_html_link_element_set_target(WebKitDOMHTMLLinkElement*, const gchar*) -WebKitDOMStyleSheet* webkit_dom_html_link_element_get_sheet(WebKitDOMHTMLLinkElement*) -WebKitDOMHTMLCollection* webkit_dom_html_map_element_get_areas(WebKitDOMHTMLMapElement*) -gchar* webkit_dom_html_map_element_get_name(WebKitDOMHTMLMapElement*) -void webkit_dom_html_map_element_set_name(WebKitDOMHTMLMapElement*, const gchar*) -void webkit_dom_html_marquee_element_start(WebKitDOMHTMLMarqueeElement*) -void webkit_dom_html_marquee_element_stop(WebKitDOMHTMLMarqueeElement*) -gchar* webkit_dom_html_marquee_element_get_behavior(WebKitDOMHTMLMarqueeElement*) -void webkit_dom_html_marquee_element_set_behavior(WebKitDOMHTMLMarqueeElement*, const gchar*) -gchar* webkit_dom_html_marquee_element_get_bg_color(WebKitDOMHTMLMarqueeElement*) -void webkit_dom_html_marquee_element_set_bg_color(WebKitDOMHTMLMarqueeElement*, const gchar*) -gchar* webkit_dom_html_marquee_element_get_direction(WebKitDOMHTMLMarqueeElement*) -void webkit_dom_html_marquee_element_set_direction(WebKitDOMHTMLMarqueeElement*, const gchar*) -gchar* webkit_dom_html_marquee_element_get_height(WebKitDOMHTMLMarqueeElement*) -void webkit_dom_html_marquee_element_set_height(WebKitDOMHTMLMarqueeElement*, const gchar*) -gulong webkit_dom_html_marquee_element_get_hspace(WebKitDOMHTMLMarqueeElement*) -void webkit_dom_html_marquee_element_set_hspace(WebKitDOMHTMLMarqueeElement*, gulong) -glong webkit_dom_html_marquee_element_get_loop(WebKitDOMHTMLMarqueeElement*) -void webkit_dom_html_marquee_element_set_loop(WebKitDOMHTMLMarqueeElement*, glong, GError**) -glong webkit_dom_html_marquee_element_get_scroll_amount(WebKitDOMHTMLMarqueeElement*) -void webkit_dom_html_marquee_element_set_scroll_amount(WebKitDOMHTMLMarqueeElement*, glong, GError**) -glong webkit_dom_html_marquee_element_get_scroll_delay(WebKitDOMHTMLMarqueeElement*) -void webkit_dom_html_marquee_element_set_scroll_delay(WebKitDOMHTMLMarqueeElement*, glong, GError**) -gboolean webkit_dom_html_marquee_element_get_true_speed(WebKitDOMHTMLMarqueeElement*) -void webkit_dom_html_marquee_element_set_true_speed(WebKitDOMHTMLMarqueeElement*, gboolean) -gulong webkit_dom_html_marquee_element_get_vspace(WebKitDOMHTMLMarqueeElement*) -void webkit_dom_html_marquee_element_set_vspace(WebKitDOMHTMLMarqueeElement*, gulong) -gchar* webkit_dom_html_marquee_element_get_width(WebKitDOMHTMLMarqueeElement*) -void webkit_dom_html_marquee_element_set_width(WebKitDOMHTMLMarqueeElement*, const gchar*) -void webkit_dom_html_media_element_load(WebKitDOMHTMLMediaElement*) -gchar* webkit_dom_html_media_element_can_play_type(WebKitDOMHTMLMediaElement*, const gchar*) -void webkit_dom_html_media_element_play(WebKitDOMHTMLMediaElement*) -void webkit_dom_html_media_element_pause(WebKitDOMHTMLMediaElement*) -void webkit_dom_html_media_element_fast_seek(WebKitDOMHTMLMediaElement*, gdouble) -WebKitDOMTextTrack* webkit_dom_html_media_element_add_text_track(WebKitDOMHTMLMediaElement*, const gchar*, const gchar*, const gchar*, GError**) -void webkit_dom_html_media_element_webkit_show_playback_target_picker(WebKitDOMHTMLMediaElement*) -WebKitDOMMediaError* webkit_dom_html_media_element_get_error(WebKitDOMHTMLMediaElement*) -gchar* webkit_dom_html_media_element_get_src(WebKitDOMHTMLMediaElement*) -void webkit_dom_html_media_element_set_src(WebKitDOMHTMLMediaElement*, const gchar*) -gchar* webkit_dom_html_media_element_get_current_src(WebKitDOMHTMLMediaElement*) -gushort webkit_dom_html_media_element_get_network_state(WebKitDOMHTMLMediaElement*) -gchar* webkit_dom_html_media_element_get_preload(WebKitDOMHTMLMediaElement*) -void webkit_dom_html_media_element_set_preload(WebKitDOMHTMLMediaElement*, const gchar*) -WebKitDOMTimeRanges* webkit_dom_html_media_element_get_buffered(WebKitDOMHTMLMediaElement*) -gushort webkit_dom_html_media_element_get_ready_state(WebKitDOMHTMLMediaElement*) -gboolean webkit_dom_html_media_element_get_seeking(WebKitDOMHTMLMediaElement*) -gdouble webkit_dom_html_media_element_get_current_time(WebKitDOMHTMLMediaElement*) -gdouble webkit_dom_html_media_element_get_duration(WebKitDOMHTMLMediaElement*) -gboolean webkit_dom_html_media_element_get_paused(WebKitDOMHTMLMediaElement*) -gdouble webkit_dom_html_media_element_get_default_playback_rate(WebKitDOMHTMLMediaElement*) -void webkit_dom_html_media_element_set_default_playback_rate(WebKitDOMHTMLMediaElement*, gdouble) -gdouble webkit_dom_html_media_element_get_playback_rate(WebKitDOMHTMLMediaElement*) -void webkit_dom_html_media_element_set_playback_rate(WebKitDOMHTMLMediaElement*, gdouble) -WebKitDOMTimeRanges* webkit_dom_html_media_element_get_played(WebKitDOMHTMLMediaElement*) -WebKitDOMTimeRanges* webkit_dom_html_media_element_get_seekable(WebKitDOMHTMLMediaElement*) -gboolean webkit_dom_html_media_element_get_ended(WebKitDOMHTMLMediaElement*) -gboolean webkit_dom_html_media_element_get_autoplay(WebKitDOMHTMLMediaElement*) -void webkit_dom_html_media_element_set_autoplay(WebKitDOMHTMLMediaElement*, gboolean) -gboolean webkit_dom_html_media_element_get_loop(WebKitDOMHTMLMediaElement*) -void webkit_dom_html_media_element_set_loop(WebKitDOMHTMLMediaElement*, gboolean) -gboolean webkit_dom_html_media_element_get_controls(WebKitDOMHTMLMediaElement*) -void webkit_dom_html_media_element_set_controls(WebKitDOMHTMLMediaElement*, gboolean) -gdouble webkit_dom_html_media_element_get_volume(WebKitDOMHTMLMediaElement*) -void webkit_dom_html_media_element_set_volume(WebKitDOMHTMLMediaElement*, gdouble, GError**) -gboolean webkit_dom_html_media_element_get_muted(WebKitDOMHTMLMediaElement*) -void webkit_dom_html_media_element_set_muted(WebKitDOMHTMLMediaElement*, gboolean) -gboolean webkit_dom_html_media_element_get_default_muted(WebKitDOMHTMLMediaElement*) -void webkit_dom_html_media_element_set_default_muted(WebKitDOMHTMLMediaElement*, gboolean) -gboolean webkit_dom_html_media_element_get_webkit_preserves_pitch(WebKitDOMHTMLMediaElement*) -void webkit_dom_html_media_element_set_webkit_preserves_pitch(WebKitDOMHTMLMediaElement*, gboolean) -gboolean webkit_dom_html_media_element_get_webkit_has_closed_captions(WebKitDOMHTMLMediaElement*) -gboolean webkit_dom_html_media_element_get_webkit_closed_captions_visible(WebKitDOMHTMLMediaElement*) -void webkit_dom_html_media_element_set_webkit_closed_captions_visible(WebKitDOMHTMLMediaElement*, gboolean) -gulong webkit_dom_html_media_element_get_webkit_audio_decoded_byte_count(WebKitDOMHTMLMediaElement*) -gulong webkit_dom_html_media_element_get_webkit_video_decoded_byte_count(WebKitDOMHTMLMediaElement*) -WebKitDOMAudioTrackList* webkit_dom_html_media_element_get_audio_tracks(WebKitDOMHTMLMediaElement*) -WebKitDOMTextTrackList* webkit_dom_html_media_element_get_text_tracks(WebKitDOMHTMLMediaElement*) -WebKitDOMVideoTrackList* webkit_dom_html_media_element_get_video_tracks(WebKitDOMHTMLMediaElement*) -gchar* webkit_dom_html_media_element_get_media_group(WebKitDOMHTMLMediaElement*) -void webkit_dom_html_media_element_set_media_group(WebKitDOMHTMLMediaElement*, const gchar*) -WebKitDOMMediaController* webkit_dom_html_media_element_get_controller(WebKitDOMHTMLMediaElement*) -gboolean webkit_dom_html_media_element_get_webkit_current_playback_target_is_wireless(WebKitDOMHTMLMediaElement*) -gboolean webkit_dom_html_menu_element_get_compact(WebKitDOMHTMLMenuElement*) -void webkit_dom_html_menu_element_set_compact(WebKitDOMHTMLMenuElement*, gboolean) -gchar* webkit_dom_html_meta_element_get_content(WebKitDOMHTMLMetaElement*) -void webkit_dom_html_meta_element_set_content(WebKitDOMHTMLMetaElement*, const gchar*) -gchar* webkit_dom_html_meta_element_get_http_equiv(WebKitDOMHTMLMetaElement*) -void webkit_dom_html_meta_element_set_http_equiv(WebKitDOMHTMLMetaElement*, const gchar*) -gchar* webkit_dom_html_meta_element_get_name(WebKitDOMHTMLMetaElement*) -void webkit_dom_html_meta_element_set_name(WebKitDOMHTMLMetaElement*, const gchar*) -gchar* webkit_dom_html_meta_element_get_scheme(WebKitDOMHTMLMetaElement*) -void webkit_dom_html_meta_element_set_scheme(WebKitDOMHTMLMetaElement*, const gchar*) -gchar* webkit_dom_html_mod_element_get_cite(WebKitDOMHTMLModElement*) -void webkit_dom_html_mod_element_set_cite(WebKitDOMHTMLModElement*, const gchar*) -gchar* webkit_dom_html_mod_element_get_date_time(WebKitDOMHTMLModElement*) -void webkit_dom_html_mod_element_set_date_time(WebKitDOMHTMLModElement*, const gchar*) -gboolean webkit_dom_html_object_element_check_validity(WebKitDOMHTMLObjectElement*) -void webkit_dom_html_object_element_set_custom_validity(WebKitDOMHTMLObjectElement*, const gchar*) -WebKitDOMHTMLFormElement* webkit_dom_html_object_element_get_form(WebKitDOMHTMLObjectElement*) -gchar* webkit_dom_html_object_element_get_code(WebKitDOMHTMLObjectElement*) -void webkit_dom_html_object_element_set_code(WebKitDOMHTMLObjectElement*, const gchar*) -gchar* webkit_dom_html_object_element_get_align(WebKitDOMHTMLObjectElement*) -void webkit_dom_html_object_element_set_align(WebKitDOMHTMLObjectElement*, const gchar*) -gchar* webkit_dom_html_object_element_get_archive(WebKitDOMHTMLObjectElement*) -void webkit_dom_html_object_element_set_archive(WebKitDOMHTMLObjectElement*, const gchar*) -gchar* webkit_dom_html_object_element_get_border(WebKitDOMHTMLObjectElement*) -void webkit_dom_html_object_element_set_border(WebKitDOMHTMLObjectElement*, const gchar*) -gchar* webkit_dom_html_object_element_get_code_base(WebKitDOMHTMLObjectElement*) -void webkit_dom_html_object_element_set_code_base(WebKitDOMHTMLObjectElement*, const gchar*) -gchar* webkit_dom_html_object_element_get_code_type(WebKitDOMHTMLObjectElement*) -void webkit_dom_html_object_element_set_code_type(WebKitDOMHTMLObjectElement*, const gchar*) -gchar* webkit_dom_html_object_element_get_data(WebKitDOMHTMLObjectElement*) -void webkit_dom_html_object_element_set_data(WebKitDOMHTMLObjectElement*, const gchar*) -gboolean webkit_dom_html_object_element_get_declare(WebKitDOMHTMLObjectElement*) -void webkit_dom_html_object_element_set_declare(WebKitDOMHTMLObjectElement*, gboolean) -gchar* webkit_dom_html_object_element_get_height(WebKitDOMHTMLObjectElement*) -void webkit_dom_html_object_element_set_height(WebKitDOMHTMLObjectElement*, const gchar*) -glong webkit_dom_html_object_element_get_hspace(WebKitDOMHTMLObjectElement*) -void webkit_dom_html_object_element_set_hspace(WebKitDOMHTMLObjectElement*, glong) -gchar* webkit_dom_html_object_element_get_name(WebKitDOMHTMLObjectElement*) -void webkit_dom_html_object_element_set_name(WebKitDOMHTMLObjectElement*, const gchar*) -gchar* webkit_dom_html_object_element_get_standby(WebKitDOMHTMLObjectElement*) -void webkit_dom_html_object_element_set_standby(WebKitDOMHTMLObjectElement*, const gchar*) -gchar* webkit_dom_html_object_element_get_use_map(WebKitDOMHTMLObjectElement*) -void webkit_dom_html_object_element_set_use_map(WebKitDOMHTMLObjectElement*, const gchar*) -glong webkit_dom_html_object_element_get_vspace(WebKitDOMHTMLObjectElement*) -void webkit_dom_html_object_element_set_vspace(WebKitDOMHTMLObjectElement*, glong) -gchar* webkit_dom_html_object_element_get_width(WebKitDOMHTMLObjectElement*) -void webkit_dom_html_object_element_set_width(WebKitDOMHTMLObjectElement*, const gchar*) -gboolean webkit_dom_html_object_element_get_will_validate(WebKitDOMHTMLObjectElement*) -WebKitDOMValidityState* webkit_dom_html_object_element_get_validity(WebKitDOMHTMLObjectElement*) -gchar* webkit_dom_html_object_element_get_validation_message(WebKitDOMHTMLObjectElement*) -WebKitDOMDocument* webkit_dom_html_object_element_get_content_document(WebKitDOMHTMLObjectElement*) -gboolean webkit_dom_htmlo_list_element_get_compact(WebKitDOMHTMLOListElement*) -void webkit_dom_htmlo_list_element_set_compact(WebKitDOMHTMLOListElement*, gboolean) -glong webkit_dom_htmlo_list_element_get_start(WebKitDOMHTMLOListElement*) -void webkit_dom_htmlo_list_element_set_start(WebKitDOMHTMLOListElement*, glong) -gboolean webkit_dom_htmlo_list_element_get_reversed(WebKitDOMHTMLOListElement*) -void webkit_dom_htmlo_list_element_set_reversed(WebKitDOMHTMLOListElement*, gboolean) -gboolean webkit_dom_html_opt_group_element_get_disabled(WebKitDOMHTMLOptGroupElement*) -void webkit_dom_html_opt_group_element_set_disabled(WebKitDOMHTMLOptGroupElement*, gboolean) -gchar* webkit_dom_html_opt_group_element_get_label(WebKitDOMHTMLOptGroupElement*) -void webkit_dom_html_opt_group_element_set_label(WebKitDOMHTMLOptGroupElement*, const gchar*) -gboolean webkit_dom_html_option_element_get_disabled(WebKitDOMHTMLOptionElement*) -void webkit_dom_html_option_element_set_disabled(WebKitDOMHTMLOptionElement*, gboolean) -WebKitDOMHTMLFormElement* webkit_dom_html_option_element_get_form(WebKitDOMHTMLOptionElement*) -gchar* webkit_dom_html_option_element_get_label(WebKitDOMHTMLOptionElement*) -void webkit_dom_html_option_element_set_label(WebKitDOMHTMLOptionElement*, const gchar*) -gboolean webkit_dom_html_option_element_get_default_selected(WebKitDOMHTMLOptionElement*) -void webkit_dom_html_option_element_set_default_selected(WebKitDOMHTMLOptionElement*, gboolean) -gboolean webkit_dom_html_option_element_get_selected(WebKitDOMHTMLOptionElement*) -void webkit_dom_html_option_element_set_selected(WebKitDOMHTMLOptionElement*, gboolean) -gchar* webkit_dom_html_option_element_get_value(WebKitDOMHTMLOptionElement*) -void webkit_dom_html_option_element_set_value(WebKitDOMHTMLOptionElement*, const gchar*) -gchar* webkit_dom_html_option_element_get_text(WebKitDOMHTMLOptionElement*) -glong webkit_dom_html_option_element_get_index(WebKitDOMHTMLOptionElement*) -WebKitDOMNode* webkit_dom_html_options_collection_named_item(WebKitDOMHTMLOptionsCollection*, const gchar*) -glong webkit_dom_html_options_collection_get_selected_index(WebKitDOMHTMLOptionsCollection*) -void webkit_dom_html_options_collection_set_selected_index(WebKitDOMHTMLOptionsCollection*, glong) -gulong webkit_dom_html_options_collection_get_length(WebKitDOMHTMLOptionsCollection*) -gchar* webkit_dom_html_paragraph_element_get_align(WebKitDOMHTMLParagraphElement*) -void webkit_dom_html_paragraph_element_set_align(WebKitDOMHTMLParagraphElement*, const gchar*) -gchar* webkit_dom_html_param_element_get_name(WebKitDOMHTMLParamElement*) -void webkit_dom_html_param_element_set_name(WebKitDOMHTMLParamElement*, const gchar*) -gchar* webkit_dom_html_param_element_get_value(WebKitDOMHTMLParamElement*) -void webkit_dom_html_param_element_set_value(WebKitDOMHTMLParamElement*, const gchar*) -gchar* webkit_dom_html_param_element_get_value_type(WebKitDOMHTMLParamElement*) -void webkit_dom_html_param_element_set_value_type(WebKitDOMHTMLParamElement*, const gchar*) -glong webkit_dom_html_pre_element_get_width(WebKitDOMHTMLPreElement*) -void webkit_dom_html_pre_element_set_width(WebKitDOMHTMLPreElement*, glong) -gboolean webkit_dom_html_pre_element_get_wrap(WebKitDOMHTMLPreElement*) -void webkit_dom_html_pre_element_set_wrap(WebKitDOMHTMLPreElement*, gboolean) -gchar* webkit_dom_html_quote_element_get_cite(WebKitDOMHTMLQuoteElement*) -void webkit_dom_html_quote_element_set_cite(WebKitDOMHTMLQuoteElement*, const gchar*) -gchar* webkit_dom_html_script_element_get_text(WebKitDOMHTMLScriptElement*) -void webkit_dom_html_script_element_set_text(WebKitDOMHTMLScriptElement*, const gchar*) -gchar* webkit_dom_html_script_element_get_html_for(WebKitDOMHTMLScriptElement*) -void webkit_dom_html_script_element_set_html_for(WebKitDOMHTMLScriptElement*, const gchar*) -gchar* webkit_dom_html_script_element_get_event(WebKitDOMHTMLScriptElement*) -void webkit_dom_html_script_element_set_event(WebKitDOMHTMLScriptElement*, const gchar*) -gchar* webkit_dom_html_script_element_get_charset(WebKitDOMHTMLScriptElement*) -void webkit_dom_html_script_element_set_charset(WebKitDOMHTMLScriptElement*, const gchar*) -gboolean webkit_dom_html_script_element_get_async(WebKitDOMHTMLScriptElement*) -void webkit_dom_html_script_element_set_async(WebKitDOMHTMLScriptElement*, gboolean) -gboolean webkit_dom_html_script_element_get_defer(WebKitDOMHTMLScriptElement*) -void webkit_dom_html_script_element_set_defer(WebKitDOMHTMLScriptElement*, gboolean) -gchar* webkit_dom_html_script_element_get_src(WebKitDOMHTMLScriptElement*) -void webkit_dom_html_script_element_set_src(WebKitDOMHTMLScriptElement*, const gchar*) -gchar* webkit_dom_html_script_element_get_cross_origin(WebKitDOMHTMLScriptElement*) -void webkit_dom_html_script_element_set_cross_origin(WebKitDOMHTMLScriptElement*, const gchar*) -gchar* webkit_dom_html_script_element_get_nonce(WebKitDOMHTMLScriptElement*) -void webkit_dom_html_script_element_set_nonce(WebKitDOMHTMLScriptElement*, const gchar*) -WebKitDOMNode* webkit_dom_html_select_element_item(WebKitDOMHTMLSelectElement*, gulong) -WebKitDOMNode* webkit_dom_html_select_element_named_item(WebKitDOMHTMLSelectElement*, const gchar*) -void webkit_dom_html_select_element_add(WebKitDOMHTMLSelectElement*, WebKitDOMHTMLElement*, WebKitDOMHTMLElement*, GError**) -void webkit_dom_html_select_element_remove(WebKitDOMHTMLSelectElement*, glong) -gboolean webkit_dom_html_select_element_check_validity(WebKitDOMHTMLSelectElement*) -void webkit_dom_html_select_element_set_custom_validity(WebKitDOMHTMLSelectElement*, const gchar*) -gboolean webkit_dom_html_select_element_get_autofocus(WebKitDOMHTMLSelectElement*) -void webkit_dom_html_select_element_set_autofocus(WebKitDOMHTMLSelectElement*, gboolean) -gboolean webkit_dom_html_select_element_get_disabled(WebKitDOMHTMLSelectElement*) -void webkit_dom_html_select_element_set_disabled(WebKitDOMHTMLSelectElement*, gboolean) -WebKitDOMHTMLFormElement* webkit_dom_html_select_element_get_form(WebKitDOMHTMLSelectElement*) -gboolean webkit_dom_html_select_element_get_multiple(WebKitDOMHTMLSelectElement*) -void webkit_dom_html_select_element_set_multiple(WebKitDOMHTMLSelectElement*, gboolean) -gchar* webkit_dom_html_select_element_get_name(WebKitDOMHTMLSelectElement*) -void webkit_dom_html_select_element_set_name(WebKitDOMHTMLSelectElement*, const gchar*) -gboolean webkit_dom_html_select_element_get_required(WebKitDOMHTMLSelectElement*) -void webkit_dom_html_select_element_set_required(WebKitDOMHTMLSelectElement*, gboolean) -glong webkit_dom_html_select_element_get_size(WebKitDOMHTMLSelectElement*) -void webkit_dom_html_select_element_set_size(WebKitDOMHTMLSelectElement*, glong) -WebKitDOMHTMLOptionsCollection* webkit_dom_html_select_element_get_options(WebKitDOMHTMLSelectElement*) -gulong webkit_dom_html_select_element_get_length(WebKitDOMHTMLSelectElement*) -void webkit_dom_html_select_element_set_length(WebKitDOMHTMLSelectElement*, gulong, GError**) -WebKitDOMHTMLCollection* webkit_dom_html_select_element_get_selected_options(WebKitDOMHTMLSelectElement*) -glong webkit_dom_html_select_element_get_selected_index(WebKitDOMHTMLSelectElement*) -void webkit_dom_html_select_element_set_selected_index(WebKitDOMHTMLSelectElement*, glong) -gchar* webkit_dom_html_select_element_get_value(WebKitDOMHTMLSelectElement*) -void webkit_dom_html_select_element_set_value(WebKitDOMHTMLSelectElement*, const gchar*) -gboolean webkit_dom_html_select_element_get_will_validate(WebKitDOMHTMLSelectElement*) -WebKitDOMValidityState* webkit_dom_html_select_element_get_validity(WebKitDOMHTMLSelectElement*) -gchar* webkit_dom_html_select_element_get_validation_message(WebKitDOMHTMLSelectElement*) -WebKitDOMNodeList* webkit_dom_html_select_element_get_labels(WebKitDOMHTMLSelectElement*) -gboolean webkit_dom_html_style_element_get_disabled(WebKitDOMHTMLStyleElement*) -void webkit_dom_html_style_element_set_disabled(WebKitDOMHTMLStyleElement*, gboolean) -gchar* webkit_dom_html_style_element_get_media(WebKitDOMHTMLStyleElement*) -void webkit_dom_html_style_element_set_media(WebKitDOMHTMLStyleElement*, const gchar*) -WebKitDOMStyleSheet* webkit_dom_html_style_element_get_sheet(WebKitDOMHTMLStyleElement*) -WebKitDOMHTMLElement* webkit_dom_html_table_element_create_t_head(WebKitDOMHTMLTableElement*) -void webkit_dom_html_table_element_delete_t_head(WebKitDOMHTMLTableElement*) -WebKitDOMHTMLElement* webkit_dom_html_table_element_create_t_foot(WebKitDOMHTMLTableElement*) -void webkit_dom_html_table_element_delete_t_foot(WebKitDOMHTMLTableElement*) -WebKitDOMHTMLElement* webkit_dom_html_table_element_create_t_body(WebKitDOMHTMLTableElement*) -WebKitDOMHTMLElement* webkit_dom_html_table_element_create_caption(WebKitDOMHTMLTableElement*) -void webkit_dom_html_table_element_delete_caption(WebKitDOMHTMLTableElement*) -WebKitDOMHTMLElement* webkit_dom_html_table_element_insert_row(WebKitDOMHTMLTableElement*, glong, GError**) -void webkit_dom_html_table_element_delete_row(WebKitDOMHTMLTableElement*, glong, GError**) -WebKitDOMHTMLTableCaptionElement* webkit_dom_html_table_element_get_caption(WebKitDOMHTMLTableElement*) -void webkit_dom_html_table_element_set_caption(WebKitDOMHTMLTableElement*, WebKitDOMHTMLTableCaptionElement*, GError**) -WebKitDOMHTMLTableSectionElement* webkit_dom_html_table_element_get_t_head(WebKitDOMHTMLTableElement*) -void webkit_dom_html_table_element_set_t_head(WebKitDOMHTMLTableElement*, WebKitDOMHTMLTableSectionElement*, GError**) -WebKitDOMHTMLTableSectionElement* webkit_dom_html_table_element_get_t_foot(WebKitDOMHTMLTableElement*) -void webkit_dom_html_table_element_set_t_foot(WebKitDOMHTMLTableElement*, WebKitDOMHTMLTableSectionElement*, GError**) -WebKitDOMHTMLCollection* webkit_dom_html_table_element_get_rows(WebKitDOMHTMLTableElement*) -WebKitDOMHTMLCollection* webkit_dom_html_table_element_get_t_bodies(WebKitDOMHTMLTableElement*) -gchar* webkit_dom_html_table_element_get_align(WebKitDOMHTMLTableElement*) -void webkit_dom_html_table_element_set_align(WebKitDOMHTMLTableElement*, const gchar*) -gchar* webkit_dom_html_table_element_get_bg_color(WebKitDOMHTMLTableElement*) -void webkit_dom_html_table_element_set_bg_color(WebKitDOMHTMLTableElement*, const gchar*) -gchar* webkit_dom_html_table_element_get_border(WebKitDOMHTMLTableElement*) -void webkit_dom_html_table_element_set_border(WebKitDOMHTMLTableElement*, const gchar*) -gchar* webkit_dom_html_table_element_get_cell_padding(WebKitDOMHTMLTableElement*) -void webkit_dom_html_table_element_set_cell_padding(WebKitDOMHTMLTableElement*, const gchar*) -gchar* webkit_dom_html_table_element_get_cell_spacing(WebKitDOMHTMLTableElement*) -void webkit_dom_html_table_element_set_cell_spacing(WebKitDOMHTMLTableElement*, const gchar*) -gchar* webkit_dom_html_table_element_get_frame(WebKitDOMHTMLTableElement*) -void webkit_dom_html_table_element_set_frame(WebKitDOMHTMLTableElement*, const gchar*) -gchar* webkit_dom_html_table_element_get_rules(WebKitDOMHTMLTableElement*) -void webkit_dom_html_table_element_set_rules(WebKitDOMHTMLTableElement*, const gchar*) -gchar* webkit_dom_html_table_element_get_summary(WebKitDOMHTMLTableElement*) -void webkit_dom_html_table_element_set_summary(WebKitDOMHTMLTableElement*, const gchar*) -gchar* webkit_dom_html_table_element_get_width(WebKitDOMHTMLTableElement*) -void webkit_dom_html_table_element_set_width(WebKitDOMHTMLTableElement*, const gchar*) -gchar* webkit_dom_html_table_caption_element_get_align(WebKitDOMHTMLTableCaptionElement*) -void webkit_dom_html_table_caption_element_set_align(WebKitDOMHTMLTableCaptionElement*, const gchar*) -gchar* webkit_dom_html_table_col_element_get_align(WebKitDOMHTMLTableColElement*) -void webkit_dom_html_table_col_element_set_align(WebKitDOMHTMLTableColElement*, const gchar*) -gchar* webkit_dom_html_table_col_element_get_ch(WebKitDOMHTMLTableColElement*) -void webkit_dom_html_table_col_element_set_ch(WebKitDOMHTMLTableColElement*, const gchar*) -gchar* webkit_dom_html_table_col_element_get_ch_off(WebKitDOMHTMLTableColElement*) -void webkit_dom_html_table_col_element_set_ch_off(WebKitDOMHTMLTableColElement*, const gchar*) -glong webkit_dom_html_table_col_element_get_span(WebKitDOMHTMLTableColElement*) -void webkit_dom_html_table_col_element_set_span(WebKitDOMHTMLTableColElement*, glong) -gchar* webkit_dom_html_table_col_element_get_v_align(WebKitDOMHTMLTableColElement*) -void webkit_dom_html_table_col_element_set_v_align(WebKitDOMHTMLTableColElement*, const gchar*) -gchar* webkit_dom_html_table_col_element_get_width(WebKitDOMHTMLTableColElement*) -void webkit_dom_html_table_col_element_set_width(WebKitDOMHTMLTableColElement*, const gchar*) -WebKitDOMHTMLElement* webkit_dom_html_table_section_element_insert_row(WebKitDOMHTMLTableSectionElement*, glong, GError**) -void webkit_dom_html_table_section_element_delete_row(WebKitDOMHTMLTableSectionElement*, glong, GError**) -gchar* webkit_dom_html_table_section_element_get_align(WebKitDOMHTMLTableSectionElement*) -void webkit_dom_html_table_section_element_set_align(WebKitDOMHTMLTableSectionElement*, const gchar*) -gchar* webkit_dom_html_table_section_element_get_ch(WebKitDOMHTMLTableSectionElement*) -void webkit_dom_html_table_section_element_set_ch(WebKitDOMHTMLTableSectionElement*, const gchar*) -gchar* webkit_dom_html_table_section_element_get_ch_off(WebKitDOMHTMLTableSectionElement*) -void webkit_dom_html_table_section_element_set_ch_off(WebKitDOMHTMLTableSectionElement*, const gchar*) -gchar* webkit_dom_html_table_section_element_get_v_align(WebKitDOMHTMLTableSectionElement*) -void webkit_dom_html_table_section_element_set_v_align(WebKitDOMHTMLTableSectionElement*, const gchar*) -WebKitDOMHTMLCollection* webkit_dom_html_table_section_element_get_rows(WebKitDOMHTMLTableSectionElement*) -glong webkit_dom_html_table_cell_element_get_cell_index(WebKitDOMHTMLTableCellElement*) -gchar* webkit_dom_html_table_cell_element_get_abbr(WebKitDOMHTMLTableCellElement*) -void webkit_dom_html_table_cell_element_set_abbr(WebKitDOMHTMLTableCellElement*, const gchar*) -gchar* webkit_dom_html_table_cell_element_get_align(WebKitDOMHTMLTableCellElement*) -void webkit_dom_html_table_cell_element_set_align(WebKitDOMHTMLTableCellElement*, const gchar*) -gchar* webkit_dom_html_table_cell_element_get_axis(WebKitDOMHTMLTableCellElement*) -void webkit_dom_html_table_cell_element_set_axis(WebKitDOMHTMLTableCellElement*, const gchar*) -gchar* webkit_dom_html_table_cell_element_get_bg_color(WebKitDOMHTMLTableCellElement*) -void webkit_dom_html_table_cell_element_set_bg_color(WebKitDOMHTMLTableCellElement*, const gchar*) -gchar* webkit_dom_html_table_cell_element_get_ch(WebKitDOMHTMLTableCellElement*) -void webkit_dom_html_table_cell_element_set_ch(WebKitDOMHTMLTableCellElement*, const gchar*) -gchar* webkit_dom_html_table_cell_element_get_ch_off(WebKitDOMHTMLTableCellElement*) -void webkit_dom_html_table_cell_element_set_ch_off(WebKitDOMHTMLTableCellElement*, const gchar*) -glong webkit_dom_html_table_cell_element_get_col_span(WebKitDOMHTMLTableCellElement*) -void webkit_dom_html_table_cell_element_set_col_span(WebKitDOMHTMLTableCellElement*, glong) -gchar* webkit_dom_html_table_cell_element_get_headers(WebKitDOMHTMLTableCellElement*) -void webkit_dom_html_table_cell_element_set_headers(WebKitDOMHTMLTableCellElement*, const gchar*) -gchar* webkit_dom_html_table_cell_element_get_height(WebKitDOMHTMLTableCellElement*) -void webkit_dom_html_table_cell_element_set_height(WebKitDOMHTMLTableCellElement*, const gchar*) -gboolean webkit_dom_html_table_cell_element_get_no_wrap(WebKitDOMHTMLTableCellElement*) -void webkit_dom_html_table_cell_element_set_no_wrap(WebKitDOMHTMLTableCellElement*, gboolean) -glong webkit_dom_html_table_cell_element_get_row_span(WebKitDOMHTMLTableCellElement*) -void webkit_dom_html_table_cell_element_set_row_span(WebKitDOMHTMLTableCellElement*, glong) -gchar* webkit_dom_html_table_cell_element_get_scope(WebKitDOMHTMLTableCellElement*) -void webkit_dom_html_table_cell_element_set_scope(WebKitDOMHTMLTableCellElement*, const gchar*) -gchar* webkit_dom_html_table_cell_element_get_v_align(WebKitDOMHTMLTableCellElement*) -void webkit_dom_html_table_cell_element_set_v_align(WebKitDOMHTMLTableCellElement*, const gchar*) -gchar* webkit_dom_html_table_cell_element_get_width(WebKitDOMHTMLTableCellElement*) -void webkit_dom_html_table_cell_element_set_width(WebKitDOMHTMLTableCellElement*, const gchar*) -gboolean webkit_dom_html_text_area_element_check_validity(WebKitDOMHTMLTextAreaElement*) -void webkit_dom_html_text_area_element_set_custom_validity(WebKitDOMHTMLTextAreaElement*, const gchar*) -void webkit_dom_html_text_area_element_select(WebKitDOMHTMLTextAreaElement*) -void webkit_dom_html_text_area_element_set_range_text(WebKitDOMHTMLTextAreaElement*, const gchar*, gulong, gulong, const gchar*, GError**) -void webkit_dom_html_text_area_element_set_selection_range(WebKitDOMHTMLTextAreaElement*, glong, glong, const gchar*) -gboolean webkit_dom_html_text_area_element_get_autofocus(WebKitDOMHTMLTextAreaElement*) -void webkit_dom_html_text_area_element_set_autofocus(WebKitDOMHTMLTextAreaElement*, gboolean) -glong webkit_dom_html_text_area_element_get_cols(WebKitDOMHTMLTextAreaElement*) -void webkit_dom_html_text_area_element_set_cols(WebKitDOMHTMLTextAreaElement*, glong) -gchar* webkit_dom_html_text_area_element_get_dir_name(WebKitDOMHTMLTextAreaElement*) -void webkit_dom_html_text_area_element_set_dir_name(WebKitDOMHTMLTextAreaElement*, const gchar*) -gboolean webkit_dom_html_text_area_element_get_disabled(WebKitDOMHTMLTextAreaElement*) -void webkit_dom_html_text_area_element_set_disabled(WebKitDOMHTMLTextAreaElement*, gboolean) -WebKitDOMHTMLFormElement* webkit_dom_html_text_area_element_get_form(WebKitDOMHTMLTextAreaElement*) -glong webkit_dom_html_text_area_element_get_max_length(WebKitDOMHTMLTextAreaElement*) -void webkit_dom_html_text_area_element_set_max_length(WebKitDOMHTMLTextAreaElement*, glong, GError**) -gchar* webkit_dom_html_text_area_element_get_name(WebKitDOMHTMLTextAreaElement*) -void webkit_dom_html_text_area_element_set_name(WebKitDOMHTMLTextAreaElement*, const gchar*) -gchar* webkit_dom_html_text_area_element_get_placeholder(WebKitDOMHTMLTextAreaElement*) -void webkit_dom_html_text_area_element_set_placeholder(WebKitDOMHTMLTextAreaElement*, const gchar*) -gboolean webkit_dom_html_text_area_element_get_read_only(WebKitDOMHTMLTextAreaElement*) -void webkit_dom_html_text_area_element_set_read_only(WebKitDOMHTMLTextAreaElement*, gboolean) -gboolean webkit_dom_html_text_area_element_get_required(WebKitDOMHTMLTextAreaElement*) -void webkit_dom_html_text_area_element_set_required(WebKitDOMHTMLTextAreaElement*, gboolean) -glong webkit_dom_html_text_area_element_get_rows(WebKitDOMHTMLTextAreaElement*) -void webkit_dom_html_text_area_element_set_rows(WebKitDOMHTMLTextAreaElement*, glong) -gchar* webkit_dom_html_text_area_element_get_wrap(WebKitDOMHTMLTextAreaElement*) -void webkit_dom_html_text_area_element_set_wrap(WebKitDOMHTMLTextAreaElement*, const gchar*) -gchar* webkit_dom_html_text_area_element_get_default_value(WebKitDOMHTMLTextAreaElement*) -void webkit_dom_html_text_area_element_set_default_value(WebKitDOMHTMLTextAreaElement*, const gchar*) -gchar* webkit_dom_html_text_area_element_get_value(WebKitDOMHTMLTextAreaElement*) -void webkit_dom_html_text_area_element_set_value(WebKitDOMHTMLTextAreaElement*, const gchar*) -gulong webkit_dom_html_text_area_element_get_text_length(WebKitDOMHTMLTextAreaElement*) -gboolean webkit_dom_html_text_area_element_get_will_validate(WebKitDOMHTMLTextAreaElement*) -WebKitDOMValidityState* webkit_dom_html_text_area_element_get_validity(WebKitDOMHTMLTextAreaElement*) -gchar* webkit_dom_html_text_area_element_get_validation_message(WebKitDOMHTMLTextAreaElement*) -WebKitDOMNodeList* webkit_dom_html_text_area_element_get_labels(WebKitDOMHTMLTextAreaElement*) -glong webkit_dom_html_text_area_element_get_selection_start(WebKitDOMHTMLTextAreaElement*) -void webkit_dom_html_text_area_element_set_selection_start(WebKitDOMHTMLTextAreaElement*, glong) -glong webkit_dom_html_text_area_element_get_selection_end(WebKitDOMHTMLTextAreaElement*) -void webkit_dom_html_text_area_element_set_selection_end(WebKitDOMHTMLTextAreaElement*, glong) -gchar* webkit_dom_html_text_area_element_get_selection_direction(WebKitDOMHTMLTextAreaElement*) -void webkit_dom_html_text_area_element_set_selection_direction(WebKitDOMHTMLTextAreaElement*, const gchar*) -gboolean webkit_dom_html_text_area_element_get_autocorrect(WebKitDOMHTMLTextAreaElement*) -void webkit_dom_html_text_area_element_set_autocorrect(WebKitDOMHTMLTextAreaElement*, gboolean) -gchar* webkit_dom_html_text_area_element_get_autocapitalize(WebKitDOMHTMLTextAreaElement*) -void webkit_dom_html_text_area_element_set_autocapitalize(WebKitDOMHTMLTextAreaElement*, const gchar*) -gchar* webkit_dom_html_title_element_get_text(WebKitDOMHTMLTitleElement*) -void webkit_dom_html_title_element_set_text(WebKitDOMHTMLTitleElement*, const gchar*) -WebKitDOMHTMLElement* webkit_dom_html_table_row_element_insert_cell(WebKitDOMHTMLTableRowElement*, glong, GError**) -void webkit_dom_html_table_row_element_delete_cell(WebKitDOMHTMLTableRowElement*, glong, GError**) -glong webkit_dom_html_table_row_element_get_row_index(WebKitDOMHTMLTableRowElement*) -glong webkit_dom_html_table_row_element_get_section_row_index(WebKitDOMHTMLTableRowElement*) -WebKitDOMHTMLCollection* webkit_dom_html_table_row_element_get_cells(WebKitDOMHTMLTableRowElement*) -gchar* webkit_dom_html_table_row_element_get_align(WebKitDOMHTMLTableRowElement*) -void webkit_dom_html_table_row_element_set_align(WebKitDOMHTMLTableRowElement*, const gchar*) -gchar* webkit_dom_html_table_row_element_get_bg_color(WebKitDOMHTMLTableRowElement*) -void webkit_dom_html_table_row_element_set_bg_color(WebKitDOMHTMLTableRowElement*, const gchar*) -gchar* webkit_dom_html_table_row_element_get_ch(WebKitDOMHTMLTableRowElement*) -void webkit_dom_html_table_row_element_set_ch(WebKitDOMHTMLTableRowElement*, const gchar*) -gchar* webkit_dom_html_table_row_element_get_ch_off(WebKitDOMHTMLTableRowElement*) -void webkit_dom_html_table_row_element_set_ch_off(WebKitDOMHTMLTableRowElement*, const gchar*) -gchar* webkit_dom_html_table_row_element_get_v_align(WebKitDOMHTMLTableRowElement*) -void webkit_dom_html_table_row_element_set_v_align(WebKitDOMHTMLTableRowElement*, const gchar*) -gboolean webkit_dom_htmlu_list_element_get_compact(WebKitDOMHTMLUListElement*) -void webkit_dom_htmlu_list_element_set_compact(WebKitDOMHTMLUListElement*, gboolean) -gushort webkit_dom_media_error_get_code(WebKitDOMMediaError*) -gdouble webkit_dom_time_ranges_start(WebKitDOMTimeRanges*, gulong, GError**) -gdouble webkit_dom_time_ranges_end(WebKitDOMTimeRanges*, gulong, GError**) -gulong webkit_dom_time_ranges_get_length(WebKitDOMTimeRanges*) -gboolean webkit_dom_validity_state_get_value_missing(WebKitDOMValidityState*) -gboolean webkit_dom_validity_state_get_type_mismatch(WebKitDOMValidityState*) -gboolean webkit_dom_validity_state_get_pattern_mismatch(WebKitDOMValidityState*) -gboolean webkit_dom_validity_state_get_too_long(WebKitDOMValidityState*) -gboolean webkit_dom_validity_state_get_range_underflow(WebKitDOMValidityState*) -gboolean webkit_dom_validity_state_get_range_overflow(WebKitDOMValidityState*) -gboolean webkit_dom_validity_state_get_step_mismatch(WebKitDOMValidityState*) -gboolean webkit_dom_validity_state_get_bad_input(WebKitDOMValidityState*) -gboolean webkit_dom_validity_state_get_custom_error(WebKitDOMValidityState*) -gboolean webkit_dom_validity_state_get_valid(WebKitDOMValidityState*) -void webkit_dom_dom_application_cache_update(WebKitDOMDOMApplicationCache*, GError**) -void webkit_dom_dom_application_cache_swap_cache(WebKitDOMDOMApplicationCache*, GError**) -void webkit_dom_dom_application_cache_abort(WebKitDOMDOMApplicationCache*) -gboolean webkit_dom_dom_application_cache_dispatch_event(WebKitDOMDOMApplicationCache*, WebKitDOMEvent*, GError**) -gushort webkit_dom_dom_application_cache_get_status(WebKitDOMDOMApplicationCache*) -gboolean webkit_dom_bar_prop_get_visible(WebKitDOMBarProp*) -void webkit_dom_console_time(WebKitDOMConsole*, const gchar*) -void webkit_dom_console_group_end(WebKitDOMConsole*) -gboolean webkit_dom_html_text_area_element_is_edited(WebKitDOMHTMLTextAreaElement*) -gboolean webkit_dom_html_input_element_is_edited(WebKitDOMHTMLInputElement*) -void webkit_dom_html_media_element_set_current_time(WebKitDOMHTMLMediaElement*, gdouble, GError**) -WebKitDOMBlob* webkit_dom_blob_webkit_slice(WebKitDOMBlob*, gint64, gint64, const gchar*) -gchar* webkit_dom_html_element_get_id(WebKitDOMHTMLElement*) -void webkit_dom_html_element_set_id(WebKitDOMHTMLElement*, const gchar*) -gchar* webkit_dom_html_element_get_class_name(WebKitDOMHTMLElement*) -void webkit_dom_html_element_set_class_name(WebKitDOMHTMLElement*, const gchar*) -WebKitDOMDOMTokenList* webkit_dom_html_element_get_class_list(WebKitDOMHTMLElement*) -void webkit_dom_html_form_element_dispatch_form_change(WebKitDOMHTMLFormElement*) -void webkit_dom_html_form_element_dispatch_form_input(WebKitDOMHTMLFormElement*) -gboolean webkit_dom_webkit_named_flow_get_overflow(WebKitDOMWebKitNamedFlow*) -gchar* webkit_dom_element_get_webkit_region_overflow(WebKitDOMElement*) -WebKitDOMNodeList* webkit_dom_webkit_named_flow_get_content_nodes(WebKitDOMWebKitNamedFlow*) -WebKitDOMNodeList* webkit_dom_webkit_named_flow_get_regions_by_content_node(WebKitDOMWebKitNamedFlow*, WebKitDOMNode*) -GType webkit_dom_bar_info_get_type(void) -gboolean webkit_dom_bar_info_get_visible(void*) -void* webkit_dom_console_get_memory(WebKitDOMConsole*) -WebKitDOMCSSValue* webkit_dom_css_style_declaration_get_property_css_value(WebKitDOMCSSStyleDeclaration*, const gchar*) -gboolean webkit_dom_document_get_webkit_hidden(WebKitDOMDocument*) -gchar* webkit_dom_document_get_webkit_visibility_state(WebKitDOMDocument*) -void webkit_dom_html_document_open(WebKitDOMHTMLDocument*) -void webkit_dom_html_element_set_item_id(WebKitDOMHTMLElement*, const gchar*) -gchar* webkit_dom_html_element_get_item_id(WebKitDOMHTMLElement*) -WebKitDOMDOMSettableTokenList* webkit_dom_html_element_get_item_ref(WebKitDOMHTMLElement*) -WebKitDOMDOMSettableTokenList* webkit_dom_html_element_get_item_prop(WebKitDOMHTMLElement*) -void webkit_dom_html_element_set_item_scope(WebKitDOMHTMLElement*, gboolean) -gboolean webkit_dom_html_element_get_item_scope(WebKitDOMHTMLElement*) -void* webkit_dom_html_element_get_item_type(WebKitDOMHTMLElement*) -void webkit_dom_html_style_element_set_scoped(WebKitDOMHTMLStyleElement*, gboolean) -gboolean webkit_dom_html_style_element_get_scoped(WebKitDOMHTMLStyleElement*) -GType webkit_dom_html_properties_collection_get_type(void) -WebKitDOMNode* webkit_dom_html_properties_collection_item(void*, gulong) -void* webkit_dom_html_properties_collection_named_item(void*, const gchar*) -gulong webkit_dom_html_properties_collection_get_length(void*) -WebKitDOMDOMStringList* webkit_dom_html_properties_collection_get_names(void*) -WebKitDOMNamedNodeMap* webkit_dom_node_get_attributes(WebKitDOMNode*) -gboolean webkit_dom_node_has_attributes(WebKitDOMNode*) -GType webkit_dom_memory_info_get_type(void) -gulong webkit_dom_memory_info_get_total_js_heap_size(void*) -gulong webkit_dom_memory_info_get_used_js_heap_size(void*) -gulong webkit_dom_memory_info_get_js_heap_size_limit(void*) -GType webkit_dom_micro_data_item_value_get_type(void) -void* webkit_dom_performance_get_memory(WebKitDOMPerformance*) -GType webkit_dom_property_node_list_get_type(void) -WebKitDOMNode* webkit_dom_property_node_list_item(void*, gulong) -gulong webkit_dom_property_node_list_get_length(void*) -gdouble webkit_dom_html_media_element_get_start_time(WebKitDOMHTMLMediaElement*) -gdouble webkit_dom_html_media_element_get_initial_time(WebKitDOMHTMLMediaElement*) -gchar* webkit_dom_processing_instruction_get_data(WebKitDOMProcessingInstruction*) -void webkit_dom_processing_instruction_set_data(WebKitDOMProcessingInstruction*, const gchar*, GError**) -gboolean webkit_dom_dom_window_css_supports(WebKitDOMDOMWindowCSS*, const gchar*, const gchar*) -WebKitDOMDOMSelection* webkit_dom_dom_window_get_selection(WebKitDOMDOMWindow*) -void webkit_dom_dom_window_focus(WebKitDOMDOMWindow*) -void webkit_dom_dom_window_blur(WebKitDOMDOMWindow*) -void webkit_dom_dom_window_close(WebKitDOMDOMWindow*) -void webkit_dom_dom_window_print(WebKitDOMDOMWindow*) -void webkit_dom_dom_window_stop(WebKitDOMDOMWindow*) -void webkit_dom_dom_window_alert(WebKitDOMDOMWindow*, const gchar*) -gboolean webkit_dom_dom_window_confirm(WebKitDOMDOMWindow*, const gchar*) -gchar* webkit_dom_dom_window_prompt(WebKitDOMDOMWindow*, const gchar*, const gchar*) -gboolean webkit_dom_dom_window_find(WebKitDOMDOMWindow*, const gchar*, gboolean, gboolean, gboolean, gboolean, gboolean, gboolean) -void webkit_dom_dom_window_scroll_by(WebKitDOMDOMWindow*, glong, glong) -void webkit_dom_dom_window_scroll_to(WebKitDOMDOMWindow*, glong, glong) -void webkit_dom_dom_window_scroll(WebKitDOMDOMWindow*, glong, glong) -void webkit_dom_dom_window_move_by(WebKitDOMDOMWindow*, gfloat, gfloat) -void webkit_dom_dom_window_move_to(WebKitDOMDOMWindow*, gfloat, gfloat) -void webkit_dom_dom_window_resize_by(WebKitDOMDOMWindow*, gfloat, gfloat) -void webkit_dom_dom_window_resize_to(WebKitDOMDOMWindow*, gfloat, gfloat) -WebKitDOMMediaQueryList* webkit_dom_dom_window_match_media(WebKitDOMDOMWindow*, const gchar*) -WebKitDOMCSSStyleDeclaration* webkit_dom_dom_window_get_computed_style(WebKitDOMDOMWindow*, WebKitDOMElement*, const gchar*) -WebKitDOMWebKitPoint* webkit_dom_dom_window_webkit_convert_point_from_page_to_node(WebKitDOMDOMWindow*, WebKitDOMNode*, WebKitDOMWebKitPoint*) -WebKitDOMWebKitPoint* webkit_dom_dom_window_webkit_convert_point_from_node_to_page(WebKitDOMDOMWindow*, WebKitDOMNode*, WebKitDOMWebKitPoint*) -void webkit_dom_dom_window_cancel_animation_frame(WebKitDOMDOMWindow*, glong) -void webkit_dom_dom_window_webkit_cancel_animation_frame(WebKitDOMDOMWindow*, glong) -void webkit_dom_dom_window_webkit_cancel_request_animation_frame(WebKitDOMDOMWindow*, glong) -gboolean webkit_dom_dom_window_dispatch_event(WebKitDOMDOMWindow*, WebKitDOMEvent*, GError**) -void webkit_dom_dom_window_capture_events(WebKitDOMDOMWindow*) -void webkit_dom_dom_window_release_events(WebKitDOMDOMWindow*) -gchar* webkit_dom_dom_window_atob(WebKitDOMDOMWindow*, const gchar*, GError**) -gchar* webkit_dom_dom_window_btoa(WebKitDOMDOMWindow*, const gchar*, GError**) -void webkit_dom_dom_window_clear_timeout(WebKitDOMDOMWindow*, glong) -void webkit_dom_dom_window_clear_interval(WebKitDOMDOMWindow*, glong) -WebKitDOMScreen* webkit_dom_dom_window_get_screen(WebKitDOMDOMWindow*) -WebKitDOMHistory* webkit_dom_dom_window_get_history(WebKitDOMDOMWindow*) -WebKitDOMBarProp* webkit_dom_dom_window_get_locationbar(WebKitDOMDOMWindow*) -WebKitDOMBarProp* webkit_dom_dom_window_get_menubar(WebKitDOMDOMWindow*) -WebKitDOMBarProp* webkit_dom_dom_window_get_personalbar(WebKitDOMDOMWindow*) -WebKitDOMBarProp* webkit_dom_dom_window_get_scrollbars(WebKitDOMDOMWindow*) -WebKitDOMBarProp* webkit_dom_dom_window_get_statusbar(WebKitDOMDOMWindow*) -WebKitDOMBarProp* webkit_dom_dom_window_get_toolbar(WebKitDOMDOMWindow*) -WebKitDOMNavigator* webkit_dom_dom_window_get_navigator(WebKitDOMDOMWindow*) -WebKitDOMNavigator* webkit_dom_dom_window_get_client_information(WebKitDOMDOMWindow*) -WebKitDOMElement* webkit_dom_dom_window_get_frame_element(WebKitDOMDOMWindow*) -gboolean webkit_dom_dom_window_get_offscreen_buffering(WebKitDOMDOMWindow*) -glong webkit_dom_dom_window_get_outer_height(WebKitDOMDOMWindow*) -glong webkit_dom_dom_window_get_outer_width(WebKitDOMDOMWindow*) -glong webkit_dom_dom_window_get_inner_height(WebKitDOMDOMWindow*) -glong webkit_dom_dom_window_get_inner_width(WebKitDOMDOMWindow*) -glong webkit_dom_dom_window_get_screen_x(WebKitDOMDOMWindow*) -glong webkit_dom_dom_window_get_screen_y(WebKitDOMDOMWindow*) -glong webkit_dom_dom_window_get_screen_left(WebKitDOMDOMWindow*) -glong webkit_dom_dom_window_get_screen_top(WebKitDOMDOMWindow*) -glong webkit_dom_dom_window_get_scroll_x(WebKitDOMDOMWindow*) -glong webkit_dom_dom_window_get_scroll_y(WebKitDOMDOMWindow*) -glong webkit_dom_dom_window_get_page_x_offset(WebKitDOMDOMWindow*) -glong webkit_dom_dom_window_get_page_y_offset(WebKitDOMDOMWindow*) -gboolean webkit_dom_dom_window_get_closed(WebKitDOMDOMWindow*) -gulong webkit_dom_dom_window_get_length(WebKitDOMDOMWindow*) -gchar* webkit_dom_dom_window_get_name(WebKitDOMDOMWindow*) -void webkit_dom_dom_window_set_name(WebKitDOMDOMWindow*, const gchar*) -gchar* webkit_dom_dom_window_get_status(WebKitDOMDOMWindow*) -void webkit_dom_dom_window_set_status(WebKitDOMDOMWindow*, const gchar*) -gchar* webkit_dom_dom_window_get_default_status(WebKitDOMDOMWindow*) -void webkit_dom_dom_window_set_default_status(WebKitDOMDOMWindow*, const gchar*) -WebKitDOMDOMWindow* webkit_dom_dom_window_get_self(WebKitDOMDOMWindow*) -WebKitDOMDOMWindow* webkit_dom_dom_window_get_window(WebKitDOMDOMWindow*) -WebKitDOMDOMWindow* webkit_dom_dom_window_get_frames(WebKitDOMDOMWindow*) -WebKitDOMDOMWindow* webkit_dom_dom_window_get_opener(WebKitDOMDOMWindow*) -WebKitDOMDOMWindow* webkit_dom_dom_window_get_parent(WebKitDOMDOMWindow*) -WebKitDOMDOMWindow* webkit_dom_dom_window_get_top(WebKitDOMDOMWindow*) -WebKitDOMDocument* webkit_dom_dom_window_get_document(WebKitDOMDOMWindow*) -WebKitDOMStyleMedia* webkit_dom_dom_window_get_style_media(WebKitDOMDOMWindow*) -gdouble webkit_dom_dom_window_get_device_pixel_ratio(WebKitDOMDOMWindow*) -WebKitDOMDOMApplicationCache* webkit_dom_dom_window_get_application_cache(WebKitDOMDOMWindow*) -WebKitDOMStorage* webkit_dom_dom_window_get_session_storage(WebKitDOMDOMWindow*, GError**) -WebKitDOMStorage* webkit_dom_dom_window_get_local_storage(WebKitDOMDOMWindow*, GError**) -WebKitDOMConsole* webkit_dom_dom_window_get_console(WebKitDOMDOMWindow*) -WebKitDOMPerformance* webkit_dom_dom_window_get_performance(WebKitDOMDOMWindow*) -WebKitDOMDOMWindowCSS* webkit_dom_dom_window_get_css(WebKitDOMDOMWindow*) -WebKitDOMStorageInfo* webkit_dom_dom_window_get_webkit_storage_info(WebKitDOMDOMWindow*) -void webkit_dom_dom_selection_collapse(WebKitDOMDOMSelection*, WebKitDOMNode*, glong, GError**) -void webkit_dom_dom_selection_collapse_to_end(WebKitDOMDOMSelection*, GError**) -void webkit_dom_dom_selection_collapse_to_start(WebKitDOMDOMSelection*, GError**) -void webkit_dom_dom_selection_delete_from_document(WebKitDOMDOMSelection*) -gboolean webkit_dom_dom_selection_contains_node(WebKitDOMDOMSelection*, WebKitDOMNode*, gboolean) -void webkit_dom_dom_selection_select_all_children(WebKitDOMDOMSelection*, WebKitDOMNode*, GError**) -void webkit_dom_dom_selection_extend(WebKitDOMDOMSelection*, WebKitDOMNode*, glong, GError**) -WebKitDOMRange* webkit_dom_dom_selection_get_range_at(WebKitDOMDOMSelection*, glong, GError**) -void webkit_dom_dom_selection_remove_all_ranges(WebKitDOMDOMSelection*) -void webkit_dom_dom_selection_add_range(WebKitDOMDOMSelection*, WebKitDOMRange*) -void webkit_dom_dom_selection_modify(WebKitDOMDOMSelection*, const gchar*, const gchar*, const gchar*) -void webkit_dom_dom_selection_set_base_and_extent(WebKitDOMDOMSelection*, WebKitDOMNode*, glong, WebKitDOMNode*, glong, GError**) -void webkit_dom_dom_selection_set_position(WebKitDOMDOMSelection*, WebKitDOMNode*, glong, GError**) -void webkit_dom_dom_selection_empty(WebKitDOMDOMSelection*) -WebKitDOMNode* webkit_dom_dom_selection_get_anchor_node(WebKitDOMDOMSelection*) -glong webkit_dom_dom_selection_get_anchor_offset(WebKitDOMDOMSelection*) -WebKitDOMNode* webkit_dom_dom_selection_get_focus_node(WebKitDOMDOMSelection*) -glong webkit_dom_dom_selection_get_focus_offset(WebKitDOMDOMSelection*) -gboolean webkit_dom_dom_selection_get_is_collapsed(WebKitDOMDOMSelection*) -glong webkit_dom_dom_selection_get_range_count(WebKitDOMDOMSelection*) -WebKitDOMNode* webkit_dom_dom_selection_get_base_node(WebKitDOMDOMSelection*) -glong webkit_dom_dom_selection_get_base_offset(WebKitDOMDOMSelection*) -WebKitDOMNode* webkit_dom_dom_selection_get_extent_node(WebKitDOMDOMSelection*) -glong webkit_dom_dom_selection_get_extent_offset(WebKitDOMDOMSelection*) -GType webkit_dom_event_target_get_type(void) -void webkit_dom_event_target_dispatch_event(WebKitDOMEventTarget*, WebKitDOMEvent* event, GError**) -gboolean webkit_dom_event_target_add_event_listener(WebKitDOMEventTarget* target, const char*, GCallback, gboolean, gpointer) -gboolean webkit_dom_event_target_remove_event_listener(WebKitDOMEventTarget*, const char*, GCallback, gboolean) -gboolean webkit_dom_event_target_add_event_listener_with_closure(WebKitDOMEventTarget*, const char*, GClosure*, gboolean) -gboolean webkit_dom_event_target_remove_event_listener_with_closure(WebKitDOMEventTarget*, const char*, GClosure*, gboolean) -void webkit_dom_history_back(WebKitDOMHistory*) -void webkit_dom_history_forward(WebKitDOMHistory*) -void webkit_dom_history_go(WebKitDOMHistory*, glong) -gulong webkit_dom_history_get_length(WebKitDOMHistory*) -gchar* webkit_dom_location_get_href(WebKitDOMLocation*) -gchar* webkit_dom_location_get_protocol(WebKitDOMLocation*) -gchar* webkit_dom_location_get_host(WebKitDOMLocation*) -gchar* webkit_dom_location_get_hostname(WebKitDOMLocation*) -gchar* webkit_dom_location_get_port(WebKitDOMLocation*) -gchar* webkit_dom_location_get_pathname(WebKitDOMLocation*) -gchar* webkit_dom_location_get_search(WebKitDOMLocation*) -gchar* webkit_dom_location_get_hash(WebKitDOMLocation*) -gchar* webkit_dom_location_get_origin(WebKitDOMLocation*) -WebKitDOMDOMStringList* webkit_dom_location_get_ancestor_origins(WebKitDOMLocation*) -GType webkit_dom_object_get_type(void) -gboolean webkit_dom_navigator_java_enabled(WebKitDOMNavigator*) -void webkit_dom_navigator_get_storage_updates(WebKitDOMNavigator*) -WebKitDOMGamepadList* webkit_dom_navigator_webkit_get_gamepads(WebKitDOMNavigator*) -void webkit_dom_navigator_register_protocol_handler(WebKitDOMNavigator*, const gchar*, const gchar*, const gchar*, GError**) -gchar* webkit_dom_navigator_is_protocol_handler_registered(WebKitDOMNavigator*, const gchar*, const gchar*, GError**) -void webkit_dom_navigator_unregister_protocol_handler(WebKitDOMNavigator*, const gchar*, const gchar*, GError**) -gchar* webkit_dom_navigator_get_app_code_name(WebKitDOMNavigator*) -gchar* webkit_dom_navigator_get_app_name(WebKitDOMNavigator*) -gchar* webkit_dom_navigator_get_app_version(WebKitDOMNavigator*) -gchar* webkit_dom_navigator_get_language(WebKitDOMNavigator*) -gchar* webkit_dom_navigator_get_user_agent(WebKitDOMNavigator*) -gchar* webkit_dom_navigator_get_platform(WebKitDOMNavigator*) -WebKitDOMDOMPluginArray* webkit_dom_navigator_get_plugins(WebKitDOMNavigator*) -WebKitDOMDOMMimeTypeArray* webkit_dom_navigator_get_mime_types(WebKitDOMNavigator*) -gchar* webkit_dom_navigator_get_product(WebKitDOMNavigator*) -gchar* webkit_dom_navigator_get_product_sub(WebKitDOMNavigator*) -gchar* webkit_dom_navigator_get_vendor(WebKitDOMNavigator*) -gchar* webkit_dom_navigator_get_vendor_sub(WebKitDOMNavigator*) -gboolean webkit_dom_navigator_get_cookie_enabled(WebKitDOMNavigator*) -gboolean webkit_dom_navigator_get_on_line(WebKitDOMNavigator*) -WebKitDOMBatteryManager* webkit_dom_navigator_get_webkit_battery(WebKitDOMNavigator*) -WebKitDOMGeolocation* webkit_dom_navigator_get_geolocation(WebKitDOMNavigator*) -WebKitDOMStorageQuota* webkit_dom_navigator_get_webkit_temporary_storage(WebKitDOMNavigator*) -WebKitDOMStorageQuota* webkit_dom_navigator_get_webkit_persistent_storage(WebKitDOMNavigator*) -gulong webkit_dom_screen_get_height(WebKitDOMScreen*) -gulong webkit_dom_screen_get_width(WebKitDOMScreen*) -gulong webkit_dom_screen_get_color_depth(WebKitDOMScreen*) -gulong webkit_dom_screen_get_pixel_depth(WebKitDOMScreen*) -glong webkit_dom_screen_get_avail_left(WebKitDOMScreen*) -glong webkit_dom_screen_get_avail_top(WebKitDOMScreen*) -gulong webkit_dom_screen_get_avail_height(WebKitDOMScreen*) -gulong webkit_dom_screen_get_avail_width(WebKitDOMScreen*) -WebKitDOMDOMSelection* webkit_dom_shadow_root_get_selection(WebKitDOMShadowRoot*) -WebKitDOMElement* webkit_dom_shadow_root_get_element_by_id(WebKitDOMShadowRoot*, const gchar*) -WebKitDOMNodeList* webkit_dom_shadow_root_get_elements_by_class_name(WebKitDOMShadowRoot*, const gchar*) -WebKitDOMNodeList* webkit_dom_shadow_root_get_elements_by_tag_name(WebKitDOMShadowRoot*, const gchar*) -WebKitDOMNodeList* webkit_dom_shadow_root_get_elements_by_tag_name_ns(WebKitDOMShadowRoot*, const gchar*, const gchar*) -WebKitDOMElement* webkit_dom_shadow_root_element_from_point(WebKitDOMShadowRoot*, glong, glong) -WebKitDOMElement* webkit_dom_shadow_root_get_active_element(WebKitDOMShadowRoot*) -gboolean webkit_dom_shadow_root_get_apply_author_styles(WebKitDOMShadowRoot*) -void webkit_dom_shadow_root_set_apply_author_styles(WebKitDOMShadowRoot*, gboolean) -gboolean webkit_dom_shadow_root_get_reset_style_inheritance(WebKitDOMShadowRoot*) -void webkit_dom_shadow_root_set_reset_style_inheritance(WebKitDOMShadowRoot*, gboolean) -gchar* webkit_dom_shadow_root_get_inner_html(WebKitDOMShadowRoot*) -void webkit_dom_shadow_root_set_inner_html(WebKitDOMShadowRoot*, const gchar*, GError**) -gfloat webkit_dom_webkit_point_get_x(WebKitDOMWebKitPoint*) -void webkit_dom_webkit_point_set_x(WebKitDOMWebKitPoint*, gfloat) -gfloat webkit_dom_webkit_point_get_y(WebKitDOMWebKitPoint*) -void webkit_dom_webkit_point_set_y(WebKitDOMWebKitPoint*, gfloat) -WebKitDOMNodeList* webkit_dom_webkit_named_flow_get_regions_by_content(WebKitDOMWebKitNamedFlow*, WebKitDOMNode*) -WebKitDOMNodeList* webkit_dom_webkit_named_flow_get_regions(WebKitDOMWebKitNamedFlow*) -WebKitDOMNodeList* webkit_dom_webkit_named_flow_get_content(WebKitDOMWebKitNamedFlow*) -gboolean webkit_dom_webkit_named_flow_dispatch_event(WebKitDOMWebKitNamedFlow*, WebKitDOMEvent*, GError**) -gchar* webkit_dom_webkit_named_flow_get_name(WebKitDOMWebKitNamedFlow*) -gboolean webkit_dom_webkit_named_flow_get_overset(WebKitDOMWebKitNamedFlow*) -glong webkit_dom_webkit_named_flow_get_first_empty_region_index(WebKitDOMWebKitNamedFlow*) -gchar* webkit_dom_dom_mime_type_get_suffixes(WebKitDOMDOMMimeType*) -gchar* webkit_dom_dom_mime_type_get_description(WebKitDOMDOMMimeType*) -WebKitDOMDOMPlugin* webkit_dom_dom_mime_type_get_enabled_plugin(WebKitDOMDOMMimeType*) -WebKitDOMDOMMimeType* webkit_dom_dom_mime_type_array_item(WebKitDOMDOMMimeTypeArray*, gulong) -WebKitDOMDOMMimeType* webkit_dom_dom_mime_type_array_named_item(WebKitDOMDOMMimeTypeArray*, const gchar*) -gulong webkit_dom_dom_mime_type_array_get_length(WebKitDOMDOMMimeTypeArray*) -WebKitDOMDOMMimeType* webkit_dom_dom_plugin_item(WebKitDOMDOMPlugin*, gulong) -WebKitDOMDOMMimeType* webkit_dom_dom_plugin_named_item(WebKitDOMDOMPlugin*, const gchar*) -gchar* webkit_dom_dom_plugin_get_name(WebKitDOMDOMPlugin*) -gchar* webkit_dom_dom_plugin_get_filename(WebKitDOMDOMPlugin*) -gchar* webkit_dom_dom_plugin_get_description(WebKitDOMDOMPlugin*) -gulong webkit_dom_dom_plugin_get_length(WebKitDOMDOMPlugin*) -WebKitDOMDOMPlugin* webkit_dom_dom_plugin_array_item(WebKitDOMDOMPluginArray*, gulong) -WebKitDOMDOMPlugin* webkit_dom_dom_plugin_array_named_item(WebKitDOMDOMPluginArray*, const gchar*) -void webkit_dom_dom_plugin_array_refresh(WebKitDOMDOMPluginArray*, gboolean) -gulong webkit_dom_dom_plugin_array_get_length(WebKitDOMDOMPluginArray*) -gchar* webkit_dom_database_get_version(WebKitDOMDatabase*) -gchar* webkit_dom_storage_key(WebKitDOMStorage*, gulong, GError**) -gchar* webkit_dom_storage_get_item(WebKitDOMStorage*, const gchar*, GError**) -void webkit_dom_storage_set_item(WebKitDOMStorage*, const gchar*, const gchar*, GError**) -void webkit_dom_storage_remove_item(WebKitDOMStorage*, const gchar*, GError**) -void webkit_dom_storage_clear(WebKitDOMStorage*, GError**) -gulong webkit_dom_storage_get_length(WebKitDOMStorage*, GError**) -WebKitDOMXPathResult* webkit_dom_xpath_expression_evaluate(WebKitDOMXPathExpression*, WebKitDOMNode*, gushort, WebKitDOMXPathResult*, GError**) -gchar* webkit_dom_xpath_ns_resolver_lookup_namespace_uri(WebKitDOMXPathNSResolver*, const gchar*) -WebKitDOMNode* webkit_dom_xpath_result_iterate_next(WebKitDOMXPathResult*, GError**) -WebKitDOMNode* webkit_dom_xpath_result_snapshot_item(WebKitDOMXPathResult*, gulong, GError**) -gushort webkit_dom_xpath_result_get_result_type(WebKitDOMXPathResult*) -gdouble webkit_dom_xpath_result_get_number_value(WebKitDOMXPathResult*, GError**) -gchar* webkit_dom_xpath_result_get_string_value(WebKitDOMXPathResult*, GError**) -gboolean webkit_dom_xpath_result_get_boolean_value(WebKitDOMXPathResult*, GError**) -WebKitDOMNode* webkit_dom_xpath_result_get_single_node_value(WebKitDOMXPathResult*, GError**) -gboolean webkit_dom_xpath_result_get_invalid_iterator_state(WebKitDOMXPathResult*) -gulong webkit_dom_xpath_result_get_snapshot_length(WebKitDOMXPathResult*, GError**) -WebKitDOMPerformanceEntryList* webkit_dom_performance_webkit_get_entries(WebKitDOMPerformance*) -WebKitDOMPerformanceEntryList* webkit_dom_performance_webkit_get_entries_by_type(WebKitDOMPerformance*, const gchar*) -WebKitDOMPerformanceEntryList* webkit_dom_performance_webkit_get_entries_by_name(WebKitDOMPerformance*, const gchar*, const gchar*) -void webkit_dom_performance_webkit_clear_resource_timings(WebKitDOMPerformance*) -void webkit_dom_performance_webkit_set_resource_timing_buffer_size(WebKitDOMPerformance*, gulong) -void webkit_dom_performance_webkit_mark(WebKitDOMPerformance*, const gchar*, GError**) -void webkit_dom_performance_webkit_clear_marks(WebKitDOMPerformance*, const gchar*) -void webkit_dom_performance_webkit_measure(WebKitDOMPerformance*, const gchar*, const gchar*, const gchar*, GError**) -void webkit_dom_performance_webkit_clear_measures(WebKitDOMPerformance*, const gchar*) -gdouble webkit_dom_performance_now(WebKitDOMPerformance*) -WebKitDOMPerformanceNavigation* webkit_dom_performance_get_navigation(WebKitDOMPerformance*) -WebKitDOMPerformanceTiming* webkit_dom_performance_get_timing(WebKitDOMPerformance*) -gchar* webkit_dom_performance_entry_get_name(WebKitDOMPerformanceEntry*) -gchar* webkit_dom_performance_entry_get_entry_type(WebKitDOMPerformanceEntry*) -gdouble webkit_dom_performance_entry_get_start_time(WebKitDOMPerformanceEntry*) -gdouble webkit_dom_performance_entry_get_duration(WebKitDOMPerformanceEntry*) -WebKitDOMPerformanceEntry* webkit_dom_performance_entry_list_item(WebKitDOMPerformanceEntryList*, gulong) -gulong webkit_dom_performance_entry_list_get_length(WebKitDOMPerformanceEntryList*) -gushort webkit_dom_performance_navigation_get_redirect_count(WebKitDOMPerformanceNavigation*) -guint64 webkit_dom_performance_timing_get_navigation_start(WebKitDOMPerformanceTiming*) -guint64 webkit_dom_performance_timing_get_unload_event_start(WebKitDOMPerformanceTiming*) -guint64 webkit_dom_performance_timing_get_unload_event_end(WebKitDOMPerformanceTiming*) -guint64 webkit_dom_performance_timing_get_redirect_start(WebKitDOMPerformanceTiming*) -guint64 webkit_dom_performance_timing_get_redirect_end(WebKitDOMPerformanceTiming*) -guint64 webkit_dom_performance_timing_get_fetch_start(WebKitDOMPerformanceTiming*) -guint64 webkit_dom_performance_timing_get_domain_lookup_start(WebKitDOMPerformanceTiming*) -guint64 webkit_dom_performance_timing_get_domain_lookup_end(WebKitDOMPerformanceTiming*) -guint64 webkit_dom_performance_timing_get_connect_start(WebKitDOMPerformanceTiming*) -guint64 webkit_dom_performance_timing_get_connect_end(WebKitDOMPerformanceTiming*) -guint64 webkit_dom_performance_timing_get_secure_connection_start(WebKitDOMPerformanceTiming*) -guint64 webkit_dom_performance_timing_get_request_start(WebKitDOMPerformanceTiming*) -guint64 webkit_dom_performance_timing_get_response_start(WebKitDOMPerformanceTiming*) -guint64 webkit_dom_performance_timing_get_response_end(WebKitDOMPerformanceTiming*) -guint64 webkit_dom_performance_timing_get_dom_loading(WebKitDOMPerformanceTiming*) -guint64 webkit_dom_performance_timing_get_dom_interactive(WebKitDOMPerformanceTiming*) -guint64 webkit_dom_performance_timing_get_dom_content_loaded_event_start(WebKitDOMPerformanceTiming*) -guint64 webkit_dom_performance_timing_get_dom_content_loaded_event_end(WebKitDOMPerformanceTiming*) -guint64 webkit_dom_performance_timing_get_dom_complete(WebKitDOMPerformanceTiming*) -guint64 webkit_dom_performance_timing_get_load_event_start(WebKitDOMPerformanceTiming*) -guint64 webkit_dom_performance_timing_get_load_event_end(WebKitDOMPerformanceTiming*) -void webkit_dom_wheel_event_init_wheel_event(WebKitDOMWheelEvent*, glong, glong, WebKitDOMDOMWindow*, glong, glong, glong, glong, gboolean, gboolean, gboolean, gboolean) -gdouble webkit_dom_wheel_event_get_delta_x(WebKitDOMWheelEvent*) -gdouble webkit_dom_wheel_event_get_delta_y(WebKitDOMWheelEvent*) -gdouble webkit_dom_wheel_event_get_delta_z(WebKitDOMWheelEvent*) -gulong webkit_dom_wheel_event_get_delta_mode(WebKitDOMWheelEvent*) -glong webkit_dom_wheel_event_get_wheel_delta_x(WebKitDOMWheelEvent*) -glong webkit_dom_wheel_event_get_wheel_delta_y(WebKitDOMWheelEvent*) -glong webkit_dom_wheel_event_get_wheel_delta(WebKitDOMWheelEvent*) -gboolean webkit_dom_wheel_event_get_webkit_direction_inverted_from_device(WebKitDOMWheelEvent*) -WebKitDOMEventTarget* webkit_dom_touch_get_target(WebKitDOMTouch*) -gfloat webkit_dom_touch_get_webkit_force(WebKitDOMTouch*) -gfloat webkit_dom_touch_get_webkit_rotation_angle(WebKitDOMTouch*) -glong webkit_dom_touch_get_client_x(WebKitDOMTouch*) -glong webkit_dom_touch_get_client_y(WebKitDOMTouch*) -glong webkit_dom_touch_get_page_x(WebKitDOMTouch*) -glong webkit_dom_touch_get_page_y(WebKitDOMTouch*) -glong webkit_dom_touch_get_screen_x(WebKitDOMTouch*) -glong webkit_dom_touch_get_screen_y(WebKitDOMTouch*) -glong webkit_dom_touch_get_webkit_radius_x(WebKitDOMTouch*) -glong webkit_dom_touch_get_webkit_radius_y(WebKitDOMTouch*) -gulong webkit_dom_touch_get_identifier(WebKitDOMTouch*) -gchar* webkit_dom_audio_track_get_id(WebKitDOMAudioTrack*) -gchar* webkit_dom_audio_track_get_kind(WebKitDOMAudioTrack*) -gchar* webkit_dom_audio_track_get_label(WebKitDOMAudioTrack*) -gchar* webkit_dom_audio_track_get_language(WebKitDOMAudioTrack*) -gboolean webkit_dom_audio_track_get_enabled(WebKitDOMAudioTrack*) -void webkit_dom_audio_track_set_enabled(WebKitDOMAudioTrack*, gboolean) -WebKitDOMAudioTrack* webkit_dom_audio_track_list_item(WebKitDOMAudioTrackList*, gulong) -WebKitDOMAudioTrack* webkit_dom_audio_track_list_get_track_by_id(WebKitDOMAudioTrackList*, const gchar*) -gboolean webkit_dom_audio_track_list_dispatch_event(WebKitDOMAudioTrackList*, WebKitDOMEvent*, GError**) -gulong webkit_dom_audio_track_list_get_length(WebKitDOMAudioTrackList*) -void webkit_dom_html_video_element_webkit_enter_fullscreen(WebKitDOMHTMLVideoElement*, GError**) -void webkit_dom_html_video_element_webkit_exit_fullscreen(WebKitDOMHTMLVideoElement*) -void webkit_dom_html_video_element_webkit_enter_full_screen(WebKitDOMHTMLVideoElement*, GError**) -void webkit_dom_html_video_element_webkit_exit_full_screen(WebKitDOMHTMLVideoElement*) -gulong webkit_dom_html_video_element_get_width(WebKitDOMHTMLVideoElement*) -void webkit_dom_html_video_element_set_width(WebKitDOMHTMLVideoElement*, gulong) -gulong webkit_dom_html_video_element_get_height(WebKitDOMHTMLVideoElement*) -void webkit_dom_html_video_element_set_height(WebKitDOMHTMLVideoElement*, gulong) -gulong webkit_dom_html_video_element_get_video_width(WebKitDOMHTMLVideoElement*) -gulong webkit_dom_html_video_element_get_video_height(WebKitDOMHTMLVideoElement*) -gchar* webkit_dom_html_video_element_get_poster(WebKitDOMHTMLVideoElement*) -void webkit_dom_html_video_element_set_poster(WebKitDOMHTMLVideoElement*, const gchar*) -gboolean webkit_dom_html_video_element_get_webkit_supports_fullscreen(WebKitDOMHTMLVideoElement*) -gboolean webkit_dom_html_video_element_get_webkit_displaying_fullscreen(WebKitDOMHTMLVideoElement*) -gboolean webkit_dom_html_video_element_get_webkit_wireless_video_playback_disabled(WebKitDOMHTMLVideoElement*) -void webkit_dom_html_video_element_set_webkit_wireless_video_playback_disabled(WebKitDOMHTMLVideoElement*, gboolean) -gulong webkit_dom_html_video_element_get_webkit_decoded_frame_count(WebKitDOMHTMLVideoElement*) -gulong webkit_dom_html_video_element_get_webkit_dropped_frame_count(WebKitDOMHTMLVideoElement*) -void webkit_dom_text_track_add_cue(WebKitDOMTextTrack*, WebKitDOMTextTrackCue*) -void webkit_dom_text_track_remove_cue(WebKitDOMTextTrack*, WebKitDOMTextTrackCue*, GError**) -gboolean webkit_dom_text_track_dispatch_event(WebKitDOMTextTrack*, WebKitDOMEvent*, GError**) -gchar* webkit_dom_text_track_get_id(WebKitDOMTextTrack*) -gchar* webkit_dom_text_track_get_kind(WebKitDOMTextTrack*) -gchar* webkit_dom_text_track_get_label(WebKitDOMTextTrack*) -gchar* webkit_dom_text_track_get_language(WebKitDOMTextTrack*) -gchar* webkit_dom_text_track_get_mode(WebKitDOMTextTrack*) -void webkit_dom_text_track_set_mode(WebKitDOMTextTrack*, const gchar*) -WebKitDOMTextTrackCueList* webkit_dom_text_track_get_cues(WebKitDOMTextTrack*) -WebKitDOMTextTrackCueList* webkit_dom_text_track_get_active_cues(WebKitDOMTextTrack*) -WebKitDOMTextTrack* webkit_dom_text_track_list_item(WebKitDOMTextTrackList*, gulong) -WebKitDOMTextTrack* webkit_dom_text_track_list_get_track_by_id(WebKitDOMTextTrackList*, const gchar*) -gboolean webkit_dom_text_track_list_dispatch_event(WebKitDOMTextTrackList*, WebKitDOMEvent*, GError**) -gulong webkit_dom_text_track_list_get_length(WebKitDOMTextTrackList*) -WebKitDOMDocumentFragment* webkit_dom_text_track_cue_get_cue_as_html(WebKitDOMTextTrackCue*) -gboolean webkit_dom_text_track_cue_dispatch_event(WebKitDOMTextTrackCue*, WebKitDOMEvent*, GError**) -WebKitDOMTextTrack* webkit_dom_text_track_cue_get_track(WebKitDOMTextTrackCue*) -gchar* webkit_dom_text_track_cue_get_id(WebKitDOMTextTrackCue*) -void webkit_dom_text_track_cue_set_id(WebKitDOMTextTrackCue*, const gchar*) -gdouble webkit_dom_text_track_cue_get_start_time(WebKitDOMTextTrackCue*) -void webkit_dom_text_track_cue_set_start_time(WebKitDOMTextTrackCue*, gdouble, GError**) -gdouble webkit_dom_text_track_cue_get_end_time(WebKitDOMTextTrackCue*) -void webkit_dom_text_track_cue_set_end_time(WebKitDOMTextTrackCue*, gdouble, GError**) -gboolean webkit_dom_text_track_cue_get_pause_on_exit(WebKitDOMTextTrackCue*) -void webkit_dom_text_track_cue_set_pause_on_exit(WebKitDOMTextTrackCue*, gboolean) -gchar* webkit_dom_text_track_cue_get_vertical(WebKitDOMTextTrackCue*) -void webkit_dom_text_track_cue_set_vertical(WebKitDOMTextTrackCue*, const gchar*, GError**) -gboolean webkit_dom_text_track_cue_get_snap_to_lines(WebKitDOMTextTrackCue*) -void webkit_dom_text_track_cue_set_snap_to_lines(WebKitDOMTextTrackCue*, gboolean) -glong webkit_dom_text_track_cue_get_line(WebKitDOMTextTrackCue*) -void webkit_dom_text_track_cue_set_line(WebKitDOMTextTrackCue*, glong, GError**) -glong webkit_dom_text_track_cue_get_position(WebKitDOMTextTrackCue*) -void webkit_dom_text_track_cue_set_position(WebKitDOMTextTrackCue*, glong, GError**) -glong webkit_dom_text_track_cue_get_size(WebKitDOMTextTrackCue*) -void webkit_dom_text_track_cue_set_size(WebKitDOMTextTrackCue*, glong, GError**) -gchar* webkit_dom_text_track_cue_get_align(WebKitDOMTextTrackCue*) -void webkit_dom_text_track_cue_set_align(WebKitDOMTextTrackCue*, const gchar*, GError**) -gchar* webkit_dom_text_track_cue_get_text(WebKitDOMTextTrackCue*) -void webkit_dom_text_track_cue_set_text(WebKitDOMTextTrackCue*, const gchar*) -WebKitDOMTextTrackCue* webkit_dom_text_track_cue_list_item(WebKitDOMTextTrackCueList*, gulong) -WebKitDOMTextTrackCue* webkit_dom_text_track_cue_list_get_cue_by_id(WebKitDOMTextTrackCueList*, const gchar*) -gulong webkit_dom_text_track_cue_list_get_length(WebKitDOMTextTrackCueList*) -gdouble webkit_dom_video_playback_quality_get_creation_time(WebKitDOMVideoPlaybackQuality*) -gulong webkit_dom_video_playback_quality_get_total_video_frames(WebKitDOMVideoPlaybackQuality*) -gulong webkit_dom_video_playback_quality_get_dropped_video_frames(WebKitDOMVideoPlaybackQuality*) -gulong webkit_dom_video_playback_quality_get_corrupted_video_frames(WebKitDOMVideoPlaybackQuality*) -gdouble webkit_dom_video_playback_quality_get_total_frame_delay(WebKitDOMVideoPlaybackQuality*) -gchar* webkit_dom_video_track_get_id(WebKitDOMVideoTrack*) -gchar* webkit_dom_video_track_get_kind(WebKitDOMVideoTrack*) -gchar* webkit_dom_video_track_get_label(WebKitDOMVideoTrack*) -gchar* webkit_dom_video_track_get_language(WebKitDOMVideoTrack*) -gboolean webkit_dom_video_track_get_selected(WebKitDOMVideoTrack*) -void webkit_dom_video_track_set_selected(WebKitDOMVideoTrack*, gboolean) -WebKitDOMVideoTrack* webkit_dom_video_track_list_item(WebKitDOMVideoTrackList*, gulong) -WebKitDOMVideoTrack* webkit_dom_video_track_list_get_track_by_id(WebKitDOMVideoTrackList*, const gchar*) -gboolean webkit_dom_video_track_list_dispatch_event(WebKitDOMVideoTrackList*, WebKitDOMEvent*, GError**) -gulong webkit_dom_video_track_list_get_length(WebKitDOMVideoTrackList*) diff --git a/Source/WebCore/bindings/js/ArrayValue.cpp b/Source/WebCore/bindings/js/ArrayValue.cpp deleted file mode 100644 index e810f435e..000000000 --- a/Source/WebCore/bindings/js/ArrayValue.cpp +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright (C) 2012 Google Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" -#include "ArrayValue.h" - -#include "Dictionary.h" -#include <runtime/JSArray.h> - -using namespace JSC; - -namespace WebCore { - -ArrayValue::ArrayValue() - : m_exec(0) -{ -} - -ArrayValue::ArrayValue(JSC::ExecState* exec, JSC::JSValue value) - : m_exec(exec) -{ - if (!value.isUndefinedOrNull() && isJSArray(value)) - m_value = value; -} - -ArrayValue& ArrayValue::operator=(const ArrayValue& other) -{ - m_exec = other.m_exec; - m_value = other.m_value; - return *this; -} - -bool ArrayValue::isUndefinedOrNull() const -{ - return m_value.isEmpty() || m_value.isUndefinedOrNull(); -} - -bool ArrayValue::length(size_t& length) const -{ - if (isUndefinedOrNull()) - return false; - - JSArray* array = asArray(m_value); - length = array->length(); - return true; -} - -bool ArrayValue::get(size_t index, Dictionary& value) const -{ - if (isUndefinedOrNull()) - return false; - - JSValue indexedValue = asArray(m_value)->getIndex(m_exec, index); - if (indexedValue.isUndefinedOrNull() || !indexedValue.isObject()) - return false; - - value = Dictionary(m_exec, indexedValue); - return true; -} - -} // namespace WebCore diff --git a/Source/WebCore/bindings/js/ArrayValue.h b/Source/WebCore/bindings/js/ArrayValue.h deleted file mode 100644 index 084f8c3cf..000000000 --- a/Source/WebCore/bindings/js/ArrayValue.h +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright (C) 2012 Google Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef ArrayValue_h -#define ArrayValue_h - -#include <interpreter/CallFrame.h> - -namespace WebCore { - -class Dictionary; - -class ArrayValue { -public: - ArrayValue(); - ArrayValue(JSC::ExecState*, JSC::JSValue); - - ArrayValue& operator=(const ArrayValue&); - - bool isUndefinedOrNull() const; - - bool length(size_t&) const; - bool get(size_t index, Dictionary&) const; - -private: - JSC::ExecState* m_exec; - JSC::JSValue m_value; -}; - -} - -#endif // ArrayValue_h diff --git a/Source/WebCore/bindings/js/BufferSource.h b/Source/WebCore/bindings/js/BufferSource.h new file mode 100644 index 000000000..01e458418 --- /dev/null +++ b/Source/WebCore/bindings/js/BufferSource.h @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2016 Igalia S.L. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +#include <runtime/ArrayBuffer.h> +#include <runtime/ArrayBufferView.h> +#include <wtf/RefPtr.h> +#include <wtf/Variant.h> + +namespace WebCore { + +class BufferSource { +public: + using VariantType = WTF::Variant<RefPtr<JSC::ArrayBufferView>, RefPtr<JSC::ArrayBuffer>>; + + BufferSource() { } + BufferSource(VariantType&& variant) + : m_variant(WTFMove(variant)) + { } + + const VariantType& variant() const { return m_variant; } + + const uint8_t* data() const + { + return WTF::visit([](auto& buffer) -> const uint8_t* { + return static_cast<const uint8_t*>(buffer->data()); + }, m_variant); + } + + size_t length() const + { + return WTF::visit([](auto& buffer) -> size_t { + return buffer->byteLength(); + }, m_variant); + } + +private: + VariantType m_variant; +}; + +} // namespace WebCore diff --git a/Source/WebCore/bindings/js/CachedModuleScriptLoader.cpp b/Source/WebCore/bindings/js/CachedModuleScriptLoader.cpp new file mode 100644 index 000000000..f15a4642e --- /dev/null +++ b/Source/WebCore/bindings/js/CachedModuleScriptLoader.cpp @@ -0,0 +1,89 @@ +/* + * Copyright (C) 2015-2016 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "CachedModuleScriptLoader.h" + +#include "CachedScript.h" +#include "CachedScriptFetcher.h" +#include "DOMWrapperWorld.h" +#include "Frame.h" +#include "JSDOMBinding.h" +#include "ResourceLoaderOptions.h" +#include "ScriptController.h" +#include "ScriptModuleLoader.h" +#include "ScriptSourceCode.h" + +namespace WebCore { + +Ref<CachedModuleScriptLoader> CachedModuleScriptLoader::create(CachedModuleScriptLoaderClient& client, DeferredPromise& promise, CachedScriptFetcher& scriptFetcher) +{ + return adoptRef(*new CachedModuleScriptLoader(client, promise, scriptFetcher)); +} + +CachedModuleScriptLoader::CachedModuleScriptLoader(CachedModuleScriptLoaderClient& client, DeferredPromise& promise, CachedScriptFetcher& scriptFetcher) + : m_client(&client) + , m_promise(&promise) + , m_scriptFetcher(scriptFetcher) +{ +} + +CachedModuleScriptLoader::~CachedModuleScriptLoader() +{ + if (m_cachedScript) { + m_cachedScript->removeClient(*this); + m_cachedScript = nullptr; + } +} + +bool CachedModuleScriptLoader::load(Document& document, const URL& sourceURL) +{ + ASSERT(!m_cachedScript); + m_cachedScript = m_scriptFetcher->requestModuleScript(document, sourceURL); + if (!m_cachedScript) + return false; + + // If the content is already cached, this immediately calls notifyFinished. + m_cachedScript->addClient(*this); + return true; +} + +void CachedModuleScriptLoader::notifyFinished(CachedResource& resource) +{ + ASSERT_UNUSED(resource, &resource == m_cachedScript); + ASSERT(m_cachedScript); + ASSERT(m_promise); + + Ref<CachedModuleScriptLoader> protectedThis(*this); + if (m_client) + m_client->notifyFinished(*this, WTFMove(m_promise)); + + // Remove the client after calling notifyFinished to keep the data buffer in + // CachedResource alive while notifyFinished processes the resource. + m_cachedScript->removeClient(*this); + m_cachedScript = nullptr; +} + +} diff --git a/Source/WebCore/bindings/js/CachedModuleScriptLoader.h b/Source/WebCore/bindings/js/CachedModuleScriptLoader.h new file mode 100644 index 000000000..04923f4dc --- /dev/null +++ b/Source/WebCore/bindings/js/CachedModuleScriptLoader.h @@ -0,0 +1,72 @@ +/* + * Copyright (C) 2015, 2016 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +#include "CachedResourceClient.h" +#include "CachedResourceHandle.h" +#include <wtf/Ref.h> +#include <wtf/RefCounted.h> +#include <wtf/RefPtr.h> + +namespace WebCore { + +class CachedModuleScriptLoaderClient; +class CachedScript; +class CachedScriptFetcher; +class DeferredPromise; +class Document; +class JSDOMGlobalObject; +class URL; + +class CachedModuleScriptLoader final : public RefCounted<CachedModuleScriptLoader>, private CachedResourceClient { +public: + static Ref<CachedModuleScriptLoader> create(CachedModuleScriptLoaderClient&, DeferredPromise&, CachedScriptFetcher&); + + virtual ~CachedModuleScriptLoader(); + + bool load(Document&, const URL& sourceURL); + + CachedScriptFetcher& scriptFetcher() { return m_scriptFetcher.get(); } + CachedScript* cachedScript() { return m_cachedScript.get(); } + + void clearClient() + { + ASSERT(m_client); + m_client = nullptr; + } + +private: + CachedModuleScriptLoader(CachedModuleScriptLoaderClient&, DeferredPromise&, CachedScriptFetcher&); + + void notifyFinished(CachedResource&) final; + + CachedModuleScriptLoaderClient* m_client { nullptr }; + RefPtr<DeferredPromise> m_promise; + Ref<CachedScriptFetcher> m_scriptFetcher; + CachedResourceHandle<CachedScript> m_cachedScript; +}; + +} // namespace WebCore diff --git a/Source/WebCore/bindings/gobject/WebKitDOMHTMLPrivate.h b/Source/WebCore/bindings/js/CachedModuleScriptLoaderClient.h index 4bd7cb938..6ccdbccca 100644 --- a/Source/WebCore/bindings/gobject/WebKitDOMHTMLPrivate.h +++ b/Source/WebCore/bindings/js/CachedModuleScriptLoaderClient.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2013 Igalia S.L. + * Copyright (C) 2016 Apple, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -10,10 +10,10 @@ * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * - * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR @@ -21,19 +21,21 @@ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ + */ -#ifndef WebKitDOMHTMLPrivate_h -#define WebKitDOMHTMLPrivate_h +#pragma once -#include <webkitdom/webkitdomdefines.h> +#include "JSDOMPromise.h" namespace WebCore { -class HTMLElement; -} -namespace WebKit { -WebKitDOMHTMLElement* wrap(WebCore::HTMLElement*); -} +class CachedModuleScriptLoader; + +class CachedModuleScriptLoaderClient { +public: + virtual ~CachedModuleScriptLoaderClient() { } -#endif // WebKitDOMHTMLPrivate_h + virtual void notifyFinished(CachedModuleScriptLoader&, RefPtr<DeferredPromise>) = 0; +}; + +} diff --git a/Source/WebCore/bindings/js/CachedScriptFetcher.cpp b/Source/WebCore/bindings/js/CachedScriptFetcher.cpp new file mode 100644 index 000000000..e54f78513 --- /dev/null +++ b/Source/WebCore/bindings/js/CachedScriptFetcher.cpp @@ -0,0 +1,68 @@ +/* + * Copyright (C) 2017 Yusuke Suzuki <utatane.tea@gmail.com> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "CachedScriptFetcher.h" + +#include "CachedResourceLoader.h" +#include "CachedScript.h" +#include "ContentSecurityPolicy.h" +#include "Document.h" +#include "Settings.h" + +namespace WebCore { + +Ref<CachedScriptFetcher> CachedScriptFetcher::create(const String& charset) +{ + return adoptRef(*new CachedScriptFetcher(charset)); +} + +CachedResourceHandle<CachedScript> CachedScriptFetcher::requestModuleScript(Document& document, const URL& sourceURL) const +{ + return requestScriptWithCache(document, sourceURL, String()); +} + +CachedResourceHandle<CachedScript> CachedScriptFetcher::requestScriptWithCache(Document& document, const URL& sourceURL, const String& crossOriginMode) const +{ + if (!document.settings().isScriptEnabled()) + return nullptr; + + ASSERT(document.contentSecurityPolicy()); + bool hasKnownNonce = document.contentSecurityPolicy()->allowScriptWithNonce(m_nonce, m_isInUserAgentShadowTree); + ResourceLoaderOptions options = CachedResourceLoader::defaultCachedResourceOptions(); + options.contentSecurityPolicyImposition = hasKnownNonce ? ContentSecurityPolicyImposition::SkipPolicyCheck : ContentSecurityPolicyImposition::DoPolicyCheck; + + CachedResourceRequest request(ResourceRequest(sourceURL), options); + request.setAsPotentiallyCrossOrigin(crossOriginMode, document); + request.upgradeInsecureRequestIfNeeded(document); + + request.setCharset(m_charset); + if (!m_initiatorName.isNull()) + request.setInitiator(m_initiatorName); + + return document.cachedResourceLoader().requestScript(WTFMove(request)); +} + +} diff --git a/Source/WebCore/bindings/js/CachedScriptFetcher.h b/Source/WebCore/bindings/js/CachedScriptFetcher.h new file mode 100644 index 000000000..a1a82ce81 --- /dev/null +++ b/Source/WebCore/bindings/js/CachedScriptFetcher.h @@ -0,0 +1,67 @@ +/* + * Copyright (C) 2017 Yusuke Suzuki <utatane.tea@gmail.com> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +#include "CachedResourceHandle.h" +#include <runtime/ScriptFetcher.h> +#include <wtf/text/WTFString.h> + +namespace WebCore { + +class CachedScript; +class Document; +class URL; + +class CachedScriptFetcher : public JSC::ScriptFetcher { +public: + virtual CachedResourceHandle<CachedScript> requestModuleScript(Document&, const URL& sourceURL) const; + + static Ref<CachedScriptFetcher> create(const String& charset); + +protected: + CachedScriptFetcher(const String& nonce, const String& charset, const AtomicString& initiatorName, bool isInUserAgentShadowTree) + : m_nonce(nonce) + , m_charset(charset) + , m_initiatorName(initiatorName) + , m_isInUserAgentShadowTree(isInUserAgentShadowTree) + { + } + + CachedScriptFetcher(const String& charset) + : m_charset(charset) + { + } + + CachedResourceHandle<CachedScript> requestScriptWithCache(Document&, const URL& sourceURL, const String& crossOriginMode) const; + +private: + String m_nonce; + String m_charset; + AtomicString m_initiatorName; + bool m_isInUserAgentShadowTree { false }; +}; + +} // namespace WebCore diff --git a/Source/WebCore/bindings/js/CachedScriptSourceProvider.h b/Source/WebCore/bindings/js/CachedScriptSourceProvider.h index b95fdc8ee..47494e7a6 100644 --- a/Source/WebCore/bindings/js/CachedScriptSourceProvider.h +++ b/Source/WebCore/bindings/js/CachedScriptSourceProvider.h @@ -23,12 +23,12 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef CachedScriptSourceProvider_h -#define CachedScriptSourceProvider_h +#pragma once #include "CachedResourceClient.h" #include "CachedResourceHandle.h" #include "CachedScript.h" +#include "CachedScriptFetcher.h" #include <parser/SourceCode.h> #include <parser/SourceProvider.h> @@ -37,31 +37,25 @@ namespace WebCore { class CachedScriptSourceProvider : public JSC::SourceProvider, public CachedResourceClient { WTF_MAKE_FAST_ALLOCATED; public: - static PassRefPtr<CachedScriptSourceProvider> create(CachedScript* cachedScript) { return adoptRef(new CachedScriptSourceProvider(cachedScript)); } + static Ref<CachedScriptSourceProvider> create(CachedScript* cachedScript, JSC::SourceProviderSourceType sourceType, Ref<CachedScriptFetcher>&& scriptFetcher) { return adoptRef(*new CachedScriptSourceProvider(cachedScript, sourceType, WTFMove(scriptFetcher))); } virtual ~CachedScriptSourceProvider() { - m_cachedScript->removeClient(this); + m_cachedScript->removeClient(*this); } - const String& source() const { return m_cachedScript->script(); } + unsigned hash() const override { return m_cachedScript->scriptHash(); } + StringView source() const override { return m_cachedScript->script(); } private: - CachedScriptSourceProvider(CachedScript* cachedScript) - : SourceProvider(cachedScript->response().url(), TextPosition::minimumPosition()) + CachedScriptSourceProvider(CachedScript* cachedScript, JSC::SourceProviderSourceType sourceType, Ref<CachedScriptFetcher>&& scriptFetcher) + : SourceProvider(JSC::SourceOrigin { cachedScript->response().url(), WTFMove(scriptFetcher) }, cachedScript->response().url(), TextPosition(), sourceType) , m_cachedScript(cachedScript) { - m_cachedScript->addClient(this); + m_cachedScript->addClient(*this); } CachedResourceHandle<CachedScript> m_cachedScript; }; -inline JSC::SourceCode makeSource(CachedScript* cachedScript) -{ - return JSC::SourceCode(CachedScriptSourceProvider::create(cachedScript)); -} - } // namespace WebCore - -#endif // CachedScriptSourceProvider_h diff --git a/Source/WebCore/bindings/js/CallbackFunction.cpp b/Source/WebCore/bindings/js/CallbackFunction.cpp deleted file mode 100644 index 145d0556b..000000000 --- a/Source/WebCore/bindings/js/CallbackFunction.cpp +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (C) 2011 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" -#include "CallbackFunction.h" - -#include "ExceptionCode.h" -#include "JSDOMBinding.h" -#include <runtime/CallData.h> - -namespace WebCore { - -bool checkFunctionOnlyCallback(JSC::ExecState* exec, JSC::JSValue value, CallbackAllowedValueFlags acceptedValues) -{ - if (value.isUndefined() && (acceptedValues & CallbackAllowUndefined)) - return false; - - if (value.isNull() && (acceptedValues & CallbackAllowNull)) - return false; - - JSC::CallData callData; - if (getCallData(value, callData) == JSC::CallTypeNone) { - setDOMException(exec, TYPE_MISMATCH_ERR); - return false; - } - - return true; -} - -} // namespace WebCore diff --git a/Source/WebCore/bindings/js/CallbackFunction.h b/Source/WebCore/bindings/js/CallbackFunction.h deleted file mode 100644 index 2562ce97a..000000000 --- a/Source/WebCore/bindings/js/CallbackFunction.h +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (C) 2011 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef CallbackFunction_h -#define CallbackFunction_h - -#include <runtime/JSObject.h> - -namespace JSC { -class ExecState; -} - -namespace WebCore { - -class JSDOMGlobalObject; - -enum CallbackAllowedValueFlag { - CallbackAllowUndefined = 1, - CallbackAllowNull = 1 << 1 -}; - -typedef unsigned CallbackAllowedValueFlags; - -bool checkFunctionOnlyCallback(JSC::ExecState*, JSC::JSValue, CallbackAllowedValueFlags); - -// Creates callback objects for callbacks marked as FunctionOnly in WebIDL. -template <typename JSCallbackType> -PassRefPtr<JSCallbackType> createFunctionOnlyCallback(JSC::ExecState* exec, JSDOMGlobalObject* globalObject, JSC::JSValue value, CallbackAllowedValueFlags acceptedValues = 0) -{ - if (checkFunctionOnlyCallback(exec, value, acceptedValues)) - return JSCallbackType::create(asObject(value), globalObject); - return 0; -} - -} // namespace WebCore - -#endif // CallbackFunction_h diff --git a/Source/WebCore/bindings/js/CommonVM.cpp b/Source/WebCore/bindings/js/CommonVM.cpp new file mode 100644 index 000000000..0187e19c9 --- /dev/null +++ b/Source/WebCore/bindings/js/CommonVM.cpp @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2016 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "CommonVM.h" + +#include "ScriptController.h" +#include "Settings.h" +#include "WebCoreJSClientData.h" +#include <heap/HeapInlines.h> +#include "heap/MachineStackMarker.h" +#include <runtime/VM.h> +#include <wtf/MainThread.h> +#include <wtf/text/AtomicString.h> + +#if PLATFORM(IOS) +#include "WebCoreThreadInternal.h" +#endif + +using namespace JSC; + +namespace WebCore { + +VM* g_commonVMOrNull; + +VM& commonVMSlow() +{ + ASSERT(isMainThread()); + ASSERT(!g_commonVMOrNull); + + ScriptController::initializeThreading(); + g_commonVMOrNull = &VM::createLeaked(LargeHeap).leakRef(); + g_commonVMOrNull->heap.acquireAccess(); // At any time, we may do things that affect the GC. +#if !PLATFORM(IOS) + g_commonVMOrNull->setExclusiveThread(std::this_thread::get_id()); +#else + g_commonVMOrNull->heap.setRunLoop(WebThreadRunLoop()); + g_commonVMOrNull->heap.machineThreads().addCurrentThread(); +#endif + + g_commonVMOrNull->setGlobalConstRedeclarationShouldThrow(Settings::globalConstRedeclarationShouldThrow()); + + JSVMClientData::initNormalWorld(g_commonVMOrNull); + + return *g_commonVMOrNull; +} + +void addImpureProperty(const AtomicString& propertyName) +{ + commonVM().addImpureProperty(propertyName); +} + +} // namespace WebCore + diff --git a/Source/WebCore/bindings/js/JSTrackEventCustom.cpp b/Source/WebCore/bindings/js/CommonVM.h index 3142cb1e5..0505168cb 100644 --- a/Source/WebCore/bindings/js/JSTrackEventCustom.cpp +++ b/Source/WebCore/bindings/js/CommonVM.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2011 Apple Inc. All rights reserved. + * Copyright (C) 2016 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -10,10 +10,10 @@ * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * - * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR @@ -23,28 +23,28 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include "config.h" +#pragma once -#if ENABLE(VIDEO_TRACK) +#include <wtf/Forward.h> -#include "JSTrackEvent.h" +namespace JSC { +class VM; +} -#include "JSTrackCustom.h" -#include "TrackBase.h" +namespace WebCore { -using namespace JSC; +WEBCORE_EXPORT extern JSC::VM* g_commonVMOrNull; -namespace WebCore { +WEBCORE_EXPORT JSC::VM& commonVMSlow(); -JSValue JSTrackEvent::track(ExecState* exec) const +inline JSC::VM& commonVM() { - TrackBase* track = impl().track(); - if (!track) - return jsNull(); - - return toJS(exec, globalObject(), track); + if (JSC::VM* result = g_commonVMOrNull) + return *result; + return commonVMSlow(); } +void addImpureProperty(const AtomicString&); + } // namespace WebCore -#endif diff --git a/Source/WebCore/bindings/js/DOMObjectHashTableMap.h b/Source/WebCore/bindings/js/DOMObjectHashTableMap.h deleted file mode 100644 index 13bf207b0..000000000 --- a/Source/WebCore/bindings/js/DOMObjectHashTableMap.h +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright (C) 1999-2001 Harri Porten (porten@kde.org) - * Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Apple Inc. All rights reserved. - * Copyright (C) 2007 Samuel Weinig <sam@webkit.org> - * Copyright (C) 2009 Google, Inc. All rights reserved. - * - * 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 DOMObjectHashTableMap_h -#define DOMObjectHashTableMap_h - -#include <runtime/Lookup.h> -#include <wtf/HashMap.h> - -namespace JSC { - class VM; -} - -namespace WebCore { - -// Map from static HashTable instances to per-GlobalData ones. -class DOMObjectHashTableMap { -public: - static DOMObjectHashTableMap& mapFor(JSC::VM&); - - ~DOMObjectHashTableMap() - { - for (HashMap<const JSC::HashTable*, JSC::HashTable>::iterator iter = m_map.begin(); iter != m_map.end(); ++iter) - iter->value.deleteTable(); - } - - const JSC::HashTable& get(const JSC::HashTable& staticTable) - { - HashMap<const JSC::HashTable*, JSC::HashTable>::iterator iter = m_map.find(&staticTable); - if (iter != m_map.end()) - return iter->value; - return m_map.set(&staticTable, staticTable.copy()).iterator->value; - } - -private: - HashMap<const JSC::HashTable*, JSC::HashTable> m_map; -}; - -} // namespace WebCore - -#endif // DOMObjectHashTableMap_h diff --git a/Source/WebCore/bindings/js/DOMRequestState.h b/Source/WebCore/bindings/js/DOMRequestState.h deleted file mode 100644 index 3453f5b53..000000000 --- a/Source/WebCore/bindings/js/DOMRequestState.h +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Copyright (C) 2012 Michael Pruett <michael@68k.org> - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef DOMRequestState_h -#define DOMRequestState_h - -#include "DOMWrapperWorld.h" -#include "Document.h" -#include "ScriptState.h" -#include "WorkerGlobalScope.h" - -#include <JavaScriptCore/APIShims.h> - -namespace WebCore { - -class ScriptExecutionContext; - -class DOMRequestState { -public: - explicit DOMRequestState(ScriptExecutionContext* scriptExecutionContext) - : m_scriptExecutionContext(scriptExecutionContext) - , m_exec(0) - { - if (m_scriptExecutionContext->isDocument()) { - Document* document = toDocument(m_scriptExecutionContext); - m_exec = execStateFromPage(mainThreadNormalWorld(), document->page()); - } else { - WorkerGlobalScope* workerGlobalScope = static_cast<WorkerGlobalScope*>(m_scriptExecutionContext); - m_exec = execStateFromWorkerGlobalScope(workerGlobalScope); - } - } - - void clear() - { - m_scriptExecutionContext = 0; - m_exec = 0; - } - - class Scope { - public: - explicit Scope(DOMRequestState& state) - : m_entryShim(state.exec()) - { - } - private: - JSC::APIEntryShim m_entryShim; - }; - - JSC::ExecState* exec() - { - return m_exec; - } - -private: - ScriptExecutionContext* m_scriptExecutionContext; - JSC::ExecState* m_exec; -}; - -} -#endif diff --git a/Source/WebCore/bindings/js/DOMWrapperWorld.cpp b/Source/WebCore/bindings/js/DOMWrapperWorld.cpp index c25efe24d..1187bc11e 100644 --- a/Source/WebCore/bindings/js/DOMWrapperWorld.cpp +++ b/Source/WebCore/bindings/js/DOMWrapperWorld.cpp @@ -21,6 +21,7 @@ #include "config.h" #include "DOMWrapperWorld.h" +#include "CommonVM.h" #include "JSDOMWindow.h" #include "ScriptController.h" #include "WebCoreJSClientData.h" @@ -30,20 +31,20 @@ using namespace JSC; namespace WebCore { -DOMWrapperWorld::DOMWrapperWorld(JSC::VM* vm, bool isNormal) +DOMWrapperWorld::DOMWrapperWorld(JSC::VM& vm, bool isNormal) : m_vm(vm) , m_isNormal(isNormal) { - VM::ClientData* clientData = m_vm->clientData; + VM::ClientData* clientData = m_vm.clientData; ASSERT(clientData); - static_cast<WebCoreJSClientData*>(clientData)->rememberWorld(*this); + static_cast<JSVMClientData*>(clientData)->rememberWorld(*this); } DOMWrapperWorld::~DOMWrapperWorld() { - VM::ClientData* clientData = m_vm->clientData; + VM::ClientData* clientData = m_vm.clientData; ASSERT(clientData); - static_cast<WebCoreJSClientData*>(clientData)->forgetWorld(*this); + static_cast<JSVMClientData*>(clientData)->forgetWorld(*this); // These items are created lazily. while (!m_scriptControllersWithWindowShells.isEmpty()) @@ -53,7 +54,6 @@ DOMWrapperWorld::~DOMWrapperWorld() void DOMWrapperWorld::clearWrappers() { m_wrappers.clear(); - m_stringCache.clear(); // These items are created lazily. while (!m_scriptControllersWithWindowShells.isEmpty()) @@ -64,13 +64,13 @@ DOMWrapperWorld& normalWorld(JSC::VM& vm) { VM::ClientData* clientData = vm.clientData; ASSERT(clientData); - return static_cast<WebCoreJSClientData*>(clientData)->normalWorld(); + return static_cast<JSVMClientData*>(clientData)->normalWorld(); } DOMWrapperWorld& mainThreadNormalWorld() { ASSERT(isMainThread()); - static DOMWrapperWorld& cachedNormalWorld = normalWorld(*JSDOMWindow::commonVM()); + static DOMWrapperWorld& cachedNormalWorld = normalWorld(commonVM()); return cachedNormalWorld; } diff --git a/Source/WebCore/bindings/js/DOMWrapperWorld.h b/Source/WebCore/bindings/js/DOMWrapperWorld.h index ac770129a..6eaec1000 100644 --- a/Source/WebCore/bindings/js/DOMWrapperWorld.h +++ b/Source/WebCore/bindings/js/DOMWrapperWorld.h @@ -19,56 +19,55 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#ifndef DOMWrapperWorld_h -#define DOMWrapperWorld_h +#pragma once #include "JSDOMGlobalObject.h" -#include <runtime/WeakGCMap.h> #include <wtf/Forward.h> namespace WebCore { -class CSSValue; -class JSDOMWrapper; +class DeprecatedCSSOMValue; class ScriptController; typedef HashMap<void*, JSC::Weak<JSC::JSObject>> DOMObjectWrapperMap; -typedef JSC::WeakGCMap<StringImpl*, JSC::JSString, PtrHash<StringImpl*>> JSStringCache; class DOMWrapperWorld : public RefCounted<DOMWrapperWorld> { public: - static PassRefPtr<DOMWrapperWorld> create(JSC::VM* vm, bool isNormal = false) + static Ref<DOMWrapperWorld> create(JSC::VM& vm, bool isNormal = false) { - return adoptRef(new DOMWrapperWorld(vm, isNormal)); + return adoptRef(*new DOMWrapperWorld(vm, isNormal)); } - ~DOMWrapperWorld(); + WEBCORE_EXPORT ~DOMWrapperWorld(); // Free as much memory held onto by this world as possible. - void clearWrappers(); + WEBCORE_EXPORT void clearWrappers(); void didCreateWindowShell(ScriptController* scriptController) { m_scriptControllersWithWindowShells.add(scriptController); } void didDestroyWindowShell(ScriptController* scriptController) { m_scriptControllersWithWindowShells.remove(scriptController); } + void setShadowRootIsAlwaysOpen() { m_shadowRootIsAlwaysOpen = true; } + bool shadowRootIsAlwaysOpen() const { return m_shadowRootIsAlwaysOpen; } + // FIXME: can we make this private? DOMObjectWrapperMap m_wrappers; - JSStringCache m_stringCache; - HashMap<CSSValue*, void*> m_cssValueRoots; + HashMap<DeprecatedCSSOMValue*, void*> m_deprecatedCSSOMValueRoots; bool isNormal() const { return m_isNormal; } - JSC::VM* vm() const { return m_vm; } + JSC::VM& vm() const { return m_vm; } protected: - DOMWrapperWorld(JSC::VM*, bool isNormal); + DOMWrapperWorld(JSC::VM&, bool isNormal); private: - JSC::VM* m_vm; + JSC::VM& m_vm; HashSet<ScriptController*> m_scriptControllersWithWindowShells; bool m_isNormal; + bool m_shadowRootIsAlwaysOpen { false }; }; DOMWrapperWorld& normalWorld(JSC::VM&); -DOMWrapperWorld& mainThreadNormalWorld(); +WEBCORE_EXPORT DOMWrapperWorld& mainThreadNormalWorld(); inline DOMWrapperWorld& debuggerWorld() { return mainThreadNormalWorld(); } inline DOMWrapperWorld& pluginWorld() { return mainThreadNormalWorld(); } @@ -77,6 +76,9 @@ inline DOMWrapperWorld& currentWorld(JSC::ExecState* exec) return JSC::jsCast<JSDOMGlobalObject*>(exec->lexicalGlobalObject())->world(); } +inline DOMWrapperWorld& worldForDOMObject(JSC::JSObject* object) +{ + return JSC::jsCast<JSDOMGlobalObject*>(object->globalObject())->world(); +} + } // namespace WebCore - -#endif // DOMWrapperWorld_h diff --git a/Source/WebCore/bindings/js/Dictionary.cpp b/Source/WebCore/bindings/js/Dictionary.cpp deleted file mode 100644 index 39ac466fa..000000000 --- a/Source/WebCore/bindings/js/Dictionary.cpp +++ /dev/null @@ -1,106 +0,0 @@ -/* - * Copyright (C) 2012 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" -#include "Dictionary.h" - -#if ENABLE(NOTIFICATIONS) -#include "JSNotification.h" -#include "Notification.h" -#endif - -using namespace JSC; - -namespace WebCore { - -Dictionary::Dictionary() - : m_dictionary(0, 0) -{ -} - -Dictionary::Dictionary(JSC::ExecState* exec, JSC::JSValue value) - : m_dictionary(exec, value.isObject() ? value.getObject() : 0) -{ -} - - -#if ENABLE(NOTIFICATIONS) -template<> -JSObject* Dictionary::asJSObject<Notification>(Notification* object) const -{ - return asObject(toJS(m_dictionary.execState(), jsCast<JSDOMGlobalObject*>(m_dictionary.execState()->lexicalGlobalObject()), object)); -} -#endif - -bool Dictionary::getOwnPropertiesAsStringHashMap(HashMap<String, String>& map) const -{ - if (!m_dictionary.isValid()) - return false; - - JSObject* object = m_dictionary.initializerObject(); - ExecState* exec = m_dictionary.execState(); - - PropertyNameArray propertyNames(exec); - JSObject::getOwnPropertyNames(object, exec, propertyNames, ExcludeDontEnumProperties); - for (PropertyNameArray::const_iterator it = propertyNames.begin(); it != propertyNames.end(); ++it) { - String stringKey = it->string(); - if (stringKey.isEmpty()) - continue; - JSValue value = object->get(exec, *it); - if (exec->hadException()) - continue; - String stringValue = value.toString(exec)->value(exec); - if (!exec->hadException()) - map.set(stringKey, stringValue); - } - - return true; -} - -bool Dictionary::getOwnPropertyNames(Vector<String>& names) const -{ - if (!m_dictionary.isValid()) - return false; - - JSObject* object = m_dictionary.initializerObject(); - ExecState* exec = m_dictionary.execState(); - - PropertyNameArray propertyNames(exec); - JSObject::getOwnPropertyNames(object, exec, propertyNames, ExcludeDontEnumProperties); - for (PropertyNameArray::const_iterator it = propertyNames.begin(); it != propertyNames.end(); ++it) { - String stringKey = it->string(); - if (!stringKey.isEmpty()) - names.append(stringKey); - } - - return true; -} - -bool Dictionary::getWithUndefinedOrNullCheck(const String& propertyName, String& value) const -{ - return m_dictionary.getWithUndefinedOrNullCheck(propertyName, value); -} - -}; diff --git a/Source/WebCore/bindings/js/Dictionary.h b/Source/WebCore/bindings/js/Dictionary.h deleted file mode 100644 index fd4bee579..000000000 --- a/Source/WebCore/bindings/js/Dictionary.h +++ /dev/null @@ -1,114 +0,0 @@ -/* - * Copyright (C) 2010 Google Inc. All rights reserved. - * Copyright (C) 2012 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef Dictionary_h -#define Dictionary_h - -#include "JSDictionary.h" -#include "JSEventListener.h" -#include "NotImplemented.h" -#include <bindings/ScriptValue.h> -#include <wtf/HashMap.h> -#include <wtf/text/CString.h> -#include <wtf/text/WTFString.h> - -namespace JSC { -class JSValue; -} - -namespace WebCore { -class EventListener; - -class Dictionary { -public: - Dictionary(); - Dictionary(JSC::ExecState*, JSC::JSValue); - - // Returns true if a value was found for the provided property. - template <typename Result> - bool get(const char* propertyName, Result&) const; - template <typename Result> - bool get(const String& propertyName, Result&) const; - - template <typename T> - PassRefPtr<EventListener> getEventListener(const char* propertyName, T* target) const; - template <typename T> - PassRefPtr<EventListener> getEventListener(const String& propertyName, T* target) const; - - bool isObject() const { return m_dictionary.isValid(); } - bool isUndefinedOrNull() const { return !m_dictionary.isValid(); } - bool getOwnPropertiesAsStringHashMap(HashMap<String, String>&) const; - bool getOwnPropertyNames(Vector<String>&) const; - bool getWithUndefinedOrNullCheck(const String& propertyName, String& value) const; - -private: - template <typename T> - JSC::JSObject* asJSObject(T*) const; - - JSDictionary m_dictionary; -}; - -template <typename Result> -bool Dictionary::get(const char* propertyName, Result& result) const -{ - if (!m_dictionary.isValid()) - return false; - - return m_dictionary.get(propertyName, result); -} - -template <typename Result> -bool Dictionary::get(const String& propertyName, Result& result) const -{ - return get(propertyName.utf8().data(), result); -} - -template <typename T> -PassRefPtr<EventListener> Dictionary::getEventListener(const char* propertyName, T* target) const -{ - if (!m_dictionary.isValid()) - return 0; - - Deprecated::ScriptValue eventListener; - if (!m_dictionary.tryGetProperty(propertyName, eventListener)) - return 0; - if (eventListener.hasNoValue()) - return 0; - if (!eventListener.isObject()) - return 0; - - return JSEventListener::create(asObject(eventListener.jsValue()), asJSObject(target), true, currentWorld(m_dictionary.execState())); -} - -template <typename T> -PassRefPtr<EventListener> Dictionary::getEventListener(const String& propertyName, T* target) const -{ - return getEventListener(propertyName.utf8().data(), target); -} - -} - -#endif // Dictionary_h diff --git a/Source/WebCore/bindings/js/GCController.cpp b/Source/WebCore/bindings/js/GCController.cpp index ba70d4a06..6f9fca67f 100644 --- a/Source/WebCore/bindings/js/GCController.cpp +++ b/Source/WebCore/bindings/js/GCController.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2007 Apple Inc. All rights reserved. + * Copyright (C) 2007, 2014, 2016 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -10,10 +10,10 @@ * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * - * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR @@ -26,11 +26,13 @@ #include "config.h" #include "GCController.h" -#include "JSDOMWindow.h" +#include "CommonVM.h" #include <runtime/VM.h> #include <runtime/JSLock.h> #include <heap/Heap.h> #include <wtf/StdLibExtras.h> +#include <wtf/FastMalloc.h> +#include <wtf/NeverDestroyed.h> using namespace JSC; @@ -38,57 +40,63 @@ namespace WebCore { static void collect(void*) { - JSLockHolder lock(JSDOMWindow::commonVM()); - JSDOMWindow::commonVM()->heap.collectAllGarbage(); + JSLockHolder lock(commonVM()); + commonVM().heap.collectAllGarbage(); } -GCController& gcController() +GCController& GCController::singleton() { - DEFINE_STATIC_LOCAL(GCController, staticGCController, ()); - return staticGCController; + static NeverDestroyed<GCController> controller; + return controller; } GCController::GCController() -#if !USE(CF) - : m_GCTimer(this, &GCController::gcTimerFired) -#endif + : m_GCTimer(*this, &GCController::gcTimerFired) { } void GCController::garbageCollectSoon() { - // We only use reportAbandonedObjectGraph on systems with CoreFoundation - // since it uses a runloop-based timer that is currently only available on - // systems with CoreFoundation. If and when the notion of a run loop is pushed - // down into WTF so that more platforms can take advantage of it, we will be - // able to use reportAbandonedObjectGraph on more platforms. -#if USE(CF) - JSLockHolder lock(JSDOMWindow::commonVM()); - JSDOMWindow::commonVM()->heap.reportAbandonedObjectGraph(); + // We only use reportAbandonedObjectGraph for systems for which there's an implementation + // of the garbage collector timers in JavaScriptCore. We wouldn't need this if JavaScriptCore + // used a timer implementation from WTF like RunLoop::Timer. +#if USE(CF) || USE(GLIB) + JSLockHolder lock(commonVM()); + commonVM().heap.reportAbandonedObjectGraph(); #else + garbageCollectOnNextRunLoop(); +#endif +} + +void GCController::garbageCollectOnNextRunLoop() +{ if (!m_GCTimer.isActive()) m_GCTimer.startOneShot(0); -#endif } -#if !USE(CF) -void GCController::gcTimerFired(Timer<GCController>*) +void GCController::gcTimerFired() { - collect(0); + collect(nullptr); } -#endif void GCController::garbageCollectNow() { - JSLockHolder lock(JSDOMWindow::commonVM()); -#if PLATFORM(IOS) - // If JavaScript was never run in this process, there's no need to call GC which will - // end up creating a VM unnecessarily. - if (!JSDOMWindow::commonVMExists()) - return; + JSLockHolder lock(commonVM()); + if (!commonVM().heap.isCurrentThreadBusy()) { + commonVM().heap.collectAllGarbage(); + WTF::releaseFastMallocFreeMemory(); + } +} + +void GCController::garbageCollectNowIfNotDoneRecently() +{ +#if USE(CF) || USE(GLIB) + JSLockHolder lock(commonVM()); + if (!commonVM().heap.isCurrentThreadBusy()) + commonVM().heap.collectAllGarbageIfNotDoneRecently(); +#else + garbageCollectSoon(); #endif - if (!JSDOMWindow::commonVM()->heap.isBusy()) - JSDOMWindow::commonVM()->heap.collectAllGarbage(); } void GCController::garbageCollectOnAlternateThreadForDebugging(bool waitUntilDone) @@ -103,37 +111,21 @@ void GCController::garbageCollectOnAlternateThreadForDebugging(bool waitUntilDon detachThread(threadID); } -void GCController::releaseExecutableMemory() +void GCController::setJavaScriptGarbageCollectorTimerEnabled(bool enable) { - JSLockHolder lock(JSDOMWindow::commonVM()); - -#if PLATFORM(IOS) - // If JavaScript was never run in this process, there's no need to call GC which will - // end up creating a VM unnecessarily. - if (!JSDOMWindow::commonVMExists()) - return; -#endif - - // We shouldn't have any javascript running on our stack when this function is called. The - // following line asserts that. - ASSERT(!JSDOMWindow::commonVM()->entryScope); - - // But be safe in release builds just in case... - if (JSDOMWindow::commonVM()->entryScope) - return; - - JSDOMWindow::commonVM()->releaseExecutableMemory(); + commonVM().heap.setGarbageCollectionTimerEnabled(enable); } -void GCController::setJavaScriptGarbageCollectorTimerEnabled(bool enable) +void GCController::deleteAllCode(DeleteAllCodeEffort effort) { - JSDOMWindow::commonVM()->heap.setGarbageCollectionTimerEnabled(enable); + JSLockHolder lock(commonVM()); + commonVM().deleteAllCode(effort); } -void GCController::discardAllCompiledCode() +void GCController::deleteAllLinkedCode(DeleteAllCodeEffort effort) { - JSLockHolder lock(JSDOMWindow::commonVM()); - JSDOMWindow::commonVM()->discardAllCode(); + JSLockHolder lock(commonVM()); + commonVM().deleteAllLinkedCode(effort); } } // namespace WebCore diff --git a/Source/WebCore/bindings/js/GCController.h b/Source/WebCore/bindings/js/GCController.h index 7db5c3058..b948c3968 100644 --- a/Source/WebCore/bindings/js/GCController.h +++ b/Source/WebCore/bindings/js/GCController.h @@ -10,10 +10,10 @@ * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * - * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR @@ -23,43 +23,36 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef GCController_h -#define GCController_h +#pragma once -#if USE(CF) -#include <wtf/FastMalloc.h> +#include <heap/DeleteAllCodeEffort.h> +#include <wtf/Forward.h> #include <wtf/Noncopyable.h> -#else #include "Timer.h" -#endif namespace WebCore { - class GCController { - WTF_MAKE_NONCOPYABLE(GCController); WTF_MAKE_FAST_ALLOCATED; - friend GCController& gcController(); +class GCController { + WTF_MAKE_NONCOPYABLE(GCController); + friend class WTF::NeverDestroyed<GCController>; +public: + WEBCORE_EXPORT static GCController& singleton(); - public: - void garbageCollectSoon(); - void garbageCollectNow(); // It's better to call garbageCollectSoon, unless you have a specific reason not to. + WEBCORE_EXPORT void garbageCollectSoon(); + WEBCORE_EXPORT void garbageCollectNow(); // It's better to call garbageCollectSoon, unless you have a specific reason not to. + WEBCORE_EXPORT void garbageCollectNowIfNotDoneRecently(); + void garbageCollectOnNextRunLoop(); - void garbageCollectOnAlternateThreadForDebugging(bool waitUntilDone); // Used for stress testing. - void releaseExecutableMemory(); - void setJavaScriptGarbageCollectorTimerEnabled(bool); - void discardAllCompiledCode(); + WEBCORE_EXPORT void garbageCollectOnAlternateThreadForDebugging(bool waitUntilDone); // Used for stress testing. + WEBCORE_EXPORT void setJavaScriptGarbageCollectorTimerEnabled(bool); + WEBCORE_EXPORT void deleteAllCode(JSC::DeleteAllCodeEffort); + WEBCORE_EXPORT void deleteAllLinkedCode(JSC::DeleteAllCodeEffort); - private: - GCController(); // Use gcController() instead +private: + GCController(); // Use singleton() instead. -#if !USE(CF) - void gcTimerFired(Timer<GCController>*); - Timer<GCController> m_GCTimer; -#endif - }; - - // Function to obtain the global GC controller. - GCController& gcController() PURE_FUNCTION; + void gcTimerFired(); + Timer m_GCTimer; +}; } // namespace WebCore - -#endif // GCController_h diff --git a/Source/WebCore/bindings/js/IDBBindingUtilities.cpp b/Source/WebCore/bindings/js/IDBBindingUtilities.cpp index 7a77db444..8fee1e297 100644 --- a/Source/WebCore/bindings/js/IDBBindingUtilities.cpp +++ b/Source/WebCore/bindings/js/IDBBindingUtilities.cpp @@ -1,6 +1,7 @@ /* * Copyright (C) 2010 Google Inc. All rights reserved. * Copyright (C) 2012 Michael Pruett <michael@68k.org> + * Copyright (C) 2014, 2015, 2016 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -27,14 +28,25 @@ #include "config.h" #if ENABLE(INDEXED_DATABASE) + #include "IDBBindingUtilities.h" -#include "DOMRequestState.h" +#include "IDBIndexInfo.h" #include "IDBKey.h" +#include "IDBKeyData.h" #include "IDBKeyPath.h" +#include "IDBValue.h" +#include "IndexKey.h" +#include "JSDOMBinding.h" +#include "JSDOMConvert.h" +#include "JSDOMStringList.h" #include "Logging.h" +#include "MessagePort.h" +#include "ScriptExecutionContext.h" +#include "SerializedScriptValue.h" #include "SharedBuffer.h" - +#include "ThreadSafeDataBuffer.h" +#include <runtime/ArrayBuffer.h> #include <runtime/DateInstance.h> #include <runtime/ObjectConstructor.h> @@ -42,18 +54,18 @@ using namespace JSC; namespace WebCore { -static bool get(ExecState* exec, JSValue object, const String& keyPathElement, JSValue& result) +static bool get(ExecState& exec, JSValue object, const String& keyPathElement, JSValue& result) { if (object.isString() && keyPathElement == "length") { - result = jsNumber(object.toString(exec)->length()); + result = jsNumber(asString(object)->length()); return true; } if (!object.isObject()) return false; - Identifier identifier(&exec->vm(), keyPathElement.utf8().data()); - if (!asObject(object)->hasProperty(exec, identifier)) + Identifier identifier = Identifier::fromString(&exec.vm(), keyPathElement); + if (!asObject(object)->hasProperty(&exec, identifier)) return false; - result = asObject(object)->get(exec, identifier); + result = asObject(object)->get(&exec, identifier); return true; } @@ -63,43 +75,64 @@ static bool canSet(JSValue object, const String& keyPathElement) return object.isObject(); } -static bool set(ExecState* exec, JSValue& object, const String& keyPathElement, JSValue jsValue) +static bool set(ExecState& exec, JSValue& object, const String& keyPathElement, JSValue jsValue) { if (!canSet(object, keyPathElement)) return false; - Identifier identifier(&exec->vm(), keyPathElement.utf8().data()); - asObject(object)->putDirect(exec->vm(), identifier, jsValue); + Identifier identifier = Identifier::fromString(&exec.vm(), keyPathElement); + asObject(object)->putDirect(exec.vm(), identifier, jsValue); return true; } -static JSValue idbKeyToJSValue(ExecState* exec, JSDOMGlobalObject* globalObject, IDBKey* key) +JSValue toJS(ExecState& state, JSGlobalObject& globalObject, IDBKey* key) { if (!key) { - // This should be undefined, not null. + // This must be undefined, not null. // Spec: http://dvcs.w3.org/hg/IndexedDB/raw-file/tip/Overview.html#idl-def-IDBKeyRange return jsUndefined(); } + VM& vm = state.vm(); + Locker<JSLock> locker(vm.apiLock()); + auto scope = DECLARE_THROW_SCOPE(vm); + switch (key->type()) { - case IDBKey::ArrayType: - { - const IDBKey::KeyArray& inArray = key->array(); - size_t size = inArray.size(); - JSArray* outArray = constructEmptyArray(exec, 0, globalObject, size); - for (size_t i = 0; i < size; ++i) { - IDBKey* arrayKey = inArray.at(i).get(); - outArray->putDirectIndex(exec, i, idbKeyToJSValue(exec, globalObject, arrayKey)); - } - return JSValue(outArray); + case KeyType::Array: { + auto& inArray = key->array(); + unsigned size = inArray.size(); + auto outArray = constructEmptyArray(&state, 0, &globalObject, size); + RETURN_IF_EXCEPTION(scope, JSValue()); + for (size_t i = 0; i < size; ++i) { + outArray->putDirectIndex(&state, i, toJS(state, globalObject, inArray.at(i).get())); + RETURN_IF_EXCEPTION(scope, JSValue()); + } + return outArray; + } + case KeyType::Binary: { + auto* data = key->binary().data(); + if (!data) { + ASSERT_NOT_REACHED(); + return jsNull(); } - case IDBKey::StringType: - return jsStringWithCache(exec, key->string()); - case IDBKey::DateType: - return jsDateOrNull(exec, key->date()); - case IDBKey::NumberType: + + auto arrayBuffer = ArrayBuffer::create(data->data(), data->size()); + Structure* structure = globalObject.arrayBufferStructure(arrayBuffer->sharingMode()); + if (!structure) + return jsNull(); + + return JSArrayBuffer::create(state.vm(), structure, WTFMove(arrayBuffer)); + } + case KeyType::String: + return jsStringWithCache(&state, key->string()); + case KeyType::Date: + // FIXME: This should probably be toJS<IDLDate>(...) as per: + // http://w3c.github.io/IndexedDB/#request-convert-a-key-to-a-value + return toJS<IDLNullable<IDLDate>>(state, key->date()); + case KeyType::Number: return jsNumber(key->number()); - case IDBKey::MinType: - case IDBKey::InvalidType: + case KeyType::Min: + case KeyType::Max: + case KeyType::Invalid: ASSERT_NOT_REACHED(); return jsUndefined(); } @@ -110,29 +143,38 @@ static JSValue idbKeyToJSValue(ExecState* exec, JSDOMGlobalObject* globalObject, static const size_t maximumDepth = 2000; -static PassRefPtr<IDBKey> createIDBKeyFromValue(ExecState* exec, JSValue value, Vector<JSArray*>& stack) +static RefPtr<IDBKey> createIDBKeyFromValue(ExecState& exec, JSValue value, Vector<JSArray*>& stack) { - if (value.isNumber() && !std::isnan(value.toNumber(exec))) - return IDBKey::createNumber(value.toNumber(exec)); + VM& vm = exec.vm(); + if (value.isNumber() && !std::isnan(value.toNumber(&exec))) + return IDBKey::createNumber(value.toNumber(&exec)); + if (value.isString()) - return IDBKey::createString(value.toString(exec)->value(exec)); - if (value.inherits(DateInstance::info()) && !std::isnan(valueToDate(exec, value))) - return IDBKey::createDate(valueToDate(exec, value)); + return IDBKey::createString(asString(value)->value(&exec)); + + if (value.inherits(vm, DateInstance::info())) { + auto dateValue = valueToDate(exec, value); + if (!std::isnan(dateValue)) + return IDBKey::createDate(dateValue); + } + if (value.isObject()) { JSObject* object = asObject(value); - if (isJSArray(object) || object->inherits(JSArray::info())) { + if (isJSArray(object) || object->inherits(vm, JSArray::info())) { JSArray* array = asArray(object); size_t length = array->length(); if (stack.contains(array)) - return 0; + return nullptr; + if (stack.size() >= maximumDepth) - return 0; + return nullptr; + stack.append(array); - IDBKey::KeyArray subkeys; + Vector<RefPtr<IDBKey>> subkeys; for (size_t i = 0; i < length; i++) { - JSValue item = array->getIndex(exec, i); + JSValue item = array->getIndex(&exec, i); RefPtr<IDBKey> subkey = createIDBKeyFromValue(exec, item, stack); if (!subkey) subkeys.append(IDBKey::createInvalid()); @@ -143,30 +185,26 @@ static PassRefPtr<IDBKey> createIDBKeyFromValue(ExecState* exec, JSValue value, stack.removeLast(); return IDBKey::createArray(subkeys); } + + if (auto* arrayBuffer = jsDynamicCast<JSArrayBuffer*>(vm, value)) + return IDBKey::createBinary(*arrayBuffer); + + if (auto* arrayBufferView = jsDynamicCast<JSArrayBufferView*>(vm, value)) + return IDBKey::createBinary(*arrayBufferView); } - return 0; + return nullptr; } -static PassRefPtr<IDBKey> createIDBKeyFromValue(ExecState* exec, JSValue value) +static Ref<IDBKey> createIDBKeyFromValue(ExecState& exec, JSValue value) { Vector<JSArray*> stack; RefPtr<IDBKey> key = createIDBKeyFromValue(exec, value, stack); if (key) - return key; + return *key; return IDBKey::createInvalid(); } -IDBKeyPath idbKeyPathFromValue(ExecState* exec, JSValue keyPathValue) -{ - IDBKeyPath keyPath; - if (isJSArray(keyPathValue)) - keyPath = IDBKeyPath(toNativeArray<String>(exec, keyPathValue)); - else - keyPath = IDBKeyPath(keyPathValue.toString(exec)->value(exec)); - return keyPath; -} - -static JSValue getNthValueOnKeyPath(ExecState* exec, JSValue rootValue, const Vector<String>& keyPathElements, size_t index) +static JSValue getNthValueOnKeyPath(ExecState& exec, JSValue rootValue, const Vector<String>& keyPathElements, size_t index) { JSValue currentValue(rootValue); ASSERT(index <= keyPathElements.size()); @@ -178,21 +216,21 @@ static JSValue getNthValueOnKeyPath(ExecState* exec, JSValue rootValue, const Ve return currentValue; } -static PassRefPtr<IDBKey> createIDBKeyFromScriptValueAndKeyPath(ExecState* exec, const Deprecated::ScriptValue& value, const String& keyPath) +static RefPtr<IDBKey> internalCreateIDBKeyFromScriptValueAndKeyPath(ExecState& exec, const JSValue& value, const String& keyPath) { Vector<String> keyPathElements; IDBKeyPathParseError error; IDBParseKeyPath(keyPath, keyPathElements, error); - ASSERT(error == IDBKeyPathParseErrorNone); + ASSERT(error == IDBKeyPathParseError::None); - JSValue jsValue = value.jsValue(); + JSValue jsValue = value; jsValue = getNthValueOnKeyPath(exec, jsValue, keyPathElements, keyPathElements.size()); if (jsValue.isUndefined()) - return 0; + return nullptr; return createIDBKeyFromValue(exec, jsValue); } -static JSValue ensureNthValueOnKeyPath(ExecState* exec, JSValue rootValue, const Vector<String>& keyPathElements, size_t index) +static JSValue ensureNthValueOnKeyPath(ExecState& exec, JSValue rootValue, const Vector<String>& keyPathElements, size_t index) { JSValue currentValue(rootValue); @@ -201,7 +239,7 @@ static JSValue ensureNthValueOnKeyPath(ExecState* exec, JSValue rootValue, const JSValue parentValue(currentValue); const String& keyPathElement = keyPathElements[i]; if (!get(exec, parentValue, keyPathElement, currentValue)) { - JSObject* object = constructEmptyObject(exec); + JSObject* object = constructEmptyObject(&exec); if (!set(exec, parentValue, keyPathElement, JSValue(object))) return jsUndefined(); currentValue = JSValue(object); @@ -211,7 +249,7 @@ static JSValue ensureNthValueOnKeyPath(ExecState* exec, JSValue rootValue, const return currentValue; } -static bool canInjectNthValueOnKeyPath(ExecState* exec, JSValue rootValue, const Vector<String>& keyPathElements, size_t index) +static bool canInjectNthValueOnKeyPath(ExecState& exec, JSValue rootValue, const Vector<String>& keyPathElements, size_t index) { if (!rootValue.isObject()) return false; @@ -228,105 +266,151 @@ static bool canInjectNthValueOnKeyPath(ExecState* exec, JSValue rootValue, const return true; } -bool injectIDBKeyIntoScriptValue(DOMRequestState* requestState, PassRefPtr<IDBKey> key, Deprecated::ScriptValue& value, const IDBKeyPath& keyPath) +bool injectIDBKeyIntoScriptValue(ExecState& exec, const IDBKeyData& keyData, JSValue value, const IDBKeyPath& keyPath) { - LOG(StorageAPI, "injectIDBKeyIntoScriptValue"); + LOG(IndexedDB, "injectIDBKeyIntoScriptValue"); - ASSERT(keyPath.type() == IDBKeyPath::StringType); + ASSERT(WTF::holds_alternative<String>(keyPath)); Vector<String> keyPathElements; IDBKeyPathParseError error; - IDBParseKeyPath(keyPath.string(), keyPathElements, error); - ASSERT(error == IDBKeyPathParseErrorNone); + IDBParseKeyPath(WTF::get<String>(keyPath), keyPathElements, error); + ASSERT(error == IDBKeyPathParseError::None); if (keyPathElements.isEmpty()) return false; - ExecState* exec = requestState->exec(); - - JSValue parent = ensureNthValueOnKeyPath(exec, value.jsValue(), keyPathElements, keyPathElements.size() - 1); + JSValue parent = ensureNthValueOnKeyPath(exec, value, keyPathElements, keyPathElements.size() - 1); if (parent.isUndefined()) return false; - if (!set(exec, parent, keyPathElements.last(), idbKeyToJSValue(exec, jsCast<JSDOMGlobalObject*>(exec->lexicalGlobalObject()), key.get()))) + auto key = keyData.maybeCreateIDBKey(); + if (!key) + return false; + + if (!set(exec, parent, keyPathElements.last(), toJS(exec, *exec.lexicalGlobalObject(), key.get()))) return false; return true; } -PassRefPtr<IDBKey> createIDBKeyFromScriptValueAndKeyPath(DOMRequestState* requestState, const Deprecated::ScriptValue& value, const IDBKeyPath& keyPath) -{ - LOG(StorageAPI, "createIDBKeyFromScriptValueAndKeyPath"); - ASSERT(!keyPath.isNull()); - ExecState* exec = requestState->exec(); - - if (keyPath.type() == IDBKeyPath::ArrayType) { - IDBKey::KeyArray result; - const Vector<String>& array = keyPath.array(); - for (size_t i = 0; i < array.size(); i++) { - RefPtr<IDBKey> key = createIDBKeyFromScriptValueAndKeyPath(exec, value, array[i]); +RefPtr<IDBKey> maybeCreateIDBKeyFromScriptValueAndKeyPath(ExecState& exec, const JSValue& value, const IDBKeyPath& keyPath) +{ + if (WTF::holds_alternative<Vector<String>>(keyPath)) { + auto& array = WTF::get<Vector<String>>(keyPath); + Vector<RefPtr<IDBKey>> result; + result.reserveInitialCapacity(array.size()); + for (auto& string : array) { + RefPtr<IDBKey> key = internalCreateIDBKeyFromScriptValueAndKeyPath(exec, value, string); if (!key) - return 0; - result.append(key); + return nullptr; + result.uncheckedAppend(WTFMove(key)); } - return IDBKey::createArray(result); + return IDBKey::createArray(WTFMove(result)); } - ASSERT(keyPath.type() == IDBKeyPath::StringType); - return createIDBKeyFromScriptValueAndKeyPath(exec, value, keyPath.string()); + return internalCreateIDBKeyFromScriptValueAndKeyPath(exec, value, WTF::get<String>(keyPath)); } -bool canInjectIDBKeyIntoScriptValue(DOMRequestState* requestState, const Deprecated::ScriptValue& scriptValue, const IDBKeyPath& keyPath) +bool canInjectIDBKeyIntoScriptValue(ExecState& exec, const JSValue& scriptValue, const IDBKeyPath& keyPath) { LOG(StorageAPI, "canInjectIDBKeyIntoScriptValue"); - ASSERT(keyPath.type() == IDBKeyPath::StringType); + ASSERT(WTF::holds_alternative<String>(keyPath)); Vector<String> keyPathElements; IDBKeyPathParseError error; - IDBParseKeyPath(keyPath.string(), keyPathElements, error); - ASSERT(error == IDBKeyPathParseErrorNone); + IDBParseKeyPath(WTF::get<String>(keyPath), keyPathElements, error); + ASSERT(error == IDBKeyPathParseError::None); if (!keyPathElements.size()) return false; - JSC::ExecState* exec = requestState->exec(); - return canInjectNthValueOnKeyPath(exec, scriptValue.jsValue(), keyPathElements, keyPathElements.size() - 1); + return canInjectNthValueOnKeyPath(exec, scriptValue, keyPathElements, keyPathElements.size() - 1); +} + +static JSValue deserializeIDBValueToJSValue(ExecState& state, JSC::JSGlobalObject& globalObject, const IDBValue& value) +{ + // FIXME: I think it's peculiar to use undefined to mean "null data" and null to mean "empty data". + // But I am not changing this at the moment because at least some callers are specifically checking isUndefined. + + if (!value.data().data()) + return jsUndefined(); + + auto& data = *value.data().data(); + if (data.isEmpty()) + return jsNull(); + + auto serializedValue = SerializedScriptValue::createFromWireBytes(Vector<uint8_t>(data)); + + state.vm().apiLock().lock(); + Vector<RefPtr<MessagePort>> messagePorts; + JSValue result = serializedValue->deserialize(state, &globalObject, messagePorts, value.blobURLs(), value.blobFilePaths(), SerializationErrorMode::NonThrowing); + state.vm().apiLock().unlock(); + + return result; } -Deprecated::ScriptValue deserializeIDBValue(DOMRequestState* requestState, PassRefPtr<SerializedScriptValue> prpValue) +JSValue deserializeIDBValueToJSValue(ExecState& state, const IDBValue& value) { - ExecState* exec = requestState->exec(); - RefPtr<SerializedScriptValue> serializedValue = prpValue; - if (serializedValue) - return SerializedScriptValue::deserialize(exec, serializedValue.get(), NonThrowing); - return Deprecated::ScriptValue(exec->vm(), jsNull()); + return deserializeIDBValueToJSValue(state, *state.lexicalGlobalObject(), value); } -Deprecated::ScriptValue deserializeIDBValueBuffer(DOMRequestState* requestState, PassRefPtr<SharedBuffer> prpBuffer) +JSC::JSValue toJS(JSC::ExecState* state, JSDOMGlobalObject* globalObject, const IDBValue& value) { - ExecState* exec = requestState->exec(); - RefPtr<SharedBuffer> buffer = prpBuffer; - if (buffer) { - // FIXME: The extra copy here can be eliminated by allowing SerializedScriptValue to take a raw const char* or const uint8_t*. - Vector<uint8_t> value; - value.append(buffer->data(), buffer->size()); - RefPtr<SerializedScriptValue> serializedValue = SerializedScriptValue::createFromWireBytes(value); - return SerializedScriptValue::deserialize(exec, serializedValue.get(), NonThrowing); - } - return Deprecated::ScriptValue(exec->vm(), jsNull()); + ASSERT(state); + return deserializeIDBValueToJSValue(*state, *globalObject, value); } -Deprecated::ScriptValue idbKeyToScriptValue(DOMRequestState* requestState, PassRefPtr<IDBKey> key) +Ref<IDBKey> scriptValueToIDBKey(ExecState& exec, const JSValue& scriptValue) { - ExecState* exec = requestState->exec(); - return Deprecated::ScriptValue(exec->vm(), idbKeyToJSValue(exec, jsCast<JSDOMGlobalObject*>(exec->lexicalGlobalObject()), key.get())); + return createIDBKeyFromValue(exec, scriptValue); } -PassRefPtr<IDBKey> scriptValueToIDBKey(DOMRequestState* requestState, const Deprecated::ScriptValue& scriptValue) +JSC::JSValue toJS(JSC::ExecState* state, JSDOMGlobalObject* globalObject, const IDBKeyData& keyData) { - ExecState* exec = requestState->exec(); - return createIDBKeyFromValue(exec, scriptValue.jsValue()); + ASSERT(state); + ASSERT(globalObject); + + return toJS(*state, *globalObject, keyData.maybeCreateIDBKey().get()); +} + +static Vector<IDBKeyData> createKeyPathArray(ExecState& exec, JSValue value, const IDBIndexInfo& info) +{ + auto visitor = WTF::makeVisitor([&](const String& string) -> Vector<IDBKeyData> { + auto idbKey = internalCreateIDBKeyFromScriptValueAndKeyPath(exec, value, string); + if (!idbKey) + return { }; + + Vector<IDBKeyData> keys; + if (info.multiEntry() && idbKey->type() == IndexedDB::Array) { + for (auto& key : idbKey->array()) + keys.append(key.get()); + } else + keys.append(idbKey.get()); + return keys; + }, [&](const Vector<String>& vector) -> Vector<IDBKeyData> { + Vector<IDBKeyData> keys; + for (auto& entry : vector) { + auto key = internalCreateIDBKeyFromScriptValueAndKeyPath(exec, value, entry); + if (!key || !key->isValid()) + return { }; + keys.append(key.get()); + } + return keys; + }); + + return WTF::visit(visitor, info.keyPath()); +} + +void generateIndexKeyForValue(ExecState& exec, const IDBIndexInfo& info, JSValue value, IndexKey& outKey) +{ + auto keyDatas = createKeyPathArray(exec, value, info); + + if (keyDatas.isEmpty()) + return; + + outKey = IndexKey(WTFMove(keyDatas)); } } // namespace WebCore diff --git a/Source/WebCore/bindings/js/IDBBindingUtilities.h b/Source/WebCore/bindings/js/IDBBindingUtilities.h index f012aef2d..c491fee7f 100644 --- a/Source/WebCore/bindings/js/IDBBindingUtilities.h +++ b/Source/WebCore/bindings/js/IDBBindingUtilities.h @@ -1,5 +1,6 @@ /* * Copyright (C) 2010 Google Inc. All rights reserved. + * Copyright (C) 2014, 2015, 2016 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -23,34 +24,41 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef IDBBindingUtilities_h -#define IDBBindingUtilities_h +#pragma once #if ENABLE(INDEXED_DATABASE) -#include "Dictionary.h" -#include <bindings/ScriptValue.h> +#include "IDBKeyPath.h" #include <wtf/Forward.h> +namespace JSC { +class ExecState; +class JSGlobalObject; +class JSValue; +} + namespace WebCore { -class DOMRequestState; +class IDBIndexInfo; class IDBKey; -class IDBKeyPath; -class SharedBuffer; +class IDBKeyData; +class IDBValue; +class IndexKey; +class JSDOMGlobalObject; + +RefPtr<IDBKey> maybeCreateIDBKeyFromScriptValueAndKeyPath(JSC::ExecState&, const JSC::JSValue&, const IDBKeyPath&); +bool canInjectIDBKeyIntoScriptValue(JSC::ExecState&, const JSC::JSValue&, const IDBKeyPath&); +bool injectIDBKeyIntoScriptValue(JSC::ExecState&, const IDBKeyData&, JSC::JSValue, const IDBKeyPath&); -IDBKeyPath idbKeyPathFromValue(JSC::ExecState*, JSC::JSValue); +void generateIndexKeyForValue(JSC::ExecState&, const IDBIndexInfo&, JSC::JSValue, IndexKey& outKey); -bool injectIDBKeyIntoScriptValue(DOMRequestState*, PassRefPtr<IDBKey>, Deprecated::ScriptValue&, const IDBKeyPath&); -PassRefPtr<IDBKey> createIDBKeyFromScriptValueAndKeyPath(DOMRequestState*, const Deprecated::ScriptValue&, const IDBKeyPath&); -bool canInjectIDBKeyIntoScriptValue(DOMRequestState*, const Deprecated::ScriptValue&, const IDBKeyPath&); -Deprecated::ScriptValue deserializeIDBValue(DOMRequestState*, PassRefPtr<SerializedScriptValue>); -Deprecated::ScriptValue deserializeIDBValueBuffer(DOMRequestState*, PassRefPtr<SharedBuffer>); -Deprecated::ScriptValue idbKeyToScriptValue(DOMRequestState*, PassRefPtr<IDBKey>); -PassRefPtr<IDBKey> scriptValueToIDBKey(DOMRequestState*, const Deprecated::ScriptValue&); +Ref<IDBKey> scriptValueToIDBKey(JSC::ExecState&, const JSC::JSValue&); + +JSC::JSValue deserializeIDBValueToJSValue(JSC::ExecState&, const IDBValue&); +JSC::JSValue toJS(JSC::ExecState*, JSDOMGlobalObject*, const IDBValue&); +JSC::JSValue toJS(JSC::ExecState&, JSC::JSGlobalObject&, IDBKey*); +JSC::JSValue toJS(JSC::ExecState*, JSDOMGlobalObject*, const IDBKeyData&); } #endif // ENABLE(INDEXED_DATABASE) - -#endif // IDBBindingUtilities_h diff --git a/Source/WebCore/bindings/js/JSAnimationTimelineCustom.cpp b/Source/WebCore/bindings/js/JSAnimationTimelineCustom.cpp new file mode 100644 index 000000000..47df4e7e7 --- /dev/null +++ b/Source/WebCore/bindings/js/JSAnimationTimelineCustom.cpp @@ -0,0 +1,56 @@ +/* + * Copyright (C) Canon Inc. 2016 + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted, provided that the following conditions + * are required to be met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Canon Inc. nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY CANON INC. AND ITS CONTRIBUTORS "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL CANON INC. AND ITS CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" + +#if ENABLE(WEB_ANIMATIONS) +#include "JSAnimationTimeline.h" + +#include "DocumentTimeline.h" +#include "JSDOMBinding.h" +#include "JSDocumentTimeline.h" + +using namespace JSC; + +namespace WebCore { + +JSValue toJSNewlyCreated(ExecState*, JSDOMGlobalObject* globalObject, Ref<AnimationTimeline>&& value) +{ + if (value->isDocumentTimeline()) + return createWrapper<DocumentTimeline>(globalObject, WTFMove(value)); + return createWrapper<AnimationTimeline>(globalObject, WTFMove(value)); +} + +JSValue toJS(ExecState* state, JSDOMGlobalObject* globalObject, AnimationTimeline& value) +{ + return wrap(state, globalObject, value); +} + +} // namespace WebCore + +#endif // ENABLE(WEB_ANIMATIONS) diff --git a/Source/WebCore/bindings/js/JSAttrCustom.cpp b/Source/WebCore/bindings/js/JSAttrCustom.cpp index 07e1689a2..d45cf6d2c 100644 --- a/Source/WebCore/bindings/js/JSAttrCustom.cpp +++ b/Source/WebCore/bindings/js/JSAttrCustom.cpp @@ -10,7 +10,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of + * 3. Neither the name of Apple Inc. ("Apple") nor the names of * its contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * @@ -29,28 +29,14 @@ #include "config.h" #include "JSAttr.h" -#include "Document.h" #include "Element.h" -#include "HTMLNames.h" - -using namespace JSC; namespace WebCore { -using namespace HTMLNames; - -void JSAttr::visitChildren(JSCell* cell, SlotVisitor& visitor) +void JSAttr::visitAdditionalChildren(JSC::SlotVisitor& visitor) { - JSAttr* thisObject = jsCast<JSAttr*>(cell); - ASSERT_GC_OBJECT_INHERITS(thisObject, info()); - COMPILE_ASSERT(StructureFlags & OverridesVisitChildren, OverridesVisitChildrenWithoutSettingFlag); - ASSERT(thisObject->structure()->typeInfo().overridesVisitChildren()); - - Base::visitChildren(thisObject, visitor); - Element* element = thisObject->impl().ownerElement(); - if (!element) - return; - visitor.addOpaqueRoot(root(element)); + if (Element* element = wrapped().ownerElement()) + visitor.addOpaqueRoot(root(element)); } } // namespace WebCore diff --git a/Source/WebCore/bindings/js/JSAudioBufferSourceNodeCustom.cpp b/Source/WebCore/bindings/js/JSAudioBufferSourceNodeCustom.cpp deleted file mode 100644 index 853576ab7..000000000 --- a/Source/WebCore/bindings/js/JSAudioBufferSourceNodeCustom.cpp +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright (C) 2010, Google Inc. All rights reserved. - * Copyright (C) 2012 Samsung Electronics - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" - -#if ENABLE(WEB_AUDIO) - -#include "JSAudioBufferSourceNode.h" - -#include "AudioBuffer.h" -#include "AudioBufferSourceNode.h" -#include "JSAudioBuffer.h" -#include <runtime/Error.h> - -using namespace JSC; - -namespace WebCore { - -void JSAudioBufferSourceNode::setBuffer(ExecState* exec, JSValue value) -{ - AudioBuffer* buffer = toAudioBuffer(value); - if (!buffer) { - exec->vm().throwException(exec, createTypeError(exec, "Value is not of type AudioBuffer")); - return; - } - - if (!impl().setBuffer(buffer)) - exec->vm().throwException(exec, createTypeError(exec, "AudioBuffer unsupported number of channels")); -} - -} // namespace WebCore - -#endif // ENABLE(WEB_AUDIO) diff --git a/Source/WebCore/bindings/js/JSAudioContextCustom.cpp b/Source/WebCore/bindings/js/JSAudioContextCustom.cpp deleted file mode 100644 index e195ddf11..000000000 --- a/Source/WebCore/bindings/js/JSAudioContextCustom.cpp +++ /dev/null @@ -1,115 +0,0 @@ -/* - * Copyright (C) 2010, Google Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" - -#if ENABLE(WEB_AUDIO) - -#include "AudioContext.h" - -#include "AudioBuffer.h" -#include "Document.h" -#include "JSAudioBuffer.h" -#include "JSAudioContext.h" -#include "JSOfflineAudioContext.h" -#include "OfflineAudioContext.h" -#include <runtime/ArrayBuffer.h> -#include <runtime/Error.h> -#include <runtime/JSArrayBuffer.h> - -using namespace JSC; - -namespace WebCore { - -EncodedJSValue JSC_HOST_CALL JSAudioContextConstructor::constructJSAudioContext(ExecState* exec) -{ - JSAudioContextConstructor* jsConstructor = jsCast<JSAudioContextConstructor*>(exec->callee()); - if (!jsConstructor) - return throwVMError(exec, createReferenceError(exec, "AudioContext constructor callee is unavailable")); - - ScriptExecutionContext* scriptExecutionContext = jsConstructor->scriptExecutionContext(); - if (!scriptExecutionContext) - return throwVMError(exec, createReferenceError(exec, "AudioContext constructor script execution context is unavailable")); - - if (!scriptExecutionContext->isDocument()) - return throwVMError(exec, createReferenceError(exec, "AudioContext constructor called in a script execution context which is not a document")); - - Document& document = toDocument(*scriptExecutionContext); - - RefPtr<AudioContext> audioContext; - - if (!exec->argumentCount()) { - // Constructor for default AudioContext which talks to audio hardware. - ExceptionCode ec = 0; - audioContext = AudioContext::create(document, ec); - if (ec) { - setDOMException(exec, ec); - return JSValue::encode(JSValue()); - } - if (!audioContext.get()) - return throwVMError(exec, createSyntaxError(exec, "audio resources unavailable for AudioContext construction")); - } else { -#if ENABLE(LEGACY_WEB_AUDIO) - // Constructor for offline (render-target) AudioContext which renders into an AudioBuffer. - // new AudioContext(in unsigned long numberOfChannels, in unsigned long numberOfFrames, in float sampleRate); - document.addConsoleMessage(JSMessageSource, WarningMessageLevel, - "Deprecated AudioContext constructor: use OfflineAudioContext instead"); - - if (exec->argumentCount() < 3) - return throwVMError(exec, createNotEnoughArgumentsError(exec)); - - int32_t numberOfChannels = exec->argument(0).toInt32(exec); - int32_t numberOfFrames = exec->argument(1).toInt32(exec); - float sampleRate = exec->argument(2).toFloat(exec); - - if (numberOfChannels <= 0 || numberOfChannels > 10) - return throwVMError(exec, createSyntaxError(exec, "Invalid number of channels")); - - if (numberOfFrames <= 0) - return throwVMError(exec, createSyntaxError(exec, "Invalid number of frames")); - - if (sampleRate <= 0) - return throwVMError(exec, createSyntaxError(exec, "Invalid sample rate")); - - - ExceptionCode ec = 0; - audioContext = OfflineAudioContext::create(document, numberOfChannels, numberOfFrames, sampleRate, ec); - if (ec) { - setDOMException(exec, ec); - return throwVMError(exec, createSyntaxError(exec, "Error creating OfflineAudioContext")); - } -#else - return throwVMError(exec, createSyntaxError(exec, "Illegal AudioContext constructor")); -#endif - } - - if (!audioContext.get()) - return throwVMError(exec, createReferenceError(exec, "Error creating AudioContext")); - - return JSValue::encode(CREATE_DOM_WRAPPER(exec, jsConstructor->globalObject(), AudioContext, audioContext.get())); -} - -} // namespace WebCore - -#endif // ENABLE(WEB_AUDIO) diff --git a/Source/WebCore/bindings/js/JSAudioTrackCustom.cpp b/Source/WebCore/bindings/js/JSAudioTrackCustom.cpp index ebbd46b5e..732341e50 100644 --- a/Source/WebCore/bindings/js/JSAudioTrackCustom.cpp +++ b/Source/WebCore/bindings/js/JSAudioTrackCustom.cpp @@ -10,10 +10,10 @@ * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * - * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR @@ -35,43 +35,38 @@ using namespace JSC; namespace WebCore { -void JSAudioTrack::visitChildren(JSCell* cell, SlotVisitor& visitor) +void JSAudioTrack::visitAdditionalChildren(SlotVisitor& visitor) { - JSAudioTrack* jsAudioTrack = jsCast<JSAudioTrack*>(cell); - ASSERT_GC_OBJECT_INHERITS(jsAudioTrack, info()); - COMPILE_ASSERT(StructureFlags & OverridesVisitChildren, OverridesVisitChildrenWithoutSettingFlag); - ASSERT(jsAudioTrack->structure()->typeInfo().overridesVisitChildren()); - Base::visitChildren(jsAudioTrack, visitor); - - AudioTrack& audioTrack = jsAudioTrack->impl(); - visitor.addOpaqueRoot(root(&audioTrack)); + visitor.addOpaqueRoot(root(&wrapped())); } -void JSAudioTrack::setKind(ExecState* exec, JSValue value) +void JSAudioTrack::setKind(ExecState& state, JSValue value) { - UNUSED_PARAM(exec); #if ENABLE(MEDIA_SOURCE) - const String& nativeValue(value.isEmpty() ? String() : value.toString(exec)->value(exec)); - if (exec->hadException()) - return; - impl().setKind(nativeValue); + VM& vm = state.vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + + auto string = value.toWTFString(&state); + RETURN_IF_EXCEPTION(scope, void()); + wrapped().setKind(string); #else + UNUSED_PARAM(state); UNUSED_PARAM(value); - return; #endif } -void JSAudioTrack::setLanguage(ExecState* exec, JSValue value) +void JSAudioTrack::setLanguage(ExecState& state, JSValue value) { - UNUSED_PARAM(exec); #if ENABLE(MEDIA_SOURCE) - const String& nativeValue(value.isEmpty() ? String() : value.toString(exec)->value(exec)); - if (exec->hadException()) - return; - impl().setLanguage(nativeValue); + VM& vm = state.vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + + auto string = value.toWTFString(&state); + RETURN_IF_EXCEPTION(scope, void()); + wrapped().setLanguage(string); #else + UNUSED_PARAM(state); UNUSED_PARAM(value); - return; #endif } diff --git a/Source/WebCore/bindings/js/JSAudioTrackListCustom.cpp b/Source/WebCore/bindings/js/JSAudioTrackListCustom.cpp index 23fd0b916..6fd1a5040 100644 --- a/Source/WebCore/bindings/js/JSAudioTrackListCustom.cpp +++ b/Source/WebCore/bindings/js/JSAudioTrackListCustom.cpp @@ -10,10 +10,10 @@ * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * - * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR @@ -26,6 +26,7 @@ #include "config.h" #if ENABLE(VIDEO_TRACK) + #include "JSAudioTrackList.h" #include "Element.h" @@ -35,17 +36,9 @@ using namespace JSC; namespace WebCore { -void JSAudioTrackList::visitChildren(JSCell* cell, SlotVisitor& visitor) +void JSAudioTrackList::visitAdditionalChildren(SlotVisitor& visitor) { - JSAudioTrackList* jsAudioTrackList = jsCast<JSAudioTrackList*>(cell); - ASSERT_GC_OBJECT_INHERITS(jsAudioTrackList, info()); - COMPILE_ASSERT(StructureFlags & OverridesVisitChildren, OverridesVisitChildrenWithoutSettingFlag); - ASSERT(jsAudioTrackList->structure()->typeInfo().overridesVisitChildren()); - Base::visitChildren(jsAudioTrackList, visitor); - - AudioTrackList& audioTrackList = jsAudioTrackList->impl(); - visitor.addOpaqueRoot(root(audioTrackList.element())); - audioTrackList.visitJSEventListeners(visitor); + visitor.addOpaqueRoot(root(wrapped().element())); } } // namespace WebCore diff --git a/Source/WebCore/bindings/js/JSBindingsAllInOne.cpp b/Source/WebCore/bindings/js/JSBindingsAllInOne.cpp new file mode 100644 index 000000000..4d379309a --- /dev/null +++ b/Source/WebCore/bindings/js/JSBindingsAllInOne.cpp @@ -0,0 +1,127 @@ +/* + * Copyright (C) 2009, 2010 Apple Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +// This all-in-one cpp file cuts down on template bloat to allow us to build our Windows release build. + +#include "CachedModuleScriptLoader.cpp" +#include "DOMWrapperWorld.cpp" +#include "GCController.cpp" +#include "JSAnimationTimelineCustom.cpp" +#include "JSAttrCustom.cpp" +#include "JSAudioTrackCustom.cpp" +#include "JSAudioTrackListCustom.cpp" +#include "JSBlobCustom.cpp" +#include "JSCSSRuleCustom.cpp" +#include "JSCSSRuleListCustom.cpp" +#include "JSCSSStyleDeclarationCustom.cpp" +#include "JSCSSValueCustom.cpp" +#include "JSCallbackData.cpp" +#include "JSCanvasRenderingContext2DCustom.cpp" +#include "JSCommandLineAPIHostCustom.cpp" +#include "JSCryptoCustom.cpp" +#include "JSCustomEventCustom.cpp" +#include "JSSQLStatementErrorCallbackCustom.cpp" +#include "JSCustomXPathNSResolver.cpp" +#include "JSDOMBindingSecurity.cpp" +#include "JSDOMBuiltinConstructorBase.cpp" +#include "JSDOMConstructorBase.cpp" +#include "JSDOMConstructorWithDocument.cpp" +#include "JSDOMExceptionHandling.cpp" +#include "JSDOMGlobalObject.cpp" +#include "JSDOMGlobalObjectTask.cpp" +#include "JSDOMPromise.cpp" +#include "JSDOMStringMapCustom.cpp" +#include "JSDOMWindowBase.cpp" +#include "JSDOMWindowCustom.cpp" +#include "JSDOMWindowProperties.cpp" +#include "JSDOMWindowShell.cpp" +#include "JSDOMWrapper.cpp" +#include "JSDOMWrapperCache.cpp" +#include "JSDocumentCustom.cpp" +#include "JSDocumentFragmentCustom.cpp" +#include "JSElementCustom.cpp" +#include "JSErrorHandler.cpp" +#include "JSEventCustom.cpp" +#include "JSEventListener.cpp" +#include "JSEventTargetCustom.cpp" +#include "JSExceptionBase.cpp" +#include "JSHTMLAllCollectionCustom.cpp" +#include "JSHTMLAppletElementCustom.cpp" +#include "JSHTMLCanvasElementCustom.cpp" +#include "JSHTMLCollectionCustom.cpp" +#include "JSHTMLDocumentCustom.cpp" +#include "JSHTMLElementCustom.cpp" +#include "JSHTMLEmbedElementCustom.cpp" +#include "JSHTMLFormControlsCollectionCustom.cpp" +#include "JSHTMLFrameSetElementCustom.cpp" +#include "JSHTMLObjectElementCustom.cpp" +#include "JSHTMLOptionsCollectionCustom.cpp" +#include "JSHTMLSelectElementCustom.cpp" +#include "JSHTMLTemplateElementCustom.cpp" +#include "JSHistoryCustom.cpp" +#include "JSImageDataCustom.cpp" +#include "JSInspectorFrontendHostCustom.cpp" +#include "JSLazyEventListener.cpp" +#include "JSLocationCustom.cpp" +#include "JSMainThreadExecState.cpp" +#include "JSMessageChannelCustom.cpp" +#include "JSMessageEventCustom.cpp" +#include "JSMessagePortCustom.cpp" +#include "JSMutationCallback.cpp" +#include "JSMutationObserverCustom.cpp" +#include "JSNodeCustom.cpp" +#include "JSNodeFilterCustom.cpp" +#include "JSNodeIteratorCustom.cpp" +#include "JSNodeListCustom.cpp" +#include "JSPluginElementFunctions.cpp" +#include "JSPopStateEventCustom.cpp" +#include "JSReadableStreamPrivateConstructors.cpp" +#include "JSSVGPathSegCustom.cpp" +#include "JSStorageCustom.cpp" +#include "JSStyleSheetCustom.cpp" +#include "JSTextCustom.cpp" +#include "JSTextTrackCueCustom.cpp" +#include "JSTextTrackCustom.cpp" +#include "JSTextTrackListCustom.cpp" +#include "JSTrackCustom.cpp" +#include "JSTreeWalkerCustom.cpp" +#include "JSVideoTrackCustom.cpp" +#include "JSVideoTrackListCustom.cpp" +#include "JSWorkerCustom.cpp" +#include "JSWorkerGlobalScopeBase.cpp" +#include "JSWorkerGlobalScopeCustom.cpp" +#include "JSXMLDocumentCustom.cpp" +#include "JSXMLHttpRequestCustom.cpp" +#include "JSXPathNSResolverCustom.cpp" +#include "JSXPathResultCustom.cpp" +#include "ScheduledAction.cpp" +#include "ScriptCachedFrameData.cpp" +#include "ScriptController.cpp" +#include "ScriptGlobalObject.cpp" +#include "ScriptModuleLoader.cpp" +#include "ScriptState.cpp" +#include "SerializedScriptValue.cpp" +#include "WebCoreTypedArrayController.cpp" +#include "WorkerScriptController.cpp" diff --git a/Source/WebCore/bindings/js/JSBiquadFilterNodeCustom.cpp b/Source/WebCore/bindings/js/JSBiquadFilterNodeCustom.cpp deleted file mode 100644 index fe342b81b..000000000 --- a/Source/WebCore/bindings/js/JSBiquadFilterNodeCustom.cpp +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright (C) 2012, Google Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" - -#if ENABLE(WEB_AUDIO) - -#include "JSBiquadFilterNode.h" - -#include "BiquadFilterNode.h" -#include "ExceptionCode.h" -#include <runtime/Error.h> - -using namespace JSC; - -namespace WebCore { - -void JSBiquadFilterNode::setType(ExecState* exec, JSValue value) -{ -#if ENABLE(LEGACY_WEB_AUDIO) - if (value.isNumber()) { - uint32_t type = value.toUInt32(exec); - if (!impl().setType(type)) - exec->vm().throwException(exec, createTypeError(exec, "Illegal BiquadFilterNode type")); - return; - } -#endif - - if (value.isString()) { - String type = value.toString(exec)->value(exec); - if (type == "lowpass" || type == "highpass" || type == "bandpass" || type == "lowshelf" || type == "highshelf" || type == "peaking" || type == "notch" || type == "allpass") { - impl().setType(type); - return; - } - } - - exec->vm().throwException(exec, createTypeError(exec, "Illegal BiquadFilterNode type")); -} - -} // namespace WebCore - -#endif // ENABLE(WEB_AUDIO) diff --git a/Source/WebCore/bindings/js/JSBlobCustom.cpp b/Source/WebCore/bindings/js/JSBlobCustom.cpp index bfcd4d192..649594010 100644 --- a/Source/WebCore/bindings/js/JSBlobCustom.cpp +++ b/Source/WebCore/bindings/js/JSBlobCustom.cpp @@ -1,5 +1,6 @@ /* * Copyright (C) 2012 Google Inc. All rights reserved. + * Copyright (C) 2016 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are @@ -31,111 +32,23 @@ #include "config.h" #include "JSBlob.h" -#include "Blob.h" -#include "ExceptionCode.h" -#include "ExceptionCodePlaceholder.h" #include "JSDOMBinding.h" -#include "JSDictionary.h" #include "JSFile.h" -#include "WebKitBlobBuilder.h" -#include <runtime/Error.h> -#include <runtime/JSArray.h> -#include <runtime/JSArrayBuffer.h> -#include <runtime/JSArrayBufferView.h> -#include <wtf/Assertions.h> using namespace JSC; namespace WebCore { -JSValue toJS(ExecState* exec, JSDOMGlobalObject* globalObject, Blob* blob) +JSValue toJSNewlyCreated(JSC::ExecState*, JSDOMGlobalObject* globalObject, Ref<Blob>&& blob) { - if (!blob) - return jsNull(); - - if (blob->isFile()) - return wrap<JSFile>(exec, globalObject, static_cast<File*>(blob)); - - return wrap<JSBlob>(exec, globalObject, blob); + if (is<File>(blob)) + return createWrapper<File>(globalObject, WTFMove(blob)); + return createWrapper<Blob>(globalObject, WTFMove(blob)); } -EncodedJSValue JSC_HOST_CALL JSBlobConstructor::constructJSBlob(ExecState* exec) +JSValue toJS(ExecState* state, JSDOMGlobalObject* globalObject, Blob& blob) { - JSBlobConstructor* jsConstructor = jsCast<JSBlobConstructor*>(exec->callee()); - ScriptExecutionContext* context = jsConstructor->scriptExecutionContext(); - if (!context) - return throwVMError(exec, createReferenceError(exec, "Blob constructor associated document is unavailable")); - - if (!exec->argumentCount()) { - RefPtr<Blob> blob = Blob::create(); - return JSValue::encode(CREATE_DOM_WRAPPER(exec, jsConstructor->globalObject(), Blob, blob.get())); - } - - unsigned blobPartsLength = 0; - JSObject* blobParts = toJSSequence(exec, exec->argument(0), blobPartsLength); - if (exec->hadException()) - return JSValue::encode(jsUndefined()); - ASSERT(blobParts); - - String type; - String endings = ASCIILiteral("transparent"); - - if (exec->argumentCount() > 1) { - JSValue blobPropertyBagValue = exec->argument(1); - - if (!blobPropertyBagValue.isObject()) - return throwVMError(exec, createTypeError(exec, "Second argument of the constructor is not of type Object")); - - // Given the above test, this will always yield an object. - JSObject* blobPropertyBagObject = blobPropertyBagValue.toObject(exec); - - // Create the dictionary wrapper from the initializer object. - JSDictionary dictionary(exec, blobPropertyBagObject); - - // Attempt to get the endings property and validate it. - bool containsEndings = dictionary.get("endings", endings); - if (exec->hadException()) - return JSValue::encode(jsUndefined()); - - if (containsEndings) { - if (endings != "transparent" && endings != "native") - return throwVMError(exec, createTypeError(exec, "The endings property must be either \"transparent\" or \"native\"")); - } - - // Attempt to get the type property. - dictionary.get("type", type); - if (exec->hadException()) - return JSValue::encode(jsUndefined()); - } - - ASSERT(endings == "transparent" || endings == "native"); - - BlobBuilder blobBuilder; - - for (unsigned i = 0; i < blobPartsLength; ++i) { - JSValue item = blobParts->get(exec, i); - if (exec->hadException()) - return JSValue::encode(jsUndefined()); - -#if ENABLE(BLOB) - if (ArrayBuffer* arrayBuffer = toArrayBuffer(item)) - blobBuilder.append(arrayBuffer); - else if (RefPtr<ArrayBufferView> arrayBufferView = toArrayBufferView(item)) - blobBuilder.append(arrayBufferView.release()); - else -#endif - if (Blob* blob = toBlob(item)) - blobBuilder.append(blob); - else { - String string = item.toString(exec)->value(exec); - if (exec->hadException()) - return JSValue::encode(jsUndefined()); - blobBuilder.append(string, endings); - } - } - - RefPtr<Blob> blob = blobBuilder.getBlob(type); - return JSValue::encode(CREATE_DOM_WRAPPER(exec, jsConstructor->globalObject(), Blob, blob.get())); + return wrap(state, globalObject, blob); } } // namespace WebCore diff --git a/Source/WebCore/bindings/js/JSCSSRuleCustom.cpp b/Source/WebCore/bindings/js/JSCSSRuleCustom.cpp index 3003a70eb..666757bf7 100644 --- a/Source/WebCore/bindings/js/JSCSSRuleCustom.cpp +++ b/Source/WebCore/bindings/js/JSCSSRuleCustom.cpp @@ -10,10 +10,10 @@ * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * - * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR @@ -26,29 +26,28 @@ #include "config.h" #include "JSCSSRule.h" -#include "CSSCharsetRule.h" #include "CSSFontFaceRule.h" #include "CSSImportRule.h" +#include "CSSKeyframeRule.h" +#include "CSSKeyframesRule.h" #include "CSSMediaRule.h" +#include "CSSNamespaceRule.h" #include "CSSPageRule.h" #include "CSSStyleRule.h" #include "CSSSupportsRule.h" -#include "JSCSSCharsetRule.h" #include "JSCSSFontFaceRule.h" -#include "JSCSSHostRule.h" #include "JSCSSImportRule.h" +#include "JSCSSKeyframeRule.h" +#include "JSCSSKeyframesRule.h" #include "JSCSSMediaRule.h" +#include "JSCSSNamespaceRule.h" #include "JSCSSPageRule.h" #include "JSCSSStyleRule.h" #include "JSCSSSupportsRule.h" #include "JSNode.h" #include "JSStyleSheetCustom.h" -#include "JSWebKitCSSKeyframeRule.h" -#include "JSWebKitCSSKeyframesRule.h" #include "JSWebKitCSSRegionRule.h" #include "JSWebKitCSSViewportRule.h" -#include "WebKitCSSKeyframeRule.h" -#include "WebKitCSSKeyframesRule.h" #include "WebKitCSSRegionRule.h" #include "WebKitCSSViewportRule.h" @@ -56,75 +55,48 @@ using namespace JSC; namespace WebCore { -void JSCSSRule::visitChildren(JSCell* cell, SlotVisitor& visitor) +void JSCSSRule::visitAdditionalChildren(SlotVisitor& visitor) { - JSCSSRule* thisObject = jsCast<JSCSSRule*>(cell); - ASSERT_GC_OBJECT_INHERITS(thisObject, info()); - COMPILE_ASSERT(StructureFlags & OverridesVisitChildren, OverridesVisitChildrenWithoutSettingFlag); - ASSERT(thisObject->structure()->typeInfo().overridesVisitChildren()); - Base::visitChildren(thisObject, visitor); - visitor.addOpaqueRoot(root(&thisObject->impl())); + visitor.addOpaqueRoot(root(&wrapped())); } -JSValue toJS(ExecState* exec, JSDOMGlobalObject* globalObject, CSSRule* rule) +JSValue toJSNewlyCreated(ExecState*, JSDOMGlobalObject* globalObject, Ref<CSSRule>&& rule) { - if (!rule) - return jsNull(); - - JSObject* wrapper = getCachedWrapper(currentWorld(exec), rule); - if (wrapper) - return wrapper; - switch (rule->type()) { - case CSSRule::STYLE_RULE: - wrapper = CREATE_DOM_WRAPPER(exec, globalObject, CSSStyleRule, rule); - break; - case CSSRule::MEDIA_RULE: - wrapper = CREATE_DOM_WRAPPER(exec, globalObject, CSSMediaRule, rule); - break; - case CSSRule::FONT_FACE_RULE: - wrapper = CREATE_DOM_WRAPPER(exec, globalObject, CSSFontFaceRule, rule); - break; - case CSSRule::PAGE_RULE: - wrapper = CREATE_DOM_WRAPPER(exec, globalObject, CSSPageRule, rule); - break; - case CSSRule::IMPORT_RULE: - wrapper = CREATE_DOM_WRAPPER(exec, globalObject, CSSImportRule, rule); - break; - case CSSRule::CHARSET_RULE: - wrapper = CREATE_DOM_WRAPPER(exec, globalObject, CSSCharsetRule, rule); - break; - case CSSRule::WEBKIT_KEYFRAME_RULE: - wrapper = CREATE_DOM_WRAPPER(exec, globalObject, WebKitCSSKeyframeRule, rule); - break; - case CSSRule::WEBKIT_KEYFRAMES_RULE: - wrapper = CREATE_DOM_WRAPPER(exec, globalObject, WebKitCSSKeyframesRule, rule); - break; -#if ENABLE(CSS3_CONDITIONAL_RULES) - case CSSRule::SUPPORTS_RULE: - wrapper = CREATE_DOM_WRAPPER(exec, globalObject, CSSSupportsRule, rule); - break; -#endif + case CSSRule::STYLE_RULE: + return createWrapper<CSSStyleRule>(globalObject, WTFMove(rule)); + case CSSRule::MEDIA_RULE: + return createWrapper<CSSMediaRule>(globalObject, WTFMove(rule)); + case CSSRule::FONT_FACE_RULE: + return createWrapper<CSSFontFaceRule>(globalObject, WTFMove(rule)); + case CSSRule::PAGE_RULE: + return createWrapper<CSSPageRule>(globalObject, WTFMove(rule)); + case CSSRule::IMPORT_RULE: + return createWrapper<CSSImportRule>(globalObject, WTFMove(rule)); + case CSSRule::NAMESPACE_RULE: + return createWrapper<CSSNamespaceRule>(globalObject, WTFMove(rule)); + case CSSRule::KEYFRAME_RULE: + return createWrapper<CSSKeyframeRule>(globalObject, WTFMove(rule)); + case CSSRule::KEYFRAMES_RULE: + return createWrapper<CSSKeyframesRule>(globalObject, WTFMove(rule)); + case CSSRule::SUPPORTS_RULE: + return createWrapper<CSSSupportsRule>(globalObject, WTFMove(rule)); #if ENABLE(CSS_DEVICE_ADAPTATION) - case CSSRule::WEBKIT_VIEWPORT_RULE: - wrapper = CREATE_DOM_WRAPPER(exec, globalObject, WebKitCSSViewportRule, rule); - break; + case CSSRule::WEBKIT_VIEWPORT_RULE: + return createWrapper<WebKitCSSViewportRule>(globalObject, WTFMove(rule)); #endif #if ENABLE(CSS_REGIONS) - case CSSRule::WEBKIT_REGION_RULE: - wrapper = CREATE_DOM_WRAPPER(exec, globalObject, WebKitCSSRegionRule, rule); - break; + case CSSRule::WEBKIT_REGION_RULE: + return createWrapper<WebKitCSSRegionRule>(globalObject, WTFMove(rule)); #endif -#if ENABLE(SHADOW_DOM) - case CSSRule::HOST_RULE: - wrapper = CREATE_DOM_WRAPPER(exec, globalObject, CSSHostRule, rule); - break; -#endif - default: - wrapper = CREATE_DOM_WRAPPER(exec, globalObject, CSSRule, rule); + default: + return createWrapper<CSSRule>(globalObject, WTFMove(rule)); } +} - return wrapper; +JSValue toJS(ExecState* state, JSDOMGlobalObject* globalObject, CSSRule& object) +{ + return wrap(state, globalObject, object); } } // namespace WebCore diff --git a/Source/WebCore/bindings/js/JSCSSRuleCustom.h b/Source/WebCore/bindings/js/JSCSSRuleCustom.h index 720565840..e99a19e02 100644 --- a/Source/WebCore/bindings/js/JSCSSRuleCustom.h +++ b/Source/WebCore/bindings/js/JSCSSRuleCustom.h @@ -10,10 +10,10 @@ * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * - * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR @@ -23,8 +23,7 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef JSCSSRuleCustom_h -#define JSCSSRuleCustom_h +#pragma once #include "CSSRule.h" #include "CSSStyleSheet.h" @@ -43,5 +42,3 @@ inline void* root(CSSRule* rule) } } // namespace WebCore - -#endif // JSCSSRuleCustom_h diff --git a/Source/WebCore/bindings/js/JSCSSRuleListCustom.cpp b/Source/WebCore/bindings/js/JSCSSRuleListCustom.cpp index d4c22a855..028444fe3 100644 --- a/Source/WebCore/bindings/js/JSCSSRuleListCustom.cpp +++ b/Source/WebCore/bindings/js/JSCSSRuleListCustom.cpp @@ -10,10 +10,10 @@ * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * - * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR @@ -38,12 +38,12 @@ namespace WebCore { bool JSCSSRuleListOwner::isReachableFromOpaqueRoots(JSC::Handle<JSC::Unknown> handle, void*, SlotVisitor& visitor) { - JSCSSRuleList* jsCSSRuleList = jsCast<JSCSSRuleList*>(handle.get().asCell()); + JSCSSRuleList* jsCSSRuleList = jsCast<JSCSSRuleList*>(handle.slot()->asCell()); if (!jsCSSRuleList->hasCustomProperties()) return false; - if (CSSStyleSheet* styleSheet = jsCSSRuleList->impl().styleSheet()) + if (CSSStyleSheet* styleSheet = jsCSSRuleList->wrapped().styleSheet()) return visitor.containsOpaqueRoot(root(styleSheet)); - if (CSSRule* cssRule = jsCSSRuleList->impl().item(0)) + if (CSSRule* cssRule = jsCSSRuleList->wrapped().item(0)) return visitor.containsOpaqueRoot(root(cssRule)); return false; } diff --git a/Source/WebCore/bindings/js/JSCSSStyleDeclarationCustom.cpp b/Source/WebCore/bindings/js/JSCSSStyleDeclarationCustom.cpp index e8190f2f1..4104a8952 100644 --- a/Source/WebCore/bindings/js/JSCSSStyleDeclarationCustom.cpp +++ b/Source/WebCore/bindings/js/JSCSSStyleDeclarationCustom.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2007, 2008, 2009, 2013 Apple Inc. All rights reserved. + * Copyright (C) 2007-2016 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -10,10 +10,10 @@ * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * - * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR @@ -26,58 +26,54 @@ #include "config.h" #include "JSCSSStyleDeclarationCustom.h" -#include "CSSParser.h" -#include "CSSPrimitiveValue.h" #include "CSSPropertyNames.h" -#include "CSSValue.h" +#include "CSSPropertyParser.h" +#include "CSSRule.h" +#include "CSSStyleDeclaration.h" +#include "CSSStyleSheet.h" +#include "CustomElementReactionQueue.h" +#include "DeprecatedCSSOMPrimitiveValue.h" #include "HashTools.h" -#include "JSCSSValue.h" +#include "JSCSSStyleDeclaration.h" +#include "JSDeprecatedCSSOMValue.h" #include "JSNode.h" +#include "JSStyleSheetCustom.h" #include "RuntimeEnabledFeatures.h" #include "Settings.h" #include "StyleProperties.h" +#include "StyledElement.h" +#include <runtime/IdentifierInlines.h> #include <runtime/StringPrototype.h> #include <wtf/ASCIICType.h> #include <wtf/text/AtomicString.h> -#include <wtf/text/StringBuilder.h> #include <wtf/text/StringConcatenate.h> -#include <wtf/text/WTFString.h> using namespace JSC; -using namespace WTF; namespace WebCore { -void JSCSSStyleDeclaration::visitChildren(JSCell* cell, SlotVisitor& visitor) +void* root(CSSStyleDeclaration* style) { - JSCSSStyleDeclaration* thisObject = jsCast<JSCSSStyleDeclaration*>(cell); - ASSERT_GC_OBJECT_INHERITS(thisObject, info()); - COMPILE_ASSERT(StructureFlags & OverridesVisitChildren, OverridesVisitChildrenWithoutSettingFlag); - ASSERT(thisObject->structure()->typeInfo().overridesVisitChildren()); - Base::visitChildren(thisObject, visitor); - visitor.addOpaqueRoot(root(&thisObject->impl())); + ASSERT(style); + if (auto* parentRule = style->parentRule()) + return root(parentRule); + if (auto* styleSheet = style->parentStyleSheet()) + return root(styleSheet); + if (auto* parentElement = style->parentElement()) + return root(parentElement); + return style; } -class CSSPropertyInfo { -public: - CSSPropertyID propertyID; - bool hadPixelOrPosPrefix; -}; - -enum PropertyNamePrefix +void JSCSSStyleDeclaration::visitAdditionalChildren(SlotVisitor& visitor) { - PropertyNamePrefixNone, - PropertyNamePrefixCSS, - PropertyNamePrefixPixel, - PropertyNamePrefixPos, -#if ENABLE(LEGACY_CSS_VENDOR_PREFIXES) - PropertyNamePrefixApple, -#endif - PropertyNamePrefixEpub, + visitor.addOpaqueRoot(root(&wrapped())); +} + +enum class PropertyNamePrefix { + None, Epub, CSS, Pixel, Pos, WebKit, #if ENABLE(LEGACY_CSS_VENDOR_PREFIXES) - PropertyNamePrefixKHTML, + Apple, KHTML, #endif - PropertyNamePrefixWebKit }; template<size_t prefixCStringLength> @@ -97,7 +93,7 @@ static inline bool matchesCSSPropertyNamePrefix(const StringImpl& propertyName, // The prefix within the property name must be followed by a capital letter. // Other characters in the prefix within the property name must be lowercase. - if (propertyName.length() < (prefixLength + 1)) + if (propertyName.length() < prefixLength + 1) return false; for (size_t i = offset; i < prefixLength; ++i) { @@ -107,10 +103,11 @@ static inline bool matchesCSSPropertyNamePrefix(const StringImpl& propertyName, if (!isASCIIUpper(propertyName[prefixLength])) return false; + return true; } -static PropertyNamePrefix getCSSPropertyNamePrefix(const StringImpl& propertyName) +static PropertyNamePrefix propertyNamePrefix(const StringImpl& propertyName) { ASSERT(propertyName.length()); @@ -120,37 +117,37 @@ static PropertyNamePrefix getCSSPropertyNamePrefix(const StringImpl& propertyNam #if ENABLE(LEGACY_CSS_VENDOR_PREFIXES) case 'a': if (RuntimeEnabledFeatures::sharedFeatures().legacyCSSVendorPrefixesEnabled() && matchesCSSPropertyNamePrefix(propertyName, "apple")) - return PropertyNamePrefixApple; + return PropertyNamePrefix::Apple; break; #endif case 'c': if (matchesCSSPropertyNamePrefix(propertyName, "css")) - return PropertyNamePrefixCSS; + return PropertyNamePrefix::CSS; break; #if ENABLE(LEGACY_CSS_VENDOR_PREFIXES) case 'k': if (RuntimeEnabledFeatures::sharedFeatures().legacyCSSVendorPrefixesEnabled() && matchesCSSPropertyNamePrefix(propertyName, "khtml")) - return PropertyNamePrefixKHTML; + return PropertyNamePrefix::KHTML; break; #endif case 'e': if (matchesCSSPropertyNamePrefix(propertyName, "epub")) - return PropertyNamePrefixEpub; + return PropertyNamePrefix::Epub; break; case 'p': if (matchesCSSPropertyNamePrefix(propertyName, "pos")) - return PropertyNamePrefixPos; + return PropertyNamePrefix::Pos; if (matchesCSSPropertyNamePrefix(propertyName, "pixel")) - return PropertyNamePrefixPixel; + return PropertyNamePrefix::Pixel; break; case 'w': if (matchesCSSPropertyNamePrefix(propertyName, "webkit")) - return PropertyNamePrefixWebKit; + return PropertyNamePrefix::WebKit; break; default: break; } - return PropertyNamePrefixNone; + return PropertyNamePrefix::None; } static inline void writeWebKitPrefix(char*& buffer) @@ -175,7 +172,12 @@ static inline void writeEpubPrefix(char*& buffer) *buffer++ = '-'; } -static CSSPropertyInfo cssPropertyIDForJSCSSPropertyName(PropertyName propertyName) +struct CSSPropertyInfo { + CSSPropertyID propertyID; + bool hadPixelOrPosPrefix; +}; + +static CSSPropertyInfo parseJavaScriptCSSPropertyName(PropertyName propertyName) { CSSPropertyInfo propertyInfo = {CSSPropertyInvalid, false}; bool hadPixelOrPosPrefix = false; @@ -188,9 +190,9 @@ static CSSPropertyInfo cssPropertyIDForJSCSSPropertyName(PropertyName propertyNa return propertyInfo; String stringForCache = String(propertyNameString); - typedef HashMap<String, CSSPropertyInfo> CSSPropertyInfoMap; - DEFINE_STATIC_LOCAL(CSSPropertyInfoMap, propertyInfoCache, ()); - propertyInfo = propertyInfoCache.get(stringForCache); + using CSSPropertyInfoMap = HashMap<String, CSSPropertyInfo>; + static NeverDestroyed<CSSPropertyInfoMap> propertyInfoCache; + propertyInfo = propertyInfoCache.get().get(stringForCache); if (propertyInfo.propertyID) return propertyInfo; @@ -203,35 +205,35 @@ static CSSPropertyInfo cssPropertyIDForJSCSSPropertyName(PropertyName propertyNa // Prefixes CSS, Pixel, Pos are ignored. // Prefixes Apple, KHTML and Webkit are transposed to "-webkit-". // The prefix "Epub" becomes "-epub-". - switch (getCSSPropertyNamePrefix(*propertyNameString)) { - case PropertyNamePrefixNone: + switch (propertyNamePrefix(*propertyNameString)) { + case PropertyNamePrefix::None: if (isASCIIUpper((*propertyNameString)[0])) return propertyInfo; break; - case PropertyNamePrefixCSS: + case PropertyNamePrefix::CSS: i += 3; break; - case PropertyNamePrefixPixel: + case PropertyNamePrefix::Pixel: i += 5; hadPixelOrPosPrefix = true; break; - case PropertyNamePrefixPos: + case PropertyNamePrefix::Pos: i += 3; hadPixelOrPosPrefix = true; break; #if ENABLE(LEGACY_CSS_VENDOR_PREFIXES) - case PropertyNamePrefixApple: - case PropertyNamePrefixKHTML: + case PropertyNamePrefix::Apple: + case PropertyNamePrefix::KHTML: ASSERT(RuntimeEnabledFeatures::sharedFeatures().legacyCSSVendorPrefixesEnabled()); writeWebKitPrefix(bufferPtr); i += 5; break; #endif - case PropertyNamePrefixEpub: + case PropertyNamePrefix::Epub: writeEpubPrefix(bufferPtr); i += 4; break; - case PropertyNamePrefixWebKit: + case PropertyNamePrefix::WebKit: writeWebKitPrefix(bufferPtr); i += 6; break; @@ -248,7 +250,7 @@ static CSSPropertyInfo cssPropertyIDForJSCSSPropertyName(PropertyName propertyNa for (; i < length; ++i) { UChar c = (*propertyNameString)[i]; - if (!c || c >= 0x7F) + if (!c || !isASCII(c)) return propertyInfo; // illegal character if (isASCIIUpper(c)) { size_t bufferSizeLeft = stringEnd - bufferPtr; @@ -256,7 +258,7 @@ static CSSPropertyInfo cssPropertyIDForJSCSSPropertyName(PropertyName propertyNa if (propertySizeLeft > bufferSizeLeft) return propertyInfo; *bufferPtr++ = '-'; - *bufferPtr++ = toASCIILower(c); + *bufferPtr++ = toASCIILowerUnchecked(c); } else *bufferPtr++ = c; ASSERT_WITH_SECURITY_IMPLICATION(bufferPtr < bufferEnd); @@ -269,142 +271,125 @@ static CSSPropertyInfo cssPropertyIDForJSCSSPropertyName(PropertyName propertyNa cssPropertyNameIOSAliasing(buffer, name, outputLength); #endif - const Property* hashTableEntry = findProperty(name, outputLength); - int propertyID = hashTableEntry ? hashTableEntry->id : 0; - if (propertyID) { + auto* hashTableEntry = findProperty(name, outputLength); + if (auto propertyID = hashTableEntry ? hashTableEntry->id : 0) { propertyInfo.hadPixelOrPosPrefix = hadPixelOrPosPrefix; propertyInfo.propertyID = static_cast<CSSPropertyID>(propertyID); - propertyInfoCache.add(stringForCache, propertyInfo); + propertyInfoCache.get().add(stringForCache, propertyInfo); } return propertyInfo; } -static inline JSValue getPropertyValueFallback(ExecState* exec, JSCSSStyleDeclaration* thisObj, unsigned index) -{ - // If the property is a shorthand property (such as "padding"), - // it can only be accessed using getPropertyValue. - return jsStringWithCache(exec, thisObj->impl().getPropertyValueInternal(static_cast<CSSPropertyID>(index))); -} - -static inline JSValue cssPropertyGetterPixelOrPosPrefix(ExecState* exec, JSCSSStyleDeclaration* thisObj, unsigned propertyID) +static inline JSValue stylePropertyGetter(ExecState& state, JSCSSStyleDeclaration& thisObject, CSSPropertyID propertyID, const RefPtr<CSSValue>& value) { - // Set up pixelOrPos boolean to handle the fact that - // pixelTop returns "CSS Top" as number value in unit pixels - // posTop returns "CSS top" as number value in unit pixels _if_ its a - // positioned element. if it is not a positioned element, return 0 - // from MSIE documentation FIXME: IMPLEMENT THAT (Dirk) - RefPtr<CSSValue> v = thisObj->impl().getPropertyCSSValueInternal(static_cast<CSSPropertyID>(propertyID)); - if (v) { - if (v->isPrimitiveValue()) - return jsNumber(static_pointer_cast<CSSPrimitiveValue>(v)->getFloatValue(CSSPrimitiveValue::CSS_PX)); - return jsStringOrNull(exec, v->cssText()); - } - - return getPropertyValueFallback(exec, thisObj, propertyID); + if (value) + return toJS<IDLNullable<IDLDOMString>>(state, value->cssText()); + // If the property is a shorthand property (such as "padding"), it can only be accessed using getPropertyValue. + return toJS<IDLDOMString>(state, thisObject.wrapped().getPropertyValueInternal(propertyID)); } -static EncodedJSValue cssPropertyGetterPixelOrPosPrefixCallback(ExecState* exec, EncodedJSValue, EncodedJSValue thisValue, unsigned propertyID) +static inline JSValue stylePropertyGetter(ExecState& state, JSCSSStyleDeclaration& thisObject, CSSPropertyID propertyID) { - JSCSSStyleDeclaration* thisObject = jsDynamicCast<JSCSSStyleDeclaration*>(JSValue::decode(thisValue)); - if (!thisObject) - return throwVMTypeError(exec); - return JSValue::encode(cssPropertyGetterPixelOrPosPrefix(exec, thisObject, propertyID)); + return stylePropertyGetter(state, thisObject, propertyID, thisObject.wrapped().getPropertyCSSValueInternal(propertyID)); } -static inline JSValue cssPropertyGetter(ExecState* exec, JSCSSStyleDeclaration* thisObj, unsigned propertyID) +static inline JSValue stylePropertyGetterPixelOrPosPrefix(ExecState& state, JSCSSStyleDeclaration& thisObject, CSSPropertyID propertyID) { - RefPtr<CSSValue> v = thisObj->impl().getPropertyCSSValueInternal(static_cast<CSSPropertyID>(propertyID)); - if (v) - return jsStringOrNull(exec, v->cssText()); - - return getPropertyValueFallback(exec, thisObj, propertyID); + // Call this version of the getter so that, e.g., pixelTop returns top as a number + // in pixel units and posTop should does the same _if_ this is a positioned element. + // FIXME: If not a positioned element, MSIE documentation says posTop should return 0; this rule is not implemented. + auto value = thisObject.wrapped().getPropertyCSSValueInternal(propertyID); + if (is<CSSPrimitiveValue>(value.get())) + return jsNumber(downcast<CSSPrimitiveValue>(*value).floatValue(CSSPrimitiveValue::CSS_PX)); + return stylePropertyGetter(state, thisObject, propertyID, value); } -static EncodedJSValue cssPropertyGetterCallback(ExecState* exec, EncodedJSValue, EncodedJSValue thisValue, unsigned propertyID) +static inline JSValue stylePropertyGetter(ExecState& state, JSCSSStyleDeclaration& thisObject, const CSSPropertyInfo& propertyInfo) { - JSCSSStyleDeclaration* thisObject = jsDynamicCast<JSCSSStyleDeclaration*>(JSValue::decode(thisValue)); - if (!thisObject) - return throwVMTypeError(exec); - return JSValue::encode(cssPropertyGetter(exec, thisObject, propertyID)); + if (propertyInfo.hadPixelOrPosPrefix) + return stylePropertyGetterPixelOrPosPrefix(state, thisObject, propertyInfo.propertyID); + return stylePropertyGetter(state, thisObject, propertyInfo.propertyID); } -bool JSCSSStyleDeclaration::getOwnPropertySlotDelegate(ExecState*, PropertyName propertyIdentifier, PropertySlot& slot) +bool JSCSSStyleDeclaration::getOwnPropertySlotDelegate(ExecState* state, PropertyName propertyName, PropertySlot& slot) { - CSSPropertyInfo propertyInfo = cssPropertyIDForJSCSSPropertyName(propertyIdentifier); + auto propertyInfo = parseJavaScriptCSSPropertyName(propertyName); if (!propertyInfo.propertyID) return false; - - if (propertyInfo.hadPixelOrPosPrefix) - slot.setCustomIndex(this, ReadOnly | DontDelete | DontEnum, static_cast<unsigned>(propertyInfo.propertyID), cssPropertyGetterPixelOrPosPrefixCallback); - else - slot.setCustomIndex(this, ReadOnly | DontDelete | DontEnum, static_cast<unsigned>(propertyInfo.propertyID), cssPropertyGetterCallback); + slot.setValue(this, DontDelete, stylePropertyGetter(*state, *this, propertyInfo)); return true; } -bool JSCSSStyleDeclaration::putDelegate(ExecState* exec, PropertyName propertyName, JSValue value, PutPropertySlot&) +bool JSCSSStyleDeclaration::putDelegate(ExecState* state, PropertyName propertyName, JSValue value, PutPropertySlot&, bool& putResult) { - CSSPropertyInfo propertyInfo = cssPropertyIDForJSCSSPropertyName(propertyName); + CustomElementReactionStack customElementReactionStack; + auto propertyInfo = parseJavaScriptCSSPropertyName(propertyName); if (!propertyInfo.propertyID) return false; - String propValue = valueToStringWithNullCheck(exec, value); + auto propertyValue = convert<IDLDOMString>(*state, value, StringConversionConfiguration::TreatNullAsEmptyString); if (propertyInfo.hadPixelOrPosPrefix) - propValue.append("px"); + propertyValue.append("px"); bool important = false; if (Settings::shouldRespectPriorityInCSSAttributeSetters()) { - size_t importantIndex = propValue.find("!important", 0, false); - if (importantIndex != notFound) { + auto importantIndex = propertyValue.findIgnoringASCIICase("!important"); + if (importantIndex && importantIndex != notFound) { important = true; - propValue = propValue.left(importantIndex - 1); + propertyValue = propertyValue.left(importantIndex - 1); } } - ExceptionCode ec = 0; - impl().setPropertyInternal(static_cast<CSSPropertyID>(propertyInfo.propertyID), propValue, important, ec); - setDOMException(exec, ec); + auto setPropertyInternalResult = wrapped().setPropertyInternal(propertyInfo.propertyID, propertyValue, important); + if (setPropertyInternalResult.hasException()) { + auto& vm = state->vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + propagateException(*state, scope, setPropertyInternalResult.releaseException()); + return true; + } + putResult = setPropertyInternalResult.releaseReturnValue(); return true; } -JSValue JSCSSStyleDeclaration::getPropertyCSSValue(ExecState* exec) +JSValue JSCSSStyleDeclaration::getPropertyCSSValue(ExecState& state) { - const String& propertyName = exec->argument(0).toString(exec)->value(exec); - if (exec->hadException()) - return jsUndefined(); + VM& vm = state.vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + + if (UNLIKELY(state.argumentCount() < 1)) + return throwException(&state, scope, createNotEnoughArgumentsError(&state)); - RefPtr<CSSValue> cssValue = impl().getPropertyCSSValue(propertyName); - if (!cssValue) + auto propertyName = state.uncheckedArgument(0).toWTFString(&state); + RETURN_IF_EXCEPTION(scope, JSValue()); + + auto value = wrapped().getPropertyCSSValue(propertyName); + if (!value) return jsNull(); - currentWorld(exec).m_cssValueRoots.add(cssValue.get(), root(&impl())); // Balanced by JSCSSValueOwner::finalize(). - return toJS(exec, globalObject(), WTF::getPtr(cssValue)); + globalObject()->world().m_deprecatedCSSOMValueRoots.add(value.get(), root(&wrapped())); // Balanced by JSDeprecatedCSSOMValueOwner::finalize(). + return toJS(&state, globalObject(), *value); } -void JSCSSStyleDeclaration::getOwnPropertyNames(JSObject* object, ExecState* exec, PropertyNameArray& propertyNames, EnumerationMode mode) +void JSCSSStyleDeclaration::getOwnPropertyNames(JSObject* object, ExecState* state, PropertyNameArray& propertyNames, EnumerationMode mode) { - JSCSSStyleDeclaration* thisObject = jsCast<JSCSSStyleDeclaration*>(object); - ASSERT_GC_OBJECT_INHERITS(thisObject, info()); - - unsigned length = thisObject->impl().length(); - for (unsigned i = 0; i < length; ++i) - propertyNames.add(Identifier::from(exec, i)); - - static Identifier* propertyIdentifiers = 0; - if (!propertyIdentifiers) { - Vector<String, numCSSProperties> jsPropertyNames; - for (int id = firstCSSProperty; id < firstCSSProperty + numCSSProperties; ++id) - jsPropertyNames.append(getJSPropertyName(static_cast<CSSPropertyID>(id))); - std::sort(jsPropertyNames.begin(), jsPropertyNames.end(), WTF::codePointCompareLessThan); - - propertyIdentifiers = new Identifier[numCSSProperties]; + static const Identifier* const cssPropertyNames = [state] { + String names[numCSSProperties]; for (int i = 0; i < numCSSProperties; ++i) - propertyIdentifiers[i] = Identifier(exec, jsPropertyNames[i].impl()); - } + names[i] = getJSPropertyName(static_cast<CSSPropertyID>(firstCSSProperty + i)); + std::sort(&names[0], &names[numCSSProperties], WTF::codePointCompareLessThan); + auto* identifiers = new Identifier[numCSSProperties]; + for (int i = 0; i < numCSSProperties; ++i) + identifiers[i] = Identifier::fromString(state, names[i]); + return identifiers; + }(); + unsigned length = jsCast<JSCSSStyleDeclaration*>(object)->wrapped().length(); + for (unsigned i = 0; i < length; ++i) + propertyNames.add(Identifier::from(state, i)); for (int i = 0; i < numCSSProperties; ++i) - propertyNames.add(propertyIdentifiers[i]); + propertyNames.add(cssPropertyNames[i]); - Base::getOwnPropertyNames(thisObject, exec, propertyNames, mode); + Base::getOwnPropertyNames(object, state, propertyNames, mode); } } // namespace WebCore diff --git a/Source/WebCore/bindings/js/JSCSSStyleDeclarationCustom.h b/Source/WebCore/bindings/js/JSCSSStyleDeclarationCustom.h index 6ed1fec30..af2a9dce5 100644 --- a/Source/WebCore/bindings/js/JSCSSStyleDeclarationCustom.h +++ b/Source/WebCore/bindings/js/JSCSSStyleDeclarationCustom.h @@ -23,26 +23,12 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef JSCSSStyleDeclarationCustom_h -#define JSCSSStyleDeclarationCustom_h - -#include "CSSRule.h" -#include "CSSStyleDeclaration.h" -#include "CSSStyleSheet.h" -#include "JSCSSStyleDeclaration.h" -#include "JSStyleSheetCustom.h" +#pragma once namespace WebCore { -inline void* root(CSSStyleDeclaration* style) -{ - if (CSSRule* parentRule = style->parentRule()) - return root(parentRule); - if (CSSStyleSheet* styleSheet = style->parentStyleSheet()) - return root(styleSheet); - return style; -} +class CSSStyleDeclaration; -} +void* root(CSSStyleDeclaration*); -#endif // JSCSSStyleDeclarationCustom_h +} // namespace WebCore diff --git a/Source/WebCore/bindings/js/JSCSSValueCustom.cpp b/Source/WebCore/bindings/js/JSCSSValueCustom.cpp index 050e4b8e3..13e23701d 100644 --- a/Source/WebCore/bindings/js/JSCSSValueCustom.cpp +++ b/Source/WebCore/bindings/js/JSCSSValueCustom.cpp @@ -10,10 +10,10 @@ * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * - * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR @@ -24,90 +24,50 @@ */ #include "config.h" -#include "JSCSSValue.h" -#include "CSSPrimitiveValue.h" -#include "CSSValueList.h" -#include "JSCSSPrimitiveValue.h" -#include "JSCSSValueList.h" +#include "DeprecatedCSSOMPrimitiveValue.h" +#include "DeprecatedCSSOMValueList.h" +#include "JSDeprecatedCSSOMPrimitiveValue.h" +#include "JSDeprecatedCSSOMValue.h" +#include "JSDeprecatedCSSOMValueList.h" #include "JSNode.h" -#include "JSWebKitCSSTransformValue.h" -#include "WebKitCSSTransformValue.h" - -#if ENABLE(CSS_FILTERS) -#include "JSWebKitCSSFilterValue.h" -#include "WebKitCSSFilterValue.h" -#endif - -#if ENABLE(SVG) -#include "JSSVGColor.h" -#include "JSSVGPaint.h" -#include "SVGColor.h" -#include "SVGPaint.h" -#endif using namespace JSC; namespace WebCore { -bool JSCSSValueOwner::isReachableFromOpaqueRoots(JSC::Handle<JSC::Unknown> handle, void* context, SlotVisitor& visitor) +bool JSDeprecatedCSSOMValueOwner::isReachableFromOpaqueRoots(JSC::Handle<JSC::Unknown> handle, void* context, SlotVisitor& visitor) { - JSCSSValue* jsCSSValue = jsCast<JSCSSValue*>(handle.get().asCell()); + JSDeprecatedCSSOMValue* jsCSSValue = jsCast<JSDeprecatedCSSOMValue*>(handle.slot()->asCell()); if (!jsCSSValue->hasCustomProperties()) return false; DOMWrapperWorld* world = static_cast<DOMWrapperWorld*>(context); - void* root = world->m_cssValueRoots.get(&jsCSSValue->impl()); + void* root = world->m_deprecatedCSSOMValueRoots.get(&jsCSSValue->wrapped()); if (!root) return false; return visitor.containsOpaqueRoot(root); } -void JSCSSValueOwner::finalize(JSC::Handle<JSC::Unknown> handle, void* context) +void JSDeprecatedCSSOMValueOwner::finalize(JSC::Handle<JSC::Unknown> handle, void* context) { - JSCSSValue* jsCSSValue = jsCast<JSCSSValue*>(handle.get().asCell()); + JSDeprecatedCSSOMValue* jsCSSValue = static_cast<JSDeprecatedCSSOMValue*>(handle.slot()->asCell()); DOMWrapperWorld& world = *static_cast<DOMWrapperWorld*>(context); - world.m_cssValueRoots.remove(&jsCSSValue->impl()); - uncacheWrapper(world, &jsCSSValue->impl(), jsCSSValue); - jsCSSValue->releaseImpl(); + world.m_deprecatedCSSOMValueRoots.remove(&jsCSSValue->wrapped()); + uncacheWrapper(world, &jsCSSValue->wrapped(), jsCSSValue); } -JSValue toJS(ExecState* exec, JSDOMGlobalObject* globalObject, CSSValue* value) +JSValue toJSNewlyCreated(ExecState*, JSDOMGlobalObject* globalObject, Ref<DeprecatedCSSOMValue>&& value) { - if (!value) - return jsNull(); - - // Scripts should only ever see cloned CSSValues, never the internal ones. - ASSERT(value->isCSSOMSafe()); - - // If we're here under erroneous circumstances, prefer returning null over a potentially insecure value. - if (!value->isCSSOMSafe()) - return jsNull(); - - JSObject* wrapper = getCachedWrapper(currentWorld(exec), value); - - if (wrapper) - return wrapper; - - if (value->isWebKitCSSTransformValue()) - wrapper = CREATE_DOM_WRAPPER(exec, globalObject, WebKitCSSTransformValue, value); -#if ENABLE(CSS_FILTERS) - else if (value->isWebKitCSSFilterValue()) - wrapper = CREATE_DOM_WRAPPER(exec, globalObject, WebKitCSSFilterValue, value); -#endif - else if (value->isValueList()) - wrapper = CREATE_DOM_WRAPPER(exec, globalObject, CSSValueList, value); -#if ENABLE(SVG) - else if (value->isSVGPaint()) - wrapper = CREATE_DOM_WRAPPER(exec, globalObject, SVGPaint, value); - else if (value->isSVGColor()) - wrapper = CREATE_DOM_WRAPPER(exec, globalObject, SVGColor, value); -#endif - else if (value->isPrimitiveValue()) - wrapper = CREATE_DOM_WRAPPER(exec, globalObject, CSSPrimitiveValue, value); - else - wrapper = CREATE_DOM_WRAPPER(exec, globalObject, CSSValue, value); + if (value->isValueList()) + return createWrapper<DeprecatedCSSOMValueList>(globalObject, WTFMove(value)); + if (value->isPrimitiveValue()) + return createWrapper<DeprecatedCSSOMPrimitiveValue>(globalObject, WTFMove(value)); + return createWrapper<DeprecatedCSSOMValue>(globalObject, WTFMove(value)); +} - return wrapper; +JSValue toJS(ExecState* state, JSDOMGlobalObject* globalObject, DeprecatedCSSOMValue& value) +{ + return wrap(state, globalObject, value); } } // namespace WebCore diff --git a/Source/WebCore/bindings/js/JSCallbackData.cpp b/Source/WebCore/bindings/js/JSCallbackData.cpp index f53d4404f..655eaf44c 100644 --- a/Source/WebCore/bindings/js/JSCallbackData.cpp +++ b/Source/WebCore/bindings/js/JSCallbackData.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2007, 2008, 2009 Apple Inc. All rights reserved. + * Copyright (C) 2007-2009, 2015 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -10,7 +10,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of + * 3. Neither the name of Apple Inc. ("Apple") nor the names of * its contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * @@ -33,60 +33,63 @@ #include "JSDOMBinding.h" #include "JSMainThreadExecState.h" #include "JSMainThreadExecStateInstrumentation.h" +#include <runtime/Exception.h> using namespace JSC; namespace WebCore { -void JSCallbackData::deleteData(void* context) +JSValue JSCallbackData::invokeCallback(JSDOMGlobalObject& globalObject, JSObject* callback, MarkedArgumentBuffer& args, CallbackType method, PropertyName functionName, NakedPtr<JSC::Exception>& returnedException) { - delete static_cast<JSCallbackData*>(context); -} - -JSValue JSCallbackData::invokeCallback(MarkedArgumentBuffer& args, bool* raisedException) -{ - ASSERT(callback()); - return invokeCallback(callback(), args, raisedException); -} + ASSERT(callback); -JSValue JSCallbackData::invokeCallback(JSValue thisValue, MarkedArgumentBuffer& args, bool* raisedException) -{ - ASSERT(callback()); - ASSERT(globalObject()); + ExecState* exec = globalObject.globalExec(); + JSValue function; + CallData callData; + CallType callType = CallType::None; - ExecState* exec = globalObject()->globalExec(); - JSValue function = callback(); + if (method != CallbackType::Object) { + function = callback; + callType = callback->methodTable()->getCallData(callback, callData); + } + if (callType == CallType::None) { + if (method == CallbackType::Function) { + returnedException = JSC::Exception::create(exec->vm(), createTypeError(exec)); + return JSValue(); + } - CallData callData; - CallType callType = callback()->methodTable()->getCallData(callback(), callData); - if (callType == CallTypeNone) { - function = callback()->get(exec, Identifier(exec, "handleEvent")); + ASSERT(!functionName.isNull()); + function = callback->get(exec, functionName); callType = getCallData(function, callData); - if (callType == CallTypeNone) + if (callType == CallType::None) { + returnedException = JSC::Exception::create(exec->vm(), createTypeError(exec)); return JSValue(); + } } - ScriptExecutionContext* context = globalObject()->scriptExecutionContext(); + ASSERT(!function.isEmpty()); + ASSERT(callType != CallType::None); + + ScriptExecutionContext* context = globalObject.scriptExecutionContext(); // We will fail to get the context if the frame has been detached. if (!context) return JSValue(); InspectorInstrumentationCookie cookie = JSMainThreadExecState::instrumentFunctionCall(context, callType, callData); + returnedException = nullptr; JSValue result = context->isDocument() - ? JSMainThreadExecState::call(exec, function, callType, callData, thisValue, args) - : JSC::call(exec, function, callType, callData, thisValue, args); + ? JSMainThreadExecState::profiledCall(exec, JSC::ProfilingReason::Other, function, callType, callData, callback, args, returnedException) + : JSC::profiledCall(exec, JSC::ProfilingReason::Other, function, callType, callData, callback, args, returnedException); - InspectorInstrumentation::didCallFunction(cookie); - - if (exec->hadException()) { - reportCurrentException(exec); - if (raisedException) - *raisedException = true; - return result; - } + InspectorInstrumentation::didCallFunction(cookie, context); return result; } +bool JSCallbackDataWeak::WeakOwner::isReachableFromOpaqueRoots(JSC::Handle<JSC::Unknown>, void* context, SlotVisitor& visitor) +{ + return visitor.containsOpaqueRoot(context); +} + } // namespace WebCore diff --git a/Source/WebCore/bindings/js/JSCallbackData.h b/Source/WebCore/bindings/js/JSCallbackData.h index ff76a9e85..3ea990e56 100644 --- a/Source/WebCore/bindings/js/JSCallbackData.h +++ b/Source/WebCore/bindings/js/JSCallbackData.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2007, 2008, 2009 Apple Inc. All rights reserved. + * Copyright (C) 2007-2009, 2015 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -10,7 +10,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of + * 3. Neither the name of Apple Inc. ("Apple") nor the names of * its contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * @@ -26,8 +26,7 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef JSCallbackData_h -#define JSCallbackData_h +#pragma once #include "JSDOMBinding.h" #include "JSDOMGlobalObject.h" @@ -45,11 +44,13 @@ namespace WebCore { class JSCallbackData { public: - static void deleteData(void*); + enum class CallbackType { Function, Object, FunctionOrObject }; - JSCallbackData(JSC::JSObject* callback, JSDOMGlobalObject* globalObject) - : m_callback(globalObject->vm(), callback) - , m_globalObject(globalObject->vm(), globalObject) + JSDOMGlobalObject* globalObject() { return m_globalObject.get(); } + +protected: + explicit JSCallbackData(JSDOMGlobalObject* globalObject) + : m_globalObject(globalObject) #ifndef NDEBUG , m_thread(currentThread()) #endif @@ -62,40 +63,74 @@ public: ASSERT(m_thread == currentThread()); #endif } - - JSC::JSObject* callback() { return m_callback.get(); } - JSDOMGlobalObject* globalObject() { return m_globalObject.get(); } - JSC::JSValue invokeCallback(JSC::MarkedArgumentBuffer&, bool* raisedException = 0); - JSC::JSValue invokeCallback(JSC::JSValue thisValue, JSC::MarkedArgumentBuffer&, bool* raisedException = 0); + static JSC::JSValue invokeCallback(JSDOMGlobalObject&, JSC::JSObject* callback, JSC::MarkedArgumentBuffer&, CallbackType, JSC::PropertyName functionName, NakedPtr<JSC::Exception>& returnedException); private: - JSC::Strong<JSC::JSObject> m_callback; - JSC::Strong<JSDOMGlobalObject> m_globalObject; + JSC::Weak<JSDOMGlobalObject> m_globalObject; #ifndef NDEBUG ThreadIdentifier m_thread; #endif }; -class DeleteCallbackDataTask : public ScriptExecutionContext::Task { +class JSCallbackDataStrong : public JSCallbackData { public: - static PassOwnPtr<DeleteCallbackDataTask> create(JSCallbackData* data) + JSCallbackDataStrong(JSC::JSObject* callback, JSDOMGlobalObject* globalObject, void*) + : JSCallbackData(globalObject) + , m_callback(globalObject->vm(), callback) { - return adoptPtr(new DeleteCallbackDataTask(data)); } - virtual void performTask(ScriptExecutionContext*) + JSC::JSObject* callback() { return m_callback.get(); } + + JSC::JSValue invokeCallback(JSC::MarkedArgumentBuffer& args, CallbackType callbackType, JSC::PropertyName functionName, NakedPtr<JSC::Exception>& returnedException) { - delete m_data; + auto* globalObject = this->globalObject(); + if (!globalObject) + return { }; + + return JSCallbackData::invokeCallback(*globalObject, callback(), args, callbackType, functionName, returnedException); } - virtual bool isCleanupTask() const { return true; } + private: + JSC::Strong<JSC::JSObject> m_callback; +}; + +class JSCallbackDataWeak : public JSCallbackData { +public: + JSCallbackDataWeak(JSC::JSObject* callback, JSDOMGlobalObject* globalObject, void* owner) + : JSCallbackData(globalObject) + , m_callback(callback, &m_weakOwner, owner) + { + } + + JSC::JSObject* callback() { return m_callback.get(); } - DeleteCallbackDataTask(JSCallbackData* data) : m_data(data) {} + JSC::JSValue invokeCallback(JSC::MarkedArgumentBuffer& args, CallbackType callbackType, JSC::PropertyName functionName, NakedPtr<JSC::Exception>& returnedException) + { + auto* globalObject = this->globalObject(); + if (!globalObject) + return { }; + + return JSCallbackData::invokeCallback(*globalObject, callback(), args, callbackType, functionName, returnedException); + } - JSCallbackData* m_data; +private: + class WeakOwner : public JSC::WeakHandleOwner { + bool isReachableFromOpaqueRoots(JSC::Handle<JSC::Unknown>, void* context, JSC::SlotVisitor&) override; + }; + WeakOwner m_weakOwner; + JSC::Weak<JSC::JSObject> m_callback; }; -} // namespace WebCore +class DeleteCallbackDataTask : public ScriptExecutionContext::Task { +public: + template <typename CallbackDataType> + explicit DeleteCallbackDataTask(CallbackDataType* data) + : ScriptExecutionContext::Task(ScriptExecutionContext::Task::CleanupTask, [data = std::unique_ptr<CallbackDataType>(data)] (ScriptExecutionContext&) { + }) + { + } +}; -#endif // JSCallbackData_h +} // namespace WebCore diff --git a/Source/WebCore/bindings/js/JSCanvasRenderingContext2DCustom.cpp b/Source/WebCore/bindings/js/JSCanvasRenderingContext2DCustom.cpp index efa539fb5..b347e3bec 100644 --- a/Source/WebCore/bindings/js/JSCanvasRenderingContext2DCustom.cpp +++ b/Source/WebCore/bindings/js/JSCanvasRenderingContext2DCustom.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2006, 2007, 2009 Apple Inc. All rights reserved. + * Copyright (C) 2006-2017 Apple Inc. All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -38,84 +38,16 @@ using namespace JSC; namespace WebCore { -static JSValue toJS(ExecState* exec, JSDOMGlobalObject* globalObject, const CanvasStyle& style) +bool JSCanvasRenderingContext2DOwner::isReachableFromOpaqueRoots(JSC::Handle<JSC::Unknown> handle, void*, SlotVisitor& visitor) { - if (style.canvasGradient()) - return toJS(exec, globalObject, style.canvasGradient()); - if (style.canvasPattern()) - return toJS(exec, globalObject, style.canvasPattern()); - return jsStringWithCache(exec, style.color()); + JSCanvasRenderingContext2D* jsCanvasRenderingContext = jsCast<JSCanvasRenderingContext2D*>(handle.slot()->asCell()); + void* root = WebCore::root(jsCanvasRenderingContext->wrapped().canvas()); + return visitor.containsOpaqueRoot(root); } -static CanvasStyle toHTMLCanvasStyle(ExecState*, JSValue value) +void JSCanvasRenderingContext2D::visitAdditionalChildren(SlotVisitor& visitor) { - if (!value.isObject()) - return CanvasStyle(); - JSObject* object = asObject(value); - if (object->inherits(JSCanvasGradient::info())) - return CanvasStyle(&jsCast<JSCanvasGradient*>(object)->impl()); - if (object->inherits(JSCanvasPattern::info())) - return CanvasStyle(&jsCast<JSCanvasPattern*>(object)->impl()); - return CanvasStyle(); -} - -JSValue JSCanvasRenderingContext2D::strokeStyle(ExecState* exec) const -{ - return toJS(exec, globalObject(), impl().strokeStyle()); -} - -void JSCanvasRenderingContext2D::setStrokeStyle(ExecState* exec, JSValue value) -{ - CanvasRenderingContext2D& context = impl(); - if (value.isString()) { - context.setStrokeColor(asString(value)->value(exec)); - return; - } - context.setStrokeStyle(toHTMLCanvasStyle(exec, value)); -} - -JSValue JSCanvasRenderingContext2D::fillStyle(ExecState* exec) const -{ - return toJS(exec, globalObject(), impl().fillStyle()); -} - -void JSCanvasRenderingContext2D::setFillStyle(ExecState* exec, JSValue value) -{ - CanvasRenderingContext2D& context = impl(); - if (value.isString()) { - context.setFillColor(asString(value)->value(exec)); - return; - } - context.setFillStyle(toHTMLCanvasStyle(exec, value)); -} - -JSValue JSCanvasRenderingContext2D::webkitLineDash(ExecState* exec) const -{ - const Vector<float>& dash = impl().getLineDash(); - - MarkedArgumentBuffer list; - Vector<float>::const_iterator end = dash.end(); - for (Vector<float>::const_iterator it = dash.begin(); it != end; ++it) - list.append(JSValue(*it)); - return constructArray(exec, 0, globalObject(), list); -} - -void JSCanvasRenderingContext2D::setWebkitLineDash(ExecState* exec, JSValue value) -{ - if (!isJSArray(value)) - return; - - Vector<float> dash; - JSArray* valueArray = asArray(value); - for (unsigned i = 0; i < valueArray->length(); ++i) { - float elem = valueArray->getIndex(exec, i).toFloat(exec); - if (elem <= 0 || !std::isfinite(elem)) - return; - - dash.append(elem); - } - - impl().setWebkitLineDash(dash); + visitor.addOpaqueRoot(root(wrapped().canvas())); } } // namespace WebCore diff --git a/Source/WebCore/bindings/js/JSCanvasRenderingContextCustom.cpp b/Source/WebCore/bindings/js/JSCanvasRenderingContextCustom.cpp deleted file mode 100644 index 0314bd205..000000000 --- a/Source/WebCore/bindings/js/JSCanvasRenderingContextCustom.cpp +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright (C) 2009 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" -#include "JSCanvasRenderingContext.h" - -#include "CanvasRenderingContext2D.h" -#include "HTMLCanvasElement.h" -#include "JSCanvasRenderingContext2D.h" -#include "JSNode.h" -#if ENABLE(WEBGL) -#include "WebGLRenderingContext.h" -#include "JSWebGLRenderingContext.h" -#endif - -using namespace JSC; - -namespace WebCore { - -void JSCanvasRenderingContext::visitChildren(JSCell* cell, SlotVisitor& visitor) -{ - JSCanvasRenderingContext* thisObject = jsCast<JSCanvasRenderingContext*>(cell); - ASSERT_GC_OBJECT_INHERITS(thisObject, info()); - COMPILE_ASSERT(StructureFlags & OverridesVisitChildren, OverridesVisitChildrenWithoutSettingFlag); - ASSERT(thisObject->structure()->typeInfo().overridesVisitChildren()); - Base::visitChildren(thisObject, visitor); - - visitor.addOpaqueRoot(root(thisObject->impl().canvas())); -} - -JSC::JSValue toJS(JSC::ExecState* exec, JSDOMGlobalObject* globalObject, CanvasRenderingContext* object) -{ - if (!object) - return jsNull(); - -#if ENABLE(WEBGL) - if (object->is3d()) - return wrap<JSWebGLRenderingContext>(exec, globalObject, static_cast<WebGLRenderingContext*>(object)); -#endif - ASSERT_WITH_SECURITY_IMPLICATION(object->is2d()); - return wrap<JSCanvasRenderingContext2D>(exec, globalObject, static_cast<CanvasRenderingContext2D*>(object)); -} - -} // namespace WebCore diff --git a/Source/WebCore/bindings/js/JSClipboardCustom.cpp b/Source/WebCore/bindings/js/JSClipboardCustom.cpp deleted file mode 100644 index 47314441c..000000000 --- a/Source/WebCore/bindings/js/JSClipboardCustom.cpp +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright (C) 2008, 2013 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of - * its contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" -#include "JSClipboard.h" - -#include "Clipboard.h" - -using namespace JSC; - -namespace WebCore { - -JSValue JSClipboard::types(ExecState* exec) const -{ - Vector<String> types = impl().types(); - return types.isEmpty() ? jsNull() : jsArray(exec, globalObject(), types); -} - -} // namespace WebCore diff --git a/Source/WebCore/bindings/js/JSCommandLineAPIHostCustom.cpp b/Source/WebCore/bindings/js/JSCommandLineAPIHostCustom.cpp index be0ae27f3..d89b305be 100644 --- a/Source/WebCore/bindings/js/JSCommandLineAPIHostCustom.cpp +++ b/Source/WebCore/bindings/js/JSCommandLineAPIHostCustom.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2007, 2008 Apple Inc. All rights reserved. + * Copyright (C) 2007-2008, 2016 Apple Inc. All rights reserved. * Copyright (C) 2008 Matt Lilek <webkit@mattlilek.com> * Copyright (C) 2010-2011 Google Inc. All rights reserved. * @@ -31,13 +31,12 @@ */ #include "config.h" - -#if ENABLE(INSPECTOR) - #include "JSCommandLineAPIHost.h" #include "CommandLineAPIHost.h" +#include "Database.h" #include "InspectorDOMAgent.h" +#include "JSDatabase.h" #include "JSEventListener.h" #include "JSNode.h" #include "JSStorage.h" @@ -45,129 +44,120 @@ #include <bindings/ScriptValue.h> #include <inspector/InspectorValues.h> #include <parser/SourceCode.h> +#include <runtime/IdentifierInlines.h> #include <runtime/JSArray.h> #include <runtime/JSFunction.h> #include <runtime/JSLock.h> #include <runtime/ObjectConstructor.h> -#if ENABLE(SQL_DATABASE) -#include "Database.h" -#include "JSDatabase.h" -#endif - using namespace JSC; namespace WebCore { -JSValue JSCommandLineAPIHost::inspectedObject(ExecState* exec) +JSValue JSCommandLineAPIHost::inspectedObject(ExecState& state) { - if (exec->argumentCount() < 1) - return jsUndefined(); - - CommandLineAPIHost::InspectableObject* object = impl().inspectedObject(exec->uncheckedArgument(0).toInt32(exec)); + CommandLineAPIHost::InspectableObject* object = wrapped().inspectedObject(); if (!object) return jsUndefined(); - JSLockHolder lock(exec); - Deprecated::ScriptValue scriptValue = object->get(exec); - if (scriptValue.hasNoValue()) - return jsUndefined(); - - return scriptValue.jsValue(); + JSLockHolder lock(&state); + auto scriptValue = object->get(state); + return scriptValue ? scriptValue : jsUndefined(); } -static JSArray* getJSListenerFunctions(ExecState* exec, Document* document, const EventListenerInfo& listenerInfo) +static JSArray* getJSListenerFunctions(ExecState& state, Document* document, const EventListenerInfo& listenerInfo) { - JSArray* result = constructEmptyArray(exec, nullptr); + VM& vm = state.vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + JSArray* result = constructEmptyArray(&state, nullptr); + RETURN_IF_EXCEPTION(scope, nullptr); size_t handlersCount = listenerInfo.eventListenerVector.size(); for (size_t i = 0, outputIndex = 0; i < handlersCount; ++i) { - const JSEventListener* jsListener = JSEventListener::cast(listenerInfo.eventListenerVector[i].listener.get()); + const JSEventListener* jsListener = JSEventListener::cast(&listenerInfo.eventListenerVector[i]->callback()); if (!jsListener) { ASSERT_NOT_REACHED(); continue; } // Hide listeners from other contexts. - if (&jsListener->isolatedWorld() != ¤tWorld(exec)) + if (&jsListener->isolatedWorld() != ¤tWorld(&state)) continue; JSObject* function = jsListener->jsFunction(document); if (!function) continue; - JSObject* listenerEntry = constructEmptyObject(exec); - listenerEntry->putDirect(exec->vm(), Identifier(exec, "listener"), function); - listenerEntry->putDirect(exec->vm(), Identifier(exec, "useCapture"), jsBoolean(listenerInfo.eventListenerVector[i].useCapture)); - result->putDirectIndex(exec, outputIndex++, JSValue(listenerEntry)); + JSObject* listenerEntry = constructEmptyObject(&state); + listenerEntry->putDirect(vm, Identifier::fromString(&state, "listener"), function); + listenerEntry->putDirect(vm, Identifier::fromString(&state, "useCapture"), jsBoolean(listenerInfo.eventListenerVector[i]->useCapture())); + result->putDirectIndex(&state, outputIndex++, JSValue(listenerEntry)); + RETURN_IF_EXCEPTION(scope, nullptr); } return result; } -JSValue JSCommandLineAPIHost::getEventListeners(ExecState* exec) +JSValue JSCommandLineAPIHost::getEventListeners(ExecState& state) { - if (exec->argumentCount() < 1) + if (state.argumentCount() < 1) return jsUndefined(); - JSValue value = exec->uncheckedArgument(0); + VM& vm = state.vm(); + JSValue value = state.uncheckedArgument(0); if (!value.isObject() || value.isNull()) return jsUndefined(); - Node* node = toNode(value); + Node* node = JSNode::toWrapped(vm, value); if (!node) return jsUndefined(); Vector<EventListenerInfo> listenersArray; - impl().getEventListenersImpl(node, listenersArray); + wrapped().getEventListenersImpl(node, listenersArray); - JSObject* result = constructEmptyObject(exec); + JSObject* result = constructEmptyObject(&state); for (size_t i = 0; i < listenersArray.size(); ++i) { - JSArray* listeners = getJSListenerFunctions(exec, &node->document(), listenersArray[i]); + JSArray* listeners = getJSListenerFunctions(state, &node->document(), listenersArray[i]); if (!listeners->length()) continue; AtomicString eventType = listenersArray[i].eventType; - result->putDirect(exec->vm(), Identifier(exec, eventType.impl()), JSValue(listeners)); + result->putDirect(state.vm(), Identifier::fromString(&state, eventType.impl()), JSValue(listeners)); } return result; } -JSValue JSCommandLineAPIHost::inspect(ExecState* exec) +JSValue JSCommandLineAPIHost::inspect(ExecState& state) { - if (exec->argumentCount() >= 2) { - Deprecated::ScriptValue object(exec->vm(), exec->uncheckedArgument(0)); - Deprecated::ScriptValue hints(exec->vm(), exec->uncheckedArgument(1)); - impl().inspectImpl(object.toInspectorValue(exec), hints.toInspectorValue(exec)); - } - + if (state.argumentCount() < 2) + return jsUndefined(); + wrapped().inspectImpl(Inspector::toInspectorValue(state, state.uncheckedArgument(0)), + Inspector::toInspectorValue(state, state.uncheckedArgument(1))); return jsUndefined(); } -JSValue JSCommandLineAPIHost::databaseId(ExecState* exec) +JSValue JSCommandLineAPIHost::databaseId(ExecState& state) { - if (exec->argumentCount() < 1) + if (state.argumentCount() < 1) return jsUndefined(); -#if ENABLE(SQL_DATABASE) - Database* database = toDatabase(exec->uncheckedArgument(0)); + VM& vm = state.vm(); + Database* database = JSDatabase::toWrapped(vm, state.uncheckedArgument(0)); if (database) - return jsStringWithCache(exec, impl().databaseIdImpl(database)); -#endif + return jsStringWithCache(&state, wrapped().databaseIdImpl(database)); return jsUndefined(); } -JSValue JSCommandLineAPIHost::storageId(ExecState* exec) +JSValue JSCommandLineAPIHost::storageId(ExecState& state) { - if (exec->argumentCount() < 1) + if (state.argumentCount() < 1) return jsUndefined(); - Storage* storage = toStorage(exec->uncheckedArgument(0)); + VM& vm = state.vm(); + Storage* storage = JSStorage::toWrapped(vm, state.uncheckedArgument(0)); if (storage) - return jsStringWithCache(exec, impl().storageIdImpl(storage)); + return jsStringWithCache(&state, wrapped().storageIdImpl(storage)); return jsUndefined(); } } // namespace WebCore - -#endif // ENABLE(INSPECTOR) diff --git a/Source/WebCore/bindings/js/JSCryptoAlgorithmBuilder.cpp b/Source/WebCore/bindings/js/JSCryptoAlgorithmBuilder.cpp new file mode 100644 index 000000000..d99c27abd --- /dev/null +++ b/Source/WebCore/bindings/js/JSCryptoAlgorithmBuilder.cpp @@ -0,0 +1,82 @@ +/* + * Copyright (C) 2013 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "JSCryptoAlgorithmBuilder.h" + +#if ENABLE(SUBTLE_CRYPTO) + +#include <runtime/JSCInlines.h> +#include <runtime/ObjectConstructor.h> +#include <runtime/TypedArrays.h> +#include <runtime/TypedArrayInlines.h> +#include <runtime/VMEntryScope.h> + +using namespace JSC; + +namespace WebCore { + +JSCryptoAlgorithmBuilder::JSCryptoAlgorithmBuilder(ExecState* exec) + : m_exec(exec) + , m_dictionary(constructEmptyObject(exec)) +{ +} + +JSCryptoAlgorithmBuilder::~JSCryptoAlgorithmBuilder() +{ +} + +void JSCryptoAlgorithmBuilder::add(const char* key, unsigned value) +{ + VM& vm = m_exec->vm(); + Identifier identifier = Identifier::fromString(&vm, key); + m_dictionary->putDirect(vm, identifier, jsNumber(value)); +} + +void JSCryptoAlgorithmBuilder::add(const char* key, const String& value) +{ + VM& vm = m_exec->vm(); + Identifier identifier = Identifier::fromString(&vm, key); + m_dictionary->putDirect(vm, identifier, jsString(m_exec, value)); +} + +void JSCryptoAlgorithmBuilder::add(const char* key, const Vector<uint8_t>& buffer) +{ + VM& vm = m_exec->vm(); + Identifier identifier = Identifier::fromString(&vm, key); + RefPtr<Uint8Array> arrayView = Uint8Array::create(buffer.data(), buffer.size()); + m_dictionary->putDirect(vm, identifier, arrayView->wrap(m_exec, vm.entryScope->globalObject())); +} + +void JSCryptoAlgorithmBuilder::add(const char* key, const JSCryptoAlgorithmBuilder& nestedBuilder) +{ + VM& vm = m_exec->vm(); + Identifier identifier = Identifier::fromString(&vm, key); + m_dictionary->putDirect(vm, identifier, nestedBuilder.result()); +} + +} // namespace WebCore + +#endif // ENABLE(SUBTLE_CRYPTO) diff --git a/Source/WebCore/bindings/js/JSCryptoAlgorithmBuilder.h b/Source/WebCore/bindings/js/JSCryptoAlgorithmBuilder.h new file mode 100644 index 000000000..ce696aef2 --- /dev/null +++ b/Source/WebCore/bindings/js/JSCryptoAlgorithmBuilder.h @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2013 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +#if ENABLE(SUBTLE_CRYPTO) + +#include <wtf/Forward.h> +#include <wtf/Noncopyable.h> +#include <wtf/Vector.h> +#include <wtf/text/WTFString.h> + +namespace JSC { +class ExecState; +class JSObject; +} + +namespace WebCore { + +class JSCryptoAlgorithmBuilder { + WTF_MAKE_NONCOPYABLE(JSCryptoAlgorithmBuilder); +public: + JSCryptoAlgorithmBuilder(JSC::ExecState*); + virtual ~JSCryptoAlgorithmBuilder(); + + JSC::JSObject* result() const { return m_dictionary; } + + void add(const char*, unsigned); + void add(const char*, const String&); + void add(const char*, const Vector<uint8_t>&); + void add(const char*, const JSCryptoAlgorithmBuilder&); + +private: + JSC::ExecState* m_exec; + JSC::JSObject* m_dictionary; +}; + +} // namespace WebCore + +#endif // ENABLE(SUBTLE_CRYPTO) diff --git a/Source/WebCore/bindings/js/JSCryptoAlgorithmDictionary.cpp b/Source/WebCore/bindings/js/JSCryptoAlgorithmDictionary.cpp new file mode 100644 index 000000000..10e1230ed --- /dev/null +++ b/Source/WebCore/bindings/js/JSCryptoAlgorithmDictionary.cpp @@ -0,0 +1,668 @@ +/* + * Copyright (C) 2013, 2016 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "JSCryptoAlgorithmDictionary.h" + +#if ENABLE(SUBTLE_CRYPTO) + +#include "CryptoAlgorithmAesCbcParamsDeprecated.h" +#include "CryptoAlgorithmAesKeyGenParamsDeprecated.h" +#include "CryptoAlgorithmHmacKeyParamsDeprecated.h" +#include "CryptoAlgorithmHmacParamsDeprecated.h" +#include "CryptoAlgorithmParameters.h" +#include "CryptoAlgorithmRegistry.h" +#include "CryptoAlgorithmRsaKeyGenParamsDeprecated.h" +#include "CryptoAlgorithmRsaKeyParamsWithHashDeprecated.h" +#include "CryptoAlgorithmRsaOaepParamsDeprecated.h" +#include "CryptoAlgorithmRsaSsaParamsDeprecated.h" +#include "ExceptionCode.h" +#include "JSCryptoOperationData.h" +#include "JSDOMBinding.h" +#include "JSDOMConvert.h" + +using namespace JSC; + +namespace WebCore { + +static inline JSValue getProperty(ExecState& state, JSObject* object, const char* name) +{ + return object->get(&state, Identifier::fromString(&state, name)); +} + +CryptoAlgorithmIdentifier JSCryptoAlgorithmDictionary::parseAlgorithmIdentifier(ExecState& state, ThrowScope& scope, JSValue value) +{ + // typedef (Algorithm or DOMString) AlgorithmIdentifier; + + String algorithmName; + VM& vm = state.vm(); + + if (value.isString()) { + algorithmName = asString(value)->value(&state); + RETURN_IF_EXCEPTION(scope, { }); + } else if (value.isObject()) { + if (asObject(value)->inherits(vm, StringObject::info())) { + algorithmName = asStringObject(value)->internalValue()->value(&state); + RETURN_IF_EXCEPTION(scope, { }); + } else { + // FIXME: This doesn't perform some checks mandated by WebIDL for dictionaries: + // - null and undefined input should be treated as if all elements in the dictionary were undefined; + // - undefined elements should be treated as having a default value, or as not present if there isn't such; + // - RegExp and Date objects cannot be converted to dictionaries. + // + // This is partially because we don't implement it elsewhere in WebCore yet, and partially because + // WebCrypto doesn't yet clearly specify what to do with non-present values in most cases anyway. + + auto nameValue = getProperty(state, asObject(value), "name"); + RETURN_IF_EXCEPTION(scope, { }); + + algorithmName = convert<IDLDOMString>(state, nameValue); + RETURN_IF_EXCEPTION(scope, { }); + } + } + + if (!algorithmName.containsOnlyASCII()) { + throwSyntaxError(&state, scope); + return { }; + } + + auto identifier = CryptoAlgorithmRegistry::singleton().identifier(algorithmName); + if (!identifier) { + throwNotSupportedError(state, scope); + return { }; + } + + return identifier.value(); +} + +static std::optional<CryptoAlgorithmIdentifier> optionalHashAlgorithm(ExecState& state, ThrowScope& scope, JSObject* object) +{ + auto hash = getProperty(state, object, "hash"); + RETURN_IF_EXCEPTION(scope, { }); + + if (hash.isUndefinedOrNull()) + return std::nullopt; + + return JSCryptoAlgorithmDictionary::parseAlgorithmIdentifier(state, scope, hash); +} + +static CryptoAlgorithmIdentifier requiredHashAlgorithm(ExecState& state, ThrowScope& scope, JSObject* object) +{ + auto result = optionalHashAlgorithm(state, scope, object); + RETURN_IF_EXCEPTION(scope, { }); + + if (!result) { + throwNotSupportedError(state, scope); + return { }; + } + + return result.value(); +} + +static RefPtr<CryptoAlgorithmParametersDeprecated> createAesCbcParams(ExecState& state, JSValue value) +{ + auto scope = DECLARE_THROW_SCOPE(state.vm()); + + if (!value.isObject()) { + throwTypeError(&state, scope); + return nullptr; + } + + auto iv = getProperty(state, asObject(value), "iv"); + RETURN_IF_EXCEPTION(scope, { }); + + auto result = adoptRef(*new CryptoAlgorithmAesCbcParamsDeprecated); + + auto ivData = cryptoOperationDataFromJSValue(state, scope, iv); + RETURN_IF_EXCEPTION(scope, { }); + + if (ivData.second != 16) { + throwException(&state, scope, createError(&state, "AES-CBC initialization data must be 16 bytes")); + return nullptr; + } + + memcpy(result->iv.data(), ivData.first, ivData.second); + + return WTFMove(result); +} + +static RefPtr<CryptoAlgorithmParametersDeprecated> createAesKeyGenParams(ExecState& state, JSValue value) +{ + auto scope = DECLARE_THROW_SCOPE(state.vm()); + + if (!value.isObject()) { + throwTypeError(&state, scope); + return nullptr; + } + + auto result = adoptRef(*new CryptoAlgorithmAesKeyGenParamsDeprecated); + + auto lengthValue = getProperty(state, asObject(value), "length"); + RETURN_IF_EXCEPTION(scope, nullptr); + + result->length = convert<IDLUnsignedShort>(state, lengthValue, IntegerConversionConfiguration::EnforceRange); + + return WTFMove(result); +} + +static RefPtr<CryptoAlgorithmParametersDeprecated> createHmacParams(ExecState& state, JSValue value) +{ + auto scope = DECLARE_THROW_SCOPE(state.vm()); + + if (!value.isObject()) { + throwTypeError(&state, scope); + return nullptr; + } + + auto result = adoptRef(*new CryptoAlgorithmHmacParamsDeprecated); + + result->hash = requiredHashAlgorithm(state, scope, asObject(value)); + RETURN_IF_EXCEPTION(scope, { }); + + return WTFMove(result); +} + +static RefPtr<CryptoAlgorithmParametersDeprecated> createHmacKeyParams(ExecState& state, JSValue value) +{ + auto scope = DECLARE_THROW_SCOPE(state.vm()); + + if (!value.isObject()) { + throwTypeError(&state, scope); + return nullptr; + } + + auto result = adoptRef(*new CryptoAlgorithmHmacKeyParamsDeprecated); + + result->hash = requiredHashAlgorithm(state, scope, asObject(value)); + RETURN_IF_EXCEPTION(scope, { }); + + auto lengthValue = getProperty(state, asObject(value), "length"); + RETURN_IF_EXCEPTION(scope, nullptr); + + result->length = convert<IDLUnsignedShort>(state, lengthValue, IntegerConversionConfiguration::Normal); + RETURN_IF_EXCEPTION(scope, nullptr); + + result->hasLength = true; + + return WTFMove(result); +} + +static RefPtr<CryptoAlgorithmParametersDeprecated> createRsaKeyGenParams(ExecState& state, JSValue value) +{ + VM& vm = state.vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + + if (!value.isObject()) { + throwTypeError(&state, scope); + return nullptr; + } + + auto result = adoptRef(*new CryptoAlgorithmRsaKeyGenParamsDeprecated); + + auto modulusLengthValue = getProperty(state, asObject(value), "modulusLength"); + RETURN_IF_EXCEPTION(scope, nullptr); + + // FIXME: Why no EnforceRange? Filed as <https://www.w3.org/Bugs/Public/show_bug.cgi?id=23779>. + result->modulusLength = convert<IDLUnsignedLong>(state, modulusLengthValue, IntegerConversionConfiguration::Normal); + RETURN_IF_EXCEPTION(scope, nullptr); + + auto publicExponentValue = getProperty(state, asObject(value), "publicExponent"); + RETURN_IF_EXCEPTION(scope, nullptr); + + auto publicExponentArray = toUnsharedUint8Array(vm, publicExponentValue); + if (!publicExponentArray) { + throwTypeError(&state, scope, ASCIILiteral("Expected a Uint8Array in publicExponent")); + return nullptr; + } + result->publicExponent.append(publicExponentArray->data(), publicExponentArray->byteLength()); + + if (auto optionalHash = optionalHashAlgorithm(state, scope, asObject(value))) { + result->hasHash = true; + result->hash = optionalHash.value(); + } + + return WTFMove(result); +} + +static RefPtr<CryptoAlgorithmParametersDeprecated> createRsaKeyParamsWithHash(ExecState&, JSValue) +{ + // WebCrypto RSA algorithms currently do not take any parameters to importKey. + return adoptRef(*new CryptoAlgorithmRsaKeyParamsWithHashDeprecated); +} + +static RefPtr<CryptoAlgorithmParametersDeprecated> createRsaOaepParams(ExecState& state, JSValue value) +{ + auto scope = DECLARE_THROW_SCOPE(state.vm()); + + if (!value.isObject()) { + throwTypeError(&state, scope); + return nullptr; + } + + auto result = adoptRef(*new CryptoAlgorithmRsaOaepParamsDeprecated); + + result->hash = requiredHashAlgorithm(state, scope, asObject(value)); + RETURN_IF_EXCEPTION(scope, { }); + + auto labelValue = getProperty(state, asObject(value), "label"); + RETURN_IF_EXCEPTION(scope, { }); + + result->hasLabel = !labelValue.isUndefinedOrNull(); + if (!result->hasLabel) + return WTFMove(result); + + auto labelData = cryptoOperationDataFromJSValue(state, scope, labelValue); + RETURN_IF_EXCEPTION(scope, { }); + + result->label.append(labelData.first, labelData.second); + + return WTFMove(result); +} + +static RefPtr<CryptoAlgorithmParametersDeprecated> createRsaSsaParams(ExecState& state, JSValue value) +{ + auto scope = DECLARE_THROW_SCOPE(state.vm()); + + if (!value.isObject()) { + throwTypeError(&state, scope); + return nullptr; + } + + auto result = adoptRef(*new CryptoAlgorithmRsaSsaParamsDeprecated); + + result->hash = requiredHashAlgorithm(state, scope, asObject(value)); + RETURN_IF_EXCEPTION(scope, { }); + + return WTFMove(result); +} + +RefPtr<CryptoAlgorithmParametersDeprecated> JSCryptoAlgorithmDictionary::createParametersForEncrypt(ExecState& state, ThrowScope& scope, CryptoAlgorithmIdentifier algorithm, JSValue value) +{ + switch (algorithm) { + case CryptoAlgorithmIdentifier::RSAES_PKCS1_v1_5: + return adoptRef(*new CryptoAlgorithmParametersDeprecated); + case CryptoAlgorithmIdentifier::RSASSA_PKCS1_v1_5: + case CryptoAlgorithmIdentifier::RSA_PSS: + throwNotSupportedError(state, scope); + return nullptr; + case CryptoAlgorithmIdentifier::RSA_OAEP: + return createRsaOaepParams(state, value); + case CryptoAlgorithmIdentifier::ECDSA: + case CryptoAlgorithmIdentifier::ECDH: + case CryptoAlgorithmIdentifier::AES_CTR: + throwNotSupportedError(state, scope); + return nullptr; + case CryptoAlgorithmIdentifier::AES_CBC: + return createAesCbcParams(state, value); + case CryptoAlgorithmIdentifier::AES_CMAC: + case CryptoAlgorithmIdentifier::AES_GCM: + case CryptoAlgorithmIdentifier::AES_CFB: + throwNotSupportedError(state, scope); + return nullptr; + case CryptoAlgorithmIdentifier::AES_KW: + return adoptRef(*new CryptoAlgorithmParametersDeprecated); + case CryptoAlgorithmIdentifier::HMAC: + case CryptoAlgorithmIdentifier::DH: + case CryptoAlgorithmIdentifier::SHA_1: + case CryptoAlgorithmIdentifier::SHA_224: + case CryptoAlgorithmIdentifier::SHA_256: + case CryptoAlgorithmIdentifier::SHA_384: + case CryptoAlgorithmIdentifier::SHA_512: + case CryptoAlgorithmIdentifier::CONCAT: + case CryptoAlgorithmIdentifier::HKDF_CTR: + case CryptoAlgorithmIdentifier::PBKDF2: + throwNotSupportedError(state, scope); + return nullptr; + } + RELEASE_ASSERT_NOT_REACHED(); + return nullptr; +} + +RefPtr<CryptoAlgorithmParametersDeprecated> JSCryptoAlgorithmDictionary::createParametersForDecrypt(ExecState& state, ThrowScope& scope, CryptoAlgorithmIdentifier algorithm, JSValue value) +{ + switch (algorithm) { + case CryptoAlgorithmIdentifier::RSAES_PKCS1_v1_5: + return adoptRef(*new CryptoAlgorithmParametersDeprecated); + case CryptoAlgorithmIdentifier::RSASSA_PKCS1_v1_5: + case CryptoAlgorithmIdentifier::RSA_PSS: + throwNotSupportedError(state, scope); + return nullptr; + case CryptoAlgorithmIdentifier::RSA_OAEP: + return createRsaOaepParams(state, value); + case CryptoAlgorithmIdentifier::ECDSA: + case CryptoAlgorithmIdentifier::ECDH: + case CryptoAlgorithmIdentifier::AES_CTR: + throwNotSupportedError(state, scope); + return nullptr; + case CryptoAlgorithmIdentifier::AES_CBC: + return createAesCbcParams(state, value); + case CryptoAlgorithmIdentifier::AES_CMAC: + case CryptoAlgorithmIdentifier::AES_GCM: + case CryptoAlgorithmIdentifier::AES_CFB: + throwNotSupportedError(state, scope); + return nullptr; + case CryptoAlgorithmIdentifier::AES_KW: + return adoptRef(*new CryptoAlgorithmParametersDeprecated); + case CryptoAlgorithmIdentifier::HMAC: + case CryptoAlgorithmIdentifier::DH: + case CryptoAlgorithmIdentifier::SHA_1: + case CryptoAlgorithmIdentifier::SHA_224: + case CryptoAlgorithmIdentifier::SHA_256: + case CryptoAlgorithmIdentifier::SHA_384: + case CryptoAlgorithmIdentifier::SHA_512: + case CryptoAlgorithmIdentifier::CONCAT: + case CryptoAlgorithmIdentifier::HKDF_CTR: + case CryptoAlgorithmIdentifier::PBKDF2: + throwNotSupportedError(state, scope); + return nullptr; + } + RELEASE_ASSERT_NOT_REACHED(); + return nullptr; +} + +RefPtr<CryptoAlgorithmParametersDeprecated> JSCryptoAlgorithmDictionary::createParametersForSign(ExecState& state, ThrowScope& scope, CryptoAlgorithmIdentifier algorithm, JSValue value) +{ + switch (algorithm) { + case CryptoAlgorithmIdentifier::RSAES_PKCS1_v1_5: + throwNotSupportedError(state, scope); + return nullptr; + case CryptoAlgorithmIdentifier::RSASSA_PKCS1_v1_5: + return createRsaSsaParams(state, value); + case CryptoAlgorithmIdentifier::RSA_PSS: + case CryptoAlgorithmIdentifier::RSA_OAEP: + case CryptoAlgorithmIdentifier::ECDSA: + case CryptoAlgorithmIdentifier::ECDH: + case CryptoAlgorithmIdentifier::AES_CTR: + case CryptoAlgorithmIdentifier::AES_CBC: + case CryptoAlgorithmIdentifier::AES_CMAC: + case CryptoAlgorithmIdentifier::AES_GCM: + case CryptoAlgorithmIdentifier::AES_CFB: + case CryptoAlgorithmIdentifier::AES_KW: + throwNotSupportedError(state, scope); + return nullptr; + case CryptoAlgorithmIdentifier::HMAC: + return createHmacParams(state, value); + case CryptoAlgorithmIdentifier::DH: + case CryptoAlgorithmIdentifier::SHA_1: + case CryptoAlgorithmIdentifier::SHA_224: + case CryptoAlgorithmIdentifier::SHA_256: + case CryptoAlgorithmIdentifier::SHA_384: + case CryptoAlgorithmIdentifier::SHA_512: + case CryptoAlgorithmIdentifier::CONCAT: + case CryptoAlgorithmIdentifier::HKDF_CTR: + case CryptoAlgorithmIdentifier::PBKDF2: + throwNotSupportedError(state, scope); + return nullptr; + } + RELEASE_ASSERT_NOT_REACHED(); + return nullptr; +} + +RefPtr<CryptoAlgorithmParametersDeprecated> JSCryptoAlgorithmDictionary::createParametersForVerify(ExecState& state, ThrowScope& scope, CryptoAlgorithmIdentifier algorithm, JSValue value) +{ + switch (algorithm) { + case CryptoAlgorithmIdentifier::RSAES_PKCS1_v1_5: + throwNotSupportedError(state, scope); + return nullptr; + case CryptoAlgorithmIdentifier::RSASSA_PKCS1_v1_5: + return createRsaSsaParams(state, value); + case CryptoAlgorithmIdentifier::RSA_PSS: + case CryptoAlgorithmIdentifier::RSA_OAEP: + case CryptoAlgorithmIdentifier::ECDSA: + case CryptoAlgorithmIdentifier::ECDH: + case CryptoAlgorithmIdentifier::AES_CTR: + case CryptoAlgorithmIdentifier::AES_CBC: + case CryptoAlgorithmIdentifier::AES_CMAC: + case CryptoAlgorithmIdentifier::AES_GCM: + case CryptoAlgorithmIdentifier::AES_CFB: + case CryptoAlgorithmIdentifier::AES_KW: + throwNotSupportedError(state, scope); + return nullptr; + case CryptoAlgorithmIdentifier::HMAC: + return createHmacParams(state, value); + case CryptoAlgorithmIdentifier::DH: + case CryptoAlgorithmIdentifier::SHA_1: + case CryptoAlgorithmIdentifier::SHA_224: + case CryptoAlgorithmIdentifier::SHA_256: + case CryptoAlgorithmIdentifier::SHA_384: + case CryptoAlgorithmIdentifier::SHA_512: + case CryptoAlgorithmIdentifier::CONCAT: + case CryptoAlgorithmIdentifier::HKDF_CTR: + case CryptoAlgorithmIdentifier::PBKDF2: + throwNotSupportedError(state, scope); + return nullptr; + } + RELEASE_ASSERT_NOT_REACHED(); + return nullptr; +} + +RefPtr<CryptoAlgorithmParametersDeprecated> JSCryptoAlgorithmDictionary::createParametersForDigest(ExecState& state, ThrowScope& scope, CryptoAlgorithmIdentifier algorithm, JSValue) +{ + switch (algorithm) { + case CryptoAlgorithmIdentifier::RSAES_PKCS1_v1_5: + case CryptoAlgorithmIdentifier::RSASSA_PKCS1_v1_5: + case CryptoAlgorithmIdentifier::RSA_PSS: + case CryptoAlgorithmIdentifier::RSA_OAEP: + case CryptoAlgorithmIdentifier::ECDSA: + case CryptoAlgorithmIdentifier::ECDH: + case CryptoAlgorithmIdentifier::AES_CTR: + case CryptoAlgorithmIdentifier::AES_CBC: + case CryptoAlgorithmIdentifier::AES_CMAC: + case CryptoAlgorithmIdentifier::AES_GCM: + case CryptoAlgorithmIdentifier::AES_CFB: + case CryptoAlgorithmIdentifier::AES_KW: + case CryptoAlgorithmIdentifier::HMAC: + case CryptoAlgorithmIdentifier::DH: + throwNotSupportedError(state, scope); + return nullptr; + case CryptoAlgorithmIdentifier::SHA_1: + case CryptoAlgorithmIdentifier::SHA_224: + case CryptoAlgorithmIdentifier::SHA_256: + case CryptoAlgorithmIdentifier::SHA_384: + case CryptoAlgorithmIdentifier::SHA_512: + return adoptRef(*new CryptoAlgorithmParametersDeprecated); + case CryptoAlgorithmIdentifier::CONCAT: + case CryptoAlgorithmIdentifier::HKDF_CTR: + case CryptoAlgorithmIdentifier::PBKDF2: + throwNotSupportedError(state, scope); + return nullptr; + } + RELEASE_ASSERT_NOT_REACHED(); + return nullptr; +} + +RefPtr<CryptoAlgorithmParametersDeprecated> JSCryptoAlgorithmDictionary::createParametersForGenerateKey(ExecState& state, ThrowScope& scope, CryptoAlgorithmIdentifier algorithm, JSValue value) +{ + switch (algorithm) { + case CryptoAlgorithmIdentifier::RSAES_PKCS1_v1_5: + case CryptoAlgorithmIdentifier::RSASSA_PKCS1_v1_5: + case CryptoAlgorithmIdentifier::RSA_PSS: + case CryptoAlgorithmIdentifier::RSA_OAEP: + return createRsaKeyGenParams(state, value); + case CryptoAlgorithmIdentifier::ECDSA: + case CryptoAlgorithmIdentifier::ECDH: + throwNotSupportedError(state, scope); + return nullptr; + case CryptoAlgorithmIdentifier::AES_CTR: + case CryptoAlgorithmIdentifier::AES_CBC: + case CryptoAlgorithmIdentifier::AES_CMAC: + case CryptoAlgorithmIdentifier::AES_GCM: + case CryptoAlgorithmIdentifier::AES_CFB: + case CryptoAlgorithmIdentifier::AES_KW: + return createAesKeyGenParams(state, value); + case CryptoAlgorithmIdentifier::HMAC: + return createHmacKeyParams(state, value); + case CryptoAlgorithmIdentifier::DH: + case CryptoAlgorithmIdentifier::SHA_1: + case CryptoAlgorithmIdentifier::SHA_224: + case CryptoAlgorithmIdentifier::SHA_256: + case CryptoAlgorithmIdentifier::SHA_384: + case CryptoAlgorithmIdentifier::SHA_512: + case CryptoAlgorithmIdentifier::CONCAT: + case CryptoAlgorithmIdentifier::HKDF_CTR: + case CryptoAlgorithmIdentifier::PBKDF2: + throwNotSupportedError(state, scope); + return nullptr; + } + RELEASE_ASSERT_NOT_REACHED(); + return nullptr; +} + +RefPtr<CryptoAlgorithmParametersDeprecated> JSCryptoAlgorithmDictionary::createParametersForDeriveKey(ExecState& state, ThrowScope& scope, CryptoAlgorithmIdentifier algorithm, JSValue) +{ + switch (algorithm) { + case CryptoAlgorithmIdentifier::RSAES_PKCS1_v1_5: + case CryptoAlgorithmIdentifier::RSASSA_PKCS1_v1_5: + case CryptoAlgorithmIdentifier::RSA_PSS: + case CryptoAlgorithmIdentifier::RSA_OAEP: + case CryptoAlgorithmIdentifier::ECDSA: + case CryptoAlgorithmIdentifier::ECDH: + case CryptoAlgorithmIdentifier::AES_CTR: + case CryptoAlgorithmIdentifier::AES_CBC: + case CryptoAlgorithmIdentifier::AES_CMAC: + case CryptoAlgorithmIdentifier::AES_GCM: + case CryptoAlgorithmIdentifier::AES_CFB: + case CryptoAlgorithmIdentifier::AES_KW: + case CryptoAlgorithmIdentifier::HMAC: + case CryptoAlgorithmIdentifier::DH: + case CryptoAlgorithmIdentifier::SHA_1: + case CryptoAlgorithmIdentifier::SHA_224: + case CryptoAlgorithmIdentifier::SHA_256: + case CryptoAlgorithmIdentifier::SHA_384: + case CryptoAlgorithmIdentifier::SHA_512: + case CryptoAlgorithmIdentifier::CONCAT: + case CryptoAlgorithmIdentifier::HKDF_CTR: + case CryptoAlgorithmIdentifier::PBKDF2: + throwNotSupportedError(state, scope); + return nullptr; + } + RELEASE_ASSERT_NOT_REACHED(); + return nullptr; +} + +RefPtr<CryptoAlgorithmParametersDeprecated> JSCryptoAlgorithmDictionary::createParametersForDeriveBits(ExecState& state, ThrowScope& scope, CryptoAlgorithmIdentifier algorithm, JSValue) +{ + switch (algorithm) { + case CryptoAlgorithmIdentifier::RSAES_PKCS1_v1_5: + case CryptoAlgorithmIdentifier::RSASSA_PKCS1_v1_5: + case CryptoAlgorithmIdentifier::RSA_PSS: + case CryptoAlgorithmIdentifier::RSA_OAEP: + case CryptoAlgorithmIdentifier::ECDSA: + case CryptoAlgorithmIdentifier::ECDH: + case CryptoAlgorithmIdentifier::AES_CTR: + case CryptoAlgorithmIdentifier::AES_CBC: + case CryptoAlgorithmIdentifier::AES_CMAC: + case CryptoAlgorithmIdentifier::AES_GCM: + case CryptoAlgorithmIdentifier::AES_CFB: + case CryptoAlgorithmIdentifier::AES_KW: + case CryptoAlgorithmIdentifier::HMAC: + case CryptoAlgorithmIdentifier::DH: + case CryptoAlgorithmIdentifier::SHA_1: + case CryptoAlgorithmIdentifier::SHA_224: + case CryptoAlgorithmIdentifier::SHA_256: + case CryptoAlgorithmIdentifier::SHA_384: + case CryptoAlgorithmIdentifier::SHA_512: + case CryptoAlgorithmIdentifier::CONCAT: + case CryptoAlgorithmIdentifier::HKDF_CTR: + case CryptoAlgorithmIdentifier::PBKDF2: + throwNotSupportedError(state, scope); + return nullptr; + } + RELEASE_ASSERT_NOT_REACHED(); + return nullptr; +} + +RefPtr<CryptoAlgorithmParametersDeprecated> JSCryptoAlgorithmDictionary::createParametersForImportKey(ExecState& state, ThrowScope& scope, CryptoAlgorithmIdentifier algorithm, JSValue value) +{ + switch (algorithm) { + case CryptoAlgorithmIdentifier::RSAES_PKCS1_v1_5: + case CryptoAlgorithmIdentifier::RSASSA_PKCS1_v1_5: + case CryptoAlgorithmIdentifier::RSA_PSS: + case CryptoAlgorithmIdentifier::RSA_OAEP: + return createRsaKeyParamsWithHash(state, value); + case CryptoAlgorithmIdentifier::ECDSA: + case CryptoAlgorithmIdentifier::ECDH: + case CryptoAlgorithmIdentifier::AES_CTR: + case CryptoAlgorithmIdentifier::AES_CBC: + case CryptoAlgorithmIdentifier::AES_CMAC: + case CryptoAlgorithmIdentifier::AES_GCM: + case CryptoAlgorithmIdentifier::AES_CFB: + case CryptoAlgorithmIdentifier::AES_KW: + return adoptRef(*new CryptoAlgorithmParametersDeprecated); + case CryptoAlgorithmIdentifier::HMAC: + return createHmacParams(state, value); + case CryptoAlgorithmIdentifier::DH: + return adoptRef(*new CryptoAlgorithmParametersDeprecated); + case CryptoAlgorithmIdentifier::SHA_1: + case CryptoAlgorithmIdentifier::SHA_224: + case CryptoAlgorithmIdentifier::SHA_256: + case CryptoAlgorithmIdentifier::SHA_384: + case CryptoAlgorithmIdentifier::SHA_512: + case CryptoAlgorithmIdentifier::CONCAT: + case CryptoAlgorithmIdentifier::HKDF_CTR: + case CryptoAlgorithmIdentifier::PBKDF2: + throwNotSupportedError(state, scope); + return nullptr; + } + RELEASE_ASSERT_NOT_REACHED(); + return nullptr; +} + +RefPtr<CryptoAlgorithmParametersDeprecated> JSCryptoAlgorithmDictionary::createParametersForExportKey(ExecState& state, ThrowScope& scope, CryptoAlgorithmIdentifier algorithm, JSValue) +{ + switch (algorithm) { + case CryptoAlgorithmIdentifier::RSAES_PKCS1_v1_5: + case CryptoAlgorithmIdentifier::RSASSA_PKCS1_v1_5: + case CryptoAlgorithmIdentifier::RSA_PSS: + case CryptoAlgorithmIdentifier::RSA_OAEP: + case CryptoAlgorithmIdentifier::ECDSA: + case CryptoAlgorithmIdentifier::ECDH: + case CryptoAlgorithmIdentifier::AES_CTR: + case CryptoAlgorithmIdentifier::AES_CBC: + case CryptoAlgorithmIdentifier::AES_CMAC: + case CryptoAlgorithmIdentifier::AES_GCM: + case CryptoAlgorithmIdentifier::AES_CFB: + case CryptoAlgorithmIdentifier::AES_KW: + case CryptoAlgorithmIdentifier::HMAC: + case CryptoAlgorithmIdentifier::DH: + return adoptRef(*new CryptoAlgorithmParametersDeprecated); + case CryptoAlgorithmIdentifier::SHA_1: + case CryptoAlgorithmIdentifier::SHA_224: + case CryptoAlgorithmIdentifier::SHA_256: + case CryptoAlgorithmIdentifier::SHA_384: + case CryptoAlgorithmIdentifier::SHA_512: + case CryptoAlgorithmIdentifier::CONCAT: + case CryptoAlgorithmIdentifier::HKDF_CTR: + case CryptoAlgorithmIdentifier::PBKDF2: + throwNotSupportedError(state, scope); + return nullptr; + } + RELEASE_ASSERT_NOT_REACHED(); + return nullptr; +} + +} + +#endif // ENABLE(SUBTLE_CRYPTO) diff --git a/Source/WebCore/bindings/js/JSCryptoAlgorithmDictionary.h b/Source/WebCore/bindings/js/JSCryptoAlgorithmDictionary.h new file mode 100644 index 000000000..64ce3db75 --- /dev/null +++ b/Source/WebCore/bindings/js/JSCryptoAlgorithmDictionary.h @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2013 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +#if ENABLE(SUBTLE_CRYPTO) + +#include "CryptoAlgorithmIdentifier.h" +#include <wtf/Forward.h> + +namespace JSC { +class ExecState; +class JSValue; +class ThrowScope; +} + +namespace WebCore { + +class CryptoAlgorithmParametersDeprecated; + +class JSCryptoAlgorithmDictionary { +public: + static CryptoAlgorithmIdentifier parseAlgorithmIdentifier(JSC::ExecState&, JSC::ThrowScope&, JSC::JSValue); + + static RefPtr<CryptoAlgorithmParametersDeprecated> createParametersForEncrypt(JSC::ExecState&, JSC::ThrowScope&, CryptoAlgorithmIdentifier, JSC::JSValue); + static RefPtr<CryptoAlgorithmParametersDeprecated> createParametersForDecrypt(JSC::ExecState&, JSC::ThrowScope&, CryptoAlgorithmIdentifier, JSC::JSValue); + static RefPtr<CryptoAlgorithmParametersDeprecated> createParametersForSign(JSC::ExecState&, JSC::ThrowScope&, CryptoAlgorithmIdentifier, JSC::JSValue); + static RefPtr<CryptoAlgorithmParametersDeprecated> createParametersForVerify(JSC::ExecState&, JSC::ThrowScope&, CryptoAlgorithmIdentifier, JSC::JSValue); + static RefPtr<CryptoAlgorithmParametersDeprecated> createParametersForDigest(JSC::ExecState&, JSC::ThrowScope&, CryptoAlgorithmIdentifier, JSC::JSValue); + static RefPtr<CryptoAlgorithmParametersDeprecated> createParametersForGenerateKey(JSC::ExecState&, JSC::ThrowScope&, CryptoAlgorithmIdentifier, JSC::JSValue); + static RefPtr<CryptoAlgorithmParametersDeprecated> createParametersForDeriveKey(JSC::ExecState&, JSC::ThrowScope&, CryptoAlgorithmIdentifier, JSC::JSValue); + static RefPtr<CryptoAlgorithmParametersDeprecated> createParametersForDeriveBits(JSC::ExecState&, JSC::ThrowScope&, CryptoAlgorithmIdentifier, JSC::JSValue); + static RefPtr<CryptoAlgorithmParametersDeprecated> createParametersForImportKey(JSC::ExecState&, JSC::ThrowScope&, CryptoAlgorithmIdentifier, JSC::JSValue); + static RefPtr<CryptoAlgorithmParametersDeprecated> createParametersForExportKey(JSC::ExecState&, JSC::ThrowScope&, CryptoAlgorithmIdentifier, JSC::JSValue); +}; + +} // namespace WebCore + +#endif // ENABLE(SUBTLE_CRYPTO) diff --git a/Source/WebCore/bindings/js/JSCryptoCustom.cpp b/Source/WebCore/bindings/js/JSCryptoCustom.cpp index 9d1177146..a71b71aeb 100644 --- a/Source/WebCore/bindings/js/JSCryptoCustom.cpp +++ b/Source/WebCore/bindings/js/JSCryptoCustom.cpp @@ -1,5 +1,6 @@ /* * Copyright (C) 2012 Google Inc. All rights reserved. + * Copyright (C) 2016 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -25,8 +26,9 @@ #include "config.h" #include "JSCrypto.h" -#include "ExceptionCode.h" - +#include "JSDOMConvertBufferSource.h" +#include "JSDOMExceptionHandling.h" +#include <heap/HeapInlines.h> #include <runtime/ArrayBufferView.h> #include <runtime/Error.h> #include <runtime/JSArrayBufferView.h> @@ -35,23 +37,20 @@ using namespace JSC; namespace WebCore { -JSValue JSCrypto::getRandomValues(ExecState* exec) +JSValue JSCrypto::getRandomValues(ExecState& state) { - if (exec->argumentCount() < 1) - return exec->vm().throwException(exec, createNotEnoughArgumentsError(exec)); + VM& vm = state.vm(); + auto scope = DECLARE_THROW_SCOPE(vm); - JSValue buffer = exec->argument(0); - RefPtr<ArrayBufferView> arrayBufferView = toArrayBufferView(buffer); - if (!arrayBufferView) - return throwTypeError(exec); + if (state.argumentCount() < 1) + return throwException(&state, scope, createNotEnoughArgumentsError(&state)); - ExceptionCode ec = 0; - impl().getRandomValues(arrayBufferView.get(), ec); + JSValue buffer = state.argument(0); + auto arrayBufferView = toUnsharedArrayBufferView(vm, buffer); + if (!arrayBufferView) + return throwTypeError(&state, scope); - if (ec) { - setDOMException(exec, ec); - return jsUndefined(); - } + propagateException(state, scope, wrapped().getRandomValues(*arrayBufferView)); return buffer; } diff --git a/Source/WebCore/bindings/js/JSCryptoKeyCustom.cpp b/Source/WebCore/bindings/js/JSCryptoKeyCustom.cpp new file mode 100644 index 000000000..e975400db --- /dev/null +++ b/Source/WebCore/bindings/js/JSCryptoKeyCustom.cpp @@ -0,0 +1,91 @@ +/* + * Copyright (C) 2013 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "JSCryptoKey.h" + +#if ENABLE(SUBTLE_CRYPTO) + +#include "CryptoKeyAES.h" +#include "CryptoKeyHMAC.h" +#include "CryptoKeyRSA.h" +#include "JSCryptoAlgorithmBuilder.h" +#include <heap/HeapInlines.h> +#include <runtime/JSCJSValueInlines.h> + +using namespace JSC; + +namespace WebCore { + +JSValue JSCryptoKey::algorithm(JSC::ExecState& state) const +{ + if (m_algorithm) + return m_algorithm.get(); + + JSCryptoAlgorithmBuilder builder(&state); + + std::unique_ptr<KeyAlgorithm> algorithm = wrapped().buildAlgorithm(); + switch (algorithm->keyAlgorithmClass()) { + case KeyAlgorithmClass::AES: { + auto& aesAlgorithm = downcast<AesKeyAlgorithm>(*algorithm); + builder.add("name", aesAlgorithm.name()); + builder.add("length", aesAlgorithm.length()); + break; + } + case KeyAlgorithmClass::HMAC: { + auto& hmacAlgorithm = downcast<HmacKeyAlgorithm>(*algorithm); + builder.add("name", hmacAlgorithm.name()); + JSCryptoAlgorithmBuilder hmacHash(&state); + hmacHash.add("name", hmacAlgorithm.hash()); + builder.add("hash", hmacHash); + builder.add("length", hmacAlgorithm.length()); + break; + } + case KeyAlgorithmClass::HRSA: { + auto& rsaAlgorithm = downcast<RsaHashedKeyAlgorithm>(*algorithm); + builder.add("name", rsaAlgorithm.name()); + builder.add("modulusLength", rsaAlgorithm.modulusLength()); + builder.add("publicExponent", rsaAlgorithm.publicExponent()); + JSCryptoAlgorithmBuilder rsaHash(&state); + rsaHash.add("name", rsaAlgorithm.hash()); + builder.add("hash", rsaHash); + break; + } + case KeyAlgorithmClass::RSA: { + auto& rsaAlgorithm = downcast<RsaKeyAlgorithm>(*algorithm); + builder.add("name", rsaAlgorithm.name()); + builder.add("modulusLength", rsaAlgorithm.modulusLength()); + builder.add("publicExponent", rsaAlgorithm.publicExponent()); + break; + } + } + + m_algorithm.set(state.vm(), this, builder.result()); + return m_algorithm.get(); +} + +} // namespace WebCore + +#endif // ENABLE(SUBTLE_CRYPTO) diff --git a/Source/WebCore/bindings/js/JSCryptoKeySerializationJWK.cpp b/Source/WebCore/bindings/js/JSCryptoKeySerializationJWK.cpp new file mode 100644 index 000000000..92317c20d --- /dev/null +++ b/Source/WebCore/bindings/js/JSCryptoKeySerializationJWK.cpp @@ -0,0 +1,771 @@ +/* + * Copyright (C) 2013, 2016 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "JSCryptoKeySerializationJWK.h" + +#if ENABLE(SUBTLE_CRYPTO) + +#include "CryptoAlgorithm.h" +#include "CryptoAlgorithmHmacParamsDeprecated.h" +#include "CryptoAlgorithmRegistry.h" +#include "CryptoAlgorithmRsaKeyParamsWithHashDeprecated.h" +#include "CryptoKey.h" +#include "CryptoKeyAES.h" +#include "CryptoKeyDataOctetSequence.h" +#include "CryptoKeyDataRSAComponents.h" +#include "CryptoKeyHMAC.h" +#include "CryptoKeyRSA.h" +#include "ExceptionCode.h" +#include "JSDOMBinding.h" +#include <heap/StrongInlines.h> +#include <runtime/JSCInlines.h> +#include <runtime/JSONObject.h> +#include <runtime/ObjectConstructor.h> +#include <wtf/text/Base64.h> + +using namespace JSC; + +namespace WebCore { + +static bool getJSArrayFromJSON(ExecState* exec, JSObject* json, const char* key, JSArray*& result) +{ + VM& vm = exec->vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + + Identifier identifier = Identifier::fromString(exec, key); + PropertySlot slot(json, PropertySlot::InternalMethodType::Get); + + if (!json->getPropertySlot(exec, identifier, slot)) + return false; + + JSValue value = slot.getValue(exec, identifier); + ASSERT(!scope.exception()); + if (!isJSArray(value)) { + throwTypeError(exec, scope, String::format("Expected an array for \"%s\" JSON key", key)); + return false; + } + + result = asArray(value); + + return true; +} + +static bool getStringFromJSON(ExecState* exec, JSObject* json, const char* key, String& result) +{ + VM& vm = exec->vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + + Identifier identifier = Identifier::fromString(exec, key); + PropertySlot slot(json, PropertySlot::InternalMethodType::Get); + + if (!json->getPropertySlot(exec, identifier, slot)) + return false; + + JSValue jsValue = slot.getValue(exec, identifier); + ASSERT(!scope.exception()); + if (!jsValue.getString(exec, result)) { + // Can get an out of memory exception. + RETURN_IF_EXCEPTION(scope, false); + throwTypeError(exec, scope, String::format("Expected a string value for \"%s\" JSON key", key)); + return false; + } + + return true; +} + +static bool getBooleanFromJSON(ExecState* exec, JSObject* json, const char* key, bool& result) +{ + VM& vm = exec->vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + + Identifier identifier = Identifier::fromString(exec, key); + PropertySlot slot(json, PropertySlot::InternalMethodType::Get); + + if (!json->getPropertySlot(exec, identifier, slot)) + return false; + + JSValue jsValue = slot.getValue(exec, identifier); + ASSERT(!scope.exception()); + if (!jsValue.isBoolean()) { + throwTypeError(exec, scope, String::format("Expected a boolean value for \"%s\" JSON key", key)); + return false; + } + + result = jsValue.asBoolean(); + return true; +} + +static bool getBigIntegerVectorFromJSON(ExecState* exec, JSObject* json, const char* key, Vector<uint8_t>& result) +{ + VM& vm = exec->vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + + String base64urlEncodedNumber; + if (!getStringFromJSON(exec, json, key, base64urlEncodedNumber)) + return false; + + if (!base64URLDecode(base64urlEncodedNumber, result)) { + throwTypeError(exec, scope, ASCIILiteral("Cannot decode base64url key data in JWK")); + return false; + } + + if (result[0] == 0) { + throwTypeError(exec, scope, ASCIILiteral("JWK BigInteger must utilize the minimum number of octets to represent the value")); + return false; + } + + return true; +} + +JSCryptoKeySerializationJWK::JSCryptoKeySerializationJWK(ExecState* exec, const String& jsonString) + : m_exec(exec) +{ + VM& vm = exec->vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + + JSValue jsonValue = JSONParse(exec, jsonString); + if (UNLIKELY(scope.exception())) + return; + + if (!jsonValue || !jsonValue.isObject()) { + throwTypeError(exec, scope, ASCIILiteral("Invalid JWK serialization")); + return; + } + + m_json.set(vm, asObject(jsonValue)); +} + +JSCryptoKeySerializationJWK::~JSCryptoKeySerializationJWK() +{ +} + +static Ref<CryptoAlgorithmParametersDeprecated> createHMACParameters(CryptoAlgorithmIdentifier hashFunction) +{ + auto hmacParameters = adoptRef(*new CryptoAlgorithmHmacParamsDeprecated); + hmacParameters->hash = hashFunction; + return WTFMove(hmacParameters); +} + +static Ref<CryptoAlgorithmParametersDeprecated> createRSAKeyParametersWithHash(CryptoAlgorithmIdentifier hashFunction) +{ + auto rsaKeyParameters = adoptRef(*new CryptoAlgorithmRsaKeyParamsWithHashDeprecated); + rsaKeyParameters->hasHash = true; + rsaKeyParameters->hash = hashFunction; + return WTFMove(rsaKeyParameters); +} + +std::optional<CryptoAlgorithmPair> JSCryptoKeySerializationJWK::reconcileAlgorithm(CryptoAlgorithm* suggestedAlgorithm, CryptoAlgorithmParametersDeprecated* suggestedParameters) const +{ + VM& vm = m_exec->vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + + if (!getStringFromJSON(m_exec, m_json.get(), "alg", m_jwkAlgorithmName)) { + // Algorithm is optional in JWK. + return CryptoAlgorithmPair { suggestedAlgorithm, suggestedParameters }; + } + + auto& algorithmRegisty = CryptoAlgorithmRegistry::singleton(); + RefPtr<CryptoAlgorithm> algorithm; + RefPtr<CryptoAlgorithmParametersDeprecated> parameters; + if (m_jwkAlgorithmName == "HS256") { + algorithm = algorithmRegisty.create(CryptoAlgorithmIdentifier::HMAC); + parameters = createHMACParameters(CryptoAlgorithmIdentifier::SHA_256); + } else if (m_jwkAlgorithmName == "HS384") { + algorithm = algorithmRegisty.create(CryptoAlgorithmIdentifier::HMAC); + parameters = createHMACParameters(CryptoAlgorithmIdentifier::SHA_384); + } else if (m_jwkAlgorithmName == "HS512") { + algorithm = algorithmRegisty.create(CryptoAlgorithmIdentifier::HMAC); + parameters = createHMACParameters(CryptoAlgorithmIdentifier::SHA_512); + } else if (m_jwkAlgorithmName == "RS256") { + algorithm = algorithmRegisty.create(CryptoAlgorithmIdentifier::RSASSA_PKCS1_v1_5); + parameters = createRSAKeyParametersWithHash(CryptoAlgorithmIdentifier::SHA_256); + } else if (m_jwkAlgorithmName == "RS384") { + algorithm = algorithmRegisty.create(CryptoAlgorithmIdentifier::RSASSA_PKCS1_v1_5); + parameters = createRSAKeyParametersWithHash(CryptoAlgorithmIdentifier::SHA_384); + } else if (m_jwkAlgorithmName == "RS512") { + algorithm = algorithmRegisty.create(CryptoAlgorithmIdentifier::RSASSA_PKCS1_v1_5); + parameters = createRSAKeyParametersWithHash(CryptoAlgorithmIdentifier::SHA_512); + } else if (m_jwkAlgorithmName == "RSA1_5") { + algorithm = algorithmRegisty.create(CryptoAlgorithmIdentifier::RSAES_PKCS1_v1_5); + parameters = adoptRef(*new CryptoAlgorithmRsaKeyParamsWithHashDeprecated); + } else if (m_jwkAlgorithmName == "RSA-OAEP") { + algorithm = algorithmRegisty.create(CryptoAlgorithmIdentifier::RSA_OAEP); + parameters = createRSAKeyParametersWithHash(CryptoAlgorithmIdentifier::SHA_1); + } else if (m_jwkAlgorithmName == "A128CBC") { + algorithm = algorithmRegisty.create(CryptoAlgorithmIdentifier::AES_CBC); + parameters = adoptRef(*new CryptoAlgorithmParametersDeprecated); + } else if (m_jwkAlgorithmName == "A192CBC") { + algorithm = algorithmRegisty.create(CryptoAlgorithmIdentifier::AES_CBC); + parameters = adoptRef(*new CryptoAlgorithmParametersDeprecated); + } else if (m_jwkAlgorithmName == "A256CBC") { + algorithm = algorithmRegisty.create(CryptoAlgorithmIdentifier::AES_CBC); + parameters = adoptRef(*new CryptoAlgorithmParametersDeprecated); + } else if (m_jwkAlgorithmName == "A128KW") { + algorithm = algorithmRegisty.create(CryptoAlgorithmIdentifier::AES_KW); + parameters = adoptRef(*new CryptoAlgorithmParametersDeprecated); + } else if (m_jwkAlgorithmName == "A192KW") { + algorithm = algorithmRegisty.create(CryptoAlgorithmIdentifier::AES_KW); + parameters = adoptRef(*new CryptoAlgorithmParametersDeprecated); + } else if (m_jwkAlgorithmName == "A256KW") { + algorithm = algorithmRegisty.create(CryptoAlgorithmIdentifier::AES_KW); + parameters = adoptRef(*new CryptoAlgorithmParametersDeprecated); + } else { + throwTypeError(m_exec, scope, "Unsupported JWK algorithm " + m_jwkAlgorithmName); + return std::nullopt; + } + + if (!suggestedAlgorithm) + return CryptoAlgorithmPair { algorithm, parameters }; + + if (!algorithm) + return CryptoAlgorithmPair { suggestedAlgorithm, suggestedParameters }; + + if (algorithm->identifier() != suggestedAlgorithm->identifier()) + return std::nullopt; + + if (algorithm->identifier() == CryptoAlgorithmIdentifier::HMAC) { + if (downcast<CryptoAlgorithmHmacParamsDeprecated>(*parameters).hash != downcast<CryptoAlgorithmHmacParamsDeprecated>(*suggestedParameters).hash) + return std::nullopt; + return CryptoAlgorithmPair { suggestedAlgorithm, suggestedParameters }; + } + if (algorithm->identifier() == CryptoAlgorithmIdentifier::RSASSA_PKCS1_v1_5 + || algorithm->identifier() == CryptoAlgorithmIdentifier::RSA_OAEP) { + CryptoAlgorithmRsaKeyParamsWithHashDeprecated& rsaKeyParameters = downcast<CryptoAlgorithmRsaKeyParamsWithHashDeprecated>(*parameters); + CryptoAlgorithmRsaKeyParamsWithHashDeprecated& suggestedRSAKeyParameters = downcast<CryptoAlgorithmRsaKeyParamsWithHashDeprecated>(*suggestedParameters); + ASSERT(rsaKeyParameters.hasHash); + if (suggestedRSAKeyParameters.hasHash) { + if (suggestedRSAKeyParameters.hash != rsaKeyParameters.hash) + return std::nullopt; + return CryptoAlgorithmPair { suggestedAlgorithm, suggestedParameters }; + } + suggestedRSAKeyParameters.hasHash = true; + suggestedRSAKeyParameters.hash = rsaKeyParameters.hash; + } + + // Other algorithms don't have parameters. + return CryptoAlgorithmPair { suggestedAlgorithm, suggestedParameters }; +} + +static bool tryJWKKeyOpsValue(ExecState* exec, CryptoKeyUsageBitmap& usages, const String& operation, const String& tryOperation, CryptoKeyUsageBitmap tryUsage) +{ + VM& vm = exec->vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + + if (operation == tryOperation) { + if (usages & tryUsage) { + throwTypeError(exec, scope, ASCIILiteral("JWK key_ops contains a duplicate operation")); + return false; + } + usages |= tryUsage; + } + return true; +} + +void JSCryptoKeySerializationJWK::reconcileUsages(CryptoKeyUsageBitmap& suggestedUsages) const +{ + VM& vm = m_exec->vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + + CryptoKeyUsageBitmap jwkUsages = 0; + + JSArray* keyOps; + if (getJSArrayFromJSON(m_exec, m_json.get(), "key_ops", keyOps)) { + for (size_t i = 0; i < keyOps->length(); ++i) { + JSValue jsValue = keyOps->getIndex(m_exec, i); + String operation; + if (!jsValue.getString(m_exec, operation)) { + if (!scope.exception()) + throwTypeError(m_exec, scope, ASCIILiteral("JWK key_ops attribute could not be processed")); + return; + } + if (!tryJWKKeyOpsValue(m_exec, jwkUsages, operation, ASCIILiteral("sign"), CryptoKeyUsageSign)) + return; + if (!tryJWKKeyOpsValue(m_exec, jwkUsages, operation, ASCIILiteral("verify"), CryptoKeyUsageVerify)) + return; + if (!tryJWKKeyOpsValue(m_exec, jwkUsages, operation, ASCIILiteral("encrypt"), CryptoKeyUsageEncrypt)) + return; + if (!tryJWKKeyOpsValue(m_exec, jwkUsages, operation, ASCIILiteral("decrypt"), CryptoKeyUsageDecrypt)) + return; + if (!tryJWKKeyOpsValue(m_exec, jwkUsages, operation, ASCIILiteral("wrapKey"), CryptoKeyUsageWrapKey)) + return; + if (!tryJWKKeyOpsValue(m_exec, jwkUsages, operation, ASCIILiteral("unwrapKey"), CryptoKeyUsageUnwrapKey)) + return; + if (!tryJWKKeyOpsValue(m_exec, jwkUsages, operation, ASCIILiteral("deriveKey"), CryptoKeyUsageDeriveKey)) + return; + if (!tryJWKKeyOpsValue(m_exec, jwkUsages, operation, ASCIILiteral("deriveBits"), CryptoKeyUsageDeriveBits)) + return; + } + } else { + RETURN_IF_EXCEPTION(scope, void()); + + String jwkUseString; + if (!getStringFromJSON(m_exec, m_json.get(), "use", jwkUseString)) { + // We have neither key_ops nor use. + return; + } + + if (jwkUseString == "enc") + jwkUsages |= (CryptoKeyUsageEncrypt | CryptoKeyUsageDecrypt | CryptoKeyUsageWrapKey | CryptoKeyUsageUnwrapKey); + else if (jwkUseString == "sig") + jwkUsages |= (CryptoKeyUsageSign | CryptoKeyUsageVerify); + else { + throwTypeError(m_exec, scope, "Unsupported JWK key use value \"" + jwkUseString + "\""); + return; + } + } + + suggestedUsages = suggestedUsages & jwkUsages; +} + +void JSCryptoKeySerializationJWK::reconcileExtractable(bool& suggestedExtractable) const +{ + bool jwkExtractable; + if (!getBooleanFromJSON(m_exec, m_json.get(), "ext", jwkExtractable)) + return; + + suggestedExtractable = suggestedExtractable && jwkExtractable; +} + +bool JSCryptoKeySerializationJWK::keySizeIsValid(size_t sizeInBits) const +{ + if (m_jwkAlgorithmName == "HS256") + return sizeInBits >= 256; + if (m_jwkAlgorithmName == "HS384") + return sizeInBits >= 384; + if (m_jwkAlgorithmName == "HS512") + return sizeInBits >= 512; + if (m_jwkAlgorithmName == "A128CBC") + return sizeInBits == 128; + if (m_jwkAlgorithmName == "A192CBC") + return sizeInBits == 192; + if (m_jwkAlgorithmName == "A256CBC") + return sizeInBits == 256; + if (m_jwkAlgorithmName == "A128KW") + return sizeInBits == 128; + if (m_jwkAlgorithmName == "A192KW") + return sizeInBits == 192; + if (m_jwkAlgorithmName == "A256KW") + return sizeInBits == 256; + if (m_jwkAlgorithmName == "RS256") + return sizeInBits >= 2048; + if (m_jwkAlgorithmName == "RS384") + return sizeInBits >= 2048; + if (m_jwkAlgorithmName == "RS512") + return sizeInBits >= 2048; + if (m_jwkAlgorithmName == "RSA1_5") + return sizeInBits >= 2048; + if (m_jwkAlgorithmName == "RSA_OAEP") + return sizeInBits >= 2048; + return true; +} + +std::unique_ptr<CryptoKeyData> JSCryptoKeySerializationJWK::keyDataOctetSequence() const +{ + VM& vm = m_exec->vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + + String keyBase64URL; + if (!getStringFromJSON(m_exec, m_json.get(), "k", keyBase64URL)) { + if (!scope.exception()) + throwTypeError(m_exec, scope, ASCIILiteral("Secret key data is not present is JWK")); + return nullptr; + } + + Vector<uint8_t> octetSequence; + if (!base64URLDecode(keyBase64URL, octetSequence)) { + throwTypeError(m_exec, scope, ASCIILiteral("Cannot decode base64url key data in JWK")); + return nullptr; + } + + if (!keySizeIsValid(octetSequence.size() * 8)) { + throwTypeError(m_exec, scope, "Key size is not valid for " + m_jwkAlgorithmName); + return nullptr; + } + + return std::make_unique<CryptoKeyDataOctetSequence>(octetSequence); +} + +std::unique_ptr<CryptoKeyData> JSCryptoKeySerializationJWK::keyDataRSAComponents() const +{ + VM& vm = m_exec->vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + + Vector<uint8_t> modulus; + Vector<uint8_t> exponent; + Vector<uint8_t> privateExponent; + + if (!getBigIntegerVectorFromJSON(m_exec, m_json.get(), "n", modulus)) { + if (!scope.exception()) + throwTypeError(m_exec, scope, ASCIILiteral("Required JWK \"n\" member is missing")); + return nullptr; + } + + if (!keySizeIsValid(modulus.size() * 8)) { + throwTypeError(m_exec, scope, "Key size is not valid for " + m_jwkAlgorithmName); + return nullptr; + } + + if (!getBigIntegerVectorFromJSON(m_exec, m_json.get(), "e", exponent)) { + if (!scope.exception()) + throwTypeError(m_exec, scope, ASCIILiteral("Required JWK \"e\" member is missing")); + return nullptr; + } + + if (!getBigIntegerVectorFromJSON(m_exec, m_json.get(), "d", modulus)) { + RETURN_IF_EXCEPTION(scope, nullptr); + return CryptoKeyDataRSAComponents::createPublic(modulus, exponent); + } + + CryptoKeyDataRSAComponents::PrimeInfo firstPrimeInfo; + CryptoKeyDataRSAComponents::PrimeInfo secondPrimeInfo; + Vector<CryptoKeyDataRSAComponents::PrimeInfo> otherPrimeInfos; + if (!getBigIntegerVectorFromJSON(m_exec, m_json.get(), "p", firstPrimeInfo.primeFactor)) { + RETURN_IF_EXCEPTION(scope, nullptr); + return CryptoKeyDataRSAComponents::createPrivate(modulus, exponent, privateExponent); + } + + if (!getBigIntegerVectorFromJSON(m_exec, m_json.get(), "dp", firstPrimeInfo.factorCRTExponent)) { + RETURN_IF_EXCEPTION(scope, nullptr); + return CryptoKeyDataRSAComponents::createPrivate(modulus, exponent, privateExponent); + } + + if (!getBigIntegerVectorFromJSON(m_exec, m_json.get(), "q", secondPrimeInfo.primeFactor)) { + RETURN_IF_EXCEPTION(scope, nullptr); + return CryptoKeyDataRSAComponents::createPrivate(modulus, exponent, privateExponent); + } + + if (!getBigIntegerVectorFromJSON(m_exec, m_json.get(), "dq", secondPrimeInfo.factorCRTExponent)) { + RETURN_IF_EXCEPTION(scope, nullptr); + return CryptoKeyDataRSAComponents::createPrivate(modulus, exponent, privateExponent); + } + + if (!getBigIntegerVectorFromJSON(m_exec, m_json.get(), "qi", secondPrimeInfo.factorCRTCoefficient)) { + RETURN_IF_EXCEPTION(scope, nullptr); + return CryptoKeyDataRSAComponents::createPrivate(modulus, exponent, privateExponent); + } + + JSArray* otherPrimeInfoJSArray; + if (!getJSArrayFromJSON(m_exec, m_json.get(), "oth", otherPrimeInfoJSArray)) { + RETURN_IF_EXCEPTION(scope, nullptr); + return CryptoKeyDataRSAComponents::createPrivateWithAdditionalData(modulus, exponent, privateExponent, firstPrimeInfo, secondPrimeInfo, otherPrimeInfos); + } + + for (size_t i = 0; i < otherPrimeInfoJSArray->length(); ++i) { + CryptoKeyDataRSAComponents::PrimeInfo info; + JSValue element = otherPrimeInfoJSArray->getIndex(m_exec, i); + RETURN_IF_EXCEPTION(scope, nullptr); + if (!element.isObject()) { + throwTypeError(m_exec, scope, ASCIILiteral("JWK \"oth\" array member is not an object")); + return nullptr; + } + if (!getBigIntegerVectorFromJSON(m_exec, asObject(element), "r", info.primeFactor)) { + if (!scope.exception()) + throwTypeError(m_exec, scope, ASCIILiteral("Cannot get prime factor for a prime in \"oth\" dictionary")); + return nullptr; + } + if (!getBigIntegerVectorFromJSON(m_exec, asObject(element), "d", info.factorCRTExponent)) { + if (!scope.exception()) + throwTypeError(m_exec, scope, ASCIILiteral("Cannot get factor CRT exponent for a prime in \"oth\" dictionary")); + return nullptr; + } + if (!getBigIntegerVectorFromJSON(m_exec, asObject(element), "t", info.factorCRTCoefficient)) { + if (!scope.exception()) + throwTypeError(m_exec, scope, ASCIILiteral("Cannot get factor CRT coefficient for a prime in \"oth\" dictionary")); + return nullptr; + } + otherPrimeInfos.append(info); + } + + return CryptoKeyDataRSAComponents::createPrivateWithAdditionalData(modulus, exponent, privateExponent, firstPrimeInfo, secondPrimeInfo, otherPrimeInfos); +} + +std::unique_ptr<CryptoKeyData> JSCryptoKeySerializationJWK::keyData() const +{ + VM& vm = m_exec->vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + + String jwkKeyType; + if (!getStringFromJSON(m_exec, m_json.get(), "kty", jwkKeyType)) { + if (!scope.exception()) + throwTypeError(m_exec, scope, ASCIILiteral("Required JWK \"kty\" member is missing")); + return nullptr; + } + + if (jwkKeyType == "oct") + return keyDataOctetSequence(); + + if (jwkKeyType == "RSA") + return keyDataRSAComponents(); + + throwTypeError(m_exec, scope, "Unsupported JWK key type " + jwkKeyType); + return nullptr; +} + +static void addToJSON(ExecState* exec, JSObject* json, const char* key, const String& value) +{ + VM& vm = exec->vm(); + Identifier identifier = Identifier::fromString(&vm, key); + json->putDirect(vm, identifier, jsString(exec, value)); +} + +static void buildJSONForOctetSequence(ExecState* exec, const Vector<uint8_t>& keyData, JSObject* result) +{ + addToJSON(exec, result, "kty", "oct"); + addToJSON(exec, result, "k", base64URLEncode(keyData)); +} + +static void buildJSONForRSAComponents(JSC::ExecState* exec, const CryptoKeyDataRSAComponents& data, JSC::JSObject* result) +{ + VM& vm = exec->vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + + addToJSON(exec, result, "kty", "RSA"); + addToJSON(exec, result, "n", base64URLEncode(data.modulus())); + addToJSON(exec, result, "e", base64URLEncode(data.exponent())); + + if (data.type() == CryptoKeyDataRSAComponents::Type::Public) + return; + + addToJSON(exec, result, "d", base64URLEncode(data.privateExponent())); + + if (!data.hasAdditionalPrivateKeyParameters()) + return; + + addToJSON(exec, result, "p", base64URLEncode(data.firstPrimeInfo().primeFactor)); + addToJSON(exec, result, "q", base64URLEncode(data.secondPrimeInfo().primeFactor)); + addToJSON(exec, result, "dp", base64URLEncode(data.firstPrimeInfo().factorCRTExponent)); + addToJSON(exec, result, "dq", base64URLEncode(data.secondPrimeInfo().factorCRTExponent)); + addToJSON(exec, result, "qi", base64URLEncode(data.secondPrimeInfo().factorCRTCoefficient)); + + if (data.otherPrimeInfos().isEmpty()) + return; + + JSArray* oth = constructEmptyArray(exec, 0, exec->lexicalGlobalObject(), data.otherPrimeInfos().size()); + RETURN_IF_EXCEPTION(scope, void()); + for (size_t i = 0, size = data.otherPrimeInfos().size(); i < size; ++i) { + JSObject* jsPrimeInfo = constructEmptyObject(exec); + addToJSON(exec, jsPrimeInfo, "r", base64URLEncode(data.otherPrimeInfos()[i].primeFactor)); + addToJSON(exec, jsPrimeInfo, "d", base64URLEncode(data.otherPrimeInfos()[i].factorCRTExponent)); + addToJSON(exec, jsPrimeInfo, "t", base64URLEncode(data.otherPrimeInfos()[i].factorCRTCoefficient)); + oth->putDirectIndex(exec, i, jsPrimeInfo); + RETURN_IF_EXCEPTION(scope, void()); + } + result->putDirect(vm, Identifier::fromString(exec, "oth"), oth); +} + +static void addBoolToJSON(ExecState* exec, JSObject* json, const char* key, bool value) +{ + VM& vm = exec->vm(); + Identifier identifier = Identifier::fromString(&vm, key); + json->putDirect(vm, identifier, jsBoolean(value)); +} + +static void addJWKAlgorithmToJSON(ExecState* exec, JSObject* json, const CryptoKey& key) +{ + VM& vm = exec->vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + + String jwkAlgorithm; + switch (key.algorithmIdentifier()) { + case CryptoAlgorithmIdentifier::HMAC: + switch (downcast<CryptoKeyHMAC>(key).hashAlgorithmIdentifier()) { + case CryptoAlgorithmIdentifier::SHA_256: + if (downcast<CryptoKeyHMAC>(key).key().size() * 8 >= 256) + jwkAlgorithm = "HS256"; + break; + case CryptoAlgorithmIdentifier::SHA_384: + if (downcast<CryptoKeyHMAC>(key).key().size() * 8 >= 384) + jwkAlgorithm = "HS384"; + break; + case CryptoAlgorithmIdentifier::SHA_512: + if (downcast<CryptoKeyHMAC>(key).key().size() * 8 >= 512) + jwkAlgorithm = "HS512"; + break; + default: + break; + } + break; + case CryptoAlgorithmIdentifier::AES_CBC: + switch (downcast<CryptoKeyAES>(key).key().size() * 8) { + case 128: + jwkAlgorithm = "A128CBC"; + break; + case 192: + jwkAlgorithm = "A192CBC"; + break; + case 256: + jwkAlgorithm = "A256CBC"; + break; + } + break; + case CryptoAlgorithmIdentifier::AES_KW: + switch (downcast<CryptoKeyAES>(key).key().size() * 8) { + case 128: + jwkAlgorithm = "A128KW"; + break; + case 192: + jwkAlgorithm = "A192KW"; + break; + case 256: + jwkAlgorithm = "A256KW"; + break; + } + break; + case CryptoAlgorithmIdentifier::RSASSA_PKCS1_v1_5: { + const CryptoKeyRSA& rsaKey = downcast<CryptoKeyRSA>(key); + CryptoAlgorithmIdentifier hash; + if (!rsaKey.isRestrictedToHash(hash)) + break; + if (rsaKey.keySizeInBits() < 2048) + break; + switch (hash) { + case CryptoAlgorithmIdentifier::SHA_256: + jwkAlgorithm = "RS256"; + break; + case CryptoAlgorithmIdentifier::SHA_384: + jwkAlgorithm = "RS384"; + break; + case CryptoAlgorithmIdentifier::SHA_512: + jwkAlgorithm = "RS512"; + break; + default: + break; + } + break; + } + case CryptoAlgorithmIdentifier::RSAES_PKCS1_v1_5: { + const CryptoKeyRSA& rsaKey = downcast<CryptoKeyRSA>(key); + if (rsaKey.keySizeInBits() < 2048) + break; + jwkAlgorithm = "RSA1_5"; + break; + } + case CryptoAlgorithmIdentifier::RSA_OAEP: { + const CryptoKeyRSA& rsaKey = downcast<CryptoKeyRSA>(key); + CryptoAlgorithmIdentifier hash; + // WebCrypto RSA-OAEP keys are not tied to any particular hash, unless previously imported from JWK, which only supports SHA-1. + if (rsaKey.isRestrictedToHash(hash) && hash != CryptoAlgorithmIdentifier::SHA_1) + break; + if (rsaKey.keySizeInBits() < 2048) + break; + jwkAlgorithm = "RSA-OAEP"; + break; + } + default: + break; + } + + if (jwkAlgorithm.isNull()) { + // The spec doesn't currently tell whether export should fail, or just skip "alg" (which is an optional key in JWK). + throwTypeError(exec, scope, ASCIILiteral("Key algorithm and size do not map to any JWK algorithm identifier")); + return; + } + + addToJSON(exec, json, "alg", jwkAlgorithm); +} + +static void addUsagesToJSON(ExecState* exec, JSObject* json, CryptoKeyUsageBitmap usages) +{ + VM& vm = exec->vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + JSArray* keyOps = constructEmptyArray(exec, 0, exec->lexicalGlobalObject(), 0); + RETURN_IF_EXCEPTION(scope, void()); + + unsigned index = 0; + if (usages & CryptoKeyUsageSign) { + keyOps->putDirectIndex(exec, index++, jsNontrivialString(exec, ASCIILiteral("sign"))); + RETURN_IF_EXCEPTION(scope, void()); + } + if (usages & CryptoKeyUsageVerify) { + keyOps->putDirectIndex(exec, index++, jsNontrivialString(exec, ASCIILiteral("verify"))); + RETURN_IF_EXCEPTION(scope, void()); + } + if (usages & CryptoKeyUsageEncrypt) { + keyOps->putDirectIndex(exec, index++, jsNontrivialString(exec, ASCIILiteral("encrypt"))); + RETURN_IF_EXCEPTION(scope, void()); + } + if (usages & CryptoKeyUsageDecrypt) { + keyOps->putDirectIndex(exec, index++, jsNontrivialString(exec, ASCIILiteral("decrypt"))); + RETURN_IF_EXCEPTION(scope, void()); + } + if (usages & CryptoKeyUsageWrapKey) { + keyOps->putDirectIndex(exec, index++, jsNontrivialString(exec, ASCIILiteral("wrapKey"))); + RETURN_IF_EXCEPTION(scope, void()); + } + if (usages & CryptoKeyUsageUnwrapKey) { + keyOps->putDirectIndex(exec, index++, jsNontrivialString(exec, ASCIILiteral("unwrapKey"))); + RETURN_IF_EXCEPTION(scope, void()); + } + if (usages & CryptoKeyUsageDeriveKey) { + keyOps->putDirectIndex(exec, index++, jsNontrivialString(exec, ASCIILiteral("deriveKey"))); + RETURN_IF_EXCEPTION(scope, void()); + } + if (usages & CryptoKeyUsageDeriveBits) { + keyOps->putDirectIndex(exec, index++, jsNontrivialString(exec, ASCIILiteral("deriveBits"))); + RETURN_IF_EXCEPTION(scope, void()); + } + + json->putDirect(vm, Identifier::fromString(exec, "key_ops"), keyOps); +} + +String JSCryptoKeySerializationJWK::serialize(ExecState* exec, const CryptoKey& key) +{ + VM& vm = exec->vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + + std::unique_ptr<CryptoKeyData> keyData = key.exportData(); + if (!keyData) { + // This generally shouldn't happen as long as all key types implement exportData(), but as underlying libraries return errors, there may be some rare failure conditions. + throwTypeError(exec, scope, ASCIILiteral("Couldn't export key material")); + return String(); + } + + JSObject* result = constructEmptyObject(exec); + + addJWKAlgorithmToJSON(exec, result, key); + RETURN_IF_EXCEPTION(scope, String()); + + addBoolToJSON(exec, result, "ext", key.extractable()); + + addUsagesToJSON(exec, result, key.usagesBitmap()); + RETURN_IF_EXCEPTION(scope, String()); + + if (is<CryptoKeyDataOctetSequence>(*keyData)) + buildJSONForOctetSequence(exec, downcast<CryptoKeyDataOctetSequence>(*keyData).octetSequence(), result); + else if (is<CryptoKeyDataRSAComponents>(*keyData)) + buildJSONForRSAComponents(exec, downcast<CryptoKeyDataRSAComponents>(*keyData), result); + else { + throwTypeError(exec, scope, ASCIILiteral("Key doesn't support exportKey")); + return String(); + } + RETURN_IF_EXCEPTION(scope, String()); + + return JSONStringify(exec, result, 0); +} + +} // namespace WebCore + +#endif // ENABLE(SUBTLE_CRYPTO) diff --git a/Source/WebCore/bindings/js/JSCryptoKeySerializationJWK.h b/Source/WebCore/bindings/js/JSCryptoKeySerializationJWK.h new file mode 100644 index 000000000..47a5a03be --- /dev/null +++ b/Source/WebCore/bindings/js/JSCryptoKeySerializationJWK.h @@ -0,0 +1,73 @@ +/* + * Copyright (C) 2013 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +#if ENABLE(SUBTLE_CRYPTO) + +#include "CryptoKeySerialization.h" +#include <heap/Strong.h> +#include <wtf/text/WTFString.h> + +namespace JSC { +class ExecState; +class JSObject; +} + +namespace WebCore { + +class CryptoAlgorithmParametersDeprecated; +class CryptoKey; +class CryptoKeyDataRSAComponents; + +class JSCryptoKeySerializationJWK final : public CryptoKeySerialization { +WTF_MAKE_NONCOPYABLE(JSCryptoKeySerializationJWK); +public: + JSCryptoKeySerializationJWK(JSC::ExecState*, const String&); + virtual ~JSCryptoKeySerializationJWK(); + + static String serialize(JSC::ExecState* exec, const CryptoKey&); + +private: + std::optional<CryptoAlgorithmPair> reconcileAlgorithm(CryptoAlgorithm*, CryptoAlgorithmParametersDeprecated*) const override; + + void reconcileUsages(CryptoKeyUsageBitmap&) const override; + void reconcileExtractable(bool&) const override; + + std::unique_ptr<CryptoKeyData> keyData() const override; + + bool keySizeIsValid(size_t sizeInBits) const; + std::unique_ptr<CryptoKeyData> keyDataOctetSequence() const; + std::unique_ptr<CryptoKeyData> keyDataRSAComponents() const; + + JSC::ExecState* m_exec; + JSC::Strong<JSC::JSObject> m_json; + + mutable String m_jwkAlgorithmName; // Stored when reconcileAlgorithm is called, and used later. +}; + +} // namespace WebCore + +#endif // ENABLE(SUBTLE_CRYPTO) diff --git a/Source/WebCore/bindings/js/JSCryptoOperationData.cpp b/Source/WebCore/bindings/js/JSCryptoOperationData.cpp new file mode 100644 index 000000000..2e35f2e14 --- /dev/null +++ b/Source/WebCore/bindings/js/JSCryptoOperationData.cpp @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2013, 2016 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "JSCryptoOperationData.h" + +#if ENABLE(SUBTLE_CRYPTO) + +#include "JSDOMConvertBufferSource.h" +#include <heap/HeapInlines.h> + +using namespace JSC; + +namespace WebCore { + +CryptoOperationData cryptoOperationDataFromJSValue(ExecState& state, ThrowScope& scope, JSValue value) +{ + VM& vm = state.vm(); + if (auto* buffer = toUnsharedArrayBuffer(vm, value)) + return { static_cast<uint8_t*>(buffer->data()), buffer->byteLength() }; + + if (auto bufferView = toUnsharedArrayBufferView(vm, value)) + return { static_cast<uint8_t*>(bufferView->baseAddress()), bufferView->byteLength() }; + + throwTypeError(&state, scope, ASCIILiteral("Only ArrayBuffer and ArrayBufferView objects can be passed as CryptoOperationData")); + return { }; +} + +} // namespace WebCore + +#endif // ENABLE(SUBTLE_CRYPTO) diff --git a/Source/WebCore/bindings/js/JSCryptoOperationData.h b/Source/WebCore/bindings/js/JSCryptoOperationData.h new file mode 100644 index 000000000..909e13242 --- /dev/null +++ b/Source/WebCore/bindings/js/JSCryptoOperationData.h @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2013 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +#if ENABLE(SUBTLE_CRYPTO) + +namespace JSC { +class ExecState; +class JSValue; +class ThrowScope; +} + +namespace WebCore { + +using CryptoOperationData = std::pair<const uint8_t*, size_t>; + +CryptoOperationData cryptoOperationDataFromJSValue(JSC::ExecState&, JSC::ThrowScope&, JSC::JSValue); + +} // namespace WebCore + +#endif // ENABLE(SUBTLE_CRYPTO) diff --git a/Source/WebCore/bindings/js/JSCustomElementInterface.cpp b/Source/WebCore/bindings/js/JSCustomElementInterface.cpp new file mode 100644 index 000000000..793ecb842 --- /dev/null +++ b/Source/WebCore/bindings/js/JSCustomElementInterface.cpp @@ -0,0 +1,315 @@ +/* + * Copyright (C) 2013 Google Inc. All rights reserved. + * Copyright (C) 2015-2016 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#include "config.h" +#include "JSCustomElementInterface.h" + +#include "DOMWrapperWorld.h" +#include "HTMLUnknownElement.h" +#include "JSDOMBinding.h" +#include "JSDOMGlobalObject.h" +#include "JSElement.h" +#include "JSHTMLElement.h" +#include "JSMainThreadExecState.h" +#include "JSMainThreadExecStateInstrumentation.h" +#include "ScriptExecutionContext.h" +#include <heap/WeakInlines.h> +#include <runtime/JSLock.h> + +using namespace JSC; + +namespace WebCore { + +JSCustomElementInterface::JSCustomElementInterface(const QualifiedName& name, JSObject* constructor, JSDOMGlobalObject* globalObject) + : ActiveDOMCallback(globalObject->scriptExecutionContext()) + , m_name(name) + , m_constructor(constructor) + , m_isolatedWorld(&globalObject->world()) +{ +} + +JSCustomElementInterface::~JSCustomElementInterface() +{ +} + +static RefPtr<Element> constructCustomElementSynchronously(Document&, VM&, ExecState&, JSObject* constructor, const AtomicString& localName); + +Ref<Element> JSCustomElementInterface::constructElementWithFallback(Document& document, const AtomicString& localName) +{ + if (auto element = tryToConstructCustomElement(document, localName)) + return element.releaseNonNull(); + + auto element = HTMLUnknownElement::create(QualifiedName(nullAtom, localName, HTMLNames::xhtmlNamespaceURI), document); + element->setIsCustomElementUpgradeCandidate(); + element->setIsFailedCustomElement(*this); + + return WTFMove(element); +} + +Ref<Element> JSCustomElementInterface::constructElementWithFallback(Document& document, const QualifiedName& name) +{ + if (auto element = tryToConstructCustomElement(document, name.localName())) { + if (name.prefix() != nullAtom) + element->setPrefix(name.prefix()); + return element.releaseNonNull(); + } + + auto element = HTMLUnknownElement::create(name, document); + element->setIsCustomElementUpgradeCandidate(); + element->setIsFailedCustomElement(*this); + + return WTFMove(element); +} + +RefPtr<Element> JSCustomElementInterface::tryToConstructCustomElement(Document& document, const AtomicString& localName) +{ + if (!canInvokeCallback()) + return nullptr; + + Ref<JSCustomElementInterface> protectedThis(*this); + + VM& vm = m_isolatedWorld->vm(); + JSLockHolder lock(vm); + auto scope = DECLARE_CATCH_SCOPE(vm); + + if (!m_constructor) + return nullptr; + + ASSERT(&document == scriptExecutionContext()); + auto& state = *document.execState(); + auto element = constructCustomElementSynchronously(document, vm, state, m_constructor.get(), localName); + ASSERT(!!scope.exception() == !element); + if (!element) { + auto* exception = scope.exception(); + scope.clearException(); + reportException(&state, exception); + return nullptr; + } + + return element; +} + +// https://dom.spec.whatwg.org/#concept-create-element +// 6. 1. If the synchronous custom elements flag is set +static RefPtr<Element> constructCustomElementSynchronously(Document& document, VM& vm, ExecState& state, JSObject* constructor, const AtomicString& localName) +{ + auto scope = DECLARE_THROW_SCOPE(vm); + ConstructData constructData; + ConstructType constructType = constructor->methodTable()->getConstructData(constructor, constructData); + if (constructType == ConstructType::None) { + ASSERT_NOT_REACHED(); + return nullptr; + } + + InspectorInstrumentationCookie cookie = JSMainThreadExecState::instrumentFunctionConstruct(&document, constructType, constructData); + MarkedArgumentBuffer args; + JSValue newElement = construct(&state, constructor, constructType, constructData, args); + InspectorInstrumentation::didCallFunction(cookie, &document); + RETURN_IF_EXCEPTION(scope, nullptr); + + ASSERT(!newElement.isEmpty()); + HTMLElement* wrappedElement = JSHTMLElement::toWrapped(vm, newElement); + if (!wrappedElement) { + throwTypeError(&state, scope, ASCIILiteral("The result of constructing a custom element must be a HTMLElement")); + return nullptr; + } + + if (wrappedElement->hasAttributes()) { + throwNotSupportedError(state, scope, ASCIILiteral("A newly constructed custom element must not have attributes")); + return nullptr; + } + if (wrappedElement->hasChildNodes()) { + throwNotSupportedError(state, scope, ASCIILiteral("A newly constructed custom element must not have child nodes")); + return nullptr; + } + if (wrappedElement->parentNode()) { + throwNotSupportedError(state, scope, ASCIILiteral("A newly constructed custom element must not have a parent node")); + return nullptr; + } + if (&wrappedElement->document() != &document) { + throwNotSupportedError(state, scope, ASCIILiteral("A newly constructed custom element belongs to a wrong docuemnt")); + return nullptr; + } + ASSERT(wrappedElement->namespaceURI() == HTMLNames::xhtmlNamespaceURI); + if (wrappedElement->localName() != localName) { + throwNotSupportedError(state, scope, ASCIILiteral("A newly constructed custom element belongs to a wrong docuemnt")); + return nullptr; + } + + return wrappedElement; +} + +void JSCustomElementInterface::upgradeElement(Element& element) +{ + ASSERT(element.tagQName() == name()); + ASSERT(element.isCustomElementUpgradeCandidate()); + if (!canInvokeCallback()) + return; + + Ref<JSCustomElementInterface> protectedThis(*this); + VM& vm = m_isolatedWorld->vm(); + JSLockHolder lock(vm); + auto scope = DECLARE_THROW_SCOPE(vm); + + if (!m_constructor) + return; + + ScriptExecutionContext* context = scriptExecutionContext(); + if (!context) + return; + ASSERT(context->isDocument()); + JSDOMGlobalObject* globalObject = toJSDOMGlobalObject(context, *m_isolatedWorld); + ExecState* state = globalObject->globalExec(); + RETURN_IF_EXCEPTION(scope, void()); + + ConstructData constructData; + ConstructType constructType = m_constructor->methodTable()->getConstructData(m_constructor.get(), constructData); + if (constructType == ConstructType::None) { + ASSERT_NOT_REACHED(); + return; + } + + CustomElementReactionQueue::enqueuePostUpgradeReactions(element); + + m_constructionStack.append(&element); + + MarkedArgumentBuffer args; + InspectorInstrumentationCookie cookie = JSMainThreadExecState::instrumentFunctionConstruct(context, constructType, constructData); + JSValue returnedElement = construct(state, m_constructor.get(), constructType, constructData, args); + InspectorInstrumentation::didCallFunction(cookie, context); + + m_constructionStack.removeLast(); + + if (UNLIKELY(scope.exception())) { + element.setIsFailedCustomElement(*this); + reportException(state, scope.exception()); + return; + } + + Element* wrappedElement = JSElement::toWrapped(vm, returnedElement); + if (!wrappedElement || wrappedElement != &element) { + element.setIsFailedCustomElement(*this); + reportException(state, createDOMException(state, INVALID_STATE_ERR, "Custom element constructor failed to upgrade an element")); + return; + } + element.setIsDefinedCustomElement(*this); +} + +void JSCustomElementInterface::invokeCallback(Element& element, JSObject* callback, const WTF::Function<void(ExecState*, JSDOMGlobalObject*, MarkedArgumentBuffer&)>& addArguments) +{ + if (!canInvokeCallback()) + return; + + auto* context = scriptExecutionContext(); + if (!context) + return; + + Ref<JSCustomElementInterface> protectedThis(*this); + JSLockHolder lock(m_isolatedWorld->vm()); + + ASSERT(context); + ASSERT(context->isDocument()); + JSDOMGlobalObject* globalObject = toJSDOMGlobalObject(context, *m_isolatedWorld); + ExecState* state = globalObject->globalExec(); + + JSObject* jsElement = asObject(toJS(state, globalObject, element)); + + CallData callData; + CallType callType = callback->methodTable()->getCallData(callback, callData); + ASSERT(callType != CallType::None); + + MarkedArgumentBuffer args; + addArguments(state, globalObject, args); + + InspectorInstrumentationCookie cookie = JSMainThreadExecState::instrumentFunctionCall(context, callType, callData); + + NakedPtr<JSC::Exception> exception; + JSMainThreadExecState::call(state, callback, callType, callData, jsElement, args, exception); + + InspectorInstrumentation::didCallFunction(cookie, context); + + if (exception) + reportException(state, exception); +} + +void JSCustomElementInterface::setConnectedCallback(JSC::JSObject* callback) +{ + m_connectedCallback = callback; +} + +void JSCustomElementInterface::invokeConnectedCallback(Element& element) +{ + invokeCallback(element, m_connectedCallback.get()); +} + +void JSCustomElementInterface::setDisconnectedCallback(JSC::JSObject* callback) +{ + m_disconnectedCallback = callback; +} + +void JSCustomElementInterface::invokeDisconnectedCallback(Element& element) +{ + invokeCallback(element, m_disconnectedCallback.get()); +} + +void JSCustomElementInterface::setAdoptedCallback(JSC::JSObject* callback) +{ + m_adoptedCallback = callback; +} + +void JSCustomElementInterface::invokeAdoptedCallback(Element& element, Document& oldDocument, Document& newDocument) +{ + invokeCallback(element, m_adoptedCallback.get(), [&](ExecState* state, JSDOMGlobalObject* globalObject, MarkedArgumentBuffer& args) { + args.append(toJS(state, globalObject, oldDocument)); + args.append(toJS(state, globalObject, newDocument)); + }); +} + +void JSCustomElementInterface::setAttributeChangedCallback(JSC::JSObject* callback, const Vector<String>& observedAttributes) +{ + m_attributeChangedCallback = callback; + m_observedAttributes.clear(); + for (auto& name : observedAttributes) + m_observedAttributes.add(name); +} + +void JSCustomElementInterface::invokeAttributeChangedCallback(Element& element, const QualifiedName& attributeName, const AtomicString& oldValue, const AtomicString& newValue) +{ + invokeCallback(element, m_attributeChangedCallback.get(), [&](ExecState* state, JSDOMGlobalObject*, MarkedArgumentBuffer& args) { + args.append(toJS<IDLDOMString>(*state, attributeName.localName())); + args.append(toJS<IDLNullable<IDLDOMString>>(*state, oldValue)); + args.append(toJS<IDLNullable<IDLDOMString>>(*state, newValue)); + args.append(toJS<IDLNullable<IDLDOMString>>(*state, attributeName.namespaceURI())); + }); +} + +void JSCustomElementInterface::didUpgradeLastElementInConstructionStack() +{ + m_constructionStack.last() = nullptr; +} + +} // namespace WebCore diff --git a/Source/WebCore/bindings/js/JSCustomElementInterface.h b/Source/WebCore/bindings/js/JSCustomElementInterface.h new file mode 100644 index 000000000..8a3f656ee --- /dev/null +++ b/Source/WebCore/bindings/js/JSCustomElementInterface.h @@ -0,0 +1,111 @@ +/* + * Copyright (C) 2013 Google Inc. All rights reserved. + * Copyright (C) 2015, 2016 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +#include "ActiveDOMCallback.h" +#include "QualifiedName.h" +#include <heap/Weak.h> +#include <heap/WeakInlines.h> +#include <runtime/JSObject.h> +#include <wtf/Forward.h> +#include <wtf/Function.h> +#include <wtf/RefCounted.h> +#include <wtf/RefPtr.h> +#include <wtf/text/AtomicStringHash.h> + +namespace JSC { +class JSObject; +class PrivateName; +} + +namespace WebCore { + +class DOMWrapperWorld; +class Document; +class Element; +class JSDOMGlobalObject; +class MathMLElement; +class SVGElement; + +class JSCustomElementInterface : public RefCounted<JSCustomElementInterface>, public ActiveDOMCallback { +public: + static Ref<JSCustomElementInterface> create(const QualifiedName& name, JSC::JSObject* callback, JSDOMGlobalObject* globalObject) + { + return adoptRef(*new JSCustomElementInterface(name, callback, globalObject)); + } + + Ref<Element> constructElementWithFallback(Document&, const AtomicString&); + Ref<Element> constructElementWithFallback(Document&, const QualifiedName&); + + void upgradeElement(Element&); + + void setConnectedCallback(JSC::JSObject*); + bool hasConnectedCallback() const { return !!m_connectedCallback; } + void invokeConnectedCallback(Element&); + + void setDisconnectedCallback(JSC::JSObject*); + bool hasDisconnectedCallback() const { return !!m_disconnectedCallback; } + void invokeDisconnectedCallback(Element&); + + void setAdoptedCallback(JSC::JSObject*); + bool hasAdoptedCallback() const { return !!m_adoptedCallback; } + void invokeAdoptedCallback(Element&, Document& oldDocument, Document& newDocument); + + void setAttributeChangedCallback(JSC::JSObject* callback, const Vector<String>& observedAttributes); + bool observesAttribute(const AtomicString& name) const { return m_observedAttributes.contains(name); } + void invokeAttributeChangedCallback(Element&, const QualifiedName&, const AtomicString& oldValue, const AtomicString& newValue); + + ScriptExecutionContext* scriptExecutionContext() const { return ContextDestructionObserver::scriptExecutionContext(); } + JSC::JSObject* constructor() { return m_constructor.get(); } + + const QualifiedName& name() const { return m_name; } + + bool isUpgradingElement() const { return !m_constructionStack.isEmpty(); } + Element* lastElementInConstructionStack() const { return m_constructionStack.last().get(); } + void didUpgradeLastElementInConstructionStack(); + + virtual ~JSCustomElementInterface(); + +private: + JSCustomElementInterface(const QualifiedName&, JSC::JSObject* callback, JSDOMGlobalObject*); + + RefPtr<Element> tryToConstructCustomElement(Document&, const AtomicString&); + + void invokeCallback(Element&, JSC::JSObject* callback, const WTF::Function<void(JSC::ExecState*, JSDOMGlobalObject*, JSC::MarkedArgumentBuffer&)>& addArguments = { }); + + QualifiedName m_name; + JSC::Weak<JSC::JSObject> m_constructor; + JSC::Weak<JSC::JSObject> m_connectedCallback; + JSC::Weak<JSC::JSObject> m_disconnectedCallback; + JSC::Weak<JSC::JSObject> m_adoptedCallback; + JSC::Weak<JSC::JSObject> m_attributeChangedCallback; + RefPtr<DOMWrapperWorld> m_isolatedWorld; + Vector<RefPtr<Element>, 1> m_constructionStack; + HashSet<AtomicString> m_observedAttributes; +}; + +} // namespace WebCore diff --git a/Source/WebCore/bindings/js/JSCustomElementRegistryCustom.cpp b/Source/WebCore/bindings/js/JSCustomElementRegistryCustom.cpp new file mode 100644 index 000000000..cf9e96d27 --- /dev/null +++ b/Source/WebCore/bindings/js/JSCustomElementRegistryCustom.cpp @@ -0,0 +1,216 @@ +/* + * Copyright (C) 2015, 2016 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "JSCustomElementRegistry.h" + +#include "CustomElementRegistry.h" +#include "Document.h" +#include "HTMLNames.h" +#include "JSCustomElementInterface.h" +#include "JSDOMBinding.h" +#include "JSDOMConvert.h" +#include "JSDOMPromise.h" + +using namespace JSC; + +namespace WebCore { + +static JSObject* getCustomElementCallback(ExecState& state, JSObject& prototype, const Identifier& id) +{ + VM& vm = state.vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + + JSValue callback = prototype.get(&state, id); + RETURN_IF_EXCEPTION(scope, nullptr); + if (callback.isUndefined()) + return nullptr; + if (!callback.isFunction()) { + throwTypeError(&state, scope, ASCIILiteral("A custom element callback must be a function")); + return nullptr; + } + return callback.getObject(); +} + +static bool validateCustomElementNameAndThrowIfNeeded(ExecState& state, const AtomicString& name) +{ + auto scope = DECLARE_THROW_SCOPE(state.vm()); + + switch (Document::validateCustomElementName(name)) { + case CustomElementNameValidationStatus::Valid: + return true; + case CustomElementNameValidationStatus::ConflictsWithBuiltinNames: + throwSyntaxError(&state, scope, ASCIILiteral("Custom element name cannot be same as one of the builtin elements")); + return false; + case CustomElementNameValidationStatus::NoHyphen: + throwSyntaxError(&state, scope, ASCIILiteral("Custom element name must contain a hyphen")); + return false; + case CustomElementNameValidationStatus::ContainsUpperCase: + throwSyntaxError(&state, scope, ASCIILiteral("Custom element name cannot contain an upper case letter")); + return false; + } + ASSERT_NOT_REACHED(); + return false; +} + +// https://html.spec.whatwg.org/#dom-customelementregistry-define +JSValue JSCustomElementRegistry::define(ExecState& state) +{ + VM& vm = state.vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + + if (UNLIKELY(state.argumentCount() < 2)) + return throwException(&state, scope, createNotEnoughArgumentsError(&state)); + + AtomicString localName(state.uncheckedArgument(0).toString(&state)->toAtomicString(&state)); + RETURN_IF_EXCEPTION(scope, JSValue()); + + JSValue constructorValue = state.uncheckedArgument(1); + if (!constructorValue.isConstructor()) + return throwTypeError(&state, scope, ASCIILiteral("The second argument must be a constructor")); + JSObject* constructor = constructorValue.getObject(); + + if (!validateCustomElementNameAndThrowIfNeeded(state, localName)) + return jsUndefined(); + + CustomElementRegistry& registry = wrapped(); + + if (registry.elementDefinitionIsRunning()) { + throwNotSupportedError(state, scope, ASCIILiteral("Cannot define a custom element while defining another custom element")); + return jsUndefined(); + } + SetForScope<bool> change(registry.elementDefinitionIsRunning(), true); + + if (registry.findInterface(localName)) { + throwNotSupportedError(state, scope, ASCIILiteral("Cannot define multiple custom elements with the same tag name")); + return jsUndefined(); + } + + if (registry.containsConstructor(constructor)) { + throwNotSupportedError(state, scope, ASCIILiteral("Cannot define multiple custom elements with the same class")); + return jsUndefined(); + } + + JSValue prototypeValue = constructor->get(&state, vm.propertyNames->prototype); + RETURN_IF_EXCEPTION(scope, JSValue()); + if (!prototypeValue.isObject()) + return throwTypeError(&state, scope, ASCIILiteral("Custom element constructor's prototype must be an object")); + JSObject& prototypeObject = *asObject(prototypeValue); + + QualifiedName name(nullAtom, localName, HTMLNames::xhtmlNamespaceURI); + auto elementInterface = JSCustomElementInterface::create(name, constructor, globalObject()); + + auto* connectedCallback = getCustomElementCallback(state, prototypeObject, Identifier::fromString(&vm, "connectedCallback")); + if (connectedCallback) + elementInterface->setConnectedCallback(connectedCallback); + RETURN_IF_EXCEPTION(scope, JSValue()); + + auto* disconnectedCallback = getCustomElementCallback(state, prototypeObject, Identifier::fromString(&vm, "disconnectedCallback")); + if (disconnectedCallback) + elementInterface->setDisconnectedCallback(disconnectedCallback); + RETURN_IF_EXCEPTION(scope, JSValue()); + + auto* adoptedCallback = getCustomElementCallback(state, prototypeObject, Identifier::fromString(&vm, "adoptedCallback")); + if (adoptedCallback) + elementInterface->setAdoptedCallback(adoptedCallback); + RETURN_IF_EXCEPTION(scope, JSValue()); + + auto* attributeChangedCallback = getCustomElementCallback(state, prototypeObject, Identifier::fromString(&vm, "attributeChangedCallback")); + RETURN_IF_EXCEPTION(scope, JSValue()); + if (attributeChangedCallback) { + auto observedAttributesValue = constructor->get(&state, Identifier::fromString(&state, "observedAttributes")); + RETURN_IF_EXCEPTION(scope, JSValue()); + if (!observedAttributesValue.isUndefined()) { + auto observedAttributes = convert<IDLSequence<IDLDOMString>>(state, observedAttributesValue); + RETURN_IF_EXCEPTION(scope, JSValue()); + elementInterface->setAttributeChangedCallback(attributeChangedCallback, observedAttributes); + } + } + + auto addToGlobalObjectWithPrivateName = [&] (JSObject* objectToAdd) { + if (objectToAdd) { + PrivateName uniquePrivateName; + globalObject()->putDirect(vm, uniquePrivateName, objectToAdd); + } + }; + + addToGlobalObjectWithPrivateName(constructor); + addToGlobalObjectWithPrivateName(connectedCallback); + addToGlobalObjectWithPrivateName(disconnectedCallback); + addToGlobalObjectWithPrivateName(adoptedCallback); + addToGlobalObjectWithPrivateName(attributeChangedCallback); + + registry.addElementDefinition(WTFMove(elementInterface)); + + return jsUndefined(); +} + +// https://html.spec.whatwg.org/#dom-customelementregistry-whendefined +static JSValue whenDefinedPromise(ExecState& state, JSDOMGlobalObject& globalObject, CustomElementRegistry& registry, JSPromiseDeferred& promiseDeferred) +{ + auto scope = DECLARE_THROW_SCOPE(state.vm()); + + if (UNLIKELY(state.argumentCount() < 1)) + return throwException(&state, scope, createNotEnoughArgumentsError(&state)); + + AtomicString localName(state.uncheckedArgument(0).toString(&state)->toAtomicString(&state)); + RETURN_IF_EXCEPTION(scope, JSValue()); + + if (!validateCustomElementNameAndThrowIfNeeded(state, localName)) { + ASSERT(scope.exception()); + return jsUndefined(); + } + + if (registry.findInterface(localName)) { + DeferredPromise::create(globalObject, promiseDeferred)->resolve(); + return promiseDeferred.promise(); + } + + auto result = registry.promiseMap().ensure(localName, [&] { + return DeferredPromise::create(globalObject, promiseDeferred); + }); + + return result.iterator->value->promise(); +} + +JSValue JSCustomElementRegistry::whenDefined(ExecState& state) +{ + auto scope = DECLARE_CATCH_SCOPE(state.vm()); + + ASSERT(globalObject()); + auto promiseDeferred = JSPromiseDeferred::create(&state, globalObject()); + ASSERT(promiseDeferred); + JSValue promise = whenDefinedPromise(state, *globalObject(), wrapped(), *promiseDeferred); + + if (UNLIKELY(scope.exception())) { + rejectPromiseWithExceptionIfAny(state, *globalObject(), *promiseDeferred); + ASSERT(!scope.exception()); + return promiseDeferred->promise(); + } + + return promise; +} + +} diff --git a/Source/WebCore/bindings/js/JSRTCStatsResponseCustom.cpp b/Source/WebCore/bindings/js/JSCustomEventCustom.cpp index 821dc1b1f..8cfb769f4 100644 --- a/Source/WebCore/bindings/js/JSRTCStatsResponseCustom.cpp +++ b/Source/WebCore/bindings/js/JSCustomEventCustom.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) Research In Motion Limited 2013. All rights reserved. + * Copyright (C) 2015 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -24,28 +24,37 @@ */ #include "config.h" +#include "JSCustomEvent.h" -#if ENABLE(MEDIA_STREAM) -#include "JSRTCStatsResponse.h" - -#include "JSRTCStatsReport.h" -#include <wtf/text/AtomicString.h> +#include "CustomEvent.h" +#include "DOMWrapperWorld.h" +#include <runtime/JSCInlines.h> +#include <runtime/JSCJSValue.h> +#include <runtime/Structure.h> using namespace JSC; namespace WebCore { - -bool JSRTCStatsResponse::canGetItemsForName(ExecState*, RTCStatsResponse* response, PropertyName propertyName) -{ - return response->canGetItemsForName(propertyNameToAtomicString(propertyName)); -} - -EncodedJSValue JSRTCStatsResponse::nameGetter(ExecState* exec, EncodedJSValue slotBase, EncodedJSValue, PropertyName propertyName) + +JSValue JSCustomEvent::detail(ExecState& state) const { - JSRTCStatsResponse* thisObj = jsCast<JSRTCStatsResponse*>(JSValue::decode(slotBase)); - return JSValue::encode(toJS(exec, thisObj->globalObject(), thisObj->impl().namedItem(propertyNameToAtomicString(propertyName)))); + auto& event = wrapped(); + + auto detail = event.detail(); + if (!detail) + return jsNull(); + + if (detail.isObject() && &worldForDOMObject(detail.getObject()) != ¤tWorld(&state)) { + // We need to make sure CustomEvents do not leak their detail property across isolated DOM worlds. + // Ideally, we would check that the worlds have different privileges but that's not possible yet. + auto serializedDetail = event.trySerializeDetail(state); + if (!serializedDetail) + return jsNull(); + return serializedDetail->deserialize(state, globalObject()); + } + + return detail; } } // namespace WebCore -#endif // ENABLE(MEDIA_STREAM) diff --git a/Source/WebCore/bindings/js/JSCustomXPathNSResolver.cpp b/Source/WebCore/bindings/js/JSCustomXPathNSResolver.cpp index f1b63f85a..2f14dff6b 100644 --- a/Source/WebCore/bindings/js/JSCustomXPathNSResolver.cpp +++ b/Source/WebCore/bindings/js/JSCustomXPathNSResolver.cpp @@ -10,10 +10,10 @@ * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * - * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR @@ -26,14 +26,14 @@ #include "config.h" #include "JSCustomXPathNSResolver.h" +#include "CommonVM.h" #include "Document.h" -#include "ExceptionCode.h" #include "Frame.h" +#include "JSDOMExceptionHandling.h" #include "JSDOMWindowCustom.h" #include "JSMainThreadExecState.h" #include "Page.h" -#include "PageConsole.h" -#include "SecurityOrigin.h" +#include "PageConsoleClient.h" #include <runtime/JSLock.h> #include <wtf/Ref.h> @@ -41,23 +41,21 @@ namespace WebCore { using namespace JSC; -PassRefPtr<JSCustomXPathNSResolver> JSCustomXPathNSResolver::create(ExecState* exec, JSValue value) +ExceptionOr<Ref<JSCustomXPathNSResolver>> JSCustomXPathNSResolver::create(ExecState& state, JSValue value) { if (value.isUndefinedOrNull()) - return 0; + return Exception { TypeError }; - JSObject* resolverObject = value.getObject(); - if (!resolverObject) { - setDOMException(exec, TYPE_MISMATCH_ERR); - return 0; - } + auto* resolverObject = value.getObject(); + if (!resolverObject) + return Exception { TYPE_MISMATCH_ERR }; - return adoptRef(new JSCustomXPathNSResolver(exec, resolverObject, asJSDOMWindow(exec->vmEntryGlobalObject()))); + return adoptRef(*new JSCustomXPathNSResolver(state.vm(), resolverObject, asJSDOMWindow(state.vmEntryGlobalObject()))); } -JSCustomXPathNSResolver::JSCustomXPathNSResolver(ExecState* exec, JSObject* customResolver, JSDOMWindow* globalObject) - : m_customResolver(exec->vm(), customResolver) - , m_globalObject(exec->vm(), globalObject) +JSCustomXPathNSResolver::JSCustomXPathNSResolver(VM& vm, JSObject* customResolver, JSDOMWindow* globalObject) + : m_customResolver(vm, customResolver) + , m_globalObject(vm, globalObject) { } @@ -69,37 +67,37 @@ String JSCustomXPathNSResolver::lookupNamespaceURI(const String& prefix) { ASSERT(m_customResolver); - JSLockHolder lock(JSDOMWindowBase::commonVM()); + JSLockHolder lock(commonVM()); ExecState* exec = m_globalObject->globalExec(); - JSValue function = m_customResolver->get(exec, Identifier(exec, "lookupNamespaceURI")); + JSValue function = m_customResolver->get(exec, Identifier::fromString(exec, "lookupNamespaceURI")); CallData callData; CallType callType = getCallData(function, callData); - if (callType == CallTypeNone) { + if (callType == CallType::None) { callType = m_customResolver->methodTable()->getCallData(m_customResolver.get(), callData); - if (callType == CallTypeNone) { - // FIXME: <http://webkit.org/b/114312> JSCustomXPathNSResolver::lookupNamespaceURI Console Message should include Line, Column, and SourceURL - if (PageConsole* console = m_globalObject->impl().pageConsole()) - console->addMessage(JSMessageSource, ErrorMessageLevel, "XPathNSResolver does not have a lookupNamespaceURI method."); + if (callType == CallType::None) { + if (PageConsoleClient* console = m_globalObject->wrapped().console()) + console->addMessage(MessageSource::JS, MessageLevel::Error, ASCIILiteral("XPathNSResolver does not have a lookupNamespaceURI method.")); return String(); } function = m_customResolver.get(); } - Ref<JSCustomXPathNSResolver> selfProtector(*this); + Ref<JSCustomXPathNSResolver> protectedThis(*this); MarkedArgumentBuffer args; args.append(jsStringWithCache(exec, prefix)); - JSValue retval = JSMainThreadExecState::call(exec, function, callType, callData, m_customResolver.get(), args); + NakedPtr<JSC::Exception> exception; + JSValue retval = JSMainThreadExecState::call(exec, function, callType, callData, m_customResolver.get(), args, exception); String result; - if (exec->hadException()) - reportCurrentException(exec); + if (exception) + reportException(exec, exception); else { if (!retval.isUndefinedOrNull()) - result = retval.toString(exec)->value(exec); + result = retval.toWTFString(exec); } return result; diff --git a/Source/WebCore/bindings/js/JSCustomXPathNSResolver.h b/Source/WebCore/bindings/js/JSCustomXPathNSResolver.h index 7e218e8b7..4cee8d316 100644 --- a/Source/WebCore/bindings/js/JSCustomXPathNSResolver.h +++ b/Source/WebCore/bindings/js/JSCustomXPathNSResolver.h @@ -10,10 +10,10 @@ * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * - * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR @@ -23,43 +23,32 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef JSCustomXPathNSResolver_h -#define JSCustomXPathNSResolver_h +#pragma once +#include "ExceptionOr.h" #include "XPathNSResolver.h" #include <heap/Strong.h> #include <heap/StrongInlines.h> +#include <runtime/JSCInlines.h> #include <runtime/JSCJSValue.h> -#include <runtime/Operations.h> -#include <wtf/Forward.h> -#include <wtf/RefPtr.h> - -namespace JSC { - class ExecState; - class JSObject; -} namespace WebCore { - class Frame; - class JSDOMWindow; +class JSDOMWindow; - class JSCustomXPathNSResolver : public XPathNSResolver { - public: - static PassRefPtr<JSCustomXPathNSResolver> create(JSC::ExecState*, JSC::JSValue); - - virtual ~JSCustomXPathNSResolver(); +class JSCustomXPathNSResolver final : public XPathNSResolver { +public: + static ExceptionOr<Ref<JSCustomXPathNSResolver>> create(JSC::ExecState&, JSC::JSValue); + virtual ~JSCustomXPathNSResolver(); - virtual String lookupNamespaceURI(const String& prefix); +private: + JSCustomXPathNSResolver(JSC::VM&, JSC::JSObject*, JSDOMWindow*); - private: - JSCustomXPathNSResolver(JSC::ExecState*, JSC::JSObject*, JSDOMWindow*); + String lookupNamespaceURI(const String& prefix) final; - // JSCustomXPathNSResolvers are always temporary so using a Strong reference is safe here. - JSC::Strong<JSC::JSObject> m_customResolver; - JSC::Strong<JSDOMWindow> m_globalObject; - }; + // JSCustomXPathNSResolvers are always temporary so using a Strong reference is safe here. + JSC::Strong<JSC::JSObject> m_customResolver; + JSC::Strong<JSDOMWindow> m_globalObject; +}; } // namespace WebCore - -#endif // JSCustomXPathNSResolver_h diff --git a/Source/WebCore/bindings/js/JSDOMBinding.cpp b/Source/WebCore/bindings/js/JSDOMBinding.cpp deleted file mode 100644 index a32d332ad..000000000 --- a/Source/WebCore/bindings/js/JSDOMBinding.cpp +++ /dev/null @@ -1,536 +0,0 @@ -/* - * Copyright (C) 1999-2001 Harri Porten (porten@kde.org) - * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2013 Apple Inc. All rights reserved. - * Copyright (C) 2007 Samuel Weinig <sam@webkit.org> - * Copyright (C) 2013 Michael Pruett <michael@68k.org> - * - * 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 - */ - -#include "config.h" -#include "JSDOMBinding.h" - -#include "CachedScript.h" -#include "DOMConstructorWithDocument.h" -#include "DOMObjectHashTableMap.h" -#include "DOMStringList.h" -#include "ExceptionCode.h" -#include "ExceptionHeaders.h" -#include "ExceptionInterfaces.h" -#include "Frame.h" -#include "HTMLParserIdioms.h" -#include "JSDOMWindowCustom.h" -#include "JSExceptionBase.h" -#include "SecurityOrigin.h" -#include "ScriptCallStack.h" -#include "ScriptCallStackFactory.h" -#include <interpreter/Interpreter.h> -#include <runtime/DateInstance.h> -#include <runtime/Error.h> -#include <runtime/ExceptionHelpers.h> -#include <runtime/JSFunction.h> -#include <wtf/MathExtras.h> - -using namespace JSC; - -namespace WebCore { - -STATIC_ASSERT_IS_TRIVIALLY_DESTRUCTIBLE(DOMConstructorObject); -STATIC_ASSERT_IS_TRIVIALLY_DESTRUCTIBLE(DOMConstructorWithDocument); - -void addImpureProperty(const AtomicString& propertyName) -{ - JSDOMWindow::commonVM()->addImpureProperty(propertyName); -} - -const JSC::HashTable& getHashTableForGlobalData(VM& vm, const JSC::HashTable& staticTable) -{ - return DOMObjectHashTableMap::mapFor(vm).get(staticTable); -} - -JSValue jsStringOrNull(ExecState* exec, const String& s) -{ - if (s.isNull()) - return jsNull(); - return jsStringWithCache(exec, s); -} - -JSValue jsOwnedStringOrNull(ExecState* exec, const String& s) -{ - if (s.isNull()) - return jsNull(); - return jsOwnedString(exec, s); -} - -JSValue jsStringOrUndefined(ExecState* exec, const String& s) -{ - if (s.isNull()) - return jsUndefined(); - return jsStringWithCache(exec, s); -} - -JSValue jsString(ExecState* exec, const URL& url) -{ - return jsStringWithCache(exec, url.string()); -} - -JSValue jsStringOrNull(ExecState* exec, const URL& url) -{ - if (url.isNull()) - return jsNull(); - return jsStringWithCache(exec, url.string()); -} - -JSValue jsStringOrUndefined(ExecState* exec, const URL& url) -{ - if (url.isNull()) - return jsUndefined(); - return jsStringWithCache(exec, url.string()); -} - -AtomicStringImpl* findAtomicString(PropertyName propertyName) -{ - StringImpl* impl = propertyName.publicName(); - if (!impl) - return 0; - ASSERT(impl->existingHash()); - return AtomicString::find(impl); -} - -String valueToStringWithNullCheck(ExecState* exec, JSValue value) -{ - if (value.isNull()) - return String(); - return value.toString(exec)->value(exec); -} - -String valueToStringWithUndefinedOrNullCheck(ExecState* exec, JSValue value) -{ - if (value.isUndefinedOrNull()) - return String(); - return value.toString(exec)->value(exec); -} - -JSValue jsDateOrNull(ExecState* exec, double value) -{ - if (!std::isfinite(value)) - return jsNull(); - return DateInstance::create(exec->vm(), exec->lexicalGlobalObject()->dateStructure(), value); -} - -double valueToDate(ExecState* exec, JSValue value) -{ - if (value.isNumber()) - return value.asNumber(); - if (!value.inherits(DateInstance::info())) - return std::numeric_limits<double>::quiet_NaN(); - return static_cast<DateInstance*>(value.toObject(exec))->internalNumber(); -} - -JSC::JSValue jsArray(JSC::ExecState* exec, JSDOMGlobalObject* globalObject, PassRefPtr<DOMStringList> stringList) -{ - JSC::MarkedArgumentBuffer list; - if (stringList) { - for (unsigned i = 0; i < stringList->length(); ++i) - list.append(jsStringWithCache(exec, stringList->item(i))); - } - return JSC::constructArray(exec, 0, globalObject, list); -} - -void reportException(ExecState* exec, JSValue exception, CachedScript* cachedScript) -{ - if (isTerminatedExecutionException(exception)) - return; - - Interpreter::ErrorHandlingMode mode(exec); - - RefPtr<ScriptCallStack> callStack(createScriptCallStackFromException(exec, exception, ScriptCallStack::maxCallStackSizeToCapture)); - exec->clearException(); - exec->clearSupplementaryExceptionInfo(); - - JSDOMGlobalObject* globalObject = jsCast<JSDOMGlobalObject*>(exec->lexicalGlobalObject()); - if (JSDOMWindow* window = jsDynamicCast<JSDOMWindow*>(globalObject)) { - if (!window->impl().isCurrentlyDisplayedInFrame()) - return; - } - - int lineNumber = 0; - int columnNumber = 0; - String exceptionSourceURL; - if (callStack->size()) { - const ScriptCallFrame& frame = callStack->at(0); - lineNumber = frame.lineNumber(); - columnNumber = frame.columnNumber(); - exceptionSourceURL = frame.sourceURL(); - } else { - // There may not be an exceptionStack for a <script> SyntaxError. Fallback to getting at least the line and sourceURL from the exception. - JSObject* exceptionObject = exception.toObject(exec); - JSValue lineValue = exceptionObject->getDirect(exec->vm(), Identifier(exec, "line")); - lineNumber = lineValue && lineValue.isNumber() ? int(lineValue.toNumber(exec)) : 0; - JSValue columnValue = exceptionObject->getDirect(exec->vm(), Identifier(exec, "column")); - columnNumber = columnValue && columnValue.isNumber() ? int(columnValue.toNumber(exec)) : 0; - JSValue sourceURLValue = exceptionObject->getDirect(exec->vm(), Identifier(exec, "sourceURL")); - exceptionSourceURL = sourceURLValue && sourceURLValue.isString() ? sourceURLValue.toString(exec)->value(exec) : ASCIILiteral("undefined"); - } - - String errorMessage; - if (ExceptionBase* exceptionBase = toExceptionBase(exception)) - errorMessage = exceptionBase->message() + ": " + exceptionBase->description(); - else { - // FIXME: <http://webkit.org/b/115087> Web Inspector: WebCore::reportException should not evaluate JavaScript handling exceptions - // If this is a custon exception object, call toString on it to try and get a nice string representation for the exception. - errorMessage = exception.toString(exec)->value(exec); - exec->clearException(); - exec->clearSupplementaryExceptionInfo(); - } - - ScriptExecutionContext* scriptExecutionContext = globalObject->scriptExecutionContext(); - scriptExecutionContext->reportException(errorMessage, lineNumber, columnNumber, exceptionSourceURL, callStack->size() ? callStack : 0, cachedScript); -} - -void reportCurrentException(ExecState* exec) -{ - JSValue exception = exec->exception(); - exec->clearException(); - reportException(exec, exception); -} - -#define TRY_TO_CREATE_EXCEPTION(interfaceName) \ - case interfaceName##Type: \ - errorObject = toJS(exec, globalObject, interfaceName::create(description)); \ - break; - -void setDOMException(ExecState* exec, ExceptionCode ec) -{ - if (!ec || exec->hadException()) - return; - - // FIXME: Handle other WebIDL exception types. - if (ec == TypeError) { - throwTypeError(exec); - return; - } - - // FIXME: All callers to setDOMException need to pass in the right global object - // for now, we're going to assume the lexicalGlobalObject. Which is wrong in cases like this: - // frames[0].document.createElement(null, null); // throws an exception which should have the subframes prototypes. - JSDOMGlobalObject* globalObject = deprecatedGlobalObjectForPrototype(exec); - - ExceptionCodeDescription description(ec); - - JSValue errorObject; - switch (description.type) { - DOM_EXCEPTION_INTERFACES_FOR_EACH(TRY_TO_CREATE_EXCEPTION) - } - - ASSERT(errorObject); - exec->vm().throwException(exec, errorObject); -} - -#undef TRY_TO_CREATE_EXCEPTION - -bool shouldAllowAccessToNode(ExecState* exec, Node* node) -{ - return BindingSecurity::shouldAllowAccessToNode(exec, node); -} - -bool shouldAllowAccessToFrame(ExecState* exec, Frame* target) -{ - return BindingSecurity::shouldAllowAccessToFrame(exec, target); -} - -bool shouldAllowAccessToFrame(ExecState* exec, Frame* frame, String& message) -{ - if (!frame) - return false; - if (BindingSecurity::shouldAllowAccessToFrame(exec, frame, DoNotReportSecurityError)) - return true; - message = frame->document()->domWindow()->crossDomainAccessErrorMessage(activeDOMWindow(exec)); - return false; -} - -bool shouldAllowAccessToDOMWindow(ExecState* exec, DOMWindow& target, String& message) -{ - if (BindingSecurity::shouldAllowAccessToDOMWindow(exec, target, DoNotReportSecurityError)) - return true; - message = target.crossDomainAccessErrorMessage(activeDOMWindow(exec)); - return false; -} - -void printErrorMessageForFrame(Frame* frame, const String& message) -{ - if (!frame) - return; - frame->document()->domWindow()->printErrorMessage(message); -} - -EncodedJSValue objectToStringFunctionGetter(ExecState* exec, EncodedJSValue, EncodedJSValue, PropertyName propertyName) -{ - return JSValue::encode(JSFunction::create(exec->vm(), exec->lexicalGlobalObject(), 0, propertyName.publicName(), objectProtoFuncToString)); -} - -Structure* getCachedDOMStructure(JSDOMGlobalObject* globalObject, const ClassInfo* classInfo) -{ - JSDOMStructureMap& structures = globalObject->structures(); - return structures.get(classInfo).get(); -} - -Structure* cacheDOMStructure(JSDOMGlobalObject* globalObject, Structure* structure, const ClassInfo* classInfo) -{ - JSDOMStructureMap& structures = globalObject->structures(); - ASSERT(!structures.contains(classInfo)); - return structures.set(classInfo, WriteBarrier<Structure>(globalObject->vm(), globalObject, structure)).iterator->value.get(); -} - -static const int32_t kMaxInt32 = 0x7fffffff; -static const int32_t kMinInt32 = -kMaxInt32 - 1; -static const uint32_t kMaxUInt32 = 0xffffffffU; -static const int64_t kJSMaxInteger = 0x20000000000000LL - 1; // 2^53 - 1, largest integer exactly representable in ECMAScript. - -static double enforceRange(ExecState* exec, double x, double minimum, double maximum) -{ - if (std::isnan(x) || std::isinf(x)) { - throwTypeError(exec); - return 0; - } - x = trunc(x); - if (x < minimum || x > maximum) { - throwTypeError(exec); - return 0; - } - return x; -} - -template <typename T> -struct IntTypeLimits { -}; - -template <> -struct IntTypeLimits<int8_t> { - static const int8_t minValue = -128; - static const int8_t maxValue = 127; - static const unsigned numberOfValues = 256; // 2^8 -}; - -template <> -struct IntTypeLimits<uint8_t> { - static const uint8_t maxValue = 255; - static const unsigned numberOfValues = 256; // 2^8 -}; - -template <> -struct IntTypeLimits<int16_t> { - static const short minValue = -32768; - static const short maxValue = 32767; - static const unsigned numberOfValues = 65536; // 2^16 -}; - -template <> -struct IntTypeLimits<uint16_t> { - static const unsigned short maxValue = 65535; - static const unsigned numberOfValues = 65536; // 2^16 -}; - -template <typename T> -static inline T toSmallerInt(ExecState* exec, JSValue value, IntegerConversionConfiguration configuration) -{ - typedef IntTypeLimits<T> LimitsTrait; - // Fast path if the value is already a 32-bit signed integer in the right range. - if (value.isInt32()) { - int32_t d = value.asInt32(); - if (d >= LimitsTrait::minValue && d <= LimitsTrait::maxValue) - return static_cast<T>(d); - if (configuration == EnforceRange) { - throwTypeError(exec); - return 0; - } - d %= LimitsTrait::numberOfValues; - return static_cast<T>(d > LimitsTrait::maxValue ? d - LimitsTrait::numberOfValues : d); - } - - double x = value.toNumber(exec); - if (exec->hadException()) - return 0; - - if (configuration == EnforceRange) - return enforceRange(exec, x, LimitsTrait::minValue, LimitsTrait::maxValue); - - if (std::isnan(x) || std::isinf(x) || !x) - return 0; - - x = x < 0 ? -floor(fabs(x)) : floor(fabs(x)); - x = fmod(x, LimitsTrait::numberOfValues); - - return static_cast<T>(x > LimitsTrait::maxValue ? x - LimitsTrait::numberOfValues : x); -} - -template <typename T> -static inline T toSmallerUInt(ExecState* exec, JSValue value, IntegerConversionConfiguration configuration) -{ - typedef IntTypeLimits<T> LimitsTrait; - // Fast path if the value is already a 32-bit unsigned integer in the right range. - if (value.isUInt32()) { - uint32_t d = value.asUInt32(); - if (d <= LimitsTrait::maxValue) - return static_cast<T>(d); - if (configuration == EnforceRange) { - throwTypeError(exec); - return 0; - } - return static_cast<T>(d); - } - - double x = value.toNumber(exec); - if (exec->hadException()) - return 0; - - if (configuration == EnforceRange) - return enforceRange(exec, x, 0, LimitsTrait::maxValue); - - if (std::isnan(x) || std::isinf(x) || !x) - return 0; - - x = x < 0 ? -floor(fabs(x)) : floor(fabs(x)); - return static_cast<T>(fmod(x, LimitsTrait::numberOfValues)); -} - -// http://www.w3.org/TR/WebIDL/#es-byte -int8_t toInt8(ExecState* exec, JSValue value, IntegerConversionConfiguration configuration) -{ - return toSmallerInt<int8_t>(exec, value, configuration); -} - -// http://www.w3.org/TR/WebIDL/#es-octet -uint8_t toUInt8(ExecState* exec, JSValue value, IntegerConversionConfiguration configuration) -{ - return toSmallerUInt<uint8_t>(exec, value, configuration); -} - -// http://www.w3.org/TR/WebIDL/#es-short -int16_t toInt16(ExecState* exec, JSValue value, IntegerConversionConfiguration configuration) -{ - return toSmallerInt<int16_t>(exec, value, configuration); -} - -// http://www.w3.org/TR/WebIDL/#es-unsigned-short -uint16_t toUInt16(ExecState* exec, JSValue value, IntegerConversionConfiguration configuration) -{ - return toSmallerUInt<uint16_t>(exec, value, configuration); -} - -// http://www.w3.org/TR/WebIDL/#es-long -int32_t toInt32EnforceRange(ExecState* exec, JSValue value) -{ - if (value.isInt32()) - return value.asInt32(); - - double x = value.toNumber(exec); - if (exec->hadException()) - return 0; - return enforceRange(exec, x, kMinInt32, kMaxInt32); -} - -// http://www.w3.org/TR/WebIDL/#es-unsigned-long -uint32_t toUInt32EnforceRange(ExecState* exec, JSValue value) -{ - if (value.isUInt32()) - return value.asUInt32(); - - double x = value.toNumber(exec); - if (exec->hadException()) - return 0; - return enforceRange(exec, x, 0, kMaxUInt32); -} - -// http://www.w3.org/TR/WebIDL/#es-long-long -int64_t toInt64(ExecState* exec, JSValue value, IntegerConversionConfiguration configuration) -{ - if (value.isInt32()) - return value.asInt32(); - - double x = value.toNumber(exec); - if (exec->hadException()) - return 0; - - if (configuration == EnforceRange) - return enforceRange(exec, x, -kJSMaxInteger, kJSMaxInteger); - - // Map NaNs and +/-Infinity to 0; convert finite values modulo 2^64. - unsigned long long n; - doubleToInteger(x, n); - return n; -} - -// http://www.w3.org/TR/WebIDL/#es-unsigned-long-long -uint64_t toUInt64(ExecState* exec, JSValue value, IntegerConversionConfiguration configuration) -{ - if (value.isUInt32()) - return value.asUInt32(); - - double x = value.toNumber(exec); - if (exec->hadException()) - return 0; - - if (configuration == EnforceRange) - return enforceRange(exec, x, 0, kJSMaxInteger); - - // Map NaNs and +/-Infinity to 0; convert finite values modulo 2^64. - unsigned long long n; - doubleToInteger(x, n); - return n; -} - -DOMWindow& activeDOMWindow(ExecState* exec) -{ - return asJSDOMWindow(exec->lexicalGlobalObject())->impl(); -} - -DOMWindow& firstDOMWindow(ExecState* exec) -{ - return asJSDOMWindow(exec->vmEntryGlobalObject())->impl(); -} - -static inline bool canAccessDocument(JSC::ExecState* state, Document* targetDocument, SecurityReportingOption reportingOption = ReportSecurityError) -{ - if (!targetDocument) - return false; - - DOMWindow& active = activeDOMWindow(state); - - if (active.document()->securityOrigin()->canAccess(targetDocument->securityOrigin())) - return true; - - if (reportingOption == ReportSecurityError) - printErrorMessageForFrame(targetDocument->frame(), targetDocument->domWindow()->crossDomainAccessErrorMessage(active)); - - return false; -} - -bool BindingSecurity::shouldAllowAccessToDOMWindow(JSC::ExecState* state, DOMWindow& target, SecurityReportingOption reportingOption) -{ - return canAccessDocument(state, target.document(), reportingOption); -} - -bool BindingSecurity::shouldAllowAccessToFrame(JSC::ExecState* state, Frame* target, SecurityReportingOption reportingOption) -{ - return target && canAccessDocument(state, target->document(), reportingOption); -} - -bool BindingSecurity::shouldAllowAccessToNode(JSC::ExecState* state, Node* target) -{ - return target && canAccessDocument(state, &target->document()); -} - -} // namespace WebCore diff --git a/Source/WebCore/bindings/js/JSDOMBinding.h b/Source/WebCore/bindings/js/JSDOMBinding.h index 097ce6b26..34890157c 100644 --- a/Source/WebCore/bindings/js/JSDOMBinding.h +++ b/Source/WebCore/bindings/js/JSDOMBinding.h @@ -1,6 +1,6 @@ /* * 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) 2003-2006, 2008-2009, 2013, 2016 Apple Inc. All rights reserved. * Copyright (C) 2007 Samuel Weinig <sam@webkit.org> * Copyright (C) 2009 Google, Inc. All rights reserved. * Copyright (C) 2012 Ericsson AB. All rights reserved. @@ -21,653 +21,24 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#ifndef JSDOMBinding_h -#define JSDOMBinding_h +#pragma once -#include "JSDOMGlobalObject.h" -#include "JSDOMWrapper.h" -#include "DOMWrapperWorld.h" -#include "ScriptWrappable.h" -#include "ScriptWrappableInlines.h" -#include "WebCoreTypedArrayController.h" +// FIXME: Remove this header. + +#include "ExceptionOr.h" +#include "JSDOMWrapperCache.h" #include <cstddef> -#include <heap/Weak.h> -#include <heap/WeakInlines.h> -#include <runtime/Error.h> -#include <runtime/FunctionPrototype.h> +#include <heap/HeapInlines.h> +#include <heap/SlotVisitorInlines.h> +#include <runtime/AuxiliaryBarrierInlines.h> #include <runtime/JSArray.h> -#include <runtime/JSArrayBuffer.h> -#include <runtime/JSDataView.h> -#include <runtime/JSTypedArrays.h> +#include <runtime/JSCJSValueInlines.h> +#include <runtime/JSCellInlines.h> +#include <runtime/JSObjectInlines.h> #include <runtime/Lookup.h> -#include <runtime/ObjectPrototype.h> -#include <runtime/Operations.h> -#include <runtime/TypedArrayInlines.h> -#include <runtime/TypedArrays.h> +#include <runtime/ObjectConstructor.h> +#include <runtime/StructureInlines.h> +#include <runtime/WriteBarrier.h> #include <wtf/Forward.h> -#include <wtf/Noncopyable.h> +#include <wtf/GetPtr.h> #include <wtf/Vector.h> - -namespace JSC { -class HashEntry; -} - -namespace WebCore { - -class DOMStringList; - -class CachedScript; -class Document; -class DOMWindow; -class Frame; -class HTMLDocument; -class URL; -class Node; - -typedef int ExceptionCode; - -DOMWindow& activeDOMWindow(JSC::ExecState*); -DOMWindow& firstDOMWindow(JSC::ExecState*); - -// Base class for all constructor objects in the JSC bindings. -class DOMConstructorObject : public JSDOMWrapper { - typedef JSDOMWrapper Base; -public: - 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: - static const unsigned StructureFlags = JSC::ImplementsHasInstance | JSC::OverridesVisitChildren | JSDOMWrapper::StructureFlags; - DOMConstructorObject(JSC::Structure* structure, JSDOMGlobalObject* globalObject) - : JSDOMWrapper(structure, globalObject) - { - } -}; - -JSC::Structure* getCachedDOMStructure(JSDOMGlobalObject*, const JSC::ClassInfo*); -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<JSDOMGlobalObject*>(exec->lexicalGlobalObject()); -} - -template<class WrapperClass> 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<class WrapperClass> 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<WrapperClass>(exec->vm(), deprecatedGlobalObjectForPrototype(exec)); -} - -template<class WrapperClass> inline JSC::JSObject* getDOMPrototype(JSC::VM& vm, JSC::JSGlobalObject* globalObject) -{ - return JSC::jsCast<JSC::JSObject*>(asObject(getDOMStructure<WrapperClass>(vm, JSC::jsCast<JSDOMGlobalObject*>(globalObject))->storedPrototype())); -} - -inline JSC::WeakHandleOwner* wrapperOwner(DOMWrapperWorld& world, JSC::ArrayBuffer*) -{ - return static_cast<WebCoreTypedArrayController*>(world.vm()->m_typedArrayController.get())->wrapperOwner(); -} - -inline void* wrapperContext(DOMWrapperWorld& world, JSC::ArrayBuffer*) -{ - return &world; -} - -inline JSDOMWrapper* getInlineCachedWrapper(DOMWrapperWorld&, void*) { return 0; } -inline bool setInlineCachedWrapper(DOMWrapperWorld&, void*, JSDOMWrapper*, JSC::WeakHandleOwner*, void*) { return false; } -inline bool clearInlineCachedWrapper(DOMWrapperWorld&, void*, JSDOMWrapper*) { return false; } - -inline JSDOMWrapper* getInlineCachedWrapper(DOMWrapperWorld& world, ScriptWrappable* domObject) -{ - if (!world.isNormal()) - return 0; - return domObject->wrapper(); -} - -inline JSC::JSArrayBuffer* getInlineCachedWrapper(DOMWrapperWorld& world, JSC::ArrayBuffer* buffer) -{ - if (!world.isNormal()) - return 0; - return buffer->m_wrapper.get(); -} - -inline bool setInlineCachedWrapper(DOMWrapperWorld& world, ScriptWrappable* domObject, JSDOMWrapper* wrapper, JSC::WeakHandleOwner* wrapperOwner, void* context) -{ - if (!world.isNormal()) - return false; - domObject->setWrapper(wrapper, wrapperOwner, context); - return true; -} - -inline bool setInlineCachedWrapper(DOMWrapperWorld& world, JSC::ArrayBuffer* domObject, JSC::JSArrayBuffer* wrapper, JSC::WeakHandleOwner* wrapperOwner, void* context) -{ - if (!world.isNormal()) - return false; - domObject->m_wrapper = JSC::Weak<JSC::JSArrayBuffer>(wrapper, wrapperOwner, context); - return true; -} - -inline bool clearInlineCachedWrapper(DOMWrapperWorld& world, ScriptWrappable* domObject, JSDOMWrapper* 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 <typename DOMClass> inline JSC::JSObject* getCachedWrapper(DOMWrapperWorld& world, DOMClass* domObject) -{ - if (JSC::JSObject* wrapper = getInlineCachedWrapper(world, domObject)) - return wrapper; - return world.m_wrappers.get(domObject); -} - -template <typename DOMClass, typename WrapperClass> inline void cacheWrapper(DOMWrapperWorld& world, DOMClass* domObject, WrapperClass* wrapper) -{ - JSC::WeakHandleOwner* owner = wrapperOwner(world, domObject); - void* context = wrapperContext(world, domObject); - if (setInlineCachedWrapper(world, domObject, wrapper, owner, context)) - return; - weakAdd(world.m_wrappers, (void*)domObject, JSC::Weak<JSC::JSObject>(wrapper, owner, context)); -} - -template <typename DOMClass, typename WrapperClass> inline void uncacheWrapper(DOMWrapperWorld& world, DOMClass* domObject, WrapperClass* wrapper) -{ - if (clearInlineCachedWrapper(world, domObject, wrapper)) - return; - weakRemove(world.m_wrappers, (void*)domObject, wrapper); -} - -#define CREATE_DOM_WRAPPER(exec, globalObject, className, object) createWrapper<JS##className>(exec, globalObject, static_cast<className*>(object)) -template<class WrapperClass, class DOMClass> inline JSDOMWrapper* createWrapper(JSC::ExecState* exec, JSDOMGlobalObject* globalObject, DOMClass* node) -{ - ASSERT(node); - ASSERT(!getCachedWrapper(currentWorld(exec), node)); - WrapperClass* wrapper = WrapperClass::create(getDOMStructure<WrapperClass>(exec->vm(), globalObject), globalObject, node); - // FIXME: The entire function can be removed, once we fix caching. - // This function is a one-off hack to make Nodes cache in the right global object. - cacheWrapper(currentWorld(exec), node, wrapper); - return wrapper; -} - -template<class WrapperClass, class DOMClass> inline JSC::JSValue wrap(JSC::ExecState* exec, JSDOMGlobalObject* globalObject, DOMClass* domObject) -{ - if (!domObject) - return JSC::jsNull(); - if (JSC::JSObject* wrapper = getCachedWrapper(currentWorld(exec), domObject)) - return wrapper; - return createWrapper<WrapperClass>(exec, globalObject, domObject); -} - -template<class WrapperClass, class DOMClass> inline JSC::JSValue getExistingWrapper(JSC::ExecState* exec, DOMClass* domObject) -{ - ASSERT(domObject); - return getCachedWrapper(currentWorld(exec), domObject); -} - -template<class WrapperClass, class DOMClass> inline JSC::JSValue createNewWrapper(JSC::ExecState* exec, JSDOMGlobalObject* globalObject, DOMClass* domObject) -{ - ASSERT(domObject); - ASSERT(!getCachedWrapper(currentWorld(exec), domObject)); - return createWrapper<WrapperClass>(exec, globalObject, domObject); -} - -inline JSC::JSValue argumentOrNull(JSC::ExecState* exec, unsigned index) -{ - return index >= exec->argumentCount() ? JSC::JSValue() : exec->argument(index); -} - -void addImpureProperty(const AtomicString&); - -const JSC::HashTable& getHashTableForGlobalData(JSC::VM&, const JSC::HashTable& staticTable); - -void reportException(JSC::ExecState*, JSC::JSValue exception, CachedScript* = 0); -void reportCurrentException(JSC::ExecState*); - -// Convert a DOM implementation exception code into a JavaScript exception in the execution state. -void setDOMException(JSC::ExecState*, ExceptionCode); - -JSC::JSValue jsStringWithCache(JSC::ExecState*, const String&); -JSC::JSValue jsString(JSC::ExecState*, const URL&); // empty if the URL is null -inline JSC::JSValue jsStringWithCache(JSC::ExecState* exec, const AtomicString& s) -{ - return jsStringWithCache(exec, s.string()); -} - -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); -AtomicStringImpl* findAtomicString(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 - -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 -}; - -int32_t toInt32EnforceRange(JSC::ExecState*, JSC::JSValue); -uint32_t toUInt32EnforceRange(JSC::ExecState*, JSC::JSValue); - -int8_t toInt8(JSC::ExecState*, JSC::JSValue, IntegerConversionConfiguration); -uint8_t toUInt8(JSC::ExecState*, JSC::JSValue, IntegerConversionConfiguration); - -int16_t toInt16(JSC::ExecState*, JSC::JSValue, IntegerConversionConfiguration); -uint16_t toUInt16(JSC::ExecState*, JSC::JSValue, IntegerConversionConfiguration); - -/* - Convert a value to an integer as per <http://www.w3.org/TR/WebIDL/>. - 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); -} - -int64_t toInt64(JSC::ExecState*, JSC::JSValue, IntegerConversionConfiguration); -uint64_t toUInt64(JSC::ExecState*, JSC::JSValue, IntegerConversionConfiguration); - -// 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) { - throwVMError(exec, createTypeError(exec, "Value is not a sequence")); - return 0; - } - - JSC::JSValue lengthValue = object->get(exec, exec->propertyNames().length); - if (exec->hadException()) - return 0; - - if (lengthValue.isUndefinedOrNull()) { - throwVMError(exec, createTypeError(exec, "Value is not a sequence")); - return 0; - } - - length = lengthValue.toUInt32(exec); - if (exec->hadException()) - return 0; - - return object; -} - -inline JSC::JSValue toJS(JSC::ExecState* exec, JSDOMGlobalObject* globalObject, JSC::ArrayBuffer* buffer) -{ - if (!buffer) - return JSC::jsNull(); - if (JSC::JSValue result = getExistingWrapper<JSC::JSArrayBuffer>(exec, buffer)) - return result; - buffer->ref(); - JSC::JSArrayBuffer* wrapper = JSC::JSArrayBuffer::create(exec->vm(), globalObject->arrayBufferStructure(), buffer); - cacheWrapper(currentWorld(exec), 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); -} - -template <typename T> -inline JSC::JSValue toJS(JSC::ExecState* exec, JSDOMGlobalObject* globalObject, PassRefPtr<T> ptr) -{ - return toJS(exec, globalObject, ptr.get()); -} - -template <typename T> -inline JSC::JSValue toJS(JSC::ExecState* exec, JSDOMGlobalObject* globalObject, const Vector<T>& vector) -{ - JSC::JSArray* array = constructEmptyArray(exec, 0, vector.size()); - - for (size_t i = 0; i < vector.size(); ++i) - array->putDirectIndex(exec, i, toJS(exec, globalObject, vector[i])); - - return array; -} - -template <typename T> -inline JSC::JSValue toJS(JSC::ExecState* exec, JSDOMGlobalObject* globalObject, const Vector<RefPtr<T>>& vector) -{ - JSC::JSArray* array = constructEmptyArray(exec, 0, 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); -} - -template <class T> -struct JSValueTraits { - static inline JSC::JSValue arrayJSValue(JSC::ExecState* exec, JSDOMGlobalObject* globalObject, const T& value) - { - return toJS(exec, globalObject, WTF::getPtr(value)); - } -}; - -template<> -struct JSValueTraits<String> { - static inline JSC::JSValue arrayJSValue(JSC::ExecState* exec, JSDOMGlobalObject*, const String& value) - { - return jsStringWithCache(exec, value); - } -}; - -template<> -struct JSValueTraits<float> { - static inline JSC::JSValue arrayJSValue(JSC::ExecState*, JSDOMGlobalObject*, const float& value) - { - return JSC::jsNumber(value); - } -}; - -template<> -struct JSValueTraits<unsigned long> { - static inline JSC::JSValue arrayJSValue(JSC::ExecState*, JSDOMGlobalObject*, const unsigned long& value) - { - return JSC::jsNumber(value); - } -}; - -template <typename T, size_t inlineCapacity> -JSC::JSValue jsArray(JSC::ExecState* exec, JSDOMGlobalObject* globalObject, const Vector<T, inlineCapacity>& iterator) -{ - JSC::MarkedArgumentBuffer list; - typename Vector<T, inlineCapacity>::const_iterator end = iterator.end(); - typedef JSValueTraits<T> TraitsType; - - for (typename Vector<T, inlineCapacity>::const_iterator iter = iterator.begin(); iter != end; ++iter) - list.append(TraitsType::arrayJSValue(exec, globalObject, *iter)); - - return JSC::constructArray(exec, 0, globalObject, list); -} - -JSC::JSValue jsArray(JSC::ExecState*, JSDOMGlobalObject*, PassRefPtr<DOMStringList>); - -inline PassRefPtr<JSC::ArrayBufferView> toArrayBufferView(JSC::JSValue value) -{ - JSC::JSArrayBufferView* wrapper = JSC::jsDynamicCast<JSC::JSArrayBufferView*>(value); - if (!wrapper) - return 0; - return wrapper->impl(); -} - -inline PassRefPtr<JSC::Int8Array> toInt8Array(JSC::JSValue value) { return JSC::toNativeTypedView<JSC::Int8Adaptor>(value); } -inline PassRefPtr<JSC::Int16Array> toInt16Array(JSC::JSValue value) { return JSC::toNativeTypedView<JSC::Int16Adaptor>(value); } -inline PassRefPtr<JSC::Int32Array> toInt32Array(JSC::JSValue value) { return JSC::toNativeTypedView<JSC::Int32Adaptor>(value); } -inline PassRefPtr<JSC::Uint8Array> toUint8Array(JSC::JSValue value) { return JSC::toNativeTypedView<JSC::Uint8Adaptor>(value); } -inline PassRefPtr<JSC::Uint8ClampedArray> toUint8ClampedArray(JSC::JSValue value) { return JSC::toNativeTypedView<JSC::Uint8ClampedAdaptor>(value); } -inline PassRefPtr<JSC::Uint16Array> toUint16Array(JSC::JSValue value) { return JSC::toNativeTypedView<JSC::Uint16Adaptor>(value); } -inline PassRefPtr<JSC::Uint32Array> toUint32Array(JSC::JSValue value) { return JSC::toNativeTypedView<JSC::Uint32Adaptor>(value); } -inline PassRefPtr<JSC::Float32Array> toFloat32Array(JSC::JSValue value) { return JSC::toNativeTypedView<JSC::Float32Adaptor>(value); } -inline PassRefPtr<JSC::Float64Array> toFloat64Array(JSC::JSValue value) { return JSC::toNativeTypedView<JSC::Float64Adaptor>(value); } - -inline PassRefPtr<JSC::DataView> toDataView(JSC::JSValue value) -{ - JSC::JSDataView* wrapper = JSC::jsDynamicCast<JSC::JSDataView*>(value); - if (!wrapper) - return 0; - return wrapper->typedImpl(); -} - -template<class T> struct NativeValueTraits; - -template<> -struct NativeValueTraits<String> { - static inline bool nativeValue(JSC::ExecState* exec, JSC::JSValue jsValue, String& indexedValue) - { - indexedValue = jsValue.toString(exec)->value(exec); - return true; - } -}; - -template<> -struct NativeValueTraits<unsigned> { - 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<float> { - static inline bool nativeValue(JSC::ExecState* exec, JSC::JSValue jsValue, float& indexedValue) - { - indexedValue = jsValue.toFloat(exec); - return !exec->hadException(); - } -}; - -template <class T, class JST> -Vector<RefPtr<T>> toRefPtrNativeArray(JSC::ExecState* exec, JSC::JSValue value, T* (*toT)(JSC::JSValue value)) -{ - if (!isJSArray(value)) - return Vector<RefPtr<T>>(); - - Vector<RefPtr<T>> 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 { - throwVMError(exec, createTypeError(exec, "Invalid Array element type")); - return Vector<RefPtr<T>>(); - } - } - return result; -} - -template <class T> -Vector<T> toNativeArray(JSC::ExecState* exec, JSC::JSValue value) -{ - unsigned length = 0; - if (isJSArray(value)) { - JSC::JSArray* array = asArray(value); - length = array->length(); - } else - toJSSequence(exec, value, length); - - JSC::JSObject* object = value.getObject(); - Vector<T> result; - result.reserveInitialCapacity(length); - typedef NativeValueTraits<T> TraitsType; - - for (unsigned i = 0; i < length; ++i) { - T indexValue; - if (!TraitsType::nativeValue(exec, object->get(exec, i), indexValue)) - return Vector<T>(); - result.uncheckedAppend(indexValue); - } - return result; -} - -template <class T> -Vector<T> toNativeArguments(JSC::ExecState* exec, size_t startIndex = 0) -{ - size_t length = exec->argumentCount(); - ASSERT(startIndex <= length); - - Vector<T> result; - result.reserveInitialCapacity(length); - typedef NativeValueTraits<T> TraitsType; - - for (size_t i = startIndex; i < length; ++i) { - T indexValue; - if (!TraitsType::nativeValue(exec, exec->argument(i), indexValue)) - return Vector<T>(); - 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); -JSC::EncodedJSValue objectToStringFunctionGetter(JSC::ExecState*, JSC::EncodedJSValue, JSC::EncodedJSValue, JSC::PropertyName); - -inline JSC::JSValue jsStringWithCache(JSC::ExecState* exec, const String& s) -{ - StringImpl* stringImpl = s.impl(); - if (!stringImpl || !stringImpl->length()) - return jsEmptyString(exec); - - if (stringImpl->length() == 1) { - UChar singleCharacter = (*stringImpl)[0u]; - if (singleCharacter <= JSC::maxSingleCharacterString) { - JSC::VM* vm = &exec->vm(); - return vm->smallStrings.singleCharacterString(static_cast<unsigned char>(singleCharacter)); - } - } - - JSStringCache& stringCache = currentWorld(exec).m_stringCache; - JSStringCache::AddResult addResult = stringCache.add(stringImpl, nullptr); - if (addResult.isNewEntry) - addResult.iterator->value = JSC::jsString(exec, String(stringImpl)); - return JSC::JSValue(addResult.iterator->value.get()); -} - -inline String propertyNameToString(JSC::PropertyName propertyName) -{ - return propertyName.publicName(); -} - -inline AtomicString propertyNameToAtomicString(JSC::PropertyName propertyName) -{ - return AtomicString(propertyName.publicName()); -} - -template <class ThisImp> -inline const JSC::HashEntry* getStaticValueSlotEntryWithoutCaching(JSC::ExecState* exec, JSC::PropertyName propertyName) -{ - const JSC::HashEntry* entry = ThisImp::info()->propHashTable(exec)->entry(exec, propertyName); - if (!entry) // not found, forward to parent - return getStaticValueSlotEntryWithoutCaching<typename ThisImp::Base>(exec, propertyName); - return entry; -} - -template <> -inline const JSC::HashEntry* getStaticValueSlotEntryWithoutCaching<JSDOMWrapper>(JSC::ExecState*, JSC::PropertyName) -{ - return 0; -} - -template<typename T> -class HasMemoryCostMemberFunction { - typedef char YesType; - struct NoType { - char padding[8]; - }; - - template<typename U> - static decltype(static_cast<U*>(nullptr)->memoryCost(), YesType()) test(int); - - template<typename U> - static NoType test(...); - -public: - static const bool value = sizeof(test<T>(0)) == sizeof(YesType); -}; - -template <typename T, bool hasReportCostFunction = HasMemoryCostMemberFunction<T>::value > struct ReportMemoryCost; -template <typename T> struct ReportMemoryCost<T, true> { - static void reportMemoryCost(JSC::ExecState* exec, T* impl) - { - exec->heap()->reportExtraMemoryCost(impl->memoryCost()); - } -}; -template <typename T> struct ReportMemoryCost<T, false> { - static void reportMemoryCost(JSC::ExecState*, T*) - { - } -}; - -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); -}; - -} // namespace WebCore - -#endif // JSDOMBinding_h diff --git a/Source/WebCore/bindings/js/JSDOMBindingCaller.h b/Source/WebCore/bindings/js/JSDOMBindingCaller.h new file mode 100644 index 000000000..715c6713d --- /dev/null +++ b/Source/WebCore/bindings/js/JSDOMBindingCaller.h @@ -0,0 +1,102 @@ +/* + * Copyright (C) 1999-2001 Harri Porten (porten@kde.org) + * Copyright (C) 2003-2006, 2008-2009, 2013, 2016 Apple Inc. All rights reserved. + * Copyright (C) 2007 Samuel Weinig <sam@webkit.org> + * Copyright (C) 2009 Google, Inc. All rights reserved. + * Copyright (C) 2012 Ericsson AB. All rights reserved. + * Copyright (C) 2013 Michael Pruett <michael@68k.org> + * + * 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 + */ + +#pragma once + +#include "JSDOMExceptionHandling.h" + +namespace WebCore { + +enum class CastedThisErrorBehavior { Throw, ReturnEarly, RejectPromise, Assert }; + +template<typename JSClass> +struct BindingCaller { + using AttributeSetterFunction = bool(JSC::ExecState&, JSClass&, JSC::JSValue, JSC::ThrowScope&); + using AttributeGetterFunction = JSC::JSValue(JSC::ExecState&, JSClass&, JSC::ThrowScope&); + using OperationCallerFunction = JSC::EncodedJSValue(JSC::ExecState*, JSClass*, JSC::ThrowScope&); + using PromiseOperationCallerFunction = JSC::EncodedJSValue(JSC::ExecState*, JSClass*, Ref<DeferredPromise>&&, JSC::ThrowScope&); + + static JSClass* castForAttribute(JSC::ExecState&, JSC::EncodedJSValue); + static JSClass* castForOperation(JSC::ExecState&); + + template<PromiseOperationCallerFunction operationCaller, CastedThisErrorBehavior shouldThrow = CastedThisErrorBehavior::RejectPromise> + static JSC::EncodedJSValue callPromiseOperation(JSC::ExecState* state, Ref<DeferredPromise>&& promise, const char* operationName) + { + ASSERT(state); + auto throwScope = DECLARE_THROW_SCOPE(state->vm()); + auto* thisObject = castForOperation(*state); + if (shouldThrow != CastedThisErrorBehavior::Assert && UNLIKELY(!thisObject)) + return rejectPromiseWithThisTypeError(promise.get(), JSClass::info()->className, operationName); + ASSERT(thisObject); + ASSERT_GC_OBJECT_INHERITS(thisObject, JSClass::info()); + // FIXME: We should refactor the binding generated code to use references for state and thisObject. + return operationCaller(state, thisObject, WTFMove(promise), throwScope); + } + + template<OperationCallerFunction operationCaller, CastedThisErrorBehavior shouldThrow = CastedThisErrorBehavior::Throw> + static JSC::EncodedJSValue callOperation(JSC::ExecState* state, const char* operationName) + { + ASSERT(state); + auto throwScope = DECLARE_THROW_SCOPE(state->vm()); + auto* thisObject = castForOperation(*state); + if (shouldThrow != CastedThisErrorBehavior::Assert && UNLIKELY(!thisObject)) { + if (shouldThrow == CastedThisErrorBehavior::Throw) + return throwThisTypeError(*state, throwScope, JSClass::info()->className, operationName); + // For custom promise-returning operations + return rejectPromiseWithThisTypeError(*state, JSClass::info()->className, operationName); + } + ASSERT(thisObject); + ASSERT_GC_OBJECT_INHERITS(thisObject, JSClass::info()); + // FIXME: We should refactor the binding generated code to use references for state and thisObject. + return operationCaller(state, thisObject, throwScope); + } + + template<AttributeSetterFunction setter, CastedThisErrorBehavior shouldThrow = CastedThisErrorBehavior::Throw> + static bool setAttribute(JSC::ExecState* state, JSC::EncodedJSValue thisValue, JSC::EncodedJSValue encodedValue, const char* attributeName) + { + ASSERT(state); + auto throwScope = DECLARE_THROW_SCOPE(state->vm()); + auto* thisObject = castForAttribute(*state, thisValue); + if (UNLIKELY(!thisObject)) + return (shouldThrow == CastedThisErrorBehavior::Throw) ? throwSetterTypeError(*state, throwScope, JSClass::info()->className, attributeName) : false; + return setter(*state, *thisObject, JSC::JSValue::decode(encodedValue), throwScope); + } + + template<AttributeGetterFunction getter, CastedThisErrorBehavior shouldThrow = CastedThisErrorBehavior::Throw> + static JSC::EncodedJSValue attribute(JSC::ExecState* state, JSC::EncodedJSValue thisValue, const char* attributeName) + { + ASSERT(state); + auto throwScope = DECLARE_THROW_SCOPE(state->vm()); + auto* thisObject = castForAttribute(*state, thisValue); + if (UNLIKELY(!thisObject)) { + if (shouldThrow == CastedThisErrorBehavior::Throw) + return throwGetterTypeError(*state, throwScope, JSClass::info()->className, attributeName); + if (shouldThrow == CastedThisErrorBehavior::RejectPromise) + return rejectPromiseWithGetterTypeError(*state, JSClass::info()->className, attributeName); + return JSC::JSValue::encode(JSC::jsUndefined()); + } + return JSC::JSValue::encode(getter(*state, *thisObject, throwScope)); + } +}; + +} // namespace WebCore diff --git a/Source/WebCore/bindings/js/JSDOMBindingSecurity.cpp b/Source/WebCore/bindings/js/JSDOMBindingSecurity.cpp new file mode 100644 index 000000000..4eefc8691 --- /dev/null +++ b/Source/WebCore/bindings/js/JSDOMBindingSecurity.cpp @@ -0,0 +1,102 @@ +/* + * Copyright (C) 1999-2001 Harri Porten (porten@kde.org) + * Copyright (C) 2004-2011, 2013, 2016 Apple Inc. All rights reserved. + * Copyright (C) 2007 Samuel Weinig <sam@webkit.org> + * Copyright (C) 2013 Michael Pruett <michael@68k.org> + * + * 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 + */ + +#include "config.h" +#include "JSDOMBindingSecurity.h" + +#include "DOMWindow.h" +#include "Document.h" +#include "Frame.h" +#include "JSDOMExceptionHandling.h" +#include "JSDOMWindowBase.h" +#include "SecurityOrigin.h" +#include <wtf/text/WTFString.h> + +using namespace JSC; + +namespace WebCore { + +void printErrorMessageForFrame(Frame* frame, const String& message) +{ + if (!frame) + return; + frame->document()->domWindow()->printErrorMessage(message); +} + +static inline bool canAccessDocument(JSC::ExecState* state, Document* targetDocument, SecurityReportingOption reportingOption) +{ + VM& vm = state->vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + + if (!targetDocument) + return false; + + DOMWindow& active = activeDOMWindow(state); + + if (active.document()->securityOrigin().canAccess(targetDocument->securityOrigin())) + return true; + + switch (reportingOption) { + case ThrowSecurityError: + throwSecurityError(*state, scope, targetDocument->domWindow()->crossDomainAccessErrorMessage(active)); + break; + case LogSecurityError: + printErrorMessageForFrame(targetDocument->frame(), targetDocument->domWindow()->crossDomainAccessErrorMessage(active)); + break; + case DoNotReportSecurityError: + break; + } + + return false; +} + +bool BindingSecurity::shouldAllowAccessToFrame(ExecState& state, Frame& frame, String& message) +{ + if (BindingSecurity::shouldAllowAccessToFrame(&state, &frame, DoNotReportSecurityError)) + return true; + message = frame.document()->domWindow()->crossDomainAccessErrorMessage(activeDOMWindow(&state)); + return false; +} + +bool BindingSecurity::shouldAllowAccessToDOMWindow(ExecState& state, DOMWindow& globalObject, String& message) +{ + if (BindingSecurity::shouldAllowAccessToDOMWindow(&state, globalObject, DoNotReportSecurityError)) + return true; + message = globalObject.crossDomainAccessErrorMessage(activeDOMWindow(&state)); + return false; +} + +bool BindingSecurity::shouldAllowAccessToDOMWindow(JSC::ExecState* state, DOMWindow& target, SecurityReportingOption reportingOption) +{ + return canAccessDocument(state, target.document(), reportingOption); +} + +bool BindingSecurity::shouldAllowAccessToFrame(JSC::ExecState* state, Frame* target, SecurityReportingOption reportingOption) +{ + return target && canAccessDocument(state, target->document(), reportingOption); +} + +bool BindingSecurity::shouldAllowAccessToNode(JSC::ExecState& state, Node* target) +{ + return !target || canAccessDocument(&state, &target->document(), LogSecurityError); +} + +} // namespace WebCore diff --git a/Source/WebCore/bindings/js/JSDOMBindingSecurity.h b/Source/WebCore/bindings/js/JSDOMBindingSecurity.h new file mode 100644 index 000000000..7b4085a51 --- /dev/null +++ b/Source/WebCore/bindings/js/JSDOMBindingSecurity.h @@ -0,0 +1,82 @@ +/* + * Copyright (C) 1999-2001 Harri Porten (porten@kde.org) + * Copyright (C) 2003-2006, 2008-2009, 2013, 2016 Apple Inc. All rights reserved. + * Copyright (C) 2007 Samuel Weinig <sam@webkit.org> + * Copyright (C) 2009 Google, Inc. All rights reserved. + * Copyright (C) 2012 Ericsson AB. All rights reserved. + * Copyright (C) 2013 Michael Pruett <michael@68k.org> + * + * 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 + */ + +#pragma once + +#include "ExceptionOr.h" +#include <wtf/Forward.h> + +namespace JSC { +class ExecState; +} + +namespace WebCore { + +class DOMWindow; +class Frame; +class Node; + +void printErrorMessageForFrame(Frame*, const String& message); + +enum SecurityReportingOption { DoNotReportSecurityError, LogSecurityError, ThrowSecurityError }; + +namespace BindingSecurity { + +template<typename T> T* checkSecurityForNode(JSC::ExecState&, T&); +template<typename T> T* checkSecurityForNode(JSC::ExecState&, T*); +template<typename T> ExceptionOr<T*> checkSecurityForNode(JSC::ExecState&, ExceptionOr<T*>&&); +template<typename T> ExceptionOr<T*> checkSecurityForNode(JSC::ExecState&, ExceptionOr<T&>&&); + +bool shouldAllowAccessToDOMWindow(JSC::ExecState*, DOMWindow&, SecurityReportingOption = LogSecurityError); +bool shouldAllowAccessToDOMWindow(JSC::ExecState&, DOMWindow&, String& message); +bool shouldAllowAccessToFrame(JSC::ExecState*, Frame*, SecurityReportingOption = LogSecurityError); +bool shouldAllowAccessToFrame(JSC::ExecState&, Frame&, String& message); +bool shouldAllowAccessToNode(JSC::ExecState&, Node*); + +}; + +template<typename T> inline T* BindingSecurity::checkSecurityForNode(JSC::ExecState& state, T& node) +{ + return shouldAllowAccessToNode(state, &node) ? &node : nullptr; +} + +template<typename T> inline T* BindingSecurity::checkSecurityForNode(JSC::ExecState& state, T* node) +{ + return shouldAllowAccessToNode(state, node) ? node : nullptr; +} + +template<typename T> inline ExceptionOr<T*> BindingSecurity::checkSecurityForNode(JSC::ExecState& state, ExceptionOr<T*>&& value) +{ + if (value.hasException()) + return value.releaseException(); + return checkSecurityForNode(state, value.releaseReturnValue()); +} + +template<typename T> inline ExceptionOr<T*> BindingSecurity::checkSecurityForNode(JSC::ExecState& state, ExceptionOr<T&>&& value) +{ + if (value.hasException()) + return value.releaseException(); + return checkSecurityForNode(state, value.releaseReturnValue()); +} + +} // namespace WebCore diff --git a/Source/WebCore/bindings/js/JSDOMBuiltinConstructor.h b/Source/WebCore/bindings/js/JSDOMBuiltinConstructor.h new file mode 100644 index 000000000..74ee3a5ca --- /dev/null +++ b/Source/WebCore/bindings/js/JSDOMBuiltinConstructor.h @@ -0,0 +1,131 @@ +/* + * Copyright (C) 2015, 2016 Canon Inc. All rights reserved. + * Copyright (C) 2016 Apple Inc. All rights reserved. + * + * 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 + */ + +#pragma once + +#include "JSDOMBuiltinConstructorBase.h" +#include "JSDOMExceptionHandling.h" +#include "JSDOMWrapperCache.h" + +namespace WebCore { + +template<typename JSClass> class JSDOMBuiltinConstructor : public JSDOMBuiltinConstructorBase { +public: + using Base = JSDOMBuiltinConstructorBase; + + static JSDOMBuiltinConstructor* create(JSC::VM&, JSC::Structure*, JSDOMGlobalObject&); + static JSC::Structure* createStructure(JSC::VM&, JSC::JSGlobalObject&, JSC::JSValue prototype); + + DECLARE_INFO; + + // Usually defined for each specialization class. + static JSC::JSValue prototypeForStructure(JSC::VM&, const JSDOMGlobalObject&); + +private: + JSDOMBuiltinConstructor(JSC::Structure* structure, JSDOMGlobalObject& globalObject) + : Base(structure, globalObject) + { + } + + void finishCreation(JSC::VM&, JSDOMGlobalObject&); + static JSC::ConstructType getConstructData(JSC::JSCell*, JSC::ConstructData&); + static JSC::EncodedJSValue JSC_HOST_CALL construct(JSC::ExecState*); + + JSC::EncodedJSValue callConstructor(JSC::ExecState&, JSC::JSObject&); + JSC::EncodedJSValue callConstructor(JSC::ExecState&, JSC::JSObject*); + + // Usually defined for each specialization class. + void initializeProperties(JSC::VM&, JSDOMGlobalObject&) { } + // Must be defined for each specialization class. + JSC::FunctionExecutable* initializeExecutable(JSC::VM&); +}; + +template<typename JSClass> inline JSDOMBuiltinConstructor<JSClass>* JSDOMBuiltinConstructor<JSClass>::create(JSC::VM& vm, JSC::Structure* structure, JSDOMGlobalObject& globalObject) +{ + JSDOMBuiltinConstructor* constructor = new (NotNull, JSC::allocateCell<JSDOMBuiltinConstructor>(vm.heap)) JSDOMBuiltinConstructor(structure, globalObject); + constructor->finishCreation(vm, globalObject); + return constructor; +} + +template<typename JSClass> inline JSC::Structure* JSDOMBuiltinConstructor<JSClass>::createStructure(JSC::VM& vm, JSC::JSGlobalObject& globalObject, JSC::JSValue prototype) +{ + return JSC::Structure::create(vm, &globalObject, prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), info()); +} + +template<typename JSClass> inline void JSDOMBuiltinConstructor<JSClass>::finishCreation(JSC::VM& vm, JSDOMGlobalObject& globalObject) +{ + Base::finishCreation(vm); + ASSERT(inherits(vm, info())); + setInitializeFunction(vm, *JSC::JSFunction::createBuiltinFunction(vm, initializeExecutable(vm), &globalObject)); + initializeProperties(vm, globalObject); +} + +template<typename JSClass> inline JSC::EncodedJSValue JSDOMBuiltinConstructor<JSClass>::callConstructor(JSC::ExecState& state, JSC::JSObject& object) +{ + Base::callFunctionWithCurrentArguments(state, object, *initializeFunction()); + return JSC::JSValue::encode(&object); +} + +template<typename JSClass> inline JSC::EncodedJSValue JSDOMBuiltinConstructor<JSClass>::callConstructor(JSC::ExecState& state, JSC::JSObject* object) +{ + JSC::VM& vm = state.vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + if (!object) + return throwConstructorScriptExecutionContextUnavailableError(state, scope, info()->className); + return callConstructor(state, *object); +} + +template<typename JSClass> inline +typename std::enable_if<JSDOMObjectInspector<JSClass>::isSimpleWrapper, JSC::JSObject&>::type createJSObject(JSDOMBuiltinConstructor<JSClass>& constructor) +{ + auto& globalObject = *constructor.globalObject(); + return *JSClass::create(getDOMStructure<JSClass>(globalObject.vm(), globalObject), &globalObject, JSClass::DOMWrapped::create()); +} + +template<typename JSClass> inline +typename std::enable_if<JSDOMObjectInspector<JSClass>::isBuiltin, JSC::JSObject&>::type createJSObject(JSDOMBuiltinConstructor<JSClass>& constructor) +{ + auto& globalObject = *constructor.globalObject(); + return *JSClass::create(getDOMStructure<JSClass>(globalObject.vm(), globalObject), &globalObject); +} + +template<typename JSClass> inline +typename std::enable_if<JSDOMObjectInspector<JSClass>::isComplexWrapper, JSC::JSObject*>::type createJSObject(JSDOMBuiltinConstructor<JSClass>& constructor) +{ + ScriptExecutionContext* context = constructor.scriptExecutionContext(); + if (!context) + return nullptr; + auto& globalObject = *constructor.globalObject(); + return JSClass::create(getDOMStructure<JSClass>(globalObject.vm(), globalObject), &globalObject, JSClass::DOMWrapped::create(*context)); +} + +template<typename JSClass> inline JSC::EncodedJSValue JSC_HOST_CALL JSDOMBuiltinConstructor<JSClass>::construct(JSC::ExecState* state) +{ + ASSERT(state); + auto* castedThis = JSC::jsCast<JSDOMBuiltinConstructor*>(state->jsCallee()); + return castedThis->callConstructor(*state, createJSObject(*castedThis)); +} + +template<typename JSClass> inline JSC::ConstructType JSDOMBuiltinConstructor<JSClass>::getConstructData(JSC::JSCell*, JSC::ConstructData& constructData) +{ + constructData.native.function = construct; + return JSC::ConstructType::Host; +} + +} // namespace WebCore diff --git a/Source/WebCore/bindings/js/JSDOMBuiltinConstructorBase.cpp b/Source/WebCore/bindings/js/JSDOMBuiltinConstructorBase.cpp new file mode 100644 index 000000000..42ea13278 --- /dev/null +++ b/Source/WebCore/bindings/js/JSDOMBuiltinConstructorBase.cpp @@ -0,0 +1,51 @@ +/* + * Copyright (C) 1999-2001 Harri Porten (porten@kde.org) + * Copyright (C) 2004-2011, 2013, 2016 Apple Inc. All rights reserved. + * Copyright (C) 2007 Samuel Weinig <sam@webkit.org> + * Copyright (C) 2013 Michael Pruett <michael@68k.org> + * + * 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 + */ + +#include "config.h" +#include "JSDOMBuiltinConstructorBase.h" + +#include <runtime/JSCInlines.h> + +using namespace JSC; + +namespace WebCore { + +void JSDOMBuiltinConstructorBase::callFunctionWithCurrentArguments(JSC::ExecState& state, JSC::JSObject& thisObject, JSC::JSFunction& function) +{ + JSC::CallData callData; + JSC::CallType callType = JSC::getCallData(&function, callData); + ASSERT(callType != CallType::None); + + JSC::MarkedArgumentBuffer arguments; + for (unsigned i = 0; i < state.argumentCount(); ++i) + arguments.append(state.uncheckedArgument(i)); + JSC::call(&state, &function, callType, callData, &thisObject, arguments); +} + +void JSDOMBuiltinConstructorBase::visitChildren(JSC::JSCell* cell, JSC::SlotVisitor& visitor) +{ + auto* thisObject = jsCast<JSDOMBuiltinConstructorBase*>(cell); + ASSERT_GC_OBJECT_INHERITS(thisObject, info()); + Base::visitChildren(thisObject, visitor); + visitor.append(thisObject->m_initializeFunction); +} + +} // namespace WebCore diff --git a/Source/WebCore/bindings/js/JSDOMBuiltinConstructorBase.h b/Source/WebCore/bindings/js/JSDOMBuiltinConstructorBase.h new file mode 100644 index 000000000..c6cf294f1 --- /dev/null +++ b/Source/WebCore/bindings/js/JSDOMBuiltinConstructorBase.h @@ -0,0 +1,58 @@ +/* + * Copyright (C) 2015, 2016 Canon Inc. All rights reserved. + * Copyright (C) 2016 Apple Inc. All rights reserved. + * + * 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 + */ + +#pragma once + +#include "JSDOMConstructorBase.h" + +namespace WebCore { + +class JSDOMBuiltinConstructorBase : public JSDOMConstructorBase { +public: + using Base = JSDOMConstructorBase; + +protected: + JSDOMBuiltinConstructorBase(JSC::Structure* structure, JSDOMGlobalObject& globalObject) + : JSDOMConstructorBase(structure, globalObject) + { + } + + static void visitChildren(JSC::JSCell*, JSC::SlotVisitor&); + + JSC::JSFunction* initializeFunction(); + void setInitializeFunction(JSC::VM&, JSC::JSFunction&); + + static void callFunctionWithCurrentArguments(JSC::ExecState&, JSC::JSObject& thisObject, JSC::JSFunction&); + +private: + JSC::WriteBarrier<JSC::JSFunction> m_initializeFunction; +}; + +inline JSC::JSFunction* JSDOMBuiltinConstructorBase::initializeFunction() +{ + return m_initializeFunction.get(); +} + +inline void JSDOMBuiltinConstructorBase::setInitializeFunction(JSC::VM& vm, JSC::JSFunction& function) +{ + m_initializeFunction.set(vm, this, &function); +} + + +} // namespace WebCore diff --git a/Source/WebCore/bindings/js/JSDOMConstructor.h b/Source/WebCore/bindings/js/JSDOMConstructor.h new file mode 100644 index 000000000..01767a940 --- /dev/null +++ b/Source/WebCore/bindings/js/JSDOMConstructor.h @@ -0,0 +1,79 @@ +/* + * Copyright (C) 2015, 2016 Canon Inc. All rights reserved. + * Copyright (C) 2016 Apple Inc. All rights reserved. + * + * 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 + */ + +#pragma once + +#include "JSDOMConstructorBase.h" + +namespace WebCore { + +template<typename JSClass> class JSDOMConstructor : public JSDOMConstructorBase { +public: + using Base = JSDOMConstructorBase; + + static JSDOMConstructor* create(JSC::VM&, JSC::Structure*, JSDOMGlobalObject&); + static JSC::Structure* createStructure(JSC::VM&, JSC::JSGlobalObject&, JSC::JSValue prototype); + + DECLARE_INFO; + + // Must be defined for each specialization class. + static JSC::JSValue prototypeForStructure(JSC::VM&, const JSDOMGlobalObject&); + +private: + JSDOMConstructor(JSC::Structure* structure, JSDOMGlobalObject& globalObject) + : Base(structure, globalObject) + { + } + + void finishCreation(JSC::VM&, JSDOMGlobalObject&); + static JSC::ConstructType getConstructData(JSC::JSCell*, JSC::ConstructData&); + + // Usually defined for each specialization class. + void initializeProperties(JSC::VM&, JSDOMGlobalObject&) { } + // Must be defined for each specialization class. + static JSC::EncodedJSValue JSC_HOST_CALL construct(JSC::ExecState*); +}; + +template<typename JSClass> inline JSDOMConstructor<JSClass>* JSDOMConstructor<JSClass>::create(JSC::VM& vm, JSC::Structure* structure, JSDOMGlobalObject& globalObject) +{ + JSDOMConstructor* constructor = new (NotNull, JSC::allocateCell<JSDOMConstructor>(vm.heap)) JSDOMConstructor(structure, globalObject); + constructor->finishCreation(vm, globalObject); + return constructor; +} + +template<typename JSClass> inline JSC::Structure* JSDOMConstructor<JSClass>::createStructure(JSC::VM& vm, JSC::JSGlobalObject& globalObject, JSC::JSValue prototype) +{ + return JSC::Structure::create(vm, &globalObject, prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), info()); +} + +template<typename JSClass> inline void JSDOMConstructor<JSClass>::finishCreation(JSC::VM& vm, JSDOMGlobalObject& globalObject) +{ + Base::finishCreation(vm); + ASSERT(inherits(vm, info())); + initializeProperties(vm, globalObject); +} + +template<typename JSClass> inline JSC::ConstructType JSDOMConstructor<JSClass>::getConstructData(JSC::JSCell*, JSC::ConstructData& constructData) +{ + constructData.native.function = construct; + return JSC::ConstructType::Host; +} + + +} // namespace WebCore diff --git a/Source/WebCore/bindings/js/JSDOMPluginCustom.cpp b/Source/WebCore/bindings/js/JSDOMConstructorBase.cpp index e23e60f76..3c04c5408 100644 --- a/Source/WebCore/bindings/js/JSDOMPluginCustom.cpp +++ b/Source/WebCore/bindings/js/JSDOMConstructorBase.cpp @@ -1,5 +1,8 @@ /* - * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies) + * Copyright (C) 1999-2001 Harri Porten (porten@kde.org) + * Copyright (C) 2004-2011, 2013, 2016 Apple Inc. All rights reserved. + * Copyright (C) 2007 Samuel Weinig <sam@webkit.org> + * Copyright (C) 2013 Michael Pruett <michael@68k.org> * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -17,25 +20,28 @@ */ #include "config.h" -#include "JSDOMPlugin.h" +#include "JSDOMConstructor.h" -#include "DOMPlugin.h" -#include "JSDOMMimeType.h" -#include <wtf/text/AtomicString.h> +#include <runtime/JSCInlines.h> + +using namespace JSC; namespace WebCore { -using namespace JSC; +STATIC_ASSERT_IS_TRIVIALLY_DESTRUCTIBLE(JSDOMConstructorBase); -bool JSDOMPlugin::canGetItemsForName(ExecState*, DOMPlugin* plugin, PropertyName propertyName) +static EncodedJSValue JSC_HOST_CALL callThrowTypeError(ExecState* exec) { - return plugin->canGetItemsForName(propertyNameToAtomicString(propertyName)); + VM& vm = exec->vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + throwTypeError(exec, scope, ASCIILiteral("Constructor requires 'new' operator")); + return JSValue::encode(jsNull()); } -EncodedJSValue JSDOMPlugin::nameGetter(ExecState* exec, EncodedJSValue slotBase, EncodedJSValue, PropertyName propertyName) +CallType JSDOMConstructorBase::getCallData(JSCell*, CallData& callData) { - JSDOMPlugin* thisObj = jsCast<JSDOMPlugin*>(JSValue::decode(slotBase)); - return JSValue::encode(toJS(exec, thisObj->globalObject(), thisObj->impl().namedItem(propertyNameToAtomicString(propertyName)))); + callData.native.function = callThrowTypeError; + return CallType::Host; } } // namespace WebCore diff --git a/Source/WebCore/bindings/js/JSDOMConstructorBase.h b/Source/WebCore/bindings/js/JSDOMConstructorBase.h new file mode 100644 index 000000000..a142e5ad6 --- /dev/null +++ b/Source/WebCore/bindings/js/JSDOMConstructorBase.h @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2015, 2016 Canon Inc. All rights reserved. + * Copyright (C) 2016 Apple Inc. All rights reserved. + * + * 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 + */ + +#pragma once + +#include "JSDOMWrapper.h" + +namespace WebCore { + +// Base class for all constructor objects in the JSC bindings. +class JSDOMConstructorBase : public JSDOMObject { +public: + using Base = JSDOMObject; + + static const unsigned StructureFlags = Base::StructureFlags | JSC::ImplementsHasInstance | JSC::ImplementsDefaultHasInstance | JSC::TypeOfShouldCallGetCallData; + static JSC::Structure* createStructure(JSC::VM&, JSC::JSGlobalObject*, JSC::JSValue); + +protected: + JSDOMConstructorBase(JSC::Structure* structure, JSDOMGlobalObject& globalObject) + : JSDOMObject(structure, globalObject) + { + } + + static String className(const JSObject*); + static JSC::CallType getCallData(JSCell*, JSC::CallData&); +}; + +inline JSC::Structure* JSDOMConstructorBase::createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype) +{ + return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), info()); +} + +inline String JSDOMConstructorBase::className(const JSObject*) +{ + return ASCIILiteral("Function"); +} + +} // namespace WebCore diff --git a/Source/WebCore/bindings/js/JSDOMConstructorNotConstructable.h b/Source/WebCore/bindings/js/JSDOMConstructorNotConstructable.h new file mode 100644 index 000000000..399742b38 --- /dev/null +++ b/Source/WebCore/bindings/js/JSDOMConstructorNotConstructable.h @@ -0,0 +1,84 @@ +/* + * Copyright (C) 2015, 2016 Canon Inc. All rights reserved. + * Copyright (C) 2016 Apple Inc. All rights reserved. + * + * 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 + */ + +#pragma once + +#include "JSDOMConstructorBase.h" +#include "JSDOMExceptionHandling.h" + +namespace WebCore { + +template<typename JSClass> class JSDOMConstructorNotConstructable : public JSDOMConstructorBase { +public: + using Base = JSDOMConstructorBase; + + static JSDOMConstructorNotConstructable* create(JSC::VM&, JSC::Structure*, JSDOMGlobalObject&); + static JSC::Structure* createStructure(JSC::VM&, JSC::JSGlobalObject&, JSC::JSValue prototype); + + DECLARE_INFO; + + // Must be defined for each specialization class. + static JSC::JSValue prototypeForStructure(JSC::VM&, const JSDOMGlobalObject&); + +private: + JSDOMConstructorNotConstructable(JSC::Structure* structure, JSDOMGlobalObject& globalObject) + : Base(structure, globalObject) + { + } + + void finishCreation(JSC::VM&, JSDOMGlobalObject&); + + // Usually defined for each specialization class. + void initializeProperties(JSC::VM&, JSDOMGlobalObject&) { } + + static JSC::EncodedJSValue JSC_HOST_CALL callThrowTypeError(JSC::ExecState* exec) + { + JSC::VM& vm = exec->vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + JSC::throwTypeError(exec, scope, ASCIILiteral("Illegal constructor")); + return JSC::JSValue::encode(JSC::jsNull()); + } + + static JSC::CallType getCallData(JSC::JSCell*, JSC::CallData& callData) + { + callData.native.function = callThrowTypeError; + return JSC::CallType::Host; + } +}; + +template<typename JSClass> inline JSDOMConstructorNotConstructable<JSClass>* JSDOMConstructorNotConstructable<JSClass>::create(JSC::VM& vm, JSC::Structure* structure, JSDOMGlobalObject& globalObject) +{ + JSDOMConstructorNotConstructable* constructor = new (NotNull, JSC::allocateCell<JSDOMConstructorNotConstructable>(vm.heap)) JSDOMConstructorNotConstructable(structure, globalObject); + constructor->finishCreation(vm, globalObject); + return constructor; +} + +template<typename JSClass> inline JSC::Structure* JSDOMConstructorNotConstructable<JSClass>::createStructure(JSC::VM& vm, JSC::JSGlobalObject& globalObject, JSC::JSValue prototype) +{ + return JSC::Structure::create(vm, &globalObject, prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), info()); +} + +template<typename JSClass> inline void JSDOMConstructorNotConstructable<JSClass>::finishCreation(JSC::VM& vm, JSDOMGlobalObject& globalObject) +{ + Base::finishCreation(vm); + ASSERT(inherits(vm, info())); + initializeProperties(vm, globalObject); +} + +} // namespace WebCore diff --git a/Source/WebCore/bindings/js/DOMObjectHashTableMap.cpp b/Source/WebCore/bindings/js/JSDOMConstructorWithDocument.cpp index 4d6b916bc..c23acffd0 100644 --- a/Source/WebCore/bindings/js/DOMObjectHashTableMap.cpp +++ b/Source/WebCore/bindings/js/JSDOMConstructorWithDocument.cpp @@ -1,7 +1,8 @@ /* * Copyright (C) 1999-2001 Harri Porten (porten@kde.org) - * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved. + * Copyright (C) 2004-2011, 2013, 2016 Apple Inc. All rights reserved. * Copyright (C) 2007 Samuel Weinig <sam@webkit.org> + * Copyright (C) 2013 Michael Pruett <michael@68k.org> * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -19,19 +20,12 @@ */ #include "config.h" -#include "DOMObjectHashTableMap.h" - -#include "WebCoreJSClientData.h" +#include "JSDOMConstructorWithDocument.h" using namespace JSC; -namespace WebCore{ +namespace WebCore { -DOMObjectHashTableMap& DOMObjectHashTableMap::mapFor(VM& vm) -{ - VM::ClientData* clientData = vm.clientData; - ASSERT(clientData); - return static_cast<WebCoreJSClientData*>(clientData)->hashTableMap; -} +STATIC_ASSERT_IS_TRIVIALLY_DESTRUCTIBLE(JSDOMConstructorWithDocument); } // namespace WebCore diff --git a/Source/WebCore/bindings/js/DOMConstructorWithDocument.h b/Source/WebCore/bindings/js/JSDOMConstructorWithDocument.h index 5c98f6116..1a9a95964 100644 --- a/Source/WebCore/bindings/js/DOMConstructorWithDocument.h +++ b/Source/WebCore/bindings/js/JSDOMConstructorWithDocument.h @@ -1,5 +1,6 @@ /* - * Copyright (C) 2009 Google, Inc. All rights reserved. + * Copyright (C) 2015, 2016 Canon Inc. All rights reserved. + * Copyright (C) 2016 Apple Inc. All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -16,38 +17,35 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ - -#ifndef DOMConstructorWithDocument_h -#define DOMConstructorWithDocument_h +#pragma once #include "Document.h" -#include "JSDOMBinding.h" +#include "JSDOMConstructorBase.h" namespace WebCore { // Constructors using this base class depend on being in a Document and // can never be used from a WorkerGlobalScope. -class DOMConstructorWithDocument : public DOMConstructorObject { - typedef DOMConstructorObject Base; +class JSDOMConstructorWithDocument : public JSDOMConstructorBase { public: + using Base = JSDOMConstructorBase; + Document* document() const { - return toDocument(scriptExecutionContext()); + return downcast<Document>(scriptExecutionContext()); } protected: - DOMConstructorWithDocument(JSC::Structure* structure, JSDOMGlobalObject* globalObject) - : DOMConstructorObject(structure, globalObject) + JSDOMConstructorWithDocument(JSC::Structure* structure, JSDOMGlobalObject& globalObject) + : JSDOMConstructorBase(structure, globalObject) { } - void finishCreation(JSDOMGlobalObject* globalObject) + void finishCreation(JSDOMGlobalObject& globalObject) { - Base::finishCreation(globalObject->vm()); - ASSERT(globalObject->scriptExecutionContext()->isDocument()); + Base::finishCreation(globalObject.vm()); + ASSERT(globalObject.scriptExecutionContext()->isDocument()); } }; } // namespace WebCore - -#endif // DOMConstructorWithDocument_h diff --git a/Source/WebCore/bindings/js/JSDOMConvert.h b/Source/WebCore/bindings/js/JSDOMConvert.h new file mode 100644 index 000000000..44afd4d3e --- /dev/null +++ b/Source/WebCore/bindings/js/JSDOMConvert.h @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2016 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +#include "JSDOMConvertAny.h" +#include "JSDOMConvertBoolean.h" +#include "JSDOMConvertBufferSource.h" +#include "JSDOMConvertCallbacks.h" +#include "JSDOMConvertDate.h" +#include "JSDOMConvertDictionary.h" +#include "JSDOMConvertEnumeration.h" +#include "JSDOMConvertEventListener.h" +#include "JSDOMConvertIndexedDB.h" +#include "JSDOMConvertInterface.h" +#include "JSDOMConvertJSON.h" +#include "JSDOMConvertNull.h" +#include "JSDOMConvertNullable.h" +#include "JSDOMConvertNumbers.h" +#include "JSDOMConvertObject.h" +#include "JSDOMConvertRecord.h" +#include "JSDOMConvertSequences.h" +#include "JSDOMConvertSerializedScriptValue.h" +#include "JSDOMConvertStrings.h" +#include "JSDOMConvertUnion.h" +#include "JSDOMConvertWebGL.h" +#include "JSDOMConvertXPathNSResolver.h" diff --git a/Source/WebCore/bindings/js/JSDOMConvertAny.h b/Source/WebCore/bindings/js/JSDOMConvertAny.h new file mode 100644 index 000000000..b27ab7ca6 --- /dev/null +++ b/Source/WebCore/bindings/js/JSDOMConvertAny.h @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2016 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +#include "IDLTypes.h" +#include "JSDOMConvertBase.h" + +namespace WebCore { + +template<> struct Converter<IDLAny> : DefaultConverter<IDLAny> { + using ReturnType = JSC::JSValue; + + static JSC::JSValue convert(JSC::ExecState&, JSC::JSValue value) + { + return value; + } + + static JSC::JSValue convert(const JSC::Strong<JSC::Unknown>& value) + { + return value.get(); + } +}; + +template<> struct JSConverter<IDLAny> { + static constexpr bool needsState = false; + static constexpr bool needsGlobalObject = false; + + static JSC::JSValue convert(const JSC::JSValue& value) + { + return value; + } + + static JSC::JSValue convert(const JSC::Strong<JSC::Unknown>& value) + { + return value.get(); + } +}; + +} // namespace WebCore diff --git a/Source/WebCore/bindings/js/JSDOMConvertBase.h b/Source/WebCore/bindings/js/JSDOMConvertBase.h new file mode 100644 index 000000000..bd23abe52 --- /dev/null +++ b/Source/WebCore/bindings/js/JSDOMConvertBase.h @@ -0,0 +1,183 @@ +/* + * Copyright (C) 2016 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +#include "JSDOMExceptionHandling.h" + +namespace WebCore { + +// Conversion from JSValue -> Implementation +template<typename T> struct Converter; + + +struct DefaultExceptionThrower { + void operator()(JSC::ExecState& state, JSC::ThrowScope& scope) + { + throwTypeError(&state, scope); + } +}; + +template<typename T> typename Converter<T>::ReturnType convert(JSC::ExecState&, JSC::JSValue); +template<typename T> typename Converter<T>::ReturnType convert(JSC::ExecState&, JSC::JSValue, JSC::JSObject&); +template<typename T> typename Converter<T>::ReturnType convert(JSC::ExecState&, JSC::JSValue, JSDOMGlobalObject&); +template<typename T, typename ExceptionThrower> typename Converter<T>::ReturnType convert(JSC::ExecState&, JSC::JSValue, ExceptionThrower&&); +template<typename T, typename ExceptionThrower> typename Converter<T>::ReturnType convert(JSC::ExecState&, JSC::JSValue, JSC::JSObject&, ExceptionThrower&&); +template<typename T, typename ExceptionThrower> typename Converter<T>::ReturnType convert(JSC::ExecState&, JSC::JSValue, JSDOMGlobalObject&, ExceptionThrower&&); + +template<typename T> inline typename Converter<T>::ReturnType convert(JSC::ExecState& state, JSC::JSValue value) +{ + return Converter<T>::convert(state, value); +} + +template<typename T> inline typename Converter<T>::ReturnType convert(JSC::ExecState& state, JSC::JSValue value, JSC::JSObject& thisObject) +{ + return Converter<T>::convert(state, value, thisObject); +} + +template<typename T> inline typename Converter<T>::ReturnType convert(JSC::ExecState& state, JSC::JSValue value, JSDOMGlobalObject& globalObject) +{ + return Converter<T>::convert(state, value, globalObject); +} + +template<typename T, typename ExceptionThrower> inline typename Converter<T>::ReturnType convert(JSC::ExecState& state, JSC::JSValue value, ExceptionThrower&& exceptionThrower) +{ + return Converter<T>::convert(state, value, std::forward<ExceptionThrower>(exceptionThrower)); +} + +template<typename T, typename ExceptionThrower> inline typename Converter<T>::ReturnType convert(JSC::ExecState& state, JSC::JSValue value, JSC::JSObject& thisObject, ExceptionThrower&& exceptionThrower) +{ + return Converter<T>::convert(state, value, thisObject, std::forward<ExceptionThrower>(exceptionThrower)); +} + +template<typename T, typename ExceptionThrower> inline typename Converter<T>::ReturnType convert(JSC::ExecState& state, JSC::JSValue value, JSDOMGlobalObject& globalObject, ExceptionThrower&& exceptionThrower) +{ + return Converter<T>::convert(state, value, globalObject, std::forward<ExceptionThrower>(exceptionThrower)); +} + +// Conversion from Implementation -> JSValue +template<typename T> struct JSConverter; + +template<typename T, typename U> inline JSC::JSValue toJS(U&&); +template<typename T, typename U> inline JSC::JSValue toJS(JSC::ExecState&, U&&); +template<typename T, typename U> inline JSC::JSValue toJS(JSC::ExecState&, JSDOMGlobalObject&, U&&); +template<typename T, typename U> inline JSC::JSValue toJS(JSC::ExecState&, JSC::ThrowScope&, ExceptionOr<U>&&); +template<typename T, typename U> inline JSC::JSValue toJS(JSC::ExecState&, JSDOMGlobalObject&, JSC::ThrowScope&, ExceptionOr<U>&&); +template<typename T, typename U> inline JSC::JSValue toJSNewlyCreated(JSC::ExecState&, JSDOMGlobalObject&, U&&); +template<typename T, typename U> inline JSC::JSValue toJSNewlyCreated(JSC::ExecState&, JSDOMGlobalObject&, JSC::ThrowScope&, ExceptionOr<U>&&); + +template<typename T, bool needsState = JSConverter<T>::needsState, bool needsGlobalObject = JSConverter<T>::needsGlobalObject> +struct JSConverterOverloader; + +template<typename T> +struct JSConverterOverloader<T, true, true> { + template<typename U> static JSC::JSValue convert(JSC::ExecState& state, JSDOMGlobalObject& globalObject, U&& value) + { + return JSConverter<T>::convert(state, globalObject, std::forward<U>(value)); + } +}; + +template<typename T> +struct JSConverterOverloader<T, true, false> { + template<typename U> static JSC::JSValue convert(JSC::ExecState& state, U&& value) + { + return JSConverter<T>::convert(state, std::forward<U>(value)); + } + + template<typename U> static JSC::JSValue convert(JSC::ExecState& state, JSDOMGlobalObject&, U&& value) + { + return JSConverter<T>::convert(state, std::forward<U>(value)); + } +}; + +template<typename T> +struct JSConverterOverloader<T, false, false> { + template<typename U> static JSC::JSValue convert(JSC::ExecState&, U&& value) + { + return JSConverter<T>::convert(std::forward<U>(value)); + } + + template<typename U> static JSC::JSValue convert(JSC::ExecState&, JSDOMGlobalObject&, U&& value) + { + return JSConverter<T>::convert(std::forward<U>(value)); + } +}; + +template<typename T, typename U> inline JSC::JSValue toJS(U&& value) +{ + return JSConverter<T>::convert(std::forward<U>(value)); +} + +template<typename T, typename U> inline JSC::JSValue toJS(JSC::ExecState& state, U&& value) +{ + return JSConverterOverloader<T>::convert(state, std::forward<U>(value)); +} + +template<typename T, typename U> inline JSC::JSValue toJS(JSC::ExecState& state, JSDOMGlobalObject& globalObject, U&& value) +{ + return JSConverterOverloader<T>::convert(state, globalObject, std::forward<U>(value)); +} + +template<typename T, typename U> inline JSC::JSValue toJS(JSC::ExecState& state, JSC::ThrowScope& throwScope, ExceptionOr<U>&& value) +{ + if (UNLIKELY(value.hasException())) { + propagateException(state, throwScope, value.releaseException()); + return { }; + } + + return toJS<T>(state, value.releaseReturnValue()); +} + +template<typename T, typename U> inline JSC::JSValue toJS(JSC::ExecState& state, JSDOMGlobalObject& globalObject, JSC::ThrowScope& throwScope, ExceptionOr<U>&& value) +{ + if (UNLIKELY(value.hasException())) { + propagateException(state, throwScope, value.releaseException()); + return { }; + } + + return toJS<T>(state, globalObject, value.releaseReturnValue()); +} + +template<typename T, typename U> inline JSC::JSValue toJSNewlyCreated(JSC::ExecState& state, JSDOMGlobalObject& globalObject, U&& value) +{ + return JSConverter<T>::convertNewlyCreated(state, globalObject, std::forward<U>(value)); +} + +template<typename T, typename U> inline JSC::JSValue toJSNewlyCreated(JSC::ExecState& state, JSDOMGlobalObject& globalObject, JSC::ThrowScope& throwScope, ExceptionOr<U>&& value) +{ + if (UNLIKELY(value.hasException())) { + propagateException(state, throwScope, value.releaseException()); + return { }; + } + + return toJSNewlyCreated<T>(state, globalObject, value.releaseReturnValue()); +} + + +template<typename T> struct DefaultConverter { + using ReturnType = typename T::ImplementationType; +}; + +} // namespace WebCore diff --git a/Source/WebCore/bindings/js/JSDOMConvertBoolean.h b/Source/WebCore/bindings/js/JSDOMConvertBoolean.h new file mode 100644 index 000000000..853be0c7e --- /dev/null +++ b/Source/WebCore/bindings/js/JSDOMConvertBoolean.h @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2016 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +#include "IDLTypes.h" +#include "JSDOMConvertBase.h" + +namespace WebCore { + +template<> struct Converter<IDLBoolean> : DefaultConverter<IDLBoolean> { + static bool convert(JSC::ExecState& state, JSC::JSValue value) + { + return value.toBoolean(&state); + } +}; + +template<> struct JSConverter<IDLBoolean> { + static constexpr bool needsState = false; + static constexpr bool needsGlobalObject = false; + + static JSC::JSValue convert(bool value) + { + return JSC::jsBoolean(value); + } +}; + +} // namespace WebCore diff --git a/Source/WebCore/bindings/js/JSDOMConvertBufferSource.h b/Source/WebCore/bindings/js/JSDOMConvertBufferSource.h new file mode 100644 index 000000000..dc45fc129 --- /dev/null +++ b/Source/WebCore/bindings/js/JSDOMConvertBufferSource.h @@ -0,0 +1,122 @@ +/* + * Copyright (C) 2016 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +#include "BufferSource.h" +#include "JSDOMConvertInterface.h" +#include "JSDOMWrapperCache.h" +#include "JSDynamicDowncast.h" +#include <runtime/JSTypedArrays.h> + +namespace WebCore { + +// FIXME: It is wrong that we treat buffer related types as interfaces, they should be their own IDL type. + +// Add adaptors to make ArrayBuffer / ArrayBufferView / typed arrays act like normal interfaces. + +template<typename ImplementationClass> struct JSDOMWrapperConverterTraits; + +template<> struct JSDOMWrapperConverterTraits<JSC::ArrayBuffer> { + using WrapperClass = JSC::JSArrayBuffer; + using ToWrappedReturnType = JSC::ArrayBuffer*; +}; + +template<> struct JSDOMWrapperConverterTraits<JSC::ArrayBufferView> { + using WrapperClass = JSC::JSArrayBufferView; + using ToWrappedReturnType = RefPtr<ArrayBufferView>; +}; + +template<typename Adaptor> struct JSDOMWrapperConverterTraits<JSC::GenericTypedArrayView<Adaptor>> { + using WrapperClass = JSC::JSGenericTypedArrayView<Adaptor>; + using ToWrappedReturnType = RefPtr<JSC::GenericTypedArrayView<Adaptor>>; +}; + + +inline RefPtr<JSC::Int8Array> toPossiblySharedInt8Array(JSC::VM& vm, JSC::JSValue value) { return JSC::toPossiblySharedNativeTypedView<JSC::Int8Adaptor>(vm, value); } +inline RefPtr<JSC::Int16Array> toPossiblySharedInt16Array(JSC::VM& vm, JSC::JSValue value) { return JSC::toPossiblySharedNativeTypedView<JSC::Int16Adaptor>(vm, value); } +inline RefPtr<JSC::Int32Array> toPossiblySharedInt32Array(JSC::VM& vm, JSC::JSValue value) { return JSC::toPossiblySharedNativeTypedView<JSC::Int32Adaptor>(vm, value); } +inline RefPtr<JSC::Uint8Array> toPossiblySharedUint8Array(JSC::VM& vm, JSC::JSValue value) { return JSC::toPossiblySharedNativeTypedView<JSC::Uint8Adaptor>(vm, value); } +inline RefPtr<JSC::Uint8ClampedArray> toPossiblySharedUint8ClampedArray(JSC::VM& vm, JSC::JSValue value) { return JSC::toPossiblySharedNativeTypedView<JSC::Uint8ClampedAdaptor>(vm, value); } +inline RefPtr<JSC::Uint16Array> toPossiblySharedUint16Array(JSC::VM& vm, JSC::JSValue value) { return JSC::toPossiblySharedNativeTypedView<JSC::Uint16Adaptor>(vm, value); } +inline RefPtr<JSC::Uint32Array> toPossiblySharedUint32Array(JSC::VM& vm, JSC::JSValue value) { return JSC::toPossiblySharedNativeTypedView<JSC::Uint32Adaptor>(vm, value); } +inline RefPtr<JSC::Float32Array> toPossiblySharedFloat32Array(JSC::VM& vm, JSC::JSValue value) { return JSC::toPossiblySharedNativeTypedView<JSC::Float32Adaptor>(vm, value); } +inline RefPtr<JSC::Float64Array> toPossiblySharedFloat64Array(JSC::VM& vm, JSC::JSValue value) { return JSC::toPossiblySharedNativeTypedView<JSC::Float64Adaptor>(vm, value); } + +inline RefPtr<JSC::Int8Array> toUnsharedInt8Array(JSC::VM& vm, JSC::JSValue value) { return JSC::toUnsharedNativeTypedView<JSC::Int8Adaptor>(vm, value); } +inline RefPtr<JSC::Int16Array> toUnsharedInt16Array(JSC::VM& vm, JSC::JSValue value) { return JSC::toUnsharedNativeTypedView<JSC::Int16Adaptor>(vm, value); } +inline RefPtr<JSC::Int32Array> toUnsharedInt32Array(JSC::VM& vm, JSC::JSValue value) { return JSC::toUnsharedNativeTypedView<JSC::Int32Adaptor>(vm, value); } +inline RefPtr<JSC::Uint8Array> toUnsharedUint8Array(JSC::VM& vm, JSC::JSValue value) { return JSC::toUnsharedNativeTypedView<JSC::Uint8Adaptor>(vm, value); } +inline RefPtr<JSC::Uint8ClampedArray> toUnsharedUint8ClampedArray(JSC::VM& vm, JSC::JSValue value) { return JSC::toUnsharedNativeTypedView<JSC::Uint8ClampedAdaptor>(vm, value); } +inline RefPtr<JSC::Uint16Array> toUnsharedUint16Array(JSC::VM& vm, JSC::JSValue value) { return JSC::toUnsharedNativeTypedView<JSC::Uint16Adaptor>(vm, value); } +inline RefPtr<JSC::Uint32Array> toUnsharedUint32Array(JSC::VM& vm, JSC::JSValue value) { return JSC::toUnsharedNativeTypedView<JSC::Uint32Adaptor>(vm, value); } +inline RefPtr<JSC::Float32Array> toUnsharedFloat32Array(JSC::VM& vm, JSC::JSValue value) { return JSC::toUnsharedNativeTypedView<JSC::Float32Adaptor>(vm, value); } +inline RefPtr<JSC::Float64Array> toUnsharedFloat64Array(JSC::VM& vm, JSC::JSValue value) { return JSC::toUnsharedNativeTypedView<JSC::Float64Adaptor>(vm, value); } + +inline JSC::JSValue toJS(JSC::ExecState* state, JSDOMGlobalObject* globalObject, JSC::ArrayBuffer& buffer) +{ + if (auto result = getCachedWrapper(globalObject->world(), buffer)) + return result; + + // The JSArrayBuffer::create function will register the wrapper in finishCreation. + return JSC::JSArrayBuffer::create(state->vm(), globalObject->arrayBufferStructure(buffer.sharingMode()), &buffer); +} + +inline JSC::JSValue toJS(JSC::ExecState* state, JSC::JSGlobalObject* globalObject, JSC::ArrayBufferView& view) +{ + return view.wrap(state, globalObject); +} + +inline JSC::JSValue toJS(JSC::ExecState* state, JSDOMGlobalObject* globalObject, JSC::ArrayBuffer* buffer) +{ + if (!buffer) + return JSC::jsNull(); + return toJS(state, globalObject, *buffer); +} + +inline JSC::JSValue toJS(JSC::ExecState* state, JSC::JSGlobalObject* globalObject, JSC::ArrayBufferView* view) +{ + if (!view) + return JSC::jsNull(); + return toJS(state, globalObject, *view); +} + +inline RefPtr<JSC::ArrayBufferView> toPossiblySharedArrayBufferView(JSC::VM& vm, JSC::JSValue value) +{ + auto* wrapper = jsDynamicDowncast<JSC::JSArrayBufferView*>(vm, value); + if (!wrapper) + return nullptr; + return wrapper->possiblySharedImpl(); +} + +inline RefPtr<JSC::ArrayBufferView> toUnsharedArrayBufferView(JSC::VM& vm, JSC::JSValue value) +{ + auto result = toPossiblySharedArrayBufferView(vm, value); + if (!result || result->isShared()) + return nullptr; + return result; +} + +} // namespace WebCore diff --git a/Source/WebCore/bindings/js/JSDOMConvertCallbacks.h b/Source/WebCore/bindings/js/JSDOMConvertCallbacks.h new file mode 100644 index 000000000..3c1397aeb --- /dev/null +++ b/Source/WebCore/bindings/js/JSDOMConvertCallbacks.h @@ -0,0 +1,100 @@ +/* + * Copyright (C) 2016 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +#include "IDLTypes.h" +#include "JSDOMConvertBase.h" + +namespace WebCore { + +template<typename T> struct Converter<IDLCallbackFunction<T>> : DefaultConverter<IDLCallbackFunction<T>> { + template<typename ExceptionThrower = DefaultExceptionThrower> + static RefPtr<T> convert(JSC::ExecState& state, JSC::JSValue value, JSDOMGlobalObject& globalObject, ExceptionThrower&& exceptionThrower = ExceptionThrower()) + { + JSC::VM& vm = state.vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + + if (!value.isFunction()) { + exceptionThrower(state, scope); + return nullptr; + } + + return T::create(JSC::asObject(value), &globalObject); + } +}; + +template<typename T> struct JSConverter<IDLCallbackFunction<T>> { + static constexpr bool needsState = false; + static constexpr bool needsGlobalObject = false; + + template <typename U> + static JSC::JSValue convert(const U& value) + { + return toJS(Detail::getPtrOrRef(value)); + } + + template<typename U> + static JSC::JSValue convertNewlyCreated(U&& value) + { + return toJSNewlyCreated(std::forward<U>(value)); + } +}; + + +template<typename T> struct Converter<IDLCallbackInterface<T>> : DefaultConverter<IDLCallbackInterface<T>> { + template<typename ExceptionThrower = DefaultExceptionThrower> + static RefPtr<T> convert(JSC::ExecState& state, JSC::JSValue value, JSDOMGlobalObject& globalObject, ExceptionThrower&& exceptionThrower = ExceptionThrower()) + { + JSC::VM& vm = state.vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + + if (!value.isObject()) { + exceptionThrower(state, scope); + return nullptr; + } + + return T::create(JSC::asObject(value), &globalObject); + } +}; + +template<typename T> struct JSConverter<IDLCallbackInterface<T>> { + static constexpr bool needsState = false; + static constexpr bool needsGlobalObject = false; + + template <typename U> + static JSC::JSValue convert(const U& value) + { + return toJS(Detail::getPtrOrRef(value)); + } + + template<typename U> + static JSC::JSValue convertNewlyCreated(U&& value) + { + return toJSNewlyCreated(std::forward<U>(value)); + } +}; + +} // namespace WebCore diff --git a/Source/WebCore/bindings/js/JSDOMConvertDate.cpp b/Source/WebCore/bindings/js/JSDOMConvertDate.cpp new file mode 100644 index 000000000..c019a6e5b --- /dev/null +++ b/Source/WebCore/bindings/js/JSDOMConvertDate.cpp @@ -0,0 +1,49 @@ +/* + * Copyright (C) 1999-2001 Harri Porten (porten@kde.org) + * Copyright (C) 2004-2011, 2013, 2016 Apple Inc. All rights reserved. + * Copyright (C) 2007 Samuel Weinig <sam@webkit.org> + * Copyright (C) 2013 Michael Pruett <michael@68k.org> + * + * 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 + */ + +#include "config.h" +#include "JSDOMConvertDate.h" + +#include <heap/HeapInlines.h> +#include <runtime/DateInstance.h> +#include <runtime/JSCJSValueInlines.h> +#include <runtime/JSGlobalObject.h> + +using namespace JSC; + +namespace WebCore { + +// FIXME: This should get passed a global object rather than getting it out of the ExecState. +JSValue jsDate(ExecState& state, double value) +{ + return DateInstance::create(state.vm(), state.lexicalGlobalObject()->dateStructure(), value); +} + +double valueToDate(ExecState& state, JSValue value) +{ + if (value.isNumber()) + return value.asNumber(); + if (!value.inherits(state.vm(), DateInstance::info())) + return std::numeric_limits<double>::quiet_NaN(); + return static_cast<DateInstance*>(value.toObject(&state))->internalNumber(); +} + +} // namespace WebCore diff --git a/Source/WebCore/bindings/js/JSDOMConvertDate.h b/Source/WebCore/bindings/js/JSDOMConvertDate.h new file mode 100644 index 000000000..4314de6e4 --- /dev/null +++ b/Source/WebCore/bindings/js/JSDOMConvertDate.h @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2016 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +#include "IDLTypes.h" +#include "JSDOMConvertBase.h" + +namespace WebCore { + +JSC::JSValue jsDate(JSC::ExecState&, double value); +double valueToDate(JSC::ExecState&, JSC::JSValue); // NaN if the value can't be converted to a date. + +template<> struct Converter<IDLDate> : DefaultConverter<IDLDate> { + static double convert(JSC::ExecState& state, JSC::JSValue value) + { + return valueToDate(state, value); + } +}; + +template<> struct JSConverter<IDLDate> { + static constexpr bool needsState = true; + static constexpr bool needsGlobalObject = false; + + // FIXME: This should be taking a JSDOMGlobalObject and passing it to jsDate. + static JSC::JSValue convert(JSC::ExecState& state, double value) + { + return jsDate(state, value); + } +}; + +} // namespace WebCore diff --git a/Source/WebCore/bindings/js/JSDOMConvertDictionary.h b/Source/WebCore/bindings/js/JSDOMConvertDictionary.h new file mode 100644 index 000000000..19fceff83 --- /dev/null +++ b/Source/WebCore/bindings/js/JSDOMConvertDictionary.h @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2016 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +#include "IDLTypes.h" +#include "JSDOMConvertBase.h" + +namespace WebCore { + +// Specialized by generated code for IDL dictionary conversion. +template<typename T> T convertDictionary(JSC::ExecState&, JSC::JSValue); + + +template<typename T> struct Converter<IDLDictionary<T>> : DefaultConverter<IDLDictionary<T>> { + using ReturnType = T; + + static ReturnType convert(JSC::ExecState& state, JSC::JSValue value) + { + return convertDictionary<T>(state, value); + } +}; + +template<typename T> struct JSConverter<IDLDictionary<T>> { + static constexpr bool needsState = true; + static constexpr bool needsGlobalObject = true; + + static JSC::JSValue convert(JSC::ExecState& state, JSDOMGlobalObject& globalObject, const T& dictionary) + { + return convertDictionaryToJS(state, globalObject, dictionary); + } +}; + +} // namespace WebCore diff --git a/Source/WebCore/bindings/js/JSDOMConvertEnumeration.h b/Source/WebCore/bindings/js/JSDOMConvertEnumeration.h new file mode 100644 index 000000000..ec43133c2 --- /dev/null +++ b/Source/WebCore/bindings/js/JSDOMConvertEnumeration.h @@ -0,0 +1,59 @@ +/* + * Copyright (C) 2016 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +#include "IDLTypes.h" +#include "JSDOMConvertBase.h" + +namespace WebCore { + +// Specialized by generated code for IDL enumeration conversion. +template<typename T> std::optional<T> parseEnumeration(JSC::ExecState&, JSC::JSValue); +template<typename T> T convertEnumeration(JSC::ExecState&, JSC::JSValue); +template<typename T> const char* expectedEnumerationValues(); + +// Specialized by generated code for IDL enumeration conversion. +template<typename T> JSC::JSString* convertEnumerationToJS(JSC::ExecState&, T); + + +template<typename T> struct Converter<IDLEnumeration<T>> : DefaultConverter<IDLEnumeration<T>> { + static T convert(JSC::ExecState& state, JSC::JSValue value) + { + return convertEnumeration<T>(state, value); + } +}; + +template<typename T> struct JSConverter<IDLEnumeration<T>> { + static constexpr bool needsState = true; + static constexpr bool needsGlobalObject = false; + + static JSC::JSValue convert(JSC::ExecState& exec, T value) + { + return convertEnumerationToJS(exec, value); + } +}; + +} // namespace WebCore diff --git a/Source/WebCore/bindings/js/JSDOMConvertEventListener.h b/Source/WebCore/bindings/js/JSDOMConvertEventListener.h new file mode 100644 index 000000000..e55f32c3c --- /dev/null +++ b/Source/WebCore/bindings/js/JSDOMConvertEventListener.h @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2016 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +#include "IDLTypes.h" +#include "JSDOMConvertBase.h" + +namespace WebCore { + +template<typename T> struct Converter<IDLEventListener<T>> : DefaultConverter<IDLEventListener<T>> { + using ReturnType = RefPtr<T>; + + static ReturnType convert(JSC::ExecState& state, JSC::JSValue value, JSC::JSObject& thisObject) + { + auto scope = DECLARE_THROW_SCOPE(state.vm()); + + auto listener = T::create(value, thisObject, false, currentWorld(&state)); + if (!listener) + throwTypeError(&state, scope); + + return listener; + } +}; + +} // namespace WebCore diff --git a/Source/WebCore/bindings/js/JSDOMConvertIndexedDB.h b/Source/WebCore/bindings/js/JSDOMConvertIndexedDB.h new file mode 100644 index 000000000..78d7e3763 --- /dev/null +++ b/Source/WebCore/bindings/js/JSDOMConvertIndexedDB.h @@ -0,0 +1,71 @@ +/* + * Copyright (C) 2016 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +#if ENABLE(INDEXED_DATABASE) + +#include "IDBBindingUtilities.h" +#include "IDLTypes.h" +#include "JSDOMConvertBase.h" + +namespace WebCore { + +template<> struct JSConverter<IDLIDBKey> { + static constexpr bool needsState = true; + static constexpr bool needsGlobalObject = true; + + template <typename U> + static JSC::JSValue convert(JSC::ExecState& state, JSDOMGlobalObject& globalObject, U&& value) + { + return toJS(state, globalObject, std::forward<U>(value)); + } +}; + +template<> struct JSConverter<IDLIDBKeyData> { + static constexpr bool needsState = true; + static constexpr bool needsGlobalObject = true; + + template <typename U> + static JSC::JSValue convert(JSC::ExecState& state, JSDOMGlobalObject& globalObject, U&& value) + { + return toJS(&state, &globalObject, std::forward<U>(value)); + } +}; + +template<> struct JSConverter<IDLIDBValue> { + static constexpr bool needsState = true; + static constexpr bool needsGlobalObject = true; + + template <typename U> + static JSC::JSValue convert(JSC::ExecState& state, JSDOMGlobalObject& globalObject, U&& value) + { + return toJS(&state, &globalObject, std::forward<U>(value)); + } +}; + +} // namespace WebCore + +#endif diff --git a/Source/WebCore/bindings/js/JSDOMConvertInterface.h b/Source/WebCore/bindings/js/JSDOMConvertInterface.h new file mode 100644 index 000000000..6c0b5eefe --- /dev/null +++ b/Source/WebCore/bindings/js/JSDOMConvertInterface.h @@ -0,0 +1,79 @@ +/* + * Copyright (C) 2016 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +#include "IDLTypes.h" +#include "JSDOMConvertBase.h" +#include "JSDOMExceptionHandling.h" + +namespace WebCore { + +template<typename ImplementationClass> struct JSDOMWrapperConverterTraits; + +template<typename T> struct Converter<IDLInterface<T>> : DefaultConverter<IDLInterface<T>> { + using ReturnType = typename JSDOMWrapperConverterTraits<T>::ToWrappedReturnType; + using WrapperType = typename JSDOMWrapperConverterTraits<T>::WrapperClass; + + template<typename ExceptionThrower = DefaultExceptionThrower> + static ReturnType convert(JSC::ExecState& state, JSC::JSValue value, ExceptionThrower&& exceptionThrower = ExceptionThrower()) + { + auto& vm = state.vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + ReturnType object = WrapperType::toWrapped(vm, value); + if (UNLIKELY(!object)) + exceptionThrower(state, scope); + return object; + } +}; + +namespace Detail { + +template <typename T> inline T* getPtrOrRef(const T* p) { return const_cast<T*>(p); } +template <typename T> inline T& getPtrOrRef(const T& p) { return const_cast<T&>(p); } +template <typename T> inline T* getPtrOrRef(const RefPtr<T>& p) { return p.get(); } +template <typename T> inline T& getPtrOrRef(const Ref<T>& p) { return p.get(); } + +} + +template<typename T> struct JSConverter<IDLInterface<T>> { + static constexpr bool needsState = true; + static constexpr bool needsGlobalObject = true; + + template <typename U> + static JSC::JSValue convert(JSC::ExecState& state, JSDOMGlobalObject& globalObject, const U& value) + { + return toJS(&state, &globalObject, Detail::getPtrOrRef(value)); + } + + template<typename U> + static JSC::JSValue convertNewlyCreated(JSC::ExecState& state, JSDOMGlobalObject& globalObject, U&& value) + { + return toJSNewlyCreated(&state, &globalObject, std::forward<U>(value)); + } +}; + + +} // namespace WebCore diff --git a/Source/WebCore/bindings/js/JSDOMConvertJSON.h b/Source/WebCore/bindings/js/JSDOMConvertJSON.h new file mode 100644 index 000000000..2f1b4d2b4 --- /dev/null +++ b/Source/WebCore/bindings/js/JSDOMConvertJSON.h @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2016 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +#include "IDLTypes.h" +#include "JSDOMConvertBase.h" +#include <runtime/JSONObject.h> + +namespace WebCore { + +template<> struct Converter<IDLJSON> : DefaultConverter<IDLJSON> { + static String convert(JSC::ExecState& state, JSC::JSValue value) + { + return JSC::JSONStringify(&state, value, 0); + } +}; + +template<> struct JSConverter<IDLJSON> { + static constexpr bool needsState = true; + static constexpr bool needsGlobalObject = false; + + static JSC::JSValue convert(JSC::ExecState& state, const String& value) + { + return JSC::JSONParse(&state, value); + } +}; + +} // namespace WebCore diff --git a/Source/WebCore/bindings/js/JSDOMConvertNull.h b/Source/WebCore/bindings/js/JSDOMConvertNull.h new file mode 100644 index 000000000..262d75106 --- /dev/null +++ b/Source/WebCore/bindings/js/JSDOMConvertNull.h @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2016 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +#include "IDLTypes.h" +#include "JSDOMConvertBase.h" + +namespace WebCore { + +template<> struct Converter<IDLNull> : DefaultConverter<IDLNull> { + static std::nullptr_t convert(JSC::ExecState&, JSC::JSValue) + { + return nullptr; + } +}; + +template<> struct JSConverter<IDLNull> { + static constexpr bool needsState = false; + static constexpr bool needsGlobalObject = false; + + static JSC::JSValue convert(std::nullptr_t) + { + return JSC::jsNull(); + } +}; + +} // namespace WebCore diff --git a/Source/WebCore/bindings/js/JSDOMConvertNullable.h b/Source/WebCore/bindings/js/JSDOMConvertNullable.h new file mode 100644 index 000000000..c42c83150 --- /dev/null +++ b/Source/WebCore/bindings/js/JSDOMConvertNullable.h @@ -0,0 +1,162 @@ +/* + * Copyright (C) 2016 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +#include "IDLTypes.h" +#include "JSDOMConvertAny.h" +#include "JSDOMConvertInterface.h" +#include "JSDOMConvertNumbers.h" +#include "JSDOMConvertStrings.h" + +namespace WebCore { + +namespace Detail { + +template<typename IDLType> +struct NullableConversionType; + +template<typename IDLType> +struct NullableConversionType { + using Type = typename IDLNullable<IDLType>::ImplementationType; +}; + +template<typename T> +struct NullableConversionType<IDLInterface<T>> { + using Type = typename Converter<IDLInterface<T>>::ReturnType; +}; + +template<> +struct NullableConversionType<IDLAny> { + using Type = typename Converter<IDLAny>::ReturnType; +}; + +} + +template<typename T> struct Converter<IDLNullable<T>> : DefaultConverter<IDLNullable<T>> { + using ReturnType = typename Detail::NullableConversionType<T>::Type; + + // 1. If Type(V) is not Object, and the conversion to an IDL value is being performed + // due to V being assigned to an attribute whose type is a nullable callback function + // that is annotated with [TreatNonObjectAsNull], then return the IDL nullable type T? + // value null. + // + // NOTE: Handled elsewhere. + // + // 2. Otherwise, if V is null or undefined, then return the IDL nullable type T? value null. + // 3. Otherwise, return the result of converting V using the rules for the inner IDL type T. + + static ReturnType convert(JSC::ExecState& state, JSC::JSValue value) + { + if (value.isUndefinedOrNull()) + return T::nullValue(); + return Converter<T>::convert(state, value); + } + static ReturnType convert(JSC::ExecState& state, JSC::JSValue value, JSC::JSObject& thisObject) + { + if (value.isUndefinedOrNull()) + return T::nullValue(); + return Converter<T>::convert(state, value, thisObject); + } + static ReturnType convert(JSC::ExecState& state, JSC::JSValue value, JSDOMGlobalObject& globalObject) + { + if (value.isUndefinedOrNull()) + return T::nullValue(); + return Converter<T>::convert(state, value, globalObject); + } + static ReturnType convert(JSC::ExecState& state, JSC::JSValue value, IntegerConversionConfiguration configuration) + { + if (value.isUndefinedOrNull()) + return T::nullValue(); + return Converter<T>::convert(state, value, configuration); + } + static ReturnType convert(JSC::ExecState& state, JSC::JSValue value, StringConversionConfiguration configuration) + { + if (value.isUndefinedOrNull()) + return T::nullValue(); + return Converter<T>::convert(state, value, configuration); + } + template<typename ExceptionThrower = DefaultExceptionThrower> + static ReturnType convert(JSC::ExecState& state, JSC::JSValue value, ExceptionThrower&& exceptionThrower) + { + if (value.isUndefinedOrNull()) + return T::nullValue(); + return Converter<T>::convert(state, value, std::forward<ExceptionThrower>(exceptionThrower)); + } + template<typename ExceptionThrower = DefaultExceptionThrower> + static ReturnType convert(JSC::ExecState& state, JSC::JSValue value, JSC::JSObject& thisObject, ExceptionThrower&& exceptionThrower) + { + if (value.isUndefinedOrNull()) + return T::nullValue(); + return Converter<T>::convert(state, value, thisObject, std::forward<ExceptionThrower>(exceptionThrower)); + } + template<typename ExceptionThrower = DefaultExceptionThrower> + static ReturnType convert(JSC::ExecState& state, JSC::JSValue value, JSDOMGlobalObject& globalObject, ExceptionThrower&& exceptionThrower) + { + if (value.isUndefinedOrNull()) + return T::nullValue(); + return Converter<T>::convert(state, value, globalObject, std::forward<ExceptionThrower>(exceptionThrower)); + } +}; + +template<typename T> struct JSConverter<IDLNullable<T>> { + using ImplementationType = typename IDLNullable<T>::ImplementationType; + + static constexpr bool needsState = JSConverter<T>::needsState; + static constexpr bool needsGlobalObject = JSConverter<T>::needsGlobalObject; + + template<typename U> + static JSC::JSValue convert(U&& value) + { + if (T::isNullValue(value)) + return JSC::jsNull(); + return JSConverter<T>::convert(T::extractValueFromNullable(value)); + } + template<typename U> + static JSC::JSValue convert(JSC::ExecState& state, U&& value) + { + if (T::isNullValue(value)) + return JSC::jsNull(); + return JSConverter<T>::convert(state, T::extractValueFromNullable(value)); + } + template<typename U> + static JSC::JSValue convert(JSC::ExecState& state, JSDOMGlobalObject& globalObject, U&& value) + { + if (T::isNullValue(value)) + return JSC::jsNull(); + return JSConverter<T>::convert(state, globalObject, T::extractValueFromNullable(value)); + } + + template<typename U> + static JSC::JSValue convertNewlyCreated(JSC::ExecState& state, JSDOMGlobalObject& globalObject, U&& value) + { + if (T::isNullValue(value)) + return JSC::jsNull(); + return JSConverter<T>::convert(state, globalObject, T::extractValueFromNullable(value)); + } +}; + + +} // namespace WebCore diff --git a/Source/WebCore/bindings/js/JSDOMConvertNumbers.cpp b/Source/WebCore/bindings/js/JSDOMConvertNumbers.cpp new file mode 100644 index 000000000..ff1f97011 --- /dev/null +++ b/Source/WebCore/bindings/js/JSDOMConvertNumbers.cpp @@ -0,0 +1,348 @@ +/* + * Copyright (C) 1999-2001 Harri Porten (porten@kde.org) + * Copyright (C) 2004-2011, 2013, 2016 Apple Inc. All rights reserved. + * Copyright (C) 2007 Samuel Weinig <sam@webkit.org> + * Copyright (C) 2013 Michael Pruett <michael@68k.org> + * + * 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 + */ + +#include "config.h" +#include "JSDOMConvertNumbers.h" + +#include "JSDOMExceptionHandling.h" +#include <heap/HeapInlines.h> +#include <runtime/JSCJSValueInlines.h> +#include <wtf/MathExtras.h> +#include <wtf/text/WTFString.h> + +using namespace JSC; + +namespace WebCore { + +static const int32_t kMaxInt32 = 0x7fffffff; +static const int32_t kMinInt32 = -kMaxInt32 - 1; +static const uint32_t kMaxUInt32 = 0xffffffffU; +static const int64_t kJSMaxInteger = 0x20000000000000LL - 1; // 2^53 - 1, largest integer exactly representable in ECMAScript. + +static String rangeErrorString(double value, double min, double max) +{ + return makeString("Value ", String::numberToStringECMAScript(value), " is outside the range [", String::numberToStringECMAScript(min), ", ", String::numberToStringECMAScript(max), "]"); +} + +static double enforceRange(ExecState& state, double x, double minimum, double maximum) +{ + VM& vm = state.vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + + if (std::isnan(x) || std::isinf(x)) { + throwTypeError(&state, scope, rangeErrorString(x, minimum, maximum)); + return 0; + } + x = trunc(x); + if (x < minimum || x > maximum) { + throwTypeError(&state, scope, rangeErrorString(x, minimum, maximum)); + return 0; + } + return x; +} + +template <typename T> +struct IntTypeLimits { +}; + +template <> +struct IntTypeLimits<int8_t> { + static const int8_t minValue = -128; + static const int8_t maxValue = 127; + static const unsigned numberOfValues = 256; // 2^8 +}; + +template <> +struct IntTypeLimits<uint8_t> { + static const uint8_t maxValue = 255; + static const unsigned numberOfValues = 256; // 2^8 +}; + +template <> +struct IntTypeLimits<int16_t> { + static const short minValue = -32768; + static const short maxValue = 32767; + static const unsigned numberOfValues = 65536; // 2^16 +}; + +template <> +struct IntTypeLimits<uint16_t> { + static const unsigned short maxValue = 65535; + static const unsigned numberOfValues = 65536; // 2^16 +}; + +template <typename T> +static inline T toSmallerInt(ExecState& state, JSValue value, IntegerConversionConfiguration configuration) +{ + VM& vm = state.vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + + static_assert(std::is_signed<T>::value && std::is_integral<T>::value, "Should only be used for signed integral types"); + + typedef IntTypeLimits<T> LimitsTrait; + // Fast path if the value is already a 32-bit signed integer in the right range. + if (value.isInt32()) { + int32_t d = value.asInt32(); + if (d >= LimitsTrait::minValue && d <= LimitsTrait::maxValue) + return static_cast<T>(d); + switch (configuration) { + case IntegerConversionConfiguration::Normal: + break; + case IntegerConversionConfiguration::EnforceRange: + throwTypeError(&state, scope); + return 0; + case IntegerConversionConfiguration::Clamp: + return d < LimitsTrait::minValue ? LimitsTrait::minValue : LimitsTrait::maxValue; + } + d %= LimitsTrait::numberOfValues; + return static_cast<T>(d > LimitsTrait::maxValue ? d - LimitsTrait::numberOfValues : d); + } + + double x = value.toNumber(&state); + RETURN_IF_EXCEPTION(scope, 0); + + switch (configuration) { + case IntegerConversionConfiguration::Normal: + break; + case IntegerConversionConfiguration::EnforceRange: + return enforceRange(state, x, LimitsTrait::minValue, LimitsTrait::maxValue); + case IntegerConversionConfiguration::Clamp: + return std::isnan(x) ? 0 : clampTo<T>(x); + } + + if (std::isnan(x) || std::isinf(x) || !x) + return 0; + + x = x < 0 ? -floor(fabs(x)) : floor(fabs(x)); + x = fmod(x, LimitsTrait::numberOfValues); + + return static_cast<T>(x > LimitsTrait::maxValue ? x - LimitsTrait::numberOfValues : x); +} + +template <typename T> +static inline T toSmallerUInt(ExecState& state, JSValue value, IntegerConversionConfiguration configuration) +{ + VM& vm = state.vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + + static_assert(std::is_unsigned<T>::value && std::is_integral<T>::value, "Should only be used for unsigned integral types"); + + typedef IntTypeLimits<T> LimitsTrait; + // Fast path if the value is already a 32-bit unsigned integer in the right range. + if (value.isUInt32()) { + uint32_t d = value.asUInt32(); + if (d <= LimitsTrait::maxValue) + return static_cast<T>(d); + switch (configuration) { + case IntegerConversionConfiguration::Normal: + return static_cast<T>(d); + case IntegerConversionConfiguration::EnforceRange: + throwTypeError(&state, scope); + return 0; + case IntegerConversionConfiguration::Clamp: + return LimitsTrait::maxValue; + } + } + + double x = value.toNumber(&state); + RETURN_IF_EXCEPTION(scope, 0); + + switch (configuration) { + case IntegerConversionConfiguration::Normal: + break; + case IntegerConversionConfiguration::EnforceRange: + return enforceRange(state, x, 0, LimitsTrait::maxValue); + case IntegerConversionConfiguration::Clamp: + return std::isnan(x) ? 0 : clampTo<T>(x); + } + + if (std::isnan(x) || std::isinf(x) || !x) + return 0; + + x = x < 0 ? -floor(fabs(x)) : floor(fabs(x)); + return static_cast<T>(fmod(x, LimitsTrait::numberOfValues)); +} + +int8_t toInt8EnforceRange(JSC::ExecState& state, JSValue value) +{ + return toSmallerInt<int8_t>(state, value, IntegerConversionConfiguration::EnforceRange); +} + +uint8_t toUInt8EnforceRange(JSC::ExecState& state, JSValue value) +{ + return toSmallerUInt<uint8_t>(state, value, IntegerConversionConfiguration::EnforceRange); +} + +int8_t toInt8Clamp(JSC::ExecState& state, JSValue value) +{ + return toSmallerInt<int8_t>(state, value, IntegerConversionConfiguration::Clamp); +} + +uint8_t toUInt8Clamp(JSC::ExecState& state, JSValue value) +{ + return toSmallerUInt<uint8_t>(state, value, IntegerConversionConfiguration::Clamp); +} + +// http://www.w3.org/TR/WebIDL/#es-byte +int8_t toInt8(ExecState& state, JSValue value) +{ + return toSmallerInt<int8_t>(state, value, IntegerConversionConfiguration::Normal); +} + +// http://www.w3.org/TR/WebIDL/#es-octet +uint8_t toUInt8(ExecState& state, JSValue value) +{ + return toSmallerUInt<uint8_t>(state, value, IntegerConversionConfiguration::Normal); +} + +int16_t toInt16EnforceRange(ExecState& state, JSValue value) +{ + return toSmallerInt<int16_t>(state, value, IntegerConversionConfiguration::EnforceRange); +} + +uint16_t toUInt16EnforceRange(ExecState& state, JSValue value) +{ + return toSmallerUInt<uint16_t>(state, value, IntegerConversionConfiguration::EnforceRange); +} + +int16_t toInt16Clamp(ExecState& state, JSValue value) +{ + return toSmallerInt<int16_t>(state, value, IntegerConversionConfiguration::Clamp); +} + +uint16_t toUInt16Clamp(ExecState& state, JSValue value) +{ + return toSmallerUInt<uint16_t>(state, value, IntegerConversionConfiguration::Clamp); +} + +// http://www.w3.org/TR/WebIDL/#es-short +int16_t toInt16(ExecState& state, JSValue value) +{ + return toSmallerInt<int16_t>(state, value, IntegerConversionConfiguration::Normal); +} + +// http://www.w3.org/TR/WebIDL/#es-unsigned-short +uint16_t toUInt16(ExecState& state, JSValue value) +{ + return toSmallerUInt<uint16_t>(state, value, IntegerConversionConfiguration::Normal); +} + +// http://www.w3.org/TR/WebIDL/#es-long +int32_t toInt32EnforceRange(ExecState& state, JSValue value) +{ + VM& vm = state.vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + + if (value.isInt32()) + return value.asInt32(); + + double x = value.toNumber(&state); + RETURN_IF_EXCEPTION(scope, 0); + return enforceRange(state, x, kMinInt32, kMaxInt32); +} + +int32_t toInt32Clamp(ExecState& state, JSValue value) +{ + if (value.isInt32()) + return value.asInt32(); + + double x = value.toNumber(&state); + return std::isnan(x) ? 0 : clampTo<int32_t>(x); +} + +uint32_t toUInt32Clamp(ExecState& state, JSValue value) +{ + if (value.isUInt32()) + return value.asUInt32(); + + double x = value.toNumber(&state); + return std::isnan(x) ? 0 : clampTo<uint32_t>(x); +} + +// http://www.w3.org/TR/WebIDL/#es-unsigned-long +uint32_t toUInt32EnforceRange(ExecState& state, JSValue value) +{ + VM& vm = state.vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + + if (value.isUInt32()) + return value.asUInt32(); + + double x = value.toNumber(&state); + RETURN_IF_EXCEPTION(scope, 0); + return enforceRange(state, x, 0, kMaxUInt32); +} + +int64_t toInt64EnforceRange(ExecState& state, JSC::JSValue value) +{ + VM& vm = state.vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + + double x = value.toNumber(&state); + RETURN_IF_EXCEPTION(scope, 0); + return enforceRange(state, x, -kJSMaxInteger, kJSMaxInteger); +} + +uint64_t toUInt64EnforceRange(ExecState& state, JSC::JSValue value) +{ + VM& vm = state.vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + + double x = value.toNumber(&state); + RETURN_IF_EXCEPTION(scope, 0); + return enforceRange(state, x, 0, kJSMaxInteger); +} + +int64_t toInt64Clamp(ExecState& state, JSC::JSValue value) +{ + double x = value.toNumber(&state); + return std::isnan(x) ? 0 : static_cast<int64_t>(std::min<double>(std::max<double>(x, -kJSMaxInteger), kJSMaxInteger)); +} + +uint64_t toUInt64Clamp(ExecState& state, JSC::JSValue value) +{ + double x = value.toNumber(&state); + return std::isnan(x) ? 0 : static_cast<uint64_t>(std::min<double>(std::max<double>(x, 0), kJSMaxInteger)); +} + +// http://www.w3.org/TR/WebIDL/#es-long-long +int64_t toInt64(ExecState& state, JSValue value) +{ + double x = value.toNumber(&state); + + // Map NaNs and +/-Infinity to 0; convert finite values modulo 2^64. + unsigned long long n; + doubleToInteger(x, n); + return n; +} + +// http://www.w3.org/TR/WebIDL/#es-unsigned-long-long +uint64_t toUInt64(ExecState& state, JSValue value) +{ + double x = value.toNumber(&state); + + // Map NaNs and +/-Infinity to 0; convert finite values modulo 2^64. + unsigned long long n; + doubleToInteger(x, n); + return n; +} + +} // namespace WebCore diff --git a/Source/WebCore/bindings/js/JSDOMConvertNumbers.h b/Source/WebCore/bindings/js/JSDOMConvertNumbers.h new file mode 100644 index 000000000..b79ed05eb --- /dev/null +++ b/Source/WebCore/bindings/js/JSDOMConvertNumbers.h @@ -0,0 +1,424 @@ +/* + * Copyright (C) 2016 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +#include "IDLTypes.h" +#include "JSDOMConvertBase.h" +#include "JSDOMExceptionHandling.h" +#include <runtime/JSCJSValueInlines.h> + +namespace WebCore { + +enum class IntegerConversionConfiguration { Normal, EnforceRange, Clamp }; + +template<typename T> typename Converter<T>::ReturnType convert(JSC::ExecState&, JSC::JSValue, IntegerConversionConfiguration); + +template<typename T> inline typename Converter<T>::ReturnType convert(JSC::ExecState& state, JSC::JSValue value, IntegerConversionConfiguration configuration) +{ + return Converter<T>::convert(state, value, configuration); +} + +// The following functions convert values to integers as per the WebIDL specification. +// 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. + +WEBCORE_EXPORT int8_t toInt8EnforceRange(JSC::ExecState&, JSC::JSValue); +WEBCORE_EXPORT uint8_t toUInt8EnforceRange(JSC::ExecState&, JSC::JSValue); +WEBCORE_EXPORT int16_t toInt16EnforceRange(JSC::ExecState&, JSC::JSValue); +WEBCORE_EXPORT uint16_t toUInt16EnforceRange(JSC::ExecState&, JSC::JSValue); +WEBCORE_EXPORT int32_t toInt32EnforceRange(JSC::ExecState&, JSC::JSValue); +WEBCORE_EXPORT uint32_t toUInt32EnforceRange(JSC::ExecState&, JSC::JSValue); +WEBCORE_EXPORT int64_t toInt64EnforceRange(JSC::ExecState&, JSC::JSValue); +WEBCORE_EXPORT uint64_t toUInt64EnforceRange(JSC::ExecState&, JSC::JSValue); + +WEBCORE_EXPORT int8_t toInt8Clamp(JSC::ExecState&, JSC::JSValue); +WEBCORE_EXPORT uint8_t toUInt8Clamp(JSC::ExecState&, JSC::JSValue); +WEBCORE_EXPORT int16_t toInt16Clamp(JSC::ExecState&, JSC::JSValue); +WEBCORE_EXPORT uint16_t toUInt16Clamp(JSC::ExecState&, JSC::JSValue); +WEBCORE_EXPORT int32_t toInt32Clamp(JSC::ExecState&, JSC::JSValue); +WEBCORE_EXPORT uint32_t toUInt32Clamp(JSC::ExecState&, JSC::JSValue); +WEBCORE_EXPORT int64_t toInt64Clamp(JSC::ExecState&, JSC::JSValue); +WEBCORE_EXPORT uint64_t toUInt64Clamp(JSC::ExecState&, JSC::JSValue); + +WEBCORE_EXPORT int8_t toInt8(JSC::ExecState&, JSC::JSValue); +WEBCORE_EXPORT uint8_t toUInt8(JSC::ExecState&, JSC::JSValue); +WEBCORE_EXPORT int16_t toInt16(JSC::ExecState&, JSC::JSValue); +WEBCORE_EXPORT uint16_t toUInt16(JSC::ExecState&, JSC::JSValue); +WEBCORE_EXPORT int64_t toInt64(JSC::ExecState&, JSC::JSValue); +WEBCORE_EXPORT uint64_t toUInt64(JSC::ExecState&, JSC::JSValue); + + +// MARK: - +// MARK: Integer types + +template<> struct Converter<IDLByte> : DefaultConverter<IDLByte> { + static int8_t convert(JSC::ExecState& state, JSC::JSValue value, IntegerConversionConfiguration configuration = IntegerConversionConfiguration::Normal) + { + switch (configuration) { + case IntegerConversionConfiguration::Normal: + break; + case IntegerConversionConfiguration::EnforceRange: + return toInt8EnforceRange(state, value); + case IntegerConversionConfiguration::Clamp: + return toInt8Clamp(state, value); + } + return toInt8(state, value); + } +}; + +template<> struct JSConverter<IDLByte> { + using Type = typename IDLByte::ImplementationType; + + static constexpr bool needsState = false; + static constexpr bool needsGlobalObject = false; + + static JSC::JSValue convert(Type value) + { + return JSC::jsNumber(value); + } +}; + +template<> struct Converter<IDLOctet> : DefaultConverter<IDLOctet> { + static uint8_t convert(JSC::ExecState& state, JSC::JSValue value, IntegerConversionConfiguration configuration = IntegerConversionConfiguration::Normal) + { + switch (configuration) { + case IntegerConversionConfiguration::Normal: + break; + case IntegerConversionConfiguration::EnforceRange: + return toUInt8EnforceRange(state, value); + case IntegerConversionConfiguration::Clamp: + return toUInt8Clamp(state, value); + } + return toUInt8(state, value); + } +}; + +template<> struct JSConverter<IDLOctet> { + using Type = typename IDLOctet::ImplementationType; + + static constexpr bool needsState = false; + static constexpr bool needsGlobalObject = false; + + static JSC::JSValue convert(Type value) + { + return JSC::jsNumber(value); + } +}; + +template<> struct Converter<IDLShort> : DefaultConverter<IDLShort> { + static int16_t convert(JSC::ExecState& state, JSC::JSValue value, IntegerConversionConfiguration configuration = IntegerConversionConfiguration::Normal) + { + switch (configuration) { + case IntegerConversionConfiguration::Normal: + break; + case IntegerConversionConfiguration::EnforceRange: + return toInt16EnforceRange(state, value); + case IntegerConversionConfiguration::Clamp: + return toInt16Clamp(state, value); + } + return toInt16(state, value); + } +}; + +template<> struct JSConverter<IDLShort> { + using Type = typename IDLShort::ImplementationType; + + static constexpr bool needsState = false; + static constexpr bool needsGlobalObject = false; + + static JSC::JSValue convert(Type value) + { + return JSC::jsNumber(value); + } +}; + +template<> struct Converter<IDLUnsignedShort> : DefaultConverter<IDLUnsignedShort> { + static uint16_t convert(JSC::ExecState& state, JSC::JSValue value, IntegerConversionConfiguration configuration = IntegerConversionConfiguration::Normal) + { + switch (configuration) { + case IntegerConversionConfiguration::Normal: + break; + case IntegerConversionConfiguration::EnforceRange: + return toUInt16EnforceRange(state, value); + case IntegerConversionConfiguration::Clamp: + return toUInt16Clamp(state, value); + } + return toUInt16(state, value); + } +}; + +template<> struct JSConverter<IDLUnsignedShort> { + using Type = typename IDLUnsignedShort::ImplementationType; + + static constexpr bool needsState = false; + static constexpr bool needsGlobalObject = false; + + static JSC::JSValue convert(Type value) + { + return JSC::jsNumber(value); + } +}; + +template<> struct Converter<IDLLong> : DefaultConverter<IDLLong> { + static inline int32_t convert(JSC::ExecState&, JSC::ThrowScope&, double number) + { + return JSC::toInt32(number); + } + + static int32_t convert(JSC::ExecState& state, JSC::JSValue value, IntegerConversionConfiguration configuration = IntegerConversionConfiguration::Normal) + { + switch (configuration) { + case IntegerConversionConfiguration::Normal: + break; + case IntegerConversionConfiguration::EnforceRange: + return toInt32EnforceRange(state, value); + case IntegerConversionConfiguration::Clamp: + return toInt32Clamp(state, value); + } + return value.toInt32(&state); + } +}; + +template<> struct JSConverter<IDLLong> { + using Type = typename IDLLong::ImplementationType; + + static constexpr bool needsState = false; + static constexpr bool needsGlobalObject = false; + + static JSC::JSValue convert(Type value) + { + return JSC::jsNumber(value); + } +}; + +template<> struct Converter<IDLUnsignedLong> : DefaultConverter<IDLUnsignedLong> { + static uint32_t convert(JSC::ExecState& state, JSC::JSValue value, IntegerConversionConfiguration configuration = IntegerConversionConfiguration::Normal) + { + switch (configuration) { + case IntegerConversionConfiguration::Normal: + break; + case IntegerConversionConfiguration::EnforceRange: + return toUInt32EnforceRange(state, value); + case IntegerConversionConfiguration::Clamp: + return toUInt32Clamp(state, value); + } + return value.toUInt32(&state); + } +}; + +template<> struct JSConverter<IDLUnsignedLong> { + using Type = typename IDLUnsignedLong::ImplementationType; + + static constexpr bool needsState = false; + static constexpr bool needsGlobalObject = false; + + static JSC::JSValue convert(Type value) + { + return JSC::jsNumber(value); + } +}; + +template<> struct Converter<IDLLongLong> : DefaultConverter<IDLLongLong> { + static int64_t convert(JSC::ExecState& state, JSC::JSValue value, IntegerConversionConfiguration configuration = IntegerConversionConfiguration::Normal) + { + if (value.isInt32()) + return value.asInt32(); + + switch (configuration) { + case IntegerConversionConfiguration::Normal: + break; + case IntegerConversionConfiguration::EnforceRange: + return toInt64EnforceRange(state, value); + case IntegerConversionConfiguration::Clamp: + return toInt64Clamp(state, value); + } + return toInt64(state, value); + } +}; + +template<> struct JSConverter<IDLLongLong> { + using Type = typename IDLLongLong::ImplementationType; + + static constexpr bool needsState = false; + static constexpr bool needsGlobalObject = false; + + static JSC::JSValue convert(Type value) + { + return JSC::jsNumber(value); + } +}; + +template<> struct Converter<IDLUnsignedLongLong> : DefaultConverter<IDLUnsignedLongLong> { + static uint64_t convert(JSC::ExecState& state, JSC::JSValue value, IntegerConversionConfiguration configuration = IntegerConversionConfiguration::Normal) + { + if (value.isUInt32()) + return value.asUInt32(); + + switch (configuration) { + case IntegerConversionConfiguration::Normal: + break; + case IntegerConversionConfiguration::EnforceRange: + return toUInt64EnforceRange(state, value); + case IntegerConversionConfiguration::Clamp: + return toUInt64Clamp(state, value); + } + return toUInt64(state, value); + } +}; + +template<> struct JSConverter<IDLUnsignedLongLong> { + using Type = typename IDLUnsignedLongLong::ImplementationType; + + static constexpr bool needsState = false; + static constexpr bool needsGlobalObject = false; + + static JSC::JSValue convert(Type value) + { + return JSC::jsNumber(value); + } +}; + +// MARK: - +// MARK: Floating point types + +template<> struct Converter<IDLFloat> : DefaultConverter<IDLFloat> { + + static inline float convert(JSC::ExecState& state, JSC::ThrowScope& scope, double number) + { + if (UNLIKELY(!std::isfinite(number))) + throwNonFiniteTypeError(state, scope); + return static_cast<float>(number); + } + + static float convert(JSC::ExecState& state, JSC::JSValue value) + { + JSC::VM& vm = state.vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + double number = value.toNumber(&state); + if (UNLIKELY(!std::isfinite(number))) + throwNonFiniteTypeError(state, scope); + return static_cast<float>(number); + } +}; + +template<> struct JSConverter<IDLFloat> { + using Type = typename IDLFloat::ImplementationType; + + static constexpr bool needsState = false; + static constexpr bool needsGlobalObject = false; + + static JSC::JSValue convert(Type value) + { + return JSC::jsNumber(value); + } +}; + +template<> struct Converter<IDLUnrestrictedFloat> : DefaultConverter<IDLUnrestrictedFloat> { + static inline float convert(JSC::ExecState&, JSC::ThrowScope&, double number) + { + return static_cast<float>(number); + } + + static float convert(JSC::ExecState& state, JSC::JSValue value) + { + return static_cast<float>(value.toNumber(&state)); + } +}; + +template<> struct JSConverter<IDLUnrestrictedFloat> { + using Type = typename IDLUnrestrictedFloat::ImplementationType; + + static constexpr bool needsState = false; + static constexpr bool needsGlobalObject = false; + + static JSC::JSValue convert(Type value) + { + return JSC::jsNumber(value); + } +}; + +template<> struct Converter<IDLDouble> : DefaultConverter<IDLDouble> { + static inline double convert(JSC::ExecState& state, JSC::ThrowScope& scope, double number) + { + if (UNLIKELY(!std::isfinite(number))) + throwNonFiniteTypeError(state, scope); + return number; + } + + static double convert(JSC::ExecState& state, JSC::JSValue value) + { + JSC::VM& vm = state.vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + double number = value.toNumber(&state); + if (UNLIKELY(!std::isfinite(number))) + throwNonFiniteTypeError(state, scope); + return number; + } +}; + +template<> struct JSConverter<IDLDouble> { + using Type = typename IDLDouble::ImplementationType; + + static constexpr bool needsState = false; + static constexpr bool needsGlobalObject = false; + + static JSC::JSValue convert(Type value) + { + return JSC::jsNumber(value); + } +}; + +template<> struct Converter<IDLUnrestrictedDouble> : DefaultConverter<IDLUnrestrictedDouble> { + static inline double convert(JSC::ExecState&, JSC::ThrowScope&, double number) + { + return number; + } + + static double convert(JSC::ExecState& state, JSC::JSValue value) + { + return value.toNumber(&state); + } +}; + +template<> struct JSConverter<IDLUnrestrictedDouble> { + using Type = typename IDLUnrestrictedDouble::ImplementationType; + + static constexpr bool needsState = false; + static constexpr bool needsGlobalObject = false; + + static JSC::JSValue convert(Type value) + { + return JSC::jsNumber(value); + } + + // Add overload for MediaTime. + static JSC::JSValue convert(MediaTime value) + { + return JSC::jsNumber(value.toDouble()); + } +}; + +} // namespace WebCore diff --git a/Source/WebCore/bindings/js/JSDOMConvertObject.h b/Source/WebCore/bindings/js/JSDOMConvertObject.h new file mode 100644 index 000000000..379eb42b8 --- /dev/null +++ b/Source/WebCore/bindings/js/JSDOMConvertObject.h @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2016 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +#include "IDLTypes.h" +#include "JSDOMConvertBase.h" + +namespace WebCore { + +template<> struct Converter<IDLObject> : DefaultConverter<IDLObject> { + template<typename ExceptionThrower = DefaultExceptionThrower> + static JSC::Strong<JSC::JSObject> convert(JSC::ExecState& state, JSC::JSValue value, ExceptionThrower&& exceptionThrower = ExceptionThrower()) + { + JSC::VM& vm = state.vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + + if (!value.isObject()) { + exceptionThrower(state, scope); + return { }; + } + + return { vm, JSC::asObject(value) }; + } +}; + +} // namespace WebCore diff --git a/Source/WebCore/bindings/js/JSDOMConvertRecord.h b/Source/WebCore/bindings/js/JSDOMConvertRecord.h new file mode 100644 index 000000000..db1dabf8d --- /dev/null +++ b/Source/WebCore/bindings/js/JSDOMConvertRecord.h @@ -0,0 +1,166 @@ +/* + * Copyright (C) 2016 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +#include "IDLTypes.h" +#include "JSDOMConvertStrings.h" +#include <runtime/ObjectConstructor.h> + +namespace WebCore { + +namespace Detail { + +template<typename IDLStringType> +struct IdentifierConverter; + +template<> struct IdentifierConverter<IDLDOMString> { + static String convert(JSC::ExecState&, const JSC::Identifier& identifier) + { + return identifier.string(); + } +}; + +template<> struct IdentifierConverter<IDLByteString> { + static String convert(JSC::ExecState& state, const JSC::Identifier& identifier) + { + return identifierToByteString(state, identifier); + } +}; + +template<> struct IdentifierConverter<IDLUSVString> { + static String convert(JSC::ExecState& state, const JSC::Identifier& identifier) + { + return identifierToUSVString(state, identifier); + } +}; + +} + +template<typename K, typename V> struct Converter<IDLRecord<K, V>> : DefaultConverter<IDLRecord<K, V>> { + using ReturnType = typename IDLRecord<K, V>::ImplementationType; + using KeyType = typename K::ImplementationType; + using ValueType = typename V::ImplementationType; + + static ReturnType convert(JSC::ExecState& state, JSC::JSValue value) + { + auto& vm = state.vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + + // 1. Let result be a new empty instance of record<K, V>. + // 2. If Type(O) is Undefined or Null, return result. + if (value.isUndefinedOrNull()) + return { }; + + // 3. If Type(O) is not Object, throw a TypeError. + if (!value.isObject()) { + throwTypeError(&state, scope); + return { }; + } + + JSC::JSObject* object = JSC::asObject(value); + + ReturnType result; + + // 4. Let keys be ? O.[[OwnPropertyKeys]](). + JSC::PropertyNameArray keys(&vm, JSC::PropertyNameMode::Strings); + object->getOwnPropertyNames(object, &state, keys, JSC::EnumerationMode()); + RETURN_IF_EXCEPTION(scope, { }); + + // 5. Repeat, for each element key of keys in List order: + for (auto& key : keys) { + // 1. Let desc be ? O.[[GetOwnProperty]](key). + JSC::PropertyDescriptor descriptor; + bool didGetDescriptor = object->getOwnPropertyDescriptor(&state, key, descriptor); + RETURN_IF_EXCEPTION(scope, { }); + + if (!didGetDescriptor) + continue; + + // 2. If desc is not undefined and desc.[[Enumerable]] is true: + + // FIXME: Do we need to check for enumerable / undefined, or is this handled by the default + // enumeration mode? + + if (!descriptor.value().isUndefined() && descriptor.enumerable()) { + // 1. Let typedKey be key converted to an IDL value of type K. + auto typedKey = Detail::IdentifierConverter<K>::convert(state, key); + + // 2. Let value be ? Get(O, key). + auto subValue = object->get(&state, key); + RETURN_IF_EXCEPTION(scope, { }); + + // 3. Let typedValue be value converted to an IDL value of type V. + auto typedValue = Converter<V>::convert(state, subValue); + RETURN_IF_EXCEPTION(scope, { }); + + // 4. If typedKey is already a key in result, set its value to typedValue. + // Note: This can happen when O is a proxy object. + // FIXME: Handle this case. + + // 5. Otherwise, append to result a mapping (typedKey, typedValue). + result.append({ typedKey, typedValue }); + } + } + + // 6. Return result. + return result; + } +}; + +template<typename K, typename V> struct JSConverter<IDLRecord<K, V>> { + static constexpr bool needsState = true; + static constexpr bool needsGlobalObject = true; + + template<typename MapType> + static JSC::JSValue convert(JSC::ExecState& state, JSDOMGlobalObject& globalObject, const MapType& map) + { + auto& vm = state.vm(); + + // 1. Let result be ! ObjectCreate(%ObjectPrototype%). + auto result = constructEmptyObject(&state); + + // 2. Repeat, for each mapping (key, value) in D: + for (const auto& keyValuePair : map) { + // 1. Let esKey be key converted to an ECMAScript value. + // Note, this step is not required, as we need the key to be + // an Identifier, not a JSValue. + + // 2. Let esValue be value converted to an ECMAScript value. + auto esValue = toJS<V>(state, globalObject, keyValuePair.value); + + // 3. Let created be ! CreateDataProperty(result, esKey, esValue). + bool created = result->putDirect(vm, JSC::Identifier::fromString(&vm, keyValuePair.key), esValue); + + // 4. Assert: created is true. + ASSERT_UNUSED(created, created); + } + + // 3. Return result. + return result; + } +}; + +} // namespace WebCore diff --git a/Source/WebCore/bindings/js/JSDOMConvertSequences.h b/Source/WebCore/bindings/js/JSDOMConvertSequences.h new file mode 100644 index 000000000..f42f45992 --- /dev/null +++ b/Source/WebCore/bindings/js/JSDOMConvertSequences.h @@ -0,0 +1,317 @@ +/* + * Copyright (C) 2016 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +#include "IDLTypes.h" +#include "JSDOMConvertBase.h" +#include <runtime/IteratorOperations.h> +#include <runtime/JSArray.h> +#include <runtime/JSGlobalObjectInlines.h> + +namespace WebCore { + +namespace Detail { + +template<typename IDLType> +struct GenericSequenceConverter { + using ReturnType = Vector<typename IDLType::ImplementationType>; + + static ReturnType convert(JSC::ExecState& state, JSC::JSObject* jsObject) + { + ReturnType result; + forEachInIterable(&state, jsObject, [&result](JSC::VM& vm, JSC::ExecState* state, JSC::JSValue jsValue) { + auto scope = DECLARE_THROW_SCOPE(vm); + + auto convertedValue = Converter<IDLType>::convert(*state, jsValue); + if (UNLIKELY(scope.exception())) + return; + result.append(WTFMove(convertedValue)); + }); + return result; + } +}; + +// Specialization for numeric types +// FIXME: This is only implemented for the IDLFloatingPointTypes and IDLLong. To add +// support for more numeric types, add an overload of Converter<IDLType>::convert that +// takes an ExecState, ThrowScope, double as its arguments. +template<typename IDLType> +struct NumericSequenceConverter { + using GenericConverter = GenericSequenceConverter<IDLType>; + using ReturnType = typename GenericConverter::ReturnType; + + static ReturnType convert(JSC::ExecState& state, JSC::JSValue value) + { + auto& vm = state.vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + + if (!value.isObject()) { + throwSequenceTypeError(state, scope); + return { }; + } + + JSC::JSObject* object = JSC::asObject(value); + if (!JSC::isJSArray(object)) + return GenericConverter::convert(state, object); + + JSC::JSArray* array = JSC::asArray(object); + if (!array->globalObject()->isArrayIteratorProtocolFastAndNonObservable()) + return GenericConverter::convert(state, object); + + unsigned length = array->length(); + + ReturnType result; + if (!result.tryReserveCapacity(length)) { + // FIXME: Is the right exception to throw? + throwTypeError(&state, scope); + return { }; + } + + JSC::IndexingType indexingType = array->indexingType() & JSC::IndexingShapeMask; + + if (indexingType == JSC::ContiguousShape) { + for (unsigned i = 0; i < length; i++) { + auto indexValue = array->butterfly()->contiguous()[i].get(); + if (!indexValue) + result.uncheckedAppend(0); + else { + auto convertedValue = Converter<IDLType>::convert(state, indexValue); + RETURN_IF_EXCEPTION(scope, { }); + + result.uncheckedAppend(convertedValue); + } + } + return result; + } + + if (indexingType == JSC::Int32Shape) { + for (unsigned i = 0; i < length; i++) { + auto indexValue = array->butterfly()->contiguousInt32()[i].get(); + ASSERT(!indexValue || indexValue.isInt32()); + if (!indexValue) + result.uncheckedAppend(0); + else + result.uncheckedAppend(indexValue.asInt32()); + } + return result; + } + + if (indexingType == JSC::DoubleShape) { + for (unsigned i = 0; i < length; i++) { + auto doubleValue = array->butterfly()->contiguousDouble()[i]; + if (std::isnan(doubleValue)) + result.uncheckedAppend(0); + else { + auto convertedValue = Converter<IDLType>::convert(state, scope, doubleValue); + RETURN_IF_EXCEPTION(scope, { }); + + result.uncheckedAppend(convertedValue); + } + } + return result; + } + + for (unsigned i = 0; i < length; i++) { + auto indexValue = array->getDirectIndex(&state, i); + RETURN_IF_EXCEPTION(scope, { }); + + if (!indexValue) + result.uncheckedAppend(0); + else { + auto convertedValue = Converter<IDLType>::convert(state, indexValue); + RETURN_IF_EXCEPTION(scope, { }); + + result.uncheckedAppend(convertedValue); + } + } + return result; + } +}; + +template<typename IDLType> +struct SequenceConverter { + using GenericConverter = GenericSequenceConverter<IDLType>; + using ReturnType = typename GenericConverter::ReturnType; + + static ReturnType convert(JSC::ExecState& state, JSC::JSValue value) + { + auto& vm = state.vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + + if (!value.isObject()) { + throwSequenceTypeError(state, scope); + return { }; + } + + JSC::JSObject* object = JSC::asObject(value); + if (!JSC::isJSArray(object)) + return GenericConverter::convert(state, object); + + JSC::JSArray* array = JSC::asArray(object); + if (!array->globalObject()->isArrayIteratorProtocolFastAndNonObservable()) + return GenericConverter::convert(state, object); + + unsigned length = array->length(); + + ReturnType result; + if (!result.tryReserveCapacity(length)) { + // FIXME: Is the right exception to throw? + throwTypeError(&state, scope); + return { }; + } + + JSC::IndexingType indexingType = array->indexingType() & JSC::IndexingShapeMask; + + if (indexingType == JSC::ContiguousShape) { + for (unsigned i = 0; i < length; i++) { + auto indexValue = array->butterfly()->contiguous()[i].get(); + if (!indexValue) + indexValue = JSC::jsUndefined(); + + auto convertedValue = Converter<IDLType>::convert(state, indexValue); + RETURN_IF_EXCEPTION(scope, { }); + + result.uncheckedAppend(convertedValue); + } + return result; + } + + for (unsigned i = 0; i < length; i++) { + auto indexValue = array->getDirectIndex(&state, i); + RETURN_IF_EXCEPTION(scope, { }); + + if (!indexValue) + indexValue = JSC::jsUndefined(); + + auto convertedValue = Converter<IDLType>::convert(state, indexValue); + RETURN_IF_EXCEPTION(scope, { }); + + result.uncheckedAppend(convertedValue); + } + return result; + } +}; + +template<> +struct SequenceConverter<IDLLong> { + using ReturnType = typename GenericSequenceConverter<IDLLong>::ReturnType; + + static ReturnType convert(JSC::ExecState& state, JSC::JSValue value) + { + return NumericSequenceConverter<IDLLong>::convert(state, value); + } +}; + +template<> +struct SequenceConverter<IDLFloat> { + using ReturnType = typename GenericSequenceConverter<IDLFloat>::ReturnType; + + static ReturnType convert(JSC::ExecState& state, JSC::JSValue value) + { + return NumericSequenceConverter<IDLFloat>::convert(state, value); + } +}; + +template<> +struct SequenceConverter<IDLUnrestrictedFloat> { + using ReturnType = typename GenericSequenceConverter<IDLUnrestrictedFloat>::ReturnType; + + static ReturnType convert(JSC::ExecState& state, JSC::JSValue value) + { + return NumericSequenceConverter<IDLUnrestrictedFloat>::convert(state, value); + } +}; + +template<> +struct SequenceConverter<IDLDouble> { + using ReturnType = typename GenericSequenceConverter<IDLDouble>::ReturnType; + + static ReturnType convert(JSC::ExecState& state, JSC::JSValue value) + { + return NumericSequenceConverter<IDLDouble>::convert(state, value); + } +}; + +template<> +struct SequenceConverter<IDLUnrestrictedDouble> { + using ReturnType = typename GenericSequenceConverter<IDLUnrestrictedDouble>::ReturnType; + + static ReturnType convert(JSC::ExecState& state, JSC::JSValue value) + { + return NumericSequenceConverter<IDLUnrestrictedDouble>::convert(state, value); + } +}; + +} + +template<typename T> struct Converter<IDLSequence<T>> : DefaultConverter<IDLSequence<T>> { + using ReturnType = typename Detail::SequenceConverter<T>::ReturnType; + + static ReturnType convert(JSC::ExecState& state, JSC::JSValue value) + { + return Detail::SequenceConverter<T>::convert(state, value); + } +}; + +template<typename T> struct JSConverter<IDLSequence<T>> { + static constexpr bool needsState = true; + static constexpr bool needsGlobalObject = true; + + template<typename U, size_t inlineCapacity> + static JSC::JSValue convert(JSC::ExecState& exec, JSDOMGlobalObject& globalObject, const Vector<U, inlineCapacity>& vector) + { + JSC::MarkedArgumentBuffer list; + for (auto& element : vector) + list.append(toJS<T>(exec, globalObject, element)); + return JSC::constructArray(&exec, nullptr, &globalObject, list); + } +}; + +template<typename T> struct Converter<IDLFrozenArray<T>> : DefaultConverter<IDLFrozenArray<T>> { + using ReturnType = typename Detail::SequenceConverter<T>::ReturnType; + + static ReturnType convert(JSC::ExecState& state, JSC::JSValue value) + { + return Detail::SequenceConverter<T>::convert(state, value); + } +}; + +template<typename T> struct JSConverter<IDLFrozenArray<T>> { + static constexpr bool needsState = true; + static constexpr bool needsGlobalObject = true; + + template<typename U, size_t inlineCapacity> + static JSC::JSValue convert(JSC::ExecState& exec, JSDOMGlobalObject& globalObject, const Vector<U, inlineCapacity>& vector) + { + JSC::MarkedArgumentBuffer list; + for (auto& element : vector) + list.append(toJS<T>(exec, globalObject, element)); + auto* array = JSC::constructArray(&exec, nullptr, &globalObject, list); + return JSC::objectConstructorFreeze(&exec, array); + } +}; + +} // namespace WebCore diff --git a/Source/WebCore/bindings/js/JSDOMConvertSerializedScriptValue.h b/Source/WebCore/bindings/js/JSDOMConvertSerializedScriptValue.h new file mode 100644 index 000000000..10b69f9ac --- /dev/null +++ b/Source/WebCore/bindings/js/JSDOMConvertSerializedScriptValue.h @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2016 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +#include "IDLTypes.h" +#include "JSDOMConvertStrings.h" + +namespace WebCore { + +template<typename T> struct Converter<IDLSerializedScriptValue<T>> : DefaultConverter<IDLSerializedScriptValue<T>> { + static RefPtr<T> convert(JSC::ExecState& state, JSC::JSValue value) + { + return T::create(state, value); + } +}; + +template<typename T> struct JSConverter<IDLSerializedScriptValue<T>> { + static constexpr bool needsState = true; + static constexpr bool needsGlobalObject = true; + + static JSC::JSValue convert(JSC::ExecState& state, JSDOMGlobalObject& globalObject, RefPtr<T> value) + { + return value ? value->deserialize(state, &globalObject) : JSC::jsNull(); + } +}; + +} // namespace WebCore diff --git a/Source/WebCore/bindings/js/JSDOMConvertStrings.cpp b/Source/WebCore/bindings/js/JSDOMConvertStrings.cpp new file mode 100644 index 000000000..6c95f6680 --- /dev/null +++ b/Source/WebCore/bindings/js/JSDOMConvertStrings.cpp @@ -0,0 +1,114 @@ +/* + * Copyright (C) 1999-2001 Harri Porten (porten@kde.org) + * Copyright (C) 2004-2011, 2013, 2016 Apple Inc. All rights reserved. + * Copyright (C) 2007 Samuel Weinig <sam@webkit.org> + * Copyright (C) 2013 Michael Pruett <michael@68k.org> + * + * 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 + */ + +#include "config.h" +#include "JSDOMConvertStrings.h" + +#include "JSDOMExceptionHandling.h" +#include <heap/HeapInlines.h> +#include <runtime/JSCJSValueInlines.h> +#include <wtf/text/StringBuilder.h> +#include <wtf/unicode/CharacterNames.h> + +using namespace JSC; + +namespace WebCore { + +static inline String stringToByteString(ExecState& state, JSC::ThrowScope& scope, String&& string) +{ + if (!string.containsOnlyLatin1()) { + throwTypeError(&state, scope); + return { }; + } + + return string; +} + +String identifierToByteString(ExecState& state, const Identifier& identifier) +{ + VM& vm = state.vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + + auto string = identifier.string(); + return stringToByteString(state, scope, WTFMove(string)); +} + +String valueToByteString(ExecState& state, JSValue value) +{ + VM& vm = state.vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + + auto string = value.toWTFString(&state); + RETURN_IF_EXCEPTION(scope, { }); + + return stringToByteString(state, scope, WTFMove(string)); +} + +static inline bool hasUnpairedSurrogate(StringView string) +{ + // Fast path for 8-bit strings; they can't have any surrogates. + if (string.is8Bit()) + return false; + for (auto codePoint : string.codePoints()) { + if (U_IS_SURROGATE(codePoint)) + return true; + } + return false; +} + +static inline String stringToUSVString(String&& string) +{ + // Fast path for the case where there are no unpaired surrogates. + if (!hasUnpairedSurrogate(string)) + return string; + + // Slow path: http://heycam.github.io/webidl/#dfn-obtain-unicode + // Replaces unpaired surrogates with the replacement character. + StringBuilder result; + result.reserveCapacity(string.length()); + StringView view { string }; + for (auto codePoint : view.codePoints()) { + if (U_IS_SURROGATE(codePoint)) + result.append(replacementCharacter); + else + result.append(codePoint); + } + return result.toString(); +} + +String identifierToUSVString(ExecState&, const Identifier& identifier) +{ + auto string = identifier.string(); + return stringToUSVString(WTFMove(string)); +} + +String valueToUSVString(ExecState& state, JSValue value) +{ + VM& vm = state.vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + + auto string = value.toWTFString(&state); + RETURN_IF_EXCEPTION(scope, { }); + + return stringToUSVString(WTFMove(string)); +} + +} // namespace WebCore diff --git a/Source/WebCore/bindings/js/JSDOMConvertStrings.h b/Source/WebCore/bindings/js/JSDOMConvertStrings.h new file mode 100644 index 000000000..dd9bfad77 --- /dev/null +++ b/Source/WebCore/bindings/js/JSDOMConvertStrings.h @@ -0,0 +1,119 @@ +/* + * Copyright (C) 2016 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +#include "IDLTypes.h" +#include "JSDOMConvertBase.h" +#include "JSDOMExceptionHandling.h" + +namespace WebCore { + +enum class StringConversionConfiguration { Normal, TreatNullAsEmptyString }; + +template<typename T> typename Converter<T>::ReturnType convert(JSC::ExecState&, JSC::JSValue, StringConversionConfiguration); + +template<typename T> inline typename Converter<T>::ReturnType convert(JSC::ExecState& state, JSC::JSValue value, StringConversionConfiguration configuration) +{ + return Converter<T>::convert(state, value, configuration); +} + +WEBCORE_EXPORT String identifierToByteString(JSC::ExecState&, const JSC::Identifier&); +WEBCORE_EXPORT String valueToByteString(JSC::ExecState&, JSC::JSValue); +WEBCORE_EXPORT String identifierToUSVString(JSC::ExecState&, const JSC::Identifier&); +WEBCORE_EXPORT String valueToUSVString(JSC::ExecState&, JSC::JSValue); + +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()); +} + +// MARK: - +// MARK: String types + +template<> struct Converter<IDLDOMString> : DefaultConverter<IDLDOMString> { + static String convert(JSC::ExecState& state, JSC::JSValue value, StringConversionConfiguration configuration = StringConversionConfiguration::Normal) + { + if (configuration == StringConversionConfiguration::TreatNullAsEmptyString && value.isNull()) + return emptyString(); + return value.toWTFString(&state); + } +}; + +template<> struct JSConverter<IDLDOMString> { + static constexpr bool needsState = true; + static constexpr bool needsGlobalObject = false; + + static JSC::JSValue convert(JSC::ExecState& state, const String& value) + { + return JSC::jsStringWithCache(&state, value); + } +}; + +template<> struct Converter<IDLByteString> : DefaultConverter<IDLByteString> { + static String convert(JSC::ExecState& state, JSC::JSValue value, StringConversionConfiguration configuration = StringConversionConfiguration::Normal) + { + if (configuration == StringConversionConfiguration::TreatNullAsEmptyString && value.isNull()) + return emptyString(); + return valueToByteString(state, value); + } +}; + +template<> struct JSConverter<IDLByteString> { + static constexpr bool needsState = true; + static constexpr bool needsGlobalObject = false; + + static JSC::JSValue convert(JSC::ExecState& state, const String& value) + { + return JSC::jsStringWithCache(&state, value); + } +}; + +template<> struct Converter<IDLUSVString> : DefaultConverter<IDLUSVString> { + static String convert(JSC::ExecState& state, JSC::JSValue value, StringConversionConfiguration configuration = StringConversionConfiguration::Normal) + { + if (configuration == StringConversionConfiguration::TreatNullAsEmptyString && value.isNull()) + return emptyString(); + return valueToUSVString(state, value); + } +}; + +template<> struct JSConverter<IDLUSVString> { + static constexpr bool needsState = true; + static constexpr bool needsGlobalObject = false; + + static JSC::JSValue convert(JSC::ExecState& state, const String& value) + { + return JSC::jsStringWithCache(&state, value); + } +}; + +} // namespace WebCore diff --git a/Source/WebCore/bindings/js/JSDOMConvertUnion.h b/Source/WebCore/bindings/js/JSDOMConvertUnion.h new file mode 100644 index 000000000..6a2501464 --- /dev/null +++ b/Source/WebCore/bindings/js/JSDOMConvertUnion.h @@ -0,0 +1,286 @@ +/* + * Copyright (C) 2016 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +#include "IDLTypes.h" +#include "JSDOMBinding.h" +#include "JSDOMConvertBase.h" +#include <runtime/IteratorOperations.h> + +namespace WebCore { + +template<typename ReturnType, typename T, bool enabled> +struct ConditionalConverter; + +template<typename ReturnType, typename T> +struct ConditionalConverter<ReturnType, T, true> { + static std::optional<ReturnType> convert(JSC::ExecState& state, JSC::JSValue value) + { + return ReturnType(Converter<T>::convert(state, value)); + } +}; + +template<typename ReturnType, typename T> +struct ConditionalConverter<ReturnType, T, false> { + static std::optional<ReturnType> convert(JSC::ExecState&, JSC::JSValue) + { + return std::nullopt; + } +}; + +namespace Detail { + +template<typename List, bool condition> +struct ConditionalFront; + +template<typename List> +struct ConditionalFront<List, true> { + using type = brigand::front<List>; +}; + +template<typename List> +struct ConditionalFront<List, false> { + using type = void; +}; + +} + +template<typename List, bool condition> +using ConditionalFront = typename Detail::ConditionalFront<List, condition>::type; + +template<typename... T> struct Converter<IDLUnion<T...>> : DefaultConverter<IDLUnion<T...>> { + using Type = IDLUnion<T...>; + using TypeList = typename Type::TypeList; + using ReturnType = typename Type::ImplementationType; + + using NumericTypeList = brigand::filter<TypeList, IsIDLNumber<brigand::_1>>; + static constexpr size_t numberOfNumericTypes = brigand::size<NumericTypeList>::value; + static_assert(numberOfNumericTypes == 0 || numberOfNumericTypes == 1, "There can be 0 or 1 numeric types in an IDLUnion."); + using NumericType = ConditionalFront<NumericTypeList, numberOfNumericTypes != 0>; + + // FIXME: This should also check for IDLEnumeration<T>. + using StringTypeList = brigand::filter<TypeList, std::is_base_of<IDLString, brigand::_1>>; + static constexpr size_t numberOfStringTypes = brigand::size<StringTypeList>::value; + static_assert(numberOfStringTypes == 0 || numberOfStringTypes == 1, "There can be 0 or 1 string types in an IDLUnion."); + using StringType = ConditionalFront<StringTypeList, numberOfStringTypes != 0>; + + using SequenceTypeList = brigand::filter<TypeList, IsIDLSequence<brigand::_1>>; + static constexpr size_t numberOfSequenceTypes = brigand::size<SequenceTypeList>::value; + static_assert(numberOfSequenceTypes == 0 || numberOfSequenceTypes == 1, "There can be 0 or 1 sequence types in an IDLUnion."); + using SequenceType = ConditionalFront<SequenceTypeList, numberOfSequenceTypes != 0>; + + using FrozenArrayTypeList = brigand::filter<TypeList, IsIDLFrozenArray<brigand::_1>>; + static constexpr size_t numberOfFrozenArrayTypes = brigand::size<FrozenArrayTypeList>::value; + static_assert(numberOfFrozenArrayTypes == 0 || numberOfFrozenArrayTypes == 1, "There can be 0 or 1 FrozenArray types in an IDLUnion."); + using FrozenArrayType = ConditionalFront<FrozenArrayTypeList, numberOfFrozenArrayTypes != 0>; + + using DictionaryTypeList = brigand::filter<TypeList, IsIDLDictionary<brigand::_1>>; + static constexpr size_t numberOfDictionaryTypes = brigand::size<DictionaryTypeList>::value; + static_assert(numberOfDictionaryTypes == 0 || numberOfDictionaryTypes == 1, "There can be 0 or 1 dictionary types in an IDLUnion."); + static constexpr bool hasDictionaryType = numberOfDictionaryTypes != 0; + using DictionaryType = ConditionalFront<DictionaryTypeList, hasDictionaryType>; + + using RecordTypeList = brigand::filter<TypeList, IsIDLRecord<brigand::_1>>; + static constexpr size_t numberOfRecordTypes = brigand::size<RecordTypeList>::value; + static_assert(numberOfRecordTypes == 0 || numberOfRecordTypes == 1, "There can be 0 or 1 record types in an IDLUnion."); + static constexpr bool hasRecordType = numberOfRecordTypes != 0; + using RecordType = ConditionalFront<RecordTypeList, hasRecordType>; + + static constexpr bool hasObjectType = (numberOfSequenceTypes + numberOfFrozenArrayTypes + numberOfDictionaryTypes + numberOfRecordTypes) > 0; + + using InterfaceTypeList = brigand::filter<TypeList, IsIDLInterface<brigand::_1>>; + + static ReturnType convert(JSC::ExecState& state, JSC::JSValue value) + { + JSC::VM& vm = state.vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + + // 1. If the union type includes a nullable type and V is null or undefined, then return the IDL value null. + constexpr bool hasNullType = brigand::any<TypeList, std::is_same<IDLNull, brigand::_1>>::value; + if (hasNullType) { + if (value.isUndefinedOrNull()) + return std::move<WTF::CheckMoveParameter>(ConditionalConverter<ReturnType, IDLNull, hasNullType>::convert(state, value).value()); + } + + // 2. Let types be the flattened member types of the union type. + // NOTE: Union is expected to be pre-flattented. + + // 3. If V is null or undefined then: + if (hasDictionaryType || hasRecordType) { + if (value.isUndefinedOrNull()) { + // 1. If types includes a dictionary type, then return the result of converting V to that dictionary type. + if (hasDictionaryType) + return std::move<WTF::CheckMoveParameter>(ConditionalConverter<ReturnType, DictionaryType, hasDictionaryType>::convert(state, value).value()); + + // 2. If types includes a record type, then return the result of converting V to that record type. + if (hasRecordType) + return std::move<WTF::CheckMoveParameter>(ConditionalConverter<ReturnType, RecordType, hasRecordType>::convert(state, value).value()); + } + } + + // 4. If V is a platform object, then: + // 1. If types includes an interface type that V implements, then return the IDL value that is a reference to the object V. + // 2. If types includes object, then return the IDL value that is a reference to the object V. + // (FIXME: Add support for object and step 4.2) + if (brigand::any<TypeList, IsIDLInterface<brigand::_1>>::value) { + std::optional<ReturnType> returnValue; + brigand::for_each<InterfaceTypeList>([&](auto&& type) { + if (returnValue) + return; + + using Type = typename WTF::RemoveCVAndReference<decltype(type)>::type::type; + using ImplementationType = typename Type::ImplementationType; + using RawType = typename Type::RawType; + using WrapperType = typename JSDOMWrapperConverterTraits<RawType>::WrapperClass; + + auto castedValue = WrapperType::toWrapped(vm, value); + if (!castedValue) + return; + + returnValue = ReturnType(ImplementationType(castedValue)); + }); + + if (returnValue) + return WTFMove(returnValue.value()); + } + + // FIXME: Add support for steps 5 - 10. + + // 11. If V is any kind of object, then: + if (hasObjectType) { + if (value.isCell()) { + JSC::JSCell* cell = value.asCell(); + if (cell->isObject()) { + // FIXME: We should be able to optimize the following code by making use + // of the fact that we have proved that the value is an object. + + // 1. If types includes a sequence type, then: + // 1. Let method be the result of GetMethod(V, @@iterator). + // 2. ReturnIfAbrupt(method). + // 3. If method is not undefined, return the result of creating a + // sequence of that type from V and method. + constexpr bool hasSequenceType = numberOfSequenceTypes != 0; + if (hasSequenceType) { + bool hasIterator = JSC::hasIteratorMethod(state, value); + RETURN_IF_EXCEPTION(scope, ReturnType()); + if (hasIterator) + return std::move<WTF::CheckMoveParameter>(ConditionalConverter<ReturnType, SequenceType, hasSequenceType>::convert(state, value).value()); + } + + // 2. If types includes a frozen array type, then: + // 1. Let method be the result of GetMethod(V, @@iterator). + // 2. ReturnIfAbrupt(method). + // 3. If method is not undefined, return the result of creating a + // frozen array of that type from V and method. + constexpr bool hasFrozenArrayType = numberOfFrozenArrayTypes != 0; + if (hasFrozenArrayType) { + bool hasIterator = JSC::hasIteratorMethod(state, value); + RETURN_IF_EXCEPTION(scope, ReturnType()); + if (hasIterator) + return std::move<WTF::CheckMoveParameter>(ConditionalConverter<ReturnType, FrozenArrayType, hasFrozenArrayType>::convert(state, value).value()); + } + + // 3. If types includes a dictionary type, then return the result of + // converting V to that dictionary type. + if (hasDictionaryType) + return std::move<WTF::CheckMoveParameter>(ConditionalConverter<ReturnType, DictionaryType, hasDictionaryType>::convert(state, value).value()); + + // 4. If types includes a record type, then return the result of converting V to that record type. + if (hasRecordType) + return std::move<WTF::CheckMoveParameter>(ConditionalConverter<ReturnType, RecordType, hasRecordType>::convert(state, value).value()); + + // 5. If types includes a callback interface type, then return the result of converting V to that interface type. + // (FIXME: Add support for callback interface type and step 12.5) + // 6. If types includes object, then return the IDL value that is a reference to the object V. + // (FIXME: Add support for object and step 12.6) + } + } + } + + // 12. If V is a Boolean value, then: + // 1. If types includes a boolean, then return the result of converting V to boolean. + constexpr bool hasBooleanType = brigand::any<TypeList, std::is_same<IDLBoolean, brigand::_1>>::value; + if (hasBooleanType) { + if (value.isBoolean()) + return std::move<WTF::CheckMoveParameter>(ConditionalConverter<ReturnType, IDLBoolean, hasBooleanType>::convert(state, value).value()); + } + + // 13. If V is a Number value, then: + // 1. If types includes a numeric type, then return the result of converting V to that numeric type. + constexpr bool hasNumericType = brigand::size<NumericTypeList>::value != 0; + if (hasNumericType) { + if (value.isNumber()) + return std::move<WTF::CheckMoveParameter>(ConditionalConverter<ReturnType, NumericType, hasNumericType>::convert(state, value).value()); + } + + // 14. If types includes a string type, then return the result of converting V to that type. + constexpr bool hasStringType = brigand::size<StringTypeList>::value != 0; + if (hasStringType) + return std::move<WTF::CheckMoveParameter>(ConditionalConverter<ReturnType, StringType, hasStringType>::convert(state, value).value()); + + // 15. If types includes a numeric type, then return the result of converting V to that numeric type. + if (hasNumericType) + return std::move<WTF::CheckMoveParameter>(ConditionalConverter<ReturnType, NumericType, hasNumericType>::convert(state, value).value()); + + // 16. If types includes a boolean, then return the result of converting V to boolean. + if (hasBooleanType) + return std::move<WTF::CheckMoveParameter>(ConditionalConverter<ReturnType, IDLBoolean, hasBooleanType>::convert(state, value).value()); + + // 17. Throw a TypeError. + throwTypeError(&state, scope); + return ReturnType(); + } +}; + +template<typename... T> struct JSConverter<IDLUnion<T...>> { + using Type = IDLUnion<T...>; + using TypeList = typename Type::TypeList; + using ImplementationType = typename Type::ImplementationType; + + static constexpr bool needsState = true; + static constexpr bool needsGlobalObject = true; + + using Sequence = brigand::make_sequence<brigand::ptrdiff_t<0>, WTF::variant_size<ImplementationType>::value>; + + static JSC::JSValue convert(JSC::ExecState& state, JSDOMGlobalObject& globalObject, const ImplementationType& variant) + { + auto index = variant.index(); + + std::optional<JSC::JSValue> returnValue; + brigand::for_each<Sequence>([&](auto&& type) { + using I = typename WTF::RemoveCVAndReference<decltype(type)>::type::type; + if (I::value == index) { + ASSERT(!returnValue); + returnValue = toJS<brigand::at<TypeList, I>>(state, globalObject, WTF::get<I::value>(variant)); + } + }); + + ASSERT(returnValue); + return returnValue.value(); + } +}; + +} // namespace WebCore diff --git a/Source/WebCore/bindings/js/JSDOMConvertVariadic.h b/Source/WebCore/bindings/js/JSDOMConvertVariadic.h new file mode 100644 index 000000000..79b2b9d55 --- /dev/null +++ b/Source/WebCore/bindings/js/JSDOMConvertVariadic.h @@ -0,0 +1,99 @@ +/* + * Copyright (C) 2016 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +#include "IDLTypes.h" +#include "JSDOMConvertBase.h" + +namespace WebCore { + +namespace Detail { + +template<typename IDLType> +struct VariadicConverterBase; + +template<typename IDLType> +struct VariadicConverterBase { + using Item = typename IDLType::ImplementationType; + + static std::optional<Item> convert(JSC::ExecState& state, JSC::JSValue value) + { + auto& vm = state.vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + + auto result = Converter<IDLType>::convert(state, value); + RETURN_IF_EXCEPTION(scope, std::nullopt); + + return WTFMove(result); + } +}; + +template<typename T> +struct VariadicConverterBase<IDLInterface<T>> { + using Item = std::reference_wrapper<T>; + + static std::optional<Item> convert(JSC::ExecState& state, JSC::JSValue value) + { + auto* result = Converter<IDLInterface<T>>::convert(state, value); + if (!result) + return std::nullopt; + return std::optional<Item>(*result); + } +}; + +template<typename IDLType> +struct VariadicConverter : VariadicConverterBase<IDLType> { + using Item = typename VariadicConverterBase<IDLType>::Item; + using Container = Vector<Item>; + + struct Result { + size_t argumentIndex; + std::optional<Container> arguments; + }; +}; + +} + +template<typename IDLType> typename Detail::VariadicConverter<IDLType>::Result convertVariadicArguments(JSC::ExecState& state, size_t startIndex) +{ + size_t length = state.argumentCount(); + if (startIndex > length) + return { 0, std::nullopt }; + + typename Detail::VariadicConverter<IDLType>::Container result; + result.reserveInitialCapacity(length - startIndex); + + for (size_t i = startIndex; i < length; ++i) { + auto value = Detail::VariadicConverter<IDLType>::convert(state, state.uncheckedArgument(i)); + if (!value) + return { i, std::nullopt }; + result.uncheckedAppend(WTFMove(*value)); + } + + return { length, WTFMove(result) }; +} + +} // namespace WebCore diff --git a/Source/WebCore/bindings/js/JSDOMConvertWebGL.h b/Source/WebCore/bindings/js/JSDOMConvertWebGL.h new file mode 100644 index 000000000..c2740d529 --- /dev/null +++ b/Source/WebCore/bindings/js/JSDOMConvertWebGL.h @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2016 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +#if ENABLE(WEBGL) + +#include "IDLTypes.h" +#include "JSDOMConvertBase.h" + +namespace WebCore { + +template<> struct JSConverter<IDLWebGLAny> { + static constexpr bool needsState = true; + static constexpr bool needsGlobalObject = true; + + static JSC::JSValue convert(JSC::ExecState& state, JSDOMGlobalObject& globalObject, const WebGLAny& value) + { + return convertToJSValue(state, globalObject, value); + } +}; + +} // namespace WebCore + +#endif diff --git a/Source/WebCore/bindings/js/JSDOMConvertXPathNSResolver.h b/Source/WebCore/bindings/js/JSDOMConvertXPathNSResolver.h new file mode 100644 index 000000000..94df3f45a --- /dev/null +++ b/Source/WebCore/bindings/js/JSDOMConvertXPathNSResolver.h @@ -0,0 +1,66 @@ +/* + * Copyright (C) 2016 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +#include "IDLTypes.h" +#include "JSDOMConvertBase.h" + +namespace WebCore { + +template<typename T> struct Converter<IDLXPathNSResolver<T>> : DefaultConverter<IDLXPathNSResolver<T>> { + using ReturnType = RefPtr<T>; + using WrapperType = typename JSDOMWrapperConverterTraits<T>::WrapperClass; + + template<typename ExceptionThrower = DefaultExceptionThrower> + static ReturnType convert(JSC::ExecState& state, JSC::JSValue value, ExceptionThrower&& exceptionThrower = ExceptionThrower()) + { + JSC::VM& vm = state.vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + ReturnType object = WrapperType::toWrapped(vm, state, value); + if (UNLIKELY(!object)) + exceptionThrower(state, scope); + return object; + } +}; + +template<typename T> struct JSConverter<IDLXPathNSResolver<T>> { + static constexpr bool needsState = true; + static constexpr bool needsGlobalObject = true; + + template <typename U> + static JSC::JSValue convert(JSC::ExecState& state, JSDOMGlobalObject& globalObject, const U& value) + { + return toJS(&state, &globalObject, Detail::getPtrOrRef(value)); + } + + template<typename U> + static JSC::JSValue convertNewlyCreated(JSC::ExecState& state, JSDOMGlobalObject& globalObject, U&& value) + { + return toJSNewlyCreated(&state, &globalObject, std::forward<U>(value)); + } +}; + +} // namespace WebCore diff --git a/Source/WebCore/bindings/js/JSDOMExceptionHandling.cpp b/Source/WebCore/bindings/js/JSDOMExceptionHandling.cpp new file mode 100644 index 000000000..585553d16 --- /dev/null +++ b/Source/WebCore/bindings/js/JSDOMExceptionHandling.cpp @@ -0,0 +1,404 @@ +/* + * Copyright (C) 1999-2001 Harri Porten (porten@kde.org) + * Copyright (C) 2004-2011, 2013, 2016 Apple Inc. All rights reserved. + * Copyright (C) 2007 Samuel Weinig <sam@webkit.org> + * Copyright (C) 2013 Michael Pruett <michael@68k.org> + * + * 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 + */ + +#include "config.h" +#include "JSDOMExceptionHandling.h" + +#include "CachedScript.h" +#include "DOMWindow.h" +#include "ExceptionCodeDescription.h" +#include "ExceptionHeaders.h" +#include "ExceptionInterfaces.h" +#include "JSDOMPromise.h" +#include "JSDOMWindow.h" +#include "JSDynamicDowncast.h" +#include "JSExceptionBase.h" +#include <inspector/ScriptCallStack.h> +#include <inspector/ScriptCallStackFactory.h> +#include <runtime/ErrorHandlingScope.h> +#include <runtime/Exception.h> +#include <runtime/ExceptionHelpers.h> +#include <wtf/text/StringBuilder.h> + +#if ENABLE(INDEXED_DATABASE) +#include "IDBDatabaseException.h" +#endif + +using namespace JSC; + +namespace WebCore { + +void reportException(ExecState* exec, JSValue exceptionValue, CachedScript* cachedScript) +{ + VM& vm = exec->vm(); + RELEASE_ASSERT(vm.currentThreadIsHoldingAPILock()); + auto* exception = jsDynamicDowncast<JSC::Exception*>(vm, exceptionValue); + if (!exception) { + exception = vm.lastException(); + if (!exception) + exception = JSC::Exception::create(exec->vm(), exceptionValue, JSC::Exception::DoNotCaptureStack); + } + + reportException(exec, exception, cachedScript); +} + +String retrieveErrorMessage(ExecState& state, VM& vm, JSValue exception, CatchScope& catchScope) +{ + if (auto* exceptionBase = toExceptionBase(vm, exception)) + return exceptionBase->toString(); + + // FIXME: <http://webkit.org/b/115087> Web Inspector: WebCore::reportException should not evaluate JavaScript handling exceptions + // If this is a custom exception object, call toString on it to try and get a nice string representation for the exception. + String errorMessage; + if (auto* error = jsDynamicDowncast<ErrorInstance*>(vm, exception)) + errorMessage = error->sanitizedToString(&state); + else + errorMessage = exception.toWTFString(&state); + + // We need to clear any new exception that may be thrown in the toString() call above. + // reportException() is not supposed to be making new exceptions. + catchScope.clearException(); + vm.clearLastException(); + return errorMessage; +} + +void reportException(ExecState* exec, JSC::Exception* exception, CachedScript* cachedScript, ExceptionDetails* exceptionDetails) +{ + VM& vm = exec->vm(); + auto scope = DECLARE_CATCH_SCOPE(vm); + + RELEASE_ASSERT(vm.currentThreadIsHoldingAPILock()); + if (isTerminatedExecutionException(vm, exception)) + return; + + ErrorHandlingScope errorScope(exec->vm()); + + auto callStack = Inspector::createScriptCallStackFromException(exec, exception, Inspector::ScriptCallStack::maxCallStackSizeToCapture); + scope.clearException(); + vm.clearLastException(); + + auto* globalObject = jsCast<JSDOMGlobalObject*>(exec->lexicalGlobalObject()); + if (auto* window = jsDynamicDowncast<JSDOMWindow*>(vm, globalObject)) { + if (!window->wrapped().isCurrentlyDisplayedInFrame()) + return; + } + + int lineNumber = 0; + int columnNumber = 0; + String exceptionSourceURL; + if (auto* callFrame = callStack->firstNonNativeCallFrame()) { + lineNumber = callFrame->lineNumber(); + columnNumber = callFrame->columnNumber(); + exceptionSourceURL = callFrame->sourceURL(); + } + + auto errorMessage = retrieveErrorMessage(*exec, vm, exception->value(), scope); + globalObject->scriptExecutionContext()->reportException(errorMessage, lineNumber, columnNumber, exceptionSourceURL, exception, callStack->size() ? callStack.ptr() : nullptr, cachedScript); + + if (exceptionDetails) { + exceptionDetails->message = errorMessage; + exceptionDetails->lineNumber = lineNumber; + exceptionDetails->columnNumber = columnNumber; + exceptionDetails->sourceURL = exceptionSourceURL; + } +} + +void reportCurrentException(ExecState* exec) +{ + VM& vm = exec->vm(); + auto scope = DECLARE_CATCH_SCOPE(vm); + auto* exception = scope.exception(); + scope.clearException(); + reportException(exec, exception); +} + +static JSValue createDOMException(ExecState* exec, ExceptionCode ec, const String* message = nullptr) +{ + if (!ec || ec == ExistingExceptionError) + return jsUndefined(); + + // FIXME: Handle other WebIDL exception types. + if (ec == TypeError) { + if (!message || message->isEmpty()) + return createTypeError(exec); + return createTypeError(exec, *message); + } + + if (ec == RangeError) { + if (!message || message->isEmpty()) + return createRangeError(exec, ASCIILiteral("Bad value")); + return createRangeError(exec, *message); + } + + if (ec == StackOverflowError) + return createStackOverflowError(exec); + + // FIXME: All callers to createDOMException need to pass in the correct global object. + // For now, we're going to assume the lexicalGlobalObject. Which is wrong in cases like this: + // frames[0].document.createElement(null, null); // throws an exception which should have the subframe's prototypes. + JSDOMGlobalObject* globalObject = deprecatedGlobalObjectForPrototype(exec); + + ExceptionCodeDescription description(ec); + + CString messageCString; + if (message) + messageCString = message->utf8(); + if (message && !message->isEmpty()) { + // It is safe to do this because the char* contents of the CString are copied into a new WTF::String before the CString is destroyed. + description.description = messageCString.data(); + } + + JSValue errorObject; + switch (description.type) { + case DOMCoreExceptionType: +#if ENABLE(INDEXED_DATABASE) + case IDBDatabaseExceptionType: +#endif + errorObject = toJS(exec, globalObject, DOMCoreException::create(description)); + break; + case FileExceptionType: + errorObject = toJS(exec, globalObject, FileException::create(description)); + break; + case SQLExceptionType: + errorObject = toJS(exec, globalObject, SQLException::create(description)); + break; + case SVGExceptionType: + errorObject = toJS(exec, globalObject, SVGException::create(description)); + break; + case XPathExceptionType: + errorObject = toJS(exec, globalObject, XPathException::create(description)); + break; + } + + ASSERT(errorObject); + addErrorInfo(exec, asObject(errorObject), true); + return errorObject; +} + +JSValue createDOMException(ExecState* exec, ExceptionCode ec, const String& message) +{ + return createDOMException(exec, ec, &message); +} + +JSValue createDOMException(ExecState& state, Exception&& exception) +{ + return createDOMException(&state, exception.code(), exception.releaseMessage()); +} + +void propagateExceptionSlowPath(JSC::ExecState& state, JSC::ThrowScope& throwScope, Exception&& exception) +{ + ASSERT(!throwScope.exception()); + throwException(&state, throwScope, createDOMException(state, WTFMove(exception))); +} + +static EncodedJSValue throwTypeError(JSC::ExecState& state, JSC::ThrowScope& scope, const String& errorMessage) +{ + return throwVMTypeError(&state, scope, errorMessage); +} + +static void appendArgumentMustBe(StringBuilder& builder, unsigned argumentIndex, const char* argumentName, const char* interfaceName, const char* functionName) +{ + builder.appendLiteral("Argument "); + builder.appendNumber(argumentIndex + 1); + builder.appendLiteral(" ('"); + builder.append(argumentName); + builder.appendLiteral("') to "); + if (!functionName) { + builder.appendLiteral("the "); + builder.append(interfaceName); + builder.appendLiteral(" constructor"); + } else { + builder.append(interfaceName); + builder.append('.'); + builder.append(functionName); + } + builder.appendLiteral(" must be "); +} + +JSC::EncodedJSValue reportDeprecatedGetterError(JSC::ExecState& state, const char* interfaceName, const char* attributeName) +{ + auto& context = *jsCast<JSDOMGlobalObject*>(state.lexicalGlobalObject())->scriptExecutionContext(); + context.addConsoleMessage(MessageSource::JS, MessageLevel::Error, makeString("Deprecated attempt to access property '", attributeName, "' on a non-", interfaceName, " object.")); + return JSValue::encode(jsUndefined()); +} + +void reportDeprecatedSetterError(JSC::ExecState& state, const char* interfaceName, const char* attributeName) +{ + auto& context = *jsCast<JSDOMGlobalObject*>(state.lexicalGlobalObject())->scriptExecutionContext(); + context.addConsoleMessage(MessageSource::JS, MessageLevel::Error, makeString("Deprecated attempt to set property '", attributeName, "' on a non-", interfaceName, " object.")); +} + +void throwNotSupportedError(JSC::ExecState& state, JSC::ThrowScope& scope) +{ + ASSERT(!scope.exception()); + throwException(&state, scope, createDOMException(&state, NOT_SUPPORTED_ERR)); +} + +void throwNotSupportedError(JSC::ExecState& state, JSC::ThrowScope& scope, const char* message) +{ + ASSERT(!scope.exception()); + String messageString(message); + throwException(&state, scope, createDOMException(&state, NOT_SUPPORTED_ERR, &messageString)); +} + +void throwInvalidStateError(JSC::ExecState& state, JSC::ThrowScope& scope, const char* message) +{ + ASSERT(!scope.exception()); + String messageString(message); + throwException(&state, scope, createDOMException(&state, INVALID_STATE_ERR, &messageString)); +} + +void throwSecurityError(JSC::ExecState& state, JSC::ThrowScope& scope, const String& message) +{ + ASSERT(!scope.exception()); + throwException(&state, scope, createDOMException(&state, SECURITY_ERR, message)); +} + +JSC::EncodedJSValue throwArgumentMustBeEnumError(JSC::ExecState& state, JSC::ThrowScope& scope, unsigned argumentIndex, const char* argumentName, const char* functionInterfaceName, const char* functionName, const char* expectedValues) +{ + StringBuilder builder; + appendArgumentMustBe(builder, argumentIndex, argumentName, functionInterfaceName, functionName); + builder.appendLiteral("one of: "); + builder.append(expectedValues); + return throwVMTypeError(&state, scope, builder.toString()); +} + +JSC::EncodedJSValue throwArgumentMustBeFunctionError(JSC::ExecState& state, JSC::ThrowScope& scope, unsigned argumentIndex, const char* argumentName, const char* interfaceName, const char* functionName) +{ + StringBuilder builder; + appendArgumentMustBe(builder, argumentIndex, argumentName, interfaceName, functionName); + builder.appendLiteral("a function"); + return throwVMTypeError(&state, scope, builder.toString()); +} + +JSC::EncodedJSValue throwArgumentTypeError(JSC::ExecState& state, JSC::ThrowScope& scope, unsigned argumentIndex, const char* argumentName, const char* functionInterfaceName, const char* functionName, const char* expectedType) +{ + StringBuilder builder; + appendArgumentMustBe(builder, argumentIndex, argumentName, functionInterfaceName, functionName); + builder.appendLiteral("an instance of "); + builder.append(expectedType); + return throwVMTypeError(&state, scope, builder.toString()); +} + +void throwArrayElementTypeError(JSC::ExecState& state, JSC::ThrowScope& scope) +{ + throwTypeError(state, scope, ASCIILiteral("Invalid Array element type")); +} + +void throwAttributeTypeError(JSC::ExecState& state, JSC::ThrowScope& scope, const char* interfaceName, const char* attributeName, const char* expectedType) +{ + throwTypeError(state, scope, makeString("The ", interfaceName, '.', attributeName, " attribute must be an instance of ", expectedType)); +} + +JSC::EncodedJSValue throwRequiredMemberTypeError(JSC::ExecState& state, JSC::ThrowScope& scope, const char* memberName, const char* dictionaryName, const char* expectedType) +{ + StringBuilder builder; + builder.appendLiteral("Member "); + builder.append(dictionaryName); + builder.append('.'); + builder.append(memberName); + builder.appendLiteral(" is required and must be an instance of "); + builder.append(expectedType); + return throwVMTypeError(&state, scope, builder.toString()); +} + +JSC::EncodedJSValue throwConstructorScriptExecutionContextUnavailableError(JSC::ExecState& state, JSC::ThrowScope& scope, const char* interfaceName) +{ + return throwVMError(&state, scope, createReferenceError(&state, makeString(interfaceName, " constructor associated execution context is unavailable"))); +} + +void throwSequenceTypeError(JSC::ExecState& state, JSC::ThrowScope& scope) +{ + throwTypeError(state, scope, ASCIILiteral("Value is not a sequence")); +} + +void throwNonFiniteTypeError(ExecState& state, JSC::ThrowScope& scope) +{ + throwTypeError(&state, scope, ASCIILiteral("The provided value is non-finite")); +} + +String makeGetterTypeErrorMessage(const char* interfaceName, const char* attributeName) +{ + return makeString("The ", interfaceName, '.', attributeName, " getter can only be used on instances of ", interfaceName); +} + +JSC::EncodedJSValue throwGetterTypeError(JSC::ExecState& state, JSC::ThrowScope& scope, const char* interfaceName, const char* attributeName) +{ + return throwVMTypeError(&state, scope, makeGetterTypeErrorMessage(interfaceName, attributeName)); +} + +JSC::EncodedJSValue rejectPromiseWithGetterTypeError(JSC::ExecState& state, const char* interfaceName, const char* attributeName) +{ + return createRejectedPromiseWithTypeError(state, makeGetterTypeErrorMessage(interfaceName, attributeName)); +} + +bool throwSetterTypeError(JSC::ExecState& state, JSC::ThrowScope& scope, const char* interfaceName, const char* attributeName) +{ + throwTypeError(state, scope, makeString("The ", interfaceName, '.', attributeName, " setter can only be used on instances of ", interfaceName)); + return false; +} + +String makeThisTypeErrorMessage(const char* interfaceName, const char* functionName) +{ + return makeString("Can only call ", interfaceName, '.', functionName, " on instances of ", interfaceName); +} + +EncodedJSValue throwThisTypeError(JSC::ExecState& state, JSC::ThrowScope& scope, const char* interfaceName, const char* functionName) +{ + return throwTypeError(state, scope, makeThisTypeErrorMessage(interfaceName, functionName)); +} + +JSC::EncodedJSValue rejectPromiseWithThisTypeError(DeferredPromise& promise, const char* interfaceName, const char* methodName) +{ + promise.reject(TypeError, makeThisTypeErrorMessage(interfaceName, methodName)); + return JSValue::encode(jsUndefined()); +} + +JSC::EncodedJSValue rejectPromiseWithThisTypeError(JSC::ExecState& state, const char* interfaceName, const char* methodName) +{ + return createRejectedPromiseWithTypeError(state, makeThisTypeErrorMessage(interfaceName, methodName)); +} + +void throwDOMSyntaxError(JSC::ExecState& state, JSC::ThrowScope& scope) +{ + ASSERT(!scope.exception()); + throwException(&state, scope, createDOMException(&state, SYNTAX_ERR)); +} + +void throwDataCloneError(JSC::ExecState& state, JSC::ThrowScope& scope) +{ + ASSERT(!scope.exception()); + throwException(&state, scope, createDOMException(&state, DATA_CLONE_ERR)); +} + +void throwIndexSizeError(JSC::ExecState& state, JSC::ThrowScope& scope) +{ + ASSERT(!scope.exception()); + throwException(&state, scope, createDOMException(&state, INDEX_SIZE_ERR)); +} + +void throwTypeMismatchError(JSC::ExecState& state, JSC::ThrowScope& scope) +{ + ASSERT(!scope.exception()); + throwException(&state, scope, createDOMException(&state, TYPE_MISMATCH_ERR)); +} + +} // namespace WebCore diff --git a/Source/WebCore/bindings/js/JSDOMExceptionHandling.h b/Source/WebCore/bindings/js/JSDOMExceptionHandling.h new file mode 100644 index 000000000..0300213b2 --- /dev/null +++ b/Source/WebCore/bindings/js/JSDOMExceptionHandling.h @@ -0,0 +1,105 @@ +/* + * Copyright (C) 1999-2001 Harri Porten (porten@kde.org) + * Copyright (C) 2003-2006, 2008-2009, 2013, 2016 Apple Inc. All rights reserved. + * Copyright (C) 2007 Samuel Weinig <sam@webkit.org> + * Copyright (C) 2009 Google, Inc. All rights reserved. + * Copyright (C) 2012 Ericsson AB. All rights reserved. + * Copyright (C) 2013 Michael Pruett <michael@68k.org> + * + * 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 + */ + +#pragma once + +#include "ExceptionCode.h" +#include "ExceptionOr.h" +#include <runtime/Error.h> + +namespace JSC { +class CatchScope; +} + +namespace WebCore { + +class CachedScript; +class DeferredPromise; +class JSDOMGlobalObject; + +struct ExceptionDetails { + String message; + int lineNumber { 0 }; + int columnNumber { 0 }; + String sourceURL; +}; + +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 throwAttributeTypeError(JSC::ExecState&, JSC::ThrowScope&, const char* interfaceName, const char* attributeName, const char* expectedType); +WEBCORE_EXPORT bool throwSetterTypeError(JSC::ExecState&, JSC::ThrowScope&, const char* interfaceName, const char* attributeName); + +void throwArrayElementTypeError(JSC::ExecState&, JSC::ThrowScope&); +void throwDataCloneError(JSC::ExecState&, JSC::ThrowScope&); +void throwDOMSyntaxError(JSC::ExecState&, JSC::ThrowScope&); // Not the same as a JavaScript syntax error. +void throwIndexSizeError(JSC::ExecState&, JSC::ThrowScope&); +void throwInvalidStateError(JSC::ExecState&, JSC::ThrowScope&, const char* message); +WEBCORE_EXPORT void throwNonFiniteTypeError(JSC::ExecState&, JSC::ThrowScope&); +void throwNotSupportedError(JSC::ExecState&, JSC::ThrowScope&); +void throwNotSupportedError(JSC::ExecState&, JSC::ThrowScope&, const char* message); +void throwSecurityError(JSC::ExecState&, JSC::ThrowScope&, const String& message); +WEBCORE_EXPORT void throwSequenceTypeError(JSC::ExecState&, JSC::ThrowScope&); +void throwTypeMismatchError(JSC::ExecState&, JSC::ThrowScope&); + +WEBCORE_EXPORT JSC::EncodedJSValue throwArgumentMustBeEnumError(JSC::ExecState&, JSC::ThrowScope&, unsigned argumentIndex, const char* argumentName, const char* functionInterfaceName, const char* functionName, const char* expectedValues); +JSC::EncodedJSValue throwArgumentMustBeFunctionError(JSC::ExecState&, JSC::ThrowScope&, unsigned argumentIndex, const char* argumentName, const char* functionInterfaceName, const char* functionName); +WEBCORE_EXPORT JSC::EncodedJSValue throwArgumentTypeError(JSC::ExecState&, JSC::ThrowScope&, unsigned argumentIndex, const char* argumentName, const char* functionInterfaceName, const char* functionName, const char* expectedType); +WEBCORE_EXPORT JSC::EncodedJSValue throwRequiredMemberTypeError(JSC::ExecState&, JSC::ThrowScope&, const char* memberName, const char* dictionaryName, const char* expectedType); +JSC::EncodedJSValue throwConstructorScriptExecutionContextUnavailableError(JSC::ExecState&, JSC::ThrowScope&, const char* interfaceName); + +String makeGetterTypeErrorMessage(const char* interfaceName, const char* attributeName); +String makeThisTypeErrorMessage(const char* interfaceName, const char* attributeName); + +WEBCORE_EXPORT JSC::EncodedJSValue throwGetterTypeError(JSC::ExecState&, JSC::ThrowScope&, const char* interfaceName, const char* attributeName); +WEBCORE_EXPORT JSC::EncodedJSValue throwThisTypeError(JSC::ExecState&, JSC::ThrowScope&, const char* interfaceName, const char* functionName); + +WEBCORE_EXPORT JSC::EncodedJSValue rejectPromiseWithGetterTypeError(JSC::ExecState&, const char* interfaceName, const char* attributeName); +WEBCORE_EXPORT JSC::EncodedJSValue rejectPromiseWithThisTypeError(DeferredPromise&, const char* interfaceName, const char* operationName); +WEBCORE_EXPORT JSC::EncodedJSValue rejectPromiseWithThisTypeError(JSC::ExecState&, const char* interfaceName, const char* operationName); + +String retrieveErrorMessage(JSC::ExecState&, JSC::VM&, JSC::JSValue exception, JSC::CatchScope&); +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&, Exception&&); +JSC::JSValue createDOMException(JSC::ExecState*, ExceptionCode, const String&); + +// Convert a DOM implementation exception into a JavaScript exception in the execution state. +WEBCORE_EXPORT void propagateExceptionSlowPath(JSC::ExecState&, JSC::ThrowScope&, Exception&&); + +ALWAYS_INLINE void propagateException(JSC::ExecState& state, JSC::ThrowScope& throwScope, Exception&& exception) +{ + if (throwScope.exception()) + return; + propagateExceptionSlowPath(state, throwScope, WTFMove(exception)); +} + +inline void propagateException(JSC::ExecState& state, JSC::ThrowScope& throwScope, ExceptionOr<void>&& value) +{ + if (UNLIKELY(value.hasException())) + propagateException(state, throwScope, value.releaseException()); +} + +} // namespace WebCore diff --git a/Source/WebCore/bindings/js/JSDOMFormDataCustom.cpp b/Source/WebCore/bindings/js/JSDOMFormDataCustom.cpp deleted file mode 100644 index 6d371b309..000000000 --- a/Source/WebCore/bindings/js/JSDOMFormDataCustom.cpp +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright (C) 2010 Google Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" -#include "JSDOMFormData.h" - -#include "DOMFormData.h" -#include "HTMLFormElement.h" -#include "JSBlob.h" -#include "JSHTMLFormElement.h" -#include <runtime/Error.h> - -using namespace JSC; - -namespace WebCore { - -static HTMLFormElement* toHTMLFormElement(JSC::JSValue value) -{ - return value.inherits(JSHTMLFormElement::info()) ? &jsCast<JSHTMLFormElement*>(asObject(value))->impl() : 0; -} - -EncodedJSValue JSC_HOST_CALL JSDOMFormDataConstructor::constructJSDOMFormData(ExecState* exec) -{ - JSDOMFormDataConstructor* jsConstructor = jsCast<JSDOMFormDataConstructor*>(exec->callee()); - - HTMLFormElement* form = 0; - if (exec->argumentCount() > 0) - form = toHTMLFormElement(exec->argument(0)); - RefPtr<DOMFormData> domFormData = DOMFormData::create(form); - return JSValue::encode(asObject(toJS(exec, jsConstructor->globalObject(), domFormData.get()))); -} - -JSValue JSDOMFormData::append(ExecState* exec) -{ - if (exec->argumentCount() >= 2) { - String name = exec->argument(0).toString(exec)->value(exec); - JSValue value = exec->argument(1); - if (value.inherits(JSBlob::info())) { - String filename; - if (exec->argumentCount() >= 3 && !exec->argument(2).isUndefinedOrNull()) - filename = exec->argument(2).toString(exec)->value(exec); - impl().append(name, toBlob(value), filename); - } else - impl().append(name, value.toString(exec)->value(exec)); - } - - return jsUndefined(); -} - -} // namespace WebCore diff --git a/Source/WebCore/bindings/js/JSDOMGlobalObject.cpp b/Source/WebCore/bindings/js/JSDOMGlobalObject.cpp index 27bd7894f..933650611 100644 --- a/Source/WebCore/bindings/js/JSDOMGlobalObject.cpp +++ b/Source/WebCore/bindings/js/JSDOMGlobalObject.cpp @@ -10,10 +10,10 @@ * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * - * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR @@ -28,23 +28,42 @@ #include "JSDOMGlobalObject.h" #include "Document.h" +#include "JSDOMPromise.h" #include "JSDOMWindow.h" #include "JSEventListener.h" +#include "JSMediaStream.h" +#include "JSMediaStreamTrack.h" +#include "JSRTCIceCandidate.h" +#include "JSRTCSessionDescription.h" +#include "JSReadableStream.h" +#include "JSReadableStreamPrivateConstructors.h" #include "JSWorkerGlobalScope.h" +#include "RuntimeEnabledFeatures.h" +#include "StructuredClone.h" +#include "WebCoreJSClientData.h" #include "WorkerGlobalScope.h" +#include <builtins/BuiltinNames.h> using namespace JSC; namespace WebCore { -const ClassInfo JSDOMGlobalObject::s_info = { "DOMGlobalObject", &JSGlobalObject::s_info, 0, 0, CREATE_METHOD_TABLE(JSDOMGlobalObject) }; +EncodedJSValue JSC_HOST_CALL makeThisTypeErrorForBuiltins(ExecState*); +EncodedJSValue JSC_HOST_CALL makeGetterTypeErrorForBuiltins(ExecState*); -JSDOMGlobalObject::JSDOMGlobalObject(VM& vm, Structure* structure, PassRefPtr<DOMWrapperWorld> world, const GlobalObjectMethodTable* globalObjectMethodTable) +const ClassInfo JSDOMGlobalObject::s_info = { "DOMGlobalObject", &JSGlobalObject::s_info, 0, CREATE_METHOD_TABLE(JSDOMGlobalObject) }; + +JSDOMGlobalObject::JSDOMGlobalObject(VM& vm, Structure* structure, Ref<DOMWrapperWorld>&& world, const GlobalObjectMethodTable* globalObjectMethodTable) : JSGlobalObject(vm, structure, globalObjectMethodTable) , m_currentEvent(0) - , m_world(world) + , m_world(WTFMove(world)) + , m_worldIsNormal(m_world->isNormal()) + , m_builtinInternalFunctions(vm) +{ +} + +JSDOMGlobalObject::~JSDOMGlobalObject() { - ASSERT(m_world); } void JSDOMGlobalObject::destroy(JSCell* cell) @@ -52,33 +71,118 @@ void JSDOMGlobalObject::destroy(JSCell* cell) static_cast<JSDOMGlobalObject*>(cell)->JSDOMGlobalObject::~JSDOMGlobalObject(); } +EncodedJSValue JSC_HOST_CALL makeThisTypeErrorForBuiltins(ExecState* execState) +{ + ASSERT(execState); + ASSERT(execState->argumentCount() == 2); + VM& vm = execState->vm(); + auto scope = DECLARE_CATCH_SCOPE(vm); + + auto interfaceName = execState->uncheckedArgument(0).getString(execState); + ASSERT_UNUSED(scope, !scope.exception()); + auto functionName = execState->uncheckedArgument(1).getString(execState); + ASSERT(!scope.exception()); + return JSValue::encode(createTypeError(execState, makeThisTypeErrorMessage(interfaceName.utf8().data(), functionName.utf8().data()))); +} + +EncodedJSValue JSC_HOST_CALL makeGetterTypeErrorForBuiltins(ExecState* execState) +{ + ASSERT(execState); + ASSERT(execState->argumentCount() == 2); + VM& vm = execState->vm(); + auto scope = DECLARE_CATCH_SCOPE(vm); + + auto interfaceName = execState->uncheckedArgument(0).getString(execState); + ASSERT_UNUSED(scope, !scope.exception()); + auto attributeName = execState->uncheckedArgument(1).getString(execState); + ASSERT(!scope.exception()); + return JSValue::encode(createTypeError(execState, makeGetterTypeErrorMessage(interfaceName.utf8().data(), attributeName.utf8().data()))); +} + +void JSDOMGlobalObject::addBuiltinGlobals(VM& vm) +{ + m_builtinInternalFunctions.initialize(*this); + +#if ENABLE(READABLE_STREAM_API) + JSObject* privateReadableStreamDefaultControllerConstructor = createReadableStreamDefaultControllerPrivateConstructor(vm, *this); +#if ENABLE(READABLE_BYTE_STREAM_API) + JSObject* privateReadableByteStreamControllerConstructor = createReadableByteStreamControllerPrivateConstructor(vm, *this); +#endif + JSObject* privateReadableStreamDefaultReaderConstructor = createReadableStreamDefaultReaderPrivateConstructor(vm, *this); + + ASSERT(!constructors(NoLockingNecessary).get(privateReadableStreamDefaultControllerConstructor->info()).get()); +#if ENABLE(READABLE_BYTE_STREAM_API) + ASSERT(!constructors(NoLockingNecessary).get(privateReadableByteStreamControllerConstructor->info()).get()); +#endif + ASSERT(!constructors(NoLockingNecessary).get(privateReadableStreamDefaultReaderConstructor->info()).get()); + JSC::WriteBarrier<JSC::JSObject> temp; + { + auto locker = lockDuringMarking(vm.heap, m_gcLock); + constructors(locker).add(privateReadableStreamDefaultControllerConstructor->info(), temp).iterator->value.set(vm, this, privateReadableStreamDefaultControllerConstructor); +#if ENABLE(READABLE_BYTE_STREAM_API) + constructors(locker).add(privateReadableByteStreamControllerConstructor->info(), temp).iterator->value.set(vm, this, privateReadableByteStreamControllerConstructor); +#endif + constructors(locker).add(privateReadableStreamDefaultReaderConstructor->info(), temp).iterator->value.set(vm, this, privateReadableStreamDefaultReaderConstructor); + } +#endif + JSVMClientData& clientData = *static_cast<JSVMClientData*>(vm.clientData); + JSDOMGlobalObject::GlobalPropertyInfo staticGlobals[] = { + JSDOMGlobalObject::GlobalPropertyInfo(clientData.builtinNames().makeThisTypeErrorPrivateName(), + JSFunction::create(vm, this, 2, String(), makeThisTypeErrorForBuiltins), DontDelete | ReadOnly), + JSDOMGlobalObject::GlobalPropertyInfo(clientData.builtinNames().makeGetterTypeErrorPrivateName(), + JSFunction::create(vm, this, 2, String(), makeGetterTypeErrorForBuiltins), DontDelete | ReadOnly), + JSDOMGlobalObject::GlobalPropertyInfo(clientData.builtinNames().structuredCloneArrayBufferPrivateName(), + JSFunction::create(vm, this, 1, String(), structuredCloneArrayBuffer), DontDelete | ReadOnly), + JSDOMGlobalObject::GlobalPropertyInfo(clientData.builtinNames().structuredCloneArrayBufferViewPrivateName(), + JSFunction::create(vm, this, 1, String(), structuredCloneArrayBufferView), DontDelete | ReadOnly), + JSDOMGlobalObject::GlobalPropertyInfo(vm.propertyNames->builtinNames().ArrayBufferPrivateName(), getDirect(vm, vm.propertyNames->ArrayBuffer), DontDelete | ReadOnly), +#if ENABLE(READABLE_STREAM_API) || ENABLE(WRITABLE_STREAM_API) + JSDOMGlobalObject::GlobalPropertyInfo(clientData.builtinNames().streamClosedPrivateName(), jsNumber(1), DontDelete | ReadOnly), + JSDOMGlobalObject::GlobalPropertyInfo(clientData.builtinNames().streamClosingPrivateName(), jsNumber(2), DontDelete | ReadOnly), + JSDOMGlobalObject::GlobalPropertyInfo(clientData.builtinNames().streamErroredPrivateName(), jsNumber(3), DontDelete | ReadOnly), + JSDOMGlobalObject::GlobalPropertyInfo(clientData.builtinNames().streamReadablePrivateName(), jsNumber(4), DontDelete | ReadOnly), + JSDOMGlobalObject::GlobalPropertyInfo(clientData.builtinNames().streamWaitingPrivateName(), jsNumber(5), DontDelete | ReadOnly), + JSDOMGlobalObject::GlobalPropertyInfo(clientData.builtinNames().streamWritablePrivateName(), jsNumber(6), DontDelete | ReadOnly), +#endif +#if ENABLE(READABLE_STREAM_API) + JSDOMGlobalObject::GlobalPropertyInfo(clientData.builtinNames().ReadableStreamDefaultControllerPrivateName(), privateReadableStreamDefaultControllerConstructor, DontDelete | ReadOnly), +#if ENABLE(READABLE_BYTE_STREAM_API) + JSDOMGlobalObject::GlobalPropertyInfo(clientData.builtinNames().ReadableByteStreamControllerPrivateName(), privateReadableByteStreamControllerConstructor, DontDelete | ReadOnly), +#endif + JSDOMGlobalObject::GlobalPropertyInfo(clientData.builtinNames().ReadableStreamDefaultReaderPrivateName(), privateReadableStreamDefaultReaderConstructor, DontDelete | ReadOnly), +#endif + }; + addStaticGlobals(staticGlobals, WTF_ARRAY_LENGTH(staticGlobals)); +} + void JSDOMGlobalObject::finishCreation(VM& vm) { Base::finishCreation(vm); - ASSERT(inherits(info())); + ASSERT(inherits(vm, info())); -#if ENABLE(REMOTE_INSPECTOR) - setRemoteDebuggingEnabled(false); -#endif + addBuiltinGlobals(vm); + + RELEASE_ASSERT(classInfo()); } void JSDOMGlobalObject::finishCreation(VM& vm, JSObject* thisValue) { Base::finishCreation(vm, thisValue); - ASSERT(inherits(info())); + ASSERT(inherits(vm, info())); -#if ENABLE(REMOTE_INSPECTOR) - setRemoteDebuggingEnabled(false); -#endif + addBuiltinGlobals(vm); + + RELEASE_ASSERT(classInfo()); } ScriptExecutionContext* JSDOMGlobalObject::scriptExecutionContext() const { - if (inherits(JSDOMWindowBase::info())) + if (inherits(vm(), JSDOMWindowBase::info())) return jsCast<const JSDOMWindowBase*>(this)->scriptExecutionContext(); - if (inherits(JSWorkerGlobalScopeBase::info())) + if (inherits(vm(), JSWorkerGlobalScopeBase::info())) return jsCast<const JSWorkerGlobalScopeBase*>(this)->scriptExecutionContext(); - ASSERT_NOT_REACHED(); + dataLog("Unexpected global object: ", JSValue(this), "\n"); + RELEASE_ASSERT_NOT_REACHED(); return 0; } @@ -86,17 +190,22 @@ void JSDOMGlobalObject::visitChildren(JSCell* cell, SlotVisitor& visitor) { JSDOMGlobalObject* thisObject = jsCast<JSDOMGlobalObject*>(cell); ASSERT_GC_OBJECT_INHERITS(thisObject, info()); - COMPILE_ASSERT(StructureFlags & OverridesVisitChildren, OverridesVisitChildrenWithoutSettingFlag); - ASSERT(thisObject->structure()->typeInfo().overridesVisitChildren()); Base::visitChildren(thisObject, visitor); - - JSDOMStructureMap::iterator end = thisObject->structures().end(); - for (JSDOMStructureMap::iterator it = thisObject->structures().begin(); it != end; ++it) - visitor.append(&it->value); - - JSDOMConstructorMap::iterator end2 = thisObject->constructors().end(); - for (JSDOMConstructorMap::iterator it2 = thisObject->constructors().begin(); it2 != end2; ++it2) - visitor.append(&it2->value); + + { + auto locker = holdLock(thisObject->m_gcLock); + + for (auto& structure : thisObject->structures(locker).values()) + visitor.append(structure); + + for (auto& constructor : thisObject->constructors(locker).values()) + visitor.append(constructor); + + for (auto& deferredPromise : thisObject->deferredPromises(locker)) + deferredPromise->visitAggregate(visitor); + } + + thisObject->m_builtinInternalFunctions.visit(visitor); } void JSDOMGlobalObject::setCurrentEvent(Event* currentEvent) @@ -116,14 +225,14 @@ JSDOMGlobalObject* toJSDOMGlobalObject(Document* document, JSC::ExecState* exec) JSDOMGlobalObject* toJSDOMGlobalObject(ScriptExecutionContext* scriptExecutionContext, JSC::ExecState* exec) { - if (scriptExecutionContext->isDocument()) - return toJSDOMGlobalObject(toDocument(scriptExecutionContext), exec); + if (is<Document>(*scriptExecutionContext)) + return toJSDOMGlobalObject(downcast<Document>(scriptExecutionContext), exec); - if (scriptExecutionContext->isWorkerGlobalScope()) - return static_cast<WorkerGlobalScope*>(scriptExecutionContext)->script()->workerGlobalScopeWrapper(); + if (is<WorkerGlobalScope>(*scriptExecutionContext)) + return downcast<WorkerGlobalScope>(*scriptExecutionContext).script()->workerGlobalScopeWrapper(); ASSERT_NOT_REACHED(); - return 0; + return nullptr; } JSDOMGlobalObject* toJSDOMGlobalObject(Document* document, DOMWrapperWorld& world) @@ -133,14 +242,14 @@ JSDOMGlobalObject* toJSDOMGlobalObject(Document* document, DOMWrapperWorld& worl JSDOMGlobalObject* toJSDOMGlobalObject(ScriptExecutionContext* scriptExecutionContext, DOMWrapperWorld& world) { - if (scriptExecutionContext->isDocument()) - return toJSDOMGlobalObject(toDocument(scriptExecutionContext), world); + if (is<Document>(*scriptExecutionContext)) + return toJSDOMGlobalObject(downcast<Document>(scriptExecutionContext), world); - if (scriptExecutionContext->isWorkerGlobalScope()) - return static_cast<WorkerGlobalScope*>(scriptExecutionContext)->script()->workerGlobalScopeWrapper(); + if (is<WorkerGlobalScope>(*scriptExecutionContext)) + return downcast<WorkerGlobalScope>(*scriptExecutionContext).script()->workerGlobalScopeWrapper(); ASSERT_NOT_REACHED(); - return 0; + return nullptr; } } // namespace WebCore diff --git a/Source/WebCore/bindings/js/JSDOMGlobalObject.h b/Source/WebCore/bindings/js/JSDOMGlobalObject.h index 6eab99967..456d953ba 100644 --- a/Source/WebCore/bindings/js/JSDOMGlobalObject.h +++ b/Source/WebCore/bindings/js/JSDOMGlobalObject.h @@ -10,10 +10,10 @@ * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * - * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR @@ -24,15 +24,17 @@ * */ -#ifndef JSDOMGlobalObject_h -#define JSDOMGlobalObject_h +#pragma once #include "PlatformExportMacros.h" +#include "WebCoreJSBuiltinInternals.h" +#include <heap/LockDuringMarking.h> #include <runtime/JSGlobalObject.h> -#include <runtime/Operations.h> +#include <runtime/StructureInlines.h> namespace WebCore { + class DeferredPromise; class Document; class Event; class DOMWrapperWorld; @@ -40,20 +42,25 @@ namespace WebCore { typedef HashMap<const JSC::ClassInfo*, JSC::WriteBarrier<JSC::Structure>> JSDOMStructureMap; typedef HashMap<const JSC::ClassInfo*, JSC::WriteBarrier<JSC::JSObject>> JSDOMConstructorMap; + typedef HashSet<DeferredPromise*> DeferredPromiseSet; - class JSDOMGlobalObject : public JSC::JSGlobalObject { + class WEBCORE_EXPORT JSDOMGlobalObject : public JSC::JSGlobalObject { typedef JSC::JSGlobalObject Base; protected: struct JSDOMGlobalObjectData; - JSDOMGlobalObject(JSC::VM&, JSC::Structure*, PassRefPtr<DOMWrapperWorld>, const JSC::GlobalObjectMethodTable* = 0); + JSDOMGlobalObject(JSC::VM&, JSC::Structure*, Ref<DOMWrapperWorld>&&, const JSC::GlobalObjectMethodTable* = 0); static void destroy(JSC::JSCell*); void finishCreation(JSC::VM&); void finishCreation(JSC::VM&, JSC::JSObject*); public: - JSDOMStructureMap& structures() { return m_structures; } - JSDOMConstructorMap& constructors() { return m_constructors; } + Lock& gcLock() { return m_gcLock; } + + JSDOMStructureMap& structures(const AbstractLocker&) { return m_structures; } + JSDOMConstructorMap& constructors(const AbstractLocker&) { return m_constructors; } + + DeferredPromiseSet& deferredPromises(const AbstractLocker&) { return m_deferredPromises; } ScriptExecutionContext* scriptExecutionContext() const; @@ -65,13 +72,19 @@ namespace WebCore { static void visitChildren(JSC::JSCell*, JSC::SlotVisitor&); - DOMWrapperWorld& world() { return *m_world; } + DOMWrapperWorld& world() { return m_world.get(); } + bool worldIsNormal() const { return m_worldIsNormal; } + static ptrdiff_t offsetOfWorldIsNormal() { return OBJECT_OFFSETOF(JSDOMGlobalObject, m_worldIsNormal); } + + JSBuiltinInternalFunctions& builtinInternalFunctions() { return m_builtinInternalFunctions; } protected: - static WEBKIT_EXPORTDATA const JSC::ClassInfo s_info; + static const JSC::ClassInfo s_info; public: - static const JSC::ClassInfo* info() { return &s_info; } + ~JSDOMGlobalObject(); + + static constexpr const JSC::ClassInfo* info() { return &s_info; } static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSValue prototype) { @@ -81,20 +94,31 @@ namespace WebCore { protected: JSDOMStructureMap m_structures; JSDOMConstructorMap m_constructors; + DeferredPromiseSet m_deferredPromises; Event* m_currentEvent; - RefPtr<DOMWrapperWorld> m_world; + Ref<DOMWrapperWorld> m_world; + uint8_t m_worldIsNormal; + Lock m_gcLock; + + private: + void addBuiltinGlobals(JSC::VM&); + friend void JSBuiltinInternalFunctions::initialize(JSDOMGlobalObject&); + + JSBuiltinInternalFunctions m_builtinInternalFunctions; }; template<class ConstructorClass> - inline JSC::JSObject* getDOMConstructor(JSC::VM& vm, const JSDOMGlobalObject* globalObject) + inline JSC::JSObject* getDOMConstructor(JSC::VM& vm, const JSDOMGlobalObject& globalObject) { - if (JSC::JSObject* constructor = const_cast<JSDOMGlobalObject*>(globalObject)->constructors().get(ConstructorClass::info()).get()) + if (JSC::JSObject* constructor = const_cast<JSDOMGlobalObject&>(globalObject).constructors(NoLockingNecessary).get(ConstructorClass::info()).get()) return constructor; - JSC::JSObject* constructor = ConstructorClass::create(vm, ConstructorClass::createStructure(vm, const_cast<JSDOMGlobalObject*>(globalObject), globalObject->objectPrototype()), const_cast<JSDOMGlobalObject*>(globalObject)); - ASSERT(!const_cast<JSDOMGlobalObject*>(globalObject)->constructors().contains(ConstructorClass::info())); + JSC::JSObject* constructor = ConstructorClass::create(vm, ConstructorClass::createStructure(vm, const_cast<JSDOMGlobalObject&>(globalObject), ConstructorClass::prototypeForStructure(vm, globalObject)), const_cast<JSDOMGlobalObject&>(globalObject)); + ASSERT(!const_cast<JSDOMGlobalObject&>(globalObject).constructors(NoLockingNecessary).contains(ConstructorClass::info())); JSC::WriteBarrier<JSC::JSObject> temp; - const_cast<JSDOMGlobalObject*>(globalObject)->constructors().add(ConstructorClass::info(), temp).iterator->value.set(vm, globalObject, constructor); + JSDOMGlobalObject& mutableGlobalObject = const_cast<JSDOMGlobalObject&>(globalObject); + auto locker = JSC::lockDuringMarking(vm.heap, mutableGlobalObject.gcLock()); + mutableGlobalObject.constructors(locker).add(ConstructorClass::info(), temp).iterator->value.set(vm, &globalObject, constructor); return constructor; } @@ -105,5 +129,3 @@ namespace WebCore { JSDOMGlobalObject* toJSDOMGlobalObject(ScriptExecutionContext*, DOMWrapperWorld&); } // namespace WebCore - -#endif // JSDOMGlobalObject_h diff --git a/Source/WebCore/bindings/js/JSDOMGlobalObjectTask.cpp b/Source/WebCore/bindings/js/JSDOMGlobalObjectTask.cpp index 847dbd164..0be269683 100644 --- a/Source/WebCore/bindings/js/JSDOMGlobalObjectTask.cpp +++ b/Source/WebCore/bindings/js/JSDOMGlobalObjectTask.cpp @@ -38,9 +38,9 @@ namespace WebCore { class JSGlobalObjectCallback final : public RefCounted<JSGlobalObjectCallback>, private ActiveDOMCallback { public: - static PassRefPtr<JSGlobalObjectCallback> create(JSDOMGlobalObject* globalObject, PassRefPtr<Microtask> task) + static Ref<JSGlobalObjectCallback> create(JSDOMGlobalObject* globalObject, Ref<Microtask>&& task) { - return adoptRef(new JSGlobalObjectCallback(globalObject, task)); + return adoptRef(*new JSGlobalObjectCallback(globalObject, WTFMove(task))); } void call() @@ -48,8 +48,10 @@ public: if (!canInvokeCallback()) return; - Ref<JSGlobalObjectCallback> protect(*this); - JSLockHolder lock(m_globalObject->vm()); + Ref<JSGlobalObjectCallback> protectedThis(*this); + VM& vm = m_globalObject->vm(); + JSLockHolder lock(vm); + auto scope = DECLARE_THROW_SCOPE(vm); ExecState* exec = m_globalObject->globalExec(); @@ -60,37 +62,32 @@ public: // When on the main thread (e.g. the document's thread), we need to make sure to // push the current ExecState on to the JSMainThreadExecState stack. - if (context->isDocument()) { - JSMainThreadExecState currentState(exec); - m_task->run(exec); - } else + if (context->isDocument()) + JSMainThreadExecState::runTask(exec, m_task); + else m_task->run(exec); + ASSERT_UNUSED(scope, !scope.exception()); } private: - JSGlobalObjectCallback(JSDOMGlobalObject* globalObject, PassRefPtr<Microtask> task) + JSGlobalObjectCallback(JSDOMGlobalObject* globalObject, Ref<Microtask>&& task) : ActiveDOMCallback(globalObject->scriptExecutionContext()) , m_globalObject(globalObject->vm(), globalObject) - , m_task(task) + , m_task(WTFMove(task)) { } Strong<JSDOMGlobalObject> m_globalObject; - RefPtr<Microtask> m_task; + Ref<Microtask> m_task; }; -JSGlobalObjectTask::JSGlobalObjectTask(JSDOMGlobalObject* globalObject, PassRefPtr<Microtask> task) - : m_callback(JSGlobalObjectCallback::create(globalObject, task)) -{ -} - -JSGlobalObjectTask::~JSGlobalObjectTask() -{ -} - -void JSGlobalObjectTask::performTask(ScriptExecutionContext*) +JSGlobalObjectTask::JSGlobalObjectTask(JSDOMGlobalObject* globalObject, Ref<Microtask>&& task) + : ScriptExecutionContext::Task({ }) { - m_callback->call(); + RefPtr<JSGlobalObjectCallback> callback = JSGlobalObjectCallback::create(globalObject, WTFMove(task)); + m_task = [callback] (ScriptExecutionContext&) { + callback->call(); + }; } } // namespace WebCore diff --git a/Source/WebCore/bindings/js/JSDOMGlobalObjectTask.h b/Source/WebCore/bindings/js/JSDOMGlobalObjectTask.h index 3cb93f311..cc0ffb0e1 100644 --- a/Source/WebCore/bindings/js/JSDOMGlobalObjectTask.h +++ b/Source/WebCore/bindings/js/JSDOMGlobalObjectTask.h @@ -23,33 +23,16 @@ * THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef JSDOMGlobalObjectTask_h -#define JSDOMGlobalObjectTask_h +#pragma once #include "JSDOMGlobalObject.h" #include "ScriptExecutionContext.h" namespace WebCore { -class JSGlobalObjectCallback; - -class JSGlobalObjectTask final : public ScriptExecutionContext::Task { +class JSGlobalObjectTask : public ScriptExecutionContext::Task { public: - static PassOwnPtr<JSGlobalObjectTask> create(JSDOMGlobalObject* globalObject, PassRefPtr<JSC::Microtask> task) - { - return adoptPtr(new JSGlobalObjectTask(globalObject, task)); - } - - virtual ~JSGlobalObjectTask(); - -private: - JSGlobalObjectTask(JSDOMGlobalObject*, PassRefPtr<JSC::Microtask>); - - virtual void performTask(ScriptExecutionContext*) override; - - RefPtr<JSGlobalObjectCallback> m_callback; + JSGlobalObjectTask(JSDOMGlobalObject*, Ref<JSC::Microtask>&&); }; } // namespace WebCore - -#endif // JSDOMGlobalObjectTask_h diff --git a/Source/WebCore/bindings/js/JSDOMIterator.cpp b/Source/WebCore/bindings/js/JSDOMIterator.cpp new file mode 100644 index 000000000..45ef3a755 --- /dev/null +++ b/Source/WebCore/bindings/js/JSDOMIterator.cpp @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2016 Apple, Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "JSDOMIterator.h" + +#include <builtins/BuiltinNames.h> +#include <runtime/ArrayPrototype.h> + +namespace WebCore { + +void addValueIterableMethods(JSC::JSGlobalObject& globalObject, JSC::JSObject& prototype) +{ + JSC::ArrayPrototype* arrayPrototype = globalObject.arrayPrototype(); + ASSERT(arrayPrototype); + + JSC::ExecState* state = globalObject.globalExec(); + ASSERT(state); + JSC::VM& vm = state->vm(); + + auto copyProperty = [&] (const JSC::Identifier& arrayIdentifier, const JSC::Identifier& otherIdentifier, unsigned attributes = 0) { + JSC::JSValue value = arrayPrototype->getDirect(vm, arrayIdentifier); + ASSERT(value); + prototype.putDirect(vm, otherIdentifier, value, attributes); + }; + + copyProperty(vm.propertyNames->builtinNames().entriesPrivateName(), vm.propertyNames->builtinNames().entriesPublicName()); + copyProperty(vm.propertyNames->builtinNames().forEachPrivateName(), vm.propertyNames->builtinNames().forEachPublicName()); + copyProperty(vm.propertyNames->builtinNames().keysPrivateName(), vm.propertyNames->builtinNames().keysPublicName()); + copyProperty(vm.propertyNames->builtinNames().valuesPrivateName(), vm.propertyNames->builtinNames().valuesPublicName()); + copyProperty(vm.propertyNames->builtinNames().valuesPrivateName(), vm.propertyNames->builtinNames().iteratorSymbol(), JSC::DontEnum); +} + +} diff --git a/Source/WebCore/bindings/js/JSDOMIterator.h b/Source/WebCore/bindings/js/JSDOMIterator.h new file mode 100644 index 000000000..101749ab9 --- /dev/null +++ b/Source/WebCore/bindings/js/JSDOMIterator.h @@ -0,0 +1,266 @@ +/* + * Copyright (C) 2016 Canon, Inc. All rights reserved. + * Copyright (C) 2016 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY CANON INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL CANON INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +#include "JSDOMConvert.h" +#include <runtime/IteratorPrototype.h> +#include <runtime/JSDestructibleObject.h> +#include <type_traits> + +namespace WebCore { + +void addValueIterableMethods(JSC::JSGlobalObject&, JSC::JSObject&); + +enum class JSDOMIteratorType { Set, Map }; + +// struct IteratorTraits { +// static constexpr JSDOMIteratorType type = [Map|Set]; +// using KeyType = [IDLType|void]; +// using ValueType = [IDLType]; +// }; + +template<typename T, typename U = void> using EnableIfMap = typename std::enable_if<T::type == JSDOMIteratorType::Map, U>::type; +template<typename T, typename U = void> using EnableIfSet = typename std::enable_if<T::type == JSDOMIteratorType::Set, U>::type; + +template<typename JSWrapper, typename IteratorTraits> class JSDOMIteratorPrototype : public JSC::JSNonFinalObject { +public: + using Base = JSC::JSNonFinalObject; + using DOMWrapped = typename JSWrapper::DOMWrapped; + + static JSDOMIteratorPrototype* create(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::Structure* structure) + { + JSDOMIteratorPrototype* prototype = new (NotNull, JSC::allocateCell<JSDOMIteratorPrototype>(vm.heap)) JSDOMIteratorPrototype(vm, structure); + prototype->finishCreation(vm, globalObject); + return prototype; + } + + DECLARE_INFO; + + 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()); + } + + static JSC::EncodedJSValue JSC_HOST_CALL next(JSC::ExecState*); + +private: + JSDOMIteratorPrototype(JSC::VM& vm, JSC::Structure* structure) : Base(vm, structure) { } + + void finishCreation(JSC::VM&, JSC::JSGlobalObject*); +}; + +enum class IterationKind { Key, Value, KeyValue }; + +template<typename JSWrapper, typename IteratorTraits> class JSDOMIterator : public JSDOMObject { +public: + using Base = JSDOMObject; + + using Wrapper = JSWrapper; + using Traits = IteratorTraits; + + using DOMWrapped = typename Wrapper::DOMWrapped; + using Prototype = JSDOMIteratorPrototype<Wrapper, Traits>; + + DECLARE_INFO; + + 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()); + } + + static JSDOMIterator* create(JSC::VM& vm, JSC::Structure* structure, JSWrapper& iteratedObject, IterationKind kind) + { + JSDOMIterator* instance = new (NotNull, JSC::allocateCell<JSDOMIterator>(vm.heap)) JSDOMIterator(structure, iteratedObject, kind); + instance->finishCreation(vm); + return instance; + } + + static Prototype* createPrototype(JSC::VM& vm, JSC::JSGlobalObject* globalObject) + { + return Prototype::create(vm, globalObject, Prototype::createStructure(vm, globalObject, globalObject->iteratorPrototype())); + } + + JSC::JSValue next(JSC::ExecState&); + +private: + JSDOMIterator(JSC::Structure* structure, JSWrapper& iteratedObject, IterationKind kind) + : Base(structure, *iteratedObject.globalObject()) + , m_iterator(iteratedObject.wrapped().createIterator()) + , m_kind(kind) + { + } + + template<typename IteratorValue, typename T = Traits> EnableIfMap<T, JSC::JSValue> asJS(JSC::ExecState&, IteratorValue&); + template<typename IteratorValue, typename T = Traits> EnableIfSet<T, JSC::JSValue> asJS(JSC::ExecState&, IteratorValue&); + + static void destroy(JSC::JSCell*); + + std::optional<typename DOMWrapped::Iterator> m_iterator; + IterationKind m_kind; +}; + +inline JSC::JSValue jsPair(JSC::ExecState& state, JSDOMGlobalObject& globalObject, JSC::JSValue value1, JSC::JSValue value2) +{ + JSC::MarkedArgumentBuffer arguments; + arguments.append(value1); + arguments.append(value2); + return constructArray(&state, nullptr, &globalObject, arguments); +} + +template<typename FirstType, typename SecondType, typename T, typename U> +inline JSC::JSValue jsPair(JSC::ExecState& state, JSDOMGlobalObject& globalObject, const T& value1, const U& value2) +{ + return jsPair(state, globalObject, toJS<FirstType>(state, globalObject, value1), toJS<SecondType>(state, globalObject, value2)); +} + +template<typename JSIterator> JSC::JSValue iteratorCreate(typename JSIterator::Wrapper&, IterationKind); +template<typename JSIterator> JSC::JSValue iteratorForEach(JSC::ExecState&, typename JSIterator::Wrapper&, JSC::ThrowScope&); + +template<typename JSIterator> JSC::JSValue iteratorCreate(typename JSIterator::Wrapper& thisObject, IterationKind kind) +{ + ASSERT(thisObject.globalObject()); + JSDOMGlobalObject& globalObject = *thisObject.globalObject(); + return JSIterator::create(globalObject.vm(), getDOMStructure<JSIterator>(globalObject.vm(), globalObject), thisObject, kind); +} + +template<typename JSWrapper, typename IteratorTraits> +template<typename IteratorValue, typename T> inline EnableIfMap<T, JSC::JSValue> JSDOMIterator<JSWrapper, IteratorTraits>::asJS(JSC::ExecState& state, IteratorValue& value) +{ + ASSERT(value); + + switch (m_kind) { + case IterationKind::Key: + return toJS<typename Traits::KeyType>(state, *globalObject(), value->key); + case IterationKind::Value: + return toJS<typename Traits::ValueType>(state, *globalObject(), value->value); + case IterationKind::KeyValue: + return jsPair<typename Traits::KeyType, typename Traits::ValueType>(state, *globalObject(), value->key, value->value); + }; + + ASSERT_NOT_REACHED(); + return { }; +} + +template<typename JSWrapper, typename IteratorTraits> +template<typename IteratorValue, typename T> inline EnableIfSet<T, JSC::JSValue> JSDOMIterator<JSWrapper, IteratorTraits>::asJS(JSC::ExecState& state, IteratorValue& value) +{ + ASSERT(value); + + auto globalObject = this->globalObject(); + auto result = toJS<typename Traits::ValueType>(state, *globalObject, value); + + switch (m_kind) { + case IterationKind::Key: + case IterationKind::Value: + return result; + case IterationKind::KeyValue: + return jsPair(state, *globalObject, result, result); + }; + + ASSERT_NOT_REACHED(); + return { }; +} + +template<typename JSIterator, typename IteratorValue> EnableIfMap<typename JSIterator::Traits> appendForEachArguments(JSC::ExecState& state, JSDOMGlobalObject& globalObject, JSC::MarkedArgumentBuffer& arguments, IteratorValue& value) +{ + ASSERT(value); + arguments.append(toJS<typename JSIterator::Traits::ValueType>(state, globalObject, value->value)); + arguments.append(toJS<typename JSIterator::Traits::KeyType>(state, globalObject, value->key)); +} + +template<typename JSIterator, typename IteratorValue> EnableIfSet<typename JSIterator::Traits> appendForEachArguments(JSC::ExecState& state, JSDOMGlobalObject& globalObject, JSC::MarkedArgumentBuffer& arguments, IteratorValue& value) +{ + ASSERT(value); + auto argument = toJS<typename JSIterator::Traits::ValueType>(state, globalObject, value); + arguments.append(argument); + arguments.append(argument); +} + +template<typename JSIterator> JSC::JSValue iteratorForEach(JSC::ExecState& state, typename JSIterator::Wrapper& thisObject, JSC::ThrowScope& scope) +{ + JSC::JSValue callback = state.argument(0); + JSC::JSValue thisValue = state.argument(1); + + JSC::CallData callData; + JSC::CallType callType = JSC::getCallData(callback, callData); + if (callType == JSC::CallType::None) + return throwTypeError(&state, scope, ASCIILiteral("Cannot call callback")); + + auto iterator = thisObject.wrapped().createIterator(); + while (auto value = iterator.next()) { + JSC::MarkedArgumentBuffer arguments; + appendForEachArguments<JSIterator>(state, *thisObject.globalObject(), arguments, value); + arguments.append(&thisObject); + JSC::call(&state, callback, callType, callData, thisValue, arguments); + if (UNLIKELY(scope.exception())) + break; + } + return JSC::jsUndefined(); +} + +template<typename JSWrapper, typename IteratorTraits> +void JSDOMIterator<JSWrapper, IteratorTraits>::destroy(JSCell* cell) +{ + JSDOMIterator<JSWrapper, IteratorTraits>* thisObject = static_cast<JSDOMIterator<JSWrapper, IteratorTraits>*>(cell); + thisObject->JSDOMIterator<JSWrapper, IteratorTraits>::~JSDOMIterator(); +} + +template<typename JSWrapper, typename IteratorTraits> +JSC::JSValue JSDOMIterator<JSWrapper, IteratorTraits>::next(JSC::ExecState& state) +{ + if (m_iterator) { + auto iteratorValue = m_iterator->next(); + if (iteratorValue) + return createIteratorResultObject(&state, asJS(state, iteratorValue), false); + m_iterator = std::nullopt; + } + return createIteratorResultObject(&state, JSC::jsUndefined(), true); +} + +template<typename JSWrapper, typename IteratorTraits> +JSC::EncodedJSValue JSC_HOST_CALL JSDOMIteratorPrototype<JSWrapper, IteratorTraits>::next(JSC::ExecState* state) +{ + JSC::VM& vm = state->vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + + auto iterator = jsDynamicDowncast<JSDOMIterator<JSWrapper, IteratorTraits>*>(vm, state->thisValue()); + if (!iterator) + return JSC::JSValue::encode(throwTypeError(state, scope, ASCIILiteral("Cannot call next() on a non-Iterator object"))); + + return JSC::JSValue::encode(iterator->next(*state)); +} + +template<typename JSWrapper, typename IteratorTraits> +void JSDOMIteratorPrototype<JSWrapper, IteratorTraits>::finishCreation(JSC::VM& vm, JSC::JSGlobalObject* globalObject) +{ + Base::finishCreation(vm); + ASSERT(inherits(vm, info())); + + JSC_NATIVE_INTRINSIC_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->next, next, 0, 0, JSC::NoIntrinsic); +} + +} diff --git a/Source/WebCore/bindings/js/JSDOMMimeTypeArrayCustom.cpp b/Source/WebCore/bindings/js/JSDOMMimeTypeArrayCustom.cpp deleted file mode 100644 index e1c910590..000000000 --- a/Source/WebCore/bindings/js/JSDOMMimeTypeArrayCustom.cpp +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies) - * Copyright (C) 2008 Apple Inc. All rights reserved. - * - * 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 - */ - -#include "config.h" -#include "JSDOMMimeTypeArray.h" - -#include "DOMMimeTypeArray.h" -#include "JSDOMMimeType.h" -#include <wtf/text/AtomicString.h> - -namespace WebCore { - -using namespace JSC; - -bool JSDOMMimeTypeArray::canGetItemsForName(ExecState*, DOMMimeTypeArray* mimeTypeArray, PropertyName propertyName) -{ - return mimeTypeArray->canGetItemsForName(propertyNameToAtomicString(propertyName)); -} - -EncodedJSValue JSDOMMimeTypeArray::nameGetter(ExecState* exec, EncodedJSValue slotBase, EncodedJSValue, PropertyName propertyName) -{ - JSDOMMimeTypeArray* thisObj = jsDynamicCast<JSDOMMimeTypeArray*>(JSValue::decode(slotBase)); - if (!thisObj) - return throwVMTypeError(exec); - return JSValue::encode(toJS(exec, thisObj->globalObject(), thisObj->impl().namedItem(propertyNameToAtomicString(propertyName)))); -} - -} // namespace WebCore diff --git a/Source/WebCore/bindings/js/JSDOMNamedConstructor.h b/Source/WebCore/bindings/js/JSDOMNamedConstructor.h new file mode 100644 index 000000000..265e6d3e3 --- /dev/null +++ b/Source/WebCore/bindings/js/JSDOMNamedConstructor.h @@ -0,0 +1,79 @@ +/* + * Copyright (C) 2015, 2016 Canon Inc. All rights reserved. + * Copyright (C) 2016 Apple Inc. All rights reserved. + * + * 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 + */ + +#pragma once + +#include "JSDOMConstructorWithDocument.h" + +namespace WebCore { + +// FIMXE: Why can't named constructors be used with workers? +template<typename JSClass> class JSDOMNamedConstructor : public JSDOMConstructorWithDocument { +public: + using Base = JSDOMConstructorWithDocument; + + static JSDOMNamedConstructor* create(JSC::VM&, JSC::Structure*, JSDOMGlobalObject&); + static JSC::Structure* createStructure(JSC::VM&, JSC::JSGlobalObject&, JSC::JSValue prototype); + + DECLARE_INFO; + + // Must be defined for each specialization class. + static JSC::JSValue prototypeForStructure(JSC::VM&, const JSDOMGlobalObject&); + +private: + JSDOMNamedConstructor(JSC::Structure* structure, JSDOMGlobalObject& globalObject) + : Base(structure, globalObject) + { + } + + void finishCreation(JSC::VM&, JSDOMGlobalObject&); + static JSC::ConstructType getConstructData(JSC::JSCell*, JSC::ConstructData&); + + // Usually defined for each specialization class. + void initializeProperties(JSC::VM&, JSDOMGlobalObject&) { } + // Must be defined for each specialization class. + static JSC::EncodedJSValue JSC_HOST_CALL construct(JSC::ExecState*); +}; + +template<typename JSClass> inline JSDOMNamedConstructor<JSClass>* JSDOMNamedConstructor<JSClass>::create(JSC::VM& vm, JSC::Structure* structure, JSDOMGlobalObject& globalObject) +{ + JSDOMNamedConstructor* constructor = new (NotNull, JSC::allocateCell<JSDOMNamedConstructor>(vm.heap)) JSDOMNamedConstructor(structure, globalObject); + constructor->finishCreation(vm, globalObject); + return constructor; +} + +template<typename JSClass> inline JSC::Structure* JSDOMNamedConstructor<JSClass>::createStructure(JSC::VM& vm, JSC::JSGlobalObject& globalObject, JSC::JSValue prototype) +{ + return JSC::Structure::create(vm, &globalObject, prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), info()); +} + +template<typename JSClass> inline void JSDOMNamedConstructor<JSClass>::finishCreation(JSC::VM& vm, JSDOMGlobalObject& globalObject) +{ + Base::finishCreation(globalObject); + ASSERT(inherits(vm, info())); + initializeProperties(vm, globalObject); +} + +template<typename JSClass> inline JSC::ConstructType JSDOMNamedConstructor<JSClass>::getConstructData(JSC::JSCell*, JSC::ConstructData& constructData) +{ + constructData.native.function = construct; + return JSC::ConstructType::Host; +} + +} // namespace WebCore diff --git a/Source/WebCore/bindings/js/JSDOMPluginArrayCustom.cpp b/Source/WebCore/bindings/js/JSDOMPluginArrayCustom.cpp deleted file mode 100644 index 807f63afe..000000000 --- a/Source/WebCore/bindings/js/JSDOMPluginArrayCustom.cpp +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies) - * Copyright (C) 2008 Apple Inc. All rights reserved. - * - * 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 - */ - -#include "config.h" -#include "JSDOMPluginArray.h" - -#include "DOMPluginArray.h" -#include "JSDOMPlugin.h" -#include <wtf/text/AtomicString.h> - -namespace WebCore { - -using namespace JSC; - -bool JSDOMPluginArray::canGetItemsForName(ExecState*, DOMPluginArray* pluginArray, PropertyName propertyName) -{ - return pluginArray->canGetItemsForName(propertyNameToAtomicString(propertyName)); -} - -EncodedJSValue JSDOMPluginArray::nameGetter(ExecState* exec, EncodedJSValue slotBase, EncodedJSValue, PropertyName propertyName) -{ - JSDOMPluginArray* thisObj = jsCast<JSDOMPluginArray*>(JSValue::decode(slotBase)); - return JSValue::encode(toJS(exec, thisObj->globalObject(), thisObj->impl().namedItem(propertyNameToAtomicString(propertyName)))); -} - -} // namespace WebCore diff --git a/Source/WebCore/bindings/js/JSDOMPromise.cpp b/Source/WebCore/bindings/js/JSDOMPromise.cpp index fa5aa95b9..188d20fef 100644 --- a/Source/WebCore/bindings/js/JSDOMPromise.cpp +++ b/Source/WebCore/bindings/js/JSDOMPromise.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2013 Apple Inc. All rights reserved. + * Copyright (C) 2013, 2016 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -26,47 +26,200 @@ #include "config.h" #include "JSDOMPromise.h" +#include "ExceptionCode.h" +#include "JSDOMError.h" +#include "JSDOMWindow.h" +#include <builtins/BuiltinNames.h> +#include <runtime/Exception.h> +#include <runtime/JSONObject.h> +#include <runtime/JSPromiseConstructor.h> + using namespace JSC; namespace WebCore { -DeferredWrapper::DeferredWrapper(ExecState* exec, JSDOMGlobalObject* globalObject) - : m_globalObject(exec->vm(), globalObject) - , m_deferred(exec->vm(), JSPromiseDeferred::create(exec, globalObject)) +DeferredPromise::DeferredPromise(JSDOMGlobalObject& globalObject, JSPromiseDeferred& promiseDeferred) + : ActiveDOMCallback(globalObject.scriptExecutionContext()) + , m_deferred(&promiseDeferred) + , m_globalObject(&globalObject) +{ + auto locker = lockDuringMarking(globalObject.vm().heap, globalObject.gcLock()); + globalObject.vm().heap.writeBarrier(&globalObject, &promiseDeferred); + globalObject.deferredPromises(locker).add(this); +} + +DeferredPromise::~DeferredPromise() +{ + clear(); +} + +void DeferredPromise::clear() { + ASSERT(!m_deferred || m_globalObject); + if (m_deferred && m_globalObject) { + auto locker = lockDuringMarking(m_globalObject->vm().heap, m_globalObject->gcLock()); + m_globalObject->deferredPromises(locker).remove(this); + } + m_deferred.clear(); } -JSObject* DeferredWrapper::promise() const +void DeferredPromise::contextDestroyed() { + ActiveDOMCallback::contextDestroyed(); + clear(); +} + +JSC::JSValue DeferredPromise::promise() const +{ + ASSERT(m_deferred); return m_deferred->promise(); } -void DeferredWrapper::resolve(ExecState* exec, JSValue resolution) +void DeferredPromise::callFunction(ExecState& exec, JSValue function, JSValue resolution) { - JSValue deferredResolve = m_deferred->resolve(); + if (!canInvokeCallback()) + return; - CallData resolveCallData; - CallType resolveCallType = getCallData(deferredResolve, resolveCallData); - ASSERT(resolveCallType != CallTypeNone); + CallData callData; + CallType callType = getCallData(function, callData); + ASSERT(callType != CallType::None); MarkedArgumentBuffer arguments; arguments.append(resolution); - call(exec, deferredResolve, resolveCallType, resolveCallData, jsUndefined(), arguments); + call(&exec, function, callType, callData, jsUndefined(), arguments); + + clear(); } -void DeferredWrapper::reject(ExecState* exec, JSValue reason) +void DeferredPromise::reject() { - JSValue deferredReject = m_deferred->reject(); + if (isSuspended()) + return; - CallData rejectCallData; - CallType rejectCallType = getCallData(deferredReject, rejectCallData); - ASSERT(rejectCallType != CallTypeNone); + ASSERT(m_deferred); + ASSERT(m_globalObject); + auto& state = *m_globalObject->globalExec(); + JSC::JSLockHolder locker(&state); + reject(state, JSC::jsUndefined()); +} + +void DeferredPromise::reject(std::nullptr_t) +{ + if (isSuspended()) + return; + + ASSERT(m_deferred); + ASSERT(m_globalObject); + auto& state = *m_globalObject->globalExec(); + JSC::JSLockHolder locker(&state); + reject(state, JSC::jsNull()); +} + +void DeferredPromise::reject(Exception&& exception) +{ + if (isSuspended()) + return; + + ASSERT(m_deferred); + ASSERT(m_globalObject); + auto& state = *m_globalObject->globalExec(); + JSC::JSLockHolder locker(&state); + reject(state, createDOMException(state, WTFMove(exception))); +} + +void DeferredPromise::reject(ExceptionCode ec, const String& message) +{ + if (isSuspended()) + return; + + ASSERT(m_deferred); + ASSERT(m_globalObject); + JSC::ExecState* state = m_globalObject->globalExec(); + JSC::JSLockHolder locker(state); + reject(*state, createDOMException(state, ec, message)); +} + +void DeferredPromise::reject(const JSC::PrivateName& privateName) +{ + if (isSuspended()) + return; + + ASSERT(m_deferred); + ASSERT(m_globalObject); + JSC::ExecState* state = m_globalObject->globalExec(); + JSC::JSLockHolder locker(state); + reject(*state, JSC::Symbol::create(state->vm(), privateName.uid())); +} + +void rejectPromiseWithExceptionIfAny(JSC::ExecState& state, JSDOMGlobalObject& globalObject, JSPromiseDeferred& promiseDeferred) +{ + VM& vm = state.vm(); + auto scope = DECLARE_CATCH_SCOPE(vm); + + if (LIKELY(!scope.exception())) + return; + + JSValue error = scope.exception()->value(); + scope.clearException(); + + DeferredPromise::create(globalObject, promiseDeferred)->reject<IDLAny>(error); +} + +Ref<DeferredPromise> createDeferredPromise(JSC::ExecState& state, JSDOMWindow& domWindow) +{ + JSC::JSPromiseDeferred* deferred = JSC::JSPromiseDeferred::create(&state, &domWindow); + // deferred can only be null in workers. + ASSERT(deferred); + return DeferredPromise::create(domWindow, *deferred); +} + +JSC::EncodedJSValue createRejectedPromiseWithTypeError(JSC::ExecState& state, const String& errorMessage) +{ + ASSERT(state.lexicalGlobalObject()); + auto& globalObject = *state.lexicalGlobalObject(); + + auto promiseConstructor = globalObject.promiseConstructor(); + auto rejectFunction = promiseConstructor->get(&state, state.vm().propertyNames->builtinNames().rejectPrivateName()); + auto rejectionValue = createTypeError(&state, errorMessage); + + CallData callData; + auto callType = getCallData(rejectFunction, callData); + ASSERT(callType != CallType::None); MarkedArgumentBuffer arguments; - arguments.append(reason); + arguments.append(rejectionValue); + + return JSValue::encode(call(&state, rejectFunction, callType, callData, promiseConstructor, arguments)); +} - call(exec, deferredReject, rejectCallType, rejectCallData, jsUndefined(), arguments); +static inline JSC::JSValue parseAsJSON(JSC::ExecState* state, const String& data) +{ + JSC::JSLockHolder lock(state); + return JSC::JSONParse(state, data); +} + +void fulfillPromiseWithJSON(Ref<DeferredPromise>&& promise, const String& data) +{ + JSC::JSValue value = parseAsJSON(promise->globalObject()->globalExec(), data); + if (!value) + promise->reject(SYNTAX_ERR); + else + promise->resolve<IDLAny>(value); +} + +void fulfillPromiseWithArrayBuffer(Ref<DeferredPromise>&& promise, ArrayBuffer* arrayBuffer) +{ + if (!arrayBuffer) { + promise->reject<IDLAny>(createOutOfMemoryError(promise->globalObject()->globalExec())); + return; + } + promise->resolve<IDLInterface<ArrayBuffer>>(*arrayBuffer); +} + +void fulfillPromiseWithArrayBuffer(Ref<DeferredPromise>&& promise, const void* data, size_t length) +{ + fulfillPromiseWithArrayBuffer(WTFMove(promise), ArrayBuffer::tryCreate(data, length).get()); } } diff --git a/Source/WebCore/bindings/js/JSDOMPromise.h b/Source/WebCore/bindings/js/JSDOMPromise.h index d431c4e5d..39530cc6e 100644 --- a/Source/WebCore/bindings/js/JSDOMPromise.h +++ b/Source/WebCore/bindings/js/JSDOMPromise.h @@ -23,87 +23,245 @@ * THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef JSDOMPromise_h -#define JSDOMPromise_h +#pragma once -#include "JSCryptoKey.h" -#include "JSCryptoKeyPair.h" -#include "JSDOMBinding.h" +#include "ActiveDOMCallback.h" +#include "JSDOMConvert.h" #include <heap/StrongInlines.h> #include <runtime/JSPromiseDeferred.h> namespace WebCore { -class DeferredWrapper { +class DeferredPromise : public RefCounted<DeferredPromise>, public ActiveDOMCallback { public: - DeferredWrapper(JSC::ExecState*, JSDOMGlobalObject*); + static Ref<DeferredPromise> create(JSDOMGlobalObject& globalObject, JSC::JSPromiseDeferred& deferred) + { + return adoptRef(*new DeferredPromise(globalObject, deferred)); + } - template<class ResolveResultType> - void resolve(const ResolveResultType&); + ~DeferredPromise(); - template<class RejectResultType> - void reject(const RejectResultType&); + template<class IDLType> + void resolve(typename IDLType::ParameterType value) + { + if (isSuspended()) + return; + ASSERT(m_deferred); + ASSERT(m_globalObject); + JSC::ExecState* exec = m_globalObject->globalExec(); + JSC::JSLockHolder locker(exec); + resolve(*exec, toJS<IDLType>(*exec, *m_globalObject.get(), std::forward<typename IDLType::ParameterType>(value))); + } - JSC::JSObject* promise() const; + void resolve() + { + if (isSuspended()) + return; + ASSERT(m_deferred); + ASSERT(m_globalObject); + JSC::ExecState* exec = m_globalObject->globalExec(); + JSC::JSLockHolder locker(exec); + resolve(*exec, JSC::jsUndefined()); + } + + template<class IDLType> + void resolveWithNewlyCreated(typename IDLType::ParameterType value) + { + if (isSuspended()) + return; + ASSERT(m_deferred); + ASSERT(m_globalObject); + JSC::ExecState* exec = m_globalObject->globalExec(); + JSC::JSLockHolder locker(exec); + resolve(*exec, toJSNewlyCreated<IDLType>(*exec, *m_globalObject.get(), std::forward<typename IDLType::ParameterType>(value))); + } + + template<class IDLType> + void reject(typename IDLType::ParameterType value) + { + if (isSuspended()) + return; + ASSERT(m_deferred); + ASSERT(m_globalObject); + JSC::ExecState* exec = m_globalObject->globalExec(); + JSC::JSLockHolder locker(exec); + reject(*exec, toJS<IDLType>(*exec, *m_globalObject.get(), std::forward<typename IDLType::ParameterType>(value))); + } + + void reject(); + void reject(std::nullptr_t); + void reject(Exception&&); + void reject(ExceptionCode, const String& = { }); + void reject(const JSC::PrivateName&); + + template<typename Callback> + void resolveWithCallback(Callback callback) + { + if (isSuspended()) + return; + ASSERT(m_deferred); + ASSERT(m_globalObject); + JSC::ExecState* exec = m_globalObject->globalExec(); + JSC::JSLockHolder locker(exec); + resolve(*exec, callback(*exec, *m_globalObject.get())); + } + + template<typename Callback> + void rejectWithCallback(Callback callback) + { + if (isSuspended()) + return; + ASSERT(m_deferred); + ASSERT(m_globalObject); + JSC::ExecState* exec = m_globalObject->globalExec(); + JSC::JSLockHolder locker(exec); + reject(*exec, callback(*exec, *m_globalObject.get())); + } + + JSC::JSValue promise() const; + + bool isSuspended() { return !m_deferred || !canInvokeCallback(); } // The wrapper world has gone away or active DOM objects have been suspended. + JSDOMGlobalObject* globalObject() { return m_globalObject.get(); } + + void visitAggregate(JSC::SlotVisitor& visitor) { visitor.append(m_deferred); } private: - void resolve(JSC::ExecState*, JSC::JSValue); - void reject(JSC::ExecState*, JSC::JSValue); + DeferredPromise(JSDOMGlobalObject&, JSC::JSPromiseDeferred&); + + void clear(); + void contextDestroyed() override; - JSC::Strong<JSDOMGlobalObject> m_globalObject; - JSC::Strong<JSC::JSPromiseDeferred> m_deferred; + void callFunction(JSC::ExecState&, JSC::JSValue function, JSC::JSValue resolution); + void resolve(JSC::ExecState& state, JSC::JSValue resolution) { callFunction(state, m_deferred->resolve(), resolution); } + void reject(JSC::ExecState& state, JSC::JSValue resolution) { callFunction(state, m_deferred->reject(), resolution); } + + JSC::Weak<JSC::JSPromiseDeferred> m_deferred; + JSC::Weak<JSDOMGlobalObject> m_globalObject; }; -template<class ResolveResultType> -inline void DeferredWrapper::resolve(const ResolveResultType& result) -{ - JSC::ExecState* exec = m_globalObject->globalExec(); - resolve(exec, toJS(exec, m_globalObject.get(), result)); -} +class DOMPromiseBase { +public: + DOMPromiseBase(Ref<DeferredPromise>&& genericPromise) + : m_promiseDeferred(WTFMove(genericPromise)) + { + } -template<class RejectResultType> -inline void DeferredWrapper::reject(const RejectResultType& result) -{ - JSC::ExecState* exec = m_globalObject->globalExec(); - reject(exec, toJS(exec, m_globalObject.get(), result)); -} + DOMPromiseBase(DOMPromiseBase&& promise) + : m_promiseDeferred(WTFMove(promise.m_promiseDeferred)) + { + } -template<> -inline void DeferredWrapper::reject(const std::nullptr_t&) -{ - JSC::ExecState* exec = m_globalObject->globalExec(); - reject(exec, JSC::jsNull()); -} + DOMPromiseBase(const DOMPromiseBase& other) + : m_promiseDeferred(other.m_promiseDeferred.copyRef()) + { + } -template<> -inline void DeferredWrapper::resolve<String>(const String& result) -{ - JSC::ExecState* exec = m_globalObject->globalExec(); - resolve(exec, jsString(exec, result)); -} + DOMPromiseBase& operator=(const DOMPromiseBase& other) + { + m_promiseDeferred = other.m_promiseDeferred.copyRef(); + return *this; + } -template<> -inline void DeferredWrapper::resolve<bool>(const bool& result) -{ - JSC::ExecState* exec = m_globalObject->globalExec(); - resolve(exec, JSC::jsBoolean(result)); -} + DOMPromiseBase& operator=(DOMPromiseBase&& other) + { + m_promiseDeferred = WTFMove(other.m_promiseDeferred); + return *this; + } + + void reject() + { + m_promiseDeferred->reject(); + } + + template<typename... ErrorType> + void reject(ErrorType&&... error) + { + m_promiseDeferred->reject(std::forward<ErrorType>(error)...); + } -template<> -inline void DeferredWrapper::resolve<Vector<unsigned char>>(const Vector<unsigned char>& result) + template<typename IDLType> + void rejectType(typename IDLType::ParameterType value) + { + m_promiseDeferred->reject<IDLType>(std::forward<typename IDLType::ParameterType>(value)); + } + + JSC::JSValue promise() const { return m_promiseDeferred->promise(); }; + +protected: + Ref<DeferredPromise> m_promiseDeferred; +}; + +template<typename IDLType> +class DOMPromise : public DOMPromiseBase { +public: + using DOMPromiseBase::DOMPromiseBase; + using DOMPromiseBase::operator=; + using DOMPromiseBase::promise; + using DOMPromiseBase::reject; + + void resolve(typename IDLType::ParameterType value) + { + m_promiseDeferred->resolve<IDLType>(std::forward<typename IDLType::ParameterType>(value)); + } +}; + +template<> class DOMPromise<void> : public DOMPromiseBase { +public: + using DOMPromiseBase::DOMPromiseBase; + using DOMPromiseBase::operator=; + using DOMPromiseBase::promise; + using DOMPromiseBase::reject; + + void resolve() + { + m_promiseDeferred->resolve(); + } +}; + + +Ref<DeferredPromise> createDeferredPromise(JSC::ExecState&, JSDOMWindow&); + +void fulfillPromiseWithJSON(Ref<DeferredPromise>&&, const String&); +void fulfillPromiseWithArrayBuffer(Ref<DeferredPromise>&&, ArrayBuffer*); +void fulfillPromiseWithArrayBuffer(Ref<DeferredPromise>&&, const void*, size_t); +void rejectPromiseWithExceptionIfAny(JSC::ExecState&, JSDOMGlobalObject&, JSC::JSPromiseDeferred&); +JSC::EncodedJSValue createRejectedPromiseWithTypeError(JSC::ExecState&, const String&); + +using PromiseFunction = void(JSC::ExecState&, Ref<DeferredPromise>&&); + +enum class PromiseExecutionScope { WindowOnly, WindowOrWorker }; + +template<PromiseFunction promiseFunction, PromiseExecutionScope executionScope> +inline JSC::JSValue callPromiseFunction(JSC::ExecState& state) { - JSC::ExecState* exec = m_globalObject->globalExec(); - RefPtr<ArrayBuffer> buffer = ArrayBuffer::create(result.data(), result.size()); - resolve(exec, toJS(exec, m_globalObject.get(), buffer.get())); + JSC::VM& vm = state.vm(); + auto scope = DECLARE_CATCH_SCOPE(vm); + + JSDOMGlobalObject& globalObject = *JSC::jsCast<JSDOMGlobalObject*>(state.lexicalGlobalObject()); + JSC::JSPromiseDeferred* promiseDeferred = JSC::JSPromiseDeferred::create(&state, &globalObject); + + // promiseDeferred can be null when terminating a Worker abruptly. + if (executionScope == PromiseExecutionScope::WindowOrWorker && !promiseDeferred) + return JSC::jsUndefined(); + + promiseFunction(state, DeferredPromise::create(globalObject, *promiseDeferred)); + + rejectPromiseWithExceptionIfAny(state, globalObject, *promiseDeferred); + ASSERT_UNUSED(scope, !scope.exception()); + return promiseDeferred->promise(); } -template<> -inline void DeferredWrapper::reject<String>(const String& result) +using BindingPromiseFunction = JSC::EncodedJSValue(JSC::ExecState*, Ref<DeferredPromise>&&); +template<BindingPromiseFunction bindingFunction> +inline void bindingPromiseFunctionAdapter(JSC::ExecState& state, Ref<DeferredPromise>&& promise) { - JSC::ExecState* exec = m_globalObject->globalExec(); - reject(exec, jsString(exec, result)); + bindingFunction(&state, WTFMove(promise)); } +template<BindingPromiseFunction bindingPromiseFunction, PromiseExecutionScope executionScope> +inline JSC::JSValue callPromiseFunction(JSC::ExecState& state) +{ + return callPromiseFunction<bindingPromiseFunctionAdapter<bindingPromiseFunction>, executionScope>(state); } -#endif // JSDOMPromise_h +} // namespace WebCore diff --git a/Source/WebCore/bindings/js/JSDOMStringListCustom.cpp b/Source/WebCore/bindings/js/JSDOMStringListCustom.cpp deleted file mode 100644 index b73378d37..000000000 --- a/Source/WebCore/bindings/js/JSDOMStringListCustom.cpp +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (C) 2012 Research In Motion Inc. All rights reserved. - * - * 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 - */ - -#include "config.h" -#include "JSDOMStringList.h" - -using namespace JSC; - -namespace WebCore { - -PassRefPtr<DOMStringList> toDOMStringList(ExecState* exec, JSValue value) -{ - if (value.inherits(JSDOMStringList::info())) - return &jsCast<JSDOMStringList*>(asObject(value))->impl(); - - if (!isJSArray(value)) - return 0; - - JSArray* array = asArray(value); - RefPtr<DOMStringList> stringList = DOMStringList::create(); - for (unsigned i = 0; i < array->length(); ++i) - stringList->append(array->getIndex(exec, i).toString(exec)->value(exec)); - - return stringList.release(); -} - -} // namespace WebCore diff --git a/Source/WebCore/bindings/js/JSDOMStringMapCustom.cpp b/Source/WebCore/bindings/js/JSDOMStringMapCustom.cpp index 6ff6b9c05..b3cc70d73 100644 --- a/Source/WebCore/bindings/js/JSDOMStringMapCustom.cpp +++ b/Source/WebCore/bindings/js/JSDOMStringMapCustom.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010 Apple Inc. All rights reserved. + * Copyright (C) 2010, 2014 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -26,64 +26,51 @@ #include "config.h" #include "JSDOMStringMap.h" +#include "CustomElementReactionQueue.h" #include "DOMStringMap.h" -#include "Element.h" +#include "JSDOMConvert.h" #include "JSNode.h" +#include <runtime/IdentifierInlines.h> #include <wtf/text/AtomicString.h> using namespace JSC; namespace WebCore { -bool JSDOMStringMap::canGetItemsForName(ExecState*, DOMStringMap* impl, PropertyName propertyName) +bool JSDOMStringMap::deleteProperty(JSCell* cell, ExecState* state, PropertyName propertyName) { - return impl->contains(propertyNameToAtomicString(propertyName)); + CustomElementReactionStack customElementReactionStack; + if (propertyName.isSymbol()) + return Base::deleteProperty(cell, state, propertyName); + return jsCast<JSDOMStringMap*>(cell)->wrapped().deleteItem(propertyNameToString(propertyName)); } -EncodedJSValue JSDOMStringMap::nameGetter(ExecState* exec, EncodedJSValue slotBase, EncodedJSValue, PropertyName propertyName) +bool JSDOMStringMap::deletePropertyByIndex(JSCell* cell, ExecState* state, unsigned index) { - JSDOMStringMap* thisObj = jsCast<JSDOMStringMap*>(JSValue::decode(slotBase)); - return JSValue::encode(jsStringWithCache(exec, thisObj->impl().item(propertyNameToAtomicString(propertyName)))); + return deleteProperty(cell, state, Identifier::from(state, index)); } -void JSDOMStringMap::getOwnPropertyNames(JSObject* object, ExecState* exec, PropertyNameArray& propertyNames, EnumerationMode mode) +bool JSDOMStringMap::putDelegate(ExecState* state, PropertyName propertyName, JSValue value, PutPropertySlot&, bool& putResult) { - JSDOMStringMap* thisObject = jsCast<JSDOMStringMap*>(object); - Vector<String> names; - thisObject->m_impl->getNames(names); - size_t length = names.size(); - for (size_t i = 0; i < length; ++i) - propertyNames.add(Identifier(exec, names[i])); + VM& vm = state->vm(); + auto scope = DECLARE_THROW_SCOPE(vm); - Base::getOwnPropertyNames(thisObject, exec, propertyNames, mode); -} - -bool JSDOMStringMap::deleteProperty(JSCell* cell, ExecState* exec, PropertyName propertyName) -{ - JSDOMStringMap* thisObject = jsCast<JSDOMStringMap*>(cell); - AtomicString stringName = propertyNameToAtomicString(propertyName); - if (!thisObject->m_impl->contains(stringName)) + if (propertyName.isSymbol()) return false; - ExceptionCode ec = 0; - thisObject->m_impl->deleteItem(stringName, ec); - setDOMException(exec, ec); - return !ec; -} -bool JSDOMStringMap::deletePropertyByIndex(JSCell* cell, ExecState* exec, unsigned index) -{ - return deleteProperty(cell, exec, Identifier::from(exec, index)); -} + CustomElementReactionStack customElementReactionStack; -bool JSDOMStringMap::putDelegate(ExecState* exec, PropertyName propertyName, JSValue value, PutPropertySlot&) -{ - String stringValue = value.toString(exec)->value(exec); - if (exec->hadException()) - return false; - ExceptionCode ec = 0; - impl().setItem(propertyNameToString(propertyName), stringValue, ec); - setDOMException(exec, ec); - return !ec; + String stringValue = value.toWTFString(state); + RETURN_IF_EXCEPTION(scope, true); + + auto result = wrapped().setItem(propertyNameToString(propertyName), WTFMove(stringValue)); + if (result.hasException()) { + propagateException(*state, scope, result.releaseException()); + return true; + } + + putResult = true; + return true; } } // namespace WebCore diff --git a/Source/WebCore/bindings/js/JSDOMWindowBase.cpp b/Source/WebCore/bindings/js/JSDOMWindowBase.cpp index c6739780b..45df5a8e0 100644 --- a/Source/WebCore/bindings/js/JSDOMWindowBase.cpp +++ b/Source/WebCore/bindings/js/JSDOMWindowBase.cpp @@ -1,8 +1,9 @@ /* * Copyright (C) 2000 Harri Porten (porten@kde.org) * Copyright (C) 2006 Jon Shier (jshier@iastate.edu) - * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reseved. + * Copyright (C) 2003-2009, 2014, 2016 Apple Inc. All rights reseved. * Copyright (C) 2006 Alexey Proskuryakov (ap@webkit.org) + * Copyright (c) 2015 Canon Inc. All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -23,45 +24,60 @@ #include "config.h" #include "JSDOMWindowBase.h" +#include "ActiveDOMCallbackMicrotask.h" #include "Chrome.h" -#include "Console.h" +#include "CommonVM.h" #include "DOMWindow.h" #include "Frame.h" #include "InspectorController.h" +#include "JSDOMBindingSecurity.h" #include "JSDOMGlobalObjectTask.h" #include "JSDOMWindowCustom.h" +#include "JSMainThreadExecState.h" #include "JSNode.h" +#include "Language.h" #include "Logging.h" #include "Page.h" +#include "RuntimeApplicationChecks.h" #include "ScriptController.h" +#include "ScriptModuleLoader.h" #include "SecurityOrigin.h" #include "Settings.h" #include "WebCoreJSClientData.h" +#include <bytecode/CodeBlock.h> +#include <heap/StrongInlines.h> +#include <runtime/JSInternalPromiseDeferred.h> #include <runtime/Microtask.h> #include <wtf/MainThread.h> #if PLATFORM(IOS) #include "ChromeClient.h" -#include "WebSafeGCActivityCallbackIOS.h" -#include "WebSafeIncrementalSweeperIOS.h" #endif using namespace JSC; namespace WebCore { -static bool shouldAllowAccessFrom(const JSGlobalObject* thisObject, ExecState* exec) -{ - return BindingSecurity::shouldAllowAccessToDOMWindow(exec, asJSDOMWindow(thisObject)->impl()); -} - -const ClassInfo JSDOMWindowBase::s_info = { "Window", &JSDOMGlobalObject::s_info, 0, 0, CREATE_METHOD_TABLE(JSDOMWindowBase) }; - -const GlobalObjectMethodTable JSDOMWindowBase::s_globalObjectMethodTable = { &shouldAllowAccessFrom, &supportsProfiling, &supportsRichSourceInfo, &shouldInterruptScript, &javaScriptExperimentsEnabled, &queueTaskToEventLoop, &shouldInterruptScriptBeforeTimeout }; - -JSDOMWindowBase::JSDOMWindowBase(VM& vm, Structure* structure, PassRefPtr<DOMWindow> window, JSDOMWindowShell* shell) - : JSDOMGlobalObject(vm, structure, &shell->world(), &s_globalObjectMethodTable) - , m_impl(window) +const ClassInfo JSDOMWindowBase::s_info = { "Window", &JSDOMGlobalObject::s_info, 0, CREATE_METHOD_TABLE(JSDOMWindowBase) }; + +const GlobalObjectMethodTable JSDOMWindowBase::s_globalObjectMethodTable = { + &supportsRichSourceInfo, + &shouldInterruptScript, + &javaScriptRuntimeFlags, + &queueTaskToEventLoop, + &shouldInterruptScriptBeforeTimeout, + &moduleLoaderImportModule, + &moduleLoaderResolve, + &moduleLoaderFetch, + nullptr, + &moduleLoaderEvaluate, + &defaultLanguage +}; + +JSDOMWindowBase::JSDOMWindowBase(VM& vm, Structure* structure, RefPtr<DOMWindow>&& window, JSDOMWindowShell* shell) + : JSDOMGlobalObject(vm, structure, shell->world(), &s_globalObjectMethodTable) + , m_windowCloseWatchpoints((window && window->frame()) ? IsWatched : IsInvalidated) + , m_wrapped(WTFMove(window)) , m_shell(shell) { } @@ -69,14 +85,24 @@ JSDOMWindowBase::JSDOMWindowBase(VM& vm, Structure* structure, PassRefPtr<DOMWin void JSDOMWindowBase::finishCreation(VM& vm, JSDOMWindowShell* shell) { Base::finishCreation(vm, shell); - ASSERT(inherits(info())); + ASSERT(inherits(vm, info())); GlobalPropertyInfo staticGlobals[] = { GlobalPropertyInfo(vm.propertyNames->document, jsNull(), DontDelete | ReadOnly), - GlobalPropertyInfo(vm.propertyNames->window, m_shell, DontDelete | ReadOnly) + GlobalPropertyInfo(vm.propertyNames->window, m_shell, DontDelete | ReadOnly), }; - + addStaticGlobals(staticGlobals, WTF_ARRAY_LENGTH(staticGlobals)); + + if (m_wrapped && m_wrapped->frame() && m_wrapped->frame()->settings().needsSiteSpecificQuirks()) + setNeedsSiteSpecificQuirks(true); +} + +void JSDOMWindowBase::visitChildren(JSCell* cell, SlotVisitor& visitor) +{ + JSDOMWindowBase* thisObject = jsCast<JSDOMWindowBase*>(cell); + ASSERT_GC_OBJECT_INHERITS(thisObject, info()); + Base::visitChildren(thisObject, visitor); } void JSDOMWindowBase::destroy(JSCell* cell) @@ -86,48 +112,31 @@ void JSDOMWindowBase::destroy(JSCell* cell) void JSDOMWindowBase::updateDocument() { - ASSERT(m_impl->document()); + // Since "document" property is defined as { configurable: false, writable: false, enumerable: true }, + // users cannot change its attributes further. + // Reaching here, the attributes of "document" property should be never changed. + ASSERT(m_wrapped->document()); ExecState* exec = globalExec(); - symbolTablePutWithAttributes(this, exec->vm(), exec->vm().propertyNames->document, toJS(exec, this, m_impl->document()), DontDelete | ReadOnly); + bool shouldThrowReadOnlyError = false; + bool ignoreReadOnlyErrors = true; + bool putResult = false; + symbolTablePutTouchWatchpointSet(this, exec, exec->vm().propertyNames->document, toJS(exec, this, m_wrapped->document()), shouldThrowReadOnlyError, ignoreReadOnlyErrors, putResult); } ScriptExecutionContext* JSDOMWindowBase::scriptExecutionContext() const { - return m_impl->document(); + return m_wrapped->document(); } void JSDOMWindowBase::printErrorMessage(const String& message) const { - printErrorMessageForFrame(impl().frame(), message); -} - -bool JSDOMWindowBase::supportsProfiling(const JSGlobalObject* object) -{ -#if !ENABLE(INSPECTOR) - UNUSED_PARAM(object); - return false; -#else - const JSDOMWindowBase* thisObject = static_cast<const JSDOMWindowBase*>(object); - Frame* frame = thisObject->impl().frame(); - if (!frame) - return false; - - Page* page = frame->page(); - if (!page) - return false; - - return page->inspectorController().profilerEnabled(); -#endif // ENABLE(INSPECTOR) + printErrorMessageForFrame(wrapped().frame(), message); } bool JSDOMWindowBase::supportsRichSourceInfo(const JSGlobalObject* object) { -#if !ENABLE(INSPECTOR) - UNUSED_PARAM(object); - return false; -#else const JSDOMWindowBase* thisObject = static_cast<const JSDOMWindowBase*>(object); - Frame* frame = thisObject->impl().frame(); + Frame* frame = thisObject->wrapped().frame(); if (!frame) return false; @@ -137,9 +146,7 @@ bool JSDOMWindowBase::supportsRichSourceInfo(const JSGlobalObject* object) bool enabled = page->inspectorController().enabled(); ASSERT(enabled || !thisObject->debugger()); - ASSERT(enabled || !supportsProfiling(thisObject)); return enabled; -#endif } static inline bool shouldInterruptScriptToPreventInfiniteRecursionWhenClosingPage(Page* page) @@ -157,16 +164,16 @@ static inline bool shouldInterruptScriptToPreventInfiniteRecursionWhenClosingPag bool JSDOMWindowBase::shouldInterruptScript(const JSGlobalObject* object) { const JSDOMWindowBase* thisObject = static_cast<const JSDOMWindowBase*>(object); - ASSERT(thisObject->impl().frame()); - Page* page = thisObject->impl().frame()->page(); - return shouldInterruptScriptToPreventInfiniteRecursionWhenClosingPage(page) || page->chrome().shouldInterruptJavaScript(); + ASSERT(thisObject->wrapped().frame()); + Page* page = thisObject->wrapped().frame()->page(); + return shouldInterruptScriptToPreventInfiniteRecursionWhenClosingPage(page); } bool JSDOMWindowBase::shouldInterruptScriptBeforeTimeout(const JSGlobalObject* object) { const JSDOMWindowBase* thisObject = static_cast<const JSDOMWindowBase*>(object); - ASSERT(thisObject->impl().frame()); - Page* page = thisObject->impl().frame()->page(); + ASSERT(thisObject->wrapped().frame()); + Page* page = thisObject->wrapped().frame()->page(); if (shouldInterruptScriptToPreventInfiniteRecursionWhenClosingPage(page)) return true; @@ -179,85 +186,79 @@ bool JSDOMWindowBase::shouldInterruptScriptBeforeTimeout(const JSGlobalObject* o return JSGlobalObject::shouldInterruptScriptBeforeTimeout(object); } -bool JSDOMWindowBase::javaScriptExperimentsEnabled(const JSGlobalObject* object) +RuntimeFlags JSDOMWindowBase::javaScriptRuntimeFlags(const JSGlobalObject* object) { const JSDOMWindowBase* thisObject = static_cast<const JSDOMWindowBase*>(object); - Frame* frame = thisObject->impl().frame(); + Frame* frame = thisObject->wrapped().frame(); if (!frame) - return false; - return frame->settings().javaScriptExperimentsEnabled(); + return RuntimeFlags(); + return frame->settings().javaScriptRuntimeFlags(); } -void JSDOMWindowBase::queueTaskToEventLoop(const JSGlobalObject* object, PassRefPtr<Microtask> task) -{ - const JSDOMWindowBase* thisObject = static_cast<const JSDOMWindowBase*>(object); - thisObject->scriptExecutionContext()->postTask(JSGlobalObjectTask::create((JSDOMWindowBase*)thisObject, task)); -} +class JSDOMWindowMicrotaskCallback : public RefCounted<JSDOMWindowMicrotaskCallback> { +public: + static Ref<JSDOMWindowMicrotaskCallback> create(JSDOMWindowBase* globalObject, Ref<JSC::Microtask>&& task) + { + return adoptRef(*new JSDOMWindowMicrotaskCallback(globalObject, WTFMove(task))); + } -void JSDOMWindowBase::willRemoveFromWindowShell() -{ - setCurrentEvent(0); -} + void call() + { + Ref<JSDOMWindowMicrotaskCallback> protectedThis(*this); + VM& vm = m_globalObject->vm(); + JSLockHolder lock(vm); + auto scope = DECLARE_THROW_SCOPE(vm); -JSDOMWindowShell* JSDOMWindowBase::shell() const -{ - return m_shell; -} + ExecState* exec = m_globalObject->globalExec(); -VM* JSDOMWindowBase::commonVM() -{ - ASSERT(isMainThread()); + JSMainThreadExecState::runTask(exec, m_task); -#if !PLATFORM(IOS) - static VM* vm = 0; -#else - VM*& vm = commonVMInternal(); -#endif - if (!vm) { - ScriptController::initializeThreading(); - vm = VM::createLeaked(LargeHeap).leakRef(); -#if PLATFORM(IOS) - PassOwnPtr<WebSafeGCActivityCallback> activityCallback = WebSafeGCActivityCallback::create(&vm->heap); - vm->heap.setActivityCallback(activityCallback); - PassOwnPtr<WebSafeIncrementalSweeper> incrementalSweeper = WebSafeIncrementalSweeper::create(&vm->heap); - vm->heap.setIncrementalSweeper(incrementalSweeper); - vm->makeUsableFromMultipleThreads(); - vm->heap.machineThreads().addCurrentThread(); -#else - vm->exclusiveThread = currentThread(); -#endif // !PLATFORM(IOS) - initNormalWorldClientData(vm); + ASSERT_UNUSED(scope, !scope.exception()); } - return vm; +private: + JSDOMWindowMicrotaskCallback(JSDOMWindowBase* globalObject, Ref<JSC::Microtask>&& task) + : m_globalObject(globalObject->vm(), globalObject) + , m_task(WTFMove(task)) + { + } + + Strong<JSDOMWindowBase> m_globalObject; + Ref<JSC::Microtask> m_task; +}; + +void JSDOMWindowBase::queueTaskToEventLoop(const JSGlobalObject* object, Ref<JSC::Microtask>&& task) +{ + const JSDOMWindowBase* thisObject = static_cast<const JSDOMWindowBase*>(object); + + RefPtr<JSDOMWindowMicrotaskCallback> callback = JSDOMWindowMicrotaskCallback::create((JSDOMWindowBase*)thisObject, WTFMove(task)); + auto microtask = std::make_unique<ActiveDOMCallbackMicrotask>(MicrotaskQueue::mainThreadQueue(), *thisObject->scriptExecutionContext(), [callback]() mutable { + callback->call(); + }); + + MicrotaskQueue::mainThreadQueue().append(WTFMove(microtask)); } -#if PLATFORM(IOS) -bool JSDOMWindowBase::commonVMExists() +void JSDOMWindowBase::willRemoveFromWindowShell() { - return commonVMInternal(); + setCurrentEvent(0); } -VM*& JSDOMWindowBase::commonVMInternal() +JSDOMWindowShell* JSDOMWindowBase::shell() const { - ASSERT(isMainThread()); - static VM* commonVM; - return commonVM; + return m_shell; } -#endif // JSDOMGlobalObject* is ignored, accessing a window in any context will // use that DOMWindow's prototype chain. -JSValue toJS(ExecState* exec, JSDOMGlobalObject*, DOMWindow* domWindow) +JSValue toJS(ExecState* exec, JSDOMGlobalObject*, DOMWindow& domWindow) { return toJS(exec, domWindow); } -JSValue toJS(ExecState* exec, DOMWindow* domWindow) +JSValue toJS(ExecState* exec, DOMWindow& domWindow) { - if (!domWindow) - return jsNull(); - Frame* frame = domWindow->frame(); + Frame* frame = domWindow.frame(); if (!frame) return jsNull(); return frame->script().windowShell(currentWorld(exec)); @@ -270,16 +271,124 @@ JSDOMWindow* toJSDOMWindow(Frame* frame, DOMWrapperWorld& world) return frame->script().windowShell(world)->window(); } -JSDOMWindow* toJSDOMWindow(JSValue value) +JSDOMWindow* toJSDOMWindow(JSC::VM& vm, JSValue value) { if (!value.isObject()) return 0; - const ClassInfo* classInfo = asObject(value)->classInfo(); - if (classInfo == JSDOMWindow::info()) - return jsCast<JSDOMWindow*>(asObject(value)); - if (classInfo == JSDOMWindowShell::info()) - return jsCast<JSDOMWindowShell*>(asObject(value))->window(); + + while (!value.isNull()) { + JSObject* object = asObject(value); + const ClassInfo* classInfo = object->classInfo(vm); + if (classInfo == JSDOMWindow::info()) + return jsCast<JSDOMWindow*>(object); + if (classInfo == JSDOMWindowShell::info()) + return jsCast<JSDOMWindowShell*>(object)->window(); + value = object->getPrototypeDirect(); + } return 0; } +DOMWindow& callerDOMWindow(ExecState* exec) +{ + class GetCallerGlobalObjectFunctor { + public: + GetCallerGlobalObjectFunctor() = default; + + StackVisitor::Status operator()(StackVisitor& visitor) const + { + if (!m_hasSkippedFirstFrame) { + m_hasSkippedFirstFrame = true; + return StackVisitor::Continue; + } + + if (auto* codeBlock = visitor->codeBlock()) + m_globalObject = codeBlock->globalObject(); + else { + ASSERT(visitor->callee()); + // FIXME: Callee is not an object if the caller is Web Assembly. + // Figure out what to do here. We can probably get the global object + // from the top-most Wasm Instance. https://bugs.webkit.org/show_bug.cgi?id=165721 + if (visitor->callee()->isObject()) + m_globalObject = jsCast<JSObject*>(visitor->callee())->globalObject(); + } + return StackVisitor::Done; + } + + JSGlobalObject* globalObject() const { return m_globalObject; } + + private: + mutable bool m_hasSkippedFirstFrame { false }; + mutable JSGlobalObject* m_globalObject { nullptr }; + }; + + GetCallerGlobalObjectFunctor iter; + exec->iterate(iter); + return iter.globalObject() ? asJSDOMWindow(iter.globalObject())->wrapped() : firstDOMWindow(exec); +} + +DOMWindow& activeDOMWindow(ExecState* exec) +{ + return asJSDOMWindow(exec->lexicalGlobalObject())->wrapped(); +} + +DOMWindow& firstDOMWindow(ExecState* exec) +{ + return asJSDOMWindow(exec->vmEntryGlobalObject())->wrapped(); +} + +void JSDOMWindowBase::fireFrameClearedWatchpointsForWindow(DOMWindow* window) +{ + JSC::VM& vm = commonVM(); + JSVMClientData* clientData = static_cast<JSVMClientData*>(vm.clientData); + Vector<Ref<DOMWrapperWorld>> wrapperWorlds; + clientData->getAllWorlds(wrapperWorlds); + for (unsigned i = 0; i < wrapperWorlds.size(); ++i) { + DOMObjectWrapperMap& wrappers = wrapperWorlds[i]->m_wrappers; + auto result = wrappers.find(window); + if (result == wrappers.end()) + continue; + JSC::JSObject* wrapper = result->value.get(); + if (!wrapper) + continue; + JSDOMWindowBase* jsWindow = JSC::jsCast<JSDOMWindowBase*>(wrapper); + jsWindow->m_windowCloseWatchpoints.fireAll(vm, "Frame cleared"); + } +} + + +JSC::JSInternalPromise* JSDOMWindowBase::moduleLoaderResolve(JSC::JSGlobalObject* globalObject, JSC::ExecState* exec, JSC::JSModuleLoader* moduleLoader, JSC::JSValue moduleName, JSC::JSValue importerModuleKey, JSC::JSValue scriptFetcher) +{ + JSDOMWindowBase* thisObject = JSC::jsCast<JSDOMWindowBase*>(globalObject); + if (RefPtr<Document> document = thisObject->wrapped().document()) + return document->moduleLoader()->resolve(globalObject, exec, moduleLoader, moduleName, importerModuleKey, scriptFetcher); + JSC::JSInternalPromiseDeferred* deferred = JSC::JSInternalPromiseDeferred::create(exec, globalObject); + return deferred->reject(exec, jsUndefined()); +} + +JSC::JSInternalPromise* JSDOMWindowBase::moduleLoaderFetch(JSC::JSGlobalObject* globalObject, JSC::ExecState* exec, JSC::JSModuleLoader* moduleLoader, JSC::JSValue moduleKey, JSC::JSValue scriptFetcher) +{ + JSDOMWindowBase* thisObject = JSC::jsCast<JSDOMWindowBase*>(globalObject); + if (RefPtr<Document> document = thisObject->wrapped().document()) + return document->moduleLoader()->fetch(globalObject, exec, moduleLoader, moduleKey, scriptFetcher); + JSC::JSInternalPromiseDeferred* deferred = JSC::JSInternalPromiseDeferred::create(exec, globalObject); + return deferred->reject(exec, jsUndefined()); +} + +JSC::JSValue JSDOMWindowBase::moduleLoaderEvaluate(JSC::JSGlobalObject* globalObject, JSC::ExecState* exec, JSC::JSModuleLoader* moduleLoader, JSC::JSValue moduleKey, JSC::JSValue moduleRecord, JSC::JSValue scriptFetcher) +{ + JSDOMWindowBase* thisObject = JSC::jsCast<JSDOMWindowBase*>(globalObject); + if (RefPtr<Document> document = thisObject->wrapped().document()) + return document->moduleLoader()->evaluate(globalObject, exec, moduleLoader, moduleKey, moduleRecord, scriptFetcher); + return JSC::jsUndefined(); +} + +JSC::JSInternalPromise* JSDOMWindowBase::moduleLoaderImportModule(JSC::JSGlobalObject* globalObject, JSC::ExecState* exec, JSC::JSModuleLoader* moduleLoader, JSC::JSString* moduleName, const JSC::SourceOrigin& sourceOrigin) +{ + JSDOMWindowBase* thisObject = JSC::jsCast<JSDOMWindowBase*>(globalObject); + if (RefPtr<Document> document = thisObject->wrapped().document()) + return document->moduleLoader()->importModule(globalObject, exec, moduleLoader, moduleName, sourceOrigin); + JSC::JSInternalPromiseDeferred* deferred = JSC::JSInternalPromiseDeferred::create(exec, globalObject); + return deferred->reject(exec, jsUndefined()); +} + } // namespace WebCore diff --git a/Source/WebCore/bindings/js/JSDOMWindowBase.h b/Source/WebCore/bindings/js/JSDOMWindowBase.h index fb4c601bc..19c3da4a7 100644 --- a/Source/WebCore/bindings/js/JSDOMWindowBase.h +++ b/Source/WebCore/bindings/js/JSDOMWindowBase.h @@ -17,8 +17,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#ifndef JSDOMWindowBase_h -#define JSDOMWindowBase_h +#pragma once #include "JSDOMBinding.h" #include "JSDOMGlobalObject.h" @@ -34,10 +33,10 @@ namespace WebCore { class JSDOMWindowBasePrivate; - class JSDOMWindowBase : public JSDOMGlobalObject { + class WEBCORE_EXPORT JSDOMWindowBase : public JSDOMGlobalObject { typedef JSDOMGlobalObject Base; protected: - JSDOMWindowBase(JSC::VM&, JSC::Structure*, PassRefPtr<DOMWindow>, JSDOMWindowShell*); + JSDOMWindowBase(JSC::VM&, JSC::Structure*, RefPtr<DOMWindow>&&, JSDOMWindowShell*); void finishCreation(JSC::VM&, JSDOMWindowShell*); static void destroy(JSCell*); @@ -45,7 +44,7 @@ namespace WebCore { public: void updateDocument(); - DOMWindow& impl() const { return *m_impl; } + DOMWindow& wrapped() const { return *m_wrapped; } ScriptExecutionContext* scriptExecutionContext() const; // Called just before removing this window from the JSDOMWindowShell. @@ -60,38 +59,46 @@ namespace WebCore { static const JSC::GlobalObjectMethodTable s_globalObjectMethodTable; - static bool supportsProfiling(const JSC::JSGlobalObject*); static bool supportsRichSourceInfo(const JSC::JSGlobalObject*); static bool shouldInterruptScript(const JSC::JSGlobalObject*); static bool shouldInterruptScriptBeforeTimeout(const JSC::JSGlobalObject*); - static bool javaScriptExperimentsEnabled(const JSC::JSGlobalObject*); - static void queueTaskToEventLoop(const JSC::JSGlobalObject*, PassRefPtr<JSC::Microtask>); + static JSC::RuntimeFlags javaScriptRuntimeFlags(const JSC::JSGlobalObject*); + static void queueTaskToEventLoop(const JSC::JSGlobalObject*, Ref<JSC::Microtask>&&); void printErrorMessage(const String&) const; JSDOMWindowShell* shell() const; - static JSC::VM* commonVM(); -#if PLATFORM(IOS) - static bool commonVMExists(); - static JSC::VM*& commonVMInternal(); -#endif + static void fireFrameClearedWatchpointsForWindow(DOMWindow*); + static void visitChildren(JSC::JSCell*, JSC::SlotVisitor&); + + protected: + JSC::WatchpointSet m_windowCloseWatchpoints; private: - RefPtr<DOMWindow> m_impl; + static JSC::JSInternalPromise* moduleLoaderResolve(JSC::JSGlobalObject*, JSC::ExecState*, JSC::JSModuleLoader*, JSC::JSValue, JSC::JSValue, JSC::JSValue); + static JSC::JSInternalPromise* moduleLoaderFetch(JSC::JSGlobalObject*, JSC::ExecState*, JSC::JSModuleLoader*, JSC::JSValue, JSC::JSValue); + static JSC::JSValue moduleLoaderEvaluate(JSC::JSGlobalObject*, JSC::ExecState*, JSC::JSModuleLoader*, JSC::JSValue, JSC::JSValue, JSC::JSValue); + static JSC::JSInternalPromise* moduleLoaderImportModule(JSC::JSGlobalObject*, JSC::ExecState*, JSC::JSModuleLoader*, JSC::JSString*, const JSC::SourceOrigin&); + + RefPtr<DOMWindow> m_wrapped; JSDOMWindowShell* m_shell; }; // Returns a JSDOMWindow or jsNull() // JSDOMGlobalObject* is ignored, accessing a window in any context will // use that DOMWindow's prototype chain. - JSC::JSValue toJS(JSC::ExecState*, JSDOMGlobalObject*, DOMWindow*); - JSC::JSValue toJS(JSC::ExecState*, DOMWindow*); + WEBCORE_EXPORT JSC::JSValue toJS(JSC::ExecState*, JSDOMGlobalObject*, DOMWindow&); + inline JSC::JSValue toJS(JSC::ExecState* exec, JSDOMGlobalObject* globalObject, DOMWindow* window) { return window ? toJS(exec, globalObject, *window) : JSC::jsNull(); } + JSC::JSValue toJS(JSC::ExecState*, DOMWindow&); + inline JSC::JSValue toJS(JSC::ExecState* exec, DOMWindow* window) { return window ? toJS(exec, *window) : JSC::jsNull(); } // Returns JSDOMWindow or 0 JSDOMWindow* toJSDOMWindow(Frame*, DOMWrapperWorld&); - JSDOMWindow* toJSDOMWindow(JSC::JSValue); + WEBCORE_EXPORT JSDOMWindow* toJSDOMWindow(JSC::VM&, JSC::JSValue); -} // namespace WebCore + DOMWindow& callerDOMWindow(JSC::ExecState*); + DOMWindow& activeDOMWindow(JSC::ExecState*); + DOMWindow& firstDOMWindow(JSC::ExecState*); -#endif // JSDOMWindowBase_h +} // namespace WebCore diff --git a/Source/WebCore/bindings/js/JSDOMWindowCustom.cpp b/Source/WebCore/bindings/js/JSDOMWindowCustom.cpp index 795da5a49..c00484af5 100644 --- a/Source/WebCore/bindings/js/JSDOMWindowCustom.cpp +++ b/Source/WebCore/bindings/js/JSDOMWindowCustom.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2007, 2008, 2009, 2010 Apple Inc. All rights reserved. + * Copyright (C) 2007-2017 Apple Inc. All rights reserved. * Copyright (C) 2011 Google Inc. All rights reserved. * * This library is free software; you can redistribute it and/or @@ -21,117 +21,74 @@ #include "config.h" #include "JSDOMWindowCustom.h" +#include "DOMWindowIndexedDatabase.h" #include "Frame.h" #include "HTMLCollection.h" #include "HTMLDocument.h" +#include "HTMLFrameOwnerElement.h" +#include "JSDOMBindingSecurity.h" #include "JSEvent.h" #include "JSEventListener.h" #include "JSHTMLAudioElement.h" #include "JSHTMLCollection.h" #include "JSHTMLOptionElement.h" -#include "JSImageConstructor.h" -#include "JSMessagePortCustom.h" +#include "JSIDBFactory.h" #include "JSWorker.h" #include "Location.h" +#include "RuntimeEnabledFeatures.h" #include "ScheduledAction.h" #include "Settings.h" -#include "SharedWorkerRepository.h" +#include <runtime/JSCInlines.h> +#include <runtime/Lookup.h> -#if ENABLE(SHARED_WORKERS) -#include "JSSharedWorker.h" -#endif - -#if ENABLE(IOS_TOUCH_EVENTS) -#include "JSTouchConstructorIOS.h" -#include "JSTouchListConstructorIOS.h" -#endif - -#if ENABLE(WEB_AUDIO) -#include "JSAudioContext.h" -#endif - -#if ENABLE(WEB_SOCKETS) -#include "JSWebSocket.h" +#if ENABLE(USER_MESSAGE_HANDLERS) +#include "JSWebKitNamespace.h" #endif using namespace JSC; namespace WebCore { -void JSDOMWindow::visitChildren(JSCell* cell, SlotVisitor& visitor) -{ - JSDOMWindow* thisObject = jsCast<JSDOMWindow*>(cell); - ASSERT_GC_OBJECT_INHERITS(thisObject, info()); - COMPILE_ASSERT(StructureFlags & OverridesVisitChildren, OverridesVisitChildrenWithoutSettingFlag); - ASSERT(thisObject->structure()->typeInfo().overridesVisitChildren()); - Base::visitChildren(thisObject, visitor); - - thisObject->impl().visitJSEventListeners(visitor); - if (Frame* frame = thisObject->impl().frame()) - visitor.addOpaqueRoot(frame); -} - -template<NativeFunction nativeFunction, int length> -EncodedJSValue nonCachingStaticFunctionGetter(ExecState* exec, EncodedJSValue, EncodedJSValue, PropertyName propertyName) -{ - return JSValue::encode(JSFunction::create(exec->vm(), exec->lexicalGlobalObject(), length, propertyName.publicName(), nativeFunction)); -} +EncodedJSValue JSC_HOST_CALL jsDOMWindowInstanceFunctionShowModalDialog(ExecState*); -static EncodedJSValue childFrameGetter(ExecState* exec, EncodedJSValue slotBase, EncodedJSValue, PropertyName propertyName) +void JSDOMWindow::visitAdditionalChildren(SlotVisitor& visitor) { - return JSValue::encode(toJS(exec, jsCast<JSDOMWindow*>(JSValue::decode(slotBase))->impl().frame()->tree().scopedChild(propertyNameToAtomicString(propertyName))->document()->domWindow())); -} - -static EncodedJSValue indexGetter(ExecState* exec, EncodedJSValue slotBase, EncodedJSValue, unsigned index) -{ - return JSValue::encode(toJS(exec, jsCast<JSDOMWindow*>(JSValue::decode(slotBase))->impl().frame()->tree().scopedChild(index)->document()->domWindow())); + if (Frame* frame = wrapped().frame()) + visitor.addOpaqueRoot(frame); + + // Normally JSEventTargetCustom.cpp's JSEventTarget::visitAdditionalChildren() would call this. But + // even though DOMWindow is an EventTarget, JSDOMWindow does not subclass JSEventTarget, so we need + // to do this here. + wrapped().visitJSEventListeners(visitor); } -static EncodedJSValue namedItemGetter(ExecState* exec, EncodedJSValue slotBase, EncodedJSValue, PropertyName propertyName) +#if ENABLE(USER_MESSAGE_HANDLERS) +static EncodedJSValue jsDOMWindowWebKit(ExecState* exec, EncodedJSValue thisValue, PropertyName) { - JSDOMWindowBase* thisObj = jsCast<JSDOMWindow*>(JSValue::decode(slotBase)); - Document* document = thisObj->impl().frame()->document(); - - ASSERT(BindingSecurity::shouldAllowAccessToDOMWindow(exec, thisObj->impl())); - ASSERT(document); - ASSERT(document->isHTMLDocument()); - - AtomicStringImpl* atomicPropertyName = findAtomicString(propertyName); - if (!atomicPropertyName || !toHTMLDocument(document)->hasWindowNamedItem(*atomicPropertyName)) + VM& vm = exec->vm(); + JSDOMWindow* castedThis = toJSDOMWindow(vm, JSValue::decode(thisValue)); + if (!BindingSecurity::shouldAllowAccessToDOMWindow(exec, castedThis->wrapped())) return JSValue::encode(jsUndefined()); - - if (UNLIKELY(toHTMLDocument(document)->windowNamedItemContainsMultipleElements(*atomicPropertyName))) { - RefPtr<HTMLCollection> collection = document->windowNamedItems(atomicPropertyName); - ASSERT(collection->length() > 1); - return JSValue::encode(toJS(exec, thisObj->globalObject(), WTF::getPtr(collection))); - } - - return JSValue::encode(toJS(exec, thisObj->globalObject(), toHTMLDocument(document)->windowNamedItem(*atomicPropertyName))); + return JSValue::encode(toJS(exec, castedThis->globalObject(), castedThis->wrapped().webkitNamespace())); } +#endif -bool JSDOMWindow::getOwnPropertySlot(JSObject* object, ExecState* exec, PropertyName propertyName, PropertySlot& slot) +static bool jsDOMWindowGetOwnPropertySlotRestrictedAccess(JSDOMWindow* thisObject, Frame* frame, ExecState* exec, PropertyName propertyName, PropertySlot& slot, const String& errorMessage) { - JSDOMWindow* thisObject = jsCast<JSDOMWindow*>(object); - // When accessing a Window cross-domain, functions are always the native built-in ones, and they - // are not affected by properties changed on the Window or anything in its prototype chain. - // This is consistent with the behavior of Firefox. - - const HashEntry* entry; - - // We don't want any properties other than "close" and "closed" on a frameless window (i.e. one whose page got closed, - // or whose iframe got removed). - // FIXME: This doesn't fully match Firefox, which allows at least toString in addition to those. - if (!thisObject->impl().frame()) { - // The following code is safe for cross-domain and same domain use. - // It ignores any custom properties that might be set on the DOMWindow (including a custom prototype). - entry = s_info.propHashTable(exec)->entry(exec, propertyName); - if (entry && !(entry->attributes() & JSC::Function) && entry->propertyGetter() == jsDOMWindowClosed) { - slot.setCustom(thisObject, ReadOnly | DontDelete | DontEnum, entry->propertyGetter()); + VM& vm = exec->vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + + // We don't want any properties other than "close" and "closed" on a frameless window + // (i.e. one whose page got closed, or whose iframe got removed). + // FIXME: This handling for frameless windows duplicates similar behaviour for cross-origin + // access below; we should try to find a way to merge the two. + if (!frame) { + if (propertyName == exec->propertyNames().closed) { + slot.setCustom(thisObject, ReadOnly | DontDelete | DontEnum, jsDOMWindowClosed); return true; } - entry = JSDOMWindowPrototype::info()->propHashTable(exec)->entry(exec, propertyName); - if (entry && (entry->attributes() & JSC::Function) && entry->function() == jsDOMWindowPrototypeFunctionClose) { - slot.setCustom(thisObject, ReadOnly | DontDelete | DontEnum, nonCachingStaticFunctionGetter<jsDOMWindowPrototypeFunctionClose, 0>); + if (propertyName == exec->propertyNames().close) { + slot.setCustom(thisObject, ReadOnly | DontDelete | DontEnum, nonCachingStaticFunctionGetter<jsDOMWindowInstanceFunctionClose, 0>); return true; } @@ -141,240 +98,186 @@ bool JSDOMWindow::getOwnPropertySlot(JSObject* object, ExecState* exec, Property return true; } - // We need to check for cross-domain access here without printing the generic warning message - // because we always allow access to some function, just different ones depending whether access - // is allowed. - String errorMessage; - bool allowsAccess = shouldAllowAccessToDOMWindow(exec, thisObject->impl(), errorMessage); - - // Look for overrides before looking at any of our own properties, but ignore overrides completely - // if this is cross-domain access. - if (allowsAccess && JSGlobalObject::getOwnPropertySlot(thisObject, exec, propertyName, slot)) + // https://html.spec.whatwg.org/#crossorigingetownpropertyhelper-(-o,-p-) + if (propertyName == exec->propertyNames().toStringTagSymbol || propertyName == exec->propertyNames().hasInstanceSymbol || propertyName == exec->propertyNames().isConcatSpreadableSymbol) { + slot.setValue(thisObject, ReadOnly | DontEnum, jsUndefined()); return true; - - // We need this code here because otherwise JSDOMWindowBase will stop the search before we even get to the - // prototype due to the blanket same origin (shouldAllowAccessToDOMWindow) check at the end of getOwnPropertySlot. - // Also, it's important to get the implementation straight out of the DOMWindow prototype regardless of - // what prototype is actually set on this object. - entry = JSDOMWindowPrototype::info()->propHashTable(exec)->entry(exec, propertyName); - if (entry) { - if (entry->attributes() & JSC::Function) { - if (entry->function() == jsDOMWindowPrototypeFunctionBlur) { - if (!allowsAccess) { - slot.setCustom(thisObject, ReadOnly | DontDelete | DontEnum, nonCachingStaticFunctionGetter<jsDOMWindowPrototypeFunctionBlur, 0>); - return true; - } - } else if (entry->function() == jsDOMWindowPrototypeFunctionClose) { - if (!allowsAccess) { - slot.setCustom(thisObject, ReadOnly | DontDelete | DontEnum, nonCachingStaticFunctionGetter<jsDOMWindowPrototypeFunctionClose, 0>); - return true; - } - } else if (entry->function() == jsDOMWindowPrototypeFunctionFocus) { - if (!allowsAccess) { - slot.setCustom(thisObject, ReadOnly | DontDelete | DontEnum, nonCachingStaticFunctionGetter<jsDOMWindowPrototypeFunctionFocus, 0>); - return true; - } - } else if (entry->function() == jsDOMWindowPrototypeFunctionPostMessage) { - if (!allowsAccess) { - slot.setCustom(thisObject, ReadOnly | DontDelete | DontEnum, nonCachingStaticFunctionGetter<jsDOMWindowPrototypeFunctionPostMessage, 2>); - return true; - } - } else if (entry->function() == jsDOMWindowPrototypeFunctionShowModalDialog) { - if (!DOMWindow::canShowModalDialog(thisObject->impl().frame())) { - slot.setUndefined(); - return true; - } - } - } - } else { - // Allow access to toString() cross-domain, but always Object.prototype.toString. - if (propertyName == exec->propertyNames().toString) { - if (!allowsAccess) { - slot.setCustom(thisObject, ReadOnly | DontDelete | DontEnum, objectToStringFunctionGetter); - return true; - } - } } - entry = JSDOMWindow::info()->propHashTable(exec)->entry(exec, propertyName); - if (entry) { - slot.setCustom(thisObject, allowsAccess ? entry->attributes() : ReadOnly | DontDelete | DontEnum, entry->propertyGetter()); + // These are the functions we allow access to cross-origin (DoNotCheckSecurity in IDL). + // Always provide the original function, on a fresh uncached function object. + if (propertyName == exec->propertyNames().blur) { + slot.setCustom(thisObject, ReadOnly | DontEnum, nonCachingStaticFunctionGetter<jsDOMWindowInstanceFunctionBlur, 0>); return true; } - - // Check for child frames by name before built-in properties to - // match Mozilla. This does not match IE, but some sites end up - // naming frames things that conflict with window properties that - // are in Moz but not IE. Since we have some of these, we have to do - // it the Moz way. - if (thisObject->impl().frame()->tree().scopedChild(propertyNameToAtomicString(propertyName))) { - slot.setCustom(thisObject, ReadOnly | DontDelete | DontEnum, childFrameGetter); + if (propertyName == exec->propertyNames().close) { + slot.setCustom(thisObject, ReadOnly | DontEnum, nonCachingStaticFunctionGetter<jsDOMWindowInstanceFunctionClose, 0>); return true; } - - // Do prototype lookup early so that functions and attributes in the prototype can have - // precedence over the index and name getters. - JSValue proto = thisObject->prototype(); - if (proto.isObject()) { - if (asObject(proto)->getPropertySlot(exec, propertyName, slot)) { - if (!allowsAccess) { - thisObject->printErrorMessage(errorMessage); - slot.setUndefined(); - } - return true; - } - } - - // FIXME: Search the whole frame hierarchy somewhere around here. - // We need to test the correct priority order. - - // allow window[1] or parent[1] etc. (#56983) - unsigned i = propertyName.asIndex(); - if (i < thisObject->impl().frame()->tree().scopedChildCount()) { - ASSERT(i != PropertyName::NotAnIndex); - slot.setCustomIndex(thisObject, ReadOnly | DontDelete | DontEnum, i, indexGetter); + if (propertyName == exec->propertyNames().focus) { + slot.setCustom(thisObject, ReadOnly | DontEnum, nonCachingStaticFunctionGetter<jsDOMWindowInstanceFunctionFocus, 0>); return true; } - - if (!allowsAccess) { - thisObject->printErrorMessage(errorMessage); - slot.setUndefined(); + if (propertyName == exec->propertyNames().postMessage) { + slot.setCustom(thisObject, ReadOnly | DontEnum, nonCachingStaticFunctionGetter<jsDOMWindowInstanceFunctionPostMessage, 2>); return true; } - // Allow shortcuts like 'Image1' instead of document.images.Image1 - Document* document = thisObject->impl().frame()->document(); - if (document->isHTMLDocument()) { - AtomicStringImpl* atomicPropertyName = findAtomicString(propertyName); - if (atomicPropertyName && toHTMLDocument(document)->hasWindowNamedItem(*atomicPropertyName)) { - slot.setCustom(thisObject, ReadOnly | DontDelete | DontEnum, namedItemGetter); + // When accessing cross-origin known Window properties, we always use the original property getter, + // even if the property was removed / redefined. As of early 2016, this matches Firefox and Chrome's + // behavior. + if (auto* entry = JSDOMWindow::info()->staticPropHashTable->entry(propertyName)) { + // Only allow access to these specific properties. + if (propertyName == exec->propertyNames().location + || propertyName == exec->propertyNames().closed + || propertyName == exec->propertyNames().length + || propertyName == exec->propertyNames().self + || propertyName == exec->propertyNames().window + || propertyName == exec->propertyNames().frames + || propertyName == exec->propertyNames().opener + || propertyName == exec->propertyNames().parent + || propertyName == exec->propertyNames().top) { + bool shouldExposeSetter = propertyName == exec->propertyNames().location; + CustomGetterSetter* customGetterSetter = CustomGetterSetter::create(vm, entry->propertyGetter(), shouldExposeSetter ? entry->propertyPutter() : nullptr); + slot.setCustomGetterSetter(thisObject, DontEnum | CustomAccessor, customGetterSetter); return true; } + + // For any other entries in the static property table, deny access. (Early return also prevents + // named getter from returning frames with matching names - this seems a little questionable, see + // FIXME comment on prototype search below.) + throwSecurityError(*exec, scope, errorMessage); + slot.setUndefined(); + return false; } - return Base::getOwnPropertySlot(thisObject, exec, propertyName, slot); + // Check for child frames by name before built-in properties to match Mozilla. This does + // not match IE, but some sites end up naming frames things that conflict with window + // properties that are in Moz but not IE. Since we have some of these, we have to do it + // the Moz way. + if (auto* scopedChild = frame->tree().scopedChild(propertyNameToAtomicString(propertyName))) { + slot.setValue(thisObject, ReadOnly | DontDelete | DontEnum, toJS(exec, scopedChild->document()->domWindow())); + return true; + } + + throwSecurityError(*exec, scope, errorMessage); + slot.setUndefined(); + return false; } -bool JSDOMWindow::getOwnPropertySlotByIndex(JSObject* object, ExecState* exec, unsigned index, PropertySlot& slot) +// Property access sequence is: +// (1) indexed properties, +// (2) regular own properties, +// (3) named properties (in fact, these shouldn't be on the window, should be on the NPO). +bool JSDOMWindow::getOwnPropertySlot(JSObject* object, ExecState* state, PropertyName propertyName, PropertySlot& slot) { - JSDOMWindow* thisObject = jsCast<JSDOMWindow*>(object); - - if (!thisObject->impl().frame()) { - // FIXME: We should have a message here that explains why the property access/function call was - // not allowed. - slot.setUndefined(); - return true; - } + // (1) First, indexed properties. + // Hand off all indexed access to getOwnPropertySlotByIndex, which supports the indexed getter. + if (std::optional<unsigned> index = parseIndex(propertyName)) + return getOwnPropertySlotByIndex(object, state, index.value(), slot); - // We need to check for cross-domain access here without printing the generic warning message - // because we always allow access to some function, just different ones depending whether access - // is allowed. - String errorMessage; - bool allowsAccess = shouldAllowAccessToDOMWindow(exec, thisObject->impl(), errorMessage); + auto* thisObject = jsCast<JSDOMWindow*>(object); + auto* frame = thisObject->wrapped().frame(); - // Look for overrides before looking at any of our own properties, but ignore overrides completely - // if this is cross-domain access. - if (allowsAccess && JSGlobalObject::getOwnPropertySlotByIndex(thisObject, exec, index, slot)) - return true; - - PropertyName propertyName = Identifier::from(exec, index); - - // Check for child frames by name before built-in properties to - // match Mozilla. This does not match IE, but some sites end up - // naming frames things that conflict with window properties that - // are in Moz but not IE. Since we have some of these, we have to do - // it the Moz way. - if (thisObject->impl().frame()->tree().scopedChild(propertyNameToAtomicString(propertyName))) { - slot.setCustom(thisObject, ReadOnly | DontDelete | DontEnum, childFrameGetter); - return true; - } + // Hand off all cross-domain/frameless access to jsDOMWindowGetOwnPropertySlotRestrictedAccess. + String errorMessage; + if (!frame || !BindingSecurity::shouldAllowAccessToDOMWindow(*state, thisObject->wrapped(), errorMessage)) + return jsDOMWindowGetOwnPropertySlotRestrictedAccess(thisObject, frame, state, propertyName, slot, errorMessage); - // Do prototype lookup early so that functions and attributes in the prototype can have - // precedence over the index and name getters. - JSValue proto = thisObject->prototype(); - if (proto.isObject()) { - if (asObject(proto)->getPropertySlot(exec, index, slot)) { - if (!allowsAccess) { - thisObject->printErrorMessage(errorMessage); - slot.setUndefined(); - } + // FIXME: this need more explanation. + // (Particularly, is it correct that this exists here but not in getOwnPropertySlotByIndex?) + slot.setWatchpointSet(thisObject->m_windowCloseWatchpoints); + + // (2) Regular own properties. + PropertySlot slotCopy = slot; + if (Base::getOwnPropertySlot(thisObject, state, propertyName, slot)) { + // Detect when we're getting the property 'showModalDialog', this is disabled, and has its original value. + bool isShowModalDialogAndShouldHide = propertyName == state->propertyNames().showModalDialog + && !DOMWindow::canShowModalDialog(*frame) + && slot.isValue() && isHostFunction(slot.getValue(state, propertyName), jsDOMWindowInstanceFunctionShowModalDialog); + // Unless we're in the showModalDialog special case, we're done. + if (!isShowModalDialogAndShouldHide) return true; - } + slot = slotCopy; } - // FIXME: Search the whole frame hierarchy somewhere around here. - // We need to test the correct priority order. - - // allow window[1] or parent[1] etc. (#56983) - if (index < thisObject->impl().frame()->tree().scopedChildCount()) { - ASSERT(index != PropertyName::NotAnIndex); - slot.setCustomIndex(thisObject, ReadOnly | DontDelete | DontEnum, index, indexGetter); +#if ENABLE(USER_MESSAGE_HANDLERS) + if (propertyName == state->propertyNames().webkit && thisObject->wrapped().shouldHaveWebKitNamespaceForWorld(thisObject->world())) { + slot.setCacheableCustom(thisObject, DontDelete | ReadOnly, jsDOMWindowWebKit); return true; } +#endif - if (!allowsAccess) { - thisObject->printErrorMessage(errorMessage); - slot.setUndefined(); + return false; +} + +// Property access sequence is: +// (1) indexed properties, +// (2) regular own properties, +// (3) named properties (in fact, these shouldn't be on the window, should be on the NPO). +bool JSDOMWindow::getOwnPropertySlotByIndex(JSObject* object, ExecState* state, unsigned index, PropertySlot& slot) +{ + auto* thisObject = jsCast<JSDOMWindow*>(object); + auto* frame = thisObject->wrapped().frame(); + + // Indexed getters take precendence over regular properties, so caching would be invalid. + slot.disableCaching(); + + // (1) First, indexed properties. + // These are also allowed cross-orgin, so come before the access check. + if (frame && index < frame->tree().scopedChildCount()) { + slot.setValue(thisObject, ReadOnly | DontEnum, toJS(state, frame->tree().scopedChild(index)->document()->domWindow())); return true; } - // Allow shortcuts like 'Image1' instead of document.images.Image1 - Document* document = thisObject->impl().frame()->document(); - if (document->isHTMLDocument()) { - AtomicStringImpl* atomicPropertyName = findAtomicString(propertyName); - if (atomicPropertyName && toHTMLDocument(document)->hasWindowNamedItem(*atomicPropertyName)) { - slot.setCustom(thisObject, ReadOnly | DontDelete | DontEnum, namedItemGetter); - return true; - } - } + // Hand off all cross-domain/frameless access to jsDOMWindowGetOwnPropertySlotRestrictedAccess. + String errorMessage; + if (!frame || !BindingSecurity::shouldAllowAccessToDOMWindow(*state, thisObject->wrapped(), errorMessage)) + return jsDOMWindowGetOwnPropertySlotRestrictedAccess(thisObject, frame, state, Identifier::from(state, index), slot, errorMessage); - return Base::getOwnPropertySlotByIndex(thisObject, exec, index, slot); + // (2) Regular own properties. + return Base::getOwnPropertySlotByIndex(thisObject, state, index, slot); } -void JSDOMWindow::put(JSCell* cell, ExecState* exec, PropertyName propertyName, JSValue value, PutPropertySlot& slot) +bool JSDOMWindow::put(JSCell* cell, ExecState* state, PropertyName propertyName, JSValue value, PutPropertySlot& slot) { - JSDOMWindow* thisObject = jsCast<JSDOMWindow*>(cell); - if (!thisObject->impl().frame()) - return; + VM& vm = state->vm(); + auto scope = DECLARE_THROW_SCOPE(vm); - // Optimization: access JavaScript global variables directly before involving the DOM. - if (thisObject->JSGlobalObject::hasOwnPropertyForWrite(exec, propertyName)) { - if (BindingSecurity::shouldAllowAccessToDOMWindow(exec, thisObject->impl())) - JSGlobalObject::put(thisObject, exec, propertyName, value, slot); - return; - } + auto* thisObject = jsCast<JSDOMWindow*>(cell); + if (!thisObject->wrapped().frame()) + return false; - if (lookupPut(exec, propertyName, thisObject, value, *s_info.propHashTable(exec), slot)) - return; + String errorMessage; + if (!BindingSecurity::shouldAllowAccessToDOMWindow(*state, thisObject->wrapped(), errorMessage)) { + // We only allow setting "location" attribute cross-origin. + if (propertyName == state->propertyNames().location) { + bool putResult = false; + if (lookupPut(state, propertyName, thisObject, value, *s_info.staticPropHashTable, slot, putResult)) + return putResult; + return false; + } + throwSecurityError(*state, scope, errorMessage); + return false; + } - if (BindingSecurity::shouldAllowAccessToDOMWindow(exec, thisObject->impl())) - Base::put(thisObject, exec, propertyName, value, slot); + return Base::put(thisObject, state, propertyName, value, slot); } -void JSDOMWindow::putByIndex(JSCell* cell, ExecState* exec, unsigned index, JSValue value, bool shouldThrow) +bool JSDOMWindow::putByIndex(JSCell* cell, ExecState* exec, unsigned index, JSValue value, bool shouldThrow) { - JSDOMWindow* thisObject = jsCast<JSDOMWindow*>(cell); - if (!thisObject->impl().frame()) - return; - - PropertyName propertyName = Identifier::from(exec, index); - - // Optimization: access JavaScript global variables directly before involving the DOM. - if (thisObject->JSGlobalObject::hasOwnPropertyForWrite(exec, propertyName)) { - if (BindingSecurity::shouldAllowAccessToDOMWindow(exec, thisObject->impl())) - JSGlobalObject::putByIndex(thisObject, exec, index, value, shouldThrow); - return; - } + auto* thisObject = jsCast<JSDOMWindow*>(cell); + if (!thisObject->wrapped().frame() || !BindingSecurity::shouldAllowAccessToDOMWindow(exec, thisObject->wrapped())) + return false; - if (BindingSecurity::shouldAllowAccessToDOMWindow(exec, thisObject->impl())) - Base::putByIndex(thisObject, exec, index, value, shouldThrow); + return Base::putByIndex(thisObject, exec, index, value, shouldThrow); } bool JSDOMWindow::deleteProperty(JSCell* cell, ExecState* exec, PropertyName propertyName) { JSDOMWindow* thisObject = jsCast<JSDOMWindow*>(cell); // Only allow deleting properties by frames in the same origin. - if (!BindingSecurity::shouldAllowAccessToDOMWindow(exec, thisObject->impl())) + if (!BindingSecurity::shouldAllowAccessToDOMWindow(exec, thisObject->wrapped(), ThrowSecurityError)) return false; return Base::deleteProperty(thisObject, exec, propertyName); } @@ -383,26 +286,128 @@ bool JSDOMWindow::deletePropertyByIndex(JSCell* cell, ExecState* exec, unsigned { JSDOMWindow* thisObject = jsCast<JSDOMWindow*>(cell); // Only allow deleting properties by frames in the same origin. - if (!BindingSecurity::shouldAllowAccessToDOMWindow(exec, thisObject->impl())) + if (!BindingSecurity::shouldAllowAccessToDOMWindow(exec, thisObject->wrapped(), ThrowSecurityError)) return false; return Base::deletePropertyByIndex(thisObject, exec, propertyName); } +uint32_t JSDOMWindow::getEnumerableLength(ExecState* exec, JSObject* object) +{ + JSDOMWindow* thisObject = jsCast<JSDOMWindow*>(object); + // Only allow the window to enumerated by frames in the same origin. + if (!BindingSecurity::shouldAllowAccessToDOMWindow(exec, thisObject->wrapped())) + return 0; + return Base::getEnumerableLength(exec, thisObject); +} + +void JSDOMWindow::getStructurePropertyNames(JSObject* object, ExecState* exec, PropertyNameArray& propertyNames, EnumerationMode mode) +{ + JSDOMWindow* thisObject = jsCast<JSDOMWindow*>(object); + // Only allow the window to enumerated by frames in the same origin. + if (!BindingSecurity::shouldAllowAccessToDOMWindow(exec, thisObject->wrapped())) + return; + Base::getStructurePropertyNames(thisObject, exec, propertyNames, mode); +} + +void JSDOMWindow::getGenericPropertyNames(JSObject* object, ExecState* exec, PropertyNameArray& propertyNames, EnumerationMode mode) +{ + JSDOMWindow* thisObject = jsCast<JSDOMWindow*>(object); + // Only allow the window to enumerated by frames in the same origin. + if (!BindingSecurity::shouldAllowAccessToDOMWindow(exec, thisObject->wrapped())) + return; + Base::getGenericPropertyNames(thisObject, exec, propertyNames, mode); +} + void JSDOMWindow::getPropertyNames(JSObject* object, ExecState* exec, PropertyNameArray& propertyNames, EnumerationMode mode) { JSDOMWindow* thisObject = jsCast<JSDOMWindow*>(object); // Only allow the window to enumerated by frames in the same origin. - if (!BindingSecurity::shouldAllowAccessToDOMWindow(exec, thisObject->impl())) + if (!BindingSecurity::shouldAllowAccessToDOMWindow(exec, thisObject->wrapped())) return; Base::getPropertyNames(thisObject, exec, propertyNames, mode); } +static bool inScope(Frame& frame, TreeScope& scope) +{ + auto* document = frame.document(); + if (!document) + return false; + auto* owner = document->ownerElement(); + return owner && &owner->treeScope() == &scope; +} + +static void addScopedChildrenNames(ExecState& state, DOMWindow& window, PropertyNameArray& propertyNames) +{ + auto* document = window.document(); + if (!document) + return; + + auto* frame = document->frame(); + if (!frame) + return; + + for (auto* child = frame->tree().firstChild(); child; child = child->tree().nextSibling()) { + if (!inScope(*child, *document)) + continue; + if (!child->tree().name().isEmpty()) + propertyNames.add(Identifier::fromString(&state, child->tree().name())); + } +} + +// https://html.spec.whatwg.org/#crossoriginproperties-(-o-) +static void addCrossOriginPropertyNames(ExecState& state, DOMWindow& window, PropertyNameArray& propertyNames) +{ + static const Identifier* const properties[] = { + &state.propertyNames().blur, &state.propertyNames().close, &state.propertyNames().closed, + &state.propertyNames().focus, &state.propertyNames().frames, &state.propertyNames().length, + &state.propertyNames().location, &state.propertyNames().opener, &state.propertyNames().parent, + &state.propertyNames().postMessage, &state.propertyNames().self, &state.propertyNames().top, + &state.propertyNames().window + }; + for (auto* property : properties) + propertyNames.add(*property); + + addScopedChildrenNames(state, window, propertyNames); +} + +static void addScopedChildrenIndexes(ExecState& state, DOMWindow& window, PropertyNameArray& propertyNames) +{ + auto* document = window.document(); + if (!document) + return; + + auto* frame = document->frame(); + if (!frame) + return; + + unsigned scopedChildCount = frame->tree().scopedChildCount(); + for (unsigned i = 0; i < scopedChildCount; ++i) + propertyNames.add(Identifier::from(&state, i)); +} + +// https://html.spec.whatwg.org/#crossoriginownpropertykeys-(-o-) +static void addCrossOriginOwnPropertyNames(ExecState& state, DOMWindow& window, PropertyNameArray& propertyNames) +{ + addCrossOriginPropertyNames(state, window, propertyNames); + + propertyNames.add(state.propertyNames().toStringTagSymbol); + propertyNames.add(state.propertyNames().hasInstanceSymbol); + propertyNames.add(state.propertyNames().isConcatSpreadableSymbol); +} + +// https://html.spec.whatwg.org/#windowproxy-ownpropertykeys void JSDOMWindow::getOwnPropertyNames(JSObject* object, ExecState* exec, PropertyNameArray& propertyNames, EnumerationMode mode) { JSDOMWindow* thisObject = jsCast<JSDOMWindow*>(object); - // Only allow the window to enumerated by frames in the same origin. - if (!BindingSecurity::shouldAllowAccessToDOMWindow(exec, thisObject->impl())) + + if (mode.includeDontEnumProperties()) + addScopedChildrenIndexes(*exec, thisObject->wrapped(), propertyNames); + + if (!BindingSecurity::shouldAllowAccessToDOMWindow(exec, thisObject->wrapped(), DoNotReportSecurityError)) { + if (mode.includeDontEnumProperties()) + addCrossOriginOwnPropertyNames(*exec, thisObject->wrapped(), propertyNames); return; + } Base::getOwnPropertyNames(thisObject, exec, propertyNames, mode); } @@ -410,88 +415,99 @@ bool JSDOMWindow::defineOwnProperty(JSC::JSObject* object, JSC::ExecState* exec, { JSDOMWindow* thisObject = jsCast<JSDOMWindow*>(object); // Only allow defining properties in this way by frames in the same origin, as it allows setters to be introduced. - if (!BindingSecurity::shouldAllowAccessToDOMWindow(exec, thisObject->impl())) + if (!BindingSecurity::shouldAllowAccessToDOMWindow(exec, thisObject->wrapped(), ThrowSecurityError)) return false; // Don't allow shadowing location using accessor properties. - if (descriptor.isAccessorDescriptor() && propertyName == Identifier(exec, "location")) + if (descriptor.isAccessorDescriptor() && propertyName == Identifier::fromString(exec, "location")) return false; return Base::defineOwnProperty(thisObject, exec, propertyName, descriptor, shouldThrow); } +JSValue JSDOMWindow::getPrototype(JSObject* object, ExecState* exec) +{ + JSDOMWindow* thisObject = jsCast<JSDOMWindow*>(object); + if (!BindingSecurity::shouldAllowAccessToDOMWindow(exec, thisObject->wrapped(), DoNotReportSecurityError)) + return jsNull(); + + return Base::getPrototype(object, exec); +} + +bool JSDOMWindow::preventExtensions(JSObject*, ExecState* exec) +{ + auto scope = DECLARE_THROW_SCOPE(exec->vm()); + + throwTypeError(exec, scope, ASCIILiteral("Cannot prevent extensions on this object")); + return false; +} + +String JSDOMWindow::toStringName(const JSObject* object, ExecState* exec) +{ + auto* thisObject = jsCast<const JSDOMWindow*>(object); + if (!BindingSecurity::shouldAllowAccessToDOMWindow(exec, thisObject->wrapped(), DoNotReportSecurityError)) + return ASCIILiteral("Object"); + return ASCIILiteral("Window"); +} + // Custom Attributes -void JSDOMWindow::setLocation(ExecState* exec, JSValue value) +void JSDOMWindow::setLocation(ExecState& state, JSValue value) { + VM& vm = state.vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + #if ENABLE(DASHBOARD_SUPPORT) // To avoid breaking old widgets, make "var location =" in a top-level frame create // a property named "location" instead of performing a navigation (<rdar://problem/5688039>). - if (Frame* activeFrame = activeDOMWindow(exec).frame()) { + if (Frame* activeFrame = activeDOMWindow(&state).frame()) { if (activeFrame->settings().usesDashboardBackwardCompatibilityMode() && !activeFrame->tree().parent()) { - if (BindingSecurity::shouldAllowAccessToDOMWindow(exec, impl())) - putDirect(exec->vm(), Identifier(exec, "location"), value); + if (BindingSecurity::shouldAllowAccessToDOMWindow(&state, wrapped())) + putDirect(state.vm(), Identifier::fromString(&state, "location"), value); return; } } #endif - String locationString = value.toString(exec)->value(exec); - if (exec->hadException()) - return; + String locationString = value.toWTFString(&state); + RETURN_IF_EXCEPTION(scope, void()); - if (Location* location = impl().location()) - location->setHref(locationString, activeDOMWindow(exec), firstDOMWindow(exec)); + if (Location* location = wrapped().location()) + location->setHref(activeDOMWindow(&state), firstDOMWindow(&state), locationString); } -JSValue JSDOMWindow::event(ExecState* exec) const +JSValue JSDOMWindow::event(ExecState& state) const { Event* event = currentEvent(); if (!event) return jsUndefined(); - return toJS(exec, const_cast<JSDOMWindow*>(this), event); -} - -JSValue JSDOMWindow::image(ExecState* exec) const -{ - return getDOMConstructor<JSImageConstructor>(exec->vm(), this); -} - -#if ENABLE(IOS_TOUCH_EVENTS) -JSValue JSDOMWindow::touch(ExecState* exec) const -{ - return getDOMConstructor<JSTouchConstructor>(exec->vm(), this); + return toJS(&state, const_cast<JSDOMWindow*>(this), event); } -JSValue JSDOMWindow::touchList(ExecState* exec) const -{ - return getDOMConstructor<JSTouchListConstructor>(exec->vm(), this); -} -#endif - // Custom functions -JSValue JSDOMWindow::open(ExecState* exec) +JSValue JSDOMWindow::open(ExecState& state) { - String urlString = valueToStringWithUndefinedOrNullCheck(exec, exec->argument(0)); - if (exec->hadException()) - return jsUndefined(); - AtomicString frameName = exec->argument(1).isUndefinedOrNull() ? "_blank" : exec->argument(1).toString(exec)->value(exec); - if (exec->hadException()) - return jsUndefined(); - String windowFeaturesString = valueToStringWithUndefinedOrNullCheck(exec, exec->argument(2)); - if (exec->hadException()) - return jsUndefined(); - - RefPtr<DOMWindow> openedWindow = impl().open(urlString, frameName, windowFeaturesString, activeDOMWindow(exec), firstDOMWindow(exec)); + VM& vm = state.vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + + String urlString = convert<IDLNullable<IDLUSVString>>(state, state.argument(0)); + RETURN_IF_EXCEPTION(scope, JSValue()); + JSValue targetValue = state.argument(1); + AtomicString target = targetValue.isUndefinedOrNull() ? AtomicString("_blank", AtomicString::ConstructFromLiteral) : targetValue.toString(&state)->toAtomicString(&state); + RETURN_IF_EXCEPTION(scope, JSValue()); + String windowFeaturesString = convert<IDLNullable<IDLDOMString>>(state, state.argument(2)); + RETURN_IF_EXCEPTION(scope, JSValue()); + + RefPtr<DOMWindow> openedWindow = wrapped().open(urlString, target, windowFeaturesString, activeDOMWindow(&state), firstDOMWindow(&state)); if (!openedWindow) - return jsUndefined(); - return toJS(exec, openedWindow.get()); + return jsNull(); + return toJS(&state, openedWindow.get()); } class DialogHandler { public: - explicit DialogHandler(ExecState* exec) + explicit DialogHandler(ExecState& exec) : m_exec(exec) { } @@ -500,7 +516,7 @@ public: JSValue returnValue() const; private: - ExecState* m_exec; + ExecState& m_exec; RefPtr<Frame> m_frame; }; @@ -510,162 +526,91 @@ inline void DialogHandler::dialogCreated(DOMWindow& dialog) // FIXME: This looks like a leak between the normal world and an isolated // world if dialogArguments comes from an isolated world. - JSDOMWindow* globalObject = toJSDOMWindow(m_frame.get(), normalWorld(m_exec->vm())); - if (JSValue dialogArguments = m_exec->argument(1)) - globalObject->putDirect(m_exec->vm(), Identifier(m_exec, "dialogArguments"), dialogArguments); + JSDOMWindow* globalObject = toJSDOMWindow(m_frame.get(), normalWorld(m_exec.vm())); + if (JSValue dialogArguments = m_exec.argument(1)) + globalObject->putDirect(m_exec.vm(), Identifier::fromString(&m_exec, "dialogArguments"), dialogArguments); } inline JSValue DialogHandler::returnValue() const { - JSDOMWindow* globalObject = toJSDOMWindow(m_frame.get(), normalWorld(m_exec->vm())); + JSDOMWindow* globalObject = toJSDOMWindow(m_frame.get(), normalWorld(m_exec.vm())); if (!globalObject) return jsUndefined(); - Identifier identifier(m_exec, "returnValue"); - PropertySlot slot(globalObject); - if (!JSGlobalObject::getOwnPropertySlot(globalObject, m_exec, identifier, slot)) + Identifier identifier = Identifier::fromString(&m_exec, "returnValue"); + PropertySlot slot(globalObject, PropertySlot::InternalMethodType::Get); + if (!JSGlobalObject::getOwnPropertySlot(globalObject, &m_exec, identifier, slot)) return jsUndefined(); - return slot.getValue(m_exec, identifier); + return slot.getValue(&m_exec, identifier); } -JSValue JSDOMWindow::showModalDialog(ExecState* exec) +JSValue JSDOMWindow::showModalDialog(ExecState& state) { - String urlString = valueToStringWithUndefinedOrNullCheck(exec, exec->argument(0)); - if (exec->hadException()) - return jsUndefined(); - String dialogFeaturesString = valueToStringWithUndefinedOrNullCheck(exec, exec->argument(2)); - if (exec->hadException()) - return jsUndefined(); + VM& vm = state.vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + + if (UNLIKELY(state.argumentCount() < 1)) + return throwException(&state, scope, createNotEnoughArgumentsError(&state)); + + String urlString = convert<IDLNullable<IDLDOMString>>(state, state.argument(0)); + RETURN_IF_EXCEPTION(scope, JSValue()); + String dialogFeaturesString = convert<IDLNullable<IDLDOMString>>(state, state.argument(2)); + RETURN_IF_EXCEPTION(scope, JSValue()); - DialogHandler handler(exec); + DialogHandler handler(state); - impl().showModalDialog(urlString, dialogFeaturesString, activeDOMWindow(exec), firstDOMWindow(exec), [&handler](DOMWindow& dialog) { + wrapped().showModalDialog(urlString, dialogFeaturesString, activeDOMWindow(&state), firstDOMWindow(&state), [&handler](DOMWindow& dialog) { handler.dialogCreated(dialog); }); return handler.returnValue(); } -static JSValue handlePostMessage(DOMWindow* impl, ExecState* exec) +JSValue JSDOMWindow::setTimeout(ExecState& state) { - MessagePortArray messagePorts; - ArrayBufferArray arrayBuffers; + VM& vm = state.vm(); + auto scope = DECLARE_THROW_SCOPE(vm); - // This function has variable arguments and can be: - // Per current spec: - // postMessage(message, targetOrigin) - // postMessage(message, targetOrigin, {sequence of transferrables}) - // Legacy non-standard implementations in webkit allowed: - // postMessage(message, {sequence of transferrables}, targetOrigin); - int targetOriginArgIndex = 1; - if (exec->argumentCount() > 2) { - int transferablesArgIndex = 2; - if (exec->argument(2).isString()) { - targetOriginArgIndex = 2; - transferablesArgIndex = 1; - } - fillMessagePortArray(exec, exec->argument(transferablesArgIndex), messagePorts, arrayBuffers); - } - if (exec->hadException()) - return jsUndefined(); - - RefPtr<SerializedScriptValue> message = SerializedScriptValue::create(exec, exec->argument(0), - &messagePorts, - &arrayBuffers); - - if (exec->hadException()) - return jsUndefined(); - - String targetOrigin = valueToStringWithUndefinedOrNullCheck(exec, exec->argument(targetOriginArgIndex)); - if (exec->hadException()) - return jsUndefined(); - - ExceptionCode ec = 0; - impl->postMessage(message.release(), &messagePorts, targetOrigin, activeDOMWindow(exec), ec); - setDOMException(exec, ec); - - return jsUndefined(); -} - -JSValue JSDOMWindow::postMessage(ExecState* exec) -{ - return handlePostMessage(&impl(), exec); -} - -JSValue JSDOMWindow::setTimeout(ExecState* exec) -{ - ContentSecurityPolicy* contentSecurityPolicy = impl().document() ? impl().document()->contentSecurityPolicy() : 0; - OwnPtr<ScheduledAction> action = ScheduledAction::create(exec, currentWorld(exec), contentSecurityPolicy); - if (exec->hadException()) - return jsUndefined(); + if (UNLIKELY(state.argumentCount() < 1)) + return throwException(&state, scope, createNotEnoughArgumentsError(&state)); + auto* contentSecurityPolicy = wrapped().document() ? wrapped().document()->contentSecurityPolicy() : nullptr; + auto action = ScheduledAction::create(&state, globalObject()->world(), contentSecurityPolicy); + RETURN_IF_EXCEPTION(scope, JSValue()); if (!action) return jsNumber(0); - int delay = exec->argument(1).toInt32(exec); - - ExceptionCode ec = 0; - int result = impl().setTimeout(action.release(), delay, ec); - setDOMException(exec, ec); - - return jsNumber(result); + int delay = state.argument(1).toInt32(&state); + return toJS<IDLLong>(state, scope, wrapped().setTimeout(WTFMove(action), delay)); } -JSValue JSDOMWindow::setInterval(ExecState* exec) +JSValue JSDOMWindow::setInterval(ExecState& state) { - ContentSecurityPolicy* contentSecurityPolicy = impl().document() ? impl().document()->contentSecurityPolicy() : 0; - OwnPtr<ScheduledAction> action = ScheduledAction::create(exec, currentWorld(exec), contentSecurityPolicy); - if (exec->hadException()) - return jsUndefined(); - int delay = exec->argument(1).toInt32(exec); + VM& vm = state.vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + if (UNLIKELY(state.argumentCount() < 1)) + return throwException(&state, scope, createNotEnoughArgumentsError(&state)); + + auto* contentSecurityPolicy = wrapped().document() ? wrapped().document()->contentSecurityPolicy() : nullptr; + auto action = ScheduledAction::create(&state, globalObject()->world(), contentSecurityPolicy); + RETURN_IF_EXCEPTION(scope, JSValue()); if (!action) return jsNumber(0); - ExceptionCode ec = 0; - int result = impl().setInterval(action.release(), delay, ec); - setDOMException(exec, ec); - - return jsNumber(result); -} - -JSValue JSDOMWindow::addEventListener(ExecState* exec) -{ - Frame* frame = impl().frame(); - if (!frame) - return jsUndefined(); - - JSValue listener = exec->argument(1); - if (!listener.isObject()) - return jsUndefined(); - - impl().addEventListener(exec->argument(0).toString(exec)->value(exec), JSEventListener::create(asObject(listener), this, false, currentWorld(exec)), exec->argument(2).toBoolean(exec)); - return jsUndefined(); + int delay = state.argument(1).toInt32(&state); + return toJS<IDLLong>(state, scope, wrapped().setInterval(WTFMove(action), delay)); } -JSValue JSDOMWindow::removeEventListener(ExecState* exec) -{ - Frame* frame = impl().frame(); - if (!frame) - return jsUndefined(); - - JSValue listener = exec->argument(1); - if (!listener.isObject()) - return jsUndefined(); - - impl().removeEventListener(exec->argument(0).toString(exec)->value(exec), JSEventListener::create(asObject(listener), this, false, currentWorld(exec)).get(), exec->argument(2).toBoolean(exec)); - return jsUndefined(); -} - -DOMWindow* toDOMWindow(JSValue value) +DOMWindow* JSDOMWindow::toWrapped(VM& vm, JSValue value) { if (!value.isObject()) - return 0; + return nullptr; JSObject* object = asObject(value); - if (object->inherits(JSDOMWindow::info())) - return &jsCast<JSDOMWindow*>(object)->impl(); - if (object->inherits(JSDOMWindowShell::info())) - return &jsCast<JSDOMWindowShell*>(object)->impl(); - return 0; + if (object->inherits(vm, JSDOMWindow::info())) + return &jsCast<JSDOMWindow*>(object)->wrapped(); + if (object->inherits(vm, JSDOMWindowShell::info())) + return &jsCast<JSDOMWindowShell*>(object)->wrapped(); + return nullptr; } } // namespace WebCore diff --git a/Source/WebCore/bindings/js/JSDOMWindowCustom.h b/Source/WebCore/bindings/js/JSDOMWindowCustom.h index b72ff0d05..ab629d6dc 100644 --- a/Source/WebCore/bindings/js/JSDOMWindowCustom.h +++ b/Source/WebCore/bindings/js/JSDOMWindowCustom.h @@ -16,8 +16,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#ifndef JSDOMWindowCustom_h -#define JSDOMWindowCustom_h +#pragma once #include "JSDOMWindow.h" #include "JSDOMWindowShell.h" @@ -34,6 +33,4 @@ inline const JSDOMWindow* asJSDOMWindow(const JSC::JSGlobalObject* globalObject) return static_cast<const JSDOMWindow*>(globalObject); } -} - -#endif // JSDOMWindowCustom_h +} // namespace WebCore diff --git a/Source/WebCore/bindings/js/JSDOMWindowProperties.cpp b/Source/WebCore/bindings/js/JSDOMWindowProperties.cpp new file mode 100644 index 000000000..c364f2fde --- /dev/null +++ b/Source/WebCore/bindings/js/JSDOMWindowProperties.cpp @@ -0,0 +1,103 @@ +/* + * Copyright (C) 2016 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "JSDOMWindowProperties.h" + +#include "Frame.h" +#include "HTMLDocument.h" +#include "JSDOMBinding.h" +#include "JSDOMBindingSecurity.h" +#include "JSDOMWindowBase.h" +#include "JSElement.h" +#include "JSHTMLCollection.h" + +namespace WebCore { + +using namespace JSC; + +const ClassInfo JSDOMWindowProperties::s_info = { "WindowProperties", &Base::s_info, 0, CREATE_METHOD_TABLE(JSDOMWindowProperties) }; + +static bool jsDOMWindowPropertiesGetOwnPropertySlotNamedItemGetter(JSDOMWindowProperties* thisObject, Frame& frame, ExecState* exec, PropertyName propertyName, PropertySlot& slot) +{ + // Check for child frames by name before built-in properties to match Mozilla. This does + // not match IE, but some sites end up naming frames things that conflict with window + // properties that are in Moz but not IE. Since we have some of these, we have to do it + // the Moz way. + if (auto* scopedChild = frame.tree().scopedChild(propertyNameToAtomicString(propertyName))) { + slot.setValue(thisObject, ReadOnly | DontDelete | DontEnum, toJS(exec, scopedChild->document()->domWindow())); + return true; + } + + if (!BindingSecurity::shouldAllowAccessToFrame(exec, &frame, ThrowSecurityError)) + return false; + + // FIXME: Search the whole frame hierarchy somewhere around here. + // We need to test the correct priority order. + + // Allow shortcuts like 'Image1' instead of document.images.Image1 + Document* document = frame.document(); + if (is<HTMLDocument>(*document)) { + auto& htmlDocument = downcast<HTMLDocument>(*document); + auto* atomicPropertyName = propertyName.publicName(); + if (atomicPropertyName && htmlDocument.hasWindowNamedItem(*atomicPropertyName)) { + JSValue namedItem; + if (UNLIKELY(htmlDocument.windowNamedItemContainsMultipleElements(*atomicPropertyName))) { + Ref<HTMLCollection> collection = document->windowNamedItems(atomicPropertyName); + ASSERT(collection->length() > 1); + namedItem = toJS(exec, thisObject->globalObject(), collection); + } else + namedItem = toJS(exec, thisObject->globalObject(), htmlDocument.windowNamedItem(*atomicPropertyName)); + slot.setValue(thisObject, ReadOnly | DontDelete | DontEnum, namedItem); + return true; + } + } + + return false; +} + +bool JSDOMWindowProperties::getOwnPropertySlot(JSObject* object, ExecState* state, PropertyName propertyName, PropertySlot& slot) +{ + auto* thisObject = jsCast<JSDOMWindowProperties*>(object); + ASSERT_GC_OBJECT_INHERITS(thisObject, info()); + if (Base::getOwnPropertySlot(thisObject, state, propertyName, slot)) + return true; + JSValue proto = thisObject->getPrototypeDirect(); + if (proto.isObject() && jsCast<JSObject*>(proto)->hasProperty(state, propertyName)) + return false; + + auto& window = jsCast<JSDOMWindowBase*>(thisObject->globalObject())->wrapped(); + if (auto* frame = window.frame()) + return jsDOMWindowPropertiesGetOwnPropertySlotNamedItemGetter(thisObject, *frame, state, propertyName, slot); + + return false; +} + +bool JSDOMWindowProperties::getOwnPropertySlotByIndex(JSObject* object, ExecState* state, unsigned index, PropertySlot& slot) +{ + return getOwnPropertySlot(object, state, Identifier::from(state, index), slot); +} + +} // namespace WebCore diff --git a/Source/WebCore/bindings/js/JSDOMWindowProperties.h b/Source/WebCore/bindings/js/JSDOMWindowProperties.h new file mode 100644 index 000000000..a3c47de31 --- /dev/null +++ b/Source/WebCore/bindings/js/JSDOMWindowProperties.h @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2016 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +#include "DOMWindow.h" +#include "JSDOMWindow.h" +#include "JSDOMWrapper.h" + +namespace WebCore { + +class JSDOMWindowProperties : public JSDOMObject { +public: + static JSDOMWindowProperties* create(JSC::Structure* structure, JSC::JSGlobalObject& globalObject) + { + JSDOMWindowProperties* ptr = new (NotNull, JSC::allocateCell<JSDOMWindowProperties>(globalObject.vm().heap)) JSDOMWindowProperties(structure, globalObject); + ptr->finishCreation(globalObject.vm()); + return ptr; + } + + DECLARE_INFO; + + 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()); + } + + static bool getOwnPropertySlot(JSC::JSObject*, JSC::ExecState*, JSC::PropertyName, JSC::PropertySlot&); + static bool getOwnPropertySlotByIndex(JSC::JSObject*, JSC::ExecState*, unsigned propertyName, JSC::PropertySlot&); + + static const unsigned StructureFlags = JSC::GetOwnPropertySlotIsImpureForPropertyAbsence | JSC::InterceptsGetOwnPropertySlotByIndexEvenWhenLengthIsNotZero | JSC::OverridesGetOwnPropertySlot | JSC::IsImmutablePrototypeExoticObject | Base::StructureFlags; + +protected: + JSDOMWindowProperties(JSC::Structure* structure, JSC::JSGlobalObject& globalObject) + : JSDOMObject(structure, globalObject) + { } +}; + +} // namespace WebCore diff --git a/Source/WebCore/bindings/js/JSDOMWindowShell.cpp b/Source/WebCore/bindings/js/JSDOMWindowShell.cpp index b5fc83e99..a42a030e9 100644 --- a/Source/WebCore/bindings/js/JSDOMWindowShell.cpp +++ b/Source/WebCore/bindings/js/JSDOMWindowShell.cpp @@ -10,7 +10,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of + * 3. Neither the name of Apple Inc. ("Apple") nor the names of * its contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * @@ -29,10 +29,12 @@ #include "config.h" #include "JSDOMWindowShell.h" +#include "CommonVM.h" #include "Frame.h" #include "GCController.h" #include "JSDOMWindow.h" -#include "DOMWindow.h" +#include "JSDOMWindowProperties.h" +#include "JSEventTarget.h" #include "ScriptController.h" #include <heap/StrongInlines.h> #include <runtime/JSObject.h> @@ -41,7 +43,7 @@ using namespace JSC; namespace WebCore { -const ClassInfo JSDOMWindowShell::s_info = { "JSDOMWindowShell", &Base::s_info, 0, 0, CREATE_METHOD_TABLE(JSDOMWindowShell) }; +const ClassInfo JSDOMWindowShell::s_info = { "JSDOMWindowShell", &Base::s_info, 0, CREATE_METHOD_TABLE(JSDOMWindowShell) }; JSDOMWindowShell::JSDOMWindowShell(VM& vm, Structure* structure, DOMWrapperWorld& world) : Base(vm, structure) @@ -49,11 +51,11 @@ JSDOMWindowShell::JSDOMWindowShell(VM& vm, Structure* structure, DOMWrapperWorld { } -void JSDOMWindowShell::finishCreation(VM& vm, PassRefPtr<DOMWindow> window) +void JSDOMWindowShell::finishCreation(VM& vm, RefPtr<DOMWindow>&& window) { Base::finishCreation(vm); - ASSERT(inherits(info())); - setWindow(window); + ASSERT(inherits(vm, info())); + setWindow(WTFMove(window)); } void JSDOMWindowShell::destroy(JSCell* cell) @@ -66,25 +68,30 @@ void JSDOMWindowShell::setWindow(VM& vm, JSDOMWindow* window) ASSERT_ARG(window, window); setTarget(vm, window); structure()->setGlobalObject(vm, window); - gcController().garbageCollectSoon(); + GCController::singleton().garbageCollectSoon(); } -void JSDOMWindowShell::setWindow(PassRefPtr<DOMWindow> domWindow) +void JSDOMWindowShell::setWindow(RefPtr<DOMWindow>&& domWindow) { // Replacing JSDOMWindow via telling JSDOMWindowShell to use the same DOMWindow it already uses makes no sense, // so we'd better never try to. - ASSERT(!window() || domWindow.get() != &window()->impl()); + ASSERT(!window() || domWindow.get() != &window()->wrapped()); // Explicitly protect the global object's prototype so it isn't collected // when we allocate the global object. (Once the global object is fully // constructed, it can mark its own prototype.) - VM& vm = *JSDOMWindow::commonVM(); + VM& vm = commonVM(); Structure* prototypeStructure = JSDOMWindowPrototype::createStructure(vm, 0, jsNull()); Strong<JSDOMWindowPrototype> prototype(vm, JSDOMWindowPrototype::create(vm, 0, prototypeStructure)); Structure* structure = JSDOMWindow::createStructure(vm, 0, prototype.get()); - JSDOMWindow* jsDOMWindow = JSDOMWindow::create(vm, structure, domWindow, this); + JSDOMWindow* jsDOMWindow = JSDOMWindow::create(vm, structure, *domWindow, this); prototype->structure()->setGlobalObject(vm, jsDOMWindow); + + Structure* windowPropertiesStructure = JSDOMWindowProperties::createStructure(vm, jsDOMWindow, JSEventTarget::prototype(vm, jsDOMWindow)); + JSDOMWindowProperties* windowProperties = JSDOMWindowProperties::create(windowPropertiesStructure, *jsDOMWindow); + + prototype->structure()->setPrototypeWithoutTransition(vm, windowProperties); setWindow(vm, jsDOMWindow); ASSERT(jsDOMWindow->globalObject() == jsDOMWindow); ASSERT(prototype->globalObject() == jsDOMWindow); @@ -94,9 +101,17 @@ void JSDOMWindowShell::setWindow(PassRefPtr<DOMWindow> domWindow) // JSDOMWindow methods // ---- -DOMWindow& JSDOMWindowShell::impl() const +DOMWindow& JSDOMWindowShell::wrapped() const +{ + return window()->wrapped(); +} + +DOMWindow* JSDOMWindowShell::toWrapped(VM& vm, JSObject* value) { - return window()->impl(); + auto* wrapper = jsDynamicDowncast<JSDOMWindowShell*>(vm, value); + if (!wrapper) + return nullptr; + return &wrapper->window()->wrapped(); } // ---- diff --git a/Source/WebCore/bindings/js/JSDOMWindowShell.h b/Source/WebCore/bindings/js/JSDOMWindowShell.h index 85a6fd873..17129237b 100644 --- a/Source/WebCore/bindings/js/JSDOMWindowShell.h +++ b/Source/WebCore/bindings/js/JSDOMWindowShell.h @@ -10,7 +10,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of + * 3. Neither the name of Apple Inc. ("Apple") nor the names of * its contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * @@ -26,15 +26,14 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef JSDOMWindowShell_h -#define JSDOMWindowShell_h +#pragma once +#include "DOMWindow.h" #include "JSDOMWindow.h" #include <runtime/JSProxy.h> namespace WebCore { - class DOMWindow; class Frame; class JSDOMWindowShell : public JSC::JSProxy { @@ -44,29 +43,30 @@ namespace WebCore { JSDOMWindow* window() const { return JSC::jsCast<JSDOMWindow*>(target()); } void setWindow(JSC::VM&, JSDOMWindow*); - void setWindow(PassRefPtr<DOMWindow>); + void setWindow(RefPtr<DOMWindow>&&); DECLARE_INFO; - DOMWindow& impl() const; + DOMWindow& wrapped() const; + static WEBCORE_EXPORT DOMWindow* toWrapped(JSC::VM&, JSC::JSObject*); - static JSDOMWindowShell* create(JSC::VM& vm, PassRefPtr<DOMWindow> window, JSC::Structure* structure, DOMWrapperWorld& world) + static JSDOMWindowShell* create(JSC::VM& vm, RefPtr<DOMWindow>&& window, JSC::Structure* structure, DOMWrapperWorld& world) { JSDOMWindowShell* shell = new (NotNull, JSC::allocateCell<JSDOMWindowShell>(vm.heap)) JSDOMWindowShell(vm, structure, world); - shell->finishCreation(vm, window); + shell->finishCreation(vm, WTFMove(window)); return shell; } static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSValue prototype) { - return JSC::Structure::create(vm, 0, prototype, JSC::TypeInfo(JSC::ProxyType, StructureFlags), info()); + return JSC::Structure::create(vm, 0, prototype, JSC::TypeInfo(JSC::PureForwardingProxyType, StructureFlags), info()); } - DOMWrapperWorld& world() { return m_world.get(); } + DOMWrapperWorld& world() { return m_world; } protected: JSDOMWindowShell(JSC::VM&, JSC::Structure*, DOMWrapperWorld&); - void finishCreation(JSC::VM&, PassRefPtr<DOMWindow>); + void finishCreation(JSC::VM&, RefPtr<DOMWindow>&&); Ref<DOMWrapperWorld> m_world; }; @@ -75,5 +75,3 @@ namespace WebCore { JSDOMWindowShell* toJSDOMWindowShell(Frame*, DOMWrapperWorld&); } // namespace WebCore - -#endif // JSDOMWindowShell_h diff --git a/Source/WebCore/bindings/js/JSDOMWrapper.cpp b/Source/WebCore/bindings/js/JSDOMWrapper.cpp index 1629ae57e..21da86365 100644 --- a/Source/WebCore/bindings/js/JSDOMWrapper.cpp +++ b/Source/WebCore/bindings/js/JSDOMWrapper.cpp @@ -26,12 +26,32 @@ #include "config.h" #include "JSDOMWrapper.h" +#include "DOMWrapperWorld.h" +#include "JSDOMWindow.h" +#include "WebCoreJSClientData.h" #include <runtime/Error.h> using namespace JSC; namespace WebCore { -STATIC_ASSERT_IS_TRIVIALLY_DESTRUCTIBLE(JSDOMWrapper); +STATIC_ASSERT_IS_TRIVIALLY_DESTRUCTIBLE(JSDOMObject); + +JSDOMWindow& JSDOMObject::domWindow() const +{ + auto* domWindow = JSC::jsCast<JSDOMWindow*>(JSC::JSNonFinalObject::globalObject()); + ASSERT(domWindow); + return *domWindow; +} + +Subspace* outputConstraintSubspaceFor(VM& vm) +{ + return &static_cast<JSVMClientData*>(vm.clientData)->outputConstraintSpace(); +} + +Subspace* globalObjectOutputConstraintSubspaceFor(VM& vm) +{ + return &static_cast<JSVMClientData*>(vm.clientData)->globalObjectOutputConstraintSpace(); +} } // namespace WebCore diff --git a/Source/WebCore/bindings/js/JSDOMWrapper.h b/Source/WebCore/bindings/js/JSDOMWrapper.h index 026dcd931..11d439ce2 100644 --- a/Source/WebCore/bindings/js/JSDOMWrapper.h +++ b/Source/WebCore/bindings/js/JSDOMWrapper.h @@ -19,31 +19,101 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#ifndef JSDOMWrapper_h -#define JSDOMWrapper_h +#pragma once #include "JSDOMGlobalObject.h" +#include "NodeConstants.h" #include <runtime/JSDestructibleObject.h> namespace WebCore { +class JSDOMWindow; class ScriptExecutionContext; -class JSDOMWrapper : public JSC::JSDestructibleObject { +// JSC allows us to extend JSType. If the highest bit is set, we can add any Object types and they are +// recognized as OtherObj in JSC. And we encode Node type into JSType if the given JSType is subclass of Node. +// offset | 7 | 6 | 5 4 | 3 2 1 0 | +// value | 1 | 0 | Non-node DOM types | +// If the given JSType is a subclass of Node, the format is the following. +// offset | 7 | 6 | 5 4 | 3 2 1 0 | +// value | 1 | 1 | Kind | NodeType | +static const uint8_t JSNodeTypeMask = 0b00001111; + +static const uint8_t JSDOMWrapperType = 0b10000000; +static const uint8_t JSEventType = 0b10000001; +static const uint8_t JSNodeType = 0b11000000; +static const uint8_t JSTextNodeType = JSNodeType | NodeConstants::TEXT_NODE; +static const uint8_t JSProcessingInstructionNodeType = JSNodeType | NodeConstants::PROCESSING_INSTRUCTION_NODE; +static const uint8_t JSDocumentTypeNodeType = JSNodeType | NodeConstants::DOCUMENT_TYPE_NODE; +static const uint8_t JSDocumentFragmentNodeType = JSNodeType | NodeConstants::DOCUMENT_FRAGMENT_NODE; +static const uint8_t JSDocumentWrapperType = JSNodeType | NodeConstants::DOCUMENT_NODE; +static const uint8_t JSCommentNodeType = JSNodeType | NodeConstants::COMMENT_NODE; +static const uint8_t JSCDATASectionNodeType = JSNodeType | NodeConstants::CDATA_SECTION_NODE; +static const uint8_t JSAttrNodeType = JSNodeType | NodeConstants::ATTRIBUTE_NODE; +static const uint8_t JSElementType = 0b11010000 | NodeConstants::ELEMENT_NODE; + +static_assert(JSDOMWrapperType > JSC::LastJSCObjectType, "JSC::JSType offers the highest bit."); +static_assert(NodeConstants::LastNodeType <= JSNodeTypeMask, "NodeType should be represented in 4bit."); + +class JSDOMObject : public JSC::JSDestructibleObject { public: typedef JSC::JSDestructibleObject Base; + static constexpr bool isDOMWrapper = false; JSDOMGlobalObject* globalObject() const { return JSC::jsCast<JSDOMGlobalObject*>(JSC::JSNonFinalObject::globalObject()); } ScriptExecutionContext* scriptExecutionContext() const { return globalObject()->scriptExecutionContext(); } + JSDOMWindow& domWindow() const; + protected: - JSDOMWrapper(JSC::Structure* structure, JSC::JSGlobalObject* globalObject) - : JSDestructibleObject(globalObject->vm(), structure) + JSDOMObject(JSC::Structure* structure, JSC::JSGlobalObject& globalObject) + : Base(globalObject.vm(), structure) { ASSERT(scriptExecutionContext()); } }; -} // namespace WebCore +WEBCORE_EXPORT JSC::Subspace* outputConstraintSubspaceFor(JSC::VM&); +WEBCORE_EXPORT JSC::Subspace* globalObjectOutputConstraintSubspaceFor(JSC::VM&); + +template<typename ImplementationClass> class JSDOMWrapper : public JSDOMObject { +public: + typedef JSDOMObject Base; + typedef ImplementationClass DOMWrapped; + static constexpr bool isDOMWrapper = true; + + ImplementationClass& wrapped() const { return m_wrapped; } + static ptrdiff_t offsetOfWrapped() { return OBJECT_OFFSETOF(JSDOMWrapper<ImplementationClass>, m_wrapped); } + +protected: + JSDOMWrapper(JSC::Structure* structure, JSC::JSGlobalObject& globalObject, Ref<ImplementationClass>&& impl) + : Base(structure, globalObject) + , m_wrapped(WTFMove(impl)) { } + +private: + Ref<ImplementationClass> m_wrapped; +}; + +template<typename ImplementationClass> struct JSDOMWrapperConverterTraits; + +template<typename JSClass, typename Enable = void> +struct JSDOMObjectInspector { +public: + static constexpr bool isSimpleWrapper = false; + static constexpr bool isComplexWrapper = false; + static constexpr bool isBuiltin = true; +}; -#endif // JSDOMWrapper_h +template<typename JSClass> +struct JSDOMObjectInspector<JSClass, typename std::enable_if<JSClass::isDOMWrapper>::type> { +private: + template<typename T> static constexpr auto test(int) -> decltype(T::create(), bool()) { return true; } + template<typename T> static constexpr bool test(...) { return false; } + +public: + static constexpr bool isSimpleWrapper = test<typename JSClass::DOMWrapped>(0); + static constexpr bool isComplexWrapper = !isSimpleWrapper; + static constexpr bool isBuiltin = false; +}; + +} // namespace WebCore diff --git a/Source/WebCore/bindings/js/JSDOMWrapperCache.cpp b/Source/WebCore/bindings/js/JSDOMWrapperCache.cpp new file mode 100644 index 000000000..6d875d58a --- /dev/null +++ b/Source/WebCore/bindings/js/JSDOMWrapperCache.cpp @@ -0,0 +1,45 @@ +/* + * Copyright (C) 1999-2001 Harri Porten (porten@kde.org) + * Copyright (C) 2004-2011, 2013, 2016 Apple Inc. All rights reserved. + * Copyright (C) 2007 Samuel Weinig <sam@webkit.org> + * Copyright (C) 2013 Michael Pruett <michael@68k.org> + * + * 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 + */ + +#include "config.h" +#include "JSDOMWrapperCache.h" + +#include <runtime/JSCInlines.h> + +using namespace JSC; + +namespace WebCore { + +Structure* getCachedDOMStructure(JSDOMGlobalObject& globalObject, const ClassInfo* classInfo) +{ + JSDOMStructureMap& structures = globalObject.structures(NoLockingNecessary); + return structures.get(classInfo).get(); +} + +Structure* cacheDOMStructure(JSDOMGlobalObject& globalObject, Structure* structure, const ClassInfo* classInfo) +{ + auto locker = lockDuringMarking(globalObject.vm().heap, globalObject.gcLock()); + JSDOMStructureMap& structures = globalObject.structures(locker); + ASSERT(!structures.contains(classInfo)); + return structures.set(classInfo, WriteBarrier<Structure>(globalObject.vm(), &globalObject, structure)).iterator->value.get(); +} + +} // namespace WebCore diff --git a/Source/WebCore/bindings/js/JSDOMWrapperCache.h b/Source/WebCore/bindings/js/JSDOMWrapperCache.h new file mode 100644 index 000000000..dd8c4b206 --- /dev/null +++ b/Source/WebCore/bindings/js/JSDOMWrapperCache.h @@ -0,0 +1,206 @@ +/* + * Copyright (C) 1999-2001 Harri Porten (porten@kde.org) + * Copyright (C) 2003-2006, 2008-2009, 2013, 2016 Apple Inc. All rights reserved. + * Copyright (C) 2007 Samuel Weinig <sam@webkit.org> + * Copyright (C) 2009 Google, Inc. All rights reserved. + * Copyright (C) 2012 Ericsson AB. All rights reserved. + * Copyright (C) 2013 Michael Pruett <michael@68k.org> + * + * 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 + */ + +#pragma once + +#include "DOMWrapperWorld.h" +#include "JSDOMGlobalObject.h" +#include "JSDOMWrapper.h" +#include "JSDynamicDowncast.h" +#include "ScriptWrappable.h" +#include "ScriptWrappableInlines.h" +#include "WebCoreTypedArrayController.h" +#include <heap/Weak.h> +#include <heap/WeakInlines.h> +#include <runtime/JSArrayBuffer.h> +#include <runtime/TypedArrayInlines.h> +#include <runtime/TypedArrays.h> + +namespace WebCore { + +WEBCORE_EXPORT JSC::Structure* getCachedDOMStructure(JSDOMGlobalObject&, const JSC::ClassInfo*); +WEBCORE_EXPORT JSC::Structure* cacheDOMStructure(JSDOMGlobalObject&, JSC::Structure*, const JSC::ClassInfo*); + +template<typename WrapperClass> JSC::Structure* getDOMStructure(JSC::VM&, JSDOMGlobalObject&); +template<typename WrapperClass> JSC::Structure* deprecatedGetDOMStructure(JSC::ExecState*); +template<typename WrapperClass> JSC::JSObject* getDOMPrototype(JSC::VM&, JSC::JSGlobalObject*); + +JSC::WeakHandleOwner* wrapperOwner(DOMWrapperWorld&, JSC::ArrayBuffer*); +void* wrapperKey(JSC::ArrayBuffer*); + +JSDOMObject* getInlineCachedWrapper(DOMWrapperWorld&, void*); +JSDOMObject* getInlineCachedWrapper(DOMWrapperWorld&, ScriptWrappable*); +JSC::JSArrayBuffer* getInlineCachedWrapper(DOMWrapperWorld&, JSC::ArrayBuffer*); + +bool setInlineCachedWrapper(DOMWrapperWorld&, void*, JSDOMObject*, JSC::WeakHandleOwner*); +bool setInlineCachedWrapper(DOMWrapperWorld&, ScriptWrappable*, JSDOMObject* wrapper, JSC::WeakHandleOwner* wrapperOwner); +bool setInlineCachedWrapper(DOMWrapperWorld&, JSC::ArrayBuffer*, JSC::JSArrayBuffer* wrapper, JSC::WeakHandleOwner* wrapperOwner); + +bool clearInlineCachedWrapper(DOMWrapperWorld&, void*, JSDOMObject*); +bool clearInlineCachedWrapper(DOMWrapperWorld&, ScriptWrappable*, JSDOMObject* wrapper); +bool clearInlineCachedWrapper(DOMWrapperWorld&, JSC::ArrayBuffer*, JSC::JSArrayBuffer* wrapper); + +template<typename DOMClass> JSC::JSObject* getCachedWrapper(DOMWrapperWorld&, DOMClass&); +template<typename DOMClass> inline JSC::JSObject* getCachedWrapper(DOMWrapperWorld& world, Ref<DOMClass>& object) { return getCachedWrapper(world, object.get()); } +template<typename DOMClass, typename WrapperClass> void cacheWrapper(DOMWrapperWorld&, DOMClass*, WrapperClass*); +template<typename DOMClass, typename WrapperClass> void uncacheWrapper(DOMWrapperWorld&, DOMClass*, WrapperClass*); +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; +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; + +template<typename DOMClass> JSC::JSValue wrap(JSC::ExecState*, JSDOMGlobalObject*, DOMClass&); + + +// Inline functions and template definitions. + +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<JSDOMGlobalObject*>(exec->lexicalGlobalObject()); +} + +template<typename WrapperClass> 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<typename WrapperClass> 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<WrapperClass>(exec->vm(), *deprecatedGlobalObjectForPrototype(exec)); +} + +template<typename WrapperClass> inline JSC::JSObject* getDOMPrototype(JSC::VM& vm, JSC::JSGlobalObject* globalObject) +{ + return JSC::jsCast<JSC::JSObject*>(asObject(getDOMStructure<WrapperClass>(vm, *JSC::jsCast<JSDOMGlobalObject*>(globalObject))->storedPrototype())); +} + +inline JSC::WeakHandleOwner* wrapperOwner(DOMWrapperWorld& world, JSC::ArrayBuffer*) +{ + return static_cast<WebCoreTypedArrayController*>(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<JSC::JSArrayBuffer>(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<typename DOMClass> inline JSC::JSObject* getCachedWrapper(DOMWrapperWorld& world, DOMClass& domObject) +{ + if (auto* wrapper = getInlineCachedWrapper(world, &domObject)) + return wrapper; + return world.m_wrappers.get(wrapperKey(&domObject)); +} + +template<typename DOMClass, typename WrapperClass> 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<JSC::JSObject>(wrapper, owner, &world)); +} + +template<typename DOMClass, typename WrapperClass> inline void uncacheWrapper(DOMWrapperWorld& world, DOMClass* domObject, WrapperClass* wrapper) +{ + if (clearInlineCachedWrapper(world, domObject, wrapper)) + return; + weakRemove(world.m_wrappers, wrapperKey(domObject), wrapper); +} + +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 +{ + using WrapperClass = typename JSDOMWrapperConverterTraits<DOMClass>::WrapperClass; + + ASSERT(!getCachedWrapper(globalObject->world(), domObject)); + auto* domObjectPtr = domObject.ptr(); + auto* wrapper = WrapperClass::create(getDOMStructure<WrapperClass>(globalObject->vm(), *globalObject), globalObject, WTFMove(domObject)); + cacheWrapper(globalObject->world(), domObjectPtr, wrapper); + return wrapper; +} + +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 +{ + return createWrapper<DOMClass>(globalObject, static_reference_cast<DOMClass>(WTFMove(domObject))); +} + +template<typename DOMClass> inline JSC::JSValue wrap(JSC::ExecState* state, JSDOMGlobalObject* globalObject, DOMClass& domObject) +{ + if (auto* wrapper = getCachedWrapper(globalObject->world(), domObject)) + return wrapper; + return toJSNewlyCreated(state, globalObject, Ref<DOMClass>(domObject)); +} + +} // namespace WebCore diff --git a/Source/WebCore/bindings/js/JSDedicatedWorkerGlobalScopeCustom.cpp b/Source/WebCore/bindings/js/JSDedicatedWorkerGlobalScopeCustom.cpp deleted file mode 100644 index ea62e28ed..000000000 --- a/Source/WebCore/bindings/js/JSDedicatedWorkerGlobalScopeCustom.cpp +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (C) 2009 Apple, Inc. All rights reserved. - * Copyright (C) 2009, 2011 Google Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" -#include "JSDedicatedWorkerGlobalScope.h" - -#include "JSDOMBinding.h" -#include "JSMessagePortCustom.h" - -using namespace JSC; - -namespace WebCore { - -JSC::JSValue JSDedicatedWorkerGlobalScope::postMessage(JSC::ExecState* exec) -{ - return handlePostMessage(exec, &impl()); -} - -} // namespace WebCore diff --git a/Source/WebCore/bindings/js/JSDeviceMotionEventCustom.cpp b/Source/WebCore/bindings/js/JSDeviceMotionEventCustom.cpp deleted file mode 100644 index b4d5c4f8d..000000000 --- a/Source/WebCore/bindings/js/JSDeviceMotionEventCustom.cpp +++ /dev/null @@ -1,195 +0,0 @@ -/* - * Copyright (C) 2010 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" - -#if ENABLE(DEVICE_ORIENTATION) - -#include "JSDeviceMotionEvent.h" - -#include "DeviceMotionData.h" -#include "DeviceMotionEvent.h" -#include <runtime/ObjectConstructor.h> - -using namespace JSC; - -namespace WebCore { - -static PassRefPtr<DeviceMotionData::Acceleration> readAccelerationArgument(JSValue value, ExecState* exec) -{ - if (value.isUndefinedOrNull()) - return 0; - - // Given the above test, this will always yield an object. - JSObject* object = value.toObject(exec); - - JSValue xValue = object->get(exec, Identifier(exec, "x")); - if (exec->hadException()) - return 0; - bool canProvideX = !xValue.isUndefinedOrNull(); - double x = xValue.toNumber(exec); - if (exec->hadException()) - return 0; - - JSValue yValue = object->get(exec, Identifier(exec, "y")); - if (exec->hadException()) - return 0; - bool canProvideY = !yValue.isUndefinedOrNull(); - double y = yValue.toNumber(exec); - if (exec->hadException()) - return 0; - - JSValue zValue = object->get(exec, Identifier(exec, "z")); - if (exec->hadException()) - return 0; - bool canProvideZ = !zValue.isUndefinedOrNull(); - double z = zValue.toNumber(exec); - if (exec->hadException()) - return 0; - - if (!canProvideX && !canProvideY && !canProvideZ) - return 0; - - return DeviceMotionData::Acceleration::create(canProvideX, x, canProvideY, y, canProvideZ, z); -} - -static PassRefPtr<DeviceMotionData::RotationRate> readRotationRateArgument(JSValue value, ExecState* exec) -{ - if (value.isUndefinedOrNull()) - return 0; - - // Given the above test, this will always yield an object. - JSObject* object = value.toObject(exec); - - JSValue alphaValue = object->get(exec, Identifier(exec, "alpha")); - if (exec->hadException()) - return 0; - bool canProvideAlpha = !alphaValue.isUndefinedOrNull(); - double alpha = alphaValue.toNumber(exec); - if (exec->hadException()) - return 0; - - JSValue betaValue = object->get(exec, Identifier(exec, "beta")); - if (exec->hadException()) - return 0; - bool canProvideBeta = !betaValue.isUndefinedOrNull(); - double beta = betaValue.toNumber(exec); - if (exec->hadException()) - return 0; - - JSValue gammaValue = object->get(exec, Identifier(exec, "gamma")); - if (exec->hadException()) - return 0; - bool canProvideGamma = !gammaValue.isUndefinedOrNull(); - double gamma = gammaValue.toNumber(exec); - if (exec->hadException()) - return 0; - - if (!canProvideAlpha && !canProvideBeta && !canProvideGamma) - return 0; - - return DeviceMotionData::RotationRate::create(canProvideAlpha, alpha, canProvideBeta, beta, canProvideGamma, gamma); -} - -static JSObject* createAccelerationObject(const DeviceMotionData::Acceleration* acceleration, ExecState* exec) -{ - JSObject* object = constructEmptyObject(exec); - object->putDirect(exec->vm(), Identifier(exec, "x"), acceleration->canProvideX() ? jsNumber(acceleration->x()) : jsNull()); - object->putDirect(exec->vm(), Identifier(exec, "y"), acceleration->canProvideY() ? jsNumber(acceleration->y()) : jsNull()); - object->putDirect(exec->vm(), Identifier(exec, "z"), acceleration->canProvideZ() ? jsNumber(acceleration->z()) : jsNull()); - return object; -} - -static JSObject* createRotationRateObject(const DeviceMotionData::RotationRate* rotationRate, ExecState* exec) -{ - JSObject* object = constructEmptyObject(exec); - object->putDirect(exec->vm(), Identifier(exec, "alpha"), rotationRate->canProvideAlpha() ? jsNumber(rotationRate->alpha()) : jsNull()); - object->putDirect(exec->vm(), Identifier(exec, "beta"), rotationRate->canProvideBeta() ? jsNumber(rotationRate->beta()) : jsNull()); - object->putDirect(exec->vm(), Identifier(exec, "gamma"), rotationRate->canProvideGamma() ? jsNumber(rotationRate->gamma()) : jsNull()); - return object; -} - -JSValue JSDeviceMotionEvent::acceleration(ExecState* exec) const -{ - DeviceMotionEvent& imp = impl(); - if (!imp.deviceMotionData()->acceleration()) - return jsNull(); - return createAccelerationObject(imp.deviceMotionData()->acceleration(), exec); -} - -JSValue JSDeviceMotionEvent::accelerationIncludingGravity(ExecState* exec) const -{ - DeviceMotionEvent& imp = impl(); - if (!imp.deviceMotionData()->accelerationIncludingGravity()) - return jsNull(); - return createAccelerationObject(imp.deviceMotionData()->accelerationIncludingGravity(), exec); -} - -JSValue JSDeviceMotionEvent::rotationRate(ExecState* exec) const -{ - DeviceMotionEvent& imp = impl(); - if (!imp.deviceMotionData()->rotationRate()) - return jsNull(); - return createRotationRateObject(imp.deviceMotionData()->rotationRate(), exec); -} - -JSValue JSDeviceMotionEvent::interval(ExecState*) const -{ - DeviceMotionEvent& imp = impl(); - if (!imp.deviceMotionData()->canProvideInterval()) - return jsNull(); - return jsNumber(imp.deviceMotionData()->interval()); -} - -JSValue JSDeviceMotionEvent::initDeviceMotionEvent(ExecState* exec) -{ - const String type = exec->argument(0).toString(exec)->value(exec); - bool bubbles = exec->argument(1).toBoolean(exec); - bool cancelable = exec->argument(2).toBoolean(exec); - - // If any of the parameters are null or undefined, mark them as not provided. - // Otherwise, use the standard JavaScript conversion. - RefPtr<DeviceMotionData::Acceleration> acceleration = readAccelerationArgument(exec->argument(3), exec); - if (exec->hadException()) - return jsUndefined(); - - RefPtr<DeviceMotionData::Acceleration> accelerationIncludingGravity = readAccelerationArgument(exec->argument(4), exec); - if (exec->hadException()) - return jsUndefined(); - - RefPtr<DeviceMotionData::RotationRate> rotationRate = readRotationRateArgument(exec->argument(5), exec); - if (exec->hadException()) - return jsUndefined(); - - bool intervalProvided = !exec->argument(6).isUndefinedOrNull(); - double interval = exec->argument(6).toNumber(exec); - RefPtr<DeviceMotionData> deviceMotionData = DeviceMotionData::create(acceleration, accelerationIncludingGravity, rotationRate, intervalProvided, interval); - impl().initDeviceMotionEvent(type, bubbles, cancelable, deviceMotionData.get()); - return jsUndefined(); -} - -} // namespace WebCore - -#endif // ENABLE(DEVICE_ORIENTATION) diff --git a/Source/WebCore/bindings/js/JSDeviceOrientationEventCustom.cpp b/Source/WebCore/bindings/js/JSDeviceOrientationEventCustom.cpp deleted file mode 100644 index 86ddc96aa..000000000 --- a/Source/WebCore/bindings/js/JSDeviceOrientationEventCustom.cpp +++ /dev/null @@ -1,121 +0,0 @@ -/* - * Copyright (C) 2010 Google Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" - -#if ENABLE(DEVICE_ORIENTATION) - -#include "JSDeviceOrientationEvent.h" - -#include "DeviceOrientationData.h" -#include "DeviceOrientationEvent.h" - -using namespace JSC; - -namespace WebCore { - -JSValue JSDeviceOrientationEvent::alpha(ExecState*) const -{ - DeviceOrientationEvent& imp = impl(); - if (!imp.orientation()->canProvideAlpha()) - return jsNull(); - return jsNumber(imp.orientation()->alpha()); -} - -JSValue JSDeviceOrientationEvent::beta(ExecState*) const -{ - DeviceOrientationEvent& imp = impl(); - if (!imp.orientation()->canProvideBeta()) - return jsNull(); - return jsNumber(imp.orientation()->beta()); -} - -JSValue JSDeviceOrientationEvent::gamma(ExecState*) const -{ - DeviceOrientationEvent& imp = impl(); - if (!imp.orientation()->canProvideGamma()) - return jsNull(); - return jsNumber(imp.orientation()->gamma()); -} - -#if PLATFORM(IOS) -JSValue JSDeviceOrientationEvent::webkitCompassHeading(ExecState*) const -{ - DeviceOrientationEvent& imp = impl(); - if (!imp.orientation()->canProvideCompassHeading()) - return jsNull(); - return jsNumber(imp.orientation()->compassHeading()); -} - -JSValue JSDeviceOrientationEvent::webkitCompassAccuracy(ExecState*) const -{ - DeviceOrientationEvent& imp = impl(); - if (!imp.orientation()->canProvideCompassAccuracy()) - return jsNull(); - return jsNumber(imp.orientation()->compassAccuracy()); -} -#endif - -#if !PLATFORM(IOS) -JSValue JSDeviceOrientationEvent::absolute(ExecState*) const -{ - DeviceOrientationEvent& imp = impl(); - if (!imp.orientation()->canProvideAbsolute()) - return jsNull(); - return jsBoolean(imp.orientation()->absolute()); -} -#endif - -JSValue JSDeviceOrientationEvent::initDeviceOrientationEvent(ExecState* exec) -{ - const String type = exec->argument(0).toString(exec)->value(exec); - bool bubbles = exec->argument(1).toBoolean(exec); - bool cancelable = exec->argument(2).toBoolean(exec); - // If alpha, beta or gamma are null or undefined, mark them as not provided. - // Otherwise, use the standard JavaScript conversion. - bool alphaProvided = !exec->argument(3).isUndefinedOrNull(); - double alpha = exec->argument(3).toNumber(exec); - bool betaProvided = !exec->argument(4).isUndefinedOrNull(); - double beta = exec->argument(4).toNumber(exec); - bool gammaProvided = !exec->argument(5).isUndefinedOrNull(); - double gamma = exec->argument(5).toNumber(exec); -#if PLATFORM(IOS) - bool compassHeadingProvided = !exec->argument(6).isUndefinedOrNull(); - double compassHeading = exec->argument(6).toNumber(exec); - bool compassAccuracyProvided = !exec->argument(7).isUndefinedOrNull(); - double compassAccuracy = exec->argument(7).toNumber(exec); - RefPtr<DeviceOrientationData> orientation = DeviceOrientationData::create(alphaProvided, alpha, betaProvided, beta, gammaProvided, gamma, compassHeadingProvided, compassHeading, compassAccuracyProvided, compassAccuracy); -#else - bool absoluteProvided = !exec->argument(6).isUndefinedOrNull(); - bool absolute = exec->argument(6).toBoolean(exec); - RefPtr<DeviceOrientationData> orientation = DeviceOrientationData::create(alphaProvided, alpha, betaProvided, beta, gammaProvided, gamma, absoluteProvided, absolute); -#endif - impl().initDeviceOrientationEvent(type, bubbles, cancelable, orientation.get()); - return jsUndefined(); -} - -} // namespace WebCore - -#endif // ENABLE(DEVICE_ORIENTATION) diff --git a/Source/WebCore/bindings/js/JSDictionary.cpp b/Source/WebCore/bindings/js/JSDictionary.cpp deleted file mode 100644 index 4c2882611..000000000 --- a/Source/WebCore/bindings/js/JSDictionary.cpp +++ /dev/null @@ -1,279 +0,0 @@ -/* - * Copyright (C) 2011 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS - * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" -#include "JSDictionary.h" - -#include "ArrayValue.h" -#include "Dictionary.h" -#include "JSCSSFontFaceRule.h" -#include "JSDOMError.h" -#include "JSDOMWindow.h" -#include "JSEventTarget.h" -#include "JSMessagePortCustom.h" -#include "JSNode.h" -#include "JSStorage.h" -#include "JSTrackCustom.h" -#include "JSVoidCallback.h" -#include "SerializedScriptValue.h" -#include <runtime/JSTypedArrays.h> -#include <wtf/HashMap.h> -#include <wtf/MathExtras.h> -#include <wtf/text/AtomicString.h> - -#if ENABLE(ENCRYPTED_MEDIA) -#include "JSMediaKeyError.h" -#endif - -#if ENABLE(MEDIA_STREAM) -#include "JSMediaStream.h" -#include "JSMediaStreamTrack.h" -#endif - -#if ENABLE(SCRIPTED_SPEECH) -#include "JSSpeechRecognitionResultList.h" -#endif - -using namespace JSC; - -namespace WebCore { - -JSDictionary::GetPropertyResult JSDictionary::tryGetProperty(const char* propertyName, JSValue& finalResult) const -{ - ASSERT(isValid()); - Identifier identifier(m_exec, propertyName); - PropertySlot slot(m_initializerObject.get()); - - if (!m_initializerObject.get()->getPropertySlot(m_exec, identifier, slot)) - return NoPropertyFound; - - if (m_exec->hadException()) - return ExceptionThrown; - - finalResult = slot.getValue(m_exec, identifier); - if (m_exec->hadException()) - return ExceptionThrown; - - return PropertyFound; -} - -void JSDictionary::convertValue(ExecState* exec, JSValue value, bool& result) -{ - result = value.toBoolean(exec); -} - -void JSDictionary::convertValue(ExecState* exec, JSValue value, int& result) -{ - result = value.toInt32(exec); -} - -void JSDictionary::convertValue(ExecState* exec, JSValue value, unsigned& result) -{ - result = value.toUInt32(exec); -} - -void JSDictionary::convertValue(ExecState* exec, JSValue value, unsigned short& result) -{ - result = static_cast<unsigned short>(value.toUInt32(exec)); -} - -void JSDictionary::convertValue(ExecState* exec, JSValue value, unsigned long& result) -{ - result = static_cast<unsigned long>(value.toUInt32(exec)); -} - -void JSDictionary::convertValue(ExecState* exec, JSValue value, unsigned long long& result) -{ - double d = value.toNumber(exec); - doubleToInteger(d, result); -} - -void JSDictionary::convertValue(ExecState* exec, JSValue value, double& result) -{ - result = value.toNumber(exec); -} - -void JSDictionary::convertValue(JSC::ExecState* exec, JSC::JSValue value, Dictionary& result) -{ - result = Dictionary(exec, value); -} - -void JSDictionary::convertValue(ExecState* exec, JSValue value, String& result) -{ - result = value.toString(exec)->value(exec); -} - -void JSDictionary::convertValue(ExecState* exec, JSValue value, Vector<String>& result) -{ - if (value.isUndefinedOrNull()) - return; - - unsigned length = 0; - JSObject* object = toJSSequence(exec, value, length); - if (exec->hadException()) - return; - - for (unsigned i = 0 ; i < length; ++i) { - JSValue itemValue = object->get(exec, i); - if (exec->hadException()) - return; - result.append(itemValue.toString(exec)->value(exec)); - } -} - -void JSDictionary::convertValue(ExecState* exec, JSValue value, Deprecated::ScriptValue& result) -{ - result = Deprecated::ScriptValue(exec->vm(), value); -} - -void JSDictionary::convertValue(ExecState* exec, JSValue value, RefPtr<SerializedScriptValue>& result) -{ - result = SerializedScriptValue::create(exec, value, 0, 0); -} - -void JSDictionary::convertValue(ExecState*, JSValue value, RefPtr<DOMWindow>& result) -{ - result = toDOMWindow(value); -} - -void JSDictionary::convertValue(ExecState*, JSValue value, RefPtr<EventTarget>& result) -{ - result = toEventTarget(value); -} - -void JSDictionary::convertValue(ExecState*, JSValue value, RefPtr<Node>& result) -{ - result = toNode(value); -} - -void JSDictionary::convertValue(ExecState*, JSValue value, RefPtr<Storage>& result) -{ - result = toStorage(value); -} - -void JSDictionary::convertValue(ExecState* exec, JSValue value, MessagePortArray& result) -{ - ArrayBufferArray arrayBuffers; - fillMessagePortArray(exec, value, result, arrayBuffers); -} - -#if ENABLE(VIDEO_TRACK) -void JSDictionary::convertValue(ExecState*, JSValue value, RefPtr<TrackBase>& result) -{ - result = toTrack(value); -} -#endif - -void JSDictionary::convertValue(ExecState* exec, JSValue value, HashSet<AtomicString>& result) -{ - result.clear(); - - if (value.isUndefinedOrNull()) - return; - - unsigned length = 0; - JSObject* object = toJSSequence(exec, value, length); - if (exec->hadException()) - return; - - for (unsigned i = 0 ; i < length; ++i) { - JSValue itemValue = object->get(exec, i); - if (exec->hadException()) - return; - result.add(itemValue.toString(exec)->value(exec)); - } -} - -void JSDictionary::convertValue(ExecState* exec, JSValue value, ArrayValue& result) -{ - if (value.isUndefinedOrNull()) - return; - - result = ArrayValue(exec, value); -} - -void JSDictionary::convertValue(JSC::ExecState*, JSC::JSValue value, RefPtr<Uint8Array>& result) -{ - result = toUint8Array(value); -} - -#if ENABLE(ENCRYPTED_MEDIA) -void JSDictionary::convertValue(JSC::ExecState*, JSC::JSValue value, RefPtr<MediaKeyError>& result) -{ - result = toMediaKeyError(value); -} -#endif - -#if ENABLE(MEDIA_STREAM) -void JSDictionary::convertValue(JSC::ExecState*, JSC::JSValue value, RefPtr<MediaStream>& result) -{ - result = toMediaStream(value); -} - -void JSDictionary::convertValue(JSC::ExecState*, JSC::JSValue value, RefPtr<MediaStreamTrack>& result) -{ - result = toMediaStreamTrack(value); -} -#endif - -#if ENABLE(FONT_LOAD_EVENTS) -void JSDictionary::convertValue(JSC::ExecState*, JSC::JSValue value, RefPtr<CSSFontFaceRule>& result) -{ - result = toCSSFontFaceRule(value); -} - -void JSDictionary::convertValue(JSC::ExecState*, JSC::JSValue value, RefPtr<DOMError>& result) -{ - result = toDOMError(value); -} - -void JSDictionary::convertValue(JSC::ExecState* exec, JSC::JSValue value, RefPtr<VoidCallback>& result) -{ - if (!value.isFunction()) - return; - - result = JSVoidCallback::create(asObject(value), jsCast<JSDOMGlobalObject*>(exec->lexicalGlobalObject())); -} -#endif - -#if ENABLE(SCRIPTED_SPEECH) -void JSDictionary::convertValue(JSC::ExecState*, JSC::JSValue value, RefPtr<SpeechRecognitionResultList>& result) -{ - result = toSpeechRecognitionResultList(value); -} -#endif - -bool JSDictionary::getWithUndefinedOrNullCheck(const String& propertyName, String& result) const -{ - ASSERT(isValid()); - JSValue value; - if (tryGetProperty(propertyName.utf8().data(), value) != PropertyFound || value.isUndefinedOrNull()) - return false; - - result = value.toWTFString(m_exec); - return true; -} - -} // namespace WebCore diff --git a/Source/WebCore/bindings/js/JSDictionary.h b/Source/WebCore/bindings/js/JSDictionary.h deleted file mode 100644 index 3a8e2cc6f..000000000 --- a/Source/WebCore/bindings/js/JSDictionary.h +++ /dev/null @@ -1,193 +0,0 @@ -/* - * Copyright (C) 2011 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS - * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef JSDictionary_h -#define JSDictionary_h - -#include "MessagePort.h" -#include <heap/Strong.h> -#include <heap/StrongInlines.h> -#include <interpreter/CallFrame.h> -#include <runtime/Operations.h> -#include <runtime/Uint8Array.h> -#include <wtf/Forward.h> - -namespace Deprecated { -class ScriptValue; -} - -namespace WebCore { - -class ArrayValue; -class CSSFontFaceRule; -class Dictionary; -class DOMError; -class DOMWindow; -class EventTarget; -class MediaKeyError; -class MediaStream; -class MediaStreamTrack; -class Node; -class SerializedScriptValue; -class Storage; -class TrackBase; -class VoidCallback; - -#if ENABLE(SCRIPTED_SPEECH) -class SpeechRecognitionResultList; -#endif - -class JSDictionary { -public: - JSDictionary(JSC::ExecState* exec, JSC::JSObject* initializerObject) - : m_exec(exec) - { - if (exec && initializerObject) - m_initializerObject = JSC::Strong<JSC::JSObject>(exec->vm(), initializerObject); - } - - // Returns false if any exceptions were thrown, regardless of whether the property was found. - template <typename Result> - bool tryGetProperty(const char* propertyName, Result&) const; - template <typename T, typename Result> - bool tryGetProperty(const char* propertyName, T* context, void (*setter)(T* context, const Result&)) const; - - // Returns true if the property was found in the dictionary, and the value could be converted to the desired type. - template <typename Result> - bool get(const char* propertyName, Result&) const; - bool getWithUndefinedOrNullCheck(const String& propertyName, String& value) const; - - JSC::ExecState* execState() const { return m_exec; } - JSC::JSObject* initializerObject() const { return m_initializerObject.get(); } - bool isValid() const { return m_exec && m_initializerObject; } - -private: - template <typename Result> - struct IdentitySetter { - static void identitySetter(Result* context, const Result& result) - { - *context = result; - } - }; - - enum GetPropertyResult { - ExceptionThrown, - NoPropertyFound, - PropertyFound - }; - - template <typename T, typename Result> - GetPropertyResult tryGetPropertyAndResult(const char* propertyName, T* context, void (*setter)(T* context, const Result&)) const; - GetPropertyResult tryGetProperty(const char* propertyName, JSC::JSValue&) const; - - static void convertValue(JSC::ExecState*, JSC::JSValue, bool& result); - static void convertValue(JSC::ExecState*, JSC::JSValue, int& result); - static void convertValue(JSC::ExecState*, JSC::JSValue, unsigned& result); - static void convertValue(JSC::ExecState*, JSC::JSValue, unsigned short& result); - static void convertValue(JSC::ExecState*, JSC::JSValue, unsigned long& result); - static void convertValue(JSC::ExecState*, JSC::JSValue, unsigned long long& result); - static void convertValue(JSC::ExecState*, JSC::JSValue, double& result); - static void convertValue(JSC::ExecState*, JSC::JSValue, Dictionary& result); - static void convertValue(JSC::ExecState*, JSC::JSValue, String& result); - static void convertValue(JSC::ExecState*, JSC::JSValue, Deprecated::ScriptValue& result); - static void convertValue(JSC::ExecState*, JSC::JSValue, Vector<String>& result); - static void convertValue(JSC::ExecState*, JSC::JSValue, RefPtr<SerializedScriptValue>& result); - static void convertValue(JSC::ExecState*, JSC::JSValue, RefPtr<DOMWindow>& result); - static void convertValue(JSC::ExecState*, JSC::JSValue, RefPtr<EventTarget>& result); - static void convertValue(JSC::ExecState*, JSC::JSValue, RefPtr<Node>& result); - static void convertValue(JSC::ExecState*, JSC::JSValue, RefPtr<Storage>& result); - static void convertValue(JSC::ExecState*, JSC::JSValue, MessagePortArray& result); -#if ENABLE(VIDEO_TRACK) - static void convertValue(JSC::ExecState*, JSC::JSValue, RefPtr<TrackBase>& result); -#endif - static void convertValue(JSC::ExecState*, JSC::JSValue, HashSet<AtomicString>& result); - static void convertValue(JSC::ExecState*, JSC::JSValue, ArrayValue& result); - static void convertValue(JSC::ExecState*, JSC::JSValue, RefPtr<JSC::Uint8Array>& result); -#if ENABLE(ENCRYPTED_MEDIA) - static void convertValue(JSC::ExecState*, JSC::JSValue, RefPtr<MediaKeyError>& result); -#endif -#if ENABLE(MEDIA_STREAM) - static void convertValue(JSC::ExecState*, JSC::JSValue, RefPtr<MediaStream>& result); - static void convertValue(JSC::ExecState*, JSC::JSValue, RefPtr<MediaStreamTrack>& result); -#endif -#if ENABLE(FONT_LOAD_EVENTS) - static void convertValue(JSC::ExecState*, JSC::JSValue, RefPtr<CSSFontFaceRule>& result); - static void convertValue(JSC::ExecState*, JSC::JSValue, RefPtr<DOMError>& result); - static void convertValue(JSC::ExecState*, JSC::JSValue, RefPtr<VoidCallback>& result); -#endif -#if ENABLE(SCRIPTED_SPEECH) - static void convertValue(JSC::ExecState*, JSC::JSValue, RefPtr<SpeechRecognitionResultList>&); -#endif - - JSC::ExecState* m_exec; - JSC::Strong<JSC::JSObject> m_initializerObject; -}; - -template <typename T, typename Result> -bool JSDictionary::tryGetProperty(const char* propertyName, T* context, void (*setter)(T* context, const Result&)) const -{ - return tryGetPropertyAndResult(propertyName, context, setter) != ExceptionThrown; -} - -template <typename Result> -bool JSDictionary::tryGetProperty(const char* propertyName, Result& finalResult) const -{ - return tryGetPropertyAndResult(propertyName, &finalResult, IdentitySetter<Result>::identitySetter) != ExceptionThrown; -} - -template <typename Result> -bool JSDictionary::get(const char* propertyName, Result& finalResult) const -{ - return tryGetPropertyAndResult(propertyName, &finalResult, IdentitySetter<Result>::identitySetter) == PropertyFound; -} - -template <typename T, typename Result> -JSDictionary::GetPropertyResult JSDictionary::tryGetPropertyAndResult(const char* propertyName, T* context, void (*setter)(T* context, const Result&)) const -{ - JSC::JSValue value; - GetPropertyResult getPropertyResult = tryGetProperty(propertyName, value); - switch (getPropertyResult) { - case ExceptionThrown: - return getPropertyResult; - case PropertyFound: { - Result result; - convertValue(m_exec, value, result); - - if (m_exec->hadException()) - return ExceptionThrown; - - setter(context, result); - break; - } - case NoPropertyFound: - break; - } - - return getPropertyResult; -} - -} // namespace WebCore - -#endif // JSDictionary_h diff --git a/Source/WebCore/bindings/js/JSDocumentCustom.cpp b/Source/WebCore/bindings/js/JSDocumentCustom.cpp index 34088ca48..a78b01844 100644 --- a/Source/WebCore/bindings/js/JSDocumentCustom.cpp +++ b/Source/WebCore/bindings/js/JSDocumentCustom.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2007, 2008, 2009, 2011 Apple Inc. All rights reserved. + * Copyright (C) 2007-2009, 2011, 2016 Apple Inc. All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -25,108 +25,138 @@ #include "FrameLoader.h" #include "HTMLDocument.h" #include "JSCanvasRenderingContext2D.h" -#if ENABLE(WEBGL) -#include "JSWebGLRenderingContext.h" -#endif +#include "JSDOMConvert.h" #include "JSDOMWindowCustom.h" #include "JSHTMLDocument.h" #include "JSLocation.h" -#include "JSTouch.h" -#include "JSTouchList.h" +#include "JSXMLDocument.h" #include "Location.h" #include "NodeTraversal.h" +#include "SVGDocument.h" #include "ScriptController.h" #include "TouchList.h" +#include "XMLDocument.h" +#include <wtf/GetPtr.h> -#if ENABLE(SVG) -#include "JSSVGDocument.h" -#include "SVGDocument.h" +#if ENABLE(WEBGL) +#include "JSWebGLRenderingContextBase.h" #endif -#include <wtf/GetPtr.h> +#if ENABLE(TOUCH_EVENTS) +#include "JSTouch.h" +#include "JSTouchList.h" +#endif using namespace JSC; namespace WebCore { -JSValue JSDocument::location(ExecState* exec) const +static inline JSValue createNewDocumentWrapper(ExecState& state, JSDOMGlobalObject& globalObject, Ref<Document>&& passedDocument) { - RefPtr<Frame> frame = impl().frame(); - if (!frame) - return jsNull(); + auto& document = passedDocument.get(); + JSObject* wrapper; + if (document.isHTMLDocument()) + wrapper = createWrapper<HTMLDocument>(&globalObject, WTFMove(passedDocument)); + else if (document.isXMLDocument()) + wrapper = createWrapper<XMLDocument>(&globalObject, WTFMove(passedDocument)); + else + wrapper = createWrapper<Document>(&globalObject, WTFMove(passedDocument)); + + reportMemoryForDocumentIfFrameless(state, document); - RefPtr<Location> location = frame->document()->domWindow()->location(); - if (JSObject* wrapper = getCachedWrapper(currentWorld(exec), location.get())) + return wrapper; +} + +JSObject* cachedDocumentWrapper(ExecState& state, JSDOMGlobalObject& globalObject, Document& document) +{ + if (auto* wrapper = getCachedWrapper(globalObject.world(), document)) return wrapper; - JSLocation* jsLocation = JSLocation::create(getDOMStructure<JSLocation>(exec->vm(), globalObject()), globalObject(), location.get()); - cacheWrapper(currentWorld(exec), location.get(), jsLocation); - return jsLocation; + auto* window = document.domWindow(); + if (!window) + return nullptr; + + // Creating a wrapper for domWindow might have created a wrapper for document as well. + return getCachedWrapper(toJSDOMWindow(state.vm(), toJS(&state, *window))->world(), document); } -void JSDocument::setLocation(ExecState* exec, JSValue value) +void reportMemoryForDocumentIfFrameless(ExecState& state, Document& document) { - String locationString = value.toString(exec)->value(exec); - if (exec->hadException()) + // Make sure the document is kept around by the window object, and works right with the back/forward cache. + if (document.frame()) return; - RefPtr<Frame> frame = impl().frame(); - if (!frame) - return; + size_t memoryCost = 0; + for (Node* node = &document; node; node = NodeTraversal::next(*node)) + memoryCost += node->approximateMemoryCost(); - if (RefPtr<Location> location = frame->document()->domWindow()->location()) - location->setHref(locationString, activeDOMWindow(exec), firstDOMWindow(exec)); + // FIXME: Adopt reportExtraMemoryVisited, and switch to reportExtraMemoryAllocated. + // https://bugs.webkit.org/show_bug.cgi?id=142595 + state.heap()->deprecatedReportExtraMemory(memoryCost); } -JSValue toJS(ExecState* exec, JSDOMGlobalObject* globalObject, Document* document) +JSValue toJSNewlyCreated(ExecState* state, JSDOMGlobalObject* globalObject, Ref<Document>&& document) { - if (!document) - return jsNull(); + return createNewDocumentWrapper(*state, *globalObject, WTFMove(document)); +} - JSObject* wrapper = getCachedWrapper(currentWorld(exec), document); - if (wrapper) +JSValue toJS(ExecState* state, JSDOMGlobalObject* globalObject, Document& document) +{ + if (auto* wrapper = cachedDocumentWrapper(*state, *globalObject, document)) return wrapper; + return toJSNewlyCreated(state, globalObject, Ref<Document>(document)); +} - if (DOMWindow* domWindow = document->domWindow()) { - globalObject = toJSDOMWindow(toJS(exec, domWindow)); - // Creating a wrapper for domWindow might have created a wrapper for document as well. - wrapper = getCachedWrapper(currentWorld(exec), document); - if (wrapper) - return wrapper; - } +#if ENABLE(TOUCH_EVENTS) +JSValue JSDocument::createTouchList(ExecState& state) +{ + VM& vm = state.vm(); + auto scope = DECLARE_THROW_SCOPE(vm); - if (document->isHTMLDocument()) - wrapper = CREATE_DOM_WRAPPER(exec, globalObject, HTMLDocument, document); -#if ENABLE(SVG) - else if (document->isSVGDocument()) - wrapper = CREATE_DOM_WRAPPER(exec, globalObject, SVGDocument, document); -#endif - else - wrapper = CREATE_DOM_WRAPPER(exec, globalObject, Document, document); - - // Make sure the document is kept around by the window object, and works right with the - // back/forward cache. - if (!document->frame()) { - size_t nodeCount = 0; - for (Node* n = document; n; n = NodeTraversal::next(n)) - nodeCount++; - - exec->heap()->reportExtraMemoryCost(nodeCount * sizeof(Node)); - } + auto touchList = TouchList::create(); - return wrapper; + for (size_t i = 0; i < state.argumentCount(); ++i) { + auto* item = JSTouch::toWrapped(vm, state.uncheckedArgument(i)); + if (!item) + return JSValue::decode(throwArgumentTypeError(state, scope, i, "touches", "Document", "createTouchList", "Touch")); + + touchList->append(*item); + } + return toJSNewlyCreated(&state, globalObject(), WTFMove(touchList)); } +#endif -#if ENABLE(TOUCH_EVENTS) -JSValue JSDocument::createTouchList(ExecState* exec) +JSValue JSDocument::getCSSCanvasContext(JSC::ExecState& state) { - RefPtr<TouchList> touchList = TouchList::create(); + VM& vm = state.vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + + if (UNLIKELY(state.argumentCount() < 4)) + return throwException(&state, scope, createNotEnoughArgumentsError(&state)); + auto contextId = state.uncheckedArgument(0).toWTFString(&state); + RETURN_IF_EXCEPTION(scope, JSValue()); + auto name = state.uncheckedArgument(1).toWTFString(&state); + RETURN_IF_EXCEPTION(scope, JSValue()); + auto width = convert<IDLLong>(state, state.uncheckedArgument(2), IntegerConversionConfiguration::Normal); + RETURN_IF_EXCEPTION(scope, JSValue()); + auto height = convert<IDLLong>(state, state.uncheckedArgument(3), IntegerConversionConfiguration::Normal); + RETURN_IF_EXCEPTION(scope, JSValue()); + + auto* context = wrapped().getCSSCanvasContext(WTFMove(contextId), WTFMove(name), WTFMove(width), WTFMove(height)); + if (!context) + return jsNull(); - for (size_t i = 0; i < exec->argumentCount(); i++) - touchList->append(toTouch(exec->argument(i))); +#if ENABLE(WEBGL) + if (is<WebGLRenderingContextBase>(*context)) + return toJS(&state, globalObject(), downcast<WebGLRenderingContextBase>(*context)); +#endif - return toJS(exec, globalObject(), touchList.release()); + return toJS(&state, globalObject(), downcast<CanvasRenderingContext2D>(*context)); +} + +void JSDocument::visitAdditionalChildren(SlotVisitor& visitor) +{ + visitor.addOpaqueRoot(static_cast<ScriptExecutionContext*>(&wrapped())); } -#endif } // namespace WebCore diff --git a/Source/WebCore/bindings/js/JSHTMLMediaElementCustom.cpp b/Source/WebCore/bindings/js/JSDocumentCustom.h index 1d40c60d8..5b60f5442 100644 --- a/Source/WebCore/bindings/js/JSHTMLMediaElementCustom.cpp +++ b/Source/WebCore/bindings/js/JSDocumentCustom.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2011 Apple Inc. All Rights Reserved. + * Copyright (C) 2015 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -23,25 +23,20 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include "config.h" -#if ENABLE(VIDEO) +#pragma once -#include "JSHTMLMediaElement.h" - -#include "JSMediaController.h" +#include "JSDOMBinding.h" +#include "JSDocument.h" namespace WebCore { -using namespace JSC; - -void JSHTMLMediaElement::setController(ExecState*, JSValue value) +template<typename From> +ALWAYS_INLINE JSDynamicCastResult<JSDocument, From> jsDocumentCast(From* value) { - // 4.8.10.11.2 Media controllers: controller attribute. - // On setting, it must first remove the element's mediagroup attribute, if any, - impl().setMediaGroup(String()); - // and then set the current media controller to the given value. - impl().setController(toMediaController(value)); + return value->type() == JSDocumentWrapperType ? JSC::jsCast<JSDynamicCastResult<JSDocument, From>>(value) : nullptr; } -} -#endif +JSC::JSObject* cachedDocumentWrapper(JSC::ExecState&, JSDOMGlobalObject&, Document&); +void reportMemoryForDocumentIfFrameless(JSC::ExecState&, Document&); + +} // namespace WebCore diff --git a/Source/WebCore/bindings/js/JSDocumentFragmentCustom.cpp b/Source/WebCore/bindings/js/JSDocumentFragmentCustom.cpp new file mode 100644 index 000000000..11557165e --- /dev/null +++ b/Source/WebCore/bindings/js/JSDocumentFragmentCustom.cpp @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2015 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "JSDocumentFragment.h" + +#include "ExceptionCode.h" +#include "JSShadowRoot.h" + +using namespace JSC; + +namespace WebCore { + +JSValue toJSNewlyCreated(ExecState*, JSDOMGlobalObject* globalObject, Ref<DocumentFragment>&& impl) +{ + if (impl->isShadowRoot()) + return createWrapper<ShadowRoot>(globalObject, WTFMove(impl)); + return createWrapper<DocumentFragment>(globalObject, WTFMove(impl)); +} + +JSValue toJS(ExecState* state, JSDOMGlobalObject* globalObject, DocumentFragment& impl) +{ + return wrap(state, globalObject, impl); +} + +} // namespace WebCore diff --git a/Source/WebCore/bindings/js/JSDynamicDowncast.h b/Source/WebCore/bindings/js/JSDynamicDowncast.h new file mode 100644 index 000000000..0160126e1 --- /dev/null +++ b/Source/WebCore/bindings/js/JSDynamicDowncast.h @@ -0,0 +1,110 @@ +/* + * Copyright (C) 2016 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +#include <runtime/JSCJSValueInlines.h> +#include <runtime/JSCellInlines.h> +#include <type_traits> + +namespace WebCore { + +template<typename To, typename From> +using JSDynamicCastResult = typename std::conditional<std::is_const<From>::value, const To, To>::type*; + +class JSNode; +template<typename From> +JSDynamicCastResult<JSNode, From> jsNodeCast(From* value); +class JSElement; +template<typename From> +JSDynamicCastResult<JSElement, From> jsElementCast(From* value); +class JSDocument; +template<typename From> +JSDynamicCastResult<JSDocument, From> jsDocumentCast(From* value); +class JSEvent; +template<typename From> +JSDynamicCastResult<JSEvent, From> jsEventCast(From* value); + +template<typename Select> +struct JSDynamicCastTrait { + template<typename To, typename From> + ALWAYS_INLINE static To cast(JSC::VM& vm, From* from) + { + return JSC::jsDynamicCast<To>(vm, from); + } +}; + +template<> +struct JSDynamicCastTrait<JSNode> { + template<typename To, typename From> + ALWAYS_INLINE static To cast(JSC::VM&, From* from) + { + return jsNodeCast(from); + } +}; + +template<> +struct JSDynamicCastTrait<JSElement> { + template<typename To, typename From> + ALWAYS_INLINE static To cast(JSC::VM&, From* from) + { + return jsElementCast(from); + } +}; + +template<> +struct JSDynamicCastTrait<JSDocument> { + template<typename To, typename From> + ALWAYS_INLINE static To cast(JSC::VM&, From* from) + { + return jsDocumentCast(from); + } +}; + +template<> +struct JSDynamicCastTrait<JSEvent> { + template<typename To, typename From> + ALWAYS_INLINE static To cast(JSC::VM&, From* from) + { + return jsEventCast(from); + } +}; + +template<typename To, typename From> +ALWAYS_INLINE To jsDynamicDowncast(JSC::VM& vm, From* from) +{ + typedef JSDynamicCastTrait<typename std::remove_cv<typename std::remove_pointer<To>::type>::type> Dispatcher; + return Dispatcher::template cast<To>(vm, from); +} + +template<typename To> +ALWAYS_INLINE To jsDynamicDowncast(JSC::VM& vm, JSC::JSValue from) +{ + if (UNLIKELY(!from.isCell())) + return nullptr; + return jsDynamicDowncast<To>(vm, from.asCell()); +} + +} diff --git a/Source/WebCore/bindings/js/JSElementCustom.cpp b/Source/WebCore/bindings/js/JSElementCustom.cpp index 021f0a683..91bb3e0d9 100644 --- a/Source/WebCore/bindings/js/JSElementCustom.cpp +++ b/Source/WebCore/bindings/js/JSElementCustom.cpp @@ -10,7 +10,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of + * 3. Neither the name of Apple Inc. ("Apple") nor the names of * its contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * @@ -38,12 +38,9 @@ #include "JSDOMBinding.h" #include "JSHTMLElementWrapperFactory.h" #include "JSNodeList.h" -#include "NodeList.h" - -#if ENABLE(SVG) #include "JSSVGElementWrapperFactory.h" +#include "NodeList.h" #include "SVGElement.h" -#endif using namespace JSC; @@ -51,24 +48,28 @@ namespace WebCore { using namespace HTMLNames; -JSValue toJSNewlyCreated(ExecState* exec, JSDOMGlobalObject* globalObject, Element* element) +static JSValue createNewElementWrapper(JSDOMGlobalObject* globalObject, Ref<Element>&& element) { - if (!element) - return jsNull(); - - ASSERT(!getCachedWrapper(currentWorld(exec), element)); + if (is<HTMLElement>(element.get())) + return createJSHTMLWrapper(globalObject, static_reference_cast<HTMLElement>(WTFMove(element))); + if (is<SVGElement>(element.get())) + return createJSSVGWrapper(globalObject, static_reference_cast<SVGElement>(WTFMove(element))); + return createWrapper<Element>(globalObject, WTFMove(element)); +} - JSDOMWrapper* wrapper; - if (element->isHTMLElement()) - wrapper = createJSHTMLWrapper(exec, globalObject, toHTMLElement(element)); -#if ENABLE(SVG) - else if (element->isSVGElement()) - wrapper = createJSSVGWrapper(exec, globalObject, toSVGElement(element)); -#endif - else - wrapper = CREATE_DOM_WRAPPER(exec, globalObject, Element, element); +JSValue toJS(ExecState*, JSDOMGlobalObject* globalObject, Element& element) +{ + if (auto* wrapper = getCachedWrapper(globalObject->world(), element)) + return wrapper; + return createNewElementWrapper(globalObject, element); +} - return wrapper; +JSValue toJSNewlyCreated(ExecState*, JSDOMGlobalObject* globalObject, Ref<Element>&& element) +{ + if (element->isDefinedCustomElement()) + return getCachedWrapper(globalObject->world(), element); + ASSERT(!getCachedWrapper(globalObject->world(), element)); + return createNewElementWrapper(globalObject, WTFMove(element)); } } // namespace WebCore diff --git a/Source/WebCore/bindings/js/JSElementCustom.h b/Source/WebCore/bindings/js/JSElementCustom.h new file mode 100644 index 000000000..b2b65f53a --- /dev/null +++ b/Source/WebCore/bindings/js/JSElementCustom.h @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2014 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +#include "JSDOMBinding.h" +#include "JSElement.h" + +namespace WebCore { + +template<typename From> +ALWAYS_INLINE JSDynamicCastResult<JSElement, From> jsElementCast(From* value) +{ + return value->type() >= JSElementType ? JSC::jsCast<JSDynamicCastResult<JSElement, From>>(value) : nullptr; +} + +} // namespace WebCore diff --git a/Source/WebCore/bindings/js/JSErrorHandler.cpp b/Source/WebCore/bindings/js/JSErrorHandler.cpp index f72c334bd..a99c808fa 100644 --- a/Source/WebCore/bindings/js/JSErrorHandler.cpp +++ b/Source/WebCore/bindings/js/JSErrorHandler.cpp @@ -30,15 +30,15 @@ */ #include "config.h" - #include "JSErrorHandler.h" #include "Document.h" #include "ErrorEvent.h" #include "Event.h" -#include "EventNames.h" +#include "JSDOMConvert.h" #include "JSEvent.h" #include "JSMainThreadExecState.h" +#include "JSMainThreadExecStateInstrumentation.h" #include <runtime/JSLock.h> #include <runtime/VMEntryScope.h> #include <wtf/Ref.h> @@ -58,15 +58,14 @@ JSErrorHandler::~JSErrorHandler() void JSErrorHandler::handleEvent(ScriptExecutionContext* scriptExecutionContext, Event* event) { - - if (event->eventInterface() != ErrorEventInterfaceType) + if (!is<ErrorEvent>(*event)) return JSEventListener::handleEvent(scriptExecutionContext, event); ASSERT(scriptExecutionContext); if (!scriptExecutionContext) return; - ErrorEvent* errorEvent = static_cast<ErrorEvent*>(event); + ErrorEvent& errorEvent = downcast<ErrorEvent>(*event); JSLockHolder lock(scriptExecutionContext->vm()); @@ -83,29 +82,35 @@ void JSErrorHandler::handleEvent(ScriptExecutionContext* scriptExecutionContext, CallData callData; CallType callType = jsFunction->methodTable()->getCallData(jsFunction, callData); - if (callType != CallTypeNone) { - Ref<JSErrorHandler> protectedctor(*this); + if (callType != CallType::None) { + Ref<JSErrorHandler> protectedThis(*this); Event* savedEvent = globalObject->currentEvent(); globalObject->setCurrentEvent(event); MarkedArgumentBuffer args; - args.append(jsStringWithCache(exec, errorEvent->message())); - args.append(jsStringWithCache(exec, errorEvent->filename())); - args.append(jsNumber(errorEvent->lineno())); - args.append(jsNumber(errorEvent->colno())); + args.append(toJS<IDLDOMString>(*exec, errorEvent.message())); + args.append(toJS<IDLUSVString>(*exec, errorEvent.filename())); + args.append(toJS<IDLUnsignedLong>(errorEvent.lineno())); + args.append(toJS<IDLUnsignedLong>(errorEvent.colno())); + args.append(errorEvent.error(*exec, *globalObject)); VM& vm = globalObject->vm(); VMEntryScope entryScope(vm, vm.entryScope ? vm.entryScope->globalObject() : globalObject); + InspectorInstrumentationCookie cookie = JSMainThreadExecState::instrumentFunctionCall(scriptExecutionContext, callType, callData); + + NakedPtr<JSC::Exception> exception; JSValue returnValue = scriptExecutionContext->isDocument() - ? JSMainThreadExecState::call(exec, jsFunction, callType, callData, globalObject, args) - : JSC::call(exec, jsFunction, callType, callData, globalObject, args); + ? JSMainThreadExecState::profiledCall(exec, JSC::ProfilingReason::Other, jsFunction, callType, callData, globalObject, args, exception) + : JSC::profiledCall(exec, JSC::ProfilingReason::Other, jsFunction, callType, callData, globalObject, args, exception); + + InspectorInstrumentation::didCallFunction(cookie, scriptExecutionContext); globalObject->setCurrentEvent(savedEvent); - if (exec->hadException()) - reportCurrentException(exec); + if (exception) + reportException(exec, exception); else { if (returnValue.isTrue()) event->preventDefault(); diff --git a/Source/WebCore/bindings/js/JSErrorHandler.h b/Source/WebCore/bindings/js/JSErrorHandler.h index 55d2d53e0..ba01c0e0b 100644 --- a/Source/WebCore/bindings/js/JSErrorHandler.h +++ b/Source/WebCore/bindings/js/JSErrorHandler.h @@ -28,37 +28,34 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef JSErrorHandler_h -#define JSErrorHandler_h +#pragma once #include "JSEventListener.h" namespace WebCore { -class JSErrorHandler : public JSEventListener { +class JSErrorHandler final : public JSEventListener { public: - static PassRefPtr<JSErrorHandler> create(JSC::JSObject* listener, JSC::JSObject* wrapper, bool isAttribute, DOMWrapperWorld& world) + static Ref<JSErrorHandler> create(JSC::JSObject* listener, JSC::JSObject* wrapper, bool isAttribute, DOMWrapperWorld& world) { - return adoptRef(new JSErrorHandler(listener, wrapper, isAttribute, world)); + return adoptRef(*new JSErrorHandler(listener, wrapper, isAttribute, world)); } virtual ~JSErrorHandler(); private: JSErrorHandler(JSC::JSObject* function, JSC::JSObject* wrapper, bool isAttribute, DOMWrapperWorld&); - virtual void handleEvent(ScriptExecutionContext*, Event*); + void handleEvent(ScriptExecutionContext*, Event*) final; }; // Creates a JS EventListener for "onerror" event handler in worker context. It has custom implementation because // unlike other event listeners it accepts three parameters. -inline PassRefPtr<JSErrorHandler> createJSErrorHandler(JSC::ExecState* exec, JSC::JSValue listener, JSC::JSObject* wrapper) +inline RefPtr<JSErrorHandler> createJSErrorHandler(JSC::ExecState* exec, JSC::JSValue listener, JSC::JSObject* wrapper) { if (!listener.isObject()) - return 0; + return nullptr; return JSErrorHandler::create(asObject(listener), wrapper, true, currentWorld(exec)); } } // namespace WebCore - -#endif // JSErrorHandler_h diff --git a/Source/WebCore/bindings/js/JSEventCustom.cpp b/Source/WebCore/bindings/js/JSEventCustom.cpp index e1698db17..72917973f 100644 --- a/Source/WebCore/bindings/js/JSEventCustom.cpp +++ b/Source/WebCore/bindings/js/JSEventCustom.cpp @@ -10,7 +10,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of + * 3. Neither the name of Apple Inc. ("Apple") nor the names of * its contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * @@ -29,45 +29,35 @@ #include "config.h" #include "JSEvent.h" -#include "Clipboard.h" +#include "DataTransfer.h" #include "Event.h" #include "EventHeaders.h" #include "EventInterfaces.h" -#include "EventNames.h" -#include "JSClipboard.h" +#include "JSDOMBinding.h" +#include "JSDataTransfer.h" #include <runtime/JSLock.h> -#include <wtf/HashMap.h> #include <wtf/text/AtomicString.h> using namespace JSC; namespace WebCore { -JSValue JSEvent::clipboardData(ExecState* exec) const -{ - return impl().isClipboardEvent() ? toJS(exec, globalObject(), impl().clipboardData()) : jsUndefined(); -} - #define TRY_TO_WRAP_WITH_INTERFACE(interfaceName) \ case interfaceName##InterfaceType: \ - return CREATE_DOM_WRAPPER(exec, globalObject, interfaceName, event); + return createWrapper<interfaceName>(globalObject, WTFMove(event)); -JSValue toJS(ExecState* exec, JSDOMGlobalObject* globalObject, Event* event) +JSValue toJSNewlyCreated(ExecState*, JSDOMGlobalObject* globalObject, Ref<Event>&& event) { - JSLockHolder lock(exec); - - if (!event) - return jsNull(); - - JSObject* wrapper = getCachedWrapper(currentWorld(exec), event); - if (wrapper) - return wrapper; - switch (event->eventInterface()) { DOM_EVENT_INTERFACES_FOR_EACH(TRY_TO_WRAP_WITH_INTERFACE) } - return CREATE_DOM_WRAPPER(exec, globalObject, Event, event); + return createWrapper<Event>(globalObject, WTFMove(event)); +} + +JSValue toJS(ExecState* state, JSDOMGlobalObject* globalObject, Event& event) +{ + return wrap(state, globalObject, event); } #undef TRY_TO_WRAP_WITH_INTERFACE diff --git a/Source/WebCore/bindings/js/ScriptProfileNode.h b/Source/WebCore/bindings/js/JSEventCustom.h index 2b9ec5beb..2b85293c4 100644 --- a/Source/WebCore/bindings/js/ScriptProfileNode.h +++ b/Source/WebCore/bindings/js/JSEventCustom.h @@ -1,6 +1,5 @@ /* - * Copyright (C) 2010 Apple Inc. All rights reserved. - * Copyright (C) 2010 Google Inc. All rights reserved. + * Copyright (C) 2016 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -11,10 +10,10 @@ * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * - * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR @@ -24,15 +23,16 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef ScriptProfileNode_h -#define ScriptProfileNode_h +#pragma once -#include <profiler/ProfileNode.h> +#include "JSDOMBinding.h" namespace WebCore { -typedef JSC::ProfileNode ScriptProfileNode; +template<typename From> +ALWAYS_INLINE JSDynamicCastResult<JSEvent, From> jsEventCast(From* value) +{ + return value->type() == JSEventType ? JSC::jsCast<JSDynamicCastResult<JSEvent, From>>(value) : nullptr; +} } // namespace WebCore - -#endif // ScriptProfileNode_h diff --git a/Source/WebCore/bindings/js/JSEventListener.cpp b/Source/WebCore/bindings/js/JSEventListener.cpp index 00d16c849..621a210bb 100644 --- a/Source/WebCore/bindings/js/JSEventListener.cpp +++ b/Source/WebCore/bindings/js/JSEventListener.cpp @@ -1,6 +1,6 @@ /* * Copyright (C) 2001 Peter Kelly (pmk@post.com) - * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2013 Apple Inc. All Rights Reserved. + * Copyright (C) 2003-2017 Apple Inc. All Rights Reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -21,9 +21,12 @@ #include "JSEventListener.h" #include "BeforeUnloadEvent.h" +#include "ContentSecurityPolicy.h" #include "Event.h" #include "Frame.h" -#include "InspectorCounters.h" +#include "HTMLElement.h" +#include "JSDOMConvert.h" +#include "JSDocument.h" #include "JSEvent.h" #include "JSEventTarget.h" #include "JSMainThreadExecState.h" @@ -33,8 +36,8 @@ #include <runtime/ExceptionHelpers.h> #include <runtime/JSLock.h> #include <runtime/VMEntryScope.h> +#include <runtime/Watchdog.h> #include <wtf/Ref.h> -#include <wtf/RefCountedLeakCounter.h> using namespace JSC; @@ -44,28 +47,22 @@ JSEventListener::JSEventListener(JSObject* function, JSObject* wrapper, bool isA : EventListener(JSEventListenerType) , m_wrapper(wrapper) , m_isAttribute(isAttribute) - , m_isolatedWorld(&isolatedWorld) + , m_isolatedWorld(isolatedWorld) { if (wrapper) { - JSC::Heap::writeBarrier(wrapper, function); + JSC::Heap::heap(wrapper)->writeBarrier(wrapper, function); m_jsFunction = JSC::Weak<JSC::JSObject>(function); } else ASSERT(!function); -#if ENABLE(INSPECTOR) - ThreadLocalInspectorCounters::current().incrementCounter(ThreadLocalInspectorCounters::JSEventListenerCounter); -#endif } JSEventListener::~JSEventListener() { -#if ENABLE(INSPECTOR) - ThreadLocalInspectorCounters::current().decrementCounter(ThreadLocalInspectorCounters::JSEventListenerCounter); -#endif } JSObject* JSEventListener::initializeJSFunction(ScriptExecutionContext*) const { - return 0; + return nullptr; } void JSEventListener::visitJSFunction(SlotVisitor& visitor) @@ -74,7 +71,17 @@ void JSEventListener::visitJSFunction(SlotVisitor& visitor) if (!m_wrapper) return; - visitor.appendUnbarrieredWeak(&m_jsFunction); + visitor.append(m_jsFunction); +} + +static void handleBeforeUnloadEventReturnValue(BeforeUnloadEvent& event, const String& returnValue) +{ + if (returnValue.isNull()) + return; + + event.preventDefault(); + if (event.returnValue().isEmpty()) + event.setReturnValue(returnValue); } void JSEventListener::handleEvent(ScriptExecutionContext* scriptExecutionContext, Event* event) @@ -83,22 +90,29 @@ void JSEventListener::handleEvent(ScriptExecutionContext* scriptExecutionContext if (!scriptExecutionContext || scriptExecutionContext->isJSExecutionForbidden()) return; - JSLockHolder lock(scriptExecutionContext->vm()); + VM& vm = scriptExecutionContext->vm(); + JSLockHolder lock(vm); + auto scope = DECLARE_CATCH_SCOPE(vm); + // See https://dom.spec.whatwg.org/#dispatching-events spec on calling handleEvent. + // "If this throws an exception, report the exception." It should not propagate the + // exception. JSObject* jsFunction = this->jsFunction(scriptExecutionContext); if (!jsFunction) return; - JSDOMGlobalObject* globalObject = toJSDOMGlobalObject(scriptExecutionContext, *m_isolatedWorld); + JSDOMGlobalObject* globalObject = toJSDOMGlobalObject(scriptExecutionContext, m_isolatedWorld); if (!globalObject) return; if (scriptExecutionContext->isDocument()) { JSDOMWindow* window = jsCast<JSDOMWindow*>(globalObject); - if (!window->impl().isCurrentlyDisplayedInFrame()) + if (!window->wrapped().isCurrentlyDisplayedInFrame()) + return; + if (wasCreatedFromMarkup() && !scriptExecutionContext->contentSecurityPolicy()->allowInlineEventHandlers(sourceURL(), sourcePosition().m_line)) return; // FIXME: Is this check needed for other contexts? - ScriptController& script = window->impl().frame()->script(); + ScriptController& script = window->wrapped().frame()->script(); if (!script.canExecuteScripts(AboutToExecuteScript) || script.isPaused()) return; } @@ -109,13 +123,21 @@ void JSEventListener::handleEvent(ScriptExecutionContext* scriptExecutionContext CallData callData; CallType callType = getCallData(handleEventFunction, callData); // If jsFunction is not actually a function, see if it implements the EventListener interface and use that - if (callType == CallTypeNone) { - handleEventFunction = jsFunction->get(exec, Identifier(exec, "handleEvent")); + if (callType == CallType::None) { + handleEventFunction = jsFunction->get(exec, Identifier::fromString(exec, "handleEvent")); + if (UNLIKELY(scope.exception())) { + auto* exception = scope.exception(); + scope.clearException(); + + event->target()->uncaughtExceptionInEventHandler(); + reportException(exec, exception); + return; + } callType = getCallData(handleEventFunction, callData); } - if (callType != CallTypeNone) { - Ref<JSEventListener> protect(*this); + if (callType != CallType::None) { + Ref<JSEventListener> protectedThis(*this); MarkedArgumentBuffer args; args.append(toJS(exec, globalObject, event)); @@ -123,32 +145,34 @@ void JSEventListener::handleEvent(ScriptExecutionContext* scriptExecutionContext Event* savedEvent = globalObject->currentEvent(); globalObject->setCurrentEvent(event); - VM& vm = globalObject->vm(); VMEntryScope entryScope(vm, vm.entryScope ? vm.entryScope->globalObject() : globalObject); InspectorInstrumentationCookie cookie = JSMainThreadExecState::instrumentFunctionCall(scriptExecutionContext, callType, callData); JSValue thisValue = handleEventFunction == jsFunction ? toJS(exec, globalObject, event->currentTarget()) : jsFunction; + NakedPtr<JSC::Exception> exception; JSValue retval = scriptExecutionContext->isDocument() - ? JSMainThreadExecState::call(exec, handleEventFunction, callType, callData, thisValue, args) - : JSC::call(exec, handleEventFunction, callType, callData, thisValue, args); + ? JSMainThreadExecState::profiledCall(exec, JSC::ProfilingReason::Other, handleEventFunction, callType, callData, thisValue, args, exception) + : JSC::profiledCall(exec, JSC::ProfilingReason::Other, handleEventFunction, callType, callData, thisValue, args, exception); - InspectorInstrumentation::didCallFunction(cookie); + InspectorInstrumentation::didCallFunction(cookie, scriptExecutionContext); globalObject->setCurrentEvent(savedEvent); - if (scriptExecutionContext->isWorkerGlobalScope()) { - bool terminatorCausedException = (exec->hadException() && isTerminatedExecutionException(exec->exception())); - if (terminatorCausedException || vm.watchdog.didFire()) - static_cast<WorkerGlobalScope*>(scriptExecutionContext)->script()->forbidExecution(); + if (is<WorkerGlobalScope>(*scriptExecutionContext)) { + auto scriptController = downcast<WorkerGlobalScope>(*scriptExecutionContext).script(); + bool terminatorCausedException = (scope.exception() && isTerminatedExecutionException(vm, scope.exception())); + if (terminatorCausedException || scriptController->isTerminatingExecution()) + scriptController->forbidExecution(); } - if (exec->hadException()) { + if (exception) { event->target()->uncaughtExceptionInEventHandler(); - reportCurrentException(exec); + reportException(exec, exception); } else { - if (!retval.isUndefinedOrNull() && event->isBeforeUnloadEvent()) - toBeforeUnloadEvent(event)->setReturnValue(retval.toString(exec)->value(exec)); + if (is<BeforeUnloadEvent>(*event)) + handleBeforeUnloadEventReturnValue(downcast<BeforeUnloadEvent>(*event), convert<IDLNullable<IDLDOMString>>(*exec, retval, StringConversionConfiguration::Normal)); + if (m_isAttribute) { if (retval.isFalse()) event->preventDefault(); @@ -162,11 +186,91 @@ bool JSEventListener::virtualisAttribute() const return m_isAttribute; } -bool JSEventListener::operator==(const EventListener& listener) +bool JSEventListener::operator==(const EventListener& listener) const { if (const JSEventListener* jsEventListener = JSEventListener::cast(&listener)) return m_jsFunction == jsEventListener->m_jsFunction && m_isAttribute == jsEventListener->m_isAttribute; return false; } +static inline JSC::JSValue eventHandlerAttribute(EventListener* abstractListener, ScriptExecutionContext& context) +{ + if (!abstractListener) + return jsNull(); + + auto* listener = JSEventListener::cast(abstractListener); + if (!listener) + return jsNull(); + + auto* function = listener->jsFunction(&context); + if (!function) + return jsNull(); + + return function; +} + +static inline RefPtr<JSEventListener> createEventListenerForEventHandlerAttribute(JSC::ExecState& state, JSC::JSValue listener, JSC::JSObject& wrapper) +{ + if (!listener.isObject()) + return nullptr; + return JSEventListener::create(asObject(listener), &wrapper, true, currentWorld(&state)); +} + +JSC::JSValue eventHandlerAttribute(EventTarget& target, const AtomicString& eventType, DOMWrapperWorld& isolatedWorld) +{ + return eventHandlerAttribute(target.attributeEventListener(eventType, isolatedWorld), *target.scriptExecutionContext()); +} + +void setEventHandlerAttribute(JSC::ExecState& state, JSC::JSObject& wrapper, EventTarget& target, const AtomicString& eventType, JSC::JSValue value) +{ + target.setAttributeEventListener(eventType, createEventListenerForEventHandlerAttribute(state, value, wrapper), currentWorld(&state)); +} + +JSC::JSValue windowEventHandlerAttribute(HTMLElement& element, const AtomicString& eventType, DOMWrapperWorld& isolatedWorld) +{ + auto& document = element.document(); + return eventHandlerAttribute(document.getWindowAttributeEventListener(eventType, isolatedWorld), document); +} + +void setWindowEventHandlerAttribute(JSC::ExecState& state, JSC::JSObject& wrapper, HTMLElement& element, const AtomicString& eventType, JSC::JSValue value) +{ + ASSERT(wrapper.globalObject()); + element.document().setWindowAttributeEventListener(eventType, createEventListenerForEventHandlerAttribute(state, value, *wrapper.globalObject()), currentWorld(&state)); +} + +JSC::JSValue windowEventHandlerAttribute(DOMWindow& window, const AtomicString& eventType, DOMWrapperWorld& isolatedWorld) +{ + return eventHandlerAttribute(window, eventType, isolatedWorld); +} + +void setWindowEventHandlerAttribute(JSC::ExecState& state, JSC::JSObject& wrapper, DOMWindow& window, const AtomicString& eventType, JSC::JSValue value) +{ + setEventHandlerAttribute(state, wrapper, window, eventType, value); +} + +JSC::JSValue documentEventHandlerAttribute(HTMLElement& element, const AtomicString& eventType, DOMWrapperWorld& isolatedWorld) +{ + auto& document = element.document(); + return eventHandlerAttribute(document.attributeEventListener(eventType, isolatedWorld), document); +} + +void setDocumentEventHandlerAttribute(JSC::ExecState& state, JSC::JSObject& wrapper, HTMLElement& element, const AtomicString& eventType, JSC::JSValue value) +{ + ASSERT(wrapper.globalObject()); + auto& document = element.document(); + auto* documentWrapper = JSC::jsCast<JSDocument*>(toJS(&state, JSC::jsCast<JSDOMGlobalObject*>(wrapper.globalObject()), document)); + ASSERT(documentWrapper); + document.setAttributeEventListener(eventType, createEventListenerForEventHandlerAttribute(state, value, *documentWrapper), currentWorld(&state)); +} + +JSC::JSValue documentEventHandlerAttribute(Document& document, const AtomicString& eventType, DOMWrapperWorld& isolatedWorld) +{ + return eventHandlerAttribute(document, eventType, isolatedWorld); +} + +void setDocumentEventHandlerAttribute(JSC::ExecState& state, JSC::JSObject& wrapper, Document& document, const AtomicString& eventType, JSC::JSValue value) +{ + setEventHandlerAttribute(state, wrapper, document, eventType, value); +} + } // namespace WebCore diff --git a/Source/WebCore/bindings/js/JSEventListener.h b/Source/WebCore/bindings/js/JSEventListener.h index 303ff691c..693853adb 100644 --- a/Source/WebCore/bindings/js/JSEventListener.h +++ b/Source/WebCore/bindings/js/JSEventListener.h @@ -1,6 +1,6 @@ /* * Copyright (C) 2001 Peter Kelly (pmk@post.com) - * Copyright (C) 2003, 2008, 2009 Apple Inc. All rights reserved. + * Copyright (C) 2003-2017 Apple Inc. All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -17,103 +17,129 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#ifndef JSEventListener_h -#define JSEventListener_h +#pragma once +#include "DOMWrapperWorld.h" #include "EventListener.h" -#include "JSDOMWindow.h" #include <heap/StrongInlines.h> #include <heap/Weak.h> #include <heap/WeakInlines.h> #include <wtf/Ref.h> +#include <wtf/TypeCasts.h> +#include <wtf/text/TextPosition.h> +#include <wtf/text/WTFString.h> namespace WebCore { - class JSDOMGlobalObject; +class DOMWindow; +class EventTarget; +class HTMLElement; +class JSDOMGlobalObject; - class JSEventListener : public EventListener { - public: - static PassRefPtr<JSEventListener> create(JSC::JSObject* listener, JSC::JSObject* wrapper, bool isAttribute, DOMWrapperWorld& world) - { - return adoptRef(new JSEventListener(listener, wrapper, isAttribute, world)); - } +class JSEventListener : public EventListener { +public: + static Ref<JSEventListener> create(JSC::JSObject* listener, JSC::JSObject* wrapper, bool isAttribute, DOMWrapperWorld& world) + { + return adoptRef(*new JSEventListener(listener, wrapper, isAttribute, world)); + } - static const JSEventListener* cast(const EventListener* listener) - { - return listener->type() == JSEventListenerType - ? static_cast<const JSEventListener*>(listener) - : 0; - } + static RefPtr<JSEventListener> create(JSC::JSValue listener, JSC::JSObject& wrapper, bool isAttribute, DOMWrapperWorld& world) + { + if (UNLIKELY(!listener.isObject())) + return nullptr; - virtual ~JSEventListener(); + return adoptRef(new JSEventListener(JSC::asObject(listener), &wrapper, isAttribute, world)); + } - virtual bool operator==(const EventListener& other) override; + static const JSEventListener* cast(const EventListener* listener) + { + return listener->type() == JSEventListenerType + ? static_cast<const JSEventListener*>(listener) + : nullptr; + } - // Returns true if this event listener was created for an event handler attribute, like "onload" or "onclick". - bool isAttribute() const { return m_isAttribute; } + virtual ~JSEventListener(); - JSC::JSObject* jsFunction(ScriptExecutionContext*) const; - DOMWrapperWorld& isolatedWorld() const { return *m_isolatedWorld; } + bool operator==(const EventListener& other) const override; - JSC::JSObject* wrapper() const { return m_wrapper.get(); } - void setWrapper(JSC::VM&, JSC::JSObject* wrapper) const { m_wrapper = JSC::Weak<JSC::JSObject>(wrapper); } + // Returns true if this event listener was created for an event handler attribute, like "onload" or "onclick". + bool isAttribute() const { return m_isAttribute; } - private: - virtual JSC::JSObject* initializeJSFunction(ScriptExecutionContext*) const; - virtual void visitJSFunction(JSC::SlotVisitor&) override; - virtual bool virtualisAttribute() const override; + JSC::JSObject* jsFunction(ScriptExecutionContext*) const; + DOMWrapperWorld& isolatedWorld() const { return m_isolatedWorld; } - protected: - JSEventListener(JSC::JSObject* function, JSC::JSObject* wrapper, bool isAttribute, DOMWrapperWorld&); - virtual void handleEvent(ScriptExecutionContext*, Event*) override; + JSC::JSObject* wrapper() const { return m_wrapper.get(); } + void setWrapper(JSC::VM&, JSC::JSObject* wrapper) const { m_wrapper = JSC::Weak<JSC::JSObject>(wrapper); } - private: - mutable JSC::Weak<JSC::JSObject> m_jsFunction; - mutable JSC::Weak<JSC::JSObject> m_wrapper; + virtual String sourceURL() const { return String(); } + virtual TextPosition sourcePosition() const { return TextPosition(); } - bool m_isAttribute; - RefPtr<DOMWrapperWorld> m_isolatedWorld; - }; +private: + virtual JSC::JSObject* initializeJSFunction(ScriptExecutionContext*) const; + void visitJSFunction(JSC::SlotVisitor&) override; + bool virtualisAttribute() const override; - inline JSC::JSObject* JSEventListener::jsFunction(ScriptExecutionContext* scriptExecutionContext) const - { - // initializeJSFunction can trigger code that deletes this event listener - // before we're done. It should always return 0 in this case. - Ref<JSEventListener> protect(const_cast<JSEventListener&>(*this)); - JSC::Strong<JSC::JSObject> wrapper(*m_isolatedWorld->vm(), m_wrapper.get()); - - if (!m_jsFunction) { - JSC::JSObject* function = initializeJSFunction(scriptExecutionContext); - JSC::Heap::writeBarrier(m_wrapper.get(), function); - m_jsFunction = JSC::Weak<JSC::JSObject>(function); - } - - // Verify that we have a valid wrapper protecting our function from - // garbage collection. That is except for when we're not in the normal - // world and can have zombie m_jsFunctions. - ASSERT(!m_isolatedWorld->isNormal() || m_wrapper || !m_jsFunction); - - // If m_wrapper is 0, then m_jsFunction is zombied, and should never be accessed. - if (!m_wrapper) - return 0; - - // Try to verify that m_jsFunction wasn't recycled. (Not exact, since an - // event listener can be almost anything, but this makes test-writing easier). - ASSERT(!m_jsFunction || static_cast<JSC::JSCell*>(m_jsFunction.get())->isObject()); - - return m_jsFunction.get(); - } +protected: + JSEventListener(JSC::JSObject* function, JSC::JSObject* wrapper, bool isAttribute, DOMWrapperWorld&); + void handleEvent(ScriptExecutionContext*, Event*) override; - // Creates a JS EventListener for an "onXXX" event attribute. - inline PassRefPtr<JSEventListener> createJSAttributeEventListener(JSC::ExecState* exec, JSC::JSValue listener, JSC::JSObject* wrapper) - { - if (!listener.isObject()) - return 0; +private: + mutable JSC::Weak<JSC::JSObject> m_jsFunction; + mutable JSC::Weak<JSC::JSObject> m_wrapper; - return JSEventListener::create(asObject(listener), wrapper, true, currentWorld(exec)); + bool m_isAttribute; + Ref<DOMWrapperWorld> m_isolatedWorld; +}; + +// For "onxxx" attributes that automatically set up JavaScript event listeners. +JSC::JSValue eventHandlerAttribute(EventTarget&, const AtomicString& eventType, DOMWrapperWorld&); +void setEventHandlerAttribute(JSC::ExecState&, JSC::JSObject&, EventTarget&, const AtomicString& eventType, JSC::JSValue); + +// Like the functions above, but for attributes that forward event handlers to the window object rather than setting them on the target. +JSC::JSValue windowEventHandlerAttribute(HTMLElement&, const AtomicString& eventType, DOMWrapperWorld&); +void setWindowEventHandlerAttribute(JSC::ExecState&, JSC::JSObject&, HTMLElement&, const AtomicString& eventType, JSC::JSValue); +JSC::JSValue windowEventHandlerAttribute(DOMWindow&, const AtomicString& eventType, DOMWrapperWorld&); +void setWindowEventHandlerAttribute(JSC::ExecState&, JSC::JSObject&, DOMWindow&, const AtomicString& eventType, JSC::JSValue); + +// Like the functions above, but for attributes that forward event handlers to the document rather than setting them on the target. +JSC::JSValue documentEventHandlerAttribute(HTMLElement&, const AtomicString& eventType, DOMWrapperWorld&); +void setDocumentEventHandlerAttribute(JSC::ExecState&, JSC::JSObject&, HTMLElement&, const AtomicString& eventType, JSC::JSValue); +JSC::JSValue documentEventHandlerAttribute(Document&, const AtomicString& eventType, DOMWrapperWorld&); +void setDocumentEventHandlerAttribute(JSC::ExecState&, JSC::JSObject&, Document&, const AtomicString& eventType, JSC::JSValue); + +inline JSC::JSObject* JSEventListener::jsFunction(ScriptExecutionContext* scriptExecutionContext) const +{ + // initializeJSFunction can trigger code that deletes this event listener + // before we're done. It should always return 0 in this case. + auto protect = makeRef(const_cast<JSEventListener&>(*this)); + JSC::Strong<JSC::JSObject> wrapper(m_isolatedWorld->vm(), m_wrapper.get()); + + if (!m_jsFunction) { + JSC::JSObject* function = initializeJSFunction(scriptExecutionContext); + JSC::JSObject* wrapper = m_wrapper.get(); + if (wrapper) + JSC::Heap::heap(wrapper)->writeBarrier(wrapper, function); + m_jsFunction = JSC::Weak<JSC::JSObject>(function); } + // Verify that we have a valid wrapper protecting our function from + // garbage collection. That is except for when we're not in the normal + // world and can have zombie m_jsFunctions. + ASSERT(!m_isolatedWorld->isNormal() || m_wrapper || !m_jsFunction); + + // If m_wrapper is 0, then m_jsFunction is zombied, and should never be accessed. + if (!m_wrapper) + return nullptr; + + // Try to verify that m_jsFunction wasn't recycled. (Not exact, since an + // event listener can be almost anything, but this makes test-writing easier). + ASSERT(!m_jsFunction || static_cast<JSC::JSCell*>(m_jsFunction.get())->isObject()); + + return m_jsFunction.get(); +} } // namespace WebCore -#endif // JSEventListener_h +SPECIALIZE_TYPE_TRAITS_BEGIN(WebCore::JSEventListener) +static bool isType(const WebCore::EventListener& input) { return input.type() == WebCore::JSEventListener::JSEventListenerType; } +SPECIALIZE_TYPE_TRAITS_END() diff --git a/Source/WebCore/bindings/js/JSEventTargetCustom.cpp b/Source/WebCore/bindings/js/JSEventTargetCustom.cpp index 5210f12bb..07b46899e 100644 --- a/Source/WebCore/bindings/js/JSEventTargetCustom.cpp +++ b/Source/WebCore/bindings/js/JSEventTargetCustom.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008 Apple Inc. All Rights Reserved. + * Copyright (C) 2008-2017 Apple Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -26,10 +26,15 @@ #include "config.h" #include "JSEventTarget.h" +#include "DOMWindow.h" +#include "EventTarget.h" #include "EventTargetHeaders.h" #include "EventTargetInterfaces.h" +#include "JSDOMWindow.h" #include "JSDOMWindowShell.h" #include "JSEventListener.h" +#include "JSWorkerGlobalScope.h" +#include "WorkerGlobalScope.h" using namespace JSC; @@ -37,14 +42,11 @@ namespace WebCore { #define TRY_TO_WRAP_WITH_INTERFACE(interfaceName) \ case interfaceName##EventTargetInterfaceType: \ - return toJS(exec, globalObject, static_cast<interfaceName*>(target)); + return toJS(exec, globalObject, static_cast<interfaceName&>(target)); -JSValue toJS(ExecState* exec, JSDOMGlobalObject* globalObject, EventTarget* target) +JSValue toJS(ExecState* exec, JSDOMGlobalObject* globalObject, EventTarget& target) { - if (!target) - return jsNull(); - - switch (target->eventTargetInterface()) { + switch (target.eventTargetInterface()) { DOM_EVENT_TARGET_INTERFACES_FOR_EACH(TRY_TO_WRAP_WITH_INTERFACE) } @@ -55,18 +57,34 @@ JSValue toJS(ExecState* exec, JSDOMGlobalObject* globalObject, EventTarget* targ #undef TRY_TO_WRAP_WITH_INTERFACE #define TRY_TO_UNWRAP_WITH_INTERFACE(interfaceName) \ - if (value.inherits(JS##interfaceName::info())) \ - return &jsCast<JS##interfaceName*>(asObject(value))->impl(); + if (value.inherits(vm, JS##interfaceName::info())) \ + return &jsCast<JS##interfaceName*>(asObject(value))->wrapped(); -EventTarget* toEventTarget(JSC::JSValue value) +EventTarget* JSEventTarget::toWrapped(VM& vm, JSValue value) { TRY_TO_UNWRAP_WITH_INTERFACE(DOMWindowShell) + TRY_TO_UNWRAP_WITH_INTERFACE(DOMWindow) + TRY_TO_UNWRAP_WITH_INTERFACE(WorkerGlobalScope) TRY_TO_UNWRAP_WITH_INTERFACE(EventTarget) - // FIXME: Remove this once all event targets extend EventTarget - DOM_EVENT_TARGET_INTERFACES_FOR_EACH(TRY_TO_UNWRAP_WITH_INTERFACE) - return 0; + return nullptr; } #undef TRY_TO_UNWRAP_WITH_INTERFACE +std::unique_ptr<JSEventTargetWrapper> jsEventTargetCast(VM& vm, JSValue thisValue) +{ + if (auto* target = jsDynamicDowncast<JSEventTarget*>(vm, thisValue)) + return std::make_unique<JSEventTargetWrapper>(target->wrapped(), *target); + if (auto* window = toJSDOMWindow(vm, thisValue)) + return std::make_unique<JSEventTargetWrapper>(window->wrapped(), *window); + if (auto* scope = toJSWorkerGlobalScope(vm, thisValue)) + return std::make_unique<JSEventTargetWrapper>(scope->wrapped(), *scope); + return nullptr; +} + +void JSEventTarget::visitAdditionalChildren(SlotVisitor& visitor) +{ + wrapped().visitJSEventListeners(visitor); +} + } // namespace WebCore diff --git a/Source/WebCore/bindings/js/JSEventTargetCustom.h b/Source/WebCore/bindings/js/JSEventTargetCustom.h new file mode 100644 index 000000000..7f55358d5 --- /dev/null +++ b/Source/WebCore/bindings/js/JSEventTargetCustom.h @@ -0,0 +1,78 @@ +/* + * Copyright (C) 2016 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +#include "DOMWindow.h" +#include "JSDOMBinding.h" +#include "JSDOMBindingCaller.h" +#include "JSDOMBindingSecurity.h" + +namespace WebCore { + +// Wrapper type for JSEventTarget's castedThis because JSDOMWindow and JSWorkerGlobalScope do not inherit JSEventTarget. +class JSEventTargetWrapper { + WTF_MAKE_FAST_ALLOCATED; +public: + JSEventTargetWrapper(EventTarget& wrapped, JSC::JSObject& wrapper) + : m_wrapped(wrapped) + , m_wrapper(wrapper) + { } + + EventTarget& wrapped() { return m_wrapped; } + + operator JSC::JSObject&() { return m_wrapper; } + +private: + EventTarget& m_wrapped; + JSC::JSObject& m_wrapper; +}; + +std::unique_ptr<JSEventTargetWrapper> jsEventTargetCast(JSC::VM&, JSC::JSValue thisValue); + +template<> struct BindingCaller<JSEventTarget> { + using OperationCallerFunction = JSC::EncodedJSValue(JSC::ExecState*, JSEventTargetWrapper*, JSC::ThrowScope&); + + template<OperationCallerFunction operationCaller> + static JSC::EncodedJSValue callOperation(JSC::ExecState* state, const char* operationName) + { + ASSERT(state); + JSC::VM& vm = state->vm(); + auto throwScope = DECLARE_THROW_SCOPE(vm); + + auto thisObject = jsEventTargetCast(vm, state->thisValue().toThis(state, JSC::NotStrictMode)); + if (UNLIKELY(!thisObject)) + return throwThisTypeError(*state, throwScope, "EventTarget", operationName); + + if (auto* window = thisObject->wrapped().toDOMWindow()) { + if (!window->frame() || !BindingSecurity::shouldAllowAccessToDOMWindow(state, *window, ThrowSecurityError)) + return JSC::JSValue::encode(JSC::jsUndefined()); + } + + return operationCaller(state, thisObject.get(), throwScope); + } +}; + +} // namespace WebCore diff --git a/Source/WebCore/bindings/js/JSExceptionBase.cpp b/Source/WebCore/bindings/js/JSExceptionBase.cpp index 8a51e0c97..f9238f333 100644 --- a/Source/WebCore/bindings/js/JSExceptionBase.cpp +++ b/Source/WebCore/bindings/js/JSExceptionBase.cpp @@ -27,40 +27,23 @@ #include "JSExceptionBase.h" #include "JSDOMCoreException.h" -#include "JSEventException.h" -#include "JSRangeException.h" -#include "JSXMLHttpRequestException.h" -#if ENABLE(SQL_DATABASE) -#include "SQLException.h" #include "JSSQLException.h" -#endif -#if ENABLE(SVG) #include "JSSVGException.h" -#endif #include "JSXPathException.h" +#include "SQLException.h" namespace WebCore { -ExceptionBase* toExceptionBase(JSC::JSValue value) +ExceptionBase* toExceptionBase(JSC::VM& vm, JSC::JSValue value) { - if (DOMCoreException* domException = toDOMCoreException(value)) + if (DOMCoreException* domException = JSDOMCoreException::toWrapped(vm, value)) return reinterpret_cast<ExceptionBase*>(domException); - if (RangeException* rangeException = toRangeException(value)) - return reinterpret_cast<ExceptionBase*>(rangeException); - if (EventException* eventException = toEventException(value)) - return reinterpret_cast<ExceptionBase*>(eventException); - if (XMLHttpRequestException* xmlHttpException = toXMLHttpRequestException(value)) - return reinterpret_cast<ExceptionBase*>(xmlHttpException); -#if ENABLE(SVG) - if (SVGException* svgException = toSVGException(value)) + if (SVGException* svgException = JSSVGException::toWrapped(vm, value)) return reinterpret_cast<ExceptionBase*>(svgException); -#endif - if (XPathException* pathException = toXPathException(value)) + if (XPathException* pathException = JSXPathException::toWrapped(vm, value)) return reinterpret_cast<ExceptionBase*>(pathException); -#if ENABLE(SQL_DATABASE) - if (SQLException* pathException = toSQLException(value)) + if (SQLException* pathException = JSSQLException::toWrapped(vm, value)) return reinterpret_cast<ExceptionBase*>(pathException); -#endif return 0; } diff --git a/Source/WebCore/bindings/js/JSExceptionBase.h b/Source/WebCore/bindings/js/JSExceptionBase.h index 771300293..d88141e02 100644 --- a/Source/WebCore/bindings/js/JSExceptionBase.h +++ b/Source/WebCore/bindings/js/JSExceptionBase.h @@ -23,21 +23,17 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef JSExceptionBase_h -#define JSExceptionBase_h +#pragma once namespace JSC { - class JSValue; - -} // namespace JSC +class VM; +} namespace WebCore { class ExceptionBase; -ExceptionBase* toExceptionBase(JSC::JSValue); +ExceptionBase* toExceptionBase(JSC::VM&, JSC::JSValue); } // namespace WebCore - -#endif // JSExceptionBase_h diff --git a/Source/WebCore/bindings/js/JSFileReaderCustom.cpp b/Source/WebCore/bindings/js/JSFileReaderCustom.cpp deleted file mode 100644 index f2970b27b..000000000 --- a/Source/WebCore/bindings/js/JSFileReaderCustom.cpp +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright (C) 2010 Google Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" - -#if ENABLE(BLOB) - -#include "JSFileReader.h" - -#include "FileReader.h" -#include <runtime/ArrayBuffer.h> -#include <runtime/JSArrayBuffer.h> - -using namespace JSC; - -namespace WebCore { - -JSValue JSFileReader::result(ExecState* exec) const -{ - FileReader& imp = impl(); - if (imp.readType() == FileReaderLoader::ReadAsArrayBuffer) - return toJS(exec, globalObject(), WTF::getPtr(imp.arrayBufferResult())); - return jsOwnedStringOrNull(exec, imp.stringResult()); -} - -} // namespace WebCore - -#endif // ENABLE(BLOB) diff --git a/Source/WebCore/bindings/js/JSFontFaceCustom.cpp b/Source/WebCore/bindings/js/JSFontFaceCustom.cpp new file mode 100644 index 000000000..af460e4ec --- /dev/null +++ b/Source/WebCore/bindings/js/JSFontFaceCustom.cpp @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2016 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "JSFontFace.h" + +#include "CSSFontSelector.h" +#include "CSSValue.h" +#include "CSSValueList.h" +#include "ExceptionCode.h" +#include "JSDOMConstructor.h" + +namespace WebCore { + +JSC::JSValue JSFontFace::loaded(JSC::ExecState& state) const +{ + if (!m_loaded) { + if (!wrapped().promise()) { + auto promise = createDeferredPromise(state, domWindow()); + m_loaded.set(state.vm(), this, promise->promise()); + wrapped().registerLoaded(WTFMove(promise)); + } else + m_loaded.set(state.vm(), this, wrapped().promise().value().promise()); + } + return m_loaded.get(); +} + +JSC::JSValue JSFontFace::load(JSC::ExecState& state) +{ + wrapped().load(); + return loaded(state); +} + +} diff --git a/Source/WebCore/bindings/js/JSFontFaceSetCustom.cpp b/Source/WebCore/bindings/js/JSFontFaceSetCustom.cpp new file mode 100644 index 000000000..22560d44f --- /dev/null +++ b/Source/WebCore/bindings/js/JSFontFaceSetCustom.cpp @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2016 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "JSFontFaceSet.h" + +#include "FontFace.h" +#include "JSFontFace.h" + +namespace WebCore { + +JSC::JSValue JSFontFaceSet::ready(JSC::ExecState& state) const +{ + if (!m_ready) { + auto promise = createDeferredPromise(state, domWindow()); + m_ready.set(state.vm(), this, promise->promise()); + wrapped().registerReady(WTFMove(promise)); + } + return m_ready.get(); +} + +} diff --git a/Source/WebCore/bindings/js/JSGeolocationCustom.cpp b/Source/WebCore/bindings/js/JSGeolocationCustom.cpp deleted file mode 100644 index d1a2daa1a..000000000 --- a/Source/WebCore/bindings/js/JSGeolocationCustom.cpp +++ /dev/null @@ -1,145 +0,0 @@ -/* - * Copyright (C) 2008 Apple Inc. All Rights Reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" -#include "JSGeolocation.h" - -#if ENABLE(GEOLOCATION) - -#include "CallbackFunction.h" -#include "DOMWindow.h" -#include "Geolocation.h" -#include "JSDOMWindow.h" -#include "JSDictionary.h" -#include "JSPositionCallback.h" -#include "JSPositionErrorCallback.h" -#include "PositionOptions.h" - -using namespace JSC; - -namespace WebCore { - -// JSDictionary helper functions - -static void setEnableHighAccuracy(PositionOptions* options, const bool& enableHighAccuracy) -{ - options->setEnableHighAccuracy(enableHighAccuracy); -} - -static void setTimeout(PositionOptions* options, const double& timeout) -{ - // If the value is positive infinity, there's nothing to do. - if (!(std::isinf(timeout) && (timeout > 0))) { - // Wrap to int32 and force non-negative to match behavior of window.setTimeout. - options->setTimeout(std::max<int>(0, timeout)); - } -} - -static void setMaximumAge(PositionOptions* options, const double& maximumAge) -{ - if (std::isinf(maximumAge) && (maximumAge > 0)) { - // If the value is positive infinity, clear maximumAge. - options->clearMaximumAge(); - } else { - // Wrap to int32 and force non-negative to match behavior of window.setTimeout. - options->setMaximumAge(std::max<int>(0, maximumAge)); - } -} - - -static PassRefPtr<PositionOptions> createPositionOptions(ExecState* exec, JSValue value) -{ - // Create default options. - RefPtr<PositionOptions> options = PositionOptions::create(); - - // Argument is optional (hence undefined is allowed), and null is allowed. - if (value.isUndefinedOrNull()) { - // Use default options. - return options.release(); - } - - // Given the above test, this will always yield an object. - JSObject* object = value.toObject(exec); - - // Create the dictionary wrapper from the initializer object. - JSDictionary dictionary(exec, object); - - if (!dictionary.tryGetProperty("enableHighAccuracy", options.get(), setEnableHighAccuracy)) - return 0; - if (!dictionary.tryGetProperty("timeout", options.get(), setTimeout)) - return 0; - if (!dictionary.tryGetProperty("maximumAge", options.get(), setMaximumAge)) - return 0; - - return options.release(); -} - -JSValue JSGeolocation::getCurrentPosition(ExecState* exec) -{ - // Arguments: PositionCallback, (optional)PositionErrorCallback, (optional)PositionOptions - - RefPtr<PositionCallback> positionCallback = createFunctionOnlyCallback<JSPositionCallback>(exec, globalObject(), exec->argument(0)); - if (exec->hadException()) - return jsUndefined(); - ASSERT(positionCallback); - - RefPtr<PositionErrorCallback> positionErrorCallback = createFunctionOnlyCallback<JSPositionErrorCallback>(exec, globalObject(), exec->argument(1), CallbackAllowUndefined | CallbackAllowNull); - if (exec->hadException()) - return jsUndefined(); - - RefPtr<PositionOptions> positionOptions = createPositionOptions(exec, exec->argument(2)); - if (exec->hadException()) - return jsUndefined(); - ASSERT(positionOptions); - - m_impl->getCurrentPosition(positionCallback.release(), positionErrorCallback.release(), positionOptions.release()); - return jsUndefined(); -} - -JSValue JSGeolocation::watchPosition(ExecState* exec) -{ - // Arguments: PositionCallback, (optional)PositionErrorCallback, (optional)PositionOptions - - RefPtr<PositionCallback> positionCallback = createFunctionOnlyCallback<JSPositionCallback>(exec, globalObject(), exec->argument(0)); - if (exec->hadException()) - return jsUndefined(); - ASSERT(positionCallback); - - RefPtr<PositionErrorCallback> positionErrorCallback = createFunctionOnlyCallback<JSPositionErrorCallback>(exec, globalObject(), exec->argument(1), CallbackAllowUndefined | CallbackAllowNull); - if (exec->hadException()) - return jsUndefined(); - - RefPtr<PositionOptions> positionOptions = createPositionOptions(exec, exec->argument(2)); - if (exec->hadException()) - return jsUndefined(); - ASSERT(positionOptions); - - int watchID = m_impl->watchPosition(positionCallback.release(), positionErrorCallback.release(), positionOptions.release()); - return jsNumber(watchID); -} - -} // namespace WebCore - -#endif // ENABLE(GEOLOCATION) diff --git a/Source/WebCore/bindings/js/JSHTMLAllCollectionCustom.cpp b/Source/WebCore/bindings/js/JSHTMLAllCollectionCustom.cpp index 227c34dfb..d8286a52a 100644 --- a/Source/WebCore/bindings/js/JSHTMLAllCollectionCustom.cpp +++ b/Source/WebCore/bindings/js/JSHTMLAllCollectionCustom.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2009 Apple Inc. All rights reserved. + * Copyright (C) 2009, 2016 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -27,63 +27,61 @@ #include "JSHTMLAllCollection.h" #include "HTMLAllCollection.h" -#include "JSDOMBinding.h" #include "JSNode.h" #include "JSNodeList.h" -#include "Node.h" #include "StaticNodeList.h" -#include <runtime/JSCJSValue.h> -#include <wtf/Vector.h> -#include <wtf/text/AtomicString.h> +#include <runtime/IdentifierInlines.h> using namespace JSC; namespace WebCore { -static JSValue getNamedItems(ExecState* exec, JSHTMLAllCollection* collection, PropertyName propertyName) +static JSValue namedItems(ExecState& state, JSHTMLAllCollection* collection, PropertyName propertyName) { - Vector<Ref<Element>> namedItems; - collection->impl().namedItems(propertyNameToAtomicString(propertyName), namedItems); + Vector<Ref<Element>> namedItems = collection->wrapped().namedItems(propertyNameToAtomicString(propertyName)); if (namedItems.isEmpty()) return jsUndefined(); if (namedItems.size() == 1) - return toJS(exec, collection->globalObject(), &namedItems[0].get()); + return toJS(&state, collection->globalObject(), namedItems[0]); // FIXME: HTML5 specification says this should be a HTMLCollection. // http://www.whatwg.org/specs/web-apps/current-work/multipage/common-dom-interfaces.html#htmlallcollection - return toJS(exec, collection->globalObject(), StaticElementList::adopt(namedItems).get()); + return toJS(&state, collection->globalObject(), StaticElementList::create(WTFMove(namedItems))); } // HTMLAllCollections are strange objects, they support both get and call. static EncodedJSValue JSC_HOST_CALL callHTMLAllCollection(ExecState* exec) { + VM& vm = exec->vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + if (exec->argumentCount() < 1) return JSValue::encode(jsUndefined()); // Do not use thisObj here. It can be the JSHTMLDocument, in the document.forms(i) case. - JSHTMLAllCollection* jsCollection = jsCast<JSHTMLAllCollection*>(exec->callee()); - HTMLAllCollection& collection = jsCollection->impl(); + JSHTMLAllCollection* jsCollection = jsCast<JSHTMLAllCollection*>(exec->jsCallee()); + HTMLAllCollection& collection = jsCollection->wrapped(); // Also, do we need the TypeError test here ? if (exec->argumentCount() == 1) { // Support for document.all(<index>) etc. - String string = exec->argument(0).toString(exec)->value(exec); - unsigned index = toUInt32FromStringImpl(string.impl()); - if (index != PropertyName::NotAnIndex) - return JSValue::encode(toJS(exec, jsCollection->globalObject(), collection.item(index))); + String string = exec->argument(0).toWTFString(exec); + RETURN_IF_EXCEPTION(scope, encodedJSValue()); + if (std::optional<uint32_t> index = parseIndex(*string.impl())) + return JSValue::encode(toJS(exec, jsCollection->globalObject(), collection.item(index.value()))); // Support for document.images('<name>') etc. - return JSValue::encode(getNamedItems(exec, jsCollection, Identifier(exec, string))); + return JSValue::encode(namedItems(*exec, jsCollection, Identifier::fromString(exec, string))); } // The second arg, if set, is the index of the item we want - String string = exec->argument(0).toString(exec)->value(exec); - unsigned index = toUInt32FromStringImpl(exec->argument(1).toWTFString(exec).impl()); - if (index != PropertyName::NotAnIndex) { - if (Node* node = collection.namedItemWithIndex(string, index)) - return JSValue::encode(toJS(exec, jsCollection->globalObject(), node)); + String string = exec->argument(0).toWTFString(exec); + RETURN_IF_EXCEPTION(scope, encodedJSValue()); + if (std::optional<uint32_t> index = parseIndex(*exec->argument(1).toWTFString(exec).impl())) { + if (auto* item = collection.namedItemWithIndex(string, index.value())) + return JSValue::encode(toJS(exec, jsCollection->globalObject(), *item)); } return JSValue::encode(jsUndefined()); @@ -92,31 +90,36 @@ static EncodedJSValue JSC_HOST_CALL callHTMLAllCollection(ExecState* exec) CallType JSHTMLAllCollection::getCallData(JSCell*, CallData& callData) { callData.native.function = callHTMLAllCollection; - return CallTypeHost; + return CallType::Host; } -bool JSHTMLAllCollection::canGetItemsForName(ExecState*, HTMLAllCollection* collection, PropertyName propertyName) +bool JSHTMLAllCollection::nameGetter(ExecState* state, PropertyName propertyName, JSValue& value) { - return collection->hasNamedItem(propertyNameToAtomicString(propertyName)); -} + JSValue items = namedItems(*state, this, propertyName); + if (items.isUndefined()) + return false; -EncodedJSValue JSHTMLAllCollection::nameGetter(ExecState* exec, EncodedJSValue slotBase, EncodedJSValue, PropertyName propertyName) -{ - JSHTMLAllCollection* thisObj = jsCast<JSHTMLAllCollection*>(JSValue::decode(slotBase)); - return JSValue::encode(getNamedItems(exec, thisObj, propertyName)); + value = items; + return true; } -JSValue JSHTMLAllCollection::item(ExecState* exec) +JSValue JSHTMLAllCollection::item(ExecState& state) { - uint32_t index = toUInt32FromStringImpl(exec->argument(0).toString(exec)->value(exec).impl()); - if (index != PropertyName::NotAnIndex) - return toJS(exec, globalObject(), impl().item(index)); - return getNamedItems(exec, this, Identifier(exec, exec->argument(0).toString(exec)->value(exec))); + VM& vm = state.vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + + if (UNLIKELY(state.argumentCount() < 1)) + return throwException(&state, scope, createNotEnoughArgumentsError(&state)); + + String argument = state.uncheckedArgument(0).toWTFString(&state); + if (std::optional<uint32_t> index = parseIndex(*argument.impl())) + return toJS(&state, globalObject(), wrapped().item(index.value())); + return namedItems(state, this, Identifier::fromString(&state, argument)); } -JSValue JSHTMLAllCollection::namedItem(ExecState* exec) +JSValue JSHTMLAllCollection::namedItem(ExecState& state) { - JSValue value = getNamedItems(exec, this, Identifier(exec, exec->argument(0).toString(exec)->value(exec))); + JSValue value = namedItems(state, this, Identifier::fromString(&state, state.argument(0).toWTFString(&state))); return value.isUndefined() ? jsNull() : value; } diff --git a/Source/WebCore/bindings/js/JSHTMLAppletElementCustom.cpp b/Source/WebCore/bindings/js/JSHTMLAppletElementCustom.cpp index 9994d4205..229e68399 100644 --- a/Source/WebCore/bindings/js/JSHTMLAppletElementCustom.cpp +++ b/Source/WebCore/bindings/js/JSHTMLAppletElementCustom.cpp @@ -10,10 +10,10 @@ * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * - * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR @@ -38,9 +38,9 @@ bool JSHTMLAppletElement::getOwnPropertySlotDelegate(ExecState* exec, PropertyNa return pluginElementCustomGetOwnPropertySlot<JSHTMLAppletElement, Base>(exec, propertyName, slot, this); } -bool JSHTMLAppletElement::putDelegate(ExecState* exec, PropertyName propertyName, JSValue value, PutPropertySlot& slot) +bool JSHTMLAppletElement::putDelegate(ExecState* exec, PropertyName propertyName, JSValue value, PutPropertySlot& slot, bool& putResult) { - return pluginElementCustomPut(exec, propertyName, value, this, slot); + return pluginElementCustomPut(exec, propertyName, value, this, slot, putResult); } CallType JSHTMLAppletElement::getCallData(JSCell* cell, CallData& callData) diff --git a/Source/WebCore/bindings/js/JSHTMLCanvasElementCustom.cpp b/Source/WebCore/bindings/js/JSHTMLCanvasElementCustom.cpp index 7ad36f8b2..172c0d997 100644 --- a/Source/WebCore/bindings/js/JSHTMLCanvasElementCustom.cpp +++ b/Source/WebCore/bindings/js/JSHTMLCanvasElementCustom.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2007 Apple Inc. All rights reserved. + * Copyright (C) 2007, 2016 Apple Inc. All rights reserved. * Copyright (C) 2010 Torch Mobile (Beijing) Co. Ltd. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -11,10 +11,10 @@ * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * - * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR @@ -27,119 +27,67 @@ #include "config.h" #include "JSHTMLCanvasElement.h" -#include "CanvasContextAttributes.h" #include "HTMLCanvasElement.h" -#include "InspectorCanvasInstrumentation.h" #include "JSCanvasRenderingContext2D.h" #include <bindings/ScriptObject.h> #include <wtf/GetPtr.h> #if ENABLE(WEBGL) -#include "JSDictionary.h" -#include "JSWebGLRenderingContext.h" -#include "WebGLContextAttributes.h" +#include "JSWebGLContextAttributes.h" +#include "JSWebGLRenderingContextBase.h" #endif using namespace JSC; namespace WebCore { -#if ENABLE(WEBGL) -static void get3DContextAttributes(ExecState* exec, RefPtr<CanvasContextAttributes>& attrs) +JSValue JSHTMLCanvasElement::getContext(ExecState& state) { - JSValue initializerValue = exec->argument(1); - if (initializerValue.isUndefinedOrNull()) - return; - - JSObject* initializerObject = initializerValue.toObject(exec); - JSDictionary dictionary(exec, initializerObject); - - GraphicsContext3D::Attributes graphicsAttrs; - - dictionary.tryGetProperty("alpha", graphicsAttrs.alpha); - dictionary.tryGetProperty("depth", graphicsAttrs.depth); - dictionary.tryGetProperty("stencil", graphicsAttrs.stencil); - dictionary.tryGetProperty("antialias", graphicsAttrs.antialias); - dictionary.tryGetProperty("premultipliedAlpha", graphicsAttrs.premultipliedAlpha); - dictionary.tryGetProperty("preserveDrawingBuffer", graphicsAttrs.preserveDrawingBuffer); - - attrs = WebGLContextAttributes::create(graphicsAttrs); -} -#endif + auto& vm = state.vm(); + auto scope = DECLARE_THROW_SCOPE(vm); -JSValue JSHTMLCanvasElement::getContext(ExecState* exec) -{ - HTMLCanvasElement& canvas = impl(); - const String& contextId = exec->argument(0).toString(exec)->value(exec); - - RefPtr<CanvasContextAttributes> attrs; -#if ENABLE(WEBGL) - if (HTMLCanvasElement::is3dType(contextId)) { - get3DContextAttributes(exec, attrs); - if (exec->hadException()) - return jsUndefined(); - } -#endif - - CanvasRenderingContext* context = canvas.getContext(contextId, attrs.get()); - if (!context) - return jsNull(); - JSValue jsValue = toJS(exec, globalObject(), WTF::getPtr(context)); - if (InspectorInstrumentation::canvasAgentEnabled(&canvas.document())) { - Deprecated::ScriptObject contextObject(exec, jsValue.getObject()); - Deprecated::ScriptObject wrapped; - if (context->is2d()) - wrapped = InspectorInstrumentation::wrapCanvas2DRenderingContextForInstrumentation(&canvas.document(), contextObject); -#if ENABLE(WEBGL) - else if (context->is3d()) - wrapped = InspectorInstrumentation::wrapWebGLRenderingContextForInstrumentation(&canvas.document(), contextObject); -#endif - if (!wrapped.hasNoValue()) - return wrapped.jsValue(); - } - return jsValue; -} + if (UNLIKELY(state.argumentCount() < 1)) + return throwException(&state, scope, createNotEnoughArgumentsError(&state)); + + auto contextId = convert<IDLDOMString>(state, state.uncheckedArgument(0), StringConversionConfiguration::Normal); + RETURN_IF_EXCEPTION(scope, JSValue()); + + if (HTMLCanvasElement::is2dType(contextId)) + return toJS<IDLNullable<IDLInterface<CanvasRenderingContext2D>>>(state, *globalObject(), static_cast<CanvasRenderingContext2D*>(wrapped().getContext2d(contextId))); -JSValue JSHTMLCanvasElement::probablySupportsContext(ExecState* exec) -{ - HTMLCanvasElement& canvas = impl(); - if (!exec->argumentCount()) - return jsBoolean(false); - const String& contextId = exec->uncheckedArgument(0).toString(exec)->value(exec); - if (exec->hadException()) - return jsUndefined(); - - RefPtr<CanvasContextAttributes> attrs; #if ENABLE(WEBGL) if (HTMLCanvasElement::is3dType(contextId)) { - get3DContextAttributes(exec, attrs); - if (exec->hadException()) - return jsUndefined(); + auto attributes = convert<IDLDictionary<WebGLContextAttributes>>(state, state.argument(1)); + RETURN_IF_EXCEPTION(scope, JSValue()); + + return toJS<IDLNullable<IDLInterface<WebGLRenderingContextBase>>>(state, *globalObject(), static_cast<WebGLRenderingContextBase*>(wrapped().getContextWebGL(contextId, WTFMove(attributes)))); } #endif - - return jsBoolean(canvas.probablySupportsContext(contextId, attrs.get())); + + return jsNull(); } -JSValue JSHTMLCanvasElement::toDataURL(ExecState* exec) +JSValue JSHTMLCanvasElement::toDataURL(ExecState& state) { - HTMLCanvasElement& canvas = impl(); - ExceptionCode ec = 0; - - const String& type = valueToStringWithUndefinedOrNullCheck(exec, exec->argument(0)); - double quality; - double* qualityPtr = 0; - if (exec->argumentCount() > 1) { - JSValue v = exec->uncheckedArgument(1); - if (v.isNumber()) { - quality = v.toNumber(exec); - qualityPtr = &quality; - } - } + VM& vm = state.vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + + auto type = convert<IDLNullable<IDLDOMString>>(state, state.argument(0)); + RETURN_IF_EXCEPTION(scope, JSC::JSValue()); - JSValue result = JSC::jsString(exec, canvas.toDataURL(type, qualityPtr, ec)); - setDOMException(exec, ec); - return result; + std::optional<double> quality; + auto qualityValue = state.argument(1); + if (qualityValue.isNumber()) + quality = qualityValue.toNumber(&state); + + // We would use toJS<IDLString> here, but it uses jsStringWithCache and we historically + // did not cache here, presumably because results are likely to be differing long strings. + auto result = wrapped().toDataURL(type, quality); + if (result.hasException()) { + propagateException(state, scope, result.releaseException()); + return { }; + } + return jsString(&state, result.releaseReturnValue()); } } // namespace WebCore diff --git a/Source/WebCore/bindings/js/JSHTMLCollectionCustom.cpp b/Source/WebCore/bindings/js/JSHTMLCollectionCustom.cpp index eecc08b0a..6c8c74d62 100644 --- a/Source/WebCore/bindings/js/JSHTMLCollectionCustom.cpp +++ b/Source/WebCore/bindings/js/JSHTMLCollectionCustom.cpp @@ -20,60 +20,34 @@ #include "config.h" #include "JSHTMLCollection.h" -#include "HTMLAllCollection.h" -#include "HTMLCollection.h" -#include "HTMLFormControlsCollection.h" -#include "HTMLOptionsCollection.h" #include "JSDOMBinding.h" #include "JSHTMLAllCollection.h" #include "JSHTMLFormControlsCollection.h" #include "JSHTMLOptionsCollection.h" -#include "JSNode.h" -#include "JSNodeList.h" -#include "JSRadioNodeList.h" -#include "Node.h" -#include "RadioNodeList.h" -#include <wtf/Vector.h> -#include <wtf/text/AtomicString.h> using namespace JSC; namespace WebCore { -bool JSHTMLCollection::canGetItemsForName(ExecState*, HTMLCollection* collection, PropertyName propertyName) +JSValue toJSNewlyCreated(ExecState*, JSDOMGlobalObject* globalObject, Ref<HTMLCollection>&& collection) { - return collection->hasNamedItem(propertyNameToAtomicString(propertyName)); -} - -EncodedJSValue JSHTMLCollection::nameGetter(ExecState* exec, EncodedJSValue slotBase, EncodedJSValue, PropertyName propertyName) -{ - JSHTMLCollection* collection = jsCast<JSHTMLCollection*>(JSValue::decode(slotBase)); - const AtomicString& name = propertyNameToAtomicString(propertyName); - return JSValue::encode(toJS(exec, collection->globalObject(), collection->impl().namedItem(name))); -} - -JSValue toJS(ExecState* exec, JSDOMGlobalObject* globalObject, HTMLCollection* collection) -{ - if (!collection) - return jsNull(); - - JSObject* wrapper = getCachedWrapper(currentWorld(exec), collection); - - if (wrapper) - return wrapper; - switch (collection->type()) { case FormControls: - return CREATE_DOM_WRAPPER(exec, globalObject, HTMLFormControlsCollection, collection); + return createWrapper<HTMLFormControlsCollection>(globalObject, WTFMove(collection)); case SelectOptions: - return CREATE_DOM_WRAPPER(exec, globalObject, HTMLOptionsCollection, collection); + return createWrapper<HTMLOptionsCollection>(globalObject, WTFMove(collection)); case DocAll: - return CREATE_DOM_WRAPPER(exec, globalObject, HTMLAllCollection, collection); + return createWrapper<HTMLAllCollection>(globalObject, WTFMove(collection)); default: break; } - return CREATE_DOM_WRAPPER(exec, globalObject, HTMLCollection, collection); + return createWrapper<HTMLCollection>(globalObject, WTFMove(collection)); +} + +JSValue toJS(ExecState* state, JSDOMGlobalObject* globalObject, HTMLCollection& collection) +{ + return wrap(state, globalObject, collection); } } // namespace WebCore diff --git a/Source/WebCore/bindings/js/JSHTMLDocumentCustom.cpp b/Source/WebCore/bindings/js/JSHTMLDocumentCustom.cpp index 7e7bb5a44..2003cacac 100644 --- a/Source/WebCore/bindings/js/JSHTMLDocumentCustom.cpp +++ b/Source/WebCore/bindings/js/JSHTMLDocumentCustom.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2007, 2008, 2009 Apple Inc. All rights reserved. + * Copyright (C) 2007-2016 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -10,10 +10,10 @@ * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * - * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR @@ -26,24 +26,11 @@ #include "config.h" #include "JSHTMLDocument.h" -#include "Frame.h" -#include "HTMLAllCollection.h" -#include "HTMLBodyElement.h" -#include "HTMLCollection.h" -#include "HTMLDocument.h" -#include "HTMLElement.h" #include "HTMLIFrameElement.h" -#include "HTMLNames.h" -#include "JSDOMWindow.h" #include "JSDOMWindowCustom.h" -#include "JSDOMWindowShell.h" #include "JSHTMLCollection.h" -#include "JSMainThreadExecState.h" #include "SegmentedString.h" -#include "DocumentParser.h" -#include <runtime/Error.h> -#include <runtime/JSCell.h> -#include <wtf/unicode/CharacterNames.h> +#include <runtime/Lookup.h> using namespace JSC; @@ -51,120 +38,153 @@ namespace WebCore { using namespace HTMLNames; -bool JSHTMLDocument::canGetItemsForName(ExecState*, HTMLDocument* document, PropertyName propertyName) +JSValue toJSNewlyCreated(ExecState* state, JSDOMGlobalObject* globalObject, Ref<HTMLDocument>&& passedDocument) { - AtomicStringImpl* atomicPropertyName = findAtomicString(propertyName); - return atomicPropertyName && document->hasDocumentNamedItem(*atomicPropertyName); + auto& document = passedDocument.get(); + auto* wrapper = createWrapper<HTMLDocument>(globalObject, WTFMove(passedDocument)); + reportMemoryForDocumentIfFrameless(*state, document); + return wrapper; } -EncodedJSValue JSHTMLDocument::nameGetter(ExecState* exec, EncodedJSValue slotBase, EncodedJSValue, PropertyName propertyName) +JSValue toJS(ExecState* state, JSDOMGlobalObject* globalObject, HTMLDocument& document) { - JSHTMLDocument* thisObj = jsCast<JSHTMLDocument*>(JSValue::decode(slotBase)); - HTMLDocument& document = thisObj->impl(); + if (auto* wrapper = cachedDocumentWrapper(*state, *globalObject, document)) + return wrapper; + return toJSNewlyCreated(state, globalObject, Ref<HTMLDocument>(document)); +} + +bool JSHTMLDocument::getOwnPropertySlot(JSObject* object, ExecState* state, PropertyName propertyName, PropertySlot& slot) +{ + auto& thisObject = *jsCast<JSHTMLDocument*>(object); + ASSERT_GC_OBJECT_INHERITS(object, info()); + + if (propertyName == "open") { + if (Base::getOwnPropertySlot(&thisObject, state, propertyName, slot)) + return true; + slot.setCustom(&thisObject, ReadOnly | DontDelete | DontEnum, nonCachingStaticFunctionGetter<jsHTMLDocumentPrototypeFunctionOpen, 2>); + return true; + } + + JSValue value; + if (thisObject.nameGetter(state, propertyName, value)) { + slot.setValue(&thisObject, ReadOnly | DontDelete | DontEnum, value); + return true; + } - AtomicStringImpl* atomicPropertyName = findAtomicString(propertyName); + return Base::getOwnPropertySlot(&thisObject, state, propertyName, slot); +} + +bool JSHTMLDocument::nameGetter(ExecState* state, PropertyName propertyName, JSValue& value) +{ + auto& document = wrapped(); + + auto* atomicPropertyName = propertyName.publicName(); if (!atomicPropertyName || !document.hasDocumentNamedItem(*atomicPropertyName)) - return JSValue::encode(jsUndefined()); + return false; if (UNLIKELY(document.documentNamedItemContainsMultipleElements(*atomicPropertyName))) { - RefPtr<HTMLCollection> collection = document.documentNamedItems(atomicPropertyName); + auto collection = document.documentNamedItems(atomicPropertyName); ASSERT(collection->length() > 1); - return JSValue::encode(toJS(exec, thisObj->globalObject(), WTF::getPtr(collection))); + value = toJS(state, globalObject(), collection); + return true; } - Element* element = document.documentNamedItem(*atomicPropertyName); - if (UNLIKELY(element->hasTagName(iframeTag))) { - if (Frame* frame = toHTMLIFrameElement(element)->contentFrame()) - return JSValue::encode(toJS(exec, frame)); + auto& element = *document.documentNamedItem(*atomicPropertyName); + if (UNLIKELY(is<HTMLIFrameElement>(element))) { + if (auto* frame = downcast<HTMLIFrameElement>(element).contentFrame()) { + value = toJS(state, frame); + return true; + } } - return JSValue::encode(toJS(exec, thisObj->globalObject(), element)); + value = toJS(state, globalObject(), element); + return true; } // Custom attributes -JSValue JSHTMLDocument::all(ExecState* exec) const +JSValue JSHTMLDocument::all(ExecState& state) const { // If "all" has been overwritten, return the overwritten value - JSValue v = getDirect(exec->vm(), Identifier(exec, "all")); - if (v) - return v; + if (auto overwrittenValue = getDirect(state.vm(), Identifier::fromString(&state, "all"))) + return overwrittenValue; - return toJS(exec, globalObject(), impl().all()); + return toJS(&state, globalObject(), wrapped().all()); } -void JSHTMLDocument::setAll(ExecState* exec, JSValue value) +void JSHTMLDocument::setAll(ExecState& state, JSValue value) { // Add "all" to the property map. - putDirect(exec->vm(), Identifier(exec, "all"), value); + putDirect(state.vm(), Identifier::fromString(&state, "all"), value); +} + +static inline Document* findCallingDocument(ExecState& state) +{ + CallerFunctor functor; + state.iterate(functor); + auto* callerFrame = functor.callerFrame(); + if (!callerFrame) + return nullptr; + return asJSDOMWindow(callerFrame->lexicalGlobalObject())->wrapped().document(); } // Custom functions -JSValue JSHTMLDocument::open(ExecState* exec) +JSValue JSHTMLDocument::open(ExecState& state) { + VM& vm = state.vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + // For compatibility with other browsers, pass open calls with more than 2 parameters to the window. - if (exec->argumentCount() > 2) { - if (Frame* frame = impl().frame()) { - JSDOMWindowShell* wrapper = toJSDOMWindowShell(frame, currentWorld(exec)); - if (wrapper) { - JSValue function = wrapper->get(exec, Identifier(exec, "open")); + if (state.argumentCount() > 2) { + if (auto* frame = wrapped().frame()) { + if (auto* wrapper = toJSDOMWindowShell(frame, currentWorld(&state))) { + auto function = wrapper->get(&state, Identifier::fromString(&state, "open")); CallData callData; - CallType callType = ::getCallData(function, callData); - if (callType == CallTypeNone) - return throwTypeError(exec); - return JSMainThreadExecState::call(exec, function, callType, callData, wrapper, ArgList(exec)); + auto callType = ::getCallData(function, callData); + if (callType == CallType::None) + return throwTypeError(&state, scope); + return JSC::call(&state, function, callType, callData, wrapper, ArgList(&state)); } } return jsUndefined(); } - // document.open clobbers the security context of the document and - // aliases it with the active security context. - Document* activeDocument = asJSDOMWindow(exec->lexicalGlobalObject())->impl().document(); - - // In the case of two parameters or fewer, do a normal document open. - impl().open(activeDocument); + // Calling document.open clobbers the security context of the document and aliases it with the active security context. + // FIXME: Is it correct that this does not use findCallingDocument as the write function below does? + wrapped().open(asJSDOMWindow(state.lexicalGlobalObject())->wrapped().document()); + // FIXME: Why do we return the document instead of returning undefined? return this; } enum NewlineRequirement { DoNotAddNewline, DoAddNewline }; -static inline void documentWrite(ExecState* exec, HTMLDocument* document, NewlineRequirement addNewline) +static inline JSValue documentWrite(ExecState& state, JSHTMLDocument& document, NewlineRequirement addNewline) { - // DOM only specifies single string argument, but browsers allow multiple or no arguments. - - size_t size = exec->argumentCount(); - - String firstString = exec->argument(0).toString(exec)->value(exec); - SegmentedString segmentedString = firstString; - if (size != 1) { - if (!size) - segmentedString.clear(); - else { - for (size_t i = 1; i < size; ++i) { - String subsequentString = exec->uncheckedArgument(i).toString(exec)->value(exec); - segmentedString.append(SegmentedString(subsequentString)); - } - } + VM& vm = state.vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + + SegmentedString segmentedString; + size_t argumentCount = state.argumentCount(); + for (size_t i = 0; i < argumentCount; ++i) { + segmentedString.append(state.uncheckedArgument(i).toWTFString(&state)); + RETURN_IF_EXCEPTION(scope, { }); } if (addNewline) - segmentedString.append(SegmentedString(String(&newlineCharacter, 1))); + segmentedString.append(String { "\n" }); - Document* activeDocument = asJSDOMWindow(exec->lexicalGlobalObject())->impl().document(); - document->write(segmentedString, activeDocument); + document.wrapped().write(WTFMove(segmentedString), findCallingDocument(state)); + return jsUndefined(); } -JSValue JSHTMLDocument::write(ExecState* exec) +JSValue JSHTMLDocument::write(ExecState& state) { - documentWrite(exec, &impl(), DoNotAddNewline); - return jsUndefined(); + return documentWrite(state, *this, DoNotAddNewline); } -JSValue JSHTMLDocument::writeln(ExecState* exec) +JSValue JSHTMLDocument::writeln(ExecState& state) { - documentWrite(exec, &impl(), DoAddNewline); - return jsUndefined(); + return documentWrite(state, *this, DoAddNewline); } } // namespace WebCore diff --git a/Source/WebCore/bindings/js/JSHTMLElementCustom.cpp b/Source/WebCore/bindings/js/JSHTMLElementCustom.cpp index 4ee3fd9ef..43792a9d8 100644 --- a/Source/WebCore/bindings/js/JSHTMLElementCustom.cpp +++ b/Source/WebCore/bindings/js/JSHTMLElementCustom.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2007 Apple Inc. All rights reserved. + * Copyright (C) 2007, 2016 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -10,10 +10,10 @@ * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * - * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR @@ -26,27 +26,108 @@ #include "config.h" #include "JSHTMLElement.h" +#include "CustomElementRegistry.h" +#include "DOMWindow.h" #include "Document.h" #include "HTMLFormElement.h" +#include "JSCustomElementInterface.h" +#include "JSDOMConstructorBase.h" +#include "JSNodeCustom.h" +#include "ScriptExecutionContext.h" +#include <runtime/InternalFunction.h> #include <runtime/JSWithScope.h> namespace WebCore { using namespace JSC; +EncodedJSValue JSC_HOST_CALL constructJSHTMLElement(ExecState& exec) +{ + VM& vm = exec.vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + + auto* jsConstructor = jsCast<JSDOMConstructorBase*>(exec.jsCallee()); + ASSERT(jsConstructor); + + auto* context = jsConstructor->scriptExecutionContext(); + if (!context) + return throwConstructorScriptExecutionContextUnavailableError(exec, scope, "HTMLElement"); + ASSERT(context->isDocument()); + + JSValue newTargetValue = exec.thisValue(); + auto* globalObject = jsConstructor->globalObject(); + JSValue htmlElementConstructorValue = JSHTMLElement::getConstructor(vm, globalObject); + if (newTargetValue == htmlElementConstructorValue) + return throwVMTypeError(&exec, scope, ASCIILiteral("new.target is not a valid custom element constructor")); + + auto& document = downcast<Document>(*context); + + auto* window = document.domWindow(); + if (!window) + return throwVMTypeError(&exec, scope, ASCIILiteral("new.target is not a valid custom element constructor")); + + auto* registry = window->customElementRegistry(); + if (!registry) + return throwVMTypeError(&exec, scope, ASCIILiteral("new.target is not a valid custom element constructor")); + + JSObject* newTarget = newTargetValue.getObject(); + auto* elementInterface = registry->findInterface(newTarget); + if (!elementInterface) + return throwVMTypeError(&exec, scope, ASCIILiteral("new.target does not define a custom element")); + + if (!elementInterface->isUpgradingElement()) { + Structure* baseStructure = getDOMStructure<JSHTMLElement>(vm, *globalObject); + auto* newElementStructure = InternalFunction::createSubclassStructure(&exec, newTargetValue, baseStructure); + RETURN_IF_EXCEPTION(scope, encodedJSValue()); + + Ref<HTMLElement> element = HTMLElement::create(elementInterface->name(), document); + element->setIsDefinedCustomElement(*elementInterface); + auto* jsElement = JSHTMLElement::create(newElementStructure, globalObject, element.get()); + cacheWrapper(globalObject->world(), element.ptr(), jsElement); + return JSValue::encode(jsElement); + } + + Element* elementToUpgrade = elementInterface->lastElementInConstructionStack(); + if (!elementToUpgrade) { + throwInvalidStateError(exec, scope, ASCIILiteral("Cannot instantiate a custom element inside its own constrcutor during upgrades")); + return JSValue::encode(jsUndefined()); + } + + JSValue elementWrapperValue = toJS(&exec, jsConstructor->globalObject(), *elementToUpgrade); + ASSERT(elementWrapperValue.isObject()); + + JSValue newPrototype = newTarget->get(&exec, vm.propertyNames->prototype); + RETURN_IF_EXCEPTION(scope, encodedJSValue()); + + JSObject* elementWrapperObject = asObject(elementWrapperValue); + JSObject::setPrototype(elementWrapperObject, &exec, newPrototype, true /* shouldThrowIfCantSet */); + RETURN_IF_EXCEPTION(scope, encodedJSValue()); + + elementInterface->didUpgradeLastElementInConstructionStack(); + + return JSValue::encode(elementWrapperValue); +} + JSScope* JSHTMLElement::pushEventHandlerScope(ExecState* exec, JSScope* scope) const { - HTMLElement& element = impl(); + HTMLElement& element = wrapped(); // The document is put on first, fall back to searching it only after the element and form. - scope = JSWithScope::create(exec, asObject(toJS(exec, globalObject(), &element.document())), scope); + // FIXME: This probably may use the wrong global object. If this is called from a native + // function, then it would be correct but not optimal since the native function would *know* + // the global object. But, it may be that globalObject() is more correct. + // https://bugs.webkit.org/show_bug.cgi?id=134932 + VM& vm = exec->vm(); + JSGlobalObject* lexicalGlobalObject = exec->lexicalGlobalObject(); + + scope = JSWithScope::create(vm, lexicalGlobalObject, asObject(toJS(exec, globalObject(), element.document())), scope); // The form is next, searched before the document, but after the element itself. if (HTMLFormElement* form = element.form()) - scope = JSWithScope::create(exec, asObject(toJS(exec, globalObject(), form)), scope); + scope = JSWithScope::create(vm, lexicalGlobalObject, asObject(toJS(exec, globalObject(), *form)), scope); // The element is on top, searched first. - return JSWithScope::create(exec, asObject(toJS(exec, globalObject(), &element)), scope); + return JSWithScope::create(vm, lexicalGlobalObject, asObject(toJS(exec, globalObject(), element)), scope); } } // namespace WebCore diff --git a/Source/WebCore/bindings/js/JSHTMLEmbedElementCustom.cpp b/Source/WebCore/bindings/js/JSHTMLEmbedElementCustom.cpp index 73f2c2bfb..919f68662 100644 --- a/Source/WebCore/bindings/js/JSHTMLEmbedElementCustom.cpp +++ b/Source/WebCore/bindings/js/JSHTMLEmbedElementCustom.cpp @@ -10,10 +10,10 @@ * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * - * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR @@ -38,9 +38,9 @@ bool JSHTMLEmbedElement::getOwnPropertySlotDelegate(ExecState* exec, PropertyNam return pluginElementCustomGetOwnPropertySlot<JSHTMLEmbedElement, Base>(exec, propertyName, slot, this); } -bool JSHTMLEmbedElement::putDelegate(ExecState* exec, PropertyName propertyName, JSValue value, PutPropertySlot& slot) +bool JSHTMLEmbedElement::putDelegate(ExecState* exec, PropertyName propertyName, JSValue value, PutPropertySlot& slot, bool& putResult) { - return pluginElementCustomPut(exec, propertyName, value, this, slot); + return pluginElementCustomPut(exec, propertyName, value, this, slot, putResult); } CallType JSHTMLEmbedElement::getCallData(JSCell* cell, CallData& callData) diff --git a/Source/WebCore/bindings/js/JSHTMLFormControlsCollectionCustom.cpp b/Source/WebCore/bindings/js/JSHTMLFormControlsCollectionCustom.cpp index fc41eb61a..58d9b676b 100644 --- a/Source/WebCore/bindings/js/JSHTMLFormControlsCollectionCustom.cpp +++ b/Source/WebCore/bindings/js/JSHTMLFormControlsCollectionCustom.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2007, 2008 Apple Inc. All rights reserved. + * Copyright (C) 2007-2008, 2016 Apple Inc. All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -18,54 +18,51 @@ */ #include "config.h" -#include "HTMLFormControlsCollection.h" - - -#include "HTMLAllCollection.h" -#include "JSDOMBinding.h" -#include "JSHTMLCollection.h" #include "JSHTMLFormControlsCollection.h" + +#include "HTMLFormControlsCollection.h" #include "JSNode.h" -#include "JSNodeList.h" #include "JSRadioNodeList.h" -#include "Node.h" #include "RadioNodeList.h" -#include <wtf/Vector.h> -#include <wtf/text/AtomicString.h> +#include <runtime/IdentifierInlines.h> using namespace JSC; namespace WebCore { -static JSValue getNamedItems(ExecState* exec, JSHTMLFormControlsCollection* collection, PropertyName propertyName) +static JSValue namedItems(ExecState& state, JSHTMLFormControlsCollection* collection, PropertyName propertyName) { - Vector<Ref<Element>> namedItems; const AtomicString& name = propertyNameToAtomicString(propertyName); - collection->impl().namedItems(name, namedItems); + Vector<Ref<Element>> namedItems = collection->wrapped().namedItems(name); if (namedItems.isEmpty()) return jsUndefined(); if (namedItems.size() == 1) - return toJS(exec, collection->globalObject(), &namedItems[0].get()); + return toJS(&state, collection->globalObject(), namedItems[0]); - ASSERT(collection->impl().type() == FormControls); - return toJS(exec, collection->globalObject(), collection->impl().ownerNode().radioNodeList(name).get()); + ASSERT(collection->wrapped().type() == FormControls); + return toJS(&state, collection->globalObject(), collection->wrapped().ownerNode().radioNodeList(name).get()); } -bool JSHTMLFormControlsCollection::canGetItemsForName(ExecState*, HTMLFormControlsCollection* collection, PropertyName propertyName) +bool JSHTMLFormControlsCollection::nameGetter(ExecState* state, PropertyName propertyName, JSValue& value) { - return collection->hasNamedItem(propertyNameToAtomicString(propertyName)); -} + auto items = namedItems(*state, this, propertyName); + if (items.isUndefined()) + return false; -EncodedJSValue JSHTMLFormControlsCollection::nameGetter(ExecState* exec, EncodedJSValue slotBase, EncodedJSValue, PropertyName propertyName) -{ - JSHTMLFormControlsCollection* thisObj = jsCast<JSHTMLFormControlsCollection*>(JSValue::decode(slotBase)); - return JSValue::encode(getNamedItems(exec, thisObj, propertyName)); + value = items; + return true; } -JSValue JSHTMLFormControlsCollection::namedItem(ExecState* exec) +JSValue JSHTMLFormControlsCollection::namedItem(ExecState& state) { - JSValue value = getNamedItems(exec, this, Identifier(exec, exec->argument(0).toString(exec)->value(exec))); + VM& vm = state.vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + + if (UNLIKELY(state.argumentCount() < 1)) + return throwException(&state, scope, createNotEnoughArgumentsError(&state)); + + JSValue value = namedItems(state, this, Identifier::fromString(&state, state.uncheckedArgument(0).toWTFString(&state))); return value.isUndefined() ? jsNull() : value; } diff --git a/Source/WebCore/bindings/js/JSHTMLFormElementCustom.cpp b/Source/WebCore/bindings/js/JSHTMLFormElementCustom.cpp deleted file mode 100644 index 416887261..000000000 --- a/Source/WebCore/bindings/js/JSHTMLFormElementCustom.cpp +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" -#include "JSHTMLFormElement.h" - -#include "Frame.h" -#include "HTMLCollection.h" -#include "HTMLFormElement.h" -#include "JSDOMWindowCustom.h" -#include "JSNodeList.h" -#include "StaticNodeList.h" - -using namespace JSC; - -namespace WebCore { - -bool JSHTMLFormElement::canGetItemsForName(ExecState*, HTMLFormElement* form, PropertyName propertyName) -{ - return form->hasNamedElement(propertyNameToAtomicString(propertyName)); -} - -EncodedJSValue JSHTMLFormElement::nameGetter(ExecState* exec, EncodedJSValue slotBase, EncodedJSValue, PropertyName propertyName) -{ - JSHTMLFormElement* jsForm = jsCast<JSHTMLFormElement*>(JSValue::decode(slotBase)); - HTMLFormElement& form = jsForm->impl(); - - Vector<Ref<Element>> namedItems; - form.getNamedElements(propertyNameToAtomicString(propertyName), namedItems); - - if (namedItems.isEmpty()) - return JSValue::encode(jsUndefined()); - if (namedItems.size() == 1) - return JSValue::encode(toJS(exec, jsForm->globalObject(), &namedItems[0].get())); - - // FIXME: HTML5 specifies that this should be a RadioNodeList. - return JSValue::encode(toJS(exec, jsForm->globalObject(), StaticElementList::adopt(namedItems).get())); -} - -} diff --git a/Source/WebCore/bindings/js/JSHTMLFrameElementCustom.cpp b/Source/WebCore/bindings/js/JSHTMLFrameElementCustom.cpp deleted file mode 100644 index 88f82c505..000000000 --- a/Source/WebCore/bindings/js/JSHTMLFrameElementCustom.cpp +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright (C) 2007, 2008 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of - * its contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" -#include "JSHTMLFrameElement.h" - -#include "Document.h" -#include "HTMLFrameElement.h" -#include "HTMLNames.h" -#include "HTMLParserIdioms.h" -#include "JSDOMBinding.h" - -using namespace JSC; - -namespace WebCore { - -using namespace HTMLNames; - -static inline bool allowSettingJavascriptURL(ExecState* exec, HTMLFrameElement* imp, const String& value) -{ - if (protocolIsJavaScript(stripLeadingAndTrailingHTMLSpaces(value))) { - Document* contentDocument = imp->contentDocument(); - if (contentDocument && !shouldAllowAccessToNode(exec, contentDocument)) - return false; - } - return true; -} - -void JSHTMLFrameElement::setLocation(ExecState* exec, JSValue value) -{ - HTMLFrameElement& imp = impl(); - String locationValue = valueToStringWithNullCheck(exec, value); - - if (!allowSettingJavascriptURL(exec, &imp, locationValue)) - return; - - imp.setLocation(locationValue); -} - -} // namespace WebCore diff --git a/Source/WebCore/bindings/js/JSHTMLFrameSetElementCustom.cpp b/Source/WebCore/bindings/js/JSHTMLFrameSetElementCustom.cpp index 6df61d1c1..125aef7ec 100644 --- a/Source/WebCore/bindings/js/JSHTMLFrameSetElementCustom.cpp +++ b/Source/WebCore/bindings/js/JSHTMLFrameSetElementCustom.cpp @@ -10,10 +10,10 @@ * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * - * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR @@ -30,7 +30,6 @@ #include "HTMLCollection.h" #include "HTMLFrameElement.h" #include "HTMLFrameSetElement.h" -#include "HTMLNames.h" #include "JSDOMWindow.h" #include "JSDOMWindowShell.h" #include "JSDOMBinding.h" @@ -39,23 +38,19 @@ using namespace JSC; namespace WebCore { -using namespace HTMLNames; - -bool JSHTMLFrameSetElement::canGetItemsForName(ExecState*, HTMLFrameSetElement* frameSet, PropertyName propertyName) -{ - Node* frame = frameSet->children()->namedItem(propertyNameToAtomicString(propertyName)); - return frame && frame->hasTagName(frameTag); -} - -EncodedJSValue JSHTMLFrameSetElement::nameGetter(ExecState* exec, EncodedJSValue slotBase, EncodedJSValue, PropertyName propertyName) +bool JSHTMLFrameSetElement::nameGetter(ExecState* exec, PropertyName propertyName, JSValue& value) { - HTMLElement& element = jsCast<JSHTMLElement*>(JSValue::decode(slotBase))->impl(); - Node* frameElement = element.children()->namedItem(propertyNameToAtomicString(propertyName)); - if (Document* document = toHTMLFrameElement(frameElement)->contentDocument()) { - if (JSDOMWindowShell* window = toJSDOMWindowShell(document->frame(), currentWorld(exec))) - return JSValue::encode(window); + auto* frameElement = wrapped().children()->namedItem(propertyNameToAtomicString(propertyName)); + if (!is<HTMLFrameElement>(frameElement)) + return false; + + if (auto* document = downcast<HTMLFrameElement>(*frameElement).contentDocument()) { + if (JSDOMWindowShell* window = toJSDOMWindowShell(document->frame(), currentWorld(exec))) { + value = window; + return true; + } } - return JSValue::encode(jsUndefined()); + return false; } } // namespace WebCore diff --git a/Source/WebCore/bindings/js/JSHTMLInputElementCustom.cpp b/Source/WebCore/bindings/js/JSHTMLInputElementCustom.cpp deleted file mode 100644 index 42ebad315..000000000 --- a/Source/WebCore/bindings/js/JSHTMLInputElementCustom.cpp +++ /dev/null @@ -1,106 +0,0 @@ -/* - * Copyright (C) 2008 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" -#include "JSHTMLInputElement.h" - -#include "HTMLInputElement.h" -#include <runtime/Error.h> - -using namespace JSC; - -namespace WebCore { - -JSValue JSHTMLInputElement::selectionStart(ExecState* exec) const -{ - HTMLInputElement& input = impl(); - if (!input.canHaveSelection()) - return throwTypeError(exec); - - return jsNumber(input.selectionStart()); -} - -void JSHTMLInputElement::setSelectionStart(ExecState* exec, JSValue value) -{ - HTMLInputElement& input = impl(); - if (!input.canHaveSelection()) - throwTypeError(exec); - - input.setSelectionStart(value.toInt32(exec)); -} - -JSValue JSHTMLInputElement::selectionEnd(ExecState* exec) const -{ - HTMLInputElement& input = impl(); - if (!input.canHaveSelection()) - return throwTypeError(exec); - - return jsNumber(input.selectionEnd()); -} - -void JSHTMLInputElement::setSelectionEnd(ExecState* exec, JSValue value) -{ - HTMLInputElement& input = impl(); - if (!input.canHaveSelection()) - throwTypeError(exec); - - input.setSelectionEnd(value.toInt32(exec)); -} - -JSValue JSHTMLInputElement::selectionDirection(ExecState* exec) const -{ - HTMLInputElement& input = impl(); - if (!input.canHaveSelection()) - return throwTypeError(exec); - - return jsStringWithCache(exec, input.selectionDirection()); -} - -void JSHTMLInputElement::setSelectionDirection(ExecState* exec, JSValue value) -{ - HTMLInputElement& input = impl(); - if (!input.canHaveSelection()) { - throwTypeError(exec); - return; - } - - input.setSelectionDirection(value.toString(exec)->value(exec)); -} - -JSValue JSHTMLInputElement::setSelectionRange(ExecState* exec) -{ - HTMLInputElement& input = impl(); - if (!input.canHaveSelection()) - return throwTypeError(exec); - - int start = exec->argument(0).toInt32(exec); - int end = exec->argument(1).toInt32(exec); - String direction = exec->argument(2).toString(exec)->value(exec); - - input.setSelectionRange(start, end, direction); - return jsUndefined(); -} - -} // namespace WebCore diff --git a/Source/WebCore/bindings/js/JSHTMLObjectElementCustom.cpp b/Source/WebCore/bindings/js/JSHTMLObjectElementCustom.cpp index b791186fc..4a8647f89 100644 --- a/Source/WebCore/bindings/js/JSHTMLObjectElementCustom.cpp +++ b/Source/WebCore/bindings/js/JSHTMLObjectElementCustom.cpp @@ -10,10 +10,10 @@ * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * - * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR @@ -38,9 +38,9 @@ bool JSHTMLObjectElement::getOwnPropertySlotDelegate(ExecState* exec, PropertyNa return pluginElementCustomGetOwnPropertySlot<JSHTMLObjectElement, Base>(exec, propertyName, slot, this); } -bool JSHTMLObjectElement::putDelegate(ExecState* exec, PropertyName propertyName, JSValue value, PutPropertySlot& slot) +bool JSHTMLObjectElement::putDelegate(ExecState* exec, PropertyName propertyName, JSValue value, PutPropertySlot& slot, bool& putResult) { - return pluginElementCustomPut(exec, propertyName, value, this, slot); + return pluginElementCustomPut(exec, propertyName, value, this, slot, putResult); } CallType JSHTMLObjectElement::getCallData(JSCell* cell, CallData& callData) diff --git a/Source/WebCore/bindings/js/JSHTMLOptionsCollectionCustom.cpp b/Source/WebCore/bindings/js/JSHTMLOptionsCollectionCustom.cpp index 74a58672f..356679a8e 100644 --- a/Source/WebCore/bindings/js/JSHTMLOptionsCollectionCustom.cpp +++ b/Source/WebCore/bindings/js/JSHTMLOptionsCollectionCustom.cpp @@ -20,72 +20,21 @@ #include "config.h" #include "JSHTMLOptionsCollection.h" +#include "CustomElementReactionQueue.h" #include "ExceptionCode.h" -#include "HTMLNames.h" -#include "HTMLOptionElement.h" -#include "HTMLOptionsCollection.h" -#include "HTMLSelectElement.h" #include "JSHTMLOptionElement.h" #include "JSHTMLSelectElement.h" #include "JSHTMLSelectElementCustom.h" -#include "JSNodeList.h" -#include "StaticNodeList.h" - #include <wtf/MathExtras.h> using namespace JSC; namespace WebCore { -void JSHTMLOptionsCollection::setLength(ExecState* exec, JSValue value) -{ - ExceptionCode ec = 0; - unsigned newLength = 0; - double lengthValue = value.toNumber(exec); - if (!std::isnan(lengthValue) && !std::isinf(lengthValue)) { - if (lengthValue < 0.0) - ec = INDEX_SIZE_ERR; - else if (lengthValue > static_cast<double>(UINT_MAX)) - newLength = UINT_MAX; - else - newLength = static_cast<unsigned>(lengthValue); - } - if (!ec) - impl().setLength(newLength, ec); - setDOMException(exec, ec); -} - -void JSHTMLOptionsCollection::indexSetter(ExecState* exec, unsigned index, JSValue value) -{ - selectIndexSetter(&impl().selectElement(), exec, index, value); -} - -JSValue JSHTMLOptionsCollection::add(ExecState* exec) -{ - HTMLOptionsCollection& imp = impl(); - HTMLOptionElement* option = toHTMLOptionElement(exec->argument(0)); - ExceptionCode ec = 0; - if (exec->argumentCount() < 2) - imp.add(option, ec); - else { - int index = exec->argument(1).toInt32(exec); - if (exec->hadException()) - return jsUndefined(); - imp.add(option, index, ec); - } - setDOMException(exec, ec); - return jsUndefined(); -} - -JSValue JSHTMLOptionsCollection::remove(ExecState* exec) +void JSHTMLOptionsCollection::indexSetter(ExecState* state, unsigned index, JSValue value) { - // The argument can be an HTMLOptionElement or an index. - JSValue argument = exec->argument(0); - if (HTMLOptionElement* option = toHTMLOptionElement(argument)) - impl().remove(option); - else - impl().remove(argument.toInt32(exec)); - return jsUndefined(); + CustomElementReactionStack customElementReactionStack; + selectElementIndexSetter(*state, wrapped().selectElement(), index, value); } } diff --git a/Source/WebCore/bindings/js/JSHTMLSelectElementCustom.cpp b/Source/WebCore/bindings/js/JSHTMLSelectElementCustom.cpp index 43f694b50..c74aed3df 100644 --- a/Source/WebCore/bindings/js/JSHTMLSelectElementCustom.cpp +++ b/Source/WebCore/bindings/js/JSHTMLSelectElementCustom.cpp @@ -21,55 +21,34 @@ #include "config.h" #include "JSHTMLSelectElementCustom.h" +#include "CustomElementReactionQueue.h" #include "ExceptionCode.h" #include "HTMLNames.h" #include "HTMLOptionElement.h" #include "HTMLSelectElement.h" #include "JSHTMLOptionElement.h" +#include "JSHTMLSelectElement.h" namespace WebCore { using namespace JSC; using namespace HTMLNames; -JSValue JSHTMLSelectElement::remove(ExecState* exec) +void selectElementIndexSetter(JSC::ExecState& state, HTMLSelectElement& element, unsigned index, JSC::JSValue value) { - HTMLSelectElement& select = impl(); + VM& vm = state.vm(); + auto throwScope = DECLARE_THROW_SCOPE(vm); - if (!exec->argumentCount()) { - // When called with no argument, we should call Element::remove() to detach. - ExceptionCode ec = 0; - select.remove(ec); - setDOMException(exec, ec); - } else { - // The HTMLSelectElement::remove() function can take either an option object or the index of an option. - if (HTMLOptionElement* option = toHTMLOptionElement(exec->argument(0))) - select.remove(option); - else - select.removeByIndex(exec->argument(0).toInt32(exec)); - } + auto* option = convert<IDLNullable<IDLInterface<HTMLOptionElement>>>(state, value); + RETURN_IF_EXCEPTION(throwScope, void()); - return jsUndefined(); + propagateException(state, throwScope, element.setItem(index, option)); } -void selectIndexSetter(HTMLSelectElement* select, JSC::ExecState* exec, unsigned index, JSC::JSValue value) +void JSHTMLSelectElement::indexSetter(JSC::ExecState* state, unsigned index, JSC::JSValue value) { - if (value.isUndefinedOrNull()) - select->removeByIndex(index); - else { - ExceptionCode ec = 0; - HTMLOptionElement* option = toHTMLOptionElement(value); - if (!option) - ec = TYPE_MISMATCH_ERR; - else - select->setOption(index, option, ec); - setDOMException(exec, ec); - } -} - -void JSHTMLSelectElement::indexSetter(JSC::ExecState* exec, unsigned index, JSC::JSValue value) -{ - selectIndexSetter(&impl(), exec, index, value); + CustomElementReactionStack customElementReactionStack; + selectElementIndexSetter(*state, wrapped(), index, value); } } diff --git a/Source/WebCore/bindings/js/JSHTMLSelectElementCustom.h b/Source/WebCore/bindings/js/JSHTMLSelectElementCustom.h index a4490380c..e012bccef 100644 --- a/Source/WebCore/bindings/js/JSHTMLSelectElementCustom.h +++ b/Source/WebCore/bindings/js/JSHTMLSelectElementCustom.h @@ -10,7 +10,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of + * 3. Neither the name of Apple Inc. ("Apple") nor the names of * its contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * @@ -26,15 +26,17 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef JSHTMLSelectElementCustom_h -#define JSHTMLSelectElementCustom_h +#pragma once -#include "JSHTMLSelectElement.h" +namespace JSC { +class ExecState; +class JSValue; +} namespace WebCore { -void selectIndexSetter(HTMLSelectElement*, JSC::ExecState*, unsigned index, JSC::JSValue); +class HTMLSelectElement; -} +void selectElementIndexSetter(JSC::ExecState&, HTMLSelectElement&, unsigned index, JSC::JSValue); -#endif +} diff --git a/Source/WebCore/bindings/js/JSHTMLTemplateElementCustom.cpp b/Source/WebCore/bindings/js/JSHTMLTemplateElementCustom.cpp index e4cda2baf..ff91eada0 100644 --- a/Source/WebCore/bindings/js/JSHTMLTemplateElementCustom.cpp +++ b/Source/WebCore/bindings/js/JSHTMLTemplateElementCustom.cpp @@ -29,9 +29,6 @@ */ #include "config.h" - -#if ENABLE(TEMPLATE_ELEMENT) - #include "JSHTMLTemplateElement.h" #include "HTMLTemplateElement.h" @@ -43,22 +40,15 @@ using namespace JSC; namespace WebCore { -JSValue JSHTMLTemplateElement::content(ExecState* exec) const +JSValue JSHTMLTemplateElement::content(ExecState& state) const { - JSLockHolder lock(exec); + JSLockHolder lock(&state); - DocumentFragment* content = impl().content(); + auto wrapper = wrap(&state, globalObject(), wrapped().content()); - JSObject* wrapper = getCachedWrapper(currentWorld(exec), content); - if (wrapper) - return wrapper; - - wrapper = CREATE_DOM_WRAPPER(exec, globalObject(), DocumentFragment, content); PrivateName propertyName; const_cast<JSHTMLTemplateElement*>(this)->putDirect(globalObject()->vm(), propertyName, wrapper); return wrapper; } } // namespace WebCore - -#endif // ENABLE(TEMPLATE_ELEMENT) diff --git a/Source/WebCore/bindings/js/JSHistoryCustom.cpp b/Source/WebCore/bindings/js/JSHistoryCustom.cpp index c608f5328..1d4efac31 100644 --- a/Source/WebCore/bindings/js/JSHistoryCustom.cpp +++ b/Source/WebCore/bindings/js/JSHistoryCustom.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008 Apple Inc. All rights reserved. + * Copyright (C) 2008, 2016 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -10,7 +10,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of + * 3. Neither the name of Apple Inc. ("Apple") nor the names of * its contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * @@ -29,8 +29,9 @@ #include "config.h" #include "JSHistory.h" +#include "ExceptionCode.h" #include "Frame.h" -#include "History.h" +#include "JSDOMConvert.h" #include "SerializedScriptValue.h" #include <runtime/JSFunction.h> @@ -38,159 +39,72 @@ using namespace JSC; namespace WebCore { -static EncodedJSValue nonCachingStaticBackFunctionGetter(ExecState* exec, EncodedJSValue, EncodedJSValue, PropertyName propertyName) +JSValue JSHistory::state(ExecState& state) const { - return JSValue::encode(JSFunction::create(exec->vm(), exec->lexicalGlobalObject(), 0, propertyName.publicName(), jsHistoryPrototypeFunctionBack)); -} - -static EncodedJSValue nonCachingStaticForwardFunctionGetter(ExecState* exec, EncodedJSValue, EncodedJSValue, PropertyName propertyName) -{ - return JSValue::encode(JSFunction::create(exec->vm(), exec->lexicalGlobalObject(), 0, propertyName.publicName(), jsHistoryPrototypeFunctionForward)); -} - -static EncodedJSValue nonCachingStaticGoFunctionGetter(ExecState* exec, EncodedJSValue, EncodedJSValue, PropertyName propertyName) -{ - return JSValue::encode(JSFunction::create(exec->vm(), exec->lexicalGlobalObject(), 1, propertyName.publicName(), jsHistoryPrototypeFunctionGo)); -} - -bool JSHistory::getOwnPropertySlotDelegate(ExecState* exec, PropertyName propertyName, PropertySlot& slot) -{ - // When accessing History cross-domain, functions are always the native built-in ones. - // See JSDOMWindow::getOwnPropertySlotDelegate for additional details. - - // Our custom code is only needed to implement the Window cross-domain scheme, so if access is - // allowed, return false so the normal lookup will take place. - String message; - if (shouldAllowAccessToFrame(exec, impl().frame(), message)) - return false; - - // Check for the few functions that we allow, even when called cross-domain. - // Make these read-only / non-configurable to prevent writes via defineProperty. - const HashEntry* entry = JSHistoryPrototype::info()->propHashTable(exec)->entry(exec, propertyName); - if (entry) { - // Allow access to back(), forward() and go() from any frame. - if (entry->attributes() & JSC::Function) { - if (entry->function() == jsHistoryPrototypeFunctionBack) { - slot.setCustom(this, ReadOnly | DontDelete | DontEnum, nonCachingStaticBackFunctionGetter); - return true; - } else if (entry->function() == jsHistoryPrototypeFunctionForward) { - slot.setCustom(this, ReadOnly | DontDelete | DontEnum, nonCachingStaticForwardFunctionGetter); - return true; - } else if (entry->function() == jsHistoryPrototypeFunctionGo) { - slot.setCustom(this, ReadOnly | DontDelete | DontEnum, nonCachingStaticGoFunctionGetter); - return true; - } - } - } else { - // Allow access to toString() cross-domain, but always Object.toString. - if (propertyName == exec->propertyNames().toString) { - slot.setCustom(this, ReadOnly | DontDelete | DontEnum, objectToStringFunctionGetter); - return true; - } - } - - printErrorMessageForFrame(impl().frame(), message); - slot.setUndefined(); - return true; -} - -bool JSHistory::putDelegate(ExecState* exec, PropertyName, JSValue, PutPropertySlot&) -{ - if (!shouldAllowAccessToFrame(exec, impl().frame())) - return true; - return false; -} - -bool JSHistory::deleteProperty(JSCell* cell, ExecState* exec, PropertyName propertyName) -{ - JSHistory* thisObject = jsCast<JSHistory*>(cell); - if (!shouldAllowAccessToFrame(exec, thisObject->impl().frame())) - return false; - return Base::deleteProperty(thisObject, exec, propertyName); -} - -bool JSHistory::deletePropertyByIndex(JSCell* cell, ExecState* exec, unsigned propertyName) -{ - JSHistory* thisObject = jsCast<JSHistory*>(cell); - if (!shouldAllowAccessToFrame(exec, thisObject->impl().frame())) - return false; - return Base::deletePropertyByIndex(thisObject, exec, propertyName); -} - -void JSHistory::getOwnPropertyNames(JSObject* object, ExecState* exec, PropertyNameArray& propertyNames, EnumerationMode mode) -{ - JSHistory* thisObject = jsCast<JSHistory*>(object); - if (!shouldAllowAccessToFrame(exec, thisObject->impl().frame())) - return; - Base::getOwnPropertyNames(thisObject, exec, propertyNames, mode); -} - -JSValue JSHistory::state(ExecState *exec) const -{ - History& history = impl(); + History& history = wrapped(); JSValue cachedValue = m_state.get(); if (!cachedValue.isEmpty() && !history.stateChanged()) return cachedValue; RefPtr<SerializedScriptValue> serialized = history.state(); - JSValue result = serialized ? serialized->deserialize(exec, globalObject(), 0) : jsNull(); - const_cast<JSHistory*>(this)->m_state.set(exec->vm(), this, result); + JSValue result = serialized ? serialized->deserialize(state, globalObject()) : jsNull(); + m_state.set(state.vm(), this, result); return result; } -JSValue JSHistory::pushState(ExecState* exec) +JSValue JSHistory::pushState(ExecState& state) { - if (!shouldAllowAccessToFrame(exec, impl().frame())) - return jsUndefined(); + VM& vm = state.vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + + auto argCount = state.argumentCount(); + if (UNLIKELY(argCount < 2)) + return throwException(&state, scope, createNotEnoughArgumentsError(&state)); - RefPtr<SerializedScriptValue> historyState = SerializedScriptValue::create(exec, exec->argument(0), 0, 0); - if (exec->hadException()) - return jsUndefined(); + auto historyState = SerializedScriptValue::create(state, state.uncheckedArgument(0)); + RETURN_IF_EXCEPTION(scope, JSValue()); + + // FIXME: title should not be nullable. + String title = convert<IDLNullable<IDLDOMString>>(state, state.uncheckedArgument(1)); + RETURN_IF_EXCEPTION(scope, JSValue()); - String title = valueToStringWithUndefinedOrNullCheck(exec, exec->argument(1)); - if (exec->hadException()) - return jsUndefined(); - String url; - if (exec->argumentCount() > 2) { - url = valueToStringWithUndefinedOrNullCheck(exec, exec->argument(2)); - if (exec->hadException()) - return jsUndefined(); + if (argCount > 2) { + url = convert<IDLNullable<IDLUSVString>>(state, state.uncheckedArgument(2)); + RETURN_IF_EXCEPTION(scope, JSValue()); } - ExceptionCode ec = 0; - impl().stateObjectAdded(historyState.release(), title, url, History::StateObjectType::Push, ec); - setDOMException(exec, ec); + propagateException(state, scope, wrapped().stateObjectAdded(WTFMove(historyState), title, url, History::StateObjectType::Push)); m_state.clear(); return jsUndefined(); } -JSValue JSHistory::replaceState(ExecState* exec) +JSValue JSHistory::replaceState(ExecState& state) { - if (!shouldAllowAccessToFrame(exec, impl().frame())) - return jsUndefined(); + VM& vm = state.vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + + auto argCount = state.argumentCount(); + if (UNLIKELY(argCount < 2)) + return throwException(&state, scope, createNotEnoughArgumentsError(&state)); + + auto historyState = SerializedScriptValue::create(state, state.uncheckedArgument(0)); + RETURN_IF_EXCEPTION(scope, JSValue()); - RefPtr<SerializedScriptValue> historyState = SerializedScriptValue::create(exec, exec->argument(0), 0, 0); - if (exec->hadException()) - return jsUndefined(); + // FIXME: title should not be nullable. + String title = convert<IDLNullable<IDLDOMString>>(state, state.uncheckedArgument(1)); + RETURN_IF_EXCEPTION(scope, JSValue()); - String title = valueToStringWithUndefinedOrNullCheck(exec, exec->argument(1)); - if (exec->hadException()) - return jsUndefined(); - String url; - if (exec->argumentCount() > 2) { - url = valueToStringWithUndefinedOrNullCheck(exec, exec->argument(2)); - if (exec->hadException()) - return jsUndefined(); + if (argCount > 2) { + url = convert<IDLNullable<IDLUSVString>>(state, state.uncheckedArgument(2)); + RETURN_IF_EXCEPTION(scope, JSValue()); } - ExceptionCode ec = 0; - impl().stateObjectAdded(historyState.release(), title, url, History::StateObjectType::Replace, ec); - setDOMException(exec, ec); + propagateException(state, scope, wrapped().stateObjectAdded(WTFMove(historyState), title, url, History::StateObjectType::Replace)); m_state.clear(); diff --git a/Source/WebCore/bindings/js/JSIDBAnyCustom.cpp b/Source/WebCore/bindings/js/JSIDBAnyCustom.cpp deleted file mode 100644 index 5649c85ca..000000000 --- a/Source/WebCore/bindings/js/JSIDBAnyCustom.cpp +++ /dev/null @@ -1,115 +0,0 @@ -/* - * Copyright (C) 2010 Google Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" - -#if ENABLE(INDEXED_DATABASE) - -#include "JSIDBAny.h" - -#include "IDBAny.h" -#include "IDBCursor.h" -#include "IDBCursorWithValue.h" -#include "IDBDatabase.h" -#include "IDBFactory.h" -#include "IDBIndex.h" -#include "IDBObjectStore.h" -#include "JSDOMStringList.h" -#include "JSIDBCursor.h" -#include "JSIDBCursorWithValue.h" -#include "JSIDBDatabase.h" -#include "JSIDBFactory.h" -#include "JSIDBIndex.h" -#include "JSIDBObjectStore.h" -#include "JSIDBTransaction.h" -#include "SerializedScriptValue.h" - -using namespace JSC; - -namespace WebCore { - -static JSValue toJS(ExecState* exec, JSDOMGlobalObject* globalObject, const IDBKeyPath& value) -{ - switch (value.type()) { - case IDBKeyPath::NullType: - return jsNull(); - case IDBKeyPath::StringType: - return jsStringWithCache(exec, value.string()); - case IDBKeyPath::ArrayType: - RefPtr<DOMStringList> keyPaths = DOMStringList::create(); - for (Vector<String>::const_iterator it = value.array().begin(); it != value.array().end(); ++it) - keyPaths->append(*it); - return toJS(exec, globalObject, keyPaths.release()); - } - - ASSERT_NOT_REACHED(); - return jsUndefined(); -} - -JSValue toJS(ExecState* exec, JSDOMGlobalObject* globalObject, IDBAny* idbAny) -{ - if (!idbAny) - return jsNull(); - - switch (idbAny->type()) { - case IDBAny::UndefinedType: - return jsUndefined(); - case IDBAny::NullType: - return jsNull(); - case IDBAny::DOMStringListType: - return toJS(exec, globalObject, idbAny->domStringList()); - case IDBAny::IDBCursorType: - return toJS(exec, globalObject, idbAny->idbCursor()); - case IDBAny::IDBCursorWithValueType: - return wrap<JSIDBCursorWithValue>(exec, globalObject, idbAny->idbCursorWithValue().get()); - case IDBAny::IDBDatabaseType: - return toJS(exec, globalObject, idbAny->idbDatabase()); - case IDBAny::IDBFactoryType: - return toJS(exec, globalObject, idbAny->idbFactory()); - case IDBAny::IDBIndexType: - return toJS(exec, globalObject, idbAny->idbIndex()); - case IDBAny::IDBObjectStoreType: - return toJS(exec, globalObject, idbAny->idbObjectStore()); - case IDBAny::IDBTransactionType: - return toJS(exec, globalObject, idbAny->idbTransaction()); - case IDBAny::ScriptValueType: - return idbAny->scriptValue().jsValue(); - case IDBAny::StringType: - return jsStringWithCache(exec, idbAny->string()); - case IDBAny::IntegerType: - return jsNumber(idbAny->integer()); - case IDBAny::KeyPathType: - return toJS(exec, globalObject, idbAny->keyPath()); - } - - ASSERT_NOT_REACHED(); - return jsUndefined(); -} - -} // namespace WebCore - -#endif // ENABLE(INDEXED_DATABASE) diff --git a/Source/WebCore/bindings/js/JSIDBCursorCustom.cpp b/Source/WebCore/bindings/js/JSIDBCursorCustom.cpp new file mode 100644 index 000000000..c74cb90da --- /dev/null +++ b/Source/WebCore/bindings/js/JSIDBCursorCustom.cpp @@ -0,0 +1,59 @@ +/* + * Copyright (C) 2016 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "JSIDBCursor.h" + +#if ENABLE(INDEXED_DATABASE) + +#include "JSDOMBinding.h" +#include "JSIDBCursorWithValue.h" + +using namespace JSC; + +namespace WebCore { + +void JSIDBCursor::visitAdditionalChildren(SlotVisitor& visitor) +{ + auto& cursor = wrapped(); + if (auto* request = cursor.request()) + visitor.addOpaqueRoot(request); +} + +JSValue toJSNewlyCreated(JSC::ExecState*, JSDOMGlobalObject* globalObject, Ref<IDBCursor>&& cursor) +{ + if (is<IDBCursorWithValue>(cursor)) + return createWrapper<IDBCursorWithValue>(globalObject, WTFMove(cursor)); + return createWrapper<IDBCursor>(globalObject, WTFMove(cursor)); +} + +JSValue toJS(JSC::ExecState* state, JSDOMGlobalObject* globalObject, IDBCursor& cursor) +{ + return wrap(state, globalObject, cursor); +} + +} // namespace WebCore + +#endif // ENABLE(INDEXED_DATABASE) diff --git a/Source/WebCore/bindings/js/JSRequestAnimationFrameCallbackCustom.cpp b/Source/WebCore/bindings/js/JSIDBCursorWithValueCustom.cpp index 91785a425..abbbc78fe 100644 --- a/Source/WebCore/bindings/js/JSRequestAnimationFrameCallbackCustom.cpp +++ b/Source/WebCore/bindings/js/JSIDBCursorWithValueCustom.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2011 Apple Inc. All rights reserved. + * Copyright (C) 2016 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -24,32 +24,22 @@ */ #include "config.h" +#include "JSIDBCursorWithValue.h" -#if ENABLE(REQUEST_ANIMATION_FRAME) +#if ENABLE(INDEXED_DATABASE) -#include "JSRequestAnimationFrameCallback.h" +#include "IDBCursorWithValue.h" +#include <heap/HeapInlines.h> using namespace JSC; namespace WebCore { -bool JSRequestAnimationFrameCallback::handleEvent(double highResNowMs) +void JSIDBCursorWithValue::visitAdditionalChildren(SlotVisitor& visitor) { - if (!canInvokeCallback()) - return true; - - Ref<JSRequestAnimationFrameCallback> protect(*this); - - JSLockHolder lock(m_data->globalObject()->vm()); - - MarkedArgumentBuffer args; - args.append(jsNumber(highResNowMs)); - - bool raisedException = false; - m_data->invokeCallback(args, &raisedException); - return !raisedException; + JSIDBCursor::visitAdditionalChildren(visitor); } -} +} // namespace WebCore -#endif +#endif // ENABLE(INDEXED_DATABASE) diff --git a/Source/WebCore/bindings/js/JSIDBDatabaseCustom.cpp b/Source/WebCore/bindings/js/JSIDBDatabaseCustom.cpp deleted file mode 100644 index 9eae7569c..000000000 --- a/Source/WebCore/bindings/js/JSIDBDatabaseCustom.cpp +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright (C) 2012 Michael Pruett <michael@68k.org> - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" - -#if ENABLE(INDEXED_DATABASE) - -#include "JSIDBDatabase.h" - -#include "IDBBindingUtilities.h" -#include "IDBDatabase.h" -#include "IDBKeyPath.h" -#include "IDBObjectStore.h" -#include "JSIDBObjectStore.h" -#include <runtime/Error.h> -#include <runtime/JSString.h> - -using namespace JSC; - -namespace WebCore { - -JSValue JSIDBDatabase::createObjectStore(ExecState* exec) -{ - if (exec->argumentCount() < 1) - return exec->vm().throwException(exec, createNotEnoughArgumentsError(exec)); - - String name = exec->argument(0).toString(exec)->value(exec); - if (exec->hadException()) - return jsUndefined(); - - JSValue optionsValue = exec->argument(1); - if (!optionsValue.isUndefinedOrNull() && !optionsValue.isObject()) - return throwTypeError(exec, "Not an object."); - - IDBKeyPath keyPath; - bool autoIncrement = false; - if (!optionsValue.isUndefinedOrNull()) { - JSValue keyPathValue = optionsValue.get(exec, Identifier(exec, "keyPath")); - if (exec->hadException()) - return jsUndefined(); - - if (!keyPathValue.isUndefinedOrNull()) { - keyPath = idbKeyPathFromValue(exec, keyPathValue); - if (exec->hadException()) - return jsUndefined(); - } - - autoIncrement = optionsValue.get(exec, Identifier(exec, "autoIncrement")).toBoolean(exec); - if (exec->hadException()) - return jsUndefined(); - } - - ExceptionCode ec = 0; - JSValue result = toJS(exec, globalObject(), impl().createObjectStore(name, keyPath, autoIncrement, ec).get()); - setDOMException(exec, ec); - return result; -} - -} - -#endif diff --git a/Source/WebCore/bindings/js/JSIDBIndexCustom.cpp b/Source/WebCore/bindings/js/JSIDBIndexCustom.cpp new file mode 100644 index 000000000..2710090f4 --- /dev/null +++ b/Source/WebCore/bindings/js/JSIDBIndexCustom.cpp @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2016 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "JSIDBIndex.h" + +#if ENABLE(INDEXED_DATABASE) + +#include "IDBIndex.h" +#include <heap/HeapInlines.h> + +using namespace JSC; + +namespace WebCore { + +void JSIDBIndex::visitAdditionalChildren(SlotVisitor& visitor) +{ + visitor.addOpaqueRoot(static_cast<IDBIndex&>(wrapped()).objectStoreAsOpaqueRoot()); +} + +} // namespace WebCore + +#endif // ENABLE(INDEXED_DATABASE) diff --git a/Source/WebCore/bindings/js/JSIDBObjectStoreCustom.cpp b/Source/WebCore/bindings/js/JSIDBObjectStoreCustom.cpp index 74fd354b2..3fe84a71f 100644 --- a/Source/WebCore/bindings/js/JSIDBObjectStoreCustom.cpp +++ b/Source/WebCore/bindings/js/JSIDBObjectStoreCustom.cpp @@ -29,56 +29,16 @@ #if ENABLE(INDEXED_DATABASE) +#include "JSDOMBinding.h" #include "JSIDBObjectStore.h" -#include "IDBBindingUtilities.h" -#include "IDBKeyPath.h" -#include "IDBObjectStore.h" -#include "JSIDBIndex.h" -#include <runtime/Error.h> -#include <runtime/JSString.h> - using namespace JSC; namespace WebCore { -JSValue JSIDBObjectStore::createIndex(ExecState* exec) +void JSIDBObjectStore::visitAdditionalChildren(SlotVisitor& visitor) { - ScriptExecutionContext* context = jsCast<JSDOMGlobalObject*>(exec->lexicalGlobalObject())->scriptExecutionContext(); - if (!context) - return exec->vm().throwException(exec, createReferenceError(exec, "IDBObjectStore script execution context is unavailable")); - - if (exec->argumentCount() < 2) - return exec->vm().throwException(exec, createNotEnoughArgumentsError(exec)); - - String name = exec->argument(0).toString(exec)->value(exec); - if (exec->hadException()) - return jsUndefined(); - - IDBKeyPath keyPath = idbKeyPathFromValue(exec, exec->argument(1)); - if (exec->hadException()) - return jsUndefined(); - - JSValue optionsValue = exec->argument(2); - if (!optionsValue.isUndefinedOrNull() && !optionsValue.isObject()) - return throwTypeError(exec, "Not an object."); - - bool unique = false; - bool multiEntry = false; - if (!optionsValue.isUndefinedOrNull()) { - unique = optionsValue.get(exec, Identifier(exec, "unique")).toBoolean(exec); - if (exec->hadException()) - return jsUndefined(); - - multiEntry = optionsValue.get(exec, Identifier(exec, "multiEntry")).toBoolean(exec); - if (exec->hadException()) - return jsUndefined(); - } - - ExceptionCode ec = 0; - JSValue result = toJS(exec, globalObject(), impl().createIndex(context, name, keyPath, unique, multiEntry, ec).get()); - setDOMException(exec, ec); - return result; + static_cast<IDBObjectStore&>(wrapped()).visitReferencedIndexes(visitor); } } diff --git a/Source/WebCore/bindings/js/JSHTMLLinkElementCustom.cpp b/Source/WebCore/bindings/js/JSIDBTransactionCustom.cpp index d3a4b543f..0e6d383e8 100644 --- a/Source/WebCore/bindings/js/JSHTMLLinkElementCustom.cpp +++ b/Source/WebCore/bindings/js/JSIDBTransactionCustom.cpp @@ -1,6 +1,5 @@ /* - * Copyright (C) 2010 Apple Inc. All rights reserved. - * Copyright (C) 2011 Google Inc. All rights reserved. + * Copyright (C) 2016 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -25,25 +24,21 @@ */ #include "config.h" -#include "JSHTMLLinkElement.h" +#include "JSIDBTransaction.h" + +#if ENABLE(INDEXED_DATABASE) -#include "HTMLLinkElement.h" #include "JSDOMBinding.h" -#include "JSDOMSettableTokenList.h" -#include <wtf/GetPtr.h> using namespace JSC; namespace WebCore { -JSValue JSHTMLLinkElement::sizes(ExecState* exec) const +void JSIDBTransaction::visitAdditionalChildren(SlotVisitor& visitor) { - return toJS(exec, globalObject(), impl().sizes()); + static_cast<IDBTransaction&>(wrapped()).visitReferencedObjectStores(visitor); } -void JSHTMLLinkElement::setSizes(ExecState* exec, JSValue value) -{ - impl().setSizes(valueToStringWithNullCheck(exec, value)); } -} // namespace WebCore +#endif diff --git a/Source/WebCore/bindings/js/JSImageConstructor.cpp b/Source/WebCore/bindings/js/JSImageConstructor.cpp deleted file mode 100644 index a86effd13..000000000 --- a/Source/WebCore/bindings/js/JSImageConstructor.cpp +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright (C) 1999-2000 Harri Porten (porten@kde.org) - * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2010 Apple Inc. All rights reserved. - * - * 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 - */ - -#include "config.h" -#include "JSImageConstructor.h" - -#include "HTMLImageElement.h" -#include "HTMLNames.h" -#include "JSHTMLImageElement.h" -#include "JSNode.h" -#include <runtime/Error.h> - -using namespace JSC; - -namespace WebCore { - -STATIC_ASSERT_IS_TRIVIALLY_DESTRUCTIBLE(JSImageConstructor); - -const ClassInfo JSImageConstructor::s_info = { "ImageConstructor", &Base::s_info, 0, 0, CREATE_METHOD_TABLE(JSImageConstructor) }; - -JSImageConstructor::JSImageConstructor(Structure* structure, JSDOMGlobalObject* globalObject) - : DOMConstructorWithDocument(structure, globalObject) -{ -} - -void JSImageConstructor::finishCreation(VM& vm, JSDOMGlobalObject* globalObject) -{ - Base::finishCreation(globalObject); - ASSERT(inherits(info())); - putDirect(vm, vm.propertyNames->prototype, JSHTMLImageElementPrototype::self(vm, globalObject), None); -} - -static EncodedJSValue JSC_HOST_CALL constructImage(ExecState* exec) -{ - JSImageConstructor* jsConstructor = jsCast<JSImageConstructor*>(exec->callee()); - Document* document = jsConstructor->document(); - if (!document) - return throwVMError(exec, createReferenceError(exec, "Image constructor associated document is unavailable")); - - // Calling toJS on the document causes the JS document wrapper to be - // added to the window object. This is done to ensure that JSDocument::visit - // will be called, which will cause the image element to be marked if necessary. - toJS(exec, jsConstructor->globalObject(), document); - int width; - int height; - int* optionalWidth = 0; - int* optionalHeight = 0; - if (exec->argumentCount() > 0) { - width = exec->argument(0).toInt32(exec); - optionalWidth = &width; - } - if (exec->argumentCount() > 1) { - height = exec->argument(1).toInt32(exec); - optionalHeight = &height; - } - - return JSValue::encode(asObject(toJS(exec, jsConstructor->globalObject(), - HTMLImageElement::createForJSConstructor(*document, optionalWidth, optionalHeight)))); -} - -ConstructType JSImageConstructor::getConstructData(JSCell*, ConstructData& constructData) -{ - constructData.native.function = constructImage; - return ConstructTypeHost; -} - -} // namespace WebCore diff --git a/Source/WebCore/bindings/js/JSImageConstructor.h b/Source/WebCore/bindings/js/JSImageConstructor.h deleted file mode 100644 index b923215b3..000000000 --- a/Source/WebCore/bindings/js/JSImageConstructor.h +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright (C) 1999 Harri Porten (porten@kde.org) - * Copyright (C) 2004, 2006, 2007, 2008 Apple Inc. All rights reserved. - * - * 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 JSImageConstructor_h -#define JSImageConstructor_h - -#include "DOMConstructorWithDocument.h" -#include "JSDOMBinding.h" -#include "JSDocument.h" - -namespace WebCore { - - class JSImageConstructor : public DOMConstructorWithDocument { - public: - typedef DOMConstructorWithDocument Base; - - static JSImageConstructor* create(JSC::VM& vm, JSC::Structure* structure, JSDOMGlobalObject* globalObject) - { - JSImageConstructor* constructor = new (NotNull, JSC::allocateCell<JSImageConstructor>(vm.heap)) JSImageConstructor(structure, globalObject); - constructor->finishCreation(vm, globalObject); - return constructor; - } - - 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()); - } - - DECLARE_INFO; - - private: - JSImageConstructor(JSC::Structure*, JSDOMGlobalObject*); - void finishCreation(JSC::VM&, JSDOMGlobalObject*); - static JSC::ConstructType getConstructData(JSC::JSCell*, JSC::ConstructData&); - }; - -} // namespace WebCore - -#endif // JSImageConstructor_h diff --git a/Source/WebCore/bindings/js/JSImageDataCustom.cpp b/Source/WebCore/bindings/js/JSImageDataCustom.cpp index 1576d5e58..518b5ef13 100644 --- a/Source/WebCore/bindings/js/JSImageDataCustom.cpp +++ b/Source/WebCore/bindings/js/JSImageDataCustom.cpp @@ -26,7 +26,10 @@ #include "config.h" #include "JSImageData.h" -#include "ImageData.h" +#include "JSDOMConvertBufferSource.h" +#include "JSDOMWrapperCache.h" +#include <heap/HeapInlines.h> +#include <runtime/IdentifierInlines.h> #include <wtf/StdLibExtras.h> #include <wtf/text/WTFString.h> @@ -34,21 +37,22 @@ using namespace JSC; namespace WebCore { -JSValue toJS(ExecState* exec, JSDOMGlobalObject* globalObject, ImageData* imageData) +JSValue toJSNewlyCreated(ExecState* state, JSDOMGlobalObject* globalObject, Ref<ImageData>&& imageData) { - if (!imageData) - return jsNull(); - - JSObject* wrapper = getCachedWrapper(currentWorld(exec), imageData); - if (wrapper) - return wrapper; - - wrapper = CREATE_DOM_WRAPPER(exec, globalObject, ImageData, imageData); - Identifier dataName(exec, "data"); - wrapper->putDirect(exec->vm(), dataName, toJS(exec, globalObject, imageData->data()), DontDelete | ReadOnly); - exec->heap()->reportExtraMemoryCost(imageData->data()->length()); + auto* data = imageData->data(); + auto* wrapper = createWrapper<ImageData>(globalObject, WTFMove(imageData)); + Identifier dataName = Identifier::fromString(state, "data"); + wrapper->putDirect(state->vm(), dataName, toJS(state, globalObject, data), DontDelete | ReadOnly); + // FIXME: Adopt reportExtraMemoryVisited, and switch to reportExtraMemoryAllocated. + // https://bugs.webkit.org/show_bug.cgi?id=142595 + state->heap()->deprecatedReportExtraMemory(data->length()); return wrapper; } +JSValue toJS(ExecState* state, JSDOMGlobalObject* globalObject, ImageData& imageData) +{ + return wrap(state, globalObject, imageData); +} + } diff --git a/Source/WebCore/bindings/js/JSInspectorFrontendHostCustom.cpp b/Source/WebCore/bindings/js/JSInspectorFrontendHostCustom.cpp index 2175181d1..447dde627 100644 --- a/Source/WebCore/bindings/js/JSInspectorFrontendHostCustom.cpp +++ b/Source/WebCore/bindings/js/JSInspectorFrontendHostCustom.cpp @@ -31,90 +31,51 @@ */ #include "config.h" - -#if ENABLE(INSPECTOR) - #include "JSInspectorFrontendHost.h" #include "ContextMenuItem.h" #include "InspectorController.h" #include "InspectorFrontendHost.h" +#include "JSDOMBinding.h" #include "JSEvent.h" #include "MouseEvent.h" #include <runtime/JSArray.h> #include <runtime/JSLock.h> #include <runtime/JSObject.h> -#include <wtf/Vector.h> #include <wtf/text/WTFString.h> using namespace JSC; namespace WebCore { -JSValue JSInspectorFrontendHost::platform(ExecState* execState) -{ -#if PLATFORM(MAC) - DEFINE_STATIC_LOCAL(const String, platform, (ASCIILiteral("mac"))); -#elif OS(WINDOWS) - DEFINE_STATIC_LOCAL(const String, platform, (ASCIILiteral("windows"))); -#elif OS(LINUX) - DEFINE_STATIC_LOCAL(const String, platform, (ASCIILiteral("linux"))); -#elif OS(FREEBSD) - DEFINE_STATIC_LOCAL(const String, platform, (ASCIILiteral("freebsd"))); -#elif OS(OPENBSD) - DEFINE_STATIC_LOCAL(const String, platform, (ASCIILiteral("openbsd"))); -#elif OS(SOLARIS) - DEFINE_STATIC_LOCAL(const String, platform, (ASCIILiteral("solaris"))); -#else - DEFINE_STATIC_LOCAL(const String, platform, (ASCIILiteral("unknown"))); -#endif - return jsStringWithCache(execState, platform); -} - -JSValue JSInspectorFrontendHost::port(ExecState* execState) -{ -#if PLATFORM(GTK) - DEFINE_STATIC_LOCAL(const String, port, (ASCIILiteral("gtk"))); -#elif PLATFORM(EFL) - DEFINE_STATIC_LOCAL(const String, port, (ASCIILiteral("efl"))); -#else - DEFINE_STATIC_LOCAL(const String, port, (ASCIILiteral("unknown"))); -#endif - return jsStringWithCache(execState, port); -} - #if ENABLE(CONTEXT_MENUS) static void populateContextMenuItems(ExecState* exec, JSArray* array, ContextMenu& menu) { + VM& vm = exec->vm(); for (size_t i = 0; i < array->length(); ++i) { JSObject* item = asObject(array->getIndex(exec, i)); - JSValue label = item->get(exec, Identifier(exec, "label")); - JSValue type = item->get(exec, Identifier(exec, "type")); - JSValue id = item->get(exec, Identifier(exec, "id")); - JSValue enabled = item->get(exec, Identifier(exec, "enabled")); - JSValue checked = item->get(exec, Identifier(exec, "checked")); - JSValue subItems = item->get(exec, Identifier(exec, "subItems")); + JSValue label = item->get(exec, Identifier::fromString(exec, "label")); + JSValue type = item->get(exec, Identifier::fromString(exec, "type")); + JSValue id = item->get(exec, Identifier::fromString(exec, "id")); + JSValue enabled = item->get(exec, Identifier::fromString(exec, "enabled")); + JSValue checked = item->get(exec, Identifier::fromString(exec, "checked")); + JSValue subItems = item->get(exec, Identifier::fromString(exec, "subItems")); if (!type.isString()) continue; - String typeString = type.toString(exec)->value(exec); + String typeString = asString(type)->value(exec); if (typeString == "separator") { - ContextMenuItem item(SeparatorType, - ContextMenuItemCustomTagNoAction, - String()); + ContextMenuItem item(SeparatorType, ContextMenuItemTagNoAction, String()); menu.appendItem(item); - } else if (typeString == "subMenu" && subItems.inherits(JSArray::info())) { + } else if (typeString == "subMenu" && subItems.inherits(vm, JSArray::info())) { ContextMenu subMenu; JSArray* subItemsArray = asArray(subItems); populateContextMenuItems(exec, subItemsArray, subMenu); - ContextMenuItem item(SubmenuType, - ContextMenuItemCustomTagNoAction, - label.toString(exec)->value(exec), - &subMenu); + ContextMenuItem item(SubmenuType, ContextMenuItemTagNoAction, label.toWTFString(exec), &subMenu); menu.appendItem(item); } else { ContextMenuAction typedId = static_cast<ContextMenuAction>(ContextMenuItemBaseCustomTag + id.toInt32(exec)); - ContextMenuItem menuItem((typeString == "checkbox" ? CheckableActionType : ActionType), typedId, label.toString(exec)->value(exec)); + ContextMenuItem menuItem((typeString == "checkbox" ? CheckableActionType : ActionType), typedId, label.toWTFString(exec)); if (!enabled.isUndefined()) menuItem.setEnabled(enabled.toBoolean(exec)); if (!checked.isUndefined()) @@ -125,44 +86,23 @@ static void populateContextMenuItems(ExecState* exec, JSArray* array, ContextMen } #endif -JSValue JSInspectorFrontendHost::showContextMenu(ExecState* exec) +JSValue JSInspectorFrontendHost::showContextMenu(ExecState& state) { #if ENABLE(CONTEXT_MENUS) - if (exec->argumentCount() < 2) + if (state.argumentCount() < 2) return jsUndefined(); - Event* event = toEvent(exec->argument(0)); + VM& vm = state.vm(); + Event* event = JSEvent::toWrapped(vm, state.argument(0)); - JSArray* array = asArray(exec->argument(1)); + JSArray* array = asArray(state.argument(1)); ContextMenu menu; - populateContextMenuItems(exec, array, menu); + populateContextMenuItems(&state, array, menu); -#if !USE(CROSS_PLATFORM_CONTEXT_MENUS) - Vector<ContextMenuItem> items = contextMenuItemVector(menu.platformDescription()); -#else - Vector<ContextMenuItem> items = menu.items(); -#endif - impl().showContextMenu(event, items); + wrapped().showContextMenu(event, menu.items()); #else - UNUSED_PARAM(exec); + UNUSED_PARAM(state); #endif return jsUndefined(); } -JSValue JSInspectorFrontendHost::recordActionTaken(ExecState*) -{ - return jsUndefined(); -} - -JSValue JSInspectorFrontendHost::recordPanelShown(ExecState*) -{ - return jsUndefined(); -} - -JSValue JSInspectorFrontendHost::recordSettingChanged(ExecState*) -{ - return jsUndefined(); -} - } // namespace WebCore - -#endif // ENABLE(INSPECTOR) diff --git a/Source/WebCore/bindings/js/JSLazyEventListener.cpp b/Source/WebCore/bindings/js/JSLazyEventListener.cpp index 01aee7fba..d270b2696 100644 --- a/Source/WebCore/bindings/js/JSLazyEventListener.cpp +++ b/Source/WebCore/bindings/js/JSLazyEventListener.cpp @@ -1,6 +1,6 @@ /* * Copyright (C) 2001 Peter Kelly (pmk@post.com) - * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2013 Apple Inc. All Rights Reserved. + * Copyright (C) 2003-2016 Apple Inc. All Rights Reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,11 +20,13 @@ #include "config.h" #include "JSLazyEventListener.h" +#include "CachedScriptFetcher.h" #include "ContentSecurityPolicy.h" #include "Frame.h" #include "JSNode.h" #include "ScriptController.h" #include <runtime/FunctionConstructor.h> +#include <runtime/IdentifierInlines.h> #include <wtf/NeverDestroyed.h> #include <wtf/RefCountedLeakCounter.h> #include <wtf/StdLibExtras.h> @@ -35,13 +37,13 @@ namespace WebCore { DEFINE_DEBUG_ONLY_GLOBAL(WTF::RefCountedLeakCounter, eventListenerCounter, ("JSLazyEventListener")); -JSLazyEventListener::JSLazyEventListener(const String& functionName, const String& eventParameterName, const String& code, ContainerNode* node, const String& sourceURL, const TextPosition& position, JSObject* wrapper, DOMWrapperWorld& isolatedWorld) +JSLazyEventListener::JSLazyEventListener(const String& functionName, const String& eventParameterName, const String& code, ContainerNode* node, const String& sourceURL, const TextPosition& sourcePosition, JSObject* wrapper, DOMWrapperWorld& isolatedWorld) : JSEventListener(0, wrapper, true, isolatedWorld) , m_functionName(functionName) , m_eventParameterName(eventParameterName) , m_code(code) , m_sourceURL(sourceURL) - , m_position(position) + , m_sourcePosition(sourcePosition) , m_originalNode(node) { // We don't retain the original node because we assume it @@ -52,8 +54,8 @@ JSLazyEventListener::JSLazyEventListener(const String& functionName, const Strin // A JSLazyEventListener can be created with a line number of zero when it is created with // a setAttribute call from JavaScript, so make the line number 1 in that case. - if (m_position == TextPosition::belowRangePosition()) - m_position = TextPosition::minimumPosition(); + if (m_sourcePosition == TextPosition::belowRangePosition()) + m_sourcePosition = TextPosition(); ASSERT(m_eventParameterName == "evt" || m_eventParameterName == "event"); @@ -71,57 +73,66 @@ JSLazyEventListener::~JSLazyEventListener() JSObject* JSLazyEventListener::initializeJSFunction(ScriptExecutionContext* executionContext) const { - ASSERT(executionContext); - ASSERT(executionContext->isDocument()); + ASSERT(is<Document>(executionContext)); if (!executionContext) - return 0; + return nullptr; ASSERT(!m_code.isNull()); ASSERT(!m_eventParameterName.isNull()); if (m_code.isNull() || m_eventParameterName.isNull()) - return 0; + return nullptr; - Document* document = toDocument(executionContext); + Document& document = downcast<Document>(*executionContext); - if (!document->frame()) - return 0; + if (!document.frame()) + return nullptr; - if (!document->contentSecurityPolicy()->allowInlineEventHandlers(m_sourceURL, m_position.m_line)) - return 0; + if (!document.contentSecurityPolicy()->allowInlineEventHandlers(m_sourceURL, m_sourcePosition.m_line)) + return nullptr; - ScriptController& script = document->frame()->script(); + ScriptController& script = document.frame()->script(); if (!script.canExecuteScripts(AboutToExecuteScript) || script.isPaused()) - return 0; + return nullptr; JSDOMGlobalObject* globalObject = toJSDOMGlobalObject(executionContext, isolatedWorld()); if (!globalObject) - return 0; + return nullptr; + VM& vm = globalObject->vm(); + JSLockHolder lock(vm); + auto scope = DECLARE_CATCH_SCOPE(vm); ExecState* exec = globalObject->globalExec(); MarkedArgumentBuffer args; args.append(jsNontrivialString(exec, m_eventParameterName)); args.append(jsStringWithCache(exec, m_code)); - JSObject* jsFunction = constructFunctionSkippingEvalEnabledCheck(exec, exec->lexicalGlobalObject(), args, Identifier(exec, m_functionName), m_sourceURL, m_position); // FIXME: is globalExec ok? - if (exec->hadException()) { + // We want all errors to refer back to the line on which our attribute was + // declared, regardless of any newlines in our JavaScript source text. + int overrideLineNumber = m_sourcePosition.m_line.oneBasedInt(); + + JSObject* jsFunction = constructFunctionSkippingEvalEnabledCheck( + exec, exec->lexicalGlobalObject(), args, Identifier::fromString(exec, m_functionName), + SourceOrigin { m_sourceURL, CachedScriptFetcher::create(document.charset()) }, m_sourceURL, m_sourcePosition, overrideLineNumber); + + if (UNLIKELY(scope.exception())) { reportCurrentException(exec); - exec->clearException(); - return 0; + scope.clearException(); + return nullptr; } JSFunction* listenerAsFunction = jsCast<JSFunction*>(jsFunction); + if (m_originalNode) { if (!wrapper()) { // Ensure that 'node' has a JavaScript wrapper to mark the event listener we're creating. - JSLockHolder lock(exec); // FIXME: Should pass the global object associated with the node - setWrapper(exec->vm(), asObject(toJS(exec, globalObject, m_originalNode))); + setWrapper(vm, asObject(toJS(exec, globalObject, *m_originalNode))); } // Add the event's home element to the scope // (and the document, and the form - see JSHTMLElement::eventHandlerScope) - listenerAsFunction->setScope(exec->vm(), jsCast<JSNode*>(wrapper())->pushEventHandlerScope(exec, listenerAsFunction->scope())); + listenerAsFunction->setScope(vm, jsCast<JSNode*>(wrapper())->pushEventHandlerScope(exec, listenerAsFunction->scope())); } return jsFunction; } @@ -133,40 +144,53 @@ static const String& eventParameterName(bool isSVGEvent) return isSVGEvent ? evtString : eventString; } -PassRefPtr<JSLazyEventListener> JSLazyEventListener::createForNode(ContainerNode& node, const QualifiedName& attributeName, const AtomicString& attributeValue) +struct JSLazyEventListener::CreationArguments { + const QualifiedName& attributeName; + const AtomicString& attributeValue; + Document& document; + ContainerNode* node; + JSC::JSObject* wrapper; + bool shouldUseSVGEventName; +}; + +RefPtr<JSLazyEventListener> JSLazyEventListener::create(const CreationArguments& arguments) { - if (attributeValue.isNull()) + if (arguments.attributeValue.isNull()) return nullptr; - TextPosition position = TextPosition::minimumPosition(); - String sourceURL; - // FIXME: We should be able to provide source information for frameless documents too (e.g. for importing nodes from XMLHttpRequest.responseXML). - if (Frame* frame = node.document().frame()) { + TextPosition position; + String sourceURL; + if (Frame* frame = arguments.document.frame()) { if (!frame->script().canExecuteScripts(AboutToExecuteScript)) return nullptr; - position = frame->script().eventHandlerPosition(); - sourceURL = node.document().url().string(); + sourceURL = arguments.document.url().string(); } - return adoptRef(new JSLazyEventListener(attributeName.localName().string(), - eventParameterName(node.isSVGElement()), attributeValue, - &node, sourceURL, position, nullptr, mainThreadNormalWorld())); + return adoptRef(*new JSLazyEventListener(arguments.attributeName.localName().string(), + eventParameterName(arguments.shouldUseSVGEventName), arguments.attributeValue, + arguments.node, sourceURL, position, arguments.wrapper, mainThreadNormalWorld())); } -PassRefPtr<JSLazyEventListener> JSLazyEventListener::createForDOMWindow(Frame& frame, const QualifiedName& attributeName, const AtomicString& attributeValue) +RefPtr<JSLazyEventListener> JSLazyEventListener::create(Element& element, const QualifiedName& attributeName, const AtomicString& attributeValue) { - if (attributeValue.isNull()) - return nullptr; + return create({ attributeName, attributeValue, element.document(), &element, nullptr, element.isSVGElement() }); +} - if (!frame.script().canExecuteScripts(AboutToExecuteScript)) - return nullptr; +RefPtr<JSLazyEventListener> JSLazyEventListener::create(Document& document, const QualifiedName& attributeName, const AtomicString& attributeValue) +{ + // FIXME: This always passes false for "shouldUseSVGEventName". Is that correct for events dispatched to SVG documents? + // This has been this way for a long time, but became more obvious when refactoring to separate the Element and Document code paths. + return create({ attributeName, attributeValue, document, &document, nullptr, false }); +} - return adoptRef(new JSLazyEventListener(attributeName.localName().string(), - eventParameterName(frame.document()->isSVGDocument()), attributeValue, - nullptr, frame.document()->url().string(), frame.script().eventHandlerPosition(), - toJSDOMWindow(&frame, mainThreadNormalWorld()), mainThreadNormalWorld())); +RefPtr<JSLazyEventListener> JSLazyEventListener::create(DOMWindow& window, const QualifiedName& attributeName, const AtomicString& attributeValue) +{ + ASSERT(window.document()); + auto& document = *window.document(); + ASSERT(document.frame()); + return create({ attributeName, attributeValue, document, nullptr, toJSDOMWindow(document.frame(), mainThreadNormalWorld()), document.isSVGDocument() }); } } // namespace WebCore diff --git a/Source/WebCore/bindings/js/JSLazyEventListener.h b/Source/WebCore/bindings/js/JSLazyEventListener.h index 31900178c..9c2849ebb 100644 --- a/Source/WebCore/bindings/js/JSLazyEventListener.h +++ b/Source/WebCore/bindings/js/JSLazyEventListener.h @@ -1,6 +1,6 @@ /* * Copyright (C) 2001 Peter Kelly (pmk@post.com) - * Copyright (C) 2003, 2008, 2009, 2013 Apple Inc. All rights reserved. + * Copyright (C) 2003-2016 Apple Inc. All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -17,42 +17,44 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#ifndef JSLazyEventListener_h -#define JSLazyEventListener_h +#pragma once #include "JSEventListener.h" -#include <wtf/text/TextPosition.h> -#include <wtf/text/WTFString.h> namespace WebCore { - class ContainerNode; - class Frame; - class QualifiedName; +class ContainerNode; +class DOMWindow; +class Document; +class Element; +class QualifiedName; - class JSLazyEventListener final : public JSEventListener { - public: - static PassRefPtr<JSLazyEventListener> createForNode(ContainerNode&, const QualifiedName& attributeName, const AtomicString& attributeValue); - static PassRefPtr<JSLazyEventListener> createForDOMWindow(Frame&, const QualifiedName& attributeName, const AtomicString& attributeValue); +class JSLazyEventListener final : public JSEventListener { +public: + static RefPtr<JSLazyEventListener> create(Element&, const QualifiedName& attributeName, const AtomicString& attributeValue); + static RefPtr<JSLazyEventListener> create(Document&, const QualifiedName& attributeName, const AtomicString& attributeValue); + static RefPtr<JSLazyEventListener> create(DOMWindow&, const QualifiedName& attributeName, const AtomicString& attributeValue); - virtual ~JSLazyEventListener(); + virtual ~JSLazyEventListener(); - private: - JSLazyEventListener(const String& functionName, const String& eventParameterName, const String& code, ContainerNode*, const String& sourceURL, const TextPosition&, JSC::JSObject* wrapper, DOMWrapperWorld& isolatedWorld); + String sourceURL() const final { return m_sourceURL; } + TextPosition sourcePosition() const final { return m_sourcePosition; } - virtual JSC::JSObject* initializeJSFunction(ScriptExecutionContext*) const override; - virtual bool wasCreatedFromMarkup() const override { return true; } +private: + struct CreationArguments; + static RefPtr<JSLazyEventListener> create(const CreationArguments&); - static void create() = delete; + JSLazyEventListener(const String& functionName, const String& eventParameterName, const String& code, ContainerNode*, const String& sourceURL, const TextPosition&, JSC::JSObject* wrapper, DOMWrapperWorld& isolatedWorld); - mutable String m_functionName; - mutable String m_eventParameterName; - mutable String m_code; - mutable String m_sourceURL; - TextPosition m_position; - ContainerNode* m_originalNode; - }; + JSC::JSObject* initializeJSFunction(ScriptExecutionContext*) const override; + bool wasCreatedFromMarkup() const override { return true; } -} // namespace WebCore + String m_functionName; + String m_eventParameterName; + String m_code; + String m_sourceURL; + TextPosition m_sourcePosition; + ContainerNode* m_originalNode; +}; -#endif // JSLazyEventListener_h +} // namespace WebCore diff --git a/Source/WebCore/bindings/js/JSLocationCustom.cpp b/Source/WebCore/bindings/js/JSLocationCustom.cpp index c99f904d8..57eb752da 100644 --- a/Source/WebCore/bindings/js/JSLocationCustom.cpp +++ b/Source/WebCore/bindings/js/JSLocationCustom.cpp @@ -23,31 +23,23 @@ #include "config.h" #include "JSLocation.h" -#include "Location.h" +#include "JSDOMBinding.h" +#include "JSDOMBindingSecurity.h" +#include "JSDOMExceptionHandling.h" +#include "RuntimeApplicationChecks.h" #include <runtime/JSFunction.h> +#include <runtime/Lookup.h> using namespace JSC; namespace WebCore { -static EncodedJSValue nonCachingStaticReplaceFunctionGetter(ExecState* exec, EncodedJSValue, EncodedJSValue, PropertyName propertyName) +bool JSLocation::getOwnPropertySlotDelegate(ExecState* state, PropertyName propertyName, PropertySlot& slot) { - return JSValue::encode(JSFunction::create(exec->vm(), exec->lexicalGlobalObject(), 1, propertyName.publicName(), jsLocationPrototypeFunctionReplace)); -} - -static EncodedJSValue nonCachingStaticReloadFunctionGetter(ExecState* exec, EncodedJSValue, EncodedJSValue, PropertyName propertyName) -{ - return JSValue::encode(JSFunction::create(exec->vm(), exec->lexicalGlobalObject(), 0, propertyName.publicName(), jsLocationPrototypeFunctionReload)); -} + VM& vm = state->vm(); + auto scope = DECLARE_THROW_SCOPE(vm); -static EncodedJSValue nonCachingStaticAssignFunctionGetter(ExecState* exec, EncodedJSValue, EncodedJSValue, PropertyName propertyName) -{ - return JSValue::encode(JSFunction::create(exec->vm(), exec->lexicalGlobalObject(), 1, propertyName.publicName(), jsLocationPrototypeFunctionAssign)); -} - -bool JSLocation::getOwnPropertySlotDelegate(ExecState* exec, PropertyName propertyName, PropertySlot& slot) -{ - Frame* frame = impl().frame(); + Frame* frame = wrapped().frame(); if (!frame) { slot.setUndefined(); return true; @@ -59,56 +51,55 @@ bool JSLocation::getOwnPropertySlotDelegate(ExecState* exec, PropertyName proper // Our custom code is only needed to implement the Window cross-domain scheme, so if access is // allowed, return false so the normal lookup will take place. String message; - if (shouldAllowAccessToFrame(exec, frame, message)) + if (BindingSecurity::shouldAllowAccessToFrame(*state, *frame, message)) return false; - // Check for the few functions that we allow, even when called cross-domain. - // Make these read-only / non-configurable to prevent writes via defineProperty. - const HashEntry* entry = JSLocationPrototype::info()->propHashTable(exec)->entry(exec, propertyName); - if (entry && (entry->attributes() & JSC::Function)) { - if (entry->function() == jsLocationPrototypeFunctionReplace) { - slot.setCustom(this, ReadOnly | DontDelete | DontEnum, nonCachingStaticReplaceFunctionGetter); - return true; - } else if (entry->function() == jsLocationPrototypeFunctionReload) { - slot.setCustom(this, ReadOnly | DontDelete | DontEnum, nonCachingStaticReloadFunctionGetter); - return true; - } else if (entry->function() == jsLocationPrototypeFunctionAssign) { - slot.setCustom(this, ReadOnly | DontDelete | DontEnum, nonCachingStaticAssignFunctionGetter); - return true; - } + // https://html.spec.whatwg.org/#crossorigingetownpropertyhelper-(-o,-p-) + if (propertyName == state->propertyNames().toStringTagSymbol || propertyName == state->propertyNames().hasInstanceSymbol || propertyName == state->propertyNames().isConcatSpreadableSymbol) { + slot.setValue(this, ReadOnly | DontEnum, jsUndefined()); + return true; } - // FIXME: Other implementers of the Window cross-domain scheme (Window, History) allow toString, - // but for now we have decided not to, partly because it seems silly to return "[Object Location]" in - // such cases when normally the string form of Location would be the URL. + // We only allow access to Location.replace() cross origin. + if (propertyName == state->propertyNames().replace) { + slot.setCustom(this, ReadOnly | DontEnum, nonCachingStaticFunctionGetter<jsLocationInstanceFunctionReplace, 1>); + return true; + } - printErrorMessageForFrame(frame, message); + // Getting location.href cross origin needs to throw. However, getOwnPropertyDescriptor() needs to return + // a descriptor that has a setter but no getter. + if (slot.internalMethodType() == PropertySlot::InternalMethodType::GetOwnProperty && propertyName == state->propertyNames().href) { + auto* entry = JSLocation::info()->staticPropHashTable->entry(propertyName); + CustomGetterSetter* customGetterSetter = CustomGetterSetter::create(vm, nullptr, entry->propertyPutter()); + slot.setCustomGetterSetter(this, DontEnum | CustomAccessor, customGetterSetter); + return true; + } + + throwSecurityError(*state, scope, message); slot.setUndefined(); return true; } -bool JSLocation::putDelegate(ExecState* exec, PropertyName propertyName, JSValue value, PutPropertySlot& slot) +bool JSLocation::putDelegate(ExecState* state, PropertyName propertyName, JSValue, PutPropertySlot&, bool& putResult) { - Frame* frame = impl().frame(); + putResult = false; + + Frame* frame = wrapped().frame(); if (!frame) return true; - if (propertyName == exec->propertyNames().toString || propertyName == exec->propertyNames().valueOf) + // Silently block access to toString and valueOf. + if (propertyName == state->propertyNames().toString || propertyName == state->propertyNames().valueOf) return true; - bool sameDomainAccess = shouldAllowAccessToFrame(exec, frame); - - const HashEntry* entry = JSLocation::info()->propHashTable(exec)->entry(exec, propertyName); - if (!entry) { - if (sameDomainAccess) - JSObject::put(this, exec, propertyName, value, slot); - return true; - } + // Always allow assigning to the whole location. + // However, alllowing assigning of pieces might inadvertently disclose parts of the original location. + // So fall through to the access check for those. + if (propertyName == state->propertyNames().href) + return false; - // Cross-domain access to the location is allowed when assigning the whole location, - // but not when assigning the individual pieces, since that might inadvertently - // disclose other parts of the original location. - if (entry->propertyPutter() != setJSLocationHref && !sameDomainAccess) + // Block access and throw if there is a security error. + if (!BindingSecurity::shouldAllowAccessToFrame(state, frame, ThrowSecurityError)) return true; return false; @@ -118,7 +109,7 @@ bool JSLocation::deleteProperty(JSCell* cell, ExecState* exec, PropertyName prop { JSLocation* thisObject = jsCast<JSLocation*>(cell); // Only allow deleting by frames in the same origin. - if (!shouldAllowAccessToFrame(exec, thisObject->impl().frame())) + if (!BindingSecurity::shouldAllowAccessToFrame(exec, thisObject->wrapped().frame(), ThrowSecurityError)) return false; return Base::deleteProperty(thisObject, exec, propertyName); } @@ -127,128 +118,89 @@ bool JSLocation::deletePropertyByIndex(JSCell* cell, ExecState* exec, unsigned p { JSLocation* thisObject = jsCast<JSLocation*>(cell); // Only allow deleting by frames in the same origin. - if (!shouldAllowAccessToFrame(exec, thisObject->impl().frame())) + if (!BindingSecurity::shouldAllowAccessToFrame(exec, thisObject->wrapped().frame(), ThrowSecurityError)) return false; return Base::deletePropertyByIndex(thisObject, exec, propertyName); } -void JSLocation::getOwnPropertyNames(JSObject* object, ExecState* exec, PropertyNameArray& propertyNames, EnumerationMode mode) +// https://html.spec.whatwg.org/#crossoriginproperties-(-o-) +static void addCrossOriginPropertyNames(ExecState& state, PropertyNameArray& propertyNames) { - JSLocation* thisObject = jsCast<JSLocation*>(object); - // Only allow the location object to enumerated by frames in the same origin. - if (!shouldAllowAccessToFrame(exec, thisObject->impl().frame())) - return; - Base::getOwnPropertyNames(thisObject, exec, propertyNames, mode); + static const Identifier* const properties[] = { &state.propertyNames().href, &state.propertyNames().replace }; + for (auto* property : properties) + propertyNames.add(*property); } -bool JSLocation::defineOwnProperty(JSObject* object, ExecState* exec, PropertyName propertyName, const PropertyDescriptor& descriptor, bool throwException) +// https://html.spec.whatwg.org/#crossoriginownpropertykeys-(-o-) +static void addCrossOriginOwnPropertyNames(ExecState& state, PropertyNameArray& propertyNames) { - if (descriptor.isAccessorDescriptor() && (propertyName == exec->propertyNames().toString || propertyName == exec->propertyNames().valueOf)) - return false; - return Base::defineOwnProperty(object, exec, propertyName, descriptor, throwException); -} + addCrossOriginPropertyNames(state, propertyNames); -void JSLocation::setHref(ExecState* exec, JSValue value) -{ - String href = value.toString(exec)->value(exec); - if (exec->hadException()) - return; - impl().setHref(href, activeDOMWindow(exec), firstDOMWindow(exec)); + propertyNames.add(state.propertyNames().toStringTagSymbol); + propertyNames.add(state.propertyNames().hasInstanceSymbol); + propertyNames.add(state.propertyNames().isConcatSpreadableSymbol); } -void JSLocation::setProtocol(ExecState* exec, JSValue value) +void JSLocation::getOwnPropertyNames(JSObject* object, ExecState* exec, PropertyNameArray& propertyNames, EnumerationMode mode) { - String protocol = value.toString(exec)->value(exec); - if (exec->hadException()) + JSLocation* thisObject = jsCast<JSLocation*>(object); + if (!BindingSecurity::shouldAllowAccessToFrame(exec, thisObject->wrapped().frame(), DoNotReportSecurityError)) { + if (mode.includeDontEnumProperties()) + addCrossOriginOwnPropertyNames(*exec, propertyNames); return; - ExceptionCode ec = 0; - impl().setProtocol(protocol, activeDOMWindow(exec), firstDOMWindow(exec), ec); - setDOMException(exec, ec); + } + Base::getOwnPropertyNames(thisObject, exec, propertyNames, mode); } -void JSLocation::setHost(ExecState* exec, JSValue value) +bool JSLocation::defineOwnProperty(JSObject* object, ExecState* exec, PropertyName propertyName, const PropertyDescriptor& descriptor, bool throwException) { - String host = value.toString(exec)->value(exec); - if (exec->hadException()) - return; - impl().setHost(host, activeDOMWindow(exec), firstDOMWindow(exec)); -} + JSLocation* thisObject = jsCast<JSLocation*>(object); + if (!BindingSecurity::shouldAllowAccessToFrame(exec, thisObject->wrapped().frame(), ThrowSecurityError)) + return false; -void JSLocation::setHostname(ExecState* exec, JSValue value) -{ - String hostname = value.toString(exec)->value(exec); - if (exec->hadException()) - return; - impl().setHostname(hostname, activeDOMWindow(exec), firstDOMWindow(exec)); + if (descriptor.isAccessorDescriptor() && (propertyName == exec->propertyNames().toString || propertyName == exec->propertyNames().valueOf)) + return false; + return Base::defineOwnProperty(object, exec, propertyName, descriptor, throwException); } -void JSLocation::setPort(ExecState* exec, JSValue value) +bool JSLocation::setPrototype(JSObject*, ExecState* exec, JSValue, bool shouldThrowIfCantSet) { - String port = value.toWTFString(exec); - if (exec->hadException()) - return; - impl().setPort(port, activeDOMWindow(exec), firstDOMWindow(exec)); -} + auto scope = DECLARE_THROW_SCOPE(exec->vm()); -void JSLocation::setPathname(ExecState* exec, JSValue value) -{ - String pathname = value.toString(exec)->value(exec); - if (exec->hadException()) - return; - impl().setPathname(pathname, activeDOMWindow(exec), firstDOMWindow(exec)); -} + if (shouldThrowIfCantSet) + throwTypeError(exec, scope, ASCIILiteral("Cannot set prototype of this object")); -void JSLocation::setSearch(ExecState* exec, JSValue value) -{ - String pathname = value.toString(exec)->value(exec); - if (exec->hadException()) - return; - impl().setSearch(pathname, activeDOMWindow(exec), firstDOMWindow(exec)); + return false; } -void JSLocation::setHash(ExecState* exec, JSValue value) +JSValue JSLocation::getPrototype(JSObject* object, ExecState* exec) { - String hash = value.toString(exec)->value(exec); - if (exec->hadException()) - return; - impl().setHash(hash, activeDOMWindow(exec), firstDOMWindow(exec)); -} + JSLocation* thisObject = jsCast<JSLocation*>(object); + if (!BindingSecurity::shouldAllowAccessToFrame(exec, thisObject->wrapped().frame(), DoNotReportSecurityError)) + return jsNull(); -JSValue JSLocation::replace(ExecState* exec) -{ - String urlString = exec->argument(0).toString(exec)->value(exec); - if (exec->hadException()) - return jsUndefined(); - impl().replace(urlString, activeDOMWindow(exec), firstDOMWindow(exec)); - return jsUndefined(); + return Base::getPrototype(object, exec); } -JSValue JSLocation::reload(ExecState* exec) +bool JSLocation::preventExtensions(JSObject*, ExecState* exec) { - impl().reload(activeDOMWindow(exec)); - return jsUndefined(); -} + auto scope = DECLARE_THROW_SCOPE(exec->vm()); -JSValue JSLocation::assign(ExecState* exec) -{ - String urlString = exec->argument(0).toString(exec)->value(exec); - if (exec->hadException()) - return jsUndefined(); - impl().assign(urlString, activeDOMWindow(exec), firstDOMWindow(exec)); - return jsUndefined(); + throwTypeError(exec, scope, ASCIILiteral("Cannot prevent extensions on this object")); + return false; } -JSValue JSLocation::toStringFunction(ExecState* exec) +String JSLocation::toStringName(const JSObject* object, ExecState* exec) { - Frame* frame = impl().frame(); - if (!frame || !shouldAllowAccessToFrame(exec, frame)) - return jsUndefined(); - - return jsStringWithCache(exec, impl().toString()); + auto* thisObject = jsCast<const JSLocation*>(object); + if (!BindingSecurity::shouldAllowAccessToFrame(exec, thisObject->wrapped().frame(), DoNotReportSecurityError)) + return ASCIILiteral("Object"); + return ASCIILiteral("Location"); } -bool JSLocationPrototype::putDelegate(ExecState* exec, PropertyName propertyName, JSValue, PutPropertySlot&) +bool JSLocationPrototype::putDelegate(ExecState* exec, PropertyName propertyName, JSValue, PutPropertySlot&, bool& putResult) { + putResult = false; return (propertyName == exec->propertyNames().toString || propertyName == exec->propertyNames().valueOf); } diff --git a/Source/WebCore/bindings/js/JSMainThreadExecState.cpp b/Source/WebCore/bindings/js/JSMainThreadExecState.cpp index 779b96ab0..f49f4a87e 100644 --- a/Source/WebCore/bindings/js/JSMainThreadExecState.cpp +++ b/Source/WebCore/bindings/js/JSMainThreadExecState.cpp @@ -25,11 +25,9 @@ #include "config.h" #include "JSMainThreadExecState.h" -#include "MutationObserver.h" -#if ENABLE(INDEXED_DATABASE) -#include "IDBPendingTransactionMonitor.h" -#endif +#include "Microtasks.h" +#include "MutationObserver.h" namespace WebCore { @@ -37,27 +35,21 @@ JSC::ExecState* JSMainThreadExecState::s_mainThreadState = 0; void JSMainThreadExecState::didLeaveScriptContext() { -#if ENABLE(INDEXED_DATABASE) - // Indexed DB requires that transactions are created with an internal |active| flag - // set to true, but the flag becomes false when control returns to the event loop. - IDBPendingTransactionMonitor::deactivateNewTransactions(); -#endif - - MutationObserver::deliverAllMutations(); + MicrotaskQueue::mainThreadQueue().performMicrotaskCheckpoint(); } -JSC::JSValue functionCallHandlerFromAnyThread(JSC::ExecState* exec, JSC::JSValue functionObject, JSC::CallType callType, const JSC::CallData& callData, JSC::JSValue thisValue, const JSC::ArgList& args) +JSC::JSValue functionCallHandlerFromAnyThread(JSC::ExecState* exec, JSC::JSValue functionObject, JSC::CallType callType, const JSC::CallData& callData, JSC::JSValue thisValue, const JSC::ArgList& args, NakedPtr<JSC::Exception>& returnedException) { if (isMainThread()) - return JSMainThreadExecState::call(exec, functionObject, callType, callData, thisValue, args); - return JSC::call(exec, functionObject, callType, callData, thisValue, args); + return JSMainThreadExecState::call(exec, functionObject, callType, callData, thisValue, args, returnedException); + return JSC::call(exec, functionObject, callType, callData, thisValue, args, returnedException); } -JSC::JSValue evaluateHandlerFromAnyThread(JSC::ExecState* exec, const JSC::SourceCode& source, JSC::JSValue thisValue, JSC::JSValue* exception) +JSC::JSValue evaluateHandlerFromAnyThread(JSC::ExecState* exec, const JSC::SourceCode& source, JSC::JSValue thisValue, NakedPtr<JSC::Exception>& returnedException) { if (isMainThread()) - return JSMainThreadExecState::evaluate(exec, source, thisValue, exception); - return JSC::evaluate(exec, source, thisValue, exception); + return JSMainThreadExecState::evaluate(exec, source, thisValue, returnedException); + return JSC::evaluate(exec, source, thisValue, returnedException); } } // namespace WebCore diff --git a/Source/WebCore/bindings/js/JSMainThreadExecState.h b/Source/WebCore/bindings/js/JSMainThreadExecState.h index ed023dbe2..d244efe0e 100644 --- a/Source/WebCore/bindings/js/JSMainThreadExecState.h +++ b/Source/WebCore/bindings/js/JSMainThreadExecState.h @@ -1,5 +1,6 @@ /* * Copyright (C) 2010 Google Inc. All rights reserved. + * Copyright (C) 2016 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -23,11 +24,12 @@ * THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef JSMainThreadExecState_h -#define JSMainThreadExecState_h +#pragma once +#include "CustomElementReactionQueue.h" #include "JSDOMBinding.h" #include <runtime/Completion.h> +#include <runtime/Microtask.h> #include <wtf/MainThread.h> #if PLATFORM(IOS) @@ -49,23 +51,82 @@ public: return s_mainThreadState; }; - static JSC::JSValue call(JSC::ExecState* exec, JSC::JSValue functionObject, JSC::CallType callType, const JSC::CallData& callData, JSC::JSValue thisValue, const JSC::ArgList& args) + static JSC::JSValue call(JSC::ExecState* exec, JSC::JSValue functionObject, JSC::CallType callType, const JSC::CallData& callData, JSC::JSValue thisValue, const JSC::ArgList& args, NakedPtr<JSC::Exception>& returnedException) { JSMainThreadExecState currentState(exec); - return JSC::call(exec, functionObject, callType, callData, thisValue, args); + return JSC::call(exec, functionObject, callType, callData, thisValue, args, returnedException); }; - static JSC::JSValue evaluate(JSC::ExecState* exec, const JSC::SourceCode& source, JSC::JSValue thisValue, JSC::JSValue* exception) + static JSC::JSValue evaluate(JSC::ExecState* exec, const JSC::SourceCode& source, JSC::JSValue thisValue, NakedPtr<JSC::Exception>& returnedException) { JSMainThreadExecState currentState(exec); - JSC::JSLockHolder lock(exec); - return JSC::evaluate(exec, source, thisValue, exception); + return JSC::evaluate(exec, source, thisValue, returnedException); }; + static JSC::JSValue evaluate(JSC::ExecState* exec, const JSC::SourceCode& source, JSC::JSValue thisValue = JSC::JSValue()) + { + NakedPtr<JSC::Exception> unused; + return evaluate(exec, source, thisValue, unused); + }; + + static JSC::JSValue profiledCall(JSC::ExecState* exec, JSC::ProfilingReason reason, JSC::JSValue functionObject, JSC::CallType callType, const JSC::CallData& callData, JSC::JSValue thisValue, const JSC::ArgList& args, NakedPtr<JSC::Exception>& returnedException) + { + JSMainThreadExecState currentState(exec); + return JSC::profiledCall(exec, reason, functionObject, callType, callData, thisValue, args, returnedException); + } + + static JSC::JSValue profiledEvaluate(JSC::ExecState* exec, JSC::ProfilingReason reason, const JSC::SourceCode& source, JSC::JSValue thisValue, NakedPtr<JSC::Exception>& returnedException) + { + JSMainThreadExecState currentState(exec); + return JSC::profiledEvaluate(exec, reason, source, thisValue, returnedException); + } + + static JSC::JSValue profiledEvaluate(JSC::ExecState* exec, JSC::ProfilingReason reason, const JSC::SourceCode& source, JSC::JSValue thisValue = JSC::JSValue()) + { + NakedPtr<JSC::Exception> unused; + return profiledEvaluate(exec, reason, source, thisValue, unused); + } + + static void runTask(JSC::ExecState* exec, JSC::Microtask& task) + { + JSMainThreadExecState currentState(exec); + task.run(exec); + } + + static JSC::JSInternalPromise& loadModule(JSC::ExecState& state, const String& moduleName, JSC::JSValue scriptFetcher) + { + JSMainThreadExecState currentState(&state); + return *JSC::loadModule(&state, moduleName, scriptFetcher); + } + + static JSC::JSInternalPromise& loadModule(JSC::ExecState& state, const JSC::SourceCode& sourceCode, JSC::JSValue scriptFetcher) + { + JSMainThreadExecState currentState(&state); + return *JSC::loadModule(&state, sourceCode, scriptFetcher); + } + + static JSC::JSValue linkAndEvaluateModule(JSC::ExecState& state, const JSC::Identifier& moduleKey, JSC::JSValue scriptFetcher, NakedPtr<JSC::Exception>& returnedException) + { + JSC::VM& vm = state.vm(); + auto scope = DECLARE_CATCH_SCOPE(vm); + + JSMainThreadExecState currentState(&state); + auto returnValue = JSC::linkAndEvaluateModule(&state, moduleKey, scriptFetcher); + if (UNLIKELY(scope.exception())) { + returnedException = scope.exception(); + scope.clearException(); + return JSC::jsUndefined(); + } + return returnValue; + } + static InspectorInstrumentationCookie instrumentFunctionCall(ScriptExecutionContext*, JSC::CallType, const JSC::CallData&); + static InspectorInstrumentationCookie instrumentFunctionConstruct(ScriptExecutionContext*, JSC::ConstructType, const JSC::ConstructData&); +private: explicit JSMainThreadExecState(JSC::ExecState* exec) : m_previousState(s_mainThreadState) + , m_lock(exec) { ASSERT(isMainThread()); s_mainThreadState = exec; @@ -73,7 +134,10 @@ public: ~JSMainThreadExecState() { + JSC::VM& vm = s_mainThreadState->vm(); + auto scope = DECLARE_CATCH_SCOPE(vm); ASSERT(isMainThread()); + ASSERT_UNUSED(scope, !scope.exception()); bool didExitJavaScript = s_mainThreadState && !m_previousState; @@ -83,9 +147,11 @@ public: didLeaveScriptContext(); } -private: - static JSC::ExecState* s_mainThreadState; + template<typename Type, Type jsType, typename DataType> static InspectorInstrumentationCookie instrumentFunctionInternal(ScriptExecutionContext*, Type, const DataType&); + + WEBCORE_EXPORT static JSC::ExecState* s_mainThreadState; JSC::ExecState* m_previousState; + JSC::JSLockHolder m_lock; static void didLeaveScriptContext(); }; @@ -110,11 +176,10 @@ public: private: JSC::ExecState* m_previousState; + CustomElementReactionStack m_customElementReactionStack; }; -JSC::JSValue functionCallHandlerFromAnyThread(JSC::ExecState*, JSC::JSValue functionObject, JSC::CallType callType, const JSC::CallData& callData, JSC::JSValue thisValue, const JSC::ArgList& args); -JSC::JSValue evaluateHandlerFromAnyThread(JSC::ExecState*, const JSC::SourceCode&, JSC::JSValue thisValue, JSC::JSValue* exception); +JSC::JSValue functionCallHandlerFromAnyThread(JSC::ExecState*, JSC::JSValue functionObject, JSC::CallType, const JSC::CallData&, JSC::JSValue thisValue, const JSC::ArgList& args, NakedPtr<JSC::Exception>& returnedException); +JSC::JSValue evaluateHandlerFromAnyThread(JSC::ExecState*, const JSC::SourceCode&, JSC::JSValue thisValue, NakedPtr<JSC::Exception>& returnedException); } // namespace WebCore - -#endif // JSMainThreadExecState_h diff --git a/Source/WebCore/bindings/js/JSMainThreadExecStateInstrumentation.h b/Source/WebCore/bindings/js/JSMainThreadExecStateInstrumentation.h index de4524696..4ad6e3201 100644 --- a/Source/WebCore/bindings/js/JSMainThreadExecStateInstrumentation.h +++ b/Source/WebCore/bindings/js/JSMainThreadExecStateInstrumentation.h @@ -24,29 +24,37 @@ * THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef JSMainThreadExecStateInstrumentation_h -#define JSMainThreadExecStateInstrumentation_h +#pragma once #include "InspectorInstrumentation.h" #include "JSMainThreadExecState.h" -#include <runtime/Executable.h> +#include <runtime/FunctionExecutable.h> namespace WebCore { -inline InspectorInstrumentationCookie JSMainThreadExecState::instrumentFunctionCall(ScriptExecutionContext* context, JSC::CallType callType, const JSC::CallData& callData) +template<typename Type, Type jsType, class DataType> +inline InspectorInstrumentationCookie JSMainThreadExecState::instrumentFunctionInternal(ScriptExecutionContext* context, Type callType, const DataType& callData) { if (!InspectorInstrumentation::timelineAgentEnabled(context)) return InspectorInstrumentationCookie(); String resourceName; int lineNumber = 1; - if (callType == JSC::CallTypeJS) { + if (callType == jsType) { resourceName = callData.js.functionExecutable->sourceURL(); - lineNumber = callData.js.functionExecutable->lineNo(); + lineNumber = callData.js.functionExecutable->firstLine(); } else resourceName = "undefined"; return InspectorInstrumentation::willCallFunction(context, resourceName, lineNumber); } -} // namespace WebCore +inline InspectorInstrumentationCookie JSMainThreadExecState::instrumentFunctionCall(ScriptExecutionContext* context, JSC::CallType type, const JSC::CallData& data) +{ + return instrumentFunctionInternal<JSC::CallType, JSC::CallType::JS, JSC::CallData>(context, type, data); +} -#endif // JSMainThreadExecStateInstrumentation_h +inline InspectorInstrumentationCookie JSMainThreadExecState::instrumentFunctionConstruct(ScriptExecutionContext* context, JSC::ConstructType type, const JSC::ConstructData& data) +{ + return instrumentFunctionInternal<JSC::ConstructType, JSC::ConstructType::JS, JSC::ConstructData>(context, type, data); +} + +} // namespace WebCore diff --git a/Source/WebCore/bindings/js/JSMediaKeySessionCustom.cpp b/Source/WebCore/bindings/js/JSMediaKeySessionCustom.cpp new file mode 100644 index 000000000..4227ccd39 --- /dev/null +++ b/Source/WebCore/bindings/js/JSMediaKeySessionCustom.cpp @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2016 Metrological Group B.V. + * Copyright (C) 2016 Igalia S.L. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" + +#if ENABLE(ENCRYPTED_MEDIA) + +#include "JSMediaKeySession.h" + +namespace WebCore { + +JSC::JSValue JSMediaKeySession::closed(JSC::ExecState& state) const +{ + if (!m_closed) { + auto promise = createDeferredPromise(state, domWindow()); + m_closed.set(state.vm(), this, promise->promise()); + wrapped().registerClosedPromise(WTFMove(promise)); + } + return m_closed.get(); +} + +} // namespace WebCore + +#endif // ENABLE(ENCRYPTED_MEDIA) diff --git a/Source/WebCore/bindings/js/JSMediaListCustom.h b/Source/WebCore/bindings/js/JSMediaListCustom.h index 8f4ff7aeb..af934b75c 100644 --- a/Source/WebCore/bindings/js/JSMediaListCustom.h +++ b/Source/WebCore/bindings/js/JSMediaListCustom.h @@ -10,10 +10,10 @@ * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * - * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR @@ -23,8 +23,7 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef JSMediaListCustom_h -#define JSMediaListCustom_h +#pragma once #include "CSSRule.h" #include "CSSStyleSheet.h" @@ -44,5 +43,3 @@ inline void* root(MediaList* mediaList) } } // namespace WebCore - -#endif // JSMediaListCustom_h diff --git a/Source/WebCore/bindings/js/JSMediaSourceStatesCustom.cpp b/Source/WebCore/bindings/js/JSMediaSourceStatesCustom.cpp deleted file mode 100644 index 4123e08b7..000000000 --- a/Source/WebCore/bindings/js/JSMediaSourceStatesCustom.cpp +++ /dev/null @@ -1,92 +0,0 @@ -/* - * Copyright (C) 2013 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" - -#if ENABLE(MEDIA_STREAM) - -#include "JSMediaSourceStates.h" - -#include "MediaSourceStates.h" - -using namespace JSC; - -namespace WebCore { - -JSValue JSMediaSourceStates::width(ExecState*) const -{ - if (!impl().hasVideoSource()) - return jsUndefined(); - - return jsNumber(impl().width()); -} - -JSValue JSMediaSourceStates::height(ExecState*) const -{ - if (!impl().hasVideoSource()) - return jsUndefined(); - - return jsNumber(impl().height()); -} - -JSValue JSMediaSourceStates::frameRate(ExecState*) const -{ - if (!impl().hasVideoSource()) - return jsUndefined(); - - return jsNumber(impl().frameRate()); -} - -JSValue JSMediaSourceStates::aspectRatio(ExecState*) const -{ - if (!impl().hasVideoSource()) - return jsUndefined(); - - return jsNumber(impl().aspectRatio()); -} - -JSValue JSMediaSourceStates::facingMode(ExecState* exec) const -{ - if (!impl().hasVideoSource()) - return jsUndefined(); - - const AtomicString& mode = impl().facingMode(); - if (mode.isEmpty()) - return jsUndefined(); - - return jsStringWithCache(exec, impl().facingMode()); -} - -JSValue JSMediaSourceStates::volume(ExecState*) const -{ - if (impl().hasVideoSource()) - return jsUndefined(); - - return jsNumber(impl().volume()); -} - -} // namespace WebCore - -#endif diff --git a/Source/WebCore/bindings/js/JSMediaStreamCapabilitiesCustom.cpp b/Source/WebCore/bindings/js/JSMediaStreamCapabilitiesCustom.cpp index 9ad691de1..b2c6257b7 100644 --- a/Source/WebCore/bindings/js/JSMediaStreamCapabilitiesCustom.cpp +++ b/Source/WebCore/bindings/js/JSMediaStreamCapabilitiesCustom.cpp @@ -10,10 +10,10 @@ * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * - * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR @@ -31,21 +31,22 @@ #include "JSAllAudioCapabilities.h" #include "JSAllVideoCapabilities.h" -#include "MediaStreamCapabilities.h" +#include "JSDOMBinding.h" using namespace JSC; namespace WebCore { -JSC::JSValue toJS(JSC::ExecState* exec, JSDOMGlobalObject* globalObject, MediaStreamCapabilities* object) +JSC::JSValue toJSNewlyCreated(JSC::ExecState*, JSDOMGlobalObject* globalObject, Ref<MediaStreamCapabilities>&& object) { - if (!object) - return jsNull(); - - if (object->hasVideoSource()) - return wrap<JSAllVideoCapabilities>(exec, globalObject, static_cast<AllVideoCapabilities*>(object)); + if (object.hasVideoSource()) + return CREATE_DOM_WRAPPER(globalObject, AllVideoCapabilities, WTFMove(object)); + return CREATE_DOM_WRAPPER(globalObject, AllAudioCapabilities, WTFMove(object)); +} - return wrap<JSAllAudioCapabilities>(exec, globalObject, static_cast<AllAudioCapabilities*>(object)); +JSValue toJS(ExecState* state, JSDOMGlobalObject* globalObject, MediaStreamCapabilities& object) +{ + return wrap(state, globalObject, object); } } // namespace WebCore diff --git a/Source/WebCore/bindings/js/JSMessageChannelCustom.cpp b/Source/WebCore/bindings/js/JSMessageChannelCustom.cpp index 3b2b26189..375dd4b5f 100644 --- a/Source/WebCore/bindings/js/JSMessageChannelCustom.cpp +++ b/Source/WebCore/bindings/js/JSMessageChannelCustom.cpp @@ -27,27 +27,18 @@ #if ENABLE(CHANNEL_MESSAGING) +#include "DOMWrapperWorld.h" #include "JSMessageChannel.h" - -#include "MessageChannel.h" -#include <runtime/Error.h> - -using namespace JSC; +#include <heap/SlotVisitorInlines.h> namespace WebCore { -void JSMessageChannel::visitChildren(JSCell* cell, SlotVisitor& visitor) +void JSMessageChannel::visitAdditionalChildren(JSC::SlotVisitor& visitor) { - JSMessageChannel* thisObject = jsCast<JSMessageChannel*>(cell); - ASSERT_GC_OBJECT_INHERITS(thisObject, info()); - COMPILE_ASSERT(StructureFlags & OverridesVisitChildren, OverridesVisitChildrenWithoutSettingFlag); - ASSERT(thisObject->structure()->typeInfo().overridesVisitChildren()); - Base::visitChildren(thisObject, visitor); - - if (MessagePort* port = thisObject->m_impl->port1()) + if (MessagePort* port = wrapped().port1()) visitor.addOpaqueRoot(port); - if (MessagePort* port = thisObject->m_impl->port2()) + if (MessagePort* port = wrapped().port2()) visitor.addOpaqueRoot(port); } diff --git a/Source/WebCore/bindings/js/JSMessageEventCustom.cpp b/Source/WebCore/bindings/js/JSMessageEventCustom.cpp index c84ca0d9a..e0886ab25 100644 --- a/Source/WebCore/bindings/js/JSMessageEventCustom.cpp +++ b/Source/WebCore/bindings/js/JSMessageEventCustom.cpp @@ -33,9 +33,10 @@ #include "JSBlob.h" #include "JSDOMBinding.h" +#include "JSDOMConvert.h" #include "JSDOMWindow.h" #include "JSEventTarget.h" -#include "JSMessagePortCustom.h" +#include "JSMessagePort.h" #include "MessageEvent.h" #include <runtime/JSArray.h> #include <runtime/JSArrayBuffer.h> @@ -44,85 +45,104 @@ using namespace JSC; namespace WebCore { -JSValue JSMessageEvent::data(ExecState* exec) const +JSValue JSMessageEvent::data(ExecState& state) const { - if (JSValue cachedValue = m_data.get()) - return cachedValue; + if (JSValue cachedValue = m_data.get()) { + // We cannot use a cached object if we are in a different world than the one it was created in. + if (!cachedValue.isObject() || &worldForDOMObject(cachedValue.getObject()) == ¤tWorld(&state)) + return cachedValue; + ASSERT_NOT_REACHED(); + } - MessageEvent& event = impl(); + MessageEvent& event = wrapped(); JSValue result; switch (event.dataType()) { case MessageEvent::DataTypeScriptValue: { - Deprecated::ScriptValue scriptValue = event.dataAsScriptValue(); - if (scriptValue.hasNoValue()) + JSValue dataValue = event.dataAsScriptValue(); + if (!dataValue) result = jsNull(); - else - result = scriptValue.jsValue(); + else { + // We need to make sure MessageEvents do not leak objects in their state property across isolated DOM worlds. + // Ideally, we would check that the worlds have different privileges but that's not possible yet. + if (dataValue.isObject() && &worldForDOMObject(dataValue.getObject()) != ¤tWorld(&state)) { + RefPtr<SerializedScriptValue> serializedValue = event.trySerializeData(&state); + if (serializedValue) + result = serializedValue->deserialize(state, globalObject()); + else + result = jsNull(); + } else + result = dataValue; + } break; } case MessageEvent::DataTypeSerializedScriptValue: if (RefPtr<SerializedScriptValue> serializedValue = event.dataAsSerializedScriptValue()) { - MessagePortArray ports = impl().ports(); - result = serializedValue->deserialize(exec, globalObject(), &ports, NonThrowing); - } - else + Vector<RefPtr<MessagePort>> ports = wrapped().ports(); + // FIXME: Why does this suppress exceptions? + result = serializedValue->deserialize(state, globalObject(), ports, SerializationErrorMode::NonThrowing); + } else result = jsNull(); break; case MessageEvent::DataTypeString: - result = jsStringWithCache(exec, event.dataAsString()); + result = jsStringWithCache(&state, event.dataAsString()); break; case MessageEvent::DataTypeBlob: - result = toJS(exec, globalObject(), event.dataAsBlob()); + result = toJS(&state, globalObject(), event.dataAsBlob()); break; case MessageEvent::DataTypeArrayBuffer: - result = toJS(exec, globalObject(), event.dataAsArrayBuffer()); + result = toJS(&state, globalObject(), event.dataAsArrayBuffer()); break; } // Save the result so we don't have to deserialize the value again. - const_cast<JSMessageEvent*>(this)->m_data.set(exec->vm(), this, result); + m_data.set(state.vm(), this, result); return result; } -static JSC::JSValue handleInitMessageEvent(JSMessageEvent* jsEvent, JSC::ExecState* exec) +static JSC::JSValue handleInitMessageEvent(JSMessageEvent* jsEvent, JSC::ExecState& state) { - const String& typeArg = exec->argument(0).toString(exec)->value(exec); - bool canBubbleArg = exec->argument(1).toBoolean(exec); - bool cancelableArg = exec->argument(2).toBoolean(exec); - const String originArg = exec->argument(4).toString(exec)->value(exec); - const String lastEventIdArg = exec->argument(5).toString(exec)->value(exec); - DOMWindow* sourceArg = toDOMWindow(exec->argument(6)); - OwnPtr<MessagePortArray> messagePorts; - OwnPtr<ArrayBufferArray> arrayBuffers; - if (!exec->argument(7).isUndefinedOrNull()) { - messagePorts = adoptPtr(new MessagePortArray); - arrayBuffers = adoptPtr(new ArrayBufferArray); - fillMessagePortArray(exec, exec->argument(7), *messagePorts, *arrayBuffers); - if (exec->hadException()) - return jsUndefined(); + VM& vm = state.vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + + const String& typeArg = state.argument(0).toWTFString(&state); + RETURN_IF_EXCEPTION(scope, JSValue()); + + bool canBubbleArg = state.argument(1).toBoolean(&state); + RETURN_IF_EXCEPTION(scope, JSValue()); + + bool cancelableArg = state.argument(2).toBoolean(&state); + RETURN_IF_EXCEPTION(scope, JSValue()); + + JSValue dataArg = state.argument(3); + + const String originArg = convert<IDLUSVString>(state, state.argument(4)); + RETURN_IF_EXCEPTION(scope, JSValue()); + + const String lastEventIdArg = state.argument(5).toWTFString(&state); + RETURN_IF_EXCEPTION(scope, JSValue()); + + auto sourceArg = convert<IDLNullable<IDLUnion<IDLInterface<DOMWindow>, IDLInterface<MessagePort>>>>(state, state.argument(6)); + RETURN_IF_EXCEPTION(scope, JSValue()); + + Vector<RefPtr<MessagePort>> messagePorts; + if (!state.argument(7).isUndefinedOrNull()) { + messagePorts = convert<IDLSequence<IDLInterface<MessagePort>>>(state, state.argument(7)); + RETURN_IF_EXCEPTION(scope, JSValue()); } - Deprecated::ScriptValue dataArg = Deprecated::ScriptValue(exec->vm(), exec->argument(3)); - if (exec->hadException()) - return jsUndefined(); - MessageEvent& event = jsEvent->impl(); - event.initMessageEvent(typeArg, canBubbleArg, cancelableArg, dataArg, originArg, lastEventIdArg, sourceArg, messagePorts.release()); - jsEvent->m_data.set(exec->vm(), jsEvent, dataArg.jsValue()); + MessageEvent& event = jsEvent->wrapped(); + event.initMessageEvent(state, typeArg, canBubbleArg, cancelableArg, dataArg, originArg, lastEventIdArg, WTFMove(sourceArg), WTFMove(messagePorts)); + jsEvent->m_data.set(vm, jsEvent, dataArg); return jsUndefined(); } -JSC::JSValue JSMessageEvent::initMessageEvent(JSC::ExecState* exec) -{ - return handleInitMessageEvent(this, exec); -} - -JSC::JSValue JSMessageEvent::webkitInitMessageEvent(JSC::ExecState* exec) +JSC::JSValue JSMessageEvent::webkitInitMessageEvent(JSC::ExecState& state) { - return handleInitMessageEvent(this, exec); + return handleInitMessageEvent(this, state); } } // namespace WebCore diff --git a/Source/WebCore/bindings/js/JSMessagePortCustom.cpp b/Source/WebCore/bindings/js/JSMessagePortCustom.cpp index 33ed4dc3a..b168cf22f 100644 --- a/Source/WebCore/bindings/js/JSMessagePortCustom.cpp +++ b/Source/WebCore/bindings/js/JSMessagePortCustom.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008, 2009 Apple Inc. All Rights Reserved. + * Copyright (C) 2008-2009, 2016 Apple Inc. All Rights Reserved. * Copyright (C) 2011 Google Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without @@ -27,87 +27,15 @@ #include "config.h" #include "JSMessagePort.h" -#include "Event.h" -#include "ExceptionCode.h" -#include "Frame.h" -#include "JSDOMGlobalObject.h" -#include "JSEvent.h" -#include "JSEventListener.h" -#include "JSMessagePortCustom.h" -#include "MessagePort.h" -#include <runtime/Error.h> -#include <runtime/JSArrayBuffer.h> -#include <wtf/text/AtomicString.h> - using namespace JSC; namespace WebCore { -void JSMessagePort::visitChildren(JSCell* cell, SlotVisitor& visitor) +void JSMessagePort::visitAdditionalChildren(SlotVisitor& visitor) { - JSMessagePort* thisObject = jsCast<JSMessagePort*>(cell); - ASSERT_GC_OBJECT_INHERITS(thisObject, info()); - COMPILE_ASSERT(StructureFlags & OverridesVisitChildren, OverridesVisitChildrenWithoutSettingFlag); - ASSERT(thisObject->structure()->typeInfo().overridesVisitChildren()); - Base::visitChildren(thisObject, visitor); - // If we have a locally entangled port, we can directly mark it as reachable. Ports that are remotely entangled are marked in-use by markActiveObjectsForContext(). - if (MessagePort* port = thisObject->m_impl->locallyEntangledPort()) + if (MessagePort* port = wrapped().locallyEntangledPort()) visitor.addOpaqueRoot(port); - - thisObject->m_impl->visitJSEventListeners(visitor); -} - -JSC::JSValue JSMessagePort::postMessage(JSC::ExecState* exec) -{ - return handlePostMessage(exec, &impl()); -} - -void fillMessagePortArray(JSC::ExecState* exec, JSC::JSValue value, MessagePortArray& portArray, ArrayBufferArray& arrayBuffers) -{ - // Convert from the passed-in JS array-like object to a MessagePortArray. - // Also validates the elements per sections 4.1.13 and 4.1.15 of the WebIDL spec and section 8.3.3 of the HTML5 spec. - if (value.isUndefinedOrNull()) { - portArray.resize(0); - arrayBuffers.resize(0); - return; - } - - // Validation of sequence types, per WebIDL spec 4.1.13. - unsigned length = 0; - JSObject* object = toJSSequence(exec, value, length); - if (exec->hadException()) - return; - - for (unsigned i = 0 ; i < length; ++i) { - JSValue value = object->get(exec, i); - if (exec->hadException()) - return; - // Validation of non-null objects, per HTML5 spec 10.3.3. - if (value.isUndefinedOrNull()) { - setDOMException(exec, INVALID_STATE_ERR); - return; - } - - // Validation of Objects implementing an interface, per WebIDL spec 4.1.15. - RefPtr<MessagePort> port = toMessagePort(value); - if (port) { - // Check for duplicate ports. - if (portArray.contains(port)) { - setDOMException(exec, INVALID_STATE_ERR); - return; - } - portArray.append(port.release()); - } else { - RefPtr<ArrayBuffer> arrayBuffer = toArrayBuffer(value); - if (arrayBuffer) - arrayBuffers.append(arrayBuffer); - else { - throwTypeError(exec); - return; - } - } - } } } // namespace WebCore diff --git a/Source/WebCore/bindings/js/JSMessagePortCustom.h b/Source/WebCore/bindings/js/JSMessagePortCustom.h deleted file mode 100644 index bbd566299..000000000 --- a/Source/WebCore/bindings/js/JSMessagePortCustom.h +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright (C) 2009 Google Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef JSMessagePortCustom_h -#define JSMessagePortCustom_h - -#include "MessagePort.h" -#include <runtime/JSCJSValue.h> -#include <runtime/Operations.h> -#include <wtf/Forward.h> - -namespace WebCore { - - typedef int ExceptionCode; - - // Helper function which pulls the values out of a JS sequence and into a MessagePortArray. - // Also validates the elements per sections 4.1.13 and 4.1.15 of the WebIDL spec and section 8.3.3 of the HTML5 spec. - // May generate an exception via the passed ExecState. - void fillMessagePortArray(JSC::ExecState*, JSC::JSValue, MessagePortArray&, ArrayBufferArray&); - - // Helper function to convert from JS postMessage arguments to WebCore postMessage arguments. - template <typename T> - inline JSC::JSValue handlePostMessage(JSC::ExecState* exec, T* impl) - { - MessagePortArray portArray; - ArrayBufferArray arrayBufferArray; - fillMessagePortArray(exec, exec->argument(1), portArray, arrayBufferArray); - RefPtr<SerializedScriptValue> message = SerializedScriptValue::create(exec, exec->argument(0), &portArray, &arrayBufferArray); - if (exec->hadException()) - return JSC::jsUndefined(); - - ExceptionCode ec = 0; - impl->postMessage(message.release(), &portArray, ec); - setDOMException(exec, ec); - return JSC::jsUndefined(); - } - -} -#endif // JSMessagePortCustom_h diff --git a/Source/WebCore/bindings/js/JSMockContentFilterSettingsCustom.cpp b/Source/WebCore/bindings/js/JSMockContentFilterSettingsCustom.cpp new file mode 100644 index 000000000..cbce60cf5 --- /dev/null +++ b/Source/WebCore/bindings/js/JSMockContentFilterSettingsCustom.cpp @@ -0,0 +1,147 @@ +/* + * Copyright (C) 2015-2016 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "JSMockContentFilterSettings.h" + +#if ENABLE(CONTENT_FILTERING) + +#include "JSDOMBinding.h" +#include "JSDOMConvert.h" +#include "MockContentFilterSettings.h" + +using namespace JSC; + +namespace WebCore { + +using Decision = MockContentFilterSettings::Decision; +using DecisionPoint = MockContentFilterSettings::DecisionPoint; + +JSValue JSMockContentFilterSettings::decisionPoint(ExecState&) const +{ + DecisionPoint decisionPoint = wrapped().decisionPoint(); + switch (decisionPoint) { + case DecisionPoint::AfterWillSendRequest: + case DecisionPoint::AfterRedirect: + case DecisionPoint::AfterResponse: + case DecisionPoint::AfterAddData: + case DecisionPoint::AfterFinishedAddingData: + case DecisionPoint::Never: + return jsNumber(static_cast<uint8_t>(decisionPoint)); + } + + ASSERT_NOT_REACHED(); + return jsUndefined(); +} + +void JSMockContentFilterSettings::setDecisionPoint(ExecState& state, JSValue value) +{ + VM& vm = state.vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + + uint8_t nativeValue { convert<IDLOctet>(state, value, IntegerConversionConfiguration::EnforceRange) }; + RETURN_IF_EXCEPTION(scope, void()); + + DecisionPoint decisionPoint { static_cast<DecisionPoint>(nativeValue) }; + switch (decisionPoint) { + case DecisionPoint::AfterWillSendRequest: + case DecisionPoint::AfterRedirect: + case DecisionPoint::AfterResponse: + case DecisionPoint::AfterAddData: + case DecisionPoint::AfterFinishedAddingData: + case DecisionPoint::Never: + wrapped().setDecisionPoint(decisionPoint); + return; + } + + throwTypeError(&state, scope, String::format("%u is not a valid decisionPoint value.", nativeValue)); +} + +static inline JSValue toJSValue(Decision decision) +{ + switch (decision) { + case Decision::Allow: + case Decision::Block: + return jsNumber(static_cast<uint8_t>(decision)); + } + + ASSERT_NOT_REACHED(); + return jsUndefined(); +} + +static inline Decision toDecision(ExecState& state, JSValue value) +{ + VM& vm = state.vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + + uint8_t nativeValue { convert<IDLOctet>(state, value, IntegerConversionConfiguration::EnforceRange) }; + RETURN_IF_EXCEPTION(scope, Decision::Allow); + + Decision decision { static_cast<Decision>(nativeValue) }; + switch (decision) { + case Decision::Allow: + case Decision::Block: + return decision; + } + + throwTypeError(&state, scope, String::format("%u is not a valid decision value.", nativeValue)); + return Decision::Allow; +} + +JSValue JSMockContentFilterSettings::decision(ExecState&) const +{ + return toJSValue(wrapped().decision()); +} + +void JSMockContentFilterSettings::setDecision(ExecState& state, JSValue value) +{ + VM& vm = state.vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + + Decision decision { toDecision(state, value) }; + RETURN_IF_EXCEPTION(scope, void()); + + wrapped().setDecision(decision); +} + +JSValue JSMockContentFilterSettings::unblockRequestDecision(ExecState&) const +{ + return toJSValue(wrapped().unblockRequestDecision()); +} + +void JSMockContentFilterSettings::setUnblockRequestDecision(ExecState& state, JSValue value) +{ + VM& vm = state.vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + + Decision unblockRequestDecision { toDecision(state, value) }; + RETURN_IF_EXCEPTION(scope, void()); + + wrapped().setUnblockRequestDecision(unblockRequestDecision); +} + +}; // namespace WebCore + +#endif // ENABLE(CONTENT_FILTERING) diff --git a/Source/WebCore/bindings/js/JSMutationCallback.cpp b/Source/WebCore/bindings/js/JSMutationCallback.cpp index adabc7eb7..afc422f36 100644 --- a/Source/WebCore/bindings/js/JSMutationCallback.cpp +++ b/Source/WebCore/bindings/js/JSMutationCallback.cpp @@ -51,12 +51,12 @@ JSMutationCallback::~JSMutationCallback() { } -void JSMutationCallback::call(const Vector<RefPtr<MutationRecord>>& mutations, MutationObserver* observer) +void JSMutationCallback::call(const Vector<Ref<MutationRecord>>& mutations, MutationObserver* observer) { if (!canInvokeCallback()) return; - Ref<JSMutationCallback> protect(*this); + Ref<JSMutationCallback> protectedThis(*this); JSLockHolder lock(m_isolatedWorld->vm()); @@ -66,7 +66,7 @@ void JSMutationCallback::call(const Vector<RefPtr<MutationRecord>>& mutations, M JSValue callback = m_callback.get(); CallData callData; CallType callType = getCallData(callback, callData); - if (callType == CallTypeNone) { + if (callType == CallType::None) { ASSERT_NOT_REACHED(); return; } @@ -82,17 +82,18 @@ void JSMutationCallback::call(const Vector<RefPtr<MutationRecord>>& mutations, M JSValue jsObserver = toJS(exec, globalObject, observer); MarkedArgumentBuffer args; - args.append(jsArray(exec, globalObject, mutations)); + args.append(toJS<IDLSequence<IDLInterface<MutationRecord>>>(*exec, *globalObject, mutations)); args.append(jsObserver); InspectorInstrumentationCookie cookie = JSMainThreadExecState::instrumentFunctionCall(context, callType, callData); - JSMainThreadExecState::call(exec, callback, callType, callData, jsObserver, args); + NakedPtr<JSC::Exception> exception; + JSMainThreadExecState::profiledCall(exec, JSC::ProfilingReason::Other, callback, callType, callData, jsObserver, args, exception); - InspectorInstrumentation::didCallFunction(cookie); + InspectorInstrumentation::didCallFunction(cookie, context); - if (exec->hadException()) - reportCurrentException(exec); + if (exception) + reportException(exec, exception); } } // namespace WebCore diff --git a/Source/WebCore/bindings/js/JSMutationCallback.h b/Source/WebCore/bindings/js/JSMutationCallback.h index d7bd8483b..427d6243a 100644 --- a/Source/WebCore/bindings/js/JSMutationCallback.h +++ b/Source/WebCore/bindings/js/JSMutationCallback.h @@ -23,8 +23,7 @@ * THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef JSMutationCallback_h -#define JSMutationCallback_h +#pragma once #include "ActiveDOMCallback.h" #include "DOMWrapperWorld.h" @@ -37,18 +36,17 @@ namespace WebCore { class JSDOMGlobalObject; -class JSMutationCallback : public MutationCallback, public ActiveDOMCallback { +class JSMutationCallback final : public MutationCallback, public ActiveDOMCallback { public: - static PassRefPtr<JSMutationCallback> create(JSC::JSObject* callback, JSDOMGlobalObject* globalObject) + static Ref<JSMutationCallback> create(JSC::JSObject* callback, JSDOMGlobalObject* globalObject) { - return adoptRef(new JSMutationCallback(callback, globalObject)); + return adoptRef(*new JSMutationCallback(callback, globalObject)); } virtual ~JSMutationCallback(); - virtual void call(const Vector<RefPtr<MutationRecord>>&, MutationObserver*) override; - - virtual ScriptExecutionContext* scriptExecutionContext() const override { return ContextDestructionObserver::scriptExecutionContext(); } + void call(const Vector<Ref<MutationRecord>>&, MutationObserver*) override; + bool canInvokeCallback() const override { return ActiveDOMCallback::canInvokeCallback(); } private: JSMutationCallback(JSC::JSObject* callback, JSDOMGlobalObject*); @@ -58,5 +56,3 @@ private: }; } // namespace WebCore - -#endif diff --git a/Source/WebCore/bindings/js/JSMutationObserverCustom.cpp b/Source/WebCore/bindings/js/JSMutationObserverCustom.cpp index 09760945e..33c5509ae 100644 --- a/Source/WebCore/bindings/js/JSMutationObserverCustom.cpp +++ b/Source/WebCore/bindings/js/JSMutationObserverCustom.cpp @@ -1,5 +1,6 @@ /* * Copyright (C) 2011 Google Inc. All rights reserved. + * Copyright (C) 2016 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are @@ -29,10 +30,10 @@ */ #include "config.h" - #include "JSMutationObserver.h" #include "ExceptionCode.h" +#include "JSDOMConstructorBase.h" #include "JSMutationCallback.h" #include "JSNodeCustom.h" #include "MutationObserver.h" @@ -43,30 +44,31 @@ using namespace JSC; namespace WebCore { -EncodedJSValue JSC_HOST_CALL JSMutationObserverConstructor::constructJSMutationObserver(ExecState* exec) +EncodedJSValue JSC_HOST_CALL constructJSMutationObserver(ExecState& exec) { - if (exec->argumentCount() < 1) - return throwVMError(exec, createNotEnoughArgumentsError(exec)); + VM& vm = exec.vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + + if (exec.argumentCount() < 1) + return throwVMError(&exec, scope, createNotEnoughArgumentsError(&exec)); - JSObject* object = exec->argument(0).getObject(); + JSObject* object = exec.uncheckedArgument(0).getObject(); CallData callData; - if (!object || object->methodTable()->getCallData(object, callData) == CallTypeNone) - return throwVMError(exec, createTypeError(exec, "Callback argument must be a function")); + if (!object || object->methodTable()->getCallData(object, callData) == CallType::None) + return throwArgumentTypeError(exec, scope, 0, "callback", "MutationObserver", nullptr, "MutationCallback"); - JSMutationObserverConstructor* jsConstructor = jsCast<JSMutationObserverConstructor*>(exec->callee()); - RefPtr<JSMutationCallback> callback = JSMutationCallback::create(object, jsConstructor->globalObject()); - JSObject* jsObserver = asObject(toJS(exec, jsConstructor->globalObject(), MutationObserver::create(callback.release()))); + auto* jsConstructor = jsCast<JSDOMConstructorBase*>(exec.jsCallee()); + auto callback = JSMutationCallback::create(object, jsConstructor->globalObject()); + JSObject* jsObserver = asObject(toJSNewlyCreated(&exec, jsConstructor->globalObject(), MutationObserver::create(WTFMove(callback)))); PrivateName propertyName; - jsObserver->putDirect(jsConstructor->globalObject()->vm(), propertyName, object); + jsObserver->putDirect(vm, propertyName, object); return JSValue::encode(jsObserver); } bool JSMutationObserverOwner::isReachableFromOpaqueRoots(JSC::Handle<JSC::Unknown> handle, void*, SlotVisitor& visitor) { - MutationObserver& observer = jsCast<JSMutationObserver*>(handle.get().asCell())->impl(); - auto observedNodes = observer.getObservedNodes(); - for (auto it = observedNodes.begin(), end = observedNodes.end(); it != end; ++it) { - if (visitor.containsOpaqueRoot(root(*it))) + for (auto* node : jsCast<JSMutationObserver*>(handle.slot()->asCell())->wrapped().observedNodes()) { + if (visitor.containsOpaqueRoot(root(node))) return true; } return false; diff --git a/Source/WebCore/bindings/js/JSNamedNodeMapCustom.cpp b/Source/WebCore/bindings/js/JSNamedNodeMapCustom.cpp deleted file mode 100644 index 5e3c898fb..000000000 --- a/Source/WebCore/bindings/js/JSNamedNodeMapCustom.cpp +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (C) 2007, 2008, 2009, 2013 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" -#include "JSNamedNodeMap.h" - -#include "JSNode.h" - -#include "Element.h" -#include "NamedNodeMap.h" - -using namespace JSC; - -namespace WebCore { - -bool JSNamedNodeMap::canGetItemsForName(ExecState*, NamedNodeMap* impl, PropertyName propertyName) -{ - return impl->getNamedItem(propertyNameToAtomicString(propertyName)); -} - -EncodedJSValue JSNamedNodeMap::nameGetter(ExecState* exec, EncodedJSValue slotBase, EncodedJSValue, PropertyName propertyName) -{ - JSNamedNodeMap* thisObj = jsCast<JSNamedNodeMap*>(JSValue::decode(slotBase)); - return JSValue::encode(toJS(exec, thisObj->globalObject(), thisObj->impl().getNamedItem(propertyNameToAtomicString(propertyName)))); -} - -} // namespace WebCore diff --git a/Source/WebCore/bindings/js/JSNodeCustom.cpp b/Source/WebCore/bindings/js/JSNodeCustom.cpp index 3c2468cd8..32548720c 100644 --- a/Source/WebCore/bindings/js/JSNodeCustom.cpp +++ b/Source/WebCore/bindings/js/JSNodeCustom.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2007, 2009, 2010 Apple Inc. All rights reserved. + * Copyright (C) 2007, 2009-2010, 2016 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -10,10 +10,10 @@ * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * - * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR @@ -32,8 +32,6 @@ #include "Document.h" #include "DocumentFragment.h" #include "DocumentType.h" -#include "Entity.h" -#include "EntityReference.h" #include "ExceptionCode.h" #include "HTMLAudioElement.h" #include "HTMLCanvasElement.h" @@ -51,29 +49,22 @@ #include "JSDocument.h" #include "JSDocumentFragment.h" #include "JSDocumentType.h" -#include "JSEntity.h" -#include "JSEntityReference.h" #include "JSEventListener.h" #include "JSHTMLElement.h" #include "JSHTMLElementWrapperFactory.h" -#include "JSNotation.h" #include "JSProcessingInstruction.h" +#include "JSSVGElementWrapperFactory.h" +#include "JSShadowRoot.h" #include "JSText.h" #include "Node.h" -#include "Notation.h" #include "ProcessingInstruction.h" #include "RegisteredEventListener.h" +#include "SVGElement.h" +#include "ScriptState.h" #include "ShadowRoot.h" #include "StyleSheet.h" #include "StyledElement.h" #include "Text.h" -#include <wtf/PassRefPtr.h> -#include <wtf/RefPtr.h> - -#if ENABLE(SVG) -#include "JSSVGElementWrapperFactory.h" -#include "SVGElement.h" -#endif using namespace JSC; @@ -81,40 +72,28 @@ namespace WebCore { using namespace HTMLNames; -static inline bool isObservable(JSNode* jsNode, Node* node) +static inline bool isReachableFromDOM(Node* node, SlotVisitor& visitor) { - // The root node keeps the tree intact. - if (!node->parentNode()) - return true; - - if (jsNode->hasCustomProperties()) - return true; - - // A node's JS wrapper is responsible for marking its JS event listeners. - if (node->hasEventListeners()) - return true; - - return false; -} + if (!node->isConnected()) { + if (is<Element>(*node)) { + auto& element = downcast<Element>(*node); -static inline bool isReachableFromDOM(JSNode* jsNode, Node* node, SlotVisitor& visitor) -{ - if (!node->inDocument()) { - // If a wrapper is the last reference to an image element - // that is loading but not in the document, the wrapper is observable - // because it is the only thing keeping the image element alive, and if - // the element is destroyed, its load event will not fire. - // FIXME: The DOM should manage this issue without the help of JavaScript wrappers. - if (isHTMLImageElement(node)) { - if (toHTMLImageElement(node)->hasPendingActivity()) - return true; - } - #if ENABLE(VIDEO) - else if (isHTMLAudioElement(node)) { - if (!toHTMLAudioElement(node)->paused()) - return true; + // If a wrapper is the last reference to an image element + // that is loading but not in the document, the wrapper is observable + // because it is the only thing keeping the image element alive, and if + // the element is destroyed, its load event will not fire. + // FIXME: The DOM should manage this issue without the help of JavaScript wrappers. + if (is<HTMLImageElement>(element)) { + if (downcast<HTMLImageElement>(element).hasPendingActivity()) + return true; + } +#if ENABLE(VIDEO) + else if (is<HTMLAudioElement>(element)) { + if (!downcast<HTMLAudioElement>(element).paused()) + return true; + } +#endif } - #endif // If a node is firing event listeners, its wrapper is observable because // its wrapper is responsible for marking those event listeners. @@ -122,144 +101,155 @@ static inline bool isReachableFromDOM(JSNode* jsNode, Node* node, SlotVisitor& v return true; } - return isObservable(jsNode, node) && visitor.containsOpaqueRoot(root(node)); + return visitor.containsOpaqueRoot(root(node)); } bool JSNodeOwner::isReachableFromOpaqueRoots(JSC::Handle<JSC::Unknown> handle, void*, SlotVisitor& visitor) { - JSNode* jsNode = jsCast<JSNode*>(handle.get().asCell()); - return isReachableFromDOM(jsNode, &jsNode->impl(), visitor); + JSNode* jsNode = jsCast<JSNode*>(handle.slot()->asCell()); + return isReachableFromDOM(&jsNode->wrapped(), visitor); } -JSValue JSNode::insertBefore(ExecState* exec) +JSValue JSNode::insertBefore(ExecState& state) { - ExceptionCode ec = 0; - bool ok = impl().insertBefore(toNode(exec->argument(0)), toNode(exec->argument(1)), ec); - setDOMException(exec, ec); - if (ok) - return exec->argument(0); - return jsNull(); + VM& vm = state.vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + + if (UNLIKELY(state.argumentCount() < 2)) + return throwException(&state, scope, createNotEnoughArgumentsError(&state)); + + JSValue newChildValue = state.uncheckedArgument(0); + auto* newChild = JSNode::toWrapped(vm, newChildValue); + if (UNLIKELY(!newChild)) + return JSValue::decode(throwArgumentTypeError(state, scope, 0, "node", "Node", "insertBefore", "Node")); + + propagateException(state, scope, wrapped().insertBefore(*newChild, JSNode::toWrapped(vm, state.uncheckedArgument(1)))); + return newChildValue; } -JSValue JSNode::replaceChild(ExecState* exec) +JSValue JSNode::replaceChild(ExecState& state) { - ExceptionCode ec = 0; - bool ok = impl().replaceChild(toNode(exec->argument(0)), toNode(exec->argument(1)), ec); - setDOMException(exec, ec); - if (ok) - return exec->argument(1); - return jsNull(); + VM& vm = state.vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + + if (UNLIKELY(state.argumentCount() < 2)) + return throwException(&state, scope, createNotEnoughArgumentsError(&state)); + + auto* newChild = JSNode::toWrapped(vm, state.uncheckedArgument(0)); + JSValue oldChildValue = state.uncheckedArgument(1); + auto* oldChild = JSNode::toWrapped(vm, oldChildValue); + if (UNLIKELY(!newChild || !oldChild)) { + if (!newChild) + return JSValue::decode(throwArgumentTypeError(state, scope, 0, "node", "Node", "replaceChild", "Node")); + return JSValue::decode(throwArgumentTypeError(state, scope, 1, "child", "Node", "replaceChild", "Node")); + } + + propagateException(state, scope, wrapped().replaceChild(*newChild, *oldChild)); + return oldChildValue; } -JSValue JSNode::removeChild(ExecState* exec) +JSValue JSNode::removeChild(ExecState& state) { - ExceptionCode ec = 0; - bool ok = impl().removeChild(toNode(exec->argument(0)), ec); - setDOMException(exec, ec); - if (ok) - return exec->argument(0); - return jsNull(); + VM& vm = state.vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + + JSValue childValue = state.argument(0); + auto* child = JSNode::toWrapped(vm, childValue); + if (UNLIKELY(!child)) + return JSValue::decode(throwArgumentTypeError(state, scope, 0, "child", "Node", "removeChild", "Node")); + + propagateException(state, scope, wrapped().removeChild(*child)); + return childValue; } -JSValue JSNode::appendChild(ExecState* exec) +JSValue JSNode::appendChild(ExecState& state) { - ExceptionCode ec = 0; - bool ok = impl().appendChild(toNode(exec->argument(0)), ec); - setDOMException(exec, ec); - if (ok) - return exec->argument(0); - return jsNull(); + VM& vm = state.vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + + JSValue newChildValue = state.argument(0); + auto newChild = JSNode::toWrapped(vm, newChildValue); + if (UNLIKELY(!newChild)) + return JSValue::decode(throwArgumentTypeError(state, scope, 0, "node", "Node", "appendChild", "Node")); + + propagateException(state, scope, wrapped().appendChild(*newChild)); + return newChildValue; } JSScope* JSNode::pushEventHandlerScope(ExecState* exec, JSScope* node) const { - if (inherits(JSHTMLElement::info())) + if (inherits(exec->vm(), JSHTMLElement::info())) return jsCast<const JSHTMLElement*>(this)->pushEventHandlerScope(exec, node); return node; } -void JSNode::visitChildren(JSCell* cell, SlotVisitor& visitor) +void JSNode::visitAdditionalChildren(SlotVisitor& visitor) { - JSNode* thisObject = jsCast<JSNode*>(cell); - ASSERT_GC_OBJECT_INHERITS(thisObject, info()); - COMPILE_ASSERT(StructureFlags & OverridesVisitChildren, OverridesVisitChildrenWithoutSettingFlag); - ASSERT(thisObject->structure()->typeInfo().overridesVisitChildren()); - Base::visitChildren(thisObject, visitor); - - Node& node = thisObject->impl(); - node.visitJSEventListeners(visitor); - - visitor.addOpaqueRoot(root(node)); + visitor.addOpaqueRoot(root(wrapped())); } -static ALWAYS_INLINE JSValue createWrapperInline(ExecState* exec, JSDOMGlobalObject* globalObject, Node* node) +static ALWAYS_INLINE JSValue createWrapperInline(ExecState* exec, JSDOMGlobalObject* globalObject, Ref<Node>&& node) { - ASSERT(node); - ASSERT(!getCachedWrapper(currentWorld(exec), node)); + ASSERT(!getCachedWrapper(globalObject->world(), node)); - JSDOMWrapper* wrapper; + JSDOMObject* wrapper; switch (node->nodeType()) { case Node::ELEMENT_NODE: - if (node->isHTMLElement()) - wrapper = createJSHTMLWrapper(exec, globalObject, toHTMLElement(node)); -#if ENABLE(SVG) - else if (node->isSVGElement()) - wrapper = createJSSVGWrapper(exec, globalObject, toSVGElement(node)); -#endif + if (is<HTMLElement>(node.get())) + wrapper = createJSHTMLWrapper(globalObject, static_reference_cast<HTMLElement>(WTFMove(node))); + else if (is<SVGElement>(node.get())) + wrapper = createJSSVGWrapper(globalObject, static_reference_cast<SVGElement>(WTFMove(node))); else - wrapper = CREATE_DOM_WRAPPER(exec, globalObject, Element, node); + wrapper = createWrapper<Element>(globalObject, WTFMove(node)); break; case Node::ATTRIBUTE_NODE: - wrapper = CREATE_DOM_WRAPPER(exec, globalObject, Attr, node); + wrapper = createWrapper<Attr>(globalObject, WTFMove(node)); break; case Node::TEXT_NODE: - wrapper = CREATE_DOM_WRAPPER(exec, globalObject, Text, node); + wrapper = createWrapper<Text>(globalObject, WTFMove(node)); break; case Node::CDATA_SECTION_NODE: - wrapper = CREATE_DOM_WRAPPER(exec, globalObject, CDATASection, node); - break; - case Node::ENTITY_NODE: - wrapper = CREATE_DOM_WRAPPER(exec, globalObject, Entity, node); + wrapper = createWrapper<CDATASection>(globalObject, WTFMove(node)); break; case Node::PROCESSING_INSTRUCTION_NODE: - wrapper = CREATE_DOM_WRAPPER(exec, globalObject, ProcessingInstruction, node); + wrapper = createWrapper<ProcessingInstruction>(globalObject, WTFMove(node)); break; case Node::COMMENT_NODE: - wrapper = CREATE_DOM_WRAPPER(exec, globalObject, Comment, node); + wrapper = createWrapper<Comment>(globalObject, WTFMove(node)); break; case Node::DOCUMENT_NODE: // we don't want to cache the document itself in the per-document dictionary - return toJS(exec, globalObject, toDocument(node)); + return toJS(exec, globalObject, downcast<Document>(node.get())); case Node::DOCUMENT_TYPE_NODE: - wrapper = CREATE_DOM_WRAPPER(exec, globalObject, DocumentType, node); - break; - case Node::NOTATION_NODE: - wrapper = CREATE_DOM_WRAPPER(exec, globalObject, Notation, node); + wrapper = createWrapper<DocumentType>(globalObject, WTFMove(node)); break; case Node::DOCUMENT_FRAGMENT_NODE: - wrapper = CREATE_DOM_WRAPPER(exec, globalObject, DocumentFragment, node); - break; - case Node::ENTITY_REFERENCE_NODE: - wrapper = CREATE_DOM_WRAPPER(exec, globalObject, EntityReference, node); + if (node->isShadowRoot()) + wrapper = createWrapper<ShadowRoot>(globalObject, WTFMove(node)); + else + wrapper = createWrapper<DocumentFragment>(globalObject, WTFMove(node)); break; default: - wrapper = CREATE_DOM_WRAPPER(exec, globalObject, Node, node); + wrapper = createWrapper<Node>(globalObject, WTFMove(node)); } - return wrapper; + return wrapper; } -JSValue createWrapper(ExecState* exec, JSDOMGlobalObject* globalObject, Node* node) +JSValue createWrapper(ExecState* exec, JSDOMGlobalObject* globalObject, Ref<Node>&& node) { - return createWrapperInline(exec, globalObject, node); + return createWrapperInline(exec, globalObject, WTFMove(node)); } -JSValue toJSNewlyCreated(ExecState* exec, JSDOMGlobalObject* globalObject, Node* node) +JSValue toJSNewlyCreated(ExecState* exec, JSDOMGlobalObject* globalObject, Ref<Node>&& node) { - if (!node) - return jsNull(); - - return createWrapperInline(exec, globalObject, node); + return createWrapperInline(exec, globalObject, WTFMove(node)); +} + +JSC::JSObject* getOutOfLineCachedWrapper(JSDOMGlobalObject* globalObject, Node& node) +{ + ASSERT(!globalObject->world().isNormal()); + return globalObject->world().m_wrappers.get(&node); } void willCreatePossiblyOrphanedTreeByRemovalSlowCase(Node* root) @@ -269,7 +259,7 @@ void willCreatePossiblyOrphanedTreeByRemovalSlowCase(Node* root) return; JSLockHolder lock(scriptState); - toJS(scriptState, static_cast<JSDOMGlobalObject*>(scriptState->lexicalGlobalObject()), root); + toJS(scriptState, static_cast<JSDOMGlobalObject*>(scriptState->lexicalGlobalObject()), *root); } } // namespace WebCore diff --git a/Source/WebCore/bindings/js/JSNodeCustom.h b/Source/WebCore/bindings/js/JSNodeCustom.h index 2880274ed..6779dad32 100644 --- a/Source/WebCore/bindings/js/JSNodeCustom.h +++ b/Source/WebCore/bindings/js/JSNodeCustom.h @@ -10,10 +10,10 @@ * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * - * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR @@ -23,26 +23,26 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef JSNodeCustom_h -#define JSNodeCustom_h +#pragma once #include "JSDOMBinding.h" #include "JSNode.h" -#include "ScriptState.h" #include "ShadowRoot.h" namespace WebCore { -JSC::JSValue createWrapper(JSC::ExecState*, JSDOMGlobalObject*, Node*); +WEBCORE_EXPORT JSC::JSValue createWrapper(JSC::ExecState*, JSDOMGlobalObject*, Ref<Node>&&); +WEBCORE_EXPORT JSC::JSObject* getOutOfLineCachedWrapper(JSDOMGlobalObject*, Node&); -inline JSC::JSValue toJS(JSC::ExecState* exec, JSDOMGlobalObject* globalObject, Node* node) +inline JSC::JSValue toJS(JSC::ExecState* exec, JSDOMGlobalObject* globalObject, Node& node) { - if (!node) - return JSC::jsNull(); - - JSNode* wrapper = JSC::jsCast<JSNode*>(getCachedWrapper(currentWorld(exec), node)); - if (wrapper) - return wrapper; + if (LIKELY(globalObject->worldIsNormal())) { + if (auto* wrapper = node.wrapper()) + return wrapper; + } else { + if (auto* wrapper = getOutOfLineCachedWrapper(globalObject, node)) + return wrapper; + } return createWrapper(exec, globalObject, node); } @@ -65,12 +65,7 @@ inline void willCreatePossiblyOrphanedTreeByRemoval(Node* root) inline void* root(Node* node) { - if (node->inDocument()) - return &node->document(); - - while (node->parentOrShadowHostNode()) - node = node->parentOrShadowHostNode(); - return node; + return node->opaqueRoot(); } inline void* root(Node& node) @@ -78,6 +73,15 @@ inline void* root(Node& node) return root(&node); } -} // namespace WebCore +template<typename From> +ALWAYS_INLINE JSDynamicCastResult<JSNode, From> jsNodeCast(From* value) +{ + return value->type() >= JSNodeType ? JSC::jsCast<JSDynamicCastResult<JSNode, From>>(value) : nullptr; +} -#endif // JSDOMNodeCustom_h +ALWAYS_INLINE JSC::JSValue JSNode::nodeType(JSC::ExecState&) const +{ + return JSC::jsNumber(static_cast<uint8_t>(type()) & JSNodeTypeMask); +} + +} // namespace WebCore diff --git a/Source/WebCore/bindings/js/JSNodeFilterCondition.cpp b/Source/WebCore/bindings/js/JSNodeFilterCondition.cpp deleted file mode 100644 index d1b472135..000000000 --- a/Source/WebCore/bindings/js/JSNodeFilterCondition.cpp +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Copyright (C) 2001 Peter Kelly (pmk@post.com) - * Copyright (C) 2007, 2008, 2009 Apple Inc. All rights reserved. - * - * 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 - */ - -#include "config.h" -#include "JSNodeFilterCondition.h" - -#include "JSMainThreadExecState.h" -#include "JSNode.h" -#include "JSNodeFilter.h" -#include "NodeFilter.h" -#include <runtime/Error.h> -#include <runtime/JSLock.h> - -namespace WebCore { - -using namespace JSC; - -JSNodeFilterCondition::JSNodeFilterCondition(VM&, NodeFilter* owner, JSValue filter) - : m_filter(filter.isObject() ? Weak<JSObject>(jsCast<JSObject*>(filter), &m_weakOwner, owner) : nullptr) -{ -} - -short JSNodeFilterCondition::acceptNode(JSC::ExecState* exec, Node* filterNode) const -{ - JSLockHolder lock(exec); - - if (!m_filter) - return NodeFilter::FILTER_ACCEPT; - - // Exec is null if we've been called from a non-JavaScript language and the document - // is no longer able to run JavaScript (e.g., it's disconnected from its frame). - if (!exec) - return NodeFilter::FILTER_REJECT; - - JSValue filter = m_filter.get(); - CallData callData; - CallType callType = getCallData(filter, callData); - if (callType == CallTypeNone) { - filter = filter.get(exec, Identifier(exec, "acceptNode")); - callType = getCallData(filter, callData); - if (callType == CallTypeNone) { - exec->vm().throwException(exec, createTypeError(exec, "NodeFilter object does not have an acceptNode function")); - return NodeFilter::FILTER_REJECT; - } - } - - MarkedArgumentBuffer args; - // FIXME: The node should have the prototype chain that came from its document, not - // whatever prototype chain might be on the window this filter came from. Bug 27662 - args.append(toJS(exec, deprecatedGlobalObjectForPrototype(exec), filterNode)); - if (exec->hadException()) - return NodeFilter::FILTER_REJECT; - - JSValue result = JSMainThreadExecState::call(exec, filter, callType, callData, m_filter.get(), args); - if (exec->hadException()) - return NodeFilter::FILTER_REJECT; - - int intResult = result.toInt32(exec); - if (exec->hadException()) - return NodeFilter::FILTER_REJECT; - - return intResult; -} - -bool JSNodeFilterCondition::WeakOwner::isReachableFromOpaqueRoots(JSC::Handle<JSC::Unknown>, void* context, SlotVisitor& visitor) -{ - return visitor.containsOpaqueRoot(context); -} - -} // namespace WebCore diff --git a/Source/WebCore/bindings/js/JSNodeFilterCondition.h b/Source/WebCore/bindings/js/JSNodeFilterCondition.h deleted file mode 100644 index 3b175815a..000000000 --- a/Source/WebCore/bindings/js/JSNodeFilterCondition.h +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright (C) 2001 Peter Kelly (pmk@post.com) - * Copyright (C) 2007, 2008, 2009 Apple Inc. All rights reserved. - * - * 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 JSNodeFilterCondition_h -#define JSNodeFilterCondition_h - -#include "NodeFilterCondition.h" -#include <heap/Weak.h> -#include <heap/WeakInlines.h> -#include <runtime/JSCJSValue.h> -#include <runtime/Operations.h> -#include <wtf/PassRefPtr.h> - -namespace WebCore { - - class Node; - class NodeFilter; - - class JSNodeFilterCondition : public NodeFilterCondition { - public: - static PassRefPtr<JSNodeFilterCondition> create(JSC::VM& vm, NodeFilter* owner, JSC::JSValue filter) - { - return adoptRef(new JSNodeFilterCondition(vm, owner, filter)); - } - - private: - JSNodeFilterCondition(JSC::VM&, NodeFilter* owner, JSC::JSValue filter); - - virtual short acceptNode(JSC::ExecState*, Node*) const; - - class WeakOwner : public JSC::WeakHandleOwner { - virtual bool isReachableFromOpaqueRoots(JSC::Handle<JSC::Unknown>, void* context, JSC::SlotVisitor&); - }; - WeakOwner m_weakOwner; - mutable JSC::Weak<JSC::JSObject> m_filter; - }; - -} // namespace WebCore - -#endif // JSNodeFilterCondition_h diff --git a/Source/WebCore/bindings/js/JSNodeFilterCustom.cpp b/Source/WebCore/bindings/js/JSNodeFilterCustom.cpp index 877c98543..fd3089b53 100644 --- a/Source/WebCore/bindings/js/JSNodeFilterCustom.cpp +++ b/Source/WebCore/bindings/js/JSNodeFilterCustom.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2007, 2008, 2009 Apple Inc. All rights reserved. + * Copyright (C) 2015-2016 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -10,50 +10,61 @@ * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * - * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. */ #include "config.h" #include "JSNodeFilter.h" -#include "JSDOMWindowBase.h" +#include "JSCallbackData.h" +#include "JSDOMConvert.h" #include "JSNode.h" -#include "JSNodeFilterCondition.h" #include "NodeFilter.h" -#include "JSDOMBinding.h" - -using namespace JSC; namespace WebCore { -void JSNodeFilter::visitChildren(JSCell* cell, SlotVisitor& visitor) -{ - JSNodeFilter* thisObject = jsCast<JSNodeFilter*>(cell); - ASSERT_GC_OBJECT_INHERITS(thisObject, info()); - COMPILE_ASSERT(StructureFlags & OverridesVisitChildren, OverridesVisitChildrenWithoutSettingFlag); - ASSERT(thisObject->structure()->typeInfo().overridesVisitChildren()); - Base::visitChildren(thisObject, visitor); - visitor.addOpaqueRoot(&thisObject->impl()); -} +using namespace JSC; -PassRefPtr<NodeFilter> toNodeFilter(VM& vm, JSValue value) +// FIXME: The bindings generator is currently not able to generate +// callback function calls if they return something other than a +// boolean. +uint16_t JSNodeFilter::acceptNode(Node* node) { - if (value.inherits(JSNodeFilter::info())) - return &jsCast<JSNodeFilter*>(asObject(value))->impl(); + Ref<JSNodeFilter> protectedThis(*this); + + VM& vm = m_data->globalObject()->vm(); + JSLockHolder lock(vm); + auto scope = DECLARE_THROW_SCOPE(vm); + + ExecState* state = m_data->globalObject()->globalExec(); + MarkedArgumentBuffer args; + args.append(toJS(state, m_data->globalObject(), node)); + RETURN_IF_EXCEPTION(scope, NodeFilter::FILTER_REJECT); + + NakedPtr<JSC::Exception> returnedException; + JSValue value = m_data->invokeCallback(args, JSCallbackData::CallbackType::FunctionOrObject, Identifier::fromString(state, "acceptNode"), returnedException); + ASSERT(!scope.exception() || returnedException); + if (returnedException) { + // Rethrow exception. + throwException(state, scope, returnedException); + + return NodeFilter::FILTER_REJECT; + } + + auto result = convert<IDLUnsignedShort>(*state, value, IntegerConversionConfiguration::Normal); + RETURN_IF_EXCEPTION(scope, NodeFilter::FILTER_REJECT); - RefPtr<NodeFilter> result = NodeFilter::create(); - result->setCondition(JSNodeFilterCondition::create(vm, result.get(), value)); - return result.release(); + return result; } } // namespace WebCore diff --git a/Source/WebCore/bindings/js/JSNodeIteratorCustom.cpp b/Source/WebCore/bindings/js/JSNodeIteratorCustom.cpp index 49cde01cc..b3f036139 100644 --- a/Source/WebCore/bindings/js/JSNodeIteratorCustom.cpp +++ b/Source/WebCore/bindings/js/JSNodeIteratorCustom.cpp @@ -20,24 +20,14 @@ #include "config.h" #include "JSNodeIterator.h" -#include "JSNode.h" #include "Node.h" -#include "NodeFilter.h" -#include "NodeIterator.h" - -using namespace JSC; +#include <heap/SlotVisitorInlines.h> namespace WebCore { -void JSNodeIterator::visitChildren(JSCell* cell, SlotVisitor& visitor) +void JSNodeIterator::visitAdditionalChildren(JSC::SlotVisitor& visitor) { - JSNodeIterator* thisObject = jsCast<JSNodeIterator*>(cell); - ASSERT_GC_OBJECT_INHERITS(thisObject, info()); - COMPILE_ASSERT(StructureFlags & OverridesVisitChildren, OverridesVisitChildrenWithoutSettingFlag); - ASSERT(thisObject->structure()->typeInfo().overridesVisitChildren()); - Base::visitChildren(thisObject, visitor); - - if (NodeFilter* filter = thisObject->m_impl->filter()) + if (NodeFilter* filter = wrapped().filter()) visitor.addOpaqueRoot(filter); } diff --git a/Source/WebCore/bindings/js/JSNodeListCustom.cpp b/Source/WebCore/bindings/js/JSNodeListCustom.cpp index a58d980ef..513bbdfda 100644 --- a/Source/WebCore/bindings/js/JSNodeListCustom.cpp +++ b/Source/WebCore/bindings/js/JSNodeListCustom.cpp @@ -10,10 +10,10 @@ * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * - * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR @@ -39,25 +39,29 @@ namespace WebCore { bool JSNodeListOwner::isReachableFromOpaqueRoots(JSC::Handle<JSC::Unknown> handle, void*, SlotVisitor& visitor) { - JSNodeList* jsNodeList = jsCast<JSNodeList*>(handle.get().asCell()); + JSNodeList* jsNodeList = jsCast<JSNodeList*>(handle.slot()->asCell()); if (!jsNodeList->hasCustomProperties()) return false; - if (jsNodeList->impl().isLiveNodeList()) - return visitor.containsOpaqueRoot(root(static_cast<LiveNodeList&>(jsNodeList->impl()).ownerNode())); - if (jsNodeList->impl().isChildNodeList()) - return visitor.containsOpaqueRoot(root(static_cast<ChildNodeList&>(jsNodeList->impl()).ownerNode())); - if (jsNodeList->impl().isEmptyNodeList()) - return visitor.containsOpaqueRoot(root(static_cast<EmptyNodeList&>(jsNodeList->impl()).ownerNode())); + if (jsNodeList->wrapped().isLiveNodeList()) + return visitor.containsOpaqueRoot(root(static_cast<LiveNodeList&>(jsNodeList->wrapped()).ownerNode())); + if (jsNodeList->wrapped().isChildNodeList()) + return visitor.containsOpaqueRoot(root(static_cast<ChildNodeList&>(jsNodeList->wrapped()).ownerNode())); + if (jsNodeList->wrapped().isEmptyNodeList()) + return visitor.containsOpaqueRoot(root(static_cast<EmptyNodeList&>(jsNodeList->wrapped()).ownerNode())); return false; } -bool JSNodeList::getOwnPropertySlotDelegate(ExecState* exec, PropertyName propertyName, PropertySlot& slot) +JSC::JSValue createWrapper(JSDOMGlobalObject& globalObject, Ref<NodeList>&& nodeList) { - if (Node* item = impl().namedItem(propertyNameToAtomicString(propertyName))) { - slot.setValue(this, ReadOnly | DontDelete | DontEnum, toJS(exec, globalObject(), item)); - return true; - } - return false; + // FIXME: Adopt reportExtraMemoryVisited, and switch to reportExtraMemoryAllocated. + // https://bugs.webkit.org/show_bug.cgi?id=142595 + globalObject.vm().heap.deprecatedReportExtraMemory(nodeList->memoryCost()); + return createWrapper<NodeList>(&globalObject, WTFMove(nodeList)); +} + +JSC::JSValue toJSNewlyCreated(ExecState*, JSDOMGlobalObject* globalObject, Ref<NodeList>&& nodeList) +{ + return createWrapper(*globalObject, WTFMove(nodeList)); } } // namespace WebCore diff --git a/Source/WebCore/bindings/js/JSNodeListCustom.h b/Source/WebCore/bindings/js/JSNodeListCustom.h new file mode 100644 index 000000000..845bb409a --- /dev/null +++ b/Source/WebCore/bindings/js/JSNodeListCustom.h @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2014 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +#include "JSDOMBinding.h" +#include "JSNodeList.h" + +namespace WebCore { + +WEBCORE_EXPORT JSC::JSValue createWrapper(JSDOMGlobalObject&, Ref<NodeList>&&); + +ALWAYS_INLINE JSC::JSValue toJS(JSC::ExecState*, JSDOMGlobalObject* globalObject, NodeList& nodeList) +{ + if (auto wrapper = getCachedWrapper(globalObject->world(), nodeList)) + return wrapper; + return createWrapper(*globalObject, nodeList); +} + +} // namespace WebCore diff --git a/Source/WebCore/bindings/js/JSOscillatorNodeCustom.cpp b/Source/WebCore/bindings/js/JSOscillatorNodeCustom.cpp deleted file mode 100644 index f44625c0f..000000000 --- a/Source/WebCore/bindings/js/JSOscillatorNodeCustom.cpp +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright (C) 2012, Google Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" - -#if ENABLE(WEB_AUDIO) - -#include "JSOscillatorNode.h" - -#include "ExceptionCode.h" -#include "OscillatorNode.h" -#include <runtime/Error.h> - -using namespace JSC; - -namespace WebCore { - -void JSOscillatorNode::setType(ExecState* exec, JSValue value) -{ - OscillatorNode& imp = impl(); - -#if ENABLE(LEGACY_WEB_AUDIO) - if (value.isNumber()) { - uint32_t type = value.toUInt32(exec); - if (!imp.setType(type)) - exec->vm().throwException(exec, createTypeError(exec, "Illegal OscillatorNode type")); - return; - } -#endif - - if (value.isString()) { - String type = value.toString(exec)->value(exec); - if (type == "sine" || type == "square" || type == "sawtooth" || type == "triangle") { - imp.setType(type); - return; - } - } - - exec->vm().throwException(exec, createTypeError(exec, "Illegal OscillatorNode type")); -} - -} // namespace WebCore - -#endif // ENABLE(WEB_AUDIO) diff --git a/Source/WebCore/bindings/js/JSPannerNodeCustom.cpp b/Source/WebCore/bindings/js/JSPannerNodeCustom.cpp deleted file mode 100644 index f28978520..000000000 --- a/Source/WebCore/bindings/js/JSPannerNodeCustom.cpp +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Copyright (C) 2012, Google Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" - -#if ENABLE(WEB_AUDIO) - -#include "JSPannerNode.h" - -#include "ExceptionCode.h" -#include "PannerNode.h" -#include <runtime/Error.h> - -using namespace JSC; - -namespace WebCore { - -void JSPannerNode::setPanningModel(ExecState* exec, JSValue value) -{ - PannerNode& imp = impl(); - -#if ENABLE(LEGACY_WEB_AUDIO) - if (value.isNumber()) { - uint32_t model = value.toUInt32(exec); - if (!imp.setPanningModel(model)) - exec->vm().throwException(exec, createTypeError(exec, "Illegal panningModel")); - return; - } -#endif - - if (value.isString()) { - String model = value.toString(exec)->value(exec); - if (model == "equalpower" || model == "HRTF" || model == "soundfield") { - imp.setPanningModel(model); - return; - } - } - - exec->vm().throwException(exec, createTypeError(exec, "Illegal panningModel")); -} - -void JSPannerNode::setDistanceModel(ExecState* exec, JSValue value) -{ - PannerNode& imp = impl(); - -#if ENABLE(LEGACY_WEB_AUDIO) - if (value.isNumber()) { - uint32_t model = value.toUInt32(exec); - if (!imp.setDistanceModel(model)) - exec->vm().throwException(exec, createTypeError(exec, "Illegal distanceModel")); - return; - } -#endif - - if (value.isString()) { - String model = value.toString(exec)->value(exec); - if (model == "linear" || model == "inverse" || model == "exponential") { - imp.setDistanceModel(model); - return; - } - } - - exec->vm().throwException(exec, createTypeError(exec, "Illegal distanceModel")); -} - -} // namespace WebCore - -#endif // ENABLE(WEB_AUDIO) diff --git a/Source/WebCore/bindings/js/JSPerformanceEntryCustom.cpp b/Source/WebCore/bindings/js/JSPerformanceEntryCustom.cpp index 0b6f98ce1..471897834 100644 --- a/Source/WebCore/bindings/js/JSPerformanceEntryCustom.cpp +++ b/Source/WebCore/bindings/js/JSPerformanceEntryCustom.cpp @@ -30,7 +30,7 @@ #include "config.h" -#if ENABLE(PERFORMANCE_TIMELINE) +#if ENABLE(WEB_TIMING) #include "JSPerformanceEntry.h" @@ -46,27 +46,25 @@ using namespace JSC; namespace WebCore { -JSValue toJS(ExecState* exec, JSDOMGlobalObject* globalObject, PerformanceEntry* entry) +JSValue toJSNewlyCreated(ExecState*, JSDOMGlobalObject* globalObject, Ref<PerformanceEntry>&& entry) { - if (!entry) - return jsNull(); + if (is<PerformanceResourceTiming>(entry)) + return createWrapper<PerformanceResourceTiming>(globalObject, WTFMove(entry)); -#if ENABLE(RESOURCE_TIMING) - if (entry->isResource()) - return wrap<JSPerformanceResourceTiming>(exec, globalObject, static_cast<PerformanceResourceTiming*>(entry)); -#endif + if (is<PerformanceMark>(entry)) + return createWrapper<PerformanceMark>(globalObject, WTFMove(entry)); -#if ENABLE(USER_TIMING) - if (entry->isMark()) - return wrap<JSPerformanceMark>(exec, globalObject, static_cast<PerformanceMark*>(entry)); + if (is<PerformanceMeasure>(entry)) + return createWrapper<PerformanceMeasure>(globalObject, WTFMove(entry)); - if (entry->isMeasure()) - return wrap<JSPerformanceMeasure>(exec, globalObject, static_cast<PerformanceMeasure*>(entry)); -#endif + return createWrapper<PerformanceEntry>(globalObject, WTFMove(entry)); +} - return wrap<JSPerformanceEntry>(exec, globalObject, entry); +JSValue toJS(JSC::ExecState* state, JSDOMGlobalObject* globalObject, PerformanceEntry& entry) +{ + return wrap(state, globalObject, entry); } } // namespace WebCore -#endif // ENABLE(PERFORMANCE_TIMELINE) +#endif // ENABLE(WEB_TIMING) diff --git a/Source/WebCore/bindings/js/JSPluginElementFunctions.cpp b/Source/WebCore/bindings/js/JSPluginElementFunctions.cpp index 7f62aa2a7..88b5b123a 100644 --- a/Source/WebCore/bindings/js/JSPluginElementFunctions.cpp +++ b/Source/WebCore/bindings/js/JSPluginElementFunctions.cpp @@ -1,6 +1,6 @@ /* * Copyright (C) 1999-2000 Harri Porten (porten@kde.org) - * Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved. + * Copyright (C) 2004-2017 Apple Inc. All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -35,77 +35,73 @@ using namespace HTMLNames; // JavaScript access to plug-in-exported properties for JSHTMLAppletElement, JSHTMLEmbedElement and JSHTMLObjectElement. -static inline bool isPluginElement(HTMLElement& element) -{ - return element.hasTagName(objectTag) || element.hasTagName(embedTag) || element.hasTagName(appletTag); -} - Instance* pluginInstance(HTMLElement& element) { // The plugin element holds an owning reference, so we don't have to. - if (!isPluginElement(element)) - return 0; - Instance* instance = toHTMLPlugInElement(element).getInstance().get(); + if (!is<HTMLPlugInElement>(element)) + return nullptr; + auto* instance = downcast<HTMLPlugInElement>(element).bindingsInstance(); if (!instance || !instance->rootObject()) - return 0; + return nullptr; return instance; } static JSObject* pluginScriptObjectFromPluginViewBase(HTMLPlugInElement& pluginElement, JSGlobalObject* globalObject) { Widget* pluginWidget = pluginElement.pluginWidget(); - if (!pluginWidget) - return 0; - - if (!pluginWidget->isPluginViewBase()) - return 0; + if (!is<PluginViewBase>(pluginWidget)) + return nullptr; - PluginViewBase* pluginViewBase = toPluginViewBase(pluginWidget); - return pluginViewBase->scriptObject(globalObject); + return downcast<PluginViewBase>(*pluginWidget).scriptObject(globalObject); } static JSObject* pluginScriptObjectFromPluginViewBase(JSHTMLElement* jsHTMLElement) { - HTMLElement& element = jsHTMLElement->impl(); - if (!isPluginElement(element)) - return 0; + HTMLElement& element = jsHTMLElement->wrapped(); + if (!is<HTMLPlugInElement>(element)) + return nullptr; - HTMLPlugInElement& pluginElement = toHTMLPlugInElement(element); + HTMLPlugInElement& pluginElement = downcast<HTMLPlugInElement>(element); return pluginScriptObjectFromPluginViewBase(pluginElement, jsHTMLElement->globalObject()); } JSObject* pluginScriptObject(ExecState* exec, JSHTMLElement* jsHTMLElement) { - HTMLElement& element = jsHTMLElement->impl(); - if (!isPluginElement(element)) - return 0; + HTMLElement& element = jsHTMLElement->wrapped(); + if (!is<HTMLPlugInElement>(element)) + return nullptr; + + auto& pluginElement = downcast<HTMLPlugInElement>(element); - HTMLPlugInElement& pluginElement = toHTMLPlugInElement(element); + // Choke point for script/plugin interaction; notify DOMTimer of the event. + DOMTimer::scriptDidInteractWithPlugin(pluginElement); // First, see if the element has a plug-in replacement with a script. - if (JSObject* scriptObject = pluginElement.scriptObjectForPluginReplacement()) + if (auto* scriptObject = pluginElement.scriptObjectForPluginReplacement()) return scriptObject; // Next, see if we can ask the plug-in view for its script object. - if (JSObject* scriptObject = pluginScriptObjectFromPluginViewBase(pluginElement, jsHTMLElement->globalObject())) + if (auto* scriptObject = pluginScriptObjectFromPluginViewBase(pluginElement, jsHTMLElement->globalObject())) return scriptObject; // Otherwise, fall back to getting the object from the instance. // The plugin element holds an owning reference, so we don't have to. - Instance* instance = pluginElement.getInstance().get(); + auto* instance = pluginElement.bindingsInstance(); if (!instance || !instance->rootObject()) - return 0; + return nullptr; return instance->createRuntimeObject(exec); } -EncodedJSValue pluginElementPropertyGetter(ExecState* exec, EncodedJSValue, EncodedJSValue thisValue, PropertyName propertyName) +EncodedJSValue pluginElementPropertyGetter(ExecState* exec, EncodedJSValue thisValue, PropertyName propertyName) { + VM& vm = exec->vm(); + auto scope = DECLARE_THROW_SCOPE(vm); - JSHTMLElement* thisObject = jsDynamicCast<JSHTMLElement*>(JSValue::decode(thisValue)); + JSHTMLElement* thisObject = jsDynamicDowncast<JSHTMLElement*>(vm, JSValue::decode(thisValue)); if (!thisObject) - return throwVMTypeError(exec); + return throwVMTypeError(exec, scope); JSObject* scriptObject = pluginScriptObject(exec, thisObject); if (!scriptObject) return JSValue::encode(jsUndefined()); @@ -125,20 +121,20 @@ bool pluginElementCustomGetOwnPropertySlot(ExecState* exec, PropertyName propert return true; } -bool pluginElementCustomPut(ExecState* exec, PropertyName propertyName, JSValue value, JSHTMLElement* element, PutPropertySlot& slot) +bool pluginElementCustomPut(ExecState* exec, PropertyName propertyName, JSValue value, JSHTMLElement* element, PutPropertySlot& slot, bool& putResult) { JSObject* scriptObject = pluginScriptObject(exec, element); if (!scriptObject) - return 0; + return false; if (!scriptObject->hasProperty(exec, propertyName)) return false; - scriptObject->methodTable()->put(scriptObject, exec, propertyName, value, slot); + putResult = scriptObject->methodTable()->put(scriptObject, exec, propertyName, value, slot); return true; } static EncodedJSValue JSC_HOST_CALL callPlugin(ExecState* exec) { - JSHTMLElement* element = jsCast<JSHTMLElement*>(exec->callee()); + JSHTMLElement* element = jsCast<JSHTMLElement*>(exec->jsCallee()); // Get the plug-in script object. JSObject* scriptObject = pluginScriptObject(exec, element); @@ -151,10 +147,10 @@ static EncodedJSValue JSC_HOST_CALL callPlugin(ExecState* exec) CallData callData; CallType callType = getCallData(scriptObject, callData); - ASSERT(callType == CallTypeHost); + ASSERT(callType == CallType::Host); // Call the object. - JSValue result = call(exec, scriptObject, callType, callData, exec->hostThisValue(), argumentList); + JSValue result = call(exec, scriptObject, callType, callData, exec->thisValue(), argumentList); return JSValue::encode(result); } @@ -164,18 +160,18 @@ CallType pluginElementGetCallData(JSHTMLElement* element, CallData& callData) if (JSObject* scriptObject = pluginScriptObjectFromPluginViewBase(element)) { CallData scriptObjectCallData; - if (scriptObject->methodTable()->getCallData(scriptObject, scriptObjectCallData) == CallTypeNone) - return CallTypeNone; + if (scriptObject->methodTable()->getCallData(scriptObject, scriptObjectCallData) == CallType::None) + return CallType::None; callData.native.function = callPlugin; - return CallTypeHost; + return CallType::Host; } - Instance* instance = pluginInstance(element->impl()); + Instance* instance = pluginInstance(element->wrapped()); if (!instance || !instance->supportsInvokeDefaultMethod()) - return CallTypeNone; + return CallType::None; callData.native.function = callPlugin; - return CallTypeHost; + return CallType::Host; } } // namespace WebCore diff --git a/Source/WebCore/bindings/js/JSPluginElementFunctions.h b/Source/WebCore/bindings/js/JSPluginElementFunctions.h index 8a2e99d59..f4f5f4ca9 100644 --- a/Source/WebCore/bindings/js/JSPluginElementFunctions.h +++ b/Source/WebCore/bindings/js/JSPluginElementFunctions.h @@ -17,8 +17,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#ifndef JSPluginElementFunctions_h -#define JSPluginElementFunctions_h +#pragma once #include "JSDOMBinding.h" @@ -36,27 +35,22 @@ namespace WebCore { // JavaScript access to plug-in-exported properties for JSHTMLAppletElement, JSHTMLEmbedElement and JSHTMLObjectElement. JSC::Bindings::Instance* pluginInstance(HTMLElement&); - JSC::JSObject* pluginScriptObject(JSC::ExecState*, JSHTMLElement*); + WEBCORE_EXPORT JSC::JSObject* pluginScriptObject(JSC::ExecState*, JSHTMLElement*); - JSC::EncodedJSValue pluginElementPropertyGetter(JSC::ExecState*, JSC::EncodedJSValue, JSC::EncodedJSValue, JSC::PropertyName); + JSC::EncodedJSValue pluginElementPropertyGetter(JSC::ExecState*, JSC::EncodedJSValue, JSC::PropertyName); bool pluginElementCustomGetOwnPropertySlot(JSC::ExecState*, JSC::PropertyName, JSC::PropertySlot&, JSHTMLElement*); - bool pluginElementCustomPut(JSC::ExecState*, JSC::PropertyName, JSC::JSValue, JSHTMLElement*, JSC::PutPropertySlot&); + bool pluginElementCustomPut(JSC::ExecState*, JSC::PropertyName, JSC::JSValue, JSHTMLElement*, JSC::PutPropertySlot&, bool& putResult); JSC::CallType pluginElementGetCallData(JSHTMLElement*, JSC::CallData&); template <class Type, class Base> bool pluginElementCustomGetOwnPropertySlot(JSC::ExecState* exec, JSC::PropertyName propertyName, JSC::PropertySlot& slot, Type* element) { if (!element->globalObject()->world().isNormal()) { - if (JSC::getStaticValueSlot<Type, Base>(exec, *Type::info()->staticPropHashTable, element, propertyName, slot)) - return true; - - JSC::JSValue proto = element->prototype(); + JSC::JSValue proto = element->getPrototypeDirect(); if (proto.isObject() && JSC::jsCast<JSC::JSObject*>(asObject(proto))->hasProperty(exec, propertyName)) return false; } - + return pluginElementCustomGetOwnPropertySlot(exec, propertyName, slot, element); } } // namespace WebCore - -#endif // JSPluginElementFunctions_h diff --git a/Source/WebCore/bindings/js/JSPopStateEventCustom.cpp b/Source/WebCore/bindings/js/JSPopStateEventCustom.cpp index e4d46f792..aadb860a3 100644 --- a/Source/WebCore/bindings/js/JSPopStateEventCustom.cpp +++ b/Source/WebCore/bindings/js/JSPopStateEventCustom.cpp @@ -29,36 +29,51 @@ */ #include "config.h" +#include "JSPopStateEvent.h" -#include "History.h" +#include "DOMWrapperWorld.h" #include "JSHistory.h" -#include "JSPopStateEvent.h" +#include <heap/HeapInlines.h> +#include <runtime/JSCJSValueInlines.h> using namespace JSC; namespace WebCore { // Save the state value to the m_state member of a JSPopStateEvent, and return it, for convenience. -static const JSValue& cacheState(ExecState* exec, JSPopStateEvent* event, const JSValue& state) +static const JSValue& cacheState(ExecState& state, const JSPopStateEvent* event, const JSValue& eventState) { - event->m_state.set(exec->vm(), event, state); - return state; + event->m_state.set(state.vm(), event, eventState); + return eventState; } -JSValue JSPopStateEvent::state(ExecState* exec) const +JSValue JSPopStateEvent::state(ExecState& state) const { JSValue cachedValue = m_state.get(); - if (!cachedValue.isEmpty()) - return cachedValue; - - PopStateEvent& event = impl(); + if (!cachedValue.isEmpty()) { + // We cannot use a cached object if we are in a different world than the one it was created in. + if (!cachedValue.isObject() || &worldForDOMObject(cachedValue.getObject()) == ¤tWorld(&state)) + return cachedValue; + ASSERT_NOT_REACHED(); + } - if (!event.state().hasNoValue()) - return cacheState(exec, const_cast<JSPopStateEvent*>(this), event.state().jsValue()); + PopStateEvent& event = wrapped(); + if (auto eventState = event.state()) { + // We need to make sure a PopStateEvent does not leak objects in its state property across isolated DOM worlds. + // Ideally, we would check that the worlds have different privileges but that's not possible yet. + if (eventState.isObject() && &worldForDOMObject(eventState.getObject()) != ¤tWorld(&state)) { + if (auto serializedValue = event.trySerializeState(state)) + eventState = serializedValue->deserialize(state, globalObject()); + else + eventState = jsNull(); + } + return cacheState(state, this, eventState); + } + History* history = event.history(); if (!history || !event.serializedState()) - return cacheState(exec, const_cast<JSPopStateEvent*>(this), jsNull()); + return cacheState(state, this, jsNull()); // There's no cached value from a previous invocation, nor a state value was provided by the // event, but there is a history object, so first we need to see if the state object has been @@ -66,16 +81,16 @@ JSValue JSPopStateEvent::state(ExecState* exec) const // The current history state object might've changed in the meantime, so we need to take care // of using the correct one, and always share the same deserialization with history.state. - bool isSameState = history->isSameAsCurrentState(event.serializedState().get()); + bool isSameState = history->isSameAsCurrentState(event.serializedState()); JSValue result; if (isSameState) { - JSHistory* jsHistory = jsCast<JSHistory*>(toJS(exec, globalObject(), history).asCell()); - result = jsHistory->state(exec); + JSHistory* jsHistory = jsCast<JSHistory*>(toJS(&state, globalObject(), *history).asCell()); + result = jsHistory->state(state); } else - result = event.serializedState()->deserialize(exec, globalObject(), 0); + result = event.serializedState()->deserialize(state, globalObject()); - return cacheState(exec, const_cast<JSPopStateEvent*>(this), result); + return cacheState(state, this, result); } } // namespace WebCore diff --git a/Source/WebCore/bindings/js/JSRTCIceCandidateCustom.cpp b/Source/WebCore/bindings/js/JSRTCIceCandidateCustom.cpp deleted file mode 100644 index 148ff1154..000000000 --- a/Source/WebCore/bindings/js/JSRTCIceCandidateCustom.cpp +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright (C) 2013 Nokia Corporation and/or its subsidiary(-ies). - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" - -#if ENABLE(MEDIA_STREAM) - -#include "JSRTCIceCandidate.h" - -#include "Dictionary.h" -#include "ExceptionCode.h" - -using namespace JSC; - -namespace WebCore { - -EncodedJSValue JSC_HOST_CALL JSRTCIceCandidateConstructor::constructJSRTCIceCandidate(ExecState* exec) -{ - ExceptionCode ec = 0; - Dictionary sessionInit; - if (exec->argumentCount() > 0) { - sessionInit = Dictionary(exec, exec->argument(0)); - if (!sessionInit.isObject()) - return throwVMError(exec, createTypeError(exec, "Optional RTCIceCandidate constructor argument must be a valid Dictionary")); - - if (exec->hadException()) - return JSValue::encode(jsUndefined()); - } - - JSRTCIceCandidateConstructor* jsConstructor = jsCast<JSRTCIceCandidateConstructor*>(exec->callee()); - RefPtr<RTCIceCandidate> iceCandidate = RTCIceCandidate::create(sessionInit, ec); - if (ec == TYPE_MISMATCH_ERR) { - setDOMException(exec, ec); - return throwVMError(exec, createTypeError(exec, "Invalid RTCIceCandidate constructor arguments")); - } - - if (ec) { - setDOMException(exec, ec); - return throwVMError(exec, createTypeError(exec, "Error creating RTCIceCandidate")); - } - - return JSValue::encode(CREATE_DOM_WRAPPER(exec, jsConstructor->globalObject(), RTCIceCandidate, iceCandidate.get())); -} - -} // namespace WebCore - -#endif // ENABLE(MEDIA_STREAM) - diff --git a/Source/WebCore/bindings/js/JSRTCPeerConnectionCustom.cpp b/Source/WebCore/bindings/js/JSRTCPeerConnectionCustom.cpp deleted file mode 100644 index f24bec22a..000000000 --- a/Source/WebCore/bindings/js/JSRTCPeerConnectionCustom.cpp +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright (C) 2013 Nokia Corporation and/or its subsidiary(-ies). - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" - -#if ENABLE(MEDIA_STREAM) - -#include "JSRTCPeerConnection.h" - -#include "ExceptionCode.h" - -using namespace JSC; - -namespace WebCore { - -EncodedJSValue JSC_HOST_CALL JSRTCPeerConnectionConstructor::constructJSRTCPeerConnection(ExecState* exec) -{ - // Spec says that we must have at least one arument, the RTCConfiguration. - if (exec->argumentCount() < 1) - return throwVMError(exec, createNotEnoughArgumentsError(exec)); - - ExceptionCode ec = 0; - Dictionary rtcConfiguration(exec, exec->argument(0)); - if (exec->hadException()) - return JSValue::encode(jsUndefined()); - - if (!rtcConfiguration.isObject()) - return throwVMError(exec, createTypeError(exec, "First argument of RTCPeerConnection must be a valid Dictionary")); - - Dictionary mediaConstraints; - if (exec->argumentCount() > 1) { - mediaConstraints = Dictionary(exec, exec->argument(1)); - if (!mediaConstraints.isObject()) - return throwVMError(exec, createTypeError(exec, "Optional constraints argument of RTCPeerConnection must be a valid Dictionary")); - - if (exec->hadException()) - return JSValue::encode(jsUndefined()); - } - - JSRTCPeerConnectionConstructor* jsConstructor = jsCast<JSRTCPeerConnectionConstructor*>(exec->callee()); - ScriptExecutionContext* scriptExecutionContext = jsConstructor->scriptExecutionContext(); - if (!scriptExecutionContext) - return throwVMError(exec, createReferenceError(exec, "RTCPeerConnection constructor associated document is unavailable")); - - RefPtr<RTCPeerConnection> peerConnection = RTCPeerConnection::create(*scriptExecutionContext, rtcConfiguration, mediaConstraints, ec); - if (ec == TYPE_MISMATCH_ERR) { - setDOMException(exec, ec); - return throwVMError(exec, createTypeError(exec, "Invalid RTCPeerConnection constructor arguments")); - } - - if (ec) { - setDOMException(exec, ec); - return throwVMError(exec, createTypeError(exec, "Error creating RTCPeerConnection")); - } - - return JSValue::encode(CREATE_DOM_WRAPPER(exec, jsConstructor->globalObject(), RTCPeerConnection, peerConnection.get())); -} - -} // namespace WebCore - -#endif // ENABLE(MEDIA_STREAM) diff --git a/Source/WebCore/bindings/js/JSRTCSessionDescriptionCustom.cpp b/Source/WebCore/bindings/js/JSRTCSessionDescriptionCustom.cpp deleted file mode 100644 index ddf03f3e7..000000000 --- a/Source/WebCore/bindings/js/JSRTCSessionDescriptionCustom.cpp +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright (C) 2013 Nokia Corporation and/or its subsidiary(-ies). - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" - -#if ENABLE(MEDIA_STREAM) - -#include "JSRTCSessionDescription.h" - -#include "Dictionary.h" -#include "ExceptionCode.h" - -using namespace JSC; - -namespace WebCore { - -EncodedJSValue JSC_HOST_CALL JSRTCSessionDescriptionConstructor::constructJSRTCSessionDescription(ExecState* exec) -{ - ExceptionCode ec = 0; - Dictionary sessionInit; - if (exec->argumentCount() > 0) { - sessionInit = Dictionary(exec, exec->argument(0)); - if (!sessionInit.isObject()) - return throwVMError(exec, createTypeError(exec, "Optional RTCSessionDescription constructor argument must be a valid Dictionary")); - - if (exec->hadException()) - return JSValue::encode(jsUndefined()); - } - - JSRTCSessionDescriptionConstructor* jsConstructor = jsCast<JSRTCSessionDescriptionConstructor*>(exec->callee()); - RefPtr<RTCSessionDescription> sessionDescription = RTCSessionDescription::create(sessionInit, ec); - if (ec == TYPE_MISMATCH_ERR) { - setDOMException(exec, ec); - return throwVMError(exec, createTypeError(exec, "Invalid RTCSessionDescription constructor arguments")); - } - - if (ec) { - setDOMException(exec, ec); - return throwVMError(exec, createTypeError(exec, "Error creating RTCSessionDescription")); - } - - return JSValue::encode(CREATE_DOM_WRAPPER(exec, jsConstructor->globalObject(), RTCSessionDescription, sessionDescription.get())); -} - -} // namespace WebCore - -#endif // ENABLE(MEDIA_STREAM) - diff --git a/Source/WebCore/bindings/js/JSReadableStreamPrivateConstructors.cpp b/Source/WebCore/bindings/js/JSReadableStreamPrivateConstructors.cpp new file mode 100644 index 000000000..984cfc315 --- /dev/null +++ b/Source/WebCore/bindings/js/JSReadableStreamPrivateConstructors.cpp @@ -0,0 +1,129 @@ +/* + * Copyright (C) 2015 Canon Inc. All rights reserved. + * Copyright (C) 2016 Apple Inc. All rights reserved. + * + * 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 + */ + +#include "config.h" +#include "JSReadableStreamPrivateConstructors.h" + +#if ENABLE(READABLE_STREAM_API) + +#include "JSDOMBuiltinConstructor.h" +#include "JSReadableByteStreamController.h" +#include "JSReadableStream.h" +#include "JSReadableStreamDefaultController.h" +#include "JSReadableStreamDefaultReader.h" +#include "ReadableByteStreamInternalsBuiltins.h" +#include "ReadableStreamInternalsBuiltins.h" +#include "WebCoreJSClientData.h" +#include <runtime/JSCInlines.h> + +using namespace JSC; + +namespace WebCore { + +// Public JS ReadableStreamReader and ReadableStreamDefaultController constructor callbacks. +EncodedJSValue JSC_HOST_CALL constructJSReadableStreamDefaultController(ExecState& exec) +{ + VM& vm = exec.vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + return throwVMTypeError(&exec, scope, ASCIILiteral("ReadableStreamDefaultController constructor should not be called directly")); +} + +#if ENABLE(READABLE_BYTE_STREAM_API) +// Public JS ReadableByteStreamController constructor callback. +EncodedJSValue JSC_HOST_CALL constructJSReadableByteStreamController(ExecState& exec) +{ + VM& vm = exec.vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + return throwVMTypeError(&exec, scope, ASCIILiteral("ReadableByteStreamController constructor should not be called directly")); +} +#endif + +EncodedJSValue JSC_HOST_CALL constructJSReadableStreamDefaultReader(ExecState& exec) +{ + VM& vm = exec.vm(); + JSVMClientData& clientData = *static_cast<JSVMClientData*>(vm.clientData); + JSDOMGlobalObject& globalObject = *static_cast<JSDOMGlobalObject*>(exec.lexicalGlobalObject()); + + JSC::JSObject* constructor = JSC::asObject(globalObject.get(&exec, clientData.builtinNames().ReadableStreamDefaultReaderPrivateName())); + ConstructData constructData; + ConstructType constructType = constructor->methodTable(vm)->getConstructData(constructor, constructData); + ASSERT(constructType != ConstructType::None); + + MarkedArgumentBuffer args; + args.append(exec.argument(0)); + return JSValue::encode(JSC::construct(&exec, constructor, constructType, constructData, args)); +} + +// Private JS ReadableStreamDefaultReader and ReadableStreamDefaultController constructors. +using JSBuiltinReadableStreamDefaultReaderPrivateConstructor = JSDOMBuiltinConstructor<JSReadableStreamDefaultReader>; +using JSBuiltinReadableStreamDefaultControllerPrivateConstructor = JSDOMBuiltinConstructor<JSReadableStreamDefaultController>; +#if ENABLE(READABLE_BYTE_STREAM_API) +// Private JS ReadableByteStreamController constructor. +using JSBuiltinReadableByteStreamControllerPrivateConstructor = JSDOMBuiltinConstructor<JSReadableByteStreamController>; +#endif + +STATIC_ASSERT_IS_TRIVIALLY_DESTRUCTIBLE(JSBuiltinReadableStreamDefaultReaderPrivateConstructor); +STATIC_ASSERT_IS_TRIVIALLY_DESTRUCTIBLE(JSBuiltinReadableStreamDefaultControllerPrivateConstructor); +#if ENABLE(READABLE_BYTE_STREAM_API) +STATIC_ASSERT_IS_TRIVIALLY_DESTRUCTIBLE(JSBuiltinReadableByteStreamControllerPrivateConstructor); +#endif + +template<> const ClassInfo JSBuiltinReadableStreamDefaultReaderPrivateConstructor::s_info = { "ReadableStreamDefaultReaderPrivateConstructor", &Base::s_info, 0, CREATE_METHOD_TABLE(JSBuiltinReadableStreamDefaultReaderPrivateConstructor) }; +template<> const ClassInfo JSBuiltinReadableStreamDefaultControllerPrivateConstructor::s_info = { "ReadableStreamDefaultControllerPrivateConstructor", &Base::s_info, 0, CREATE_METHOD_TABLE(JSBuiltinReadableStreamDefaultControllerPrivateConstructor) }; +#if ENABLE(READABLE_BYTE_STREAM_API) +template<> const ClassInfo JSBuiltinReadableByteStreamControllerPrivateConstructor::s_info = { "ReadableByteStreamControllerPrivateConstructor", &Base::s_info, 0, CREATE_METHOD_TABLE(JSBuiltinReadableByteStreamControllerPrivateConstructor) }; +#endif + +template<> FunctionExecutable* JSBuiltinReadableStreamDefaultReaderPrivateConstructor::initializeExecutable(JSC::VM& vm) +{ + return readableStreamInternalsPrivateInitializeReadableStreamDefaultReaderCodeGenerator(vm); +} + +template<> FunctionExecutable* JSBuiltinReadableStreamDefaultControllerPrivateConstructor::initializeExecutable(JSC::VM& vm) +{ + return readableStreamInternalsPrivateInitializeReadableStreamDefaultControllerCodeGenerator(vm); +} + +#if ENABLE(READABLE_BYTE_STREAM_API) +template<> FunctionExecutable* JSBuiltinReadableByteStreamControllerPrivateConstructor::initializeExecutable(JSC::VM& vm) +{ + return readableByteStreamInternalsPrivateInitializeReadableByteStreamControllerCodeGenerator(vm); +} +#endif + +JSObject* createReadableStreamDefaultReaderPrivateConstructor(VM& vm, JSDOMGlobalObject& globalObject) +{ + return JSBuiltinReadableStreamDefaultReaderPrivateConstructor::create(vm, JSBuiltinReadableStreamDefaultReaderPrivateConstructor::createStructure(vm, globalObject, globalObject.objectPrototype()), globalObject); +} + +JSObject* createReadableStreamDefaultControllerPrivateConstructor(VM& vm, JSDOMGlobalObject& globalObject) +{ + return JSBuiltinReadableStreamDefaultControllerPrivateConstructor::create(vm, JSBuiltinReadableStreamDefaultControllerPrivateConstructor::createStructure(vm, globalObject, globalObject.objectPrototype()), globalObject); +} + +#if ENABLE(READABLE_BYTE_STREAM_API) +JSObject* createReadableByteStreamControllerPrivateConstructor(VM& vm, JSDOMGlobalObject& globalObject) +{ + return JSBuiltinReadableByteStreamControllerPrivateConstructor::create(vm, JSBuiltinReadableByteStreamControllerPrivateConstructor::createStructure(vm, globalObject, globalObject.objectPrototype()), globalObject); +} +#endif + +} // namespace WebCore + +#endif diff --git a/Source/WebCore/bindings/gobject/DOMObjectCache.h b/Source/WebCore/bindings/js/JSReadableStreamPrivateConstructors.h index e3e9fc3ec..ac16afdef 100644 --- a/Source/WebCore/bindings/gobject/DOMObjectCache.h +++ b/Source/WebCore/bindings/js/JSReadableStreamPrivateConstructors.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010 Igalia S.L. + * Copyright (C) 2015 Canon Inc. All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -16,21 +16,26 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#ifndef DOMObjectCache_h -#define DOMObjectCache_h +#pragma once + +#if ENABLE(READABLE_STREAM_API) + +namespace JSC { +class JSObject; +class VM; +} namespace WebCore { -class Node; -}; - -namespace WebKit { -class DOMObjectCache { -public: - static void* get(void* objectHandle); - static void put(void* objectHandle, void* wrapper); - static void put(WebCore::Node* objectHandle, void* wrapper); - static void forget(void* objectHandle); -}; -} // namespace WebKit +class JSDOMGlobalObject; + +JSC::JSObject* createReadableStreamDefaultReaderPrivateConstructor(JSC::VM&, JSDOMGlobalObject&); +JSC::JSObject* createReadableStreamDefaultControllerPrivateConstructor(JSC::VM&, JSDOMGlobalObject&); + +#if ENABLE(READABLE_BYTE_STREAM_API) +JSC::JSObject* createReadableByteStreamControllerPrivateConstructor(JSC::VM&, JSDOMGlobalObject&); #endif + +} // namespace WebCore + +#endif // ENABLE(READABLE_STREAM_API) diff --git a/Source/WebCore/bindings/js/JSReadableStreamSourceCustom.cpp b/Source/WebCore/bindings/js/JSReadableStreamSourceCustom.cpp new file mode 100644 index 000000000..5cf0a8478 --- /dev/null +++ b/Source/WebCore/bindings/js/JSReadableStreamSourceCustom.cpp @@ -0,0 +1,85 @@ +/* + * Copyright (C) 2016 Canon Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted, provided that the following conditions + * are required to be met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Canon Inc. nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY CANON INC. AND ITS CONTRIBUTORS "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL CANON INC. AND ITS CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "JSReadableStreamSource.h" + +#if ENABLE(READABLE_STREAM_API) + +using namespace JSC; + +namespace WebCore { + +static void startReadableStream(JSC::ExecState& state, Ref<DeferredPromise>&& promise) +{ + VM& vm = state.vm(); + JSReadableStreamSource* source = jsDynamicDowncast<JSReadableStreamSource*>(vm, state.thisValue()); + ASSERT(source); + + ASSERT(state.argumentCount()); + JSReadableStreamDefaultController* controller = jsDynamicDowncast<JSReadableStreamDefaultController*>(vm, state.uncheckedArgument(0)); + ASSERT(controller); + + source->wrapped().start(ReadableStreamDefaultController(controller), WTFMove(promise)); +} + +JSValue JSReadableStreamSource::start(ExecState& state) +{ + VM& vm = state.vm(); + ASSERT(state.argumentCount()); + JSReadableStreamDefaultController* controller = jsDynamicDowncast<JSReadableStreamDefaultController*>(vm, state.uncheckedArgument(0)); + ASSERT(controller); + + m_controller.set(vm, this, controller); + + return callPromiseFunction<startReadableStream, PromiseExecutionScope::WindowOrWorker>(state); +} + +static void pullReadableStream(JSC::ExecState& state, Ref<DeferredPromise>&& promise) +{ + VM& vm = state.vm(); + JSReadableStreamSource* source = jsDynamicDowncast<JSReadableStreamSource*>(vm, state.thisValue()); + ASSERT(source); + + source->wrapped().pull(WTFMove(promise)); +} + +JSValue JSReadableStreamSource::pull(ExecState& state) +{ + return callPromiseFunction<pullReadableStream, PromiseExecutionScope::WindowOrWorker>(state); +} + +JSValue JSReadableStreamSource::controller(ExecState&) const +{ + ASSERT_NOT_REACHED(); + return jsUndefined(); +} + +} + +#endif // ENABLE(READABLE_STREAM_API) diff --git a/Source/WebCore/bindings/js/JSSQLResultSetRowListCustom.cpp b/Source/WebCore/bindings/js/JSSQLResultSetRowListCustom.cpp deleted file mode 100644 index c0b240d11..000000000 --- a/Source/WebCore/bindings/js/JSSQLResultSetRowListCustom.cpp +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright (C) 2007 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of - * its contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" - -#if ENABLE(SQL_DATABASE) - -#include "JSSQLResultSetRowList.h" - -#include "ExceptionCode.h" -#include "SQLValue.h" -#include "SQLResultSetRowList.h" -#include <runtime/ObjectConstructor.h> - -using namespace JSC; - -namespace WebCore { - -JSValue JSSQLResultSetRowList::item(ExecState* exec) -{ - bool indexOk; - int index = finiteInt32Value(exec->argument(0), exec, indexOk); - if (!indexOk) { - setDOMException(exec, TYPE_MISMATCH_ERR); - return jsUndefined(); - } - if (index < 0 || (unsigned)index >= m_impl->length()) { - setDOMException(exec, INDEX_SIZE_ERR); - return jsUndefined(); - } - - JSObject* object = constructEmptyObject(exec); - - unsigned numColumns = m_impl->columnNames().size(); - unsigned valuesIndex = index * numColumns; - for (unsigned i = 0; i < numColumns; i++) { - const SQLValue& value = m_impl->values()[valuesIndex + i]; - JSValue jsValue; - - switch (value.type()) { - case SQLValue::StringValue: - jsValue = jsStringWithCache(exec, value.string()); - break; - case SQLValue::NullValue: - jsValue = jsNull(); - break; - case SQLValue::NumberValue: - jsValue = jsNumber(value.number()); - break; - default: - ASSERT_NOT_REACHED(); - } - - object->putDirect(exec->vm(), Identifier(exec, m_impl->columnNames()[i]), jsValue, DontDelete | ReadOnly); - } - - return object; -} - -} // namespace WebCore - -#endif // ENABLE(SQL_DATABASE) diff --git a/Source/WebCore/bindings/js/JSCustomSQLStatementErrorCallback.cpp b/Source/WebCore/bindings/js/JSSQLStatementErrorCallbackCustom.cpp index b4e315e6e..0030f0178 100644 --- a/Source/WebCore/bindings/js/JSCustomSQLStatementErrorCallback.cpp +++ b/Source/WebCore/bindings/js/JSSQLStatementErrorCallbackCustom.cpp @@ -10,7 +10,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of + * 3. Neither the name of Apple Inc. ("Apple") nor the names of * its contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * @@ -27,14 +27,13 @@ */ #include "config.h" - -#if ENABLE(SQL_DATABASE) - #include "JSSQLStatementErrorCallback.h" +#include "JSDOMExceptionHandling.h" #include "JSSQLError.h" #include "JSSQLTransaction.h" #include "ScriptExecutionContext.h" +#include <runtime/Exception.h> #include <runtime/JSLock.h> #include <wtf/Ref.h> @@ -47,7 +46,7 @@ bool JSSQLStatementErrorCallback::handleEvent(SQLTransaction* transaction, SQLEr if (!m_data || !m_data->globalObject() || !canInvokeCallback()) return true; - Ref<JSSQLStatementErrorCallback> protect(*this); + Ref<JSSQLStatementErrorCallback> protectedThis(*this); JSC::JSLockHolder lock(m_data->globalObject()->vm()); @@ -56,9 +55,11 @@ bool JSSQLStatementErrorCallback::handleEvent(SQLTransaction* transaction, SQLEr args.append(toJS(exec, m_data->globalObject(), transaction)); args.append(toJS(exec, m_data->globalObject(), error)); - bool raisedException = false; - JSValue result = m_data->invokeCallback(args, &raisedException); - if (raisedException) { + NakedPtr<JSC::Exception> returnedException; + JSValue result = m_data->invokeCallback(args, JSCallbackData::CallbackType::Function, Identifier(), returnedException); + if (returnedException) { + reportException(exec, returnedException); + // The spec says: // "If the error callback returns false, then move on to the next statement..." // "Otherwise, the error callback did not return false, or there was no error callback" @@ -69,5 +70,3 @@ bool JSSQLStatementErrorCallback::handleEvent(SQLTransaction* transaction, SQLEr } } - -#endif // ENABLE(SQL_DATABASE) diff --git a/Source/WebCore/bindings/js/JSSQLTransactionCustom.cpp b/Source/WebCore/bindings/js/JSSQLTransactionCustom.cpp deleted file mode 100644 index 7a90c43bf..000000000 --- a/Source/WebCore/bindings/js/JSSQLTransactionCustom.cpp +++ /dev/null @@ -1,122 +0,0 @@ -/* - * Copyright (C) 2007 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of - * its contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" - -#if ENABLE(SQL_DATABASE) - -#include "JSSQLTransaction.h" - -#include "DOMWindow.h" -#include "ExceptionCode.h" -#include "JSSQLStatementCallback.h" -#include "JSSQLStatementErrorCallback.h" -#include "JSDOMWindowCustom.h" -#include "SQLTransaction.h" - -using namespace JSC; - -namespace WebCore { - -JSValue JSSQLTransaction::executeSql(ExecState* exec) -{ - if (!exec->argumentCount()) { - setDOMException(exec, SYNTAX_ERR); - return jsUndefined(); - } - - String sqlStatement = exec->argument(0).toString(exec)->value(exec); - if (exec->hadException()) - return jsUndefined(); - - // Now assemble the list of SQL arguments - Vector<SQLValue> sqlValues; - if (!exec->argument(1).isUndefinedOrNull()) { - JSObject* object = exec->argument(1).getObject(); - if (!object) { - setDOMException(exec, TYPE_MISMATCH_ERR); - return jsUndefined(); - } - - JSValue lengthValue = object->get(exec, exec->propertyNames().length); - if (exec->hadException()) - return jsUndefined(); - unsigned length = lengthValue.toUInt32(exec); - if (exec->hadException()) - return jsUndefined(); - - for (unsigned i = 0 ; i < length; ++i) { - JSValue value = object->get(exec, i); - if (exec->hadException()) - return jsUndefined(); - - if (value.isUndefinedOrNull()) - sqlValues.append(SQLValue()); - else if (value.isNumber()) - sqlValues.append(value.asNumber()); - else { - // Convert the argument to a string and append it - sqlValues.append(value.toString(exec)->value(exec)); - if (exec->hadException()) - return jsUndefined(); - } - } - } - - RefPtr<SQLStatementCallback> callback; - if (!exec->argument(2).isUndefinedOrNull()) { - JSObject* object = exec->argument(2).getObject(); - if (!object) { - setDOMException(exec, TYPE_MISMATCH_ERR); - return jsUndefined(); - } - - callback = JSSQLStatementCallback::create(object, jsCast<JSDOMGlobalObject*>(globalObject())); - } - - RefPtr<SQLStatementErrorCallback> errorCallback; - if (!exec->argument(3).isUndefinedOrNull()) { - JSObject* object = exec->argument(3).getObject(); - if (!object) { - setDOMException(exec, TYPE_MISMATCH_ERR); - return jsUndefined(); - } - - errorCallback = JSSQLStatementErrorCallback::create(object, jsCast<JSDOMGlobalObject*>(globalObject())); - } - - ExceptionCode ec = 0; - m_impl->executeSQL(sqlStatement, sqlValues, callback.release(), errorCallback.release(), ec); - setDOMException(exec, ec); - - return jsUndefined(); -} - -} // namespace WebCore - -#endif // ENABLE(SQL_DATABASE) diff --git a/Source/WebCore/bindings/js/JSSQLTransactionSyncCustom.cpp b/Source/WebCore/bindings/js/JSSQLTransactionSyncCustom.cpp deleted file mode 100644 index b682c451d..000000000 --- a/Source/WebCore/bindings/js/JSSQLTransactionSyncCustom.cpp +++ /dev/null @@ -1,99 +0,0 @@ -/* - * Copyright (C) 2010 Google Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of - * its contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" - -#if ENABLE(SQL_DATABASE) - -#include "JSSQLTransactionSync.h" - -#include "ExceptionCode.h" -#include "JSSQLResultSet.h" -#include "SQLResultSet.h" -#include "SQLTransactionSync.h" -#include "SQLValue.h" - -using namespace JSC; - -namespace WebCore { - -JSValue JSSQLTransactionSync::executeSql(ExecState* exec) -{ - if (!exec->argumentCount()) { - setDOMException(exec, SYNTAX_ERR); - return jsUndefined(); - } - - String sqlStatement = exec->uncheckedArgument(0).toString(exec)->value(exec); - if (exec->hadException()) - return jsUndefined(); - - // Now assemble the list of SQL arguments - Vector<SQLValue> sqlValues; - if (!exec->argument(1).isUndefinedOrNull()) { - JSObject* object = exec->argument(1).getObject(); - if (!object) { - setDOMException(exec, TYPE_MISMATCH_ERR); - return jsUndefined(); - } - - JSValue lengthValue = object->get(exec, exec->propertyNames().length); - if (exec->hadException()) - return jsUndefined(); - unsigned length = lengthValue.toUInt32(exec); - if (exec->hadException()) - return jsUndefined(); - - for (unsigned i = 0 ; i < length; ++i) { - JSValue value = object->get(exec, i); - if (exec->hadException()) - return jsUndefined(); - - if (value.isUndefinedOrNull()) - sqlValues.append(SQLValue()); - else if (value.isNumber()) - sqlValues.append(value.asNumber()); - else { - // Convert the argument to a string and append it - sqlValues.append(value.toString(exec)->value(exec)); - if (exec->hadException()) - return jsUndefined(); - } - } - } - - ExceptionCode ec = 0; - JSValue result = toJS(exec, globalObject(), WTF::getPtr(m_impl->executeSQL(sqlStatement, sqlValues, ec))); - setDOMException(exec, ec); - - return result; -} - -} // namespace WebCore - -#endif // ENABLE(SQL_DATABASE) diff --git a/Source/WebCore/bindings/js/JSSVGElementInstanceCustom.cpp b/Source/WebCore/bindings/js/JSSVGElementInstanceCustom.cpp deleted file mode 100644 index b28e7cf59..000000000 --- a/Source/WebCore/bindings/js/JSSVGElementInstanceCustom.cpp +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright (C) 2008 Nikolas Zimmermann <zimmermann@kde.org> - * Copyright (C) 2009 Apple, Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" - -#if ENABLE(SVG) - -#include "JSSVGElementInstance.h" - -#include "JSEventTarget.h" -#include "JSNodeCustom.h" - -namespace WebCore { - -void JSSVGElementInstance::visitChildren(JSC::JSCell* cell, JSC::SlotVisitor& visitor) -{ - JSSVGElementInstance* thisObject = JSC::jsCast<JSSVGElementInstance*>(cell); - ASSERT_GC_OBJECT_INHERITS(thisObject, info()); - COMPILE_ASSERT(StructureFlags & JSC::OverridesVisitChildren, OverridesVisitChildrenWithoutSettingFlag); - ASSERT(thisObject->structure()->typeInfo().overridesVisitChildren()); - // Skip JSEventTarget::visitChildren because event listener registration is - // forwarded to the corresponding element. - JSEventTarget::Base::visitChildren(thisObject, visitor); - visitor.addOpaqueRoot(root(thisObject->impl().correspondingElement())); -} - -} // namespace WebCore - -#endif // ENABLE(SVG) diff --git a/Source/WebCore/bindings/js/JSSVGLengthCustom.cpp b/Source/WebCore/bindings/js/JSSVGLengthCustom.cpp deleted file mode 100644 index cf78a03ad..000000000 --- a/Source/WebCore/bindings/js/JSSVGLengthCustom.cpp +++ /dev/null @@ -1,104 +0,0 @@ -/* - Copyright (C) 2008 Nikolas Zimmermann <zimmermann@kde.org> - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public License - along with this library; see the file COPYING.LIB. If not, write to - the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - Boston, MA 02110-1301, USA. -*/ - -#include "config.h" - -#if ENABLE(SVG) -#include "JSSVGLength.h" - -#include "ExceptionCode.h" -#include "SVGAnimatedProperty.h" -#include "SVGException.h" -#include "SVGLengthContext.h" -#include <runtime/Error.h> - -using namespace JSC; - -namespace WebCore { - -JSValue JSSVGLength::value(ExecState* exec) const -{ - SVGLength& podImp = impl().propertyReference(); - ExceptionCode ec = 0; - SVGLengthContext lengthContext(impl().contextElement()); - float value = podImp.value(lengthContext, ec); - if (ec) { - setDOMException(exec, ec); - return jsUndefined(); - } - - return jsNumber(value); -} - -void JSSVGLength::setValue(ExecState* exec, JSValue value) -{ - if (impl().isReadOnly()) { - setDOMException(exec, NO_MODIFICATION_ALLOWED_ERR); - return; - } - - if (!value.isUndefinedOrNull() && !value.isNumber() && !value.isBoolean()) { - throwVMTypeError(exec); - return; - } - - SVGLength& podImp = impl().propertyReference(); - - ExceptionCode ec = 0; - SVGLengthContext lengthContext(impl().contextElement()); - podImp.setValue(value.toFloat(exec), lengthContext, ec); - if (ec) { - setDOMException(exec, ec); - return; - } - - impl().commitChange(); -} - -JSValue JSSVGLength::convertToSpecifiedUnits(ExecState* exec) -{ - if (impl().isReadOnly()) { - setDOMException(exec, NO_MODIFICATION_ALLOWED_ERR); - return jsUndefined(); - } - - SVGLength& podImp = impl().propertyReference(); - - if (exec->argumentCount() < 1) - return exec->vm().throwException(exec, createNotEnoughArgumentsError(exec)); - - unsigned short unitType = exec->uncheckedArgument(0).toUInt32(exec); - if (exec->hadException()) - return jsUndefined(); - - ExceptionCode ec = 0; - SVGLengthContext lengthContext(impl().contextElement()); - podImp.convertToSpecifiedUnits(unitType, lengthContext, ec); - if (ec) { - setDOMException(exec, ec); - return jsUndefined(); - } - - impl().commitChange(); - return jsUndefined(); -} - -} - -#endif // ENABLE(SVG) diff --git a/Source/WebCore/bindings/js/JSSVGPathSegCustom.cpp b/Source/WebCore/bindings/js/JSSVGPathSegCustom.cpp index 9d6bf2d39..b4747184a 100644 --- a/Source/WebCore/bindings/js/JSSVGPathSegCustom.cpp +++ b/Source/WebCore/bindings/js/JSSVGPathSegCustom.cpp @@ -18,8 +18,6 @@ */ #include "config.h" - -#if ENABLE(SVG) #include "JSSVGPathSeg.h" #include "JSDOMBinding.h" @@ -61,59 +59,56 @@ using namespace JSC; namespace WebCore { -JSValue toJS(ExecState* exec, JSDOMGlobalObject* globalObject, SVGPathSeg* object) +JSValue toJSNewlyCreated(ExecState*, JSDOMGlobalObject* globalObject, Ref<SVGPathSeg>&& object) { - if (!object) - return jsNull(); - - if (JSObject* wrapper = getCachedWrapper(currentWorld(exec), object)) - return wrapper; - switch (object->pathSegType()) { case SVGPathSeg::PATHSEG_CLOSEPATH: - return CREATE_DOM_WRAPPER(exec, globalObject, SVGPathSegClosePath, object); + return createWrapper<SVGPathSegClosePath>(globalObject, WTFMove(object)); case SVGPathSeg::PATHSEG_MOVETO_ABS: - return CREATE_DOM_WRAPPER(exec, globalObject, SVGPathSegMovetoAbs, object); + return createWrapper<SVGPathSegMovetoAbs>(globalObject, WTFMove(object)); case SVGPathSeg::PATHSEG_MOVETO_REL: - return CREATE_DOM_WRAPPER(exec, globalObject, SVGPathSegMovetoRel, object); + return createWrapper<SVGPathSegMovetoRel>(globalObject, WTFMove(object)); case SVGPathSeg::PATHSEG_LINETO_ABS: - return CREATE_DOM_WRAPPER(exec, globalObject, SVGPathSegLinetoAbs, object); + return createWrapper<SVGPathSegLinetoAbs>(globalObject, WTFMove(object)); case SVGPathSeg::PATHSEG_LINETO_REL: - return CREATE_DOM_WRAPPER(exec, globalObject, SVGPathSegLinetoRel, object); + return createWrapper<SVGPathSegLinetoRel>(globalObject, WTFMove(object)); case SVGPathSeg::PATHSEG_CURVETO_CUBIC_ABS: - return CREATE_DOM_WRAPPER(exec, globalObject, SVGPathSegCurvetoCubicAbs, object); + return createWrapper<SVGPathSegCurvetoCubicAbs>(globalObject, WTFMove(object)); case SVGPathSeg::PATHSEG_CURVETO_CUBIC_REL: - return CREATE_DOM_WRAPPER(exec, globalObject, SVGPathSegCurvetoCubicRel, object); + return createWrapper<SVGPathSegCurvetoCubicRel>(globalObject, WTFMove(object)); case SVGPathSeg::PATHSEG_CURVETO_QUADRATIC_ABS: - return CREATE_DOM_WRAPPER(exec, globalObject, SVGPathSegCurvetoQuadraticAbs, object); + return createWrapper<SVGPathSegCurvetoQuadraticAbs>(globalObject, WTFMove(object)); case SVGPathSeg::PATHSEG_CURVETO_QUADRATIC_REL: - return CREATE_DOM_WRAPPER(exec, globalObject, SVGPathSegCurvetoQuadraticRel, object); + return createWrapper<SVGPathSegCurvetoQuadraticRel>(globalObject, WTFMove(object)); case SVGPathSeg::PATHSEG_ARC_ABS: - return CREATE_DOM_WRAPPER(exec, globalObject, SVGPathSegArcAbs, object); + return createWrapper<SVGPathSegArcAbs>(globalObject, WTFMove(object)); case SVGPathSeg::PATHSEG_ARC_REL: - return CREATE_DOM_WRAPPER(exec, globalObject, SVGPathSegArcRel, object); + return createWrapper<SVGPathSegArcRel>(globalObject, WTFMove(object)); case SVGPathSeg::PATHSEG_LINETO_HORIZONTAL_ABS: - return CREATE_DOM_WRAPPER(exec, globalObject, SVGPathSegLinetoHorizontalAbs, object); + return createWrapper<SVGPathSegLinetoHorizontalAbs>(globalObject, WTFMove(object)); case SVGPathSeg::PATHSEG_LINETO_HORIZONTAL_REL: - return CREATE_DOM_WRAPPER(exec, globalObject, SVGPathSegLinetoHorizontalRel, object); + return createWrapper<SVGPathSegLinetoHorizontalRel>(globalObject, WTFMove(object)); case SVGPathSeg::PATHSEG_LINETO_VERTICAL_ABS: - return CREATE_DOM_WRAPPER(exec, globalObject, SVGPathSegLinetoVerticalAbs, object); + return createWrapper<SVGPathSegLinetoVerticalAbs>(globalObject, WTFMove(object)); case SVGPathSeg::PATHSEG_LINETO_VERTICAL_REL: - return CREATE_DOM_WRAPPER(exec, globalObject, SVGPathSegLinetoVerticalRel, object); + return createWrapper<SVGPathSegLinetoVerticalRel>(globalObject, WTFMove(object)); case SVGPathSeg::PATHSEG_CURVETO_CUBIC_SMOOTH_ABS: - return CREATE_DOM_WRAPPER(exec, globalObject, SVGPathSegCurvetoCubicSmoothAbs, object); + return createWrapper<SVGPathSegCurvetoCubicSmoothAbs>(globalObject, WTFMove(object)); case SVGPathSeg::PATHSEG_CURVETO_CUBIC_SMOOTH_REL: - return CREATE_DOM_WRAPPER(exec, globalObject, SVGPathSegCurvetoCubicSmoothRel, object); + return createWrapper<SVGPathSegCurvetoCubicSmoothRel>(globalObject, WTFMove(object)); case SVGPathSeg::PATHSEG_CURVETO_QUADRATIC_SMOOTH_ABS: - return CREATE_DOM_WRAPPER(exec, globalObject, SVGPathSegCurvetoQuadraticSmoothAbs, object); + return createWrapper<SVGPathSegCurvetoQuadraticSmoothAbs>(globalObject, WTFMove(object)); case SVGPathSeg::PATHSEG_CURVETO_QUADRATIC_SMOOTH_REL: - return CREATE_DOM_WRAPPER(exec, globalObject, SVGPathSegCurvetoQuadraticSmoothRel, object); + return createWrapper<SVGPathSegCurvetoQuadraticSmoothRel>(globalObject, WTFMove(object)); case SVGPathSeg::PATHSEG_UNKNOWN: default: - return CREATE_DOM_WRAPPER(exec, globalObject, SVGPathSeg, object); + return createWrapper<SVGPathSeg>(globalObject, WTFMove(object)); } } +JSValue toJS(ExecState* state, JSDOMGlobalObject* globalObject, SVGPathSeg& object) +{ + return wrap(state, globalObject, object); } -#endif // ENABLE(SVG) +} diff --git a/Source/WebCore/bindings/js/JSSharedWorkerCustom.cpp b/Source/WebCore/bindings/js/JSSharedWorkerCustom.cpp deleted file mode 100644 index 2c2786417..000000000 --- a/Source/WebCore/bindings/js/JSSharedWorkerCustom.cpp +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Copyright (C) 2009 Google Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" - -#if ENABLE(SHARED_WORKERS) - -#include "JSSharedWorker.h" - -#include "Document.h" -#include "JSDOMGlobalObject.h" -#include "JSDOMWindowCustom.h" -#include "SharedWorker.h" -#include <runtime/Error.h> - -using namespace JSC; - -namespace WebCore { - -void JSSharedWorker::visitChildren(JSCell* cell, SlotVisitor& visitor) -{ - JSSharedWorker* thisObject = jsCast<JSSharedWorker*>(cell); - ASSERT_GC_OBJECT_INHERITS(thisObject, info()); - COMPILE_ASSERT(StructureFlags & OverridesVisitChildren, OverridesVisitChildrenWithoutSettingFlag); - ASSERT(thisObject->structure()->typeInfo().overridesVisitChildren()); - Base::visitChildren(thisObject, visitor); - - if (MessagePort* port = thisObject->impl().port()) - visitor.addOpaqueRoot(port); -} - -EncodedJSValue JSC_HOST_CALL JSSharedWorkerConstructor::constructJSSharedWorker(ExecState* exec) -{ - JSSharedWorkerConstructor* jsConstructor = jsCast<JSSharedWorkerConstructor*>(exec->callee()); - - if (exec->argumentCount() < 1) - return throwVMError(exec, createNotEnoughArgumentsError(exec)); - - String scriptURL = exec->uncheckedArgument(0).toString(exec)->value(exec); - String name; - if (exec->argumentCount() > 1) - name = exec->uncheckedArgument(1).toString(exec)->value(exec); - - if (exec->hadException()) - return JSValue::encode(JSValue()); - - // FIXME: We need to use both the dynamic scope and the lexical scope (dynamic scope for resolving the worker URL) - DOMWindow& window = asJSDOMWindow(exec->lexicalGlobalObject())->impl(); - ExceptionCode ec = 0; - ASSERT(window.document()); - RefPtr<SharedWorker> worker = SharedWorker::create(*window.document(), scriptURL, name, ec); - if (ec) { - setDOMException(exec, ec); - return JSValue::encode(JSValue()); - } - - return JSValue::encode(asObject(toJS(exec, jsConstructor->globalObject(), worker.release()))); -} - -} // namespace WebCore - -#endif // ENABLE(SHARED_WORKERS) diff --git a/Source/WebCore/bindings/js/JSStorageCustom.cpp b/Source/WebCore/bindings/js/JSStorageCustom.cpp index f2e22a3b6..044044361 100644 --- a/Source/WebCore/bindings/js/JSStorageCustom.cpp +++ b/Source/WebCore/bindings/js/JSStorageCustom.cpp @@ -26,7 +26,9 @@ #include "config.h" #include "JSStorage.h" -#include "Storage.h" +#include "JSDOMConvertStrings.h" +#include "JSDOMExceptionHandling.h" +#include <runtime/JSCInlines.h> #include <runtime/PropertyNameArray.h> #include <wtf/text/WTFString.h> @@ -34,45 +36,25 @@ using namespace JSC; namespace WebCore { -bool JSStorage::canGetItemsForName(ExecState* exec, Storage* impl, PropertyName propertyName) +bool JSStorage::deleteProperty(JSCell* cell, ExecState* state, PropertyName propertyName) { - ExceptionCode ec = 0; - bool result = impl->contains(propertyNameToString(propertyName), ec); - setDOMException(exec, ec); - return result; -} - -EncodedJSValue JSStorage::nameGetter(ExecState* exec, EncodedJSValue slotBase, EncodedJSValue, PropertyName propertyName) -{ - JSStorage* thisObj = jsCast<JSStorage*>(JSValue::decode(slotBase)); - - JSValue prototype = asObject(JSValue::decode(slotBase))->prototype(); - if (prototype.isObject() && asObject(prototype)->hasProperty(exec, propertyName)) - return JSValue::encode(asObject(prototype)->get(exec, propertyName)); - - ExceptionCode ec = 0; - JSValue result = jsStringOrNull(exec, thisObj->impl().getItem(propertyNameToString(propertyName), ec)); - setDOMException(exec, ec); - return JSValue::encode(result); -} + auto& thisObject = *jsCast<JSStorage*>(cell); -bool JSStorage::deleteProperty(JSCell* cell, ExecState* exec, PropertyName propertyName) -{ - JSStorage* thisObject = jsCast<JSStorage*>(cell); // Only perform the custom delete if the object doesn't have a native property by this name. // Since hasProperty() would end up calling canGetItemsForName() and be fooled, we need to check // the native property slots manually. - PropertySlot slot(thisObject); - if (getStaticValueSlot<JSStorage, Base>(exec, *s_info.propHashTable(exec), thisObject, propertyName, slot)) - return false; - - JSValue prototype = thisObject->prototype(); - if (prototype.isObject() && asObject(prototype)->hasProperty(exec, propertyName)) - return false; + PropertySlot slot(&thisObject, PropertySlot::InternalMethodType::GetOwnProperty); + + JSValue prototype = thisObject.getPrototypeDirect(); + if (prototype.isObject() && asObject(prototype)->getPropertySlot(state, propertyName, slot)) + return Base::deleteProperty(&thisObject, state, propertyName); - ExceptionCode ec = 0; - thisObject->m_impl->removeItem(propertyNameToString(propertyName), ec); - setDOMException(exec, ec); + if (propertyName.isSymbol()) + return Base::deleteProperty(&thisObject, state, propertyName); + + VM& vm = state->vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + propagateException(*state, scope, thisObject.wrapped().removeItem(propertyNameToString(propertyName))); return true; } @@ -81,45 +63,57 @@ bool JSStorage::deletePropertyByIndex(JSCell* cell, ExecState* exec, unsigned pr return deleteProperty(cell, exec, Identifier::from(exec, propertyName)); } -void JSStorage::getOwnPropertyNames(JSObject* object, ExecState* exec, PropertyNameArray& propertyNames, EnumerationMode mode) +void JSStorage::getOwnPropertyNames(JSObject* object, ExecState* state, PropertyNameArray& propertyNames, EnumerationMode mode) { - JSStorage* thisObject = jsCast<JSStorage*>(object); - ExceptionCode ec = 0; - unsigned length = thisObject->m_impl->length(ec); - setDOMException(exec, ec); - if (exec->hadException()) + VM& vm = state->vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + + auto& thisObject = *jsCast<JSStorage*>(object); + auto lengthResult = thisObject.wrapped().length(); + if (lengthResult.hasException()) { + propagateException(*state, scope, lengthResult.releaseException()); return; + } + unsigned length = lengthResult.releaseReturnValue(); for (unsigned i = 0; i < length; ++i) { - propertyNames.add(Identifier(exec, thisObject->m_impl->key(i, ec))); - setDOMException(exec, ec); - if (exec->hadException()) + auto keyResult = thisObject.wrapped().key(i); + if (keyResult.hasException()) { + propagateException(*state, scope, lengthResult.releaseException()); return; + } + propertyNames.add(Identifier::fromString(state, keyResult.releaseReturnValue())); } - Base::getOwnPropertyNames(thisObject, exec, propertyNames, mode); + Base::getOwnPropertyNames(&thisObject, state, propertyNames, mode); } -bool JSStorage::putDelegate(ExecState* exec, PropertyName propertyName, JSValue value, PutPropertySlot&) +bool JSStorage::putDelegate(ExecState* state, PropertyName propertyName, JSValue value, PutPropertySlot&, bool& putResult) { + VM& vm = state->vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + // Only perform the custom put if the object doesn't have a native property by this name. // Since hasProperty() would end up calling canGetItemsForName() and be fooled, we need to check // the native property slots manually. - PropertySlot slot(this); - if (getStaticValueSlot<JSStorage, Base>(exec, *s_info.propHashTable(exec), this, propertyName, slot)) + PropertySlot slot { this, PropertySlot::InternalMethodType::GetOwnProperty }; + + JSValue prototype = this->getPrototypeDirect(); + if (prototype.isObject() && asObject(prototype)->getPropertySlot(state, propertyName, slot)) return false; - - JSValue prototype = this->prototype(); - if (prototype.isObject() && asObject(prototype)->hasProperty(exec, propertyName)) + + if (propertyName.isSymbol()) return false; - - String stringValue = value.toString(exec)->value(exec); - if (exec->hadException()) + + String stringValue = value.toWTFString(state); + RETURN_IF_EXCEPTION(scope, true); + + auto setItemResult = wrapped().setItem(propertyNameToString(propertyName), stringValue); + if (setItemResult.hasException()) { + propagateException(*state, scope, setItemResult.releaseException()); return true; - - ExceptionCode ec = 0; - impl().setItem(propertyNameToString(propertyName), stringValue, ec); - setDOMException(exec, ec); + } + putResult = true; return true; } diff --git a/Source/WebCore/bindings/js/JSStyleSheetCustom.cpp b/Source/WebCore/bindings/js/JSStyleSheetCustom.cpp index f7063061f..5c3b82f13 100644 --- a/Source/WebCore/bindings/js/JSStyleSheetCustom.cpp +++ b/Source/WebCore/bindings/js/JSStyleSheetCustom.cpp @@ -10,10 +10,10 @@ * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * - * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR @@ -26,40 +26,25 @@ #include "config.h" #include "JSStyleSheet.h" -#include "CSSStyleSheet.h" -#include "Node.h" #include "JSCSSStyleSheet.h" -#include "JSNode.h" - -using namespace JSC; namespace WebCore { -void JSStyleSheet::visitChildren(JSCell* cell, SlotVisitor& visitor) +void JSStyleSheet::visitAdditionalChildren(JSC::SlotVisitor& visitor) { - JSStyleSheet* thisObject = jsCast<JSStyleSheet*>(cell); - ASSERT_GC_OBJECT_INHERITS(thisObject, info()); - COMPILE_ASSERT(StructureFlags & OverridesVisitChildren, OverridesVisitChildrenWithoutSettingFlag); - ASSERT(thisObject->structure()->typeInfo().overridesVisitChildren()); - Base::visitChildren(thisObject, visitor); - visitor.addOpaqueRoot(root(&thisObject->impl())); + visitor.addOpaqueRoot(root(&wrapped())); } -JSValue toJS(ExecState* exec, JSDOMGlobalObject* globalObject, StyleSheet* styleSheet) +JSC::JSValue toJSNewlyCreated(JSC::ExecState*, JSDOMGlobalObject* globalObject, Ref<StyleSheet>&& styleSheet) { - if (!styleSheet) - return jsNull(); - - JSObject* wrapper = getCachedWrapper(currentWorld(exec), styleSheet); - if (wrapper) - return wrapper; - if (styleSheet->isCSSStyleSheet()) - wrapper = CREATE_DOM_WRAPPER(exec, globalObject, CSSStyleSheet, styleSheet); - else - wrapper = CREATE_DOM_WRAPPER(exec, globalObject, StyleSheet, styleSheet); + return createWrapper<CSSStyleSheet>(globalObject, WTFMove(styleSheet)); + return createWrapper<StyleSheet>(globalObject, WTFMove(styleSheet)); +} - return wrapper; +JSC::JSValue toJS(JSC::ExecState* state, JSDOMGlobalObject* globalObject, StyleSheet& stylesheet) +{ + return wrap(state, globalObject, stylesheet); } } // namespace WebCore diff --git a/Source/WebCore/bindings/js/JSStyleSheetCustom.h b/Source/WebCore/bindings/js/JSStyleSheetCustom.h index 8c9c18756..95777fc53 100644 --- a/Source/WebCore/bindings/js/JSStyleSheetCustom.h +++ b/Source/WebCore/bindings/js/JSStyleSheetCustom.h @@ -10,10 +10,10 @@ * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * - * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR @@ -23,8 +23,7 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef JSStyleSheetCustom_h -#define JSStyleSheetCustom_h +#pragma once #include "CSSImportRule.h" #include "CSSStyleSheet.h" @@ -43,5 +42,3 @@ inline void* root(StyleSheet* styleSheet) } } // namespace WebCore - -#endif // JSStyleSheetCustom_h diff --git a/Source/WebCore/bindings/js/JSStyleSheetListCustom.cpp b/Source/WebCore/bindings/js/JSStyleSheetListCustom.cpp deleted file mode 100644 index a5b4eef85..000000000 --- a/Source/WebCore/bindings/js/JSStyleSheetListCustom.cpp +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (C) 2007, 2009 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" -#include "JSStyleSheetList.h" - -#include "HTMLStyleElement.h" -#include "JSStyleSheet.h" -#include "StyleSheet.h" -#include "StyleSheetList.h" - -using namespace JSC; - -namespace WebCore { - -bool JSStyleSheetList::canGetItemsForName(ExecState*, StyleSheetList* styleSheetList, PropertyName propertyName) -{ - return styleSheetList->getNamedItem(propertyNameToString(propertyName)); -} - -EncodedJSValue JSStyleSheetList::nameGetter(ExecState* exec, EncodedJSValue slotBase, EncodedJSValue, PropertyName propertyName) -{ - JSStyleSheetList* thisObj = jsCast<JSStyleSheetList*>(JSValue::decode(slotBase)); - HTMLStyleElement* element = thisObj->impl().getNamedItem(propertyNameToString(propertyName)); - ASSERT(element); - return JSValue::encode(toJS(exec, thisObj->globalObject(), element->sheet())); -} - -} // namespace WebCore diff --git a/Source/WebCore/bindings/js/JSSubtleCryptoCustom.cpp b/Source/WebCore/bindings/js/JSSubtleCryptoCustom.cpp new file mode 100644 index 000000000..86b95d71a --- /dev/null +++ b/Source/WebCore/bindings/js/JSSubtleCryptoCustom.cpp @@ -0,0 +1,1113 @@ +/* + * Copyright (C) 2016 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "JSSubtleCrypto.h" + +#if ENABLE(SUBTLE_CRYPTO) + +#include "CryptoAlgorithm.h" +#include "CryptoAlgorithmRegistry.h" +#include "JSAesCbcParams.h" +#include "JSAesKeyGenParams.h" +#include "JSCryptoAlgorithmParameters.h" +#include "JSCryptoKey.h" +#include "JSCryptoKeyPair.h" +#include "JSDOMPromise.h" +#include "JSDOMWrapper.h" +#include "JSHmacKeyParams.h" +#include "JSJsonWebKey.h" +#include "JSRsaHashedImportParams.h" +#include "JSRsaHashedKeyGenParams.h" +#include "JSRsaKeyGenParams.h" +#include "JSRsaOaepParams.h" +#include "ScriptState.h" +#include <runtime/Error.h> +#include <runtime/JSArray.h> +#include <runtime/JSONObject.h> + +using namespace JSC; + +namespace WebCore { + +enum class Operations { + Encrypt, + Decrypt, + Sign, + Verify, + Digest, + DeriveKey, + DeriveBits, + GenerateKey, + ImportKey, + WrapKey, + UnwrapKey +}; + +static std::unique_ptr<CryptoAlgorithmParameters> normalizeCryptoAlgorithmParameters(ExecState&, JSValue, Operations); + +static CryptoAlgorithmIdentifier toHashIdentifier(ExecState& state, JSValue value) +{ + VM& vm = state.vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + + auto digestParams = normalizeCryptoAlgorithmParameters(state, value, Operations::Digest); + RETURN_IF_EXCEPTION(scope, { }); + return digestParams->identifier; +} + +static std::unique_ptr<CryptoAlgorithmParameters> normalizeCryptoAlgorithmParameters(ExecState& state, JSValue value, Operations operation) +{ + VM& vm = state.vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + + if (value.isString()) { + JSObject* newParams = constructEmptyObject(&state); + newParams->putDirect(vm, Identifier::fromString(&vm, "name"), value); + return normalizeCryptoAlgorithmParameters(state, newParams, operation); + } + + if (value.isObject()) { + auto params = convertDictionary<CryptoAlgorithmParameters>(state, value); + RETURN_IF_EXCEPTION(scope, nullptr); + + auto identifier = CryptoAlgorithmRegistry::singleton().identifier(params.name); + if (UNLIKELY(!identifier)) { + throwNotSupportedError(state, scope); + return nullptr; + } + + std::unique_ptr<CryptoAlgorithmParameters> result; + switch (operation) { + case Operations::Encrypt: + case Operations::Decrypt: + switch (*identifier) { + case CryptoAlgorithmIdentifier::RSAES_PKCS1_v1_5: + result = std::make_unique<CryptoAlgorithmParameters>(params); + break; + case CryptoAlgorithmIdentifier::RSA_OAEP: { + auto params = convertDictionary<CryptoAlgorithmRsaOaepParams>(state, value); + RETURN_IF_EXCEPTION(scope, nullptr); + result = std::make_unique<CryptoAlgorithmRsaOaepParams>(params); + break; + } + case CryptoAlgorithmIdentifier::AES_CBC: { + auto params = convertDictionary<CryptoAlgorithmAesCbcParams>(state, value); + RETURN_IF_EXCEPTION(scope, nullptr); + result = std::make_unique<CryptoAlgorithmAesCbcParams>(params); + break; + } + default: + throwNotSupportedError(state, scope); + return nullptr; + } + break; + case Operations::Sign: + case Operations::Verify: + switch (*identifier) { + case CryptoAlgorithmIdentifier::RSASSA_PKCS1_v1_5: + case CryptoAlgorithmIdentifier::HMAC: + result = std::make_unique<CryptoAlgorithmParameters>(params); + break; + default: + throwNotSupportedError(state, scope); + return nullptr; + } + break; + case Operations::Digest: + switch (*identifier) { + case CryptoAlgorithmIdentifier::SHA_1: + case CryptoAlgorithmIdentifier::SHA_224: + case CryptoAlgorithmIdentifier::SHA_256: + case CryptoAlgorithmIdentifier::SHA_384: + case CryptoAlgorithmIdentifier::SHA_512: + result = std::make_unique<CryptoAlgorithmParameters>(params); + break; + default: + throwNotSupportedError(state, scope); + return nullptr; + } + break; + case Operations::DeriveKey: + case Operations::DeriveBits: + throwNotSupportedError(state, scope); + return nullptr; + case Operations::GenerateKey: + switch (*identifier) { + case CryptoAlgorithmIdentifier::RSAES_PKCS1_v1_5: { + auto params = convertDictionary<CryptoAlgorithmRsaKeyGenParams>(state, value); + RETURN_IF_EXCEPTION(scope, nullptr); + result = std::make_unique<CryptoAlgorithmRsaKeyGenParams>(params); + break; + } + case CryptoAlgorithmIdentifier::RSASSA_PKCS1_v1_5: + case CryptoAlgorithmIdentifier::RSA_PSS: + case CryptoAlgorithmIdentifier::RSA_OAEP: { + auto params = convertDictionary<CryptoAlgorithmRsaHashedKeyGenParams>(state, value); + RETURN_IF_EXCEPTION(scope, nullptr); + params.hashIdentifier = toHashIdentifier(state, params.hash); + RETURN_IF_EXCEPTION(scope, nullptr); + result = std::make_unique<CryptoAlgorithmRsaHashedKeyGenParams>(params); + break; + } + case CryptoAlgorithmIdentifier::AES_CTR: + case CryptoAlgorithmIdentifier::AES_CBC: + case CryptoAlgorithmIdentifier::AES_CMAC: + case CryptoAlgorithmIdentifier::AES_GCM: + case CryptoAlgorithmIdentifier::AES_CFB: + case CryptoAlgorithmIdentifier::AES_KW: { + auto params = convertDictionary<CryptoAlgorithmAesKeyGenParams>(state, value); + RETURN_IF_EXCEPTION(scope, nullptr); + result = std::make_unique<CryptoAlgorithmAesKeyGenParams>(params); + break; + } + case CryptoAlgorithmIdentifier::HMAC: { + auto params = convertDictionary<CryptoAlgorithmHmacKeyParams>(state, value); + RETURN_IF_EXCEPTION(scope, nullptr); + params.hashIdentifier = toHashIdentifier(state, params.hash); + RETURN_IF_EXCEPTION(scope, nullptr); + result = std::make_unique<CryptoAlgorithmHmacKeyParams>(params); + break; + } + default: + throwNotSupportedError(state, scope); + return nullptr; + } + break; + case Operations::ImportKey: + switch (*identifier) { + case CryptoAlgorithmIdentifier::RSAES_PKCS1_v1_5: + result = std::make_unique<CryptoAlgorithmParameters>(params); + break; + case CryptoAlgorithmIdentifier::RSASSA_PKCS1_v1_5: + case CryptoAlgorithmIdentifier::RSA_PSS: + case CryptoAlgorithmIdentifier::RSA_OAEP: { + auto params = convertDictionary<CryptoAlgorithmRsaHashedImportParams>(state, value); + RETURN_IF_EXCEPTION(scope, nullptr); + params.hashIdentifier = toHashIdentifier(state, params.hash); + RETURN_IF_EXCEPTION(scope, nullptr); + result = std::make_unique<CryptoAlgorithmRsaHashedImportParams>(params); + break; + } + case CryptoAlgorithmIdentifier::AES_CTR: + case CryptoAlgorithmIdentifier::AES_CBC: + case CryptoAlgorithmIdentifier::AES_CMAC: + case CryptoAlgorithmIdentifier::AES_GCM: + case CryptoAlgorithmIdentifier::AES_CFB: + case CryptoAlgorithmIdentifier::AES_KW: + result = std::make_unique<CryptoAlgorithmParameters>(params); + break; + case CryptoAlgorithmIdentifier::HMAC: { + auto params = convertDictionary<CryptoAlgorithmHmacKeyParams>(state, value); + RETURN_IF_EXCEPTION(scope, nullptr); + params.hashIdentifier = toHashIdentifier(state, params.hash); + RETURN_IF_EXCEPTION(scope, nullptr); + result = std::make_unique<CryptoAlgorithmHmacKeyParams>(params); + break; + } + default: + throwNotSupportedError(state, scope); + return nullptr; + } + break; + case Operations::WrapKey: + case Operations::UnwrapKey: + switch (*identifier) { + case CryptoAlgorithmIdentifier::AES_KW: + result = std::make_unique<CryptoAlgorithmParameters>(params); + break; + default: + throwNotSupportedError(state, scope); + return nullptr; + } + break; + default: + ASSERT_NOT_REACHED(); + return nullptr; + } + + result->identifier = *identifier; + return result; + } + + throwTypeError(&state, scope, ASCIILiteral("Invalid AlgorithmIdentifier")); + return nullptr; +} + +static CryptoKeyUsageBitmap toCryptoKeyUsageBitmap(CryptoKeyUsage usage) +{ + switch (usage) { + case CryptoKeyUsage::Encrypt: + return CryptoKeyUsageEncrypt; + case CryptoKeyUsage::Decrypt: + return CryptoKeyUsageDecrypt; + case CryptoKeyUsage::Sign: + return CryptoKeyUsageSign; + case CryptoKeyUsage::Verify: + return CryptoKeyUsageVerify; + case CryptoKeyUsage::DeriveKey: + return CryptoKeyUsageDeriveKey; + case CryptoKeyUsage::DeriveBits: + return CryptoKeyUsageDeriveBits; + case CryptoKeyUsage::WrapKey: + return CryptoKeyUsageWrapKey; + case CryptoKeyUsage::UnwrapKey: + return CryptoKeyUsageUnwrapKey; + } + + ASSERT_NOT_REACHED(); + return 0; +} + +static CryptoKeyUsageBitmap cryptoKeyUsageBitmapFromJSValue(ExecState& state, JSValue value) +{ + VM& vm = state.vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + + CryptoKeyUsageBitmap result = 0; + auto usages = convert<IDLSequence<IDLEnumeration<CryptoKeyUsage>>>(state, value); + RETURN_IF_EXCEPTION(scope, 0); + // Maybe we shouldn't silently bypass duplicated usages? + for (auto usage : usages) + result |= toCryptoKeyUsageBitmap(usage); + + return result; +} + +// Maybe we want more specific error messages? +static void rejectWithException(Ref<DeferredPromise>&& passedPromise, ExceptionCode ec) +{ + switch (ec) { + case NOT_SUPPORTED_ERR: + passedPromise->reject(ec, ASCIILiteral("The algorithm is not supported")); + return; + case SYNTAX_ERR: + passedPromise->reject(ec, ASCIILiteral("A required parameter was missing or out-of-range")); + return; + case INVALID_STATE_ERR: + passedPromise->reject(ec, ASCIILiteral("The requested operation is not valid for the current state of the provided key")); + return; + case INVALID_ACCESS_ERR: + passedPromise->reject(ec, ASCIILiteral("The requested operation is not valid for the provided key")); + return; + case UnknownError: + passedPromise->reject(ec, ASCIILiteral("The operation failed for an unknown transient reason (e.g. out of memory)")); + return; + case DataError: + passedPromise->reject(ec, ASCIILiteral("Data provided to an operation does not meet requirements")); + return; + case OperationError: + passedPromise->reject(ec, ASCIILiteral("The operation failed for an operation-specific reason")); + return; + } + ASSERT_NOT_REACHED(); +} + +static KeyData toKeyData(ExecState& state, SubtleCrypto::KeyFormat format, JSValue value) +{ + VM& vm = state.vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + + KeyData result; + switch (format) { + case SubtleCrypto::KeyFormat::Spki: + case SubtleCrypto::KeyFormat::Pkcs8: + case SubtleCrypto::KeyFormat::Raw: { + BufferSource bufferSource = convert<IDLBufferSource>(state, value); + RETURN_IF_EXCEPTION(scope, result); + Vector<uint8_t> vector; + vector.append(bufferSource.data(), bufferSource.length()); + result = WTFMove(vector); + return result; + } + case SubtleCrypto::KeyFormat::Jwk: { + result = convertDictionary<JsonWebKey>(state, value); + RETURN_IF_EXCEPTION(scope, result); + CryptoKeyUsageBitmap usages = 0; + if (WTF::get<JsonWebKey>(result).key_ops) { + // Maybe we shouldn't silently bypass duplicated usages? + for (auto usage : WTF::get<JsonWebKey>(result).key_ops.value()) + usages |= toCryptoKeyUsageBitmap(usage); + } + WTF::get<JsonWebKey>(result).usages = usages; + return result; + } + } + ASSERT_NOT_REACHED(); + return result; +} + +static RefPtr<CryptoKey> toCryptoKey(ExecState& state, JSValue value) +{ + VM& vm = state.vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + + RefPtr<CryptoKey> result = JSCryptoKey::toWrapped(vm, value); + if (!result) { + throwTypeError(&state, scope, ASCIILiteral("Invalid CryptoKey")); + return nullptr; + } + return result; +} + +static Vector<uint8_t> toVector(ExecState& state, JSValue value) +{ + VM& vm = state.vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + + BufferSource data = convert<IDLBufferSource>(state, value); + RETURN_IF_EXCEPTION(scope, { }); + Vector<uint8_t> dataVector; + dataVector.append(data.data(), data.length()); + + return dataVector; +} + +static void supportExportKeyThrow(ExecState& state, ThrowScope& scope, CryptoAlgorithmIdentifier identifier) +{ + switch (identifier) { + case CryptoAlgorithmIdentifier::RSAES_PKCS1_v1_5: + case CryptoAlgorithmIdentifier::RSASSA_PKCS1_v1_5: + case CryptoAlgorithmIdentifier::RSA_PSS: + case CryptoAlgorithmIdentifier::RSA_OAEP: + case CryptoAlgorithmIdentifier::AES_CTR: + case CryptoAlgorithmIdentifier::AES_CBC: + case CryptoAlgorithmIdentifier::AES_CMAC: + case CryptoAlgorithmIdentifier::AES_GCM: + case CryptoAlgorithmIdentifier::AES_CFB: + case CryptoAlgorithmIdentifier::AES_KW: + case CryptoAlgorithmIdentifier::HMAC: + return; + default: + throwNotSupportedError(state, scope); + } +} + +static void jsSubtleCryptoFunctionEncryptPromise(ExecState& state, Ref<DeferredPromise>&& promise) +{ + VM& vm = state.vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + + if (UNLIKELY(state.argumentCount() < 3)) { + promise->reject<IDLAny>(createNotEnoughArgumentsError(&state)); + return; + } + + auto params = normalizeCryptoAlgorithmParameters(state, state.uncheckedArgument(0), Operations::Encrypt); + RETURN_IF_EXCEPTION(scope, void()); + + auto key = toCryptoKey(state, state.uncheckedArgument(1)); + RETURN_IF_EXCEPTION(scope, void()); + + auto data = toVector(state, state.uncheckedArgument(2)); + RETURN_IF_EXCEPTION(scope, void()); + + if (params->identifier != key->algorithmIdentifier()) { + promise->reject(INVALID_ACCESS_ERR, ASCIILiteral("CryptoKey doesn't match AlgorithmIdentifier")); + return; + } + + if (!key->allows(CryptoKeyUsageEncrypt)) { + promise->reject(INVALID_ACCESS_ERR, ASCIILiteral("CryptoKey doesn't support encryption")); + return; + } + + auto algorithm = CryptoAlgorithmRegistry::singleton().create(key->algorithmIdentifier()); + if (UNLIKELY(!algorithm)) { + throwNotSupportedError(state, scope); + return; + } + + auto callback = [capturedPromise = promise.copyRef()](const Vector<uint8_t>& cipherText) mutable { + fulfillPromiseWithArrayBuffer(WTFMove(capturedPromise), cipherText.data(), cipherText.size()); + return; + }; + auto exceptionCallback = [capturedPromise = WTFMove(promise)](ExceptionCode ec) mutable { + rejectWithException(WTFMove(capturedPromise), ec); + }; + + auto subtle = jsDynamicDowncast<JSSubtleCrypto*>(vm, state.thisValue()); + ASSERT(subtle); + algorithm->encrypt(WTFMove(params), key.releaseNonNull(), WTFMove(data), WTFMove(callback), WTFMove(exceptionCallback), *scriptExecutionContextFromExecState(&state), subtle->wrapped().workQueue()); +} + +static void jsSubtleCryptoFunctionDecryptPromise(ExecState& state, Ref<DeferredPromise>&& promise) +{ + VM& vm = state.vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + + if (UNLIKELY(state.argumentCount() < 3)) { + promise->reject<IDLAny>(createNotEnoughArgumentsError(&state)); + return; + } + + auto params = normalizeCryptoAlgorithmParameters(state, state.uncheckedArgument(0), Operations::Decrypt); + RETURN_IF_EXCEPTION(scope, void()); + + auto key = toCryptoKey(state, state.uncheckedArgument(1)); + RETURN_IF_EXCEPTION(scope, void()); + + auto data = toVector(state, state.uncheckedArgument(2)); + RETURN_IF_EXCEPTION(scope, void()); + + if (params->identifier != key->algorithmIdentifier()) { + promise->reject(INVALID_ACCESS_ERR, ASCIILiteral("CryptoKey doesn't match AlgorithmIdentifier")); + return; + } + + if (!key->allows(CryptoKeyUsageDecrypt)) { + promise->reject(INVALID_ACCESS_ERR, ASCIILiteral("CryptoKey doesn't support decryption")); + return; + } + + auto algorithm = CryptoAlgorithmRegistry::singleton().create(key->algorithmIdentifier()); + if (UNLIKELY(!algorithm)) { + throwNotSupportedError(state, scope); + return; + } + + auto callback = [capturedPromise = promise.copyRef()](const Vector<uint8_t>& plainText) mutable { + fulfillPromiseWithArrayBuffer(WTFMove(capturedPromise), plainText.data(), plainText.size()); + return; + }; + auto exceptionCallback = [capturedPromise = WTFMove(promise)](ExceptionCode ec) mutable { + rejectWithException(WTFMove(capturedPromise), ec); + }; + + auto subtle = jsDynamicDowncast<JSSubtleCrypto*>(vm, state.thisValue()); + ASSERT(subtle); + algorithm->decrypt(WTFMove(params), key.releaseNonNull(), WTFMove(data), WTFMove(callback), WTFMove(exceptionCallback), *scriptExecutionContextFromExecState(&state), subtle->wrapped().workQueue()); +} + +static void jsSubtleCryptoFunctionSignPromise(ExecState& state, Ref<DeferredPromise>&& promise) +{ + VM& vm = state.vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + + if (UNLIKELY(state.argumentCount() < 3)) { + promise->reject<IDLAny>(createNotEnoughArgumentsError(&state)); + return; + } + + auto params = normalizeCryptoAlgorithmParameters(state, state.uncheckedArgument(0), Operations::Sign); + RETURN_IF_EXCEPTION(scope, void()); + + auto key = toCryptoKey(state, state.uncheckedArgument(1)); + RETURN_IF_EXCEPTION(scope, void()); + + auto data = toVector(state, state.uncheckedArgument(2)); + RETURN_IF_EXCEPTION(scope, void()); + + if (params->identifier != key->algorithmIdentifier()) { + promise->reject(INVALID_ACCESS_ERR, ASCIILiteral("CryptoKey doesn't match AlgorithmIdentifier")); + return; + } + + if (!key->allows(CryptoKeyUsageSign)) { + promise->reject(INVALID_ACCESS_ERR, ASCIILiteral("CryptoKey doesn't support signing")); + return; + } + + auto algorithm = CryptoAlgorithmRegistry::singleton().create(key->algorithmIdentifier()); + if (UNLIKELY(!algorithm)) { + throwNotSupportedError(state, scope); + return; + } + + auto callback = [capturedPromise = promise.copyRef()](const Vector<uint8_t>& signature) mutable { + fulfillPromiseWithArrayBuffer(WTFMove(capturedPromise), signature.data(), signature.size()); + return; + }; + auto exceptionCallback = [capturedPromise = WTFMove(promise)](ExceptionCode ec) mutable { + rejectWithException(WTFMove(capturedPromise), ec); + }; + + JSSubtleCrypto* subtle = jsDynamicDowncast<JSSubtleCrypto*>(vm, state.thisValue()); + ASSERT(subtle); + algorithm->sign(key.releaseNonNull(), WTFMove(data), WTFMove(callback), WTFMove(exceptionCallback), *scriptExecutionContextFromExecState(&state), subtle->wrapped().workQueue()); +} + +static void jsSubtleCryptoFunctionVerifyPromise(ExecState& state, Ref<DeferredPromise>&& promise) +{ + VM& vm = state.vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + + if (UNLIKELY(state.argumentCount() < 4)) { + promise->reject<IDLAny>(createNotEnoughArgumentsError(&state)); + return; + } + + auto params = normalizeCryptoAlgorithmParameters(state, state.uncheckedArgument(0), Operations::Verify); + RETURN_IF_EXCEPTION(scope, void()); + + auto key = toCryptoKey(state, state.uncheckedArgument(1)); + RETURN_IF_EXCEPTION(scope, void()); + + auto signature = toVector(state, state.uncheckedArgument(2)); + RETURN_IF_EXCEPTION(scope, void()); + + auto data = toVector(state, state.uncheckedArgument(3)); + RETURN_IF_EXCEPTION(scope, void()); + + if (params->identifier != key->algorithmIdentifier()) { + promise->reject(INVALID_ACCESS_ERR, ASCIILiteral("CryptoKey doesn't match AlgorithmIdentifier")); + return; + } + + if (!key->allows(CryptoKeyUsageVerify)) { + promise->reject(INVALID_ACCESS_ERR, ASCIILiteral("CryptoKey doesn't support verification")); + return; + } + + auto algorithm = CryptoAlgorithmRegistry::singleton().create(key->algorithmIdentifier()); + if (UNLIKELY(!algorithm)) { + throwNotSupportedError(state, scope); + return; + } + + auto callback = [capturedPromise = promise.copyRef()](bool result) mutable { + capturedPromise->resolve<IDLBoolean>(result); + return; + }; + auto exceptionCallback = [capturedPromise = WTFMove(promise)](ExceptionCode ec) mutable { + rejectWithException(WTFMove(capturedPromise), ec); + }; + + auto subtle = jsDynamicDowncast<JSSubtleCrypto*>(vm, state.thisValue()); + ASSERT(subtle); + algorithm->verify(key.releaseNonNull(), WTFMove(signature), WTFMove(data), WTFMove(callback), WTFMove(exceptionCallback), *scriptExecutionContextFromExecState(&state), subtle->wrapped().workQueue()); +} + +static void jsSubtleCryptoFunctionDigestPromise(ExecState& state, Ref<DeferredPromise>&& promise) +{ + VM& vm = state.vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + + if (UNLIKELY(state.argumentCount() < 2)) { + promise->reject<IDLAny>(createNotEnoughArgumentsError(&state)); + return; + } + + auto params = normalizeCryptoAlgorithmParameters(state, state.uncheckedArgument(0), Operations::Digest); + RETURN_IF_EXCEPTION(scope, void()); + + auto data = toVector(state, state.uncheckedArgument(1)); + RETURN_IF_EXCEPTION(scope, void()); + + auto algorithm = CryptoAlgorithmRegistry::singleton().create(params->identifier); + if (UNLIKELY(!algorithm)) { + throwNotSupportedError(state, scope); + return; + } + + auto callback = [capturedPromise = promise.copyRef()](const Vector<uint8_t>& digest) mutable { + fulfillPromiseWithArrayBuffer(WTFMove(capturedPromise), digest.data(), digest.size()); + return; + }; + auto exceptionCallback = [capturedPromise = WTFMove(promise)](ExceptionCode ec) mutable { + rejectWithException(WTFMove(capturedPromise), ec); + }; + + auto subtle = jsDynamicDowncast<JSSubtleCrypto*>(vm, state.thisValue()); + ASSERT(subtle); + algorithm->digest(WTFMove(data), WTFMove(callback), WTFMove(exceptionCallback), *scriptExecutionContextFromExecState(&state), subtle->wrapped().workQueue()); +} + +static void jsSubtleCryptoFunctionDeriveKeyPromise(ExecState& state, Ref<DeferredPromise>&& promise) +{ + VM& vm = state.vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + + if (UNLIKELY(state.argumentCount() < 5)) { + promise->reject<IDLAny>(createNotEnoughArgumentsError(&state)); + return; + } + + auto params = normalizeCryptoAlgorithmParameters(state, state.uncheckedArgument(0), Operations::DeriveKey); + RETURN_IF_EXCEPTION(scope, void()); + + // We should always return a NOT_SUPPORTED_ERR since we currently don't support any algorithms that has deriveKey operation. + ASSERT_NOT_REACHED(); +} + +static void jsSubtleCryptoFunctionDeriveBitsPromise(ExecState& state, Ref<DeferredPromise>&& promise) +{ + VM& vm = state.vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + + if (UNLIKELY(state.argumentCount() < 3)) { + promise->reject<IDLAny>(createNotEnoughArgumentsError(&state)); + return; + } + + auto params = normalizeCryptoAlgorithmParameters(state, state.uncheckedArgument(0), Operations::DeriveBits); + RETURN_IF_EXCEPTION(scope, void()); + + // We should always return a NOT_SUPPORTED_ERR since we currently don't support any algorithms that has deriveBits operation. + ASSERT_NOT_REACHED(); +} + +static void jsSubtleCryptoFunctionGenerateKeyPromise(ExecState& state, Ref<DeferredPromise>&& promise) +{ + VM& vm = state.vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + + if (UNLIKELY(state.argumentCount() < 3)) { + promise->reject<IDLAny>(createNotEnoughArgumentsError(&state)); + return; + } + + auto params = normalizeCryptoAlgorithmParameters(state, state.uncheckedArgument(0), Operations::GenerateKey); + RETURN_IF_EXCEPTION(scope, void()); + + auto extractable = state.uncheckedArgument(1).toBoolean(&state); + RETURN_IF_EXCEPTION(scope, void()); + + auto keyUsages = cryptoKeyUsageBitmapFromJSValue(state, state.uncheckedArgument(2)); + RETURN_IF_EXCEPTION(scope, void()); + + auto algorithm = CryptoAlgorithmRegistry::singleton().create(params->identifier); + if (UNLIKELY(!algorithm)) { + throwNotSupportedError(state, scope); + return; + } + + auto callback = [capturedPromise = promise.copyRef()](KeyOrKeyPair&& keyOrKeyPair) mutable { + WTF::switchOn(keyOrKeyPair, + [&capturedPromise] (RefPtr<CryptoKey>& key) { + if ((key->type() == CryptoKeyType::Private || key->type() == CryptoKeyType::Secret) && !key->usagesBitmap()) { + rejectWithException(WTFMove(capturedPromise), SYNTAX_ERR); + return; + } + capturedPromise->resolve<IDLInterface<CryptoKey>>(*key); + }, + [&capturedPromise] (CryptoKeyPair& keyPair) { + if (!keyPair.privateKey->usagesBitmap()) { + rejectWithException(WTFMove(capturedPromise), SYNTAX_ERR); + return; + } + capturedPromise->resolve<IDLDictionary<CryptoKeyPair>>(keyPair); + } + ); + }; + auto exceptionCallback = [capturedPromise = WTFMove(promise)](ExceptionCode ec) mutable { + rejectWithException(WTFMove(capturedPromise), ec); + }; + + // The 11 December 2014 version of the specification suggests we should perform the following task asynchronously + // regardless what kind of keys it produces: https://www.w3.org/TR/WebCryptoAPI/#SubtleCrypto-method-generateKey + // That's simply not efficient for AES and HMAC keys. Therefore, we perform it as an async task conditionally. + algorithm->generateKey(*params, extractable, keyUsages, WTFMove(callback), WTFMove(exceptionCallback), *scriptExecutionContextFromExecState(&state)); +} + +static void jsSubtleCryptoFunctionImportKeyPromise(ExecState& state, Ref<DeferredPromise>&& promise) +{ + VM& vm = state.vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + + if (UNLIKELY(state.argumentCount() < 5)) { + promise->reject<IDLAny>(createNotEnoughArgumentsError(&state)); + return; + } + + auto format = convertEnumeration<SubtleCrypto::KeyFormat>(state, state.uncheckedArgument(0)); + RETURN_IF_EXCEPTION(scope, void()); + + auto keyData = toKeyData(state, format, state.uncheckedArgument(1)); + RETURN_IF_EXCEPTION(scope, void()); + + auto params = normalizeCryptoAlgorithmParameters(state, state.uncheckedArgument(2), Operations::ImportKey); + RETURN_IF_EXCEPTION(scope, void()); + + auto extractable = state.uncheckedArgument(3).toBoolean(&state); + RETURN_IF_EXCEPTION(scope, void()); + + auto keyUsages = cryptoKeyUsageBitmapFromJSValue(state, state.uncheckedArgument(4)); + RETURN_IF_EXCEPTION(scope, void()); + + auto algorithm = CryptoAlgorithmRegistry::singleton().create(params->identifier); + if (UNLIKELY(!algorithm)) { + throwNotSupportedError(state, scope); + return; + } + + auto callback = [capturedPromise = promise.copyRef()](CryptoKey& key) mutable { + if ((key.type() == CryptoKeyType::Private || key.type() == CryptoKeyType::Secret) && !key.usagesBitmap()) { + rejectWithException(WTFMove(capturedPromise), SYNTAX_ERR); + return; + } + capturedPromise->resolve<IDLInterface<CryptoKey>>(key); + }; + auto exceptionCallback = [capturedPromise = WTFMove(promise)](ExceptionCode ec) mutable { + rejectWithException(WTFMove(capturedPromise), ec); + }; + + // The 11 December 2014 version of the specification suggests we should perform the following task asynchronously: + // https://www.w3.org/TR/WebCryptoAPI/#SubtleCrypto-method-importKey + // It is not beneficial for less time consuming operations. Therefore, we perform it synchronously. + algorithm->importKey(format, WTFMove(keyData), WTFMove(params), extractable, keyUsages, WTFMove(callback), WTFMove(exceptionCallback)); +} + +static void jsSubtleCryptoFunctionExportKeyPromise(ExecState& state, Ref<DeferredPromise>&& promise) +{ + VM& vm = state.vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + + if (UNLIKELY(state.argumentCount() < 2)) { + promise->reject<IDLAny>(createNotEnoughArgumentsError(&state)); + return; + } + + auto format = convertEnumeration<SubtleCrypto::KeyFormat>(state, state.uncheckedArgument(0)); + RETURN_IF_EXCEPTION(scope, void()); + + auto key = toCryptoKey(state, state.uncheckedArgument(1)); + RETURN_IF_EXCEPTION(scope, void()); + + supportExportKeyThrow(state, scope, key->algorithmIdentifier()); + RETURN_IF_EXCEPTION(scope, void()); + + if (!key->extractable()) { + promise->reject(INVALID_ACCESS_ERR, ASCIILiteral("The CryptoKey is nonextractable")); + return; + } + + auto algorithm = CryptoAlgorithmRegistry::singleton().create(key->algorithmIdentifier()); + if (UNLIKELY(!algorithm)) { + throwNotSupportedError(state, scope); + return; + } + + auto callback = [capturedPromise = promise.copyRef()](SubtleCrypto::KeyFormat format, KeyData&& key) mutable { + switch (format) { + case SubtleCrypto::KeyFormat::Spki: + case SubtleCrypto::KeyFormat::Pkcs8: + case SubtleCrypto::KeyFormat::Raw: { + Vector<uint8_t>& rawKey = WTF::get<Vector<uint8_t>>(key); + fulfillPromiseWithArrayBuffer(WTFMove(capturedPromise), rawKey.data(), rawKey.size()); + return; + } + case SubtleCrypto::KeyFormat::Jwk: + capturedPromise->resolve<IDLDictionary<JsonWebKey>>(WTFMove(WTF::get<JsonWebKey>(key))); + return; + } + ASSERT_NOT_REACHED(); + }; + auto exceptionCallback = [capturedPromise = WTFMove(promise)](ExceptionCode ec) mutable { + rejectWithException(WTFMove(capturedPromise), ec); + }; + + // The 11 December 2014 version of the specification suggests we should perform the following task asynchronously: + // https://www.w3.org/TR/WebCryptoAPI/#SubtleCrypto-method-exportKey + // It is not beneficial for less time consuming operations. Therefore, we perform it synchronously. + algorithm->exportKey(format, key.releaseNonNull(), WTFMove(callback), WTFMove(exceptionCallback)); +} + +static void jsSubtleCryptoFunctionWrapKeyPromise(ExecState& state, Ref<DeferredPromise>&& promise) +{ + VM& vm = state.vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + + if (UNLIKELY(state.argumentCount() < 4)) { + promise->reject<IDLAny>(createNotEnoughArgumentsError(&state)); + return; + } + + auto format = convertEnumeration<SubtleCrypto::KeyFormat>(state, state.uncheckedArgument(0)); + RETURN_IF_EXCEPTION(scope, void()); + + auto key = toCryptoKey(state, state.uncheckedArgument(1)); + RETURN_IF_EXCEPTION(scope, void()); + + auto wrappingKey = toCryptoKey(state, state.uncheckedArgument(2)); + RETURN_IF_EXCEPTION(scope, void()); + + auto catchScope = DECLARE_CATCH_SCOPE(vm); + bool isEncryption = false; + auto wrapParams = normalizeCryptoAlgorithmParameters(state, state.uncheckedArgument(3), Operations::WrapKey); + if (catchScope.exception()) { + catchScope.clearException(); + wrapParams = normalizeCryptoAlgorithmParameters(state, state.uncheckedArgument(3), Operations::Encrypt); + RETURN_IF_EXCEPTION(scope, void()); + isEncryption = true; + } + + if (wrapParams->identifier != wrappingKey->algorithmIdentifier()) { + promise->reject(INVALID_ACCESS_ERR, ASCIILiteral("Wrapping CryptoKey doesn't match AlgorithmIdentifier")); + return; + } + + if (!wrappingKey->allows(CryptoKeyUsageWrapKey)) { + promise->reject(INVALID_ACCESS_ERR, ASCIILiteral("Wrapping CryptoKey doesn't support wrapKey operation")); + return; + } + + supportExportKeyThrow(state, scope, key->algorithmIdentifier()); + RETURN_IF_EXCEPTION(scope, void()); + + if (!key->extractable()) { + promise->reject(INVALID_ACCESS_ERR, ASCIILiteral("The CryptoKey is nonextractable")); + return; + } + + auto exportAlgorithm = CryptoAlgorithmRegistry::singleton().create(key->algorithmIdentifier()); + if (UNLIKELY(!exportAlgorithm)) { + throwNotSupportedError(state, scope); + return; + } + + auto wrapAlgorithm = CryptoAlgorithmRegistry::singleton().create(wrappingKey->algorithmIdentifier()); + if (UNLIKELY(!wrapAlgorithm)) { + throwNotSupportedError(state, scope); + return; + } + + auto context = scriptExecutionContextFromExecState(&state); + + auto subtle = jsDynamicDowncast<JSSubtleCrypto*>(vm, state.thisValue()); + ASSERT(subtle); + auto& workQueue = subtle->wrapped().workQueue(); + + auto callback = [promise = promise.copyRef(), wrapAlgorithm, wrappingKey = WTFMove(wrappingKey), wrapParams = WTFMove(wrapParams), isEncryption, context, &workQueue](SubtleCrypto::KeyFormat format, KeyData&& key) mutable { + Vector<uint8_t> bytes; + switch (format) { + case SubtleCrypto::KeyFormat::Spki: + case SubtleCrypto::KeyFormat::Pkcs8: + case SubtleCrypto::KeyFormat::Raw: + bytes = WTF::get<Vector<uint8_t>>(key); + break; + case SubtleCrypto::KeyFormat::Jwk: { + auto jwk = toJS<IDLDictionary<JsonWebKey>>(*(promise->globalObject()->globalExec()), *(promise->globalObject()), WTFMove(WTF::get<JsonWebKey>(key))); + String jwkString = JSONStringify(promise->globalObject()->globalExec(), jwk, 0); + CString jwkUtf8String = jwkString.utf8(StrictConversion); + bytes.append(jwkUtf8String.data(), jwkUtf8String.length()); + } + } + + auto callback = [promise = promise.copyRef()](const Vector<uint8_t>& wrappedKey) mutable { + fulfillPromiseWithArrayBuffer(WTFMove(promise), wrappedKey.data(), wrappedKey.size()); + return; + }; + auto exceptionCallback = [promise = WTFMove(promise)](ExceptionCode ec) mutable { + rejectWithException(WTFMove(promise), ec); + }; + + if (!isEncryption) { + // The 11 December 2014 version of the specification suggests we should perform the following task asynchronously: + // https://www.w3.org/TR/WebCryptoAPI/#SubtleCrypto-method-wrapKey + // It is not beneficial for less time consuming operations. Therefore, we perform it synchronously. + wrapAlgorithm->wrapKey(wrappingKey.releaseNonNull(), WTFMove(bytes), WTFMove(callback), WTFMove(exceptionCallback)); + return; + } + // The following operation should be performed asynchronously. + wrapAlgorithm->encrypt(WTFMove(wrapParams), wrappingKey.releaseNonNull(), WTFMove(bytes), WTFMove(callback), WTFMove(exceptionCallback), *context, workQueue); + }; + auto exceptionCallback = [capturedPromise = WTFMove(promise)](ExceptionCode ec) mutable { + rejectWithException(WTFMove(capturedPromise), ec); + }; + + // The following operation should be performed synchronously. + exportAlgorithm->exportKey(format, key.releaseNonNull(), WTFMove(callback), WTFMove(exceptionCallback)); +} + +static void jsSubtleCryptoFunctionUnwrapKeyPromise(ExecState& state, Ref<DeferredPromise>&& promise) +{ + VM& vm = state.vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + + if (UNLIKELY(state.argumentCount() < 7)) { + promise->reject<IDLAny>(createNotEnoughArgumentsError(&state)); + return; + } + + auto format = convertEnumeration<SubtleCrypto::KeyFormat>(state, state.uncheckedArgument(0)); + RETURN_IF_EXCEPTION(scope, void()); + + auto wrappedKey = toVector(state, state.uncheckedArgument(1)); + RETURN_IF_EXCEPTION(scope, void()); + + auto unwrappingKey = toCryptoKey(state, state.uncheckedArgument(2)); + RETURN_IF_EXCEPTION(scope, void()); + + auto catchScope = DECLARE_CATCH_SCOPE(vm); + bool isDecryption = false; + auto unwrapParams = normalizeCryptoAlgorithmParameters(state, state.uncheckedArgument(3), Operations::UnwrapKey); + if (catchScope.exception()) { + catchScope.clearException(); + unwrapParams = normalizeCryptoAlgorithmParameters(state, state.uncheckedArgument(3), Operations::Decrypt); + RETURN_IF_EXCEPTION(scope, void()); + isDecryption = true; + } + + auto unwrappedKeyAlgorithm = normalizeCryptoAlgorithmParameters(state, state.uncheckedArgument(4), Operations::ImportKey); + RETURN_IF_EXCEPTION(scope, void()); + + auto extractable = state.uncheckedArgument(5).toBoolean(&state); + RETURN_IF_EXCEPTION(scope, void()); + + auto keyUsages = cryptoKeyUsageBitmapFromJSValue(state, state.uncheckedArgument(6)); + RETURN_IF_EXCEPTION(scope, void()); + + if (unwrapParams->identifier != unwrappingKey->algorithmIdentifier()) { + promise->reject(INVALID_ACCESS_ERR, ASCIILiteral("Unwrapping CryptoKey doesn't match unwrap AlgorithmIdentifier")); + return; + } + + if (!unwrappingKey->allows(CryptoKeyUsageUnwrapKey)) { + promise->reject(INVALID_ACCESS_ERR, ASCIILiteral("Unwrapping CryptoKey doesn't support unwrapKey operation")); + return; + } + + auto importAlgorithm = CryptoAlgorithmRegistry::singleton().create(unwrappedKeyAlgorithm->identifier); + if (UNLIKELY(!importAlgorithm)) { + throwNotSupportedError(state, scope); + return; + } + + auto unwrapAlgorithm = CryptoAlgorithmRegistry::singleton().create(unwrappingKey->algorithmIdentifier()); + if (UNLIKELY(!unwrapAlgorithm)) { + throwNotSupportedError(state, scope); + return; + } + + auto callback = [promise = promise.copyRef(), format, importAlgorithm, unwrappedKeyAlgorithm = WTFMove(unwrappedKeyAlgorithm), extractable, keyUsages](const Vector<uint8_t>& bytes) mutable { + ExecState& state = *(promise->globalObject()->globalExec()); + VM& vm = state.vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + + KeyData keyData; + switch (format) { + case SubtleCrypto::KeyFormat::Spki: + case SubtleCrypto::KeyFormat::Pkcs8: + case SubtleCrypto::KeyFormat::Raw: + keyData = bytes; + break; + case SubtleCrypto::KeyFormat::Jwk: { + String jwkString(reinterpret_cast_ptr<const char*>(bytes.data()), bytes.size()); + JSC::JSLockHolder locker(vm); + auto jwk = JSONParse(&state, jwkString); + if (!jwk) { + promise->reject(DataError, ASCIILiteral("WrappedKey cannot be converted to a JSON object")); + return; + } + keyData = toKeyData(state, format, jwk); + RETURN_IF_EXCEPTION(scope, void()); + } + } + + auto callback = [promise = promise.copyRef()](CryptoKey& key) mutable { + if ((key.type() == CryptoKeyType::Private || key.type() == CryptoKeyType::Secret) && !key.usagesBitmap()) { + rejectWithException(WTFMove(promise), SYNTAX_ERR); + return; + } + promise->resolve<IDLInterface<CryptoKey>>(key); + }; + auto exceptionCallback = [promise = WTFMove(promise)](ExceptionCode ec) mutable { + rejectWithException(WTFMove(promise), ec); + }; + + // The following operation should be performed synchronously. + importAlgorithm->importKey(format, WTFMove(keyData), WTFMove(unwrappedKeyAlgorithm), extractable, keyUsages, WTFMove(callback), WTFMove(exceptionCallback)); + }; + auto exceptionCallback = [capturedPromise = WTFMove(promise)](ExceptionCode ec) mutable { + rejectWithException(WTFMove(capturedPromise), ec); + }; + + if (!isDecryption) { + // The 11 December 2014 version of the specification suggests we should perform the following task asynchronously: + // https://www.w3.org/TR/WebCryptoAPI/#SubtleCrypto-method-unwrapKey + // It is not beneficial for less time consuming operations. Therefore, we perform it synchronously. + unwrapAlgorithm->unwrapKey(unwrappingKey.releaseNonNull(), WTFMove(wrappedKey), WTFMove(callback), WTFMove(exceptionCallback)); + return; + } + auto subtle = jsDynamicDowncast<JSSubtleCrypto*>(vm, state.thisValue()); + ASSERT(subtle); + // The following operation should be performed asynchronously. + unwrapAlgorithm->decrypt(WTFMove(unwrapParams), unwrappingKey.releaseNonNull(), WTFMove(wrappedKey), WTFMove(callback), WTFMove(exceptionCallback), *scriptExecutionContextFromExecState(&state), subtle->wrapped().workQueue()); +} + +JSValue JSSubtleCrypto::encrypt(ExecState& state) +{ + return callPromiseFunction<jsSubtleCryptoFunctionEncryptPromise, PromiseExecutionScope::WindowOrWorker>(state); +} + +JSValue JSSubtleCrypto::decrypt(ExecState& state) +{ + return callPromiseFunction<jsSubtleCryptoFunctionDecryptPromise, PromiseExecutionScope::WindowOrWorker>(state); +} + +JSValue JSSubtleCrypto::sign(ExecState& state) +{ + return callPromiseFunction<jsSubtleCryptoFunctionSignPromise, PromiseExecutionScope::WindowOrWorker>(state); +} + +JSValue JSSubtleCrypto::verify(ExecState& state) +{ + return callPromiseFunction<jsSubtleCryptoFunctionVerifyPromise, PromiseExecutionScope::WindowOrWorker>(state); +} + +JSValue JSSubtleCrypto::digest(ExecState& state) +{ + return callPromiseFunction<jsSubtleCryptoFunctionDigestPromise, PromiseExecutionScope::WindowOrWorker>(state); +} + +JSValue JSSubtleCrypto::deriveKey(ExecState& state) +{ + return callPromiseFunction<jsSubtleCryptoFunctionDeriveKeyPromise, PromiseExecutionScope::WindowOrWorker>(state); +} + +JSValue JSSubtleCrypto::deriveBits(ExecState& state) +{ + return callPromiseFunction<jsSubtleCryptoFunctionDeriveBitsPromise, PromiseExecutionScope::WindowOrWorker>(state); +} + +JSValue JSSubtleCrypto::generateKey(ExecState& state) +{ + return callPromiseFunction<jsSubtleCryptoFunctionGenerateKeyPromise, PromiseExecutionScope::WindowOrWorker>(state); +} + +JSValue JSSubtleCrypto::importKey(ExecState& state) +{ + return callPromiseFunction<jsSubtleCryptoFunctionImportKeyPromise, PromiseExecutionScope::WindowOrWorker>(state); +} + +JSValue JSSubtleCrypto::exportKey(ExecState& state) +{ + return callPromiseFunction<jsSubtleCryptoFunctionExportKeyPromise, PromiseExecutionScope::WindowOrWorker>(state); +} + +JSValue JSSubtleCrypto::wrapKey(ExecState& state) +{ + return callPromiseFunction<jsSubtleCryptoFunctionWrapKeyPromise, PromiseExecutionScope::WindowOrWorker>(state); +} + +JSValue JSSubtleCrypto::unwrapKey(ExecState& state) +{ + return callPromiseFunction<jsSubtleCryptoFunctionUnwrapKeyPromise, PromiseExecutionScope::WindowOrWorker>(state); +} + +} // namespace WebCore + +#endif diff --git a/Source/WebCore/bindings/js/JSTextCustom.cpp b/Source/WebCore/bindings/js/JSTextCustom.cpp index 4b6e52965..8343e5043 100644 --- a/Source/WebCore/bindings/js/JSTextCustom.cpp +++ b/Source/WebCore/bindings/js/JSTextCustom.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008 Apple Inc. All Rights Reserved. + * Copyright (C) 2016 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -10,34 +10,38 @@ * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * - * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. */ #include "config.h" #include "JSText.h" -#include "Text.h" +#include "JSCDATASection.h" + +namespace WebCore { using namespace JSC; -namespace WebCore { +JSValue toJSNewlyCreated(ExecState*, JSDOMGlobalObject* globalObject, Ref<Text>&& text) +{ + if (is<CDATASection>(text.get())) + return createWrapper<CDATASection>(globalObject, WTFMove(text)); + return createWrapper<Text>(globalObject, WTFMove(text)); +} -JSValue toJSNewlyCreated(ExecState* exec, JSDOMGlobalObject* globalObject, Text* text) +JSValue toJS(ExecState* state, JSDOMGlobalObject* globalObject, Text& text) { - if (!text) - return jsNull(); - - return CREATE_DOM_WRAPPER(exec, globalObject, Text, text); + return wrap(state, globalObject, text); } } // namespace WebCore diff --git a/Source/WebCore/bindings/js/JSTextTrackCueCustom.cpp b/Source/WebCore/bindings/js/JSTextTrackCueCustom.cpp index 1605ab3e3..a297e8df2 100644 --- a/Source/WebCore/bindings/js/JSTextTrackCueCustom.cpp +++ b/Source/WebCore/bindings/js/JSTextTrackCueCustom.cpp @@ -10,10 +10,10 @@ * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * - * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR @@ -28,7 +28,10 @@ #if ENABLE(VIDEO_TRACK) #include "JSTextTrackCue.h" + +#include "JSDataCue.h" #include "JSTrackCustom.h" +#include "JSVTTCue.h" #include "TextTrack.h" using namespace JSC; @@ -37,18 +40,14 @@ namespace WebCore { bool JSTextTrackCueOwner::isReachableFromOpaqueRoots(JSC::Handle<JSC::Unknown> handle, void*, SlotVisitor& visitor) { - JSTextTrackCue* jsTextTrackCue = jsCast<JSTextTrackCue*>(handle.get().asCell()); - TextTrackCue& textTrackCue = jsTextTrackCue->impl(); + JSTextTrackCue* jsTextTrackCue = jsCast<JSTextTrackCue*>(handle.slot()->asCell()); + TextTrackCue& textTrackCue = jsTextTrackCue->wrapped(); // If the cue is firing event listeners, its wrapper is reachable because // the wrapper is responsible for marking those event listeners. if (textTrackCue.isFiringEventListeners()) return true; - // If the cue has no event listeners and has no custom properties, it is not reachable. - if (!textTrackCue.hasEventListeners() && !jsTextTrackCue->hasCustomProperties()) - return false; - // If the cue is not associated with a track, it is not reachable. if (!textTrackCue.track()) return false; @@ -56,20 +55,29 @@ bool JSTextTrackCueOwner::isReachableFromOpaqueRoots(JSC::Handle<JSC::Unknown> h return visitor.containsOpaqueRoot(root(textTrackCue.track())); } -void JSTextTrackCue::visitChildren(JSCell* cell, SlotVisitor& visitor) +JSValue toJSNewlyCreated(ExecState*, JSDOMGlobalObject* globalObject, Ref<TextTrackCue>&& cue) +{ + switch (cue->cueType()) { + case TextTrackCue::Data: + return createWrapper<DataCue>(globalObject, WTFMove(cue)); + case TextTrackCue::WebVTT: + case TextTrackCue::Generic: + return createWrapper<VTTCue>(globalObject, WTFMove(cue)); + default: + ASSERT_NOT_REACHED(); + return jsNull(); + } +} + +JSValue toJS(ExecState* state, JSDOMGlobalObject* globalObject, TextTrackCue& cue) +{ + return wrap(state, globalObject, cue); +} + +void JSTextTrackCue::visitAdditionalChildren(SlotVisitor& visitor) { - JSTextTrackCue* jsTextTrackCue = jsCast<JSTextTrackCue*>(cell); - ASSERT_GC_OBJECT_INHERITS(jsTextTrackCue, info()); - COMPILE_ASSERT(StructureFlags & OverridesVisitChildren, OverridesVisitChildrenWithoutSettingFlag); - ASSERT(jsTextTrackCue->structure()->typeInfo().overridesVisitChildren()); - Base::visitChildren(jsTextTrackCue, visitor); - - // Mark the cue's track root if it has one. - TextTrackCue& textTrackCue = jsTextTrackCue->impl(); - if (TextTrack* textTrack = textTrackCue.track()) + if (TextTrack* textTrack = wrapped().track()) visitor.addOpaqueRoot(root(textTrack)); - - textTrackCue.visitJSEventListeners(visitor); } } // namespace WebCore diff --git a/Source/WebCore/bindings/js/JSTextTrackCustom.cpp b/Source/WebCore/bindings/js/JSTextTrackCustom.cpp index 078f6f256..793b6eadf 100644 --- a/Source/WebCore/bindings/js/JSTextTrackCustom.cpp +++ b/Source/WebCore/bindings/js/JSTextTrackCustom.cpp @@ -10,10 +10,10 @@ * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * - * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR @@ -26,7 +26,9 @@ #include "config.h" #if ENABLE(VIDEO_TRACK) + #include "JSTextTrack.h" + #include "JSTextTrackCueList.h" #include "JSTrackCustom.h" @@ -34,45 +36,23 @@ using namespace JSC; namespace WebCore { -void JSTextTrack::visitChildren(JSCell* cell, SlotVisitor& visitor) +void JSTextTrack::visitAdditionalChildren(SlotVisitor& visitor) { - JSTextTrack* jsTextTrack = jsCast<JSTextTrack*>(cell); - ASSERT_GC_OBJECT_INHERITS(jsTextTrack, info()); - COMPILE_ASSERT(StructureFlags & OverridesVisitChildren, OverridesVisitChildrenWithoutSettingFlag); - ASSERT(jsTextTrack->structure()->typeInfo().overridesVisitChildren()); - Base::visitChildren(jsTextTrack, visitor); - - TextTrack& textTrack = jsTextTrack->impl(); - visitor.addOpaqueRoot(root(&textTrack)); - - textTrack.visitJSEventListeners(visitor); + visitor.addOpaqueRoot(root(&wrapped())); } -void JSTextTrack::setKind(ExecState* exec, JSValue value) +void JSTextTrack::setLanguage(ExecState& state, JSValue value) { - UNUSED_PARAM(exec); #if ENABLE(MEDIA_SOURCE) - const String& nativeValue(value.isEmpty() ? String() : value.toString(exec)->value(exec)); - if (exec->hadException()) - return; - impl().setKind(nativeValue); -#else - UNUSED_PARAM(value); - return; -#endif -} + VM& vm = state.vm(); + auto scope = DECLARE_THROW_SCOPE(vm); -void JSTextTrack::setLanguage(ExecState* exec, JSValue value) -{ - UNUSED_PARAM(exec); -#if ENABLE(MEDIA_SOURCE) - const String& nativeValue(value.isEmpty() ? String() : value.toString(exec)->value(exec)); - if (exec->hadException()) - return; - impl().setLanguage(nativeValue); + auto string = value.toWTFString(&state); + RETURN_IF_EXCEPTION(scope, void()); + wrapped().setLanguage(string); #else + UNUSED_PARAM(state); UNUSED_PARAM(value); - return; #endif } diff --git a/Source/WebCore/bindings/js/JSTextTrackListCustom.cpp b/Source/WebCore/bindings/js/JSTextTrackListCustom.cpp index 8be5ef40c..3f46f4331 100644 --- a/Source/WebCore/bindings/js/JSTextTrackListCustom.cpp +++ b/Source/WebCore/bindings/js/JSTextTrackListCustom.cpp @@ -10,10 +10,10 @@ * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * - * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR @@ -26,6 +26,7 @@ #include "config.h" #if ENABLE(VIDEO_TRACK) + #include "JSTextTrackList.h" #include "Element.h" @@ -35,17 +36,9 @@ using namespace JSC; namespace WebCore { -void JSTextTrackList::visitChildren(JSCell* cell, SlotVisitor& visitor) +void JSTextTrackList::visitAdditionalChildren(JSC::SlotVisitor& visitor) { - JSTextTrackList* jsTextTrackList = jsCast<JSTextTrackList*>(cell); - ASSERT_GC_OBJECT_INHERITS(jsTextTrackList, info()); - COMPILE_ASSERT(StructureFlags & OverridesVisitChildren, OverridesVisitChildrenWithoutSettingFlag); - ASSERT(jsTextTrackList->structure()->typeInfo().overridesVisitChildren()); - Base::visitChildren(jsTextTrackList, visitor); - - TextTrackList& textTrackList = jsTextTrackList->impl(); - visitor.addOpaqueRoot(root(textTrackList.element())); - textTrackList.visitJSEventListeners(visitor); + visitor.addOpaqueRoot(root(wrapped().element())); } } // namespace WebCore diff --git a/Source/WebCore/bindings/js/JSTouchCustom.cpp b/Source/WebCore/bindings/js/JSTouchCustom.cpp deleted file mode 100644 index d9434c0f2..000000000 --- a/Source/WebCore/bindings/js/JSTouchCustom.cpp +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright 2010, The Android Open Source Project - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" - -#if !PLATFORM(IOS) -#if ENABLE(TOUCH_EVENTS) - -#include "JSTouch.h" - -#include "Touch.h" - -using namespace JSC; - -namespace WebCore { - -JSValue toJSNewlyCreated(ExecState* exec, JSDOMGlobalObject* globalObject, Touch* touch) -{ - if (!touch) - return jsNull(); - - return CREATE_DOM_WRAPPER(exec, globalObject, Touch, touch); -} - -} // namespace WebCore - -#endif // ENABLE(TOUCH_EVENTS) -#endif // !PLATFORM(IOS) diff --git a/Source/WebCore/bindings/js/JSTouchListCustom.cpp b/Source/WebCore/bindings/js/JSTouchListCustom.cpp deleted file mode 100644 index 11318c005..000000000 --- a/Source/WebCore/bindings/js/JSTouchListCustom.cpp +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright 2010, The Android Open Source Project - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" - -#if !PLATFORM(IOS) -#if ENABLE(TOUCH_EVENTS) - -#include "JSTouchList.h" - -#include "TouchList.h" - -using namespace JSC; - -namespace WebCore { - -JSValue toJSNewlyCreated(ExecState* exec, JSDOMGlobalObject* globalObject, TouchList* touchList) -{ - if (!touchList) - return jsNull(); - - return CREATE_DOM_WRAPPER(exec, globalObject, TouchList, touchList); -} - -} // namespace WebCore - -#endif // ENABLE(TOUCH_EVENTS) -#endif // !PLATFORM(IOS) diff --git a/Source/WebCore/bindings/js/JSTrackCustom.cpp b/Source/WebCore/bindings/js/JSTrackCustom.cpp index 0ad233618..57bb6b2c5 100644 --- a/Source/WebCore/bindings/js/JSTrackCustom.cpp +++ b/Source/WebCore/bindings/js/JSTrackCustom.cpp @@ -10,10 +10,10 @@ * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * - * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR @@ -37,49 +37,22 @@ using namespace JSC; namespace WebCore { -TrackBase* toTrack(JSValue value) +JSC::JSValue toJS(JSC::ExecState* state, JSDOMGlobalObject* globalObject, TrackBase& track) { - if (!value.isObject()) - return 0; - - JSObject* object = asObject(value); - if (object->inherits(JSTextTrack::info())) - return &jsCast<JSTextTrack*>(object)->impl(); - - // FIXME: Fill in additional tests and casts here for VideoTrack and AudioTrack when - // they have been added to WebCore. - - return 0; -} - -JSC::JSValue toJS(JSC::ExecState* exec, JSDOMGlobalObject* globalObject, TrackBase* track) -{ - if (!track) - return jsNull(); - - JSObject* wrapper = getCachedWrapper(currentWorld(exec), track); - if (wrapper) - return wrapper; - - switch (track->type()) { + switch (track.type()) { case TrackBase::BaseTrack: // This should never happen. ASSERT_NOT_REACHED(); break; - - case TrackBase::AudioTrack: - return CREATE_DOM_WRAPPER(exec, globalObject, AudioTrack, track); - break; + case TrackBase::AudioTrack: + return wrap(state, globalObject, downcast<AudioTrack>(track)); case TrackBase::VideoTrack: - return CREATE_DOM_WRAPPER(exec, globalObject, VideoTrack, track); - break; - + return wrap(state, globalObject, downcast<VideoTrack>(track)); case TrackBase::TextTrack: - return CREATE_DOM_WRAPPER(exec, globalObject, TextTrack, track); - break; + return wrap(state, globalObject, downcast<TextTrack>(track)); } - + return jsNull(); } diff --git a/Source/WebCore/bindings/js/JSTrackCustom.h b/Source/WebCore/bindings/js/JSTrackCustom.h index 6e24a0915..30dd99066 100644 --- a/Source/WebCore/bindings/js/JSTrackCustom.h +++ b/Source/WebCore/bindings/js/JSTrackCustom.h @@ -10,10 +10,10 @@ * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * - * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR @@ -23,8 +23,7 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef JSTrackCustom_h -#define JSTrackCustom_h +#pragma once #if ENABLE(VIDEO_TRACK) @@ -35,8 +34,7 @@ namespace WebCore { -TrackBase* toTrack(JSC::JSValue); -JSC::JSValue toJS(JSC::ExecState*, JSDOMGlobalObject*, TrackBase*); +JSC::JSValue toJS(JSC::ExecState*, JSDOMGlobalObject*, TrackBase&); inline void* root(TrackBase* track) { @@ -45,7 +43,6 @@ inline void* root(TrackBase* track) return track; } -} +} // namespace WebCore -#endif -#endif +#endif // ENABLE(VIDEO_TRACK) diff --git a/Source/WebCore/bindings/js/JSTreeWalkerCustom.cpp b/Source/WebCore/bindings/js/JSTreeWalkerCustom.cpp index 9f01659f9..2be08a991 100644 --- a/Source/WebCore/bindings/js/JSTreeWalkerCustom.cpp +++ b/Source/WebCore/bindings/js/JSTreeWalkerCustom.cpp @@ -20,24 +20,14 @@ #include "config.h" #include "JSTreeWalker.h" -#include "JSNode.h" #include "Node.h" -#include "NodeFilter.h" -#include "TreeWalker.h" - -using namespace JSC; +#include <heap/SlotVisitorInlines.h> namespace WebCore { -void JSTreeWalker::visitChildren(JSCell* cell, SlotVisitor& visitor) +void JSTreeWalker::visitAdditionalChildren(JSC::SlotVisitor& visitor) { - JSTreeWalker* thisObject = jsCast<JSTreeWalker*>(cell); - ASSERT_GC_OBJECT_INHERITS(thisObject, info()); - COMPILE_ASSERT(StructureFlags & OverridesVisitChildren, OverridesVisitChildrenWithoutSettingFlag); - ASSERT(thisObject->structure()->typeInfo().overridesVisitChildren()); - Base::visitChildren(thisObject, visitor); - - if (NodeFilter* filter = thisObject->m_impl->filter()) + if (NodeFilter* filter = wrapped().filter()) visitor.addOpaqueRoot(filter); } diff --git a/Source/WebCore/bindings/js/JSUserMessageHandlersNamespaceCustom.cpp b/Source/WebCore/bindings/js/JSUserMessageHandlersNamespaceCustom.cpp new file mode 100644 index 000000000..1dd42d4fd --- /dev/null +++ b/Source/WebCore/bindings/js/JSUserMessageHandlersNamespaceCustom.cpp @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2014 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "JSUserMessageHandlersNamespace.h" + +#if ENABLE(USER_MESSAGE_HANDLERS) + +#include "JSDOMConvertInterface.h" +#include "JSDOMConvertStrings.h" +#include "JSUserMessageHandler.h" +#include <runtime/JSCInlines.h> + +using namespace JSC; + +namespace WebCore { + +bool JSUserMessageHandlersNamespace::getOwnPropertySlotDelegate(ExecState* exec, PropertyName propertyName, PropertySlot& slot) +{ + if (auto* handler = wrapped().handler(propertyNameToAtomicString(propertyName), globalObject()->world())) { + slot.setValue(this, ReadOnly | DontDelete | DontEnum, toJS<IDLInterface<UserMessageHandler>>(*exec, *globalObject(), *handler)); + return true; + } + return false; +} + +} + +#endif // ENABLE(USER_MESSAGE_HANDLERS) diff --git a/Source/WebCore/bindings/js/JSVideoTrackCustom.cpp b/Source/WebCore/bindings/js/JSVideoTrackCustom.cpp index a82e7b8bc..f79a3341f 100644 --- a/Source/WebCore/bindings/js/JSVideoTrackCustom.cpp +++ b/Source/WebCore/bindings/js/JSVideoTrackCustom.cpp @@ -10,10 +10,10 @@ * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * - * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR @@ -35,43 +35,38 @@ using namespace JSC; namespace WebCore { -void JSVideoTrack::visitChildren(JSCell* cell, SlotVisitor& visitor) +void JSVideoTrack::visitAdditionalChildren(SlotVisitor& visitor) { - JSVideoTrack* jsVideoTrack = jsCast<JSVideoTrack*>(cell); - ASSERT_GC_OBJECT_INHERITS(jsVideoTrack, info()); - COMPILE_ASSERT(StructureFlags & OverridesVisitChildren, OverridesVisitChildrenWithoutSettingFlag); - ASSERT(jsVideoTrack->structure()->typeInfo().overridesVisitChildren()); - Base::visitChildren(jsVideoTrack, visitor); - - VideoTrack& videoTrack = jsVideoTrack->impl(); - visitor.addOpaqueRoot(root(&videoTrack)); + visitor.addOpaqueRoot(root(&wrapped())); } -void JSVideoTrack::setKind(ExecState* exec, JSValue value) +void JSVideoTrack::setKind(ExecState& state, JSValue value) { - UNUSED_PARAM(exec); #if ENABLE(MEDIA_SOURCE) - const String& nativeValue(value.isEmpty() ? String() : value.toString(exec)->value(exec)); - if (exec->hadException()) - return; - impl().setKind(nativeValue); + VM& vm = state.vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + + auto string = value.toWTFString(&state); + RETURN_IF_EXCEPTION(scope, void()); + wrapped().setKind(string); #else + UNUSED_PARAM(state); UNUSED_PARAM(value); - return; #endif } -void JSVideoTrack::setLanguage(ExecState* exec, JSValue value) +void JSVideoTrack::setLanguage(ExecState& state, JSValue value) { - UNUSED_PARAM(exec); #if ENABLE(MEDIA_SOURCE) - const String& nativeValue(value.isEmpty() ? String() : value.toString(exec)->value(exec)); - if (exec->hadException()) - return; - impl().setLanguage(nativeValue); + VM& vm = state.vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + + auto string = value.toWTFString(&state); + RETURN_IF_EXCEPTION(scope, void()); + wrapped().setLanguage(string); #else + UNUSED_PARAM(state); UNUSED_PARAM(value); - return; #endif } diff --git a/Source/WebCore/bindings/js/JSVideoTrackListCustom.cpp b/Source/WebCore/bindings/js/JSVideoTrackListCustom.cpp index 0a669d3e3..a2a36184a 100644 --- a/Source/WebCore/bindings/js/JSVideoTrackListCustom.cpp +++ b/Source/WebCore/bindings/js/JSVideoTrackListCustom.cpp @@ -10,10 +10,10 @@ * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * - * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR @@ -26,26 +26,18 @@ #include "config.h" #if ENABLE(VIDEO_TRACK) + #include "JSVideoTrackList.h" -#include "Element.h" #include "JSNodeCustom.h" using namespace JSC; namespace WebCore { -void JSVideoTrackList::visitChildren(JSCell* cell, SlotVisitor& visitor) +void JSVideoTrackList::visitAdditionalChildren(SlotVisitor& visitor) { - JSVideoTrackList* jsVideoTrackList = jsCast<JSVideoTrackList*>(cell); - ASSERT_GC_OBJECT_INHERITS(jsVideoTrackList, info()); - COMPILE_ASSERT(StructureFlags & OverridesVisitChildren, OverridesVisitChildrenWithoutSettingFlag); - ASSERT(jsVideoTrackList->structure()->typeInfo().overridesVisitChildren()); - Base::visitChildren(jsVideoTrackList, visitor); - - VideoTrackList& videoTrackList = jsVideoTrackList->impl(); - visitor.addOpaqueRoot(root(videoTrackList.element())); - videoTrackList.visitJSEventListeners(visitor); + visitor.addOpaqueRoot(root(wrapped().element())); } } // namespace WebCore diff --git a/Source/WebCore/bindings/js/JSCDATASectionCustom.cpp b/Source/WebCore/bindings/js/JSWebGL2RenderingContextCustom.cpp index de655c129..9cefb0ea3 100644 --- a/Source/WebCore/bindings/js/JSCDATASectionCustom.cpp +++ b/Source/WebCore/bindings/js/JSWebGL2RenderingContextCustom.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008, 2009 Apple Inc. All Rights Reserved. + * Copyright (C) 2015-2017 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -20,24 +20,25 @@ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "config.h" -#include "JSCDATASection.h" -#include "CDATASection.h" +#if ENABLE(WEBGL) && ENABLE(WEBGL2) + +#include "JSWebGL2RenderingContext.h" +#include <heap/HeapInlines.h> using namespace JSC; namespace WebCore { -JSValue toJSNewlyCreated(ExecState* exec, JSDOMGlobalObject* globalObject, CDATASection* section) +void JSWebGL2RenderingContext::visitAdditionalChildren(SlotVisitor& visitor) { - if (!section) - return jsNull(); - - return CREATE_DOM_WRAPPER(exec, globalObject, CDATASection, section); + visitor.addOpaqueRoot(&wrapped()); } } // namespace WebCore + +#endif // ENABLE(WEBGL) diff --git a/Source/WebCore/bindings/js/JSWebGLRenderingContextBaseCustom.cpp b/Source/WebCore/bindings/js/JSWebGLRenderingContextBaseCustom.cpp new file mode 100644 index 000000000..66d7ebd04 --- /dev/null +++ b/Source/WebCore/bindings/js/JSWebGLRenderingContextBaseCustom.cpp @@ -0,0 +1,206 @@ +/* + * Copyright (C) 2015-2017 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" + +#if ENABLE(WEBGL) + +#include "EXTBlendMinMax.h" +#include "EXTFragDepth.h" +#include "EXTShaderTextureLOD.h" +#include "EXTTextureFilterAnisotropic.h" +#include "EXTsRGB.h" +#include "ExceptionCode.h" +#include "JSANGLEInstancedArrays.h" +#include "JSEXTBlendMinMax.h" +#include "JSEXTFragDepth.h" +#include "JSEXTShaderTextureLOD.h" +#include "JSEXTTextureFilterAnisotropic.h" +#include "JSEXTsRGB.h" +#include "JSHTMLCanvasElement.h" +#include "JSHTMLImageElement.h" +#include "JSImageData.h" +#include "JSOESElementIndexUint.h" +#include "JSOESStandardDerivatives.h" +#include "JSOESTextureFloat.h" +#include "JSOESTextureFloatLinear.h" +#include "JSOESTextureHalfFloat.h" +#include "JSOESTextureHalfFloatLinear.h" +#include "JSOESVertexArrayObject.h" +#include "JSWebGLBuffer.h" +#include "JSWebGLCompressedTextureATC.h" +#include "JSWebGLCompressedTexturePVRTC.h" +#include "JSWebGLCompressedTextureS3TC.h" +#include "JSWebGLDebugRendererInfo.h" +#include "JSWebGLDebugShaders.h" +#include "JSWebGLDepthTexture.h" +#include "JSWebGLDrawBuffers.h" +#include "JSWebGLFramebuffer.h" +#include "JSWebGLLoseContext.h" +#include "JSWebGLProgram.h" +#include "JSWebGLRenderbuffer.h" +#include "JSWebGLRenderingContext.h" +#include "JSWebGLShader.h" +#include "JSWebGLTexture.h" +#include "JSWebGLUniformLocation.h" +#include "JSWebGLVertexArrayObject.h" +#include "JSWebGLVertexArrayObjectOES.h" +#include "JSWebKitCSSMatrix.h" +#include "OESElementIndexUint.h" +#include "OESStandardDerivatives.h" +#include "OESTextureFloat.h" +#include "OESTextureFloatLinear.h" +#include "OESTextureHalfFloat.h" +#include "OESTextureHalfFloatLinear.h" +#include "OESVertexArrayObject.h" +#include "WebGLBuffer.h" +#include "WebGLCompressedTextureATC.h" +#include "WebGLCompressedTexturePVRTC.h" +#include "WebGLCompressedTextureS3TC.h" +#include "WebGLDebugRendererInfo.h" +#include "WebGLDebugShaders.h" +#include "WebGLDepthTexture.h" +#include "WebGLDrawBuffers.h" +#include "WebGLExtension.h" +#include "WebGLFramebuffer.h" +#include "WebGLLoseContext.h" +#include "WebGLProgram.h" +#include "WebGLRenderingContextBase.h" +#include "WebGLVertexArrayObject.h" +#include "WebGLVertexArrayObjectOES.h" +#include <runtime/Error.h> +#include <runtime/JSObjectInlines.h> +#include <runtime/JSTypedArrays.h> +#include <runtime/TypedArrayInlines.h> +#include <runtime/TypedArrays.h> +#include <wtf/FastMalloc.h> + +#if ENABLE(VIDEO) +#include "JSHTMLVideoElement.h" +#endif + +#if ENABLE(WEBGL2) +#include "JSWebGL2RenderingContext.h" +#endif + +using namespace JSC; + +namespace WebCore { + +JSValue toJSNewlyCreated(ExecState*, JSDOMGlobalObject* globalObject, Ref<WebGLRenderingContextBase>&& object) +{ +#if ENABLE(WEBGL2) + if (is<WebGL2RenderingContext>(object)) + return createWrapper<WebGL2RenderingContext>(globalObject, WTFMove(object)); +#endif + return createWrapper<WebGLRenderingContext>(globalObject, WTFMove(object)); +} + +JSValue toJS(ExecState* state, JSDOMGlobalObject* globalObject, WebGLRenderingContextBase& object) +{ + return wrap(state, globalObject, object); +} + +static JSValue toJS(ExecState& state, JSDOMGlobalObject& globalObject, WebGLExtension* extension) +{ + if (!extension) + return jsNull(); + switch (extension->getName()) { + case WebGLExtension::WebGLLoseContextName: + return toJS(&state, &globalObject, static_cast<WebGLLoseContext*>(extension)); + case WebGLExtension::EXTShaderTextureLODName: + return toJS(&state, &globalObject, static_cast<EXTShaderTextureLOD*>(extension)); + case WebGLExtension::EXTTextureFilterAnisotropicName: + return toJS(&state, &globalObject, static_cast<EXTTextureFilterAnisotropic*>(extension)); + case WebGLExtension::EXTsRGBName: + return toJS(&state, &globalObject, static_cast<EXTsRGB*>(extension)); + case WebGLExtension::EXTFragDepthName: + return toJS(&state, &globalObject, static_cast<EXTFragDepth*>(extension)); + case WebGLExtension::EXTBlendMinMaxName: + return toJS(&state, &globalObject, static_cast<EXTBlendMinMax*>(extension)); + case WebGLExtension::OESStandardDerivativesName: + return toJS(&state, &globalObject, static_cast<OESStandardDerivatives*>(extension)); + case WebGLExtension::OESTextureFloatName: + return toJS(&state, &globalObject, static_cast<OESTextureFloat*>(extension)); + case WebGLExtension::OESTextureFloatLinearName: + return toJS(&state, &globalObject, static_cast<OESTextureFloatLinear*>(extension)); + case WebGLExtension::OESTextureHalfFloatName: + return toJS(&state, &globalObject, static_cast<OESTextureHalfFloat*>(extension)); + case WebGLExtension::OESTextureHalfFloatLinearName: + return toJS(&state, &globalObject, static_cast<OESTextureHalfFloatLinear*>(extension)); + case WebGLExtension::OESVertexArrayObjectName: + return toJS(&state, &globalObject, static_cast<OESVertexArrayObject*>(extension)); + case WebGLExtension::OESElementIndexUintName: + return toJS(&state, &globalObject, static_cast<OESElementIndexUint*>(extension)); + case WebGLExtension::WebGLDebugRendererInfoName: + return toJS(&state, &globalObject, static_cast<WebGLDebugRendererInfo*>(extension)); + case WebGLExtension::WebGLDebugShadersName: + return toJS(&state, &globalObject, static_cast<WebGLDebugShaders*>(extension)); + case WebGLExtension::WebGLCompressedTextureATCName: + return toJS(&state, &globalObject, static_cast<WebGLCompressedTextureATC*>(extension)); + case WebGLExtension::WebGLCompressedTexturePVRTCName: + return toJS(&state, &globalObject, static_cast<WebGLCompressedTexturePVRTC*>(extension)); + case WebGLExtension::WebGLCompressedTextureS3TCName: + return toJS(&state, &globalObject, static_cast<WebGLCompressedTextureS3TC*>(extension)); + case WebGLExtension::WebGLDepthTextureName: + return toJS(&state, &globalObject, static_cast<WebGLDepthTexture*>(extension)); + case WebGLExtension::WebGLDrawBuffersName: + return toJS(&state, &globalObject, static_cast<WebGLDrawBuffers*>(extension)); + case WebGLExtension::ANGLEInstancedArraysName: + return toJS(&state, &globalObject, static_cast<ANGLEInstancedArrays*>(extension)); + } + ASSERT_NOT_REACHED(); + return jsNull(); +} + +bool JSWebGLRenderingContextBaseOwner::isReachableFromOpaqueRoots(Handle<JSC::Unknown> handle, void*, SlotVisitor& visitor) +{ + JSWebGLRenderingContextBase* jsWebGLRenderingContext = jsCast<JSWebGLRenderingContextBase*>(handle.slot()->asCell()); + void* root = WebCore::root(jsWebGLRenderingContext->wrapped().canvas()); + return visitor.containsOpaqueRoot(root); +} + +void JSWebGLRenderingContextBase::visitAdditionalChildren(SlotVisitor& visitor) +{ + visitor.addOpaqueRoot(&wrapped()); + visitor.addOpaqueRoot(root(wrapped().canvas())); +} + +JSValue JSWebGLRenderingContextBase::getExtension(ExecState& state) +{ + VM& vm = state.vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + + if (state.argumentCount() < 1) + return throwException(&state, scope, createNotEnoughArgumentsError(&state)); + + auto name = state.uncheckedArgument(0).toWTFString(&state); + RETURN_IF_EXCEPTION(scope, { }); + return toJS(state, *globalObject(), wrapped().getExtension(name)); +} + +} // namespace WebCore + +#endif // ENABLE(WEBGL) diff --git a/Source/WebCore/bindings/js/JSWebGLRenderingContextCustom.cpp b/Source/WebCore/bindings/js/JSWebGLRenderingContextCustom.cpp index 9e390fc23..65abcdd1f 100644 --- a/Source/WebCore/bindings/js/JSWebGLRenderingContextCustom.cpp +++ b/Source/WebCore/bindings/js/JSWebGLRenderingContextCustom.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2009 Apple Inc. All rights reserved. + * Copyright (C) 2015 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -10,10 +10,10 @@ * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * - * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR @@ -26,727 +26,20 @@ #include "config.h" #if ENABLE(WEBGL) - #include "JSWebGLRenderingContext.h" - -#include "ANGLEInstancedArrays.h" -#include "EXTDrawBuffers.h" -#include "EXTTextureFilterAnisotropic.h" -#include "ExceptionCode.h" -#include "HTMLCanvasElement.h" -#include "HTMLImageElement.h" -#include "JSANGLEInstancedArrays.h" -#include "JSEXTDrawBuffers.h" -#include "JSEXTTextureFilterAnisotropic.h" -#include "JSHTMLCanvasElement.h" -#include "JSHTMLImageElement.h" -#include "JSImageData.h" -#include "JSOESElementIndexUint.h" -#include "JSOESStandardDerivatives.h" -#include "JSOESTextureFloat.h" -#include "JSOESTextureFloatLinear.h" -#include "JSOESTextureHalfFloat.h" -#include "JSOESTextureHalfFloatLinear.h" -#include "JSOESVertexArrayObject.h" -#include "JSWebGLBuffer.h" -#include "JSWebGLCompressedTextureATC.h" -#include "JSWebGLCompressedTexturePVRTC.h" -#include "JSWebGLCompressedTextureS3TC.h" -#include "JSWebGLDebugRendererInfo.h" -#include "JSWebGLDebugShaders.h" -#include "JSWebGLDepthTexture.h" -#include "JSWebGLFramebuffer.h" -#include "JSWebGLLoseContext.h" -#include "JSWebGLProgram.h" -#include "JSWebGLRenderbuffer.h" -#include "JSWebGLShader.h" -#include "JSWebGLTexture.h" -#include "JSWebGLUniformLocation.h" -#include "JSWebGLVertexArrayObjectOES.h" -#include "JSWebKitCSSMatrix.h" -#include "NotImplemented.h" -#include "OESElementIndexUint.h" -#include "OESStandardDerivatives.h" -#include "OESTextureFloat.h" -#include "OESTextureFloatLinear.h" -#include "OESTextureHalfFloat.h" -#include "OESTextureHalfFloatLinear.h" -#include "OESVertexArrayObject.h" -#include "WebGLBuffer.h" -#include "WebGLCompressedTextureATC.h" -#include "WebGLCompressedTexturePVRTC.h" -#include "WebGLCompressedTextureS3TC.h" -#include "WebGLDebugRendererInfo.h" -#include "WebGLDebugShaders.h" -#include "WebGLDepthTexture.h" -#include "WebGLExtension.h" -#include "WebGLFramebuffer.h" -#include "WebGLGetInfo.h" -#include "WebGLLoseContext.h" -#include "WebGLProgram.h" -#include "WebGLRenderingContext.h" -#include "WebGLVertexArrayObjectOES.h" -#include <runtime/Error.h> -#include <runtime/JSTypedArrays.h> -#include <runtime/TypedArrayInlines.h> -#include <runtime/TypedArrays.h> -#include <wtf/FastMalloc.h> - -#if ENABLE(VIDEO) -#include "HTMLVideoElement.h" -#include "JSHTMLVideoElement.h" -#endif +#include "DOMWrapperWorld.h" +#include <JavaScriptCore/JSCellInlines.h> +#include <JavaScriptCore/StructureInlines.h> +#include <heap/HeapInlines.h> +#include <heap/SlotVisitorInlines.h> using namespace JSC; namespace WebCore { -static JSValue toJS(ExecState* exec, JSDOMGlobalObject* globalObject, const WebGLGetInfo& info) -{ - switch (info.getType()) { - case WebGLGetInfo::kTypeBool: - return jsBoolean(info.getBool()); - case WebGLGetInfo::kTypeBoolArray: { - MarkedArgumentBuffer list; - const Vector<bool>& value = info.getBoolArray(); - for (size_t ii = 0; ii < value.size(); ++ii) - list.append(jsBoolean(value[ii])); - return constructArray(exec, 0, globalObject, list); - } - case WebGLGetInfo::kTypeFloat: - return jsNumber(info.getFloat()); - case WebGLGetInfo::kTypeInt: - return jsNumber(info.getInt()); - case WebGLGetInfo::kTypeNull: - return jsNull(); - case WebGLGetInfo::kTypeString: - return jsStringWithCache(exec, info.getString()); - case WebGLGetInfo::kTypeUnsignedInt: - return jsNumber(info.getUnsignedInt()); - case WebGLGetInfo::kTypeWebGLBuffer: - return toJS(exec, globalObject, info.getWebGLBuffer()); - case WebGLGetInfo::kTypeWebGLFloatArray: - return toJS(exec, globalObject, info.getWebGLFloatArray()); - case WebGLGetInfo::kTypeWebGLFramebuffer: - return toJS(exec, globalObject, info.getWebGLFramebuffer()); - case WebGLGetInfo::kTypeWebGLIntArray: - return toJS(exec, globalObject, info.getWebGLIntArray()); - // FIXME: implement WebGLObjectArray - // case WebGLGetInfo::kTypeWebGLObjectArray: - case WebGLGetInfo::kTypeWebGLProgram: - return toJS(exec, globalObject, info.getWebGLProgram()); - case WebGLGetInfo::kTypeWebGLRenderbuffer: - return toJS(exec, globalObject, info.getWebGLRenderbuffer()); - case WebGLGetInfo::kTypeWebGLTexture: - return toJS(exec, globalObject, info.getWebGLTexture()); - case WebGLGetInfo::kTypeWebGLUnsignedByteArray: - return toJS(exec, globalObject, info.getWebGLUnsignedByteArray()); - case WebGLGetInfo::kTypeWebGLUnsignedIntArray: - return toJS(exec, globalObject, info.getWebGLUnsignedIntArray()); - case WebGLGetInfo::kTypeWebGLVertexArrayObjectOES: - return toJS(exec, globalObject, info.getWebGLVertexArrayObjectOES()); - default: - notImplemented(); - return jsUndefined(); - } -} - -enum ObjectType { - kBuffer, kRenderbuffer, kTexture, kVertexAttrib -}; - -static JSValue getObjectParameter(JSWebGLRenderingContext* obj, ExecState* exec, ObjectType objectType) -{ - if (exec->argumentCount() != 2) - return exec->vm().throwException(exec, createNotEnoughArgumentsError(exec)); - - ExceptionCode ec = 0; - WebGLRenderingContext& context = obj->impl(); - unsigned target = exec->uncheckedArgument(0).toInt32(exec); - if (exec->hadException()) - return jsUndefined(); - unsigned pname = exec->uncheckedArgument(1).toInt32(exec); - if (exec->hadException()) - return jsUndefined(); - WebGLGetInfo info; - switch (objectType) { - case kBuffer: - info = context.getBufferParameter(target, pname, ec); - break; - case kRenderbuffer: - info = context.getRenderbufferParameter(target, pname, ec); - break; - case kTexture: - info = context.getTexParameter(target, pname, ec); - break; - case kVertexAttrib: - // target => index - info = context.getVertexAttrib(target, pname, ec); - break; - default: - notImplemented(); - break; - } - if (ec) { - setDOMException(exec, ec); - return jsUndefined(); - } - return toJS(exec, obj->globalObject(), info); -} - -enum WhichProgramCall { - kProgramParameter, kUniform -}; - -static JSValue toJS(ExecState* exec, JSDOMGlobalObject* globalObject, WebGLExtension* extension) -{ - if (!extension) - return jsNull(); - switch (extension->getName()) { - case WebGLExtension::WebGLLoseContextName: - return toJS(exec, globalObject, static_cast<WebGLLoseContext*>(extension)); - case WebGLExtension::EXTDrawBuffersName: - return toJS(exec, globalObject, static_cast<EXTDrawBuffers*>(extension)); - case WebGLExtension::EXTTextureFilterAnisotropicName: - return toJS(exec, globalObject, static_cast<EXTTextureFilterAnisotropic*>(extension)); - case WebGLExtension::OESStandardDerivativesName: - return toJS(exec, globalObject, static_cast<OESStandardDerivatives*>(extension)); - case WebGLExtension::OESTextureFloatName: - return toJS(exec, globalObject, static_cast<OESTextureFloat*>(extension)); - case WebGLExtension::OESTextureFloatLinearName: - return toJS(exec, globalObject, static_cast<OESTextureFloatLinear*>(extension)); - case WebGLExtension::OESTextureHalfFloatName: - return toJS(exec, globalObject, static_cast<OESTextureHalfFloat*>(extension)); - case WebGLExtension::OESTextureHalfFloatLinearName: - return toJS(exec, globalObject, static_cast<OESTextureHalfFloatLinear*>(extension)); - case WebGLExtension::OESVertexArrayObjectName: - return toJS(exec, globalObject, static_cast<OESVertexArrayObject*>(extension)); - case WebGLExtension::OESElementIndexUintName: - return toJS(exec, globalObject, static_cast<OESElementIndexUint*>(extension)); - case WebGLExtension::WebGLDebugRendererInfoName: - return toJS(exec, globalObject, static_cast<WebGLDebugRendererInfo*>(extension)); - case WebGLExtension::WebGLDebugShadersName: - return toJS(exec, globalObject, static_cast<WebGLDebugShaders*>(extension)); - case WebGLExtension::WebGLCompressedTextureATCName: - return toJS(exec, globalObject, static_cast<WebGLCompressedTextureATC*>(extension)); - case WebGLExtension::WebGLCompressedTexturePVRTCName: - return toJS(exec, globalObject, static_cast<WebGLCompressedTexturePVRTC*>(extension)); - case WebGLExtension::WebGLCompressedTextureS3TCName: - return toJS(exec, globalObject, static_cast<WebGLCompressedTextureS3TC*>(extension)); - case WebGLExtension::WebGLDepthTextureName: - return toJS(exec, globalObject, static_cast<WebGLDepthTexture*>(extension)); - case WebGLExtension::ANGLEInstancedArraysName: - return toJS(exec, globalObject, static_cast<ANGLEInstancedArrays*>(extension)); - } - ASSERT_NOT_REACHED(); - return jsNull(); -} - -void JSWebGLRenderingContext::visitChildren(JSCell* cell, SlotVisitor& visitor) -{ - JSWebGLRenderingContext* thisObject = jsCast<JSWebGLRenderingContext*>(cell); - ASSERT_GC_OBJECT_INHERITS(thisObject, info()); - COMPILE_ASSERT(StructureFlags & OverridesVisitChildren, OverridesVisitChildrenWithoutSettingFlag); - ASSERT(thisObject->structure()->typeInfo().overridesVisitChildren()); - Base::visitChildren(thisObject, visitor); - visitor.addOpaqueRoot(&thisObject->impl()); -} - -JSValue JSWebGLRenderingContext::getAttachedShaders(ExecState* exec) -{ - if (exec->argumentCount() < 1) - return exec->vm().throwException(exec, createNotEnoughArgumentsError(exec)); - ExceptionCode ec = 0; - WebGLRenderingContext& context = impl(); - WebGLProgram* program = toWebGLProgram(exec->uncheckedArgument(0)); - if (!program && !exec->uncheckedArgument(0).isUndefinedOrNull()) - return throwTypeError(exec); - Vector<RefPtr<WebGLShader>> shaders; - bool succeed = context.getAttachedShaders(program, shaders, ec); - if (ec) { - setDOMException(exec, ec); - return jsNull(); - } - if (!succeed) - return jsNull(); - MarkedArgumentBuffer list; - for (size_t ii = 0; ii < shaders.size(); ++ii) - list.append(toJS(exec, globalObject(), shaders[ii].get())); - return constructArray(exec, 0, globalObject(), list); -} - -JSValue JSWebGLRenderingContext::getExtension(ExecState* exec) -{ - if (exec->argumentCount() < 1) - return exec->vm().throwException(exec, createNotEnoughArgumentsError(exec)); - - WebGLRenderingContext& context = impl(); - const String name = exec->uncheckedArgument(0).toString(exec)->value(exec); - if (exec->hadException()) - return jsUndefined(); - WebGLExtension* extension = context.getExtension(name); - return toJS(exec, globalObject(), extension); -} - -JSValue JSWebGLRenderingContext::getBufferParameter(ExecState* exec) -{ - return getObjectParameter(this, exec, kBuffer); -} - -JSValue JSWebGLRenderingContext::getFramebufferAttachmentParameter(ExecState* exec) -{ - if (exec->argumentCount() != 3) - return exec->vm().throwException(exec, createNotEnoughArgumentsError(exec)); - - ExceptionCode ec = 0; - WebGLRenderingContext& context = impl(); - unsigned target = exec->uncheckedArgument(0).toInt32(exec); - if (exec->hadException()) - return jsUndefined(); - unsigned attachment = exec->uncheckedArgument(1).toInt32(exec); - if (exec->hadException()) - return jsUndefined(); - unsigned pname = exec->uncheckedArgument(2).toInt32(exec); - if (exec->hadException()) - return jsUndefined(); - WebGLGetInfo info = context.getFramebufferAttachmentParameter(target, attachment, pname, ec); - if (ec) { - setDOMException(exec, ec); - return jsUndefined(); - } - return toJS(exec, globalObject(), info); -} - -JSValue JSWebGLRenderingContext::getParameter(ExecState* exec) -{ - if (exec->argumentCount() != 1) - return exec->vm().throwException(exec, createNotEnoughArgumentsError(exec)); - - ExceptionCode ec = 0; - WebGLRenderingContext& context = impl(); - unsigned pname = exec->uncheckedArgument(0).toInt32(exec); - if (exec->hadException()) - return jsUndefined(); - WebGLGetInfo info = context.getParameter(pname, ec); - if (ec) { - setDOMException(exec, ec); - return jsUndefined(); - } - return toJS(exec, globalObject(), info); -} - -JSValue JSWebGLRenderingContext::getProgramParameter(ExecState* exec) -{ - if (exec->argumentCount() != 2) - return exec->vm().throwException(exec, createNotEnoughArgumentsError(exec)); - - ExceptionCode ec = 0; - WebGLRenderingContext& context = impl(); - WebGLProgram* program = toWebGLProgram(exec->uncheckedArgument(0)); - if (!program && !exec->uncheckedArgument(0).isUndefinedOrNull()) - return throwTypeError(exec); - unsigned pname = exec->uncheckedArgument(1).toInt32(exec); - if (exec->hadException()) - return jsUndefined(); - WebGLGetInfo info = context.getProgramParameter(program, pname, ec); - if (ec) { - setDOMException(exec, ec); - return jsUndefined(); - } - return toJS(exec, globalObject(), info); -} - -JSValue JSWebGLRenderingContext::getRenderbufferParameter(ExecState* exec) -{ - return getObjectParameter(this, exec, kRenderbuffer); -} - -JSValue JSWebGLRenderingContext::getShaderParameter(ExecState* exec) -{ - if (exec->argumentCount() != 2) - return exec->vm().throwException(exec, createNotEnoughArgumentsError(exec)); - - ExceptionCode ec = 0; - WebGLRenderingContext& context = impl(); - if (!exec->uncheckedArgument(0).isUndefinedOrNull() && !exec->uncheckedArgument(0).inherits(JSWebGLShader::info())) - return throwTypeError(exec); - WebGLShader* shader = toWebGLShader(exec->uncheckedArgument(0)); - unsigned pname = exec->uncheckedArgument(1).toInt32(exec); - if (exec->hadException()) - return jsUndefined(); - WebGLGetInfo info = context.getShaderParameter(shader, pname, ec); - if (ec) { - setDOMException(exec, ec); - return jsUndefined(); - } - return toJS(exec, globalObject(), info); -} - -JSValue JSWebGLRenderingContext::getSupportedExtensions(ExecState* exec) -{ - WebGLRenderingContext& context = impl(); - if (context.isContextLost()) - return jsNull(); - Vector<String> value = context.getSupportedExtensions(); - MarkedArgumentBuffer list; - for (size_t ii = 0; ii < value.size(); ++ii) - list.append(jsStringWithCache(exec, value[ii])); - return constructArray(exec, 0, globalObject(), list); -} - -JSValue JSWebGLRenderingContext::getTexParameter(ExecState* exec) -{ - return getObjectParameter(this, exec, kTexture); -} - -JSValue JSWebGLRenderingContext::getUniform(ExecState* exec) -{ - if (exec->argumentCount() != 2) - return exec->vm().throwException(exec, createNotEnoughArgumentsError(exec)); - - ExceptionCode ec = 0; - WebGLRenderingContext& context = impl(); - WebGLProgram* program = toWebGLProgram(exec->uncheckedArgument(0)); - if (!program && !exec->uncheckedArgument(0).isUndefinedOrNull()) - return throwTypeError(exec); - WebGLUniformLocation* location = toWebGLUniformLocation(exec->uncheckedArgument(1)); - if (!location && !exec->uncheckedArgument(1).isUndefinedOrNull()) - return throwTypeError(exec); - WebGLGetInfo info = context.getUniform(program, location, ec); - if (ec) { - setDOMException(exec, ec); - return jsUndefined(); - } - return toJS(exec, globalObject(), info); -} - -JSValue JSWebGLRenderingContext::getVertexAttrib(ExecState* exec) -{ - return getObjectParameter(this, exec, kVertexAttrib); -} - -template<typename T, size_t inlineCapacity> -bool toVector(JSC::ExecState* exec, JSC::JSValue value, Vector<T, inlineCapacity>& vector) -{ - if (!value.isObject()) - return false; - - JSC::JSObject* object = asObject(value); - int32_t length = object->get(exec, exec->vm().propertyNames->length).toInt32(exec); - - if (!vector.tryReserveCapacity(length)) - return false; - vector.resize(length); - - for (int32_t i = 0; i < length; ++i) { - JSC::JSValue v = object->get(exec, i); - if (exec->hadException()) - return false; - vector[i] = static_cast<T>(v.toNumber(exec)); - } - - return true; -} - -enum DataFunctionToCall { - f_uniform1v, f_uniform2v, f_uniform3v, f_uniform4v, - f_vertexAttrib1v, f_vertexAttrib2v, f_vertexAttrib3v, f_vertexAttrib4v -}; - -enum DataFunctionMatrixToCall { - f_uniformMatrix2fv, f_uniformMatrix3fv, f_uniformMatrix4fv -}; - -static bool functionForUniform(DataFunctionToCall f) -{ - switch (f) { - case f_uniform1v: - case f_uniform2v: - case f_uniform3v: - case f_uniform4v: - return true; - break; - default: break; - } - return false; -} - -static JSC::JSValue dataFunctionf(DataFunctionToCall f, JSC::ExecState* exec, WebGLRenderingContext& context) -{ - if (exec->argumentCount() != 2) - return exec->vm().throwException(exec, createNotEnoughArgumentsError(exec)); - - WebGLUniformLocation* location = 0; - long index = -1; - - if (functionForUniform(f)) { - location = toWebGLUniformLocation(exec->uncheckedArgument(0)); - if (!location && !exec->uncheckedArgument(0).isUndefinedOrNull()) - return throwTypeError(exec); - } else - index = exec->uncheckedArgument(0).toInt32(exec); - - if (exec->hadException()) - return jsUndefined(); - - RefPtr<Float32Array> webGLArray = toFloat32Array(exec->uncheckedArgument(1)); - if (exec->hadException()) - return jsUndefined(); - - ExceptionCode ec = 0; - if (webGLArray) { - switch (f) { - case f_uniform1v: - context.uniform1fv(location, webGLArray.get(), ec); - break; - case f_uniform2v: - context.uniform2fv(location, webGLArray.get(), ec); - break; - case f_uniform3v: - context.uniform3fv(location, webGLArray.get(), ec); - break; - case f_uniform4v: - context.uniform4fv(location, webGLArray.get(), ec); - break; - case f_vertexAttrib1v: - context.vertexAttrib1fv(index, webGLArray.get()); - break; - case f_vertexAttrib2v: - context.vertexAttrib2fv(index, webGLArray.get()); - break; - case f_vertexAttrib3v: - context.vertexAttrib3fv(index, webGLArray.get()); - break; - case f_vertexAttrib4v: - context.vertexAttrib4fv(index, webGLArray.get()); - break; - } - - setDOMException(exec, ec); - return jsUndefined(); - } - - Vector<float, 64> array; - if (!toVector(exec, exec->uncheckedArgument(1), array)) - return throwTypeError(exec); - - switch (f) { - case f_uniform1v: - context.uniform1fv(location, array.data(), array.size(), ec); - break; - case f_uniform2v: - context.uniform2fv(location, array.data(), array.size(), ec); - break; - case f_uniform3v: - context.uniform3fv(location, array.data(), array.size(), ec); - break; - case f_uniform4v: - context.uniform4fv(location, array.data(), array.size(), ec); - break; - case f_vertexAttrib1v: - context.vertexAttrib1fv(index, array.data(), array.size()); - break; - case f_vertexAttrib2v: - context.vertexAttrib2fv(index, array.data(), array.size()); - break; - case f_vertexAttrib3v: - context.vertexAttrib3fv(index, array.data(), array.size()); - break; - case f_vertexAttrib4v: - context.vertexAttrib4fv(index, array.data(), array.size()); - break; - } - - setDOMException(exec, ec); - return jsUndefined(); -} - -static JSC::JSValue dataFunctioni(DataFunctionToCall f, JSC::ExecState* exec, WebGLRenderingContext& context) -{ - if (exec->argumentCount() != 2) - return exec->vm().throwException(exec, createNotEnoughArgumentsError(exec)); - - WebGLUniformLocation* location = toWebGLUniformLocation(exec->uncheckedArgument(0)); - if (!location && !exec->uncheckedArgument(0).isUndefinedOrNull()) - return throwTypeError(exec); - - RefPtr<Int32Array> webGLArray = toInt32Array(exec->uncheckedArgument(1)); - - ExceptionCode ec = 0; - if (webGLArray) { - switch (f) { - case f_uniform1v: - context.uniform1iv(location, webGLArray.get(), ec); - break; - case f_uniform2v: - context.uniform2iv(location, webGLArray.get(), ec); - break; - case f_uniform3v: - context.uniform3iv(location, webGLArray.get(), ec); - break; - case f_uniform4v: - context.uniform4iv(location, webGLArray.get(), ec); - break; - default: - break; - } - - setDOMException(exec, ec); - return jsUndefined(); - } - - - Vector<int, 64> array; - if (!toVector(exec, exec->uncheckedArgument(1), array)) - return throwTypeError(exec); - - switch (f) { - case f_uniform1v: - context.uniform1iv(location, array.data(), array.size(), ec); - break; - case f_uniform2v: - context.uniform2iv(location, array.data(), array.size(), ec); - break; - case f_uniform3v: - context.uniform3iv(location, array.data(), array.size(), ec); - break; - case f_uniform4v: - context.uniform4iv(location, array.data(), array.size(), ec); - break; - default: - break; - } - - setDOMException(exec, ec); - return jsUndefined(); -} - -static JSC::JSValue dataFunctionMatrix(DataFunctionMatrixToCall f, JSC::ExecState* exec, WebGLRenderingContext& context) -{ - if (exec->argumentCount() != 3) - return exec->vm().throwException(exec, createNotEnoughArgumentsError(exec)); - - WebGLUniformLocation* location = toWebGLUniformLocation(exec->uncheckedArgument(0)); - if (!location && !exec->uncheckedArgument(0).isUndefinedOrNull()) - return throwTypeError(exec); - - bool transpose = exec->uncheckedArgument(1).toBoolean(exec); - if (exec->hadException()) - return jsUndefined(); - - RefPtr<Float32Array> webGLArray = toFloat32Array(exec->uncheckedArgument(2)); - - ExceptionCode ec = 0; - if (webGLArray) { - switch (f) { - case f_uniformMatrix2fv: - context.uniformMatrix2fv(location, transpose, webGLArray.get(), ec); - break; - case f_uniformMatrix3fv: - context.uniformMatrix3fv(location, transpose, webGLArray.get(), ec); - break; - case f_uniformMatrix4fv: - context.uniformMatrix4fv(location, transpose, webGLArray.get(), ec); - break; - } - - setDOMException(exec, ec); - return jsUndefined(); - } - - Vector<float, 64> array; - if (!toVector(exec, exec->uncheckedArgument(2), array)) - return throwTypeError(exec); - - switch (f) { - case f_uniformMatrix2fv: - context.uniformMatrix2fv(location, transpose, array.data(), array.size(), ec); - break; - case f_uniformMatrix3fv: - context.uniformMatrix3fv(location, transpose, array.data(), array.size(), ec); - break; - case f_uniformMatrix4fv: - context.uniformMatrix4fv(location, transpose, array.data(), array.size(), ec); - break; - } - - setDOMException(exec, ec); - return jsUndefined(); -} - -JSC::JSValue JSWebGLRenderingContext::uniform1fv(JSC::ExecState* exec) -{ - return dataFunctionf(f_uniform1v, exec, impl()); -} - -JSC::JSValue JSWebGLRenderingContext::uniform1iv(JSC::ExecState* exec) -{ - return dataFunctioni(f_uniform1v, exec, impl()); -} - -JSC::JSValue JSWebGLRenderingContext::uniform2fv(JSC::ExecState* exec) -{ - return dataFunctionf(f_uniform2v, exec, impl()); -} - -JSC::JSValue JSWebGLRenderingContext::uniform2iv(JSC::ExecState* exec) -{ - return dataFunctioni(f_uniform2v, exec, impl()); -} - -JSC::JSValue JSWebGLRenderingContext::uniform3fv(JSC::ExecState* exec) -{ - return dataFunctionf(f_uniform3v, exec, impl()); -} - -JSC::JSValue JSWebGLRenderingContext::uniform3iv(JSC::ExecState* exec) -{ - return dataFunctioni(f_uniform3v, exec, impl()); -} - -JSC::JSValue JSWebGLRenderingContext::uniform4fv(JSC::ExecState* exec) -{ - return dataFunctionf(f_uniform4v, exec, impl()); -} - -JSC::JSValue JSWebGLRenderingContext::uniform4iv(JSC::ExecState* exec) -{ - return dataFunctioni(f_uniform4v, exec, impl()); -} - -JSC::JSValue JSWebGLRenderingContext::uniformMatrix2fv(JSC::ExecState* exec) -{ - return dataFunctionMatrix(f_uniformMatrix2fv, exec, impl()); -} - -JSC::JSValue JSWebGLRenderingContext::uniformMatrix3fv(JSC::ExecState* exec) -{ - return dataFunctionMatrix(f_uniformMatrix3fv, exec, impl()); -} - -JSC::JSValue JSWebGLRenderingContext::uniformMatrix4fv(JSC::ExecState* exec) -{ - return dataFunctionMatrix(f_uniformMatrix4fv, exec, impl()); -} - -JSC::JSValue JSWebGLRenderingContext::vertexAttrib1fv(JSC::ExecState* exec) -{ - return dataFunctionf(f_vertexAttrib1v, exec, impl()); -} - -JSC::JSValue JSWebGLRenderingContext::vertexAttrib2fv(JSC::ExecState* exec) -{ - return dataFunctionf(f_vertexAttrib2v, exec, impl()); -} - -JSC::JSValue JSWebGLRenderingContext::vertexAttrib3fv(JSC::ExecState* exec) -{ - return dataFunctionf(f_vertexAttrib3v, exec, impl()); -} - -JSC::JSValue JSWebGLRenderingContext::vertexAttrib4fv(JSC::ExecState* exec) +void JSWebGLRenderingContext::visitAdditionalChildren(SlotVisitor& visitor) { - return dataFunctionf(f_vertexAttrib4v, exec, impl()); + visitor.addOpaqueRoot(&wrapped()); } } // namespace WebCore diff --git a/Source/WebCore/bindings/js/JSWebKitPointCustom.cpp b/Source/WebCore/bindings/js/JSWebKitPointCustom.cpp deleted file mode 100644 index 7ef129103..000000000 --- a/Source/WebCore/bindings/js/JSWebKitPointCustom.cpp +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright (C) 2009, 2010 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" -#include "JSWebKitPoint.h" - -#include "WebKitPoint.h" - -using namespace JSC; - -namespace WebCore { - -EncodedJSValue JSC_HOST_CALL JSWebKitPointConstructor::constructJSWebKitPoint(ExecState* exec) -{ - JSWebKitPointConstructor* jsConstructor = jsCast<JSWebKitPointConstructor*>(exec->callee()); - - float x = 0; - float y = 0; - if (exec->argumentCount() >= 2) { - x = static_cast<float>(exec->argument(0).toNumber(exec)); - y = static_cast<float>(exec->argument(1).toNumber(exec)); - if (std::isnan(x)) - x = 0; - if (std::isnan(y)) - y = 0; - } - return JSValue::encode(asObject(toJS(exec, jsConstructor->globalObject(), WebKitPoint::create(x, y)))); -} - -} // namespace WebCore diff --git a/Source/WebCore/bindings/js/JSWebKitSubtleCryptoCustom.cpp b/Source/WebCore/bindings/js/JSWebKitSubtleCryptoCustom.cpp new file mode 100644 index 000000000..638b37e4a --- /dev/null +++ b/Source/WebCore/bindings/js/JSWebKitSubtleCryptoCustom.cpp @@ -0,0 +1,705 @@ +/* + * Copyright (C) 2013, 2016 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "JSWebKitSubtleCrypto.h" + +#if ENABLE(SUBTLE_CRYPTO) + +#include "CryptoAlgorithm.h" +#include "CryptoAlgorithmParametersDeprecated.h" +#include "CryptoAlgorithmRegistry.h" +#include "CryptoKeyData.h" +#include "CryptoKeySerializationRaw.h" +#include "Document.h" +#include "ExceptionCode.h" +#include "JSCryptoAlgorithmDictionary.h" +#include "JSCryptoKey.h" +#include "JSCryptoKeyPair.h" +#include "JSCryptoKeySerializationJWK.h" +#include "JSCryptoOperationData.h" +#include "JSDOMPromise.h" +#include "ScriptState.h" +#include <runtime/Error.h> + +using namespace JSC; + +namespace WebCore { + +enum class CryptoKeyFormat { + // An unformatted sequence of bytes. Intended for secret keys. + Raw, + + // The DER encoding of the PrivateKeyInfo structure from RFC 5208. + PKCS8, + + // The DER encoding of the SubjectPublicKeyInfo structure from RFC 5280. + SPKI, + + // The key is represented as JSON according to the JSON Web Key format. + JWK +}; + +static RefPtr<CryptoAlgorithm> createAlgorithmFromJSValue(ExecState& state, ThrowScope& scope, JSValue value) +{ + auto algorithmIdentifier = JSCryptoAlgorithmDictionary::parseAlgorithmIdentifier(state, scope, value); + RETURN_IF_EXCEPTION(scope, { }); + + auto result = CryptoAlgorithmRegistry::singleton().create(algorithmIdentifier); + if (!result) + throwNotSupportedError(state, scope); + + return result; +} + +static CryptoKeyFormat cryptoKeyFormatFromJSValue(ExecState& state, ThrowScope& scope, JSValue value) +{ + auto keyFormatString = value.toWTFString(&state); + RETURN_IF_EXCEPTION(scope, { }); + + if (keyFormatString == "raw") + return CryptoKeyFormat::Raw; + if (keyFormatString == "pkcs8") + return CryptoKeyFormat::PKCS8; + if (keyFormatString == "spki") + return CryptoKeyFormat::SPKI; + if (keyFormatString == "jwk") + return CryptoKeyFormat::JWK; + + throwTypeError(&state, scope, ASCIILiteral("Unknown key format")); + return { }; +} + +static CryptoKeyUsageBitmap cryptoKeyUsagesFromJSValue(ExecState& state, ThrowScope& scope, JSValue value) +{ + if (!isJSArray(value)) { + throwTypeError(&state, scope); + return { }; + } + + CryptoKeyUsageBitmap result = 0; + JSArray* array = asArray(value); + for (unsigned i = 0; i < array->length(); ++i) { + auto usageString = array->getIndex(&state, i).toWTFString(&state); + RETURN_IF_EXCEPTION(scope, { }); + if (usageString == "encrypt") + result |= CryptoKeyUsageEncrypt; + else if (usageString == "decrypt") + result |= CryptoKeyUsageDecrypt; + else if (usageString == "sign") + result |= CryptoKeyUsageSign; + else if (usageString == "verify") + result |= CryptoKeyUsageVerify; + else if (usageString == "deriveKey") + result |= CryptoKeyUsageDeriveKey; + else if (usageString == "deriveBits") + result |= CryptoKeyUsageDeriveBits; + else if (usageString == "wrapKey") + result |= CryptoKeyUsageWrapKey; + else if (usageString == "unwrapKey") + result |= CryptoKeyUsageUnwrapKey; + } + return result; +} + +JSValue JSWebKitSubtleCrypto::encrypt(ExecState& state) +{ + VM& vm = state.vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + + if (state.argumentCount() < 3) + return throwException(&state, scope, createNotEnoughArgumentsError(&state)); + + auto algorithm = createAlgorithmFromJSValue(state, scope, state.uncheckedArgument(0)); + RETURN_IF_EXCEPTION(scope, { }); + + auto parameters = JSCryptoAlgorithmDictionary::createParametersForEncrypt(state, scope, algorithm->identifier(), state.uncheckedArgument(0)); + RETURN_IF_EXCEPTION(scope, { }); + + RefPtr<CryptoKey> key = JSCryptoKey::toWrapped(vm, state.uncheckedArgument(1)); + if (!key) + return throwTypeError(&state, scope); + + if (!key->allows(CryptoKeyUsageEncrypt)) { + wrapped().document()->addConsoleMessage(MessageSource::JS, MessageLevel::Error, ASCIILiteral("Key usages do not include 'encrypt'")); + throwNotSupportedError(state, scope); + return jsUndefined(); + } + + auto data = cryptoOperationDataFromJSValue(state, scope, state.uncheckedArgument(2)); + RETURN_IF_EXCEPTION(scope, { }); + + RefPtr<DeferredPromise> wrapper = createDeferredPromise(state, domWindow()); + auto promise = wrapper->promise(); + auto successCallback = [wrapper](const Vector<uint8_t>& result) mutable { + fulfillPromiseWithArrayBuffer(wrapper.releaseNonNull(), result.data(), result.size()); + }; + auto failureCallback = [wrapper]() mutable { + wrapper->reject(); // FIXME: This should reject with an Exception. + }; + + auto result = algorithm->encrypt(*parameters, *key, data, WTFMove(successCallback), WTFMove(failureCallback)); + if (result.hasException()) { + propagateException(state, scope, result.releaseException()); + return { }; + } + + return promise; +} + +JSValue JSWebKitSubtleCrypto::decrypt(ExecState& state) +{ + VM& vm = state.vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + + if (state.argumentCount() < 3) + return throwException(&state, scope, createNotEnoughArgumentsError(&state)); + + auto algorithm = createAlgorithmFromJSValue(state, scope, state.uncheckedArgument(0)); + RETURN_IF_EXCEPTION(scope, { }); + + auto parameters = JSCryptoAlgorithmDictionary::createParametersForDecrypt(state, scope, algorithm->identifier(), state.uncheckedArgument(0)); + RETURN_IF_EXCEPTION(scope, { }); + + RefPtr<CryptoKey> key = JSCryptoKey::toWrapped(vm, state.uncheckedArgument(1)); + if (!key) + return throwTypeError(&state, scope); + + if (!key->allows(CryptoKeyUsageDecrypt)) { + wrapped().document()->addConsoleMessage(MessageSource::JS, MessageLevel::Error, ASCIILiteral("Key usages do not include 'decrypt'")); + throwNotSupportedError(state, scope); + return jsUndefined(); + } + + auto data = cryptoOperationDataFromJSValue(state, scope, state.uncheckedArgument(2)); + RETURN_IF_EXCEPTION(scope, { }); + + RefPtr<DeferredPromise> wrapper = createDeferredPromise(state, domWindow()); + auto promise = wrapper->promise(); + auto successCallback = [wrapper](const Vector<uint8_t>& result) mutable { + fulfillPromiseWithArrayBuffer(wrapper.releaseNonNull(), result.data(), result.size()); + }; + auto failureCallback = [wrapper]() mutable { + wrapper->reject(); // FIXME: This should reject with an Exception. + }; + + auto result = algorithm->decrypt(*parameters, *key, data, WTFMove(successCallback), WTFMove(failureCallback)); + if (result.hasException()) { + propagateException(state, scope, result.releaseException()); + return { }; + } + + return promise; +} + +JSValue JSWebKitSubtleCrypto::sign(ExecState& state) +{ + VM& vm = state.vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + + if (state.argumentCount() < 3) + return throwException(&state, scope, createNotEnoughArgumentsError(&state)); + + auto algorithm = createAlgorithmFromJSValue(state, scope, state.uncheckedArgument(0)); + RETURN_IF_EXCEPTION(scope, { }); + + auto parameters = JSCryptoAlgorithmDictionary::createParametersForSign(state, scope, algorithm->identifier(), state.uncheckedArgument(0)); + RETURN_IF_EXCEPTION(scope, { }); + + RefPtr<CryptoKey> key = JSCryptoKey::toWrapped(vm, state.uncheckedArgument(1)); + if (!key) + return throwTypeError(&state, scope); + + if (!key->allows(CryptoKeyUsageSign)) { + wrapped().document()->addConsoleMessage(MessageSource::JS, MessageLevel::Error, ASCIILiteral("Key usages do not include 'sign'")); + throwNotSupportedError(state, scope); + return jsUndefined(); + } + + auto data = cryptoOperationDataFromJSValue(state, scope, state.uncheckedArgument(2)); + RETURN_IF_EXCEPTION(scope, { }); + + RefPtr<DeferredPromise> wrapper = createDeferredPromise(state, domWindow()); + auto promise = wrapper->promise(); + auto successCallback = [wrapper](const Vector<uint8_t>& result) mutable { + fulfillPromiseWithArrayBuffer(wrapper.releaseNonNull(), result.data(), result.size()); + }; + auto failureCallback = [wrapper]() mutable { + wrapper->reject(); // FIXME: This should reject with an Exception. + }; + + auto result = algorithm->sign(*parameters, *key, data, WTFMove(successCallback), WTFMove(failureCallback)); + if (result.hasException()) { + propagateException(state, scope, result.releaseException()); + return { }; + } + + return promise; +} + +JSValue JSWebKitSubtleCrypto::verify(ExecState& state) +{ + VM& vm = state.vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + + if (state.argumentCount() < 4) + return throwException(&state, scope, createNotEnoughArgumentsError(&state)); + + auto algorithm = createAlgorithmFromJSValue(state, scope, state.uncheckedArgument(0)); + RETURN_IF_EXCEPTION(scope, { }); + + auto parameters = JSCryptoAlgorithmDictionary::createParametersForVerify(state, scope, algorithm->identifier(), state.uncheckedArgument(0)); + RETURN_IF_EXCEPTION(scope, { }); + + RefPtr<CryptoKey> key = JSCryptoKey::toWrapped(vm, state.uncheckedArgument(1)); + if (!key) + return throwTypeError(&state, scope); + + if (!key->allows(CryptoKeyUsageVerify)) { + wrapped().document()->addConsoleMessage(MessageSource::JS, MessageLevel::Error, ASCIILiteral("Key usages do not include 'verify'")); + throwNotSupportedError(state, scope); + return jsUndefined(); + } + + auto signature = cryptoOperationDataFromJSValue(state, scope, state.uncheckedArgument(2)); + RETURN_IF_EXCEPTION(scope, { }); + + auto data = cryptoOperationDataFromJSValue(state, scope, state.uncheckedArgument(3)); + RETURN_IF_EXCEPTION(scope, { }); + + RefPtr<DeferredPromise> wrapper = createDeferredPromise(state, domWindow()); + auto promise = wrapper->promise(); + auto successCallback = [wrapper](bool result) mutable { + wrapper->resolve<IDLBoolean>(result); + }; + auto failureCallback = [wrapper]() mutable { + wrapper->reject(); // FIXME: This should reject with an Exception. + }; + + auto result = algorithm->verify(*parameters, *key, signature, data, WTFMove(successCallback), WTFMove(failureCallback)); + if (result.hasException()) { + propagateException(state, scope, result.releaseException()); + return { }; + } + + return promise; +} + +JSValue JSWebKitSubtleCrypto::digest(ExecState& state) +{ + VM& vm = state.vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + + if (state.argumentCount() < 2) + return throwException(&state, scope, createNotEnoughArgumentsError(&state)); + + auto algorithm = createAlgorithmFromJSValue(state, scope, state.uncheckedArgument(0)); + RETURN_IF_EXCEPTION(scope, { }); + + auto parameters = JSCryptoAlgorithmDictionary::createParametersForDigest(state, scope, algorithm->identifier(), state.uncheckedArgument(0)); + RETURN_IF_EXCEPTION(scope, { }); + + auto data = cryptoOperationDataFromJSValue(state, scope, state.uncheckedArgument(1)); + RETURN_IF_EXCEPTION(scope, { }); + + RefPtr<DeferredPromise> wrapper = createDeferredPromise(state, domWindow()); + auto promise = wrapper->promise(); + auto successCallback = [wrapper](const Vector<uint8_t>& result) mutable { + fulfillPromiseWithArrayBuffer(wrapper.releaseNonNull(), result.data(), result.size()); + }; + auto failureCallback = [wrapper]() mutable { + wrapper->reject(); // FIXME: This should reject with an Exception. + }; + + auto result = algorithm->digest(*parameters, data, WTFMove(successCallback), WTFMove(failureCallback)); + if (result.hasException()) { + propagateException(state, scope, result.releaseException()); + return { }; + } + + return promise; +} + +JSValue JSWebKitSubtleCrypto::generateKey(ExecState& state) +{ + VM& vm = state.vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + + if (state.argumentCount() < 1) + return throwException(&state, scope, createNotEnoughArgumentsError(&state)); + + auto algorithm = createAlgorithmFromJSValue(state, scope, state.uncheckedArgument(0)); + RETURN_IF_EXCEPTION(scope, { }); + + auto parameters = JSCryptoAlgorithmDictionary::createParametersForGenerateKey(state, scope, algorithm->identifier(), state.uncheckedArgument(0)); + RETURN_IF_EXCEPTION(scope, { }); + + bool extractable = state.argument(1).toBoolean(&state); + RETURN_IF_EXCEPTION(scope, { }); + + CryptoKeyUsageBitmap keyUsages = 0; + if (state.argumentCount() >= 3) { + keyUsages = cryptoKeyUsagesFromJSValue(state, scope, state.uncheckedArgument(2)); + RETURN_IF_EXCEPTION(scope, { }); + } + + RefPtr<DeferredPromise> wrapper = createDeferredPromise(state, domWindow()); + auto promise = wrapper->promise(); + auto successCallback = [wrapper](KeyOrKeyPair&& keyOrKeyPair) mutable { + WTF::switchOn(keyOrKeyPair, + [&wrapper] (RefPtr<CryptoKey>& key) { + wrapper->resolve<IDLInterface<CryptoKey>>(*key); + }, + [&wrapper] (CryptoKeyPair& keyPair) { + wrapper->resolve<IDLDictionary<CryptoKeyPair>>(keyPair); + } + ); + }; + auto failureCallback = [wrapper]() mutable { + wrapper->reject(); // FIXME: This should reject with an Exception. + }; + + auto result = algorithm->generateKey(*parameters, extractable, keyUsages, WTFMove(successCallback), WTFMove(failureCallback), *scriptExecutionContextFromExecState(&state)); + if (result.hasException()) { + propagateException(state, scope, result.releaseException()); + return { }; + } + + return promise; +} + +static void importKey(ExecState& state, CryptoKeyFormat keyFormat, CryptoOperationData data, RefPtr<CryptoAlgorithm> algorithm, RefPtr<CryptoAlgorithmParametersDeprecated> parameters, bool extractable, CryptoKeyUsageBitmap keyUsages, CryptoAlgorithm::KeyCallback callback, CryptoAlgorithm::VoidCallback failureCallback) +{ + VM& vm = state.vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + + std::unique_ptr<CryptoKeySerialization> keySerialization; + switch (keyFormat) { + case CryptoKeyFormat::Raw: + keySerialization = CryptoKeySerializationRaw::create(data); + break; + case CryptoKeyFormat::JWK: { + String jwkString = String::fromUTF8(data.first, data.second); + if (jwkString.isNull()) { + throwTypeError(&state, scope, ASCIILiteral("JWK JSON serialization is not valid UTF-8")); + return; + } + keySerialization = std::make_unique<JSCryptoKeySerializationJWK>(&state, jwkString); + RETURN_IF_EXCEPTION(scope, void()); + break; + } + default: + throwTypeError(&state, scope, ASCIILiteral("Unsupported key format for import")); + return; + } + + ASSERT(keySerialization); + + std::optional<CryptoAlgorithmPair> reconciledResult = keySerialization->reconcileAlgorithm(algorithm.get(), parameters.get()); + if (!reconciledResult) { + if (!scope.exception()) + throwTypeError(&state, scope, ASCIILiteral("Algorithm specified in key is not compatible with one passed to importKey as argument")); + return; + } + RETURN_IF_EXCEPTION(scope, void()); + + algorithm = reconciledResult->algorithm; + parameters = reconciledResult->parameters; + if (!algorithm) { + throwTypeError(&state, scope, ASCIILiteral("Neither key nor function argument has crypto algorithm specified")); + return; + } + ASSERT(parameters); + + keySerialization->reconcileExtractable(extractable); + RETURN_IF_EXCEPTION(scope, void()); + + keySerialization->reconcileUsages(keyUsages); + RETURN_IF_EXCEPTION(scope, void()); + + auto keyData = keySerialization->keyData(); + RETURN_IF_EXCEPTION(scope, void()); + + propagateException(state, scope, algorithm->importKey(*parameters, *keyData, extractable, keyUsages, WTFMove(callback), WTFMove(failureCallback))); +} + +JSValue JSWebKitSubtleCrypto::importKey(ExecState& state) +{ + VM& vm = state.vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + + if (state.argumentCount() < 3) + return throwException(&state, scope, createNotEnoughArgumentsError(&state)); + + auto keyFormat = cryptoKeyFormatFromJSValue(state, scope, state.uncheckedArgument(0)); + RETURN_IF_EXCEPTION(scope, { }); + + auto data = cryptoOperationDataFromJSValue(state, scope, state.uncheckedArgument(1)); + RETURN_IF_EXCEPTION(scope, { }); + + RefPtr<CryptoAlgorithm> algorithm; + RefPtr<CryptoAlgorithmParametersDeprecated> parameters; + if (!state.uncheckedArgument(2).isNull()) { + algorithm = createAlgorithmFromJSValue(state, scope, state.uncheckedArgument(2)); + RETURN_IF_EXCEPTION(scope, { }); + + parameters = JSCryptoAlgorithmDictionary::createParametersForImportKey(state, scope, algorithm->identifier(), state.uncheckedArgument(2)); + RETURN_IF_EXCEPTION(scope, { }); + } + + bool extractable = state.argument(3).toBoolean(&state); + RETURN_IF_EXCEPTION(scope, JSValue()); + + CryptoKeyUsageBitmap keyUsages = 0; + if (state.argumentCount() >= 5) { + keyUsages = cryptoKeyUsagesFromJSValue(state, scope, state.uncheckedArgument(4)); + RETURN_IF_EXCEPTION(scope, { }); + } + + RefPtr<DeferredPromise> wrapper = createDeferredPromise(state, domWindow()); + auto promise = wrapper->promise(); + auto successCallback = [wrapper](CryptoKey& result) mutable { + wrapper->resolve<IDLInterface<CryptoKey>>(result); + }; + auto failureCallback = [wrapper]() mutable { + wrapper->reject(); // FIXME: This should reject with an Exception. + }; + + WebCore::importKey(state, keyFormat, data, WTFMove(algorithm), WTFMove(parameters), extractable, keyUsages, WTFMove(successCallback), WTFMove(failureCallback)); + RETURN_IF_EXCEPTION(scope, JSValue()); + + return promise; +} + +static void exportKey(ExecState& state, CryptoKeyFormat keyFormat, const CryptoKey& key, CryptoAlgorithm::VectorCallback callback, CryptoAlgorithm::VoidCallback failureCallback) +{ + VM& vm = state.vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + + if (!key.extractable()) { + throwTypeError(&state, scope, ASCIILiteral("Key is not extractable")); + return; + } + + switch (keyFormat) { + case CryptoKeyFormat::Raw: { + Vector<uint8_t> result; + if (CryptoKeySerializationRaw::serialize(key, result)) + callback(result); + else + failureCallback(); + break; + } + case CryptoKeyFormat::JWK: { + String result = JSCryptoKeySerializationJWK::serialize(&state, key); + RETURN_IF_EXCEPTION(scope, void()); + CString utf8String = result.utf8(StrictConversion); + Vector<uint8_t> resultBuffer; + resultBuffer.append(utf8String.data(), utf8String.length()); + callback(resultBuffer); + break; + } + default: + throwTypeError(&state, scope, ASCIILiteral("Unsupported key format for export")); + break; + } +} + +JSValue JSWebKitSubtleCrypto::exportKey(ExecState& state) +{ + VM& vm = state.vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + + if (state.argumentCount() < 2) + return throwException(&state, scope, createNotEnoughArgumentsError(&state)); + + auto keyFormat = cryptoKeyFormatFromJSValue(state, scope, state.uncheckedArgument(0)); + RETURN_IF_EXCEPTION(scope, { }); + + RefPtr<CryptoKey> key = JSCryptoKey::toWrapped(vm, state.uncheckedArgument(1)); + if (!key) + return throwTypeError(&state, scope); + + RefPtr<DeferredPromise> wrapper = createDeferredPromise(state, domWindow()); + auto promise = wrapper->promise(); + auto successCallback = [wrapper](const Vector<uint8_t>& result) mutable { + fulfillPromiseWithArrayBuffer(wrapper.releaseNonNull(), result.data(), result.size()); + }; + auto failureCallback = [wrapper]() mutable { + wrapper->reject(); // FIXME: This should reject with an Exception. + }; + + WebCore::exportKey(state, keyFormat, *key, WTFMove(successCallback), WTFMove(failureCallback)); + RETURN_IF_EXCEPTION(scope, JSValue()); + + return promise; +} + +JSValue JSWebKitSubtleCrypto::wrapKey(ExecState& state) +{ + VM& vm = state.vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + + if (state.argumentCount() < 4) + return throwException(&state, scope, createNotEnoughArgumentsError(&state)); + + auto keyFormat = cryptoKeyFormatFromJSValue(state, scope, state.uncheckedArgument(0)); + RETURN_IF_EXCEPTION(scope, { }); + + RefPtr<CryptoKey> key = JSCryptoKey::toWrapped(vm, state.uncheckedArgument(1)); + if (!key) + return throwTypeError(&state, scope); + + RefPtr<CryptoKey> wrappingKey = JSCryptoKey::toWrapped(vm, state.uncheckedArgument(2)); + if (!key) + return throwTypeError(&state, scope); + + if (!wrappingKey->allows(CryptoKeyUsageWrapKey)) { + wrapped().document()->addConsoleMessage(MessageSource::JS, MessageLevel::Error, ASCIILiteral("Key usages do not include 'wrapKey'")); + throwNotSupportedError(state, scope); + return jsUndefined(); + } + + auto algorithm = createAlgorithmFromJSValue(state, scope, state.uncheckedArgument(3)); + RETURN_IF_EXCEPTION(scope, { }); + + auto parameters = JSCryptoAlgorithmDictionary::createParametersForEncrypt(state, scope, algorithm->identifier(), state.uncheckedArgument(3)); + RETURN_IF_EXCEPTION(scope, { }); + + RefPtr<DeferredPromise> wrapper = createDeferredPromise(state, domWindow()); + auto promise = wrapper->promise(); + + auto exportSuccessCallback = [keyFormat, algorithm, parameters, wrappingKey, wrapper](const Vector<uint8_t>& exportedKeyData) mutable { + auto encryptSuccessCallback = [wrapper](const Vector<uint8_t>& encryptedData) mutable { + fulfillPromiseWithArrayBuffer(wrapper.releaseNonNull(), encryptedData.data(), encryptedData.size()); + }; + auto encryptFailureCallback = [wrapper]() mutable { + wrapper->reject(); // FIXME: This should reject with an Exception. + }; + auto result = algorithm->encryptForWrapKey(*parameters, *wrappingKey, std::make_pair(exportedKeyData.data(), exportedKeyData.size()), WTFMove(encryptSuccessCallback), WTFMove(encryptFailureCallback)); + if (result.hasException()) { + // FIXME: Report failure details to console, and possibly to calling script once there is a standardized way to pass errors to WebCrypto promise reject functions. + wrapper->reject(); // FIXME: This should reject with an Exception. + } + }; + + auto exportFailureCallback = [wrapper]() mutable { + wrapper->reject(); // FIXME: This should reject with an Exception. + }; + + WebCore::exportKey(state, keyFormat, *key, WTFMove(exportSuccessCallback), WTFMove(exportFailureCallback)); + + return promise; +} + +JSValue JSWebKitSubtleCrypto::unwrapKey(ExecState& state) +{ + VM& vm = state.vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + + if (state.argumentCount() < 5) + return throwException(&state, scope, createNotEnoughArgumentsError(&state)); + + auto keyFormat = cryptoKeyFormatFromJSValue(state, scope, state.uncheckedArgument(0)); + RETURN_IF_EXCEPTION(scope, { }); + + auto wrappedKeyData = cryptoOperationDataFromJSValue(state, scope, state.uncheckedArgument(1)); + RETURN_IF_EXCEPTION(scope, { }); + + RefPtr<CryptoKey> unwrappingKey = JSCryptoKey::toWrapped(vm, state.uncheckedArgument(2)); + if (!unwrappingKey) + return throwTypeError(&state, scope); + + if (!unwrappingKey->allows(CryptoKeyUsageUnwrapKey)) { + wrapped().document()->addConsoleMessage(MessageSource::JS, MessageLevel::Error, ASCIILiteral("Key usages do not include 'unwrapKey'")); + throwNotSupportedError(state, scope); + return jsUndefined(); + } + + auto unwrapAlgorithm = createAlgorithmFromJSValue(state, scope, state.uncheckedArgument(3)); + RETURN_IF_EXCEPTION(scope, { }); + + auto unwrapAlgorithmParameters = JSCryptoAlgorithmDictionary::createParametersForDecrypt(state, scope, unwrapAlgorithm->identifier(), state.uncheckedArgument(3)); + RETURN_IF_EXCEPTION(scope, { }); + + RefPtr<CryptoAlgorithm> unwrappedKeyAlgorithm; + RefPtr<CryptoAlgorithmParametersDeprecated> unwrappedKeyAlgorithmParameters; + if (!state.uncheckedArgument(4).isNull()) { + unwrappedKeyAlgorithm = createAlgorithmFromJSValue(state, scope, state.uncheckedArgument(4)); + RETURN_IF_EXCEPTION(scope, { }); + + unwrappedKeyAlgorithmParameters = JSCryptoAlgorithmDictionary::createParametersForImportKey(state, scope, unwrappedKeyAlgorithm->identifier(), state.uncheckedArgument(4)); + RETURN_IF_EXCEPTION(scope, { }); + } + + bool extractable = state.argument(5).toBoolean(&state); + RETURN_IF_EXCEPTION(scope, { }); + + CryptoKeyUsageBitmap keyUsages = 0; + if (state.argumentCount() >= 7) { + keyUsages = cryptoKeyUsagesFromJSValue(state, scope, state.uncheckedArgument(6)); + RETURN_IF_EXCEPTION(scope, { }); + } + + RefPtr<DeferredPromise> wrapper = createDeferredPromise(state, domWindow()); + auto promise = wrapper->promise(); + Strong<JSDOMGlobalObject> domGlobalObject(state.vm(), globalObject()); + + auto decryptSuccessCallback = [domGlobalObject, keyFormat, unwrappedKeyAlgorithm, unwrappedKeyAlgorithmParameters, extractable, keyUsages, wrapper](const Vector<uint8_t>& result) mutable { + auto importSuccessCallback = [wrapper](CryptoKey& key) mutable { + wrapper->resolve<IDLInterface<CryptoKey>>(key); + }; + auto importFailureCallback = [wrapper]() mutable { + wrapper->reject(); // FIXME: This should reject with an Exception. + }; + + VM& vm = domGlobalObject->vm(); + auto scope = DECLARE_CATCH_SCOPE(vm); + + ExecState& state = *domGlobalObject->globalExec(); + WebCore::importKey(state, keyFormat, std::make_pair(result.data(), result.size()), unwrappedKeyAlgorithm, unwrappedKeyAlgorithmParameters, extractable, keyUsages, WTFMove(importSuccessCallback), WTFMove(importFailureCallback)); + if (UNLIKELY(scope.exception())) { + // FIXME: Report exception details to console, and possibly to calling script once there is a standardized way to pass errors to WebCrypto promise reject functions. + scope.clearException(); + wrapper->reject(); // FIXME: This should reject with an Exception. + } + }; + + auto decryptFailureCallback = [wrapper]() mutable { + wrapper->reject(); // FIXME: This should reject with an Exception. + }; + + auto result = unwrapAlgorithm->decryptForUnwrapKey(*unwrapAlgorithmParameters, *unwrappingKey, wrappedKeyData, WTFMove(decryptSuccessCallback), WTFMove(decryptFailureCallback)); + if (result.hasException()) { + propagateException(state, scope, result.releaseException()); + return { }; + } + + return promise; +} + +} // namespace WebCore + +#endif diff --git a/Source/WebCore/bindings/js/JSWorkerCustom.cpp b/Source/WebCore/bindings/js/JSWorkerCustom.cpp index caa5318f1..84e07fe05 100644 --- a/Source/WebCore/bindings/js/JSWorkerCustom.cpp +++ b/Source/WebCore/bindings/js/JSWorkerCustom.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008, 2009 Apple Inc. All Rights Reserved. + * Copyright (C) 2008-2009, 2016 Apple Inc. All Rights Reserved. * Copyright (C) 2011 Google Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without @@ -25,48 +25,41 @@ */ #include "config.h" - #include "JSWorker.h" #include "Document.h" +#include "JSDOMConstructorBase.h" +#include "JSDOMConvertStrings.h" +#include "JSDOMExceptionHandling.h" #include "JSDOMGlobalObject.h" -#include "JSMessagePortCustom.h" -#include "Worker.h" #include "JSDOMWindowCustom.h" +#include "Worker.h" #include <runtime/Error.h> using namespace JSC; namespace WebCore { -JSC::JSValue JSWorker::postMessage(JSC::ExecState* exec) +EncodedJSValue JSC_HOST_CALL constructJSWorker(ExecState& state) { - return handlePostMessage(exec, &impl()); -} + VM& vm = state.vm(); + auto scope = DECLARE_THROW_SCOPE(vm); -EncodedJSValue JSC_HOST_CALL JSWorkerConstructor::constructJSWorker(ExecState* exec) -{ - JSWorkerConstructor* jsConstructor = jsCast<JSWorkerConstructor*>(exec->callee()); + ASSERT(jsCast<JSDOMConstructorBase*>(state.jsCallee())); + ASSERT(jsCast<JSDOMConstructorBase*>(state.jsCallee())->globalObject()); + auto& globalObject = *jsCast<JSDOMConstructorBase*>(state.jsCallee())->globalObject(); - if (!exec->argumentCount()) - return throwVMError(exec, createNotEnoughArgumentsError(exec)); + if (!state.argumentCount()) + return throwVMError(&state, scope, createNotEnoughArgumentsError(&state)); - String scriptURL = exec->argument(0).toString(exec)->value(exec); - if (exec->hadException()) - return JSValue::encode(JSValue()); + auto scriptURL = convert<IDLDOMString>(state, state.uncheckedArgument(0)); + RETURN_IF_EXCEPTION(scope, encodedJSValue()); - // See section 4.8.2 step 14 of WebWorkers for why this is the lexicalGlobalObject. - DOMWindow& window = asJSDOMWindow(exec->lexicalGlobalObject())->impl(); + // See section 4.8.2 step 14 of WebWorkers for why this is the lexicalGlobalObject. + auto& window = asJSDOMWindow(state.lexicalGlobalObject())->wrapped(); - ExceptionCode ec = 0; ASSERT(window.document()); - RefPtr<Worker> worker = Worker::create(*window.document(), scriptURL, ec); - if (ec) { - setDOMException(exec, ec); - return JSValue::encode(JSValue()); - } - - return JSValue::encode(asObject(toJS(exec, jsConstructor->globalObject(), worker.release()))); + return JSValue::encode(toJSNewlyCreated<IDLInterface<Worker>>(state, globalObject, scope, Worker::create(*window.document(), scriptURL, globalObject.runtimeFlags()))); } } // namespace WebCore diff --git a/Source/WebCore/bindings/js/JSWorkerGlobalScopeBase.cpp b/Source/WebCore/bindings/js/JSWorkerGlobalScopeBase.cpp index bc42aba4c..f1e6d8ed4 100644 --- a/Source/WebCore/bindings/js/JSWorkerGlobalScopeBase.cpp +++ b/Source/WebCore/bindings/js/JSWorkerGlobalScopeBase.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008, 2009 Apple Inc. All rights reserved. + * Copyright (C) 2008, 2009, 2016 Apple Inc. All rights reserved. * Copyright (C) 2009 Google Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without @@ -11,10 +11,10 @@ * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * - * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR @@ -26,58 +26,70 @@ */ #include "config.h" - #include "JSWorkerGlobalScopeBase.h" #include "DOMWrapperWorld.h" #include "JSDOMGlobalObjectTask.h" #include "JSDedicatedWorkerGlobalScope.h" +#include "JSDynamicDowncast.h" #include "JSWorkerGlobalScope.h" +#include "Language.h" #include "WorkerGlobalScope.h" +#include "WorkerThread.h" +#include <runtime/JSCInlines.h> +#include <runtime/JSCJSValueInlines.h> #include <runtime/Microtask.h> -#if ENABLE(SHARED_WORKERS) -#include "JSSharedWorkerGlobalScope.h" -#endif - using namespace JSC; namespace WebCore { -const ClassInfo JSWorkerGlobalScopeBase::s_info = { "WorkerGlobalScope", &JSDOMGlobalObject::s_info, 0, 0, CREATE_METHOD_TABLE(JSWorkerGlobalScopeBase) }; +const ClassInfo JSWorkerGlobalScopeBase::s_info = { "WorkerGlobalScope", &JSDOMGlobalObject::s_info, 0, CREATE_METHOD_TABLE(JSWorkerGlobalScopeBase) }; -const GlobalObjectMethodTable JSWorkerGlobalScopeBase::s_globalObjectMethodTable = { &allowsAccessFrom, &supportsProfiling, &supportsRichSourceInfo, &shouldInterruptScript, &javaScriptExperimentsEnabled, &queueTaskToEventLoop, &shouldInterruptScriptBeforeTimeout }; +const GlobalObjectMethodTable JSWorkerGlobalScopeBase::s_globalObjectMethodTable = { + &supportsRichSourceInfo, + &shouldInterruptScript, + &javaScriptRuntimeFlags, + &queueTaskToEventLoop, + &shouldInterruptScriptBeforeTimeout, + nullptr, + nullptr, + nullptr, + nullptr, + nullptr, + &defaultLanguage +}; -JSWorkerGlobalScopeBase::JSWorkerGlobalScopeBase(JSC::VM& vm, JSC::Structure* structure, PassRefPtr<WorkerGlobalScope> impl) - : JSDOMGlobalObject(vm, structure, &normalWorld(vm), &s_globalObjectMethodTable) - , m_impl(impl) +JSWorkerGlobalScopeBase::JSWorkerGlobalScopeBase(JSC::VM& vm, JSC::Structure* structure, RefPtr<WorkerGlobalScope>&& impl) + : JSDOMGlobalObject(vm, structure, normalWorld(vm), &s_globalObjectMethodTable) + , m_wrapped(WTFMove(impl)) { } -void JSWorkerGlobalScopeBase::finishCreation(VM& vm) +void JSWorkerGlobalScopeBase::finishCreation(VM& vm, JSProxy* proxy) { - Base::finishCreation(vm); - ASSERT(inherits(info())); -} + m_proxy.set(vm, this, proxy); -void JSWorkerGlobalScopeBase::destroy(JSCell* cell) -{ - static_cast<JSWorkerGlobalScopeBase*>(cell)->JSWorkerGlobalScopeBase::~JSWorkerGlobalScopeBase(); + Base::finishCreation(vm, m_proxy.get()); + ASSERT(inherits(vm, info())); } -ScriptExecutionContext* JSWorkerGlobalScopeBase::scriptExecutionContext() const +void JSWorkerGlobalScopeBase::visitChildren(JSCell* cell, SlotVisitor& visitor) { - return m_impl.get(); + JSWorkerGlobalScopeBase* thisObject = jsCast<JSWorkerGlobalScopeBase*>(cell); + ASSERT_GC_OBJECT_INHERITS(thisObject, info()); + Base::visitChildren(thisObject, visitor); + visitor.append(thisObject->m_proxy); } -bool JSWorkerGlobalScopeBase::allowsAccessFrom(const JSGlobalObject* object, ExecState* exec) +void JSWorkerGlobalScopeBase::destroy(JSCell* cell) { - return JSGlobalObject::allowsAccessFrom(object, exec); + static_cast<JSWorkerGlobalScopeBase*>(cell)->JSWorkerGlobalScopeBase::~JSWorkerGlobalScopeBase(); } -bool JSWorkerGlobalScopeBase::supportsProfiling(const JSGlobalObject* object) +ScriptExecutionContext* JSWorkerGlobalScopeBase::scriptExecutionContext() const { - return JSGlobalObject::supportsProfiling(object); + return m_wrapped.get(); } bool JSWorkerGlobalScopeBase::supportsRichSourceInfo(const JSGlobalObject* object) @@ -95,64 +107,49 @@ bool JSWorkerGlobalScopeBase::shouldInterruptScriptBeforeTimeout(const JSGlobalO return JSGlobalObject::shouldInterruptScriptBeforeTimeout(object); } -bool JSWorkerGlobalScopeBase::javaScriptExperimentsEnabled(const JSGlobalObject* object) +RuntimeFlags JSWorkerGlobalScopeBase::javaScriptRuntimeFlags(const JSGlobalObject* object) { - return JSGlobalObject::javaScriptExperimentsEnabled(object); + const JSWorkerGlobalScopeBase *thisObject = jsCast<const JSWorkerGlobalScopeBase*>(object); + return thisObject->m_wrapped->thread().runtimeFlags(); } -void JSWorkerGlobalScopeBase::queueTaskToEventLoop(const JSGlobalObject* object, PassRefPtr<Microtask> task) +void JSWorkerGlobalScopeBase::queueTaskToEventLoop(const JSGlobalObject* object, Ref<JSC::Microtask>&& task) { const JSWorkerGlobalScopeBase* thisObject = static_cast<const JSWorkerGlobalScopeBase*>(object); - thisObject->scriptExecutionContext()->postTask(JSGlobalObjectTask::create((JSDOMGlobalObject*)thisObject, task)); + thisObject->scriptExecutionContext()->postTask(JSGlobalObjectTask((JSDOMGlobalObject*)thisObject, WTFMove(task))); } -JSValue toJS(ExecState* exec, JSDOMGlobalObject*, WorkerGlobalScope* workerGlobalScope) +JSValue toJS(ExecState* exec, JSDOMGlobalObject*, WorkerGlobalScope& workerGlobalScope) { return toJS(exec, workerGlobalScope); } -JSValue toJS(ExecState*, WorkerGlobalScope* workerGlobalScope) +JSValue toJS(ExecState*, WorkerGlobalScope& workerGlobalScope) { - if (!workerGlobalScope) - return jsNull(); - WorkerScriptController* script = workerGlobalScope->script(); + WorkerScriptController* script = workerGlobalScope.script(); if (!script) return jsNull(); JSWorkerGlobalScope* contextWrapper = script->workerGlobalScopeWrapper(); ASSERT(contextWrapper); - return contextWrapper; + return contextWrapper->proxy(); } -JSDedicatedWorkerGlobalScope* toJSDedicatedWorkerGlobalScope(JSValue value) +JSDedicatedWorkerGlobalScope* toJSDedicatedWorkerGlobalScope(VM& vm, JSValue value) { if (!value.isObject()) return 0; - const ClassInfo* classInfo = asObject(value)->classInfo(); + const ClassInfo* classInfo = asObject(value)->classInfo(vm); if (classInfo == JSDedicatedWorkerGlobalScope::info()) return jsCast<JSDedicatedWorkerGlobalScope*>(asObject(value)); + if (classInfo == JSProxy::info()) + return jsDynamicDowncast<JSDedicatedWorkerGlobalScope*>(vm, jsCast<JSProxy*>(asObject(value))->target()); return 0; } -#if ENABLE(SHARED_WORKERS) -JSSharedWorkerGlobalScope* toJSSharedWorkerGlobalScope(JSValue value) -{ - if (!value.isObject()) - return 0; - const ClassInfo* classInfo = asObject(value)->classInfo(); - if (classInfo == JSSharedWorkerGlobalScope::info()) - return jsCast<JSSharedWorkerGlobalScope*>(asObject(value)); - return 0; -} -#endif -JSWorkerGlobalScope* toJSWorkerGlobalScope(JSValue value) +JSWorkerGlobalScope* toJSWorkerGlobalScope(VM& vm, JSValue value) { - JSWorkerGlobalScope* context = toJSDedicatedWorkerGlobalScope(value); -#if ENABLE(SHARED_WORKERS) - if (!context) - context = toJSSharedWorkerGlobalScope(value); -#endif - return context; + return toJSDedicatedWorkerGlobalScope(vm, value); } } // namespace WebCore diff --git a/Source/WebCore/bindings/js/JSWorkerGlobalScopeBase.h b/Source/WebCore/bindings/js/JSWorkerGlobalScopeBase.h index e2e93e14e..b0b36f9be 100644 --- a/Source/WebCore/bindings/js/JSWorkerGlobalScopeBase.h +++ b/Source/WebCore/bindings/js/JSWorkerGlobalScopeBase.h @@ -10,10 +10,10 @@ * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * - * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR @@ -24,15 +24,14 @@ * */ -#ifndef JSWorkerGlobalScopeBase_h -#define JSWorkerGlobalScopeBase_h +#pragma once #include "JSDOMGlobalObject.h" +#include "JSDOMWrapper.h" namespace WebCore { class JSDedicatedWorkerGlobalScope; - class JSSharedWorkerGlobalScope; class JSWorkerGlobalScope; class WorkerGlobalScope; @@ -43,7 +42,8 @@ namespace WebCore { DECLARE_INFO; - WorkerGlobalScope& impl() const { return *m_impl; } + WorkerGlobalScope& wrapped() const { return *m_wrapped; } + JSC::JSProxy* proxy() const { ASSERT(m_proxy); return m_proxy.get(); } ScriptExecutionContext* scriptExecutionContext() const; static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype) @@ -53,34 +53,31 @@ namespace WebCore { static const JSC::GlobalObjectMethodTable s_globalObjectMethodTable; - static bool allowsAccessFrom(const JSC::JSGlobalObject*, JSC::ExecState*); - static bool supportsProfiling(const JSC::JSGlobalObject*); static bool supportsRichSourceInfo(const JSC::JSGlobalObject*); static bool shouldInterruptScript(const JSC::JSGlobalObject*); static bool shouldInterruptScriptBeforeTimeout(const JSC::JSGlobalObject*); - static bool javaScriptExperimentsEnabled(const JSC::JSGlobalObject*); - static void queueTaskToEventLoop(const JSC::JSGlobalObject*, PassRefPtr<JSC::Microtask>); + static JSC::RuntimeFlags javaScriptRuntimeFlags(const JSC::JSGlobalObject*); + static void queueTaskToEventLoop(const JSC::JSGlobalObject*, Ref<JSC::Microtask>&&); protected: - JSWorkerGlobalScopeBase(JSC::VM&, JSC::Structure*, PassRefPtr<WorkerGlobalScope>); - void finishCreation(JSC::VM&); + JSWorkerGlobalScopeBase(JSC::VM&, JSC::Structure*, RefPtr<WorkerGlobalScope>&&); + void finishCreation(JSC::VM&, JSC::JSProxy*); + + static void visitChildren(JSC::JSCell*, JSC::SlotVisitor&); private: - RefPtr<WorkerGlobalScope> m_impl; + RefPtr<WorkerGlobalScope> m_wrapped; + JSC::WriteBarrier<JSC::JSProxy> m_proxy; }; // Returns a JSWorkerGlobalScope or jsNull() // Always ignores the execState and passed globalObject, WorkerGlobalScope is itself a globalObject and will always use its own prototype chain. - JSC::JSValue toJS(JSC::ExecState*, JSDOMGlobalObject*, WorkerGlobalScope*); - JSC::JSValue toJS(JSC::ExecState*, WorkerGlobalScope*); - - JSDedicatedWorkerGlobalScope* toJSDedicatedWorkerGlobalScope(JSC::JSValue); - JSWorkerGlobalScope* toJSWorkerGlobalScope(JSC::JSValue); + JSC::JSValue toJS(JSC::ExecState*, JSDOMGlobalObject*, WorkerGlobalScope&); + inline JSC::JSValue toJS(JSC::ExecState* exec, JSDOMGlobalObject* globalObject, WorkerGlobalScope* scope) { return scope ? toJS(exec, globalObject, *scope) : JSC::jsNull(); } + JSC::JSValue toJS(JSC::ExecState*, WorkerGlobalScope&); + inline JSC::JSValue toJS(JSC::ExecState* exec, WorkerGlobalScope* scope) { return scope ? toJS(exec, *scope) : JSC::jsNull(); } -#if ENABLE(SHARED_WORKERS) - JSSharedWorkerGlobalScope* toJSSharedWorkerGlobalScope(JSC::JSValue); -#endif + JSDedicatedWorkerGlobalScope* toJSDedicatedWorkerGlobalScope(JSC::VM&, JSC::JSValue); + JSWorkerGlobalScope* toJSWorkerGlobalScope(JSC::VM&, JSC::JSValue); } // namespace WebCore - -#endif // JSWorkerGlobalScopeBase_h diff --git a/Source/WebCore/bindings/js/JSWorkerGlobalScopeCustom.cpp b/Source/WebCore/bindings/js/JSWorkerGlobalScopeCustom.cpp index d12d98e84..6663dfb7b 100644 --- a/Source/WebCore/bindings/js/JSWorkerGlobalScopeCustom.cpp +++ b/Source/WebCore/bindings/js/JSWorkerGlobalScopeCustom.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008, 2009, 2011 Apple Inc. All Rights Reserved. + * Copyright (C) 2008-2009, 2011, 2016 Apple Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -24,95 +24,61 @@ */ #include "config.h" - #include "JSWorkerGlobalScope.h" -#include "ExceptionCode.h" -#include "JSDOMBinding.h" -#include "JSDOMGlobalObject.h" -#include "JSEventListener.h" -#include "JSEventSource.h" -#include "JSMessageChannel.h" -#include "JSMessagePort.h" -#include "JSWorkerLocation.h" -#include "JSWorkerNavigator.h" -#include "JSXMLHttpRequest.h" +#include "JSDOMConvert.h" #include "ScheduledAction.h" #include "WorkerGlobalScope.h" -#include "WorkerLocation.h" -#include "WorkerNavigator.h" -#include <interpreter/Interpreter.h> - -#if ENABLE(WEB_SOCKETS) -#include "JSWebSocket.h" -#endif using namespace JSC; namespace WebCore { -void JSWorkerGlobalScope::visitChildren(JSCell* cell, SlotVisitor& visitor) +void JSWorkerGlobalScope::visitAdditionalChildren(SlotVisitor& visitor) { - JSWorkerGlobalScope* thisObject = jsCast<JSWorkerGlobalScope*>(cell); - ASSERT_GC_OBJECT_INHERITS(thisObject, info()); - COMPILE_ASSERT(StructureFlags & OverridesVisitChildren, OverridesVisitChildrenWithoutSettingFlag); - ASSERT(thisObject->structure()->typeInfo().overridesVisitChildren()); - Base::visitChildren(thisObject, visitor); - - if (WorkerLocation* location = thisObject->impl().optionalLocation()) + if (auto* location = wrapped().optionalLocation()) visitor.addOpaqueRoot(location); - if (WorkerNavigator* navigator = thisObject->impl().optionalNavigator()) + if (auto* navigator = wrapped().optionalNavigator()) visitor.addOpaqueRoot(navigator); - - thisObject->impl().visitJSEventListeners(visitor); -} - -bool JSWorkerGlobalScope::getOwnPropertySlotDelegate(ExecState* exec, PropertyName propertyName, PropertySlot& slot) -{ - // Look for overrides before looking at any of our own properties. - if (JSGlobalObject::getOwnPropertySlot(this, exec, propertyName, slot)) - return true; - return false; + ScriptExecutionContext& context = wrapped(); + visitor.addOpaqueRoot(&context); + + // Normally JSEventTargetCustom.cpp's JSEventTarget::visitAdditionalChildren() would call this. But + // even though WorkerGlobalScope is an EventTarget, JSWorkerGlobalScope does not subclass + // JSEventTarget, so we need to do this here. + wrapped().visitJSEventListeners(visitor); } -JSValue JSWorkerGlobalScope::importScripts(ExecState* exec) +JSValue JSWorkerGlobalScope::setTimeout(ExecState& state) { - if (!exec->argumentCount()) - return jsUndefined(); - - Vector<String> urls; - for (unsigned i = 0; i < exec->argumentCount(); i++) { - urls.append(exec->uncheckedArgument(i).toString(exec)->value(exec)); - if (exec->hadException()) - return jsUndefined(); - } - ExceptionCode ec = 0; + VM& vm = state.vm(); + auto scope = DECLARE_THROW_SCOPE(vm); - impl().importScripts(urls, ec); - setDOMException(exec, ec); - return jsUndefined(); -} + if (UNLIKELY(state.argumentCount() < 1)) + return throwException(&state, scope, createNotEnoughArgumentsError(&state)); -JSValue JSWorkerGlobalScope::setTimeout(ExecState* exec) -{ - OwnPtr<ScheduledAction> action = ScheduledAction::create(exec, currentWorld(exec), impl().contentSecurityPolicy()); - if (exec->hadException()) - return jsUndefined(); + std::unique_ptr<ScheduledAction> action = ScheduledAction::create(&state, globalObject()->world(), wrapped().contentSecurityPolicy()); + RETURN_IF_EXCEPTION(scope, JSValue()); if (!action) return jsNumber(0); - int delay = exec->argument(1).toInt32(exec); - return jsNumber(impl().setTimeout(action.release(), delay)); + int delay = state.argument(1).toInt32(&state); + return jsNumber(wrapped().setTimeout(WTFMove(action), delay)); } -JSValue JSWorkerGlobalScope::setInterval(ExecState* exec) +JSValue JSWorkerGlobalScope::setInterval(ExecState& state) { - OwnPtr<ScheduledAction> action = ScheduledAction::create(exec, currentWorld(exec), impl().contentSecurityPolicy()); - if (exec->hadException()) - return jsUndefined(); + VM& vm = state.vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + + if (UNLIKELY(state.argumentCount() < 1)) + return throwException(&state, scope, createNotEnoughArgumentsError(&state)); + + std::unique_ptr<ScheduledAction> action = ScheduledAction::create(&state, globalObject()->world(), wrapped().contentSecurityPolicy()); + RETURN_IF_EXCEPTION(scope, JSValue()); if (!action) return jsNumber(0); - int delay = exec->argument(1).toInt32(exec); - return jsNumber(impl().setInterval(action.release(), delay)); + int delay = state.argument(1).toInt32(&state); + return jsNumber(wrapped().setInterval(WTFMove(action), delay)); } } // namespace WebCore diff --git a/Source/WebCore/bindings/js/JSXMLDocumentCustom.cpp b/Source/WebCore/bindings/js/JSXMLDocumentCustom.cpp new file mode 100644 index 000000000..9c82c500b --- /dev/null +++ b/Source/WebCore/bindings/js/JSXMLDocumentCustom.cpp @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2016 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "JSXMLDocument.h" + +#include "JSDOMWindow.h" +#include "JSDocumentCustom.h" +#include "JSSVGDocument.h" +#include "NodeTraversal.h" + +namespace WebCore { + +using namespace JSC; + +JSValue toJSNewlyCreated(ExecState* state, JSDOMGlobalObject* globalObject, Ref<XMLDocument>&& document) +{ + reportMemoryForDocumentIfFrameless(*state, document.get()); + + return createWrapper<XMLDocument>(globalObject, WTFMove(document)); +} + +JSValue toJS(ExecState* state, JSDOMGlobalObject* globalObject, XMLDocument& document) +{ + if (auto* wrapper = cachedDocumentWrapper(*state, *globalObject, document)) + return wrapper; + return toJSNewlyCreated(state, globalObject, Ref<XMLDocument>(document)); +} + +} // namespace WebCore diff --git a/Source/WebCore/bindings/js/JSXMLHttpRequestCustom.cpp b/Source/WebCore/bindings/js/JSXMLHttpRequestCustom.cpp index 7ea887833..7d584d74c 100644 --- a/Source/WebCore/bindings/js/JSXMLHttpRequestCustom.cpp +++ b/Source/WebCore/bindings/js/JSXMLHttpRequestCustom.cpp @@ -10,7 +10,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of + * 3. Neither the name of Apple Inc. ("Apple") nor the names of * its contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * @@ -39,13 +39,13 @@ #include "HTMLDocument.h" #include "InspectorInstrumentation.h" #include "JSBlob.h" +#include "JSDOMConvert.h" #include "JSDOMFormData.h" #include "JSDOMWindowCustom.h" #include "JSDocument.h" #include "JSEvent.h" #include "JSEventListener.h" #include "XMLHttpRequest.h" -#include <interpreter/StackVisitor.h> #include <runtime/ArrayBuffer.h> #include <runtime/Error.h> #include <runtime/JSArrayBuffer.h> @@ -56,184 +56,81 @@ using namespace JSC; namespace WebCore { -void JSXMLHttpRequest::visitChildren(JSCell* cell, SlotVisitor& visitor) +void JSXMLHttpRequest::visitAdditionalChildren(SlotVisitor& visitor) { - JSXMLHttpRequest* thisObject = jsCast<JSXMLHttpRequest*>(cell); - ASSERT_GC_OBJECT_INHERITS(thisObject, info()); - COMPILE_ASSERT(StructureFlags & OverridesVisitChildren, OverridesVisitChildrenWithoutSettingFlag); - ASSERT(thisObject->structure()->typeInfo().overridesVisitChildren()); - Base::visitChildren(thisObject, visitor); - - if (XMLHttpRequestUpload* upload = thisObject->m_impl->optionalUpload()) + if (XMLHttpRequestUpload* upload = wrapped().optionalUpload()) visitor.addOpaqueRoot(upload); - if (Document* responseDocument = thisObject->m_impl->optionalResponseXML()) + if (Document* responseDocument = wrapped().optionalResponseXML()) visitor.addOpaqueRoot(responseDocument); - - if (ArrayBuffer* responseArrayBuffer = thisObject->m_impl->optionalResponseArrayBuffer()) - visitor.addOpaqueRoot(responseArrayBuffer); - - if (Blob* responseBlob = thisObject->m_impl->optionalResponseBlob()) - visitor.addOpaqueRoot(responseBlob); - - if (thisObject->m_response) - visitor.append(&thisObject->m_response); - - thisObject->m_impl->visitJSEventListeners(visitor); } -// Custom functions -JSValue JSXMLHttpRequest::open(ExecState* exec) +JSValue JSXMLHttpRequest::responseText(ExecState& state) const { - if (exec->argumentCount() < 2) - return exec->vm().throwException(exec, createNotEnoughArgumentsError(exec)); - - const URL& url = impl().scriptExecutionContext()->completeURL(exec->uncheckedArgument(1).toString(exec)->value(exec)); - String method = exec->uncheckedArgument(0).toString(exec)->value(exec); - - ExceptionCode ec = 0; - if (exec->argumentCount() >= 3) { - bool async = exec->uncheckedArgument(2).toBoolean(exec); - if (!exec->argument(3).isUndefined()) { - String user = valueToStringWithNullCheck(exec, exec->uncheckedArgument(3)); - - if (!exec->argument(4).isUndefined()) { - String password = valueToStringWithNullCheck(exec, exec->uncheckedArgument(4)); - impl().open(method, url, async, user, password, ec); - } else - impl().open(method, url, async, user, ec); - } else - impl().open(method, url, async, ec); - } else - impl().open(method, url, ec); - - setDOMException(exec, ec); - return jsUndefined(); -} - -class SendFunctor { -public: - SendFunctor() - : m_hasSkippedFirstFrame(false) - , m_line(0) - , m_column(0) - { - } + auto result = wrapped().responseText(); - unsigned line() const { return m_line; } - unsigned column() const { return m_column; } - String url() const { return m_url; } - - StackVisitor::Status operator()(StackVisitor& visitor) - { - if (!m_hasSkippedFirstFrame) { - m_hasSkippedFirstFrame = true; - return StackVisitor::Continue; - } - - unsigned line = 0; - unsigned column = 0; - visitor->computeLineAndColumn(line, column); - m_line = line; - m_column = column; - m_url = visitor->sourceURL(); - return StackVisitor::Done; + if (UNLIKELY(result.hasException())) { + auto& vm = state.vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + propagateException(state, scope, result.releaseException()); + return { }; } -private: - bool m_hasSkippedFirstFrame; - unsigned m_line; - unsigned m_column; - String m_url; -}; + auto resultValue = result.releaseReturnValue(); + if (resultValue.isNull()) + return jsNull(); -JSValue JSXMLHttpRequest::send(ExecState* exec) -{ - InspectorInstrumentation::willSendXMLHttpRequest(impl().scriptExecutionContext(), impl().url()); - - ExceptionCode ec = 0; - JSValue val = exec->argument(0); - if (val.isUndefinedOrNull()) - impl().send(ec); - else if (val.inherits(JSDocument::info())) - impl().send(toDocument(val), ec); - else if (val.inherits(JSBlob::info())) - impl().send(toBlob(val), ec); - else if (val.inherits(JSDOMFormData::info())) - impl().send(toDOMFormData(val), ec); - else if (val.inherits(JSArrayBuffer::info())) - impl().send(toArrayBuffer(val), ec); - else if (val.inherits(JSArrayBufferView::info())) { - RefPtr<ArrayBufferView> view = toArrayBufferView(val); - impl().send(view.get(), ec); - } else - impl().send(val.toString(exec)->value(exec), ec); - - SendFunctor functor; - exec->iterate(functor); - impl().setLastSendLineAndColumnNumber(functor.line(), functor.column()); - impl().setLastSendURL(functor.url()); - setDOMException(exec, ec); - return jsUndefined(); + // 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. + return jsOwnedString(&state, resultValue); } -JSValue JSXMLHttpRequest::responseText(ExecState* exec) const +JSValue JSXMLHttpRequest::retrieveResponse(ExecState& state) { - ExceptionCode ec = 0; - String text = impl().responseText(ec); - if (ec) { - setDOMException(exec, ec); + auto type = wrapped().responseType(); + + switch (type) { + case XMLHttpRequest::ResponseType::EmptyString: + case XMLHttpRequest::ResponseType::Text: + return responseText(state); + default: + break; + } + + if (!wrapped().doneWithoutErrors()) + return jsNull(); + + JSValue value; + switch (type) { + case XMLHttpRequest::ResponseType::EmptyString: + case XMLHttpRequest::ResponseType::Text: + ASSERT_NOT_REACHED(); return jsUndefined(); + + case XMLHttpRequest::ResponseType::Json: + value = JSONParse(&state, wrapped().responseTextIgnoringResponseType()); + if (!value) + value = jsNull(); + break; + + case XMLHttpRequest::ResponseType::Document: { + auto document = wrapped().responseXML(); + ASSERT(!document.hasException()); + value = toJS<IDLInterface<Document>>(state, *globalObject(), document.releaseReturnValue()); + break; } - return jsOwnedStringOrNull(exec, text); -} -JSValue JSXMLHttpRequest::response(ExecState* exec) const -{ - switch (impl().responseTypeCode()) { - case XMLHttpRequest::ResponseTypeDefault: - case XMLHttpRequest::ResponseTypeText: - return responseText(exec); - - case XMLHttpRequest::ResponseTypeJSON: - { - // FIXME: Use CachedAttribute for other types as well. - if (m_response && impl().responseCacheIsValid()) - return m_response.get(); - - if (!impl().doneWithoutErrors()) - return jsNull(); - - JSValue value = JSONParse(exec, impl().responseTextIgnoringResponseType()); - if (!value) - value = jsNull(); - JSXMLHttpRequest* jsRequest = const_cast<JSXMLHttpRequest*>(this); - jsRequest->m_response.set(exec->vm(), jsRequest, value); - - impl().didCacheResponseJSON(); - - return value; - } - - case XMLHttpRequest::ResponseTypeDocument: - { - ExceptionCode ec = 0; - Document* document = impl().responseXML(ec); - if (ec) { - setDOMException(exec, ec); - return jsUndefined(); - } - return toJS(exec, globalObject(), document); - } - - case XMLHttpRequest::ResponseTypeBlob: - return toJS(exec, globalObject(), impl().responseBlob()); - - case XMLHttpRequest::ResponseTypeArrayBuffer: - return toJS(exec, globalObject(), impl().responseArrayBuffer()); + case XMLHttpRequest::ResponseType::Blob: + value = toJSNewlyCreated<IDLInterface<Blob>>(state, *globalObject(), wrapped().createResponseBlob()); + break; + + case XMLHttpRequest::ResponseType::Arraybuffer: + value = toJS<IDLInterface<ArrayBuffer>>(state, *globalObject(), wrapped().createResponseArrayBuffer()); + break; } - return jsUndefined(); + wrapped().didCacheResponse(); + return value; } } // namespace WebCore diff --git a/Source/WebCore/bindings/js/JSXPathNSResolverCustom.cpp b/Source/WebCore/bindings/js/JSXPathNSResolverCustom.cpp new file mode 100644 index 000000000..8c1761ccb --- /dev/null +++ b/Source/WebCore/bindings/js/JSXPathNSResolverCustom.cpp @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2016 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "JSXPathNSResolver.h" + +#include "JSCustomXPathNSResolver.h" +#include "JSDOMExceptionHandling.h" + +using namespace JSC; + +namespace WebCore { + +RefPtr<XPathNSResolver> JSXPathNSResolver::toWrapped(VM& vm, ExecState& state, JSValue value) +{ + if (value.inherits(vm, JSXPathNSResolver::info())) + return &jsCast<JSXPathNSResolver*>(asObject(value))->wrapped(); + + auto result = JSCustomXPathNSResolver::create(state, value); + if (UNLIKELY(result.hasException())) { + auto scope = DECLARE_THROW_SCOPE(vm); + propagateException(state, scope, result.releaseException()); + return nullptr; + } + return result.releaseReturnValue(); +} + +} // namespace WebCore diff --git a/Source/WebCore/bindings/js/JSXPathResultCustom.cpp b/Source/WebCore/bindings/js/JSXPathResultCustom.cpp index 35ba89231..d4fbbef6f 100644 --- a/Source/WebCore/bindings/js/JSXPathResultCustom.cpp +++ b/Source/WebCore/bindings/js/JSXPathResultCustom.cpp @@ -26,30 +26,18 @@ #include "config.h" #include "JSXPathResult.h" -#include "JSDOMBinding.h" #include "JSNodeCustom.h" -#include "XPathResult.h" #include "XPathValue.h" -using namespace JSC; - namespace WebCore { -void JSXPathResult::visitChildren(JSCell* cell, SlotVisitor& visitor) +void JSXPathResult::visitAdditionalChildren(JSC::SlotVisitor& visitor) { - JSXPathResult* thisObject = jsCast<JSXPathResult*>(cell); - ASSERT_GC_OBJECT_INHERITS(thisObject, info()); - COMPILE_ASSERT(StructureFlags & OverridesVisitChildren, OverridesVisitChildrenWithoutSettingFlag); - ASSERT(thisObject->structure()->typeInfo().overridesVisitChildren()); - Base::visitChildren(thisObject, visitor); - - const XPath::Value& xpathValue = thisObject->impl().value(); - if (xpathValue.isNodeSet()) { - const XPath::NodeSet& nodesToMark = xpathValue.toNodeSet(); - for (size_t i = 0; i < nodesToMark.size(); ++i) { - Node* node = nodesToMark[i]; - visitor.addOpaqueRoot(root(node)); - } + auto& value = wrapped().value(); + if (value.isNodeSet()) { + // FIXME: This looks like it might race, but I'm not sure. + for (auto& node : value.toNodeSet()) + visitor.addOpaqueRoot(root(node.get())); } } diff --git a/Source/WebCore/bindings/js/JSXSLTProcessorCustom.cpp b/Source/WebCore/bindings/js/JSXSLTProcessorCustom.cpp deleted file mode 100644 index 1086de270..000000000 --- a/Source/WebCore/bindings/js/JSXSLTProcessorCustom.cpp +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright (C) 2008 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of - * its contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" - -#if ENABLE(XSLT) - -#include "JSXSLTProcessor.h" - -#include "Document.h" -#include "DocumentFragment.h" -#include "JSDocument.h" -#include "JSDocumentFragment.h" -#include "JSNode.h" -#include "Node.h" -#include "XSLTProcessor.h" -#include "JSDOMBinding.h" -#include <wtf/text/WTFString.h> - -using namespace JSC; - -namespace WebCore { - -JSValue JSXSLTProcessor::setParameter(ExecState* exec) -{ - if (exec->argument(1).isUndefinedOrNull() || exec->argument(2).isUndefinedOrNull()) - return jsUndefined(); // Throw exception? - String namespaceURI = exec->uncheckedArgument(0).toString(exec)->value(exec); - String localName = exec->uncheckedArgument(1).toString(exec)->value(exec); - String value = exec->uncheckedArgument(2).toString(exec)->value(exec); - impl().setParameter(namespaceURI, localName, value); - return jsUndefined(); -} - -JSValue JSXSLTProcessor::getParameter(ExecState* exec) -{ - if (exec->argument(1).isUndefinedOrNull()) - return jsUndefined(); - String namespaceURI = exec->uncheckedArgument(0).toString(exec)->value(exec); - String localName = exec->uncheckedArgument(1).toString(exec)->value(exec); - String value = impl().getParameter(namespaceURI, localName); - return jsStringOrUndefined(exec, value); -} - -JSValue JSXSLTProcessor::removeParameter(ExecState* exec) -{ - if (exec->argument(1).isUndefinedOrNull()) - return jsUndefined(); - String namespaceURI = exec->uncheckedArgument(0).toString(exec)->value(exec); - String localName = exec->uncheckedArgument(1).toString(exec)->value(exec); - impl().removeParameter(namespaceURI, localName); - return jsUndefined(); -} - -} // namespace WebCore - -#endif // ENABLE(XSLT) diff --git a/Source/WebCore/bindings/js/ModuleFetchFailureKind.h b/Source/WebCore/bindings/js/ModuleFetchFailureKind.h new file mode 100644 index 000000000..259ef1ed6 --- /dev/null +++ b/Source/WebCore/bindings/js/ModuleFetchFailureKind.h @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2017 Yusuke Suzuki <utatane.tea@gmail.com> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +namespace WebCore { + +enum class ModuleFetchFailureKind { + WasErrored, + WasCanceled, +}; + +} // namespace WebCore + diff --git a/Source/WebCore/bindings/js/PageScriptDebugServer.cpp b/Source/WebCore/bindings/js/PageScriptDebugServer.cpp deleted file mode 100644 index e938d8900..000000000 --- a/Source/WebCore/bindings/js/PageScriptDebugServer.cpp +++ /dev/null @@ -1,273 +0,0 @@ -/* - * Copyright (c) 2011 Google Inc. All rights reserved. - * Copyright (C) 2013 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" -#include "PageScriptDebugServer.h" - -#include "Document.h" -#include "EventLoop.h" -#include "FrameView.h" -#include "JSDOMWindowCustom.h" -#include "MainFrame.h" -#include "Page.h" -#include "PageGroup.h" -#include "PluginView.h" -#include "ScriptController.h" -#include "Timer.h" -#include "Widget.h" -#include <runtime/JSLock.h> -#include <wtf/MainThread.h> -#include <wtf/OwnPtr.h> -#include <wtf/PassOwnPtr.h> -#include <wtf/StdLibExtras.h> - -#if PLATFORM(IOS) -#include "JSDOMWindowBase.h" -#include "WebCoreThreadInternal.h" -#endif - -using namespace JSC; -using namespace Inspector; - -namespace WebCore { - -static Page* toPage(JSGlobalObject* globalObject) -{ - ASSERT_ARG(globalObject, globalObject); - - JSDOMWindow* window = asJSDOMWindow(globalObject); - Frame* frame = window->impl().frame(); - return frame ? frame->page() : 0; -} - -PageScriptDebugServer& PageScriptDebugServer::shared() -{ - DEFINE_STATIC_LOCAL(PageScriptDebugServer, server, ()); - return server; -} - -PageScriptDebugServer::PageScriptDebugServer() - : ScriptDebugServer() - , m_pausedPage(0) -{ -} - -PageScriptDebugServer::~PageScriptDebugServer() -{ -} - -void PageScriptDebugServer::addListener(ScriptDebugListener* listener, Page* page) -{ - ASSERT_ARG(listener, listener); - ASSERT_ARG(page, page); - - OwnPtr<ListenerSet>& listeners = m_pageListenersMap.add(page, nullptr).iterator->value; - if (!listeners) - listeners = adoptPtr(new ListenerSet); - - bool wasEmpty = listeners->isEmpty(); - listeners->add(listener); - - if (wasEmpty) - didAddFirstListener(page); -} - -void PageScriptDebugServer::removeListener(ScriptDebugListener* listener, Page* page, bool skipRecompile) -{ - ASSERT_ARG(listener, listener); - ASSERT_ARG(page, page); - - PageListenersMap::iterator it = m_pageListenersMap.find(page); - if (it == m_pageListenersMap.end()) - return; - - ListenerSet* listeners = it->value.get(); - listeners->remove(listener); - - if (listeners->isEmpty()) { - m_pageListenersMap.remove(it); - didRemoveLastListener(page, skipRecompile); - } -} - -void PageScriptDebugServer::recompileAllJSFunctions() -{ - JSLockHolder lock(JSDOMWindow::commonVM()); - Debugger::recompileAllJSFunctions(JSDOMWindow::commonVM()); -} - -ScriptDebugServer::ListenerSet* PageScriptDebugServer::getListenersForGlobalObject(JSGlobalObject* globalObject) -{ - Page* page = toPage(globalObject); - if (!page) - return 0; - return m_pageListenersMap.get(page); -} - -void PageScriptDebugServer::didPause(JSC::JSGlobalObject* globalObject) -{ - ASSERT(!m_pausedPage); - - Page* page = toPage(globalObject); - ASSERT(page); - if (!page) - return; - - m_pausedPage = page; - - setJavaScriptPaused(page->group(), true); -} - -void PageScriptDebugServer::didContinue(JSC::JSGlobalObject* globalObject) -{ - // Page can be null if we are continuing because the Page closed. - Page* page = toPage(globalObject); - ASSERT(!page || page == m_pausedPage); - - m_pausedPage = 0; - - if (page) - setJavaScriptPaused(page->group(), false); -} - -void PageScriptDebugServer::didAddFirstListener(Page* page) -{ - // Set debugger before recompiling to get sourceParsed callbacks. - page->setDebugger(this); - recompileAllJSFunctions(); -} - -void PageScriptDebugServer::didRemoveLastListener(Page* page, bool skipRecompile) -{ - ASSERT(page); - - if (m_pausedPage == page) - m_doneProcessingDebuggerEvents = true; - - // Clear debugger before recompiling because we do not need sourceParsed callbacks. - page->setDebugger(nullptr); - - if (!skipRecompile) - recompileAllJSFunctions(); -} - -void PageScriptDebugServer::runEventLoopWhilePaused() -{ -#if PLATFORM(IOS) - // On iOS, running an EventLoop causes us to run a nested WebRunLoop. - // Since the WebThread is autoreleased at the end of run loop iterations - // we need to gracefully handle releasing and reacquiring the lock. - ASSERT(WebThreadIsLockedOrDisabled()); - { - if (WebThreadIsEnabled()) - JSC::JSLock::DropAllLocks dropAllLocks(WebCore::JSDOMWindowBase::commonVM(), JSC::JSLock::DropAllLocks::AlwaysDropLocks); - WebRunLoopEnableNested(); -#endif - - TimerBase::fireTimersInNestedEventLoop(); - - EventLoop loop; - while (!m_doneProcessingDebuggerEvents && !loop.ended()) - loop.cycle(); - -#if PLATFORM(IOS) - WebRunLoopDisableNested(); - } - ASSERT(WebThreadIsLockedOrDisabled()); -#endif -} - -bool PageScriptDebugServer::isContentScript(ExecState* exec) const -{ - return ¤tWorld(exec) != &mainThreadNormalWorld(); -} - -void PageScriptDebugServer::reportException(ExecState* exec, JSValue exception) const -{ - WebCore::reportException(exec, exception); -} - -void PageScriptDebugServer::setJavaScriptPaused(const PageGroup& pageGroup, bool paused) -{ - setMainThreadCallbacksPaused(paused); - - const HashSet<Page*>& pages = pageGroup.pages(); - - HashSet<Page*>::const_iterator end = pages.end(); - for (HashSet<Page*>::const_iterator it = pages.begin(); it != end; ++it) - setJavaScriptPaused(*it, paused); -} - -void PageScriptDebugServer::setJavaScriptPaused(Page* page, bool paused) -{ - ASSERT_ARG(page, page); - - page->setDefersLoading(paused); - - for (Frame* frame = &page->mainFrame(); frame; frame = frame->tree().traverseNext()) - setJavaScriptPaused(frame, paused); -} - -void PageScriptDebugServer::setJavaScriptPaused(Frame* frame, bool paused) -{ - ASSERT_ARG(frame, frame); - - if (!frame->script().canExecuteScripts(NotAboutToExecuteScript)) - return; - - frame->script().setPaused(paused); - - Document* document = frame->document(); - if (paused) { - document->suspendScriptedAnimationControllerCallbacks(); - document->suspendActiveDOMObjects(ActiveDOMObject::JavaScriptDebuggerPaused); - } else { - document->resumeActiveDOMObjects(ActiveDOMObject::JavaScriptDebuggerPaused); - document->resumeScriptedAnimationControllerCallbacks(); - } - - setJavaScriptPaused(frame->view(), paused); -} - -void PageScriptDebugServer::setJavaScriptPaused(FrameView* view, bool paused) -{ - if (!view) - return; - - for (auto it = view->children().begin(), end = view->children().end(); it != end; ++it) { - Widget* widget = (*it).get(); - if (!widget->isPluginView()) - continue; - toPluginView(widget)->setJavaScriptPaused(paused); - } -} - -} // namespace WebCore diff --git a/Source/WebCore/bindings/js/PageScriptDebugServer.h b/Source/WebCore/bindings/js/PageScriptDebugServer.h deleted file mode 100644 index 75db77a1c..000000000 --- a/Source/WebCore/bindings/js/PageScriptDebugServer.h +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright (c) 2011 Google Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef PageScriptDebugServer_h -#define PageScriptDebugServer_h - -#include <inspector/ScriptDebugServer.h> -#include <wtf/Forward.h> - -namespace WebCore { - -class Frame; -class FrameView; -class Page; -class PageGroup; - -class PageScriptDebugServer : public Inspector::ScriptDebugServer { - WTF_MAKE_NONCOPYABLE(PageScriptDebugServer); -public: - static PageScriptDebugServer& shared(); - - void addListener(Inspector::ScriptDebugListener*, Page*); - void removeListener(Inspector::ScriptDebugListener*, Page*, bool skipRecompile); - - virtual void recompileAllJSFunctions() override; - -private: - typedef HashMap<Page*, OwnPtr<ListenerSet>> PageListenersMap; - - PageScriptDebugServer(); - virtual ~PageScriptDebugServer(); - - virtual ListenerSet* getListenersForGlobalObject(JSC::JSGlobalObject*); - virtual void didPause(JSC::JSGlobalObject*); - virtual void didContinue(JSC::JSGlobalObject*); - virtual void runEventLoopWhilePaused(); - virtual bool isContentScript(JSC::ExecState*) const override; - virtual void reportException(JSC::ExecState*, JSC::JSValue) const override; - - - void didAddFirstListener(Page*); - void didRemoveLastListener(Page*, bool skipRecompile); - - void setJavaScriptPaused(const PageGroup&, bool paused); - void setJavaScriptPaused(Page*, bool paused); - void setJavaScriptPaused(Frame*, bool paused); - void setJavaScriptPaused(FrameView*, bool paused); - - PageListenersMap m_pageListenersMap; - Page* m_pausedPage; -}; - -} // namespace WebCore - -#endif // PageScriptDebugServer_h diff --git a/Source/WebCore/bindings/js/ReadableStreamDefaultController.cpp b/Source/WebCore/bindings/js/ReadableStreamDefaultController.cpp new file mode 100644 index 000000000..080cf7013 --- /dev/null +++ b/Source/WebCore/bindings/js/ReadableStreamDefaultController.cpp @@ -0,0 +1,96 @@ +/* + * Copyright (C) 2016 Canon Inc. + * Copyright (C) 2016 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted, provided that the following conditions + * are required to be met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Canon Inc. nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY CANON INC. AND ITS CONTRIBUTORS "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL CANON INC. AND ITS CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#include "config.h" +#include "ReadableStreamDefaultController.h" + +#if ENABLE(READABLE_STREAM_API) + +#include "WebCoreJSClientData.h" +#include <heap/HeapInlines.h> +#include <runtime/IdentifierInlines.h> +#include <runtime/JSObjectInlines.h> + +namespace WebCore { + +static inline JSC::JSValue callFunction(JSC::ExecState& state, JSC::JSValue jsFunction, JSC::JSValue thisValue, const JSC::ArgList& arguments) +{ + JSC::CallData callData; + auto callType = JSC::getCallData(jsFunction, callData); + return call(&state, jsFunction, callType, callData, thisValue, arguments); +} + +JSC::JSValue ReadableStreamDefaultController::invoke(JSC::ExecState& state, JSC::JSObject& object, const char* propertyName, JSC::JSValue parameter) +{ + JSC::VM& vm = state.vm(); + JSC::JSLockHolder lock(vm); + auto scope = DECLARE_THROW_SCOPE(vm); + + auto function = object.get(&state, JSC::Identifier::fromString(&state, propertyName)); + RETURN_IF_EXCEPTION(scope, JSC::JSValue()); + + if (!function.isFunction()) { + if (!function.isUndefined()) + throwTypeError(&state, scope, ASCIILiteral("ReadableStream trying to call a property that is not callable")); + return JSC::jsUndefined(); + } + + JSC::MarkedArgumentBuffer arguments; + arguments.append(parameter); + + return callFunction(state, function, &object, arguments); +} + +bool ReadableStreamDefaultController::isControlledReadableStreamLocked() const +{ + auto& globalObject = this->globalObject(); + JSC::VM& vm = globalObject.vm(); + JSC::JSLockHolder lock(vm); + auto scope = DECLARE_CATCH_SCOPE(vm); + auto& state = globalExec(); + + auto& clientData = *static_cast<JSVMClientData*>(vm.clientData); + auto readableStream = m_jsController->get(&state, clientData.builtinNames().controlledReadableStreamPrivateName()); + ASSERT_UNUSED(scope, !scope.exception()); + + auto* isLocked = globalObject.builtinInternalFunctions().readableStreamInternals().m_isReadableStreamLockedFunction.get(); + ASSERT(isLocked); + + JSC::MarkedArgumentBuffer arguments; + arguments.append(readableStream); + auto result = callFunction(state, isLocked, JSC::jsUndefined(), arguments); + ASSERT(!scope.exception()); + + return result.isTrue(); +} + +} // namespace WebCore + +#endif // ENABLE(READABLE_STREAM_API) diff --git a/Source/WebCore/bindings/js/ReadableStreamDefaultController.h b/Source/WebCore/bindings/js/ReadableStreamDefaultController.h new file mode 100644 index 000000000..c3500b14a --- /dev/null +++ b/Source/WebCore/bindings/js/ReadableStreamDefaultController.h @@ -0,0 +1,119 @@ +/* + * Copyright (C) 2016 Canon Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted, provided that the following conditions + * are required to be met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Canon Inc. nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY CANON INC. AND ITS CONTRIBUTORS "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL CANON INC. AND ITS CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +#if ENABLE(READABLE_STREAM_API) + +#include "JSDOMConvertBufferSource.h" +#include "JSReadableStreamDefaultController.h" +#include <runtime/JSCJSValue.h> +#include <runtime/JSCJSValueInlines.h> +#include <runtime/TypedArrays.h> + +namespace WebCore { + +class ReadableStreamSource; + +class ReadableStreamDefaultController { +public: + explicit ReadableStreamDefaultController(JSReadableStreamDefaultController* controller) : m_jsController(controller) { } + + static JSC::JSValue invoke(JSC::ExecState&, JSC::JSObject&, const char*, JSC::JSValue); + + bool enqueue(RefPtr<JSC::ArrayBuffer>&&); + + template<class ResolveResultType> + void error(const ResolveResultType&); + + void close() { invoke(*globalObject().globalExec(), jsController(), "close", JSC::jsUndefined()); } + + bool isControlledReadableStreamLocked() const; + +private: + void error(JSC::ExecState& state, JSC::JSValue value) { invoke(state, jsController(), "error", value); } + void enqueue(JSC::ExecState& state, JSC::JSValue value) { invoke(state, jsController(), "enqueue", value); } + JSReadableStreamDefaultController& jsController() const; + + JSDOMGlobalObject& globalObject() const; + JSC::ExecState& globalExec() const; + + // The owner of ReadableStreamDefaultController is responsible to keep uncollected the JSReadableStreamDefaultController. + JSReadableStreamDefaultController* m_jsController { nullptr }; +}; + +inline JSReadableStreamDefaultController& ReadableStreamDefaultController::jsController() const +{ + ASSERT(m_jsController); + return *m_jsController; +} + +inline JSDOMGlobalObject& ReadableStreamDefaultController::globalObject() const +{ + ASSERT(m_jsController); + ASSERT(m_jsController->globalObject()); + return *static_cast<JSDOMGlobalObject*>(m_jsController->globalObject()); +} + +inline JSC::ExecState& ReadableStreamDefaultController::globalExec() const +{ + ASSERT(globalObject().globalExec()); + return *globalObject().globalExec(); +} + +inline bool ReadableStreamDefaultController::enqueue(RefPtr<JSC::ArrayBuffer>&& buffer) +{ + auto& globalObject = this->globalObject(); + JSC::VM& vm = globalObject.vm(); + JSC::JSLockHolder locker(vm); + auto scope = DECLARE_THROW_SCOPE(vm); + JSC::ExecState& state = globalExec(); + + if (!buffer) { + error(state, createOutOfMemoryError(&state)); + return false; + } + auto length = buffer->byteLength(); + auto chunk = JSC::Uint8Array::create(WTFMove(buffer), 0, length); + ASSERT(chunk); + enqueue(state, toJS(&state, &globalObject, chunk.get())); + ASSERT_UNUSED(scope, !scope.exception()); + return true; +} + +template<> +inline void ReadableStreamDefaultController::error<String>(const String& errorMessage) +{ + JSC::ExecState& state = globalExec(); + JSC::JSLockHolder locker(&state); + error(state, JSC::createTypeError(&state, errorMessage)); +} + +} // namespace WebCore + +#endif // ENABLE(READABLE_STREAM_API) diff --git a/Source/WebCore/bindings/js/ScheduledAction.cpp b/Source/WebCore/bindings/js/ScheduledAction.cpp index 9173edd49..93332666b 100644 --- a/Source/WebCore/bindings/js/ScheduledAction.cpp +++ b/Source/WebCore/bindings/js/ScheduledAction.cpp @@ -29,7 +29,7 @@ #include "Document.h" #include "Frame.h" #include "FrameLoader.h" -#include "JSDOMBinding.h" +#include "JSDOMExceptionHandling.h" #include "JSDOMWindow.h" #include "JSMainThreadExecState.h" #include "JSMainThreadExecStateInstrumentation.h" @@ -39,27 +39,28 @@ #include "ScriptSourceCode.h" #include "WorkerGlobalScope.h" #include "WorkerThread.h" -#include <bindings/ScriptValue.h> #include <runtime/JSLock.h> using namespace JSC; namespace WebCore { -PassOwnPtr<ScheduledAction> ScheduledAction::create(ExecState* exec, DOMWrapperWorld& isolatedWorld, ContentSecurityPolicy* policy) +std::unique_ptr<ScheduledAction> ScheduledAction::create(ExecState* exec, DOMWrapperWorld& isolatedWorld, ContentSecurityPolicy* policy) { + VM& vm = exec->vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + JSValue v = exec->argument(0); CallData callData; - if (getCallData(v, callData) == CallTypeNone) { + if (getCallData(v, callData) == CallType::None) { if (policy && !policy->allowEval(exec)) return nullptr; - String string = v.toString(exec)->value(exec); - if (exec->hadException()) - return nullptr; - return adoptPtr(new ScheduledAction(string, isolatedWorld)); + String string = v.toWTFString(exec); + RETURN_IF_EXCEPTION(scope, nullptr); + return std::unique_ptr<ScheduledAction>(new ScheduledAction(string, isolatedWorld)); } - return adoptPtr(new ScheduledAction(exec, v, isolatedWorld)); + return std::unique_ptr<ScheduledAction>(new ScheduledAction(exec, v, isolatedWorld)); } ScheduledAction::ScheduledAction(ExecState* exec, JSValue function, DOMWrapperWorld& isolatedWorld) @@ -72,24 +73,22 @@ ScheduledAction::ScheduledAction(ExecState* exec, JSValue function, DOMWrapperWo m_args.append(Strong<JSC::Unknown>(exec->vm(), exec->uncheckedArgument(i))); } -void ScheduledAction::execute(ScriptExecutionContext* context) +void ScheduledAction::execute(ScriptExecutionContext& context) { - if (context->isDocument()) - execute(toDocument(context)); - else { - ASSERT_WITH_SECURITY_IMPLICATION(context->isWorkerGlobalScope()); - execute(static_cast<WorkerGlobalScope*>(context)); - } + if (is<Document>(context)) + execute(downcast<Document>(context)); + else + execute(downcast<WorkerGlobalScope>(context)); } -void ScheduledAction::executeFunctionInContext(JSGlobalObject* globalObject, JSValue thisValue, ScriptExecutionContext* context) +void ScheduledAction::executeFunctionInContext(JSGlobalObject* globalObject, JSValue thisValue, ScriptExecutionContext& context) { ASSERT(m_function); - JSLockHolder lock(context->vm()); + JSLockHolder lock(context.vm()); CallData callData; CallType callType = getCallData(m_function.get(), callData); - if (callType == CallTypeNone) + if (callType == CallType::None) return; ExecState* exec = globalObject->globalExec(); @@ -99,26 +98,27 @@ void ScheduledAction::executeFunctionInContext(JSGlobalObject* globalObject, JSV for (size_t i = 0; i < size; ++i) args.append(m_args[i].get()); - InspectorInstrumentationCookie cookie = JSMainThreadExecState::instrumentFunctionCall(context, callType, callData); + InspectorInstrumentationCookie cookie = JSMainThreadExecState::instrumentFunctionCall(&context, callType, callData); - if (context->isDocument()) - JSMainThreadExecState::call(exec, m_function.get(), callType, callData, thisValue, args); + NakedPtr<JSC::Exception> exception; + if (is<Document>(context)) + JSMainThreadExecState::profiledCall(exec, JSC::ProfilingReason::Other, m_function.get(), callType, callData, thisValue, args, exception); else - JSC::call(exec, m_function.get(), callType, callData, thisValue, args); + JSC::profiledCall(exec, JSC::ProfilingReason::Other, m_function.get(), callType, callData, thisValue, args, exception); - InspectorInstrumentation::didCallFunction(cookie); + InspectorInstrumentation::didCallFunction(cookie, &context); - if (exec->hadException()) - reportCurrentException(exec); + if (exception) + reportException(exec, exception); } -void ScheduledAction::execute(Document* document) +void ScheduledAction::execute(Document& document) { - JSDOMWindow* window = toJSDOMWindow(document->frame(), *m_isolatedWorld); + JSDOMWindow* window = toJSDOMWindow(document.frame(), *m_isolatedWorld); if (!window) return; - RefPtr<Frame> frame = window->impl().frame(); + RefPtr<Frame> frame = window->wrapped().frame(); if (!frame || !frame->script().canExecuteScripts(AboutToExecuteScript)) return; @@ -128,18 +128,18 @@ void ScheduledAction::execute(Document* document) frame->script().executeScriptInWorld(*m_isolatedWorld, m_code); } -void ScheduledAction::execute(WorkerGlobalScope* workerGlobalScope) +void ScheduledAction::execute(WorkerGlobalScope& workerGlobalScope) { // In a Worker, the execution should always happen on a worker thread. - ASSERT(workerGlobalScope->thread()->threadID() == currentThread()); + ASSERT(workerGlobalScope.thread().threadID() == currentThread()); - WorkerScriptController* scriptController = workerGlobalScope->script(); + WorkerScriptController* scriptController = workerGlobalScope.script(); if (m_function) { JSWorkerGlobalScope* contextWrapper = scriptController->workerGlobalScopeWrapper(); executeFunctionInContext(contextWrapper, contextWrapper, workerGlobalScope); } else { - ScriptSourceCode code(m_code, workerGlobalScope->url()); + ScriptSourceCode code(m_code, workerGlobalScope.url()); scriptController->evaluate(code); } } diff --git a/Source/WebCore/bindings/js/ScheduledAction.h b/Source/WebCore/bindings/js/ScheduledAction.h index 19add3fe8..dac8579ea 100644 --- a/Source/WebCore/bindings/js/ScheduledAction.h +++ b/Source/WebCore/bindings/js/ScheduledAction.h @@ -17,14 +17,13 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#ifndef ScheduledAction_h -#define ScheduledAction_h +#pragma once #include "JSDOMBinding.h" #include <heap/Strong.h> #include <heap/StrongInlines.h> +#include <memory> #include <runtime/JSCell.h> -#include <wtf/PassOwnPtr.h> #include <wtf/Vector.h> #include <wtf/text/WTFString.h> @@ -46,22 +45,22 @@ namespace WebCore { class ScheduledAction { WTF_MAKE_NONCOPYABLE(ScheduledAction); WTF_MAKE_FAST_ALLOCATED; public: - static PassOwnPtr<ScheduledAction> create(JSC::ExecState*, DOMWrapperWorld& isolatedWorld, ContentSecurityPolicy*); + static std::unique_ptr<ScheduledAction> create(JSC::ExecState*, DOMWrapperWorld& isolatedWorld, ContentSecurityPolicy*); - void execute(ScriptExecutionContext*); + void execute(ScriptExecutionContext&); private: ScheduledAction(JSC::ExecState*, JSC::JSValue function, DOMWrapperWorld& isolatedWorld); ScheduledAction(const String& code, DOMWrapperWorld& isolatedWorld) - : m_function(*isolatedWorld.vm()) + : m_function(isolatedWorld.vm()) , m_code(code) , m_isolatedWorld(&isolatedWorld) { } - void executeFunctionInContext(JSC::JSGlobalObject*, JSC::JSValue thisValue, ScriptExecutionContext*); - void execute(Document*); - void execute(WorkerGlobalScope*); + void executeFunctionInContext(JSC::JSGlobalObject*, JSC::JSValue thisValue, ScriptExecutionContext&); + void execute(Document&); + void execute(WorkerGlobalScope&); JSC::Strong<JSC::Unknown> m_function; Vector<JSC::Strong<JSC::Unknown>> m_args; @@ -70,5 +69,3 @@ namespace WebCore { }; } // namespace WebCore - -#endif // ScheduledAction_h diff --git a/Source/WebCore/bindings/js/ScriptCachedFrameData.cpp b/Source/WebCore/bindings/js/ScriptCachedFrameData.cpp index c4e12f942..1196db791 100644 --- a/Source/WebCore/bindings/js/ScriptCachedFrameData.cpp +++ b/Source/WebCore/bindings/js/ScriptCachedFrameData.cpp @@ -1,11 +1,11 @@ /* * Copyright (c) 2008, Google Inc. All rights reserved. * Copyright (C) 2008 Apple Inc. All Rights Reserved. - * + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: - * + * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above @@ -15,7 +15,7 @@ * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. - * + * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -32,14 +32,17 @@ #include "config.h" #include "ScriptCachedFrameData.h" +#include "CommonVM.h" #include "Document.h" #include "Frame.h" #include "GCController.h" #include "Page.h" +#include "PageConsoleClient.h" #include "PageGroup.h" +#include "ScriptController.h" #include <heap/StrongInlines.h> #include <runtime/JSLock.h> -#include "ScriptController.h" +#include <runtime/WeakGCMapInlines.h> using namespace JSC; @@ -47,18 +50,19 @@ namespace WebCore { ScriptCachedFrameData::ScriptCachedFrameData(Frame& frame) { - JSLockHolder lock(JSDOMWindowBase::commonVM()); + JSLockHolder lock(commonVM()); ScriptController& scriptController = frame.script(); - ScriptController::ShellMap& windowShells = scriptController.m_windowShells; + Vector<JSC::Strong<JSDOMWindowShell>> windowShells = scriptController.windowShells(); - ScriptController::ShellMap::iterator windowShellsEnd = windowShells.end(); - for (ScriptController::ShellMap::iterator iter = windowShells.begin(); iter != windowShellsEnd; ++iter) { - JSDOMWindow* window = iter->value->window(); - m_windows.add(iter->key.get(), Strong<JSDOMWindow>(window->vm(), window)); + for (size_t i = 0; i < windowShells.size(); ++i) { + JSDOMWindowShell* windowShell = windowShells[i].get(); + JSDOMWindow* window = windowShell->window(); + m_windows.add(&windowShell->world(), Strong<JSDOMWindow>(window->vm(), window)); + window->setConsoleClient(nullptr); } - scriptController.attachDebugger(0); + scriptController.attachDebugger(nullptr); } ScriptCachedFrameData::~ScriptCachedFrameData() @@ -68,29 +72,33 @@ ScriptCachedFrameData::~ScriptCachedFrameData() void ScriptCachedFrameData::restore(Frame& frame) { - JSLockHolder lock(JSDOMWindowBase::commonVM()); + JSLockHolder lock(commonVM()); + Page* page = frame.page(); ScriptController& scriptController = frame.script(); - ScriptController::ShellMap& windowShells = scriptController.m_windowShells; + Vector<JSC::Strong<JSDOMWindowShell>> windowShells = scriptController.windowShells(); - for (auto it = windowShells.begin(), end = windowShells.end(); it != end; ++it) { - DOMWrapperWorld* world = it->key.get(); - JSDOMWindowShell* windowShell = it->value.get(); + for (size_t i = 0; i < windowShells.size(); ++i) { + JSDOMWindowShell* windowShell = windowShells[i].get(); + DOMWrapperWorld* world = &windowShell->world(); if (JSDOMWindow* window = m_windows.get(world).get()) windowShell->setWindow(window->vm(), window); else { DOMWindow* domWindow = frame.document()->domWindow(); - if (&windowShell->window()->impl() == domWindow) + if (&windowShell->window()->wrapped() == domWindow) continue; windowShell->setWindow(domWindow); - if (Page* page = frame.page()) { + if (page) { scriptController.attachDebugger(windowShell, page->debugger()); windowShell->window()->setProfileGroup(page->group().identifier()); } } + + if (page) + windowShell->window()->setConsoleClient(&page->console()); } } @@ -99,9 +107,9 @@ void ScriptCachedFrameData::clear() if (m_windows.isEmpty()) return; - JSLockHolder lock(JSDOMWindowBase::commonVM()); + JSLockHolder lock(commonVM()); m_windows.clear(); - gcController().garbageCollectSoon(); + GCController::singleton().garbageCollectSoon(); } } // namespace WebCore diff --git a/Source/WebCore/bindings/js/ScriptCachedFrameData.h b/Source/WebCore/bindings/js/ScriptCachedFrameData.h index 55b98e3be..eff5e3802 100644 --- a/Source/WebCore/bindings/js/ScriptCachedFrameData.h +++ b/Source/WebCore/bindings/js/ScriptCachedFrameData.h @@ -29,8 +29,7 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef ScriptCachedFrameData_h -#define ScriptCachedFrameData_h +#pragma once #include <heap/Strong.h> #include <wtf/HashMap.h> @@ -56,5 +55,3 @@ private: }; } // namespace WebCore - -#endif // ScriptCachedFrameData_h diff --git a/Source/WebCore/bindings/js/ScriptCallStackFactory.cpp b/Source/WebCore/bindings/js/ScriptCallStackFactory.cpp deleted file mode 100644 index 7d695a444..000000000 --- a/Source/WebCore/bindings/js/ScriptCallStackFactory.cpp +++ /dev/null @@ -1,209 +0,0 @@ -/* - * Copyright (c) 2010 Google Inc. All rights reserved. - * Copyright (C) 2012 Research In Motion Limited. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" -#include "ScriptCallStackFactory.h" - -#include "InspectorInstrumentation.h" -#include "JSDOMBinding.h" -#include "JSMainThreadExecState.h" -#include "ScriptArguments.h" -#include "ScriptCallFrame.h" -#include "ScriptCallStack.h" -#include <bindings/ScriptValue.h> -#include <interpreter/CallFrame.h> -#include <interpreter/CallFrameInlines.h> -#include <interpreter/StackVisitor.h> -#include <runtime/ArgList.h> -#include <runtime/JSCJSValue.h> -#include <runtime/JSFunction.h> -#include <runtime/VM.h> -#include <wtf/text/WTFString.h> - -using namespace JSC; - -namespace WebCore { - -class ScriptExecutionContext; - -class CreateScriptCallStackFunctor { -public: - CreateScriptCallStackFunctor(Vector<ScriptCallFrame>& frames, size_t remainingCapacity) - : m_frames(frames) - , m_remainingCapacityForFrameCapture(remainingCapacity) - { - } - - StackVisitor::Status operator()(StackVisitor& visitor) - { - if (m_remainingCapacityForFrameCapture) { - unsigned line; - unsigned column; - visitor->computeLineAndColumn(line, column); - m_frames.append(ScriptCallFrame(visitor->functionName(), visitor->sourceURL(), line, column)); - - m_remainingCapacityForFrameCapture--; - return StackVisitor::Continue; - } - return StackVisitor::Done; - } - -private: - Vector<ScriptCallFrame>& m_frames; - size_t m_remainingCapacityForFrameCapture; -}; - -PassRefPtr<ScriptCallStack> createScriptCallStack(size_t maxStackSize, bool emptyIsAllowed) -{ - Vector<ScriptCallFrame> frames; - if (JSC::ExecState* exec = JSMainThreadExecState::currentState()) { - CallFrame* frame = exec->vm().topCallFrame; - CreateScriptCallStackFunctor functor(frames, maxStackSize); - frame->iterate(functor); - } - if (frames.isEmpty() && !emptyIsAllowed) { - // No frames found. It may happen in the case where - // a bound function is called from native code for example. - // Fallback to setting lineNumber to 0, and source and function name to "undefined". - frames.append(ScriptCallFrame("undefined", "undefined", 0, 0)); - } - return ScriptCallStack::create(frames); -} - -class CreateScriptCallStackForConsoleFunctor { -public: - CreateScriptCallStackForConsoleFunctor(bool needToSkipAFrame, size_t remainingCapacity, Vector<ScriptCallFrame>& frames) - : m_needToSkipAFrame(needToSkipAFrame) - , m_remainingCapacityForFrameCapture(remainingCapacity) - , m_frames(frames) - { - } - - StackVisitor::Status operator()(StackVisitor& visitor) - { - if (m_needToSkipAFrame) { - m_needToSkipAFrame = false; - return StackVisitor::Continue; - } - - if (m_remainingCapacityForFrameCapture) { - // This early exit is necessary to maintain our old behaviour - // but the stack trace we produce now is complete and handles all - // ways in which code may be running - if (!visitor->callee() && m_frames.size()) - return StackVisitor::Done; - - unsigned line; - unsigned column; - visitor->computeLineAndColumn(line, column); - m_frames.append(ScriptCallFrame(visitor->functionName(), visitor->sourceURL(), line, column)); - - m_remainingCapacityForFrameCapture--; - return StackVisitor::Continue; - } - return StackVisitor::Done; - } - -private: - bool m_needToSkipAFrame; - size_t m_remainingCapacityForFrameCapture; - Vector<ScriptCallFrame>& m_frames; -}; - -PassRefPtr<ScriptCallStack> createScriptCallStack(JSC::ExecState* exec, size_t maxStackSize) -{ - Vector<ScriptCallFrame> frames; - ASSERT(exec); - CallFrame* frame = exec->vm().topCallFrame; - CreateScriptCallStackForConsoleFunctor functor(true, maxStackSize, frames); - frame->iterate(functor); - if (frames.isEmpty()) { - CreateScriptCallStackForConsoleFunctor functor(false, maxStackSize, frames); - frame->iterate(functor); - } - return ScriptCallStack::create(frames); -} - -PassRefPtr<ScriptCallStack> createScriptCallStackFromException(JSC::ExecState* exec, JSC::JSValue& exception, size_t maxStackSize) -{ - Vector<ScriptCallFrame> frames; - RefCountedArray<StackFrame> stackTrace = exec->vm().exceptionStack(); - for (size_t i = 0; i < stackTrace.size() && i < maxStackSize; i++) { - if (!stackTrace[i].callee && frames.size()) - break; - - String functionName = stackTrace[i].friendlyFunctionName(exec); - unsigned line; - unsigned column; - stackTrace[i].computeLineAndColumn(line, column); - frames.append(ScriptCallFrame(functionName, stackTrace[i].sourceURL, line, column)); - } - - // FIXME: <http://webkit.org/b/115087> Web Inspector: WebCore::reportException should not evaluate JavaScript handling exceptions - // Fallback to getting at least the line and sourceURL from the exception if it has values and the exceptionStack doesn't. - if (frames.size() > 0) { - const ScriptCallFrame& firstCallFrame = frames.first(); - JSObject* exceptionObject = exception.toObject(exec); - if (exception.isObject() && firstCallFrame.sourceURL().isEmpty()) { - JSValue lineValue = exceptionObject->getDirect(exec->vm(), Identifier(exec, "line")); - int lineNumber = lineValue && lineValue.isNumber() ? int(lineValue.toNumber(exec)) : 0; - JSValue columnValue = exceptionObject->getDirect(exec->vm(), Identifier(exec, "column")); - int columnNumber = columnValue && columnValue.isNumber() ? int(columnValue.toNumber(exec)) : 0; - JSValue sourceURLValue = exceptionObject->getDirect(exec->vm(), Identifier(exec, "sourceURL")); - String exceptionSourceURL = sourceURLValue && sourceURLValue.isString() ? sourceURLValue.toString(exec)->value(exec) : ASCIILiteral("undefined"); - frames[0] = ScriptCallFrame(firstCallFrame.functionName(), exceptionSourceURL, lineNumber, columnNumber); - } - } - - return ScriptCallStack::create(frames); -} - -PassRefPtr<ScriptCallStack> createScriptCallStackForConsole(JSC::ExecState* exec) -{ - size_t maxStackSize = 1; - if (InspectorInstrumentation::hasFrontends()) { - ScriptExecutionContext* scriptExecutionContext = jsCast<JSDOMGlobalObject*>(exec->lexicalGlobalObject())->scriptExecutionContext(); - if (InspectorInstrumentation::consoleAgentEnabled(scriptExecutionContext)) - maxStackSize = ScriptCallStack::maxCallStackSizeToCapture; - } - return createScriptCallStack(exec, maxStackSize); -} - -PassRefPtr<ScriptArguments> createScriptArguments(JSC::ExecState* exec, unsigned skipArgumentCount) -{ - Vector<Deprecated::ScriptValue> arguments; - size_t argumentCount = exec->argumentCount(); - for (size_t i = skipArgumentCount; i < argumentCount; ++i) - arguments.append(Deprecated::ScriptValue(exec->vm(), exec->uncheckedArgument(i))); - return ScriptArguments::create(exec, arguments); -} - -} // namespace WebCore diff --git a/Source/WebCore/bindings/js/ScriptCallStackFactory.h b/Source/WebCore/bindings/js/ScriptCallStackFactory.h deleted file mode 100644 index 298bbbd40..000000000 --- a/Source/WebCore/bindings/js/ScriptCallStackFactory.h +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright (c) 2010 Google Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef ScriptCallStackFactory_h -#define ScriptCallStackFactory_h - -#include <wtf/Forward.h> -#include <wtf/RefCountedArray.h> - -namespace JSC { -class ExecState; -class JSValue; -struct StackFrame; -} - -namespace WebCore { - -class ScriptArguments; -class ScriptCallStack; - -PassRefPtr<ScriptCallStack> createScriptCallStack(size_t maxStackSize, bool emptyStackIsAllowed); -PassRefPtr<ScriptCallStack> createScriptCallStack(JSC::ExecState*, size_t maxStackSize); -PassRefPtr<ScriptCallStack> createScriptCallStackFromException(JSC::ExecState*, JSC::JSValue& exception, size_t maxStackSize); -PassRefPtr<ScriptCallStack> createScriptCallStackForConsole(JSC::ExecState*); -PassRefPtr<ScriptArguments> createScriptArguments(JSC::ExecState*, unsigned skipArgumentCount); - -} // namespace WebCore - -#endif // ScriptCallStackFactory_h diff --git a/Source/WebCore/bindings/js/ScriptController.cpp b/Source/WebCore/bindings/js/ScriptController.cpp index c0135ae8d..68eb91bed 100644 --- a/Source/WebCore/bindings/js/ScriptController.cpp +++ b/Source/WebCore/bindings/js/ScriptController.cpp @@ -1,7 +1,7 @@ /* * Copyright (C) 1999-2001 Harri Porten (porten@kde.org) * Copyright (C) 2001 Peter Kelly (pmk@post.com) - * Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved. + * Copyright (C) 2006-2016 Apple Inc. All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -22,36 +22,48 @@ #include "ScriptController.h" #include "BridgeJSC.h" +#include "CachedScriptFetcher.h" +#include "CommonVM.h" #include "ContentSecurityPolicy.h" #include "DocumentLoader.h" #include "Event.h" -#include "EventNames.h" #include "Frame.h" #include "FrameLoaderClient.h" #include "GCController.h" #include "HTMLPlugInElement.h" #include "InspectorInstrumentation.h" +#include "JSDOMBindingSecurity.h" +#include "JSDOMExceptionHandling.h" #include "JSDOMWindow.h" #include "JSDocument.h" #include "JSMainThreadExecState.h" +#include "LoadableModuleScript.h" +#include "MainFrame.h" +#include "MemoryPressureHandler.h" +#include "ModuleFetchFailureKind.h" #include "NP_jsobject.h" #include "Page.h" +#include "PageConsoleClient.h" #include "PageGroup.h" -#include "PluginView.h" -#include "ScriptCallStack.h" +#include "PluginViewBase.h" #include "ScriptSourceCode.h" #include "ScriptableDocumentParser.h" #include "Settings.h" -#include "StorageNamespace.h" #include "UserGestureIndicator.h" #include "WebCoreJSClientData.h" #include "npruntime_impl.h" #include "runtime_root.h" -#include <bindings/ScriptValue.h> #include <debugger/Debugger.h> #include <heap/StrongInlines.h> +#include <inspector/ScriptCallStack.h> #include <runtime/InitializeThreading.h> +#include <runtime/JSFunction.h> +#include <runtime/JSInternalPromise.h> #include <runtime/JSLock.h> +#include <runtime/JSModuleRecord.h> +#include <runtime/JSNativeStdFunction.h> +#include <runtime/JSScriptFetcher.h> +#include <wtf/SetForScope.h> #include <wtf/Threading.h> #include <wtf/text/TextPosition.h> @@ -59,6 +71,18 @@ using namespace JSC; namespace WebCore { +static void collectGarbageAfterWindowShellDestruction() +{ + // Make sure to GC Extra Soon(tm) during memory pressure conditions + // to soften high peaks of memory usage during navigation. + if (MemoryPressureHandler::singleton().isUnderMemoryPressure()) { + // NOTE: We do the collection on next runloop to ensure that there's no pointer + // to the window object on the stack. + GCController::singleton().garbageCollectOnNextRunLoop(); + } else + GCController::singleton().garbageCollectSoon(); +} + void ScriptController::initializeThreading() { #if !PLATFORM(IOS) @@ -74,7 +98,7 @@ ScriptController::ScriptController(Frame& frame) #if ENABLE(NETSCAPE_PLUGIN_API) , m_windowScriptNPObject(0) #endif -#if PLATFORM(MAC) +#if PLATFORM(COCOA) , m_windowScriptObject(0) #endif { @@ -85,16 +109,19 @@ ScriptController::~ScriptController() disconnectPlatformScriptObjects(); if (m_cacheableBindingRootObject) { - JSLockHolder lock(JSDOMWindowBase::commonVM()); + JSLockHolder lock(commonVM()); m_cacheableBindingRootObject->invalidate(); - m_cacheableBindingRootObject = 0; + m_cacheableBindingRootObject = nullptr; } // It's likely that destroying m_windowShells will create a lot of garbage. if (!m_windowShells.isEmpty()) { - while (!m_windowShells.isEmpty()) - destroyWindowShell(*m_windowShells.begin()->key); - gcController().garbageCollectSoon(); + while (!m_windowShells.isEmpty()) { + ShellMap::iterator iter = m_windowShells.begin(); + iter->value->window()->setConsoleClient(nullptr); + destroyWindowShell(*iter->key); + } + collectGarbageAfterWindowShellDestruction(); } } @@ -105,22 +132,24 @@ void ScriptController::destroyWindowShell(DOMWrapperWorld& world) world.didDestroyWindowShell(this); } -JSDOMWindowShell* ScriptController::createWindowShell(DOMWrapperWorld& world) +JSDOMWindowShell& ScriptController::createWindowShell(DOMWrapperWorld& world) { ASSERT(!m_windowShells.contains(&world)); - VM& vm = *world.vm(); + VM& vm = world.vm(); Structure* structure = JSDOMWindowShell::createStructure(vm, jsNull()); Strong<JSDOMWindowShell> windowShell(vm, JSDOMWindowShell::create(vm, m_frame.document()->domWindow(), structure, world)); Strong<JSDOMWindowShell> windowShell2(windowShell); m_windowShells.add(&world, windowShell); world.didCreateWindowShell(this); - return windowShell.get(); + return *windowShell.get(); } -Deprecated::ScriptValue ScriptController::evaluateInWorld(const ScriptSourceCode& sourceCode, DOMWrapperWorld& world) +JSValue ScriptController::evaluateInWorld(const ScriptSourceCode& sourceCode, DOMWrapperWorld& world, ExceptionDetails* exceptionDetails) { + JSLockHolder lock(world.vm()); + const SourceCode& jsSourceCode = sourceCode.jsSourceCode(); String sourceURL = jsSourceCode.provider()->url(); @@ -136,77 +165,178 @@ Deprecated::ScriptValue ScriptController::evaluateInWorld(const ScriptSourceCode const String* savedSourceURL = m_sourceURL; m_sourceURL = &sourceURL; - JSLockHolder lock(exec); - - Ref<Frame> protect(m_frame); - - InspectorInstrumentationCookie cookie = InspectorInstrumentation::willEvaluateScript(&m_frame, sourceURL, sourceCode.startLine()); + Ref<Frame> protector(m_frame); - JSValue evaluationException; + InspectorInstrumentationCookie cookie = InspectorInstrumentation::willEvaluateScript(m_frame, sourceURL, sourceCode.startLine()); - JSValue returnValue = JSMainThreadExecState::evaluate(exec, jsSourceCode, shell, &evaluationException); + NakedPtr<JSC::Exception> evaluationException; + JSValue returnValue = JSMainThreadExecState::profiledEvaluate(exec, JSC::ProfilingReason::Other, jsSourceCode, shell, evaluationException); - InspectorInstrumentation::didEvaluateScript(cookie); + InspectorInstrumentation::didEvaluateScript(cookie, m_frame); if (evaluationException) { - reportException(exec, evaluationException, sourceCode.cachedScript()); + reportException(exec, evaluationException, sourceCode.cachedScript(), exceptionDetails); m_sourceURL = savedSourceURL; - return Deprecated::ScriptValue(); + return { }; } m_sourceURL = savedSourceURL; - return Deprecated::ScriptValue(exec->vm(), returnValue); + return returnValue; +} + +JSValue ScriptController::evaluate(const ScriptSourceCode& sourceCode, ExceptionDetails* exceptionDetails) +{ + return evaluateInWorld(sourceCode, mainThreadNormalWorld(), exceptionDetails); +} + +void ScriptController::loadModuleScriptInWorld(LoadableModuleScript& moduleScript, const String& moduleName, DOMWrapperWorld& world) +{ + JSLockHolder lock(world.vm()); + + auto& shell = *windowShell(world); + auto& state = *shell.window()->globalExec(); + + auto& promise = JSMainThreadExecState::loadModule(state, moduleName, JSC::JSScriptFetcher::create(state.vm(), { &moduleScript })); + setupModuleScriptHandlers(moduleScript, promise, world); +} + +void ScriptController::loadModuleScript(LoadableModuleScript& moduleScript, const String& moduleName) +{ + loadModuleScriptInWorld(moduleScript, moduleName, mainThreadNormalWorld()); +} + +void ScriptController::loadModuleScriptInWorld(LoadableModuleScript& moduleScript, const ScriptSourceCode& sourceCode, DOMWrapperWorld& world) +{ + JSLockHolder lock(world.vm()); + + auto& shell = *windowShell(world); + auto& state = *shell.window()->globalExec(); + + auto& promise = JSMainThreadExecState::loadModule(state, sourceCode.jsSourceCode(), JSC::JSScriptFetcher::create(state.vm(), { &moduleScript })); + setupModuleScriptHandlers(moduleScript, promise, world); +} + +void ScriptController::loadModuleScript(LoadableModuleScript& moduleScript, const ScriptSourceCode& sourceCode) +{ + loadModuleScriptInWorld(moduleScript, sourceCode, mainThreadNormalWorld()); +} + +JSC::JSValue ScriptController::linkAndEvaluateModuleScriptInWorld(LoadableModuleScript& moduleScript, DOMWrapperWorld& world) +{ + JSLockHolder lock(world.vm()); + + auto& shell = *windowShell(world); + auto& state = *shell.window()->globalExec(); + + // FIXME: Preventing Frame from being destroyed is essentially unnecessary. + // https://bugs.webkit.org/show_bug.cgi?id=164763 + Ref<Frame> protector(m_frame); + + NakedPtr<JSC::Exception> evaluationException; + auto returnValue = JSMainThreadExecState::linkAndEvaluateModule(state, Identifier::fromUid(&state.vm(), moduleScript.moduleKey()), jsUndefined(), evaluationException); + if (evaluationException) { + // FIXME: Give a chance to dump the stack trace if the "crossorigin" attribute allows. + // https://bugs.webkit.org/show_bug.cgi?id=164539 + reportException(&state, evaluationException, nullptr); + return jsUndefined(); + } + return returnValue; +} + +JSC::JSValue ScriptController::linkAndEvaluateModuleScript(LoadableModuleScript& moduleScript) +{ + return linkAndEvaluateModuleScriptInWorld(moduleScript, mainThreadNormalWorld()); +} + +JSC::JSValue ScriptController::evaluateModule(const URL& sourceURL, JSModuleRecord& moduleRecord, DOMWrapperWorld& world) +{ + JSLockHolder lock(world.vm()); + + const auto& jsSourceCode = moduleRecord.sourceCode(); + + auto& shell = *windowShell(world); + auto& state = *shell.window()->globalExec(); + SetForScope<const String*> sourceURLScope(m_sourceURL, &sourceURL.string()); + + Ref<Frame> protector(m_frame); + + auto cookie = InspectorInstrumentation::willEvaluateScript(m_frame, sourceURL, jsSourceCode.firstLine().oneBasedInt()); + + auto returnValue = moduleRecord.evaluate(&state); + InspectorInstrumentation::didEvaluateScript(cookie, m_frame); + + return returnValue; +} + +JSC::JSValue ScriptController::evaluateModule(const URL& sourceURL, JSModuleRecord& moduleRecord) +{ + return evaluateModule(sourceURL, moduleRecord, mainThreadNormalWorld()); } -Deprecated::ScriptValue ScriptController::evaluate(const ScriptSourceCode& sourceCode) +Ref<DOMWrapperWorld> ScriptController::createWorld() { - return evaluateInWorld(sourceCode, mainThreadNormalWorld()); + return DOMWrapperWorld::create(commonVM()); } -PassRefPtr<DOMWrapperWorld> ScriptController::createWorld() +Vector<JSC::Strong<JSDOMWindowShell>> ScriptController::windowShells() { - return DOMWrapperWorld::create(JSDOMWindow::commonVM()); + Vector<JSC::Strong<JSDOMWindowShell>> windowShells; + copyValuesToVector(m_windowShells, windowShells); + return windowShells; } void ScriptController::getAllWorlds(Vector<Ref<DOMWrapperWorld>>& worlds) { - static_cast<WebCoreJSClientData*>(JSDOMWindow::commonVM()->clientData)->getAllWorlds(worlds); + static_cast<JSVMClientData*>(commonVM().clientData)->getAllWorlds(worlds); } -void ScriptController::clearWindowShell(DOMWindow* newDOMWindow, bool goingIntoPageCache) +void ScriptController::clearWindowShellsNotMatchingDOMWindow(DOMWindow* newDOMWindow, bool goingIntoPageCache) { if (m_windowShells.isEmpty()) return; - JSLockHolder lock(JSDOMWindowBase::commonVM()); + JSLockHolder lock(commonVM()); - for (ShellMap::iterator iter = m_windowShells.begin(); iter != m_windowShells.end(); ++iter) { - JSDOMWindowShell* windowShell = iter->value.get(); - - if (&windowShell->window()->impl() == newDOMWindow) + for (auto& windowShell : windowShells()) { + if (&windowShell->window()->wrapped() == newDOMWindow) continue; - // Clear the debugger from the current window before setting the new window. - attachDebugger(windowShell, 0); - + // Clear the debugger and console from the current window before setting the new window. + attachDebugger(windowShell.get(), nullptr); + windowShell->window()->setConsoleClient(nullptr); windowShell->window()->willRemoveFromWindowShell(); - windowShell->setWindow(newDOMWindow); + } + // It's likely that resetting our windows created a lot of garbage, unless + // it went in a back/forward cache. + if (!goingIntoPageCache) + collectGarbageAfterWindowShellDestruction(); +} + +void ScriptController::setDOMWindowForWindowShell(DOMWindow* newDOMWindow) +{ + if (m_windowShells.isEmpty()) + return; + + JSLockHolder lock(commonVM()); + + for (auto& windowShell : windowShells()) { + if (&windowShell->window()->wrapped() == newDOMWindow) + continue; + + windowShell->setWindow(newDOMWindow); + // An m_cacheableBindingRootObject persists between page navigations // so needs to know about the new JSDOMWindow. if (m_cacheableBindingRootObject) m_cacheableBindingRootObject->updateGlobalObject(windowShell->window()); if (Page* page = m_frame.page()) { - attachDebugger(windowShell, page->debugger()); + attachDebugger(windowShell.get(), page->debugger()); windowShell->window()->setProfileGroup(page->group().identifier()); + windowShell->window()->setConsoleClient(&page->console()); } } - - // It's likely that resetting our windows created a lot of garbage, unless - // it went in a back/forward cache. - if (!goingIntoPageCache) - gcController().garbageCollectSoon(); } JSDOMWindowShell* ScriptController::initScript(DOMWrapperWorld& world) @@ -215,29 +345,97 @@ JSDOMWindowShell* ScriptController::initScript(DOMWrapperWorld& world) JSLockHolder lock(world.vm()); - JSDOMWindowShell* windowShell = createWindowShell(world); + JSDOMWindowShell& windowShell = createWindowShell(world); - windowShell->window()->updateDocument(); + windowShell.window()->updateDocument(); - if (m_frame.document()) - windowShell->window()->setEvalEnabled(m_frame.document()->contentSecurityPolicy()->allowEval(0, ContentSecurityPolicy::SuppressReport), m_frame.document()->contentSecurityPolicy()->evalDisabledErrorMessage()); + if (Document* document = m_frame.document()) + document->contentSecurityPolicy()->didCreateWindowShell(windowShell); if (Page* page = m_frame.page()) { - attachDebugger(windowShell, page->debugger()); - windowShell->window()->setProfileGroup(page->group().identifier()); + attachDebugger(&windowShell, page->debugger()); + windowShell.window()->setProfileGroup(page->group().identifier()); + windowShell.window()->setConsoleClient(&page->console()); } m_frame.loader().dispatchDidClearWindowObjectInWorld(world); - return windowShell; + return &windowShell; +} + +static Identifier jsValueToModuleKey(ExecState* exec, JSValue value) +{ + if (value.isSymbol()) + return Identifier::fromUid(jsCast<Symbol*>(value)->privateName()); + ASSERT(value.isString()); + return asString(value)->toIdentifier(exec); +} + +void ScriptController::setupModuleScriptHandlers(LoadableModuleScript& moduleScriptRef, JSInternalPromise& promise, DOMWrapperWorld& world) +{ + auto& shell = *windowShell(world); + auto& state = *shell.window()->globalExec(); + + // It is not guaranteed that either fulfillHandler or rejectHandler is eventually called. + // For example, if the page load is canceled, the DeferredPromise used in the module loader pipeline will stop executing JS code. + // Thus the promise returned from this function could remain unresolved. + + RefPtr<LoadableModuleScript> moduleScript(&moduleScriptRef); + + auto& fulfillHandler = *JSNativeStdFunction::create(state.vm(), shell.window(), 1, String(), [moduleScript](ExecState* exec) { + Identifier moduleKey = jsValueToModuleKey(exec, exec->argument(0)); + moduleScript->notifyLoadCompleted(*moduleKey.impl()); + return JSValue::encode(jsUndefined()); + }); + + auto& rejectHandler = *JSNativeStdFunction::create(state.vm(), shell.window(), 1, String(), [moduleScript](ExecState* exec) { + VM& vm = exec->vm(); + JSValue errorValue = exec->argument(0); + if (errorValue.isObject()) { + auto* object = JSC::asObject(errorValue); + if (JSValue failureKindValue = object->getDirect(vm, static_cast<JSVMClientData&>(*vm.clientData).builtinNames().failureKindPrivateName())) { + // This is host propagated error in the module loader pipeline. + switch (static_cast<ModuleFetchFailureKind>(failureKindValue.asInt32())) { + case ModuleFetchFailureKind::WasErrored: + moduleScript->notifyLoadFailed(LoadableScript::Error { + LoadableScript::ErrorType::CachedScript, + std::nullopt + }); + break; + case ModuleFetchFailureKind::WasCanceled: + moduleScript->notifyLoadWasCanceled(); + break; + } + return JSValue::encode(jsUndefined()); + } + } + + auto scope = DECLARE_CATCH_SCOPE(vm); + moduleScript->notifyLoadFailed(LoadableScript::Error { + LoadableScript::ErrorType::CachedScript, + LoadableScript::ConsoleMessage { + MessageSource::JS, + MessageLevel::Error, + retrieveErrorMessage(*exec, vm, errorValue, scope), + } + }); + return JSValue::encode(jsUndefined()); + }); + + promise.then(&state, &fulfillHandler, &rejectHandler); } TextPosition ScriptController::eventHandlerPosition() const { + // FIXME: If we are not currently parsing, we should use our current location + // in JavaScript, to cover cases like "element.setAttribute('click', ...)". + + // FIXME: This location maps to the end of the HTML tag, and not to the + // exact column number belonging to the event handler attribute. ScriptableDocumentParser* parser = m_frame.document()->scriptableDocumentParser(); if (parser) return parser->textPosition(); - return TextPosition::minimumPosition(); + return TextPosition(); } void ScriptController::enableEval() @@ -261,20 +459,27 @@ bool ScriptController::processingUserGesture() return UserGestureIndicator::processingUserGesture(); } -bool ScriptController::canAccessFromCurrentOrigin(Frame *frame) +bool ScriptController::processingUserGestureForMedia() { - ExecState* exec = JSMainThreadExecState::currentState(); - if (exec) - return shouldAllowAccessToFrame(exec, frame); - // If the current state is 0 we're in a call path where the DOM security - // check doesn't apply (eg. parser). - return true; + return UserGestureIndicator::processingUserGestureForMedia(); +} + +bool ScriptController::canAccessFromCurrentOrigin(Frame* frame) +{ + ExecState* state = JSMainThreadExecState::currentState(); + + // If the current state is null we're in a call path where the DOM security check doesn't apply (eg. parser). + if (!state) + return true; + + return BindingSecurity::shouldAllowAccessToFrame(state, frame); } void ScriptController::attachDebugger(JSC::Debugger* debugger) { - for (ShellMap::iterator iter = m_windowShells.begin(); iter != m_windowShells.end(); ++iter) - attachDebugger(iter->value.get(), debugger); + Vector<JSC::Strong<JSDOMWindowShell>> windowShells = this->windowShells(); + for (size_t i = 0; i < windowShells.size(); ++i) + attachDebugger(windowShells[i].get(), debugger); } void ScriptController::attachDebugger(JSDOMWindowShell* shell, JSC::Debugger* debugger) @@ -283,6 +488,7 @@ void ScriptController::attachDebugger(JSDOMWindowShell* shell, JSC::Debugger* de return; JSDOMWindow* globalObject = shell->window(); + JSLockHolder lock(globalObject->vm()); if (debugger) debugger->attach(globalObject); else if (JSC::Debugger* currentDebugger = globalObject->debugger()) @@ -291,9 +497,11 @@ void ScriptController::attachDebugger(JSDOMWindowShell* shell, JSC::Debugger* de void ScriptController::updateDocument() { - for (ShellMap::iterator iter = m_windowShells.begin(); iter != m_windowShells.end(); ++iter) { - JSLockHolder lock(iter->key->vm()); - iter->value->window()->updateDocument(); + Vector<JSC::Strong<JSDOMWindowShell>> windowShells = this->windowShells(); + for (size_t i = 0; i < windowShells.size(); ++i) { + JSDOMWindowShell* windowShell = windowShells[i].get(); + JSLockHolder lock(windowShell->world().vm()); + windowShell->window()->updateDocument(); } } @@ -303,7 +511,7 @@ Bindings::RootObject* ScriptController::cacheableBindingRootObject() return 0; if (!m_cacheableBindingRootObject) { - JSLockHolder lock(JSDOMWindowBase::commonVM()); + JSLockHolder lock(commonVM()); m_cacheableBindingRootObject = Bindings::RootObject::create(0, globalObject(pluginWorld())); } return m_cacheableBindingRootObject.get(); @@ -315,13 +523,13 @@ Bindings::RootObject* ScriptController::bindingRootObject() return 0; if (!m_bindingRootObject) { - JSLockHolder lock(JSDOMWindowBase::commonVM()); + JSLockHolder lock(commonVM()); m_bindingRootObject = Bindings::RootObject::create(0, globalObject(pluginWorld())); } return m_bindingRootObject.get(); } -PassRefPtr<Bindings::RootObject> ScriptController::createRootObject(void* nativeHandle) +RefPtr<Bindings::RootObject> ScriptController::createRootObject(void* nativeHandle) { RootObjectMap::iterator it = m_rootObjects.find(nativeHandle); if (it != m_rootObjects.end()) @@ -330,36 +538,28 @@ PassRefPtr<Bindings::RootObject> ScriptController::createRootObject(void* native RefPtr<Bindings::RootObject> rootObject = Bindings::RootObject::create(nativeHandle, globalObject(pluginWorld())); m_rootObjects.set(nativeHandle, rootObject); - return rootObject.release(); -} - -#if ENABLE(INSPECTOR) -void ScriptController::setCaptureCallStackForUncaughtExceptions(bool) -{ + return rootObject; } void ScriptController::collectIsolatedContexts(Vector<std::pair<JSC::ExecState*, SecurityOrigin*>>& result) { for (ShellMap::iterator iter = m_windowShells.begin(); iter != m_windowShells.end(); ++iter) { JSC::ExecState* exec = iter->value->window()->globalExec(); - SecurityOrigin* origin = iter->value->window()->impl().document()->securityOrigin(); + SecurityOrigin* origin = &iter->value->window()->wrapped().document()->securityOrigin(); result.append(std::pair<JSC::ExecState*, SecurityOrigin*>(exec, origin)); } } -#endif - #if ENABLE(NETSCAPE_PLUGIN_API) - NPObject* ScriptController::windowScriptNPObject() { if (!m_windowScriptNPObject) { + JSLockHolder lock(commonVM()); if (canExecuteScripts(NotAboutToExecuteScript)) { // JavaScript is enabled, so there is a JavaScript window object. // Return an NPObject bound to the window object. JSDOMWindow* win = windowShell(pluginWorld())->window(); ASSERT(win); - JSC::JSLockHolder lock(win->globalExec()); Bindings::RootObject* root = bindingRootObject(); m_windowScriptNPObject = _NPN_CreateScriptObject(0, win, root); } else { @@ -371,26 +571,15 @@ NPObject* ScriptController::windowScriptNPObject() return m_windowScriptNPObject; } - -NPObject* ScriptController::createScriptObjectForPluginElement(HTMLPlugInElement* plugin) -{ - JSObject* object = jsObjectForPluginElement(plugin); - if (!object) - return _NPN_CreateNoScriptObject(); - - // Wrap the JSObject in an NPObject - return _NPN_CreateScriptObject(0, object, bindingRootObject()); -} - #endif -#if !PLATFORM(MAC) -PassRefPtr<JSC::Bindings::Instance> ScriptController::createScriptInstanceForWidget(Widget* widget) +#if !PLATFORM(COCOA) +RefPtr<JSC::Bindings::Instance> ScriptController::createScriptInstanceForWidget(Widget* widget) { - if (!widget->isPluginView()) - return 0; + if (!is<PluginViewBase>(*widget)) + return nullptr; - return toPluginView(widget)->bindingInstance(); + return downcast<PluginViewBase>(*widget).bindingInstance(); } #endif @@ -400,9 +589,10 @@ JSObject* ScriptController::jsObjectForPluginElement(HTMLPlugInElement* plugin) if (!canExecuteScripts(NotAboutToExecuteScript)) return 0; + JSLockHolder lock(commonVM()); + // Create a JSObject bound to this element JSDOMWindow* globalObj = globalObject(pluginWorld()); - JSLockHolder lock(globalObj->globalExec()); // FIXME: is normal okay? - used for NP plugins? JSValue jsElementValue = toJS(globalObj->globalExec(), globalObj, plugin); if (!jsElementValue || !jsElementValue.isObject()) @@ -411,7 +601,7 @@ JSObject* ScriptController::jsObjectForPluginElement(HTMLPlugInElement* plugin) return jsElementValue.getObject(); } -#if !PLATFORM(MAC) +#if !PLATFORM(COCOA) void ScriptController::updatePlatformScriptObjects() { @@ -436,7 +626,7 @@ void ScriptController::cleanupScriptObjectsForPlugin(void* nativeHandle) void ScriptController::clearScriptObjects() { - JSLockHolder lock(JSDOMWindowBase::commonVM()); + JSLockHolder lock(commonVM()); RootObjectMap::const_iterator end = m_rootObjects.end(); for (RootObjectMap::const_iterator it = m_rootObjects.begin(); it != end; ++it) @@ -446,7 +636,7 @@ void ScriptController::clearScriptObjects() if (m_bindingRootObject) { m_bindingRootObject->invalidate(); - m_bindingRootObject = 0; + m_bindingRootObject = nullptr; } #if ENABLE(NETSCAPE_PLUGIN_API) @@ -455,67 +645,53 @@ void ScriptController::clearScriptObjects() // script object properly. // This shouldn't cause any problems for plugins since they should have already been stopped and destroyed at this point. _NPN_DeallocateObject(m_windowScriptNPObject); - m_windowScriptNPObject = 0; + m_windowScriptNPObject = nullptr; } #endif } -Deprecated::ScriptValue ScriptController::executeScriptInWorld(DOMWrapperWorld& world, const String& script, bool forceUserGesture) +JSValue ScriptController::executeScriptInWorld(DOMWrapperWorld& world, const String& script, bool forceUserGesture) { - UserGestureIndicator gestureIndicator(forceUserGesture ? DefinitelyProcessingUserGesture : PossiblyProcessingUserGesture); - ScriptSourceCode sourceCode(script, m_frame.document()->url()); + UserGestureIndicator gestureIndicator(forceUserGesture ? std::optional<ProcessingUserGestureState>(ProcessingUserGesture) : std::nullopt); + ScriptSourceCode sourceCode(script, m_frame.document()->url(), TextPosition(), JSC::SourceProviderSourceType::Program, CachedScriptFetcher::create(m_frame.document()->charset())); if (!canExecuteScripts(AboutToExecuteScript) || isPaused()) - return Deprecated::ScriptValue(); + return { }; return evaluateInWorld(sourceCode, world); } -bool ScriptController::shouldBypassMainWorldContentSecurityPolicy() -{ - CallFrame* callFrame = JSDOMWindow::commonVM()->topCallFrame; - if (callFrame == CallFrame::noCaller()) - return false; - DOMWrapperWorld& domWrapperWorld = currentWorld(callFrame); - if (domWrapperWorld.isNormal()) - return false; - return true; -} - bool ScriptController::canExecuteScripts(ReasonForCallingCanExecuteScripts reason) { if (m_frame.document() && m_frame.document()->isSandboxed(SandboxScripts)) { // FIXME: This message should be moved off the console once a solution to https://bugs.webkit.org/show_bug.cgi?id=103274 exists. if (reason == AboutToExecuteScript) - m_frame.document()->addConsoleMessage(SecurityMessageSource, ErrorMessageLevel, "Blocked script execution in '" + m_frame.document()->url().stringCenterEllipsizedToLength() + "' because the document's frame is sandboxed and the 'allow-scripts' permission is not set."); + m_frame.document()->addConsoleMessage(MessageSource::Security, MessageLevel::Error, "Blocked script execution in '" + m_frame.document()->url().stringCenterEllipsizedToLength() + "' because the document's frame is sandboxed and the 'allow-scripts' permission is not set."); return false; } - if (m_frame.document() && m_frame.document()->isViewSource()) { - ASSERT(m_frame.document()->securityOrigin()->isUnique()); - return true; - } - if (!m_frame.page()) return false; return m_frame.loader().client().allowScript(m_frame.settings().isScriptEnabled()); } -Deprecated::ScriptValue ScriptController::executeScript(const String& script, bool forceUserGesture) +JSValue ScriptController::executeScript(const String& script, bool forceUserGesture, ExceptionDetails* exceptionDetails) { - UserGestureIndicator gestureIndicator(forceUserGesture ? DefinitelyProcessingUserGesture : PossiblyProcessingUserGesture); - return executeScript(ScriptSourceCode(script, m_frame.document()->url())); + UserGestureIndicator gestureIndicator(forceUserGesture ? std::optional<ProcessingUserGestureState>(ProcessingUserGesture) : std::nullopt); + return executeScript(ScriptSourceCode(script, m_frame.document()->url(), TextPosition(), JSC::SourceProviderSourceType::Program, CachedScriptFetcher::create(m_frame.document()->charset())), exceptionDetails); } -Deprecated::ScriptValue ScriptController::executeScript(const ScriptSourceCode& sourceCode) +JSValue ScriptController::executeScript(const ScriptSourceCode& sourceCode, ExceptionDetails* exceptionDetails) { if (!canExecuteScripts(AboutToExecuteScript) || isPaused()) - return Deprecated::ScriptValue(); + return { }; // FIXME: Would jsNull be better? - Ref<Frame> protect(m_frame); // Script execution can destroy the frame, and thus the ScriptController. + // FIXME: Preventing Frame from being destroyed is essentially unnecessary. + // https://bugs.webkit.org/show_bug.cgi?id=164763 + Ref<Frame> protector(m_frame); // Script execution can destroy the frame, and thus the ScriptController. - return evaluate(sourceCode); + return evaluate(sourceCode, exceptionDetails); } bool ScriptController::executeIfJavaScriptURL(const URL& url, ShouldReplaceDocumentIfJavaScriptURL shouldReplaceDocumentIfJavaScriptURL) @@ -534,7 +710,7 @@ bool ScriptController::executeIfJavaScriptURL(const URL& url, ShouldReplaceDocum const int javascriptSchemeLength = sizeof("javascript:") - 1; String decodedURL = decodeURLEscapeSequences(url.string()); - Deprecated::ScriptValue result = executeScript(decodedURL.substring(javascriptSchemeLength)); + auto result = executeScript(decodedURL.substring(javascriptSchemeLength)); // If executing script caused this frame to be removed from the page, we // don't want to try to replace its document! @@ -542,9 +718,7 @@ bool ScriptController::executeIfJavaScriptURL(const URL& url, ShouldReplaceDocum return true; String scriptResult; - JSDOMWindowShell* shell = windowShell(mainThreadNormalWorld()); - JSC::ExecState* exec = shell->window()->globalExec(); - if (!result.getString(exec, scriptResult)) + if (!result || !result.getString(windowShell(mainThreadNormalWorld())->window()->globalExec(), scriptResult)) return true; // FIXME: We should always replace the document, but doing so diff --git a/Source/WebCore/bindings/js/ScriptController.h b/Source/WebCore/bindings/js/ScriptController.h index 67e96ec3c..58fd49da8 100644 --- a/Source/WebCore/bindings/js/ScriptController.h +++ b/Source/WebCore/bindings/js/ScriptController.h @@ -1,7 +1,7 @@ /* * Copyright (C) 1999 Harri Porten (porten@kde.org) * Copyright (C) 2001 Peter Kelly (pmk@post.com) - * Copyright (C) 2008 Apple Inc. All rights reserved. + * Copyright (C) 2008-2016 Apple Inc. All rights reserved. * Copyright (C) 2008 Eric Seidel <eric@webkit.org> * * This library is free software; you can redistribute it and/or @@ -19,8 +19,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#ifndef ScriptController_h -#define ScriptController_h +#pragma once #include "FrameLoaderTypes.h" #include "JSDOMWindowShell.h" @@ -30,37 +29,40 @@ #include <wtf/RefPtr.h> #include <wtf/text/TextPosition.h> -#if PLATFORM(MAC) +#if PLATFORM(COCOA) #include <wtf/RetainPtr.h> -OBJC_CLASS WebScriptObject; OBJC_CLASS JSContext; +OBJC_CLASS WebScriptObject; #endif struct NPObject; -namespace Deprecated { -class ScriptValue; -} - namespace JSC { - class JSGlobalObject; - class ExecState; - - namespace Bindings { - class Instance; - class RootObject; - } +class ExecState; +class JSGlobalObject; +class JSInternalPromise; +class JSModuleRecord; + +namespace Bindings { +class Instance; +class RootObject; +} } namespace WebCore { -class HTMLPlugInElement; +class CachedScriptFetcher; class Frame; +class HTMLDocument; +class HTMLPlugInElement; +class LoadableModuleScript; class ScriptSourceCode; class SecurityOrigin; +class URL; class Widget; +struct ExceptionDetails; -typedef HashMap<void*, RefPtr<JSC::Bindings::RootObject>> RootObjectMap; +using RootObjectMap = HashMap<void*, RefPtr<JSC::Bindings::RootObject>>; enum ReasonForCallingCanExecuteScripts { AboutToExecuteScript, @@ -68,18 +70,21 @@ enum ReasonForCallingCanExecuteScripts { }; class ScriptController { - friend class ScriptCachedFrameData; + WTF_MAKE_FAST_ALLOCATED; + typedef HashMap<RefPtr<DOMWrapperWorld>, JSC::Strong<JSDOMWindowShell>> ShellMap; public: explicit ScriptController(Frame&); ~ScriptController(); - static PassRefPtr<DOMWrapperWorld> createWorld(); + WEBCORE_EXPORT static Ref<DOMWrapperWorld> createWorld(); - JSDOMWindowShell* createWindowShell(DOMWrapperWorld&); + JSDOMWindowShell& createWindowShell(DOMWrapperWorld&); void destroyWindowShell(DOMWrapperWorld&); + Vector<JSC::Strong<JSDOMWindowShell>> windowShells(); + JSDOMWindowShell* windowShell(DOMWrapperWorld& world) { ShellMap::iterator iter = m_windowShells.find(&world); @@ -97,9 +102,9 @@ public: static void getAllWorlds(Vector<Ref<DOMWrapperWorld>>&); - Deprecated::ScriptValue executeScript(const ScriptSourceCode&); - Deprecated::ScriptValue executeScript(const String& script, bool forceUserGesture = false); - Deprecated::ScriptValue executeScriptInWorld(DOMWrapperWorld&, const String& script, bool forceUserGesture = false); + JSC::JSValue executeScript(const ScriptSourceCode&, ExceptionDetails* = nullptr); + WEBCORE_EXPORT JSC::JSValue executeScript(const String& script, bool forceUserGesture = false, ExceptionDetails* = nullptr); + WEBCORE_EXPORT JSC::JSValue executeScriptInWorld(DOMWrapperWorld&, const String& script, bool forceUserGesture = false); // Returns true if argument is a JavaScript URL. bool executeIfJavaScriptURL(const URL&, ShouldReplaceDocumentIfJavaScriptURL shouldReplaceDocumentIfJavaScriptURL = ReplaceDocumentIfJavaScriptURL); @@ -108,18 +113,30 @@ public: // Darwin is an exception to this rule: it is OK to call this function from any thread, even reentrantly. static void initializeThreading(); - Deprecated::ScriptValue evaluate(const ScriptSourceCode&); - Deprecated::ScriptValue evaluateInWorld(const ScriptSourceCode&, DOMWrapperWorld&); + JSC::JSValue evaluate(const ScriptSourceCode&, ExceptionDetails* = nullptr); + JSC::JSValue evaluateInWorld(const ScriptSourceCode&, DOMWrapperWorld&, ExceptionDetails* = nullptr); + + void loadModuleScriptInWorld(LoadableModuleScript&, const String& moduleName, DOMWrapperWorld&); + void loadModuleScript(LoadableModuleScript&, const String& moduleName); + void loadModuleScriptInWorld(LoadableModuleScript&, const ScriptSourceCode&, DOMWrapperWorld&); + void loadModuleScript(LoadableModuleScript&, const ScriptSourceCode&); + + JSC::JSValue linkAndEvaluateModuleScriptInWorld(LoadableModuleScript& , DOMWrapperWorld&); + JSC::JSValue linkAndEvaluateModuleScript(LoadableModuleScript&); + + JSC::JSValue evaluateModule(const URL&, JSC::JSModuleRecord&, DOMWrapperWorld&); + JSC::JSValue evaluateModule(const URL&, JSC::JSModuleRecord&); WTF::TextPosition eventHandlerPosition() const; void enableEval(); void disableEval(const String& errorMessage); - static bool processingUserGesture(); + WEBCORE_EXPORT static bool processingUserGesture(); + WEBCORE_EXPORT static bool processingUserGestureForMedia(); static bool canAccessFromCurrentOrigin(Frame*); - bool canExecuteScripts(ReasonForCallingCanExecuteScripts); + WEBCORE_EXPORT bool canExecuteScripts(ReasonForCallingCanExecuteScripts); // Debugger can be 0 to detach any existing Debugger. void attachDebugger(JSC::Debugger*); // Attaches/detaches in all worlds/window shells. @@ -130,44 +147,40 @@ public: const String* sourceURL() const { return m_sourceURL; } // 0 if we are not evaluating any script - void clearWindowShell(DOMWindow* newDOMWindow, bool goingIntoPageCache); + void clearWindowShellsNotMatchingDOMWindow(DOMWindow*, bool goingIntoPageCache); + void setDOMWindowForWindowShell(DOMWindow*); void updateDocument(); void namedItemAdded(HTMLDocument*, const AtomicString&) { } void namedItemRemoved(HTMLDocument*, const AtomicString&) { } void clearScriptObjects(); - void cleanupScriptObjectsForPlugin(void*); + WEBCORE_EXPORT void cleanupScriptObjectsForPlugin(void*); void updatePlatformScriptObjects(); - PassRefPtr<JSC::Bindings::Instance> createScriptInstanceForWidget(Widget*); - JSC::Bindings::RootObject* bindingRootObject(); + RefPtr<JSC::Bindings::Instance> createScriptInstanceForWidget(Widget*); + WEBCORE_EXPORT JSC::Bindings::RootObject* bindingRootObject(); JSC::Bindings::RootObject* cacheableBindingRootObject(); - PassRefPtr<JSC::Bindings::RootObject> createRootObject(void* nativeHandle); + WEBCORE_EXPORT RefPtr<JSC::Bindings::RootObject> createRootObject(void* nativeHandle); -#if ENABLE(INSPECTOR) - static void setCaptureCallStackForUncaughtExceptions(bool); void collectIsolatedContexts(Vector<std::pair<JSC::ExecState*, SecurityOrigin*>>&); -#endif -#if PLATFORM(MAC) - WebScriptObject* windowScriptObject(); - JSContext *javaScriptContext(); +#if PLATFORM(COCOA) + WEBCORE_EXPORT WebScriptObject* windowScriptObject(); + WEBCORE_EXPORT JSContext *javaScriptContext(); #endif - JSC::JSObject* jsObjectForPluginElement(HTMLPlugInElement*); + WEBCORE_EXPORT JSC::JSObject* jsObjectForPluginElement(HTMLPlugInElement*); #if ENABLE(NETSCAPE_PLUGIN_API) - NPObject* createScriptObjectForPluginElement(HTMLPlugInElement*); - NPObject* windowScriptNPObject(); + WEBCORE_EXPORT NPObject* windowScriptNPObject(); #endif - bool shouldBypassMainWorldContentSecurityPolicy(); - private: - JSDOMWindowShell* initScript(DOMWrapperWorld&); + WEBCORE_EXPORT JSDOMWindowShell* initScript(DOMWrapperWorld&); + void setupModuleScriptHandlers(LoadableModuleScript&, JSC::JSInternalPromise&, DOMWrapperWorld&); void disconnectPlatformScriptObjects(); @@ -188,11 +201,9 @@ private: #if ENABLE(NETSCAPE_PLUGIN_API) NPObject* m_windowScriptNPObject; #endif -#if PLATFORM(MAC) +#if PLATFORM(COCOA) RetainPtr<WebScriptObject> m_windowScriptObject; #endif }; } // namespace WebCore - -#endif // ScriptController_h diff --git a/Source/WebCore/bindings/js/ScriptGlobalObject.cpp b/Source/WebCore/bindings/js/ScriptGlobalObject.cpp index a8b5a620f..2275ff939 100644 --- a/Source/WebCore/bindings/js/ScriptGlobalObject.cpp +++ b/Source/WebCore/bindings/js/ScriptGlobalObject.cpp @@ -31,63 +31,38 @@ #include "config.h" #include "ScriptGlobalObject.h" -#include "JSDOMBinding.h" -#include <bindings/ScriptObject.h> -#include <runtime/JSLock.h> - -#if ENABLE(INSPECTOR) +#include "JSDOMConvert.h" +#include "JSDOMExceptionHandling.h" #include "JSInspectorFrontendHost.h" -#endif +#include <runtime/IdentifierInlines.h> using namespace JSC; namespace WebCore { -static bool handleException(JSC::ExecState* scriptState) -{ - if (!scriptState->hadException()) - return true; - - reportException(scriptState, scriptState->exception()); - return false; -} - -bool ScriptGlobalObject::set(JSC::ExecState* scriptState, const char* name, const Deprecated::ScriptObject& value) -{ - JSLockHolder lock(scriptState); - scriptState->lexicalGlobalObject()->putDirect(scriptState->vm(), Identifier(scriptState, name), value.jsObject()); - return handleException(scriptState); -} - -#if ENABLE(INSPECTOR) -bool ScriptGlobalObject::set(JSC::ExecState* scriptState, const char* name, InspectorFrontendHost* value) +bool ScriptGlobalObject::set(ExecState& scriptState, const char* name, InspectorFrontendHost& value) { - JSLockHolder lock(scriptState); - JSDOMGlobalObject* globalObject = jsCast<JSDOMGlobalObject*>(scriptState->lexicalGlobalObject()); - globalObject->putDirect(scriptState->vm(), Identifier(scriptState, name), toJS(scriptState, globalObject, value)); - return handleException(scriptState); -} -#endif // ENABLE(INSPECTOR) - -bool ScriptGlobalObject::get(JSC::ExecState* scriptState, const char* name, Deprecated::ScriptObject& value) -{ - JSLockHolder lock(scriptState); - JSValue jsValue = scriptState->lexicalGlobalObject()->get(scriptState, Identifier(scriptState, name)); - if (!jsValue) - return false; - - if (!jsValue.isObject()) + auto& vm = scriptState.vm(); + JSLockHolder lock(vm); + auto scope = DECLARE_CATCH_SCOPE(vm); + auto& globalObject = *jsCast<JSDOMGlobalObject*>(scriptState.lexicalGlobalObject()); + globalObject.putDirect(vm, Identifier::fromString(&vm, name), toJS<IDLInterface<InspectorFrontendHost>>(scriptState, globalObject, value)); + if (UNLIKELY(scope.exception())) { + reportException(&scriptState, scope.exception()); return false; - - value = Deprecated::ScriptObject(scriptState, asObject(jsValue)); + } return true; } -bool ScriptGlobalObject::remove(JSC::ExecState* scriptState, const char* name) +bool ScriptGlobalObject::get(ExecState& scriptState, const char* name, JSObject*& object) { - JSLockHolder lock(scriptState); - scriptState->lexicalGlobalObject()->methodTable()->deleteProperty(scriptState->lexicalGlobalObject(), scriptState, Identifier(scriptState, name)); - return handleException(scriptState); + auto& vm = scriptState.vm(); + JSLockHolder lock(vm); + JSValue value = scriptState.lexicalGlobalObject()->get(&scriptState, Identifier::fromString(&vm, name)); + if (!value || !value.isObject()) + return false; + object = asObject(value); + return true; } } // namespace WebCore diff --git a/Source/WebCore/bindings/js/ScriptGlobalObject.h b/Source/WebCore/bindings/js/ScriptGlobalObject.h index 8aa055bd6..f879a025d 100644 --- a/Source/WebCore/bindings/js/ScriptGlobalObject.h +++ b/Source/WebCore/bindings/js/ScriptGlobalObject.h @@ -28,15 +28,11 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef ScriptGlobalObject_h -#define ScriptGlobalObject_h - -namespace Deprecated { -class ScriptObject; -} +#pragma once namespace JSC { class ExecState; +class JSObject; } namespace WebCore { @@ -45,17 +41,11 @@ class InspectorFrontendHost; class ScriptGlobalObject { public: - static bool set(JSC::ExecState*, const char* name, const Deprecated::ScriptObject&); -#if ENABLE(INSPECTOR) - static bool set(JSC::ExecState*, const char* name, InspectorFrontendHost*); -#endif + WEBCORE_EXPORT static bool set(JSC::ExecState&, const char* name, InspectorFrontendHost&); + static bool get(JSC::ExecState&, const char* name, JSC::JSObject*&); - static bool get(JSC::ExecState*, const char* name, Deprecated::ScriptObject&); - static bool remove(JSC::ExecState*, const char* name); private: - ScriptGlobalObject() { } + ScriptGlobalObject() = delete; }; } // namespace WebCore - -#endif // ScriptGlobalObject_h diff --git a/Source/WebCore/bindings/js/ScriptHeapSnapshot.h b/Source/WebCore/bindings/js/ScriptHeapSnapshot.h deleted file mode 100644 index 5269ff925..000000000 --- a/Source/WebCore/bindings/js/ScriptHeapSnapshot.h +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright (c) 2010, Google Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef ScriptHeapSnapshot_h -#define ScriptHeapSnapshot_h - -#include <wtf/RefCounted.h> -#include <wtf/text/WTFString.h> - -namespace WebCore { - -typedef uint32_t SnapshotObjectId; - -class ScriptHeapSnapshot : public RefCounted<ScriptHeapSnapshot> { -public: - class OutputStream { - public: - virtual ~OutputStream() { } - virtual void Write(const String& chunk) = 0; - virtual void Close() = 0; - }; - - virtual ~ScriptHeapSnapshot() { } - - String title() const { return ""; } - unsigned int uid() const { return 0; } - - void writeJSON(OutputStream*) { } - SnapshotObjectId maxSnapshotJSObjectId() const { return 0; } - -private: - ScriptHeapSnapshot() { } -}; - -} // namespace WebCore - -#endif // ScriptHeapSnapshot_h diff --git a/Source/WebCore/bindings/js/ScriptModuleLoader.cpp b/Source/WebCore/bindings/js/ScriptModuleLoader.cpp new file mode 100644 index 000000000..b67ffa3e6 --- /dev/null +++ b/Source/WebCore/bindings/js/ScriptModuleLoader.cpp @@ -0,0 +1,294 @@ +/* + * Copyright (C) 2015-2017 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "ScriptModuleLoader.h" + +#include "CachedModuleScriptLoader.h" +#include "CachedScript.h" +#include "CachedScriptFetcher.h" +#include "Document.h" +#include "Frame.h" +#include "JSDOMBinding.h" +#include "LoadableModuleScript.h" +#include "MIMETypeRegistry.h" +#include "ModuleFetchFailureKind.h" +#include "ScriptController.h" +#include "ScriptSourceCode.h" +#include "WebCoreJSClientData.h" +#include <runtime/Completion.h> +#include <runtime/JSInternalPromise.h> +#include <runtime/JSInternalPromiseDeferred.h> +#include <runtime/JSModuleRecord.h> +#include <runtime/JSScriptFetcher.h> +#include <runtime/JSSourceCode.h> +#include <runtime/JSString.h> +#include <runtime/Symbol.h> + +namespace WebCore { + +ScriptModuleLoader::ScriptModuleLoader(Document& document) + : m_document(document) +{ +} + +ScriptModuleLoader::~ScriptModuleLoader() +{ + for (auto& loader : m_loaders) + loader->clearClient(); +} + +static bool isRootModule(JSC::JSValue importerModuleKey) +{ + return importerModuleKey.isSymbol() || importerModuleKey.isUndefined(); +} + +static Expected<URL, ASCIILiteral> resolveModuleSpecifier(Document& document, const String& specifier, const URL& baseURL) +{ + // https://html.spec.whatwg.org/multipage/webappapis.html#resolve-a-module-specifier + + URL absoluteURL(URL(), specifier); + if (absoluteURL.isValid()) + return absoluteURL; + + if (!specifier.startsWith('/') && !specifier.startsWith("./") && !specifier.startsWith("../")) + return makeUnexpected(ASCIILiteral("Module specifier does not start with \"/\", \"./\", or \"../\".")); + + auto result = document.completeURL(specifier, baseURL); + if (!result.isValid()) + return makeUnexpected(ASCIILiteral("Module name does not resolve to a valid URL.")); + return result; +} + +JSC::JSInternalPromise* ScriptModuleLoader::resolve(JSC::JSGlobalObject* jsGlobalObject, JSC::ExecState* exec, JSC::JSModuleLoader*, JSC::JSValue moduleNameValue, JSC::JSValue importerModuleKey, JSC::JSValue) +{ + auto& globalObject = *JSC::jsCast<JSDOMGlobalObject*>(jsGlobalObject); + auto& jsPromise = *JSC::JSInternalPromiseDeferred::create(exec, &globalObject); + auto promise = DeferredPromise::create(globalObject, jsPromise); + + // We use a Symbol as a special purpose; It means this module is an inline module. + // So there is no correct URL to retrieve the module source code. If the module name + // value is a Symbol, it is used directly as a module key. + if (moduleNameValue.isSymbol()) { + promise->resolve<IDLAny>(JSC::Symbol::create(exec->vm(), asSymbol(moduleNameValue)->privateName().uid())); + return jsPromise.promise(); + } + + if (!moduleNameValue.isString()) { + promise->reject(TypeError, ASCIILiteral("Importer module key is not a Symbol or a String.")); + return jsPromise.promise(); + } + + String specifier = asString(moduleNameValue)->value(exec); + URL baseURL; + if (isRootModule(importerModuleKey)) + baseURL = m_document.baseURL(); + else { + ASSERT(importerModuleKey.isString()); + URL importerModuleRequestURL(URL(), asString(importerModuleKey)->value(exec)); + ASSERT_WITH_MESSAGE(importerModuleRequestURL.isValid(), "Invalid module referrer never starts importing dependent modules."); + + auto iterator = m_requestURLToResponseURLMap.find(importerModuleRequestURL); + ASSERT_WITH_MESSAGE(iterator != m_requestURLToResponseURLMap.end(), "Module referrer must register itself to the map before starting importing dependent modules."); + baseURL = iterator->value; + } + + auto result = resolveModuleSpecifier(m_document, specifier, baseURL); + if (!result) { + promise->reject(TypeError, result.error()); + return jsPromise.promise(); + } + + promise->resolve<IDLDOMString>(result->string()); + return jsPromise.promise(); +} + +static void rejectToPropagateNetworkError(DeferredPromise& deferred, ModuleFetchFailureKind failureKind, ASCIILiteral message) +{ + deferred.rejectWithCallback([&] (JSC::ExecState& state, JSDOMGlobalObject&) { + // We annotate exception with special private symbol. It allows us to distinguish these errors from the user thrown ones. + JSC::VM& vm = state.vm(); + // FIXME: Propagate more descriptive error. + // https://bugs.webkit.org/show_bug.cgi?id=167553 + auto* error = JSC::createTypeError(&state, message); + ASSERT(error); + error->putDirect(vm, static_cast<JSVMClientData&>(*vm.clientData).builtinNames().failureKindPrivateName(), JSC::jsNumber(static_cast<int32_t>(failureKind))); + return error; + }); +} + +JSC::JSInternalPromise* ScriptModuleLoader::fetch(JSC::JSGlobalObject* jsGlobalObject, JSC::ExecState* exec, JSC::JSModuleLoader*, JSC::JSValue moduleKeyValue, JSC::JSValue scriptFetcher) +{ + ASSERT(JSC::jsDynamicCast<JSC::JSScriptFetcher*>(exec->vm(), scriptFetcher)); + + auto& globalObject = *JSC::jsCast<JSDOMGlobalObject*>(jsGlobalObject); + auto& jsPromise = *JSC::JSInternalPromiseDeferred::create(exec, &globalObject); + auto deferred = DeferredPromise::create(globalObject, jsPromise); + if (moduleKeyValue.isSymbol()) { + deferred->reject(TypeError, ASCIILiteral("Symbol module key should be already fulfilled with the inlined resource.")); + return jsPromise.promise(); + } + + if (!moduleKeyValue.isString()) { + deferred->reject(TypeError, ASCIILiteral("Module key is not Symbol or String.")); + return jsPromise.promise(); + } + + // https://html.spec.whatwg.org/multipage/webappapis.html#fetch-a-single-module-script + + URL completedURL(URL(), asString(moduleKeyValue)->value(exec)); + if (!completedURL.isValid()) { + deferred->reject(TypeError, ASCIILiteral("Module key is a valid URL.")); + return jsPromise.promise(); + } + + auto loader = CachedModuleScriptLoader::create(*this, deferred.get(), *static_cast<CachedScriptFetcher*>(JSC::jsCast<JSC::JSScriptFetcher*>(scriptFetcher)->fetcher())); + m_loaders.add(loader.copyRef()); + if (!loader->load(m_document, completedURL)) { + loader->clearClient(); + m_loaders.remove(WTFMove(loader)); + rejectToPropagateNetworkError(deferred.get(), ModuleFetchFailureKind::WasErrored, ASCIILiteral("Importing a module script failed.")); + return jsPromise.promise(); + } + + return jsPromise.promise(); +} + +JSC::JSValue ScriptModuleLoader::evaluate(JSC::JSGlobalObject*, JSC::ExecState* exec, JSC::JSModuleLoader*, JSC::JSValue moduleKeyValue, JSC::JSValue moduleRecordValue, JSC::JSValue) +{ + JSC::VM& vm = exec->vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + + // FIXME: Currently, we only support JSModuleRecord. + // Once the reflective part of the module loader is supported, we will handle arbitrary values. + // https://whatwg.github.io/loader/#registry-prototype-provide + auto* moduleRecord = jsDynamicDowncast<JSC::JSModuleRecord*>(vm, moduleRecordValue); + if (!moduleRecord) + return JSC::jsUndefined(); + + URL sourceURL; + if (moduleKeyValue.isSymbol()) + sourceURL = m_document.url(); + else if (moduleKeyValue.isString()) + sourceURL = URL(URL(), asString(moduleKeyValue)->value(exec)); + else + return JSC::throwTypeError(exec, scope, ASCIILiteral("Module key is not Symbol or String.")); + + if (!sourceURL.isValid()) + return JSC::throwTypeError(exec, scope, ASCIILiteral("Module key is an invalid URL.")); + + if (auto* frame = m_document.frame()) + return frame->script().evaluateModule(sourceURL, *moduleRecord); + return JSC::jsUndefined(); +} + +static JSC::JSInternalPromise* rejectPromise(JSC::ExecState& state, JSDOMGlobalObject& globalObject, ExceptionCode ec, ASCIILiteral message) +{ + auto& jsPromise = *JSC::JSInternalPromiseDeferred::create(&state, &globalObject); + auto deferred = DeferredPromise::create(globalObject, jsPromise); + deferred->reject(ec, WTFMove(message)); + return jsPromise.promise(); +} + +JSC::JSInternalPromise* ScriptModuleLoader::importModule(JSC::JSGlobalObject* jsGlobalObject, JSC::ExecState* exec, JSC::JSModuleLoader*, JSC::JSString* moduleName, const JSC::SourceOrigin& sourceOrigin) +{ + auto& state = *exec; + JSC::VM& vm = exec->vm(); + auto& globalObject = *JSC::jsCast<JSDOMGlobalObject*>(jsGlobalObject); + + // If SourceOrigin and/or CachedScriptFetcher is null, we import the module with the default fetcher. + // SourceOrigin can be null if the source code is not coupled with the script file. + // The examples, + // 1. The code evaluated by the inspector. + // 2. The other unusual code execution like the evaluation through the NPAPI. + // 3. The code from injected bundle's script. + // 4. The code from extension script. + URL baseURL; + RefPtr<JSC::ScriptFetcher> scriptFetcher; + if (sourceOrigin.isNull()) { + baseURL = m_document.baseURL(); + scriptFetcher = CachedScriptFetcher::create(m_document.charset()); + } else { + baseURL = URL(URL(), sourceOrigin.string()); + if (!baseURL.isValid()) + return rejectPromise(state, globalObject, TypeError, ASCIILiteral("Importer module key is not a Symbol or a String.")); + + if (sourceOrigin.fetcher()) + scriptFetcher = sourceOrigin.fetcher(); + else + scriptFetcher = CachedScriptFetcher::create(m_document.charset()); + } + ASSERT(baseURL.isValid()); + ASSERT(scriptFetcher); + + auto specifier = moduleName->value(exec); + auto result = resolveModuleSpecifier(m_document, specifier, baseURL); + if (!result) + return rejectPromise(state, globalObject, TypeError, result.error()); + + return JSC::importModule(exec, JSC::Identifier::fromString(&vm, result->string()), JSC::JSScriptFetcher::create(vm, WTFMove(scriptFetcher) )); +} + +void ScriptModuleLoader::notifyFinished(CachedModuleScriptLoader& loader, RefPtr<DeferredPromise> promise) +{ + // https://html.spec.whatwg.org/multipage/webappapis.html#fetch-a-single-module-script + + if (!m_loaders.remove(&loader)) + return; + loader.clearClient(); + + auto& cachedScript = *loader.cachedScript(); + + if (cachedScript.resourceError().isAccessControl()) { + promise->reject(TypeError, ASCIILiteral("Cross-origin script load denied by Cross-Origin Resource Sharing policy.")); + return; + } + + if (cachedScript.errorOccurred()) { + rejectToPropagateNetworkError(*promise, ModuleFetchFailureKind::WasErrored, ASCIILiteral("Importing a module script failed.")); + return; + } + + if (cachedScript.wasCanceled()) { + rejectToPropagateNetworkError(*promise, ModuleFetchFailureKind::WasCanceled, ASCIILiteral("Importing a module script is canceled.")); + return; + } + + if (!MIMETypeRegistry::isSupportedJavaScriptMIMEType(cachedScript.response().mimeType())) { + // https://html.spec.whatwg.org/multipage/webappapis.html#fetch-a-single-module-script + // The result of extracting a MIME type from response's header list (ignoring parameters) is not a JavaScript MIME type. + // For historical reasons, fetching a classic script does not include MIME type checking. In contrast, module scripts will fail to load if they are not of a correct MIME type. + promise->reject(TypeError, makeString("'", cachedScript.response().mimeType(), "' is not a valid JavaScript MIME type.")); + return; + } + + m_requestURLToResponseURLMap.add(cachedScript.url(), cachedScript.response().url()); + promise->resolveWithCallback([&] (JSC::ExecState& state, JSDOMGlobalObject&) { + return JSC::JSSourceCode::create(state.vm(), + JSC::SourceCode { ScriptSourceCode { &cachedScript, JSC::SourceProviderSourceType::Module, loader.scriptFetcher() }.jsSourceCode() }); + }); +} + +} diff --git a/Source/WebCore/bindings/js/ScriptModuleLoader.h b/Source/WebCore/bindings/js/ScriptModuleLoader.h new file mode 100644 index 000000000..6e7a61b57 --- /dev/null +++ b/Source/WebCore/bindings/js/ScriptModuleLoader.h @@ -0,0 +1,71 @@ +/* + * Copyright (C) 2015, 2016 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +#include "CachedModuleScriptLoader.h" +#include "CachedModuleScriptLoaderClient.h" +#include "URL.h" +#include "URLHash.h" +#include <runtime/JSCJSValue.h> +#include <wtf/Noncopyable.h> + +namespace JSC { + +class ExecState; +class JSGlobalObject; +class JSInternalPromise; +class JSModuleLoader; +class SourceOrigin; + +} + +namespace WebCore { + +class Document; +class JSDOMGlobalObject; + +class ScriptModuleLoader final : private CachedModuleScriptLoaderClient { + WTF_MAKE_NONCOPYABLE(ScriptModuleLoader); WTF_MAKE_FAST_ALLOCATED; +public: + explicit ScriptModuleLoader(Document&); + ~ScriptModuleLoader(); + + Document& document() { return m_document; } + + JSC::JSInternalPromise* resolve(JSC::JSGlobalObject*, JSC::ExecState*, JSC::JSModuleLoader*, JSC::JSValue moduleName, JSC::JSValue importerModuleKey, JSC::JSValue scriptFetcher); + JSC::JSInternalPromise* fetch(JSC::JSGlobalObject*, JSC::ExecState*, JSC::JSModuleLoader*, JSC::JSValue moduleKey, JSC::JSValue scriptFetcher); + JSC::JSValue evaluate(JSC::JSGlobalObject*, JSC::ExecState*, JSC::JSModuleLoader*, JSC::JSValue moduleKey, JSC::JSValue moduleRecord, JSC::JSValue scriptFetcher); + JSC::JSInternalPromise* importModule(JSC::JSGlobalObject*, JSC::ExecState*, JSC::JSModuleLoader*, JSC::JSString*, const JSC::SourceOrigin&); + +private: + void notifyFinished(CachedModuleScriptLoader&, RefPtr<DeferredPromise>) final; + + Document& m_document; + HashMap<URL, URL> m_requestURLToResponseURLMap; + HashSet<Ref<CachedModuleScriptLoader>> m_loaders; +}; + +} // namespace WebCore diff --git a/Source/WebCore/bindings/js/ScriptProfile.cpp b/Source/WebCore/bindings/js/ScriptProfile.cpp deleted file mode 100644 index c8778a580..000000000 --- a/Source/WebCore/bindings/js/ScriptProfile.cpp +++ /dev/null @@ -1,107 +0,0 @@ -/* - * Copyright (C) 2010 Apple Inc. All rights reserved. - * Copyright (C) 2010 Google Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" - -#include "ScriptProfile.h" - -#include "JSDOMBinding.h" -#include <inspector/InspectorValues.h> -#include <profiler/Profile.h> -#include <profiler/ProfileNode.h> - -namespace WebCore { - -PassRefPtr<ScriptProfile> ScriptProfile::create(PassRefPtr<JSC::Profile> profile) -{ - if (!profile) - return 0; - return adoptRef(new ScriptProfile(profile)); -} - -ScriptProfile::ScriptProfile(PassRefPtr<JSC::Profile> profile) - : m_profile(profile) -{ -} - -ScriptProfile::~ScriptProfile() -{ -} - -String ScriptProfile::title() const -{ - return m_profile->title(); -} - -unsigned int ScriptProfile::uid() const -{ - return m_profile->uid(); -} - -ScriptProfileNode* ScriptProfile::head() const -{ - return m_profile->head(); -} - -double ScriptProfile::idleTime() const -{ - return 0.0; -} - -#if ENABLE(INSPECTOR) -static PassRefPtr<Inspector::TypeBuilder::Profiler::CPUProfileNode> buildInspectorObjectFor(const JSC::ProfileNode* node) -{ - typedef Vector<RefPtr<JSC::ProfileNode>> ProfileNodesList; - const ProfileNodesList& nodeChildren = node->children(); - ProfileNodesList::const_iterator end = nodeChildren.end(); - RefPtr<Inspector::TypeBuilder::Array<Inspector::TypeBuilder::Profiler::CPUProfileNode>> children = Inspector::TypeBuilder::Array<Inspector::TypeBuilder::Profiler::CPUProfileNode>::create(); - for (ProfileNodesList::const_iterator iter = nodeChildren.begin(); iter != end; ++iter) - children->addItem(buildInspectorObjectFor(iter->get())); - - RefPtr<Inspector::TypeBuilder::Profiler::CPUProfileNode> result = Inspector::TypeBuilder::Profiler::CPUProfileNode::create() - .setFunctionName(node->functionName()) - .setUrl(node->url()) - .setLineNumber(node->lineNumber()) - .setTotalTime(node->totalTime()) - .setSelfTime(node->selfTime()) - .setNumberOfCalls(node->numberOfCalls()) - .setCallUID(node->callIdentifier().hash()) - .setChildren(children.release()); - return result.release(); -} - -PassRefPtr<Inspector::TypeBuilder::Profiler::CPUProfileNode> ScriptProfile::buildInspectorObjectForHead() const -{ - return buildInspectorObjectFor(m_profile->head()); -} - -PassRefPtr<Inspector::TypeBuilder::Profiler::CPUProfileNode> ScriptProfile::buildInspectorObjectForBottomUpHead() const -{ - return 0; -} -#endif - -} // namespace WebCore diff --git a/Source/WebCore/bindings/js/ScriptProfile.h b/Source/WebCore/bindings/js/ScriptProfile.h deleted file mode 100644 index 1f4c03ec9..000000000 --- a/Source/WebCore/bindings/js/ScriptProfile.h +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright (C) 2010 Apple Inc. All rights reserved. - * Copyright (C) 2010 Google Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef ScriptProfile_h -#define ScriptProfile_h - -#include "ScriptProfileNode.h" -#include <wtf/Forward.h> -#include <wtf/PassRefPtr.h> -#include <wtf/RefCounted.h> -#include <wtf/RefPtr.h> - -#if ENABLE(INSPECTOR) -#include "InspectorWebTypeBuilders.h" -#endif - -namespace JSC { -class Profile; -} - -namespace WebCore { - -class ScriptProfile : public RefCounted<ScriptProfile> { -public: - static PassRefPtr<ScriptProfile> create(PassRefPtr<JSC::Profile> profile); - virtual ~ScriptProfile(); - - String title() const; - unsigned int uid() const; - ScriptProfileNode* head() const; - double idleTime() const; - -#if ENABLE(INSPECTOR) - PassRefPtr<Inspector::TypeBuilder::Profiler::CPUProfileNode> buildInspectorObjectForHead() const; - PassRefPtr<Inspector::TypeBuilder::Profiler::CPUProfileNode> buildInspectorObjectForBottomUpHead() const; -#endif - -private: - ScriptProfile(PassRefPtr<JSC::Profile> profile); - - RefPtr<JSC::Profile> m_profile; -}; - - -} // namespace WebCore - -#endif // ScriptProfile_h diff --git a/Source/WebCore/bindings/js/ScriptProfiler.cpp b/Source/WebCore/bindings/js/ScriptProfiler.cpp deleted file mode 100644 index a30e7b285..000000000 --- a/Source/WebCore/bindings/js/ScriptProfiler.cpp +++ /dev/null @@ -1,92 +0,0 @@ -/* - * Copyright (C) 2010 Apple Inc. All rights reserved. - * Copyright (C) 2010 Google Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" - -#include "ScriptProfiler.h" - -#include "GCController.h" -#include "JSDOMBinding.h" -#include "JSDOMWindow.h" -#include "MainFrame.h" -#include "Page.h" -#include "ScriptState.h" -#include <bindings/ScriptObject.h> -#include <bindings/ScriptValue.h> -#include <profiler/LegacyProfiler.h> -#include <wtf/Forward.h> - -namespace WebCore { - -void ScriptProfiler::collectGarbage() -{ - gcController().garbageCollectSoon(); -} - -Deprecated::ScriptObject ScriptProfiler::objectByHeapObjectId(unsigned) -{ - return Deprecated::ScriptObject(); -} - -unsigned ScriptProfiler::getHeapObjectId(const Deprecated::ScriptValue&) -{ - return 0; -} - -void ScriptProfiler::start(JSC::ExecState* state, const String& title) -{ - JSC::LegacyProfiler::profiler()->startProfiling(state, title); -} - -void ScriptProfiler::startForPage(Page* inspectedPage, const String& title) -{ - JSC::ExecState* scriptState = toJSDOMWindow(&inspectedPage->mainFrame(), debuggerWorld())->globalExec(); - start(scriptState, title); -} - -void ScriptProfiler::startForWorkerGlobalScope(WorkerGlobalScope* context, const String& title) -{ - start(execStateFromWorkerGlobalScope(context), title); -} - -PassRefPtr<ScriptProfile> ScriptProfiler::stop(JSC::ExecState* state, const String& title) -{ - RefPtr<JSC::Profile> profile = JSC::LegacyProfiler::profiler()->stopProfiling(state, title); - return ScriptProfile::create(profile); -} - -PassRefPtr<ScriptProfile> ScriptProfiler::stopForPage(Page* inspectedPage, const String& title) -{ - JSC::ExecState* scriptState = toJSDOMWindow(&inspectedPage->mainFrame(), debuggerWorld())->globalExec(); - return stop(scriptState, title); -} - -PassRefPtr<ScriptProfile> ScriptProfiler::stopForWorkerGlobalScope(WorkerGlobalScope* context, const String& title) -{ - return stop(execStateFromWorkerGlobalScope(context), title); -} - -} // namespace WebCore diff --git a/Source/WebCore/bindings/js/ScriptProfiler.h b/Source/WebCore/bindings/js/ScriptProfiler.h deleted file mode 100644 index 3e99168a4..000000000 --- a/Source/WebCore/bindings/js/ScriptProfiler.h +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright (C) 2010 Apple Inc. All rights reserved. - * Copyright (C) 2010 Google Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef ScriptProfiler_h -#define ScriptProfiler_h - -#include "ScriptHeapSnapshot.h" -#include "ScriptProfile.h" -#include "ScriptState.h" -#include <wtf/Forward.h> -#include <wtf/PassRefPtr.h> - -namespace Deprecated { -class ScriptObject; -class ScriptValue; -} - -namespace WebCore { - -class Page; -class WorkerGlobalScope; - -class ScriptProfiler { - WTF_MAKE_NONCOPYABLE(ScriptProfiler); -public: - class HeapSnapshotProgress { - public: - virtual ~HeapSnapshotProgress() { } - virtual void Start(int totalWork) = 0; - virtual void Worked(int workDone) = 0; - virtual void Done() = 0; - virtual bool isCanceled() = 0; - }; - - static void collectGarbage(); - static Deprecated::ScriptObject objectByHeapObjectId(unsigned id); - static unsigned getHeapObjectId(const Deprecated::ScriptValue&); - static void start(JSC::ExecState*, const String& title); - static void startForPage(Page*, const String& title); - static void startForWorkerGlobalScope(WorkerGlobalScope*, const String& title); - static PassRefPtr<ScriptProfile> stop(JSC::ExecState*, const String& title); - static PassRefPtr<ScriptProfile> stopForPage(Page*, const String& title); - static PassRefPtr<ScriptProfile> stopForWorkerGlobalScope(WorkerGlobalScope*, const String& title); - static PassRefPtr<ScriptHeapSnapshot> takeHeapSnapshot(const String&, HeapSnapshotProgress*) { return 0; } - static bool isSampling() { return false; } - static bool hasHeapProfiler() { return false; } - static HashMap<String, double>* currentProfileNameIdleTimeMap() { return 0; } -}; - -} // namespace WebCore - -#endif // ScriptProfiler_h diff --git a/Source/WebCore/bindings/js/ScriptSourceCode.h b/Source/WebCore/bindings/js/ScriptSourceCode.h index 2d3c15970..06a8edc83 100644 --- a/Source/WebCore/bindings/js/ScriptSourceCode.h +++ b/Source/WebCore/bindings/js/ScriptSourceCode.h @@ -28,11 +28,11 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef ScriptSourceCode_h -#define ScriptSourceCode_h +#pragma once #include "CachedResourceHandle.h" #include "CachedScript.h" +#include "CachedScriptFetcher.h" #include "CachedScriptSourceProvider.h" #include "URL.h" #include <parser/SourceProvider.h> @@ -43,43 +43,44 @@ namespace WebCore { class ScriptSourceCode { public: - ScriptSourceCode(const String& source, const URL& url = URL(), const TextPosition& startPosition = TextPosition::minimumPosition()) - : m_provider(JSC::StringSourceProvider::create(source, url.isNull() ? String() : url.string(), startPosition)) - , m_code(m_provider, startPosition.m_line.oneBasedInt(), startPosition.m_column.oneBasedInt()) + ScriptSourceCode(const String& source, const URL& url = URL(), const TextPosition& startPosition = TextPosition(), JSC::SourceProviderSourceType sourceType = JSC::SourceProviderSourceType::Program) + : m_provider(JSC::StringSourceProvider::create(source, JSC::SourceOrigin { url.string() }, url.string(), startPosition, sourceType)) + , m_code(m_provider.copyRef(), startPosition.m_line.oneBasedInt(), startPosition.m_column.oneBasedInt()) , m_url(url) { } - explicit ScriptSourceCode(CachedScript* cachedScript) - : m_provider(CachedScriptSourceProvider::create(cachedScript)) - , m_code(m_provider) + ScriptSourceCode(CachedScript* cachedScript, JSC::SourceProviderSourceType sourceType, Ref<CachedScriptFetcher>&& scriptFetcher) + : m_provider(CachedScriptSourceProvider::create(cachedScript, sourceType, WTFMove(scriptFetcher))) + , m_code(m_provider.copyRef()) , m_cachedScript(cachedScript) { } + ScriptSourceCode(const String& source, const URL& url, const TextPosition& startPosition, JSC::SourceProviderSourceType sourceType, Ref<CachedScriptFetcher>&& scriptFetcher) + : m_provider(JSC::StringSourceProvider::create(source, JSC::SourceOrigin { url.string(), WTFMove(scriptFetcher) }, url.string(), startPosition, sourceType)) + , m_code(m_provider.copyRef(), startPosition.m_line.oneBasedInt(), startPosition.m_column.oneBasedInt()) + , m_url(url) + { + } + bool isEmpty() const { return m_code.length() == 0; } const JSC::SourceCode& jsSourceCode() const { return m_code; } - const String& source() const { return m_provider->source(); } + StringView source() const { return m_provider->source(); } - int startLine() const { return m_code.firstLine(); } + int startLine() const { return m_code.firstLine().oneBasedInt(); } CachedScript* cachedScript() const { return m_cachedScript.get(); } const URL& url() const { return m_url; } private: - RefPtr<JSC::SourceProvider> m_provider; - + Ref<JSC::SourceProvider> m_provider; JSC::SourceCode m_code; - CachedResourceHandle<CachedScript> m_cachedScript; - URL m_url; - }; } // namespace WebCore - -#endif // ScriptSourceCode_h diff --git a/Source/WebCore/bindings/js/ScriptState.cpp b/Source/WebCore/bindings/js/ScriptState.cpp index af1048dce..301c7cc50 100644 --- a/Source/WebCore/bindings/js/ScriptState.cpp +++ b/Source/WebCore/bindings/js/ScriptState.cpp @@ -50,23 +50,32 @@ namespace WebCore { DOMWindow* domWindowFromExecState(JSC::ExecState* scriptState) { JSC::JSGlobalObject* globalObject = scriptState->lexicalGlobalObject(); - if (!globalObject->inherits(JSDOMWindowBase::info())) - return 0; - return &JSC::jsCast<JSDOMWindowBase*>(globalObject)->impl(); + JSC::VM& vm = globalObject->vm(); + if (!globalObject->inherits(vm, JSDOMWindowBase::info())) + return nullptr; + return &JSC::jsCast<JSDOMWindowBase*>(globalObject)->wrapped(); +} + +Frame* frameFromExecState(JSC::ExecState* scriptState) +{ + ScriptExecutionContext* context = scriptExecutionContextFromExecState(scriptState); + Document* document = is<Document>(context) ? downcast<Document>(context) : nullptr; + return document ? document->frame() : nullptr; } ScriptExecutionContext* scriptExecutionContextFromExecState(JSC::ExecState* scriptState) { JSC::JSGlobalObject* globalObject = scriptState->lexicalGlobalObject(); - if (!globalObject->inherits(JSDOMGlobalObject::info())) - return 0; + JSC::VM& vm = globalObject->vm(); + if (!globalObject->inherits(vm, JSDOMGlobalObject::info())) + return nullptr; return JSC::jsCast<JSDOMGlobalObject*>(globalObject)->scriptExecutionContext(); } JSC::ExecState* mainWorldExecState(Frame* frame) { if (!frame) - return 0; + return nullptr; JSDOMWindowShell* shell = frame->script().windowShell(mainThreadNormalWorld()); return shell->window()->globalExec(); } @@ -74,18 +83,18 @@ JSC::ExecState* mainWorldExecState(Frame* frame) JSC::ExecState* execStateFromNode(DOMWrapperWorld& world, Node* node) { if (!node) - return 0; + return nullptr; Frame* frame = node->document().frame(); if (!frame) - return 0; + return nullptr; if (!frame->script().canExecuteScripts(NotAboutToExecuteScript)) - return 0; + return nullptr; return frame->script().globalObject(world)->globalExec(); } JSC::ExecState* execStateFromPage(DOMWrapperWorld& world, Page* page) { - return page->mainFrame().script().globalObject(world)->globalExec(); + return page ? page->mainFrame().script().globalObject(world)->globalExec() : nullptr; } JSC::ExecState* execStateFromWorkerGlobalScope(WorkerGlobalScope* workerGlobalScope) diff --git a/Source/WebCore/bindings/js/ScriptState.h b/Source/WebCore/bindings/js/ScriptState.h index 70d14c7cd..74421fd95 100644 --- a/Source/WebCore/bindings/js/ScriptState.h +++ b/Source/WebCore/bindings/js/ScriptState.h @@ -29,14 +29,14 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef ScriptState_h -#define ScriptState_h +#pragma once namespace JSC { class ExecState; } namespace WebCore { + class DOMWindow; class DOMWrapperWorld; class Frame; @@ -45,21 +45,14 @@ class Page; class ScriptExecutionContext; class WorkerGlobalScope; -// The idea is to expose "state-like" methods (hadException, and any other -// methods where ExecState just dips into vm) of JSC::ExecState as a -// separate abstraction. -// For now, the separation is purely by convention. -typedef JSC::ExecState ScriptState; - DOMWindow* domWindowFromExecState(JSC::ExecState*); +Frame* frameFromExecState(JSC::ExecState*); ScriptExecutionContext* scriptExecutionContextFromExecState(JSC::ExecState*); JSC::ExecState* mainWorldExecState(Frame*); JSC::ExecState* execStateFromNode(DOMWrapperWorld&, Node*); -JSC::ExecState* execStateFromPage(DOMWrapperWorld&, Page*); +WEBCORE_EXPORT JSC::ExecState* execStateFromPage(DOMWrapperWorld&, Page*); JSC::ExecState* execStateFromWorkerGlobalScope(WorkerGlobalScope*); } // namespace WebCore - -#endif // ScriptState_h diff --git a/Source/WebCore/bindings/js/ScriptWrappable.h b/Source/WebCore/bindings/js/ScriptWrappable.h index 5b6c65e30..fc0dca0a8 100644 --- a/Source/WebCore/bindings/js/ScriptWrappable.h +++ b/Source/WebCore/bindings/js/ScriptWrappable.h @@ -29,8 +29,7 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef ScriptWrappable_h -#define ScriptWrappable_h +#pragma once #include <heap/Weak.h> @@ -40,18 +39,22 @@ class WeakHandleOwner; namespace WebCore { -class JSDOMWrapper; +class JSDOMObject; class ScriptWrappable { public: - JSDOMWrapper* wrapper() const; - void setWrapper(JSDOMWrapper*, JSC::WeakHandleOwner*, void*); - void clearWrapper(JSDOMWrapper*); + JSDOMObject* wrapper() const; + void setWrapper(JSDOMObject*, JSC::WeakHandleOwner*, void*); + void clearWrapper(JSDOMObject*); + + template<typename Derived> + static ptrdiff_t offsetOfWrapper() { return CAST_OFFSET(Derived*, ScriptWrappable*) + OBJECT_OFFSETOF(ScriptWrappable, m_wrapper); } + +protected: + ~ScriptWrappable() { } private: - JSC::Weak<JSDOMWrapper> m_wrapper; + JSC::Weak<JSDOMObject> m_wrapper; }; } // namespace WebCore - -#endif // ScriptWrappable_h diff --git a/Source/WebCore/bindings/js/ScriptWrappableInlines.h b/Source/WebCore/bindings/js/ScriptWrappableInlines.h index dabb657eb..f102c217c 100644 --- a/Source/WebCore/bindings/js/ScriptWrappableInlines.h +++ b/Source/WebCore/bindings/js/ScriptWrappableInlines.h @@ -29,8 +29,7 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef ScriptWrappableInlines_h -#define ScriptWrappableInlines_h +#pragma once #include "JSDOMWrapper.h" #include <heap/Weak.h> @@ -38,22 +37,20 @@ namespace WebCore { -inline JSDOMWrapper* ScriptWrappable::wrapper() const +inline JSDOMObject* ScriptWrappable::wrapper() const { return m_wrapper.get(); } -inline void ScriptWrappable::setWrapper(JSDOMWrapper* wrapper, JSC::WeakHandleOwner* wrapperOwner, void* context) +inline void ScriptWrappable::setWrapper(JSDOMObject* wrapper, JSC::WeakHandleOwner* wrapperOwner, void* context) { ASSERT(!m_wrapper); - m_wrapper = JSC::Weak<JSDOMWrapper>(wrapper, wrapperOwner, context); + m_wrapper = JSC::Weak<JSDOMObject>(wrapper, wrapperOwner, context); } -inline void ScriptWrappable::clearWrapper(JSDOMWrapper* wrapper) +inline void ScriptWrappable::clearWrapper(JSDOMObject* wrapper) { weakClear(m_wrapper, wrapper); } } // namespace WebCore - -#endif // ScriptWrappableInlines_h diff --git a/Source/WebCore/bindings/js/SerializedScriptValue.cpp b/Source/WebCore/bindings/js/SerializedScriptValue.cpp index 1f7919289..c9904c091 100644 --- a/Source/WebCore/bindings/js/SerializedScriptValue.cpp +++ b/Source/WebCore/bindings/js/SerializedScriptValue.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2009, 2013 Apple Inc. All rights reserved. + * Copyright (C) 2009, 2013, 2016 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -10,10 +10,10 @@ * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * - * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR @@ -28,49 +28,56 @@ #include "SerializedScriptValue.h" #include "Blob.h" +#include "BlobRegistry.h" #include "CryptoKeyAES.h" #include "CryptoKeyDataOctetSequence.h" #include "CryptoKeyDataRSAComponents.h" #include "CryptoKeyHMAC.h" #include "CryptoKeyRSA.h" -#include "ExceptionCode.h" #include "File.h" #include "FileList.h" +#include "IDBValue.h" #include "ImageData.h" #include "JSBlob.h" #include "JSCryptoKey.h" +#include "JSDOMBinding.h" #include "JSDOMGlobalObject.h" #include "JSFile.h" #include "JSFileList.h" #include "JSImageData.h" #include "JSMessagePort.h" #include "JSNavigator.h" -#include "NotImplemented.h" +#include "ScriptExecutionContext.h" +#include "ScriptState.h" #include "SharedBuffer.h" #include "WebCoreJSClientData.h" #include <limits> #include <JavaScriptCore/APICast.h> -#include <JavaScriptCore/APIShims.h> #include <runtime/ArrayBuffer.h> #include <runtime/BooleanObject.h> #include <runtime/DateInstance.h> #include <runtime/Error.h> +#include <runtime/Exception.h> #include <runtime/ExceptionHelpers.h> +#include <runtime/IterationKind.h> #include <runtime/JSArrayBuffer.h> #include <runtime/JSArrayBufferView.h> +#include <runtime/JSCInlines.h> #include <runtime/JSDataView.h> #include <runtime/JSMap.h> +#include <runtime/JSMapIterator.h> #include <runtime/JSSet.h> +#include <runtime/JSSetIterator.h> #include <runtime/JSTypedArrays.h> -#include <runtime/MapData.h> #include <runtime/ObjectConstructor.h> -#include <runtime/Operations.h> #include <runtime/PropertyNameArray.h> #include <runtime/RegExp.h> #include <runtime/RegExpObject.h> #include <runtime/TypedArrayInlines.h> #include <runtime/TypedArrays.h> #include <wtf/HashTraits.h> +#include <wtf/MainThread.h> +#include <wtf/RunLoop.h> #include <wtf/Vector.h> using namespace JSC; @@ -85,9 +92,20 @@ namespace WebCore { static const unsigned maximumFilterRecursion = 40000; +enum class SerializationReturnCode { + SuccessfullyCompleted, + StackOverflowError, + InterruptedExecutionError, + ValidationError, + ExistingExceptionError, + DataCloneError, + UnspecifiedError +}; + enum WalkerState { StateUnknown, ArrayStartState, ArrayStartVisitMember, ArrayEndVisitMember, ObjectStartState, ObjectStartVisitMember, ObjectEndVisitMember, - MapDataStartVisitEntry, MapDataEndVisitKey, MapDataEndVisitValue }; + MapDataStartVisitEntry, MapDataEndVisitKey, MapDataEndVisitValue, + SetDataStartVisitEntry, SetDataEndVisitKey }; // These can't be reordered, and any new types must be added to the end of the list enum SerializationTag { @@ -122,9 +140,11 @@ enum SerializationTag { SetObjectTag = 29, MapObjectTag = 30, NonMapPropertiesTag = 31, + NonSetPropertiesTag = 32, #if ENABLE(SUBTLE_CRYPTO) - CryptoKeyTag = 32, + CryptoKeyTag = 33, #endif + SharedArrayBufferTag = 34, ErrorTag = 255 }; @@ -166,6 +186,8 @@ static unsigned typedArrayElementSize(ArrayBufferViewSubtag tag) #if ENABLE(SUBTLE_CRYPTO) +const uint32_t currentKeyFormatVersion = 1; + enum class CryptoKeyClassSubtag { HMAC = 0, AES = 1, @@ -217,7 +239,7 @@ enum class CryptoAlgorithmIdentifierTag { }; const uint8_t cryptoAlgorithmIdentifierTagMaximumValue = 21; -static unsigned countUsages(CryptoKeyUsage usages) +static unsigned countUsages(CryptoKeyUsageBitmap usages) { // Fast bit count algorithm for sparse bit maps. unsigned count = 0; @@ -239,12 +261,16 @@ static unsigned countUsages(CryptoKeyUsage usages) * and EmptyStringObjectTag for serialization of Boolean, Number and String objects. * Version 4. added support for serializing non-index properties of arrays. * Version 5. added support for Map and Set types. + * Version 6. added support for 8-bit strings. */ -static const unsigned CurrentVersion = 5; +static const unsigned CurrentVersion = 6; static const unsigned TerminatorTag = 0xFFFFFFFF; static const unsigned StringPoolTag = 0xFFFFFFFE; static const unsigned NonIndexPropertiesTag = 0xFFFFFFFD; +// The high bit of a StringData's length determines the character size. +static const unsigned StringDataIs8BitFlag = 0x80000000; + /* * Object serialization is performed according to the following grammar, all tags * are recorded as a single uint8_t. @@ -264,9 +290,10 @@ static const unsigned NonIndexPropertiesTag = 0xFFFFFFFD; * * Map :- MapObjectTag MapData * - * Set :- SetObjectTag MapData + * Set :- SetObjectTag SetData * - * MapData :- (<key:Value><value:Value>) NonMapPropertiesTag (<name:StringData><value:Value>)* TerminatorTag + * MapData :- (<key:Value><value:Value>)* NonMapPropertiesTag (<name:StringData><value:Value>)* TerminatorTag + * SetData :- (<key:Value>)* NonSetPropertiesTag (<name:StringData><value:Value>)* TerminatorTag * * Terminal :- * UndefinedTag @@ -293,7 +320,11 @@ static const unsigned NonIndexPropertiesTag = 0xFFFFFFFD; * | ArrayBuffer * | ArrayBufferViewTag ArrayBufferViewSubtag <byteOffset:uint32_t> <byteLength:uint32_t> (ArrayBuffer | ObjectReference) * | ArrayBufferTransferTag <value:uint32_t> - * | CryptoKeyTag <extractable:int32_t> <usagesCount:uint32_t> <usages:byte{usagesCount}> CryptoKeyClassSubtag (CryptoKeyHMAC | CryptoKeyAES | CryptoKeyRSA) + * | CryptoKeyTag <wrappedKeyLength:uint32_t> <factor:byte{wrappedKeyLength}> + * + * Inside wrapped crypto key, data is serialized in this format: + * + * <keyFormatVersion:uint32_t> <extractable:int32_t> <usagesCount:uint32_t> <usages:byte{usagesCount}> CryptoKeyClassSubtag (CryptoKeyHMAC | CryptoKeyAES | CryptoKeyRSA) * * String :- * EmptyStringTag @@ -305,13 +336,13 @@ static const unsigned NonIndexPropertiesTag = 0xFFFFFFFD; * * StringData :- * StringPoolTag <cpIndex:IndexType> - * (not (TerminatorTag | StringPoolTag))<length:uint32_t><characters:UChar{length}> // Added to constant pool when seen, string length 0xFFFFFFFF is disallowed + * (not (TerminatorTag | StringPoolTag))<is8Bit:uint32_t:1><length:uint32_t:31><characters:CharType{length}> // Added to constant pool when seen, string length 0xFFFFFFFF is disallowed * * File :- * FileTag FileData * * FileData :- - * <path:StringData> <url:StringData> <type:StringData> + * <path:StringData> <url:StringData> <type:StringData> <name:StringData> * * FileList :- * FileListTag <length:uint32_t>(<file:FileData>){length} @@ -354,7 +385,7 @@ static const unsigned NonIndexPropertiesTag = 0xFFFFFFFD; * <factorSize:uint32_t> <factor:byte{factorSize}> <crtExponentSize:uint32_t> <crtExponent:byte{crtExponentSize}> <crtCoefficientSize:uint32_t> <crtCoefficient:byte{crtCoefficientSize}> */ -typedef std::pair<JSC::JSValue, SerializationReturnCode> DeserializationResult; +using DeserializationResult = std::pair<JSC::JSValue, SerializationReturnCode>; class CloneBase { protected: @@ -366,18 +397,13 @@ protected: bool shouldTerminate() { - return m_exec->hadException(); - } - - void throwStackOverflow() - { - m_exec->vm().throwException(m_exec, createStackOverflowError(m_exec)); + VM& vm = m_exec->vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + return scope.exception(); } - NO_RETURN_DUE_TO_ASSERT void fail() { - ASSERT_NOT_REACHED(); m_failed = true; } @@ -386,6 +412,24 @@ protected: MarkedArgumentBuffer m_gcBuffer; }; +#if ENABLE(SUBTLE_CRYPTO) +static bool wrapCryptoKey(ExecState* exec, const Vector<uint8_t>& key, Vector<uint8_t>& wrappedKey) +{ + ScriptExecutionContext* scriptExecutionContext = scriptExecutionContextFromExecState(exec); + if (!scriptExecutionContext) + return false; + return scriptExecutionContext->wrapCryptoKey(key, wrappedKey); +} + +static bool unwrapCryptoKey(ExecState* exec, const Vector<uint8_t>& wrappedKey, Vector<uint8_t>& key) +{ + ScriptExecutionContext* scriptExecutionContext = scriptExecutionContextFromExecState(exec); + if (!scriptExecutionContext) + return false; + return scriptExecutionContext->unwrapCryptoKey(wrappedKey, key); +} +#endif + #if ASSUME_LITTLE_ENDIAN template <typename T> static void writeLittleEndian(Vector<uint8_t>& buffer, T value) { @@ -433,24 +477,26 @@ template <> bool writeLittleEndian<uint8_t>(Vector<uint8_t>& buffer, const uint8 class CloneSerializer : CloneBase { public: - static SerializationReturnCode serialize(ExecState* exec, JSValue value, - MessagePortArray* messagePorts, ArrayBufferArray* arrayBuffers, - Vector<String>& blobURLs, Vector<uint8_t>& out) + static SerializationReturnCode serialize(ExecState* exec, JSValue value, Vector<RefPtr<MessagePort>>& messagePorts, Vector<RefPtr<JSC::ArrayBuffer>>& arrayBuffers, Vector<String>& blobURLs, Vector<uint8_t>& out, SerializationContext context, ArrayBufferContentsArray& sharedBuffers) { - CloneSerializer serializer(exec, messagePorts, arrayBuffers, blobURLs, out); + CloneSerializer serializer(exec, messagePorts, arrayBuffers, blobURLs, out, context, sharedBuffers); return serializer.serialize(value); } - static bool serialize(const String& s, Vector<uint8_t>& out) + static bool serialize(StringView string, Vector<uint8_t>& out) { writeLittleEndian(out, CurrentVersion); - if (s.isEmpty()) { + if (string.isEmpty()) { writeLittleEndian<uint8_t>(out, EmptyStringTag); return true; } writeLittleEndian<uint8_t>(out, StringTag); - writeLittleEndian(out, s.length()); - return writeLittleEndian(out, s.impl()->deprecatedCharacters(), s.length()); + if (string.is8Bit()) { + writeLittleEndian(out, string.length() | StringDataIs8BitFlag); + return writeLittleEndian(out, string.characters8(), string.length()); + } + writeLittleEndian(out, string.length()); + return writeLittleEndian(out, string.characters16(), string.length()); } static void serializeUndefined(Vector<uint8_t>& out) @@ -480,11 +526,13 @@ public: private: typedef HashMap<JSObject*, uint32_t> ObjectPool; - CloneSerializer(ExecState* exec, MessagePortArray* messagePorts, ArrayBufferArray* arrayBuffers, Vector<String>& blobURLs, Vector<uint8_t>& out) + CloneSerializer(ExecState* exec, Vector<RefPtr<MessagePort>>& messagePorts, Vector<RefPtr<JSC::ArrayBuffer>>& arrayBuffers, Vector<String>& blobURLs, Vector<uint8_t>& out, SerializationContext context, ArrayBufferContentsArray& sharedBuffers) : CloneBase(exec) , m_buffer(out) , m_blobURLs(blobURLs) - , m_emptyIdentifier(exec, emptyString()) + , m_emptyIdentifier(Identifier::fromString(exec, emptyString())) + , m_context(context) + , m_sharedBuffers(sharedBuffers) { write(CurrentVersion); fillTransferMap(messagePorts, m_transferredMessagePorts); @@ -492,13 +540,13 @@ private: } template <class T> - void fillTransferMap(Vector<RefPtr<T>, 1>* input, ObjectPool& result) + void fillTransferMap(Vector<RefPtr<T>>& input, ObjectPool& result) { - if (!input) + if (input.isEmpty()) return; JSDOMGlobalObject* globalObject = jsCast<JSDOMGlobalObject*>(m_exec->lexicalGlobalObject()); - for (size_t i = 0; i < input->size(); i++) { - JSC::JSValue value = toJS(m_exec, globalObject, input->at(i).get()); + for (size_t i = 0; i < input.size(); i++) { + JSC::JSValue value = toJS(m_exec, globalObject, input[i].get()); JSC::JSObject* obj = value.getObject(); if (obj && !result.contains(obj)) result.add(obj, i); @@ -507,27 +555,27 @@ private: SerializationReturnCode serialize(JSValue in); - bool isArray(JSValue value) + bool isArray(VM& vm, JSValue value) { if (!value.isObject()) return false; JSObject* object = asObject(value); - return isJSArray(object) || object->inherits(JSArray::info()); + return isJSArray(object) || object->inherits(vm, JSArray::info()); } - bool isMap(JSValue value) + bool isMap(VM& vm, JSValue value) { if (!value.isObject()) return false; JSObject* object = asObject(value); - return object->inherits(JSMap::info()); + return object->inherits(vm, JSMap::info()); } - bool isSet(JSValue value) + bool isSet(VM& vm, JSValue value) { if (!value.isObject()) return false; JSObject* object = asObject(value); - return object->inherits(JSSet::info()); + return object->inherits(vm, JSSet::info()); } bool checkForDuplicate(JSObject* object) @@ -538,7 +586,7 @@ private: // Handle duplicate references if (found != m_objectPool.end()) { write(ObjectReferenceTag); - ASSERT(static_cast<int32_t>(found->value) < m_objectPool.size()); + ASSERT(found->value < m_objectPool.size()); writeObjectIndex(found->value); return true; } @@ -604,7 +652,7 @@ private: JSValue getProperty(JSObject* object, const Identifier& propertyName) { - PropertySlot slot(object); + PropertySlot slot(object, PropertySlot::InternalMethodType::Get); if (object->methodTable()->getOwnPropertySlot(object, m_exec, propertyName, slot)) return slot.getValue(m_exec, propertyName); return JSValue(); @@ -638,58 +686,59 @@ private: } } - void dumpString(String str) + void dumpString(const String& string) { - if (str.isEmpty()) + if (string.isEmpty()) write(EmptyStringTag); else { write(StringTag); - write(str); + write(string); } } - void dumpStringObject(String str) + void dumpStringObject(const String& string) { - if (str.isEmpty()) + if (string.isEmpty()) write(EmptyStringObjectTag); else { write(StringObjectTag); - write(str); + write(string); } } bool dumpArrayBufferView(JSObject* obj, SerializationReturnCode& code) { + VM& vm = m_exec->vm(); write(ArrayBufferViewTag); - if (obj->inherits(JSDataView::info())) + if (obj->inherits(vm, JSDataView::info())) write(DataViewTag); - else if (obj->inherits(JSUint8ClampedArray::info())) + else if (obj->inherits(vm, JSUint8ClampedArray::info())) write(Uint8ClampedArrayTag); - else if (obj->inherits(JSInt8Array::info())) + else if (obj->inherits(vm, JSInt8Array::info())) write(Int8ArrayTag); - else if (obj->inherits(JSUint8Array::info())) + else if (obj->inherits(vm, JSUint8Array::info())) write(Uint8ArrayTag); - else if (obj->inherits(JSInt16Array::info())) + else if (obj->inherits(vm, JSInt16Array::info())) write(Int16ArrayTag); - else if (obj->inherits(JSUint16Array::info())) + else if (obj->inherits(vm, JSUint16Array::info())) write(Uint16ArrayTag); - else if (obj->inherits(JSInt32Array::info())) + else if (obj->inherits(vm, JSInt32Array::info())) write(Int32ArrayTag); - else if (obj->inherits(JSUint32Array::info())) + else if (obj->inherits(vm, JSUint32Array::info())) write(Uint32ArrayTag); - else if (obj->inherits(JSFloat32Array::info())) + else if (obj->inherits(vm, JSFloat32Array::info())) write(Float32ArrayTag); - else if (obj->inherits(JSFloat64Array::info())) + else if (obj->inherits(vm, JSFloat64Array::info())) write(Float64ArrayTag); else return false; - RefPtr<ArrayBufferView> arrayBufferView = toArrayBufferView(obj); + RefPtr<ArrayBufferView> arrayBufferView = toPossiblySharedArrayBufferView(vm, obj); write(static_cast<uint32_t>(arrayBufferView->byteOffset())); write(static_cast<uint32_t>(arrayBufferView->byteLength())); - RefPtr<ArrayBuffer> arrayBuffer = arrayBufferView->buffer(); + RefPtr<ArrayBuffer> arrayBuffer = arrayBufferView->possiblySharedBuffer(); if (!arrayBuffer) { - code = ValidationError; + code = SerializationReturnCode::ValidationError; return true; } JSValue bufferObj = toJS(m_exec, jsCast<JSDOMGlobalObject*>(m_exec->lexicalGlobalObject()), arrayBuffer.get()); @@ -704,8 +753,7 @@ private: } if (value.isString()) { - String str = asString(value)->value(m_exec); - dumpString(str); + dumpString(asString(value)->value(m_exec)); return true; } @@ -715,31 +763,32 @@ private: return true; } - if (value.isObject() && asObject(value)->inherits(DateInstance::info())) { + VM& vm = m_exec->vm(); + if (value.isObject() && asObject(value)->inherits(vm, DateInstance::info())) { write(DateTag); write(asDateInstance(value)->internalNumber()); return true; } - if (isArray(value)) + if (isArray(vm, value)) return false; if (value.isObject()) { JSObject* obj = asObject(value); - if (obj->inherits(BooleanObject::info())) { + if (obj->inherits(vm, BooleanObject::info())) { if (!startObjectInternal(obj)) // handle duplicates return true; write(asBooleanObject(value)->internalValue().toBoolean(m_exec) ? TrueObjectTag : FalseObjectTag); return true; } - if (obj->inherits(StringObject::info())) { + if (obj->inherits(vm, StringObject::info())) { if (!startObjectInternal(obj)) // handle duplicates return true; String str = asString(asStringObject(value)->internalValue())->value(m_exec); dumpStringObject(str); return true; } - if (obj->inherits(NumberObject::info())) { + if (obj->inherits(vm, NumberObject::info())) { if (!startObjectInternal(obj)) // handle duplicates return true; write(NumberObjectTag); @@ -747,12 +796,12 @@ private: write(obj->internalValue().asNumber()); return true; } - if (File* file = toFile(obj)) { + if (File* file = JSFile::toWrapped(vm, obj)) { write(FileTag); write(file); return true; } - if (FileList* list = toFileList(obj)) { + if (FileList* list = JSFileList::toWrapped(vm, obj)) { write(FileListTag); unsigned length = list->length(); write(length); @@ -760,7 +809,7 @@ private: write(list->item(i)); return true; } - if (Blob* blob = toBlob(obj)) { + if (Blob* blob = JSBlob::toWrapped(vm, obj)) { write(BlobTag); m_blobURLs.append(blob->url()); write(blob->url()); @@ -768,7 +817,7 @@ private: write(blob->size()); return true; } - if (ImageData* data = toImageData(obj)) { + if (ImageData* data = JSImageData::toWrapped(vm, obj)) { write(ImageDataTag); write(data->width()); write(data->height()); @@ -776,7 +825,7 @@ private: write(data->data()->data(), data->data()->length()); return true; } - if (obj->inherits(RegExpObject::info())) { + if (obj->inherits(vm, RegExpObject::info())) { RegExpObject* regExp = asRegExpObject(obj); char flags[3]; int flagCount = 0; @@ -791,7 +840,7 @@ private: write(String(flags, flagCount)); return true; } - if (obj->inherits(JSMessagePort::info())) { + if (obj->inherits(vm, JSMessagePort::info())) { ObjectPool::iterator index = m_transferredMessagePorts.find(obj); if (index != m_transferredMessagePorts.end()) { write(MessagePortReferenceTag); @@ -799,12 +848,12 @@ private: return true; } // MessagePort object could not be found in transferred message ports - code = ValidationError; + code = SerializationReturnCode::ValidationError; return true; } - if (ArrayBuffer* arrayBuffer = toArrayBuffer(obj)) { + if (ArrayBuffer* arrayBuffer = toPossiblySharedArrayBuffer(vm, obj)) { if (arrayBuffer->isNeutered()) { - code = ValidationError; + code = SerializationReturnCode::ValidationError; return true; } ObjectPool::iterator index = m_transferredArrayBuffers.find(obj); @@ -815,12 +864,25 @@ private: } if (!startObjectInternal(obj)) // handle duplicates return true; + + if (arrayBuffer->isShared() + && m_context == SerializationContext::WorkerPostMessage) { + uint32_t index = m_sharedBuffers.size(); + ArrayBufferContents contents; + if (arrayBuffer->shareWith(contents)) { + write(SharedArrayBufferTag); + m_sharedBuffers.append(WTFMove(contents)); + write(index); + return true; + } + } + write(ArrayBufferTag); write(arrayBuffer->byteLength()); write(static_cast<const uint8_t*>(arrayBuffer->data()), arrayBuffer->byteLength()); return true; } - if (obj->inherits(JSArrayBufferView::info())) { + if (obj->inherits(vm, JSArrayBufferView::info())) { if (checkForDuplicate(obj)) return true; bool success = dumpArrayBufferView(obj, code); @@ -828,9 +890,19 @@ private: return success; } #if ENABLE(SUBTLE_CRYPTO) - if (CryptoKey* key = toCryptoKey(obj)) { + if (CryptoKey* key = JSCryptoKey::toWrapped(vm, obj)) { write(CryptoKeyTag); - write(key); + Vector<uint8_t> serializedKey; + Vector<String> dummyBlobURLs; + Vector<RefPtr<MessagePort>> dummyMessagePorts; + Vector<RefPtr<JSC::ArrayBuffer>> dummyArrayBuffers; + ArrayBufferContentsArray dummySharedBuffers; + CloneSerializer rawKeySerializer(m_exec, dummyMessagePorts, dummyArrayBuffers, dummyBlobURLs, serializedKey, SerializationContext::Default, dummySharedBuffers); + rawKeySerializer.write(key); + Vector<uint8_t> wrappedKey; + if (!wrapCryptoKey(m_exec, serializedKey, wrappedKey)) + return false; + write(wrappedKey); return true; } #endif @@ -921,7 +993,7 @@ private: template <class T> void writeConstantPoolIndex(const T& constantPool, unsigned i) { - ASSERT(static_cast<int32_t>(i) < constantPool.size()); + ASSERT(i < constantPool.size()); if (constantPool.size() <= 0xFF) write(static_cast<uint8_t>(i)); else if (constantPool.size() <= 0xFFFF) @@ -933,28 +1005,34 @@ private: void write(const Identifier& ident) { const String& str = ident.string(); - StringConstantPool::AddResult addResult = m_constantPool.add(str.impl(), m_constantPool.size()); + StringConstantPool::AddResult addResult = m_constantPool.add(ident.impl(), m_constantPool.size()); if (!addResult.isNewEntry) { write(StringPoolTag); writeStringIndex(addResult.iterator->value); return; } - // This condition is unlikely to happen as they would imply an ~8gb - // string but we should guard against it anyway - if (str.length() >= StringPoolTag) { - fail(); - return; - } + unsigned length = str.length(); // Guard against overflow - if (str.length() > (std::numeric_limits<uint32_t>::max() - sizeof(uint32_t)) / sizeof(UChar)) { + if (length > (std::numeric_limits<uint32_t>::max() - sizeof(uint32_t)) / sizeof(UChar)) { fail(); return; } - writeLittleEndian<uint32_t>(m_buffer, str.length()); - if (!writeLittleEndian<uint16_t>(m_buffer, reinterpret_cast<const uint16_t*>(str.deprecatedCharacters()), str.length())) + if (str.is8Bit()) + writeLittleEndian<uint32_t>(m_buffer, length | StringDataIs8BitFlag); + else + writeLittleEndian<uint32_t>(m_buffer, length); + + if (!length) + return; + if (str.is8Bit()) { + if (!writeLittleEndian(m_buffer, str.characters8(), length)) + fail(); + return; + } + if (!writeLittleEndian(m_buffer, str.characters16(), length)) fail(); } @@ -963,7 +1041,7 @@ private: if (str.isNull()) write(m_emptyIdentifier); else - write(Identifier(m_exec, str)); + write(Identifier::fromString(m_exec, str)); } void write(const Vector<uint8_t>& vector) @@ -979,6 +1057,7 @@ private: write(file->path()); write(file->url()); write(file->type()); + write(file->name()); } #if ENABLE(SUBTLE_CRYPTO) @@ -1095,9 +1174,11 @@ private: void write(const CryptoKey* key) { + write(currentKeyFormatVersion); + write(key->extractable()); - CryptoKeyUsage usages = key->usagesBitmap(); + CryptoKeyUsageBitmap usages = key->usagesBitmap(); write(countUsages(usages)); if (usages & CryptoKeyUsageEncrypt) write(CryptoKeyUsageTag::Encrypt); @@ -1119,23 +1200,23 @@ private: switch (key->keyClass()) { case CryptoKeyClass::HMAC: write(CryptoKeyClassSubtag::HMAC); - write(toCryptoKeyHMAC(key)->key()); - write(toCryptoKeyHMAC(key)->hashAlgorithmIdentifier()); + write(downcast<CryptoKeyHMAC>(*key).key()); + write(downcast<CryptoKeyHMAC>(*key).hashAlgorithmIdentifier()); break; case CryptoKeyClass::AES: write(CryptoKeyClassSubtag::AES); write(key->algorithmIdentifier()); - write(toCryptoKeyAES(key)->key()); + write(downcast<CryptoKeyAES>(*key).key()); break; case CryptoKeyClass::RSA: write(CryptoKeyClassSubtag::RSA); write(key->algorithmIdentifier()); CryptoAlgorithmIdentifier hash; - bool isRestrictedToHash = toCryptoKeyRSA(key)->isRestrictedToHash(hash); + bool isRestrictedToHash = downcast<CryptoKeyRSA>(*key).isRestrictedToHash(hash); write(isRestrictedToHash); if (isRestrictedToHash) write(hash); - write(toCryptoKeyDataRSAComponents(*key->exportData())); + write(downcast<CryptoKeyDataRSAComponents>(*key->exportData())); break; } } @@ -1151,20 +1232,23 @@ private: ObjectPool m_objectPool; ObjectPool m_transferredMessagePorts; ObjectPool m_transferredArrayBuffers; - typedef HashMap<RefPtr<StringImpl>, uint32_t, IdentifierRepHash> StringConstantPool; + typedef HashMap<RefPtr<UniquedStringImpl>, uint32_t, IdentifierRepHash> StringConstantPool; StringConstantPool m_constantPool; Identifier m_emptyIdentifier; + SerializationContext m_context; + ArrayBufferContentsArray& m_sharedBuffers; }; SerializationReturnCode CloneSerializer::serialize(JSValue in) { + VM& vm = m_exec->vm(); Vector<uint32_t, 16> indexStack; Vector<uint32_t, 16> lengthStack; Vector<PropertyNameArray, 16> propertyStack; Vector<JSObject*, 32> inputObjectStack; - Vector<MapData*, 4> mapDataStack; - Vector<MapData::const_iterator, 4> iteratorStack; - Vector<JSValue, 4> iteratorValueStack; + Vector<JSMapIterator*, 4> mapIteratorStack; + Vector<JSSetIterator*, 4> setIteratorStack; + Vector<JSValue, 4> mapIteratorValueStack; Vector<WalkerState, 16> stateStack; WalkerState state = StateUnknown; JSValue inValue = in; @@ -1172,9 +1256,9 @@ SerializationReturnCode CloneSerializer::serialize(JSValue in) switch (state) { arrayStartState: case ArrayStartState: { - ASSERT(isArray(inValue)); + ASSERT(isArray(vm, inValue)); if (inputObjectStack.size() > maximumFilterRecursion) - return StackOverflowError; + return SerializationReturnCode::StackOverflowError; JSArray* inArray = asArray(inValue); unsigned length = inArray->length(); @@ -1193,8 +1277,8 @@ SerializationReturnCode CloneSerializer::serialize(JSValue in) indexStack.removeLast(); lengthStack.removeLast(); - propertyStack.append(PropertyNameArray(m_exec)); - array->methodTable()->getOwnNonIndexPropertyNames(array, m_exec, propertyStack.last(), ExcludeDontEnumProperties); + propertyStack.append(PropertyNameArray(m_exec, PropertyNameMode::Strings)); + array->methodTable()->getOwnNonIndexPropertyNames(array, m_exec, propertyStack.last(), EnumerationMode()); if (propertyStack.last().size()) { write(NonIndexPropertiesTag); indexStack.append(0); @@ -1213,9 +1297,9 @@ SerializationReturnCode CloneSerializer::serialize(JSValue in) } write(index); - SerializationReturnCode terminalCode = SuccessfullyCompleted; + auto terminalCode = SerializationReturnCode::SuccessfullyCompleted; if (dumpIfTerminal(inValue, terminalCode)) { - if (terminalCode != SuccessfullyCompleted) + if (terminalCode != SerializationReturnCode::SuccessfullyCompleted) return terminalCode; indexStack.last()++; goto arrayStartVisitMember; @@ -1231,7 +1315,7 @@ SerializationReturnCode CloneSerializer::serialize(JSValue in) case ObjectStartState: { ASSERT(inValue.isObject()); if (inputObjectStack.size() > maximumFilterRecursion) - return StackOverflowError; + return SerializationReturnCode::StackOverflowError; JSObject* inObject = asObject(inValue); if (!startObject(inObject)) break; @@ -1239,12 +1323,12 @@ SerializationReturnCode CloneSerializer::serialize(JSValue in) // objects have been handled. If we reach this point and // the input is not an Object object then we should throw // a DataCloneError. - if (inObject->classInfo() != JSFinalObject::info()) - return DataCloneError; + if (inObject->classInfo(vm) != JSFinalObject::info()) + return SerializationReturnCode::DataCloneError; inputObjectStack.append(inObject); indexStack.append(0); - propertyStack.append(PropertyNameArray(m_exec)); - inObject->methodTable()->getOwnPropertyNames(inObject, m_exec, propertyStack.last(), ExcludeDontEnumProperties); + propertyStack.append(PropertyNameArray(m_exec, PropertyNameMode::Strings)); + inObject->methodTable()->getOwnPropertyNames(inObject, m_exec, propertyStack.last(), EnumerationMode()); } objectStartVisitMember: FALLTHROUGH; @@ -1261,7 +1345,7 @@ SerializationReturnCode CloneSerializer::serialize(JSValue in) } inValue = getProperty(object, properties[index]); if (shouldTerminate()) - return ExistingExceptionError; + return SerializationReturnCode::ExistingExceptionError; if (!inValue) { // Property was removed during serialisation @@ -1271,20 +1355,20 @@ SerializationReturnCode CloneSerializer::serialize(JSValue in) write(properties[index]); if (shouldTerminate()) - return ExistingExceptionError; + return SerializationReturnCode::ExistingExceptionError; - SerializationReturnCode terminalCode = SuccessfullyCompleted; + auto terminalCode = SerializationReturnCode::SuccessfullyCompleted; if (!dumpIfTerminal(inValue, terminalCode)) { stateStack.append(ObjectEndVisitMember); goto stateUnknown; } - if (terminalCode != SuccessfullyCompleted) + if (terminalCode != SerializationReturnCode::SuccessfullyCompleted) return terminalCode; FALLTHROUGH; } case ObjectEndVisitMember: { if (shouldTerminate()) - return ExistingExceptionError; + return SerializationReturnCode::ExistingExceptionError; indexStack.last()++; goto objectStartVisitMember; @@ -1292,78 +1376,97 @@ SerializationReturnCode CloneSerializer::serialize(JSValue in) mapStartState: { ASSERT(inValue.isObject()); if (inputObjectStack.size() > maximumFilterRecursion) - return StackOverflowError; + return SerializationReturnCode::StackOverflowError; JSMap* inMap = jsCast<JSMap*>(inValue); if (!startMap(inMap)) break; - MapData* mapData = inMap->mapData(); - m_gcBuffer.append(mapData); - mapDataStack.append(mapData); - iteratorStack.append(mapData->begin()); + JSMapIterator* iterator = JSMapIterator::create(vm, m_exec->lexicalGlobalObject()->mapIteratorStructure(), inMap, IterateKeyValue); + m_gcBuffer.append(inMap); + m_gcBuffer.append(iterator); + mapIteratorStack.append(iterator); inputObjectStack.append(inMap); goto mapDataStartVisitEntry; } - setStartState: { - ASSERT(inValue.isObject()); - if (inputObjectStack.size() > maximumFilterRecursion) - return StackOverflowError; - JSSet* inSet = jsCast<JSSet*>(inValue); - if (!startSet(inSet)) - break; - MapData* mapData = inSet->mapData(); - m_gcBuffer.append(mapData); - mapDataStack.append(mapData); - iteratorStack.append(mapData->begin()); - inputObjectStack.append(inSet); - goto mapDataStartVisitEntry; - } mapDataStartVisitEntry: case MapDataStartVisitEntry: { - MapData::const_iterator& ptr = iteratorStack.last(); - MapData* mapData = mapDataStack.last(); - if (ptr == mapData->end()) { - iteratorStack.removeLast(); - mapDataStack.removeLast(); + JSMapIterator* iterator = mapIteratorStack.last(); + JSValue key, value; + if (!iterator->nextKeyValue(m_exec, key, value)) { + mapIteratorStack.removeLast(); JSObject* object = inputObjectStack.last(); - ASSERT(jsDynamicCast<JSSet*>(object) || jsDynamicCast<JSMap*>(object)); - propertyStack.append(PropertyNameArray(m_exec)); - object->methodTable()->getOwnPropertyNames(object, m_exec, propertyStack.last(), ExcludeDontEnumProperties); + ASSERT(jsDynamicDowncast<JSMap*>(vm, object)); + propertyStack.append(PropertyNameArray(m_exec, PropertyNameMode::Strings)); + object->methodTable()->getOwnPropertyNames(object, m_exec, propertyStack.last(), EnumerationMode()); write(NonMapPropertiesTag); indexStack.append(0); goto objectStartVisitMember; } - inValue = ptr.key(); - m_gcBuffer.append(ptr.value()); - iteratorValueStack.append(ptr.value()); + inValue = key; + m_gcBuffer.append(value); + mapIteratorValueStack.append(value); stateStack.append(MapDataEndVisitKey); goto stateUnknown; } case MapDataEndVisitKey: { - inValue = iteratorValueStack.last(); - iteratorValueStack.removeLast(); + inValue = mapIteratorValueStack.last(); + mapIteratorValueStack.removeLast(); stateStack.append(MapDataEndVisitValue); goto stateUnknown; } case MapDataEndVisitValue: { - if (iteratorStack.last() != mapDataStack.last()->end()) - ++iteratorStack.last(); goto mapDataStartVisitEntry; } + setStartState: { + ASSERT(inValue.isObject()); + if (inputObjectStack.size() > maximumFilterRecursion) + return SerializationReturnCode::StackOverflowError; + JSSet* inSet = jsCast<JSSet*>(inValue); + if (!startSet(inSet)) + break; + JSSetIterator* iterator = JSSetIterator::create(vm, m_exec->lexicalGlobalObject()->setIteratorStructure(), inSet, IterateKey); + m_gcBuffer.append(inSet); + m_gcBuffer.append(iterator); + setIteratorStack.append(iterator); + inputObjectStack.append(inSet); + goto setDataStartVisitEntry; + } + setDataStartVisitEntry: + case SetDataStartVisitEntry: { + JSSetIterator* iterator = setIteratorStack.last(); + JSValue key; + if (!iterator->next(m_exec, key)) { + setIteratorStack.removeLast(); + JSObject* object = inputObjectStack.last(); + ASSERT(jsDynamicDowncast<JSSet*>(vm, object)); + propertyStack.append(PropertyNameArray(m_exec, PropertyNameMode::Strings)); + object->methodTable()->getOwnPropertyNames(object, m_exec, propertyStack.last(), EnumerationMode()); + write(NonSetPropertiesTag); + indexStack.append(0); + goto objectStartVisitMember; + } + inValue = key; + stateStack.append(SetDataEndVisitKey); + goto stateUnknown; + } + case SetDataEndVisitKey: { + goto setDataStartVisitEntry; + } + stateUnknown: case StateUnknown: { - SerializationReturnCode terminalCode = SuccessfullyCompleted; + auto terminalCode = SerializationReturnCode::SuccessfullyCompleted; if (dumpIfTerminal(inValue, terminalCode)) { - if (terminalCode != SuccessfullyCompleted) + if (terminalCode != SerializationReturnCode::SuccessfullyCompleted) return terminalCode; break; } - if (isArray(inValue)) + if (isArray(vm, inValue)) goto arrayStartState; - if (isMap(inValue)) + if (isMap(vm, inValue)) goto mapStartState; - if (isSet(inValue)) + if (isSet(vm, inValue)) goto setStartState; goto objectStartState; } @@ -1375,13 +1478,11 @@ SerializationReturnCode CloneSerializer::serialize(JSValue in) stateStack.removeLast(); } if (m_failed) - return UnspecifiedError; + return SerializationReturnCode::UnspecifiedError; - return SuccessfullyCompleted; + return SerializationReturnCode::SuccessfullyCompleted; } -typedef Vector<JSC::ArrayBufferContents> ArrayBufferContentsArray; - class CloneDeserializer : CloneBase { public: static String deserializeString(const Vector<uint8_t>& buffer) @@ -1397,23 +1498,23 @@ public: if (!readLittleEndian(ptr, end, tag) || tag != StringTag) return String(); uint32_t length; - if (!readLittleEndian(ptr, end, length) || length >= StringPoolTag) + if (!readLittleEndian(ptr, end, length)) return String(); + bool is8Bit = length & StringDataIs8BitFlag; + length &= ~StringDataIs8BitFlag; String str; - if (!readString(ptr, end, str, length)) + if (!readString(ptr, end, str, length, is8Bit)) return String(); - return String(str.impl()); + return str; } - static DeserializationResult deserialize(ExecState* exec, JSGlobalObject* globalObject, - MessagePortArray* messagePorts, ArrayBufferContentsArray* arrayBufferContentsArray, - const Vector<uint8_t>& buffer) + static DeserializationResult deserialize(ExecState* exec, JSGlobalObject* globalObject, Vector<RefPtr<MessagePort>>& messagePorts, ArrayBufferContentsArray* arrayBufferContentsArray, const Vector<uint8_t>& buffer, const Vector<String>& blobURLs, const Vector<String> blobFilePaths, ArrayBufferContentsArray* sharedBuffers) { if (!buffer.size()) - return std::make_pair(jsNull(), UnspecifiedError); - CloneDeserializer deserializer(exec, globalObject, messagePorts, arrayBufferContentsArray, buffer); + return std::make_pair(jsNull(), SerializationReturnCode::UnspecifiedError); + CloneDeserializer deserializer(exec, globalObject, messagePorts, arrayBufferContentsArray, buffer, blobURLs, blobFilePaths, sharedBuffers); if (!deserializer.isValid()) - return std::make_pair(JSValue(), ValidationError); + return std::make_pair(JSValue(), SerializationReturnCode::ValidationError); return deserializer.deserialize(); } @@ -1456,12 +1557,10 @@ private: size_t m_index; }; - CloneDeserializer(ExecState* exec, JSGlobalObject* globalObject, - MessagePortArray* messagePorts, ArrayBufferContentsArray* arrayBufferContents, - const Vector<uint8_t>& buffer) + CloneDeserializer(ExecState* exec, JSGlobalObject* globalObject, Vector<RefPtr<MessagePort>>& messagePorts, ArrayBufferContentsArray* arrayBufferContents, const Vector<uint8_t>& buffer) : CloneBase(exec) , m_globalObject(globalObject) - , m_isDOMGlobalObject(globalObject->inherits(JSDOMGlobalObject::info())) + , m_isDOMGlobalObject(globalObject->inherits(globalObject->vm(), JSDOMGlobalObject::info())) , m_ptr(buffer.data()) , m_end(buffer.data() + buffer.size()) , m_version(0xFFFFFFFF) @@ -1473,13 +1572,26 @@ private: m_version = 0xFFFFFFFF; } - DeserializationResult deserialize(); - - void throwValidationError() + CloneDeserializer(ExecState* exec, JSGlobalObject* globalObject, Vector<RefPtr<MessagePort>>& messagePorts, ArrayBufferContentsArray* arrayBufferContents, const Vector<uint8_t>& buffer, const Vector<String>& blobURLs, const Vector<String> blobFilePaths, ArrayBufferContentsArray* sharedBuffers) + : CloneBase(exec) + , m_globalObject(globalObject) + , m_isDOMGlobalObject(globalObject->inherits(globalObject->vm(), JSDOMGlobalObject::info())) + , m_ptr(buffer.data()) + , m_end(buffer.data() + buffer.size()) + , m_version(0xFFFFFFFF) + , m_messagePorts(messagePorts) + , m_arrayBufferContents(arrayBufferContents) + , m_arrayBuffers(arrayBufferContents ? arrayBufferContents->size() : 0) + , m_blobURLs(blobURLs) + , m_blobFilePaths(blobFilePaths) + , m_sharedBuffers(sharedBuffers) { - m_exec->vm().throwException(m_exec, createTypeError(m_exec, "Unable to deserialize data.")); + if (!read(m_version)) + m_version = 0xFFFFFFFF; } + DeserializationResult deserialize(); + bool isValid() const { return m_version <= CurrentVersion; } template <typename T> bool readLittleEndian(T& value) @@ -1582,11 +1694,19 @@ private: return read(i); } - static bool readString(const uint8_t*& ptr, const uint8_t* end, String& str, unsigned length) + static bool readString(const uint8_t*& ptr, const uint8_t* end, String& str, unsigned length, bool is8Bit) { if (length >= std::numeric_limits<int32_t>::max() / sizeof(UChar)) return false; + if (is8Bit) { + if ((end - ptr) < static_cast<int>(length)) + return false; + str = String(reinterpret_cast<const LChar*>(ptr), length); + ptr += length; + return true; + } + unsigned size = length * sizeof(UChar); if ((end - ptr) < static_cast<int>(size)) return false; @@ -1602,7 +1722,7 @@ private: readLittleEndian(ptr, end, ch); buffer.append(ch); } - str = String::adopt(buffer); + str = String::adopt(WTFMove(buffer)); #endif return true; } @@ -1637,8 +1757,10 @@ private: cachedString = CachedStringRef(&m_constantPool, index); return true; } + bool is8Bit = length & StringDataIs8BitFlag; + length &= ~StringDataIs8BitFlag; String str; - if (!readString(m_ptr, m_end, str, length)) { + if (!readString(m_ptr, m_end, str, length, is8Bit)) { fail(); return false; } @@ -1683,8 +1805,17 @@ private: CachedStringRef type; if (!readStringData(type)) return 0; + CachedStringRef name; + if (!readStringData(name)) + return 0; + + // If the blob URL for this file has an associated blob file path, prefer that one over the "built-in" path. + String filePath = blobFilePathForBlobURL(url->string()); + if (filePath.isEmpty()) + filePath = path->string(); + if (m_isDOMGlobalObject) - file = File::create(path->string(), URL(URL(), url->string()), type->string()); + file = File::deserialize(filePath, URL(URL(), url->string()), type->string(), name->string()); return true; } @@ -1700,7 +1831,7 @@ private: return true; } - bool readArrayBufferView(JSValue& arrayBufferView) + bool readArrayBufferView(VM& vm, JSValue& arrayBufferView) { ArrayBufferViewSubtag arrayBufferViewSubtag; if (!readArrayBufferViewSubtag(arrayBufferViewSubtag)) @@ -1712,7 +1843,7 @@ private: if (!read(byteLength)) return false; JSObject* arrayBufferObj = asObject(readTerminal()); - if (!arrayBufferObj || !arrayBufferObj->inherits(JSArrayBuffer::info())) + if (!arrayBufferObj || !arrayBufferObj->inherits(vm, JSArrayBuffer::info())) return false; unsigned elementSize = typedArrayElementSize(arrayBufferViewSubtag); @@ -1722,37 +1853,37 @@ private: if (length * elementSize != byteLength) return false; - RefPtr<ArrayBuffer> arrayBuffer = toArrayBuffer(arrayBufferObj); + RefPtr<ArrayBuffer> arrayBuffer = toPossiblySharedArrayBuffer(vm, arrayBufferObj); switch (arrayBufferViewSubtag) { case DataViewTag: - arrayBufferView = getJSValue(DataView::create(arrayBuffer, byteOffset, length).get()); + arrayBufferView = getJSValue(DataView::create(WTFMove(arrayBuffer), byteOffset, length).get()); return true; case Int8ArrayTag: - arrayBufferView = getJSValue(Int8Array::create(arrayBuffer, byteOffset, length).get()); + arrayBufferView = toJS(m_exec, m_globalObject, Int8Array::create(WTFMove(arrayBuffer), byteOffset, length).get()); return true; case Uint8ArrayTag: - arrayBufferView = getJSValue(Uint8Array::create(arrayBuffer, byteOffset, length).get()); + arrayBufferView = toJS(m_exec, m_globalObject, Uint8Array::create(WTFMove(arrayBuffer), byteOffset, length).get()); return true; case Uint8ClampedArrayTag: - arrayBufferView = getJSValue(Uint8ClampedArray::create(arrayBuffer, byteOffset, length).get()); + arrayBufferView = toJS(m_exec, m_globalObject, Uint8ClampedArray::create(WTFMove(arrayBuffer), byteOffset, length).get()); return true; case Int16ArrayTag: - arrayBufferView = getJSValue(Int16Array::create(arrayBuffer, byteOffset, length).get()); + arrayBufferView = toJS(m_exec, m_globalObject, Int16Array::create(WTFMove(arrayBuffer), byteOffset, length).get()); return true; case Uint16ArrayTag: - arrayBufferView = getJSValue(Uint16Array::create(arrayBuffer, byteOffset, length).get()); + arrayBufferView = toJS(m_exec, m_globalObject, Uint16Array::create(WTFMove(arrayBuffer), byteOffset, length).get()); return true; case Int32ArrayTag: - arrayBufferView = getJSValue(Int32Array::create(arrayBuffer, byteOffset, length).get()); + arrayBufferView = toJS(m_exec, m_globalObject, Int32Array::create(WTFMove(arrayBuffer), byteOffset, length).get()); return true; case Uint32ArrayTag: - arrayBufferView = getJSValue(Uint32Array::create(arrayBuffer, byteOffset, length).get()); + arrayBufferView = toJS(m_exec, m_globalObject, Uint32Array::create(WTFMove(arrayBuffer), byteOffset, length).get()); return true; case Float32ArrayTag: - arrayBufferView = getJSValue(Float32Array::create(arrayBuffer, byteOffset, length).get()); + arrayBufferView = toJS(m_exec, m_globalObject, Float32Array::create(WTFMove(arrayBuffer), byteOffset, length).get()); return true; case Float64ArrayTag: - arrayBufferView = getJSValue(Float64Array::create(arrayBuffer, byteOffset, length).get()); + arrayBufferView = toJS(m_exec, m_globalObject, Float64Array::create(WTFMove(arrayBuffer), byteOffset, length).get()); return true; default: return false; @@ -1884,7 +2015,7 @@ private: return true; } - bool readHMACKey(bool extractable, CryptoKeyUsage usages, RefPtr<CryptoKey>& result) + bool readHMACKey(bool extractable, CryptoKeyUsageBitmap usages, RefPtr<CryptoKey>& result) { Vector<uint8_t> keyData; if (!read(keyData)) @@ -1896,7 +2027,7 @@ private: return true; } - bool readAESKey(bool extractable, CryptoKeyUsage usages, RefPtr<CryptoKey>& result) + bool readAESKey(bool extractable, CryptoKeyUsageBitmap usages, RefPtr<CryptoKey>& result) { CryptoAlgorithmIdentifier algorithm; if (!read(algorithm)) @@ -1910,7 +2041,7 @@ private: return true; } - bool readRSAKey(bool extractable, CryptoKeyUsage usages, RefPtr<CryptoKey>& result) + bool readRSAKey(bool extractable, CryptoKeyUsageBitmap usages, RefPtr<CryptoKey>& result) { CryptoAlgorithmIdentifier algorithm; if (!read(algorithm)) @@ -1936,10 +2067,8 @@ private: if (type == CryptoKeyAsymmetricTypeSubtag::Public) { auto keyData = CryptoKeyDataRSAComponents::createPublic(modulus, exponent); - auto key = CryptoKeyRSA::create(algorithm, *keyData, extractable, usages); - if (isRestrictedToHash) - key->restrictToHash(hash); - result = std::move(key); + auto key = CryptoKeyRSA::create(algorithm, hash, isRestrictedToHash, *keyData, extractable, usages); + result = WTFMove(key); return true; } @@ -1953,10 +2082,8 @@ private: if (!primeCount) { auto keyData = CryptoKeyDataRSAComponents::createPrivate(modulus, exponent, privateExponent); - auto key = CryptoKeyRSA::create(algorithm, *keyData, extractable, usages); - if (isRestrictedToHash) - key->restrictToHash(hash); - result = std::move(key); + auto key = CryptoKeyRSA::create(algorithm, hash, isRestrictedToHash, *keyData, extractable, usages); + result = WTFMove(key); return true; } @@ -1987,15 +2114,17 @@ private: } auto keyData = CryptoKeyDataRSAComponents::createPrivateWithAdditionalData(modulus, exponent, privateExponent, firstPrimeInfo, secondPrimeInfo, otherPrimeInfos); - auto key = CryptoKeyRSA::create(algorithm, *keyData, extractable, usages); - if (isRestrictedToHash) - key->restrictToHash(hash); - result = std::move(key); + auto key = CryptoKeyRSA::create(algorithm, hash, isRestrictedToHash, *keyData, extractable, usages); + result = WTFMove(key); return true; } bool readCryptoKey(JSValue& cryptoKey) { + uint32_t keyFormatVersion; + if (!read(keyFormatVersion) || keyFormatVersion > currentKeyFormatVersion) + return false; + int32_t extractable; if (!read(extractable)) return false; @@ -2004,7 +2133,7 @@ private: if (!read(usagesCount)) return false; - CryptoKeyUsage usages = 0; + CryptoKeyUsageBitmap usages = 0; for (uint32_t i = 0; i < usagesCount; ++i) { CryptoKeyUsageTag usage; if (!read(usage)) @@ -2066,6 +2195,12 @@ private: return toJS(m_exec, jsCast<JSDOMGlobalObject*>(m_globalObject), nativeObj); } + template<class T> + JSValue getJSValue(T& nativeObj) + { + return getJSValue(&nativeObj); + } + JSValue readTerminal() { SerializationTag tag = readTag(); @@ -2132,29 +2267,29 @@ private: unsigned length = 0; if (!read(length)) return JSValue(); - RefPtr<FileList> result = FileList::create(); + Vector<RefPtr<File>> files; for (unsigned i = 0; i < length; i++) { RefPtr<File> file; if (!readFile(file)) return JSValue(); if (m_isDOMGlobalObject) - result->append(file.get()); + files.append(WTFMove(file)); } if (!m_isDOMGlobalObject) return jsNull(); - return getJSValue(result.get()); + return getJSValue(FileList::create(WTFMove(files)).get()); } case ImageDataTag: { - int32_t width; + uint32_t width; if (!read(width)) return JSValue(); - int32_t height; + uint32_t height; if (!read(height)) return JSValue(); uint32_t length; if (!read(length)) return JSValue(); - if (m_end < ((uint8_t*)0) + length || m_ptr > m_end - length) { + if (static_cast<uint32_t>(m_end - m_ptr) < length) { fail(); return JSValue(); } @@ -2162,8 +2297,17 @@ private: m_ptr += length; return jsNull(); } - RefPtr<ImageData> result = ImageData::create(IntSize(width, height)); - memcpy(result->data()->data(), m_ptr, length); + IntSize imageSize(width, height); + RELEASE_ASSERT(!length || (imageSize.area() * 4).unsafeGet() <= length); + RefPtr<ImageData> result = ImageData::create(imageSize); + if (!result) { + fail(); + return JSValue(); + } + if (length) + memcpy(result->data()->data(), m_ptr, length); + else + result->data()->zeroFill(); m_ptr += length; return getJSValue(result.get()); } @@ -2179,7 +2323,7 @@ private: return JSValue(); if (!m_isDOMGlobalObject) return jsNull(); - return getJSValue(Blob::create(URL(URL(), url->string()), type->string(), size).get()); + return getJSValue(Blob::deserialize(URL(URL(), url->string()), type->string(), size, blobFilePathForBlobURL(url->string())).get()); } case StringTag: { CachedStringRef cachedString; @@ -2227,11 +2371,11 @@ private: case MessagePortReferenceTag: { uint32_t index; bool indexSuccessfullyRead = read(index); - if (!indexSuccessfullyRead || !m_messagePorts || index >= m_messagePorts->size()) { + if (!indexSuccessfullyRead || index >= m_messagePorts.size()) { fail(); return JSValue(); } - return getJSValue(m_messagePorts->at(index).get()); + return getJSValue(m_messagePorts[index].get()); } case ArrayBufferTag: { RefPtr<ArrayBuffer> arrayBuffer; @@ -2239,7 +2383,14 @@ private: fail(); return JSValue(); } - JSValue result = getJSValue(arrayBuffer.get()); + Structure* structure = m_globalObject->arrayBufferStructure(arrayBuffer->sharingMode()); + // A crazy RuntimeFlags mismatch could mean that we are not equipped to handle shared + // array buffers while the sender is. In that case, we would see a null structure here. + if (!structure) { + fail(); + return JSValue(); + } + JSValue result = JSArrayBuffer::create(m_exec->vm(), structure, WTFMove(arrayBuffer)); m_gcBuffer.append(result); return result; } @@ -2252,13 +2403,27 @@ private: } if (!m_arrayBuffers[index]) - m_arrayBuffers[index] = ArrayBuffer::create(m_arrayBufferContents->at(index)); + m_arrayBuffers[index] = ArrayBuffer::create(WTFMove(m_arrayBufferContents->at(index))); return getJSValue(m_arrayBuffers[index].get()); } + case SharedArrayBufferTag: { + uint32_t index = UINT_MAX; + bool indexSuccessfullyRead = read(index); + if (!indexSuccessfullyRead || !m_sharedBuffers || index >= m_sharedBuffers->size()) { + fail(); + return JSValue(); + } + + RELEASE_ASSERT(m_sharedBuffers->at(index)); + RefPtr<ArrayBuffer> buffer = ArrayBuffer::create(WTFMove(m_sharedBuffers->at(index))); + JSValue result = getJSValue(buffer.get()); + m_gcBuffer.append(result); + return result; + } case ArrayBufferViewTag: { JSValue arrayBufferView; - if (!readArrayBufferView(arrayBufferView)) { + if (!readArrayBufferView(m_exec->vm(), arrayBufferView)) { fail(); return JSValue(); } @@ -2267,8 +2432,20 @@ private: } #if ENABLE(SUBTLE_CRYPTO) case CryptoKeyTag: { + Vector<uint8_t> wrappedKey; + if (!read(wrappedKey)) { + fail(); + return JSValue(); + } + Vector<uint8_t> serializedKey; + if (!unwrapCryptoKey(m_exec, wrappedKey, serializedKey)) { + fail(); + return JSValue(); + } JSValue cryptoKey; - if (!readCryptoKey(cryptoKey)) { + Vector<RefPtr<MessagePort>> dummyMessagePorts; + CloneDeserializer rawKeyDeserializer(m_exec, m_globalObject, dummyMessagePorts, nullptr, serializedKey); + if (!rawKeyDeserializer.readCryptoKey(cryptoKey)) { fail(); return JSValue(); } @@ -2282,9 +2459,10 @@ private: } } - bool consumeMapDataTerminationIfPossible() + template<SerializationTag Tag> + bool consumeCollectionDataTerminationIfPossible() { - if (readTag() == NonMapPropertiesTag) + if (readTag() == Tag) return true; m_ptr--; return false; @@ -2296,18 +2474,36 @@ private: const uint8_t* m_end; unsigned m_version; Vector<CachedString> m_constantPool; - MessagePortArray* m_messagePorts; + Vector<RefPtr<MessagePort>>& m_messagePorts; ArrayBufferContentsArray* m_arrayBufferContents; - ArrayBufferArray m_arrayBuffers; + Vector<RefPtr<JSC::ArrayBuffer>> m_arrayBuffers; + Vector<String> m_blobURLs; + Vector<String> m_blobFilePaths; + ArrayBufferContentsArray* m_sharedBuffers; + + String blobFilePathForBlobURL(const String& blobURL) + { + size_t i = 0; + for (; i < m_blobURLs.size(); ++i) { + if (m_blobURLs[i] == blobURL) + break; + } + + return i < m_blobURLs.size() ? m_blobFilePaths[i] : String(); + } }; DeserializationResult CloneDeserializer::deserialize() { + VM& vm = m_exec->vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + Vector<uint32_t, 16> indexStack; Vector<Identifier, 16> propertyNameStack; Vector<JSObject*, 32> outputObjectStack; - Vector<JSValue, 4> keyStack; - Vector<MapData*, 4> mapDataStack; + Vector<JSValue, 4> mapKeyStack; + Vector<JSMap*, 4> mapStack; + Vector<JSSet*, 4> setStack; Vector<WalkerState, 16> stateStack; WalkerState state = StateUnknown; JSValue outValue; @@ -2322,6 +2518,8 @@ DeserializationResult CloneDeserializer::deserialize() goto error; } JSArray* outArray = constructEmptyArray(m_exec, 0, m_globalObject, length); + if (UNLIKELY(scope.exception())) + goto error; m_gcBuffer.append(outArray); outputObjectStack.append(outArray); } @@ -2361,7 +2559,7 @@ DeserializationResult CloneDeserializer::deserialize() objectStartState: case ObjectStartState: { if (outputObjectStack.size() > maximumFilterRecursion) - return std::make_pair(JSValue(), StackOverflowError); + return std::make_pair(JSValue(), SerializationReturnCode::StackOverflowError); JSObject* outObject = constructEmptyObject(m_exec, m_globalObject->objectPrototype()); m_gcBuffer.append(outObject); outputObjectStack.append(outObject); @@ -2382,11 +2580,11 @@ DeserializationResult CloneDeserializer::deserialize() } if (JSValue terminal = readTerminal()) { - putProperty(outputObjectStack.last(), Identifier(m_exec, cachedString->string()), terminal); + putProperty(outputObjectStack.last(), Identifier::fromString(m_exec, cachedString->string()), terminal); goto objectStartVisitMember; } stateStack.append(ObjectEndVisitMember); - propertyNameStack.append(Identifier(m_exec, cachedString->string())); + propertyNameStack.append(Identifier::fromString(m_exec, cachedString->string())); goto stateUnknown; } case ObjectEndVisitMember: { @@ -2396,45 +2594,61 @@ DeserializationResult CloneDeserializer::deserialize() } mapObjectStartState: { if (outputObjectStack.size() > maximumFilterRecursion) - return std::make_pair(JSValue(), StackOverflowError); - JSMap* map = JSMap::create(m_exec->vm(), m_globalObject->mapStructure()); + return std::make_pair(JSValue(), SerializationReturnCode::StackOverflowError); + JSMap* map = JSMap::create(m_exec, m_exec->vm(), m_globalObject->mapStructure()); + if (UNLIKELY(scope.exception())) + goto error; m_gcBuffer.append(map); outputObjectStack.append(map); - MapData* mapData = map->mapData(); - mapDataStack.append(mapData); - goto mapDataStartVisitEntry; - } - setObjectStartState: { - if (outputObjectStack.size() > maximumFilterRecursion) - return std::make_pair(JSValue(), StackOverflowError); - JSSet* set = JSSet::create(m_exec->vm(), m_globalObject->setStructure()); - m_gcBuffer.append(set); - outputObjectStack.append(set); - MapData* mapData = set->mapData(); - mapDataStack.append(mapData); + mapStack.append(map); goto mapDataStartVisitEntry; } mapDataStartVisitEntry: case MapDataStartVisitEntry: { - if (consumeMapDataTerminationIfPossible()) { - mapDataStack.removeLast(); + if (consumeCollectionDataTerminationIfPossible<NonMapPropertiesTag>()) { + mapStack.removeLast(); goto objectStartVisitMember; } stateStack.append(MapDataEndVisitKey); goto stateUnknown; } - case MapDataEndVisitKey: { - keyStack.append(outValue); + mapKeyStack.append(outValue); stateStack.append(MapDataEndVisitValue); goto stateUnknown; } - case MapDataEndVisitValue: { - mapDataStack.last()->set(m_exec, keyStack.last(), outValue); - keyStack.removeLast(); + mapStack.last()->set(m_exec, mapKeyStack.last(), outValue); + mapKeyStack.removeLast(); goto mapDataStartVisitEntry; } + + setObjectStartState: { + if (outputObjectStack.size() > maximumFilterRecursion) + return std::make_pair(JSValue(), SerializationReturnCode::StackOverflowError); + JSSet* set = JSSet::create(m_exec, m_exec->vm(), m_globalObject->setStructure()); + if (UNLIKELY(scope.exception())) + goto error; + m_gcBuffer.append(set); + outputObjectStack.append(set); + setStack.append(set); + goto setDataStartVisitEntry; + } + setDataStartVisitEntry: + case SetDataStartVisitEntry: { + if (consumeCollectionDataTerminationIfPossible<NonSetPropertiesTag>()) { + setStack.removeLast(); + goto objectStartVisitMember; + } + stateStack.append(SetDataEndVisitKey); + goto stateUnknown; + } + case SetDataEndVisitKey: { + JSSet* set = setStack.last(); + set->add(m_exec, outValue); + goto setDataStartVisitEntry; + } + stateUnknown: case StateUnknown: if (JSValue terminal = readTerminal()) { @@ -2460,63 +2674,39 @@ DeserializationResult CloneDeserializer::deserialize() } ASSERT(outValue); ASSERT(!m_failed); - return std::make_pair(outValue, SuccessfullyCompleted); + return std::make_pair(outValue, SerializationReturnCode::SuccessfullyCompleted); error: fail(); - return std::make_pair(JSValue(), ValidationError); -} - -void SerializedScriptValue::addBlobURL(const String& string) -{ - m_blobURLs.append(Vector<uint16_t>()); - m_blobURLs.last().reserveCapacity(string.length()); - for (size_t i = 0; i < string.length(); i++) - m_blobURLs.last().append(string.characterAt(i)); - m_blobURLs.last().resize(m_blobURLs.last().size()); + return std::make_pair(JSValue(), SerializationReturnCode::ValidationError); } SerializedScriptValue::~SerializedScriptValue() { } -SerializedScriptValue::SerializedScriptValue(const Vector<uint8_t>& buffer) - : m_data(buffer) +SerializedScriptValue::SerializedScriptValue(Vector<uint8_t>&& buffer) + : m_data(WTFMove(buffer)) { } -SerializedScriptValue::SerializedScriptValue(Vector<uint8_t>& buffer) +SerializedScriptValue::SerializedScriptValue(Vector<uint8_t>&& buffer, const Vector<String>& blobURLs, std::unique_ptr<ArrayBufferContentsArray> arrayBufferContentsArray, std::unique_ptr<ArrayBufferContentsArray> sharedBufferContentsArray) + : m_data(WTFMove(buffer)) + , m_arrayBufferContentsArray(WTFMove(arrayBufferContentsArray)) + , m_sharedBufferContentsArray(WTFMove(sharedBufferContentsArray)) { - m_data.swap(buffer); + // Since this SerializedScriptValue is meant to be passed between threads, its String data members + // need to be isolatedCopies so we don't run into thread safety issues for the StringImpls. + m_blobURLs.reserveInitialCapacity(blobURLs.size()); + for (auto& url : blobURLs) + m_blobURLs.uncheckedAppend(url.isolatedCopy()); } -SerializedScriptValue::SerializedScriptValue(Vector<uint8_t>& buffer, Vector<String>& blobURLs) +static ExceptionOr<std::unique_ptr<ArrayBufferContentsArray>> transferArrayBuffers(VM& vm, const Vector<RefPtr<JSC::ArrayBuffer>>& arrayBuffers) { - m_data.swap(buffer); - for (auto& string : blobURLs) - addBlobURL(string); -} + if (arrayBuffers.isEmpty()) + return nullptr; -SerializedScriptValue::SerializedScriptValue(Vector<uint8_t>& buffer, Vector<String>& blobURLs, PassOwnPtr<ArrayBufferContentsArray> arrayBufferContentsArray) - : m_arrayBufferContentsArray(arrayBufferContentsArray) -{ - m_data.swap(buffer); - for (auto& string : blobURLs) - addBlobURL(string); -} - -PassOwnPtr<SerializedScriptValue::ArrayBufferContentsArray> SerializedScriptValue::transferArrayBuffers( - ExecState* exec, ArrayBufferArray& arrayBuffers, SerializationReturnCode& code) -{ - for (size_t i = 0; i < arrayBuffers.size(); i++) { - if (arrayBuffers[i]->isNeutered()) { - code = ValidationError; - return nullptr; - } - } - - OwnPtr<ArrayBufferContentsArray> contents = adoptPtr(new ArrayBufferContentsArray(arrayBuffers.size())); - Vector<Ref<DOMWrapperWorld>> worlds; - static_cast<WebCoreJSClientData*>(exec->vm().clientData)->getAllWorlds(worlds); + auto contents = std::make_unique<ArrayBufferContentsArray>(arrayBuffers.size()); HashSet<JSC::ArrayBuffer*> visited; for (size_t arrayBufferIndex = 0; arrayBufferIndex < arrayBuffers.size(); arrayBufferIndex++) { @@ -2524,207 +2714,255 @@ PassOwnPtr<SerializedScriptValue::ArrayBufferContentsArray> SerializedScriptValu continue; visited.add(arrayBuffers[arrayBufferIndex].get()); - bool result = arrayBuffers[arrayBufferIndex]->transfer(contents->at(arrayBufferIndex)); - if (!result) { - code = ValidationError; - return nullptr; - } + bool result = arrayBuffers[arrayBufferIndex]->transferTo(vm, contents->at(arrayBufferIndex)); + if (!result) + return Exception { TypeError }; + } + + return WTFMove(contents); +} + +static void maybeThrowExceptionIfSerializationFailed(ExecState& state, SerializationReturnCode code) +{ + auto& vm = state.vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + + switch (code) { + case SerializationReturnCode::SuccessfullyCompleted: + break; + case SerializationReturnCode::StackOverflowError: + throwException(&state, scope, createStackOverflowError(&state)); + break; + case SerializationReturnCode::ValidationError: + throwTypeError(&state, scope, ASCIILiteral("Unable to deserialize data.")); + break; + case SerializationReturnCode::DataCloneError: + throwDataCloneError(state, scope); + break; + case SerializationReturnCode::ExistingExceptionError: + case SerializationReturnCode::UnspecifiedError: + break; + case SerializationReturnCode::InterruptedExecutionError: + ASSERT_NOT_REACHED(); } - return contents.release(); } +static Exception exceptionForSerializationFailure(SerializationReturnCode code) +{ + ASSERT(code != SerializationReturnCode::SuccessfullyCompleted); + + switch (code) { + case SerializationReturnCode::StackOverflowError: + return Exception { StackOverflowError }; + case SerializationReturnCode::ValidationError: + return Exception { TypeError }; + case SerializationReturnCode::DataCloneError: + return Exception { DATA_CLONE_ERR }; + case SerializationReturnCode::ExistingExceptionError: + return Exception { ExistingExceptionError }; + case SerializationReturnCode::UnspecifiedError: + return Exception { TypeError }; + case SerializationReturnCode::SuccessfullyCompleted: + case SerializationReturnCode::InterruptedExecutionError: + ASSERT_NOT_REACHED(); + return Exception { TypeError }; + } + ASSERT_NOT_REACHED(); + return Exception { TypeError }; +} -PassRefPtr<SerializedScriptValue> SerializedScriptValue::create(ExecState* exec, JSValue value, - MessagePortArray* messagePorts, ArrayBufferArray* arrayBuffers, - SerializationErrorMode throwExceptions) +RefPtr<SerializedScriptValue> SerializedScriptValue::create(ExecState& exec, JSValue value, SerializationErrorMode throwExceptions) { Vector<uint8_t> buffer; Vector<String> blobURLs; - SerializationReturnCode code = CloneSerializer::serialize(exec, value, messagePorts, arrayBuffers, blobURLs, buffer); - - OwnPtr<ArrayBufferContentsArray> arrayBufferContentsArray; + Vector<RefPtr<MessagePort>> dummyMessagePorts; + Vector<RefPtr<JSC::ArrayBuffer>> dummyArrayBuffers; + ArrayBufferContentsArray dummySharedBuffers; + auto code = CloneSerializer::serialize(&exec, value, dummyMessagePorts, dummyArrayBuffers, blobURLs, buffer, SerializationContext::Default, dummySharedBuffers); - if (arrayBuffers && serializationDidCompleteSuccessfully(code)) - arrayBufferContentsArray = transferArrayBuffers(exec, *arrayBuffers, code); - - if (throwExceptions == Throwing) + if (throwExceptions == SerializationErrorMode::Throwing) maybeThrowExceptionIfSerializationFailed(exec, code); - if (!serializationDidCompleteSuccessfully(code)) - return 0; + if (code != SerializationReturnCode::SuccessfullyCompleted) + return nullptr; - return adoptRef(new SerializedScriptValue(buffer, blobURLs, arrayBufferContentsArray.release())); + return adoptRef(*new SerializedScriptValue(WTFMove(buffer), blobURLs, nullptr, nullptr)); } -PassRefPtr<SerializedScriptValue> SerializedScriptValue::create() +ExceptionOr<Ref<SerializedScriptValue>> SerializedScriptValue::create(ExecState& state, JSValue value, Vector<JSC::Strong<JSC::JSObject>>&& transferList, Vector<RefPtr<MessagePort>>& messagePorts, SerializationContext context) { - Vector<uint8_t> buffer; - return adoptRef(new SerializedScriptValue(buffer)); -} + VM& vm = state.vm(); + Vector<RefPtr<JSC::ArrayBuffer>> arrayBuffers; + for (auto& transferable : transferList) { + if (auto arrayBuffer = toPossiblySharedArrayBuffer(vm, transferable.get())) { + if (arrayBuffer->isNeutered()) + return Exception { DATA_CLONE_ERR }; + if (arrayBuffer->isShared()) + return Exception { TypeError }; + arrayBuffers.append(WTFMove(arrayBuffer)); + continue; + } + if (auto port = JSMessagePort::toWrapped(vm, transferable.get())) { + // FIXME: This should check if the port is detached as per https://html.spec.whatwg.org/multipage/infrastructure.html#istransferable. + messagePorts.append(WTFMove(port)); + continue; + } + + return Exception { DATA_CLONE_ERR }; + } -PassRefPtr<SerializedScriptValue> SerializedScriptValue::create(const String& string) -{ Vector<uint8_t> buffer; - if (!CloneSerializer::serialize(string, buffer)) - return 0; - return adoptRef(new SerializedScriptValue(buffer)); -} + Vector<String> blobURLs; + std::unique_ptr<ArrayBufferContentsArray> sharedBuffers = std::make_unique<ArrayBufferContentsArray>(); + auto code = CloneSerializer::serialize(&state, value, messagePorts, arrayBuffers, blobURLs, buffer, context, *sharedBuffers); -#if ENABLE(INDEXED_DATABASE) -PassRefPtr<SerializedScriptValue> SerializedScriptValue::create(JSC::ExecState* exec, JSC::JSValue value) -{ - return SerializedScriptValue::create(exec, value, 0, 0); -} + if (code != SerializationReturnCode::SuccessfullyCompleted) + return exceptionForSerializationFailure(code); -PassRefPtr<SerializedScriptValue> SerializedScriptValue::numberValue(double value) -{ - Vector<uint8_t> buffer; - CloneSerializer::serializeNumber(value, buffer); - return adoptRef(new SerializedScriptValue(buffer)); + auto arrayBufferContentsArray = transferArrayBuffers(vm, arrayBuffers); + if (arrayBufferContentsArray.hasException()) + return arrayBufferContentsArray.releaseException(); + + return adoptRef(*new SerializedScriptValue(WTFMove(buffer), blobURLs, arrayBufferContentsArray.releaseReturnValue(), context == SerializationContext::WorkerPostMessage ? WTFMove(sharedBuffers) : nullptr)); } -JSValue SerializedScriptValue::deserialize(JSC::ExecState* exec, JSC::JSGlobalObject* globalObject) +RefPtr<SerializedScriptValue> SerializedScriptValue::create(StringView string) { - return deserialize(exec, globalObject, 0); + Vector<uint8_t> buffer; + if (!CloneSerializer::serialize(string, buffer)) + return nullptr; + return adoptRef(*new SerializedScriptValue(WTFMove(buffer))); } -#endif -PassRefPtr<SerializedScriptValue> SerializedScriptValue::create(JSContextRef originContext, JSValueRef apiValue, - MessagePortArray* messagePorts, ArrayBufferArray* arrayBuffers, - JSValueRef* exception) +RefPtr<SerializedScriptValue> SerializedScriptValue::create(JSContextRef originContext, JSValueRef apiValue, JSValueRef* exception) { ExecState* exec = toJS(originContext); - APIEntryShim entryShim(exec); + VM& vm = exec->vm(); + JSLockHolder locker(vm); + auto scope = DECLARE_CATCH_SCOPE(vm); + JSValue value = toJS(exec, apiValue); - RefPtr<SerializedScriptValue> serializedValue = SerializedScriptValue::create(exec, value, messagePorts, arrayBuffers); - if (exec->hadException()) { + RefPtr<SerializedScriptValue> serializedValue = SerializedScriptValue::create(*exec, value); + if (UNLIKELY(scope.exception())) { if (exception) - *exception = toRef(exec, exec->exception()); - exec->clearException(); - return 0; + *exception = toRef(exec, scope.exception()->value()); + scope.clearException(); + return nullptr; } ASSERT(serializedValue); - return serializedValue.release(); + return serializedValue; } -PassRefPtr<SerializedScriptValue> SerializedScriptValue::create(JSContextRef originContext, JSValueRef apiValue, - JSValueRef* exception) +String SerializedScriptValue::toString() { - return create(originContext, apiValue, 0, 0, exception); + return CloneDeserializer::deserializeString(m_data); } -String SerializedScriptValue::toString() +JSValue SerializedScriptValue::deserialize(ExecState& exec, JSGlobalObject* globalObject, SerializationErrorMode throwExceptions) { - return CloneDeserializer::deserializeString(m_data); + Vector<RefPtr<MessagePort>> dummyMessagePorts; + return deserialize(exec, globalObject, dummyMessagePorts, throwExceptions); } -JSValue SerializedScriptValue::deserialize(ExecState* exec, JSGlobalObject* globalObject, - MessagePortArray* messagePorts, SerializationErrorMode throwExceptions) +JSValue SerializedScriptValue::deserialize(ExecState& exec, JSGlobalObject* globalObject, Vector<RefPtr<MessagePort>>& messagePorts, SerializationErrorMode throwExceptions) { - DeserializationResult result = CloneDeserializer::deserialize(exec, globalObject, messagePorts, - m_arrayBufferContentsArray.get(), m_data); - if (throwExceptions == Throwing) - maybeThrowExceptionIfSerializationFailed(exec, result.second); - return result.first; + Vector<String> dummyBlobs; + Vector<String> dummyPaths; + return deserialize(exec, globalObject, messagePorts, dummyBlobs, dummyPaths, throwExceptions); } -#if ENABLE(INSPECTOR) -Deprecated::ScriptValue SerializedScriptValue::deserializeForInspector(JSC::ExecState* scriptState) +JSValue SerializedScriptValue::deserialize(ExecState& exec, JSGlobalObject* globalObject, Vector<RefPtr<MessagePort>>& messagePorts, const Vector<String>& blobURLs, const Vector<String>& blobFilePaths, SerializationErrorMode throwExceptions) { - JSValue value = deserialize(scriptState, scriptState->lexicalGlobalObject(), 0); - return Deprecated::ScriptValue(scriptState->vm(), value); + DeserializationResult result = CloneDeserializer::deserialize(&exec, globalObject, messagePorts, m_arrayBufferContentsArray.get(), m_data, blobURLs, blobFilePaths, m_sharedBufferContentsArray.get()); + if (throwExceptions == SerializationErrorMode::Throwing) + maybeThrowExceptionIfSerializationFailed(exec, result.second); + return result.first ? result.first : jsNull(); } -#endif -JSValueRef SerializedScriptValue::deserialize(JSContextRef destinationContext, JSValueRef* exception, MessagePortArray* messagePorts) +JSValueRef SerializedScriptValue::deserialize(JSContextRef destinationContext, JSValueRef* exception) { ExecState* exec = toJS(destinationContext); - APIEntryShim entryShim(exec); - JSValue value = deserialize(exec, exec->lexicalGlobalObject(), messagePorts); - if (exec->hadException()) { + VM& vm = exec->vm(); + JSLockHolder locker(vm); + auto scope = DECLARE_CATCH_SCOPE(vm); + + JSValue value = deserialize(*exec, exec->lexicalGlobalObject()); + if (UNLIKELY(scope.exception())) { if (exception) - *exception = toRef(exec, exec->exception()); - exec->clearException(); - return 0; + *exception = toRef(exec, scope.exception()->value()); + scope.clearException(); + return nullptr; } ASSERT(value); return toRef(exec, value); } - -JSValueRef SerializedScriptValue::deserialize(JSContextRef destinationContext, JSValueRef* exception) +Ref<SerializedScriptValue> SerializedScriptValue::nullValue() { - return deserialize(destinationContext, exception, 0); + return adoptRef(*new SerializedScriptValue(Vector<uint8_t>())); } -PassRefPtr<SerializedScriptValue> SerializedScriptValue::nullValue() +uint32_t SerializedScriptValue::wireFormatVersion() { - return SerializedScriptValue::create(); + return CurrentVersion; } -PassRefPtr<SerializedScriptValue> SerializedScriptValue::undefinedValue() +#if ENABLE(INDEXED_DATABASE) +Vector<String> SerializedScriptValue::blobURLsIsolatedCopy() const { - Vector<uint8_t> buffer; - CloneSerializer::serializeUndefined(buffer); - return adoptRef(new SerializedScriptValue(buffer)); -} + Vector<String> result; + result.reserveInitialCapacity(m_blobURLs.size()); + for (auto& url : m_blobURLs) + result.uncheckedAppend(url.isolatedCopy()); -PassRefPtr<SerializedScriptValue> SerializedScriptValue::booleanValue(bool value) -{ - Vector<uint8_t> buffer; - CloneSerializer::serializeBoolean(value, buffer); - return adoptRef(new SerializedScriptValue(buffer)); + return result; } -PassRefPtr<SerializedScriptValue> SerializedScriptValue::serialize(const Deprecated::ScriptValue& value, JSC::ExecState* scriptState, SerializationErrorMode throwExceptions) +void SerializedScriptValue::writeBlobsToDiskForIndexedDB(WTF::Function<void (const IDBValue&)>&& completionHandler) { - return SerializedScriptValue::create(scriptState, value.jsValue(), nullptr, nullptr, throwExceptions); -} + ASSERT(isMainThread()); + ASSERT(hasBlobURLs()); -PassRefPtr<SerializedScriptValue> SerializedScriptValue::serialize(const Deprecated::ScriptValue& value, JSC::ExecState* scriptState, MessagePortArray* messagePorts, ArrayBufferArray* arrayBuffers, bool& didThrow) -{ - RefPtr<SerializedScriptValue> serializedValue = SerializedScriptValue::create(scriptState, value.jsValue(), messagePorts, arrayBuffers); - didThrow = scriptState->hadException(); - return serializedValue.release(); -} + RefPtr<SerializedScriptValue> protectedThis(this); + blobRegistry().writeBlobsToTemporaryFiles(m_blobURLs, [completionHandler = WTFMove(completionHandler), this, protectedThis = WTFMove(protectedThis)](auto& blobFilePaths) { + ASSERT(isMainThread()); -Deprecated::ScriptValue SerializedScriptValue::deserialize(JSC::ExecState* scriptState, SerializedScriptValue* value, SerializationErrorMode throwExceptions) -{ - return Deprecated::ScriptValue(scriptState->vm(), value->deserialize(scriptState, scriptState->lexicalGlobalObject(), 0, throwExceptions)); -} + if (blobFilePaths.isEmpty()) { + // We should have successfully written blobs to temporary files. + // If we failed, then we can't successfully store this record. + completionHandler({ }); + return; + } -void SerializedScriptValue::maybeThrowExceptionIfSerializationFailed(ExecState* exec, SerializationReturnCode code) -{ - if (code == SuccessfullyCompleted) - return; - - switch (code) { - case StackOverflowError: - exec->vm().throwException(exec, createStackOverflowError(exec)); - break; - case ValidationError: - exec->vm().throwException(exec, createTypeError(exec, "Unable to deserialize data.")); - break; - case DataCloneError: - setDOMException(exec, DATA_CLONE_ERR); - break; - case ExistingExceptionError: - break; - case UnspecifiedError: - break; - default: - ASSERT_NOT_REACHED(); - } + ASSERT(m_blobURLs.size() == blobFilePaths.size()); + + completionHandler({ *this, m_blobURLs, blobFilePaths }); + }); } -bool SerializedScriptValue::serializationDidCompleteSuccessfully(SerializationReturnCode code) +IDBValue SerializedScriptValue::writeBlobsToDiskForIndexedDBSynchronously() { - return (code == SuccessfullyCompleted); -} + ASSERT(!isMainThread()); -uint32_t SerializedScriptValue::wireFormatVersion() -{ - return CurrentVersion; -} + IDBValue value; + Lock lock; + Condition condition; + lock.lock(); + + RunLoop::main().dispatch([this, conditionPtr = &condition, valuePtr = &value] { + writeBlobsToDiskForIndexedDB([conditionPtr, valuePtr](const IDBValue& result) { + ASSERT(isMainThread()); + valuePtr->setAsIsolatedCopy(result); + + conditionPtr->notifyAll(); + }); + }); + condition.wait(lock); + + return value; } + +#endif // ENABLE(INDEXED_DATABASE) + +} // namespace WebCore diff --git a/Source/WebCore/bindings/js/SerializedScriptValue.h b/Source/WebCore/bindings/js/SerializedScriptValue.h index 37b31729a..1729011c4 100644 --- a/Source/WebCore/bindings/js/SerializedScriptValue.h +++ b/Source/WebCore/bindings/js/SerializedScriptValue.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2009, 2013 Apple Inc. All rights reserved. + * Copyright (C) 2009, 2013, 2016 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -10,10 +10,10 @@ * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * - * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR @@ -24,16 +24,14 @@ * */ -#ifndef SerializedScriptValue_h -#define SerializedScriptValue_h +#pragma once -#include "ScriptState.h" -#include <bindings/ScriptValue.h> +#include "ExceptionOr.h" #include <heap/Strong.h> #include <runtime/ArrayBuffer.h> #include <runtime/JSCJSValue.h> #include <wtf/Forward.h> -#include <wtf/PassRefPtr.h> +#include <wtf/Function.h> #include <wtf/RefCounted.h> #include <wtf/text/WTFString.h> @@ -42,96 +40,67 @@ typedef const struct OpaqueJSValue* JSValueRef; namespace WebCore { +class IDBValue; class MessagePort; -typedef Vector<RefPtr<MessagePort>, 1> MessagePortArray; -typedef Vector<RefPtr<JSC::ArrayBuffer>, 1> ArrayBufferArray; - -enum SerializationReturnCode { - SuccessfullyCompleted, - StackOverflowError, - InterruptedExecutionError, - ValidationError, - ExistingExceptionError, - DataCloneError, - UnspecifiedError -}; - -enum SerializationErrorMode { NonThrowing, Throwing }; - class SharedBuffer; +enum class SerializationReturnCode; -class SerializedScriptValue : -#if ENABLE(INDEXED_DATABASE) - public ThreadSafeRefCounted<SerializedScriptValue> { -#else - public RefCounted<SerializedScriptValue> { -#endif +enum class SerializationErrorMode { NonThrowing, Throwing }; +enum class SerializationContext { Default, WorkerPostMessage }; + +using ArrayBufferContentsArray = Vector<JSC::ArrayBufferContents>; + +class SerializedScriptValue : public ThreadSafeRefCounted<SerializedScriptValue> { public: - static PassRefPtr<SerializedScriptValue> create(JSC::ExecState*, JSC::JSValue, MessagePortArray*, ArrayBufferArray*, SerializationErrorMode = Throwing); - static PassRefPtr<SerializedScriptValue> create(JSContextRef, JSValueRef, MessagePortArray*, ArrayBufferArray*, JSValueRef* exception); - static PassRefPtr<SerializedScriptValue> create(JSContextRef, JSValueRef, JSValueRef* exception); + WEBCORE_EXPORT static RefPtr<SerializedScriptValue> create(JSC::ExecState&, JSC::JSValue, SerializationErrorMode = SerializationErrorMode::Throwing); + + WEBCORE_EXPORT static ExceptionOr<Ref<SerializedScriptValue>> create(JSC::ExecState&, JSC::JSValue, Vector<JSC::Strong<JSC::JSObject>>&& transfer, Vector<RefPtr<MessagePort>>&, SerializationContext = SerializationContext::Default); - static PassRefPtr<SerializedScriptValue> create(const String&); - static PassRefPtr<SerializedScriptValue> adopt(Vector<uint8_t>& buffer) + WEBCORE_EXPORT static RefPtr<SerializedScriptValue> create(StringView); + static Ref<SerializedScriptValue> adopt(Vector<uint8_t>&& buffer) { - return adoptRef(new SerializedScriptValue(buffer)); + return adoptRef(*new SerializedScriptValue(WTFMove(buffer))); } - static PassRefPtr<SerializedScriptValue> create(); - static PassRefPtr<SerializedScriptValue> nullValue(); - static PassRefPtr<SerializedScriptValue> undefinedValue(); - static PassRefPtr<SerializedScriptValue> booleanValue(bool value); + static Ref<SerializedScriptValue> nullValue(); - static PassRefPtr<SerializedScriptValue> serialize(const Deprecated::ScriptValue&, JSC::ExecState*, SerializationErrorMode = Throwing); - static PassRefPtr<SerializedScriptValue> serialize(const Deprecated::ScriptValue&, JSC::ExecState*, MessagePortArray*, ArrayBufferArray*, bool&); - static Deprecated::ScriptValue deserialize(JSC::ExecState*, SerializedScriptValue*, SerializationErrorMode = Throwing); + WEBCORE_EXPORT JSC::JSValue deserialize(JSC::ExecState&, JSC::JSGlobalObject*, SerializationErrorMode = SerializationErrorMode::Throwing); + WEBCORE_EXPORT JSC::JSValue deserialize(JSC::ExecState&, JSC::JSGlobalObject*, Vector<RefPtr<MessagePort>>&, SerializationErrorMode = SerializationErrorMode::Throwing); + JSC::JSValue deserialize(JSC::ExecState&, JSC::JSGlobalObject*, Vector<RefPtr<MessagePort>>&, const Vector<String>& blobURLs, const Vector<String>& blobFilePaths, SerializationErrorMode = SerializationErrorMode::Throwing); static uint32_t wireFormatVersion(); String toString(); - - JSC::JSValue deserialize(JSC::ExecState*, JSC::JSGlobalObject*, MessagePortArray*, SerializationErrorMode = Throwing); - JSValueRef deserialize(JSContextRef, JSValueRef* exception, MessagePortArray*); - JSValueRef deserialize(JSContextRef, JSValueRef* exception); -#if ENABLE(INSPECTOR) - Deprecated::ScriptValue deserializeForInspector(JSC::ExecState*); -#endif + // API implementation helpers. These don't expose special behavior for ArrayBuffers or MessagePorts. + WEBCORE_EXPORT static RefPtr<SerializedScriptValue> create(JSContextRef, JSValueRef, JSValueRef* exception); + WEBCORE_EXPORT JSValueRef deserialize(JSContextRef, JSValueRef* exception); const Vector<uint8_t>& data() const { return m_data; } bool hasBlobURLs() const { return !m_blobURLs.isEmpty(); } - void blobURLs(Vector<String>&) const; #if ENABLE(INDEXED_DATABASE) - static PassRefPtr<SerializedScriptValue> create(JSC::ExecState*, JSC::JSValue); - static PassRefPtr<SerializedScriptValue> numberValue(double value); - JSC::JSValue deserialize(JSC::ExecState*, JSC::JSGlobalObject*); -#endif + Vector<String> blobURLsIsolatedCopy() const; + void writeBlobsToDiskForIndexedDB(WTF::Function<void (const IDBValue&)>&& completionHandler); + IDBValue writeBlobsToDiskForIndexedDBSynchronously(); +#endif // ENABLE(INDEXED_DATABASE) - static PassRefPtr<SerializedScriptValue> createFromWireBytes(const Vector<uint8_t>& data) + static Ref<SerializedScriptValue> createFromWireBytes(Vector<uint8_t>&& data) { - return adoptRef(new SerializedScriptValue(data)); + return adoptRef(*new SerializedScriptValue(WTFMove(data))); } const Vector<uint8_t>& toWireBytes() const { return m_data; } - ~SerializedScriptValue(); + WEBCORE_EXPORT ~SerializedScriptValue(); private: - typedef Vector<JSC::ArrayBufferContents> ArrayBufferContentsArray; - static void maybeThrowExceptionIfSerializationFailed(JSC::ExecState*, SerializationReturnCode); - static bool serializationDidCompleteSuccessfully(SerializationReturnCode); - static PassOwnPtr<ArrayBufferContentsArray> transferArrayBuffers(JSC::ExecState*, ArrayBufferArray&, SerializationReturnCode&); - void addBlobURL(const String&); - - SerializedScriptValue(const Vector<unsigned char>&); - SerializedScriptValue(Vector<unsigned char>&); - SerializedScriptValue(Vector<unsigned char>&, Vector<String>& blobURLs); - SerializedScriptValue(Vector<unsigned char>&, Vector<String>& blobURLs, PassOwnPtr<ArrayBufferContentsArray>); + WEBCORE_EXPORT SerializedScriptValue(Vector<unsigned char>&&); + SerializedScriptValue(Vector<unsigned char>&&, const Vector<String>& blobURLs, std::unique_ptr<ArrayBufferContentsArray>, std::unique_ptr<ArrayBufferContentsArray> sharedBuffers); + Vector<unsigned char> m_data; - OwnPtr<ArrayBufferContentsArray> m_arrayBufferContentsArray; - Vector<Vector<uint16_t>> m_blobURLs; + std::unique_ptr<ArrayBufferContentsArray> m_arrayBufferContentsArray; + std::unique_ptr<ArrayBufferContentsArray> m_sharedBufferContentsArray; + Vector<String> m_blobURLs; }; } - -#endif // SerializedScriptValue_h diff --git a/Source/WebCore/bindings/js/StructuredClone.cpp b/Source/WebCore/bindings/js/StructuredClone.cpp new file mode 100644 index 000000000..4869ac0df --- /dev/null +++ b/Source/WebCore/bindings/js/StructuredClone.cpp @@ -0,0 +1,97 @@ +/* + * Copyright (C) 2016 Apple Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "config.h" +#include "StructuredClone.h" + +#include "JSDOMBinding.h" +#include "JSDOMExceptionHandling.h" +#include <runtime/JSTypedArrays.h> + +using namespace JSC; + +namespace WebCore { + +EncodedJSValue JSC_HOST_CALL structuredCloneArrayBuffer(ExecState* state) +{ + ASSERT(state); + ASSERT(state->argumentCount()); + ASSERT(state->lexicalGlobalObject()); + + VM& vm = state->vm(); + auto* buffer = toUnsharedArrayBuffer(vm, state->uncheckedArgument(0)); + if (!buffer) { + auto scope = DECLARE_THROW_SCOPE(vm); + throwDataCloneError(*state, scope); + return { }; + } + return JSValue::encode(JSArrayBuffer::create(state->vm(), state->lexicalGlobalObject()->arrayBufferStructure(ArrayBufferSharingMode::Default), ArrayBuffer::tryCreate(buffer->data(), buffer->byteLength()))); +} + +EncodedJSValue JSC_HOST_CALL structuredCloneArrayBufferView(ExecState* state) +{ + ASSERT(state); + ASSERT(state->argumentCount()); + + JSValue value = state->uncheckedArgument(0); + VM& vm = state->vm(); + auto* bufferView = jsDynamicDowncast<JSArrayBufferView*>(vm, value); + ASSERT(bufferView); + + auto* buffer = bufferView->unsharedBuffer(); + if (!buffer) { + auto scope = DECLARE_THROW_SCOPE(vm); + throwDataCloneError(*state, scope); + return { }; + } + auto bufferClone = ArrayBuffer::tryCreate(buffer->data(), buffer->byteLength()); + + if (jsDynamicDowncast<JSInt8Array*>(vm, value)) + return JSValue::encode(JSInt8Array::create(state, bufferView->structure(), WTFMove(bufferClone), bufferView->byteOffset(), bufferView->length())); + if (jsDynamicDowncast<JSInt16Array*>(vm, value)) + return JSValue::encode(JSInt16Array::create(state, bufferView->structure(), WTFMove(bufferClone), bufferView->byteOffset(), bufferView->length())); + if (jsDynamicDowncast<JSInt32Array*>(vm, value)) + return JSValue::encode(JSInt32Array::create(state, bufferView->structure(), WTFMove(bufferClone), bufferView->byteOffset(), bufferView->length())); + if (jsDynamicDowncast<JSUint8Array*>(vm, value)) + return JSValue::encode(JSUint8Array::create(state, bufferView->structure(), WTFMove(bufferClone), bufferView->byteOffset(), bufferView->length())); + if (jsDynamicDowncast<JSUint8ClampedArray*>(vm, value)) + return JSValue::encode(JSUint8ClampedArray::create(state, bufferView->structure(), WTFMove(bufferClone), bufferView->byteOffset(), bufferView->length())); + if (jsDynamicDowncast<JSUint16Array*>(vm, value)) + return JSValue::encode(JSUint16Array::create(state, bufferView->structure(), WTFMove(bufferClone), bufferView->byteOffset(), bufferView->length())); + if (jsDynamicDowncast<JSUint32Array*>(vm, value)) + return JSValue::encode(JSUint32Array::create(state, bufferView->structure(), WTFMove(bufferClone), bufferView->byteOffset(), bufferView->length())); + if (jsDynamicDowncast<JSFloat32Array*>(vm, value)) + return JSValue::encode(JSFloat32Array::create(state, bufferView->structure(), WTFMove(bufferClone), bufferView->byteOffset(), bufferView->length())); + if (jsDynamicDowncast<JSFloat64Array*>(vm, value)) + return JSValue::encode(JSFloat64Array::create(state, bufferView->structure(), WTFMove(bufferClone), bufferView->byteOffset(), bufferView->length())); + if (jsDynamicDowncast<JSDataView*>(vm, value)) + return JSValue::encode(JSDataView::create(state, bufferView->structure(), WTFMove(bufferClone), bufferView->byteOffset(), bufferView->length())); + + ASSERT_NOT_REACHED(); + return JSValue::encode(jsUndefined()); +} + +} // namespace WebCore diff --git a/Source/WebCore/bindings/js/JSHTMLInputElementCustom.h b/Source/WebCore/bindings/js/StructuredClone.h index f5222d24c..ea6d01b69 100644 --- a/Source/WebCore/bindings/js/JSHTMLInputElementCustom.h +++ b/Source/WebCore/bindings/js/StructuredClone.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008 Apple Inc. All rights reserved. + * Copyright (C) 2016 Apple Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -20,12 +20,18 @@ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * */ -#ifndef JSHTMLInputElementCustom_h -#define JSHTMLInputElementCustom_h +namespace JSC { +using EncodedJSValue = int64_t; +class ExecState; +} + +namespace WebCore { -#include "JSHTMLInputElement.h" +JSC::EncodedJSValue JSC_HOST_CALL structuredCloneArrayBuffer(JSC::ExecState*); +JSC::EncodedJSValue JSC_HOST_CALL structuredCloneArrayBufferView(JSC::ExecState*); -#endif // JSHTMLInputElementCustom_h +} // namespace WebCore diff --git a/Source/WebCore/bindings/js/WebCoreBuiltinNames.h b/Source/WebCore/bindings/js/WebCoreBuiltinNames.h new file mode 100644 index 000000000..8ab00bc07 --- /dev/null +++ b/Source/WebCore/bindings/js/WebCoreBuiltinNames.h @@ -0,0 +1,138 @@ +/* + * Copyright (c) 2015, Canon Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Canon Inc. nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * THIS SOFTWARE IS PROVIDED BY CANON INC. AND ITS CONTRIBUTORS "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL CANON INC. AND ITS CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +#include <builtins/BuiltinUtils.h> + +namespace WebCore { + +#define WEBCORE_COMMON_PRIVATE_IDENTIFIERS_EACH_PROPERTY_NAME(macro)\ + macro(addTrack) \ + macro(appendFromJS) \ + macro(autoAllocateChunkSize) \ + macro(body) \ + macro(cancel) \ + macro(cloneForJS) \ + macro(closeRequested) \ + macro(closedPromiseCapability) \ + macro(consume) \ + macro(consumeChunk) \ + macro(controlledReadableStream) \ + macro(controller) \ + macro(createReadableStreamSource) \ + macro(disturbed) \ + macro(failureKind) \ + macro(fetchRequest) \ + macro(fillFromJS) \ + macro(finishConsumingStream) \ + macro(getUserMedia) \ + macro(getRemoteStreams) \ + macro(getSenders) \ + macro(getTracks) \ + macro(initializeWith) \ + macro(isDisturbed) \ + macro(isLoading) \ + macro(localStreams) \ + macro(makeThisTypeError) \ + macro(makeGetterTypeError) \ + macro(mediaStreamTrackConstraints) \ + macro(operations) \ + macro(ownerReadableStream) \ + macro(pendingPullIntos) \ + macro(privateGetStats) \ + macro(pull) \ + macro(pulling) \ + macro(pullAgain) \ + macro(queue) \ + macro(queuedAddIceCandidate) \ + macro(queuedCreateAnswer) \ + macro(queuedCreateOffer) \ + macro(queuedSetLocalDescription) \ + macro(queuedSetRemoteDescription) \ + macro(reader) \ + macro(readIntoRequests) \ + macro(readRequests) \ + macro(readableStreamController) \ + macro(readyPromiseCapability) \ + macro(removeTrack) \ + macro(responseCacheIsValid) \ + macro(retrieveResponse) \ + macro(response) \ + macro(setBody) \ + macro(setStatus) \ + macro(state) \ + macro(startConsumingStream) \ + macro(started) \ + macro(startedPromise) \ + macro(storedError) \ + macro(strategy) \ + macro(strategyHWM) \ + macro(streamClosed) \ + macro(streamClosing) \ + macro(streamErrored) \ + macro(streamReadable) \ + macro(streamWaiting) \ + macro(streamWritable) \ + macro(structuredCloneArrayBuffer) \ + macro(structuredCloneArrayBufferView) \ + macro(totalQueuedBytes) \ + macro(underlyingByteSource) \ + macro(underlyingSink) \ + macro(underlyingSource) \ + macro(writing) \ + macro(Headers) \ + macro(MediaStream) \ + macro(MediaStreamTrack) \ + macro(ReadableByteStreamController) \ + macro(ReadableStream) \ + macro(ReadableStreamDefaultController) \ + macro(ReadableStreamDefaultReader) \ + macro(Request) \ + macro(Response) \ + macro(RTCIceCandidate) \ + macro(RTCSessionDescription) \ + macro(XMLHttpRequest) + +class WebCoreBuiltinNames { +public: + explicit WebCoreBuiltinNames(JSC::VM* vm) + : m_vm(*vm) + WEBCORE_COMMON_PRIVATE_IDENTIFIERS_EACH_PROPERTY_NAME(INITIALIZE_BUILTIN_NAMES) + { +#define EXPORT_NAME(name) m_vm.propertyNames->appendExternalName(name##PublicName(), name##PrivateName()); + WEBCORE_COMMON_PRIVATE_IDENTIFIERS_EACH_PROPERTY_NAME(EXPORT_NAME) +#undef EXPORT_NAME + } + + WEBCORE_COMMON_PRIVATE_IDENTIFIERS_EACH_PROPERTY_NAME(DECLARE_BUILTIN_IDENTIFIER_ACCESSOR) + +private: + JSC::VM& m_vm; + WEBCORE_COMMON_PRIVATE_IDENTIFIERS_EACH_PROPERTY_NAME(DECLARE_BUILTIN_NAMES) +}; + +} // namespace WebCore diff --git a/Source/WebCore/bindings/js/WebCoreJSClientData.cpp b/Source/WebCore/bindings/js/WebCoreJSClientData.cpp new file mode 100644 index 000000000..d87931f6e --- /dev/null +++ b/Source/WebCore/bindings/js/WebCoreJSClientData.cpp @@ -0,0 +1,117 @@ +/* + * Copyright (C) 2017 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "WebCoreJSClientData.h" + +#include "JSDOMBinding.h" +#include <heap/HeapInlines.h> +#include <heap/MarkingConstraint.h> +#include <heap/MarkedAllocatorInlines.h> +#include <heap/MarkedBlockInlines.h> +#include <heap/SubspaceInlines.h> +#include <heap/VisitingTimeout.h> +#include <runtime/VM.h> +#include <wtf/MainThread.h> + +using namespace JSC; + +namespace WebCore { + +JSVMClientData::JSVMClientData(VM& vm) + : m_builtinFunctions(vm) + , m_builtinNames(&vm) + , m_outputConstraintSpace("WebCore Wrapper w/ Output Constraint", vm.heap) + , m_globalObjectOutputConstraintSpace("WebCore Global Object w/ Output Constraint", vm.heap) +{ +} + +JSVMClientData::~JSVMClientData() +{ + ASSERT(m_worldSet.contains(m_normalWorld.get())); + ASSERT(m_worldSet.size() == 1); + ASSERT(m_normalWorld->hasOneRef()); + m_normalWorld = nullptr; + ASSERT(m_worldSet.isEmpty()); +} + +void JSVMClientData::getAllWorlds(Vector<Ref<DOMWrapperWorld>>& worlds) +{ + ASSERT(worlds.isEmpty()); + + worlds.reserveInitialCapacity(m_worldSet.size()); + for (auto it = m_worldSet.begin(), end = m_worldSet.end(); it != end; ++it) + worlds.uncheckedAppend(*(*it)); +} + +void JSVMClientData::initNormalWorld(VM* vm) +{ + JSVMClientData* clientData = new JSVMClientData(*vm); + vm->clientData = clientData; // ~VM deletes this pointer. + + auto constraint = std::make_unique<MarkingConstraint>( + "Wcoc", "WebCore Output Constraints", + [vm, clientData, lastExecutionVersion = vm->heap.mutatorExecutionVersion()] + (SlotVisitor& slotVisitor, const VisitingTimeout&) mutable { + Heap& heap = vm->heap; + + if (heap.mutatorExecutionVersion() == lastExecutionVersion) + return; + + lastExecutionVersion = heap.mutatorExecutionVersion(); + + // We have to manage the visit count here ourselves. We need to know that if this adds + // opaque roots then we cannot declare termination yet. The way we signal this to the + // constraint solver is by adding to the visit count. + + size_t numOpaqueRootsBefore = heap.numOpaqueRoots(); + + // FIXME: Make this parallel! + unsigned numRevisited = 0; + clientData->forEachOutputConstraintSpace( + [&] (Subspace& subspace) { + subspace.forEachMarkedCell( + [&] (HeapCell* heapCell, HeapCell::Kind) { + JSCell* cell = static_cast<JSCell*>(heapCell); + cell->methodTable(*vm)->visitOutputConstraints(cell, slotVisitor); + numRevisited++; + }); + }); + if (Options::logGC()) + dataLog("(", numRevisited, ")"); + + slotVisitor.mergeIfNecessary(); + + slotVisitor.addToVisitCount(heap.numOpaqueRoots() - numOpaqueRootsBefore); + }, + ConstraintVolatility::SeldomGreyed); + vm->heap.addMarkingConstraint(WTFMove(constraint)); + + clientData->m_normalWorld = DOMWrapperWorld::create(*vm, true); + vm->m_typedArrayController = adoptRef(new WebCoreTypedArrayController()); +} + +} // namespace WebCore + diff --git a/Source/WebCore/bindings/js/WebCoreJSClientData.h b/Source/WebCore/bindings/js/WebCoreJSClientData.h index 87e95de0f..47243c6de 100644 --- a/Source/WebCore/bindings/js/WebCoreJSClientData.h +++ b/Source/WebCore/bindings/js/WebCoreJSClientData.h @@ -1,6 +1,6 @@ /* * Copyright (C) 1999-2001 Harri Porten (porten@kde.org) - * Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Apple Inc. All rights reserved. + * Copyright (C) 2003-2017 Apple Inc. All rights reserved. * Copyright (C) 2007 Samuel Weinig <sam@webkit.org> * Copyright (C) 2009 Google, Inc. All rights reserved. * @@ -19,46 +19,31 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#ifndef WebCoreJSClientData_h -#define WebCoreJSClientData_h +#pragma once #include "DOMWrapperWorld.h" -#include "DOMObjectHashTableMap.h" +#include "WebCoreBuiltinNames.h" +#include "WebCoreJSBuiltins.h" #include "WebCoreTypedArrayController.h" #include <wtf/HashSet.h> #include <wtf/RefPtr.h> namespace WebCore { -class WebCoreJSClientData : public JSC::VM::ClientData { - WTF_MAKE_NONCOPYABLE(WebCoreJSClientData); WTF_MAKE_FAST_ALLOCATED; +class JSVMClientData : public JSC::VM::ClientData { + WTF_MAKE_NONCOPYABLE(JSVMClientData); WTF_MAKE_FAST_ALLOCATED; friend class VMWorldIterator; - friend void initNormalWorldClientData(JSC::VM*); public: - WebCoreJSClientData() - { - } + explicit JSVMClientData(JSC::VM&); - virtual ~WebCoreJSClientData() - { - ASSERT(m_worldSet.contains(m_normalWorld.get())); - ASSERT(m_worldSet.size() == 1); - ASSERT(m_normalWorld->hasOneRef()); - m_normalWorld.clear(); - ASSERT(m_worldSet.isEmpty()); - } + virtual ~JSVMClientData(); + + WEBCORE_EXPORT static void initNormalWorld(JSC::VM*); DOMWrapperWorld& normalWorld() { return *m_normalWorld; } - void getAllWorlds(Vector<Ref<DOMWrapperWorld>>& worlds) - { - ASSERT(worlds.isEmpty()); - - worlds.reserveInitialCapacity(m_worldSet.size()); - for (auto it = m_worldSet.begin(), end = m_worldSet.end(); it != end; ++it) - worlds.uncheckedAppend(*(*it)); - } + void getAllWorlds(Vector<Ref<DOMWrapperWorld>>&); void rememberWorld(DOMWrapperWorld& world) { @@ -72,21 +57,28 @@ public: m_worldSet.remove(&world); } - DOMObjectHashTableMap hashTableMap; + WebCoreBuiltinNames& builtinNames() { return m_builtinNames; } + JSBuiltinFunctions& builtinFunctions() { return m_builtinFunctions; } + + JSC::Subspace& outputConstraintSpace() { return m_outputConstraintSpace; } + JSC::Subspace& globalObjectOutputConstraintSpace() { return m_globalObjectOutputConstraintSpace; } + + template<typename Func> + void forEachOutputConstraintSpace(const Func& func) + { + func(m_outputConstraintSpace); + func(m_globalObjectOutputConstraintSpace); + } private: HashSet<DOMWrapperWorld*> m_worldSet; RefPtr<DOMWrapperWorld> m_normalWorld; -}; -inline void initNormalWorldClientData(JSC::VM* vm) -{ - WebCoreJSClientData* webCoreJSClientData = new WebCoreJSClientData; - vm->clientData = webCoreJSClientData; // ~VM deletes this pointer. - webCoreJSClientData->m_normalWorld = DOMWrapperWorld::create(vm, true); - vm->m_typedArrayController = adoptRef(new WebCoreTypedArrayController()); -} + JSBuiltinFunctions m_builtinFunctions; + WebCoreBuiltinNames m_builtinNames; + + JSC::JSDestructibleObjectSubspace m_outputConstraintSpace; + JSC::JSSegmentedVariableObjectSubspace m_globalObjectOutputConstraintSpace; +}; } // namespace WebCore - -#endif // WebCoreJSClientData_h diff --git a/Source/WebCore/bindings/js/WebCoreTypedArrayController.cpp b/Source/WebCore/bindings/js/WebCoreTypedArrayController.cpp index 0db3d5237..a3c938518 100644 --- a/Source/WebCore/bindings/js/WebCoreTypedArrayController.cpp +++ b/Source/WebCore/bindings/js/WebCoreTypedArrayController.cpp @@ -26,11 +26,11 @@ #include "config.h" #include "WebCoreTypedArrayController.h" -#include "JSDOMBinding.h" +#include "JSDOMConvertBufferSource.h" #include "JSDOMGlobalObject.h" #include <runtime/ArrayBuffer.h> #include <runtime/JSArrayBuffer.h> -#include <runtime/Operations.h> +#include <runtime/JSCInlines.h> namespace WebCore { @@ -47,20 +47,26 @@ JSC::JSArrayBuffer* WebCoreTypedArrayController::toJS(JSC::ExecState* state, JSC return JSC::jsCast<JSC::JSArrayBuffer*>(WebCore::toJS(state, JSC::jsCast<JSDOMGlobalObject*>(globalObject), buffer)); } +void WebCoreTypedArrayController::registerWrapper(JSC::JSGlobalObject* globalObject, JSC::ArrayBuffer* native, JSC::JSArrayBuffer* wrapper) +{ + cacheWrapper(JSC::jsCast<JSDOMGlobalObject*>(globalObject)->world(), native, wrapper); +} + +bool WebCoreTypedArrayController::isAtomicsWaitAllowedOnCurrentThread() +{ + return !isMainThread(); +} + bool WebCoreTypedArrayController::JSArrayBufferOwner::isReachableFromOpaqueRoots(JSC::Handle<JSC::Unknown> handle, void*, JSC::SlotVisitor& visitor) { - auto& wrapper = *JSC::jsCast<JSC::JSArrayBuffer*>(handle.get().asCell()); - if (!wrapper.hasCustomProperties()) - return false; + auto& wrapper = *JSC::jsCast<JSC::JSArrayBuffer*>(handle.slot()->asCell()); return visitor.containsOpaqueRoot(wrapper.impl()); } void WebCoreTypedArrayController::JSArrayBufferOwner::finalize(JSC::Handle<JSC::Unknown> handle, void* context) { - auto& wrapper = *static_cast<JSC::JSArrayBuffer*>(handle.get().asCell()); - auto& buffer = *wrapper.impl(); - uncacheWrapper(*static_cast<DOMWrapperWorld*>(context), &buffer, &wrapper); - buffer.deref(); + auto& wrapper = *static_cast<JSC::JSArrayBuffer*>(handle.slot()->asCell()); + uncacheWrapper(*static_cast<DOMWrapperWorld*>(context), wrapper.impl(), &wrapper); } } // namespace WebCore diff --git a/Source/WebCore/bindings/js/WebCoreTypedArrayController.h b/Source/WebCore/bindings/js/WebCoreTypedArrayController.h index 23f3eb0f0..3bb94bc85 100644 --- a/Source/WebCore/bindings/js/WebCoreTypedArrayController.h +++ b/Source/WebCore/bindings/js/WebCoreTypedArrayController.h @@ -23,13 +23,15 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef WebCoreTypedArrayController_h -#define WebCoreTypedArrayController_h +#pragma once -#include <heap/Weak.h> #include <runtime/JSGlobalObject.h> #include <runtime/TypedArrayController.h> +namespace JSC { +class WeakHandleOwner; +} + namespace WebCore { class WebCoreTypedArrayController : public JSC::TypedArrayController { @@ -37,21 +39,20 @@ public: WebCoreTypedArrayController(); virtual ~WebCoreTypedArrayController(); - virtual JSC::JSArrayBuffer* toJS(JSC::ExecState*, JSC::JSGlobalObject*, JSC::ArrayBuffer*) override; - + JSC::JSArrayBuffer* toJS(JSC::ExecState*, JSC::JSGlobalObject*, JSC::ArrayBuffer*) override; + void registerWrapper(JSC::JSGlobalObject*, ArrayBuffer*, JSC::JSArrayBuffer*) override; + bool isAtomicsWaitAllowedOnCurrentThread() override; + JSC::WeakHandleOwner* wrapperOwner() { return &m_owner; } private: class JSArrayBufferOwner : public JSC::WeakHandleOwner { public: - virtual bool isReachableFromOpaqueRoots(JSC::Handle<JSC::Unknown>, void* context, JSC::SlotVisitor&) override; - virtual void finalize(JSC::Handle<JSC::Unknown>, void* context) override; + bool isReachableFromOpaqueRoots(JSC::Handle<JSC::Unknown>, void* context, JSC::SlotVisitor&) override; + void finalize(JSC::Handle<JSC::Unknown>, void* context) override; }; JSArrayBufferOwner m_owner; }; } // namespace WebCore - -#endif // WebCoreTypedArrayController_h - diff --git a/Source/WebCore/bindings/js/WorkerScriptController.cpp b/Source/WebCore/bindings/js/WorkerScriptController.cpp index 579a0b4af..230af90bd 100644 --- a/Source/WebCore/bindings/js/WorkerScriptController.cpp +++ b/Source/WebCore/bindings/js/WorkerScriptController.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008 Apple Inc. All Rights Reserved. + * Copyright (C) 2008, 2016 Apple Inc. All Rights Reserved. * Copyright (C) 2011, 2012 Google Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without @@ -11,18 +11,17 @@ * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * - * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "config.h" @@ -30,23 +29,18 @@ #include "JSDOMBinding.h" #include "JSDedicatedWorkerGlobalScope.h" +#include "JSEventTarget.h" #include "ScriptSourceCode.h" #include "WebCoreJSClientData.h" +#include "WorkerConsoleClient.h" #include "WorkerGlobalScope.h" -#include "WorkerObjectProxy.h" -#include "WorkerScriptDebugServer.h" -#include "WorkerThread.h" #include <bindings/ScriptValue.h> #include <heap/StrongInlines.h> -#include <interpreter/Interpreter.h> #include <runtime/Completion.h> +#include <runtime/Exception.h> #include <runtime/ExceptionHelpers.h> -#include <runtime/Error.h> #include <runtime/JSLock.h> - -#if ENABLE(SHARED_WORKERS) -#include "JSSharedWorkerGlobalScope.h" -#endif +#include <runtime/Watchdog.h> using namespace JSC; @@ -56,16 +50,21 @@ WorkerScriptController::WorkerScriptController(WorkerGlobalScope* workerGlobalSc : m_vm(VM::create()) , m_workerGlobalScope(workerGlobalScope) , m_workerGlobalScopeWrapper(*m_vm) - , m_executionForbidden(false) { - initNormalWorldClientData(m_vm.get()); + m_vm->heap.acquireAccess(); // It's not clear that we have good discipline for heap access, so turn it on permanently. + m_vm->ensureWatchdog(); + JSVMClientData::initNormalWorld(m_vm.get()); } WorkerScriptController::~WorkerScriptController() { JSLockHolder lock(vm()); + if (m_workerGlobalScopeWrapper) { + m_workerGlobalScopeWrapper->setConsoleClient(nullptr); + m_consoleClient = nullptr; + } m_workerGlobalScopeWrapper.clear(); - m_vm.clear(); + m_vm = nullptr; } void WorkerScriptController::initScript() @@ -77,35 +76,28 @@ void WorkerScriptController::initScript() // Explicitly protect the global object's prototype so it isn't collected // when we allocate the global object. (Once the global object is fully // constructed, it can mark its own prototype.) - Structure* workerGlobalScopePrototypeStructure = JSWorkerGlobalScopePrototype::createStructure(*m_vm, 0, jsNull()); - Strong<JSWorkerGlobalScopePrototype> workerGlobalScopePrototype(*m_vm, JSWorkerGlobalScopePrototype::create(*m_vm, 0, workerGlobalScopePrototypeStructure)); - if (m_workerGlobalScope->isDedicatedWorkerGlobalScope()) { - Structure* dedicatedContextPrototypeStructure = JSDedicatedWorkerGlobalScopePrototype::createStructure(*m_vm, 0, workerGlobalScopePrototype.get()); - Strong<JSDedicatedWorkerGlobalScopePrototype> dedicatedContextPrototype(*m_vm, JSDedicatedWorkerGlobalScopePrototype::create(*m_vm, 0, dedicatedContextPrototypeStructure)); - Structure* structure = JSDedicatedWorkerGlobalScope::createStructure(*m_vm, 0, dedicatedContextPrototype.get()); + Structure* dedicatedContextPrototypeStructure = JSDedicatedWorkerGlobalScopePrototype::createStructure(*m_vm, nullptr, jsNull()); + Strong<JSDedicatedWorkerGlobalScopePrototype> dedicatedContextPrototype(*m_vm, JSDedicatedWorkerGlobalScopePrototype::create(*m_vm, nullptr, dedicatedContextPrototypeStructure)); + Structure* structure = JSDedicatedWorkerGlobalScope::createStructure(*m_vm, nullptr, dedicatedContextPrototype.get()); + auto* proxyStructure = JSProxy::createStructure(*m_vm, nullptr, jsNull(), PureForwardingProxyType); + auto* proxy = JSProxy::create(*m_vm, proxyStructure); - m_workerGlobalScopeWrapper.set(*m_vm, JSDedicatedWorkerGlobalScope::create(*m_vm, structure, static_cast<DedicatedWorkerGlobalScope*>(m_workerGlobalScope))); - workerGlobalScopePrototypeStructure->setGlobalObject(*m_vm, m_workerGlobalScopeWrapper.get()); + m_workerGlobalScopeWrapper.set(*m_vm, JSDedicatedWorkerGlobalScope::create(*m_vm, structure, static_cast<DedicatedWorkerGlobalScope&>(*m_workerGlobalScope), proxy)); dedicatedContextPrototypeStructure->setGlobalObject(*m_vm, m_workerGlobalScopeWrapper.get()); ASSERT(structure->globalObject() == m_workerGlobalScopeWrapper); ASSERT(m_workerGlobalScopeWrapper->structure()->globalObject() == m_workerGlobalScopeWrapper); - workerGlobalScopePrototype->structure()->setGlobalObject(*m_vm, m_workerGlobalScopeWrapper.get()); dedicatedContextPrototype->structure()->setGlobalObject(*m_vm, m_workerGlobalScopeWrapper.get()); -#if ENABLE(SHARED_WORKERS) - } else { - ASSERT(m_workerGlobalScope->isSharedWorkerGlobalScope()); - Structure* sharedContextPrototypeStructure = JSSharedWorkerGlobalScopePrototype::createStructure(*m_vm, 0, workerGlobalScopePrototype.get()); - Strong<JSSharedWorkerGlobalScopePrototype> sharedContextPrototype(*m_vm, JSSharedWorkerGlobalScopePrototype::create(*m_vm, 0, sharedContextPrototypeStructure)); - Structure* structure = JSSharedWorkerGlobalScope::createStructure(*m_vm, 0, sharedContextPrototype.get()); - - m_workerGlobalScopeWrapper.set(*m_vm, JSSharedWorkerGlobalScope::create(*m_vm, structure, static_cast<SharedWorkerGlobalScope*>(m_workerGlobalScope))); - workerGlobalScopePrototype->structure()->setGlobalObject(*m_vm, m_workerGlobalScopeWrapper.get()); - sharedContextPrototype->structure()->setGlobalObject(*m_vm, m_workerGlobalScopeWrapper.get()); -#endif + dedicatedContextPrototype->structure()->setPrototypeWithoutTransition(*m_vm, JSWorkerGlobalScope::prototype(*m_vm, m_workerGlobalScopeWrapper.get())); + + proxy->setTarget(*m_vm, m_workerGlobalScopeWrapper.get()); + proxy->structure()->setGlobalObject(*m_vm, m_workerGlobalScopeWrapper.get()); } ASSERT(m_workerGlobalScopeWrapper->globalObject() == m_workerGlobalScopeWrapper); - ASSERT(asObject(m_workerGlobalScopeWrapper->prototype())->globalObject() == m_workerGlobalScopeWrapper); + ASSERT(asObject(m_workerGlobalScopeWrapper->getPrototypeDirect())->globalObject() == m_workerGlobalScopeWrapper); + + m_consoleClient = std::make_unique<WorkerConsoleClient>(*m_workerGlobalScope); + m_workerGlobalScopeWrapper->setConsoleClient(m_consoleClient.get()); } void WorkerScriptController::evaluate(const ScriptSourceCode& sourceCode) @@ -113,15 +105,15 @@ void WorkerScriptController::evaluate(const ScriptSourceCode& sourceCode) if (isExecutionForbidden()) return; - Deprecated::ScriptValue exception; - evaluate(sourceCode, &exception); - if (exception.jsValue()) { + NakedPtr<JSC::Exception> exception; + evaluate(sourceCode, exception); + if (exception) { JSLockHolder lock(vm()); - reportException(m_workerGlobalScopeWrapper->globalExec(), exception.jsValue()); + reportException(m_workerGlobalScopeWrapper->globalExec(), exception); } } -void WorkerScriptController::evaluate(const ScriptSourceCode& sourceCode, Deprecated::ScriptValue* exception) +void WorkerScriptController::evaluate(const ScriptSourceCode& sourceCode, NakedPtr<JSC::Exception>& returnedException) { if (isExecutionForbidden()) return; @@ -129,47 +121,52 @@ void WorkerScriptController::evaluate(const ScriptSourceCode& sourceCode, Deprec initScriptIfNeeded(); ExecState* exec = m_workerGlobalScopeWrapper->globalExec(); - JSLockHolder lock(exec); + VM& vm = exec->vm(); + JSLockHolder lock(vm); - JSValue evaluationException; - JSC::evaluate(exec, sourceCode.jsSourceCode(), m_workerGlobalScopeWrapper.get(), &evaluationException); + JSC::evaluate(exec, sourceCode.jsSourceCode(), m_workerGlobalScopeWrapper->globalThis(), returnedException); - if ((evaluationException && isTerminatedExecutionException(evaluationException)) || m_workerGlobalScopeWrapper->vm().watchdog.didFire()) { + if ((returnedException && isTerminatedExecutionException(vm, returnedException)) || isTerminatingExecution()) { forbidExecution(); return; } - if (evaluationException) { + if (returnedException) { String errorMessage; int lineNumber = 0; int columnNumber = 0; String sourceURL = sourceCode.url().string(); - if (m_workerGlobalScope->sanitizeScriptError(errorMessage, lineNumber, columnNumber, sourceURL, sourceCode.cachedScript())) - *exception = Deprecated::ScriptValue(*m_vm, exec->vm().throwException(exec, createError(exec, errorMessage.impl()))); - else - *exception = Deprecated::ScriptValue(*m_vm, evaluationException); + JSC::Strong<JSC::Unknown> error; + if (m_workerGlobalScope->sanitizeScriptError(errorMessage, lineNumber, columnNumber, sourceURL, error, sourceCode.cachedScript())) + returnedException = JSC::Exception::create(vm, createError(exec, errorMessage.impl())); } } -void WorkerScriptController::setException(const Deprecated::ScriptValue& exception) +void WorkerScriptController::setException(JSC::Exception* exception) { - m_workerGlobalScopeWrapper->globalExec()->vm().throwException(m_workerGlobalScopeWrapper->globalExec(), exception.jsValue()); + JSC::ExecState* exec = m_workerGlobalScopeWrapper->globalExec(); + VM& vm = exec->vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + throwException(exec, scope, exception); } void WorkerScriptController::scheduleExecutionTermination() { // The mutex provides a memory barrier to ensure that once - // termination is scheduled, isExecutionTerminating will + // termination is scheduled, isTerminatingExecution() will // accurately reflect that state when called from another thread. - MutexLocker locker(m_scheduledTerminationMutex); - m_vm->watchdog.fire(); + LockHolder locker(m_scheduledTerminationMutex); + m_isTerminatingExecution = true; + + ASSERT(m_vm->watchdog()); + m_vm->watchdog()->terminateSoon(); } -bool WorkerScriptController::isExecutionTerminating() const +bool WorkerScriptController::isTerminatingExecution() const { // See comments in scheduleExecutionTermination regarding mutex usage. - MutexLocker locker(m_scheduledTerminationMutex); - return m_vm->watchdog.didFire(); + LockHolder locker(m_scheduledTerminationMutex); + return m_isTerminatingExecution; } void WorkerScriptController::forbidExecution() @@ -192,6 +189,16 @@ void WorkerScriptController::disableEval(const String& errorMessage) m_workerGlobalScopeWrapper->setEvalEnabled(false, errorMessage); } +void WorkerScriptController::releaseHeapAccess() +{ + m_vm->heap.releaseAccess(); +} + +void WorkerScriptController::acquireHeapAccess() +{ + m_vm->heap.acquireAccess(); +} + void WorkerScriptController::attachDebugger(JSC::Debugger* debugger) { initScriptIfNeeded(); diff --git a/Source/WebCore/bindings/js/WorkerScriptController.h b/Source/WebCore/bindings/js/WorkerScriptController.h index 025c37d2c..460455208 100644 --- a/Source/WebCore/bindings/js/WorkerScriptController.h +++ b/Source/WebCore/bindings/js/WorkerScriptController.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008 Apple Inc. All Rights Reserved. + * Copyright (C) 2008, 2015, 2016 Apple Inc. All Rights Reserved. * Copyright (C) 2012 Google Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without @@ -11,10 +11,10 @@ * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * - * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR @@ -22,20 +22,15 @@ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * */ -#ifndef WorkerScriptController_h -#define WorkerScriptController_h +#pragma once #include <debugger/Debugger.h> #include <heap/Strong.h> #include <wtf/Forward.h> -#include <wtf/Threading.h> - -namespace Deprecated { -class ScriptValue; -} +#include <wtf/Lock.h> +#include <wtf/NakedPtr.h> namespace JSC { class VM; @@ -45,6 +40,7 @@ namespace WebCore { class JSWorkerGlobalScope; class ScriptSourceCode; + class WorkerConsoleClient; class WorkerGlobalScope; class WorkerScriptController { @@ -60,9 +56,9 @@ namespace WebCore { } void evaluate(const ScriptSourceCode&); - void evaluate(const ScriptSourceCode&, Deprecated::ScriptValue* exception); + void evaluate(const ScriptSourceCode&, NakedPtr<JSC::Exception>& returnedException); - void setException(const Deprecated::ScriptValue&); + void setException(JSC::Exception*); // Async request to terminate a JS run execution. Eventually causes termination // exception raised during JS execution, if the worker thread happens to run JS. @@ -70,7 +66,7 @@ namespace WebCore { // forbidExecution()/isExecutionForbidden() to guard against reentry into JS. // Can be called from any thread. void scheduleExecutionTermination(); - bool isExecutionTerminating() const; + bool isTerminatingExecution() const; // Called on Worker thread when JS exits with termination exception caused by forbidExecution() request, // or by Worker thread termination code to prevent future entry into JS. @@ -79,7 +75,10 @@ namespace WebCore { void disableEval(const String& errorMessage); - JSC::VM* vm() { return m_vm.get(); } + JSC::VM& vm() { return *m_vm; } + + void releaseHeapAccess(); + void acquireHeapAccess(); void attachDebugger(JSC::Debugger*); void detachDebugger(JSC::Debugger*); @@ -95,10 +94,10 @@ namespace WebCore { RefPtr<JSC::VM> m_vm; WorkerGlobalScope* m_workerGlobalScope; JSC::Strong<JSWorkerGlobalScope> m_workerGlobalScopeWrapper; - bool m_executionForbidden; - mutable Mutex m_scheduledTerminationMutex; + std::unique_ptr<WorkerConsoleClient> m_consoleClient; + bool m_executionForbidden { false }; + bool m_isTerminatingExecution { false }; + mutable Lock m_scheduledTerminationMutex; }; } // namespace WebCore - -#endif // WorkerScriptController_h diff --git a/Source/WebCore/bindings/js/WorkerScriptDebugServer.cpp b/Source/WebCore/bindings/js/WorkerScriptDebugServer.cpp deleted file mode 100644 index 76c95eebc..000000000 --- a/Source/WebCore/bindings/js/WorkerScriptDebugServer.cpp +++ /dev/null @@ -1,111 +0,0 @@ -/* - * Copyright (c) 2011 Google Inc. All rights reserved. - * Copyright (c) 2013 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" -#include "WorkerScriptDebugServer.h" - -#include "JSDOMBinding.h" -#include "Timer.h" -#include "WorkerDebuggerAgent.h" -#include "WorkerGlobalScope.h" -#include "WorkerRunLoop.h" -#include "WorkerThread.h" -#include <runtime/VM.h> -#include <wtf/PassOwnPtr.h> - -using namespace Inspector; - -namespace WebCore { - -WorkerScriptDebugServer::WorkerScriptDebugServer(WorkerGlobalScope* context, const String& mode) - : ScriptDebugServer(true) - , m_workerGlobalScope(context) - , m_debuggerTaskMode(mode) -{ -} - -void WorkerScriptDebugServer::addListener(ScriptDebugListener* listener) -{ - if (!listener) - return; - - bool wasEmpty = m_listeners.isEmpty(); - m_listeners.add(listener); - - if (wasEmpty) { - m_workerGlobalScope->script()->attachDebugger(this); - recompileAllJSFunctions(); - } -} - -void WorkerScriptDebugServer::removeListener(ScriptDebugListener* listener, bool skipRecompile) -{ - if (!listener) - return; - - m_listeners.remove(listener); - - if (m_listeners.isEmpty()) { - m_workerGlobalScope->script()->detachDebugger(this); - if (!skipRecompile) - recompileAllJSFunctions(); - } -} - -void WorkerScriptDebugServer::recompileAllJSFunctions() -{ - JSC::VM* vm = m_workerGlobalScope->script()->vm(); - - JSC::JSLockHolder lock(vm); - JSC::Debugger::recompileAllJSFunctions(vm); -} - -void WorkerScriptDebugServer::runEventLoopWhilePaused() -{ - TimerBase::fireTimersInNestedEventLoop(); - - MessageQueueWaitResult result; - do { - result = m_workerGlobalScope->thread()->runLoop().runInMode(m_workerGlobalScope, m_debuggerTaskMode); - // Keep waiting until execution is resumed. - } while (result != MessageQueueTerminated && !m_doneProcessingDebuggerEvents); -} - -void WorkerScriptDebugServer::reportException(JSC::ExecState* exec, JSC::JSValue exception) const -{ - WebCore::reportException(exec, exception); -} - -void WorkerScriptDebugServer::interruptAndRunTask(PassOwnPtr<ScriptDebugServer::Task>) -{ -} - -} // namespace WebCore diff --git a/Source/WebCore/bindings/js/WorkerScriptDebugServer.h b/Source/WebCore/bindings/js/WorkerScriptDebugServer.h deleted file mode 100644 index 78efd0bc7..000000000 --- a/Source/WebCore/bindings/js/WorkerScriptDebugServer.h +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright (c) 2011 Google Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef WorkerScriptDebugServer_h -#define WorkerScriptDebugServer_h - -#include <inspector/ScriptDebugServer.h> - -namespace WebCore { - -class WorkerGlobalScope; - -class WorkerScriptDebugServer final : public Inspector::ScriptDebugServer { - WTF_MAKE_NONCOPYABLE(WorkerScriptDebugServer); -public: - WorkerScriptDebugServer(WorkerGlobalScope*, const String&); - ~WorkerScriptDebugServer() { } - - virtual void recompileAllJSFunctions() override; - - void addListener(Inspector::ScriptDebugListener*); - void removeListener(Inspector::ScriptDebugListener*, bool skipRecompile); - - void interruptAndRunTask(PassOwnPtr<ScriptDebugServer::Task>); - -private: - virtual ListenerSet* getListenersForGlobalObject(JSC::JSGlobalObject*) override { return &m_listeners; } - virtual void didPause(JSC::JSGlobalObject*) override { } - virtual void didContinue(JSC::JSGlobalObject*) override { } - virtual void runEventLoopWhilePaused() override; - virtual bool isContentScript(JSC::ExecState*) const override { return false; } - virtual void reportException(JSC::ExecState*, JSC::JSValue) const override; - - WorkerGlobalScope* m_workerGlobalScope; - ListenerSet m_listeners; - String m_debuggerTaskMode; -}; - -} // namespace WebCore - -#endif // WorkerScriptDebugServer_h diff --git a/Source/WebCore/bindings/scripts/CodeGenerator.pm b/Source/WebCore/bindings/scripts/CodeGenerator.pm index 943959f54..6f77d7de5 100644 --- a/Source/WebCore/bindings/scripts/CodeGenerator.pm +++ b/Source/WebCore/bindings/scripts/CodeGenerator.pm @@ -28,14 +28,16 @@ package CodeGenerator; use strict; +use File::Basename; use File::Find; +use Carp qw<longmess>; +use Data::Dumper; my $useDocument = ""; my $useGenerator = ""; my $useOutputDir = ""; my $useOutputHeadersDir = ""; my $useDirectories = ""; -my $useLayerOnTop = 0; my $preprocessor; my $writeDependencies = 0; my $defines = ""; @@ -45,59 +47,88 @@ my $codeGenerator = 0; my $verbose = 0; -my %numericTypeHash = ("int" => 1, "short" => 1, "long" => 1, "long long" => 1, - "unsigned int" => 1, "unsigned short" => 1, - "unsigned long" => 1, "unsigned long long" => 1, - "float" => 1, "double" => 1, "byte" => 1, - "octet" => 1); +my %integerTypeHash = ( + "byte" => 1, + "long long" => 1, + "long" => 1, + "octet" => 1, + "short" => 1, + "unsigned long long" => 1, + "unsigned long" => 1, + "unsigned short" => 1, +); -my %primitiveTypeHash = ( "boolean" => 1, "void" => 1, "Date" => 1); +my %floatingPointTypeHash = ( + "float" => 1, + "unrestricted float" => 1, + "double" => 1, + "unrestricted double" => 1, +); -my %stringTypeHash = ("DOMString" => 1, "AtomicString" => 1); +my %stringTypeHash = ( + "ByteString" => 1, + "DOMString" => 1, + "USVString" => 1, +); -# WebCore types used directly in IDL files. -my %webCoreTypeHash = ( - "CompareHow" => 1, - "SerializedScriptValue" => 1, - "Dictionary" => 1 +my %typedArrayTypes = ( + "ArrayBuffer" => 1, + "ArrayBufferView" => 1, + "DataView" => 1, + "Float32Array" => 1, + "Float64Array" => 1, + "Int16Array" => 1, + "Int32Array" => 1, + "Int8Array" => 1, + "Uint16Array" => 1, + "Uint32Array" => 1, + "Uint8Array" => 1, + "Uint8ClampedArray" => 1, ); -my %enumTypeHash = (); - -my %nonPointerTypeHash = ("DOMTimeStamp" => 1, "CompareHow" => 1); - -my %svgAttributesInHTMLHash = ("class" => 1, "id" => 1, "onabort" => 1, "onclick" => 1, - "onerror" => 1, "onload" => 1, "onmousedown" => 1, - "onmouseenter" => 1, "onmouseleave" => 1, - "onmousemove" => 1, "onmouseout" => 1, "onmouseover" => 1, - "onmouseup" => 1, "onresize" => 1, "onscroll" => 1, - "onunload" => 1); - -my %svgTypeNeedingTearOff = ( - "SVGAngle" => "SVGPropertyTearOff<SVGAngle>", - "SVGLength" => "SVGPropertyTearOff<SVGLength>", - "SVGLengthList" => "SVGListPropertyTearOff<SVGLengthList>", - "SVGMatrix" => "SVGPropertyTearOff<SVGMatrix>", - "SVGNumber" => "SVGPropertyTearOff<float>", - "SVGNumberList" => "SVGListPropertyTearOff<SVGNumberList>", - "SVGPathSegList" => "SVGPathSegListPropertyTearOff", - "SVGPoint" => "SVGPropertyTearOff<SVGPoint>", - "SVGPointList" => "SVGListPropertyTearOff<SVGPointList>", - "SVGPreserveAspectRatio" => "SVGPropertyTearOff<SVGPreserveAspectRatio>", - "SVGRect" => "SVGPropertyTearOff<FloatRect>", - "SVGStringList" => "SVGStaticListPropertyTearOff<SVGStringList>", - "SVGTransform" => "SVGPropertyTearOff<SVGTransform>", - "SVGTransformList" => "SVGTransformListPropertyTearOff" +my %primitiveTypeHash = ( + "boolean" => 1, + "void" => 1, + "Date" => 1 ); -my %svgTypeWithWritablePropertiesNeedingTearOff = ( - "SVGPoint" => 1, - "SVGMatrix" => 1 +my %dictionaryTypeImplementationNameOverrides = (); +my %enumTypeImplementationNameOverrides = (); + +my %svgAttributesInHTMLHash = ( + "class" => 1, + "id" => 1, + "onabort" => 1, + "onclick" => 1, + "onerror" => 1, + "onload" => 1, + "onmousedown" => 1, + "onmouseenter" => 1, + "onmouseleave" => 1, + "onmousemove" => 1, + "onmouseout" => 1, + "onmouseover" => 1, + "onmouseup" => 1, + "onresize" => 1, + "onscroll" => 1, + "onunload" => 1, ); # Cache of IDL file pathnames. my $idlFiles; my $cachedInterfaces = {}; +my $cachedExternalDictionaries = {}; +my $cachedExternalEnumerations = {}; + +sub assert +{ + my $message = shift; + + my $mess = longmess(); + print Dumper($mess); + + die $message; +} # Default constructor sub new @@ -109,7 +140,6 @@ sub new $useGenerator = shift; $useOutputDir = shift; $useOutputHeadersDir = shift; - $useLayerOnTop = shift; $preprocessor = shift; $writeDependencies = shift; $verbose = shift; @@ -128,24 +158,86 @@ sub ProcessDocument my $ifaceName = "CodeGenerator" . $useGenerator; require $ifaceName . ".pm"; - %enumTypeHash = map { $_->name => $_->values } @{$useDocument->enumerations}; + foreach my $dictionary (@{$useDocument->dictionaries}) { + if ($dictionary->extendedAttributes->{"ImplementedAs"}) { + $dictionaryTypeImplementationNameOverrides{$dictionary->type->name} = $dictionary->extendedAttributes->{"ImplementedAs"}; + } + } + + foreach my $enumeration (@{$useDocument->enumerations}) { + if ($enumeration->extendedAttributes->{"ImplementedAs"}) { + $enumTypeImplementationNameOverrides{$enumeration->type->name} = $enumeration->extendedAttributes->{"ImplementedAs"}; + } + } # Dynamically load external code generation perl module - $codeGenerator = $ifaceName->new($object, $useLayerOnTop, $preprocessor, $writeDependencies, $verbose, $targetIdlFilePath); + $codeGenerator = $ifaceName->new($object, $writeDependencies, $verbose, $targetIdlFilePath); unless (defined($codeGenerator)) { my $interfaces = $useDocument->interfaces; foreach my $interface (@$interfaces) { - print "Skipping $useGenerator code generation for IDL interface \"" . $interface->name . "\".\n" if $verbose; + print "Skipping $useGenerator code generation for IDL interface \"" . $interface->type->name . "\".\n" if $verbose; } return; } my $interfaces = $useDocument->interfaces; - foreach my $interface (@$interfaces) { - print "Generating $useGenerator bindings code for IDL interface \"" . $interface->name . "\"...\n" if $verbose; - $codeGenerator->GenerateInterface($interface, $defines); + if (@$interfaces) { + die "Multiple interfaces per document are not supported" if @$interfaces > 1; + + my $interface = @$interfaces[0]; + print "Generating $useGenerator bindings code for IDL interface \"" . $interface->type->name . "\"...\n" if $verbose; + $codeGenerator->GenerateInterface($interface, $defines, $useDocument->enumerations, $useDocument->dictionaries); $codeGenerator->WriteData($interface, $useOutputDir, $useOutputHeadersDir); + return; + } + + my $callbackFunctions = $useDocument->callbackFunctions; + if (@$callbackFunctions) { + die "Multiple standalone callback functions per document are not supported" if @$callbackFunctions > 1; + + my $callbackFunction = @$callbackFunctions[0]; + print "Generating $useGenerator bindings code for IDL callback function \"" . $callbackFunction->type->name . "\"...\n" if $verbose; + $codeGenerator->GenerateCallbackFunction($callbackFunction, $useDocument->enumerations, $useDocument->dictionaries); + $codeGenerator->WriteData($callbackFunction, $useOutputDir, $useOutputHeadersDir); + return; + } + + my $dictionaries = $useDocument->dictionaries; + if (@$dictionaries) { + my $dictionary; + my $otherDictionaries; + if (@$dictionaries == 1) { + $dictionary = @$dictionaries[0]; + } else { + my $primaryDictionaryName = fileparse($targetIdlFilePath, ".idl"); + for my $candidate (@$dictionaries) { + if ($candidate->type->name eq $primaryDictionaryName) { + $dictionary = $candidate; + } else { + push @$otherDictionaries, $candidate; + } + } + die "Multiple dictionaries per document are only supported if one matches the filename" unless $dictionary; + } + + print "Generating $useGenerator bindings code for IDL dictionary \"" . $dictionary->type->name . "\"...\n" if $verbose; + $codeGenerator->GenerateDictionary($dictionary, $useDocument->enumerations, $otherDictionaries); + $codeGenerator->WriteData($dictionary, $useOutputDir, $useOutputHeadersDir); + return; } + + my $enumerations = $useDocument->enumerations; + if (@$enumerations) { + die "Multiple standalone enumerations per document are not supported" if @$enumerations > 1; + + my $enumeration = @$enumerations[0]; + print "Generating $useGenerator bindings code for IDL enumeration \"" . $enumeration->type->name . "\"...\n" if $verbose; + $codeGenerator->GenerateEnumeration($enumeration); + $codeGenerator->WriteData($enumeration, $useOutputDir, $useOutputHeadersDir); + return; + } + + die "Processing document " . $useDocument->fileName . " did not generate anything" } sub FileNamePrefix @@ -156,7 +248,7 @@ sub FileNamePrefix require $ifaceName . ".pm"; # Dynamically load external code generation perl module - $codeGenerator = $ifaceName->new($object, $useLayerOnTop, $preprocessor, $writeDependencies, $verbose); + $codeGenerator = $ifaceName->new($object, $writeDependencies, $verbose); return $codeGenerator->FileNamePrefix(); } @@ -166,7 +258,9 @@ sub UpdateFile my $fileName = shift; my $contents = shift; - open FH, "> $fileName" or die "Couldn't open $fileName: $!\n"; + # FIXME: We should only write content if it is different from what is in the file. + # But that would mean running more often the binding generator, see https://bugs.webkit.org/show_bug.cgi?id=131756 + open FH, ">", $fileName or die "Couldn't open $fileName: $!\n"; print FH $contents; close FH; } @@ -183,8 +277,8 @@ sub ForAllParents my $outerInterface = shift; my $currentInterface = shift; - for (@{$currentInterface->parents}) { - my $interfaceName = $_; + if ($currentInterface->parentType) { + my $interfaceName = $currentInterface->parentType->name; my $parentInterface = $object->ParseInterface($outerInterface, $interfaceName); if ($beforeRecursion) { @@ -198,22 +292,6 @@ sub ForAllParents &$recurse($interface, $interface); } -sub FindSuperMethod -{ - my ($object, $interface, $functionName) = @_; - my $indexer; - $object->ForAllParents($interface, undef, sub { - my $currentInterface = shift; - foreach my $function (@{$currentInterface->functions}) { - if ($function->signature->name eq $functionName) { - $indexer = $function->signature; - return 'prune'; - } - } - }); - return $indexer; -} - sub IDLFileForInterface { my $object = shift; @@ -236,6 +314,26 @@ sub IDLFileForInterface return $idlFiles->{$interfaceName}; } +sub GetInterfaceForAttribute +{ + my ($object, $currentInterface, $attribute) = @_; + + return undef unless $object->IsInterfaceType($attribute->type); + + return $object->ParseInterface($currentInterface, $attribute->type->name); +} + +sub GetAttributeFromInterface +{ + my ($object, $outerInterface, $interfaceName, $attributeName) = @_; + + my $interface = $object->ParseInterface($outerInterface, $interfaceName); + for my $attribute (@{$interface->attributes}) { + return $attribute if $attribute->name eq $attributeName; + } + die("Could not find attribute '$attributeName' on interface '$interfaceName'."); +} + sub ParseInterface { my $object = shift; @@ -243,6 +341,7 @@ sub ParseInterface my $interfaceName = shift; return undef if $interfaceName eq 'Object'; + return undef if $interfaceName eq 'UNION'; if (exists $cachedInterfaces->{$interfaceName}) { return $cachedInterfaces->{$interfaceName}; @@ -250,7 +349,7 @@ sub ParseInterface # Step #1: Find the IDL file associated with 'interface' my $filename = $object->IDLFileForInterface($interfaceName) - or die("Could NOT find IDL file for interface \"$interfaceName\", reachable from \"" . $outerInterface->name . "\"!\n"); + or assert("Could NOT find IDL file for interface \"$interfaceName\", reachable from \"" . $outerInterface->type->name . "\"!\n"); print " | |> Parsing parent IDL \"$filename\" for interface \"$interfaceName\"\n" if $verbose; @@ -259,7 +358,7 @@ sub ParseInterface my $document = $parser->Parse($filename, $defines, $preprocessor); foreach my $interface (@{$document->interfaces}) { - if ($interface->name eq $interfaceName) { + if ($interface->type->name eq $interfaceName) { $cachedInterfaces->{$interfaceName} = $interface; return $interface; } @@ -270,197 +369,330 @@ sub ParseInterface # Helpers for all CodeGenerator***.pm modules -sub SkipIncludeHeader +sub IsNumericType { - my $object = shift; - my $type = shift; + my ($object, $type) = @_; - return 1 if $object->IsPrimitiveType($type); + assert("Not a type") if ref($type) ne "IDLType"; - # Special case: SVGNumber.h does not exist. - return 1 if $type eq "SVGNumber"; - - # Typed arrays already included by JSDOMBinding.h. - return 1 if $object->IsTypedArrayType($type); + return 1 if $integerTypeHash{$type->name}; + return 1 if $floatingPointTypeHash{$type->name}; + return 0; +} + +sub IsStringOrEnumType +{ + my ($object, $type) = @_; + assert("Not a type") if ref($type) ne "IDLType"; + + return 1 if $object->IsStringType($type); + return 1 if $object->IsEnumType($type); return 0; } -sub IsConstructorTemplate +sub IsIntegerType { - my $object = shift; - my $interface = shift; - my $template = shift; + my ($object, $type) = @_; - return $interface->extendedAttributes->{"ConstructorTemplate"} && $interface->extendedAttributes->{"ConstructorTemplate"} eq $template; + assert("Not a type") if ref($type) ne "IDLType"; + + return 1 if $integerTypeHash{$type->name}; + return 0; } -sub IsNumericType +sub IsFloatingPointType { - my $object = shift; - my $type = shift; + my ($object, $type) = @_; - return 1 if $numericTypeHash{$type}; + assert("Not a type") if ref($type) ne "IDLType"; + + return 1 if $floatingPointTypeHash{$type->name}; return 0; } sub IsPrimitiveType { - my $object = shift; - my $type = shift; + my ($object, $type) = @_; - return 1 if $primitiveTypeHash{$type}; - return 1 if $numericTypeHash{$type}; + assert("Not a type") if ref($type) ne "IDLType"; + + return 1 if $primitiveTypeHash{$type->name}; + return 1 if $object->IsNumericType($type); return 0; } sub IsStringType { - my $object = shift; - my $type = shift; + my ($object, $type) = @_; - return 1 if $stringTypeHash{$type}; + assert("Not a type") if ref($type) ne "IDLType"; + + return 1 if $stringTypeHash{$type->name}; return 0; } sub IsEnumType { - my $object = shift; - my $type = shift; + my ($object, $type) = @_; - return 1 if exists $enumTypeHash{$type}; - return 0; + assert("Not a type") if ref($type) ne "IDLType"; + + return defined($object->GetEnumByType($type)); } -sub ValidEnumValues +sub GetEnumByType { - my $object = shift; - my $type = shift; + my ($object, $type) = @_; + + assert("Not a type") if ref($type) ne "IDLType"; + + my $name = $type->name; + + die "GetEnumByType() was called with an undefined enumeration name" unless defined($name); + + for my $enumeration (@{$useDocument->enumerations}) { + return $enumeration if $enumeration->type->name eq $name; + } + + return $cachedExternalEnumerations->{$name} if exists($cachedExternalEnumerations->{$name}); - return @{$enumTypeHash{$type}}; + # Find the IDL file associated with the dictionary. + my $filename = $object->IDLFileForInterface($name) or return; + + # Do a fast check to see if it seems to contain a dictionary. + my $fileContents = slurp($filename); + + if ($fileContents =~ /\benum\s+$name/gs) { + # Parse the IDL. + my $parser = IDLParser->new(1); + my $document = $parser->Parse($filename, $defines, $preprocessor); + + foreach my $enumeration (@{$document->enumerations}) { + next unless $enumeration->type->name eq $name; + + $cachedExternalEnumerations->{$name} = $enumeration; + my $implementedAs = $enumeration->extendedAttributes->{ImplementedAs}; + $enumTypeImplementationNameOverrides{$enumeration->type->name} = $implementedAs if $implementedAs; + return $enumeration; + } + } + $cachedExternalEnumerations->{$name} = undef; } -sub IsNonPointerType +# An enumeration defined in its own IDL file. +sub IsExternalEnumType { - my $object = shift; - my $type = shift; + my ($object, $type) = @_; - return 1 if $nonPointerTypeHash{$type} or $primitiveTypeHash{$type} or $numericTypeHash{$type}; + assert("Not a type") if ref($type) ne "IDLType"; + + return $object->IsEnumType($type) && defined($cachedExternalEnumerations->{$type->name}); +} + +sub HasEnumImplementationNameOverride +{ + my ($object, $type) = @_; + + assert("Not a type") if ref($type) ne "IDLType"; + + return 1 if exists $enumTypeImplementationNameOverrides{$type->name}; return 0; } -sub IsSVGTypeNeedingTearOff +sub GetEnumImplementationNameOverride { - my $object = shift; - my $type = shift; + my ($object, $type) = @_; + + assert("Not a type") if ref($type) ne "IDLType"; + + return $enumTypeImplementationNameOverrides{$type->name}; +} + +sub GetDictionaryByType +{ + my ($object, $type) = @_; + + assert("Not a type") if ref($type) ne "IDLType"; + + my $name = $type->name; + + die "GetDictionaryByType() was called with an undefined dictionary name" unless defined($name); + + for my $dictionary (@{$useDocument->dictionaries}) { + return $dictionary if $dictionary->type->name eq $name; + } - return 1 if exists $svgTypeNeedingTearOff{$type}; + return $cachedExternalDictionaries->{$name} if exists($cachedExternalDictionaries->{$name}); + + # Find the IDL file associated with the dictionary. + my $filename = $object->IDLFileForInterface($name) or return; + + # Do a fast check to see if it seems to contain a dictionary. + my $fileContents = slurp($filename); + + if ($fileContents =~ /\bdictionary\s+$name/gs) { + # Parse the IDL. + my $parser = IDLParser->new(1); + my $document = $parser->Parse($filename, $defines, $preprocessor); + + foreach my $dictionary (@{$document->dictionaries}) { + next unless $dictionary->type->name eq $name; + + $cachedExternalDictionaries->{$name} = $dictionary; + my $implementedAs = $dictionary->extendedAttributes->{ImplementedAs}; + $dictionaryTypeImplementationNameOverrides{$dictionary->type->name} = $implementedAs if $implementedAs; + return $dictionary; + } + } + $cachedExternalDictionaries->{$name} = undef; +} + +sub IsDictionaryType +{ + my ($object, $type) = @_; + + assert("Not a type") if ref($type) ne "IDLType"; + + return $type->name =~ /^[A-Z]/ && defined($object->GetDictionaryByType($type)); +} + +# A dictionary defined in its own IDL file. +sub IsExternalDictionaryType +{ + my ($object, $type) = @_; + + assert("Not a type") if ref($type) ne "IDLType"; + + return $object->IsDictionaryType($type) && defined($cachedExternalDictionaries->{$type->name}); +} + +sub HasDictionaryImplementationNameOverride +{ + my ($object, $type) = @_; + + assert("Not a type") if ref($type) ne "IDLType"; + + return 1 if exists $dictionaryTypeImplementationNameOverrides{$type->name}; return 0; } -sub IsSVGTypeWithWritablePropertiesNeedingTearOff +sub GetDictionaryImplementationNameOverride { - my $object = shift; - my $type = shift; + my ($object, $type) = @_; + + assert("Not a type") if ref($type) ne "IDLType"; + + return $dictionaryTypeImplementationNameOverrides{$type->name}; +} - return 1 if $svgTypeWithWritablePropertiesNeedingTearOff{$type}; +sub IsNonPointerType +{ + my ($object, $type) = @_; + + assert("Not a type") if ref($type) ne "IDLType"; + + return 1 if $object->IsPrimitiveType($type); return 0; } sub IsTypedArrayType { - my $object = shift; - my $type = shift; - return 1 if (($type eq "ArrayBuffer") or ($type eq "ArrayBufferView")); - return 1 if (($type eq "Uint8Array") or ($type eq "Uint8ClampedArray") or ($type eq "Uint16Array") or ($type eq "Uint32Array")); - return 1 if (($type eq "Int8Array") or ($type eq "Int16Array") or ($type eq "Int32Array")); - return 1 if (($type eq "Float32Array") or ($type eq "Float64Array") or ($type eq "DataView")); + my ($object, $type) = @_; + + assert("Not a type") if ref($type) ne "IDLType"; + + return 1 if $typedArrayTypes{$type->name}; return 0; } sub IsRefPtrType { - my $object = shift; - my $type = shift; + my ($object, $type) = @_; + + assert("Not a type") if ref($type) ne "IDLType"; return 0 if $object->IsPrimitiveType($type); - return 0 if $object->GetArrayType($type); - return 0 if $object->GetSequenceType($type); - return 0 if $type eq "DOMString"; + return 0 if $object->IsDictionaryType($type); return 0 if $object->IsEnumType($type); + return 0 if $object->IsSequenceOrFrozenArrayType($type); + return 0 if $object->IsRecordType($type); + return 0 if $object->IsStringType($type); + return 0 if $type->isUnion; + return 0 if $type->name eq "any"; + return 0 if $type->name eq "object"; return 1; } -sub GetSVGTypeNeedingTearOff +sub IsSVGAnimatedTypeName { - my $object = shift; - my $type = shift; + my ($object, $typeName) = @_; - return $svgTypeNeedingTearOff{$type} if exists $svgTypeNeedingTearOff{$type}; - return undef; + return $typeName =~ /^SVGAnimated/; } -sub GetSVGWrappedTypeNeedingTearOff +sub IsSVGAnimatedType { - my $object = shift; - my $type = shift; + my ($object, $type) = @_; + + assert("Not a type") if ref($type) ne "IDLType"; - my $svgTypeNeedingTearOff = $object->GetSVGTypeNeedingTearOff($type); - return $svgTypeNeedingTearOff if not $svgTypeNeedingTearOff; + return $object->IsSVGAnimatedTypeName($type->name); +} - if ($svgTypeNeedingTearOff =~ /SVGPropertyTearOff/) { - $svgTypeNeedingTearOff =~ s/SVGPropertyTearOff<//; - } elsif ($svgTypeNeedingTearOff =~ /SVGListPropertyTearOff/) { - $svgTypeNeedingTearOff =~ s/SVGListPropertyTearOff<//; - } elsif ($svgTypeNeedingTearOff =~ /SVGStaticListPropertyTearOff/) { - $svgTypeNeedingTearOff =~ s/SVGStaticListPropertyTearOff<//; - } elsif ($svgTypeNeedingTearOff =~ /SVGTransformListPropertyTearOff/) { - $svgTypeNeedingTearOff =~ s/SVGTransformListPropertyTearOff<//; - } +sub IsConstructorType +{ + my ($object, $type) = @_; - $svgTypeNeedingTearOff =~ s/>//; - return $svgTypeNeedingTearOff; + assert("Not a type") if ref($type) ne "IDLType"; + + return $type->name =~ /Constructor$/; } -sub IsSVGAnimatedType +sub IsSequenceType { - my $object = shift; - my $type = shift; + my ($object, $type) = @_; + + assert("Not a type") if ref($type) ne "IDLType"; - return $type =~ /^SVGAnimated/; + return $type->name eq "sequence"; } -sub GetSequenceType +sub IsFrozenArrayType { - my $object = shift; - my $type = shift; + my ($object, $type) = @_; + + assert("Not a type") if ref($type) ne "IDLType"; - return $1 if $type =~ /^sequence<([\w\d_\s]+)>.*/; - return ""; + return $type->name eq "FrozenArray"; } -sub GetArrayType +sub IsSequenceOrFrozenArrayType { - my $object = shift; - my $type = shift; + my ($object, $type) = @_; + + assert("Not a type") if ref($type) ne "IDLType"; - return $1 if $type =~ /^([\w\d_\s]+)\[\]/; - return ""; + return $object->IsSequenceType($type) || $object->IsFrozenArrayType($type); } -sub AssertNotSequenceType +sub IsRecordType { - my $object = shift; - my $type = shift; - die "Sequences must not be used as the type of an attribute, constant or exception field." if $object->GetSequenceType($type); + my ($object, $type) = @_; + + assert("Not a type") if ref($type) ne "IDLType"; + + return $type->name eq "record"; } +# These match WK_lcfirst and WK_ucfirst defined in builtins_generator.py. # Uppercase the first letter while respecting WebKit style guidelines. # E.g., xmlEncoding becomes XMLEncoding, but xmlllang becomes Xmllang. sub WK_ucfirst { my ($object, $param) = @_; + my $ret = ucfirst($param); $ret =~ s/Xml/XML/ if $ret =~ /^Xml[^a-z]/; $ret =~ s/Svg/SVG/ if $ret =~ /^Svg/; @@ -473,13 +705,16 @@ sub WK_ucfirst sub WK_lcfirst { my ($object, $param) = @_; + my $ret = lcfirst($param); + $ret =~ s/dOM/dom/ if $ret =~ /^dOM/; $ret =~ s/hTML/html/ if $ret =~ /^hTML/; $ret =~ s/uRL/url/ if $ret =~ /^uRL/; $ret =~ s/jS/js/ if $ret =~ /^jS/; $ret =~ s/xML/xml/ if $ret =~ /^xML/; $ret =~ s/xSLT/xslt/ if $ret =~ /^xSLT/; $ret =~ s/cSS/css/ if $ret =~ /^cSS/; + $ret =~ s/rTC/rtc/ if $ret =~ /^rTC/; # For HTML5 FileSystem API Flags attributes. # (create is widely used to instantiate an object and must be avoided.) @@ -489,10 +724,30 @@ sub WK_lcfirst return $ret; } +sub slurp +{ + my $file = shift; + + open my $fh, '<', $file or die; + local $/ = undef; + my $content = <$fh>; + close $fh; + return $content; +} + +sub trim +{ + my $string = shift; + + $string =~ s/^\s+|\s+$//g; + return $string; +} + # Return the C++ namespace that a given attribute name string is defined in. sub NamespaceForAttributeName { my ($object, $interfaceName, $attributeName) = @_; + return "SVGNames" if $interfaceName =~ /^SVG/ && !$svgAttributesInHTMLHash{$attributeName}; return "HTMLNames"; } @@ -505,23 +760,30 @@ sub LinkOverloadedFunctions my %nameToFunctionsMap = (); foreach my $function (@{$interface->functions}) { - my $name = $function->signature->name; + my $name = $function->name; $nameToFunctionsMap{$name} = [] if !exists $nameToFunctionsMap{$name}; push(@{$nameToFunctionsMap{$name}}, $function); $function->{overloads} = $nameToFunctionsMap{$name}; $function->{overloadIndex} = @{$nameToFunctionsMap{$name}}; } + + my $index = 1; + foreach my $constructor (@{$interface->constructors}) { + $constructor->{overloads} = $interface->constructors; + $constructor->{overloadIndex} = $index; + $index++; + } } sub AttributeNameForGetterAndSetter { my ($generator, $attribute) = @_; - my $attributeName = $attribute->signature->name; - if ($attribute->signature->extendedAttributes->{"ImplementedAs"}) { - $attributeName = $attribute->signature->extendedAttributes->{"ImplementedAs"}; + my $attributeName = $attribute->name; + if ($attribute->extendedAttributes->{"ImplementedAs"}) { + $attributeName = $attribute->extendedAttributes->{"ImplementedAs"}; } - my $attributeType = $attribute->signature->type; + my $attributeType = $attribute->type; # SVG animated types need to use a special attribute name. # The rest of the special casing for SVG animated types is handled in the language-specific code generators. @@ -534,7 +796,7 @@ sub ContentAttributeName { my ($generator, $implIncludes, $interfaceName, $attribute) = @_; - my $contentAttributeName = $attribute->signature->extendedAttributes->{"Reflect"}; + my $contentAttributeName = $attribute->extendedAttributes->{"Reflect"}; return undef if !$contentAttributeName; $contentAttributeName = lc $generator->AttributeNameForGetterAndSetter($attribute) if $contentAttributeName eq "VALUE_IS_MISSING"; @@ -555,16 +817,16 @@ sub GetterExpression return ($generator->WK_lcfirst($generator->AttributeNameForGetterAndSetter($attribute))); } - my $attributeType = $attribute->signature->type; + my $attributeType = $attribute->type; my $functionName; - if ($attribute->signature->extendedAttributes->{"URL"}) { + if ($attribute->extendedAttributes->{"URL"}) { $functionName = "getURLAttribute"; - } elsif ($attributeType eq "boolean") { - $functionName = "fastHasAttribute"; - } elsif ($attributeType eq "long") { + } elsif ($attributeType->name eq "boolean") { + $functionName = "hasAttributeWithoutSynchronization"; + } elsif ($attributeType->name eq "long") { $functionName = "getIntegralAttribute"; - } elsif ($attributeType eq "unsigned long") { + } elsif ($attributeType->name eq "unsigned long") { $functionName = "getUnsignedIntegralAttribute"; } else { if ($contentAttributeName eq "WebCore::HTMLNames::idAttr") { @@ -576,7 +838,7 @@ sub GetterExpression } elsif ($generator->IsSVGAnimatedType($attributeType)) { $functionName = "getAttribute"; } else { - $functionName = "fastGetAttribute"; + $functionName = "attributeWithoutSynchronization"; } } @@ -593,74 +855,209 @@ sub SetterExpression return ("set" . $generator->WK_ucfirst($generator->AttributeNameForGetterAndSetter($attribute))); } + my $attributeType = $attribute->type; + my $functionName; - if ($attribute->signature->type eq "boolean") { + if ($attributeType->name eq "boolean") { $functionName = "setBooleanAttribute"; - } elsif ($attribute->signature->type eq "long") { + } elsif ($attributeType->name eq "long") { $functionName = "setIntegralAttribute"; - } elsif ($attribute->signature->type eq "unsigned long") { + } elsif ($attributeType->name eq "unsigned long") { $functionName = "setUnsignedIntegralAttribute"; - } else { + } elsif ($generator->IsSVGAnimatedType($attributeType)) { $functionName = "setAttribute"; + } else { + $functionName = "setAttributeWithoutSynchronization"; } return ($functionName, $contentAttributeName); } -sub IsWrapperType +sub IsBuiltinType { - my $object = shift; - my $type = shift; + my ($object, $type) = @_; - return 0 if $object->IsPrimitiveType($type); - return 0 if $object->GetArrayType($type); - return 0 if $object->GetSequenceType($type); + assert("Not a type") if ref($type) ne "IDLType"; + + return 1 if $object->IsPrimitiveType($type); + return 1 if $object->IsSequenceOrFrozenArrayType($type); + return 1 if $object->IsRecordType($type); + return 1 if $object->IsStringType($type); + return 1 if $object->IsTypedArrayType($type); + return 1 if $type->isUnion; + return 1 if $type->name eq "BufferSource"; + return 1 if $type->name eq "EventListener"; + return 1 if $type->name eq "JSON"; + return 1 if $type->name eq "Promise"; + return 1 if $type->name eq "SerializedScriptValue"; + return 1 if $type->name eq "XPathNSResolver"; + return 1 if $type->name eq "any"; + return 1 if $type->name eq "object"; + + return 0; +} + +sub IsInterfaceType +{ + my ($object, $type) = @_; + + assert("Not a type") if ref($type) ne "IDLType"; + + return 0 if $object->IsBuiltinType($type); + return 0 if $object->IsDictionaryType($type); return 0 if $object->IsEnumType($type); - return 0 if $object->IsStringType($type); - return 0 if $object->IsTypedArrayType($type); - return 0 if $webCoreTypeHash{$type}; - return 0 if $type eq "any"; return 1; } -sub IsCallbackInterface +sub IsWrapperType { - my $object = shift; - my $type = shift; + my ($object, $type) = @_; - return 0 unless $object->IsWrapperType($type); + assert("Not a type") if ref($type) ne "IDLType"; - my $idlFile = $object->IDLFileForInterface($type) - or die("Could NOT find IDL file for interface \"$type\"!\n"); + return 1 if $object->IsInterfaceType($type); + return 1 if $type->name eq "XPathNSResolver"; - open FILE, "<", $idlFile; - my @lines = <FILE>; - close FILE; + return 0; +} + +sub IsSerializableAttribute +{ + my ($object, $currentInterface, $attribute) = @_; + + # https://heycam.github.io/webidl/#dfn-serializable-type + + my $type = $attribute->type; + return 1 if $type->name eq "boolean"; + return 1 if $object->IsNumericType($type); + return 1 if $object->IsEnumType($type); + return 1 if $object->IsStringType($type); + return 0 if $type->name eq "EventHandler"; + + if ($type->isUnion || $object->IsSequenceType($type) || $object->IsDictionaryType($type)) { + die "Serializer for non-primitive types is not currently supported\n"; + } - my $fileContents = join('', @lines); - return ($fileContents =~ /callback\s+interface\s+(\w+)/gs); + my $interface = GetInterfaceForAttribute($object, $currentInterface, $attribute); + if ($interface && $interface->serializable) { + die "Serializer for non-primitive types is not currently supported\n"; + } + + return 0; } -sub GenerateConditionalString +sub GetInterfaceExtendedAttributesFromName { - my $generator = shift; - my $node = shift; + # FIXME: It's bad to have a function like this that opens another IDL file to answer a question. + # Overusing this kind of function can make things really slow. Lets avoid these if we can. - my $conditional = $node->extendedAttributes->{"Conditional"}; - if ($conditional) { - return $generator->GenerateConditionalStringFromAttributeValue($conditional); - } else { - return ""; + my ($object, $interfaceName) = @_; + + my $idlFile = $object->IDLFileForInterface($interfaceName) or assert("Could NOT find IDL file for interface \"$interfaceName\"!\n"); + + open FILE, "<", $idlFile or die; + my @lines = <FILE>; + close FILE; + + my $fileContents = join('', @lines); + + my $extendedAttributes = {}; + + if ($fileContents =~ /\[(.*)\]\s+(callback interface|interface|exception)\s+(\w+)/gs) { + my @parts = split(',', $1); + foreach my $part (@parts) { + my @keyValue = split('=', $part); + my $key = trim($keyValue[0]); + next unless length($key); + my $value = "VALUE_IS_MISSING"; + $value = trim($keyValue[1]) if @keyValue > 1; + $extendedAttributes->{$key} = $value; + } } + + return $extendedAttributes; +} + +sub ComputeIsCallbackInterface +{ + my ($object, $type) = @_; + + assert("Not a type") if ref($type) ne "IDLType"; + + return 0 unless $object->IsInterfaceType($type); + + my $typeName = $type->name; + my $idlFile = $object->IDLFileForInterface($typeName) or assert("Could NOT find IDL file for interface \"$typeName\"!\n"); + + open FILE, "<", $idlFile or die; + my @lines = <FILE>; + close FILE; + + my $fileContents = join('', @lines); + return ($fileContents =~ /callback\s+interface\s+(\w+)/gs); +} + +my %isCallbackInterface = (); + +sub IsCallbackInterface +{ + # FIXME: It's bad to have a function like this that opens another IDL file to answer a question. + # Overusing this kind of function can make things really slow. Lets avoid these if we can. + # To mitigate that, lets cache what we learn in a hash so we don't open the same file over and over. + + my ($object, $type) = @_; + + assert("Not a type") if ref($type) ne "IDLType"; + + return $isCallbackInterface{$type->name} if exists $isCallbackInterface{$type->name}; + my $result = $object->ComputeIsCallbackInterface($type); + $isCallbackInterface{$type->name} = $result; + return $result; } -sub GenerateConstructorConditionalString +sub ComputeIsCallbackFunction { - my $generator = shift; - my $node = shift; + my ($object, $type) = @_; + + assert("Not a type") if ref($type) ne "IDLType"; + + return 0 unless $object->IsInterfaceType($type); + + my $typeName = $type->name; + my $idlFile = $object->IDLFileForInterface($typeName) or assert("Could NOT find IDL file for interface \"$typeName\"!\n"); + + open FILE, "<", $idlFile or die; + my @lines = <FILE>; + close FILE; + + my $fileContents = join('', @lines); + return ($fileContents =~ /(.*)callback\s+(\w+)\s+=/gs); +} + +my %isCallbackFunction = (); + +sub IsCallbackFunction +{ + # FIXME: It's bad to have a function like this that opens another IDL file to answer a question. + # Overusing this kind of function can make things really slow. Lets avoid these if we can. + # To mitigate that, lets cache what we learn in a hash so we don't open the same file over and over. + + my ($object, $type) = @_; - my $conditional = $node->extendedAttributes->{"ConstructorConditional"}; + assert("Not a type") if ref($type) ne "IDLType"; + + return $isCallbackFunction{$type->name} if exists $isCallbackFunction{$type->name}; + my $result = $object->ComputeIsCallbackFunction($type); + $isCallbackFunction{$type->name} = $result; + return $result; +} + +sub GenerateConditionalString +{ + my ($generator, $node) = @_; + + my $conditional = $node->extendedAttributes->{"Conditional"}; if ($conditional) { return $generator->GenerateConditionalStringFromAttributeValue($conditional); } else { @@ -670,51 +1067,49 @@ sub GenerateConstructorConditionalString sub GenerateConditionalStringFromAttributeValue { - my $generator = shift; - my $conditional = shift; - - my $operator = ($conditional =~ /&/ ? '&' : ($conditional =~ /\|/ ? '|' : '')); - if ($operator) { - # Avoid duplicated conditions. - my %conditions; - map { $conditions{$_} = 1 } split('\\' . $operator, $conditional); - return "ENABLE(" . join(") $operator$operator ENABLE(", sort keys %conditions) . ")"; - } else { - return "ENABLE(" . $conditional . ")"; - } + my ($generator, $conditional) = @_; + + my %disjunction; + map { + my $expression = $_; + my %conjunction; + map { $conjunction{$_} = 1; } split(/&/, $expression); + $expression = "ENABLE(" . join(") && ENABLE(", sort keys %conjunction) . ")"; + $disjunction{$expression} = 1 + } split(/\|/, $conditional); + + return "1" if keys %disjunction == 0; + return (%disjunction)[0] if keys %disjunction == 1; + + my @parenthesized; + map { + my $expression = $_; + $expression = "($expression)" if $expression =~ / /; + push @parenthesized, $expression; + } sort keys %disjunction; + + return join(" || ", @parenthesized); } sub GenerateCompileTimeCheckForEnumsIfNeeded { my ($generator, $interface) = @_; - my $interfaceName = $interface->name; - my @checks = (); - # If necessary, check that all constants are available as enums with the same value. - if (!$interface->extendedAttributes->{"DoNotCheckConstants"} && @{$interface->constants}) { - push(@checks, "\n"); - foreach my $constant (@{$interface->constants}) { - my $reflect = $constant->extendedAttributes->{"Reflect"}; - my $name = $reflect ? $reflect : $constant->name; - my $value = $constant->value; - my $conditional = $constant->extendedAttributes->{"Conditional"}; - - if ($conditional) { - my $conditionalString = $generator->GenerateConditionalStringFromAttributeValue($conditional); - push(@checks, "#if ${conditionalString}\n"); - } - if ($constant->extendedAttributes->{"ImplementedBy"}) { - push(@checks, "COMPILE_ASSERT($value == " . $constant->extendedAttributes->{"ImplementedBy"} . "::$name, ${interfaceName}Enum${name}IsWrongUseDoNotCheckConstants);\n"); - } else { - push(@checks, "COMPILE_ASSERT($value == ${interfaceName}::$name, ${interfaceName}Enum${name}IsWrongUseDoNotCheckConstants);\n"); - } + return () if $interface->extendedAttributes->{"DoNotCheckConstants"} || !@{$interface->constants}; - if ($conditional) { - push(@checks, "#endif\n"); - } - } - push(@checks, "\n"); + my $baseScope = $interface->extendedAttributes->{"ConstantsScope"} || $interface->type->name; + + my @checks = (); + foreach my $constant (@{$interface->constants}) { + my $scope = $constant->extendedAttributes->{"ImplementedBy"} || $baseScope; + my $name = $constant->extendedAttributes->{"Reflect"} || $constant->name; + my $value = $constant->value; + my $conditional = $constant->extendedAttributes->{"Conditional"}; + push(@checks, "#if " . $generator->GenerateConditionalStringFromAttributeValue($conditional) . "\n") if $conditional; + push(@checks, "static_assert(${scope}::${name} == ${value}, \"${name} in ${scope} does not match value from IDL\");\n"); + push(@checks, "#endif\n") if $conditional; } + push(@checks, "\n"); return @checks; } @@ -733,23 +1128,22 @@ sub ExtendedAttributeContains # should use the real interface name in the IDL files and then use ImplementedAs to map this to the implementation name. sub GetVisibleInterfaceName { - my $object = shift; - my $interface = shift; + my ($object, $interface) = @_; + my $interfaceName = $interface->extendedAttributes->{"InterfaceName"}; - return $interfaceName ? $interfaceName : $interface->name; + return $interfaceName ? $interfaceName : $interface->type->name; } sub InheritsInterface { - my $object = shift; - my $interface = shift; - my $interfaceName = shift; - my $found = 0; + my ($object, $interface, $interfaceName) = @_; - return 1 if $interfaceName eq $interface->name; + return 1 if $interfaceName eq $interface->type->name; + + my $found = 0; $object->ForAllParents($interface, sub { my $currentInterface = shift; - if ($currentInterface->name eq $interfaceName) { + if ($currentInterface->type->name eq $interfaceName) { $found = 1; } return 1 if $found; @@ -760,12 +1154,11 @@ sub InheritsInterface sub InheritsExtendedAttribute { - my $object = shift; - my $interface = shift; - my $extendedAttribute = shift; - my $found = 0; + my ($object, $interface, $extendedAttribute) = @_; return 1 if $interface->extendedAttributes->{$extendedAttribute}; + + my $found = 0; $object->ForAllParents($interface, sub { my $currentInterface = shift; if ($currentInterface->extendedAttributes->{$extendedAttribute}) { @@ -777,4 +1170,5 @@ sub InheritsExtendedAttribute return $found; } + 1; diff --git a/Source/WebCore/bindings/scripts/CodeGeneratorGObject.pm b/Source/WebCore/bindings/scripts/CodeGeneratorGObject.pm deleted file mode 100644 index b5b1d8e43..000000000 --- a/Source/WebCore/bindings/scripts/CodeGeneratorGObject.pm +++ /dev/null @@ -1,1694 +0,0 @@ -# Copyright (C) 2008 Luke Kenneth Casson Leighton <lkcl@lkcl.net> -# Copyright (C) 2008 Martin Soto <soto@freedesktop.org> -# Copyright (C) 2008 Alp Toker <alp@atoker.com> -# Copyright (C) 2009 Adam Dingle <adam@yorba.org> -# Copyright (C) 2009 Jim Nelson <jim@yorba.org> -# Copyright (C) 2009, 2010 Igalia S.L. -# -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Library 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 -# Library General Public License for more details. -# -# You should have received a copy of the GNU Library General Public License -# along with this library; see the file COPYING.LIB. If not, write to -# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, -# Boston, MA 02111-1307, USA. - -package CodeGeneratorGObject; - -use constant FileNamePrefix => "WebKitDOM"; - -# Global Variables -my %implIncludes = (); -my %hdrIncludes = (); - -my $defineTypeMacro = "G_DEFINE_TYPE"; -my $defineTypeInterfaceImplementation = ")"; -my @txtEventListeners = (); -my @txtInstallProps = (); -my @txtSetProps = (); -my @txtGetProps = (); - -my $className = ""; - -# FIXME: this should be replaced with a function that recurses up the tree -# to find the actual base type. -my %baseTypeHash = ("Object" => 1, "Node" => 1, "NodeList" => 1, "NamedNodeMap" => 1, "DOMImplementation" => 1, - "Event" => 1, "CSSRule" => 1, "CSSValue" => 1, "StyleSheet" => 1, "MediaList" => 1, - "Counter" => 1, "Rect" => 1, "RGBColor" => 1, "XPathExpression" => 1, "XPathResult" => 1, - "NodeIterator" => 1, "TreeWalker" => 1, "AbstractView" => 1, "Blob" => 1, "DOMTokenList" => 1, - "HTMLCollection" => 1); - -# Only objects derived from Node are released by the DOM object cache and can be -# transfer none. Ideally we could use GetBaseClass with the parent type to check -# whether it's Node, but unfortunately we only have the name of the return type, -# and we can't know its parent base class. Since there are fewer classes in the -# API that are not derived from Node, we will list them here to decide the -# transfer type. -my %transferFullTypeHash = ("AudioTrack" => 1, "AudioTrackList" => 1, "BarProp" => 1, "BatteryManager" => 1, - "CSSRuleList" => 1, "CSSStyleDeclaration" => 1, "CSSStyleSheet" => 1, - "DOMApplicationCache" => 1, "DOMMimeType" => 1, "DOMMimeTypeArray" => 1, "DOMNamedFlowCollection" => 1, - "DOMPlugin" => 1, "DOMPluginArray" => 1, "DOMSecurityPolicy" => 1, - "DOMSelection" => 1, "DOMSettableTokenList" => 1, "DOMStringList" => 1, - "DOMWindow" => 1, "DOMWindowCSS" => 1, "EventTarget" => 1, - "File" => 1, "FileList" => 1, "Gamepad" => 1, "GamepadList" => 1, - "Geolocation" => 1, "HTMLOptionsCollection" => 1, "History" => 1, - "KeyboardEvent" => 1, "MediaError" => 1, "MediaController" => 1, - "MouseEvent" => 1, "MediaQueryList" => 1, "Navigator" => 1, "NodeFilter" => 1, - "Performance" => 1, "PerformanceEntry" => 1, "PerformanceEntryList" => 1, "PerformanceNavigation" => 1, "PerformanceTiming" => 1, - "Range" => 1, "Screen" => 1, "SpeechSynthesis" => 1, "SpeechSynthesisVoice" => 1, - "Storage" => 1, "StyleMedia" => 1, "TextTrack" => 1, "TextTrackCueList" => 1, - "TimeRanges" => 1, "Touch" => 1, "UIEvent" => 1, "UserMessageHandler" => 1, "UserMessageHandlersNamespace" => 1, - "ValidityState" => 1, "VideoTrack" => 1, "WebKitNamedFlow" => 1, - "WebKitNamespace" => 1, "WebKitPoint" => 1, "WheelEvent" => 1, "XPathNSResolver" => 1); - -# List of function parameters that are allowed to be NULL -my $canBeNullParams = { - 'webkit_dom_document_create_attribute_ns' => ['namespaceURI'], - 'webkit_dom_document_create_element_ns' => ['namespaceURI'], - 'webkit_dom_document_create_entity_reference' => ['name'], - 'webkit_dom_document_evaluate' => ['inResult', 'resolver'], - 'webkit_dom_document_get_override_style' => ['pseudoElement'], - 'webkit_dom_dom_implementation_create_document' => ['namespaceURI', 'doctype'], - 'webkit_dom_dom_window_get_computed_style' => ['pseudoElement'], - 'webkit_dom_element_set_attribute_ns' => ['namespaceURI'], - 'webkit_dom_node_insert_before' => ['refChild'], -}; - -# Default constructor -sub new { - my $object = shift; - my $reference = { }; - - $codeGenerator = shift; - - bless($reference, $object); -} - -my $licenceTemplate = << "EOF"; -/* - * This file is part of the WebKit open source project. - * This file has been generated by generate-bindings.pl. DO NOT MODIFY! - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public License - * along with this library; see the file COPYING.LIB. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ -EOF - -sub GetParentClassName { - my $interface = shift; - - return "WebKitDOMObject" unless $interface->parent; - return "WebKitDOM" . $interface->parent; -} - -sub GetParentImplClassName { - my $interface = shift; - - return "Object" unless $interface->parent; - return $interface->parent; -} - -sub IsBaseType -{ - my $type = shift; - - return 1 if $baseTypeHash{$type}; - return 0; -} - -sub GetBaseClass -{ - $parent = shift; - $interface = shift; - - return $parent if $parent eq "Object" or IsBaseType($parent); - return "Event" if $codeGenerator->InheritsInterface($interface, "Event"); - return "CSSValue" if $parent eq "SVGColor" or $parent eq "CSSValueList"; - return "Node"; -} - - -# From String::CamelCase 0.01 -sub camelize -{ - my $s = shift; - join('', map{ ucfirst $_ } split(/(?<=[A-Za-z])_(?=[A-Za-z])|\b/, $s)); -} - -sub decamelize -{ - my $s = shift; - $s =~ s{([^a-zA-Z]?)([A-Z]*)([A-Z])([a-z]?)}{ - my $fc = pos($s)==0; - my ($p0,$p1,$p2,$p3) = ($1,lc$2,lc$3,$4); - my $t = $p0 || $fc ? $p0 : '_'; - $t .= $p3 ? $p1 ? "${p1}_$p2$p3" : "$p2$p3" : "$p1$p2"; - $t; - }ge; - - # Some strings are not correctly decamelized, apply fix ups - for ($s) { - s/domcss/dom_css/; - s/domhtml/dom_html/; - s/domdom/dom_dom/; - s/domcdata/dom_cdata/; - s/domui/dom_ui/; - s/x_path/xpath/; - s/web_kit/webkit/; - s/htmli_frame/html_iframe/; - } - return $s; -} - -sub HumanReadableConditional { - my @conditional = split('_', shift); - my @upperCaseExceptions = ("SQL", "API"); - my @humanReadable; - - for $part (@conditional) { - if (!grep {$_ eq $part} @upperCaseExceptions) { - $part = camelize(lc($part)); - } - push(@humanReadable, $part); - } - - return join(' ', @humanReadable); -} - -sub GetParentGObjType { - my $interface = shift; - - return "WEBKIT_TYPE_DOM_OBJECT" unless $interface->parent; - return "WEBKIT_TYPE_DOM_" . uc(decamelize(($interface->parent))); -} - -sub GetClassName { - my $name = shift; - - return "WebKitDOM$name"; -} - -sub GetCoreObject { - my ($interfaceName, $name, $parameter) = @_; - - return "WebCore::${interfaceName}* $name = WebKit::core($parameter);"; -} - -sub SkipAttribute { - my $attribute = shift; - - if ($attribute->signature->extendedAttributes->{"Custom"} - || $attribute->signature->extendedAttributes->{"CustomGetter"}) { - return 1; - } - - my $propType = $attribute->signature->type; - if ($propType =~ /Constructor$/) { - return 1; - } - - return 1 if $attribute->isStatic; - return 1 if $codeGenerator->IsTypedArrayType($propType); - - $codeGenerator->AssertNotSequenceType($propType); - - if ($codeGenerator->GetArrayType($propType)) { - return 1; - } - - if ($codeGenerator->IsEnumType($propType)) { - return 1; - } - - # This is for DOMWindow.idl location attribute - if ($attribute->signature->name eq "location") { - return 1; - } - - # This is for HTMLInput.idl valueAsDate - if ($attribute->signature->name eq "valueAsDate") { - return 1; - } - - # This is for DOMWindow.idl Crypto attribute - if ($attribute->signature->type eq "Crypto") { - return 1; - } - - if ($attribute->signature->type eq "EventListener") { - return 1; - } - - if ($attribute->signature->type eq "MediaQueryListListener") { - return 1; - } - - # Skip indexed database attributes for now, they aren't yet supported for the GObject generator. - if ($attribute->signature->name =~ /^(?:webkit)?[Ii]ndexedDB/ or $attribute->signature->name =~ /^(?:webkit)?IDB/) { - return 1; - } - - return 0; -} - -sub SkipFunction { - my $object = shift; - my $function = shift; - my $parentNode = shift; - my $decamelize = shift; - my $prefix = shift; - - my $functionName = "webkit_dom_" . $decamelize . "_" . $prefix . decamelize($function->signature->name); - my $functionReturnType = $prefix eq "set_" ? "void" : $function->signature->type; - my $isCustomFunction = $function->signature->extendedAttributes->{"Custom"}; - my $callWith = $function->signature->extendedAttributes->{"CallWith"}; - my $isUnsupportedCallWith = $codeGenerator->ExtendedAttributeContains($callWith, "ScriptArguments") || $codeGenerator->ExtendedAttributeContains($callWith, "CallStack"); - - if (($isCustomFunction || $isUnsupportedCallWith) && - $functionName ne "webkit_dom_node_replace_child" && - $functionName ne "webkit_dom_node_insert_before" && - $functionName ne "webkit_dom_node_remove_child" && - $functionName ne "webkit_dom_node_append_child" && - $functionName ne "webkit_dom_html_collection_item" && - $functionName ne "webkit_dom_html_collection_named_item") { - return 1; - } - - # Skip functions that have callback parameters, because this code generator doesn't know - # how to auto-generate callbacks. Skip functions that have "MediaQueryListListener" or - # sequence<T> parameters, because this code generator doesn't know how to auto-generate - # MediaQueryListListener or sequence<T>. Skip EventListeners because they are handled elsewhere. - foreach my $param (@{$function->parameters}) { - if ($codeGenerator->IsCallbackInterface($param->type) || - $param->extendedAttributes->{"Clamp"} || - $param->type eq "MediaQueryListListener" || - $param->type eq "EventListener" || - $codeGenerator->GetSequenceType($param->type)) { - return 1; - } - } - - # Skip functions for which we have a custom implementation due to API breaks - if ($functionName eq "webkit_dom_html_media_element_set_current_time") { - return 1; - } - - # This is for DataTransferItemList.idl add(File) method - if ($functionName eq "webkit_dom_data_transfer_item_list_add" && @{$function->parameters} == 1) { - return 1; - } - - # Skip dispatch_event methods, except the one already deprecated. - if ($parentNode->extendedAttributes->{"EventTarget"} && $function->signature->name eq "dispatchEvent" - && $functionName ne "webkit_dom_audio_track_list_dispatch_event" - && $functionName ne "webkit_dom_battery_manager_dispatch_event" - && $functionName ne "webkit_dom_dom_application_cache_dispatch_event" - && $functionName ne "webkit_dom_dom_window_dispatch_event" - && $functionName ne "webkit_dom_node_dispatch_event" - && $functionName ne "webkit_dom_text_track_cue_dispatch_event" - && $functionName ne "webkit_dom_text_track_dispatch_event" - && $functionName ne "webkit_dom_text_track_list_dispatch_event" - && $functionName ne "webkit_dom_video_track_list_dispatch_event" - && $functionName ne "webkit_dom_webkit_named_flow_dispatch_event" - && $functionName ne "webkit_dom_test_event_target_dispatch_event") { - return 1; - } - - # Skip Console::profile() and Console::profileEnd() as they're not correctly generated for the moment. - if ($functionName eq "webkit_dom_console_profile" || $functionName eq "webkit_dom_console_profile_end") { - return 1; - } - - if ($function->signature->name eq "set" and $parentNode->extendedAttributes->{"TypedArray"}) { - return 1; - } - - if ($object eq "MediaQueryListListener") { - return 1; - } - - if ($function->signature->name eq "getSVGDocument") { - return 1; - } - - if ($function->signature->name eq "getCSSCanvasContext") { - return 1; - } - - if ($function->signature->name eq "setRangeText" && @{$function->parameters} == 1) { - return 1; - } - - if ($function->signature->name eq "timeEnd") { - return 1; - } - - if ($codeGenerator->GetSequenceType($functionReturnType)) { - return 1; - } - - if ($function->signature->name eq "supports" && @{$function->parameters} == 1) { - return 1; - } - - return 0; -} - -# Name type used in the g_value_{set,get}_* functions -sub GetGValueTypeName { - my $type = shift; - - my %types = ("DOMString", "string", - "DOMTimeStamp", "uint", - "float", "float", - "double", "double", - "boolean", "boolean", - "char", "char", - "long", "long", - "long long", "int64", - "byte", "int8", - "octet", "uint8", - "short", "int", - "uchar", "uchar", - "unsigned", "uint", - "int", "int", - "unsigned int", "uint", - "unsigned long long", "uint64", - "unsigned long", "ulong", - "unsigned short", "uint"); - - return $types{$type} ? $types{$type} : "object"; -} - -# Name type used in C declarations -sub GetGlibTypeName { - my $type = shift; - my $name = GetClassName($type); - - my %types = ("DOMString", "gchar*", - "DOMTimeStamp", "guint32", - "CompareHow", "gushort", - "float", "gfloat", - "double", "gdouble", - "boolean", "gboolean", - "char", "gchar", - "long", "glong", - "long long", "gint64", - "byte", "gint8", - "octet", "guint8", - "short", "gshort", - "uchar", "guchar", - "unsigned", "guint", - "int", "gint", - "unsigned int", "guint", - "unsigned long", "gulong", - "unsigned long long", "guint64", - "unsigned short", "gushort", - "void", "void"); - - return $types{$type} ? $types{$type} : "$name*"; -} - -sub IsGDOMClassType { - my $type = shift; - - return 0 if $codeGenerator->IsNonPointerType($type) || $codeGenerator->IsStringType($type); - return 1; -} - -sub IsPropertyReadable { - my $property = shift; - return !SkipAttribute($property); -} - -sub IsPropertyWriteable { - my $property = shift; - - if (!IsPropertyReadable($property)) { - return 0; - } - - if ($property->isReadOnly) { - return 0; - } - - my $gtype = GetGValueTypeName($property->signature->type); - my $hasGtypeSignature = $gtype eq "boolean" || $gtype eq "float" || $gtype eq "double" || - $gtype eq "int64" || $gtype eq "uint64" || - $gtype eq "long" || $gtype eq "ulong" || - $gtype eq "int" || $gtype eq "uint" || - $gtype eq "short" || $gtype eq "ushort" || - $gtype eq "int8" || $gtype eq "uint8" || - $gtype eq "char" || $gtype eq "uchar" || - $gtype eq "string"; - if (!$hasGtypeSignature) { - return 0; - } - - # FIXME: We are not generating setters for 'Replaceable' attributes now, but we should somehow. - if ($property->signature->extendedAttributes->{"Replaceable"}) { - return 0; - } - - if ($property->signature->extendedAttributes->{"CustomSetter"}) { - return 0; - } - - return 1; -} - -sub GenerateConditionalWarning -{ - my $node = shift; - my $indentSize = shift; - if (!$indentSize) { - $indentSize = 4; - } - - my $conditional = $node->extendedAttributes->{"Conditional"}; - my @warn; - - if ($conditional) { - if ($conditional =~ /&/) { - my @splitConditionals = split(/&/, $conditional); - foreach $condition (@splitConditionals) { - push(@warn, "#if !ENABLE($condition)\n"); - push(@warn, ' ' x $indentSize . "WEBKIT_WARN_FEATURE_NOT_PRESENT(\"" . HumanReadableConditional($condition) . "\")\n"); - push(@warn, "#endif\n"); - } - } elsif ($conditional =~ /\|/) { - foreach $condition (split(/\|/, $conditional)) { - push(@warn, ' ' x $indentSize . "WEBKIT_WARN_FEATURE_NOT_PRESENT(\"" . HumanReadableConditional($condition) . "\")\n"); - } - } else { - push(@warn, ' ' x $indentSize . "WEBKIT_WARN_FEATURE_NOT_PRESENT(\"" . HumanReadableConditional($conditional) . "\")\n"); - } - } - - return @warn; -} - -sub GenerateProperty { - my $attribute = shift; - my $interfaceName = shift; - my @writeableProperties = @{shift @_}; - my $parentNode = shift; - - my $conditionalString = $codeGenerator->GenerateConditionalString($attribute->signature); - my @conditionalWarn = GenerateConditionalWarning($attribute->signature, 8); - my $parentConditionalString = $codeGenerator->GenerateConditionalString($parentNode); - my @parentConditionalWarn = GenerateConditionalWarning($parentNode, 8); - my $camelPropName = $attribute->signature->name; - my $setPropNameFunction = $codeGenerator->WK_ucfirst($camelPropName); - my $getPropNameFunction = $codeGenerator->WK_lcfirst($camelPropName); - my $hasGetterException = $attribute->signature->extendedAttributes->{"GetterRaisesException"}; - my $hasSetterException = $attribute->signature->extendedAttributes->{"SetterRaisesException"}; - - my $propName = decamelize($camelPropName); - my $propNameCaps = uc($propName); - $propName =~ s/_/-/g; - my ${propEnum} = "PROP_${propNameCaps}"; - push(@cBodyProperties, " ${propEnum},\n"); - - my $propType = $attribute->signature->type; - my ${propGType} = decamelize($propType); - my ${ucPropGType} = uc($propGType); - - my $gtype = GetGValueTypeName($propType); - my $gparamflag = "WEBKIT_PARAM_READABLE"; - my $writeable = IsPropertyWriteable($attribute); - - my $mutableString = "read-only"; - my $hasCustomSetter = $attribute->signature->extendedAttributes->{"CustomSetter"}; - if ($writeable && $hasCustomSetter) { - $mutableString = "read-only (due to custom functions needed in webkitdom)"; - } elsif ($writeable) { - $gparamflag = "WEBKIT_PARAM_READWRITE"; - $mutableString = "read-write"; - } - - my $convertFunction = ""; - if ($gtype eq "string") { - $convertFunction = "WTF::String::fromUTF8"; - } - - my ($getterFunctionName, @getterArguments) = $codeGenerator->GetterExpression(\%implIncludes, $interfaceName, $attribute); - my ($setterFunctionName, @setterArguments) = $codeGenerator->SetterExpression(\%implIncludes, $interfaceName, $attribute); - - if ($attribute->signature->extendedAttributes->{"ImplementedBy"}) { - my $implementedBy = $attribute->signature->extendedAttributes->{"ImplementedBy"}; - $implIncludes{"${implementedBy}.h"} = 1; - push(@setterArguments, "${convertFunction}(g_value_get_$gtype(value))"); - unshift(@getterArguments, "coreSelf"); - unshift(@setterArguments, "coreSelf"); - $getterFunctionName = "WebCore::${implementedBy}::$getterFunctionName"; - $setterFunctionName = "WebCore::${implementedBy}::$setterFunctionName"; - } else { - push(@setterArguments, "${convertFunction}(g_value_get_$gtype(value))"); - $getterFunctionName = "coreSelf->$getterFunctionName"; - $setterFunctionName = "coreSelf->$setterFunctionName"; - } - push(@getterArguments, "isNull") if $attribute->signature->isNullable; - push(@getterArguments, "ec") if $hasGetterException; - push(@setterArguments, "ec") if $hasSetterException; - - if (grep {$_ eq $attribute} @writeableProperties) { - push(@txtSetProps, " case ${propEnum}: {\n"); - push(@txtSetProps, "#if ${parentConditionalString}\n") if $parentConditionalString; - push(@txtSetProps, "#if ${conditionalString}\n") if $conditionalString; - push(@txtSetProps, " WebCore::ExceptionCode ec = 0;\n") if $hasSetterException; - push(@txtSetProps, " ${setterFunctionName}(" . join(", ", @setterArguments) . ");\n"); - push(@txtSetProps, "#else\n") if $conditionalString; - push(@txtSetProps, @conditionalWarn) if scalar(@conditionalWarn); - push(@txtSetProps, "#endif /* ${conditionalString} */\n") if $conditionalString; - push(@txtSetProps, "#else\n") if $parentConditionalString; - push(@txtSetProps, @parentConditionalWarn) if scalar(@parentConditionalWarn); - push(@txtSetProps, "#endif /* ${parentConditionalString} */\n") if $parentConditionalString; - push(@txtSetProps, " break;\n }\n"); - } - - push(@txtGetProps, " case ${propEnum}: {\n"); - push(@txtGetProps, "#if ${parentConditionalString}\n") if $parentConditionalString; - push(@txtGetProps, "#if ${conditionalString}\n") if $conditionalString; - push(@txtGetProps, " bool isNull = false;\n") if $attribute->signature->isNullable; - push(@txtGetProps, " WebCore::ExceptionCode ec = 0;\n") if $hasGetterException; - - # FIXME: Should we return a default value when isNull == true? - - my $postConvertFunction = ""; - if ($gtype eq "string") { - push(@txtGetProps, " g_value_take_string(value, convertToUTF8String(${getterFunctionName}(" . join(", ", @getterArguments) . ")));\n"); - } elsif ($gtype eq "object") { - push(@txtGetProps, " RefPtr<WebCore::${propType}> ptr = ${getterFunctionName}(" . join(", ", @getterArguments) . ");\n"); - push(@txtGetProps, " g_value_set_object(value, WebKit::kit(ptr.get()));\n"); - } else { - push(@txtGetProps, " g_value_set_$gtype(value, ${convertFunction}${getterFunctionName}(" . join(", ", @getterArguments) . ")${postConvertFunction});\n"); - } - - push(@txtGetProps, "#else\n") if $conditionalString; - push(@txtGetProps, @conditionalWarn) if scalar(@conditionalWarn); - push(@txtGetProps, "#endif /* ${conditionalString} */\n") if $conditionalString; - push(@txtGetProps, "#else\n") if $parentConditionalString; - push(@txtGetProps, @parentConditionalWarn) if scalar(@parentConditionalWarn); - push(@txtGetProps, "#endif /* ${parentConditionalString} */\n") if $parentConditionalString; - push(@txtGetProps, " break;\n }\n"); - - my %parameterSpecOptions = ("int" => [ "G_MININT", "G_MAXINT", "0" ], - "int8" => [ "G_MININT8", "G_MAXINT8", "0" ], - "boolean" => [ "FALSE" ], - "float" => [ "-G_MAXFLOAT", "G_MAXFLOAT", "0" ], - "double" => [ "-G_MAXDOUBLE", "G_MAXDOUBLE", "0" ], - "uint64" => [ "0", "G_MAXUINT64", "0" ], - "long" => [ "G_MINLONG", "G_MAXLONG", "0" ], - "int64" => [ "G_MININT64", "G_MAXINT64", "0" ], - "ulong" => [ "0", "G_MAXULONG", "0" ], - "uint" => [ "0", "G_MAXUINT", "0" ], - "uint8" => [ "0", "G_MAXUINT8", "0" ], - "ushort" => [ "0", "G_MAXUINT16", "0" ], - "uchar" => [ "G_MININT8", "G_MAXINT8", "0" ], - "char" => [ "0", "G_MAXUINT8", "0" ], - "string" => [ '""', ], - "object" => [ "WEBKIT_TYPE_DOM_${ucPropGType}" ]); - - my $extraParameters = join(", ", @{$parameterSpecOptions{$gtype}}); - my $glibTypeName = GetGlibTypeName($propType); - my $txtInstallProp = << "EOF"; - g_object_class_install_property( - gobjectClass, - $propEnum, - g_param_spec_$gtype( - "$propName", - "$interfaceName:$propName", - "$mutableString $glibTypeName $interfaceName:$propName", - $extraParameters, - $gparamflag)); - -EOF - push(@txtInstallProps, $txtInstallProp); -} - -sub GenerateProperties { - my ($object, $interfaceName, $interface) = @_; - - my $decamelize = decamelize($interfaceName); - my $clsCaps = uc($decamelize); - my $lowerCaseIfaceName = "webkit_dom_$decamelize"; - my $parentImplClassName = GetParentImplClassName($interface); - - my $conditionGuardStart = ""; - my $conditionGuardEnd = ""; - my $conditionalString = $codeGenerator->GenerateConditionalString($interface); - if ($conditionalString) { - $conditionGuardStart = "#if ${conditionalString}"; - $conditionGuardEnd = "#endif // ${conditionalString}"; - } - - # Properties - my $implContent = ""; - my @readableProperties = grep { IsPropertyReadable($_) } @{$interface->attributes}; - my @writeableProperties = grep { IsPropertyWriteable($_) } @{$interface->attributes}; - my $numProperties = scalar @readableProperties; - - # Properties - my $privFunction = GetCoreObject($interfaceName, "coreSelf", "self"); - if ($numProperties > 0) { - $implContent = << "EOF"; -enum { - PROP_0, -EOF - push(@cBodyProperties, $implContent); - - my $txtGetProp = << "EOF"; -static void ${lowerCaseIfaceName}_get_property(GObject* object, guint propertyId, GValue* value, GParamSpec* pspec) -{ - WebCore::JSMainThreadNullState state; -EOF - push(@txtGetProps, $txtGetProp); - $txtGetProp = << "EOF"; -$conditionGuardStart - ${className}* self = WEBKIT_DOM_${clsCaps}(object); - $privFunction -$conditionGuardEnd -EOF - push(@txtGetProps, $txtGetProp); - - $txtGetProp = << "EOF"; - switch (propertyId) { -EOF - push(@txtGetProps, $txtGetProp); - - if (scalar @writeableProperties > 0) { - my $txtSetProps = << "EOF"; -static void ${lowerCaseIfaceName}_set_property(GObject* object, guint propertyId, const GValue* value, GParamSpec* pspec) -{ - WebCore::JSMainThreadNullState state; -EOF - push(@txtSetProps, $txtSetProps); - - $txtSetProps = << "EOF"; -$conditionGuardStart - ${className}* self = WEBKIT_DOM_${clsCaps}(object); - $privFunction -$conditionGuardEnd -EOF - push(@txtSetProps, $txtSetProps); - - $txtSetProps = << "EOF"; - switch (propertyId) { -EOF - push(@txtSetProps, $txtSetProps); - } - - foreach my $attribute (@readableProperties) { - GenerateProperty($attribute, $interfaceName, \@writeableProperties, $interface); - } - - push(@cBodyProperties, "};\n\n"); - - $txtGetProp = << "EOF"; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, propertyId, pspec); - break; - } -} -EOF - push(@txtGetProps, $txtGetProp); - - if (scalar @writeableProperties > 0) { - $txtSetProps = << "EOF"; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, propertyId, pspec); - break; - } -} -EOF - push(@txtSetProps, $txtSetProps); - } - } - - # Do not insert extra spaces when interpolating array variables - $" = ""; - - if ($parentImplClassName eq "Object") { - $implContent = << "EOF"; -static void ${lowerCaseIfaceName}_finalize(GObject* object) -{ - ${className}Private* priv = WEBKIT_DOM_${clsCaps}_GET_PRIVATE(object); -$conditionGuardStart - WebKit::DOMObjectCache::forget(priv->coreObject.get()); -$conditionGuardEnd - priv->~${className}Private(); - G_OBJECT_CLASS(${lowerCaseIfaceName}_parent_class)->finalize(object); -} - -EOF - push(@cBodyProperties, $implContent); - } - - if ($numProperties > 0) { - if (scalar @writeableProperties > 0) { - push(@cBodyProperties, @txtSetProps); - push(@cBodyProperties, "\n"); - } - push(@cBodyProperties, @txtGetProps); - push(@cBodyProperties, "\n"); - } - - # Add a constructor implementation only for direct subclasses of Object to make sure - # that the WebCore wrapped object is added only once to the DOM cache. The DOM garbage - # collector works because Node is a direct subclass of Object and the version of - # DOMObjectCache::put() that receives a Node (which is the one setting the frame) is - # always called for DOM objects derived from Node. - if ($parentImplClassName eq "Object") { - $implContent = << "EOF"; -static GObject* ${lowerCaseIfaceName}_constructor(GType type, guint constructPropertiesCount, GObjectConstructParam* constructProperties) -{ - GObject* object = G_OBJECT_CLASS(${lowerCaseIfaceName}_parent_class)->constructor(type, constructPropertiesCount, constructProperties); -$conditionGuardStart - ${className}Private* priv = WEBKIT_DOM_${clsCaps}_GET_PRIVATE(object); - priv->coreObject = static_cast<WebCore::${interfaceName}*>(WEBKIT_DOM_OBJECT(object)->coreObject); - WebKit::DOMObjectCache::put(priv->coreObject.get(), object); -$conditionGuardEnd - return object; -} - -EOF - push(@cBodyProperties, $implContent); - } - - $implContent = << "EOF"; -static void ${lowerCaseIfaceName}_class_init(${className}Class* requestClass) -{ -EOF - push(@cBodyProperties, $implContent); - - if ($parentImplClassName eq "Object" || $numProperties > 0) { - push(@cBodyProperties, " GObjectClass* gobjectClass = G_OBJECT_CLASS(requestClass);\n"); - - if ($parentImplClassName eq "Object") { - push(@cBodyProperties, " g_type_class_add_private(gobjectClass, sizeof(${className}Private));\n"); - push(@cBodyProperties, " gobjectClass->constructor = ${lowerCaseIfaceName}_constructor;\n"); - push(@cBodyProperties, " gobjectClass->finalize = ${lowerCaseIfaceName}_finalize;\n"); - } - - if ($numProperties > 0) { - if (scalar @writeableProperties > 0) { - push(@cBodyProperties, " gobjectClass->set_property = ${lowerCaseIfaceName}_set_property;\n"); - } - push(@cBodyProperties, " gobjectClass->get_property = ${lowerCaseIfaceName}_get_property;\n"); - push(@cBodyProperties, "\n"); - push(@cBodyProperties, @txtInstallProps); - } - } - $implContent = << "EOF"; -} - -static void ${lowerCaseIfaceName}_init(${className}* request) -{ -EOF - push(@cBodyProperties, $implContent); - - if ($parentImplClassName eq "Object") { - $implContent = << "EOF"; - ${className}Private* priv = WEBKIT_DOM_${clsCaps}_GET_PRIVATE(request); - new (priv) ${className}Private(); -EOF - push(@cBodyProperties, $implContent); - } - $implContent = << "EOF"; -} - -EOF - push(@cBodyProperties, $implContent); -} - -sub GenerateHeader { - my ($object, $interfaceName, $parentClassName) = @_; - - my $implContent = ""; - - # Add the default header template - @hPrefix = split("\r", $licenceTemplate); - push(@hPrefix, "\n"); - - # Force single header include. - my $headerCheck = << "EOF"; -#if !defined(__WEBKITDOM_H_INSIDE__) && !defined(BUILDING_WEBKIT) -#error "Only <webkitdom/webkitdom.h> can be included directly." -#endif - -EOF - push(@hPrefix, $headerCheck); - - # Header guard - my $guard = $className . "_h"; - - @hPrefixGuard = << "EOF"; -#ifndef $guard -#define $guard - -EOF - - $implContent = << "EOF"; -G_BEGIN_DECLS - -EOF - - push(@hBodyPre, $implContent); - - my $decamelize = decamelize($interfaceName); - my $clsCaps = uc($decamelize); - my $lowerCaseIfaceName = "webkit_dom_$decamelize"; - - $implContent = << "EOF"; -#define WEBKIT_TYPE_DOM_${clsCaps} (${lowerCaseIfaceName}_get_type()) -#define WEBKIT_DOM_${clsCaps}(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), WEBKIT_TYPE_DOM_${clsCaps}, ${className})) -#define WEBKIT_DOM_${clsCaps}_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), WEBKIT_TYPE_DOM_${clsCaps}, ${className}Class) -#define WEBKIT_DOM_IS_${clsCaps}(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), WEBKIT_TYPE_DOM_${clsCaps})) -#define WEBKIT_DOM_IS_${clsCaps}_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), WEBKIT_TYPE_DOM_${clsCaps})) -#define WEBKIT_DOM_${clsCaps}_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), WEBKIT_TYPE_DOM_${clsCaps}, ${className}Class)) - -struct _${className} { - ${parentClassName} parent_instance; -}; - -struct _${className}Class { - ${parentClassName}Class parent_class; -}; - -WEBKIT_API GType -${lowerCaseIfaceName}_get_type (void); - -EOF - - push(@hBody, $implContent); -} - -sub GetGReturnMacro { - my ($paramName, $paramIDLType, $returnType, $functionName) = @_; - - my $condition; - if ($paramIDLType eq "GError") { - $condition = "!$paramName || !*$paramName"; - } elsif (IsGDOMClassType($paramIDLType)) { - my $paramTypeCaps = uc(decamelize($paramIDLType)); - $condition = "WEBKIT_DOM_IS_${paramTypeCaps}($paramName)"; - if (ParamCanBeNull($functionName, $paramName)) { - $condition = "!$paramName || $condition"; - } - } else { - if (ParamCanBeNull($functionName, $paramName)) { - return ""; - } - $condition = "$paramName"; - } - - my $macro; - if ($returnType ne "void") { - $defaultReturn = $returnType eq "gboolean" ? "FALSE" : 0; - $macro = " g_return_val_if_fail($condition, $defaultReturn);\n"; - } else { - $macro = " g_return_if_fail($condition);\n"; - } - - return $macro; -} - -sub ParamCanBeNull { - my($functionName, $paramName) = @_; - - if (defined($functionName)) { - return scalar(grep {$_ eq $paramName} @{$canBeNullParams->{$functionName}}); - } - return 0; -} - -sub GetFunctionDeprecationInformation { - my($function, $parentNode) = @_; - - my $version; - my $replacement; - - if ($parentNode->extendedAttributes->{"EventTarget"} && $function->signature->name eq "dispatchEvent") { - # dispatchEvent is implemented already as part fo the WebKitDOMEventTarget interface. - # Mark it as deprecated for now in favor of the interface method, and skip it once - # we break the API. All other methods of WebKitDOMEventTarget interface are already - # skipped because they receive an EventListener as parameter. - $version = "2.4"; - $replacement = "webkit_dom_event_target_dispatch_event"; - } - - return ($version, $replacement); -} - -sub GetTransferTypeForReturnType { - my $returnType = shift; - - # Node is always transfer none. - return "none" if $returnType eq "Node"; - - # Any base class but Node is transfer full. - return "full" if IsBaseType($returnType); - - # Any other class not derived from Node is transfer full. - return "full" if $transferFullTypeHash{$returnType}; - return "none"; -} - -sub GenerateFunction { - my ($object, $interfaceName, $function, $prefix, $parentNode) = @_; - - my $decamelize = decamelize($interfaceName); - - if (SkipFunction($object, $function, $parentNode, $decamelize, $prefix)) { - return; - } - - my ($deprecationVersion, $deprecationReplacement) = GetFunctionDeprecationInformation($function, $parentNode); - my $functionSigType = $prefix eq "set_" ? "void" : $function->signature->type; - my $functionName = "webkit_dom_" . $decamelize . "_" . $prefix . decamelize($function->signature->name); - my $returnType = GetGlibTypeName($functionSigType); - my $returnValueIsGDOMType = IsGDOMClassType($functionSigType); - my $raisesException = $function->signature->extendedAttributes->{"RaisesException"}; - - my $conditionalString = $codeGenerator->GenerateConditionalString($function->signature); - my $parentConditionalString = $codeGenerator->GenerateConditionalString($parentNode); - my @conditionalWarn = GenerateConditionalWarning($function->signature); - my @parentConditionalWarn = GenerateConditionalWarning($parentNode); - - my $functionSig = "${className}* self"; - my $symbolSig = "${className}*"; - - my @callImplParams; - foreach my $param (@{$function->parameters}) { - my $paramIDLType = $param->type; - my $paramType = GetGlibTypeName($paramIDLType); - my $const = $paramType eq "gchar*" ? "const " : ""; - my $paramName = $param->name; - - $functionSig .= ", ${const}$paramType $paramName"; - $symbolSig .= ", ${const}$paramType"; - - my $paramIsGDOMType = IsGDOMClassType($paramIDLType); - if ($paramIsGDOMType) { - if ($paramIDLType ne "any") { - $implIncludes{"WebKitDOM${paramIDLType}Private.h"} = 1; - } - } - if ($paramIsGDOMType || ($paramIDLType eq "DOMString") || ($paramIDLType eq "CompareHow")) { - $paramName = "converted" . $codeGenerator->WK_ucfirst($paramName); - } - push(@callImplParams, $paramName); - } - - if ($returnType ne "void" && $returnValueIsGDOMType && $functionSigType ne "any") { - $implIncludes{"WebKitDOM${functionSigType}Private.h"} = 1; - } - - $functionSig .= ", GError** error" if $raisesException; - $symbolSig .= ", GError**" if $raisesException; - - push(@symbols, "$returnType $functionName($symbolSig)\n"); - - if ($deprecationVersion) { - push(@hBody, "#if !defined(WEBKIT_DISABLE_DEPRECATED)\n"); - } - - # Insert introspection annotations - push(@hBody, "/**\n"); - push(@hBody, " * ${functionName}:\n"); - push(@hBody, " * \@self: A #${className}\n"); - - foreach my $param (@{$function->parameters}) { - my $paramType = GetGlibTypeName($param->type); - # $paramType can have a trailing * in some cases - $paramType =~ s/\*$//; - my $paramName = $param->name; - my $paramAnnotations = ""; - if (ParamCanBeNull($functionName, $paramName)) { - $paramAnnotations = " (allow-none):"; - } - push(@hBody, " * \@${paramName}:${paramAnnotations} A #${paramType}\n"); - } - push(@hBody, " * \@error: #GError\n") if $raisesException; - push(@hBody, " *\n"); - my $returnTypeName = $returnType; - $returnTypeName =~ s/\*$//; - if ($returnValueIsGDOMType) { - my $transferType = GetTransferTypeForReturnType($functionSigType); - push(@hBody, " * Returns: (transfer $transferType): A #${returnTypeName}\n"); - } elsif ($returnType ne "void") { - push(@hBody, " * Returns: A #${returnTypeName}\n"); - } - if ($deprecationVersion) { - push(@hBody, " *\n"); - push(@hBody, " * Deprecated: $deprecationVersion"); - if ($deprecationReplacement) { - push(@hBody, ": Use $deprecationReplacement() instead."); - } - push(@hBody, "\n"); - } - push(@hBody, "**/\n"); - - if ($deprecationVersion && $deprecationReplacement) { - push(@hBody, "WEBKIT_DEPRECATED_FOR($deprecationReplacement) "); - } elsif ($deprecationVersion) { - push(@hBody, "WEBKIT_DEPRECATED "); - } else { - push(@hBody, "WEBKIT_API "); - } - push(@hBody, "$returnType\n$functionName($functionSig);\n"); - if ($deprecationVersion) { - push(@hBody, "#endif /* WEBKIT_DISABLE_DEPRECATED */\n"); - } - push(@hBody, "\n"); - - push(@cBody, "$returnType $functionName($functionSig)\n{\n"); - push(@cBody, "#if ${parentConditionalString}\n") if $parentConditionalString; - push(@cBody, "#if ${conditionalString}\n") if $conditionalString; - - push(@cBody, " WebCore::JSMainThreadNullState state;\n"); - - # g_return macros to check parameters of public methods. - $gReturnMacro = GetGReturnMacro("self", $interfaceName, $returnType); - push(@cBody, $gReturnMacro); - - foreach my $param (@{$function->parameters}) { - my $paramName = $param->name; - my $paramIDLType = $param->type; - my $paramTypeIsPointer = !$codeGenerator->IsNonPointerType($paramIDLType); - if ($paramTypeIsPointer) { - $gReturnMacro = GetGReturnMacro($paramName, $paramIDLType, $returnType, $functionName); - push(@cBody, $gReturnMacro); - } - } - - if ($raisesException) { - $gReturnMacro = GetGReturnMacro("error", "GError", $returnType); - push(@cBody, $gReturnMacro); - } - - # The WebKit::core implementations check for null already; no need to duplicate effort. - push(@cBody, " WebCore::${interfaceName}* item = WebKit::core(self);\n"); - - $returnParamName = ""; - foreach my $param (@{$function->parameters}) { - my $paramIDLType = $param->type; - my $paramName = $param->name; - - my $paramIsGDOMType = IsGDOMClassType($paramIDLType); - $convertedParamName = "converted" . $codeGenerator->WK_ucfirst($paramName); - if ($paramIDLType eq "DOMString") { - push(@cBody, " WTF::String ${convertedParamName} = WTF::String::fromUTF8($paramName);\n"); - } elsif ($paramIDLType eq "CompareHow") { - push(@cBody, " WebCore::Range::CompareHow ${convertedParamName} = static_cast<WebCore::Range::CompareHow>($paramName);\n"); - } elsif ($paramIsGDOMType) { - push(@cBody, " WebCore::${paramIDLType}* ${convertedParamName} = WebKit::core($paramName);\n"); - } - $returnParamName = $convertedParamName if $param->extendedAttributes->{"CustomReturn"}; - } - - my $assign = ""; - my $assignPre = ""; - my $assignPost = ""; - - # We need to special-case these Node methods because their C++ - # signature is different from what we'd expect given their IDL - # description; see Node.h. - my $functionHasCustomReturn = $functionName eq "webkit_dom_node_append_child" || - $functionName eq "webkit_dom_node_insert_before" || - $functionName eq "webkit_dom_node_replace_child" || - $functionName eq "webkit_dom_node_remove_child"; - - if ($returnType ne "void" && !$functionHasCustomReturn) { - if ($returnValueIsGDOMType) { - $assign = "RefPtr<WebCore::${functionSigType}> gobjectResult = "; - $assignPre = "WTF::getPtr("; - $assignPost = ")"; - } else { - $assign = "${returnType} result = "; - } - } - - # FIXME: Should we return a default value when isNull == true? - if ($function->signature->isNullable) { - push(@cBody, " bool isNull = false;\n"); - push(@callImplParams, "isNull"); - } - - if ($raisesException) { - push(@cBody, " WebCore::ExceptionCode ec = 0;\n"); - push(@callImplParams, "ec"); - } - - my $functionImplementationName = $function->signature->extendedAttributes->{"ImplementedAs"} || $function->signature->name; - - if ($functionHasCustomReturn) { - push(@cBody, " bool ok = item->${functionImplementationName}(" . join(", ", @callImplParams) . ");\n"); - my $customNodeAppendChild = << "EOF"; - if (ok) - return WebKit::kit($returnParamName); -EOF - push(@cBody, $customNodeAppendChild); - - if($raisesException) { - my $exceptionHandling = << "EOF"; - - WebCore::ExceptionCodeDescription ecdesc(ec); - g_set_error_literal(error, g_quark_from_string("WEBKIT_DOM"), ecdesc.code, ecdesc.name); -EOF - push(@cBody, $exceptionHandling); - } - push(@cBody, " return 0;\n"); - push(@cBody, "}\n\n"); - return; - } elsif ($functionSigType eq "DOMString") { - my $getterContentHead; - if ($prefix) { - my ($functionName, @arguments) = $codeGenerator->GetterExpression(\%implIncludes, $interfaceName, $function); - push(@arguments, @callImplParams); - if ($function->signature->extendedAttributes->{"ImplementedBy"}) { - my $implementedBy = $function->signature->extendedAttributes->{"ImplementedBy"}; - $implIncludes{"${implementedBy}.h"} = 1; - unshift(@arguments, "item"); - $functionName = "WebCore::${implementedBy}::${functionName}"; - } else { - $functionName = "item->${functionName}"; - } - $getterContentHead = "${assign}convertToUTF8String(${functionName}(" . join(", ", @arguments) . "));\n"; - } else { - my @arguments = @callImplParams; - if ($function->signature->extendedAttributes->{"ImplementedBy"}) { - my $implementedBy = $function->signature->extendedAttributes->{"ImplementedBy"}; - $implIncludes{"${implementedBy}.h"} = 1; - unshift(@arguments, "item"); - $getterContentHead = "${assign}convertToUTF8String(WebCore::${implementedBy}::${functionImplementationName}(" . join(", ", @arguments) . "));\n"; - } else { - $getterContentHead = "${assign}convertToUTF8String(item->${functionImplementationName}(" . join(", ", @arguments) . "));\n"; - } - } - push(@cBody, " ${getterContentHead}"); - } else { - my $contentHead; - if ($prefix eq "get_") { - my ($functionName, @arguments) = $codeGenerator->GetterExpression(\%implIncludes, $interfaceName, $function); - push(@arguments, @callImplParams); - if ($function->signature->extendedAttributes->{"ImplementedBy"}) { - my $implementedBy = $function->signature->extendedAttributes->{"ImplementedBy"}; - $implIncludes{"${implementedBy}.h"} = 1; - unshift(@arguments, "item"); - $functionName = "WebCore::${implementedBy}::${functionName}"; - } else { - $functionName = "item->${functionName}"; - } - $contentHead = "${assign}${assignPre}${functionName}(" . join(", ", @arguments) . "${assignPost});\n"; - } elsif ($prefix eq "set_") { - my ($functionName, @arguments) = $codeGenerator->SetterExpression(\%implIncludes, $interfaceName, $function); - push(@arguments, @callImplParams); - if ($function->signature->extendedAttributes->{"ImplementedBy"}) { - my $implementedBy = $function->signature->extendedAttributes->{"ImplementedBy"}; - $implIncludes{"${implementedBy}.h"} = 1; - unshift(@arguments, "item"); - $functionName = "WebCore::${implementedBy}::${functionName}"; - $contentHead = "${assign}${assignPre}${functionName}(" . join(", ", @arguments) . "${assignPost});\n"; - } else { - $functionName = "item->${functionName}"; - $contentHead = "${assign}${assignPre}${functionName}(" . join(", ", @arguments) . "${assignPost});\n"; - } - } else { - my @arguments = @callImplParams; - if ($function->signature->extendedAttributes->{"ImplementedBy"}) { - my $implementedBy = $function->signature->extendedAttributes->{"ImplementedBy"}; - $implIncludes{"${implementedBy}.h"} = 1; - unshift(@arguments, "item"); - $contentHead = "${assign}${assignPre}WebCore::${implementedBy}::${functionImplementationName}(" . join(", ", @arguments) . "${assignPost});\n"; - } else { - $contentHead = "${assign}${assignPre}item->${functionImplementationName}(" . join(", ", @arguments) . "${assignPost});\n"; - } - } - push(@cBody, " ${contentHead}"); - - if($raisesException) { - my $exceptionHandling = << "EOF"; - if (ec) { - WebCore::ExceptionCodeDescription ecdesc(ec); - g_set_error_literal(error, g_quark_from_string("WEBKIT_DOM"), ecdesc.code, ecdesc.name); - } -EOF - push(@cBody, $exceptionHandling); - } - } - - if ($returnType ne "void" && !$functionHasCustomReturn) { - if ($functionSigType ne "any") { - if ($returnValueIsGDOMType) { - push(@cBody, " return WebKit::kit(gobjectResult.get());\n"); - } else { - push(@cBody, " return result;\n"); - } - } else { - push(@cBody, " return 0; // TODO: return canvas object\n"); - } - } - - if ($conditionalString) { - push(@cBody, "#else\n"); - push(@cBody, @conditionalWarn) if scalar(@conditionalWarn); - if ($returnType ne "void") { - if ($codeGenerator->IsNonPointerType($functionSigType)) { - push(@cBody, " return static_cast<${returnType}>(0);\n"); - } else { - push(@cBody, " return 0;\n"); - } - } - push(@cBody, "#endif /* ${conditionalString} */\n"); - } - - if ($parentConditionalString) { - push(@cBody, "#else\n"); - push(@cBody, @parentConditionalWarn) if scalar(@parentConditionalWarn); - if ($returnType ne "void") { - if ($codeGenerator->IsNonPointerType($functionSigType)) { - push(@cBody, " return static_cast<${returnType}>(0);\n"); - } else { - push(@cBody, " return 0;\n"); - } - } - push(@cBody, "#endif /* ${parentConditionalString} */\n"); - } - - push(@cBody, "}\n\n"); -} - -sub ClassHasFunction { - my ($class, $name) = @_; - - foreach my $function (@{$class->functions}) { - if ($function->signature->name eq $name) { - return 1; - } - } - - return 0; -} - -sub GenerateFunctions { - my ($object, $interfaceName, $interface) = @_; - - foreach my $function (@{$interface->functions}) { - $object->GenerateFunction($interfaceName, $function, "", $interface); - } - - TOP: - foreach my $attribute (@{$interface->attributes}) { - if (SkipAttribute($attribute)) { - next TOP; - } - - if ($attribute->signature->name eq "type") { - # This will conflict with the get_type() function we define to return a GType - # according to GObject conventions. Skip this for now. - next TOP; - } - - my $attrNameUpper = $codeGenerator->WK_ucfirst($attribute->signature->name); - my $getname = "get${attrNameUpper}"; - my $setname = "set${attrNameUpper}"; - if (ClassHasFunction($interface, $getname) || ClassHasFunction($interface, $setname)) { - # Very occasionally an IDL file defines getter/setter functions for one of its - # attributes; in this case we don't need to autogenerate the getter/setter. - next TOP; - } - - # Generate an attribute getter. For an attribute "foo", this is a function named - # "get_foo" which calls a DOM class method named foo(). - my $function = new domFunction(); - $function->signature($attribute->signature); - $function->signature->extendedAttributes({%{$attribute->signature->extendedAttributes}}); - if ($attribute->signature->extendedAttributes->{"GetterRaisesException"}) { - $function->signature->extendedAttributes->{"RaisesException"} = "VALUE_IS_MISSING"; - } - $object->GenerateFunction($interfaceName, $function, "get_", $interface); - - # FIXME: We are not generating setters for 'Replaceable' - # attributes now, but we should somehow. - my $custom = $attribute->signature->extendedAttributes->{"CustomSetter"}; - if ($attribute->isReadOnly || $attribute->signature->extendedAttributes->{"Replaceable"} || $custom) { - next TOP; - } - - # Generate an attribute setter. For an attribute, "foo", this is a function named - # "set_foo" which calls a DOM class method named setFoo(). - $function = new domFunction(); - - $function->signature(new domSignature()); - $function->signature->name($attribute->signature->name); - $function->signature->type($attribute->signature->type); - $function->signature->extendedAttributes({%{$attribute->signature->extendedAttributes}}); - - my $param = new domSignature(); - $param->name("value"); - $param->type($attribute->signature->type); - my %attributes = (); - $param->extendedAttributes(\%attributes); - my $arrayRef = $function->parameters; - push(@$arrayRef, $param); - - if ($attribute->signature->extendedAttributes->{"SetterRaisesException"}) { - $function->signature->extendedAttributes->{"RaisesException"} = "VALUE_IS_MISSING"; - } else { - delete $function->signature->extendedAttributes->{"RaisesException"}; - } - - $object->GenerateFunction($interfaceName, $function, "set_", $interface); - } -} - -sub GenerateCFile { - my ($object, $interfaceName, $parentClassName, $parentGObjType, $interface) = @_; - - if ($interface->extendedAttributes->{"EventTarget"}) { - $object->GenerateEventTargetIface($interface); - } - - my $implContent = ""; - - my $decamelize = decamelize($interfaceName); - my $clsCaps = uc($decamelize); - my $lowerCaseIfaceName = "webkit_dom_$decamelize"; - my $parentImplClassName = GetParentImplClassName($interface); - my $baseClassName = GetBaseClass($parentImplClassName, $interface); - - # Add a private struct only for direct subclasses of Object so that we can use RefPtr - # for the WebCore wrapped object and make sure we only increment the reference counter once. - if ($parentImplClassName eq "Object") { - my $conditionalString = $codeGenerator->GenerateConditionalString($interface); - push(@cStructPriv, "#define WEBKIT_DOM_${clsCaps}_GET_PRIVATE(obj) G_TYPE_INSTANCE_GET_PRIVATE(obj, WEBKIT_TYPE_DOM_${clsCaps}, ${className}Private)\n\n"); - push(@cStructPriv, "typedef struct _${className}Private {\n"); - push(@cStructPriv, "#if ${conditionalString}\n") if $conditionalString; - push(@cStructPriv, " RefPtr<WebCore::${interfaceName}> coreObject;\n"); - push(@cStructPriv, "#endif // ${conditionalString}\n") if $conditionalString; - push(@cStructPriv, "} ${className}Private;\n\n"); - } - - $implContent = << "EOF"; -${defineTypeMacro}(${className}, ${lowerCaseIfaceName}, ${parentGObjType}${defineTypeInterfaceImplementation} - -EOF - push(@cBodyProperties, $implContent); - - if ($parentImplClassName eq "Object") { - push(@cBodyPriv, "${className}* kit(WebCore::$interfaceName* obj)\n"); - push(@cBodyPriv, "{\n"); - push(@cBodyPriv, " if (!obj)\n"); - push(@cBodyPriv, " return 0;\n\n"); - push(@cBodyPriv, " if (gpointer ret = DOMObjectCache::get(obj))\n"); - push(@cBodyPriv, " return WEBKIT_DOM_${clsCaps}(ret);\n\n"); - if (IsPolymorphic($interfaceName)) { - push(@cBodyPriv, " return wrap(obj);\n"); - } else { - push(@cBodyPriv, " return wrap${interfaceName}(obj);\n"); - } - push(@cBodyPriv, "}\n\n"); - } else { - push(@cBodyPriv, "${className}* kit(WebCore::$interfaceName* obj)\n"); - push(@cBodyPriv, "{\n"); - if (!IsPolymorphic($baseClassName)) { - push(@cBodyPriv, " if (!obj)\n"); - push(@cBodyPriv, " return 0;\n\n"); - push(@cBodyPriv, " if (gpointer ret = DOMObjectCache::get(obj))\n"); - push(@cBodyPriv, " return WEBKIT_DOM_${clsCaps}(ret);\n\n"); - push(@cBodyPriv, " return wrap${interfaceName}(obj);\n"); - } else { - push(@cBodyPriv, " return WEBKIT_DOM_${clsCaps}(kit(static_cast<WebCore::$baseClassName*>(obj)));\n"); - } - push(@cBodyPriv, "}\n\n"); - } - - $implContent = << "EOF"; -WebCore::${interfaceName}* core(${className}* request) -{ - return request ? static_cast<WebCore::${interfaceName}*>(WEBKIT_DOM_OBJECT(request)->coreObject) : 0; -} - -${className}* wrap${interfaceName}(WebCore::${interfaceName}* coreObject) -{ - ASSERT(coreObject); - return WEBKIT_DOM_${clsCaps}(g_object_new(WEBKIT_TYPE_DOM_${clsCaps}, "core-object", coreObject, NULL)); -} - -EOF - push(@cBodyPriv, $implContent); - - $object->GenerateProperties($interfaceName, $interface); - $object->GenerateFunctions($interfaceName, $interface); -} - -sub GenerateEndHeader { - my ($object) = @_; - - #Header guard - my $guard = $className . "_h"; - - push(@hBody, "G_END_DECLS\n\n"); - push(@hPrefixGuardEnd, "#endif /* $guard */\n"); -} - -sub IsPolymorphic { - my $type = shift; - - return scalar(grep {$_ eq $type} qw(Blob Event HTMLCollection Node StyleSheet)); -} - -sub GenerateEventTargetIface { - my $object = shift; - my $interface = shift; - - my $interfaceName = $interface->name; - my $decamelize = decamelize($interfaceName); - my $conditionalString = $codeGenerator->GenerateConditionalString($interface); - my @conditionalWarn = GenerateConditionalWarning($interface); - - $implIncludes{"GObjectEventListener.h"} = 1; - $implIncludes{"WebKitDOMEventTarget.h"} = 1; - $implIncludes{"WebKitDOMEventPrivate.h"} = 1; - - push(@cBodyProperties, "static gboolean webkit_dom_${decamelize}_dispatch_event(WebKitDOMEventTarget* target, WebKitDOMEvent* event, GError** error)\n{\n"); - push(@cBodyProperties, "#if ${conditionalString}\n") if $conditionalString; - push(@cBodyProperties, " WebCore::Event* coreEvent = WebKit::core(event);\n"); - push(@cBodyProperties, " WebCore::${interfaceName}* coreTarget = static_cast<WebCore::${interfaceName}*>(WEBKIT_DOM_OBJECT(target)->coreObject);\n\n"); - push(@cBodyProperties, " WebCore::ExceptionCode ec = 0;\n"); - push(@cBodyProperties, " gboolean result = coreTarget->dispatchEvent(coreEvent, ec);\n"); - push(@cBodyProperties, " if (ec) {\n WebCore::ExceptionCodeDescription description(ec);\n"); - push(@cBodyProperties, " g_set_error_literal(error, g_quark_from_string(\"WEBKIT_DOM\"), description.code, description.name);\n }\n"); - push(@cBodyProperties, " return result;\n"); - push(@cBodyProperties, "#else\n") if $conditionalString; - push(@cBodyProperties, @conditionalWarn) if scalar(@conditionalWarn); - push(@cBodyProperties, " return false;\n#endif // ${conditionalString}\n") if $conditionalString; - push(@cBodyProperties, "}\n\n"); - - push(@cBodyProperties, "static gboolean webkit_dom_${decamelize}_add_event_listener(WebKitDOMEventTarget* target, const char* eventName, GClosure* handler, gboolean useCapture)\n{\n"); - push(@cBodyProperties, "#if ${conditionalString}\n") if $conditionalString; - push(@cBodyProperties, " WebCore::${interfaceName}* coreTarget = static_cast<WebCore::${interfaceName}*>(WEBKIT_DOM_OBJECT(target)->coreObject);\n"); - push(@cBodyProperties, " return WebCore::GObjectEventListener::addEventListener(G_OBJECT(target), coreTarget, eventName, handler, useCapture);\n"); - push(@cBodyProperties, "#else\n") if $conditionalString; - push(@cBodyProperties, @conditionalWarn) if scalar(@conditionalWarn); - push(@cBodyProperties, " return false;\n#endif // ${conditionalString}\n") if $conditionalString; - push(@cBodyProperties, "}\n\n"); - - push(@cBodyProperties, "static gboolean webkit_dom_${decamelize}_remove_event_listener(WebKitDOMEventTarget* target, const char* eventName, GClosure* handler, gboolean useCapture)\n{\n"); - push(@cBodyProperties, "#if ${conditionalString}\n") if $conditionalString; - push(@cBodyProperties, " WebCore::${interfaceName}* coreTarget = static_cast<WebCore::${interfaceName}*>(WEBKIT_DOM_OBJECT(target)->coreObject);\n"); - push(@cBodyProperties, " return WebCore::GObjectEventListener::removeEventListener(G_OBJECT(target), coreTarget, eventName, handler, useCapture);\n"); - push(@cBodyProperties, "#else\n") if $conditionalString; - push(@cBodyProperties, @conditionalWarn) if scalar(@conditionalWarn); - push(@cBodyProperties, " return false;\n#endif // ${conditionalString}\n") if $conditionalString; - push(@cBodyProperties, "}\n\n"); - - push(@cBodyProperties, "static void webkit_dom_event_target_init(WebKitDOMEventTargetIface* iface)\n{\n"); - push(@cBodyProperties, " iface->dispatch_event = webkit_dom_${decamelize}_dispatch_event;\n"); - push(@cBodyProperties, " iface->add_event_listener = webkit_dom_${decamelize}_add_event_listener;\n"); - push(@cBodyProperties, " iface->remove_event_listener = webkit_dom_${decamelize}_remove_event_listener;\n}\n\n"); - - $defineTypeMacro = "G_DEFINE_TYPE_WITH_CODE"; - $defineTypeInterfaceImplementation = ", G_IMPLEMENT_INTERFACE(WEBKIT_TYPE_DOM_EVENT_TARGET, webkit_dom_event_target_init))"; -} - -sub Generate { - my ($object, $interface) = @_; - - my $parentClassName = GetParentClassName($interface); - my $parentGObjType = GetParentGObjType($interface); - my $interfaceName = $interface->name; - my $parentImplClassName = GetParentImplClassName($interface); - my $baseClassName = GetBaseClass($parentImplClassName, $interface); - - # Add the default impl header template - @cPrefix = split("\r", $licenceTemplate); - push(@cPrefix, "\n"); - - $implIncludes{"DOMObjectCache.h"} = 1; - $implIncludes{"WebKitDOMPrivate.h"} = 1; - $implIncludes{"gobject/ConvertToUTF8String.h"} = 1; - $implIncludes{"${className}Private.h"} = 1; - $implIncludes{"Document.h"} = 1; - $implIncludes{"JSMainThreadExecState.h"} = 1; - $implIncludes{"ExceptionCode.h"} = 1; - $implIncludes{"CSSImportRule.h"} = 1; - if ($parentImplClassName ne "Object" and IsPolymorphic($baseClassName)) { - $implIncludes{"WebKitDOM${baseClassName}Private.h"} = 1; - } - - $hdrIncludes{"webkitdom/${parentClassName}.h"} = 1; - - $object->GenerateHeader($interfaceName, $parentClassName); - $object->GenerateCFile($interfaceName, $parentClassName, $parentGObjType, $interface); - $object->GenerateEndHeader(); -} - -sub WriteData { - my $object = shift; - my $interface = shift; - my $outputDir = shift; - mkdir $outputDir; - - # Write a private header. - my $interfaceName = $interface->name; - my $filename = "$outputDir/" . $className . "Private.h"; - my $guard = "${className}Private_h"; - - # Add the guard if the 'Conditional' extended attribute exists - my $conditionalString = $codeGenerator->GenerateConditionalString($interface); - - open(PRIVHEADER, ">$filename") or die "Couldn't open file $filename for writing"; - - print PRIVHEADER split("\r", $licenceTemplate); - print PRIVHEADER "\n"; - - my $text = << "EOF"; -#ifndef $guard -#define $guard - -#include "${interfaceName}.h" -#include <webkitdom/${className}.h> -EOF - - print PRIVHEADER $text; - print PRIVHEADER "#if ${conditionalString}\n" if $conditionalString; - print PRIVHEADER map { "#include \"$_\"\n" } sort keys(%hdrPropIncludes); - print PRIVHEADER "\n"; - $text = << "EOF"; -namespace WebKit { -${className}* wrap${interfaceName}(WebCore::${interfaceName}*); -${className}* kit(WebCore::${interfaceName}*); -WebCore::${interfaceName}* core(${className}*); -EOF - - print PRIVHEADER $text; - - $text = << "EOF"; -} // namespace WebKit - -EOF - - print PRIVHEADER $text; - print PRIVHEADER "#endif /* ${conditionalString} */\n\n" if $conditionalString; - print PRIVHEADER "#endif /* ${guard} */\n"; - - close(PRIVHEADER); - - my $basename = FileNamePrefix . $interfaceName; - $basename =~ s/_//g; - - # Write public header. - my $fullHeaderFilename = "$outputDir/" . $basename . ".h"; - my $installedHeaderFilename = "${basename}.h"; - open(HEADER, ">$fullHeaderFilename") or die "Couldn't open file $fullHeaderFilename"; - - print HEADER @hPrefix; - print HEADER @hPrefixGuard; - print HEADER "#include <glib-object.h>\n"; - print HEADER map { "#include <$_>\n" } sort keys(%hdrIncludes); - print HEADER "#include <webkitdom/webkitdomdefines.h>\n\n"; - print HEADER @hBodyPre; - print HEADER @hBody; - print HEADER @hPrefixGuardEnd; - - close(HEADER); - - # Write the implementation sources - my $implFileName = "$outputDir/" . $basename . ".cpp"; - open(IMPL, ">$implFileName") or die "Couldn't open file $implFileName"; - - print IMPL @cPrefix; - print IMPL "#include \"config.h\"\n"; - print IMPL "#include \"$installedHeaderFilename\"\n\n"; - - # Remove the implementation header from the list of included files. - %includesCopy = %implIncludes; - print IMPL map { "#include \"$_\"\n" } sort keys(%includesCopy); - - print IMPL "#include <wtf/GetPtr.h>\n"; - print IMPL "#include <wtf/RefPtr.h>\n\n"; - print IMPL @cStructPriv; - print IMPL "#if ${conditionalString}\n\n" if $conditionalString; - - print IMPL "namespace WebKit {\n\n"; - print IMPL @cBodyPriv; - print IMPL "} // namespace WebKit\n\n"; - print IMPL "#endif // ${conditionalString}\n\n" if $conditionalString; - - print IMPL @cBodyProperties; - print IMPL @cBody; - - close(IMPL); - - # Write a symbols file. - my $symbolsFileName = "$outputDir/" . $basename . ".symbols"; - open(SYM, ">$symbolsFileName") or die "Couldn't open file $symbolsFileName"; - print SYM @symbols; - close(SYM); - - %implIncludes = (); - %hdrIncludes = (); - @hPrefix = (); - @hBody = (); - - @cPrefix = (); - @cBody = (); - @cBodyPriv = (); - @cBodyProperties = (); - @cStructPriv = (); - - @symbols = (); -} - -sub GenerateInterface { - my ($object, $interface, $defines) = @_; - - # Set up some global variables - $className = GetClassName($interface->name); - - $object->Generate($interface); -} - -1; diff --git a/Source/WebCore/bindings/scripts/CodeGeneratorJS.pm b/Source/WebCore/bindings/scripts/CodeGeneratorJS.pm index d3685f8e3..b71e2ce9a 100644 --- a/Source/WebCore/bindings/scripts/CodeGeneratorJS.pm +++ b/Source/WebCore/bindings/scripts/CodeGeneratorJS.pm @@ -3,7 +3,7 @@ # Copyright (C) 2006 Anders Carlsson <andersca@mac.com> # Copyright (C) 2006, 2007 Samuel Weinig <sam@webkit.org> # Copyright (C) 2006 Alexey Proskuryakov <ap@webkit.org> -# Copyright (C) 2006, 2007, 2008, 2009, 2010, 2013 Apple Inc. All rights reserved. +# Copyright (C) 2006-2017 Apple Inc. All rights reserved. # Copyright (C) 2009 Cameron McCormack <cam@mcc.id.au> # Copyright (C) Research In Motion Limited 2010. All rights reserved. # Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies) @@ -11,6 +11,7 @@ # Copyright (C) 2012 Ericsson AB. All rights reserved. # Copyright (C) 2007, 2008, 2009, 2012 Google Inc. # Copyright (C) 2013 Samsung Electronics. All rights reserved. +# Copyright (C) 2015, 2016 Canon Inc. All rights reserved. # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Library General Public @@ -27,15 +28,17 @@ # the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, # Boston, MA 02110-1301, USA. + package CodeGeneratorJS; use strict; use constant FileNamePrefix => "JS"; +use Carp qw<longmess>; +use Data::Dumper; use Hasher; my $codeGenerator; - -my $writeDependencies = 0; +my $writeDependencies; my @headerContentHeader = (); my @headerContent = (); @@ -47,7 +50,6 @@ my @implContent = (); my %implIncludes = (); my @depsContent = (); my $numCachedAttributes = 0; -my $currentCachedAttribute = 0; my $beginAppleCopyrightForHeaderFiles = <<END; // ------- Begin Apple Copyright ------- @@ -106,6 +108,16 @@ my $headerTemplate = << "EOF"; */ EOF +sub assert +{ + my $message = shift; + + my $mess = longmess(); + print Dumper($mess); + + die $message; +} + # Default constructor sub new { @@ -113,96 +125,99 @@ sub new my $reference = { }; $codeGenerator = shift; - shift; # $useLayerOnTop - shift; # $preprocessor $writeDependencies = shift; bless($reference, $object); return $reference; } +sub GenerateEnumeration +{ + my ($object, $enumeration) = @_; + + my $className = GetEnumerationClassName($enumeration->type); + $object->GenerateEnumerationHeader($enumeration, $className); + $object->GenerateEnumerationImplementation($enumeration, $className); +} + +sub GenerateDictionary +{ + my ($object, $dictionary, $enumerations, $otherDictionaries) = @_; + + my $className = GetDictionaryClassName($dictionary->type); + $object->GenerateDictionaryHeader($dictionary, $className, $enumerations, $otherDictionaries); + $object->GenerateDictionaryImplementation($dictionary, $className, $enumerations, $otherDictionaries); +} + +sub GenerateCallbackFunction +{ + my ($object, $callbackFunction, $enumerations, $dictionaries) = @_; + + $object->GenerateCallbackFunctionHeader($callbackFunction, $enumerations, $dictionaries); + $object->GenerateCallbackFunctionImplementation($callbackFunction, $enumerations, $dictionaries); +} + sub GenerateInterface { - my $object = shift; - my $interface = shift; - my $defines = shift; + my ($object, $interface, $defines, $enumerations, $dictionaries) = @_; $codeGenerator->LinkOverloadedFunctions($interface); + AddStringifierOperationIfNeeded($interface); - # Start actual generation if ($interface->isCallback) { - $object->GenerateCallbackHeader($interface); - $object->GenerateCallbackImplementation($interface); + $object->GenerateCallbackInterfaceHeader($interface, $enumerations, $dictionaries); + $object->GenerateCallbackInterfaceImplementation($interface, $enumerations, $dictionaries); } else { - $object->GenerateHeader($interface); - $object->GenerateImplementation($interface); + $object->GenerateHeader($interface, $enumerations, $dictionaries); + $object->GenerateImplementation($interface, $enumerations, $dictionaries); } } -sub GenerateAttributeEventListenerCall +sub AddStringifierOperationIfNeeded { - my $className = shift; - my $implSetterFunctionName = shift; - my $windowEventListener = shift; + my $interface = shift; - my $wrapperObject = $windowEventListener ? "globalObject" : "castedThis"; - my @GenerateEventListenerImpl = (); + foreach my $attribute (@{$interface->attributes}) { + next unless $attribute->isStringifier; - if ($className eq "JSSVGElementInstance") { - # SVGElementInstances have to create JSEventListeners with the wrapper equal to the correspondingElement - $wrapperObject = "asObject(correspondingElementWrapper)"; + my $stringifier = IDLOperation->new(); + $stringifier->name("toString"); - push(@GenerateEventListenerImpl, <<END); - JSValue correspondingElementWrapper = toJS(exec, castedThis->globalObject(), impl.correspondingElement()); - if (correspondingElementWrapper.isObject()) -END + my $extendedAttributeList = {}; + $extendedAttributeList->{ImplementedAs} = $attribute->name; + $stringifier->extendedAttributes($extendedAttributeList); + die "stringifier can only be used on attributes of String types" unless $codeGenerator->IsStringType($attribute->type); + + # FIXME: This should use IDLParser's cloneType. + my $type = IDLType->new(); + $type->name($attribute->type->name); - # Add leading whitespace to format the impl.set... line correctly - push(@GenerateEventListenerImpl, " "); - } + $stringifier->type($type); - push(@GenerateEventListenerImpl, " impl.set$implSetterFunctionName(createJSAttributeEventListener(exec, value, $wrapperObject));\n"); - return @GenerateEventListenerImpl; + push(@{$interface->functions}, $stringifier); + last; + } } -sub GenerateEventListenerCall +sub EventHandlerAttributeEventName { - my $className = shift; - my $functionName = shift; - my $passRefPtrHandling = ($functionName eq "add") ? "" : ".get()"; - - $implIncludes{"JSEventListener.h"} = 1; - - my @GenerateEventListenerImpl = (); - my $wrapperObject = "castedThis"; - if ($className eq "JSSVGElementInstance") { - # SVGElementInstances have to create JSEventListeners with the wrapper equal to the correspondingElement - $wrapperObject = "asObject(correspondingElementWrapper)"; + my $attribute = shift; + my $eventType = $attribute->extendedAttributes->{ImplementedAs} || $attribute->name; - push(@GenerateEventListenerImpl, <<END); - JSValue correspondingElementWrapper = toJS(exec, castedThis->globalObject(), impl.correspondingElement()); - if (!correspondingElementWrapper.isObject()) - return JSValue::encode(jsUndefined()); -END - } + # Remove the "on" prefix. + $eventType = substr($eventType, 2); - push(@GenerateEventListenerImpl, <<END); - JSValue listener = exec->argument(1); - if (!listener.isObject()) - return JSValue::encode(jsUndefined()); - impl.${functionName}EventListener(exec->argument(0).toString(exec)->value(exec), JSEventListener::create(asObject(listener), $wrapperObject, false, currentWorld(exec))$passRefPtrHandling, exec->argument(2).toBoolean(exec)); - return JSValue::encode(jsUndefined()); -END - return @GenerateEventListenerImpl; + return "eventNames().${eventType}Event"; } sub GetParentClassName { my $interface = shift; - return $interface->extendedAttributes->{"JSLegacyParent"} if $interface->extendedAttributes->{"JSLegacyParent"}; - return "JSDOMWrapper" unless $interface->parent; - return "JS" . $interface->parent; + return $interface->extendedAttributes->{JSLegacyParent} if $interface->extendedAttributes->{JSLegacyParent}; + return "JSDOMObject" unless NeedsImplementationClass($interface); + return "JSDOMWrapper<" . GetImplClassName($interface) . ">" unless $interface->parentType; + return "JS" . $interface->parentType->name; } sub GetCallbackClassName @@ -212,286 +227,499 @@ sub GetCallbackClassName return "JS$className"; } -sub AddIncludesForTypeInImpl +sub GetJSCallbackDataType { - my $type = shift; - my $isCallback = @_ ? shift : 0; - - AddIncludesForType($type, $isCallback, \%implIncludes); + my $callback = shift; + + return $callback->extendedAttributes->{IsWeakCallback} ? "JSCallbackDataWeak" : "JSCallbackDataStrong"; } -sub AddIncludesForTypeInHeader +sub GetExportMacroForJSClass { - my $type = shift; - my $isCallback = @_ ? shift : 0; + my $interface = shift; + + return $interface->extendedAttributes->{ExportMacro} . " " if $interface->extendedAttributes->{ExportMacro}; + return ""; +} + +sub AddIncludesForImplementationTypeInImpl +{ + my $implementationType = shift; - AddIncludesForType($type, $isCallback, \%headerIncludes); + AddIncludesForImplementationType($implementationType, \%implIncludes); } -my %typesWithoutHeader = ( - "Array" => 1, - "DOMString" => 1, - "DOMTimeStamp" => 1, - "any" => 1 -); +sub AddIncludesForImplementationTypeInHeader +{ + my $implementationType = shift; + + AddIncludesForImplementationType($implementationType, \%headerIncludes); +} -sub SkipIncludeHeader +sub AddIncludesForImplementationType { - my $type = shift; + my ($implementationType, $includesRef) = @_; - return 1 if $codeGenerator->SkipIncludeHeader($type); - return $typesWithoutHeader{$type}; + $includesRef->{"${implementationType}.h"} = 1; } -sub AddIncludesForType +sub AddToImplIncludesForIDLType { - my $type = shift; - my $isCallback = shift; - my $includesRef = shift; + my ($type, $conditional) = @_; + + return AddToIncludesForIDLType($type, \%implIncludes, $conditional) +} - return if SkipIncludeHeader($type); +sub AddToIncludesForIDLType +{ + my ($type, $includesRef, $conditional) = @_; - # When we're finished with the one-file-per-class - # reorganization, we won't need these special cases. - if ($type eq "XPathNSResolver") { - $includesRef->{"JSXPathNSResolver.h"} = 1; - $includesRef->{"JSCustomXPathNSResolver.h"} = 1; - } elsif ($isCallback && $codeGenerator->IsWrapperType($type)) { - $includesRef->{"JS${type}.h"} = 1; - } elsif ($codeGenerator->GetSequenceType($type) or $codeGenerator->GetArrayType($type)) { - my $arrayType = $codeGenerator->GetArrayType($type); - my $sequenceType = $codeGenerator->GetSequenceType($type); - my $arrayOrSequenceType = $arrayType || $sequenceType; - - if ($arrayType eq "DOMString") { - $includesRef->{"JSDOMStringList.h"} = 1; - $includesRef->{"DOMStringList.h"} = 1; - } elsif ($codeGenerator->IsRefPtrType($arrayOrSequenceType)) { - $includesRef->{"JS${arrayOrSequenceType}.h"} = 1; - $includesRef->{"${arrayOrSequenceType}.h"} = 1; + return if $codeGenerator->IsPrimitiveType($type); + return if $codeGenerator->IsStringType($type); + return if $codeGenerator->IsTypedArrayType($type); + return if $type->name eq "any"; + return if $type->name eq "object"; + + if ($type->isUnion) { + AddToIncludes("<wtf/Variant.h>", $includesRef, $conditional); + + foreach my $memberType (@{$type->subtypes}) { + AddToIncludesForIDLType($memberType, $includesRef, $conditional); } - $includesRef->{"<runtime/JSArray.h>"} = 1; - } else { - # default, include the same named file - $includesRef->{"${type}.h"} = 1; + + return; + } + + if ($codeGenerator->IsSequenceOrFrozenArrayType($type)) { + AddToIncludes("<runtime/JSArray.h>", $includesRef, $conditional); + AddToIncludesForIDLType(@{$type->subtypes}[0], $includesRef, $conditional); + return; + } + + if ($codeGenerator->IsRecordType($type)) { + AddToIncludes("<wtf/Vector.h>", $includesRef, $conditional); + AddToIncludesForIDLType(@{$type->subtypes}[0], $includesRef, $conditional); + AddToIncludesForIDLType(@{$type->subtypes}[1], $includesRef, $conditional); + return; + } + + if ($codeGenerator->IsWrapperType($type) || $codeGenerator->IsExternalDictionaryType($type) || $codeGenerator->IsExternalEnumType($type) || $type->name eq "EventListener") { + AddToIncludes("JS" . $type->name . ".h", $includesRef, $conditional); + return; + } + + if ($type->name eq "SerializedScriptValue") { + AddToIncludes($type->name . ".h", $includesRef, $conditional); + return; } } sub AddToImplIncludes { - my $header = shift; - my $conditional = shift; + my ($header, $conditional) = @_; - if (not $conditional) { - $implIncludes{$header} = 1; - } elsif (not exists($implIncludes{$header})) { - $implIncludes{$header} = $conditional; - } else { - my $oldValue = $implIncludes{$header}; - if ($oldValue ne 1) { - my %newValue = (); - $newValue{$conditional} = 1; - foreach my $condition (split(/\|/, $oldValue)) { - $newValue{$condition} = 1; - } - $implIncludes{$header} = join("|", sort keys %newValue); - } - } + AddToIncludes($header, \%implIncludes, $conditional); } -sub IsScriptProfileType +sub AddToIncludes { - my $type = shift; - return 1 if ($type eq "ScriptProfileNode"); - return 0; + my ($header, $includesRef, $conditional) = @_; + + if (not $conditional) { + $includesRef->{$header} = 1; + } elsif (not exists($includesRef->{$header})) { + $includesRef->{$header} = $conditional; + } else { + my $oldValue = $includesRef->{$header}; + $includesRef->{$header} = "$oldValue|$conditional" if $oldValue ne 1; + } } sub IsReadonly { my $attribute = shift; - return $attribute->isReadOnly && !$attribute->signature->extendedAttributes->{"Replaceable"}; + return $attribute->isReadOnly && !$attribute->extendedAttributes->{Replaceable} && !$attribute->extendedAttributes->{PutForwards}; } -sub AddTypedefForScriptProfileType +sub AddClassForwardIfNeeded { my $type = shift; - (my $jscType = $type) =~ s/Script//; - push(@headerContent, "typedef JSC::$jscType $type;\n\n"); -} + # SVGAnimatedLength/Number/etc. are not classes so they can't be forward declared as classes. + return if $codeGenerator->IsSVGAnimatedType($type); + return if $codeGenerator->IsTypedArrayType($type); + return if $type->name eq "BufferSource"; -sub AddClassForwardIfNeeded -{ - my $interfaceName = shift; - - # SVGAnimatedLength/Number/etc. are typedefs to SVGAnimatedTemplate, so don't use class forwards for them! - unless ($codeGenerator->IsSVGAnimatedType($interfaceName) or IsScriptProfileType($interfaceName) or $codeGenerator->IsTypedArrayType($interfaceName)) { - push(@headerContent, "class $interfaceName;\n\n"); - # ScriptProfile and ScriptProfileNode are typedefs to JSC::Profile and JSC::ProfileNode. - } elsif (IsScriptProfileType($interfaceName)) { - $headerIncludes{"<profiler/ProfileNode.h>"} = 1; - AddTypedefForScriptProfileType($interfaceName); - } + push(@headerContent, "class " . $type->name . ";\n\n"); } -sub hashTableAccessor +sub GetGenerateIsReachable { - my $noStaticTables = shift; - my $className = shift; - if ($noStaticTables) { - return "get${className}Table(exec->vm())"; - } else { - return "${className}Table"; - } + my $interface = shift; + return $interface->extendedAttributes->{GenerateIsReachable}; } -sub prototypeHashTableAccessor +sub GetCustomIsReachable { - my $noStaticTables = shift; - my $className = shift; - if ($noStaticTables) { - return "get${className}PrototypeTable(exec->vm())"; - } else { - return "${className}PrototypeTable"; - } + my $interface = shift; + return $interface->extendedAttributes->{CustomIsReachable}; } -sub constructorHashTableAccessor +sub IsDOMGlobalObject { - my $noStaticTables = shift; - my $constructorClassName = shift; - if ($noStaticTables) { - return "get${constructorClassName}Table(exec->vm())"; - } else { - return "${constructorClassName}Table"; - } + my $interface = shift; + return $interface->type->name eq "DOMWindow" || $codeGenerator->InheritsInterface($interface, "WorkerGlobalScope") || $interface->type->name eq "TestGlobalObject"; } -sub GetGenerateIsReachable +sub ShouldUseGlobalObjectPrototype { my $interface = shift; - return $interface->extendedAttributes->{"GenerateIsReachable"}; + + # For workers, the global object is a DedicatedWorkerGlobalScope. + return 0 if $interface->type->name eq "WorkerGlobalScope"; + + return IsDOMGlobalObject($interface); } -sub GetCustomIsReachable +sub GenerateIndexedGetter { - my $interface = shift; - return $interface->extendedAttributes->{"CustomIsReachable"}; + my ($interface, $indexedGetterFunction) = @_; + + my @output = (); + + my @attributes = (); + push(@attributes, "ReadOnly") if !$interface->extendedAttributes->{CustomNamedSetter}; + + my $attributeString = ((@attributes > 0) ? join(" | ", @attributes) : "0"); + + my $indexedGetterFunctionName = $indexedGetterFunction->name || "item"; + my $nativeToJSConversion = NativeToJSValueUsingPointers($indexedGetterFunction, $interface, "thisObject->wrapped().${indexedGetterFunctionName}(index)", "thisObject"); + + push(@output, " slot.setValue(thisObject, ${attributeString}, ${nativeToJSConversion});\n"); + push(@output, " return true;\n"); + + return @output; } -sub IsDOMGlobalObject +sub GenerateNamedGetter { - my $interface = shift; - return $interface->name eq "DOMWindow" || $codeGenerator->InheritsInterface($interface, "WorkerGlobalScope"); + my ($interface, $namedGetterFunction) = @_; + + my @output = (); + + my @attributes = (); + push(@attributes, "ReadOnly") if !$interface->extendedAttributes->{CustomNamedSetter}; + push(@attributes, "DontEnum") if $interface->extendedAttributes->{LegacyUnenumerableNamedProperties}; + + my $attributeString = ((@attributes > 0) ? join(" | ", @attributes) : "0"); + + if ($interface->extendedAttributes->{CustomNamedGetter}) { + push(@output, " JSValue value;\n"); + push(@output, " if (thisObject->nameGetter(state, propertyName, value)) {\n"); + push(@output, " slot.setValue(thisObject, ${attributeString}, value);\n"); + } else { + my $namedGetterFunctionName = $namedGetterFunction->name || "namedItem"; + my $itemVariable = "item"; + push(@output, " auto item = thisObject->wrapped().${namedGetterFunctionName}(propertyNameToAtomicString(propertyName));\n"); + + if ($namedGetterFunction->extendedAttributes->{MayThrowException}) { + push(@output, " if (item.hasException()) {\n"); + push(@output, " auto throwScope = DECLARE_THROW_SCOPE(state->vm());\n"); + push(@output, " propagateException(*state, throwScope, item.releaseException());\n"); + push(@output, " return true;\n"); + push(@output, " }\n\n"); + push(@output, " auto itemValue = item.releaseReturnValue();\n"); + + $itemVariable = "itemValue"; + } + + my $IDLType = GetIDLType($interface, $namedGetterFunction->type); + push(@output, " if (!${IDLType}::isNullValue(${itemVariable})) {\n"); + + my $nativeToJSConversion = NativeToJSValueUsingPointers($namedGetterFunction, $interface, $itemVariable, "thisObject", 1); + push(@output, " slot.setValue(thisObject, ${attributeString}, ${nativeToJSConversion});\n"); + } + + push(@output, " return true;\n"); + push(@output, " }\n"); + + return @output; } sub GenerateGetOwnPropertySlotBody { - my ($interface, $interfaceName, $className, $hasAttributes, $inlined) = @_; + my ($interface, $className, $indexedGetterFunction, $namedGetterFunction) = @_; - my $namespaceMaybe = ($inlined ? "JSC::" : ""); - my $namedGetterFunction = GetNamedGetterFunction($interface); - my $indexedGetterFunction = GetIndexedGetterFunction($interface); - my $hasNumericIndexedGetter = $indexedGetterFunction ? $codeGenerator->IsNumericType($indexedGetterFunction->signature->type) : 0; + my @output = (); - my @getOwnPropertySlotImpl = (); + my $ownPropertyCheck = sub { + push(@output, " if (Base::getOwnPropertySlot(thisObject, state, propertyName, slot))\n"); + push(@output, " return true;\n"); + }; - if ($interfaceName eq "NamedNodeMap" or $interfaceName =~ /^HTML\w*Collection$/) { - push(@getOwnPropertySlotImpl, " ${namespaceMaybe}JSValue proto = thisObject->prototype();\n"); - push(@getOwnPropertySlotImpl, " if (proto.isObject() && jsCast<${namespaceMaybe}JSObject*>(asObject(proto))->hasProperty(exec, propertyName))\n"); - push(@getOwnPropertySlotImpl, " return false;\n\n"); + # FIXME: As per the Web IDL specification, the prototype check is supposed to skip "named properties objects": + # https://heycam.github.io/webidl/#dfn-named-property-visibility + # https://heycam.github.io/webidl/#dfn-named-properties-object + my $prototypeCheck = sub { + push(@output, " JSValue proto = thisObject->getPrototypeDirect();\n"); + push(@output, " if (proto.isObject() && jsCast<JSObject*>(proto)->hasProperty(state, propertyName))\n"); + push(@output, " return false;\n\n"); + }; + + push(@output, "bool ${className}::getOwnPropertySlot(JSObject* object, ExecState* state, PropertyName propertyName, PropertySlot& slot)\n"); + push(@output, "{\n"); + push(@output, " auto* thisObject = jsCast<${className}*>(object);\n"); + push(@output, " ASSERT_GC_OBJECT_INHERITS(thisObject, info());\n"); + + + if ($indexedGetterFunction) { + push(@output, " auto optionalIndex = parseIndex(propertyName);\n"); + push(@output, " if (optionalIndex && optionalIndex.value() < thisObject->wrapped().length()) {\n"); + push(@output, " auto index = optionalIndex.value();\n"); + push(@output, GenerateIndexedGetter($interface, $indexedGetterFunction)); + push(@output, " }\n"); + } + + my $hasNamedGetter = $namedGetterFunction || $interface->extendedAttributes->{CustomNamedGetter}; + if ($hasNamedGetter) { + if (!$interface->extendedAttributes->{OverrideBuiltins}) { + &$ownPropertyCheck(); + &$prototypeCheck(); + } + if ($indexedGetterFunction) { + push(@output, " if (!optionalIndex && thisObject->classInfo() == info() && !propertyName.isSymbol()) {\n"); + } else { + push(@output, " if (thisObject->classInfo() == info() && !propertyName.isSymbol()) {\n"); + } + push(@output, GenerateNamedGetter($interface, $namedGetterFunction)); + push(@output, " }\n"); + } + + if ($interface->extendedAttributes->{JSCustomGetOwnPropertySlotAndDescriptor}) { + push(@output, " if (thisObject->getOwnPropertySlotDelegate(state, propertyName, slot))\n"); + push(@output, " return true;\n"); + } + + if (!$hasNamedGetter || $interface->extendedAttributes->{OverrideBuiltins}) { + &$ownPropertyCheck(); } - my $manualLookupGetterGeneration = sub { - my $requiresManualLookup = ($indexedGetterFunction && !$hasNumericIndexedGetter) || $namedGetterFunction; - if ($requiresManualLookup) { - push(@getOwnPropertySlotImpl, " const ${namespaceMaybe}HashEntry* entry = getStaticValueSlotEntryWithoutCaching<$className>(exec, propertyName);\n"); - push(@getOwnPropertySlotImpl, " if (entry) {\n"); - push(@getOwnPropertySlotImpl, " slot.setCustom(thisObject, entry->attributes(), entry->propertyGetter());\n"); - push(@getOwnPropertySlotImpl, " return true;\n"); - push(@getOwnPropertySlotImpl, " }\n"); + push(@output, " return false;\n"); + push(@output, "}\n\n"); + + return @output; +} + +sub GenerateGetOwnPropertySlotBodyByIndex +{ + my ($interface, $className, $indexedGetterFunction, $namedGetterFunction) = @_; + + my @output = (); + + push(@output, "bool ${className}::getOwnPropertySlotByIndex(JSObject* object, ExecState* state, unsigned index, PropertySlot& slot)\n"); + push(@output, "{\n"); + push(@output, " auto* thisObject = jsCast<${className}*>(object);\n"); + push(@output, " ASSERT_GC_OBJECT_INHERITS(thisObject, info());\n"); + + # Sink the int-to-string conversion that happens when we create a PropertyName + # to the point where we actually need it. + my $generatedPropertyName = 0; + my $propertyNameGeneration = sub { + if ($generatedPropertyName) { + return; } + push(@output, " Identifier propertyName = Identifier::from(state, index);\n"); + $generatedPropertyName = 1; }; + + if ($indexedGetterFunction) { + push(@output, " if (LIKELY(index < thisObject->wrapped().length())) {\n"); + push(@output, GenerateIndexedGetter($interface, $indexedGetterFunction)); + push(@output, " }\n"); + } - if (!$interface->extendedAttributes->{"CustomNamedGetter"}) { - &$manualLookupGetterGeneration(); + # Indexing an object with an integer that is not a supported property index should not call the named property getter. + # https://heycam.github.io/webidl/#idl-indexed-properties + if (!$indexedGetterFunction && ($namedGetterFunction || $interface->extendedAttributes->{CustomNamedGetter})) { + &$propertyNameGeneration(); + push(@output, " if (thisObject->classInfo() == info()) {\n"); + push(@output, GenerateNamedGetter($interface, $namedGetterFunction)); + push(@output, " }\n"); } - if ($indexedGetterFunction) { - push(@getOwnPropertySlotImpl, " unsigned index = propertyName.asIndex();\n"); + if ($interface->extendedAttributes->{JSCustomGetOwnPropertySlotAndDescriptor}) { + &$propertyNameGeneration(); + push(@output, " if (thisObject->getOwnPropertySlotDelegate(state, propertyName, slot))\n"); + push(@output, " return true;\n"); + } - # If the item function returns a string then we let the TreatReturnedNullStringAs handle the cases - # where the index is out of range. - if ($indexedGetterFunction->signature->type eq "DOMString") { - push(@getOwnPropertySlotImpl, " if (index != PropertyName::NotAnIndex) {\n"); - } else { - push(@getOwnPropertySlotImpl, " if (index != PropertyName::NotAnIndex && index < thisObject->impl().length()) {\n"); - } - # Assume that if there's a setter, the index will be writable - if ($interface->extendedAttributes->{"CustomIndexedSetter"}) { - push(@getOwnPropertySlotImpl, " unsigned attributes = ${namespaceMaybe}DontDelete;\n"); - } else { - push(@getOwnPropertySlotImpl, " unsigned attributes = ${namespaceMaybe}DontDelete | ${namespaceMaybe}ReadOnly;\n"); - } - if ($hasNumericIndexedGetter) { - push(@getOwnPropertySlotImpl, " slot.setValue(thisObject, attributes, thisObject->getByIndex(exec, index));\n"); + push(@output, " return Base::getOwnPropertySlotByIndex(thisObject, state, index, slot);\n"); + push(@output, "}\n\n"); + + return @output; +} + +sub GenerateGetOwnPropertyNames +{ + my ($interface, $className, $indexedGetterFunction, $namedGetterFunction) = @_; + + my @output = (); + + # Property enumeration - https://heycam.github.io/webidl/#legacy-platform-object-property-enumeration + + push(@implContent, "void ${className}::getOwnPropertyNames(JSObject* object, ExecState* state, PropertyNameArray& propertyNames, EnumerationMode mode)\n"); + push(@implContent, "{\n"); + push(@implContent, " auto* thisObject = jsCast<${className}*>(object);\n"); + push(@implContent, " ASSERT_GC_OBJECT_INHERITS(thisObject, info());\n"); + + # 1. If the object supports indexed properties, then the object’s supported + # property indices are enumerated first, in numerical order. + if ($indexedGetterFunction) { + push(@implContent, " for (unsigned i = 0, count = thisObject->wrapped().length(); i < count; ++i)\n"); + push(@implContent, " propertyNames.add(Identifier::from(state, i));\n"); + } + + # 2. If the object supports named properties and doesn’t implement an interface + # with the [LegacyUnenumerableNamedProperties] extended attribute, then the + # object’s supported property names that are visible according to the named + # property visibility algorithm are enumerated next, in the order given in + # the definition of the set of supported property names. + if ($namedGetterFunction) { + if (!$interface->extendedAttributes->{LegacyUnenumerableNamedProperties}) { + push(@implContent, " for (auto& propertyName : thisObject->wrapped().supportedPropertyNames())\n"); + push(@implContent, " propertyNames.add(Identifier::fromString(state, propertyName));\n"); } else { - push(@getOwnPropertySlotImpl, " slot.setCustomIndex(thisObject, attributes, index, indexGetter);\n"); + push(@implContent, " if (mode.includeDontEnumProperties()) {\n"); + push(@implContent, " for (auto& propertyName : thisObject->wrapped().supportedPropertyNames())\n"); + push(@implContent, " propertyNames.add(Identifier::fromString(state, propertyName));\n"); + push(@implContent, " }\n"); } - push(@getOwnPropertySlotImpl, " return true;\n"); - push(@getOwnPropertySlotImpl, " }\n"); } + # 3. Finally, any enumerable own properties or properties from the object’s + # prototype chain are then enumerated, in no defined order. + push(@implContent, " Base::getOwnPropertyNames(thisObject, state, propertyNames, mode);\n"); + push(@implContent, "}\n\n"); - if ($namedGetterFunction || $interface->extendedAttributes->{"CustomNamedGetter"}) { - push(@getOwnPropertySlotImpl, " if (canGetItemsForName(exec, &thisObject->impl(), propertyName)) {\n"); - push(@getOwnPropertySlotImpl, " slot.setCustom(thisObject, ReadOnly | DontDelete | DontEnum, thisObject->nameGetter);\n"); - push(@getOwnPropertySlotImpl, " return true;\n"); - push(@getOwnPropertySlotImpl, " }\n"); - if ($inlined) { - $headerIncludes{"wtf/text/AtomicString.h"} = 1; + return @output; +} + +sub GeneratePut +{ + my ($interface, $className, $indexedSetterFunction, $namedSetterFunction) = @_; + + assert("Named setters are not supported.") if $namedSetterFunction; + + my @output = (); + + push(@output, "bool ${className}::put(JSCell* cell, ExecState* state, PropertyName propertyName, JSValue value, PutPropertySlot& slot)\n"); + push(@output, "{\n"); + push(@output, " auto* thisObject = jsCast<${className}*>(cell);\n"); + push(@output, " ASSERT_GC_OBJECT_INHERITS(thisObject, info());\n"); + + if ($indexedSetterFunction || $interface->extendedAttributes->{CustomIndexedSetter}) { + if ($interface->extendedAttributes->{CustomIndexedSetter}) { + push(@output, " if (auto index = parseIndex(propertyName)) {\n"); + push(@output, " thisObject->indexSetter(state, index.value(), value);\n"); + push(@output, " return true;\n"); + push(@output, " }\n"); } else { - $implIncludes{"wtf/text/AtomicString.h"} = 1; + # The second argument of the indexed setter function is the argument being converted. + my $argument = @{$indexedSetterFunction->arguments}[1]; + my ($nativeValue, $mayThrowException) = JSValueToNative($interface, $argument, "value", $indexedSetterFunction->extendedAttributes->{Conditional}, "state", "*state", "thisObject", "", ""); + + push(@output, " if (auto index = parseIndex(propertyName)) {\n"); + push(@output, " auto throwScope = DECLARE_THROW_SCOPE(state->vm());\n"); + push(@output, " auto nativeValue = ${nativeValue};\n"); + push(@output, " RETURN_IF_EXCEPTION(throwScope, true);\n") if $mayThrowException; + + my $indexedSetterFunctionName = $indexedSetterFunction->name || "setItem"; + my $functionString = "${indexedSetterFunctionName}(index, WTFMove(nativeValue))"; + $functionString = "propagateException(*state, throwScope, ${functionString})" if NeedsExplicitPropagateExceptionCall($indexedSetterFunction); + + push(@output, " ${functionString};\n"); + push(@output, " return true;\n"); + push(@output, " }\n"); } } - - if ($interface->extendedAttributes->{"CustomNamedGetter"}) { - &$manualLookupGetterGeneration(); + + if ($interface->extendedAttributes->{CustomNamedSetter}) { + push(@output, " bool putResult = false;\n"); + push(@output, " if (thisObject->putDelegate(state, propertyName, value, slot, putResult))\n"); + push(@output, " return putResult;\n"); } - if ($interface->extendedAttributes->{"JSCustomGetOwnPropertySlotAndDescriptor"}) { - push(@getOwnPropertySlotImpl, " if (thisObject->getOwnPropertySlotDelegate(exec, propertyName, slot))\n"); - push(@getOwnPropertySlotImpl, " return true;\n"); - } + push(@output, " return Base::put(thisObject, state, propertyName, value, slot);\n"); + push(@output, "}\n\n"); + + return @output; +} + +sub GeneratePutByIndex +{ + my ($interface, $className, $indexedSetterFunction, $namedSetterFunction) = @_; + + assert("Named setters are not supported.") if $namedSetterFunction; + + my @output = (); - if ($hasAttributes) { - if ($inlined) { - die "Cannot inline if NoStaticTables is set." if ($interface->extendedAttributes->{"JSNoStaticTables"}); - push(@getOwnPropertySlotImpl, " return ${namespaceMaybe}getStaticValueSlot<$className, Base>(exec, *info()->staticPropHashTable, thisObject, propertyName, slot);\n"); + push(@output, "bool ${className}::putByIndex(JSCell* cell, ExecState* state, unsigned index, JSValue value, bool shouldThrow)\n"); + push(@output, "{\n"); + push(@output, " auto* thisObject = jsCast<${className}*>(cell);\n"); + push(@output, " ASSERT_GC_OBJECT_INHERITS(thisObject, info());\n"); + + if ($indexedSetterFunction || $interface->extendedAttributes->{CustomIndexedSetter}) { + if ($interface->extendedAttributes->{CustomIndexedSetter}) { + push(@output, " if (LIKELY(index <= MAX_ARRAY_INDEX)) {\n"); + push(@output, " thisObject->indexSetter(state, index, value);\n"); + push(@output, " return true;\n"); + push(@output, " }\n"); } else { - push(@getOwnPropertySlotImpl, " return ${namespaceMaybe}getStaticValueSlot<$className, Base>(exec, " . hashTableAccessor($interface->extendedAttributes->{"JSNoStaticTables"}, $className) . ", thisObject, propertyName, slot);\n"); + # The second argument of the indexed setter function is the argument being converted. + my $argument = @{$indexedSetterFunction->arguments}[1]; + my ($nativeValue, $mayThrowException) = JSValueToNative($interface, $argument, "value", $indexedSetterFunction->extendedAttributes->{Conditional}, "state", "*state", "thisObject", "", ""); + + push(@output, " if (LIKELY(index <= MAX_ARRAY_INDEX)) {\n"); + push(@output, " auto throwScope = DECLARE_THROW_SCOPE(state->vm());\n"); + push(@output, " auto nativeValue = ${nativeValue};\n"); + push(@output, " RETURN_IF_EXCEPTION(throwScope, true);\n") if $mayThrowException; + + my $indexedSetterFunctionName = $indexedSetterFunction->name || "setItem"; + my $functionString = "${indexedSetterFunctionName}(index, WTFMove(nativeValue))"; + $functionString = "propagateException(*state, throwScope, ${functionString})" if NeedsExplicitPropagateExceptionCall($indexedSetterFunction); + + push(@output, " ${functionString};\n"); + push(@output, " return true;\n"); + push(@output, " }\n"); } - } else { - push(@getOwnPropertySlotImpl, " return Base::getOwnPropertySlot(thisObject, exec, propertyName, slot);\n"); } - return @getOwnPropertySlotImpl; + if ($interface->extendedAttributes->{CustomNamedSetter}) { + push(@output, " Identifier propertyName = Identifier::from(state, index);\n"); + push(@output, " PutPropertySlot slot(thisObject, shouldThrow);\n"); + push(@output, " bool putResult = false;\n"); + push(@output, " if (thisObject->putDelegate(state, propertyName, value, slot, putResult))\n"); + push(@output, " return putResult;\n"); + } + + push(@output, " return Base::putByIndex(cell, state, index, value, shouldThrow);\n"); + push(@output, "}\n\n"); + + return @output; } sub GenerateHeaderContentHeader { my $interface = shift; - my $className = "JS" . $interface->name; + my $className = "JS" . $interface->type->name; my @headerContentHeader; - if ($interface->extendedAttributes->{"AppleCopyright"}) { + if ($interface->extendedAttributes->{AppleCopyright}) { @headerContentHeader = split("\r", $beginAppleCopyrightForHeaderFiles); } else { @headerContentHeader = split("\r", $headerTemplate); } - # - Add header protection - push(@headerContentHeader, "\n#ifndef $className" . "_h"); - push(@headerContentHeader, "\n#define $className" . "_h\n\n"); + push(@headerContentHeader, "\n#pragma once\n\n"); my $conditionalString = $codeGenerator->GenerateConditionalString($interface); push(@headerContentHeader, "#if ${conditionalString}\n\n") if $conditionalString; @@ -501,10 +729,10 @@ sub GenerateHeaderContentHeader sub GenerateImplementationContentHeader { my $interface = shift; - my $className = "JS" . $interface->name; + my $className = "JS" . $interface->type->name; my @implContentHeader; - if ($interface->extendedAttributes->{"AppleCopyright"}) { + if ($interface->extendedAttributes->{AppleCopyright}) { @implContentHeader = split("\r", $beginAppleCopyrightForSourceFiles); } else { @implContentHeader = split("\r", $headerTemplate); @@ -517,54 +745,157 @@ sub GenerateImplementationContentHeader return @implContentHeader; } -my %usesToJSNewlyCreated = ( - "CDATASection" => 1, - "Element" => 1, - "Node" => 1, - "Text" => 1, - "Touch" => 1, - "TouchList" => 1 -); +sub NeedsImplementationClass +{ + my ($interface) = @_; + + return 0 if $interface->extendedAttributes->{JSBuiltin}; + return 1; +} + +sub ShouldGenerateToWrapped +{ + my ($hasParent, $interface) = @_; + + return 0 if not NeedsImplementationClass($interface); + return 1 if !$hasParent or $interface->extendedAttributes->{JSGenerateToNativeObject}; + return 1 if $interface->parentType && $interface->parentType->name eq "EventTarget"; + return 0; +} + +sub ShouldGenerateWrapperOwnerCode +{ + my ($hasParent, $interface) = @_; + + return 0 if not NeedsImplementationClass($interface); + return 1 if !$hasParent; + return 1 if GetGenerateIsReachable($interface); + return 1 if GetCustomIsReachable($interface); + return 1 if $interface->extendedAttributes->{JSCustomFinalize}; + return 1 if $codeGenerator->InheritsExtendedAttribute($interface, "ActiveDOMObject"); + return 0; +} sub ShouldGenerateToJSDeclaration { my ($hasParent, $interface) = @_; - return 0 if ($interface->extendedAttributes->{"SuppressToJSObject"}); - return 1 if (!$hasParent or $interface->extendedAttributes->{"JSGenerateToJSObject"} or $interface->extendedAttributes->{"CustomToJSObject"}); + + return 0 if ($interface->extendedAttributes->{SuppressToJSObject}); + return 0 if not NeedsImplementationClass($interface); + return 0 if $interface->extendedAttributes->{CustomProxyToJSObject}; + return 1 if (!$hasParent or $interface->extendedAttributes->{JSGenerateToJSObject} or $interface->extendedAttributes->{CustomToJSObject}); + return 1 if $interface->parentType && $interface->parentType->name eq "EventTarget"; + return 1 if $interface->extendedAttributes->{Constructor} or $interface->extendedAttributes->{NamedConstructor}; return 0; } sub ShouldGenerateToJSImplementation { my ($hasParent, $interface) = @_; - return 0 if ($interface->extendedAttributes->{"SuppressToJSObject"}); - return 1 if ((!$hasParent or $interface->extendedAttributes->{"JSGenerateToJSObject"}) and !$interface->extendedAttributes->{"CustomToJSObject"}); + + return 0 if not ShouldGenerateToJSDeclaration($hasParent, $interface); + return 1 if not $interface->extendedAttributes->{CustomToJSObject}; return 0; } -sub GetAttributeGetterName +sub GetArgumentExceptionFunction { - my ($interfaceName, $className, $attribute) = @_; - if ($attribute->isStatic) { - return $codeGenerator->WK_lcfirst($className) . "Constructor" . $codeGenerator->WK_ucfirst($attribute->signature->name); + my ($interface, $argument, $argumentIndex, $quotedFunctionName) = @_; + + my $name = $argument->name; + my $visibleInterfaceName = $codeGenerator->GetVisibleInterfaceName($interface); + my $typeName = $argument->type->name; + + if ($codeGenerator->IsCallbackInterface($argument->type) || $codeGenerator->IsCallbackFunction($argument->type)) { + # FIXME: We should have specialized messages for callback interfaces vs. callback functions. + return "throwArgumentMustBeFunctionError(state, scope, ${argumentIndex}, \"${name}\", \"${visibleInterfaceName}\", ${quotedFunctionName});"; } - return "js" . $interfaceName . $codeGenerator->WK_ucfirst($attribute->signature->name) . ($attribute->signature->type =~ /Constructor$/ ? "Constructor" : ""); + + if ($codeGenerator->IsWrapperType($argument->type) || $codeGenerator->IsTypedArrayType($argument->type)) { + return "throwArgumentTypeError(state, scope, ${argumentIndex}, \"${name}\", \"${visibleInterfaceName}\", ${quotedFunctionName}, \"${typeName}\");"; + } + + return undef; } -sub GetAttributeSetterName +sub GetArgumentExceptionThrower { - my ($interfaceName, $className, $attribute) = @_; - if ($attribute->isStatic) { - return "set" . $codeGenerator->WK_ucfirst($className) . "Constructor" . $codeGenerator->WK_ucfirst($attribute->signature->name); + my ($interface, $argument, $argumentIndex, $quotedFunctionName) = @_; + + my $functionCall = GetArgumentExceptionFunction($interface, $argument, $argumentIndex, $quotedFunctionName); + return "[](JSC::ExecState& state, JSC::ThrowScope& scope) { " . $functionCall . " }" if $functionCall; +} + +sub GetAttributeExceptionFunction +{ + my ($interface, $attribute) = @_; + + my $name = $attribute->name; + my $visibleInterfaceName = $codeGenerator->GetVisibleInterfaceName($interface); + my $typeName = $attribute->type->name; + + if ($codeGenerator->IsWrapperType($attribute->type) || $codeGenerator->IsTypedArrayType($attribute->type)) { + return "throwAttributeTypeError(state, scope, \"${visibleInterfaceName}\", \"${name}\", \"${typeName}\");"; } - return "setJS" . $interfaceName . $codeGenerator->WK_ucfirst($attribute->signature->name) . ($attribute->signature->type =~ /Constructor$/ ? "Constructor" : ""); +} + +sub GetAttributeExceptionThrower +{ + my ($interface, $attribute) = @_; + + my $functionCall = GetAttributeExceptionFunction($interface, $attribute); + return "[](JSC::ExecState& state, JSC::ThrowScope& scope) { " . $functionCall . " }" if $functionCall; + +} + +sub PassArgumentExpression +{ + my ($name, $context) = @_; + + my $type = $context->type; + + return "${name}.value()" if $codeGenerator->IsEnumType($type); + return "WTFMove(${name})" if $type->isNullable; + + if ($codeGenerator->IsTypedArrayType($type)) { + return "*${name}" if $type->name eq "ArrayBuffer"; + return "${name}.releaseNonNull()"; + } + + return "${name}.releaseNonNull()" if $codeGenerator->IsCallbackInterface($type) || $codeGenerator->IsCallbackFunction($type); + return "*${name}" if $codeGenerator->IsWrapperType($type); + return "WTFMove(${name})"; +} + +sub GetAttributeGetterName +{ + my ($interface, $className, $attribute) = @_; + + return $codeGenerator->WK_lcfirst($className) . "Constructor" . $codeGenerator->WK_ucfirst($attribute->name) if $attribute->isStatic; + return GetJSBuiltinFunctionName($className, $attribute) if IsJSBuiltin($interface, $attribute); + return "js" . $interface->type->name . $codeGenerator->WK_ucfirst($attribute->name) . ($codeGenerator->IsConstructorType($attribute->type) ? "Constructor" : ""); +} + +sub GetAttributeSetterName +{ + my ($interface, $className, $attribute) = @_; + + return "set" . $codeGenerator->WK_ucfirst($className) . "Constructor" . $codeGenerator->WK_ucfirst($attribute->name) if $attribute->isStatic; + return "set" . $codeGenerator->WK_ucfirst(GetJSBuiltinFunctionName($className, $attribute)) if IsJSBuiltin($interface, $attribute); + return "setJS" . $interface->type->name . $codeGenerator->WK_ucfirst($attribute->name) . ($codeGenerator->IsConstructorType($attribute->type) ? "Constructor" : ""); } sub GetFunctionName { - my ($className, $function) = @_; - my $kind = $function->isStatic ? "Constructor" : "Prototype"; - return $codeGenerator->WK_lcfirst($className) . $kind . "Function" . $codeGenerator->WK_ucfirst($function->signature->name); + my ($interface, $className, $function) = @_; + + return GetJSBuiltinFunctionName($className, $function) if IsJSBuiltin($interface, $function); + + my $functionName = $function->name; + $functionName = "SymbolIterator" if $functionName eq "[Symbol.Iterator]"; + + my $kind = $function->isStatic ? "Constructor" : (OperationShouldBeOnInstance($interface, $function) ? "Instance" : "Prototype"); + return $codeGenerator->WK_lcfirst($className) . $kind . "Function" . $codeGenerator->WK_ucfirst($functionName); } sub GetSpecialAccessorFunctionForType @@ -575,10 +906,10 @@ sub GetSpecialAccessorFunctionForType my $numberOfParameters = shift; foreach my $function (@{$interface->functions}, @{$interface->anonymousFunctions}) { - my $specials = $function->signature->specials; + my $specials = $function->specials; my $specialExists = grep { $_ eq $special } @$specials; - my $parameters = $function->parameters; - if ($specialExists and scalar(@$parameters) == $numberOfParameters and $parameters->[0]->type eq $firstParameterType) { + my $arguments = $function->arguments; + if ($specialExists and scalar(@$arguments) == $numberOfParameters and $arguments->[0]->type->name eq $firstParameterType) { return $function; } } @@ -586,76 +917,787 @@ sub GetSpecialAccessorFunctionForType return 0; } +sub HasComplexGetOwnProperty +{ + my $interface = shift; + return $interface->extendedAttributes->{CheckSecurity} + || IsDOMGlobalObject($interface) + || InstanceOverridesGetOwnPropertySlot($interface); +} + +sub IsGlobalOrPrimaryGlobalInterface +{ + my $interface = shift; + + return $interface->extendedAttributes->{Global} || $interface->extendedAttributes->{PrimaryGlobal}; +} + +sub InterfaceRequiresAttributesOnInstance +{ + my $interface = shift; + my $interfaceName = $interface->type->name; + + # FIXME: All these return 1 if ... should ideally be removed. + # Some of them are unavoidable due to DOM weirdness, in which case we should + # add an IDL attribute for them. + + # FIXME: We should be able to drop this once <rdar://problem/24466097> is fixed. + return 1 if $interface->isException; + + return 1 if IsGlobalOrPrimaryGlobalInterface($interface); + + return 0; +} + +sub AttributeShouldBeOnInstance +{ + my $interface = shift; + my $attribute = shift; + + return 1 if InterfaceRequiresAttributesOnInstance($interface); + return 1 if $codeGenerator->IsConstructorType($attribute->type); + + # [Unforgeable] attributes should be on the instance. + # https://heycam.github.io/webidl/#Unforgeable + return 1 if IsUnforgeable($interface, $attribute); + + if ($interface->extendedAttributes->{CheckSecurity}) { + return 0 if $attribute->extendedAttributes->{DoNotCheckSecurity}; + return 0 if $attribute->extendedAttributes->{DoNotCheckSecurityOnGetter}; + return 1; + } + + return 0; +} + +sub NeedsRuntimeCheck +{ + my $interface = shift; + return $interface->extendedAttributes->{EnabledAtRuntime} + || $interface->extendedAttributes->{EnabledForWorld}; +} + +# https://heycam.github.io/webidl/#es-operations +sub OperationShouldBeOnInstance +{ + my $interface = shift; + my $function = shift; + + return 1 if IsGlobalOrPrimaryGlobalInterface($interface); + + # FIXME: The bindings generator does not support putting runtime-enabled operations on the instance yet (except for global objects). + return 0 if NeedsRuntimeCheck($function); + + # [Unforgeable] operations should be on the instance. https://heycam.github.io/webidl/#Unforgeable + return 1 if IsUnforgeable($interface, $function); + + return 0; +} + +sub GetJSCAttributesForAttribute +{ + my $interface = shift; + my $attribute = shift; + + my @specials = (); + push(@specials, "DontDelete") if IsUnforgeable($interface, $attribute); + + # As per Web IDL specification, constructor properties on the ECMAScript global object should not be enumerable. + my $isGlobalConstructor = $codeGenerator->IsConstructorType($attribute->type); + push(@specials, "DontEnum") if ($attribute->extendedAttributes->{NotEnumerable} || $isGlobalConstructor); + push(@specials, "ReadOnly") if IsReadonly($attribute); + push(@specials, "CustomAccessor") unless $isGlobalConstructor or IsJSBuiltin($interface, $attribute); + push(@specials, "DOMJITAttribute") if $attribute->extendedAttributes->{"DOMJIT"}; + push(@specials, "Accessor | Builtin") if IsJSBuiltin($interface, $attribute); + return (@specials > 0) ? join(" | ", @specials) : "0"; +} + sub GetIndexedGetterFunction { my $interface = shift; return GetSpecialAccessorFunctionForType($interface, "getter", "unsigned long", 1); } +sub GetIndexedSetterFunction +{ + my $interface = shift; + return GetSpecialAccessorFunctionForType($interface, "setter", "unsigned long", 2); +} + sub GetNamedGetterFunction { my $interface = shift; return GetSpecialAccessorFunctionForType($interface, "getter", "DOMString", 1); } -sub InstanceOverridesGetOwnPropertySlot +sub GetNamedSetterFunction { my $interface = shift; - my $numAttributes = @{$interface->attributes}; + return GetSpecialAccessorFunctionForType($interface, "setter", "DOMString", 2); +} - my $namedGetterFunction = GetNamedGetterFunction($interface); - my $indexedGetterFunction = GetIndexedGetterFunction($interface); - my $hasNumericIndexedGetter = $indexedGetterFunction ? $codeGenerator->IsNumericType($indexedGetterFunction->signature->type) : 0; +sub GetNamedDeleterFunction +{ + my $interface = shift; + return GetSpecialAccessorFunctionForType($interface, "deleter", "DOMString", 1); +} - my $hasImpureNamedGetter = $namedGetterFunction - || $interface->extendedAttributes->{"CustomNamedGetter"} - || $interface->extendedAttributes->{"CustomGetOwnPropertySlot"}; +sub InstanceFunctionCount +{ + my $interface = shift; + my $count = 0; - my $hasComplexGetter = $indexedGetterFunction - || $interface->extendedAttributes->{"JSCustomGetOwnPropertySlotAndDescriptor"} - || $hasImpureNamedGetter; + foreach my $function (@{$interface->functions}) { + $count++ if OperationShouldBeOnInstance($interface, $function); + } + + return $count; +} + +sub PrototypeFunctionCount +{ + my $interface = shift; + my $count = 0; + + foreach my $function (@{$interface->functions}) { + $count++ if !$function->isStatic && !OperationShouldBeOnInstance($interface, $function); + } - return $numAttributes > 0 || !$interface->extendedAttributes->{"NoInterfaceObject"} || $hasComplexGetter; + $count += scalar @{$interface->iterable->functions} if $interface->iterable; + $count += scalar @{$interface->serializable->functions} if $interface->serializable; + + return $count; +} +sub InstancePropertyCount +{ + my $interface = shift; + my $count = 0; + foreach my $attribute (@{$interface->attributes}) { + $count++ if AttributeShouldBeOnInstance($interface, $attribute); + } + $count += InstanceFunctionCount($interface); + return $count; +} + +sub PrototypePropertyCount +{ + my $interface = shift; + my $count = 0; + foreach my $attribute (@{$interface->attributes}) { + $count++ if !AttributeShouldBeOnInstance($interface, $attribute); + } + $count += PrototypeFunctionCount($interface); + $count++ if NeedsConstructorProperty($interface); + return $count; +} + +sub InstanceOverridesGetOwnPropertySlot +{ + my $interface = shift; + return $interface->extendedAttributes->{CustomGetOwnPropertySlot} + || $interface->extendedAttributes->{CustomNamedGetter} + || $interface->extendedAttributes->{JSCustomGetOwnPropertySlotAndDescriptor} + || GetIndexedGetterFunction($interface) + || GetNamedGetterFunction($interface); +} + +sub InstanceOverridesPut +{ + my $interface = shift; + return $interface->extendedAttributes->{CustomNamedSetter} + || $interface->extendedAttributes->{CustomIndexedSetter} + || GetIndexedSetterFunction($interface) + || GetNamedSetterFunction($interface); } -sub PrototypeOverridesGetOwnPropertySlot +sub PrototypeHasStaticPropertyTable { my $interface = shift; my $numConstants = @{$interface->constants}; - my $numFunctions = @{$interface->functions}; - return $numFunctions > 0 || $numConstants > 0; + return $numConstants > 0 || PrototypePropertyCount($interface) > 0; } sub InstanceOverridesPutImplementation { my $interface = shift; - return $interface->extendedAttributes->{"CustomNamedSetter"} - || $interface->extendedAttributes->{"CustomIndexedSetter"}; + return $interface->extendedAttributes->{CustomNamedSetter} + || $interface->extendedAttributes->{CustomIndexedSetter}; } sub InstanceOverridesPutDeclaration { my $interface = shift; - return $interface->extendedAttributes->{"CustomPutFunction"} - || $interface->extendedAttributes->{"CustomNamedSetter"} - || $interface->extendedAttributes->{"CustomIndexedSetter"}; + return $interface->extendedAttributes->{CustomPutFunction} + || $interface->extendedAttributes->{CustomNamedSetter} + || $interface->extendedAttributes->{CustomIndexedSetter}; } -sub GenerateHeader +sub InstanceNeedsVisitChildren +{ + my $interface = shift; + return $interface->extendedAttributes->{JSCustomMarkFunction} + || $codeGenerator->InheritsInterface($interface, "EventTarget") + || $interface->type->name eq "EventTarget" + || $interface->extendedAttributes->{ReportExtraMemoryCost} + || IsJSBuiltinConstructor($interface) +} + +sub InstanceNeedsEstimatedSize +{ + my $interface = shift; + return $interface->extendedAttributes->{ReportExtraMemoryCost}; +} + +sub GetImplClassName { - my $object = shift; my $interface = shift; - my $interfaceName = $interface->name; + return $interface->type->name; +} + +sub IsClassNameWordBoundary +{ + my ($name, $i) = @_; + + # Interpret negative numbers as distance from end of string, just as the substr function does. + $i += length($name) if $i < 0; + + return 0 if $i < 0; + return 1 if $i == 0; + return 1 if $i == length($name); + return 0 if $i > length($name); + + my $checkString = substr($name, $i - 1); + return $checkString =~ /^[^A-Z][A-Z]/ || $checkString =~ /^[A-Z][A-Z][^A-Z]/; +} + +sub IsPrefixRemovable +{ + my ($class, $name, $i) = @_; + + return IsClassNameWordBoundary($name, $i) + && (IsClassNameWordBoundary($class, $i) && substr($class, 0, $i) eq substr($name, 0, $i) + || IsClassNameWordBoundary($class, -$i) && substr($class, -$i) eq substr($name, 0, $i)); +} + +sub GetNestedClassName +{ + my ($interface, $name) = @_; + + my $class = GetImplClassName($interface); + my $member = $codeGenerator->WK_ucfirst($name); + + # Since the enumeration name will be nested in the class name's namespace, remove any words + # that happen to match the start or end of the class name. If an enumeration is named TrackType or + # TextTrackType, and the class is named TextTrack, then we will get a name like TextTrack::Type. + my $memberLength = length($member); + my $longestPrefixLength = 0; + if ($member =~ /^[A-Z]./) { + for (my $i = 2; $i < $memberLength - 1; $i++) { + $longestPrefixLength = $i if IsPrefixRemovable($class, $member, $i); + } + } + $member = substr($member, $longestPrefixLength); + + return "${class}::$member"; +} + +sub GetEnumerationClassName +{ + my ($type, $interface) = @_; + + assert("Not a type") if ref($type) ne "IDLType"; + + if ($codeGenerator->HasEnumImplementationNameOverride($type)) { + return $codeGenerator->GetEnumImplementationNameOverride($type); + } + + my $name = $type->name; + + return $name if $codeGenerator->IsExternalEnumType($type); + return $name unless defined($interface); + + return GetNestedClassName($interface, $name); +} + +sub GetEnumerationValueName +{ + my ($name) = @_; + + return "EmptyString" if $name eq ""; + $name = join("", map { $codeGenerator->WK_ucfirst($_) } split("-", $name)); + $name = "_$name" if $name =~ /^\d/; + return $name; +} + +sub GenerateEnumerationHeader +{ + my ($object, $enumeration, $className) = @_; + + # - Add default header template and header protection. + push(@headerContentHeader, GenerateHeaderContentHeader($enumeration)); + + $headerIncludes{"$className.h"} = 1; + $headerIncludes{"JSDOMConvert.h"} = 1; + + push(@headerContent, "\nnamespace WebCore {\n\n"); + push(@headerContent, GenerateEnumerationHeaderContent($enumeration, $className)); + push(@headerContent, "} // namespace WebCore\n"); + + my $conditionalString = $codeGenerator->GenerateConditionalString($enumeration); + push(@headerContent, "\n#endif // ${conditionalString}\n") if $conditionalString; +} + +sub GenerateEnumerationImplementation +{ + my ($object, $enumeration, $className) = @_; + + # - Add default header template + push(@implContentHeader, GenerateImplementationContentHeader($enumeration)); + + # FIXME: A little ugly to have this be a side effect instead of a return value. + AddToImplIncludes("<runtime/JSString.h>"); + AddToImplIncludes("JSDOMConvert.h"); + + push(@implContent, "\nusing namespace JSC;\n\n"); + push(@implContent, "namespace WebCore {\n\n"); + push(@implContent, GenerateEnumerationImplementationContent($enumeration, $className)); + push(@implContent, "} // namespace WebCore\n"); + + my $conditionalString = $codeGenerator->GenerateConditionalString($enumeration); + push(@implContent, "\n#endif // ${conditionalString}\n") if $conditionalString; +} + +sub GenerateEnumerationImplementationContent +{ + my ($enumeration, $className, $interface, $conditionalString) = @_; + + my $result = ""; + $result .= "#if ${conditionalString}\n\n" if $conditionalString; + + # FIXME: Change to take VM& instead of ExecState*. + $result .= "template<> JSString* convertEnumerationToJS(ExecState& state, $className enumerationValue)\n"; + $result .= "{\n"; + # FIXME: Might be nice to make this global be "const", but NeverDestroyed does not currently support that. + # FIXME: Might be nice to make the entire array be NeverDestroyed instead of each value, but not sure what the syntax for that is. + AddToImplIncludes("<wtf/NeverDestroyed.h>"); + $result .= " static NeverDestroyed<const String> values[] = {\n"; + foreach my $value (@{$enumeration->values}) { + if ($value eq "") { + $result .= " emptyString(),\n"; + } else { + $result .= " ASCIILiteral(\"$value\"),\n"; + } + } + $result .= " };\n"; + my $index = 0; + foreach my $value (@{$enumeration->values}) { + my $enumerationValueName = GetEnumerationValueName($value); + $result .= " static_assert(static_cast<size_t>(${className}::$enumerationValueName) == $index, \"${className}::$enumerationValueName is not $index as expected\");\n"; + $index++; + } + $result .= " ASSERT(static_cast<size_t>(enumerationValue) < WTF_ARRAY_LENGTH(values));\n"; + $result .= " return jsStringWithCache(&state, values[static_cast<size_t>(enumerationValue)]);\n"; + $result .= "}\n\n"; + + # FIXME: Change to take VM& instead of ExecState&. + # FIXME: Consider using toStringOrNull to make exception checking faster. + # FIXME: Consider finding a more efficient way to match against all the strings quickly. + $result .= "template<> std::optional<$className> parseEnumeration<$className>(ExecState& state, JSValue value)\n"; + $result .= "{\n"; + $result .= " auto stringValue = value.toWTFString(&state);\n"; + foreach my $value (@{$enumeration->values}) { + my $enumerationValueName = GetEnumerationValueName($value); + if ($value eq "") { + $result .= " if (stringValue.isEmpty())\n"; + } else { + $result .= " if (stringValue == \"$value\")\n"; + } + $result .= " return ${className}::${enumerationValueName};\n"; + } + $result .= " return std::nullopt;\n"; + $result .= "}\n\n"; + + $result .= "template<> $className convertEnumeration<$className>(ExecState& state, JSValue value)\n"; + $result .= "{\n"; + $result .= " VM& vm = state.vm();\n"; + $result .= " auto throwScope = DECLARE_THROW_SCOPE(vm);\n"; + $result .= " auto result = parseEnumeration<$className>(state, value);\n"; + $result .= " if (UNLIKELY(!result)) {\n"; + $result .= " throwTypeError(&state, throwScope);\n"; + $result .= " return { };\n"; + $result .= " }\n"; + $result .= " return result.value();\n"; + $result .= "}\n\n"; + + $result .= "template<> const char* expectedEnumerationValues<$className>()\n"; + $result .= "{\n"; + $result .= " return \"\\\"" . join ("\\\", \\\"", @{$enumeration->values}) . "\\\"\";\n"; + $result .= "}\n\n"; + + $result .= "#endif\n\n" if $conditionalString; + + return $result; +} + +sub GenerateEnumerationsImplementationContent +{ + my ($interface, $enumerations) = @_; + + return "" unless @$enumerations; + + # FIXME: A little ugly to have this be a side effect instead of a return value. + AddToImplIncludes("<runtime/JSString.h>"); + AddToImplIncludes("JSDOMConvert.h"); + + my $result = ""; + foreach my $enumeration (@$enumerations) { + my $className = GetEnumerationClassName($enumeration->type, $interface); + my $conditionalString = $codeGenerator->GenerateConditionalString($enumeration); + $result .= GenerateEnumerationImplementationContent($enumeration, $className, $interface, $conditionalString); + } + return $result; +} + +sub GenerateEnumerationHeaderContent +{ + my ($enumeration, $className, $conditionalString) = @_; + + my $result = ""; + $result .= "#if ${conditionalString}\n\n" if $conditionalString; + + my $exportMacro = GetExportMacroForJSClass($enumeration); + + $result .= "template<> ${exportMacro}JSC::JSString* convertEnumerationToJS(JSC::ExecState&, $className);\n\n"; + $result .= "template<> ${exportMacro}std::optional<$className> parseEnumeration<$className>(JSC::ExecState&, JSC::JSValue);\n"; + $result .= "template<> ${exportMacro}$className convertEnumeration<$className>(JSC::ExecState&, JSC::JSValue);\n"; + $result .= "template<> ${exportMacro}const char* expectedEnumerationValues<$className>();\n\n"; + $result .= "#endif\n\n" if $conditionalString; + + return $result; +} + +sub GenerateEnumerationsHeaderContent +{ + my ($interface, $enumerations) = @_; + + return "" unless @$enumerations; + + # FIXME: Could optimize this to only generate the parts of each enumeration that are actually + # used, which would require iterating over everything in the interface. + + $headerIncludes{"JSDOMConvert.h"} = 1; + + my $result = ""; + foreach my $enumeration (@$enumerations) { + my $className = GetEnumerationClassName($enumeration->type, $interface); + my $conditionalString = $codeGenerator->GenerateConditionalString($enumeration); + $result .= GenerateEnumerationHeaderContent($enumeration, $className, $conditionalString); + } + return $result; +} + +sub GetDictionaryClassName +{ + my ($type, $interface) = @_; + + if ($codeGenerator->HasDictionaryImplementationNameOverride($type)) { + return $codeGenerator->GetDictionaryImplementationNameOverride($type); + } + + my $name = $type->name; + return $name if $codeGenerator->IsExternalDictionaryType($type); + return $name unless defined($interface); + return GetNestedClassName($interface, $name); +} + +sub GenerateDefaultValue +{ + my ($typeScope, $context, $type, $defaultValue) = @_; + + if ($codeGenerator->IsStringType($type)) { + my $useAtomicString = $context->extendedAttributes->{AtomicString}; + if ($defaultValue eq "null") { + return $useAtomicString ? "nullAtom" : "String()"; + } elsif ($defaultValue eq "\"\"") { + return $useAtomicString ? "emptyAtom" : "emptyString()"; + } else { + return $useAtomicString ? "AtomicString(${defaultValue}, AtomicString::ConstructFromLiteral)" : "ASCIILiteral(${defaultValue})"; + } + } + + if ($codeGenerator->IsEnumType($type)) { + # FIXME: Would be nice to report an error if the value does not have quote marks around it. + # FIXME: Would be nice to report an error if the value is not one of the enumeration values. + my $className = GetEnumerationClassName($type, $typeScope); + my $enumerationValueName = GetEnumerationValueName(substr($defaultValue, 1, -1)); + return $className . "::" . $enumerationValueName; + } + if ($defaultValue eq "null") { + if ($type->isUnion) { + return "std::nullopt" if $type->isNullable; + + my $IDLType = GetIDLType($typeScope, $type); + return "convert<${IDLType}>(state, jsNull());"; + } + + return "jsNull()" if $type->name eq "any"; + return "nullptr" if $codeGenerator->IsWrapperType($type) || $codeGenerator->IsTypedArrayType($type); + return "String()" if $codeGenerator->IsStringType($type); + return "std::nullopt"; + } + + if ($defaultValue eq "[]") { + my $IDLType = GetIDLType($typeScope, $type); + return "Converter<${IDLType}>::ReturnType{ }" if $codeGenerator->IsSequenceOrFrozenArrayType($type); + + my $nativeType = GetNativeType($typeScope, $type); + return "$nativeType()" + } + + return "jsUndefined()" if $defaultValue eq "undefined"; + return "PNaN" if $defaultValue eq "NaN"; + + return $defaultValue; +} + +sub GenerateDictionaryHeaderContent +{ + my ($dictionary, $className, $conditionalString) = @_; + + my $result = ""; + $result .= "#if ${conditionalString}\n\n" if $conditionalString; + $result .= "template<> ${className} convertDictionary<$className>(JSC::ExecState&, JSC::JSValue);\n\n"; + + if ($dictionary->extendedAttributes->{JSGenerateToJSObject}) { + $result .= "JSC::JSObject* convertDictionaryToJS(JSC::ExecState&, JSDOMGlobalObject&, const ${className}&);\n\n"; + } + + $result .= "#endif\n\n" if $conditionalString; + return $result; +} + +sub GenerateDictionariesHeaderContent +{ + my ($typeScope, $allDictionaries) = @_; + + return "" unless @$allDictionaries; + + $headerIncludes{"JSDOMConvert.h"} = 1; + + my $result = ""; + foreach my $dictionary (@$allDictionaries) { + $headerIncludes{$typeScope->type->name . ".h"} = 1 if $typeScope; + my $className = GetDictionaryClassName($dictionary->type, $typeScope); + my $conditionalString = $codeGenerator->GenerateConditionalString($dictionary); + $result .= GenerateDictionaryHeaderContent($dictionary, $className, $conditionalString); + } + return $result; +} + +sub GenerateDictionaryImplementationContent +{ + my ($dictionary, $className, $interface, $conditionalString) = @_; + + my $result = ""; + + my $name = $dictionary->type->name; + my $typeScope = $interface || $dictionary; + + $result .= "#if ${conditionalString}\n\n" if $conditionalString; + + # FIXME: A little ugly to have this be a side effect instead of a return value. + AddToImplIncludes("JSDOMConvert.h"); + + # https://heycam.github.io/webidl/#es-dictionary + $result .= "template<> $className convertDictionary<$className>(ExecState& state, JSValue value)\n"; + $result .= "{\n"; + $result .= " VM& vm = state.vm();\n"; + $result .= " auto throwScope = DECLARE_THROW_SCOPE(vm);\n"; + $result .= " bool isNullOrUndefined = value.isUndefinedOrNull();\n"; + $result .= " auto* object = isNullOrUndefined ? nullptr : value.getObject();\n"; + + # 1. If Type(V) is not Undefined, Null or Object, then throw a TypeError. + $result .= " if (UNLIKELY(!isNullOrUndefined && !object)) {\n"; + $result .= " throwTypeError(&state, throwScope);\n"; + $result .= " return { };\n"; + $result .= " }\n"; + + # 2. If V is a native RegExp object, then throw a TypeError. + # FIXME: This RegExp special handling is likely to go away in the specification. + $result .= " if (UNLIKELY(object && object->type() == RegExpObjectType)) {\n"; + $result .= " throwTypeError(&state, throwScope);\n"; + $result .= " return { };\n"; + $result .= " }\n"; + + # 3. Let dict be an empty dictionary value of type D; every dictionary member is initially considered to be not present. + + # 4. Let dictionaries be a list consisting of D and all of D’s inherited dictionaries, in order from least to most derived. + my @dictionaries; + push(@dictionaries, $dictionary); + my $parentType = $dictionary->parentType; + while (defined($parentType)) { + my $parentDictionary = $codeGenerator->GetDictionaryByType($parentType); + assert("Unable to find definition for dictionary named '" . $parentType->name . "'!") unless defined($parentDictionary); + unshift(@dictionaries, $parentDictionary); + $parentType = $parentDictionary->parentType; + } + + my $arguments = ""; + my $comma = ""; + + $result .= " $className result;\n"; + + # 5. For each dictionary dictionary in dictionaries, in order: + foreach my $dictionary (@dictionaries) { + # For each dictionary member member declared on dictionary, in lexicographical order: + my @sortedMembers = sort { $a->name cmp $b->name } @{$dictionary->members}; + foreach my $member (@sortedMembers) { + $member->default("undefined") if $member->type->name eq "any" and !defined($member->default); # Use undefined as default value for member of type 'any' unless specified otherwise. + + my $type = $member->type; + AddToImplIncludesForIDLType($type); + + # 5.1. Let key be the identifier of member. + my $key = $member->name; + + # 5.2. Let value be an ECMAScript value, depending on Type(V): + $result .= " JSValue ${key}Value = isNullOrUndefined ? jsUndefined() : object->get(&state, Identifier::fromString(&state, \"${key}\"));\n"; + + my $IDLType = GetIDLType($typeScope, $type); + + # 5.3. If value is not undefined, then: + $result .= " if (!${key}Value.isUndefined()) {\n"; + $result .= " result.$key = convert<${IDLType}>(state, ${key}Value);\n"; + $result .= " RETURN_IF_EXCEPTION(throwScope, { });\n"; + + # Value is undefined. + # 5.4. Otherwise, if value is undefined but the dictionary member has a default value, then: + if (!$member->isRequired && defined $member->default) { + $result .= " } else\n"; + $result .= " result.$key = " . GenerateDefaultValue($typeScope, $member, $member->type, $member->default) . ";\n"; + } elsif ($member->isRequired) { + # 5.5. Otherwise, if value is undefined and the dictionary member is a required dictionary member, then throw a TypeError. + $result .= " } else {\n"; + $result .= " throwRequiredMemberTypeError(state, throwScope, \"". $member->name ."\", \"$name\", \"". $type->name ."\");\n"; + $result .= " return { };\n"; + $result .= " }\n"; + } else { + $result .= " }\n"; + } + } + } + + $result .= " return result;\n"; + $result .= "}\n\n"; + + if ($dictionary->extendedAttributes->{JSGenerateToJSObject}) { + $result .= "JSC::JSObject* convertDictionaryToJS(JSC::ExecState& state, JSDOMGlobalObject& globalObject, const ${className}& dictionary)\n"; + $result .= "{\n"; + $result .= " auto& vm = state.vm();\n\n"; + + # 1. Let O be ! ObjectCreate(%ObjectPrototype%). + $result .= " auto result = constructEmptyObject(&state);\n\n"; + + # 2. Let dictionaries be a list consisting of D and all of D’s inherited dictionaries, + # in order from least to most derived. + # NOTE: This was done above. + + # 3. For each dictionary dictionary in dictionaries, in order: + foreach my $dictionary (@dictionaries) { + # 3.1. For each dictionary member member declared on dictionary, in lexicographical order: + my @sortedMembers = sort { $a->name cmp $b->name } @{$dictionary->members}; + foreach my $member (@sortedMembers) { + my $key = $member->name; + my $IDLType = GetIDLType($typeScope, $member->type); + + # 1. Let key be the identifier of member. + # 2. If the dictionary member named key is present in V, then: + # 1. Let idlValue be the value of member on V. + # 2. Let value be the result of converting idlValue to an ECMAScript value. + # 3. Perform ! CreateDataProperty(O, key, value). + if (!$member->isRequired && not defined $member->default) { + $result .= " if (!${IDLType}::isNullValue(dictionary.${key})) {\n"; + $result .= " auto ${key}Value = toJS<$IDLType>(state, globalObject, ${IDLType}::extractValueFromNullable(dictionary.${key}));\n"; + $result .= " result->putDirect(vm, JSC::Identifier::fromString(&vm, \"${key}\"), ${key}Value);\n"; + $result .= " }\n"; + } else { + $result .= " auto ${key}Value = toJS<$IDLType>(state, globalObject, dictionary.${key});\n"; + $result .= " result->putDirect(vm, JSC::Identifier::fromString(&vm, \"${key}\"), ${key}Value);\n"; + } + } + } + + $result .= " return result;\n"; + $result .= "}\n\n"; + } + + $result .= "#endif\n\n" if $conditionalString; + + return $result; +} + +sub GenerateDictionariesImplementationContent +{ + my ($typeScope, $allDictionaries) = @_; + + my $result = ""; + foreach my $dictionary (@$allDictionaries) { + my $className = GetDictionaryClassName($dictionary->type, $typeScope); + my $conditionalString = $codeGenerator->GenerateConditionalString($dictionary); + $result .= GenerateDictionaryImplementationContent($dictionary, $className, $typeScope, $conditionalString); + } + return $result; +} + +sub GetJSTypeForNode +{ + my ($interface) = @_; + + if ($codeGenerator->InheritsInterface($interface, "Document")) { + return "JSDocumentWrapperType"; + } + if ($codeGenerator->InheritsInterface($interface, "DocumentFragment")) { + return "JSDocumentFragmentNodeType"; + } + if ($codeGenerator->InheritsInterface($interface, "DocumentType")) { + return "JSDocumentTypeNodeType"; + } + if ($codeGenerator->InheritsInterface($interface, "ProcessingInstruction")) { + return "JSProcessingInstructionNodeType"; + } + if ($codeGenerator->InheritsInterface($interface, "CDATASection")) { + return "JSCDATASectionNodeType"; + } + if ($codeGenerator->InheritsInterface($interface, "Attr")) { + return "JSAttrNodeType"; + } + if ($codeGenerator->InheritsInterface($interface, "Comment")) { + return "JSCommentNodeType"; + } + if ($codeGenerator->InheritsInterface($interface, "Text")) { + return "JSTextNodeType"; + } + if ($codeGenerator->InheritsInterface($interface, "Element")) { + return "JSElementType"; + } + return "JSNodeType"; +} + +sub GenerateHeader +{ + my ($object, $interface, $enumerations, $dictionaries) = @_; + + my $interfaceName = $interface->type->name; my $className = "JS$interfaceName"; my %structureFlags = (); - my $hasLegacyParent = $interface->extendedAttributes->{"JSLegacyParent"}; - my $hasRealParent = $interface->parent; + my $hasLegacyParent = $interface->extendedAttributes->{JSLegacyParent}; + my $hasRealParent = $interface->parentType; my $hasParent = $hasLegacyParent || $hasRealParent; my $parentClassName = GetParentClassName($interface); - my $needsMarkChildren = $interface->extendedAttributes->{"JSCustomMarkFunction"} || $interface->extendedAttributes->{"EventTarget"} || $interface->name eq "EventTarget"; + my $needsVisitChildren = InstanceNeedsVisitChildren($interface); # - Add default header template and header protection push(@headerContentHeader, GenerateHeaderContentHeader($interface)); @@ -663,33 +1705,19 @@ sub GenerateHeader if ($hasParent) { $headerIncludes{"$parentClassName.h"} = 1; } else { - $headerIncludes{"JSDOMBinding.h"} = 1; - $headerIncludes{"<runtime/JSGlobalObject.h>"} = 1; + $headerIncludes{"JSDOMWrapper.h"} = 1; if ($interface->isException) { $headerIncludes{"<runtime/ErrorPrototype.h>"} = 1; - } else { - $headerIncludes{"<runtime/ObjectPrototype.h>"} = 1; } } - if ($interface->extendedAttributes->{"CustomCall"}) { - $headerIncludes{"<runtime/CallData.h>"} = 1; - } + $headerIncludes{"<runtime/CallData.h>"} = 1 if $interface->extendedAttributes->{CustomCall}; - if ($hasParent && $interface->extendedAttributes->{"JSGenerateToNativeObject"}) { - $headerIncludes{"$interfaceName.h"} = 1; - } - - $headerIncludes{"<runtime/JSObject.h>"} = 1; - $headerIncludes{"SVGElement.h"} = 1 if $className =~ /^JSSVG/; + $headerIncludes{"$interfaceName.h"} = 1 if $hasParent && $interface->extendedAttributes->{JSGenerateToNativeObject}; - my $implType = $interfaceName; - my ($svgPropertyType, $svgListPropertyType, $svgNativeType) = GetSVGPropertyTypes($implType); - $implType = $svgNativeType if $svgNativeType; + $headerIncludes{"SVGElement.h"} = 1 if $className =~ /^JSSVG/; - my $svgPropertyOrListPropertyType; - $svgPropertyOrListPropertyType = $svgPropertyType if $svgPropertyType; - $svgPropertyOrListPropertyType = $svgListPropertyType if $svgListPropertyType; + my $implType = GetImplClassName($interface); my $numConstants = @{$interface->constants}; my $numAttributes = @{$interface->attributes}; @@ -697,228 +1725,303 @@ sub GenerateHeader push(@headerContent, "\nnamespace WebCore {\n\n"); - if ($codeGenerator->IsSVGAnimatedType($interfaceName)) { + if ($codeGenerator->IsSVGAnimatedType($interface->type)) { $headerIncludes{"$interfaceName.h"} = 1; } else { # Implementation class forward declaration if (IsDOMGlobalObject($interface)) { - AddClassForwardIfNeeded($interfaceName) unless $svgPropertyOrListPropertyType; + AddClassForwardIfNeeded($interface->type); } } - AddClassForwardIfNeeded("JSDOMWindowShell") if $interfaceName eq "DOMWindow"; - AddClassForwardIfNeeded("JSDictionary") if $codeGenerator->IsConstructorTemplate($interface, "Event"); + push(@headerContent, "class JSDOMWindowShell;\n\n") if $interfaceName eq "DOMWindow"; + + my $exportMacro = GetExportMacroForJSClass($interface); # Class declaration - push(@headerContent, "class $className : public $parentClassName {\n"); + push(@headerContent, "class $exportMacro$className : public $parentClassName {\n"); # Static create methods push(@headerContent, "public:\n"); - push(@headerContent, " typedef $parentClassName Base;\n"); + push(@headerContent, " using Base = $parentClassName;\n"); + push(@headerContent, " using DOMWrapped = $implType;\n") if $hasRealParent; + if ($interfaceName eq "DOMWindow") { - push(@headerContent, " static $className* create(JSC::VM& vm, JSC::Structure* structure, PassRefPtr<$implType> impl, JSDOMWindowShell* windowShell)\n"); + push(@headerContent, " static $className* create(JSC::VM& vm, JSC::Structure* structure, Ref<$implType>&& impl, JSDOMWindowShell* windowShell)\n"); push(@headerContent, " {\n"); - push(@headerContent, " $className* ptr = new (NotNull, JSC::allocateCell<$className>(vm.heap)) ${className}(vm, structure, impl, windowShell);\n"); + push(@headerContent, " $className* ptr = new (NotNull, JSC::allocateCell<$className>(vm.heap)) ${className}(vm, structure, WTFMove(impl), windowShell);\n"); push(@headerContent, " ptr->finishCreation(vm, windowShell);\n"); - push(@headerContent, " vm.heap.addFinalizer(ptr, destroy);\n"); push(@headerContent, " return ptr;\n"); push(@headerContent, " }\n\n"); } elsif ($codeGenerator->InheritsInterface($interface, "WorkerGlobalScope")) { - push(@headerContent, " static $className* create(JSC::VM& vm, JSC::Structure* structure, PassRefPtr<$implType> impl)\n"); + push(@headerContent, " static $className* create(JSC::VM& vm, JSC::Structure* structure, Ref<$implType>&& impl, JSC::JSProxy* proxy)\n"); push(@headerContent, " {\n"); - push(@headerContent, " $className* ptr = new (NotNull, JSC::allocateCell<$className>(vm.heap)) ${className}(vm, structure, impl);\n"); - push(@headerContent, " ptr->finishCreation(vm);\n"); - push(@headerContent, " vm.heap.addFinalizer(ptr, destroy);\n"); + push(@headerContent, " $className* ptr = new (NotNull, JSC::allocateCell<$className>(vm.heap)) ${className}(vm, structure, WTFMove(impl));\n"); + push(@headerContent, " ptr->finishCreation(vm, proxy);\n"); push(@headerContent, " return ptr;\n"); push(@headerContent, " }\n\n"); - } elsif ($interface->extendedAttributes->{"MasqueradesAsUndefined"}) { - AddIncludesForTypeInHeader($implType) unless $svgPropertyOrListPropertyType; - push(@headerContent, " static $className* create(JSC::Structure* structure, JSDOMGlobalObject* globalObject, PassRefPtr<$implType> impl)\n"); + } elsif ($interface->extendedAttributes->{MasqueradesAsUndefined}) { + AddIncludesForImplementationTypeInHeader($implType); + push(@headerContent, " static $className* create(JSC::Structure* structure, JSDOMGlobalObject* globalObject, Ref<$implType>&& impl)\n"); push(@headerContent, " {\n"); - push(@headerContent, " globalObject->masqueradesAsUndefinedWatchpoint()->fireAll();\n"); - push(@headerContent, " $className* ptr = new (NotNull, JSC::allocateCell<$className>(globalObject->vm().heap)) $className(structure, globalObject, impl);\n"); + push(@headerContent, " globalObject->masqueradesAsUndefinedWatchpoint()->fireAll(globalObject->vm(), \"Allocated masquerading object\");\n"); + push(@headerContent, " $className* ptr = new (NotNull, JSC::allocateCell<$className>(globalObject->vm().heap)) $className(structure, *globalObject, WTFMove(impl));\n"); push(@headerContent, " ptr->finishCreation(globalObject->vm());\n"); push(@headerContent, " return ptr;\n"); push(@headerContent, " }\n\n"); + } elsif (!NeedsImplementationClass($interface)) { + push(@headerContent, " static $className* create(JSC::Structure* structure, JSDOMGlobalObject* globalObject)\n"); + push(@headerContent, " {\n"); + push(@headerContent, " $className* ptr = new (NotNull, JSC::allocateCell<$className>(globalObject->vm().heap)) $className(structure, *globalObject);\n"); + push(@headerContent, " ptr->finishCreation(globalObject->vm());\n"); + push(@headerContent, " return ptr;\n"); + push(@headerContent, " }\n\n"); } else { - AddIncludesForTypeInHeader($implType) unless $svgPropertyOrListPropertyType; - push(@headerContent, " static $className* create(JSC::Structure* structure, JSDOMGlobalObject* globalObject, PassRefPtr<$implType> impl)\n"); + AddIncludesForImplementationTypeInHeader($implType); + push(@headerContent, " static $className* create(JSC::Structure* structure, JSDOMGlobalObject* globalObject, Ref<$implType>&& impl)\n"); push(@headerContent, " {\n"); - push(@headerContent, " $className* ptr = new (NotNull, JSC::allocateCell<$className>(globalObject->vm().heap)) $className(structure, globalObject, impl);\n"); + push(@headerContent, " $className* ptr = new (NotNull, JSC::allocateCell<$className>(globalObject->vm().heap)) $className(structure, *globalObject, WTFMove(impl));\n"); push(@headerContent, " ptr->finishCreation(globalObject->vm());\n"); push(@headerContent, " return ptr;\n"); push(@headerContent, " }\n\n"); } - if (IsDOMGlobalObject($interface)) { - push(@headerContent, " static const bool needsDestruction = false;\n\n"); - } + push(@headerContent, " static const bool needsDestruction = false;\n\n") if IsDOMGlobalObject($interface); + + $structureFlags{"JSC::HasStaticPropertyTable"} = 1 if InstancePropertyCount($interface) > 0; # Prototype - push(@headerContent, " static JSC::JSObject* createPrototype(JSC::VM&, JSC::JSGlobalObject*);\n") unless IsDOMGlobalObject($interface); + unless (ShouldUseGlobalObjectPrototype($interface)) { + push(@headerContent, " static JSC::JSObject* createPrototype(JSC::VM&, JSC::JSGlobalObject*);\n"); + push(@headerContent, " static JSC::JSObject* prototype(JSC::VM&, JSC::JSGlobalObject*);\n"); + } + + # JSValue to implementation type + if (ShouldGenerateToWrapped($hasParent, $interface)) { + my $nativeType = GetNativeType($interface, $interface->type); - $headerTrailingIncludes{"${className}Custom.h"} = 1 if $interface->extendedAttributes->{"JSCustomHeader"}; + # FIXME: Add extended attribute for this. + my @toWrappedArguments = (); + push(@toWrappedArguments, "JSC::VM&"); + push(@toWrappedArguments, "JSC::ExecState&") if $interface->type->name eq "XPathNSResolver"; + push(@toWrappedArguments, "JSC::JSValue"); + + my $export = ""; + $export = "WEBCORE_EXPORT " if $interface->extendedAttributes->{ExportToWrappedFunction}; + push(@headerContent, " static $export$nativeType toWrapped(" . join(", ", @toWrappedArguments) . ");\n"); + } + + $headerTrailingIncludes{"${className}Custom.h"} = 1 if $interface->extendedAttributes->{JSCustomHeader}; my $namedGetterFunction = GetNamedGetterFunction($interface); my $indexedGetterFunction = GetIndexedGetterFunction($interface); - my $hasNumericIndexedGetter = $indexedGetterFunction ? $codeGenerator->IsNumericType($indexedGetterFunction->signature->type) : 0; - my $hasImpureNamedGetter = - $namedGetterFunction - || $interface->extendedAttributes->{"CustomNamedGetter"} - || $interface->extendedAttributes->{"CustomGetOwnPropertySlot"}; + my $hasNamedGetter = $namedGetterFunction + || $interface->extendedAttributes->{CustomNamedGetter}; + + my $hasComplexGetter = $indexedGetterFunction + || $interface->extendedAttributes->{JSCustomGetOwnPropertySlotAndDescriptor} + || $interface->extendedAttributes->{CustomGetOwnPropertySlot} + || $hasNamedGetter; - my $hasComplexGetter = - $indexedGetterFunction - || $interface->extendedAttributes->{"JSCustomGetOwnPropertySlotAndDescriptor"} - || $hasImpureNamedGetter; - my $hasGetter = InstanceOverridesGetOwnPropertySlot($interface); - if ($hasImpureNamedGetter) { - $structureFlags{"JSC::HasImpureGetOwnPropertySlot"} = 1; - } - if ($interface->extendedAttributes->{"NewImpurePropertyFiresWatchpoints"}) { - $structureFlags{"JSC::NewImpurePropertyFiresWatchpoints"} = 1; + if ($hasNamedGetter) { + if ($interface->extendedAttributes->{OverrideBuiltins}) { + $structureFlags{"JSC::GetOwnPropertySlotIsImpure"} = 1; + } else { + $structureFlags{"JSC::GetOwnPropertySlotIsImpureForPropertyAbsence"} = 1; + } } + $structureFlags{"JSC::NewImpurePropertyFiresWatchpoints"} = 1 if $interface->extendedAttributes->{NewImpurePropertyFiresWatchpoints}; + $structureFlags{"JSC::IsImmutablePrototypeExoticObject"} = 1 if $interface->extendedAttributes->{IsImmutablePrototypeExoticObject}; + $structureFlags{"JSC::TypeOfShouldCallGetCallData"} = 1 if $interface->extendedAttributes->{CustomCall}; # Getters if ($hasGetter) { push(@headerContent, " static bool getOwnPropertySlot(JSC::JSObject*, JSC::ExecState*, JSC::PropertyName, JSC::PropertySlot&);\n"); - push(@headerContent, " static bool getOwnPropertySlotByIndex(JSC::JSObject*, JSC::ExecState*, unsigned propertyName, JSC::PropertySlot&);\n") if ($hasComplexGetter); - push(@headerContent, " bool getOwnPropertySlotDelegate(JSC::ExecState*, JSC::PropertyName, JSC::PropertySlot&);\n") if $interface->extendedAttributes->{"JSCustomGetOwnPropertySlotAndDescriptor"}; $structureFlags{"JSC::OverridesGetOwnPropertySlot"} = 1; - $structureFlags{"JSC::InterceptsGetOwnPropertySlotByIndexEvenWhenLengthIsNotZero"} = 1; + + if ($hasComplexGetter) { + push(@headerContent, " static bool getOwnPropertySlotByIndex(JSC::JSObject*, JSC::ExecState*, unsigned propertyName, JSC::PropertySlot&);\n"); + $structureFlags{"JSC::InterceptsGetOwnPropertySlotByIndexEvenWhenLengthIsNotZero"} = 1; + } } my $overridesPut = InstanceOverridesPutDeclaration($interface); # Getters if ($overridesPut) { - push(@headerContent, " static void put(JSC::JSCell*, JSC::ExecState*, JSC::PropertyName, JSC::JSValue, JSC::PutPropertySlot&);\n"); - push(@headerContent, " static void putByIndex(JSC::JSCell*, JSC::ExecState*, unsigned propertyName, JSC::JSValue, bool shouldThrow);\n"); - push(@headerContent, " bool putDelegate(JSC::ExecState*, JSC::PropertyName, JSC::JSValue, JSC::PutPropertySlot&);\n") if $interface->extendedAttributes->{"CustomNamedSetter"}; + push(@headerContent, " static bool put(JSC::JSCell*, JSC::ExecState*, JSC::PropertyName, JSC::JSValue, JSC::PutPropertySlot&);\n"); + push(@headerContent, " static bool putByIndex(JSC::JSCell*, JSC::ExecState*, unsigned propertyName, JSC::JSValue, bool shouldThrow);\n"); } if (!$hasParent) { push(@headerContent, " static void destroy(JSC::JSCell*);\n"); - push(@headerContent, " ~${className}();\n"); } # Class info if ($interfaceName eq "Node") { - push(@headerContent, "protected:"); - push(@headerContent, " static WEBKIT_EXPORTDATA const JSC::ClassInfo s_info;\n"); - push(@headerContent, "public:"); - push(@headerContent, " static const JSC::ClassInfo* info() { return &s_info; }\n\n"); + push(@headerContent, "\n"); + push(@headerContent, "protected:\n"); + push(@headerContent, " static const JSC::ClassInfo s_info;\n"); + push(@headerContent, "public:\n"); + push(@headerContent, " static constexpr const JSC::ClassInfo* info() { return &s_info; }\n\n"); } else { + push(@headerContent, "\n"); push(@headerContent, " DECLARE_INFO;\n\n"); } + # Structure ID - if ($interfaceName eq "DOMWindow") { - $structureFlags{"JSC::ImplementsHasInstance"} = 1; - } + $structureFlags{"JSC::ImplementsHasInstance | JSC::ImplementsDefaultHasInstance"} = 1 if $interfaceName eq "DOMWindow"; push(@headerContent, " static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype)\n"); push(@headerContent, " {\n"); if (IsDOMGlobalObject($interface)) { push(@headerContent, " return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(JSC::GlobalObjectType, StructureFlags), info());\n"); + } elsif ($codeGenerator->InheritsInterface($interface, "Node")) { + my $type = GetJSTypeForNode($interface); + push(@headerContent, " return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(JSC::JSType($type), StructureFlags), info());\n"); + } elsif ($codeGenerator->InheritsInterface($interface, "Event")) { + push(@headerContent, " return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(JSC::JSType(JSEventType), StructureFlags), info());\n"); } else { push(@headerContent, " return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), info());\n"); } push(@headerContent, " }\n\n"); # Custom pushEventHandlerScope function - push(@headerContent, " JSC::JSScope* pushEventHandlerScope(JSC::ExecState*, JSC::JSScope*) const;\n\n") if $interface->extendedAttributes->{"JSCustomPushEventHandlerScope"}; + push(@headerContent, " JSC::JSScope* pushEventHandlerScope(JSC::ExecState*, JSC::JSScope*) const;\n\n") if $interface->extendedAttributes->{JSCustomPushEventHandlerScope}; # Custom call functions - push(@headerContent, " static JSC::CallType getCallData(JSC::JSCell*, JSC::CallData&);\n\n") if $interface->extendedAttributes->{"CustomCall"}; + push(@headerContent, " static JSC::CallType getCallData(JSC::JSCell*, JSC::CallData&);\n\n") if $interface->extendedAttributes->{CustomCall}; # Custom deleteProperty function - push(@headerContent, " static bool deleteProperty(JSC::JSCell*, JSC::ExecState*, JSC::PropertyName);\n") if $interface->extendedAttributes->{"CustomDeleteProperty"}; - push(@headerContent, " static bool deletePropertyByIndex(JSC::JSCell*, JSC::ExecState*, unsigned);\n") if $interface->extendedAttributes->{"CustomDeleteProperty"}; + push(@headerContent, " static bool deleteProperty(JSC::JSCell*, JSC::ExecState*, JSC::PropertyName);\n") if $interface->extendedAttributes->{CustomDeleteProperty}; + push(@headerContent, " static bool deletePropertyByIndex(JSC::JSCell*, JSC::ExecState*, unsigned);\n") if $interface->extendedAttributes->{CustomDeleteProperty}; # Custom getPropertyNames function exists on DOMWindow if ($interfaceName eq "DOMWindow") { - push(@headerContent, " static void getPropertyNames(JSC::JSObject*, JSC::ExecState*, JSC::PropertyNameArray&, JSC::EnumerationMode mode = JSC::ExcludeDontEnumProperties);\n"); + push(@headerContent, " static void getPropertyNames(JSC::JSObject*, JSC::ExecState*, JSC::PropertyNameArray&, JSC::EnumerationMode = JSC::EnumerationMode());\n"); + push(@headerContent, " static void getGenericPropertyNames(JSC::JSObject*, JSC::ExecState*, JSC::PropertyNameArray&, JSC::EnumerationMode = JSC::EnumerationMode());\n"); + push(@headerContent, " static void getStructurePropertyNames(JSC::JSObject*, JSC::ExecState*, JSC::PropertyNameArray&, JSC::EnumerationMode = JSC::EnumerationMode());\n"); + push(@headerContent, " static uint32_t getEnumerableLength(JSC::ExecState*, JSC::JSObject*);\n"); $structureFlags{"JSC::OverridesGetPropertyNames"} = 1; } # Custom getOwnPropertyNames function - if ($interface->extendedAttributes->{"CustomEnumerateProperty"} || $indexedGetterFunction) { - push(@headerContent, " static void getOwnPropertyNames(JSC::JSObject*, JSC::ExecState*, JSC::PropertyNameArray&, JSC::EnumerationMode mode = JSC::ExcludeDontEnumProperties);\n"); + if ($interface->extendedAttributes->{CustomEnumerateProperty} || $indexedGetterFunction || $namedGetterFunction) { + push(@headerContent, " static void getOwnPropertyNames(JSC::JSObject*, JSC::ExecState*, JSC::PropertyNameArray&, JSC::EnumerationMode = JSC::EnumerationMode());\n"); $structureFlags{"JSC::OverridesGetPropertyNames"} = 1; } # Custom defineOwnProperty function - push(@headerContent, " static bool defineOwnProperty(JSC::JSObject*, JSC::ExecState*, JSC::PropertyName, const JSC::PropertyDescriptor&, bool shouldThrow);\n") if $interface->extendedAttributes->{"JSCustomDefineOwnProperty"}; + push(@headerContent, " static bool defineOwnProperty(JSC::JSObject*, JSC::ExecState*, JSC::PropertyName, const JSC::PropertyDescriptor&, bool shouldThrow);\n") if $interface->extendedAttributes->{JSCustomDefineOwnProperty}; - # Override toBoolean to return false for objects that want to 'MasqueradesAsUndefined'. - if ($interface->extendedAttributes->{"MasqueradesAsUndefined"}) { - $structureFlags{"JSC::MasqueradesAsUndefined"} = 1; - } + # Custom getPrototype / setPrototype functions. + push (@headerContent, " static JSC::JSValue getPrototype(JSC::JSObject*, JSC::ExecState*);\n") if $interface->extendedAttributes->{CustomGetPrototype}; + push (@headerContent, " static bool setPrototype(JSC::JSObject*, JSC::ExecState*, JSC::JSValue, bool shouldThrowIfCantSet);\n") if $interface->extendedAttributes->{CustomSetPrototype}; + + # Custom toStringName function. + push (@headerContent, " static String toStringName(const JSC::JSObject*, JSC::ExecState*);\n") if $interface->extendedAttributes->{CustomToStringName}; + + # Custom preventExtensions function. + push(@headerContent, " static bool preventExtensions(JSC::JSObject*, JSC::ExecState*);\n") if $interface->extendedAttributes->{CustomPreventExtensions}; + + $structureFlags{"JSC::MasqueradesAsUndefined"} = 1 if $interface->extendedAttributes->{MasqueradesAsUndefined}; # Constructor object getter - unless ($interface->extendedAttributes->{"NoInterfaceObject"}) { - push(@headerContent, " static JSC::JSValue getConstructor(JSC::VM&, JSC::JSGlobalObject*);\n"); - push(@headerContent, " static JSC::JSValue getNamedConstructor(JSC::VM&, JSC::JSGlobalObject*);\n") if $interface->extendedAttributes->{"NamedConstructor"}; + unless ($interface->extendedAttributes->{NoInterfaceObject}) { + push(@headerContent, " static JSC::JSValue getConstructor(JSC::VM&, const JSC::JSGlobalObject*);\n"); + push(@headerContent, " static JSC::JSValue getNamedConstructor(JSC::VM&, JSC::JSGlobalObject*);\n") if $interface->extendedAttributes->{NamedConstructor}; } + # Serializer function. + push(@headerContent, " static JSC::JSObject* serialize(JSC::ExecState*, JS${interfaceName}* thisObject, JSC::ThrowScope&);\n") if $interface->serializable; + my $numCustomFunctions = 0; my $numCustomAttributes = 0; + my $hasForwardDeclaringFunctions = 0; + my $hasForwardDeclaringAttributes = 0; + + my $hasDOMJITAttributes = 0; + # Attribute and function enums if ($numAttributes > 0) { foreach (@{$interface->attributes}) { my $attribute = $_; - $numCustomAttributes++ if HasCustomGetter($attribute->signature->extendedAttributes); - $numCustomAttributes++ if HasCustomSetter($attribute->signature->extendedAttributes); - if ($attribute->signature->extendedAttributes->{"CachedAttribute"}) { - my $conditionalString = $codeGenerator->GenerateConditionalString($attribute->signature); + $numCustomAttributes++ if HasCustomGetter($attribute->extendedAttributes); + $numCustomAttributes++ if HasCustomSetter($attribute->extendedAttributes); + if ($attribute->extendedAttributes->{CachedAttribute}) { + my $conditionalString = $codeGenerator->GenerateConditionalString($attribute); push(@headerContent, "#if ${conditionalString}\n") if $conditionalString; - push(@headerContent, " JSC::WriteBarrier<JSC::Unknown> m_" . $attribute->signature->name . ";\n"); + push(@headerContent, " mutable JSC::WriteBarrier<JSC::Unknown> m_" . $attribute->name . ";\n"); $numCachedAttributes++; - $needsMarkChildren = 1; + $needsVisitChildren = 1; push(@headerContent, "#endif\n") if $conditionalString; } + $hasDOMJITAttributes = 1 if $attribute->extendedAttributes->{"DOMJIT"}; + + $hasForwardDeclaringAttributes = 1 if $attribute->extendedAttributes->{ForwardDeclareInHeader}; } } # visit function - if ($needsMarkChildren) { - push(@headerContent, " static void visitChildren(JSCell*, JSC::SlotVisitor&);\n\n"); - $structureFlags{"JSC::OverridesVisitChildren"} = 1; + if ($needsVisitChildren) { + push(@headerContent, " static void visitChildren(JSCell*, JSC::SlotVisitor&);\n"); + push(@headerContent, " void visitAdditionalChildren(JSC::SlotVisitor&);\n") if $interface->extendedAttributes->{JSCustomMarkFunction}; + push(@headerContent, "\n"); + + if ($interface->extendedAttributes->{JSCustomMarkFunction}) { + # We assume that the logic in visitAdditionalChildren is highly volatile, and during a + # concurrent GC or in between eden GCs something may happen that would lead to this + # logic behaving differently. Since this could mark objects or add opaque roots, this + # means that after any increment of mutator resumption in a concurrent GC and at least + # once during any eden GC we need to re-execute visitAdditionalChildren on any objects + # that we had executed it on before. We do this using the DOM's own MarkingConstraint, + # which will call visitOutputConstraints on all objects in the DOM's own + # outputConstraintSubspace. visitOutputConstraints is the name JSC uses for the method + # that the GC calls to ask an object is it would like to mark anything else after the + # program resumed since the last call to visitChildren or visitOutputConstraints. Since + # this just calls visitAdditionalChildren, you usually don't have to worry about this. + push(@headerContent, " static void visitOutputConstraints(JSCell*, JSC::SlotVisitor&);\n"); + my $subspaceFunc = IsDOMGlobalObject($interface) ? "globalObjectOutputConstraintSubspaceFor" : "outputConstraintSubspaceFor"; + push(@headerContent, " template<typename> static JSC::Subspace* subspaceFor(JSC::VM& vm) { return $subspaceFunc(vm); }\n"); + } + } + + if (InstanceNeedsEstimatedSize($interface)) { + push(@headerContent, " static size_t estimatedSize(JSCell*);\n"); } if ($numCustomAttributes > 0) { push(@headerContent, "\n // Custom attributes\n"); foreach my $attribute (@{$interface->attributes}) { - my $conditionalString = $codeGenerator->GenerateConditionalString($attribute->signature); - if (HasCustomGetter($attribute->signature->extendedAttributes)) { + my $conditionalString = $codeGenerator->GenerateConditionalString($attribute); + if (HasCustomGetter($attribute->extendedAttributes)) { push(@headerContent, "#if ${conditionalString}\n") if $conditionalString; - my $methodName = $codeGenerator->WK_lcfirst($attribute->signature->name); - push(@headerContent, " JSC::JSValue " . $methodName . "(JSC::ExecState*) const;\n"); + my $methodName = $codeGenerator->WK_lcfirst($attribute->name); + push(@headerContent, " JSC::JSValue " . $methodName . "(JSC::ExecState&) const;\n"); push(@headerContent, "#endif\n") if $conditionalString; } - if (HasCustomSetter($attribute->signature->extendedAttributes) && !IsReadonly($attribute)) { + if (HasCustomSetter($attribute->extendedAttributes) && !IsReadonly($attribute)) { push(@headerContent, "#if ${conditionalString}\n") if $conditionalString; - push(@headerContent, " void set" . $codeGenerator->WK_ucfirst($attribute->signature->name) . "(JSC::ExecState*, JSC::JSValue);\n"); + push(@headerContent, " void set" . $codeGenerator->WK_ucfirst($attribute->name) . "(JSC::ExecState&, JSC::JSValue);\n"); push(@headerContent, "#endif\n") if $conditionalString; } } } foreach my $function (@{$interface->functions}) { - $numCustomFunctions++ if HasCustomMethod($function->signature->extendedAttributes); + $numCustomFunctions++ if HasCustomMethod($function->extendedAttributes); + $hasForwardDeclaringFunctions = 1 if $function->extendedAttributes->{ForwardDeclareInHeader}; } if ($numCustomFunctions > 0) { my $inAppleCopyright = 0; push(@headerContent, "\n // Custom functions\n"); foreach my $function (@{$interface->functions}) { - # PLATFORM_IOS - my $needsAppleCopyright = $function->signature->extendedAttributes->{"AppleCopyright"}; - if ($needsAppleCopyright) { + if ($function->extendedAttributes->{AppleCopyright}) { if (!$inAppleCopyright) { push(@headerContent, $beginAppleCopyrightForHeaderFiles); $inAppleCopyright = 1; @@ -927,88 +2030,83 @@ sub GenerateHeader push(@headerContent, $endAppleCopyright); $inAppleCopyright = 0; } - # end PLATFORM_IOS - next unless HasCustomMethod($function->signature->extendedAttributes); + next unless HasCustomMethod($function->extendedAttributes); next if $function->{overloads} && $function->{overloadIndex} != 1; - my $conditionalString = $codeGenerator->GenerateConditionalString($function->signature); + my $conditionalString = $codeGenerator->GenerateConditionalString($function); push(@headerContent, "#if ${conditionalString}\n") if $conditionalString; - my $functionImplementationName = $function->signature->extendedAttributes->{"ImplementedAs"} || $codeGenerator->WK_lcfirst($function->signature->name); - push(@headerContent, " " . ($function->isStatic ? "static " : "") . "JSC::JSValue " . $functionImplementationName . "(JSC::ExecState*);\n"); + my $functionImplementationName = $function->extendedAttributes->{ImplementedAs} || $codeGenerator->WK_lcfirst($function->name); + push(@headerContent, " " . ($function->isStatic ? "static " : "") . "JSC::JSValue " . $functionImplementationName . "(JSC::ExecState&);\n"); push(@headerContent, "#endif\n") if $conditionalString; } push(@headerContent, $endAppleCopyright) if $inAppleCopyright; } - if (!$hasParent) { - push(@headerContent, " $implType& impl() const { return *m_impl; }\n"); - push(@headerContent, " void releaseImpl() { m_impl->deref(); m_impl = 0; }\n\n"); - push(@headerContent, " void releaseImplIfNotNull()\n"); - push(@headerContent, " {\n"); - push(@headerContent, " if (m_impl) {\n"); - push(@headerContent, " m_impl->deref();\n"); - push(@headerContent, " m_impl = 0;\n"); - push(@headerContent, " }\n"); - push(@headerContent, " }\n\n"); - push(@headerContent, "private:\n"); - push(@headerContent, " $implType* m_impl;\n"); - } else { - push(@headerContent, " $interfaceName& impl() const\n"); - push(@headerContent, " {\n"); - push(@headerContent, " return static_cast<$interfaceName&>(Base::impl());\n"); - push(@headerContent, " }\n"); + if (NeedsImplementationClass($interface)) { + if ($hasParent) { + push(@headerContent, " $interfaceName& wrapped() const\n"); + push(@headerContent, " {\n"); + push(@headerContent, " return static_cast<$interfaceName&>(Base::wrapped());\n"); + push(@headerContent, " }\n"); + } + } + + # structure flags + if (%structureFlags) { + push(@headerContent, "public:\n"); + push(@headerContent, " static const unsigned StructureFlags = "); + foreach my $structureFlag (sort (keys %structureFlags)) { + push(@headerContent, $structureFlag . " | "); + } + push(@headerContent, "Base::StructureFlags;\n"); } push(@headerContent, "protected:\n"); + # Constructor if ($interfaceName eq "DOMWindow") { - push(@headerContent, " $className(JSC::VM&, JSC::Structure*, PassRefPtr<$implType>, JSDOMWindowShell*);\n"); + push(@headerContent, " $className(JSC::VM&, JSC::Structure*, Ref<$implType>&&, JSDOMWindowShell*);\n"); + } elsif ($codeGenerator->InheritsInterface($interface, "WorkerGlobalScope")) { + push(@headerContent, " $className(JSC::VM&, JSC::Structure*, Ref<$implType>&&);\n"); + } elsif (!NeedsImplementationClass($interface)) { + push(@headerContent, " $className(JSC::Structure*, JSDOMGlobalObject&);\n\n"); + } else { + push(@headerContent, " $className(JSC::Structure*, JSDOMGlobalObject&, Ref<$implType>&&);\n\n"); + } + + if ($interfaceName eq "DOMWindow") { + push(@headerContent, " void finishCreation(JSC::VM&, JSDOMWindowShell*);\n"); } elsif ($codeGenerator->InheritsInterface($interface, "WorkerGlobalScope")) { - push(@headerContent, " $className(JSC::VM&, JSC::Structure*, PassRefPtr<$implType>);\n"); + push(@headerContent, " void finishCreation(JSC::VM&, JSC::JSProxy*);\n"); } else { - push(@headerContent, " $className(JSC::Structure*, JSDOMGlobalObject*, PassRefPtr<$implType>);\n"); push(@headerContent, " void finishCreation(JSC::VM&);\n"); } - # structure flags - push(@headerContent, " static const unsigned StructureFlags = "); - foreach my $structureFlag (sort (keys %structureFlags)) { - push(@headerContent, $structureFlag . " | "); + if ($interface->extendedAttributes->{JSCustomGetOwnPropertySlotAndDescriptor}) { + push(@headerContent, " bool getOwnPropertySlotDelegate(JSC::ExecState*, JSC::PropertyName, JSC::PropertySlot&);\n"); } - push(@headerContent, "Base::StructureFlags;\n"); - # Index getter - if ($indexedGetterFunction) { - if ($hasNumericIndexedGetter) { - push(@headerContent, " JSC::JSValue getByIndex(JSC::ExecState*, unsigned index);\n"); - } else { - push(@headerContent, " static JSC::EncodedJSValue indexGetter(JSC::ExecState*, JSC::EncodedJSValue, JSC::EncodedJSValue, unsigned);\n"); - } + if ($interface->extendedAttributes->{CustomNamedGetter}) { + push(@headerContent, " bool nameGetter(JSC::ExecState*, JSC::PropertyName, JSC::JSValue&);\n"); } - # Index setter - if ($interface->extendedAttributes->{"CustomIndexedSetter"}) { - push(@headerContent, " void indexSetter(JSC::ExecState*, unsigned index, JSC::JSValue);\n"); + if ($interface->extendedAttributes->{CustomNamedSetter}) { + push(@headerContent, " bool putDelegate(JSC::ExecState*, JSC::PropertyName, JSC::JSValue, JSC::PutPropertySlot&, bool& putResult);\n"); } - # Name getter - if ($namedGetterFunction || $interface->extendedAttributes->{"CustomNamedGetter"}) { - push(@headerContent, "private:\n"); - push(@headerContent, " static bool canGetItemsForName(JSC::ExecState*, $interfaceName*, JSC::PropertyName);\n"); - push(@headerContent, " static JSC::EncodedJSValue nameGetter(JSC::ExecState*, JSC::EncodedJSValue, JSC::EncodedJSValue, JSC::PropertyName);\n"); + + if ($interface->extendedAttributes->{CustomIndexedSetter}) { + push(@headerContent, " void indexSetter(JSC::ExecState*, unsigned index, JSC::JSValue);\n"); } push(@headerContent, "};\n\n"); - if (!$hasParent || - GetGenerateIsReachable($interface) || - GetCustomIsReachable($interface) || - $interface->extendedAttributes->{"JSCustomFinalize"} || - $codeGenerator->InheritsExtendedAttribute($interface, "ActiveDOMObject")) { + if (ShouldGenerateWrapperOwnerCode($hasParent, $interface)) { if ($interfaceName ne "Node" && $codeGenerator->InheritsInterface($interface, "Node")) { $headerIncludes{"JSNode.h"} = 1; push(@headerContent, "class JS${interfaceName}Owner : public JSNodeOwner {\n"); } else { push(@headerContent, "class JS${interfaceName}Owner : public JSC::WeakHandleOwner {\n"); } + $headerIncludes{"<wtf/NeverDestroyed.h>"} = 1; push(@headerContent, "public:\n"); push(@headerContent, " virtual bool isReachableFromOpaqueRoots(JSC::Handle<JSC::Unknown>, void* context, JSC::SlotVisitor&);\n"); push(@headerContent, " virtual void finalize(JSC::Handle<JSC::Unknown>, void* context);\n"); @@ -1016,99 +2114,42 @@ sub GenerateHeader push(@headerContent, "\n"); push(@headerContent, "inline JSC::WeakHandleOwner* wrapperOwner(DOMWrapperWorld&, $implType*)\n"); push(@headerContent, "{\n"); - push(@headerContent, " DEFINE_STATIC_LOCAL(JS${interfaceName}Owner, js${interfaceName}Owner, ());\n"); - push(@headerContent, " return &js${interfaceName}Owner;\n"); + push(@headerContent, " static NeverDestroyed<JS${interfaceName}Owner> owner;\n"); + push(@headerContent, " return &owner.get();\n"); push(@headerContent, "}\n"); push(@headerContent, "\n"); - push(@headerContent, "inline void* wrapperContext(DOMWrapperWorld& world, $implType*)\n"); + push(@headerContent, "inline void* wrapperKey($implType* wrappableObject)\n"); push(@headerContent, "{\n"); - push(@headerContent, " return &world;\n"); + push(@headerContent, " return wrappableObject;\n"); push(@headerContent, "}\n"); push(@headerContent, "\n"); } if (ShouldGenerateToJSDeclaration($hasParent, $interface)) { - push(@headerContent, "JSC::JSValue toJS(JSC::ExecState*, JSDOMGlobalObject*, $implType*);\n"); - } - if (!$hasParent || $interface->extendedAttributes->{"JSGenerateToNativeObject"}) { - if ($interfaceName eq "NodeFilter") { - push(@headerContent, "PassRefPtr<NodeFilter> toNodeFilter(JSC::VM&, JSC::JSValue);\n"); - } elsif ($interfaceName eq "DOMStringList") { - push(@headerContent, "PassRefPtr<DOMStringList> toDOMStringList(JSC::ExecState*, JSC::JSValue);\n"); + # Node and NodeList have custom inline implementations which thus cannot be exported. + # FIXME: The special case for Node and NodeList should probably be implemented via an IDL attribute. + if ($implType eq "Node" or $implType eq "NodeList") { + push(@headerContent, "JSC::JSValue toJS(JSC::ExecState*, JSDOMGlobalObject*, $implType&);\n"); } else { - push(@headerContent, "$implType* to${interfaceName}(JSC::JSValue);\n"); + push(@headerContent, $exportMacro."JSC::JSValue toJS(JSC::ExecState*, JSDOMGlobalObject*, $implType&);\n"); } - } - if ($usesToJSNewlyCreated{$interfaceName}) { - push(@headerContent, "JSC::JSValue toJSNewlyCreated(JSC::ExecState*, JSDOMGlobalObject*, $interfaceName*);\n"); - } - - push(@headerContent, "\n"); - - # Add prototype declaration. - %structureFlags = (); - push(@headerContent, "class ${className}Prototype : public JSC::JSNonFinalObject {\n"); - push(@headerContent, "public:\n"); - push(@headerContent, " typedef JSC::JSNonFinalObject Base;\n"); - unless (IsDOMGlobalObject($interface)) { - push(@headerContent, " static JSC::JSObject* self(JSC::VM&, JSC::JSGlobalObject*);\n"); - } - - push(@headerContent, " static ${className}Prototype* create(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::Structure* structure)\n"); - push(@headerContent, " {\n"); - push(@headerContent, " ${className}Prototype* ptr = new (NotNull, JSC::allocateCell<${className}Prototype>(vm.heap)) ${className}Prototype(vm, globalObject, structure);\n"); - push(@headerContent, " ptr->finishCreation(vm);\n"); - push(@headerContent, " return ptr;\n"); - push(@headerContent, " }\n\n"); - - push(@headerContent, " DECLARE_INFO;\n"); - if (PrototypeOverridesGetOwnPropertySlot($interface)) { - push(@headerContent, " static bool getOwnPropertySlot(JSC::JSObject*, JSC::ExecState*, JSC::PropertyName, JSC::PropertySlot&);\n"); - $structureFlags{"JSC::OverridesGetOwnPropertySlot"} = 1; - } - if ($interface->extendedAttributes->{"JSCustomMarkFunction"} or $needsMarkChildren) { - $structureFlags{"JSC::OverridesVisitChildren"} = 1; - } - push(@headerContent, - " static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype)\n" . - " {\n" . - " return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), info());\n" . - " }\n"); - if ($interface->extendedAttributes->{"JSCustomNamedGetterOnPrototype"}) { - push(@headerContent, " static void put(JSC::JSCell*, JSC::ExecState*, JSC::PropertyName, JSC::JSValue, JSC::PutPropertySlot&);\n"); - push(@headerContent, " bool putDelegate(JSC::ExecState*, JSC::PropertyName, JSC::JSValue, JSC::PutPropertySlot&);\n"); - } + push(@headerContent, "inline JSC::JSValue toJS(JSC::ExecState* state, JSDOMGlobalObject* globalObject, $implType* impl) { return impl ? toJS(state, globalObject, *impl) : JSC::jsNull(); }\n"); - # Custom defineOwnProperty function - push(@headerContent, " static bool defineOwnProperty(JSC::JSObject*, JSC::ExecState*, JSC::PropertyName, const JSC::PropertyDescriptor&, bool shouldThrow);\n") if $interface->extendedAttributes->{"JSCustomDefineOwnPropertyOnPrototype"}; - - push(@headerContent, "\nprivate:\n"); - push(@headerContent, " ${className}Prototype(JSC::VM& vm, JSC::JSGlobalObject*, JSC::Structure* structure) : JSC::JSNonFinalObject(vm, structure) { }\n"); - - # structure flags - push(@headerContent, "protected:\n"); - push(@headerContent, " static const unsigned StructureFlags = "); - foreach my $structureFlag (sort (keys %structureFlags)) { - push(@headerContent, $structureFlag . " | "); - } - push(@headerContent, "Base::StructureFlags;\n"); + push(@headerContent, "JSC::JSValue toJSNewlyCreated(JSC::ExecState*, JSDOMGlobalObject*, Ref<$implType>&&);\n"); + push(@headerContent, "inline JSC::JSValue toJSNewlyCreated(JSC::ExecState* state, JSDOMGlobalObject* globalObject, RefPtr<$implType>&& impl) { return impl ? toJSNewlyCreated(state, globalObject, impl.releaseNonNull()) : JSC::jsNull(); }\n"); + } - push(@headerContent, "};\n\n"); + push(@headerContent, "\n"); - if (!$interface->extendedAttributes->{"NoInterfaceObject"}) { - $headerIncludes{"JSDOMBinding.h"} = 1; - if ($interface->extendedAttributes->{"NamedConstructor"}) { - $headerIncludes{"DOMConstructorWithDocument.h"} = 1; - } - GenerateConstructorDeclaration(\@headerContent, $className, $interface, $interfaceName); - } + GeneratePrototypeDeclaration(\@headerContent, $className, $interface) if HeaderNeedsPrototypeDeclaration($interface); - if ($numFunctions > 0) { + if ($hasForwardDeclaringFunctions) { my $inAppleCopyright = 0; push(@headerContent,"// Functions\n\n"); foreach my $function (@{$interface->functions}) { next if $function->{overloadIndex} && $function->{overloadIndex} > 1; - my $needsAppleCopyright = $function->signature->extendedAttributes->{"AppleCopyright"}; - if ($needsAppleCopyright) { + next unless $function->extendedAttributes->{ForwardDeclareInHeader}; + + if ($function->extendedAttributes->{AppleCopyright}) { if (!$inAppleCopyright) { push(@headerContent, $beginAppleCopyrightForHeaderFiles); $inAppleCopyright = 1; @@ -1118,296 +2159,619 @@ sub GenerateHeader $inAppleCopyright = 0; } - my $conditionalString = $codeGenerator->GenerateConditionalString($function->signature); + my $conditionalAttribute = getConditionalForFunctionConsideringOverloads($function); + my $conditionalString = $conditionalAttribute ? $codeGenerator->GenerateConditionalStringFromAttributeValue($conditionalAttribute) : undef; push(@headerContent, "#if ${conditionalString}\n") if $conditionalString; - my $functionName = GetFunctionName($className, $function); + my $functionName = GetFunctionName($interface, $className, $function); push(@headerContent, "JSC::EncodedJSValue JSC_HOST_CALL ${functionName}(JSC::ExecState*);\n"); push(@headerContent, "#endif\n") if $conditionalString; } push(@headerContent, $endAppleCopyright) if $inAppleCopyright; + push(@headerContent,"\n"); } - if ($numAttributes > 0 || !$interface->extendedAttributes->{"NoInterfaceObject"}) { + if ($hasForwardDeclaringAttributes) { push(@headerContent,"// Attributes\n\n"); foreach my $attribute (@{$interface->attributes}) { - my $conditionalString = $codeGenerator->GenerateConditionalString($attribute->signature); + next unless $attribute->extendedAttributes->{ForwardDeclareInHeader}; + + my $conditionalString = $codeGenerator->GenerateConditionalString($attribute); push(@headerContent, "#if ${conditionalString}\n") if $conditionalString; - my $getter = GetAttributeGetterName($interfaceName, $className, $attribute); - push(@headerContent, "JSC::EncodedJSValue ${getter}(JSC::ExecState*, JSC::EncodedJSValue, JSC::EncodedJSValue, JSC::PropertyName);\n"); + my $getter = GetAttributeGetterName($interface, $className, $attribute); + push(@headerContent, "JSC::EncodedJSValue ${getter}(JSC::ExecState*, JSC::EncodedJSValue, JSC::PropertyName);\n"); if (!IsReadonly($attribute)) { - my $setter = GetAttributeSetterName($interfaceName, $className, $attribute); - push(@headerContent, "void ${setter}(JSC::ExecState*, JSC::JSObject*, JSC::EncodedJSValue, JSC::EncodedJSValue);\n"); + my $setter = GetAttributeSetterName($interface, $className, $attribute); + push(@headerContent, "bool ${setter}(JSC::ExecState*, JSC::EncodedJSValue, JSC::EncodedJSValue);\n"); } push(@headerContent, "#endif\n") if $conditionalString; } - - if (!$interface->extendedAttributes->{"NoInterfaceObject"}) { - my $getter = "js" . $interfaceName . "Constructor"; - push(@headerContent, "JSC::EncodedJSValue ${getter}(JSC::ExecState*, JSC::EncodedJSValue, JSC::EncodedJSValue, JSC::PropertyName);\n"); - } + } - if ($interface->extendedAttributes->{"ReplaceableConstructor"}) { - my $constructorFunctionName = "setJS" . $interfaceName . "Constructor"; - push(@headerContent, "void ${constructorFunctionName}(JSC::ExecState*, JSC::JSObject*, JSC::EncodedJSValue, JSC::EncodedJSValue);\n"); + if ($hasDOMJITAttributes) { + $headerIncludes{"<domjit/DOMJITGetterSetter.h>"} = 1; + push(@headerContent,"// DOMJIT emitters for attributes\n\n"); + foreach my $attribute (@{$interface->attributes}) { + next unless $attribute->extendedAttributes->{"DOMJIT"}; + assert("Only DOMJIT=Getter is supported for attributes") unless $codeGenerator->ExtendedAttributeContains($attribute->extendedAttributes->{DOMJIT}, "Getter"); + + my $interfaceName = $interface->type->name; + my $className = $interfaceName . $codeGenerator->WK_ucfirst($attribute->name); + my $domJITClassName = $className . "DOMJIT"; + + push(@headerContent, "JSC::DOMJIT::GetterSetter* domJITGetterSetterFor$className(void);\n"); + + push(@headerContent, "class ${domJITClassName} : public JSC::DOMJIT::GetterSetter {\n"); + push(@headerContent, "public:\n"); + push(@headerContent, " ${domJITClassName}();\n"); + push(@headerContent, "#if ENABLE(JIT)\n"); + push(@headerContent, " Ref<JSC::DOMJIT::Patchpoint> checkDOM() override;\n"); + push(@headerContent, " Ref<JSC::DOMJIT::CallDOMGetterPatchpoint> callDOMGetter() override;\n"); + push(@headerContent, "#endif\n"); + push(@headerContent, "};\n\n"); } } - if ($numConstants > 0) { - push(@headerContent,"// Constants\n\n"); - foreach my $constant (@{$interface->constants}) { - my $conditionalString = $codeGenerator->GenerateConditionalString($constant); - push(@headerContent, "#if ${conditionalString}\n") if $conditionalString; - my $getter = "js" . $interfaceName . $codeGenerator->WK_ucfirst($constant->name); - push(@headerContent, "JSC::EncodedJSValue ${getter}(JSC::ExecState*, JSC::EncodedJSValue, JSC::EncodedJSValue, JSC::PropertyName);\n"); - push(@headerContent, "#endif\n") if $conditionalString; - } + if (HasCustomConstructor($interface)) { + push(@headerContent, "// Custom constructor\n"); + push(@headerContent, "JSC::EncodedJSValue JSC_HOST_CALL construct${className}(JSC::ExecState&);\n\n"); } + if (NeedsImplementationClass($interface)) { + push(@headerContent, "template<> struct JSDOMWrapperConverterTraits<${implType}> {\n"); + push(@headerContent, " using WrapperClass = ${className};\n"); + push(@headerContent, " using ToWrappedReturnType = " . GetNativeType($interface, $interface->type) . ";\n"); + push(@headerContent, "};\n"); + } + + push(@headerContent, GenerateEnumerationsHeaderContent($interface, $enumerations)); + push(@headerContent, GenerateDictionariesHeaderContent($interface, $dictionaries)); + my $conditionalString = $codeGenerator->GenerateConditionalString($interface); - push(@headerContent, "\n} // namespace WebCore\n\n"); - push(@headerContent, "#endif // ${conditionalString}\n\n") if $conditionalString; - push(@headerContent, "#endif\n"); + push(@headerContent, "\n} // namespace WebCore\n"); + push(@headerContent, "\n#endif // ${conditionalString}\n") if $conditionalString; - if ($interface->extendedAttributes->{"AppleCopyright"}) { + if ($interface->extendedAttributes->{AppleCopyright}) { + push(@headerContent, "\n"); push(@headerContent, split("\r", $endAppleCopyright)); } + + # - Generate dependencies. + if ($writeDependencies) { + my @ancestors; + $codeGenerator->ForAllParents($interface, sub { + my $currentInterface = shift; + push(@ancestors, $currentInterface->type->name); + }, 0); + for my $dictionary (@$dictionaries) { + my $parentType = $dictionary->parentType; + while (defined($parentType)) { + push(@ancestors, $parentType->name) if $codeGenerator->IsExternalDictionaryType($parentType); + my $parentDictionary = $codeGenerator->GetDictionaryByType($parentType); + assert("Unable to find definition for dictionary named '" . $parentType->name . "'!") unless defined($parentDictionary); + $parentType = $parentDictionary->parentType; + } + } + push(@depsContent, "$className.h : ", join(" ", map { "$_.idl" } @ancestors), "\n"); + push(@depsContent, map { "$_.idl :\n" } @ancestors); + } } -sub GenerateAttributesHashTable($$) +sub GeneratePropertiesHashTable { - my ($object, $interface) = @_; + my ($object, $interface, $isInstance, $hashKeys, $hashSpecials, $hashValue1, $hashValue2, $conditionals, $runtimeEnabledFunctions, $runtimeEnabledAttributes) = @_; # FIXME: These should be functions on $interface. - my $interfaceName = $interface->name; + my $interfaceName = $interface->type->name; my $className = "JS$interfaceName"; - # - Add all attributes in a hashtable definition - my $numAttributes = @{$interface->attributes}; - $numAttributes++ if !$interface->extendedAttributes->{"NoInterfaceObject"}; + # - Add all properties in a hashtable definition + my $propertyCount = $isInstance ? InstancePropertyCount($interface) : PrototypePropertyCount($interface); - return 0 if !$numAttributes; - - my $hashSize = $numAttributes; - my $hashName = $className . "Table"; + if (!$isInstance && NeedsConstructorProperty($interface)) { + die if !$propertyCount; + push(@$hashKeys, "constructor"); + my $getter = "js" . $interfaceName . "Constructor"; + push(@$hashValue1, $getter); - my @hashKeys = (); - my @hashSpecials = (); - my @hashValue1 = (); - my @hashValue2 = (); - my %conditionals = (); + my $setter = "setJS" . $interfaceName . "Constructor"; + push(@$hashValue2, $setter); + push(@$hashSpecials, "DontEnum"); + } - my @entries = (); + return 0 if !$propertyCount; foreach my $attribute (@{$interface->attributes}) { next if ($attribute->isStatic); - my $name = $attribute->signature->name; - push(@hashKeys, $name); + next if AttributeShouldBeOnInstance($interface, $attribute) != $isInstance; - my @specials = (); - # As per Web IDL specification, constructor properties on the ECMAScript global object should be - # configurable and should not be enumerable. - my $is_global_constructor = $attribute->signature->type =~ /Constructor$/; - push(@specials, "DontDelete") unless ($attribute->signature->extendedAttributes->{"Deletable"} || $is_global_constructor); - push(@specials, "DontEnum") if ($attribute->signature->extendedAttributes->{"NotEnumerable"} || $is_global_constructor); - push(@specials, "ReadOnly") if IsReadonly($attribute); - my $special = (@specials > 0) ? join(" | ", @specials) : "0"; - push(@hashSpecials, $special); + # Global objects add RuntimeEnabled attributes after creation so do not add them to the static table. + if ($isInstance && NeedsRuntimeCheck($attribute)) { + $propertyCount -= 1; + next; + } - my $getter = GetAttributeGetterName($interfaceName, $className, $attribute); - push(@hashValue1, $getter); + my $name = $attribute->name; + push(@$hashKeys, $name); - if (IsReadonly($attribute)) { - push(@hashValue2, "0"); + my $special = GetJSCAttributesForAttribute($interface, $attribute); + push(@$hashSpecials, $special); + + if ($attribute->extendedAttributes->{"DOMJIT"}) { + push(@$hashValue1, "domJITGetterSetterFor" . $interface->type->name . $codeGenerator->WK_ucfirst($attribute->name)); + push(@$hashValue2, "0"); } else { - my $setter = GetAttributeSetterName($interfaceName, $className, $attribute); - push(@hashValue2, $setter); + my $getter = GetAttributeGetterName($interface, $className, $attribute); + push(@$hashValue1, $getter); + + if (IsReadonly($attribute)) { + push(@$hashValue2, "0"); + } else { + my $setter = GetAttributeSetterName($interface, $className, $attribute); + push(@$hashValue2, $setter); + } } - my $conditional = $attribute->signature->extendedAttributes->{"Conditional"}; - if ($conditional) { - $conditionals{$name} = $conditional; + my $conditional = $attribute->extendedAttributes->{Conditional}; + $conditionals->{$name} = $conditional if $conditional; + + if (NeedsRuntimeCheck($attribute)) { + push(@$runtimeEnabledAttributes, $attribute); } } - if (!$interface->extendedAttributes->{"NoInterfaceObject"}) { - push(@hashKeys, "constructor"); - my $getter = "js" . $interfaceName . "Constructor"; - push(@hashValue1, $getter); - if ($interface->extendedAttributes->{"ReplaceableConstructor"}) { - my $setter = "setJS" . $interfaceName . "Constructor"; - push(@hashValue2, $setter); - push(@hashSpecials, "DontEnum | DontDelete"); - } else { - push(@hashValue2, "0"); - push(@hashSpecials, "DontEnum | ReadOnly"); + my @functions = @{$interface->functions}; + push(@functions, @{$interface->iterable->functions}) if IsKeyValueIterableInterface($interface); + push(@functions, @{$interface->serializable->functions}) if $interface->serializable; + foreach my $function (@functions) { + next if ($function->extendedAttributes->{PrivateIdentifier} and not $function->extendedAttributes->{PublicIdentifier}); + next if ($function->isStatic); + next if $function->{overloadIndex} && $function->{overloadIndex} > 1; + next if OperationShouldBeOnInstance($interface, $function) != $isInstance; + next if $function->name eq "[Symbol.Iterator]"; + + # Global objects add RuntimeEnabled operations after creation so do not add them to the static table. + if ($isInstance && NeedsRuntimeCheck($function)) { + $propertyCount -= 1; + next; + } + + my $name = $function->name; + push(@$hashKeys, $name); + + my $functionName = GetFunctionName($interface, $className, $function); + push(@$hashValue1, $functionName); + + my $functionLength = GetFunctionLength($function); + + if ($function->extendedAttributes->{DOMJIT}) { + push(@$hashValue2, "&DOMJITSignatureFor" . $interface->type->name . $codeGenerator->WK_ucfirst($function->name)); + } else { + push(@$hashValue2, $functionLength); + } + + push(@$hashSpecials, ComputeFunctionSpecial($interface, $function)); + + my $conditional = getConditionalForFunctionConsideringOverloads($function); + $conditionals->{$name} = $conditional if $conditional; + + if (NeedsRuntimeCheck($function)) { + push(@$runtimeEnabledFunctions, $function); } } - $object->GenerateHashTable($hashName, $hashSize, - \@hashKeys, \@hashSpecials, - \@hashValue1, \@hashValue2, - \%conditionals); - return $numAttributes; + return $propertyCount; } -sub GenerateParametersCheckExpression +# This computes an effective overload set for a given operation / constructor, +# which represents the allowable invocations.This set is used as input for +# the Web IDL overload resolution algorithm. +# http://heycam.github.io/webidl/#dfn-effective-overload-set +sub ComputeEffectiveOverloadSet { - my $numParameters = shift; - my $function = shift; + my ($overloads) = @_; + + my %allSets; + my $addTuple = sub { + my $tuple = shift; + # The Web IDL specification uses a flat set of tuples but we use a hash where the key is the + # number of parameters and the value is the set of tuples for the given number of parameters. + my $length = scalar(@{@$tuple[1]}); + if (!exists($allSets{$length})) { + $allSets{$length} = [ $tuple ]; + } else { + push(@{$allSets{$length}}, $tuple); + } + }; - my @andExpression = (); - push(@andExpression, "argsCount == $numParameters"); - my $parameterIndex = 0; - my %usedArguments = (); - foreach my $parameter (@{$function->parameters}) { - last if $parameterIndex >= $numParameters; - my $value = "arg$parameterIndex"; - my $type = $parameter->type; - - # Only DOMString or wrapper types are checked. - # For DOMString with StrictTypeChecking only Null, Undefined and Object - # are accepted for compatibility. Otherwise, no restrictions are made to - # match the non-overloaded behavior. - # FIXME: Implement WebIDL overload resolution algorithm. - if ($codeGenerator->IsStringType($type)) { - if ($parameter->extendedAttributes->{"StrictTypeChecking"}) { - push(@andExpression, "(${value}.isUndefinedOrNull() || ${value}.isString() || ${value}.isObject())"); - $usedArguments{$parameterIndex} = 1; - } - } elsif ($codeGenerator->IsCallbackInterface($parameter->type)) { - # For Callbacks only checks if the value is null or object. - push(@andExpression, "(${value}.isNull() || ${value}.isFunction())"); - $usedArguments{$parameterIndex} = 1; - } elsif ($codeGenerator->GetArrayType($type) || $codeGenerator->GetSequenceType($type)) { - # FIXME: Add proper support for T[], T[]?, sequence<T> - if ($parameter->isNullable) { - push(@andExpression, "(${value}.isNull() || (${value}.isObject() && isJSArray(${value})))"); + my $m = LengthOfLongestFunctionParameterList($overloads); + foreach my $overload (@{$overloads}) { + my $n = @{$overload->arguments}; + my @t; + my @o; + my $isVariadic = 0; + foreach my $argument (@{$overload->arguments}) { + push(@t, $argument->type); + if ($argument->isOptional) { + push(@o, "optional"); + } elsif ($argument->isVariadic) { + push(@o, "variadic"); + $isVariadic = 1; } else { - push(@andExpression, "(${value}.isObject() && isJSArray(${value}))"); + push(@o, "required"); } - $usedArguments{$parameterIndex} = 1; - } elsif (!IsNativeType($type)) { - if ($parameter->isNullable) { - push(@andExpression, "(${value}.isNull() || (${value}.isObject() && asObject(${value})->inherits(JS${type}::info())))"); - } else { - push(@andExpression, "(${value}.isObject() && asObject(${value})->inherits(JS${type}::info()))"); + } + &$addTuple([$overload, [@t], [@o]]); + if ($isVariadic) { + my @newT = @t; + my @newO = @o; + for (my $i = $n; $i < $m; $i++) { + push(@newT, $t[-1]); + push(@newO, "variadic"); + &$addTuple([$overload, [@newT], [@newO]]); } - $usedArguments{$parameterIndex} = 1; } - $parameterIndex++; + for (my $i = $n - 1; $i >= 0; $i--) { + my $argument = @{$overload->arguments}[$i]; + last unless ($argument->isOptional || $argument->isVariadic); + pop(@t); + pop(@o); + &$addTuple([$overload, [@t], [@o]]); + } } - my $res = join(" && ", @andExpression); - $res = "($res)" if @andExpression > 1; - return ($res, sort {$a <=> $b} (keys %usedArguments)); + return %allSets; } -# As per Web IDL specification, the length of a function Object is -# its number of mandatory parameters. -sub GetFunctionLength +sub IsIDLTypeDistinguishableWithUnionForOverloadResolution { - my $function = shift; + my ($type, $unionSubtypes) = @_; - my $numMandatoryParams = 0; - foreach my $parameter (@{$function->parameters}) { - # Abort as soon as we find the first optional parameter as no mandatory - # parameter can follow an optional one. - last if $parameter->isOptional; - $numMandatoryParams++; - } - return $numMandatoryParams; + assert("First type should not be a union") if $type->isUnion; + for my $unionSubType (@$unionSubtypes) { + return 0 unless AreTypesDistinguishableForOverloadResolution($type, $unionSubType); + } + return 1; } -sub GenerateFunctionParametersCheck +# Determines if two types are distinguishable in the context of overload resolution, +# according to the Web IDL specification: +# http://heycam.github.io/webidl/#dfn-distinguishable +sub AreTypesDistinguishableForOverloadResolution { - my $function = shift; + my ($typeA, $typeB) = @_; - my @orExpression = (); - my $numParameters = 0; - my @neededArguments = (); - my $hasVariadic = 0; - my $numMandatoryParams = @{$function->parameters}; - - foreach my $parameter (@{$function->parameters}) { - if ($parameter->isOptional) { - my ($expression, @usedArguments) = GenerateParametersCheckExpression($numParameters, $function); - push(@orExpression, $expression); - push(@neededArguments, @usedArguments); - $numMandatoryParams--; + my $isDictionary = sub { + my $type = shift; + return $codeGenerator->IsDictionaryType($type); + }; + my $isCallbackFunctionOrDictionary = sub { + my $type = shift; + return $codeGenerator->IsCallbackFunction($type) || &$isDictionary($type); + }; + + # Two types are distinguishable for overload resolution if at most one of the two includes a nullable type. + return 0 if $typeA->isNullable && $typeB->isNullable; + + # Union types: typeA and typeB are distinguishable if: + # - Both types are either a union type or nullable union type, and each member type of the one is + # distinguishable with each member type of the other. + # - One type is a union type or nullable union type, the other is neither a union type nor a nullable + # union type, and each member type of the first is distinguishable with the second. + if ($typeA->isUnion && $typeB->isUnion) { + for my $unionASubType (@{$typeA->subtypes}) { + return 0 unless IsIDLTypeDistinguishableWithUnionForOverloadResolution($unionASubType, $typeB->subtypes); } - if ($parameter->isVariadic) { - $hasVariadic = 1; - last; + return 1; + } elsif ($typeA->isUnion) { + return IsIDLTypeDistinguishableWithUnionForOverloadResolution($typeB, $typeA->subtypes); + } elsif ($typeB->isUnion) { + return IsIDLTypeDistinguishableWithUnionForOverloadResolution($typeA, $typeB->subtypes); + } + + return 0 if $typeA->name eq $typeB->name; + return 0 if $typeA->name eq "object" or $typeB->name eq "object"; + return 0 if $codeGenerator->IsNumericType($typeA) && $codeGenerator->IsNumericType($typeB); + return 0 if $codeGenerator->IsStringOrEnumType($typeA) && $codeGenerator->IsStringOrEnumType($typeB); + return 0 if &$isDictionary($typeA) && &$isDictionary($typeB); + return 0 if $codeGenerator->IsCallbackInterface($typeA) && $codeGenerator->IsCallbackInterface($typeB); + return 0 if &$isCallbackFunctionOrDictionary($typeA) && &$isCallbackFunctionOrDictionary($typeB); + return 0 if $codeGenerator->IsSequenceOrFrozenArrayType($typeA) && $codeGenerator->IsSequenceOrFrozenArrayType($typeB); + # FIXME: return 0 if $typeA and $typeB are both exception types. + return 1; +} + +# If there is more than one entry in an effective overload set that has a given type list length, +# then for those entries there must be an index i such that for each pair of entries the types +# at index i are distinguishable. The lowest such index is termed the distinguishing argument index. +# http://heycam.github.io/webidl/#dfn-distinguishing-argument-index +sub GetDistinguishingArgumentIndex +{ + my ($function, $S) = @_; + + # FIXME: Consider all the tuples, not just the 2 first ones? + my $firstTupleTypes = @{@{$S}[0]}[1]; + my $secondTupleTypes = @{@{$S}[1]}[1]; + for (my $index = 0; $index < scalar(@$firstTupleTypes); $index++) { + return $index if AreTypesDistinguishableForOverloadResolution(@{$firstTupleTypes}[$index], @{$secondTupleTypes}[$index]); + } + die "Undistinguishable overloads for operation " . $function->name . " with length: " . scalar(@$firstTupleTypes); +} + +sub GetOverloadThatMatches +{ + my ($S, $parameterIndex, $matches) = @_; + + for my $tuple (@{$S}) { + my $type = @{@{$tuple}[1]}[$parameterIndex]; + my $optionality = @{@{$tuple}[2]}[$parameterIndex]; + if ($type->isUnion) { + for my $subtype (GetFlattenedMemberTypes($type)) { + return @{$tuple}[0] if $matches->($subtype, $optionality); + } + } else { + return @{$tuple}[0] if $matches->($type, $optionality); } - $numParameters++; } - if (!$hasVariadic) { - my ($expression, @usedArguments) = GenerateParametersCheckExpression($numParameters, $function); - push(@orExpression, $expression); - push(@neededArguments, @usedArguments); +} + +sub GetOverloadThatMatchesIgnoringUnionSubtypes +{ + my ($S, $parameterIndex, $matches) = @_; + + for my $tuple (@{$S}) { + my $type = @{@{$tuple}[1]}[$parameterIndex]; + my $optionality = @{@{$tuple}[2]}[$parameterIndex]; + return @{$tuple}[0] if $matches->($type, $optionality); } - return ($numMandatoryParams, join(" || ", @orExpression), @neededArguments); } -sub GenerateOverloadedFunction +sub getConditionalForFunctionConsideringOverloads { my $function = shift; - my $interface = shift; - my $interfaceName = shift; - # Generate code for choosing the correct overload to call. Overloads are - # chosen based on the total number of arguments passed and the type of - # values passed in non-primitive argument slots. When more than a single - # overload is applicable, precedence is given according to the order of - # declaration in the IDL. + return $function->extendedAttributes->{Conditional} unless $function->{overloads}; - my $kind = $function->isStatic ? "Constructor" : "Prototype"; - my $functionName = "js${interfaceName}${kind}Function" . $codeGenerator->WK_ucfirst($function->signature->name); + my %conditions; + foreach my $overload (@{$function->{overloads}}) { + my $conditional = $overload->extendedAttributes->{Conditional}; + return unless $conditional; + $conditions{$conditional} = 1; + } + return join("|", keys %conditions); +} - push(@implContent, "EncodedJSValue JSC_HOST_CALL ${functionName}(ExecState* exec)\n"); - push(@implContent, <<END); +# Implements the overload resolution algorithm, as defined in the Web IDL specification: +# http://heycam.github.io/webidl/#es-overloads +sub GenerateOverloadedFunctionOrConstructor { - size_t argsCount = exec->argumentCount(); + my ($function, $interface, $isConstructor) = @_; + my %allSets = ComputeEffectiveOverloadSet($function->{overloads}); + + my $interfaceName = $interface->type->name; + my $className = "JS$interfaceName"; + my $functionName; + if ($isConstructor) { + $functionName = "construct${className}"; + } else { + my $kind = $function->isStatic ? "Constructor" : (OperationShouldBeOnInstance($interface, $function) ? "Instance" : "Prototype"); + $functionName = "js${interfaceName}${kind}Function" . $codeGenerator->WK_ucfirst($function->name); + } + + my $generateOverloadCallIfNecessary = sub { + my ($overload, $condition, $include) = @_; + return unless $overload; + my $conditionalString = $codeGenerator->GenerateConditionalString($overload); + push(@implContent, "#if ${conditionalString}\n") if $conditionalString; + push(@implContent, " if ($condition)\n ") if $condition; + push(@implContent, " return ${functionName}$overload->{overloadIndex}(state);\n"); + push(@implContent, "#endif\n") if $conditionalString; + AddToImplIncludes($include, $overload->extendedAttributes->{"Conditional"}) if $include; + }; + my $isOptionalParameter = sub { + my ($type, $optionality) = @_; + return $optionality eq "optional"; + }; + my $isDictionaryOrRecordParameter = sub { + my ($type, $optionality) = @_; + return $codeGenerator->IsDictionaryType($type) || $codeGenerator->IsRecordType($type); + }; + my $isNullableOrDictionaryOrRecordOrUnionContainingOne = sub { + my ($type, $optionality) = @_; + return 1 if $type->isNullable; + if ($type->isUnion) { + for my $subtype (GetFlattenedMemberTypes($type)) { + return 1 if $type->isNullable || &$isDictionaryOrRecordParameter($subtype, $optionality); + } + return 0; + } else { + return &$isDictionaryOrRecordParameter($type, $optionality); + } + }; + my $isRegExpOrObjectParameter = sub { + my ($type, $optionality) = @_; + return $type->name eq "RegExp" || $type->name eq "object"; + }; + my $isObjectOrErrorParameter = sub { + my ($type, $optionality) = @_; + return $type->name eq "object" || $type->name eq "Error"; + }; + my $isObjectOrErrorOrDOMExceptionParameter = sub { + my ($type, $optionality) = @_; + return 1 if &$isObjectOrErrorParameter($type, $optionality); + return $type->name eq "DOMException"; + }; + my $isObjectOrCallbackFunctionParameter = sub { + my ($type, $optionality) = @_; + return $type->name eq "object" || $codeGenerator->IsCallbackFunction($type); + }; + my $isSequenceOrFrozenArrayParameter = sub { + my ($type, $optionality) = @_; + return $codeGenerator->IsSequenceOrFrozenArrayType($type); + }; + my $isDictionaryOrRecordOrObjectOrCallbackInterfaceParameter = sub { + my ($type, $optionality) = @_; + return 1 if &$isDictionaryOrRecordParameter($type, $optionality); + return 1 if $type->name eq "object"; + return 1 if $codeGenerator->IsCallbackInterface($type) && !$codeGenerator->IsCallbackFunction($type); + return 0; + }; + my $isBooleanParameter = sub { + my ($type, $optionality) = @_; + return $type->name eq "boolean"; + }; + my $isNumericParameter = sub { + my ($type, $optionality) = @_; + return $codeGenerator->IsNumericType($type); + }; + my $isStringOrEnumParameter = sub { + my ($type, $optionality) = @_; + return $codeGenerator->IsStringOrEnumType($type); + }; + my $isAnyParameter = sub { + my ($type, $optionality) = @_; + return $type->name eq "any"; + }; + + my $maxArgCount = LengthOfLongestFunctionParameterList($function->{overloads}); + + my $conditionalAttribute = getConditionalForFunctionConsideringOverloads($function); + my $conditionalString = $conditionalAttribute ? $codeGenerator->GenerateConditionalStringFromAttributeValue($conditionalAttribute) : undef; + push(@implContent, "#if ${conditionalString}\n") if $conditionalString; + if ($isConstructor) { + push(@implContent, "template<> EncodedJSValue JSC_HOST_CALL ${className}Constructor::construct(ExecState* state)\n"); + } else { + push(@implContent, "EncodedJSValue JSC_HOST_CALL ${functionName}(ExecState* state)\n"); + } + push(@implContent, <<END); +{ + VM& vm = state->vm(); + auto throwScope = DECLARE_THROW_SCOPE(vm); + UNUSED_PARAM(throwScope); + size_t argsCount = std::min<size_t>($maxArgCount, state->argumentCount()); +END + + for my $length ( sort keys %allSets ) { + push(@implContent, <<END); + if (argsCount == $length) { END + my $S = $allSets{$length}; + if (scalar(@$S) > 1) { + my $d = GetDistinguishingArgumentIndex($function, $S); + push(@implContent, " JSValue distinguishingArg = state->uncheckedArgument($d);\n"); + + my $overload = GetOverloadThatMatchesIgnoringUnionSubtypes($S, $d, \&$isOptionalParameter); + &$generateOverloadCallIfNecessary($overload, "distinguishingArg.isUndefined()"); + + $overload = GetOverloadThatMatchesIgnoringUnionSubtypes($S, $d, \&$isNullableOrDictionaryOrRecordOrUnionContainingOne); + &$generateOverloadCallIfNecessary($overload, "distinguishingArg.isUndefinedOrNull()"); + + for my $tuple (@{$S}) { + my $overload = @{$tuple}[0]; + my $type = @{@{$tuple}[1]}[$d]; + + my @subtypes = $type->isUnion ? GetFlattenedMemberTypes($type) : ( $type ); + for my $subtype (@subtypes) { + if ($codeGenerator->IsWrapperType($subtype) || $codeGenerator->IsTypedArrayType($subtype)) { + if ($subtype->name eq "DOMWindow") { + AddToImplIncludes("JSDOMWindowShell.h"); + &$generateOverloadCallIfNecessary($overload, "distinguishingArg.isObject() && (asObject(distinguishingArg)->inherits(vm, JSDOMWindowShell::info()) || asObject(distinguishingArg)->inherits(vm, JSDOMWindow::info()))"); + } else { + &$generateOverloadCallIfNecessary($overload, "distinguishingArg.isObject() && asObject(distinguishingArg)->inherits(vm, JS" . $subtype->name . "::info())"); + } + } + } + } - my %fetchedArguments = (); - my $leastNumMandatoryParams = 255; + $overload = GetOverloadThatMatches($S, $d, \&$isRegExpOrObjectParameter); + &$generateOverloadCallIfNecessary($overload, "distinguishingArg.isObject() && asObject(distinguishingArg)->type() == RegExpObjectType"); - foreach my $overload (@{$function->{overloads}}) { - my ($numMandatoryParams, $parametersCheck, @neededArguments) = GenerateFunctionParametersCheck($overload); - $leastNumMandatoryParams = $numMandatoryParams if ($numMandatoryParams < $leastNumMandatoryParams); + $overload = GetOverloadThatMatches($S, $d, \&$isObjectOrErrorOrDOMExceptionParameter); + &$generateOverloadCallIfNecessary($overload, "distinguishingArg.isObject() && asObject(distinguishingArg)->inherits(vm, JSDOMCoreException::info())"); - foreach my $parameterIndex (@neededArguments) { - next if exists $fetchedArguments{$parameterIndex}; - push(@implContent, " JSValue arg$parameterIndex(exec->argument($parameterIndex));\n"); - $fetchedArguments{$parameterIndex} = 1; - } + $overload = GetOverloadThatMatches($S, $d, \&$isObjectOrErrorParameter); + &$generateOverloadCallIfNecessary($overload, "distinguishingArg.isObject() && asObject(distinguishingArg)->type() == ErrorInstanceType"); - my $conditionalString = $codeGenerator->GenerateConditionalString($overload->signature); - push(@implContent, "#if ${conditionalString}\n") if $conditionalString; + $overload = GetOverloadThatMatches($S, $d, \&$isObjectOrCallbackFunctionParameter); + &$generateOverloadCallIfNecessary($overload, "distinguishingArg.isFunction()"); + + # FIXME: Avoid invoking GetMethod(object, Symbol.iterator) again in convert<IDLSequence<T>>(...). + $overload = GetOverloadThatMatches($S, $d, \&$isSequenceOrFrozenArrayParameter); + &$generateOverloadCallIfNecessary($overload, "hasIteratorMethod(*state, distinguishingArg)", "<runtime/IteratorOperations.h>"); + + $overload = GetOverloadThatMatches($S, $d, \&$isDictionaryOrRecordOrObjectOrCallbackInterfaceParameter); + &$generateOverloadCallIfNecessary($overload, "distinguishingArg.isObject() && asObject(distinguishingArg)->type() != RegExpObjectType"); + + my $booleanOverload = GetOverloadThatMatches($S, $d, \&$isBooleanParameter); + &$generateOverloadCallIfNecessary($booleanOverload, "distinguishingArg.isBoolean()"); - push(@implContent, " if ($parametersCheck)\n"); - push(@implContent, " return ${functionName}$overload->{overloadIndex}(exec);\n"); - push(@implContent, "#endif\n\n") if $conditionalString; + my $numericOverload = GetOverloadThatMatches($S, $d, \&$isNumericParameter); + &$generateOverloadCallIfNecessary($numericOverload, "distinguishingArg.isNumber()"); + # Fallbacks. + $overload = GetOverloadThatMatches($S, $d, \&$isStringOrEnumParameter); + if ($overload) { + &$generateOverloadCallIfNecessary($overload); + } elsif ($numericOverload) { + &$generateOverloadCallIfNecessary($numericOverload); + } elsif ($booleanOverload) { + &$generateOverloadCallIfNecessary($booleanOverload); + } else { + $overload = GetOverloadThatMatches($S, $d, \&$isAnyParameter); + &$generateOverloadCallIfNecessary($overload); + } + } else { + # Only 1 overload with this number of parameters. + my $overload = @{@{$S}[0]}[0]; + &$generateOverloadCallIfNecessary($overload); + } + push(@implContent, <<END); + } +END } - if ($leastNumMandatoryParams >= 1) { - push(@implContent, " if (argsCount < $leastNumMandatoryParams)\n"); - push(@implContent, " return throwVMError(exec, createNotEnoughArgumentsError(exec));\n"); + my $minArgCount = GetFunctionLength($function); + if ($minArgCount > 0) { + push(@implContent, " return argsCount < $minArgCount ? throwVMError(state, throwScope, createNotEnoughArgumentsError(state)) : throwVMTypeError(state, throwScope);\n") + } else { + push(@implContent, " return throwVMTypeError(state, throwScope);\n") } - push(@implContent, <<END); - return throwVMTypeError(exec); + push(@implContent, "}\n"); + push(@implContent, "#endif\n") if $conditionalString; + push(@implContent, "\n"); } -END +# As per Web IDL specification, the length of a function Object is its number of mandatory parameters. +sub GetFunctionLength +{ + my $function = shift; + + my $getOverloadLength = sub { + my $function = shift; + + my $length = 0; + foreach my $argument (@{$function->arguments}) { + last if $argument->isOptional || $argument->isVariadic; + $length++; + } + return $length; + }; + + my $length = &$getOverloadLength($function); + foreach my $overload (@{$function->{overloads}}) { + my $newLength = &$getOverloadLength($overload); + $length = $newLength if $newLength < $length; + } + return $length; } -sub GetNativeTypeForConversions +sub LengthOfLongestFunctionParameterList { - my $interface = shift; - my $interfaceName = $interface->name; - $interfaceName = $codeGenerator->GetSVGTypeNeedingTearOff($interfaceName) if $codeGenerator->IsSVGTypeNeedingTearOff($interfaceName); - return $interfaceName; + my ($overloads) = @_; + my $result = 0; + foreach my $overload (@{$overloads}) { + my @arguments = @{$overload->arguments}; + $result = @arguments if $result < @arguments; + } + return $result; } # See http://refspecs.linux-foundation.org/cxxabi-1.83.html. @@ -1418,7 +2782,7 @@ sub GetGnuVTableRefForInterface if (!$vtableName) { return "0"; } - my $typename = GetNativeTypeForConversions($interface); + my $typename = $interface->type->name; my $offset = GetGnuVTableOffsetForType($typename); return "&" . $vtableName . "[" . $offset . "]"; } @@ -1426,7 +2790,7 @@ sub GetGnuVTableRefForInterface sub GetGnuVTableNameForInterface { my $interface = shift; - my $typename = GetNativeTypeForConversions($interface); + my $typename = $interface->type->name; my $templatePosition = index($typename, "<"); return "" if $templatePosition != -1; return "" if GetImplementationLacksVTableForInterface($interface); @@ -1437,13 +2801,13 @@ sub GetGnuVTableNameForInterface sub GetGnuMangledNameForInterface { my $interface = shift; - my $typename = GetNativeTypeForConversions($interface); + my $typename = $interface->type->name; my $templatePosition = index($typename, "<"); if ($templatePosition != -1) { return ""; } my $mangledType = length($typename) . $typename; - my $namespace = GetNamespaceForInterface($interface); + my $namespace = "WebCore"; my $mangledNamespace = "N" . length($namespace) . $namespace; return $mangledNamespace . $mangledType . "E"; } @@ -1487,7 +2851,7 @@ sub GetWinVTableRefForInterface sub GetWinVTableNameForInterface { my $interface = shift; - my $typename = GetNativeTypeForConversions($interface); + my $typename = $interface->type->name; my $templatePosition = index($typename, "<"); return "" if $templatePosition != -1; return "" if GetImplementationLacksVTableForInterface($interface); @@ -1498,27 +2862,21 @@ sub GetWinVTableNameForInterface sub GetWinMangledNameForInterface { my $interface = shift; - my $typename = GetNativeTypeForConversions($interface); - my $namespace = GetNamespaceForInterface($interface); + my $typename = $interface->type->name; + my $namespace = "WebCore"; return $typename . "@" . $namespace . "@@"; } -sub GetNamespaceForInterface -{ - my $interface = shift; - return $interface->extendedAttributes->{"ImplementationNamespace"} || "WebCore"; -} - sub GetImplementationLacksVTableForInterface { my $interface = shift; - return $interface->extendedAttributes->{"ImplementationLacksVTable"}; + return $interface->extendedAttributes->{ImplementationLacksVTable}; } sub GetSkipVTableValidationForInterface { my $interface = shift; - return $interface->extendedAttributes->{"SkipVTableValidation"}; + return $interface->extendedAttributes->{SkipVTableValidation}; } # URL becomes url, but SetURL becomes setURL. @@ -1526,12 +2884,13 @@ sub ToMethodName { my $param = shift; my $ret = lcfirst($param); + $ret =~ s/cSS/css/ if $ret =~ /^cSS/; + $ret =~ s/dOM/dom/ if $ret =~ /^dOM/; $ret =~ s/hTML/html/ if $ret =~ /^hTML/; - $ret =~ s/uRL/url/ if $ret =~ /^uRL/; $ret =~ s/jS/js/ if $ret =~ /^jS/; + $ret =~ s/uRL/url/ if $ret =~ /^uRL/; $ret =~ s/xML/xml/ if $ret =~ /^xML/; $ret =~ s/xSLT/xslt/ if $ret =~ /^xSLT/; - $ret =~ s/cSS/css/ if $ret =~ /^cSS/; # For HTML5 FileSystem API Flags attributes. # (create is widely used to instantiate an object and must be avoided.) @@ -1542,57 +2901,282 @@ sub ToMethodName } # Returns the RuntimeEnabledFeatures function name that is hooked up to check if a method/attribute is enabled. +# NOTE: Parameter passed in must have both an 'extendedAttributes' property. +# (e.g. DOMInterface, DOMAttribute, DOMOperation, DOMIterable, etc.) sub GetRuntimeEnableFunctionName { - my $signature = shift; + my $context = shift; + + AddToImplIncludes("RuntimeEnabledFeatures.h"); + + if ($context->extendedAttributes->{EnabledForWorld}) { + return "worldForDOMObject(this)." . ToMethodName($context->extendedAttributes->{EnabledForWorld}); + } # If a parameter is given (e.g. "EnabledAtRuntime=FeatureName") return the RuntimeEnabledFeatures::sharedFeatures().{FeatureName}Enabled() method. - return "RuntimeEnabledFeatures::sharedFeatures()." . ToMethodName($signature->extendedAttributes->{"EnabledAtRuntime"}) . "Enabled" if ($signature->extendedAttributes->{"EnabledAtRuntime"} && $signature->extendedAttributes->{"EnabledAtRuntime"} ne "VALUE_IS_MISSING"); + if ($context->extendedAttributes->{EnabledAtRuntime} && $context->extendedAttributes->{EnabledAtRuntime} ne "VALUE_IS_MISSING") { + return "RuntimeEnabledFeatures::sharedFeatures()." . ToMethodName($context->extendedAttributes->{EnabledAtRuntime}) . "Enabled"; + } # Otherwise return a function named RuntimeEnabledFeatures::sharedFeatures().{methodName}Enabled(). - return "RuntimeEnabledFeatures::sharedFeatures()." . ToMethodName($signature->name) . "Enabled"; + return "RuntimeEnabledFeatures::sharedFeatures()." . ToMethodName($context->name) . "Enabled"; +} + +sub GetCastingHelperForThisObject +{ + my $interface = shift; + my $interfaceName = $interface->type->name; + return "jsDynamicDowncast<JS$interfaceName*>"; +} + +# http://heycam.github.io/webidl/#Unscopable +sub addUnscopableProperties +{ + my $interface = shift; + + my @unscopables; + foreach my $functionOrAttribute (@{$interface->functions}, @{$interface->attributes}) { + push(@unscopables, $functionOrAttribute->name) if $functionOrAttribute->extendedAttributes->{Unscopable}; + } + return if scalar(@unscopables) == 0; + + AddToImplIncludes("<runtime/ObjectConstructor.h>"); + push(@implContent, " JSObject& unscopables = *constructEmptyObject(globalObject()->globalExec(), globalObject()->nullPrototypeObjectStructure());\n"); + foreach my $unscopable (@unscopables) { + push(@implContent, " unscopables.putDirect(vm, Identifier::fromString(&vm, \"$unscopable\"), jsBoolean(true));\n"); + } + push(@implContent, " putDirectWithoutTransition(vm, vm.propertyNames->unscopablesSymbol, &unscopables, DontEnum | ReadOnly);\n"); +} + +sub GetUnsafeArgumentType +{ + my ($interface, $type) = @_; + + my $IDLType = GetIDLType($interface, $type); + return "DOMJIT::IDLJSArgumentType<${IDLType}>"; +} + +sub GetArgumentTypeFilter +{ + my ($interface, $type) = @_; + + my $IDLType = GetIDLType($interface, $type); + return "DOMJIT::IDLArgumentTypeFilter<${IDLType}>::value"; +} + +sub GetResultTypeFilter +{ + my ($interface, $type) = @_; + + my $IDLType = GetIDLType($interface, $type); + return "DOMJIT::IDLResultTypeFilter<${IDLType}>::value"; +} + +sub GetAttributeWithName +{ + my ($interface, $attributeName) = @_; + + foreach my $attribute (@{$interface->attributes}) { + return $attribute if $attribute->name eq $attributeName; + } +} + +# https://heycam.github.io/webidl/#es-iterator +sub InterfaceNeedsIterator +{ + my ($interface) = @_; + + return 1 if $interface->iterable; + if (GetIndexedGetterFunction($interface)) { + my $lengthAttribute = GetAttributeWithName($interface, "length"); + return 1 if $lengthAttribute and $codeGenerator->IsIntegerType($lengthAttribute->type); + } + # FIXME: This should return 1 for maplike and setlike once we support them. + return 0; } sub GenerateImplementation { - my ($object, $interface) = @_; + my ($object, $interface, $enumerations, $dictionaries) = @_; - my $interfaceName = $interface->name; + my $interfaceName = $interface->type->name; my $className = "JS$interfaceName"; - my $hasLegacyParent = $interface->extendedAttributes->{"JSLegacyParent"}; - my $hasRealParent = $interface->parent; + my $hasLegacyParent = $interface->extendedAttributes->{JSLegacyParent}; + my $hasRealParent = $interface->parentType; my $hasParent = $hasLegacyParent || $hasRealParent; my $parentClassName = GetParentClassName($interface); my $visibleInterfaceName = $codeGenerator->GetVisibleInterfaceName($interface); - my $eventTarget = $interface->extendedAttributes->{"EventTarget"} || ($codeGenerator->InheritsInterface($interface, "EventTarget") && $interface->name ne "EventTarget"); - my $needsMarkChildren = $interface->extendedAttributes->{"JSCustomMarkFunction"} || $interface->extendedAttributes->{"EventTarget"} || $interface->name eq "EventTarget"; + my $eventTarget = $codeGenerator->InheritsInterface($interface, "EventTarget") && $interface->type->name ne "EventTarget"; + my $needsVisitChildren = InstanceNeedsVisitChildren($interface); my $namedGetterFunction = GetNamedGetterFunction($interface); my $indexedGetterFunction = GetIndexedGetterFunction($interface); - my $hasNumericIndexedGetter = $indexedGetterFunction ? $codeGenerator->IsNumericType($indexedGetterFunction->signature->type) : 0; # - Add default header template push(@implContentHeader, GenerateImplementationContentHeader($interface)); + $implIncludes{"JSDOMBinding.h"} = 1; + $implIncludes{"JSDOMBindingCaller.h"} = 1; + $implIncludes{"JSDOMExceptionHandling.h"} = 1; + $implIncludes{"JSDOMWrapperCache.h"} = 1; $implIncludes{"<wtf/GetPtr.h>"} = 1; $implIncludes{"<runtime/PropertyNameArray.h>"} = 1 if $indexedGetterFunction; - AddIncludesForTypeInImpl($interfaceName); + my $implType = GetImplClassName($interface); + + AddJSBuiltinIncludesIfNeeded($interface); @implContent = (); push(@implContent, "\nusing namespace JSC;\n\n"); push(@implContent, "namespace WebCore {\n\n"); - my $numAttributes = GenerateAttributesHashTable($object, $interface); + push(@implContent, GenerateEnumerationsImplementationContent($interface, $enumerations)); + push(@implContent, GenerateDictionariesImplementationContent($interface, $dictionaries)); + + my @functions = @{$interface->functions}; + push(@functions, @{$interface->iterable->functions}) if IsKeyValueIterableInterface($interface); + push(@functions, @{$interface->serializable->functions}) if $interface->serializable; my $numConstants = @{$interface->constants}; - my $numFunctions = @{$interface->functions}; + my $numFunctions = @functions; + my $numAttributes = @{$interface->attributes}; + + if ($numFunctions > 0) { + my $inAppleCopyright = 0; + push(@implContent,"// Functions\n\n"); + foreach my $function (@functions) { + next if $function->{overloadIndex} && $function->{overloadIndex} > 1; + next if $function->extendedAttributes->{ForwardDeclareInHeader}; + next if IsJSBuiltin($interface, $function); + + if ($function->extendedAttributes->{AppleCopyright}) { + if (!$inAppleCopyright) { + push(@implContent, $beginAppleCopyrightForHeaderFiles); + $inAppleCopyright = 1; + } + } elsif ($inAppleCopyright) { + push(@implContent, $endAppleCopyright); + $inAppleCopyright = 0; + } + + my $conditionalAttribute = getConditionalForFunctionConsideringOverloads($function); + my $conditionalString = $conditionalAttribute ? $codeGenerator->GenerateConditionalStringFromAttributeValue($conditionalAttribute) : undef; + push(@implContent, "#if ${conditionalString}\n") if $conditionalString; + my $functionName = GetFunctionName($interface, $className, $function); + push(@implContent, "JSC::EncodedJSValue JSC_HOST_CALL ${functionName}(JSC::ExecState*);\n"); + if ($function->extendedAttributes->{DOMJIT}) { + $implIncludes{"DOMJITIDLType.h"} = 1; + my $unsafeFunctionName = "unsafe" . $codeGenerator->WK_ucfirst($functionName); + my $functionSignature = "JSC::EncodedJSValue JIT_OPERATION ${unsafeFunctionName}(JSC::ExecState*, $className*"; + foreach my $argument (@{$function->arguments}) { + my $type = $argument->type; + my $argumentType = GetUnsafeArgumentType($interface, $type); + $functionSignature .= ", ${argumentType}"; + } + push(@implContent, $functionSignature . ");\n"); + } + push(@implContent, "#endif\n") if $conditionalString; + } + + push(@implContent, $endAppleCopyright) if $inAppleCopyright; + push(@implContent, "\n"); + } + + if ($numAttributes > 0 || NeedsConstructorProperty($interface)) { + push(@implContent, "// Attributes\n\n"); + + foreach my $attribute (@{$interface->attributes}) { + next if $attribute->extendedAttributes->{ForwardDeclareInHeader}; + next if IsJSBuiltin($interface, $attribute); - # - Add all constants - if (!$interface->extendedAttributes->{"NoInterfaceObject"}) { - my $hashSize = $numConstants; + my $conditionalString = $codeGenerator->GenerateConditionalString($attribute); + push(@implContent, "#if ${conditionalString}\n") if $conditionalString; + my $getter = GetAttributeGetterName($interface, $className, $attribute); + push(@implContent, "JSC::EncodedJSValue ${getter}(JSC::ExecState*, JSC::EncodedJSValue, JSC::PropertyName);\n"); + if (!IsReadonly($attribute)) { + my $setter = GetAttributeSetterName($interface, $className, $attribute); + push(@implContent, "bool ${setter}(JSC::ExecState*, JSC::EncodedJSValue, JSC::EncodedJSValue);\n"); + } + push(@implContent, "#endif\n") if $conditionalString; + } + + if (NeedsConstructorProperty($interface)) { + my $getter = "js" . $interfaceName . "Constructor"; + push(@implContent, "JSC::EncodedJSValue ${getter}(JSC::ExecState*, JSC::EncodedJSValue, JSC::PropertyName);\n"); + } + + my $constructorFunctionName = "setJS" . $interfaceName . "Constructor"; + push(@implContent, "bool ${constructorFunctionName}(JSC::ExecState*, JSC::EncodedJSValue, JSC::EncodedJSValue);\n"); + + push(@implContent, "\n"); + } + + if ($numFunctions > 0) { + foreach my $function (@functions) { + next unless $function->extendedAttributes->{DOMJIT}; + $implIncludes{"DOMJITIDLTypeFilter.h"} = 1; + $implIncludes{"DOMJITCheckDOM.h"} = 1; + $implIncludes{"DOMJITAbstractHeapRepository.h"} = 1; + + my $isOverloaded = $function->{overloads} && @{$function->{overloads}} > 1; + die "Overloads is not supported in DOMJIT" if $isOverloaded; + die "Currently ReadDOM value is only allowed" unless $codeGenerator->ExtendedAttributeContains($function->extendedAttributes->{DOMJIT}, "ReadDOM"); + + my $interfaceName = $interface->type->name; + my $functionName = GetFunctionName($interface, $className, $function); + my $unsafeFunctionName = "unsafe" . $codeGenerator->WK_ucfirst($functionName); + my $domJITSignatureName = "DOMJITSignatureFor" . $interface->type->name . $codeGenerator->WK_ucfirst($function->name); + my $classInfo = "JS" . $interface->type->name . "::info()"; + my $resultType = GetResultTypeFilter($interface, $function->type); + my $domJITSignatureHeader = "static const JSC::DOMJIT::Signature ${domJITSignatureName}((uintptr_t)${unsafeFunctionName},"; + my $domJITSignatureFooter = "$classInfo, JSC::DOMJIT::Effect::forRead(DOMJIT::AbstractHeapRepository::DOM), ${resultType}"; + foreach my $argument (@{$function->arguments}) { + my $type = $argument->type; + my $argumentType = GetArgumentTypeFilter($interface, $type); + $domJITSignatureFooter .= ", ${argumentType}"; + } + $domJITSignatureFooter .= ");"; + my $conditionalString = $codeGenerator->GenerateConditionalString($function); + push(@implContent, "#if ${conditionalString}\n") if $conditionalString; + push(@implContent, "#if ENABLE(JIT)\n"); + push(@implContent, "$domJITSignatureHeader DOMJIT::checkDOM<$interfaceName>, $domJITSignatureFooter\n"); + push(@implContent, "#else\n"); + push(@implContent, "$domJITSignatureHeader nullptr, $domJITSignatureFooter\n"); + push(@implContent, "#endif\n"); + push(@implContent, "#endif\n") if $conditionalString; + push(@implContent, "\n"); + } + } + + GeneratePrototypeDeclaration(\@implContent, $className, $interface) if !HeaderNeedsPrototypeDeclaration($interface); + + GenerateConstructorDeclaration(\@implContent, $className, $interface) if NeedsConstructorProperty($interface); + + my @hashKeys = (); + my @hashValue1 = (); + my @hashValue2 = (); + my @hashSpecials = (); + my %conditionals = (); + my $hashName = $className . "Table"; + my @runtimeEnabledFunctions = (); + my @runtimeEnabledAttributes = (); + + # Generate hash table for properties on the instance. + my $numInstanceProperties = GeneratePropertiesHashTable($object, $interface, 1, + \@hashKeys, \@hashSpecials, + \@hashValue1, \@hashValue2, + \%conditionals, \@runtimeEnabledFunctions, \@runtimeEnabledAttributes); + + $object->GenerateHashTable($hashName, $numInstanceProperties, + \@hashKeys, \@hashSpecials, + \@hashValue1, \@hashValue2, + \%conditionals, 0) if $numInstanceProperties > 0; + + # - Add all interface object (aka constructor) properties (constants, static attributes, static operations). + if (NeedsConstructorProperty($interface)) { + my $hashSize = 0; my $hashName = $className . "ConstructorTable"; my @hashKeys = (); @@ -1601,855 +3185,762 @@ sub GenerateImplementation my @hashSpecials = (); my %conditionals = (); - # FIXME: we should not need a function for every constant. + my $needsConstructorTable = 0; + foreach my $constant (@{$interface->constants}) { my $name = $constant->name; push(@hashKeys, $name); - my $getter = "js" . $interfaceName . $codeGenerator->WK_ucfirst($name); - push(@hashValue1, $getter); + push(@hashValue1, $constant->value); push(@hashValue2, "0"); - push(@hashSpecials, "DontDelete | ReadOnly"); + push(@hashSpecials, "DontDelete | ReadOnly | ConstantInteger"); - my $implementedBy = $constant->extendedAttributes->{"ImplementedBy"}; - if ($implementedBy) { - $implIncludes{"${implementedBy}.h"} = 1; - } - my $conditional = $constant->extendedAttributes->{"Conditional"}; - if ($conditional) { - $conditionals{$name} = $conditional; - } + my $implementedBy = $constant->extendedAttributes->{ImplementedBy}; + $implIncludes{"${implementedBy}.h"} = 1 if $implementedBy; + + my $conditional = $constant->extendedAttributes->{Conditional}; + $conditionals{$name} = $conditional if $conditional; + + $hashSize++; } foreach my $attribute (@{$interface->attributes}) { next unless ($attribute->isStatic); - my $name = $attribute->signature->name; + my $name = $attribute->name; push(@hashKeys, $name); my @specials = (); - push(@specials, "DontDelete") unless $attribute->signature->extendedAttributes->{"Deletable"}; + push(@specials, "DontDelete") if IsUnforgeable($interface, $attribute); push(@specials, "ReadOnly") if IsReadonly($attribute); + push(@specials, "DOMJITAttribute") if $attribute->extendedAttributes->{"DOMJIT"}; my $special = (@specials > 0) ? join(" | ", @specials) : "0"; push(@hashSpecials, $special); - my $getter = GetAttributeGetterName($interfaceName, $className, $attribute); - push(@hashValue1, $getter); - - if (IsReadonly($attribute)) { + if ($attribute->extendedAttributes->{"DOMJIT"}) { + push(@hashValue1, "domJITGetterSetterFor" . $interface->type->name . $codeGenerator->WK_ucfirst($attribute->name)); push(@hashValue2, "0"); } else { - my $setter = GetAttributeSetterName($interfaceName, $className, $attribute); - push(@hashValue2, $setter); - } + my $getter = GetAttributeGetterName($interface, $className, $attribute); + push(@hashValue1, $getter); - my $conditional = $attribute->signature->extendedAttributes->{"Conditional"}; - if ($conditional) { - $conditionals{$name} = $conditional; + if (IsReadonly($attribute)) { + push(@hashValue2, "0"); + } else { + my $setter = GetAttributeSetterName($interface, $className, $attribute); + push(@hashValue2, $setter); + } } + + my $conditional = $attribute->extendedAttributes->{Conditional}; + $conditionals{$name} = $conditional if $conditional; + + $hashSize++; } foreach my $function (@{$interface->functions}) { next unless ($function->isStatic); next if $function->{overloadIndex} && $function->{overloadIndex} > 1; - my $name = $function->signature->name; + my $name = $function->name; push(@hashKeys, $name); - my $functionName = GetFunctionName($className, $function); + my $functionName = GetFunctionName($interface, $className, $function); push(@hashValue1, $functionName); my $functionLength = GetFunctionLength($function); - push(@hashValue2, $functionLength); + if ($function->extendedAttributes->{DOMJIT}) { + push(@hashValue2, "DOMJITFunctionFor" . $interface->type->name . $codeGenerator->WK_ucfirst($function->name)); + } else { + push(@hashValue2, $functionLength); + } - my @specials = (); - push(@specials, "DontDelete") if $interface->extendedAttributes->{"OperationsNotDeletable"} - || $function->signature->extendedAttributes->{"NotDeletable"}; - push(@specials, "DontEnum") if $function->signature->extendedAttributes->{"NotEnumerable"}; - push(@specials, "JSC::Function"); - my $special = (@specials > 0) ? join(" | ", @specials) : "0"; - push(@hashSpecials, $special); + push(@hashSpecials, ComputeFunctionSpecial($interface, $function)); - my $conditional = $function->signature->extendedAttributes->{"Conditional"}; - if ($conditional) { - $conditionals{$name} = $conditional; - } + my $conditional = $function->extendedAttributes->{Conditional}; + $conditionals{$name} = $conditional if $conditional; + + $hashSize++; } $object->GenerateHashTable($hashName, $hashSize, \@hashKeys, \@hashSpecials, \@hashValue1, \@hashValue2, - \%conditionals); + \%conditionals, 1) if $hashSize > 0; push(@implContent, $codeGenerator->GenerateCompileTimeCheckForEnumsIfNeeded($interface)); my $protoClassName = "${className}Prototype"; - GenerateConstructorDefinitions(\@implContent, $className, $protoClassName, $interfaceName, $visibleInterfaceName, $interface); - if ($interface->extendedAttributes->{"NamedConstructor"}) { - GenerateConstructorDefinitions(\@implContent, $className, $protoClassName, $interfaceName, $interface->extendedAttributes->{"NamedConstructor"}, $interface, "GeneratingNamedConstructor"); - } + GenerateConstructorDefinitions(\@implContent, $className, $protoClassName, $visibleInterfaceName, $interface); + + my $namedConstructor = $interface->extendedAttributes->{NamedConstructor}; + GenerateConstructorDefinitions(\@implContent, $className, $protoClassName, $namedConstructor, $interface, "GeneratingNamedConstructor") if $namedConstructor; } # - Add functions and constants to a hashtable definition - my $hashSize = $numFunctions + $numConstants; - my $hashName = $className . "PrototypeTable"; - my @hashKeys = (); - my @hashValue1 = (); - my @hashValue2 = (); - my @hashSpecials = (); - my %conditionals = (); + $hashName = $className . "PrototypeTable"; + + @hashKeys = (); + @hashValue1 = (); + @hashValue2 = (); + @hashSpecials = (); + %conditionals = (); + @runtimeEnabledFunctions = (); + @runtimeEnabledAttributes = (); + + # Generate hash table for properties on the prototype. + my $numPrototypeProperties = GeneratePropertiesHashTable($object, $interface, 0, + \@hashKeys, \@hashSpecials, + \@hashValue1, \@hashValue2, + \%conditionals, \@runtimeEnabledFunctions, \@runtimeEnabledAttributes); + my $hashSize = $numPrototypeProperties; - # FIXME: we should not need a function for every constant. foreach my $constant (@{$interface->constants}) { my $name = $constant->name; - push(@hashKeys, $name); - my $getter = "js" . $interfaceName . $codeGenerator->WK_ucfirst($name); - push(@hashValue1, $getter); - push(@hashValue2, "0"); - push(@hashSpecials, "DontDelete | ReadOnly"); - - my $conditional = $constant->extendedAttributes->{"Conditional"}; - if ($conditional) { - $conditionals{$name} = $conditional; - } - } - foreach my $function (@{$interface->functions}) { - next if ($function->isStatic); - next if $function->{overloadIndex} && $function->{overloadIndex} > 1; - my $name = $function->signature->name; push(@hashKeys, $name); + push(@hashValue1, $constant->value); + push(@hashValue2, "0"); + push(@hashSpecials, "DontDelete | ReadOnly | ConstantInteger"); - my $functionName = GetFunctionName($className, $function); - push(@hashValue1, $functionName); - - my $functionLength = GetFunctionLength($function); - push(@hashValue2, $functionLength); - - my @specials = (); - push(@specials, "DontDelete") if $interface->extendedAttributes->{"OperationsNotDeletable"} - || $function->signature->extendedAttributes->{"NotDeletable"}; - push(@specials, "DontEnum") if $function->signature->extendedAttributes->{"NotEnumerable"}; - push(@specials, "JSC::Function"); - my $special = (@specials > 0) ? join(" | ", @specials) : "0"; - push(@hashSpecials, $special); + my $conditional = $constant->extendedAttributes->{Conditional}; + $conditionals{$name} = $conditional if $conditional; - my $conditional = $function->signature->extendedAttributes->{"Conditional"}; - if ($conditional) { - $conditionals{$name} = $conditional; - } + $hashSize++; } + my $justGenerateValueArray = !IsDOMGlobalObject($interface); + $object->GenerateHashTable($hashName, $hashSize, \@hashKeys, \@hashSpecials, \@hashValue1, \@hashValue2, - \%conditionals); + \%conditionals, $justGenerateValueArray); - if ($interface->extendedAttributes->{"JSNoStaticTables"}) { - push(@implContent, "static const HashTable& get${className}PrototypeTable(VM& vm)\n"); - push(@implContent, "{\n"); - push(@implContent, " return getHashTableForGlobalData(vm, ${className}PrototypeTable);\n"); - push(@implContent, "}\n\n"); - push(@implContent, "const ClassInfo ${className}Prototype::s_info = { \"${visibleInterfaceName}Prototype\", &Base::s_info, 0, get${className}PrototypeTable, CREATE_METHOD_TABLE(${className}Prototype) };\n\n"); + if ($justGenerateValueArray) { + push(@implContent, "const ClassInfo ${className}Prototype::s_info = { \"${visibleInterfaceName}Prototype\", &Base::s_info, 0, CREATE_METHOD_TABLE(${className}Prototype) };\n\n"); } else { - push(@implContent, "const ClassInfo ${className}Prototype::s_info = { \"${visibleInterfaceName}Prototype\", &Base::s_info, &${className}PrototypeTable, 0, CREATE_METHOD_TABLE(${className}Prototype) };\n\n"); - } - unless (IsDOMGlobalObject($interface)) { - push(@implContent, "JSObject* ${className}Prototype::self(VM& vm, JSGlobalObject* globalObject)\n"); - push(@implContent, "{\n"); - push(@implContent, " return getDOMPrototype<${className}>(vm, globalObject);\n"); - push(@implContent, "}\n\n"); + push(@implContent, "const ClassInfo ${className}Prototype::s_info = { \"${visibleInterfaceName}Prototype\", &Base::s_info, &${className}PrototypeTable, CREATE_METHOD_TABLE(${className}Prototype) };\n\n"); } - if (PrototypeOverridesGetOwnPropertySlot($interface)) { - push(@implContent, "bool ${className}Prototype::getOwnPropertySlot(JSObject* object, ExecState* exec, PropertyName propertyName, PropertySlot& slot)\n"); + if (PrototypeHasStaticPropertyTable($interface) && !IsGlobalOrPrimaryGlobalInterface($interface)) { + push(@implContent, "void ${className}Prototype::finishCreation(VM& vm)\n"); push(@implContent, "{\n"); - push(@implContent, " ${className}Prototype* thisObject = jsCast<${className}Prototype*>(object);\n"); - - if ($numConstants eq 0 && $numFunctions eq 0) { - push(@implContent, " return Base::getOwnPropertySlot(thisObject, exec, propertyName, slot);\n"); - } elsif ($numConstants eq 0) { - push(@implContent, " return getStaticFunctionSlot<JSObject>(exec, " . prototypeHashTableAccessor($interface->extendedAttributes->{"JSNoStaticTables"}, $className) . ", thisObject, propertyName, slot);\n"); - } elsif ($numFunctions eq 0) { - push(@implContent, " return getStaticValueSlot<${className}Prototype, JSObject>(exec, " . prototypeHashTableAccessor($interface->extendedAttributes->{"JSNoStaticTables"}, $className) . ", thisObject, propertyName, slot);\n"); - } else { - push(@implContent, " return getStaticPropertySlot<${className}Prototype, JSObject>(exec, " . prototypeHashTableAccessor($interface->extendedAttributes->{"JSNoStaticTables"}, $className) . ", thisObject, propertyName, slot);\n"); + push(@implContent, " Base::finishCreation(vm);\n"); + push(@implContent, " reifyStaticProperties(vm, ${className}PrototypeTableValues, *this);\n"); + + my @runtimeEnabledProperties = @runtimeEnabledFunctions; + push(@runtimeEnabledProperties, @runtimeEnabledAttributes); + foreach my $functionOrAttribute (@runtimeEnabledProperties) { + my $conditionalString = $codeGenerator->GenerateConditionalString($functionOrAttribute); + push(@implContent, "#if ${conditionalString}\n") if $conditionalString; + AddToImplIncludes("RuntimeEnabledFeatures.h"); + my $enable_function = GetRuntimeEnableFunctionName($functionOrAttribute); + my $name = $functionOrAttribute->name; + push(@implContent, " if (!${enable_function}()) {\n"); + push(@implContent, " Identifier propertyName = Identifier::fromString(&vm, reinterpret_cast<const LChar*>(\"$name\"), strlen(\"$name\"));\n"); + push(@implContent, " VM::DeletePropertyModeScope scope(vm, VM::DeletePropertyMode::IgnoreConfigurable);\n"); + push(@implContent, " JSObject::deleteProperty(this, globalObject()->globalExec(), propertyName);\n"); + push(@implContent, " }\n"); + push(@implContent, "#endif\n") if $conditionalString; } - push(@implContent, "}\n\n"); - } - if ($interface->extendedAttributes->{"JSCustomNamedGetterOnPrototype"}) { - push(@implContent, "void ${className}Prototype::put(JSCell* cell, ExecState* exec, PropertyName propertyName, JSValue value, PutPropertySlot& slot)\n"); - push(@implContent, "{\n"); - push(@implContent, " ${className}Prototype* thisObject = jsCast<${className}Prototype*>(cell);\n"); - push(@implContent, " if (thisObject->putDelegate(exec, propertyName, value, slot))\n"); - push(@implContent, " return;\n"); - push(@implContent, " Base::put(thisObject, exec, propertyName, value, slot);\n"); + foreach my $function (@{$interface->functions}) { + next unless ($function->extendedAttributes->{PrivateIdentifier}); + AddToImplIncludes("WebCoreJSClientData.h"); + my $conditionalString = $codeGenerator->GenerateConditionalString($function); + push(@implContent, "#if ${conditionalString}\n") if $conditionalString; + push(@implContent, " putDirect(vm, static_cast<JSVMClientData*>(vm.clientData)->builtinNames()." . $function->name . "PrivateName(), JSFunction::create(vm, globalObject(), 0, String(), " . GetFunctionName($interface, $className, $function) . "), ReadOnly | DontEnum);\n"); + push(@implContent, "#endif\n") if $conditionalString; + } + + if (InterfaceNeedsIterator($interface)) { + if (IsKeyValueIterableInterface($interface)) { + my $functionName = GetFunctionName($interface, $className, @{$interface->iterable->functions}[0]); + push(@implContent, " putDirect(vm, vm.propertyNames->iteratorSymbol, JSFunction::create(vm, globalObject(), 0, ASCIILiteral(\"[Symbol.Iterator]\"), $functionName), DontEnum);\n"); + } else { + AddToImplIncludes("<builtins/BuiltinNames.h>"); + push(@implContent, " putDirect(vm, vm.propertyNames->iteratorSymbol, globalObject()->arrayPrototype()->getDirect(vm, vm.propertyNames->builtinNames().valuesPrivateName()), DontEnum);\n"); + } + } + push(@implContent, " addValueIterableMethods(*globalObject(), *this);\n") if $interface->iterable and !IsKeyValueIterableInterface($interface); + + addUnscopableProperties($interface); + push(@implContent, "}\n\n"); } - # - Initialize static ClassInfo object - if ($numAttributes > 0 && $interface->extendedAttributes->{"JSNoStaticTables"}) { - push(@implContent, "static const HashTable& get${className}Table(VM& vm)\n"); + if ($interface->extendedAttributes->{JSCustomNamedGetterOnPrototype}) { + push(@implContent, "bool ${className}Prototype::put(JSCell* cell, ExecState* state, PropertyName propertyName, JSValue value, PutPropertySlot& slot)\n"); push(@implContent, "{\n"); - push(@implContent, " return getHashTableForGlobalData(vm, ${className}Table);\n"); + push(@implContent, " auto* thisObject = jsCast<${className}Prototype*>(cell);\n"); + push(@implContent, " bool putResult = false;\n"); + push(@implContent, " if (thisObject->putDelegate(state, propertyName, value, slot, putResult))\n"); + push(@implContent, " return putResult;\n"); + push(@implContent, " return Base::put(thisObject, state, propertyName, value, slot);\n"); push(@implContent, "}\n\n"); } + # - Initialize static ClassInfo object push(@implContent, "const ClassInfo $className" . "::s_info = { \"${visibleInterfaceName}\", &Base::s_info, "); - if ($numAttributes > 0 && !$interface->extendedAttributes->{"JSNoStaticTables"}) { + if ($numInstanceProperties > 0) { push(@implContent, "&${className}Table"); } else { push(@implContent, "0"); } - if ($numAttributes > 0 && $interface->extendedAttributes->{"JSNoStaticTables"}) { - push(@implContent, ", get${className}Table "); - } else { - push(@implContent, ", 0 "); - } push(@implContent, ", CREATE_METHOD_TABLE($className) };\n\n"); - my $implType = $interfaceName; - my ($svgPropertyType, $svgListPropertyType, $svgNativeType) = GetSVGPropertyTypes($implType); - $implType = $svgNativeType if $svgNativeType; - - my $svgPropertyOrListPropertyType; - $svgPropertyOrListPropertyType = $svgPropertyType if $svgPropertyType; - $svgPropertyOrListPropertyType = $svgListPropertyType if $svgListPropertyType; - # Constructor if ($interfaceName eq "DOMWindow") { - AddIncludesForTypeInImpl("JSDOMWindowShell"); - push(@implContent, "${className}::$className(VM& vm, Structure* structure, PassRefPtr<$implType> impl, JSDOMWindowShell* shell)\n"); - push(@implContent, " : $parentClassName(vm, structure, impl, shell)\n"); + AddIncludesForImplementationTypeInImpl("JSDOMWindowShell"); + push(@implContent, "${className}::$className(VM& vm, Structure* structure, Ref<$implType>&& impl, JSDOMWindowShell* shell)\n"); + push(@implContent, " : $parentClassName(vm, structure, WTFMove(impl), shell)\n"); push(@implContent, "{\n"); push(@implContent, "}\n\n"); } elsif ($codeGenerator->InheritsInterface($interface, "WorkerGlobalScope")) { - AddIncludesForTypeInImpl($interfaceName); - push(@implContent, "${className}::$className(VM& vm, Structure* structure, PassRefPtr<$implType> impl)\n"); - push(@implContent, " : $parentClassName(vm, structure, impl)\n"); + AddIncludesForImplementationTypeInImpl($interfaceName); + push(@implContent, "${className}::$className(VM& vm, Structure* structure, Ref<$implType>&& impl)\n"); + push(@implContent, " : $parentClassName(vm, structure, WTFMove(impl))\n"); push(@implContent, "{\n"); push(@implContent, "}\n\n"); + } elsif (!NeedsImplementationClass($interface)) { + push(@implContent, "${className}::$className(Structure* structure, JSDOMGlobalObject& globalObject)\n"); + push(@implContent, " : $parentClassName(structure, globalObject) { }\n\n"); } else { - push(@implContent, "${className}::$className(Structure* structure, JSDOMGlobalObject* globalObject, PassRefPtr<$implType> impl)\n"); - if ($hasParent) { - push(@implContent, " : $parentClassName(structure, globalObject, impl)\n"); - } else { - push(@implContent, " : $parentClassName(structure, globalObject)\n"); - push(@implContent, " , m_impl(impl.leakRef())\n"); - } + push(@implContent, "${className}::$className(Structure* structure, JSDOMGlobalObject& globalObject, Ref<$implType>&& impl)\n"); + push(@implContent, " : $parentClassName(structure, globalObject, WTFMove(impl))\n"); push(@implContent, "{\n"); push(@implContent, "}\n\n"); + } + if ($interfaceName eq "DOMWindow") { + push(@implContent, "void ${className}::finishCreation(VM& vm, JSDOMWindowShell* shell)\n"); + push(@implContent, "{\n"); + push(@implContent, " Base::finishCreation(vm, shell);\n\n"); + } elsif ($codeGenerator->InheritsInterface($interface, "WorkerGlobalScope")) { + push(@implContent, "void ${className}::finishCreation(VM& vm, JSProxy* proxy)\n"); + push(@implContent, "{\n"); + push(@implContent, " Base::finishCreation(vm, proxy);\n\n"); + } else { push(@implContent, "void ${className}::finishCreation(VM& vm)\n"); push(@implContent, "{\n"); push(@implContent, " Base::finishCreation(vm);\n"); - push(@implContent, " ASSERT(inherits(info()));\n"); - push(@implContent, "}\n\n"); + push(@implContent, " ASSERT(inherits(vm, info()));\n\n"); + } + + if ($interfaceName eq "Location") { + push(@implContent, " putDirect(vm, vm.propertyNames->valueOf, globalObject()->objectProtoValueOfFunction(), DontDelete | ReadOnly | DontEnum);\n"); + push(@implContent, " putDirect(vm, vm.propertyNames->toPrimitiveSymbol, jsUndefined(), DontDelete | ReadOnly | DontEnum);\n"); } - unless (IsDOMGlobalObject($interface)) { + # Support for RuntimeEnabled attributes on instances. + foreach my $attribute (@{$interface->attributes}) { + next unless NeedsRuntimeCheck($attribute); + next unless AttributeShouldBeOnInstance($interface, $attribute); + + my $conditionalString = $codeGenerator->GenerateConditionalString($attribute); + push(@implContent, "#if ${conditionalString}\n") if $conditionalString; + my $enable_function = GetRuntimeEnableFunctionName($attribute); + my $attributeName = $attribute->name; + push(@implContent, " if (${enable_function}()) {\n"); + my $getter = GetAttributeGetterName($interface, $className, $attribute); + my $setter = IsReadonly($attribute) ? "nullptr" : GetAttributeSetterName($interface, $className, $attribute); + push(@implContent, " auto* customGetterSetter = CustomGetterSetter::create(vm, $getter, $setter);\n"); + my $jscAttributes = GetJSCAttributesForAttribute($interface, $attribute); + push(@implContent, " putDirectCustomAccessor(vm, vm.propertyNames->$attributeName, customGetterSetter, attributesForStructure($jscAttributes));\n"); + push(@implContent, " }\n"); + push(@implContent, "#endif\n") if $conditionalString; + } + + # Support PrivateIdentifier attributes on instances. + foreach my $attribute (@{$interface->attributes}) { + next unless $attribute->extendedAttributes->{PrivateIdentifier}; + next unless AttributeShouldBeOnInstance($interface, $attribute); + + AddToImplIncludes("WebCoreJSClientData.h"); + my $conditionalString = $codeGenerator->GenerateConditionalString($attribute); + my $attributeName = $attribute->name; + my $getter = GetAttributeGetterName($interface, $className, $attribute); + + push(@implContent, "#if ${conditionalString}\n") if $conditionalString; + push(@implContent, " putDirectCustomAccessor(vm, static_cast<JSVMClientData*>(vm.clientData)->builtinNames()." . $attributeName . "PrivateName(), CustomGetterSetter::create(vm, $getter, nullptr), attributesForStructure(DontDelete | ReadOnly));\n"); + push(@implContent, "#endif\n") if $conditionalString; + } + + # Support for RuntimeEnabled operations on instances. + foreach my $function (@{$interface->functions}) { + next unless NeedsRuntimeCheck($function); + next unless OperationShouldBeOnInstance($interface, $function); + next if $function->{overloadIndex} && $function->{overloadIndex} > 1; + + my $conditionalString = $codeGenerator->GenerateConditionalString($function); + push(@implContent, "#if ${conditionalString}\n") if $conditionalString; + my $enable_function = GetRuntimeEnableFunctionName($function); + my $functionName = $function->name; + my $implementationFunction = GetFunctionName($interface, $className, $function); + my $functionLength = GetFunctionLength($function); + my $jsAttributes = ComputeFunctionSpecial($interface, $function); + push(@implContent, " if (${enable_function}())\n"); + + my $propertyName = "vm.propertyNames->$functionName"; + $propertyName = "static_cast<JSVMClientData*>(vm.clientData)->builtinNames()." . $functionName . "PrivateName()" if $function->extendedAttributes->{PrivateIdentifier}; + if (IsJSBuiltin($interface, $function)) { + push(@implContent, " putDirectBuiltinFunction(vm, this, $propertyName, $implementationFunction(vm), attributesForStructure($jsAttributes));\n"); + } else { + push(@implContent, " putDirectNativeFunction(vm, this, $propertyName, $functionLength, $implementationFunction, NoIntrinsic, attributesForStructure($jsAttributes));\n"); + } + push(@implContent, "#endif\n") if $conditionalString; + } + push(@implContent, "}\n\n"); + + unless (ShouldUseGlobalObjectPrototype($interface)) { push(@implContent, "JSObject* ${className}::createPrototype(VM& vm, JSGlobalObject* globalObject)\n"); push(@implContent, "{\n"); - if ($hasParent && $parentClassName ne "JSC::DOMNodeFilter") { - push(@implContent, " return ${className}Prototype::create(vm, globalObject, ${className}Prototype::createStructure(vm, globalObject, ${parentClassName}Prototype::self(vm, globalObject)));\n"); + if ($interface->parentType) { + my $parentClassNameForPrototype = "JS" . $interface->parentType->name; + push(@implContent, " return ${className}Prototype::create(vm, globalObject, ${className}Prototype::createStructure(vm, globalObject, ${parentClassNameForPrototype}::prototype(vm, globalObject)));\n"); } else { my $prototype = $interface->isException ? "errorPrototype" : "objectPrototype"; push(@implContent, " return ${className}Prototype::create(vm, globalObject, ${className}Prototype::createStructure(vm, globalObject, globalObject->${prototype}()));\n"); } push(@implContent, "}\n\n"); + + push(@implContent, "JSObject* ${className}::prototype(VM& vm, JSGlobalObject* globalObject)\n"); + push(@implContent, "{\n"); + push(@implContent, " return getDOMPrototype<${className}>(vm, globalObject);\n"); + push(@implContent, "}\n\n"); } if (!$hasParent) { - # FIXME: This destroy function should not be necessary, as - # a finalizer should be called for each DOM object wrapper. - # However, that seems not to be the case, so this has been - # added back to avoid leaking while we figure out why the - # finalizers are not always getting called. The work tracking - # the finalizer issue is being tracked in http://webkit.org/b/75451 push(@implContent, "void ${className}::destroy(JSC::JSCell* cell)\n"); push(@implContent, "{\n"); push(@implContent, " ${className}* thisObject = static_cast<${className}*>(cell);\n"); push(@implContent, " thisObject->${className}::~${className}();\n"); push(@implContent, "}\n\n"); - - # We also need a destructor for the allocateCell to work properly with the destructor-free part of the heap. - # Otherwise, these destroy functions/destructors won't get called. - push(@implContent, "${className}::~${className}()\n"); - push(@implContent, "{\n"); - push(@implContent, " releaseImplIfNotNull();\n"); - push(@implContent, "}\n\n"); } my $hasGetter = InstanceOverridesGetOwnPropertySlot($interface); # Attributes if ($hasGetter) { - if (!$interface->extendedAttributes->{"CustomGetOwnPropertySlot"}) { - push(@implContent, "bool ${className}::getOwnPropertySlot(JSObject* object, ExecState* exec, PropertyName propertyName, PropertySlot& slot)\n"); - push(@implContent, "{\n"); - push(@implContent, " ${className}* thisObject = jsCast<${className}*>(object);\n"); - push(@implContent, " ASSERT_GC_OBJECT_INHERITS(thisObject, info());\n"); - push(@implContent, GenerateGetOwnPropertySlotBody($interface, $interfaceName, $className, $numAttributes > 0, 0)); - push(@implContent, "}\n\n"); + if (!$interface->extendedAttributes->{CustomGetOwnPropertySlot}) { + push(@implContent, GenerateGetOwnPropertySlotBody($interface, $className, $indexedGetterFunction, $namedGetterFunction)); } if ($indexedGetterFunction || $namedGetterFunction - || $interface->extendedAttributes->{"CustomNamedGetter"} - || $interface->extendedAttributes->{"JSCustomGetOwnPropertySlotAndDescriptor"}) { - push(@implContent, "bool ${className}::getOwnPropertySlotByIndex(JSObject* object, ExecState* exec, unsigned index, PropertySlot& slot)\n"); - push(@implContent, "{\n"); - push(@implContent, " ${className}* thisObject = jsCast<${className}*>(object);\n"); - push(@implContent, " ASSERT_GC_OBJECT_INHERITS(thisObject, info());\n"); + || $interface->extendedAttributes->{CustomNamedGetter} + || $interface->extendedAttributes->{JSCustomGetOwnPropertySlotAndDescriptor}) { + push(@implContent, GenerateGetOwnPropertySlotBodyByIndex($interface, $className, $indexedGetterFunction, $namedGetterFunction)); + } - # Sink the int-to-string conversion that happens when we create a PropertyName - # to the point where we actually need it. - my $generatedPropertyName = 0; - my $propertyNameGeneration = sub { - if ($generatedPropertyName) { - return; - } - push(@implContent, " PropertyName propertyName = Identifier::from(exec, index);\n"); - $generatedPropertyName = 1; - }; + } - if ($indexedGetterFunction) { - if ($indexedGetterFunction->signature->type eq "DOMString") { - push(@implContent, " if (index <= MAX_ARRAY_INDEX) {\n"); - } else { - push(@implContent, " if (index < thisObject->impl().length()) {\n"); - } - # Assume that if there's a setter, the index will be writable - if ($interface->extendedAttributes->{"CustomIndexedSetter"}) { - push(@implContent, " unsigned attributes = DontDelete;\n"); - } else { - push(@implContent, " unsigned attributes = DontDelete | ReadOnly;\n"); - } - if ($hasNumericIndexedGetter) { - push(@implContent, " slot.setValue(thisObject, attributes, thisObject->getByIndex(exec, index));\n"); - } else { - push(@implContent, " slot.setCustomIndex(thisObject, attributes, index, thisObject->indexGetter);\n"); - } - push(@implContent, " return true;\n"); - push(@implContent, " }\n"); - } - if ($namedGetterFunction || $interface->extendedAttributes->{"CustomNamedGetter"}) { - &$propertyNameGeneration(); - push(@implContent, " if (canGetItemsForName(exec, &thisObject->impl(), propertyName)) {\n"); - push(@implContent, " slot.setCustom(thisObject, ReadOnly | DontDelete | DontEnum, thisObject->nameGetter);\n"); - push(@implContent, " return true;\n"); - push(@implContent, " }\n"); - $implIncludes{"wtf/text/AtomicString.h"} = 1; - } + if (($indexedGetterFunction || $namedGetterFunction) && !$interface->extendedAttributes->{CustomEnumerateProperty}) { + push(@implContent, GenerateGetOwnPropertyNames($interface, $className, $indexedGetterFunction, $namedGetterFunction)); + } - if ($interface->extendedAttributes->{"JSCustomGetOwnPropertySlotAndDescriptor"}) { - &$propertyNameGeneration(); - push(@implContent, " if (thisObject->getOwnPropertySlotDelegate(exec, propertyName, slot))\n"); - push(@implContent, " return true;\n"); + my $namedSetterFunction = GetNamedSetterFunction($interface); + my $indexedSetterFunction = GetIndexedSetterFunction($interface); + + my $hasSetter = InstanceOverridesPut($interface); + if ($hasSetter) { + if (!$interface->extendedAttributes->{CustomPutFunction}) { + push(@implContent, GeneratePut($interface, $className, $indexedSetterFunction, $namedSetterFunction)); + + if ($interface->extendedAttributes->{CustomIndexedSetter} || $interface->extendedAttributes->{CustomNamedSetter}) { + push(@implContent, GeneratePutByIndex($interface, $className, $indexedSetterFunction, $namedSetterFunction)); } + } + } - push(@implContent, " return Base::getOwnPropertySlotByIndex(thisObject, exec, index, slot);\n"); + if ($numAttributes > 0) { + my $castingFunction = $interface->extendedAttributes->{"CustomProxyToJSObject"} ? "to${className}" : GetCastingHelperForThisObject($interface); + # FIXME: Remove ImplicitThis keyword as it is no longer defined by WebIDL spec and is only used in DOMWindow. + if ($interface->extendedAttributes->{"ImplicitThis"}) { + push(@implContent, "template<> inline ${className}* BindingCaller<${className}>::castForAttribute(ExecState& state, EncodedJSValue thisValue)\n"); + push(@implContent, "{\n"); + push(@implContent, " auto decodedThisValue = JSValue::decode(thisValue);\n"); + push(@implContent, " if (decodedThisValue.isUndefinedOrNull())\n"); + push(@implContent, " decodedThisValue = state.thisValue().toThis(&state, NotStrictMode);\n"); + push(@implContent, " return $castingFunction(state.vm(), decodedThisValue);"); + push(@implContent, "}\n\n"); + } else { + push(@implContent, "template<> inline ${className}* BindingCaller<${className}>::castForAttribute(ExecState& state, EncodedJSValue thisValue)\n"); + push(@implContent, "{\n"); + push(@implContent, " return $castingFunction(state.vm(), JSValue::decode(thisValue));\n"); push(@implContent, "}\n\n"); } + } + if ($numFunctions > 0 && $interfaceName ne "EventTarget") { + # FIXME: Make consistent castForAttibute and castForOperation in case of CustomProxyToJSObject. + my $castingFunction = $interface->extendedAttributes->{"CustomProxyToJSObject"} ? "to${className}" : GetCastingHelperForThisObject($interface); + my $thisValue = $interface->extendedAttributes->{"CustomProxyToJSObject"} ? "state.thisValue().toThis(&state, NotStrictMode)" : "state.thisValue()"; + push(@implContent, "template<> inline ${className}* BindingCaller<${className}>::castForOperation(ExecState& state)\n"); + push(@implContent, "{\n"); + push(@implContent, " return $castingFunction(state.vm(), $thisValue);\n"); + push(@implContent, "}\n\n"); } + + $numAttributes = $numAttributes + 1 if NeedsConstructorProperty($interface); if ($numAttributes > 0) { foreach my $attribute (@{$interface->attributes}) { - my $name = $attribute->signature->name; - my $type = $attribute->signature->type; - my $isNullable = $attribute->signature->isNullable; - $codeGenerator->AssertNotSequenceType($type); - my $getFunctionName = GetAttributeGetterName($interfaceName, $className, $attribute); - my $implGetterFunctionName = $codeGenerator->WK_lcfirst($attribute->signature->extendedAttributes->{"ImplementedAs"} || $name); - - my $attributeConditionalString = $codeGenerator->GenerateConditionalString($attribute->signature); - push(@implContent, "#if ${attributeConditionalString}\n") if $attributeConditionalString; + next if IsJSBuiltin($interface, $attribute); - push(@implContent, "EncodedJSValue ${getFunctionName}(ExecState* exec, EncodedJSValue slotBase, EncodedJSValue thisValue, PropertyName)\n"); - push(@implContent, "{\n"); + my $name = $attribute->name; + my $type = $attribute->type; + my $getFunctionName = GetAttributeGetterName($interface, $className, $attribute); + my $implGetterFunctionName = $codeGenerator->WK_lcfirst($attribute->extendedAttributes->{ImplementedAs} || $name); - if (!$attribute->isStatic || $attribute->signature->type =~ /Constructor$/) { - if ($interfaceName eq "DOMWindow") { - push(@implContent, " ${className}* castedThis = jsCast<$className*>(JSValue::decode(slotBase));\n"); - push(@implContent, " UNUSED_PARAM(thisValue);\n"); - } else { - push(@implContent, " ${className}* castedThis = jsDynamicCast<$className*>(JSValue::decode(thisValue));\n"); - push(@implContent, " UNUSED_PARAM(slotBase);\n"); - push(@implContent, " if (!castedThis)\n"); - push(@implContent, " return throwVMTypeError(exec);\n"); + my $attributeConditionalString = $codeGenerator->GenerateConditionalString($attribute); + push(@implContent, "#if ${attributeConditionalString}\n") if $attributeConditionalString; + + if (!$attribute->isStatic || $codeGenerator->IsConstructorType($type)) { + my $templateParameters = "${getFunctionName}Getter"; + if ($attribute->extendedAttributes->{LenientThis}) { + $templateParameters .= ", CastedThisErrorBehavior::ReturnEarly"; + } elsif (IsReturningPromise($attribute)) { + $templateParameters .= ", CastedThisErrorBehavior::RejectPromise"; } + + push(@implContent, "static inline JSValue ${getFunctionName}Getter(ExecState&, ${className}&, ThrowScope& throwScope);\n\n"); + + push(@implContent, "EncodedJSValue ${getFunctionName}(ExecState* state, EncodedJSValue thisValue, PropertyName)\n"); + push(@implContent, "{\n"); + push(@implContent, " return BindingCaller<${className}>::attribute<${templateParameters}>(state, thisValue, \"$name\");\n"); + push(@implContent, "}\n\n"); + + push(@implContent, "static inline JSValue ${getFunctionName}Getter(ExecState& state, ${className}& thisObject, ThrowScope& throwScope)\n"); + push(@implContent, "{\n"); + push(@implContent, " UNUSED_PARAM(throwScope);\n"); } else { - push(@implContent, " UNUSED_PARAM(thisValue);\n"); - push(@implContent, " UNUSED_PARAM(slotBase);\n"); + push(@implContent, "static inline JSValue ${getFunctionName}Getter(ExecState&);\n\n"); + + push(@implContent, "EncodedJSValue ${getFunctionName}(ExecState* state, EncodedJSValue, PropertyName)\n"); + push(@implContent, "{\n"); + push(@implContent, " ASSERT(state);\n"); + push(@implContent, " return JSValue::encode(${getFunctionName}Getter(*state));\n"); + push(@implContent, "}\n\n"); + + push(@implContent, "static inline JSValue ${getFunctionName}Getter(ExecState& state)\n"); + push(@implContent, "{\n"); } + push(@implContent, " UNUSED_PARAM(state);\n"); # Global constructors can be disabled at runtime. - if ($attribute->signature->type =~ /Constructor$/) { - if ($attribute->signature->extendedAttributes->{"EnabledAtRuntime"}) { - AddToImplIncludes("RuntimeEnabledFeatures.h"); - my $enable_function = GetRuntimeEnableFunctionName($attribute->signature); - push(@implContent, " if (!${enable_function}())\n"); - push(@implContent, " return JSValue::encode(jsUndefined());\n"); - } elsif ($attribute->signature->extendedAttributes->{"EnabledBySetting"}) { + if ($codeGenerator->IsConstructorType($type)) { + if ($attribute->extendedAttributes->{EnabledBySetting}) { AddToImplIncludes("Frame.h"); AddToImplIncludes("Settings.h"); - my $enable_function = ToMethodName($attribute->signature->extendedAttributes->{"EnabledBySetting"}) . "Enabled"; - push(@implContent, " if (!castedThis->impl().frame())\n"); - push(@implContent, " return JSValue::encode(jsUndefined());\n"); - push(@implContent, " Settings& settings = castedThis->impl().frame()->settings();\n"); + my $enable_function = ToMethodName($attribute->extendedAttributes->{EnabledBySetting}) . "Enabled"; + push(@implContent, " if (UNLIKELY(!thisObject.wrapped().frame()))\n"); + push(@implContent, " return jsUndefined();\n"); + push(@implContent, " Settings& settings = thisObject.wrapped().frame()->settings();\n"); push(@implContent, " if (!settings.$enable_function())\n"); - push(@implContent, " return JSValue::encode(jsUndefined());\n"); + push(@implContent, " return jsUndefined();\n"); } } - if ($attribute->signature->extendedAttributes->{"CachedAttribute"}) { - $needsMarkChildren = 1; - } - - if ($interface->extendedAttributes->{"CheckSecurity"} && - !$attribute->signature->extendedAttributes->{"DoNotCheckSecurity"} && - !$attribute->signature->extendedAttributes->{"DoNotCheckSecurityOnGetter"}) { - push(@implContent, " if (!BindingSecurity::shouldAllowAccessToDOMWindow(exec, castedThis->impl()))\n"); - push(@implContent, " return JSValue::encode(jsUndefined());\n"); - } + $needsVisitChildren = 1 if $attribute->extendedAttributes->{CachedAttribute}; - if (HasCustomGetter($attribute->signature->extendedAttributes)) { - push(@implContent, " return JSValue::encode(castedThis->$implGetterFunctionName(exec));\n"); - } elsif ($attribute->signature->extendedAttributes->{"CheckSecurityForNode"}) { - $implIncludes{"JSDOMBinding.h"} = 1; - push(@implContent, " $interfaceName& impl = castedThis->impl();\n"); - push(@implContent, " return JSValue::encode(shouldAllowAccessToNode(exec, impl." . $attribute->signature->name . "()) ? " . NativeToJSValue($attribute->signature, 0, $interfaceName, "impl.$implGetterFunctionName()", "castedThis") . " : jsNull());\n"); - } elsif ($type eq "EventListener") { - $implIncludes{"EventListener.h"} = 1; - push(@implContent, " UNUSED_PARAM(exec);\n"); - push(@implContent, " $interfaceName& impl = castedThis->impl();\n"); - push(@implContent, " if (EventListener* listener = impl.$implGetterFunctionName()) {\n"); - push(@implContent, " if (const JSEventListener* jsListener = JSEventListener::cast(listener)) {\n"); - if ($interfaceName eq "Document" || $codeGenerator->InheritsInterface($interface, "WorkerGlobalScope")) { - push(@implContent, " if (JSObject* jsFunction = jsListener->jsFunction(&impl))\n"); + if ($interface->extendedAttributes->{CheckSecurity} && + !$attribute->extendedAttributes->{DoNotCheckSecurity} && + !$attribute->extendedAttributes->{DoNotCheckSecurityOnGetter}) { + AddToImplIncludes("JSDOMBindingSecurity.h"); + if ($interfaceName eq "DOMWindow") { + push(@implContent, " if (!BindingSecurity::shouldAllowAccessToDOMWindow(&state, thisObject.wrapped(), ThrowSecurityError))\n"); } else { - push(@implContent, " if (JSObject* jsFunction = jsListener->jsFunction(impl.scriptExecutionContext()))\n"); + push(@implContent, " if (!BindingSecurity::shouldAllowAccessToFrame(&state, thisObject.wrapped().frame(), ThrowSecurityError))\n"); } - push(@implContent, " return JSValue::encode(jsFunction);\n"); - push(@implContent, " }\n"); - push(@implContent, " }\n"); - push(@implContent, " return JSValue::encode(jsNull());\n"); - } elsif ($attribute->signature->type =~ /Constructor$/) { - my $constructorType = $attribute->signature->type; + push(@implContent, " return jsUndefined();\n"); + } + + if (HasCustomGetter($attribute->extendedAttributes)) { + push(@implContent, " return thisObject.$implGetterFunctionName(state);\n"); + } elsif ($type->name eq "EventHandler") { + $implIncludes{"EventNames.h"} = 1; + my $getter = $attribute->extendedAttributes->{WindowEventHandler} ? "windowEventHandlerAttribute" + : $attribute->extendedAttributes->{DocumentEventHandler} ? "documentEventHandlerAttribute" + : "eventHandlerAttribute"; + my $eventName = EventHandlerAttributeEventName($attribute); + push(@implContent, " return $getter(thisObject.wrapped(), $eventName, worldForDOMObject(&thisObject));\n"); + } elsif ($codeGenerator->IsConstructorType($attribute->type)) { + my $constructorType = $attribute->type->name; $constructorType =~ s/Constructor$//; - # When Constructor attribute is used by DOMWindow.idl, it's correct to pass castedThis as the global object - # When JSDOMWrappers have a back-pointer to the globalObject we can pass castedThis->globalObject() + # When Constructor attribute is used by DOMWindow.idl, it's correct to pass thisObject as the global object + # When JSDOMWrappers have a back-pointer to the globalObject we can pass thisObject->globalObject() if ($interfaceName eq "DOMWindow") { my $named = ($constructorType =~ /Named$/) ? "Named" : ""; $constructorType =~ s/Named$//; - push(@implContent, " return JSValue::encode(JS" . $constructorType . "::get${named}Constructor(exec->vm(), castedThis));\n"); + push(@implContent, " return JS" . $constructorType . "::get${named}Constructor(state.vm(), &thisObject);\n"); } else { - AddToImplIncludes("JS" . $constructorType . ".h", $attribute->signature->extendedAttributes->{"Conditional"}); - push(@implContent, " return JSValue::encode(JS" . $constructorType . "::getConstructor(exec->vm(), castedThis->globalObject()));\n"); - } - } elsif (!$attribute->signature->extendedAttributes->{"GetterRaisesException"}) { - push(@implContent, " UNUSED_PARAM(exec);\n") if !$attribute->signature->extendedAttributes->{"CallWith"}; - push(@implContent, " bool isNull = false;\n") if $isNullable; - - my $cacheIndex = 0; - if ($attribute->signature->extendedAttributes->{"CachedAttribute"}) { - $cacheIndex = $currentCachedAttribute; - $currentCachedAttribute++; - push(@implContent, " if (JSValue cachedValue = castedThis->m_" . $attribute->signature->name . ".get())\n"); - push(@implContent, " return JSValue::encode(cachedValue);\n"); + AddToImplIncludes("JS" . $constructorType . ".h", $attribute->extendedAttributes->{Conditional}); + push(@implContent, " return JS" . $constructorType . "::getConstructor(state.vm(), thisObject.globalObject());\n"); } - - my @callWithArgs = GenerateCallWith($attribute->signature->extendedAttributes->{"CallWith"}, \@implContent, "JSValue::encode(jsUndefined())"); - - if ($svgListPropertyType) { - push(@implContent, " JSValue result = " . NativeToJSValue($attribute->signature, 0, $interfaceName, "castedThis->impl().$implGetterFunctionName(" . (join ", ", @callWithArgs) . ")", "castedThis") . ";\n"); - } elsif ($svgPropertyOrListPropertyType) { - push(@implContent, " $svgPropertyOrListPropertyType& impl = castedThis->impl().propertyReference();\n"); - if ($svgPropertyOrListPropertyType eq "float") { # Special case for JSSVGNumber - push(@implContent, " JSValue result = " . NativeToJSValue($attribute->signature, 0, $interfaceName, "impl", "castedThis") . ";\n"); - } else { - push(@implContent, " JSValue result = " . NativeToJSValue($attribute->signature, 0, $interfaceName, "impl.$implGetterFunctionName(" . (join ", ", @callWithArgs) . ")", "castedThis") . ";\n"); - - } - } else { - my ($functionName, @arguments) = $codeGenerator->GetterExpression(\%implIncludes, $interfaceName, $attribute); - push(@arguments, "isNull") if $isNullable; - if ($attribute->signature->extendedAttributes->{"ImplementedBy"}) { - my $implementedBy = $attribute->signature->extendedAttributes->{"ImplementedBy"}; - $implIncludes{"${implementedBy}.h"} = 1; - $functionName = "${implementedBy}::${functionName}"; - unshift(@arguments, "&impl") if !$attribute->isStatic; - } elsif ($attribute->isStatic) { - $functionName = "${interfaceName}::${functionName}"; - } else { - $functionName = "impl.${functionName}"; - } - - unshift(@arguments, @callWithArgs); - my $jsType = NativeToJSValue($attribute->signature, 0, $interfaceName, "${functionName}(" . join(", ", @arguments) . ")", "castedThis"); - push(@implContent, " $interfaceName& impl = castedThis->impl();\n") if !$attribute->isStatic; - if ($codeGenerator->IsSVGAnimatedType($type)) { - push(@implContent, " RefPtr<$type> obj = $jsType;\n"); - push(@implContent, " JSValue result = toJS(exec, castedThis->globalObject(), obj.get());\n"); - } else { - push(@implContent, " JSValue result = $jsType;\n"); - } - - if ($isNullable) { - push(@implContent, " if (isNull)\n"); - push(@implContent, " return JSValue::encode(jsNull());\n"); - } - } - - push(@implContent, " castedThis->m_" . $attribute->signature->name . ".set(exec->vm(), castedThis, result);\n") if ($attribute->signature->extendedAttributes->{"CachedAttribute"}); - push(@implContent, " return JSValue::encode(result);\n"); - } else { - my @arguments = ("ec"); - push(@implContent, " ExceptionCode ec = 0;\n"); - - if ($isNullable) { - push(@implContent, " bool isNull = false;\n"); - unshift(@arguments, "isNull"); + if ($attribute->extendedAttributes->{CachedAttribute}) { + push(@implContent, " if (JSValue cachedValue = thisObject.m_" . $attribute->name . ".get())\n"); + push(@implContent, " return cachedValue;\n"); } - unshift(@arguments, GenerateCallWith($attribute->signature->extendedAttributes->{"CallWith"}, \@implContent, "JSValue::encode(jsUndefined())")); + my @callWithArgs = GenerateCallWithUsingReferences($attribute->extendedAttributes->{CallWith}, \@implContent, "jsUndefined()"); - if ($svgPropertyOrListPropertyType) { - push(@implContent, " $svgPropertyOrListPropertyType impl(*castedThis->impl());\n"); - push(@implContent, " JSC::JSValue result = " . NativeToJSValue($attribute->signature, 0, $interfaceName, "impl.$implGetterFunctionName(" . join(", ", @arguments) . ")", "castedThis") . ";\n"); + my ($functionName, @arguments) = $codeGenerator->GetterExpression(\%implIncludes, $interfaceName, $attribute); + my $implementedBy = $attribute->extendedAttributes->{ImplementedBy}; + if ($implementedBy) { + $implIncludes{"${implementedBy}.h"} = 1; + $functionName = "WebCore::${implementedBy}::${functionName}"; + unshift(@arguments, "impl") if !$attribute->isStatic; + } elsif ($attribute->isStatic) { + $functionName = "${interfaceName}::${functionName}"; } else { - push(@implContent, " $interfaceName& impl = castedThis->impl();\n"); - push(@implContent, " JSC::JSValue result = " . NativeToJSValue($attribute->signature, 0, $interfaceName, "impl.$implGetterFunctionName(" . join(", ", @arguments) . ")", "castedThis") . ";\n"); + $functionName = "impl.${functionName}"; } - if ($isNullable) { - push(@implContent, " if (isNull)\n"); - push(@implContent, " return JSValue::encode(jsNull());\n"); - } + unshift(@arguments, @callWithArgs); + my $jsType = NativeToJSValueUsingReferences($attribute, $interface, "${functionName}(" . join(", ", @arguments) . ")", "thisObject"); + push(@implContent, " auto& impl = thisObject.wrapped();\n") if !$attribute->isStatic; + push(@implContent, " JSValue result = $jsType;\n"); - push(@implContent, " setDOMException(exec, ec);\n"); - push(@implContent, " return JSValue::encode(result);\n"); + push(@implContent, " thisObject.m_" . $attribute->name . ".set(state.vm(), &thisObject, result);\n") if $attribute->extendedAttributes->{CachedAttribute}; + push(@implContent, " return result;\n"); } push(@implContent, "}\n\n"); - push(@implContent, "#endif\n") if $attributeConditionalString; + if ($attribute->extendedAttributes->{"DOMJIT"}) { + assert("Only DOMJIT=Getter is supported for attributes") unless $codeGenerator->ExtendedAttributeContains($attribute->extendedAttributes->{DOMJIT}, "Getter"); + + $implIncludes{"<wtf/NeverDestroyed.h>"} = 1; + $implIncludes{"DOMJITIDLTypeFilter.h"} = 1; + my $generatorName = $interface->type->name . $codeGenerator->WK_ucfirst($attribute->name); + my $domJITClassName = $generatorName . "DOMJIT"; + my $getter = GetAttributeGetterName($interface, $generatorName, $attribute); + my $setter = IsReadonly($attribute) ? "nullptr" : GetAttributeSetterName($interface, $generatorName, $attribute); + my $resultType = GetResultTypeFilter($interface, $attribute->type); + push(@implContent, "${domJITClassName}::${domJITClassName}()\n"); + push(@implContent, " : JSC::DOMJIT::GetterSetter($getter, $setter, ${className}::info(), $resultType)\n"); + push(@implContent, "{\n"); + push(@implContent, "}\n\n"); - push(@implContent, "\n"); + push(@implContent, "JSC::DOMJIT::GetterSetter* domJITGetterSetterFor" . $generatorName . "()\n"); + push(@implContent, "{\n"); + push(@implContent, " static NeverDestroyed<${domJITClassName}> compiler;\n"); + push(@implContent, " return &compiler.get();\n"); + push(@implContent, "}\n\n"); + } + + push(@implContent, "#endif\n\n") if $attributeConditionalString; } - if (!$interface->extendedAttributes->{"NoInterfaceObject"}) { + if (NeedsConstructorProperty($interface)) { my $constructorFunctionName = "js" . $interfaceName . "Constructor"; - push(@implContent, "EncodedJSValue ${constructorFunctionName}(ExecState* exec, EncodedJSValue thisValue, EncodedJSValue, PropertyName)\n"); + push(@implContent, "EncodedJSValue ${constructorFunctionName}(ExecState* state, EncodedJSValue thisValue, PropertyName)\n"); push(@implContent, "{\n"); - if ($interfaceName eq "DOMWindow") { - push(@implContent, " ${className}* domObject = jsDynamicCast<$className*>(JSValue::decode(thisValue));\n"); - push(@implContent, " if (!domObject) {\n"); - push(@implContent, " if (JSDOMWindowShell* shell = jsDynamicCast<JSDOMWindowShell*>(JSValue::decode(thisValue)))\n"); - push(@implContent, " domObject = shell->window();\n"); - push(@implContent, " }\n"); + push(@implContent, " VM& vm = state->vm();\n"); + push(@implContent, " auto throwScope = DECLARE_THROW_SCOPE(vm);\n"); + push(@implContent, " ${className}Prototype* domObject = jsDynamicDowncast<${className}Prototype*>(vm, JSValue::decode(thisValue));\n"); + push(@implContent, " if (UNLIKELY(!domObject))\n"); + push(@implContent, " return throwVMTypeError(state, throwScope);\n"); + + if (!$interface->extendedAttributes->{NoInterfaceObject}) { + push(@implContent, " return JSValue::encode(${className}::getConstructor(state->vm(), domObject->globalObject()));\n"); } else { - push(@implContent, " ${className}* domObject = jsDynamicCast<$className*>(JSValue::decode(thisValue));\n"); - push(@implContent, " if (!domObject)\n"); - push(@implContent, " return throwVMTypeError(exec);\n"); - } - push(@implContent, " if (!domObject)\n"); - push(@implContent, " return throwVMTypeError(exec);\n"); - - if ($interface->extendedAttributes->{"CheckSecurity"}) { - push(@implContent, " if (!BindingSecurity::shouldAllowAccessToDOMWindow(exec, domObject->impl()))\n"); - push(@implContent, " return JSValue::encode(jsUndefined());\n"); + push(@implContent, " JSValue constructor = ${className}Constructor::create(state->vm(), ${className}Constructor::createStructure(state->vm(), *domObject->globalObject(), domObject->globalObject()->objectPrototype()), *jsCast<JSDOMGlobalObject*>(domObject->globalObject()));\n"); + push(@implContent, " // Shadowing constructor property to ensure reusing the same constructor object\n"); + push(@implContent, " domObject->putDirect(state->vm(), state->propertyNames().constructor, constructor, DontEnum | ReadOnly);\n"); + push(@implContent, " return JSValue::encode(constructor);\n"); } - - push(@implContent, " return JSValue::encode(${className}::getConstructor(exec->vm(), domObject->globalObject()));\n"); push(@implContent, "}\n\n"); } + my $constructorFunctionName = "setJS" . $interfaceName . "Constructor"; - # Check if we have any writable attributes - my $hasReadWriteProperties = 0; - foreach my $attribute (@{$interface->attributes}) { - $hasReadWriteProperties = 1 if !IsReadonly($attribute) && !$attribute->isStatic; - } + push(@implContent, "bool ${constructorFunctionName}(ExecState* state, EncodedJSValue thisValue, EncodedJSValue encodedValue)\n"); + push(@implContent, "{\n"); + push(@implContent, " VM& vm = state->vm();\n"); + push(@implContent, " auto throwScope = DECLARE_THROW_SCOPE(vm);\n"); + push(@implContent, " JSValue value = JSValue::decode(encodedValue);\n"); + push(@implContent, " ${className}Prototype* domObject = jsDynamicDowncast<${className}Prototype*>(vm, JSValue::decode(thisValue));\n"); + push(@implContent, " if (UNLIKELY(!domObject)) {\n"); + push(@implContent, " throwVMTypeError(state, throwScope);\n"); + push(@implContent, " return false;\n"); + push(@implContent, " }\n"); - my $overridesPutImplementation = InstanceOverridesPutImplementation($interface); - my $hasSetter = $hasReadWriteProperties; + push(@implContent, " // Shadowing a built-in constructor\n"); - if ($hasSetter || $overridesPutImplementation) { - if ($overridesPutImplementation) { - push(@implContent, "void ${className}::put(JSCell* cell, ExecState* exec, PropertyName propertyName, JSValue value, PutPropertySlot& slot)\n"); - push(@implContent, "{\n"); - push(@implContent, " ${className}* thisObject = jsCast<${className}*>(cell);\n"); - push(@implContent, " ASSERT_GC_OBJECT_INHERITS(thisObject, info());\n"); - if ($interface->extendedAttributes->{"CustomIndexedSetter"}) { - push(@implContent, " unsigned index = propertyName.asIndex();\n"); - push(@implContent, " if (index != PropertyName::NotAnIndex) {\n"); - push(@implContent, " thisObject->indexSetter(exec, index, value);\n"); - push(@implContent, " return;\n"); - push(@implContent, " }\n"); - } - if ($interface->extendedAttributes->{"CustomNamedSetter"}) { - push(@implContent, " if (thisObject->putDelegate(exec, propertyName, value, slot))\n"); - push(@implContent, " return;\n"); - } + push(@implContent, " return domObject->putDirect(state->vm(), state->propertyNames().constructor, value);\n"); + push(@implContent, "}\n\n"); + } + + foreach my $attribute (@{$interface->attributes}) { + if (!IsReadonly($attribute)) { + next if IsJSBuiltin($interface, $attribute); + + my $name = $attribute->name; + my $type = $attribute->type; + my $putFunctionName = GetAttributeSetterName($interface, $className, $attribute); + my $implSetterFunctionName = $codeGenerator->WK_ucfirst($name); - push(@implContent, " Base::put(thisObject, exec, propertyName, value, slot);\n"); + my $attributeConditionalString = $codeGenerator->GenerateConditionalString($attribute); + push(@implContent, "#if ${attributeConditionalString}\n") if $attributeConditionalString; + + if (!$attribute->isStatic) { + my $setterFunction = "${putFunctionName}Function"; + my $templateParameters = $setterFunction; + $templateParameters .= ", CastedThisErrorBehavior::ReturnEarly" if $attribute->extendedAttributes->{LenientThis}; + push(@implContent, "static inline bool ${setterFunction}(ExecState&, ${className}&, JSValue, ThrowScope&);\n\n"); + + push(@implContent, "bool ${putFunctionName}(ExecState* state, EncodedJSValue thisValue, EncodedJSValue encodedValue)\n"); + push(@implContent, "{\n"); + push(@implContent, " return BindingCaller<${className}>::setAttribute<${templateParameters}>(state, thisValue, encodedValue, \"$name\");\n"); push(@implContent, "}\n\n"); - if ($interface->extendedAttributes->{"CustomIndexedSetter"} || $interface->extendedAttributes->{"CustomNamedSetter"}) { - push(@implContent, "void ${className}::putByIndex(JSCell* cell, ExecState* exec, unsigned index, JSValue value, bool shouldThrow)\n"); - push(@implContent, "{\n"); - push(@implContent, " ${className}* thisObject = jsCast<${className}*>(cell);\n"); - push(@implContent, " ASSERT_GC_OBJECT_INHERITS(thisObject, info());\n"); - if ($interface->extendedAttributes->{"CustomIndexedSetter"}) { - push(@implContent, " if (index <= MAX_ARRAY_INDEX) {\n"); - push(@implContent, " UNUSED_PARAM(shouldThrow);\n"); - push(@implContent, " thisObject->indexSetter(exec, index, value);\n"); - push(@implContent, " return;\n"); - push(@implContent, " }\n"); - } + push(@implContent, "static inline bool ${setterFunction}(ExecState& state, ${className}& thisObject, JSValue value, ThrowScope& throwScope)\n"); + push(@implContent, "{\n"); + push(@implContent, " UNUSED_PARAM(state);\n"); + push(@implContent, " UNUSED_PARAM(throwScope);\n"); + } else { + push(@implContent, "bool ${putFunctionName}(ExecState* statePointer, EncodedJSValue, EncodedJSValue encodedValue)\n"); + push(@implContent, "{\n"); + push(@implContent, " ASSERT(statePointer);\n"); + push(@implContent, " auto& state = *statePointer;\n"); + push(@implContent, " UNUSED_PARAM(state);\n"); + push(@implContent, " auto value = JSValue::decode(encodedValue);\n"); + } - if ($interface->extendedAttributes->{"CustomNamedSetter"}) { - push(@implContent, " PropertyName propertyName = Identifier::from(exec, index);\n"); - push(@implContent, " PutPropertySlot slot(thisObject, shouldThrow);\n"); - push(@implContent, " if (thisObject->putDelegate(exec, propertyName, value, slot))\n"); - push(@implContent, " return;\n"); - } + if ($attribute->extendedAttributes->{CEReactions}) { + push(@implContent, " CustomElementReactionStack customElementReactionStack;\n"); + $implIncludes{"CustomElementReactionQueue.h"} = 1; + } - push(@implContent, " Base::putByIndex(cell, exec, index, value, shouldThrow);\n"); - push(@implContent, "}\n\n"); + if ($interface->extendedAttributes->{CheckSecurity} && !$attribute->extendedAttributes->{DoNotCheckSecurity} && !$attribute->extendedAttributes->{DoNotCheckSecurityOnSetter}) { + AddToImplIncludes("JSDOMBindingSecurity.h"); + if ($interfaceName eq "DOMWindow") { + push(@implContent, " if (!BindingSecurity::shouldAllowAccessToDOMWindow(&state, thisObject.wrapped(), ThrowSecurityError))\n"); + } else { + push(@implContent, " if (!BindingSecurity::shouldAllowAccessToFrame(&state, thisObject.wrapped().frame(), ThrowSecurityError))\n"); } + push(@implContent, " return false;\n"); } - if ($hasReadWriteProperties) { - foreach my $attribute (@{$interface->attributes}) { - if (!IsReadonly($attribute)) { - my $name = $attribute->signature->name; - my $type = $attribute->signature->type; - my $putFunctionName = GetAttributeSetterName($interfaceName, $className, $attribute); - my $implSetterFunctionName = $codeGenerator->WK_ucfirst($name); - my $setterRaisesException = $attribute->signature->extendedAttributes->{"SetterRaisesException"}; - - my $attributeConditionalString = $codeGenerator->GenerateConditionalString($attribute->signature); - push(@implContent, "#if ${attributeConditionalString}\n") if $attributeConditionalString; - - push(@implContent, "void ${putFunctionName}(ExecState* exec, JSObject* /* baseObject */, EncodedJSValue"); - push(@implContent, " thisValue") if !$attribute->isStatic; - push(@implContent, ", EncodedJSValue encodedValue)\n"); - push(@implContent, "{\n"); - push(@implContent, " JSValue value = JSValue::decode(encodedValue);\n"); - push(@implContent, " UNUSED_PARAM(exec);\n"); - if (!$attribute->isStatic) { - push(@implContent, " ${className}* castedThis = jsDynamicCast<${className}*>(JSValue::decode(thisValue));\n"); - if ($interfaceName eq "DOMWindow") { - push(@implContent, " if (!castedThis) {\n"); - push(@implContent, " if (JSDOMWindowShell* shell = jsDynamicCast<JSDOMWindowShell*>(JSValue::decode(thisValue)))\n"); - push(@implContent, " castedThis = shell->window();\n"); - push(@implContent, " }\n"); - } - push(@implContent, " if (!castedThis) {\n"); - push(@implContent, " throwVMTypeError(exec);\n"); - push(@implContent, " return;\n"); - push(@implContent, " }\n"); - } - if ($interface->extendedAttributes->{"CheckSecurity"} && !$attribute->signature->extendedAttributes->{"DoNotCheckSecurity"}) { - if ($interfaceName eq "DOMWindow") { - push(@implContent, " if (!BindingSecurity::shouldAllowAccessToDOMWindow(exec, castedThis->impl()))\n"); - } else { - push(@implContent, " if (!shouldAllowAccessToFrame(exec, castedThis->impl().frame()))\n"); - } - push(@implContent, " return;\n"); + if (HasCustomSetter($attribute->extendedAttributes)) { + push(@implContent, " thisObject.set$implSetterFunctionName(state, value);\n"); + push(@implContent, " return true;\n"); + } elsif ($type->name eq "EventHandler") { + $implIncludes{"JSEventListener.h"} = 1; + my $eventName = EventHandlerAttributeEventName($attribute); + # FIXME: Find a way to do this special case without hardcoding the class and attribute names here. + if ((($interfaceName eq "DOMWindow") or ($interfaceName eq "WorkerGlobalScope")) and $name eq "onerror") { + $implIncludes{"JSErrorHandler.h"} = 1; + push(@implContent, " thisObject.wrapped().setAttributeEventListener($eventName, createJSErrorHandler(&state, value, &thisObject), worldForDOMObject(&thisObject));\n"); + } else { + $implIncludes{"JSEventListener.h"} = 1; + my $setter = $attribute->extendedAttributes->{WindowEventHandler} ? "setWindowEventHandlerAttribute" + : $attribute->extendedAttributes->{DocumentEventHandler} ? "setDocumentEventHandlerAttribute" + : "setEventHandlerAttribute"; + push(@implContent, " $setter(state, thisObject, thisObject.wrapped(), $eventName, value);\n"); + } + push(@implContent, " return true;\n"); + } elsif ($codeGenerator->IsConstructorType($type)) { + my $constructorType = $type->name; + $constructorType =~ s/Constructor$//; + # $constructorType ~= /Constructor$/ indicates that it is NamedConstructor. + # We do not generate the header file for NamedConstructor of class XXXX, + # since we generate the NamedConstructor declaration into the header file of class XXXX. + if ($constructorType ne "any" and $constructorType !~ /Named$/) { + AddToImplIncludes("JS" . $constructorType . ".h", $attribute->extendedAttributes->{Conditional}); + } + push(@implContent, " // Shadowing a built-in constructor.\n"); + push(@implContent, " return thisObject.putDirect(state.vm(), Identifier::fromString(&state, \"$name\"), value);\n"); + } elsif ($attribute->extendedAttributes->{Replaceable}) { + push(@implContent, " // Shadowing a built-in property.\n"); + if (AttributeShouldBeOnInstance($interface, $attribute)) { + push(@implContent, " return replaceStaticPropertySlot(state.vm(), &thisObject, Identifier::fromString(&state, \"$name\"), value);\n"); + } else { + push(@implContent, " return thisObject.putDirect(state.vm(), Identifier::fromString(&state, \"$name\"), value);\n"); + } + } else { + if (!$attribute->isStatic) { + my $putForwards = $attribute->extendedAttributes->{PutForwards}; + if ($putForwards) { + my $implGetterFunctionName = $codeGenerator->WK_lcfirst($attribute->extendedAttributes->{ImplementedAs} || $name); + my $forwardedAttribute = $codeGenerator->GetAttributeFromInterface($interface, $type->name, $putForwards); + + if ($forwardedAttribute->extendedAttributes->{CEReactions}) { + push(@implContent, " CustomElementReactionStack customElementReactionStack;\n"); + $implIncludes{"CustomElementReactionQueue.h"} = 1; } - if (HasCustomSetter($attribute->signature->extendedAttributes)) { - push(@implContent, " castedThis->set$implSetterFunctionName(exec, value);\n"); - } elsif ($type eq "EventListener") { - $implIncludes{"JSEventListener.h"} = 1; - push(@implContent, " UNUSED_PARAM(exec);\n"); - my $windowEventListener = $attribute->signature->extendedAttributes->{"JSWindowEventListener"}; - if ($windowEventListener) { - push(@implContent, " JSDOMGlobalObject* globalObject = castedThis->globalObject();\n"); - } - push(@implContent, " $interfaceName& impl = castedThis->impl();\n"); - if ((($interfaceName eq "DOMWindow") or ($interfaceName eq "WorkerGlobalScope")) and $name eq "onerror") { - $implIncludes{"JSErrorHandler.h"} = 1; - push(@implContent, " impl.set$implSetterFunctionName(createJSErrorHandler(exec, value, castedThis));\n"); - } else { - push(@implContent, GenerateAttributeEventListenerCall($className, $implSetterFunctionName, $windowEventListener)); - } - } elsif ($attribute->signature->type =~ /Constructor$/) { - my $constructorType = $attribute->signature->type; - $constructorType =~ s/Constructor$//; - # $constructorType ~= /Constructor$/ indicates that it is NamedConstructor. - # We do not generate the header file for NamedConstructor of class XXXX, - # since we generate the NamedConstructor declaration into the header file of class XXXX. - if ($constructorType ne "any" and $constructorType !~ /Named$/) { - AddToImplIncludes("JS" . $constructorType . ".h", $attribute->signature->extendedAttributes->{"Conditional"}); - } - push(@implContent, " // Shadowing a built-in constructor\n"); - if ($interfaceName eq "DOMWindow" && $className eq "JSblah") { - # FIXME: This branch never executes and should be removed. - push(@implContent, " castedThis->putDirect(exec->vm(), exec->propertyNames().constructor, value);\n"); - } else { - push(@implContent, " castedThis->putDirect(exec->vm(), Identifier(exec, \"$name\"), value);\n"); - } - } elsif ($attribute->signature->extendedAttributes->{"Replaceable"}) { - push(@implContent, " // Shadowing a built-in object\n"); - push(@implContent, " castedThis->putDirect(exec->vm(), Identifier(exec, \"$name\"), value);\n"); + if ($type->isNullable) { + push(@implContent, " RefPtr<" . $type->name . "> forwardedImpl = thisObject.wrapped().${implGetterFunctionName}();\n"); + push(@implContent, " if (!forwardedImpl)\n"); + push(@implContent, " return false;\n"); + push(@implContent, " auto& impl = *forwardedImpl;\n"); } else { - if (!$attribute->isStatic) { - push(@implContent, " $implType& impl = castedThis->impl();\n"); - } - push(@implContent, " ExceptionCode ec = 0;\n") if $setterRaisesException; - - # If the "StrictTypeChecking" extended attribute is present, and the attribute's type is an - # interface type, then if the incoming value does not implement that interface, a TypeError - # is thrown rather than silently passing NULL to the C++ code. - # Per the Web IDL and ECMAScript specifications, incoming values can always be converted to - # both strings and numbers, so do not throw TypeError if the attribute is of these types. - if ($attribute->signature->extendedAttributes->{"StrictTypeChecking"}) { - $implIncludes{"<runtime/Error.h>"} = 1; - - my $argType = $attribute->signature->type; - if ($codeGenerator->IsWrapperType($argType)) { - push(@implContent, " if (!value.isUndefinedOrNull() && !value.inherits(JS${argType}::info())) {\n"); - push(@implContent, " throwVMTypeError(exec);\n"); - push(@implContent, " return;\n"); - push(@implContent, " };\n"); - } - } - - push(@implContent, " " . GetNativeTypeFromSignature($attribute->signature) . " nativeValue(" . JSValueToNative($attribute->signature, "value") . ");\n"); - push(@implContent, " if (exec->hadException())\n"); - push(@implContent, " return;\n"); - - if ($codeGenerator->IsEnumType($type)) { - my @enumValues = $codeGenerator->ValidEnumValues($type); - my @enumChecks = (); - foreach my $enumValue (@enumValues) { - push(@enumChecks, "nativeValue != \"$enumValue\""); - } - push (@implContent, " if (" . join(" && ", @enumChecks) . ")\n"); - push (@implContent, " return;\n"); - } - - if ($svgPropertyOrListPropertyType) { - if ($svgPropertyType) { - push(@implContent, " if (impl.isReadOnly()) {\n"); - push(@implContent, " setDOMException(exec, NO_MODIFICATION_ALLOWED_ERR);\n"); - push(@implContent, " return;\n"); - push(@implContent, " }\n"); - $implIncludes{"ExceptionCode.h"} = 1; - } - push(@implContent, " $svgPropertyOrListPropertyType& podImpl = impl.propertyReference();\n"); - if ($svgPropertyOrListPropertyType eq "float") { # Special case for JSSVGNumber - push(@implContent, " podImpl = nativeValue;\n"); - } else { - push(@implContent, " podImpl.set$implSetterFunctionName(nativeValue"); - push(@implContent, ", ec") if $setterRaisesException; - push(@implContent, ");\n"); - push(@implContent, " setDOMException(exec, ec);\n") if $setterRaisesException; - } - if ($svgPropertyType) { - if ($setterRaisesException) { - push(@implContent, " if (!ec)\n"); - push(@implContent, " impl.commitChange();\n"); - } else { - push(@implContent, " impl.commitChange();\n"); - } - } - } else { - my ($functionName, @arguments) = $codeGenerator->SetterExpression(\%implIncludes, $interfaceName, $attribute); - if ($codeGenerator->IsTypedArrayType($attribute->signature->type) and not $attribute->signature->type eq "ArrayBuffer") { - push(@arguments, "nativeValue.get()"); - } else { - push(@arguments, "nativeValue"); - } - if ($attribute->signature->extendedAttributes->{"ImplementedBy"}) { - my $implementedBy = $attribute->signature->extendedAttributes->{"ImplementedBy"}; - $implIncludes{"${implementedBy}.h"} = 1; - unshift(@arguments, "&impl") if !$attribute->isStatic; - $functionName = "${implementedBy}::${functionName}"; - } elsif ($attribute->isStatic) { - $functionName = "${interfaceName}::${functionName}"; - } else { - $functionName = "impl.${functionName}"; - } - - unshift(@arguments, GenerateCallWith($attribute->signature->extendedAttributes->{"CallWith"}, \@implContent, "")); - - push(@arguments, "ec") if $setterRaisesException; - push(@implContent, " ${functionName}(" . join(", ", @arguments) . ");\n"); - push(@implContent, " setDOMException(exec, ec);\n") if $setterRaisesException; - } + # Attribute is not nullable, the implementation is expected to return a reference. + push(@implContent, " Ref<" . $type->name . "> forwardedImpl = thisObject.wrapped().${implGetterFunctionName}();\n"); + push(@implContent, " auto& impl = forwardedImpl.get();\n"); } - - push(@implContent, "}\n\n"); - push(@implContent, "#endif\n") if $attributeConditionalString; - push(@implContent, "\n"); + $attribute = $forwardedAttribute; + $type = $attribute->type; + } else { + push(@implContent, " auto& impl = thisObject.wrapped();\n"); } } - } - } - if ($interface->extendedAttributes->{"ReplaceableConstructor"}) { - my $constructorFunctionName = "setJS" . $interfaceName . "Constructor"; + my $globalObjectReference = $attribute->isStatic ? "*jsCast<JSDOMGlobalObject*>(state->lexicalGlobalObject())" : "*thisObject.globalObject()"; + my $exceptionThrower = GetAttributeExceptionThrower($interface, $attribute); - push(@implContent, "void ${constructorFunctionName}(ExecState* exec, JSObject*, EncodedJSValue thisValue, EncodedJSValue encodedValue)\n"); - push(@implContent, "{\n"); - push(@implContent, " JSValue value = JSValue::decode(encodedValue);"); - push(@implContent, " ${className}* castedThis = jsDynamicCast<${className}*>(JSValue::decode(thisValue));\n"); - if ($interfaceName eq "DOMWindow") { - push(@implContent, " if (!castedThis) {\n"); - push(@implContent, " if (JSDOMWindowShell* shell = jsDynamicCast<JSDOMWindowShell*>(JSValue::decode(thisValue)))\n"); - push(@implContent, " castedThis = shell->window();\n"); - push(@implContent, " }\n"); - } - push(@implContent, " if (!castedThis) {\n"); - push(@implContent, " throwVMTypeError(exec);\n"); - push(@implContent, " return;\n"); - push(@implContent, " }\n"); - if ($interface->extendedAttributes->{"CheckSecurity"}) { - if ($interfaceName eq "DOMWindow") { - push(@implContent, " if (!BindingSecurity::shouldAllowAccessToDOMWindow(exec, castedThis->impl()))\n"); + my ($nativeValue, $mayThrowException) = JSValueToNative($interface, $attribute, "value", $attribute->extendedAttributes->{Conditional}, "&state", "state", "thisObject", $globalObjectReference, $exceptionThrower); + + push(@implContent, " auto nativeValue = $nativeValue;\n"); + push(@implContent, " RETURN_IF_EXCEPTION(throwScope, false);\n") if $mayThrowException; + + if ($codeGenerator->IsEnumType($type)) { + push (@implContent, " if (UNLIKELY(!nativeValue))\n"); + push (@implContent, " return false;\n"); + } + + my ($functionName, @arguments) = $codeGenerator->SetterExpression(\%implIncludes, $interfaceName, $attribute); + + push(@arguments, PassArgumentExpression("nativeValue", $attribute)); + + my $implementedBy = $attribute->extendedAttributes->{ImplementedBy}; + if ($implementedBy) { + AddToImplIncludes("${implementedBy}.h", $attribute->extendedAttributes->{Conditional}); + unshift(@arguments, "impl") if !$attribute->isStatic; + $functionName = "WebCore::${implementedBy}::${functionName}"; + } elsif ($attribute->isStatic) { + $functionName = "${interfaceName}::${functionName}"; } else { - push(@implContent, " if (!shouldAllowAccessToFrame(exec, castedThis->impl().frame()))\n"); + $functionName = "impl.${functionName}"; } - push(@implContent, " return;\n"); - } - push(@implContent, " // Shadowing a built-in constructor\n"); + unshift(@arguments, GenerateCallWithUsingReferences($attribute->extendedAttributes->{SetterCallWith}, \@implContent, "false")); + unshift(@arguments, GenerateCallWithUsingReferences($attribute->extendedAttributes->{CallWith}, \@implContent, "false")); - if ($interfaceName eq "DOMWindow") { - push(@implContent, " castedThis->putDirect(exec->vm(), exec->propertyNames().constructor, value);\n"); - } else { - die "No way to handle interface with ReplaceableConstructor extended attribute: $interfaceName"; + my $functionString = "$functionName(" . join(", ", @arguments) . ")"; + $functionString = "propagateException(state, throwScope, $functionString)" if $attribute->extendedAttributes->{SetterMayThrowException}; + + push(@implContent, " $functionString;\n"); + push(@implContent, " return true;\n"); } + push(@implContent, "}\n\n"); + push(@implContent, "#endif\n") if $attributeConditionalString; + push(@implContent, "\n"); } } - if ($indexedGetterFunction && !$interface->extendedAttributes->{"CustomEnumerateProperty"}) { - push(@implContent, "void ${className}::getOwnPropertyNames(JSObject* object, ExecState* exec, PropertyNameArray& propertyNames, EnumerationMode mode)\n"); - push(@implContent, "{\n"); - push(@implContent, " ${className}* thisObject = jsCast<${className}*>(object);\n"); - push(@implContent, " ASSERT_GC_OBJECT_INHERITS(thisObject, info());\n"); - push(@implContent, " for (unsigned i = 0, count = thisObject->impl().length(); i < count; ++i)\n"); - push(@implContent, " propertyNames.add(Identifier::from(exec, i));\n"); - push(@implContent, " Base::getOwnPropertyNames(thisObject, exec, propertyNames, mode);\n"); - push(@implContent, "}\n\n"); - } - - if (!$interface->extendedAttributes->{"NoInterfaceObject"}) { - push(@implContent, "JSValue ${className}::getConstructor(VM& vm, JSGlobalObject* globalObject)\n{\n"); - push(@implContent, " return getDOMConstructor<${className}Constructor>(vm, jsCast<JSDOMGlobalObject*>(globalObject));\n"); + if (!$interface->extendedAttributes->{NoInterfaceObject}) { + push(@implContent, "JSValue ${className}::getConstructor(VM& vm, const JSGlobalObject* globalObject)\n{\n"); + push(@implContent, " return getDOMConstructor<${className}Constructor>(vm, *jsCast<const JSDOMGlobalObject*>(globalObject));\n"); push(@implContent, "}\n\n"); - if ($interface->extendedAttributes->{"NamedConstructor"}) { + if ($interface->extendedAttributes->{NamedConstructor}) { push(@implContent, "JSValue ${className}::getNamedConstructor(VM& vm, JSGlobalObject* globalObject)\n{\n"); - push(@implContent, " return getDOMConstructor<${className}NamedConstructor>(vm, jsCast<JSDOMGlobalObject*>(globalObject));\n"); + push(@implContent, " return getDOMConstructor<${className}NamedConstructor>(vm, *jsCast<JSDOMGlobalObject*>(globalObject));\n"); push(@implContent, "}\n\n"); } } @@ -2458,8 +3949,8 @@ sub GenerateImplementation if ($numFunctions > 0) { my $inAppleCopyright = 0; foreach my $function (@{$interface->functions}) { - my $needsAppleCopyright = $function->signature->extendedAttributes->{"AppleCopyright"}; - if ($needsAppleCopyright) { + next if IsJSBuiltin($interface, $function); + if ($function->extendedAttributes->{AppleCopyright}) { if (!$inAppleCopyright) { push(@implContent, $beginAppleCopyrightForSourceFiles); $inAppleCopyright = 1; @@ -2469,240 +3960,271 @@ sub GenerateImplementation $inAppleCopyright = 0; } - my $isCustom = HasCustomMethod($function->signature->extendedAttributes); + my $isCustom = HasCustomMethod($function->extendedAttributes); my $isOverloaded = $function->{overloads} && @{$function->{overloads}} > 1; - my $raisesException = $function->signature->extendedAttributes->{"RaisesException"}; next if $isCustom && $isOverloaded && $function->{overloadIndex} > 1; - AddIncludesForTypeInImpl($function->signature->type) unless $isCustom; + AddToImplIncludesForIDLType($function->type) unless $isCustom or IsReturningPromise($function); - my $functionName = GetFunctionName($className, $function); + my $functionName = GetFunctionName($interface, $className, $function); - my $conditional = $function->signature->extendedAttributes->{"Conditional"}; + my $conditional = $function->extendedAttributes->{Conditional}; if ($conditional) { my $conditionalString = $codeGenerator->GenerateConditionalStringFromAttributeValue($conditional); push(@implContent, "#if ${conditionalString}\n"); } - + my $functionReturn = "EncodedJSValue JSC_HOST_CALL"; if (!$isCustom && $isOverloaded) { # Append a number to an overloaded method's name to make it unique: $functionName = $functionName . $function->{overloadIndex}; - # Make this function static to avoid compiler warnings, since we - # don't generate a prototype for it in the header. - push(@implContent, "static "); + # Make this function static to avoid compiler warnings, since we don't generate a prototype for it in the header. + $functionReturn = "static inline EncodedJSValue"; + } + + my $functionImplementationName = $function->extendedAttributes->{ImplementedAs} || $codeGenerator->WK_lcfirst($function->name); + + AddToImplIncludes("JSDOMPromise.h") if IsReturningPromise($function); + + if (!$function->isStatic) { + my $classParameterType = $className eq "JSEventTarget" ? "JSEventTargetWrapper*" : "${className}*"; + my $optionalPromiseParameter = (IsReturningPromise($function) && !$isCustom) ? " Ref<DeferredPromise>&&," : ""; + push(@implContent, "static inline JSC::EncodedJSValue ${functionName}Caller(JSC::ExecState*, ${classParameterType},${optionalPromiseParameter} JSC::ThrowScope&);\n"); + push(@implContent, "\n"); } - my $functionImplementationName = $function->signature->extendedAttributes->{"ImplementedAs"} || $codeGenerator->WK_lcfirst($function->signature->name); + if (IsReturningPromise($function) && !$isCustom) { + my $scope = $interface->extendedAttributes->{Exposed} ? "WindowOrWorker" : "WindowOnly"; + push(@implContent, <<END); +static EncodedJSValue ${functionName}Promise(ExecState*, Ref<DeferredPromise>&&); + +${functionReturn} ${functionName}(ExecState* state) +{ + ASSERT(state); + return JSValue::encode(callPromiseFunction<${functionName}Promise, PromiseExecutionScope::${scope}>(*state)); +} + +static inline EncodedJSValue ${functionName}Promise(ExecState* state, Ref<DeferredPromise>&& promise) +END + } else { + push(@implContent, "${functionReturn} ${functionName}(ExecState* state)\n"); + } - push(@implContent, "EncodedJSValue JSC_HOST_CALL ${functionName}(ExecState* exec)\n"); push(@implContent, "{\n"); $implIncludes{"<runtime/Error.h>"} = 1; + if ($function->extendedAttributes->{CEReactions}) { + push(@implContent, " CustomElementReactionStack customElementReactionStack;\n"); + $implIncludes{"CustomElementReactionQueue.h"} = 1; + } + if ($function->isStatic) { if ($isCustom) { GenerateArgumentsCountCheck(\@implContent, $function, $interface); - push(@implContent, " return JSValue::encode(${className}::" . $functionImplementationName . "(exec));\n"); + push(@implContent, " return JSValue::encode(${className}::" . $functionImplementationName . "(state));\n"); } else { - GenerateArgumentsCountCheck(\@implContent, $function, $interface); + push(@implContent, " VM& vm = state->vm();\n"); + push(@implContent, " auto throwScope = DECLARE_THROW_SCOPE(vm);\n"); + push(@implContent, " UNUSED_PARAM(throwScope);\n"); - push(@implContent, " ExceptionCode ec = 0;\n") if $raisesException; + GenerateArgumentsCountCheck(\@implContent, $function, $interface); - my $numParameters = @{$function->parameters}; - my ($functionString, $dummy) = GenerateParametersCheck(\@implContent, $function, $interface, $numParameters, $interfaceName, $functionImplementationName, $svgPropertyType, $svgPropertyOrListPropertyType, $svgListPropertyType); - GenerateImplementationFunctionCall($function, $functionString, " ", $svgPropertyType, $interfaceName); + my ($functionString, $dummy) = GenerateParametersCheck(\@implContent, $function, $interface, $functionImplementationName); + GenerateImplementationFunctionCall($function, $functionString, " ", $interface); } } else { - if ($interfaceName eq "DOMWindow") { - push(@implContent, " $className* castedThis = toJSDOMWindow(exec->hostThisValue().toThis(exec, NotStrictMode));\n"); - push(@implContent, " if (!castedThis)\n"); - push(@implContent, " return throwVMTypeError(exec);\n"); - } elsif ($interface->extendedAttributes->{"WorkerGlobalScope"}) { - push(@implContent, " $className* castedThis = to${className}(exec->hostThisValue().toThis(exec, NotStrictMode));\n"); - push(@implContent, " if (!castedThis)\n"); - push(@implContent, " return throwVMTypeError(exec);\n"); + my $methodName = $function->name; + if (IsReturningPromise($function) && !$isCustom) { + my $templateParameters = "${functionName}Caller"; + $templateParameters .= ", CastedThisErrorBehavior::Assert" if ($function->extendedAttributes->{PrivateIdentifier} and not $function->extendedAttributes->{PublicIdentifier}); + push(@implContent, " return BindingCaller<$className>::callPromiseOperation<${templateParameters}>(state, WTFMove(promise), \"${methodName}\");\n"); + push(@implContent, "}\n"); + push(@implContent, "\n"); + push(@implContent, "static inline JSC::EncodedJSValue ${functionName}Caller(JSC::ExecState* state, ${className}* castedThis, Ref<DeferredPromise>&& promise, JSC::ThrowScope& throwScope)\n"); } else { - push(@implContent, " JSValue thisValue = exec->hostThisValue();\n"); - push(@implContent, " $className* castedThis = jsDynamicCast<$className*>(thisValue);\n"); - push(@implContent, " if (!castedThis)\n"); - push(@implContent, " return throwVMTypeError(exec);\n"); + my $classParameterType = $className eq "JSEventTarget" ? "JSEventTargetWrapper*" : "${className}*"; + my $templateParameters = "${functionName}Caller"; + if ($function->extendedAttributes->{PrivateIdentifier} and not $function->extendedAttributes->{PublicIdentifier}) { + $templateParameters .= ", CastedThisErrorBehavior::Assert"; + } elsif (IsReturningPromise($function)) { + # FIXME: We need this specific handling for custom promise-returning functions. + # It would be better to have the casted-this code calling the promise-specific code. + $templateParameters .= ", CastedThisErrorBehavior::RejectPromise" if IsReturningPromise($function); + } + + push(@implContent, " return BindingCaller<$className>::callOperation<${templateParameters}>(state, \"${methodName}\");\n"); + push(@implContent, "}\n"); + push(@implContent, "\n"); + push(@implContent, "static inline JSC::EncodedJSValue ${functionName}Caller(JSC::ExecState* state, ${classParameterType} castedThis, JSC::ThrowScope& throwScope)\n"); } - push(@implContent, " ASSERT_GC_OBJECT_INHERITS(castedThis, ${className}::info());\n"); + push(@implContent, "{\n"); + push(@implContent, " UNUSED_PARAM(state);\n"); + push(@implContent, " UNUSED_PARAM(throwScope);\n"); - if ($interface->extendedAttributes->{"CheckSecurity"} and - !$function->signature->extendedAttributes->{"DoNotCheckSecurity"}) { - push(@implContent, " if (!BindingSecurity::shouldAllowAccessToDOMWindow(exec, castedThis->impl()))\n"); + if ($interface->extendedAttributes->{CheckSecurity} and !$function->extendedAttributes->{DoNotCheckSecurity}) { + AddToImplIncludes("JSDOMBindingSecurity.h"); + if ($interfaceName eq "DOMWindow") { + push(@implContent, " if (!BindingSecurity::shouldAllowAccessToDOMWindow(state, castedThis->wrapped(), ThrowSecurityError))\n"); + } else { + push(@implContent, " if (!BindingSecurity::shouldAllowAccessToFrame(state, castedThis->wrapped().frame(), ThrowSecurityError))\n"); + } push(@implContent, " return JSValue::encode(jsUndefined());\n"); } if ($isCustom) { - push(@implContent, " return JSValue::encode(castedThis->" . $functionImplementationName . "(exec));\n"); + push(@implContent, " return JSValue::encode(castedThis->" . $functionImplementationName . "(*state));\n"); } else { - push(@implContent, " $implType& impl = castedThis->impl();\n"); - if ($svgPropertyType) { - push(@implContent, " if (impl.isReadOnly()) {\n"); - push(@implContent, " setDOMException(exec, NO_MODIFICATION_ALLOWED_ERR);\n"); - push(@implContent, " return JSValue::encode(jsUndefined());\n"); - push(@implContent, " }\n"); - push(@implContent, " $svgPropertyType& podImpl = impl.propertyReference();\n"); - $implIncludes{"ExceptionCode.h"} = 1; - } + push(@implContent, " auto& impl = castedThis->wrapped();\n"); - # For compatibility with legacy content, the EventListener calls are generated without GenerateArgumentsCountCheck. - if ($function->signature->name eq "addEventListener") { - push(@implContent, GenerateEventListenerCall($className, "add")); - } elsif ($function->signature->name eq "removeEventListener") { - push(@implContent, GenerateEventListenerCall($className, "remove")); - } else { - GenerateArgumentsCountCheck(\@implContent, $function, $interface); + GenerateArgumentsCountCheck(\@implContent, $function, $interface); + + my ($functionString, $dummy) = GenerateParametersCheck(\@implContent, $function, $interface, $functionImplementationName); + GenerateImplementationFunctionCall($function, $functionString, " ", $interface); + } + } - push(@implContent, " ExceptionCode ec = 0;\n") if $raisesException; + push(@implContent, "}\n\n"); - if ($function->signature->extendedAttributes->{"CheckSecurityForNode"}) { - push(@implContent, " if (!shouldAllowAccessToNode(exec, impl." . $function->signature->name . "(" . ($raisesException ? "ec" : "") .")))\n"); - push(@implContent, " return JSValue::encode(jsNull());\n"); - $implIncludes{"JSDOMBinding.h"} = 1; - } + if ($function->extendedAttributes->{DOMJIT}) { + $implIncludes{"<interpreter/FrameTracers.h>"} = 1; + my $unsafeFunctionName = "unsafe" . $codeGenerator->WK_ucfirst($functionName); + push(@implContent, "JSC::EncodedJSValue JIT_OPERATION ${unsafeFunctionName}(JSC::ExecState* state, $className* castedThis"); + foreach my $argument (@{$function->arguments}) { + my $type = $argument->type; + my $argumentType = GetUnsafeArgumentType($interface, $type); + my $name = $argument->name; + my $encodedName = "encoded" . $codeGenerator->WK_ucfirst($name); + push(@implContent, ", ${argumentType} ${encodedName}"); + } + push(@implContent, ")\n"); + push(@implContent, "{\n"); + push(@implContent, " UNUSED_PARAM(state);\n"); + push(@implContent, " VM& vm = state->vm();\n"); + push(@implContent, " JSC::NativeCallFrameTracer tracer(&vm, state);\n"); + push(@implContent, " auto throwScope = DECLARE_THROW_SCOPE(vm);\n"); + push(@implContent, " UNUSED_PARAM(throwScope);\n"); + push(@implContent, " auto& impl = castedThis->wrapped();\n"); + my @arguments; + my $implFunctionName; + my $implementedBy = $function->extendedAttributes->{ImplementedBy}; + + if ($implementedBy) { + AddToImplIncludes("${implementedBy}.h", $function->extendedAttributes->{Conditional}); + unshift(@arguments, "impl") if !$function->isStatic; + $implFunctionName = "WebCore::${implementedBy}::${functionImplementationName}"; + } elsif ($function->isStatic) { + $implFunctionName = "${interfaceName}::${functionImplementationName}"; + } else { + $implFunctionName = "impl.${functionImplementationName}"; + } - my $numParameters = @{$function->parameters}; - my ($functionString, $dummy) = GenerateParametersCheck(\@implContent, $function, $interface, $numParameters, $interfaceName, $functionImplementationName, $svgPropertyType, $svgPropertyOrListPropertyType, $svgListPropertyType); - GenerateImplementationFunctionCall($function, $functionString, " ", $svgPropertyType, $interfaceName); + foreach my $argument (@{$function->arguments}) { + my $value = ""; + my $type = $argument->type; + my $name = $argument->name; + my $encodedName = "encoded" . $codeGenerator->WK_ucfirst($name); + my $nativeType = GetNativeType($interface, $argument->type); + my $shouldPassByReference = ShouldPassArgumentByReference($argument); + + if (!$shouldPassByReference && ($codeGenerator->IsWrapperType($type) || $codeGenerator->IsTypedArrayType($type))) { + $implIncludes{"<runtime/Error.h>"} = 1; + my ($nativeValue, $mayThrowException) = UnsafeToNative($interface, $argument, $encodedName, $function->extendedAttributes->{Conditional}); + push(@implContent, " $nativeType $name = nullptr;\n"); + push(@implContent, " $name = $nativeValue;\n"); + push(@implContent, " RETURN_IF_EXCEPTION(throwScope, encodedJSValue());\n") if $mayThrowException; + $value = "WTFMove($name)"; + } else { + my ($nativeValue, $mayThrowException) = UnsafeToNative($interface, $argument, $encodedName, $function->extendedAttributes->{Conditional}); + push(@implContent, " auto $name = ${nativeValue};\n"); + $value = "WTFMove($name)"; + push(@implContent, " RETURN_IF_EXCEPTION(throwScope, encodedJSValue());\n") if $mayThrowException; + } + + if ($shouldPassByReference) { + $value = "*$name"; } + push(@arguments, $value); } + my $functionString = "$implFunctionName(" . join(", ", @arguments) . ")"; + $functionString = "propagateException(*state, throwScope, $functionString)" if NeedsExplicitPropagateExceptionCall($function); + push(@implContent, " return JSValue::encode(" . NativeToJSValueUsingPointers($function, $interface, $functionString, "castedThis") . ");\n"); + push(@implContent, "}\n\n"); } - push(@implContent, "}\n\n"); push(@implContent, "#endif\n\n") if $conditional; - if (!$isCustom && $isOverloaded && $function->{overloadIndex} == @{$function->{overloads}}) { - # Generate a function dispatching call to the rest of the overloads. - GenerateOverloadedFunction($function, $interface, $interfaceName); - } - + # Generate a function dispatching call to the rest of the overloads. + GenerateOverloadedFunctionOrConstructor($function, $interface, 0) if !$isCustom && $isOverloaded && $function->{overloadIndex} == @{$function->{overloads}}; } push(@implContent, $endAppleCopyright) if $inAppleCopyright; } - if ($needsMarkChildren && !$interface->extendedAttributes->{"JSCustomMarkFunction"}) { + + GenerateImplementationIterableFunctions($interface) if $interface->iterable; + GenerateSerializerFunction($interface, $className) if $interface->serializable; + + if ($needsVisitChildren) { push(@implContent, "void ${className}::visitChildren(JSCell* cell, SlotVisitor& visitor)\n"); push(@implContent, "{\n"); - push(@implContent, " ${className}* thisObject = jsCast<${className}*>(cell);\n"); + push(@implContent, " auto* thisObject = jsCast<${className}*>(cell);\n"); push(@implContent, " ASSERT_GC_OBJECT_INHERITS(thisObject, info());\n"); - push(@implContent, " COMPILE_ASSERT(StructureFlags & OverridesVisitChildren, OverridesVisitChildrenWithoutSettingFlag);\n"); - push(@implContent, " ASSERT(thisObject->structure()->typeInfo().overridesVisitChildren());\n"); push(@implContent, " Base::visitChildren(thisObject, visitor);\n"); - if ($interface->extendedAttributes->{"EventTarget"} || $interface->name eq "EventTarget") { - push(@implContent, " thisObject->impl().visitJSEventListeners(visitor);\n"); + push(@implContent, " thisObject->visitAdditionalChildren(visitor);\n") if $interface->extendedAttributes->{JSCustomMarkFunction}; + if ($interface->extendedAttributes->{ReportExtraMemoryCost}) { + push(@implContent, " visitor.reportExtraMemoryVisited(thisObject->wrapped().memoryCost());\n"); + if ($interface->extendedAttributes->{ReportExternalMemoryCost}) {; + push(@implContent, "#if ENABLE(RESOURCE_USAGE)\n"); + push(@implContent, " visitor.reportExternalMemoryVisited(thisObject->wrapped().externalMemoryCost());\n"); + push(@implContent, "#endif\n"); + } } if ($numCachedAttributes > 0) { foreach (@{$interface->attributes}) { my $attribute = $_; - if ($attribute->signature->extendedAttributes->{"CachedAttribute"}) { - push(@implContent, " visitor.append(&thisObject->m_" . $attribute->signature->name . ");\n"); + if ($attribute->extendedAttributes->{CachedAttribute}) { + push(@implContent, " visitor.append(thisObject->m_" . $attribute->name . ");\n"); } } } push(@implContent, "}\n\n"); - } - - # Cached attributes are indeed allowed when there is a custom mark/visitChildren function. - # The custom function must make sure to account for the cached attribute. - # Uncomment the below line to temporarily enforce generated mark functions when cached attributes are present. - # die "Can't generate binding for class with cached attribute and custom mark." if (($numCachedAttributes > 0) and ($interface->extendedAttributes->{"JSCustomMarkFunction"})); - - if ($numConstants > 0) { - push(@implContent, "// Constant getters\n\n"); - - foreach my $constant (@{$interface->constants}) { - my $getter = "js" . $interfaceName . $codeGenerator->WK_ucfirst($constant->name); - my $conditional = $constant->extendedAttributes->{"Conditional"}; - - if ($conditional) { - my $conditionalString = $codeGenerator->GenerateConditionalStringFromAttributeValue($conditional); - push(@implContent, "#if ${conditionalString}\n"); - } - - # FIXME: this casts into int to match our previous behavior which turned 0xFFFFFFFF in -1 for NodeFilter.SHOW_ALL - push(@implContent, "EncodedJSValue ${getter}(ExecState* exec, EncodedJSValue, EncodedJSValue, PropertyName)\n"); + if ($interface->extendedAttributes->{JSCustomMarkFunction}) { + push(@implContent, "void ${className}::visitOutputConstraints(JSCell* cell, SlotVisitor& visitor)\n"); push(@implContent, "{\n"); - if ($constant->type eq "DOMString") { - push(@implContent, " return JSValue::encode(jsStringOrNull(exec, String(" . $constant->value . ")));\n"); - } else { - push(@implContent, " UNUSED_PARAM(exec);\n"); - push(@implContent, " return JSValue::encode(jsNumber(static_cast<int>(" . $constant->value . ")));\n"); - } + push(@implContent, " auto* thisObject = jsCast<${className}*>(cell);\n"); + push(@implContent, " ASSERT_GC_OBJECT_INHERITS(thisObject, info());\n"); + push(@implContent, " Base::visitOutputConstraints(thisObject, visitor);\n"); + push(@implContent, " thisObject->visitAdditionalChildren(visitor);\n"); push(@implContent, "}\n\n"); - push(@implContent, "#endif\n") if $conditional; } } - if ($indexedGetterFunction && !$hasNumericIndexedGetter) { - push(@implContent, "\nEncodedJSValue ${className}::indexGetter(ExecState* exec, EncodedJSValue slotBase, EncodedJSValue, unsigned index)\n"); + if (InstanceNeedsEstimatedSize($interface)) { + push(@implContent, "size_t ${className}::estimatedSize(JSCell* cell)\n"); push(@implContent, "{\n"); - push(@implContent, " ${className}* thisObj = jsCast<$className*>(JSValue::decode(slotBase));\n"); - push(@implContent, " ASSERT_GC_OBJECT_INHERITS(thisObj, info());\n"); - if ($indexedGetterFunction->signature->type eq "DOMString") { - $implIncludes{"URL.h"} = 1; - push(@implContent, " return JSValue::encode(jsStringOrUndefined(exec, thisObj->impl().item(index)));\n"); - } else { - push(@implContent, " return JSValue::encode(toJS(exec, thisObj->globalObject(), thisObj->impl().item(index)));\n"); - } + push(@implContent, " auto* thisObject = jsCast<${className}*>(cell);\n"); + push(@implContent, " return Base::estimatedSize(thisObject) + thisObject->wrapped().memoryCost();\n"); push(@implContent, "}\n\n"); - if ($interfaceName =~ /^HTML\w*Collection$/ or $interfaceName eq "RadioNodeList") { - $implIncludes{"JSNode.h"} = 1; - $implIncludes{"Node.h"} = 1; - } } - if ($hasNumericIndexedGetter) { - push(@implContent, "\nJSValue ${className}::getByIndex(ExecState*, unsigned index)\n"); - push(@implContent, "{\n"); - push(@implContent, " ASSERT_GC_OBJECT_INHERITS(this, info());\n"); - push(@implContent, " double result = impl().item(index);\n"); - # jsNumber conversion doesn't suppress signalling NaNs, so enforce that here. - push(@implContent, " if (std::isnan(result))\n"); - push(@implContent, " return jsNaN();\n"); - push(@implContent, " return JSValue(result);\n"); - push(@implContent, "}\n\n"); - if ($interfaceName =~ /^HTML\w*Collection$/) { + # Cached attributes are indeed allowed when there is a custom mark/visitChildren function. + # The custom function must make sure to account for the cached attribute. + # Uncomment the below line to temporarily enforce generated mark functions when cached attributes are present. + # die "Can't generate binding for class with cached attribute and custom mark." if $numCachedAttributes > 0 and $interface->extendedAttributes->{JSCustomMarkFunction}; + + if ($indexedGetterFunction) { + $implIncludes{"URL.h"} = 1 if $indexedGetterFunction->type->name eq "DOMString"; + if ($interfaceName =~ /^HTML\w*Collection$/ or $interfaceName eq "RadioNodeList") { $implIncludes{"JSNode.h"} = 1; $implIncludes{"Node.h"} = 1; } } - if ($interfaceName eq "DOMNamedFlowCollection") { - if ($namedGetterFunction) { - push(@implContent, "bool ${className}::canGetItemsForName(ExecState*, $interfaceName* collection, PropertyName propertyName)\n"); - push(@implContent, "{\n"); - push(@implContent, " return collection->hasNamedItem(propertyNameToAtomicString(propertyName));\n"); - push(@implContent, "}\n\n"); - push(@implContent, "EncodedJSValue ${className}::nameGetter(ExecState* exec, EncodedJSValue slotBase, EncodedJSValue, PropertyName propertyName)\n"); - push(@implContent, "{\n"); - push(@implContent, " ${className}* thisObj = jsCast<$className*>(JSValue::decode(slotBase));\n"); - push(@implContent, " return JSValue::encode(toJS(exec, thisObj->globalObject(), thisObj->impl().namedItem(propertyNameToAtomicString(propertyName))));\n"); - push(@implContent, "}\n\n"); - } - } - - if ((!$hasParent && !GetCustomIsReachable($interface)) || GetGenerateIsReachable($interface) || $codeGenerator->InheritsExtendedAttribute($interface, "ActiveDOMObject")) { - if (GetGenerateIsReachable($interface)) { - push(@implContent, "static inline bool isObservable(JS${interfaceName}* js${interfaceName})\n"); - push(@implContent, "{\n"); - push(@implContent, " if (js${interfaceName}->hasCustomProperties())\n"); - push(@implContent, " return true;\n"); - if ($eventTarget) { - push(@implContent, " if (js${interfaceName}->impl().hasEventListeners())\n"); - push(@implContent, " return true;\n"); - } - push(@implContent, " return false;\n"); - push(@implContent, "}\n\n"); - } - + if (ShouldGenerateWrapperOwnerCode($hasParent, $interface) && !GetCustomIsReachable($interface)) { push(@implContent, "bool JS${interfaceName}Owner::isReachableFromOpaqueRoots(JSC::Handle<JSC::Unknown> handle, void*, SlotVisitor& visitor)\n"); push(@implContent, "{\n"); # All ActiveDOMObjects implement hasPendingActivity(), but not all of them @@ -2711,25 +4233,25 @@ sub GenerateImplementation # their pending activities complete. To wallpaper over this bug, JavaScript # wrappers unconditionally keep ActiveDOMObjects with pending activity alive. # FIXME: Fix this lifetime issue in the DOM, and move this hasPendingActivity - # check below the isObservable check. + # check just above the (GetGenerateIsReachable($interface) eq "Impl") check below. my $emittedJSCast = 0; if ($codeGenerator->InheritsExtendedAttribute($interface, "ActiveDOMObject")) { - push(@implContent, " JS${interfaceName}* js${interfaceName} = jsCast<JS${interfaceName}*>(handle.get().asCell());\n"); + push(@implContent, " auto* js${interfaceName} = jsCast<JS${interfaceName}*>(handle.slot()->asCell());\n"); $emittedJSCast = 1; - push(@implContent, " if (js${interfaceName}->impl().hasPendingActivity())\n"); + push(@implContent, " if (js${interfaceName}->wrapped().hasPendingActivity())\n"); push(@implContent, " return true;\n"); } - if ($codeGenerator->InheritsExtendedAttribute($interface, "EventTarget")) { + if ($codeGenerator->InheritsInterface($interface, "EventTarget")) { if (!$emittedJSCast) { - push(@implContent, " JS${interfaceName}* js${interfaceName} = jsCast<JS${interfaceName}*>(handle.get().asCell());\n"); + push(@implContent, " auto* js${interfaceName} = jsCast<JS${interfaceName}*>(handle.slot()->asCell());\n"); $emittedJSCast = 1; } - push(@implContent, " if (js${interfaceName}->impl().isFiringEventListeners())\n"); + push(@implContent, " if (js${interfaceName}->wrapped().isFiringEventListeners())\n"); push(@implContent, " return true;\n"); } if ($codeGenerator->InheritsInterface($interface, "Node")) { if (!$emittedJSCast) { - push(@implContent, " JS${interfaceName}* js${interfaceName} = jsCast<JS${interfaceName}*>(handle.get().asCell());\n"); + push(@implContent, " auto* js${interfaceName} = jsCast<JS${interfaceName}*>(handle.slot()->asCell());\n"); $emittedJSCast = 1; } push(@implContent, " if (JSNodeOwner::isReachableFromOpaqueRoots(handle, 0, visitor))\n"); @@ -2737,40 +4259,40 @@ sub GenerateImplementation } if (GetGenerateIsReachable($interface)) { if (!$emittedJSCast) { - push(@implContent, " JS${interfaceName}* js${interfaceName} = jsCast<JS${interfaceName}*>(handle.get().asCell());\n"); + push(@implContent, " auto* js${interfaceName} = jsCast<JS${interfaceName}*>(handle.slot()->asCell());\n"); $emittedJSCast = 1; } - push(@implContent, " if (!isObservable(js${interfaceName}))\n"); - push(@implContent, " return false;\n"); my $rootString; if (GetGenerateIsReachable($interface) eq "Impl") { - $rootString = " ${implType}* root = &js${interfaceName}->impl();\n"; + $rootString = " ${implType}* root = &js${interfaceName}->wrapped();\n"; } elsif (GetGenerateIsReachable($interface) eq "ImplWebGLRenderingContext") { - $rootString = " WebGLRenderingContext* root = js${interfaceName}->impl().context();\n"; + $rootString = " WebGLRenderingContextBase* root = WTF::getPtr(js${interfaceName}->wrapped().context());\n"; } elsif (GetGenerateIsReachable($interface) eq "ImplFrame") { - $rootString = " Frame* root = js${interfaceName}->impl().frame();\n"; + $rootString = " Frame* root = WTF::getPtr(js${interfaceName}->wrapped().frame());\n"; $rootString .= " if (!root)\n"; $rootString .= " return false;\n"; } elsif (GetGenerateIsReachable($interface) eq "ImplDocument") { - $rootString = " Document* root = js${interfaceName}->impl().document();\n"; + $rootString = " Document* root = WTF::getPtr(js${interfaceName}->wrapped().document());\n"; $rootString .= " if (!root)\n"; $rootString .= " return false;\n"; } elsif (GetGenerateIsReachable($interface) eq "ImplElementRoot") { $implIncludes{"Element.h"} = 1; $implIncludes{"JSNodeCustom.h"} = 1; - $rootString = " Element* element = js${interfaceName}->impl().element();\n"; + $rootString = " Element* element = WTF::getPtr(js${interfaceName}->wrapped().element());\n"; $rootString .= " if (!element)\n"; $rootString .= " return false;\n"; $rootString .= " void* root = WebCore::root(element);\n"; - } elsif ($interfaceName eq "CanvasRenderingContext") { - $rootString = " void* root = WebCore::root(js${interfaceName}->impl().canvas());\n"; } elsif (GetGenerateIsReachable($interface) eq "ImplOwnerNodeRoot") { $implIncludes{"Element.h"} = 1; $implIncludes{"JSNodeCustom.h"} = 1; - $rootString = " void* root = WebCore::root(js${interfaceName}->impl().ownerNode());\n"; + $rootString = " void* root = WebCore::root(js${interfaceName}->wrapped().ownerNode());\n"; + } elsif (GetGenerateIsReachable($interface) eq "ImplScriptExecutionContext") { + $rootString = " ScriptExecutionContext* root = WTF::getPtr(js${interfaceName}->wrapped().scriptExecutionContext());\n"; + $rootString .= " if (!root)\n"; + $rootString .= " return false;\n"; } else { - $rootString = " void* root = WebCore::root(&js${interfaceName}->impl());\n"; + $rootString = " void* root = WebCore::root(&js${interfaceName}->wrapped());\n"; } push(@implContent, $rootString); @@ -2785,17 +4307,12 @@ sub GenerateImplementation push(@implContent, "}\n\n"); } - if (!$interface->extendedAttributes->{"JSCustomFinalize"} && - (!$hasParent || - GetGenerateIsReachable($interface) || - GetCustomIsReachable($interface) || - $codeGenerator->InheritsExtendedAttribute($interface, "ActiveDOMObject"))) { + if (ShouldGenerateWrapperOwnerCode($hasParent, $interface) && !$interface->extendedAttributes->{JSCustomFinalize}) { push(@implContent, "void JS${interfaceName}Owner::finalize(JSC::Handle<JSC::Unknown> handle, void* context)\n"); push(@implContent, "{\n"); - push(@implContent, " JS${interfaceName}* js${interfaceName} = jsCast<JS${interfaceName}*>(handle.get().asCell());\n"); - push(@implContent, " DOMWrapperWorld& world = *static_cast<DOMWrapperWorld*>(context);\n"); - push(@implContent, " uncacheWrapper(world, &js${interfaceName}->impl(), js${interfaceName});\n"); - push(@implContent, " js${interfaceName}->releaseImpl();\n"); + push(@implContent, " auto* js${interfaceName} = static_cast<JS${interfaceName}*>(handle.slot()->asCell());\n"); + push(@implContent, " auto& world = *static_cast<DOMWrapperWorld*>(context);\n"); + push(@implContent, " uncacheWrapper(world, &js${interfaceName}->wrapped(), js${interfaceName});\n"); push(@implContent, "}\n\n"); } @@ -2813,26 +4330,15 @@ extern "C" { extern void (*const ${vtableRefWin}[])(); } extern "C" { extern void* ${vtableNameGnu}[]; } #endif #endif -END - push(@implContent, "JSC::JSValue toJS(JSC::ExecState* exec, JSDOMGlobalObject* globalObject, $implType* impl)\n"); - push(@implContent, "{\n"); - push(@implContent, <<END); - if (!impl) - return jsNull(); END - if ($svgPropertyType) { - push(@implContent, " if (JSValue result = getExistingWrapper<$className, $implType>(exec, impl))\n"); - push(@implContent, " return result;\n"); - } else { - push(@implContent, " if (JSValue result = getExistingWrapper<$className>(exec, impl))\n"); - push(@implContent, " return result;\n"); - } + push(@implContent, "JSC::JSValue toJSNewlyCreated(JSC::ExecState*, JSDOMGlobalObject* globalObject, Ref<$implType>&& impl)\n"); + push(@implContent, "{\n"); push(@implContent, <<END) if $vtableNameGnu; #if ENABLE(BINDING_INTEGRITY) - void* actualVTablePointer = *(reinterpret_cast<void**>(impl)); + void* actualVTablePointer = *(reinterpret_cast<void**>(impl.ptr())); #if PLATFORM(WIN) void* expectedVTablePointer = reinterpret_cast<void*>(${vtableRefWin}); #else @@ -2840,7 +4346,7 @@ END #if COMPILER(CLANG) // If this fails $implType does not have a vtable, so you need to add the // ImplementationLacksVTable attribute to the interface definition - COMPILE_ASSERT(__is_polymorphic($implType), ${implType}_is_not_polymorphic); + static_assert(__is_polymorphic($implType), "${implType} is not polymorphic"); #endif #endif // If you hit this assertion you either have a use after free bug, or @@ -2850,33 +4356,35 @@ END RELEASE_ASSERT(actualVTablePointer == expectedVTablePointer); #endif END - push(@implContent, <<END) if $interface->extendedAttributes->{"ImplementationLacksVTable"}; + push(@implContent, <<END) if $interface->extendedAttributes->{ImplementationLacksVTable}; #if COMPILER(CLANG) // If you hit this failure the interface definition has the ImplementationLacksVTable // attribute. You should remove that attribute. If the class has subclasses // that may be passed through this toJS() function you should use the SkipVTableValidation // attribute to $interfaceName. - COMPILE_ASSERT(!__is_polymorphic($implType), ${implType}_is_polymorphic_but_idl_claims_not_to_be); + static_assert(!__is_polymorphic($implType), "${implType} is polymorphic but the IDL claims it is not"); #endif END - push(@implContent, <<END); - ReportMemoryCost<$implType>::reportMemoryCost(exec, impl); + push(@implContent, <<END) if $interface->extendedAttributes->{ReportExtraMemoryCost}; + globalObject->vm().heap.reportExtraMemoryAllocated(impl->memoryCost()); END - if ($svgPropertyType) { - push(@implContent, " return createNewWrapper<$className, $implType>(exec, globalObject, impl);\n"); - } else { - push(@implContent, " return createNewWrapper<$className>(exec, globalObject, impl);\n"); - } + push(@implContent, " return createWrapper<$implType>(globalObject, WTFMove(impl));\n"); + push(@implContent, "}\n\n"); + push(@implContent, "JSC::JSValue toJS(JSC::ExecState* state, JSDOMGlobalObject* globalObject, $implType& impl)\n"); + push(@implContent, "{\n"); + push(@implContent, " return wrap(state, globalObject, impl);\n"); push(@implContent, "}\n\n"); } - if ((!$hasParent or $interface->extendedAttributes->{"JSGenerateToNativeObject"}) and !$interface->extendedAttributes->{"JSCustomToNativeObject"}) { - push(@implContent, "$implType* to${interfaceName}(JSC::JSValue value)\n"); + if (ShouldGenerateToWrapped($hasParent, $interface) and !$interface->extendedAttributes->{JSCustomToNativeObject}) { + push(@implContent, "$implType* ${className}::toWrapped(JSC::VM& vm, JSC::JSValue value)\n"); push(@implContent, "{\n"); - push(@implContent, " return value.inherits(${className}::info()) ? &jsCast<$className*>(value)->impl() : 0"); - push(@implContent, ";\n}\n"); + push(@implContent, " if (auto* wrapper = " . GetCastingHelperForThisObject($interface) . "(vm, value))\n"); + push(@implContent, " return &wrapper->wrapped();\n"); + push(@implContent, " return nullptr;\n"); + push(@implContent, "}\n"); } push(@implContent, "\n}\n"); @@ -2885,30 +4393,160 @@ END push(@implContent, "\n#endif // ${conditionalString}\n") if $conditionalString; } +sub GenerateSerializerFunction +{ + my ($interface, $className) = @_; + + my $interfaceName = $interface->type->name; + + my $parentSerializerInterface = 0; + if ($interface->serializable->hasInherit) { + $codeGenerator->ForAllParents($interface, sub { + my $parentInterface = shift; + if ($parentInterface->serializable && !$parentSerializerInterface) { + $parentSerializerInterface = $parentInterface; + } + }, 0); + die "Failed to find parent interface with \"serializer\" for \"inherit\" serializer in $interfaceName\n" if !$parentSerializerInterface; + } + + my @serializedAttributes = (); + + foreach my $attributeName (@{$interface->serializable->attributes}) { + my $foundAttribute = 0; + foreach my $attribute (@{$interface->attributes}) { + if ($attributeName eq $attribute->name) { + $foundAttribute = 1; + if ($codeGenerator->IsSerializableAttribute($interface, $attribute)) { + push(@serializedAttributes, $attribute); + last; + } + die "Explicit \"serializer\" attribute \"$attributeName\" is not serializable\n" if !$interface->serializable->hasAttribute; + last; + } + } + die "Failed to find \"serializer\" attribute \"$attributeName\" in $interfaceName\n" if !$foundAttribute; + } + + my $serializerFunctionName = "toJSON"; + my $serializerNativeFunctionName = $codeGenerator->WK_lcfirst($className) . "PrototypeFunction" . $codeGenerator->WK_ucfirst($serializerFunctionName); + + AddToImplIncludes("<runtime/ObjectConstructor.h>"); + + push(@implContent, "JSC::JSObject* JS${interfaceName}::serialize(ExecState* state, JS${interfaceName}* thisObject, ThrowScope& throwScope)\n"); + push(@implContent, "{\n"); + push(@implContent, " auto& vm = state->vm();\n"); + + if ($interface->serializable->hasInherit) { + my $parentSerializerInterfaceName = $parentSerializerInterface->type->name; + push(@implContent, " auto* result = JS${parentSerializerInterfaceName}::serialize(state, thisObject, throwScope);\n"); + } else { + push(@implContent, " auto* result = constructEmptyObject(state);\n"); + } + push(@implContent, "\n"); + + foreach my $attribute (@serializedAttributes) { + my $name = $attribute->name; + my $getFunctionName = GetAttributeGetterName($interface, $className, $attribute); + push(@implContent, " auto ${name}Value = ${getFunctionName}Getter(*state, *thisObject, throwScope);\n"); + push(@implContent, " ASSERT(!throwScope.exception());\n"); + push(@implContent, " result->putDirect(vm, Identifier::fromString(&vm, \"${name}\"), ${name}Value);\n"); + push(@implContent, "\n"); + } + + push(@implContent, " return result;\n"); + push(@implContent, "}\n"); + push(@implContent, "\n"); + + push(@implContent, "static inline EncodedJSValue ${serializerNativeFunctionName}Caller(ExecState* state, JS${interfaceName}* thisObject, JSC::ThrowScope& throwScope)\n"); + push(@implContent, "{\n"); + push(@implContent, " return JSValue::encode(JS${interfaceName}::serialize(state, thisObject, throwScope));\n"); + push(@implContent, "}\n"); + push(@implContent, "\n"); + push(@implContent, "EncodedJSValue JSC_HOST_CALL ${serializerNativeFunctionName}(ExecState* state)\n"); + push(@implContent, "{\n"); + push(@implContent, " return BindingCaller<JS$interfaceName>::callOperation<${serializerNativeFunctionName}Caller>(state, \"$serializerFunctionName\");\n"); + push(@implContent, "}\n"); + push(@implContent, "\n"); +} + +sub GenerateCallWithUsingReferences +{ + my ($callWith, $outputArray, $returnValue, $function) = @_; + + my $statePointer = "&state"; + my $stateReference = "state"; + my $globalObject = "jsCast<JSDOMGlobalObject*>(state.lexicalGlobalObject())"; + + return GenerateCallWith($callWith, $outputArray, $returnValue, $function, $statePointer, $stateReference, $globalObject); +} + +# FIXME: We should remove GenerateCallWithUsingPointers and combine GenerateCallWithUsingReferences and GenerateCallWith +sub GenerateCallWithUsingPointers +{ + my ($callWith, $outputArray, $returnValue, $function) = @_; + + my $statePointer = "state"; + my $stateReference = "*state"; + my $globalObject = "jsCast<JSDOMGlobalObject*>(state->lexicalGlobalObject())"; + + return GenerateCallWith($callWith, $outputArray, $returnValue, $function, $statePointer, $stateReference, $globalObject); +} + sub GenerateCallWith { - my $callWith = shift; + my ($callWith, $outputArray, $returnValue, $function, $statePointer, $stateReference, $globalObject) = @_; + return () unless $callWith; - my $outputArray = shift; - my $returnValue = shift; - my $function = shift; my @callWithArgs; - if ($codeGenerator->ExtendedAttributeContains($callWith, "ScriptState")) { - push(@callWithArgs, "exec"); - } + push(@callWithArgs, $stateReference) if $codeGenerator->ExtendedAttributeContains($callWith, "ScriptState"); + push(@callWithArgs, "*${globalObject}") if $codeGenerator->ExtendedAttributeContains($callWith, "GlobalObject"); if ($codeGenerator->ExtendedAttributeContains($callWith, "ScriptExecutionContext")) { - push(@$outputArray, " ScriptExecutionContext* scriptContext = jsCast<JSDOMGlobalObject*>(exec->lexicalGlobalObject())->scriptExecutionContext();\n"); - push(@$outputArray, " if (!scriptContext)\n"); + push(@$outputArray, " auto* context = $globalObject->scriptExecutionContext();\n"); + push(@$outputArray, " if (!context)\n"); push(@$outputArray, " return" . ($returnValue ? " " . $returnValue : "") . ";\n"); - push(@callWithArgs, "scriptContext"); + push(@callWithArgs, "*context"); + } + if ($codeGenerator->ExtendedAttributeContains($callWith, "Document")) { + $implIncludes{"Document.h"} = 1; + push(@$outputArray, " auto* context = $globalObject->scriptExecutionContext();\n"); + push(@$outputArray, " if (!context)\n"); + push(@$outputArray, " return" . ($returnValue ? " " . $returnValue : "") . ";\n"); + push(@$outputArray, " ASSERT(context->isDocument());\n"); + push(@$outputArray, " auto& document = downcast<Document>(*context);\n"); + push(@callWithArgs, "document"); + } + if ($codeGenerator->ExtendedAttributeContains($callWith, "CallerDocument")) { + $implIncludes{"Document.h"} = 1; + $implIncludes{"JSDOMWindowBase.h"} = 1; + push(@$outputArray, " auto* document = callerDOMWindow($statePointer).document();\n"); + push(@$outputArray, " if (!document)\n"); + push(@$outputArray, " return" . ($returnValue ? " " . $returnValue : "") . ";\n"); + push(@callWithArgs, "*document"); } if ($function and $codeGenerator->ExtendedAttributeContains($callWith, "ScriptArguments")) { - push(@$outputArray, " RefPtr<ScriptArguments> scriptArguments(createScriptArguments(exec, " . @{$function->parameters} . "));\n"); - $implIncludes{"ScriptArguments.h"} = 1; - $implIncludes{"ScriptCallStackFactory.h"} = 1; - push(@callWithArgs, "scriptArguments.release()"); + push(@$outputArray, " Ref<Inspector::ScriptArguments> scriptArguments(Inspector::createScriptArguments($statePointer, " . @{$function->arguments} . "));\n"); + $implIncludes{"<inspector/ScriptArguments.h>"} = 1; + $implIncludes{"<inspector/ScriptCallStackFactory.h>"} = 1; + push(@callWithArgs, "WTFMove(scriptArguments)"); + } + if ($codeGenerator->ExtendedAttributeContains($callWith, "ActiveWindow")) { + $implIncludes{"JSDOMWindowBase.h"} = 1; + push(@callWithArgs, "activeDOMWindow($statePointer)"); + } + if ($codeGenerator->ExtendedAttributeContains($callWith, "FirstWindow")) { + $implIncludes{"JSDOMWindowBase.h"} = 1; + push(@callWithArgs, "firstDOMWindow($statePointer)"); + + } + if ($codeGenerator->ExtendedAttributeContains($callWith, "CallerWindow")) { + $implIncludes{"JSDOMWindowBase.h"} = 1; + push(@callWithArgs, "callerDOMWindow($statePointer)"); + + } + return @callWithArgs; } @@ -2918,795 +4556,1132 @@ sub GenerateArgumentsCountCheck my $function = shift; my $interface = shift; - my $numMandatoryParams = @{$function->parameters}; - foreach my $param (reverse(@{$function->parameters})) { - if ($param->isOptional or $param->isVariadic) { - $numMandatoryParams--; + my $numMandatoryArguments = @{$function->arguments}; + foreach my $argument (reverse(@{$function->arguments})) { + if ($argument->isOptional or $argument->isVariadic) { + $numMandatoryArguments--; } else { last; } } - if ($numMandatoryParams >= 1) - { - push(@$outputArray, " if (exec->argumentCount() < $numMandatoryParams)\n"); - push(@$outputArray, " return throwVMError(exec, createNotEnoughArgumentsError(exec));\n"); + if ($numMandatoryArguments >= 1) { + push(@$outputArray, " if (UNLIKELY(state->argumentCount() < $numMandatoryArguments))\n"); + push(@$outputArray, " return throwVMError(state, throwScope, createNotEnoughArgumentsError(state));\n"); } } -sub GenerateParametersCheck +my %automaticallyGeneratedDefaultValues = ( + "any" => "undefined", + + # toString() will convert undefined to the string "undefined"; + # (note that this optimizes a behavior that is almost never useful) + "DOMString" => "\"undefined\"", + "USVString" => "\"undefined\"", + + # JSValue::toBoolean() will convert undefined to false. + "boolean" => "false", + + # JSValue::toInt*() / JSValue::toUint*() will convert undefined to 0. + "byte" => "0", + "long long" => "0", + "long" => "0", + "octet" => "0", + "short" => "0", + "unsigned long long" => "0", + "unsigned long" => "0", + "unsigned short" => "0", + + # toNumber() / toFloat() convert undefined to NaN. + "double" => "NaN", + "float" => "NaN", + "unrestricted double" => "NaN", + "unrestricted float" => "NaN", +); + +sub WillConvertUndefinedToDefaultParameterValue { - my $outputArray = shift; - my $function = shift; - my $interface = shift; - my $numParameters = shift; - my $interfaceName = shift; - my $functionImplementationName = shift; - my $svgPropertyType = shift; - my $svgPropertyOrListPropertyType = shift; - my $svgListPropertyType = shift; + my ($parameterType, $defaultValue) = @_; + + my $automaticallyGeneratedDefaultValue = $automaticallyGeneratedDefaultValues{$parameterType->name}; + return 1 if defined $automaticallyGeneratedDefaultValue && $automaticallyGeneratedDefaultValue eq $defaultValue; - my $argsIndex = 0; - my $hasOptionalArguments = 0; - my $raisesException = $function->signature->extendedAttributes->{"RaisesException"}; + return 1 if $defaultValue eq "null" && $codeGenerator->IsWrapperType($parameterType); + return 1 if $defaultValue eq "[]" && $codeGenerator->IsDictionaryType($parameterType); + return 0; +} + +sub NeedsExplicitPropagateExceptionCall +{ + my ($function) = @_; + + return 0 unless $function->extendedAttributes->{MayThrowException}; + + return 1 if $function->type && $function->type->name eq "void"; + return 1 if IsReturningPromise($function); + + return 0; +} + +sub GenerateParametersCheck +{ + my ($outputArray, $function, $interface, $functionImplementationName) = @_; + + my $interfaceName = $interface->type->name; + my $visibleInterfaceName = $codeGenerator->GetVisibleInterfaceName($interface); my @arguments; my $functionName; - my $implementedBy = $function->signature->extendedAttributes->{"ImplementedBy"}; + my $implementedBy = $function->extendedAttributes->{ImplementedBy}; + my $numArguments = @{$function->arguments}; + my $conditional = $function->extendedAttributes->{Conditional}; + if ($implementedBy) { - AddToImplIncludes("${implementedBy}.h"); - unshift(@arguments, "&impl") if !$function->isStatic; - $functionName = "${implementedBy}::${functionImplementationName}"; + AddToImplIncludes("${implementedBy}.h", $conditional); + unshift(@arguments, "impl") if !$function->isStatic; + $functionName = "WebCore::${implementedBy}::${functionImplementationName}"; } elsif ($function->isStatic) { $functionName = "${interfaceName}::${functionImplementationName}"; - } elsif ($svgPropertyOrListPropertyType and !$svgListPropertyType) { - $functionName = "podImpl.${functionImplementationName}"; } else { $functionName = "impl.${functionImplementationName}"; } - if (!$function->signature->extendedAttributes->{"Constructor"}) { - push(@arguments, GenerateCallWith($function->signature->extendedAttributes->{"CallWith"}, \@$outputArray, "JSValue::encode(jsUndefined())", $function)); + my $quotedFunctionName; + if (!$function->extendedAttributes->{Constructor}) { + my $name = $function->name; + $quotedFunctionName = "\"$name\""; + push(@arguments, GenerateCallWithUsingPointers($function->extendedAttributes->{CallWith}, \@$outputArray, "JSValue::encode(jsUndefined())", $function)); + } else { + $quotedFunctionName = "nullptr"; } - $implIncludes{"ExceptionCode.h"} = 1; - $implIncludes{"JSDOMBinding.h"} = 1; + my $argumentIndex = 0; + foreach my $argument (@{$function->arguments}) { + my $type = $argument->type; - foreach my $parameter (@{$function->parameters}) { - my $argType = $parameter->type; - - # Optional arguments with [Optional] should generate an early call with fewer arguments. - # Optional arguments with [Optional=...] should not generate the early call. - # Optional Dictionary arguments always considered to have default of empty dictionary. - my $optional = $parameter->isOptional; - my $defaultAttribute = $parameter->extendedAttributes->{"Default"}; - if ($optional && !$defaultAttribute && $argType ne "Dictionary" && !$codeGenerator->IsCallbackInterface($parameter->type)) { - # Generate early call if there are enough parameters. - if (!$hasOptionalArguments) { - push(@$outputArray, "\n size_t argsCount = exec->argumentCount();\n"); - $hasOptionalArguments = 1; - } - push(@$outputArray, " if (argsCount <= $argsIndex) {\n"); + die "Optional arguments of non-nullable wrapper types are not supported" if $argument->isOptional && !$type->isNullable && $codeGenerator->IsWrapperType($type); + die "Optional arguments preceding variadic arguments are not supported" if ($argument->isOptional && @{$function->arguments}[$numArguments - 1]->isVariadic); + + if ($argument->isOptional && !defined($argument->default)) { + # As per Web IDL, optional dictionary arguments are always considered to have a default value of an empty dictionary, unless otherwise specified. + $argument->default("[]") if $codeGenerator->IsDictionaryType($type); - my @optionalCallbackArguments = @arguments; - push(@optionalCallbackArguments, "ec") if $raisesException; - my $functionString = "$functionName(" . join(", ", @optionalCallbackArguments) . ")"; - GenerateImplementationFunctionCall($function, $functionString, " " x 2, $svgPropertyType, $interfaceName); - push(@$outputArray, " }\n\n"); + # Treat undefined the same as an empty sequence Or frozen array. + $argument->default("[]") if $codeGenerator->IsSequenceOrFrozenArrayType($type); + + # We use undefined as default value for optional arguments of type 'any' unless specified otherwise. + $argument->default("undefined") if $type->name eq "any"; + + # We use the null string as default value for arguments of type DOMString unless specified otherwise. + $argument->default("null") if $codeGenerator->IsStringType($type); + + # As per Web IDL, passing undefined for a nullable argument is treated as null. Therefore, use null as + # default value for nullable arguments unless otherwise specified. + $argument->default("null") if $type->isNullable; + + # For callback arguments, the generated bindings treat undefined as null, so use null as implicit default value. + $argument->default("null") if $codeGenerator->IsCallbackInterface($type) || $codeGenerator->IsCallbackFunction($type); } - my $name = $parameter->name; - - if ($argType eq "XPathNSResolver") { - push(@$outputArray, " RefPtr<XPathNSResolver> customResolver;\n"); - push(@$outputArray, " XPathNSResolver* resolver = toXPathNSResolver(exec->argument($argsIndex));\n"); - push(@$outputArray, " if (!resolver) {\n"); - push(@$outputArray, " customResolver = JSCustomXPathNSResolver::create(exec, exec->argument($argsIndex));\n"); - push(@$outputArray, " if (exec->hadException())\n"); - push(@$outputArray, " return JSValue::encode(jsUndefined());\n"); - push(@$outputArray, " resolver = customResolver.get();\n"); - push(@$outputArray, " }\n"); - } elsif ($codeGenerator->IsCallbackInterface($parameter->type)) { - my $callbackClassName = GetCallbackClassName($argType); - $implIncludes{"$callbackClassName.h"} = 1; - if ($optional) { - push(@$outputArray, " RefPtr<$argType> $name;\n"); - push(@$outputArray, " if (!exec->argument($argsIndex).isUndefinedOrNull()) {\n"); - push(@$outputArray, " if (!exec->uncheckedArgument($argsIndex).isFunction())\n"); - push(@$outputArray, " return throwVMTypeError(exec);\n"); - if ($function->isStatic) { - AddToImplIncludes("CallbackFunction.h"); - push(@$outputArray, " $name = createFunctionOnlyCallback<${callbackClassName}>(exec, jsCast<JSDOMGlobalObject*>(exec->lexicalGlobalObject()), exec->uncheckedArgument($argsIndex));\n"); - } else { - push(@$outputArray, " $name = ${callbackClassName}::create(asObject(exec->uncheckedArgument($argsIndex)), castedThis->globalObject());\n"); - } - push(@$outputArray, " }\n"); - } else { - push(@$outputArray, " if (!exec->argument($argsIndex).isFunction())\n"); - push(@$outputArray, " return throwVMTypeError(exec);\n"); - if ($function->isStatic) { - AddToImplIncludes("CallbackFunction.h"); - push(@$outputArray, " RefPtr<$argType> $name = createFunctionOnlyCallback<${callbackClassName}>(exec, jsCast<JSDOMGlobalObject*>(exec->lexicalGlobalObject()), exec->uncheckedArgument($argsIndex));\n"); - } else { - push(@$outputArray, " RefPtr<$argType> $name = ${callbackClassName}::create(asObject(exec->uncheckedArgument($argsIndex)), castedThis->globalObject());\n"); - } - } - } elsif ($parameter->extendedAttributes->{"Clamp"}) { - my $nativeValue = "${name}NativeValue"; - push(@$outputArray, " $argType $name = 0;\n"); - push(@$outputArray, " double $nativeValue = exec->argument($argsIndex).toNumber(exec);\n"); - push(@$outputArray, " if (exec->hadException())\n"); - push(@$outputArray, " return JSValue::encode(jsUndefined());\n\n"); - push(@$outputArray, " if (!std::isnan($nativeValue))\n"); - push(@$outputArray, " $name = clampTo<$argType>($nativeValue);\n\n"); - } elsif ($parameter->isVariadic) { - my $nativeElementType; - if ($argType eq "DOMString") { - $nativeElementType = "String"; - } else { - $nativeElementType = GetNativeType($argType); - if ($nativeElementType =~ />$/) { - $nativeElementType .= " "; - } - } + my $name = $argument->name; + my $value = $name; - if (!IsNativeType($argType)) { - push(@$outputArray, " Vector<$nativeElementType> $name;\n"); - push(@$outputArray, " for (unsigned i = $argsIndex, count = exec->argumentCount(); i < count; ++i) {\n"); - push(@$outputArray, " if (!exec->uncheckedArgument(i).inherits(JS${argType}::info()))\n"); - push(@$outputArray, " return throwVMTypeError(exec);\n"); - push(@$outputArray, " $name.append(to$argType(exec->uncheckedArgument(i)));\n"); - push(@$outputArray, " }\n") - } else { - push(@$outputArray, " Vector<$nativeElementType> $name = toNativeArguments<$nativeElementType>(exec, $argsIndex);\n"); - # Check if the type conversion succeeded. - push(@$outputArray, " if (exec->hadException())\n"); - push(@$outputArray, " return JSValue::encode(jsUndefined());\n"); - } + if ($argument->isVariadic) { + AddToImplIncludes("JSDOMConvertVariadic.h", $conditional); + AddToImplIncludesForIDLType($type, $conditional); + + my $IDLType = GetIDLType($interface, $type); - } elsif ($codeGenerator->IsEnumType($argType)) { - $implIncludes{"<runtime/Error.h>"} = 1; + push(@$outputArray, " auto ${name} = convertVariadicArguments<${IDLType}>(*state, ${argumentIndex});\n"); + push(@$outputArray, " RETURN_IF_EXCEPTION(throwScope, encodedJSValue());\n"); + + $value = "WTFMove(${name}.arguments.value())"; + + } elsif ($codeGenerator->IsEnumType($type)) { + AddToImplIncludes("<runtime/Error.h>", $conditional); + + my $className = GetEnumerationClassName($type, $interface); + my $nativeType = $className; + my $optionalValue = "optionalValue"; + my $defineOptionalValue = "auto optionalValue"; + my $indent = ""; - my $argValue = "exec->argument($argsIndex)"; - push(@$outputArray, " const String ${name}(${argValue}.isEmpty() ? String() : ${argValue}.toString(exec)->value(exec));\n"); - push(@$outputArray, " if (exec->hadException())\n"); - push(@$outputArray, " return JSValue::encode(jsUndefined());\n"); + die "Variadic argument is already handled here" if $argument->isVariadic; + my $argumentLookupMethod = $argument->isOptional ? "argument" : "uncheckedArgument"; - my @enumValues = $codeGenerator->ValidEnumValues($argType); - my @enumChecks = (); - foreach my $enumValue (@enumValues) { - push(@enumChecks, "${name} != \"$enumValue\""); + if ($argument->isOptional && !defined($argument->default)) { + $nativeType = "std::optional<$className>"; + $optionalValue = $name; + $defineOptionalValue = $name; } - push (@$outputArray, " if (" . join(" && ", @enumChecks) . ")\n"); - push (@$outputArray, " return throwVMTypeError(exec);\n"); - } else { - # If the "StrictTypeChecking" extended attribute is present, and the argument's type is an - # interface type, then if the incoming value does not implement that interface, a TypeError - # is thrown rather than silently passing NULL to the C++ code. - # Per the Web IDL and ECMAScript semantics, incoming values can always be converted to both - # strings and numbers, so do not throw TypeError if the argument is of these types. - if ($function->signature->extendedAttributes->{"StrictTypeChecking"}) { - $implIncludes{"<runtime/Error.h>"} = 1; - - my $argValue = "exec->argument($argsIndex)"; - if ($codeGenerator->IsWrapperType($argType)) { - push(@$outputArray, " if (exec->argumentCount() > $argsIndex && !${argValue}.isUndefinedOrNull() && !${argValue}.inherits(JS${argType}::info()))\n"); - push(@$outputArray, " return throwVMTypeError(exec);\n"); + + push(@$outputArray, " auto ${name}Value = state->$argumentLookupMethod($argumentIndex);\n"); + push(@$outputArray, " $nativeType $name;\n"); + + if ($argument->isOptional) { + if (!defined $argument->default) { + push(@$outputArray, " if (!${name}Value.isUndefined()) {\n"); + } else { + push(@$outputArray, " if (${name}Value.isUndefined())\n"); + push(@$outputArray, " $name = " . GenerateDefaultValue($interface, $argument, $argument->type, $argument->default) . ";\n"); + push(@$outputArray, " else {\n"); } + $indent = " "; } - push(@$outputArray, " " . GetNativeTypeFromSignature($parameter) . " $name(" . JSValueToNative($parameter, $optional && $defaultAttribute && $defaultAttribute eq "NullString" ? "argumentOrNull(exec, $argsIndex)" : "exec->argument($argsIndex)") . ");\n"); + $implIncludes{"JS$className.h"} = 1 if $codeGenerator->IsExternalEnumType($type); + push(@$outputArray, "$indent $defineOptionalValue = parseEnumeration<$className>(*state, ${name}Value);\n"); + push(@$outputArray, "$indent RETURN_IF_EXCEPTION(throwScope, encodedJSValue());\n"); + push(@$outputArray, "$indent if (UNLIKELY(!$optionalValue))\n"); + push(@$outputArray, "$indent return throwArgumentMustBeEnumError(*state, throwScope, $argumentIndex, \"$name\", \"$visibleInterfaceName\", $quotedFunctionName, expectedEnumerationValues<$className>());\n"); + push(@$outputArray, "$indent $name = optionalValue.value();\n") if $optionalValue ne $name; - # If a parameter is "an index" and it's negative it should throw an INDEX_SIZE_ERR exception. - # But this needs to be done in the bindings, because the type is unsigned and the fact that it - # was negative will be lost by the time we're inside the DOM. - if ($parameter->extendedAttributes->{"IsIndex"}) { - push(@$outputArray, " if ($name < 0) {\n"); - push(@$outputArray, " setDOMException(exec, INDEX_SIZE_ERR);\n"); - push(@$outputArray, " return JSValue::encode(jsUndefined());\n"); - push(@$outputArray, " }\n"); - } + push(@$outputArray, " }\n") if $indent ne ""; + } else { + my $outer; + my $inner; + my $nativeType = GetNativeType($interface, $argument->type); + + die "Variadic argument is already handled here" if $argument->isVariadic; + my $argumentLookupMethod = $argument->isOptional ? "argument" : "uncheckedArgument"; + + if ($argument->isOptional && defined($argument->default) && !WillConvertUndefinedToDefaultParameterValue($type, $argument->default)) { + my $defaultValue = $argument->default; - # Check if the type conversion succeeded. - push(@$outputArray, " if (exec->hadException())\n"); - push(@$outputArray, " return JSValue::encode(jsUndefined());\n"); + $defaultValue = GenerateDefaultValue($interface, $argument, $argument->type, $argument->default); - if ($codeGenerator->IsSVGTypeNeedingTearOff($argType) and not $interfaceName =~ /List$/) { - push(@$outputArray, " if (!$name) {\n"); - push(@$outputArray, " setDOMException(exec, TYPE_MISMATCH_ERR);\n"); - push(@$outputArray, " return JSValue::encode(jsUndefined());\n"); - push(@$outputArray, " }\n"); + $outer = "state->$argumentLookupMethod($argumentIndex).isUndefined() ? $defaultValue : "; + $inner = "state->uncheckedArgument($argumentIndex)"; + } elsif ($argument->isOptional && !defined($argument->default)) { + # Use std::optional<>() for optional arguments that are missing or undefined and that do not have a default value in the IDL. + $outer = "state->$argumentLookupMethod($argumentIndex).isUndefined() ? std::optional<$nativeType>() : "; + $inner = "state->uncheckedArgument($argumentIndex)"; + } else { + $outer = ""; + $inner = "state->$argumentLookupMethod($argumentIndex)"; } + + my $globalObjectReference = $function->isStatic ? "*jsCast<JSDOMGlobalObject*>(state->lexicalGlobalObject())" : "*castedThis->globalObject()"; + my $argumentExceptionThrower = GetArgumentExceptionThrower($interface, $argument, $argumentIndex, $quotedFunctionName); + + my ($nativeValue, $mayThrowException) = JSValueToNative($interface, $argument, $inner, $conditional, "state", "*state", "*castedThis", $globalObjectReference, $argumentExceptionThrower); + + push(@$outputArray, " auto $name = ${outer}${nativeValue};\n"); + push(@$outputArray, " RETURN_IF_EXCEPTION(throwScope, encodedJSValue());\n") if $mayThrowException; + + $value = PassArgumentExpression($name, $argument); } - if ($argType eq "NodeFilter" || ($codeGenerator->IsTypedArrayType($argType) and not $argType eq "ArrayBuffer")) { - push @arguments, "$name.get()"; - } elsif ($codeGenerator->IsSVGTypeNeedingTearOff($argType) and not $interfaceName =~ /List$/) { - push @arguments, "$name->propertyReference()"; - } else { - push @arguments, $name; + push(@arguments, $value); + $argumentIndex++; + } + + push(@arguments, "WTFMove(promise)") if IsReturningPromise($function); + + my $functionString = "$functionName(" . join(", ", @arguments) . ")"; + $functionString = "propagateException(*state, throwScope, $functionString)" if NeedsExplicitPropagateExceptionCall($function); + + return ($functionString, scalar @arguments); +} + +sub GenerateDictionaryHeader +{ + my ($object, $dictionary, $className, $enumerations, $otherDictionaries) = @_; + + # - Add default header template and header protection. + push(@headerContentHeader, GenerateHeaderContentHeader($dictionary)); + + $headerIncludes{"$className.h"} = 1; + $headerIncludes{"JSDOMConvert.h"} = 1; + + push(@headerContent, "\nnamespace WebCore {\n\n"); + push(@headerContent, GenerateDictionaryHeaderContent($dictionary, $className)); + push(@headerContent, GenerateEnumerationsHeaderContent($dictionary, $enumerations)); + push(@headerContent, GenerateDictionariesHeaderContent($dictionary, $otherDictionaries)) if $otherDictionaries; + push(@headerContent, "} // namespace WebCore\n"); + + my $conditionalString = $codeGenerator->GenerateConditionalString($dictionary); + push(@headerContent, "\n#endif // ${conditionalString}\n") if $conditionalString; + + # - Generate dependencies. + if ($writeDependencies) { + my @ancestors; + my $parentType = $dictionary->parentType; + while (defined($parentType)) { + push(@ancestors, $parentType->name) if $codeGenerator->IsExternalDictionaryType($parentType); + my $parentDictionary = $codeGenerator->GetDictionaryByType($parentType); + assert("Unable to find definition for dictionary named '" . $parentType->name . "'!") unless $parentDictionary; + $parentType = $parentDictionary->parentType; } - $argsIndex++; + push(@depsContent, "$className.h : ", join(" ", map { "$_.idl" } @ancestors), "\n"); + push(@depsContent, map { "$_.idl :\n" } @ancestors); } +} + +sub GenerateDictionaryImplementation +{ + my ($object, $dictionary, $className, $enumerations, $otherDictionaries) = @_; + + # - Add default header template + push(@implContentHeader, GenerateImplementationContentHeader($dictionary)); - push(@arguments, "ec") if $raisesException; + push(@implContent, "\nusing namespace JSC;\n\n"); + push(@implContent, "namespace WebCore {\n\n"); + push(@implContent, GenerateDictionaryImplementationContent($dictionary, $className)); + push(@implContent, GenerateEnumerationsImplementationContent($dictionary, $enumerations)); + push(@implContent, GenerateDictionariesImplementationContent($dictionary, $otherDictionaries)) if $otherDictionaries; + push(@implContent, "} // namespace WebCore\n"); - return ("$functionName(" . join(", ", @arguments) . ")", scalar @arguments); + my $conditionalString = $codeGenerator->GenerateConditionalString($dictionary); + push(@implContent, "\n#endif // ${conditionalString}\n") if $conditionalString; } -sub GenerateCallbackHeader +sub GenerateCallbackFunctionHeader { - my $object = shift; - my $interface = shift; + my ($object, $callbackFunction, $enumerations, $dictionaries) = @_; - my $interfaceName = $interface->name; - my $className = "JS$interfaceName"; + push(@headerContentHeader, GenerateHeaderContentHeader($callbackFunction)); - # - Add default header template and header protection - push(@headerContentHeader, GenerateHeaderContentHeader($interface)); + push(@headerContent, "\nnamespace WebCore {\n\n"); + + my @functions = (); + push(@functions, $callbackFunction->operation); + my @constants = (); - $headerIncludes{"ActiveDOMCallback.h"} = 1; - $headerIncludes{"$interfaceName.h"} = 1; - $headerIncludes{"JSCallbackData.h"} = 1; - $headerIncludes{"<wtf/Forward.h>"} = 1; + $object->GenerateCallbackHeaderContent($callbackFunction, \@functions, \@constants, \@headerContent, \%headerIncludes); + + push(@headerContent, GenerateEnumerationsHeaderContent($callbackFunction, $enumerations)); + push(@headerContent, GenerateDictionariesHeaderContent($callbackFunction, $dictionaries)); + + push(@headerContent, "} // namespace WebCore\n"); + + my $conditionalString = $codeGenerator->GenerateConditionalString($callbackFunction); + push(@headerContent, "\n#endif // ${conditionalString}\n") if $conditionalString; +} + +sub GenerateCallbackFunctionImplementation +{ + my ($object, $callbackFunction, $enumerations, $dictionaries) = @_; + + push(@implContentHeader, GenerateImplementationContentHeader($callbackFunction)); + + push(@implContent, "\nusing namespace JSC;\n\n"); + push(@implContent, "namespace WebCore {\n\n"); + + push(@implContent, GenerateEnumerationsImplementationContent($callbackFunction, $enumerations)); + push(@implContent, GenerateDictionariesImplementationContent($callbackFunction, $dictionaries)); + + my @functions = (); + push(@functions, $callbackFunction->operation); + my @constants = (); + + $object->GenerateCallbackImplementationContent($callbackFunction, \@functions, \@constants, \@implContent, \%implIncludes); + + push(@implContent, "} // namespace WebCore\n"); + + my $conditionalString = $codeGenerator->GenerateConditionalString($callbackFunction); + push(@implContent, "\n#endif // ${conditionalString}\n") if $conditionalString; +} + +sub GenerateCallbackInterfaceHeader +{ + my ($object, $callbackInterface, $enumerations, $dictionaries) = @_; + + push(@headerContentHeader, GenerateHeaderContentHeader($callbackInterface)); push(@headerContent, "\nnamespace WebCore {\n\n"); - push(@headerContent, "class $className : public $interfaceName, public ActiveDOMCallback {\n"); - push(@headerContent, "public:\n"); + + $object->GenerateCallbackHeaderContent($callbackInterface, $callbackInterface->functions, $callbackInterface->constants, \@headerContent, \%headerIncludes); + + push(@headerContent, GenerateEnumerationsHeaderContent($callbackInterface, $enumerations)); + push(@headerContent, GenerateDictionariesHeaderContent($callbackInterface, $dictionaries)); + + push(@headerContent, "} // namespace WebCore\n"); + + my $conditionalString = $codeGenerator->GenerateConditionalString($callbackInterface); + push(@headerContent, "\n#endif // ${conditionalString}\n") if $conditionalString; +} + +sub GenerateCallbackInterfaceImplementation +{ + my ($object, $callbackInterface, $enumerations, $dictionaries) = @_; + + push(@implContentHeader, GenerateImplementationContentHeader($callbackInterface)); + + push(@implContent, "\nusing namespace JSC;\n\n"); + push(@implContent, "namespace WebCore {\n\n"); + + push(@implContent, GenerateEnumerationsImplementationContent($callbackInterface, $enumerations)); + push(@implContent, GenerateDictionariesImplementationContent($callbackInterface, $dictionaries)); + + $object->GenerateCallbackImplementationContent($callbackInterface, $callbackInterface->functions, $callbackInterface->constants, \@implContent, \%implIncludes); + + push(@implContent, "} // namespace WebCore\n"); + + my $conditionalString = $codeGenerator->GenerateConditionalString($callbackInterface); + push(@implContent, "\n#endif // ${conditionalString}\n") if $conditionalString; +} + +sub GenerateCallbackHeaderContent +{ + my ($object, $interfaceOrCallback, $functions, $constants, $contentRef, $includesRef) = @_; + + my $name = $interfaceOrCallback->type->name; + my $callbackDataType = GetJSCallbackDataType($interfaceOrCallback); + my $className = "JS${name}"; + + $includesRef->{"ActiveDOMCallback.h"} = 1; + $includesRef->{"JSCallbackData.h"} = 1; + $includesRef->{"<wtf/Forward.h>"} = 1; + $includesRef->{"${name}.h"} = 1; + + push(@$contentRef, "class $className : public ${name}, public ActiveDOMCallback {\n"); + push(@$contentRef, "public:\n"); # The static create() method. - push(@headerContent, " static PassRefPtr<$className> create(JSC::JSObject* callback, JSDOMGlobalObject* globalObject)\n"); - push(@headerContent, " {\n"); - push(@headerContent, " return adoptRef(new $className(callback, globalObject));\n"); - push(@headerContent, " }\n\n"); + push(@$contentRef, " static Ref<$className> create(JSC::JSObject* callback, JSDOMGlobalObject* globalObject)\n"); + push(@$contentRef, " {\n"); + push(@$contentRef, " return adoptRef(*new ${className}(callback, globalObject));\n"); + push(@$contentRef, " }\n\n"); - # ScriptExecutionContext - push(@headerContent, " virtual ScriptExecutionContext* scriptExecutionContext() const { return ContextDestructionObserver::scriptExecutionContext(); }\n\n"); + push(@$contentRef, " virtual ScriptExecutionContext* scriptExecutionContext() const { return ContextDestructionObserver::scriptExecutionContext(); }\n\n"); - # Destructor - push(@headerContent, " virtual ~$className();\n"); + push(@$contentRef, " virtual ~$className();\n"); - if ($interface->extendedAttributes->{"CallbackNeedsOperatorEqual"}) { - push(@headerContent, " virtual bool operator==(const $interfaceName&) const;\n\n") - } + push(@$contentRef, " ${callbackDataType}* callbackData() { return m_data; }\n"); + + push(@$contentRef, " static JSC::JSValue getConstructor(JSC::VM&, const JSC::JSGlobalObject*);\n") if @{$constants}; + + push(@$contentRef, " virtual bool operator==(const ${name}&) const;\n\n") if $interfaceOrCallback->extendedAttributes->{CallbackNeedsOperatorEqual}; # Functions - my $numFunctions = @{$interface->functions}; + my $numFunctions = @{$functions}; if ($numFunctions > 0) { - push(@headerContent, "\n // Functions\n"); - foreach my $function (@{$interface->functions}) { - my @params = @{$function->parameters}; - if (!$function->signature->extendedAttributes->{"Custom"} && - !(GetNativeType($function->signature->type) eq "bool")) { - push(@headerContent, " COMPILE_ASSERT(false)"); + push(@$contentRef, "\n // Functions\n"); + foreach my $function (@{$functions}) { + my @arguments = (); + foreach my $argument (@{$function->arguments}) { + push(@arguments, GetNativeTypeForCallbacks($argument->type, $interfaceOrCallback) . " " . $argument->name); } - push(@headerContent, " virtual " . GetNativeTypeForCallbacks($function->signature->type) . " " . $function->signature->name . "("); + # FIXME: Add support for non-void return types (the bool actually is returning exception state), for non-custom functions. + my $nativeReturnType = $function->extendedAttributes->{Custom} ? GetNativeTypeForCallbacks($function->type, $interfaceOrCallback) : "bool"; + + # FIXME: Change the default name (used for callback functions) to something other than handleEvent. It makes little sense. + my $functionName = $function->name ? $function->name : "handleEvent"; - my @args = (); - foreach my $param (@params) { - push(@args, GetNativeTypeForCallbacks($param->type) . " " . $param->name); - } - push(@headerContent, join(", ", @args)); - - push(@headerContent, ");\n"); + push(@$contentRef, " virtual ${nativeReturnType} ${functionName}(" . join(", ", @arguments) . ");\n"); } } - push(@headerContent, "\nprivate:\n"); + push(@$contentRef, "\nprivate:\n"); # Constructor - push(@headerContent, " $className(JSC::JSObject* callback, JSDOMGlobalObject*);\n\n"); + push(@$contentRef, " ${className}(JSC::JSObject*, JSDOMGlobalObject*);\n\n"); # Private members - push(@headerContent, " JSCallbackData* m_data;\n"); - push(@headerContent, "};\n\n"); + push(@$contentRef, " ${callbackDataType}* m_data;\n"); + push(@$contentRef, "};\n\n"); - push(@headerContent, "} // namespace WebCore\n\n"); - my $conditionalString = $codeGenerator->GenerateConditionalString($interface); - push(@headerContent, "#endif // ${conditionalString}\n\n") if $conditionalString; - push(@headerContent, "#endif\n"); + # toJS(). + push(@$contentRef, "JSC::JSValue toJS(${name}&);\n"); + push(@$contentRef, "inline JSC::JSValue toJS(${name}* impl) { return impl ? toJS(*impl) : JSC::jsNull(); }\n\n"); } -sub GenerateCallbackImplementation +sub GenerateCallbackImplementationContent { - my ($object, $interface) = @_; + my ($object, $interfaceOrCallback, $functions, $constants, $contentRef, $includesRef) = @_; - my $interfaceName = $interface->name; - my $className = "JS$interfaceName"; + my $name = $interfaceOrCallback->type->name; + my $callbackDataType = GetJSCallbackDataType($interfaceOrCallback); + my $visibleName = $codeGenerator->GetVisibleInterfaceName($interfaceOrCallback); + my $className = "JS${name}"; - # - Add default header template - push(@implContentHeader, GenerateImplementationContentHeader($interface)); - - $implIncludes{"ScriptExecutionContext.h"} = 1; - $implIncludes{"<runtime/JSLock.h>"} = 1; - - @implContent = (); - - push(@implContent, "\nusing namespace JSC;\n\n"); - push(@implContent, "namespace WebCore {\n\n"); + $includesRef->{"ScriptExecutionContext.h"} = 1; + $includesRef->{"<runtime/JSLock.h>"} = 1; # Constructor - push(@implContent, "${className}::${className}(JSObject* callback, JSDOMGlobalObject* globalObject)\n"); - if ($interface->extendedAttributes->{"CallbackNeedsOperatorEqual"}) { - push(@implContent, " : ${interfaceName}(${className}Type)\n"); + push(@$contentRef, "${className}::${className}(JSObject* callback, JSDOMGlobalObject* globalObject)\n"); + if ($interfaceOrCallback->extendedAttributes->{CallbackNeedsOperatorEqual}) { + push(@$contentRef, " : ${name}(${className}Type)\n"); } else { - push(@implContent, " : ${interfaceName}()\n"); + push(@$contentRef, " : ${name}()\n"); } - push(@implContent, " , ActiveDOMCallback(globalObject->scriptExecutionContext())\n"); - push(@implContent, " , m_data(new JSCallbackData(callback, globalObject))\n"); - push(@implContent, "{\n"); - push(@implContent, "}\n\n"); + push(@$contentRef, " , ActiveDOMCallback(globalObject->scriptExecutionContext())\n"); + push(@$contentRef, " , m_data(new ${callbackDataType}(callback, globalObject, this))\n"); + push(@$contentRef, "{\n"); + push(@$contentRef, "}\n\n"); # Destructor - push(@implContent, "${className}::~${className}()\n"); - push(@implContent, "{\n"); - push(@implContent, " ScriptExecutionContext* context = scriptExecutionContext();\n"); - push(@implContent, " // When the context is destroyed, all tasks with a reference to a callback\n"); - push(@implContent, " // should be deleted. So if the context is 0, we are on the context thread.\n"); - push(@implContent, " if (!context || context->isContextThread())\n"); - push(@implContent, " delete m_data;\n"); - push(@implContent, " else\n"); - push(@implContent, " context->postTask(DeleteCallbackDataTask::create(m_data));\n"); - push(@implContent, "#ifndef NDEBUG\n"); - push(@implContent, " m_data = 0;\n"); - push(@implContent, "#endif\n"); - push(@implContent, "}\n\n"); + push(@$contentRef, "${className}::~${className}()\n"); + push(@$contentRef, "{\n"); + push(@$contentRef, " ScriptExecutionContext* context = scriptExecutionContext();\n"); + push(@$contentRef, " // When the context is destroyed, all tasks with a reference to a callback\n"); + push(@$contentRef, " // should be deleted. So if the context is 0, we are on the context thread.\n"); + push(@$contentRef, " if (!context || context->isContextThread())\n"); + push(@$contentRef, " delete m_data;\n"); + push(@$contentRef, " else\n"); + push(@$contentRef, " context->postTask(DeleteCallbackDataTask(m_data));\n"); + push(@$contentRef, "#ifndef NDEBUG\n"); + push(@$contentRef, " m_data = nullptr;\n"); + push(@$contentRef, "#endif\n"); + push(@$contentRef, "}\n\n"); + + if ($interfaceOrCallback->extendedAttributes->{CallbackNeedsOperatorEqual}) { + push(@$contentRef, "bool ${className}::operator==(const ${name}& other) const\n"); + push(@$contentRef, "{\n"); + push(@$contentRef, " if (other.type() != type())\n"); + push(@$contentRef, " return false;\n"); + push(@$contentRef, " return static_cast<const ${className}*>(&other)->m_data->callback() == m_data->callback();\n"); + push(@$contentRef, "}\n\n"); + } + + # Constants. + my $numConstants = @{$constants}; + if ($numConstants > 0) { + GenerateConstructorDeclaration($contentRef, $className, $interfaceOrCallback, $name); - if ($interface->extendedAttributes->{"CallbackNeedsOperatorEqual"}) { - push(@implContent, "bool ${className}::operator==(const ${interfaceName}& other) const\n"); - push(@implContent, "{\n"); - push(@implContent, " if (other.type() != type())\n"); - push(@implContent, " return false;\n"); - push(@implContent, " return static_cast<const ${className}*>(&other)->m_data->callback() == m_data->callback();\n"); - push(@implContent, "}\n\n"); + my $hashSize = 0; + my $hashName = $className . "ConstructorTable"; + + my @hashKeys = (); + my @hashValue1 = (); + my @hashValue2 = (); + my @hashSpecials = (); + my %conditionals = (); + + foreach my $constant (@{$constants}) { + my $name = $constant->name; + push(@hashKeys, $name); + push(@hashValue1, $constant->value); + push(@hashValue2, "0"); + push(@hashSpecials, "DontDelete | ReadOnly | ConstantInteger"); + + my $implementedBy = $constant->extendedAttributes->{ImplementedBy}; + $implIncludes{"${implementedBy}.h"} = 1 if $implementedBy; + + my $conditional = $constant->extendedAttributes->{Conditional}; + $conditionals{$name} = $conditional if $conditional; + + $hashSize++; + } + $object->GenerateHashTable($hashName, $hashSize, \@hashKeys, \@hashSpecials, \@hashValue1, \@hashValue2, \%conditionals, 1) if $hashSize > 0; + + push(@$contentRef, $codeGenerator->GenerateCompileTimeCheckForEnumsIfNeeded($interfaceOrCallback)); + + GenerateConstructorDefinitions($contentRef, $className, "", $visibleName, $interfaceOrCallback); + + push(@$contentRef, "JSValue ${className}::getConstructor(VM& vm, const JSGlobalObject* globalObject)\n{\n"); + push(@$contentRef, " return getDOMConstructor<${className}Constructor>(vm, *jsCast<const JSDOMGlobalObject*>(globalObject));\n"); + push(@$contentRef, "}\n\n"); } - # Functions - my $numFunctions = @{$interface->functions}; + + # Functions. + my $numFunctions = @{$functions}; if ($numFunctions > 0) { - push(@implContent, "\n// Functions\n"); - foreach my $function (@{$interface->functions}) { - my @params = @{$function->parameters}; - if ($function->signature->extendedAttributes->{"Custom"} || - !(GetNativeType($function->signature->type) eq "bool")) { - next; - } + foreach my $function (@{$functions}) { + next if $function->extendedAttributes->{Custom}; + + assert("Unsupport return type: " . $function->type->name . ".") unless $function->type->name eq "void"; - AddIncludesForTypeInImpl($function->signature->type); - push(@implContent, "\n" . GetNativeTypeForCallbacks($function->signature->type) . " ${className}::" . $function->signature->name . "("); + AddToIncludesForIDLType($function->type, $includesRef); + + # FIXME: Change the default name (used for callback functions) to something other than handleEvent. It makes little sense. + my $functionName = $function->name ? $function->name : "handleEvent"; my @args = (); - my @argsCheck = (); - foreach my $param (@params) { - my $paramName = $param->name; - AddIncludesForTypeInImpl($param->type, 1); - push(@args, GetNativeTypeForCallbacks($param->type) . " " . $paramName); + foreach my $argument (@{$function->arguments}) { + AddToIncludesForIDLType($argument->type, $includesRef, 1); + push(@args, GetNativeTypeForCallbacks($argument->type, $interfaceOrCallback) . " " . $argument->name); } - push(@implContent, join(", ", @args)); - push(@implContent, ")\n"); - - push(@implContent, "{\n"); - push(@implContent, @argsCheck) if @argsCheck; - push(@implContent, " if (!canInvokeCallback())\n"); - push(@implContent, " return true;\n\n"); - push(@implContent, " Ref<$className> protect(*this);\n\n"); - push(@implContent, " JSLockHolder lock(m_data->globalObject()->vm());\n\n"); - if (@params) { - push(@implContent, " ExecState* exec = m_data->globalObject()->globalExec();\n"); + push(@$contentRef, "bool ${className}::${functionName}(" . join(", ", @args) . ")\n"); + push(@$contentRef, "{\n"); + push(@$contentRef, " if (!canInvokeCallback())\n"); + push(@$contentRef, " return true;\n\n"); + push(@$contentRef, " Ref<$className> protectedThis(*this);\n\n"); + push(@$contentRef, " JSLockHolder lock(m_data->globalObject()->vm());\n\n"); + push(@$contentRef, " ExecState* state = m_data->globalObject()->globalExec();\n"); + push(@$contentRef, " MarkedArgumentBuffer args;\n"); + + foreach my $argument (@{$function->arguments}) { + push(@$contentRef, " args.append(" . NativeToJSValueUsingPointers($argument, $interfaceOrCallback, $argument->name, "m_data") . ");\n"); } - push(@implContent, " MarkedArgumentBuffer args;\n"); - - foreach my $param (@params) { - my $paramName = $param->name; - if ($param->type eq "DOMString") { - push(@implContent, " args.append(jsStringWithCache(exec, ${paramName}));\n"); - } elsif ($param->type eq "boolean") { - push(@implContent, " args.append(jsBoolean(${paramName}));\n"); - } elsif ($param->type eq "SerializedScriptValue") { - push(@implContent, " args.append($paramName ? $paramName->deserialize(exec, m_data->globalObject(), 0) : jsNull());\n"); - } else { - push(@implContent, " args.append(toJS(exec, m_data->globalObject(), ${paramName}));\n"); - } + + push(@$contentRef, "\n NakedPtr<JSC::Exception> returnedException;\n"); + + if (ref($interfaceOrCallback) eq "IDLCallbackFunction") { + push(@$contentRef, " m_data->invokeCallback(args, JSCallbackData::CallbackType::Function, Identifier(), returnedException);\n"); + } else { + my $callbackType = $numFunctions > 1 ? "Object" : "FunctionOrObject"; + push(@$contentRef, " m_data->invokeCallback(args, JSCallbackData::CallbackType::${callbackType}, Identifier::fromString(state, \"${functionName}\"), returnedException);\n"); } - push(@implContent, "\n bool raisedException = false;\n"); - push(@implContent, " m_data->invokeCallback(args, &raisedException);\n"); - push(@implContent, " return !raisedException;\n"); - push(@implContent, "}\n"); + # FIXME: We currently just report the exception. We should probably add an extended attribute to indicate when + # we want the exception to be rethrown instead. + $includesRef->{"JSDOMExceptionHandling.h"} = 1; + push(@$contentRef, " if (returnedException)\n"); + push(@$contentRef, " reportException(state, returnedException);\n"); + push(@$contentRef, " return !returnedException;\n"); + push(@$contentRef, "}\n\n"); } } - push(@implContent, "\n}\n"); - my $conditionalString = $codeGenerator->GenerateConditionalString($interface); - push(@implContent, "\n#endif // ${conditionalString}\n") if $conditionalString; - - if ($interface->extendedAttributes->{"AppleCopyright"}) { - push(@implContent, split("\r", $endAppleCopyright)); - } + # toJS() implementation. + push(@$contentRef, "JSC::JSValue toJS(${name}& impl)\n"); + push(@$contentRef, "{\n"); + push(@$contentRef, " if (!static_cast<${className}&>(impl).callbackData())\n"); + push(@$contentRef, " return jsNull();\n\n"); + push(@$contentRef, " return static_cast<${className}&>(impl).callbackData()->callback();\n\n"); + push(@$contentRef, "}\n\n"); } sub GenerateImplementationFunctionCall() { - my $function = shift; - my $functionString = shift; - my $indent = shift; - my $svgPropertyType = shift; - my $interfaceName = shift; + my ($function, $functionString, $indent, $interface) = @_; - my $raisesException = $function->signature->extendedAttributes->{"RaisesException"}; - - if ($function->signature->type eq "void") { + if ($function->type->name eq "void" || IsReturningPromise($function)) { push(@implContent, $indent . "$functionString;\n"); - push(@implContent, $indent . "setDOMException(exec, ec);\n") if $raisesException; - - if ($svgPropertyType and !$function->isStatic) { - if ($raisesException) { - push(@implContent, $indent . "if (!ec)\n"); - push(@implContent, $indent . " impl.commitChange();\n"); - } else { - push(@implContent, $indent . "impl.commitChange();\n"); - } - } - push(@implContent, $indent . "return JSValue::encode(jsUndefined());\n"); } else { my $thisObject = $function->isStatic ? 0 : "castedThis"; - push(@implContent, "\n" . $indent . "JSC::JSValue result = " . NativeToJSValue($function->signature, 1, $interfaceName, $functionString, $thisObject) . ";\n"); - push(@implContent, $indent . "setDOMException(exec, ec);\n") if $raisesException; + push(@implContent, $indent . "return JSValue::encode(" . NativeToJSValueUsingPointers($function, $interface, $functionString, $thisObject) . ");\n"); + } +} - if ($codeGenerator->ExtendedAttributeContains($function->signature->extendedAttributes->{"CallWith"}, "ScriptState")) { - push(@implContent, $indent . "if (exec->hadException())\n"); - push(@implContent, $indent . " return JSValue::encode(jsUndefined());\n"); - } +sub IsValueIterableInterface +{ + my $interface = shift; + return 0 unless $interface->iterable; + return 0 if length $interface->iterable->keyType; + # FIXME: See https://webkit.org/b/159140, we should die if the next check is false. + return 0 unless GetIndexedGetterFunction($interface); + return 1; +} - push(@implContent, $indent . "return JSValue::encode(result);\n"); - } +sub IsKeyValueIterableInterface +{ + my $interface = shift; + return 0 unless $interface->iterable; + return 0 if IsValueIterableInterface($interface); + return 1; } -sub GetNativeTypeFromSignature +sub GenerateImplementationIterableFunctions { - my $signature = shift; - my $type = $signature->type; + my $interface = shift; - if ($type eq "unsigned long" and $signature->extendedAttributes->{"IsIndex"}) { - # Special-case index arguments because we need to check that they aren't < 0. - return "int"; - } + my $interfaceName = $interface->type->name; + my $className = "JS$interfaceName"; + my $visibleInterfaceName = $codeGenerator->GetVisibleInterfaceName($interface); + + AddToImplIncludes("JSDOMIterator.h"); + + return unless IsKeyValueIterableInterface($interface); + + my $iteratorName = "${interfaceName}Iterator"; + my $iteratorPrototypeName = "${interfaceName}IteratorPrototype"; + + my $iteratorTraitsName = "${interfaceName}IteratorTraits"; + my $iteratorTraitsType = $interface->iterable->isKeyValue ? "JSDOMIteratorType::Map" : "JSDOMIteratorType::Set"; + my $iteratorTraitsKeyType = $interface->iterable->isKeyValue ? GetIDLType($interface, $interface->iterable->keyType) : "void"; + my $iteratorTraitsValueType = GetIDLType($interface, $interface->iterable->valueType); + + push(@implContent, <<END); +struct ${iteratorTraitsName} { + static constexpr JSDOMIteratorType type = ${iteratorTraitsType}; + using KeyType = ${iteratorTraitsKeyType}; + using ValueType = ${iteratorTraitsValueType}; +}; + +using ${iteratorName} = JSDOMIterator<${className}, ${iteratorTraitsName}>; +using ${iteratorPrototypeName} = JSDOMIteratorPrototype<${className}, ${iteratorTraitsName}>; + +template<> +const JSC::ClassInfo ${iteratorName}::s_info = { "${visibleInterfaceName} Iterator", &Base::s_info, 0, CREATE_METHOD_TABLE(${iteratorName}) }; + +template<> +const JSC::ClassInfo ${iteratorPrototypeName}::s_info = { "${visibleInterfaceName} Iterator", &Base::s_info, 0, CREATE_METHOD_TABLE(${iteratorPrototypeName}) }; + +END + + foreach my $function (@{$interface->iterable->functions}) { + my $propertyName = $function->name; + my $functionName = GetFunctionName($interface, $className, $function); + + if ($propertyName eq "forEach") { + push(@implContent, <<END); +static inline EncodedJSValue ${functionName}Caller(ExecState* state, JS$interfaceName* thisObject, JSC::ThrowScope& throwScope) +{ + return JSValue::encode(iteratorForEach<${iteratorName}>(*state, *thisObject, throwScope)); +} + +END + } else { + my $iterationKind = "KeyValue"; + $iterationKind = "Key" if $propertyName eq "keys"; + $iterationKind = "Value" if $propertyName eq "values"; + $iterationKind = "Value" if $propertyName eq "[Symbol.Iterator]" and not $interface->iterable->isKeyValue; + + push(@implContent, <<END); +static inline EncodedJSValue ${functionName}Caller(ExecState*, JS$interfaceName* thisObject, JSC::ThrowScope&) +{ + return JSValue::encode(iteratorCreate<${iteratorName}>(*thisObject, IterationKind::${iterationKind})); +} + +END + } + + push(@implContent, <<END); +JSC::EncodedJSValue JSC_HOST_CALL ${functionName}(JSC::ExecState* state) +{ + return BindingCaller<$className>::callOperation<${functionName}Caller>(state, "${propertyName}"); +} - return GetNativeType($type); +END + } } my %nativeType = ( - "CompareHow" => "Range::CompareHow", - "DOMString" => "const String&", - "NodeFilter" => "RefPtr<NodeFilter>", - "SerializedScriptValue" => "RefPtr<SerializedScriptValue>", + "ByteString" => "String", + "DOMString" => "String", + "USVString" => "String", "Date" => "double", - "Dictionary" => "Dictionary", - "any" => "Deprecated::ScriptValue", + "EventListener" => "RefPtr<EventListener>", + "SerializedScriptValue" => "RefPtr<SerializedScriptValue>", + "XPathNSResolver" => "RefPtr<XPathNSResolver>", + "any" => "JSC::JSValue", + "object" => "JSC::Strong<JSC::JSObject>", "boolean" => "bool", + "byte" => "int8_t", "double" => "double", "float" => "float", + "long long" => "int64_t", + "long" => "int32_t", + "octet" => "uint8_t", "short" => "int16_t", - "long" => "int", - "unsigned long" => "unsigned", + "unrestricted double" => "double", + "unrestricted float" => "float", + "unsigned long long" => "uint64_t", + "unsigned long" => "uint32_t", "unsigned short" => "uint16_t", - "long long" => "long long", - "unsigned long long" => "unsigned long long", - "byte" => "int8_t", - "octet" => "uint8_t", - "DOMTimeStamp" => "DOMTimeStamp", ); -sub GetNativeType +# http://heycam.github.io/webidl/#dfn-flattened-union-member-types +sub GetFlattenedMemberTypes { - my $type = shift; + my ($idlUnionType) = @_; - my $svgNativeType = $codeGenerator->GetSVGTypeNeedingTearOff($type); - return "${svgNativeType}*" if $svgNativeType; - return "RefPtr<DOMStringList>" if $type eq "DOMStringList"; - return "RefPtr<${type}>" if $codeGenerator->IsTypedArrayType($type) and not $type eq "ArrayBuffer"; - return $nativeType{$type} if exists $nativeType{$type}; + my @flattenedMemberTypes = (); - my $arrayType = $codeGenerator->GetArrayType($type); - my $sequenceType = $codeGenerator->GetSequenceType($type); - my $arrayOrSequenceType = $arrayType || $sequenceType; + foreach my $memberType (@{$idlUnionType->subtypes}) { + if ($memberType->isUnion) { + push(@flattenedMemberTypes, GetFlattenedMemberTypes($memberType)); + } else { + push(@flattenedMemberTypes, $memberType); + } + } - return "Vector<" . GetNativeVectorInnerType($arrayOrSequenceType) . ">" if $arrayOrSequenceType; + return @flattenedMemberTypes; +} - if ($codeGenerator->IsEnumType($type)) { - return "const String"; +# http://heycam.github.io/webidl/#dfn-number-of-nullable-member-types +sub GetNumberOfNullableMemberTypes +{ + my ($idlUnionType) = @_; + + my $count = 0; + + foreach my $memberType (@{$idlUnionType->subtypes}) { + $count++ if $memberType->isNullable; + $count += GetNumberOfNullableMemberTypes($memberType) if $memberType->isUnion; } - # For all other types, the native type is a pointer with same type name as the IDL type. - return "${type}*"; + return $count; +} + +sub GetIDLUnionMemberTypes +{ + my ($interface, $idlUnionType) = @_; + + my $numberOfNullableMembers = GetNumberOfNullableMemberTypes($idlUnionType); + assert("Union types must only have 0 or 1 nullable types.") if $numberOfNullableMembers > 1; + + my @idlUnionMemberTypes = (); + + push(@idlUnionMemberTypes, "IDLNull") if $numberOfNullableMembers == 1; + + foreach my $memberType (GetFlattenedMemberTypes($idlUnionType)) { + push(@idlUnionMemberTypes, GetBaseIDLType($interface, $memberType)); + } + + return @idlUnionMemberTypes; +} + +sub GetBaseIDLType +{ + my ($interface, $type, $context) = @_; + + if ($context && $context->extendedAttributes->{OverrideIDLType}) { + return $context->extendedAttributes->{OverrideIDLType}; + } + + my %IDLTypes = ( + "any" => "IDLAny", + "boolean" => "IDLBoolean", + "byte" => "IDLByte", + "octet" => "IDLOctet", + "short" => "IDLShort", + "unsigned short" => "IDLUnsignedShort", + "long" => "IDLLong", + "unsigned long" => "IDLUnsignedLong", + "long long" => "IDLLongLong", + "unsigned long long" => "IDLUnsignedLongLong", + "float" => "IDLFloat", + "unrestricted float" => "IDLUnrestrictedFloat", + "double" => "IDLDouble", + "unrestricted double" => "IDLUnrestrictedDouble", + "DOMString" => "IDLDOMString", + "ByteString" => "IDLByteString", + "USVString" => "IDLUSVString", + "object" => "IDLObject", + + # Non-WebIDL extensions + "Date" => "IDLDate", + "EventListener" => "IDLEventListener<JSEventListener>", + "JSON" => "IDLJSON", + "SerializedScriptValue" => "IDLSerializedScriptValue<SerializedScriptValue>", + "XPathNSResolver" => "IDLXPathNSResolver<XPathNSResolver>", + + # Convenience type aliases + "BufferSource" => "IDLBufferSource", + ); + + return $IDLTypes{$type->name} if exists $IDLTypes{$type->name}; + return "IDLEnumeration<" . GetEnumerationClassName($type, $interface) . ">" if $codeGenerator->IsEnumType($type); + return "IDLDictionary<" . GetDictionaryClassName($type, $interface) . ">" if $codeGenerator->IsDictionaryType($type); + return "IDLSequence<" . GetIDLType($interface, @{$type->subtypes}[0]) . ">" if $codeGenerator->IsSequenceType($type); + return "IDLFrozenArray<" . GetIDLType($interface, @{$type->subtypes}[0]) . ">" if $codeGenerator->IsFrozenArrayType($type); + return "IDLRecord<" . GetIDLType($interface, @{$type->subtypes}[0]) . ", " . GetIDLType($interface, @{$type->subtypes}[1]) . ">" if $codeGenerator->IsRecordType($type); + return "IDLUnion<" . join(", ", GetIDLUnionMemberTypes($interface, $type)) . ">" if $type->isUnion; + return "IDLCallbackFunction<" . GetCallbackClassName($type->name) . ">" if $codeGenerator->IsCallbackFunction($type); + return "IDLCallbackInterface<" . GetCallbackClassName($type->name) . ">" if $codeGenerator->IsCallbackInterface($type); + + assert("Unknown type '" . $type->name . "'.\n") unless $codeGenerator->IsInterfaceType($type) || $codeGenerator->IsTypedArrayType($type); + return "IDLInterface<" . $type->name . ">"; +} + +sub GetIDLType +{ + my ($interface, $type, $context) = @_; + + my $baseIDLType = GetBaseIDLType($interface, $type, $context); + return "IDLNullable<" . $baseIDLType . ">" if $type->isNullable; + return $baseIDLType; } -sub GetNativeVectorInnerType +sub GetNativeType { - my $arrayOrSequenceType = shift; + my ($interface, $type) = @_; + + assert("Not a type") if ref($type) ne "IDLType"; - return "String" if $arrayOrSequenceType eq "DOMString"; - return $nativeType{$arrayOrSequenceType} if exists $nativeType{$arrayOrSequenceType}; - return "RefPtr<${arrayOrSequenceType}> "; + my $typeName = $type->name; + + return $nativeType{$typeName} if exists $nativeType{$typeName}; + + return GetEnumerationClassName($type, $interface) if $codeGenerator->IsEnumType($type); + return GetDictionaryClassName($type, $interface) if $codeGenerator->IsDictionaryType($type); + return "Vector<" . GetNativeInnerType(@{$type->subtypes}[0], $interface) . ">" if $codeGenerator->IsSequenceOrFrozenArrayType($type); + return "Vector<WTF::KeyValuePair<" . GetNativeInnerType(@{$type->subtypes}[0], $interface) . ", " . GetNativeInnerType(@{$type->subtypes}[1], $interface) . ">>" if $codeGenerator->IsRecordType($type); + + return "RefPtr<${typeName}>" if $codeGenerator->IsTypedArrayType($type) and $typeName ne "ArrayBuffer"; + return "${typeName}*"; +} + +sub GetNativeInnerType +{ + my ($innerType, $interface) = @_; + + my $innerTypeName = $innerType->name; + + return $nativeType{$innerTypeName} if exists $nativeType{$innerTypeName}; + + return GetEnumerationClassName($innerType, $interface) if $codeGenerator->IsEnumType($innerType); + return GetDictionaryClassName($innerType, $interface) if $codeGenerator->IsDictionaryType($innerType); + return "Vector<" . GetNativeInnerType(@{$innerType->subtypes}[0], $interface) . ">" if $codeGenerator->IsSequenceOrFrozenArrayType($innerType); + return "Vector<WTF::KeyValuePair<" . GetNativeInnerType(@{$innerType->subtypes}[0], $interface) . ", " . GetNativeInnerType(@{$innerType->subtypes}[1], $interface) . ">>" if $codeGenerator->IsRecordType($innerType); + return "RefPtr<$innerTypeName>"; } sub GetNativeTypeForCallbacks { - my $type = shift; - return "PassRefPtr<SerializedScriptValue>" if $type eq "SerializedScriptValue"; - return "PassRefPtr<DOMStringList>" if $type eq "DOMStringList"; + my ($type, $interface) = @_; - return GetNativeType($type); + return "RefPtr<SerializedScriptValue>&&" if $type->name eq "SerializedScriptValue"; + return "const String&" if $codeGenerator->IsStringType($type); + return GetNativeType($interface, $type); } -sub GetSVGPropertyTypes +sub ShouldPassArgumentByReference { - my $implType = shift; + my ($argument) = @_; - my $svgPropertyType; - my $svgListPropertyType; - my $svgNativeType; + my $type = $argument->type; - return ($svgPropertyType, $svgListPropertyType, $svgNativeType) if not $implType =~ /SVG/; - - $svgNativeType = $codeGenerator->GetSVGTypeNeedingTearOff($implType); - return ($svgPropertyType, $svgListPropertyType, $svgNativeType) if not $svgNativeType; - - # Append space to avoid compilation errors when using PassRefPtr<$svgNativeType> - $svgNativeType = "$svgNativeType "; - - my $svgWrappedNativeType = $codeGenerator->GetSVGWrappedTypeNeedingTearOff($implType); - if ($svgNativeType =~ /SVGPropertyTearOff/) { - $svgPropertyType = $svgWrappedNativeType; - $headerIncludes{"$svgWrappedNativeType.h"} = 1; - $headerIncludes{"SVGAnimatedPropertyTearOff.h"} = 1; - } elsif ($svgNativeType =~ /SVGListPropertyTearOff/ or $svgNativeType =~ /SVGStaticListPropertyTearOff/) { - $svgListPropertyType = $svgWrappedNativeType; - $headerIncludes{"$svgWrappedNativeType.h"} = 1; - $headerIncludes{"SVGAnimatedListPropertyTearOff.h"} = 1; - } elsif ($svgNativeType =~ /SVGTransformListPropertyTearOff/) { - $svgListPropertyType = $svgWrappedNativeType; - $headerIncludes{"$svgWrappedNativeType.h"} = 1; - $headerIncludes{"SVGAnimatedListPropertyTearOff.h"} = 1; - $headerIncludes{"SVGTransformListPropertyTearOff.h"} = 1; - } elsif ($svgNativeType =~ /SVGPathSegListPropertyTearOff/) { - $svgListPropertyType = $svgWrappedNativeType; - $headerIncludes{"$svgWrappedNativeType.h"} = 1; - $headerIncludes{"SVGAnimatedListPropertyTearOff.h"} = 1; - $headerIncludes{"SVGPathSegListPropertyTearOff.h"} = 1; - } - - return ($svgPropertyType, $svgListPropertyType, $svgNativeType); -} - -sub IsNativeType + return 0 if $type->isNullable; + return 0 if $codeGenerator->IsCallbackInterface($type); + return 0 if $codeGenerator->IsCallbackFunction($type); + return 0 if !$codeGenerator->IsWrapperType($type) && !$codeGenerator->IsTypedArrayType($type); + + return 1; +} + +sub GetIntegerConversionConfiguration { - my $type = shift; - return exists $nativeType{$type}; + my $context = shift; + + return "IntegerConversionConfiguration::EnforceRange" if $context->extendedAttributes->{EnforceRange}; + return "IntegerConversionConfiguration::Clamp" if $context->extendedAttributes->{Clamp}; + return "IntegerConversionConfiguration::Normal"; } -sub JSValueToNative +sub GetStringConversionConfiguration { - my $signature = shift; - my $value = shift; - - my $conditional = $signature->extendedAttributes->{"Conditional"}; - my $type = $signature->type; - - return "$value.toBoolean(exec)" if $type eq "boolean"; - return "$value.toNumber(exec)" if $type eq "double"; - return "$value.toFloat(exec)" if $type eq "float"; - - my $intConversion = $signature->extendedAttributes->{"EnforceRange"} ? "EnforceRange" : "NormalConversion"; - return "toInt8(exec, $value, $intConversion)" if $type eq "byte"; - return "toUInt8(exec, $value, $intConversion)" if $type eq "octet"; - return "toInt16(exec, $value, $intConversion)" if $type eq "short"; - return "toUInt16(exec, $value, $intConversion)" if $type eq "unsigned short"; - return "toInt32(exec, $value, $intConversion)" if $type eq "long"; - return "toUInt32(exec, $value, $intConversion)" if $type eq "unsigned long"; - return "toInt64(exec, $value, $intConversion)" if $type eq "long long"; - return "toUInt64(exec, $value, $intConversion)" if $type eq "unsigned long long"; - - return "valueToDate(exec, $value)" if $type eq "Date"; - return "static_cast<Range::CompareHow>($value.toInt32(exec))" if $type eq "CompareHow"; - - if ($type eq "DOMString") { - # FIXME: This implements [TreatNullAs=NullString] and [TreatUndefinedAs=NullString], - # but the Web IDL spec requires [TreatNullAs=EmptyString] and [TreatUndefinedAs=EmptyString]. - if (($signature->extendedAttributes->{"TreatNullAs"} and $signature->extendedAttributes->{"TreatNullAs"} eq "NullString") and ($signature->extendedAttributes->{"TreatUndefinedAs"} and $signature->extendedAttributes->{"TreatUndefinedAs"} eq "NullString")) { - return "valueToStringWithUndefinedOrNullCheck(exec, $value)" - } - if (($signature->extendedAttributes->{"TreatNullAs"} and $signature->extendedAttributes->{"TreatNullAs"} eq "NullString") or $signature->extendedAttributes->{"Reflect"}) { - return "valueToStringWithNullCheck(exec, $value)" - } - # FIXME: Add the case for 'if ($signature->extendedAttributes->{"TreatUndefinedAs"} and $signature->extendedAttributes->{"TreatUndefinedAs"} eq "NullString"))'. - return "$value.isEmpty() ? String() : $value.toString(exec)->value(exec)"; - } + my $context = shift; - if ($type eq "any") { - return "exec->vm(), $value"; - } + return "StringConversionConfiguration::TreatNullAsEmptyString" if $context->extendedAttributes->{TreatNullAs} && $context->extendedAttributes->{TreatNullAs} eq "EmptyString"; + return "StringConversionConfiguration::Normal"; +} - if ($type eq "NodeFilter") { - AddToImplIncludes("JS$type.h", $conditional); - return "to$type(exec->vm(), $value)"; - } +sub JSValueToNativeDOMConvertNeedsThisObject +{ + my $type = shift; - if ($type eq "SerializedScriptValue") { - AddToImplIncludes("SerializedScriptValue.h", $conditional); - return "SerializedScriptValue::create(exec, $value, 0, 0)"; - } + return 1 if $type->name eq "EventListener"; + return 0; +} - if ($type eq "Dictionary") { - AddToImplIncludes("Dictionary.h", $conditional); - return "exec, $value"; - } +sub JSValueToNativeDOMConvertNeedsGlobalObject +{ + my $type = shift; - if ($type eq "DOMStringList" ) { - AddToImplIncludes("JSDOMStringList.h", $conditional); - return "toDOMStringList(exec, $value)"; - } + return 1 if $codeGenerator->IsCallbackInterface($type); + return 1 if $codeGenerator->IsCallbackFunction($type); + return 0; +} + +sub IsValidContextForJSValueToNative +{ + my $context = shift; - if ($codeGenerator->IsTypedArrayType($type)) { - return "to$type($value)"; - } + return ref($context) eq "IDLAttribute" || ref($context) eq "IDLArgument"; +} - AddToImplIncludes("HTMLOptionElement.h", $conditional) if $type eq "HTMLOptionElement"; - AddToImplIncludes("Event.h", $conditional) if $type eq "Event"; +# Returns (convertString, mayThrowException). - my $arrayType = $codeGenerator->GetArrayType($type); - my $sequenceType = $codeGenerator->GetSequenceType($type); - my $arrayOrSequenceType = $arrayType || $sequenceType; +sub JSValueToNative +{ + my ($interface, $context, $value, $conditional, $statePointer, $stateReference, $thisObjectReference, $globalObjectReference, $exceptionThrower) = @_; - if ($arrayOrSequenceType) { - if ($codeGenerator->IsRefPtrType($arrayOrSequenceType)) { - AddToImplIncludes("JS${arrayOrSequenceType}.h"); - return "(toRefPtrNativeArray<${arrayOrSequenceType}, JS${arrayOrSequenceType}>(exec, $value, &to${arrayOrSequenceType}))"; - } - return "toNativeArray<" . GetNativeVectorInnerType($arrayOrSequenceType) . ">(exec, $value)"; + assert("Invalid context type") if !IsValidContextForJSValueToNative($context); + + my $type = $context->type; + + # FIXME: Remove these 3 variables when all JSValueToNative use references. + $statePointer = "state" unless $statePointer; + $stateReference = "*state" unless $stateReference; + $thisObjectReference = "*castedThis" unless $thisObjectReference; + + AddToImplIncludesForIDLType($type, $conditional); + + if ($type->name eq "DOMString") { + return ("AtomicString($value.toString($statePointer)->toExistingAtomicString($statePointer))", 1) if $context->extendedAttributes->{RequiresExistingAtomicString}; + return ("$value.toString($statePointer)->toAtomicString($statePointer)", 1) if $context->extendedAttributes->{AtomicString}; } if ($codeGenerator->IsEnumType($type)) { - return "$value.isEmpty() ? String() : $value.toString(exec)->value(exec)"; + return ("parseEnumeration<" . GetEnumerationClassName($type, $interface) . ">($stateReference, $value)", 1); } - # Default, assume autogenerated type conversion routines - AddToImplIncludes("JS$type.h", $conditional); - return "to$type($value)"; + AddToImplIncludes("JSDOMConvert.h"); + + my $IDLType = GetIDLType($interface, $type); + + my @conversionArguments = (); + push(@conversionArguments, $stateReference); + push(@conversionArguments, $value); + push(@conversionArguments, $thisObjectReference) if JSValueToNativeDOMConvertNeedsThisObject($type); + push(@conversionArguments, $globalObjectReference) if JSValueToNativeDOMConvertNeedsGlobalObject($type); + push(@conversionArguments, GetIntegerConversionConfiguration($context)) if $codeGenerator->IsIntegerType($type); + push(@conversionArguments, GetStringConversionConfiguration($context)) if $codeGenerator->IsStringType($type); + push(@conversionArguments, $exceptionThrower) if $exceptionThrower; + + return ("convert<$IDLType>(" . join(", ", @conversionArguments) . ")", 1); } -sub NativeToJSValue +sub UnsafeToNative { - my $signature = shift; - my $inFunctionCall = shift; - my $interfaceName = shift; - my $value = shift; - my $thisValue = shift; + my ($interface, $context, $value, $conditional, $statePointer, $stateReference, $thisObjectReference) = @_; - my $conditional = $signature->extendedAttributes->{"Conditional"}; - my $type = $signature->type; + assert("Invalid context type") if !IsValidContextForJSValueToNative($context); - return "jsBoolean($value)" if $type eq "boolean"; + my $type = $context->type; - # Need to check Date type before IsPrimitiveType(). - if ($type eq "Date") { - return "jsDateOrNull(exec, $value)"; - } + # FIXME: Remove these 3 variables when all JSValueToNative use references. + $statePointer = "state" unless $statePointer; + $stateReference = "*state" unless $stateReference; + $thisObjectReference = "*castedThis" unless $thisObjectReference; - if ($signature->extendedAttributes->{"Reflect"} and ($type eq "unsigned long" or $type eq "unsigned short")) { - $value =~ s/getUnsignedIntegralAttribute/getIntegralAttribute/g; - return "jsNumber(std::max(0, " . $value . "))"; - } + AddToImplIncludesForIDLType($type, $conditional); - if ($codeGenerator->IsPrimitiveType($type) or $type eq "DOMTimeStamp") { - return "jsNumber($value)"; - } + # FIXME: Support more types. - if ($codeGenerator->IsEnumType($type)) { - AddToImplIncludes("<runtime/JSString.h>", $conditional); - return "jsStringWithCache(exec, $value)"; + if ($type->name eq "DOMString") { + return ("AtomicString($value->toExistingAtomicString($statePointer))", 1) if $context->extendedAttributes->{RequiresExistingAtomicString}; + return ("$value->toAtomicString($statePointer)", 1) if $context->extendedAttributes->{AtomicString}; } - if ($codeGenerator->IsStringType($type)) { - AddToImplIncludes("URL.h", $conditional); - my $conv = $signature->extendedAttributes->{"TreatReturnedNullStringAs"}; - if (defined $conv) { - return "jsStringOrNull(exec, $value)" if $conv eq "Null"; - return "jsStringOrUndefined(exec, $value)" if $conv eq "Undefined"; + AddToImplIncludes("DOMJITIDLConvert.h"); - die "Unknown value for TreatReturnedNullStringAs extended attribute"; - } - AddToImplIncludes("<runtime/JSString.h>", $conditional); - return "jsStringWithCache(exec, $value)"; + my $IDLType = GetIDLType($interface, $type); + + my @conversionArguments = (); + push(@conversionArguments, "$stateReference"); + push(@conversionArguments, "$value"); + + my @conversionStaticArguments = (); + push(@conversionStaticArguments, GetIntegerConversionConfiguration($context)) if $codeGenerator->IsIntegerType($type); + push(@conversionStaticArguments, GetStringConversionConfiguration($context)) if $codeGenerator->IsStringType($type); + + if (scalar(@conversionStaticArguments) > 0) { + return ("DOMJIT::DirectConverter<$IDLType>::directConvert<" . join(", ", @conversionStaticArguments) . ">(" . join(", ", @conversionArguments) . ")", 1); } + return ("DOMJIT::DirectConverter<$IDLType>::directConvert(" . join(", ", @conversionArguments) . ")", 1); +} + +sub NativeToJSValueDOMConvertNeedsState +{ + my ($type, $context) = @_; + + # FIXME: We need a more robust way to specify this requirement so as not + # to require specializing each type. Perhaps just requiring all override + # types to take both state and the global object would work? + if ($context->extendedAttributes->{OverrideIDLType}) { + my $overrideTypeName = $context->extendedAttributes->{OverrideIDLType}; + return 1 if $overrideTypeName eq "IDLIDBKey"; + return 1 if $overrideTypeName eq "IDLWebGLAny"; + + return 0; + } + + # FIXME: This should actually check if all the sub-objects of the union need the state. + return 1 if $type->isUnion; + return 1 if $codeGenerator->IsSequenceOrFrozenArrayType($type); + return 1 if $codeGenerator->IsRecordType($type); + return 1 if $codeGenerator->IsStringType($type); + return 1 if $codeGenerator->IsEnumType($type); + return 1 if $codeGenerator->IsDictionaryType($type); + return 1 if $codeGenerator->IsInterfaceType($type); + return 1 if $codeGenerator->IsTypedArrayType($type); + return 1 if $type->name eq "Date"; + return 1 if $type->name eq "JSON"; + return 1 if $type->name eq "SerializedScriptValue"; + return 1 if $type->name eq "XPathNSResolver"; + + return 0; +} + +sub NativeToJSValueDOMConvertNeedsGlobalObject +{ + my ($type, $context) = @_; - my $globalObject; - if ($thisValue) { - $globalObject = "$thisValue->globalObject()"; - } + # FIXME: We need a more robust way to specify this requirement so as not + # to require specializing each type. Perhaps just requiring all override + # types to take both state and the global object would work? + if ($context->extendedAttributes->{OverrideIDLType}) { + my $overrideTypeName = $context->extendedAttributes->{OverrideIDLType}; + return 1 if $overrideTypeName eq "IDLIDBKey"; + return 1 if $overrideTypeName eq "IDLWebGLAny"; + + return 0; + } + + # FIXME: This should actually check if all the sub-objects of the union need the global object. + return 1 if $type->isUnion; + return 1 if $codeGenerator->IsSequenceOrFrozenArrayType($type); + return 1 if $codeGenerator->IsRecordType($type); + return 1 if $codeGenerator->IsDictionaryType($type); + return 1 if $codeGenerator->IsInterfaceType($type); + return 1 if $codeGenerator->IsTypedArrayType($type); + return 1 if $type->name eq "SerializedScriptValue"; + return 1 if $type->name eq "XPathNSResolver"; - if ($type eq "CSSStyleDeclaration") { - AddToImplIncludes("StyleProperties.h", $conditional); - } + return 0; +} - if ($type eq "NodeList") { - AddToImplIncludes("NameNodeList.h", $conditional); - } +sub NativeToJSValueUsingReferences +{ + my ($context, $interface, $value, $thisValue, $suppressExceptionCheck) = @_; + my $stateReference = "state"; + my $wrapped = "$thisValue.wrapped()"; + my $globalObjectReference = $thisValue ? "*$thisValue.globalObject()" : "*jsCast<JSDOMGlobalObject*>(state.lexicalGlobalObject())"; - my $arrayType = $codeGenerator->GetArrayType($type); - my $sequenceType = $codeGenerator->GetSequenceType($type); - my $arrayOrSequenceType = $arrayType || $sequenceType; + return NativeToJSValue($context, $interface, $value, $stateReference, $wrapped, $globalObjectReference, $suppressExceptionCheck); +} - if ($arrayOrSequenceType) { - if ($arrayType eq "DOMString") { - AddToImplIncludes("JSDOMStringList.h", $conditional); - AddToImplIncludes("DOMStringList.h", $conditional); +# FIXME: We should remove NativeToJSValueUsingPointers and combine NativeToJSValueUsingReferences and NativeToJSValue +sub NativeToJSValueUsingPointers +{ + my ($context, $interface, $value, $thisValue, $suppressExceptionCheck) = @_; + my $stateReference = "*state"; + my $wrapped = "$thisValue->wrapped()"; + my $globalObjectReference = $thisValue ? "*$thisValue->globalObject()" : "*jsCast<JSDOMGlobalObject*>(state->lexicalGlobalObject())"; - } elsif ($codeGenerator->IsRefPtrType($arrayOrSequenceType)) { - AddToImplIncludes("JS${arrayOrSequenceType}.h", $conditional); - AddToImplIncludes("${arrayOrSequenceType}.h", $conditional); - } - AddToImplIncludes("<runtime/JSArray.h>", $conditional); + return NativeToJSValue($context, $interface, $value, $stateReference, $wrapped, $globalObjectReference, $suppressExceptionCheck); +} - return "jsArray(exec, $thisValue->globalObject(), $value)"; - } +sub IsValidContextForNativeToJSValue +{ + my $context = shift; + + return ref($context) eq "IDLAttribute" || ref($context) eq "IDLOperation" || ref($context) eq "IDLArgument"; +} - if ($type eq "any") { - if ($interfaceName eq "Document") { - AddToImplIncludes("JSCanvasRenderingContext2D.h", $conditional); - } else { - return "($value.hasNoValue() ? jsNull() : $value.jsValue())"; - } - } elsif ($type eq "SerializedScriptValue" or $type eq "any") { - AddToImplIncludes("SerializedScriptValue.h", $conditional); - return "$value ? $value->deserialize(exec, castedThis->globalObject(), 0) : jsNull()"; - } elsif ($codeGenerator->IsTypedArrayType($type)) { - # Do nothing - all headers are already included. - } else { - # Default, include header with same name. - AddToImplIncludes("JS$type.h", $conditional); - AddToImplIncludes("$type.h", $conditional) if not $codeGenerator->SkipIncludeHeader($type); - } - - return $value if $codeGenerator->IsSVGAnimatedType($type); - - if ($signature->extendedAttributes->{"ReturnNewObject"}) { - return "toJSNewlyCreated(exec, $globalObject, WTF::getPtr($value))"; - } - - if ($codeGenerator->IsSVGAnimatedType($interfaceName) or $interfaceName eq "SVGViewSpec") { - # Convert from abstract SVGProperty to real type, so the right toJS() method can be invoked. - $value = "static_cast<" . GetNativeType($type) . ">($value)"; - } elsif ($codeGenerator->IsSVGTypeNeedingTearOff($type) and not $interfaceName =~ /List$/) { - my $tearOffType = $codeGenerator->GetSVGTypeNeedingTearOff($type); - if ($codeGenerator->IsSVGTypeWithWritablePropertiesNeedingTearOff($type) and $inFunctionCall eq 0 and not defined $signature->extendedAttributes->{"Immutable"}) { - my $getter = $value; - $getter =~ s/impl\.//; - $getter =~ s/impl->//; - $getter =~ s/\(\)//; - my $updateMethod = "&${interfaceName}::update" . $codeGenerator->WK_ucfirst($getter); - - my $selfIsTearOffType = $codeGenerator->IsSVGTypeNeedingTearOff($interfaceName); - if ($selfIsTearOffType) { - AddToImplIncludes("SVGMatrixTearOff.h", $conditional); - # FIXME: Blink: Don't create a new one everytime we access the matrix property. This means, e.g, === won't work. - $value = "SVGMatrixTearOff::create(castedThis->impl(), $value)"; - } else { - AddToImplIncludes("SVGStaticPropertyTearOff.h", $conditional); - $tearOffType =~ s/SVGPropertyTearOff</SVGStaticPropertyTearOff<$interfaceName, /; - $value = "${tearOffType}::create(impl, $value, $updateMethod)"; - } - } elsif ($tearOffType =~ /SVGStaticListPropertyTearOff/) { - $value = "${tearOffType}::create(impl, $value)"; - } elsif (not $tearOffType =~ /SVG(Point|PathSeg)List/) { - $value = "${tearOffType}::create($value)"; - } +sub NativeToJSValue +{ + my ($context, $interface, $value, $stateReference, $wrapped, $globalObjectReference, $suppressExceptionCheck) = @_; + + assert("Invalid context type") if !IsValidContextForNativeToJSValue($context); + + my $conditional = $context->extendedAttributes->{Conditional}; + my $type = $context->type; + my $mayThrowException = $context->extendedAttributes->{GetterMayThrowException} || $context->extendedAttributes->{MayThrowException} && !$suppressExceptionCheck; + + # We could instead overload a function to work with optional as well as non-optional numbers, but this + # is slightly better because it guarantees we will fail to compile if the IDL file doesn't match the C++. + if ($context->extendedAttributes->{Reflect} and ($type->name eq "unsigned long" or $type->name eq "unsigned short")) { + $value =~ s/getUnsignedIntegralAttribute/getIntegralAttribute/g; + $value = "std::max(0, $value)"; } - if ($globalObject) { - return "toJS(exec, $globalObject, WTF::getPtr($value))"; - } else { - return "toJS(exec, jsCast<JSDOMGlobalObject*>(exec->lexicalGlobalObject()), WTF::getPtr($value))"; + + AddToImplIncludesForIDLType($type, $conditional); + AddToImplIncludes("JSDOMConvert.h", $conditional); + + if ($context->extendedAttributes->{CheckSecurityForNode}) { + AddToImplIncludes("JSDOMBindingSecurity.h", $conditional); + $value = "BindingSecurity::checkSecurityForNode($stateReference, $value)"; } + + my $IDLType = GetIDLType($interface, $type, $context); + + my @conversionArguments = (); + push(@conversionArguments, $stateReference) if NativeToJSValueDOMConvertNeedsState($type, $context) || $mayThrowException; + push(@conversionArguments, $globalObjectReference) if NativeToJSValueDOMConvertNeedsGlobalObject($type, $context); + push(@conversionArguments, "throwScope") if $mayThrowException; + push(@conversionArguments, $value); + + my $functionName = $context->extendedAttributes->{NewObject} ? "toJSNewlyCreated" : "toJS"; + + return "${functionName}<${IDLType}>(" . join(", ", @conversionArguments) . ")"; } sub ceilingToPowerOf2 @@ -3722,6 +5697,69 @@ sub ceilingToPowerOf2 } # Internal Helper +sub GenerateHashTableValueArray +{ + my $keys = shift; + my $specials = shift; + my $value1 = shift; + my $value2 = shift; + my $conditionals = shift; + my $nameEntries = shift; + + my $packedSize = scalar @{$keys}; + push(@implContent, "\nstatic const HashTableValue $nameEntries\[\] =\n\{\n"); + + my $hasSetter = "false"; + + my $i = 0; + foreach my $key (@{$keys}) { + my $conditional; + my $firstTargetType; + my $secondTargetType = ""; + + if ($conditionals) { + $conditional = $conditionals->{$key}; + } + if ($conditional) { + my $conditionalString = $codeGenerator->GenerateConditionalStringFromAttributeValue($conditional); + push(@implContent, "#if ${conditionalString}\n"); + } + + if ("@$specials[$i]" =~ m/DOMJITFunction/) { + $firstTargetType = "static_cast<NativeFunction>"; + $secondTargetType = "static_cast<const JSC::DOMJIT::Signature*>"; + } elsif ("@$specials[$i]" =~ m/Function/) { + $firstTargetType = "static_cast<NativeFunction>"; + } elsif ("@$specials[$i]" =~ m/Builtin/) { + $firstTargetType = "static_cast<BuiltinGenerator>"; + } elsif ("@$specials[$i]" =~ m/ConstantInteger/) { + $firstTargetType = ""; + } elsif ("@$specials[$i]" =~ m/DOMJITAttribute/) { + $firstTargetType = "static_cast<DOMJITGetterSetterGenerator>"; + } else { + $firstTargetType = "static_cast<PropertySlot::GetValueFunc>"; + $secondTargetType = "static_cast<PutPropertySlot::PutValueFunc>"; + $hasSetter = "true"; + } + if ("@$specials[$i]" =~ m/ConstantInteger/) { + push(@implContent, " { \"$key\", @$specials[$i], NoIntrinsic, { (long long)" . $firstTargetType . "(@$value1[$i]) } },\n"); + } else { + push(@implContent, " { \"$key\", @$specials[$i], NoIntrinsic, { (intptr_t)" . $firstTargetType . "(@$value1[$i]), (intptr_t) " . $secondTargetType . "(@$value2[$i]) } },\n"); + } + if ($conditional) { + push(@implContent, "#else\n") ; + push(@implContent, " { 0, 0, NoIntrinsic, { 0, 0 } },\n"); + push(@implContent, "#endif\n") ; + } + ++$i; + } + + push(@implContent, " { 0, 0, NoIntrinsic, { 0, 0 } }\n") if (!$packedSize); + push(@implContent, "};\n\n"); + + return $hasSetter; +} + sub GenerateHashTable { my $object = shift; @@ -3733,6 +5771,34 @@ sub GenerateHashTable my $value1 = shift; my $value2 = shift; my $conditionals = shift; + my $justGenerateValueArray = shift; + + my $nameEntries = "${name}Values"; + $nameEntries =~ s/:/_/g; + my $nameIndex = "${name}Index"; + $nameIndex =~ s/:/_/g; + + if (($name =~ /Prototype/) or ($name =~ /Constructor/)) { + my $type = $name; + my $implClass; + + if ($name =~ /Prototype/) { + $type =~ s/Prototype.*//; + $implClass = $type; $implClass =~ s/Wrapper$//; + push(@implContent, "/* Hash table for prototype */\n"); + } else { + $type =~ s/Constructor.*//; + $implClass = $type; $implClass =~ s/Constructor$//; + push(@implContent, "/* Hash table for constructor */\n"); + } + } else { + push(@implContent, "/* Hash table */\n"); + } + + if ($justGenerateValueArray) { + GenerateHashTableValueArray($keys, $specials, $value1, $value2, $conditionals, $nameEntries) if $size; + return; + } # Generate size data for compact' size hash table @@ -3768,60 +5834,22 @@ sub GenerateHashTable $maxDepth = $depth if ($depth > $maxDepth); } - # Start outputing the hashtables - my $nameEntries = "${name}Values"; - $nameEntries =~ s/:/_/g; - my $hasSetter = "false"; - - if (($name =~ /Prototype/) or ($name =~ /Constructor/)) { - my $type = $name; - my $implClass; - - if ($name =~ /Prototype/) { - $type =~ s/Prototype.*//; - $implClass = $type; $implClass =~ s/Wrapper$//; - push(@implContent, "/* Hash table for prototype */\n"); - } else { - $type =~ s/Constructor.*//; - $implClass = $type; $implClass =~ s/Constructor$//; - push(@implContent, "/* Hash table for constructor */\n"); - } - } else { - push(@implContent, "/* Hash table */\n"); + push(@implContent, "\nstatic const struct CompactHashIndex ${nameIndex}\[$compactSize\] = {\n"); + for (my $i = 0; $i < $compactSize; $i++) { + my $T = -1; + if (defined($table[$i])) { $T = $table[$i]; } + my $L = -1; + if (defined($links[$i])) { $L = $links[$i]; } + push(@implContent, " { $T, $L },\n"); } + push(@implContent, "};\n\n"); # Dump the hash table - push(@implContent, "\nstatic const HashTableValue $nameEntries\[\] =\n\{\n"); - $i = 0; - foreach my $key (@{$keys}) { - my $conditional; - my $firstTargetType; - my $secondTargetType = ""; - - if ($conditionals) { - $conditional = $conditionals->{$key}; - } - if ($conditional) { - my $conditionalString = $codeGenerator->GenerateConditionalStringFromAttributeValue($conditional); - push(@implContent, "#if ${conditionalString}\n"); - } - - if ("@$specials[$i]" =~ m/Function/) { - $firstTargetType = "static_cast<NativeFunction>"; - } else { - $firstTargetType = "static_cast<PropertySlot::GetValueFunc>"; - $secondTargetType = "static_cast<PutPropertySlot::PutValueFunc>"; - $hasSetter = "true"; - } - push(@implContent, " { \"$key\", @$specials[$i], NoIntrinsic, (intptr_t)" . $firstTargetType . "(@$value1[$i]), (intptr_t) " . $secondTargetType . "(@$value2[$i]) },\n"); - push(@implContent, "#endif\n") if $conditional; - ++$i; - } + my $hasSetter = GenerateHashTableValueArray($keys, $specials, $value1, $value2, $conditionals, $nameEntries); + my $packedSize = scalar @{$keys}; - push(@implContent, " { 0, 0, NoIntrinsic, 0, 0 }\n"); - push(@implContent, "};\n\n"); my $compactSizeMask = $numEntries - 1; - push(@implContent, "static const HashTable $name = { $compactSize, $compactSizeMask, $hasSetter, $nameEntries, 0 };\n"); + push(@implContent, "static const HashTable $name = { $packedSize, $compactSizeMask, $hasSetter, $nameEntries, $nameIndex };\n"); } sub WriteData @@ -3830,11 +5858,10 @@ sub WriteData my $interface = shift; my $outputDir = shift; - my $name = $interface->name; - my $prefix = FileNamePrefix; - my $headerFileName = "$outputDir/$prefix$name.h"; - my $implFileName = "$outputDir/$prefix$name.cpp"; - my $depsFileName = "$outputDir/$prefix$name.dep"; + my $name = $interface->type->name; + my $headerFileName = "$outputDir/JS$name.h"; + my $implFileName = "$outputDir/JS$name.cpp"; + my $depsFileName = "$outputDir/JS$name.dep"; # Update a .cpp file if the contents are changed. my $contents = join "", @implContentHeader; @@ -3842,24 +5869,28 @@ sub WriteData my @includes = (); my %implIncludeConditions = (); foreach my $include (keys %implIncludes) { + next if $headerIncludes{$include}; + next if $headerTrailingIncludes{$include}; + my $condition = $implIncludes{$include}; + my $checkType = $include; $checkType =~ s/\.h//; - next if $codeGenerator->IsSVGAnimatedType($checkType); + next if $codeGenerator->IsSVGAnimatedTypeName($checkType); $include = "\"$include\"" unless $include =~ /^["<]/; # " if ($condition eq 1) { push @includes, $include; } else { - push @{$implIncludeConditions{$condition}}, $include; + push @{$implIncludeConditions{$codeGenerator->GenerateConditionalStringFromAttributeValue($condition)}}, $include; } } foreach my $include (sort @includes) { $contents .= "#include $include\n"; } foreach my $condition (sort keys %implIncludeConditions) { - $contents .= "\n#if " . $codeGenerator->GenerateConditionalStringFromAttributeValue($condition) . "\n"; + $contents .= "\n#if " . $condition . "\n"; foreach my $include (sort @{$implIncludeConditions{$condition}}) { $contents .= "#include $include\n"; } @@ -3883,7 +5914,7 @@ sub WriteData } foreach my $include (sort @includes) { # "JSClassName.h" is already included right after config.h. - next if $include eq "\"$prefix$name.h\""; + next if $include eq "\"JS$name.h\""; $contents .= "#include $include\n"; } @@ -3913,253 +5944,150 @@ sub WriteData } } -sub GenerateConstructorDeclaration +sub GeneratePrototypeDeclaration { - my $outputArray = shift; - my $className = shift; - my $interface = shift; - my $interfaceName = shift; - - my $constructorClassName = "${className}Constructor"; + my ($outputArray, $className, $interface) = @_; - push(@$outputArray, "class ${constructorClassName} : public DOMConstructorObject {\n"); - push(@$outputArray, "private:\n"); - push(@$outputArray, " ${constructorClassName}(JSC::Structure*, JSDOMGlobalObject*);\n"); - push(@$outputArray, " void finishCreation(JSC::VM&, JSDOMGlobalObject*);\n\n"); + my $prototypeClassName = "${className}Prototype"; + my %structureFlags = (); + push(@$outputArray, "class ${prototypeClassName} : public JSC::JSNonFinalObject {\n"); push(@$outputArray, "public:\n"); - push(@$outputArray, " typedef DOMConstructorObject Base;\n"); - push(@$outputArray, " static $constructorClassName* create(JSC::VM& vm, JSC::Structure* structure, JSDOMGlobalObject* globalObject)\n"); + push(@$outputArray, " using Base = JSC::JSNonFinalObject;\n"); + + push(@$outputArray, " static ${prototypeClassName}* create(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::Structure* structure)\n"); push(@$outputArray, " {\n"); - push(@$outputArray, " $constructorClassName* ptr = new (NotNull, JSC::allocateCell<$constructorClassName>(vm.heap)) $constructorClassName(structure, globalObject);\n"); - push(@$outputArray, " ptr->finishCreation(vm, globalObject);\n"); + push(@$outputArray, " ${className}Prototype* ptr = new (NotNull, JSC::allocateCell<${className}Prototype>(vm.heap)) ${className}Prototype(vm, globalObject, structure);\n"); + push(@$outputArray, " ptr->finishCreation(vm);\n"); push(@$outputArray, " return ptr;\n"); push(@$outputArray, " }\n\n"); - push(@$outputArray, " static bool getOwnPropertySlot(JSC::JSObject*, JSC::ExecState*, JSC::PropertyName, JSC::PropertySlot&);\n"); push(@$outputArray, " DECLARE_INFO;\n"); - push(@$outputArray, " static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype)\n"); + push(@$outputArray, + " static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype)\n" . + " {\n" . + " return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), info());\n" . + " }\n"); + + push(@$outputArray, "\nprivate:\n"); + push(@$outputArray, " ${prototypeClassName}(JSC::VM& vm, JSC::JSGlobalObject*, JSC::Structure* structure)\n"); + push(@$outputArray, " : JSC::JSNonFinalObject(vm, structure)\n"); push(@$outputArray, " {\n"); - push(@$outputArray, " return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), info());\n"); push(@$outputArray, " }\n"); - push(@$outputArray, "protected:\n"); - push(@$outputArray, " static const unsigned StructureFlags = JSC::OverridesGetOwnPropertySlot | JSC::ImplementsHasInstance | DOMConstructorObject::StructureFlags;\n"); - - if (IsConstructable($interface) && !$interface->extendedAttributes->{"NamedConstructor"}) { - push(@$outputArray, " static JSC::EncodedJSValue JSC_HOST_CALL construct${className}(JSC::ExecState*);\n"); - - if (!HasCustomConstructor($interface)) { - my @constructors = @{$interface->constructors}; - if (@constructors > 1) { - foreach my $constructor (@constructors) { - my $overloadedIndex = "" . $constructor->{overloadedIndex}; - push(@$outputArray, " static JSC::EncodedJSValue JSC_HOST_CALL construct${className}${overloadedIndex}(JSC::ExecState*);\n"); - } - } + if (PrototypeHasStaticPropertyTable($interface)) { + if (IsGlobalOrPrimaryGlobalInterface($interface)) { + $structureFlags{"JSC::HasStaticPropertyTable"} = 1; + } else { + push(@$outputArray, "\n"); + push(@$outputArray, " void finishCreation(JSC::VM&);\n"); } + } - my $conditionalString = $codeGenerator->GenerateConstructorConditionalString($interface); - push(@$outputArray, "#if $conditionalString\n") if $conditionalString; - push(@$outputArray, " static JSC::ConstructType getConstructData(JSC::JSCell*, JSC::ConstructData&);\n"); - push(@$outputArray, "#endif // $conditionalString\n") if $conditionalString; + if ($interface->extendedAttributes->{JSCustomNamedGetterOnPrototype}) { + push(@$outputArray, "\n"); + push(@$outputArray, " static bool put(JSC::JSCell*, JSC::ExecState*, JSC::PropertyName, JSC::JSValue, JSC::PutPropertySlot&);\n"); + push(@$outputArray, " bool putDelegate(JSC::ExecState*, JSC::PropertyName, JSC::JSValue, JSC::PutPropertySlot&, bool& putResult);\n"); } - push(@$outputArray, "};\n\n"); - if ($codeGenerator->IsConstructorTemplate($interface, "Event")) { - push(@$outputArray, "bool fill${interfaceName}Init(${interfaceName}Init&, JSDictionary&);\n\n"); + # Custom defineOwnProperty function + if ($interface->extendedAttributes->{JSCustomDefineOwnPropertyOnPrototype}) { + push(@$outputArray, "\n"); + push(@$outputArray, " static bool defineOwnProperty(JSC::JSObject*, JSC::ExecState*, JSC::PropertyName, const JSC::PropertyDescriptor&, bool shouldThrow);\n"); } - if ($interface->extendedAttributes->{"NamedConstructor"}) { - push(@$outputArray, <<END); -class JS${interfaceName}NamedConstructor : public DOMConstructorWithDocument { -public: - typedef DOMConstructorWithDocument Base; + $structureFlags{"JSC::IsImmutablePrototypeExoticObject"} = 1 if $interface->extendedAttributes->{IsImmutablePrototypeExoticObjectOnPrototype}; - static JS${interfaceName}NamedConstructor* create(JSC::VM& vm, JSC::Structure* structure, JSDOMGlobalObject* globalObject) - { - JS${interfaceName}NamedConstructor* constructor = new (NotNull, JSC::allocateCell<JS${interfaceName}NamedConstructor>(vm.heap)) JS${interfaceName}NamedConstructor(structure, globalObject); - constructor->finishCreation(vm, globalObject); - return constructor; + # structure flags + if (%structureFlags) { + push(@$outputArray, "public:\n"); + push(@$outputArray, " static const unsigned StructureFlags = "); + foreach my $structureFlag (sort (keys %structureFlags)) { + push(@$outputArray, $structureFlag . " | "); + } + push(@$outputArray, "Base::StructureFlags;\n"); } - 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()); - } + push(@$outputArray, "};\n\n"); +} + +sub GetConstructorTemplateClassName +{ + my $interface = shift; + return "JSDOMConstructorNotConstructable" if $interface->extendedAttributes->{NamedConstructor}; + return "JSDOMConstructorNotConstructable" unless IsConstructable($interface); + return "JSDOMBuiltinConstructor" if IsJSBuiltinConstructor($interface); + return "JSDOMConstructor"; +} - DECLARE_INFO; +sub GenerateConstructorDeclaration +{ + my ($outputArray, $className, $interface) = @_; -private: - JS${interfaceName}NamedConstructor(JSC::Structure*, JSDOMGlobalObject*); - static JSC::EncodedJSValue JSC_HOST_CALL constructJS${interfaceName}(JSC::ExecState*); - static JSC::ConstructType getConstructData(JSC::JSCell*, JSC::ConstructData&); - void finishCreation(JSC::VM&, JSDOMGlobalObject*); -}; + my $interfaceName = $interface->type->name; + my $constructorClassName = "${className}Constructor"; + my $templateClassName = GetConstructorTemplateClassName($interface); -END - } + AddToImplIncludes("${templateClassName}.h"); + AddToImplIncludes("JSDOMNamedConstructor.h") if $interface->extendedAttributes->{NamedConstructor}; + + push(@$outputArray, "using $constructorClassName = $templateClassName<$className>;\n"); + push(@$outputArray, "using JS${interfaceName}NamedConstructor = JSDOMNamedConstructor<$className>;\n") if $interface->extendedAttributes->{NamedConstructor}; + push(@$outputArray, "\n"); } sub GenerateConstructorDefinitions { - my $outputArray = shift; - my $className = shift; - my $protoClassName = shift; - my $interfaceName = shift; - my $visibleInterfaceName = shift; - my $interface = shift; - my $generatingNamedConstructor = shift; + my ($outputArray, $className, $protoClassName, $visibleInterfaceName, $interface, $generatingNamedConstructor) = @_; if (IsConstructable($interface)) { my @constructors = @{$interface->constructors}; if (@constructors > 1) { foreach my $constructor (@constructors) { - GenerateConstructorDefinition($outputArray, $className, $protoClassName, $interfaceName, $visibleInterfaceName, $interface, $generatingNamedConstructor, $constructor); + GenerateConstructorDefinition($outputArray, $className, $protoClassName, $visibleInterfaceName, $interface, $generatingNamedConstructor, $constructor); } - GenerateOverloadedConstructorDefinition($outputArray, $className, $interface); + GenerateOverloadedFunctionOrConstructor(@{$interface->constructors}[0], $interface, 1); } elsif (@constructors == 1) { - GenerateConstructorDefinition($outputArray, $className, $protoClassName, $interfaceName, $visibleInterfaceName, $interface, $generatingNamedConstructor, $constructors[0]); + GenerateConstructorDefinition($outputArray, $className, $protoClassName, $visibleInterfaceName, $interface, $generatingNamedConstructor, $constructors[0]); } else { - GenerateConstructorDefinition($outputArray, $className, $protoClassName, $interfaceName, $visibleInterfaceName, $interface, $generatingNamedConstructor); + GenerateConstructorDefinition($outputArray, $className, $protoClassName, $visibleInterfaceName, $interface, $generatingNamedConstructor); } } - GenerateConstructorHelperMethods($outputArray, $className, $protoClassName, $interfaceName, $visibleInterfaceName, $interface, $generatingNamedConstructor); -} - -sub GenerateOverloadedConstructorDefinition -{ - my $outputArray = shift; - my $className = shift; - my $interface = shift; - - my $functionName = "${className}Constructor::construct${className}"; - push(@$outputArray, <<END); -EncodedJSValue JSC_HOST_CALL ${functionName}(ExecState* exec) -{ - size_t argsCount = exec->argumentCount(); -END - - my %fetchedArguments = (); - my $leastNumMandatoryParams = 255; - - my @constructors = @{$interface->constructors}; - foreach my $overload (@constructors) { - my ($numMandatoryParams, $parametersCheck, @neededArguments) = GenerateFunctionParametersCheck($overload); - $leastNumMandatoryParams = $numMandatoryParams if ($numMandatoryParams < $leastNumMandatoryParams); - - foreach my $parameterIndex (@neededArguments) { - next if exists $fetchedArguments{$parameterIndex}; - push(@$outputArray, " JSValue arg$parameterIndex(exec->argument($parameterIndex));\n"); - $fetchedArguments{$parameterIndex} = 1; - } - - push(@$outputArray, " if ($parametersCheck)\n"); - push(@$outputArray, " return ${functionName}$overload->{overloadedIndex}(exec);\n"); - } - - if ($leastNumMandatoryParams >= 1) { - push(@$outputArray, " if (argsCount < $leastNumMandatoryParams)\n"); - push(@$outputArray, " return throwVMError(exec, createNotEnoughArgumentsError(exec));\n"); - } - push(@$outputArray, <<END); - return throwVMTypeError(exec); -} - -END + GenerateConstructorHelperMethods($outputArray, $className, $protoClassName, $visibleInterfaceName, $interface, $generatingNamedConstructor); } sub GenerateConstructorDefinition { - my $outputArray = shift; - my $className = shift; - my $protoClassName = shift; - my $interfaceName = shift; - my $visibleInterfaceName = shift; - my $interface = shift; - my $generatingNamedConstructor = shift; - my $function = shift; + my ($outputArray, $className, $protoClassName, $visibleInterfaceName, $interface, $generatingNamedConstructor, $function) = @_; + return if IsJSBuiltinConstructor($interface); + + my $interfaceName = $interface->type->name; my $constructorClassName = $generatingNamedConstructor ? "${className}NamedConstructor" : "${className}Constructor"; if (IsConstructable($interface)) { - if ($codeGenerator->IsConstructorTemplate($interface, "Event")) { - $implIncludes{"JSDictionary.h"} = 1; - $implIncludes{"<runtime/Error.h>"} = 1; - - push(@$outputArray, <<END); -EncodedJSValue JSC_HOST_CALL ${constructorClassName}::construct${className}(ExecState* exec) -{ - ${constructorClassName}* jsConstructor = jsCast<${constructorClassName}*>(exec->callee()); - - ScriptExecutionContext* executionContext = jsConstructor->scriptExecutionContext(); - if (!executionContext) - return throwVMError(exec, createReferenceError(exec, "Constructor associated execution context is unavailable")); - - AtomicString eventType = exec->argument(0).toString(exec)->value(exec); - if (exec->hadException()) - return JSValue::encode(jsUndefined()); - - ${interfaceName}Init eventInit; - - JSValue initializerValue = exec->argument(1); - if (!initializerValue.isUndefinedOrNull()) { - // Given the above test, this will always yield an object. - JSObject* initializerObject = initializerValue.toObject(exec); - - // Create the dictionary wrapper from the initializer object. - JSDictionary dictionary(exec, initializerObject); - - // Attempt to fill in the EventInit. - if (!fill${interfaceName}Init(eventInit, dictionary)) - return JSValue::encode(jsUndefined()); - } - - RefPtr<${interfaceName}> event = ${interfaceName}::create(eventType, eventInit); - return JSValue::encode(toJS(exec, jsConstructor->globalObject(), event.get())); -} - -bool fill${interfaceName}Init(${interfaceName}Init& eventInit, JSDictionary& dictionary) -{ -END - - if ($interface->parent) { - my $interfaceBase = $interface->parent; - push(@implContent, <<END); - if (!fill${interfaceBase}Init(eventInit, dictionary)) - return false; - -END - } - - for (my $index = 0; $index < @{$interface->attributes}; $index++) { - my $attribute = @{$interface->attributes}[$index]; - if ($attribute->signature->extendedAttributes->{"InitializedByEventConstructor"}) { - my $attributeName = $attribute->signature->name; - my $attributeImplName = $attribute->signature->extendedAttributes->{"ImplementedAs"} || $attributeName; - push(@implContent, <<END); - if (!dictionary.tryGetProperty("${attributeName}", eventInit.${attributeImplName})) - return false; -END - } - } - - push(@$outputArray, <<END); - return true; -} - -END - } elsif (!HasCustomConstructor($interface) && (!$interface->extendedAttributes->{"NamedConstructor"} || $generatingNamedConstructor)) { - my $overloadedIndexString = ""; - if ($function->{overloadedIndex} && $function->{overloadedIndex} > 0) { - $overloadedIndexString .= $function->{overloadedIndex}; + if ($interface->extendedAttributes->{CustomConstructor}) { + push(@$outputArray, "template<> JSC::EncodedJSValue JSC_HOST_CALL ${constructorClassName}::construct(JSC::ExecState* exec)\n"); + push(@$outputArray, "{\n"); + push(@$outputArray, " ASSERT(exec);\n"); + push(@$outputArray, " return construct${className}(*exec);\n"); + push(@$outputArray, "}\n\n"); + } elsif (!HasCustomConstructor($interface) && (!$interface->extendedAttributes->{NamedConstructor} || $generatingNamedConstructor)) { + my $isOverloaded = $function->{overloads} && @{$function->{overloads}} > 1; + if ($isOverloaded) { + push(@$outputArray, "static inline EncodedJSValue construct${className}$function->{overloadIndex}(ExecState* state)\n"); + } else { + push(@$outputArray, "template<> EncodedJSValue JSC_HOST_CALL ${constructorClassName}::construct(ExecState* state)\n"); } - push(@$outputArray, "EncodedJSValue JSC_HOST_CALL ${constructorClassName}::construct${className}${overloadedIndexString}(ExecState* exec)\n"); push(@$outputArray, "{\n"); - push(@$outputArray, " ${constructorClassName}* castedThis = jsCast<${constructorClassName}*>(exec->callee());\n"); + push(@$outputArray, " VM& vm = state->vm();\n"); + push(@$outputArray, " auto throwScope = DECLARE_THROW_SCOPE(vm);\n"); + push(@$outputArray, " UNUSED_PARAM(throwScope);\n"); + push(@$outputArray, " auto* castedThis = jsCast<${constructorClassName}*>(state->jsCallee());\n"); + push(@$outputArray, " ASSERT(castedThis);\n"); my @constructorArgList; @@ -4167,71 +6095,91 @@ END GenerateArgumentsCountCheck($outputArray, $function, $interface); - if ($function->signature->extendedAttributes->{"RaisesException"} || $interface->extendedAttributes->{"ConstructorRaisesException"}) { - $implIncludes{"ExceptionCode.h"} = 1; - push(@$outputArray, " ExceptionCode ec = 0;\n"); - } - # FIXME: For now, we do not support SVG constructors. # FIXME: Currently [Constructor(...)] does not yet support optional arguments without [Default=...] - my $numParameters = @{$function->parameters}; - my ($dummy, $paramIndex) = GenerateParametersCheck($outputArray, $function, $interface, $numParameters, $interfaceName, "constructorCallback", undef, undef, undef); + my ($dummy, $paramIndex) = GenerateParametersCheck($outputArray, $function, $interface, "constructorCallback"); - if ($codeGenerator->ExtendedAttributeContains($interface->extendedAttributes->{"ConstructorCallWith"}, "ScriptExecutionContext") ) { + push(@constructorArgList, "*state") if $codeGenerator->ExtendedAttributeContains($interface->extendedAttributes->{ConstructorCallWith}, "ScriptState");; + + if ($codeGenerator->ExtendedAttributeContains($interface->extendedAttributes->{ConstructorCallWith}, "ScriptExecutionContext")) { push(@constructorArgList, "*context"); push(@$outputArray, " ScriptExecutionContext* context = castedThis->scriptExecutionContext();\n"); - push(@$outputArray, " if (!context)\n"); - push(@$outputArray, " return throwVMError(exec, createReferenceError(exec, \"${interfaceName} constructor associated document is unavailable\"));\n"); + push(@$outputArray, " if (UNLIKELY(!context))\n"); + push(@$outputArray, " return throwConstructorScriptExecutionContextUnavailableError(*state, throwScope, \"${visibleInterfaceName}\");\n"); } - if ($generatingNamedConstructor) { - push(@constructorArgList, "*castedThis->document()"); + + if ($codeGenerator->ExtendedAttributeContains($interface->extendedAttributes->{ConstructorCallWith}, "Document")) { + $implIncludes{"Document.h"} = 1; + push(@constructorArgList, "document"); + push(@$outputArray, " ScriptExecutionContext* context = castedThis->scriptExecutionContext();\n"); + push(@$outputArray, " if (UNLIKELY(!context))\n"); + push(@$outputArray, " return throwConstructorScriptExecutionContextUnavailableError(*state, throwScope, \"${visibleInterfaceName}\");\n"); + push(@$outputArray, " ASSERT(context->isDocument());\n"); + push(@$outputArray, " auto& document = downcast<Document>(*context);\n"); } + push(@constructorArgList, "*castedThis->document()") if $generatingNamedConstructor; + my $index = 0; - foreach my $parameter (@{$function->parameters}) { + foreach my $argument (@{$function->arguments}) { last if $index eq $paramIndex; - push(@constructorArgList, $parameter->name); + + push(@constructorArgList, PassArgumentExpression($argument->name, $argument)); + $index++; } - if ($interface->extendedAttributes->{"ConstructorRaisesException"}) { - push(@constructorArgList, "ec"); - } my $constructorArg = join(", ", @constructorArgList); if ($generatingNamedConstructor) { - push(@$outputArray, " RefPtr<${interfaceName}> object = ${interfaceName}::createForJSConstructor(${constructorArg});\n"); + push(@$outputArray, " auto object = ${interfaceName}::createForJSConstructor(${constructorArg});\n"); } else { - push(@$outputArray, " RefPtr<${interfaceName}> object = ${interfaceName}::create(${constructorArg});\n"); + push(@$outputArray, " auto object = ${interfaceName}::create(${constructorArg});\n"); } - if ($interface->extendedAttributes->{"ConstructorRaisesException"}) { - push(@$outputArray, " if (ec) {\n"); - push(@$outputArray, " setDOMException(exec, ec);\n"); - push(@$outputArray, " return JSValue::encode(JSValue());\n"); - push(@$outputArray, " }\n"); - } + push(@$outputArray, " RETURN_IF_EXCEPTION(throwScope, encodedJSValue());\n") if $codeGenerator->ExtendedAttributeContains($interface->extendedAttributes->{ConstructorCallWith}, "ScriptState"); + + my $IDLType = GetIDLType($interface, $interface->type); - push(@$outputArray, " return JSValue::encode(asObject(toJS(exec, castedThis->globalObject(), object.get())));\n"); + my @constructionConversionArguments = (); + push(@constructionConversionArguments, "*state"); + push(@constructionConversionArguments, "*castedThis->globalObject()"); + push(@constructionConversionArguments, "throwScope") if $interface->extendedAttributes->{ConstructorMayThrowException}; + push(@constructionConversionArguments, "WTFMove(object)"); + + push(@$outputArray, " return JSValue::encode(toJSNewlyCreated<${IDLType}>(" . join(", ", @constructionConversionArguments) . "));\n"); push(@$outputArray, "}\n\n"); } } } -sub GenerateConstructorHelperMethods +sub ConstructorHasProperties { - my $outputArray = shift; - my $className = shift; - my $protoClassName = shift; - my $interfaceName = shift; - my $visibleInterfaceName = shift; my $interface = shift; - my $generatingNamedConstructor = shift; + + foreach my $constant (@{$interface->constants}) { + return 1; + } + + foreach my $attribute (@{$interface->attributes}) { + next unless ($attribute->isStatic); + return 1; + } + + foreach my $function (@{$interface->functions}) { + next unless ($function->isStatic); + return 1; + } + + return 0; +} + +sub GenerateConstructorHelperMethods +{ + my ($outputArray, $className, $protoClassName, $visibleInterfaceName, $interface, $generatingNamedConstructor) = @_; my $constructorClassName = $generatingNamedConstructor ? "${className}NamedConstructor" : "${className}Constructor"; my $leastConstructorLength = 0; - if ($codeGenerator->IsConstructorTemplate($interface, "Event")) { - $leastConstructorLength = 1; - } elsif ($interface->extendedAttributes->{"Constructor"} || $interface->extendedAttributes->{"CustomConstructor"}) { + if ($interface->extendedAttributes->{Constructor} || $interface->extendedAttributes->{CustomConstructor}) { my @constructors = @{$interface->constructors}; my @customConstructors = @{$interface->customConstructors}; $leastConstructorLength = 255; @@ -4243,108 +6191,192 @@ sub GenerateConstructorHelperMethods $leastConstructorLength = 0; } - if ($generatingNamedConstructor) { - push(@$outputArray, "const ClassInfo ${constructorClassName}::s_info = { \"${visibleInterfaceName}Constructor\", &Base::s_info, 0, 0, CREATE_METHOD_TABLE($constructorClassName) };\n\n"); - push(@$outputArray, "${constructorClassName}::${constructorClassName}(Structure* structure, JSDOMGlobalObject* globalObject)\n"); - push(@$outputArray, " : DOMConstructorWithDocument(structure, globalObject)\n"); - push(@$outputArray, "{\n"); - push(@$outputArray, "}\n\n"); + # If the interface has a parent interface which does not have [NoInterfaceObject], then use its interface object as prototype, + # otherwise use FunctionPrototype: http://heycam.github.io/webidl/#interface-object + push(@$outputArray, "template<> JSValue ${constructorClassName}::prototypeForStructure(JSC::VM& vm, const JSDOMGlobalObject& globalObject)\n"); + push(@$outputArray, "{\n"); + # FIXME: IDL does not allow an interface without [NoInterfaceObject] to inherit one that is marked as [NoInterfaceObject] + # so we should be able to use our parent's interface object no matter what. However, some of our IDL files (e.g. CanvasRenderingContext2D) + # are not valid so we need this check for now. + if ($interface->parentType && !$codeGenerator->GetInterfaceExtendedAttributesFromName($interface->parentType->name)->{NoInterfaceObject}) { + my $parentClassName = "JS" . $interface->parentType->name; + push(@$outputArray, " return ${parentClassName}::getConstructor(vm, &globalObject);\n"); } else { - if ($interface->extendedAttributes->{"JSNoStaticTables"}) { - push(@$outputArray, "static const HashTable& get${constructorClassName}Table(VM& vm)\n"); - push(@$outputArray, "{\n"); - push(@$outputArray, " return getHashTableForGlobalData(vm, ${constructorClassName}Table);\n"); - push(@$outputArray, "}\n\n"); - push(@$outputArray, "const ClassInfo ${constructorClassName}::s_info = { \"${visibleInterfaceName}Constructor\", &Base::s_info, 0, get${constructorClassName}Table, CREATE_METHOD_TABLE($constructorClassName) };\n\n"); - } else { - push(@$outputArray, "const ClassInfo ${constructorClassName}::s_info = { \"${visibleInterfaceName}Constructor\", &Base::s_info, &${constructorClassName}Table, 0, CREATE_METHOD_TABLE($constructorClassName) };\n\n"); - } - - push(@$outputArray, "${constructorClassName}::${constructorClassName}(Structure* structure, JSDOMGlobalObject* globalObject)\n"); - push(@$outputArray, " : DOMConstructorObject(structure, globalObject)\n"); - push(@$outputArray, "{\n}\n\n"); + AddToImplIncludes("<runtime/FunctionPrototype.h>"); + push(@$outputArray, " UNUSED_PARAM(vm);\n"); + push(@$outputArray, " return globalObject.functionPrototype();\n"); } + push(@$outputArray, "}\n\n"); - push(@$outputArray, "void ${constructorClassName}::finishCreation(VM& vm, JSDOMGlobalObject* globalObject)\n"); + + push(@$outputArray, "template<> void ${constructorClassName}::initializeProperties(VM& vm, JSDOMGlobalObject& globalObject)\n"); push(@$outputArray, "{\n"); - if (IsDOMGlobalObject($interface)) { - push(@$outputArray, " Base::finishCreation(vm);\n"); - push(@$outputArray, " ASSERT(inherits(info()));\n"); - push(@$outputArray, " putDirect(vm, vm.propertyNames->prototype, globalObject->prototype(), DontDelete | ReadOnly);\n"); - } elsif ($generatingNamedConstructor) { - push(@$outputArray, " Base::finishCreation(globalObject);\n"); - push(@$outputArray, " ASSERT(inherits(info()));\n"); - push(@$outputArray, " putDirect(vm, vm.propertyNames->prototype, ${className}Prototype::self(vm, globalObject), None);\n"); + + # There must exist an interface prototype object for every non-callback interface defined, regardless + # of whether the interface was declared with the [NoInterfaceObject] extended attribute. + # https://heycam.github.io/webidl/#interface-prototype-object + if (ShouldUseGlobalObjectPrototype($interface)) { + push(@$outputArray, " putDirect(vm, vm.propertyNames->prototype, globalObject.getPrototypeDirect(), DontDelete | ReadOnly | DontEnum);\n"); + } elsif ($interface->isCallback) { + push(@$outputArray, " UNUSED_PARAM(globalObject);\n"); } else { - push(@$outputArray, " Base::finishCreation(vm);\n"); - push(@$outputArray, " ASSERT(inherits(info()));\n"); - push(@$outputArray, " putDirect(vm, vm.propertyNames->prototype, ${protoClassName}::self(vm, globalObject), DontDelete | ReadOnly);\n"); + push(@$outputArray, " putDirect(vm, vm.propertyNames->prototype, ${className}::prototype(vm, &globalObject), DontDelete | ReadOnly | DontEnum);\n"); } - push(@$outputArray, " putDirect(vm, vm.propertyNames->length, jsNumber(${leastConstructorLength}), ReadOnly | DontDelete | DontEnum);\n") if defined $leastConstructorLength; - push(@$outputArray, "}\n\n"); - if (!$generatingNamedConstructor) { - my $hasStaticFunctions = 0; - foreach my $function (@{$interface->functions}) { - if ($function->isStatic) { - $hasStaticFunctions = 1; - last; - } - } + push(@$outputArray, " putDirect(vm, vm.propertyNames->name, jsNontrivialString(&vm, String(ASCIILiteral(\"$visibleInterfaceName\"))), ReadOnly | DontEnum);\n"); + push(@$outputArray, " putDirect(vm, vm.propertyNames->length, jsNumber(${leastConstructorLength}), ReadOnly | DontEnum);\n") if defined $leastConstructorLength; + push(@$outputArray, " reifyStaticProperties(vm, ${className}ConstructorTableValues, *this);\n") if ConstructorHasProperties($interface); - my $kind = $hasStaticFunctions ? "Property" : "Value"; + push(@$outputArray, "}\n\n"); - push(@$outputArray, "bool ${constructorClassName}::getOwnPropertySlot(JSObject* object, ExecState* exec, PropertyName propertyName, PropertySlot& slot)\n"); + if (IsJSBuiltinConstructor($interface)) { + push(@$outputArray, "template<> FunctionExecutable* ${constructorClassName}::initializeExecutable(VM& vm)\n"); push(@$outputArray, "{\n"); - push(@$outputArray, " return getStatic${kind}Slot<${constructorClassName}, JSDOMWrapper>(exec, " . constructorHashTableAccessor($interface->extendedAttributes->{"JSNoStaticTables"}, $constructorClassName) . ", jsCast<${constructorClassName}*>(object), propertyName, slot);\n"); - push(@$outputArray, "}\n\n"); - } - - if (IsConstructable($interface)) { - if (!$interface->extendedAttributes->{"NamedConstructor"} || $generatingNamedConstructor) { - my $conditionalString = $codeGenerator->GenerateConstructorConditionalString($interface); - push(@$outputArray, "#if $conditionalString\n") if $conditionalString; - push(@$outputArray, "ConstructType ${constructorClassName}::getConstructData(JSCell*, ConstructData& constructData)\n"); - push(@$outputArray, "{\n"); - push(@$outputArray, " constructData.native.function = construct${className};\n"); - push(@$outputArray, " return ConstructTypeHost;\n"); - push(@$outputArray, "}\n"); - push(@$outputArray, "#endif // $conditionalString\n") if $conditionalString; - push(@$outputArray, "\n"); - } + push(@$outputArray, " return " . GetJSBuiltinFunctionNameFromString($interface->type->name, "initialize" . $interface->type->name) . "(vm);\n"); + push(@$outputArray, "}\n"); + push(@$outputArray, "\n"); } + push(@$outputArray, "template<> const ClassInfo ${constructorClassName}::s_info = { \"${visibleInterfaceName}\", &Base::s_info, 0, CREATE_METHOD_TABLE($constructorClassName) };\n\n"); } sub HasCustomConstructor { my $interface = shift; - - return $interface->extendedAttributes->{"CustomConstructor"}; + return $interface->extendedAttributes->{CustomConstructor}; } sub HasCustomGetter { - my $attrExt = shift; - return $attrExt->{"Custom"} || $attrExt->{"CustomGetter"} ; + my $extendedAttributes = shift; + return $extendedAttributes->{Custom} || $extendedAttributes->{CustomGetter} ; } sub HasCustomSetter { - my $attrExt = shift; - return $attrExt->{"Custom"} || $attrExt->{"CustomSetter"}; + my $extendedAttributes = shift; + return $extendedAttributes->{Custom} || $extendedAttributes->{CustomSetter}; } sub HasCustomMethod { - my $attrExt = shift; - return $attrExt->{"Custom"}; + my $extendedAttributes = shift; + return $extendedAttributes->{Custom}; +} + +sub NeedsConstructorProperty +{ + my $interface = shift; + return !$interface->extendedAttributes->{NoInterfaceObject} || $interface->extendedAttributes->{CustomConstructor}; +} + +sub IsReturningPromise +{ + my $function = shift; + return $function->type && $function->type->name eq "Promise"; } sub IsConstructable { my $interface = shift; + return HasCustomConstructor($interface) + || $interface->extendedAttributes->{Constructor} + || $interface->extendedAttributes->{NamedConstructor} + || $interface->extendedAttributes->{JSBuiltinConstructor}; +} + +sub HeaderNeedsPrototypeDeclaration +{ + my $interface = shift; + return IsDOMGlobalObject($interface) || $interface->extendedAttributes->{JSCustomNamedGetterOnPrototype} || $interface->extendedAttributes->{JSCustomDefineOwnPropertyOnPrototype}; +} + +sub IsUnforgeable +{ + my $interface = shift; + my $property = shift; + return $property->extendedAttributes->{Unforgeable} || $interface->extendedAttributes->{Unforgeable}; +} + +sub ComputeFunctionSpecial +{ + my $interface = shift; + my $function = shift; + + my @specials = (); + push(@specials, ("DontDelete", "ReadOnly")) if IsUnforgeable($interface, $function); + push(@specials, "DontEnum") if $function->extendedAttributes->{NotEnumerable}; + if (IsJSBuiltin($interface, $function)) { + push(@specials, "JSC::Builtin"); + } + else { + push(@specials, "JSC::Function"); + } + if ($function->extendedAttributes->{"DOMJIT"}) { + push(@specials, "DOMJITFunction") if $function->extendedAttributes->{DOMJIT}; + } + return (@specials > 0) ? join(" | ", @specials) : "0"; +} + +sub IsJSBuiltin +{ + my ($interface, $object) = @_; - return HasCustomConstructor($interface) || $interface->extendedAttributes->{"Constructor"} || $interface->extendedAttributes->{"NamedConstructor"} || $interface->extendedAttributes->{"ConstructorTemplate"}; + return 0 if $object->extendedAttributes->{Custom}; + return 0 if $object->extendedAttributes->{CustomGetter}; + return 0 if $object->extendedAttributes->{CustomSetter}; + + return 1 if $object->extendedAttributes->{JSBuiltin}; + return 1 if $interface->extendedAttributes->{JSBuiltin}; + + return 0; +} + +sub IsJSBuiltinConstructor +{ + my ($interface) = @_; + + return 0 if $interface->extendedAttributes->{CustomConstructor}; + return 1 if $interface->extendedAttributes->{JSBuiltin}; + return 1 if $interface->extendedAttributes->{JSBuiltinConstructor}; + return 0; +} + +sub GetJSBuiltinFunctionName +{ + my ($className, $function) = @_; + my $scopeName = $function->extendedAttributes->{ImplementedBy}; + $scopeName = substr $className, 2 unless $scopeName; + return GetJSBuiltinFunctionNameFromString($scopeName, $function->name); +} + +sub GetJSBuiltinFunctionNameFromString +{ + my ($scopeName, $functionName) = @_; + return $codeGenerator->WK_lcfirst($scopeName) . $codeGenerator->WK_ucfirst($functionName) . "CodeGenerator"; +} + +sub GetJSBuiltinScopeName +{ + my ($interface, $object) = @_; + return $object->extendedAttributes->{ImplementedBy} || $interface->type->name; +} + +sub AddJSBuiltinIncludesIfNeeded() +{ + my $interface = shift; + + if ($interface->extendedAttributes->{JSBuiltin} || $interface->extendedAttributes->{JSBuiltinConstructor}) { + AddToImplIncludes($interface->type->name . "Builtins.h"); + return; + } + + foreach my $function (@{$interface->functions}) { + AddToImplIncludes(GetJSBuiltinScopeName($interface, $function) . "Builtins.h", $function->extendedAttributes->{Conditional}) if IsJSBuiltin($interface, $function); + } + + foreach my $attribute (@{$interface->attributes}) { + AddToImplIncludes(GetJSBuiltinScopeName($interface, $attribute) . "Builtins.h", $attribute->extendedAttributes->{Conditional}) if IsJSBuiltin($interface, $attribute); + } } 1; diff --git a/Source/WebCore/bindings/scripts/IDLAttributes.txt b/Source/WebCore/bindings/scripts/IDLAttributes.txt index 85ead715d..e872d88d9 100644 --- a/Source/WebCore/bindings/scripts/IDLAttributes.txt +++ b/Source/WebCore/bindings/scripts/IDLAttributes.txt @@ -19,54 +19,66 @@ # ActiveDOMObject -CPPPureInterface +AppleCopyright +AtomicString +CEReactions CachedAttribute CallbackNeedsOperatorEqual -CallWith=ScriptExecutionContext|ScriptState|ScriptArguments|CallStack +CallWith=Document|ScriptExecutionContext|ScriptState|ScriptArguments|CallStack|GlobalObject|ActiveWindow|FirstWindow|CallerDocument|CallerWindow CheckSecurity CheckSecurityForNode Clamp Conditional=* +ConstantsScope=* Constructor -ConstructorCallWith=ScriptExecutionContext -ConstructorConditional=* -ConstructorRaisesException -ConstructorTemplate=Event|TypedArray +ConstructorCallWith=Document|ScriptExecutionContext|ScriptState +ConstructorMayThrowException Custom CustomCall CustomConstructor CustomDeleteProperty CustomEnumerateProperty CustomGetOwnPropertySlot +CustomGetPrototype CustomGetter CustomIndexedSetter CustomIsReachable CustomNamedGetter CustomNamedSetter +CustomPreventExtensions +CustomProxyToJSObject CustomPutFunction -CustomReturn +CustomSetPrototype CustomSetter CustomToJSObject -Default=NullString|Undefined -Deletable +CustomToStringName +DOMJIT=|ReadDOM|Getter DoNotCheckConstants DoNotCheckSecurity DoNotCheckSecurityOnGetter DoNotCheckSecurityOnSetter +DocumentEventHandler EnabledAtRuntime=* EnabledBySetting=* +EnabledForWorld=* EnforceRange -EventTarget -GenerateIsReachable=|Impl|ImplWebGLRenderingContext|ImplDocument|ImplElementRoot|ImplFrame|ImplOwnerNodeRoot -GetterRaisesException -GlobalContext=DOMWindow|WorkerGlobalScope|SharedWorkerGlobalScope|DedicatedWorkerGlobalScope +ExportMacro=WEBCORE_EXPORT|WEBCORE_TESTSUPPORT_EXPORT +ExportToWrappedFunction +Exposed=* +ForwardDeclareInHeader +GenerateIsReachable=|Impl|ImplWebGLRenderingContext|ImplDocument|ImplElementRoot|ImplFrame|ImplOwnerNodeRoot|ImplScriptExecutionContext +GetterMayThrowException +Global=* Immutable -ImplementationLacksVTable -ImplementationNamespace=* ImplementedAs=* -InitializedByEventConstructor +ImplementationLacksVTable +ImplicitThis InterfaceName=* -IsIndex +IsImmutablePrototypeExoticObject +IsImmutablePrototypeExoticObjectOnPrototype +IsWeakCallback +JSBuiltin +JSBuiltinConstructor JSCustomDefineOwnProperty JSCustomDefineOwnPropertyOnPrototype JSCustomFinalize @@ -79,34 +91,33 @@ JSCustomToNativeObject JSGenerateToJSObject JSGenerateToNativeObject JSLegacyParent=* -JSNoStaticTables -JSWindowEventListener +LegacyUnenumerableNamedProperties +LenientThis MasqueradesAsUndefined +MayThrowException NamedConstructor=* NewImpurePropertyFiresWatchpoints +NewObject NoInterfaceObject NotEnumerable -NotDeletable -ObjCCustomImplementation -ObjCLegacyUnnamedParameters -ObjCPolymorphic -ObjCProtocol -OperationsNotDeletable +OverrideBuiltins +OverrideIDLType=* PassContext -RaisesException +PrimaryGlobal +PrivateIdentifier +PublicIdentifier +PutForwards=* Reflect=* Replaceable -ReplaceableConstructor -ReturnNewObject -SetterRaisesException +ReportExtraMemoryCost +ReportExternalMemoryCost +RequiresExistingAtomicString +SetterCallWith=ScriptExecutionContext|ScriptState|ScriptArguments|CallStack|GlobalObject|ActiveWindow|FirstWindow +SetterMayThrowException SkipVTableValidation -StrictTypeChecking SuppressToJSObject -TreatNullAs=NullString -TreatReturnedNullStringAs=Null|Undefined -TreatUndefinedAs=NullString -TypedArray=* +TreatNullAs=EmptyString URL - -# PLATFORM(IOS) -AppleCopyright +Unforgeable +Unscopable +WindowEventHandler diff --git a/Source/WebCore/bindings/scripts/IDLParser.pm b/Source/WebCore/bindings/scripts/IDLParser.pm index 319f62bae..2107b94a5 100644 --- a/Source/WebCore/bindings/scripts/IDLParser.pm +++ b/Source/WebCore/bindings/scripts/IDLParser.pm @@ -23,6 +23,9 @@ package IDLParser; use strict; +use Carp qw<longmess>; +use Data::Dumper; + use preprocessor; use Class::Struct; @@ -34,68 +37,132 @@ use constant OtherToken => 4; use constant EmptyToken => 5; # Used to represent a parsed IDL document -struct( idlDocument => { - interfaces => '@', # All parsed interfaces - enumerations => '@', # All parsed enumerations - fileName => '$', # file name +struct( IDLDocument => { + interfaces => '@', # List of 'IDLInterface' + enumerations => '@', # List of 'IDLEnum' + dictionaries => '@', # List of 'IDLDictionary' + callbackFunctions => '@', # List of 'IDLCallbackFunction' + fileName => '$', +}); + +# https://heycam.github.io/webidl/#idl-types +struct( IDLType => { + name => '$', # Type identifier + isNullable => '$', # Is the type Nullable (T?) + isUnion => '$', # Is the type a union (T or U) + subtypes => '@', # Array of subtypes, only valid if isUnion or sequence }); # Used to represent 'interface' blocks -struct( domInterface => { - name => '$', # Class identifier - parent => '$', # Parent class identifier - parents => '@', # Parent class identifiers (Kept for compatibility with ObjC bindings) - constants => '@', # List of 'domConstant' - functions => '@', # List of 'domFunction' - anonymousFunctions => '@', # List of 'domFunction' - attributes => '@', # List of 'domAttribute' - extendedAttributes => '$', # Extended attributes - constructors => '@', # Constructors, list of 'domFunction' - customConstructors => '@', # Custom constructors, list of 'domFunction' +struct( IDLInterface => { + type => 'IDLType', + parentType => 'IDLType', + constants => '@', # List of 'IDLConstant' + functions => '@', # List of 'IDLOperation' + anonymousFunctions => '@', # List of 'IDLOperation' + attributes => '@', # List of 'IDLAttribute' + constructors => '@', # Constructors, list of 'IDLOperation' + customConstructors => '@', # Custom constructors, list of 'IDLOperation' isException => '$', # Used for exception interfaces isCallback => '$', # Used for callback interfaces isPartial => '$', # Used for partial interfaces + iterable => '$', # Used for iterable interfaces + serializable => '$', # Used for serializable interfaces + extendedAttributes => '$', }); -# Used to represent domInterface contents (name of method, signature) -struct( domFunction => { +# Used to represent an argument to a IDLOperation. +struct( IDLArgument => { + name => '$', + type => 'IDLType', + isVariadic => '$', + isOptional => '$', + default => '$', + extendedAttributes => '$', +}); + +# https://heycam.github.io/webidl/#idl-operations +struct( IDLOperation => { + name => '$', + type => 'IDLType', # Return type + arguments => '@', # List of 'IDLArgument' isStatic => '$', - signature => '$', # Return type/Object name/extended attributes - parameters => '@', # List of 'domSignature' + specials => '@', + extendedAttributes => '$', }); -# Used to represent domInterface contents (name of attribute, signature) -struct( domAttribute => { - type => '$', # Attribute type (including namespace) + +# https://heycam.github.io/webidl/#idl-attributes +struct( IDLAttribute => { + name => '$', + type => 'IDLType', isStatic => '$', + isStringifier => '$', isReadOnly => '$', - signature => '$', # Attribute signature + extendedAttributes => '$', +}); + +# https://heycam.github.io/webidl/#idl-iterable +struct( IDLIterable => { + isKeyValue => '$', + keyType => 'IDLType', + valueType => 'IDLType', + functions => '@', # Iterable functions (entries, keys, values, [Symbol.Iterator], forEach) + extendedAttributes => '$', +}); + +# https://heycam.github.io/webidl/#idl-serializers +struct( IDLSerializable => { + attributes => '@', # List of attributes to serialize + hasAttribute => '$', # serializer = { attribute } + hasInherit => '$', # serializer = { inherit } + hasGetter => '$', # serializer = { getter } + functions => '@', # toJSON function +}); + +# https://heycam.github.io/webidl/#idl-constants +struct( IDLConstant => { + name => '$', + type => 'IDLType', + value => '$', + extendedAttributes => '$', +}); + +# https://heycam.github.io/webidl/#idl-enums +struct( IDLEnum => { + name => '$', + type => 'IDLType', + values => '@', + extendedAttributes => '$', +}); + +# https://heycam.github.io/webidl/#dfn-dictionary-member +struct( IDLDictionaryMember => { + name => '$', + type => 'IDLType', + isRequired => '$', + default => '$', + extendedAttributes => '$', }); -# Used to represent a map of 'variable name' <-> 'variable type' -struct( domSignature => { - direction => '$', # Variable direction (in or out) - name => '$', # Variable name - type => '$', # Variable type - specials => '@', # Specials - extendedAttributes => '$', # Extended attributes - isNullable => '$', # Is variable type Nullable (T?) - isVariadic => '$', # Is variable variadic (long... numbers) - isOptional => '$', # Is variable optional (optional T) +# https://heycam.github.io/webidl/#idl-dictionaries +struct( IDLDictionary => { + type => 'IDLType', + parentType => 'IDLType', + members => '@', # List of 'IDLDictionaryMember' + extendedAttributes => '$', }); -# Used to represent string constants -struct( domConstant => { - name => '$', # DOM Constant identifier - type => '$', # Type of data - value => '$', # Constant value - extendedAttributes => '$', # Extended attributes +# https://heycam.github.io/webidl/#idl-callback-functions +struct( IDLCallbackFunction => { + type => '$', + operation => 'IDLOperation', + extendedAttributes => '$', }); -# Used to represent 'enum' definitions -struct( domEnum => { - name => '$', # Enumeration identifier - values => '@', # Enumeration values (list of unique strings) +# https://heycam.github.io/webidl/#idl-typedefs +struct( IDLTypedef => { + type => 'IDLType', }); struct( Token => { @@ -103,11 +170,6 @@ struct( Token => { value => '$' # value of token }); -struct( Typedef => { - extendedAttributes => '$', # Extended attributes - type => '$', # Type of data -}); - # Maps 'typedef name' -> Typedef my %typedefs = (); @@ -129,17 +191,28 @@ sub new { return bless $self, $class; } +sub assert +{ + my $message = shift; + + my $mess = longmess(); + print Dumper($mess); + + die $message; +} + sub assertTokenValue { my $self = shift; my $token = shift; my $value = shift; my $line = shift; - my $msg = "Next token should be " . $value . ", but " . $token->value() . " at " . $self->{Line}; + my $msg = "Next token should be " . $value . ", but " . $token->value() . " on line " . $self->{Line}; if (defined ($line)) { $msg .= " IDLParser.pm:" . $line; } - die $msg unless $token->value() eq $value; + + assert $msg unless $token->value() eq $value; } sub assertTokenType @@ -147,7 +220,8 @@ sub assertTokenType my $self = shift; my $token = shift; my $type = shift; - die "Next token's type should be " . $type . ", but " . $token->type() . " at " . $self->{Line} unless $token->type() eq $type; + + assert "Next token's type should be " . $type . ", but " . $token->type() . " on line " . $self->{Line} unless $token->type() eq $type; } sub assertUnexpectedToken @@ -155,11 +229,12 @@ sub assertUnexpectedToken my $self = shift; my $token = shift; my $line = shift; - my $msg = "Unexpected token " . $token . " at " . $self->{Line}; + my $msg = "Unexpected token " . $token . " on line " . $self->{Line}; if (defined ($line)) { $msg .= " IDLParser.pm:" . $line; } - die $msg; + + assert $msg; } sub assertNoExtendedAttributesInTypedef @@ -168,11 +243,12 @@ sub assertNoExtendedAttributesInTypedef my $name = shift; my $line = shift; my $typedef = $typedefs{$name}; - my $msg = "Unexpected extendedAttributeList in typedef \"$name\" at " . $self->{Line}; + my $msg = "Unexpected extendedAttributeList in typedef \"$name\" on line " . $self->{Line}; if (defined ($line)) { $msg .= " IDLParser.pm:" . $line; } - die $msg if %{$typedef->extendedAttributes}; + + assert $msg if %{$typedef->extendedAttributes}; } sub Parse @@ -196,15 +272,19 @@ sub Parse my $next = $self->nextToken(); $self->assertTokenType($next, EmptyToken); }; - die $@ . " in $fileName" if $@; + assert $@ . " in $fileName" if $@; - my $document = idlDocument->new(); + my $document = IDLDocument->new(); $document->fileName($fileName); foreach my $definition (@definitions) { - if (ref($definition) eq "domInterface") { + if (ref($definition) eq "IDLInterface") { push(@{$document->interfaces}, $definition); - } elsif (ref($definition) eq "domEnum") { + } elsif (ref($definition) eq "IDLEnum") { push(@{$document->enumerations}, $definition); + } elsif (ref($definition) eq "IDLDictionary") { + push(@{$document->dictionaries}, $definition); + } elsif (ref($definition) eq "IDLCallbackFunction") { + push(@{$document->callbackFunctions}, $definition); } else { die "Unrecognized IDL definition kind: \"" . ref($definition) . "\""; } @@ -231,7 +311,7 @@ my $floatTokenPattern = '^(-?(([0-9]+\.[0-9]*|[0-9]*\.[0-9]+)([Ee][+-]?[0-9]+)?| my $integerTokenPattern = '^(-?[1-9][0-9]*|-?0[Xx][0-9A-Fa-f]+|-?0[0-7]*)'; my $stringTokenPattern = '^(\"[^\"]*\")'; my $identifierTokenPattern = '^([A-Z_a-z][0-9A-Z_a-z]*)'; -my $otherTokenPattern = '^(::|\.\.\.|[^\t\n\r 0-9A-Z_a-z])'; +my $otherTokenPattern = '^(\.\.\.|[^\t\n\r 0-9A-Z_a-z])'; sub getTokenInternal { @@ -296,51 +376,75 @@ sub unquoteString die "Failed to parse string (" . $quotedString . ") at " . $self->{Line}; } -sub typeHasNullableSuffix +sub identifierRemoveNullablePrefix { my $type = shift; - return $type =~ /\?$/; + $type =~ s/^_//; + return $type; } -sub typeRemoveNullableSuffix +sub typeDescription { my $type = shift; - $type =~ s/\?//g; + + if (scalar @{$type->subtypes}) { + return $type->name . '<' . join(', ', map { typeDescription($_) } @{$type->subtypes}) . '>' . ($type->isNullable ? "?" : ""); + } + + return $type->name . ($type->isNullable ? "?" : ""); +} + +sub makeSimpleType +{ + my $typeName = shift; + + my $type = IDLType->new(); + $type->name($typeName); + return $type; } -sub identifierRemoveNullablePrefix +sub cloneType { + my $self = shift; my $type = shift; - $type =~ s/^_//; - return $type; + + my $clonedType = IDLType->new(); + $clonedType->name($type->name); + $clonedType->isNullable($type->isNullable); + $clonedType->isUnion($type->isUnion); + foreach my $subtype (@{$type->subtypes}) { + push(@{$clonedType->subtypes}, $self->cloneType($subtype)); + } + + return $clonedType; } my $nextAttribute_1 = '^(attribute|inherit|readonly)$'; my $nextPrimitiveType_1 = '^(int|long|short|unsigned)$'; my $nextPrimitiveType_2 = '^(double|float|unrestricted)$'; -my $nextArgumentList_1 = '^(\(|::|ByteString|DOMString|Date|\[|any|boolean|byte|double|float|in|int|long|object|octet|optional|sequence|short|unrestricted|unsigned)$'; -my $nextNonAnyType_1 = '^(boolean|byte|double|float|int|long|octet|short|unrestricted|unsigned)$'; -my $nextInterfaceMember_1 = '^(\(|::|ByteString|DOMString|Date|any|attribute|boolean|byte|creator|deleter|double|float|getter|inherit|int|legacycaller|long|object|octet|readonly|sequence|serializer|setter|short|static|stringifier|unrestricted|unsigned|void)$'; -my $nextOptionalIteratorInterfaceOrObject_1 = '^(;|=)$'; -my $nextAttributeOrOperationOrIterator_1 = '^(static|stringifier)$'; -my $nextAttributeOrOperationOrIterator_2 = '^(\(|::|ByteString|DOMString|Date|any|boolean|byte|creator|deleter|double|float|getter|int|legacycaller|long|object|octet|sequence|setter|short|unrestricted|unsigned|void)$'; +my $nextArgumentList_1 = '^(\(|ByteString|DOMString|USVString|Date|\[|any|boolean|byte|double|float|in|long|object|octet|optional|sequence|short|unrestricted|unsigned)$'; +my $nextNonAnyType_1 = '^(boolean|byte|double|float|long|octet|short|unrestricted|unsigned)$'; +my $nextStringType_1 = '^(ByteString|DOMString|USVString)$'; +my $nextInterfaceMember_1 = '^(\(|ByteString|DOMString|USVString|Date|any|attribute|boolean|byte|creator|deleter|double|float|getter|inherit|legacycaller|long|object|octet|readonly|sequence|serializer|setter|short|static|stringifier|unrestricted|unsigned|void)$'; +my $nextAttributeOrOperation_1 = '^(static|stringifier)$'; +my $nextAttributeOrOperation_2 = '^(\(|ByteString|DOMString|USVString|Date|any|boolean|byte|creator|deleter|double|float|getter|legacycaller|long|object|octet|sequence|setter|short|unrestricted|unsigned|void)$'; my $nextUnrestrictedFloatType_1 = '^(double|float)$'; -my $nextExtendedAttributeRest3_1 = '^(\,|::|\])$'; -my $nextExceptionField_1 = '^(\(|::|ByteString|DOMString|Date|any|boolean|byte|double|float|int|long|object|octet|sequence|short|unrestricted|unsigned)$'; -my $nextType_1 = '^(::|ByteString|DOMString|Date|any|boolean|byte|double|float|int|long|object|octet|sequence|short|unrestricted|unsigned)$'; +my $nextExtendedAttributeRest3_1 = '^(\,|\])$'; +my $nextExceptionField_1 = '^(\(|ByteString|DOMString|USVString|Date|any|boolean|byte|double|float|long|object|octet|sequence|short|unrestricted|unsigned)$'; +my $nextType_1 = '^(ByteString|DOMString|USVString|Date|any|boolean|byte|double|float|long|object|octet|sequence|short|unrestricted|unsigned)$'; my $nextSpecials_1 = '^(creator|deleter|getter|legacycaller|setter)$'; -my $nextDefinitions_1 = '^(::|callback|dictionary|enum|exception|interface|partial|typedef)$'; -my $nextExceptionMembers_1 = '^(\(|::|ByteString|DOMString|Date|\[|any|boolean|byte|const|double|float|int|long|object|octet|optional|sequence|short|unrestricted|unsigned)$'; +my $nextDefinitions_1 = '^(callback|dictionary|enum|exception|interface|partial|typedef)$'; +my $nextExceptionMembers_1 = '^(\(|ByteString|DOMString|USVString|Date|\[|any|boolean|byte|const|double|float|long|object|octet|optional|sequence|short|unrestricted|unsigned)$'; my $nextAttributeRest_1 = '^(attribute|readonly)$'; -my $nextInterfaceMembers_1 = '^(\(|::|ByteString|DOMString|Date|any|attribute|boolean|byte|const|creator|deleter|double|float|getter|inherit|int|legacycaller|long|object|octet|readonly|sequence|serializer|setter|short|static|stringifier|unrestricted|unsigned|void)$'; -my $nextSingleType_1 = '^(::|ByteString|DOMString|Date|boolean|byte|double|float|int|long|object|octet|sequence|short|unrestricted|unsigned)$'; +my $nextInterfaceMembers_1 = '^(\(|ByteString|DOMString|USVString|Date|any|attribute|boolean|byte|const|creator|deleter|double|float|getter|inherit|legacycaller|long|object|octet|readonly|sequence|serializer|setter|short|static|stringifier|unrestricted|unsigned|void)$'; +my $nextSingleType_1 = '^(ByteString|DOMString|USVString|Date|boolean|byte|double|float|long|object|octet|sequence|short|unrestricted|unsigned)$'; my $nextArgumentName_1 = '^(attribute|callback|const|creator|deleter|dictionary|enum|exception|getter|implements|inherit|interface|legacycaller|partial|serializer|setter|static|stringifier|typedef|unrestricted)$'; my $nextConstValue_1 = '^(false|true)$'; my $nextConstValue_2 = '^(-|Infinity|NaN)$'; my $nextDefinition_1 = '^(callback|interface)$'; -my $nextAttributeOrOperationRest_1 = '^(\(|::|ByteString|DOMString|Date|any|boolean|byte|double|float|int|long|object|octet|sequence|short|unrestricted|unsigned|void)$'; -my $nextUnsignedIntegerType_1 = '^(int|long|short)$'; +my $nextAttributeOrOperationRest_1 = '^(\(|ByteString|DOMString|USVString|Date|any|boolean|byte|double|float|long|object|octet|sequence|short|unrestricted|unsigned|void)$'; +my $nextUnsignedIntegerType_1 = '^(long|short)$'; my $nextDefaultValue_1 = '^(-|Infinity|NaN|false|null|true)$'; @@ -374,59 +478,71 @@ sub applyTypedefs if (!%typedefs) { return; } + + # FIXME: Add support for applying typedefs to IDLIterable. foreach my $definition (@$definitions) { - if (ref($definition) eq "domInterface") { + if (ref($definition) eq "IDLInterface") { foreach my $constant (@{$definition->constants}) { - if (exists $typedefs{$constant->type}) { - my $typedef = $typedefs{$constant->type}; - $self->assertNoExtendedAttributesInTypedef($constant->type, __LINE__); - $constant->type($typedef->type); - } + $constant->type($self->typeByApplyingTypedefs($constant->type)); } foreach my $attribute (@{$definition->attributes}) { - $self->applyTypedefsForSignature($attribute->signature); + $attribute->type($self->typeByApplyingTypedefs($attribute->type)); } - foreach my $function (@{$definition->functions}, @{$definition->anonymousFunctions}, @{$definition->constructors}, @{$definition->customConstructors}) { - $self->applyTypedefsForSignature($function->signature); - foreach my $signature (@{$function->parameters}) { - $self->applyTypedefsForSignature($signature); - } + foreach my $operation (@{$definition->functions}, @{$definition->anonymousFunctions}, @{$definition->constructors}, @{$definition->customConstructors}) { + $self->applyTypedefsToOperation($operation); } + } elsif (ref($definition) eq "IDLDictionary") { + foreach my $member (@{$definition->members}) { + $member->type($self->typeByApplyingTypedefs($member->type)); + } + } elsif (ref($definition) eq "IDLCallbackFunction") { + $self->applyTypedefsToOperation($definition->operation); } } } -sub applyTypedefsForSignature +sub applyTypedefsToOperation { my $self = shift; - my $signature = shift; + my $operation = shift; - if (!defined ($signature->type)) { - return; + if ($operation->type) { + $operation->type($self->typeByApplyingTypedefs($operation->type)); } - my $type = $signature->type; - $type =~ s/[\?\[\]]+$//g; - my $typeSuffix = $signature->type; - $typeSuffix =~ s/^[^\?\[\]]+//g; - if (exists $typedefs{$type}) { - my $typedef = $typedefs{$type}; - $signature->type($typedef->type . $typeSuffix); - copyExtendedAttributes($signature->extendedAttributes, $typedef->extendedAttributes); + foreach my $argument (@{$operation->arguments}) { + $argument->type($self->typeByApplyingTypedefs($argument->type)); } +} - # Handle union types, sequences and etc. - foreach my $name (%typedefs) { - if (!exists $typedefs{$name}) { - next; +sub typeByApplyingTypedefs +{ + my $self = shift; + my $type = shift; + + assert("Missing type") if !$type; + + my $numberOfSubtypes = scalar @{$type->subtypes}; + if ($numberOfSubtypes) { + for my $i (0..$numberOfSubtypes - 1) { + my $subtype = @{$type->subtypes}[$i]; + my $replacementSubtype = $self->typeByApplyingTypedefs($subtype); + @{$type->subtypes}[$i] = $replacementSubtype } - my $typedef = $typedefs{$name}; - my $regex = '\\b' . $name . '\\b'; - my $replacement = $typedef->type; - my $type = $signature->type; - $type =~ s/($regex)/$replacement/g; - $signature->type($type); + + return $type; } + + if (exists $typedefs{$type->name}) { + my $typedef = $typedefs{$type->name}; + + my $clonedType = $self->cloneType($typedef->type); + $clonedType->isNullable($clonedType->isNullable || $type->isNullable); + + return $self->typeByApplyingTypedefs($clonedType); + } + + return $type; } sub parseDefinition @@ -453,7 +569,7 @@ sub parseDefinition if ($next->value() eq "typedef") { return $self->parseTypedef($extendedAttributeList); } - if ($next->type() == IdentifierToken || $next->value() eq "::") { + if ($next->type() == IdentifierToken) { return $self->parseImplementsStatement($extendedAttributeList); } $self->assertUnexpectedToken($next->value(), __LINE__); @@ -499,14 +615,20 @@ sub parseInterface my $next = $self->nextToken(); if ($next->value() eq "interface") { - my $interface = domInterface->new(); + my $interface = IDLInterface->new(); $self->assertTokenValue($self->getToken(), "interface", __LINE__); my $interfaceNameToken = $self->getToken(); $self->assertTokenType($interfaceNameToken, IdentifierToken); - $interface->name(identifierRemoveNullablePrefix($interfaceNameToken->value())); - my $parents = $self->parseInheritance(); - $interface->parents($parents); - $interface->parent($parents->[0]); + + my $name = identifierRemoveNullablePrefix($interfaceNameToken->value()); + $interface->type(makeSimpleType($name)); + + $next = $self->nextToken(); + if ($next->value() eq ":") { + my $parent = $self->parseInheritance(); + $interface->parentType(makeSimpleType($parent)); + } + $self->assertTokenValue($self->getToken(), "{", __LINE__); my $interfaceMembers = $self->parseInterfaceMembers(); $self->assertTokenValue($self->getToken(), "}", __LINE__); @@ -610,14 +732,27 @@ sub parseDictionary my $next = $self->nextToken(); if ($next->value() eq "dictionary") { + my $dictionary = IDLDictionary->new(); + $dictionary->extendedAttributes($extendedAttributeList); $self->assertTokenValue($self->getToken(), "dictionary", __LINE__); - $self->assertTokenType($self->getToken(), IdentifierToken); - $self->parseInheritance(); + + my $nameToken = $self->getToken(); + $self->assertTokenType($nameToken, IdentifierToken); + + my $name = $nameToken->value(); + $dictionary->type(makeSimpleType($name)); + + $next = $self->nextToken(); + if ($next->value() eq ":") { + my $parent = $self->parseInheritance(); + $dictionary->parentType(makeSimpleType($parent)); + } + $self->assertTokenValue($self->getToken(), "{", __LINE__); - $self->parseDictionaryMembers(); + $dictionary->members($self->parseDictionaryMembers()); $self->assertTokenValue($self->getToken(), "}", __LINE__); $self->assertTokenValue($self->getToken(), ";", __LINE__); - return; + return $dictionary; } $self->assertUnexpectedToken($next->value(), __LINE__); } @@ -626,15 +761,19 @@ sub parseDictionaryMembers { my $self = shift; + my @members = (); + while (1) { my $extendedAttributeList = $self->parseExtendedAttributeListAllowEmpty(); my $next = $self->nextToken(); if ($next->type() == IdentifierToken || $next->value() =~ /$nextExceptionField_1/) { - $self->parseDictionaryMember($extendedAttributeList); + push(@members, $self->parseDictionaryMember($extendedAttributeList)); } else { last; } } + + return \@members; } sub parseDictionaryMember @@ -644,11 +783,24 @@ sub parseDictionaryMember my $next = $self->nextToken(); if ($next->type() == IdentifierToken || $next->value() =~ /$nextExceptionField_1/) { - $self->parseType(); - $self->assertTokenType($self->getToken(), IdentifierToken); - $self->parseDefault(); + my $member = IDLDictionaryMember->new(); + if ($next->value eq "required") { + $self->assertTokenValue($self->getToken(), "required", __LINE__); + $member->isRequired(1); + } else { + $member->isRequired(0); + } + $member->extendedAttributes($extendedAttributeList); + + my $type = $self->parseType(); + $member->type($type); + + my $nameToken = $self->getToken(); + $self->assertTokenType($nameToken, IdentifierToken); + $member->name($nameToken->value); + $member->default($self->parseDefault()); $self->assertTokenValue($self->getToken(), ";", __LINE__); - return; + return $member; } $self->assertUnexpectedToken($next->value(), __LINE__); } @@ -677,6 +829,7 @@ sub parseDefault $self->assertTokenValue($self->getToken(), "=", __LINE__); return $self->parseDefaultValue(); } + return undef; } sub parseDefaultValue @@ -689,6 +842,11 @@ sub parseDefaultValue if ($next->type() == StringToken) { return $self->getToken()->value(); } + if ($next->value() eq "[") { + $self->assertTokenValue($self->getToken(), "[", __LINE__); + $self->assertTokenValue($self->getToken(), "]", __LINE__); + return "[]"; + } $self->assertUnexpectedToken($next->value(), __LINE__); } @@ -699,15 +857,21 @@ sub parseException my $next = $self->nextToken(); if ($next->value() eq "exception") { - my $interface = domInterface->new(); + my $interface = IDLInterface->new(); $self->assertTokenValue($self->getToken(), "exception", __LINE__); my $exceptionNameToken = $self->getToken(); $self->assertTokenType($exceptionNameToken, IdentifierToken); - $interface->name(identifierRemoveNullablePrefix($exceptionNameToken->value())); + + my $name = identifierRemoveNullablePrefix($exceptionNameToken->value()); + $interface->type(makeSimpleType($name)); $interface->isException(1); - my $parents = $self->parseInheritance(); - $interface->parents($parents); - $interface->parent($parents->[0]); + + $next = $self->nextToken(); + if ($next->value() eq ":") { + my $parent = $self->parseInheritance(); + $interface->parentType(makeSimpleType($parent)); + } + $self->assertTokenValue($self->getToken(), "{", __LINE__); my $exceptionMembers = $self->parseExceptionMembers(); $self->assertTokenValue($self->getToken(), "}", __LINE__); @@ -743,35 +907,34 @@ sub parseExceptionMembers sub parseInheritance { my $self = shift; - my @parent = (); my $next = $self->nextToken(); if ($next->value() eq ":") { $self->assertTokenValue($self->getToken(), ":", __LINE__); - my $scopedName = $self->parseScopedName(); - push(@parent, $scopedName); - # Multiple inheritance (needed for ObjC bindings). - push(@parent, @{$self->parseIdentifiers()}); + return $self->parseName(); } - return \@parent; + $self->assertUnexpectedToken($next->value(), __LINE__); } sub parseEnum { my $self = shift; - my $extendedAttributeList = shift; # ignored: Extended attributes are not applicable to enumerations + my $extendedAttributeList = shift; my $next = $self->nextToken(); if ($next->value() eq "enum") { - my $enum = domEnum->new(); + my $enum = IDLEnum->new(); $self->assertTokenValue($self->getToken(), "enum", __LINE__); my $enumNameToken = $self->getToken(); $self->assertTokenType($enumNameToken, IdentifierToken); - $enum->name(identifierRemoveNullablePrefix($enumNameToken->value())); + my $name = identifierRemoveNullablePrefix($enumNameToken->value()); + $enum->name($name); + $enum->type(makeSimpleType($name)); $self->assertTokenValue($self->getToken(), "{", __LINE__); push(@{$enum->values}, @{$self->parseEnumValueList()}); $self->assertTokenValue($self->getToken(), "}", __LINE__); $self->assertTokenValue($self->getToken(), ";", __LINE__); + $enum->extendedAttributes($extendedAttributeList); return $enum; } $self->assertUnexpectedToken($next->value(), __LINE__); @@ -818,14 +981,30 @@ sub parseCallbackRest my $next = $self->nextToken(); if ($next->type() == IdentifierToken) { - $self->assertTokenType($self->getToken(), IdentifierToken); + my $callback = IDLCallbackFunction->new(); + + my $nameToken = $self->getToken(); + $self->assertTokenType($nameToken, IdentifierToken); + + $callback->type(makeSimpleType($nameToken->value())); + $self->assertTokenValue($self->getToken(), "=", __LINE__); - $self->parseReturnType(); + + my $operation = IDLOperation->new(); + $operation->type($self->parseReturnType()); + $operation->extendedAttributes($extendedAttributeList); + $self->assertTokenValue($self->getToken(), "(", __LINE__); - $self->parseArgumentList(); + + push(@{$operation->arguments}, @{$self->parseArgumentList()}); + $self->assertTokenValue($self->getToken(), ")", __LINE__); $self->assertTokenValue($self->getToken(), ";", __LINE__); - return; + + $callback->operation($operation); + $callback->extendedAttributes($extendedAttributeList); + + return $callback; } $self->assertUnexpectedToken($next->value(), __LINE__); } @@ -839,14 +1018,16 @@ sub parseTypedef my $next = $self->nextToken(); if ($next->value() eq "typedef") { $self->assertTokenValue($self->getToken(), "typedef", __LINE__); - my $typedef = Typedef->new(); - $typedef->extendedAttributes($self->parseExtendedAttributeListAllowEmpty()); - $typedef->type($self->parseType()); + my $typedef = IDLTypedef->new(); + + my $type = $self->parseType(); + $typedef->type($type); + my $nameToken = $self->getToken(); $self->assertTokenType($nameToken, IdentifierToken); $self->assertTokenValue($self->getToken(), ";", __LINE__); my $name = $nameToken->value(); - die "typedef redefinition for " . $name . " at " . $self->{Line} if (exists $typedefs{$name} && $typedef->type ne $typedefs{$name}->type); + die "typedef redefinition for " . $name . " at " . $self->{Line} if (exists $typedefs{$name} && $typedef->type->name ne $typedefs{$name}->type->name); $typedefs{$name} = $typedef; return; } @@ -860,9 +1041,9 @@ sub parseImplementsStatement my $next = $self->nextToken(); if ($next->type() == IdentifierToken) { - $self->parseScopedName(); + $self->parseName(); $self->assertTokenValue($self->getToken(), "implements", __LINE__); - $self->parseScopedName(); + $self->parseName(); $self->assertTokenValue($self->getToken(), ";", __LINE__); return; } @@ -876,9 +1057,10 @@ sub parseConst my $next = $self->nextToken(); if ($next->value() eq "const") { - my $newDataNode = domConstant->new(); + my $newDataNode = IDLConstant->new(); $self->assertTokenValue($self->getToken(), "const", __LINE__); - $newDataNode->type($self->parseConstType()); + my $type = $self->parseConstType(); + $newDataNode->type($type); my $constNameToken = $self->getToken(); $self->assertTokenType($constNameToken, IdentifierToken); $newDataNode->name(identifierRemoveNullablePrefix($constNameToken->value())); @@ -905,10 +1087,6 @@ sub parseConstValue if ($next->type() == FloatToken || $next->value() =~ /$nextConstValue_2/) { return $self->parseFloatLiteral(); } - # backward compatibility - if ($next->type() == StringToken) { - return $self->getToken()->value(); - } if ($next->type() == IntegerToken) { return $self->getToken()->value(); } @@ -962,18 +1140,19 @@ sub parseAttributeOrOperationOrIterator if ($next->value() eq "serializer") { return $self->parseSerializer($extendedAttributeList); } - if ($next->value() =~ /$nextAttributeOrOperationOrIterator_1/) { + if ($next->value() =~ /$nextAttributeOrOperation_1/) { my $qualifier = $self->parseQualifier(); my $newDataNode = $self->parseAttributeOrOperationRest($extendedAttributeList); - if (defined($newDataNode) && $qualifier eq "static") { - $newDataNode->isStatic(1); + if (defined($newDataNode)) { + $newDataNode->isStatic(1) if $qualifier eq "static"; + $newDataNode->isStringifier(1) if $qualifier eq "stringifier"; } return $newDataNode; } if ($next->value() =~ /$nextAttribute_1/) { return $self->parseAttribute($extendedAttributeList); } - if ($next->type() == IdentifierToken || $next->value() =~ /$nextAttributeOrOperationOrIterator_2/) { + if ($next->type() == IdentifierToken || $next->value() =~ /$nextAttributeOrOperation_2/) { return $self->parseOperationOrIterator($extendedAttributeList); } $self->assertUnexpectedToken($next->value(), __LINE__); @@ -987,7 +1166,22 @@ sub parseSerializer my $next = $self->nextToken(); if ($next->value() eq "serializer") { $self->assertTokenValue($self->getToken(), "serializer", __LINE__); - return $self->parseSerializerRest($extendedAttributeList); + my $next = $self->nextToken(); + my $newDataNode; + if ($next->value() ne ";") { + $newDataNode = $self->parseSerializerRest($extendedAttributeList); + my $next = $self->nextToken(); + } else { + $newDataNode = IDLSerializable->new(); + } + + my $toJSONFunction = IDLOperation->new(); + $toJSONFunction->name("toJSON"); + $toJSONFunction->extendedAttributes($extendedAttributeList); + push(@{$newDataNode->functions}, $toJSONFunction); + + $self->assertTokenValue($self->getToken(), ";", __LINE__); + return $newDataNode; } $self->assertUnexpectedToken($next->value(), __LINE__); } @@ -1000,7 +1194,9 @@ sub parseSerializerRest my $next = $self->nextToken(); if ($next->value() eq "=") { $self->assertTokenValue($self->getToken(), "=", __LINE__); - return $self->parseSerializationPattern($extendedAttributeList); + + return $self->parseSerializationPattern(); + } if ($next->type() == IdentifierToken || $next->value() eq "(") { return $self->parseOperationRest($extendedAttributeList); @@ -1010,59 +1206,74 @@ sub parseSerializerRest sub parseSerializationPattern { my $self = shift; - my $extendedAttributeList = shift; my $next = $self->nextToken(); if ($next->value() eq "{") { $self->assertTokenValue($self->getToken(), "{", __LINE__); - $self->parseSerializationPatternMap(); + my $newDataNode = IDLSerializable->new(); + $self->parseSerializationAttributes($newDataNode); $self->assertTokenValue($self->getToken(), "}", __LINE__); - return; + return $newDataNode; } if ($next->value() eq "[") { - $self->assertTokenValue($self->getToken(), "[", __LINE__); - $self->parseSerializationPatternList(); - $self->assertTokenValue($self->getToken(), "]", __LINE__); - return; + die "Serialization of lists pattern is not currently supported."; } if ($next->type() == IdentifierToken) { - $self->assertTokenType($self->getToken(), IdentifierToken); - return; + my @attributes = (); + my $token = $self->getToken(); + $self->assertTokenType($token, IdentifierToken); + push(@attributes, $token->value()); + + my $newDataNode = IDLSerializable->new(); + $newDataNode->attributes(\@attributes); + + return $newDataNode; } $self->assertUnexpectedToken($next->value(), __LINE__); } -sub parseSerializationPatternMap +sub parseSerializationAttributes { my $self = shift; - my $next = $self->nextToken(); - if ($next->value() eq "getter") { - $self->assertTokenValue($self->getToken(), "getter", __LINE__); - return; - } - if ($next->value() eq "inherit") { - $self->assertTokenValue($self->getToken(), "inherit", __LINE__); - $self->parseIdentifiers(); - return; - } - if ($next->type() == IdentifierToken) { - $self->assertTokenType($self->getToken(), IdentifierToken); - $self->parseIdentifiers(); + my $serializable = shift; + + my @attributes = (); + my @identifiers = $self->parseIdentifierList(); + + for my $identifier (@identifiers) { + if ($identifier eq "getter") { + $serializable->hasGetter(1); + die "Serializer getter keyword is not currently supported."; + } + + if ($identifier eq "inherit") { + $serializable->hasInherit(1); + next; + } + + if ($identifier eq "attribute") { + $serializable->hasAttribute(1); + # Attributes will be filled in via applyMemberList() + next; + } + + push(@attributes, $identifier); } + + $serializable->attributes(\@attributes); } -sub parseSerializationPatternList +sub parseIdentifierList { my $self = shift; my $next = $self->nextToken(); - if ($next->value() eq "getter") { - $self->assertTokenValue($self->getToken(), "getter", __LINE__); - return; - } - if ($next->type() == IdentifierToken) { - $self->assertTokenType($self->getToken(), IdentifierToken); - $self->parseIdentifiers(); + + my @identifiers = (); + if ($next->type == IdentifierToken) { + push(@identifiers, $self->getToken()->value()); + push(@identifiers, @{$self->parseIdentifiers()}); } + return @identifiers; } sub parseIdentifiers @@ -1115,11 +1326,11 @@ sub parseAttributeOrOperationRest } if ($next->type() == IdentifierToken || $next->value() =~ /$nextAttributeOrOperationRest_1/) { my $returnType = $self->parseReturnType(); - my $interface = $self->parseOperationRest($extendedAttributeList); - if (defined ($interface)) { - $interface->signature->type($returnType); + my $operation = $self->parseOperationRest($extendedAttributeList); + if (defined ($operation)) { + $operation->type($returnType); } - return $interface; + return $operation; } $self->assertUnexpectedToken($next->value(), __LINE__); } @@ -1144,33 +1355,25 @@ sub parseAttributeRest my $next = $self->nextToken(); if ($next->value() =~ /$nextAttributeRest_1/) { - my $newDataNode = domAttribute->new(); - if ($self->parseReadOnly()) { - $newDataNode->type("attribute"); - $newDataNode->isReadOnly(1); - } else { - $newDataNode->type("attribute"); - } + my $newDataNode = IDLAttribute->new(); + $newDataNode->isReadOnly($self->parseReadOnly()); + $self->assertTokenValue($self->getToken(), "attribute", __LINE__); - $newDataNode->signature(domSignature->new()); + my $type = $self->parseType(); - if (typeHasNullableSuffix($type)) { - $newDataNode->signature->isNullable(1); - } else { - $newDataNode->signature->isNullable(0); - } - # Remove all "?" in the type declaration, e.g. "double?" -> "double". - $newDataNode->signature->type(typeRemoveNullableSuffix($type)); + $newDataNode->type($type); + my $token = $self->getToken(); $self->assertTokenType($token, IdentifierToken); - $newDataNode->signature->name(identifierRemoveNullablePrefix($token->value())); + $newDataNode->name(identifierRemoveNullablePrefix($token->value())); $self->assertTokenValue($self->getToken(), ";", __LINE__); + # CustomConstructor may also be used on attributes. if (defined $extendedAttributeList->{"CustomConstructors"}) { delete $extendedAttributeList->{"CustomConstructors"}; $extendedAttributeList->{"CustomConstructor"} = "VALUE_IS_MISSING"; } - $newDataNode->signature->extendedAttributes($extendedAttributeList); + $newDataNode->extendedAttributes($extendedAttributeList); return $newDataNode; } $self->assertUnexpectedToken($next->value(), __LINE__); @@ -1207,13 +1410,17 @@ sub parseOperationOrIterator if ($next->value() =~ /$nextSpecials_1/) { return $self->parseSpecialOperation($extendedAttributeList); } + if ($next->value() eq "iterable") { + return $self->parseIterableRest($extendedAttributeList); + } if ($next->type() == IdentifierToken || $next->value() =~ /$nextAttributeOrOperationRest_1/) { my $returnType = $self->parseReturnType(); - my $interface = $self->parseOperationOrIteratorRest($extendedAttributeList); - if (defined ($interface)) { - $interface->signature->type($returnType); + my $next = $self->nextToken(); + if ($next->type() == IdentifierToken || $next->value() eq "(") { + my $operation = $self->parseOperationRest($extendedAttributeList); + $operation->type($returnType); + return $operation; } - return $interface; } $self->assertUnexpectedToken($next->value(), __LINE__); } @@ -1228,12 +1435,12 @@ sub parseSpecialOperation my @specials = (); push(@specials, @{$self->parseSpecials()}); my $returnType = $self->parseReturnType(); - my $interface = $self->parseOperationRest($extendedAttributeList); - if (defined ($interface)) { - $interface->signature->type($returnType); - $interface->signature->specials(\@specials); + my $operation = $self->parseOperationRest($extendedAttributeList); + if (defined ($operation)) { + $operation->type($returnType); + $operation->specials(\@specials); } - return $interface; + return $operation; } $self->assertUnexpectedToken($next->value(), __LINE__); } @@ -1281,62 +1488,75 @@ sub parseSpecial $self->assertUnexpectedToken($next->value(), __LINE__); } -sub parseOperationOrIteratorRest +sub parseIterableRest { my $self = shift; my $extendedAttributeList = shift; my $next = $self->nextToken(); - if ($next->value() eq "iterator") { - return $self->parseIteratorRest($extendedAttributeList); - } - if ($next->type() == IdentifierToken || $next->value() eq "(") { - return $self->parseOperationRest($extendedAttributeList); - } - $self->assertUnexpectedToken($next->value(), __LINE__); -} - -sub parseIteratorRest -{ - my $self = shift; - my $extendedAttributeList = shift; - - my $next = $self->nextToken(); - if ($next->value() eq "iterator") { - $self->assertTokenValue($self->getToken(), "iterator", __LINE__); - $self->parseOptionalIteratorInterfaceOrObject($extendedAttributeList); + if ($next->value() eq "iterable") { + $self->assertTokenValue($self->getToken(), "iterable", __LINE__); + my $iterableNode = $self->parseOptionalIterableInterface($extendedAttributeList); $self->assertTokenValue($self->getToken(), ";", __LINE__); - return; + return $iterableNode; } $self->assertUnexpectedToken($next->value(), __LINE__); } -sub parseOptionalIteratorInterfaceOrObject +sub parseOptionalIterableInterface { my $self = shift; my $extendedAttributeList = shift; - my $next = $self->nextToken(); - if ($next->value() =~ /$nextOptionalIteratorInterfaceOrObject_1/) { - return $self->parseOptionalIteratorInterface($extendedAttributeList); - } - if ($next->value() eq "object") { - $self->assertTokenValue($self->getToken(), "object", __LINE__); - return; - } - $self->assertUnexpectedToken($next->value(), __LINE__); -} - -sub parseOptionalIteratorInterface -{ - my $self = shift; - my $extendedAttributeList = shift; + my $symbolIteratorFunction = IDLOperation->new(); + $symbolIteratorFunction->name("[Symbol.Iterator]"); + $symbolIteratorFunction->extendedAttributes($extendedAttributeList); + + my $entriesFunction = IDLOperation->new(); + $entriesFunction->name("entries"); + $entriesFunction->extendedAttributes($extendedAttributeList); + + my $keysFunction = IDLOperation->new(); + $keysFunction->name("keys"); + $keysFunction->extendedAttributes($extendedAttributeList); + + my $valuesFunction = IDLOperation->new(); + $valuesFunction->name("values"); + $valuesFunction->extendedAttributes($extendedAttributeList); + + my $forEachFunction = IDLOperation->new(); + $forEachFunction->name("forEach"); + $forEachFunction->extendedAttributes($extendedAttributeList); + my $forEachArgument = IDLArgument->new(); + $forEachArgument->name("callback"); + $forEachArgument->type(makeSimpleType("any")); + push(@{$forEachFunction->arguments}, ($forEachArgument)); + + my $newDataNode = IDLIterable->new(); + $newDataNode->extendedAttributes($extendedAttributeList); + push(@{$newDataNode->functions}, $symbolIteratorFunction); + push(@{$newDataNode->functions}, $entriesFunction); + push(@{$newDataNode->functions}, $keysFunction); + push(@{$newDataNode->functions}, $valuesFunction); + push(@{$newDataNode->functions}, $forEachFunction); + + $self->assertTokenValue($self->getToken(), "<", __LINE__); + my $type1 = $self->parseType(); + + if ($self->nextToken()->value() eq ",") { + $self->assertTokenValue($self->getToken(), ",", __LINE__); - my $next = $self->nextToken(); - if ($next->value() eq "=") { - $self->assertTokenValue($self->getToken(), "=", __LINE__); - $self->assertTokenType($self->getToken(), IdentifierToken); + my $type2 = $self->parseType(); + $newDataNode->isKeyValue(1); + $newDataNode->keyType($type1); + $newDataNode->valueType($type2); + } else { + $newDataNode->isKeyValue(0); + $newDataNode->valueType($type1); } + $self->assertTokenValue($self->getToken(), ">", __LINE__); + + return $newDataNode; } sub parseOperationRest @@ -1346,15 +1566,19 @@ sub parseOperationRest my $next = $self->nextToken(); if ($next->type() == IdentifierToken || $next->value() eq "(") { - my $newDataNode = domFunction->new(); - $newDataNode->signature(domSignature->new()); + my $newDataNode = IDLOperation->new(); + my $name = $self->parseOptionalIdentifier(); - $newDataNode->signature->name(identifierRemoveNullablePrefix($name)); + $newDataNode->name(identifierRemoveNullablePrefix($name)); + $self->assertTokenValue($self->getToken(), "(", $name, __LINE__); - push(@{$newDataNode->parameters}, @{$self->parseArgumentList()}); + + push(@{$newDataNode->arguments}, @{$self->parseArgumentList()}); + $self->assertTokenValue($self->getToken(), ")", __LINE__); $self->assertTokenValue($self->getToken(), ";", __LINE__); - $newDataNode->signature->extendedAttributes($extendedAttributeList); + + $newDataNode->extendedAttributes($extendedAttributeList); return $newDataNode; } $self->assertUnexpectedToken($next->value(), __LINE__); @@ -1406,10 +1630,8 @@ sub parseArgument my $self = shift; my $next = $self->nextToken(); if ($next->type() == IdentifierToken || $next->value() =~ /$nextArgumentList_1/) { - my $in = $self->parseIn(); my $extendedAttributeList = $self->parseExtendedAttributeListAllowEmpty(); my $argument = $self->parseOptionalOrRequiredArgument($extendedAttributeList); - $argument->direction($self->parseIn()); return $argument; } $self->assertUnexpectedToken($next->value(), __LINE__); @@ -1420,36 +1642,23 @@ sub parseOptionalOrRequiredArgument my $self = shift; my $extendedAttributeList = shift; - my $paramDataNode = domSignature->new(); + my $paramDataNode = IDLArgument->new(); $paramDataNode->extendedAttributes($extendedAttributeList); my $next = $self->nextToken(); if ($next->value() eq "optional") { $self->assertTokenValue($self->getToken(), "optional", __LINE__); + my $type = $self->parseType(); - # domDataNode can only consider last "?". - if (typeHasNullableSuffix($type)) { - $paramDataNode->isNullable(1); - } else { - $paramDataNode->isNullable(0); - } - # Remove all "?" if exists, e.g. "object?[]?" -> "object[]". - $paramDataNode->type(identifierRemoveNullablePrefix(typeRemoveNullableSuffix($type))); + $paramDataNode->type($type); $paramDataNode->isOptional(1); $paramDataNode->name($self->parseArgumentName()); - $self->parseDefault(); + $paramDataNode->default($self->parseDefault()); return $paramDataNode; } if ($next->type() == IdentifierToken || $next->value() =~ /$nextExceptionField_1/) { my $type = $self->parseType(); - # domDataNode can only consider last "?". - if (typeHasNullableSuffix($type)) { - $paramDataNode->isNullable(1); - } else { - $paramDataNode->isNullable(0); - } - # Remove all "?" if exists, e.g. "object?[]?" -> "object[]". - $paramDataNode->type(typeRemoveNullableSuffix($type)); + $paramDataNode->type($type); $paramDataNode->isOptional(0); $paramDataNode->isVariadic($self->parseEllipsis()); $paramDataNode->name($self->parseArgumentName()); @@ -1504,16 +1713,17 @@ sub parseExceptionField my $next = $self->nextToken(); if ($next->type() == IdentifierToken || $next->value() =~ /$nextExceptionField_1/) { - my $newDataNode = domAttribute->new(); - $newDataNode->type("attribute"); + my $newDataNode = IDLAttribute->new(); $newDataNode->isReadOnly(1); - $newDataNode->signature(domSignature->new()); - $newDataNode->signature->type($self->parseType()); + + my $type = $self->parseType(); + $newDataNode->type($type); + my $token = $self->getToken(); $self->assertTokenType($token, IdentifierToken); - $newDataNode->signature->name(identifierRemoveNullablePrefix($token->value())); + $newDataNode->name(identifierRemoveNullablePrefix($token->value())); $self->assertTokenValue($self->getToken(), ";", __LINE__); - $newDataNode->signature->extendedAttributes($extendedAttributeList); + $newDataNode->extendedAttributes($extendedAttributeList); return $newDataNode; } $self->assertUnexpectedToken($next->value(), __LINE__); @@ -1594,9 +1804,9 @@ sub parseExtendedAttribute { my $self = shift; my $next = $self->nextToken(); - if ($next->type() == IdentifierToken || $next->value() eq "::") { - my $scopedName = $self->parseScopedName(); - return $self->parseExtendedAttributeRest($scopedName); + if ($next->type() == IdentifierToken) { + my $name = $self->parseName(); + return $self->parseExtendedAttributeRest($name); } # backward compatibility. Spec doesn' allow "[]". But WebKit requires. if ($next->value() eq ']') { @@ -1609,9 +1819,9 @@ sub parseExtendedAttribute2 { my $self = shift; my $next = $self->nextToken(); - if ($next->type() == IdentifierToken || $next->value() eq "::") { - my $scopedName = $self->parseScopedName(); - return $self->parseExtendedAttributeRest($scopedName); + if ($next->type() == IdentifierToken) { + my $name = $self->parseName(); + return $self->parseExtendedAttributeRest($name); } return {}; } @@ -1647,9 +1857,15 @@ sub parseExtendedAttributeRest2 { my $self = shift; my $next = $self->nextToken(); - if ($next->type() == IdentifierToken || $next->value() eq "::") { - my $scopedName = $self->parseScopedName(); - return $self->parseExtendedAttributeRest3($scopedName); + if ($next->value() eq "(") { + $self->assertTokenValue($self->getToken(), "(", __LINE__); + my @arguments = $self->parseIdentifierList(); + $self->assertTokenValue($self->getToken(), ")", __LINE__); + return @arguments; + } + if ($next->type() == IdentifierToken) { + my $name = $self->parseName(); + return $self->parseExtendedAttributeRest3($name); } if ($next->type() == IntegerToken) { my $token = $self->getToken(); @@ -1666,12 +1882,12 @@ sub parseExtendedAttributeRest3 my $next = $self->nextToken(); if ($next->value() eq "&") { $self->assertTokenValue($self->getToken(), "&", __LINE__); - my $rightValue = $self->parseScopedName(); + my $rightValue = $self->parseName(); return $name . "&" . $rightValue; } if ($next->value() eq "|") { $self->assertTokenValue($self->getToken(), "|", __LINE__); - my $rightValue = $self->parseScopedName(); + my $rightValue = $self->parseName(); return $name . "|" . $rightValue; } if ($next->value() eq "(") { @@ -1682,30 +1898,12 @@ sub parseExtendedAttributeRest3 return $attr; } if ($next->type() == IdentifierToken || $next->value() =~ /$nextExtendedAttributeRest3_1/) { - my @names = (); - push(@names, $name); - push(@names, @{$self->parseScopedNameListNoComma()}); - return join(' ', @names); + $self->parseNameNoComma(); + return $name; } $self->assertUnexpectedToken($next->value()); } -sub parseScopedNameListNoComma -{ - my $self = shift; - my @names = (); - - while (1) { - my $next = $self->nextToken(); - if ($next->type() == IdentifierToken || $next->value() eq "::") { - push(@names, $self->parseScopedName()); - } else { - last; - } - } - return \@names; -} - sub parseArgumentNameKeyword { my $self = shift; @@ -1778,9 +1976,9 @@ sub parseType my $self = shift; my $next = $self->nextToken(); if ($next->value() eq "(") { - $self->parseUnionType(); - $self->parseTypeSuffix(); - return; + my $unionType = $self->parseUnionType(); + $unionType->isNullable($self->parseNull()); + return $unionType; } if ($next->type() == IdentifierToken || $next->value() =~ /$nextType_1/) { return $self->parseSingleType(); @@ -1794,10 +1992,15 @@ sub parseSingleType my $next = $self->nextToken(); if ($next->value() eq "any") { $self->assertTokenValue($self->getToken(), "any", __LINE__); - return "any" . $self->parseTypeSuffixStartingWithArray(); + + my $anyType = IDLType->new(); + $anyType->name("any"); + return $anyType; } if ($next->type() == IdentifierToken || $next->value() =~ /$nextSingleType_1/) { - return $self->parseNonAnyType(); + my $nonAnyType = $self->parseNonAnyType(); + $nonAnyType->isNullable($self->parseNull()); + return $nonAnyType; } $self->assertUnexpectedToken($next->value(), __LINE__); } @@ -1806,14 +2009,20 @@ sub parseUnionType { my $self = shift; my $next = $self->nextToken(); + + my $unionType = IDLType->new(); + $unionType->name("UNION"); + $unionType->isUnion(1); + if ($next->value() eq "(") { $self->assertTokenValue($self->getToken(), "(", __LINE__); - $self->parseUnionMemberType(); - $self->assertTokenValue($self->getToken(), "or", __LINE__); - $self->parseUnionMemberType(); - $self->parseUnionMemberTypes(); + + push(@{$unionType->subtypes}, $self->parseUnionMemberType()); + push(@{$unionType->subtypes}, $self->parseUnionMemberTypes()); + $self->assertTokenValue($self->getToken(), ")", __LINE__); - return; + + return $unionType; } $self->assertUnexpectedToken($next->value(), __LINE__); } @@ -1823,20 +2032,14 @@ sub parseUnionMemberType my $self = shift; my $next = $self->nextToken(); if ($next->value() eq "(") { - $self->parseUnionType(); - $self->parseTypeSuffix(); - return; - } - if ($next->value() eq "any") { - $self->assertTokenValue($self->getToken(), "any", __LINE__); - $self->assertTokenValue($self->getToken(), "[", __LINE__); - $self->assertTokenValue($self->getToken(), "]", __LINE__); - $self->parseTypeSuffix(); - return; + my $unionType = $self->parseUnionType(); + $unionType->isNullable($self->parseNull()); + return $unionType; } if ($next->type() == IdentifierToken || $next->value() =~ /$nextSingleType_1/) { - $self->parseNonAnyType(); - return; + my $nonAnyType = $self->parseNonAnyType(); + $nonAnyType->isNullable($self->parseNull()); + return $nonAnyType; } $self->assertUnexpectedToken($next->value(), __LINE__); } @@ -1845,46 +2048,126 @@ sub parseUnionMemberTypes { my $self = shift; my $next = $self->nextToken(); + + my @subtypes = (); + if ($next->value() eq "or") { $self->assertTokenValue($self->getToken(), "or", __LINE__); - $self->parseUnionMemberType(); - $self->parseUnionMemberTypes(); + push(@subtypes, $self->parseUnionMemberType()); + push(@subtypes, $self->parseUnionMemberTypes()); } + + return @subtypes; } sub parseNonAnyType { my $self = shift; my $next = $self->nextToken(); + + my $type = IDLType->new(); + if ($next->value() =~ /$nextNonAnyType_1/) { - return $self->parsePrimitiveType() . $self->parseTypeSuffix(); + $type->name($self->parsePrimitiveType()); + return $type; } - if ($next->value() eq "ByteString") { - $self->assertTokenValue($self->getToken(), "ByteString", __LINE__); - return "ByteString" . $self->parseTypeSuffix(); + if ($next->value() =~ /$nextStringType_1/) { + $type->name($self->parseStringType()); + return $type; } - if ($next->value() eq "DOMString") { - $self->assertTokenValue($self->getToken(), "DOMString", __LINE__); - return "DOMString" . $self->parseTypeSuffix(); + if ($next->value() eq "object") { + $self->assertTokenValue($self->getToken(), "object", __LINE__); + + $type->name("object"); + return $type; + } + if ($next->value() eq "RegExp") { + $self->assertTokenValue($self->getToken(), "RegExp", __LINE__); + + $type->name("RegExp"); + return $type; + } + if ($next->value() eq "Error") { + $self->assertTokenValue($self->getToken(), "Error", __LINE__); + + $type->name("Error"); + return $type; + } + if ($next->value() eq "DOMException") { + $self->assertTokenValue($self->getToken(), "DOMException", __LINE__); + + $type->name("DOMException"); + return $type; + } + if ($next->value() eq "Date") { + $self->assertTokenValue($self->getToken(), "Date", __LINE__); + + $type->name("Date"); + return $type; } if ($next->value() eq "sequence") { $self->assertTokenValue($self->getToken(), "sequence", __LINE__); $self->assertTokenValue($self->getToken(), "<", __LINE__); - my $type = $self->parseType(); + + my $subtype = $self->parseType(); + $self->assertTokenValue($self->getToken(), ">", __LINE__); - return "sequence<" . $type . ">" . $self->parseNull(); + + $type->name("sequence"); + push(@{$type->subtypes}, $subtype); + + return $type; } - if ($next->value() eq "object") { - $self->assertTokenValue($self->getToken(), "object", __LINE__); - return "object" . $self->parseTypeSuffix(); + if ($next->value() eq "FrozenArray") { + $self->assertTokenValue($self->getToken(), "FrozenArray", __LINE__); + $self->assertTokenValue($self->getToken(), "<", __LINE__); + + my $subtype = $self->parseType(); + + $self->assertTokenValue($self->getToken(), ">", __LINE__); + + $type->name("FrozenArray"); + push(@{$type->subtypes}, $subtype); + + return $type; } - if ($next->value() eq "Date") { - $self->assertTokenValue($self->getToken(), "Date", __LINE__); - return "Date" . $self->parseTypeSuffix(); + if ($next->value() eq "Promise") { + $self->assertTokenValue($self->getToken(), "Promise", __LINE__); + $self->assertTokenValue($self->getToken(), "<", __LINE__); + + my $subtype = $self->parseReturnType(); + + $self->assertTokenValue($self->getToken(), ">", __LINE__); + + $type->name("Promise"); + push(@{$type->subtypes}, $subtype); + + return $type; } - if ($next->type() == IdentifierToken || $next->value() eq "::") { - my $name = identifierRemoveNullablePrefix($self->parseScopedName()); - return $name . $self->parseTypeSuffix(); + if ($next->value() eq "record") { + $self->assertTokenValue($self->getToken(), "record", __LINE__); + $self->assertTokenValue($self->getToken(), "<", __LINE__); + + my $keyType = IDLType->new(); + $keyType->name($self->parseStringType()); + + $self->assertTokenValue($self->getToken(), ",", __LINE__); + + my $valueType = $self->parseType(); + + $self->assertTokenValue($self->getToken(), ">", __LINE__); + + $type->name("record"); + push(@{$type->subtypes}, $keyType); + push(@{$type->subtypes}, $valueType); + + return $type; + } + if ($next->type() == IdentifierToken) { + my $identifier = $self->getToken(); + + $type->name(identifierRemoveNullablePrefix($identifier->value())); + return $type; } $self->assertUnexpectedToken($next->value(), __LINE__); } @@ -1893,12 +2176,40 @@ sub parseConstType { my $self = shift; my $next = $self->nextToken(); + + my $type = IDLType->new(); + if ($next->value() =~ /$nextNonAnyType_1/) { - return $self->parsePrimitiveType() . $self->parseNull(); + $type->name($self->parsePrimitiveType()); + $type->isNullable($self->parseNull()); + return $type; } if ($next->type() == IdentifierToken) { - my $token = $self->getToken(); - return $token->value() . $self->parseNull(); + my $identifier = $self->getToken(); + + $type->name($identifier->value()); + $type->isNullable($self->parseNull()); + + return $type; + } + $self->assertUnexpectedToken($next->value(), __LINE__); +} + +sub parseStringType +{ + my $self = shift; + my $next = $self->nextToken(); + if ($next->value() eq "ByteString") { + $self->assertTokenValue($self->getToken(), "ByteString", __LINE__); + return "ByteString"; + } + if ($next->value() eq "DOMString") { + $self->assertTokenValue($self->getToken(), "DOMString", __LINE__); + return "DOMString"; + } + if ($next->value() eq "USVString") { + $self->assertTokenValue($self->getToken(), "USVString", __LINE__); + return "USVString"; } $self->assertUnexpectedToken($next->value(), __LINE__); } @@ -2004,43 +2315,15 @@ sub parseOptionalLong return 0; } -sub parseTypeSuffix -{ - my $self = shift; - my $next = $self->nextToken(); - if ($next->value() eq "[") { - $self->assertTokenValue($self->getToken(), "[", __LINE__); - $self->assertTokenValue($self->getToken(), "]", __LINE__); - return "[]" . $self->parseTypeSuffix(); - } - if ($next->value() eq "?") { - $self->assertTokenValue($self->getToken(), "?", __LINE__); - return "?" . $self->parseTypeSuffixStartingWithArray(); - } - return ""; -} - -sub parseTypeSuffixStartingWithArray -{ - my $self = shift; - my $next = $self->nextToken(); - if ($next->value() eq "[") { - $self->assertTokenValue($self->getToken(), "[", __LINE__); - $self->assertTokenValue($self->getToken(), "]", __LINE__); - return "[]" . $self->parseTypeSuffix(); - } - return ""; -} - sub parseNull { my $self = shift; my $next = $self->nextToken(); if ($next->value() eq "?") { $self->assertTokenValue($self->getToken(), "?", __LINE__); - return "?"; + return 1; } - return ""; + return 0; } sub parseReturnType @@ -2049,7 +2332,10 @@ sub parseReturnType my $next = $self->nextToken(); if ($next->value() eq "void") { $self->assertTokenValue($self->getToken(), "void", __LINE__); - return "void"; + + my $voidType = IDLType->new(); + $voidType->name("void"); + return $voidType; } if ($next->type() == IdentifierToken || $next->value() =~ /$nextExceptionField_1/) { return $self->parseType(); @@ -2057,17 +2343,6 @@ sub parseReturnType $self->assertUnexpectedToken($next->value(), __LINE__); } -sub parseIn -{ - my $self = shift; - my $next = $self->nextToken(); - if ($next->value() eq "in") { - $self->assertTokenValue($self->getToken(), "in", __LINE__); - return "in"; - } - return ""; -} - sub parseOptionalSemicolon { my $self = shift; @@ -2077,115 +2352,72 @@ sub parseOptionalSemicolon } } -sub parseScopedName +sub parseNameNoComma { my $self = shift; my $next = $self->nextToken(); - if ($next->value() eq "::") { - return $self->parseAbsoluteScopedName(); - } if ($next->type() == IdentifierToken) { - return $self->parseRelativeScopedName(); + my $identifier = $self->getToken(); + return ($identifier->value()); } - $self->assertUnexpectedToken($next->value()); -} -sub parseAbsoluteScopedName -{ - my $self = shift; - my $next = $self->nextToken(); - if ($next->value() eq "::") { - $self->assertTokenValue($self->getToken(), "::"); - my $token = $self->getToken(); - $self->assertTokenType($token, IdentifierToken); - return "::" . $token->value() . $self->parseScopedNameParts(); - } - $self->assertUnexpectedToken($next->value()); + return (); } -sub parseRelativeScopedName +sub parseName { my $self = shift; my $next = $self->nextToken(); if ($next->type() == IdentifierToken) { - my $token = $self->getToken(); - return $token->value() . $self->parseScopedNameParts(); + my $identifier = $self->getToken(); + return $identifier->value(); } $self->assertUnexpectedToken($next->value()); } -sub parseScopedNameParts -{ - my $self = shift; - my @names = (); - - while (1) { - my $next = $self->nextToken(); - if ($next->value() eq "::") { - $self->assertTokenValue($self->getToken(), "::"); - push(@names, "::"); - my $token = $self->getToken(); - $self->assertTokenType($token, IdentifierToken); - push(@names, $token->value()); - } else { - last; - } - } - return join("", @names); -} - -sub parseScopedNameList -{ - my $self = shift; - my $next = $self->nextToken(); - if ($next->type() == IdentifierToken || $next->value() eq "::") { - my @names = (); - push(@names, $self->parseScopedName()); - push(@names, @{$self->parseScopedNames()}); - return \@names; - } - $self->assertUnexpectedToken($next->value(), __LINE__); -} - -sub parseScopedNames -{ - my $self = shift; - my @names = (); - - while (1) { - my $next = $self->nextToken(); - if ($next->value() eq ",") { - $self->assertTokenValue($self->getToken(), ","); - push(@names, $self->parseScopedName()); - } else { - last; - } - } - return \@names; -} - sub applyMemberList { my $interface = shift; my $members = shift; for my $item (@{$members}) { - if (ref($item) eq "domAttribute") { + if (ref($item) eq "IDLAttribute") { push(@{$interface->attributes}, $item); next; } - if (ref($item) eq "domConstant") { + if (ref($item) eq "IDLConstant") { push(@{$interface->constants}, $item); next; } - if (ref($item) eq "domFunction") { - if ($item->signature->name eq "") { + if (ref($item) eq "IDLIterable") { + $interface->iterable($item); + next; + } + if (ref($item) eq "IDLOperation") { + if ($item->name eq "") { push(@{$interface->anonymousFunctions}, $item); } else { push(@{$interface->functions}, $item); } next; } + if (ref($item) eq "IDLSerializable") { + $interface->serializable($item); + next; + } + } + + if ($interface->serializable) { + my $numSerializerAttributes = @{$interface->serializable->attributes}; + if ($interface->serializable->hasAttribute) { + foreach my $attribute (@{$interface->attributes}) { + push(@{$interface->serializable->attributes}, $attribute->name); + } + } elsif ($numSerializerAttributes == 0) { + foreach my $attribute (@{$interface->attributes}) { + push(@{$interface->serializable->attributes}, $attribute->name); + } + } } } @@ -2198,25 +2430,22 @@ sub applyExtendedAttributeList my @constructorParams = @{$extendedAttributeList->{"Constructors"}}; my $index = (@constructorParams == 1) ? 0 : 1; foreach my $param (@constructorParams) { - my $constructor = domFunction->new(); - $constructor->signature(domSignature->new()); - $constructor->signature->name("Constructor"); - $constructor->signature->extendedAttributes($extendedAttributeList); - $constructor->parameters($param); - $constructor->{overloadedIndex} = $index++; + my $constructor = IDLOperation->new(); + $constructor->name("Constructor"); + $constructor->extendedAttributes($extendedAttributeList); + $constructor->arguments($param); push(@{$interface->constructors}, $constructor); } delete $extendedAttributeList->{"Constructors"}; $extendedAttributeList->{"Constructor"} = "VALUE_IS_MISSING"; } elsif (defined $extendedAttributeList->{"NamedConstructor"}) { - my $newDataNode = domFunction->new(); - $newDataNode->signature(domSignature->new()); - $newDataNode->signature->name("NamedConstructor"); - $newDataNode->signature->extendedAttributes($extendedAttributeList); + my $newDataNode = IDLOperation->new(); + $newDataNode->name("NamedConstructor"); + $newDataNode->extendedAttributes($extendedAttributeList); my %attributes = %{$extendedAttributeList->{"NamedConstructor"}}; my @attributeKeys = keys (%attributes); my $constructorName = $attributeKeys[0]; - push(@{$newDataNode->parameters}, @{$attributes{$constructorName}}); + push(@{$newDataNode->arguments}, @{$attributes{$constructorName}}); $extendedAttributeList->{"NamedConstructor"} = $constructorName; push(@{$interface->constructors}, $newDataNode); } @@ -2224,12 +2453,10 @@ sub applyExtendedAttributeList my @customConstructorParams = @{$extendedAttributeList->{"CustomConstructors"}}; my $index = (@customConstructorParams == 1) ? 0 : 1; foreach my $param (@customConstructorParams) { - my $customConstructor = domFunction->new(); - $customConstructor->signature(domSignature->new()); - $customConstructor->signature->name("CustomConstructor"); - $customConstructor->signature->extendedAttributes($extendedAttributeList); - $customConstructor->parameters($param); - $customConstructor->{overloadedIndex} = $index++; + my $customConstructor = IDLOperation->new(); + $customConstructor->name("CustomConstructor"); + $customConstructor->extendedAttributes($extendedAttributeList); + $customConstructor->arguments($param); push(@{$interface->customConstructors}, $customConstructor); } delete $extendedAttributeList->{"CustomConstructors"}; diff --git a/Source/WebCore/bindings/scripts/InFilesCompiler.pm b/Source/WebCore/bindings/scripts/InFilesCompiler.pm index 297568c97..0780d9456 100644 --- a/Source/WebCore/bindings/scripts/InFilesCompiler.pm +++ b/Source/WebCore/bindings/scripts/InFilesCompiler.pm @@ -14,7 +14,7 @@ # THIS SOFTWARE IS PROVIDED BY GOOGLE, INC. ``AS IS'' AND ANY # EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR +# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR # CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, # EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, # PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR @@ -37,7 +37,7 @@ require Config; package InFilesCompiler; -my $inputFile = ""; +my @inputFiles; my $outputDir = "."; my $defaultItemFactory; @@ -82,11 +82,11 @@ sub new() sub initializeFromCommandLine() { ::GetOptions( - 'input=s' => \$inputFile, + 'input=s' => \@inputFiles, 'outputDir=s' => \$outputDir, ); - die "You must specify --input <file>" unless length($inputFile); + die "You must specify at least one --input <file>" unless scalar(@inputFiles); ::mkpath($outputDir); @@ -99,14 +99,17 @@ sub compile() my $object = shift; my $generateCode = shift; - my $file = new IO::File; - open($file, $inputFile) or die "Failed to open file: $!"; - my $InParser = InFilesParser->new(); - $InParser->parse($file, \¶meterHandler, \&itemHandler); - close($file); - die "Failed to read from file: $inputFile" if (keys %parsedItems == 0); + foreach my $inputFile (@inputFiles) { + my $file = new IO::File; + open($file, $inputFile) or die "Failed to open file: $!"; + + $InParser->parse($file, \¶meterHandler, \&itemHandler); + + close($file); + die "Failed to read from file: $inputFile" if (keys %parsedItems == 0); + } &$generateCode(\%parsedParameters, \%parsedItems); } @@ -130,7 +133,7 @@ sub license() * THIS SOFTWARE IS PROVIDED BY GOOGLE, INC. ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR diff --git a/Source/WebCore/bindings/scripts/InFilesParser.pm b/Source/WebCore/bindings/scripts/InFilesParser.pm index 65393807f..75db11999 100644 --- a/Source/WebCore/bindings/scripts/InFilesParser.pm +++ b/Source/WebCore/bindings/scripts/InFilesParser.pm @@ -11,10 +11,10 @@ # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # -# THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY +# THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY # EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR +# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR # CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, # EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, # PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR diff --git a/Source/WebCore/bindings/scripts/StaticString.pm b/Source/WebCore/bindings/scripts/StaticString.pm index b8feaa57e..9ba0c70a8 100644 --- a/Source/WebCore/bindings/scripts/StaticString.pm +++ b/Source/WebCore/bindings/scripts/StaticString.pm @@ -33,27 +33,26 @@ sub GenerateStrings($) my @result = (); - while ( my ($name, $value) = each %strings ) { - push(@result, "static const LChar ${name}String8[] = \"${value}\";\n"); - } - - push(@result, "\n"); + push(@result, <<END); +#if COMPILER(MSVC) +#pragma warning(push) +#pragma warning(disable: 4307) +#endif - while ( my ($name, $value) = each %strings ) { - my $length = length($value); - my $hash = Hasher::GenerateHashValue($value); - push(@result, <<END); -static StringImpl::StaticASCIILiteral ${name}Data = { - StringImpl::StaticASCIILiteral::s_initialRefCount, - $length, - ${name}String8, - 0, - StringImpl::StaticASCIILiteral::s_initialFlags | (${hash} << StringImpl::StaticASCIILiteral::s_hashShift) -}; END + + for my $name (sort keys %strings) { + my $value = $strings{$name}; + push(@result, "static StringImpl::StaticStringImpl ${name}Data(\"${value}\");\n"); } - push(@result, "\n"); + push(@result, <<END); + +#if COMPILER(MSVC) +#pragma warning(pop) +#endif + +END return join "", @result; } @@ -67,7 +66,7 @@ sub GenerateStringAsserts($) push(@result, "#ifndef NDEBUG\n"); - while ( my ($name, $value) = each %strings ) { + for my $name (sort keys %strings) { push(@result, " reinterpret_cast<StringImpl*>(&${name}Data)->assertHashIsCorrect();\n"); } diff --git a/Source/WebCore/bindings/scripts/generate-bindings-all.pl b/Source/WebCore/bindings/scripts/generate-bindings-all.pl new file mode 100755 index 000000000..968ea113e --- /dev/null +++ b/Source/WebCore/bindings/scripts/generate-bindings-all.pl @@ -0,0 +1,245 @@ +#!/usr/bin/perl +# +# Copyright (C) 2016 Sony Interactive Entertainment Inc. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY +# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY +# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +# ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +use strict; +use warnings; +use FindBin; +use lib $FindBin::Bin; + +use File::Basename; +use File::Spec; +use File::Find; +use Getopt::Long; + +my $perl = $^X; +my $scriptDir = $FindBin::Bin; +my @idlDirectories; +my $outputDirectory; +my $idlFilesList; +my $generator; +my @generatorDependency; +my $defines; +my $preprocessor; +my $supplementalDependencyFile; +my @ppExtraOutput; +my @ppExtraArgs; +my $numOfJobs = 1; +my $idlAttributesFile; +my $showProgress; + +GetOptions('include=s@' => \@idlDirectories, + 'outputDir=s' => \$outputDirectory, + 'idlFilesList=s' => \$idlFilesList, + 'generator=s' => \$generator, + 'generatorDependency=s@' => \@generatorDependency, + 'defines=s' => \$defines, + 'preprocessor=s' => \$preprocessor, + 'supplementalDependencyFile=s' => \$supplementalDependencyFile, + 'ppExtraOutput=s@' => \@ppExtraOutput, + 'ppExtraArgs=s@' => \@ppExtraArgs, + 'idlAttributesFile=s' => \$idlAttributesFile, + 'numOfJobs=i' => \$numOfJobs, + 'showProgress' => \$showProgress); + +$| = 1; +my @idlFiles; +open(my $fh, '<', $idlFilesList) or die "Cannot open $idlFilesList"; +@idlFiles = map { CygwinPathIfNeeded(s/\r?\n?$//r) } <$fh>; +close($fh) or die; + +my %oldSupplements; +my %newSupplements; +if ($supplementalDependencyFile) { + my @output = ($supplementalDependencyFile, @ppExtraOutput); + my @deps = ($idlFilesList, @idlFiles, @generatorDependency); + if (needsUpdate(\@output, \@deps)) { + readSupplementalDependencyFile($supplementalDependencyFile, \%oldSupplements) if -e $supplementalDependencyFile; + my @args = (File::Spec->catfile($scriptDir, 'preprocess-idls.pl'), + '--defines', $defines, + '--idlFilesList', $idlFilesList, + '--supplementalDependencyFile', $supplementalDependencyFile, + @ppExtraArgs); + printProgress("Preprocess IDL"); + executeCommand($perl, @args) == 0 or die; + } + readSupplementalDependencyFile($supplementalDependencyFile, \%newSupplements); +} + +my @args = (File::Spec->catfile($scriptDir, 'generate-bindings.pl'), + '--defines', $defines, + '--generator', $generator, + '--outputDir', $outputDirectory, + '--preprocessor', $preprocessor, + '--idlAttributesFile', $idlAttributesFile, + '--write-dependencies'); +push @args, map { ('--include', $_) } @idlDirectories; +push @args, '--supplementalDependencyFile', $supplementalDependencyFile if $supplementalDependencyFile; + +my %directoryCache; +buildDirectoryCache(); + +my @idlFilesToUpdate = grep &{sub { + if (defined($oldSupplements{$_}) + && @{$oldSupplements{$_}} ne @{$newSupplements{$_} or []}) { + # Re-process the IDL file if its supplemental dependencies were added or removed + return 1; + } + my ($filename, $dirs, $suffix) = fileparse($_, '.idl'); + my $sourceFile = File::Spec->catfile($outputDirectory, "JS$filename.cpp"); + my $headerFile = File::Spec->catfile($outputDirectory, "JS$filename.h"); + my $depFile = File::Spec->catfile($outputDirectory, "JS$filename.dep"); + my @output = ($sourceFile, $headerFile); + my @deps = ($_, + $idlAttributesFile, + @generatorDependency, + @{$newSupplements{$_} or []}, + implicitDependencies($depFile)); + needsUpdate(\@output, \@deps); +}}, @idlFiles; + +my $abort = 0; +my $totalCount = @idlFilesToUpdate; +my $currentCount = 0; + +spawnGenerateBindingsIfNeeded() for (1 .. $numOfJobs); +while (waitpid(-1, 0) != -1) { + if ($?) { + $abort = 1; + } + spawnGenerateBindingsIfNeeded(); +} +exit $abort; + +sub needsUpdate +{ + my ($objects, $depends) = @_; + my $oldestObjectTime; + for (@$objects) { + return 1 if !-f; + my $m = mtime($_); + if (!defined $oldestObjectTime || $m < $oldestObjectTime) { + $oldestObjectTime = $m; + } + } + for (@$depends) { + die "Missing required dependency: $_" if !-f; + my $m = mtime($_); + if ($oldestObjectTime < $m) { + return 1; + } + } + return 0; +} + +sub mtime +{ + my ($file) = @_; + return (stat $file)[9]; +} + +sub spawnGenerateBindingsIfNeeded +{ + return if $abort; + return unless @idlFilesToUpdate; + my $file = shift @idlFilesToUpdate; + $currentCount++; + my $basename = basename($file); + printProgress("[$currentCount/$totalCount] $basename"); + my $pid = spawnCommand($perl, @args, $file); + $abort = 1 unless defined $pid; +} + +sub buildDirectoryCache +{ + my $wanted = sub { + $directoryCache{$_} = $File::Find::name; + $File::Find::prune = 1 unless ~/\./; + }; + find($wanted, @idlDirectories); +} + +sub implicitDependencies +{ + my ($depFile) = @_; + return () unless -f $depFile; + open(my $fh, '<', $depFile) or die "Cannot open $depFile"; + my $firstLine = <$fh>; + close($fh) or die; + my (undef, $deps) = split(/ : /, $firstLine); + my @deps = split(/\s+/, $deps); + return map { $directoryCache{$_} or () } @deps; +} + +sub executeCommand +{ + if ($^O eq 'MSWin32') { + return system(quoteCommand(@_)); + } + return system(@_); +} + +sub spawnCommand +{ + my $pid = fork(); + if ($pid == 0) { + @_ = quoteCommand(@_) if ($^O eq 'MSWin32'); + exec(@_); + die "Cannot exec"; + } + return $pid; +} + +sub quoteCommand +{ + return map { + '"' . s/([\\\"])/\\$1/gr . '"'; + } @_; +} + +sub CygwinPathIfNeeded +{ + my $path = shift; + return Cygwin::win_to_posix_path($path) if ($^O eq 'cygwin'); + return $path; +} + +sub readSupplementalDependencyFile +{ + my $filename = shift; + my $supplements = shift; + open(my $fh, '<', $filename) or die "Cannot open $filename"; + while (<$fh>) { + my ($idlFile, @followingIdlFiles) = split(/\s+/); + $supplements->{$idlFile} = [sort @followingIdlFiles]; + } + close($fh) or die; +} + +sub printProgress +{ + return unless $showProgress; + my $msg = shift; + print "$msg\n"; +} diff --git a/Source/WebCore/bindings/scripts/generate-bindings.pl b/Source/WebCore/bindings/scripts/generate-bindings.pl index f93434e40..1048a512e 100755 --- a/Source/WebCore/bindings/scripts/generate-bindings.pl +++ b/Source/WebCore/bindings/scripts/generate-bindings.pl @@ -1,6 +1,6 @@ #!/usr/bin/perl -w # -# Copyright (C) 2005 Apple Computer, Inc. +# Copyright (C) 2005 Apple Inc. # Copyright (C) 2006 Anders Carlsson <andersca@mac.com> # # This file is part of WebKit @@ -29,6 +29,8 @@ # <rdar://problems/4251781&4251785> use strict; +use FindBin; +use lib '.', $FindBin::Bin; use File::Path; use File::Basename; @@ -80,7 +82,7 @@ $targetIdlFile = Cwd::realpath($targetIdlFile); if ($verbose) { print "$generator: $targetIdlFile\n"; } -my $targetInterfaceName = fileparse(basename($targetIdlFile), ".idl"); +my $targetInterfaceName = fileparse($targetIdlFile, ".idl"); my $idlFound = 0; my @supplementedIdlFiles; @@ -98,7 +100,7 @@ if ($supplementalDependencyFile) { open FH, "< $supplementalDependencyFile" or die "Cannot open $supplementalDependencyFile\n"; while (my $line = <FH>) { my ($idlFile, @followingIdlFiles) = split(/\s+/, $line); - if ($idlFile and basename($idlFile) eq basename($targetIdlFile)) { + if ($idlFile and fileparse($idlFile) eq fileparse($targetIdlFile)) { $idlFound = 1; @supplementedIdlFiles = sort @followingIdlFiles; } @@ -110,11 +112,11 @@ if ($supplementalDependencyFile) { # dependency file) but should generate .h and .cpp files. if (!$idlFound and $additionalIdlFiles) { my @idlFiles = shellwords($additionalIdlFiles); - $idlFound = grep { $_ and basename($_) eq basename($targetIdlFile) } @idlFiles; + $idlFound = grep { $_ and fileparse($_) eq fileparse($targetIdlFile) } @idlFiles; } if (!$idlFound) { - my $codeGen = CodeGenerator->new(\@idlDirectories, $generator, $outputDirectory, $outputHeadersDirectory, 0, $preprocessor, $writeDependencies, $verbose); + my $codeGen = CodeGenerator->new(\@idlDirectories, $generator, $outputDirectory, $outputHeadersDirectory, $preprocessor, $writeDependencies, $verbose); # We generate empty .h and .cpp files just to tell build scripts that .h and .cpp files are created. generateEmptyHeaderAndCpp($codeGen->FileNamePrefix(), $targetInterfaceName, $outputHeadersDirectory, $outputDirectory); @@ -128,22 +130,26 @@ my $targetDocument = $targetParser->Parse($targetIdlFile, $defines, $preprocesso if ($idlAttributesFile) { my $idlAttributes = loadIDLAttributes($idlAttributesFile); - checkIDLAttributes($idlAttributes, $targetDocument, basename($targetIdlFile)); + checkIDLAttributes($idlAttributes, $targetDocument, fileparse($targetIdlFile)); } foreach my $idlFile (@supplementedIdlFiles) { next if $idlFile eq $targetIdlFile; - my $interfaceName = fileparse(basename($idlFile), ".idl"); + my $interfaceName = fileparse($idlFile, ".idl"); my $parser = IDLParser->new(!$verbose); my $document = $parser->Parse($idlFile, $defines, $preprocessor); foreach my $interface (@{$document->interfaces}) { - if (!$interface->isPartial || $interface->name eq $targetInterfaceName) { + if (!$interface->isPartial || $interface->type->name eq $targetInterfaceName) { my $targetDataNode; + my @targetGlobalContexts; foreach my $interface (@{$targetDocument->interfaces}) { - if ($interface->name eq $targetInterfaceName) { + if ($interface->type->name eq $targetInterfaceName) { $targetDataNode = $interface; + my $exposedAttribute = $targetDataNode->extendedAttributes->{"Exposed"} || "Window"; + $exposedAttribute = substr($exposedAttribute, 1, -1) if substr($exposedAttribute, 0, 1) eq "("; + @targetGlobalContexts = split(",", $exposedAttribute); last; } } @@ -151,30 +157,36 @@ foreach my $idlFile (@supplementedIdlFiles) { # Support for attributes of partial interfaces. foreach my $attribute (@{$interface->attributes}) { + next unless shouldPropertyBeExposed($attribute, \@targetGlobalContexts); + # Record that this attribute is implemented by $interfaceName. - $attribute->signature->extendedAttributes->{"ImplementedBy"} = $interfaceName if $interface->isPartial; + $attribute->extendedAttributes->{"ImplementedBy"} = $interfaceName if $interface->isPartial; # Add interface-wide extended attributes to each attribute. foreach my $extendedAttributeName (keys %{$interface->extendedAttributes}) { - $attribute->signature->extendedAttributes->{$extendedAttributeName} = $interface->extendedAttributes->{$extendedAttributeName}; + $attribute->extendedAttributes->{$extendedAttributeName} = $interface->extendedAttributes->{$extendedAttributeName}; } push(@{$targetDataNode->attributes}, $attribute); } # Support for methods of partial interfaces. foreach my $function (@{$interface->functions}) { + next unless shouldPropertyBeExposed($function, \@targetGlobalContexts); + # Record that this method is implemented by $interfaceName. - $function->signature->extendedAttributes->{"ImplementedBy"} = $interfaceName if $interface->isPartial; + $function->extendedAttributes->{"ImplementedBy"} = $interfaceName if $interface->isPartial; # Add interface-wide extended attributes to each method. foreach my $extendedAttributeName (keys %{$interface->extendedAttributes}) { - $function->signature->extendedAttributes->{$extendedAttributeName} = $interface->extendedAttributes->{$extendedAttributeName}; + $function->extendedAttributes->{$extendedAttributeName} = $interface->extendedAttributes->{$extendedAttributeName}; } push(@{$targetDataNode->functions}, $function); } # Support for constants of partial interfaces. foreach my $constant (@{$interface->constants}) { + next unless shouldPropertyBeExposed($constant, \@targetGlobalContexts); + # Record that this constant is implemented by $interfaceName. $constant->extendedAttributes->{"ImplementedBy"} = $interfaceName if $interface->isPartial; @@ -191,9 +203,28 @@ foreach my $idlFile (@supplementedIdlFiles) { } # Generate desired output for the target IDL file. -my $codeGen = CodeGenerator->new(\@idlDirectories, $generator, $outputDirectory, $outputHeadersDirectory, 0, $preprocessor, $writeDependencies, $verbose, $targetIdlFile); +my $codeGen = CodeGenerator->new(\@idlDirectories, $generator, $outputDirectory, $outputHeadersDirectory, $preprocessor, $writeDependencies, $verbose, $targetIdlFile); $codeGen->ProcessDocument($targetDocument, $defines); +# Attributes / Operations / Constants of supplemental interfaces can have an [Exposed=XX] attribute which restricts +# on which global contexts they should be exposed. +sub shouldPropertyBeExposed +{ + my ($context, $targetGlobalContexts) = @_; + + my $exposed = $context->extendedAttributes->{Exposed}; + + return 1 unless $exposed; + + $exposed = substr($exposed, 1, -1) if substr($exposed, 0, 1) eq "("; + my @sourceGlobalContexts = split(",", $exposed); + + for my $targetGlobalContext (@$targetGlobalContexts) { + return 1 if grep(/^$targetGlobalContext$/, @sourceGlobalContexts); + } + return 0; +} + sub generateEmptyHeaderAndCpp { my ($prefix, $targetInterfaceName, $outputHeadersDirectory, $outputDirectory) = @_; @@ -240,7 +271,7 @@ sub loadIDLAttributes $idlAttributes{$name}{"VALUE_IS_MISSING"} = 1; } } else { - die "The format of " . basename($idlAttributesFile) . " is wrong: line $.\n"; + die "The format of " . fileparse($idlAttributesFile) . " is wrong: line $.\n"; } } close FH; @@ -258,13 +289,13 @@ sub checkIDLAttributes checkIfIDLAttributesExists($idlAttributes, $interface->extendedAttributes, $idlFile); foreach my $attribute (@{$interface->attributes}) { - checkIfIDLAttributesExists($idlAttributes, $attribute->signature->extendedAttributes, $idlFile); + checkIfIDLAttributesExists($idlAttributes, $attribute->extendedAttributes, $idlFile); } foreach my $function (@{$interface->functions}) { - checkIfIDLAttributesExists($idlAttributes, $function->signature->extendedAttributes, $idlFile); - foreach my $parameter (@{$function->parameters}) { - checkIfIDLAttributesExists($idlAttributes, $parameter->extendedAttributes, $idlFile); + checkIfIDLAttributesExists($idlAttributes, $function->extendedAttributes, $idlFile); + foreach my $argument (@{$function->arguments}) { + checkIfIDLAttributesExists($idlAttributes, $argument->extendedAttributes, $idlFile); } } } diff --git a/Source/WebCore/bindings/scripts/gobject-generate-headers.pl b/Source/WebCore/bindings/scripts/gobject-generate-headers.pl deleted file mode 100644 index b39cf253a..000000000 --- a/Source/WebCore/bindings/scripts/gobject-generate-headers.pl +++ /dev/null @@ -1,98 +0,0 @@ -#!/usr/bin/perl -w -# -# Copyright (C) 2009 Adam Dingle <adam@yorba.org> -# -# This file is part of WebKit -# -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Library 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 -# Library General Public License for more details. -# -# You should have received a copy of the GNU Library General Public License -# aint with this library; see the file COPYING.LIB. If not, write to -# the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, -# Boston, MA 02110-1301, USA. -# - -my $classlist = <STDIN>; -chomp($classlist); -my @classes = split / /, $classlist; -@classes = sort @classes; - -print <<EOF; -/* This file is part of the WebKit open source project. - This file has been generated by gobject-generate-headers.pl. DO NOT MODIFY! - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public License - along with this library; see the file COPYING.LIB. If not, write to - the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - Boston, MA 02110-1301, USA. -*/ - -EOF - -my $outType = $ARGV[0]; -my $header; -if ($outType eq "defines") { - $header = "webkitdomdefines_h"; -} elsif ($outType eq "gdom") { - $header = "webkitdom_h"; -} else { - die "unknown output type"; -} - -print "#ifndef ${header}\n"; -print "#define ${header}\n"; -print "\n"; - -if ($outType eq "defines") { - print "#include <glib.h>\n\n"; - print "#ifdef G_OS_WIN32\n"; - print " #ifdef BUILDING_WEBKIT\n"; - print " #define WEBKIT_API __declspec(dllexport)\n"; - print " #else\n"; - print " #define WEBKIT_API __declspec(dllimport)\n"; - print " #endif\n"; - print "#else\n"; - print " #define WEBKIT_API __attribute__((visibility(\"default\")))\n"; - print "#endif\n\n"; - print "#define WEBKIT_DEPRECATED WEBKIT_API G_DEPRECATED\n"; - print "#define WEBKIT_DEPRECATED_FOR(f) WEBKIT_API G_DEPRECATED_FOR(f)\n"; - print "\n"; - print "#ifndef WEBKIT_API\n"; - print " #define WEBKIT_API\n"; - print "#endif\n"; - - foreach my $class (@classes) { - if ($class ne "Deprecated" && $class ne "Custom") { - print "typedef struct _WebKitDOM${class} WebKitDOM${class};\n"; - print "typedef struct _WebKitDOM${class}Class WebKitDOM${class}Class;\n"; - print "\n"; - } - } -} elsif ($outType eq "gdom") { - print "#define __WEBKITDOM_H_INSIDE__\n\n"; - foreach my $class (@classes) { - print "#include <webkitdom/WebKitDOM${class}.h>\n"; - } - print "\n#undef __WEBKITDOM_H_INSIDE__\n"; -} - -print "\n"; -print "#endif\n"; diff --git a/Source/WebCore/bindings/scripts/preprocess-idls.pl b/Source/WebCore/bindings/scripts/preprocess-idls.pl index d65df33cf..a984ab7c5 100644 --- a/Source/WebCore/bindings/scripts/preprocess-idls.pl +++ b/Source/WebCore/bindings/scripts/preprocess-idls.pl @@ -19,10 +19,13 @@ # use strict; +use FindBin; +use lib $FindBin::Bin; use File::Basename; use Getopt::Long; use Cwd; +use Config; my $defines; my $preprocessor; @@ -30,7 +33,6 @@ my $idlFilesList; my $supplementalDependencyFile; my $windowConstructorsFile; my $workerGlobalScopeConstructorsFile; -my $sharedWorkerGlobalScopeConstructorsFile; my $dedicatedWorkerGlobalScopeConstructorsFile; my $supplementalMakefileDeps; @@ -40,7 +42,6 @@ GetOptions('defines=s' => \$defines, 'supplementalDependencyFile=s' => \$supplementalDependencyFile, 'windowConstructorsFile=s' => \$windowConstructorsFile, 'workerGlobalScopeConstructorsFile=s' => \$workerGlobalScopeConstructorsFile, - 'sharedWorkerGlobalScopeConstructorsFile=s' => \$sharedWorkerGlobalScopeConstructorsFile, 'dedicatedWorkerGlobalScopeConstructorsFile=s' => \$dedicatedWorkerGlobalScopeConstructorsFile, 'supplementalMakefileDeps=s' => \$supplementalMakefileDeps); @@ -48,13 +49,22 @@ die('Must specify #define macros using --defines.') unless defined($defines); die('Must specify an output file using --supplementalDependencyFile.') unless defined($supplementalDependencyFile); die('Must specify an output file using --windowConstructorsFile.') unless defined($windowConstructorsFile); die('Must specify an output file using --workerGlobalScopeConstructorsFile.') unless defined($workerGlobalScopeConstructorsFile); -die('Must specify an output file using --sharedWorkerGlobalScopeConstructorsFile.') unless defined($sharedWorkerGlobalScopeConstructorsFile); die('Must specify an output file using --dedicatedWorkerGlobalScopeConstructorsFile.') unless defined($dedicatedWorkerGlobalScopeConstructorsFile); die('Must specify the file listing all IDLs using --idlFilesList.') unless defined($idlFilesList); +$supplementalDependencyFile = CygwinPathIfNeeded($supplementalDependencyFile); +$windowConstructorsFile = CygwinPathIfNeeded($windowConstructorsFile); +$workerGlobalScopeConstructorsFile = CygwinPathIfNeeded($workerGlobalScopeConstructorsFile); +$dedicatedWorkerGlobalScopeConstructorsFile = CygwinPathIfNeeded($dedicatedWorkerGlobalScopeConstructorsFile); +$supplementalMakefileDeps = CygwinPathIfNeeded($supplementalMakefileDeps); + open FH, "< $idlFilesList" or die "Cannot open $idlFilesList\n"; -my @idlFiles = <FH>; -chomp(@idlFiles); +my @idlFilesIn = <FH>; +chomp(@idlFilesIn); +my @idlFiles = (); +foreach (@idlFilesIn) { + push @idlFiles, CygwinPathIfNeeded($_); +} close FH; my %interfaceNameToIdlFile; @@ -63,14 +73,13 @@ my %supplementalDependencies; my %supplementals; my $windowConstructorsCode = ""; my $workerGlobalScopeConstructorsCode = ""; -my $sharedWorkerGlobalScopeConstructorsCode = ""; my $dedicatedWorkerGlobalScopeConstructorsCode = ""; # Get rid of duplicates in idlFiles array. my %idlFileHash = map { $_, 1 } @idlFiles; # Populate $idlFileToInterfaceName and $interfaceNameToIdlFile. -foreach my $idlFile (keys %idlFileHash) { +foreach my $idlFile (sort keys %idlFileHash) { my $fullPath = Cwd::realpath($idlFile); my $interfaceName = fileparse(basename($idlFile), ".idl"); $idlFileToInterfaceName{$fullPath} = $interfaceName; @@ -87,6 +96,13 @@ foreach my $idlFile (sort keys %idlFileHash) { $supplementalDependencies{$fullPath} = [$partialInterfaceName]; next; } + + $supplementals{$fullPath} = []; + + # Skip if the IDL file does not contain an interface, a callback interface or an exception. + # The IDL may contain a dictionary. + next unless containsInterfaceOrExceptionFromIDL($idlFileContents); + my $interfaceName = fileparse(basename($idlFile), ".idl"); # Handle implements statements. my $implementedInterfaces = getImplementedInterfacesFromIDL($idlFileContents, $interfaceName); @@ -99,29 +115,41 @@ foreach my $idlFile (sort keys %idlFileHash) { $supplementalDependencies{$implementedIdlFile} = [$interfaceName]; } } - # Handle [NoInterfaceObject]. - unless (isCallbackInterfaceFromIDL($idlFileContents)) { - my $extendedAttributes = getInterfaceExtendedAttributesFromIDL($idlFileContents); - unless ($extendedAttributes->{"NoInterfaceObject"}) { - my @globalContexts = split("&", $extendedAttributes->{"GlobalContext"} || "DOMWindow"); + + # For every interface that is exposed in a given ECMAScript global environment and: + # - is a callback interface that has constants declared on it, or + # - is a non-callback interface that is not declared with the [NoInterfaceObject] extended attribute, a corresponding + # property must exist on the ECMAScript environment's global object. + # See https://heycam.github.io/webidl/#es-interfaces + my $extendedAttributes = getInterfaceExtendedAttributesFromIDL($idlFileContents); + unless ($extendedAttributes->{"NoInterfaceObject"}) { + if (!isCallbackInterfaceFromIDL($idlFileContents) || interfaceHasConstantAttribute($idlFileContents)) { + my $exposedAttribute = $extendedAttributes->{"Exposed"} || "Window"; + $exposedAttribute = substr($exposedAttribute, 1, -1) if substr($exposedAttribute, 0, 1) eq "("; + my @globalContexts = split(",", $exposedAttribute); my $attributeCode = GenerateConstructorAttribute($interfaceName, $extendedAttributes); - $windowConstructorsCode .= $attributeCode if grep(/^DOMWindow$/, @globalContexts); - $workerGlobalScopeConstructorsCode .= $attributeCode if grep(/^WorkerGlobalScope$/, @globalContexts); - $sharedWorkerGlobalScopeConstructorsCode .= $attributeCode if grep(/^SharedWorkerGlobalScope$/, @globalContexts); - $dedicatedWorkerGlobalScopeConstructorsCode .= $attributeCode if grep(/^DedicatedWorkerGlobalScope$/, @globalContexts); + foreach my $globalContext (@globalContexts) { + if ($globalContext eq "Window") { + $windowConstructorsCode .= $attributeCode; + } elsif ($globalContext eq "Worker") { + $workerGlobalScopeConstructorsCode .= $attributeCode; + } elsif ($globalContext eq "DedicatedWorker") { + $dedicatedWorkerGlobalScopeConstructorsCode .= $attributeCode; + } else { + die "Unsupported global context '$globalContext' used in [Exposed] at $idlFile"; + } + } } } - $supplementals{$fullPath} = []; } # Generate partial interfaces for Constructors. GeneratePartialInterface("DOMWindow", $windowConstructorsCode, $windowConstructorsFile); GeneratePartialInterface("WorkerGlobalScope", $workerGlobalScopeConstructorsCode, $workerGlobalScopeConstructorsFile); -GeneratePartialInterface("SharedWorkerGlobalScope", $sharedWorkerGlobalScopeConstructorsCode, $sharedWorkerGlobalScopeConstructorsFile); GeneratePartialInterface("DedicatedWorkerGlobalScope", $dedicatedWorkerGlobalScopeConstructorsCode, $dedicatedWorkerGlobalScopeConstructorsFile); # Resolves partial interfaces and implements dependencies. -foreach my $idlFile (keys %supplementalDependencies) { +foreach my $idlFile (sort keys %supplementalDependencies) { my $baseFiles = $supplementalDependencies{$idlFile}; foreach my $baseFile (@{$baseFiles}) { my $targetIdlFile = $interfaceNameToIdlFile{$baseFile}; @@ -165,6 +193,21 @@ if ($supplementalMakefileDeps) { WriteFileIfChanged($supplementalMakefileDeps, $makefileDeps); } +my $cygwinPathAdded; +sub CygwinPathIfNeeded +{ + my $path = shift; + if ($path && $Config{osname} eq "cygwin") { + if (not $cygwinPathAdded) { + $ENV{PATH} = "$ENV{PATH}:/cygdrive/c/cygwin/bin"; + $cygwinPathAdded = 1; + } + chomp($path = `cygpath -u '$path'`); + $path =~ s/[\r\n]//; + } + return $path; +} + sub WriteFileIfChanged { my $fileName = shift; @@ -202,8 +245,8 @@ sub GenerateConstructorAttribute my $code = " "; my @extendedAttributesList; - foreach my $attributeName (keys %{$extendedAttributes}) { - next unless ($attributeName eq "Conditional" || $attributeName eq "EnabledAtRuntime" || $attributeName eq "EnabledBySetting"); + foreach my $attributeName (sort keys %{$extendedAttributes}) { + next unless ($attributeName eq "Conditional" || $attributeName eq "EnabledAtRuntime" || $attributeName eq "EnabledForWorld" || $attributeName eq "EnabledBySetting" || $attributeName eq "PrivateIdentifier" || $attributeName eq "PublicIdentifier"); my $extendedAttribute = $attributeName; $extendedAttribute .= "=" . $extendedAttributes->{$attributeName} unless $extendedAttributes->{$attributeName} eq "VALUE_IS_MISSING"; push(@extendedAttributesList, $extendedAttribute); @@ -270,6 +313,16 @@ sub isCallbackInterfaceFromIDL return ($fileContents =~ /callback\s+interface\s+\w+/gs); } +sub containsInterfaceOrExceptionFromIDL +{ + my $fileContents = shift; + + return 1 if $fileContents =~ /\bcallback\s+interface\s+\w+/gs; + return 1 if $fileContents =~ /\binterface\s+\w+/gs; + return 1 if $fileContents =~ /\bexception\s+\w+/gs; + return 0; +} + sub trim { my $string = shift; @@ -283,8 +336,13 @@ sub getInterfaceExtendedAttributesFromIDL my $extendedAttributes = {}; - if ($fileContents =~ /\[(.*)\]\s+(interface|exception)\s+(\w+)/gs) { - my @parts = split(',', $1); + # Remove comments from fileContents before processing. + # FIX: Preference to use Regex::Common::comment, however it is not available on + # all build systems. + $fileContents =~ s/(?:(?:(?:\/\/)(?:[^\n]*)(?:\n))|(?:(?:\/\*)(?:(?:[^\*]+|\*(?!\/))*)(?:\*\/)))//g; + + if ($fileContents =~ /\[(.*)\]\s+(callback interface|interface|exception)\s+(\w+)/gs) { + my @parts = split(m/,(?![^()]*\))/, $1); foreach my $part (@parts) { my @keyValue = split('=', $part); my $key = trim($keyValue[0]); @@ -297,3 +355,10 @@ sub getInterfaceExtendedAttributesFromIDL return $extendedAttributes; } + +sub interfaceHasConstantAttribute +{ + my $fileContents = shift; + + return $fileContents =~ /\s+const[\s\w]+=\s+[\w]+;/gs; +} diff --git a/Source/WebCore/bindings/scripts/preprocessor.pm b/Source/WebCore/bindings/scripts/preprocessor.pm index d92590d77..2321d5191 100644 --- a/Source/WebCore/bindings/scripts/preprocessor.pm +++ b/Source/WebCore/bindings/scripts/preprocessor.pm @@ -51,18 +51,20 @@ sub applyPreprocessor $preprocessor = "/usr/sfw/bin/gcc"; } elsif (-x "/usr/bin/clang") { $preprocessor = "/usr/bin/clang"; - } elsif ($Config{osname} eq 'msys') { - $preprocessor = "gcc"; } else { $preprocessor = "/usr/bin/gcc"; } - push(@args, qw(-E -P -x c++)); + if ($Config::Config{"osname"} eq "MSWin32") { + push(@args, qw(/EP)); + } else { + push(@args, qw(-E -P -x c++)); + } } if ($Config::Config{"osname"} eq "darwin") { push(@args, "-I" . $ENV{BUILT_PRODUCTS_DIR} . "/usr/local/include") if $ENV{BUILT_PRODUCTS_DIR}; push(@args, "-isysroot", $ENV{SDKROOT}) if $ENV{SDKROOT}; - $defines .= " WTF_PLATFORM_IOS" if defined $ENV{PLATFORM_NAME} && $ENV{PLATFORM_NAME} =~ /iphone(os|simulator)/; + $defines .= " WTF_PLATFORM_IOS" if defined $ENV{PLATFORM_NAME} && $ENV{PLATFORM_NAME} !~ /macosx/; } # Remove double quotations from $defines and extract macros. @@ -73,19 +75,34 @@ sub applyPreprocessor @macros = map { "-D$_" } @macros; my $pid = 0; - if ($Config{osname} eq "cygwin" || $Config{osname} eq 'MSWin32' || $Config{osname} eq 'msys') { + if ($Config{osname} eq "cygwin") { + $ENV{PATH} = "$ENV{PATH}:/cygdrive/c/cygwin/bin"; + my @preprocessorAndFlags; + if ($preprocessor eq "/usr/bin/gcc") { + @preprocessorAndFlags = split(' ', $preprocessor); + } else { + $preprocessor =~ /"(.*)"/; + chomp(my $preprocessor = `cygpath -u '$1'`) if (defined $1); + chomp($fileName = `cygpath -w '$fileName'`); + @preprocessorAndFlags = ($preprocessor, "/nologo", "/EP"); + } # This call can fail if Windows rebases cygwin, so retry a few times until it succeeds. for (my $tries = 0; !$pid && ($tries < 20); $tries++) { eval { # Suppress STDERR so that if we're using cl.exe, the output # name isn't needlessly echoed. use Symbol 'gensym'; my $err = gensym; - $pid = open3(\*PP_IN, \*PP_OUT, $err, split(' ', $preprocessor), @args, @macros, $fileName); + $pid = open3(\*PP_IN, \*PP_OUT, $err, @preprocessorAndFlags, @args, @macros, $fileName); 1; } or do { sleep 1; } }; + } elsif ($Config::Config{"osname"} eq "MSWin32") { + # Suppress STDERR so that if we're using cl.exe, the output + # name isn't needlessly echoed. + use Symbol 'gensym'; my $err = gensym; + $pid = open3(\*PP_IN, \*PP_OUT, $err, $preprocessor, @args, @macros, $fileName); } else { $pid = open2(\*PP_OUT, \*PP_IN, split(' ', $preprocessor), @args, @macros, $fileName); } |