Changeset 95751 in webkit for trunk/Source/JavaScriptCore


Ignore:
Timestamp:
Sep 22, 2011, 2:22:17 PM (14 years ago)
Author:
[email protected]
Message:

Implement Function.prototype.bind
https://bugs.webkit.org/show_bug.cgi?id=26382

Reviewed by Sam Weinig.

Source/JavaScriptCore:

This patch provides a basic functional implementation
for Function.bind. It should (hopefully!) be fully
functionally correct, and the bound functions can be
called to quickly (since they are a subclass of
JSFunction, not InternalFunction), but we'll probably
want to follow up with some optimization work to keep
bound calls in JIT code.

(JSC::JITThunks::hostFunctionStub):

  • jit/JITStubs.h:
  • jsc.cpp:

(GlobalObject::addFunction):

  • runtime/CommonIdentifiers.h:
  • runtime/ConstructData.h:
  • runtime/Executable.h:

(JSC::NativeExecutable::NativeExecutable):

  • runtime/FunctionPrototype.cpp:

(JSC::FunctionPrototype::addFunctionProperties):
(JSC::functionProtoFuncBind):

  • runtime/FunctionPrototype.h:
  • runtime/JSBoundFunction.cpp: Added.

(JSC::boundFunctionCall):
(JSC::boundFunctionConstruct):
(JSC::JSBoundFunction::create):
(JSC::JSBoundFunction::hasInstance):
(JSC::JSBoundFunction::getOwnPropertySlot):
(JSC::JSBoundFunction::getOwnPropertyDescriptor):
(JSC::JSBoundFunction::JSBoundFunction):
(JSC::JSBoundFunction::finishCreation):

  • runtime/JSBoundFunction.h: Added.

(JSC::JSBoundFunction::targetFunction):
(JSC::JSBoundFunction::boundThis):
(JSC::JSBoundFunction::boundArgs):
(JSC::JSBoundFunction::createStructure):

  • runtime/JSFunction.cpp:

(JSC::JSFunction::create):
(JSC::JSFunction::finishCreation):
(JSC::createDescriptorForThrowingProperty):
(JSC::JSFunction::getOwnPropertySlot):

  • runtime/JSFunction.h:
  • runtime/JSGlobalData.cpp:

(JSC::JSGlobalData::getHostFunction):

  • runtime/JSGlobalData.h:
  • runtime/JSGlobalObject.cpp:

(JSC::JSGlobalObject::reset):
(JSC::JSGlobalObject::visitChildren):

  • runtime/JSGlobalObject.h:

(JSC::JSGlobalObject::boundFunctionStructure):

  • runtime/Lookup.cpp:

(JSC::setUpStaticFunctionSlot):

Source/WebCore:

Test: fast/js/function-bind.html

  • bindings/js/JSDOMBinding.cpp:

(WebCore::objectToStringFunctionGetter):

  • bindings/js/JSDOMWindowCustom.cpp:

(WebCore::nonCachingStaticFunctionGetter):

  • bindings/js/JSHistoryCustom.cpp:

(WebCore::nonCachingStaticBackFunctionGetter):
(WebCore::nonCachingStaticForwardFunctionGetter):
(WebCore::nonCachingStaticGoFunctionGetter):

  • bindings/js/JSLocationCustom.cpp:

(WebCore::nonCachingStaticReplaceFunctionGetter):
(WebCore::nonCachingStaticReloadFunctionGetter):
(WebCore::nonCachingStaticAssignFunctionGetter):

  • Function::create no longer requires functionStructure() to be passed.

LayoutTests:

We now pass Function.bind tests.

  • fast/js/Object-getOwnPropertyNames-expected.txt:
  • fast/js/basic-strict-mode-expected.txt:
  • fast/js/function-bind-expected.txt: Added.
  • fast/js/function-bind.html: Added.
  • fast/js/mozilla/strict/15.3.4.5-expected.txt:
  • fast/js/script-tests/function-bind.js: Added.
  • ietestcenter/Javascript/15.2.3.3-4-38-expected.txt:
  • ietestcenter/Javascript/15.3.4.5-0-1-expected.txt:
  • ietestcenter/Javascript/15.3.4.5-0-2-expected.txt:
  • ietestcenter/Javascript/15.3.4.5-13.b-1-expected.txt:
  • ietestcenter/Javascript/15.3.4.5-13.b-2-expected.txt:
  • ietestcenter/Javascript/15.3.4.5-13.b-3-expected.txt:
  • ietestcenter/Javascript/15.3.4.5-13.b-4-expected.txt:
  • ietestcenter/Javascript/15.3.4.5-13.b-5-expected.txt:
  • ietestcenter/Javascript/15.3.4.5-15-1-expected.txt:
  • ietestcenter/Javascript/15.3.4.5-15-2-expected.txt:
  • ietestcenter/Javascript/15.3.4.5-16-1-expected.txt:
  • ietestcenter/Javascript/15.3.4.5-2-1-expected.txt:
  • ietestcenter/Javascript/15.3.4.5-2-2-expected.txt:
  • ietestcenter/Javascript/15.3.4.5-2-3-expected.txt:
  • ietestcenter/Javascript/15.3.4.5-2-4-expected.txt:
  • ietestcenter/Javascript/15.3.4.5-2-5-expected.txt:
  • ietestcenter/Javascript/15.3.4.5-2-6-expected.txt:
  • ietestcenter/Javascript/15.3.4.5-2-7-expected.txt:
  • ietestcenter/Javascript/15.3.4.5-2-8-expected.txt:
  • ietestcenter/Javascript/15.3.4.5-2-9-expected.txt:
  • ietestcenter/Javascript/15.3.4.5-8-1-expected.txt:
  • ietestcenter/Javascript/15.3.4.5-8-2-expected.txt:
  • ietestcenter/Javascript/15.3.4.5-9-1-expected.txt:
  • ietestcenter/Javascript/15.3.4.5-9-2-expected.txt:
