Title: [197815] trunk
Revision
197815
Author
[email protected]
Date
2016-03-08 16:01:09 -0800 (Tue, 08 Mar 2016)

Log Message

Implement Function.name support for getters/setters and inferring name of function properties.
https://bugs.webkit.org/show_bug.cgi?id=154865

Reviewed by Geoffrey Garen.

Source/_javascript_Core:

1. toString() no longer uses the value of Function.name as the name of the
   function in the returned string, because ...

    i. Function.name is supposed to be configurable.  Hence, it can be made
       writable and can be set to any JSValue, or deleted.
   ii. Function.prototype.toString() is supposed to produce a string that can be
       eval'ed.  Hence, for JS functions, the function name in the produced
       string must be a legal function name (and not some arbitrary value set in
       Function.name).  For example, while a number is a legal value for
       Function.name, it is not legal as the function name in the toString()
       string.

   Instead, we'll always use the original name from the JS source that the
   function was parsed from.

2. JSFunction::name() now always return the original name, not the value of
   the Function.name property.  As a result, it also no longer needs an
   ExecState* arg.

   If the original name is an empty string, JSFunction::name() will use the
   inferred name.

3. For JS functions, the original name can be attained from their
   FunctionExecutable object.

   For host/native functions (which do not have a FunctionExecutable), we get the
   "original" name from its NativeExecutable.

4. The m_hostFunctionStubMap now keys its NativeExecutable pointers using the
   original name, in addition to the native function and constructor pointers.

   This is needed because we want a different NativeExecutable for functions with
   a different name (to satisfy (3) above).

5. Changed JSBoundFunction to store the name of its bound function in its
   NativeExecutable.  This will later be used to generate the toString() string.
   It's Function.name value is eagerly initialized at construction time.

6. Function.name for getters/setters are now prefixed with "get"/"set".
   This was done both for the JSBoundSlotBaseFunctions and JS definable get/set
   functions.

7. Added InternalFunction::m_originalName so that we can use it to generate the
   toString() string.  We're storing it as a JSString instead of a WTF::String
   only because we want InternalFunction to be continue to be trivially
   destructible.

* inspector/JSInjectedScriptHost.cpp:
(Inspector::JSInjectedScriptHost::functionDetails):
* jit/JITThunks.cpp:
(JSC::JITThunks::finalize):
(JSC::JITThunks::hostFunctionStub):
* jit/JITThunks.h:
* runtime/Executable.h:
* runtime/FunctionPrototype.cpp:
(JSC::functionProtoFuncToString):
* runtime/InternalFunction.cpp:
(JSC::InternalFunction::finishCreation):
(JSC::InternalFunction::visitChildren):
(JSC::InternalFunction::name):
(JSC::InternalFunction::displayName):
* runtime/InternalFunction.h:
* runtime/JSBoundFunction.cpp:
(JSC::JSBoundFunction::create):
(JSC::JSBoundFunction::visitChildren):
(JSC::JSBoundFunction::toStringName): Deleted.
* runtime/JSBoundFunction.h:
(JSC::JSBoundFunction::boundThis):
(JSC::JSBoundFunction::boundArgs):
(JSC::JSBoundFunction::createStructure):
* runtime/JSBoundSlotBaseFunction.cpp:
(JSC::boundSlotBaseFunctionCall):
(JSC::JSBoundSlotBaseFunction::create):
* runtime/JSFunction.cpp:
(JSC::JSFunction::initializeRareData):
(JSC::JSFunction::name):
(JSC::JSFunction::displayName):
(JSC::JSFunction::calculatedDisplayName):
(JSC::JSFunction::reifyName):
* runtime/JSFunction.h:
* tests/es6.yaml:

LayoutTests:

* js/function-toString-vs-name-expected.txt: Added.
* js/function-toString-vs-name.html: Added.
* js/script-tests/function-toString-vs-name.js: Added.

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (197814 => 197815)


--- trunk/LayoutTests/ChangeLog	2016-03-08 23:59:18 UTC (rev 197814)
+++ trunk/LayoutTests/ChangeLog	2016-03-09 00:01:09 UTC (rev 197815)
@@ -1,3 +1,14 @@
+2016-03-08  Mark Lam  <[email protected]>
+
+        Implement Function.name support for getters/setters and inferring name of function properties.
+        https://bugs.webkit.org/show_bug.cgi?id=154865
+
+        Reviewed by Geoffrey Garen.
+
+        * js/function-toString-vs-name-expected.txt: Added.
+        * js/function-toString-vs-name.html: Added.
+        * js/script-tests/function-toString-vs-name.js: Added.
+
 2016-03-08  Myles C. Maxfield  <[email protected]>
 
         Font size computed style is innaccurate

Modified: trunk/LayoutTests/inspector/model/remote-object-get-properties-expected.txt (197814 => 197815)


--- trunk/LayoutTests/inspector/model/remote-object-get-properties-expected.txt	2016-03-08 23:59:18 UTC (rev 197814)
+++ trunk/LayoutTests/inspector/model/remote-object-get-properties-expected.txt	2016-03-09 00:01:09 UTC (rev 197815)
@@ -220,7 +220,7 @@
 -----------------------------------------------------
 _expression_: window.boundFunction
 type: function
