deps: backport a7e50a5 from upstream v8
authorBen Noordhuis <info@bnoordhuis.nl>
Wed, 18 Nov 2015 17:12:52 +0000 (18:12 +0100)
committerRod Vagg <rod@vagg.org>
Thu, 3 Dec 2015 11:54:58 +0000 (22:54 +1100)
PR-URL: https://github.com/nodejs/node-private/pull/8
Reviewed-By: Fedor Indutny <fedor@indutny.com>
deps/v8/src/json-stringifier.h
deps/v8/test/mjsunit/regress/regress-crbug-554946.js

index 3214586..69ccf48 100644 (file)
@@ -83,7 +83,8 @@ class BasicJsonStringifier BASE_EMBEDDED {
   INLINE(Result SerializeJSArray(Handle<JSArray> object));
   INLINE(Result SerializeJSObject(Handle<JSObject> object));
 
-  Result SerializeJSArraySlow(Handle<JSArray> object, uint32_t length);
+  Result SerializeJSArraySlow(Handle<JSArray> object, uint32_t start,
+                              uint32_t length);
 
   void SerializeString(Handle<String> object);
 
@@ -440,8 +441,59 @@ BasicJsonStringifier::Result BasicJsonStringifier::SerializeJSArray(
   uint32_t length = 0;
   CHECK(object->length()->ToArrayLength(&length));
   builder_.AppendCharacter('[');
-  Result result = SerializeJSArraySlow(object, length);
-  if (result != SUCCESS) return result;
+  switch (object->GetElementsKind()) {
+    case FAST_SMI_ELEMENTS: {
+      Handle<FixedArray> elements(FixedArray::cast(object->elements()),
+                                  isolate_);
+      for (uint32_t i = 0; i < length; i++) {
+        if (i > 0) builder_.AppendCharacter(',');
+        SerializeSmi(Smi::cast(elements->get(i)));
+      }
+      break;
+    }
+    case FAST_DOUBLE_ELEMENTS: {
+      // Empty array is FixedArray but not FixedDoubleArray.
+      if (length == 0) break;
+      Handle<FixedDoubleArray> elements(
+          FixedDoubleArray::cast(object->elements()), isolate_);
+      for (uint32_t i = 0; i < length; i++) {
+        if (i > 0) builder_.AppendCharacter(',');
+        SerializeDouble(elements->get_scalar(i));
+      }
+      break;
+    }
+    case FAST_ELEMENTS: {
+      Handle<Object> old_length(object->length(), isolate_);
+      for (uint32_t i = 0; i < length; i++) {
+        if (object->length() != *old_length ||
+            object->GetElementsKind() != FAST_ELEMENTS) {
+          Result result = SerializeJSArraySlow(object, i, length);
+          if (result != SUCCESS) return result;
+          break;
+        }
+        if (i > 0) builder_.AppendCharacter(',');
+        Result result = SerializeElement(
+            isolate_,
+            Handle<Object>(FixedArray::cast(object->elements())->get(i),
+                           isolate_),
+            i);
+        if (result == SUCCESS) continue;
+        if (result == UNCHANGED) {
+          builder_.AppendCString("null");
+        } else {
+          return result;
+        }
+      }
+      break;
+    }
+    // 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);
+      if (result != SUCCESS) return result;
+      break;
+    }
+  }
   builder_.AppendCharacter(']');
   StackPop();
   return SUCCESS;
@@ -449,8 +501,8 @@ BasicJsonStringifier::Result BasicJsonStringifier::SerializeJSArray(
 
 
 BasicJsonStringifier::Result BasicJsonStringifier::SerializeJSArraySlow(
-    Handle<JSArray> object, uint32_t length) {
-  for (uint32_t i = 0; i < length; i++) {
+    Handle<JSArray> object, uint32_t start, uint32_t length) {
+  for (uint32_t i = start; i < length; i++) {
     if (i > 0) builder_.AppendCharacter(',');
     Handle<Object> element;
     ASSIGN_RETURN_ON_EXCEPTION_VALUE(
index ab2e327..fbb79f6 100644 (file)
@@ -10,3 +10,52 @@ for (var i = 0; i < 10; i++) array[i] = i;
 array[0] = funky;
 assertEquals('["funky",null,null,null,null,null,null,null,null,null]',
              JSON.stringify(array));
+
+array = [];
+funky = {
+  get value() { array.length = 1; return "funky"; }
+};
+for (var i = 0; i < 10; i++) array[i] = i;
+array[3] = funky;
+assertEquals('[0,1,2,{"value":"funky"},null,null,null,null,null,null]',
+             JSON.stringify(array));
+
+array = [];
+funky = {
+  get value() { array.pop(); return "funky"; }
+};
+for (var i = 0; i < 10; i++) array[i] = i;
+array[3] = funky;
+assertEquals('[0,1,2,{"value":"funky"},4,5,6,7,8,null]', JSON.stringify(array));
+
+array = [];
+funky = {
+  get value() { delete array[9]; return "funky"; }
+};
+for (var i = 0; i < 10; i++) array[i] = i;
+array[3] = funky;
+assertEquals('[0,1,2,{"value":"funky"},4,5,6,7,8,null]', JSON.stringify(array));
+
+array = [];
+funky = {
+  get value() { delete array[6]; return "funky"; }
+};
+for (var i = 0; i < 10; i++) array[i] = i;
+array[3] = funky;
+assertEquals('[0,1,2,{"value":"funky"},4,5,null,7,8,9]', JSON.stringify(array));
+
+array = [];
+funky = {
+  get value() { array[12] = 12; return "funky"; }
+};
+for (var i = 0; i < 10; i++) array[i] = i;
+array[3] = funky;
+assertEquals('[0,1,2,{"value":"funky"},4,5,6,7,8,9]', JSON.stringify(array));
+
+array = [];
+funky = {
+  get value() { array[10000000] = 12; return "funky"; }
+};
+for (var i = 0; i < 10; i++) array[i] = i;
+array[3] = funky;
+assertEquals('[0,1,2,{"value":"funky"},4,5,6,7,8,9]', JSON.stringify(array));