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<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;
}
 bool js_to_number(JSContext *cx, JS::HandleValue v, double *dp) {
     if (v.isNumber()) {
         *dp = v.toNumber();
         return true;
     } else {
         *dp = 0;
         return false;
     }
 }
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;
}
bool jsval_to_std_string(JSContext *cx, JS::HandleValue v, std::string* ret) {
	if(v.isString() || v.isNumber())
	{
		JSString *tmp = JS::ToString(cx, v);
		JSB_PRECONDITION3(tmp, cx, false, "Error processing jsval_to_std_string");

		JSStringWrapper str(tmp, cx);
		*ret = str.get();
		return true;
	}

	return false;
}
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;
}