source: webkit/trunk/JavaScriptCore/API/JSNode.c@ 17372

Last change on this file since 17372 was 15497, checked in by ggaren, 19 years ago

Reviewed by Maciej.


  • Added automatic prototype creation for classes.


A class stores a weak reference to a prototype, which is cleared when
the prototype is garbage collected, to avoid a reference cycle.


We now have an attributes field in JSClassDefinition, that currently is
used only to override automatic prototype creation when you want to manage your
own prototypes, but can be extended in the future for other nefarious purposes.


Similarly, we have JSObjectMake and JSObjectMakeWithPrototype, the latter
allowing you to manage your own prototypes.


JSObjectMakeConstructor is more interesting now, able to make a constructor
on your behalf if you just give it a class.


  • Removed bogus old code from minidom.js.


  • Tweaked the headerdocs.


  • Added more GC testing, which caught some leaks, and tested more funny edge cases in lookup, which caught a lookup bug. Removed some testing we used to do with MyObject because it was redundant with the new, cool stuff.


While fixing the lookup bug I retracted this change:


"If a static setProperty callback returns 'false', to indicate that the
property was not set, we no longer forward the set request up the class
chain, because that's almost certainly not what the programmer expected."

Returning false when setting a static property is a little silly, but you can see
it being useful when shadowing a base class's static properties, and, regardless
of usefullness, this is the defined behavior of the setProperty callback.


  • Plus a little ASCII art, for the kids.
File size: 7.2 KB
Line 
1// -*- mode: c++; c-basic-offset: 4 -*-
2/*
3 * Copyright (C) 2006 Apple Computer, Inc. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
15 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
18 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
21 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
22 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 */
26
27#include "JSNode.h"
28#include "JSNodeList.h"
29#include "Node.h"
30#include "NodeList.h"
31#include "UnusedParam.h"
32
33static JSValueRef JSNode_appendChild(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
34{
35 UNUSED_PARAM(context);
36 UNUSED_PARAM(function);
37
38 // Example of throwing a type error for invalid values
39 if (!JSValueIsObjectOfClass(context, thisObject, JSNode_class(context))) {
40 JSStringRef message = JSStringCreateWithUTF8CString("TypeError: appendChild can only be called on nodes");
41 *exception = JSValueMakeString(context, message);
42 JSStringRelease(message);
43 } else if (argumentCount < 1 || !JSValueIsObjectOfClass(context, arguments[0], JSNode_class(context))) {
44 JSStringRef message = JSStringCreateWithUTF8CString("TypeError: first argument to appendChild must be a node");
45 *exception = JSValueMakeString(context, message);
46 JSStringRelease(message);
47 } else {
48 Node* node = JSObjectGetPrivate(thisObject);
49 Node* child = JSObjectGetPrivate(JSValueToObject(context, arguments[0], NULL));
50
51 Node_appendChild(node, child);
52 }
53
54 return JSValueMakeUndefined(context);
55}
56
57static JSValueRef JSNode_removeChild(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
58{
59 UNUSED_PARAM(context);
60 UNUSED_PARAM(function);
61
62 // Example of ignoring invalid values
63 if (argumentCount > 0) {
64 if (JSValueIsObjectOfClass(context, thisObject, JSNode_class(context))) {
65 if (JSValueIsObjectOfClass(context, arguments[0], JSNode_class(context))) {
66 Node* node = JSObjectGetPrivate(thisObject);
67 Node* child = JSObjectGetPrivate(JSValueToObject(context, arguments[0], NULL));
68
69 Node_removeChild(node, child);
70 }
71 }
72 }
73
74 return JSValueMakeUndefined(context);
75}
76
77static JSValueRef JSNode_replaceChild(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
78{
79 UNUSED_PARAM(context);
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], NULL));
88 Node* oldChild = JSObjectGetPrivate(JSValueToObject(context, arguments[1], NULL));
89
90 Node_replaceChild(node, newChild, oldChild);
91 }
92 }
93 }
94 }
95
96 return JSValueMakeUndefined(context);
97}
98
99static JSStaticFunction JSNode_staticFunctions[] = {
100 { "appendChild", JSNode_appendChild, kJSPropertyAttributeDontDelete },
101 { "removeChild", JSNode_removeChild, kJSPropertyAttributeDontDelete },
102 { "replaceChild", JSNode_replaceChild, kJSPropertyAttributeDontDelete },
103 { 0, 0, 0 }
104};
105
106static JSValueRef JSNode_getNodeType(JSContextRef context, JSObjectRef object, JSStringRef propertyName, JSValueRef* exception)
107{
108 UNUSED_PARAM(context);
109 UNUSED_PARAM(propertyName);
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
122static JSValueRef JSNode_getChildNodes(JSContextRef context, JSObjectRef thisObject, JSStringRef propertyName, JSValueRef* exception)
123{
124 UNUSED_PARAM(propertyName);
125 Node* node = JSObjectGetPrivate(thisObject);
126 assert(node);
127 return JSNodeList_new(context, NodeList_new(node));
128}
129
130static JSValueRef JSNode_getFirstChild(JSContextRef context, JSObjectRef object, JSStringRef propertyName, JSValueRef* exception)
131{
132 UNUSED_PARAM(context);
133 UNUSED_PARAM(propertyName);
134 UNUSED_PARAM(object);
135
136 return JSValueMakeUndefined(context);
137}
138
139static JSStaticValue JSNode_staticValues[] = {
140 { "nodeType", JSNode_getNodeType, NULL, kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly },
141 { "childNodes", JSNode_getChildNodes, NULL, kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly },
142 { "firstChild", JSNode_getFirstChild, NULL, kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly },
143 { 0, 0, 0, 0 }
144};
145
146static void JSNode_initialize(JSContextRef context, JSObjectRef object)
147{
148 Node* node = JSObjectGetPrivate(object);
149 assert(node);
150
151 Node_ref(node);
152}
153
154static void JSNode_finalize(JSObjectRef object)
155{
156 Node* node = JSObjectGetPrivate(object);
157 assert(node);
158
159 Node_deref(node);
160}
161
162JSClassRef JSNode_class(JSContextRef context)
163{
164 static JSClassRef jsClass;
165 if (!jsClass) {
166 JSClassDefinition definition = kJSClassDefinitionEmpty;
167 definition.staticValues = JSNode_staticValues;
168 definition.staticFunctions = JSNode_staticFunctions;
169 definition.initialize = JSNode_initialize;
170 definition.finalize = JSNode_finalize;
171
172 jsClass = JSClassCreate(&definition);
173 }
174 return jsClass;
175}
176
177JSObjectRef JSNode_new(JSContextRef context, Node* node)
178{
179 return JSObjectMake(context, JSNode_class(context), node);
180}
181
182JSObjectRef JSNode_construct(JSContextRef context, JSObjectRef object, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
183{
184 UNUSED_PARAM(object);
185 UNUSED_PARAM(argumentCount);
186 UNUSED_PARAM(arguments);
187
188 return JSNode_new(context, Node_new());
189}
Note: See TracBrowser for help on using the repository browser.