Changeset 10646 in webkit for trunk/JavaScriptCore/kjs/nodes.cpp


Ignore:
Timestamp:
Sep 28, 2005, 11:51:15 AM (20 years ago)
Author:
darin
Message:

Reviewed by Maciej.

  • update grammar to fix conflicts; fixes one of our test cases because it resolves the relationship between function expressions and declarations in the way required by the ECMA specification
  • kjs/grammar.y: Added lots of new grammar rules so we have no conflicts. A new set of rules for "no bracket or function at start of expression" and another set of rules for "no in anywhere in expression". Also simplified the handling of try to use only a single node and used operator precedence to get rid of the conflict in handling of if and else. Also used a macro to streamline the handling of automatic semicolons and changed parenthesis handling to use a virtual function.
  • kjs/nodes.h: Added nodeInsideAllParens, removed unused abortStatement. (KJS::TryNode::TryNode): Updated to hold catch and finally blocks directly instead of using a special node for each.
  • kjs/nodes.cpp: (Node::createErrorCompletion): Added. Used instead of throwError when creating errors that should not be in a completion rather than an ExecState. (Node::throwUndefinedVariableError): Added. Sets source location unlike the call it replaces. (Node::nodeInsideAllParens): Added. (GroupNode::nodeInsideAllParens): Added. (StatListNode::execute): Removed code to move exceptions into completion objects; that's now done solely by the KJS_CHECKEXCEPTION macro. (TryNode::execute): Include execution of catch and finally here rather than using separate nodes. (FuncDeclNode::execute): Moved here, no longer inline.
  • kjs/nodes2string.cpp: (TryNode::streamTo): Updated for change. (FuncDeclNode::streamTo): Ditto. (FuncExprNode::streamTo): Ditto.
  • kjs/kjs-test: Removed. Was part of "make check".
  • kjs/kjs-test.chk: Ditto.
  • kjs/test.js: Ditto.
  • tests/mozilla/expected.html: Updated because one more test succeeds.
File:
1 edited

