Don't use tinyids in jsxml.cpp (569114, r=jorendorff).

This commit is contained in:
Andreas Gal 2010-05-30 17:02:09 -07:00
parent 8b429d23a7
commit c84cee0514
3 changed files with 66 additions and 219 deletions

View File

@ -1068,10 +1068,6 @@ JS_SetGlobalObject(JSContext *cx, JSObject *obj)
{
CHECK_REQUEST(cx);
cx->globalObject = obj;
#if JS_HAS_XML_SUPPORT
cx->xmlSettingFlags = 0;
#endif
}
JS_BEGIN_EXTERN_C

View File

@ -1649,19 +1649,6 @@ struct JSContext
/* JSRuntime contextList linkage. */
JSCList link;
#if JS_HAS_XML_SUPPORT
/*
* Bit-set formed from binary exponentials of the XML_* tiny-ids defined
* for boolean settings in jsxml.c, plus an XSF_CACHE_VALID bit. Together
* these act as a cache of the boolean XML.ignore* and XML.prettyPrinting
* property values associated with this context's global object.
*/
uint8 xmlSettingFlags;
uint8 padding;
#else
uint16 padding;
#endif
/*
* Classic Algol "display" static link optimization.
*/

View File

@ -185,33 +185,21 @@ AppendString(JSCharBuffer &cb, JSString *str)
return cb.append(chars, end);
}
#define DEFINE_GETTER(name,code) \
static JSBool \
name(JSContext *cx, JSObject *obj, jsval id, jsval *vp) \
{ \
{ code; } \
return true; \
}
/*
* Namespace class and library functions.
*/
enum namespace_tinyid {
NAMESPACE_PREFIX = -1,
NAMESPACE_URI = -2
};
static JSBool
namespace_getProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
{
if (!JSVAL_IS_INT(id))
return JS_TRUE;
if (obj->getClass() != &js_NamespaceClass.base)
return JS_TRUE;
switch (JSVAL_TO_INT(id)) {
case NAMESPACE_PREFIX:
*vp = obj->getNamePrefix();
break;
case NAMESPACE_URI:
*vp = obj->getNameURI();
break;
}
return JS_TRUE;
}
DEFINE_GETTER(NamePrefix_getter,
*vp = (obj->getClass() == &js_NamespaceClass.base) ? obj->getNamePrefix() : *vp)
DEFINE_GETTER(NameURI_getter,
*vp = (obj->getClass() == &js_NamespaceClass.base) ? obj->getNameURI() : *vp)
static void
namespace_finalize(JSContext *cx, JSObject *obj)
@ -238,7 +226,7 @@ JS_FRIEND_DATA(JSExtendedClass) js_NamespaceClass = {
JSCLASS_CONSTRUCT_PROTOTYPE | JSCLASS_IS_EXTENDED |
JSCLASS_HAS_RESERVED_SLOTS(JSObject::NAMESPACE_FIXED_RESERVED_SLOTS) |
JSCLASS_MARK_IS_TRACE | JSCLASS_HAS_CACHED_PROTO(JSProto_Namespace),
JS_PropertyStub, JS_PropertyStub, namespace_getProperty, NULL,
JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, namespace_finalize,
NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL },
@ -250,8 +238,8 @@ JS_FRIEND_DATA(JSExtendedClass) js_NamespaceClass = {
(JSPROP_ENUMERATE | JSPROP_READONLY | JSPROP_PERMANENT | JSPROP_SHARED)
static JSPropertySpec namespace_props[] = {
{js_prefix_str, NAMESPACE_PREFIX, NAMESPACE_ATTRS, 0, 0},
{js_uri_str, NAMESPACE_URI, NAMESPACE_ATTRS, 0, 0},
{js_prefix_str, 0, NAMESPACE_ATTRS, NamePrefix_getter, 0},
{js_uri_str, 0, NAMESPACE_ATTRS, NameURI_getter, 0},
{0,0,0,0,0}
};
@ -296,32 +284,11 @@ NewXMLNamespace(JSContext *cx, JSString *prefix, JSString *uri, JSBool declared)
/*
* QName class and library functions.
*/
enum qname_tinyid {
QNAME_URI = -1,
QNAME_LOCALNAME = -2
};
static JSBool
qname_getProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
{
if (!JSVAL_IS_INT(id))
return JS_TRUE;
if (obj->getClass() != &js_QNameClass.base)
return JS_TRUE;
switch (JSVAL_TO_INT(id)) {
case QNAME_URI:
*vp = obj->getNameURI();
if (*vp == JSVAL_VOID)
*vp = JSVAL_NULL;
break;
case QNAME_LOCALNAME:
*vp = obj->getQNameLocalName();
break;
}
return JS_TRUE;
}
DEFINE_GETTER(QNameNameURI_getter,
*vp = (obj->getClass() == &js_QNameClass.base)
? (JSVAL_IS_VOID(obj->getNameURI()) ? JSVAL_NULL : obj->getNameURI()) : *vp)
DEFINE_GETTER(QNameLocalName_getter,
*vp = (obj->getClass() == &js_QNameClass.base) ? obj->getQNameLocalName() : *vp)
static void
anyname_finalize(JSContext* cx, JSObject* obj)
@ -362,7 +329,7 @@ JS_FRIEND_DATA(JSExtendedClass) js_QNameClass = {
JSCLASS_CONSTRUCT_PROTOTYPE | JSCLASS_IS_EXTENDED |
JSCLASS_HAS_RESERVED_SLOTS(JSObject::QNAME_FIXED_RESERVED_SLOTS) |
JSCLASS_MARK_IS_TRACE | JSCLASS_HAS_CACHED_PROTO(JSProto_QName),
JS_PropertyStub, JS_PropertyStub, qname_getProperty, NULL,
JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, NULL,
NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL },
@ -402,8 +369,8 @@ JS_FRIEND_DATA(JSClass) js_AnyNameClass = {
(JSPROP_ENUMERATE | JSPROP_READONLY | JSPROP_PERMANENT | JSPROP_SHARED)
static JSPropertySpec qname_props[] = {
{js_uri_str, QNAME_URI, QNAME_ATTRS, 0, 0},
{js_localName_str, QNAME_LOCALNAME, QNAME_ATTRS, 0, 0},
{js_uri_str, 0, QNAME_ATTRS, QNameNameURI_getter, 0},
{js_localName_str, 0, QNAME_ATTRS, QNameLocalName_getter, 0},
{0,0,0,0,0}
};
@ -1080,7 +1047,7 @@ XMLArrayTruncate(JSContext *cx, JSXMLArray *array, uint32 length)
/*
* Define XML setting property strings and constants early, so everyone can
* use the same names and their magic numbers (tinyids, flags).
* use the same names.
*/
static const char js_ignoreComments_str[] = "ignoreComments";
static const char js_ignoreProcessingInstructions_str[]
@ -1089,79 +1056,20 @@ static const char js_ignoreWhitespace_str[] = "ignoreWhitespace";
static const char js_prettyPrinting_str[] = "prettyPrinting";
static const char js_prettyIndent_str[] = "prettyIndent";
/*
* NB: These XML static property tinyids must
* (a) not collide with the generic negative tinyids at the top of jsfun.cpp;
* (b) index their corresponding xml_static_props array elements.
* Don't change 'em!
*/
enum xml_static_tinyid {
XML_IGNORE_COMMENTS,
XML_IGNORE_PROCESSING_INSTRUCTIONS,
XML_IGNORE_WHITESPACE,
XML_PRETTY_PRINTING,
XML_PRETTY_INDENT
};
static JSBool
xml_setting_getter(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
{
return JS_TRUE;
}
static JSBool
xml_setting_setter(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
{
uint8 flag;
JS_ASSERT(JSVAL_IS_INT(id));
flag = JS_BIT(JSVAL_TO_INT(id));
if (js_ValueToBoolean(*vp))
cx->xmlSettingFlags |= flag;
else
cx->xmlSettingFlags &= ~flag;
return JS_TRUE;
}
#define XSF_IGNORE_COMMENTS JS_BIT(0)
#define XSF_IGNORE_PROCESSING_INSTRUCTIONS JS_BIT(1)
#define XSF_IGNORE_WHITESPACE JS_BIT(2)
#define XSF_PRETTY_PRINTING JS_BIT(3)
static JSPropertySpec xml_static_props[] = {
{js_ignoreComments_str, XML_IGNORE_COMMENTS, JSPROP_PERMANENT,
xml_setting_getter, xml_setting_setter},
{js_ignoreProcessingInstructions_str,
XML_IGNORE_PROCESSING_INSTRUCTIONS, JSPROP_PERMANENT,
xml_setting_getter, xml_setting_setter},
{js_ignoreWhitespace_str, XML_IGNORE_WHITESPACE, JSPROP_PERMANENT,
xml_setting_getter, xml_setting_setter},
{js_prettyPrinting_str, XML_PRETTY_PRINTING, JSPROP_PERMANENT,
xml_setting_getter, xml_setting_setter},
{js_prettyIndent_str, XML_PRETTY_INDENT, JSPROP_PERMANENT,
xml_setting_getter, NULL},
{js_ignoreComments_str, 0, JSPROP_PERMANENT, NULL, NULL},
{js_ignoreProcessingInstructions_str, 0, JSPROP_PERMANENT, NULL, NULL},
{js_ignoreWhitespace_str, 0, JSPROP_PERMANENT, NULL, NULL},
{js_prettyPrinting_str, 0, JSPROP_PERMANENT, NULL, NULL},
{js_prettyIndent_str, 0, JSPROP_PERMANENT, NULL, NULL},
{0,0,0,0,0}
};
/* Derive cx->xmlSettingFlags bits from xml_static_props tinyids. */
#define XSF_IGNORE_COMMENTS JS_BIT(XML_IGNORE_COMMENTS)
#define XSF_IGNORE_PROCESSING_INSTRUCTIONS \
JS_BIT(XML_IGNORE_PROCESSING_INSTRUCTIONS)
#define XSF_IGNORE_WHITESPACE JS_BIT(XML_IGNORE_WHITESPACE)
#define XSF_PRETTY_PRINTING JS_BIT(XML_PRETTY_PRINTING)
#define XSF_CACHE_VALID JS_BIT(XML_PRETTY_INDENT)
/*
* Extra, unrelated but necessarily disjoint flag used by ParseNodeToXML.
* This flag means a couple of things:
*
* - The top JSXML created for a parse tree must have an object owning it.
*
* - That the default namespace normally inherited from the temporary
* <parent xmlns='...'> tag that wraps a runtime-concatenated XML source
* string must, in the case of a precompiled XML object tree, inherit via
* ad-hoc code in ParseNodeToXML.
*
* Because of the second purpose, we name this flag XSF_PRECOMPILED_ROOT.
*/
#define XSF_PRECOMPILED_ROOT (XSF_CACHE_VALID << 1)
/* Macros for special-casing xml:, xmlns= and xmlns:foo= in ParseNodeToQName. */
#define IS_XML(str) \
(str->length() == 3 && IS_XML_CHARS(str->chars()))
@ -1345,7 +1253,6 @@ ParseNodeToXML(Parser *parser, JSParseNode *pn,
if (!xml)
goto fail;
flags &= ~XSF_PRECOMPILED_ROOT;
n = pn->pn_count;
JS_ASSERT(n >= 2);
n -= 2;
@ -1525,22 +1432,6 @@ ParseNodeToXML(Parser *parser, JSParseNode *pn,
pnp = &pn2->pn_next;
}
/*
* If called from js_ParseNodeToXMLObject, emulate the effect of the
* <parent xmlns='%s'>...</parent> wrapping done by "ToXML Applied to
* the String Type" (ECMA-357 10.3.1).
*/
if (flags & XSF_PRECOMPILED_ROOT) {
JS_ASSERT(length >= 1);
ns = XMLARRAY_MEMBER(inScopeNSes, 0, JSObject);
JS_ASSERT(!XMLARRAY_HAS_MEMBER(&xml->xml_namespaces, ns,
namespace_identity));
ns = NewXMLNamespace(cx, GetPrefix(ns), GetURI(ns), JS_FALSE);
if (!ns)
goto fail;
if (!XMLARRAY_APPEND(cx, &xml->xml_namespaces, ns))
goto fail;
}
XMLArrayTrim(&xml->xml_namespaces);
/* Second pass: process tag name and attributes, using namespaces. */
@ -1648,8 +1539,6 @@ ParseNodeToXML(Parser *parser, JSParseNode *pn,
}
js_LeaveLocalRootScopeWithResult(cx, (jsval) xml);
if ((flags & XSF_PRECOMPILED_ROOT) && !js_GetXMLObject(cx, xml))
return NULL;
return xml;
skip_child:
@ -1683,44 +1572,12 @@ GetXMLSetting(JSContext *cx, const char *name, jsval *vp)
return JS_GetProperty(cx, JSVAL_TO_OBJECT(v), name, vp);
}
static JSBool
FillSettingsCache(JSContext *cx)
{
int i;
const char *name;
jsval v;
/* Note: XML_PRETTY_INDENT is not a boolean setting. */
for (i = XML_IGNORE_COMMENTS; i < XML_PRETTY_INDENT; i++) {
name = xml_static_props[i].name;
if (!GetXMLSetting(cx, name, &v))
return JS_FALSE;
if (js_ValueToBoolean(v))
cx->xmlSettingFlags |= JS_BIT(i);
else
cx->xmlSettingFlags &= ~JS_BIT(i);
}
cx->xmlSettingFlags |= XSF_CACHE_VALID;
return JS_TRUE;
}
static JSBool
GetBooleanXMLSetting(JSContext *cx, const char *name, JSBool *bp)
{
int i;
jsval v;
if (!(cx->xmlSettingFlags & XSF_CACHE_VALID) && !FillSettingsCache(cx))
return JS_FALSE;
for (i = 0; xml_static_props[i].name; i++) {
if (!strcmp(xml_static_props[i].name, name)) {
*bp = (cx->xmlSettingFlags & JS_BIT(i)) != 0;
return JS_TRUE;
}
}
*bp = JS_FALSE;
return JS_TRUE;
return GetXMLSetting(cx, name, &v) && JS_ValueToBoolean(cx, v, bp);
}
static JSBool
@ -1734,13 +1591,20 @@ GetUint32XMLSetting(JSContext *cx, const char *name, uint32 *uip)
static JSBool
GetXMLSettingFlags(JSContext *cx, uintN *flagsp)
{
JSBool flag;
JSBool flag[4];
/* Just get the first flag to validate the setting flags cache. */
if (!GetBooleanXMLSetting(cx, js_ignoreComments_str, &flag))
return JS_FALSE;
*flagsp = cx->xmlSettingFlags;
return JS_TRUE;
if (!GetBooleanXMLSetting(cx, js_ignoreComments_str, &flag[0]) ||
!GetBooleanXMLSetting(cx, js_ignoreProcessingInstructions_str, &flag[1]) ||
!GetBooleanXMLSetting(cx, js_ignoreWhitespace_str, &flag[2]) ||
!GetBooleanXMLSetting(cx, js_prettyPrinting_str, &flag[3])) {
return false;
}
*flagsp = 0;
for (size_t n = 0; n < 4; ++n)
if (flag[n])
*flagsp |= JS_BIT(n);
return true;
}
static JSXML *
@ -6810,20 +6674,23 @@ CopyXMLSettings(JSContext *cx, JSObject *from, JSObject *to)
const char *name;
jsval v;
for (i = XML_IGNORE_COMMENTS; i < XML_PRETTY_INDENT; i++) {
/* Note: PRETTY_INDENT is not a boolean setting. */
for (i = 0; xml_static_props[i].name; i++) {
name = xml_static_props[i].name;
if (!JS_GetProperty(cx, from, name, &v))
return JS_FALSE;
if (JSVAL_IS_BOOLEAN(v) && !JS_SetProperty(cx, to, name, &v))
return JS_FALSE;
return false;
if (name == js_prettyIndent_str) {
if (!JSVAL_IS_NUMBER(v))
continue;
} else {
if (!JSVAL_IS_BOOLEAN(v))
continue;
}
if (!JS_SetProperty(cx, to, name, &v))
return false;
}
name = xml_static_props[i].name;
if (!JS_GetProperty(cx, from, name, &v))
return JS_FALSE;
if (JSVAL_IS_NUMBER(v) && !JS_SetProperty(cx, to, name, &v))
return JS_FALSE;
return JS_TRUE;
return true;
}
static JSBool
@ -6832,13 +6699,14 @@ SetDefaultXMLSettings(JSContext *cx, JSObject *obj)
int i;
jsval v;
for (i = XML_IGNORE_COMMENTS; i < XML_PRETTY_INDENT; i++) {
v = JSVAL_TRUE;
/* Note: PRETTY_INDENT is not a boolean setting. */
for (i = 0; xml_static_props[i].name; i++) {
v = (xml_static_props[i].name != js_prettyIndent_str)
? JSVAL_TRUE : INT_TO_JSVAL(2);
if (!JS_SetProperty(cx, obj, xml_static_props[i].name, &v))
return JS_FALSE;
}
v = INT_TO_JSVAL(2);
return JS_SetProperty(cx, obj, xml_static_props[i].name, &v);
return true;
}
static JSBool
@ -6867,17 +6735,13 @@ xml_setSettings(JSContext *cx, uintN argc, jsval *vp)
return JS_FALSE;
v = (argc == 0) ? JSVAL_VOID : vp[2];
if (JSVAL_IS_NULL(v) || JSVAL_IS_VOID(v)) {
cx->xmlSettingFlags = 0;
ok = SetDefaultXMLSettings(cx, obj);
} else {
if (JSVAL_IS_PRIMITIVE(v))
return JS_TRUE;
settings = JSVAL_TO_OBJECT(v);
cx->xmlSettingFlags = 0;
ok = CopyXMLSettings(cx, settings, obj);
}
if (ok)
cx->xmlSettingFlags |= XSF_CACHE_VALID;
return ok;
}