| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (C) 2011 Google Inc. All rights reserved. | 2 * Copyright (C) 2011 Google Inc. All rights reserved. |
| 3 * | 3 * |
| 4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
| 5 * modification, are permitted provided that the following conditions | 5 * modification, are permitted provided that the following conditions |
| 6 * are met: | 6 * are met: |
| 7 * | 7 * |
| 8 * 1. Redistributions of source code must retain the above copyright | 8 * 1. Redistributions of source code must retain the above copyright |
| 9 * notice, this list of conditions and the following disclaimer. | 9 * notice, this list of conditions and the following disclaimer. |
| 10 * 2. Redistributions in binary form must reproduce the above copyright | 10 * 2. Redistributions in binary form must reproduce the above copyright |
| (...skipping 17 matching lines...) Expand all Loading... |
| 28 | 28 |
| 29 #if ENABLE(INDEXED_DATABASE) | 29 #if ENABLE(INDEXED_DATABASE) |
| 30 | 30 |
| 31 #include "IDBDatabaseException.h" | 31 #include "IDBDatabaseException.h" |
| 32 #include "IDBKey.h" | 32 #include "IDBKey.h" |
| 33 #include "IDBKeyPath.h" | 33 #include "IDBKeyPath.h" |
| 34 #include "IDBTracing.h" | 34 #include "IDBTracing.h" |
| 35 #include "SerializedScriptValue.h" | 35 #include "SerializedScriptValue.h" |
| 36 #include "V8Binding.h" | 36 #include "V8Binding.h" |
| 37 #include "V8IDBKey.h" | 37 #include "V8IDBKey.h" |
| 38 #include "WorldContextHandle.h" | |
| 39 #include <wtf/MathExtras.h> | 38 #include <wtf/MathExtras.h> |
| 40 #include <wtf/Vector.h> | 39 #include <wtf/Vector.h> |
| 41 | 40 |
| 42 namespace WebCore { | 41 namespace WebCore { |
| 43 | 42 |
| 44 static const size_t maximumDepth = 2000; | 43 static const size_t maximumDepth = 2000; |
| 45 | 44 |
| 46 static PassRefPtr<IDBKey> createIDBKeyFromValue(v8::Handle<v8::Value> value, Vec
tor<v8::Handle<v8::Array> >& stack) | 45 static PassRefPtr<IDBKey> createIDBKeyFromValue(v8::Handle<v8::Value> value, Vec
tor<v8::Handle<v8::Array> >& stack) |
| 47 { | 46 { |
| 48 if (value->IsNumber() && !isnan(value->NumberValue())) | 47 if (value->IsNumber() && !isnan(value->NumberValue())) |
| (...skipping 30 matching lines...) Expand all Loading... |
| 79 | 78 |
| 80 PassRefPtr<IDBKey> createIDBKeyFromValue(v8::Handle<v8::Value> value) | 79 PassRefPtr<IDBKey> createIDBKeyFromValue(v8::Handle<v8::Value> value) |
| 81 { | 80 { |
| 82 Vector<v8::Handle<v8::Array> > stack; | 81 Vector<v8::Handle<v8::Array> > stack; |
| 83 RefPtr<IDBKey> key = createIDBKeyFromValue(value, stack); | 82 RefPtr<IDBKey> key = createIDBKeyFromValue(value, stack); |
| 84 if (key) | 83 if (key) |
| 85 return key; | 84 return key; |
| 86 return IDBKey::createInvalid(); | 85 return IDBKey::createInvalid(); |
| 87 } | 86 } |
| 88 | 87 |
| 88 namespace { |
| 89 |
| 89 template<typename T> | 90 template<typename T> |
| 90 static bool getValueFrom(T indexOrName, v8::Handle<v8::Value>& v8Value) | 91 bool getValueFrom(T indexOrName, v8::Handle<v8::Value>& v8Value) |
| 91 { | 92 { |
| 92 v8::Local<v8::Object> object = v8Value->ToObject(); | 93 v8::Local<v8::Object> object = v8Value->ToObject(); |
| 93 if (!object->Has(indexOrName)) | 94 if (!object->Has(indexOrName)) |
| 94 return false; | 95 return false; |
| 95 v8Value = object->Get(indexOrName); | 96 v8Value = object->Get(indexOrName); |
| 96 return true; | 97 return true; |
| 97 } | 98 } |
| 98 | 99 |
| 99 template<typename T> | 100 template<typename T> |
| 100 static bool setValue(v8::Handle<v8::Value>& v8Object, T indexOrName, const v8::H
andle<v8::Value>& v8Value) | 101 bool setValue(v8::Handle<v8::Value>& v8Object, T indexOrName, const v8::Handle<v
8::Value>& v8Value) |
| 101 { | 102 { |
| 102 v8::Local<v8::Object> object = v8Object->ToObject(); | 103 v8::Local<v8::Object> object = v8Object->ToObject(); |
| 103 return object->Set(indexOrName, v8Value); | 104 return object->Set(indexOrName, v8Value); |
| 104 } | 105 } |
| 105 | 106 |
| 106 static bool get(v8::Handle<v8::Value>& object, const String& keyPathElement, v8:
:Handle<v8::Value>& result) | 107 bool get(v8::Handle<v8::Value>& object, const String& keyPathElement) |
| 107 { | 108 { |
| 108 if (object->IsString() && keyPathElement == "length") { | 109 if (object->IsString() && keyPathElement == "length") { |
| 109 int32_t length = v8::Handle<v8::String>::Cast(object)->Length(); | 110 int32_t length = v8::Handle<v8::String>::Cast(object)->Length(); |
| 110 result = v8::Number::New(length); | 111 object = v8::Number::New(length); |
| 111 return true; | 112 return true; |
| 112 } | 113 } |
| 113 return object->IsObject() && getValueFrom(v8String(keyPathElement), result); | 114 return object->IsObject() && getValueFrom(v8String(keyPathElement), object); |
| 114 } | 115 } |
| 115 | 116 |
| 116 static bool canSet(v8::Handle<v8::Value>& object, const String& keyPathElement) | 117 bool set(v8::Handle<v8::Value>& object, const String& keyPathElement, const v8::
Handle<v8::Value>& v8Value) |
| 117 { | 118 { |
| 118 return object->IsObject(); | 119 return object->IsObject() && setValue(object, v8String(keyPathElement), v8Va
lue); |
| 119 } | 120 } |
| 120 | 121 |
| 121 static bool set(v8::Handle<v8::Value>& object, const String& keyPathElement, con
st v8::Handle<v8::Value>& v8Value) | 122 v8::Handle<v8::Value> getNthValueOnKeyPath(v8::Handle<v8::Value>& rootValue, con
st Vector<String>& keyPathElements, size_t index) |
| 122 { | |
| 123 return canSet(object, keyPathElement) && setValue(object, v8String(keyPathEl
ement), v8Value); | |
| 124 } | |
| 125 | |
| 126 static v8::Handle<v8::Value> getNthValueOnKeyPath(v8::Handle<v8::Value>& rootVal
ue, const Vector<String>& keyPathElements, size_t index) | |
| 127 { | 123 { |
| 128 v8::Handle<v8::Value> currentValue(rootValue); | 124 v8::Handle<v8::Value> currentValue(rootValue); |
| 125 |
| 129 ASSERT(index <= keyPathElements.size()); | 126 ASSERT(index <= keyPathElements.size()); |
| 130 for (size_t i = 0; i < index; ++i) { | 127 for (size_t i = 0; i < index; ++i) { |
| 131 v8::Handle<v8::Value> parentValue(currentValue); | 128 if (!get(currentValue, keyPathElements[i])) |
| 132 if (!get(parentValue, keyPathElements[i], currentValue)) | |
| 133 return v8Undefined(); | 129 return v8Undefined(); |
| 134 } | 130 } |
| 135 | 131 |
| 136 return currentValue; | 132 return currentValue; |
| 137 } | 133 } |
| 138 | 134 |
| 139 static bool canInjectNthValueOnKeyPath(v8::Handle<v8::Value>& rootValue, const V
ector<String>& keyPathElements, size_t index) | 135 v8::Handle<v8::Value> ensureNthValueOnKeyPath(v8::Handle<v8::Value>& rootValue,
const Vector<String>& keyPathElements, size_t index) |
| 140 { | |
| 141 if (!rootValue->IsObject()) | |
| 142 return false; | |
| 143 | |
| 144 v8::Handle<v8::Value> currentValue(rootValue); | |
| 145 | |
| 146 ASSERT(index <= keyPathElements.size()); | |
| 147 for (size_t i = 0; i < index; ++i) { | |
| 148 v8::Handle<v8::Value> parentValue(currentValue); | |
| 149 const String& keyPathElement = keyPathElements[i]; | |
| 150 if (!get(parentValue, keyPathElement, currentValue)) | |
| 151 return canSet(parentValue, keyPathElement); | |
| 152 } | |
| 153 return true; | |
| 154 } | |
| 155 | |
| 156 | |
| 157 static v8::Handle<v8::Value> ensureNthValueOnKeyPath(v8::Handle<v8::Value>& root
Value, const Vector<String>& keyPathElements, size_t index) | |
| 158 { | 136 { |
| 159 v8::Handle<v8::Value> currentValue(rootValue); | 137 v8::Handle<v8::Value> currentValue(rootValue); |
| 160 | 138 |
| 161 ASSERT(index <= keyPathElements.size()); | 139 ASSERT(index <= keyPathElements.size()); |
| 162 for (size_t i = 0; i < index; ++i) { | 140 for (size_t i = 0; i < index; ++i) { |
| 163 v8::Handle<v8::Value> parentValue(currentValue); | 141 v8::Handle<v8::Value> parentValue(currentValue); |
| 164 const String& keyPathElement = keyPathElements[i]; | 142 const String& keyPathElement = keyPathElements[i]; |
| 165 if (!get(parentValue, keyPathElement, currentValue)) { | 143 if (!get(currentValue, keyPathElement)) { |
| 166 v8::Handle<v8::Object> object = v8::Object::New(); | 144 v8::Handle<v8::Object> object = v8::Object::New(); |
| 167 if (!set(parentValue, keyPathElement, object)) | 145 if (!set(parentValue, keyPathElement, object)) |
| 168 return v8Undefined(); | 146 return v8Undefined(); |
| 169 currentValue = object; | 147 currentValue = object; |
| 170 } | 148 } |
| 171 } | 149 } |
| 172 | 150 |
| 173 return currentValue; | 151 return currentValue; |
| 174 } | 152 } |
| 175 | 153 |
| 176 static PassRefPtr<IDBKey> createIDBKeyFromScriptValueAndKeyPath(const ScriptValu
e& value, const String& keyPath) | 154 } // anonymous namespace |
| 177 { | |
| 178 Vector<String> keyPathElements; | |
| 179 IDBKeyPathParseError error; | |
| 180 IDBParseKeyPath(keyPath, keyPathElements, error); | |
| 181 ASSERT(error == IDBKeyPathParseErrorNone); | |
| 182 | |
| 183 v8::Handle<v8::Value> v8Value(value.v8Value()); | |
| 184 v8::Handle<v8::Value> v8Key(getNthValueOnKeyPath(v8Value, keyPathElements, k
eyPathElements.size())); | |
| 185 if (v8Key.IsEmpty()) | |
| 186 return 0; | |
| 187 return createIDBKeyFromValue(v8Key); | |
| 188 } | |
| 189 | |
| 190 PassRefPtr<IDBKey> createIDBKeyFromScriptValueAndKeyPath(const ScriptValue& valu
e, const IDBKeyPath& keyPath) | |
| 191 { | |
| 192 IDB_TRACE("createIDBKeyFromScriptValueAndKeyPath"); | |
| 193 ASSERT(!keyPath.isNull()); | |
| 194 | |
| 195 v8::HandleScope scope; | |
| 196 if (keyPath.type() == IDBKeyPath::ArrayType) { | |
| 197 IDBKey::KeyArray result; | |
| 198 const Vector<String>& array = keyPath.array(); | |
| 199 for (size_t i = 0; i < array.size(); ++i) { | |
| 200 RefPtr<IDBKey> key = createIDBKeyFromScriptValueAndKeyPath(value, ar
ray[i]); | |
| 201 if (!key) | |
| 202 return 0; | |
| 203 result.append(key); | |
| 204 } | |
| 205 return IDBKey::createArray(result); | |
| 206 } | |
| 207 | |
| 208 ASSERT(keyPath.type() == IDBKeyPath::StringType); | |
| 209 return createIDBKeyFromScriptValueAndKeyPath(value, keyPath.string()); | |
| 210 } | |
| 211 | 155 |
| 212 static PassRefPtr<IDBKey> createIDBKeyFromSerializedValueAndKeyPath(PassRefPtr<S
erializedScriptValue> prpValue, const String& keyPath) | 156 static PassRefPtr<IDBKey> createIDBKeyFromSerializedValueAndKeyPath(PassRefPtr<S
erializedScriptValue> prpValue, const String& keyPath) |
| 213 { | 157 { |
| 214 Vector<String> keyPathElements; | 158 Vector<String> keyPathElements; |
| 215 IDBKeyPathParseError error; | 159 IDBKeyPathParseError error; |
| 216 IDBParseKeyPath(keyPath, keyPathElements, error); | 160 IDBParseKeyPath(keyPath, keyPathElements, error); |
| 217 ASSERT(error == IDBKeyPathParseErrorNone); | 161 ASSERT(error == IDBKeyPathParseErrorNone); |
| 218 | 162 |
| 219 RefPtr<SerializedScriptValue> value = prpValue; | 163 RefPtr<SerializedScriptValue> value = prpValue; |
| 220 | 164 |
| 221 v8::HandleScope handleScope; | 165 v8::HandleScope handleScope; |
| 222 v8::Context::Scope scope(V8PerIsolateData::current()->ensureAuxiliaryContext
()); | 166 v8::Context::Scope scope(V8PerIsolateData::current()->ensureAuxiliaryContext
()); |
| 223 | 167 |
| 224 v8::Handle<v8::Value> v8Value(value->deserialize()); | 168 v8::Handle<v8::Value> v8Value(value->deserialize()); |
| 225 v8::Handle<v8::Value> v8Key(getNthValueOnKeyPath(v8Value, keyPathElements, k
eyPathElements.size())); | 169 v8::Handle<v8::Value> v8Key(getNthValueOnKeyPath(v8Value, keyPathElements, k
eyPathElements.size())); |
| 226 if (v8Key.IsEmpty()) | 170 if (v8Key.IsEmpty()) |
| 227 return 0; | 171 return 0; |
| 228 return createIDBKeyFromValue(v8Key); | 172 return createIDBKeyFromValue(v8Key); |
| 229 } | 173 } |
| 230 | 174 |
| 231 // FIXME: The only reason this exists is because we need a v8::Context and scope
inside a timer. Is there a better / more general way to do this? | |
| 232 ScriptValue deserializeIDBValue(ScriptExecutionContext* scriptContext, PassRefPt
r<SerializedScriptValue> prpValue) | |
| 233 { | |
| 234 v8::HandleScope handleScope; | |
| 235 v8::Context::Scope contextScope(toV8Context(scriptContext, UseCurrentWorld))
; | |
| 236 return ScriptValue(prpValue->deserialize()); | |
| 237 } | |
| 238 | 175 |
| 239 PassRefPtr<IDBKey> createIDBKeyFromSerializedValueAndKeyPath(PassRefPtr<Serializ
edScriptValue> prpValue, const IDBKeyPath& keyPath) | 176 PassRefPtr<IDBKey> createIDBKeyFromSerializedValueAndKeyPath(PassRefPtr<Serializ
edScriptValue> prpValue, const IDBKeyPath& keyPath) |
| 240 { | 177 { |
| 241 IDB_TRACE("createIDBKeyFromSerializedValueAndKeyPath"); | 178 IDB_TRACE("createIDBKeyFromSerializedValueAndKeyPath"); |
| 242 ASSERT(!keyPath.isNull()); | 179 ASSERT(!keyPath.isNull()); |
| 243 | 180 |
| 244 RefPtr<SerializedScriptValue> value = prpValue; | 181 RefPtr<SerializedScriptValue> value = prpValue; |
| 245 | 182 |
| 246 if (keyPath.type() == IDBKeyPath::ArrayType) { | 183 if (keyPath.type() == IDBKeyPath::ArrayType) { |
| 247 IDBKey::KeyArray result; | 184 IDBKey::KeyArray result; |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 279 v8::Handle<v8::Value> parent(ensureNthValueOnKeyPath(v8Value, keyPathElement
s, keyPathElements.size() - 1)); | 216 v8::Handle<v8::Value> parent(ensureNthValueOnKeyPath(v8Value, keyPathElement
s, keyPathElements.size() - 1)); |
| 280 if (parent.IsEmpty()) | 217 if (parent.IsEmpty()) |
| 281 return 0; | 218 return 0; |
| 282 | 219 |
| 283 if (!set(parent, keyPathElements.last(), toV8(key.get()))) | 220 if (!set(parent, keyPathElements.last(), toV8(key.get()))) |
| 284 return 0; | 221 return 0; |
| 285 | 222 |
| 286 return SerializedScriptValue::create(v8Value); | 223 return SerializedScriptValue::create(v8Value); |
| 287 } | 224 } |
| 288 | 225 |
| 289 bool canInjectIDBKeyIntoScriptValue(const ScriptValue& scriptValue, const IDBKey
Path& keyPath) | |
| 290 { | |
| 291 IDB_TRACE("canInjectIDBKeyIntoScriptValue"); | |
| 292 ASSERT(keyPath.type() == IDBKeyPath::StringType); | |
| 293 Vector<String> keyPathElements; | |
| 294 IDBKeyPathParseError error; | |
| 295 IDBParseKeyPath(keyPath.string(), keyPathElements, error); | |
| 296 ASSERT(error == IDBKeyPathParseErrorNone); | |
| 297 | |
| 298 if (!keyPathElements.size()) | |
| 299 return false; | |
| 300 | |
| 301 v8::Handle<v8::Value> v8Value(scriptValue.v8Value()); | |
| 302 return canInjectNthValueOnKeyPath(v8Value, keyPathElements, keyPathElements.
size() - 1); | |
| 303 } | |
| 304 | |
| 305 } // namespace WebCore | 226 } // namespace WebCore |
| 306 | 227 |
| 307 #endif | 228 #endif |
| OLD | NEW |