Add JS_EnumerateResolvedStandardClasses, and fix a few lazy-standard-class-init glitches hindering it (292903, r=shaver, a=me).

This commit is contained in:
brendan%mozilla.org 2005-06-16 04:24:03 +00:00
Родитель d029c0d690
Коммит ea0bf58dc3
8 изменённых файлов: 159 добавлений и 38 удалений

Просмотреть файл

@ -1235,6 +1235,11 @@ static struct {
#endif #endif
#if JS_HAS_SCRIPT_OBJECT #if JS_HAS_SCRIPT_OBJECT
{js_InitScriptClass, ATOM_OFFSET(Script)}, {js_InitScriptClass, ATOM_OFFSET(Script)},
#endif
#if JS_HAS_XML_SUPPORT
{js_InitXMLClass, ATOM_OFFSET(XML)},
{js_InitNamespaceClass, ATOM_OFFSET(Namespace)},
{js_InitQNameClass, ATOM_OFFSET(QName)},
#endif #endif
{NULL, 0} {NULL, 0}
}; };
@ -1308,13 +1313,10 @@ static JSStdName standard_class_names[] = {
#endif #endif
#if JS_HAS_XML_SUPPORT #if JS_HAS_XML_SUPPORT
{js_InitXMLClass, LAZILY_PINNED_ATOM(isXMLName)}, {js_InitAnyNameClass, LAZILY_PINNED_ATOM(AnyName)},
{js_InitNamespaceClass, LAZILY_PINNED_ATOM(Namespace)}, {js_InitAttributeNameClass, LAZILY_PINNED_ATOM(AttributeName)},
{js_InitQNameClass, LAZILY_PINNED_ATOM(QName)},
{js_InitQNameClass, LAZILY_PINNED_ATOM(AnyName)},
{js_InitQNameClass, LAZILY_PINNED_ATOM(AttributeName)},
{js_InitXMLClass, LAZILY_PINNED_ATOM(XML)},
{js_InitXMLClass, LAZILY_PINNED_ATOM(XMLList)}, {js_InitXMLClass, LAZILY_PINNED_ATOM(XMLList)},
{js_InitXMLClass, LAZILY_PINNED_ATOM(isXMLName)},
#endif #endif
{NULL, 0, NULL} {NULL, 0, NULL}
@ -1372,7 +1374,7 @@ JS_ResolveStandardClass(JSContext *cx, JSObject *obj, jsval id,
rt = cx->runtime; rt = cx->runtime;
#if JS_HAS_UNDEFINED #if JS_HAS_UNDEFINED
/* See if we're resolving 'undefined', and define it if so. */ /* Check whether we're resolving 'undefined', and define it if so. */
atom = rt->atomState.typeAtoms[JSTYPE_VOID]; atom = rt->atomState.typeAtoms[JSTYPE_VOID];
if (idstr == ATOM_TO_STRING(atom)) { if (idstr == ATOM_TO_STRING(atom)) {
*resolved = JS_TRUE; *resolved = JS_TRUE;
@ -1455,7 +1457,7 @@ JS_EnumerateStandardClasses(JSContext *cx, JSObject *obj)
rt = cx->runtime; rt = cx->runtime;
#if JS_HAS_UNDEFINED #if JS_HAS_UNDEFINED
/* See if we need to bind 'undefined' and define it if so. */ /* Check whether we need to bind 'undefined' and define it if so. */
atom = rt->atomState.typeAtoms[JSTYPE_VOID]; atom = rt->atomState.typeAtoms[JSTYPE_VOID];
if (!HasOwnProperty(cx, obj, atom, &found)) if (!HasOwnProperty(cx, obj, atom, &found))
return JS_FALSE; return JS_FALSE;
@ -1478,6 +1480,96 @@ JS_EnumerateStandardClasses(JSContext *cx, JSObject *obj)
return JS_TRUE; return JS_TRUE;
} }
static JSIdArray *
AddAtomToArray(JSContext *cx, JSAtom *atom, JSIdArray *ida, jsint *ip)
{
jsint i = *ip;
if (i >= ida->length) {
ida = js_SetIdArrayLength(cx, ida, ida->length * 2);
if (!ida)
return NULL;
}
ida->vector[i] = ATOM_TO_JSID(atom);
*ip = i + 1;
return ida;
}
static JSIdArray *
EnumerateIfResolved(JSContext *cx, JSObject *obj, JSAtom *atom, JSIdArray *ida,
jsint *ip, JSBool *foundp)
{
if (!HasOwnProperty(cx, obj, atom, foundp)) {
JS_DestroyIdArray(cx, ida);
return NULL;
}
if (*foundp) {
ida = AddAtomToArray(cx, atom, ida, ip);
if (!ida)
return NULL;
}
return ida;
}
JS_PUBLIC_API(JSIdArray *)
JS_EnumerateResolvedStandardClasses(JSContext *cx, JSObject *obj)
{
JSRuntime *rt;
JSIdArray *ida;
JSAtom *atom;
jsint i, j, k;
JSBool found;
JSObjectOp init;
CHECK_REQUEST(cx);
rt = cx->runtime;
ida = js_NewIdArray(cx, 8);
if (!ida)
return NULL;
i = 0;
#if JS_HAS_UNDEFINED
/* Check whether 'undefined' has been resolved and enumerate it if so. */
atom = rt->atomState.typeAtoms[JSTYPE_VOID];
ida = EnumerateIfResolved(cx, obj, atom, ida, &i, &found);
if (!ida)
return NULL;
#endif
/* Enumerate only classes that *have* been resolved. */
for (j = 0; standard_class_atoms[j].init; j++) {
atom = OFFSET_TO_ATOM(rt, standard_class_atoms[j].atomOffset);
ida = EnumerateIfResolved(cx, obj, atom, ida, &i, &found);
if (!ida)
return NULL;
if (found) {
init = standard_class_atoms[j].init;
for (k = 0; standard_class_names[k].init; k++) {
if (standard_class_names[k].init == init) {
atom = StdNameToAtom(cx, &standard_class_names[k]);
ida = AddAtomToArray(cx, atom, ida, &i);
if (!ida)
return NULL;
}
}
if (init == js_InitObjectClass) {
for (k = 0; object_prototype_names[k].init; k++) {
atom = StdNameToAtom(cx, &object_prototype_names[k]);
ida = AddAtomToArray(cx, atom, ida, &i);
if (!ida)
return NULL;
}
}
}
}
/* Trim to exact length via js_SetIdArrayLength. */
return js_SetIdArrayLength(cx, ida, i);
}
#undef ATOM_OFFSET #undef ATOM_OFFSET
#undef OFFSET_TO_ATOM #undef OFFSET_TO_ATOM
@ -3028,7 +3120,7 @@ JS_Enumerate(JSContext *cx, JSObject *obj)
if (i == ida->length) { if (i == ida->length) {
/* Grow length by factor of 1.5 instead of doubling. */ /* Grow length by factor of 1.5 instead of doubling. */
jsint newlen = ida->length + (((jsuint)ida->length + 1) >> 1); jsint newlen = ida->length + (((jsuint)ida->length + 1) >> 1);
ida = js_GrowIdArray(cx, ida, newlen); ida = js_SetIdArrayLength(cx, ida, newlen);
if (!ida) if (!ida)
goto error; goto error;
vector = &ida->vector[0]; vector = &ida->vector[0];

Просмотреть файл

@ -506,6 +506,9 @@ JS_ResolveStandardClass(JSContext *cx, JSObject *obj, jsval id,
extern JS_PUBLIC_API(JSBool) extern JS_PUBLIC_API(JSBool)
JS_EnumerateStandardClasses(JSContext *cx, JSObject *obj); JS_EnumerateStandardClasses(JSContext *cx, JSObject *obj);
extern JS_PUBLIC_API(JSIdArray *)
JS_EnumerateResolvedStandardClasses(JSContext *cx, JSObject *obj);
extern JS_PUBLIC_API(JSObject *) extern JS_PUBLIC_API(JSObject *)
JS_GetScopeChain(JSContext *cx); JS_GetScopeChain(JSContext *cx);

Просмотреть файл

@ -94,11 +94,14 @@ const char js_Call_str[] = "Call";
const char js_Date_str[] = "Date"; const char js_Date_str[] = "Date";
const char js_Function_str[] = "Function"; const char js_Function_str[] = "Function";
const char js_Math_str[] = "Math"; const char js_Math_str[] = "Math";
const char js_Namespace_str[] = "Namespace";
const char js_Number_str[] = "Number"; const char js_Number_str[] = "Number";
const char js_Object_str[] = "Object"; const char js_Object_str[] = "Object";
const char js_QName_str[] = "QName";
const char js_RegExp_str[] = "RegExp"; const char js_RegExp_str[] = "RegExp";
const char js_Script_str[] = "Script"; const char js_Script_str[] = "Script";
const char js_String_str[] = "String"; const char js_String_str[] = "String";
const char js_XML_str[] = "XML";
const char js_anonymous_str[] = "anonymous"; const char js_anonymous_str[] = "anonymous";
const char js_arguments_str[] = "arguments"; const char js_arguments_str[] = "arguments";
const char js_arity_str[] = "arity"; const char js_arity_str[] = "arity";
@ -308,11 +311,14 @@ js_InitPinnedAtoms(JSContext *cx, JSAtomState *state)
#endif #endif
FROB(FunctionAtom, js_Function_str); FROB(FunctionAtom, js_Function_str);
FROB(MathAtom, js_Math_str); FROB(MathAtom, js_Math_str);
FROB(NamespaceAtom, js_Namespace_str);
FROB(NumberAtom, js_Number_str); FROB(NumberAtom, js_Number_str);
FROB(ObjectAtom, js_Object_str); FROB(ObjectAtom, js_Object_str);
FROB(QNameAtom, js_QName_str);
FROB(RegExpAtom, js_RegExp_str); FROB(RegExpAtom, js_RegExp_str);
FROB(ScriptAtom, js_Script_str); FROB(ScriptAtom, js_Script_str);
FROB(StringAtom, js_String_str); FROB(StringAtom, js_String_str);
FROB(XMLAtom, js_XML_str);
FROB(anonymousAtom, js_anonymous_str); FROB(anonymousAtom, js_anonymous_str);
FROB(argumentsAtom, js_arguments_str); FROB(argumentsAtom, js_arguments_str);
FROB(arityAtom, js_arity_str); FROB(arityAtom, js_arity_str);

Просмотреть файл

@ -172,11 +172,14 @@ struct JSAtomState {
JSAtom *ErrorAtom; JSAtom *ErrorAtom;
JSAtom *FunctionAtom; JSAtom *FunctionAtom;
JSAtom *MathAtom; JSAtom *MathAtom;
JSAtom *NamespaceAtom;
JSAtom *NumberAtom; JSAtom *NumberAtom;
JSAtom *ObjectAtom; JSAtom *ObjectAtom;
JSAtom *QNameAtom;
JSAtom *RegExpAtom; JSAtom *RegExpAtom;
JSAtom *ScriptAtom; JSAtom *ScriptAtom;
JSAtom *StringAtom; JSAtom *StringAtom;
JSAtom *XMLAtom;
JSAtom *anonymousAtom; JSAtom *anonymousAtom;
JSAtom *argumentsAtom; JSAtom *argumentsAtom;
JSAtom *arityAtom; JSAtom *arityAtom;
@ -221,14 +224,11 @@ struct JSAtomState {
JSAtom *InfinityAtom; JSAtom *InfinityAtom;
JSAtom *InternalErrorAtom; JSAtom *InternalErrorAtom;
JSAtom *NaNAtom; JSAtom *NaNAtom;
JSAtom *NamespaceAtom;
JSAtom *QNameAtom;
JSAtom *RangeErrorAtom; JSAtom *RangeErrorAtom;
JSAtom *ReferenceErrorAtom; JSAtom *ReferenceErrorAtom;
JSAtom *SyntaxErrorAtom; JSAtom *SyntaxErrorAtom;
JSAtom *TypeErrorAtom; JSAtom *TypeErrorAtom;
JSAtom *URIErrorAtom; JSAtom *URIErrorAtom;
JSAtom *XMLAtom;
JSAtom *XMLListAtom; JSAtom *XMLListAtom;
JSAtom *anynameAtom; JSAtom *anynameAtom;
JSAtom *decodeURIAtom; JSAtom *decodeURIAtom;
@ -280,11 +280,14 @@ extern const char js_Call_str[];
extern const char js_Date_str[]; extern const char js_Date_str[];
extern const char js_Function_str[]; extern const char js_Function_str[];
extern const char js_Math_str[]; extern const char js_Math_str[];
extern const char js_Namespace_str[];
extern const char js_Number_str[]; extern const char js_Number_str[];
extern const char js_Object_str[]; extern const char js_Object_str[];
extern const char js_QName_str[];
extern const char js_RegExp_str[]; extern const char js_RegExp_str[];
extern const char js_Script_str[]; extern const char js_Script_str[];
extern const char js_String_str[]; extern const char js_String_str[];
extern const char js_XML_str[];
extern const char js_anonymous_str[]; extern const char js_anonymous_str[];
extern const char js_arguments_str[]; extern const char js_arguments_str[];
extern const char js_arity_str[]; extern const char js_arity_str[];

Просмотреть файл

@ -3249,20 +3249,24 @@ js_NewIdArray(JSContext *cx, jsint length)
JSIdArray *ida; JSIdArray *ida;
ida = (JSIdArray *) ida = (JSIdArray *)
JS_malloc(cx, sizeof(JSIdArray) + (length - 1) * sizeof(jsval)); JS_malloc(cx, sizeof(JSIdArray) + (length-1) * sizeof(jsval));
if (ida) if (ida)
ida->length = length; ida->length = length;
return ida; return ida;
} }
JSIdArray * JSIdArray *
js_GrowIdArray(JSContext *cx, JSIdArray *ida, jsint length) js_SetIdArrayLength(JSContext *cx, JSIdArray *ida, jsint length)
{ {
ida = (JSIdArray *) JSIdArray *rida;
JS_realloc(cx, ida, sizeof(JSIdArray) + (length - 1) * sizeof(jsval));
if (ida) rida = (JSIdArray *)
ida->length = length; JS_realloc(cx, ida, sizeof(JSIdArray) + (length-1) * sizeof(jsval));
return ida; if (!rida)
JS_DestroyIdArray(cx, ida);
else
rida->length = length;
return rida;
} }
/* Private type used to iterate over all properties of a native JS object */ /* Private type used to iterate over all properties of a native JS object */

Просмотреть файл

@ -412,8 +412,11 @@ js_DefaultValue(JSContext *cx, JSObject *obj, JSType hint, jsval *vp);
extern JSIdArray * extern JSIdArray *
js_NewIdArray(JSContext *cx, jsint length); js_NewIdArray(JSContext *cx, jsint length);
/*
* Unlike realloc(3), this function frees ida on failure.
*/
extern JSIdArray * extern JSIdArray *
js_GrowIdArray(JSContext *cx, JSIdArray *ida, jsint length); js_SetIdArrayLength(JSContext *cx, JSIdArray *ida, jsint length);
extern JSBool extern JSBool
js_Enumerate(JSContext *cx, JSObject *obj, JSIterateOp enum_op, js_Enumerate(JSContext *cx, JSObject *obj, JSIterateOp enum_op,

Просмотреть файл

@ -118,9 +118,6 @@ static struct {
const char js_AnyName_str[] = "AnyName"; const char js_AnyName_str[] = "AnyName";
const char js_AttributeName_str[] = "AttributeName"; const char js_AttributeName_str[] = "AttributeName";
const char js_isXMLName_str[] = "isXMLName"; const char js_isXMLName_str[] = "isXMLName";
const char js_Namespace_str[] = "Namespace";
const char js_QName_str[] = "QName";
const char js_XML_str[] = "XML";
const char js_XMLList_str[] = "XMLList"; const char js_XMLList_str[] = "XMLList";
const char js_localName_str[] = "localName"; const char js_localName_str[] = "localName";
const char js_xml_parent_str[] = "parent"; const char js_xml_parent_str[] = "parent";
@ -7347,20 +7344,24 @@ js_InitNamespaceClass(JSContext *cx, JSObject *obj)
JSObject * JSObject *
js_InitQNameClass(JSContext *cx, JSObject *obj) js_InitQNameClass(JSContext *cx, JSObject *obj)
{ {
if (!JS_InitClass(cx, obj, NULL, &js_AttributeNameClass, AttributeName, 2,
qname_props, qname_methods, NULL, NULL)) {
return NULL;
}
if (!JS_InitClass(cx, obj, NULL, &js_AnyNameClass, AnyName, 0,
qname_props, qname_methods, NULL, NULL)) {
return NULL;
}
return JS_InitClass(cx, obj, NULL, &js_QNameClass.base, QName, 2, return JS_InitClass(cx, obj, NULL, &js_QNameClass.base, QName, 2,
qname_props, qname_methods, NULL, NULL); qname_props, qname_methods, NULL, NULL);
} }
JSObject *
js_InitAttributeNameClass(JSContext *cx, JSObject *obj)
{
return JS_InitClass(cx, obj, NULL, &js_AttributeNameClass, AttributeName, 2,
qname_props, qname_methods, NULL, NULL);
}
JSObject *
js_InitAnyNameClass(JSContext *cx, JSObject *obj)
{
return JS_InitClass(cx, obj, NULL, &js_AnyNameClass, AnyName, 0,
qname_props, qname_methods, NULL, NULL);
}
JSObject * JSObject *
js_InitXMLClass(JSContext *cx, JSObject *obj) js_InitXMLClass(JSContext *cx, JSObject *obj)
{ {
@ -7444,7 +7445,13 @@ js_InitXMLClass(JSContext *cx, JSObject *obj)
JSObject * JSObject *
js_InitXMLClasses(JSContext *cx, JSObject *obj) js_InitXMLClasses(JSContext *cx, JSObject *obj)
{ {
if (!js_InitNamespaceClass(cx, obj) || !js_InitQNameClass(cx, obj)) if (!js_InitNamespaceClass(cx, obj))
return NULL;
if (!js_InitQNameClass(cx, obj))
return NULL;
if (!js_InitAttributeNameClass(cx, obj))
return NULL;
if (!js_InitAnyNameClass(cx, obj))
return NULL; return NULL;
return js_InitXMLClass(cx, obj); return js_InitXMLClass(cx, obj);
} }

Просмотреть файл

@ -45,9 +45,6 @@
extern const char js_AnyName_str[]; extern const char js_AnyName_str[];
extern const char js_AttributeName_str[]; extern const char js_AttributeName_str[];
extern const char js_isXMLName_str[]; extern const char js_isXMLName_str[];
extern const char js_Namespace_str[];
extern const char js_QName_str[];
extern const char js_XML_str[];
extern const char js_XMLList_str[]; extern const char js_XMLList_str[];
extern const char js_amp_entity_str[]; extern const char js_amp_entity_str[];
@ -217,10 +214,10 @@ js_GetXMLObject(JSContext *cx, JSXML *xml);
extern JS_FRIEND_DATA(JSXMLObjectOps) js_XMLObjectOps; extern JS_FRIEND_DATA(JSXMLObjectOps) js_XMLObjectOps;
extern JS_FRIEND_DATA(JSClass) js_XMLClass; extern JS_FRIEND_DATA(JSClass) js_XMLClass;
extern JS_FRIEND_DATA(JSExtendedClass) js_NamespaceClass;
extern JS_FRIEND_DATA(JSExtendedClass) js_QNameClass; extern JS_FRIEND_DATA(JSExtendedClass) js_QNameClass;
extern JS_FRIEND_DATA(JSClass) js_AttributeNameClass; extern JS_FRIEND_DATA(JSClass) js_AttributeNameClass;
extern JS_FRIEND_DATA(JSClass) js_AnyNameClass; extern JS_FRIEND_DATA(JSClass) js_AnyNameClass;
extern JS_FRIEND_DATA(JSExtendedClass) js_NamespaceClass;
/* /*
* Macros to test whether an object or a value is of type "xml" (per typeof). * Macros to test whether an object or a value is of type "xml" (per typeof).
@ -236,6 +233,12 @@ js_InitNamespaceClass(JSContext *cx, JSObject *obj);
extern JSObject * extern JSObject *
js_InitQNameClass(JSContext *cx, JSObject *obj); js_InitQNameClass(JSContext *cx, JSObject *obj);
extern JSObject *
js_InitAttributeNameClass(JSContext *cx, JSObject *obj);
extern JSObject *
js_InitAnyNameClass(JSContext *cx, JSObject *obj);
extern JSObject * extern JSObject *
js_InitXMLClass(JSContext *cx, JSObject *obj); js_InitXMLClass(JSContext *cx, JSObject *obj);