-description: function () {
+description: function unboundFunction() {
     [native code]
 }
 

Added: trunk/LayoutTests/js/function-toString-vs-name-expected.txt (0 => 197815)


--- trunk/LayoutTests/js/function-toString-vs-name-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/js/function-toString-vs-name-expected.txt	2016-03-09 00:01:09 UTC (rev 197815)
@@ -0,0 +1,3 @@
+
+TEST COMPLETE
+

Added: trunk/LayoutTests/js/function-toString-vs-name.html (0 => 197815)


--- trunk/LayoutTests/js/function-toString-vs-name.html	                        (rev 0)
+++ trunk/LayoutTests/js/function-toString-vs-name.html	2016-03-09 00:01:09 UTC (rev 197815)
@@ -0,0 +1,10 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+<head>
+<script src=""
+</head>
+<body>
+<script src=""
+<script src=""
+</body>
+</html>

Added: trunk/LayoutTests/js/script-tests/function-toString-vs-name.js (0 => 197815)


--- trunk/LayoutTests/js/script-tests/function-toString-vs-name.js	                        (rev 0)
+++ trunk/LayoutTests/js/script-tests/function-toString-vs-name.js	2016-03-09 00:01:09 UTC (rev 197815)
@@ -0,0 +1,419 @@
+// isWhiteSpace() and stripSpaces() are borrowed from
+// kde/script-tests/inbuilt_function_tostring.js and modified.
+
+let section;
+let failures = "";
+let failureCount = 0;
+
+function isWhiteSpace(string) {
+    let cc = string.charCodeAt(0);
+    switch (cc) {
+        case (0x0009):
+        case (0x000B):
+        case (0x000C):
+        case (0x0020):
+        case (0x000A):
+        case (0x000D):
+        case (59): // let's strip out semicolons, too
+            return true;
+            break;
+        default:
+            return false;
+    }
+}
+
+function minimizeSpaces(s) {
+    let currentChar;
+    let strippedString;
+    let previousCharIsWhiteSpace = false;
+    for (currentChar = 0, strippedString = ""; currentChar < s.length; currentChar++) {
+        let ch = s.charAt(currentChar);
+        if (!isWhiteSpace(ch)) {
+            if (previousCharIsWhiteSpace &&
+                (ch == '(' || ch == ')' || ch == '{' || ch == '}' || ch == '[' || ch == ']'))
+                strippedString = strippedString.slice(0, strippedString.length - 1);
+            strippedString += ch;
+            previousCharIsWhiteSpace = false;
+        } else if (!previousCharIsWhiteSpace) {
+            strippedString += ' ';
+            previousCharIsWhiteSpace = true;
+        }
+    }
+    return strippedString;
+}
+
+function shouldBe(desc, funcName, actual, expected) {
+    if (typeof(actual) !== typeof(expected)) {
+        failures += ("   " + section + ": " + desc + "'" + funcName + "': typeof expected: " + typeof(expected) + ", typeof actual: " + typeof(actual) + "\n");
+        failures += ("       expected: '" + expected + "', actual: '" + actual + "'\n");
+        failureCount++;
+    } else if (typeof(actual) !== typeof(expected) || actual !== expected) {
+        failures += ("   " + section + ": " + desc + "'" + funcName + "': expected: '" + expected + "', actual: '" + actual + "'\n");
+        failureCount++;
+    }
+}
+
+function toString(x) {
+    if (typeof x === "symbol")
+        return x.toString();
+    return "" + x;
+}
+
+function test(func, expectedName, expectedToString) {
+    shouldBe("Function.name on ", expectedName, func.name, expectedName);
+
+    let str = func.toString();
+    shouldBe("Function#toString on ", expectedName, minimizeSpaces(str), minimizeSpaces(expectedToString));
+
+    let origDesc = Object.getOwnPropertyDescriptor(func, "name");
+    shouldBe("Function.name configurability of ", expectedName, origDesc.configurable, true);
+    shouldBe("Function.name writability of ", expectedName, origDesc.writable, false);
+    shouldBe("Function.name enumerability of ", expectedName, origDesc.enumerable, false);
+
+    // We should not be able to change Function.name while it is not writable.
+    let origFuncName = func.name;
+    let modifiedFuncName = "modified_" + toString(origFuncName);
+    func.name = modifiedFuncName;
+    shouldBe("Function.name (after attempted write) on ", expectedName, func.name, expectedName);
+
+    // We should be able to change Function.name after making it writable.
+    Object.defineProperty(func, "name", { writable: true });
+    let modifiedDesc = Object.getOwnPropertyDescriptor(func, "name");
+    shouldBe("Function.name writability (after made writable) of ", expectedName, modifiedDesc.writable, true);
+
+    func.name = modifiedFuncName;
+    shouldBe("Function.name (after attempted write again) on ", expectedName, func.name, modifiedFuncName);
+
+    // But the toString name should not have changed.
+    str = func.toString();
+    shouldBe("Function#toString (after attempted write) on ", expectedName, minimizeSpaces(str), minimizeSpaces(expectedToString));
+
+    // Put things back to the original state.
+    Object.defineProperty(func, "name", origDesc);
+}
+
+section = "builtin function";
+{
+    test(Array.prototype.every, "every", "function every() { [native code] }");
+    test(Array.prototype.forEach, "forEach", "function forEach() { [native code] }");
+    test(Array.prototype.some, "some", "function some() { [native code] }");
+
+    section = "bound builtin function";
+    {
+        let o = {}
+        let boundEvery = Array.prototype.every.bind(o);
+        test(boundEvery, "bound every", "function every() { [native code] }");
+        let boundForEach = Array.prototype.forEach.bind(o);
+        test(boundForEach, "bound forEach", "function forEach() { [native code] }");
+    }
+}
+
+section = "native function";
+{
+    test(Array.prototype.splice, "splice", "function splice() { [native code] }");
+    test(Array.prototype.unshift, "unshift", "function unshift() { [native code] }");
+    test(Array.prototype.indexOf, "indexOf", "function indexOf() { [native code] }");
+
+    section = "bound native function";
+    {
+        let o = {}
+        let boundSplice = Array.prototype.splice.bind(o);
+        test(boundSplice, "bound splice", "function splice() { [native code] }");
+        let boundUnshift = Array.prototype.unshift.bind(o);
+        test(boundUnshift, "bound unshift", "function unshift() { [native code] }");
+    }
+}
+
+section = "InternalFunction";
+{
+    test(Array, "Array", "function Array() { [native code] }");
+    test(Boolean, "Boolean", "function Boolean() { [native code] }");
+
+    section = "bound InternalFunction";
+    {
+        let o = {}
+        let boundArray = Array.bind(o);
+        test(boundArray, "bound Array", "function Array() { [native code] }");
+        let boundBoolean = Boolean.bind(o);
+        test(boundBoolean, "bound Boolean", "function Boolean() { [native code] }");
+    }
+}
+
+section = "JS function";
+{
+    function foo1() {}
+    test(foo1, "foo1", "function foo1() {}");
+
+    let foo2 = function() {}
+    test(foo2, "foo2", "function() {}");
+
+    let foo3 = (function() {
+        function goo3() {}
+        return goo3;
+    }) ();
+    test(foo3, "goo3", "function goo3() {}");
+
+    let foo4 = (function() {
+        return (function() {});
+    }) ();
+    test(foo4, "", "function() {}");
+
+    // Test functions in object properties.
+    section = "Object property";
+    let o = {
+        prop1: function() {},
+        prop2: function namedProp2() {}
+    };
+    test(o.prop1, "prop1", "function() {}");
+    test(o.prop2, "namedProp2", "function namedProp2() {}");
+
+    section = "bound JS function";
+    {
+        let o = {}
+        let boundFoo1 = foo1.bind(o);
+        test(boundFoo1, "bound foo1", "function foo1() { [native code] }");
+        let boundFoo2 = foo2.bind(o);
+        test(boundFoo2, "bound foo2", "function foo2() { [native code] }");
+        let boundFoo3 = foo3.bind(o);
+        test(boundFoo3, "bound goo3", "function goo3() { [native code] }");
+        let boundFoo4 = foo4.bind(o);
+        test(boundFoo4, "bound ", "function () { [native code] }");
+
+        test((function(){}).bind({}), "bound ", "function () { [native code] }");
+    }
+}
+
+section = "object shorthand method";
+{
+    let o = {
+        prop1() {},
+        prop2(x) {}
+    };
+    test(o.prop1, "prop1", "function prop1() {}");
+    test(o.prop2, "prop2", "function prop2(x) {}");
+
+    section = "bound object shorthand method";
+    {
+        let boundProp1 = o.prop1.bind(o);
+        test(boundProp1, "bound prop1", "function prop1() { [native code] }");
+        let boundProp2 = o.prop2.bind(o);
+        test(boundProp2, "bound prop2", "function prop2() { [native code] }");
+    }
+}
+
+// FIXME: Uncomment these when we've added support for Function.name of computed properties.
+// section = "Object computed string property";
+// {
+//     let str1 = "foo";
+//     let str2 = "";
+//     let o = {    
+//         [str1]: function() {},
+//         [str2]: function() {}
+//     };
+//     test(o[str1], "foo", "function() {}");
+//     test(o[str2], "", "function() {}");
+// }
+// 
+// let sym1 = Symbol("foo");
+// let sym2 = Symbol();
+
+// section = "Object computed symbol property";
+// {
+//     let o = {    
+//         [sym1]: function() {},
+//         [sym2]: function() {}
+//     };
+//     test(o[sym1], "[foo]", "function() {}");
+//     test(o[sym2], "", "function() {}");
+// }
+
+// section = "Object computed symbol property with shorthand function";
+// {
+//     let o = {
+//         [sym1]() {},
+//         [sym2]() {}
+//     };
+//     test(o[sym1], "[foo]", "function() {}");
+//     test(o[sym2], "", "function() {}");
+// }
+
+// section = "Object computed symbol property with get/set function";
+// {
+//     let o = {
+//         get [sym1]() {},
+//         set [sym1](x) {},
+//         get [sym2]() {},
+//         set [sym2](x) {}
+//     };
+//     let desc = Object.getOwnPropertyDescriptor(o, sym1);
+//     test(desc.get, "get [foo]", "function() {}");
+//     test(desc.set, "set [foo]", "function(x) {}");
+// 
+//     desc = Object.getOwnPropertyDescriptor(o, sym2);
+//     test(desc.get, "get ", "function() {}");
+//     test(desc.set, "set ", "function(x) {}");
+// }
+
+// Test functions in destructuring assignments.
+section = "destructuring assignment";
+{
+    let prop1;
+    let prop2;
+    { prop1 = function() {}, prop2 = function namedProp2() {} }
+    test(prop1, "prop1", "function() {}");
+    test(prop2, "namedProp2", "function namedProp2() {}");
+
+    section = "bound destructuring assignment";
+    {
+        let o = {}
+        let bound1 = prop1.bind(o);
+        test(bound1, "bound prop1", "function prop1() { [native code] }");
+
+        let bound2 = prop2.bind(o);
+        test(bound2, "bound namedProp2", "function namedProp2() { [native code] }");
+    }
+}
+
+section = "dynamically created function";
+{
+    let dynamic1 = new Function("");
+    test(dynamic1, "anonymous", "function anonymous() {}");
+
+    let dynamic2 = new Function("");
+    dynamic2.name = "Goo2";
+    test(dynamic2, "anonymous", "function anonymous() {}");
+
+    section = "bound dynamically created function";
+    {
+        let o = {}
+        let bound1 = dynamic1.bind(o);
+        test(bound1, "bound anonymous", "function anonymous() { [native code] }");
+
+        let bound2 = dynamic2.bind(o);
+        test(bound2, "bound anonymous", "function anonymous() { [native code] }");
+    }
+}
+
+section = "JSBoundSlotBaseFunction";
+{
+    if (typeof document !== "undefined") {
+        let desc = Object.getOwnPropertyDescriptor(document, "location");
+        test(desc.get, "get location", "function location() { [native code] }");
+        test(desc.set, "set location", "function location() { [native code] }");
+
+        section = "bound JSBoundSlotBaseFunction";
+        {
+            let o = {}
+            let bound1 = desc.get.bind(o);
+            test(bound1, "bound get location", "function get location() { [native code] }");
+
+            let bound2 = desc.set.bind(o);
+            test(bound2, "bound set location", "function set location() { [native code] }");
+        }
+    }
+}
+
+section = "get/set function";
+{
+    let o = { get foo() {}, set foo(x){} };
+    let desc = Object.getOwnPropertyDescriptor(o, "foo");
+    test(desc.get, "get foo", "function() {}");
+    test(desc.set, "set foo", "function(x) {}");
+
+    let o1 = { get "bar"() {}, set "bar"(x){} };
+    let desc1 = Object.getOwnPropertyDescriptor(o1, "bar");
+    test(desc1.get, "get bar", "function() {}");
+    test(desc1.set, "set bar", "function(x) {}");
+
+    let o2 = { get 100() {}, set 100(x){} };
+    let desc2 = Object.getOwnPropertyDescriptor(o2, 100);
+    test(desc2.get, "get ", "function() {}");
+    test(desc2.set, "set ", "function(x) {}");
+
+    let o3 = { get [100]() {}, set [100](x){} };
+    let desc3 = Object.getOwnPropertyDescriptor(o3, 100);
+    test(desc3.get, "get ", "function() {}");
+    test(desc3.set, "set ", "function(x) {}");
+
+    section = "bound get/set function";
+    {
+        let bound1;
+        let bound2;
+
+        bound1 = desc.get.bind(o);
+        test(bound1, "bound get foo", "function get foo() { [native code] }");
+        bound2 = desc.set.bind(o);
+        test(bound2, "bound set foo", "function set foo() { [native code] }");
+
+        bound1 = desc1.get.bind(o);
+        test(bound1, "bound get bar", "function get bar() { [native code] }");
+        bound2 = desc1.set.bind(o);
+        test(bound2, "bound set bar", "function set bar() { [native code] }");
+
+        bound1 = desc2.get.bind(o);
+        test(bound1, "bound get ", "function get () { [native code] }");
+        bound2 = desc2.set.bind(o);
+        test(bound2, "bound set ", "function set () { [native code] }");
+
+        bound1 = desc3.get.bind(o);
+        test(bound1, "bound get ", "function get () { [native code] }");
+        bound2 = desc3.set.bind(o);
+        test(bound2, "bound set ", "function set () { [native code] }");
+    }
+}
+
+// https://tc39.github.io/ecma262/#sec-function.prototype.bind
+//     9. Let targetName be ? Get(Target, "name").
+//    10. If Type(targetName) is not String, let targetName be the empty string.
+//    11. Perform SetFunctionName(F, targetName, "bound").
+section = "bound functions with non-string names";
+{
+    let foo = function() {};
+    let bound;
+
+    function setName(func, newName) {
+        Object.defineProperty(func, "name", { writable:true });
+        func.name = newName;
+        Object.defineProperty(func, "name", { writable:false });
+    }
+
+    setName(foo, undefined);
+    test(foo, undefined, "function() {}");
+    bound = foo.bind({});
+    test(bound, "bound ", "function () { [native code] }");    
+
+    setName(foo, null);
+    test(foo, null, "function() {}");
+    bound = foo.bind({});
+    test(bound, "bound ", "function () { [native code] }");    
+
+    setName(foo, true);
+    test(foo, true, "function() {}");
+    bound = foo.bind({});
+    test(bound, "bound ", "function () { [native code] }");    
+
+    setName(foo, false);
+    test(foo, false, "function() {}");
+    bound = foo.bind({});
+    test(bound, "bound ", "function () { [native code] }");    
+
+    setName(foo, 1234.567);
+    test(foo, 1234.567, "function() {}");
+    bound = foo.bind({});
+    test(bound, "bound ", "function () { [native code] }");    
+
+    let anonSym = Symbol();
+    setName(foo, anonSym);
+    test(foo, anonSym, "function() {}");
+    bound = foo.bind({});
+    test(bound, "bound ", "function () { [native code] }");    
+
+    let sym = Symbol("baz");
+    setName(foo, sym);
+    test(foo, sym, "function() {}");
+    bound = foo.bind({});
+    test(bound, "bound ", "function () { [native code] }");    
+}
+
+if (failureCount)
+    throw Error("Found " + failureCount + " failures:\n" + failures);

Modified: trunk/LayoutTests/platform/mac/http/tests/media/media-source/SourceBuffer-abort-readyState-expected.txt (197814 => 197815)


--- trunk/LayoutTests/platform/mac/http/tests/media/media-source/SourceBuffer-abort-readyState-expected.txt	2016-03-08 23:59:18 UTC (rev 197814)
+++ trunk/LayoutTests/platform/mac/http/tests/media/media-source/SourceBuffer-abort-readyState-expected.txt	2016-03-09 00:01:09 UTC (rev 197815)
@@ -4,7 +4,7 @@
 http://127.0.0.1:8000/media/media-source/SourceBuffer-abort-readyState.html:20:29
 step@http://127.0.0.1:8000/w3c/resources/testharness.js:1160:30
 isTypeSupported@http://127.0.0.1:8000/media/media-source/SourceBuffer-abort-readyState.html:19:18
-bound isTypeSupported@[native code]
+isTypeSupported@[native code]
 http://127.0.0.1:8000/media/media-source/SourceBuffer-abort-readyState.html:42:36
 step@http://127.0.0.1:8000/w3c/resources/testharness.js:1160:30
 async_test@http://127.0.0.1:8000/w3c/resources/testharness.js:460:26

Modified: trunk/LayoutTests/platform/mac/http/tests/media/media-source/SourceBuffer-abort-removed-expected.txt (197814 => 197815)


--- trunk/LayoutTests/platform/mac/http/tests/media/media-source/SourceBuffer-abort-removed-expected.txt	2016-03-08 23:59:18 UTC (rev 197814)
+++ trunk/LayoutTests/platform/mac/http/tests/media/media-source/SourceBuffer-abort-removed-expected.txt	2016-03-09 00:01:09 UTC (rev 197815)
@@ -4,7 +4,7 @@
 http://127.0.0.1:8000/media/media-source/SourceBuffer-abort-removed.html:19:29
 step@http://127.0.0.1:8000/w3c/resources/testharness.js:1160:30
 isTypeSupported@http://127.0.0.1:8000/media/media-source/SourceBuffer-abort-removed.html:18:18
-bound isTypeSupported@[native code]
+isTypeSupported@[native code]
 http://127.0.0.1:8000/media/media-source/SourceBuffer-abort-removed.html:28:36
 step@http://127.0.0.1:8000/w3c/resources/testharness.js:1160:30
 async_test@http://127.0.0.1:8000/w3c/resources/testharness.js:460:26

Modified: trunk/LayoutTests/platform/mac/http/tests/media/media-source/SourceBuffer-abort-updating-expected.txt (197814 => 197815)


--- trunk/LayoutTests/platform/mac/http/tests/media/media-source/SourceBuffer-abort-updating-expected.txt	2016-03-08 23:59:18 UTC (rev 197814)
+++ trunk/LayoutTests/platform/mac/http/tests/media/media-source/SourceBuffer-abort-updating-expected.txt	2016-03-09 00:01:09 UTC (rev 197815)
@@ -4,7 +4,7 @@
 http://127.0.0.1:8000/media/media-source/SourceBuffer-abort-updating.html:33:29
 step@http://127.0.0.1:8000/w3c/resources/testharness.js:1160:30
 isTypeSupported@http://127.0.0.1:8000/media/media-source/SourceBuffer-abort-updating.html:32:18
-bound isTypeSupported@[native code]
+isTypeSupported@[native code]
 http://127.0.0.1:8000/media/media-source/SourceBuffer-abort-updating.html:42:36
 step@http://127.0.0.1:8000/w3c/resources/testharness.js:1160:30
 async_test@http://127.0.0.1:8000/w3c/resources/testharness.js:460:26

Modified: trunk/LayoutTests/platform/mac/http/tests/media/media-source/mediasource-sourcebuffer-mode-expected.txt (197814 => 197815)


--- trunk/LayoutTests/platform/mac/http/tests/media/media-source/mediasource-sourcebuffer-mode-expected.txt	2016-03-08 23:59:18 UTC (rev 197814)
+++ trunk/LayoutTests/platform/mac/http/tests/media/media-source/mediasource-sourcebuffer-mode-expected.txt	2016-03-09 00:01:09 UTC (rev 197815)
@@ -8,7 +8,7 @@
 assert_throws@http://127.0.0.1:8000/w3c/resources/testharness.js:947:19
 http://127.0.0.1:8000/media/media-source/mediasource-sourcebuffer-mode.html:114:32
 handleWaitCallback_@http://127.0.0.1:8000/media/media-source/mediasource-util.js:97:17
-bound @[native code]
+handleWaitCallback_@[native code]
 step@http://127.0.0.1:8000/w3c/resources/testharness.js:1160:30
 http://127.0.0.1:8000/w3c/resources/testharness.js:1189:33)
 

Modified: trunk/Source/_javascript_Core/ChangeLog (197814 => 197815)


--- trunk/Source/_javascript_Core/ChangeLog	2016-03-08 23:59:18 UTC (rev 197814)
+++ trunk/Source/_javascript_Core/ChangeLog	2016-03-09 00:01:09 UTC (rev 197815)
@@ -1,3 +1,92 @@
+2016-03-08  Mark Lam  <[email protected]>
+
+        Implement Function.name support for getters/setters and inferring name of function properties.
+        https://bugs.webkit.org/show_bug.cgi?id=154865
+
+        Reviewed by Geoffrey Garen.
+
+        1. toString() no longer uses the value of Function.name as the name of the
+           function in the returned string, because ...
+
+            i. Function.name is supposed to be configurable.  Hence, it can be made
+               writable and can be set to any JSValue, or deleted.
+           ii. Function.prototype.toString() is supposed to produce a string that can be
+               eval'ed.  Hence, for JS functions, the function name in the produced
+               string must be a legal function name (and not some arbitrary value set in
+               Function.name).  For example, while a number is a legal value for
+               Function.name, it is not legal as the function name in the toString()
+               string.
+
+           Instead, we'll always use the original name from the JS source that the
+           function was parsed from.
+
+        2. JSFunction::name() now always return the original name, not the value of
+           the Function.name property.  As a result, it also no longer needs an
+           ExecState* arg.
+
+           If the original name is an empty string, JSFunction::name() will use the
+           inferred name.
+
+        3. For JS functions, the original name can be attained from their
+           FunctionExecutable object.
+
+           For host/native functions (which do not have a FunctionExecutable), we get the
+           "original" name from its NativeExecutable.
+
+        4. The m_hostFunctionStubMap now keys its NativeExecutable pointers using the
+           original name, in addition to the native function and constructor pointers.
+
+           This is needed because we want a different NativeExecutable for functions with
+           a different name (to satisfy (3) above).
+
+        5. Changed JSBoundFunction to store the name of its bound function in its
+           NativeExecutable.  This will later be used to generate the toString() string.
+           It's Function.name value is eagerly initialized at construction time.
+
+        6. Function.name for getters/setters are now prefixed with "get"/"set".
+           This was done both for the JSBoundSlotBaseFunctions and JS definable get/set
+           functions.
+
+        7. Added InternalFunction::m_originalName so that we can use it to generate the
+           toString() string.  We're storing it as a JSString instead of a WTF::String
+           only because we want InternalFunction to be continue to be trivially
+           destructible.
+
+        * inspector/JSInjectedScriptHost.cpp:
+        (Inspector::JSInjectedScriptHost::functionDetails):
+        * jit/JITThunks.cpp:
+        (JSC::JITThunks::finalize):
+        (JSC::JITThunks::hostFunctionStub):
+        * jit/JITThunks.h:
+        * runtime/Executable.h:
+        * runtime/FunctionPrototype.cpp:
+        (JSC::functionProtoFuncToString):
+        * runtime/InternalFunction.cpp:
+        (JSC::InternalFunction::finishCreation):
+        (JSC::InternalFunction::visitChildren):
+        (JSC::InternalFunction::name):
+        (JSC::InternalFunction::displayName):
+        * runtime/InternalFunction.h:
+        * runtime/JSBoundFunction.cpp:
+        (JSC::JSBoundFunction::create):
+        (JSC::JSBoundFunction::visitChildren):
+        (JSC::JSBoundFunction::toStringName): Deleted.
+        * runtime/JSBoundFunction.h:
+        (JSC::JSBoundFunction::boundThis):
+        (JSC::JSBoundFunction::boundArgs):
+        (JSC::JSBoundFunction::createStructure):
+        * runtime/JSBoundSlotBaseFunction.cpp:
+        (JSC::boundSlotBaseFunctionCall):
+        (JSC::JSBoundSlotBaseFunction::create):
+        * runtime/JSFunction.cpp:
+        (JSC::JSFunction::initializeRareData):
+        (JSC::JSFunction::name):
+        (JSC::JSFunction::displayName):
+        (JSC::JSFunction::calculatedDisplayName):
+        (JSC::JSFunction::reifyName):
+        * runtime/JSFunction.h:
+        * tests/es6.yaml:
+
 2016-03-08  Commit Queue  <[email protected]>
 
         Unreviewed, rolling out r197793 and r197799.

Modified: trunk/Source/_javascript_Core/inspector/JSInjectedScriptHost.cpp (197814 => 197815)


--- trunk/Source/_javascript_Core/inspector/JSInjectedScriptHost.cpp	2016-03-08 23:59:18 UTC (rev 197814)
+++ trunk/Source/_javascript_Core/inspector/JSInjectedScriptHost.cpp	2016-03-09 00:01:09 UTC (rev 197815)
@@ -203,7 +203,7 @@
     JSObject* result = constructEmptyObject(exec);
     result->putDirect(exec->vm(), Identifier::fromString(exec, "location"), location);
 
-    String name = function->name(exec);
+    String name = function->name();
     if (!name.isEmpty())
         result->putDirect(exec->vm(), Identifier::fromString(exec, "name"), jsString(exec, name));
 

Modified: trunk/Source/_javascript_Core/jit/JITThunks.cpp (197814 => 197815)


--- trunk/Source/_javascript_Core/jit/JITThunks.cpp	2016-03-08 23:59:18 UTC (rev 197814)
+++ trunk/Source/_javascript_Core/jit/JITThunks.cpp	2016-03-09 00:01:09 UTC (rev 197815)
@@ -79,14 +79,14 @@
 void JITThunks::finalize(Handle<Unknown> handle, void*)
 {
     auto* nativeExecutable = jsCast<NativeExecutable*>(handle.get().asCell());
-    weakRemove(*m_hostFunctionStubMap, std::make_pair(nativeExecutable->function(), nativeExecutable->constructor()), nativeExecutable);
+    weakRemove(*m_hostFunctionStubMap, std::make_tuple(nativeExecutable->function(), nativeExecutable->constructor(), nativeExecutable->name()), nativeExecutable);
 }
 
 NativeExecutable* JITThunks::hostFunctionStub(VM* vm, NativeFunction function, NativeFunction constructor, const String& name)
 {
     ASSERT(!isCompilationThread());
 
-    if (NativeExecutable* nativeExecutable = m_hostFunctionStubMap->get(std::make_pair(function, constructor)))
+    if (NativeExecutable* nativeExecutable = m_hostFunctionStubMap->get(std::make_tuple(function, constructor, name)))
         return nativeExecutable;
 
     NativeExecutable* nativeExecutable = NativeExecutable::create(
@@ -95,7 +95,7 @@
         function,
         adoptRef(new NativeJITCode(MacroAssemblerCodeRef::createSelfManagedCodeRef(ctiNativeConstruct(vm)), JITCode::HostCallThunk)),
         constructor, NoIntrinsic, name);
-    weakAdd(*m_hostFunctionStubMap, std::make_pair(function, constructor), Weak<NativeExecutable>(nativeExecutable, this));
+    weakAdd(*m_hostFunctionStubMap, std::make_tuple(function, constructor, name), Weak<NativeExecutable>(nativeExecutable, this));
     return nativeExecutable;
 }
 
@@ -104,7 +104,7 @@
     ASSERT(!isCompilationThread());    
     ASSERT(vm->canUseJIT());
 
-    if (NativeExecutable* nativeExecutable = m_hostFunctionStubMap->get(std::make_pair(function, &callHostFunctionAsConstructor)))
+    if (NativeExecutable* nativeExecutable = m_hostFunctionStubMap->get(std::make_tuple(function, &callHostFunctionAsConstructor, name)))
         return nativeExecutable;
 
     RefPtr<JITCode> forCall;
@@ -117,7 +117,7 @@
     RefPtr<JITCode> forConstruct = adoptRef(new NativeJITCode(MacroAssemblerCodeRef::createSelfManagedCodeRef(ctiNativeConstruct(vm)), JITCode::HostCallThunk));
     
     NativeExecutable* nativeExecutable = NativeExecutable::create(*vm, forCall, function, forConstruct, callHostFunctionAsConstructor, intrinsic, name);
-    weakAdd(*m_hostFunctionStubMap, std::make_pair(function, &callHostFunctionAsConstructor), Weak<NativeExecutable>(nativeExecutable, this));
+    weakAdd(*m_hostFunctionStubMap, std::make_tuple(function, &callHostFunctionAsConstructor, name), Weak<NativeExecutable>(nativeExecutable, this));
     return nativeExecutable;
 }
 

