示例#1
0
std::wstring ScriptInterface::ToString(jsval obj, bool pretty)
{
	if (JSVAL_IS_VOID(obj))
		return L"(void 0)";

	// Try to stringify as JSON if possible
	// (TODO: this is maybe a bad idea since it'll drop 'undefined' values silently)
	if (pretty)
	{
		StringifierW str;

		// Temporary disable the error reporter, so we don't print complaints about cyclic values
		JSErrorReporter er = JS_SetErrorReporter(m->m_cx, NULL);

		bool ok = JS_Stringify(m->m_cx, &obj, NULL, INT_TO_JSVAL(2), &StringifierW::callback, &str) == JS_TRUE;

		// Restore error reporter
		JS_SetErrorReporter(m->m_cx, er);

		if (ok)
			return str.stream.str();

		// Clear the exception set when Stringify failed
		JS_ClearPendingException(m->m_cx);
	}

	// Caller didn't want pretty output, or JSON conversion failed (e.g. due to cycles),
	// so fall back to obj.toSource()

	std::wstring source = L"(error)";
	CallFunction(obj, "toSource", source);
	return source;
}
示例#2
0
std::string CThreadDebugger::StringifyCyclicJSON(jsval obj, bool indent)
{
	CyclicRefWorkaround::Stringifier str;
	CyclicRefWorkaround::g_ProcessedObjects.clear();
	CyclicRefWorkaround::g_LastKey = JSVAL_VOID;
	
	JSObject* pGlob = JSVAL_TO_OBJECT(m->m_pScriptInterface->GetGlobalObject());
	JSFunction* fun = JS_DefineFunction(m->m_pScriptInterface->GetContext(), pGlob, "replacer", CyclicRefWorkaround::replacer, 0, JSPROP_ENUMERATE | JSPROP_READONLY | JSPROP_PERMANENT);
	JSObject* replacer = JS_GetFunctionObject(fun);
	if (!JS_Stringify(m->m_pScriptInterface->GetContext(), &obj, replacer, indent ? INT_TO_JSVAL(2) : JSVAL_VOID, &CyclicRefWorkaround::Stringifier::callback, &str))
	{
		LOGERROR(L"StringifyJSON failed");
		jsval exec;
		jsval execString;
		if (JS_GetPendingException(m->m_pScriptInterface->GetContext(), &exec))
		{
			if (JSVAL_IS_OBJECT(exec))
			{
				JS_GetProperty(m->m_pScriptInterface->GetContext(), JSVAL_TO_OBJECT(exec), "message", &execString);
			
				if (JSVAL_IS_STRING(execString))
				{
					std::string strExec = JS_EncodeString(m->m_pScriptInterface->GetContext(), JSVAL_TO_STRING(execString));
					LOGERROR(L"Error: %hs", strExec.c_str());
				}
			}
			
		}			
		JS_ClearPendingException(m->m_pScriptInterface->GetContext());
		return "";
	}

	return str.stream.str();
}
示例#3
0
nsresult
nsJSON::EncodeInternal(JSContext* cx, const JS::Value& aValue,
                       nsJSONWriter* writer)
{
  JSAutoRequest ar(cx);

  // Backward compatibility:
  // nsIJSON does not allow to serialize anything other than objects
  if (!aValue.isObject()) {
    return NS_ERROR_INVALID_ARG;
  }

  JSObject* obj = &aValue.toObject();

  JS::Value val = aValue;

  /* Backward compatibility:
   * Manually call toJSON if implemented by the object and check that
   * the result is still an object
   * Note: It is perfectly fine to not implement toJSON, so it is
   * perfectly fine for GetMethod to fail
   */
  JS::Value toJSON;
  if (JS_GetMethod(cx, obj, "toJSON", NULL, &toJSON) &&
      !JSVAL_IS_PRIMITIVE(toJSON) &&
      JS_ObjectIsCallable(cx, JSVAL_TO_OBJECT(toJSON))) {
    // If toJSON is implemented, it must not throw
    if (!JS_CallFunctionValue(cx, obj, toJSON, 0, NULL, &val)) {
      if (JS_IsExceptionPending(cx))
        // passing NS_OK will throw the pending exception
        return NS_OK;

      // No exception, but still failed
      return NS_ERROR_FAILURE;
    }

    // Backward compatibility:
    // nsIJSON does not allow to serialize anything other than objects
    if (JSVAL_IS_PRIMITIVE(val))
      return NS_ERROR_INVALID_ARG;
  }
  // GetMethod may have thrown
  else if (JS_IsExceptionPending(cx))
    // passing NS_OK will throw the pending exception
    return NS_OK;

  // Backward compatibility:
  // function shall not pass, just "plain" objects and arrays
  JSType type = JS_TypeOfValue(cx, val);
  if (type == JSTYPE_FUNCTION)
    return NS_ERROR_INVALID_ARG;

  // We're good now; try to stringify
  if (!JS_Stringify(cx, &val, NULL, JSVAL_NULL, WriteCallback, writer))
    return NS_ERROR_FAILURE;

  return NS_OK;
}
示例#4
0
nsresult
nsJSON::EncodeInternal(nsJSONWriter *writer)
{
  nsresult rv;
  nsIXPConnect *xpc = nsContentUtils::XPConnect();
  if (!xpc)
    return NS_ERROR_FAILURE;

  nsAXPCNativeCallContext *cc = nsnull;
  rv = xpc->GetCurrentNativeCallContext(&cc);
  NS_ENSURE_SUCCESS(rv, rv);

  JSContext *cx = nsnull;
  rv = cc->GetJSContext(&cx);
  NS_ENSURE_SUCCESS(rv, rv);

  JSAutoRequest ar(cx);

  PRUint32 argc = 0;
  rv = cc->GetArgc(&argc);
  NS_ENSURE_SUCCESS(rv, rv);

  // Now fish for the JS arguments. If it's a call to encode, we'll
  // want the first two arguments. If it's a call to encodeToStream,
  // we'll want the fourth and fifth;
  PRUint32 firstArg = writer->mStream ? 3 : 0;

  // Get the object we're going to serialize.
  JSObject *inputObj = nsnull;
  jsval *argv = nsnull;
  rv = cc->GetArgvPtr(&argv);
  NS_ENSURE_SUCCESS(rv, rv);

  if (argc <= firstArg ||
      !(JSVAL_IS_OBJECT(argv[firstArg]) &&
        (inputObj = JSVAL_TO_OBJECT(argv[firstArg])))) {
    // return if it's not something we can deal with
    return NS_ERROR_INVALID_ARG;
  }

  jsval *vp = &argv[firstArg];
  JSBool ok = JS_TryJSON(cx, vp);
  JSType type;
  if (!(ok && !JSVAL_IS_PRIMITIVE(*vp) &&
        (type = JS_TypeOfValue(cx, *vp)) != JSTYPE_FUNCTION &&
        type != JSTYPE_XML)) {
    return NS_ERROR_INVALID_ARG;
  }

  ok = JS_Stringify(cx, vp, NULL, JSVAL_NULL, WriteCallback, writer);
  if (!ok)
    return NS_ERROR_FAILURE;
    
  return NS_OK;
}
示例#5
0
nsresult
nsJSON::EncodeInternal(JSContext* cx, const JS::Value& aValue,
                       nsJSONWriter* writer)
{
  // Backward compatibility:
  // nsIJSON does not allow to serialize anything other than objects
  if (!aValue.isObject()) {
    return NS_ERROR_INVALID_ARG;
  }
  JS::Rooted<JSObject*> obj(cx, &aValue.toObject());

  /* Backward compatibility:
   * Manually call toJSON if implemented by the object and check that
   * the result is still an object
   * Note: It is perfectly fine to not implement toJSON, so it is
   * perfectly fine for GetMethod to fail
   */
  JS::Rooted<JS::Value> val(cx, aValue);
  JS::Rooted<JS::Value> toJSON(cx);
  if (JS_GetProperty(cx, obj, "toJSON", &toJSON) &&
      toJSON.isObject() &&
      JS_ObjectIsCallable(cx, &toJSON.toObject())) {
    // If toJSON is implemented, it must not throw
    if (!JS_CallFunctionValue(cx, obj, toJSON, 0, nullptr, val.address())) {
      if (JS_IsExceptionPending(cx))
        // passing NS_OK will throw the pending exception
        return NS_OK;

      // No exception, but still failed
      return NS_ERROR_FAILURE;
    }

    // Backward compatibility:
    // nsIJSON does not allow to serialize anything other than objects
    if (val.isPrimitive())
      return NS_ERROR_INVALID_ARG;
  }
  // GetMethod may have thrown
  else if (JS_IsExceptionPending(cx))
    // passing NS_OK will throw the pending exception
    return NS_OK;

  // Backward compatibility:
  // function shall not pass, just "plain" objects and arrays
  JSType type = JS_TypeOfValue(cx, val);
  if (type == JSTYPE_FUNCTION)
    return NS_ERROR_INVALID_ARG;

  // We're good now; try to stringify
  if (!JS_Stringify(cx, &val, JS::NullPtr(), JS::NullHandleValue, WriteCallback, writer))
    return NS_ERROR_FAILURE;

  return NS_OK;
}
示例#6
0
std::string ScriptInterface::StringifyJSON(jsval obj, bool indent)
{
	Stringifier str;
	if (!JS_Stringify(m->m_cx, &obj, NULL, indent ? INT_TO_JSVAL(2) : JSVAL_VOID, &Stringifier::callback, &str))
	{
		JS_ClearPendingException(m->m_cx);
		LOGERROR(L"StringifyJSON failed");
		JS_ClearPendingException(m->m_cx);
		return std::string();
	}

	return str.stream.str();
}
示例#7
0
// TODO: It's not quite clear why JS_Stringify needs JS::MutableHandleValue. |obj| should not get modified.
// It probably has historical reasons and could be changed by SpiderMonkey in the future.
std::string ScriptInterface::StringifyJSON(JS::MutableHandleValue obj, bool indent)
{
	JSAutoRequest rq(m->m_cx);
	Stringifier str;
	JS::RootedValue indentVal(m->m_cx, indent ? JS::Int32Value(2) : JS::UndefinedValue());
	if (!JS_Stringify(m->m_cx, obj, JS::NullPtr(), indentVal, &Stringifier::callback, &str))
	{
		JS_ClearPendingException(m->m_cx);
		LOGERROR("StringifyJSON failed");
		return std::string();
	}

	return str.stream.str();
}
示例#8
0
NS_IMETHODIMP
nsJSON::EncodeFromJSVal(JS::Value *value, JSContext *cx, nsAString &result)
{
  result.Truncate();

  // Begin a new request
  JSAutoRequest ar(cx);

  JSAutoEnterCompartment ac;
  nsIScriptSecurityManager *ssm = nsnull;
  if (value->isObject()) {
    JSObject *obj = &value->toObject();
    if (!ac.enter(cx, obj)) {
      return NS_ERROR_FAILURE;
    }

    nsCOMPtr<nsIPrincipal> principal;
    ssm = nsContentUtils::GetSecurityManager();
    nsresult rv = ssm->GetObjectPrincipal(cx, obj, getter_AddRefs(principal));
    NS_ENSURE_SUCCESS(rv, rv);

    JSStackFrame *fp = nsnull;
    rv = ssm->PushContextPrincipal(cx, JS_FrameIterator(cx, &fp), principal);
    NS_ENSURE_SUCCESS(rv, rv);
  }

  nsJSONWriter writer;
  JSBool ok = JS_Stringify(cx, value, NULL, JSVAL_NULL,
                           WriteCallback, &writer);

  if (ssm) {
    ssm->PopContextPrincipal(cx);
  }

  if (!ok) {
    return NS_ERROR_XPC_BAD_CONVERT_JS;
  }

  NS_ENSURE_TRUE(writer.DidWrite(), NS_ERROR_UNEXPECTED);
  writer.FlushBuffer();
  result.Assign(writer.mOutputString);
  return NS_OK;
}
示例#9
0
NS_IMETHODIMP
nsJSON::EncodeFromJSVal(jsval *value, JSContext *cx, nsAString &result)
{
  result.Truncate();

  // Begin a new request
  JSAutoRequest ar(cx);

  nsJSONWriter writer;
  JSBool ok = JS_Stringify(cx, value, NULL, JSVAL_NULL,
                           WriteCallback, &writer);
  if (!ok) {
    return NS_ERROR_XPC_BAD_CONVERT_JS;
  }

  NS_ENSURE_TRUE(writer.DidWrite(), NS_ERROR_UNEXPECTED);
  writer.FlushBuffer();
  result.Assign(writer.mOutputString);
  return NS_OK;
}
示例#10
0
NS_IMETHODIMP
nsJSON::EncodeFromJSVal(JS::Value *value, JSContext *cx, nsAString &result)
{
  result.Truncate();

  mozilla::Maybe<JSAutoCompartment> ac;
  if (value->isObject()) {
    JS::Rooted<JSObject*> obj(cx, &value->toObject());
    ac.construct(cx, obj);
  }

  nsJSONWriter writer;
  if (!JS_Stringify(cx, value, NULL, JSVAL_NULL, WriteCallback, &writer)) {
    return NS_ERROR_XPC_BAD_CONVERT_JS;
  }

  NS_ENSURE_TRUE(writer.DidWrite(), NS_ERROR_UNEXPECTED);
  writer.FlushBuffer();
  result.Assign(writer.mOutputString);
  return NS_OK;
}
示例#11
0
std::string ScriptInterface::ToString(JS::MutableHandleValue obj, bool pretty)
{
	JSAutoRequest rq(m->m_cx);

	if (obj.isUndefined())
		return "(void 0)";

	// Try to stringify as JSON if possible
	// (TODO: this is maybe a bad idea since it'll drop 'undefined' values silently)
	if (pretty)
	{
		Stringifier str;
		JS::RootedValue indentVal(m->m_cx, JS::Int32Value(2));

		// Temporary disable the error reporter, so we don't print complaints about cyclic values
		JSErrorReporter er = JS_SetErrorReporter(m->m_cx, NULL);

		bool ok = JS_Stringify(m->m_cx, obj, JS::NullPtr(), indentVal, &Stringifier::callback, &str);

		// Restore error reporter
		JS_SetErrorReporter(m->m_cx, er);

		if (ok)
			return str.stream.str();

		// Clear the exception set when Stringify failed
		JS_ClearPendingException(m->m_cx);
	}

	// Caller didn't want pretty output, or JSON conversion failed (e.g. due to cycles),
	// so fall back to obj.toSource()

	std::wstring source = L"(error)";
	CallFunction(obj, "toSource", source);
	return utf8_from_wstring(source);
}
示例#12
0
nsresult
SaveProfileTask::Run() {
  // Get file path
#if defined(SPS_PLAT_arm_android) && !defined(MOZ_WIDGET_GONK)
  nsCString tmpPath;
  tmpPath.AppendPrintf("/sdcard/profile_%i_%i.txt", XRE_GetProcessType(), getpid());
#else
  nsCOMPtr<nsIFile> tmpFile;
  nsAutoCString tmpPath;
  if (NS_FAILED(NS_GetSpecialDirectory(NS_OS_TEMP_DIR, getter_AddRefs(tmpFile)))) {
    LOG("Failed to find temporary directory.");
    return NS_ERROR_FAILURE;
  }
  tmpPath.AppendPrintf("profile_%i_%i.txt", XRE_GetProcessType(), getpid());

  nsresult rv = tmpFile->AppendNative(tmpPath);
  if (NS_FAILED(rv))
    return rv;

  rv = tmpFile->GetNativePath(tmpPath);
  if (NS_FAILED(rv))
    return rv;
#endif

  // Create a JSContext to run a JSObjectBuilder :(
  // Based on XPCShellEnvironment
  JSRuntime *rt;
  JSContext *cx;
  nsCOMPtr<nsIJSRuntimeService> rtsvc
    = do_GetService("@mozilla.org/js/xpc/RuntimeService;1");
  if (!rtsvc || NS_FAILED(rtsvc->GetRuntime(&rt)) || !rt) {
    LOG("failed to get RuntimeService");
    return NS_ERROR_FAILURE;;
  }

  cx = JS_NewContext(rt, 8192);
  if (!cx) {
    LOG("Failed to get context");
    return NS_ERROR_FAILURE;
  }

  {
    JSAutoRequest ar(cx);
    static const JSClass c = {
      "global", JSCLASS_GLOBAL_FLAGS,
      JS_PropertyStub, JS_DeletePropertyStub, JS_PropertyStub, JS_StrictPropertyStub,
      JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub
    };
    JSObject *obj = JS_NewGlobalObject(cx, &c, nullptr, JS::FireOnNewGlobalHook);

    std::ofstream stream;
    stream.open(tmpPath.get());
    if (stream.is_open()) {
      JSAutoCompartment autoComp(cx, obj);
      JSObject* profileObj = profiler_get_profile_jsobject(cx);
      JS::Rooted<JS::Value> val(cx, OBJECT_TO_JSVAL(profileObj));
      JS_Stringify(cx, &val, JS::NullPtr(), JS::NullHandleValue, WriteCallback, &stream);
      stream.close();
      LOGF("Saved to %s", tmpPath.get());
    } else {
      LOG("Fail to open profile log file.");
    }
  }
  JS_DestroyContext(cx);

  return NS_OK;
}
示例#13
0
JSBool RemoteStagedService::evaluate(struct mg_connection *conn, void *closures)
{
	RemoteStagedService *that = (RemoteStagedService *) closures;
	mg_send_header(conn, "Content-Type", "application/json");
	if(!that->cleanUp())
	{
		HttpHandler::response(conn, NULL, RESP_FAIL_STR, ERR_CODE_GENERAL, "cleanUp");
		return JS_TRUE;
	}

	if(!(conn->query_string && (strlen(conn->query_string)<STG_RECEIVE_SRC_SIZE))) {
		HttpHandler::response(conn, NULL, RESP_FAIL_STR, ERR_CODE_INVALID_ARGS, "");
		return JS_TRUE;
	}

	JSString *queryStr = JS_InternString(that->cx, conn->query_string + 4);
	JSString *queryEscStr;
	if(!JS_UnescapedString(that->cx, queryStr, &queryEscStr))
	{
		HttpHandler::response(conn, NULL, RESP_FAIL_STR, ERR_CODE_GENERAL, "unescapeString");
		return JS_TRUE;
	}

	char *queryEscChars = JS_EncodeString(that->cx, queryEscStr);
	jsSrcBufferSize = STG_RECEIVE_SRC_SIZE;
	if(!JS_DecodeBytes(that->cx, queryEscChars, strlen(queryEscChars), jsSrcBuffer, &jsSrcBufferSize)) 
	{
		HttpHandler::response(conn, NULL, RESP_FAIL_STR, ERR_CODE_GENERAL, "JS_DecodeBytes");
		return JS_TRUE;
	}

	jsval parseVal;
	if (!reflect_parse_from_string(that->cx, jsSrcBuffer, jsSrcBufferSize, &parseVal))
	{
		HttpHandler::response(conn, NULL, RESP_FAIL_STR, ERR_CODE_REFLECT_PARSE, "reflection parse error");
		return JS_TRUE;
	}

	JS::Value unparseArgs[] = { parseVal  };
	JS::Value unparseRes;
	if (!JS_CallFunctionName(that->cx, that->global, "unparse", 1, unparseArgs, &unparseRes)){
		HttpHandler::response(conn, NULL, RESP_FAIL_STR, ERR_CODE_GENERAL, "unparse");
		return JS_TRUE;
	}

	JS::Value *stringifyArg = { &OBJECT_TO_JSVAL(that->respArray) };
	if(!JS_Stringify(that->cx, stringifyArg, 0, js::NullValue(), onJSONStringifyFinished, 0)) 
	{
		HttpHandler::response(conn, NULL, RESP_FAIL_STR, ERR_CODE_GENERAL, "JS_Stringify");
		return JS_TRUE;
	}

	char srcBuffer[STG_RECEIVE_SRC_SIZE];
	size_t srcBufferSize=STG_RECEIVE_SRC_SIZE;
  if (!DeflateStringToBuffer(that->cx, jsSrcBuffer, jsSrcBufferSize, srcBuffer, &srcBufferSize)) 
	{
		HttpHandler::response(conn, NULL, RESP_FAIL_STR, ERR_CODE_GENERAL, "DeflateStringToBuffer");
		return JS_TRUE;
  }
	srcBuffer[srcBufferSize] = 0;

	HttpHandler::response(conn, NULL, RESP_SUCCESS_STR, srcBuffer);
	return JS_TRUE;
}