Commit 0e892e0e authored by andersca's avatar andersca

2005-12-12 Anders Carlsson <andersca@mac.com>

        Reviewed by Darin.

        - Fixes <http://bugzilla.opendarwin.org/show_bug.cgi?id=6041>

        * bindings/runtime_array.cpp:
        (RuntimeArray::lengthGetter):
        (RuntimeArray::indexGetter):
        * bindings/runtime_array.h:
        * bindings/runtime_method.cpp:
        (RuntimeMethod::lengthGetter):
        * bindings/runtime_method.h:
        * bindings/runtime_object.cpp:
        (RuntimeObjectImp::fallbackObjectGetter):
        (RuntimeObjectImp::fieldGetter):
        (RuntimeObjectImp::methodGetter):
        * bindings/runtime_object.h:
        * kjs/array_instance.h:
        * kjs/array_object.cpp:
        (ArrayInstance::lengthGetter):
        (getProperty):
        Update for changes to PropertySlot::getValue and
        PropertySlot::GetValueFunc.

        * kjs/collector.cpp:
        (KJS::className):
        Handle GetterSetterType.

        * kjs/function.cpp:
        (KJS::FunctionImp::argumentsGetter):
        (KJS::FunctionImp::lengthGetter):
        (KJS::Arguments::mappedIndexGetter):
        (KJS::ActivationImp::argumentsGetter):
        * kjs/function.h:
        Update for changes to PropertySlot::getValue and
        PropertySlot::GetValueFunc.

        * kjs/grammar.y:
        Rework grammar parts for get set declarations directly
        in the object literal.

        * kjs/internal.cpp:
        (KJS::GetterSetterImp::mark):
        (KJS::GetterSetterImp::toPrimitive):
        (KJS::GetterSetterImp::toBoolean):
        (KJS::GetterSetterImp::toNumber):
        (KJS::GetterSetterImp::toString):
        (KJS::GetterSetterImp::toObject):
        Add type conversion functions. These aren't meant to be called.

        (KJS::printInfo):
        Handle GetterSetterType.

        * kjs/lookup.h:
        (KJS::staticFunctionGetter):
        (KJS::staticValueGetter):
        Update for changes to PropertySlot::GetValueFunc.

        * kjs/nodes.cpp:
        Refactor they way properties nodes are implemented.
        We now have a PropertyListNode which is a list of PropertyNodes.
        Each PropertyNode has a name (which is a PropertyNameNode) and an associated
        value node. PropertyNodes can be of different types. The Constant type is the
        old constant declaration and the Getter and Setter types are for property getters
        and setters.
        (ResolveNode::evaluate):
        Update for changes to PropertySlot::getValue.

        (PropertyListNode::evaluate):
        Go through all property nodes and set them on the newly created object. If the
        property nodes are of type Getter or Setter, define getters and setters. Otherwise,
        just add the properties like before.

        (PropertyNode::evaluate):
        This should never be called directly.

        (PropertyNameNode::evaluate):
        Rename from PropertyNode::evaluate.

        (FunctionCallResolveNode::evaluate):
        (FunctionCallBracketNode::evaluate):
        (FunctionCallDotNode::evaluate):
        (PostfixResolveNode::evaluate):
        (PostfixBracketNode::evaluate):
        (PostfixDotNode::evaluate):
        (TypeOfResolveNode::evaluate):
        (PrefixResolveNode::evaluate):
        (PrefixBracketNode::evaluate):
        (PrefixDotNode::evaluate):
        (AssignResolveNode::evaluate):
        (AssignDotNode::evaluate):
        (AssignBracketNode::evaluate):
        Update for changes to PropertySlot::getValue.

        * kjs/nodes.h:
        (KJS::PropertyNameNode::PropertyNameNode):
        Rename from PropertyNode.

        (KJS::PropertyNode::):
        (KJS::PropertyNode::PropertyNode):
        New class, representing a single property.

        (KJS::PropertyListNode::PropertyListNode):
        Rename from PropertyValueNode.

        (KJS::FuncExprNode::FuncExprNode):
        Put ParameterNode parameter last, and make it optional.

        (KJS::ObjectLiteralNode::ObjectLiteralNode):
        Use a PropertyListNode here now.

        * kjs/nodes2string.cpp:
        (PropertyListNode::streamTo):
        Iterate through all property nodes.

        (PropertyNode::streamTo):
        Print out the name and value. Doesn't handle getters and setters currently.

        (PropertyNameNode::streamTo):
        Rename from PropertyNode::streamTo.

        * kjs/object.cpp:
        (KJS::JSObject::get):
        Update for changes to PropertySlot::getValue.

        (KJS::JSObject::put):
        If the property already exists and has a Setter, invoke
        the setter function instead of setting the property directly.

        (KJS::JSObject::defineGetter):
        (KJS::JSObject::defineSetter):
        New functions for defining property getters and setters on the object.

        * kjs/object.h:
        (KJS::GetterSetterImp::type):
        (KJS::GetterSetterImp::GetterSetterImp):
        (KJS::GetterSetterImp::getGetter):
        (KJS::GetterSetterImp::setGetter):
        (KJS::GetterSetterImp::getSetter):
        (KJS::GetterSetterImp::setSetter):
        New class for properties which have getters and setters defined.
        This class is only used internally and should never be seen from the outside.

        (KJS::JSObject::getOwnPropertySlot):
         If the property is a getter, call setGetterSlot on the property slot.

        * kjs/object_object.cpp:
        (ObjectPrototype::ObjectPrototype):
        Add __defineGetter__, __defineSetter, __lookupGetter__, __lookupSetter__
        to prototype.

        (ObjectProtoFunc::callAsFunction):
        Implement handlers for new functions.

        * kjs/object_object.h:
        (KJS::ObjectProtoFunc::):
        Add ids for new functions.

        * kjs/property_slot.cpp:
        (KJS::PropertySlot::undefinedGetter):
        Update for changes to PropertySlot::GetValueFunc.

        (KJS::PropertySlot::functionGetter):
        Call the function getter object and return its value.

        * kjs/property_slot.h:
        (KJS::PropertySlot::getValue):
        Add a new argument which is the original object that
        getPropertySlot was called on.

        (KJS::PropertySlot::setGetterSlot):
        (KJS::PropertySlot::):
        New function which sets a getter slot. When getValue is called on a
        getter slot, the getter function object is invoked.

        * kjs/string_object.cpp:
        (StringInstance::lengthGetter):
        (StringInstance::indexGetter):
        * kjs/string_object.h:
        Update for changes to PropertySlot::GetValueFunc.

        * kjs/value.h:
        (KJS::):
        Add GetterSetterType and make GetterSetterImp a friend class of JSCell.


