[webkit-changes] cvs commit: WebCore ChangeLog

Maciej mjs at opensource.apple.com
Thu Aug 11 03:26:58 PDT 2005


mjs         05/08/11 03:26:58

  Modified:    .        ChangeLog
               kjs      grammar.y lexer.cpp nodes.cpp nodes.h
                        nodes2string.cpp property_slot.h
               .        ChangeLog
  Log:
  JavaScriptCore:
  
          Reviewed by Geoff.
  
  	Refactor assignment grammar to avoid Reference type, and to later
  	be able to take advantage of writeable PropertySlots, when those
  	are added. I also fixed a minor bug, turning a function to a
  	string lost parentheses, I made sure they are printed at least
  	where semantically significant.
  
  	Test cases: see WebCore
  
          * kjs/grammar.y: Change grammar so that assignment expressions are parsed
  	directly to nodes that know how to set the kind of location being assigned, instead
  	of having a generic assign node that counts on evaluateReference.
          * kjs/lexer.cpp: Include grammar_types.h.
          * kjs/nodes.cpp:
          (BracketAccessorNode): Renamed from AccessorNode1 for clarity.
          (DotAccessorNode): Renamed from AccessorNode2 for clarity.
          (combineForAssignment): Inline function for doing the proper kind of
  	operation for various update assignments like += or *=.
          (AssignResolveNode): Node that handles assignment to a bare identifier.
          (AssignDotNode): Node that handles assignments of the form EXPR . IDENT = EXPR
          (AssignBracketNode): EXPR [ IDENT ] = EXPR
          * kjs/nodes.h: Updated for declarations/renames of new classes.
          * kjs/nodes2string.cpp:
          (GroupNode::streamTo): Fixed to print parens around the expression.
          (BracketAccessorNode::streamTo): Renamed.
          (DotAccessorNode::streamTo): Renamed.
          (AssignResolveNode::streamTo): Added.
          (AssignBracketNode::streamTo): Added.
          (AssignDotNode::streamTo): Added.
          (streamAssignmentOperatorTo): helper function for the above
          * kjs/property_slot.h:
          (KJS::PropertySlot::isSet): Made this const.
  
  WebCore:
  
          Reviewed by Geoff.
  
          Test cases added:
  
          * layout-tests/fast/js/assign.html: Added. Test case for assignment to make sure
  	I didn't break anything.
          * layout-tests/fast/js/code-serialize-paren.html: Added, test case for a minor bug
  	I fixed where parens were not getting serialized at all when turning a function
  	into a string.
  
  Revision  Changes    Path
  1.785     +36 -0     JavaScriptCore/ChangeLog
  
  Index: ChangeLog
  ===================================================================
  RCS file: /cvs/root/JavaScriptCore/ChangeLog,v
  retrieving revision 1.784
  retrieving revision 1.785
  diff -u -r1.784 -r1.785
  --- ChangeLog	10 Aug 2005 21:55:43 -0000	1.784
  +++ ChangeLog	11 Aug 2005 10:26:52 -0000	1.785
  @@ -1,3 +1,39 @@
  +2005-08-10  Maciej Stachowiak  <mjs at apple.com>
  +
  +        Reviewed by Geoff.
  +
  +	Refactor assignment grammar to avoid Reference type, and to later
  +	be able to take advantage of writeable PropertySlots, when those
  +	are added. I also fixed a minor bug, turning a function to a
  +	string lost parentheses, I made sure they are printed at least
  +	where semantically significant.
  +	
  +	Test cases: see WebCore
  +	
  +        * kjs/grammar.y: Change grammar so that assignment expressions are parsed
  +	directly to nodes that know how to set the kind of location being assigned, instead
  +	of having a generic assign node that counts on evaluateReference.
  +        * kjs/lexer.cpp: Include grammar_types.h.
  +        * kjs/nodes.cpp:
  +        (BracketAccessorNode): Renamed from AccessorNode1 for clarity.
  +        (DotAccessorNode): Renamed from AccessorNode2 for clarity.
  +        (combineForAssignment): Inline function for doing the proper kind of
  +	operation for various update assignments like += or *=.
  +        (AssignResolveNode): Node that handles assignment to a bare identifier.
  +        (AssignDotNode): Node that handles assignments of the form EXPR . IDENT = EXPR
  +        (AssignBracketNode): EXPR [ IDENT ] = EXPR
  +        * kjs/nodes.h: Updated for declarations/renames of new classes.
  +        * kjs/nodes2string.cpp:
  +        (GroupNode::streamTo): Fixed to print parens around the expression.
  +        (BracketAccessorNode::streamTo): Renamed.
  +        (DotAccessorNode::streamTo): Renamed.
  +        (AssignResolveNode::streamTo): Added.
  +        (AssignBracketNode::streamTo): Added.
  +        (AssignDotNode::streamTo): Added.
  +        (streamAssignmentOperatorTo): helper function for the above
  +        * kjs/property_slot.h:
  +        (KJS::PropertySlot::isSet): Made this const.
  +
   2005-08-10  Adele Peterson  <adele at apple.com>
   
           Bumping version to 420+
  
  
  
  1.24      +61 -7     JavaScriptCore/kjs/grammar.y
  
  Index: grammar.y
  ===================================================================
  RCS file: /cvs/root/JavaScriptCore/kjs/grammar.y,v
  retrieving revision 1.23
  retrieving revision 1.24
  diff -u -r1.23 -r1.24
  --- grammar.y	27 Jul 2005 23:10:49 -0000	1.23
  +++ grammar.y	11 Aug 2005 10:26:53 -0000	1.24
  @@ -32,6 +32,7 @@
   #include "nodes.h"
   #include "lexer.h"
   #include "internal.h"
  +#include "grammar_types.h"
   
   // Not sure why, but yacc doesn't add this define along with the others.
   #define yylloc kjsyylloc
  @@ -78,6 +79,8 @@
     PropertyNode        *pnode;
     CatchNode           *cnode;
     FinallyNode         *fnode;
  +  NodePair            np;
  +  NodeWithIdent       ni;
   }
   
   %start Program
  @@ -162,6 +165,10 @@
   %type <plist> PropertyNameAndValueList
   %type <pnode> PropertyName
   
  +%type <ident> ParenthesizedIdent;
  +%type <np>    MemberBracketExpr CallBracketExpr ParenthesizedBracketExpr
  +%type <ni>    MemberDotExpr CallDotExpr ParenthesizedDotExpr
  +
   %%
   
   Literal:
  @@ -179,11 +186,18 @@
                                        $$ = new RegExpNode(UString('=')+l->pattern,l->flags);}
   ;
   
  +ParenthesizedIdent:
  +    IDENT
  +  | '(' ParenthesizedIdent ')' { $$ = $2 }
  +;
  +
   PrimaryExpr:
       THIS                           { $$ = new ThisNode(); }
  -  | IDENT                          { $$ = new ResolveNode(*$1); }
     | Literal
     | ArrayLiteral
  +  | ParenthesizedIdent             { $$ = new ResolveNode(*$1); }
  +  | ParenthesizedBracketExpr       { $$ = new GroupNode(new BracketAccessorNode($1.first, $1.second)); }
  +  | ParenthesizedDotExpr           { $$ = new GroupNode(new DotAccessorNode($1.node, *$1.ident)); }
     | '(' Expr ')'                   { $$ = new GroupNode($2); }
     | '{' '}'                        { $$ = new ObjectLiteralNode(); }
     | '{' PropertyNameAndValueList '}'   { $$ = new ObjectLiteralNode($2); }
  @@ -223,11 +237,39 @@
     | NUMBER                         { $$ = new PropertyNode($1); }
   ;
   
  +CallBracketExpr:
  +  CallExpr '[' Expr ']' { $$ = makeNodePair($1, $3); }
  +;
  +
  +MemberBracketExpr:
  +  MemberExpr '[' Expr ']' { $$ = makeNodePair($1, $3); }
  +;
  +
  +ParenthesizedBracketExpr:
  +    '(' MemberBracketExpr ')' { $$ = $2; }
  +  | '(' CallBracketExpr ')' { $$ = $2; }
  +  | '(' ParenthesizedBracketExpr ')' { $$ = $2; }
  +;
  +
  +CallDotExpr:
  +  CallExpr '.' IDENT { $$ = makeNodeWithIdent($1, $3); }
  +;
  +
  +MemberDotExpr:
  +  MemberExpr '.' IDENT { $$ = makeNodeWithIdent($1, $3); }
  +;
  +
  +ParenthesizedDotExpr:
  +    '(' MemberDotExpr ')' { $$ = $2; }
  +  | '(' CallDotExpr ')' { $$ = $2; }
  +  | '(' ParenthesizedDotExpr ')' { $$ = $2; }
  +;
  +
   MemberExpr:
       PrimaryExpr
     | FunctionExpr
  -  | MemberExpr '[' Expr ']'        { $$ = new AccessorNode1($1, $3); }
  -  | MemberExpr '.' IDENT           { $$ = new AccessorNode2($1, *$3); }
  +  | MemberBracketExpr              { $$ = new BracketAccessorNode($1.first, $1.second); }
  +  | MemberDotExpr                  { $$ = new DotAccessorNode($1.node, *$1.ident); }
     | NEW MemberExpr Arguments       { $$ = new NewExprNode($2, $3); }
   ;
   
  @@ -239,8 +281,8 @@
   CallExpr:
       MemberExpr Arguments           { $$ = new FunctionCallNode($1, $2); }
     | CallExpr Arguments             { $$ = new FunctionCallNode($1, $2); }
  -  | CallExpr '[' Expr ']'          { $$ = new AccessorNode1($1, $3); }
  -  | CallExpr '.' IDENT             { $$ = new AccessorNode2($1, *$3); }
  +  | CallBracketExpr                { $$ = new BracketAccessorNode($1.first, $1.second); }
  +  | CallDotExpr                    { $$ = new DotAccessorNode($1.node, *$1.ident); }
   ;
   
   Arguments:
  @@ -358,8 +400,20 @@
   
   AssignmentExpr:
       ConditionalExpr
  -  | LeftHandSideExpr AssignmentOperator AssignmentExpr
  -                           { $$ = new AssignNode($1, $2, $3);}
  +  | ParenthesizedIdent AssignmentOperator AssignmentExpr
  +                           { $$ = new AssignResolveNode(*$1, $2, $3); }
  +  | MemberBracketExpr AssignmentOperator AssignmentExpr
  +                           { $$ = new AssignBracketNode($1.first, $1.second, $2, $3); }
  +  | CallBracketExpr AssignmentOperator AssignmentExpr
  +                           { $$ = new AssignBracketNode($1.first, $1.second, $2, $3); }
  +  | ParenthesizedBracketExpr AssignmentOperator AssignmentExpr
  +                           { $$ = new AssignBracketNode($1.first, $1.second, $2, $3); }
  +  | MemberDotExpr AssignmentOperator AssignmentExpr
  +                           { $$ = new AssignDotNode($1.node, *$1.ident, $2, $3); }
  +  | CallDotExpr AssignmentOperator AssignmentExpr
  +                           { $$ = new AssignDotNode($1.node, *$1.ident, $2, $3); }
  +  | ParenthesizedDotExpr AssignmentOperator AssignmentExpr
  +                           { $$ = new AssignDotNode($1.node, *$1.ident, $2, $3); }
   ;
   
   AssignmentOperator:
  
  
  
  1.19      +1 -0      JavaScriptCore/kjs/lexer.cpp
  
  Index: lexer.cpp
  ===================================================================
  RCS file: /cvs/root/JavaScriptCore/kjs/lexer.cpp,v
  retrieving revision 1.18
  retrieving revision 1.19
  diff -u -r1.18 -r1.19
  --- lexer.cpp	14 Jul 2005 18:27:02 -0000	1.18
  +++ lexer.cpp	11 Aug 2005 10:26:53 -0000	1.19
  @@ -39,6 +39,7 @@
   #include "identifier.h"
   #include "lookup.h"
   #include "internal.h"
  +#include "grammar_types.h"
   
   // we can't specify the namespace in yacc's C output, so do it here
   using namespace KJS;
  
  
  
  1.71      +241 -88   JavaScriptCore/kjs/nodes.cpp
  
  Index: nodes.cpp
  ===================================================================
  RCS file: /cvs/root/JavaScriptCore/kjs/nodes.cpp,v
  retrieving revision 1.70
  retrieving revision 1.71
  diff -u -r1.70 -r1.71
  --- nodes.cpp	8 Aug 2005 04:07:28 -0000	1.70
  +++ nodes.cpp	11 Aug 2005 10:26:53 -0000	1.71
  @@ -270,6 +270,14 @@
   
   // ------------------------------ ResolveNode ----------------------------------
   
  +static ValueImp *undefinedVariableError(ExecState *exec, const Identifier &ident)
  +{
  +  UString m = I18N_NOOP("Can't find variable: ") + ident.ustring();
  +  ObjectImp *err = Error::create(exec, ReferenceError, m.ascii());
  +  exec->setException(err);
  +  return err;
  +}
  +
   // ECMA 11.1.2 & 10.1.4
   ValueImp *ResolveNode::evaluate(ExecState *exec)
   {
  @@ -287,7 +295,7 @@
       chain.pop();
     } while (!chain.isEmpty());
   
  -  return Reference(ident).getValue(exec);
  +  return undefinedVariableError(exec, ident);
   }
   
   Reference ResolveNode::evaluateReference(ExecState *exec)
  @@ -497,9 +505,9 @@
     return s;
   }
   
  -// ------------------------------ AccessorNode1 --------------------------------
  +// ------------------------------ BracketAccessorNode --------------------------------
   
  -void AccessorNode1::ref()
  +void BracketAccessorNode::ref()
   {
     Node::ref();
     if ( expr1 )
  @@ -508,7 +516,7 @@
       expr2->ref();
   }
   
  -bool AccessorNode1::deref()
  +bool BracketAccessorNode::deref()
   {
     if ( expr1 && expr1->deref() )
       delete expr1;
  @@ -518,7 +526,7 @@
   }
   
   // ECMA 11.2.1a
  -ValueImp *AccessorNode1::evaluate(ExecState *exec)
  +ValueImp *BracketAccessorNode::evaluate(ExecState *exec)
   {
     ValueImp *v1 = expr1->evaluate(exec);
     KJS_CHECKEXCEPTIONVALUE
  @@ -531,7 +539,7 @@
     return o->get(exec, Identifier(v2->toString(exec)));
   }
   
  -Reference AccessorNode1::evaluateReference(ExecState *exec)
  +Reference BracketAccessorNode::evaluateReference(ExecState *exec)
   {
     ValueImp *v1 = expr1->evaluate(exec);
     KJS_CHECKEXCEPTIONREFERENCE
  @@ -544,16 +552,16 @@
     return Reference(o, Identifier(v2->toString(exec)));
   }
   
  -// ------------------------------ AccessorNode2 --------------------------------
  +// ------------------------------ DotAccessorNode --------------------------------
   
  -void AccessorNode2::ref()
  +void DotAccessorNode::ref()
   {
     Node::ref();
     if ( expr )
       expr->ref();
   }
   
  -bool AccessorNode2::deref()
  +bool DotAccessorNode::deref()
   {
     if ( expr && expr->deref() )
       delete expr;
  @@ -561,7 +569,7 @@
   }
   
   // ECMA 11.2.1b
  -ValueImp *AccessorNode2::evaluate(ExecState *exec)
  +ValueImp *DotAccessorNode::evaluate(ExecState *exec)
   {
     ValueImp *v = expr->evaluate(exec);
     KJS_CHECKEXCEPTIONVALUE
  @@ -569,7 +577,7 @@
   
   }
   
  -Reference AccessorNode2::evaluateReference(ExecState *exec)
  +Reference DotAccessorNode::evaluateReference(ExecState *exec)
   {
     ValueImp *v = expr->evaluate(exec);
     KJS_CHECKEXCEPTIONREFERENCE
  @@ -1359,101 +1367,246 @@
     return v;
   }
   
  -// ------------------------------ AssignNode -----------------------------------
  +// ECMA 11.13
   
  -void AssignNode::ref()
  +// gcc refuses to inline this without the always_inline, but inlining it does help
  +static inline ValueImp *valueForReadModifyAssignment(ExecState * exec, ValueImp *v1, ValueImp *v2, Operator oper) __attribute__((always_inline));
  +
  +static inline ValueImp *valueForReadModifyAssignment(ExecState * exec, ValueImp *v1, ValueImp *v2, Operator oper)
  +{
  +  ValueImp *v;
  +  int i1;
  +  int i2;
  +  unsigned int ui;
  +  switch (oper) {
  +  case OpMultEq:
  +    v = mult(exec, v1, v2, '*');
  +    break;
  +  case OpDivEq:
  +    v = mult(exec, v1, v2, '/');
  +    break;
  +  case OpPlusEq:
  +    v = add(exec, v1, v2, '+');
  +    break;
  +  case OpMinusEq:
  +    v = add(exec, v1, v2, '-');
  +    break;
  +  case OpLShift:
  +    i1 = v1->toInt32(exec);
  +    i2 = v2->toInt32(exec);
  +    v = jsNumber(i1 << i2);
  +    break;
  +  case OpRShift:
  +    i1 = v1->toInt32(exec);
  +    i2 = v2->toInt32(exec);
  +    v = jsNumber(i1 >> i2);
  +    break;
  +  case OpURShift:
  +    ui = v1->toUInt32(exec);
  +    i2 = v2->toInt32(exec);
  +    v = jsNumber(ui >> i2);
  +    break;
  +  case OpAndEq:
  +    i1 = v1->toInt32(exec);
  +    i2 = v2->toInt32(exec);
  +    v = jsNumber(i1 & i2);
  +    break;
  +  case OpXOrEq:
  +    i1 = v1->toInt32(exec);
  +    i2 = v2->toInt32(exec);
  +    v = jsNumber(i1 ^ i2);
  +    break;
  +  case OpOrEq:
  +    i1 = v1->toInt32(exec);
  +    i2 = v2->toInt32(exec);
  +    v = jsNumber(i1 | i2);
  +    break;
  +  case OpModEq: {
  +    bool d1KnownToBeInteger;
  +    double d1 = v1->toNumber(exec, d1KnownToBeInteger);
  +    bool d2KnownToBeInteger;
  +    double d2 = v2->toNumber(exec, d2KnownToBeInteger);
  +    v = jsNumber(fmod(d1, d2), d1KnownToBeInteger && d2KnownToBeInteger && d2 != 0);
  +  }
  +    break;
  +  default:
  +    assert(0);
  +    v = Undefined();
  +  }
  +  
  +  return v;
  +}
  +
  +// ------------------------------ AssignResolveNode -----------------------------------
  +
  +void AssignResolveNode::ref()
   {
     Node::ref();
  -  if ( left )
  -    left->ref();
  -  if ( expr )
  -    expr->ref();
  +  if (m_right)
  +    m_right->ref();
   }
   
  -bool AssignNode::deref()
  +bool AssignResolveNode::deref()
   {
  -  if ( left && left->deref() )
  -    delete left;
  -  if ( expr && expr->deref() )
  -    delete expr;
  +  if (m_right && m_right->deref())
  +    delete m_right;
  +
     return Node::deref();
   }
   
  -// ECMA 11.13
  -ValueImp *AssignNode::evaluate(ExecState *exec)
  +ValueImp *AssignResolveNode::evaluate(ExecState *exec)
   {
  -  Reference l = left->evaluateReference(exec);
  -  KJS_CHECKEXCEPTIONVALUE
  +  ScopeChain chain = exec->context().imp()->scopeChain();
  +
  +  assert(!chain.isEmpty());
  +
  +  PropertySlot slot;
  +  ObjectImp *base;
  +  do { 
  +    base = chain.top();
  +    if (base->getPropertySlot(exec, m_ident, slot))
  +      goto found;
  +
  +    chain.pop();
  +  } while (!chain.isEmpty());
  +
  +  if (m_oper != OpEqual)
  +    return undefinedVariableError(exec, m_ident);
  +
  + found:
     ValueImp *v;
  -  if (oper == OpEqual) {
  -    v = expr->evaluate(exec);
  +
  +  if (m_oper == OpEqual) {
  +    v = m_right->evaluate(exec);
  +  } else {
  +    assert(slot.isSet());
  +    ValueImp *v1 = slot.getValue(exec, m_ident);
       KJS_CHECKEXCEPTIONVALUE
  +    ValueImp *v2 = m_right->evaluate(exec);
  +    v = valueForReadModifyAssignment(exec, v1, v2, m_oper);
  +  }
  +
  +  KJS_CHECKEXCEPTIONVALUE
  +
  +  base->put(exec, m_ident, v);
  +  return v;
  +}
  +
  +// ------------------------------ AssignDotNode -----------------------------------
  +
  +void AssignDotNode::ref()
  +{
  +  Node::ref();
  +  if (m_base)
  +    m_base->ref();
  +  if (m_right)
  +    m_right->ref();
  +}
  +
  +bool AssignDotNode::deref()
  +{
  +  if (m_base && m_base->deref())
  +    delete m_base;
  +  if (m_right && m_right->deref())
  +    delete m_right;
  +  return Node::deref();
  +}
  +
  +ValueImp *AssignDotNode::evaluate(ExecState *exec)
  +{
  +  ValueImp *baseValue = m_base->evaluate(exec);
  +  KJS_CHECKEXCEPTIONVALUE
  +  ObjectImp *base = baseValue->toObject(exec);
  +
  +  ValueImp *v;
  +
  +  if (m_oper == OpEqual) {
  +    v = m_right->evaluate(exec);
     } else {
  -    ValueImp *v1 = l.getValue(exec);
  -    ValueImp *v2 = expr->evaluate(exec);
  +    PropertySlot slot;
  +    ValueImp *v1 = base->getPropertySlot(exec, m_ident, slot) ? slot.getValue(exec, m_ident) : Undefined();
       KJS_CHECKEXCEPTIONVALUE
  -    int i1;
  -    int i2;
  -    unsigned int ui;
  -    switch (oper) {
  -    case OpMultEq:
  -      v = mult(exec, v1, v2, '*');
  -      break;
  -    case OpDivEq:
  -      v = mult(exec, v1, v2, '/');
  -      break;
  -    case OpPlusEq:
  -      v = add(exec, v1, v2, '+');
  -      break;
  -    case OpMinusEq:
  -      v = add(exec, v1, v2, '-');
  -      break;
  -    case OpLShift:
  -      i1 = v1->toInt32(exec);
  -      i2 = v2->toInt32(exec);
  -      v = jsNumber(i1 << i2);
  -      break;
  -    case OpRShift:
  -      i1 = v1->toInt32(exec);
  -      i2 = v2->toInt32(exec);
  -      v = jsNumber(i1 >> i2);
  -      break;
  -    case OpURShift:
  -      ui = v1->toUInt32(exec);
  -      i2 = v2->toInt32(exec);
  -      v = jsNumber(ui >> i2);
  -      break;
  -    case OpAndEq:
  -      i1 = v1->toInt32(exec);
  -      i2 = v2->toInt32(exec);
  -      v = jsNumber(i1 & i2);
  -      break;
  -    case OpXOrEq:
  -      i1 = v1->toInt32(exec);
  -      i2 = v2->toInt32(exec);
  -      v = jsNumber(i1 ^ i2);
  -      break;
  -    case OpOrEq:
  -      i1 = v1->toInt32(exec);
  -      i2 = v2->toInt32(exec);
  -      v = jsNumber(i1 | i2);
  -      break;
  -    case OpModEq: {
  -      bool d1KnownToBeInteger;
  -      double d1 = v1->toNumber(exec, d1KnownToBeInteger);
  -      bool d2KnownToBeInteger;
  -      double d2 = v2->toNumber(exec, d2KnownToBeInteger);
  -      v = jsNumber(fmod(d1, d2), d1KnownToBeInteger && d2KnownToBeInteger && d2 != 0);
  -    }
  -      break;
  -    default:
  -      v = Undefined();
  +    ValueImp *v2 = m_right->evaluate(exec);
  +    v = valueForReadModifyAssignment(exec, v1, v2, m_oper);
  +  }
  +
  +  KJS_CHECKEXCEPTIONVALUE
  +
  +  base->put(exec, m_ident, v);
  +  return v;
  +}
  +
  +// ------------------------------ AssignBracketNode -----------------------------------
  +
  +void AssignBracketNode::ref()
  +{
  +  Node::ref();
  +  if (m_base)
  +    m_base->ref();
  +  if (m_subscript)
  +    m_subscript->ref();
  +  if (m_right)
  +    m_right->ref();
  +}
  +
  +bool AssignBracketNode::deref()
  +{
  +  if (m_base && m_base->deref())
  +    delete m_base;
  +  if (m_subscript && m_subscript->deref())
  +    delete m_subscript;
  +  if (m_right && m_right->deref())
  +    delete m_right;
  +
  +  return Node::deref();
  +}
  +
  +ValueImp *AssignBracketNode::evaluate(ExecState *exec)
  +{
  +  ValueImp *baseValue = m_base->evaluate(exec);
  +  KJS_CHECKEXCEPTIONVALUE
  +  ValueImp *subscript = m_subscript->evaluate(exec);
  +  KJS_CHECKEXCEPTIONVALUE
  +
  +  ObjectImp *base = baseValue->toObject(exec);
  +
  +  uint32_t propertyIndex;
  +  if (subscript->getUInt32(propertyIndex)) {
  +    ValueImp *v;
  +    if (m_oper == OpEqual) {
  +      v = m_right->evaluate(exec);
  +    } else {
  +      PropertySlot slot;
  +      base->getPropertySlot(exec, propertyIndex, slot);    
  +      ValueImp *v1 = slot.isSet() ? slot.getValue(exec, propertyIndex) : Undefined();
  +      KJS_CHECKEXCEPTIONVALUE
  +      ValueImp *v2 = m_right->evaluate(exec);
  +      v = valueForReadModifyAssignment(exec, v1, v2, m_oper);
       }
  -  };
  -  l.putValue(exec,v);
  +
  +    KJS_CHECKEXCEPTIONVALUE
  +
  +    base->put(exec, propertyIndex, v);
  +    return v;
  +  }
  +
  +  Identifier propertyName(subscript->toString(exec));
  +  ValueImp *v;
  +
  +  if (m_oper == OpEqual) {
  +    v = m_right->evaluate(exec);
  +  } else {
  +    PropertySlot slot;
  +    base->getPropertySlot(exec, propertyName, slot);    
  +    ValueImp *v1 = slot.isSet() ? slot.getValue(exec, propertyName) : Undefined();
  +    KJS_CHECKEXCEPTIONVALUE
  +    ValueImp *v2 = m_right->evaluate(exec);
  +    v = valueForReadModifyAssignment(exec, v1, v2, m_oper);
  +  }
   
     KJS_CHECKEXCEPTIONVALUE
   
  +  base->put(exec, propertyName, v);
     return v;
   }
   
  
  
  
  1.25      +42 -11    JavaScriptCore/kjs/nodes.h
  
  Index: nodes.h
  ===================================================================
  RCS file: /cvs/root/JavaScriptCore/kjs/nodes.h,v
  retrieving revision 1.24
  retrieving revision 1.25
  diff -u -r1.24 -r1.25
  --- nodes.h	8 Aug 2005 04:07:28 -0000	1.24
  +++ nodes.h	11 Aug 2005 10:26:53 -0000	1.25
  @@ -210,7 +210,7 @@
       virtual bool deref();
       virtual ValueImp *evaluate(ExecState *exec);
       virtual Reference evaluateReference(ExecState *exec);
  -    virtual void streamTo(SourceStream &s) const { group->streamTo(s); }
  +    virtual void streamTo(SourceStream &s) const;
     private:
       Node *group;
     };
  @@ -290,9 +290,9 @@
       Identifier str;
     };
   
  -  class AccessorNode1 : public Node {
  +  class BracketAccessorNode : public Node {
     public:
  -    AccessorNode1(Node *e1, Node *e2) : expr1(e1), expr2(e2) {}
  +    BracketAccessorNode(Node *e1, Node *e2) : expr1(e1), expr2(e2) {}
       virtual void ref();
       virtual bool deref();
       ValueImp *evaluate(ExecState *exec);
  @@ -303,9 +303,9 @@
       Node *expr2;
     };
   
  -  class AccessorNode2 : public Node {
  +  class DotAccessorNode : public Node {
     public:
  -    AccessorNode2(Node *e, const Identifier &s) : expr(e), ident(s) { }
  +    DotAccessorNode(Node *e, const Identifier &s) : expr(e), ident(s) { }
       virtual void ref();
       virtual bool deref();
       ValueImp *evaluate(ExecState *exec);
  @@ -580,17 +580,48 @@
       Node *logical, *expr1, *expr2;
     };
   
  -  class AssignNode : public Node {
  +  class AssignResolveNode : public Node {
     public:
  -    AssignNode(Node *l, Operator o, Node *e) : left(l), oper(o), expr(e) {}
  +    AssignResolveNode(const Identifier &ident, Operator oper, Node *right) 
  +      : m_ident(ident), m_oper(oper), m_right(right) {}
       virtual void ref();
       virtual bool deref();
       ValueImp *evaluate(ExecState *exec);
       virtual void streamTo(SourceStream &s) const;
  -  private:
  -    Node *left;
  -    Operator oper;
  -    Node *expr;
  +  protected:
  +    Identifier m_ident;
  +    Operator m_oper;
  +    Node *m_right;
  +  };
  +
  +  class AssignBracketNode : public Node {
  +  public:
  +    AssignBracketNode(Node *base, Node *subscript, Operator oper, Node *right) 
  +      : m_base(base), m_subscript(subscript), m_oper(oper), m_right(right) {}
  +    virtual void ref();
  +    virtual bool deref();
  +    ValueImp *evaluate(ExecState *exec);
  +    virtual void streamTo(SourceStream &s) const;
  +  protected:
  +    Node *m_base;
  +    Node *m_subscript;
  +    Operator m_oper;
  +    Node *m_right;
  +  };
  +
  +  class AssignDotNode : public Node {
  +  public:
  +    AssignDotNode(Node *base, const Identifier& ident, Operator oper, Node *right)
  +      : m_base(base), m_ident(ident), m_oper(oper), m_right(right) {}
  +    virtual void ref();
  +    virtual bool deref();
  +    ValueImp *evaluate(ExecState *exec);
  +    virtual void streamTo(SourceStream &s) const;
  +  protected:
  +    Node *m_base;
  +    Identifier m_ident;
  +    Operator m_oper;
  +    Node *m_right;
     };
   
     class CommaNode : public Node {
  
  
  
  1.12      +31 -6     JavaScriptCore/kjs/nodes2string.cpp
  
  Index: nodes2string.cpp
  ===================================================================
  RCS file: /cvs/root/JavaScriptCore/kjs/nodes2string.cpp,v
  retrieving revision 1.11
  retrieving revision 1.12
  diff -u -r1.11 -r1.12
  --- nodes2string.cpp	14 Jul 2005 18:27:03 -0000	1.11
  +++ nodes2string.cpp	11 Aug 2005 10:26:53 -0000	1.12
  @@ -124,6 +124,11 @@
   
   void ResolveNode::streamTo(SourceStream &s) const { s << ident; }
   
  +void GroupNode::streamTo(SourceStream &s) const
  +{
  +  s << "(" << group << ")"; 
  +}
  +
   void ElementNode::streamTo(SourceStream &s) const
   {
     for (const ElementNode *n = this; n; n = n->list) {
  @@ -163,12 +168,12 @@
       s << str;
   }
   
  -void AccessorNode1::streamTo(SourceStream &s) const
  +void BracketAccessorNode::streamTo(SourceStream &s) const
   {
     s << expr1 << "[" << expr2 << "]";
   }
   
  -void AccessorNode2::streamTo(SourceStream &s) const
  +void DotAccessorNode::streamTo(SourceStream &s) const
   {
     s << expr << "." << ident;
   }
  @@ -338,9 +343,8 @@
     s << logical << " ? " << expr1 << " : " << expr2;
   }
   
  -void AssignNode::streamTo(SourceStream &s) const
  +void streamAssignmentOperatorTo(SourceStream &s, Operator oper)
   {
  -  s << left;
     const char *opStr;
     switch (oper) {
     case OpEqual:
  @@ -365,7 +369,7 @@
       opStr = " >>= ";
       break;
     case OpURShift:
  -    opStr = " >>= ";
  +    opStr = " >>>= ";
       break;
     case OpAndEq:
       opStr = " &= ";
  @@ -382,7 +386,28 @@
     default:
       opStr = " ?= ";
     }
  -  s << opStr << expr;
  +  s << opStr;
  +}
  +
  +void AssignResolveNode::streamTo(SourceStream &s) const
  +{
  +  s << m_ident;
  +  streamAssignmentOperatorTo(s, m_oper);
  +  s << m_right;
  +}
  +
  +void AssignBracketNode::streamTo(SourceStream &s) const
  +{
  +  s << m_base << "[" << m_subscript << "]";
  +  streamAssignmentOperatorTo(s, m_oper);
  +  s << m_right;
  +}
  +
  +void AssignDotNode::streamTo(SourceStream &s) const
  +{
  +  s << m_base << "." << m_ident;
  +  streamAssignmentOperatorTo(s, m_oper);
  +  s << m_right;
   }
   
   void CommaNode::streamTo(SourceStream &s) const
  
  
  
  1.3       +2 -1      JavaScriptCore/kjs/property_slot.h
  
  Index: property_slot.h
  ===================================================================
  RCS file: /cvs/root/JavaScriptCore/kjs/property_slot.h,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- property_slot.h	8 Aug 2005 04:07:29 -0000	1.2
  +++ property_slot.h	11 Aug 2005 10:26:53 -0000	1.3
  @@ -38,7 +38,8 @@
   public:
       typedef ValueImp *(*GetValueFunc)(ExecState *, const Identifier&, const PropertySlot&);
   
  -    bool isSet() { return m_getValue != 0; }
  +    bool isSet() const { return m_getValue != 0; }
  +
       ValueImp *getValue(ExecState *exec, const Identifier& propertyName) const
       { 
           if (m_getValue == VALUE_SLOT_MARKER)
  
  
  
  1.4559    +12 -0     WebCore/ChangeLog
  
  Index: ChangeLog
  ===================================================================
  RCS file: /cvs/root/WebCore/ChangeLog,v
  retrieving revision 1.4558
  retrieving revision 1.4559
  diff -u -r1.4558 -r1.4559
  --- ChangeLog	11 Aug 2005 09:39:43 -0000	1.4558
  +++ ChangeLog	11 Aug 2005 10:26:54 -0000	1.4559
  @@ -1,3 +1,15 @@
  +2005-08-10  Maciej Stachowiak  <mjs at apple.com>
  +
  +        Reviewed by Geoff.
  +
  +        Test cases added:
  +
  +        * layout-tests/fast/js/assign.html: Added. Test case for assignment to make sure
  +	I didn't break anything.
  +        * layout-tests/fast/js/code-serialize-paren.html: Added, test case for a minor bug
  +	I fixed where parens were not getting serialized at all when turning a function
  +	into a string.
  +
   2005-08-11  Maciej Stachowiak  <mjs at apple.com>
   
           At Least Rougly Glanced At by Anders.
  
  
  



More information about the webkit-changes mailing list