зеркало из https://github.com/mozilla/pjs.git
- Use 8 space hard tabstops like god and IBM intended, but indent-tabs-mode:nil
should eliminate hard tabs anyway (so 8 is just in case one gets thru -- LXR was not displaying this source well with 4). - Don't nest jsapi.h outside the idempotent-include #ifndef in dom.h. - Include xp.h to get this code working on Windows (to cope with some kind of compiled header problem). - Fix bad JS_GetEmptyStringValue calls that were treated as returning JSString* rather than jsval, and fed into STRING_TO_JSVAL. - Avoid tagging and untagging a jsval to test for a null JSString* return. - Fiddle formatting in a couple of places. - Avoid leaving cdata->data null after realloc failure. Use of a local temp (data2) also improves generated code by eliminating memory ambiguity.
This commit is contained in:
Родитель
41da07107a
Коммит
eac532ad80
|
@ -1,4 +1,4 @@
|
|||
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
|
@ -21,10 +21,11 @@
|
|||
* See http://www.w3.org/DOM/ for details.
|
||||
*/
|
||||
|
||||
#include "jsapi.h"
|
||||
#ifndef DOM_H
|
||||
#define DOM_H
|
||||
|
||||
#include "jsapi.h"
|
||||
|
||||
typedef enum DOM_NodeType {
|
||||
NODE_TYPE_ELEMENT = 1,
|
||||
NODE_TYPE_ATTRIBUTE,
|
||||
|
@ -56,16 +57,16 @@ typedef enum DOM_ExceptionCode {
|
|||
} DOM_ExceptionCode;
|
||||
|
||||
/* struct typedefs */
|
||||
typedef struct DOM_Node DOM_Node;
|
||||
typedef struct DOM_NodeOps DOM_NodeOps;
|
||||
typedef struct DOM_AttributeEntry DOM_AttributeEntry;
|
||||
typedef struct DOM_Element DOM_Element;
|
||||
typedef struct DOM_ElementOps DOM_ElementOps;
|
||||
typedef struct DOM_AttributeList DOM_AttributeList;
|
||||
typedef struct DOM_Attribute DOM_Attribute;
|
||||
typedef struct DOM_Document DOM_Document;
|
||||
typedef struct DOM_CharacterData DOM_CharacterData;
|
||||
typedef struct DOM_Text DOM_Text;
|
||||
typedef struct DOM_Node DOM_Node;
|
||||
typedef struct DOM_NodeOps DOM_NodeOps;
|
||||
typedef struct DOM_AttributeEntry DOM_AttributeEntry;
|
||||
typedef struct DOM_Element DOM_Element;
|
||||
typedef struct DOM_ElementOps DOM_ElementOps;
|
||||
typedef struct DOM_AttributeList DOM_AttributeList;
|
||||
typedef struct DOM_Attribute DOM_Attribute;
|
||||
typedef struct DOM_Document DOM_Document;
|
||||
typedef struct DOM_CharacterData DOM_CharacterData;
|
||||
typedef struct DOM_Text DOM_Text;
|
||||
|
||||
/*
|
||||
* All of these handlers are called before the DOM tree is manipulated, with
|
||||
|
@ -84,20 +85,20 @@ typedef struct DOM_Text DOM_Text;
|
|||
* at this point, or signal an exception and return false.
|
||||
*/
|
||||
struct DOM_NodeOps {
|
||||
JSBool (*insertBefore)(JSContext *cx, DOM_Node *node, DOM_Node *child,
|
||||
DOM_Node *ref, JSBool before);
|
||||
JSBool (*replaceChild)(JSContext *cx, DOM_Node *node, DOM_Node *child,
|
||||
DOM_Node *old, JSBool before);
|
||||
JSBool (*removeChild) (JSContext *cx, DOM_Node *node, DOM_Node *old,
|
||||
JSBool before);
|
||||
JSBool (*appendChild) (JSContext *cx, DOM_Node *node, DOM_Node *child,
|
||||
JSBool before);
|
||||
JSBool (*insertBefore)(JSContext *cx, DOM_Node *node, DOM_Node *child,
|
||||
DOM_Node *ref, JSBool before);
|
||||
JSBool (*replaceChild)(JSContext *cx, DOM_Node *node, DOM_Node *child,
|
||||
DOM_Node *old, JSBool before);
|
||||
JSBool (*removeChild) (JSContext *cx, DOM_Node *node, DOM_Node *old,
|
||||
JSBool before);
|
||||
JSBool (*appendChild) (JSContext *cx, DOM_Node *node, DOM_Node *child,
|
||||
JSBool before);
|
||||
|
||||
/* free up Node-private data */
|
||||
void (*destroyNode) (JSContext *cx, DOM_Node *node);
|
||||
void (*destroyNode) (JSContext *cx, DOM_Node *node);
|
||||
|
||||
/* construct a JSObject and fill in Node-private data as appropriate. */
|
||||
JSObject * (*reflectNode) (JSContext *cx, DOM_Node *node);
|
||||
JSObject * (*reflectNode) (JSContext *cx, DOM_Node *node);
|
||||
|
||||
};
|
||||
|
||||
|
@ -138,18 +139,18 @@ struct DOM_ElementOps {
|
|||
* DOM_SignalException(cx, DOM_INVALID_NAME_ERR) if it's an
|
||||
* invalid name. (The DOM_NO_MODIFICATION_ALLOWED_ERR case is
|
||||
* handled in the DOM code itself, and no call will be made to the
|
||||
* setAttribute handler in that case.)
|
||||
* setAttribute handler in that case.)
|
||||
*/
|
||||
JSBool (*setAttribute)(JSContext *cx, DOM_Element *element,
|
||||
const char *name, const char *value);
|
||||
JSBool (*setAttribute)(JSContext *cx, DOM_Element *element,
|
||||
const char *name, const char *value);
|
||||
|
||||
/* returns attribute value (caller must copy) or NULL if not found */
|
||||
const char * (*getAttribute)(JSContext *cx, DOM_Element *element,
|
||||
const char *name, JSBool *cacheable);
|
||||
const char * (*getAttribute)(JSContext *cx, DOM_Element *element,
|
||||
const char *name, JSBool *cacheable);
|
||||
|
||||
/* returns number of attributes, or -1 if the number isn't known */
|
||||
intN (*getNumAttrs)(JSContext *cx, DOM_Element *element,
|
||||
JSBool *cacheable);
|
||||
intN (*getNumAttrs)(JSContext *cx, DOM_Element *element,
|
||||
JSBool *cacheable);
|
||||
};
|
||||
|
||||
/* stubs */
|
||||
|
@ -171,15 +172,15 @@ DOM_SignalException(JSContext *cx, DOM_ExceptionCode exception);
|
|||
/* The basic node */
|
||||
|
||||
struct DOM_Node {
|
||||
DOM_NodeType type;
|
||||
DOM_NodeOps *ops;
|
||||
char *name;
|
||||
struct DOM_Node *sibling;
|
||||
struct DOM_Node *prev_sibling;
|
||||
struct DOM_Node *child;
|
||||
struct DOM_Node *parent;
|
||||
JSObject *mocha_object;
|
||||
void *data; /* embedding-private data */
|
||||
DOM_NodeType type;
|
||||
DOM_NodeOps *ops;
|
||||
char *name;
|
||||
struct DOM_Node *sibling;
|
||||
struct DOM_Node *prev_sibling;
|
||||
struct DOM_Node *child;
|
||||
struct DOM_Node *parent;
|
||||
JSObject *mocha_object;
|
||||
void *data; /* embedding-private data */
|
||||
};
|
||||
|
||||
JSBool
|
||||
|
@ -219,10 +220,10 @@ struct DOM_AttributeEntry {
|
|||
};
|
||||
|
||||
struct DOM_Element {
|
||||
DOM_Node node;
|
||||
DOM_ElementOps *ops;
|
||||
const char *tagName;
|
||||
uintN nattrs;
|
||||
DOM_Node node;
|
||||
DOM_ElementOps *ops;
|
||||
const char *tagName;
|
||||
uintN nattrs;
|
||||
DOM_AttributeEntry *attrs;
|
||||
void *style; /* later, later... */
|
||||
};
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
|
@ -26,9 +26,7 @@
|
|||
#define DOM_PRIV_H
|
||||
|
||||
#include "dom.h"
|
||||
#include "xp_mem.h" /* XP_NEW_ZAP, XP_FREE */
|
||||
#include "xpassert.h" /* XP_ASSERT */
|
||||
#include "xp_str.h" /* XP_STRDUP */
|
||||
#include "xp.h"
|
||||
|
||||
JSObject *
|
||||
dom_NodeInit(JSContext *cx, JSObject *obj);
|
||||
|
|
|
@ -1,128 +0,0 @@
|
|||
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Original Code is Mozilla Communicator client code.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
/*
|
||||
* DOM Attribute implementation.
|
||||
*/
|
||||
|
||||
#include "dom_priv.h"
|
||||
|
||||
static JSBool
|
||||
attribute_getter(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
|
||||
{
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
static JSBool
|
||||
attribute_setter(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
|
||||
{
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
static JSClass DOM_AttributeClass = {
|
||||
"Attribute", JSCLASS_HAS_PRIVATE,
|
||||
JS_PropertyStub, JS_PropertyStub, attribute_getter, attribute_setter,
|
||||
JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub
|
||||
};
|
||||
|
||||
/* must start after the DOM_NODE tinyids */
|
||||
enum {
|
||||
ATTRIBUTE_SPECIFIED = -1,
|
||||
ATTRIBUTE_NAME = -2,
|
||||
ATTRIBUTE_VALUE = -3,
|
||||
};
|
||||
|
||||
static JSPropertySpec attribute_props[] = {
|
||||
{"specified", ATTRIBUTE_SPECIFIED, JSPROP_ENUMERATE, 0, 0},
|
||||
{"name", ATTRIBUTE_NAME, JSPROP_ENUMERATE, 0, 0},
|
||||
{"value", ATTRIBUTE_VALUE, JSPROP_ENUMERATE, 0, 0},
|
||||
{0}
|
||||
};
|
||||
|
||||
JSObject *
|
||||
DOM_NewAttributeObject(JSContext *cx, DOM_Attribute *attr)
|
||||
{
|
||||
DOM_Node *node = (DOM_Node *)attr;
|
||||
JSObject *obj;
|
||||
JSString *str;
|
||||
jsval v;
|
||||
|
||||
obj = JS_ConstructObject(cx, &DOM_AttributeClass, NULL, NULL);
|
||||
if (!obj)
|
||||
return NULL;
|
||||
|
||||
if (!JS_SetPrivate(cx, obj, attr)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
str = JS_NewStringCopyZ(cx, node->name);
|
||||
v = STRING_TO_JSVAL(str);
|
||||
if (!str ||
|
||||
!JS_SetProperty(cx, obj, "name", &v))
|
||||
return NULL;
|
||||
|
||||
v = JSVAL_TRUE;
|
||||
if (!JS_SetProperty(cx, obj, "specified", &v))
|
||||
return NULL;
|
||||
node->mocha_object = obj;
|
||||
return obj;
|
||||
}
|
||||
|
||||
DOM_Attribute *
|
||||
DOM_NewAttribute(const char *name, const char *value, DOM_Element *element)
|
||||
{
|
||||
DOM_Attribute *attr;
|
||||
attr = XP_NEW_ZAP(DOM_Attribute);
|
||||
if (!attr)
|
||||
return NULL;
|
||||
|
||||
attr->node.name = XP_STRDUP(name);
|
||||
attr->element = element;
|
||||
return attr;
|
||||
}
|
||||
|
||||
JSObject *
|
||||
DOM_ObjectForAttribute(JSContext *cx, DOM_Attribute *attr)
|
||||
{
|
||||
if (!attr)
|
||||
return NULL;
|
||||
|
||||
if (attr->node.mocha_object)
|
||||
return attr->node.mocha_object;
|
||||
|
||||
return DOM_NewAttributeObject(cx, attr);
|
||||
}
|
||||
|
||||
static JSBool
|
||||
Attribute(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
||||
{
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
JSObject *
|
||||
dom_AttributeInit(JSContext *cx, JSObject *scope, JSObject *node_proto)
|
||||
{
|
||||
JSObject *proto;
|
||||
proto = JS_InitClass(cx, scope, node_proto, &DOM_AttributeClass,
|
||||
Attribute, 0,
|
||||
attribute_props, NULL,
|
||||
NULL, NULL);
|
||||
return proto;
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
|
@ -183,7 +183,7 @@ dom_hasFeature(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
|
|||
*rval = JSVAL_FALSE;
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
|
||||
static JSFunctionSpec dom_methods[] = {
|
||||
{"hasFeature", dom_hasFeature, 2},
|
||||
{0}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
|
@ -172,7 +172,7 @@ doc_getElementsByTagName(JSContext *cx, JSObject* obj, uintN argc,
|
|||
JSString *tagName;
|
||||
if (!JS_ConvertArguments(cx, argc, argv, "S", &tagName))
|
||||
return JS_FALSE;
|
||||
|
||||
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
|
@ -23,7 +23,7 @@
|
|||
#include "dom_priv.h"
|
||||
|
||||
static JSPropertySpec element_props[] = {
|
||||
{"tagName", DOM_ELEMENT_TAGNAME, JSPROP_READONLY, 0, 0},
|
||||
{"tagName", DOM_ELEMENT_TAGNAME, JSPROP_READONLY, 0, 0},
|
||||
{0}
|
||||
};
|
||||
|
||||
|
@ -38,7 +38,7 @@ element_getter(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
|
|||
|
||||
slot = JSVAL_TO_INT(id);
|
||||
|
||||
/*
|
||||
/*
|
||||
* Look, ma! Inheritance!
|
||||
* We handle .attributes ourselves because we return something other
|
||||
* than null, unlike every other Node subclass.
|
||||
|
@ -56,15 +56,15 @@ element_getter(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
|
|||
if (slot == DOM_ELEMENT_TAGNAME) {
|
||||
JSString *tagName;
|
||||
#ifdef DEBUG_shaver_0
|
||||
fprintf(stderr, "getting tagName %s",
|
||||
element->tagName ? element->tagName : "#tag");
|
||||
tagName = JS_InternString(cx, element->tagName ?
|
||||
element->tagName : "#tag");
|
||||
fprintf(stderr, ": %x\n", tagName);
|
||||
fprintf(stderr, "getting tagName %s",
|
||||
element->tagName ? element->tagName : "#tag");
|
||||
tagName = JS_InternString(cx, element->tagName ?
|
||||
element->tagName : "#tag");
|
||||
fprintf(stderr, ": %x\n", tagName);
|
||||
#else
|
||||
|
||||
tagName = JS_NewStringCopyZ(cx,
|
||||
element->tagName ? element->tagName : "#tag");
|
||||
tagName = JS_NewStringCopyZ(cx, element->tagName
|
||||
? element->tagName
|
||||
: "#tag");
|
||||
#endif
|
||||
if (!tagName)
|
||||
return JS_FALSE;
|
||||
|
@ -106,11 +106,12 @@ element_getAttribute(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
|
|||
return JS_FALSE;
|
||||
|
||||
if (entry && entry->value) {
|
||||
*rval = STRING_TO_JSVAL(JS_NewStringCopyZ(cx, entry->value));
|
||||
if (!JSVAL_TO_STRING(*rval))
|
||||
JSString *valstr = JS_NewStringCopyZ(cx, entry->value);
|
||||
if (!valstr)
|
||||
return JS_FALSE;
|
||||
*rval = STRING_TO_JSVAL(valstr);
|
||||
} else {
|
||||
*rval = STRING_TO_JSVAL(JS_GetEmptyStringValue(cx));
|
||||
*rval = JS_GetEmptyStringValue(cx);
|
||||
}
|
||||
|
||||
return JS_TRUE;
|
||||
|
@ -176,11 +177,11 @@ element_removeAttributeNode(JSContext *cx, JSObject *obj, uintN argc,
|
|||
}
|
||||
|
||||
static JSFunctionSpec element_methods[] = {
|
||||
{"setAttribute", element_setAttribute, 2},
|
||||
{"getAttribute", element_getAttribute, 1},
|
||||
{"removeAttribute", element_removeAttribute, 1},
|
||||
{"setAttributeNode", element_setAttributeNode, 1},
|
||||
{"getAttributeNode", element_getAttributeNode, 1},
|
||||
{"setAttribute", element_setAttribute, 2},
|
||||
{"getAttribute", element_getAttribute, 1},
|
||||
{"removeAttribute", element_removeAttribute, 1},
|
||||
{"setAttributeNode", element_setAttributeNode, 1},
|
||||
{"getAttributeNode", element_getAttributeNode, 1},
|
||||
{"removeAttributeNode", element_removeAttributeNode, 1},
|
||||
{0}
|
||||
};
|
||||
|
@ -208,7 +209,7 @@ JSObject *
|
|||
DOM_NewElementObject(JSContext *cx, DOM_Element *element)
|
||||
{
|
||||
JSObject *obj;
|
||||
|
||||
|
||||
obj = JS_ConstructObject(cx, &DOM_ElementClass, NULL, NULL);
|
||||
if (!obj)
|
||||
return NULL;
|
||||
|
@ -342,9 +343,9 @@ JSObject *
|
|||
dom_ElementInit(JSContext *cx, JSObject *scope, JSObject *node_proto)
|
||||
{
|
||||
JSObject *proto = JS_InitClass(cx, scope, node_proto, &DOM_ElementClass,
|
||||
Element, 0,
|
||||
element_props, element_methods,
|
||||
NULL, NULL);
|
||||
Element, 0,
|
||||
element_props, element_methods,
|
||||
NULL, NULL);
|
||||
if (!JS_DefineProperties(cx, proto, dom_node_props))
|
||||
return NULL;
|
||||
return proto;
|
||||
|
|
|
@ -1,595 +0,0 @@
|
|||
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
/*
|
||||
* DOM Node, NodeList, NamedNodeMap implementation.
|
||||
*/
|
||||
|
||||
#include "dom_priv.h"
|
||||
|
||||
#ifdef DEBUG_shaver
|
||||
int DOM_node_indent = 0;
|
||||
#endif
|
||||
|
||||
DOM_Node *
|
||||
DOM_PopNode(DOM_Node *node)
|
||||
{
|
||||
return node->parent;
|
||||
}
|
||||
|
||||
JSBool
|
||||
DOM_PushNode(DOM_Node *node, DOM_Node *parent)
|
||||
{
|
||||
DOM_Node *iter;
|
||||
node->parent = parent;
|
||||
node->sibling = NULL;
|
||||
node->prev_sibling = NULL;
|
||||
node->child = NULL;
|
||||
|
||||
/* First child */
|
||||
if (!parent->child) {
|
||||
parent->child = node;
|
||||
return JS_TRUE;
|
||||
}
|
||||
/*
|
||||
* XXX optimize by using parent->mocha_object to cache last child, and
|
||||
* XXX NULLing parent->mocha_object on PopNode?
|
||||
*/
|
||||
for (iter = parent->child; iter->sibling; iter = iter->sibling)
|
||||
; /* empty */
|
||||
XP_ASSERT(iter);
|
||||
iter->sibling = node;
|
||||
node->prev_sibling = iter;
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
JSObject *
|
||||
DOM_ObjectForNode(JSContext *cx, DOM_Node *node)
|
||||
{
|
||||
if (!node)
|
||||
return NULL;
|
||||
if (node->mocha_object)
|
||||
return node->mocha_object;
|
||||
|
||||
return DOM_NewNodeObject(cx, node);
|
||||
}
|
||||
|
||||
JSBool
|
||||
dom_node_getter(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
|
||||
{
|
||||
intN slot;
|
||||
DOM_Node *node;
|
||||
JSString *str;
|
||||
|
||||
if (!JSVAL_IS_INT(id))
|
||||
return JS_TRUE;
|
||||
|
||||
node = (DOM_Node *)JS_GetPrivate(cx, obj);
|
||||
if (!node)
|
||||
return JS_TRUE;
|
||||
|
||||
slot = JSVAL_TO_INT(id);
|
||||
|
||||
switch(slot) {
|
||||
case DOM_NODE_NODENAME:
|
||||
if (!node->name) {
|
||||
*vp = JSVAL_NULL; /* XXX '#nameless' or some such? */
|
||||
return JS_TRUE;
|
||||
}
|
||||
#ifdef DEBUG_shaver_0
|
||||
str = JS_InternString(cx, node->name);
|
||||
#else
|
||||
str = JS_NewStringCopyZ(cx, node->name);
|
||||
#endif
|
||||
if (!str)
|
||||
return JS_FALSE;
|
||||
*vp = STRING_TO_JSVAL(str);
|
||||
return JS_TRUE;
|
||||
case DOM_NODE_NODETYPE:
|
||||
*vp = INT_TO_JSVAL(node->type);
|
||||
return JS_TRUE;
|
||||
case DOM_NODE_FIRSTCHILD:
|
||||
*vp = OBJECT_TO_JSVAL(DOM_ObjectForNodeDowncast(cx, node->child));
|
||||
return JS_TRUE;
|
||||
case DOM_NODE_NEXTSIBLING:
|
||||
*vp = OBJECT_TO_JSVAL(DOM_ObjectForNodeDowncast(cx, node->sibling));
|
||||
return JS_TRUE;
|
||||
case DOM_NODE_PREVIOUSSIBLING:
|
||||
*vp = OBJECT_TO_JSVAL(DOM_ObjectForNodeDowncast(cx,
|
||||
node->prev_sibling));
|
||||
return JS_TRUE;
|
||||
case DOM_NODE_PARENTNODE:
|
||||
*vp = OBJECT_TO_JSVAL(DOM_ObjectForNodeDowncast(cx, node->parent));
|
||||
return JS_TRUE;
|
||||
case DOM_NODE_HASCHILDNODES:
|
||||
*vp = BOOLEAN_TO_JSVAL((JSBool)(node->child != NULL));
|
||||
return JS_TRUE;
|
||||
case DOM_NODE_ATTRIBUTES:
|
||||
/* only elements have non-null attributes */
|
||||
*vp = JSVAL_NULL;
|
||||
return JS_TRUE;
|
||||
default:
|
||||
XP_ASSERT(0);
|
||||
break;
|
||||
}
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
JSBool
|
||||
dom_node_setter(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
|
||||
{
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
dom_node_finalize(JSContext *cx, JSObject *obj)
|
||||
{
|
||||
DOM_Node *priv = (DOM_Node *)JS_GetPrivate(cx, obj);
|
||||
if (!priv)
|
||||
return;
|
||||
priv->mocha_object = NULL;
|
||||
DOM_DestroyTree(cx, priv);
|
||||
}
|
||||
|
||||
static JSClass DOM_NodeClass = {
|
||||
"Node", JSCLASS_HAS_PRIVATE,
|
||||
JS_PropertyStub, JS_PropertyStub, dom_node_getter, dom_node_setter,
|
||||
JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, dom_node_finalize
|
||||
};
|
||||
|
||||
JSObject *
|
||||
DOM_NewNodeObject(JSContext *cx, DOM_Node *node)
|
||||
{
|
||||
JSObject *obj;
|
||||
|
||||
obj = JS_ConstructObject(cx, &DOM_NodeClass, NULL, NULL);
|
||||
if (!obj)
|
||||
return NULL;
|
||||
|
||||
if (!JS_SetPrivate(cx, obj, node)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
node->mocha_object = obj;
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
void
|
||||
DOM_DestroyNode(JSContext *cx, DOM_Node *node)
|
||||
{
|
||||
XP_ASSERT(!node->mocha_object);
|
||||
if (node->ops && node->ops->destroyNode)
|
||||
node->ops->destroyNode(cx, node);
|
||||
if (node->name && node->type != NODE_TYPE_TEXT)
|
||||
JS_free(cx, node->name);
|
||||
JS_free(cx, node);
|
||||
}
|
||||
|
||||
#define REMOVE_FROM_TREE(node) \
|
||||
PR_BEGIN_MACRO \
|
||||
if (node->prev_sibling) \
|
||||
node->prev_sibling->sibling = node->sibling; \
|
||||
if (node->sibling) \
|
||||
node->sibling->prev_sibling = node->prev_sibling; \
|
||||
node->sibling = node->prev_sibling = node->parent = NULL; \
|
||||
PR_END_MACRO
|
||||
|
||||
#define FAIL_UNLESS_CHILD(node, refNode) \
|
||||
PR_BEGIN_MACRO \
|
||||
if (refNode->parent != node) { \
|
||||
/* XXX walk the tree looking for it? */ \
|
||||
DOM_SignalException(cx, DOM_NOT_FOUND_ERR); \
|
||||
return JS_FALSE; \
|
||||
} \
|
||||
PR_END_MACRO
|
||||
|
||||
static JSBool
|
||||
IsLegalChild(DOM_Node *node, DOM_Node *child)
|
||||
{
|
||||
switch(node->type) {
|
||||
case NODE_TYPE_ATTRIBUTE:
|
||||
if (child->type == NODE_TYPE_TEXT ||
|
||||
child->type == NODE_TYPE_ENTITY_REF)
|
||||
return JS_TRUE;
|
||||
return JS_FALSE;
|
||||
if (child->type == NODE_TYPE_ELEMENT ||
|
||||
child->type == NODE_TYPE_COMMENT ||
|
||||
child->type == NODE_TYPE_TEXT ||
|
||||
child->type == NODE_TYPE_PI ||
|
||||
child->type == NODE_TYPE_CDATA ||
|
||||
child->type == NODE_TYPE_ENTITY_REF)
|
||||
return JS_TRUE;
|
||||
return JS_FALSE;
|
||||
case NODE_TYPE_ELEMENT:
|
||||
case NODE_TYPE_DOCFRAGMENT:
|
||||
case NODE_TYPE_ENTITY_REF:
|
||||
if (child->type == NODE_TYPE_ELEMENT ||
|
||||
child->type == NODE_TYPE_PI ||
|
||||
child->type == NODE_TYPE_COMMENT ||
|
||||
child->type == NODE_TYPE_TEXT ||
|
||||
child->type == NODE_TYPE_CDATA ||
|
||||
child->type == NODE_TYPE_ENTITY_REF)
|
||||
return JS_TRUE;
|
||||
return JS_FALSE;
|
||||
case NODE_TYPE_DOCUMENT:
|
||||
if(child->type == NODE_TYPE_PI ||
|
||||
child->type == NODE_TYPE_COMMENT ||
|
||||
child->type == NODE_TYPE_DOCTYPE)
|
||||
return JS_TRUE;
|
||||
if (child->type == NODE_TYPE_ELEMENT)
|
||||
/* XXX check to make sure it's the only one */
|
||||
return JS_TRUE;
|
||||
return JS_FALSE;
|
||||
case NODE_TYPE_DOCTYPE:
|
||||
if (child->type == NODE_TYPE_NOTATION ||
|
||||
child->type == NODE_TYPE_ENTITY)
|
||||
return JS_TRUE;
|
||||
return JS_FALSE;
|
||||
default: /* PI, COMMENT, TEXT, CDATA, ENTITY, NOTATION */
|
||||
return JS_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
#define CHECK_LEGAL_CHILD(node, child) \
|
||||
PR_BEGIN_MACRO \
|
||||
if (!IsLegalChild(node, child)) { \
|
||||
DOM_SignalException(cx, DOM_HIERARCHY_REQUEST_ERR); \
|
||||
return JS_FALSE; \
|
||||
} \
|
||||
PR_END_MACRO
|
||||
|
||||
static JSBool
|
||||
node_insertBefore(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
|
||||
jsval *vp)
|
||||
{
|
||||
JSObject *newChild, *refChild;
|
||||
DOM_Node *newNode, *refNode, *node;
|
||||
|
||||
if (!JS_ConvertArguments(cx, argc, argv, "oo", &newChild, &refChild))
|
||||
return JS_FALSE;
|
||||
|
||||
node = (DOM_Node *)JS_GetPrivate(cx, obj);
|
||||
if (!node)
|
||||
return JS_TRUE;
|
||||
newNode = (DOM_Node *)JS_GetPrivate(cx, newChild);
|
||||
refNode = (DOM_Node *)JS_GetPrivate(cx, refChild);
|
||||
|
||||
*vp = argv[0]; /* newChild */
|
||||
if (!newNode || !refNode) {
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
CHECK_LEGAL_CHILD(node, newNode);
|
||||
FAIL_UNLESS_CHILD(node, refNode);
|
||||
if (!node->ops->insertBefore(cx, node, newNode, refNode, JS_TRUE))
|
||||
return JS_FALSE;
|
||||
REMOVE_FROM_TREE(newNode);
|
||||
|
||||
newNode->parent = node;
|
||||
|
||||
newNode->sibling = refNode;
|
||||
newNode->prev_sibling = refNode->prev_sibling;
|
||||
|
||||
refNode->prev_sibling = newNode;
|
||||
|
||||
return node->ops->insertBefore(cx, node, newNode, refNode, JS_TRUE);
|
||||
}
|
||||
|
||||
static JSBool
|
||||
node_replaceChild(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
|
||||
jsval *vp)
|
||||
{
|
||||
JSObject *oldChild, *newChild;
|
||||
DOM_Node *oldNode, *newNode, *node;
|
||||
|
||||
if (!JS_ConvertArguments(cx, argc, argv, "oo", &newChild, &oldChild))
|
||||
return JS_FALSE;
|
||||
|
||||
node = (DOM_Node *)JS_GetPrivate(cx, obj);
|
||||
if (!node)
|
||||
return JS_TRUE;
|
||||
newNode = (DOM_Node *)JS_GetPrivate(cx, newChild);
|
||||
oldNode = (DOM_Node *)JS_GetPrivate(cx, oldChild);
|
||||
|
||||
*vp = argv[1]; /* oldChild */
|
||||
if (newNode == oldNode ||
|
||||
!newNode || !oldNode)
|
||||
return JS_TRUE;
|
||||
|
||||
CHECK_LEGAL_CHILD(node, newNode);
|
||||
FAIL_UNLESS_CHILD(node, oldNode);
|
||||
if (!node->ops->replaceChild(cx, node, newNode, oldNode, JS_TRUE))
|
||||
return JS_FALSE;
|
||||
REMOVE_FROM_TREE(newNode);
|
||||
|
||||
newNode->parent = node;
|
||||
oldNode->sibling->prev_sibling = newNode;
|
||||
oldNode->prev_sibling->sibling = newNode;
|
||||
|
||||
oldNode->parent = oldNode->sibling = oldNode->prev_sibling = NULL;
|
||||
|
||||
return node->ops->replaceChild(cx, node, newNode, oldNode, JS_FALSE);
|
||||
}
|
||||
|
||||
static JSBool
|
||||
node_removeChild(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
|
||||
jsval *vp)
|
||||
{
|
||||
JSObject *deadChild;
|
||||
DOM_Node *deadNode, *node;
|
||||
|
||||
if (!JS_ConvertArguments(cx, argc, argv, "o", &deadChild))
|
||||
return JS_FALSE;
|
||||
|
||||
*vp = argv[0]; /* deadChild */
|
||||
node = (DOM_Node *)JS_GetPrivate(cx, obj);
|
||||
deadNode = (DOM_Node *)JS_GetPrivate(cx, deadChild);
|
||||
if (!deadNode || !node)
|
||||
return JS_TRUE;
|
||||
|
||||
FAIL_UNLESS_CHILD(node, deadNode);
|
||||
if (!node->ops->removeChild(cx, node, deadNode, JS_TRUE))
|
||||
return JS_FALSE;
|
||||
|
||||
REMOVE_FROM_TREE(deadNode);
|
||||
|
||||
return node->ops->removeChild(cx, node, deadNode, JS_FALSE);
|
||||
}
|
||||
|
||||
static JSBool
|
||||
node_appendChild(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
|
||||
jsval *vp)
|
||||
{
|
||||
JSObject *newChild;
|
||||
DOM_Node *newNode, *node, *iter;
|
||||
|
||||
if (!JS_ConvertArguments(cx, argc, argv, "o", &newChild))
|
||||
return JS_FALSE;
|
||||
|
||||
*vp = argv[0]; /* newChild */
|
||||
node = (DOM_Node *)JS_GetPrivate(cx, obj);
|
||||
newNode = (DOM_Node *)JS_GetPrivate(cx, obj);
|
||||
if (!node || !newNode)
|
||||
return JS_TRUE;
|
||||
|
||||
CHECK_LEGAL_CHILD(node, newNode);
|
||||
if (node->ops->appendChild(cx, node, newNode, JS_TRUE))
|
||||
REMOVE_FROM_TREE(newNode);
|
||||
|
||||
newNode->parent = node;
|
||||
|
||||
iter = node->child;
|
||||
if (iter) {
|
||||
while (iter->sibling)
|
||||
iter = iter->sibling;
|
||||
iter->sibling = newNode;
|
||||
newNode->prev_sibling = iter;
|
||||
} else {
|
||||
node->child = newNode;
|
||||
}
|
||||
|
||||
return node->ops->appendChild(cx, node, newNode, JS_FALSE);
|
||||
}
|
||||
|
||||
static JSBool
|
||||
node_cloneNode(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
|
||||
jsval *vp)
|
||||
{
|
||||
JSBool deep;
|
||||
if (!JS_ConvertArguments(cx, argc, argv, "b", &deep))
|
||||
return JS_FALSE;
|
||||
|
||||
DOM_SignalException(cx, DOM_NOT_SUPPORTED_ERR);
|
||||
/* clone */
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
static JSBool
|
||||
node_equals(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *vp)
|
||||
{
|
||||
JSObject *node;
|
||||
DOM_Node *node1, *node2;
|
||||
if (!JS_ConvertArguments(cx, argc, argv, "o", &node))
|
||||
return JS_FALSE;
|
||||
|
||||
node1 = (DOM_Node *)JS_GetPrivate(cx, obj);
|
||||
node2 = (DOM_Node *)JS_GetPrivate(cx, node);
|
||||
*vp = (JSBool)(node1 == node2);
|
||||
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
static JSFunctionSpec node_methods[] = {
|
||||
{"insertBefore", node_insertBefore, 2},
|
||||
{"replaceChild", node_replaceChild, 2},
|
||||
{"removeChild", node_removeChild, 1},
|
||||
{"appendChild", node_appendChild, 1},
|
||||
{"cloneNode", node_cloneNode, 1},
|
||||
{"equals", node_equals, 2},
|
||||
{0}
|
||||
};
|
||||
|
||||
JSPropertySpec dom_node_props[] = {
|
||||
{"nodeName", DOM_NODE_NODENAME},
|
||||
{"nodeValue", DOM_NODE_NODEVALUE},
|
||||
{"nodeType", DOM_NODE_NODETYPE},
|
||||
{"parentNode", DOM_NODE_PARENTNODE},
|
||||
{"childNodes", DOM_NODE_CHILDNODES},
|
||||
{"firstChild", DOM_NODE_FIRSTCHILD},
|
||||
{"lastChild", DOM_NODE_LASTCHILD},
|
||||
{"previousSibling", DOM_NODE_PREVIOUSSIBLING},
|
||||
{"nextSibling", DOM_NODE_NEXTSIBLING},
|
||||
{"attributes", DOM_NODE_ATTRIBUTES},
|
||||
{"hasChildNodes", DOM_NODE_HASCHILDNODES},
|
||||
{0}
|
||||
};
|
||||
|
||||
static JSConstDoubleSpec node_static_props[] = {
|
||||
{NODE_TYPE_ELEMENT, "ELEMENT"},
|
||||
{NODE_TYPE_ATTRIBUTE, "ATTRIBUTE"},
|
||||
{NODE_TYPE_PI, "PROCESSING_INSTRUCTION"},
|
||||
{NODE_TYPE_CDATA, "CDATA_SECTION"},
|
||||
{NODE_TYPE_TEXT, "TEXT"},
|
||||
{NODE_TYPE_ENTITY_REF, "ENTITY_REFERENCE"},
|
||||
{NODE_TYPE_ENTITY, "ENTITY"},
|
||||
{NODE_TYPE_COMMENT, "COMMENT"},
|
||||
{NODE_TYPE_DOCUMENT, "DOCUMENT"},
|
||||
{NODE_TYPE_DOCTYPE, "DOCUMENT_TYPE"},
|
||||
{NODE_TYPE_DOCFRAGMENT, "DOCUMENT_FRAGMENT"},
|
||||
{NODE_TYPE_NOTATION, "NOTATION"},
|
||||
{0}
|
||||
};
|
||||
|
||||
static JSBool
|
||||
Node(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *vp)
|
||||
{
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
JSObject *
|
||||
dom_NodeInit(JSContext *cx, JSObject *scope)
|
||||
{
|
||||
JSObject *proto, *ctor;
|
||||
proto = JS_InitClass(cx, scope, NULL, &DOM_NodeClass,
|
||||
Node, 0,
|
||||
dom_node_props, node_methods,
|
||||
NULL, NULL);
|
||||
if (!proto || !(ctor = JS_GetConstructor(cx, proto)))
|
||||
return NULL;
|
||||
if (!JS_DefineConstDoubles(cx, ctor, node_static_props))
|
||||
return NULL;
|
||||
return proto;
|
||||
}
|
||||
|
||||
/*
|
||||
* NodeList
|
||||
*
|
||||
* Basically an Array with magic methods.
|
||||
*/
|
||||
|
||||
#if 0
|
||||
|
||||
static JSClass DOM_NodeListClass = {
|
||||
"NodeList", 0,
|
||||
JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
|
||||
JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub
|
||||
};
|
||||
|
||||
static JSBool
|
||||
nodelist_item(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
|
||||
jsval *rval)
|
||||
{
|
||||
uint32 index;
|
||||
if (!JS_ConvertArguments(cx, argc, argv, "j", &index))
|
||||
return JS_TRUE;
|
||||
/* JS_GetElement */
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
static JSFunctionSpec nodelist_methods[] = {
|
||||
{"item", nodelist_item, 1},
|
||||
{0},
|
||||
};
|
||||
|
||||
static JSBool
|
||||
nodelist_size_get(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
|
||||
{
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
static JSPropertySpec nodelist_props[] = {
|
||||
{"size", -1, 0, nodelist_size_get},
|
||||
{0}
|
||||
};
|
||||
|
||||
/*
|
||||
* NamedNodeMap
|
||||
*
|
||||
* Basically an Object with magic resolve and helper methods.
|
||||
*/
|
||||
|
||||
static JSBool
|
||||
nnm_resolve(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
|
||||
{
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
static JSClass DOM_NamedNodeMapClass = {
|
||||
"NamedNodeMap", 0,
|
||||
JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
|
||||
JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub
|
||||
};
|
||||
|
||||
static JSBool
|
||||
nnm_getNamedItem(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
|
||||
jsval *rval)
|
||||
{
|
||||
/* JS_GetProperty */
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
static JSBool
|
||||
nnm_setNamedItem(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
|
||||
jsval *rval)
|
||||
{
|
||||
return JS_TRUE;
|
||||
/* JS_SetProperty */
|
||||
}
|
||||
|
||||
static JSBool
|
||||
nnm_removeNamedItem(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
|
||||
jsval *rval)
|
||||
{
|
||||
/* JS_DeleteProperty */
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
static JSBool
|
||||
nnm_item(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
|
||||
jsval *rval)
|
||||
{
|
||||
/* return given slot -- OBJ_GET_SLOT? */
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
static JSFunctionSpec nnm_methods[] = {
|
||||
{"getNamedItem", nnm_getNamedItem, 1},
|
||||
{"setNamedItem", nnm_setNamedItem, 1},
|
||||
{"removeNamedItem", nnm_removeNamedItem,1},
|
||||
{"item", nnm_item, 1},
|
||||
{0}
|
||||
};
|
||||
|
||||
static JSBool
|
||||
nnm_get_size(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
|
||||
{
|
||||
/* return __count__ */
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
enum {
|
||||
NNM_SIZE = -1
|
||||
};
|
||||
|
||||
static JSPropertySpec nnm_props[] = {
|
||||
{"size", NNM_SIZE, 0, nnm_get_size},
|
||||
{0}
|
||||
};
|
||||
|
||||
#endif /* 0 */
|
|
@ -1,4 +1,4 @@
|
|||
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
|
@ -20,7 +20,7 @@
|
|||
|
||||
static DOM_StyleSelector *
|
||||
GetBaseSelector(JSContext *cx, DOM_StyleDatabase *db, DOM_StyleToken type,
|
||||
DOM_StyleToken pseudo)
|
||||
DOM_StyleToken pseudo)
|
||||
{
|
||||
DOM_StyleSelector *sel = NULL;
|
||||
/* sel = HASH_LOOKUP(db->hashtable, type); */
|
||||
|
@ -32,17 +32,17 @@ DestroySelector(JSContext *cx, DOM_StyleSelector *sel)
|
|||
{
|
||||
XP_FREE(sel->selector);
|
||||
if (sel->pseudo)
|
||||
XP_FREE(sel->pseudo);
|
||||
XP_FREE(sel->pseudo);
|
||||
if (sel->rules) {
|
||||
DOM_StyleRule *iter, *next;
|
||||
iter = sel->rules;
|
||||
do {
|
||||
next = iter->next;
|
||||
XP_FREE(iter->entry.name);
|
||||
XP_FREE(iter->entry.value);
|
||||
XP_FREE(iter);
|
||||
iter = next;
|
||||
} while (iter);
|
||||
DOM_StyleRule *iter, *next;
|
||||
iter = sel->rules;
|
||||
do {
|
||||
next = iter->next;
|
||||
XP_FREE(iter->entry.name);
|
||||
XP_FREE(iter->entry.value);
|
||||
XP_FREE(iter);
|
||||
iter = next;
|
||||
} while (iter);
|
||||
}
|
||||
XP_FREE(sel);
|
||||
}
|
||||
|
@ -53,29 +53,29 @@ NewSelector(JSContext *cx, DOM_StyleToken selector, DOM_StyleToken pseudo)
|
|||
DOM_StyleSelector *sel;
|
||||
sel = XP_NEW_ZAP(DOM_StyleSelector);
|
||||
if (!sel)
|
||||
return NULL;
|
||||
return NULL;
|
||||
if (selector[0] == '.') {
|
||||
sel->type = SELECTOR_CLASS;
|
||||
selector++;
|
||||
sel->type = SELECTOR_CLASS;
|
||||
selector++;
|
||||
} else if (selector[0] == '#') {
|
||||
sel->type = SELECTOR_ID;
|
||||
selector++;
|
||||
sel->type = SELECTOR_ID;
|
||||
selector++;
|
||||
} else {
|
||||
sel->type = SELECTOR_TAG;
|
||||
sel->type = SELECTOR_TAG;
|
||||
}
|
||||
|
||||
sel->selector = XP_STRDUP(selector);
|
||||
if (!sel->selector) {
|
||||
DestroySelector(cx, sel);
|
||||
return NULL;
|
||||
DestroySelector(cx, sel);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (pseudo) {
|
||||
sel->pseudo = XP_STRDUP(pseudo);
|
||||
if (!sel->pseudo) {
|
||||
DestroySelector(cx, sel);
|
||||
return NULL;
|
||||
}
|
||||
sel->pseudo = XP_STRDUP(pseudo);
|
||||
if (!sel->pseudo) {
|
||||
DestroySelector(cx, sel);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return sel;
|
||||
|
@ -88,8 +88,8 @@ GetPseudo(JSContext *cx, DOM_Element *element)
|
|||
DOM_AttributeEntry *entry;
|
||||
|
||||
if (!DOM_GetElementAttribute(cx, element, ":pseudoclass", &entry))
|
||||
/* report error? */
|
||||
return NULL;
|
||||
/* report error? */
|
||||
return NULL;
|
||||
return entry ? entry->value : NULL;
|
||||
}
|
||||
|
||||
|
@ -98,23 +98,23 @@ GetPseudo(JSContext *cx, DOM_Element *element)
|
|||
|
||||
#define PSEUDO_MATCHES(p1, p2) (!XP_STRCMP((p1), (p2)))
|
||||
|
||||
#define MATCH() \
|
||||
#ifdef DEBUG_shaver \
|
||||
fprintf(stderr, "selector %s:%s matches element %s\n", \
|
||||
sel->selector, sel->pseudo ? sel->pseudo : "", \
|
||||
element->tagName); \
|
||||
#define MATCH() \
|
||||
#ifdef DEBUG_shaver \
|
||||
fprintf(stderr, "selector %s:%s matches element %s\n", \
|
||||
sel->selector, sel->pseudo ? sel->pseudo : "", \
|
||||
element->tagName); \
|
||||
#endif
|
||||
|
||||
#define NO_MATCH() \
|
||||
#ifdef DEBUG_shaver \
|
||||
fprintf(stderr, "selector %s:%s doesn't match element %s\n", \
|
||||
sel->selector, sel->pseudo ? sel->pseudo : "", \
|
||||
element->tagName); \
|
||||
#define NO_MATCH() \
|
||||
#ifdef DEBUG_shaver \
|
||||
fprintf(stderr, "selector %s:%s doesn't match element %s\n", \
|
||||
sel->selector, sel->pseudo ? sel->pseudo : "", \
|
||||
element->tagName); \
|
||||
#endif
|
||||
|
||||
static JSBool
|
||||
SelectorMatchesToken(JSContext *cx, DOM_StyleSelector *sel,
|
||||
DOM_StyleToken token, DOM_StyleToken pseudo)
|
||||
DOM_StyleToken token, DOM_StyleToken pseudo)
|
||||
{
|
||||
/* XXX handle #ID and .class */
|
||||
return !XPSTRCMP(sel->type, token);
|
||||
|
@ -122,21 +122,21 @@ SelectorMatchesToken(JSContext *cx, DOM_StyleSelector *sel,
|
|||
|
||||
static JSBool
|
||||
SelectorMatchesElement(JSContext *cx, DOM_Element *element,
|
||||
DOM_StyleSelector *sel)
|
||||
DOM_StyleSelector *sel)
|
||||
{
|
||||
/* XXX handle class and ID */
|
||||
if (ELEMENT_IS_TYPE(element, sel->selector)) {
|
||||
/* check pseudo, if any */
|
||||
if (sel->pseudo) {
|
||||
DOM_StyleToken elementPseudo = GetPseudo(element);
|
||||
if (PSEUDO_MATCHES(sel->pseudo, elementPseudo)) {
|
||||
MATCH();
|
||||
return JS_TRUE;
|
||||
}
|
||||
} else {
|
||||
MATCH();
|
||||
return JS_TRUE;
|
||||
}
|
||||
/* check pseudo, if any */
|
||||
if (sel->pseudo) {
|
||||
DOM_StyleToken elementPseudo = GetPseudo(element);
|
||||
if (PSEUDO_MATCHES(sel->pseudo, elementPseudo)) {
|
||||
MATCH();
|
||||
return JS_TRUE;
|
||||
}
|
||||
} else {
|
||||
MATCH();
|
||||
return JS_TRUE;
|
||||
}
|
||||
}
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
@ -148,9 +148,9 @@ RuleValueFor(JSContext *cx, DOM_StyleRule *rule, DOM_StyleToken property)
|
|||
{
|
||||
DOM_StyleRule *iter = rule;
|
||||
do {
|
||||
if (!XP_STRCMP(iter->entry.name, property))
|
||||
return &iter->entry;
|
||||
iter = iter->next;
|
||||
if (!XP_STRCMP(iter->entry.name, property))
|
||||
return &iter->entry;
|
||||
iter = iter->next;
|
||||
} while (iter);
|
||||
return NULL;
|
||||
}
|
||||
|
@ -160,10 +160,10 @@ static DOM_Element *
|
|||
AncestorOfType(JSContext *cx, DOM_Element *element, DOM_StyleSelector *sel)
|
||||
{
|
||||
do {
|
||||
/* check type */
|
||||
if (SelectorMatchesElement(cx, element, sel))
|
||||
return element;
|
||||
element = (DOM_Element *)element.node->parent;
|
||||
/* check type */
|
||||
if (SelectorMatchesElement(cx, element, sel))
|
||||
return element;
|
||||
element = (DOM_Element *)element.node->parent;
|
||||
} while (element);
|
||||
|
||||
return NULL;
|
||||
|
@ -175,70 +175,70 @@ AncestorOfType(JSContext *cx, DOM_Element *element, DOM_StyleSelector *sel)
|
|||
*/
|
||||
static JSBool
|
||||
CheckSelector(JSContext *cx, DOM_Element *element, DOM_StyleSelector *sel,
|
||||
DOM_StyleToken property, DOM_AttributeEntry **entryp,
|
||||
uintN *best, uintN specificity)
|
||||
DOM_StyleToken property, DOM_AttributeEntry **entryp,
|
||||
uintN *best, uintN specificity)
|
||||
{
|
||||
DOM_AttributeEntry *entry;
|
||||
DOM_Element *next;
|
||||
|
||||
/* check self */
|
||||
if (SelectorMatchesElement(cx, element, sel)) {
|
||||
/* if we have rules, maybe get an entry from them */
|
||||
if (sel->rules) {
|
||||
uintN score = SELECTOR_SCORE(sel, specificity);
|
||||
if (score > *best) { /* are we the best so far? */
|
||||
entry = RuleValueFor(sel, property);
|
||||
if (entry) { /* do we have a value for this property? */
|
||||
/* if we have rules, maybe get an entry from them */
|
||||
if (sel->rules) {
|
||||
uintN score = SELECTOR_SCORE(sel, specificity);
|
||||
if (score > *best) { /* are we the best so far? */
|
||||
entry = RuleValueFor(sel, property);
|
||||
if (entry) { /* do we have a value for this property? */
|
||||
#ifdef DEBUG_shaver
|
||||
fprintf(stderr, "- score %d, value %s\n",
|
||||
score, entry->value);
|
||||
fprintf(stderr, "- score %d, value %s\n",
|
||||
score, entry->value);
|
||||
#endif
|
||||
*best = score;
|
||||
*entryp = entry;
|
||||
}
|
||||
}
|
||||
}
|
||||
*best = score;
|
||||
*entryp = entry;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* now, check our enclosing selector */
|
||||
if (sel->enclosing) {
|
||||
next = AncestorOfType(cx, element, sel->enclosing);
|
||||
if (next)
|
||||
if (!CheckSelector(cx, next, sel->enclosing, property, entryp,
|
||||
best, specificity + 1))
|
||||
return JS_FALSE;
|
||||
}
|
||||
/* now, check our enclosing selector */
|
||||
if (sel->enclosing) {
|
||||
next = AncestorOfType(cx, element, sel->enclosing);
|
||||
if (next)
|
||||
if (!CheckSelector(cx, next, sel->enclosing, property, entryp,
|
||||
best, specificity + 1))
|
||||
return JS_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
/* check our sibling */
|
||||
if (sel->sibling)
|
||||
if (!CheckSelector(cx, element, sel->sibling, property, entryp,
|
||||
best, specificity))
|
||||
return JS_FALSE;
|
||||
if (!CheckSelector(cx, element, sel->sibling, property, entryp,
|
||||
best, specificity))
|
||||
return JS_FALSE;
|
||||
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
JSBool
|
||||
DOM_StyleGetProperty(JSContext *cx, DOM_StyleDatabase *db,
|
||||
DOM_Node *node, DOM_StyleToken property.
|
||||
DOM_StyleToken pseudo, DOM_AttributeEntry **entryp)
|
||||
DOM_Node *node, DOM_StyleToken property.
|
||||
DOM_StyleToken pseudo, DOM_AttributeEntry **entryp)
|
||||
{
|
||||
DOM_StyleSelector *sel;
|
||||
DOM_Element *element;
|
||||
uintN best = 0;
|
||||
|
||||
if (node->type != NODE_TYPE_ELEMENT) {
|
||||
element = (DOM_Element *)node->parent;
|
||||
XP_ASSERT(element->node.type == NODE_TYPE_ELEMENT);
|
||||
element = (DOM_Element *)node->parent;
|
||||
XP_ASSERT(element->node.type == NODE_TYPE_ELEMENT);
|
||||
} else {
|
||||
element = (DOM_Element *)node;
|
||||
element = (DOM_Element *)node;
|
||||
}
|
||||
|
||||
*entryp = NULL;
|
||||
|
||||
sel = GetBaseSelector(db, element->tagName);
|
||||
if (!sel)
|
||||
return JS_TRUE;
|
||||
return JS_TRUE;
|
||||
|
||||
/*
|
||||
* CheckSelector will recursively find the best match for a given
|
||||
|
@ -249,41 +249,41 @@ DOM_StyleGetProperty(JSContext *cx, DOM_StyleDatabase *db,
|
|||
|
||||
DOM_StyleSelector *
|
||||
DOM_StyleFindSelector(JSContext *cx, DOM_StyleDatabase *db,
|
||||
DOM_StyleSelector *base, DOM_StyleToken enclosing,
|
||||
DOM_StyleToken pseudo)
|
||||
DOM_StyleSelector *base, DOM_StyleToken enclosing,
|
||||
DOM_StyleToken pseudo)
|
||||
{
|
||||
DOM_StyleSelector *sel;
|
||||
|
||||
/* looking for the base one */
|
||||
if (!base) {
|
||||
sel = GetBaseSelector(cx, db, enclosing, pseudo);
|
||||
if (!sel)
|
||||
sel = NewSelector(cx, enclosing, pseudo);
|
||||
if (sel)
|
||||
InsertBaseSelector(cx, db, sel);
|
||||
return sel;
|
||||
sel = GetBaseSelector(cx, db, enclosing, pseudo);
|
||||
if (!sel)
|
||||
sel = NewSelector(cx, enclosing, pseudo);
|
||||
if (sel)
|
||||
InsertBaseSelector(cx, db, sel);
|
||||
return sel;
|
||||
}
|
||||
|
||||
if (!base->enclosing) {
|
||||
sel = NewSelector(cx, enclosing, pseudo);
|
||||
if (!sel)
|
||||
return NULL;
|
||||
base->enclosing = sel;
|
||||
return sel;
|
||||
sel = NewSelector(cx, enclosing, pseudo);
|
||||
if (!sel)
|
||||
return NULL;
|
||||
base->enclosing = sel;
|
||||
return sel;
|
||||
}
|
||||
|
||||
/* check existing enclosing selectors */
|
||||
sel = base->enclosing;
|
||||
do {
|
||||
if (SelectorMatchesToken(cx, sel, enclosing, pseudo))
|
||||
return sel;
|
||||
sel = sel->sibling;
|
||||
if (SelectorMatchesToken(cx, sel, enclosing, pseudo))
|
||||
return sel;
|
||||
sel = sel->sibling;
|
||||
} while (sel);
|
||||
|
||||
/* nothing found that matches, so create a new one */
|
||||
sel = NewSelector(cx, enclosing, pseudo);
|
||||
if (!sel)
|
||||
return NULL;
|
||||
return NULL;
|
||||
sel->sibling = base->enclosing;
|
||||
base->enclosing = sel;
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
|
@ -39,10 +39,10 @@ typedef struct DOM_StyleRule DOM_StyleRule;
|
|||
/* this may become int or something later, for speed */
|
||||
typedef const char *DOM_StyleToken;
|
||||
|
||||
#define DOM_STYLE_PSEUDO_TAG (1 << 7)
|
||||
#define DOM_SELECTOR_IS_PSEUDO(sel) ((sel) & DOM_STYLE_PSEUDO_TAG)
|
||||
#define DOM_STYLE_SELECTOR_TYPE(sel) ((sel) & ~DOM_STYLE_PSEUDO_TAG)
|
||||
#define DOM_PSEUDOIZE(sel) ((sel) | DOM_STYLE_PSEUDO_TAG)
|
||||
#define DOM_STYLE_PSEUDO_TAG (1 << 7)
|
||||
#define DOM_SELECTOR_IS_PSEUDO(sel) ((sel) & DOM_STYLE_PSEUDO_TAG)
|
||||
#define DOM_STYLE_SELECTOR_TYPE(sel) ((sel) & ~DOM_STYLE_PSEUDO_TAG)
|
||||
#define DOM_PSEUDOIZE(sel) ((sel) | DOM_STYLE_PSEUDO_TAG)
|
||||
|
||||
enum {
|
||||
SELECTOR_UNKNOWN = 0
|
||||
|
@ -110,7 +110,7 @@ struct DOM_StyleRule {
|
|||
|
||||
JSBool
|
||||
DOM_StyleAddRule(JSContext *cx, DOM_StyleDatabase *db, const char *rule,
|
||||
uintN len, intN baseWeight);
|
||||
uintN len, intN baseWeight);
|
||||
|
||||
/*
|
||||
* Get a style property for a node.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
|
@ -37,14 +37,14 @@ cdata_getter(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
|
|||
|
||||
if (!JSVAL_IS_INT(id))
|
||||
return JS_TRUE;
|
||||
|
||||
|
||||
slot = JSVAL_TO_INT(id);
|
||||
/* Look, ma! Inheritance! */
|
||||
if (slot <= DOM_NODE_NODENAME &&
|
||||
slot >= DOM_NODE_HASCHILDNODES) {
|
||||
return dom_node_getter(cx, obj, id, vp);
|
||||
}
|
||||
|
||||
|
||||
cdata = (DOM_CharacterData *)JS_GetPrivate(cx, obj);
|
||||
if (!cdata)
|
||||
return JS_TRUE;
|
||||
|
@ -73,17 +73,17 @@ cdata_setter(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
|
|||
intN slot;
|
||||
DOM_CharacterData *cdata;
|
||||
JSString *str;
|
||||
|
||||
|
||||
if (!JSVAL_IS_INT(id))
|
||||
return JS_TRUE;
|
||||
|
||||
|
||||
slot = JSVAL_TO_INT(id);
|
||||
/* Look, ma! Inheritance! */
|
||||
if (slot <= DOM_NODE_NODENAME &&
|
||||
slot >= DOM_NODE_HASCHILDNODES) {
|
||||
return dom_node_setter(cx, obj, id, vp);
|
||||
}
|
||||
|
||||
|
||||
cdata = (DOM_CharacterData *)JS_GetPrivate(cx, obj);
|
||||
if (!cdata)
|
||||
return JS_TRUE;
|
||||
|
@ -118,7 +118,7 @@ cdata_substringData(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
|
|||
|
||||
cdata = (DOM_CharacterData *)JS_GetPrivate(cx, obj);
|
||||
if (!cdata) {
|
||||
*vp = STRING_TO_JSVAL(JS_GetEmptyStringValue(cx));
|
||||
*vp = JS_GetEmptyStringValue(cx);
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
|
@ -129,11 +129,11 @@ cdata_substringData(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
|
|||
|
||||
if (offset + count > cdata->len)
|
||||
count = cdata->len - offset;
|
||||
|
||||
|
||||
substr = JS_NewStringCopyN(cx, cdata->data + offset, count);
|
||||
if (!substr)
|
||||
return JS_FALSE;
|
||||
|
||||
|
||||
*vp = STRING_TO_JSVAL(substr);
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
@ -143,8 +143,9 @@ cdata_appendData(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
|
|||
jsval *vp)
|
||||
{
|
||||
JSString *newData;
|
||||
uint32 newlen;
|
||||
DOM_CharacterData *cdata;
|
||||
uint32 newlen;
|
||||
char *data2;
|
||||
|
||||
if (!JS_ConvertArguments(cx, argc, argv, "S", &newData))
|
||||
return JS_FALSE;
|
||||
|
@ -155,14 +156,14 @@ cdata_appendData(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
|
|||
|
||||
newlen = JS_GetStringLength(newData);
|
||||
|
||||
cdata->data = XP_REALLOC(cdata->data, cdata->len + newlen);
|
||||
if (!cdata->data)
|
||||
data2 = XP_REALLOC(cdata->data, cdata->len + newlen);
|
||||
if (!data2)
|
||||
return JS_FALSE;
|
||||
|
||||
XP_MEMCPY(cdata->data + cdata->len, JS_GetStringBytes(newData),
|
||||
newlen);
|
||||
XP_MEMCPY(data2 + cdata->len, JS_GetStringBytes(newData), newlen);
|
||||
cdata->data = data2;
|
||||
cdata->len += newlen;
|
||||
|
||||
|
||||
return cdata->notify(cx, cdata, CDATA_APPEND);
|
||||
}
|
||||
|
||||
|
@ -289,8 +290,8 @@ static JSClass DOM_CDataClass = {
|
|||
};
|
||||
|
||||
static JSPropertySpec cdata_props[] = {
|
||||
{"data", DOM_CDATA_DATA, JSPROP_ENUMERATE, 0, 0},
|
||||
{"length", DOM_CDATA_LENGTH, JSPROP_ENUMERATE | JSPROP_READONLY,
|
||||
{"data", DOM_CDATA_DATA, JSPROP_ENUMERATE, 0, 0},
|
||||
{"length", DOM_CDATA_LENGTH, JSPROP_ENUMERATE | JSPROP_READONLY,
|
||||
0, 0},
|
||||
{0}
|
||||
};
|
||||
|
@ -299,7 +300,7 @@ static JSFunctionSpec cdata_methods[] = {
|
|||
{"substringData", cdata_substringData, 2},
|
||||
{"appendData", cdata_appendData, 1},
|
||||
{"insertData", cdata_insertData, 2},
|
||||
{"deleteData", cdata_deleteData, 2},
|
||||
{"deleteData", cdata_deleteData, 2},
|
||||
{"replaceData", cdata_replaceData, 3},
|
||||
{0}
|
||||
};
|
||||
|
@ -316,9 +317,9 @@ dom_CharacterDataInit(JSContext *cx, JSObject *scope, JSObject *node_proto)
|
|||
{
|
||||
JSObject *proto;
|
||||
proto = JS_InitClass(cx, scope, node_proto, &DOM_CDataClass,
|
||||
CharacterData, 0,
|
||||
cdata_props, cdata_methods,
|
||||
NULL, NULL);
|
||||
CharacterData, 0,
|
||||
cdata_props, cdata_methods,
|
||||
NULL, NULL);
|
||||
return proto;
|
||||
}
|
||||
|
||||
|
@ -388,7 +389,7 @@ DOM_ObjectForText(JSContext *cx, DOM_Text *text)
|
|||
|
||||
if (text->cdata.node.mocha_object)
|
||||
return text->cdata.node.mocha_object;
|
||||
|
||||
|
||||
return DOM_NewTextObject(cx, text);
|
||||
}
|
||||
|
||||
|
@ -403,9 +404,9 @@ dom_TextInit(JSContext *cx, JSObject *scope, JSObject *cdata_proto)
|
|||
{
|
||||
JSObject *proto;
|
||||
proto = JS_InitClass(cx, scope, cdata_proto, &DOM_TextClass,
|
||||
Text, 0,
|
||||
cdata_props, text_methods,
|
||||
NULL, NULL);
|
||||
Text, 0,
|
||||
cdata_props, text_methods,
|
||||
NULL, NULL);
|
||||
return proto;
|
||||
}
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче