Ignore:
Timestamp:
Mar 8, 2016, 4:01:09 PM (9 years ago)
Author:
[email protected]
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/JavaScriptCore:

  1. toString() no longer uses the value of Function.name as the name of the function in the returned string, because ...
  1. Function.name is supposed to be configurable. Hence, it can be made writable and can be set to any JSValue, or deleted.
  1. 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.

  1. 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.

  1. 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.

  1. 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).

  1. 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.
  1. Function.name for getters/setters are now prefixed with "get"/"set". This was done both for the JSBoundSlotBaseFunctions and JS definable get/set functions.
  1. 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.
File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/jit/JITThunks.h

    r195000 r197815  
    3737#include "WeakHandleOwner.h"
    3838#include "WeakInlines.h"
     39#include <tuple>
    3940#include <wtf/HashMap.h>
    4041#include <wtf/RefPtr.h>
     
    6869    typedef HashMap<ThunkGenerator, MacroAssemblerCodeRef> CTIStubMap;
    6970    CTIStubMap m_ctiStubMap;
    70     typedef HashMap<std::pair<NativeFunction, NativeFunction>, Weak<NativeExecutable>> HostFunctionStubMap;
     71
     72    typedef std::tuple<NativeFunction, NativeFunction, String> HostFunctionKey;
     73
     74    struct HostFunctionHash {
     75        static unsigned hash(const HostFunctionKey& key)
     76        {
     77            unsigned hash = WTF::pairIntHash(hashPointer(std::get<0>(key)), hashPointer(std::get<1>(key)));
     78            if (!std::get<2>(key).isNull())
     79                hash = WTF::pairIntHash(hash, DefaultHash<String>::Hash::hash(std::get<2>(key)));
     80            return hash;
     81        }
     82        static bool equal(const HostFunctionKey& a, const HostFunctionKey& b)
     83        {
     84            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));
     85        }
     86        static const bool safeToCompareToEmptyOrDeleted = true;
     87
     88    private:
     89        static inline unsigned hashPointer(NativeFunction p)
     90        {
     91            return DefaultHash<NativeFunction>::Hash::hash(p);
     92        }
     93    };
     94
     95    struct HostFunctionHashTrait : WTF::GenericHashTraits<HostFunctionKey> {
     96        static const bool emptyValueIsZero = true;
     97        static EmptyValueType emptyValue() { return std::make_tuple(nullptr, nullptr, String()); }
     98
     99        static void constructDeletedValue(HostFunctionKey& slot) { std::get<0>(slot) = reinterpret_cast<NativeFunction>(-1); }
     100        static bool isDeletedValue(const HostFunctionKey& value) { return std::get<0>(value) == reinterpret_cast<NativeFunction>(-1); }
     101    };
     102   
     103    typedef HashMap<HostFunctionKey, Weak<NativeExecutable>, HostFunctionHash, HostFunctionHashTrait> HostFunctionStubMap;
    71104    std::unique_ptr<HostFunctionStubMap> m_hostFunctionStubMap;
    72105    Lock m_lock;
Note: See TracChangeset for help on using the changeset viewer.