⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 objc_class.mm

📁 linux下开源浏览器WebKit的源码,市面上的很多商用浏览器都是移植自WebKit
💻 MM
字号:
/* * Copyright (C) 2004 Apple Computer, Inc.  All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright *    notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright *    notice, this list of conditions and the following disclaimer in the *    documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.  */#include "config.h"#include "objc_class.h"#include "objc_instance.h"#include "WebScriptObject.h"namespace JSC {namespace Bindings {    static void deleteMethod(CFAllocatorRef, const void* value){    delete static_cast<const Method*>(value);}    static void deleteField(CFAllocatorRef, const void* value){    delete static_cast<const Field*>(value);}const CFDictionaryValueCallBacks MethodDictionaryValueCallBacks = { 0, 0, &deleteMethod, 0 , 0 };const CFDictionaryValueCallBacks FieldDictionaryValueCallBacks = { 0, 0, &deleteField, 0 , 0 };        ObjcClass::ObjcClass(ClassStructPtr aClass)    : _isa(aClass)    , _methods(AdoptCF, CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &MethodDictionaryValueCallBacks))    , _fields(AdoptCF, CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &FieldDictionaryValueCallBacks)){}static CFMutableDictionaryRef classesByIsA = 0;static void _createClassesByIsAIfNecessary(){    if (!classesByIsA)        classesByIsA = CFDictionaryCreateMutable(NULL, 0, NULL, NULL);}ObjcClass* ObjcClass::classForIsA(ClassStructPtr isa){    _createClassesByIsAIfNecessary();    ObjcClass* aClass = (ObjcClass*)CFDictionaryGetValue(classesByIsA, isa);    if (!aClass) {        aClass = new ObjcClass(isa);        CFDictionaryAddValue(classesByIsA, isa, aClass);    }    return aClass;}MethodList ObjcClass::methodsNamed(const Identifier& identifier, Instance*) const{    MethodList methodList;    char fixedSizeBuffer[1024];    char* buffer = fixedSizeBuffer;    const char* JSName = identifier.ascii();    if (!convertJSMethodNameToObjc(JSName, buffer, sizeof(fixedSizeBuffer))) {        int length = strlen(JSName) + 1;        buffer = new char[length];        if (!buffer || !convertJSMethodNameToObjc(JSName, buffer, length))            return methodList;    }        RetainPtr<CFStringRef> methodName(AdoptCF, CFStringCreateWithCString(NULL, buffer, kCFStringEncodingASCII));    Method* method = (Method*)CFDictionaryGetValue(_methods.get(), methodName.get());    if (method) {        methodList.append(method);        return methodList;    }    ClassStructPtr thisClass = _isa;    while (thisClass && methodList.isEmpty()) {#if defined(OBJC_API_VERSION) && OBJC_API_VERSION >= 2        unsigned numMethodsInClass = 0;        MethodStructPtr* objcMethodList = class_copyMethodList(thisClass, &numMethodsInClass);#else        void* iterator = 0;        struct objc_method_list* objcMethodList;        while ((objcMethodList = class_nextMethodList(thisClass, &iterator))) {            unsigned numMethodsInClass = objcMethodList->method_count;#endif            for (unsigned i = 0; i < numMethodsInClass; i++) {#if defined(OBJC_API_VERSION) && OBJC_API_VERSION >= 2                MethodStructPtr objcMethod = objcMethodList[i];                SEL objcMethodSelector = method_getName(objcMethod);#else                struct objc_method* objcMethod = &objcMethodList->method_list[i];                SEL objcMethodSelector = objcMethod->method_name;#endif                const char* objcMethodSelectorName = sel_getName(objcMethodSelector);                NSString* mappedName = nil;                // See if the class wants to exclude the selector from visibility in JavaScript.                if ([thisClass respondsToSelector:@selector(isSelectorExcludedFromWebScript:)])                    if ([thisClass isSelectorExcludedFromWebScript:objcMethodSelector])                        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 ([thisClass respondsToSelector:@selector(webScriptNameForSelector:)])                    mappedName = [thisClass webScriptNameForSelector:objcMethodSelector];                if ((mappedName && [mappedName isEqual:(NSString*)methodName.get()]) || strcmp(objcMethodSelectorName, buffer) == 0) {                    Method* aMethod = new ObjcMethod(thisClass, objcMethodSelector); // deleted when the dictionary is destroyed                    CFDictionaryAddValue(_methods.get(), methodName.get(), aMethod);                    methodList.append(aMethod);                    break;                }            }#if defined(OBJC_API_VERSION) && OBJC_API_VERSION >= 2            thisClass = class_getSuperclass(thisClass);            free(objcMethodList);#else        }        thisClass = thisClass->super_class;#endif    }    if (buffer != fixedSizeBuffer)        delete [] buffer;    return methodList;}Field* ObjcClass::fieldNamed(const Identifier& identifier, Instance* instance) const{    ClassStructPtr thisClass = _isa;    const char* name = identifier.ascii();    RetainPtr<CFStringRef> fieldName(AdoptCF, CFStringCreateWithCString(NULL, name, kCFStringEncodingASCII));    Field* aField = (Field*)CFDictionaryGetValue(_fields.get(), fieldName.get());    if (aField)        return aField;    id targetObject = (static_cast<ObjcInstance*>(instance))->getObject();    id attributes = [targetObject attributeKeys];    if (attributes) {        // Class overrides attributeKeys, use that array of key names.        unsigned count = [attributes count];        for (unsigned 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 ([thisClass respondsToSelector:@selector(isKeyExcludedFromWebScript:)])                if ([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 = nil;            if ([thisClass respondsToSelector:@selector(webScriptNameForKey:)])                mappedName = [thisClass webScriptNameForKey:UTF8KeyName];            if ((mappedName && [mappedName isEqual:(NSString*)fieldName.get()]) || [keyName isEqual:(NSString*)fieldName.get()]) {                aField = new ObjcField((CFStringRef)keyName); // deleted when the dictionary is destroyed                CFDictionaryAddValue(_fields.get(), fieldName.get(), aField);                break;            }        }    } else {        // Class doesn't override attributeKeys, so fall back on class runtime        // introspection.        while (thisClass) {#if defined(OBJC_API_VERSION) && OBJC_API_VERSION >= 2            unsigned numFieldsInClass = 0;            IvarStructPtr* ivarsInClass = class_copyIvarList(thisClass, &numFieldsInClass);#else            struct objc_ivar_list* fieldsInClass = thisClass->ivars;            if (fieldsInClass) {                unsigned numFieldsInClass = fieldsInClass->ivar_count;#endif                for (unsigned i = 0; i < numFieldsInClass; i++) {#if defined(OBJC_API_VERSION) && OBJC_API_VERSION >= 2                    IvarStructPtr objcIVar = ivarsInClass[i];                    const char* objcIvarName = ivar_getName(objcIVar);#else                    IvarStructPtr objcIVar = &fieldsInClass->ivar_list[i];                    const char* objcIvarName = objcIVar->ivar_name;#endif                    NSString* mappedName = 0;                    // See if the class wants to exclude the selector from visibility in JavaScript.                    if ([thisClass respondsToSelector:@selector(isKeyExcludedFromWebScript:)])                        if ([thisClass isKeyExcludedFromWebScript:objcIvarName])                            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 ([thisClass respondsToSelector:@selector(webScriptNameForKey:)])                        mappedName = [thisClass webScriptNameForKey:objcIvarName];                    if ((mappedName && [mappedName isEqual:(NSString*)fieldName.get()]) || strcmp(objcIvarName, name) == 0) {                        aField = new ObjcField(objcIVar); // deleted when the dictionary is destroyed                        CFDictionaryAddValue(_fields.get(), fieldName.get(), aField);                        break;                    }                }#if defined(OBJC_API_VERSION) && OBJC_API_VERSION >= 2            thisClass = class_getSuperclass(thisClass);            free(ivarsInClass);#else            }            thisClass = thisClass->super_class;#endif        }    }    return aField;}JSValuePtr ObjcClass::fallbackObject(ExecState* exec, Instance* instance, const Identifier &propertyName){    ObjcInstance* objcInstance = static_cast<ObjcInstance*>(instance);    id targetObject = objcInstance->getObject();        if (![targetObject respondsToSelector:@selector(invokeUndefinedMethodFromWebScript:withArguments:)])        return jsUndefined();    return new (exec) ObjcFallbackObjectImp(exec, objcInstance, propertyName);}}}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -