[json] implement JSON.stringify gap pre-processing in C++.
This is in preparation of fully porting JSON.stringify to C++. R=cbruni@chromium.org Review-Url: https://codereview.chromium.org/2006663002 Cr-Commit-Position: refs/heads/master@{#36449}
This commit is contained in:
parent
f43aa0bc6c
commit
c1f1e1ab98
@ -2778,8 +2778,8 @@ MaybeLocal<String> JSON::Stringify(Local<Context> context,
|
||||
? isolate->factory()->empty_string()
|
||||
: Utils::OpenHandle(*gap);
|
||||
i::Handle<i::Object> maybe;
|
||||
has_pending_exception = !i::BasicJsonStringifier(isolate, gap_string)
|
||||
.Stringify(object)
|
||||
has_pending_exception = !i::BasicJsonStringifier(isolate)
|
||||
.Stringify(object, gap_string)
|
||||
.ToHandle(&maybe);
|
||||
RETURN_ON_FAILED_EXECUTION(String);
|
||||
Local<String> result;
|
||||
|
@ -233,6 +233,9 @@ function JSONStringify(value, replacer, space) {
|
||||
space = TO_STRING(space);
|
||||
}
|
||||
}
|
||||
if (!IS_CALLABLE(replacer) && !property_list) {
|
||||
return %BasicJSONStringify(value, space);
|
||||
}
|
||||
var gap;
|
||||
if (IS_NUMBER(space)) {
|
||||
space = MaxSimple(0, MinSimple(TO_INTEGER(space), 10));
|
||||
@ -246,9 +249,6 @@ function JSONStringify(value, replacer, space) {
|
||||
} else {
|
||||
gap = "";
|
||||
}
|
||||
if (!IS_CALLABLE(replacer) && !property_list) {
|
||||
return %BasicJSONStringify(value, gap);
|
||||
}
|
||||
return JSONSerialize('', {'': value}, replacer, new Stack(), "", gap);
|
||||
}
|
||||
|
||||
|
@ -81,29 +81,15 @@ const char* const BasicJsonStringifier::JsonEscapeTable =
|
||||
"\370\0 \371\0 \372\0 \373\0 "
|
||||
"\374\0 \375\0 \376\0 \377\0 ";
|
||||
|
||||
BasicJsonStringifier::BasicJsonStringifier(Isolate* isolate, Handle<String> gap)
|
||||
: isolate_(isolate), builder_(isolate), gap_string_(gap), indent_(0) {
|
||||
BasicJsonStringifier::BasicJsonStringifier(Isolate* isolate)
|
||||
: isolate_(isolate), builder_(isolate), gap_(nullptr), indent_(0) {
|
||||
tojson_string_ = factory()->toJSON_string();
|
||||
stack_ = factory()->NewJSArray(8);
|
||||
int gap_length = gap->length();
|
||||
if (gap_length != 0) {
|
||||
gap = String::Flatten(gap);
|
||||
if (gap->IsTwoByteRepresentation()) builder_.ChangeEncoding();
|
||||
DisallowHeapAllocation no_gc;
|
||||
String::FlatContent flat = gap->GetFlatContent();
|
||||
gap_ = NewArray<uc16>(gap_length + 1);
|
||||
if (flat.IsOneByte()) {
|
||||
CopyChars(gap_, flat.ToOneByteVector().start(), gap_length);
|
||||
} else {
|
||||
CopyChars(gap_, flat.ToUC16Vector().start(), gap_length);
|
||||
}
|
||||
gap_[gap_length] = '\0';
|
||||
} else {
|
||||
gap_ = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
MaybeHandle<Object> BasicJsonStringifier::Stringify(Handle<Object> object) {
|
||||
MaybeHandle<Object> BasicJsonStringifier::Stringify(Handle<Object> object,
|
||||
Handle<Object> gap) {
|
||||
if (!gap->IsUndefined() && !InitializeGap(gap)) return MaybeHandle<Object>();
|
||||
Result result = SerializeObject(object);
|
||||
if (result == UNCHANGED) return factory()->undefined_value();
|
||||
if (result == SUCCESS) return builder_.Finish();
|
||||
@ -111,6 +97,46 @@ MaybeHandle<Object> BasicJsonStringifier::Stringify(Handle<Object> object) {
|
||||
return MaybeHandle<Object>();
|
||||
}
|
||||
|
||||
bool BasicJsonStringifier::InitializeGap(Handle<Object> gap) {
|
||||
DCHECK_NULL(gap_);
|
||||
HandleScope scope(isolate_);
|
||||
if (gap->IsJSReceiver()) {
|
||||
Handle<String> class_name(Handle<JSReceiver>::cast(gap)->class_name());
|
||||
if (class_name.is_identical_to(factory()->String_string())) {
|
||||
ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate_, gap,
|
||||
Object::ToString(isolate_, gap), false);
|
||||
} else if (class_name.is_identical_to(factory()->number_string())) {
|
||||
ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate_, gap, Object::ToNumber(gap),
|
||||
false);
|
||||
}
|
||||
}
|
||||
|
||||
if (gap->IsString()) {
|
||||
Handle<String> gap_string = Handle<String>::cast(gap);
|
||||
if (gap_string->length() > 0) {
|
||||
int gap_length = std::min(gap_string->length(), 10);
|
||||
gap_ = NewArray<uc16>(gap_length + 1);
|
||||
String::WriteToFlat(*gap_string, gap_, 0, gap_length);
|
||||
for (int i = 0; i < gap_length; i++) {
|
||||
if (gap_[i] > String::kMaxOneByteCharCode) {
|
||||
builder_.ChangeEncoding();
|
||||
break;
|
||||
}
|
||||
}
|
||||
gap_[gap_length] = '\0';
|
||||
}
|
||||
} else if (gap->IsNumber()) {
|
||||
int num_value = DoubleToInt32(gap->Number());
|
||||
if (num_value > 0) {
|
||||
int gap_length = std::min(num_value, 10);
|
||||
gap_ = NewArray<uc16>(gap_length + 1);
|
||||
for (int i = 0; i < gap_length; i++) gap_[i] = ' ';
|
||||
gap_[gap_length] = '\0';
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
MaybeHandle<Object> BasicJsonStringifier::StringifyString(
|
||||
Isolate* isolate, Handle<String> object) {
|
||||
static const int kJsonQuoteWorstCaseBlowup = 6;
|
||||
@ -119,9 +145,8 @@ MaybeHandle<Object> BasicJsonStringifier::StringifyString(
|
||||
object->length() * kJsonQuoteWorstCaseBlowup + kSpaceForQuotes;
|
||||
|
||||
if (worst_case_length > 32 * KB) { // Slow path if too large.
|
||||
BasicJsonStringifier stringifier(isolate,
|
||||
isolate->factory()->empty_string());
|
||||
return stringifier.Stringify(object);
|
||||
BasicJsonStringifier stringifier(isolate);
|
||||
return stringifier.Stringify(object, isolate->factory()->undefined_value());
|
||||
}
|
||||
|
||||
object = String::Flatten(object);
|
||||
|
@ -13,11 +13,12 @@ namespace internal {
|
||||
|
||||
class BasicJsonStringifier BASE_EMBEDDED {
|
||||
public:
|
||||
BasicJsonStringifier(Isolate* isolate, Handle<String> gap);
|
||||
explicit BasicJsonStringifier(Isolate* isolate);
|
||||
|
||||
~BasicJsonStringifier() { DeleteArray(gap_); }
|
||||
|
||||
MUST_USE_RESULT MaybeHandle<Object> Stringify(Handle<Object> object);
|
||||
MUST_USE_RESULT MaybeHandle<Object> Stringify(Handle<Object> object,
|
||||
Handle<Object> gap);
|
||||
|
||||
MUST_USE_RESULT static MaybeHandle<Object> StringifyString(
|
||||
Isolate* isolate, Handle<String> object);
|
||||
@ -25,6 +26,8 @@ class BasicJsonStringifier BASE_EMBEDDED {
|
||||
private:
|
||||
enum Result { UNCHANGED, SUCCESS, EXCEPTION };
|
||||
|
||||
bool InitializeGap(Handle<Object> gap);
|
||||
|
||||
MUST_USE_RESULT MaybeHandle<Object> ApplyToJsonFunction(
|
||||
Handle<Object> object,
|
||||
Handle<Object> key);
|
||||
@ -104,7 +107,6 @@ class BasicJsonStringifier BASE_EMBEDDED {
|
||||
IncrementalStringBuilder builder_;
|
||||
Handle<String> tojson_string_;
|
||||
Handle<JSArray> stack_;
|
||||
Handle<String> gap_string_;
|
||||
uc16* gap_;
|
||||
int indent_;
|
||||
|
||||
|
@ -28,10 +28,10 @@ RUNTIME_FUNCTION(Runtime_BasicJSONStringify) {
|
||||
HandleScope scope(isolate);
|
||||
DCHECK(args.length() == 2);
|
||||
CONVERT_ARG_HANDLE_CHECKED(Object, object, 0);
|
||||
CONVERT_ARG_HANDLE_CHECKED(String, gap, 1);
|
||||
CONVERT_ARG_HANDLE_CHECKED(Object, gap, 1);
|
||||
Handle<Object> result;
|
||||
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
|
||||
isolate, result, BasicJsonStringifier(isolate, gap).Stringify(object));
|
||||
isolate, result, BasicJsonStringifier(isolate).Stringify(object, gap));
|
||||
return *result;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user