1/* 2 * Copyright (C) 2006 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#include <wtf/Platform.h> 27 28#include "JSNode.h" 29#include "JSNodeList.h" 30#include "JSObjectRef.h" 31#include "JSStringRef.h" 32#include "JSValueRef.h" 33#include "Node.h" 34#include "NodeList.h" 35#include <wtf/Assertions.h> 36 37static JSValueRef JSNode_appendChild(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) 38{ 39 UNUSED_PARAM(function); 40 41 /* Example of throwing a type error for invalid values */ 42 if (!JSValueIsObjectOfClass(context, thisObject, JSNode_class(context))) { 43 JSStringRef message = JSStringCreateWithUTF8CString("TypeError: appendChild can only be called on nodes"); 44 *exception = JSValueMakeString(context, message); 45 JSStringRelease(message); 46 } else if (argumentCount < 1 || !JSValueIsObjectOfClass(context, arguments[0], JSNode_class(context))) { 47 JSStringRef message = JSStringCreateWithUTF8CString("TypeError: first argument to appendChild must be a node"); 48 *exception = JSValueMakeString(context, message); 49 JSStringRelease(message); 50 } else { 51 Node* node = JSObjectGetPrivate(thisObject); 52 Node* child = JSObjectGetPrivate(JSValueToObject(context, arguments[0], NULL)); 53 54 Node_appendChild(node, child); 55 } 56 57 return JSValueMakeUndefined(context); 58} 59 60static JSValueRef JSNode_removeChild(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) 61{ 62 UNUSED_PARAM(function); 63 64 /* Example of ignoring invalid values */ 65 if (argumentCount > 0) { 66 if (JSValueIsObjectOfClass(context, thisObject, JSNode_class(context))) { 67 if (JSValueIsObjectOfClass(context, arguments[0], JSNode_class(context))) { 68 Node* node = JSObjectGetPrivate(thisObject); 69 Node* child = JSObjectGetPrivate(JSValueToObject(context, arguments[0], exception)); 70 71 Node_removeChild(node, child); 72 } 73 } 74 } 75 76 return JSValueMakeUndefined(context); 77} 78 79static JSValueRef JSNode_replaceChild(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) 80{ 81 UNUSED_PARAM(function); 82 83 if (argumentCount > 1) { 84 if (JSValueIsObjectOfClass(context, thisObject, JSNode_class(context))) { 85 if (JSValueIsObjectOfClass(context, arguments[0], JSNode_class(context))) { 86 if (JSValueIsObjectOfClass(context, arguments[1], JSNode_class(context))) { 87 Node* node = JSObjectGetPrivate(thisObject); 88 Node* newChild = JSObjectGetPrivate(JSValueToObject(context, arguments[0], exception)); 89 Node* oldChild = JSObjectGetPrivate(JSValueToObject(context, arguments[1], exception)); 90 91 Node_replaceChild(node, newChild, oldChild); 92 } 93 } 94 } 95 } 96 97 return JSValueMakeUndefined(context); 98} 99 100static JSStaticFunction JSNode_staticFunctions[] = { 101 { "appendChild", JSNode_appendChild, kJSPropertyAttributeDontDelete }, 102 { "removeChild", JSNode_removeChild, kJSPropertyAttributeDontDelete }, 103 { "replaceChild", JSNode_replaceChild, kJSPropertyAttributeDontDelete }, 104 { 0, 0, 0 } 105}; 106 107static JSValueRef JSNode_getNodeType(JSContextRef context, JSObjectRef object, JSStringRef propertyName, JSValueRef* exception) 108{ 109 UNUSED_PARAM(propertyName); 110 UNUSED_PARAM(exception); 111 112 Node* node = JSObjectGetPrivate(object); 113 if (node) { 114 JSStringRef nodeType = JSStringCreateWithUTF8CString(node->nodeType); 115 JSValueRef value = JSValueMakeString(context, nodeType); 116 JSStringRelease(nodeType); 117 return value; 118 } 119 120 return NULL; 121} 122 123static JSValueRef JSNode_getChildNodes(JSContextRef context, JSObjectRef thisObject, JSStringRef propertyName, JSValueRef* exception) 124{ 125 UNUSED_PARAM(propertyName); 126 UNUSED_PARAM(exception); 127 128 Node* node = JSObjectGetPrivate(thisObject); 129 ASSERT(node); 130 return JSNodeList_new(context, NodeList_new(node)); 131} 132 133static JSValueRef JSNode_getFirstChild(JSContextRef context, JSObjectRef object, JSStringRef propertyName, JSValueRef* exception) 134{ 135 UNUSED_PARAM(object); 136 UNUSED_PARAM(propertyName); 137 UNUSED_PARAM(exception); 138 139 return JSValueMakeUndefined(context); 140} 141 142static JSStaticValue JSNode_staticValues[] = { 143 { "nodeType", JSNode_getNodeType, NULL, kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly }, 144 { "childNodes", JSNode_getChildNodes, NULL, kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly }, 145 { "firstChild", JSNode_getFirstChild, NULL, kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly }, 146 { 0, 0, 0, 0 } 147}; 148 149static void JSNode_initialize(JSContextRef context, JSObjectRef object) 150{ 151 UNUSED_PARAM(context); 152 153 Node* node = JSObjectGetPrivate(object); 154 ASSERT(node); 155 156 Node_ref(node); 157} 158 159static void JSNode_finalize(JSObjectRef object) 160{ 161 Node* node = JSObjectGetPrivate(object); 162 ASSERT(node); 163 164 Node_deref(node); 165} 166 167JSClassRef JSNode_class(JSContextRef context) 168{ 169 UNUSED_PARAM(context); 170 171 static JSClassRef jsClass; 172 if (!jsClass) { 173 JSClassDefinition definition = kJSClassDefinitionEmpty; 174 definition.staticValues = JSNode_staticValues; 175 definition.staticFunctions = JSNode_staticFunctions; 176 definition.initialize = JSNode_initialize; 177 definition.finalize = JSNode_finalize; 178 179 jsClass = JSClassCreate(&definition); 180 } 181 return jsClass; 182} 183 184JSObjectRef JSNode_new(JSContextRef context, Node* node) 185{ 186 return JSObjectMake(context, JSNode_class(context), node); 187} 188 189JSObjectRef JSNode_construct(JSContextRef context, JSObjectRef object, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) 190{ 191 UNUSED_PARAM(object); 192 UNUSED_PARAM(argumentCount); 193 UNUSED_PARAM(arguments); 194 UNUSED_PARAM(exception); 195 196 return JSNode_new(context, Node_new()); 197} 198