Changeset 275544 in webkit
- Timestamp:
- Apr 6, 2021 1:20:41 PM (3 years ago)
- Location:
- trunk
- Files:
-
- 1 added
- 5 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/JSTests/ChangeLog
r275472 r275544 1 2021-04-06 Alexey Shvayka <shvaikalesh@gmail.com> 2 3 Array's toString() is incorrect if join() is non-callable 4 https://bugs.webkit.org/show_bug.cgi?id=224215 5 6 Reviewed by Yusuke Suzuki. 7 8 * stress/array-toString-non-callable-join.js: Added. 9 1 10 2021-04-05 Keith Miller <keith_miller@apple.com> 2 11 -
trunk/Source/JavaScriptCore/ChangeLog
r275542 r275544 1 2021-04-06 Alexey Shvayka <shvaikalesh@gmail.com> 2 3 Array's toString() is incorrect if join() is non-callable 4 https://bugs.webkit.org/show_bug.cgi?id=224215 5 6 Reviewed by Yusuke Suzuki. 7 8 This patch exposes objectPrototypeToString() to be used by Array.prototype.toString 9 if "join" lookup doesn't return a callable value [1]. 10 11 Fixes Array's toString() to return the correct tag instead of internal `className`, 12 perform Symbol.toStringTag lookup, and throw for revoked Proxy objects. 13 Aligns JSC with V8 and SpiderMonkey. 14 15 Also, a few objectPrototypeToString() tweaks: a bit nicer `undefined` / `null` 16 checks and simpler toObject() exception handling. 17 18 [1]: https://tc39.es/ecma262/#sec-array.prototype.tostring (step 3) 19 20 * runtime/ArrayPrototype.cpp: 21 (JSC::JSC_DEFINE_HOST_FUNCTION): 22 * runtime/ObjectPrototype.cpp: 23 (JSC::objectPrototypeToString): 24 (JSC::JSC_DEFINE_HOST_FUNCTION): 25 * runtime/ObjectPrototype.h: 26 1 27 2021-04-06 Yusuke Suzuki <ysuzuki@apple.com> 2 28 -
trunk/Source/JavaScriptCore/runtime/ArrayPrototype.cpp
r272471 r275544 35 35 #include "JSStringJoiner.h" 36 36 #include "ObjectConstructor.h" 37 #include "ObjectPrototype.h" 37 38 #include "StringRecursionChecker.h" 38 39 #include <algorithm> … … 613 614 if (!canUseDefaultArrayJoinForToString(vm, thisObject)) { 614 615 // 2. Let func be the result of calling the [[Get]] internal method of array with argument "join". 615 JSValue function = JSValue(thisObject).get(globalObject, vm.propertyNames->join);616 JSValue function = thisObject->get(globalObject, vm.propertyNames->join); 616 617 RETURN_IF_EXCEPTION(scope, encodedJSValue()); 617 618 618 619 // 3. If IsCallable(func) is false, then let func be the standard built-in method Object.prototype.toString (15.2.4.2). 619 bool customJoinCase = false;620 if (!function.isCell())621 customJoinCase = true;622 620 auto callData = getCallData(vm, function); 623 if (callData.type == CallData::Type::None) 624 customJoinCase = true; 625 626 if (UNLIKELY(customJoinCase)) 627 RELEASE_AND_RETURN(scope, JSValue::encode(jsMakeNontrivialString(globalObject, "[object ", thisObject->methodTable(vm)->className(thisObject, vm), "]"))); 621 if (UNLIKELY(callData.type == CallData::Type::None)) 622 RELEASE_AND_RETURN(scope, JSValue::encode(objectPrototypeToString(globalObject, thisObject))); 628 623 629 624 // 4. Return the result of calling the [[Call]] internal method of func providing array as the this value and an empty arguments list. -
trunk/Source/JavaScriptCore/runtime/ObjectPrototype.cpp
r267594 r275544 312 312 } 313 313 314 JSC_DEFINE_HOST_FUNCTION(objectProtoFuncToString, (JSGlobalObject* globalObject, CallFrame* callFrame)) 315 { 316 VM& vm = globalObject->vm(); 317 auto scope = DECLARE_THROW_SCOPE(vm); 318 319 JSValue thisValue = callFrame->thisValue().toThis(globalObject, ECMAMode::strict()); 320 if (thisValue.isUndefinedOrNull()) 321 return JSValue::encode(thisValue.isUndefined() ? vm.smallStrings.undefinedObjectString() : vm.smallStrings.nullObjectString()); 314 JSString* objectPrototypeToString(JSGlobalObject* globalObject, JSValue thisValue) 315 { 316 VM& vm = globalObject->vm(); 317 auto scope = DECLARE_THROW_SCOPE(vm); 318 319 if (thisValue.isUndefined()) 320 return vm.smallStrings.undefinedObjectString(); 321 if (thisValue.isNull()) 322 return vm.smallStrings.nullObjectString(); 322 323 JSObject* thisObject = thisValue.toObject(globalObject); 323 EXCEPTION_ASSERT(!!scope.exception() == !thisObject); 324 if (!thisObject) 325 return JSValue::encode(jsUndefined()); 324 scope.assertNoException(); 326 325 327 326 Integrity::auditStructureID(vm, thisObject->structureID()); 328 327 auto result = thisObject->structure(vm)->cachedSpecialProperty(CachedSpecialPropertyKey::ToStringTag); 329 328 if (result) 330 return JSValue::encode(result);329 return asString(result); 331 330 332 331 String tag = thisObject->methodTable(vm)->toStringName(thisObject, globalObject); 333 RETURN_IF_EXCEPTION(scope, { });332 RETURN_IF_EXCEPTION(scope, nullptr); 334 333 JSString* jsTag = nullptr; 335 334 … … 339 338 if (hasProperty) { 340 339 JSValue tagValue = slot.getValue(globalObject, vm.propertyNames->toStringTagSymbol); 341 RETURN_IF_EXCEPTION(scope, { });340 RETURN_IF_EXCEPTION(scope, nullptr); 342 341 if (tagValue.isString()) 343 342 jsTag = asString(tagValue); … … 350 349 351 350 JSString* jsResult = jsString(globalObject, vm.smallStrings.objectStringStart(), jsTag, vm.smallStrings.singleCharacterString(']')); 352 RETURN_IF_EXCEPTION(scope, { });351 RETURN_IF_EXCEPTION(scope, nullptr); 353 352 thisObject->structure(vm)->cacheSpecialProperty(globalObject, vm, jsResult, CachedSpecialPropertyKey::ToStringTag, slot); 354 return JSValue::encode(jsResult); 353 return jsResult; 354 } 355 356 JSC_DEFINE_HOST_FUNCTION(objectProtoFuncToString, (JSGlobalObject* globalObject, CallFrame* callFrame)) 357 { 358 JSValue thisValue = callFrame->thisValue().toThis(globalObject, ECMAMode::strict()); 359 return JSValue::encode(objectPrototypeToString(globalObject, thisValue)); 355 360 } 356 361 -
trunk/Source/JavaScriptCore/runtime/ObjectPrototype.h
r267594 r275544 52 52 53 53 JS_EXPORT_PRIVATE JSC_DECLARE_HOST_FUNCTION(objectProtoFuncToString); 54 JSString* objectPrototypeToString(JSGlobalObject*, JSValue thisValue); 54 55 bool objectPrototypeHasOwnProperty(JSGlobalObject*, JSValue base, const Identifier& property); 55 56
Note: See TracChangeset
for help on using the changeset viewer.