Modified: trunk/Source/_javascript_Core/jit/JITThunks.h (197814 => 197815)


--- trunk/Source/_javascript_Core/jit/JITThunks.h	2016-03-08 23:59:18 UTC (rev 197814)
+++ trunk/Source/_javascript_Core/jit/JITThunks.h	2016-03-09 00:01:09 UTC (rev 197815)
@@ -36,6 +36,7 @@
 #include "Weak.h"
 #include "WeakHandleOwner.h"
 #include "WeakInlines.h"
+#include <tuple>
 #include <wtf/HashMap.h>
 #include <wtf/RefPtr.h>
 #include <wtf/ThreadingPrimitives.h>
@@ -67,7 +68,39 @@
     
     typedef HashMap<ThunkGenerator, MacroAssemblerCodeRef> CTIStubMap;
     CTIStubMap m_ctiStubMap;
-    typedef HashMap<std::pair<NativeFunction, NativeFunction>, Weak<NativeExecutable>> HostFunctionStubMap;
+
+    typedef std::tuple<NativeFunction, NativeFunction, String> HostFunctionKey;
+
+    struct HostFunctionHash {
+        static unsigned hash(const HostFunctionKey& key)
+        {
+            unsigned hash = WTF::pairIntHash(hashPointer(std::get<0>(key)), hashPointer(std::get<1>(key)));
+            if (!std::get<2>(key).isNull())
+                hash = WTF::pairIntHash(hash, DefaultHash<String>::Hash::hash(std::get<2>(key)));
+            return hash;
+        }
+        static bool equal(const HostFunctionKey& a, const HostFunctionKey& b)
+        {
+            return (std::get<0>(a) == std::get<0>(b)) && (std::get<1>(a) == std::get<1>(b)) && (std::get<2>(a) == std::get<2>(b));
+        }
+        static const bool safeToCompareToEmptyOrDeleted = true;
+
+    private:
+        static inline unsigned hashPointer(NativeFunction p)
+        {
+            return DefaultHash<NativeFunction>::Hash::hash(p);
+        }
+    };
+
+    struct HostFunctionHashTrait : WTF::GenericHashTraits<HostFunctionKey> {
+        static const bool emptyValueIsZero = true;
+        static EmptyValueType emptyValue() { return std::make_tuple(nullptr, nullptr, String()); }
+
+        static void constructDeletedValue(HostFunctionKey& slot) { std::get<0>(slot) = reinterpret_cast<NativeFunction>(-1); }
+        static bool isDeletedValue(const HostFunctionKey& value) { return std::get<0>(value) == reinterpret_cast<NativeFunction>(-1); }
+    };
+    
+    typedef HashMap<HostFunctionKey, Weak<NativeExecutable>, HostFunctionHash, HostFunctionHashTrait> HostFunctionStubMap;
     std::unique_ptr<HostFunctionStubMap> m_hostFunctionStubMap;
     Lock m_lock;
 };

