Title: [261159] trunk
Revision
261159
Author
[email protected]
Date
2020-05-05 04:33:21 -0700 (Tue, 05 May 2020)

Log Message

Object.prototype.toString is not spec-perfect
https://bugs.webkit.org/show_bug.cgi?id=199138

Reviewed by Darin Adler and Keith Miller.

JSTests:

* ChakraCore.yaml: Skip a test as `global` now has @@toStringTag.
* ChakraCore/test/LetConst/delete.baseline: Removed.
* stress/internal-promise-constructor-not-confusing.js: Use @isPromise.
* stress/object-get-own-property-symbols.js: Adjust test as `global` now has @@toStringTag.
* test262/expectations.yaml: Mark 6 test cases as passing.

LayoutTests/imported/w3c:

* web-platform-tests/WebIDL/ecmascript-binding/class-string-interface.any-expected.txt:
* web-platform-tests/WebIDL/ecmascript-binding/class-string-interface.any.worker-expected.txt:
* web-platform-tests/WebIDL/ecmascript-binding/class-string-iterator-prototype-object.any-expected.txt:
* web-platform-tests/WebIDL/ecmascript-binding/class-string-iterator-prototype-object.any.worker-expected.txt:

Source/_javascript_Core:

Before ES6, Object.prototype.toString relied only on internal [[Class]] slot. Starting with ES6,
Object.prototype.toString checks for a handful of internal slots, mimicing [[Class]], to ensure
backwards compatibility for pre-ES6 instances. Newly-added built-ins provide @@toStringTag for
the method to use.

Before this change, Object.prototype.toString in JSC relied on className() a.k.a [[Class]] for
all instances. For (almost all) new built-ins, it was overriden by toStringName() returning
"Object", while @@toStringTag was set to correct value. This is quite an error-prone approach
and observable spec discrepancy if @@toStringTag is deleted or set to a non-string.

This change eliminates the above-mentioned discrepancy and fixes Object.prototype.toString
to return "[object Function]" for callable Proxy objects, aligning JSC with the spec [1], V8,
and SpiderMonkey.

For Object.prototype.toString to work through DebuggerScope and JSProxy, we perform all checks
in JSObject::toStringName(). Given that isArray() may throw a TypeError [2], we invoke
toStringName() before @@toStringTag lookup to accomodate revoked Proxy case.

Also, this patch defines @@toStringTag for WebAssembly namespace object (to match Chrome),
JSC shell, and ConsoleObject.

[1]: https://tc39.es/ecma262/#sec-object.prototype.tostring
[2]: https://tc39.es/ecma262/#sec-isarray (step 3.a)

* jsc.cpp:
* runtime/BigIntObject.cpp:
(JSC::BigIntObject::toStringName): Deleted.
* runtime/BigIntObject.h:
* runtime/BooleanObject.cpp:
(JSC::BooleanObject::toStringName):
* runtime/BooleanObject.h:
* runtime/ConsoleObject.cpp:
(JSC::ConsoleObject::finishCreation):
* runtime/DateInstance.cpp:
(JSC::DateInstance::toStringName):
* runtime/DateInstance.h:
* runtime/ErrorInstance.cpp:
(JSC::ErrorInstance::toStringName):
* runtime/ErrorInstance.h:
* runtime/JSArrayBufferView.cpp:
(JSC::JSArrayBufferView::toStringName): Deleted.
* runtime/JSArrayBufferView.h:
* runtime/JSMap.cpp:
(JSC::JSMap::toStringName): Deleted.
* runtime/JSMap.h:
* runtime/JSObject.cpp:
(JSC::JSObject::toStringName):
* runtime/JSSet.cpp:
(JSC::JSSet::toStringName): Deleted.
* runtime/JSSet.h:
* runtime/JSWeakMap.cpp:
(JSC::JSWeakMap::toStringName): Deleted.
* runtime/JSWeakMap.h:
* runtime/JSWeakObjectRef.cpp:
(JSC::JSWeakObjectRef::toStringName): Deleted.
* runtime/JSWeakObjectRef.h:
* runtime/JSWeakSet.cpp:
(JSC::JSWeakSet::toStringName): Deleted.
* runtime/JSWeakSet.h:
* runtime/NumberObject.cpp:
(JSC::NumberObject::toStringName):
* runtime/NumberObject.h:
* runtime/ObjectPrototype.cpp:
(JSC::objectProtoFuncToString):
* runtime/ProxyObject.cpp:
(JSC::ProxyObject::toStringName): Deleted.
* runtime/ProxyObject.h:
* runtime/RegExpObject.cpp:
(JSC::RegExpObject::toStringName):
* runtime/RegExpObject.h:
* runtime/StringObject.cpp:
(JSC::StringObject::toStringName):
* runtime/StringObject.h:
* runtime/SymbolObject.cpp:
(JSC::SymbolObject::toStringName): Deleted.
* runtime/SymbolObject.h:
* wasm/js/JSWebAssembly.cpp:
(JSC::JSWebAssembly::finishCreation):

Source/WebCore:

This patch defines @@toStringTag symbols for all WebIDL prototypes, including
interfaces that are not exposed, as required by the spec [1].

With updated JSObject::toStringName() and @@toStringTag symbols added in r260992,
className() and toStringName() methods of JSDOMConstructorBase can be safely removed.

[1]: https://heycam.github.io/webidl/#dfn-class-string

Tests: imported/w3c/web-platform-tests/WebIDL/ecmascript-binding/class-string-interface.any.js
       imported/w3c/web-platform-tests/WebIDL/ecmascript-binding/class-string-iterator-prototype-object.any.js

* bindings/js/JSDOMConstructorBase.cpp:
(WebCore::JSDOMConstructorBase::className): Deleted.
(WebCore::JSDOMConstructorBase::toStringName): Deleted.
* bindings/js/JSDOMConstructorBase.h:
* bindings/scripts/CodeGeneratorJS.pm:
(GenerateImplementation):
(GeneratePrototypeDeclaration):
* bindings/scripts/test/JS/JSTestGlobalObject.cpp:
(WebCore::JSTestGlobalObjectPrototype::finishCreation):

Tools:

* TestWebKitAPI/Tests/_javascript_Core/glib/TestJSC.cpp:

Modified Paths

Removed Paths

Diff

Deleted: trunk/JSTests/ChakraCore/test/LetConst/delete.baseline (261158 => 261159)


--- trunk/JSTests/ChakraCore/test/LetConst/delete.baseline	2020-05-05 09:45:11 UTC (rev 261158)
+++ trunk/JSTests/ChakraCore/test/LetConst/delete.baseline	2020-05-05 11:33:21 UTC (rev 261159)
@@ -1,4 +0,0 @@
-20
-let x
-let x
-PASS

Modified: trunk/JSTests/ChakraCore.yaml (261158 => 261159)


--- trunk/JSTests/ChakraCore.yaml	2020-05-05 09:45:11 UTC (rev 261158)
+++ trunk/JSTests/ChakraCore.yaml	2020-05-05 11:33:21 UTC (rev 261159)
@@ -817,7 +817,8 @@
 - path: ChakraCore/test/LetConst/defer5.js
   cmd: runChakra :baseline, "ReferenceError", "defer5.baseline-jsc", []
 - path: ChakraCore/test/LetConst/delete.js
-  cmd: runChakra :baseline, "NoException", "delete.baseline", []
+  # The test should use Reflect.ownKeys as `this` may have symbol properties.
+  cmd: runChakra :skipDueToOutdatedOrBadTest, "NoException", "", []
 - path: ChakraCore/test/LetConst/dop.js
   cmd: runChakra :baseline, "NoException", "dop.baseline-jsc", []
 - path: ChakraCore/test/LetConst/dop1.js

Modified: trunk/JSTests/ChangeLog (261158 => 261159)


