Web Replay: add infrastructure for memoizing nondeterministic DOM APIs
[WebKit-https.git] / Source / WebCore / replay / MemoizedDOMResult.h
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
36 namespace WebCore {
37
38 class SerializedScriptValue;
39
40 typedef 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.
56 enum class EncodedCType {
57 #define CREATE_ENUM_VALUE(name, type) name,
58
59 FOR_EACH_MEMOIZED_CTYPE(CREATE_ENUM_VALUE)
60 #undef CREATE_ENUM_VALUE
61 };
62
63 class MemoizedDOMResultBase : public NondeterministicInputBase {
64 public:
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; }
84 private:
85     String m_attribute;
86     EncodedCType m_ctype;
87     ExceptionCode m_exceptionCode;
88 };
89
90 template<typename T>
91 struct 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) \
99 template<> \
100 struct CTypeTraits<_type> { \
101     typedef _type CType; \
102     static const EncodedCType encodedType = EncodedCType::_name; \
103 }; \
104
105 FOR_EACH_MEMOIZED_CTYPE(CREATE_CTYPE_TRAITS)
106 #undef CREATE_CTYPE_TRAITS
107
108 template<typename MemoizedType>
109 class MemoizedDOMResult final : public MemoizedDOMResultBase {
110 public:
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; }
122 private:
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().
128 template<typename T>
129 bool 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
142 using WebCore::MemoizedDOMResultBase;
143
144 namespace JSC {
145
146 template<>
147 struct 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