Modified: trunk/Source/_javascript_Core/runtime/Executable.h (197814 => 197815)


--- trunk/Source/_javascript_Core/runtime/Executable.h	2016-03-08 23:59:18 UTC (rev 197814)
+++ trunk/Source/_javascript_Core/runtime/Executable.h	2016-03-09 00:01:09 UTC (rev 197815)
@@ -663,10 +663,15 @@
     bool isBuiltinFunction() const { return m_unlinkedExecutable->isBuiltinFunction(); }
     ConstructAbility constructAbility() const { return m_unlinkedExecutable->constructAbility(); }
     bool isArrowFunction() const { return parseMode() == SourceParseMode::ArrowFunctionMode; }
+    bool isGetter() const { return parseMode() == SourceParseMode::GetterMode; }
+    bool isSetter() const { return parseMode() == SourceParseMode::SetterMode; }
     DerivedContextType derivedContextType() const { return m_unlinkedExecutable->derivedContextType(); }
     bool isClassConstructorFunction() const { return m_unlinkedExecutable->isClassConstructorFunction(); }
     const Identifier& name() { return m_unlinkedExecutable->name(); }
     const Identifier& inferredName() { return m_unlinkedExecutable->inferredName(); }
+    // FIXME: ecmaName() needs to be reimplement to be based on ES6 rules of determining the inferred
+    // Function.name from non-computed names. https://bugs.webkit.org/show_bug.cgi?id=155203
+    const Identifier& ecmaName() { return inferredName(); }
     size_t parameterCount() const { return m_unlinkedExecutable->parameterCount(); } // Excluding 'this'!
     SourceParseMode parseMode() const { return m_unlinkedExecutable->parseMode(); }
 

