18e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project/*
28e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * Copyright (C) 2004 Apple Computer, Inc.  All rights reserved.
38e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *
48e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * Redistribution and use in source and binary forms, with or without
58e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * modification, are permitted provided that the following conditions
68e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * are met:
78e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * 1. Redistributions of source code must retain the above copyright
88e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *    notice, this list of conditions and the following disclaimer.
98e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * 2. Redistributions in binary form must reproduce the above copyright
108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *    notice, this list of conditions and the following disclaimer in the
118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *    documentation and/or other materials provided with the distribution.
128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *
138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project */
258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "config.h"
278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "objc_class.h"
288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "objc_instance.h"
308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "WebScriptObject.h"
318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectnamespace JSC {
338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectnamespace Bindings {
348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic void deleteMethod(CFAllocatorRef, const void* value)
368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    delete static_cast<const Method*>(value);
388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic void deleteField(CFAllocatorRef, const void* value)
418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    delete static_cast<const Field*>(value);
438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectconst CFDictionaryValueCallBacks MethodDictionaryValueCallBacks = { 0, 0, &deleteMethod, 0 , 0 };
468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectconst CFDictionaryValueCallBacks FieldDictionaryValueCallBacks = { 0, 0, &deleteField, 0 , 0 };
478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectObjcClass::ObjcClass(ClassStructPtr aClass)
498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    : _isa(aClass)
508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    , _methods(AdoptCF, CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &MethodDictionaryValueCallBacks))
518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    , _fields(AdoptCF, CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &FieldDictionaryValueCallBacks))
528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic CFMutableDictionaryRef classesByIsA = 0;
568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic void _createClassesByIsAIfNecessary()
588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!classesByIsA)
608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        classesByIsA = CFDictionaryCreateMutable(NULL, 0, NULL, NULL);
618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectObjcClass* ObjcClass::classForIsA(ClassStructPtr isa)
648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    _createClassesByIsAIfNecessary();
668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ObjcClass* aClass = (ObjcClass*)CFDictionaryGetValue(classesByIsA, isa);
688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!aClass) {
698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        aClass = new ObjcClass(isa);
708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        CFDictionaryAddValue(classesByIsA, isa, aClass);
718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return aClass;
748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectMethodList ObjcClass::methodsNamed(const Identifier& identifier, Instance*) const
778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    MethodList methodList;
798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    char fixedSizeBuffer[1024];
808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    char* buffer = fixedSizeBuffer;
81f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    CString jsName = identifier.ascii();
82f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    if (!convertJSMethodNameToObjc(jsName.data(), buffer, sizeof(fixedSizeBuffer))) {
83f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick        int length = jsName.length() + 1;
848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        buffer = new char[length];
85f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick        if (!buffer || !convertJSMethodNameToObjc(jsName.data(), buffer, length))
868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            return methodList;
878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    RetainPtr<CFStringRef> methodName(AdoptCF, CFStringCreateWithCString(NULL, buffer, kCFStringEncodingASCII));
918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    Method* method = (Method*)CFDictionaryGetValue(_methods.get(), methodName.get());
928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (method) {
938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        methodList.append(method);
948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return methodList;
958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ClassStructPtr thisClass = _isa;
988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    while (thisClass && methodList.isEmpty()) {
998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#if defined(OBJC_API_VERSION) && OBJC_API_VERSION >= 2
1008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        unsigned numMethodsInClass = 0;
1018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        MethodStructPtr* objcMethodList = class_copyMethodList(thisClass, &numMethodsInClass);
1028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#else
1038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        void* iterator = 0;
1048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        struct objc_method_list* objcMethodList;
1058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        while ((objcMethodList = class_nextMethodList(thisClass, &iterator))) {
1068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            unsigned numMethodsInClass = objcMethodList->method_count;
1078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#endif
1088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            for (unsigned i = 0; i < numMethodsInClass; i++) {
1098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#if defined(OBJC_API_VERSION) && OBJC_API_VERSION >= 2
1108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                MethodStructPtr objcMethod = objcMethodList[i];
1118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                SEL objcMethodSelector = method_getName(objcMethod);
1128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#else
1138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                struct objc_method* objcMethod = &objcMethodList->method_list[i];
1148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                SEL objcMethodSelector = objcMethod->method_name;
1158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#endif
1168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                const char* objcMethodSelectorName = sel_getName(objcMethodSelector);
1178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                NSString* mappedName = nil;
1188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                // See if the class wants to exclude the selector from visibility in JavaScript.
1208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                if ([thisClass respondsToSelector:@selector(isSelectorExcludedFromWebScript:)])
1218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    if ([thisClass isSelectorExcludedFromWebScript:objcMethodSelector])
1228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                        continue;
1238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                // See if the class want to provide a different name for the selector in JavaScript.
1258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                // Note that we do not do any checks to guarantee uniqueness. That's the responsiblity
1268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                // of the class.
1278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                if ([thisClass respondsToSelector:@selector(webScriptNameForSelector:)])
1288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    mappedName = [thisClass webScriptNameForSelector:objcMethodSelector];
1298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                if ((mappedName && [mappedName isEqual:(NSString*)methodName.get()]) || strcmp(objcMethodSelectorName, buffer) == 0) {
131635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project                    Method* aMethod = new ObjcMethod(thisClass, objcMethodSelector); // deleted when the dictionary is destroyed
1328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    CFDictionaryAddValue(_methods.get(), methodName.get(), aMethod);
1338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    methodList.append(aMethod);
1348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    break;
1358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                }
1368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            }
1378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#if defined(OBJC_API_VERSION) && OBJC_API_VERSION >= 2
1388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            thisClass = class_getSuperclass(thisClass);
1398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            free(objcMethodList);
1408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#else
1418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        }
1428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        thisClass = thisClass->super_class;
1438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#endif
1448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
1458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (buffer != fixedSizeBuffer)
1478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        delete [] buffer;
1488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return methodList;
1508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
1518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectField* ObjcClass::fieldNamed(const Identifier& identifier, Instance* instance) const
1538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
1548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ClassStructPtr thisClass = _isa;
1558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
156f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    CString jsName = identifier.ascii();
157f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    RetainPtr<CFStringRef> fieldName(AdoptCF, CFStringCreateWithCString(NULL, jsName.data(), kCFStringEncodingASCII));
1588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    Field* aField = (Field*)CFDictionaryGetValue(_fields.get(), fieldName.get());
1598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (aField)
1608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return aField;
1618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    id targetObject = (static_cast<ObjcInstance*>(instance))->getObject();
1638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    id attributes = [targetObject attributeKeys];
1648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (attributes) {
1658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        // Class overrides attributeKeys, use that array of key names.
1668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        unsigned count = [attributes count];
1678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        for (unsigned i = 0; i < count; i++) {
1688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            NSString* keyName = [attributes objectAtIndex:i];
1698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            const char* UTF8KeyName = [keyName UTF8String]; // ObjC actually only supports ASCII names.
1708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            // See if the class wants to exclude the selector from visibility in JavaScript.
1728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            if ([thisClass respondsToSelector:@selector(isKeyExcludedFromWebScript:)])
1738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                if ([thisClass isKeyExcludedFromWebScript:UTF8KeyName])
1748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    continue;
1758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            // See if the class want to provide a different name for the selector in JavaScript.
1778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            // Note that we do not do any checks to guarantee uniqueness. That's the responsiblity
1788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            // of the class.
1798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            NSString* mappedName = nil;
1808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            if ([thisClass respondsToSelector:@selector(webScriptNameForKey:)])
1818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                mappedName = [thisClass webScriptNameForKey:UTF8KeyName];
1828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            if ((mappedName && [mappedName isEqual:(NSString*)fieldName.get()]) || [keyName isEqual:(NSString*)fieldName.get()]) {
1848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                aField = new ObjcField((CFStringRef)keyName); // deleted when the dictionary is destroyed
1858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                CFDictionaryAddValue(_fields.get(), fieldName.get(), aField);
1868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                break;
1878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            }
1888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        }
1898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    } else {
1908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        // Class doesn't override attributeKeys, so fall back on class runtime
1918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        // introspection.
1928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        while (thisClass) {
1948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#if defined(OBJC_API_VERSION) && OBJC_API_VERSION >= 2
1958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            unsigned numFieldsInClass = 0;
1968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            IvarStructPtr* ivarsInClass = class_copyIvarList(thisClass, &numFieldsInClass);
1978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#else
1988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            struct objc_ivar_list* fieldsInClass = thisClass->ivars;
1998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            if (fieldsInClass) {
2008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                unsigned numFieldsInClass = fieldsInClass->ivar_count;
2018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#endif
2028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                for (unsigned i = 0; i < numFieldsInClass; i++) {
2038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#if defined(OBJC_API_VERSION) && OBJC_API_VERSION >= 2
2048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    IvarStructPtr objcIVar = ivarsInClass[i];
2058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    const char* objcIvarName = ivar_getName(objcIVar);
2068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#else
2078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    IvarStructPtr objcIVar = &fieldsInClass->ivar_list[i];
2088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    const char* objcIvarName = objcIVar->ivar_name;
2098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#endif
2108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    NSString* mappedName = 0;
2118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    // See if the class wants to exclude the selector from visibility in JavaScript.
2138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    if ([thisClass respondsToSelector:@selector(isKeyExcludedFromWebScript:)])
2148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                        if ([thisClass isKeyExcludedFromWebScript:objcIvarName])
2158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                            continue;
2168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    // See if the class want to provide a different name for the selector in JavaScript.
2188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    // Note that we do not do any checks to guarantee uniqueness. That's the responsiblity
2198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    // of the class.
2208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    if ([thisClass respondsToSelector:@selector(webScriptNameForKey:)])
2218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                        mappedName = [thisClass webScriptNameForKey:objcIvarName];
2228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
223f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick                    if ((mappedName && [mappedName isEqual:(NSString*)fieldName.get()]) || strcmp(objcIvarName, jsName.data()) == 0) {
2248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                        aField = new ObjcField(objcIVar); // deleted when the dictionary is destroyed
2258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                        CFDictionaryAddValue(_fields.get(), fieldName.get(), aField);
2268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                        break;
2278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    }
2288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                }
2298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#if defined(OBJC_API_VERSION) && OBJC_API_VERSION >= 2
2308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            thisClass = class_getSuperclass(thisClass);
2318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            free(ivarsInClass);
2328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#else
2338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            }
2348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            thisClass = thisClass->super_class;
2358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#endif
2368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        }
2378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
2388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return aField;
2408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
2418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2425f1ab04193ad0130ca8204aadaceae083aca9881Feng QianJSValue ObjcClass::fallbackObject(ExecState* exec, Instance* instance, const Identifier &propertyName)
2438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
2448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ObjcInstance* objcInstance = static_cast<ObjcInstance*>(instance);
2458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    id targetObject = objcInstance->getObject();
2468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (![targetObject respondsToSelector:@selector(invokeUndefinedMethodFromWebScript:withArguments:)])
2488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return jsUndefined();
249e78cbe89e6f337f2f1fe40315be88f742b547151Steve Block    return new (exec) ObjcFallbackObjectImp(exec, exec->lexicalGlobalObject(), objcInstance, propertyName);
2508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
2518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
2538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
254