Line data Source code
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/. */
6 :
7 : #include "nsJSUtils.h"
8 : #include "nsMemory.h"
9 : #include "nsString.h"
10 :
11 : #include "jsapi.h"
12 :
13 : #include "mozStoragePrivateHelpers.h"
14 : #include "mozStorageStatementParams.h"
15 : #include "mozIStorageStatement.h"
16 :
17 : namespace mozilla {
18 : namespace storage {
19 :
20 : ////////////////////////////////////////////////////////////////////////////////
21 : //// StatementParams
22 :
23 0 : StatementParams::StatementParams(mozIStorageStatement *aStatement) :
24 : mStatement(aStatement),
25 0 : mParamCount(0)
26 : {
27 0 : NS_ASSERTION(mStatement != nullptr, "mStatement is null");
28 0 : (void)mStatement->GetParameterCount(&mParamCount);
29 0 : }
30 :
31 0 : NS_IMPL_ISUPPORTS(
32 : StatementParams,
33 : mozIStorageStatementParams,
34 : nsIXPCScriptable
35 : )
36 :
37 : ////////////////////////////////////////////////////////////////////////////////
38 : //// nsIXPCScriptable
39 :
40 : #define XPC_MAP_CLASSNAME StatementParams
41 : #define XPC_MAP_QUOTED_CLASSNAME "StatementParams"
42 : #define XPC_MAP_FLAGS (XPC_SCRIPTABLE_WANT_SETPROPERTY | \
43 : XPC_SCRIPTABLE_WANT_NEWENUMERATE | \
44 : XPC_SCRIPTABLE_WANT_RESOLVE | \
45 : XPC_SCRIPTABLE_ALLOW_PROP_MODS_DURING_RESOLVE)
46 : #include "xpc_map_end.h"
47 :
48 : NS_IMETHODIMP
49 0 : StatementParams::SetProperty(nsIXPConnectWrappedNative *aWrapper,
50 : JSContext *aCtx,
51 : JSObject *aScopeObj,
52 : jsid aId,
53 : JS::Value *_vp,
54 : bool *_retval)
55 : {
56 0 : NS_ENSURE_TRUE(mStatement, NS_ERROR_NOT_INITIALIZED);
57 :
58 0 : if (JSID_IS_INT(aId)) {
59 0 : int idx = JSID_TO_INT(aId);
60 :
61 0 : nsCOMPtr<nsIVariant> variant(convertJSValToVariant(aCtx, *_vp));
62 0 : NS_ENSURE_TRUE(variant, NS_ERROR_UNEXPECTED);
63 0 : nsresult rv = mStatement->BindByIndex(idx, variant);
64 0 : NS_ENSURE_SUCCESS(rv, rv);
65 : }
66 0 : else if (JSID_IS_STRING(aId)) {
67 0 : JSString *str = JSID_TO_STRING(aId);
68 0 : nsAutoJSString autoStr;
69 0 : if (!autoStr.init(aCtx, str)) {
70 0 : return NS_ERROR_FAILURE;
71 : }
72 :
73 0 : NS_ConvertUTF16toUTF8 name(autoStr);
74 :
75 : // check to see if there's a parameter with this name
76 0 : nsCOMPtr<nsIVariant> variant(convertJSValToVariant(aCtx, *_vp));
77 0 : NS_ENSURE_TRUE(variant, NS_ERROR_UNEXPECTED);
78 0 : nsresult rv = mStatement->BindByName(name, variant);
79 0 : NS_ENSURE_SUCCESS(rv, rv);
80 : }
81 : else {
82 0 : return NS_ERROR_INVALID_ARG;
83 : }
84 :
85 0 : *_retval = true;
86 0 : return NS_OK;
87 : }
88 :
89 : NS_IMETHODIMP
90 0 : StatementParams::NewEnumerate(nsIXPConnectWrappedNative *aWrapper,
91 : JSContext *aCtx,
92 : JSObject *aScopeObj,
93 : JS::AutoIdVector &aProperties,
94 : bool *_retval)
95 : {
96 0 : NS_ENSURE_TRUE(mStatement, NS_ERROR_NOT_INITIALIZED);
97 0 : JS::RootedObject scope(aCtx, aScopeObj);
98 :
99 0 : if (!aProperties.reserve(mParamCount)) {
100 0 : *_retval = false;
101 0 : return NS_OK;
102 : }
103 :
104 0 : for (uint32_t i = 0; i < mParamCount; i++) {
105 : // Get the name of our parameter.
106 0 : nsAutoCString name;
107 0 : nsresult rv = mStatement->GetParameterName(i, name);
108 0 : NS_ENSURE_SUCCESS(rv, rv);
109 :
110 : // But drop the first character, which is going to be a ':'.
111 0 : JS::RootedString jsname(aCtx, ::JS_NewStringCopyN(aCtx, &(name.get()[1]),
112 0 : name.Length() - 1));
113 0 : NS_ENSURE_TRUE(jsname, NS_ERROR_OUT_OF_MEMORY);
114 :
115 : // Set our name.
116 0 : JS::Rooted<jsid> id(aCtx);
117 0 : if (!::JS_StringToId(aCtx, jsname, &id)) {
118 0 : *_retval = false;
119 0 : return NS_OK;
120 : }
121 :
122 0 : aProperties.infallibleAppend(id);
123 : }
124 :
125 0 : return NS_OK;
126 : }
127 :
128 : NS_IMETHODIMP
129 0 : StatementParams::Resolve(nsIXPConnectWrappedNative *aWrapper,
130 : JSContext *aCtx,
131 : JSObject *aScopeObj,
132 : jsid aId,
133 : bool *resolvedp,
134 : bool *_retval)
135 : {
136 0 : NS_ENSURE_TRUE(mStatement, NS_ERROR_NOT_INITIALIZED);
137 : // We do not throw at any point after this unless our index is out of range
138 : // because we want to allow the prototype chain to be checked for the
139 : // property.
140 :
141 0 : JS::RootedObject scope(aCtx, aScopeObj);
142 0 : JS::RootedId id(aCtx, aId);
143 0 : bool resolved = false;
144 0 : bool ok = true;
145 0 : if (JSID_IS_INT(id)) {
146 0 : uint32_t idx = JSID_TO_INT(id);
147 :
148 : // Ensure that our index is within range. We do not care about the
149 : // prototype chain being checked here.
150 0 : if (idx >= mParamCount)
151 0 : return NS_ERROR_INVALID_ARG;
152 :
153 0 : ok = ::JS_DefineElement(aCtx, scope, idx, JS::UndefinedHandleValue,
154 0 : JSPROP_ENUMERATE | JSPROP_RESOLVING);
155 0 : resolved = true;
156 : }
157 0 : else if (JSID_IS_STRING(id)) {
158 0 : JSString *str = JSID_TO_STRING(id);
159 0 : nsAutoJSString autoStr;
160 0 : if (!autoStr.init(aCtx, str)) {
161 0 : return NS_ERROR_FAILURE;
162 : }
163 :
164 : // Check to see if there's a parameter with this name, and if not, let
165 : // the rest of the prototype chain be checked.
166 0 : NS_ConvertUTF16toUTF8 name(autoStr);
167 : uint32_t idx;
168 0 : nsresult rv = mStatement->GetParameterIndex(name, &idx);
169 0 : if (NS_SUCCEEDED(rv)) {
170 0 : ok = ::JS_DefinePropertyById(aCtx, scope, id, JS::UndefinedHandleValue,
171 0 : JSPROP_ENUMERATE | JSPROP_RESOLVING);
172 0 : resolved = true;
173 : }
174 : }
175 :
176 0 : *_retval = ok;
177 0 : *resolvedp = resolved && ok;
178 0 : return NS_OK;
179 : }
180 :
181 : } // namespace storage
182 : } // namespace mozilla
|