| Index: src/json-stringifier.h
|
| diff --git a/src/json-stringifier.h b/src/json-stringifier.h
|
| index 1b4ab9a0faa9f8a9e803c85575f994359dadc4da..728575bdb982a87524a451978da96492ece47410 100644
|
| --- a/src/json-stringifier.h
|
| +++ b/src/json-stringifier.h
|
| @@ -48,7 +48,7 @@ class BasicJsonStringifier BASE_EMBEDDED {
|
|
|
| enum Result { UNCHANGED, SUCCESS, EXCEPTION, CIRCULAR, STACK_OVERFLOW };
|
|
|
| - template <bool is_ascii> void Extend();
|
| + void Extend();
|
|
|
| void ChangeEncoding();
|
|
|
| @@ -82,9 +82,14 @@ class BasicJsonStringifier BASE_EMBEDDED {
|
| Handle<Object> ApplyToJsonFunction(Handle<Object> object,
|
| Handle<Object> key);
|
|
|
| + Result SerializeGeneric(Handle<Object> object,
|
| + Handle<Object> key,
|
| + bool deferred_comma,
|
| + bool deferred_key);
|
| +
|
| // Entry point to serialize the object.
|
| INLINE(Result SerializeObject(Handle<Object> obj)) {
|
| - return Serialize_<false>(obj, false, isolate_->factory()->empty_string());
|
| + return Serialize_<false>(obj, false, factory_->empty_string());
|
| }
|
|
|
| // Serialize an array element.
|
| @@ -147,7 +152,7 @@ class BasicJsonStringifier BASE_EMBEDDED {
|
| void StackPop();
|
|
|
| INLINE(Handle<String> accumulator()) {
|
| - return Handle<String>(String::cast(accumulator_store_->value()));
|
| + return Handle<String>(String::cast(accumulator_store_->value()), isolate_);
|
| }
|
|
|
| INLINE(void set_accumulator(Handle<String> string)) {
|
| @@ -155,6 +160,7 @@ class BasicJsonStringifier BASE_EMBEDDED {
|
| }
|
|
|
| Isolate* isolate_;
|
| + Factory* factory_;
|
| // We use a value wrapper for the string accumulator to keep the
|
| // (indirect) handle to it in the outermost handle scope.
|
| Handle<JSValue> accumulator_store_;
|
| @@ -209,13 +215,13 @@ const char* const BasicJsonStringifier::JsonEscapeTable =
|
|
|
| BasicJsonStringifier::BasicJsonStringifier(Isolate* isolate)
|
| : isolate_(isolate), current_index_(0), is_ascii_(true) {
|
| + factory_ = isolate_->factory();
|
| accumulator_store_ = Handle<JSValue>::cast(
|
| - isolate_->factory()->ToObject(isolate_->factory()->empty_string()));
|
| + factory_->ToObject(factory_->empty_string()));
|
| part_length_ = kInitialPartLength;
|
| - current_part_ =
|
| - isolate_->factory()->NewRawAsciiString(kInitialPartLength);
|
| - tojson_symbol_ = isolate_->factory()->LookupAsciiSymbol("toJSON");
|
| - stack_ = isolate_->factory()->NewJSArray(8);
|
| + current_part_ = factory_->NewRawAsciiString(kInitialPartLength);
|
| + tojson_symbol_ = factory_->LookupAsciiSymbol("toJSON");
|
| + stack_ = factory_->NewJSArray(8);
|
| }
|
|
|
|
|
| @@ -225,9 +231,9 @@ MaybeObject* BasicJsonStringifier::Stringify(Handle<Object> object) {
|
| return isolate_->heap()->undefined_value();
|
| case SUCCESS:
|
| ShrinkCurrentPart();
|
| - return *isolate_->factory()->NewConsString(accumulator(), current_part_);
|
| + return *factory_->NewConsString(accumulator(), current_part_);
|
| case CIRCULAR:
|
| - return isolate_->Throw(*isolate_->factory()->NewTypeError(
|
| + return isolate_->Throw(*factory_->NewTypeError(
|
| "circular_structure", HandleVector<Object>(NULL, 0)));
|
| case STACK_OVERFLOW:
|
| return isolate_->StackOverflow();
|
| @@ -246,7 +252,7 @@ void BasicJsonStringifier::Append_(Char c) {
|
| SeqTwoByteString::cast(*current_part_)->SeqTwoByteStringSet(
|
| current_index_++, c);
|
| }
|
| - if (current_index_ == part_length_) Extend<is_ascii>();
|
| + if (current_index_ == part_length_) Extend();
|
| }
|
|
|
|
|
| @@ -260,20 +266,20 @@ Handle<Object> BasicJsonStringifier::GetProperty(Handle<JSObject> object,
|
| Handle<String> key) {
|
| LookupResult lookup(isolate_);
|
| object->LocalLookupRealNamedProperty(*key, &lookup);
|
| - if (!lookup.IsProperty()) return isolate_->factory()->undefined_value();
|
| + if (!lookup.IsProperty()) return factory_->undefined_value();
|
| switch (lookup.type()) {
|
| case NORMAL: {
|
| Object* value = lookup.holder()->GetNormalizedProperty(&lookup);
|
| ASSERT(!value->IsTheHole());
|
| - return Handle<Object>(value);
|
| + return Handle<Object>(value, isolate_);
|
| }
|
| case FIELD: {
|
| Object* value = lookup.holder()->FastPropertyAt(lookup.GetFieldIndex());
|
| ASSERT(!value->IsTheHole());
|
| - return Handle<Object>(value);
|
| + return Handle<Object>(value, isolate_);
|
| }
|
| case CONSTANT_FUNCTION:
|
| - return Handle<Object>(lookup.GetConstantFunction());
|
| + return Handle<Object>(lookup.GetConstantFunction(), isolate_);
|
| default: {
|
| PropertyAttributes attr;
|
| return Object::GetProperty(object, object, &lookup, key, &attr);
|
| @@ -294,7 +300,7 @@ Handle<Object> BasicJsonStringifier::ApplyToJsonFunction(
|
| if (!fun->IsJSFunction()) return object;
|
|
|
| // Call toJSON function.
|
| - if (key->IsSmi()) key = isolate_->factory()->NumberToString(key);
|
| + if (key->IsSmi()) key = factory_->NumberToString(key);
|
| Handle<Object> argv[] = { key };
|
| bool has_exception = false;
|
| HandleScope scope(isolate_);
|
| @@ -338,47 +344,84 @@ BasicJsonStringifier::Result BasicJsonStringifier::Serialize_(
|
| if (object.is_null()) return EXCEPTION;
|
| }
|
|
|
| - if (object->IsJSObject()) {
|
| - if (object->IsJSFunction()) return UNCHANGED;
|
| + if (object->IsSmi()) {
|
| if (deferred_string_key) SerializeDeferredKey(comma, key);
|
| - if (object->IsJSArray()) {
|
| - return SerializeJSArray(Handle<JSArray>::cast(object));
|
| - } else if (object->IsJSValue()) {
|
| - return SerializeJSValue(Handle<JSValue>::cast(object));
|
| - } else {
|
| - return SerializeJSObject(Handle<JSObject>::cast(object));
|
| - }
|
| + return SerializeSmi(Smi::cast(*object));
|
| }
|
|
|
| - // Handle non-JSObject.
|
| - if (object->IsString()) {
|
| - if (deferred_string_key) SerializeDeferredKey(comma, key);
|
| - SerializeString(Handle<String>::cast(object));
|
| - return SUCCESS;
|
| - } else if (object->IsSmi()) {
|
| - if (deferred_string_key) SerializeDeferredKey(comma, key);
|
| - return SerializeSmi(Smi::cast(*object));
|
| - } else if (object->IsHeapNumber()) {
|
| - if (deferred_string_key) SerializeDeferredKey(comma, key);
|
| - return SerializeHeapNumber(Handle<HeapNumber>::cast(object));
|
| - } else if (object->IsOddball()) {
|
| - switch (Oddball::cast(*object)->kind()) {
|
| - case Oddball::kFalse:
|
| - if (deferred_string_key) SerializeDeferredKey(comma, key);
|
| - Append("false");
|
| - return SUCCESS;
|
| - case Oddball::kTrue:
|
| + switch (HeapObject::cast(*object)->map()->instance_type()) {
|
| + case HEAP_NUMBER_TYPE:
|
| + if (deferred_string_key) SerializeDeferredKey(comma, key);
|
| + return SerializeHeapNumber(Handle<HeapNumber>::cast(object));
|
| + case ODDBALL_TYPE:
|
| + switch (Oddball::cast(*object)->kind()) {
|
| + case Oddball::kFalse:
|
| + if (deferred_string_key) SerializeDeferredKey(comma, key);
|
| + Append("false");
|
| + return SUCCESS;
|
| + case Oddball::kTrue:
|
| + if (deferred_string_key) SerializeDeferredKey(comma, key);
|
| + Append("true");
|
| + return SUCCESS;
|
| + case Oddball::kNull:
|
| + if (deferred_string_key) SerializeDeferredKey(comma, key);
|
| + Append("null");
|
| + return SUCCESS;
|
| + default:
|
| + return UNCHANGED;
|
| + }
|
| + case JS_ARRAY_TYPE:
|
| + if (deferred_string_key) SerializeDeferredKey(comma, key);
|
| + return SerializeJSArray(Handle<JSArray>::cast(object));
|
| + case JS_VALUE_TYPE:
|
| + if (deferred_string_key) SerializeDeferredKey(comma, key);
|
| + return SerializeJSValue(Handle<JSValue>::cast(object));
|
| + case JS_FUNCTION_TYPE:
|
| + return UNCHANGED;
|
| + default:
|
| + if (object->IsString()) {
|
| if (deferred_string_key) SerializeDeferredKey(comma, key);
|
| - Append("true");
|
| + SerializeString(Handle<String>::cast(object));
|
| return SUCCESS;
|
| - case Oddball::kNull:
|
| + } else if (object->IsJSObject()) {
|
| if (deferred_string_key) SerializeDeferredKey(comma, key);
|
| - Append("null");
|
| - return SUCCESS;
|
| - }
|
| + return SerializeJSObject(Handle<JSObject>::cast(object));
|
| + } else {
|
| + return SerializeGeneric(object, key, comma, deferred_string_key);
|
| + }
|
| }
|
| +}
|
| +
|
|
|
| - return UNCHANGED;
|
| +BasicJsonStringifier::Result BasicJsonStringifier::SerializeGeneric(
|
| + Handle<Object> object,
|
| + Handle<Object> key,
|
| + bool deferred_comma,
|
| + bool deferred_key) {
|
| + Handle<JSObject> builtins(isolate_->native_context()->builtins());
|
| + Handle<JSFunction> builtin = Handle<JSFunction>::cast(
|
| + v8::internal::GetProperty(builtins, "JSONSerializeAdapter"));
|
| +
|
| + Handle<Object> argv[] = { key, object };
|
| + bool has_exception = false;
|
| + Handle<Object> result =
|
| + Execution::Call(builtin, object, 2, argv, &has_exception);
|
| + if (has_exception) return EXCEPTION;
|
| + if (result->IsUndefined()) return UNCHANGED;
|
| + if (deferred_key) {
|
| + if (key->IsSmi()) key = factory_->NumberToString(key);
|
| + SerializeDeferredKey(deferred_comma, key);
|
| + }
|
| +
|
| + Handle<String> result_string = Handle<String>::cast(result);
|
| + // Shrink current part, attach it to the accumulator, also attach the result
|
| + // string to the accumulator, and allocate a new part.
|
| + ShrinkCurrentPart(); // Shrink.
|
| + part_length_ = kInitialPartLength; // Allocate conservatively.
|
| + Extend(); // Attach current part and allocate new part.
|
| + // Attach result string to the accumulator.
|
| + set_accumulator(factory_->NewConsString(accumulator(), result_string));
|
| + return SUCCESS;
|
| }
|
|
|
|
|
| @@ -437,7 +480,8 @@ BasicJsonStringifier::Result BasicJsonStringifier::SerializeJSArray(
|
| Append('[');
|
| switch (object->GetElementsKind()) {
|
| case FAST_SMI_ELEMENTS: {
|
| - Handle<FixedArray> elements(FixedArray::cast(object->elements()));
|
| + Handle<FixedArray> elements(
|
| + FixedArray::cast(object->elements()), isolate_);
|
| for (int i = 0; i < length; i++) {
|
| if (i > 0) Append(',');
|
| SerializeSmi(Smi::cast(elements->get(i)));
|
| @@ -446,7 +490,7 @@ BasicJsonStringifier::Result BasicJsonStringifier::SerializeJSArray(
|
| }
|
| case FAST_DOUBLE_ELEMENTS: {
|
| Handle<FixedDoubleArray> elements(
|
| - FixedDoubleArray::cast(object->elements()));
|
| + FixedDoubleArray::cast(object->elements()), isolate_);
|
| for (int i = 0; i < length; i++) {
|
| if (i > 0) Append(',');
|
| SerializeDouble(elements->get_scalar(i));
|
| @@ -454,10 +498,12 @@ BasicJsonStringifier::Result BasicJsonStringifier::SerializeJSArray(
|
| break;
|
| }
|
| case FAST_ELEMENTS: {
|
| - Handle<FixedArray> elements(FixedArray::cast(object->elements()));
|
| + Handle<FixedArray> elements(
|
| + FixedArray::cast(object->elements()), isolate_);
|
| for (int i = 0; i < length; i++) {
|
| if (i > 0) Append(',');
|
| - Result result = SerializeElement(Handle<Object>(elements->get(i)), i);
|
| + Result result =
|
| + SerializeElement(Handle<Object>(elements->get(i), isolate_), i);
|
| if (result == SUCCESS) continue;
|
| if (result == UNCHANGED) {
|
| Append("null");
|
| @@ -510,7 +556,8 @@ BasicJsonStringifier::Result BasicJsonStringifier::SerializeJSObject(
|
| Result stack_push = StackPush(object);
|
| if (stack_push != SUCCESS) return stack_push;
|
| if (object->IsJSGlobalProxy()) {
|
| - object = Handle<JSObject>(JSObject::cast(object->GetPrototype()));
|
| + object = Handle<JSObject>(
|
| + JSObject::cast(object->GetPrototype()), isolate_);
|
| ASSERT(object->IsGlobalObject());
|
| }
|
| bool has_exception = false;
|
| @@ -524,11 +571,11 @@ BasicJsonStringifier::Result BasicJsonStringifier::SerializeJSObject(
|
| Handle<String> key_handle;
|
| Handle<Object> property;
|
| if (key->IsString()) {
|
| - key_handle = Handle<String>(String::cast(key));
|
| + key_handle = Handle<String>(String::cast(key), isolate_);
|
| property = GetProperty(object, key_handle);
|
| } else {
|
| ASSERT(key->IsNumber());
|
| - key_handle = isolate_->factory()->NumberToString(Handle<Object>(key));
|
| + key_handle = factory_->NumberToString(Handle<Object>(key, isolate_));
|
| uint32_t index;
|
| if (key->IsSmi()) {
|
| property = Object::GetElement(object, Smi::cast(key)->value());
|
| @@ -553,7 +600,7 @@ BasicJsonStringifier::Result BasicJsonStringifier::SerializeJSObject(
|
| void BasicJsonStringifier::ShrinkCurrentPart() {
|
| ASSERT(current_index_ < part_length_);
|
| if (current_index_ == 0) {
|
| - current_part_ = isolate_->factory()->empty_string();
|
| + current_part_ = factory_->empty_string();
|
| return;
|
| }
|
|
|
| @@ -580,19 +627,15 @@ void BasicJsonStringifier::ShrinkCurrentPart() {
|
| }
|
|
|
|
|
| -template <bool is_ascii>
|
| void BasicJsonStringifier::Extend() {
|
| - set_accumulator(
|
| - isolate_->factory()->NewConsString(accumulator(), current_part_));
|
| + set_accumulator(factory_->NewConsString(accumulator(), current_part_));
|
| if (part_length_ <= kMaxPartLength / kPartLengthGrowthFactor) {
|
| part_length_ *= kPartLengthGrowthFactor;
|
| }
|
| - if (is_ascii) {
|
| - current_part_ =
|
| - isolate_->factory()->NewRawAsciiString(part_length_);
|
| + if (is_ascii_) {
|
| + current_part_ = factory_->NewRawAsciiString(part_length_);
|
| } else {
|
| - current_part_ =
|
| - isolate_->factory()->NewRawTwoByteString(part_length_);
|
| + current_part_ = factory_->NewRawTwoByteString(part_length_);
|
| }
|
| current_index_ = 0;
|
| }
|
| @@ -600,10 +643,8 @@ void BasicJsonStringifier::Extend() {
|
|
|
| void BasicJsonStringifier::ChangeEncoding() {
|
| ShrinkCurrentPart();
|
| - set_accumulator(
|
| - isolate_->factory()->NewConsString(accumulator(), current_part_));
|
| - current_part_ =
|
| - isolate_->factory()->NewRawTwoByteString(part_length_);
|
| + set_accumulator(factory_->NewConsString(accumulator(), current_part_));
|
| + current_part_ = factory_->NewRawTwoByteString(part_length_);
|
| current_index_ = 0;
|
| is_ascii_ = false;
|
| }
|
|
|