1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/storage/src/mozStorageStatementParams.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,208 @@ 1.4 +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- 1.5 + * vim: sw=2 ts=2 et lcs=trail\:.,tab\:>~ : 1.6 + * This Source Code Form is subject to the terms of the Mozilla Public 1.7 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.8 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.9 + 1.10 +#include "nsMemory.h" 1.11 +#include "nsString.h" 1.12 + 1.13 +#include "jsapi.h" 1.14 + 1.15 +#include "mozStoragePrivateHelpers.h" 1.16 +#include "mozStorageStatementParams.h" 1.17 +#include "mozIStorageStatement.h" 1.18 + 1.19 +namespace mozilla { 1.20 +namespace storage { 1.21 + 1.22 +//////////////////////////////////////////////////////////////////////////////// 1.23 +//// StatementParams 1.24 + 1.25 +StatementParams::StatementParams(mozIStorageStatement *aStatement) : 1.26 + mStatement(aStatement) 1.27 +{ 1.28 + NS_ASSERTION(mStatement != nullptr, "mStatement is null"); 1.29 + (void)mStatement->GetParameterCount(&mParamCount); 1.30 +} 1.31 + 1.32 +NS_IMPL_ISUPPORTS( 1.33 + StatementParams, 1.34 + mozIStorageStatementParams, 1.35 + nsIXPCScriptable 1.36 +) 1.37 + 1.38 +//////////////////////////////////////////////////////////////////////////////// 1.39 +//// nsIXPCScriptable 1.40 + 1.41 +#define XPC_MAP_CLASSNAME StatementParams 1.42 +#define XPC_MAP_QUOTED_CLASSNAME "StatementParams" 1.43 +#define XPC_MAP_WANT_SETPROPERTY 1.44 +#define XPC_MAP_WANT_NEWENUMERATE 1.45 +#define XPC_MAP_WANT_NEWRESOLVE 1.46 +#define XPC_MAP_FLAGS nsIXPCScriptable::ALLOW_PROP_MODS_DURING_RESOLVE 1.47 +#include "xpc_map_end.h" 1.48 + 1.49 +NS_IMETHODIMP 1.50 +StatementParams::SetProperty(nsIXPConnectWrappedNative *aWrapper, 1.51 + JSContext *aCtx, 1.52 + JSObject *aScopeObj, 1.53 + jsid aId, 1.54 + JS::Value *_vp, 1.55 + bool *_retval) 1.56 +{ 1.57 + NS_ENSURE_TRUE(mStatement, NS_ERROR_NOT_INITIALIZED); 1.58 + 1.59 + if (JSID_IS_INT(aId)) { 1.60 + int idx = JSID_TO_INT(aId); 1.61 + 1.62 + nsCOMPtr<nsIVariant> variant(convertJSValToVariant(aCtx, *_vp)); 1.63 + NS_ENSURE_TRUE(variant, NS_ERROR_UNEXPECTED); 1.64 + nsresult rv = mStatement->BindByIndex(idx, variant); 1.65 + NS_ENSURE_SUCCESS(rv, rv); 1.66 + } 1.67 + else if (JSID_IS_STRING(aId)) { 1.68 + JSString *str = JSID_TO_STRING(aId); 1.69 + size_t length; 1.70 + const jschar *chars = JS_GetStringCharsAndLength(aCtx, str, &length); 1.71 + NS_ENSURE_TRUE(chars, NS_ERROR_UNEXPECTED); 1.72 + NS_ConvertUTF16toUTF8 name(chars, length); 1.73 + 1.74 + // check to see if there's a parameter with this name 1.75 + nsCOMPtr<nsIVariant> variant(convertJSValToVariant(aCtx, *_vp)); 1.76 + NS_ENSURE_TRUE(variant, NS_ERROR_UNEXPECTED); 1.77 + nsresult rv = mStatement->BindByName(name, variant); 1.78 + NS_ENSURE_SUCCESS(rv, rv); 1.79 + } 1.80 + else { 1.81 + return NS_ERROR_INVALID_ARG; 1.82 + } 1.83 + 1.84 + *_retval = true; 1.85 + return NS_OK; 1.86 +} 1.87 + 1.88 +NS_IMETHODIMP 1.89 +StatementParams::NewEnumerate(nsIXPConnectWrappedNative *aWrapper, 1.90 + JSContext *aCtx, 1.91 + JSObject *aScopeObj, 1.92 + uint32_t aEnumOp, 1.93 + jsval *_statep, 1.94 + jsid *_idp, 1.95 + bool *_retval) 1.96 +{ 1.97 + NS_ENSURE_TRUE(mStatement, NS_ERROR_NOT_INITIALIZED); 1.98 + 1.99 + switch (aEnumOp) { 1.100 + case JSENUMERATE_INIT: 1.101 + case JSENUMERATE_INIT_ALL: 1.102 + { 1.103 + // Start our internal index at zero. 1.104 + *_statep = JSVAL_ZERO; 1.105 + 1.106 + // And set our length, if needed. 1.107 + if (_idp) 1.108 + *_idp = INT_TO_JSID(mParamCount); 1.109 + 1.110 + break; 1.111 + } 1.112 + case JSENUMERATE_NEXT: 1.113 + { 1.114 + NS_ASSERTION(*_statep != JSVAL_NULL, "Internal state is null!"); 1.115 + 1.116 + // Make sure we are in range first. 1.117 + uint32_t index = static_cast<uint32_t>(JSVAL_TO_INT(*_statep)); 1.118 + if (index >= mParamCount) { 1.119 + *_statep = JSVAL_NULL; 1.120 + return NS_OK; 1.121 + } 1.122 + 1.123 + // Get the name of our parameter. 1.124 + nsAutoCString name; 1.125 + nsresult rv = mStatement->GetParameterName(index, name); 1.126 + NS_ENSURE_SUCCESS(rv, rv); 1.127 + 1.128 + // But drop the first character, which is going to be a ':'. 1.129 + JS::RootedString jsname(aCtx, ::JS_NewStringCopyN(aCtx, &(name.get()[1]), 1.130 + name.Length() - 1)); 1.131 + NS_ENSURE_TRUE(jsname, NS_ERROR_OUT_OF_MEMORY); 1.132 + 1.133 + // Set our name. 1.134 + JS::Rooted<jsid> id(aCtx); 1.135 + if (!::JS_StringToId(aCtx, jsname, &id)) { 1.136 + *_retval = false; 1.137 + return NS_OK; 1.138 + } 1.139 + *_idp = id; 1.140 + 1.141 + // And increment our index. 1.142 + *_statep = INT_TO_JSVAL(++index); 1.143 + 1.144 + break; 1.145 + } 1.146 + case JSENUMERATE_DESTROY: 1.147 + { 1.148 + // Clear our state. 1.149 + *_statep = JSVAL_NULL; 1.150 + 1.151 + break; 1.152 + } 1.153 + } 1.154 + 1.155 + return NS_OK; 1.156 +} 1.157 + 1.158 +NS_IMETHODIMP 1.159 +StatementParams::NewResolve(nsIXPConnectWrappedNative *aWrapper, 1.160 + JSContext *aCtx, 1.161 + JSObject *aScopeObj, 1.162 + jsid aId, 1.163 + JSObject **_objp, 1.164 + bool *_retval) 1.165 +{ 1.166 + NS_ENSURE_TRUE(mStatement, NS_ERROR_NOT_INITIALIZED); 1.167 + // We do not throw at any point after this unless our index is out of range 1.168 + // because we want to allow the prototype chain to be checked for the 1.169 + // property. 1.170 + 1.171 + JS::RootedObject scope(aCtx, aScopeObj); 1.172 + JS::RootedId id(aCtx, aId); 1.173 + bool resolved = false; 1.174 + bool ok = true; 1.175 + if (JSID_IS_INT(id)) { 1.176 + uint32_t idx = JSID_TO_INT(id); 1.177 + 1.178 + // Ensure that our index is within range. We do not care about the 1.179 + // prototype chain being checked here. 1.180 + if (idx >= mParamCount) 1.181 + return NS_ERROR_INVALID_ARG; 1.182 + 1.183 + ok = ::JS_DefineElement(aCtx, scope, idx, JSVAL_VOID, nullptr, 1.184 + nullptr, JSPROP_ENUMERATE); 1.185 + resolved = true; 1.186 + } 1.187 + else if (JSID_IS_STRING(id)) { 1.188 + JSString *str = JSID_TO_STRING(id); 1.189 + size_t nameLength; 1.190 + const jschar *nameChars = JS_GetStringCharsAndLength(aCtx, str, &nameLength); 1.191 + NS_ENSURE_TRUE(nameChars, NS_ERROR_UNEXPECTED); 1.192 + 1.193 + // Check to see if there's a parameter with this name, and if not, let 1.194 + // the rest of the prototype chain be checked. 1.195 + NS_ConvertUTF16toUTF8 name(nameChars, nameLength); 1.196 + uint32_t idx; 1.197 + nsresult rv = mStatement->GetParameterIndex(name, &idx); 1.198 + if (NS_SUCCEEDED(rv)) { 1.199 + ok = ::JS_DefinePropertyById(aCtx, scope, id, JSVAL_VOID, nullptr, 1.200 + nullptr, JSPROP_ENUMERATE); 1.201 + resolved = true; 1.202 + } 1.203 + } 1.204 + 1.205 + *_retval = ok; 1.206 + *_objp = resolved && ok ? scope.get() : nullptr; 1.207 + return NS_OK; 1.208 +} 1.209 + 1.210 +} // namespace storage 1.211 +} // namespace mozilla