Legend:

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

    r10636 r10646  
    6060  if (exec->hadException()) { \
    6161    setExceptionDetailsIfNeeded(exec); \
    62     return Completion(Throw, exec->exception()); \
     62    ValueImp *ex = exec->exception(); \
     63    exec->clearException(); \
     64    return Completion(Throw, ex); \
    6365  } \
    6466  if (Collector::outOfMemory()) \
     
    6870  if (exec->hadException()) { \
    6971    setExceptionDetailsIfNeeded(exec); \
    70     return exec->exception(); \
     72    return Undefined(); \
    7173  } \
    7274  if (Collector::outOfMemory()) \
     
    8183    return List(); // will be picked up by KJS_CHECKEXCEPTION
    8284
    83 #ifdef KJS_DEBUG_MEM
    84 std::list<Node *> * Node::s_nodes = 0L;
    85 #endif
    86 
    8785// ------------------------------ Node -----------------------------------------
    8886
     
    9997}
    10098
    101 #ifdef KJS_DEBUG_MEM
    102 void Node::finalCheck()
    103 {
    104   fprintf( stderr, "Node::finalCheck(): list count       : %d\n", (int)s_nodes.size() );
    105   std::list<Node *>::iterator it = s_nodes->begin();
    106   for ( unsigned i = 0; it != s_nodes->end() ; ++it, ++i )
    107     fprintf( stderr, "[%d] Still having node %p (%s) (refcount %d)\n", i, (void*)*it, typeid( **it ).name(), (*it)->refcount );
    108   delete s_nodes;
    109   s_nodes = 0L;
    110 }
    111 #endif
    112 
    113 ValueImp *Node::throwError(ExecState *exec, ErrorType e, const char *msg)
    114 {
    115     return KJS::throwError(exec, e, msg, lineNo(), sourceId(), &sourceURL);
    116 }
    117 
    11899static void substitute(UString &string, const UString &substring)
    119100{
     
    121102    assert(position != -1);
    122103    string = string.substr(0, position) + substring + string.substr(position + 2);
     104}
     105
     106Completion Node::createErrorCompletion(ExecState *exec, ErrorType e, const char *msg)
     107{
     108    return Completion(Throw, Error::create(exec, e, msg, lineNo(), sourceId(), &sourceURL));
     109}
     110
     111Completion Node::createErrorCompletion(ExecState *exec, ErrorType e, const char *msg, const Identifier &ident)
     112{
     113    UString message = msg;
     114    substitute(message, ident.ustring());
     115    return Completion(Throw, Error::create(exec, e, message, lineNo(), sourceId(), &sourceURL));
     116}
     117
     118ValueImp *Node::throwError(ExecState *exec, ErrorType e, const char *msg)
     119{
     120    return KJS::throwError(exec, e, msg, lineNo(), sourceId(), &sourceURL);
    123121}
    124122
     
    163161    substitute(message, label.ustring());
    164162    return KJS::throwError(exec, e, message, lineNo(), sourceId(), &sourceURL);
     163}
     164
     165ValueImp *Node::throwUndefinedVariableError(ExecState *exec, const Identifier &ident)
     166{
     167    return throwError(exec, ReferenceError, "Can't find variable: %s", ident);
    165168}
    166169
     
    177180}
    178181
     182Node *Node::nodeInsideAllParens()
     183{
     184    return this;
     185}
     186
    179187// ------------------------------ StatementNode --------------------------------
    180188
     
    200208}
    201209
    202 // return true if the debugger wants us to stop at this point
    203 bool StatementNode::abortStatement(ExecState *exec)
    204 {
    205   Debugger *dbg = exec->dynamicInterpreter()->imp()->debugger();
    206   if (dbg)
    207     return dbg->imp()->aborted();
    208   else
    209     return false;
    210 }
    211 
    212210void StatementNode::processFuncDecl(ExecState *exec)
    213211{
     
    216214// ------------------------------ NullNode -------------------------------------
    217215
    218 ValueImp *NullNode::evaluate(ExecState */*exec*/)
     216ValueImp *NullNode::evaluate(ExecState *)
    219217{
    220218  return Null();
     
    223221// ------------------------------ BooleanNode ----------------------------------
    224222
    225 ValueImp *BooleanNode::evaluate(ExecState */*exec*/)
     223ValueImp *BooleanNode::evaluate(ExecState *)
    226224{
    227225  return jsBoolean(value);
     
    230228// ------------------------------ NumberNode -----------------------------------
    231229
    232 ValueImp *NumberNode::evaluate(ExecState */*exec*/)
     230ValueImp *NumberNode::evaluate(ExecState *)
    233231{
    234232  return jsNumber(value);
     
    237235// ------------------------------ StringNode -----------------------------------
    238236
    239 ValueImp *StringNode::evaluate(ExecState */*exec*/)
     237ValueImp *StringNode::evaluate(ExecState *)
    240238{
    241239  return jsString(value);
     
    263261
    264262// ------------------------------ ResolveNode ----------------------------------
    265 
    266 static ValueImp *undefinedVariableError(ExecState *exec, const Identifier &ident)
    267 {
    268     return throwError(exec, ReferenceError, "Can't find variable: " + ident.ustring());
    269 }
    270263
    271264// ECMA 11.1.2 & 10.1.4
     
    289282  } while (iter != end);
    290283
    291   return undefinedVariableError(exec, ident);
     284  return throwUndefinedVariableError(exec, ident);
    292285}
    293286
     
    298291{
    299292  return group->evaluate(exec);
     293}
     294
     295Node *GroupNode::nodeInsideAllParens()
     296{
     297    Node *n = this;
     298    do
     299        n = static_cast<GroupNode *>(n)->group.get();
     300    while (n->isGroupNode());
     301    return n;
    300302}
    301303
     
    373375
    374376// ECMA 11.1.5
    375 ValueImp *PropertyNode::evaluate(ExecState */*exec*/)
     377ValueImp *PropertyNode::evaluate(ExecState *)
    376378{
    377379  ValueImp *s;
     
    415417// ------------------------------ ArgumentListNode -----------------------------
    416418
    417 ValueImp *ArgumentListNode::evaluate(ExecState */*exec*/)
     419ValueImp *ArgumentListNode::evaluate(ExecState *)
    418420{
    419421  assert(0);
    420   return NULL; // dummy, see evaluateList()
     422  return 0; // dummy, see evaluateList()
    421423}
    422424
     
    437439// ------------------------------ ArgumentsNode --------------------------------
    438440
    439 ValueImp *ArgumentsNode::evaluate(ExecState */*exec*/)
     441ValueImp *ArgumentsNode::evaluate(ExecState *)
    440442{
    441443  assert(0);
    442   return NULL; // dummy, see evaluateList()
     444  return 0; // dummy, see evaluateList()
    443445}
    444446
     
    549551  } while (iter != end);
    550552 
    551   return undefinedVariableError(exec, ident);
     553  return throwUndefinedVariableError(exec, ident);
    552554}
    553555
     
    672674  } while (iter != end);
    673675
    674   return undefinedVariableError(exec, m_ident);
     676  return throwUndefinedVariableError(exec, m_ident);
    675677}
    676678
     
    903905  } while (iter != end);
    904906
    905   return undefinedVariableError(exec, m_ident);
     907  return throwUndefinedVariableError(exec, m_ident);
    906908}
    907909
     
    978980  KJS_CHECKEXCEPTIONVALUE
    979981
    980   return jsNumber(v->toNumber(exec)); /* TODO: optimize */
     982  return jsNumber(v->toNumber(exec));
    981983}
    982984
     
    12921294
    12931295  if (m_oper != OpEqual)
    1294     return undefinedVariableError(exec, m_ident);
     1296    return throwUndefinedVariableError(exec, m_ident);
    12951297
    12961298 found:
     
    14201422  Completion c = statement->execute(exec);
    14211423  KJS_ABORTPOINT
    1422   if (exec->hadException()) {
    1423     ValueImp *ex = exec->exception();
    1424     exec->clearException();
    1425     return Completion(Throw, ex);
    1426   }
    1427 
    14281424  if (c.complType() != Normal)
    14291425    return c;
     
    14371433      return c2;
    14381434
    1439     if (exec->hadException()) {
    1440       ValueImp *ex = exec->exception();
    1441       exec->clearException();
    1442       return Completion(Throw, ex);
    1443     }
    1444 
    14451435    if (c2.isValueCompletion())
    14461436      v = c2.value();
     
    14861476      // built-in properties of the global object with var declarations.
    14871477      if (variable->getDirect(ident))
    1488           return NULL;
     1478          return 0;
    14891479      val = Undefined();
    14901480  }
     
    15901580
    15911581// ECMA 12.3
    1592 Completion EmptyStatementNode::execute(ExecState */*exec*/)
     1582Completion EmptyStatementNode::execute(ExecState *)
    15931583{
    15941584  return Completion(Normal);
     
    16581648    if (!((c.complType() == Continue) && ls.contains(c.target()))) {
    16591649      if ((c.complType() == Break) && ls.contains(c.target()))
    1660         return Completion(Normal, NULL);
     1650        return Completion(Normal, 0);
    16611651      if (c.complType() != Normal)
    16621652        return c;
     
    16661656  } while (bv->toBoolean(exec));
    16671657
    1668   return Completion(Normal, NULL);
     1658  return Completion(Normal, 0);
    16691659}
    16701660
     
    16841674  Completion c;
    16851675  bool b(false);
    1686   ValueImp *value = NULL;
     1676  ValueImp *value = 0;
    16871677
    16881678  while (1) {
     
    17241714Completion ForNode::execute(ExecState *exec)
    17251715{
    1726   ValueImp *v, *cval = NULL;
     1716  ValueImp *v, *cval = 0;
    17271717
    17281718  if (expr1) {
     
    17871777{
    17881778  ValueImp *e;
    1789   ValueImp *retval = NULL;
     1779  ValueImp *retval = 0;
    17901780  ObjectImp *v;
    17911781  Completion c;
     
    18041794  // access any property.
    18051795  if (e->isUndefinedOrNull()) {
    1806     return Completion(Normal, NULL);
     1796    return Completion(Normal, 0);
    18071797  }
    18081798
     
    19031893
    19041894  if (ident.isEmpty() && !exec->context().imp()->seenLabels()->inIteration())
    1905     return Completion(Throw,
    1906                       throwError(exec, SyntaxError, "Invalid continue statement."));
     1895    return createErrorCompletion(exec, SyntaxError, "Invalid continue statement.");
    19071896  else if (!ident.isEmpty() && !exec->context().imp()->seenLabels()->contains(ident))
    1908     return Completion(Throw,
    1909                       throwError(exec, SyntaxError, "Label %s not found.", ident));
     1897    return createErrorCompletion(exec, SyntaxError, "Label %s not found.", ident);
    19101898  else
    1911     return Completion(Continue, NULL, ident);
     1899    return Completion(Continue, 0, ident);
    19121900}
    19131901
     
    19211909  if (ident.isEmpty() && !exec->context().imp()->seenLabels()->inIteration() &&
    19221910      !exec->context().imp()->seenLabels()->inSwitch())
    1923     return Completion(Throw,
    1924                       throwError(exec, SyntaxError, "Invalid break statement."));
     1911    return createErrorCompletion(exec, SyntaxError, "Invalid break statement.");
    19251912  else if (!ident.isEmpty() && !exec->context().imp()->seenLabels()->contains(ident))
    1926     return Completion(Throw,
    1927                       throwError(exec, SyntaxError, "Label %s not found.", ident));
     1913    return createErrorCompletion(exec, SyntaxError, "Label %s not found.");
    19281914  else
    1929     return Completion(Break, NULL, ident);
     1915    return Completion(Break, 0, ident);
    19301916}
    19311917
     
    19391925  CodeType codeType = exec->context().imp()->codeType();
    19401926  if (codeType != FunctionCode && codeType != AnonymousCode ) {
    1941     return Completion(Throw, throwError(exec, SyntaxError, "Invalid return statement."));   
     1927    return createErrorCompletion(exec, SyntaxError, "Invalid return statement.");
    19421928  }
    19431929
     
    20021988// ------------------------------ ClauseListNode -------------------------------
    20031989
    2004 ValueImp *ClauseListNode::evaluate(ExecState */*exec*/)
    2005 {
    2006   /* should never be called */
     1990ValueImp *ClauseListNode::evaluate(ExecState *)
     1991{
     1992  // should never be called
    20071993  assert(false);
    2008   return NULL;
     1994  return 0;
    20091995}
    20101996
     
    20392025}
    20402026 
    2041 ValueImp *CaseBlockNode::evaluate(ExecState */*exec*/)
    2042 {
    2043   /* should never be called */
     2027ValueImp *CaseBlockNode::evaluate(ExecState *)
     2028{
     2029  // should never be called
    20442030  assert(false);
    2045   return NULL;
     2031  return 0;
    20462032}
    20472033
     
    21482134Completion LabelNode::execute(ExecState *exec)
    21492135{
    2150   Completion e;
    2151 
    2152   if (!exec->context().imp()->seenLabels()->push(label)) {
    2153     return Completion( Throw,
    2154                        throwError(exec, SyntaxError, "Duplicated label %s found.", label));
    2155   };
    2156   e = statement->execute(exec);
     2136  if (!exec->context().imp()->seenLabels()->push(label))
     2137    return createErrorCompletion(exec, SyntaxError, "Duplicated label %s found.", label);
     2138  Completion e = statement->execute(exec);
    21572139  exec->context().imp()->seenLabels()->pop();
    21582140
     
    21802162}
    21812163
    2182 // ------------------------------ CatchNode ------------------------------------
    2183 
    2184 Completion CatchNode::execute(ExecState */*exec*/)
    2185 {
    2186   // should never be reached. execute(exec, arg) is used instead
    2187   assert(0L);
    2188   return Completion();
    2189 }
    2190 
    2191 // ECMA 12.14
    2192 Completion CatchNode::execute(ExecState *exec, ValueImp *arg)
    2193 {
    2194   /* TODO: correct ? Not part of the spec */
    2195 
    2196   exec->clearException();
    2197 
    2198   ObjectImp *obj(new ObjectImp());
    2199   obj->put(exec, ident, arg, DontDelete);
    2200   exec->context().imp()->pushScope(obj);
    2201   Completion c = block->execute(exec);
    2202   exec->context().imp()->popScope();
    2203 
    2204   return c;
    2205 }
    2206 
    2207 void CatchNode::processVarDecls(ExecState *exec)
    2208 {
    2209   block->processVarDecls(exec);
    2210 }
    2211 
    2212 // ------------------------------ FinallyNode ----------------------------------
    2213 
    2214 // ECMA 12.14
    2215 Completion FinallyNode::execute(ExecState *exec)
    2216 {
    2217   return block->execute(exec);
    2218 }
    2219 
    2220 void FinallyNode::processVarDecls(ExecState *exec)
    2221 {
    2222   block->processVarDecls(exec);
    2223 }
    2224 
    22252164// ------------------------------ TryNode --------------------------------------
    22262165
     
    22302169  KJS_BREAKPOINT;
    22312170
    2232   Completion c, c2;
    2233 
    2234   c = block->execute(exec);
    2235 
    2236   if (!_final) {
    2237     if (c.complType() != Throw)
    2238       return c;
    2239     return _catch->execute(exec,c.value());
    2240   }
    2241 
    2242   if (!_catch) {
    2243     ValueImp *lastException = exec->exception();
    2244     exec->clearException();
    2245    
    2246     c2 = _final->execute(exec);
    2247    
    2248     if (!exec->hadException())
    2249       exec->setException(lastException);
    2250    
    2251     return (c2.complType() == Normal) ? c : c2;
    2252   }
    2253 
    2254   if (c.complType() == Throw)
    2255     c = _catch->execute(exec,c.value());
    2256 
    2257   c2 = _final->execute(exec);
    2258   return (c2.complType() == Normal) ? c : c2;
     2171  Completion c = tryBlock->execute(exec);
     2172
     2173  if (catchBlock && c.complType() == Throw) {
     2174    ObjectImp *obj = new ObjectImp;
     2175    obj->put(exec, exceptionIdent, c.value(), DontDelete);
     2176    exec->context().imp()->pushScope(obj);
     2177    c = catchBlock->execute(exec);
     2178    exec->context().imp()->popScope();
     2179  }
     2180
     2181  if (finallyBlock) {
     2182    Completion c2 = finallyBlock->execute(exec);
     2183    if (c2.complType() != Normal)
     2184      c = c2;
     2185  }
     2186
     2187  return c;
    22592188}
    22602189
    22612190void TryNode::processVarDecls(ExecState *exec)
    22622191{
    2263   block->processVarDecls(exec);
    2264   if (_final)
    2265     _final->processVarDecls(exec);
    2266   if (_catch)
    2267     _catch->processVarDecls(exec);
     2192  tryBlock->processVarDecls(exec);
     2193  if (catchBlock)
     2194    catchBlock->processVarDecls(exec);
     2195  if (finallyBlock)
     2196    finallyBlock->processVarDecls(exec);
    22682197}
    22692198
     
    22712200
    22722201// ECMA 13
    2273 ValueImp *ParameterNode::evaluate(ExecState */*exec*/)
     2202ValueImp *ParameterNode::evaluate(ExecState *)
    22742203{
    22752204  return Undefined();
     
    22822211{
    22832212  setLoc(-1, -1, -1);
    2284   //fprintf(stderr,"FunctionBodyNode::FunctionBodyNode %p\n",this);
    22852213}
    22862214
     
    22992227
    23002228  // TODO: let this be an object with [[Class]] property "Function"
    2301   FunctionImp *fimp = new DeclaredFunctionImp(exec, ident, body.get(), context->scopeChain());
    2302   ObjectImp *func(fimp); // protect from GC
     2229  FunctionImp *func = new DeclaredFunctionImp(exec, ident, body.get(), context->scopeChain());
    23032230
    23042231  ObjectImp *proto = exec->lexicalInterpreter()->builtinObject()->construct(exec, List::empty());
     
    23082235  int plen = 0;
    23092236  for(ParameterNode *p = param.get(); p != 0L; p = p->nextParam(), plen++)
    2310     fimp->addParameter(p->ident());
     2237    func->addParameter(p->ident());
    23112238
    23122239  func->put(exec, lengthPropertyName, Number(plen), ReadOnly|DontDelete|DontEnum);
     
    23272254}
    23282255
     2256Completion FuncDeclNode::execute(ExecState *)
     2257{
     2258    return Completion(Normal);
     2259}
     2260
    23292261// ------------------------------ FuncExprNode ---------------------------------
    23302262
     
    23342266  ContextImp *context = exec->context().imp();
    23352267  bool named = !ident.isNull();
    2336   ObjectImp *functionScopeObject = NULL;
     2268  ObjectImp *functionScopeObject = 0;
    23372269
    23382270  if (named) {
     
    23442276  }
    23452277
    2346   FunctionImp *fimp = new DeclaredFunctionImp(exec, ident, body.get(), context->scopeChain());
    2347   ValueImp *ret(fimp);
     2278  FunctionImp *func = new DeclaredFunctionImp(exec, ident, body.get(), context->scopeChain());
    23482279  ObjectImp *proto = exec->lexicalInterpreter()->builtinObject()->construct(exec, List::empty());
    2349   proto->put(exec, constructorPropertyName, ret, ReadOnly|DontDelete|DontEnum);
    2350   fimp->put(exec, prototypePropertyName, proto, Internal|DontDelete);
     2280  proto->put(exec, constructorPropertyName, func, ReadOnly|DontDelete|DontEnum);
     2281  func->put(exec, prototypePropertyName, proto, Internal|DontDelete);
    23512282
    23522283  int plen = 0;
    23532284  for(ParameterNode *p = param.get(); p != 0L; p = p->nextParam(), plen++)
    2354     fimp->addParameter(p->ident());
     2285    func->addParameter(p->ident());
    23552286
    23562287  if (named) {
    2357     functionScopeObject->put(exec, ident, ret, Internal | ReadOnly | (context->codeType() == EvalCode ? 0 : DontDelete));
     2288    functionScopeObject->put(exec, ident, func, Internal | ReadOnly | (context->codeType() == EvalCode ? 0 : DontDelete));
    23582289    context->popScope();
    23592290  }
    23602291
    2361   return ret;
     2292  return func;
    23622293}
    23632294
Note: See TracChangeset for help on using the changeset viewer.