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