Modified: trunk/Source/_javascript_Core/runtime/FunctionPrototype.cpp (197814 => 197815)


--- trunk/Source/_javascript_Core/runtime/FunctionPrototype.cpp	2016-03-08 23:59:18 UTC (rev 197814)
+++ trunk/Source/_javascript_Core/runtime/FunctionPrototype.cpp	2016-03-09 00:01:09 UTC (rev 197815)
@@ -85,14 +85,8 @@
     JSValue thisValue = exec->thisValue();
     if (thisValue.inherits(JSFunction::info())) {
         JSFunction* function = jsCast<JSFunction*>(thisValue);
-        if (function->isHostOrBuiltinFunction()) {
-            String name;
-            if (JSBoundFunction* boundFunction = jsDynamicCast<JSBoundFunction*>(function))
-                name = boundFunction->toStringName(exec);
-            else
-                name = function->name(exec);
-            return JSValue::encode(jsMakeNontrivialString(exec, "function ", name, "() {\n    [native code]\n}"));
-        }
+        if (function->isHostOrBuiltinFunction())
+            return JSValue::encode(jsMakeNontrivialString(exec, "function ", function->name(), "() {\n    [native code]\n}"));
 
         FunctionExecutable* executable = function->jsExecutable();
         
@@ -101,7 +95,7 @@
         StringView source = executable->source().provider()->getRange(
             executable->parametersStartOffset(),
             executable->parametersStartOffset() + executable->source().length());
-        return JSValue::encode(jsMakeNontrivialString(exec, functionHeader, function->name(exec), source));
+        return JSValue::encode(jsMakeNontrivialString(exec, functionHeader, function->name(), source));
     }
 
     if (thisValue.inherits(InternalFunction::info())) {
@@ -167,7 +161,8 @@
         }
     }
 
