Bug 1865172 Part 1 - Always store a page name value when a breakpoint is first found...
[gecko.git] / storage / mozStorageStatementJSHelper.cpp
blobc891e955a2589462f7786f98c715a33b7eb6de19
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 "nsString.h"
12 #include "nsServiceManagerUtils.h"
14 #include "mozStorageStatementJSHelper.h"
16 #include "mozStorageStatementRow.h"
17 #include "mozStorageStatementParams.h"
19 #include "jsapi.h"
20 #include "js/PropertyAndElement.h" // JS_DefineFunction, JS_DefineProperty, JS_DefinePropertyById
21 #include "js/Value.h"
23 #include "xpc_make_class.h"
25 namespace mozilla {
26 namespace storage {
28 ////////////////////////////////////////////////////////////////////////////////
29 //// Global Functions
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");
39 return false;
42 JS::Rooted<JSObject*> obj(aCtx, &args.thisv().toObject());
43 nsresult rv =
44 xpc->GetWrappedNativeOfJSObject(aCtx, obj, getter_AddRefs(wrapper));
45 if (NS_FAILED(rv)) {
46 ::JS_ReportErrorASCII(
47 aCtx, "mozIStorageStatement::step() could not obtain native statement");
48 return false;
51 #ifdef DEBUG
53 nsCOMPtr<mozIStorageStatement> isStatement(
54 do_QueryInterface(wrapper->Native()));
55 NS_ASSERTION(isStatement, "How is this not a statement?!");
57 #endif
59 Statement* stmt = static_cast<Statement*>(
60 static_cast<mozIStorageStatement*>(wrapper->Native()));
62 bool hasMore = false;
63 rv = stmt->ExecuteStep(&hasMore);
64 if (NS_SUCCEEDED(rv) && !hasMore) {
65 args.rval().setBoolean(false);
66 (void)stmt->Reset();
67 return true;
70 if (NS_FAILED(rv)) {
71 ::JS_ReportErrorASCII(aCtx,
72 "mozIStorageStatement::step() returned an error");
73 return false;
76 args.rval().setBoolean(hasMore);
77 return true;
80 ////////////////////////////////////////////////////////////////////////////////
81 //// StatementJSHelper
83 nsresult StatementJSHelper::getRow(Statement* aStatement, JSContext* aCtx,
84 JSObject* aScopeObj, JS::Value* _row) {
85 MOZ_ASSERT(NS_IsMainThread());
87 #ifdef DEBUG
88 int32_t state;
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!");
92 #endif
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);
118 if (!obj) {
119 return NS_ERROR_UNEXPECTED;
122 _row->setObject(*obj);
123 return NS_OK;
126 nsresult StatementJSHelper::getParams(Statement* aStatement, JSContext* aCtx,
127 JSObject* aScopeObj, JS::Value* _params) {
128 MOZ_ASSERT(NS_IsMainThread());
130 #ifdef DEBUG
131 int32_t state;
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!");
135 #endif
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);
162 if (!obj) {
163 return NS_ERROR_UNEXPECTED;
166 _params->setObject(*obj);
167 return NS_OK;
170 NS_IMETHODIMP_(MozExternalRefCountType) StatementJSHelper::AddRef() {
171 return 2;
173 NS_IMETHODIMP_(MozExternalRefCountType) StatementJSHelper::Release() {
174 return 1;
176 NS_INTERFACE_MAP_BEGIN(StatementJSHelper)
177 NS_INTERFACE_MAP_ENTRY(nsIXPCScriptable)
178 NS_INTERFACE_MAP_ENTRY(nsISupports)
179 NS_INTERFACE_MAP_END
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"
190 NS_IMETHODIMP
191 StatementJSHelper::Resolve(nsIXPConnectWrappedNative* aWrapper, JSContext* aCtx,
192 JSObject* aScopeObj, jsid aId, bool* aResolvedp,
193 bool* _retval) {
194 if (!aId.isString()) return NS_OK;
196 JS::Rooted<JSObject*> scope(aCtx, aScopeObj);
197 JS::Rooted<jsid> id(aCtx, aId);
199 #ifdef DEBUG
201 nsCOMPtr<mozIStorageStatement> isStatement(
202 do_QueryInterface(aWrapper->Native()));
203 NS_ASSERTION(isStatement, "How is this not a statement?!");
205 #endif
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;
214 *aResolvedp = true;
215 return NS_OK;
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);
224 *aResolvedp = true;
225 return NS_OK;
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);
232 *aResolvedp = true;
233 return NS_OK;
236 return NS_OK;
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