1/* 2 * Copyright (C) 2004, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * 2. Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY 14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR 17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 */ 25 26#import "config.h" 27#import "DOMInternal.h" 28 29#import "DOMNodeInternal.h" 30#import "Frame.h" 31#import "JSNode.h" 32#import "ScriptController.h" 33#import "WebScriptObjectPrivate.h" 34#import "runtime_root.h" 35 36#if PLATFORM(IOS) 37#define NEEDS_WRAPPER_CACHE_LOCK 1 38#endif 39 40//------------------------------------------------------------------------------------------ 41// Wrapping WebCore implementation objects 42 43static NSMapTable* DOMWrapperCache; 44 45#ifdef NEEDS_WRAPPER_CACHE_LOCK 46static Mutex& wrapperCacheLock() 47{ 48 DEPRECATED_DEFINE_STATIC_LOCAL(Mutex, wrapperCacheMutex, ()); 49 return wrapperCacheMutex; 50} 51#endif 52 53#if COMPILER(CLANG) 54#pragma clang diagnostic push 55#pragma clang diagnostic ignored "-Wdeprecated-declarations" 56#endif 57 58NSMapTable* createWrapperCache() 59{ 60 // NSMapTable with zeroing weak pointers is the recommended way to build caches like this under garbage collection. 61 NSPointerFunctionsOptions keyOptions = NSPointerFunctionsOpaqueMemory | NSPointerFunctionsOpaquePersonality; 62 NSPointerFunctionsOptions valueOptions = NSPointerFunctionsZeroingWeakMemory | NSPointerFunctionsObjectPersonality; 63 return [[NSMapTable alloc] initWithKeyOptions:keyOptions valueOptions:valueOptions capacity:0]; 64} 65 66#if COMPILER(CLANG) 67#pragma clang diagnostic pop 68#endif 69 70NSObject* getDOMWrapper(DOMObjectInternal* impl) 71{ 72#ifdef NEEDS_WRAPPER_CACHE_LOCK 73 MutexLocker locker(wrapperCacheLock()); 74#endif 75 if (!DOMWrapperCache) 76 return nil; 77 return static_cast<NSObject*>(NSMapGet(DOMWrapperCache, impl)); 78} 79 80void addDOMWrapper(NSObject* wrapper, DOMObjectInternal* impl) 81{ 82#ifdef NEEDS_WRAPPER_CACHE_LOCK 83 MutexLocker locker(wrapperCacheLock()); 84#endif 85 if (!DOMWrapperCache) 86 DOMWrapperCache = createWrapperCache(); 87 NSMapInsert(DOMWrapperCache, impl, wrapper); 88} 89 90void removeDOMWrapper(DOMObjectInternal* impl) 91{ 92#ifdef NEEDS_WRAPPER_CACHE_LOCK 93 MutexLocker locker(wrapperCacheLock()); 94#endif 95 if (!DOMWrapperCache) 96 return; 97 NSMapRemove(DOMWrapperCache, impl); 98} 99 100//------------------------------------------------------------------------------------------ 101 102@implementation WebScriptObject (WebScriptObjectInternal) 103 104// Only called by DOMObject subclass. 105- (id)_init 106{ 107 self = [super init]; 108 109 if (![self isKindOfClass:[DOMObject class]]) { 110 [NSException raise:NSGenericException format:@"+%@: _init is an internal initializer", [self class]]; 111 return nil; 112 } 113 114 _private = [[WebScriptObjectPrivate alloc] init]; 115 _private->isCreatedByDOMWrapper = YES; 116 117 return self; 118} 119 120- (void)_initializeScriptDOMNodeImp 121{ 122 ASSERT(_private->isCreatedByDOMWrapper); 123 124 if (![self isKindOfClass:[DOMNode class]]) { 125 // DOMObject can't map back to a document, and thus an interpreter, 126 // so for now only create wrappers for DOMNodes. 127 NSLog(@"%s:%d: We don't know how to create ObjC JS wrappers from DOMObjects yet.", __FILE__, __LINE__); 128 return; 129 } 130 131 // Extract the WebCore::Node from the ObjectiveC wrapper. 132 DOMNode *n = (DOMNode *)self; 133 WebCore::Node *nodeImpl = core(n); 134 135 // Dig up Interpreter and ExecState. 136 WebCore::Frame *frame = nodeImpl->document().frame(); 137 if (!frame) 138 return; 139 140 // The global object which should own this node - FIXME: does this need to be isolated-world aware? 141 WebCore::JSDOMGlobalObject* globalObject = frame->script().globalObject(WebCore::mainThreadNormalWorld()); 142 JSC::ExecState *exec = globalObject->globalExec(); 143 144 // Get (or create) a cached JS object for the DOM node. 145 JSC::JSObject *scriptImp = asObject(WebCore::toJS(exec, globalObject, nodeImpl)); 146 147 JSC::Bindings::RootObject* rootObject = frame->script().bindingRootObject(); 148 149 [self _setImp:scriptImp originRootObject:rootObject rootObject:rootObject]; 150} 151 152@end 153