|
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 "nsMemory.h" |
|
8 #include "nsString.h" |
|
9 |
|
10 #include "mozStorageStatementRow.h" |
|
11 #include "mozStorageStatement.h" |
|
12 |
|
13 #include "jsapi.h" |
|
14 |
|
15 namespace mozilla { |
|
16 namespace storage { |
|
17 |
|
18 //////////////////////////////////////////////////////////////////////////////// |
|
19 //// StatementRow |
|
20 |
|
21 StatementRow::StatementRow(Statement *aStatement) |
|
22 : mStatement(aStatement) |
|
23 { |
|
24 } |
|
25 |
|
26 NS_IMPL_ISUPPORTS( |
|
27 StatementRow, |
|
28 mozIStorageStatementRow, |
|
29 nsIXPCScriptable |
|
30 ) |
|
31 |
|
32 //////////////////////////////////////////////////////////////////////////////// |
|
33 //// nsIXPCScriptable |
|
34 |
|
35 #define XPC_MAP_CLASSNAME StatementRow |
|
36 #define XPC_MAP_QUOTED_CLASSNAME "StatementRow" |
|
37 #define XPC_MAP_WANT_GETPROPERTY |
|
38 #define XPC_MAP_WANT_NEWRESOLVE |
|
39 #define XPC_MAP_FLAGS nsIXPCScriptable::ALLOW_PROP_MODS_DURING_RESOLVE |
|
40 #include "xpc_map_end.h" |
|
41 |
|
42 NS_IMETHODIMP |
|
43 StatementRow::GetProperty(nsIXPConnectWrappedNative *aWrapper, |
|
44 JSContext *aCtx, |
|
45 JSObject *aScopeObj, |
|
46 jsid aId, |
|
47 jsval *_vp, |
|
48 bool *_retval) |
|
49 { |
|
50 NS_ENSURE_TRUE(mStatement, NS_ERROR_NOT_INITIALIZED); |
|
51 |
|
52 JS::RootedObject scope(aCtx, aScopeObj); |
|
53 if (JSID_IS_STRING(aId)) { |
|
54 ::JSAutoByteString idBytes(aCtx, JSID_TO_STRING(aId)); |
|
55 NS_ENSURE_TRUE(!!idBytes, NS_ERROR_OUT_OF_MEMORY); |
|
56 nsDependentCString jsid(idBytes.ptr()); |
|
57 |
|
58 uint32_t idx; |
|
59 nsresult rv = mStatement->GetColumnIndex(jsid, &idx); |
|
60 NS_ENSURE_SUCCESS(rv, rv); |
|
61 int32_t type; |
|
62 rv = mStatement->GetTypeOfIndex(idx, &type); |
|
63 NS_ENSURE_SUCCESS(rv, rv); |
|
64 |
|
65 if (type == mozIStorageValueArray::VALUE_TYPE_INTEGER || |
|
66 type == mozIStorageValueArray::VALUE_TYPE_FLOAT) { |
|
67 double dval; |
|
68 rv = mStatement->GetDouble(idx, &dval); |
|
69 NS_ENSURE_SUCCESS(rv, rv); |
|
70 *_vp = ::JS_NumberValue(dval); |
|
71 } |
|
72 else if (type == mozIStorageValueArray::VALUE_TYPE_TEXT) { |
|
73 uint32_t bytes; |
|
74 const jschar *sval = reinterpret_cast<const jschar *>( |
|
75 static_cast<mozIStorageStatement *>(mStatement)-> |
|
76 AsSharedWString(idx, &bytes) |
|
77 ); |
|
78 JSString *str = ::JS_NewUCStringCopyN(aCtx, sval, bytes / 2); |
|
79 if (!str) { |
|
80 *_retval = false; |
|
81 return NS_OK; |
|
82 } |
|
83 *_vp = STRING_TO_JSVAL(str); |
|
84 } |
|
85 else if (type == mozIStorageValueArray::VALUE_TYPE_BLOB) { |
|
86 uint32_t length; |
|
87 const uint8_t *blob = static_cast<mozIStorageStatement *>(mStatement)-> |
|
88 AsSharedBlob(idx, &length); |
|
89 JSObject *obj = ::JS_NewArrayObject(aCtx, length); |
|
90 if (!obj) { |
|
91 *_retval = false; |
|
92 return NS_OK; |
|
93 } |
|
94 *_vp = OBJECT_TO_JSVAL(obj); |
|
95 |
|
96 // Copy the blob over to the JS array. |
|
97 for (uint32_t i = 0; i < length; i++) { |
|
98 if (!::JS_SetElement(aCtx, scope, i, blob[i])) { |
|
99 *_retval = false; |
|
100 return NS_OK; |
|
101 } |
|
102 } |
|
103 } |
|
104 else if (type == mozIStorageValueArray::VALUE_TYPE_NULL) { |
|
105 *_vp = JSVAL_NULL; |
|
106 } |
|
107 else { |
|
108 NS_ERROR("unknown column type returned, what's going on?"); |
|
109 } |
|
110 } |
|
111 |
|
112 return NS_OK; |
|
113 } |
|
114 |
|
115 NS_IMETHODIMP |
|
116 StatementRow::NewResolve(nsIXPConnectWrappedNative *aWrapper, |
|
117 JSContext *aCtx, |
|
118 JSObject *aScopeObj, |
|
119 jsid aId, |
|
120 JSObject **_objp, |
|
121 bool *_retval) |
|
122 { |
|
123 JS::Rooted<JSObject*> scopeObj(aCtx, aScopeObj); |
|
124 |
|
125 NS_ENSURE_TRUE(mStatement, NS_ERROR_NOT_INITIALIZED); |
|
126 // We do not throw at any point after this because we want to allow the |
|
127 // prototype chain to be checked for the property. |
|
128 |
|
129 if (JSID_IS_STRING(aId)) { |
|
130 ::JSAutoByteString idBytes(aCtx, JSID_TO_STRING(aId)); |
|
131 NS_ENSURE_TRUE(!!idBytes, NS_ERROR_OUT_OF_MEMORY); |
|
132 nsDependentCString name(idBytes.ptr()); |
|
133 |
|
134 uint32_t idx; |
|
135 nsresult rv = mStatement->GetColumnIndex(name, &idx); |
|
136 if (NS_FAILED(rv)) { |
|
137 // It's highly likely that the name doesn't exist, so let the JS engine |
|
138 // check the prototype chain and throw if that doesn't have the property |
|
139 // either. |
|
140 *_objp = nullptr; |
|
141 return NS_OK; |
|
142 } |
|
143 |
|
144 *_retval = ::JS_DefinePropertyById(aCtx, scopeObj, aId, JSVAL_VOID, |
|
145 nullptr, nullptr, 0); |
|
146 *_objp = scopeObj; |
|
147 return NS_OK; |
|
148 } |
|
149 |
|
150 return NS_OK; |
|
151 } |
|
152 |
|
153 } // namespace storage |
|
154 } // namescape mozilla |