Bug 452897 - Automatically provide the wrapper for JavaScript
authorShawn Wilsher <sdwilsh@shawnwilsher.com>
Fri, 12 Sep 2008 17:30:41 -0400
changeset 19194 37298927e98bc94bb2d427128e92f8ae7fd6a419
parent 19193 66f60fcbdfad2e6015a906169cc592a8811c8ff8
child 19195 df52c99e42ad7f25ae9a47e8642ec8b70f7686fe
push id1
push userroot
push dateTue, 26 Apr 2011 22:38:44 +0000
treeherdermozilla-beta@bfdb6e623a36 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs452897
milestone1.9.1b1pre
Bug 452897 - Automatically provide the wrapper for JavaScript This changeset adds a language helper to mozStorageStatement so it gets the attributes and methods that mozIStorageStatementWrapper has. We can now mark the wrapper as depreciated. r=vlad r=mrbkap
storage/public/mozIStorageStatement.idl
storage/src/Makefile.in
storage/src/mozStorageStatement.cpp
storage/src/mozStorageStatement.h
storage/src/mozStorageStatementJSHelper.cpp
storage/src/mozStorageStatementJSHelper.h
storage/src/mozStorageStatementRow.cpp
storage/src/mozStorageStatementRow.h
storage/src/mozStorageStatementWrapper.cpp
storage/src/mozStorageStatementWrapper.h
storage/test/unit/test_statement_wrapper_automatically.js
--- a/storage/public/mozIStorageStatement.idl
+++ b/storage/public/mozIStorageStatement.idl
@@ -1,10 +1,10 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
- * vim: sw=2 ts=2 sts=2 expandtab 
+ * vim: sw=2 ts=2 sts=2 expandtab
  * ***** BEGIN LICENSE BLOCK *****
  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
  *
  * The contents of this file are subject to the Mozilla Public License Version
  * 1.1 (the "License"); you may not use this file except in compliance with
  * the License. You may obtain a copy of the License at
  * http://www.mozilla.org/MPL/
  *
@@ -148,16 +148,40 @@ interface mozIStorageStatement : mozISto
    * @returns a boolean indicating whether there are more rows or not;
    * row data may be accessed using mozIStorageValueArray methods on
    * the statement.
    *
    */
   boolean executeStep();
 
   /**
+   * Execute a query, using any currently-bound parameters.  Reset is called
+   * when no more data is returned.  This method is only available to JavaScript
+   * consumers.
+   *
+   * @returns a boolean indicating whether there are more rows or not.
+   *
+   * boolean step();
+   */
+
+  /**
+   * Obtains the current list of named parameters, which are settable.  This
+   * property is only available to JavaScript consumers.
+   *
+   * readonly attribute mozIStorageStatementParams params;
+   */
+
+  /**
+   * Obtains the current row, with access to all the data members by name.  This
+   * property is only available to JavaScript consumers.
+   *
+   * readonly attribute mozIStorageStatementRow row;
+   */
+
+  /**
    * Execute a query asynchronously using any currently bound parameters.  This
    * statement can be reused immediately, and reset does not need to be called.
    *
    * @param aCallback [optional]
    *        The callback object that will be notified of progress, errors, and
    *        completion.
    * @returns an object that can be used to cancel the statements execution.
    */
--- a/storage/src/Makefile.in
+++ b/storage/src/Makefile.in
@@ -70,16 +70,17 @@ CPPSRCS = \
   mozStorageStatementRow.cpp \
   mozStorageValueArray.cpp \
   mozStorageUnicodeFunctions.cpp \
   mozStorageRow.cpp \
   mozStorageResultSet.cpp \
   mozStorageError.cpp \
   mozStorageBackground.cpp \
   mozStorageEvents.cpp \
+  mozStorageStatementJSHelper.cpp \
   $(NULL)
 
 LOCAL_INCLUDES = \
 	$(SQLITE_CFLAGS)
 
 # This is the default value.  If we ever change it when compiling sqlite, we
 # will need to change it here as well.
 DEFINES += -DSQLITE_MAX_LIKE_PATTERN_LENGTH=50000
--- a/storage/src/mozStorageStatement.cpp
+++ b/storage/src/mozStorageStatement.cpp
@@ -40,29 +40,113 @@
  * ***** END LICENSE BLOCK ***** */
 
 #include <stdio.h>
 
 #include "nsAutoLock.h"
 #include "nsError.h"
 #include "nsISimpleEnumerator.h"
 #include "nsMemory.h"