git-svn-id: http://svn.webkit.org/repository/webkit/trunk@11566 268f45cc-cd09-0410-ab3c-d52691b4dbfc
parent bd2cbf7d
2005-12-12 Anders Carlsson <andersca@mac.com>
Reviewed by Darin.
- Fixes <http://bugzilla.opendarwin.org/show_bug.cgi?id=6041>
* bindings/runtime_array.cpp:
(RuntimeArray::lengthGetter):
(RuntimeArray::indexGetter):
* bindings/runtime_array.h:
* bindings/runtime_method.cpp:
(RuntimeMethod::lengthGetter):
* bindings/runtime_method.h:
* bindings/runtime_object.cpp:
(RuntimeObjectImp::fallbackObjectGetter):
(RuntimeObjectImp::fieldGetter):
(RuntimeObjectImp::methodGetter):
* bindings/runtime_object.h:
* kjs/array_instance.h:
* kjs/array_object.cpp:
(ArrayInstance::lengthGetter):
(getProperty):
Update for changes to PropertySlot::getValue and
PropertySlot::GetValueFunc.
* kjs/collector.cpp:
(KJS::className):
Handle GetterSetterType.
* kjs/function.cpp:
(KJS::FunctionImp::argumentsGetter):
(KJS::FunctionImp::lengthGetter):
(KJS::Arguments::mappedIndexGetter):
(KJS::ActivationImp::argumentsGetter):
* kjs/function.h:
Update for changes to PropertySlot::getValue and
PropertySlot::GetValueFunc.
* kjs/grammar.y:
Rework grammar parts for get set declarations directly
in the object literal.
* kjs/internal.cpp:
(KJS::GetterSetterImp::mark):
(KJS::GetterSetterImp::toPrimitive):
(KJS::GetterSetterImp::toBoolean):
(KJS::GetterSetterImp::toNumber):
(KJS::GetterSetterImp::toString):
(KJS::GetterSetterImp::toObject):
Add type conversion functions. These aren't meant to be called.
(KJS::printInfo):
Handle GetterSetterType.
* kjs/lookup.h:
(KJS::staticFunctionGetter):
(KJS::staticValueGetter):
Update for changes to PropertySlot::GetValueFunc.
* kjs/nodes.cpp:
Refactor they way properties nodes are implemented.
We now have a PropertyListNode which is a list of PropertyNodes.
Each PropertyNode has a name (which is a PropertyNameNode) and an associated
value node. PropertyNodes can be of different types. The Constant type is the
old constant declaration and the Getter and Setter types are for property getters
and setters.
(ResolveNode::evaluate):
Update for changes to PropertySlot::getValue.
(PropertyListNode::evaluate):
Go through all property nodes and set them on the newly created object. If the
property nodes are of type Getter or Setter, define getters and setters. Otherwise,
just add the properties like before.
(PropertyNode::evaluate):
This should never be called directly.
(PropertyNameNode::evaluate):
Rename from PropertyNode::evaluate.
(FunctionCallResolveNode::evaluate):
(FunctionCallBracketNode::evaluate):
(FunctionCallDotNode::evaluate):
(PostfixResolveNode::evaluate):
(PostfixBracketNode::evaluate):
(PostfixDotNode::evaluate):
(TypeOfResolveNode::evaluate):
(PrefixResolveNode::evaluate):
(PrefixBracketNode::evaluate):
(PrefixDotNode::evaluate):
(AssignResolveNode::evaluate):
(AssignDotNode::evaluate):
(AssignBracketNode::evaluate):
Update for changes to PropertySlot::getValue.
* kjs/nodes.h:
(KJS::PropertyNameNode::PropertyNameNode):
Rename from PropertyNode.
(KJS::PropertyNode::):
(KJS::PropertyNode::PropertyNode):
New class, representing a single property.
(KJS::PropertyListNode::PropertyListNode):
Rename from PropertyValueNode.
(KJS::FuncExprNode::FuncExprNode):
Put ParameterNode parameter last, and make it optional.
(KJS::ObjectLiteralNode::ObjectLiteralNode):
Use a PropertyListNode here now.
* kjs/nodes2string.cpp:
(PropertyListNode::streamTo):
Iterate through all property nodes.
(PropertyNode::streamTo):
Print out the name and value. Doesn't handle getters and setters currently.
(PropertyNameNode::streamTo):
Rename from PropertyNode::streamTo.
* kjs/object.cpp:
(KJS::JSObject::get):
Update for changes to PropertySlot::getValue.
(KJS::JSObject::put):
If the property already exists and has a Setter, invoke
the setter function instead of setting the property directly.
(KJS::JSObject::defineGetter):
(KJS::JSObject::defineSetter):
New functions for defining property getters and setters on the object.
* kjs/object.h:
(KJS::GetterSetterImp::type):
(KJS::GetterSetterImp::GetterSetterImp):
(KJS::GetterSetterImp::getGetter):
(KJS::GetterSetterImp::setGetter):
(KJS::GetterSetterImp::getSetter):
(KJS::GetterSetterImp::setSetter):
New class for properties which have getters and setters defined.
This class is only used internally and should never be seen from the outside.
(KJS::JSObject::getOwnPropertySlot):
If the property is a getter, call setGetterSlot on the property slot.
* kjs/object_object.cpp:
(ObjectPrototype::ObjectPrototype):
Add __defineGetter__, __defineSetter, __lookupGetter__, __lookupSetter__
to prototype.
(ObjectProtoFunc::callAsFunction):
Implement handlers for new functions.
* kjs/object_object.h:
(KJS::ObjectProtoFunc::):
Add ids for new functions.
* kjs/property_slot.cpp:
(KJS::PropertySlot::undefinedGetter):
Update for changes to PropertySlot::GetValueFunc.
(KJS::PropertySlot::functionGetter):
Call the function getter object and return its value.
* kjs/property_slot.h:
(KJS::PropertySlot::getValue):
Add a new argument which is the original object that
getPropertySlot was called on.
(KJS::PropertySlot::setGetterSlot):
(KJS::PropertySlot::):
New function which sets a getter slot. When getValue is called on a
getter slot, the getter function object is invoked.
* kjs/string_object.cpp:
(StringInstance::lengthGetter):
(StringInstance::indexGetter):
* kjs/string_object.h:
Update for changes to PropertySlot::GetValueFunc.
* kjs/value.h:
(KJS::):
Add GetterSetterType and make GetterSetterImp a friend class of JSCell.
2005-12-12 Maciej Stachowiak <mjs@apple.com>
Reviewed by Eric.
......
......@@ -44,13 +44,13 @@ RuntimeArray::~RuntimeArray()
delete _array;
}
JSValue *RuntimeArray::lengthGetter(ExecState *exec, const Identifier& propertyName, const PropertySlot& slot)
JSValue *RuntimeArray::lengthGetter(ExecState *exec, JSObject *originalObject, const Identifier& propertyName, const PropertySlot& slot)
{
RuntimeArray *thisObj = static_cast<RuntimeArray *>(slot.slotBase());
return jsNumber(thisObj->getLength());
}
JSValue *RuntimeArray::indexGetter(ExecState *exec, const Identifier& propertyName, const PropertySlot& slot)
JSValue *RuntimeArray::indexGetter(ExecState *exec, JSObject *originalObject, const Identifier& propertyName, const PropertySlot& slot)
{
RuntimeArray *thisObj = static_cast<RuntimeArray *>(slot.slotBase());
return thisObj->getConcreteArray()->valueAt(exec, slot.index());
......
......@@ -54,8 +54,8 @@ public:
static const ClassInfo info;
private:
static JSValue *lengthGetter(ExecState *, const Identifier&, const PropertySlot&);
static JSValue *indexGetter(ExecState *, const Identifier&, const PropertySlot&);
static JSValue *lengthGetter(ExecState *, JSObject *, const Identifier&, const PropertySlot&);
static JSValue *indexGetter(ExecState *, JSObject *, const Identifier&, const PropertySlot&);
Bindings::Array *_array;
};
......
......@@ -41,7 +41,7 @@ RuntimeMethod::~RuntimeMethod()
{
}
JSValue *RuntimeMethod::lengthGetter(ExecState *exec, const Identifier& propertyName, const PropertySlot& slot)
JSValue *RuntimeMethod::lengthGetter(ExecState *exec, JSObject *originalObject, const Identifier& propertyName, const PropertySlot& slot)
{
RuntimeMethod *thisObj = static_cast<RuntimeMethod *>(slot.slotBase());
......
......@@ -48,7 +48,7 @@ public:
virtual Completion execute(ExecState *exec);
private:
static JSValue *lengthGetter(ExecState *, const Identifier&, const PropertySlot&);
static JSValue *lengthGetter(ExecState *, JSObject *, const Identifier&, const PropertySlot&);
Bindings::MethodList _methodList;
};
......
......@@ -61,7 +61,7 @@ RuntimeObjectImp::RuntimeObjectImp(Bindings::Instance *i, bool oi)
instance = i;
}
JSValue *RuntimeObjectImp::fallbackObjectGetter(ExecState *exec, const Identifier& propertyName, const PropertySlot& slot)
JSValue *RuntimeObjectImp::fallbackObjectGetter(ExecState *exec, JSObject *originalObject, const Identifier& propertyName, const PropertySlot& slot)
{
RuntimeObjectImp *thisObj = static_cast<RuntimeObjectImp *>(slot.slotBase());
Bindings::Instance *instance = thisObj->instance;
......@@ -76,7 +76,7 @@ JSValue *RuntimeObjectImp::fallbackObjectGetter(ExecState *exec, const Identifie
return result;
}
JSValue *RuntimeObjectImp::fieldGetter(ExecState *exec, const Identifier& propertyName, const PropertySlot& slot)
JSValue *RuntimeObjectImp::fieldGetter(ExecState *exec, JSObject *originalObject, const Identifier& propertyName, const PropertySlot& slot)
{
RuntimeObjectImp *thisObj = static_cast<RuntimeObjectImp *>(slot.slotBase());
Bindings::Instance *instance = thisObj->instance;
......@@ -92,7 +92,7 @@ JSValue *RuntimeObjectImp::fieldGetter(ExecState *exec, const Identifier& proper
return result;
}
JSValue *RuntimeObjectImp::methodGetter(ExecState *exec, const Identifier& propertyName, const PropertySlot& slot)
JSValue *RuntimeObjectImp::methodGetter(ExecState *exec, JSObject *originalObject, const Identifier& propertyName, const PropertySlot& slot)
{
RuntimeObjectImp *thisObj = static_cast<RuntimeObjectImp *>(slot.slotBase());
Bindings::Instance *instance = thisObj->instance;
......
......@@ -53,9 +53,9 @@ public:
static const ClassInfo info;
private:
static JSValue *fallbackObjectGetter(ExecState *, const Identifier&, const PropertySlot&);
static JSValue *fieldGetter(ExecState *, const Identifier&, const PropertySlot&);
static JSValue *methodGetter(ExecState *, const Identifier&, const PropertySlot&);
static JSValue *fallbackObjectGetter(ExecState *, JSObject *, const Identifier&, const PropertySlot&);
static JSValue *fieldGetter(ExecState *, JSObject *, const Identifier&, const PropertySlot&);
static JSValue *methodGetter(ExecState *, JSObject *, const Identifier&, const PropertySlot&);
Bindings::Instance *instance;
bool ownsInstance;
......
......@@ -52,7 +52,7 @@ namespace KJS {
void sort(ExecState *exec, JSObject *compareFunction);
private:
static JSValue *lengthGetter(ExecState *, const Identifier&, const PropertySlot&);
static JSValue *lengthGetter(ExecState *, JSObject *, const Identifier&, const PropertySlot&);
void setLength(unsigned newLength, ExecState *exec);
......
......@@ -74,7 +74,7 @@ ArrayInstance::~ArrayInstance()
fastFree(storage);
}
JSValue *ArrayInstance::lengthGetter(ExecState *exec, const Identifier& propertyName, const PropertySlot& slot)
JSValue *ArrayInstance::lengthGetter(ExecState *exec, JSObject *originalObject, const Identifier& propertyName, const PropertySlot& slot)
{
return jsNumber(static_cast<ArrayInstance *>(slot.slotBase())->length);
}
......@@ -428,7 +428,7 @@ static JSValue *getProperty(ExecState *exec, JSObject *obj, unsigned index)
PropertySlot slot;
if (!obj->getPropertySlot(exec, index, slot))
return NULL;
return slot.getValue(exec, index);
return slot.getValue(exec, obj, index);
}
// ECMA 15.4.4
......
......@@ -618,6 +618,9 @@ static const char *className(JSCell *val)
name = info ? info->className : "Object";
break;
}
case GetterSetterType:
name = "gettersetter";
break;
}
return name;
}
......
......@@ -206,7 +206,7 @@ void FunctionImp::processVarDecls(ExecState */*exec*/)
{
}
JSValue *FunctionImp::argumentsGetter(ExecState *exec, const Identifier& propertyName, const PropertySlot& slot)
JSValue *FunctionImp::argumentsGetter(ExecState *exec, JSObject *originalObject, const Identifier& propertyName, const PropertySlot& slot)
{
FunctionImp *thisObj = static_cast<FunctionImp *>(slot.slotBase());
ContextImp *context = exec->_context;
......@@ -219,7 +219,7 @@ JSValue *FunctionImp::argumentsGetter(ExecState *exec, const Identifier& propert
return jsNull();
}
JSValue *FunctionImp::lengthGetter(ExecState *exec, const Identifier& propertyName, const PropertySlot& slot)
JSValue *FunctionImp::lengthGetter(ExecState *exec, JSObject *originalObject, const Identifier& propertyName, const PropertySlot& slot)
{
FunctionImp *thisObj = static_cast<FunctionImp *>(slot.slotBase());
const Parameter *p = thisObj->param;
......@@ -442,7 +442,7 @@ void Arguments::mark()
_activationObject->mark();
}
JSValue *Arguments::mappedIndexGetter(ExecState *exec, const Identifier& propertyName, const PropertySlot& slot)
JSValue *Arguments::mappedIndexGetter(ExecState *exec, JSObject *originalObject, const Identifier& propertyName, const PropertySlot& slot)
{
Arguments *thisObj = static_cast<Arguments *>(slot.slotBase());
return thisObj->_activationObject->get(exec, thisObj->indexToNameMap[propertyName]);
......@@ -489,7 +489,7 @@ ActivationImp::ActivationImp(FunctionImp *function, const List &arguments)
// FIXME: Do we need to support enumerating the arguments property?
}
JSValue *ActivationImp::argumentsGetter(ExecState *exec, const Identifier& propertyName, const PropertySlot& slot)
JSValue *ActivationImp::argumentsGetter(ExecState *exec, JSObject *originalObject, const Identifier& propertyName, const PropertySlot& slot)
{
ActivationImp *thisObj = static_cast<ActivationImp *>(slot.slotBase());
......
......@@ -64,8 +64,8 @@ namespace KJS {
Identifier ident;
private:
static JSValue *argumentsGetter(ExecState *, const Identifier &, const PropertySlot&);
static JSValue *lengthGetter(ExecState *, const Identifier &, const PropertySlot&);
static JSValue *argumentsGetter(ExecState *, JSObject *, const Identifier &, const PropertySlot&);
static JSValue *lengthGetter(ExecState *, JSObject *, const Identifier &, const PropertySlot&);
void processParameters(ExecState *exec, const List &);
virtual void processVarDecls(ExecState *exec);
......@@ -115,7 +115,7 @@ namespace KJS {
virtual const ClassInfo *classInfo() const { return &info; }
static const ClassInfo info;
private:
static JSValue *mappedIndexGetter(ExecState *exec, const Identifier &, const PropertySlot& slot);
static JSValue *mappedIndexGetter(ExecState *exec, JSObject *, const Identifier &, const PropertySlot& slot);
ActivationImp *_activationObject;
mutable IndexToNameMap indexToNameMap;
......@@ -136,7 +136,7 @@ namespace KJS {
bool isActivation() { return true; }
private:
static PropertySlot::GetValueFunc getArgumentsGetter();
static JSValue *argumentsGetter(ExecState *exec, const Identifier &, const PropertySlot& slot);
static JSValue *argumentsGetter(ExecState *exec, JSObject *, const Identifier &, const PropertySlot& slot);
void createArgumentsObject(ExecState *exec) const;
FunctionImp *_function;
......
......@@ -54,6 +54,7 @@ using namespace KJS;
static bool makeAssignNode(Node*& result, Node *loc, Operator op, Node *expr);
static bool makePrefixNode(Node*& result, Node *expr, Operator op);
static bool makePostfixNode(Node*& result, Node *expr, Operator op);
static bool makeGetterOrSetterPropertyNode(PropertyNode*& result, Identifier &getOrSet, Identifier& name, ParameterNode *params, FunctionBodyNode *body);
static Node *makeFunctionCallNode(Node *func, ArgumentsNode *args);
static Node *makeTypeOfNode(Node *expr);
static Node *makeDeleteNode(Node *expr);
......@@ -84,8 +85,9 @@ static Node *makeDeleteNode(Node *expr);
CaseClauseNode *ccl;
ElementNode *elm;
Operator op;
PropertyValueNode *plist;
PropertyNode *pnode;
PropertyListNode *plist;
PropertyNode *pnode;
PropertyNameNode *pname;
}
%start Program
......@@ -179,9 +181,9 @@ static Node *makeDeleteNode(Node *expr);
%type <clist> CaseClauses CaseClausesOpt
%type <ival> Elision ElisionOpt
%type <elm> ElementList
%type <plist> PropertyNameAndValueList
%type <pnode> PropertyName
%type <pname> PropertyName
%type <pnode> Property
%type <plist> PropertyList
%%
Literal:
......@@ -202,10 +204,28 @@ Literal:
}
;
PropertyName:
IDENT { $$ = new PropertyNameNode(*$1); }
| STRING { $$ = new PropertyNameNode(Identifier(*$1)); }
| NUMBER { $$ = new PropertyNameNode($1); }
;
Property:
PropertyName ':' AssignmentExpr { $$ = new PropertyNode($1, $3, PropertyNode::Constant); }
| IDENT IDENT '(' ')' FunctionBody { if (!makeGetterOrSetterPropertyNode($$, *$1, *$2, 0, $5)) YYABORT; }
| IDENT IDENT '(' FormalParameterList ')' FunctionBody
{ if (!makeGetterOrSetterPropertyNode($$, *$1, *$2, $4, $6)) YYABORT; }
;
PropertyList:
Property { $$ = new PropertyListNode($1); }
| PropertyList ',' Property { $$ = new PropertyListNode($3, $1); }
;
PrimaryExpr:
PrimaryExprNoBrace
| '{' '}' { $$ = new ObjectLiteralNode(); }
| '{' PropertyNameAndValueList '}' { $$ = new ObjectLiteralNode($2); }
| '{' PropertyList '}' { $$ = new ObjectLiteralNode($2); }
;
PrimaryExprNoBrace:
......@@ -238,18 +258,6 @@ Elision:
| Elision ',' { $$ = $1 + 1; }
;
PropertyNameAndValueList:
PropertyName ':' AssignmentExpr { $$ = new PropertyValueNode($1, $3); }
| PropertyNameAndValueList ',' PropertyName ':' AssignmentExpr
{ $$ = new PropertyValueNode($3, $5, $1); }
;
PropertyName:
IDENT { $$ = new PropertyNode(*$1); }
| STRING { $$ = new PropertyNode(Identifier(*$1)); }
| NUMBER { $$ = new PropertyNode($1); }
;
MemberExpr:
PrimaryExpr
| FunctionExpr { $$ = $1; }
......@@ -806,10 +814,10 @@ FunctionDeclaration:
FunctionExpr:
FUNCTION '(' ')' FunctionBody { $$ = new FuncExprNode(Identifier::null(), $4); }
| FUNCTION '(' FormalParameterList ')' FunctionBody
{ $$ = new FuncExprNode(Identifier::null(), $3, $5); }
{ $$ = new FuncExprNode(Identifier::null(), $5, $3); }
| FUNCTION IDENT '(' ')' FunctionBody { $$ = new FuncExprNode(*$2, $5); }
| FUNCTION IDENT '(' FormalParameterList ')' FunctionBody
{ $$ = new FuncExprNode(*$2, $4, $6); }
{ $$ = new FuncExprNode(*$2, $6, $4); }
;
FormalParameterList:
......@@ -960,6 +968,23 @@ static Node *makeDeleteNode(Node *expr)
}
}
static bool makeGetterOrSetterPropertyNode(PropertyNode*& result, Identifier& getOrSet, Identifier& name, ParameterNode *params, FunctionBodyNode *body)
{
PropertyNode::Type type;
if (getOrSet == "get")
type = PropertyNode::Getter;
else if (getOrSet == "set")
type = PropertyNode::Setter;
else
return false;
result = new PropertyNode(new PropertyNameNode(name),
new FuncExprNode(Identifier::null(), body, params), type);
return true;
}
int yyerror(const char * /* s */) /* Called by yyparse on error */
{
// fprintf(stderr, "ERROR: %s at line %d\n", s, KJS::Lexer::curr()->lineNo());
......
......@@ -223,6 +223,45 @@ bool NumberImp::getUInt32(uint32_t& uint32) const
return (double)uint32 == val;
}
// --------------------------- GetterSetterImp ---------------------------------
void GetterSetterImp::mark()
{
if (getter && !getter->marked())
getter->mark();
if (setter && !setter->marked())
setter->mark();
}
JSValue *GetterSetterImp::toPrimitive(ExecState *exec, Type type) const
{
assert(false);
return jsNull();
}
bool GetterSetterImp::toBoolean(ExecState *) const
{
assert(false);
return false;
}
double GetterSetterImp::toNumber(ExecState *) const
{
assert(false);
return 0.0;
}
UString GetterSetterImp::toString(ExecState *) const
{
assert(false);
return UString::null();
}
JSObject *GetterSetterImp::toObject(ExecState *exec) const
{
assert(false);
return jsNull()->toObject(exec);
}
// ------------------------------ LabelStack -----------------------------------
bool LabelStack::push(const Identifier &id)
......@@ -835,6 +874,9 @@ void printInfo(ExecState *exec, const char *s, JSValue *o, int lineno)
if (name.isNull())
name = "(unknown class)";
break;
case GetterSetterType:
name = "GetterSetter";
break;
}
UString vString = v->toString(exec);
if ( vString.size() > 50 )
......
......@@ -127,7 +127,7 @@ namespace KJS {
* Helper for getStaticFunctionSlot and getStaticPropertySlot
*/
template <class FuncImp>
inline JSValue *staticFunctionGetter(ExecState *exec, const Identifier& propertyName, const PropertySlot& slot)
inline JSValue *staticFunctionGetter(ExecState *exec, JSObject *originalObject, const Identifier& propertyName, const PropertySlot& slot)
{
// Look for cached value in dynamic map of properties (in JSObject)
JSObject *thisObj = slot.slotBase();
......@@ -146,7 +146,7 @@ namespace KJS {
* Helper for getStaticValueSlot and getStaticPropertySlot
*/
template <class ThisImp>
inline JSValue *staticValueGetter(ExecState *exec, const Identifier&, const PropertySlot& slot)
inline JSValue *staticValueGetter(ExecState *exec, JSObject *originalObject, const Identifier&, const PropertySlot& slot)
{
ThisImp *thisObj = static_cast<ThisImp *>(slot.slotBase());
const HashEntry *entry = slot.staticEntry();
......
......@@ -277,7 +277,7 @@ JSValue *ResolveNode::evaluate(ExecState *exec)
JSObject *o = *iter;
if (o->getPropertySlot(exec, ident, slot))
return slot.getValue(exec, ident);
return slot.getValue(exec, o, ident);
++iter;
} while (iter != end);
......@@ -353,29 +353,50 @@ JSValue *ObjectLiteralNode::evaluate(ExecState *exec)
return exec->lexicalInterpreter()->builtinObject()->construct(exec,List::empty());
}
// ------------------------------ PropertyValueNode ----------------------------
// ------------------------------ PropertyListNode -----------------------------
// ECMA 11.1.5
JSValue *PropertyValueNode::evaluate(ExecState *exec)
JSValue *PropertyListNode::evaluate(ExecState *exec)
{
JSObject *obj = exec->lexicalInterpreter()->builtinObject()->construct(exec, List::empty());
for (PropertyValueNode *p = this; p; p = p->list.get()) {
JSValue *n = p->name->evaluate(exec);
for (PropertyListNode *p = this; p; p = p->list.get()) {
JSValue *n = p->node->name->evaluate(exec);
KJS_CHECKEXCEPTIONVALUE
JSValue *v = p->assign->evaluate(exec);
JSValue *v = p->node->assign->evaluate(exec);
KJS_CHECKEXCEPTIONVALUE
obj->put(exec, Identifier(n->toString(exec)), v);
Identifier propertyName = Identifier(n->toString(exec));
switch (p->node->type) {
case PropertyNode::Getter:
assert(v->isObject());
obj->defineGetter(exec, propertyName, static_cast<JSObject *>(v));
break;
case PropertyNode::Setter:
assert(v->isObject());
obj->defineSetter(exec, propertyName, static_cast<JSObject *>(v));
break;
case PropertyNode::Constant:
obj->put(exec, propertyName, v);
break;
}
}
return obj;
}
// ------------------------------ PropertyNode ---------------------------------
// ------------------------------ PropertyNode -----------------------------
// ECMA 11.1.5
JSValue *PropertyNode::evaluate(ExecState *exec)
{
assert(false);