-    JSString* name = target.get(exec, exec->propertyNames().name).toString(exec);
+    JSValue nameProp = target.get(exec, exec->propertyNames().name);
+    JSString* name = nameProp.isString() ? nameProp.toString(exec) : jsEmptyString(exec);
     return JSValue::encode(JSBoundFunction::create(vm, exec, globalObject, targetObject, exec->argument(0), boundArgs, length, name->value(exec)));
 }
 

Modified: trunk/Source/_javascript_Core/runtime/InternalFunction.cpp (197814 => 197815)


--- trunk/Source/_javascript_Core/runtime/InternalFunction.cpp	2016-03-08 23:59:18 UTC (rev 197814)
+++ trunk/Source/_javascript_Core/runtime/InternalFunction.cpp	2016-03-09 00:01:09 UTC (rev 197815)
@@ -44,14 +44,27 @@
     Base::finishCreation(vm);
     ASSERT(inherits(info()));
     ASSERT(methodTable()->getCallData != InternalFunction::info()->methodTable.getCallData);
-    putDirect(vm, vm.propertyNames->name, jsString(&vm, name), DontDelete | ReadOnly | DontEnum);
+    JSString* nameString = jsString(&vm, name);
+    m_originalName.set(vm, this, nameString);
+    putDirect(vm, vm.propertyNames->name, nameString, ReadOnly | DontEnum);
 }
 
