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: https://svn.webkit.org/repository/webkit/trunk@11566
268f45cc-cd09-0410-ab3c-
d52691b4dbfc
+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.
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());
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;
};
{
}
-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());
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;
};
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;
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;
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;
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;
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);
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);
}
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
name = info ? info->className : "Object";
break;
}
+ case GetterSetterType:
+ name = "gettersetter";
+ break;
}
return name;
}
{
}
-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;
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;
_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]);
// 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());
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);
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;
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;
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);
CaseClauseNode *ccl;
ElementNode *elm;
Operator op;
- PropertyValueNode *plist;
- PropertyNode *pnode;
+ PropertyListNode *plist;
+ PropertyNode *pnode;
+ PropertyNameNode *pname;
}
%start Program
%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:
}
;
+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:
| 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; }
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:
}
}
+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());
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)
if (name.isNull())
name = "(unknown class)";
break;
+ case GetterSetterType:
+ name = "GetterSetter";
+ break;
}
UString vString = v->toString(exec);
if ( vString.size() > 50 )
* 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();
* 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();
JSObject *o = *iter;
if (o->getPropertySlot(exec, ident, slot))
- return slot.getValue(exec, ident);
+ return slot.getValue(exec, o, ident);
++iter;
} while (iter != end);
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);
+ return jsNull();
+}
+
+// ---------------------------- PropertyNameNode -------------------------------
// ECMA 11.1.5
-JSValue *PropertyNode::evaluate(ExecState *)
+JSValue *PropertyNameNode::evaluate(ExecState *)
{
JSValue *s;
do {
base = *iter;
if (base->getPropertySlot(exec, ident, slot)) {
- JSValue *v = slot.getValue(exec, ident);
+ JSValue *v = slot.getValue(exec, base, ident);
KJS_CHECKEXCEPTIONVALUE
if (!v->isObject()) {
JSValue *funcVal;
if (subscriptVal->getUInt32(i)) {
if (baseObj->getPropertySlot(exec, i, slot))
- funcVal = slot.getValue(exec, i);
+ funcVal = slot.getValue(exec, baseObj, i);
else
funcVal = jsUndefined();
} else {
JSObject *baseObj = baseVal->toObject(exec);
PropertySlot slot;
- JSValue *funcVal = baseObj->getPropertySlot(exec, ident, slot) ? slot.getValue(exec, ident) : jsUndefined();
+ JSValue *funcVal = baseObj->getPropertySlot(exec, ident, slot) ? slot.getValue(exec, baseObj, ident) : jsUndefined();
KJS_CHECKEXCEPTIONVALUE
if (!funcVal->isObject())
do {
base = *iter;
if (base->getPropertySlot(exec, m_ident, slot)) {
- JSValue *v = slot.getValue(exec, m_ident);
+ JSValue *v = slot.getValue(exec, base, m_ident);
double n = v->toNumber(exec);
uint32_t propertyIndex;
if (subscript->getUInt32(propertyIndex)) {
PropertySlot slot;
- JSValue *v = base->getPropertySlot(exec, propertyIndex, slot) ? slot.getValue(exec, propertyIndex) : jsUndefined();
+ JSValue *v = base->getPropertySlot(exec, propertyIndex, slot) ? slot.getValue(exec, base, propertyIndex) : jsUndefined();
KJS_CHECKEXCEPTIONVALUE
double n = v->toNumber(exec);
Identifier propertyName(subscript->toString(exec));
PropertySlot slot;
- JSValue *v = base->getPropertySlot(exec, propertyName, slot) ? slot.getValue(exec, propertyName) : jsUndefined();
+ JSValue *v = base->getPropertySlot(exec, propertyName, slot) ? slot.getValue(exec, base, propertyName) : jsUndefined();
KJS_CHECKEXCEPTIONVALUE
double n = v->toNumber(exec);
JSObject *base = baseValue->toObject(exec);
PropertySlot slot;
- JSValue *v = base->getPropertySlot(exec, m_ident, slot) ? slot.getValue(exec, m_ident) : jsUndefined();
+ JSValue *v = base->getPropertySlot(exec, m_ident, slot) ? slot.getValue(exec, base, m_ident) : jsUndefined();
KJS_CHECKEXCEPTIONVALUE
double n = v->toNumber(exec);
do {
base = *iter;
if (base->getPropertySlot(exec, m_ident, slot)) {
- JSValue *v = slot.getValue(exec, m_ident);
+ JSValue *v = slot.getValue(exec, base, m_ident);
return typeStringForValue(v);
}
do {
base = *iter;
if (base->getPropertySlot(exec, m_ident, slot)) {
- JSValue *v = slot.getValue(exec, m_ident);
+ JSValue *v = slot.getValue(exec, base, m_ident);
double n = v->toNumber(exec);
uint32_t propertyIndex;
if (subscript->getUInt32(propertyIndex)) {
PropertySlot slot;
- JSValue *v = base->getPropertySlot(exec, propertyIndex, slot) ? slot.getValue(exec, propertyIndex) : jsUndefined();
+ JSValue *v = base->getPropertySlot(exec, propertyIndex, slot) ? slot.getValue(exec, base, propertyIndex) : jsUndefined();
KJS_CHECKEXCEPTIONVALUE
double n = v->toNumber(exec);
Identifier propertyName(subscript->toString(exec));
PropertySlot slot;
- JSValue *v = base->getPropertySlot(exec, propertyName, slot) ? slot.getValue(exec, propertyName) : jsUndefined();
+ JSValue *v = base->getPropertySlot(exec, propertyName, slot) ? slot.getValue(exec, base, propertyName) : jsUndefined();
KJS_CHECKEXCEPTIONVALUE
double n = v->toNumber(exec);
JSObject *base = baseValue->toObject(exec);
PropertySlot slot;
- JSValue *v = base->getPropertySlot(exec, m_ident, slot) ? slot.getValue(exec, m_ident) : jsUndefined();
+ JSValue *v = base->getPropertySlot(exec, m_ident, slot) ? slot.getValue(exec, base, m_ident) : jsUndefined();
KJS_CHECKEXCEPTIONVALUE
double n = v->toNumber(exec);
if (m_oper == OpEqual) {
v = m_right->evaluate(exec);
} else {
- JSValue *v1 = slot.getValue(exec, m_ident);
+ JSValue *v1 = slot.getValue(exec, base, m_ident);
KJS_CHECKEXCEPTIONVALUE
JSValue *v2 = m_right->evaluate(exec);
v = valueForReadModifyAssignment(exec, v1, v2, m_oper);
v = m_right->evaluate(exec);
} else {
PropertySlot slot;
- JSValue *v1 = base->getPropertySlot(exec, m_ident, slot) ? slot.getValue(exec, m_ident) : jsUndefined();
+ JSValue *v1 = base->getPropertySlot(exec, m_ident, slot) ? slot.getValue(exec, base, m_ident) : jsUndefined();
KJS_CHECKEXCEPTIONVALUE
JSValue *v2 = m_right->evaluate(exec);
v = valueForReadModifyAssignment(exec, v1, v2, m_oper);
v = m_right->evaluate(exec);
} else {
PropertySlot slot;
- JSValue *v1 = base->getPropertySlot(exec, propertyIndex, slot) ? slot.getValue(exec, propertyIndex) : jsUndefined();
+ JSValue *v1 = base->getPropertySlot(exec, propertyIndex, slot) ? slot.getValue(exec, base, propertyIndex) : jsUndefined();
KJS_CHECKEXCEPTIONVALUE
JSValue *v2 = m_right->evaluate(exec);
v = valueForReadModifyAssignment(exec, v1, v2, m_oper);
v = m_right->evaluate(exec);
} else {
PropertySlot slot;
- JSValue *v1 = base->getPropertySlot(exec, propertyName, slot) ? slot.getValue(exec, propertyName) : jsUndefined();
+ JSValue *v1 = base->getPropertySlot(exec, propertyName, slot) ? slot.getValue(exec, base, propertyName) : jsUndefined();
KJS_CHECKEXCEPTIONVALUE
JSValue *v2 = m_right->evaluate(exec);
v = valueForReadModifyAssignment(exec, v1, v2, m_oper);
namespace KJS {
class ProgramNode;
- class PropertyNode;
- class PropertyValueNode;
+ class PropertyNameNode;
+ class PropertyListNode;
class Reference;
class RegExp;
class SourceElementsNode;
bool opt;
};
- class PropertyValueNode : public Node {
+ class PropertyNameNode : public Node {
public:
- // list pointer is tail of a circular list, cracked in the ObjectLiteralNode ctor
- PropertyValueNode(PropertyNode *n, Node *a)
- : name(n), assign(a), list(this) { }
- PropertyValueNode(PropertyNode *n, Node *a, PropertyValueNode *l)
- : name(n), assign(a), list(l->list) { l->list = this; }
+ PropertyNameNode(double d) : numeric(d) { }
+ PropertyNameNode(const Identifier &s) : str(s) { }
JSValue *evaluate(ExecState *exec);
virtual void streamTo(SourceStream &s) const;
private:
- friend class ObjectLiteralNode;
- RefPtr<PropertyNode> name;
+ double numeric;
+ Identifier str;
+ };
+
+ class PropertyNode : public Node {
+ public:
+ enum Type { Constant, Getter, Setter };
+ PropertyNode(PropertyNameNode *n, Node *a, Type t)
+ : name(n), assign(a), type(t) { }
+ JSValue *evaluate(ExecState *exec);
+ virtual void streamTo(SourceStream &s) const;
+ friend class PropertyListNode;
+ private:
+ RefPtr<PropertyNameNode> name;
RefPtr<Node> assign;
- RefPtr<PropertyValueNode> list;
+ Type type;
};
-
- class ObjectLiteralNode : public Node {
+
+ class PropertyListNode : public Node {
public:
- ObjectLiteralNode() : list(0) { }
- ObjectLiteralNode(PropertyValueNode *l) : list(l->list) { l->list = 0; }
+ // list pointer is tail of a circular list, cracked in the ObjectLiteralNode ctor
+ PropertyListNode(PropertyNode *n)\v
+ : node(n), list(this) { }
+ PropertyListNode(PropertyNode *n, PropertyListNode *l)
+ : node(n), list(l->list) { l->list = this; }
JSValue *evaluate(ExecState *exec);
virtual void streamTo(SourceStream &s) const;
private:
- RefPtr<PropertyValueNode> list;
+ friend class ObjectLiteralNode;
+ RefPtr<PropertyNode> node;
+ RefPtr<PropertyListNode> list;
};
- class PropertyNode : public Node {
+ class ObjectLiteralNode : public Node {
public:
- PropertyNode(double d) : numeric(d) { }
- PropertyNode(const Identifier &s) : str(s) { }
+ ObjectLiteralNode() : list(0) { }
+ ObjectLiteralNode(PropertyListNode *l) : list(l->list) { l->list = 0; }
JSValue *evaluate(ExecState *exec);
virtual void streamTo(SourceStream &s) const;
private:
- double numeric;
- Identifier str;
+ RefPtr<PropertyListNode> list;
};
class BracketAccessorNode : public Node {
class FuncExprNode : public Node {
public:
- FuncExprNode(const Identifier &i, FunctionBodyNode *b)
- : ident(i), param(0), body(b) { }
- FuncExprNode(const Identifier &i, ParameterNode *p, FunctionBodyNode *b)
- : ident(i), param(p->next), body(b) { p->next = 0; }
+ FuncExprNode(const Identifier &i, FunctionBodyNode *b, ParameterNode *p = 0)
+ : ident(i), param(p ? p->next : 0), body(b) { if (p) p->next = 0; }
virtual JSValue *evaluate(ExecState *);
virtual void streamTo(SourceStream &) const;
private:
+ // Used for streamTo
+ friend class PropertyNode;
Identifier ident;
RefPtr<ParameterNode> param;
RefPtr<FunctionBodyNode> body;
s << "{ }";
}
-void PropertyValueNode::streamTo(SourceStream &s) const
+void PropertyListNode::streamTo(SourceStream &s) const
{
- for (const PropertyValueNode *n = this; n; n = n->list.get())
- s << n->name << ": " << n->assign;
+ s << node;
+
+ for (const PropertyListNode *n = list.get(); n; n = n->list.get())
+ s << ", " << n->node;
}
void PropertyNode::streamTo(SourceStream &s) const
+{
+ switch (type) {
+ case Constant:
+ s << name << ": " << assign;
+ break;
+ case Getter:
+ case Setter: {
+ const FuncExprNode *func = static_cast<const FuncExprNode *>(assign.get());
+ if (type == Getter)
+ s << "get ";
+ else
+ s << "set ";
+
+ s << name << "(" << func->param << ")" << func->body;
+ break;
+ }
+ }
+}
+
+void PropertyNameNode::streamTo(SourceStream &s) const
{
if (str.isNull())
s << UString::from(numeric);
PropertySlot slot;
if (const_cast<JSObject *>(this)->getPropertySlot(exec, propertyName, slot))
- return slot.getValue(exec, propertyName);
+ return slot.getValue(exec, const_cast<JSObject *>(this), propertyName);
return jsUndefined();
}
{
PropertySlot slot;
if (const_cast<JSObject *>(this)->getPropertySlot(exec, propertyName, slot))
- return slot.getValue(exec, propertyName);
+ return slot.getValue(exec, const_cast<JSObject *>(this), propertyName);
return jsUndefined();
}
return;
}
+ JSObject *obj = this;
+ while (true) {
+ if (JSValue *gs = obj->_prop.get(propertyName)) {
+ if (gs->type() == GetterSetterType) {
+ JSObject *setterFunc = static_cast<GetterSetterImp *>(gs)->getSetter();
+
+ if (!setterFunc) {
+ throwError(exec, TypeError, "setting a property that has only a getter");
+ return;
+ }
+
+ List args;
+ args.append(value);
+
+ setterFunc->call(exec, this, args);
+ return;
+ } else {
+ // If there's an existing property on the object or one of its
+ // prototype it should be replaced, so we just break here.
+ break;
+ }
+ }
+
+ if (!obj->_proto || !obj->_proto->isObject())
+ break;
+
+ obj = static_cast<JSObject *>(obj->_proto);
+ }
+
_prop.put(propertyName,value,attr);
}
return 0;
}
+void JSObject::defineGetter(ExecState *exec, const Identifier& propertyName, JSObject *getterFunc)
+{
+ JSValue *o = getDirect(propertyName);
+ GetterSetterImp *gs;
+
+ if (o && o->type() == GetterSetterType) {
+ gs = static_cast<GetterSetterImp *>(o);
+ } else {
+ gs = new GetterSetterImp;
+ putDirect(propertyName, gs);
+ }
+
+ gs->setGetter(getterFunc);
+}
+
+void JSObject::defineSetter(ExecState *exec, const Identifier& propertyName, JSObject *setterFunc)
+{
+ JSValue *o = getDirect(propertyName);
+ GetterSetterImp *gs;
+
+ if (o && o->type() == GetterSetterType) {
+ gs = static_cast<GetterSetterImp *>(o);
+ } else {
+ gs = new GetterSetterImp;
+ putDirect(propertyName, gs);
+ }
+
+ gs->setSetter(setterFunc);
+}
+
bool JSObject::implementsConstruct() const
{
return false;
void *dummy;
};
+ // This is an internal value object which stores getter and setter functions
+ // for a property.
+ class GetterSetterImp : public JSCell {
+ public:
+ Type type() const { return GetterSetterType; }
+
+ GetterSetterImp() : getter(0), setter(0) { }
+
+ virtual JSValue *toPrimitive(ExecState *exec, Type preferred = UnspecifiedType) const;
+ virtual bool toBoolean(ExecState *exec) const;
+ virtual double toNumber(ExecState *exec) const;
+ virtual UString toString(ExecState *exec) const;
+ virtual JSObject *toObject(ExecState *exec) const;
+
+ virtual void mark();
+
+ JSObject *getGetter() { return getter; }
+ void setGetter(JSObject *g) { getter = g; }
+ JSObject *getSetter() { return setter; }
+ void setSetter(JSObject *s) { setter = s; }
+
+ private:
+ JSObject *getter;
+ JSObject *setter;
+ };
+
class JSObject : public JSCell {
public:
/**
void putDirect(const Identifier &propertyName, JSValue *value, int attr = 0);
void putDirect(const Identifier &propertyName, int value, int attr = 0);
+ void defineGetter(ExecState *exec, const Identifier& propertyName, JSObject *getterFunc);
+ void defineSetter(ExecState *exec, const Identifier& propertyName, JSObject *setterFunc);
+
/**
* Remove all properties from this object.
* This doesn't take DontDelete into account, and isn't in the ECMA spec.
inline bool JSObject::getOwnPropertySlot(ExecState *exec, const Identifier& propertyName, PropertySlot& slot)
{
if (JSValue **location = getDirectLocation(propertyName)) {
- slot.setValueSlot(this, location);
+ if ((*location)->type() == GetterSetterType) {
+ GetterSetterImp *gs = static_cast<GetterSetterImp *>(*location);
+ JSObject *getterFunc = gs->getGetter();
+ if (getterFunc)
+ slot.setGetterSlot(this, getterFunc);
+ else
+ slot.setUndefined(this);
+ } else {
+ slot.setValueSlot(this, location);
+ }
return true;
}
putDirect(valueOfPropertyName, new ObjectProtoFunc(exec, funcProto, ObjectProtoFunc::ValueOf, 0), DontEnum);
putDirect("hasOwnProperty", new ObjectProtoFunc(exec, funcProto, ObjectProtoFunc::HasOwnProperty, 1), DontEnum);
putDirect("propertyIsEnumerable", new ObjectProtoFunc(exec, funcProto, ObjectProtoFunc::PropertyIsEnumerable, 1), DontEnum);
+ // Mozilla extensions
+ putDirect("__defineGetter__", new ObjectProtoFunc(exec, funcProto, ObjectProtoFunc::DefineGetter, 2), DontEnum);
+ putDirect("__defineSetter__", new ObjectProtoFunc(exec, funcProto, ObjectProtoFunc::DefineSetter, 2), DontEnum);
+ putDirect("__lookupGetter__", new ObjectProtoFunc(exec, funcProto, ObjectProtoFunc::LookupGetter, 1), DontEnum);
+ putDirect("__lookupSetter__", new ObjectProtoFunc(exec, funcProto, ObjectProtoFunc::LookupSetter, 1), DontEnum);
}
PropertySlot slot;
return jsBoolean(thisObj->getOwnPropertySlot(exec, Identifier(args[0]->toString(exec)), slot));
}
+ case DefineGetter:
+ case DefineSetter: {
+ if (!args[1]->isObject() ||
+ !static_cast<JSObject *>(args[1])->implementsCall()) {
+ if (id == DefineGetter)
+ return throwError(exec, SyntaxError, "invalid getter usage");
+ else
+ return throwError(exec, SyntaxError, "invalid setter usage");
+ }
+
+ if (id == DefineGetter)
+ thisObj->defineGetter(exec, Identifier(args[0]->toString(exec)), static_cast<JSObject *>(args[1]));
+ else
+ thisObj->defineSetter(exec, Identifier(args[0]->toString(exec)), static_cast<JSObject *>(args[1]));
+ return jsUndefined();
+ }
+ case LookupGetter:
+ case LookupSetter: {
+ Identifier propertyName = Identifier(args[0]->toString(exec));
+
+ JSObject *obj = thisObj;
+ while (true) {
+ JSValue *v = obj->getDirect(propertyName);
+
+ if (v) {
+ if (v->type() != GetterSetterType)
+ return jsUndefined();
+
+ JSObject *funcObj;
+
+ if (id == LookupGetter)
+ funcObj = static_cast<GetterSetterImp *>(v)->getGetter();
+ else
+ funcObj = static_cast<GetterSetterImp *>(v)->getSetter();
+
+ if (!funcObj)
+ return jsUndefined();
+ else
+ return funcObj;
+ }
+
+ if (!obj->prototype() || !obj->prototype()->isObject())
+ return jsUndefined();
+
+ obj = static_cast<JSObject *>(obj->prototype());
+ }
+ }
case PropertyIsEnumerable:
return jsBoolean(thisObj->propertyIsEnumerable(exec, Identifier(args[0]->toString(exec))));
case ToLocaleString:
virtual bool implementsCall() const;
virtual JSValue *callAsFunction(ExecState *, JSObject *, const List &args);
- enum { ToString, ToLocaleString, ValueOf, HasOwnProperty, PropertyIsEnumerable };
+ enum { ToString, ToLocaleString, ValueOf, HasOwnProperty, PropertyIsEnumerable,
+ DefineGetter, DefineSetter, LookupGetter, LookupSetter };
private:
int id;
};
#include "config.h"
#include "property_slot.h"
+#include "object.h"
namespace KJS {
-JSValue *PropertySlot::undefinedGetter(ExecState *, const Identifier& propertyName, const PropertySlot& slot)
+JSValue *PropertySlot::undefinedGetter(ExecState *, JSObject *, const Identifier& propertyName, const PropertySlot& slot)
{
return jsUndefined();
}
+JSValue *PropertySlot::functionGetter(ExecState *exec, JSObject *originalObject, const Identifier&, const PropertySlot& slot)
+{
+ return slot.m_data.getterFunc->call(exec, originalObject, List::empty());
+}
+
}
class PropertySlot
{
public:
- typedef JSValue *(*GetValueFunc)(ExecState *, const Identifier&, const PropertySlot&);
+ typedef JSValue *(*GetValueFunc)(ExecState *, JSObject *originalObject, const Identifier&, const PropertySlot&);
- JSValue *getValue(ExecState *exec, const Identifier& propertyName) const
+ JSValue *getValue(ExecState *exec, JSObject *originalObject, const Identifier& propertyName) const
{
if (m_getValue == VALUE_SLOT_MARKER)
return *m_data.valueSlot;
- return m_getValue(exec, propertyName, *this);
+ return m_getValue(exec, originalObject, propertyName, *this);
}
- JSValue *getValue(ExecState *exec, unsigned propertyName) const
+ JSValue *getValue(ExecState *exec, JSObject *originalObject, unsigned propertyName) const
{
if (m_getValue == VALUE_SLOT_MARKER)
return *m_data.valueSlot;
- return m_getValue(exec, Identifier::from(propertyName), *this);
+ return m_getValue(exec, originalObject, Identifier::from(propertyName), *this);
}
void setValueSlot(JSObject *slotBase, JSValue **valueSlot)
m_data.index = index;
m_getValue = getValue;
}
-
+
+ void setGetterSlot(JSObject *slotBase, JSObject *getterFunc)
+ {
+ m_getValue = functionGetter;
+ m_slotBase = slotBase;
+ m_data.getterFunc = getterFunc;
+ }
+
void setUndefined(JSObject *slotBase)
{
m_slotBase = slotBase;
unsigned index() const { return m_data.index; }
private:
- static JSValue *undefinedGetter(ExecState *, const Identifier&, const PropertySlot&);
-
+ static JSValue *undefinedGetter(ExecState *, JSObject *, const Identifier&, const PropertySlot&);
+ static JSValue *functionGetter(ExecState *, JSObject *, const Identifier&, const PropertySlot&);
+
GetValueFunc m_getValue;
JSObject *m_slotBase;
union {
+ JSObject *getterFunc;
JSValue **valueSlot;
const HashEntry *staticEntry;
unsigned index;
setInternalValue(jsString(string));
}
-JSValue *StringInstance::lengthGetter(ExecState *exec, const Identifier& propertyName, const PropertySlot &slot)
+JSValue *StringInstance::lengthGetter(ExecState *exec, JSObject *originalObject, const Identifier& propertyName, const PropertySlot &slot)
{
return jsNumber(static_cast<StringInstance *>(slot.slotBase())->internalValue()->toString(exec).size());
}
-JSValue *StringInstance::indexGetter(ExecState *exec, const Identifier& propertyName, const PropertySlot &slot)
+JSValue *StringInstance::indexGetter(ExecState *exec, JSObject *originalObject, const Identifier& propertyName, const PropertySlot &slot)
{
const UChar c = static_cast<StringInstance *>(slot.slotBase())->internalValue()->toString(exec)[slot.index()];
return jsString(UString(&c, 1));
virtual const ClassInfo *classInfo() const { return &info; }
static const ClassInfo info;
private:
- static JSValue *lengthGetter(ExecState *exec, const Identifier&, const PropertySlot &slot);
- static JSValue *indexGetter(ExecState *exec, const Identifier&, const PropertySlot &slot);
+ static JSValue *lengthGetter(ExecState *exec, JSObject *, const Identifier&, const PropertySlot &slot);
+ static JSValue *indexGetter(ExecState *exec, JSObject *, const Identifier&, const PropertySlot &slot);
};
/**
BooleanType = 3,
StringType = 4,
NumberType = 5,
- ObjectType = 6
+ ObjectType = 6,
+ GetterSetterType = 7
};
/**
friend class NumberImp;
friend class StringImp;
friend class JSObject;
+ friend class GetterSetterImp;
private:
JSCell();
virtual ~JSCell();