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

📄 objc_runtime.mm

📁 linux下开源浏览器WebKit的源码,市面上的很多商用浏览器都是移植自WebKit
💻 MM
字号:
/* * Copyright (C) 2004, 2008 Apple 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_runtime.h"#include "JSDOMBinding.h"#include "WebScriptObject.h"#include "objc_instance.h"#include "runtime_array.h"#include "runtime_object.h"#include <runtime/Error.h>#include <runtime/JSGlobalObject.h>#include <runtime/JSLock.h>#include <runtime/ObjectPrototype.h>#include <wtf/RetainPtr.h>using namespace WebCore;namespace JSC {namespace Bindings {ClassStructPtr webScriptObjectClass(){    static ClassStructPtr<WebScriptObject> webScriptObjectClass = NSClassFromString(@"WebScriptObject");    return webScriptObjectClass;}ClassStructPtr webUndefinedClass(){    static ClassStructPtr<WebUndefined> webUndefinedClass = NSClassFromString(@"WebUndefined");    return webUndefinedClass;}// ---------------------- ObjcMethod ----------------------ObjcMethod::ObjcMethod(ClassStructPtr aClass, SEL selector)    : _objcClass(aClass)    , _selector(selector){}int ObjcMethod::numParameters() const{    return [getMethodSignature() numberOfArguments] - 2;}NSMethodSignature* ObjcMethod::getMethodSignature() const{    return [_objcClass instanceMethodSignatureForSelector:_selector];}// ---------------------- ObjcField ----------------------ObjcField::ObjcField(Ivar ivar)     : _ivar(ivar)#if defined(OBJC_API_VERSION) && OBJC_API_VERSION >= 2    , _name(AdoptCF, CFStringCreateWithCString(0, ivar_getName(_ivar), kCFStringEncodingASCII))#else    , _name(AdoptCF, CFStringCreateWithCString(0, _ivar->ivar_name, kCFStringEncodingASCII))#endif{}ObjcField::ObjcField(CFStringRef name)    : _ivar(0)    , _name(name){}JSValuePtr ObjcField::valueFromInstance(ExecState* exec, const Instance* instance) const{    JSValuePtr result = jsUndefined();        id targetObject = (static_cast<const ObjcInstance*>(instance))->getObject();    JSLock::DropAllLocks dropAllLocks(false); // Can't put this inside the @try scope because it unwinds incorrectly.    @try {        if (id objcValue = [targetObject valueForKey:(NSString *)_name.get()])            result = convertObjcValueToValue(exec, &objcValue, ObjcObjectType, instance->rootObject());    } @catch(NSException* localException) {        JSLock::lock(false);        throwError(exec, GeneralError, [localException reason]);        JSLock::unlock(false);    }    // Work around problem in some versions of GCC where result gets marked volatile and    // it can't handle copying from a volatile to non-volatile.    return const_cast<JSValuePtr&>(result);}static id convertValueToObjcObject(ExecState* exec, JSValuePtr value){    RefPtr<RootObject> rootObject = findRootObject(exec->dynamicGlobalObject());    if (!rootObject)        return nil;    return [webScriptObjectClass() _convertValueToObjcValue:value originRootObject:rootObject.get() rootObject:rootObject.get()];}void ObjcField::setValueToInstance(ExecState* exec, const Instance* instance, JSValuePtr aValue) const{    id targetObject = (static_cast<const ObjcInstance*>(instance))->getObject();    id value = convertValueToObjcObject(exec, aValue);    JSLock::DropAllLocks dropAllLocks(false); // Can't put this inside the @try scope because it unwinds incorrectly.    @try {        [targetObject setValue:value forKey:(NSString *)_name.get()];    } @catch(NSException* localException) {        JSLock::lock(false);        throwError(exec, GeneralError, [localException reason]);        JSLock::unlock(false);    }}// ---------------------- ObjcArray ----------------------ObjcArray::ObjcArray(ObjectStructPtr a, PassRefPtr<RootObject> rootObject)    : Array(rootObject)    , _array(a){}void ObjcArray::setValueAt(ExecState* exec, unsigned int index, JSValuePtr aValue) const{    if (![_array.get() respondsToSelector:@selector(insertObject:atIndex:)]) {        throwError(exec, TypeError, "Array is not mutable.");        return;    }    if (index > [_array.get() count]) {        throwError(exec, RangeError, "Index exceeds array size.");        return;    }        // Always try to convert the value to an ObjC object, so it can be placed in the    // array.    ObjcValue oValue = convertValueToObjcValue (exec, aValue, ObjcObjectType);    @try {        [_array.get() insertObject:oValue.objectValue atIndex:index];    } @catch(NSException* localException) {        throwError(exec, GeneralError, "Objective-C exception.");    }}JSValuePtr ObjcArray::valueAt(ExecState* exec, unsigned int index) const{    if (index > [_array.get() count])        return throwError(exec, RangeError, "Index exceeds array size.");    @try {        id obj = [_array.get() objectAtIndex:index];        if (obj)            return convertObjcValueToValue (exec, &obj, ObjcObjectType, _rootObject.get());    } @catch(NSException* localException) {        return throwError(exec, GeneralError, "Objective-C exception.");    }    return jsUndefined();}unsigned int ObjcArray::getLength() const{    return [_array.get() count];}const ClassInfo ObjcFallbackObjectImp::s_info = { "ObjcFallbackObject", 0, 0, 0 };ObjcFallbackObjectImp::ObjcFallbackObjectImp(ExecState* exec, ObjcInstance* i, const Identifier& propertyName)    : JSObject(getDOMStructure<ObjcFallbackObjectImp>(exec))    , _instance(i)    , _item(propertyName){}bool ObjcFallbackObjectImp::getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot& slot){    // keep the prototype from getting called instead of just returning false    slot.setUndefined();    return true;}void ObjcFallbackObjectImp::put(ExecState*, const Identifier&, JSValuePtr, PutPropertySlot&){}static JSValuePtr callObjCFallbackObject(ExecState* exec, JSObject* function, JSValuePtr thisValue, const ArgList& args){    if (!thisValue.isObject(&RuntimeObjectImp::s_info))        return throwError(exec, TypeError);    JSValuePtr result = jsUndefined();    RuntimeObjectImp* imp = static_cast<RuntimeObjectImp*>(asObject(thisValue));    Instance* instance = imp->getInternalInstance();    if (!instance)        return RuntimeObjectImp::throwInvalidAccessError(exec);        instance->begin();    ObjcInstance* objcInstance = static_cast<ObjcInstance*>(instance);    id targetObject = objcInstance->getObject();        if ([targetObject respondsToSelector:@selector(invokeUndefinedMethodFromWebScript:withArguments:)]){        ObjcClass* objcClass = static_cast<ObjcClass*>(instance->getClass());        OwnPtr<ObjcMethod> fallbackMethod(new ObjcMethod(objcClass->isa(), @selector(invokeUndefinedMethodFromWebScript:withArguments:)));        const Identifier& nameIdentifier = static_cast<ObjcFallbackObjectImp*>(function)->propertyName();        RetainPtr<CFStringRef> name(AdoptCF, CFStringCreateWithCharacters(0, nameIdentifier.data(), nameIdentifier.size()));        fallbackMethod->setJavaScriptName(name.get());        MethodList methodList;        methodList.append(fallbackMethod.get());        result = instance->invokeMethod(exec, methodList, args);    }                instance->end();    return result;}CallType ObjcFallbackObjectImp::getCallData(CallData& callData){    id targetObject = _instance->getObject();    if (![targetObject respondsToSelector:@selector(invokeUndefinedMethodFromWebScript:withArguments:)])        return CallTypeNone;    callData.native.function = callObjCFallbackObject;    return CallTypeHost;}bool ObjcFallbackObjectImp::deleteProperty(ExecState*, const Identifier&){    return false;}JSValuePtr ObjcFallbackObjectImp::defaultValue(ExecState* exec, PreferredPrimitiveType) const{    return _instance->getValueOfUndefinedField(exec, _item);}bool ObjcFallbackObjectImp::toBoolean(ExecState *) const{    id targetObject = _instance->getObject();        if ([targetObject respondsToSelector:@selector(invokeUndefinedMethodFromWebScript:withArguments:)])        return true;        return false;}}}

⌨️ 快捷键说明

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