-const String& InternalFunction::name(ExecState* exec)
+void InternalFunction::visitChildren(JSCell* cell, SlotVisitor& visitor)
 {
-    return asString(getDirect(exec->vm(), exec->vm().propertyNames->name))->tryGetValue();
+    InternalFunction* thisObject = jsCast<InternalFunction*>(cell);
+    ASSERT_GC_OBJECT_INHERITS(thisObject, info());
+    Base::visitChildren(thisObject, visitor);
+    
+    visitor.append(&thisObject->m_originalName);
 }
 
+const String& InternalFunction::name(ExecState*)
+{
+    const String& name = m_originalName->tryGetValue();
+    ASSERT(name); // m_originalName was built from a String, and hence, there is no rope to resolve.
+    return name;
+}
+
 const String InternalFunction::displayName(ExecState* exec)
 {
     JSValue displayName = getDirect(exec->vm(), exec->vm().propertyNames->displayName);

Modified: trunk/Source/_javascript_Core/runtime/InternalFunction.h (197814 => 197815)


--- trunk/Source/_javascript_Core/runtime/InternalFunction.h	2016-03-08 23:59:18 UTC (rev 197814)
+++ trunk/Source/_javascript_Core/runtime/InternalFunction.h	2016-03-09 00:01:09 UTC (rev 197815)
@@ -38,6 +38,8 @@
 
     DECLARE_EXPORT_INFO;
 
+    JS_EXPORT_PRIVATE static void visitChildren(JSCell*, SlotVisitor&);
+
     JS_EXPORT_PRIVATE const String& name(ExecState*);
     const String displayName(ExecState*);
     const String calculatedDisplayName(ExecState*);
@@ -55,6 +57,7 @@
     JS_EXPORT_PRIVATE void finishCreation(VM&, const String& name);
 
     static CallType getCallData(JSCell*, CallData&);
+    WriteBarrier<JSString> m_originalName;
 };
 
 InternalFunction* asInternalFunction(JSValue);

Modified: trunk/Source/_javascript_Core/runtime/JSBoundFunction.cpp (197814 => 197815)


--- trunk/Source/_javascript_Core/runtime/JSBoundFunction.cpp	2016-03-08 23:59:18 UTC (rev 197814)
+++ trunk/Source/_javascript_Core/runtime/JSBoundFunction.cpp	2016-03-09 00:01:09 UTC (rev 197815)
@@ -124,7 +124,7 @@
     ConstructData constructData;
     ConstructType constructType = JSC::getConstructData(targetFunction, constructData);
     bool canConstruct = constructType != ConstructType::None;
-    NativeExecutable* executable = vm.getHostFunction(boundFunctionCall, canConstruct ? boundFunctionConstruct : callHostFunctionAsConstructor, ASCIILiteral("Function.prototype.bind result"));
+    NativeExecutable* executable = vm.getHostFunction(boundFunctionCall, canConstruct ? boundFunctionConstruct : callHostFunctionAsConstructor, name);
     Structure* structure = getBoundFunctionStructure(vm, exec, globalObject, targetFunction);
     if (UNLIKELY(vm.exception()))
         return nullptr;
@@ -167,9 +167,4 @@
     visitor.append(&thisObject->m_boundArgs);
 }
 
-String JSBoundFunction::toStringName(ExecState* exec)
-{
-    return m_targetFunction->get(exec, exec->vm().propertyNames->name).toWTFString(exec);
-}
-
 } // namespace JSC

Modified: trunk/Source/_javascript_Core/runtime/JSBoundFunction.h (197814 => 197815)


--- trunk/Source/_javascript_Core/runtime/JSBoundFunction.h	2016-03-08 23:59:18 UTC (rev 197814)
+++ trunk/Source/_javascript_Core/runtime/JSBoundFunction.h	2016-03-09 00:01:09 UTC (rev 197815)
@@ -40,7 +40,7 @@
     typedef JSFunction Base;
     const static unsigned StructureFlags = ~ImplementsDefaultHasInstance & Base::StructureFlags;
 
-    static JSBoundFunction* create(VM&, ExecState*, JSGlobalObject*, JSObject* targetFunction, JSValue boundThis, JSValue boundArgs, int, const String&);
+    static JSBoundFunction* create(VM&, ExecState*, JSGlobalObject*, JSObject* targetFunction, JSValue boundThis, JSValue boundArgs, int, const String& name);
     
     static bool customHasInstance(JSObject*, ExecState*, JSValue);
 
@@ -48,9 +48,7 @@
     JSValue boundThis() { return m_boundThis.get(); }
     JSValue boundArgs() { return m_boundArgs.get(); }
 
