OLD | NEW |
(Empty) | |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. |
| 4 |
| 5 #ifndef PropertyBag_h |
| 6 #define PropertyBag_h |
| 7 |
| 8 #include "bindings/core/v8/ArrayValue.h" |
| 9 #include "bindings/core/v8/ExceptionMessages.h" |
| 10 #include "bindings/core/v8/ExceptionState.h" |
| 11 #include "bindings/core/v8/Nullable.h" |
| 12 #include "bindings/core/v8/PropertyBagTraits.h" |
| 13 #include "bindings/core/v8/V8Binding.h" |
| 14 #include "bindings/core/v8/V8MessagePort.h" |
| 15 #include "bindings/core/v8/custom/V8ArrayBufferViewCustom.h" |
| 16 #include "bindings/core/v8/custom/V8Uint8ArrayCustom.h" |
| 17 #include "core/html/track/TrackBase.h" |
| 18 #include "wtf/HashSet.h" |
| 19 #include "wtf/Noncopyable.h" |
| 20 #include "wtf/Vector.h" |
| 21 #include "wtf/text/AtomicString.h" |
| 22 #include "wtf/text/WTFString.h" |
| 23 #include <v8.h> |
| 24 |
| 25 namespace blink { |
| 26 |
| 27 class ArrayValue; |
| 28 class Dictionary; |
| 29 class LocalDOMWindow; |
| 30 |
| 31 // FIXME: Remove these specialization. Maybe the IDL compiler |
| 32 // should generate them. |
| 33 template <> |
| 34 struct PropertyBagTraits<Uint8Array> { |
| 35 typedef V8Uint8Array type; |
| 36 }; |
| 37 |
| 38 template <> |
| 39 struct PropertyBagTraits<ArrayBufferView> { |
| 40 typedef V8ArrayBufferView type; |
| 41 }; |
| 42 |
| 43 // PropertyBag is used by bindings layer to retrieve native values from |
| 44 // a V8 object. |
| 45 class PropertyBag { |
| 46 WTF_MAKE_NONCOPYABLE(PropertyBag); |
| 47 public: |
| 48 enum PropertyNullable { |
| 49 IsNullable, |
| 50 IsNotNullable |
| 51 }; |
| 52 |
| 53 PropertyBag(v8::Isolate* isolate, const v8::Handle<v8::Object>& object, Exce
ptionState& exceptionState) |
| 54 : m_isolate(isolate) |
| 55 , m_object(object) |
| 56 , m_exceptionState(exceptionState) |
| 57 { |
| 58 ASSERT(!m_object.IsEmpty()); |
| 59 } |
| 60 |
| 61 bool hasProperty(const String& key) const |
| 62 { |
| 63 v8::Handle<v8::String> v8Key = v8String(m_isolate, key); |
| 64 return m_object->Has(v8Key); |
| 65 } |
| 66 |
| 67 template <typename T> |
| 68 bool get(const String& key, T& value, bool& hasValue, PropertyNullable nulla
ble = IsNotNullable) const |
| 69 { |
| 70 hasValue = false; |
| 71 v8::Handle<v8::String> v8Key = v8String(m_isolate, key); |
| 72 v8::Local<v8::Value> v8Value = m_object->Get(v8Key); |
| 73 if (v8Value.IsEmpty()) |
| 74 return false; |
| 75 |
| 76 hasValue = true; |
| 77 bool success; |
| 78 if (nullable == IsNullable) { |
| 79 // Try to get a value before isUndefinedOrNull() check |
| 80 // because getInternal() may handle null/undefined. |
| 81 success = getInternal(key, v8Value, value); |
| 82 if (isUndefinedOrNull(v8Value)) { |
| 83 m_exceptionState.clearException(); |
| 84 return true; |
| 85 } |
| 86 } else { |
| 87 if (isUndefinedOrNull(v8Value)) |
| 88 return false; |
| 89 success = getInternal(key, v8Value, value); |
| 90 } |
| 91 |
| 92 if (m_exceptionState.throwIfNeeded()) { |
| 93 m_exceptionState.clearException(); |
| 94 return false; |
| 95 } |
| 96 return success; |
| 97 } |
| 98 |
| 99 template <typename T> |
| 100 bool get(const String& key, T& value, PropertyNullable nullable = IsNotNulla
ble) const |
| 101 { |
| 102 bool unused; |
| 103 return get(key, value, unused, nullable); |
| 104 } |
| 105 |
| 106 // Similar to get() but returns true when the V8 object doesn't have the giv
en key. |
| 107 template <typename T> |
| 108 bool convert(const String& key, T& value) const |
| 109 { |
| 110 v8::Handle<v8::String> v8Key = v8String(m_isolate, key); |
| 111 v8::Local<v8::Value> v8Value = m_object->Get(v8Key); |
| 112 if (v8Value.IsEmpty()) |
| 113 return true; |
| 114 bool success = getInternal(key, v8Value, value); |
| 115 if (isUndefinedOrNull(v8Value)) { |
| 116 m_exceptionState.clearException(); |
| 117 return true; |
| 118 } |
| 119 return success; |
| 120 } |
| 121 |
| 122 template <typename T> |
| 123 bool set(const String& key, const T& value) |
| 124 { |
| 125 // FIXME: Use the right creationContext. |
| 126 v8::Handle<v8::Object> creationContext; |
| 127 return m_object->Set(v8String(m_isolate, key), V8ValueTraits<T>::toV8Val
ue(value, creationContext, m_isolate)); |
| 128 } |
| 129 |
| 130 private: |
| 131 // FIXME: Following specializations should be gone. |
| 132 bool getInternal(const String&, v8::Handle<v8::Value>&, ArrayValue&) const; |
| 133 bool getInternal(const String&, v8::Handle<v8::Value>&, RefPtrWillBeMember<L
ocalDOMWindow>&) const; |
| 134 bool getInternal(const String&, v8::Handle<v8::Value>&, MessagePortArray&) c
onst; |
| 135 bool getInternal(const String&, v8::Handle<v8::Value>&, HashSet<AtomicString
>&) const; |
| 136 bool getInternal(const String&, v8::Handle<v8::Value>&, RefPtrWillBeMember<T
rackBase>&) const; |
| 137 bool getInternal(const String&, v8::Handle<v8::Value>&, RefPtrWillBeMember<E
ventTarget>&) const; |
| 138 |
| 139 // 'any' type use this function. |
| 140 bool getInternal(const String& key, v8::Handle<v8::Value>& v8Value, v8::Loca
l<v8::Value>& value) const |
| 141 { |
| 142 value = v8Value; |
| 143 return true; |
| 144 } |
| 145 |
| 146 // IDL interface types use this template. |
| 147 template <template <typename> class PointerType, typename T> |
| 148 bool getInternal(const String& key, v8::Handle<v8::Value>& v8Value, PointerT
ype<T>& value) const |
| 149 { |
| 150 value = PropertyBagTraits<T>::type::toImplWithTypeCheck(m_isolate, v8Val
ue); |
| 151 return !!value; |
| 152 } |
| 153 |
| 154 // Container types use following templates. |
| 155 |
| 156 template <typename T> |
| 157 bool getInternal(const String& key, v8::Handle<v8::Value>& v8Value, Vector<T
>& value) const |
| 158 { |
| 159 if (!v8Value->IsArray()) |
| 160 return false; |
| 161 value = toImplArray<T>(v8Value, 0, m_isolate); |
| 162 return true; |
| 163 } |
| 164 |
| 165 template <typename T> |
| 166 bool getInternal(const String& key, v8::Handle<v8::Value>& v8Value, Nullable
<T>& value) const |
| 167 { |
| 168 if (isUndefinedOrNull(v8Value)) |
| 169 return true; |
| 170 |
| 171 T innerValue; |
| 172 if (getInternal(key, v8Value, innerValue)) { |
| 173 value.set(innerValue); |
| 174 return true; |
| 175 } |
| 176 return false; |
| 177 } |
| 178 |
| 179 // Default template, primitive types use this template. |
| 180 template <typename T> |
| 181 bool getInternal(const String& key, v8::Handle<v8::Value>& v8Value, T& value
) const |
| 182 { |
| 183 value = NativeValueTraits<T>::nativeValueMayFail(m_isolate, v8Value, m_e
xceptionState); |
| 184 if (m_exceptionState.hadException()) |
| 185 return false; |
| 186 return true; |
| 187 } |
| 188 |
| 189 v8::Isolate* m_isolate; |
| 190 v8::Handle<v8::Object> m_object; |
| 191 ExceptionState& m_exceptionState; |
| 192 |
| 193 friend class Dictionary; |
| 194 }; |
| 195 |
| 196 // FIXME: Reduce duplication. Maybe move to V8Binding.h? |
| 197 template <typename T> |
| 198 struct TypeErrorMessage { |
| 199 static void throwTypeError(const String& key, const String& typeName, Except
ionState& exceptionState) |
| 200 { |
| 201 exceptionState.throwTypeError(ExceptionMessages::incorrectPropertyType(k
ey, "does not have a " + typeName + " type.")); |
| 202 } |
| 203 }; |
| 204 |
| 205 template <typename T> |
| 206 struct TypeErrorMessage<HashSet<T> > { |
| 207 static void throwTypeError(const String& key, const String& typeName, Except
ionState& exceptionState) |
| 208 { |
| 209 exceptionState.throwTypeError(ExceptionMessages::notASequenceTypePropert
y(key)); |
| 210 } |
| 211 }; |
| 212 |
| 213 template <typename T> |
| 214 struct TypeErrorMessage<Vector<T> > { |
| 215 static void throwTypeError(const String& key, const String& typeName, Except
ionState& exceptionState) |
| 216 { |
| 217 exceptionState.throwTypeError(ExceptionMessages::notASequenceTypePropert
y(key)); |
| 218 } |
| 219 }; |
| 220 |
| 221 template <> |
| 222 struct TypeErrorMessage<ArrayValue> { |
| 223 static void throwTypeError(const String& key, const String& typeName, Except
ionState& exceptionState) |
| 224 { |
| 225 exceptionState.throwTypeError(ExceptionMessages::notASequenceTypePropert
y(key)); |
| 226 } |
| 227 }; |
| 228 |
| 229 // FIXME: Separate into its own header file. |
| 230 class EventInitInitializer { |
| 231 public: |
| 232 EventInitInitializer(const String& interfaceName, const PropertyBag& bag, Ex
ceptionState& exceptionState) |
| 233 : m_interfaceName(interfaceName) |
| 234 , m_bag(bag) |
| 235 , m_exceptionState(exceptionState) |
| 236 { |
| 237 } |
| 238 |
| 239 template <typename T> |
| 240 bool initializeProperty(const String& key, T& value, const String& typeName,
PropertyBag::PropertyNullable nullable) |
| 241 { |
| 242 if (!m_bag.hasProperty(key)) |
| 243 return true; |
| 244 |
| 245 if (m_bag.convert(key, value)) |
| 246 return true; |
| 247 |
| 248 if (m_exceptionState.throwIfNeeded()) |
| 249 return false; |
| 250 |
| 251 TypeErrorMessage<T>::throwTypeError(key, typeName, m_exceptionState); |
| 252 return false; |
| 253 } |
| 254 |
| 255 // FIXME: unnecessary? |
| 256 const String& interfaceName() const { return m_interfaceName; } |
| 257 |
| 258 private: |
| 259 const String m_interfaceName; |
| 260 const PropertyBag& m_bag; |
| 261 ExceptionState& m_exceptionState; |
| 262 }; |
| 263 |
| 264 } // namespace blink |
| 265 |
| 266 #endif // PropertyBag_h |
OLD | NEW |