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