1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/dom/bindings/ToJSValue.h Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,291 @@ 1.4 +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-*/ 1.5 +/* vim: set ts=2 sw=2 et tw=79: */ 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 file, 1.8 + * You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.9 + 1.10 +#ifndef mozilla_dom_ToJSValue_h 1.11 +#define mozilla_dom_ToJSValue_h 1.12 + 1.13 +#include "mozilla/TypeTraits.h" 1.14 +#include "mozilla/Assertions.h" 1.15 +#include "mozilla/dom/BindingUtils.h" 1.16 +#include "mozilla/dom/TypedArray.h" 1.17 +#include "jsapi.h" 1.18 +#include "nsISupports.h" 1.19 +#include "nsTArray.h" 1.20 +#include "nsWrapperCache.h" 1.21 + 1.22 +namespace mozilla { 1.23 +namespace dom { 1.24 + 1.25 +// If ToJSValue returns false, it must set an exception on the 1.26 +// JSContext. 1.27 + 1.28 +// Accept strings. 1.29 +bool 1.30 +ToJSValue(JSContext* aCx, 1.31 + const nsAString& aArgument, 1.32 + JS::MutableHandle<JS::Value> aValue); 1.33 + 1.34 +// Accept booleans. 1.35 +inline bool 1.36 +ToJSValue(JSContext* aCx, 1.37 + bool aArgument, 1.38 + JS::MutableHandle<JS::Value> aValue) 1.39 +{ 1.40 + // Make sure we're called in a compartment 1.41 + MOZ_ASSERT(JS::CurrentGlobalOrNull(aCx)); 1.42 + 1.43 + aValue.setBoolean(aArgument); 1.44 + return true; 1.45 +} 1.46 + 1.47 +// Accept integer types 1.48 +inline bool 1.49 +ToJSValue(JSContext* aCx, 1.50 + int32_t aArgument, 1.51 + JS::MutableHandle<JS::Value> aValue) 1.52 +{ 1.53 + // Make sure we're called in a compartment 1.54 + MOZ_ASSERT(JS::CurrentGlobalOrNull(aCx)); 1.55 + 1.56 + aValue.setInt32(aArgument); 1.57 + return true; 1.58 +} 1.59 + 1.60 +// The uint32_t version is disabled for now because on the super-old b2g 1.61 +// compiler nsresult and uint32_t are the same type. If someone needs this at 1.62 +// some point we'll need to figure out how to make it work (e.g. by switching to 1.63 +// traits structs and using the trick IPC's ParamTraits uses, where a traits 1.64 +// struct templated on the type inherits from a base traits struct of some sort, 1.65 +// templated on the same type, or something). Maybe b2g will update to a modern 1.66 +// compiler before that happens.... 1.67 +#if 0 1.68 +inline bool 1.69 +ToJSValue(JSContext* aCx, 1.70 + uint32_t aArgument, 1.71 + JS::MutableHandle<JS::Value> aValue) 1.72 +{ 1.73 + // Make sure we're called in a compartment 1.74 + MOZ_ASSERT(JS::CurrentGlobalOrNull(aCx)); 1.75 + 1.76 + aValue.setNumber(aArgument); 1.77 + return true; 1.78 +} 1.79 +#endif 1.80 + 1.81 +inline bool 1.82 +ToJSValue(JSContext* aCx, 1.83 + int64_t aArgument, 1.84 + JS::MutableHandle<JS::Value> aValue) 1.85 +{ 1.86 + // Make sure we're called in a compartment 1.87 + MOZ_ASSERT(JS::CurrentGlobalOrNull(aCx)); 1.88 + 1.89 + aValue.setNumber(double(aArgument)); 1.90 + return true; 1.91 +} 1.92 + 1.93 +inline bool 1.94 +ToJSValue(JSContext* aCx, 1.95 + uint64_t aArgument, 1.96 + JS::MutableHandle<JS::Value> aValue) 1.97 +{ 1.98 + // Make sure we're called in a compartment 1.99 + MOZ_ASSERT(JS::CurrentGlobalOrNull(aCx)); 1.100 + 1.101 + aValue.setNumber(double(aArgument)); 1.102 + return true; 1.103 +} 1.104 + 1.105 +// accept floating point types 1.106 +inline bool 1.107 +ToJSValue(JSContext* aCx, 1.108 + float aArgument, 1.109 + JS::MutableHandle<JS::Value> aValue) 1.110 +{ 1.111 + // Make sure we're called in a compartment 1.112 + MOZ_ASSERT(JS::CurrentGlobalOrNull(aCx)); 1.113 + 1.114 + aValue.setNumber(aArgument); 1.115 + return true; 1.116 +} 1.117 + 1.118 +inline bool 1.119 +ToJSValue(JSContext* aCx, 1.120 + double aArgument, 1.121 + JS::MutableHandle<JS::Value> aValue) 1.122 +{ 1.123 + // Make sure we're called in a compartment 1.124 + MOZ_ASSERT(JS::CurrentGlobalOrNull(aCx)); 1.125 + 1.126 + aValue.setNumber(aArgument); 1.127 + return true; 1.128 +} 1.129 + 1.130 +// Accept objects that inherit from nsWrapperCache and nsISupports (e.g. most 1.131 +// DOM objects). 1.132 +template <class T> 1.133 +typename EnableIf<IsBaseOf<nsWrapperCache, T>::value && 1.134 + IsBaseOf<nsISupports, T>::value, bool>::Type 1.135 +ToJSValue(JSContext* aCx, 1.136 + T& aArgument, 1.137 + JS::MutableHandle<JS::Value> aValue) 1.138 +{ 1.139 + // Make sure we're called in a compartment 1.140 + MOZ_ASSERT(JS::CurrentGlobalOrNull(aCx)); 1.141 + // Make sure non-webidl objects don't sneak in here 1.142 + MOZ_ASSERT(aArgument.IsDOMBinding()); 1.143 + 1.144 + return WrapNewBindingObject(aCx, aArgument, aValue); 1.145 +} 1.146 + 1.147 +// Accept typed arrays built from appropriate nsTArray values 1.148 +template<typename T> 1.149 +typename EnableIf<IsBaseOf<AllTypedArraysBase, T>::value, bool>::Type 1.150 +ToJSValue(JSContext* aCx, 1.151 + const TypedArrayCreator<T>& aArgument, 1.152 + JS::MutableHandle<JS::Value> aValue) 1.153 +{ 1.154 + // Make sure we're called in a compartment 1.155 + MOZ_ASSERT(JS::CurrentGlobalOrNull(aCx)); 1.156 + 1.157 + JSObject* obj = aArgument.Create(aCx); 1.158 + if (!obj) { 1.159 + return false; 1.160 + } 1.161 + aValue.setObject(*obj); 1.162 + return true; 1.163 +} 1.164 + 1.165 +// We don't want to include nsContentUtils here, so use a helper 1.166 +// function for the nsISupports case. 1.167 +namespace tojsvalue_detail { 1.168 +bool 1.169 +ISupportsToJSValue(JSContext* aCx, 1.170 + nsISupports* aArgument, 1.171 + JS::MutableHandle<JS::Value> aValue); 1.172 +} // namespace tojsvalue_detail 1.173 + 1.174 +// Accept objects that inherit from nsISupports but not nsWrapperCache (e.g. 1.175 +// nsIDOMFile). 1.176 +template <class T> 1.177 +typename EnableIf<!IsBaseOf<nsWrapperCache, T>::value && 1.178 + IsBaseOf<nsISupports, T>::value, bool>::Type 1.179 +ToJSValue(JSContext* aCx, 1.180 + T& aArgument, 1.181 + JS::MutableHandle<JS::Value> aValue) 1.182 +{ 1.183 + // Make sure we're called in a compartment 1.184 + MOZ_ASSERT(JS::CurrentGlobalOrNull(aCx)); 1.185 + 1.186 + return tojsvalue_detail::ISupportsToJSValue(aCx, &aArgument, aValue); 1.187 +} 1.188 + 1.189 +// Accept nsRefPtr/nsCOMPtr 1.190 +template <typename T> 1.191 +bool 1.192 +ToJSValue(JSContext* aCx, 1.193 + const nsCOMPtr<T>& aArgument, 1.194 + JS::MutableHandle<JS::Value> aValue) 1.195 +{ 1.196 + return ToJSValue(aCx, *aArgument.get(), aValue); 1.197 +} 1.198 + 1.199 +template <typename T> 1.200 +bool 1.201 +ToJSValue(JSContext* aCx, 1.202 + const nsRefPtr<T>& aArgument, 1.203 + JS::MutableHandle<JS::Value> aValue) 1.204 +{ 1.205 + return ToJSValue(aCx, *aArgument.get(), aValue); 1.206 +} 1.207 + 1.208 +// Accept WebIDL dictionaries 1.209 +template <class T> 1.210 +typename EnableIf<IsBaseOf<DictionaryBase, T>::value, bool>::Type 1.211 +ToJSValue(JSContext* aCx, 1.212 + const T& aArgument, 1.213 + JS::MutableHandle<JS::Value> aValue) 1.214 +{ 1.215 + return aArgument.ToObject(aCx, aValue); 1.216 +} 1.217 + 1.218 +// Accept existing JS values (which may not be same-compartment with us 1.219 +inline bool 1.220 +ToJSValue(JSContext* aCx, JS::Handle<JS::Value> aArgument, 1.221 + JS::MutableHandle<JS::Value> aValue) 1.222 +{ 1.223 + aValue.set(aArgument); 1.224 + return MaybeWrapValue(aCx, aValue); 1.225 +} 1.226 + 1.227 +// Accept nsresult, for use in rejections, and create an XPCOM 1.228 +// exception object representing that nsresult. 1.229 +bool 1.230 +ToJSValue(JSContext* aCx, 1.231 + nsresult aArgument, 1.232 + JS::MutableHandle<JS::Value> aValue); 1.233 + 1.234 +// Accept arrays of other things we accept 1.235 +template <typename T> 1.236 +bool 1.237 +ToJSValue(JSContext* aCx, 1.238 + T* aArguments, 1.239 + size_t aLength, 1.240 + JS::MutableHandle<JS::Value> aValue) 1.241 +{ 1.242 + // Make sure we're called in a compartment 1.243 + MOZ_ASSERT(JS::CurrentGlobalOrNull(aCx)); 1.244 + 1.245 + JS::AutoValueVector v(aCx); 1.246 + if (!v.resize(aLength)) { 1.247 + return false; 1.248 + } 1.249 + for (size_t i = 0; i < aLength; ++i) { 1.250 + if (!ToJSValue(aCx, aArguments[i], v.handleAt(i))) { 1.251 + return false; 1.252 + } 1.253 + } 1.254 + JSObject* arrayObj = JS_NewArrayObject(aCx, v); 1.255 + if (!arrayObj) { 1.256 + return false; 1.257 + } 1.258 + aValue.setObject(*arrayObj); 1.259 + return true; 1.260 +} 1.261 + 1.262 +template <typename T> 1.263 +bool 1.264 +ToJSValue(JSContext* aCx, 1.265 + const nsTArray<T>& aArgument, 1.266 + JS::MutableHandle<JS::Value> aValue) 1.267 +{ 1.268 + return ToJSValue(aCx, aArgument.Elements(), 1.269 + aArgument.Length(), aValue); 1.270 +} 1.271 + 1.272 +template <typename T> 1.273 +bool 1.274 +ToJSValue(JSContext* aCx, 1.275 + const FallibleTArray<T>& aArgument, 1.276 + JS::MutableHandle<JS::Value> aValue) 1.277 +{ 1.278 + return ToJSValue(aCx, aArgument.Elements(), 1.279 + aArgument.Length(), aValue); 1.280 +} 1.281 + 1.282 +template <typename T, int N> 1.283 +bool 1.284 +ToJSValue(JSContext* aCx, 1.285 + const T(&aArgument)[N], 1.286 + JS::MutableHandle<JS::Value> aValue) 1.287 +{ 1.288 + return ToJSValue(aCx, aArgument, N, aValue); 1.289 +} 1.290 + 1.291 +} // namespace dom 1.292 +} // namespace mozilla 1.293 + 1.294 +#endif /* mozilla_dom_ToJSValue_h */