зеркало из https://github.com/mozilla/pjs.git
Remove DOMSetAttribute event guck (now tweak on mocha thread with layout
lock held, and signal reflow via event). Check doc_id before trusting LO_Element *s. Make <TD>.bgcolor mutable. Use DOM_NewElement instead of inline hackery. Defend against NULL returns from DOM_HTMLPopElementByType. Make PR_ASSERTs XP_ASSERT for sake of brave users.
This commit is contained in:
Родитель
8449fcec22
Коммит
ac073e9c77
|
@ -3197,73 +3197,4 @@ ET_DOMReflow(MWContext *context, LO_Element *element, PRBool reflow,
|
||||||
return (int)et_PostEvent(&event->ce, FALSE);
|
return (int)et_PostEvent(&event->ce, FALSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* alter attributes for a layout element */
|
|
||||||
typedef struct {
|
|
||||||
ETEvent ce;
|
|
||||||
TagType tagtype;
|
|
||||||
void *ele1;
|
|
||||||
void *ele2;
|
|
||||||
char *name;
|
|
||||||
char *value;
|
|
||||||
} MozillaEvent_DOMSetAttr;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Set the attributes, and all that.
|
|
||||||
*/
|
|
||||||
PR_STATIC_CALLBACK(int)
|
|
||||||
et_HandleEvent_DOMSetAttr(MozillaEvent_DOMSetAttr *e)
|
|
||||||
{
|
|
||||||
/* check that the doc_id is valid */
|
|
||||||
if(XP_DOCID(e->ce.context) != e->ce.doc_id)
|
|
||||||
return FALSE;
|
|
||||||
|
|
||||||
switch(e->tagtype) {
|
|
||||||
case P_TABLE_DATA:
|
|
||||||
LO_SetTableCellAttributes(e->ce.context, e->ele1, e->name, e->value);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
PR_STATIC_CALLBACK(void)
|
|
||||||
et_DestroyEvent_DOMSetAttr(MozillaEvent_DOMSetAttr *event)
|
|
||||||
{
|
|
||||||
XP_FREE(event->name);
|
|
||||||
XP_FREEIF(event->value);
|
|
||||||
XP_FREE(event);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* arguably, we should define enums or something so that we don't have to
|
|
||||||
* XP_STRCASECMP both in lm_DOMSetAttributes and in the various handler
|
|
||||||
* functions. Later...
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
ET_DOMSetAttributes(MWContext *context, TagType tagtype, void *ele1,
|
|
||||||
void *ele2, const char *name, const char *value,
|
|
||||||
int32 doc_id)
|
|
||||||
{
|
|
||||||
MozillaEvent_DOMSetAttr *event;
|
|
||||||
event = PR_NEW(MozillaEvent_DOMSetAttr);
|
|
||||||
if (!event)
|
|
||||||
return 0;
|
|
||||||
PR_InitEvent(&event->ce.event, context,
|
|
||||||
(PRHandleEventProc)et_HandleEvent_DOMSetAttr,
|
|
||||||
(PRDestroyEventProc)et_DestroyEvent_DOMSetAttr);
|
|
||||||
event->ce.context = context;
|
|
||||||
event->ce.doc_id = doc_id;
|
|
||||||
event->tagtype = tagtype;
|
|
||||||
event->ele1 = ele1;
|
|
||||||
event->ele2 = ele2;
|
|
||||||
event->name = XP_STRDUP(name);
|
|
||||||
if (value)
|
|
||||||
event->value = XP_STRDUP(value);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* we post this synchronously so that a subsequent getAttribute
|
|
||||||
* call will see the right value. We should really cache the value
|
|
||||||
* in the lm_dom.c code so that this isn't necessary, but for now...
|
|
||||||
*/
|
|
||||||
return (int)et_PostEvent(&event->ce, TRUE);
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -40,6 +40,12 @@ PR_BEGIN_MACRO \
|
||||||
LO_UnlockLayout(); \
|
LO_UnlockLayout(); \
|
||||||
PR_END_MACRO
|
PR_END_MACRO
|
||||||
|
|
||||||
|
JSBool
|
||||||
|
lm_CheckNodeDocId(MWContext *context, DOM_HTMLElementPrivate *priv)
|
||||||
|
{
|
||||||
|
return priv->doc_id == context->doc_id;
|
||||||
|
}
|
||||||
|
|
||||||
/* from et_moz.c */
|
/* from et_moz.c */
|
||||||
int
|
int
|
||||||
ET_DOMReflow(MWContext *context, LO_Element *element, PRBool reflow,
|
ET_DOMReflow(MWContext *context, LO_Element *element, PRBool reflow,
|
||||||
|
@ -99,6 +105,19 @@ DOM_NodeOps lm_NodeOps = {
|
||||||
lm_DOMAppendChild, DOM_DestroyNodeStub, lm_DOMReflectNode
|
lm_DOMAppendChild, DOM_DestroyNodeStub, lm_DOMReflectNode
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Signal an exception on doc_id mismatch. Must be called with layout lock
|
||||||
|
* held (unlocks on failure).
|
||||||
|
*/
|
||||||
|
#define CHECK_DOC_ID(context, priv) \
|
||||||
|
PR_BEGIN_MACRO \
|
||||||
|
if (!lm_CheckNodeDocId(context, priv)) { \
|
||||||
|
DOM_SignalException(cx, DOM_WRONG_DOCUMENT_ERR); \
|
||||||
|
LO_UnlockLayout(); \
|
||||||
|
return JS_FALSE; \
|
||||||
|
} \
|
||||||
|
PR_END_MACRO
|
||||||
|
|
||||||
static JSBool
|
static JSBool
|
||||||
lm_DOMSetAttributes(JSContext *cx, DOM_Element *element, const char *name,
|
lm_DOMSetAttributes(JSContext *cx, DOM_Element *element, const char *name,
|
||||||
const char *value)
|
const char *value)
|
||||||
|
@ -107,21 +126,50 @@ lm_DOMSetAttributes(JSContext *cx, DOM_Element *element, const char *name,
|
||||||
MochaDecoder *decoder;
|
MochaDecoder *decoder;
|
||||||
MWContext *context;
|
MWContext *context;
|
||||||
DOM_HTMLElementPrivate *priv;
|
DOM_HTMLElementPrivate *priv;
|
||||||
void *ele1, *ele2;
|
void *ele;
|
||||||
|
lo_DocState *doc;
|
||||||
|
|
||||||
decoder = (MochaDecoder *)JS_GetPrivate(cx, JS_GetGlobalObject(cx));
|
decoder = (MochaDecoder *)JS_GetPrivate(cx, JS_GetGlobalObject(cx));
|
||||||
context = decoder->window_context;
|
context = decoder->window_context;
|
||||||
|
doc = (lo_FetchTopState(context->doc_id))->doc_state;
|
||||||
priv = (DOM_HTMLElementPrivate *)element->node.data;
|
priv = (DOM_HTMLElementPrivate *)element->node.data;
|
||||||
|
|
||||||
switch(priv->tagtype) {
|
switch(priv->tagtype) {
|
||||||
case P_TABLE_DATA:
|
case P_TABLE_DATA: {
|
||||||
if (!XP_STRCASECMP("valign", name) ||
|
LO_Element *iter, *start, *end;
|
||||||
!XP_STRCASECMP("halign", name) ||
|
lo_TableCell *cell;
|
||||||
!XP_STRCASECMP("bgcolor", name)) {
|
|
||||||
ele1 = priv->ele_start;
|
LO_LockLayout();
|
||||||
matched = JS_TRUE;
|
CHECK_DOC_ID(context, priv);
|
||||||
|
cell = (lo_TableCell *)priv->ele_start;
|
||||||
|
if (!cell)
|
||||||
|
goto out_unlock;
|
||||||
|
|
||||||
|
if (!XP_STRCASECMP("valign", name)) {
|
||||||
|
/* tweak valign */
|
||||||
|
} else if(!XP_STRCASECMP("halign", name)) {
|
||||||
|
/* tweak halign */
|
||||||
|
} else if(!XP_STRCASECMP("bgcolor", name)) {
|
||||||
|
LO_Color rgb;
|
||||||
|
start = cell->cell->cell_list;
|
||||||
|
end = cell->cell->cell_list_end;
|
||||||
|
if (!start ||
|
||||||
|
!LO_ParseRGB((char *)value, &rgb.red, &rgb.green, &rgb.blue))
|
||||||
|
goto out_unlock;
|
||||||
|
for (iter = start; iter && iter != end; iter = iter->lo_any.next)
|
||||||
|
lo_SetColor(iter, &rgb, doc, TRUE);
|
||||||
|
if (iter != start)
|
||||||
|
lo_SetColor(start, &rgb, doc, TRUE);
|
||||||
|
} else {
|
||||||
|
/* No match */
|
||||||
|
matched = JS_FALSE;
|
||||||
|
LO_UnlockLayout();
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
LO_UnlockLayout();
|
||||||
|
matched = JS_TRUE;
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
default:;
|
default:;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -130,9 +178,10 @@ lm_DOMSetAttributes(JSContext *cx, DOM_Element *element, const char *name,
|
||||||
return JS_FALSE;
|
return JS_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
ET_DOMSetAttributes(context, priv->tagtype, ele1, ele2,
|
return (JSBool)ET_DOMReflow(context, (LO_Element *)ele, PR_TRUE,
|
||||||
name, value, decoder->doc_id);
|
decoder->doc_id);
|
||||||
|
out_unlock:
|
||||||
|
LO_UnlockLayout();
|
||||||
return JS_TRUE;
|
return JS_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -199,7 +248,10 @@ lm_CDataOp(JSContext *cx, DOM_CharacterData *cdata, DOM_CDataOperationCode op)
|
||||||
* sure we're not a subdoc, etc. All this logic lives in
|
* sure we're not a subdoc, etc. All this logic lives in
|
||||||
* lo_process_title_tag, and should be refactored.
|
* lo_process_title_tag, and should be refactored.
|
||||||
*/
|
*/
|
||||||
FE_SetDocTitle(context, data);
|
LAYLOCKED(
|
||||||
|
CHECK_DOC_ID(context, ELEMENT_PRIV(node));
|
||||||
|
FE_SetDocTitle(context, data);
|
||||||
|
);
|
||||||
return JS_TRUE;
|
return JS_TRUE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -257,25 +309,21 @@ lm_NodeForTag(PA_Tag *tag, DOM_Node *current, MWContext *context, int16 csid)
|
||||||
return NULL;
|
return NULL;
|
||||||
default:
|
default:
|
||||||
/* just a regular old element */
|
/* just a regular old element */
|
||||||
element = XP_NEW_ZAP(DOM_Element);
|
node = (DOM_Node *)
|
||||||
if (!element) {
|
DOM_NewElement(PA_TagString(tag->type), &lm_ElementOps,
|
||||||
|
(char *)PA_FetchParamValue(tag, "name", csid),
|
||||||
|
&lm_NodeOps, 0);
|
||||||
|
if (!node)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
|
||||||
element->ops = &lm_ElementOps;
|
|
||||||
element->tagName = PA_TagString(tag->type);
|
|
||||||
|
|
||||||
node = (DOM_Node *)element;
|
|
||||||
node->type = NODE_TYPE_ELEMENT;
|
|
||||||
/* what about ID? */
|
|
||||||
node->name = (char *)PA_FetchParamValue(tag, "name", csid);
|
|
||||||
node->ops = &lm_NodeOps;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
elepriv = XP_NEW_ZAP(DOM_HTMLElementPrivate);
|
elepriv = XP_NEW_ZAP(DOM_HTMLElementPrivate);
|
||||||
if (!elepriv) {
|
if (!elepriv) {
|
||||||
XP_FREE(element);
|
XP_FREE(element);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
elepriv->tagtype = tag->type;
|
elepriv->tagtype = tag->type;
|
||||||
|
elepriv->doc_id = context->doc_id;
|
||||||
node->data = elepriv;
|
node->data = elepriv;
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
@ -403,6 +451,8 @@ LM_ReflectTagNode(PA_Tag *tag, void *doc_state, MWContext *context)
|
||||||
}
|
}
|
||||||
last_node = (DOM_Node *)DOM_HTMLPopElementByType(tag->type,
|
last_node = (DOM_Node *)DOM_HTMLPopElementByType(tag->type,
|
||||||
(DOM_Element *)CURRENT_NODE(doc));
|
(DOM_Element *)CURRENT_NODE(doc));
|
||||||
|
if (!last_node)
|
||||||
|
return NULL;
|
||||||
CURRENT_NODE(doc) = last_node->parent;
|
CURRENT_NODE(doc) = last_node->parent;
|
||||||
return last_node;
|
return last_node;
|
||||||
}
|
}
|
||||||
|
@ -414,7 +464,7 @@ LM_ReflectTagNode(PA_Tag *tag, void *doc_state, MWContext *context)
|
||||||
fprintf(stderr, "bad push of node %d for tag %d\n",
|
fprintf(stderr, "bad push of node %d for tag %d\n",
|
||||||
node->type, tag->type);
|
node->type, tag->type);
|
||||||
#endif
|
#endif
|
||||||
if (node->ops->destroyNode)
|
if (node->ops && node->ops->destroyNode)
|
||||||
node->ops->destroyNode(context->mocha_context,
|
node->ops->destroyNode(context->mocha_context,
|
||||||
node);
|
node);
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -435,7 +485,7 @@ LM_ReflectTagNode(PA_Tag *tag, void *doc_state, MWContext *context)
|
||||||
tag->type);
|
tag->type);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
PR_ASSERT(!CURRENT_NODE(doc)->parent ||
|
XP_ASSERT(!CURRENT_NODE(doc)->parent ||
|
||||||
CURRENT_NODE(doc)->parent->type != NODE_TYPE_TEXT);
|
CURRENT_NODE(doc)->parent->type != NODE_TYPE_TEXT);
|
||||||
|
|
||||||
return node;
|
return node;
|
||||||
|
@ -499,7 +549,7 @@ DOM_HTMLPopElementByType(TagType type, DOM_Element *element)
|
||||||
/* really, we're closing the enclosing parent */
|
/* really, we're closing the enclosing parent */
|
||||||
element = (DOM_Element *)element->node.parent;
|
element = (DOM_Element *)element->node.parent;
|
||||||
|
|
||||||
PR_ASSERT(element->node.type == NODE_TYPE_ELEMENT);
|
XP_ASSERT(element->node.type == NODE_TYPE_ELEMENT);
|
||||||
if (element->node.type != NODE_TYPE_ELEMENT)
|
if (element->node.type != NODE_TYPE_ELEMENT)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
|
|
@ -30,6 +30,7 @@ typedef struct DOM_HTMLElementPrivate {
|
||||||
TagType tagtype;
|
TagType tagtype;
|
||||||
LO_Element * ele_start;
|
LO_Element * ele_start;
|
||||||
LO_Element * ele_end;
|
LO_Element * ele_end;
|
||||||
|
uint32 doc_id;
|
||||||
} DOM_HTMLElementPrivate;
|
} DOM_HTMLElementPrivate;
|
||||||
|
|
||||||
#define ELEMENT_PRIV(e) ((DOM_HTMLElementPrivate *)(((DOM_Node *)(e))->data))
|
#define ELEMENT_PRIV(e) ((DOM_HTMLElementPrivate *)(((DOM_Node *)(e))->data))
|
||||||
|
@ -54,6 +55,9 @@ lm_DOMInitAttribute(MochaDecoder *decoder);
|
||||||
void
|
void
|
||||||
lm_DestroyDocumentNodes(MWContext *context);
|
lm_DestroyDocumentNodes(MWContext *context);
|
||||||
|
|
||||||
|
JSBool
|
||||||
|
lm_CheckDocId(MWContext *context, DOM_HTMLElementPrivate *priv);
|
||||||
|
|
||||||
#endif /* DOM */
|
#endif /* DOM */
|
||||||
|
|
||||||
#endif /* LM_DOM_H */
|
#endif /* LM_DOM_H */
|
||||||
|
|
Загрузка…
Ссылка в новой задаче