Changeset 128379 in webkit
- Timestamp:
- Sep 12, 2012 4:20:22 PM (12 years ago)
- Location:
- trunk/Source/WebCore
- Files:
-
- 9 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/WebCore/ChangeLog
r128376 r128379 1 2012-09-12 Alec Flett <alecflett@chromium.org> 2 3 IndexedDB: Use ScriptValue instead of SerializedScriptValue when possible 4 https://bugs.webkit.org/show_bug.cgi?id=94023 5 6 Reviewed by Kentaro Hara. 7 8 Transition the put/add/update methods to accept direct ScriptValue 9 objects rather than SerializedScriptValues, to eliminate lots of 10 redundant deserialization/serialization steps while storing 11 values. 12 13 Also see https://bugs.webkit.org/show_bug.cgi?id=95409 for 14 followup get/openCursor work, following this. 15 16 No new tests, this is a performance refactor of core IDB 17 functionality. Most existing tests cover correctness. Tests that 18 might fail include: 19 20 storage/indexeddb/objectstore-basics.html 21 storage/indexeddb/keypath-basics.html 22 storage/indexeddb/index-basics.html 23 24 * Modules/indexeddb/IDBCursor.cpp: 25 (WebCore::IDBCursor::update): 26 * Modules/indexeddb/IDBCursor.h: 27 (IDBCursor): 28 * Modules/indexeddb/IDBCursor.idl: 29 * Modules/indexeddb/IDBObjectStore.cpp: 30 (WebCore::generateIndexKeysForValue): 31 (WebCore::IDBObjectStore::add): 32 (WebCore::IDBObjectStore::put): 33 (WebCore): 34 * Modules/indexeddb/IDBObjectStore.h: 35 (WebCore::IDBObjectStore::add): 36 (WebCore::IDBObjectStore::put): 37 (IDBObjectStore): 38 * Modules/indexeddb/IDBObjectStore.idl: 39 * bindings/v8/IDBBindingUtilities.cpp: 40 (WebCore): 41 (WebCore::createIDBKeyFromScriptValueAndKeyPath): 42 (WebCore::deserializeIDBValue): 43 (WebCore::canInjectIDBKeyIntoScriptValue): 44 * bindings/v8/IDBBindingUtilities.h: 45 (WebCore): 46 1 47 2012-09-12 Chris Fleizach <cfleizach@apple.com> 2 48 -
trunk/Source/WebCore/Modules/indexeddb/IDBCursor.cpp
r126254 r128379 126 126 } 127 127 128 PassRefPtr<IDBRequest> IDBCursor::update(ScriptExecutionContext* context, PassRefPtr<SerializedScriptValue> prpValue, ExceptionCode& ec)128 PassRefPtr<IDBRequest> IDBCursor::update(ScriptExecutionContext* context, ScriptValue& value, ExceptionCode& ec) 129 129 { 130 130 IDB_TRACE("IDBCursor::update"); 131 RefPtr<SerializedScriptValue> value = prpValue;132 131 133 132 if (!m_gotValue || isKeyCursor()) { … … 141 140 if (m_transaction->isReadOnly()) { 142 141 ec = IDBDatabaseException::READ_ONLY_ERR; 143 return 0;144 }145 if (value->blobURLs().size() > 0) {146 // FIXME: Add Blob/File/FileList support147 ec = IDBDatabaseException::IDB_DATA_CLONE_ERR;148 142 return 0; 149 143 } … … 153 147 const bool usesInLineKeys = !keyPath.isNull(); 154 148 if (usesInLineKeys) { 155 RefPtr<IDBKey> keyPathKey = createIDBKeyFromS erializedValueAndKeyPath(value, keyPath);149 RefPtr<IDBKey> keyPathKey = createIDBKeyFromScriptValueAndKeyPath(value, keyPath); 156 150 if (!keyPathKey || !keyPathKey->isEqual(m_currentPrimaryKey.get())) { 157 151 ec = IDBDatabaseException::DATA_ERR; -
trunk/Source/WebCore/Modules/indexeddb/IDBCursor.h
r125568 r128379 76 76 IDBAny* source() const; 77 77 78 PassRefPtr<IDBRequest> update(ScriptExecutionContext*, PassRefPtr<SerializedScriptValue>, ExceptionCode&);78 PassRefPtr<IDBRequest> update(ScriptExecutionContext*, ScriptValue&, ExceptionCode&); 79 79 void advance(unsigned long, ExceptionCode&); 80 80 void continueFunction(PassRefPtr<IDBKey>, ExceptionCode&); -
trunk/Source/WebCore/Modules/indexeddb/IDBCursor.idl
r116337 r128379 40 40 readonly attribute IDBAny source; 41 41 42 [CallWith=ScriptExecutionContext] IDBRequest update(in SerializedScriptValuevalue)42 [CallWith=ScriptExecutionContext] IDBRequest update(in any value) 43 43 raises (IDBDatabaseException); 44 44 void advance(in unsigned long count) -
trunk/Source/WebCore/Modules/indexeddb/IDBObjectStore.cpp
r126968 r128379 106 106 107 107 static void generateIndexKeysForValue(const IDBIndexMetadata& indexMetadata, 108 PassRefPtr<SerializedScriptValue>objectValue,108 const ScriptValue& objectValue, 109 109 IDBObjectStore::IndexKeys* indexKeys) 110 110 { 111 111 ASSERT(indexKeys); 112 RefPtr<IDBKey> indexKey = createIDBKeyFromS erializedValueAndKeyPath(objectValue, indexMetadata.keyPath);112 RefPtr<IDBKey> indexKey = createIDBKeyFromScriptValueAndKeyPath(objectValue, indexMetadata.keyPath); 113 113 114 114 if (!indexKey) … … 130 130 } 131 131 132 PassRefPtr<IDBRequest> IDBObjectStore::add(ScriptExecutionContext* context, PassRefPtr<SerializedScriptValue>value, PassRefPtr<IDBKey> key, ExceptionCode& ec)132 PassRefPtr<IDBRequest> IDBObjectStore::add(ScriptExecutionContext* context, ScriptValue& value, PassRefPtr<IDBKey> key, ExceptionCode& ec) 133 133 { 134 134 IDB_TRACE("IDBObjectStore::add"); … … 136 136 } 137 137 138 PassRefPtr<IDBRequest> IDBObjectStore::put(ScriptExecutionContext* context, PassRefPtr<SerializedScriptValue>value, PassRefPtr<IDBKey> key, ExceptionCode& ec)138 PassRefPtr<IDBRequest> IDBObjectStore::put(ScriptExecutionContext* context, ScriptValue& value, PassRefPtr<IDBKey> key, ExceptionCode& ec) 139 139 { 140 140 IDB_TRACE("IDBObjectStore::put"); … … 142 142 } 143 143 144 PassRefPtr<IDBRequest> IDBObjectStore::put(IDBObjectStoreBackendInterface::PutMode putMode, PassRefPtr<IDBAny> source, ScriptExecutionContext* context, PassRefPtr<SerializedScriptValue> prpValue, PassRefPtr<IDBKey> prpKey, ExceptionCode& ec)144 PassRefPtr<IDBRequest> IDBObjectStore::put(IDBObjectStoreBackendInterface::PutMode putMode, PassRefPtr<IDBAny> source, ScriptExecutionContext* context, ScriptValue& value, PassRefPtr<IDBKey> prpKey, ExceptionCode& ec) 145 145 { 146 146 IDB_TRACE("IDBObjectStore::put"); 147 RefPtr<SerializedScriptValue> value = prpValue;148 147 RefPtr<IDBKey> key = prpKey; 149 148 if (m_deleted) { … … 159 158 return 0; 160 159 } 161 if (value->blobURLs().size() > 0) { 160 161 ScriptState* state = ScriptState::current(); 162 RefPtr<SerializedScriptValue> serializedValue = value.serialize(state); 163 if (state->hadException()) { 164 ec = IDBDatabaseException::IDB_DATA_CLONE_ERR; 165 return 0; 166 } 167 168 if (serializedValue->blobURLs().size() > 0) { 162 169 // FIXME: Add Blob/File/FileList support 163 170 ec = IDBDatabaseException::IDB_DATA_CLONE_ERR; … … 178 185 } 179 186 if (usesInLineKeys) { 180 RefPtr<IDBKey> keyPathKey = createIDBKeyFromS erializedValueAndKeyPath(value, keyPath);187 RefPtr<IDBKey> keyPathKey = createIDBKeyFromScriptValueAndKeyPath(value, keyPath); 181 188 if (keyPathKey && !keyPathKey->isValid()) { 182 189 ec = IDBDatabaseException::DATA_ERR; … … 188 195 } 189 196 if (hasKeyGenerator && !keyPathKey) { 190 RefPtr<IDBKey> dummyKey = IDBKey::createNumber(-1); 191 RefPtr<SerializedScriptValue> valueAfterInjection = injectIDBKeyIntoSerializedValue(dummyKey, value, keyPath); 192 if (!valueAfterInjection) { 197 if (!canInjectIDBKeyIntoScriptValue(value, keyPath)) { 193 198 ec = IDBDatabaseException::DATA_ERR; 194 199 return 0; … … 214 219 215 220 RefPtr<IDBRequest> request = IDBRequest::create(context, source, m_transaction.get()); 216 m_backend->putWithIndexKeys( value.release(), key.release(), putMode, request, m_transaction->backend(), indexNames, indexKeys, ec);221 m_backend->putWithIndexKeys(serializedValue.release(), key.release(), putMode, request, m_transaction->backend(), indexNames, indexKeys, ec); 217 222 if (ec) { 218 223 request->markEarlyDeath(); … … 314 319 } 315 320 316 virtual void handleEvent(ScriptExecutionContext* , Event* event)321 virtual void handleEvent(ScriptExecutionContext* context, Event* event) 317 322 { 318 323 ASSERT(event->type() == eventNames().successEvent); … … 337 342 338 343 ASSERT(valueAny->type() == IDBAny::SerializedScriptValueType); 339 RefPtr<SerializedScriptValue> value = valueAny->serializedScriptValue(); 344 RefPtr<SerializedScriptValue> serializedValue = valueAny->serializedScriptValue(); 345 ScriptValue value(deserializeIDBValue(context, serializedValue)); 340 346 341 347 IDBObjectStore::IndexKeys indexKeys; -
trunk/Source/WebCore/Modules/indexeddb/IDBObjectStore.h
r127757 r128379 65 65 bool autoIncrement() const { return m_metadata.autoIncrement; } 66 66 67 PassRefPtr<IDBRequest> add(ScriptExecutionContext* context, PassRefPtr<SerializedScriptValue>value, ExceptionCode& ec) { return add(context, value, 0, ec); }68 PassRefPtr<IDBRequest> put(ScriptExecutionContext* context, PassRefPtr<SerializedScriptValue>value, ExceptionCode& ec) { return put(context, value, 0, ec); }67 PassRefPtr<IDBRequest> add(ScriptExecutionContext* context, ScriptValue& value, ExceptionCode& ec) { return add(context, value, 0, ec); } 68 PassRefPtr<IDBRequest> put(ScriptExecutionContext* context, ScriptValue& value, ExceptionCode& ec) { return put(context, value, 0, ec); } 69 69 PassRefPtr<IDBRequest> openCursor(ScriptExecutionContext* context, ExceptionCode& ec) { return openCursor(context, static_cast<IDBKeyRange*>(0), ec); } 70 70 PassRefPtr<IDBRequest> openCursor(ScriptExecutionContext* context, PassRefPtr<IDBKeyRange> keyRange, ExceptionCode& ec) { return openCursor(context, keyRange, IDBCursor::directionNext(), ec); } … … 78 78 PassRefPtr<IDBRequest> get(ScriptExecutionContext*, PassRefPtr<IDBKey>, ExceptionCode&); 79 79 PassRefPtr<IDBRequest> get(ScriptExecutionContext*, PassRefPtr<IDBKeyRange>, ExceptionCode&); 80 PassRefPtr<IDBRequest> add(ScriptExecutionContext*, PassRefPtr<SerializedScriptValue>, PassRefPtr<IDBKey>, ExceptionCode&);81 PassRefPtr<IDBRequest> put(ScriptExecutionContext*, PassRefPtr<SerializedScriptValue>, PassRefPtr<IDBKey>, ExceptionCode&);80 PassRefPtr<IDBRequest> add(ScriptExecutionContext*, ScriptValue&, PassRefPtr<IDBKey>, ExceptionCode&); 81 PassRefPtr<IDBRequest> put(ScriptExecutionContext*, ScriptValue&, PassRefPtr<IDBKey>, ExceptionCode&); 82 82 PassRefPtr<IDBRequest> deleteFunction(ScriptExecutionContext*, PassRefPtr<IDBKeyRange>, ExceptionCode&); 83 83 PassRefPtr<IDBRequest> deleteFunction(ScriptExecutionContext*, PassRefPtr<IDBKey> key, ExceptionCode&); … … 98 98 PassRefPtr<IDBRequest> count(ScriptExecutionContext*, PassRefPtr<IDBKey>, ExceptionCode&); 99 99 100 PassRefPtr<IDBRequest> put(IDBObjectStoreBackendInterface::PutMode, PassRefPtr<IDBAny> source, ScriptExecutionContext*, PassRefPtr<SerializedScriptValue>, PassRefPtr<IDBKey>, ExceptionCode&);100 PassRefPtr<IDBRequest> put(IDBObjectStoreBackendInterface::PutMode, PassRefPtr<IDBAny> source, ScriptExecutionContext*, ScriptValue&, PassRefPtr<IDBKey>, ExceptionCode&); 101 101 void markDeleted() { m_deleted = true; } 102 102 void transactionFinished(); -
trunk/Source/WebCore/Modules/indexeddb/IDBObjectStore.idl
r125730 r128379 35 35 readonly attribute boolean autoIncrement; 36 36 37 [CallWith=ScriptExecutionContext] IDBRequest put(in SerializedScriptValuevalue, in [Optional] IDBKey key)37 [CallWith=ScriptExecutionContext] IDBRequest put(in any value, in [Optional] IDBKey key) 38 38 raises (IDBDatabaseException); 39 [CallWith=ScriptExecutionContext] IDBRequest add(in SerializedScriptValuevalue, in [Optional] IDBKey key)39 [CallWith=ScriptExecutionContext] IDBRequest add(in any value, in [Optional] IDBKey key) 40 40 raises (IDBDatabaseException); 41 41 [CallWith=ScriptExecutionContext, ImplementedAs=deleteFunction] IDBRequest delete(in IDBKeyRange? keyRange) -
trunk/Source/WebCore/bindings/v8/IDBBindingUtilities.cpp
r128125 r128379 36 36 #include "V8Binding.h" 37 37 #include "V8IDBKey.h" 38 #include "WorldContextHandle.h" 38 39 #include <wtf/MathExtras.h> 39 40 #include <wtf/Vector.h> … … 86 87 } 87 88 88 namespace {89 90 89 template<typename T> 91 bool getValueFrom(T indexOrName, v8::Handle<v8::Value>& v8Value)90 static bool getValueFrom(T indexOrName, v8::Handle<v8::Value>& v8Value) 92 91 { 93 92 v8::Local<v8::Object> object = v8Value->ToObject(); … … 99 98 100 99 template<typename T> 101 bool setValue(v8::Handle<v8::Value>& v8Object, T indexOrName, const v8::Handle<v8::Value>& v8Value)100 static bool setValue(v8::Handle<v8::Value>& v8Object, T indexOrName, const v8::Handle<v8::Value>& v8Value) 102 101 { 103 102 v8::Local<v8::Object> object = v8Object->ToObject(); … … 105 104 } 106 105 107 bool get(v8::Handle<v8::Value>& object, const String& keyPathElement)106 static bool get(v8::Handle<v8::Value>& object, const String& keyPathElement, v8::Handle<v8::Value>& result) 108 107 { 109 108 if (object->IsString() && keyPathElement == "length") { 110 109 int32_t length = v8::Handle<v8::String>::Cast(object)->Length(); 111 object = v8::Number::New(length);110 result = v8::Number::New(length); 112 111 return true; 113 112 } 114 return object->IsObject() && getValueFrom(v8String(keyPathElement), object); 115 } 116 117 bool set(v8::Handle<v8::Value>& object, const String& keyPathElement, const v8::Handle<v8::Value>& v8Value) 118 { 119 return object->IsObject() && setValue(object, v8String(keyPathElement), v8Value); 120 } 121 122 v8::Handle<v8::Value> getNthValueOnKeyPath(v8::Handle<v8::Value>& rootValue, const Vector<String>& keyPathElements, size_t index) 113 return object->IsObject() && getValueFrom(v8String(keyPathElement), result); 114 } 115 116 static bool canSet(v8::Handle<v8::Value>& object, const String& keyPathElement) 117 { 118 return object->IsObject(); 119 } 120 121 static bool set(v8::Handle<v8::Value>& object, const String& keyPathElement, const v8::Handle<v8::Value>& v8Value) 122 { 123 return canSet(object, keyPathElement) && setValue(object, v8String(keyPathElement), v8Value); 124 } 125 126 static v8::Handle<v8::Value> getNthValueOnKeyPath(v8::Handle<v8::Value>& rootValue, const Vector<String>& keyPathElements, size_t index) 123 127 { 124 128 v8::Handle<v8::Value> currentValue(rootValue); 125 126 129 ASSERT(index <= keyPathElements.size()); 127 130 for (size_t i = 0; i < index; ++i) { 128 if (!get(currentValue, keyPathElements[i])) 131 v8::Handle<v8::Value> parentValue(currentValue); 132 if (!get(parentValue, keyPathElements[i], currentValue)) 129 133 return v8Undefined(); 130 134 } … … 133 137 } 134 138 135 v8::Handle<v8::Value> ensureNthValueOnKeyPath(v8::Handle<v8::Value>& rootValue, const Vector<String>& keyPathElements, size_t index) 136 { 139 static bool canInjectNthValueOnKeyPath(v8::Handle<v8::Value>& rootValue, const Vector<String>& keyPathElements, size_t index) 140 { 141 if (!rootValue->IsObject()) 142 return false; 143 137 144 v8::Handle<v8::Value> currentValue(rootValue); 138 145 … … 141 148 v8::Handle<v8::Value> parentValue(currentValue); 142 149 const String& keyPathElement = keyPathElements[i]; 143 if (!get(currentValue, keyPathElement)) { 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>& rootValue, const Vector<String>& keyPathElements, size_t index) 158 { 159 v8::Handle<v8::Value> currentValue(rootValue); 160 161 ASSERT(index <= keyPathElements.size()); 162 for (size_t i = 0; i < index; ++i) { 163 v8::Handle<v8::Value> parentValue(currentValue); 164 const String& keyPathElement = keyPathElements[i]; 165 if (!get(parentValue, keyPathElement, currentValue)) { 144 166 v8::Handle<v8::Object> object = v8::Object::New(); 145 167 if (!set(parentValue, keyPathElement, object)) … … 152 174 } 153 175 154 } // anonymous namespace 155 156 static PassRefPtr<IDBKey> createIDBKeyFromSerializedValueAndKeyPath(PassRefPtr<SerializedScriptValue> prpValue, const String& keyPath) 176 static PassRefPtr<IDBKey> createIDBKeyFromScriptValueAndKeyPath(const ScriptValue& value, const String& keyPath) 157 177 { 158 178 Vector<String> keyPathElements; … … 161 181 ASSERT(error == IDBKeyPathParseErrorNone); 162 182 183 v8::Handle<v8::Value> v8Value(value.v8Value()); 184 v8::Handle<v8::Value> v8Key(getNthValueOnKeyPath(v8Value, keyPathElements, keyPathElements.size())); 185 if (v8Key.IsEmpty()) 186 return 0; 187 return createIDBKeyFromValue(v8Key); 188 } 189 190 PassRefPtr<IDBKey> createIDBKeyFromScriptValueAndKeyPath(const ScriptValue& value, 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, array[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 212 static PassRefPtr<IDBKey> createIDBKeyFromSerializedValueAndKeyPath(PassRefPtr<SerializedScriptValue> prpValue, const String& keyPath) 213 { 214 Vector<String> keyPathElements; 215 IDBKeyPathParseError error; 216 IDBParseKeyPath(keyPath, keyPathElements, error); 217 ASSERT(error == IDBKeyPathParseErrorNone); 218 163 219 RefPtr<SerializedScriptValue> value = prpValue; 164 220 … … 173 229 } 174 230 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, PassRefPtr<SerializedScriptValue> prpValue) 233 { 234 v8::HandleScope handleScope; 235 v8::Context::Scope contextScope(toV8Context(scriptContext, UseCurrentWorld)); 236 return ScriptValue(prpValue->deserialize()); 237 } 175 238 176 239 PassRefPtr<IDBKey> createIDBKeyFromSerializedValueAndKeyPath(PassRefPtr<SerializedScriptValue> prpValue, const IDBKeyPath& keyPath) … … 224 287 } 225 288 289 bool canInjectIDBKeyIntoScriptValue(const ScriptValue& scriptValue, const IDBKeyPath& 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 226 305 } // namespace WebCore 227 306 -
trunk/Source/WebCore/bindings/v8/IDBBindingUtilities.h
r117817 r128379 29 29 #if ENABLE(INDEXED_DATABASE) 30 30 31 #include "ScriptValue.h" 31 32 #include <v8.h> 32 33 #include <wtf/Forward.h> … … 39 40 40 41 PassRefPtr<IDBKey> createIDBKeyFromValue(v8::Handle<v8::Value>); 42 43 // FIXME: remove the SerializedValue versions when their use is finally removed in https://bugs.webkit.org/show_bug.cgi?id=95409. 41 44 PassRefPtr<IDBKey> createIDBKeyFromSerializedValueAndKeyPath(PassRefPtr<SerializedScriptValue>, const IDBKeyPath&); 42 45 PassRefPtr<SerializedScriptValue> injectIDBKeyIntoSerializedValue(PassRefPtr<IDBKey>, PassRefPtr<SerializedScriptValue>, const IDBKeyPath&); 46 47 PassRefPtr<IDBKey> createIDBKeyFromScriptValueAndKeyPath(const ScriptValue&, const IDBKeyPath&); 48 bool canInjectIDBKeyIntoScriptValue(const ScriptValue&, const IDBKeyPath&); 49 ScriptValue deserializeIDBValue(ScriptExecutionContext*, PassRefPtr<SerializedScriptValue>); 43 50 44 51 }
Note: See TracChangeset
for help on using the changeset viewer.