Changeset 109461 in webkit


Ignore:
Timestamp:
Mar 1, 2012 4:12:58 PM (12 years ago)
Author:
barraclough@apple.com
Message:

ES5.1-15.3.5.4. prohibits Function.caller from Get?ting a strict caller
https://bugs.webkit.org/show_bug.cgi?id=80011

Reviewed by Oliver Hunt.

Also, fix getting the caller from within a bound function, for within a getter,
or setter (make our implementation match other browsers).

Source/JavaScriptCore:

  • interpreter/Interpreter.cpp:

(JSC::getCallerInfo):

  • Allow this to get the caller of host functions.

(JSC::Interpreter::retrieveCallerFromVMCode):

  • This should use getCallerInfo, and should skip over function bindings.
  • runtime/JSFunction.cpp:

(JSC::JSFunction::callerGetter):

  • This should never return a strict-mode function.

LayoutTests:

  • fast/js/caller-property-expected.txt:
  • fast/js/script-tests/caller-property.js:
    • Add test cases covering permutations of caller/callee being strict/non-strict, And for callee being a getter/setter/bound.
  • fast/js/stack-trace-expected.txt:
    • Allow stack tracing over host functions.
Location:
trunk
Files:
7 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r109458 r109461  
     12012-03-01  Gavin Barraclough  <barraclough@apple.com>
     2
     3        ES5.1-15.3.5.4. prohibits Function.caller from [[Get]]ting a strict caller
     4        https://bugs.webkit.org/show_bug.cgi?id=80011
     5
     6        Reviewed by Oliver Hunt.
     7
     8        Also, fix getting the caller from within a bound function, for within a getter,
     9        or setter (make our implementation match other browsers).
     10
     11        * fast/js/caller-property-expected.txt:
     12        * fast/js/script-tests/caller-property.js:
     13            - Add test cases covering permutations of caller/callee being strict/non-strict,
     14              And for callee being a getter/setter/bound.
     15        * fast/js/stack-trace-expected.txt:
     16            - Allow stack tracing over host functions.
     17
    1182012-03-01  Xingnan Wang  <xingnan.wang@intel.com>
    219
  • trunk/LayoutTests/fast/js/caller-property-expected.txt

    r17483 r109461  
    77PASS childHasCallerWhenCalledWithoutParent is false
    88PASS childHasCallerWhenCalledFromWithinParent is true
     9PASS nonStrictCaller(nonStrictCallee) is nonStrictCaller
     10PASS nonStrictCaller(strictCallee) threw exception TypeError: Type error.
     11PASS strictCaller(nonStrictCallee) threw exception TypeError: Function.caller used to retrieve strict caller.
     12PASS strictCaller(strictCallee) threw exception TypeError: Type error.
     13PASS nonStrictCaller(boundNonStrictCallee) is nonStrictCaller
     14PASS nonStrictCaller(boundStrictCallee) threw exception TypeError: Type error.
     15PASS strictCaller(boundNonStrictCallee) threw exception TypeError: Function.caller used to retrieve strict caller.
     16PASS strictCaller(boundStrictCallee) threw exception TypeError: Type error.
     17PASS nonStrictGetter(nonStrictAccessor) is nonStrictGetter
     18PASS nonStrictSetter(nonStrictAccessor) is true
     19PASS nonStrictGetter(strictAccessor) threw exception TypeError: Type error.
     20PASS nonStrictSetter(strictAccessor) threw exception TypeError: Type error.
     21PASS strictGetter(nonStrictAccessor) threw exception TypeError: Function.caller used to retrieve strict caller.
     22PASS strictSetter(nonStrictAccessor) threw exception TypeError: Function.caller used to retrieve strict caller.
     23PASS strictGetter(strictAccessor) threw exception TypeError: Type error.
     24PASS strictSetter(strictAccessor) threw exception TypeError: Type error.
    925PASS successfullyParsed is true
    1026
  • trunk/LayoutTests/fast/js/script-tests/caller-property.js

    r98407 r109461  
    1919shouldBe('childHasCallerWhenCalledWithoutParent', 'false');
    2020shouldBe('childHasCallerWhenCalledFromWithinParent', 'true')
     21
     22// The caller property should throw in strict mode, and a non-strict function cannot use caller to reach a strict caller (see ES5.1 15.3.5.4).
     23function nonStrictCallee() { return nonStrictCallee.caller; }
     24function strictCallee() { "use strict"; return strictCallee.caller; }
     25function nonStrictCaller(x) { return x(); }
     26function strictCaller(x) { "use strict"; return x(); }
     27shouldBe("nonStrictCaller(nonStrictCallee)", "nonStrictCaller");
     28shouldThrow("nonStrictCaller(strictCallee)", '"TypeError: Type error"');
     29shouldThrow("strictCaller(nonStrictCallee)", '"TypeError: Function.caller used to retrieve strict caller"');
     30shouldThrow("strictCaller(strictCallee)", '"TypeError: Type error"');
     31
     32// .caller within a bound function reaches the caller, ignoring the binding.
     33var boundNonStrictCallee = nonStrictCallee.bind();
     34var boundStrictCallee = strictCallee.bind();
     35shouldBe("nonStrictCaller(boundNonStrictCallee)", "nonStrictCaller");
     36shouldThrow("nonStrictCaller(boundStrictCallee)", '"TypeError: Type error"');
     37shouldThrow("strictCaller(boundNonStrictCallee)", '"TypeError: Function.caller used to retrieve strict caller"');
     38shouldThrow("strictCaller(boundStrictCallee)", '"TypeError: Type error"');
     39
     40// Check that .caller works (or throws) as expected, over an accessor call.
     41function getFooGetter(x) { return Object.getOwnPropertyDescriptor(x, 'foo').get; }
     42function getFooSetter(x) { return Object.getOwnPropertyDescriptor(x, 'foo').set; }
     43var nonStrictAccessor = {
     44    get foo() { return getFooGetter(nonStrictAccessor).caller; },
     45    set foo(x) { if (getFooSetter(nonStrictAccessor).caller !==x) throw false; }
     46};
     47var strictAccessor = {
     48    get foo() { "use strict"; return getFooGetter(strictAccessor).caller; },
     49    set foo(x) { "use strict"; if (getFooSetter(strictAccessor).caller !==x) throw false; }
     50};
     51function nonStrictGetter(x) { return x.foo; }
     52function nonStrictSetter(x) { x.foo = nonStrictSetter; return true; }
     53function strictGetter(x) { "use strict"; return x.foo; }
     54function strictSetter(x) { "use strict"; x.foo = nonStrictSetter; return true; }
     55shouldBe("nonStrictGetter(nonStrictAccessor)", "nonStrictGetter");
     56shouldBeTrue("nonStrictSetter(nonStrictAccessor)");
     57shouldThrow("nonStrictGetter(strictAccessor)", '"TypeError: Type error"');
     58shouldThrow("nonStrictSetter(strictAccessor)", '"TypeError: Type error"');
     59shouldThrow("strictGetter(nonStrictAccessor)", '"TypeError: Function.caller used to retrieve strict caller"');
     60shouldThrow("strictSetter(nonStrictAccessor)", '"TypeError: Function.caller used to retrieve strict caller"');
     61shouldThrow("strictGetter(strictAccessor)", '"TypeError: Type error"');
     62shouldThrow("strictSetter(strictAccessor)", '"TypeError: Type error"');
  • trunk/LayoutTests/fast/js/stack-trace-expected.txt

    r108112 r109461  
    1313    1    at eval code
    1414    2   eval at [native code]
     15    3   evaler at stack-trace.js:29
     16    4   global code at stack-trace.js:39
    1517
    1618--> Stack Trace:
     
    1921    2    at eval code
    2022    3   eval at [native code]
     23    4   evaler at stack-trace.js:29
     24    5   global code at stack-trace.js:40
    2125
    2226--> Stack Trace:
     
    252256    1    at eval code
    253257    2   eval at [native code]
     258    3   selfRecursive3 at stack-trace.js:69
     259    4    at eval code
     260    5   eval at [native code]
     261    6   selfRecursive3 at stack-trace.js:69
     262    7    at eval code
     263    8   eval at [native code]
     264    9   selfRecursive3 at stack-trace.js:69
     265    10    at eval code
     266    11   eval at [native code]
     267    12   selfRecursive3 at stack-trace.js:69
     268    13    at eval code
     269    14   eval at [native code]
     270    15   selfRecursive3 at stack-trace.js:69
     271    16    at eval code
     272    17   eval at [native code]
     273    18   selfRecursive3 at stack-trace.js:69
     274    19    at eval code
     275    20   eval at [native code]
     276    21   selfRecursive3 at stack-trace.js:69
     277    22    at eval code
     278    23   eval at [native code]
     279    24   selfRecursive3 at stack-trace.js:69
     280    25    at eval code
     281    26   eval at [native code]
     282    27   selfRecursive3 at stack-trace.js:69
     283    28    at eval code
     284    29   eval at [native code]
     285    30   selfRecursive3 at stack-trace.js:69
     286    31    at eval code
     287    32   eval at [native code]
     288    33   selfRecursive3 at stack-trace.js:69
     289    34    at eval code
     290    35   eval at [native code]
     291    36   selfRecursive3 at stack-trace.js:69
     292    37    at eval code
     293    38   eval at [native code]
     294    39   selfRecursive3 at stack-trace.js:69
     295    40    at eval code
     296    41   eval at [native code]
     297    42   selfRecursive3 at stack-trace.js:69
     298    43    at eval code
     299    44   eval at [native code]
     300    45   selfRecursive3 at stack-trace.js:69
     301    46    at eval code
     302    47   eval at [native code]
     303    48   selfRecursive3 at stack-trace.js:69
     304    49    at eval code
     305    50   eval at [native code]
     306    51   selfRecursive3 at stack-trace.js:69
     307    52    at eval code
     308    53   eval at [native code]
     309    54   selfRecursive3 at stack-trace.js:69
     310    55    at eval code
     311    56   eval at [native code]
     312    57   selfRecursive3 at stack-trace.js:69
     313    58    at eval code
     314    59   eval at [native code]
     315    60   selfRecursive3 at stack-trace.js:69
     316    61    at eval code
     317    62   eval at [native code]
     318    63   selfRecursive3 at stack-trace.js:69
     319    64    at eval code
     320    65   eval at [native code]
     321    66   selfRecursive3 at stack-trace.js:69
     322    67    at eval code
     323    68   eval at [native code]
     324    69   selfRecursive3 at stack-trace.js:69
     325    70    at eval code
     326    71   eval at [native code]
     327    72   selfRecursive3 at stack-trace.js:69
     328    73    at eval code
     329    74   eval at [native code]
     330    75   selfRecursive3 at stack-trace.js:69
     331    76    at eval code
     332    77   eval at [native code]
     333    78   selfRecursive3 at stack-trace.js:69
     334    79    at eval code
     335    80   eval at [native code]
     336    81   selfRecursive3 at stack-trace.js:69
     337    82    at eval code
     338    83   eval at [native code]
     339    84   selfRecursive3 at stack-trace.js:69
     340    85    at eval code
     341    86   eval at [native code]
     342    87   selfRecursive3 at stack-trace.js:69
     343    88    at eval code
     344    89   eval at [native code]
     345    90   selfRecursive3 at stack-trace.js:69
     346    91    at eval code
     347    92   eval at [native code]
     348    93   selfRecursive3 at stack-trace.js:69
     349    94    at eval code
     350    95   eval at [native code]
     351    96   selfRecursive3 at stack-trace.js:69
     352    97    at eval code
     353    98   eval at [native code]
     354    99   selfRecursive3 at stack-trace.js:69
    254355
    255356--> Stack Trace:
     
    263364    7   g at stack-trace.js:140
    264365    8   map at [native code]
     366    9   global code at stack-trace.js:143
    265367
    266368--> Stack Trace:
     
    273375    6   g at stack-trace.js:140
    274376    7   map at [native code]
     377    8   global code at stack-trace.js:143
    275378
    276379--> Stack Trace:
     
    283386    6   g at stack-trace.js:140
    284387    7   map at [native code]
     388    8   global code at stack-trace.js:143
    285389
    286390--> Stack Trace:
     
    294398    7   g at stack-trace.js:140
    295399    8   map at [native code]
     400    9   global code at stack-trace.js:143
    296401
    297402--> Stack Trace:
    298403    0   h at stack-trace.js:151
    299404    1   map at [native code]
     405    2   mapTest at stack-trace.js:158
     406    3   mapTestDriver at stack-trace.js:164
     407    4   global code at stack-trace.js:169
    300408
    301409--> Stack Trace:
    302410    0   h at stack-trace.js:153
    303411    1   map at [native code]
     412    2   mapTest at stack-trace.js:158
     413    3   mapTestDriver at stack-trace.js:164
     414    4   global code at stack-trace.js:175
    304415
    305416--> Stack Trace:
     
    307418    1   dfgFunction at stack-trace.js:184
    308419    2   map at [native code]
     420    3   global code at stack-trace.js:193
    309421
    310422--> Stack Trace:
  • trunk/Source/JavaScriptCore/ChangeLog

    r109325 r109461  
     12012-03-01  Gavin Barraclough  <barraclough@apple.com>
     2
     3        ES5.1-15.3.5.4. prohibits Function.caller from [[Get]]ting a strict caller
     4        https://bugs.webkit.org/show_bug.cgi?id=80011
     5
     6        Reviewed by Oliver Hunt.
     7
     8        Also, fix getting the caller from within a bound function, for within a getter,
     9        or setter (make our implementation match other browsers).
     10
     11        * interpreter/Interpreter.cpp:
     12        (JSC::getCallerInfo):
     13            - Allow this to get the caller of host functions.
     14        (JSC::Interpreter::retrieveCallerFromVMCode):
     15            - This should use getCallerInfo, and should skip over function bindings.
     16        * runtime/JSFunction.cpp:
     17        (JSC::JSFunction::callerGetter):
     18            - This should never return a strict-mode function.
     19
    1202012-03-01  Yuqiang Xian  <yuqiang.xian@intel.com>
    221
  • trunk/Source/JavaScriptCore/interpreter/Interpreter.cpp

    r109007 r109461  
    4545#include "JSActivation.h"
    4646#include "JSArray.h"
     47#include "JSBoundFunction.h"
    4748#include "JSByteArray.h"
    4849#include "JSNotAnObject.h"
     
    846847    lineNumber = -1;
    847848    ASSERT(!callFrame->hasHostCallFrameFlag());
    848     CallFrame* callerFrame = callFrame->codeBlock() ? callFrame->trueCallerFrame() : 0;
     849    CallFrame* callerFrame = callFrame->codeBlock() ? callFrame->trueCallerFrame() : callFrame->callerFrame()->removeHostCallFrameFlag();
    849850    bool callframeIsHost = callerFrame->addHostCallFrameFlag() == callFrame->callerFrame();
    850851    ASSERT(!callerFrame->hasHostCallFrameFlag());
     
    53025303{
    53035304    CallFrame* functionCallFrame = findFunctionCallFrameFromVMCode(callFrame, function);
     5305
    53045306    if (!functionCallFrame)
    53055307        return jsNull();
    53065308   
    5307     if (functionCallFrame->callerFrame()->hasHostCallFrameFlag())
     5309    int lineNumber;
     5310    CallFrame* callerFrame = getCallerInfo(&callFrame->globalData(), functionCallFrame, lineNumber);
     5311    if (!callerFrame)
    53085312        return jsNull();
    5309 
    5310     CallFrame* callerFrame = functionCallFrame->trueCallerFrame();
    5311 
    53125313    JSValue caller = callerFrame->callee();
    53135314    if (!caller)
    53145315        return jsNull();
     5316
     5317    // Skip over function bindings.
     5318    ASSERT(caller.isObject());
     5319    while (asObject(caller)->inherits(&JSBoundFunction::s_info)) {
     5320        callerFrame = getCallerInfo(&callFrame->globalData(), callerFrame, lineNumber);
     5321        if (!callerFrame)
     5322            return jsNull();
     5323        caller = callerFrame->callee();
     5324        if (!caller)
     5325            return jsNull();
     5326    }
    53155327
    53165328    return caller;
  • trunk/Source/JavaScriptCore/runtime/JSFunction.cpp

    r107445 r109461  
    182182    JSFunction* thisObj = asFunction(slotBase);
    183183    ASSERT(!thisObj->isHostFunction());
    184     return exec->interpreter()->retrieveCallerFromVMCode(exec, thisObj);
     184    JSValue caller = exec->interpreter()->retrieveCallerFromVMCode(exec, thisObj);
     185
     186    // See ES5.1 15.3.5.4 - Function.caller may not be used to retrieve a strict caller.
     187    if (!caller.isObject() || !asObject(caller)->inherits(&JSFunction::s_info))
     188        return caller;
     189    JSFunction* function = asFunction(caller);
     190    if (function->isHostFunction() || !function->jsExecutable()->isStrictMode())
     191        return caller;
     192    return throwTypeError(exec, "Function.caller used to retrieve strict caller");
    185193}
    186194
Note: See TracChangeset for help on using the changeset viewer.