Modified: trunk/JSTests/ChangeLog (258048 => 258049)
--- trunk/JSTests/ChangeLog 2020-03-07 02:25:29 UTC (rev 258048)
+++ trunk/JSTests/ChangeLog 2020-03-07 03:02:43 UTC (rev 258049)
@@ -1,3 +1,14 @@
+2020-03-06 Alexey Shvayka <shvaikal...@gmail.com>
+
+ JSON.stringify should call replacer on deleted properties
+ https://bugs.webkit.org/show_bug.cgi?id=208725
+
+ Reviewed by Ross Kirsling.
+
+ * microbenchmarks/json-stringify-many-objects-to-json.js: Added.
+ * microbenchmarks/json-stringify-many-objects.js: Added.
+ * test262/expectations.yaml: Mark 2 test cases as passing.
+
2020-03-04 Mark Lam <mark....@apple.com>
Handle an out of memory error while constructing the BytecodeGenerator.
Added: trunk/JSTests/microbenchmarks/json-stringify-many-objects-to-json.js (0 => 258049)
--- trunk/JSTests/microbenchmarks/json-stringify-many-objects-to-json.js (rev 0)
+++ trunk/JSTests/microbenchmarks/json-stringify-many-objects-to-json.js 2020-03-07 03:02:43 UTC (rev 258049)
@@ -0,0 +1,6 @@
+const toJSON = () => '';
+const value = {};
+for (let i = 0; i < 100; ++i)
+ value[i] = {toJSON};
+for (let i = 0; i < 1e5 / 4; ++i)
+ JSON.stringify(value);
Added: trunk/JSTests/microbenchmarks/json-stringify-many-objects.js (0 => 258049)
--- trunk/JSTests/microbenchmarks/json-stringify-many-objects.js (rev 0)
+++ trunk/JSTests/microbenchmarks/json-stringify-many-objects.js 2020-03-07 03:02:43 UTC (rev 258049)
@@ -0,0 +1,5 @@
+const value = {};
+for (let i = 0; i < 100; ++i)
+ value[i] = {};
+for (let i = 0; i < 1e5 / 4; ++i)
+ JSON.stringify(value);
Modified: trunk/JSTests/test262/expectations.yaml (258048 => 258049)
--- trunk/JSTests/test262/expectations.yaml 2020-03-07 02:25:29 UTC (rev 258048)
+++ trunk/JSTests/test262/expectations.yaml 2020-03-07 03:02:43 UTC (rev 258049)
@@ -1095,9 +1095,6 @@
test/built-ins/JSON/parse/reviver-object-non-configurable-prop-create.js:
default: 'Test262Error: Expected SameValue(«22», «2») to be true'
strict mode: 'Test262Error: Expected SameValue(«22», «2») to be true'
-test/built-ins/JSON/stringify/replacer-function-object-deleted-property.js:
- default: 'Test262Error: Expected SameValue(«{"a":1}», «{"a":1,"b":"<replaced>"}») to be true'
- strict mode: 'Test262Error: Expected SameValue(«{"a":1}», «{"a":1,"b":"<replaced>"}») to be true'
test/built-ins/Map/proto-from-ctor-realm.js:
default: 'Test262Error: Expected SameValue(«[object Map]», «[object Map]») to be true'
strict mode: 'Test262Error: Expected SameValue(«[object Map]», «[object Map]») to be true'
Modified: trunk/Source/_javascript_Core/ChangeLog (258048 => 258049)
--- trunk/Source/_javascript_Core/ChangeLog 2020-03-07 02:25:29 UTC (rev 258048)
+++ trunk/Source/_javascript_Core/ChangeLog 2020-03-07 03:02:43 UTC (rev 258049)
@@ -1,3 +1,24 @@
+2020-03-06 Alexey Shvayka <shvaikal...@gmail.com>
+
+ JSON.stringify should call replacer on deleted properties
+ https://bugs.webkit.org/show_bug.cgi?id=208725
+
+ Reviewed by Ross Kirsling.
+
+ This change removes extra `hasProperty` check from `appendNextProperty` as
+ it does not exist in the spec [1], aligning JSC with V8 and SpiderMonkey.
+
+ This patch also replaces 3 usages of `getPropertySlot` with semantically
+ equivalent (yet more concise) `get` and inlines `toJSONImpl` (this change
+ is performance-neutral).
+
+ [1]: https://tc39.es/ecma262/#sec-serializejsonobject (steps 6, 8.a)
+
+ * runtime/JSONObject.cpp:
+ (JSC::Stringifier::toJSON):
+ (JSC::Stringifier::Holder::appendNextProperty):
+ (JSC::Stringifier::toJSONImpl): Deleted.
+
2020-03-06 Mark Lam <mark....@apple.com>
Fix some issues in the ARM64 moveConditionallyAfterFloatingPointCompare() and moveDoubleConditionallyAfterFloatingPointCompare().
Modified: trunk/Source/_javascript_Core/runtime/JSONObject.cpp (258048 => 258049)
--- trunk/Source/_javascript_Core/runtime/JSONObject.cpp 2020-03-07 02:25:29 UTC (rev 258048)
+++ trunk/Source/_javascript_Core/runtime/JSONObject.cpp 2020-03-07 03:02:43 UTC (rev 258049)
@@ -113,7 +113,6 @@
friend class Holder;
JSValue toJSON(JSValue, const PropertyNameForFunctionCall&);
- JSValue toJSONImpl(VM&, JSValue, JSValue toJSONFunction, const PropertyNameForFunctionCall&);
enum StringifyResult { StringifyFailed, StringifySucceeded, StringifyFailedDueToUndefinedOrSymbolValue };
StringifyResult appendStringifiedValue(StringBuilder&, JSValue, const Holder&, const PropertyNameForFunctionCall&);
@@ -302,19 +301,9 @@
auto scope = DECLARE_THROW_SCOPE(vm);
scope.assertNoException();
- PropertySlot slot(baseValue, PropertySlot::InternalMethodType::Get);
- bool hasProperty = baseValue.getPropertySlot(m_globalObject, vm.propertyNames->toJSON, slot);
- EXCEPTION_ASSERT(!scope.exception() || !hasProperty);
- if (!hasProperty)
- return baseValue;
-
- JSValue toJSONFunction = slot.getValue(m_globalObject, vm.propertyNames->toJSON);
+ JSValue toJSONFunction = baseValue.get(m_globalObject, vm.propertyNames->toJSON);
RETURN_IF_EXCEPTION(scope, { });
- RELEASE_AND_RETURN(scope, toJSONImpl(vm, baseValue, toJSONFunction, propertyName));
-}
-JSValue Stringifier::toJSONImpl(VM& vm, JSValue baseValue, JSValue toJSONFunction, const PropertyNameForFunctionCall& propertyName)
-{
CallType callType;
CallData callData;
if (!toJSONFunction.isCallable(vm, callType, callData))
@@ -528,13 +517,7 @@
if (m_isJSArray && m_object->canGetIndexQuickly(index))
value = m_object->getIndexQuickly(index);
else {
- PropertySlot slot(m_object, PropertySlot::InternalMethodType::Get);
- bool hasProperty = m_object->getPropertySlot(globalObject, index, slot);
- EXCEPTION_ASSERT(!scope.exception() || !hasProperty);
- if (hasProperty)
- value = slot.getValue(globalObject, index);
- else
- value = jsUndefined();
+ value = m_object->get(globalObject, index);
RETURN_IF_EXCEPTION(scope, false);
}
@@ -548,13 +531,8 @@
ASSERT(stringifyResult != StringifyFailedDueToUndefinedOrSymbolValue);
} else {
// Get the value.
- PropertySlot slot(m_object, PropertySlot::InternalMethodType::Get);
Identifier& propertyName = m_propertyNames->propertyNameVector()[index];
- bool hasProperty = m_object->getPropertySlot(globalObject, propertyName, slot);
- EXCEPTION_ASSERT(!scope.exception() || !hasProperty);
- if (!hasProperty)
- return true;
- JSValue value = slot.getValue(globalObject, propertyName);
+ JSValue value = m_object->get(globalObject, propertyName);
RETURN_IF_EXCEPTION(scope, false);
rollBackPoint = builder.length();