зеркало из https://github.com/mozilla/pjs.git
add destructor to entries
This commit is contained in:
Родитель
49df0a1ecc
Коммит
8d5465ff84
352
lib/libdom/dom.h
352
lib/libdom/dom.h
|
@ -1,352 +0,0 @@
|
|||
/* -*- 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
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* JSAPI DOM stuff, distinct from any HTML/XML embedding.
|
||||
* See http://www.w3.org/DOM/ for details.
|
||||
*/
|
||||
|
||||
#ifndef DOM_H
|
||||
#define DOM_H
|
||||
|
||||
#include "jsapi.h"
|
||||
|
||||
typedef enum DOM_NodeType {
|
||||
NODE_TYPE_ELEMENT = 1,
|
||||
NODE_TYPE_ATTRIBUTE,
|
||||
NODE_TYPE_TEXT,
|
||||
NODE_TYPE_CDATA,
|
||||
NODE_TYPE_ENTITY_REF,
|
||||
NODE_TYPE_ENTITY,
|
||||
NODE_TYPE_PI,
|
||||
NODE_TYPE_COMMENT,
|
||||
NODE_TYPE_DOCUMENT,
|
||||
NODE_TYPE_DOCTYPE,
|
||||
NODE_TYPE_DOCFRAGMENT,
|
||||
NODE_TYPE_NOTATION
|
||||
} DOM_NodeType;
|
||||
|
||||
typedef enum DOM_ExceptionCode {
|
||||
DOM_NONE = 0,
|
||||
DOM_INDEX_SIZE_ERR,
|
||||
DOM_WSTRING_SIZE_ERR,
|
||||
DOM_HIERARCHY_REQUEST_ERR,
|
||||
DOM_WRONG_DOCUMENT_ERR,
|
||||
DOM_INVALID_NAME_ERR,
|
||||
DOM_NO_DATA_ALLOWED_ERR,
|
||||
DOM_NO_MODIFICATION_ALLOWED_ERR,
|
||||
DOM_NOT_FOUND_ERR,
|
||||
DOM_NOT_SUPPORTED_ERR,
|
||||
DOM_INUSE_ATTRIBUTE_ERR,
|
||||
DOM_UNSUPPORTED_DOCUMENT_ERR
|
||||
} 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;
|
||||
|
||||
/*
|
||||
* All of these handlers are called before the DOM tree is manipulated, with
|
||||
* before == JS_TRUE, and then again afterwards, with before == JS_FALSE.
|
||||
*
|
||||
* Before:
|
||||
* Handlers should do nothing but check for legality of the operation in
|
||||
* question, and shouldn't make any changes to the underlying document
|
||||
* structure. They should signal an error with DOM_SignalException as
|
||||
* appropriate and return false if the operation should not be permitted.
|
||||
* This handler will never be called if the DOM code can detect that the
|
||||
* operation in question is illegal (DOM_NOT_CHILD, for example).
|
||||
*
|
||||
* After:
|
||||
* The handlers should perform whatever back-end manipulation is appropriate
|
||||
* 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);
|
||||
|
||||
/* free up Node-private data */
|
||||
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);
|
||||
|
||||
};
|
||||
|
||||
/* stubs */
|
||||
JSBool
|
||||
DOM_InsertBeforeStub(JSContext *cx, DOM_Node *node, DOM_Node *child,
|
||||
DOM_Node *ref, JSBool before);
|
||||
|
||||
JSBool
|
||||
DOM_ReplaceChildStub(JSContext *cx, DOM_Node *node, DOM_Node *child,
|
||||
DOM_Node *old, JSBool before);
|
||||
|
||||
JSBool
|
||||
DOM_RemoveChildStub(JSContext *cx, DOM_Node *node, DOM_Node *old,
|
||||
JSBool before);
|
||||
|
||||
JSBool
|
||||
DOM_AppendChildStub(JSContext *cx, DOM_Node *node, DOM_Node *child,
|
||||
JSBool before);
|
||||
|
||||
void
|
||||
DOM_DestroyNodeStub(JSContext *cx, DOM_Node *node);
|
||||
|
||||
JSObject *
|
||||
DOM_ReflectNodeStub(JSContext *cx, DOM_Node *node);
|
||||
|
||||
/*
|
||||
* ElementOps are called before any JS or DOM reflection occurs,
|
||||
* and an error return (JS_FALSE or NULL) will prevent such
|
||||
* manipulation.
|
||||
*/
|
||||
struct DOM_ElementOps {
|
||||
/*
|
||||
* if this succeeds, pre-existing JS reflections (DOM_Attributes)
|
||||
* will be updated as well. Removal (removeAttribute, etc.) of an
|
||||
* attribute is signalled by passing a value of NULL. The
|
||||
* setAttribute function is responsible for doing
|
||||
* 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.)
|
||||
*/
|
||||
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);
|
||||
|
||||
/* returns number of attributes, or -1 if the number isn't known */
|
||||
intN (*getNumAttrs)(JSContext *cx, DOM_Element *element,
|
||||
JSBool *cacheable);
|
||||
};
|
||||
|
||||
/* stubs */
|
||||
|
||||
JSBool
|
||||
DOM_SetAttributeStub(JSContext *cx, DOM_Element *element, const char *name,
|
||||
const char *value);
|
||||
|
||||
const char *
|
||||
DOM_GetAttributeStub(JSContext *cx, DOM_Element *element, const char *name,
|
||||
JSBool *cacheable);
|
||||
|
||||
intN
|
||||
DOM_GetNumAttrsStub(JSContext *cx, DOM_Element *element, JSBool *cacheable);
|
||||
|
||||
JSBool
|
||||
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 */
|
||||
};
|
||||
|
||||
JSBool
|
||||
DOM_Init(JSContext *cx, JSObject *scope);
|
||||
|
||||
void
|
||||
DOM_DestroyNode(JSContext *cx, DOM_Node *node);
|
||||
|
||||
void
|
||||
DOM_DestroyTree(JSContext *cx, DOM_Node *top);
|
||||
|
||||
JSObject *
|
||||
DOM_NewNodeObject(JSContext *cx, DOM_Node *node);
|
||||
|
||||
JSObject *
|
||||
DOM_ObjectForNode(JSContext *cx, DOM_Node *node);
|
||||
|
||||
JSBool
|
||||
DOM_PushNode(DOM_Node *node, DOM_Node *parent);
|
||||
|
||||
DOM_Node *
|
||||
DOM_PopNode(DOM_Node *node);
|
||||
|
||||
/*
|
||||
* An attribute entry, for name="value".
|
||||
* data is for use by the underlying embedding, to keep it from having to parse
|
||||
* "value" every time. Dirty is set to true when a set operation happens
|
||||
* through the DOM interface, and the embedding can key on that to reparse
|
||||
* "value", and reset data and dirty.
|
||||
*/
|
||||
|
||||
struct DOM_AttributeEntry {
|
||||
const char *name;
|
||||
const char *value;
|
||||
uint32 data;
|
||||
JSBool dirty;
|
||||
};
|
||||
|
||||
struct DOM_Element {
|
||||
DOM_Node node;
|
||||
DOM_ElementOps *ops;
|
||||
const char *tagName;
|
||||
uintN nattrs;
|
||||
DOM_AttributeEntry *attrs;
|
||||
char *styleClass;
|
||||
char *styleID;
|
||||
};
|
||||
|
||||
/*
|
||||
* Create a new Element node.
|
||||
* Caller hands off name and tagName; they're freed at destruction time.
|
||||
*/
|
||||
|
||||
DOM_Element *
|
||||
DOM_NewElement(const char *tagName, DOM_ElementOps *eleops, char *name,
|
||||
char *styleClass, char *styleID, DOM_NodeOps *nodeops);
|
||||
|
||||
JSObject *
|
||||
DOM_NewElementObject(JSContext *cx, DOM_Element *element);
|
||||
|
||||
JSObject *
|
||||
DOM_ObjectForElement(JSContext *cx, DOM_Element *element);
|
||||
|
||||
JSBool
|
||||
DOM_GetElementAttribute(JSContext *cx, DOM_Element *element, const char *name,
|
||||
DOM_AttributeEntry **entryp);
|
||||
|
||||
JSBool
|
||||
DOM_SetElementAttribute(JSContext *cx, DOM_Element *element, const char *name,
|
||||
const char *value);
|
||||
|
||||
typedef JSBool(*DOM_DataParser)(const char *str, uint32 *data, void *closure);
|
||||
|
||||
JSBool
|
||||
DOM_GetCleanEntryData(JSContext *cx, DOM_AttributeEntry *entry,
|
||||
DOM_DataParser parser, uint32 *data, void *closure);
|
||||
|
||||
/*
|
||||
* Set the attributes from a pair of synchronized lists.
|
||||
* (This is what PA_FetchAllNameValues provides, handily enough.)
|
||||
*
|
||||
* The names and values lists should be malloc'd by the caller, and will
|
||||
* be freed by the engine as appropriate.
|
||||
*/
|
||||
JSBool
|
||||
DOM_SetElementAttributes(JSContext *cx, DOM_Element *element,
|
||||
const char **names, const char **values, uintN count);
|
||||
|
||||
/*
|
||||
* Set the attributes from a list that looks like:
|
||||
* name1, value1, name2, value2, ..., name<n>, value<n>, NULL.
|
||||
*
|
||||
* By pure coincidence, this is what the expat start-element callback
|
||||
* provides. What luck!
|
||||
*
|
||||
* The attrs list should be malloc'd by the caller, as well as all the
|
||||
* entries. The DOM engine will free them as appropriate.
|
||||
*/
|
||||
JSBool
|
||||
DOM_SetElementAttributes2(JSContext *cx, DOM_Element *element,
|
||||
const char **attrs);
|
||||
|
||||
/*
|
||||
* Remove all attributes from an element.
|
||||
*/
|
||||
JSBool
|
||||
DOM_ClearElementAttributes(JSContext *cx, DOM_Element *element);
|
||||
|
||||
struct DOM_Attribute {
|
||||
DOM_Node node;
|
||||
char * name;
|
||||
DOM_Element *element;
|
||||
};
|
||||
|
||||
DOM_Attribute *
|
||||
DOM_NewAttribute(const char *name, const char *value, DOM_Element *element);
|
||||
|
||||
JSObject *
|
||||
DOM_NewAttributeObject(JSContext *cx, DOM_Attribute *attr);
|
||||
|
||||
JSObject *
|
||||
DOM_ObjectForAttribute(JSContext *cx, DOM_Attribute *attr);
|
||||
|
||||
JSBool
|
||||
DOM_SignalException(JSContext *cx, DOM_ExceptionCode code);
|
||||
|
||||
JSObject *
|
||||
DOM_ObjectForNodeDowncast(JSContext *cx, DOM_Node *node);
|
||||
|
||||
struct DOM_Document {
|
||||
DOM_Node node;
|
||||
};
|
||||
|
||||
typedef enum DOM_CDataOperationCode {
|
||||
CDATA_APPEND,
|
||||
CDATA_INSERT,
|
||||
CDATA_DELETE,
|
||||
CDATA_REPLACE
|
||||
} DOM_CDataOperationCode;
|
||||
|
||||
typedef JSBool (*DOM_CDataOp)(JSContext *cx, DOM_CharacterData *cdata,
|
||||
DOM_CDataOperationCode op);
|
||||
|
||||
struct DOM_CharacterData {
|
||||
DOM_Node node;
|
||||
char *data;
|
||||
uintN len;
|
||||
DOM_CDataOp notify;
|
||||
};
|
||||
|
||||
struct DOM_Text {
|
||||
DOM_CharacterData cdata;
|
||||
};
|
||||
|
||||
DOM_Text *
|
||||
DOM_NewText(const char *data, int64 len, DOM_CDataOp notify,
|
||||
DOM_NodeOps *ops);
|
||||
|
||||
JSObject *
|
||||
DOM_NewTextObject(JSContext *cx, DOM_Text *text);
|
||||
|
||||
JSObject *
|
||||
DOM_ObjectForText(JSContext *cx, DOM_Text *text);
|
||||
|
||||
struct DOM_Comment {
|
||||
DOM_CharacterData cdata;
|
||||
};
|
||||
|
||||
#endif /* DOM_H */
|
|
@ -1,391 +0,0 @@
|
|||
/* -*- 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
|
||||
* 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 Element implementation.
|
||||
*/
|
||||
|
||||
#include "dom_priv.h"
|
||||
|
||||
static JSPropertySpec element_props[] = {
|
||||
{"tagName", DOM_ELEMENT_TAGNAME, JSPROP_READONLY, 0, 0},
|
||||
{0}
|
||||
};
|
||||
|
||||
static JSBool
|
||||
element_getter(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
|
||||
{
|
||||
intN slot;
|
||||
DOM_Element *element;
|
||||
|
||||
if (!JSVAL_IS_INT(id))
|
||||
return JS_TRUE;
|
||||
|
||||
slot = JSVAL_TO_INT(id);
|
||||
|
||||
/*
|
||||
* Look, ma! Inheritance!
|
||||
* We handle .attributes ourselves because we return something other
|
||||
* than null, unlike every other Node subclass.
|
||||
*/
|
||||
if (slot != DOM_NODE_ATTRIBUTES &&
|
||||
slot <= DOM_NODE_NODENAME &&
|
||||
slot >= DOM_NODE_HASCHILDNODES) {
|
||||
return dom_node_getter(cx, obj, id, vp);
|
||||
}
|
||||
|
||||
element = (DOM_Element *)JS_GetPrivate(cx, obj);
|
||||
if (!element)
|
||||
return JS_TRUE;
|
||||
|
||||
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);
|
||||
#else
|
||||
tagName = JS_NewStringCopyZ(cx, element->tagName
|
||||
? element->tagName
|
||||
: "#tag");
|
||||
#endif
|
||||
if (!tagName)
|
||||
return JS_FALSE;
|
||||
*vp = STRING_TO_JSVAL(tagName);
|
||||
}
|
||||
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
static JSBool
|
||||
element_setter(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
|
||||
{
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
static JSClass DOM_ElementClass = {
|
||||
"Element", JSCLASS_HAS_PRIVATE,
|
||||
JS_PropertyStub, JS_PropertyStub, element_getter, element_setter,
|
||||
JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, dom_node_finalize
|
||||
};
|
||||
|
||||
static JSBool
|
||||
element_getAttribute(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
|
||||
jsval *rval)
|
||||
{
|
||||
DOM_Element *element;
|
||||
JSString *name;
|
||||
DOM_AttributeEntry *entry;
|
||||
|
||||
if (!JS_ConvertArguments(cx, argc, argv, "S", &name))
|
||||
return JS_FALSE;
|
||||
|
||||
element = (DOM_Element *)JS_GetPrivate(cx, obj);
|
||||
if (!element)
|
||||
return JS_TRUE;
|
||||
|
||||
if (!DOM_GetElementAttribute(cx, element, JS_GetStringBytes(name),
|
||||
&entry))
|
||||
return JS_FALSE;
|
||||
|
||||
if (entry && entry->value) {
|
||||
JSString *valstr = JS_NewStringCopyZ(cx, entry->value);
|
||||
if (!valstr)
|
||||
return JS_FALSE;
|
||||
*rval = STRING_TO_JSVAL(valstr);
|
||||
} else {
|
||||
*rval = JS_GetEmptyStringValue(cx);
|
||||
}
|
||||
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
static JSBool
|
||||
element_setAttribute(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
|
||||
jsval *rval)
|
||||
{
|
||||
DOM_Element *element;
|
||||
char *name, *value;
|
||||
|
||||
if (!JS_ConvertArguments(cx, argc, argv, "ss", &name, &value))
|
||||
return JS_FALSE;
|
||||
|
||||
element = (DOM_Element *)JS_GetPrivate(cx, obj);
|
||||
if (!element)
|
||||
return JS_TRUE;
|
||||
|
||||
return DOM_SetElementAttribute(cx, element, name, value);
|
||||
|
||||
}
|
||||
|
||||
static JSBool
|
||||
element_removeAttribute(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
|
||||
jsval *rval)
|
||||
{
|
||||
DOM_Element *element;
|
||||
JSString *name;
|
||||
|
||||
if (!JS_ConvertArguments(cx, argc, argv, "S", &name))
|
||||
return JS_FALSE;
|
||||
|
||||
element = (DOM_Element *)JS_GetPrivate(cx, obj);
|
||||
if (!element)
|
||||
return JS_TRUE;
|
||||
|
||||
/* NULL setAttribute call indicates removal */
|
||||
return element->ops->setAttribute(cx, element, JS_GetStringBytes(name),
|
||||
NULL);
|
||||
|
||||
}
|
||||
|
||||
static JSBool
|
||||
element_getAttributeNode(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
|
||||
jsval *rval)
|
||||
{
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
static JSBool
|
||||
element_setAttributeNode(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
|
||||
jsval *rval)
|
||||
{
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
static JSBool
|
||||
element_removeAttributeNode(JSContext *cx, JSObject *obj, uintN argc,
|
||||
jsval *argv, jsval *rval)
|
||||
{
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
static JSFunctionSpec element_methods[] = {
|
||||
{"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}
|
||||
};
|
||||
|
||||
DOM_Element *
|
||||
DOM_NewElement(const char *tagName, DOM_ElementOps *eleops, char *name,
|
||||
char *styleClass, char *styleID, DOM_NodeOps *nodeops)
|
||||
{
|
||||
DOM_Node *node;
|
||||
DOM_Element *element = XP_NEW_ZAP(DOM_Element);
|
||||
if (!element)
|
||||
return NULL;
|
||||
|
||||
node = (DOM_Node *)element;
|
||||
node->type = NODE_TYPE_ELEMENT;
|
||||
node->name = name;
|
||||
node->ops = nodeops;
|
||||
|
||||
element->tagName = tagName;
|
||||
element->styleClass = styleClass;
|
||||
element->styleID = styleID;
|
||||
element->ops = eleops;
|
||||
|
||||
return element;
|
||||
}
|
||||
|
||||
JSObject *
|
||||
DOM_NewElementObject(JSContext *cx, DOM_Element *element)
|
||||
{
|
||||
JSObject *obj;
|
||||
|
||||
obj = JS_ConstructObject(cx, &DOM_ElementClass, NULL, NULL);
|
||||
if (!obj)
|
||||
return NULL;
|
||||
if (!JS_SetPrivate(cx, obj, element))
|
||||
return NULL;
|
||||
element->node.mocha_object = obj;
|
||||
return obj;
|
||||
}
|
||||
|
||||
JSObject *
|
||||
DOM_ObjectForElement(JSContext *cx, DOM_Element *element)
|
||||
{
|
||||
if (!element)
|
||||
return NULL;
|
||||
if (element->node.mocha_object)
|
||||
return element->node.mocha_object;
|
||||
return DOM_NewElementObject(cx, element);
|
||||
}
|
||||
|
||||
static void
|
||||
DestroyAttrs(JSContext *cx, DOM_Element *element)
|
||||
{
|
||||
uintN i;
|
||||
DOM_AttributeEntry *entry;
|
||||
for (i = 0; i < element->nattrs; i++) {
|
||||
entry = element->attrs + i;
|
||||
JS_free(cx, (char *)entry->name);
|
||||
JS_free(cx, (char *)entry->value);
|
||||
JS_free(cx, entry);
|
||||
}
|
||||
JS_free(cx, element->attrs);
|
||||
element->attrs = NULL;
|
||||
element->nattrs = 0;
|
||||
}
|
||||
|
||||
JSBool
|
||||
DOM_SetElementAttributes(JSContext *cx, DOM_Element *element,
|
||||
const char **names, const char **values, uintN count)
|
||||
{
|
||||
DOM_AttributeEntry *entry;
|
||||
uintN i;
|
||||
|
||||
if (element->attrs)
|
||||
DestroyAttrs(cx, element);
|
||||
if (!(count && names && values))
|
||||
return JS_TRUE;
|
||||
element->attrs =
|
||||
(DOM_AttributeEntry *)JS_malloc(cx,count * sizeof(DOM_AttributeEntry));
|
||||
if (!element->attrs)
|
||||
return JS_FALSE;
|
||||
element->nattrs = count;
|
||||
|
||||
#ifdef DEBUG_shaver_attributes
|
||||
fprintf(stderr, "ELEMENT %p has %d attrs\n", element,
|
||||
element->nattrs);
|
||||
#endif
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
entry = element->attrs + i;
|
||||
entry->name = names[i];
|
||||
entry->value = values[i];
|
||||
entry->dirty = entry->data = 0;
|
||||
}
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
JSBool
|
||||
DOM_GetElementAttribute(JSContext *cx, DOM_Element *element, const char *name,
|
||||
DOM_AttributeEntry **entryp)
|
||||
{
|
||||
DOM_AttributeEntry *entry;
|
||||
uintN i;
|
||||
|
||||
for (i = 0, entry = element->attrs;
|
||||
i < element->nattrs && entry->name;
|
||||
i++, entry++) {
|
||||
if (!strcmp(name, entry->name)) {
|
||||
*entryp = entry;
|
||||
return JS_TRUE;
|
||||
}
|
||||
}
|
||||
*entryp = NULL;
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
JSBool
|
||||
DOM_GetCleanEntryData(JSContext *cx, DOM_AttributeEntry *entry,
|
||||
DOM_DataParser parser, uint32 *data, void *closure)
|
||||
{
|
||||
if (entry->dirty) {
|
||||
uint32 newdata;
|
||||
if (!parser(entry->value, &newdata, closure))
|
||||
return JS_FALSE;
|
||||
entry->data = newdata;
|
||||
entry->dirty = JS_FALSE;
|
||||
}
|
||||
*data = entry->data;
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
static DOM_AttributeEntry *
|
||||
AddAttribute(JSContext *cx, DOM_Element *element, const char *name,
|
||||
const char *value)
|
||||
{
|
||||
DOM_AttributeEntry *entry;
|
||||
|
||||
if (!element->attrs) {
|
||||
element->attrs = JS_malloc(cx, sizeof(DOM_AttributeEntry));
|
||||
if (!element->attrs)
|
||||
return NULL;
|
||||
element->nattrs = 1;
|
||||
} else {
|
||||
element->attrs = XP_REALLOC(element->attrs,
|
||||
(element->nattrs++) * sizeof(DOM_AttributeEntry));
|
||||
if (!element->attrs)
|
||||
return NULL;
|
||||
}
|
||||
entry = element->attrs + element->nattrs - 1;
|
||||
entry->name = name;
|
||||
entry->value = value;
|
||||
#ifdef DEBUG_shaver_attributes
|
||||
fprintf(stderr,
|
||||
"ELEMENT %p has %d attrs after adding #%d %p/%s=%p/%s @ %p\n",
|
||||
element, element->nattrs, entry - element->attrs, entry->name,
|
||||
entry->name, entry->value, entry->value, entry);
|
||||
#endif
|
||||
return entry;
|
||||
}
|
||||
|
||||
JSBool
|
||||
dom_SetElementAttribute(JSContext *cx, DOM_Element *element, const char *name,
|
||||
const char *value, JSBool runCallback)
|
||||
{
|
||||
DOM_AttributeEntry *entry;
|
||||
if (!DOM_GetElementAttribute(cx, element, name, &entry))
|
||||
return JS_FALSE;
|
||||
if (!entry) {
|
||||
entry = AddAttribute(cx, element, name, value);
|
||||
if (!entry)
|
||||
return JS_FALSE;
|
||||
} else {
|
||||
if (entry->value)
|
||||
JS_free(cx, (char *)entry->value);
|
||||
entry->value = value;
|
||||
}
|
||||
entry->dirty = JS_TRUE;
|
||||
|
||||
if (!runCallback)
|
||||
return JS_TRUE;
|
||||
return element->ops->setAttribute(cx, element, name, value);
|
||||
}
|
||||
|
||||
JSBool
|
||||
DOM_SetElementAttribute(JSContext *cx, DOM_Element *element, const char *name,
|
||||
const char *value)
|
||||
{
|
||||
return dom_SetElementAttribute(cx, element, name, value, JS_TRUE);
|
||||
}
|
||||
|
||||
static JSBool
|
||||
Element(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *vp)
|
||||
{
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
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);
|
||||
if (!JS_DefineProperties(cx, proto, dom_node_props))
|
||||
return NULL;
|
||||
return proto;
|
||||
}
|
Загрузка…
Ссылка в новой задаче