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 COMPUTER, 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 COMPUTER, 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 "WebScriptObjectPrivate.h" 33#import "runtime_root.h" 34 35//------------------------------------------------------------------------------------------ 36// Wrapping WebCore implementation objects 37 38static NSMapTable* DOMWrapperCache; 39 40NSMapTable* createWrapperCache() 41{ 42#ifdef BUILDING_ON_TIGER 43 return NSCreateMapTable(NSNonOwnedPointerMapKeyCallBacks, NSNonRetainedObjectMapValueCallBacks, 0); 44#else 45 // NSMapTable with zeroing weak pointers is the recommended way to build caches like this under garbage collection. 46 NSPointerFunctionsOptions keyOptions = NSPointerFunctionsOpaqueMemory | NSPointerFunctionsOpaquePersonality; 47 NSPointerFunctionsOptions valueOptions = NSPointerFunctionsZeroingWeakMemory | NSPointerFunctionsObjectPersonality; 48 return [[NSMapTable alloc] initWithKeyOptions:keyOptions valueOptions:valueOptions capacity:0]; 49#endif 50} 51 52NSObject* getDOMWrapper(DOMObjectInternal* impl) 53{ 54 if (!DOMWrapperCache) 55 return nil; 56 return static_cast<NSObject*>(NSMapGet(DOMWrapperCache, impl)); 57} 58 59void addDOMWrapper(NSObject* wrapper, DOMObjectInternal* impl) 60{ 61 if (!DOMWrapperCache) 62 DOMWrapperCache = createWrapperCache(); 63 NSMapInsert(DOMWrapperCache, impl, wrapper); 64} 65 66void removeDOMWrapper(DOMObjectInternal* impl) 67{ 68 if (!DOMWrapperCache) 69 return; 70 NSMapRemove(DOMWrapperCache, impl); 71} 72 73//------------------------------------------------------------------------------------------ 74 75@implementation WebScriptObject (WebScriptObjectInternal) 76 77// Only called by DOMObject subclass. 78- (id)_init 79{ 80 self = [super init]; 81 82 if (![self isKindOfClass:[DOMObject class]]) { 83 [NSException raise:NSGenericException format:@"+%@: _init is an internal initializer", [self class]]; 84 return nil; 85 } 86 87 _private = [[WebScriptObjectPrivate alloc] init]; 88 _private->isCreatedByDOMWrapper = YES; 89 90 return self; 91} 92 93- (void)_initializeScriptDOMNodeImp 94{ 95 ASSERT(_private->isCreatedByDOMWrapper); 96 97 if (![self isKindOfClass:[DOMNode class]]) { 98 // DOMObject can't map back to a document, and thus an interpreter, 99 // so for now only create wrappers for DOMNodes. 100 NSLog(@"%s:%d: We don't know how to create ObjC JS wrappers from DOMObjects yet.", __FILE__, __LINE__); 101 return; 102 } 103 104 // Extract the WebCore::Node from the ObjectiveC wrapper. 105 DOMNode *n = (DOMNode *)self; 106 WebCore::Node *nodeImpl = core(n); 107 108 // Dig up Interpreter and ExecState. 109 WebCore::Frame *frame = 0; 110 if (WebCore::Document* document = nodeImpl->document()) 111 frame = document->frame(); 112 if (!frame) 113 return; 114 115 // The global object which should own this node - FIXME: does this need to be isolated-world aware? 116 WebCore::JSDOMGlobalObject* globalObject = frame->script()->globalObject(WebCore::mainThreadNormalWorld()); 117 JSC::ExecState *exec = globalObject->globalExec(); 118 119 // Get (or create) a cached JS object for the DOM node. 120 JSC::JSObject *scriptImp = asObject(WebCore::toJS(exec, globalObject, nodeImpl)); 121 122 JSC::Bindings::RootObject* rootObject = frame->script()->bindingRootObject(); 123 124 [self _setImp:scriptImp originRootObject:rootObject rootObject:rootObject]; 125} 126 127@end 128