Ignore:
Timestamp:
Oct 31, 2006, 10:16:08 AM (19 years ago)
Author:
ap
Message:

2006-10-31 Vladimir Olexa <[email protected]>

Reviewed by Geoff.

http://bugs.webkit.org/show_bug.cgi?id=4166
Function object does not support caller property

Test: fast/js/caller-property.html

  • kjs/function.cpp: (KJS::FunctionImp::callerGetter): added (KJS::FunctionImp::getOwnPropertySlot): added if statement to handle callerGetter()
  • kjs/function.h: added callerGetter() declaration
  • kjs/identifier.h: added caller property macro
  • tests/mozilla/expected.html:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/JavaScriptCore/kjs/function.cpp

    r17372 r17483  
    5252  public:
    5353    Parameter() {};
    54     Parameter(const Identifier &n) : name(n) { }
     54    Parameter(const Identifier& n) : name(n) { }
    5555    Identifier name;
    5656  };
    5757
    58 FunctionImp::FunctionImp(ExecState *exec, const Identifier &n, FunctionBodyNode* b)
     58FunctionImp::FunctionImp(ExecState* exec, const Identifier& n, FunctionBodyNode* b)
    5959  : InternalFunctionImp(static_cast<FunctionPrototype*>
    6060                        (exec->lexicalInterpreter()->builtinFunctionPrototype()), n)
     
    7373}
    7474
    75 JSValue *FunctionImp::callAsFunction(ExecState* exec, JSObject* thisObj, const List& args)
    76 {
    77   JSObject *globalObj = exec->dynamicInterpreter()->globalObject();
     75JSValue* FunctionImp::callAsFunction(ExecState* exec, JSObject* thisObj, const List& args)
     76{
     77  JSObject* globalObj = exec->dynamicInterpreter()->globalObject();
    7878
    7979  // enter a new execution context
     
    9090  processVarDecls(&newExec);
    9191
    92   Debugger *dbg = exec->dynamicInterpreter()->debugger();
     92  Debugger* dbg = exec->dynamicInterpreter()->debugger();
    9393  int sid = -1;
    9494  int lineno = -1;
     
    150150}
    151151
    152 void FunctionImp::addParameter(const Identifier &n)
     152void FunctionImp::addParameter(const Identifier& n)
    153153{
    154154    if (!parameters)
     
    176176
    177177// ECMA 10.1.3q
    178 void FunctionImp::processParameters(ExecState *exec, const List &args)
     178void FunctionImp::processParameters(ExecState* exec, const List& args)
    179179{
    180180    if (!parameters)
     
    191191    ListIterator it = args.begin();
    192192
    193     JSValue  *v = *it;
     193    JSValue * v = *it;
    194194    for (size_t i = 0; i < parameters->size(); ++i) {
    195195      if (it != args.end()) {
     
    215215}
    216216
    217 JSValue *FunctionImp::argumentsGetter(ExecState* exec, JSObject*, const Identifier& propertyName, const PropertySlot& slot)
    218 {
    219   FunctionImp *thisObj = static_cast<FunctionImp *>(slot.slotBase());
    220   Context *context = exec->m_context;
     217JSValue* FunctionImp::argumentsGetter(ExecState* exec, JSObject*, const Identifier& propertyName, const PropertySlot& slot)
     218{
     219  FunctionImp* thisObj = static_cast<FunctionImp*>(slot.slotBase());
     220  Context* context = exec->m_context;
    221221  while (context) {
    222222    if (context->function() == thisObj) {
    223       return static_cast<ActivationImp *>(context->activationObject())->get(exec, propertyName);
     223      return static_cast<ActivationImp*>(context->activationObject())->get(exec, propertyName);
    224224    }
    225225    context = context->callingContext();
     
    228228}
    229229
    230 JSValue *FunctionImp::lengthGetter(ExecState*, JSObject*, const Identifier&, const PropertySlot& slot)
    231 {
    232     FunctionImp *thisObj = static_cast<FunctionImp *>(slot.slotBase());
     230JSValue* FunctionImp::callerGetter(ExecState* exec, JSObject*, const Identifier&, const PropertySlot& slot)
     231{
     232    FunctionImp* thisObj = static_cast<FunctionImp* >(slot.slotBase());
     233    Context* context = exec->m_context;
     234    while (context) {
     235        if (context->function() == thisObj)
     236            return (context->callingContext()->function()) ? context->callingContext()->function() : jsNull();
     237       
     238        context = context->callingContext();
     239    }
     240    return jsNull();
     241}
     242
     243JSValue* FunctionImp::lengthGetter(ExecState*, JSObject*, const Identifier&, const PropertySlot& slot)
     244{
     245    FunctionImp* thisObj = static_cast<FunctionImp*>(slot.slotBase());
    233246    return jsNumber(thisObj->parameters ? thisObj->parameters->size() : 0);
    234247}
    235248
    236 bool FunctionImp::getOwnPropertySlot(ExecState *exec, const Identifier& propertyName, PropertySlot& slot)
     249bool FunctionImp::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
    237250{
    238251    // Find the arguments from the closest context.
     
    241254        return true;
    242255    }
    243    
     256
    244257    // Compute length of parameters.
    245258    if (propertyName == lengthPropertyName) {
     
    247260        return true;
    248261    }
    249    
     262
     263    if (propertyName == callerPropertyName) {
     264        slot.setCustom(this, callerGetter);
     265        return true;
     266    }
     267
    250268    return InternalFunctionImp::getOwnPropertySlot(exec, propertyName, slot);
    251269}
    252270
    253 void FunctionImp::put(ExecState *exec, const Identifier &propertyName, JSValue *value, int attr)
     271void FunctionImp::put(ExecState* exec, const Identifier& propertyName, JSValue* value, int attr)
    254272{
    255273    if (propertyName == exec->dynamicInterpreter()->argumentsIdentifier() || propertyName == lengthPropertyName)
     
    258276}
    259277
    260 bool FunctionImp::deleteProperty(ExecState *exec, const Identifier &propertyName)
     278bool FunctionImp::deleteProperty(ExecState* exec, const Identifier& propertyName)
    261279{
    262280    if (propertyName == exec->dynamicInterpreter()->argumentsIdentifier() || propertyName == lengthPropertyName)
     
    295313const ClassInfo DeclaredFunctionImp::info = {"Function", &FunctionImp::info, 0, 0};
    296314
    297 DeclaredFunctionImp::DeclaredFunctionImp(ExecState *exec, const Identifier &n,
    298                                          FunctionBodyNode *b, const ScopeChain &sc)
     315DeclaredFunctionImp::DeclaredFunctionImp(ExecState* exec, const Identifier& n,
     316                                         FunctionBodyNode* b, const ScopeChain& sc)
    299317  : FunctionImp(exec, n, b)
    300318{
     
    308326
    309327// ECMA 13.2.2 [[Construct]]
    310 JSObject *DeclaredFunctionImp::construct(ExecState *exec, const List &args)
    311 {
    312   JSObject *proto;
    313   JSValue *p = get(exec,prototypePropertyName);
     328JSObject* DeclaredFunctionImp::construct(ExecState* exec, const List& args)
     329{
     330  JSObject* proto;
     331  JSValue* p = get(exec,prototypePropertyName);
    314332  if (p->isObject())
    315333    proto = static_cast<JSObject*>(p);
     
    317335    proto = exec->lexicalInterpreter()->builtinObjectPrototype();
    318336
    319   JSObject *obj(new JSObject(proto));
    320 
    321   JSValue *res = call(exec,obj,args);
     337  JSObject* obj(new JSObject(proto));
     338
     339  JSValue* res = call(exec,obj,args);
    322340
    323341  if (res->isObject())
    324     return static_cast<JSObject *>(res);
     342    return static_cast<JSObject*>(res);
    325343  else
    326344    return obj;
    327345}
    328346
    329 Completion DeclaredFunctionImp::execute(ExecState *exec)
     347Completion DeclaredFunctionImp::execute(ExecState* exec)
    330348{
    331349  Completion result = body->execute(exec);
     
    336354}
    337355
    338 void DeclaredFunctionImp::processVarDecls(ExecState *exec)
     356void DeclaredFunctionImp::processVarDecls(ExecState* exec)
    339357{
    340358  body->processVarDecls(exec);
     
    352370// isn't stored in the activation object.
    353371
    354 IndexToNameMap::IndexToNameMap(FunctionImp *func, const List &args)
     372IndexToNameMap::IndexToNameMap(FunctionImp* func, const List& args)
    355373{
    356374  _map = new Identifier[args.size()];
     
    367385}
    368386
    369 bool IndexToNameMap::isMapped(const Identifier &index) const
     387bool IndexToNameMap::isMapped(const Identifier& index) const
    370388{
    371389  bool indexIsNumber;
     
    384402}
    385403
    386 void IndexToNameMap::unMap(const Identifier &index)
     404void IndexToNameMap::unMap(const Identifier& index)
    387405{
    388406  bool indexIsNumber;
     
    399417}
    400418
    401 Identifier& IndexToNameMap::operator[](const Identifier &index)
     419Identifier& IndexToNameMap::operator[](const Identifier& index)
    402420{
    403421  bool indexIsNumber;
     
    414432
    415433// ECMA 10.1.8
    416 Arguments::Arguments(ExecState *exec, FunctionImp *func, const List &args, ActivationImp *act)
     434Arguments::Arguments(ExecState* exec, FunctionImp* func, const List& args, ActivationImp* act)
    417435: JSObject(exec->lexicalInterpreter()->builtinObjectPrototype()),
    418436_activationObject(act),
     
    438456}
    439457
    440 JSValue *Arguments::mappedIndexGetter(ExecState* exec, JSObject*, const Identifier& propertyName, const PropertySlot& slot)
    441 {
    442   Arguments *thisObj = static_cast<Arguments *>(slot.slotBase());
     458JSValue* Arguments::mappedIndexGetter(ExecState* exec, JSObject*, const Identifier& propertyName, const PropertySlot& slot)
     459{
     460  Arguments* thisObj = static_cast<Arguments*>(slot.slotBase());
    443461  return thisObj->_activationObject->get(exec, thisObj->indexToNameMap[propertyName]);
    444462}
    445463
    446 bool Arguments::getOwnPropertySlot(ExecState *exec, const Identifier& propertyName, PropertySlot& slot)
     464bool Arguments::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
    447465{
    448466  if (indexToNameMap.isMapped(propertyName)) {
     
    454472}
    455473
    456 void Arguments::put(ExecState *exec, const Identifier &propertyName, JSValue *value, int attr)
     474void Arguments::put(ExecState* exec, const Identifier& propertyName, JSValue* value, int attr)
    457475{
    458476  if (indexToNameMap.isMapped(propertyName)) {
     
    463481}
    464482
    465 bool Arguments::deleteProperty(ExecState *exec, const Identifier &propertyName)
     483bool Arguments::deleteProperty(ExecState* exec, const Identifier& propertyName)
    466484{
    467485  if (indexToNameMap.isMapped(propertyName)) {
     
    478496
    479497// ECMA 10.1.6
    480 ActivationImp::ActivationImp(FunctionImp *function, const List &arguments)
     498ActivationImp::ActivationImp(FunctionImp* function, const List& arguments)
    481499    : _function(function), _arguments(true), _argumentsObject(0)
    482500{
     
    485503}
    486504
    487 JSValue *ActivationImp::argumentsGetter(ExecState* exec, JSObject*, const Identifier&, const PropertySlot& slot)
    488 {
    489   ActivationImp *thisObj = static_cast<ActivationImp *>(slot.slotBase());
     505JSValue* ActivationImp::argumentsGetter(ExecState* exec, JSObject*, const Identifier&, const PropertySlot& slot)
     506{
     507  ActivationImp* thisObj = static_cast<ActivationImp*>(slot.slotBase());
    490508
    491509  // default: return builtin arguments array
     
    501519}
    502520
    503 bool ActivationImp::getOwnPropertySlot(ExecState *exec, const Identifier& propertyName, PropertySlot& slot)
     521bool ActivationImp::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
    504522{
    505523    // do this first so property map arguments property wins over the below
     
    507525    // and we don't want to support __proto__
    508526
    509     if (JSValue **location = getDirectLocation(propertyName)) {
     527    if (JSValue** location = getDirectLocation(propertyName)) {
    510528        slot.setValueSlot(this, location);
    511529        return true;
     
    520538}
    521539
    522 bool ActivationImp::deleteProperty(ExecState *exec, const Identifier &propertyName)
     540bool ActivationImp::deleteProperty(ExecState* exec, const Identifier& propertyName)
    523541{
    524542    if (propertyName == exec->dynamicInterpreter()->argumentsIdentifier())
     
    546564}
    547565
    548 void ActivationImp::createArgumentsObject(ExecState *exec) const
    549 {
    550   _argumentsObject = new Arguments(exec, _function, _arguments, const_cast<ActivationImp *>(this));
     566void ActivationImp::createArgumentsObject(ExecState* exec) const
     567{
     568  _argumentsObject = new Arguments(exec, _function, _arguments, const_cast<ActivationImp*>(this));
    551569}
    552570
     
    566584}
    567585
    568 static JSValue *encode(ExecState *exec, const List &args, const char *do_not_escape)
     586static JSValue* encode(ExecState* exec, const List& args, const char* do_not_escape)
    569587{
    570588  UString r = "", s, str = args[0]->toString(exec);
    571589  CString cstr = str.UTF8String();
    572   const char *p = cstr.c_str();
     590  const char* p = cstr.c_str();
    573591  for (size_t k = 0; k < cstr.size(); k++, p++) {
    574592    char c = *p;
     
    584602}
    585603
    586 static JSValue *decode(ExecState *exec, const List &args, const char *do_not_unescape, bool strict)
     604static JSValue* decode(ExecState* exec, const List& args, const char* do_not_unescape, bool strict)
    587605{
    588606  UString s = "", str = args[0]->toString(exec);
    589607  int k = 0, len = str.size();
    590   const UChar *d = str.data();
     608  const UChar* d = str.data();
    591609  UChar u;
    592610  while (k < len) {
    593     const UChar *p = d + k;
     611    const UChar* p = d + k;
    594612    UChar c = *p;
    595613    if (c == '%') {
     
    603621          sequence[0] = b0;
    604622          for (int i = 1; i < sequenceLen; ++i) {
    605             const UChar *q = p + i * 3;
     623            const UChar* q = p + i * 3;
    606624            if (q[0] == '%' && isxdigit(q[1].uc) && isxdigit(q[2].uc))
    607625              sequence[i] = Lexer::convertHex(q[1].uc, q[2].uc);
     
    684702}
    685703
    686 static double parseInt(const UString &s, int radix)
     704static double parseInt(const UString& s, int radix)
    687705{
    688706    int length = s.size();
     
    734752}
    735753
    736 static double parseFloat(const UString &s)
     754static double parseFloat(const UString& s)
    737755{
    738756    // Check for 0x prefix here, because toDouble allows it, but we must treat it as 0.
     
    753771}
    754772
    755 JSValue *GlobalFuncImp::callAsFunction(ExecState *exec, JSObject* /*thisObj*/, const List &args)
    756 {
    757   JSValue *res = jsUndefined();
     773JSValue* GlobalFuncImp::callAsFunction(ExecState* exec, JSObject* /*thisObj*/, const List& args)
     774{
     775  JSValue* res = jsUndefined();
    758776
    759777  static const char do_not_escape[] =
     
    778796  switch (id) {
    779797    case Eval: { // eval()
    780       JSValue *x = args[0];
     798      JSValue* x = args[0];
    781799      if (!x->isString())
    782800        return x;
     
    789807        RefPtr<ProgramNode> progNode(Parser::parse(UString(), 0, s.data(),s.size(),&sid,&errLine,&errMsg));
    790808
    791         Debugger *dbg = exec->dynamicInterpreter()->debugger();
     809        Debugger* dbg = exec->dynamicInterpreter()->debugger();
    792810        if (dbg) {
    793811          bool cont = dbg->sourceParsed(exec, sid, UString(), s, 0, errLine, errMsg);
     
    801819
    802820        // enter a new execution context
    803         JSObject *thisVal = static_cast<JSObject *>(exec->context()->thisValue());
     821        JSObject* thisVal = static_cast<JSObject*>(exec->context()->thisValue());
    804822        Context ctx(exec->dynamicInterpreter()->globalObject(),
    805823                       exec->dynamicInterpreter(),
     
    858876    {
    859877      UString r = "", s, str = args[0]->toString(exec);
    860       const UChar *c = str.data();
     878      const UChar* c = str.data();
    861879      for (int k = 0; k < str.size(); k++, c++) {
    862880        int u = c->uc;
     
    882900      int k = 0, len = str.size();
    883901      while (k < len) {
    884         const UChar *c = str.data() + k;
     902        const UChar* c = str.data() + k;
    885903        UChar u;
    886904        if (*c == UChar('%') && k <= len - 6 && *(c+1) == UChar('u')) {
Note: See TracChangeset for help on using the changeset viewer.