1/* 2 * Copyright (C) 2012 University of Washington. All rights reserved. 3 * Copyright (C) 2014 Apple Inc. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS 16 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 17 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 18 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 19 * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 20 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 21 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 25 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 */ 27 28#ifndef MemoizedDOMResult_h 29#define MemoizedDOMResult_h 30 31#if ENABLE(WEB_REPLAY) 32 33#include <replay/EncodedValue.h> 34#include <replay/NondeterministicInput.h> 35 36namespace WebCore { 37 38class SerializedScriptValue; 39 40typedef int ExceptionCode; 41 42// Add new memoized ctypes here. The first argument is the enum value, 43// which cannot conflict with built-in primitive types. The second is 44// the actual C type that is used to specialize CTypeTraits. New enum 45// values should also be added to the definition in WebInputs.json. 46#define FOR_EACH_MEMOIZED_CTYPE(macro) \ 47 macro(Boolean, bool) \ 48 macro(Int, int) \ 49 macro(String, String) \ 50 macro(Unsigned, unsigned) \ 51 \ 52// end of FOR_EACH_MEMOIZED_CTYPE 53 54// We encode this enum so that we can recover MemoizedType when decoding the input 55// and then call the correct specialized MemoizedDOMResult<T> constructor. 56enum class EncodedCType { 57#define CREATE_ENUM_VALUE(name, type) name, 58 59FOR_EACH_MEMOIZED_CTYPE(CREATE_ENUM_VALUE) 60#undef CREATE_ENUM_VALUE 61}; 62 63class MemoizedDOMResultBase : public NondeterministicInputBase { 64public: 65 MemoizedDOMResultBase(const String& attribute, EncodedCType ctype, ExceptionCode exceptionCode = 0) 66 : m_attribute(attribute) 67 , m_ctype(ctype) 68 , m_exceptionCode(exceptionCode) { } 69 70 virtual ~MemoizedDOMResultBase() { } 71 72 static std::unique_ptr<MemoizedDOMResultBase> createFromEncodedResult(const String& attribute, EncodedCType, EncodedValue, ExceptionCode); 73 74 template<typename T> 75 bool convertTo(T& decodedValue); 76 77 virtual EncodedValue encodedResult() const = 0; 78 virtual InputQueue queue() const final override { return InputQueue::ScriptMemoizedData; } 79 virtual const AtomicString& type() const final override; 80 81 const String& attribute() const { return m_attribute; } 82 EncodedCType ctype() const { return m_ctype; } 83 ExceptionCode exceptionCode() const { return m_exceptionCode; } 84private: 85 String m_attribute; 86 EncodedCType m_ctype; 87 ExceptionCode m_exceptionCode; 88}; 89 90template<typename T> 91struct CTypeTraits { 92 static bool decode(EncodedValue& encodedValue, T& decodedValue) 93 { 94 return EncodingTraits<T>::decodeValue(encodedValue, decodedValue); 95 } 96}; 97 98#define CREATE_CTYPE_TRAITS(_name, _type) \ 99template<> \ 100struct CTypeTraits<_type> { \ 101 typedef _type CType; \ 102 static const EncodedCType encodedType = EncodedCType::_name; \ 103}; \ 104 105FOR_EACH_MEMOIZED_CTYPE(CREATE_CTYPE_TRAITS) 106#undef CREATE_CTYPE_TRAITS 107 108template<typename MemoizedType> 109class MemoizedDOMResult final : public MemoizedDOMResultBase { 110public: 111 MemoizedDOMResult(const String& attribute, typename CTypeTraits<MemoizedType>::CType result, ExceptionCode exceptionCode) 112 : MemoizedDOMResultBase(attribute, CTypeTraits<MemoizedType>::encodedType, exceptionCode) 113 , m_result(result) { } 114 virtual ~MemoizedDOMResult() { } 115 116 virtual EncodedValue encodedResult() const override 117 { 118 return EncodingTraits<MemoizedType>::encodeValue(m_result); 119 } 120 121 typename CTypeTraits<MemoizedType>::CType result() const { return m_result; } 122private: 123 typename CTypeTraits<MemoizedType>::CType m_result; 124}; 125 126// This is used by clients of the memoized DOM result to get out the memoized 127// value without performing a cast to MemoizedDOMResult<T> and calling result(). 128template<typename T> 129bool MemoizedDOMResultBase::convertTo(T& convertedValue) 130{ 131 // Type tag doesn't match; fail to decode the value. 132 if (m_ctype != CTypeTraits<T>::encodedType) 133 return false; 134 135 MemoizedDOMResult<T>& castedResult = static_cast<MemoizedDOMResult<T>&>(*this); 136 convertedValue = castedResult.result(); 137 return true; 138} 139 140} // namespace WebCore 141 142using WebCore::MemoizedDOMResultBase; 143 144namespace JSC { 145 146template<> 147struct InputTraits<MemoizedDOMResultBase> { 148 static InputQueue queue() { return InputQueue::ScriptMemoizedData; } 149 static const AtomicString& type(); 150 151 static void encode(EncodedValue&, const MemoizedDOMResultBase& input); 152 static bool decode(EncodedValue&, std::unique_ptr<MemoizedDOMResultBase>& input); 153}; 154 155} // namespace JSC 156 157#endif // ENABLE(WEB_REPLAY) 158 159#endif // MemoizedDOMResult_h 160