Changeset 208123 in webkit
- Timestamp:
- Oct 30, 2016 2:14:37 AM (7 years ago)
- Location:
- trunk
- Files:
-
- 1 added
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/JSTests/ChangeLog
r208117 r208123 1 2016-10-29 Yusuke Suzuki <utatane.tea@gmail.com> 2 3 [JSC] JSON.stringify should handle Proxy which is non JSArray but isArray is true 4 https://bugs.webkit.org/show_bug.cgi?id=164123 5 6 Reviewed by Mark Lam. 7 8 * stress/json-stringify-with-non-jsarray-array.js: Added. 9 (shouldBe): 10 (shouldBe.JSON.stringify.new.Proxy): 11 1 12 2016-10-29 Saam Barati <sbarati@apple.com> 2 13 -
trunk/Source/JavaScriptCore/ChangeLog
r208117 r208123 1 2016-10-29 Yusuke Suzuki <utatane.tea@gmail.com> 2 3 [JSC] JSON.stringify should handle Proxy which is non JSArray but isArray is true 4 https://bugs.webkit.org/show_bug.cgi?id=164123 5 6 Reviewed by Mark Lam. 7 8 When JSON.stringify encounter the undefined value, the result depends 9 on the context. If it is produced under the object property context, we ignore 10 that property. On the other hand, if it is produced under the array element 11 context, we produce "null". 12 13 For example, 14 // https://tc39.github.io/ecma262/#sec-serializejsonobject section 8.b. 15 // Skip the property that value is undefined. 16 JSON.stringify({ value: undefined }); // => "{}" 17 18 // https://tc39.github.io/ecma262/#sec-serializejsonarray section 8.b. 19 // Write "null" when the element is undefined. 20 JSON.stringify([undefined]); // => "[null]" 21 22 At that time, we decide the context based on the `holder->inherits(JSArray::info())`. 23 But it is not correct since we have a holder that creates the array element context 24 but it is not JSArray subtype. ES6 Proxy to an array is one example. In that case, 25 `isArray(exec, proxy)` returns `true`, but `inherits(JSArray::info())` returns false. 26 Since we already have this `isArray()` value in Stringifier::Holder, we should reuse 27 this here. And this is the correct behavior in the ES6 spec. 28 29 * runtime/JSONObject.cpp: 30 (JSC::Stringifier::Holder::isArray): 31 (JSC::Stringifier::stringify): 32 (JSC::Stringifier::appendStringifiedValue): 33 (JSC::Stringifier::Holder::Holder): 34 (JSC::Stringifier::Holder::appendNextProperty): 35 1 36 2016-10-29 Saam Barati <sbarati@apple.com> 2 37 -
trunk/Source/JavaScriptCore/runtime/JSONObject.cpp
r207785 r208123 94 94 class Holder { 95 95 public: 96 enum RootHolderTag { RootHolder }; 96 97 Holder(VM&, ExecState*, JSObject*); 98 Holder(RootHolderTag, VM&, JSObject*); 97 99 98 100 JSObject* object() const { return m_object.get(); } 101 bool isArray() const { return m_isArray; } 99 102 100 103 bool appendNextProperty(Stringifier&, StringBuilder&); … … 103 106 Local<JSObject> m_object; 104 107 const bool m_isArray; 105 bool m_isJSArray;108 const bool m_isJSArray; 106 109 unsigned m_index; 107 110 unsigned m_size; … … 115 118 116 119 enum StringifyResult { StringifyFailed, StringifySucceeded, StringifyFailedDueToUndefinedOrSymbolValue }; 117 StringifyResult appendStringifiedValue(StringBuilder&, JSValue, JSObject* holder, const PropertyNameForFunctionCall&);120 StringifyResult appendStringifiedValue(StringBuilder&, JSValue, const Holder&, const PropertyNameForFunctionCall&); 118 121 119 122 bool willIndent() const; … … 260 263 261 264 StringBuilder result; 262 if (appendStringifiedValue(result, value.get(), object, emptyPropertyName) != StringifySucceeded) 265 Holder root(Holder::RootHolder, vm, object); 266 if (appendStringifiedValue(result, value.get(), root, emptyPropertyName) != StringifySucceeded) 263 267 return Local<Unknown>(vm, jsUndefined()); 264 268 RETURN_IF_EXCEPTION(scope, Local<Unknown>(vm, jsNull())); … … 297 301 } 298 302 299 Stringifier::StringifyResult Stringifier::appendStringifiedValue(StringBuilder& builder, JSValue value, JSObject*holder, const PropertyNameForFunctionCall& propertyName)303 Stringifier::StringifyResult Stringifier::appendStringifiedValue(StringBuilder& builder, JSValue value, const Holder& holder, const PropertyNameForFunctionCall& propertyName) 300 304 { 301 305 VM& vm = m_exec->vm(); … … 311 315 args.append(propertyName.value(m_exec)); 312 316 args.append(value); 313 value = call(m_exec, m_replacer.get(), m_replacerCallType, m_replacerCallData, holder , args);317 value = call(m_exec, m_replacer.get(), m_replacerCallType, m_replacerCallData, holder.object(), args); 314 318 RETURN_IF_EXCEPTION(scope, StringifyFailed); 315 319 } 316 320 317 if ((value.isUndefined() || value.isSymbol()) && !holder ->inherits(JSArray::info()))321 if ((value.isUndefined() || value.isSymbol()) && !holder.isArray()) 318 322 return StringifyFailedDueToUndefinedOrSymbolValue; 319 323 … … 360 364 CallData callData; 361 365 if (object->methodTable()->getCallData(object, callData) != CallType::None) { 362 if (holder ->inherits(JSArray::info())) {366 if (holder.isArray()) { 363 367 builder.appendLiteral("null"); 364 368 return StringifySucceeded; … … 420 424 inline Stringifier::Holder::Holder(VM& vm, ExecState* exec, JSObject* object) 421 425 : m_object(vm, object) 422 , m_isArray(isArray(exec, object)) 426 , m_isArray(JSC::isArray(exec, object)) 427 , m_isJSArray(m_isArray && isJSArray(object)) 423 428 , m_index(0) 424 429 #ifndef NDEBUG … … 428 433 } 429 434 435 inline Stringifier::Holder::Holder(RootHolderTag, VM& vm, JSObject* object) 436 : m_object(vm, object) 437 , m_isArray(false) 438 , m_isJSArray(false) 439 , m_index(0) 440 #ifndef NDEBUG 441 , m_size(0) 442 #endif 443 { 444 } 445 430 446 bool Stringifier::Holder::appendNextProperty(Stringifier& stringifier, StringBuilder& builder) 431 447 { … … 439 455 if (!m_index) { 440 456 if (m_isArray) { 441 m_isJSArray = isJSArray(m_object.get());442 457 if (m_isJSArray) 443 458 m_size = asArray(m_object.get())->length(); 444 else 459 else { 445 460 m_size = m_object->get(exec, vm.propertyNames->length).toUInt32(exec); 461 RETURN_IF_EXCEPTION(scope, false); 462 } 446 463 builder.append('['); 447 464 } else { … … 493 510 494 511 // Append the stringified value. 495 stringifyResult = stringifier.appendStringifiedValue(builder, value, m_object.get(), index); 512 stringifyResult = stringifier.appendStringifiedValue(builder, value, *this, index); 513 ASSERT(stringifyResult != StringifyFailedDueToUndefinedOrSymbolValue); 496 514 } else { 497 515 // Get the value. … … 517 535 518 536 // Append the stringified value. 519 stringifyResult = stringifier.appendStringifiedValue(builder, value, m_object.get(), propertyName);537 stringifyResult = stringifier.appendStringifiedValue(builder, value, *this, propertyName); 520 538 } 521 539
Note: See TracChangeset
for help on using the changeset viewer.