Expose JSON stringifier through V8 API

BUG=602659
LOG=N

Review URL: https://codereview.chromium.org/1891203002

Cr-Commit-Position: refs/heads/master@{#35543}
This commit is contained in:
haavardm 2016-04-15 11:23:48 -07:00 committed by Commit bot
parent 451fa77235
commit 0ba934d7bf
7 changed files with 83 additions and 25 deletions

View File

@ -1668,9 +1668,8 @@ struct SampleInfo {
StateTag vm_state;
};
/**
* A JSON Parser.
* A JSON Parser and Stringifier.
*/
class V8_EXPORT JSON {
public:
@ -1681,10 +1680,23 @@ class V8_EXPORT JSON {
* \param json_string The string to parse.
* \return The corresponding value if successfully parsed.
*/
static V8_DEPRECATED("Use maybe version",
static V8_DEPRECATED("Use the maybe version taking context",
Local<Value> Parse(Local<String> json_string));
static V8_DEPRECATE_SOON("Use the maybe version taking context",
MaybeLocal<Value> Parse(Isolate* isolate,
Local<String> json_string));
static V8_WARN_UNUSED_RESULT MaybeLocal<Value> Parse(
Isolate* isolate, Local<String> json_string);
Local<Context> context, Local<String> json_string);
/**
* Tries to stringify the JSON-serializable object |json_object| and returns
* it as string if successful.
*
* \param json_object The JSON-serializable object to stringify.
* \return The corresponding string if successfully stringified.
*/
static V8_WARN_UNUSED_RESULT MaybeLocal<String> Stringify(
Local<Context> context, Local<Object> json_object);
};

View File

@ -49,12 +49,12 @@
#include "src/profiler/heap-snapshot-generator-inl.h"
#include "src/profiler/profile-generator-inl.h"
#include "src/profiler/sampler.h"
#include "src/property.h"
#include "src/property-descriptor.h"
#include "src/property-details.h"
#include "src/property.h"
#include "src/prototype.h"
#include "src/runtime/runtime.h"
#include "src/runtime-profiler.h"
#include "src/runtime/runtime.h"
#include "src/simulator.h"
#include "src/snapshot/natives.h"
#include "src/snapshot/snapshot.h"
@ -66,7 +66,6 @@
#include "src/version.h"
#include "src/vm-state-inl.h"
namespace v8 {
#define LOG_API(isolate, expr) LOG(isolate, ApiEntryCall(expr))
@ -2747,13 +2746,38 @@ MaybeLocal<Value> JSON::Parse(Isolate* v8_isolate, Local<String> json_string) {
RETURN_ESCAPED(result);
}
Local<Value> JSON::Parse(Local<String> json_string) {
auto isolate = reinterpret_cast<v8::Isolate*>(
Utils::OpenHandle(*json_string)->GetIsolate());
RETURN_TO_LOCAL_UNCHECKED(Parse(isolate, json_string), Value);
MaybeLocal<Value> JSON::Parse(Local<Context> context,
Local<String> json_string) {
PREPARE_FOR_EXECUTION(context, "JSON::Parse", Value);
i::Handle<i::String> string = Utils::OpenHandle(*json_string);
i::Handle<i::String> source = i::String::Flatten(string);
auto maybe = source->IsSeqOneByteString()
? i::JsonParser<true>::Parse(source)
: i::JsonParser<false>::Parse(source);
Local<Value> result;
has_pending_exception = !ToLocal<Value>(maybe, &result);
RETURN_ON_FAILED_EXECUTION(Value);
RETURN_ESCAPED(result);
}
Local<Value> JSON::Parse(Local<String> json_string) {
RETURN_TO_LOCAL_UNCHECKED(Parse(Local<Context>(), json_string), Value);
}
MaybeLocal<String> JSON::Stringify(Local<Context> context,
Local<Object> json_object) {
PREPARE_FOR_EXECUTION(context, "JSON::Stringify", String);
i::Handle<i::Object> object = Utils::OpenHandle(*json_object);
i::Handle<i::Object> maybe;
has_pending_exception =
!i::Runtime::BasicJsonStringify(isolate, object).ToHandle(&maybe);
RETURN_ON_FAILED_EXECUTION(String);
Local<String> result;
has_pending_exception =
!ToLocal<String>(i::Object::ToString(isolate, maybe), &result);
RETURN_ON_FAILED_EXECUTION(String);
RETURN_ESCAPED(result);
}
// --- D a t a ---

View File

@ -8,7 +8,6 @@
#include "src/char-predicates-inl.h"
#include "src/isolate-inl.h"
#include "src/json-parser.h"
#include "src/json-stringifier.h"
#include "src/objects-inl.h"
namespace v8 {
@ -20,23 +19,20 @@ RUNTIME_FUNCTION(Runtime_QuoteJSONString) {
DCHECK(args.length() == 1);
Handle<Object> result;
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
isolate, result, BasicJsonStringifier::StringifyString(isolate, string));
isolate, result, Runtime::BasicJsonStringifyString(isolate, string));
return *result;
}
RUNTIME_FUNCTION(Runtime_BasicJSONStringify) {
HandleScope scope(isolate);
DCHECK(args.length() == 1);
CONVERT_ARG_HANDLE_CHECKED(Object, object, 0);
BasicJsonStringifier stringifier(isolate);
Handle<Object> result;
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result,
stringifier.Stringify(object));
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
isolate, result, Runtime::BasicJsonStringify(isolate, object));
return *result;
}
RUNTIME_FUNCTION(Runtime_ParseJson) {
HandleScope scope(isolate);
DCHECK_EQ(1, args.length());

View File

@ -8,6 +8,7 @@
#include "src/bootstrapper.h"
#include "src/debug/debug.h"
#include "src/isolate-inl.h"
#include "src/json-stringifier.h"
#include "src/messages.h"
#include "src/property-descriptor.h"
#include "src/runtime/runtime.h"
@ -225,6 +226,15 @@ MaybeHandle<Object> Runtime::SetObjectProperty(Isolate* isolate,
return value;
}
MaybeHandle<Object> Runtime::BasicJsonStringify(Isolate* isolate,
Handle<Object> object) {
return BasicJsonStringifier(isolate).Stringify(object);
}
MaybeHandle<Object> Runtime::BasicJsonStringifyString(Isolate* isolate,
Handle<String> string) {
return BasicJsonStringifier::StringifyString(isolate, string);
}
RUNTIME_FUNCTION(Runtime_GetPrototype) {
HandleScope scope(isolate);

View File

@ -1110,6 +1110,12 @@ class Runtime : public AllStatic {
MUST_USE_RESULT static MaybeHandle<Object> GetObjectProperty(
Isolate* isolate, Handle<Object> object, Handle<Object> key);
MUST_USE_RESULT static MaybeHandle<Object> BasicJsonStringify(
Isolate* isolate, Handle<Object> object);
MUST_USE_RESULT static MaybeHandle<Object> BasicJsonStringifyString(
Isolate* isolate, Handle<String> string);
enum TypedArrayId {
// arrayIds below should be synchronized with typedarray.js natives.
ARRAY_ID_UINT8 = 1,

View File

@ -21947,29 +21947,39 @@ THREADED_TEST(Regress260106) {
CHECK(function->IsFunction());
}
THREADED_TEST(JSONParseObject) {
LocalContext context;
HandleScope scope(context->GetIsolate());
Local<Value> obj =
v8::JSON::Parse(context->GetIsolate(), v8_str("{\"x\":42}"))
.ToLocalChecked();
v8::JSON::Parse(context.local(), v8_str("{\"x\":42}")).ToLocalChecked();
Local<Object> global = context->Global();
global->Set(context.local(), v8_str("obj"), obj).FromJust();
ExpectString("JSON.stringify(obj)", "{\"x\":42}");
}
THREADED_TEST(JSONParseNumber) {
LocalContext context;
HandleScope scope(context->GetIsolate());
Local<Value> obj =
v8::JSON::Parse(context->GetIsolate(), v8_str("42")).ToLocalChecked();
v8::JSON::Parse(context.local(), v8_str("42")).ToLocalChecked();
Local<Object> global = context->Global();
global->Set(context.local(), v8_str("obj"), obj).FromJust();
ExpectString("JSON.stringify(obj)", "42");
}
THREADED_TEST(JSONStringifyObject) {
LocalContext context;
HandleScope scope(context->GetIsolate());
Local<Value> value =
v8::JSON::Parse(context.local(), v8_str("{\"x\":42}")).ToLocalChecked();
Local<Object> obj = value->ToObject(context.local()).ToLocalChecked();
Local<Object> global = context->Global();
global->Set(context.local(), v8_str("obj"), obj).FromJust();
Local<String> json =
v8::JSON::Stringify(context.local(), obj).ToLocalChecked();
v8::String::Utf8Value utf8(json);
ExpectString("JSON.stringify(obj)", *utf8);
}
#if V8_OS_POSIX && !V8_OS_NACL
class ThreadInterruptTest {

View File

@ -26,6 +26,6 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
return 0;
}
v8::JSON::Parse(isolate, source).IsEmpty();
v8::JSON::Parse(support->GetContext(), source).IsEmpty();
return 0;
}