Skip to content

Commit

Permalink
Expose JSON stringifier through V8 API
Browse files Browse the repository at this point in the history
BUG=602659
LOG=N

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

Cr-Commit-Position: refs/heads/master@{#35543}
  • Loading branch information
haavardmolland authored and Commit bot committed Apr 15, 2016
1 parent 451fa77 commit 0ba934d
Show file tree
Hide file tree
Showing 7 changed files with 81 additions and 23 deletions.
20 changes: 16 additions & 4 deletions include/v8.h
Expand Up @@ -1668,9 +1668,8 @@ struct SampleInfo {
StateTag vm_state;
};


/**
* A JSON Parser.
* A JSON Parser and Stringifier.
*/
class V8_EXPORT JSON {
public:
Expand All @@ -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);
};


Expand Down
36 changes: 30 additions & 6 deletions src/api.cc
Expand Up @@ -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"
Expand All @@ -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))
Expand Down Expand Up @@ -2747,13 +2746,38 @@ MaybeLocal<Value> JSON::Parse(Isolate* v8_isolate, Local<String> json_string) {
RETURN_ESCAPED(result);
}

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) {
auto isolate = reinterpret_cast<v8::Isolate*>(
Utils::OpenHandle(*json_string)->GetIsolate());
RETURN_TO_LOCAL_UNCHECKED(Parse(isolate, json_string), Value);
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 ---

Expand Down
10 changes: 3 additions & 7 deletions src/runtime/runtime-json.cc
Expand Up @@ -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 {
Expand All @@ -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());
Expand Down
10 changes: 10 additions & 0 deletions src/runtime/runtime-object.cc
Expand Up @@ -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"
Expand Down Expand Up @@ -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);
Expand Down
6 changes: 6 additions & 0 deletions src/runtime/runtime.h
Expand Up @@ -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,
Expand Down
20 changes: 15 additions & 5 deletions test/cctest/test-api.cc
Expand Up @@ -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 {
Expand Down
2 changes: 1 addition & 1 deletion test/fuzzer/json.cc
Expand Up @@ -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;
}

0 comments on commit 0ba934d

Please sign in to comment.