Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(150)

Unified Diff: src/json-stringifier.h

Issue 1994183002: [json] handle proxies in BasicJsonSerializer. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: address comments Created 4 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/js/json.js ('k') | src/objects.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/json-stringifier.h
diff --git a/src/json-stringifier.h b/src/json-stringifier.h
index 0b084e070d0aa43eeef090c92c4ff517ee1f3dbc..8172b7080c2559fcceae010dc02c319706884c9b 100644
--- a/src/json-stringifier.h
+++ b/src/json-stringifier.h
@@ -85,8 +85,10 @@ class BasicJsonStringifier BASE_EMBEDDED {
INLINE(Result SerializeJSArray(Handle<JSArray> object));
INLINE(Result SerializeJSObject(Handle<JSObject> object));
- Result SerializeJSArraySlow(Handle<JSArray> object, uint32_t start,
- uint32_t length);
+ Result SerializeJSProxy(Handle<JSProxy> object);
+ Result SerializeJSReceiverSlow(Handle<JSReceiver> object);
+ Result SerializeArrayLikeSlow(Handle<JSReceiver> object, uint32_t start,
+ uint32_t length);
void SerializeString(Handle<String> object);
@@ -326,7 +328,7 @@ void BasicJsonStringifier::StackPop() {
template <bool deferred_string_key>
BasicJsonStringifier::Result BasicJsonStringifier::Serialize_(
Handle<Object> object, bool comma, Handle<Object> key) {
- if (object->IsJSObject()) {
+ if (object->IsJSReceiver()) {
ASSIGN_RETURN_ON_EXCEPTION_VALUE(
isolate_, object,
ApplyToJsonFunction(object, key),
@@ -372,11 +374,14 @@ BasicJsonStringifier::Result BasicJsonStringifier::Serialize_(
if (deferred_string_key) SerializeDeferredKey(comma, key);
SerializeString(Handle<String>::cast(object));
return SUCCESS;
- } else if (object->IsJSObject()) {
+ } else if (object->IsJSReceiver()) {
if (object->IsCallable()) return UNCHANGED;
// Go to slow path for global proxy and objects requiring access checks.
if (object->IsAccessCheckNeeded() || object->IsJSGlobalProxy()) break;
if (deferred_string_key) SerializeDeferredKey(comma, key);
+ if (object->IsJSProxy()) {
+ return SerializeJSProxy(Handle<JSProxy>::cast(object));
+ }
return SerializeJSObject(Handle<JSObject>::cast(object));
}
}
@@ -494,7 +499,7 @@ BasicJsonStringifier::Result BasicJsonStringifier::SerializeJSArray(
for (uint32_t i = 0; i < length; i++) {
if (object->length() != *old_length ||
object->GetElementsKind() != FAST_ELEMENTS) {
- Result result = SerializeJSArraySlow(object, i, length);
+ Result result = SerializeArrayLikeSlow(object, i, length);
if (result != SUCCESS) return result;
break;
}
@@ -516,7 +521,7 @@ BasicJsonStringifier::Result BasicJsonStringifier::SerializeJSArray(
// The FAST_HOLEY_* cases could be handled in a faster way. They resemble
// the non-holey cases except that a lookup is necessary for holes.
default: {
- Result result = SerializeJSArraySlow(object, 0, length);
+ Result result = SerializeArrayLikeSlow(object, 0, length);
if (result != SUCCESS) return result;
break;
}
@@ -528,9 +533,8 @@ BasicJsonStringifier::Result BasicJsonStringifier::SerializeJSArray(
return SUCCESS;
}
-
-BasicJsonStringifier::Result BasicJsonStringifier::SerializeJSArraySlow(
- Handle<JSArray> object, uint32_t start, uint32_t length) {
+BasicJsonStringifier::Result BasicJsonStringifier::SerializeArrayLikeSlow(
+ Handle<JSReceiver> object, uint32_t start, uint32_t length) {
for (uint32_t i = start; i < length; i++) {
Separator(i == 0);
Handle<Object> element;
@@ -552,7 +556,6 @@ BasicJsonStringifier::Result BasicJsonStringifier::SerializeJSArraySlow(
return SUCCESS;
}
-
BasicJsonStringifier::Result BasicJsonStringifier::SerializeJSObject(
Handle<JSObject> object) {
HandleScope handle_scope(isolate_);
@@ -560,15 +563,17 @@ BasicJsonStringifier::Result BasicJsonStringifier::SerializeJSObject(
if (stack_push != SUCCESS) return stack_push;
DCHECK(!object->IsJSGlobalProxy() && !object->IsJSGlobalObject());
- builder_.AppendCharacter('{');
- Indent();
- bool comma = false;
-
- if (object->HasFastProperties() &&
- !object->HasIndexedInterceptor() &&
- !object->HasNamedInterceptor() &&
- object->elements()->length() == 0) {
- Handle<Map> map(object->map());
+ if (object->map()->instance_type() > LAST_CUSTOM_ELEMENTS_RECEIVER &&
+ object->HasFastProperties() &&
+ Handle<JSObject>::cast(object)->elements()->length() == 0) {
+ DCHECK(object->IsJSObject());
+ Handle<JSObject> js_obj = Handle<JSObject>::cast(object);
+ DCHECK(!js_obj->HasIndexedInterceptor());
+ DCHECK(!js_obj->HasNamedInterceptor());
+ Handle<Map> map(js_obj->map());
+ builder_.AppendCharacter('{');
+ Indent();
+ bool comma = false;
for (int i = 0; i < map->NumberOfOwnDescriptors(); i++) {
Handle<Name> name(map->instance_descriptors()->GetKey(i), isolate_);
// TODO(rossberg): Should this throw?
@@ -577,60 +582,104 @@ BasicJsonStringifier::Result BasicJsonStringifier::SerializeJSObject(
PropertyDetails details = map->instance_descriptors()->GetDetails(i);
if (details.IsDontEnum()) continue;
Handle<Object> property;
- if (details.type() == DATA && *map == object->map()) {
+ if (details.type() == DATA && *map == js_obj->map()) {
FieldIndex field_index = FieldIndex::ForDescriptor(*map, i);
- Isolate* isolate = object->GetIsolate();
- if (object->IsUnboxedDoubleField(field_index)) {
- double value = object->RawFastDoublePropertyAt(field_index);
- property = isolate->factory()->NewHeapNumber(value);
-
+ if (js_obj->IsUnboxedDoubleField(field_index)) {
+ double value = js_obj->RawFastDoublePropertyAt(field_index);
+ property = isolate_->factory()->NewHeapNumber(value);
} else {
- property = handle(object->RawFastPropertyAt(field_index), isolate);
+ property = handle(js_obj->RawFastPropertyAt(field_index), isolate_);
}
} else {
ASSIGN_RETURN_ON_EXCEPTION_VALUE(
- isolate_, property,
- Object::GetPropertyOrElement(object, key),
+ isolate_, property, Object::GetPropertyOrElement(js_obj, key),
EXCEPTION);
}
Result result = SerializeProperty(property, comma, key);
if (!comma && result == SUCCESS) comma = true;
if (result == EXCEPTION) return result;
}
+ Unindent();
+ if (comma) NewLine();
+ builder_.AppendCharacter('}');
} else {
- Handle<FixedArray> contents;
- ASSIGN_RETURN_ON_EXCEPTION_VALUE(
- isolate_, contents,
- JSReceiver::GetKeys(object, OWN_ONLY, ENUMERABLE_STRINGS), EXCEPTION);
-
- for (int i = 0; i < contents->length(); i++) {
- Object* key = contents->get(i);
- Handle<String> key_handle;
- MaybeHandle<Object> maybe_property;
- if (key->IsString()) {
- key_handle = Handle<String>(String::cast(key), isolate_);
- maybe_property = Object::GetPropertyOrElement(object, key_handle);
+ Result result = SerializeJSReceiverSlow(object);
+ if (result != SUCCESS) return result;
+ }
+ StackPop();
+ return SUCCESS;
+}
+
+BasicJsonStringifier::Result BasicJsonStringifier::SerializeJSReceiverSlow(
+ Handle<JSReceiver> object) {
+ Handle<FixedArray> contents;
+ ASSIGN_RETURN_ON_EXCEPTION_VALUE(
+ isolate_, contents,
+ JSReceiver::GetKeys(object, OWN_ONLY, ENUMERABLE_STRINGS), EXCEPTION);
+
+ builder_.AppendCharacter('{');
+ Indent();
+ bool comma = false;
+ for (int i = 0; i < contents->length(); i++) {
+ Object* key = contents->get(i);
+ Handle<String> key_handle;
+ MaybeHandle<Object> maybe_property;
+ if (key->IsString()) {
+ key_handle = Handle<String>(String::cast(key), isolate_);
+ maybe_property = Object::GetPropertyOrElement(object, key_handle);
+ } else {
+ DCHECK(key->IsNumber());
+ key_handle = factory()->NumberToString(Handle<Object>(key, isolate_));
+ if (key->IsSmi()) {
+ maybe_property =
+ JSReceiver::GetElement(isolate_, object, Smi::cast(key)->value());
} else {
- DCHECK(key->IsNumber());
- key_handle = factory()->NumberToString(Handle<Object>(key, isolate_));
- if (key->IsSmi()) {
- maybe_property =
- JSReceiver::GetElement(isolate_, object, Smi::cast(key)->value());
- } else {
- maybe_property = Object::GetPropertyOrElement(object, key_handle);
- }
+ maybe_property = Object::GetPropertyOrElement(object, key_handle);
}
- Handle<Object> property;
- ASSIGN_RETURN_ON_EXCEPTION_VALUE(
- isolate_, property, maybe_property, EXCEPTION);
- Result result = SerializeProperty(property, comma, key_handle);
- if (!comma && result == SUCCESS) comma = true;
- if (result == EXCEPTION) return result;
}
+ Handle<Object> property;
+ ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate_, property, maybe_property,
+ EXCEPTION);
+ Result result = SerializeProperty(property, comma, key_handle);
+ if (!comma && result == SUCCESS) comma = true;
+ if (result == EXCEPTION) return result;
}
Unindent();
if (comma) NewLine();
builder_.AppendCharacter('}');
+ return SUCCESS;
+}
+
+BasicJsonStringifier::Result BasicJsonStringifier::SerializeJSProxy(
+ Handle<JSProxy> object) {
+ Result stack_push = StackPush(object);
+ if (stack_push != SUCCESS) return stack_push;
+ Maybe<bool> is_array = Object::IsArray(object);
+ if (is_array.IsNothing()) return EXCEPTION;
+ if (is_array.FromJust()) {
+ Handle<Object> length_object;
+ ASSIGN_RETURN_ON_EXCEPTION_VALUE(
+ isolate_, length_object,
+ Object::GetLengthFromArrayLike(isolate_, object), EXCEPTION);
+ uint32_t length;
+ if (!length_object->ToUint32(&length)) {
+ // Technically, we need to be able to handle lengths outside the
+ // uint32_t range. However, we would run into string size overflow
+ // if we tried to stringify such an array.
+ isolate_->Throw(*isolate_->factory()->NewInvalidStringLengthError());
+ return EXCEPTION;
+ }
+ builder_.AppendCharacter('[');
+ Indent();
+ Result result = SerializeArrayLikeSlow(object, 0, length);
+ if (result != SUCCESS) return result;
+ Unindent();
+ if (length > 0) NewLine();
+ builder_.AppendCharacter(']');
+ } else {
+ Result result = SerializeJSReceiverSlow(object);
+ if (result != SUCCESS) return result;
+ }
StackPop();
return SUCCESS;
}
« no previous file with comments | « src/js/json.js ('k') | src/objects.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698