-    String toStringName(ExecState*);
-
-    static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype) 
+    static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)
     {
         ASSERT(globalObject);
         return Structure::create(vm, globalObject, prototype, TypeInfo(JSFunctionType, StructureFlags), info()); 
@@ -64,7 +62,7 @@
 private:
     JSBoundFunction(VM&, JSGlobalObject*, Structure*, JSObject* targetFunction, JSValue boundThis, JSValue boundArgs);
     
-    void finishCreation(VM&, NativeExecutable*, int, const String&);
+    void finishCreation(VM&, NativeExecutable*, int length, const String& name);
 
     WriteBarrier<JSObject> m_targetFunction;
     WriteBarrier<Unknown> m_boundThis;

Modified: trunk/Source/_javascript_Core/runtime/JSBoundSlotBaseFunction.cpp (197814 => 197815)


--- trunk/Source/_javascript_Core/runtime/JSBoundSlotBaseFunction.cpp	2016-03-08 23:59:18 UTC (rev 197814)
+++ trunk/Source/_javascript_Core/runtime/JSBoundSlotBaseFunction.cpp	2016-03-09 00:01:09 UTC (rev 197815)
@@ -50,7 +50,7 @@
     if (!getter)
         return JSValue::encode(jsUndefined());
 
-    const String& name = boundSlotBaseFunction->name(exec);
+    const String& name = boundSlotBaseFunction->name();
     return getter(exec, JSValue::encode(exec->thisValue()), PropertyName(Identifier::fromString(exec, name)));
 }
 
@@ -67,7 +67,8 @@
     JSBoundSlotBaseFunction* function = new (NotNull, allocateCell<JSBoundSlotBaseFunction>(vm.heap)) JSBoundSlotBaseFunction(vm, globalObject, globalObject->boundSlotBaseFunctionStructure(), type);
 
     // Can't do this during initialization because getHostFunction might do a GC allocation.
-    function->finishCreation(vm, executable, boundSlotBase, getterSetter, name);
+    String prefix = (type == Type::Getter) ? "get " : "set ";
+    function->finishCreation(vm, executable, boundSlotBase, getterSetter, makeString(prefix, name));
     return function;
 }
 

Modified: trunk/Source/_javascript_Core/runtime/JSCJSValue.cpp (197814 => 197815)


--- trunk/Source/_javascript_Core/runtime/JSCJSValue.cpp	2016-03-08 23:59:18 UTC (rev 197814)
+++ trunk/Source/_javascript_Core/runtime/JSCJSValue.cpp	2016-03-09 00:01:09 UTC (rev 197815)
@@ -207,6 +207,7 @@
     if (prototype->attemptToInterceptPutByIndexOnHoleForPrototype(exec, *this, propertyName, value, shouldThrow))
         return;
     
+    if (shouldThrow && !exec->hadException())
     if (shouldThrow)
         throwTypeError(exec, StrictModeReadonlyPropertyWriteError);
 }

Modified: trunk/Source/_javascript_Core/runtime/JSFunction.cpp (197814 => 197815)


--- trunk/Source/_javascript_Core/runtime/JSFunction.cpp	2016-03-08 23:59:18 UTC (rev 197814)
+++ trunk/Source/_javascript_Core/runtime/JSFunction.cpp	2016-03-09 00:01:09 UTC (rev 197815)
@@ -177,9 +177,13 @@
     return m_rareData.get();
 }
 
-String JSFunction::name(ExecState* exec)
+String JSFunction::name()
 {
-    return get(exec, exec->vm().propertyNames->name).toWTFString(exec);
+    if (isHostFunction()) {
+        NativeExecutable* executable = jsCast<NativeExecutable*>(this->executable());
+        return executable->name();
+    }
+    return jsExecutable()->name().string();
 }
 
 String JSFunction::displayName(ExecState* exec)
@@ -199,7 +203,7 @@
     if (!explicitName.isEmpty())
         return explicitName;
     
-    const String actualName = name(exec);
+    const String actualName = name();
     if (!actualName.isEmpty() || isHostOrBuiltinFunction())
         return actualName;
     
@@ -589,9 +593,19 @@
     ASSERT(!hasReifiedName());
     ASSERT(!isHostFunction());
     unsigned initialAttributes = DontEnum | ReadOnly;
-    const Identifier& identifier = exec->propertyNames().name;
-    putDirect(vm, identifier, jsString(exec, jsExecutable()->name().string()), initialAttributes);
+    const Identifier& propID = exec->propertyNames().name;
 
+    const Identifier& nameID = jsExecutable()->name();
+    String name = nameID.string();
+    if (name.isEmpty())
+        name = jsExecutable()->ecmaName().string();
+
+    if (jsExecutable()->isGetter())
+        name = makeString("get ", name);
+    else if (jsExecutable()->isSetter())
+        name = makeString("set ", name);
+
+    putDirect(vm, propID, jsString(exec, name), initialAttributes);
     rareData->setHasReifiedName();
 }
 

Modified: trunk/Source/_javascript_Core/runtime/JSFunction.h (197814 => 197815)


--- trunk/Source/_javascript_Core/runtime/JSFunction.h	2016-03-08 23:59:18 UTC (rev 197814)
+++ trunk/Source/_javascript_Core/runtime/JSFunction.h	2016-03-09 00:01:09 UTC (rev 197815)
@@ -81,7 +81,7 @@
     JS_EXPORT_PRIVATE static JSFunction* createBuiltinFunction(VM&, FunctionExecutable*, JSGlobalObject*);
     static JSFunction* createBuiltinFunction(VM&, FunctionExecutable*, JSGlobalObject*, const String& name);
 
-    JS_EXPORT_PRIVATE String name(ExecState*);
+    JS_EXPORT_PRIVATE String name();
     JS_EXPORT_PRIVATE String displayName(ExecState*);
     const String calculatedDisplayName(ExecState*);
 

Modified: trunk/Source/_javascript_Core/tests/es6.yaml (197814 => 197815)


--- trunk/Source/_javascript_Core/tests/es6.yaml	2016-03-08 23:59:18 UTC (rev 197814)
+++ trunk/Source/_javascript_Core/tests/es6.yaml	2016-03-09 00:01:09 UTC (rev 197815)
@@ -791,7 +791,7 @@
 - path: es6/Function_is_subclassable_Function.prototype.call.js
   cmd: runES6 :normal
 - path: es6/function_name_property_accessor_properties.js
-  cmd: runES6 :fail
+  cmd: runES6 :normal
 - path: es6/function_name_property_bound_functions.js
   cmd: runES6 :normal
 - path: es6/function_name_property_class_expressions.js
@@ -811,7 +811,7 @@
 - path: es6/function_name_property_variables_class.js
   cmd: runES6 :fail
 - path: es6/function_name_property_variables_function.js
-  cmd: runES6 :fail
+  cmd: runES6 :normal
 - path: es6/generators_%GeneratorPrototype%.constructor.js
   cmd: runES6 :normal
 - path: es6/generators_%GeneratorPrototype%.js
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to