DOMNode.mm   [plain text]

/*
* Copyright (C) 2004-2016 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 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 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 "DOMNodeInternal.h"

#import "DOMDocumentInternal.h"
#import "DOMElementInternal.h"
#import "DOMEventInternal.h"
#import "DOMInternal.h"
#import "DOMNamedNodeMapInternal.h"
#import "DOMNodeListInternal.h"
#import "ExceptionHandlers.h"
#import "ObjCEventListener.h"
#import <WebCore/DOMImplementation.h>
#import <WebCore/Element.h>
#import <WebCore/JSMainThreadExecState.h>
#import <WebCore/NodeList.h>
#import <WebCore/SVGTests.h>
#import <WebCore/ThreadCheck.h>
#import <WebCore/WebCoreObjCExtras.h>
#import <WebCore/WebScriptObjectPrivate.h>

using namespace WebCore;

static inline Node& unwrap(DOMNode& wrapper)
{
ASSERT(wrapper._internal);
return reinterpret_cast<Node&>(*wrapper._internal);
}

Node* core(DOMNode *wrapper)
{
return wrapper ? &unwrap(*wrapper) : nullptr;
}

DOMNode *kit(Node* value)
{
WebCoreThreadViolationCheckRoundOne();
if (!value)
return nil;
if (DOMNode *wrapper = getDOMWrapper(value))
return [[wrapper retain] autorelease];
DOMNode *wrapper = [[kitClass(value) alloc] _init];
if (!wrapper)
return nil;
wrapper->_internal = reinterpret_cast<DOMObjectInternal*>(value);
value->ref();
addDOMWrapper(wrapper, value);
return [wrapper autorelease];
}

@implementation DOMNode

- (void)dealloc
{
if (WebCoreObjCScheduleDeallocateOnMainThread([DOMNode class], self))
return;
if (_internal)
unwrap(*self).deref();
[super dealloc];
}

- (NSString *)nodeName
{
JSMainThreadNullState state;
return unwrap(*self).nodeName();
}

- (NSString *)nodeValue
{
JSMainThreadNullState state;
return unwrap(*self).nodeValue();
}

- (void)setNodeValue:(NSString *)newNodeValue
{
JSMainThreadNullState state;
raiseOnDOMError(unwrap(*self).setNodeValue(newNodeValue));
}

- (unsigned short)nodeType
{
JSMainThreadNullState state;
return unwrap(*self).nodeType();
}

- (DOMNode *)parentNode
{
JSMainThreadNullState state;
return kit(unwrap(*self).parentNode());
}

- (DOMNodeList *)childNodes
{
JSMainThreadNullState state;
return kit(unwrap(*self).childNodes().get());
}

- (DOMNode *)firstChild
{
JSMainThreadNullState state;
return kit(unwrap(*self).firstChild());
}

- (DOMNode *)lastChild
{
JSMainThreadNullState state;
return kit(unwrap(*self).lastChild());
}

- (DOMNode *)previousSibling
{
JSMainThreadNullState state;
return kit(unwrap(*self).previousSibling());
}

- (DOMNode *)nextSibling
{
JSMainThreadNullState state;
return kit(unwrap(*self).nextSibling());
}

- (DOMDocument *)ownerDocument
{
JSMainThreadNullState state;
return kit(&unwrap(*self).document());
}

- (NSString *)namespaceURI
{
JSMainThreadNullState state;
return unwrap(*self).namespaceURI();
}

- (NSString *)prefix
{
JSMainThreadNullState state;
return unwrap(*self).prefix();
}

- (void)setPrefix:(NSString *)newPrefix
{
JSMainThreadNullState state;
raiseOnDOMError(unwrap(*self).setPrefix(newPrefix));
}

- (NSString *)localName
{
JSMainThreadNullState state;
return unwrap(*self).localName();
}

- (DOMNamedNodeMap *)attributes
{
JSMainThreadNullState state;
return kit(unwrap(*self).attributes());
}

- (NSString *)baseURI
{
JSMainThreadNullState state;
return unwrap(*self).baseURI();
}

- (NSString *)textContent
{
JSMainThreadNullState state;
return unwrap(*self).textContent();
}

- (void)setTextContent:(NSString *)newTextContent
{
JSMainThreadNullState state;
raiseOnDOMError(unwrap(*self).setTextContent(newTextContent));
}

- (BOOL)isConnected
{
JSMainThreadNullState state;
return unwrap(*self).isConnected();
}

- (DOMElement *)parentElement
{
JSMainThreadNullState state;
return kit(unwrap(*self).parentElement());
}

- (BOOL)isContentEditable
{
JSMainThreadNullState state;
return unwrap(*self).isContentEditable();
}

- (DOMNode *)insertBefore:(DOMNode *)newChild refChild:(DOMNode *)refChild
{
JSMainThreadNullState state;
if (!newChild)
raiseTypeErrorException();
raiseOnDOMError(unwrap(*self).insertBefore(*core(newChild), core(refChild)));
return newChild;
}

- (DOMNode *)replaceChild:(DOMNode *)newChild oldChild:(DOMNode *)oldChild
{
JSMainThreadNullState state;
if (!newChild)
raiseTypeErrorException();
if (!oldChild)
raiseTypeErrorException();
raiseOnDOMError(unwrap(*self).replaceChild(*core(newChild), *core(oldChild)));
return oldChild;
}

- (DOMNode *)removeChild:(DOMNode *)oldChild
{
JSMainThreadNullState state;
if (!oldChild)
raiseTypeErrorException();
raiseOnDOMError(unwrap(*self).removeChild(*core(oldChild)));
return oldChild;
}

- (DOMNode *)appendChild:(DOMNode *)newChild
{
JSMainThreadNullState state;
if (!newChild)
raiseTypeErrorException();
raiseOnDOMError(unwrap(*self).appendChild(*core(newChild)));
return newChild;
}

- (BOOL)hasChildNodes
{
JSMainThreadNullState state;
return unwrap(*self).hasChildNodes();
}

- (DOMNode *)cloneNode:(BOOL)deep
{
JSMainThreadNullState state;
return kit(raiseOnDOMError(unwrap(*self).cloneNodeForBindings(deep)).ptr());
}

- (void)normalize
{
JSMainThreadNullState state;
unwrap(*self).normalize();
}

- (BOOL)isSupported:(NSString *)feature version:(NSString *)version
{
return SVGTests::hasFeatureForLegacyBindings(feature, version);
}

- (BOOL)hasAttributes
{
JSMainThreadNullState state;
return unwrap(*self).hasAttributes();
}

- (BOOL)isSameNode:(DOMNode *)other
{
JSMainThreadNullState state;
return unwrap(*self).isSameNode(core(other));
}

- (BOOL)isEqualNode:(DOMNode *)other
{
JSMainThreadNullState state;
return unwrap(*self).isEqualNode(core(other));
}

- (NSString *)lookupPrefix:(NSString *)inNamespaceURI
{
JSMainThreadNullState state;
return unwrap(*self).lookupPrefix(inNamespaceURI);
}

- (NSString *)lookupNamespaceURI:(NSString *)inPrefix
{
JSMainThreadNullState state;
return unwrap(*self).lookupNamespaceURI(inPrefix);
}

- (BOOL)isDefaultNamespace:(NSString *)inNamespaceURI
{
JSMainThreadNullState state;
return unwrap(*self).isDefaultNamespace(inNamespaceURI);
}

- (unsigned short)compareDocumentPosition:(DOMNode *)other
{
JSMainThreadNullState state;
if (!other)
return Node::DOCUMENT_POSITION_DISCONNECTED;
return unwrap(*self).compareDocumentPosition(*core(other));
}

- (BOOL)contains:(DOMNode *)other
{
JSMainThreadNullState state;
return unwrap(*self).contains(core(other));
}

- (void)inspect
{
JSMainThreadNullState state;
unwrap(*self).inspect();
}

- (void)addEventListener:(NSString *)type listener:(id <DOMEventListener>)listener useCapture:(BOOL)useCapture
{
JSMainThreadNullState state;
unwrap(*self).addEventListenerForBindings(type, ObjCEventListener::wrap(listener), static_cast<bool>(useCapture));
}

- (void)addEventListener:(NSString *)type :(id <DOMEventListener>)listener :(BOOL)useCapture
{
JSMainThreadNullState state;
unwrap(*self).addEventListenerForBindings(type, ObjCEventListener::wrap(listener), static_cast<bool>(useCapture));
}

- (void)removeEventListener:(NSString *)type listener:(id <DOMEventListener>)listener useCapture:(BOOL)useCapture
{
JSMainThreadNullState state;
unwrap(*self).removeEventListenerForBindings(type, ObjCEventListener::wrap(listener), static_cast<bool>(useCapture));
}

- (void)removeEventListener:(NSString *)type :(id <DOMEventListener>)listener :(BOOL)useCapture
{
JSMainThreadNullState state;
unwrap(*self).removeEventListenerForBindings(type, ObjCEventListener::wrap(listener), static_cast<bool>(useCapture));
}

- (BOOL)dispatchEvent:(DOMEvent *)event
{
JSMainThreadNullState state;
if (!event)
raiseTypeErrorException();
return raiseOnDOMError(unwrap(*self).dispatchEventForBindings(*core(event)));
}

@end

@implementation DOMNode (DOMNodeDeprecated)

- (DOMNode *)insertBefore:(DOMNode *)newChild :(DOMNode *)refChild
{
return [self insertBefore:newChild refChild:refChild];
}

- (DOMNode *)replaceChild:(DOMNode *)newChild :(DOMNode *)oldChild
{
return [self replaceChild:newChild oldChild:oldChild];
}

- (BOOL)isSupported:(NSString *)feature :(NSString *)version
{
return [self isSupported:feature version:version];
}

@end