Location:
trunk/Source/JavaScriptCore
Files:
2 added
25 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/CMakeLists.txt

    r95681 r95751  
    124124    runtime/JSCell.cpp
    125125    runtime/JSFunction.cpp
     126    runtime/JSBoundFunction.cpp
    126127    runtime/JSGlobalData.cpp
    127128    runtime/JSGlobalObject.cpp
  • trunk/Source/JavaScriptCore/ChangeLog

    r95742 r95751  
     12011-09-22  Gavin Barraclough  <[email protected]>
     2
     3        Implement Function.prototype.bind
     4        https://bugs.webkit.org/show_bug.cgi?id=26382
     5
     6        Reviewed by Sam Weinig.
     7
     8        This patch provides a basic functional implementation
     9        for Function.bind. It should (hopefully!) be fully
     10        functionally correct, and the bound functions can be
     11        called to quickly (since they are a subclass of
     12        JSFunction, not InternalFunction), but we'll probably
     13        want to follow up with some optimization work to keep
     14        bound calls in JIT code.
     15
     16        * JavaScriptCore.JSVALUE32_64only.exp:
     17        * JavaScriptCore.JSVALUE64only.exp:
     18        * JavaScriptCore.exp:
     19        * JavaScriptCore.xcodeproj/project.pbxproj:
     20        * jit/JITStubs.cpp:
     21        (JSC::JITThunks::hostFunctionStub):
     22        * jit/JITStubs.h:
     23        * jsc.cpp:
     24        (GlobalObject::addFunction):
     25        * runtime/CommonIdentifiers.h:
     26        * runtime/ConstructData.h:
     27        * runtime/Executable.h:
     28        (JSC::NativeExecutable::NativeExecutable):
     29        * runtime/FunctionPrototype.cpp:
     30        (JSC::FunctionPrototype::addFunctionProperties):
     31        (JSC::functionProtoFuncBind):
     32        * runtime/FunctionPrototype.h:
     33        * runtime/JSBoundFunction.cpp: Added.
     34        (JSC::boundFunctionCall):
     35        (JSC::boundFunctionConstruct):
     36        (JSC::JSBoundFunction::create):
     37        (JSC::JSBoundFunction::hasInstance):
     38        (JSC::JSBoundFunction::getOwnPropertySlot):
     39        (JSC::JSBoundFunction::getOwnPropertyDescriptor):
     40        (JSC::JSBoundFunction::JSBoundFunction):
     41        (JSC::JSBoundFunction::finishCreation):
     42        * runtime/JSBoundFunction.h: Added.
     43        (JSC::JSBoundFunction::targetFunction):
     44        (JSC::JSBoundFunction::boundThis):
     45        (JSC::JSBoundFunction::boundArgs):
     46        (JSC::JSBoundFunction::createStructure):
     47        * runtime/JSFunction.cpp:
     48        (JSC::JSFunction::create):
     49        (JSC::JSFunction::finishCreation):
     50        (JSC::createDescriptorForThrowingProperty):
     51        (JSC::JSFunction::getOwnPropertySlot):
     52        * runtime/JSFunction.h:
     53        * runtime/JSGlobalData.cpp:
     54        (JSC::JSGlobalData::getHostFunction):
     55        * runtime/JSGlobalData.h:
     56        * runtime/JSGlobalObject.cpp:
     57        (JSC::JSGlobalObject::reset):
     58        (JSC::JSGlobalObject::visitChildren):
     59        * runtime/JSGlobalObject.h:
     60        (JSC::JSGlobalObject::boundFunctionStructure):
     61        * runtime/Lookup.cpp:
     62        (JSC::setUpStaticFunctionSlot):
     63
    1642011-09-22  Oliver Hunt  <[email protected]>
    265
  • trunk/Source/JavaScriptCore/GNUmakefile.list.am

    r95681 r95751  
    348348        Source/JavaScriptCore/runtime/JSFunction.cpp \
    349349        Source/JavaScriptCore/runtime/JSFunction.h \
     350        Source/JavaScriptCore/runtime/JSBoundFunction.cpp \
     351        Source/JavaScriptCore/runtime/JSBoundFunction.h \
    350352        Source/JavaScriptCore/runtime/JSGlobalData.cpp \
    351353        Source/JavaScriptCore/runtime/JSGlobalData.h \
  • trunk/Source/JavaScriptCore/JavaScriptCore.JSVALUE32_64only.exp

    r94376 r95751  
    1 __ZN3JSC12JSGlobalData15getHostFunctionEPFxPNS_9ExecStateEE
     1__ZN3JSC10JSFunction6createEPNS_9ExecStateEPNS_14JSGlobalObjectEiRKNS_10IdentifierEPFxS2_ES9_
  • trunk/Source/JavaScriptCore/JavaScriptCore.JSVALUE64only.exp

    r94376 r95751  
    1 __ZN3JSC12JSGlobalData15getHostFunctionEPFPvPNS_9ExecStateEE
     1__ZN3JSC10JSFunction6createEPNS_9ExecStateEPNS_14JSGlobalObjectEiRKNS_10IdentifierEPFPvS2_ESA_
  • trunk/Source/JavaScriptCore/JavaScriptCore.exp

    r95559 r95751  
    110110__ZN3JSC10Identifier4fromEPNS_9ExecStateEj
    111111__ZN3JSC10Identifier8toUInt32ERKNS_7UStringERb
    112 __ZN3JSC10JSFunction14finishCreationEPNS_9ExecStateEiRKNS_10IdentifierEPNS_14ExecutableBaseE
    113112__ZN3JSC10JSFunction4nameEPNS_9ExecStateE
    114113__ZN3JSC10JSFunction6s_infoE
     
    230229__ZN3JSC24createStackOverflowErrorEPNS_9ExecStateE
    231230__ZN3JSC25evaluateInGlobalCallFrameERKNS_7UStringERNS_7JSValueEPNS_14JSGlobalObjectE
     231__ZN3JSC29callHostFunctionAsConstructorEPNS_9ExecStateE
    232232__ZN3JSC30isTerminatedExecutionExceptionENS_7JSValueE
    233233__ZN3JSC35createInterruptedExecutionExceptionEPNS_12JSGlobalDataE
  • trunk/Source/JavaScriptCore/JavaScriptCore.gypi

    r95559 r95751  
    8484            'runtime/JSCell.h',
    8585            'runtime/JSFunction.h',
     86            'runtime/JSBoundFunction.h',
    8687            'runtime/JSGlobalData.h',
    8788            'runtime/JSGlobalObject.h',
     
    517518            'runtime/JSCell.cpp',
    518519            'runtime/JSFunction.cpp',
     520            'runtime/JSBoundFunction.cpp',
    519521            'runtime/JSGlobalData.cpp',
    520522            'runtime/JSGlobalObject.cpp',
  • trunk/Source/JavaScriptCore/JavaScriptCore.pro

    r95681 r95751  
    154154    runtime/JSCell.cpp \
    155155    runtime/JSFunction.cpp \
     156    runtime/JSBoundFunction.cpp \
    156157    runtime/JSGlobalData.cpp \
    157158    runtime/JSGlobalObject.cpp \
  • trunk/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj

    r95681 r95751  
    799799                        </File>
    800800                        <File
     801                                RelativePath="..\..\runtime\JSBoundFunction.cpp"
     802                                >
     803                        </File>
     804                        <File
     805                                RelativePath="..\..\runtime\JSBoundFunction.h"
     806                                >
     807                        </File>
     808                        <File
    801809                                RelativePath="..\..\runtime\JSGlobalData.cpp"
    802810                                >
  • trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj

    r95681 r95751  
    362362                86ECA3FA132DF25A002B2AD7 /* DFGScoreBoard.h in Headers */ = {isa = PBXBuildFile; fileRef = 86ECA3F9132DF25A002B2AD7 /* DFGScoreBoard.h */; };
    363363                86F38859121130CA007A7CE3 /* AtomicStringHash.h in Headers */ = {isa = PBXBuildFile; fileRef = 86F38858121130CA007A7CE3 /* AtomicStringHash.h */; settings = {ATTRIBUTES = (Private, ); }; };
     364                86FA9E91142BBB2E001773B7 /* JSBoundFunction.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 86FA9E8F142BBB2D001773B7 /* JSBoundFunction.cpp */; };
     365                86FA9E92142BBB2E001773B7 /* JSBoundFunction.h in Headers */ = {isa = PBXBuildFile; fileRef = 86FA9E90142BBB2E001773B7 /* JSBoundFunction.h */; };
    364366                90213E3D123A40C200D422F3 /* MemoryStatistics.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 90213E3B123A40C200D422F3 /* MemoryStatistics.cpp */; };
    365367                90213E3E123A40C200D422F3 /* MemoryStatistics.h in Headers */ = {isa = PBXBuildFile; fileRef = 90213E3C123A40C200D422F3 /* MemoryStatistics.h */; settings = {ATTRIBUTES = (Private, ); }; };
     
    11161118                86ECA3F9132DF25A002B2AD7 /* DFGScoreBoard.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGScoreBoard.h; path = dfg/DFGScoreBoard.h; sourceTree = "<group>"; };
    11171119                86F38858121130CA007A7CE3 /* AtomicStringHash.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AtomicStringHash.h; path = text/AtomicStringHash.h; sourceTree = "<group>"; };
     1120                86FA9E8F142BBB2D001773B7 /* JSBoundFunction.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSBoundFunction.cpp; sourceTree = "<group>"; };
     1121                86FA9E90142BBB2E001773B7 /* JSBoundFunction.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSBoundFunction.h; sourceTree = "<group>"; };
    11181122                90213E3B123A40C200D422F3 /* MemoryStatistics.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MemoryStatistics.cpp; sourceTree = "<group>"; };
    11191123                90213E3C123A40C200D422F3 /* MemoryStatistics.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MemoryStatistics.h; sourceTree = "<group>"; };
     
    20672071                                93ADFCE60CCBD7AC00D30B08 /* JSArray.cpp */,
    20682072                                938772E5038BFE19008635CE /* JSArray.h */,
     2073                                86FA9E8F142BBB2D001773B7 /* JSBoundFunction.cpp */,
     2074                                86FA9E90142BBB2E001773B7 /* JSBoundFunction.h */,
    20692075                                A791EF270F11E07900AE1F68 /* JSByteArray.cpp */,
    20702076                                A791EF260F11E07900AE1F68 /* JSByteArray.h */,
     
    28122818                                1A08277A142168D70090CCAC /* BinarySemaphore.h in Headers */,
    28132819                                A70456B01427FB910037DA68 /* AllocationSpace.h in Headers */,
     2820                                86FA9E92142BBB2E001773B7 /* JSBoundFunction.h in Headers */,
    28142821                        );
    28152822                        runOnlyForDeploymentPostprocessing = 0;
     
    33353342                                1A082779142168D70090CCAC /* BinarySemaphore.cpp in Sources */,
    33363343                                A70456B11427FB950037DA68 /* AllocationSpace.cpp in Sources */,
     3344                                86FA9E91142BBB2E001773B7 /* JSBoundFunction.cpp in Sources */,
    33373345                        );
    33383346                        runOnlyForDeploymentPostprocessing = 0;
  • trunk/Source/JavaScriptCore/jit/JITStubs.cpp

    r95681 r95751  
    20872087    ASSERT(typeInfo.type() != UnspecifiedType);
    20882088
    2089     if (!typeInfo.overridesHasInstance()) {
    2090         if (!value.isObject())
    2091             return JSValue::encode(jsBoolean(false));
    2092 
    2093         if (!proto.isObject()) {
    2094             throwError(callFrame, createTypeError(callFrame, "instanceof called on an object with an invalid prototype property."));
    2095             VM_THROW_EXCEPTION();
    2096         }
    2097     }
     2089    if (!typeInfo.overridesHasInstance() && !value.isObject())
     2090        return JSValue::encode(jsBoolean(false));
    20982091
    20992092    JSValue result = jsBoolean(asObject(baseVal)->hasInstance(callFrame, value, proto));
     
    38273820}
    38283821
    3829 NativeExecutable* JITThunks::hostFunctionStub(JSGlobalData* globalData, NativeFunction function)
     3822NativeExecutable* JITThunks::hostFunctionStub(JSGlobalData* globalData, NativeFunction function, NativeFunction constructor)
    38303823{
    38313824    std::pair<HostFunctionStubMap::iterator, bool> entry = m_hostFunctionStubMap->add(function, Weak<NativeExecutable>());
    38323825    if (!*entry.first->second)
    3833         entry.first->second.set(*globalData, NativeExecutable::create(*globalData, JIT::compileCTINativeCall(globalData, function), function, MacroAssemblerCodeRef::createSelfManagedCodeRef(ctiNativeConstruct()), callHostFunctionAsConstructor, DFG::NoIntrinsic));
     3826        entry.first->second.set(*globalData, NativeExecutable::create(*globalData, JIT::compileCTINativeCall(globalData, function), function, MacroAssemblerCodeRef::createSelfManagedCodeRef(ctiNativeConstruct()), constructor, DFG::NoIntrinsic));
    38343827    return entry.first->second.get();
    38353828}
  • trunk/Source/JavaScriptCore/jit/JITStubs.h

    r95388 r95751  
    298298        MacroAssemblerCodeRef ctiStub(JSGlobalData*, ThunkGenerator);
    299299
    300         NativeExecutable* hostFunctionStub(JSGlobalData*, NativeFunction);
     300        NativeExecutable* hostFunctionStub(JSGlobalData*, NativeFunction, NativeFunction constructor);
    301301        NativeExecutable* hostFunctionStub(JSGlobalData*, NativeFunction, ThunkGenerator, DFG::Intrinsic);
    302302
  • trunk/Source/JavaScriptCore/jsc.cpp

    r95318 r95751  
    191191    {
    192192        Identifier identifier(globalExec(), name);
    193         putDirect(globalData, identifier, JSFunction::create(globalExec(), this, functionStructure(), arguments, identifier, function));
     193        putDirect(globalData, identifier, JSFunction::create(globalExec(), this, arguments, identifier, function));
    194194    }
    195195};
  • trunk/Source/JavaScriptCore/runtime/CommonIdentifiers.h

    r89109 r95751  
    3434    macro(apply) \
    3535    macro(arguments) \
     36    macro(bind) \
    3637    macro(call) \
    3738    macro(callee) \
  • trunk/Source/JavaScriptCore/runtime/ConstructData.h

    r60708 r95751  
    3030#define ConstructData_h
    3131
     32#include "CallData.h"
    3233#include "JSValue.h"
    3334
     
    4647    };
    4748
    48     typedef EncodedJSValue (JSC_HOST_CALL *NativeConstructor)(ExecState*);
    49 
    5049    union ConstructData {
    5150        struct {
    52             NativeConstructor function;
     51            NativeFunction function;
    5352        } native;
    5453        struct {
  • trunk/Source/JavaScriptCore/runtime/Executable.h

    r95681 r95751  
    202202
    203203        NativeFunction function() { return m_function; }
     204        NativeFunction constructor() { return m_constructor; }
    204205
    205206        static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue proto) { return Structure::create(globalData, globalObject, proto, TypeInfo(LeafType, StructureFlags), &s_info); }
     
    229230 
    230231    private:
    231 #if ENABLE(JIT)
    232232        NativeExecutable(JSGlobalData& globalData, NativeFunction function, NativeFunction constructor)
    233233            : ExecutableBase(globalData, globalData.nativeExecutableStructure.get(), NUM_PARAMETERS_IS_HOST)
     
    236236        {
    237237        }
    238 #else
    239         NativeExecutable(JSGlobalData& globalData, NativeFunction function, NativeFunction constructor)
    240             : ExecutableBase(globalData, globalData.nativeExecutableStructure.get(), NUM_PARAMETERS_IS_HOST)
    241             , m_function(function)
    242             , m_constructor(constructor)
    243         {
    244         }
    245 #endif
    246238
    247239        NativeFunction m_function;
    248         // Probably should be a NativeConstructor, but this will currently require rewriting the JIT
    249         // trampoline. It may be easier to make NativeFunction be passed 'this' as a part of the ArgList.
    250240        NativeFunction m_constructor;
    251241       
     
    639629    }
    640630
     631    inline NativeFunction JSFunction::nativeConstructor()
     632    {
     633        ASSERT(isHostFunction());
     634        return static_cast<NativeExecutable*>(m_executable.get())->constructor();
     635    }
     636
    641637    inline bool isHostFunction(JSValue value, NativeFunction nativeFunction)
    642638    {
  • trunk/Source/JavaScriptCore/runtime/FunctionPrototype.cpp

    r95318 r95751  
    2424#include "Arguments.h"
    2525#include "JSArray.h"
     26#include "JSBoundFunction.h"
    2627#include "JSFunction.h"
    2728#include "JSString.h"
     
    3738static EncodedJSValue JSC_HOST_CALL functionProtoFuncApply(ExecState*);
    3839static EncodedJSValue JSC_HOST_CALL functionProtoFuncCall(ExecState*);
     40static EncodedJSValue JSC_HOST_CALL functionProtoFuncBind(ExecState*);
    3941
    4042FunctionPrototype::FunctionPrototype(JSGlobalObject* globalObject, Structure* structure)
     
    4951}
    5052
    51 void FunctionPrototype::addFunctionProperties(ExecState* exec, JSGlobalObject* globalObject, Structure* functionStructure, JSFunction** callFunction, JSFunction** applyFunction)
    52 {
    53     JSFunction* toStringFunction = JSFunction::create(exec, globalObject, functionStructure, 0, exec->propertyNames().toString, functionProtoFuncToString);
     53void FunctionPrototype::addFunctionProperties(ExecState* exec, JSGlobalObject* globalObject, JSFunction** callFunction, JSFunction** applyFunction)
     54{
     55    JSFunction* toStringFunction = JSFunction::create(exec, globalObject, 0, exec->propertyNames().toString, functionProtoFuncToString);
    5456    putDirectWithoutTransition(exec->globalData(), exec->propertyNames().toString, toStringFunction, DontEnum);
    5557
    56     *applyFunction = JSFunction::create(exec, globalObject, functionStructure, 2, exec->propertyNames().apply, functionProtoFuncApply);
     58    *applyFunction = JSFunction::create(exec, globalObject, 2, exec->propertyNames().apply, functionProtoFuncApply);
    5759    putDirectWithoutTransition(exec->globalData(), exec->propertyNames().apply, *applyFunction, DontEnum);
    5860
    59     *callFunction = JSFunction::create(exec, globalObject, functionStructure, 1, exec->propertyNames().call, functionProtoFuncCall);
     61    *callFunction = JSFunction::create(exec, globalObject, 1, exec->propertyNames().call, functionProtoFuncCall);
    6062    putDirectWithoutTransition(exec->globalData(), exec->propertyNames().call, *callFunction, DontEnum);
     63
     64    JSFunction* bindFunction = JSFunction::create(exec, globalObject, 0, exec->propertyNames().bind, functionProtoFuncBind);
     65    putDirectWithoutTransition(exec->globalData(), exec->propertyNames().bind, bindFunction, DontEnum);
    6166}
    6267
     
    154159}
    155160
     161// 15.3.4.5 Function.prototype.bind (thisArg [, arg1 [, arg2, ...]])
     162EncodedJSValue JSC_HOST_CALL functionProtoFuncBind(ExecState* exec)
     163{
     164    JSGlobalObject* globalObject = exec->callee()->globalObject();
     165
     166    // Let Target be the this value.
     167    JSValue target = exec->hostThisValue();
     168
     169    // If IsCallable(Target) is false, throw a TypeError exception.
     170    CallData callData;
     171    CallType callType = getCallData(target, callData);
     172    if (callType == CallTypeNone)
     173        return throwVMTypeError(exec);
     174    // Primitive values are not callable.
     175    ASSERT(target.isObject());
     176    JSObject* targetObject = asObject(target);
     177
     178    // Let A be a new (possibly empty) internal list of all of the argument values provided after thisArg (arg1, arg2 etc), in order.
     179    size_t numBoundArgs = exec->argumentCount() > 1 ? exec->argumentCount() - 1 : 0;
     180    JSArray* boundArgs = JSArray::create(exec->globalData(), globalObject->arrayStructure(), numBoundArgs, CreateCompact);
     181    for (size_t i = 0; i < numBoundArgs; ++i)
     182        boundArgs->uncheckedSetIndex(exec->globalData(), i, exec->argument(i + 1));
     183    boundArgs->setLength(numBoundArgs);
     184
     185    // If the [[Class]] internal property of Target is "Function", then ...
     186    // Else set the length own property of F to 0.
     187    unsigned length = 0;
     188    if (targetObject->inherits(&JSFunction::s_info)) {
     189        ASSERT(target.get(exec, exec->propertyNames().length).isNumber());
     190        // a. Let L be the length property of Target minus the length of A.
     191        // b. Set the length own property of F to either 0 or L, whichever is larger.
     192        unsigned targetLength = (unsigned)target.get(exec, exec->propertyNames().length).uncheckedGetNumber();
     193        if (targetLength > numBoundArgs)
     194            length = targetLength - numBoundArgs;
     195    }
     196
     197    Identifier name(exec, target.get(exec, exec->propertyNames().name).toString(exec));
     198
     199    return JSValue::encode(JSBoundFunction::create(exec, globalObject, targetObject, exec->argument(0), boundArgs, length, name));
     200}
     201
    156202} // namespace JSC
  • trunk/Source/JavaScriptCore/runtime/FunctionPrototype.h

    r95108 r95751  
    3737        }
    3838       
    39         void addFunctionProperties(ExecState*, JSGlobalObject*, Structure* functionStructure, JSFunction** callFunction, JSFunction** applyFunction);
     39        void addFunctionProperties(ExecState*, JSGlobalObject*, JSFunction** callFunction, JSFunction** applyFunction);
    4040       
    4141        static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue proto)
  • trunk/Source/JavaScriptCore/runtime/JSFunction.cpp

    r95205 r95751  
    3131#include "ExceptionHelpers.h"
    3232#include "FunctionPrototype.h"
     33#include "JSArray.h"
    3334#include "JSGlobalObject.h"
    3435#include "JSNotAnObject.h"
     
    5758}
    5859
     60JSFunction* JSFunction::create(ExecState* exec, JSGlobalObject* globalObject, int length, const Identifier& name, NativeFunction nativeFunction, NativeFunction nativeConstructor)
     61{
     62    NativeExecutable* executable = exec->globalData().getHostFunction(nativeFunction, nativeConstructor);
     63    JSFunction* function = new (allocateCell<JSFunction>(*exec->heap())) JSFunction(exec, globalObject, globalObject->functionStructure());
     64    // Can't do this during initialization because getHostFunction might do a GC allocation.
     65    function->finishCreation(exec, executable, length, name);
     66    return function;
     67}
     68
     69JSFunction* JSFunction::create(ExecState* exec, JSGlobalObject* globalObject, int length, const Identifier& name, NativeExecutable* nativeExecutable)
     70{
     71    JSFunction* function = new (allocateCell<JSFunction>(*exec->heap())) JSFunction(exec, globalObject, globalObject->functionStructure());
     72    function->finishCreation(exec, nativeExecutable, length, name);
     73    return function;
     74}
     75
    5976JSFunction::JSFunction(VPtrStealingHackType)
    6077    : Base(VPtrStealingHack)
     
    7693}
    7794
    78 void JSFunction::finishCreation(ExecState* exec, int length, const Identifier& name, ExecutableBase* executable)
     95void JSFunction::finishCreation(ExecState* exec, NativeExecutable* executable, int length, const Identifier& name)
    7996{
    8097    Base::finishCreation(exec->globalData());
     
    89106    Base::finishCreation(exec->globalData());
    90107    ASSERT(inherits(&s_info));
     108
     109    // Switching the structure here is only safe if we currently have the function structure!
     110    ASSERT(structure() == scopeChainNode->globalObject->functionStructure());
    91111    setStructure(exec->globalData(), scopeChainNode->globalObject->namedFunctionStructure());
    92112    putDirectOffset(exec->globalData(), scopeChainNode->globalObject->functionNameOffset(), executable->nameValue());
     
    98118}
    99119
    100 static const char* StrictModeCallerAccessError = "Cannot access caller property of a strict mode function";
    101 static const char* StrictModeArgumentsAccessError = "Cannot access arguments property of a strict mode function";
    102 
    103 static void createDescriptorForThrowingProperty(ExecState* exec, PropertyDescriptor& descriptor, const char* message)
     120const char* StrictModeCallerAccessError = "Cannot access caller property of a strict mode function";
     121const char* StrictModeArgumentsAccessError = "Cannot access arguments property of a strict mode function";
     122
     123void createDescriptorForThrowingProperty(ExecState* exec, PropertyDescriptor& descriptor, const char* message)
    104124{
    105125    JSValue thrower = createTypeErrorFunction(exec, message);
     
    197217    if (propertyName == exec->propertyNames().arguments) {
    198218        if (jsExecutable()->isStrictMode()) {
    199             throwTypeError(exec, "Can't access arguments object of a strict mode function");
     219            throwTypeError(exec, StrictModeArgumentsAccessError);
    200220            slot.setValue(jsNull());
    201221            return true;
     
    312332ConstructType JSFunction::getConstructData(ConstructData& constructData)
    313333{
    314     if (isHostFunction())
    315         return ConstructTypeNone;
     334    if (isHostFunction()) {
     335        constructData.native.function = nativeConstructor();
     336        return ConstructTypeHost;
     337    }
    316338    constructData.js.functionExecutable = jsExecutable();
    317339    constructData.js.scopeChain = scope();
  • trunk/Source/JavaScriptCore/runtime/JSFunction.h

    r95666 r95751  
    4242    EncodedJSValue JSC_HOST_CALL callHostFunctionAsConstructor(ExecState*);
    4343
     44    extern const char* StrictModeCallerAccessError;
     45    extern const char* StrictModeArgumentsAccessError;
     46
     47    void createDescriptorForThrowingProperty(ExecState*, PropertyDescriptor&, const char* message);
     48
    4449    class JSFunction : public JSNonFinalObject {
    4550        friend class JIT;
     
    4752        friend class JSGlobalData;
    4853
    49         JSFunction(ExecState*, JSGlobalObject*, Structure*);
    50         JSFunction(ExecState*, FunctionExecutable*, ScopeChainNode*);
    51        
    5254    public:
    5355        typedef JSNonFinalObject Base;
    5456
    55         static JSFunction* create(ExecState* exec, JSGlobalObject* globalObject, Structure* structure, int length, const Identifier& name, NativeFunction nativeFunction)
    56         {
    57             ASSERT(structure->globalObject());
    58             ASSERT(structure->globalObject() == globalObject);
    59            
    60             ExecutableBase* executable = (ExecutableBase*)exec->globalData().getHostFunction(nativeFunction);
    61             JSFunction* function = new (allocateCell<JSFunction>(*exec->heap())) JSFunction(exec, globalObject, structure);
    62             // Can't do this during initialization because getHostFunction might do a GC allocation.
    63             function->finishCreation(exec, length, name, executable);
    64             return function;
    65         }
    66 
    67         static JSFunction* create(ExecState* exec, JSGlobalObject* globalObject, Structure* structure, int length, const Identifier& name, NativeExecutable* nativeExecutable)
    68         {
    69             ASSERT(structure->globalObject());
    70             ASSERT(structure->globalObject() == globalObject);
    71 
    72             JSFunction* function = new (allocateCell<JSFunction>(*exec->heap())) JSFunction(exec, globalObject, structure);
    73             function->finishCreation(exec, length, name, (ExecutableBase*)nativeExecutable);
    74             return function;
    75         }
     57        static JSFunction* create(ExecState*, JSGlobalObject*, int length, const Identifier& name, NativeFunction nativeFunction, NativeFunction nativeConstructor = callHostFunctionAsConstructor);
     58        static JSFunction* create(ExecState*, JSGlobalObject*, int length, const Identifier& name, NativeExecutable* nativeExecutable);
    7659
    7760        static JSFunction* create(ExecState* exec, FunctionExecutable* executable, ScopeChainNode* scopeChain)
     
    124107
    125108        NativeFunction nativeFunction();
     109        NativeFunction nativeConstructor();
    126110
    127111        virtual ConstructType getConstructData(ConstructData&);
     
    141125        const static unsigned StructureFlags = OverridesGetOwnPropertySlot | ImplementsHasInstance | OverridesVisitChildren | OverridesGetPropertyNames | JSObject::StructureFlags;
    142126
    143         void finishCreation(ExecState*, int length, const Identifier& name, ExecutableBase*);
     127        JSFunction(ExecState*, JSGlobalObject*, Structure*);
     128        JSFunction(ExecState*, FunctionExecutable*, ScopeChainNode*);
     129       
     130        void finishCreation(ExecState*, NativeExecutable*, int length, const Identifier& name);
    144131        void finishCreation(ExecState*, FunctionExecutable*, ScopeChainNode*);
     132
     133        virtual bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&);
     134        virtual bool getOwnPropertyDescriptor(ExecState*, const Identifier&, PropertyDescriptor&);
     135        virtual void getOwnPropertyNames(ExecState*, PropertyNameArray&, EnumerationMode = ExcludeDontEnumProperties);
     136
     137        virtual void visitChildren(SlotVisitor&);
    145138
    146139    private:
     
    149142        bool isHostFunctionNonInline() const;
    150143
    151         virtual bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&);
    152         virtual bool getOwnPropertyDescriptor(ExecState*, const Identifier&, PropertyDescriptor&);
    153         virtual void getOwnPropertyNames(ExecState*, PropertyNameArray&, EnumerationMode mode = ExcludeDontEnumProperties);
    154144        virtual void put(ExecState*, const Identifier& propertyName, JSValue, PutPropertySlot&);
    155145        virtual bool deleteProperty(ExecState*, const Identifier& propertyName);
    156 
    157         virtual void visitChildren(SlotVisitor&);
    158146
    159147        static JSValue argumentsGetter(ExecState*, JSValue, const Identifier&);
  • trunk/Source/JavaScriptCore/runtime/JSGlobalData.cpp

    r95559 r95751  
    396396
    397397#if ENABLE(JIT)
    398 NativeExecutable* JSGlobalData::getHostFunction(NativeFunction function)
    399 {
    400     return jitStubs->hostFunctionStub(this, function);
     398NativeExecutable* JSGlobalData::getHostFunction(NativeFunction function, NativeFunction constructor)
     399{
     400    return jitStubs->hostFunctionStub(this, function, constructor);
    401401}
    402402NativeExecutable* JSGlobalData::getHostFunction(NativeFunction function, ThunkGenerator generator, DFG::Intrinsic intrinsic)
     
    405405}
    406406#else
    407 NativeExecutable* JSGlobalData::getHostFunction(NativeFunction function)
    408 {
    409     return NativeExecutable::create(*this, function, callHostFunctionAsConstructor);
     407NativeExecutable* JSGlobalData::getHostFunction(NativeFunction function, NativeFunction constructor)
     408{
     409    return NativeExecutable::create(*this, function, constructor);
    410410}
    411411#endif
  • trunk/Source/JavaScriptCore/runtime/JSGlobalData.h

    r95510 r95751  
    220220        NativeExecutable* getHostFunction(NativeFunction, ThunkGenerator, DFG::Intrinsic);
    221221#endif
    222         NativeExecutable* getHostFunction(NativeFunction);
     222        NativeExecutable* getHostFunction(NativeFunction, NativeFunction constructor);
    223223
    224224        TimeoutChecker timeoutChecker;
  • trunk/Source/JavaScriptCore/runtime/JSGlobalObject.cpp

    r95318 r95751  
    4747#include "FunctionConstructor.h"
    4848#include "FunctionPrototype.h"
     49#include "JSBoundFunction.h"
    4950#include "JSFunction.h"
    5051#include "JSGlobalObjectFunctions.h"
     
    188189    m_functionPrototype.set(exec->globalData(), this, FunctionPrototype::create(exec, this, FunctionPrototype::createStructure(exec->globalData(), this, jsNull()))); // The real prototype will be set once ObjectPrototype is created.
    189190    m_functionStructure.set(exec->globalData(), this, JSFunction::createStructure(exec->globalData(), this, m_functionPrototype.get()));
     191    m_boundFunctionStructure.set(exec->globalData(), this, JSBoundFunction::createStructure(exec->globalData(), this, m_functionPrototype.get()));
    190192    m_namedFunctionStructure.set(exec->globalData(), this, Structure::addPropertyTransition(exec->globalData(), m_functionStructure.get(), exec->globalData().propertyNames->name, DontDelete | ReadOnly | DontEnum, 0, m_functionNameOffset));
    191193    m_internalFunctionStructure.set(exec->globalData(), this, InternalFunction::createStructure(exec->globalData(), this, m_functionPrototype.get()));
    192194    JSFunction* callFunction = 0;
    193195    JSFunction* applyFunction = 0;
    194     m_functionPrototype->addFunctionProperties(exec, this, m_functionStructure.get(), &callFunction, &applyFunction);
     196    m_functionPrototype->addFunctionProperties(exec, this, &callFunction, &applyFunction);
    195197    m_callFunction.set(exec->globalData(), this, callFunction);
    196198    m_applyFunction.set(exec->globalData(), this, applyFunction);
     
    281283    putDirectWithoutTransition(exec->globalData(), Identifier(exec, "URIError"), m_URIErrorConstructor.get(), DontEnum);
    282284
    283     m_evalFunction.set(exec->globalData(), this, JSFunction::create(exec, this, m_functionStructure.get(), 1, exec->propertyNames().eval, globalFuncEval));
     285    m_evalFunction.set(exec->globalData(), this, JSFunction::create(exec, this, 1, exec->propertyNames().eval, globalFuncEval));
    284286    putDirectWithoutTransition(exec->globalData(), exec->propertyNames().eval, m_evalFunction.get(), DontEnum);
    285287
     
    350352    visitIfNeeded(visitor, &m_errorStructure);
    351353    visitIfNeeded(visitor, &m_functionStructure);
     354    visitIfNeeded(visitor, &m_boundFunctionStructure);
    352355    visitIfNeeded(visitor, &m_namedFunctionStructure);
    353356    visitIfNeeded(visitor, &m_numberObjectStructure);
  • trunk/Source/JavaScriptCore/runtime/JSGlobalObject.h

    r95326 r95751  
    117117        WriteBarrier<Structure> m_errorStructure;
    118118        WriteBarrier<Structure> m_functionStructure;
     119        WriteBarrier<Structure> m_boundFunctionStructure;
    119120        WriteBarrier<Structure> m_namedFunctionStructure;
    120121        size_t m_functionNameOffset;
     
    229230        Structure* errorStructure() const { return m_errorStructure.get(); }
    230231        Structure* functionStructure() const { return m_functionStructure.get(); }
     232        Structure* boundFunctionStructure() const { return m_boundFunctionStructure.get(); }
    231233        Structure* namedFunctionStructure() const { return m_namedFunctionStructure.get(); }
    232234        size_t functionNameOffset() const { return m_functionNameOffset; }
  • trunk/Source/JavaScriptCore/runtime/Lookup.cpp

    r95399 r95751  
    8383#if ENABLE(JIT)
    8484        if (entry->generator() || entry->intrinsic() != DFG::NoIntrinsic)
    85             function = JSFunction::create(exec, globalObject, globalObject->functionStructure(), entry->functionLength(), propertyName, exec->globalData().getHostFunction(entry->function(), entry->generator(), entry->intrinsic()));
     85            function = JSFunction::create(exec, globalObject, entry->functionLength(), propertyName, exec->globalData().getHostFunction(entry->function(), entry->generator(), entry->intrinsic()));
    8686        else
    8787#endif
    88             function = JSFunction::create(exec, globalObject, globalObject->functionStructure(), entry->functionLength(), propertyName, entry->function());
     88            function = JSFunction::create(exec, globalObject, entry->functionLength(), propertyName, entry->function());
    8989
    9090        thisObj->putDirect(exec->globalData(), propertyName, function, entry->attributes());
Note: See TracChangeset for help on using the changeset viewer.