--- trunk/JSTests/ChangeLog	2020-05-05 09:45:11 UTC (rev 261158)
+++ trunk/JSTests/ChangeLog	2020-05-05 11:33:21 UTC (rev 261159)
@@ -1,3 +1,16 @@
+2020-05-05  Alexey Shvayka  <[email protected]>
+
+        Object.prototype.toString is not spec-perfect
+        https://bugs.webkit.org/show_bug.cgi?id=199138
+
+        Reviewed by Darin Adler and Keith Miller.
+
+        * ChakraCore.yaml: Skip a test as `global` now has @@toStringTag.
+        * ChakraCore/test/LetConst/delete.baseline: Removed.
+        * stress/internal-promise-constructor-not-confusing.js: Use @isPromise.
+        * stress/object-get-own-property-symbols.js: Adjust test as `global` now has @@toStringTag.
+        * test262/expectations.yaml: Mark 6 test cases as passing.
+
 2020-05-04  Yusuke Suzuki  <[email protected]>
 
         [JSC] Implement BigInt.asIntN and BigInt.asUintN

Modified: trunk/JSTests/stress/internal-promise-constructor-not-confusing.js (261158 => 261159)


--- trunk/JSTests/stress/internal-promise-constructor-not-confusing.js	2020-05-05 09:45:11 UTC (rev 261158)
+++ trunk/JSTests/stress/internal-promise-constructor-not-confusing.js	2020-05-05 11:33:21 UTC (rev 261159)
@@ -7,19 +7,26 @@
     return @InternalPromise;
 })`)();
 
+var isPromise = $vm.createBuiltin(`(function (p) {
+    return @isPromise(p);
+})`);
+
 function DerivedPromise() { }
 
 for (var i = 0; i < 1e4; ++i) {
     var promise = Reflect.construct(InternalPromise, [function (resolve) { resolve(42); }], DerivedPromise);
-    shouldBe(promise.toString(), `[object InternalPromise]`);
+    shouldBe(promise.toString(), `[object Object]`);
+    shouldBe(isPromise(promise), true);
 }
 drainMicrotasks();
 for (var i = 0; i < 1e4; ++i) {
     var promise = Reflect.construct(Promise, [function (resolve) { resolve(42); }], DerivedPromise);
-    shouldBe(promise.toString(), `[object Promise]`);
+    shouldBe(promise.toString(), `[object Object]`);
+    shouldBe(isPromise(promise), true);
 }
 drainMicrotasks();
 for (var i = 0; i < 1e4; ++i) {
     var promise = Reflect.construct(InternalPromise, [function (resolve) { resolve(42); }], DerivedPromise);
-    shouldBe(promise.toString(), `[object InternalPromise]`);
+    shouldBe(promise.toString(), `[object Object]`);
+    shouldBe(isPromise(promise), true);
 }

Modified: trunk/JSTests/stress/object-get-own-property-symbols.js (261158 => 261159)


--- trunk/JSTests/stress/object-get-own-property-symbols.js	2020-05-05 09:45:11 UTC (rev 261158)
+++ trunk/JSTests/stress/object-get-own-property-symbols.js	2020-05-05 11:33:21 UTC (rev 261159)
@@ -3,8 +3,9 @@
 var global = (Function("return this")());
 
 // private names for privileged code should not be exposed.
-if (Object.getOwnPropertySymbols(global).length !== 0)
-    throw "Error: bad value " + Object.getOwnPropertySymbols(global).length;
+var globalSymbols = Object.getOwnPropertySymbols(global).filter(s => s !== Symbol.toStringTag);
+if (globalSymbols.length !== 0)
+    throw "Error: bad value " + globalSymbols.length;
 
 var object = {};
 var symbol = Symbol("Cocoa");

Modified: trunk/JSTests/test262/expectations.yaml (261158 => 261159)


--- trunk/JSTests/test262/expectations.yaml	2020-05-05 09:45:11 UTC (rev 261158)
+++ trunk/JSTests/test262/expectations.yaml	2020-05-05 11:33:21 UTC (rev 261159)
@@ -970,15 +970,6 @@
 test/built-ins/Object/keys/order-after-define-property.js:
   default: 'Test262Error: Expected [b, a] and [a, b] to have the same contents. '
   strict mode: 'Test262Error: Expected [b, a] and [a, b] to have the same contents. '
-test/built-ins/Object/prototype/toString/proxy-function.js:
-  default: 'Test262Error: function proxy Expected SameValue(«[object Object]», «[object Function]») to be true'
-  strict mode: 'Test262Error: function proxy Expected SameValue(«[object Object]», «[object Function]») to be true'
-test/built-ins/Object/prototype/toString/symbol-tag-non-str-builtin.js:
-  default: 'Test262Error: Expected SameValue(«[object Math]», «[object Object]») to be true'
-  strict mode: 'Test262Error: Expected SameValue(«[object Math]», «[object Object]») to be true'
-test/built-ins/Object/prototype/toString/symbol-tag-non-str-proxy-function.js:
-  default: 'Test262Error: generator function proxy without Symbol.toStringTag Expected SameValue(«[object Object]», «[object Function]») to be true'
-  strict mode: 'Test262Error: generator function proxy without Symbol.toStringTag Expected SameValue(«[object Object]», «[object Function]») to be true'
 test/built-ins/Object/values/order-after-define-property.js:
   default: 'Test262Error: Expected [b, a] and [a, b] to have the same contents. '
   strict mode: 'Test262Error: Expected [b, a] and [a, b] to have the same contents. '

Modified: trunk/LayoutTests/imported/w3c/ChangeLog (261158 => 261159)


--- trunk/LayoutTests/imported/w3c/ChangeLog	2020-05-05 09:45:11 UTC (rev 261158)
+++ trunk/LayoutTests/imported/w3c/ChangeLog	2020-05-05 11:33:21 UTC (rev 261159)
@@ -1,3 +1,15 @@
+2020-05-05  Alexey Shvayka  <[email protected]>
+
+        Object.prototype.toString is not spec-perfect
+        https://bugs.webkit.org/show_bug.cgi?id=199138
+
+        Reviewed by Darin Adler and Keith Miller.
+
+        * web-platform-tests/WebIDL/ecmascript-binding/class-string-interface.any-expected.txt:
+        * web-platform-tests/WebIDL/ecmascript-binding/class-string-interface.any.worker-expected.txt:
+        * web-platform-tests/WebIDL/ecmascript-binding/class-string-iterator-prototype-object.any-expected.txt:
+        * web-platform-tests/WebIDL/ecmascript-binding/class-string-iterator-prototype-object.any.worker-expected.txt:
+
 2020-05-04  Yusuke Suzuki  <[email protected]>
 
         [JSC] Add @@toStringTag to WebAssembly.Global

Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/WebIDL/ecmascript-binding/class-string-interface.any-expected.txt (261158 => 261159)


--- trunk/LayoutTests/imported/w3c/web-platform-tests/WebIDL/ecmascript-binding/class-string-interface.any-expected.txt	2020-05-05 09:45:11 UTC (rev 261158)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/WebIDL/ecmascript-binding/class-string-interface.any-expected.txt	2020-05-05 11:33:21 UTC (rev 261159)
@@ -5,6 +5,6 @@
 PASS Object.prototype.toString applied to an instance 
 PASS Object.prototype.toString applied after modifying the prototype's @@toStringTag 
 PASS Object.prototype.toString applied to the instance after modifying the instance's @@toStringTag 
-FAIL Object.prototype.toString applied to a null-prototype instance assert_equals: expected "[object Object]" but got "[object Blob]"
-FAIL Object.prototype.toString applied after deleting @@toStringTag assert_equals: prototype expected "[object Object]" but got "[object Blob]"
+PASS Object.prototype.toString applied to a null-prototype instance 
+PASS Object.prototype.toString applied after deleting @@toStringTag 
 

Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/WebIDL/ecmascript-binding/class-string-interface.any.worker-expected.txt (261158 => 261159)


--- trunk/LayoutTests/imported/w3c/web-platform-tests/WebIDL/ecmascript-binding/class-string-interface.any.worker-expected.txt	2020-05-05 09:45:11 UTC (rev 261158)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/WebIDL/ecmascript-binding/class-string-interface.any.worker-expected.txt	2020-05-05 11:33:21 UTC (rev 261159)
@@ -5,6 +5,6 @@
 PASS Object.prototype.toString applied to an instance 
 PASS Object.prototype.toString applied after modifying the prototype's @@toStringTag 
 PASS Object.prototype.toString applied to the instance after modifying the instance's @@toStringTag 
-FAIL Object.prototype.toString applied to a null-prototype instance assert_equals: expected "[object Object]" but got "[object Blob]"
-FAIL Object.prototype.toString applied after deleting @@toStringTag assert_equals: prototype expected "[object Object]" but got "[object Blob]"
+PASS Object.prototype.toString applied to a null-prototype instance 
+PASS Object.prototype.toString applied after deleting @@toStringTag 
 

Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/WebIDL/ecmascript-binding/class-string-iterator-prototype-object.any-expected.txt (261158 => 261159)


--- trunk/LayoutTests/imported/w3c/web-platform-tests/WebIDL/ecmascript-binding/class-string-iterator-prototype-object.any-expected.txt	2020-05-05 09:45:11 UTC (rev 261158)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/WebIDL/ecmascript-binding/class-string-iterator-prototype-object.any-expected.txt	2020-05-05 11:33:21 UTC (rev 261159)
@@ -3,5 +3,5 @@
 PASS Object.prototype.toString 
 PASS Object.prototype.toString applied after modifying @@toStringTag 
 FAIL Object.prototype.toString applied after nulling the prototype assert_equals: expected "[object Object]" but got "[object URLSearchParams Iterator]"
-FAIL Object.prototype.toString applied after deleting @@toStringTag assert_equals: prototype expected "[object Object]" but got "[object URLSearchParams Iterator]"
+PASS Object.prototype.toString applied after deleting @@toStringTag 
 

Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/WebIDL/ecmascript-binding/class-string-iterator-prototype-object.any.worker-expected.txt (261158 => 261159)


--- trunk/LayoutTests/imported/w3c/web-platform-tests/WebIDL/ecmascript-binding/class-string-iterator-prototype-object.any.worker-expected.txt	2020-05-05 09:45:11 UTC (rev 261158)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/WebIDL/ecmascript-binding/class-string-iterator-prototype-object.any.worker-expected.txt	2020-05-05 11:33:21 UTC (rev 261159)
@@ -3,5 +3,5 @@
 PASS Object.prototype.toString 
 PASS Object.prototype.toString applied after modifying @@toStringTag 
 FAIL Object.prototype.toString applied after nulling the prototype assert_equals: expected "[object Object]" but got "[object URLSearchParams Iterator]"
-FAIL Object.prototype.toString applied after deleting @@toStringTag assert_equals: prototype expected "[object Object]" but got "[object URLSearchParams Iterator]"
+PASS Object.prototype.toString applied after deleting @@toStringTag 
 

Modified: trunk/Source/_javascript_Core/ChangeLog (261158 => 261159)


--- trunk/Source/_javascript_Core/ChangeLog	2020-05-05 09:45:11 UTC (rev 261158)
+++ trunk/Source/_javascript_Core/ChangeLog	2020-05-05 11:33:21 UTC (rev 261159)
@@ -1,3 +1,89 @@
+2020-05-05  Alexey Shvayka  <[email protected]>
+
+        Object.prototype.toString is not spec-perfect
+        https://bugs.webkit.org/show_bug.cgi?id=199138
+
+        Reviewed by Darin Adler and Keith Miller.
+
+        Before ES6, Object.prototype.toString relied only on internal [[Class]] slot. Starting with ES6,
+        Object.prototype.toString checks for a handful of internal slots, mimicing [[Class]], to ensure
+        backwards compatibility for pre-ES6 instances. Newly-added built-ins provide @@toStringTag for
+        the method to use.
+
+        Before this change, Object.prototype.toString in JSC relied on className() a.k.a [[Class]] for
+        all instances. For (almost all) new built-ins, it was overriden by toStringName() returning
+        "Object", while @@toStringTag was set to correct value. This is quite an error-prone approach
+        and observable spec discrepancy if @@toStringTag is deleted or set to a non-string.
+
+        This change eliminates the above-mentioned discrepancy and fixes Object.prototype.toString
+        to return "[object Function]" for callable Proxy objects, aligning JSC with the spec [1], V8,
+        and SpiderMonkey.
+
+        For Object.prototype.toString to work through DebuggerScope and JSProxy, we perform all checks
+        in JSObject::toStringName(). Given that isArray() may throw a TypeError [2], we invoke
+        toStringName() before @@toStringTag lookup to accomodate revoked Proxy case.
+
+        Also, this patch defines @@toStringTag for WebAssembly namespace object (to match Chrome),
+        JSC shell, and ConsoleObject.
+
+        [1]: https://tc39.es/ecma262/#sec-object.prototype.tostring
+        [2]: https://tc39.es/ecma262/#sec-isarray (step 3.a)
+
+        * jsc.cpp:
+        * runtime/BigIntObject.cpp:
+        (JSC::BigIntObject::toStringName): Deleted.
+        * runtime/BigIntObject.h:
+        * runtime/BooleanObject.cpp:
+        (JSC::BooleanObject::toStringName):
+        * runtime/BooleanObject.h:
+        * runtime/ConsoleObject.cpp:
+        (JSC::ConsoleObject::finishCreation):
+        * runtime/DateInstance.cpp:
+        (JSC::DateInstance::toStringName):
+        * runtime/DateInstance.h:
+        * runtime/ErrorInstance.cpp:
+        (JSC::ErrorInstance::toStringName):
+        * runtime/ErrorInstance.h:
+        * runtime/JSArrayBufferView.cpp:
+        (JSC::JSArrayBufferView::toStringName): Deleted.
+        * runtime/JSArrayBufferView.h:
+        * runtime/JSMap.cpp:
+        (JSC::JSMap::toStringName): Deleted.
+        * runtime/JSMap.h:
+        * runtime/JSObject.cpp:
+        (JSC::JSObject::toStringName):
+        * runtime/JSSet.cpp:
+        (JSC::JSSet::toStringName): Deleted.
+        * runtime/JSSet.h:
+        * runtime/JSWeakMap.cpp:
+        (JSC::JSWeakMap::toStringName): Deleted.
+        * runtime/JSWeakMap.h:
+        * runtime/JSWeakObjectRef.cpp:
+        (JSC::JSWeakObjectRef::toStringName): Deleted.
+        * runtime/JSWeakObjectRef.h:
+        * runtime/JSWeakSet.cpp:
+        (JSC::JSWeakSet::toStringName): Deleted.
+        * runtime/JSWeakSet.h:
+        * runtime/NumberObject.cpp:
+        (JSC::NumberObject::toStringName):
+        * runtime/NumberObject.h:
+        * runtime/ObjectPrototype.cpp:
+        (JSC::objectProtoFuncToString):
+        * runtime/ProxyObject.cpp:
+        (JSC::ProxyObject::toStringName): Deleted.
+        * runtime/ProxyObject.h:
+        * runtime/RegExpObject.cpp:
+        (JSC::RegExpObject::toStringName):
+        * runtime/RegExpObject.h:
+        * runtime/StringObject.cpp:
+        (JSC::StringObject::toStringName):
+        * runtime/StringObject.h:
+        * runtime/SymbolObject.cpp:
+        (JSC::SymbolObject::toStringName): Deleted.
+        * runtime/SymbolObject.h:
+        * wasm/js/JSWebAssembly.cpp:
+        (JSC::JSWebAssembly::finishCreation):
+
 2020-05-04  Yusuke Suzuki  <[email protected]>
 
         [JSC] Implement BigInt.asIntN and BigInt.asUintN

Modified: trunk/Source/_javascript_Core/jsc.cpp (261158 => 261159)


--- trunk/Source/_javascript_Core/jsc.cpp	2020-05-05 09:45:11 UTC (rev 261158)
+++ trunk/Source/_javascript_Core/jsc.cpp	2020-05-05 11:33:21 UTC (rev 261159)
@@ -494,6 +494,7 @@
     void finishCreation(VM& vm, const Vector<String>& arguments)
     {
         Base::finishCreation(vm);
+        JSC_TO_STRING_TAG_WITHOUT_TRANSITION();
 
         addFunction(vm, "debug", functionDebug, 1);
         addFunction(vm, "describe", functionDescribe, 1);

Modified: trunk/Source/_javascript_Core/runtime/BigIntObject.cpp (261158 => 261159)


--- trunk/Source/_javascript_Core/runtime/BigIntObject.cpp	2020-05-05 09:45:11 UTC (rev 261158)
+++ trunk/Source/_javascript_Core/runtime/BigIntObject.cpp	2020-05-05 11:33:21 UTC (rev 261159)
@@ -56,11 +56,6 @@
     setInternalValue(vm, bigInt);
 }
 
-String BigIntObject::toStringName(const JSObject*, JSGlobalObject*)
-{
-    return "Object"_s;
-}
-
 JSValue BigIntObject::defaultValue(const JSObject* object, JSGlobalObject*, PreferredPrimitiveType)
 {
     const BigIntObject* bigIntObject = jsCast<const BigIntObject*>(object);

Modified: trunk/Source/_javascript_Core/runtime/BigIntObject.h (261158 => 261159)


--- trunk/Source/_javascript_Core/runtime/BigIntObject.h	2020-05-05 09:45:11 UTC (rev 261158)
+++ trunk/Source/_javascript_Core/runtime/BigIntObject.h	2020-05-05 11:33:21 UTC (rev 261159)
@@ -53,8 +53,6 @@
 
     static JSValue defaultValue(const JSObject*, JSGlobalObject*, PreferredPrimitiveType);
 
-    static String toStringName(const JSObject*, JSGlobalObject*);
-
 private:
     JS_EXPORT_PRIVATE void finishCreation(VM&, JSValue);
     JS_EXPORT_PRIVATE BigIntObject(VM&, Structure*);

Modified: trunk/Source/_javascript_Core/runtime/BooleanObject.cpp (261158 => 261159)


--- trunk/Source/_javascript_Core/runtime/BooleanObject.cpp	2020-05-05 09:45:11 UTC (rev 261158)
+++ trunk/Source/_javascript_Core/runtime/BooleanObject.cpp	2020-05-05 11:33:21 UTC (rev 261159)
@@ -41,4 +41,9 @@
     ASSERT(inherits(vm, info()));
 }
 
+String BooleanObject::toStringName(const JSObject*, JSGlobalObject*)
+{
+    return "Boolean"_s;
+}
+
 } // namespace JSC

Modified: trunk/Source/_javascript_Core/runtime/BooleanObject.h (261158 => 261159)


--- trunk/Source/_javascript_Core/runtime/BooleanObject.h	2020-05-05 09:45:11 UTC (rev 261158)
+++ trunk/Source/_javascript_Core/runtime/BooleanObject.h	2020-05-05 11:33:21 UTC (rev 261159)
@@ -51,6 +51,8 @@
     {
         return Structure::create(vm, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), info());
     }
+
+    static String toStringName(const JSObject*, JSGlobalObject*);
 };
 static_assert(sizeof(BooleanObject) == sizeof(JSWrapperObject));
 

Modified: trunk/Source/_javascript_Core/runtime/ConsoleObject.cpp (261158 => 261159)


--- trunk/Source/_javascript_Core/runtime/ConsoleObject.cpp	2020-05-05 09:45:11 UTC (rev 261158)
+++ trunk/Source/_javascript_Core/runtime/ConsoleObject.cpp	2020-05-05 11:33:21 UTC (rev 261159)
@@ -117,6 +117,8 @@
     JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION("record", consoleProtoFuncRecord, static_cast<unsigned>(PropertyAttribute::None), 0);
     JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION("recordEnd", consoleProtoFuncRecordEnd, static_cast<unsigned>(PropertyAttribute::None), 0);
     JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION("screenshot", consoleProtoFuncScreenshot, static_cast<unsigned>(PropertyAttribute::None), 0);
+
+    JSC_TO_STRING_TAG_WITHOUT_TRANSITION();
 }
 
 static String valueToStringWithUndefinedOrNullCheck(JSGlobalObject* globalObject, JSValue value)

Modified: trunk/Source/_javascript_Core/runtime/DateInstance.cpp (261158 => 261159)


--- trunk/Source/_javascript_Core/runtime/DateInstance.cpp	2020-05-05 09:45:11 UTC (rev 261158)
+++ trunk/Source/_javascript_Core/runtime/DateInstance.cpp	2020-05-05 11:33:21 UTC (rev 261159)
@@ -50,6 +50,11 @@
     m_internalNumber = timeClip(time);
 }
 
+String DateInstance::toStringName(const JSObject*, JSGlobalObject*)
+{
+    return "Date"_s;
+}
+
 const GregorianDateTime* DateInstance::calculateGregorianDateTime(VM& vm) const
 {
     double milli = internalNumber();

Modified: trunk/Source/_javascript_Core/runtime/DateInstance.h (261158 => 261159)


--- trunk/Source/_javascript_Core/runtime/DateInstance.h	2020-05-05 09:45:11 UTC (rev 261158)
+++ trunk/Source/_javascript_Core/runtime/DateInstance.h	2020-05-05 11:33:21 UTC (rev 261159)
@@ -54,6 +54,7 @@
         return instance;
     }
 
+    static String toStringName(const JSObject*, JSGlobalObject*);
     double internalNumber() const { return m_internalNumber; }
     void setInternalNumber(double value) { m_internalNumber = value; }
 

Modified: trunk/Source/_javascript_Core/runtime/ErrorInstance.cpp (261158 => 261159)


--- trunk/Source/_javascript_Core/runtime/ErrorInstance.cpp	2020-05-05 09:45:11 UTC (rev 261158)
+++ trunk/Source/_javascript_Core/runtime/ErrorInstance.cpp	2020-05-05 11:33:21 UTC (rev 261159)
@@ -311,4 +311,9 @@
     return Base::deleteProperty(thisObject, globalObject, propertyName, slot);
 }
 
+String ErrorInstance::toStringName(const JSObject*, JSGlobalObject*)
+{
+    return "Error"_s;
+}
+
 } // namespace JSC

Modified: trunk/Source/_javascript_Core/runtime/ErrorInstance.h (261158 => 261159)


--- trunk/Source/_javascript_Core/runtime/ErrorInstance.h	2020-05-05 09:45:11 UTC (rev 261158)
+++ trunk/Source/_javascript_Core/runtime/ErrorInstance.h	2020-05-05 11:33:21 UTC (rev 261159)
@@ -98,6 +98,7 @@
     static bool defineOwnProperty(JSObject*, JSGlobalObject*, PropertyName, const PropertyDescriptor&, bool shouldThrow);
     static bool put(JSCell*, JSGlobalObject*, PropertyName, JSValue, PutPropertySlot&);
     static bool deleteProperty(JSCell*, JSGlobalObject*, PropertyName, DeletePropertySlot&);
+    static String toStringName(const JSObject*, JSGlobalObject*);
 
     void computeErrorInfo(VM&);
 

Modified: trunk/Source/_javascript_Core/runtime/JSArrayBufferView.cpp (261158 => 261159)


--- trunk/Source/_javascript_Core/runtime/JSArrayBufferView.cpp	2020-05-05 09:45:11 UTC (rev 261158)
+++ trunk/Source/_javascript_Core/runtime/JSArrayBufferView.cpp	2020-05-05 11:33:21 UTC (rev 261159)
@@ -42,11 +42,6 @@
     "ArrayBufferView", &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(JSArrayBufferView)
 };
 
-String JSArrayBufferView::toStringName(const JSObject*, JSGlobalObject*)
-{
-    return "Object"_s;
-}
-
 JSArrayBufferView::ConstructionContext::ConstructionContext(
     Structure* structure, uint32_t length, void* vector)
     : m_structure(structure)

Modified: trunk/Source/_javascript_Core/runtime/JSArrayBufferView.h (261158 => 261159)


--- trunk/Source/_javascript_Core/runtime/JSArrayBufferView.h	2020-05-05 09:45:11 UTC (rev 261158)
+++ trunk/Source/_javascript_Core/runtime/JSArrayBufferView.h	2020-05-05 11:33:21 UTC (rev 261159)
@@ -212,8 +212,6 @@
 
     ArrayBuffer* existingBufferInButterfly();
 
-    static String toStringName(const JSObject*, JSGlobalObject*);
-
     VectorPtr m_vector;
     uint32_t m_length;
     TypedArrayMode m_mode;

Modified: trunk/Source/_javascript_Core/runtime/JSMap.cpp (261158 => 261159)


--- trunk/Source/_javascript_Core/runtime/JSMap.cpp	2020-05-05 09:45:11 UTC (rev 261158)
+++ trunk/Source/_javascript_Core/runtime/JSMap.cpp	2020-05-05 11:33:21 UTC (rev 261159)
@@ -33,11 +33,6 @@
 
 const ClassInfo JSMap::s_info = { "Map", &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(JSMap) };
 
-String JSMap::toStringName(const JSObject*, JSGlobalObject*)
-{
-    return "Object"_s;
-}
-
 JSMap* JSMap::clone(JSGlobalObject* globalObject, VM& vm, Structure* structure)
 {
     JSMap* instance = new (NotNull, allocateCell<JSMap>(vm.heap)) JSMap(vm, structure);

Modified: trunk/Source/_javascript_Core/runtime/JSMap.h (261158 => 261159)


--- trunk/Source/_javascript_Core/runtime/JSMap.h	2020-05-05 09:45:11 UTC (rev 261158)
+++ trunk/Source/_javascript_Core/runtime/JSMap.h	2020-05-05 11:33:21 UTC (rev 261159)
@@ -68,8 +68,6 @@
         : Base(vm, structure)
     {
     }
-
-    static String toStringName(const JSObject*, JSGlobalObject*);
 };
 
 static_assert(std::is_final<JSMap>::value, "Required for JSType based casting");

Modified: trunk/Source/_javascript_Core/runtime/JSObject.cpp (261158 => 261159)


--- trunk/Source/_javascript_Core/runtime/JSObject.cpp	2020-05-05 09:45:11 UTC (rev 261158)
+++ trunk/Source/_javascript_Core/runtime/JSObject.cpp	2020-05-05 11:33:21 UTC (rev 261159)
@@ -24,6 +24,7 @@
 #include "config.h"
 #include "JSObject.h"
 
+#include "ArrayConstructor.h"
 #include "ButterflyInlines.h"
 #include "CatchScope.h"
 #include "CustomGetterSetter.h"
@@ -519,9 +520,16 @@
 String JSObject::toStringName(const JSObject* object, JSGlobalObject* globalObject)
 {
     VM& vm = globalObject->vm();
-    const ClassInfo* info = object->classInfo(vm);
-    ASSERT(info);
-    return info->className;
+    auto scope = DECLARE_THROW_SCOPE(vm);
+    bool objectIsArray = isArray(globalObject, object);
+    RETURN_IF_EXCEPTION(scope, String());
+    if (objectIsArray)
+        return "Array"_s;
+    if (TypeInfo::isArgumentsType(object->type()))
+        return "Arguments"_s;
+    if (const_cast<JSObject*>(object)->isCallable(vm))
+        return "Function"_s;
+    return "Object"_s;
 }
 
 String JSObject::calculatedClassName(JSObject* object)

Modified: trunk/Source/_javascript_Core/runtime/JSSet.cpp (261158 => 261159)


--- trunk/Source/_javascript_Core/runtime/JSSet.cpp	2020-05-05 09:45:11 UTC (rev 261158)
+++ trunk/Source/_javascript_Core/runtime/JSSet.cpp	2020-05-05 11:33:21 UTC (rev 261159)
@@ -33,11 +33,6 @@
 
 const ClassInfo JSSet::s_info = { "Set", &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(JSSet) };
 
-String JSSet::toStringName(const JSObject*, JSGlobalObject*)
-{
-    return "Object"_s;
-}
-
 JSSet* JSSet::clone(JSGlobalObject* globalObject, VM& vm, Structure* structure)
 {
     JSSet* instance = new (NotNull, allocateCell<JSSet>(vm.heap)) JSSet(vm, structure);

Modified: trunk/Source/_javascript_Core/runtime/JSSet.h (261158 => 261159)


--- trunk/Source/_javascript_Core/runtime/JSSet.h	2020-05-05 09:45:11 UTC (rev 261158)
+++ trunk/Source/_javascript_Core/runtime/JSSet.h	2020-05-05 11:33:21 UTC (rev 261159)
@@ -73,8 +73,6 @@
         : Base(vm, structure, sizeHint)
     {
     }
-
-    static String toStringName(const JSObject*, JSGlobalObject*);
 };
 
 static_assert(std::is_final<JSSet>::value, "Required for JSType based casting");

Modified: trunk/Source/_javascript_Core/runtime/JSWeakMap.cpp (261158 => 261159)


--- trunk/Source/_javascript_Core/runtime/JSWeakMap.cpp	2020-05-05 09:45:11 UTC (rev 261158)
+++ trunk/Source/_javascript_Core/runtime/JSWeakMap.cpp	2020-05-05 11:33:21 UTC (rev 261159)
@@ -32,9 +32,4 @@
 
 const ClassInfo JSWeakMap::s_info = { "WeakMap", &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(JSWeakMap) };
 
-String JSWeakMap::toStringName(const JSObject*, JSGlobalObject*)
-{
-    return "Object"_s;
 }
-
-}

Modified: trunk/Source/_javascript_Core/runtime/JSWeakMap.h (261158 => 261159)


--- trunk/Source/_javascript_Core/runtime/JSWeakMap.h	2020-05-05 09:45:11 UTC (rev 261158)
+++ trunk/Source/_javascript_Core/runtime/JSWeakMap.h	2020-05-05 11:33:21 UTC (rev 261159)
@@ -58,8 +58,6 @@
         : Base(vm, structure)
     {
     }
-
-    static String toStringName(const JSObject*, JSGlobalObject*);
 };
 
 static_assert(std::is_final<JSWeakMap>::value, "Required for JSType based casting");

Modified: trunk/Source/_javascript_Core/runtime/JSWeakObjectRef.cpp (261158 => 261159)


--- trunk/Source/_javascript_Core/runtime/JSWeakObjectRef.cpp	2020-05-05 09:45:11 UTC (rev 261158)
+++ trunk/Source/_javascript_Core/runtime/JSWeakObjectRef.cpp	2020-05-05 11:33:21 UTC (rev 261159)
@@ -57,10 +57,5 @@
         m_value.clear();
 }
 
-String JSWeakObjectRef::toStringName(const JSC::JSObject*, JSGlobalObject*)
-{
-    return "Object"_s;
 }
 
-}
-

Modified: trunk/Source/_javascript_Core/runtime/JSWeakObjectRef.h (261158 => 261159)


--- trunk/Source/_javascript_Core/runtime/JSWeakObjectRef.h	2020-05-05 09:45:11 UTC (rev 261158)
+++ trunk/Source/_javascript_Core/runtime/JSWeakObjectRef.h	2020-05-05 11:33:21 UTC (rev 261159)
@@ -75,8 +75,6 @@
 
     JS_EXPORT_PRIVATE void finishCreation(VM&, JSObject* value);
 
-    static String toStringName(const JSObject*, JSGlobalObject*);
-
     uintptr_t m_lastAccessVersion;
     WriteBarrier<JSObject> m_value;
 };

Modified: trunk/Source/_javascript_Core/runtime/JSWeakSet.cpp (261158 => 261159)


--- trunk/Source/_javascript_Core/runtime/JSWeakSet.cpp	2020-05-05 09:45:11 UTC (rev 261158)
+++ trunk/Source/_javascript_Core/runtime/JSWeakSet.cpp	2020-05-05 11:33:21 UTC (rev 261159)
@@ -32,9 +32,4 @@
 
 const ClassInfo JSWeakSet::s_info = { "WeakSet", &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(JSWeakSet) };
 
-String JSWeakSet::toStringName(const JSC::JSObject*, JSGlobalObject*)
-{
-    return "Object"_s;
 }
-
-}

Modified: trunk/Source/_javascript_Core/runtime/JSWeakSet.h (261158 => 261159)


--- trunk/Source/_javascript_Core/runtime/JSWeakSet.h	2020-05-05 09:45:11 UTC (rev 261158)
+++ trunk/Source/_javascript_Core/runtime/JSWeakSet.h	2020-05-05 11:33:21 UTC (rev 261159)
@@ -53,8 +53,6 @@
         : Base(vm, structure)
     {
     }
-
-    static String toStringName(const JSObject*, JSGlobalObject*);
 };
 
 static_assert(std::is_final<JSWeakSet>::value, "Required for JSType based casting");

Modified: trunk/Source/_javascript_Core/runtime/NumberObject.cpp (261158 => 261159)


--- trunk/Source/_javascript_Core/runtime/NumberObject.cpp	2020-05-05 09:45:11 UTC (rev 261158)
+++ trunk/Source/_javascript_Core/runtime/NumberObject.cpp	2020-05-05 11:33:21 UTC (rev 261159)
@@ -44,6 +44,11 @@
     ASSERT(type() == NumberObjectType);
 }
 
+String NumberObject::toStringName(const JSObject*, JSGlobalObject*)
+{
+    return "Number"_s;
+}
+
 NumberObject* constructNumber(JSGlobalObject* globalObject, JSValue number)
 {
     NumberObject* object = NumberObject::create(globalObject->vm(), globalObject->numberObjectStructure());

Modified: trunk/Source/_javascript_Core/runtime/NumberObject.h (261158 => 261159)


--- trunk/Source/_javascript_Core/runtime/NumberObject.h	2020-05-05 09:45:11 UTC (rev 261158)
+++ trunk/Source/_javascript_Core/runtime/NumberObject.h	2020-05-05 11:33:21 UTC (rev 261159)
@@ -51,6 +51,8 @@
     {
         return Structure::create(vm, globalObject, prototype, TypeInfo(NumberObjectType, StructureFlags), info());
     }
+
+    static String toStringName(const JSObject*, JSGlobalObject*);
 };
 static_assert(sizeof(NumberObject) == sizeof(JSWrapperObject));
 

Modified: trunk/Source/_javascript_Core/runtime/ObjectPrototype.cpp (261158 => 261159)


--- trunk/Source/_javascript_Core/runtime/ObjectPrototype.cpp	2020-05-05 09:45:11 UTC (rev 261158)
+++ trunk/Source/_javascript_Core/runtime/ObjectPrototype.cpp	2020-05-05 11:33:21 UTC (rev 261159)
@@ -325,29 +325,29 @@
     if (result)
         return JSValue::encode(result);
 
-    PropertyName toStringTagSymbol = vm.propertyNames->toStringTagSymbol;
-    RELEASE_AND_RETURN(scope, JSValue::encode(thisObject->getPropertySlot(globalObject, toStringTagSymbol, [&] (bool found, PropertySlot& toStringTagSlot) -> JSValue {
-        if (found) {
-            JSValue stringTag = toStringTagSlot.getValue(globalObject, toStringTagSymbol);
-            RETURN_IF_EXCEPTION(scope, { });
-            if (stringTag.isString()) {
-                JSString* result = jsString(globalObject, vm.smallStrings.objectStringStart(), asString(stringTag), vm.smallStrings.singleCharacterString(']'));
-                RETURN_IF_EXCEPTION(scope, { });
-                thisObject->structure(vm)->setObjectToStringValue(globalObject, vm, result, toStringTagSlot);
-                return result;
-            }
-        }
+    String tag = thisObject->methodTable(vm)->toStringName(thisObject, globalObject);
+    RETURN_IF_EXCEPTION(scope, { });
+    JSString* jsTag = nullptr;
 
-        String tag = thisObject->methodTable(vm)->toStringName(thisObject, globalObject);
+    PropertySlot slot(thisObject, PropertySlot::InternalMethodType::Get);
+    bool hasProperty = thisObject->getPropertySlot(globalObject, vm.propertyNames->toStringTagSymbol, slot);
+    EXCEPTION_ASSERT(!scope.exception() || !hasProperty);
+    if (hasProperty) {
+        JSValue tagValue = slot.getValue(globalObject, vm.propertyNames->toStringTagSymbol);
         RETURN_IF_EXCEPTION(scope, { });
-        String newString = tryMakeString("[object ", WTFMove(tag), "]");
-        if (!newString)
-            return throwOutOfMemoryError(globalObject, scope);
+        if (tagValue.isString())
+            jsTag = asString(tagValue);
+    }
 
-        auto result = jsNontrivialString(vm, newString);
-        thisObject->structure(vm)->setObjectToStringValue(globalObject, vm, result, toStringTagSlot);
-        return result;
-    })));
+    if (!jsTag) {
+        ASSERT_WITH_MESSAGE(tag.length() > 1, "toStringName() should return strings two or more characters long.");
+        jsTag = jsNontrivialString(vm, WTFMove(tag));
+    }
+
+    JSString* jsResult = jsString(globalObject, vm.smallStrings.objectStringStart(), jsTag, vm.smallStrings.singleCharacterString(']'));
+    RETURN_IF_EXCEPTION(scope, { });
+    thisObject->structure(vm)->setObjectToStringValue(globalObject, vm, jsResult, slot);
+    return JSValue::encode(jsResult);
 }
 
 } // namespace JSC

Modified: trunk/Source/_javascript_Core/runtime/ProxyObject.cpp (261158 => 261159)


--- trunk/Source/_javascript_Core/runtime/ProxyObject.cpp	2020-05-05 09:45:11 UTC (rev 261158)
+++ trunk/Source/_javascript_Core/runtime/ProxyObject.cpp	2020-05-05 11:33:21 UTC (rev 261159)
@@ -51,24 +51,6 @@
 {
 }
 
-String ProxyObject::toStringName(const JSObject* object, JSGlobalObject* globalObject)
-{
-    VM& vm = globalObject->vm();
-    auto scope = DECLARE_THROW_SCOPE(vm);
-    const ProxyObject* proxy = jsCast<const ProxyObject*>(object);
-    while (proxy) {
-        const JSObject* target = proxy->target();
-        bool targetIsArray = isArray(globalObject, target);
-        if (UNLIKELY(scope.exception()))
-            break;
-        if (targetIsArray)
-            RELEASE_AND_RETURN(scope, target->classInfo(vm)->methodTable.toStringName(target, globalObject));
-
-        proxy = jsDynamicCast<const ProxyObject*>(vm, target);
-    }
-    return "Object"_s;
-}
-
 Structure* ProxyObject::structureForTarget(JSGlobalObject* globalObject, JSValue target)
 {
     VM& vm = globalObject->vm();

Modified: trunk/Source/_javascript_Core/runtime/ProxyObject.h (261158 => 261159)


--- trunk/Source/_javascript_Core/runtime/ProxyObject.h	2020-05-05 09:45:11 UTC (rev 261158)
+++ trunk/Source/_javascript_Core/runtime/ProxyObject.h	2020-05-05 11:33:21 UTC (rev 261159)
@@ -80,7 +80,6 @@
     JS_EXPORT_PRIVATE void finishCreation(VM&, JSGlobalObject*, JSValue target, JSValue handler);
     JS_EXPORT_PRIVATE static Structure* structureForTarget(JSGlobalObject*, JSValue target);
 
-    static String toStringName(const JSObject*, JSGlobalObject*);
     static bool getOwnPropertySlot(JSObject*, JSGlobalObject*, PropertyName, PropertySlot&);
     static bool getOwnPropertySlotByIndex(JSObject*, JSGlobalObject*, unsigned propertyName, PropertySlot&);
     static CallData getCallData(JSCell*);

Modified: trunk/Source/_javascript_Core/runtime/RegExpObject.cpp (261158 => 261159)


--- trunk/Source/_javascript_Core/runtime/RegExpObject.cpp	2020-05-05 09:45:11 UTC (rev 261158)
+++ trunk/Source/_javascript_Core/runtime/RegExpObject.cpp	2020-05-05 11:33:21 UTC (rev 261159)
@@ -167,6 +167,11 @@
     return Base::put(cell, globalObject, propertyName, value, slot);
 }
 
+String RegExpObject::toStringName(const JSObject*, JSGlobalObject*)
+{
+    return "RegExp"_s;
+}
+
 JSValue RegExpObject::exec(JSGlobalObject* globalObject, JSString* string)
 {
     return execInline(globalObject, string);

Modified: trunk/Source/_javascript_Core/runtime/RegExpObject.h (261158 => 261159)


--- trunk/Source/_javascript_Core/runtime/RegExpObject.h	2020-05-05 09:45:11 UTC (rev 261158)
+++ trunk/Source/_javascript_Core/runtime/RegExpObject.h	2020-05-05 11:33:21 UTC (rev 261159)
@@ -104,6 +104,7 @@
 
     static bool getOwnPropertySlot(JSObject*, JSGlobalObject*, PropertyName, PropertySlot&);
     static bool put(JSCell*, JSGlobalObject*, PropertyName, JSValue, PutPropertySlot&);
+    static String toStringName(const JSObject*, JSGlobalObject*);
 
     DECLARE_EXPORT_INFO;
 

Modified: trunk/Source/_javascript_Core/runtime/StringObject.cpp (261158 => 261159)


--- trunk/Source/_javascript_Core/runtime/StringObject.cpp	2020-05-05 09:45:11 UTC (rev 261158)
+++ trunk/Source/_javascript_Core/runtime/StringObject.cpp	2020-05-05 11:33:21 UTC (rev 261159)
@@ -166,6 +166,11 @@
     return JSObject::getOwnNonIndexPropertyNames(thisObject, globalObject, propertyNames, mode);
 }
 
+String StringObject::toStringName(const JSObject*, JSGlobalObject*)
+{
+    return "String"_s;
+}
+
 StringObject* constructString(VM& vm, JSGlobalObject* globalObject, JSValue string)
 {
     StringObject* object = StringObject::create(vm, globalObject->stringObjectStructure());

Modified: trunk/Source/_javascript_Core/runtime/StringObject.h (261158 => 261159)


--- trunk/Source/_javascript_Core/runtime/StringObject.h	2020-05-05 09:45:11 UTC (rev 261158)
+++ trunk/Source/_javascript_Core/runtime/StringObject.h	2020-05-05 11:33:21 UTC (rev 261159)
@@ -62,6 +62,7 @@
     JS_EXPORT_PRIVATE static void getOwnPropertyNames(JSObject*, JSGlobalObject*, PropertyNameArray&, EnumerationMode);
     JS_EXPORT_PRIVATE static void getOwnNonIndexPropertyNames(JSObject*, JSGlobalObject*, PropertyNameArray&, EnumerationMode);
     JS_EXPORT_PRIVATE static bool defineOwnProperty(JSObject*, JSGlobalObject*, PropertyName, const PropertyDescriptor&, bool shouldThrow);
+    static String toStringName(const JSObject*, JSGlobalObject*);
 
     DECLARE_EXPORT_INFO;
 

Modified: trunk/Source/_javascript_Core/runtime/SymbolObject.cpp (261158 => 261159)


--- trunk/Source/_javascript_Core/runtime/SymbolObject.cpp	2020-05-05 09:45:11 UTC (rev 261158)
+++ trunk/Source/_javascript_Core/runtime/SymbolObject.cpp	2020-05-05 11:33:21 UTC (rev 261159)
@@ -47,11 +47,6 @@
     setInternalValue(vm, symbol);
 }
 
-String SymbolObject::toStringName(const JSObject*, JSGlobalObject*)
-{
-    return "Object"_s;
-}
-
 JSValue SymbolObject::defaultValue(const JSObject* object, JSGlobalObject*, PreferredPrimitiveType)
 {
     const SymbolObject* symbolObject = jsCast<const SymbolObject*>(object);

Modified: trunk/Source/_javascript_Core/runtime/SymbolObject.h (261158 => 261159)


--- trunk/Source/_javascript_Core/runtime/SymbolObject.h	2020-05-05 09:45:11 UTC (rev 261158)
+++ trunk/Source/_javascript_Core/runtime/SymbolObject.h	2020-05-05 11:33:21 UTC (rev 261159)
@@ -62,8 +62,6 @@
 
     static JSValue defaultValue(const JSObject*, JSGlobalObject*, PreferredPrimitiveType);
 
-    static String toStringName(const JSObject*, JSGlobalObject*);
-
 private:
     JS_EXPORT_PRIVATE void finishCreation(VM&, Symbol*);
     JS_EXPORT_PRIVATE SymbolObject(VM&, Structure*);

Modified: trunk/Source/_javascript_Core/wasm/js/JSWebAssembly.cpp (261158 => 261159)


--- trunk/Source/_javascript_Core/wasm/js/JSWebAssembly.cpp	2020-05-05 09:45:11 UTC (rev 261158)
+++ trunk/Source/_javascript_Core/wasm/js/JSWebAssembly.cpp	2020-05-05 11:33:21 UTC (rev 261159)
@@ -114,6 +114,7 @@
 {
     Base::finishCreation(vm);
     ASSERT(inherits(vm, info()));
+    JSC_TO_STRING_TAG_WITHOUT_TRANSITION();
     if (Options::useWebAssemblyStreamingApi()) {
         JSC_BUILTIN_FUNCTION_WITHOUT_TRANSITION("compileStreaming", webAssemblyCompileStreamingCodeGenerator, static_cast<unsigned>(PropertyAttribute::DontEnum));
         JSC_BUILTIN_FUNCTION_WITHOUT_TRANSITION("instantiateStreaming", webAssemblyInstantiateStreamingCodeGenerator, static_cast<unsigned>(PropertyAttribute::DontEnum));

Modified: trunk/Source/WebCore/ChangeLog (261158 => 261159)


--- trunk/Source/WebCore/ChangeLog	2020-05-05 09:45:11 UTC (rev 261158)
+++ trunk/Source/WebCore/ChangeLog	2020-05-05 11:33:21 UTC (rev 261159)
@@ -1,3 +1,31 @@
+2020-05-05  Alexey Shvayka  <[email protected]>
+
+        Object.prototype.toString is not spec-perfect
+        https://bugs.webkit.org/show_bug.cgi?id=199138
+
+        Reviewed by Darin Adler and Keith Miller.
+
+        This patch defines @@toStringTag symbols for all WebIDL prototypes, including
+        interfaces that are not exposed, as required by the spec [1].
+
+        With updated JSObject::toStringName() and @@toStringTag symbols added in r260992,
+        className() and toStringName() methods of JSDOMConstructorBase can be safely removed.
+
+        [1]: https://heycam.github.io/webidl/#dfn-class-string
+
+        Tests: imported/w3c/web-platform-tests/WebIDL/ecmascript-binding/class-string-interface.any.js
+               imported/w3c/web-platform-tests/WebIDL/ecmascript-binding/class-string-iterator-prototype-object.any.js
+
+        * bindings/js/JSDOMConstructorBase.cpp:
+        (WebCore::JSDOMConstructorBase::className): Deleted.
+        (WebCore::JSDOMConstructorBase::toStringName): Deleted.
+        * bindings/js/JSDOMConstructorBase.h:
+        * bindings/scripts/CodeGeneratorJS.pm:
+        (GenerateImplementation):
+        (GeneratePrototypeDeclaration):
+        * bindings/scripts/test/JS/JSTestGlobalObject.cpp:
+        (WebCore::JSTestGlobalObjectPrototype::finishCreation):
+
 2020-05-04  Darin Adler  <[email protected]>
 
         [Mac] Remove __MAC_OS_X_VERSION_MIN_REQUIRED checks for versions older than 10.14

Modified: trunk/Source/WebCore/bindings/js/JSDOMConstructorBase.cpp (261158 => 261159)


--- trunk/Source/WebCore/bindings/js/JSDOMConstructorBase.cpp	2020-05-05 09:45:11 UTC (rev 261158)
+++ trunk/Source/WebCore/bindings/js/JSDOMConstructorBase.cpp	2020-05-05 11:33:21 UTC (rev 261159)
@@ -46,19 +46,6 @@
     return callData;
 }
 
-String JSDOMConstructorBase::className(const JSObject*, JSC::VM&)
-{
-    return "Function"_s;
-}
-
-String JSDOMConstructorBase::toStringName(const JSObject* object, JSC::JSGlobalObject* lexicalGlobalObject)
-{
-    VM& vm = lexicalGlobalObject->vm();
-    const ClassInfo* info = object->classInfo(vm);
-    ASSERT(info);
-    return info->methodTable.className(object, vm);
-}
-
 JSC::IsoSubspace* JSDOMConstructorBase::subspaceForImpl(JSC::VM& vm)
 {
     return &static_cast<JSVMClientData*>(vm.clientData)->domConstructorSpace();

Modified: trunk/Source/WebCore/bindings/js/JSDOMConstructorBase.h (261158 => 261159)


--- trunk/Source/WebCore/bindings/js/JSDOMConstructorBase.h	2020-05-05 09:45:11 UTC (rev 261158)
+++ trunk/Source/WebCore/bindings/js/JSDOMConstructorBase.h	2020-05-05 11:33:21 UTC (rev 261159)
@@ -49,8 +49,6 @@
     {
     }
 
-    static String className(const JSObject*, JSC::VM&);
-    static String toStringName(const JSObject*, JSC::JSGlobalObject*);
     static JSC::CallData getCallData(JSC::JSCell*);
 };
 

Modified: trunk/Source/WebCore/bindings/scripts/CodeGeneratorJS.pm (261158 => 261159)


--- trunk/Source/WebCore/bindings/scripts/CodeGeneratorJS.pm	2020-05-05 09:45:11 UTC (rev 261158)
+++ trunk/Source/WebCore/bindings/scripts/CodeGeneratorJS.pm	2020-05-05 11:33:21 UTC (rev 261159)
@@ -4301,12 +4301,13 @@
     my $hashTable = $justGenerateValueArray ? "nullptr" : "&${className}PrototypeTable";
     push(@implContent, "const ClassInfo ${className}Prototype::s_info = { \"${visibleInterfaceName}\", &Base::s_info, ${hashTable}, nullptr, CREATE_METHOD_TABLE(${className}Prototype) };\n\n");
 
-    if (PrototypeHasStaticPropertyTable($interface) || IsGlobalInterface($interface)) {
-        push(@implContent, "void ${className}Prototype::finishCreation(VM& vm)\n");
-        push(@implContent, "{\n");
-        push(@implContent, "    Base::finishCreation(vm);\n");
-        push(@implContent, "    reifyStaticProperties(vm, ${className}::info(), ${className}PrototypeTableValues, *this);\n") if !IsGlobalInterface($interface);
+    push(@implContent, "void ${className}Prototype::finishCreation(VM& vm)\n");
+    push(@implContent, "{\n");
+    push(@implContent, "    Base::finishCreation(vm);\n");
 
+    if (PrototypeHasStaticPropertyTable($interface) && !IsGlobalInterface($interface)) {
+        push(@implContent, "    reifyStaticProperties(vm, ${className}::info(), ${className}PrototypeTableValues, *this);\n");
+
         my @runtimeEnabledProperties = @runtimeEnabledOperations;
         push(@runtimeEnabledProperties, @runtimeEnabledAttributes);
 
@@ -4374,12 +4375,12 @@
         push(@implContent, "    addValueIterableMethods(*globalObject(), *this);\n") if $interface->iterable and !IsKeyValueIterableInterface($interface);
 
         addUnscopableProperties($interface);
-
-        assert("JSC_TO_STRING_TAG_WITHOUT_TRANSITION() requires strings two or more characters long") if length($visibleInterfaceName) < 2;
-        push(@implContent, "    JSC_TO_STRING_TAG_WITHOUT_TRANSITION();\n");
-        push(@implContent, "}\n\n");
     }
 
+    assert("JSC_TO_STRING_TAG_WITHOUT_TRANSITION() requires strings two or more characters long") if length($visibleInterfaceName) < 2;
+    push(@implContent, "    JSC_TO_STRING_TAG_WITHOUT_TRANSITION();\n");
+    push(@implContent, "}\n\n");
+
     # - Initialize static ClassInfo object
     push(@implContent, "const ClassInfo $className" . "::s_info = { \"${visibleInterfaceName}\", &Base::s_info, ");
 
@@ -7339,13 +7340,9 @@
     push(@$outputArray, "    {\n");
     push(@$outputArray, "    }\n");
 
-    if (PrototypeHasStaticPropertyTable($interface) || IsGlobalInterface($interface)) {
-        $structureFlags{"JSC::HasStaticPropertyTable"} = 1 if IsGlobalInterface($interface);
+    push(@$outputArray, "\n");
+    push(@$outputArray, "    void finishCreation(JSC::VM&);\n");
 
-        push(@$outputArray, "\n");
-        push(@$outputArray, "    void finishCreation(JSC::VM&);\n");
-    }
-
     # FIXME: Should this override putByIndex as well?
     if ($interface->extendedAttributes->{CustomPutOnPrototype}) {
         push(@$outputArray, "\n");
@@ -7357,6 +7354,7 @@
         push(@$outputArray, "    static bool defineOwnProperty(JSC::JSObject*, JSC::JSGlobalObject*, JSC::PropertyName, const JSC::PropertyDescriptor&, bool shouldThrow);\n");
     }
 
+    $structureFlags{"JSC::HasStaticPropertyTable"} = 1 if PrototypeHasStaticPropertyTable($interface) && IsGlobalInterface($interface);
     $structureFlags{"JSC::IsImmutablePrototypeExoticObject"} = 1 if $interface->extendedAttributes->{IsImmutablePrototypeExoticObjectOnPrototype};
 
     # structure flags

Modified: trunk/Source/WebCore/bindings/scripts/test/JS/JSTestGlobalObject.cpp (261158 => 261159)


--- trunk/Source/WebCore/bindings/scripts/test/JS/JSTestGlobalObject.cpp	2020-05-05 09:45:11 UTC (rev 261158)
+++ trunk/Source/WebCore/bindings/scripts/test/JS/JSTestGlobalObject.cpp	2020-05-05 11:33:21 UTC (rev 261159)
@@ -700,9 +700,6 @@
 void JSTestGlobalObjectPrototype::finishCreation(VM& vm)
 {
     Base::finishCreation(vm);
-#if ENABLE(TEST_FEATURE)
-    putDirect(vm, static_cast<JSVMClientData*>(vm.clientData)->builtinNames().testPrivateFunctionPrivateName(), JSFunction::create(vm, globalObject(), 0, String(), jsTestGlobalObjectInstanceFunctionTestPrivateFunction), JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::DontEnum);
-#endif
     JSC_TO_STRING_TAG_WITHOUT_TRANSITION();
 }
 

Modified: trunk/Tools/ChangeLog (261158 => 261159)


--- trunk/Tools/ChangeLog	2020-05-05 09:45:11 UTC (rev 261158)
+++ trunk/Tools/ChangeLog	2020-05-05 11:33:21 UTC (rev 261159)
@@ -1,3 +1,12 @@
+2020-05-05  Alexey Shvayka  <[email protected]>
+
+        Object.prototype.toString is not spec-perfect
+        https://bugs.webkit.org/show_bug.cgi?id=199138
+
+        Reviewed by Darin Adler and Keith Miller.
+
+        * TestWebKitAPI/Tests/_javascript_Core/glib/TestJSC.cpp:
+
 2020-05-05  Tim Horton  <[email protected]>
 
         Excessive error logging from daemons trying to use WebKit, under -[UIDevice currentDevice]

Modified: trunk/Tools/TestWebKitAPI/Tests/_javascript_Core/glib/TestJSC.cpp (261158 => 261159)


--- trunk/Tools/TestWebKitAPI/Tests/_javascript_Core/glib/TestJSC.cpp	2020-05-05 09:45:11 UTC (rev 261158)
+++ trunk/Tools/TestWebKitAPI/Tests/_javascript_Core/glib/TestJSC.cpp	2020-05-05 11:33:21 UTC (rev 261159)
@@ -671,7 +671,7 @@
         g_assert_true(JSC_IS_VALUE(module.get()));
         g_assert_true(jsc_value_is_object(module.get()));
         GUniquePtr<char> valueString(jsc_value_to_string(module.get()));
-        g_assert_cmpstr(valueString.get(), ==, "[object GlobalObject]");
+        g_assert_cmpstr(valueString.get(), ==, "[object Object]");
         jsc_context_set_value(context.get(), "module", module.get());
 
         GRefPtr<JSCValue> bar = adoptGRef(jsc_value_object_get_property(module.get(), "bar"));
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to