From 6e6a1c8aee16cffdcbbf54f09b73b2b79b2ecedf Mon Sep 17 00:00:00 2001 From: arv Date: Wed, 24 Jun 2015 15:17:52 -0700 Subject: [PATCH] JSON.stringify should use toString of replacer and not valueOf If the replacer array contains a number wrapper we should use the toString result and not valueOf. BUG=v8:4228 LOG=N R=adamk CQ_INCLUDE_TRYBOTS=tryserver.chromium.linux:linux_chromium_rel_ng;tryserver.blink:linux_blink_rel Review URL: https://codereview.chromium.org/1207013002 Cr-Commit-Position: refs/heads/master@{#29270} --- src/json.js | 20 +++++++++++--------- .../mjsunit/json-replacer-number-wrapper-tostring.js | 20 ++++++++++++++++++++ 2 files changed, 31 insertions(+), 9 deletions(-) create mode 100644 test/mjsunit/json-replacer-number-wrapper-tostring.js diff --git a/src/json.js b/src/json.js index 8b5f229..fe820f9 100644 --- a/src/json.js +++ b/src/json.js @@ -208,20 +208,22 @@ function JSONStringify(value, replacer, space) { // Deduplicate replacer array items. var property_list = new InternalArray(); var seen_properties = { __proto__: null }; - var seen_sentinel = {}; var length = replacer.length; for (var i = 0; i < length; i++) { - var item = replacer[i]; - if (IS_STRING_WRAPPER(item)) { - item = $toString(item); + var v = replacer[i]; + var item; + if (IS_STRING(v)) { + item = v; + } else if (IS_NUMBER(v)) { + item = %_NumberToString(v); + } else if (IS_STRING_WRAPPER(v) || IS_NUMBER_WRAPPER(v)) { + item = $toString(v); } else { - if (IS_NUMBER_WRAPPER(item)) item = $toNumber(item); - if (IS_NUMBER(item)) item = %_NumberToString(item); + continue; } - if (IS_STRING(item) && seen_properties[item] != seen_sentinel) { + if (!seen_properties[item]) { property_list.push(item); - // We cannot use true here because __proto__ needs to be an object. - seen_properties[item] = seen_sentinel; + seen_properties[item] = true; } } replacer = property_list; diff --git a/test/mjsunit/json-replacer-number-wrapper-tostring.js b/test/mjsunit/json-replacer-number-wrapper-tostring.js new file mode 100644 index 0000000..b4ef792 --- /dev/null +++ b/test/mjsunit/json-replacer-number-wrapper-tostring.js @@ -0,0 +1,20 @@ +// Copyright 2015 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// http://ecma-international.org/ecma-262/6.0/#sec-json.stringify +// Step 4.b.iii.5.f.i + +var calls = 0; + +var num = new Number; +num.toString = function() { + calls++; + return ''; +}; +num.valueOf = function() { + assertUnreachable(); +}; + +JSON.stringify('', [num]); +assertEquals(1, calls); -- 2.7.4