+#include "nsIClassInfoImpl.h"
+#include "nsIProgrammingLanguage.h"
 
 #include "mozStorageConnection.h"
 #include "mozStorageStatement.h"
+#include "mozStorageStatementJSHelper.h"
 #include "mozStorageValueArray.h"
 #include "mozStorage.h"
 #include "mozStorageEvents.h"
 
 #include "prlog.h"
 
 #ifdef PR_LOGGING
 extern PRLogModuleInfo* gStorageLog;
 #endif
 
+////////////////////////////////////////////////////////////////////////////////
+//// nsIClassInfo
+
+NS_IMPL_CI_INTERFACE_GETTER2(
+    mozStorageStatement
+,   mozIStorageStatement
+,   mozIStorageValueArray
+)
+
+class mozStorageStatementClassInfo : public nsIClassInfo
+{
+public:
+    NS_DECL_ISUPPORTS
+
+    NS_IMETHODIMP
+    GetInterfaces(PRUint32 *_count, nsIID ***_array)
+    {
+        return NS_CI_INTERFACE_GETTER_NAME(mozStorageStatement)(_count, _array);
+    }
+
+    NS_IMETHODIMP
+    GetHelperForLanguage(PRUint32 aLanguage, nsISupports **_helper)
+    {
+        if (aLanguage == nsIProgrammingLanguage::JAVASCRIPT) {
+            static mozStorageStatementJSHelper sJSHelper;
+            *_helper = &sJSHelper;
+            return NS_OK;
+        }
+
+        *_helper = nsnull;
+        return NS_OK;
+    }
+
+    NS_IMETHODIMP
+    GetContractID(char **_contractID)
+    {
+        *_contractID = nsnull;
+        return NS_OK;
+    }
+
+    NS_IMETHODIMP
+    GetClassDescription(char **_desc)
+    {
+        *_desc = nsnull;
+        return NS_OK;
+    }
+
+    NS_IMETHODIMP
+    GetClassID(nsCID **_id)
+    {
+        *_id = nsnull;
+        return NS_OK;
+    }
+
+    NS_IMETHODIMP
+    GetImplementationLanguage(PRUint32 *_language)
+    {
+        *_language = nsIProgrammingLanguage::CPLUSPLUS;
+        return NS_OK;
+    }
+
+    NS_IMETHODIMP
+    GetFlags(PRUint32 *_flags)
+    {
+        *_flags = nsnull;
+        return NS_OK;
+    }
+
+    NS_IMETHODIMP
+    GetClassIDNoAlloc(nsCID *_cid)
+    {
+        return NS_ERROR_NOT_AVAILABLE;
+    }
+};
+
+NS_IMETHODIMP_(nsrefcnt) mozStorageStatementClassInfo::AddRef() { return 2; }
+NS_IMETHODIMP_(nsrefcnt) mozStorageStatementClassInfo::Release() { return 1; }
+NS_IMPL_QUERY_INTERFACE1(mozStorageStatementClassInfo, nsIClassInfo);
+
+static mozStorageStatementClassInfo sStatementClassInfo;
+
 /**
  ** mozStorageStatementRowEnumerator
  **/
 class mozStorageStatementRowEnumerator : public nsISimpleEnumerator {
 public:
     // this expects a statement that has NOT had step called on it yet
     mozStorageStatementRowEnumerator (sqlite3_stmt *aDBStatement);
 
@@ -82,21 +166,27 @@ protected:
     void DoRealStep();
 };
 
 
 /**
  ** mozStorageStatement
  **/
 
