1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2 * vim: sw=2 ts=2 et lcs=trail\:.,tab\:>~ :
3 * This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #include "nsIXPConnect.h"
8 #include "mozStorageStatement.h"
9 #include "mozStorageService.h"
12 #include "nsServiceManagerUtils.h"
14 #include "mozStorageStatementJSHelper.h"
16 #include "mozStorageStatementRow.h"
17 #include "mozStorageStatementParams.h"
20 #include "js/PropertyAndElement.h" // JS_DefineFunction, JS_DefineProperty, JS_DefinePropertyById
23 #include "xpc_make_class.h"
28 ////////////////////////////////////////////////////////////////////////////////
31 static bool stepFunc(JSContext
* aCtx
, uint32_t argc
, JS::Value
* _vp
) {
32 JS::CallArgs args
= CallArgsFromVp(argc
, _vp
);
34 nsCOMPtr
<nsIXPConnect
> xpc(nsIXPConnect::XPConnect());
35 nsCOMPtr
<nsIXPConnectWrappedNative
> wrapper
;
37 if (!args
.thisv().isObject()) {
38 ::JS_ReportErrorASCII(aCtx
, "mozIStorageStatement::step() requires object");
42 JS::Rooted
<JSObject
*> obj(aCtx
, &args
.thisv().toObject());
44 xpc
->GetWrappedNativeOfJSObject(aCtx
, obj
, getter_AddRefs(wrapper
));
46 ::JS_ReportErrorASCII(
47 aCtx
, "mozIStorageStatement::step() could not obtain native statement");
53 nsCOMPtr
<mozIStorageStatement
> isStatement(
54 do_QueryInterface(wrapper
->Native()));
55 NS_ASSERTION(isStatement
, "How is this not a statement?!");
59 Statement
* stmt
= static_cast<Statement
*>(
60 static_cast<mozIStorageStatement
*>(wrapper
->Native()));
63 rv
= stmt
->ExecuteStep(&hasMore
);
64 if (NS_SUCCEEDED(rv
) && !hasMore
) {
65 args
.rval().setBoolean(false);
71 ::JS_ReportErrorASCII(aCtx
,
72 "mozIStorageStatement::step() returned an error");
76 args
.rval().setBoolean(hasMore
);
80 ////////////////////////////////////////////////////////////////////////////////
81 //// StatementJSHelper
83 nsresult
StatementJSHelper::getRow(Statement
* aStatement
, JSContext
* aCtx
,
84 JSObject
* aScopeObj
, JS::Value
* _row
) {
85 MOZ_ASSERT(NS_IsMainThread());
89 (void)aStatement
->GetState(&state
);
90 NS_ASSERTION(state
== mozIStorageStatement::MOZ_STORAGE_STATEMENT_EXECUTING
,
91 "Invalid state to get the row object - all calls will fail!");
94 JS::Rooted
<JSObject
*> scope(aCtx
, aScopeObj
);
96 if (!aStatement
->mStatementRowHolder
) {
97 dom::GlobalObject
global(aCtx
, scope
);
98 if (global
.Failed()) {
99 return NS_ERROR_UNEXPECTED
;
102 nsCOMPtr
<nsPIDOMWindowInner
> window
=
103 do_QueryInterface(global
.GetAsSupports());
105 RefPtr
<StatementRow
> row(new StatementRow(window
, aStatement
));
106 NS_ENSURE_TRUE(row
, NS_ERROR_OUT_OF_MEMORY
);
108 RefPtr
<StatementRowHolder
> rowHolder
= new StatementRowHolder(row
);
109 NS_ENSURE_TRUE(rowHolder
, NS_ERROR_OUT_OF_MEMORY
);
111 aStatement
->mStatementRowHolder
=
112 new nsMainThreadPtrHolder
<StatementRowHolder
>(
113 "Statement::mStatementRowHolder", rowHolder
);
116 RefPtr
<StatementRow
> row(aStatement
->mStatementRowHolder
->Get());
117 JSObject
* obj
= row
->WrapObject(aCtx
, nullptr);
119 return NS_ERROR_UNEXPECTED
;
122 _row
->setObject(*obj
);
126 nsresult
StatementJSHelper::getParams(Statement
* aStatement
, JSContext
* aCtx
,
127 JSObject
* aScopeObj
, JS::Value
* _params
) {
128 MOZ_ASSERT(NS_IsMainThread());
132 (void)aStatement
->GetState(&state
);
133 NS_ASSERTION(state
== mozIStorageStatement::MOZ_STORAGE_STATEMENT_READY
,
134 "Invalid state to get the params object - all calls will fail!");
137 JS::Rooted
<JSObject
*> scope(aCtx
, aScopeObj
);
139 if (!aStatement
->mStatementParamsHolder
) {
140 dom::GlobalObject
global(aCtx
, scope
);
141 if (global
.Failed()) {
142 return NS_ERROR_UNEXPECTED
;
145 nsCOMPtr
<nsPIDOMWindowInner
> window
=
146 do_QueryInterface(global
.GetAsSupports());
148 RefPtr
<StatementParams
> params(new StatementParams(window
, aStatement
));
149 NS_ENSURE_TRUE(params
, NS_ERROR_OUT_OF_MEMORY
);
151 RefPtr
<StatementParamsHolder
> paramsHolder
=
152 new StatementParamsHolder(params
);
153 NS_ENSURE_TRUE(paramsHolder
, NS_ERROR_OUT_OF_MEMORY
);
155 aStatement
->mStatementParamsHolder
=
156 new nsMainThreadPtrHolder
<StatementParamsHolder
>(
157 "Statement::mStatementParamsHolder", paramsHolder
);
160 RefPtr
<StatementParams
> params(aStatement
->mStatementParamsHolder
->Get());
161 JSObject
* obj
= params
->WrapObject(aCtx
, nullptr);
163 return NS_ERROR_UNEXPECTED
;
166 _params
->setObject(*obj
);
170 NS_IMETHODIMP_(MozExternalRefCountType
) StatementJSHelper::AddRef() {
173 NS_IMETHODIMP_(MozExternalRefCountType
) StatementJSHelper::Release() {
176 NS_INTERFACE_MAP_BEGIN(StatementJSHelper
)
177 NS_INTERFACE_MAP_ENTRY(nsIXPCScriptable
)
178 NS_INTERFACE_MAP_ENTRY(nsISupports
)
181 ////////////////////////////////////////////////////////////////////////////////
182 //// nsIXPCScriptable
184 #define XPC_MAP_CLASSNAME StatementJSHelper
185 #define XPC_MAP_QUOTED_CLASSNAME "StatementJSHelper"
186 #define XPC_MAP_FLAGS \
187 (XPC_SCRIPTABLE_WANT_RESOLVE | XPC_SCRIPTABLE_ALLOW_PROP_MODS_DURING_RESOLVE)
188 #include "xpc_map_end.h"
191 StatementJSHelper::Resolve(nsIXPConnectWrappedNative
* aWrapper
, JSContext
* aCtx
,
192 JSObject
* aScopeObj
, jsid aId
, bool* aResolvedp
,
194 if (!aId
.isString()) return NS_OK
;
196 JS::Rooted
<JSObject
*> scope(aCtx
, aScopeObj
);
197 JS::Rooted
<jsid
> id(aCtx
, aId
);
201 nsCOMPtr
<mozIStorageStatement
> isStatement(
202 do_QueryInterface(aWrapper
->Native()));
203 NS_ASSERTION(isStatement
, "How is this not a statement?!");
207 Statement
* stmt
= static_cast<Statement
*>(
208 static_cast<mozIStorageStatement
*>(aWrapper
->Native()));
210 JSLinearString
* str
= id
.toLinearString();
211 if (::JS_LinearStringEqualsLiteral(str
, "step")) {
212 *_retval
= ::JS_DefineFunction(aCtx
, scope
, "step", stepFunc
, 0,
213 JSPROP_RESOLVING
) != nullptr;
218 JS::Rooted
<JS::Value
> val(aCtx
);
220 if (::JS_LinearStringEqualsLiteral(str
, "row")) {
221 nsresult rv
= getRow(stmt
, aCtx
, scope
, val
.address());
222 NS_ENSURE_SUCCESS(rv
, rv
);
223 *_retval
= ::JS_DefinePropertyById(aCtx
, scope
, id
, val
, JSPROP_RESOLVING
);
228 if (::JS_LinearStringEqualsLiteral(str
, "params")) {
229 nsresult rv
= getParams(stmt
, aCtx
, scope
, val
.address());
230 NS_ENSURE_SUCCESS(rv
, rv
);
231 *_retval
= ::JS_DefinePropertyById(aCtx
, scope
, id
, val
, JSPROP_RESOLVING
);
239 NS_IMPL_ISUPPORTS0(StatementParamsHolder
);
241 StatementParamsHolder::~StatementParamsHolder() {
242 MOZ_ASSERT(NS_IsMainThread());
243 // We are considered dead at this point, so any wrappers for row or params
244 // need to lose their reference to the statement.
245 mParams
->mStatement
= nullptr;
248 NS_IMPL_ISUPPORTS0(StatementRowHolder
);
250 StatementRowHolder::~StatementRowHolder() {
251 MOZ_ASSERT(NS_IsMainThread());
252 // We are considered dead at this point, so any wrappers for row or params
253 // need to lose their reference to the statement.
254 mRow
->mStatement
= nullptr;
257 } // namespace storage
258 } // namespace mozilla