IndexedDB: Implement custom bindings for parsing options
authorcommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 19 Dec 2012 00:10:20 +0000 (00:10 +0000)
committercommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 19 Dec 2012 00:10:20 +0000 (00:10 +0000)
https://bugs.webkit.org/show_bug.cgi?id=96614

Patch by Michael Pruett <michael@68k.org> on 2012-12-18
Reviewed by Darin Adler.

Parsing the options dictionary in IDBDatabase.createObjectStore()
and IDBObjectStore.createIndex() requires custom bindings in JSC.

Tests: storage/indexeddb/*

* GNUmakefile.list.am:
* Modules/indexeddb/IDBDatabase.cpp:
(WebCore::IDBDatabase::createObjectStore):
(WebCore):
* Modules/indexeddb/IDBDatabase.h:
(IDBDatabase):
* Modules/indexeddb/IDBDatabase.idl:
* Modules/indexeddb/IDBObjectStore.cpp:
(WebCore::IDBObjectStore::createIndex):
(WebCore):
* Modules/indexeddb/IDBObjectStore.h:
(IDBObjectStore):
* Modules/indexeddb/IDBObjectStore.idl:
* UseJSC.cmake:
* bindings/js/IDBBindingUtilities.cpp:
(WebCore::idbKeyPathFromValue): Added utility function for converting a JSValue to an IDBKeyPath.
(WebCore):
* bindings/js/IDBBindingUtilities.h:
(WebCore):
* bindings/js/JSIDBDatabaseCustom.cpp: Added.
(WebCore):
(WebCore::JSIDBDatabase::createObjectStore):
* bindings/js/JSIDBObjectStoreCustom.cpp: Added.
(WebCore):
(WebCore::JSIDBObjectStore::createIndex):

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@138081 268f45cc-cd09-0410-ab3c-d52691b4dbfc

13 files changed:
Source/WebCore/ChangeLog
Source/WebCore/GNUmakefile.list.am
Source/WebCore/Modules/indexeddb/IDBDatabase.cpp
Source/WebCore/Modules/indexeddb/IDBDatabase.h
Source/WebCore/Modules/indexeddb/IDBDatabase.idl
Source/WebCore/Modules/indexeddb/IDBObjectStore.cpp
Source/WebCore/Modules/indexeddb/IDBObjectStore.h
Source/WebCore/Modules/indexeddb/IDBObjectStore.idl
Source/WebCore/UseJSC.cmake
Source/WebCore/bindings/js/IDBBindingUtilities.cpp
Source/WebCore/bindings/js/IDBBindingUtilities.h
Source/WebCore/bindings/js/JSIDBDatabaseCustom.cpp [new file with mode: 0644]
Source/WebCore/bindings/js/JSIDBObjectStoreCustom.cpp [new file with mode: 0644]

index 7f9891a..6f5bb5f 100644 (file)
@@ -1,3 +1,41 @@
+2012-12-18  Michael Pruett  <michael@68k.org>
+
+        IndexedDB: Implement custom bindings for parsing options
+        https://bugs.webkit.org/show_bug.cgi?id=96614
+
+        Reviewed by Darin Adler.
+
+        Parsing the options dictionary in IDBDatabase.createObjectStore()
+        and IDBObjectStore.createIndex() requires custom bindings in JSC.
+
+        Tests: storage/indexeddb/*
+
+        * GNUmakefile.list.am:
+        * Modules/indexeddb/IDBDatabase.cpp:
+        (WebCore::IDBDatabase::createObjectStore):
+        (WebCore):
+        * Modules/indexeddb/IDBDatabase.h:
+        (IDBDatabase):
+        * Modules/indexeddb/IDBDatabase.idl:
+        * Modules/indexeddb/IDBObjectStore.cpp:
+        (WebCore::IDBObjectStore::createIndex):
+        (WebCore):
+        * Modules/indexeddb/IDBObjectStore.h:
+        (IDBObjectStore):
+        * Modules/indexeddb/IDBObjectStore.idl:
+        * UseJSC.cmake:
+        * bindings/js/IDBBindingUtilities.cpp:
+        (WebCore::idbKeyPathFromValue): Added utility function for converting a JSValue to an IDBKeyPath.
+        (WebCore):
+        * bindings/js/IDBBindingUtilities.h:
+        (WebCore):
+        * bindings/js/JSIDBDatabaseCustom.cpp: Added.
+        (WebCore):
+        (WebCore::JSIDBDatabase::createObjectStore):
+        * bindings/js/JSIDBObjectStoreCustom.cpp: Added.
+        (WebCore):
+        (WebCore::JSIDBObjectStore::createIndex):
+
 2012-12-18  Yuki Sekiguchi  <yuki.sekiguchi@access-company.com>
 
         Cannot click an element at 2nd line or more inside inline-block in vertical writing mode.
index b7a6a2c..b783ca3 100644 (file)
@@ -2346,7 +2346,9 @@ webcore_sources += \
        Source/WebCore/bindings/js/JSHistoryCustom.cpp \
        Source/WebCore/bindings/js/JSHistoryCustom.h \
        Source/WebCore/bindings/js/JSIDBAnyCustom.cpp \
+       Source/WebCore/bindings/js/JSIDBDatabaseCustom.cpp \
        Source/WebCore/bindings/js/JSIDBKeyCustom.cpp \
+       Source/WebCore/bindings/js/JSIDBObjectStoreCustom.cpp \
        Source/WebCore/bindings/js/JSImageConstructor.cpp \
        Source/WebCore/bindings/js/JSImageConstructor.h \
        Source/WebCore/bindings/js/JSImageDataCustom.cpp \
index 1bd5b88..ebde0f1 100644 (file)
@@ -141,16 +141,8 @@ PassRefPtr<IDBAny> IDBDatabase::version() const
 
 PassRefPtr<IDBObjectStore> IDBDatabase::createObjectStore(const String& name, const Dictionary& options, ExceptionCode& ec)
 {
-    if (!m_versionChangeTransaction) {
-        ec = IDBDatabaseException::InvalidStateError;
-        return 0;
-    }
-    if (!m_versionChangeTransaction->isActive()) {
-        ec = IDBDatabaseException::TransactionInactiveError;
-        return 0;
-    }
-
     IDBKeyPath keyPath;
+    bool autoIncrement = false;
     if (!options.isUndefinedOrNull()) {
         String keyPathString;
         Vector<String> keyPathArray;
@@ -158,6 +150,22 @@ PassRefPtr<IDBObjectStore> IDBDatabase::createObjectStore(const String& name, co
             keyPath = IDBKeyPath(keyPathArray);
         else if (options.getWithUndefinedOrNullCheck("keyPath", keyPathString))
             keyPath = IDBKeyPath(keyPathString);
+
+        options.get("autoIncrement", autoIncrement);
+    }
+
+    return createObjectStore(name, keyPath, autoIncrement, ec);
+}
+
+PassRefPtr<IDBObjectStore> IDBDatabase::createObjectStore(const String& name, const IDBKeyPath& keyPath, bool autoIncrement, ExceptionCode& ec)
+{
+    if (!m_versionChangeTransaction) {
+        ec = IDBDatabaseException::InvalidStateError;
+        return 0;
+    }
+    if (!m_versionChangeTransaction->isActive()) {
+        ec = IDBDatabaseException::TransactionInactiveError;
+        return 0;
     }
 
     if (containsObjectStore(name)) {
@@ -170,10 +178,6 @@ PassRefPtr<IDBObjectStore> IDBDatabase::createObjectStore(const String& name, co
         return 0;
     }
 
-    bool autoIncrement = false;
-    if (!options.isUndefinedOrNull())
-        options.get("autoIncrement", autoIncrement);
-
     if (autoIncrement && ((keyPath.type() == IDBKeyPath::StringType && keyPath.string().isEmpty()) || keyPath.type() == IDBKeyPath::ArrayType)) {
         ec = IDBDatabaseException::InvalidAccessError;
         return 0;
index 1c97796..a9c4c5b 100644 (file)
@@ -65,6 +65,7 @@ public:
     PassRefPtr<DOMStringList> objectStoreNames() const;
 
     PassRefPtr<IDBObjectStore> createObjectStore(const String& name, const Dictionary&, ExceptionCode&);
+    PassRefPtr<IDBObjectStore> createObjectStore(const String& name, const IDBKeyPath&, bool autoIncrement, ExceptionCode&);
     PassRefPtr<IDBTransaction> transaction(ScriptExecutionContext* context, PassRefPtr<DOMStringList> scope, const String& mode, ExceptionCode& ec) { return transaction(context, *scope, mode, ec); }
     PassRefPtr<IDBTransaction> transaction(ScriptExecutionContext*, const Vector<String>&, const String& mode, ExceptionCode&);
     PassRefPtr<IDBTransaction> transaction(ScriptExecutionContext*, const String&, const String& mode, ExceptionCode&);
index 50f7e63..1348548 100644 (file)
@@ -38,7 +38,7 @@
     attribute EventListener onerror;
     attribute EventListener onversionchange;
 
-    IDBObjectStore createObjectStore(in DOMString name, in [Optional] Dictionary options)
+    [JSCustom] IDBObjectStore createObjectStore(in DOMString name, in [Optional] Dictionary options)
         raises (DOMException);
     void deleteObjectStore(in DOMString name)
         raises (DOMException);
index 7228996..073e397 100644 (file)
@@ -353,6 +353,17 @@ private:
 
 PassRefPtr<IDBIndex> IDBObjectStore::createIndex(ScriptExecutionContext* context, const String& name, const IDBKeyPath& keyPath, const Dictionary& options, ExceptionCode& ec)
 {
+    bool unique = false;
+    options.get("unique", unique);
+
+    bool multiEntry = false;
+    options.get("multiEntry", multiEntry);
+
+    return createIndex(context, name, keyPath, unique, multiEntry, ec);
+}
+
+PassRefPtr<IDBIndex> IDBObjectStore::createIndex(ScriptExecutionContext* context, const String& name, const IDBKeyPath& keyPath, bool unique, bool multiEntry, ExceptionCode& ec)
+{
     IDB_TRACE("IDBObjectStore::createIndex");
     if (!m_transaction->isVersionChange() || m_deleted) {
         ec = IDBDatabaseException::InvalidStateError;
@@ -375,12 +386,6 @@ PassRefPtr<IDBIndex> IDBObjectStore::createIndex(ScriptExecutionContext* context
         return 0;
     }
 
-    bool unique = false;
-    options.get("unique", unique);
-
-    bool multiEntry = false;
-    options.get("multiEntry", multiEntry);
-
     if (keyPath.type() == IDBKeyPath::ArrayType && multiEntry) {
         ec = IDBDatabaseException::InvalidAccessError;
         return 0;
index dcb9981..fcb4379 100644 (file)
@@ -84,7 +84,8 @@ public:
 
     PassRefPtr<IDBIndex> createIndex(ScriptExecutionContext* context, const String& name, const String& keyPath, const Dictionary& options, ExceptionCode& ec) { return createIndex(context, name, IDBKeyPath(keyPath), options, ec); }
     PassRefPtr<IDBIndex> createIndex(ScriptExecutionContext* context, const String& name, const Vector<String>& keyPath, const Dictionary& options, ExceptionCode& ec) { return createIndex(context, name, IDBKeyPath(keyPath), options, ec); }
-    PassRefPtr<IDBIndex> createIndex(ScriptExecutionContext*, const String&, const IDBKeyPath&, const Dictionary&, ExceptionCode&);
+    PassRefPtr<IDBIndex> createIndex(ScriptExecutionContext*, const String& name, const IDBKeyPath&, const Dictionary&, ExceptionCode&);
+    PassRefPtr<IDBIndex> createIndex(ScriptExecutionContext*, const String& name, const IDBKeyPath&, bool unique, bool multiEntry, ExceptionCode&);
 
     PassRefPtr<IDBIndex> index(const String& name, ExceptionCode&);
     void deleteIndex(const String& name, ExceptionCode&);
index 39642c2..3d28e9c 100644 (file)
@@ -52,9 +52,9 @@
     [CallWith=ScriptExecutionContext] IDBRequest openCursor(in IDBKey key, in [Optional] DOMString direction)
         raises (DOMException);
 
-    [CallWith=ScriptExecutionContext] IDBIndex createIndex(in DOMString name, in sequence<DOMString> keyPath, in [Optional] Dictionary options)
+    [CallWith=ScriptExecutionContext, JSCustom] IDBIndex createIndex(in DOMString name, in sequence<DOMString> keyPath, in [Optional] Dictionary options)
         raises (DOMException);
-    [CallWith=ScriptExecutionContext] IDBIndex createIndex(in DOMString name, in DOMString keyPath, in [Optional] Dictionary options)
+    [CallWith=ScriptExecutionContext, JSCustom] IDBIndex createIndex(in DOMString name, in DOMString keyPath, in [Optional] Dictionary options)
         raises (DOMException);
     IDBIndex index(in DOMString name)
         raises (DOMException);
index 89ff8cb..d304fb6 100644 (file)
@@ -202,7 +202,9 @@ if (ENABLE_INDEXED_DATABASE)
     list(APPEND WebCore_SOURCES
         bindings/js/IDBBindingUtilities.cpp
         bindings/js/JSIDBAnyCustom.cpp
+        bindings/js/JSIDBDatabaseCustom.cpp
         bindings/js/JSIDBKeyCustom.cpp
+        bindings/js/JSIDBObjectStoreCustom.cpp
     )
 endif ()
 
index ef819fc..34c77bf 100644 (file)
@@ -118,6 +118,16 @@ PassRefPtr<IDBKey> createIDBKeyFromValue(ExecState* exec, JSValue value)
     return IDBKey::createInvalid();
 }
 
+IDBKeyPath idbKeyPathFromValue(ExecState* exec, JSValue keyPathValue)
+{
+    IDBKeyPath keyPath;
+    if (isJSArray(keyPathValue))
+        keyPath = IDBKeyPath(toNativeArray<String>(exec, keyPathValue));
+    else
+        keyPath = IDBKeyPath(keyPathValue.toString(exec)->value(exec));
+    return keyPath;
+}
+
 static JSValue getNthValueOnKeyPath(ExecState* exec, JSValue rootValue, const Vector<String>& keyPathElements, size_t index)
 {
     JSValue currentValue(rootValue);
index 6e8288e..9978cc5 100644 (file)
@@ -40,6 +40,8 @@ class IDBKeyPath;
 
 PassRefPtr<IDBKey> createIDBKeyFromValue(JSC::ExecState*, JSC::JSValue);
 
+IDBKeyPath idbKeyPathFromValue(JSC::ExecState*, JSC::JSValue);
+
 bool injectIDBKeyIntoScriptValue(DOMRequestState*, PassRefPtr<IDBKey>, ScriptValue&, const IDBKeyPath&);
 PassRefPtr<IDBKey> createIDBKeyFromScriptValueAndKeyPath(DOMRequestState*, const ScriptValue&, const IDBKeyPath&);
 bool canInjectIDBKeyIntoScriptValue(DOMRequestState*, const ScriptValue&, const IDBKeyPath&);
diff --git a/Source/WebCore/bindings/js/JSIDBDatabaseCustom.cpp b/Source/WebCore/bindings/js/JSIDBDatabaseCustom.cpp
new file mode 100644 (file)
index 0000000..64dc34f
--- /dev/null
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2012 Michael Pruett <michael@68k.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#if ENABLE(INDEXED_DATABASE)
+
+#include "JSIDBDatabase.h"
+
+#include "IDBBindingUtilities.h"
+#include "IDBDatabase.h"
+#include "IDBKeyPath.h"
+#include "IDBObjectStore.h"
+#include "JSIDBObjectStore.h"
+#include <runtime/Error.h>
+#include <runtime/JSString.h>
+
+using namespace JSC;
+
+namespace WebCore {
+
+JSValue JSIDBDatabase::createObjectStore(ExecState* exec)
+{
+    if (exec->argumentCount() < 1)
+        return throwError(exec, createNotEnoughArgumentsError(exec));
+
+    String name = exec->argument(0).toString(exec)->value(exec);
+    if (exec->hadException())
+        return jsUndefined();
+
+    JSValue optionsValue = exec->argument(1);
+    if (!optionsValue.isUndefinedOrNull() && !optionsValue.isObject())
+        return throwTypeError(exec, "Not an object.");
+
+    IDBKeyPath keyPath;
+    bool autoIncrement = false;
+    if (!optionsValue.isUndefinedOrNull()) {
+        JSValue keyPathValue = optionsValue.get(exec, Identifier(exec, "keyPath"));
+        if (exec->hadException())
+            return jsUndefined();
+
+        if (!keyPathValue.isUndefinedOrNull()) {
+            keyPath = idbKeyPathFromValue(exec, keyPathValue);
+            if (exec->hadException())
+                return jsUndefined();
+        }
+
+        autoIncrement = optionsValue.get(exec, Identifier(exec, "autoIncrement")).toBoolean(exec);
+        if (exec->hadException())
+            return jsUndefined();
+    }
+
+    ExceptionCode ec = 0;
+    JSValue result = toJS(exec, globalObject(), impl()->createObjectStore(name, keyPath, autoIncrement, ec).get());
+    setDOMException(exec, ec);
+    return result;
+}
+
+}
+
+#endif
diff --git a/Source/WebCore/bindings/js/JSIDBObjectStoreCustom.cpp b/Source/WebCore/bindings/js/JSIDBObjectStoreCustom.cpp
new file mode 100644 (file)
index 0000000..54c9d60
--- /dev/null
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2012 Michael Pruett <michael@68k.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#if ENABLE(INDEXED_DATABASE)
+
+#include "JSIDBObjectStore.h"
+
+#include "IDBBindingUtilities.h"
+#include "IDBKeyPath.h"
+#include "IDBObjectStore.h"
+#include "JSIDBIndex.h"
+#include <runtime/Error.h>
+#include <runtime/JSString.h>
+
+using namespace JSC;
+
+namespace WebCore {
+
+JSValue JSIDBObjectStore::createIndex(ExecState* exec)
+{
+    ScriptExecutionContext* context = jsCast<JSDOMGlobalObject*>(exec->lexicalGlobalObject())->scriptExecutionContext();
+    if (!context)
+        return throwError(exec, createReferenceError(exec, "IDBObjectStore script execution context is unavailable"));
+
+    if (exec->argumentCount() < 2)
+        return throwError(exec, createNotEnoughArgumentsError(exec));
+
+    String name = exec->argument(0).toString(exec)->value(exec);
+    if (exec->hadException())
+        return jsUndefined();
+
+    IDBKeyPath keyPath = idbKeyPathFromValue(exec, exec->argument(1));
+    if (exec->hadException())
+        return jsUndefined();
+
+    JSValue optionsValue = exec->argument(2);
+    if (!optionsValue.isUndefinedOrNull() && !optionsValue.isObject())
+        return throwTypeError(exec, "Not an object.");
+
+    bool unique = false;
+    bool multiEntry = false;
+    if (!optionsValue.isUndefinedOrNull()) {
+        unique = optionsValue.get(exec, Identifier(exec, "unique")).toBoolean(exec);
+        if (exec->hadException())
+            return jsUndefined();
+
+        multiEntry = optionsValue.get(exec, Identifier(exec, "multiEntry")).toBoolean(exec);
+        if (exec->hadException())
+            return jsUndefined();
+    }
+
+    ExceptionCode ec = 0;
+    JSValue result = toJS(exec, globalObject(), impl()->createIndex(context, name, keyPath, unique, multiEntry, ec).get());
+    setDOMException(exec, ec);
+    return result;
+}
+
+}
+
+#endif