diff options
Diffstat (limited to 'WebCore/bindings/objc/WebScriptObject.mm')
-rw-r--r-- | WebCore/bindings/objc/WebScriptObject.mm | 678 |
1 files changed, 0 insertions, 678 deletions
diff --git a/WebCore/bindings/objc/WebScriptObject.mm b/WebCore/bindings/objc/WebScriptObject.mm deleted file mode 100644 index 6bf7afe..0000000 --- a/WebCore/bindings/objc/WebScriptObject.mm +++ /dev/null @@ -1,678 +0,0 @@ -/* - * Copyright (C) 2004, 2006, 2007, 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. - */ - -#import "config.h" -#import "WebScriptObjectPrivate.h" - -#import "Bridge.h" -#import "Console.h" -#import "DOMInternal.h" -#import "DOMWindow.h" -#import "Frame.h" -#import "JSDOMWindow.h" -#import "JSDOMWindowCustom.h" -#import "JSHTMLElement.h" -#import "JSMainThreadExecState.h" -#import "JSPluginElementFunctions.h" -#import "ObjCRuntimeObject.h" -#import "PlatformString.h" -#import "StringSourceProvider.h" -#import "WebCoreObjCExtras.h" -#import "objc_instance.h" -#import "runtime_object.h" -#import "runtime_root.h" -#import <JavaScriptCore/APICast.h> -#import <interpreter/CallFrame.h> -#import <runtime/InitializeThreading.h> -#import <runtime/JSGlobalObject.h> -#import <runtime/JSLock.h> -#import <runtime/Completion.h> -#import <runtime/Completion.h> -#import <wtf/Threading.h> - -#ifdef BUILDING_ON_TIGER -typedef unsigned NSUInteger; -#endif - -using namespace JSC; -using namespace JSC::Bindings; -using namespace WebCore; - -namespace WebCore { - -static NSMapTable* JSWrapperCache; - -NSObject* getJSWrapper(JSObject* impl) -{ - if (!JSWrapperCache) - return nil; - return static_cast<NSObject*>(NSMapGet(JSWrapperCache, impl)); -} - -void addJSWrapper(NSObject* wrapper, JSObject* impl) -{ - if (!JSWrapperCache) - JSWrapperCache = createWrapperCache(); - NSMapInsert(JSWrapperCache, impl, wrapper); -} - -void removeJSWrapper(JSObject* impl) -{ - if (!JSWrapperCache) - return; - NSMapRemove(JSWrapperCache, impl); -} - -id createJSWrapper(JSC::JSObject* object, PassRefPtr<JSC::Bindings::RootObject> origin, PassRefPtr<JSC::Bindings::RootObject> root) -{ - if (id wrapper = getJSWrapper(object)) - return [[wrapper retain] autorelease]; - return [[[WebScriptObject alloc] _initWithJSObject:object originRootObject:origin rootObject:root] autorelease]; -} - -static void addExceptionToConsole(ExecState* exec) -{ - JSDOMWindow* window = asJSDOMWindow(exec->dynamicGlobalObject()); - if (!window || !exec->hadException()) - return; - reportCurrentException(exec); -} - -} // namespace WebCore - -@implementation WebScriptObjectPrivate - -@end - -@implementation WebScriptObject - -+ (void)initialize -{ - JSC::initializeThreading(); - WTF::initializeMainThreadToProcessMainThread(); -#ifndef BUILDING_ON_TIGER - WebCoreObjCFinalizeOnMainThread(self); -#endif -} - -+ (id)scriptObjectForJSObject:(JSObjectRef)jsObject originRootObject:(RootObject*)originRootObject rootObject:(RootObject*)rootObject -{ - if (id domWrapper = createDOMWrapper(toJS(jsObject), originRootObject, rootObject)) - return domWrapper; - - return WebCore::createJSWrapper(toJS(jsObject), originRootObject, rootObject); -} - -static void _didExecute(WebScriptObject *obj) -{ - ASSERT(JSLock::lockCount() > 0); - - RootObject* root = [obj _rootObject]; - if (!root) - return; - - ExecState* exec = root->globalObject()->globalExec(); - KJSDidExecuteFunctionPtr func = Instance::didExecuteFunction(); - if (func) - func(exec, root->globalObject()); -} - -- (void)_setImp:(JSObject*)imp originRootObject:(PassRefPtr<RootObject>)originRootObject rootObject:(PassRefPtr<RootObject>)rootObject -{ - // This function should only be called once, as a (possibly lazy) initializer. - ASSERT(!_private->imp); - ASSERT(!_private->rootObject); - ASSERT(!_private->originRootObject); - ASSERT(imp); - - _private->imp = imp; - _private->rootObject = rootObject.releaseRef(); - _private->originRootObject = originRootObject.releaseRef(); - - WebCore::addJSWrapper(self, imp); - - if (_private->rootObject) - _private->rootObject->gcProtect(imp); -} - -- (void)_setOriginRootObject:(PassRefPtr<RootObject>)originRootObject andRootObject:(PassRefPtr<RootObject>)rootObject -{ - ASSERT(_private->imp); - - if (rootObject) - rootObject->gcProtect(_private->imp); - - if (_private->rootObject && _private->rootObject->isValid()) - _private->rootObject->gcUnprotect(_private->imp); - - if (_private->rootObject) - _private->rootObject->deref(); - - if (_private->originRootObject) - _private->originRootObject->deref(); - - _private->rootObject = rootObject.releaseRef(); - _private->originRootObject = originRootObject.releaseRef(); -} - -- (id)_initWithJSObject:(JSC::JSObject*)imp originRootObject:(PassRefPtr<JSC::Bindings::RootObject>)originRootObject rootObject:(PassRefPtr<JSC::Bindings::RootObject>)rootObject -{ - ASSERT(imp); - - self = [super init]; - _private = [[WebScriptObjectPrivate alloc] init]; - [self _setImp:imp originRootObject:originRootObject rootObject:rootObject]; - - return self; -} - -- (JSObject*)_imp -{ - // Associate the WebScriptObject with the JS wrapper for the ObjC DOM wrapper. - // This is done on lazily, on demand. - if (!_private->imp && _private->isCreatedByDOMWrapper) - [self _initializeScriptDOMNodeImp]; - return [self _rootObject] ? _private->imp : 0; -} - -- (BOOL)_hasImp -{ - return _private->imp != nil; -} - -// Node that DOMNode overrides this method. So you should almost always -// use this method call instead of _private->rootObject directly. -- (RootObject*)_rootObject -{ - return _private->rootObject && _private->rootObject->isValid() ? _private->rootObject : 0; -} - -- (RootObject *)_originRootObject -{ - return _private->originRootObject && _private->originRootObject->isValid() ? _private->originRootObject : 0; -} - -- (BOOL)_isSafeScript -{ - RootObject *root = [self _rootObject]; - if (!root) - return false; - - if (!_private->originRootObject) - return true; - - if (!_private->originRootObject->isValid()) - return false; - - return root->globalObject()->allowsAccessFrom(_private->originRootObject->globalObject()); -} - -- (void)dealloc -{ - if (WebCoreObjCScheduleDeallocateOnMainThread([WebScriptObject class], self)) - return; - - if (_private->imp) - WebCore::removeJSWrapper(_private->imp); - - if (_private->rootObject && _private->rootObject->isValid()) - _private->rootObject->gcUnprotect(_private->imp); - - if (_private->rootObject) - _private->rootObject->deref(); - - if (_private->originRootObject) - _private->originRootObject->deref(); - - [_private release]; - - [super dealloc]; -} - -- (void)finalize -{ - if (_private->rootObject && _private->rootObject->isValid()) - _private->rootObject->gcUnprotect(_private->imp); - - if (_private->rootObject) - _private->rootObject->deref(); - - if (_private->originRootObject) - _private->originRootObject->deref(); - - [super finalize]; -} - -+ (BOOL)throwException:(NSString *)exceptionMessage -{ - ObjcInstance::setGlobalException(exceptionMessage); - return YES; -} - -static void getListFromNSArray(ExecState *exec, NSArray *array, RootObject* rootObject, MarkedArgumentBuffer& aList) -{ - int i, numObjects = array ? [array count] : 0; - - for (i = 0; i < numObjects; i++) { - id anObject = [array objectAtIndex:i]; - aList.append(convertObjcValueToValue(exec, &anObject, ObjcObjectType, rootObject)); - } -} - -- (id)callWebScriptMethod:(NSString *)name withArguments:(NSArray *)args -{ - if (![self _isSafeScript]) - return nil; - - JSLock lock(SilenceAssertionsOnly); - - // Look up the function object. - ExecState* exec = [self _rootObject]->globalObject()->globalExec(); - ASSERT(!exec->hadException()); - - JSValue function = [self _imp]->get(exec, Identifier(exec, stringToUString(String(name)))); - CallData callData; - CallType callType = getCallData(function, callData); - if (callType == CallTypeNone) - return nil; - - MarkedArgumentBuffer argList; - getListFromNSArray(exec, args, [self _rootObject], argList); - - if (![self _isSafeScript]) - return nil; - - [self _rootObject]->globalObject()->globalData().timeoutChecker.start(); - JSValue result = JSMainThreadExecState::call(exec, function, callType, callData, [self _imp], argList); - [self _rootObject]->globalObject()->globalData().timeoutChecker.stop(); - - if (exec->hadException()) { - addExceptionToConsole(exec); - result = jsUndefined(); - exec->clearException(); - } - - // Convert and return the result of the function call. - id resultObj = [WebScriptObject _convertValueToObjcValue:result originRootObject:[self _originRootObject] rootObject:[self _rootObject]]; - - _didExecute(self); - - return resultObj; -} - -- (id)evaluateWebScript:(NSString *)script -{ - if (![self _isSafeScript]) - return nil; - - ExecState* exec = [self _rootObject]->globalObject()->globalExec(); - ASSERT(!exec->hadException()); - - JSValue result; - JSLock lock(SilenceAssertionsOnly); - - [self _rootObject]->globalObject()->globalData().timeoutChecker.start(); - Completion completion = JSMainThreadExecState::evaluate([self _rootObject]->globalObject()->globalExec(), [self _rootObject]->globalObject()->globalScopeChain(), makeSource(String(script)), JSC::JSValue()); - [self _rootObject]->globalObject()->globalData().timeoutChecker.stop(); - ComplType type = completion.complType(); - - if (type == Normal) { - result = completion.value(); - if (!result) - result = jsUndefined(); - } else - result = jsUndefined(); - - if (exec->hadException()) { - addExceptionToConsole(exec); - result = jsUndefined(); - exec->clearException(); - } - - id resultObj = [WebScriptObject _convertValueToObjcValue:result originRootObject:[self _originRootObject] rootObject:[self _rootObject]]; - - _didExecute(self); - - return resultObj; -} - -- (void)setValue:(id)value forKey:(NSString *)key -{ - if (![self _isSafeScript]) - return; - - ExecState* exec = [self _rootObject]->globalObject()->globalExec(); - ASSERT(!exec->hadException()); - - JSLock lock(SilenceAssertionsOnly); - - PutPropertySlot slot; - [self _imp]->put(exec, Identifier(exec, stringToUString(String(key))), convertObjcValueToValue(exec, &value, ObjcObjectType, [self _rootObject]), slot); - - if (exec->hadException()) { - addExceptionToConsole(exec); - exec->clearException(); - } - - _didExecute(self); -} - -- (id)valueForKey:(NSString *)key -{ - if (![self _isSafeScript]) - return nil; - - ExecState* exec = [self _rootObject]->globalObject()->globalExec(); - ASSERT(!exec->hadException()); - - id resultObj; - { - // Need to scope this lock to ensure that we release the lock before calling - // [super valueForKey:key] which might throw an exception and bypass the JSLock destructor, - // leaving the lock permanently held - JSLock lock(SilenceAssertionsOnly); - - JSValue result = [self _imp]->get(exec, Identifier(exec, stringToUString(String(key)))); - - if (exec->hadException()) { - addExceptionToConsole(exec); - result = jsUndefined(); - exec->clearException(); - } - - resultObj = [WebScriptObject _convertValueToObjcValue:result originRootObject:[self _originRootObject] rootObject:[self _rootObject]]; - } - - if ([resultObj isKindOfClass:[WebUndefined class]]) - resultObj = [super valueForKey:key]; // defaults to throwing an exception - - JSLock lock(SilenceAssertionsOnly); - _didExecute(self); - - return resultObj; -} - -- (void)removeWebScriptKey:(NSString *)key -{ - if (![self _isSafeScript]) - return; - - ExecState* exec = [self _rootObject]->globalObject()->globalExec(); - ASSERT(!exec->hadException()); - - JSLock lock(SilenceAssertionsOnly); - [self _imp]->deleteProperty(exec, Identifier(exec, stringToUString(String(key)))); - - if (exec->hadException()) { - addExceptionToConsole(exec); - exec->clearException(); - } - - _didExecute(self); -} - -- (BOOL)hasWebScriptKey:(NSString *)key -{ - if (![self _isSafeScript]) - return NO; - - ExecState* exec = [self _rootObject]->globalObject()->globalExec(); - ASSERT(!exec->hadException()); - - JSLock lock(SilenceAssertionsOnly); - BOOL result = [self _imp]->hasProperty(exec, Identifier(exec, stringToUString(String(key)))); - - if (exec->hadException()) { - addExceptionToConsole(exec); - exec->clearException(); - } - - _didExecute(self); - - return result; -} - -- (NSString *)stringRepresentation -{ - if (![self _isSafeScript]) { - // This is a workaround for a gcc 3.3 internal compiler error. - return @"Undefined"; - } - - JSLock lock(SilenceAssertionsOnly); - ExecState* exec = [self _rootObject]->globalObject()->globalExec(); - - id result = convertValueToObjcValue(exec, [self _imp], ObjcObjectType).objectValue; - - NSString *description = [result description]; - - _didExecute(self); - - return description; -} - -- (id)webScriptValueAtIndex:(unsigned)index -{ - if (![self _isSafeScript]) - return nil; - - ExecState* exec = [self _rootObject]->globalObject()->globalExec(); - ASSERT(!exec->hadException()); - - JSLock lock(SilenceAssertionsOnly); - JSValue result = [self _imp]->get(exec, index); - - if (exec->hadException()) { - addExceptionToConsole(exec); - result = jsUndefined(); - exec->clearException(); - } - - id resultObj = [WebScriptObject _convertValueToObjcValue:result originRootObject:[self _originRootObject] rootObject:[self _rootObject]]; - - _didExecute(self); - - return resultObj; -} - -- (void)setWebScriptValueAtIndex:(unsigned)index value:(id)value -{ - if (![self _isSafeScript]) - return; - - ExecState* exec = [self _rootObject]->globalObject()->globalExec(); - ASSERT(!exec->hadException()); - - JSLock lock(SilenceAssertionsOnly); - [self _imp]->put(exec, index, convertObjcValueToValue(exec, &value, ObjcObjectType, [self _rootObject])); - - if (exec->hadException()) { - addExceptionToConsole(exec); - exec->clearException(); - } - - _didExecute(self); -} - -- (void)setException:(NSString *)description -{ - if (![self _rootObject]) - return; - ObjcInstance::setGlobalException(description, [self _rootObject]->globalObject()); -} - -- (JSObjectRef)JSObject -{ - if (![self _isSafeScript]) - return NULL; - - return toRef([self _imp]); -} - -+ (id)_convertValueToObjcValue:(JSValue)value originRootObject:(RootObject*)originRootObject rootObject:(RootObject*)rootObject -{ - if (value.isObject()) { - JSObject* object = asObject(value); - JSLock lock(SilenceAssertionsOnly); - - if (object->inherits(&JSHTMLElement::s_info)) { - // Plugin elements cache the instance internally. - HTMLElement* el = static_cast<JSHTMLElement*>(object)->impl(); - ObjcInstance* instance = static_cast<ObjcInstance*>(pluginInstance(el)); - if (instance) - return instance->getObject(); - } else if (object->inherits(&ObjCRuntimeObject::s_info)) { - ObjCRuntimeObject* runtimeObject = static_cast<ObjCRuntimeObject*>(object); - ObjcInstance* instance = runtimeObject->getInternalObjCInstance(); - if (instance) - return instance->getObject(); - return nil; - } - - return [WebScriptObject scriptObjectForJSObject:toRef(object) originRootObject:originRootObject rootObject:rootObject]; - } - - if (value.isString()) { - ExecState* exec = rootObject->globalObject()->globalExec(); - const UString& u = asString(value)->value(exec); - return [NSString stringWithCharacters:u.characters() length:u.length()]; - } - - if (value.isNumber()) - return [NSNumber numberWithDouble:value.uncheckedGetNumber()]; - - if (value.isBoolean()) - return [NSNumber numberWithBool:value.getBoolean()]; - - if (value.isUndefined()) - return [WebUndefined undefined]; - - // jsNull is not returned as NSNull because existing applications do not expect - // that return value. Return as nil for compatibility. <rdar://problem/4651318> <rdar://problem/4701626> - // Other types (e.g., UnspecifiedType) also return as nil. - return nil; -} - -@end - -@interface WebScriptObject (WebKitCocoaBindings) - -- (id)objectAtIndex:(unsigned)index; - -@end - -@implementation WebScriptObject (WebKitCocoaBindings) - -#if 0 - -// FIXME: We'd like to add this, but we can't do that until this issue is resolved: -// http://bugs.webkit.org/show_bug.cgi?id=13129: presence of 'count' method on -// WebScriptObject breaks Democracy player. - -- (unsigned)count -{ - id length = [self valueForKey:@"length"]; - if (![length respondsToSelector:@selector(intValue)]) - return 0; - return [length intValue]; -} - -#endif - -- (id)objectAtIndex:(unsigned)index -{ - return [self webScriptValueAtIndex:index]; -} - -@end - -@implementation WebUndefined - -+ (id)allocWithZone:(NSZone *)unusedZone -{ - UNUSED_PARAM(unusedZone); - - static WebUndefined *sharedUndefined = 0; - if (!sharedUndefined) - sharedUndefined = [super allocWithZone:NULL]; - return sharedUndefined; -} - -- (NSString *)description -{ - return @"undefined"; -} - -- (id)initWithCoder:(NSCoder *)unusedCoder -{ - UNUSED_PARAM(unusedCoder); - - return self; -} - -- (void)encodeWithCoder:(NSCoder *)unusedCoder -{ - UNUSED_PARAM(unusedCoder); -} - -- (id)copyWithZone:(NSZone *)unusedZone -{ - UNUSED_PARAM(unusedZone); - - return self; -} - -- (id)retain -{ - return self; -} - -- (void)release -{ -} - -- (NSUInteger)retainCount -{ - return UINT_MAX; -} - -- (id)autorelease -{ - return self; -} - -- (void)dealloc -{ - ASSERT(false); - return; - [super dealloc]; // make -Wdealloc-check happy -} - -+ (WebUndefined *)undefined -{ - return [WebUndefined allocWithZone:NULL]; -} - -@end |