зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1819287 - Make nsContentUtils::StringifyJSON more flexible; r=smaug
Differential Revision: https://phabricator.services.mozilla.com/D171215
This commit is contained in:
Родитель
92601c6d5a
Коммит
3f2d0f2321
|
@ -133,7 +133,8 @@ void ConvertSerializedStackToJSON(UniquePtr<SerializedStackHolder> aStackHolder,
|
|||
}
|
||||
|
||||
JS::Rooted<JS::Value> convertedValue(cx, JS::ObjectValue(*converted));
|
||||
if (!nsContentUtils::StringifyJSON(cx, convertedValue, aStackString)) {
|
||||
if (!nsContentUtils::StringifyJSON(cx, convertedValue, aStackString,
|
||||
UndefinedIsNullStringLiteral)) {
|
||||
JS_ClearPendingException(cx);
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -10628,16 +10628,28 @@ static bool JSONCreator(const char16_t* aBuf, uint32_t aLen, void* aData) {
|
|||
|
||||
/* static */
|
||||
bool nsContentUtils::StringifyJSON(JSContext* aCx, JS::Handle<JS::Value> aValue,
|
||||
nsAString& aOutStr) {
|
||||
nsAString& aOutStr, JSONBehavior aBehavior) {
|
||||
MOZ_ASSERT(aCx);
|
||||
aOutStr.Truncate();
|
||||
JS::Rooted<JS::Value> value(aCx, aValue);
|
||||
nsAutoString serializedValue;
|
||||
NS_ENSURE_TRUE(JS_Stringify(aCx, &value, nullptr, JS::NullHandleValue,
|
||||
JSONCreator, &serializedValue),
|
||||
false);
|
||||
aOutStr = serializedValue;
|
||||
return true;
|
||||
switch (aBehavior) {
|
||||
case UndefinedIsNullStringLiteral: {
|
||||
aOutStr.Truncate();
|
||||
JS::Rooted<JS::Value> value(aCx, aValue);
|
||||
nsAutoString serializedValue;
|
||||
NS_ENSURE_TRUE(JS_Stringify(aCx, &value, nullptr, JS::NullHandleValue,
|
||||
JSONCreator, &serializedValue),
|
||||
false);
|
||||
aOutStr = serializedValue;
|
||||
return true;
|
||||
}
|
||||
case UndefinedIsVoidString: {
|
||||
aOutStr.SetIsVoid(true);
|
||||
return JS::ToJSON(aCx, aValue, nullptr, JS::NullHandleValue, JSONCreator,
|
||||
&aOutStr);
|
||||
}
|
||||
default:
|
||||
MOZ_ASSERT_UNREACHABLE("Invalid value for aBehavior");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/* static */
|
||||
|
|
|
@ -243,7 +243,11 @@ struct EventNameMapping {
|
|||
|
||||
namespace mozilla {
|
||||
enum class PreventDefaultResult : uint8_t { No, ByContent, ByChrome };
|
||||
|
||||
namespace dom {
|
||||
enum JSONBehavior { UndefinedIsNullStringLiteral, UndefinedIsVoidString };
|
||||
}
|
||||
} // namespace mozilla
|
||||
|
||||
class nsContentUtils {
|
||||
friend class nsAutoScriptBlockerSuppressNodeRemoved;
|
||||
|
@ -256,6 +260,7 @@ class nsContentUtils {
|
|||
using EventMessage = mozilla::EventMessage;
|
||||
using TimeDuration = mozilla::TimeDuration;
|
||||
using Trusted = mozilla::Trusted;
|
||||
using JSONBehavior = mozilla::dom::JSONBehavior;
|
||||
|
||||
public:
|
||||
static nsresult Init();
|
||||
|
@ -3256,15 +3261,21 @@ class nsContentUtils {
|
|||
static nsresult AnonymizeURI(nsIURI* aURI, nsCString& aAnonymizedURI);
|
||||
|
||||
/**
|
||||
* Serializes a JSON-like JS::Value into a string, returning the string "null"
|
||||
* where JSON.stringify would return undefined.
|
||||
* Serializes a JSON-like JS::Value into a string.
|
||||
* Cases where JSON.stringify would return undefined are handled according to
|
||||
* the |aBehavior| argument:
|
||||
*
|
||||
* - If it is |UndefinedIsNullStringLiteral|, the string "null" is returned.
|
||||
* - If it is |UndefinedIsVoidString|, the void string is returned.
|
||||
*
|
||||
* The |UndefinedIsNullStringLiteral| case is likely not desirable, but is
|
||||
* retained for now for historical reasons.
|
||||
* Usage:
|
||||
* nsAutoString serializedValue;
|
||||
* nsContentUtils::StringifyJSON(cx, value, serializedValue);
|
||||
* nsContentUtils::StringifyJSON(cx, value, serializedValue, behavior);
|
||||
*/
|
||||
static bool StringifyJSON(JSContext* aCx, JS::Handle<JS::Value> aValue,
|
||||
nsAString& aOutStr);
|
||||
nsAString& aOutStr, JSONBehavior aBehavior);
|
||||
|
||||
/**
|
||||
* Returns true if the top level ancestor content document of aDocument hasn't
|
||||
|
|
|
@ -472,7 +472,9 @@ bool nsFrameMessageManager::GetParamsForMessage(JSContext* aCx,
|
|||
// properly cases when interface is implemented in JS and used
|
||||
// as a dictionary.
|
||||
nsAutoString json;
|
||||
NS_ENSURE_TRUE(nsContentUtils::StringifyJSON(aCx, v, json), false);
|
||||
NS_ENSURE_TRUE(
|
||||
nsContentUtils::StringifyJSON(aCx, v, json, UndefinedIsNullStringLiteral),
|
||||
false);
|
||||
NS_ENSURE_TRUE(!json.IsEmpty(), false);
|
||||
|
||||
JS::Rooted<JS::Value> val(aCx, JS::NullValue());
|
||||
|
|
|
@ -14,6 +14,8 @@
|
|||
#include "mozilla/dom/ScriptSettings.h"
|
||||
#include "mozilla/dom/SimpleGlobalObject.h"
|
||||
|
||||
using namespace mozilla::dom;
|
||||
|
||||
struct IsURIInListMatch {
|
||||
nsLiteralCString pattern;
|
||||
bool firstMatch, secondMatch;
|
||||
|
@ -64,7 +66,8 @@ TEST(DOM_Base_ContentUtils, IsURIInList)
|
|||
}
|
||||
}
|
||||
|
||||
TEST(DOM_Base_ContentUtils, StringifyJSON_EmptyValue)
|
||||
TEST(DOM_Base_ContentUtils,
|
||||
StringifyJSON_EmptyValue_UndefinedIsNullStringLiteral)
|
||||
{
|
||||
JS::Rooted<JSObject*> globalObject(
|
||||
mozilla::dom::RootingCx(),
|
||||
|
@ -76,11 +79,12 @@ TEST(DOM_Base_ContentUtils, StringifyJSON_EmptyValue)
|
|||
nsAutoString serializedValue;
|
||||
|
||||
ASSERT_TRUE(nsContentUtils::StringifyJSON(cx, JS::UndefinedHandleValue,
|
||||
serializedValue));
|
||||
serializedValue,
|
||||
UndefinedIsNullStringLiteral));
|
||||
ASSERT_TRUE(serializedValue.EqualsLiteral("null"));
|
||||
}
|
||||
|
||||
TEST(DOM_Base_ContentUtils, StringifyJSON_Object)
|
||||
TEST(DOM_Base_ContentUtils, StringifyJSON_Object_UndefinedIsNullStringLiteral)
|
||||
{
|
||||
JS::Rooted<JSObject*> globalObject(
|
||||
mozilla::dom::RootingCx(),
|
||||
|
@ -96,7 +100,47 @@ TEST(DOM_Base_ContentUtils, StringifyJSON_Object)
|
|||
ASSERT_TRUE(JS_DefineProperty(cx, jsObj, "key1", valueStr, JSPROP_ENUMERATE));
|
||||
JS::Rooted<JS::Value> jsValue(cx, JS::ObjectValue(*jsObj));
|
||||
|
||||
ASSERT_TRUE(nsContentUtils::StringifyJSON(cx, jsValue, serializedValue));
|
||||
ASSERT_TRUE(nsContentUtils::StringifyJSON(cx, jsValue, serializedValue,
|
||||
UndefinedIsNullStringLiteral));
|
||||
|
||||
ASSERT_TRUE(serializedValue.EqualsLiteral("{\"key1\":\"Hello World!\"}"));
|
||||
}
|
||||
|
||||
TEST(DOM_Base_ContentUtils, StringifyJSON_EmptyValue_UndefinedIsVoidString)
|
||||
{
|
||||
JS::Rooted<JSObject*> globalObject(
|
||||
mozilla::dom::RootingCx(),
|
||||
mozilla::dom::SimpleGlobalObject::Create(
|
||||
mozilla::dom::SimpleGlobalObject::GlobalType::BindingDetail));
|
||||
mozilla::dom::AutoJSAPI jsAPI;
|
||||
ASSERT_TRUE(jsAPI.Init(globalObject));
|
||||
JSContext* cx = jsAPI.cx();
|
||||
nsAutoString serializedValue;
|
||||
|
||||
ASSERT_TRUE(nsContentUtils::StringifyJSON(
|
||||
cx, JS::UndefinedHandleValue, serializedValue, UndefinedIsVoidString));
|
||||
|
||||
ASSERT_TRUE(serializedValue.IsVoid());
|
||||
}
|
||||
|
||||
TEST(DOM_Base_ContentUtils, StringifyJSON_Object_UndefinedIsVoidString)
|
||||
{
|
||||
JS::Rooted<JSObject*> globalObject(
|
||||
mozilla::dom::RootingCx(),
|
||||
mozilla::dom::SimpleGlobalObject::Create(
|
||||
mozilla::dom::SimpleGlobalObject::GlobalType::BindingDetail));
|
||||
mozilla::dom::AutoJSAPI jsAPI;
|
||||
ASSERT_TRUE(jsAPI.Init(globalObject));
|
||||
JSContext* cx = jsAPI.cx();
|
||||
nsAutoString serializedValue;
|
||||
|
||||
JS::Rooted<JSObject*> jsObj(cx, JS_NewPlainObject(cx));
|
||||
JS::Rooted<JSString*> valueStr(cx, JS_NewStringCopyZ(cx, "Hello World!"));
|
||||
ASSERT_TRUE(JS_DefineProperty(cx, jsObj, "key1", valueStr, JSPROP_ENUMERATE));
|
||||
JS::Rooted<JS::Value> jsValue(cx, JS::ObjectValue(*jsObj));
|
||||
|
||||
ASSERT_TRUE(nsContentUtils::StringifyJSON(cx, jsValue, serializedValue,
|
||||
UndefinedIsVoidString));
|
||||
|
||||
ASSERT_TRUE(serializedValue.EqualsLiteral("{\"key1\":\"Hello World!\"}"));
|
||||
}
|
||||
|
|
|
@ -48,7 +48,8 @@ nsresult GetAsString(const RefPtr<Promise>& aPromise, nsAString& aString) {
|
|||
}
|
||||
|
||||
case Promise::PromiseState::Resolved: {
|
||||
if (nsContentUtils::StringifyJSON(cx, vp, aString)) {
|
||||
if (nsContentUtils::StringifyJSON(cx, vp, aString,
|
||||
UndefinedIsNullStringLiteral)) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
|
|
@ -142,7 +142,8 @@ void DOMLocalization::SetAttributes(
|
|||
if (aArgs.WasPassed() && aArgs.Value()) {
|
||||
nsAutoString data;
|
||||
JS::Rooted<JS::Value> val(aCx, JS::ObjectValue(*aArgs.Value()));
|
||||
if (!nsContentUtils::StringifyJSON(aCx, val, data)) {
|
||||
if (!nsContentUtils::StringifyJSON(aCx, val, data,
|
||||
UndefinedIsNullStringLiteral)) {
|
||||
aRv.NoteJSContextException(aCx);
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -22,7 +22,8 @@ nsresult SerializeFromJSObject(JSContext* aCx, JS::Handle<JSObject*> aObject,
|
|||
nsresult SerializeFromJSVal(JSContext* aCx, JS::Handle<JS::Value> aValue,
|
||||
nsAString& aSerializedValue) {
|
||||
aSerializedValue.Truncate();
|
||||
NS_ENSURE_TRUE(nsContentUtils::StringifyJSON(aCx, aValue, aSerializedValue),
|
||||
NS_ENSURE_TRUE(nsContentUtils::StringifyJSON(aCx, aValue, aSerializedValue,
|
||||
UndefinedIsNullStringLiteral),
|
||||
NS_ERROR_XPC_BAD_CONVERT_JS);
|
||||
NS_ENSURE_TRUE(!aSerializedValue.IsEmpty(), NS_ERROR_FAILURE);
|
||||
return NS_OK;
|
||||
|
|
|
@ -1128,7 +1128,8 @@ MOZ_CAN_RUN_SCRIPT
|
|||
static void SetSessionData(JSContext* aCx, Element* aElement,
|
||||
JS::MutableHandle<JS::Value> aObject) {
|
||||
nsAutoString data;
|
||||
if (nsContentUtils::StringifyJSON(aCx, aObject, data)) {
|
||||
if (nsContentUtils::StringifyJSON(aCx, aObject, data,
|
||||
UndefinedIsNullStringLiteral)) {
|
||||
SetElementAsString(aElement, data);
|
||||
} else {
|
||||
JS_ClearPendingException(aCx);
|
||||
|
|
|
@ -230,7 +230,8 @@ class UntrustedModulesFixture : public TelemetryTestFixture {
|
|||
serializer.GetObject(&jsval);
|
||||
|
||||
nsAutoString json;
|
||||
EXPECT_TRUE(nsContentUtils::StringifyJSON(cx.GetJSContext(), jsval, json));
|
||||
EXPECT_TRUE(nsContentUtils::StringifyJSON(
|
||||
cx.GetJSContext(), jsval, json, dom::UndefinedIsNullStringLiteral));
|
||||
|
||||
JS::Rooted<JSObject*> re(
|
||||
cx.GetJSContext(),
|
||||
|
|
Загрузка…
Ссылка в новой задаче