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"
13 #include "nsServiceManagerUtils.h"
15 #include "mozStorageStatementJSHelper.h"
17 #include "mozStorageStatementRow.h"
18 #include "mozStorageStatementParams.h"
21 #include "js/PropertyAndElement.h" // JS_DefineFunction, JS_DefineProperty, JS_DefinePropertyById
24 #include "xpc_make_class.h"
29 ////////////////////////////////////////////////////////////////////////////////
32 static bool stepFunc(JSContext
* aCtx
, uint32_t argc
, JS::Value
* _vp
) {
33 JS::CallArgs args
= CallArgsFromVp(argc
, _vp
);
35 nsCOMPtr
<nsIXPConnect
> xpc(nsIXPConnect::XPConnect());
36 nsCOMPtr
<nsIXPConnectWrappedNative
> wrapper
;
38 if (!args
.thisv().isObject()) {
39 ::JS_ReportErrorASCII(aCtx
, "mozIStorageStatement::step() requires object");
43 JS::RootedObject
obj(aCtx
, &args
.thisv().toObject());
45 xpc
->GetWrappedNativeOfJSObject(aCtx
, obj
, getter_AddRefs(wrapper
));
47 ::JS_ReportErrorASCII(
48 aCtx
, "mozIStorageStatement::step() could not obtain native statement");
54 nsCOMPtr
<mozIStorageStatement
> isStatement(
55 do_QueryInterface(wrapper
->Native()));
56 NS_ASSERTION(isStatement
, "How is this not a statement?!");
60 Statement
* stmt
= static_cast<Statement
*>(
61 static_cast<mozIStorageStatement
*>(wrapper
->Native()));
64 rv
= stmt
->ExecuteStep(&hasMore
);
65 if (NS_SUCCEEDED(rv
) && !hasMore
) {
66 args
.rval().setBoolean(false);
72 ::JS_ReportErrorASCII(aCtx
,
73 "mozIStorageStatement::step() returned an error");
77 args
.rval().setBoolean(hasMore
);
81 ////////////////////////////////////////////////////////////////////////////////
82 //// StatementJSHelper
84 nsresult
StatementJSHelper::getRow(Statement
* aStatement
, JSContext
* aCtx
,
85 JSObject
* aScopeObj
, JS::Value
* _row
) {
86 MOZ_ASSERT(NS_IsMainThread());
90 (void)aStatement
->GetState(&state
);
91 NS_ASSERTION(state
== mozIStorageStatement::MOZ_STORAGE_STATEMENT_EXECUTING
,
92 "Invalid state to get the row object - all calls will fail!");
95 JS::RootedObject
scope(aCtx
, aScopeObj
);
97 if (!aStatement
->mStatementRowHolder
) {
98 dom::GlobalObject
global(aCtx
, scope
);
99 if (global
.Failed()) {
100 return NS_ERROR_UNEXPECTED
;
103 nsCOMPtr
<nsPIDOMWindowInner
> window
=
104 do_QueryInterface(global
.GetAsSupports());
106 RefPtr
<StatementRow
> row(new StatementRow(window
, aStatement
));
107 NS_ENSURE_TRUE(row
, NS_ERROR_OUT_OF_MEMORY
);
109 RefPtr
<StatementRowHolder
> rowHolder
= new StatementRowHolder(row
);
110 NS_ENSURE_TRUE(rowHolder
, NS_ERROR_OUT_OF_MEMORY
);
112 aStatement
->mStatementRowHolder
=
113 new nsMainThreadPtrHolder
<StatementRowHolder
>(
114 "Statement::mStatementRowHolder", rowHolder
);
117 RefPtr
<StatementRow
> row(aStatement
->mStatementRowHolder
->Get());
118 JSObject
* obj
= row
->WrapObject(aCtx
, nullptr);
120 return NS_ERROR_UNEXPECTED
;
123 _row
->setObject(*obj
);
127 nsresult
StatementJSHelper::getParams(Statement
* aStatement
, JSContext
* aCtx
,
128 JSObject
* aScopeObj
, JS::Value
* _params
) {
129 MOZ_ASSERT(NS_IsMainThread());
133 (void)aStatement
->GetState(&state
);
134 NS_ASSERTION(state
== mozIStorageStatement::MOZ_STORAGE_STATEMENT_READY
,
135 "Invalid state to get the params object - all calls will fail!");
138 JS::RootedObject
scope(aCtx
, aScopeObj
);
140 if (!aStatement
->mStatementParamsHolder
) {
141 dom::GlobalObject
global(aCtx
, scope
);
142 if (global
.Failed()) {
143 return NS_ERROR_UNEXPECTED
;
146 nsCOMPtr
<nsPIDOMWindowInner
> window
=
147 do_QueryInterface(global
.GetAsSupports());
149 RefPtr
<StatementParams
> params(new StatementParams(window
, aStatement
));
150 NS_ENSURE_TRUE(params
, NS_ERROR_OUT_OF_MEMORY
);
152 RefPtr
<StatementParamsHolder
> paramsHolder
=
153 new StatementParamsHolder(params
);
154 NS_ENSURE_TRUE(paramsHolder
, NS_ERROR_OUT_OF_MEMORY
);
156 aStatement
->mStatementParamsHolder
=
157 new nsMainThreadPtrHolder
<StatementParamsHolder
>(
158 "Statement::mStatementParamsHolder", paramsHolder
);
161 RefPtr
<StatementParams
> params(aStatement
->mStatementParamsHolder
->Get());
162 JSObject
* obj
= params
->WrapObject(aCtx
, nullptr);
164 return NS_ERROR_UNEXPECTED
;
167 _params
->setObject(*obj
);
171 NS_IMETHODIMP_(MozExternalRefCountType
) StatementJSHelper::AddRef() {
174 NS_IMETHODIMP_(MozExternalRefCountType
) StatementJSHelper::Release() {
177 NS_INTERFACE_MAP_BEGIN(StatementJSHelper
)
178 NS_INTERFACE_MAP_ENTRY(nsIXPCScriptable
)
179 NS_INTERFACE_MAP_ENTRY(nsISupports
)
182 ////////////////////////////////////////////////////////////////////////////////
183 //// nsIXPCScriptable
185 #define XPC_MAP_CLASSNAME StatementJSHelper
186 #define XPC_MAP_QUOTED_CLASSNAME "StatementJSHelper"
187 #define XPC_MAP_FLAGS \
188 (XPC_SCRIPTABLE_WANT_RESOLVE | XPC_SCRIPTABLE_ALLOW_PROP_MODS_DURING_RESOLVE)
189 #include "xpc_map_end.h"
192 StatementJSHelper::Resolve(nsIXPConnectWrappedNative
* aWrapper
, JSContext
* aCtx
,
193 JSObject
* aScopeObj
, jsid aId
, bool* aResolvedp
,
195 if (!JSID_IS_STRING(aId
)) return NS_OK
;
197 JS::Rooted
<JSObject
*> scope(aCtx
, aScopeObj
);
198 JS::Rooted
<jsid
> id(aCtx
, aId
);
202 nsCOMPtr
<mozIStorageStatement
> isStatement(
203 do_QueryInterface(aWrapper
->Native()));
204 NS_ASSERTION(isStatement
, "How is this not a statement?!");
208 Statement
* stmt
= static_cast<Statement
*>(
209 static_cast<mozIStorageStatement
*>(aWrapper
->Native()));
211 JSLinearString
* str
= JSID_TO_LINEAR_STRING(id
);
212 if (::JS_LinearStringEqualsLiteral(str
, "step")) {
213 *_retval
= ::JS_DefineFunction(aCtx
, scope
, "step", stepFunc
, 0,
214 JSPROP_RESOLVING
) != nullptr;
219 JS::RootedValue
val(aCtx
);
221 if (::JS_LinearStringEqualsLiteral(str
, "row")) {
222 nsresult rv
= getRow(stmt
, aCtx
, scope
, val
.address());
223 NS_ENSURE_SUCCESS(rv
, rv
);
224 *_retval
= ::JS_DefinePropertyById(aCtx
, scope
, id
, val
, JSPROP_RESOLVING
);
229 if (::JS_LinearStringEqualsLiteral(str
, "params")) {
230 nsresult rv
= getParams(stmt
, aCtx
, scope
, val
.address());
231 NS_ENSURE_SUCCESS(rv
, rv
);
232 *_retval
= ::JS_DefinePropertyById(aCtx
, scope
, id
, val
, JSPROP_RESOLVING
);
240 NS_IMPL_ISUPPORTS0(StatementParamsHolder
);
242 StatementParamsHolder::~StatementParamsHolder() {
243 MOZ_ASSERT(NS_IsMainThread());
244 // We are considered dead at this point, so any wrappers for row or params
245 // need to lose their reference to the statement.
246 mParams
->mStatement
= nullptr;
249 NS_IMPL_ISUPPORTS0(StatementRowHolder
);
251 StatementRowHolder::~StatementRowHolder() {
252 MOZ_ASSERT(NS_IsMainThread());
253 // We are considered dead at this point, so any wrappers for row or params
254 // need to lose their reference to the statement.
255 mRow
->mStatement
= nullptr;
258 } // namespace storage
259 } // namespace mozilla