1 /*
2  * The contents of this file are subject to the Mozilla Public
3  * License Version 1.1 (the "License"); you may not use this file
4  * except in compliance with the License. You may obtain a copy of
5  * the License at http://www.mozilla.org/MPL/
6  *
7  * Software distributed under the License is distributed on an "AS
8  * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
9  * implied. See the License for the specific language governing
10  * rights and limitations under the License.
11  *
12  * The Original Code is the Sablotron XSLT Processor.
13  *
14  * The Initial Developer of the Original Code is Ginger Alliance Ltd.
15  * Portions created by Ginger Alliance are Copyright (C) 2000-2002
16  * Ginger Alliance Ltd. All Rights Reserved.
17  *
18  * Contributor(s): Han Qi
19  *
20  * Alternatively, the contents of this file may be used under the
21  * terms of the GNU General Public License Version 2 or later (the
22  * "GPL"), in which case the provisions of the GPL are applicable
23  * instead of those above.  If you wish to allow use of your
24  * version of this file only under the terms of the GPL and not to
25  * allow others to use your version of this file under the MPL,
26  * indicate your decision by deleting the provisions above and
27  * replace them with the notice and other provisions required by
28  * the GPL.  If you do not delete the provisions above, a recipient
29  * may use your version of this file under either the MPL or the
30  * GPL.
31  */
32 
33 #include "jsdom.h"
34 
35 #ifdef ENABLE_JS
36 
37 #define SablotAsExport
38 #include "base.h"
39 #include "sdom.h"
40 #include "verts.h"
41 
42 #define declPRIV  NodePrivate *np = (NodePrivate*)JS_GetPrivate(cx, obj)
43 #define NPDOM np->situa->dom()
44 
45 /************************ domex  *********************/
46 
domexFinalize(JSContext * cx,JSObject * obj)47 void domexFinalize(JSContext *cx, JSObject *obj)
48 {
49   DomExPrivate *priv = (DomExPrivate*)JS_GetPrivate(cx, obj);
50   if (priv) {
51     delete priv;
52   }
53 }
54 
55 JSClass domexClass = {
56   "DOMException",
57   JSCLASS_HAS_PRIVATE,
58   JS_PropertyStub, JS_PropertyStub,
59   JS_PropertyStub,
60   JS_PropertyStub,
61   JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub,
62   domexFinalize, 0, 0, NULL, NULL, NULL, NULL, 0, 0
63 };
64 
domexGetProperty(JSContext * cx,JSObject * obj,jsval id,jsval * vp)65 JSBool domexGetProperty (JSContext *cx, JSObject *obj, jsval id, jsval *vp)
66 {
67   *vp = id;
68   return TRUE;
69 }
70 
JS_PROP(domexGetCode)71 JS_PROP(domexGetCode)
72 {
73   DomExPrivate *priv = (DomExPrivate*)JS_GetPrivate(cx, obj);
74   *rval = INT_TO_JSVAL(priv -> code);
75   return TRUE;
76 }
77 
78 JSPropertySpec domexProtoProps[] =
79 {
80   {"INDEX_SIZE_ERR", 1, PROP_OPT, domexGetProperty, NULL},
81   {"STRING_SIZE_ERR", 2, PROP_OPT, domexGetProperty, NULL},
82   {"HIERARCHY_REQUEST_ERR", 3, PROP_OPT, domexGetProperty, NULL},
83   {"WRONG_DOCUMENT_ERR", 4, PROP_OPT, domexGetProperty, NULL},
84   {"INVALID_CHARACTER_ERR", 5, PROP_OPT, domexGetProperty, NULL},
85   {"NO_DATA_ALLOWED_ERR", 6, PROP_OPT, domexGetProperty, NULL},
86   {"NO_MODIFICATION_ALLOWED_ERR", 7, PROP_OPT, domexGetProperty, NULL},
87   {"NOT_FOUND_ERR", 8, PROP_OPT, domexGetProperty, NULL},
88   {"NOT_SUPPORTED_ERR", 9, PROP_OPT, domexGetProperty, NULL},
89   {"INUSE_ATTRIBUTE_ERR", 10, PROP_OPT, domexGetProperty, NULL},
90   {"INVALID_STATE_ERR", 11, PROP_OPT, domexGetProperty, NULL},
91   {"SYNTAX_ERR", 12, PROP_OPT, domexGetProperty, NULL},
92   {"INVALID_MODIFICATION_ERR", 13, PROP_OPT, domexGetProperty, NULL},
93   {"NAMESPACE_ERR", 14, PROP_OPT, domexGetProperty, NULL},
94   {"INVALID_ACCESS_ERR", 15, PROP_OPT, domexGetProperty, NULL},
95   {NULL, 0, 0, 0, 0}
96 };
97 
JS_METHOD(domexToString)98 JS_METHOD(domexToString)
99 {
100   DomExPrivate *priv = (DomExPrivate*)JS_GetPrivate(cx, obj);
101   char buff[128];
102   //find the entry
103   JSPropertySpec* aux = domexProtoProps;
104   while (aux -> name)
105     {
106       if (aux -> tinyid == priv -> code) break;
107       aux++;
108     }
109 
110   sprintf(buff, "[DOMException %d = %s]", priv -> code,
111 	  aux -> name ? aux -> name : "unknown code");
112   JSString *str = JS_NewStringCopyZ(cx, buff);
113   *rval = STRING_TO_JSVAL(str);
114   return TRUE;
115 }
116 
117 JSPropertySpec domexProps[] =
118 {
119   {"code", 0, PROP_OPT, domexGetCode, NULL},
120   {NULL, 0, 0, 0, 0}
121 };
122 
123 JSFunctionSpec domexFunctions[] =
124 {
125   {"toString", domexToString, 0, 0, 0},
126   {NULL, 0, 0, 0, 0}
127 };
128 
129 /***************nodelist array **********************/
130 
JS_METHOD(nlistItem)131 JS_METHOD(nlistItem)
132 {
133   JSBool rv;
134   if (argc >= 1) {
135     rv = JS_GetElement(cx, obj, JSVAL_TO_INT(argv[0]), rval);
136   }
137   else {
138     *rval = JSVAL_VOID;
139     rv = TRUE;
140   }
141   return rv;
142 }
143 
144 //  JS_METHOD(nlistDebug)
145 //  {
146 //    JSObject *foo = obj;
147 //    while (foo)
148 //      {
149 //        JSClass *cls = JS_GetClass(foo);
150 //        printf("---> clsname: %s\n", cls -> name);
151 //        foo = JS_GetPrototype(cx, foo);
152 //      }
153 
154 //    return TRUE;
155 //  }
156 
JS_METHOD(nlistAppend)157 JS_METHOD(nlistAppend)
158 {
159   jsuint len;
160   JS_GetArrayLength(cx, obj, &len);
161   for (unsigned int i = 0; i < argc; i++)
162     {
163       JS_SetElement(cx, obj, len++, &argv[i]);
164     }
165   return TRUE;
166 }
167 
JS_METHOD(nlistRemove)168 JS_METHOD(nlistRemove)
169 {
170   if (argc > 0)
171     {
172       JS_DeleteElement(cx, obj, JSVAL_TO_INT(argv[0]));
173     }
174   return TRUE;
175 }
176 
177 JSFunctionSpec nlistFunctions[] = {
178   {"item", nlistItem, 0, 0, 0},
179   {"append", nlistAppend, 0, 0, 0},
180   //{"remove", nlistRemove, 0, 0, 0}, //BUGGY
181    {NULL, 0, 0, 0, 0}
182 };
183 
JS_METHOD(nlistConstructor)184 JS_METHOD(nlistConstructor)
185 {
186   //create an array object to replace obj instance
187   JSObject *arr = JS_NewArrayObject(cx, 0, NULL);
188 
189   //get array prototypr (all methods)
190 //    JSContextItem *cxi = (JSContextItem*)JS_GetContextPrivate(cx);
191 //    sabassert(cxi);
192 //    if (cxi -> array_proto)
193 //      {
194 //        //JS_SetPrototype(cx, obj, cxi -> array_proto);
195 //        JS_SetPrototype(cx, arr, cxi -> array_proto);
196 //      }
197 
198   //set original object as a prototype of returned array
199   JS_SetPrototype(cx, arr, obj);
200   //set specific object methods
201   JS_DefineFunctions(cx, obj, nlistFunctions);
202 
203   *rval = OBJECT_TO_JSVAL(arr);
204   return TRUE;
205 }
206 
207 JSClass nlistClass = {
208   "NodeList", 0,
209   JS_PropertyStub,
210   JS_PropertyStub,
211   JS_PropertyStub,
212   JS_PropertyStub,
213   JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub,
214   JS_FinalizeStub,
215   0,
216   0,
217   NULL,
218   nlistConstructor, NULL, NULL, 0, 0
219 };
220 
221 /******************** dom implementation ************/
222 
223 JSClass domimplClass = {
224   "DOMImplementation", 0,
225   JS_PropertyStub, JS_PropertyStub,
226   JS_PropertyStub,
227   JS_PropertyStub,
228   JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub,
229   JS_FinalizeStub, 0, 0, NULL, NULL, NULL, NULL, 0, 0
230 };
231 
JS_METHOD(domimplHasFeature)232 JS_METHOD(domimplHasFeature)
233 {
234   *rval = JSVAL_FALSE;
235   return TRUE;
236 }
237 
JS_METHOD(domimplCreateDocumentType)238 JS_METHOD(domimplCreateDocumentType)
239 {
240   DOM_EX( 9 );
241   return TRUE;
242 }
243 
JS_METHOD(domimplCreateDocument)244 JS_METHOD(domimplCreateDocument)
245 {
246   DOM_EX( 9 );
247   return TRUE;
248 }
249 
250 JSFunctionSpec domimplFunctions[] = {
251   {"hasFeature", domimplHasFeature, 0, 0, 0},
252   {"createDocumentType", domimplCreateDocumentType, 0, 0, 0},
253   {"createDocument", domimplCreateDocument, 0, 0, 0},
254   {NULL, 0, 0, 0, 0}
255 };
256 
257 /************************ node  *********************/
_jsdom_getNodePrivate(Sit S,NodeHandle node)258 void* _jsdom_getNodePrivate(Sit S, NodeHandle node)
259 {
260   NodePrivate *np = new NodePrivate;
261   np -> situa = &S;
262   np -> node = node;
263   return (void*)np;
264 }
265 
nodeGetProperty(JSContext * cx,JSObject * obj,jsval id,jsval * vp)266 JSBool nodeGetProperty (JSContext *cx, JSObject *obj, jsval id, jsval *vp)
267 {
268   *vp = id;
269   return TRUE;
270 }
271 
nodeFinalize(JSContext * cx,JSObject * obj)272 void nodeFinalize(JSContext *cx, JSObject *obj)
273 {
274   NodePrivate *np = (NodePrivate*)JS_GetPrivate(cx, obj);
275   if (np) {
276     delete np;
277   }
278 }
279 
280 
JS_PROP(nodeGetNodeName)281 JS_PROP(nodeGetNodeName)
282 {
283   declPRIV;
284   if (np) {
285     char* val;
286     Bool doFree = FALSE;
287     switch(NPDOM.getNodeType(np->node)) {
288     case ELEMENT_NODE:
289     case ATTRIBUTE_NODE:
290     case PROCESSING_INSTRUCTION_NODE:
291       val = (char *)NPDOM.getNodeName(np->node);
292       doFree = TRUE;
293       break;
294     case TEXT_NODE:
295       val = "#text";
296       break;
297     case COMMENT_NODE:
298       val = "#comment";
299       break;
300     case DOCUMENT_NODE:
301       val = "#document";
302       break;
303     default:
304       /* NAMESPACE_NODE - not in DOM 2;
305        * CDATASection, DocumentFragment, DocumentType,
306        * Entity,EntityReference, Notation - not in Sablotron
307        */
308       val = (char *)NPDOM.getNodeName(np->node);
309       doFree = TRUE;
310     }
311     JSString *str = JS_NewStringCopyZ(cx, val);
312     if (doFree) NPDOM.freeName(np->node, val);
313     *rval = STRING_TO_JSVAL(str);
314     return TRUE;
315   }
316   else {
317     return FALSE;
318   }
319 }
320 
JS_PROP(nodeGetNodeValue)321 JS_PROP(nodeGetNodeValue)
322 {
323   declPRIV;
324   if (np) {
325     char* val = (char *)NPDOM.getNodeValue(np->node);
326     JSString *str = JS_NewStringCopyZ(cx, val);
327     NPDOM.freeValue(np->node, val);
328     *rval = STRING_TO_JSVAL(str);
329     return TRUE;
330   }
331   else {
332     return FALSE;
333   }
334 }
335 
JS_PROP(nodeGetNodeType)336 JS_PROP(nodeGetNodeType)
337 {
338   declPRIV;
339   if (np) {
340     *rval = INT_TO_JSVAL(NPDOM.getNodeType(np->node));
341     return TRUE;
342   }
343   else {
344     return FALSE;
345   }
346 }
347 
JS_PROP(nodeGetParentNode)348 JS_PROP(nodeGetParentNode)
349 {
350   declPRIV;
351   if (np) {
352     JSObject *o = jsdom_createNode(cx, np, NPDOM.getParent(np->node));
353     *rval = o ? OBJECT_TO_JSVAL(o) : JSVAL_NULL;
354     return TRUE;
355   }
356   else {
357     return FALSE;
358   }
359 }
360 
JS_PROP(nodeGetChildNodes)361 JS_PROP(nodeGetChildNodes)
362 {
363   declPRIV;
364   if (np) {
365     JSObject *arr = jsdom_createNodeList(cx, 0);
366     *rval = OBJECT_TO_JSVAL(arr);
367     int count = NPDOM.getChildCount(np->node);
368 
369     for (int i = 0; i < count; i++)
370       {
371 	JSObject *x = jsdom_createNode(cx, np, NPDOM.getChildNo(np->node, i));
372 	jsval xx = OBJECT_TO_JSVAL(x);
373 	JS_SetElement(cx, arr, i, &xx);
374       }
375     return TRUE;
376   }
377   else {
378     return FALSE;
379   }
380 }
381 
JS_PROP(nodeGetFirstChild)382 JS_PROP(nodeGetFirstChild)
383 {
384   declPRIV;
385   if (np) {
386     JSObject *o = jsdom_createNode(cx, np, NPDOM.getChildNo(np->node, 0));
387     *rval = o ? OBJECT_TO_JSVAL(o) : JSVAL_NULL;
388     return TRUE;
389   }
390   else {
391     return FALSE;
392   }
393 }
394 
JS_PROP(nodeGetLastChild)395 JS_PROP(nodeGetLastChild)
396 {
397   declPRIV;
398   if (np) {
399     JSObject *o = jsdom_createNode(cx, np,
400 				   NPDOM.getChildNo(np->node,
401 						    NPDOM.getChildCount(np->node) - 1 ));
402     *rval = o ? OBJECT_TO_JSVAL(o) : JSVAL_NULL;
403     return TRUE;
404   }
405   else {
406     return FALSE;
407   }
408 }
409 
JS_PROP(nodeGetPreviousSibling)410 JS_PROP(nodeGetPreviousSibling)
411 {
412   declPRIV;
413   if (np) {
414     JSObject *o = jsdom_createNode(cx, np, NPDOM.getPreviousSibling(np->node));
415     *rval = o ? OBJECT_TO_JSVAL(o) : JSVAL_NULL;
416     return TRUE;
417   }
418   else {
419     return FALSE;
420   }
421 }
422 
JS_PROP(nodeGetNextSibling)423 JS_PROP(nodeGetNextSibling)
424 {
425   declPRIV;
426   if (np) {
427     JSObject *o = jsdom_createNode(cx, np, NPDOM.getNextSibling(np->node));
428     *rval = o ? OBJECT_TO_JSVAL(o) : JSVAL_NULL;
429     return TRUE;
430   }
431   else {
432     return FALSE;
433   }
434 }
435 
JS_PROP(nodeGetAttributes)436 JS_PROP(nodeGetAttributes)
437 {
438   declPRIV;
439   if (np) {
440     if (NPDOM.getNodeType(np->node) == ELEMENT_NODE) {
441       JSObject *nmap = jsdom_createNamedNodeMap(cx, 0);
442       //iterate attributes
443       int attcount = NPDOM.getAttributeCount(np->node);
444       for (int i = 0; i < attcount; i++)
445 	{
446 	  SXP_Node n = NPDOM.getAttributeNo(np->node, i);
447 	  JSObject *att = jsdom_wrapNode(*(np->situa), cx, n);
448 	  jsval val = OBJECT_TO_JSVAL(att);
449 	  char *name = (char *)NPDOM.getNodeName(n);
450 	  JS_SetProperty(cx, nmap, name, &val);
451 	  NPDOM.freeName(n,name);
452 	}
453       //return
454       *rval = OBJECT_TO_JSVAL(nmap);
455     } else {
456       *rval = JSVAL_NULL;
457     }
458     return TRUE;
459   }
460   else {
461     return FALSE;
462   }
463 }
464 
JS_PROP(nodeGetOwnerDocument)465 JS_PROP(nodeGetOwnerDocument)
466 {
467   declPRIV;
468   if (np) {
469     JSObject *o = jsdom_createNode(cx, np, NPDOM.getOwnerDocument(np->node));
470     *rval = o ? OBJECT_TO_JSVAL(o) : JSVAL_NULL;
471     return TRUE;
472   }
473   else {
474     return FALSE;
475   }
476 }
477 
JS_PROP(nodeGetNamespaceUri)478 JS_PROP(nodeGetNamespaceUri)
479 {
480   declPRIV;
481   if (np) {
482     char* val = (char *)NPDOM.getNodeNameURI(np->node);
483     if (val) {
484       JSString *str = JS_NewStringCopyZ(cx, val);
485       *rval = STRING_TO_JSVAL(str);
486     }
487     else {
488       *rval = JSVAL_NULL;
489     }
490     NPDOM.freeName(np->node,val);
491     return TRUE;
492   }
493   else {
494     return FALSE;
495   }
496 }
497 
JS_PROP(nodeGetPrefix)498 JS_PROP(nodeGetPrefix)
499 {
500   declPRIV;
501   if (np) {
502     char *val = NULL, *colon = NULL;
503     bool doFree = false;
504     switch(NPDOM.getNodeType(np->node)) {
505     case TEXT_NODE:
506     case DOCUMENT_NODE:
507     case COMMENT_NODE:
508       break;
509     case ELEMENT_NODE:
510     case ATTRIBUTE_NODE:
511     case PROCESSING_INSTRUCTION_NODE:
512     default: // see comment within nodeGetNodeName
513       val = (char *)NPDOM.getNodeName(np->node);
514       colon = strchr(val,':');
515       doFree = true;
516     }
517     if (val && colon) {
518       JSString *str = JS_NewStringCopyN(cx, val, colon - val);
519       *rval = STRING_TO_JSVAL(str);
520     }
521     else {
522       *rval = JSVAL_NULL;
523     }
524     if (doFree) NPDOM.freeName(np->node, val);
525     return TRUE;
526   }
527   else {
528     return FALSE;
529   }
530 }
531 
JS_PROP(nodeGetLocalName)532 JS_PROP(nodeGetLocalName)
533 {
534   declPRIV;
535   if (np) {
536     char* val = (char *)NPDOM.getNodeNameLocal(np->node);
537     if (val) {
538       JSString *str = JS_NewStringCopyZ(cx, val);
539       *rval = STRING_TO_JSVAL(str);
540     }
541     else {
542       *rval = JSVAL_NULL;
543     }
544     NPDOM.freeName(np->node,val);
545     return TRUE;
546   }
547   else {
548     return FALSE;
549   }
550 }
551 
JS_METHOD(nodeToString)552 JS_METHOD(nodeToString)
553 {
554   declPRIV;
555   if (np) {
556     DStr val;
557     NPDOM.constructStringValue(np->node, val);
558     JSString *str = JS_NewStringCopyZ(cx, (char*)val);
559     *rval = STRING_TO_JSVAL(str);
560     return TRUE;
561   }
562   else {
563     return FALSE;
564   }
565 }
566 
JS_METHOD(nodeUnsupported)567 JS_METHOD(nodeUnsupported)
568 {
569   DOM_EX( 9 );
570   return TRUE;
571 }
572 
JS_METHOD(nodeHasChildNodes)573 JS_METHOD(nodeHasChildNodes)
574 {
575   declPRIV;
576   if (np) {
577     if (NPDOM.getChildCount(np->node)) *rval = JSVAL_TRUE;
578     else *rval = JSVAL_FALSE;
579     return TRUE;
580   }
581   else {
582     return FALSE;
583   }
584 }
585 
JS_METHOD(nodeNormalize)586 JS_METHOD(nodeNormalize)
587 {
588   //simply does nothing
589   return TRUE;
590 }
591 
JS_METHOD(nodeIsSupported)592 JS_METHOD(nodeIsSupported)
593 {
594   //harmlessly unsupported
595   *rval = JSVAL_FALSE;
596   return TRUE;
597 }
598 
JS_METHOD(nodeHasAttributes)599 JS_METHOD(nodeHasAttributes)
600 {
601   declPRIV;
602   if (np) {
603     if (NPDOM.getAttributeCount(np->node)) *rval = JSVAL_TRUE;
604     else *rval = JSVAL_FALSE;
605     return TRUE;
606   }
607   else {
608     return FALSE;
609   }
610 }
611 
612 JSClass nodeClass = {
613   "Node",
614   JSCLASS_HAS_PRIVATE,
615   JS_PropertyStub, JS_PropertyStub,
616   JS_PropertyStub,
617   JS_PropertyStub,
618   JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub,
619   nodeFinalize, 0, 0, NULL, NULL, NULL, NULL, 0, 0
620 };
621 
622 //node prototype properties
623 JSPropertySpec nodeProtoProps[] =
624 {
625   //nodetype constants
626   {"ELEMENT_NODE",  SDOM_ELEMENT_NODE,
627    PROP_OPT, nodeGetProperty, NULL},
628   {"ATTRIBUTE_NODE",  SDOM_ATTRIBUTE_NODE,
629    PROP_OPT, nodeGetProperty, NULL},
630   {"TEXT_NODE",  SDOM_TEXT_NODE,
631    PROP_OPT, nodeGetProperty, NULL},
632   {"CDATA_SECTION_NODE",  SDOM_CDATA_SECTION_NODE,
633    PROP_OPT, nodeGetProperty, NULL},
634   {"ENTITY_REFERENCE_NODE",  SDOM_ENTITY_REFERENCE_NODE,
635    PROP_OPT, nodeGetProperty, NULL},
636   {"ENTITY_NODE",  SDOM_ENTITY_NODE,
637    PROP_OPT, nodeGetProperty, NULL},
638   {"PROCESSING_INSTRUCTION_NODE",  SDOM_PROCESSING_INSTRUCTION_NODE,
639    PROP_OPT, nodeGetProperty, NULL},
640   {"COMMENT_NODE",  SDOM_COMMENT_NODE,
641    PROP_OPT, nodeGetProperty, NULL},
642   {"DOCUMENT_NODE",  SDOM_DOCUMENT_NODE,
643    PROP_OPT, nodeGetProperty, NULL},
644   {"DOCUMENT_TYPE_NODE",  SDOM_DOCUMENT_TYPE_NODE,
645    PROP_OPT, nodeGetProperty, NULL},
646   {"DOCUMENT_FRAGMENT_NODE",  SDOM_DOCUMENT_FRAGMENT_NODE,
647    PROP_OPT, nodeGetProperty, NULL},
648   {"NOTATION_NODE",  SDOM_NOTATION_NODE ,
649    PROP_OPT, nodeGetProperty, NULL},
650   {NULL, 0, 0, 0, 0}
651 };
652 
653 //'real' node props
654 JSPropertySpec nodeProps[] =
655 {
656   //other properties
657   {"nodeName", 0, PROP_OPT, nodeGetNodeName, NULL},
658   {"nodeValue", 0, PROP_OPT, nodeGetNodeValue, NULL},
659   {"nodeType", 0, PROP_OPT, nodeGetNodeType, NULL},
660   {"parentNode", 0, PROP_OPT, nodeGetParentNode, NULL},
661   {"childNodes", 0, PROP_OPT, nodeGetChildNodes, NULL},
662   {"firstChild", 0, PROP_OPT, nodeGetFirstChild, NULL},
663   {"lastChild", 0, PROP_OPT, nodeGetLastChild, NULL},
664   {"previousSibling", 0, PROP_OPT, nodeGetPreviousSibling, NULL},
665   {"nextSibling", 0, PROP_OPT, nodeGetNextSibling, NULL},
666   {"attributes", 0, PROP_OPT, nodeGetAttributes, NULL},
667   {"ownerDocument", 0, PROP_OPT, nodeGetOwnerDocument, NULL},
668   {"namespaceURI", 0, PROP_OPT, nodeGetNamespaceUri, NULL},
669   {"prefix", 0, PROP_OPT, nodeGetPrefix, NULL},
670   {"localName", 0, PROP_OPT, nodeGetLocalName, NULL},
671   {NULL, 0, 0, 0, 0}
672 };
673 
674 
675 JSFunctionSpec nodeFunctions[] =
676 {
677   //unsupported
678   {"toString", nodeToString, 0, 0, 0},
679   {"insertBefore", nodeUnsupported, 0, 0, 0},
680   {"replaceChild", nodeUnsupported, 0, 0, 0},
681   {"removeChild", nodeUnsupported, 0, 0, 0},
682   {"appendChild", nodeUnsupported, 0, 0, 0},
683   {"cloneNode", nodeUnsupported, 0, 0, 0},
684   //supported
685   {"hasChildNodes", nodeHasChildNodes, 0, 0, 0},
686   {"normalize", nodeNormalize, 0, 0, 0},
687   {"isSupported", nodeIsSupported, 0, 0, 0},
688   {"hasAttributes", nodeHasAttributes, 0, 0, 0},
689   {NULL, 0, 0, 0, 0}
690 };
691 
692 /************************** document ***********************/
693 
694 JSClass documentClass = {
695   "Document",
696   JSCLASS_HAS_PRIVATE,
697   JS_PropertyStub, JS_PropertyStub,
698   JS_PropertyStub,
699   JS_PropertyStub,
700   JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub,
701   nodeFinalize, 0, 0, NULL, NULL, NULL, NULL, 0, 0
702 };
703 
JS_PROP(docGetType)704 JS_PROP(docGetType)
705 {
706   *rval = JSVAL_VOID;
707   return TRUE;
708 }
709 
JS_PROP(docGetImplementation)710 JS_PROP(docGetImplementation)
711 {
712   JSContextItem *item = (JSContextItem*)JS_GetContextPrivate(cx);
713   sabassert(item);
714 
715   *rval = OBJECT_TO_JSVAL(item -> domimpl);
716   return TRUE;
717 }
718 
JS_PROP(docGetDocumentElement)719 JS_PROP(docGetDocumentElement)
720 {
721   declPRIV;
722   if (np) {
723     JSObject *o = jsdom_createNode(cx, np, NPDOM.getChildNo(np->node, 0));
724     *rval = o ? OBJECT_TO_JSVAL(o) : JSVAL_NULL;
725     return TRUE;
726   }
727   else {
728     return FALSE;
729   }
730 }
731 
JS_METHOD(docElementsByTagName)732 JS_METHOD(docElementsByTagName)
733 {
734   DOM_EX( 9 );
735   return TRUE;
736 }
737 
JS_METHOD(docElementsByTagNameNS)738 JS_METHOD(docElementsByTagNameNS)
739 {
740   DOM_EX( 9 );
741   return TRUE;
742 }
743 
744 JSPropertySpec documentProps[] = {
745   {"doctype", 0, PROP_OPT, docGetType, NULL},
746   {"implementation", 0, PROP_OPT, docGetImplementation, NULL},
747   {"documentElement", 0, PROP_OPT, docGetDocumentElement, NULL},
748   {NULL, 0, 0, 0, 0}
749 };
750 
751 JSFunctionSpec documentFunctions[] = {
752   //not needed
753   {"createElement", nodeUnsupported, 0, 0, 0},
754   {"createDocumentFragment", nodeUnsupported, 0, 0, 0},
755   {"createTextNode", nodeUnsupported, 0, 0, 0},
756   {"createComment", nodeUnsupported, 0, 0, 0},
757   {"createCDATASection", nodeUnsupported, 0, 0, 0},
758   {"createProcessingInstruction", nodeUnsupported, 0, 0, 0},
759   {"createAttribute", nodeUnsupported, 0, 0, 0},
760   {"createEntityReference", nodeUnsupported, 0, 0, 0},
761   {"importNode", nodeUnsupported, 0, 0, 0},
762   {"createElementNS", nodeUnsupported, 0, 0, 0},
763   {"createAttributeNS", nodeUnsupported, 0, 0, 0},
764   //we do not support ids
765   {"getElementsById", nodeUnsupported, 0, 0, 0},
766   //should be supported
767   {"getElementsByTagName", docElementsByTagName, 0, 0, 0},
768   {"getElementsByTagNameNS", docElementsByTagNameNS, 0, 0, 0},
769   {NULL, 0, 0, 0, 0}
770 };
771 
772 /************************** element ************************/
773 
774 JSClass elementClass = {
775   "Element",
776   JSCLASS_HAS_PRIVATE,
777   JS_PropertyStub, JS_PropertyStub,
778   JS_PropertyStub,
779   JS_PropertyStub,
780   JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub,
781   nodeFinalize, 0, 0, NULL, NULL, NULL, NULL, 0, 0
782 };
783 
784 
JS_PROP(eleGetTagName)785 JS_PROP(eleGetTagName)
786 {
787   declPRIV;
788   if (np) {
789     char *name;
790     name = (char *)NPDOM.getNodeName(np->node);
791     JSString *jname = JS_NewStringCopyZ(cx, name);
792     *rval = STRING_TO_JSVAL(jname);
793     NPDOM.freeName(np->node, name);
794     return TRUE;
795   }
796   else {
797     return FALSE;
798   }
799 }
800 
JS_METHOD(eleGetAttribute)801 JS_METHOD(eleGetAttribute)
802 {
803   declPRIV;
804   if (argc < 1)
805     {
806       JS_ReportError(cx, "Element.getAttribute must have one parameter");
807       return FALSE;
808     }
809   if (np) {
810     JSString *str = JSVAL_TO_STRING(argv[0]);
811     char *name = JS_GetStringBytes(str);
812     char *value;
813     int attcount = NPDOM.getAttributeCount(np->node);
814     char *attname;
815     NodeHandle attnode;
816     JSString *jval;
817     for (int i = 0; i < attcount; i++) {
818       attnode = NPDOM.getAttributeNo(np->node, i);
819       attname = (char *)NPDOM.getNodeName(attnode);
820       if ( !strcmp(name, attname) ) {
821 	value = (char *)NPDOM.getNodeValue(attnode);
822 	jval = JS_NewStringCopyZ(cx, value);
823 	*rval = STRING_TO_JSVAL(jval);
824 	NPDOM.freeValue(attnode, value);
825 	NPDOM.freeName(attnode, attname);
826 	return TRUE;
827       };
828       NPDOM.freeName(attnode, attname);
829     };
830     jval = JS_NewStringCopyZ(cx, "");
831     *rval = STRING_TO_JSVAL(jval);
832     return TRUE;
833   }
834   else {
835     return FALSE;
836   }
837 }
838 
JS_METHOD(eleGetAttributeNode)839 JS_METHOD(eleGetAttributeNode)
840 {
841   declPRIV;
842   if (argc < 1)
843     {
844       JS_ReportError(cx, "Element.getAttribute must have one parameter");
845       return FALSE;
846     }
847   if (np) {
848     JSString *str = JSVAL_TO_STRING(argv[0]);
849     char *name = JS_GetStringBytes(str);
850     int attcount = NPDOM.getAttributeCount(np->node);
851     char *attname;
852     NodeHandle attnode;
853     for (int i = 0; i < attcount; i++) {
854       attnode = NPDOM.getAttributeNo(np->node, i);
855       attname = (char *)NPDOM.getNodeName(attnode);
856       if ( !strcmp(name, attname) ) {
857 	JSObject *o = jsdom_createNode(cx, np, attnode);
858 	*rval = o ? OBJECT_TO_JSVAL(o) : JSVAL_NULL;
859 	NPDOM.freeName(attnode, attname);
860 	return TRUE;
861       };
862       NPDOM.freeName(attnode, attname);
863     };
864     *rval = JSVAL_NULL;
865     return TRUE;
866   }
867   else {
868     return FALSE;
869   }
870 }
871 
JS_METHOD(eleGetElementsByTagName)872 JS_METHOD(eleGetElementsByTagName)
873 {
874   *rval = JSVAL_NULL;
875   return TRUE;
876 }
877 
JS_METHOD(eleHasAttribute)878 JS_METHOD(eleHasAttribute)
879 {
880   declPRIV;
881   if (np) {
882     JSString *str = JSVAL_TO_STRING(argv[0]);
883     char *name = JS_GetStringBytes(str);
884     int attcount = NPDOM.getAttributeCount(np->node);
885     char *attname;
886     NodeHandle attnode;
887     for (int i = 0; i < attcount; i++) {
888       attnode = NPDOM.getAttributeNo(np->node, i);
889       attname = (char *)NPDOM.getNodeName(attnode);
890       if ( !strcmp(name, attname) ) {
891 	NPDOM.freeName(attnode, attname);
892 	*rval = JSVAL_TRUE;
893 	return TRUE;
894       };
895       NPDOM.freeName(attnode, attname);
896     };
897     *rval = JSVAL_FALSE;
898     return TRUE;
899   }
900   else {
901     return FALSE;
902   }
903 }
904 
905 JSPropertySpec elementProps[] =
906 {
907   {"tagName", 0, PROP_OPT, eleGetTagName, NULL},
908   {NULL, 0, 0, 0, 0}
909 };
910 
911 JSFunctionSpec elementFunctions[] =
912 {
913   {"getAttribute", eleGetAttribute, 0, 0, 0},
914   {"setAttribute", nodeUnsupported, 0, 0, 0},
915   {"removeAttribute", nodeUnsupported, 0, 0, 0},
916   {"getAttributeNode", eleGetAttributeNode, 0, 0, 0},
917   {"setAttributeNode", nodeUnsupported, 0, 0, 0},
918   {"removeAttributeNode", nodeUnsupported, 0, 0, 0},
919   {"getElementsByTagName", eleGetElementsByTagName, 0, 0, 0},
920   {"getAttributeNS", nodeUnsupported, 0, 0, 0},
921   {"setAttributeNS", nodeUnsupported, 0, 0, 0},
922   {"removeAttributeNS", nodeUnsupported, 0, 0, 0},
923   {"getAttributeNodeNS", nodeUnsupported, 0, 0, 0},
924   {"setAttributeNodeNS", nodeUnsupported, 0, 0, 0},
925   {"getElementsByTagNameNS", nodeUnsupported, 0, 0, 0},
926   {"hasAttribute", eleHasAttribute, 0, 0, 0},
927   {"hasAttributeNS", nodeUnsupported, 0, 0, 0},
928   {NULL, 0, 0, 0, 0}
929 };
930 
931 /********************* Attr ************************/
932 
933 JSClass attrClass = {
934   "Attr",
935   JSCLASS_HAS_PRIVATE,
936   JS_PropertyStub, JS_PropertyStub,
937   JS_PropertyStub,
938   JS_PropertyStub,
939   JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub,
940   nodeFinalize, 0, 0, NULL, NULL, NULL, NULL, 0, 0
941 };
942 
JS_PROP(attrGetSpecified)943 JS_PROP(attrGetSpecified)
944 {
945   *rval = JSVAL_TRUE;
946   return TRUE;
947 }
948 
JS_PROP(attrGetOwnerElement)949 JS_PROP(attrGetOwnerElement)
950 {
951   declPRIV;
952   if (np) {
953     JSObject *o = jsdom_createNode(cx, np, NPDOM.getParent(np->node));
954     *rval = o ? OBJECT_TO_JSVAL(o) : JSVAL_NULL;
955     return TRUE;
956   }
957   else {
958     return FALSE;
959   }
960 }
961 
962 JSPropertySpec attrProps[] = {
963   {"name", 0, PROP_OPT, nodeGetNodeName, NULL},
964   {"value", 0, PROP_OPT, nodeGetNodeValue, NULL},
965   {"specified", 0, PROP_OPT, attrGetSpecified, NULL},
966   {"ownerElement", 0, PROP_OPT, attrGetOwnerElement, NULL},
967   {NULL, 0, 0, 0, 0}
968 };
969 
970 /******************* character data & Co. **********/
971 
972 JSClass chardataClass = {
973   "CharacterData",
974   JSCLASS_HAS_PRIVATE,
975   JS_PropertyStub, JS_PropertyStub,
976   JS_PropertyStub,
977   JS_PropertyStub,
978   JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub,
979   nodeFinalize, 0, 0, NULL, NULL, NULL, NULL, 0, 0
980 };
981 
JS_PROP(chardataGetData)982 JS_PROP(chardataGetData)
983 {
984   declPRIV;
985   if (np) {
986     char *val = (char *)NPDOM.getNodeValue(np->node);
987     if (val) {
988       JSString *jval = JS_NewStringCopyZ(cx, val);
989       *rval = STRING_TO_JSVAL(jval);
990     } else {
991       *rval = JSVAL_NULL;
992     }
993     NPDOM.freeValue(np->node, val);
994     return TRUE;
995   }
996   else {
997     return FALSE;
998   }
999 }
1000 
_getDataLen(const char * data)1001 int _getDataLen(const char* data)
1002 {
1003   return strlen((char *)data);
1004 }
1005 
JS_PROP(chardataGetLength)1006 JS_PROP(chardataGetLength)
1007 {
1008   declPRIV;
1009   if (np) {
1010     const char* val = NPDOM.getNodeValue(np->node);
1011     *rval = INT_TO_JSVAL(_getDataLen(val));
1012     NPDOM.freeValue(np->node, (char*)val);
1013     return TRUE;
1014   }
1015   else {
1016     return FALSE;
1017   }
1018 }
1019 
JS_METHOD(chardataSubstringData)1020 JS_METHOD(chardataSubstringData)
1021 {
1022   declPRIV;
1023   if (argc < 2)
1024     {
1025       JS_ReportError(cx,
1026 		     "CharacterData.substringData must have two parameters");
1027       return FALSE;
1028     }
1029   if (np) {
1030     const char *val = NPDOM.getNodeValue(np->node);
1031     int len = _getDataLen(val);
1032     int off = JSVAL_TO_INT(argv[0]);
1033     int count = JSVAL_TO_INT(argv[1]);
1034     JSString *str;
1035     if (off >= len)
1036       {
1037 	str = JS_NewStringCopyZ(cx, "");
1038       }
1039     else
1040       {
1041 	if (off + count > len) count = len - off;
1042 	str = JS_NewStringCopyN(cx, val + off, count);
1043       }
1044     NPDOM.freeValue(np->node, (char*)val);
1045     *rval = STRING_TO_JSVAL(str);
1046     return TRUE;
1047   }
1048   else {
1049     return FALSE;
1050   }
1051 }
1052 
1053 JSPropertySpec chardataProps[] =
1054 {
1055   {"data", 0, PROP_OPT, chardataGetData, NULL},
1056   {"length", 0, PROP_OPT, chardataGetLength, NULL},
1057   {NULL, 0, 0, 0, 0}
1058 };
1059 
1060 JSFunctionSpec chardataFunctions[] =
1061 {
1062   {"substringData", chardataSubstringData, 0, 0, 0},
1063   {"appendData", nodeUnsupported, 0, 0, 0},
1064   {"insertData", nodeUnsupported, 0, 0, 0},
1065   {"deleteData", nodeUnsupported, 0, 0, 0},
1066   {"replaceData", nodeUnsupported, 0, 0, 0},
1067   {NULL, 0, 0, 0, 0}
1068 };
1069 
1070 /********************* text ************************/
1071 
1072 JSClass textClass = {
1073   "Text",
1074   JSCLASS_HAS_PRIVATE,
1075   JS_PropertyStub, JS_PropertyStub,
1076   JS_PropertyStub,
1077   JS_PropertyStub,
1078   JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub,
1079   nodeFinalize, 0, 0, NULL, NULL, NULL, NULL, 0, 0
1080 };
1081 
1082 JSFunctionSpec textFunctions[] =
1083 {
1084   {"splitText", nodeUnsupported, 0, 0, 0},
1085   {NULL, 0, 0, 0, 0}
1086 };
1087 
1088 /******************** cdata ************************/
1089 
1090 JSClass cdataClass = {
1091   "CDATASection",
1092   JSCLASS_HAS_PRIVATE,
1093   JS_PropertyStub, JS_PropertyStub,
1094   JS_PropertyStub,
1095   JS_PropertyStub,
1096   JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub,
1097   nodeFinalize, 0, 0, NULL, NULL, NULL, NULL, 0, 0
1098 };
1099 
1100 /***************** comment *************************/
1101 
1102 JSClass commentClass = {
1103   "Comment",
1104   JSCLASS_HAS_PRIVATE,
1105   JS_PropertyStub, JS_PropertyStub,
1106   JS_PropertyStub,
1107   JS_PropertyStub,
1108   JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub,
1109   nodeFinalize, 0, 0, NULL, NULL, NULL, NULL, 0, 0
1110 };
1111 
1112 /********************* named node map **************/
1113 
JS_PROP(nnmGetLength)1114 JS_PROP(nnmGetLength)
1115 {
1116   JSIdArray *arr = JS_Enumerate(cx, obj);
1117   *rval = INT_TO_JSVAL(arr -> length - 1);
1118   JS_DestroyIdArray(cx, arr);
1119   return TRUE;
1120 }
1121 
JS_METHOD(nnmGetNamedItem)1122 JS_METHOD(nnmGetNamedItem)
1123 {
1124   JSBool rv;
1125   if (argc != 1)
1126     {
1127       JS_ReportError(cx, "NamedNodeMap.getNamedItem must have one parameter");
1128       return FALSE;
1129     }
1130   JSString *str = JSVAL_TO_STRING(argv[0]);
1131   jsval value;
1132   char *name = JS_GetStringBytes(str);
1133   rv = JS_GetProperty(cx, obj, name, &value);
1134   if (rv) *rval = value;
1135   return rv;
1136 }
1137 
JS_METHOD(nnmSetNamedItem)1138 JS_METHOD(nnmSetNamedItem)
1139 {
1140   if (argc != 1)
1141     {
1142       JS_ReportError(cx, "NamedNodeMap.setNamedItem must have one parameter");
1143       return FALSE;
1144     }
1145   //check the type here!!!
1146   JSObject *nobj = JSVAL_TO_OBJECT(argv[0]);
1147   JSClass *cls = JS_GET_CLASS(cx, nobj);
1148   JSObject *proto = JS_GetPrototype(cx, nobj);
1149   JSContextItem *cxi = (JSContextItem*)JS_GetContextPrivate(cx);
1150   if (proto == cxi->node || cls == &nodeClass)
1151     {
1152       NodePrivate *np = (NodePrivate*)JS_GetPrivate(cx, nobj);
1153       char *name = (char *)NPDOM.getNodeName(np->node);
1154       JS_SetProperty(cx, obj, name, &(argv[0]));
1155       NPDOM.freeName(np->node,name);
1156       return TRUE;
1157     }
1158   else
1159     {
1160       JS_ReportError(cx, "invalid NamedNodeMap.setNamedItem parameter");
1161       return FALSE;
1162     }
1163 }
1164 
JS_METHOD(nnmRemoveNamedItem)1165 JS_METHOD(nnmRemoveNamedItem)
1166 {
1167   if (argc != 1)
1168     {
1169       JS_ReportError(cx, "NamedNodeMap.removeNamedItem must have one parameter");
1170       return FALSE;
1171     }
1172   JSString *str = JSVAL_TO_STRING(argv[0]);
1173   char *name = JS_GetStringBytes(str);
1174   return JS_DeleteProperty(cx, obj, name);
1175 }
1176 
JS_METHOD(nnmItem)1177 JS_METHOD(nnmItem)
1178 {
1179   if (argc >= 1 || ! JSVAL_IS_INT(argv[0]) )
1180     {
1181       JSIdArray *arr = JS_Enumerate(cx, obj);
1182       int idx = JSVAL_TO_INT(argv[0]);
1183       if (idx < 0 || idx >= arr -> length - 1)
1184 	{
1185 	  *rval = JSVAL_VOID;
1186 	}
1187       else
1188 	{
1189 	  jsval val;
1190 	  //skip the 'length' property
1191 	  JS_IdToValue(cx, arr->vector[idx + 1], &val);
1192 	  JS_GetProperty(cx, obj,
1193 			 JS_GetStringBytes(JSVAL_TO_STRING(val)), rval);
1194 	}
1195       JS_DestroyIdArray(cx, arr);
1196       return TRUE;
1197     }
1198   else
1199     {
1200       JS_ReportError(cx, "NamedNodeMap.item must have one parameter");
1201       return FALSE;
1202     }
1203 }
1204 
1205 JSPropertySpec nnmProps[] = {
1206   {"length", 0, PROP_OPT, nnmGetLength, NULL},
1207   {NULL, 0, 0, 0, 0}
1208 };
1209 
1210 JSFunctionSpec nnmFunctions[] = {
1211   {"getNamedItem", nnmGetNamedItem, 0, 0, 0},
1212   {"setNamedItem", nnmSetNamedItem, 0, 0, 0},
1213   {"removeNamedItem", nnmRemoveNamedItem, 0, 0, 0},
1214   {"item", nnmItem, 0, 0, 0},
1215   {"getNamedItemsNS", nodeUnsupported, 0, 0, 0},
1216   {"setNamedItemsNS", nodeUnsupported, 0, 0, 0},
1217   {"removeNamedItemsNS", nodeUnsupported, 0, 0, 0},
1218   {NULL, 0, 0, 0, 0}
1219 };
1220 
1221 JSClass nnmClass = {
1222   "NamedNodeMap", 0,
1223   JS_PropertyStub,
1224   JS_PropertyStub,
1225   JS_PropertyStub,
1226   JS_PropertyStub,
1227   JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub,
1228   JS_FinalizeStub, 0, 0, NULL, NULL, NULL, NULL, 0, 0
1229 };
1230 
1231 /********************* functions *******************/
1232 
_jsdom_getNodeClass(SDOM_NodeType type)1233 JSClass* _jsdom_getNodeClass(SDOM_NodeType type)
1234 {
1235   JSClass *cls;
1236   switch (type)
1237     {
1238     case SDOM_ELEMENT_NODE:
1239       cls = &elementClass;
1240       break;
1241     case SDOM_DOCUMENT_NODE:
1242       cls = &documentClass;
1243       break;
1244     case SDOM_ATTRIBUTE_NODE:
1245       cls = &attrClass;
1246       break;
1247     case SDOM_TEXT_NODE:
1248       cls = &textClass;
1249       break;
1250     case SDOM_CDATA_SECTION_NODE:
1251       cls = &cdataClass;
1252       break;
1253     case SDOM_COMMENT_NODE:
1254       cls = &commentClass;
1255       break;
1256     default:
1257       {
1258 	cls = &nodeClass;
1259       }
1260     }
1261   return cls;
1262 }
1263 
_jsdom_getNodeClass(Sit S,JSContext * cx,NodeHandle node)1264 JSClass* _jsdom_getNodeClass(Sit S, JSContext *cx, NodeHandle node)
1265 {
1266   return _jsdom_getNodeClass((SDOM_NodeType)S.dom().getNodeType(node));
1267 }
1268 
jsdom_wrapNode(Sit S,JSContext * cx,NodeHandle node)1269 JSObject* jsdom_wrapNode(Sit S, JSContext *cx, NodeHandle node)
1270 {
1271   JSObject *obj = NULL;
1272   if (node)
1273     {
1274       JSContextItem *item = (JSContextItem*)JS_GetContextPrivate(cx);
1275       sabassert(item);
1276 
1277       SDOM_NodeType type = (SDOM_NodeType)S.dom().getNodeType(node);
1278 
1279       obj = JS_NewObject(cx, _jsdom_getNodeClass(type),
1280 				   item->node, NULL);
1281       JS_SetPrivate(cx, obj, _jsdom_getNodePrivate(S, node));
1282 
1283       //common methods and properties
1284       JS_DefineProperties(cx, obj, nodeProps);
1285       JS_DefineFunctions(cx, obj, nodeFunctions);
1286 
1287       //tweak the class
1288       switch (type)
1289 	{
1290 	case SDOM_ELEMENT_NODE:
1291 	  {
1292 	    JS_DefineProperties(cx, obj, elementProps);
1293 	    JS_DefineFunctions(cx, obj, elementFunctions);
1294 	  }; break;
1295 	case SDOM_DOCUMENT_NODE:
1296 	  {
1297 	    JS_DefineProperties(cx, obj, documentProps);
1298 	    JS_DefineFunctions(cx, obj, documentFunctions);
1299 	  }; break;
1300 	case SDOM_ATTRIBUTE_NODE:
1301 	  {
1302 	    JS_DefineProperties(cx, obj, attrProps);
1303 	  }; break;
1304 	case SDOM_TEXT_NODE:
1305 	  {
1306 	    JS_DefineProperties(cx, obj, chardataProps);
1307 	    JS_DefineFunctions(cx, obj, chardataFunctions);
1308 	    //text specs.
1309 	    JS_DefineFunctions(cx, obj, textFunctions);
1310 	  }; break;
1311 	case SDOM_CDATA_SECTION_NODE:
1312 	  {
1313 	    JS_DefineProperties(cx, obj, chardataProps);
1314 	    JS_DefineFunctions(cx, obj, chardataFunctions);
1315 	  }; break;
1316 	case SDOM_COMMENT_NODE:
1317 	  {
1318 	    JS_DefineProperties(cx, obj, chardataProps);
1319 	    JS_DefineFunctions(cx, obj, chardataFunctions);
1320 	  }; break;
1321 	}
1322     }
1323   return obj;
1324 }
1325 
jsdom_createNode(JSContext * cx,NodePrivate * np_,NodeHandle node)1326 JSObject* jsdom_createNode(JSContext *cx, NodePrivate *np_, NodeHandle node)
1327 {
1328   return jsdom_wrapNode(*(np_->situa), cx, node);
1329 }
1330 
1331 
jsdom_delegateDOM(JSContext * cx)1332 void jsdom_delegateDOM(JSContext *cx)
1333 {
1334   JSContextItem *item = (JSContextItem*)JS_GetContextPrivate(cx);
1335   JSObject *obj;
1336   //Node prototype
1337   obj = JS_DefineObject(cx, JS_GetGlobalObject(cx), "Node",
1338 			&nodeClass, NULL,
1339 			JSPROP_ENUMERATE |
1340 			JSPROP_READONLY |
1341 			JSPROP_PERMANENT);
1342   JS_DefineProperties(cx, obj, nodeProtoProps);
1343   item -> node = obj;
1344   //DOMException prototype
1345   obj = JS_DefineObject(cx, JS_GetGlobalObject(cx), "DOMException",
1346 			&domexClass, NULL,
1347 			JSPROP_ENUMERATE |
1348 			JSPROP_READONLY |
1349 			JSPROP_PERMANENT);
1350   JS_DefineProperties(cx, obj, domexProtoProps);
1351   item -> domex = obj;
1352   //DOMImplementation
1353   obj = JS_DefineObject(cx, JS_GetGlobalObject(cx), "DOMImplementation",
1354 			&domexClass, NULL,
1355 			JSPROP_ENUMERATE |
1356 			JSPROP_READONLY |
1357 			JSPROP_PERMANENT);
1358   JS_DefineFunctions(cx, obj, domimplFunctions);
1359   item -> domimpl = obj;
1360   //nodelist class
1361   JSObject *nlclass = JS_InitClass(cx, JS_GetGlobalObject(cx),
1362 				   NULL,
1363 				   &nlistClass, nlistConstructor, 0,
1364 				   NULL, NULL, NULL, NULL);
1365   item -> nlclass = nlclass;
1366   //nodelist class
1367   //  JSObject *nnmclass = JS_InitClass(cx, JS_GetGlobalObject(cx),
1368 //  				    NULL,
1369 //  				    &nnmClass, NULL, 0,
1370 //  				    NULL, nnmFunctions, NULL, NULL);
1371 //    item -> nnmclass = nnmclass;
1372 }
1373 
jsdom_raiseException(JSContext * cx,int code)1374 void jsdom_raiseException(JSContext *cx, int code)
1375 {
1376   JSContextItem *item = (JSContextItem*)JS_GetContextPrivate(cx);
1377   sabassert(item);
1378 
1379   JSObject *obj = JS_NewObject(cx, &domexClass, item -> domex, NULL);
1380   //set private
1381   DomExPrivate *c = new DomExPrivate;
1382   c -> code = code;
1383   JS_SetPrivate(cx, obj, c);
1384   //instance props. and funcs.
1385   JS_DefineProperties(cx, obj, domexProps);
1386   JS_DefineFunctions(cx, obj, domexFunctions);
1387   //raise exception
1388   JS_SetPendingException(cx, OBJECT_TO_JSVAL(obj));
1389 }
1390 
jsdom_createNodeList(JSContext * cx,int num)1391 JSObject* jsdom_createNodeList(JSContext *cx, int num)
1392 {
1393   //JSObject *obj = JS_NewArrayObject(cx, 0, NULL);
1394   //JS_DefineFunctions(cx, obj, nlistFunctions);
1395   JSObject *obj = JS_ConstructObject(cx, &nlistClass, NULL, NULL);
1396 
1397   return obj;
1398 }
1399 
jsdom_createNamedNodeMap(JSContext * cx,int num)1400 JSObject* jsdom_createNamedNodeMap(JSContext *cx, int num)
1401 {
1402   JSObject *obj = JS_NewObject(cx, &nnmClass, NULL, NULL);
1403   JS_DefineFunctions(cx, obj, nnmFunctions);
1404   JS_DefineProperties(cx, obj, nnmProps);
1405 
1406   return obj;
1407 }
1408 
1409 #endif //ENABLE_JS
1410