-NS_IMPL_THREADSAFE_ISUPPORTS2(
-    mozStorageStatement
-,   mozIStorageStatement
-,   mozIStorageValueArray
-)
+NS_IMPL_THREADSAFE_ADDREF(mozStorageStatement)
+NS_IMPL_THREADSAFE_RELEASE(mozStorageStatement)
+
+NS_INTERFACE_MAP_BEGIN(mozStorageStatement)
+    NS_INTERFACE_MAP_ENTRY(mozIStorageStatement)
+    NS_INTERFACE_MAP_ENTRY(mozIStorageValueArray)
+    if (aIID.Equals(NS_GET_IID(nsIClassInfo))) {
+        foundInterface = static_cast<nsIClassInfo *>(&sStatementClassInfo);
+    } else
+    NS_INTERFACE_MAP_ENTRY(nsISupports)
+NS_INTERFACE_MAP_END
 
 mozStorageStatement::mozStorageStatement()
     : mDBConnection (nsnull), mDBStatement(nsnull), mColumnNames(nsnull), mExecuting(PR_FALSE)
 {
 }
 
 nsresult
 mozStorageStatement::Initialize(mozStorageConnection *aDBConnection,
@@ -171,16 +261,19 @@ mozStorageStatement::Initialize(mozStora
     return NS_OK;
 }
 
 mozStorageStatement::~mozStorageStatement()
 {
     (void)Finalize();
 }
 
+////////////////////////////////////////////////////////////////////////////////
+//// mozIStorageStatement
+
 /* mozIStorageStatement clone (); */
 NS_IMETHODIMP
 mozStorageStatement::Clone(mozIStorageStatement **_retval)
 {
     mozStorageStatement *mss = new mozStorageStatement();
     if (!mss)
       return NS_ERROR_OUT_OF_MEMORY;
 
--- a/storage/src/mozStorageStatement.h
+++ b/storage/src/mozStorageStatement.h
@@ -44,16 +44,18 @@
 
 #include "nsVoidArray.h"
 
 #include "mozIStorageStatement.h"
 
 #include <sqlite3.h>
 
 class mozStorageConnection;
+class nsIXPConnectJSObjectHolder;
+class mozStorageStatementJSHelper;
 
 class mozStorageStatement : public mozIStorageStatement
 {
 public:
     mozStorageStatement();
 
     // interfaces
     NS_DECL_ISUPPORTS
@@ -84,11 +86,19 @@ private:
 protected:
     nsRefPtr<mozStorageConnection> mDBConnection;
     sqlite3_stmt *mDBStatement;
     PRUint32 mParamCount;
     PRUint32 mResultColumnCount;
     nsCStringArray mColumnNames;
     PRBool mExecuting;
 
+    /**
+     * The following two members are only used with the JS helper.  They cache
+     * the row and params objects.
+     */
+    nsCOMPtr<nsIXPConnectJSObjectHolder> mStatementParamsHolder;
+    nsCOMPtr<nsIXPConnectJSObjectHolder> mStatementRowHolder;
+
+    friend class mozStorageStatementJSHelper;
 };
 
 #endif /* _MOZSTORAGESTATEMENT_H_ */
new file mode 100644
--- /dev/null
+++ b/storage/src/mozStorageStatementJSHelper.cpp
@@ -0,0 +1,232 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * vim: sw=2 ts=2 sts=2 expandtab
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozStorage code.
+ *
+ * The Initial Developer of the Original Code is
+ * Mozilla Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2008
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Shawn Wilsher <me@shawnwilsher.com> (Original Author)
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsIXPConnect.h"
+#include "mozStorageStatement.h"
+
+#include "nsMemory.h"
+#include "nsString.h"
+#include "nsServiceManagerUtils.h"
+
+#include "mozStorageStatementJSHelper.h"
+
+#include "mozStorageStatementRow.h"
+#include "mozStorageStatementParams.h"
+
+#include "jsapi.h"
+
+static nsIXPConnect *sXPConnect = nsnull;
+static inline
+nsIXPConnect *
+XPConnect()
+{
+  if (!sXPConnect) {
+    (void)CallGetService(nsIXPConnect::GetCID(), &sXPConnect);
+    NS_ASSERTION(sXPConnect, "Could not get XPConnect!");
+  }
+  return sXPConnect;
+}
+
+static
+JSBool
+stepFunc(JSContext *aCtx, PRUint32, jsval *_vp)
+{
+  nsCOMPtr<nsIXPConnectWrappedNative> wrapper;
+  nsresult rv = XPConnect()->GetWrappedNativeOfJSObject(
+    aCtx, JS_THIS_OBJECT(aCtx, _vp), getter_AddRefs(wrapper)
+  );
+  if (NS_FAILED(rv)) {
+    JS_ReportError(aCtx, "mozIStorageStatement::step() could not obtain native statement");
+    return JS_FALSE;
+  }
+
+  mozStorageStatement *stmt =
+    static_cast<mozStorageStatement *>(wrapper->Native());
+
+#ifdef DEBUG
+  {
+    nsCOMPtr<mozIStorageStatement> isStatement(do_QueryInterface(stmt));
+    NS_ASSERTION(isStatement, "How is this not a statement?!");
+  }
+#endif
+
+  PRBool hasMore = PR_FALSE;
+  rv = stmt->ExecuteStep(&hasMore);
+  if (NS_SUCCEEDED(rv) && !hasMore) {
+    *_vp = JSVAL_FALSE;
+    (void)stmt->Reset();
+    return JS_TRUE;
+  }
+
+  if (NS_FAILED(rv)) {
+    JS_ReportError(aCtx, "mozIStorageStatement::step() returned an error");
+    return JS_FALSE;
+  }
+
+  *_vp = BOOLEAN_TO_JSVAL(hasMore);
+  return JS_TRUE;
+}
+
+nsresult
+mozStorageStatementJSHelper::getRow(mozStorageStatement *aStatement,
+                                    JSContext *aCtx, JSObject *aScopeObj,
+                                    jsval *_row)
+{
+  nsresult rv;
+
+  PRInt32 state;
+  (void)aStatement->GetState(&state);
+  if (state != mozIStorageStatement::MOZ_STORAGE_STATEMENT_EXECUTING)
+    return NS_ERROR_UNEXPECTED;
+
+  if (!aStatement->mStatementRowHolder) {
+    nsCOMPtr<mozIStorageStatementRow> row =
+      new mozStorageStatementRow(aStatement);
+    NS_ENSURE_TRUE(row, NS_ERROR_OUT_OF_MEMORY);
+
+    rv = XPConnect()->WrapNative(aCtx, ::JS_GetGlobalForObject(aCtx, aScopeObj),
+                                 row, NS_GET_IID(mozIStorageStatementRow),
+                                 getter_AddRefs(aStatement->mStatementRowHolder));
+    NS_ENSURE_SUCCESS(rv, rv);
+  }
+
+  JSObject *obj = nsnull;
+  rv = aStatement->mStatementRowHolder->GetJSObject(&obj);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  *_row = OBJECT_TO_JSVAL(obj);
+  return NS_OK;
+}
+
+nsresult
+mozStorageStatementJSHelper::getParams(mozStorageStatement *aStatement,
+                                       JSContext *aCtx, JSObject *aScopeObj,
+                                       jsval *_params)
+{
+  nsresult rv;
+
+  PRInt32 state;
+  (void)aStatement->GetState(&state);
+  if (state != mozIStorageStatement::MOZ_STORAGE_STATEMENT_READY)
+    return NS_ERROR_UNEXPECTED;
+
+  if (!aStatement->mStatementParamsHolder) {
+    nsCOMPtr<mozIStorageStatementParams> params =
+      new mozStorageStatementParams(aStatement);
+    NS_ENSURE_TRUE(params, NS_ERROR_OUT_OF_MEMORY);
+
+    rv = XPConnect()->WrapNative(aCtx, ::JS_GetGlobalForObject(aCtx, aScopeObj),
+                                 params, NS_GET_IID(mozIStorageStatementParams),
+                                 getter_AddRefs(aStatement->mStatementParamsHolder));
+    NS_ENSURE_SUCCESS(rv, rv);
+  }
+
+  JSObject *obj = nsnull;
+  rv = aStatement->mStatementParamsHolder->GetJSObject(&obj);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  *_params = OBJECT_TO_JSVAL(obj);
+  return NS_OK;
+}
+
+NS_IMETHODIMP_(nsrefcnt) mozStorageStatementJSHelper::AddRef() { return 2; }
+NS_IMETHODIMP_(nsrefcnt) mozStorageStatementJSHelper::Release() { return 1; }
+NS_INTERFACE_MAP_BEGIN(mozStorageStatementJSHelper)
+  NS_INTERFACE_MAP_ENTRY(nsIXPCScriptable)
+  NS_INTERFACE_MAP_ENTRY(nsISupports)
+NS_INTERFACE_MAP_END
+
+////////////////////////////////////////////////////////////////////////////////
+//// nsIXPCScriptable
+
+#define XPC_MAP_CLASSNAME mozStorageStatementJSHelper
+#define XPC_MAP_QUOTED_CLASSNAME "mozStorageStatementJSHelper"
+#define XPC_MAP_WANT_GETPROPERTY
+#define XPC_MAP_WANT_NEWRESOLVE
+#define XPC_MAP_FLAGS nsIXPCScriptable::ALLOW_PROP_MODS_DURING_RESOLVE
+#include "xpc_map_end.h"
+
+NS_IMETHODIMP
+mozStorageStatementJSHelper::GetProperty(nsIXPConnectWrappedNative *aWrapper,
+                                         JSContext *aCtx, JSObject *aScopeObj,
+                                         jsval aId, jsval *_result,
+                                         PRBool *_retval)
+{
+  if (!JSVAL_IS_STRING(aId))
+    return NS_OK;
+
+  mozStorageStatement *stmt =
+    static_cast<mozStorageStatement *>(aWrapper->Native());
+
+#ifdef DEBUG
+  {
+    nsCOMPtr<mozIStorageStatement> isStatement(do_QueryInterface(stmt));
+    NS_ASSERTION(isStatement, "How is this not a statement?!");
+  }
+#endif
+
+  const char *propName = JS_GetStringBytes(JSVAL_TO_STRING(aId));
+  if (strcmp(propName, "row") == 0)
+    return getRow(stmt, aCtx, aScopeObj, _result);
+
+  if (strcmp(propName, "params") == 0)
+    return getParams(stmt, aCtx, aScopeObj, _result);
+
+  return NS_OK;
+}
+
+
+NS_IMETHODIMP
+mozStorageStatementJSHelper::NewResolve(nsIXPConnectWrappedNative *aWrapper,
+                                        JSContext *aCtx, JSObject *aScopeObj,
+                                        jsval aId, PRUint32 aFlags,
+                                        JSObject **_objp, PRBool *_retval)
+{
+  if (!JSVAL_IS_STRING(aId))
+    return NS_OK;
+
+  const char *name = JS_GetStringBytes(JSVAL_TO_STRING(aId));
+  if (strcmp(name, "step") == 0) {
+    *_retval = JS_DefineFunction(aCtx, aScopeObj, "step", (JSNative)stepFunc, 0,
+                                 JSFUN_FAST_NATIVE) != nsnull;
+    *_objp = aScopeObj;
+    return NS_OK;
+  }
+  return NS_OK;
+}
new file mode 100644
--- /dev/null
+++ b/storage/src/mozStorageStatementJSHelper.h
@@ -0,0 +1,58 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * vim: sw=2 ts=2 sts=2 expandtab
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozStorage code.
+ *
+ * The Initial Developer of the Original Code is
+ * Mozilla Corporation
+ * Portions created by the Initial Developer are Copyright (C) 2008
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *  Shawn Wilsher <me@shawnwilsher.com> (Original Author)
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef __MOZSTORAGESTATEMENTJSHELPER_H__
+#define __MOZSTORAGESTATEMENTJSHELPER_H__
+
+#include "nsIXPCScriptable.h"
+
+class mozStorageStatement;
+
+class mozStorageStatementJSHelper : public nsIXPCScriptable
+{
+public:
+  NS_DECL_ISUPPORTS
+  NS_DECL_NSIXPCSCRIPTABLE
+
+private:
+  nsresult getRow(mozStorageStatement *, JSContext *, JSObject *, jsval *);
+  nsresult getParams(mozStorageStatement *, JSContext *, JSObject *, jsval *);
+};
+
+#endif // __MOZSTORAGESTATEMENTJSHELPER_H__
--- a/storage/src/mozStorageStatementRow.cpp
+++ b/storage/src/mozStorageStatementRow.cpp
@@ -51,22 +51,18 @@
 /*************************************************************************
  ****
  **** mozStorageStatementRow
  ****
  *************************************************************************/
 
 NS_IMPL_ISUPPORTS2(mozStorageStatementRow, mozIStorageStatementRow, nsIXPCScriptable)
 
-mozStorageStatementRow::mozStorageStatementRow(mozIStorageStatement *aStatement,
-                                               int aNumColumns,
-                                               const nsStringArray *aColumnNames)
-    : mStatement(aStatement),
-      mNumColumns(aNumColumns),
-      mColumnNames(aColumnNames)
+mozStorageStatementRow::mozStorageStatementRow(mozStorageStatement *aStatement)
+    : mStatement(aStatement)
 {
 }
 
 /*
  * nsIXPCScriptable impl
  */
 
 /* readonly attribute string className; */
@@ -92,54 +88,50 @@ mozStorageStatementRow::GetScriptableFla
 }
 
 /* PRBool getProperty (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj, in JSVal id, in JSValPtr vp); */
 NS_IMETHODIMP
 mozStorageStatementRow::GetProperty(nsIXPConnectWrappedNative *wrapper, JSContext * cx,
                          JSObject * obj, jsval id, jsval * vp, PRBool *_retval)
 {
     if (JSVAL_IS_STRING(id)) {
-        nsDependentString jsid((PRUnichar *)::JS_GetStringChars(JSVAL_TO_STRING(id)),
-                               ::JS_GetStringLength(JSVAL_TO_STRING(id)));
+        nsDependentCString jsid(::JS_GetStringBytes(JSVAL_TO_STRING(id)));
 
-        for (int i = 0; i < mNumColumns; i++) {
-            if (jsid.Equals(*(*mColumnNames)[i])) {
-                int ctype = sqlite3_column_type(NativeStatement(), i);
+        PRUint32 idx;
+        nsresult rv = mStatement->GetColumnIndex(jsid, &idx);
+        NS_ENSURE_SUCCESS(rv, rv);
+        int ctype = sqlite3_column_type(NativeStatement(), idx);
 
-                if (ctype == SQLITE_INTEGER || ctype == SQLITE_FLOAT) {
-                    double dval = sqlite3_column_double(NativeStatement(), i);
-                    if (!JS_NewNumberValue(cx, dval, vp)) {
-                        *_retval = PR_FALSE;
-                        return NS_OK;
-                    }
-                } else if (ctype == SQLITE_TEXT) {
-                    JSString *str = JS_NewUCStringCopyN(cx,
-                                                        (jschar*) sqlite3_column_text16(NativeStatement(), i),
-                                                        sqlite3_column_bytes16(NativeStatement(), i)/2);
-                    if (!str) {
-                        *_retval = PR_FALSE;
-                        return NS_OK;
-                    }
-                    *vp = STRING_TO_JSVAL(str);
-                } else if (ctype == SQLITE_BLOB) {
-                    JSString *str = JS_NewStringCopyN(cx,
-                                                      (char*) sqlite3_column_blob(NativeStatement(), i),
-                                                      sqlite3_column_bytes(NativeStatement(), i));
-                    if (!str) {
-                        *_retval = PR_FALSE;
-                        return NS_OK;
-                    }
-                } else if (ctype == SQLITE_NULL) {
-                    *vp = JSVAL_NULL;
-                } else {
-                    NS_ERROR("sqlite3_column_type returned unknown column type, what's going on?");
-                }
-
-                break;
+        if (ctype == SQLITE_INTEGER || ctype == SQLITE_FLOAT) {
+            double dval = sqlite3_column_double(NativeStatement(), idx);
+            if (!JS_NewNumberValue(cx, dval, vp)) {
+                *_retval = PR_FALSE;
+                return NS_OK;
+            }
+        } else if (ctype == SQLITE_TEXT) {
+            JSString *str = JS_NewUCStringCopyN(cx,
+                                                (jschar*) sqlite3_column_text16(NativeStatement(), idx),
+                                                sqlite3_column_bytes16(NativeStatement(), idx)/2);
+            if (!str) {
+                *_retval = PR_FALSE;
+                return NS_OK;
             }
+            *vp = STRING_TO_JSVAL(str);
+        } else if (ctype == SQLITE_BLOB) {
+            JSString *str = JS_NewStringCopyN(cx,
+                                              (char*) sqlite3_column_blob(NativeStatement(), idx),
+                                              sqlite3_column_bytes(NativeStatement(), idx));
+            if (!str) {
+                *_retval = PR_FALSE;
+                return NS_OK;
+            }
+        } else if (ctype == SQLITE_NULL) {
+            *vp = JSVAL_NULL;
+        } else {
+            NS_ERROR("sqlite3_column_type returned unknown column type, what's going on?");
         }
     }
 
     return NS_OK;
 }
 
 
 /* PRBool setProperty (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj, in JSVal id, in JSValPtr vp); */
@@ -206,31 +198,30 @@ mozStorageStatementRow::NewEnumerate(nsI
 
 /* PRBool newResolve (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj, in JSVal id, in PRUint32 flags, out JSObjectPtr objp); */
 NS_IMETHODIMP
 mozStorageStatementRow::NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext * cx,
                                    JSObject * obj, jsval id, PRUint32 flags, JSObject * *objp, PRBool *_retval)
 {
     if (JSVAL_IS_STRING(id)) {
         JSString *str = JSVAL_TO_STRING(id);
-        nsDependentString name((PRUnichar *)::JS_GetStringChars(str),
-                               ::JS_GetStringLength(str));
+        nsDependentCString name(::JS_GetStringBytes(str));
+
+        PRUint32 idx;
+        nsresult rv = mStatement->GetColumnIndex(name, &idx);
+        NS_ENSURE_SUCCESS(rv, rv);
 
-        for (int i = 0; i < mNumColumns; i++) {
-            if (name.Equals(*(*mColumnNames)[i])) {
-                *_retval = ::JS_DefineUCProperty(cx, obj, ::JS_GetStringChars(str),
-                                                 ::JS_GetStringLength(str),
-                                                 JSVAL_VOID,
-                                                 nsnull, nsnull, 0);
-                *objp = obj;
-                return *_retval ? NS_OK : NS_ERROR_FAILURE;
-            }
-        }
+        *_retval = ::JS_DefineUCProperty(cx, obj, ::JS_GetStringChars(str),
+                                         ::JS_GetStringLength(str),
+                                         JSVAL_VOID,
+                                         nsnull, nsnull, 0);
+        *objp = obj;
+        return *_retval ? NS_OK : NS_ERROR_FAILURE;
     }
-                
+
     *_retval = PR_TRUE;
     return NS_OK;
 }
 
 /* PRBool convert (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj, in PRUint32 type, in JSValPtr vp); */
 NS_IMETHODIMP
 mozStorageStatementRow::Convert(nsIXPConnectWrappedNative *wrapper, JSContext * cx,
                                 JSObject * obj, PRUint32 type, jsval * vp, PRBool *_retval)
--- a/storage/src/mozStorageStatementRow.h
+++ b/storage/src/mozStorageStatementRow.h
@@ -36,39 +36,35 @@
  *
  * ***** END LICENSE BLOCK ***** */
 
 #ifndef _MOZSTORAGESTATEMENTROW_H_
 #define _MOZSTORAGESTATEMENTROW_H_
 
 #include "mozIStorageStatementWrapper.h"
 #include "nsIXPCScriptable.h"
-#include "mozIStorageStatement.h"
+#include "mozStorageStatement.h"
 #include "nsString.h"
 #include "nsVoidArray.h"
 
 class mozStorageStatementRow : public mozIStorageStatementRow,
                                public nsIXPCScriptable
 {
 public:
-    mozStorageStatementRow(mozIStorageStatement *aStatement,
-                           int aNumColumns,
-                           const nsStringArray *aColumnNames);
+    mozStorageStatementRow(mozStorageStatement *aStatement);
 
     // nsISupports interface
     NS_DECL_ISUPPORTS
 
     // mozIStorageStatementRow interface (empty)
     NS_DECL_MOZISTORAGESTATEMENTROW
 
     // nsIXPCScriptable interface
     NS_DECL_NSIXPCSCRIPTABLE
 protected:
     sqlite3_stmt* NativeStatement() {
         return mStatement->GetNativeStatementPointer();
     }
 
-    nsCOMPtr<mozIStorageStatement> mStatement;
-    int mNumColumns;
-    const nsStringArray *mColumnNames;
+    nsRefPtr<mozStorageStatement> mStatement;
 };
 
 #endif /* _MOZSTORAGESTATEMENTROW_H_ */
--- a/storage/src/mozStorageStatementWrapper.cpp
+++ b/storage/src/mozStorageStatementWrapper.cpp
@@ -67,17 +67,17 @@ mozStorageStatementWrapper::~mozStorageS
 }
 
 NS_IMETHODIMP
 mozStorageStatementWrapper::Initialize(mozIStorageStatement *aStatement)
 {
     NS_ASSERTION(mStatement == nsnull, "mozStorageStatementWrapper is already initialized");
     NS_ENSURE_ARG_POINTER(aStatement);
 
-    mStatement = aStatement;
+    mStatement = static_cast<mozStorageStatement *>(aStatement);
 
     // fetch various things we care about
     mStatement->GetParameterCount(&mParamCount);
     mStatement->GetColumnCount(&mResultColumnCount);
 
     for (unsigned int i = 0; i < mResultColumnCount; i++) {
         const void *name = sqlite3_column_name16 (NativeStatement(), i);
         mColumnNames.AppendString(nsDependentString(static_cast<const PRUnichar*>(name)));
@@ -138,17 +138,17 @@ mozStorageStatementWrapper::GetRow(mozIS
         return NS_ERROR_FAILURE;
 
     PRInt32 state;
     mStatement->GetState(&state);
     if (state != mozIStorageStatement::MOZ_STORAGE_STATEMENT_EXECUTING)
         return NS_ERROR_FAILURE;
 
     if (!mStatementRow) {
-        mozStorageStatementRow *row = new mozStorageStatementRow(mStatement, mResultColumnCount, &mColumnNames);
+        mozStorageStatementRow *row = new mozStorageStatementRow(mStatement);
         if (!row)
             return NS_ERROR_OUT_OF_MEMORY;
         mStatementRow = row;
     }
 
     NS_ADDREF(*aRow = mStatementRow);
     return NS_OK;
 }
--- a/storage/src/mozStorageStatementWrapper.h
+++ b/storage/src/mozStorageStatementWrapper.h
@@ -34,17 +34,17 @@
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #ifndef _MOZSTORAGESTATEMENTWRAPPER_H_
 #define _MOZSTORAGESTATEMENTWRAPPER_H_
 
-#include "mozIStorageStatement.h"
+#include "mozStorageStatement.h"
 #include "mozIStorageStatementWrapper.h"
 #include "nsIXPCScriptable.h"
 
 #include "nsVoidArray.h"
 
 #include "sqlite3.h"
 
 
@@ -66,17 +66,17 @@ private:
     ~mozStorageStatementWrapper();
 
 protected:
     sqlite3_stmt* NativeStatement() {
         return mStatement->GetNativeStatementPointer();
     }
 
     // note: pointer to the concrete statement
-    nsCOMPtr<mozIStorageStatement> mStatement;
+    nsRefPtr<mozStorageStatement> mStatement;
     PRUint32 mParamCount;
     PRUint32 mResultColumnCount;
     nsStringArray mColumnNames;
 
     nsCOMPtr<mozIStorageStatementRow> mStatementRow;
     nsCOMPtr<mozIStorageStatementParams> mStatementParams;
 };
 
copy from storage/test/unit/test_storage_statement_wrapper.js
copy to storage/test/unit/test_statement_wrapper_automatically.js
--- a/storage/test/unit/test_storage_statement_wrapper.js
+++ b/storage/test/unit/test_statement_wrapper_automatically.js
@@ -38,74 +38,65 @@
 // This file tests the functions of mozIStorageStatementWrapper
 
 function setup()
 {
   getOpenedDatabase().createTable("test", "id INTEGER PRIMARY KEY, name TEXT," +
                                           "alt_name TEXT");
 }
 
-var wrapper = new Components.Constructor("@mozilla.org/storage/statement-wrapper;1",
-                                         Ci.mozIStorageStatementWrapper,
-                                         "initialize");
-
-// we want to override the default function for this file
-createStatement = function(aSQL) {
-  return new wrapper(getOpenedDatabase().createStatement(aSQL));
-}
-
 function test_binding_params()
 {
   var stmt = createStatement("INSERT INTO test (name) VALUES (:name)");
 
   const name = "foo";
   stmt.params.name = name;
   stmt.execute();
-  stmt.statement.finalize();
+  stmt.finalize();
 
   stmt = createStatement("SELECT COUNT(*) AS number FROM test");
   do_check_true(stmt.step());
   do_check_eq(1, stmt.row.number);
   stmt.reset();
-  stmt.statement.finalize();
+  stmt.finalize();
 
   stmt = createStatement("SELECT name FROM test WHERE id = 1");
   do_check_true(stmt.step());
   do_check_eq(name, stmt.row.name);
   stmt.reset();
-  stmt.statement.finalize();
+  stmt.finalize();
 }
 
 function test_binding_multiple_params()
 {
   var stmt = createStatement("INSERT INTO test (name, alt_name)" +
                              "VALUES (:name, :name)");
   const name = "me";
   stmt.params.name = name;
   stmt.execute();
-  stmt.statement.finalize();
+  stmt.finalize();
 
   stmt = createStatement("SELECT COUNT(*) AS number FROM test");
   do_check_true(stmt.step());
   do_check_eq(2, stmt.row.number);
   stmt.reset();
-  stmt.statement.finalize();
+  stmt.finalize();
 
   stmt = createStatement("SELECT name, alt_name FROM test WHERE id = 2");
   do_check_true(stmt.step());
   do_check_eq(name, stmt.row.name);
   do_check_eq(name, stmt.row.alt_name);
   stmt.reset();
-  stmt.statement.finalize();
+  stmt.finalize();
 }
 
 var tests = [test_binding_params, test_binding_multiple_params];
 
 function run_test()
 {
   setup();
 
   for (var i = 0; i < tests.length; i++)
     tests[i]();
-    
+
   cleanup();
 }