From f88b1576e5a53d773f4fa1bfe18db4f2a2057a07 Mon Sep 17 00:00:00 2001 From: Ben Noordhuis Date: Wed, 18 Nov 2015 18:08:24 +0100 Subject: [PATCH] deps: backport a7e50a5 from upstream v8 PR-URL: https://github.com/nodejs/node-private/pull/6 Reviewed-By: Fedor Indutny --- deps/v8/src/json-stringifier.h | 62 +++++++++++++++++-- .../mjsunit/regress/regress-crbug-554946.js | 49 +++++++++++++++ 2 files changed, 106 insertions(+), 5 deletions(-) diff --git a/deps/v8/src/json-stringifier.h b/deps/v8/src/json-stringifier.h index 0a4101b7dffc08..3bbfb63a658ffe 100644 --- a/deps/v8/src/json-stringifier.h +++ b/deps/v8/src/json-stringifier.h @@ -82,7 +82,8 @@ class BasicJsonStringifier BASE_EMBEDDED { INLINE(Result SerializeJSArray(Handle object)); INLINE(Result SerializeJSObject(Handle object)); - Result SerializeJSArraySlow(Handle object, uint32_t length); + Result SerializeJSArraySlow(Handle object, uint32_t start, + uint32_t length); void SerializeString(Handle object); @@ -434,8 +435,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 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 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 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(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; @@ -443,8 +495,8 @@ BasicJsonStringifier::Result BasicJsonStringifier::SerializeJSArray( BasicJsonStringifier::Result BasicJsonStringifier::SerializeJSArraySlow( - Handle object, uint32_t length) { - for (uint32_t i = 0; i < length; i++) { + Handle object, uint32_t start, uint32_t length) { + for (uint32_t i = start; i < length; i++) { if (i > 0) builder_.AppendCharacter(','); Handle element; ASSIGN_RETURN_ON_EXCEPTION_VALUE( diff --git a/deps/v8/test/mjsunit/regress/regress-crbug-554946.js b/deps/v8/test/mjsunit/regress/regress-crbug-554946.js index ab2e327295818e..fbb79f61b0bac4 100644 --- a/deps/v8/test/mjsunit/regress/regress-crbug-554946.js +++ b/deps/v8/test/mjsunit/regress/regress-crbug-554946.js @@ -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));