template<> bool ScriptInterface::FromJSVal<std::wstring>(JSContext* cx, JS::HandleValue v, std::wstring& out) { JSAutoRequest rq(cx); WARN_IF_NOT(v.isString() || v.isNumber(), v); // allow implicit number conversions JS::RootedString str(cx, JS::ToString(cx, v)); if (!str) FAIL("Argument must be convertible to a string"); if (JS_StringHasLatin1Chars(str)) { size_t length; JS::AutoCheckCannotGC nogc; const JS::Latin1Char* ch = JS_GetLatin1StringCharsAndLength(cx, nogc, str, &length); if (!ch) FAIL("JS_GetLatin1StringCharsAndLength failed"); out.assign(ch, ch + length); } else { size_t length; JS::AutoCheckCannotGC nogc; const char16_t* ch = JS_GetTwoByteStringCharsAndLength(cx, nogc, str, &length); if (!ch) FAIL("JS_GetTwoByteStringsCharsAndLength failed"); // out of memory out.assign(ch, ch + length); } return true; }
template<> bool ScriptInterface::FromJSVal<bool>(JSContext* cx, JS::HandleValue v, bool& out) { JSAutoRequest rq(cx); WARN_IF_NOT(v.isBoolean(), v); out = JS::ToBoolean(v); return true; }
template<> bool ScriptInterface::FromJSVal<u16>(JSContext* cx, JS::HandleValue v, u16& out) { JSAutoRequest rq(cx); WARN_IF_NOT(v.isNumber(), v); if (!JS::ToUint16(cx, v, &out)) return false; return true; }
template<> bool ScriptInterface::FromJSVal<u8>(JSContext* cx, jsval v, u8& out) { uint16 ret; WARN_IF_NOT(JSVAL_IS_NUMBER(v), v); if (!JS_ValueToUint16(cx, v, &ret)) return false; out = (u8)ret; return true; }
template<> bool ScriptInterface::FromJSVal<u32>(JSContext* cx, jsval v, u32& out) { uint32 ret; WARN_IF_NOT(JSVAL_IS_NUMBER(v), v); if (!JS_ValueToECMAUint32(cx, v, &ret)) return false; out = ret; return true; }
template<> bool ScriptInterface::FromJSVal<double>(JSContext* cx, jsval v, double& out) { jsdouble ret; WARN_IF_NOT(JSVAL_IS_NUMBER(v), v); if (!JS_ValueToNumber(cx, v, &ret)) return false; out = ret; return true; }
template<> bool ScriptInterface::FromJSVal<bool>(JSContext* cx, jsval v, bool& out) { JSBool ret; WARN_IF_NOT(JSVAL_IS_BOOLEAN(v), v); if (!JS_ValueToBoolean(cx, v, &ret)) return false; out = (ret ? true : false); return true; }
template<> bool ScriptInterface::FromJSVal<float>(JSContext* cx, JS::HandleValue v, float& out) { JSAutoRequest rq(cx); double tmp; WARN_IF_NOT(v.isNumber(), v); if (!JS::ToNumber(cx, v, &tmp)) return false; out = tmp; return true; }
template<> bool ScriptInterface::FromJSVal<std::string>(JSContext* cx, jsval v, std::string& out) { WARN_IF_NOT(JSVAL_IS_STRING(v) || JSVAL_IS_NUMBER(v), v); // allow implicit number conversions JSString* ret = JS_ValueToString(cx, v); if (!ret) FAIL("Argument must be convertible to a string"); char* ch = JS_EncodeString(cx, ret); // chops off high byte of each jschar if (!ch) FAIL("JS_EncodeString failed"); // out of memory out = std::string(ch, ch + JS_GetStringLength(ret)); JS_free(cx, ch); return true; }
template<> bool ScriptInterface::FromJSVal<std::wstring>(JSContext* cx, jsval v, std::wstring& out) { WARN_IF_NOT(JSVAL_IS_STRING(v) || JSVAL_IS_NUMBER(v), v); // allow implicit number conversions JSString* ret = JS_ValueToString(cx, v); if (!ret) FAIL("Argument must be convertible to a string"); size_t length; const jschar* ch = JS_GetStringCharsAndLength(cx, ret, &length); if (!ch) FAIL("JS_GetStringsCharsAndLength failed"); // out of memory out = std::wstring(ch, ch + length); return true; }
template<> bool ScriptInterface::FromJSVal<std::string>(JSContext* cx, JS::HandleValue v, std::string& out) { JSAutoRequest rq(cx); WARN_IF_NOT(v.isString() || v.isNumber(), v); // allow implicit number conversions JS::RootedString str(cx, JS::ToString(cx, v)); if (!str) FAIL("Argument must be convertible to a string"); char* ch = JS_EncodeString(cx, str); // chops off high byte of each char16_t if (!ch) FAIL("JS_EncodeString failed"); // out of memory out.assign(ch, ch + JS_GetStringLength(str)); JS_free(cx, ch); return true; }