Bug 1713895 - Enable browser tests in Linux + ASAN + Fission configuration r=robwu
[gecko.git] / storage / mozStorageStatementJSHelper.cpp
blobe02721087a2704558b71d8673e4c2c87a699eb55
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"
11 #include "nsMemory.h"
12 #include "nsString.h"
13 #include "nsServiceManagerUtils.h"
15 #include "mozStorageStatementJSHelper.h"
17 #include "mozStorageStatementRow.h"
18 #include "mozStorageStatementParams.h"
20 #include "jsapi.h"
21 #include "js/PropertyAndElement.h" // JS_DefineFunction, JS_DefineProperty, JS_DefinePropertyById
22 #include "js/Value.h"
24 #include "xpc_make_class.h"
26 namespace mozilla {
27 namespace storage {
29 ////////////////////////////////////////////////////////////////////////////////
30 //// Global Functions
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");
40 return false;
43 JS::RootedObject obj(aCtx, &args.thisv().toObject());
44 nsresult rv =
45 xpc->GetWrappedNativeOfJSObject(aCtx, obj, getter_AddRefs(wrapper));
46 if (NS_FAILED(rv)) {
47 ::JS_ReportErrorASCII(
48 aCtx, "mozIStorageStatement::step() could not obtain native statement");
49 return false;
52 #ifdef DEBUG
54 nsCOMPtr<mozIStorageStatement> isStatement(
55 do_QueryInterface(wrapper->Native()));
56 NS_ASSERTION(isStatement, "How is this not a statement?!");
58 #endif
60 Statement* stmt = static_cast<Statement*>(
61 static_cast<mozIStorageStatement*>(wrapper->Native()));
63 bool hasMore = false;
64 rv = stmt->ExecuteStep(&hasMore);
65 if (NS_SUCCEEDED(rv) && !hasMore) {
66 args.rval().setBoolean(false);
67 (void)stmt->Reset();
68 return true;
71 if (NS_FAILED(rv)) {
72 ::JS_ReportErrorASCII(aCtx,
73 "mozIStorageStatement::step() returned an error");
74 return false;
77 args.rval().setBoolean(hasMore);
78 return true;
81 ////////////////////////////////////////////////////////////////////////////////
82 //// StatementJSHelper
84 nsresult StatementJSHelper::getRow(Statement* aStatement, JSContext* aCtx,
85 JSObject* aScopeObj, JS::Value* _row) {
86 MOZ_ASSERT(NS_IsMainThread());
88 #ifdef DEBUG
89 int32_t state;
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!");
93 #endif
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);
119 if (!obj) {
120 return NS_ERROR_UNEXPECTED;
123 _row->setObject(*obj);
124 return NS_OK;
127 nsresult StatementJSHelper::getParams(Statement* aStatement, JSContext* aCtx,
128 JSObject* aScopeObj, JS::Value* _params) {
129 MOZ_ASSERT(NS_IsMainThread());
131 #ifdef DEBUG
132 int32_t state;
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!");
136 #endif
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);
163 if (!obj) {
164 return NS_ERROR_UNEXPECTED;
167 _params->setObject(*obj);
168 return NS_OK;
171 NS_IMETHODIMP_(MozExternalRefCountType) StatementJSHelper::AddRef() {
172 return 2;
174 NS_IMETHODIMP_(MozExternalRefCountType) StatementJSHelper::Release() {
175 return 1;
177 NS_INTERFACE_MAP_BEGIN(StatementJSHelper)
178 NS_INTERFACE_MAP_ENTRY(nsIXPCScriptable)
179 NS_INTERFACE_MAP_ENTRY(nsISupports)
180 NS_INTERFACE_MAP_END
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"
191 NS_IMETHODIMP
192 StatementJSHelper::Resolve(nsIXPConnectWrappedNative* aWrapper, JSContext* aCtx,
193 JSObject* aScopeObj, jsid aId, bool* aResolvedp,
194 bool* _retval) {
195 if (!JSID_IS_STRING(aId)) return NS_OK;
197 JS::Rooted<JSObject*> scope(aCtx, aScopeObj);
198 JS::Rooted<jsid> id(aCtx, aId);
200 #ifdef DEBUG
202 nsCOMPtr<mozIStorageStatement> isStatement(
203 do_QueryInterface(aWrapper->Native()));
204 NS_ASSERTION(isStatement, "How is this not a statement?!");
206 #endif
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;
215 *aResolvedp = true;
216 return NS_OK;
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);
225 *aResolvedp = true;
226 return NS_OK;
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);
233 *aResolvedp = true;
234 return NS_OK;
237 return NS_OK;
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