Bug 752092 - Support building SpiderMonkey without JS_HAS_XML_SUPPORT. r=terrence.
authorJason Orendorff <jorendorff@mozilla.com>
Mon, 14 May 2012 18:53:30 -0500
changeset 95580 8be72d70f108ef7fb49c41c48ee2887ea29a9511
parent 95579 3bdd2ce20e5237dc4759807191b51b157b8c7ff0
child 95581 b697bb3d384689ab8ee5f87831dd1a4727e82347
push idunknown
push userunknown
push dateunknown
reviewersterrence
bugs752092
milestone15.0a1
Bug 752092 - Support building SpiderMonkey without JS_HAS_XML_SUPPORT. r=terrence.
js/src/frontend/Parser.cpp
js/src/gc/Marking.cpp
js/src/gc/Marking.h
js/src/jscntxt.h
js/src/jscntxtinlines.h
js/src/jsgc.cpp
js/src/jsgc.h
js/src/jsinterp.cpp
js/src/jsiter.cpp
js/src/jsobj.cpp
js/src/jsobj.h
js/src/jsobjinlines.h
js/src/json.cpp
js/src/jsopcode.cpp
js/src/jsprvtd.h
js/src/jsreflect.cpp
js/src/jswrapper.cpp
js/src/jsxml.cpp
js/src/jsxml.h
--- a/js/src/frontend/Parser.cpp
+++ b/js/src/frontend/Parser.cpp
@@ -6027,28 +6027,16 @@ Parser::xmlExpr(JSBool inTag)
 
     MUST_MATCH_TOKEN(TOK_RC, JSMSG_CURLY_IN_XML_EXPR);
     tokenStream.setXMLTagMode(oldflag);
     pn->pn_kid = pn2;
     pn->setOp(inTag ? JSOP_XMLTAGEXPR : JSOP_XMLELTEXPR);
     return pn;
 }
 
-ParseNode *
-Parser::atomNode(ParseNodeKind kind, JSOp op)
-{
-    ParseNode *node = NullaryNode::create(kind, this);
-    if (!node)
-        return NULL;
-    node->setOp(op);
-    const Token &tok = tokenStream.currentToken();
-    node->pn_atom = tok.atom();
-    return node;
-}
-
 /*
  * Parse the productions:
  *
  *      XMLNameExpr:
  *              XMLName XMLNameExpr?
  *              { Expr } XMLNameExpr?
  *
  * Return a PN_LIST, PN_UNARY, or PN_NULLARY according as XMLNameExpr produces
@@ -6547,16 +6535,28 @@ Parser::starOrAtPropertyIdentifier(Token
         reportErrorNumber(NULL, JSREPORT_ERROR, JSMSG_SYNTAX_ERROR);
         return NULL;
     }
     return (tt == TOK_AT) ? attributeIdentifier() : qualifiedIdentifier();
 }
 #endif
 
 ParseNode *
+Parser::atomNode(ParseNodeKind kind, JSOp op)
+{
+    ParseNode *node = NullaryNode::create(kind, this);
+    if (!node)
+        return NULL;
+    node->setOp(op);
+    const Token &tok = tokenStream.currentToken();
+    node->pn_atom = tok.atom();
+    return node;
+}
+
+ParseNode *
 Parser::primaryExpr(TokenKind tt, bool afterDoubleDot)
 {
     JS_ASSERT(tokenStream.isCurrentTokenType(tt));
 
     ParseNode *pn, *pn2, *pn3;
     JSOp op;
 
     JS_CHECK_RECURSION(context, return NULL);
--- a/js/src/gc/Marking.cpp
+++ b/js/src/gc/Marking.cpp
@@ -2,16 +2,17 @@
  */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "jsprf.h"
 #include "jsscope.h"
 #include "jsstr.h"
+#include "jsxml.h"
 
 #include "gc/Marking.h"
 #include "methodjit/MethodJIT.h"
 
 #include "jsobjinlines.h"
 #include "jsscopeinlines.h"
 
 #include "vm/String-inl.h"
