The following WebScripting methods are now supported on bound
objects:
- (id)invokeUndefinedMethodFromWebScript:(NSString *)name withArguments:(NSArray *)args;
- (void)setValue:(id)value forUndefinedKey:(NSString *)key
- (id)valueForUndefinedKey:(NSString *)key
Reviewed by Chris.
* bindings/c/c_class.cpp:
(CClass::fieldNamed):
* bindings/c/c_class.h:
* bindings/jni/jni_class.cpp:
(JavaClass::fieldNamed):
* bindings/jni/jni_class.h:
* bindings/objc/objc_class.h:
(KJS::Bindings::ObjcClass::isa):
* bindings/objc/objc_class.mm:
(ObjcClass::methodsNamed):
(ObjcClass::fieldNamed):
(ObjcClass::fallbackObject):
* bindings/objc/objc_instance.h:
* bindings/objc/objc_instance.mm:
(ObjcInstance::invokeMethod):
(ObjcInstance::setValueOfField):
(ObjcInstance::setValueOfUndefinedField):
(ObjcInstance::getValueOfField):
(ObjcInstance::getValueOfUndefinedField):
* bindings/objc/objc_runtime.h:
(KJS::Bindings::ObjcField::~ObjcField):
(KJS::Bindings::ObjcField::ObjcField):
(KJS::Bindings::ObjcField::operator=):
(KJS::Bindings::FallbackObjectImp::classInfo):
* bindings/objc/objc_runtime.mm:
(ObjcField::ObjcField):
(ObjcField::name):
(ObjcField::type):
(ObjcField::valueFromInstance):
(ObjcField::setValueToInstance):
(FallbackObjectImp::FallbackObjectImp):
(FallbackObjectImp::get):
(FallbackObjectImp::put):
(FallbackObjectImp::canPut):
(FallbackObjectImp::implementsCall):
(FallbackObjectImp::call):
(FallbackObjectImp::hasProperty):
(FallbackObjectImp::deleteProperty):
(FallbackObjectImp::defaultValue):
* bindings/runtime.h:
(KJS::Bindings::Class::fallbackObject):
(KJS::Bindings::Instance::getValueOfUndefinedField):
(KJS::Bindings::Instance::setValueOfUndefinedField):
* bindings/runtime_object.cpp:
(RuntimeObjectImp::get):
(RuntimeObjectImp::put):
(RuntimeObjectImp::canPut):
(RuntimeObjectImp::hasProperty):
* bindings/testbindings.mm:
(-[MyFirstInterface valueForUndefinedKey:]):
(-[MyFirstInterface setValue:forUndefinedKey:]):
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@7227
268f45cc-cd09-0410-ab3c-
d52691b4dbfc
+2004-08-10 Richard Williamson <rjw@apple.com>
+
+ Fixed <rdar://problem/3674747> Need to implement invokeUndefinedMethodFromWebScript:withArguments:
+
+ The following WebScripting methods are now supported on bound
+ objects:
+
+ - (id)invokeUndefinedMethodFromWebScript:(NSString *)name withArguments:(NSArray *)args;
+ - (void)setValue:(id)value forUndefinedKey:(NSString *)key
+ - (id)valueForUndefinedKey:(NSString *)key
+
+ Reviewed by Chris.
+
+ * bindings/c/c_class.cpp:
+ (CClass::fieldNamed):
+ * bindings/c/c_class.h:
+ * bindings/jni/jni_class.cpp:
+ (JavaClass::fieldNamed):
+ * bindings/jni/jni_class.h:
+ * bindings/objc/objc_class.h:
+ (KJS::Bindings::ObjcClass::isa):
+ * bindings/objc/objc_class.mm:
+ (ObjcClass::methodsNamed):
+ (ObjcClass::fieldNamed):
+ (ObjcClass::fallbackObject):
+ * bindings/objc/objc_instance.h:
+ * bindings/objc/objc_instance.mm:
+ (ObjcInstance::invokeMethod):
+ (ObjcInstance::setValueOfField):
+ (ObjcInstance::setValueOfUndefinedField):
+ (ObjcInstance::getValueOfField):
+ (ObjcInstance::getValueOfUndefinedField):
+ * bindings/objc/objc_runtime.h:
+ (KJS::Bindings::ObjcField::~ObjcField):
+ (KJS::Bindings::ObjcField::ObjcField):
+ (KJS::Bindings::ObjcField::operator=):
+ (KJS::Bindings::FallbackObjectImp::classInfo):
+ * bindings/objc/objc_runtime.mm:
+ (ObjcField::ObjcField):
+ (ObjcField::name):
+ (ObjcField::type):
+ (ObjcField::valueFromInstance):
+ (ObjcField::setValueToInstance):
+ (FallbackObjectImp::FallbackObjectImp):
+ (FallbackObjectImp::get):
+ (FallbackObjectImp::put):
+ (FallbackObjectImp::canPut):
+ (FallbackObjectImp::implementsCall):
+ (FallbackObjectImp::call):
+ (FallbackObjectImp::hasProperty):
+ (FallbackObjectImp::deleteProperty):
+ (FallbackObjectImp::defaultValue):
+ * bindings/runtime.h:
+ (KJS::Bindings::Class::fallbackObject):
+ (KJS::Bindings::Instance::getValueOfUndefinedField):
+ (KJS::Bindings::Instance::setValueOfUndefinedField):
+ * bindings/runtime_object.cpp:
+ (RuntimeObjectImp::get):
+ (RuntimeObjectImp::put):
+ (RuntimeObjectImp::canPut):
+ (RuntimeObjectImp::hasProperty):
+ * bindings/testbindings.mm:
+ (-[MyFirstInterface valueForUndefinedKey:]):
+ (-[MyFirstInterface setValue:forUndefinedKey:]):
+
2004-08-10 Darin Adler <darin@apple.com>
Reviewed by Dave.
}
-Field *CClass::fieldNamed(const char *name) const
+Field *CClass::fieldNamed(const char *name, Instance *instance) const
{
CFStringRef fieldName = CFStringCreateWithCString(NULL, name, kCFStringEncodingASCII);
Field *aField = (Field *)CFDictionaryGetValue (_fields, fieldName);
virtual MethodList methodsNamed(const char *name) const;
- virtual Field *fieldNamed(const char *name) const;
+ virtual Field *fieldNamed(const char *name, Instance *instance) const;
virtual Constructor *constructorAt(long i) const {
return 0;
}
-Field *JavaClass::fieldNamed(const char *name) const
+Field *JavaClass::fieldNamed(const char *name, Instance *instance) const
{
CFStringRef fieldName = CFStringCreateWithCString(NULL, name, kCFStringEncodingASCII);
Field *aField = (Field *)CFDictionaryGetValue(_fields, fieldName);
virtual MethodList methodsNamed(const char *name) const;
- virtual Field *fieldNamed(const char *name) const;
+ virtual Field *fieldNamed(const char *name, Instance *instance) const;
virtual Constructor *constructorAt(long i) const {
return &_constructors[i];
virtual MethodList methodsNamed(const char *name) const;
- virtual Field *fieldNamed(const char *name) const;
+ virtual Field *fieldNamed(const char *name, Instance *instance) const;
+
+ virtual Value fallbackObject(ExecState *exec, Instance *instance, const Identifier &propertyName);
virtual Constructor *constructorAt(long i) const {
return 0;
};
virtual long numConstructors() const { return 0; };
-
+
+ ClassStructPtr isa() { return _isa; }
+
private:
ClassStructPtr _isa;
CFDictionaryRef _methods;
#include <Foundation/Foundation.h>
#include <objc_class.h>
+#include <objc_instance.h>
+#include <objc_runtime.h>
#include <objc_utility.h>
#include <WebScriptObject.h>
}
thisClass = thisClass->super_class;
}
-
- if (methodList.length() == 0) {
- thisClass = _isa;
- if ([(id)thisClass instancesRespondToSelector:@selector(invokeUndefinedMethodFromWebScript:withArguments:)]){
- // Fallback methods are created for one-shot use. They are created here
- // and deleted in ObjcInstance::invokeMethod().
- ObjcMethod *fallbackMethod = new ObjcMethod (thisClass, (const char *)@selector(invokeUndefinedMethodFromWebScript:withArguments:));
- fallbackMethod->setJavaScriptName(methodName);
- methodList.addMethod ((Method *)fallbackMethod);
- }
- }
CFRelease (methodName);
}
-Field *ObjcClass::fieldNamed(const char *name) const
+Field *ObjcClass::fieldNamed(const char *name, Instance *instance) const
{
ClassStructPtr thisClass = _isa;
return aField;
}
- // FIX ME. See if the instance implement attributeKeys. Will need to
- // change fieldNamed() signature to take a Bindings::Instance.
- while (thisClass != 0) {
- struct objc_ivar_list *fieldsInClass = thisClass->ivars;
- if (fieldsInClass) {
- int i, numFieldsInClass = fieldsInClass->ivar_count;
- for (i = 0; i < numFieldsInClass; i++) {
- Ivar objcIVar = &fieldsInClass->ivar_list[i];
- NSString *mappedName = 0;
+ id targetObject = (static_cast<ObjcInstance*>(instance))->getObject();
+ id attributes = [targetObject attributeKeys];
+ if (attributes != nil) {
+ // Class overrides attributeKeys, use that array of key names.
+ unsigned i, count = [attributes count];
+ for (i = 0; i < count; i++) {
+ NSString *keyName = [attributes objectAtIndex: i];
+ const char *UTF8KeyName = [keyName UTF8String]; // ObjC actually only supports ASCII names.
+
+ // See if the class wants to exclude the selector from visibility in JavaScript.
+ if ([(id)thisClass respondsToSelector:@selector(isKeyExcludedFromWebScript:)]) {
+ if ([(id)thisClass isKeyExcludedFromWebScript:UTF8KeyName]) {
+ continue;
+ }
+ }
+
+ // See if the class want to provide a different name for the selector in JavaScript.
+ // Note that we do not do any checks to guarantee uniqueness. That's the responsiblity
+ // of the class.
+ NSString *mappedName = 0;
+ if ([(id)thisClass respondsToSelector:@selector(webScriptNameForKey:)]){
+ mappedName = [(id)thisClass webScriptNameForKey:UTF8KeyName];
+ }
- // See if the class wants to exclude the selector from visibility in JavaScript.
- if ([(id)thisClass respondsToSelector:@selector(isKeyExcludedFromWebScript:)]) {
- if ([(id)thisClass isKeyExcludedFromWebScript:objcIVar->ivar_name]) {
- continue;
+ if ((mappedName && [mappedName isEqual:(NSString *)fieldName]) ||
+ [keyName isEqual:(NSString *)fieldName]) {
+ aField = new ObjcField ((CFStringRef)keyName);
+ CFDictionaryAddValue ((CFMutableDictionaryRef)_fields, fieldName, aField);
+ break;
+ }
+ }
+ }
+ else {
+ // Class doesn't override attributeKeys, so fall back on class runtime
+ // introspection.
+
+ while (thisClass != 0) {
+ struct objc_ivar_list *fieldsInClass = thisClass->ivars;
+ if (fieldsInClass) {
+ int i, numFieldsInClass = fieldsInClass->ivar_count;
+ for (i = 0; i < numFieldsInClass; i++) {
+ Ivar objcIVar = &fieldsInClass->ivar_list[i];
+ NSString *mappedName = 0;
+
+ // See if the class wants to exclude the selector from visibility in JavaScript.
+ if ([(id)thisClass respondsToSelector:@selector(isKeyExcludedFromWebScript:)]) {
+ if ([(id)thisClass isKeyExcludedFromWebScript:objcIVar->ivar_name]) {
+ continue;
+ }
+ }
+
+ // See if the class want to provide a different name for the selector in JavaScript.
+ // Note that we do not do any checks to guarantee uniqueness. That's the responsiblity
+ // of the class.
+ if ([(id)thisClass respondsToSelector:@selector(webScriptNameForKey:)]){
+ mappedName = [(id)thisClass webScriptNameForKey:objcIVar->ivar_name];
}
- }
-
- // See if the class want to provide a different name for the selector in JavaScript.
- // Note that we do not do any checks to guarantee uniqueness. That's the responsiblity
- // of the class.
- if ([(id)thisClass respondsToSelector:@selector(webScriptNameForKey:)]){
- mappedName = [(id)thisClass webScriptNameForKey:objcIVar->ivar_name];
- }
- if ((mappedName && [mappedName isEqual:(NSString *)fieldName]) ||
- strcmp(objcIVar->ivar_name,name) == 0) {
- aField = new ObjcField (objcIVar);
- CFDictionaryAddValue ((CFMutableDictionaryRef)_fields, fieldName, aField);
- break;
+ if ((mappedName && [mappedName isEqual:(NSString *)fieldName]) ||
+ strcmp(objcIVar->ivar_name,name) == 0) {
+ aField = new ObjcField (objcIVar);
+ CFDictionaryAddValue ((CFMutableDictionaryRef)_fields, fieldName, aField);
+ break;
+ }
}
}
+ thisClass = thisClass->super_class;
}
- thisClass = thisClass->super_class;
- }
- CFRelease (fieldName);
+ CFRelease (fieldName);
+ }
return aField;
-};
+}
+
+KJS::Value ObjcClass::fallbackObject (ExecState *exec, Instance *instance, const Identifier &propertyName)
+{
+ return Object (new FallbackObjectImp(static_cast<ObjcInstance*>(instance), propertyName));
+}
virtual KJS::Value invokeMethod (KJS::ExecState *exec, const MethodList &method, const KJS::List &args);
+ virtual void setValueOfField (KJS::ExecState *exec, const Field *aField, const KJS::Value &aValue) const;
+ virtual void setValueOfUndefinedField (KJS::ExecState *exec, const KJS::Identifier &property, const KJS::Value &aValue);
+
+ virtual Value ObjcInstance::getValueOfField (KJS::ExecState *exec, const Field *aField) const;
+ virtual KJS::Value getValueOfUndefinedField (KJS::ExecState *exec, const KJS::Identifier &property, KJS::Type hint) const;
+
ObjectStructPtr getObject() const { return _instance; }
KJS::Value stringValue() const;
}
#endif
+#include <JavaScriptCore/objc_runtime.h>
+
using namespace KJS::Bindings;
using namespace KJS;
resultValue = convertObjcValueToValue (exec, buffer, objcValueType);
}
- // Fallback methods are created for one-shot use. They are created in
- // ObjcClass::methodsNamed() and deleted here.
- if (method->isFallbackMethod())
- delete method;
-
NS_HANDLER
resultValue = Undefined();
return resultValue;
}
+void ObjcInstance::setValueOfField (KJS::ExecState *exec, const Field *aField, const KJS::Value &aValue) const
+{
+ aField->setValueToInstance (exec, this, aValue);
+}
+
+void ObjcInstance::setValueOfUndefinedField (KJS::ExecState *exec, const KJS::Identifier &property, const KJS::Value &aValue)
+{
+ id targetObject = getObject();
+
+ // This check is not really necessary because NSObject implements
+ // setValue:forUndefinedKey:, and unfortnately the default implementation
+ // throws an exception.
+ if ([targetObject respondsToSelector:@selector(setValue:forUndefinedKey:)]){
+
+ NS_DURING
+
+ ObjcValue objcValue = convertValueToObjcValue (exec, aValue, ObjcObjectType);
+ [targetObject setValue:objcValue.objectValue forUndefinedKey:[NSString stringWithCString:property.ascii()]];
+
+ NS_HANDLER
+
+ // Do nothing. Class did not override valueForUndefinedKey:.
+
+ NS_ENDHANDLER
+
+ }
+}
+
+Value ObjcInstance::getValueOfField (KJS::ExecState *exec, const Field *aField) const {
+ return aField->valueFromInstance (exec, this);
+}
+
+KJS::Value ObjcInstance::getValueOfUndefinedField (KJS::ExecState *exec, const KJS::Identifier &property, KJS::Type hint) const
+{
+ Value result = Undefined();
+
+ id targetObject = getObject();
+
+ // This check is not really necessary because NSObject implements
+ // valueForUndefinedKey:, and unfortnately the default implementation
+ // throws an exception.
+ if ([targetObject respondsToSelector:@selector(valueForUndefinedKey:)]){
+ id objcValue;
+
+ NS_DURING
+
+ objcValue = [targetObject valueForUndefinedKey:[NSString stringWithCString:property.ascii()]];
+ result = convertObjcValueToValue (exec, &objcValue, ObjcObjectType);
+
+ NS_HANDLER
+
+ // Do nothing. Class did not override valueForUndefinedKey:.
+
+ NS_ENDHANDLER
+
+ }
+
+ return result;
+}
KJS::Value ObjcInstance::defaultValue (KJS::Type hint) const
{
namespace Bindings
{
+class ObjcInstance;
+
class ObjcField : public Field
{
public:
ObjcField(Ivar ivar);
+
+ ObjcField(CFStringRef name);
- ~ObjcField() {};
+ ~ObjcField() {
+ if (_name)
+ CFRelease (_name);
+ };
ObjcField(const ObjcField &other) : Field() {
_ivar = other._ivar;
+
+ if (other._name != _name) {
+ if (_name)
+ CFRelease (_name);
+ if (other._name)
+ _name = (CFStringRef)CFRetain (other._name);
+ else
+ _name = 0;
+ }
};
ObjcField &operator=(const ObjcField &other) {
_ivar = other._ivar;
+ if (other._name != _name) {
+ if (_name)
+ CFRelease (_name);
+ if (other._name)
+ _name = (CFStringRef)CFRetain (other._name);
+ else
+ _name = 0;
+ }
+
return *this;
};
virtual const char *name() const;
virtual RuntimeType type() const;
-
+
private:
Ivar _ivar;
+ CFStringRef _name;
};
ObjectStructPtr _array;
};
+class FallbackObjectImp : public KJS::ObjectImp {
+public:
+ FallbackObjectImp(ObjectImp *proto);
+
+ FallbackObjectImp(ObjcInstance *i, const KJS::Identifier propertyName);
+
+ const ClassInfo *classInfo() const { return &info; }
+
+ virtual Value get(ExecState *exec, const Identifier &propertyName) const;
+
+ virtual void put(ExecState *exec, const Identifier &propertyName,
+ const Value &value, int attr = None);
+
+ virtual bool canPut(ExecState *exec, const Identifier &propertyName) const;
+
+ virtual bool implementsCall() const;
+ virtual Value call(ExecState *exec, Object &thisObj, const List &args);
+
+ virtual bool hasProperty(ExecState *exec,
+ const Identifier &propertyName) const;
+
+
+ virtual bool deleteProperty(ExecState *exec,
+ const Identifier &propertyName);
+
+ virtual Value defaultValue(ExecState *exec, Type hint) const;
+
+private:
+ static const ClassInfo info;
+
+ ObjcInstance *_instance;
+ KJS::Identifier _item;
+};
+
} // namespace Bindings
} // namespace KJS
ObjcField::ObjcField(Ivar ivar)
{
_ivar = ivar; // Assume ObjectiveC runtime will keep this alive forever
+ _name = 0;
+}
+
+ObjcField::ObjcField(CFStringRef name)
+{
+ _ivar = 0;
+ _name = (CFStringRef)CFRetain(name);
}
const char *ObjcField::name() const
{
- return _ivar->ivar_name;
+ if (_ivar)
+ return _ivar->ivar_name;
+ return [(NSString *)_name UTF8String];
}
RuntimeType ObjcField::type() const
-{
- return _ivar->ivar_type;
+{
+ if (_ivar)
+ return _ivar->ivar_type;
+
+ // Type is irrelevant if we use KV to set/get the value.
+ return "";
}
Value ObjcField::valueFromInstance(KJS::ExecState *exec, const Instance *instance) const
NS_DURING
- NSString *key = [NSString stringWithCString:_ivar->ivar_name];
+ NSString *key = [NSString stringWithCString:name()];
objcValue = [targetObject valueForKey:key];
NS_HANDLER
NS_DURING
- NSString *key = [NSString stringWithCString:_ivar->ivar_name];
+ NSString *key = [NSString stringWithCString:name()];
[targetObject setValue:value forKey:key];
-
+
NS_HANDLER
Value aValue = Error::create(exec, GeneralError, [[localException reason] lossyCString]);
{
return [_array count];
}
+
+
+const ClassInfo FallbackObjectImp::info = {"FallbackObject", 0, 0, 0};
+
+FallbackObjectImp::FallbackObjectImp(ObjectImp *proto)
+ : ObjectImp(proto)
+{
+ _instance = 0;
+}
+
+FallbackObjectImp::FallbackObjectImp(ObjcInstance *i, const KJS::Identifier propertyName) : ObjectImp ((ObjectImp *)0)
+{
+ _instance = i;
+ _item = propertyName;
+}
+
+Value FallbackObjectImp::get(ExecState *exec, const Identifier &propertyName) const
+{
+ return Undefined();
+}
+
+void FallbackObjectImp::put(ExecState *exec, const Identifier &propertyName,
+ const Value &value, int attr)
+{
+}
+
+bool FallbackObjectImp::canPut(ExecState *exec, const Identifier &propertyName) const
+{
+ return false;
+}
+
+
+bool FallbackObjectImp::implementsCall() const
+{
+ return true;
+}
+
+Value FallbackObjectImp::call(ExecState *exec, Object &thisObj, const List &args)
+{
+ Value result = Undefined();
+
+ RuntimeObjectImp *imp = static_cast<RuntimeObjectImp*>(thisObj.imp());
+ if (imp) {
+ Instance *instance = imp->getInternalInstance();
+
+ instance->begin();
+
+ ObjcInstance *objcInstance = static_cast<ObjcInstance*>(instance);
+ id targetObject = objcInstance->getObject();
+
+ if ([targetObject respondsToSelector:@selector(invokeUndefinedMethodFromWebScript:withArguments:)]){
+ MethodList methodList;
+ ObjcClass *objcClass = static_cast<ObjcClass*>(instance->getClass());
+ ObjcMethod *fallbackMethod = new ObjcMethod (objcClass->isa(), (const char *)@selector(invokeUndefinedMethodFromWebScript:withArguments:));
+ fallbackMethod->setJavaScriptName((CFStringRef)[NSString stringWithCString:_item.ascii()]);
+ methodList.addMethod ((Method *)fallbackMethod);
+ result = instance->invokeMethod(exec, methodList, args);
+ delete fallbackMethod;
+ }
+
+ instance->end();
+ }
+
+ return result;
+}
+
+bool FallbackObjectImp::hasProperty(ExecState *exec,
+ const Identifier &propertyName) const
+{
+ return false;
+}
+
+bool FallbackObjectImp::deleteProperty(ExecState *exec,
+ const Identifier &propertyName)
+{
+ return false;
+}
+
+Value FallbackObjectImp::defaultValue(ExecState *exec, Type hint) const
+{
+ return _instance->getValueOfUndefinedField(exec, _item, hint);
+}
+
virtual Constructor *constructorAt(long i) const = 0;
virtual long numConstructors() const = 0;
- virtual Field *fieldNamed(const char *name) const = 0;
+ virtual Field *fieldNamed(const char *name, Instance *instance) const = 0;
+ virtual Value fallbackObject(KJS::ExecState *exec, Bindings::Instance *instance, const KJS::Identifier &propertyName) { return Undefined(); }
+
virtual ~Class() {};
};
virtual Class *getClass() const = 0;
virtual KJS::Value getValueOfField (KJS::ExecState *exec, const Field *aField) const;
+ virtual KJS::Value getValueOfUndefinedField (KJS::ExecState *exec, const KJS::Identifier &property, KJS::Type hint) const { return Undefined(); };
virtual void setValueOfField (KJS::ExecState *exec, const Field *aField, const KJS::Value &aValue) const;
+ virtual void setValueOfUndefinedField (KJS::ExecState *exec, const KJS::Identifier &property, const KJS::Value &aValue) {};
virtual KJS::Value invokeMethod (KJS::ExecState *exec, const MethodList &method, const KJS::List &args) = 0;
Value RuntimeObjectImp::get(ExecState *exec, const Identifier &propertyName) const
{
+ Value result = Undefined();
+
instance->begin();
Class *aClass = instance->getClass();
if (aClass) {
+
// See if the instance have a field with the specified name.
- Field *aField = aClass->fieldNamed(propertyName.ascii());
+ Field *aField = aClass->fieldNamed(propertyName.ascii(), instance);
if (aField) {
- return instance->getValueOfField (exec, aField);
+ result = instance->getValueOfField (exec, aField);
}
-
- // Now check if a method with specified name exists, if so return a function object for
- // that method.
- MethodList methodList = aClass->methodsNamed(propertyName.ascii());
- if (methodList.length() > 0) {
- instance->end();
- return Object (new RuntimeMethodImp(exec, propertyName, methodList));
+ else {
+ // Now check if a method with specified name exists, if so return a function object for
+ // that method.
+ MethodList methodList = aClass->methodsNamed(propertyName.ascii());
+ if (methodList.length() > 0) {
+ result = Object (new RuntimeMethodImp(exec, propertyName, methodList));
+ }
}
- }
+ if (result.type() == UndefinedType) {
+ // Try a fallback object.
+ result = aClass->fallbackObject (exec, instance, propertyName);
+ }
+ }
+
+
instance->end();
-
- return Undefined();
+
+ return result;
}
void RuntimeObjectImp::put(ExecState *exec, const Identifier &propertyName,
instance->begin();
// Set the value of the property.
- Field *aField = instance->getClass()->fieldNamed(propertyName.ascii());
+ Field *aField = instance->getClass()->fieldNamed(propertyName.ascii(), instance);
if (aField) {
getInternalInstance()->setValueOfField(exec, aField, value);
}
+ else {
+ getInternalInstance()->setValueOfUndefinedField(exec, propertyName, value);
+ }
instance->end();
}
{
instance->begin();
- Field *aField = instance->getClass()->fieldNamed(propertyName.ascii());
+ Field *aField = instance->getClass()->fieldNamed(propertyName.ascii(), instance);
instance->end();
{
instance->begin();
- Field *aField = instance->getClass()->fieldNamed(propertyName.ascii());
+ Field *aField = instance->getClass()->fieldNamed(propertyName.ascii(), instance);
if (aField) {
instance->end();
return true;
return @"success";
}
+- (id)valueForUndefinedKey:(NSString *)key
+{
+ NSLog (@"%s: key = %@", __PRETTY_FUNCTION__, key);
+ return @"aValue";
+}
+
+- (void)setValue:(id)value forUndefinedKey:(NSString *)key
+{
+ NSLog (@"%s: key = %@", __PRETTY_FUNCTION__, key);
+}
+
- init
{
LOG ("\n");