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 38 static NSMapTable* DOMWrapperCache; 39 40 NSMapTable* 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 52 NSObject* getDOMWrapper(DOMObjectInternal* impl) 53 { 54 if (!DOMWrapperCache) 55 return nil; 56 return static_cast<NSObject*>(NSMapGet(DOMWrapperCache, impl)); 57 } 58 59 void addDOMWrapper(NSObject* wrapper, DOMObjectInternal* impl) 60 { 61 if (!DOMWrapperCache) 62 DOMWrapperCache = createWrapperCache(); 63 NSMapInsert(DOMWrapperCache, impl, wrapper); 64 } 65 66 void 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