@@ -44,18 +45,20 @@
  * pointers to be visited. Eventually, this leads to the MarkChildren functions
  * being called. These functions duplicate much of the functionality of
  * scanning functions, but they don't push onto an explicit stack.
  */
 
 namespace js {
 namespace gc {
 
+#if JS_HAS_XML_SUPPORT
 static inline void
 PushMarkStack(GCMarker *gcmarker, JSXML *thing);
+#endif
 
 static inline void
 PushMarkStack(GCMarker *gcmarker, JSObject *thing);
 
 static inline void
 PushMarkStack(GCMarker *gcmarker, JSFunction *thing);
 
 static inline void
@@ -446,24 +449,26 @@ MarkValueUnbarriered(JSTracer *trc, Valu
 
 #define JS_COMPARTMENT_ASSERT(rt, thing)                                \
     JS_ASSERT((thing)->compartment()->isCollecting())
 
 #define JS_COMPARTMENT_ASSERT_STR(rt, thing)                            \
     JS_ASSERT((thing)->compartment()->isCollecting() ||                 \
               (thing)->compartment() == (rt)->atomsCompartment);
 
+#if JS_HAS_XML_SUPPORT
 static void
 PushMarkStack(GCMarker *gcmarker, JSXML *thing)
 {
     JS_COMPARTMENT_ASSERT(gcmarker->runtime, thing);
 
     if (thing->markIfUnmarked(gcmarker->getMarkColor()))
         gcmarker->pushXML(thing);
 }
+#endif
 
 static void
 PushMarkStack(GCMarker *gcmarker, JSObject *thing)
 {
     JS_COMPARTMENT_ASSERT(gcmarker->runtime, thing);
 
     if (thing->markIfUnmarked(gcmarker->getMarkColor()))
         gcmarker->pushObject(thing);
@@ -810,17 +815,17 @@ MarkChildren(JSTracer *trc, types::TypeO
         MarkObject(trc, &type->newScript->fun, "type_new_function");
         MarkShape(trc, &type->newScript->shape, "type_new_shape");
     }
 
     if (type->interpretedFunction)
         MarkObject(trc, &type->interpretedFunction, "type_function");
 }
 
-#ifdef JS_HAS_XML_SUPPORT
+#if JS_HAS_XML_SUPPORT
 static void
 MarkChildren(JSTracer *trc, JSXML *xml)
 {
     js_TraceXML(trc, xml);
 }
 #endif
 
 template<typename T>
@@ -990,20 +995,23 @@ GCMarker::processMarkStackOther(uintptr_
     } else if (tag == SavedValueArrayTag) {
         JS_ASSERT(!(addr & Cell::CellMask));
         JSObject *obj = reinterpret_cast<JSObject *>(addr);
         HeapValue *vp, *end;
         if (restoreValueArray(obj, (void **)&vp, (void **)&end))
             pushValueArray(obj, vp, end);
         else
             pushObject(obj);
-    } else {
+    }
+#if JS_HAS_XML_SUPPORT
+    else {
         JS_ASSERT(tag == XmlTag);
         MarkChildren(this, reinterpret_cast<JSXML *>(addr));
     }
+#endif
 }
 
 inline void
 GCMarker::processMarkStackTop(SliceBudget &budget)
 {
     /*
      * The function uses explicit goto and implements the scanning of the
      * object directly. It allows to eliminate the tail recursion and
--- a/js/src/gc/Marking.h
+++ b/js/src/gc/Marking.h
@@ -211,21 +211,23 @@ Mark(JSTracer *trc, HeapPtr<JSObject> *o
 }
 
 inline void
 Mark(JSTracer *trc, HeapPtr<JSScript> *o, const char *name)
 {
     MarkScript(trc, o, name);
 }
 
+#if JS_HAS_XML_SUPPORT
 inline void
 Mark(JSTracer *trc, HeapPtr<JSXML> *xml, const char *name)
 {
     MarkXML(trc, xml, name);
 }
+#endif
 
 inline bool
 IsMarked(const Value &v)
 {
     if (v.isMarkable())
         return !IsAboutToBeFinalized(v);
     return true;
 }
--- a/js/src/jscntxt.h
+++ b/js/src/jscntxt.h
@@ -1371,17 +1371,17 @@ struct AutoResolving {
     JSContext           *const context;
     JSObject            *const object;
     jsid                const id;
     Kind                const kind;
     AutoResolving       *const link;
     JS_DECL_USE_GUARD_OBJECT_NOTIFIER
 };
 
-#ifdef JS_HAS_XML_SUPPORT
+#if JS_HAS_XML_SUPPORT
 class AutoXMLRooter : private AutoGCRooter {
   public:
     AutoXMLRooter(JSContext *cx, JSXML *xml
                   JS_GUARD_OBJECT_NOTIFIER_PARAM)
       : AutoGCRooter(cx, XML), xml(xml)
     {
         JS_GUARD_OBJECT_NOTIFIER_INIT;
         JS_ASSERT(xml);
--- a/js/src/jscntxtinlines.h
+++ b/js/src/jscntxtinlines.h
@@ -197,16 +197,18 @@ GetGlobalForScopeChain(JSContext *cx)
 }
 
 inline GSNCache *
 GetGSNCache(JSContext *cx)
 {
     return &cx->runtime->gsnCache;
 }
 
+#if JS_HAS_XML_SUPPORT
+
 class AutoNamespaceArray : protected AutoGCRooter {
   public:
     AutoNamespaceArray(JSContext *cx)
         : AutoGCRooter(cx, NAMESPACES), context(cx) {
         array.init();
     }
 
     ~AutoNamespaceArray() {
@@ -218,16 +220,18 @@ class AutoNamespaceArray : protected Aut
   private:
     JSContext *context;
     friend void AutoGCRooter::trace(JSTracer *trc);
 
   public:
     JSXMLArray<JSObject> array;
 };
 
+#endif /* JS_HAS_XML_SUPPORT */
+
 template <typename T>
 class AutoPtr
 {
     JSContext *cx;
     T *value;
 
     AutoPtr(const AutoPtr &other) MOZ_DELETE;
 
--- a/js/src/jsgc.cpp
+++ b/js/src/jsgc.cpp
@@ -2160,26 +2160,28 @@ AutoGCRooter::trace(JSTracer *trc)
         if (desc.attrs & JSPROP_SETTER && desc.setter) {
             JSObject *tmp = JS_FUNC_TO_DATA_PTR(JSObject *, desc.setter);
             MarkObjectRoot(trc, &tmp, "Descriptor::set");
             desc.setter = JS_DATA_TO_FUNC_PTR(JSStrictPropertyOp, tmp);
         }
         return;
       }
 
+#if JS_HAS_XML_SUPPORT
       case NAMESPACES: {
         JSXMLArray<JSObject> &array = static_cast<AutoNamespaceArray *>(this)->array;
         MarkObjectRange(trc, array.length, array.vector, "JSXMLArray.vector");
         js_XMLArrayCursorTrace(trc, array.cursors);
         return;
       }
 
       case XML:
         js_TraceXML(trc, static_cast<AutoXMLRooter *>(this)->xml);
         return;
+#endif
 
       case OBJECT:
         if (static_cast<AutoObjectRooter *>(this)->obj)
             MarkObjectRoot(trc, &static_cast<AutoObjectRooter *>(this)->obj,
                            "JS::AutoObjectRooter.obj");
         return;
 
       case ID:
--- a/js/src/jsgc.h
+++ b/js/src/jsgc.h
@@ -59,19 +59,16 @@
 #include "gc/Heap.h"
 #include "gc/Statistics.h"
 #include "js/HashTable.h"
 #include "js/Vector.h"
 #include "js/TemplateLib.h"
 
 struct JSCompartment;
 
-extern void
-js_TraceXML(JSTracer *trc, JSXML* thing);
-
 #if JS_STACK_GROWTH_DIRECTION > 0
 # define JS_CHECK_STACK_SIZE(limit, lval)  ((uintptr_t)(lval) < limit)
 #else
 # define JS_CHECK_STACK_SIZE(limit, lval)  ((uintptr_t)(lval) > limit)
 #endif
 
 namespace js {
 
@@ -919,19 +916,21 @@ struct GCMarker : public JSTracer {
     void pushObject(JSObject *obj) {
         pushTaggedPtr(ObjectTag, obj);
     }
 
     void pushType(types::TypeObject *type) {
         pushTaggedPtr(TypeTag, type);
     }
 
+#if JS_HAS_XML_SUPPORT
     void pushXML(JSXML *xml) {
         pushTaggedPtr(XmlTag, xml);
     }
+#endif
 
     uint32_t getMarkColor() const {
         return color;
     }
 
     /*
      * The only valid color transition during a GC is from black to gray. It is
      * wrong to switch the mark color from gray to black. The reason is that the
--- a/js/src/jsinterp.cpp
+++ b/js/src/jsinterp.cpp
@@ -3630,31 +3630,33 @@ BEGIN_CASE(JSOP_ANYNAME)
     cx->runtime->gcExactScanningEnabled = false;
 
     jsid id;
     if (!js_GetAnyName(cx, &id))
         goto error;
     PUSH_COPY(IdToValue(id));
 }
 END_CASE(JSOP_ANYNAME)
+#endif
 
 BEGIN_CASE(JSOP_QNAMEPART)
 {
     /*
      * We do not JS_ASSERT(!script->strictModeCode) here because JSOP_QNAMEPART
      * is used for __proto__ and (in contexts where we favor JSOP_*ELEM instead
      * of JSOP_*PROP) obj.prop compiled as obj['prop'].
      */
 
     JSAtom *atom;
     LOAD_ATOM(0, atom);
     PUSH_STRING(atom);
 }
 END_CASE(JSOP_QNAMEPART)
 
+#if JS_HAS_XML_SUPPORT
 BEGIN_CASE(JSOP_QNAMECONST)
 {
     JS_ASSERT(!script->strictModeCode);
 
     JSAtom *atom;
     LOAD_ATOM(0, atom);
     Value rval = StringValue(atom);
     Value lval = regs.sp[-1];
@@ -4111,17 +4113,16 @@ END_CASE(JSOP_ARRAYPUSH)
   L_JSOP_SETXMLNAME:
   L_JSOP_BINDXMLNAME:
   L_JSOP_ADDATTRVAL:
   L_JSOP_ADDATTRNAME:
   L_JSOP_TOATTRVAL:
   L_JSOP_TOATTRNAME:
   L_JSOP_QNAME:
   L_JSOP_QNAMECONST:
-  L_JSOP_QNAMEPART:
   L_JSOP_ANYNAME:
   L_JSOP_DEFXMLNS:
 # endif
 
 #endif /* !JS_THREADED_INTERP */
 #if !JS_THREADED_INTERP
           default:
 #endif
--- a/js/src/jsiter.cpp
+++ b/js/src/jsiter.cpp
@@ -374,18 +374,23 @@ Snapshot(JSContext *cx, JSObject *obj, u
                     if (state.isNull())
                         break;
                     if (!Enumerate(cx, obj, pobj, id, true, flags, ht, props))
                         return false;
                 }
             }
         }
 
-        if ((flags & JSITER_OWNONLY) || pobj->isXML())
+        if (flags & JSITER_OWNONLY)
             break;
+
+#if JS_HAS_XML_SUPPORT
+        if (pobj->isXML())
+            break;
+#endif
     } while ((pobj = pobj->getProto()) != NULL);
 
 #ifdef JS_MORE_DETERMINISTIC
 
     /*
      * In some cases the enumeration order for an object depends on the
      * execution mode (interpreter vs. JIT), especially for native objects
      * with a class enumerate hook (where resolving a property changes the
--- a/js/src/jsobj.cpp
+++ b/js/src/jsobj.cpp
@@ -2396,20 +2396,22 @@ obj_create(JSContext *cx, unsigned argc,
             return false;
         JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_UNEXPECTED_TYPE,
                              bytes, "not an object or null");
         JS_free(cx, bytes);
         return false;
     }
 
     JSObject *proto = v.toObjectOrNull();
+#if JS_HAS_XML_SUPPORT
     if (proto && proto->isXML()) {
         JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_XML_PROTO_FORBIDDEN);
         return false;
     }
+#endif
 
     /*
      * Use the callee's global as the parent of the new object to avoid dynamic
      * scoping (i.e., using the caller's global).
      */
     RootedVarObject obj(cx);
     obj = NewObjectWithGivenProto(cx, &ObjectClass, proto, &args.callee().global());
     if (!obj)
@@ -4126,20 +4128,22 @@ static JSObjectOp lazy_prototype_init[JS
 namespace js {
 
 bool
 SetProto(JSContext *cx, HandleObject obj, HandleObject proto, bool checkForCycles)
 {
     JS_ASSERT_IF(!checkForCycles, obj != proto);
     JS_ASSERT(obj->isExtensible());
 
+#if JS_HAS_XML_SUPPORT
     if (proto && proto->isXML()) {
         JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_XML_PROTO_FORBIDDEN);
         return false;
     }
+#endif
 
     /*
      * Regenerate shapes for all of the scopes along the old prototype chain,
      * in case any entries were filled by looking up through obj. Stop when a
      * non-native object is found, prototype lookups will not be cached across
      * these.
      *
      * How this shape change is done is very delicate; the change can be made
@@ -5597,17 +5601,19 @@ MaybeCallMethod(JSContext *cx, HandleObj
     }
     return Invoke(cx, ObjectValue(*obj), *vp, 0, NULL, vp);
 }
 
 JSBool
 DefaultValue(JSContext *cx, HandleObject obj, JSType hint, Value *vp)
 {
     JS_ASSERT(hint == JSTYPE_NUMBER || hint == JSTYPE_STRING || hint == JSTYPE_VOID);
+#if JS_HAS_XML_SUPPORT
     JS_ASSERT(!obj->isXML());
+#endif
 
     Class *clasp = obj->getClass();
     if (hint == JSTYPE_STRING) {
         /* Optimize (new String(...)).toString(). */
         if (clasp == &StringClass &&
             ClassMethodIsNative(cx, obj,
                                  &StringClass,
                                  RootedVarId(cx, NameToId(cx->runtime->atomState.toStringAtom)),
--- a/js/src/jsobj.h
+++ b/js/src/jsobj.h
@@ -920,30 +920,32 @@ struct JSObject : public js::ObjectImpl
     inline bool isDataView() const;
     inline bool isDate() const;
     inline bool isElementIterator() const;
     inline bool isError() const;
     inline bool isFunction() const;
     inline bool isGenerator() const;
     inline bool isGlobal() const;
     inline bool isIterator() const;
-    inline bool isNamespace() const;
     inline bool isObject() const;
-    inline bool isQName() const;
     inline bool isPrimitive() const;
     inline bool isProxy() const;
     inline bool isRegExp() const;
     inline bool isRegExpStatics() const;
     inline bool isScope() const;
     inline bool isScript() const;
     inline bool isStopIteration() const;
     inline bool isTypedArray() const;
     inline bool isWeakMap() const;
+#if JS_HAS_XML_SUPPORT
+    inline bool isNamespace() const;
+    inline bool isQName() const;
     inline bool isXML() const;
     inline bool isXMLId() const;
+#endif
 
     /* Subtypes of ScopeObject. */
     inline bool isBlock() const;
     inline bool isCall() const;
     inline bool isDeclEnv() const;
     inline bool isNestedScope() const;
     inline bool isWith() const;
     inline bool isClonedBlock() const;
--- a/js/src/jsobjinlines.h
+++ b/js/src/jsobjinlines.h
@@ -575,16 +575,18 @@ JSObject::getNativeIterator() const
 }
 
 inline void
 JSObject::setNativeIterator(js::NativeIterator *ni)
 {
     setPrivate(ni);
 }
 
+#if JS_HAS_XML_SUPPORT
+
 inline JSLinearString *
 JSObject::getNamePrefix() const
 {
     JS_ASSERT(isNamespace() || isQName());
     const js::Value &v = getSlot(JSSLOT_NAME_PREFIX);
     return !v.isUndefined() ? &v.toString()->asLinear() : NULL;
 }
 
@@ -662,16 +664,18 @@ JSObject::getQNameLocalNameVal() const
 
 inline void
 JSObject::setQNameLocalName(JSAtom *name)
 {
     JS_ASSERT(isQName());
     setSlot(JSSLOT_QNAME_LOCAL_NAME, name ? js::StringValue(name) : js::UndefinedValue());
 }
 
+#endif
+
 inline bool
 JSObject::setSingletonType(JSContext *cx)
 {
     if (!cx->typeInferenceEnabled())
         return true;
 
     JS_ASSERT(!hasLazyType());
     JS_ASSERT_IF(getProto(), type() == getProto()->getNewType(cx, NULL));
@@ -794,32 +798,34 @@ inline bool JSObject::isDataView() const
 inline bool JSObject::isDate() const { return hasClass(&js::DateClass); }
 inline bool JSObject::isDeclEnv() const { return hasClass(&js::DeclEnvClass); }
 inline bool JSObject::isElementIterator() const { return hasClass(&js::ElementIteratorClass); }
 inline bool JSObject::isError() const { return hasClass(&js::ErrorClass); }
 inline bool JSObject::isFunction() const { return hasClass(&js::FunctionClass); }
 inline bool JSObject::isFunctionProxy() const { return hasClass(&js::FunctionProxyClass); }
 inline bool JSObject::isGenerator() const { return hasClass(&js::GeneratorClass); }
 inline bool JSObject::isIterator() const { return hasClass(&js::IteratorClass); }
-inline bool JSObject::isNamespace() const { return hasClass(&js::NamespaceClass); }
 inline bool JSObject::isNestedScope() const { return isBlock() || isWith(); }
 inline bool JSObject::isNormalArguments() const { return hasClass(&js::NormalArgumentsObjectClass); }
 inline bool JSObject::isNumber() const { return hasClass(&js::NumberClass); }
 inline bool JSObject::isObject() const { return hasClass(&js::ObjectClass); }
 inline bool JSObject::isPrimitive() const { return isNumber() || isString() || isBoolean(); }
 inline bool JSObject::isRegExp() const { return hasClass(&js::RegExpClass); }
 inline bool JSObject::isRegExpStatics() const { return hasClass(&js::RegExpStaticsClass); }
 inline bool JSObject::isScope() const { return isCall() || isDeclEnv() || isNestedScope(); }
 inline bool JSObject::isStaticBlock() const { return isBlock() && !getProto(); }
 inline bool JSObject::isStopIteration() const { return hasClass(&js::StopIterationClass); }
 inline bool JSObject::isStrictArguments() const { return hasClass(&js::StrictArgumentsObjectClass); }
 inline bool JSObject::isString() const { return hasClass(&js::StringClass); }
 inline bool JSObject::isTypedArray() const { return IsTypedArrayClass(getClass()); }
 inline bool JSObject::isWeakMap() const { return hasClass(&js::WeakMapClass); }
 inline bool JSObject::isWith() const { return hasClass(&js::WithClass); }
+
+#if JS_HAS_XML_SUPPORT
+inline bool JSObject::isNamespace() const { return hasClass(&js::NamespaceClass); }
 inline bool JSObject::isXML() const { return hasClass(&js::XMLClass); }
 
 inline bool
 JSObject::isXMLId() const
 {
     return hasClass(&js::QNameClass)
         || hasClass(&js::AttributeNameClass)
         || hasClass(&js::AnyNameClass);
@@ -827,16 +833,17 @@ JSObject::isXMLId() const
 
 inline bool
 JSObject::isQName() const
 {
     return hasClass(&js::QNameClass)
         || hasClass(&js::AttributeNameClass)
         || hasClass(&js::AnyNameClass);
 }
+#endif /* JS_HAS_XML_SUPPORT */
 
 /* static */ inline JSObject *
 JSObject::create(JSContext *cx, js::gc::AllocKind kind,
                  js::HandleShape shape, js::HandleTypeObject type, js::HeapSlot *slots)
 {
     /*
      * Callers must use dynamicSlotsCount to size the initial slot array of the
      * object. We can't check the allocated capacity of the dynamic slots, but
@@ -1219,28 +1226,35 @@ OBJ_TO_INNER_OBJECT(JSContext *cx, JSObj
 
 inline void
 OBJ_TO_OUTER_OBJECT(JSContext *cx, JSObject *&obj)
 {
     if (JSObjectOp op = obj->getClass()->ext.outerObject)
         obj = op(cx, obj);
 }
 
+#if JS_HAS_XML_SUPPORT
 /*
  * Methods to test whether an object or a value is of type "xml" (per typeof).
  */
 
-#define VALUE_IS_XML(v)      (!JSVAL_IS_PRIMITIVE(v) && JSVAL_TO_OBJECT(v)->isXML())
+#define VALUE_IS_XML(v)     ((v).isObject() && (v).toObject().isXML())
 
 static inline bool
 IsXML(const js::Value &v)
 {
     return v.isObject() && v.toObject().isXML();
 }
 
+#else
+
+#define VALUE_IS_XML(v)     false
+
+#endif /* JS_HAS_XML_SUPPORT */
+
 static inline bool
 IsStopIteration(const js::Value &v)
 {
     return v.isObject() && v.toObject().isStopIteration();
 }
 
 /* ES5 9.1 ToPrimitive(input). */
 static JS_ALWAYS_INLINE bool
@@ -1590,20 +1604,20 @@ IsObjectWithClass(const Value &v, ESClas
     if (!v.isObject())
         return false;
     return ObjectClassIs(v.toObject(), classValue, cx);
 }
 
 static JS_ALWAYS_INLINE bool
 ValueIsSpecial(JSObject *obj, Value *propval, SpecialId *sidp, JSContext *cx)
 {
+#if JS_HAS_XML_SUPPORT
     if (!propval->isObject())
         return false;
 
-#if JS_HAS_XML_SUPPORT
     if (obj->isXML()) {
         *sidp = SpecialId(propval->toObject());
         return true;
     }
 
     JSObject &propobj = propval->toObject();
     JSAtom *name;
     if (propobj.isQName() && GetLocalNameFromFunctionQName(&propobj, &name, cx)) {
--- a/js/src/json.cpp
+++ b/js/src/json.cpp
@@ -386,17 +386,17 @@ PreprocessValue(JSContext *cx, JSObject 
  * gauntlet will result in Str returning |undefined|.  This function is used to
  * properly omit properties resulting in such values when stringifying objects,
  * while properly stringifying such properties as null when they're encountered
  * in arrays.
  */
 static inline bool
 IsFilteredValue(const Value &v)
 {
-    return v.isUndefined() || js_IsCallable(v) || (v.isObject() && v.toObject().isXML());
+    return v.isUndefined() || js_IsCallable(v) || VALUE_IS_XML(v);
 }
 
 /* ES5 15.12.3 JO. */
 static JSBool
 JO(JSContext *cx, HandleObject obj, StringifyContext *scx)
 {
     /*
      * This method implements the JO algorithm in ES5 15.12.3, but:
--- a/js/src/jsopcode.cpp
+++ b/js/src/jsopcode.cpp
@@ -2570,18 +2570,19 @@ Decompile(SprintStack *ss, jsbytecode *p
     const char *lval, *rval, *xval, *fmt, *token;
     unsigned nuses;
     int i, argc;
     JSAtom *atom;
     JSObject *obj;
     JSFunction *fun = NULL; /* init to shut GCC up */
     JSString *str;
     JSBool ok;
+    JSBool foreach;
 #if JS_HAS_XML_SUPPORT
-    JSBool foreach, inXML, quoteAttr;
+    JSBool inXML, quoteAttr;
 #else
 #define inXML JS_FALSE
 #endif
     jsval val;
 
     static const char exception_cookie[] = "/*EXCEPTION*/";
     static const char retsub_pc_cookie[] = "/*RETSUB_PC*/";
     static const char forelem_cookie[]   = "/*FORELEM*/";
@@ -2677,18 +2678,19 @@ Decompile(SprintStack *ss, jsbytecode *p
     startpc = pc;
     endpc = (nb < 0) ? jp->script->code + jp->script->length : pc + nb;
     tail = -1;
     todo = -2;                  /* NB: different from Sprint() error return. */
     saveop = JSOP_NOP;
     sn = NULL;
     rval = NULL;
     bool forOf = false;
+    foreach = false;
 #if JS_HAS_XML_SUPPORT
-    foreach = inXML = quoteAttr = JS_FALSE;
+    inXML = quoteAttr = false;
 #endif
 
     while (nb < 0 || pc < endpc) {
         /*
          * Move saveop to lastop so prefixed bytecodes can take special action
          * while sharing maximal code.  Set op and saveop to the new bytecode,
          * use op in POP_STR to trigger automatic parenthesization, but push
          * saveop at the bottom of the loop if this op pushes.  Thus op may be
@@ -5197,27 +5199,31 @@ Decompile(SprintStack *ss, jsbytecode *p
               case JSOP_ANYNAME:
                 if (pc[JSOP_ANYNAME_LENGTH] == JSOP_TOATTRNAME) {
                     len += JSOP_TOATTRNAME_LENGTH;
                     todo = ss->sprinter.put("@*", 2);
                 } else {
                     todo = ss->sprinter.put("*", 1);
                 }
                 break;
+#endif
 
               case JSOP_QNAMEPART:
                 LOAD_ATOM(0);
+#if JS_HAS_XML_SUPPORT
                 if (pc[JSOP_QNAMEPART_LENGTH] == JSOP_TOATTRNAME) {
                     saveop = JSOP_TOATTRNAME;
                     len += JSOP_TOATTRNAME_LENGTH;
                     lval = "@";
                     goto do_qname;
                 }
+#endif
                 goto do_name;
 
+#if JS_HAS_XML_SUPPORT
               case JSOP_QNAMECONST:
                 LOAD_ATOM(0);
                 rval = QuoteString(&ss->sprinter, atom, 0);
                 if (!rval)
                     return NULL;
                 ss->sprinter.setOffset(rval);
                 lval = POP_STR();
                 todo = Sprint(&ss->sprinter, "%s::%s", lval, rval);
--- a/js/src/jsprvtd.h
+++ b/js/src/jsprvtd.h
@@ -90,17 +90,20 @@ typedef struct JSTryNote            JSTr
 
 /* Friend "Advanced API" typedefs. */
 typedef struct JSAtomState          JSAtomState;
 typedef struct JSCodeSpec           JSCodeSpec;
 typedef struct JSPrinter            JSPrinter;
 typedef struct JSStackHeader        JSStackHeader;
 typedef struct JSSubString          JSSubString;
 typedef struct JSSpecializedNative  JSSpecializedNative;
+
+#if JS_HAS_XML_SUPPORT
 typedef struct JSXML                JSXML;
+#endif
 
 /*
  * Template declarations.
  *
  * jsprvtd.h can be included in both C and C++ translation units. For C++, it
  * may possibly be wrapped in an extern "C" block which does not agree with
  * templates.
  */
--- a/js/src/jsreflect.cpp
+++ b/js/src/jsreflect.cpp
@@ -2491,17 +2491,17 @@ ASTSerializer::expression(ParseNode *pn,
         Value expr;
         return expression(pn->pn_kid, &expr) &&
                builder.unaryExpression(op, expr, &pn->pn_pos, dst);
       }
 
       case PNK_NEW:
       case PNK_LP:
       {
-#ifdef JS_HAS_GENERATOR_EXPRS
+#if JS_HAS_GENERATOR_EXPRS
         if (pn->isGeneratorExpr())
             return generatorExpression(pn->generatorExpr(), dst);
 #endif
 
         ParseNode *next = pn->pn_head;
 
         Value callee;
         if (!expression(next, &callee))
@@ -2606,17 +2606,17 @@ ASTSerializer::expression(ParseNode *pn,
         LOCAL_ASSERT(pn->pn_count == 1);
         LOCAL_ASSERT(pn->pn_head->isKind(PNK_LEXICALSCOPE));
 
         return comprehension(pn->pn_head->pn_expr, dst);
 
       case PNK_LET:
         return let(pn, true, dst);
 
-#ifdef JS_HAS_XML_SUPPORT
+#if JS_HAS_XML_SUPPORT
       case PNK_XMLUNARY:
         JS_ASSERT(pn->isOp(JSOP_XMLNAME) ||
                   pn->isOp(JSOP_SETXMLNAME) ||
                   pn->isOp(JSOP_BINDXMLNAME));
         return expression(pn->pn_kid, dst);
 
       case PNK_ANYNAME:
         return builder.xmlAnyName(&pn->pn_pos, dst);
@@ -2680,17 +2680,17 @@ ASTSerializer::expression(ParseNode *pn,
     }
 }
 
 bool
 ASTSerializer::xml(ParseNode *pn, Value *dst)
 {
     JS_CHECK_RECURSION(cx, return false);
     switch (pn->getKind()) {
-#ifdef JS_HAS_XML_SUPPORT
+#if JS_HAS_XML_SUPPORT
       case PNK_XMLCURLYEXPR:
       {
         Value expr;
         return expression(pn->pn_kid, &expr) &&
                builder.xmlEscapeExpression(expr, &pn->pn_pos, dst);
       }
 
       case PNK_XMLELEM:
@@ -2944,24 +2944,24 @@ ASTSerializer::identifier(ParseNode *pn,
 }
 
 bool
 ASTSerializer::function(ParseNode *pn, ASTType type, Value *dst)
 {
     JSFunction *func = (JSFunction *)pn->pn_funbox->object;
 
     bool isGenerator =
-#ifdef JS_HAS_GENERATORS
+#if JS_HAS_GENERATORS
         pn->pn_funbox->tcflags & TCF_FUN_IS_GENERATOR;
 #else
         false;
 #endif
 
     bool isExpression =
-#ifdef JS_HAS_EXPR_CLOSURES
+#if JS_HAS_EXPR_CLOSURES
         func->flags & JSFUN_EXPR_CLOSURE;
 #else
         false;
 #endif
 
     Value id;
     if (!optIdentifier(func->atom, NULL, &id))
         return false;
--- a/js/src/jswrapper.cpp
+++ b/js/src/jswrapper.cpp
@@ -408,20 +408,23 @@ AbstractWrapper::leave(JSContext *cx, JS
 }
 
 Wrapper Wrapper::singleton((unsigned)0);
 
 JSObject *
 Wrapper::New(JSContext *cx, JSObject *obj, JSObject *proto, JSObject *parent, Wrapper *handler)
 {
     JS_ASSERT(parent);
+#if JS_HAS_XML_SUPPORT
     if (obj->isXML()) {
         JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_CANT_WRAP_XML_OBJECT);
         return NULL;
     }
+#endif
+
     return NewProxyObject(cx, handler, ObjectValue(*obj), proto, parent,
                           obj->isCallable() ? obj : NULL, NULL);
 }
 
 /* Compartments. */
 
 namespace js {
 
--- a/js/src/jsxml.cpp
+++ b/js/src/jsxml.cpp
@@ -32,18 +32,21 @@
  * use your version of this file under the terms of the MPL, indicate your
  * decision by deleting the provisions above and replace them with the notice
  * and other provisions required by the GPL or the LGPL. If you do not delete
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
+#include <stddef.h>
 #include "jsversion.h"
 
+size_t sE4XObjectsCreated = 0;
+
 #if JS_HAS_XML_SUPPORT
 
 #include <math.h>
 #include <stdlib.h>
 #include <string.h>
 
 #include "mozilla/Util.h"
 
@@ -169,18 +172,16 @@ IsDeclared(const JSObject *obj)
 
 static JSBool
 xml_isXMLName(JSContext *cx, unsigned argc, jsval *vp)
 {
     *vp = BOOLEAN_TO_JSVAL(js_IsXMLName(cx, argc ? vp[2] : JSVAL_VOID));
     return JS_TRUE;
 }
 
-size_t sE4XObjectsCreated = 0;
-
 /*
  * This wrapper is needed because NewBuiltinClassInstance doesn't
  * call the constructor, and we need a place to set the
  * HAS_EQUALITY bit.
  */
 static inline JSObject *
 NewBuiltinClassInstanceXML(JSContext *cx, Class *clasp)
 {
--- a/js/src/jsxml.h
+++ b/js/src/jsxml.h
@@ -40,16 +40,18 @@
 #define jsxml_h___
 
 #include "jspubtd.h"
 #include "jsobj.h"
 
 #include "gc/Barrier.h"
 #include "gc/Heap.h"
 
+#if JS_HAS_XML_SUPPORT
+
 extern const char js_AnyName_str[];
 extern const char js_AttributeName_str[];
 extern const char js_isXMLName_str[];
 extern const char js_XMLList_str[];
 
 extern const char js_amp_entity_str[];
 extern const char js_gt_entity_str[];
 extern const char js_lt_entity_str[];
@@ -327,9 +329,11 @@ js_ConcatenateXML(JSContext *cx, JSObjec
 
 namespace js {
 
 extern bool
 GetLocalNameFromFunctionQName(JSObject *qn, JSAtom **namep, JSContext *cx);
 
 } /* namespace js */
 
+#endif /* JS_HAS_XML_SUPPORT */
+
 #endif /* jsxml_h___ */