Wed, 31 Dec 2014 13:27:57 +0100
Ignore runtime configuration files generated during quality assurance.
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 "nsMemory.h"
8 #include "nsString.h"
10 #include "jsapi.h"
12 #include "mozStoragePrivateHelpers.h"
13 #include "mozStorageStatementParams.h"
14 #include "mozIStorageStatement.h"
16 namespace mozilla {
17 namespace storage {
19 ////////////////////////////////////////////////////////////////////////////////
20 //// StatementParams
22 StatementParams::StatementParams(mozIStorageStatement *aStatement) :
23 mStatement(aStatement)
24 {
25 NS_ASSERTION(mStatement != nullptr, "mStatement is null");
26 (void)mStatement->GetParameterCount(&mParamCount);
27 }
29 NS_IMPL_ISUPPORTS(
30 StatementParams,
31 mozIStorageStatementParams,
32 nsIXPCScriptable
33 )
35 ////////////////////////////////////////////////////////////////////////////////
36 //// nsIXPCScriptable
38 #define XPC_MAP_CLASSNAME StatementParams
39 #define XPC_MAP_QUOTED_CLASSNAME "StatementParams"
40 #define XPC_MAP_WANT_SETPROPERTY
41 #define XPC_MAP_WANT_NEWENUMERATE
42 #define XPC_MAP_WANT_NEWRESOLVE
43 #define XPC_MAP_FLAGS nsIXPCScriptable::ALLOW_PROP_MODS_DURING_RESOLVE
44 #include "xpc_map_end.h"
46 NS_IMETHODIMP
47 StatementParams::SetProperty(nsIXPConnectWrappedNative *aWrapper,
48 JSContext *aCtx,
49 JSObject *aScopeObj,
50 jsid aId,
51 JS::Value *_vp,
52 bool *_retval)
53 {
54 NS_ENSURE_TRUE(mStatement, NS_ERROR_NOT_INITIALIZED);
56 if (JSID_IS_INT(aId)) {
57 int idx = JSID_TO_INT(aId);
59 nsCOMPtr<nsIVariant> variant(convertJSValToVariant(aCtx, *_vp));
60 NS_ENSURE_TRUE(variant, NS_ERROR_UNEXPECTED);
61 nsresult rv = mStatement->BindByIndex(idx, variant);
62 NS_ENSURE_SUCCESS(rv, rv);
63 }
64 else if (JSID_IS_STRING(aId)) {
65 JSString *str = JSID_TO_STRING(aId);
66 size_t length;
67 const jschar *chars = JS_GetStringCharsAndLength(aCtx, str, &length);
68 NS_ENSURE_TRUE(chars, NS_ERROR_UNEXPECTED);
69 NS_ConvertUTF16toUTF8 name(chars, length);
71 // check to see if there's a parameter with this name
72 nsCOMPtr<nsIVariant> variant(convertJSValToVariant(aCtx, *_vp));
73 NS_ENSURE_TRUE(variant, NS_ERROR_UNEXPECTED);
74 nsresult rv = mStatement->BindByName(name, variant);
75 NS_ENSURE_SUCCESS(rv, rv);
76 }
77 else {
78 return NS_ERROR_INVALID_ARG;
79 }
81 *_retval = true;
82 return NS_OK;
83 }
85 NS_IMETHODIMP
86 StatementParams::NewEnumerate(nsIXPConnectWrappedNative *aWrapper,
87 JSContext *aCtx,
88 JSObject *aScopeObj,
89 uint32_t aEnumOp,
90 jsval *_statep,
91 jsid *_idp,
92 bool *_retval)
93 {
94 NS_ENSURE_TRUE(mStatement, NS_ERROR_NOT_INITIALIZED);
96 switch (aEnumOp) {
97 case JSENUMERATE_INIT:
98 case JSENUMERATE_INIT_ALL:
99 {
100 // Start our internal index at zero.
101 *_statep = JSVAL_ZERO;
103 // And set our length, if needed.
104 if (_idp)
105 *_idp = INT_TO_JSID(mParamCount);
107 break;
108 }
109 case JSENUMERATE_NEXT:
110 {
111 NS_ASSERTION(*_statep != JSVAL_NULL, "Internal state is null!");
113 // Make sure we are in range first.
114 uint32_t index = static_cast<uint32_t>(JSVAL_TO_INT(*_statep));
115 if (index >= mParamCount) {
116 *_statep = JSVAL_NULL;
117 return NS_OK;
118 }
120 // Get the name of our parameter.
121 nsAutoCString name;
122 nsresult rv = mStatement->GetParameterName(index, name);
123 NS_ENSURE_SUCCESS(rv, rv);
125 // But drop the first character, which is going to be a ':'.
126 JS::RootedString jsname(aCtx, ::JS_NewStringCopyN(aCtx, &(name.get()[1]),
127 name.Length() - 1));
128 NS_ENSURE_TRUE(jsname, NS_ERROR_OUT_OF_MEMORY);
130 // Set our name.
131 JS::Rooted<jsid> id(aCtx);
132 if (!::JS_StringToId(aCtx, jsname, &id)) {
133 *_retval = false;
134 return NS_OK;
135 }
136 *_idp = id;
138 // And increment our index.
139 *_statep = INT_TO_JSVAL(++index);
141 break;
142 }
143 case JSENUMERATE_DESTROY:
144 {
145 // Clear our state.
146 *_statep = JSVAL_NULL;
148 break;
149 }
150 }
152 return NS_OK;
153 }
155 NS_IMETHODIMP
156 StatementParams::NewResolve(nsIXPConnectWrappedNative *aWrapper,
157 JSContext *aCtx,
158 JSObject *aScopeObj,
159 jsid aId,
160 JSObject **_objp,
161 bool *_retval)
162 {
163 NS_ENSURE_TRUE(mStatement, NS_ERROR_NOT_INITIALIZED);
164 // We do not throw at any point after this unless our index is out of range
165 // because we want to allow the prototype chain to be checked for the
166 // property.
168 JS::RootedObject scope(aCtx, aScopeObj);
169 JS::RootedId id(aCtx, aId);
170 bool resolved = false;
171 bool ok = true;
172 if (JSID_IS_INT(id)) {
173 uint32_t idx = JSID_TO_INT(id);
175 // Ensure that our index is within range. We do not care about the
176 // prototype chain being checked here.
177 if (idx >= mParamCount)
178 return NS_ERROR_INVALID_ARG;
180 ok = ::JS_DefineElement(aCtx, scope, idx, JSVAL_VOID, nullptr,
181 nullptr, JSPROP_ENUMERATE);
182 resolved = true;
183 }
184 else if (JSID_IS_STRING(id)) {
185 JSString *str = JSID_TO_STRING(id);
186 size_t nameLength;
187 const jschar *nameChars = JS_GetStringCharsAndLength(aCtx, str, &nameLength);
188 NS_ENSURE_TRUE(nameChars, NS_ERROR_UNEXPECTED);
190 // Check to see if there's a parameter with this name, and if not, let
191 // the rest of the prototype chain be checked.
192 NS_ConvertUTF16toUTF8 name(nameChars, nameLength);
193 uint32_t idx;
194 nsresult rv = mStatement->GetParameterIndex(name, &idx);
195 if (NS_SUCCEEDED(rv)) {
196 ok = ::JS_DefinePropertyById(aCtx, scope, id, JSVAL_VOID, nullptr,
197 nullptr, JSPROP_ENUMERATE);
198 resolved = true;
199 }
200 }
202 *_retval = ok;
203 *_objp = resolved && ok ? scope.get() : nullptr;
204 return NS_OK;
205 }
207 } // namespace storage
208 } // namespace mozilla