From d9f49c3dc83bc86cad2c05a2b05289ec8d70f5ad Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 24 Jan 2013 21:24:57 -0800 Subject: [PATCH] Bug 788293 - Remove e4x support. r=jorendorff,terrence,evilpie. Ding dong! The witch is dead! --- content/base/src/nsFrameMessageManager.cpp | 5 +- content/base/src/nsScriptLoader.cpp | 14 - content/xul/document/src/nsXULContentSink.cpp | 37 +- dom/base/nsGlobalWindow.cpp | 11 +- dom/base/nsJSEnvironment.cpp | 14 +- dom/src/json/nsJSON.cpp | 4 +- dom/workers/RuntimeService.cpp | 5 - js/ipc/ObjectWrapperChild.cpp | 2 - js/ipc/ObjectWrapperParent.cpp | 2 - js/public/MemoryMetrics.h | 12 - js/src/Makefile.in | 1 - js/src/builtin/Object.cpp | 6 - js/src/builtin/TestingFunctions.cpp | 19 +- js/src/configure.in | 9 - js/src/frontend/BytecodeCompiler.cpp | 26 +- js/src/frontend/BytecodeEmitter.cpp | 358 +- js/src/frontend/FoldConstants.cpp | 203 - js/src/frontend/ParseNode.cpp | 6 +- js/src/frontend/ParseNode.h | 234 +- js/src/frontend/Parser.cpp | 946 +- js/src/frontend/Parser.h | 38 +- js/src/frontend/SharedContext.h | 3 +- js/src/frontend/TokenStream.cpp | 541 +- js/src/frontend/TokenStream.h | 74 +- js/src/gc/Barrier.h | 3 - js/src/gc/Heap.h | 3 - js/src/gc/Marking.cpp | 55 - js/src/gc/Marking.h | 11 - js/src/gc/RootMarking.cpp | 13 - js/src/gc/StoreBuffer.h | 3 - js/src/gc/Verifier.cpp | 10 +- js/src/gdb/mozilla/jsid.py | 3 - js/src/gdb/tests/test-jsid.cpp | 2 - js/src/gdb/tests/test-jsid.py | 1 - js/src/ion/IonCaches.cpp | 2 +- js/src/js-config.h.in | 3 - js/src/js.msg | 62 +- js/src/jsanalyze.cpp | 6 +- js/src/jsanalyze.h | 3 - js/src/jsapi.cpp | 55 +- js/src/jsapi.h | 49 +- js/src/jsarray.cpp | 2 +- js/src/jsast.tbl | 19 - js/src/jsatom.cpp | 28 - js/src/jsclass.h | 29 +- js/src/jscntxt.h | 80 +- js/src/jscntxtinlines.h | 26 - js/src/jsfriendapi.cpp | 16 - js/src/jsfriendapi.h | 13 +- js/src/jsgc.cpp | 34 +- js/src/jsgc.h | 24 +- js/src/jsgcinlines.h | 6 - js/src/jsinfer.cpp | 65 - js/src/jsinterp.cpp | 398 +- js/src/jsinterpinlines.h | 40 +- js/src/jsiter.cpp | 13 +- js/src/jsmemorymetrics.cpp | 10 - js/src/jsobj.cpp | 25 +- js/src/jsobj.h | 46 - js/src/jsobjinlines.h | 149 - js/src/json.cpp | 3 +- js/src/jsopcode.cpp | 252 +- js/src/jsopcode.h | 1 - js/src/jsopcode.tbl | 63 +- js/src/jspropertytree.cpp | 2 - js/src/jsprototypes.h | 58 +- js/src/jsprvtd.h | 4 - js/src/jspubtd.h | 5 - js/src/jsreflect.cpp | 455 - js/src/jsreflect.h | 2 - js/src/jswrapper.cpp | 15 - js/src/jsxml.cpp | 8032 ----------------- js/src/jsxml.h | 314 - js/src/methodjit/InvokeHelpers.cpp | 1 - js/src/methodjit/PolyIC.cpp | 10 - js/src/methodjit/StubCalls.cpp | 28 +- js/src/shell/js.cpp | 3 - js/src/vm/CommonPropertyNames.h | 22 +- js/src/vm/GlobalObject.cpp | 3 - js/src/vm/GlobalObject.h | 11 +- js/src/vm/ObjectImpl.h | 5 +- js/src/vm/Shape-inl.h | 2 +- js/src/vm/Stack.h | 5 +- js/src/vm/String.h | 4 +- js/src/vm/Unicode.h | 60 +- js/src/vm/Xdr.h | 2 +- js/xpconnect/idl/xpccomponents.idl | 3 - js/xpconnect/loader/mozJSComponentLoader.cpp | 5 - js/xpconnect/shell/xpcshell.cpp | 8 +- js/xpconnect/src/XPCComponents.cpp | 7 +- js/xpconnect/src/XPCConvert.cpp | 6 - js/xpconnect/src/XPCJSRuntime.cpp | 7 - js/xpconnect/src/XPCQuickStubs.cpp | 8 - js/xpconnect/src/nsXPConnect.cpp | 8 +- js/xpconnect/src/xpcprivate.h | 4 +- modules/libpref/src/init/all.js | 2 - 96 files changed, 259 insertions(+), 13038 deletions(-) delete mode 100644 js/src/jsxml.cpp delete mode 100644 js/src/jsxml.h diff --git a/content/base/src/nsFrameMessageManager.cpp b/content/base/src/nsFrameMessageManager.cpp index 82a63d75eed6..32a470cae2f3 100644 --- a/content/base/src/nsFrameMessageManager.cpp +++ b/content/base/src/nsFrameMessageManager.cpp @@ -1129,10 +1129,7 @@ nsFrameScriptExecutor::InitTabChildGlobalInternal(nsISupports* aScope) nsContentUtils::GetSecurityManager()->GetSystemPrincipal(getter_AddRefs(mPrincipal)); - bool allowXML = Preferences::GetBool("javascript.options.xml.chrome"); - JS_SetOptions(cx, JS_GetOptions(cx) | - JSOPTION_PRIVATE_IS_NSISUPPORTS | - (allowXML ? JSOPTION_ALLOW_XML : 0)); + JS_SetOptions(cx, JS_GetOptions(cx) | JSOPTION_PRIVATE_IS_NSISUPPORTS); JS_SetVersion(cx, JSVERSION_LATEST); JS_SetErrorReporter(cx, ContentScriptErrorReporter); diff --git a/content/base/src/nsScriptLoader.cpp b/content/base/src/nsScriptLoader.cpp index 69017d7efd36..62259aaadda8 100644 --- a/content/base/src/nsScriptLoader.cpp +++ b/content/base/src/nsScriptLoader.cpp @@ -398,20 +398,6 @@ ParseTypeAttribute(const nsAString& aType, JSVersion* aVersion) return false; } - nsAutoString value; - rv = parser.GetParameter("e4x", value); - if (NS_SUCCEEDED(rv)) { - if (value.Length() == 1 && value[0] == '1') { - // This happens in about 2 web pages. Enable E4X no matter what JS - // version number was selected. We do this by turning on the "moar - // XML" version bit. This is OK even if version has - // JSVERSION_UNKNOWN (-1). - *aVersion = js::VersionSetMoarXML(*aVersion, true); - } - } else if (rv != NS_ERROR_INVALID_ARG) { - return false; - } - return true; } diff --git a/content/xul/document/src/nsXULContentSink.cpp b/content/xul/document/src/nsXULContentSink.cpp index 54eb53f8a48f..ab7fa15c855e 100644 --- a/content/xul/document/src/nsXULContentSink.cpp +++ b/content/xul/document/src/nsXULContentSink.cpp @@ -1,4 +1,5 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* vim: set ts=8 sts=4 et sw=4 tw=80: */ /* 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/. */ @@ -873,30 +874,14 @@ XULContentSinkImpl::OpenScript(const PRUnichar** aAttributes, } if (langID != nsIProgrammingLanguage::UNKNOWN) { - // Get the version string, and ensure the language supports it. - nsAutoString versionName; - rv = parser.GetParameter("version", versionName); + // Get the version string, and ensure the language supports it. + nsAutoString versionName; + rv = parser.GetParameter("version", versionName); - if (NS_SUCCEEDED(rv)) { - version = nsContentUtils::ParseJavascriptVersion(versionName); - } else if (rv != NS_ERROR_INVALID_ARG) { - return rv; - } - } - // Some js specifics yet to be abstracted. - if (langID == nsIProgrammingLanguage::JAVASCRIPT) { - // By default scripts in XUL documents have E4X turned on. This - // is still OK if version is JSVERSION_UNKNOWN (-1), - version = js::VersionSetMoarXML(JSVersion(version), true); - - nsAutoString value; - rv = parser.GetParameter("e4x", value); - if (NS_FAILED(rv)) { - if (rv != NS_ERROR_INVALID_ARG) - return rv; - } else { - if (value.Length() == 1 && value[0] == '0') - version = js::VersionSetMoarXML(JSVersion(version), false); + if (NS_SUCCEEDED(rv)) { + version = nsContentUtils::ParseJavascriptVersion(versionName); + } else if (rv != NS_ERROR_INVALID_ARG) { + return rv; } } } @@ -907,10 +892,6 @@ XULContentSinkImpl::OpenScript(const PRUnichar** aAttributes, nsAutoString lang(aAttributes[1]); if (nsContentUtils::IsJavaScriptLanguage(lang, &version)) { langID = nsIProgrammingLanguage::JAVASCRIPT; - - // Even when JS version < 1.6 is specified, E4X is - // turned on in XUL. - version = js::VersionSetMoarXML(JSVersion(version), true); } } aAttributes += 2; diff --git a/dom/base/nsGlobalWindow.cpp b/dom/base/nsGlobalWindow.cpp index 18e4f39e4423..8ebb7a2e9b7a 100644 --- a/dom/base/nsGlobalWindow.cpp +++ b/dom/base/nsGlobalWindow.cpp @@ -1906,17 +1906,8 @@ nsGlobalWindow::CreateOuterObject(nsGlobalWindow* aNewInner) { JSContext* cx = mContext->GetNativeContext(); - bool isChrome = IsChromeWindow(); - if (isChrome) { - // Always enable E4X for XUL and other chrome content -- there is no - // need to preserve the as a token, - not backward compatible with - the comment-hiding hack used - in HTML script tags. */ + +/* JS_BIT(6) is currently unused. */ + +/* JS_BIT(7) is currently unused. */ + #define JSOPTION_DONT_REPORT_UNCAUGHT \ JS_BIT(8) /* When returning from the outermost API call, prevent @@ -3216,7 +3189,7 @@ JS_StringToVersion(const char *string); #define JSOPTION_ION JS_BIT(20) /* IonMonkey */ /* Options which reflect compile-time properties of scripts. */ -#define JSCOMPILEOPTION_MASK (JSOPTION_ALLOW_XML | JSOPTION_MOAR_XML) +#define JSCOMPILEOPTION_MASK 0 #define JSRUNOPTION_MASK (JS_BITMASK(21) & ~JSCOMPILEOPTION_MASK) #define JSALLOPTION_MASK (JSCOMPILEOPTION_MASK | JSRUNOPTION_MASK) diff --git a/js/src/jsarray.cpp b/js/src/jsarray.cpp index 42f3a74e9539..6ec1654c43c9 100644 --- a/js/src/jsarray.cpp +++ b/js/src/jsarray.cpp @@ -93,7 +93,7 @@ js::GetLengthProperty(JSContext *cx, HandleObject obj, uint32_t *lengthp) } /* - * Determine if the id represents an array index or an XML property index. + * Determine if the id represents an array index. * * An id is an array index according to ECMA by (15.4): * diff --git a/js/src/jsast.tbl b/js/src/jsast.tbl index 556d2643db74..6b4ae7940084 100644 --- a/js/src/jsast.tbl +++ b/js/src/jsast.tbl @@ -66,23 +66,4 @@ ASTDEF(AST_ARRAY_PATT, "ArrayPattern", "arrayPatter ASTDEF(AST_OBJECT_PATT, "ObjectPattern", "objectPattern") ASTDEF(AST_PROP_PATT, "Property", "propertyPattern") -ASTDEF(AST_XMLANYNAME, "XMLAnyName", "xmlAnyName") -ASTDEF(AST_XMLATTR_SEL, "XMLAttributeSelector", "xmlAttributeSelector") -ASTDEF(AST_XMLESCAPE, "XMLEscape", "xmlEscape") -ASTDEF(AST_XMLFILTER, "XMLFilterExpression", "xmlFilterExpression") -ASTDEF(AST_XMLDEFAULT, "XMLDefaultDeclaration", "xmlDefaultDeclaration") -ASTDEF(AST_XMLQUAL, "XMLQualifiedIdentifier", "xmlQualifiedIdentifier") -ASTDEF(AST_XMLFUNCQUAL, "XMLFunctionQualifiedIdentifier", "xmlFunctionQualifiedIdentifier") -ASTDEF(AST_XMLELEM, "XMLElement", "xmlElement") -ASTDEF(AST_XMLTEXT, "XMLText", "xmlText") -ASTDEF(AST_XMLLIST, "XMLList", "xmlList") -ASTDEF(AST_XMLSTART, "XMLStartTag", "xmlStartTag") -ASTDEF(AST_XMLEND, "XMLEndTag", "xmlEndTag") -ASTDEF(AST_XMLPOINT, "XMLPointTag", "xmlPointTag") -ASTDEF(AST_XMLNAME, "XMLName", "xmlName") -ASTDEF(AST_XMLATTR, "XMLAttribute", "xmlAttribute") -ASTDEF(AST_XMLCDATA, "XMLCdata", "xmlCdata") -ASTDEF(AST_XMLCOMMENT, "XMLComment", "xmlComment") -ASTDEF(AST_XMLPI, "XMLProcessingInstruction", "xmlProcessingInstruction") - /* AST_LIMIT = last + 1 */ diff --git a/js/src/jsatom.cpp b/js/src/jsatom.cpp index ce09c35e01e7..30b6e12fdcf9 100644 --- a/js/src/jsatom.cpp +++ b/js/src/jsatom.cpp @@ -24,7 +24,6 @@ #include "jsnum.h" #include "jsstr.h" #include "jsversion.h" -#include "jsxml.h" #include "frontend/Parser.h" #include "gc/Marking.h" @@ -57,7 +56,6 @@ const char * js::TypeStrings[] = { js_number_str, js_boolean_str, js_null_str, - js_xml_str, }; #define DEFINE_PROTO_STRING(name,code,init) const char js_##name##_str[] = #name; @@ -452,32 +450,6 @@ js::InternNonIntElementId(JSContext *cx, JSObject *obj, const Value &idval, typename MaybeRooted::MutableHandleType idp, typename MaybeRooted::MutableHandleType vp) { -#if JS_HAS_XML_SUPPORT - if (idval.isObject()) { - JSObject *idobj = &idval.toObject(); - - if (obj && obj->isXML()) { - idp.set(OBJECT_TO_JSID(idobj)); - vp.set(idval); - return true; - } - - if (!allowGC) - return false; - - if (js_GetLocalNameFromFunctionQName(idobj, idp.address(), cx)) { - vp.set(IdToValue(idp)); - return true; - } - - if (!obj && idobj->isXMLId()) { - idp.set(OBJECT_TO_JSID(idobj)); - vp.set(idval); - return JS_TRUE; - } - } -#endif - JSAtom *atom = ToAtom(cx, idval); if (!atom) return false; diff --git a/js/src/jsclass.h b/js/src/jsclass.h index c1f413985807..a40861277c44 100644 --- a/js/src/jsclass.h +++ b/js/src/jsclass.h @@ -33,10 +33,10 @@ SPECIALID_TO_JSID(const SpecialId &sid); * (PropertyName, see vm/String.h); and by various special values. * * Special values are encoded using SpecialId, which is layout-compatible but - * non-interconvertible with jsid. A SpecialId may be: an object (used by E4X - * and perhaps eventually by Harmony-proposed private names); JSID_VOID, which + * non-interconvertible with jsid. A SpecialId is used for JSID_VOID, which * does not occur in JS scripts but may be used to indicate the absence of a - * valid identifier; or JS_DEFAULT_XML_NAMESPACE_ID, if E4X is enabled. + * valid identifier. In the future, a SpecialId may also be an object used by + * Harmony-proposed private names. */ class SpecialId { @@ -48,7 +48,6 @@ class SpecialId static const uintptr_t TYPE_VOID = JSID_TYPE_VOID; static const uintptr_t TYPE_OBJECT = JSID_TYPE_OBJECT; - static const uintptr_t TYPE_DEFAULT_XML_NAMESPACE = JSID_TYPE_DEFAULT_XML_NAMESPACE; static const uintptr_t TYPE_MASK = JSID_TYPE_MASK; SpecialId(uintptr_t bits) : bits(bits) { } @@ -97,18 +96,6 @@ class SpecialId bool isVoid() const { return bits == TYPE_VOID; } - - /* Default XML namespace */ - - static SpecialId defaultXMLNamespace() { - SpecialId sid(TYPE_DEFAULT_XML_NAMESPACE); - JS_ASSERT(sid.isDefaultXMLNamespace()); - return sid; - } - - bool isDefaultXMLNamespace() const { - return bits == TYPE_DEFAULT_XML_NAMESPACE; - } }; static JS_ALWAYS_INLINE jsid @@ -119,15 +106,13 @@ SPECIALID_TO_JSID(const SpecialId &sid) JS_ASSERT_IF(sid.isObject(), JSID_IS_OBJECT(id) && JSID_TO_OBJECT(id) == sid.toObject()); JS_ASSERT_IF(sid.isVoid(), JSID_IS_VOID(id)); JS_ASSERT_IF(sid.isEmpty(), JSID_IS_EMPTY(id)); - JS_ASSERT_IF(sid.isDefaultXMLNamespace(), JSID_IS_DEFAULT_XML_NAMESPACE(id)); return id; } static JS_ALWAYS_INLINE bool JSID_IS_SPECIAL(jsid id) { - return JSID_IS_OBJECT(id) || JSID_IS_EMPTY(id) || JSID_IS_VOID(id) || - JSID_IS_DEFAULT_XML_NAMESPACE(id); + return JSID_IS_OBJECT(id) || JSID_IS_EMPTY(id) || JSID_IS_VOID(id); } static JS_ALWAYS_INLINE SpecialId @@ -138,10 +123,8 @@ JSID_TO_SPECIALID(jsid id) return SpecialId(*JSID_TO_OBJECT(id)); if (JSID_IS_EMPTY(id)) return SpecialId::empty(); - if (JSID_IS_VOID(id)) - return SpecialId::voidId(); - JS_ASSERT(JSID_IS_DEFAULT_XML_NAMESPACE(id)); - return SpecialId::defaultXMLNamespace(); + JS_ASSERT(JSID_IS_VOID(id)); + return SpecialId::voidId(); } typedef JS::Handle HandleSpecialId; diff --git a/js/src/jscntxt.h b/js/src/jscntxt.h index 0140f942d242..94399ccca1f7 100644 --- a/js/src/jscntxt.h +++ b/js/src/jscntxt.h @@ -878,14 +878,6 @@ struct JSRuntime : js::RuntimeFriendFields, */ bool gcGenerationalEnabled; - /* - * Whether exact stack scanning is enabled for this runtime. This is - * currently only used for dynamic root analysis. Exact scanning starts out - * enabled, and is disabled if e4x has been used. - */ - bool gcExactScanningEnabled; - - /* * This is true if we are in the middle of a brain transplant (e.g., * JS_TransplantObject) or some other operation that can manipulate @@ -1289,25 +1281,6 @@ namespace js { struct AutoResolving; -static inline bool -OptionsHasAllowXML(uint32_t options) -{ - return !!(options & JSOPTION_ALLOW_XML); -} - -static inline bool -OptionsHasMoarXML(uint32_t options) -{ - return !!(options & JSOPTION_MOAR_XML); -} - -static inline bool -OptionsSameVersionFlags(uint32_t self, uint32_t other) -{ - static const uint32_t mask = JSOPTION_MOAR_XML; - return !((self & mask) ^ (other & mask)); -} - /* * Flags accompany script version data so that a) dynamically created scripts * can inherit their caller's compile-time properties and b) scripts can be @@ -1318,9 +1291,7 @@ OptionsSameVersionFlags(uint32_t self, uint32_t other) */ namespace VersionFlags { static const unsigned MASK = 0x0FFF; /* see JSVersion in jspubtd.h */ -static const unsigned ALLOW_XML = 0x1000; /* flag induced by JSOPTION_ALLOW_XML */ -static const unsigned MOAR_XML = 0x2000; /* flag induced by JSOPTION_MOAR_XML */ -static const unsigned FULL_MASK = 0x3FFF; +static const unsigned FULL_MASK = 0x0FFF; } /* namespace VersionFlags */ static inline JSVersion @@ -1329,25 +1300,6 @@ VersionNumber(JSVersion version) return JSVersion(uint32_t(version) & VersionFlags::MASK); } -static inline bool -VersionHasAllowXML(JSVersion version) -{ - return !!(version & VersionFlags::ALLOW_XML); -} - -static inline bool -VersionHasMoarXML(JSVersion version) -{ - return !!(version & VersionFlags::MOAR_XML); -} - -/* @warning This is a distinct condition from having the XML flag set. */ -static inline bool -VersionShouldParseXML(JSVersion version) -{ - return VersionHasMoarXML(version) || VersionNumber(version) >= JSVERSION_1_6; -} - static inline JSVersion VersionExtractFlags(JSVersion version) { @@ -1369,8 +1321,7 @@ VersionHasFlags(JSVersion version) static inline unsigned VersionFlagsToOptions(JSVersion version) { - unsigned copts = (VersionHasAllowXML(version) ? JSOPTION_ALLOW_XML : 0) | - (VersionHasMoarXML(version) ? JSOPTION_MOAR_XML : 0); + unsigned copts = 0; JS_ASSERT((copts & JSCOMPILEOPTION_MASK) == copts); return copts; } @@ -1378,13 +1329,7 @@ VersionFlagsToOptions(JSVersion version) static inline JSVersion OptionFlagsToVersion(unsigned options, JSVersion version) { - uint32_t v = version; - v &= ~(VersionFlags::ALLOW_XML | VersionFlags::MOAR_XML); - if (OptionsHasAllowXML(options)) - v |= VersionFlags::ALLOW_XML; - if (OptionsHasMoarXML(options)) - v |= VersionFlags::MOAR_XML; - return JSVersion(v); + return version; } static inline bool @@ -1789,25 +1734,6 @@ struct AutoResolving { MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER }; -#if JS_HAS_XML_SUPPORT -class AutoXMLRooter : private AutoGCRooter { - public: - AutoXMLRooter(JSContext *cx, JSXML *xml - MOZ_GUARD_OBJECT_NOTIFIER_PARAM) - : AutoGCRooter(cx, XML), xml(xml) - { - MOZ_GUARD_OBJECT_NOTIFIER_INIT; - JS_ASSERT(xml); - } - - friend void AutoGCRooter::trace(JSTracer *trc); - - private: - JSXML * const xml; - MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER -}; -#endif /* JS_HAS_XML_SUPPORT */ - #ifdef JS_THREADSAFE # define JS_LOCK_GC(rt) PR_Lock((rt)->gcLock) # define JS_UNLOCK_GC(rt) PR_Unlock((rt)->gcLock) diff --git a/js/src/jscntxtinlines.h b/js/src/jscntxtinlines.h index 7d9640db8a44..bc90cc7ccf6d 100644 --- a/js/src/jscntxtinlines.h +++ b/js/src/jscntxtinlines.h @@ -13,7 +13,6 @@ #include "jsfriendapi.h" #include "jsinterp.h" #include "jsprobes.h" -#include "jsxml.h" #include "jsgc.h" #include "builtin/Object.h" // For js::obj_construct @@ -135,31 +134,6 @@ struct PreserveRegsGuard FrameRegs ®s_; }; -#if JS_HAS_XML_SUPPORT - -class AutoNamespaceArray : protected AutoGCRooter { - public: - AutoNamespaceArray(JSContext *cx) - : AutoGCRooter(cx, NAMESPACES), context(cx) { - array.init(); - } - - ~AutoNamespaceArray() { - array.finish(context->runtime->defaultFreeOp()); - } - - uint32_t length() const { return array.length; } - - private: - JSContext *context; - friend void AutoGCRooter::trace(JSTracer *trc); - - public: - JSXMLArray array; -}; - -#endif /* JS_HAS_XML_SUPPORT */ - #ifdef JS_CRASH_DIAGNOSTICS class CompartmentChecker { diff --git a/js/src/jsfriendapi.cpp b/js/src/jsfriendapi.cpp index 3a1a1cf0c41a..e9c349461f6a 100644 --- a/js/src/jsfriendapi.cpp +++ b/js/src/jsfriendapi.cpp @@ -501,15 +501,6 @@ js::SetPreserveWrapperCallback(JSRuntime *rt, PreserveWrapperCallback callback) * sufficient data has been harvested. */ -// Defined in jsxml.cpp. -extern size_t sE4XObjectsCreated; - -JS_FRIEND_API(size_t) -JS_GetE4XObjectsCreated(JSContext *) -{ - return sE4XObjectsCreated; -} - namespace js { // Defined in vm/GlobalObject.cpp. extern size_t sSetProtoCalled; @@ -718,13 +709,6 @@ js::GetContextStructuredCloneCallbacks(JSContext *cx) return cx->runtime->structuredCloneCallbacks; } -JS_FRIEND_API(JSVersion) -js::VersionSetMoarXML(JSVersion version, bool enable) -{ - return enable ? JSVersion(uint32_t(version) | VersionFlags::MOAR_XML) - : JSVersion(uint32_t(version) & ~VersionFlags::MOAR_XML); -} - JS_FRIEND_API(bool) js::CanCallContextDebugHandler(JSContext *cx) { diff --git a/js/src/jsfriendapi.h b/js/src/jsfriendapi.h index 6f23f369dc9d..78cfe495c182 100644 --- a/js/src/jsfriendapi.h +++ b/js/src/jsfriendapi.h @@ -50,9 +50,6 @@ JS_NewObjectWithUniqueType(JSContext *cx, JSClass *clasp, JSObject *proto, JSObj extern JS_FRIEND_API(uint32_t) JS_ObjectCountDynamicSlots(JSHandleObject obj); -extern JS_FRIEND_API(size_t) -JS_GetE4XObjectsCreated(JSContext *cx); - extern JS_FRIEND_API(size_t) JS_SetProtoCalled(JSContext *cx); @@ -355,17 +352,12 @@ struct Atom { } /* namespace shadow */ -extern JS_FRIEND_DATA(js::Class) AnyNameClass; -extern JS_FRIEND_DATA(js::Class) AttributeNameClass; extern JS_FRIEND_DATA(js::Class) CallClass; extern JS_FRIEND_DATA(js::Class) DeclEnvClass; extern JS_FRIEND_DATA(js::Class) FunctionClass; extern JS_FRIEND_DATA(js::Class) FunctionProxyClass; -extern JS_FRIEND_DATA(js::Class) NamespaceClass; extern JS_FRIEND_DATA(js::Class) OuterWindowProxyClass; extern JS_FRIEND_DATA(js::Class) ObjectProxyClass; -extern JS_FRIEND_DATA(js::Class) QNameClass; -extern JS_FRIEND_DATA(js::Class) XMLClass; extern JS_FRIEND_DATA(js::Class) ObjectClass; inline js::Class * @@ -712,9 +704,6 @@ SetActivityCallback(JSRuntime *rt, ActivityCallback cb, void *arg); extern JS_FRIEND_API(const JSStructuredCloneCallbacks *) GetContextStructuredCloneCallbacks(JSContext *cx); -extern JS_FRIEND_API(JSVersion) -VersionSetMoarXML(JSVersion version, bool enable); - extern JS_FRIEND_API(bool) CanCallContextDebugHandler(JSContext *cx); @@ -1362,7 +1351,7 @@ IdToValue(jsid id) return Int32Value(JSID_TO_INT(id)); if (JS_LIKELY(JSID_IS_OBJECT(id))) return ObjectValue(*JSID_TO_OBJECT(id)); - JS_ASSERT(JSID_IS_DEFAULT_XML_NAMESPACE(id) || JSID_IS_VOID(id)); + JS_ASSERT(JSID_IS_VOID(id)); return UndefinedValue(); } diff --git a/js/src/jsgc.cpp b/js/src/jsgc.cpp index 0b975f0884aa..24bb4f8c23e1 100644 --- a/js/src/jsgc.cpp +++ b/js/src/jsgc.cpp @@ -68,9 +68,6 @@ #include "jsscript.h" #include "jswatchpoint.h" #include "jsweakmap.h" -#if JS_HAS_XML_SUPPORT -#include "jsxml.h" -#endif #include "builtin/MapObject.h" #include "frontend/Parser.h" @@ -148,9 +145,6 @@ const uint32_t Arena::ThingSizes[] = { sizeof(Shape), /* FINALIZE_SHAPE */ sizeof(BaseShape), /* FINALIZE_BASE_SHAPE */ sizeof(types::TypeObject), /* FINALIZE_TYPE_OBJECT */ -#if JS_HAS_XML_SUPPORT - sizeof(JSXML), /* FINALIZE_XML */ -#endif sizeof(JSShortString), /* FINALIZE_SHORT_STRING */ sizeof(JSString), /* FINALIZE_STRING */ sizeof(JSExternalString), /* FINALIZE_EXTERNAL_STRING */ @@ -176,9 +170,6 @@ const uint32_t Arena::FirstThingOffsets[] = { OFFSET(Shape), /* FINALIZE_SHAPE */ OFFSET(BaseShape), /* FINALIZE_BASE_SHAPE */ OFFSET(types::TypeObject), /* FINALIZE_TYPE_OBJECT */ -#if JS_HAS_XML_SUPPORT - OFFSET(JSXML), /* FINALIZE_XML */ -#endif OFFSET(JSShortString), /* FINALIZE_SHORT_STRING */ OFFSET(JSString), /* FINALIZE_STRING */ OFFSET(JSExternalString), /* FINALIZE_EXTERNAL_STRING */ @@ -464,10 +455,6 @@ FinalizeArenas(FreeOp *fop, return FinalizeTypedArenas(fop, src, dest, thingKind, budget); case FINALIZE_TYPE_OBJECT: return FinalizeTypedArenas(fop, src, dest, thingKind, budget); -#if JS_HAS_XML_SUPPORT - case FINALIZE_XML: - return FinalizeTypedArenas(fop, src, dest, thingKind, budget); -#endif case FINALIZE_STRING: return FinalizeTypedArenas(fop, src, dest, thingKind, budget); case FINALIZE_SHORT_STRING: @@ -933,8 +920,8 @@ InitGCZeal(JSRuntime *rt) " 3: GC when the window paints (browser only)\n" " 4: Verify pre write barriers between instructions\n" " 5: Verify pre write barriers between paints\n" - " 6: Verify stack rooting (ignoring XML)\n" - " 7: Verify stack rooting (all roots)\n" + " 6: Verify stack rooting\n" + " 7: Verify stack rooting (yes, it's the same as 6)\n" " 8: Incremental GC in two slices: 1) mark roots 2) finish collection\n" " 9: Incremental GC in two slices: 1) mark all 2) new marking and finish\n" " 10: Incremental GC in multiple slices\n" @@ -1446,10 +1433,6 @@ ArenaLists::queueObjectsForSweep(FreeOp *fop) queueForBackgroundSweep(fop, FINALIZE_OBJECT8_BACKGROUND); queueForBackgroundSweep(fop, FINALIZE_OBJECT12_BACKGROUND); queueForBackgroundSweep(fop, FINALIZE_OBJECT16_BACKGROUND); - -#if JS_HAS_XML_SUPPORT - finalizeNow(fop, FINALIZE_XML); -#endif } void @@ -4926,16 +4909,3 @@ AutoMaybeTouchDeadCompartments::~AutoMaybeTouchDeadCompartments() runtime->gcManipulatingDeadCompartments = manipulatingDeadCompartments; } - -#if JS_HAS_XML_SUPPORT -extern size_t sE4XObjectsCreated; - -JSXML * -js_NewGCXML(JSContext *cx) -{ - if (!cx->runningWithTrustedPrincipals()) - ++sE4XObjectsCreated; - - return NewGCThing(cx, js::gc::FINALIZE_XML, sizeof(JSXML)); -} -#endif diff --git a/js/src/jsgc.h b/js/src/jsgc.h index 569c995e5e9c..c7a31075d5e2 100644 --- a/js/src/jsgc.h +++ b/js/src/jsgc.h @@ -108,9 +108,6 @@ MapAllocToTraceKind(AllocKind kind) JSTRACE_SHAPE, /* FINALIZE_SHAPE */ JSTRACE_BASE_SHAPE, /* FINALIZE_BASE_SHAPE */ JSTRACE_TYPE_OBJECT,/* FINALIZE_TYPE_OBJECT */ -#if JS_HAS_XML_SUPPORT /* FINALIZE_XML */ - JSTRACE_XML, -#endif JSTRACE_STRING, /* FINALIZE_SHORT_STRING */ JSTRACE_STRING, /* FINALIZE_STRING */ JSTRACE_STRING, /* FINALIZE_EXTERNAL_STRING */ @@ -142,9 +139,6 @@ IsNurseryAllocable(AllocKind kind) false, /* FINALIZE_SHAPE */ false, /* FINALIZE_BASE_SHAPE */ false, /* FINALIZE_TYPE_OBJECT */ -#if JS_HAS_XML_SUPPORT - false, /* FINALIZE_XML */ -#endif true, /* FINALIZE_SHORT_STRING */ true, /* FINALIZE_STRING */ false, /* FINALIZE_EXTERNAL_STRING */ @@ -176,9 +170,6 @@ IsBackgroundFinalized(AllocKind kind) false, /* FINALIZE_SHAPE */ false, /* FINALIZE_BASE_SHAPE */ false, /* FINALIZE_TYPE_OBJECT */ -#if JS_HAS_XML_SUPPORT - false, /* FINALIZE_XML */ -#endif true, /* FINALIZE_SHORT_STRING */ true, /* FINALIZE_STRING */ false, /* FINALIZE_EXTERNAL_STRING */ @@ -1004,13 +995,6 @@ struct GCMarker : public JSTracer { pushTaggedPtr(TypeTag, type); } -#if JS_HAS_XML_SUPPORT - void pushXML(JSXML *xml) { - pushTaggedPtr(XmlTag, xml); - } - -#endif - void pushIonCode(ion::IonCode *code) { pushTaggedPtr(IonCodeTag, code); } @@ -1115,7 +1099,7 @@ struct GCMarker : public JSTracer { void appendGrayRoot(void *thing, JSGCTraceKind kind); - /* The color is only applied to objects, functions and xml. */ + /* The color is only applied to objects and functions. */ uint32_t color; mozilla::DebugOnly started; @@ -1197,8 +1181,10 @@ const int ZealAllocValue = 2; const int ZealFrameGCValue = 3; const int ZealVerifierPreValue = 4; const int ZealFrameVerifierPreValue = 5; -const int ZealStackRootingSafeValue = 6; -const int ZealStackRootingValue = 7; +// These two values used to be distinct. They no longer are, but both were +// kept to avoid breaking fuzz tests. Avoid using ZealStackRootingValue__2. +const int ZealStackRootingValue = 6; +const int ZealStackRootingValue__2 = 7; const int ZealIncrementalRootsThenFinish = 8; const int ZealIncrementalMarkAllThenFinish = 9; const int ZealIncrementalMultipleSlices = 10; diff --git a/js/src/jsgcinlines.h b/js/src/jsgcinlines.h index b06208f5ab03..836538eb7546 100644 --- a/js/src/jsgcinlines.h +++ b/js/src/jsgcinlines.h @@ -11,7 +11,6 @@ #include "jscntxt.h" #include "jscompartment.h" #include "jslock.h" -#include "jsxml.h" #include "gc/Root.h" #include "js/TemplateLib.h" @@ -604,9 +603,4 @@ js_NewGCBaseShape(JSContext *cx) return js::gc::NewGCThing(cx, js::gc::FINALIZE_BASE_SHAPE, sizeof(js::BaseShape)); } -#if JS_HAS_XML_SUPPORT -extern JSXML * -js_NewGCXML(JSContext *cx); -#endif - #endif /* jsgcinlines_h___ */ diff --git a/js/src/jsinfer.cpp b/js/src/jsinfer.cpp index b5683526c5a4..900d83b04c33 100644 --- a/js/src/jsinfer.cpp +++ b/js/src/jsinfer.cpp @@ -45,10 +45,6 @@ #include "vm/Stack-inl.h" -#ifdef JS_HAS_XML_SUPPORT -#include "jsxml.h" -#endif - #ifdef __SUNPRO_CC #include #endif @@ -3991,9 +3987,6 @@ ScriptAnalysis::analyzeTypesBytecode(JSContext *cx, unsigned offset, TypeInferen case JSOP_CONDSWITCH: case JSOP_DEFAULT: case JSOP_POPN: - case JSOP_STARTXML: - case JSOP_STARTXMLEXPR: - case JSOP_DEFXMLNS: case JSOP_POPV: case JSOP_DEBUGGER: case JSOP_SETCALL: @@ -4035,7 +4028,6 @@ ScriptAnalysis::analyzeTypesBytecode(JSContext *cx, unsigned offset, TypeInferen case JSOP_STRICTNE: case JSOP_IN: case JSOP_INSTANCEOF: - case JSOP_DELDESC: pushed[0].addType(cx, Type::BooleanType()); break; case JSOP_DOUBLE: @@ -4044,12 +4036,6 @@ ScriptAnalysis::analyzeTypesBytecode(JSContext *cx, unsigned offset, TypeInferen case JSOP_STRING: case JSOP_TYPEOF: case JSOP_TYPEOFEXPR: - case JSOP_QNAMEPART: - case JSOP_XMLTAGEXPR: - case JSOP_TOATTRVAL: - case JSOP_ADDATTRNAME: - case JSOP_ADDATTRVAL: - case JSOP_XMLELTEXPR: pushed[0].addType(cx, Type::StringType()); break; case JSOP_NULL: @@ -4639,39 +4625,6 @@ ScriptAnalysis::analyzeTypesBytecode(JSContext *cx, unsigned offset, TypeInferen pushed[0].addType(cx, Type::UnknownType()); break; - case JSOP_CALLXMLNAME: - pushed[1].addType(cx, Type::UnknownType()); - /* FALLTHROUGH */ - - case JSOP_XMLNAME: - pushed[0].addType(cx, Type::UnknownType()); - break; - - case JSOP_SETXMLNAME: - cx->compartment->types.monitorBytecode(cx, script, offset); - poppedTypes(pc, 0)->addSubset(cx, &pushed[0]); - break; - - case JSOP_BINDXMLNAME: - break; - - case JSOP_TOXML: - case JSOP_TOXMLLIST: - case JSOP_XMLPI: - case JSOP_XMLCDATA: - case JSOP_XMLCOMMENT: - case JSOP_DESCENDANTS: - case JSOP_TOATTRNAME: - case JSOP_QNAMECONST: - case JSOP_QNAME: - case JSOP_ANYNAME: - case JSOP_GETFUNNS: - case JSOP_FILTER: - /* Note: the second value pushed by filter is a hole, and not modelled. */ - case JSOP_ENDFILTER: - pushed[0].addType(cx, Type::UnknownType()); - break; - case JSOP_CALLEE: pushed[0].addType(cx, Type::AnyObjectType()); break; @@ -5719,7 +5672,6 @@ IgnorePushed(const jsbytecode *pc, unsigned index) case JSOP_BINDNAME: case JSOP_BINDGNAME: case JSOP_BINDINTRINSIC: - case JSOP_BINDXMLNAME: return true; /* Stack not consistent in TRY_BRANCH_AFTER_COND. */ @@ -5740,8 +5692,6 @@ IgnorePushed(const jsbytecode *pc, unsigned index) /* Holes tracked separately. */ case JSOP_HOLE: return (index == 0); - case JSOP_FILTER: - return (index == 1); /* Storage for 'with' and 'let' blocks not monitored. */ case JSOP_ENTERWITH: @@ -6066,15 +6016,6 @@ JSObject::makeLazyType(JSContext *cx) if (self->lastProperty()->hasObjectFlag(BaseShape::ITERATED_SINGLETON)) type->flags |= OBJECT_FLAG_ITERATED; -#if JS_HAS_XML_SUPPORT - /* - * XML objects do not have equality hooks but are treated special by EQ/NE - * ops. Just mark the type as totally unknown. - */ - if (self->isXML() && !type->unknownProperties()) - type->markUnknown(cx); -#endif - if (self->getClass()->ext.equality) type->flags |= OBJECT_FLAG_SPECIAL_EQUALITY; if (self->getClass()->emulatesUndefined()) @@ -6215,12 +6156,6 @@ JSCompartment::getNewType(JSContext *cx, Class *clasp, TaggedProto proto_, JSFun if (fun) CheckNewScriptProperties(cx, type, fun); -#if JS_HAS_XML_SUPPORT - /* Special case for XML object equality, see makeLazyType(). */ - if (obj->isXML() && !type->unknownProperties()) - type->flags |= OBJECT_FLAG_UNKNOWN_MASK; -#endif - if (obj->isRegExp()) { AddTypeProperty(cx, type, "source", types::Type::StringType()); AddTypeProperty(cx, type, "global", types::Type::BooleanType()); diff --git a/js/src/jsinterp.cpp b/js/src/jsinterp.cpp index cfb576d6ddc0..e49639dfd493 100644 --- a/js/src/jsinterp.cpp +++ b/js/src/jsinterp.cpp @@ -66,10 +66,6 @@ #include "vm/Stack-inl.h" #include "vm/String-inl.h" -#if JS_HAS_XML_SUPPORT -#include "jsxml.h" -#endif - #include "jsautooplen.h" #if defined(JS_METHODJIT) && defined(JS_MONOIC) @@ -205,15 +201,6 @@ js::OnUnknownMethod(JSContext *cx, HandleObject obj, Value idval_, MutableHandle if (value.get().isPrimitive()) { vp.set(value); } else { -#if JS_HAS_XML_SUPPORT - /* Extract the function name from function::name qname. */ - if (idval.get().isObject()) { - JSObject *obj = &idval.get().toObject(); - if (js_GetLocalNameFromFunctionQName(obj, id.address(), cx)) - idval = IdToValue(id); - } -#endif - JSObject *obj = NewObjectWithClassProto(cx, &js_NoSuchMethodClass, NULL, NULL); if (!obj) return false; @@ -592,17 +579,6 @@ js::HasInstance(JSContext *cx, HandleObject obj, HandleValue v, JSBool *bp) bool js::LooselyEqual(JSContext *cx, const Value &lval, const Value &rval, bool *result) { -#if JS_HAS_XML_SUPPORT - if (JS_UNLIKELY(lval.isObject() && lval.toObject().isXML()) || - (rval.isObject() && rval.toObject().isXML())) { - JSBool res; - if (!js_TestXMLEquality(cx, lval, rval, &res)) - return false; - *result = !!res; - return true; - } -#endif - if (SameType(lval, rval)) { if (lval.isString()) { JSString *l = lval.toString(); @@ -966,7 +942,6 @@ js::AssertValidPropertyCacheHit(JSContext *cx, JSObject *start, JS_STATIC_ASSERT(JSOP_NAME_LENGTH == JSOP_CALLNAME_LENGTH); JS_STATIC_ASSERT(JSOP_GETARG_LENGTH == JSOP_CALLARG_LENGTH); JS_STATIC_ASSERT(JSOP_GETLOCAL_LENGTH == JSOP_CALLLOCAL_LENGTH); -JS_STATIC_ASSERT(JSOP_XMLNAME_LENGTH == JSOP_CALLXMLNAME_LENGTH); /* * Same for JSOP_SETNAME and JSOP_SETPROP, which differ only slightly but @@ -1346,6 +1321,29 @@ ADD_EMPTY_CASE(JSOP_UNUSED107) ADD_EMPTY_CASE(JSOP_UNUSED132) ADD_EMPTY_CASE(JSOP_UNUSED147) ADD_EMPTY_CASE(JSOP_UNUSED148) +ADD_EMPTY_CASE(JSOP_UNUSED161) +ADD_EMPTY_CASE(JSOP_UNUSED162) +ADD_EMPTY_CASE(JSOP_UNUSED163) +ADD_EMPTY_CASE(JSOP_UNUSED164) +ADD_EMPTY_CASE(JSOP_UNUSED165) +ADD_EMPTY_CASE(JSOP_UNUSED166) +ADD_EMPTY_CASE(JSOP_UNUSED167) +ADD_EMPTY_CASE(JSOP_UNUSED168) +ADD_EMPTY_CASE(JSOP_UNUSED169) +ADD_EMPTY_CASE(JSOP_UNUSED170) +ADD_EMPTY_CASE(JSOP_UNUSED171) +ADD_EMPTY_CASE(JSOP_UNUSED172) +ADD_EMPTY_CASE(JSOP_UNUSED173) +ADD_EMPTY_CASE(JSOP_UNUSED174) +ADD_EMPTY_CASE(JSOP_UNUSED175) +ADD_EMPTY_CASE(JSOP_UNUSED176) +ADD_EMPTY_CASE(JSOP_UNUSED177) +ADD_EMPTY_CASE(JSOP_UNUSED178) +ADD_EMPTY_CASE(JSOP_UNUSED179) +ADD_EMPTY_CASE(JSOP_UNUSED180) +ADD_EMPTY_CASE(JSOP_UNUSED181) +ADD_EMPTY_CASE(JSOP_UNUSED182) +ADD_EMPTY_CASE(JSOP_UNUSED183) ADD_EMPTY_CASE(JSOP_UNUSED188) ADD_EMPTY_CASE(JSOP_UNUSED189) ADD_EMPTY_CASE(JSOP_UNUSED190) @@ -1361,10 +1359,6 @@ ADD_EMPTY_CASE(JSOP_UNUSED222) ADD_EMPTY_CASE(JSOP_UNUSED223) ADD_EMPTY_CASE(JSOP_CONDSWITCH) ADD_EMPTY_CASE(JSOP_TRY) -#if JS_HAS_XML_SUPPORT -ADD_EMPTY_CASE(JSOP_STARTXML) -ADD_EMPTY_CASE(JSOP_STARTXMLEXPR) -#endif END_EMPTY_CASES BEGIN_CASE(JSOP_LOOPHEAD) @@ -1616,12 +1610,6 @@ BEGIN_CASE(JSOP_AND) } END_CASE(JSOP_AND) -/* - * If the index value at sp[n] is not an int that fits in a jsval, it could - * be an object (an XML QName, AttributeName, or AnyName), but only if we are - * compiling with JS_HAS_XML_SUPPORT. Otherwise convert the index value to a - * string atom id. - */ #define FETCH_ELEMENT_ID(obj, n, id) \ JS_BEGIN_MACRO \ const Value &idval_ = regs.sp[n]; \ @@ -2139,10 +2127,9 @@ END_CASE(JSOP_DELELEM) BEGIN_CASE(JSOP_TOID) { /* - * Increment or decrement requires use to lookup the same property twice, but we need to avoid - * the oberservable stringification the second time. - * There must be an object value below the id, which will not be popped - * but is necessary in interning the id for XML. + * Increment or decrement requires use to lookup the same property twice, + * but we need to avoid the observable stringification the second time. + * There must be an object value below the id, which will not be popped. */ RootedValue &objval = rootValue0, &idval = rootValue1; objval = regs.sp[-2]; @@ -3126,339 +3113,6 @@ BEGIN_CASE(JSOP_DEBUGGER) } END_CASE(JSOP_DEBUGGER) -#if JS_HAS_XML_SUPPORT -BEGIN_CASE(JSOP_DEFXMLNS) -{ - JS_ASSERT(!script->strict); - - if (!js_SetDefaultXMLNamespace(cx, regs.sp[-1])) - goto error; - regs.sp--; -} -END_CASE(JSOP_DEFXMLNS) - -BEGIN_CASE(JSOP_ANYNAME) -{ - JS_ASSERT(!script->strict); - - 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->strict) 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']. - */ - PUSH_STRING(script->getAtom(regs.pc)); -END_CASE(JSOP_QNAMEPART) - -#if JS_HAS_XML_SUPPORT -BEGIN_CASE(JSOP_QNAMECONST) -{ - JS_ASSERT(!script->strict); - Value rval = StringValue(script->getAtom(regs.pc)); - Value lval = regs.sp[-1]; - JSObject *obj = js_ConstructXMLQNameObject(cx, lval, rval); - if (!obj) - goto error; - regs.sp[-1].setObject(*obj); -} -END_CASE(JSOP_QNAMECONST) - -BEGIN_CASE(JSOP_QNAME) -{ - JS_ASSERT(!script->strict); - - Value rval = regs.sp[-1]; - Value lval = regs.sp[-2]; - JSObject *obj = js_ConstructXMLQNameObject(cx, lval, rval); - if (!obj) - goto error; - regs.sp--; - regs.sp[-1].setObject(*obj); -} -END_CASE(JSOP_QNAME) - -BEGIN_CASE(JSOP_TOATTRNAME) -{ - JS_ASSERT(!script->strict); - - Value rval; - rval = regs.sp[-1]; - if (!js_ToAttributeName(cx, &rval)) - goto error; - regs.sp[-1] = rval; -} -END_CASE(JSOP_TOATTRNAME) - -BEGIN_CASE(JSOP_TOATTRVAL) -{ - JS_ASSERT(!script->strict); - - Value rval; - rval = regs.sp[-1]; - JS_ASSERT(rval.isString()); - JSString *str = js_EscapeAttributeValue(cx, rval.toString(), JS_FALSE); - if (!str) - goto error; - regs.sp[-1].setString(str); -} -END_CASE(JSOP_TOATTRVAL) - -BEGIN_CASE(JSOP_ADDATTRNAME) -BEGIN_CASE(JSOP_ADDATTRVAL) -{ - JS_ASSERT(!script->strict); - - Value rval = regs.sp[-1]; - Value lval = regs.sp[-2]; - JSString *str = lval.toString(); - JSString *str2 = rval.toString(); - str = js_AddAttributePart(cx, op == JSOP_ADDATTRNAME, str, str2); - if (!str) - goto error; - regs.sp--; - regs.sp[-1].setString(str); -} -END_CASE(JSOP_ADDATTRNAME) - -BEGIN_CASE(JSOP_BINDXMLNAME) -{ - JS_ASSERT(!script->strict); - - Value lval; - lval = regs.sp[-1]; - RootedObject &obj = rootObject0; - jsid id; - if (!js_FindXMLProperty(cx, lval, &obj, &id)) - goto error; - regs.sp[-1].setObjectOrNull(obj); - PUSH_COPY(IdToValue(id)); -} -END_CASE(JSOP_BINDXMLNAME) - -BEGIN_CASE(JSOP_SETXMLNAME) -{ - JS_ASSERT(!script->strict); - - RootedObject &obj = rootObject0; - obj = ®s.sp[-3].toObject(); - RootedValue &rval = rootValue0; - rval = regs.sp[-1]; - RootedId &id = rootId0; - FETCH_ELEMENT_ID(obj, -2, id); - if (!JSObject::setGeneric(cx, obj, obj, id, &rval, script->strict)) - goto error; - rval = regs.sp[-1]; - regs.sp -= 2; - regs.sp[-1] = rval; -} -END_CASE(JSOP_SETXMLNAME) - -BEGIN_CASE(JSOP_CALLXMLNAME) -BEGIN_CASE(JSOP_XMLNAME) -{ - JS_ASSERT(!script->strict); - - Value lval = regs.sp[-1]; - RootedObject &obj = rootObject0; - RootedId &id = rootId0; - if (!js_FindXMLProperty(cx, lval, &obj, id.address())) - goto error; - RootedValue &rval = rootValue0; - if (!JSObject::getGeneric(cx, obj, obj, id, &rval)) - goto error; - regs.sp[-1] = rval; - if (op == JSOP_CALLXMLNAME) { - Value v; - if (!ComputeImplicitThis(cx, obj, &v)) - goto error; - PUSH_COPY(v); - } -} -END_CASE(JSOP_XMLNAME) - -BEGIN_CASE(JSOP_DESCENDANTS) -BEGIN_CASE(JSOP_DELDESC) -{ - JS_ASSERT(!script->strict); - - JSObject *obj; - FETCH_OBJECT(cx, -2, obj); - jsval rval = regs.sp[-1]; - if (!js_GetXMLDescendants(cx, obj, rval, &rval)) - goto error; - - if (op == JSOP_DELDESC) { - regs.sp[-1] = rval; /* set local root */ - if (!js_DeleteXMLListElements(cx, JSVAL_TO_OBJECT(rval))) - goto error; - rval = JSVAL_TRUE; /* always succeed */ - } - - regs.sp--; - regs.sp[-1] = rval; -} -END_CASE(JSOP_DESCENDANTS) - -BEGIN_CASE(JSOP_FILTER) -{ - JS_ASSERT(!script->strict); - - /* - * We push the hole value before jumping to [enditer] so we can detect the - * first iteration and direct js_StepXMLListFilter to initialize filter's - * state. - */ - PUSH_HOLE(); - len = GET_JUMP_OFFSET(regs.pc); - JS_ASSERT(len > 0); -} -END_VARLEN_CASE - -BEGIN_CASE(JSOP_ENDFILTER) -{ - JS_ASSERT(!script->strict); - - bool cond = !regs.sp[-1].isMagic(); - if (cond) { - /* Exit the "with" block left from the previous iteration. */ - regs.fp()->popWith(cx); - } - if (!js_StepXMLListFilter(cx, cond)) - goto error; - if (!regs.sp[-1].isNull()) { - /* - * Decrease sp after EnterWith returns as we use sp[-1] there to root - * temporaries. - */ - JS_ASSERT(IsXML(regs.sp[-1])); - if (!EnterWith(cx, -2)) - goto error; - regs.sp--; - len = GET_JUMP_OFFSET(regs.pc); - JS_ASSERT(len < 0); - BRANCH(len); - } - regs.sp--; -} -END_CASE(JSOP_ENDFILTER); - -BEGIN_CASE(JSOP_TOXML) -{ - JS_ASSERT(!script->strict); - - cx->runtime->gcExactScanningEnabled = false; - - Value rval = regs.sp[-1]; - JSObject *obj = js_ValueToXMLObject(cx, rval); - if (!obj) - goto error; - regs.sp[-1].setObject(*obj); -} -END_CASE(JSOP_TOXML) - -BEGIN_CASE(JSOP_TOXMLLIST) -{ - JS_ASSERT(!script->strict); - - Value rval = regs.sp[-1]; - JSObject *obj = js_ValueToXMLListObject(cx, rval); - if (!obj) - goto error; - regs.sp[-1].setObject(*obj); -} -END_CASE(JSOP_TOXMLLIST) - -BEGIN_CASE(JSOP_XMLTAGEXPR) -{ - JS_ASSERT(!script->strict); - - Value rval = regs.sp[-1]; - JSString *str = ToString(cx, rval); - if (!str) - goto error; - regs.sp[-1].setString(str); -} -END_CASE(JSOP_XMLTAGEXPR) - -BEGIN_CASE(JSOP_XMLELTEXPR) -{ - JS_ASSERT(!script->strict); - - Value rval = regs.sp[-1]; - JSString *str; - if (IsXML(rval)) { - str = js_ValueToXMLString(cx, rval); - } else { - str = ToString(cx, rval); - if (str) - str = js_EscapeElementValue(cx, str); - } - if (!str) - goto error; - regs.sp[-1].setString(str); -} -END_CASE(JSOP_XMLELTEXPR) - -BEGIN_CASE(JSOP_XMLCDATA) -{ - JS_ASSERT(!script->strict); - - JSAtom *atom = script->getAtom(regs.pc); - JSObject *obj = js_NewXMLSpecialObject(cx, JSXML_CLASS_TEXT, NULL, atom); - if (!obj) - goto error; - PUSH_OBJECT(*obj); -} -END_CASE(JSOP_XMLCDATA) - -BEGIN_CASE(JSOP_XMLCOMMENT) -{ - JS_ASSERT(!script->strict); - - JSAtom *atom = script->getAtom(regs.pc); - JSObject *obj = js_NewXMLSpecialObject(cx, JSXML_CLASS_COMMENT, NULL, atom); - if (!obj) - goto error; - PUSH_OBJECT(*obj); -} -END_CASE(JSOP_XMLCOMMENT) - -BEGIN_CASE(JSOP_XMLPI) -{ - JS_ASSERT(!script->strict); - - JSAtom *atom = script->getAtom(regs.pc); - Value rval = regs.sp[-1]; - JSString *str2 = rval.toString(); - JSObject *obj = js_NewXMLSpecialObject(cx, JSXML_CLASS_PROCESSING_INSTRUCTION, atom, str2); - if (!obj) - goto error; - regs.sp[-1].setObject(*obj); -} -END_CASE(JSOP_XMLPI) - -BEGIN_CASE(JSOP_GETFUNNS) -{ - JS_ASSERT(!script->strict); - - Value rval; - if (!cx->fp()->global().getFunctionNamespace(cx, &rval)) - goto error; - PUSH_COPY(rval); -} -END_CASE(JSOP_GETFUNNS) -#endif /* JS_HAS_XML_SUPPORT */ - BEGIN_CASE(JSOP_ENTERBLOCK) BEGIN_CASE(JSOP_ENTERLET0) BEGIN_CASE(JSOP_ENTERLET1) diff --git a/js/src/jsinterpinlines.h b/js/src/jsinterpinlines.h index 82806c3e4ce4..bc02d5947fc6 100644 --- a/js/src/jsinterpinlines.h +++ b/js/src/jsinterpinlines.h @@ -219,21 +219,6 @@ AssertValidPropertyCacheHit(JSContext *cx, JSObject *start, JSObject *found, {} #endif -inline bool -GetPropertyGenericMaybeCallXML(JSContext *cx, JSOp op, HandleObject obj, HandleId id, MutableHandleValue vp) -{ - /* - * Various XML properties behave differently when accessed in a - * call vs. normal context, and getGeneric will not work right. - */ -#if JS_HAS_XML_SUPPORT - if (op == JSOP_CALLPROP && obj->isXML()) - return js_GetXMLMethod(cx, obj, id, vp); -#endif - - return JSObject::getGeneric(cx, obj, obj, id, vp); -} - inline bool GetLengthProperty(const Value &lval, MutableHandleValue vp) { @@ -304,7 +289,7 @@ GetPropertyOperation(JSContext *cx, JSScript *script, jsbytecode *pc, MutableHan RootedObject nobj(cx, obj); if (obj->getOps()->getProperty) { - if (!GetPropertyGenericMaybeCallXML(cx, op, nobj, id, vp)) + if (!JSObject::getGeneric(cx, nobj, nobj, id, vp)) return false; } else { if (!GetPropertyHelper(cx, nobj, id, JSGET_CACHE_RESULT, vp)) @@ -577,15 +562,6 @@ AddOperation(JSContext *cx, HandleScript script, jsbytecode *pc, return true; } -#if JS_HAS_XML_SUPPORT - if (IsXML(lhs) && IsXML(rhs)) { - if (!js_ConcatenateXML(cx, &lhs.toObject(), &rhs.toObject(), res)) - return false; - types::TypeScript::MonitorUnknown(cx, script, pc); - return true; - } -#endif - /* * If either operand is an object, any non-integer result must be * reported to inference. @@ -767,20 +743,6 @@ GetObjectElementOperation(JSContext *cx, JSOp op, JSObject *objArg, bool wasObje HandleValue rref, MutableHandleValue res) { do { - -#if JS_HAS_XML_SUPPORT - if (op == JSOP_CALLELEM && JS_UNLIKELY(objArg->isXML())) { - RootedObject obj(cx, objArg); - RootedId id(cx); - if (!FetchElementId(cx, obj, rref, &id, res)) - return false; - if (!js_GetXMLMethod(cx, obj, id, res)) - return false; - objArg = obj; - break; - } -#endif - // Don't call GetPcScript (needed for analysis) from inside Ion since it's expensive. bool analyze = !cx->fp()->beginsIonActivation(); diff --git a/js/src/jsiter.cpp b/js/src/jsiter.cpp index 3bc12860d7f0..1fa123a4cc98 100644 --- a/js/src/jsiter.cpp +++ b/js/src/jsiter.cpp @@ -30,10 +30,6 @@ #include "jsproxy.h" #include "jsscript.h" -#if JS_HAS_XML_SUPPORT -#include "jsxml.h" -#endif - #include "builtin/ParallelArray.h" #include "ds/Sort.h" #include "frontend/TokenStream.h" @@ -151,11 +147,8 @@ EnumerateNativeProperties(JSContext *cx, HandleObject pobj, unsigned flags, IdSe for (; !r.empty(); r.popFront()) { Shape &shape = r.front(); - if (!JSID_IS_DEFAULT_XML_NAMESPACE(shape.propid()) && - !Enumerate(cx, pobj, shape.propid(), shape.enumerable(), flags, ht, props)) - { + if (!Enumerate(cx, pobj, shape.propid(), shape.enumerable(), flags, ht, props)) return false; - } } ::Reverse(props->begin() + initialLength, props->end()); @@ -264,10 +257,6 @@ Snapshot(JSContext *cx, RawObject pobj_, unsigned flags, AutoIdVector *props) if (flags & JSITER_OWNONLY) break; -#if JS_HAS_XML_SUPPORT - if (pobj->isXML()) - break; -#endif } while ((pobj = pobj->getProto()) != NULL); #ifdef JS_MORE_DETERMINISTIC diff --git a/js/src/jsmemorymetrics.cpp b/js/src/jsmemorymetrics.cpp index f59dc5c4c288..97c0106ecbc6 100644 --- a/js/src/jsmemorymetrics.cpp +++ b/js/src/jsmemorymetrics.cpp @@ -64,9 +64,6 @@ CompartmentStats::gcHeapThingsSize() n += gcHeapScripts; n += gcHeapTypeObjects; n += gcHeapIonCodes; -#if JS_HAS_XML_SUPPORT - n += gcHeapXML; -#endif #ifdef DEBUG size_t n2 = n; @@ -249,13 +246,6 @@ StatsCellCallback(JSRuntime *rt, void *data, void *thing, JSGCTraceKind traceKin cStats->typeInference.typeObjects += obj->sizeOfExcludingThis(rtStats->mallocSizeOf); break; } -#if JS_HAS_XML_SUPPORT - case JSTRACE_XML: - { - cStats->gcHeapXML += thingSize; - break; - } -#endif } // Yes, this is a subtraction: see StatsArenaCallback() for details. cStats->gcHeapUnusedGcThings -= thingSize; diff --git a/js/src/jsobj.cpp b/js/src/jsobj.cpp index 29a7f11f3331..6da00d5abc98 100644 --- a/js/src/jsobj.cpp +++ b/js/src/jsobj.cpp @@ -42,7 +42,6 @@ #include "json.h" #include "jswatchpoint.h" #include "jswrapper.h" -#include "jsxml.h" #include "builtin/MapObject.h" #include "builtin/Module.h" @@ -2174,8 +2173,7 @@ js::DefineConstructorAndPrototype(JSContext *cx, HandleObject obj, JSProtoKey ke /* * Optionally construct the prototype object, before the class has * been fully initialized. Allow the ctor to replace proto with a - * different object, as is done for operator new -- and as at least - * XML support requires. + * different object, as is done for operator new. */ ctor = fun; if (!LinkConstructorAndPrototype(cx, ctor, proto)) @@ -2791,13 +2789,6 @@ js::SetClassAndProto(JSContext *cx, HandleObject obj, { JS_ASSERT_IF(!checkForCycles, obj.get() != proto.raw()); -#if JS_HAS_XML_SUPPORT - if (proto.isObject() && proto.toObject()->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 @@ -3910,16 +3901,9 @@ js::GetMethod(JSContext *cx, HandleObject obj, HandleId id, unsigned getHow, Mut JSAutoResolveFlags rf(cx, 0); GenericIdOp op = obj->getOps()->getGeneric; - if (!op) { -#if JS_HAS_XML_SUPPORT - JS_ASSERT(!obj->isXML()); -#endif + if (!op) return GetPropertyHelper(cx, obj, id, getHow, vp); - } -#if JS_HAS_XML_SUPPORT - if (obj->isXML()) - return js_GetXMLMethod(cx, obj, id, vp); -#endif + return op(cx, obj, obj, id, vp); } @@ -4409,9 +4393,6 @@ JSBool js::DefaultValue(JSContext *cx, HandleObject obj, JSType hint, MutableHandleValue vp) { JS_ASSERT(hint == JSTYPE_NUMBER || hint == JSTYPE_STRING || hint == JSTYPE_VOID); -#if JS_HAS_XML_SUPPORT - JS_ASSERT(!obj->isXML()); -#endif Rooted id(cx); diff --git a/js/src/jsobj.h b/js/src/jsobj.h index 41001253da82..226f6d42417e 100644 --- a/js/src/jsobj.h +++ b/js/src/jsobj.h @@ -237,7 +237,6 @@ extern Class StringClass; extern Class StrictArgumentsObjectClass; extern Class WeakMapClass; extern Class WithClass; -extern Class XMLFilterClass; class ArgumentsObject; class ArrayBufferObject; @@ -699,45 +698,6 @@ class JSObject : public js::ObjectImpl static const uint32_t ITER_CLASS_NFIXED_SLOTS = 1; - /* - * XML-related getters and setters. - */ - - /* - * Slots for XML-related classes are as follows: - * - NamespaceClass.base reserves the *_NAME_* and *_NAMESPACE_* slots. - * - QNameClass.base, AttributeNameClass, AnyNameClass reserve - * the *_NAME_* and *_QNAME_* slots. - * - Others (XMLClass, js_XMLFilterClass) don't reserve any slots. - */ - private: - static const uint32_t JSSLOT_NAME_PREFIX = 0; // shared - static const uint32_t JSSLOT_NAME_URI = 1; // shared - - static const uint32_t JSSLOT_NAMESPACE_DECLARED = 2; - - static const uint32_t JSSLOT_QNAME_LOCAL_NAME = 2; - - public: - static const uint32_t NAMESPACE_CLASS_RESERVED_SLOTS = 3; - static const uint32_t QNAME_CLASS_RESERVED_SLOTS = 3; - - inline JSLinearString *getNamePrefix() const; - inline jsval getNamePrefixVal() const; - inline void setNamePrefix(JSLinearString *prefix); - inline void clearNamePrefix(); - - inline JSLinearString *getNameURI() const; - inline jsval getNameURIVal() const; - inline void setNameURI(JSLinearString *uri); - - inline jsval getNamespaceDeclared() const; - inline void setNamespaceDeclared(jsval decl); - - inline JSAtom *getQNameLocalName() const; - inline jsval getQNameLocalNameVal() const; - inline void setQNameLocalName(JSAtom *name); - /* * Back to generic stuff. */ @@ -1026,12 +986,6 @@ class JSObject : public js::ObjectImpl 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; diff --git a/js/src/jsobjinlines.h b/js/src/jsobjinlines.h index efa77baf8d88..a5cba85582f4 100644 --- a/js/src/jsobjinlines.h +++ b/js/src/jsobjinlines.h @@ -22,7 +22,6 @@ #include "jsproxy.h" #include "jsstr.h" #include "jstypedarray.h" -#include "jsxml.h" #include "jswrapper.h" #include "builtin/MapObject.h" @@ -749,97 +748,6 @@ JSObject::setDateUTCTime(const js::Value &time) setFixedSlot(JSSLOT_DATE_UTC_TIME, time); } -#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; -} - -inline jsval -JSObject::getNamePrefixVal() const -{ - JS_ASSERT(isNamespace() || isQName()); - return getSlot(JSSLOT_NAME_PREFIX); -} - -inline void -JSObject::setNamePrefix(JSLinearString *prefix) -{ - JS_ASSERT(isNamespace() || isQName()); - setSlot(JSSLOT_NAME_PREFIX, prefix ? js::StringValue(prefix) : js::UndefinedValue()); -} - -inline void -JSObject::clearNamePrefix() -{ - JS_ASSERT(isNamespace() || isQName()); - setSlot(JSSLOT_NAME_PREFIX, js::UndefinedValue()); -} - -inline JSLinearString * -JSObject::getNameURI() const -{ - JS_ASSERT(isNamespace() || isQName()); - const js::Value &v = getSlot(JSSLOT_NAME_URI); - return !v.isUndefined() ? &v.toString()->asLinear() : NULL; -} - -inline jsval -JSObject::getNameURIVal() const -{ - JS_ASSERT(isNamespace() || isQName()); - return getSlot(JSSLOT_NAME_URI); -} - -inline void -JSObject::setNameURI(JSLinearString *uri) -{ - JS_ASSERT(isNamespace() || isQName()); - setSlot(JSSLOT_NAME_URI, uri ? js::StringValue(uri) : js::UndefinedValue()); -} - -inline jsval -JSObject::getNamespaceDeclared() const -{ - JS_ASSERT(isNamespace()); - return getSlot(JSSLOT_NAMESPACE_DECLARED); -} - -inline void -JSObject::setNamespaceDeclared(jsval decl) -{ - JS_ASSERT(isNamespace()); - setSlot(JSSLOT_NAMESPACE_DECLARED, decl); -} - -inline JSAtom * -JSObject::getQNameLocalName() const -{ - JS_ASSERT(isQName()); - const js::Value &v = getSlot(JSSLOT_QNAME_LOCAL_NAME); - return !v.isUndefined() ? &v.toString()->asAtom() : NULL; -} - -inline jsval -JSObject::getQNameLocalNameVal() const -{ - JS_ASSERT(isQName()); - return getSlot(JSSLOT_QNAME_LOCAL_NAME); -} - -inline void -JSObject::setQNameLocalName(JSAtom *name) -{ - JS_ASSERT(isQName()); - setSlot(JSSLOT_QNAME_LOCAL_NAME, name ? js::StringValue(name) : js::UndefinedValue()); -} - -#endif - /* static */ inline bool JSObject::setSingletonType(JSContext *cx, js::HandleObject obj) { @@ -1032,27 +940,6 @@ JSObject::isDebugScope() const return getClass() == &js::ObjectProxyClass && js_IsDebugScopeSlow(const_cast(this)); } -#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); -} - -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) @@ -1483,25 +1370,6 @@ GetOuterObject(JSContext *cx, HandleObject obj) return 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) ((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) { @@ -1944,23 +1812,6 @@ static JS_ALWAYS_INLINE bool ValueIsSpecial(JSObject *obj, MutableHandleValue propval, MutableHandle sidp, JSContext *cx) { -#if JS_HAS_XML_SUPPORT - if (!propval.isObject()) - return false; - - if (obj->isXML()) { - sidp.set(SpecialId(propval.toObject())); - return true; - } - - JSObject &propobj = propval.toObject(); - JSAtom *name; - if (propobj.isQName() && GetLocalNameFromFunctionQName(&propobj, &name, cx)) { - propval.setString(name); - return false; - } -#endif - return false; } diff --git a/js/src/json.cpp b/js/src/json.cpp index 9fc7629bc538..fb55276939be 100644 --- a/js/src/json.cpp +++ b/js/src/json.cpp @@ -24,7 +24,6 @@ #include "jsstr.h" #include "jstypes.h" #include "jsutil.h" -#include "jsxml.h" #include "frontend/TokenStream.h" #include "vm/StringBuffer.h" @@ -360,7 +359,7 @@ PreprocessValue(JSContext *cx, HandleObject holder, KeyType key, MutableHandleVa static inline bool IsFilteredValue(const Value &v) { - return v.isUndefined() || js_IsCallable(v) || VALUE_IS_XML(v); + return v.isUndefined() || js_IsCallable(v); } /* ES5 15.12.3 JO. */ diff --git a/js/src/jsopcode.cpp b/js/src/jsopcode.cpp index 763c40ea7897..ae69146d90ec 100644 --- a/js/src/jsopcode.cpp +++ b/js/src/jsopcode.cpp @@ -2106,14 +2106,10 @@ DecompileDestructuringLHS(SprintStack *ss, jsbytecode *pc, jsbytecode *endpc, JS /* lval is from JSOP_BINDNAME, so just print xval. */ todo = ss->sprinter.put(xval); } else if (*xval == '\0') { - /* xval is from JSOP_SETCALL or JSOP_BINDXMLNAME, print lval. */ + /* xval is from JSOP_SETCALL, so print lval. */ todo = ss->sprinter.put(lval); } else { - todo = Sprint(&ss->sprinter, - (JOF_OPMODE(ss->opcodes[ss->top+1]) == JOF_XMLNAME) - ? "%s.%s" - : "%s[%s]", - lval, xval); + todo = Sprint(&ss->sprinter, "%s[%s]", lval, xval); } if (todo < 0) return NULL; @@ -2627,18 +2623,12 @@ Decompile(SprintStack *ss, jsbytecode *pc, int nb) JSBool ok; JSBool foreach; JSBool defaultsSwitch = false; -#if JS_HAS_XML_SUPPORT - 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*/"; static const char with_cookie[] = "/*WITH*/"; - static const char dot_format[] = "%s.%s"; static const char index_format[] = "%s[%s]"; static const char predot_format[] = "%s%s.%s"; static const char postdot_format[] = "%s.%s%s"; @@ -2734,9 +2724,6 @@ Decompile(SprintStack *ss, jsbytecode *pc, int nb) rval = NULL; bool forOf = false; foreach = false; -#if JS_HAS_XML_SUPPORT - inXML = quoteAttr = false; -#endif while (nb < 0 || pc < endpc) { /* @@ -2841,9 +2828,6 @@ Decompile(SprintStack *ss, jsbytecode *pc, int nb) case JSOP_ENUMCONSTELEM: op = JSOP_GETELEM; break; - case JSOP_SETXMLNAME: - op = JSOp(JSOP_GETELEM2); - break; default: LOCAL_ASSERT(0); } @@ -2880,19 +2864,13 @@ Decompile(SprintStack *ss, jsbytecode *pc, int nb) /* Print only the right operand of the assignment-op. */ todo = ss->sprinter.put(rval); - } else if (!inXML) { + } else { rval = PopStrPrecDupe(ss, cs->prec + !!(cs->format & JOF_LEFTASSOC), &rvalpc); lval = PopStrPrec(ss, cs->prec + !(cs->format & JOF_LEFTASSOC), &lvalpc); todo = ss->sprinter.getOffset(); SprintOpcode(ss, lval, lvalpc, pc, todo); Sprint(&ss->sprinter, " %s ", token); SprintOpcode(ss, rval, rvalpc, pc, todo); - } else { - /* In XML, just concatenate the two operands. */ - LOCAL_ASSERT(op == JSOP_ADD); - rval = POP_STR(); - lval = POP_STR(); - todo = Sprint(&ss->sprinter, ss_format, lval, rval); } break; @@ -4174,11 +4152,7 @@ Decompile(SprintStack *ss, jsbytecode *pc, int nb) if (*xval == '\0') { todo = ss->sprinter.put(lval); } else { - todo = Sprint(&ss->sprinter, - (JOF_OPMODE(lastop) == JOF_XMLNAME) - ? dot_format - : index_format, - lval, xval); + todo = Sprint(&ss->sprinter, index_format, lval, xval); } break; @@ -4452,23 +4426,9 @@ Decompile(SprintStack *ss, jsbytecode *pc, int nb) lval = POP_STR(); if (*xval == '\0') goto do_delete_lval; - todo = Sprint(&ss->sprinter, - (JOF_OPMODE(lastop) == JOF_XMLNAME) - ? "%s %s.%s" - : "%s %s[%s]", - js_delete_str, lval, xval); + todo = Sprint(&ss->sprinter, "%s %s[%s]", js_delete_str, lval, xval); break; -#if JS_HAS_XML_SUPPORT - case JSOP_DELDESC: - xval = POP_STR(); - op = JSOP_GETPROP; - lval = POP_STR(); - todo = Sprint(&ss->sprinter, "%s %s..%s", - js_delete_str, lval, xval); - break; -#endif - case JSOP_TYPEOFEXPR: case JSOP_TYPEOF: case JSOP_VOID: @@ -4530,10 +4490,7 @@ Decompile(SprintStack *ss, jsbytecode *pc, int nb) op = JSOP_GETELEM; lval = POP_STR(); if (*xval != '\0') { - todo = Sprint(&ss->sprinter, - (JOF_OPMODE(lastop) == JOF_XMLNAME) - ? predot_format - : preindex_format, + todo = Sprint(&ss->sprinter, preindex_format, js_incop_strs[!(cs->format & JOF_INC)], lval, xval); } else { @@ -4591,11 +4548,7 @@ Decompile(SprintStack *ss, jsbytecode *pc, int nb) op = JSOP_GETELEM; lval = POP_STR(); if (*xval != '\0') { - todo = Sprint(&ss->sprinter, - (JOF_OPMODE(lastop) == JOF_XMLNAME) - ? postdot_format - : postindex_format, - lval, xval, + todo = Sprint(&ss->sprinter, postindex_format, lval, xval, js_incop_strs[!(cs->format & JOF_INC)]); } else { todo = Sprint(&ss->sprinter, ss_format, @@ -4660,10 +4613,9 @@ Decompile(SprintStack *ss, jsbytecode *pc, int nb) todo = ss->sprinter.getOffset(); SprintOpcode(ss, lval, lvalpc, pc, todo); if (*xval != '\0') { - bool xml = (JOF_OPMODE(lastop) == JOF_XMLNAME); - ss->sprinter.put(xml ? "." : "["); + ss->sprinter.put("["); SprintOpcode(ss, xval, xvalpc, pc, todo); - ss->sprinter.put(xml ? "" : "]"); + ss->sprinter.put("]"); } break; @@ -4679,15 +4631,14 @@ Decompile(SprintStack *ss, jsbytecode *pc, int nb) if (*xval == '\0') goto do_setlval; sn = js_GetSrcNote(cx, jp->script, pc - 1); - bool xml = (JOF_MODE(cs->format) == JOF_XMLNAME); const char *token = GetTokenForAssignment(jp, sn, lastop, pc, rvalpc, &lastlvalpc, &lastrvalpc); todo = ss->sprinter.getOffset(); SprintOpcode(ss, lval, lvalpc, pc, todo); - ss->sprinter.put(xml ? "." : "["); + ss->sprinter.put("["); SprintOpcode(ss, xval, xvalpc, pc, todo); - ss->sprinter.put(xml ? "" : "]"); + ss->sprinter.put("]"); Sprint(&ss->sprinter, " %s= ", token); SprintOpcode(ss, rval, rvalpc, pc, todo); break; @@ -4714,11 +4665,8 @@ Decompile(SprintStack *ss, jsbytecode *pc, int nb) LOAD_ATOM(0); do_name: lval = ""; -#if JS_HAS_XML_SUPPORT - do_qname: -#endif sn = js_GetSrcNote(cx, jp->script, pc); - rval = QuoteString(&ss->sprinter, atom, inXML ? DONT_ESCAPE : 0); + rval = QuoteString(&ss->sprinter, atom, 0); if (!rval) return NULL; ss->sprinter.setOffset(rval); @@ -4753,7 +4701,7 @@ Decompile(SprintStack *ss, jsbytecode *pc, int nb) case JSOP_STRING: LOAD_ATOM(0); - rval = QuoteString(&ss->sprinter, atom, inXML ? DONT_ESCAPE : '"'); + rval = QuoteString(&ss->sprinter, atom, '"'); if (!rval) return NULL; todo = ss->sprinter.getOffsetOf(rval); @@ -5266,172 +5214,6 @@ Decompile(SprintStack *ss, jsbytecode *pc, int nb) todo = -2; break; -#if JS_HAS_XML_SUPPORT - case JSOP_STARTXML: - case JSOP_STARTXMLEXPR: - inXML = op == JSOP_STARTXML; - todo = -2; - break; - - case JSOP_DEFXMLNS: - rval = POP_STR(); - js_printf(jp, "\t%s %s %s = %s;\n", - js_default_str, js_xml_str, js_namespace_str, rval); - todo = -2; - break; - - 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); - break; - - case JSOP_QNAME: - rval = POP_STR(); - lval = POP_STR(); - todo = Sprint(&ss->sprinter, "%s::[%s]", lval, rval); - break; - - case JSOP_TOATTRNAME: - op = JSOP_NOP; /* turn off parens */ - rval = POP_STR(); - todo = Sprint(&ss->sprinter, "@[%s]", rval); - break; - - case JSOP_TOATTRVAL: - todo = -2; - break; - - case JSOP_ADDATTRNAME: - rval = POP_STR(); - lval = POP_STR(); - todo = Sprint(&ss->sprinter, "%s %s", lval, rval); - /* This gets reset by all XML tag expressions. */ - quoteAttr = JS_TRUE; - break; - - case JSOP_ADDATTRVAL: - rval = POP_STR(); - lval = POP_STR(); - if (quoteAttr) - todo = Sprint(&ss->sprinter, "%s=\"%s\"", lval, rval); - else - todo = Sprint(&ss->sprinter, "%s=%s", lval, rval); - break; - - case JSOP_BINDXMLNAME: - /* Leave the name stacked and push a dummy string. */ - todo = Sprint(&ss->sprinter, ""); - break; - - case JSOP_SETXMLNAME: - /* Pop the r.h.s., the dummy string, and the name. */ - rval = PopStrDupe(ss, op, &rvalpc); - (void) PopOff(ss, op); - lval = POP_STR(); - goto do_setlval; - - case JSOP_XMLELTEXPR: - case JSOP_XMLTAGEXPR: - todo = Sprint(&ss->sprinter, "{%s}", POP_STR()); - inXML = JS_TRUE; - /* If we're an attribute value, we shouldn't quote this. */ - quoteAttr = JS_FALSE; - break; - - case JSOP_TOXMLLIST: - op = JSOP_NOP; /* turn off parens */ - todo = Sprint(&ss->sprinter, "<>%s", POP_STR()); - inXML = JS_FALSE; - break; - - case JSOP_TOXML: - case JSOP_CALLXMLNAME: - case JSOP_XMLNAME: - case JSOP_FILTER: - /* These ops indicate the end of XML expressions. */ - inXML = JS_FALSE; - todo = -2; - break; - - case JSOP_ENDFILTER: - rval = POP_STR(); - PROPAGATE_CALLNESS(); - lval = POP_STR(); - todo = Sprint(&ss->sprinter, "%s.(%s)", lval, rval); - break; - - case JSOP_DESCENDANTS: - rval = POP_STR(); - PROPAGATE_CALLNESS(); - lval = POP_STR(); - todo = Sprint(&ss->sprinter, "%s..%s", lval, rval); - break; - - case JSOP_XMLCDATA: - LOAD_ATOM(0); - todo = ss->sprinter.put("sprinter, atom, DONT_ESCAPE)) - return NULL; - ss->sprinter.put("]]>", 3); - break; - - case JSOP_XMLCOMMENT: - LOAD_ATOM(0); - todo = ss->sprinter.put("", 3); - break; - - case JSOP_XMLPI: - LOAD_ATOM(0); - rval = JS_strdup(cx, POP_STR()); - if (!rval) - return NULL; - todo = ss->sprinter.put("sprinter, atom, 0) && - (*rval == '\0' || - (ss->sprinter.put(" ", 1) >= 0 && - ss->sprinter.put(rval))); - js_free((char *)rval); - if (!ok) - return NULL; - ss->sprinter.put("?>", 2); - break; - - case JSOP_GETFUNNS: - todo = ss->sprinter.put(js_function_str, 8); - break; -#endif /* JS_HAS_XML_SUPPORT */ - case JSOP_REST: // Ignore bytecode related to handling rest. pc += GetBytecodeLength(pc); @@ -5472,19 +5254,12 @@ Decompile(SprintStack *ss, jsbytecode *pc, int nb) CopyDecompiledTextForDecomposedOp(jp, pc); } - if (op == JSOP_CALLXMLNAME) { - todo = Sprint(&ss->sprinter, ""); - if (todo < 0 || !PushOff(ss, todo, saveop)) - return NULL; - } - pc += len; } /* * Undefine local macros. */ -#undef inXML #undef DECOMPILE_CODE #undef TOP_STR #undef POP_STR @@ -6425,7 +6200,6 @@ DecompileExpression(JSContext *cx, JSScript *script, JSFunction *fun, jsbytecode switch (JOF_MODE(cs->format)) { case JOF_PROP: case JOF_ELEM: - case JOF_XMLNAME: case 0: { jssrcnote *sn = js_GetSrcNote(cx, script, pc); if (!sn) diff --git a/js/src/jsopcode.h b/js/src/jsopcode.h index 2fcedca50c44..8c8f91ea4dd1 100644 --- a/js/src/jsopcode.h +++ b/js/src/jsopcode.h @@ -64,7 +64,6 @@ typedef enum JSOp { #define JOF_NAME (1U<<5) /* name operation */ #define JOF_PROP (2U<<5) /* obj.prop operation */ #define JOF_ELEM (3U<<5) /* obj[index] operation */ -#define JOF_XMLNAME (4U<<5) /* XML name: *, a::b, @a, @a::b, etc. */ #define JOF_MODEMASK (7U<<5) /* mask for above addressing modes */ #define JOF_SET (1U<<8) /* set (i.e., assignment) operation */ #define JOF_DEL (1U<<9) /* delete operation */ diff --git a/js/src/jsopcode.tbl b/js/src/jsopcode.tbl index ac885d85166d..20bfb1e59628 100644 --- a/js/src/jsopcode.tbl +++ b/js/src/jsopcode.tbl @@ -192,7 +192,7 @@ OPDEF(JSOP_ENDITER, 78, "enditer", NULL, 1, 1, 0, 0, JOF_BYTE) OPDEF(JSOP_FUNAPPLY, 79, "funapply", NULL, 3, -1, 1, 18, JOF_UINT16|JOF_INVOKE|JOF_TYPESET) -/* Push object literal: either an XML object or initialiser object. */ +/* Push object initializer literal. */ OPDEF(JSOP_OBJECT, 80, "object", NULL, 5, 0, 1, 19, JOF_OBJECT) /* Pop value and discard it. */ @@ -339,8 +339,8 @@ OPDEF(JSOP_FINALLY, 135,"finally", NULL, 1, 0, 2, 0, JOF_BYTE) * An "aliased variable" is a var, let, or formal arg that is aliased. Sources * of aliasing include: nested functions accessing the vars of an enclosing * function, function statements that are conditionally executed, 'eval', - * 'with', 'arguments' and E4X filters. All of these cases require creating a - * CallObject to own the aliased variable. + * 'with', and 'arguments'. All of these cases require creating a CallObject to + * own the aliased variable. * * An ALIASEDVAR opcode contains the following immediates: * uint16 hops: the number of scope objects to skip to find the ScopeObject @@ -396,30 +396,29 @@ OPDEF(JSOP_GNAMEDEC, 159,"gnamedec", NULL, 6, 0, 1, 15, JOF_ATOM| /* Regular expression literal requiring special "fork on exec" handling. */ OPDEF(JSOP_REGEXP, 160,"regexp", NULL, 5, 0, 1, 19, JOF_REGEXP) -/* XML (ECMA-357, a.k.a. "E4X") support. */ -OPDEF(JSOP_DEFXMLNS, 161,"defxmlns", NULL, 1, 1, 0, 0, JOF_BYTE) -OPDEF(JSOP_ANYNAME, 162,"anyname", NULL, 1, 0, 1, 19, JOF_BYTE|JOF_XMLNAME) -OPDEF(JSOP_QNAMEPART, 163,"qnamepart", NULL, 5, 0, 1, 19, JOF_ATOM|JOF_XMLNAME) -OPDEF(JSOP_QNAMECONST, 164,"qnameconst", NULL, 5, 1, 1, 19, JOF_ATOM|JOF_XMLNAME) -OPDEF(JSOP_QNAME, 165,"qname", NULL, 1, 2, 1, 0, JOF_BYTE|JOF_XMLNAME) -OPDEF(JSOP_TOATTRNAME, 166,"toattrname", NULL, 1, 1, 1, 19, JOF_BYTE|JOF_XMLNAME) -OPDEF(JSOP_TOATTRVAL, 167,"toattrval", NULL, 1, 1, 1, 19, JOF_BYTE) -OPDEF(JSOP_ADDATTRNAME, 168,"addattrname",NULL, 1, 2, 1, 13, JOF_BYTE) -OPDEF(JSOP_ADDATTRVAL, 169,"addattrval", NULL, 1, 2, 1, 13, JOF_BYTE) -OPDEF(JSOP_BINDXMLNAME, 170,"bindxmlname",NULL, 1, 1, 2, 3, JOF_BYTE|JOF_SET) -OPDEF(JSOP_SETXMLNAME, 171,"setxmlname", NULL, 1, 3, 1, 3, JOF_BYTE|JOF_SET|JOF_DETECTING) -OPDEF(JSOP_XMLNAME, 172,"xmlname", NULL, 1, 1, 1, 19, JOF_BYTE) -OPDEF(JSOP_DESCENDANTS, 173,"descendants",NULL, 1, 2, 1, 18, JOF_BYTE) -OPDEF(JSOP_FILTER, 174,"filter", NULL, 5, 1, 1, 0, JOF_JUMP) -OPDEF(JSOP_ENDFILTER, 175,"endfilter", NULL, 5, 2, 1, 18, JOF_JUMP) -OPDEF(JSOP_TOXML, 176,"toxml", NULL, 1, 1, 1, 19, JOF_BYTE) -OPDEF(JSOP_TOXMLLIST, 177,"toxmllist", NULL, 1, 1, 1, 19, JOF_BYTE) -OPDEF(JSOP_XMLTAGEXPR, 178,"xmltagexpr", NULL, 1, 1, 1, 0, JOF_BYTE) -OPDEF(JSOP_XMLELTEXPR, 179,"xmleltexpr", NULL, 1, 1, 1, 0, JOF_BYTE) -OPDEF(JSOP_XMLCDATA, 180,"xmlcdata", NULL, 5, 0, 1, 19, JOF_ATOM) -OPDEF(JSOP_XMLCOMMENT, 181,"xmlcomment", NULL, 5, 0, 1, 19, JOF_ATOM) -OPDEF(JSOP_XMLPI, 182,"xmlpi", NULL, 5, 1, 1, 19, JOF_ATOM) -OPDEF(JSOP_DELDESC, 183,"deldesc", NULL, 1, 2, 1, 15, JOF_BYTE|JOF_ELEM|JOF_DEL) +OPDEF(JSOP_UNUSED161, 161,"unused161", NULL, 1, 0, 0, 0, JOF_BYTE) +OPDEF(JSOP_UNUSED162, 162,"unused162", NULL, 1, 0, 0, 0, JOF_BYTE) +OPDEF(JSOP_UNUSED163, 163,"unused163", NULL, 1, 0, 0, 0, JOF_BYTE) +OPDEF(JSOP_UNUSED164, 164,"unused164", NULL, 1, 0, 0, 0, JOF_BYTE) +OPDEF(JSOP_UNUSED165, 165,"unused165", NULL, 1, 0, 0, 0, JOF_BYTE) +OPDEF(JSOP_UNUSED166, 166,"unused166", NULL, 1, 0, 0, 0, JOF_BYTE) +OPDEF(JSOP_UNUSED167, 167,"unused167", NULL, 1, 0, 0, 0, JOF_BYTE) +OPDEF(JSOP_UNUSED168, 168,"unused168", NULL, 1, 0, 0, 0, JOF_BYTE) +OPDEF(JSOP_UNUSED169, 169,"unused169", NULL, 1, 0, 0, 0, JOF_BYTE) +OPDEF(JSOP_UNUSED170, 170,"unused170", NULL, 1, 0, 0, 0, JOF_BYTE) +OPDEF(JSOP_UNUSED171, 171,"unused171", NULL, 1, 0, 0, 0, JOF_BYTE) +OPDEF(JSOP_UNUSED172, 172,"unused172", NULL, 1, 0, 0, 0, JOF_BYTE) +OPDEF(JSOP_UNUSED173, 173,"unused173", NULL, 1, 0, 0, 0, JOF_BYTE) +OPDEF(JSOP_UNUSED174, 174,"unused174", NULL, 1, 0, 0, 0, JOF_BYTE) +OPDEF(JSOP_UNUSED175, 175,"unused175", NULL, 1, 0, 0, 0, JOF_BYTE) +OPDEF(JSOP_UNUSED176, 176,"unused176", NULL, 1, 0, 0, 0, JOF_BYTE) +OPDEF(JSOP_UNUSED177, 177,"unused177", NULL, 1, 0, 0, 0, JOF_BYTE) +OPDEF(JSOP_UNUSED178, 178,"unused178", NULL, 1, 0, 0, 0, JOF_BYTE) +OPDEF(JSOP_UNUSED179, 179,"unused179", NULL, 1, 0, 0, 0, JOF_BYTE) +OPDEF(JSOP_UNUSED180, 180,"unused180", NULL, 1, 0, 0, 0, JOF_BYTE) +OPDEF(JSOP_UNUSED181, 181,"unused181", NULL, 1, 0, 0, 0, JOF_BYTE) +OPDEF(JSOP_UNUSED182, 182,"unused182", NULL, 1, 0, 0, 0, JOF_BYTE) +OPDEF(JSOP_UNUSED183, 183,"unused183", NULL, 1, 0, 0, 0, JOF_BYTE) OPDEF(JSOP_CALLPROP, 184,"callprop", NULL, 5, 1, 1, 18, JOF_ATOM|JOF_PROP|JOF_TYPESET|JOF_TMPSLOT3) @@ -437,12 +436,8 @@ OPDEF(JSOP_UINT24, 187,"uint24", NULL, 4, 0, 1, 16, JOF_UINT24 OPDEF(JSOP_UNUSED188, 188,"unused188", NULL, 1, 0, 0, 0, JOF_BYTE) OPDEF(JSOP_UNUSED189, 189,"unused189", NULL, 1, 0, 0, 0, JOF_BYTE) OPDEF(JSOP_UNUSED190, 190,"unused190", NULL, 1, 0, 0, 0, JOF_BYTE) - -/* - * Opcodes to help the decompiler deal with XML. - */ -OPDEF(JSOP_STARTXML, 191,"startxml", NULL, 1, 0, 0, 0, JOF_BYTE) -OPDEF(JSOP_STARTXMLEXPR, 192,"startxmlexpr",NULL, 1, 0, 0, 0, JOF_BYTE) +OPDEF(JSOP_UNUSED191, 191,"unused191", NULL, 1, 0, 0, 0, JOF_BYTE) +OPDEF(JSOP_UNUSED192, 192,"unused192", NULL, 1, 0, 0, 0, JOF_BYTE) OPDEF(JSOP_CALLELEM, 193, "callelem", NULL, 1, 2, 1, 18, JOF_BYTE |JOF_ELEM|JOF_TYPESET|JOF_LEFTASSOC) @@ -458,7 +453,7 @@ OPDEF(JSOP_STOP, 194,"stop", NULL, 1, 0, 0, 0, JOF_BYTE) */ OPDEF(JSOP_GETXPROP, 195,"getxprop", NULL, 5, 1, 1, 18, JOF_ATOM|JOF_PROP|JOF_TYPESET) -OPDEF(JSOP_CALLXMLNAME, 196, "callxmlname", NULL, 1, 1, 2, 19, JOF_BYTE) +OPDEF(JSOP_UNUSED196, 196,"unused196", NULL, 1, 0, 0, 0, JOF_BYTE) /* * Specialized JSOP_TYPEOF to avoid reporting undefined for typeof(0, undef). diff --git a/js/src/jspropertytree.cpp b/js/src/jspropertytree.cpp index ca9a0da994f1..5b52307f319b 100644 --- a/js/src/jspropertytree.cpp +++ b/js/src/jspropertytree.cpp @@ -259,8 +259,6 @@ Shape::dump(JSContext *cx, FILE *fp) const if (JSID_IS_INT(propid)) { fprintf(fp, "[%ld]", (long) JSID_TO_INT(propid)); - } else if (JSID_IS_DEFAULT_XML_NAMESPACE(propid)) { - fprintf(fp, ""); } else { JSLinearString *str; if (JSID_IS_ATOM(propid)) { diff --git a/js/src/jsprototypes.h b/js/src/jsprototypes.h index 1abbc831a929..27f5c84450b1 100644 --- a/js/src/jsprototypes.h +++ b/js/src/jsprototypes.h @@ -30,36 +30,32 @@ macro(Number, 8, js_InitNumberClass) \ macro(String, 9, js_InitStringClass) \ macro(RegExp, 10, js_InitRegExpClass) \ - macro(XML, 11, js_InitXMLClass) \ - macro(Namespace, 12, js_InitNamespaceClass) \ - macro(QName, 13, js_InitQNameClass) \ - macro(Error, 14, js_InitExceptionClasses) \ - macro(InternalError, 15, js_InitExceptionClasses) \ - macro(EvalError, 16, js_InitExceptionClasses) \ - macro(RangeError, 17, js_InitExceptionClasses) \ - macro(ReferenceError, 18, js_InitExceptionClasses) \ - macro(SyntaxError, 19, js_InitExceptionClasses) \ - macro(TypeError, 20, js_InitExceptionClasses) \ - macro(URIError, 21, js_InitExceptionClasses) \ - macro(Iterator, 22, js_InitIteratorClasses) \ - macro(StopIteration, 23, js_InitIteratorClasses) \ - macro(ArrayBuffer, 24, js_InitTypedArrayClasses) \ - macro(Int8Array, 25, js_InitTypedArrayClasses) \ - macro(Uint8Array, 26, js_InitTypedArrayClasses) \ - macro(Int16Array, 27, js_InitTypedArrayClasses) \ - macro(Uint16Array, 28, js_InitTypedArrayClasses) \ - macro(Int32Array, 29, js_InitTypedArrayClasses) \ - macro(Uint32Array, 30, js_InitTypedArrayClasses) \ - macro(Float32Array, 31, js_InitTypedArrayClasses) \ - macro(Float64Array, 32, js_InitTypedArrayClasses) \ - macro(Uint8ClampedArray, 33, js_InitTypedArrayClasses) \ - macro(Proxy, 34, js_InitProxyClass) \ - macro(AnyName, 35, js_InitNullClass) \ - macro(WeakMap, 36, js_InitWeakMapClass) \ - macro(Map, 37, js_InitMapClass) \ - macro(Set, 38, js_InitSetClass) \ - macro(DataView, 39, js_InitTypedArrayClasses) \ - macro(ParallelArray, 40, js_InitParallelArrayClass) \ - macro(Intl, 41, js_InitIntlClass) \ + macro(Error, 11, js_InitExceptionClasses) \ + macro(InternalError, 12, js_InitExceptionClasses) \ + macro(EvalError, 13, js_InitExceptionClasses) \ + macro(RangeError, 14, js_InitExceptionClasses) \ + macro(ReferenceError, 15, js_InitExceptionClasses) \ + macro(SyntaxError, 16, js_InitExceptionClasses) \ + macro(TypeError, 17, js_InitExceptionClasses) \ + macro(URIError, 18, js_InitExceptionClasses) \ + macro(Iterator, 19, js_InitIteratorClasses) \ + macro(StopIteration, 20, js_InitIteratorClasses) \ + macro(ArrayBuffer, 21, js_InitTypedArrayClasses) \ + macro(Int8Array, 22, js_InitTypedArrayClasses) \ + macro(Uint8Array, 23, js_InitTypedArrayClasses) \ + macro(Int16Array, 24, js_InitTypedArrayClasses) \ + macro(Uint16Array, 25, js_InitTypedArrayClasses) \ + macro(Int32Array, 26, js_InitTypedArrayClasses) \ + macro(Uint32Array, 27, js_InitTypedArrayClasses) \ + macro(Float32Array, 28, js_InitTypedArrayClasses) \ + macro(Float64Array, 29, js_InitTypedArrayClasses) \ + macro(Uint8ClampedArray, 30, js_InitTypedArrayClasses) \ + macro(Proxy, 31, js_InitProxyClass) \ + macro(WeakMap, 32, js_InitWeakMapClass) \ + macro(Map, 33, js_InitMapClass) \ + macro(Set, 34, js_InitSetClass) \ + macro(DataView, 35, js_InitTypedArrayClasses) \ + macro(ParallelArray, 36, js_InitParallelArrayClass) \ + macro(Intl, 37, js_InitIntlClass) \ #endif /* jsprototypes_h___ */ diff --git a/js/src/jsprvtd.h b/js/src/jsprvtd.h index 44aa9c02beec..6d9a2061f549 100644 --- a/js/src/jsprvtd.h +++ b/js/src/jsprvtd.h @@ -58,10 +58,6 @@ typedef struct JSStackHeader JSStackHeader; typedef struct JSSubString JSSubString; typedef struct JSSpecializedNative JSSpecializedNative; -#if JS_HAS_XML_SUPPORT -typedef struct JSXML JSXML; -#endif - /* * Template declarations. * diff --git a/js/src/jspubtd.h b/js/src/jspubtd.h index 16b9f1a1a575..621fe2f5cd0b 100644 --- a/js/src/jspubtd.h +++ b/js/src/jspubtd.h @@ -91,7 +91,6 @@ typedef enum JSType { JSTYPE_NUMBER, /* number */ JSTYPE_BOOLEAN, /* boolean */ JSTYPE_NULL, /* null */ - JSTYPE_XML, /* xml object */ JSTYPE_LIMIT } JSType; @@ -154,9 +153,6 @@ typedef enum { * implements JSTraceCallback. */ JSTRACE_IONCODE, -#if JS_HAS_XML_SUPPORT - JSTRACE_XML, -#endif JSTRACE_SHAPE, JSTRACE_BASE_SHAPE, JSTRACE_TYPE_OBJECT, @@ -227,7 +223,6 @@ enum ThingRootKind THING_ROOT_TYPE_OBJECT, THING_ROOT_STRING, THING_ROOT_SCRIPT, - THING_ROOT_XML, THING_ROOT_ID, THING_ROOT_PROPERTY_ID, THING_ROOT_VALUE, diff --git a/js/src/jsreflect.cpp b/js/src/jsreflect.cpp index b016bc333765..f9d2510d914c 100644 --- a/js/src/jsreflect.cpp +++ b/js/src/jsreflect.cpp @@ -75,7 +75,6 @@ char const *js::binopNames[] = { "&", /* BINOP_BITAND */ "in", /* BINOP_IN */ "instanceof", /* BINOP_INSTANCEOF */ - "..", /* BINOP_DBLDOT */ }; char const *js::unopNames[] = { @@ -612,52 +611,6 @@ class NodeBuilder bool objectPattern(NodeVector &elts, TokenPos *pos, MutableHandleValue dst); bool propertyPattern(HandleValue key, HandleValue patt, TokenPos *pos, MutableHandleValue dst); - - /* - * xml - */ - - bool xmlAnyName(TokenPos *pos, MutableHandleValue dst); - - bool xmlEscapeExpression(HandleValue expr, TokenPos *pos, MutableHandleValue dst); - - bool xmlDefaultNamespace(HandleValue ns, TokenPos *pos, MutableHandleValue dst); - - bool xmlFilterExpression(HandleValue left, HandleValue right, TokenPos *pos, - MutableHandleValue dst); - - bool xmlAttributeSelector(HandleValue expr, bool computed, TokenPos *pos, - MutableHandleValue dst); - - bool xmlQualifiedIdentifier(HandleValue left, HandleValue right, bool computed, TokenPos *pos, - MutableHandleValue dst); - - bool xmlFunctionQualifiedIdentifier(HandleValue right, bool computed, TokenPos *pos, - MutableHandleValue dst); - - bool xmlElement(NodeVector &elts, TokenPos *pos, MutableHandleValue dst); - - bool xmlText(HandleValue text, TokenPos *pos, MutableHandleValue dst); - - bool xmlList(NodeVector &elts, TokenPos *pos, MutableHandleValue dst); - - bool xmlStartTag(NodeVector &elts, TokenPos *pos, MutableHandleValue dst); - - bool xmlEndTag(NodeVector &elts, TokenPos *pos, MutableHandleValue dst); - - bool xmlPointTag(NodeVector &elts, TokenPos *pos, MutableHandleValue dst); - - bool xmlName(HandleValue text, TokenPos *pos, MutableHandleValue dst); - - bool xmlName(NodeVector &elts, TokenPos *pos, MutableHandleValue dst); - - bool xmlAttribute(HandleValue text, TokenPos *pos, MutableHandleValue dst); - - bool xmlCdata(HandleValue text, TokenPos *pos, MutableHandleValue dst); - - bool xmlComment(HandleValue text, TokenPos *pos, MutableHandleValue dst); - - bool xmlPI(HandleValue target, HandleValue content, TokenPos *pos, MutableHandleValue dst); }; bool @@ -1497,195 +1450,6 @@ NodeBuilder::function(ASTType type, TokenPos *pos, dst); } -bool -NodeBuilder::xmlAnyName(TokenPos *pos, MutableHandleValue dst) -{ - RootedValue cb(cx, callbacks[AST_XMLANYNAME]); - if (!cb.isNull()) - return callback(cb, pos, dst); - - return newNode(AST_XMLANYNAME, pos, dst); -} - -bool -NodeBuilder::xmlEscapeExpression(HandleValue expr, TokenPos *pos, MutableHandleValue dst) -{ - RootedValue cb(cx, callbacks[AST_XMLESCAPE]); - if (!cb.isNull()) - return callback(cb, expr, pos, dst); - - return newNode(AST_XMLESCAPE, pos, "expression", expr, dst); -} - -bool -NodeBuilder::xmlFilterExpression(HandleValue left, HandleValue right, TokenPos *pos, - MutableHandleValue dst) -{ - RootedValue cb(cx, callbacks[AST_XMLFILTER]); - if (!cb.isNull()) - return callback(cb, left, right, pos, dst); - - return newNode(AST_XMLFILTER, pos, "left", left, "right", right, dst); -} - -bool -NodeBuilder::xmlDefaultNamespace(HandleValue ns, TokenPos *pos, MutableHandleValue dst) -{ - RootedValue cb(cx, callbacks[AST_XMLDEFAULT]); - if (!cb.isNull()) - return callback(cb, ns, pos, dst); - - return newNode(AST_XMLDEFAULT, pos, "namespace", ns, dst); -} - -bool -NodeBuilder::xmlAttributeSelector(HandleValue expr, bool computed, TokenPos *pos, - MutableHandleValue dst) -{ - RootedValue computedVal(cx, BooleanValue(computed)); - - RootedValue cb(cx, callbacks[AST_XMLATTR_SEL]); - if (!cb.isNull()) - return callback(cb, expr, computedVal, pos, dst); - - return newNode(AST_XMLATTR_SEL, pos, - "attribute", expr, - "computed", computedVal, - dst); -} - -bool -NodeBuilder::xmlFunctionQualifiedIdentifier(HandleValue right, bool computed, TokenPos *pos, - MutableHandleValue dst) -{ - RootedValue computedVal(cx, BooleanValue(computed)); - - RootedValue cb(cx, callbacks[AST_XMLFUNCQUAL]); - if (!cb.isNull()) - return callback(cb, right, computedVal, pos, dst); - - return newNode(AST_XMLFUNCQUAL, pos, - "right", right, - "computed", computedVal, - dst); -} - -bool -NodeBuilder::xmlQualifiedIdentifier(HandleValue left, HandleValue right, bool computed, - TokenPos *pos, MutableHandleValue dst) -{ - RootedValue computedVal(cx, BooleanValue(computed)); - - RootedValue cb(cx, callbacks[AST_XMLQUAL]); - if (!cb.isNull()) - return callback(cb, left, right, computedVal, pos, dst); - - return newNode(AST_XMLQUAL, pos, - "left", left, - "right", right, - "computed", computedVal, - dst); -} - -bool -NodeBuilder::xmlElement(NodeVector &elts, TokenPos *pos, MutableHandleValue dst) -{ - return listNode(AST_XMLELEM, "contents", elts, pos, dst); -} - -bool -NodeBuilder::xmlText(HandleValue text, TokenPos *pos, MutableHandleValue dst) -{ - RootedValue cb(cx, callbacks[AST_XMLTEXT]); - if (!cb.isNull()) - return callback(cb, text, pos, dst); - - return newNode(AST_XMLTEXT, pos, "text", text, dst); -} - -bool -NodeBuilder::xmlList(NodeVector &elts, TokenPos *pos, MutableHandleValue dst) -{ - return listNode(AST_XMLLIST, "contents", elts, pos, dst); -} - -bool -NodeBuilder::xmlStartTag(NodeVector &elts, TokenPos *pos, MutableHandleValue dst) -{ - return listNode(AST_XMLSTART, "contents", elts, pos, dst); -} - -bool -NodeBuilder::xmlEndTag(NodeVector &elts, TokenPos *pos, MutableHandleValue dst) -{ - return listNode(AST_XMLEND, "contents", elts, pos, dst); -} - -bool -NodeBuilder::xmlPointTag(NodeVector &elts, TokenPos *pos, MutableHandleValue dst) -{ - return listNode(AST_XMLPOINT, "contents", elts, pos, dst); -} - -bool -NodeBuilder::xmlName(HandleValue text, TokenPos *pos, MutableHandleValue dst) -{ - RootedValue cb(cx, callbacks[AST_XMLNAME]); - if (!cb.isNull()) - return callback(cb, text, pos, dst); - - return newNode(AST_XMLNAME, pos, "contents", text, dst); -} - -bool -NodeBuilder::xmlName(NodeVector &elts, TokenPos *pos, MutableHandleValue dst) -{ - return listNode(AST_XMLNAME, "contents", elts, pos, dst); -} - -bool -NodeBuilder::xmlAttribute(HandleValue text, TokenPos *pos, MutableHandleValue dst) -{ - RootedValue cb(cx, callbacks[AST_XMLATTR]); - if (!cb.isNull()) - return callback(cb, text, pos, dst); - - return newNode(AST_XMLATTR, pos, "value", text, dst); -} - -bool -NodeBuilder::xmlCdata(HandleValue text, TokenPos *pos, MutableHandleValue dst) -{ - RootedValue cb(cx, callbacks[AST_XMLCDATA]); - if (!cb.isNull()) - return callback(cb, text, pos, dst); - - return newNode(AST_XMLCDATA, pos, "contents", text, dst); -} - -bool -NodeBuilder::xmlComment(HandleValue text, TokenPos *pos, MutableHandleValue dst) -{ - RootedValue cb(cx, callbacks[AST_XMLCOMMENT]); - if (!cb.isNull()) - return callback(cb, text, pos, dst); - - return newNode(AST_XMLCOMMENT, pos, "contents", text, dst); -} - -bool -NodeBuilder::xmlPI(HandleValue target, HandleValue contents, TokenPos *pos, MutableHandleValue dst) -{ - RootedValue cb(cx, callbacks[AST_XMLPI]); - if (!cb.isNull()) - return callback(cb, target, contents, pos, dst); - - return newNode(AST_XMLPI, pos, - "target", target, - "contents", contents, - dst); -} - /* * Serialization of parse nodes to JavaScript objects. * @@ -1708,7 +1472,6 @@ class ASTSerializer bool statements(ParseNode *pn, NodeVector &elts); bool expressions(ParseNode *pn, NodeVector &elts); - bool xmls(ParseNode *pn, NodeVector &elts); bool leftAssociate(ParseNode *pn, MutableHandleValue dst); bool functionArgs(ParseNode *pn, ParseNode *pnargs, ParseNode *pndestruct, ParseNode *pnbody, NodeVector &args, NodeVector &defaults, MutableHandleValue rest); @@ -1776,8 +1539,6 @@ class ASTSerializer bool comprehension(ParseNode *pn, MutableHandleValue dst); bool generatorExpression(ParseNode *pn, MutableHandleValue dst); - bool xml(ParseNode *pn, MutableHandleValue dst); - public: ASTSerializer(JSContext *c, bool l, char const *src, uint32_t ln) : cx(c) @@ -1902,8 +1663,6 @@ ASTSerializer::binop(ParseNodeKind kind, JSOp op) return BINOP_IN; case PNK_INSTANCEOF: return BINOP_INSTANCEOF; - case PNK_DBLDOT: - return BINOP_DBLDOT; default: return BINOP_ERR; } @@ -1948,24 +1707,6 @@ ASTSerializer::expressions(ParseNode *pn, NodeVector &elts) return true; } -bool -ASTSerializer::xmls(ParseNode *pn, NodeVector &elts) -{ - if (!elts.reserve(pn->pn_count)) - return false; - - for (ParseNode *next = pn->pn_head; next; next = next->pn_next) { - JS_ASSERT(pn->pn_pos.encloses(next->pn_pos)); - - RootedValue elt(cx); - if (!xml(next, &elt)) - return false; - elts.infallibleAppend(elt); - } - - return true; -} - bool ASTSerializer::blockStatement(ParseNode *pn, MutableHandleValue dst) { @@ -2420,20 +2161,6 @@ ASTSerializer::statement(ParseNode *pn, MutableHandleValue dst) case PNK_DEBUGGER: return builder.debuggerStatement(&pn->pn_pos, dst); -#if JS_HAS_XML_SUPPORT - case PNK_DEFXMLNS: - { - JS_ASSERT(pn->pn_pos.encloses(pn->pn_kid->pn_pos)); - - LOCAL_ASSERT(pn->isArity(PN_UNARY)); - - RootedValue ns(cx); - - return expression(pn->pn_kid, &ns) && - builder.xmlDefaultNamespace(ns, &pn->pn_pos, dst); - } -#endif - case PNK_NOP: return builder.emptyStatement(&pn->pn_pos, dst); @@ -2677,7 +2404,6 @@ ASTSerializer::expression(ParseNode *pn, MutableHandleValue dst) case PNK_BITAND: case PNK_IN: case PNK_INSTANCEOF: - case PNK_DBLDOT: if (pn->isArity(PN_BINARY)) { JS_ASSERT(pn->pn_pos.encloses(pn->pn_left->pn_pos)); JS_ASSERT(pn->pn_pos.encloses(pn->pn_right->pn_pos)); @@ -2852,189 +2578,8 @@ ASTSerializer::expression(ParseNode *pn, MutableHandleValue dst) case PNK_LET: return let(pn, true, dst); -#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); - - case PNK_DBLCOLON: - { - RootedValue right(cx); - - LOCAL_ASSERT(pn->isArity(PN_NAME) || pn->isArity(PN_BINARY)); - - ParseNode *pnleft; - bool computed; - - if (pn->isArity(PN_BINARY)) { - JS_ASSERT(pn->pn_pos.encloses(pn->pn_left->pn_pos)); - JS_ASSERT(pn->pn_pos.encloses(pn->pn_right->pn_pos)); - - computed = true; - pnleft = pn->pn_left; - if (!expression(pn->pn_right, &right)) - return false; - } else { - JS_ASSERT(pn->isArity(PN_NAME)); - JS_ASSERT(pn->pn_pos.encloses(pn->pn_expr->pn_pos)); - - computed = false; - pnleft = pn->pn_expr; - RootedAtom pnAtom(cx, pn->pn_atom); - if (!identifier(pnAtom, NULL, &right)) - return false; - } - - if (pnleft->isKind(PNK_FUNCTIONNS)) - return builder.xmlFunctionQualifiedIdentifier(right, computed, &pn->pn_pos, dst); - - RootedValue left(cx); - return expression(pnleft, &left) && - builder.xmlQualifiedIdentifier(left, right, computed, &pn->pn_pos, dst); - } - - case PNK_AT: - { - JS_ASSERT(pn->pn_pos.encloses(pn->pn_kid->pn_pos)); - - RootedValue expr(cx); - ParseNode *kid = pn->pn_kid; - bool computed = ((!kid->isKind(PNK_NAME) || !kid->isOp(JSOP_QNAMEPART)) && - !kid->isKind(PNK_DBLCOLON) && - !kid->isKind(PNK_ANYNAME)); - return expression(kid, &expr) && - builder.xmlAttributeSelector(expr, computed, &pn->pn_pos, dst); - } - - case PNK_FILTER: - { - JS_ASSERT(pn->pn_pos.encloses(pn->pn_left->pn_pos)); - JS_ASSERT(pn->pn_pos.encloses(pn->pn_right->pn_pos)); - - RootedValue left(cx), right(cx); - return expression(pn->pn_left, &left) && - expression(pn->pn_right, &right) && - builder.xmlFilterExpression(left, right, &pn->pn_pos, dst); - } - - default: - return xml(pn, dst); - -#else default: LOCAL_NOT_REACHED("unexpected expression type"); -#endif - } -} - -bool -ASTSerializer::xml(ParseNode *pn, MutableHandleValue dst) -{ - JS_CHECK_RECURSION(cx, return false); - switch (pn->getKind()) { -#if JS_HAS_XML_SUPPORT - case PNK_XMLCURLYEXPR: - { - JS_ASSERT(pn->pn_pos.encloses(pn->pn_kid->pn_pos)); - - RootedValue expr(cx); - return expression(pn->pn_kid, &expr) && - builder.xmlEscapeExpression(expr, &pn->pn_pos, dst); - } - - case PNK_XMLELEM: - { - NodeVector elts(cx); - if (!xmls(pn, elts)) - return false; - return builder.xmlElement(elts, &pn->pn_pos, dst); - } - - case PNK_XMLLIST: - { - NodeVector elts(cx); - if (!xmls(pn, elts)) - return false; - return builder.xmlList(elts, &pn->pn_pos, dst); - } - - case PNK_XMLSTAGO: - { - NodeVector elts(cx); - if (!xmls(pn, elts)) - return false; - return builder.xmlStartTag(elts, &pn->pn_pos, dst); - } - - case PNK_XMLETAGO: - { - NodeVector elts(cx); - if (!xmls(pn, elts)) - return false; - return builder.xmlEndTag(elts, &pn->pn_pos, dst); - } - - case PNK_XMLPTAGC: - { - NodeVector elts(cx); - if (!xmls(pn, elts)) - return false; - return builder.xmlPointTag(elts, &pn->pn_pos, dst); - } - - case PNK_XMLTEXT: - case PNK_XMLSPACE: { - RootedValue atomContentsVal(cx, unrootedAtomContents(pn->pn_atom)); - return builder.xmlText(atomContentsVal, &pn->pn_pos, dst); - } - - case PNK_XMLNAME: - if (pn->isArity(PN_NULLARY)) { - RootedValue atomContentsVal(cx, unrootedAtomContents(pn->pn_atom)); - return builder.xmlName(atomContentsVal, &pn->pn_pos, dst); - } - - LOCAL_ASSERT(pn->isArity(PN_LIST)); - - { - NodeVector elts(cx); - return xmls(pn, elts) && - builder.xmlName(elts, &pn->pn_pos, dst); - } - - case PNK_XMLATTR: { - RootedValue atomContentsVal(cx, unrootedAtomContents(pn->pn_atom)); - return builder.xmlAttribute(atomContentsVal, &pn->pn_pos, dst); - } - - case PNK_XMLCDATA: { - RootedValue atomContentsVal(cx, unrootedAtomContents(pn->pn_atom)); - return builder.xmlCdata(atomContentsVal, &pn->pn_pos, dst); - } - - case PNK_XMLCOMMENT: { - RootedValue atomContentsVal(cx, unrootedAtomContents(pn->pn_atom)); - return builder.xmlComment(atomContentsVal, &pn->pn_pos, dst); - } - - case PNK_XMLPI: { - XMLProcessingInstruction &pi = pn->as(); - RootedValue targetAtomContentsVal(cx, unrootedAtomContents(pi.target())); - RootedValue dataAtomContentsVal(cx, unrootedAtomContents(pi.data())); - return builder.xmlPI(targetAtomContentsVal, - dataAtomContentsVal, - &pi.pn_pos, - dst); - } -#endif - - default: - LOCAL_NOT_REACHED("unexpected XML node type"); } } diff --git a/js/src/jsreflect.h b/js/src/jsreflect.h index 4cd7519bc32b..b517c1bc4d90 100644 --- a/js/src/jsreflect.h +++ b/js/src/jsreflect.h @@ -54,8 +54,6 @@ enum BinaryOperator { BINOP_BITOR, BINOP_BITXOR, BINOP_BITAND, /* misc */ BINOP_IN, BINOP_INSTANCEOF, - /* xml */ - BINOP_DBLDOT, BINOP_LIMIT }; diff --git a/js/src/jswrapper.cpp b/js/src/jswrapper.cpp index 774a543ba6bb..d15adae17548 100644 --- a/js/src/jswrapper.cpp +++ b/js/src/jswrapper.cpp @@ -45,13 +45,6 @@ Wrapper::New(JSContext *cx, JSObject *obj, JSObject *proto, JSObject *parent, AutoMarkInDeadCompartment amd(cx->compartment); -#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); } @@ -59,14 +52,6 @@ Wrapper::New(JSContext *cx, JSObject *obj, JSObject *proto, JSObject *parent, JSObject * Wrapper::Renew(JSContext *cx, JSObject *existing, JSObject *obj, Wrapper *handler) { -#if JS_HAS_XML_SUPPORT - if (obj->isXML()) { - JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, - JSMSG_CANT_WRAP_XML_OBJECT); - return NULL; - } -#endif - JS_ASSERT(!obj->isCallable()); return RenewProxyObject(cx, existing, handler, ObjectValue(*obj)); } diff --git a/js/src/jsxml.cpp b/js/src/jsxml.cpp deleted file mode 100644 index 61460db5de4a..000000000000 --- a/js/src/jsxml.cpp +++ /dev/null @@ -1,8032 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * vim: set ts=4 sw=4 et tw=78: - * - * 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 -#include "jsversion.h" - -size_t sE4XObjectsCreated = 0; - -#if JS_HAS_XML_SUPPORT - -#include -#include -#include - -#include "mozilla/Util.h" - -#include "jstypes.h" -#include "jsprf.h" -#include "jsutil.h" -#include "jsapi.h" -#include "jsarray.h" -#include "jsatom.h" -#include "jsbool.h" -#include "jscntxt.h" -#include "jsfun.h" -#include "jsgc.h" -#include "jslock.h" -#include "jsnum.h" -#include "jsobj.h" -#include "jsopcode.h" -#include "jsscript.h" -#include "jsstr.h" -#include "jsxml.h" - -#include "frontend/Parser.h" -#include "frontend/TokenStream.h" -#include "gc/Marking.h" -#include "vm/GlobalObject.h" -#include "vm/Shape.h" -#include "vm/StringBuffer.h" - -#include "jsatominlines.h" -#include "jsinferinlines.h" -#include "jsobjinlines.h" - -#include "vm/Stack-inl.h" -#include "vm/String-inl.h" - -#ifdef DEBUG -#include /* for #ifdef DEBUG memset calls */ -#endif - -using namespace js; -using namespace js::gc; -using namespace js::types; -using namespace js::frontend; - -using mozilla::ArrayLength; - -template -struct IdentityOp -{ - typedef JSBool (* compare)(const T *a, const U *b); -}; - -template -static JSBool -pointer_match(const T *a, const T *b) -{ - return a == b; -} - -/* - * NOTES - * - in the js shell, you must use the -x command line option, or call - * options('xml') before compiling anything that uses XML literals - * - * TODO - * - XXXbe patrol - * - Fuse objects and their JSXML* private data into single GC-things - * - fix function::foo vs. x.(foo == 42) collision using proper namespacing - */ - -/* - * Random utilities and global functions. - */ -const char js_AttributeName_str[] = "AttributeName"; -const char js_localName_str[] = "localName"; -const char js_xml_parent_str[] = "parent"; -const char js_prefix_str[] = "prefix"; -const char js_toXMLString_str[] = "toXMLString"; -const char js_uri_str[] = "uri"; - -const char js_amp_entity_str[] = "&"; -const char js_gt_entity_str[] = ">"; -const char js_lt_entity_str[] = "<"; -const char js_quot_entity_str[] = """; -const char js_leftcurly_entity_str[] = "{"; - -#define IS_STAR(str) ((str)->length() == 1 && *(str)->chars() == '*') - -static JSBool -GetXMLFunction(JSContext *cx, HandleObject obj, HandleId id, MutableHandleValue vp); - -static JSBool -IsDeclared(const JSObject *obj) -{ - jsval v; - - JS_ASSERT(obj->getClass() == &NamespaceClass); - v = obj->getNamespaceDeclared(); - JS_ASSERT(JSVAL_IS_VOID(v) || v == JSVAL_TRUE); - return v == JSVAL_TRUE; -} - -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; -} - -/* - * 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) -{ - if (!cx->runningWithTrustedPrincipals()) - ++sE4XObjectsCreated; - - return NewBuiltinClassInstance(cx, clasp); -} - -#define DEFINE_GETTER(name,code) \ - static JSBool \ - name(JSContext *cx, HandleObject obj, HandleId id, MutableHandleValue vp) \ - { \ - code; \ - return true; \ - } - -/* - * Namespace class and library functions. - */ -DEFINE_GETTER(NamePrefix_getter, - if (obj->getClass() == &NamespaceClass) vp.set(obj->getNamePrefixVal())) -DEFINE_GETTER(NameURI_getter, - if (obj->getClass() == &NamespaceClass) vp.set(obj->getNameURIVal())) - -static JSBool -namespace_equality(JSContext *cx, HandleObject obj, HandleValue v, JSBool *bp) -{ - JSObject *obj2; - - JS_ASSERT(v.isObjectOrNull()); - obj2 = v.toObjectOrNull(); - *bp = (!obj2 || obj2->getClass() != &NamespaceClass) - ? JS_FALSE - : EqualStrings(obj->getNameURI(), obj2->getNameURI()); - return JS_TRUE; -} - -JS_FRIEND_DATA(Class) js::NamespaceClass = { - "Namespace", - JSCLASS_HAS_RESERVED_SLOTS(JSObject::NAMESPACE_CLASS_RESERVED_SLOTS) | - JSCLASS_HAS_CACHED_PROTO(JSProto_Namespace), - JS_PropertyStub, /* addProperty */ - JS_PropertyStub, /* delProperty */ - JS_PropertyStub, /* getProperty */ - JS_StrictPropertyStub, /* setProperty */ - JS_EnumerateStub, - JS_ResolveStub, - JS_ConvertStub, - NULL, /* finalize */ - NULL, /* checkAccess */ - NULL, /* call */ - NULL, /* construct */ - NULL, /* hasInstance */ - NULL, /* trace */ - { - namespace_equality, - NULL, /* outerObject */ - NULL, /* innerObject */ - NULL, /* iteratorObject */ - NULL, /* wrappedObject */ - } -}; - -#define NAMESPACE_ATTRS \ - (JSPROP_ENUMERATE | JSPROP_READONLY | JSPROP_PERMANENT | JSPROP_SHARED) - -static JSPropertySpec namespace_props[] = { - {js_prefix_str, 0, NAMESPACE_ATTRS, JSOP_WRAPPER(NamePrefix_getter), JSOP_NULLWRAPPER}, - {js_uri_str, 0, NAMESPACE_ATTRS, JSOP_WRAPPER(NameURI_getter), JSOP_NULLWRAPPER}, - {0,0,0,JSOP_NULLWRAPPER, JSOP_NULLWRAPPER} -}; - -static JSBool -namespace_toString(JSContext *cx, unsigned argc, Value *vp) -{ - JSObject *obj = ToObject(cx, HandleValue::fromMarkedLocation(&vp[1])); - if (!obj) - return JS_FALSE; - if (!obj->isNamespace()) { - ReportIncompatibleMethod(cx, CallReceiverFromVp(vp), &NamespaceClass); - return JS_FALSE; - } - *vp = obj->getNameURIVal(); - return JS_TRUE; -} - -static JSFunctionSpec namespace_methods[] = { - JS_FN(js_toString_str, namespace_toString, 0,0), - JS_FS_END -}; - -static JSObject * -NewXMLNamespace(JSContext *cx, JSLinearString *prefix, JSLinearString *uri, JSBool declared) -{ - RootedObject obj(cx, NewBuiltinClassInstanceXML(cx, &NamespaceClass)); - if (!obj) - return NULL; - - JS_ASSERT(JSVAL_IS_VOID(obj->getNamePrefixVal())); - JS_ASSERT(JSVAL_IS_VOID(obj->getNameURIVal())); - JS_ASSERT(JSVAL_IS_VOID(obj->getNamespaceDeclared())); - - /* Per ECMA-357, 13.2.5, these properties must be "own". */ - if (!JS_DefineProperties(cx, obj, namespace_props)) - return NULL; - - if (prefix) - obj->setNamePrefix(prefix); - if (uri) - obj->setNameURI(uri); - if (declared) - obj->setNamespaceDeclared(JSVAL_TRUE); - return obj; -} - -/* - * QName class and library functions. - */ -DEFINE_GETTER(QNameNameURI_getter, - if (obj->getClass() == &QNameClass) - vp.set(JSVAL_IS_VOID(obj->getNameURIVal()) ? JSVAL_NULL : obj->getNameURIVal())) -DEFINE_GETTER(QNameLocalName_getter, - if (obj->getClass() == &QNameClass) - vp.set(obj->getQNameLocalNameVal())) - -static JSBool -qname_identity(JSObject *qna, const JSObject *qnb) -{ - JSLinearString *uri1 = qna->getNameURI(); - JSLinearString *uri2 = qnb->getNameURI(); - - if (!uri1 ^ !uri2) - return JS_FALSE; - if (uri1 && !EqualStrings(uri1, uri2)) - return JS_FALSE; - return EqualStrings(qna->getQNameLocalName(), qnb->getQNameLocalName()); -} - -static JSBool -qname_equality(JSContext *cx, HandleObject qn, HandleValue v, JSBool *bp) -{ - JSObject *obj2; - - obj2 = v.toObjectOrNull(); - *bp = (!obj2 || obj2->getClass() != &QNameClass) - ? JS_FALSE - : qname_identity(qn, obj2); - return JS_TRUE; -} - -JS_FRIEND_DATA(Class) js::QNameClass = { - "QName", - JSCLASS_HAS_RESERVED_SLOTS(JSObject::QNAME_CLASS_RESERVED_SLOTS) | - JSCLASS_HAS_CACHED_PROTO(JSProto_QName), - JS_PropertyStub, /* addProperty */ - JS_PropertyStub, /* delProperty */ - JS_PropertyStub, /* getProperty */ - JS_StrictPropertyStub, /* setProperty */ - JS_EnumerateStub, - JS_ResolveStub, - JS_ConvertStub, - NULL, /* finalize */ - NULL, /* checkAccess */ - NULL, /* call */ - NULL, /* construct */ - NULL, /* hasInstance */ - NULL, /* trace */ - { - qname_equality, - NULL, /* outerObject */ - NULL, /* innerObject */ - NULL, /* iteratorObject */ - NULL, /* wrappedObject */ - } -}; - -/* - * Classes for the ECMA-357-internal types AttributeName and AnyName, which - * are like QName, except that they have no property getters. They share the - * qname_toString method, and therefore are exposed as constructable objects - * in this implementation. - */ -JS_FRIEND_DATA(Class) js::AttributeNameClass = { - js_AttributeName_str, - JSCLASS_HAS_RESERVED_SLOTS(JSObject::QNAME_CLASS_RESERVED_SLOTS) | - JSCLASS_IS_ANONYMOUS, - JS_PropertyStub, /* addProperty */ - JS_PropertyStub, /* delProperty */ - JS_PropertyStub, /* getProperty */ - JS_StrictPropertyStub, /* setProperty */ - JS_EnumerateStub, - JS_ResolveStub, - JS_ConvertStub -}; - -JS_FRIEND_DATA(Class) js::AnyNameClass = { - js_AnyName_str, - JSCLASS_HAS_RESERVED_SLOTS(JSObject::QNAME_CLASS_RESERVED_SLOTS) | - JSCLASS_IS_ANONYMOUS, - JS_PropertyStub, /* addProperty */ - JS_PropertyStub, /* delProperty */ - JS_PropertyStub, /* getProperty */ - JS_StrictPropertyStub, /* setProperty */ - JS_EnumerateStub, - JS_ResolveStub, - JS_ConvertStub -}; - -#define QNAME_ATTRS (JSPROP_ENUMERATE | JSPROP_READONLY | JSPROP_PERMANENT | JSPROP_SHARED) - -static JSPropertySpec qname_props[] = { - {js_uri_str, 0, QNAME_ATTRS, JSOP_WRAPPER(QNameNameURI_getter), JSOP_NULLWRAPPER}, - {js_localName_str, 0, QNAME_ATTRS, JSOP_WRAPPER(QNameLocalName_getter), JSOP_NULLWRAPPER}, - {0,0,0,JSOP_NULLWRAPPER,JSOP_NULLWRAPPER} -}; - -static JSString * -ConvertQNameToString(JSContext *cx, JSObject *obj) -{ - JS_ASSERT(obj->isQName()); - RootedString uri(cx, obj->getNameURI()); - RootedString str(cx); - if (!uri) { - /* No uri means wildcard qualifier. */ - str = cx->names().starQualifier; - } else if (uri->empty()) { - /* Empty string for uri means localName is in no namespace. */ - str = cx->runtime->emptyString; - } else { - RootedString qualstr(cx, cx->names().qualifier); - str = ConcatStrings(cx, uri, qualstr); - if (!str) - return NULL; - } - Rooted localName(cx, obj->getQNameLocalName()); - str = ConcatStrings(cx, str, localName); - if (!str) - return NULL; - - if (obj->getClass() == &AttributeNameClass) { - JS::Anchor anchor(str); - size_t length = str->length(); - jschar *chars = cx->pod_malloc(length + 2); - if (!chars) - return NULL; - *chars = '@'; - const jschar *strChars = str->getChars(cx); - if (!strChars) { - js_free(chars); - return NULL; - } - js_strncpy(chars + 1, strChars, length); - chars[++length] = 0; - str = js_NewString(cx, chars, length); - if (!str) { - js_free(chars); - return NULL; - } - } - return str; -} - -static JSBool -qname_toString(JSContext *cx, unsigned argc, Value *vp) -{ - JSObject *obj = ToObject(cx, HandleValue::fromMarkedLocation(&vp[1])); - if (!obj) - return false; - - if (!obj->isQName()) { - ReportIncompatibleMethod(cx, CallReceiverFromVp(vp), &QNameClass); - return false; - } - - JSString *str = ConvertQNameToString(cx, obj); - if (!str) - return false; - - vp->setString(str); - return true; -} - -static JSFunctionSpec qname_methods[] = { - JS_FN(js_toString_str, qname_toString, 0,0), - JS_FS_END -}; - - -static bool -InitXMLQName(JSContext *cx, HandleObject obj, JSLinearString *uri, JSLinearString *prefix, - JSAtom *localName) -{ - JS_ASSERT(obj->isQName()); - JS_ASSERT(JSVAL_IS_VOID(obj->getNamePrefixVal())); - JS_ASSERT(JSVAL_IS_VOID(obj->getNameURIVal())); - JS_ASSERT(JSVAL_IS_VOID(obj->getQNameLocalNameVal())); - - /* Per ECMA-357, 13.3.5, these properties must be "own". */ - if (!JS_DefineProperties(cx, obj, qname_props)) - return false; - - if (uri) - obj->setNameURI(uri); - if (prefix) - obj->setNamePrefix(prefix); - if (localName) - obj->setQNameLocalName(localName); - return true; -} - -static JSObject * -NewXMLQName(JSContext *cx, JSLinearString *uri, JSLinearString *prefix, - JSAtom *localName) -{ - RootedObject obj(cx, NewBuiltinClassInstanceXML(cx, &QNameClass)); - if (!obj) - return NULL; - if (!InitXMLQName(cx, obj, uri, prefix, localName)) - return NULL; - return obj; -} - -static JSObject * -NewXMLAttributeName(JSContext *cx, JSLinearString *uri, JSLinearString *prefix, - JSAtom *localName) -{ - /* - * AttributeName is an internal anonymous class which instances are not - * exposed to scripts. - */ - RootedObject obj(cx, NewObjectWithGivenProto(cx, &AttributeNameClass, NULL, cx->global())); - if (!obj) - return NULL; - JS_ASSERT(obj->isQName()); - if (!InitXMLQName(cx, obj, uri, prefix, localName)) - return NULL; - return obj; -} - -static JSObject * -ConstructObjectWithArguments(JSContext *cx, Class *clasp, - unsigned argc, jsval *argv) -{ - assertSameCompartment(cx, JSValueArray(argv, argc)); - - AutoArrayRooter argtvr(cx, argc, argv); - - JSProtoKey protoKey = GetClassProtoKey(clasp); - - /* Protect constructor in case a crazy getter for .prototype uproots it. */ - RootedValue value(cx); - RootedObject null(cx); - if (!js_FindClassObject(cx, protoKey, &value, clasp)) - return NULL; - - Value rval; - if (!InvokeConstructor(cx, value, argc, argv, &rval)) - return NULL; - - /* - * If the instance's class differs from what was requested, throw a type - * error. - */ - if (!rval.isObject() || rval.toObject().getClass() != clasp) { - JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, - JSMSG_WRONG_CONSTRUCTOR, clasp->name); - return NULL; - } - return &rval.toObject(); -} - -JSObject * -js_ConstructXMLQNameObject(JSContext *cx, const Value &nsval, const Value &lnval) -{ - Value argv[2]; - - /* - * ECMA-357 11.1.2, - * The _QualifiedIdentifier : PropertySelector :: PropertySelector_ - * production, step 2. - */ - if (nsval.isObject() && - nsval.toObject().getClass() == &AnyNameClass) { - argv[0].setNull(); - } else { - argv[0] = nsval; - } - argv[1] = lnval; - return ConstructObjectWithArguments(cx, &QNameClass, 2, argv); -} - -static JSBool -IsXMLName(const jschar *cp, size_t n) -{ - JSBool rv; - jschar c; - - rv = JS_FALSE; - if (n != 0 && unicode::IsXMLNamespaceStart(*cp)) { - while (--n != 0) { - c = *++cp; - if (!unicode::IsXMLNamespacePart(c)) - return rv; - } - rv = JS_TRUE; - } - return rv; -} - -JSBool -js_IsXMLName(JSContext *cx, jsval v) -{ - JSLinearString *name = NULL; - JSErrorReporter older; - - /* - * Inline specialization of the QName constructor called with v passed as - * the only argument, to compute the localName for the constructed qname, - * without actually allocating the object or computing its uri and prefix. - * See ECMA-357 13.1.2.1 step 1 and 13.3.2. - */ - if (!JSVAL_IS_PRIMITIVE(v) && - JSVAL_TO_OBJECT(v)->isQName()) { - name = JSVAL_TO_OBJECT(v)->getQNameLocalName(); - } else { - older = JS_SetErrorReporter(cx, NULL); - JSString *str = ToString(cx, v); - if (str) - name = str->ensureLinear(cx); - JS_SetErrorReporter(cx, older); - if (!name) { - JS_ClearPendingException(cx); - return JS_FALSE; - } - } - - return IsXMLName(name->chars(), name->length()); -} - -/* - * When argc is -1, it indicates argv is empty but the code should behave as - * if argc is 1 and argv[0] is JSVAL_VOID. - */ -static JSBool -NamespaceHelper(JSContext *cx, int argc, jsval *argv, jsval *rval) -{ - jsval urival, prefixval; - JSObject *uriobj; - JSBool isNamespace, isQName; - Class *clasp; - JSLinearString *empty, *prefix, *uri; - - isNamespace = isQName = JS_FALSE; -#ifdef __GNUC__ /* suppress bogus gcc warnings */ - uriobj = NULL; -#endif - if (argc <= 0) { - urival = JSVAL_VOID; - } else { - urival = argv[argc > 1]; - if (!JSVAL_IS_PRIMITIVE(urival)) { - uriobj = JSVAL_TO_OBJECT(urival); - clasp = uriobj->getClass(); - isNamespace = (clasp == &NamespaceClass); - isQName = (clasp == &QNameClass); - } - } - - /* Namespace called as function. */ - if (argc == 1 && isNamespace) { - /* Namespace called with one Namespace argument is identity. */ - *rval = urival; - return JS_TRUE; - } - - RootedObject obj(cx, NewBuiltinClassInstanceXML(cx, &NamespaceClass)); - if (!obj) - return JS_FALSE; - - /* Per ECMA-357, 13.2.5, these properties must be "own". */ - if (!JS_DefineProperties(cx, obj, namespace_props)) - return JS_FALSE; - - empty = cx->runtime->emptyString; - obj->setNamePrefix(empty); - obj->setNameURI(empty); - - if (argc == 1 || argc == -1) { - if (isNamespace) { - obj->setNameURI(uriobj->getNameURI()); - obj->setNamePrefix(uriobj->getNamePrefix()); - } else if (isQName && (uri = uriobj->getNameURI())) { - obj->setNameURI(uri); - obj->setNamePrefix(uriobj->getNamePrefix()); - } else { - JSString *str = ToString(cx, urival); - if (!str) - return JS_FALSE; - uri = str->ensureLinear(cx); - if (!uri) - return JS_FALSE; - obj->setNameURI(uri); - if (!uri->empty()) - obj->clearNamePrefix(); - } - } else if (argc == 2) { - if (!isQName || !(uri = uriobj->getNameURI())) { - JSString *str = ToString(cx, urival); - if (!str) - return JS_FALSE; - uri = str->ensureLinear(cx); - if (!uri) - return JS_FALSE; - } - obj->setNameURI(uri); - - prefixval = argv[0]; - if (uri->empty()) { - if (!JSVAL_IS_VOID(prefixval)) { - JSString *str = ToString(cx, prefixval); - if (!str) - return JS_FALSE; - if (!str->empty()) { - JSAutoByteString bytes; - if (js_ValueToPrintable(cx, StringValue(str), &bytes)) { - JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, - JSMSG_BAD_XML_NAMESPACE, bytes.ptr()); - } - return JS_FALSE; - } - } - } else if (JSVAL_IS_VOID(prefixval) || !js_IsXMLName(cx, prefixval)) { - obj->clearNamePrefix(); - } else { - JSString *str = ToString(cx, prefixval); - if (!str) - return JS_FALSE; - prefix = str->ensureLinear(cx); - if (!prefix) - return JS_FALSE; - obj->setNamePrefix(prefix); - } - } - - *rval = OBJECT_TO_JSVAL(obj); - return JS_TRUE; -} - -static JSBool -Namespace(JSContext *cx, unsigned argc, Value *vp) -{ - return NamespaceHelper(cx, argc, vp + 2, vp); -} - -/* - * When argc is -1, it indicates argv is empty but the code should behave as - * if argc is 1 and argv[0] is JSVAL_VOID. - */ -static JSBool -QNameHelper(JSContext *cx, int argc, jsval *argv, jsval *rval) -{ - jsval nameval, nsval; - JSBool isQName, isNamespace; - JSObject *qn; - JSLinearString *uri, *prefix; - JSObject *obj2; - - JSAtom *name; - if (argc <= 0) { - nameval = JSVAL_VOID; - isQName = JS_FALSE; - } else { - nameval = argv[argc > 1]; - isQName = - !JSVAL_IS_PRIMITIVE(nameval) && - JSVAL_TO_OBJECT(nameval)->getClass() == &QNameClass; - } - - /* QName called as function. */ - if (argc == 1 && isQName) { - /* QName called with one QName argument is identity. */ - *rval = nameval; - return JS_TRUE; - } - - /* Create and return a new QName object exactly as if constructed. */ - RootedObject obj(cx, NewBuiltinClassInstanceXML(cx, &QNameClass)); - if (!obj) - return JS_FALSE; - - if (isQName) { - /* If namespace is not specified and name is a QName, clone it. */ - qn = JSVAL_TO_OBJECT(nameval); - if (argc == 1) { - uri = qn->getNameURI(); - prefix = qn->getNamePrefix(); - name = qn->getQNameLocalName(); - goto out; - } - - /* Namespace and qname were passed -- use the qname's localName. */ - nameval = qn->getQNameLocalNameVal(); - } - - if (argc == 0) { - name = cx->runtime->emptyString; - } else if (argc < 0) { - name = cx->names().undefined; - } else { - name = ToAtom(cx, nameval); - if (!name) - return false; - } - - if (argc > 1 && !JSVAL_IS_VOID(argv[0])) { - nsval = argv[0]; - } else if (IS_STAR(name)) { - nsval = JSVAL_NULL; - } else { - if (!js_GetDefaultXMLNamespace(cx, &nsval)) - return JS_FALSE; - JS_ASSERT(!JSVAL_IS_PRIMITIVE(nsval)); - JS_ASSERT(JSVAL_TO_OBJECT(nsval)->getClass() == - &NamespaceClass); - } - - if (JSVAL_IS_NULL(nsval)) { - /* NULL prefix represents *undefined* in ECMA-357 13.3.2 5(a). */ - prefix = uri = NULL; - } else { - /* - * Inline specialization of the Namespace constructor called with - * nsval passed as the only argument, to compute the uri and prefix - * for the constructed namespace, without actually allocating the - * object or computing other members. See ECMA-357 13.3.2 6(a) and - * 13.2.2. - */ - isNamespace = isQName = JS_FALSE; - if (!JSVAL_IS_PRIMITIVE(nsval)) { - obj2 = JSVAL_TO_OBJECT(nsval); - isNamespace = (obj2->getClass() == &NamespaceClass); - isQName = (obj2->getClass() == &QNameClass); - } -#ifdef __GNUC__ /* suppress bogus gcc warnings */ - else obj2 = NULL; -#endif - - if (isNamespace) { - uri = obj2->getNameURI(); - prefix = obj2->getNamePrefix(); - } else if (isQName && (uri = obj2->getNameURI())) { - JS_ASSERT(argc > 1); - prefix = obj2->getNamePrefix(); - } else { - JS_ASSERT(argc > 1); - JSString *str = ToString(cx, nsval); - if (!str) - return JS_FALSE; - uri = str->ensureLinear(cx); - if (!uri) - return JS_FALSE; - argv[0] = STRING_TO_JSVAL(uri); /* local root */ - - /* NULL here represents *undefined* in ECMA-357 13.2.2 3(c)iii. */ - prefix = uri->empty() ? cx->runtime->emptyString : NULL; - } - } - -out: - *rval = OBJECT_TO_JSVAL(obj); - return InitXMLQName(cx, obj, uri, prefix, name); -} - -static JSBool -QName(JSContext *cx, unsigned argc, Value *vp) -{ - return QNameHelper(cx, argc, vp + 2, vp); -} - -/* - * XMLArray library functions. - */ -static JSBool -namespace_identity(const JSObject *nsa, const JSObject *nsb) -{ - JSLinearString *prefixa = nsa->getNamePrefix(); - JSLinearString *prefixb = nsb->getNamePrefix(); - - if (prefixa && prefixb) { - if (!EqualStrings(prefixa, prefixb)) - return JS_FALSE; - } else { - if (prefixa || prefixb) - return JS_FALSE; - } - return EqualStrings(nsa->getNameURI(), nsb->getNameURI()); -} - -static JSBool -attr_identity(const JSXML *xmla, const JSXML *xmlb) -{ - return qname_identity(xmla->name, xmlb->name); -} - -void -js_XMLArrayCursorTrace(JSTracer *trc, JSXMLArrayCursor *cursor) -{ - for (; cursor; cursor = cursor->next) { - if (cursor->root) - MarkXML(trc, &(HeapPtr &)cursor->root, "cursor_root"); - } -} - -void -js_XMLArrayCursorTrace(JSTracer *trc, JSXMLArrayCursor *cursor) -{ - for (; cursor; cursor = cursor->next) { - if (cursor->root) - MarkObject(trc, &(HeapPtr &)cursor->root, "cursor_root"); - } -} - -template -static HeapPtr * -ReallocateVector(HeapPtr *vector, size_t count) -{ -#if JS_BITS_PER_WORD == 32 - if (count > ~(size_t)0 / sizeof(HeapPtr)) - return NULL; -#endif - - size_t size = count * sizeof(HeapPtr); - return (HeapPtr *) js_realloc(vector, size); -} - -/* NB: called with null cx from the GC, via xml_trace => JSXMLArray::trim. */ -template -bool -JSXMLArray::setCapacity(JSContext *cx, uint32_t newCapacity) -{ - if (newCapacity == 0) { - /* We could let realloc(p, 0) free this, but purify gets confused. */ - if (vector) { - if (cx) - js_free(vector); - else - js_free(vector); - } - vector = NULL; - } else { - HeapPtr *tmp = ReallocateVector(vector, newCapacity); - if (!tmp) { - if (cx) - JS_ReportOutOfMemory(cx); - return false; - } - vector = tmp; - } - capacity = JSXML_PRESET_CAPACITY | newCapacity; - return true; -} - -template -void -JSXMLArray::trim() -{ - if (capacity & JSXML_PRESET_CAPACITY) - return; - if (length < capacity) - setCapacity(NULL, length); -} - -template -void -JSXMLArray::finish(FreeOp *fop) -{ - if (!fop->runtime()->isHeapBusy()) { - /* We need to clear these to trigger a write barrier. */ - for (uint32_t i = 0; i < length; i++) - vector[i].~HeapPtr(); - } - - fop->free_(vector); - - while (JSXMLArrayCursor *cursor = cursors) - cursor->disconnect(); - -#ifdef DEBUG - memset(this, 0xd5, sizeof *this); -#endif -} - -#define XML_NOT_FOUND UINT32_MAX - -template -static uint32_t -XMLArrayFindMember(const JSXMLArray *array, U *elt, typename IdentityOp::compare identity) -{ - HeapPtr *vector; - uint32_t i, n; - - /* The identity op must not reallocate array->vector. */ - vector = array->vector; - for (i = 0, n = array->length; i < n; i++) { - if (identity(vector[i].get(), elt)) - return i; - } - return XML_NOT_FOUND; -} - -/* - * Grow array vector capacity by powers of two to LINEAR_THRESHOLD, and after - * that, grow by LINEAR_INCREMENT. Both must be powers of two, and threshold - * should be greater than increment. - */ -#define LINEAR_THRESHOLD 256 -#define LINEAR_INCREMENT 32 - -template -static JSBool -XMLArrayAddMember(JSContext *cx, JSXMLArray *array, uint32_t index, T *elt) -{ - uint32_t capacity, i; - int log2; - HeapPtr *vector; - - if (index >= array->length) { - if (index >= JSXML_CAPACITY(array)) { - /* Arrange to clear JSXML_PRESET_CAPACITY from array->capacity. */ - capacity = index + 1; - if (index >= LINEAR_THRESHOLD) { - capacity = JS_ROUNDUP(capacity, LINEAR_INCREMENT); - } else { - JS_CEILING_LOG2(log2, capacity); - capacity = JS_BIT(log2); - } - if (!(vector = ReallocateVector(array->vector, capacity))) { - JS_ReportOutOfMemory(cx); - return JS_FALSE; - } - array->capacity = capacity; - array->vector = vector; - for (i = array->length; i < index; i++) - vector[i].init(NULL); - } - array->vector[index].init(NULL); - array->length = index + 1; - } - - array->vector[index] = elt; - return JS_TRUE; -} - -template -static JSBool -XMLArrayInsert(JSContext *cx, JSXMLArray *array, uint32_t i, uint32_t n) -{ - uint32_t j, k; - JSXMLArrayCursor *cursor; - - j = array->length; - JS_ASSERT(i <= j); - if (!array->setCapacity(cx, j + n)) - return JS_FALSE; - - k = j; - while (k != j + n) { - array->vector[k].init(NULL); - k++; - } - - array->length = j + n; - JS_ASSERT(n != (uint32_t)-1); - while (j != i) { - --j; - array->vector[j + n] = array->vector[j]; - } - - for (cursor = array->cursors; cursor; cursor = cursor->next) { - if (cursor->index > i) - cursor->index += n; - } - return JS_TRUE; -} - -template -static T * -XMLArrayDelete(JSContext *cx, JSXMLArray *array, uint32_t index, JSBool compress) -{ - uint32_t length; - HeapPtr *vector; - T *elt; - JSXMLArrayCursor *cursor; - - length = array->length; - if (index >= length) - return NULL; - - vector = array->vector; - elt = vector[index]; - if (compress) { - vector[length - 1].~HeapPtr(); - while (++index < length) - vector[index-1] = vector[index]; - array->length = length - 1; - array->capacity = JSXML_CAPACITY(array); - } else { - vector[index] = NULL; - } - - for (cursor = array->cursors; cursor; cursor = cursor->next) { - if (cursor->index > index) - --cursor->index; - } - return elt; -} - -template -static void -XMLArrayTruncate(JSContext *cx, JSXMLArray *array, uint32_t length) -{ - HeapPtr *vector; - - JS_ASSERT(!array->cursors); - if (length >= array->length) - return; - - for (uint32_t i = length; i < array->length; i++) - array->vector[i].~HeapPtr(); - - if (length == 0) { - if (array->vector) - js_free(array->vector); - vector = NULL; - } else { - vector = ReallocateVector(array->vector, length); - if (!vector) - return; - } - - if (array->length > length) - array->length = length; - array->capacity = length; - array->vector = vector; -} - -#define XMLARRAY_FIND_MEMBER(a,e,f) XMLArrayFindMember(a, e, f) -#define XMLARRAY_HAS_MEMBER(a,e,f) (XMLArrayFindMember(a, e, f) != \ - XML_NOT_FOUND) -#define XMLARRAY_MEMBER(a,i,t) (((i) < (a)->length) \ - ? (a)->vector[i].get() \ - : NULL) -#define XMLARRAY_SET_MEMBER(a,i,e) JS_BEGIN_MACRO \ - if ((a)->length <= (i)) { \ - (a)->length = (i) + 1; \ - ((a)->vector[i].init(e)); \ - } else { \ - ((a)->vector[i] = e); \ - } \ - JS_END_MACRO -#define XMLARRAY_ADD_MEMBER(x,a,i,e)XMLArrayAddMember(x, a, i, e) -#define XMLARRAY_INSERT(x,a,i,n) XMLArrayInsert(x, a, i, n) -#define XMLARRAY_APPEND(x,a,e) XMLARRAY_ADD_MEMBER(x, a, (a)->length, (e)) -#define XMLARRAY_DELETE(x,a,i,c,t) (XMLArrayDelete(x, a, i, c)) -#define XMLARRAY_TRUNCATE(x,a,n) XMLArrayTruncate(x, a, n) - -/* - * Define XML setting property strings and constants early, so everyone can - * use the same names. - */ -static const char js_ignoreComments_str[] = "ignoreComments"; -static const char js_ignoreProcessingInstructions_str[] - = "ignoreProcessingInstructions"; -static const char js_ignoreWhitespace_str[] = "ignoreWhitespace"; -static const char js_prettyPrinting_str[] = "prettyPrinting"; -static const char js_prettyIndent_str[] = "prettyIndent"; - -#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, 0, JSPROP_PERMANENT, JSOP_NULLWRAPPER, JSOP_NULLWRAPPER}, - {js_ignoreProcessingInstructions_str, 0, JSPROP_PERMANENT, JSOP_NULLWRAPPER, JSOP_NULLWRAPPER}, - {js_ignoreWhitespace_str, 0, JSPROP_PERMANENT, JSOP_NULLWRAPPER, JSOP_NULLWRAPPER}, - {js_prettyPrinting_str, 0, JSPROP_PERMANENT, JSOP_NULLWRAPPER, JSOP_NULLWRAPPER}, - {js_prettyIndent_str, 0, JSPROP_PERMANENT, JSOP_NULLWRAPPER, JSOP_NULLWRAPPER}, - {0,0,0,JSOP_NULLWRAPPER, JSOP_NULLWRAPPER} -}; - -/* Macros for special-casing xml:, xmlns= and xmlns:foo= in ParseNodeToQName. */ -#define IS_XML(str) \ - (str->length() == 3 && IS_XML_CHARS(str->chars())) - -#define IS_XMLNS(str) \ - (str->length() == 5 && IS_XMLNS_CHARS(str->chars())) - -static inline bool -IS_XML_CHARS(const jschar *chars) -{ - return (chars[0] == 'x' || chars[0] == 'X') && - (chars[1] == 'm' || chars[1] == 'M') && - (chars[2] == 'l' || chars[2] == 'L'); -} - -static inline bool -HAS_NS_AFTER_XML(const jschar *chars) -{ - return (chars[3] == 'n' || chars[3] == 'N') && - (chars[4] == 's' || chars[4] == 'S'); -} - -#define IS_XMLNS_CHARS(chars) \ - (IS_XML_CHARS(chars) && HAS_NS_AFTER_XML(chars)) - -#define STARTS_WITH_XML(chars,length) \ - (length >= 3 && IS_XML_CHARS(chars)) - -static const char xml_namespace_str[] = "http://www.w3.org/XML/1998/namespace"; -static const char xmlns_namespace_str[] = "http://www.w3.org/2000/xmlns/"; - -void -JSXML::finalize(FreeOp *fop) -{ - if (JSXML_HAS_KIDS(this)) { - xml_kids.finish(fop); - if (xml_class == JSXML_CLASS_ELEMENT) { - xml_namespaces.finish(fop); - xml_attrs.finish(fop); - } - } -#ifdef DEBUG_notme - JS_REMOVE_LINK(&links); -#endif -} - -static JSObject * -ParseNodeToQName(Parser *parser, ParseNode *pn, - JSXMLArray *inScopeNSes, JSBool isAttributeName) -{ - JSContext *cx = parser->context; - JSLinearString *uri, *prefix; - size_t length, offset; - const jschar *start, *limit, *colon; - uint32_t n; - JSObject *ns; - JSLinearString *nsprefix; - - JS_ASSERT(pn->isArity(PN_NULLARY)); - JSAtom *atom = pn->pn_atom; - JSStableString *str = atom->ensureStable(cx); - if (!str) - return NULL; - start = str->chars().get(); - length = str->length(); - JS_ASSERT(length != 0 && *start != '@'); - JS_ASSERT(length != 1 || *start != '*'); - - JSAtom *localName; - - uri = cx->runtime->emptyString; - limit = start + length; - colon = js_strchr_limit(start, ':', limit); - if (colon) { - offset = colon - start; - prefix = js_NewDependentString(cx, str, 0, offset); - if (!prefix) - return NULL; - - if (STARTS_WITH_XML(start, offset)) { - if (offset == 3) { - uri = JS_ASSERT_STRING_IS_FLAT(JS_InternString(cx, xml_namespace_str)); - if (!uri) - return NULL; - } else if (offset == 5 && HAS_NS_AFTER_XML(start)) { - uri = JS_ASSERT_STRING_IS_FLAT(JS_InternString(cx, xmlns_namespace_str)); - if (!uri) - return NULL; - } else { - uri = NULL; - } - } else { - uri = NULL; - n = inScopeNSes->length; - while (n != 0) { - --n; - ns = XMLARRAY_MEMBER(inScopeNSes, n, JSObject); - nsprefix = ns->getNamePrefix(); - if (nsprefix && EqualStrings(nsprefix, prefix)) { - uri = ns->getNameURI(); - break; - } - } - } - - if (!uri) { - Value v = StringValue(prefix); - JSAutoByteString bytes; - if (js_ValueToPrintable(parser->context, v, &bytes)) - parser->reportError(pn, JSMSG_BAD_XML_NAMESPACE, bytes.ptr()); - return NULL; - } - - localName = AtomizeChars(parser->context, colon + 1, length - (offset + 1)); - if (!localName) - return NULL; - } else { - if (isAttributeName) { - /* - * An unprefixed attribute is not in any namespace, so set prefix - * as well as uri to the empty string. - */ - prefix = uri; - } else { - /* - * Loop from back to front looking for the closest declared default - * namespace. - */ - n = inScopeNSes->length; - while (n != 0) { - --n; - ns = XMLARRAY_MEMBER(inScopeNSes, n, JSObject); - nsprefix = ns->getNamePrefix(); - if (!nsprefix || nsprefix->empty()) { - uri = ns->getNameURI(); - break; - } - } - prefix = uri->empty() ? parser->context->runtime->emptyString : NULL; - } - localName = atom; - } - - return NewXMLQName(parser->context, uri, prefix, localName); -} - -static JSString * -ChompXMLWhitespace(JSContext *cx, JSString *str) -{ - size_t length, newlength, offset; - const jschar *cp, *start, *end; - jschar c; - - length = str->length(); - start = str->getChars(cx); - if (!start) - return NULL; - - for (cp = start, end = cp + length; cp < end; cp++) { - c = *cp; - if (!unicode::IsXMLSpace(c)) - break; - } - while (end > cp) { - c = end[-1]; - if (!unicode::IsXMLSpace(c)) - break; - --end; - } - newlength = end - cp; - if (newlength == length) - return str; - offset = cp - start; - return js_NewDependentString(cx, str, offset, newlength); -} - -static JSXML * -ParseNodeToXML(Parser *parser, ParseNode *pn, - JSXMLArray *inScopeNSes, unsigned flags) -{ - JSContext *cx = parser->context; - JSXML *xml, *kid, *attr, *attrj; - JSLinearString *str; - uint32_t length, n, i, j; - ParseNode *pn2, *pn3, *head, **pnp; - JSObject *ns; - JSObject *qn, *attrjqn; - JSXMLClass xml_class; - int stackDummy; - - if (!JS_CHECK_STACK_SIZE(cx->mainThread().nativeStackLimit, &stackDummy)) { - parser->reportError(pn, JSMSG_OVER_RECURSED); - return NULL; - } - -#define PN2X_SKIP_CHILD ((JSXML *) 1) - - /* - * Cases return early to avoid common code that gets an outermost xml's - * object, which protects GC-things owned by xml and its descendants from - * garbage collection. - */ - xml = NULL; - switch (pn->getKind()) { - case PNK_XMLELEM: - length = inScopeNSes->length; - pn2 = pn->pn_head; - xml = ParseNodeToXML(parser, pn2, inScopeNSes, flags); - if (!xml) - goto fail; - - n = pn->pn_count; - JS_ASSERT(n >= 2); - n -= 2; - if (!xml->xml_kids.setCapacity(cx, n)) - goto fail; - - i = 0; - while ((pn2 = pn2->pn_next) != NULL) { - if (!pn2->pn_next) { - /* Don't append the end tag! */ - JS_ASSERT(pn2->isKind(PNK_XMLETAGO)); - break; - } - - if ((flags & XSF_IGNORE_WHITESPACE) && - n > 1 && pn2->isKind(PNK_XMLSPACE)) { - --n; - continue; - } - - kid = ParseNodeToXML(parser, pn2, inScopeNSes, flags); - if (kid == PN2X_SKIP_CHILD) { - --n; - continue; - } - - if (!kid) - goto fail; - - /* Store kid in xml right away, to protect it from GC. */ - XMLARRAY_SET_MEMBER(&xml->xml_kids, i, kid); - kid->parent = xml; - ++i; - - /* XXX where is this documented in an XML spec, or in E4X? */ - if ((flags & XSF_IGNORE_WHITESPACE) && - n > 1 && kid->xml_class == JSXML_CLASS_TEXT) { - JSString *str = ChompXMLWhitespace(cx, kid->xml_value); - if (!str) - goto fail; - kid->xml_value = str; - } - } - - JS_ASSERT(i == n); - if (n < pn->pn_count - 2) - xml->xml_kids.trim(); - XMLARRAY_TRUNCATE(cx, inScopeNSes, length); - break; - - case PNK_XMLLIST: - xml = js_NewXML(cx, JSXML_CLASS_LIST); - if (!xml) - goto fail; - - n = pn->pn_count; - if (!xml->xml_kids.setCapacity(cx, n)) - goto fail; - - i = 0; - for (pn2 = pn->pn_head; pn2; pn2 = pn2->pn_next) { - /* - * Always ignore insignificant whitespace in lists -- we shouldn't - * condition this on an XML.ignoreWhitespace setting when the list - * constructor is XMLList (note XML/XMLList unification hazard). - */ - if (pn2->isKind(PNK_XMLSPACE)) { - --n; - continue; - } - - kid = ParseNodeToXML(parser, pn2, inScopeNSes, flags); - if (kid == PN2X_SKIP_CHILD) { - --n; - continue; - } - - if (!kid) - goto fail; - - XMLARRAY_SET_MEMBER(&xml->xml_kids, i, kid); - ++i; - } - - if (n < pn->pn_count) - xml->xml_kids.trim(); - break; - - case PNK_XMLSTAGO: - case PNK_XMLPTAGC: - length = inScopeNSes->length; - pn2 = pn->pn_head; - JS_ASSERT(pn2->isKind(PNK_XMLNAME)); - if (pn2->isArity(PN_LIST)) - goto syntax; - - xml = js_NewXML(cx, JSXML_CLASS_ELEMENT); - if (!xml) - goto fail; - - /* First pass: check syntax and process namespace declarations. */ - JS_ASSERT(pn->pn_count >= 1); - n = pn->pn_count - 1; - pnp = &pn2->pn_next; - head = *pnp; - while ((pn2 = *pnp) != NULL) { - size_t length; - const jschar *chars; - - if (!pn2->isKind(PNK_XMLNAME) || !pn2->isArity(PN_NULLARY)) - goto syntax; - - /* Enforce "Well-formedness constraint: Unique Att Spec". */ - for (pn3 = head; pn3 != pn2; pn3 = pn3->pn_next->pn_next) { - if (pn3->pn_atom == pn2->pn_atom) { - Value v = StringValue(pn2->pn_atom); - JSAutoByteString bytes; - if (js_ValueToPrintable(cx, v, &bytes)) - parser->reportError(pn2, JSMSG_DUPLICATE_XML_ATTR, bytes.ptr()); - goto fail; - } - } - - JSAtom *atom = pn2->pn_atom; - pn2 = pn2->pn_next; - JS_ASSERT(pn2); - if (!pn2->isKind(PNK_XMLATTR)) - goto syntax; - - chars = atom->chars(); - length = atom->length(); - if (length >= 5 && - IS_XMLNS_CHARS(chars) && - (length == 5 || chars[5] == ':')) { - JSLinearString *uri, *prefix; - - uri = pn2->pn_atom; - if (length == 5) { - /* 10.3.2.1. Step 6(h)(i)(1)(a). */ - prefix = cx->runtime->emptyString; - } else { - prefix = js_NewStringCopyN(cx, chars + 6, length - 6); - if (!prefix) - goto fail; - } - - /* - * Once the new ns is appended to xml->xml_namespaces, it is - * protected from GC by the object that owns xml -- which is - * either xml->object if outermost, or the object owning xml's - * oldest ancestor if !outermost. - */ - ns = NewXMLNamespace(cx, prefix, uri, JS_TRUE); - if (!ns) - goto fail; - - /* - * Don't add a namespace that's already in scope. If someone - * extracts a child property from its parent via [[Get]], then - * we enforce the invariant, noted many times in ECMA-357, that - * the child's namespaces form a possibly-improper superset of - * its ancestors' namespaces. - */ - if (!XMLARRAY_HAS_MEMBER(inScopeNSes, ns, namespace_identity)) { - if (!XMLARRAY_APPEND(cx, inScopeNSes, ns) || - !XMLARRAY_APPEND(cx, &xml->xml_namespaces, ns)) { - goto fail; - } - } - - JS_ASSERT(n >= 2); - n -= 2; - *pnp = pn2->pn_next; - /* XXXbe recycle pn2 */ - continue; - } - - pnp = &pn2->pn_next; - } - - xml->xml_namespaces.trim(); - - /* Second pass: process tag name and attributes, using namespaces. */ - pn2 = pn->pn_head; - qn = ParseNodeToQName(parser, pn2, inScopeNSes, JS_FALSE); - if (!qn) - goto fail; - xml->name = qn; - - JS_ASSERT((n & 1) == 0); - n >>= 1; - if (!xml->xml_attrs.setCapacity(cx, n)) - goto fail; - - for (i = 0; (pn2 = pn2->pn_next) != NULL; i++) { - qn = ParseNodeToQName(parser, pn2, inScopeNSes, JS_TRUE); - if (!qn) { - xml->xml_attrs.length = i; - goto fail; - } - - /* - * Enforce "Well-formedness constraint: Unique Att Spec", part 2: - * this time checking local name and namespace URI. - */ - for (j = 0; j < i; j++) { - attrj = XMLARRAY_MEMBER(&xml->xml_attrs, j, JSXML); - attrjqn = attrj->name; - if (EqualStrings(attrjqn->getNameURI(), qn->getNameURI()) && - EqualStrings(attrjqn->getQNameLocalName(), qn->getQNameLocalName())) { - Value v = StringValue(pn2->pn_atom); - JSAutoByteString bytes; - if (js_ValueToPrintable(cx, v, &bytes)) - parser->reportError(pn2, JSMSG_DUPLICATE_XML_ATTR, bytes.ptr()); - goto fail; - } - } - - pn2 = pn2->pn_next; - JS_ASSERT(pn2); - JS_ASSERT(pn2->isKind(PNK_XMLATTR)); - - attr = js_NewXML(cx, JSXML_CLASS_ATTRIBUTE); - if (!attr) - goto fail; - - XMLARRAY_SET_MEMBER(&xml->xml_attrs, i, attr); - attr->parent = xml; - attr->name = qn; - attr->xml_value = pn2->pn_atom; - } - - /* Point tag closes its own namespace scope. */ - if (pn->isKind(PNK_XMLPTAGC)) - XMLARRAY_TRUNCATE(cx, inScopeNSes, length); - break; - - case PNK_XMLSPACE: - case PNK_XMLTEXT: - case PNK_XMLCDATA: - case PNK_XMLCOMMENT: - case PNK_XMLPI: - str = pn->pn_atom; - qn = NULL; - if (pn->isKind(PNK_XMLCOMMENT)) { - if (flags & XSF_IGNORE_COMMENTS) - goto skip_child; - xml_class = JSXML_CLASS_COMMENT; - } else if (pn->isKind(PNK_XMLPI)) { - XMLProcessingInstruction &pi = pn->as(); - if (IS_XML(str)) { - Value v = StringValue(str); - JSAutoByteString bytes; - if (js_ValueToPrintable(cx, v, &bytes)) - parser->reportError(&pi, JSMSG_RESERVED_ID, bytes.ptr()); - goto fail; - } - - if (flags & XSF_IGNORE_PROCESSING_INSTRUCTIONS) - goto skip_child; - - qn = ParseNodeToQName(parser, &pi, inScopeNSes, JS_FALSE); - if (!qn) - goto fail; - - str = pi.data(); - xml_class = JSXML_CLASS_PROCESSING_INSTRUCTION; - } else { - /* CDATA section content, or element text. */ - xml_class = JSXML_CLASS_TEXT; - } - - xml = js_NewXML(cx, xml_class); - if (!xml) - goto fail; - xml->name = qn; - if (pn->isKind(PNK_XMLSPACE)) - xml->xml_flags |= XMLF_WHITESPACE_TEXT; - xml->xml_value = str; - break; - - default: - goto syntax; - } - - return xml; - -skip_child: - return PN2X_SKIP_CHILD; - -#undef PN2X_SKIP_CHILD - -syntax: - parser->reportError(pn, JSMSG_BAD_XML_MARKUP); -fail: - return NULL; -} - -/* - * XML helper, object-ops, and library functions. We start with the helpers, - * in ECMA-357 order, but merging XML (9.1) and XMLList (9.2) helpers. - */ -static JSBool -GetXMLSetting(JSContext *cx, const char *name, jsval *vp) -{ - RootedValue v(cx); - if (!js_FindClassObject(cx, JSProto_XML, &v)) - return JS_FALSE; - if (v.get().isPrimitive() || !v.get().toObject().isFunction()) { - *vp = JSVAL_VOID; - return JS_TRUE; - } - RootedObject obj(cx, &v.get().toObject()); - return JS_GetProperty(cx, obj, name, vp); -} - -static JSBool -GetBooleanXMLSetting(JSContext *cx, const char *name, JSBool *bp) -{ - jsval v; - - return GetXMLSetting(cx, name, &v) && JS_ValueToBoolean(cx, v, bp); -} - -static JSBool -GetUint32XMLSetting(JSContext *cx, const char *name, uint32_t *uip) -{ - jsval v; - - return GetXMLSetting(cx, name, &v) && JS_ValueToECMAUint32(cx, v, uip); -} - -static JSBool -GetXMLSettingFlags(JSContext *cx, unsigned *flagsp) -{ - JSBool flag[4]; - - 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 JSObject * -GetCurrentScopeChain(JSContext *cx) -{ - if (cx->hasfp() && cx->fp()->scopeChain()->compartment() == cx->compartment) - return cx->fp()->scopeChain(); - return cx->global(); -} - -static JSXML * -ParseXMLSource(JSContext *cx, HandleString src) -{ - jsval nsval; - JSLinearString *uri; - size_t urilen, srclen, length, offset, dstlen; - jschar *chars; - const jschar *srcp, *endp; - JSXML *xml; - const char *filename; - unsigned lineno; - JSOp op; - - static const char prefix[] = ""; - static const char suffix[] = ""; - -#define constrlen(constr) (sizeof(constr) - 1) - - if (!js_GetDefaultXMLNamespace(cx, &nsval)) - return NULL; - uri = JSVAL_TO_OBJECT(nsval)->getNameURI(); - uri = js_EscapeAttributeValue(cx, uri, JS_FALSE); - if (!uri) - return NULL; - - urilen = uri->length(); - srclen = src->length(); - length = constrlen(prefix) + urilen + constrlen(middle) + srclen + - constrlen(suffix); - - chars = cx->pod_malloc(length + 1); - if (!chars) - return NULL; - - dstlen = length; - InflateStringToBuffer(cx, prefix, constrlen(prefix), chars, &dstlen); - offset = dstlen; - js_strncpy(chars + offset, uri->chars(), urilen); - offset += urilen; - dstlen = length - offset + 1; - InflateStringToBuffer(cx, middle, constrlen(middle), chars + offset, &dstlen); - offset += dstlen; - srcp = src->getChars(cx); - if (!srcp) { - js_free(chars); - return NULL; - } - js_strncpy(chars + offset, srcp, srclen); - offset += srclen; - dstlen = length - offset + 1; - InflateStringToBuffer(cx, suffix, constrlen(suffix), chars + offset, &dstlen); - chars [offset + dstlen] = 0; - - xml = NULL; - filename = NULL; - lineno = 1; - ScriptFrameIter i(cx); - if (!i.done()) { - op = (JSOp) *i.pc(); - if (op == JSOP_TOXML || op == JSOP_TOXMLLIST) { - filename = i.script()->filename; - RootedScript script(cx, i.script()); - lineno = PCToLineNumber(script, i.pc()); - for (endp = srcp + srclen; srcp < endp; srcp++) { - if (*srcp == '\n') - --lineno; - } - } - } - - { - CompileOptions options(cx); - options.setFileAndLine(filename, lineno); - Parser parser(cx, options, StableCharPtr(chars, length), length, /* foldConstants = */ true); - if (parser.init()) { - JSObject *scopeChain = GetCurrentScopeChain(cx); - if (!scopeChain) { - js_free(chars); - return NULL; - } - - ParseNode *pn = parser.parseXMLText(scopeChain, false); - unsigned flags; - if (pn && GetXMLSettingFlags(cx, &flags)) { - AutoNamespaceArray namespaces(cx); - if (namespaces.array.setCapacity(cx, 1)) - xml = ParseNodeToXML(&parser, pn, &namespaces.array, flags); - } - } - } - - js_free(chars); - return xml; - -#undef constrlen -} - -/* - * Errata in 10.3.1, 10.4.1, and 13.4.4.24 (at least). - * - * 10.3.1 Step 6(a) fails to NOTE that implementations that do not enforce - * the constraint: - * - * for all x belonging to XML: - * x.[[InScopeNamespaces]] >= x.[[Parent]].[[InScopeNamespaces]] - * - * must union x.[[InScopeNamespaces]] into x[0].[[InScopeNamespaces]] here - * (in new sub-step 6(a), renumbering the others to (b) and (c)). - * - * Same goes for 10.4.1 Step 7(a). - * - * In order for XML.prototype.namespaceDeclarations() to work correctly, the - * default namespace thereby unioned into x[0].[[InScopeNamespaces]] must be - * flagged as not declared, so that 13.4.4.24 Step 8(a) can exclude all such - * undeclared namespaces associated with x not belonging to ancestorNS. - */ -static JSXML * -OrphanXMLChild(JSContext *cx, JSXML *xml, uint32_t i) -{ - JSObject *ns; - - ns = XMLARRAY_MEMBER(&xml->xml_namespaces, 0, JSObject); - xml = XMLARRAY_MEMBER(&xml->xml_kids, i, JSXML); - if (!ns || !xml) - return xml; - if (xml->xml_class == JSXML_CLASS_ELEMENT) { - if (!XMLARRAY_APPEND(cx, &xml->xml_namespaces, ns)) - return NULL; - ns->setNamespaceDeclared(JSVAL_VOID); - } - xml->parent = NULL; - return xml; -} - -static JSObject * -ToXML(JSContext *cx, jsval v) -{ - JSObject *obj; - JSXML *xml; - Class *clasp; - RootedString str(cx); - uint32_t length; - - if (JSVAL_IS_PRIMITIVE(v)) { - if (JSVAL_IS_NULL(v) || JSVAL_IS_VOID(v)) - goto bad; - } else { - obj = JSVAL_TO_OBJECT(v); - if (obj->isXML()) { - xml = (JSXML *) obj->getPrivate(); - if (xml->xml_class == JSXML_CLASS_LIST) { - if (xml->xml_kids.length != 1) - goto bad; - xml = XMLARRAY_MEMBER(&xml->xml_kids, 0, JSXML); - if (xml) { - JS_ASSERT(xml->xml_class != JSXML_CLASS_LIST); - return js_GetXMLObject(cx, xml); - } - } - return obj; - } - - clasp = obj->getClass(); - if (clasp != &StringClass && - clasp != &NumberClass && - clasp != &BooleanClass) { - goto bad; - } - } - - str = ToString(cx, v); - if (!str) - return NULL; - if (str->empty()) { - length = 0; -#ifdef __GNUC__ /* suppress bogus gcc warnings */ - xml = NULL; -#endif - } else { - xml = ParseXMLSource(cx, str); - if (!xml) - return NULL; - length = JSXML_LENGTH(xml); - } - - if (length == 0) { - obj = js_NewXMLObject(cx, JSXML_CLASS_TEXT); - if (!obj) - return NULL; - } else if (length == 1) { - xml = OrphanXMLChild(cx, xml, 0); - if (!xml) - return NULL; - obj = js_GetXMLObject(cx, xml); - if (!obj) - return NULL; - } else { - JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_SYNTAX_ERROR); - return NULL; - } - return obj; - -bad: - RootedValue val(cx, v); - js_ReportValueError(cx, JSMSG_BAD_XML_CONVERSION, - JSDVG_IGNORE_STACK, val, NullPtr()); - return NULL; -} - -static JSBool -Append(JSContext *cx, JSXML *list, JSXML *kid); - -static JSObject * -ToXMLList(JSContext *cx, jsval v) -{ - JSObject *obj, *listobj; - JSXML *xml, *list, *kid; - Class *clasp; - RootedString str(cx); - uint32_t i, length; - - if (JSVAL_IS_PRIMITIVE(v)) { - if (JSVAL_IS_NULL(v) || JSVAL_IS_VOID(v)) - goto bad; - } else { - obj = JSVAL_TO_OBJECT(v); - if (obj->isXML()) { - xml = (JSXML *) obj->getPrivate(); - if (xml->xml_class != JSXML_CLASS_LIST) { - listobj = js_NewXMLObject(cx, JSXML_CLASS_LIST); - if (!listobj) - return NULL; - list = (JSXML *) listobj->getPrivate(); - if (!Append(cx, list, xml)) - return NULL; - return listobj; - } - return obj; - } - - clasp = obj->getClass(); - if (clasp != &StringClass && - clasp != &NumberClass && - clasp != &BooleanClass) { - goto bad; - } - } - - str = ToString(cx, v); - if (!str) - return NULL; - if (str->empty()) { - xml = NULL; - length = 0; - } else { - xml = ParseXMLSource(cx, str); - if (!xml) - return NULL; - length = JSXML_LENGTH(xml); - } - - listobj = js_NewXMLObject(cx, JSXML_CLASS_LIST); - if (listobj) { - list = (JSXML *) listobj->getPrivate(); - for (i = 0; i < length; i++) { - kid = OrphanXMLChild(cx, xml, i); - if (!kid || !Append(cx, list, kid)) { - listobj = NULL; - break; - } - } - } - - return listobj; - -bad: - RootedValue val(cx, v); - js_ReportValueError(cx, JSMSG_BAD_XMLLIST_CONVERSION, - JSDVG_IGNORE_STACK, val, NullPtr()); - return NULL; -} - -/* - * ECMA-357 10.2.1 Steps 5-7 pulled out as common subroutines of XMLToXMLString - * and their library-public js_* counterparts. The guts of MakeXMLCDataString, - * MakeXMLCommentString, and MakeXMLPIString are further factored into a common - * MakeXMLSpecialString subroutine. - * - * These functions mutate sb, leaving it empty. - */ -static JSFlatString * -MakeXMLSpecialString(JSContext *cx, StringBuffer &sb, - JSString *str, JSString *str2, - const jschar *prefix, size_t prefixlength, - const jschar *suffix, size_t suffixlength) -{ - if (!sb.append(prefix, prefixlength) || !sb.append(str)) - return NULL; - if (str2 && !str2->empty()) { - if (!sb.append(' ') || !sb.append(str2)) - return NULL; - } - if (!sb.append(suffix, suffixlength)) - return NULL; - - return sb.finishString(); -} - -static JSFlatString * -MakeXMLCDATAString(JSContext *cx, StringBuffer &sb, JSString *str) -{ - static const jschar cdata_prefix_ucNstr[] = {'<', '!', '[', - 'C', 'D', 'A', 'T', 'A', - '['}; - static const jschar cdata_suffix_ucNstr[] = {']', ']', '>'}; - - return MakeXMLSpecialString(cx, sb, str, NULL, - cdata_prefix_ucNstr, 9, - cdata_suffix_ucNstr, 3); -} - -static JSFlatString * -MakeXMLCommentString(JSContext *cx, StringBuffer &sb, JSString *str) -{ - static const jschar comment_prefix_ucNstr[] = {'<', '!', '-', '-'}; - static const jschar comment_suffix_ucNstr[] = {'-', '-', '>'}; - - return MakeXMLSpecialString(cx, sb, str, NULL, - comment_prefix_ucNstr, 4, - comment_suffix_ucNstr, 3); -} - -static JSFlatString * -MakeXMLPIString(JSContext *cx, StringBuffer &sb, JSString *name, - JSString *value) -{ - static const jschar pi_prefix_ucNstr[] = {'<', '?'}; - static const jschar pi_suffix_ucNstr[] = {'?', '>'}; - - return MakeXMLSpecialString(cx, sb, name, value, - pi_prefix_ucNstr, 2, - pi_suffix_ucNstr, 2); -} - -/* - * ECMA-357 10.2.1.2 EscapeAttributeValue helper method. - * - * This function appends the output into the supplied string buffer. - */ -static bool -EscapeAttributeValueBuffer(JSContext *cx, StringBuffer &sb, JSString *str, JSBool quote) -{ - size_t length = str->length(); - const jschar *start = str->getChars(cx); - if (!start) - return false; - - if (quote && !sb.append('"')) - return false; - - for (const jschar *cp = start, *end = start + length; cp != end; ++cp) { - jschar c = *cp; - switch (c) { - case '"': - if (!sb.append(js_quot_entity_str)) - return false; - break; - case '<': - if (!sb.append(js_lt_entity_str)) - return false; - break; - case '&': - if (!sb.append(js_amp_entity_str)) - return false; - break; - case '\n': - if (!sb.append(" ")) - return false; - break; - case '\r': - if (!sb.append(" ")) - return false; - break; - case '\t': - if (!sb.append(" ")) - return false; - break; - default: - if (!sb.append(c)) - return false; - } - } - - if (quote && !sb.append('"')) - return false; - - return true; -} - -/* - * ECMA-357 10.2.1.2 EscapeAttributeValue helper method. - * - * This function mutates sb, leaving it empty. - */ -static JSFlatString * -EscapeAttributeValue(JSContext *cx, StringBuffer &sb, JSString *str, JSBool quote) -{ - if (!EscapeAttributeValueBuffer(cx, sb, str, quote)) - return NULL; - return sb.finishString(); -} - -/* - * ECMA-357 10.2.1 17(d-g) pulled out into a common subroutine that appends - * equals, a double quote, an attribute value, and a closing double quote. - */ -static bool -AppendAttributeValue(JSContext *cx, StringBuffer &sb, JSString *valstr) -{ - if (!sb.append('=')) - return false; - return EscapeAttributeValueBuffer(cx, sb, valstr, JS_TRUE); -} - -/* - * ECMA-357 10.2.1.1 EscapeElementValue helper method. - - * These functions mutate sb, leaving it empty. - */ -static JSFlatString * -EscapeElementValue(JSContext *cx, StringBuffer &sb, JSString *str, uint32_t toSourceFlag) -{ - size_t length = str->length(); - const jschar *start = str->getChars(cx); - if (!start) - return NULL; - - for (const jschar *cp = start, *end = start + length; cp != end; ++cp) { - jschar c = *cp; - switch (*cp) { - case '<': - if (!sb.append(js_lt_entity_str)) - return NULL; - break; - case '>': - if (!sb.append(js_gt_entity_str)) - return NULL; - break; - case '&': - if (!sb.append(js_amp_entity_str)) - return NULL; - break; - case '{': - /* - * If EscapeElementValue is called by toSource/uneval, we also need - * to escape '{'. See bug 463360. - */ - if (toSourceFlag) { - if (!sb.append(js_leftcurly_entity_str)) - return NULL; - break; - } - /* FALL THROUGH */ - default: - if (!sb.append(c)) - return NULL; - } - } - return sb.finishString(); -} - -/* 13.3.5.4 [[GetNamespace]]([InScopeNamespaces]) */ -static JSObject * -GetNamespace(JSContext *cx, JSObject *qn, const JSXMLArray *inScopeNSes) -{ - JSLinearString *uri, *prefix, *nsprefix; - JSObject *match, *ns; - uint32_t i, n; - jsval argv[2]; - - uri = qn->getNameURI(); - prefix = qn->getNamePrefix(); - JS_ASSERT(uri); - if (!uri) { - JSAutoByteString bytes; - const char *s = !prefix ? - js_undefined_str - : js_ValueToPrintable(cx, StringValue(prefix), &bytes); - if (s) - JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_BAD_XML_NAMESPACE, s); - return NULL; - } - - /* Look for a matching namespace in inScopeNSes, if provided. */ - match = NULL; - if (inScopeNSes) { - for (i = 0, n = inScopeNSes->length; i < n; i++) { - ns = XMLARRAY_MEMBER(inScopeNSes, i, JSObject); - if (!ns) - continue; - - /* - * Erratum, very tricky, and not specified in ECMA-357 13.3.5.4: - * If we preserve prefixes, we must match null prefix against - * an empty prefix of ns, in order to avoid generating redundant - * prefixed and default namespaces for cases such as: - * - * x = - * print(x.toXMLString()); - * - * Per 10.3.2.1, the namespace attribute in t has an empty string - * prefix (*not* a null prefix), per 10.3.2.1 Step 6(h)(i)(1): - * - * 1. If the [local name] property of a is "xmlns" - * a. Map ns.prefix to the empty string - * - * But t's name has a null prefix in this implementation, meaning - * *undefined*, per 10.3.2.1 Step 6(c)'s NOTE (which refers to - * the http://www.w3.org/TR/xml-infoset/ spec, item 2.2.3, without - * saying how "no value" maps to an ECMA-357 value -- but it must - * map to the *undefined* prefix value). - * - * Since "" != undefined (or null, in the current implementation) - * the ECMA-357 spec will fail to match in [[GetNamespace]] called - * on t with argument {} U {(prefix="", uri="http://foo.com")}. - * This spec bug leads to ToXMLString results that duplicate the - * declared namespace. - */ - if (EqualStrings(ns->getNameURI(), uri)) { - nsprefix = ns->getNamePrefix(); - if (nsprefix == prefix || - ((nsprefix && prefix) - ? EqualStrings(nsprefix, prefix) - : (nsprefix ? nsprefix : prefix)->empty())) { - match = ns; - break; - } - } - } - } - - /* If we didn't match, make a new namespace from qn. */ - if (!match) { - argv[0] = prefix ? STRING_TO_JSVAL(prefix) : JSVAL_VOID; - argv[1] = STRING_TO_JSVAL(uri); - ns = ConstructObjectWithArguments(cx, &NamespaceClass, 2, argv); - if (!ns) - return NULL; - match = ns; - } - return match; -} - -static JSLinearString * -GeneratePrefix(JSContext *cx, JSLinearString *uri, JSXMLArray *decls) -{ - const jschar *cp, *start, *end; - size_t length, newlength, offset; - uint32_t i, n, m, serial; - jschar *bp, *dp; - JSBool done; - JSObject *ns; - JSLinearString *nsprefix, *prefix; - - JS_ASSERT(!uri->empty()); - - /* - * If there are no *declared* namespaces, skip all collision detection and - * return a short prefix quickly; an example of such a situation: - * - * var x = ; - * var n = new Namespace("http://example.com/"); - * x.@n::att = "val"; - * x.toXMLString(); - * - * This is necessary for various log10 uses below to be valid. - */ - if (decls->length == 0) - return js_NewStringCopyZ(cx, "a"); - - /* - * Try peeling off the last filename suffix or pathname component till - * we have a valid XML name. This heuristic will prefer "xul" given - * ".../there.is.only.xul", "xbl" given ".../xbl", and "xbl2" given any - * likely URI of the form ".../xbl2/2005". - */ - start = uri->chars(); - end = start + uri->length(); - cp = end; - while (--cp > start) { - if (*cp == '.' || *cp == '/' || *cp == ':') { - ++cp; - length = end - cp; - if (IsXMLName(cp, length) && !STARTS_WITH_XML(cp, length)) - break; - end = --cp; - } - } - length = end - cp; - - /* - * If the namespace consisted only of non-XML names or names that begin - * case-insensitively with "xml", arbitrarily create a prefix consisting - * of 'a's of size length (allowing dp-calculating code to work with or - * without this branch executing) plus the space for storing a hyphen and - * the serial number (avoiding reallocation if a collision happens). - */ - bp = (jschar *) cp; - newlength = length; - if (STARTS_WITH_XML(cp, length) || !IsXMLName(cp, length)) { - newlength = length + 2 + (size_t) log10((double) decls->length); - bp = cx->pod_malloc(newlength + 1); - if (!bp) - return NULL; - - bp[newlength] = 0; - for (i = 0; i < newlength; i++) - bp[i] = 'a'; - } - - /* - * Now search through decls looking for a collision. If we collide with - * an existing prefix, start tacking on a hyphen and a serial number. - */ - serial = 0; - do { - done = JS_TRUE; - for (i = 0, n = decls->length; i < n; i++) { - ns = XMLARRAY_MEMBER(decls, i, JSObject); - if (ns && (nsprefix = ns->getNamePrefix()) && - nsprefix->length() == newlength && - !memcmp(nsprefix->chars(), bp, - newlength * sizeof(jschar))) { - if (bp == cp) { - newlength = length + 2 + (size_t) log10((double) n); - bp = cx->pod_malloc(newlength + 1); - if (!bp) - return NULL; - js_strncpy(bp, cp, length); - } - - ++serial; - JS_ASSERT(serial <= n); - dp = bp + length + 2 + (size_t) log10((double) serial); - *dp = 0; - for (m = serial; m != 0; m /= 10) - *--dp = (jschar)('0' + m % 10); - *--dp = '-'; - JS_ASSERT(dp == bp + length); - - done = JS_FALSE; - break; - } - } - } while (!done); - - if (bp == cp) { - offset = cp - start; - prefix = js_NewDependentString(cx, uri, offset, length); - } else { - prefix = js_NewString(cx, bp, newlength); - if (!prefix) - js_free(bp); - } - return prefix; -} - -static JSBool -namespace_match(const JSObject *nsa, const JSObject *nsb) -{ - JSLinearString *prefixa, *prefixb = nsb->getNamePrefix(); - - if (prefixb) { - prefixa = nsa->getNamePrefix(); - return prefixa && EqualStrings(prefixa, prefixb); - } - return EqualStrings(nsa->getNameURI(), nsb->getNameURI()); -} - -/* ECMA-357 10.2.1 and 10.2.2 */ -#define TO_SOURCE_FLAG 0x80000000 - -static JSString * -XMLToXMLString(JSContext *cx, JSXML *xml, const JSXMLArray *ancestorNSes, - uint32_t indentLevel, JSBool pretty) -{ - JSBool indentKids; - StringBuffer sb(cx); - JSString *str; - JSLinearString *prefix, *nsuri; - uint32_t i, n, nextIndentLevel; - JSObject *ns, *ns2; - AutoNamespaceArray empty(cx), decls(cx), ancdecls(cx); - - if (pretty) { - if (!sb.appendN(' ', indentLevel & ~TO_SOURCE_FLAG)) - return NULL; - } - - str = NULL; - - switch (xml->xml_class) { - case JSXML_CLASS_TEXT: - /* Step 4. */ - if (pretty) { - str = ChompXMLWhitespace(cx, xml->xml_value); - if (!str) - return NULL; - } else { - str = xml->xml_value; - } - return EscapeElementValue(cx, sb, str, indentLevel & TO_SOURCE_FLAG); - - case JSXML_CLASS_ATTRIBUTE: - /* Step 5. */ - return EscapeAttributeValue(cx, sb, xml->xml_value, - (indentLevel & TO_SOURCE_FLAG) != 0); - - case JSXML_CLASS_COMMENT: - /* Step 6. */ - return MakeXMLCommentString(cx, sb, xml->xml_value); - - case JSXML_CLASS_PROCESSING_INSTRUCTION: - /* Step 7. */ - return MakeXMLPIString(cx, sb, xml->name->getQNameLocalName(), - xml->xml_value); - - case JSXML_CLASS_LIST: - /* ECMA-357 10.2.2. */ - { - JSXMLArrayCursor cursor(&xml->xml_kids); - i = 0; - while (JSXML *kid = cursor.getNext()) { - if (pretty && i != 0) { - if (!sb.append('\n')) - return NULL; - } - - JSString *kidstr = XMLToXMLString(cx, kid, ancestorNSes, indentLevel, pretty); - if (!kidstr || !sb.append(kidstr)) - return NULL; - ++i; - } - } - - if (sb.empty()) - return cx->runtime->emptyString; - return sb.finishString(); - - default:; - } - - /* ECMA-357 10.2.1 step 8 onward: handle ToXMLString on an XML element. */ - if (!ancestorNSes) { - // Ensure a namespace with empty strings exists in the initial array, - // otherwise every call to GetNamespace() when running toString() on - // an XML object with no namespace defined will create a new Namespace - // object on every call. - JSObject *emptyns = NewXMLNamespace(cx, cx->runtime->emptyString, cx->runtime->emptyString, JS_FALSE); - if (!emptyns || !XMLARRAY_APPEND(cx, &empty.array, emptyns)) - goto out; - ancestorNSes = &empty.array; - } - - /* Clone in-scope namespaces not in ancestorNSes into decls. */ - { - JSXMLArrayCursor cursor(&xml->xml_namespaces); - while ((ns = cursor.getNext()) != NULL) { - if (!IsDeclared(ns)) - continue; - if (!XMLARRAY_HAS_MEMBER(ancestorNSes, ns, namespace_identity)) { - /* NOTE: may want to exclude unused namespaces here. */ - ns2 = NewXMLNamespace(cx, ns->getNamePrefix(), ns->getNameURI(), JS_TRUE); - if (!ns2 || !XMLARRAY_APPEND(cx, &decls.array, ns2)) - goto out; - } - } - } - - /* - * Union ancestorNSes and decls into ancdecls. Note that ancdecls does - * not own its member references. In the spec, ancdecls has no name, but - * is always written out as (AncestorNamespaces U namespaceDeclarations). - */ - - if (!ancdecls.array.setCapacity(cx, ancestorNSes->length + decls.length())) - goto out; - for (i = 0, n = ancestorNSes->length; i < n; i++) { - ns2 = XMLARRAY_MEMBER(ancestorNSes, i, JSObject); - if (!ns2) - continue; - JS_ASSERT(!XMLARRAY_HAS_MEMBER(&decls.array, ns2, namespace_identity)); - if (!XMLARRAY_APPEND(cx, &ancdecls.array, ns2)) - goto out; - } - for (i = 0, n = decls.length(); i < n; i++) { - ns2 = XMLARRAY_MEMBER(&decls.array, i, JSObject); - if (!ns2) - continue; - JS_ASSERT(!XMLARRAY_HAS_MEMBER(&ancdecls.array, ns2, namespace_identity)); - if (!XMLARRAY_APPEND(cx, &ancdecls.array, ns2)) - goto out; - } - - /* Step 11, except we don't clone ns unless its prefix is undefined. */ - ns = GetNamespace(cx, xml->name, &ancdecls.array); - if (!ns) - goto out; - - /* Step 12 (NULL means *undefined* here), plus the deferred ns cloning. */ - prefix = ns->getNamePrefix(); - if (!prefix) { - /* - * Create a namespace prefix that isn't used by any member of decls. - * Assign the new prefix to a copy of ns. Flag this namespace as if - * it were declared, for assertion-testing's sake later below. - * - * Erratum: if prefix and xml->name are both null (*undefined* in - * ECMA-357), we know that xml was named using the default namespace - * (proof: see GetNamespace and the Namespace constructor called with - * two arguments). So we ought not generate a new prefix here, when - * we can declare ns as the default namespace for xml. - * - * This helps descendants inherit the namespace instead of redundantly - * redeclaring it with generated prefixes in each descendant. - */ - nsuri = ns->getNameURI(); - if (!xml->name->getNamePrefix()) { - prefix = cx->runtime->emptyString; - } else { - prefix = GeneratePrefix(cx, nsuri, &ancdecls.array); - if (!prefix) - goto out; - } - ns = NewXMLNamespace(cx, prefix, nsuri, JS_TRUE); - if (!ns) - goto out; - - /* - * If the xml->name was unprefixed, we must remove any declared default - * namespace from decls before appending ns. How can you get a default - * namespace in decls that doesn't match the one from name? Apparently - * by calling x.setNamespace(ns) where ns has no prefix. The other way - * to fix this is to update x's in-scope namespaces when setNamespace - * is called, but that's not specified by ECMA-357. - * - * Likely Erratum here, depending on whether the lack of update to x's - * in-scope namespace in XML.prototype.setNamespace (13.4.4.36) is an - * erratum or not. Note that changing setNamespace to update the list - * of in-scope namespaces will change x.namespaceDeclarations(). - */ - if (prefix->empty()) { - i = XMLArrayFindMember(&decls.array, ns, namespace_match); - if (i != XML_NOT_FOUND) - XMLArrayDelete(cx, &decls.array, i, JS_TRUE); - } - - /* - * In the spec, ancdecls has no name, but is always written out as - * (AncestorNamespaces U namespaceDeclarations). Since we compute - * that union in ancdecls, any time we append a namespace strong - * ref to decls, we must also append a weak ref to ancdecls. Order - * matters here: code at label out: releases strong refs in decls. - */ - if (!XMLARRAY_APPEND(cx, &ancdecls.array, ns) || - !XMLARRAY_APPEND(cx, &decls.array, ns)) { - goto out; - } - } - - /* Format the element or point-tag into sb. */ - if (!sb.append('<')) - goto out; - - if (!prefix->empty()) { - if (!sb.append(prefix) || !sb.append(':')) - goto out; - } - if (!sb.append(xml->name->getQNameLocalName())) - goto out; - - /* - * Step 16 makes a union to avoid writing two loops in step 17, to share - * common attribute value appending spec-code. We prefer two loops for - * faster code and less data overhead. - */ - - /* Step 17(b): append attributes. */ - { - JSXMLArrayCursor cursor(&xml->xml_attrs); - while (JSXML *attr = cursor.getNext()) { - if (!sb.append(' ')) - goto out; - ns2 = GetNamespace(cx, attr->name, &ancdecls.array); - if (!ns2) - goto out; - - /* 17(b)(ii): NULL means *undefined* here. */ - prefix = ns2->getNamePrefix(); - if (!prefix) { - prefix = GeneratePrefix(cx, ns2->getNameURI(), &ancdecls.array); - if (!prefix) - goto out; - - /* Again, we avoid copying ns2 until we know it's prefix-less. */ - ns2 = NewXMLNamespace(cx, prefix, ns2->getNameURI(), JS_TRUE); - if (!ns2) - goto out; - - /* - * In the spec, ancdecls has no name, but is always written out as - * (AncestorNamespaces U namespaceDeclarations). Since we compute - * that union in ancdecls, any time we append a namespace strong - * ref to decls, we must also append a weak ref to ancdecls. Order - * matters here: code at label out: releases strong refs in decls. - */ - if (!XMLARRAY_APPEND(cx, &ancdecls.array, ns2) || - !XMLARRAY_APPEND(cx, &decls.array, ns2)) { - goto out; - } - } - - /* 17(b)(iii). */ - if (!prefix->empty()) { - if (!sb.append(prefix) || !sb.append(':')) - goto out; - } - - /* 17(b)(iv). */ - if (!sb.append(attr->name->getQNameLocalName())) - goto out; - - /* 17(d-g). */ - if (!AppendAttributeValue(cx, sb, attr->xml_value)) - goto out; - } - } - - /* Step 17(c): append XML namespace declarations. */ - { - JSXMLArrayCursor cursor(&decls.array); - while (JSObject *ns3 = cursor.getNext()) { - JS_ASSERT(IsDeclared(ns3)); - - if (!sb.append(" xmlns")) - goto out; - - /* 17(c)(ii): NULL means *undefined* here. */ - prefix = ns3->getNamePrefix(); - if (!prefix) { - prefix = GeneratePrefix(cx, ns3->getNameURI(), &ancdecls.array); - if (!prefix) - goto out; - ns3->setNamePrefix(prefix); - } - - /* 17(c)(iii). */ - if (!prefix->empty()) { - if (!sb.append(':') || !sb.append(prefix)) - goto out; - } - - /* 17(d-g). */ - if (!AppendAttributeValue(cx, sb, ns3->getNameURI())) - goto out; - } - } - - /* Step 18: handle point tags. */ - n = xml->xml_kids.length; - if (n == 0) { - if (!sb.append("/>")) - goto out; - } else { - /* Steps 19 through 25: handle element content, and open the end-tag. */ - if (!sb.append('>')) - goto out; - { - JSXML *kid; - indentKids = n > 1 || - (n == 1 && - (kid = XMLARRAY_MEMBER(&xml->xml_kids, 0, JSXML)) && - kid->xml_class != JSXML_CLASS_TEXT); - } - - if (pretty && indentKids) { - if (!GetUint32XMLSetting(cx, js_prettyIndent_str, &i)) - goto out; - nextIndentLevel = indentLevel + i; - } else { - nextIndentLevel = indentLevel & TO_SOURCE_FLAG; - } - - { - JSXMLArrayCursor cursor(&xml->xml_kids); - while (JSXML *kid = cursor.getNext()) { - if (pretty && indentKids) { - if (!sb.append('\n')) - goto out; - } - - JSString *kidstr = XMLToXMLString(cx, kid, &ancdecls.array, nextIndentLevel, pretty); - if (!kidstr) - goto out; - - if (!sb.append(kidstr)) - goto out; - } - } - - if (pretty && indentKids) { - if (!sb.append('\n') || - !sb.appendN(' ', indentLevel & ~TO_SOURCE_FLAG)) - goto out; - } - if (!sb.append("getNamePrefix(); - if (prefix && !prefix->empty()) { - if (!sb.append(prefix) || !sb.append(':')) - goto out; - } - - /* Step 27. */ - if (!sb.append(xml->name->getQNameLocalName()) || !sb.append('>')) - goto out; - } - - str = sb.finishString(); -out: - return str; -} - -/* ECMA-357 10.2 */ -static JSString * -ToXMLString(JSContext *cx, jsval v, uint32_t toSourceFlag) -{ - if (JSVAL_IS_NULL(v) || JSVAL_IS_VOID(v)) { - JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, - JSMSG_BAD_XML_CONVERSION, - JSVAL_IS_NULL(v) ? js_null_str : js_undefined_str); - return NULL; - } - - if (JSVAL_IS_BOOLEAN(v) || JSVAL_IS_NUMBER(v)) - return ToString(cx, v); - - if (JSVAL_IS_STRING(v)) { - StringBuffer sb(cx); - return EscapeElementValue(cx, sb, JSVAL_TO_STRING(v), toSourceFlag); - } - - JSObject *obj = JSVAL_TO_OBJECT(v); - if (!obj->isXML()) { - if (!ToPrimitive(cx, JSTYPE_STRING, &v)) - return NULL; - JSString *str = ToString(cx, v); - if (!str) - return NULL; - StringBuffer sb(cx); - return EscapeElementValue(cx, sb, str, toSourceFlag); - } - - JSBool pretty; - if (!GetBooleanXMLSetting(cx, js_prettyPrinting_str, &pretty)) - return NULL; - - /* Handle non-element cases in this switch, returning from each case. */ - JS::Anchor anch(obj); - JSXML *xml = reinterpret_cast(obj->getPrivate()); - return XMLToXMLString(cx, xml, NULL, toSourceFlag | 0, pretty); -} - -static JSObject * -ToAttributeName(JSContext *cx, jsval v) -{ - JSLinearString *uri, *prefix; - JSObject *obj; - Class *clasp; - JSObject *qn; - - JSAtom *name; - if (JSVAL_IS_STRING(v)) { - name = ToAtom(cx, v); - if (!name) - return NULL; - uri = prefix = cx->runtime->emptyString; - } else { - if (JSVAL_IS_PRIMITIVE(v)) { - RootedValue val(cx, v); - js_ReportValueError(cx, JSMSG_BAD_XML_ATTR_NAME, - JSDVG_IGNORE_STACK, val, NullPtr()); - return NULL; - } - - obj = JSVAL_TO_OBJECT(v); - clasp = obj->getClass(); - if (clasp == &AttributeNameClass) - return obj; - - if (clasp == &QNameClass) { - qn = obj; - uri = qn->getNameURI(); - prefix = qn->getNamePrefix(); - name = qn->getQNameLocalName(); - } else { - if (clasp == &AnyNameClass) { - name = cx->names().star; - } else { - name = ToAtom(cx, v); - if (!name) - return NULL; - } - uri = prefix = cx->runtime->emptyString; - } - } - - qn = NewXMLAttributeName(cx, uri, prefix, name); - if (!qn) - return NULL; - return qn; -} - -static void -ReportBadXMLName(JSContext *cx, const Value &idval) -{ - RootedValue val(cx, idval); - js_ReportValueError(cx, JSMSG_BAD_XML_NAME, JSDVG_IGNORE_STACK, val, NullPtr()); -} - -bool -js::GetLocalNameFromFunctionQName(JSObject *qn, JSAtom **namep, JSContext *cx) -{ - JSAtom *atom = cx->names().functionNamespaceURI; - JSLinearString *uri = qn->getNameURI(); - if (uri && (uri == atom || EqualStrings(uri, atom))) { - *namep = qn->getQNameLocalName(); - return true; - } - return false; -} - -bool -js_GetLocalNameFromFunctionQName(JSObject *obj, jsid *funidp, JSContext *cx) -{ - if (!obj->isQName()) - return false; - JSAtom *name; - if (GetLocalNameFromFunctionQName(obj, &name, cx)) { - *funidp = AtomToId(name); - return true; - } - return false; -} - -static JSObject * -ToXMLName(JSContext *cx, jsval v, jsid *funidp) -{ - JSAtom *atomizedName; - JSString *name; - JSObject *obj; - Class *clasp; - uint32_t index; - - if (JSVAL_IS_STRING(v)) { - name = JSVAL_TO_STRING(v); - } else { - if (JSVAL_IS_PRIMITIVE(v)) { - ReportBadXMLName(cx, v); - return NULL; - } - - obj = JSVAL_TO_OBJECT(v); - clasp = obj->getClass(); - if (clasp == &AttributeNameClass || clasp == &QNameClass) - goto out; - if (clasp == &AnyNameClass) { - name = cx->names().star; - goto construct; - } - name = ToStringSlow(cx, v); - if (!name) - return NULL; - } - - atomizedName = AtomizeString(cx, name); - if (!atomizedName) - return NULL; - - /* - * ECMA-357 10.6.1 step 1 seems to be incorrect. The spec says: - * - * 1. If ToString(ToNumber(P)) == ToString(P), throw a TypeError exception - * - * First, _P_ should be _s_, to refer to the given string. - * - * Second, why does ToXMLName applied to the string type throw TypeError - * only for numeric literals without any leading or trailing whitespace? - * - * If the idea is to reject uint32_t property names, then the check needs to - * be stricter, to exclude hexadecimal and floating point literals. - */ - if (js_IdIsIndex(AtomToId(atomizedName), &index)) - goto bad; - - if (*atomizedName->chars() == '@') { - name = js_NewDependentString(cx, name, 1, name->length() - 1); - if (!name) - return NULL; - *funidp = JSID_VOID; - return ToAttributeName(cx, STRING_TO_JSVAL(name)); - } - -construct: - v = STRING_TO_JSVAL(name); - obj = ConstructObjectWithArguments(cx, &QNameClass, 1, &v); - if (!obj) - return NULL; - -out: - JSAtom *localName; - *funidp = GetLocalNameFromFunctionQName(obj, &localName, cx) - ? AtomToId(localName) - : JSID_VOID; - return obj; - -bad: - JSAutoByteString bytes; - if (js_ValueToPrintable(cx, StringValue(name), &bytes)) - JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_BAD_XML_NAME, bytes.ptr()); - return NULL; -} - -/* ECMA-357 9.1.1.13 XML [[AddInScopeNamespace]]. */ -static JSBool -AddInScopeNamespace(JSContext *cx, JSXML *xml, JSObject *ns) -{ - JSLinearString *prefix, *prefix2; - JSObject *match, *ns2; - uint32_t i, n, m; - - if (xml->xml_class != JSXML_CLASS_ELEMENT) - return JS_TRUE; - - /* NULL means *undefined* here -- see ECMA-357 9.1.1.13 step 2. */ - prefix = ns->getNamePrefix(); - if (!prefix) { - match = NULL; - for (i = 0, n = xml->xml_namespaces.length; i < n; i++) { - ns2 = XMLARRAY_MEMBER(&xml->xml_namespaces, i, JSObject); - if (ns2 && EqualStrings(ns2->getNameURI(), ns->getNameURI())) { - match = ns2; - break; - } - } - if (!match && !XMLARRAY_ADD_MEMBER(cx, &xml->xml_namespaces, n, ns)) - return JS_FALSE; - } else { - if (prefix->empty() && xml->name->getNameURI()->empty()) - return JS_TRUE; - match = NULL; -#ifdef __GNUC__ /* suppress bogus gcc warnings */ - m = XML_NOT_FOUND; -#endif - for (i = 0, n = xml->xml_namespaces.length; i < n; i++) { - ns2 = XMLARRAY_MEMBER(&xml->xml_namespaces, i, JSObject); - if (ns2 && (prefix2 = ns2->getNamePrefix()) && - EqualStrings(prefix2, prefix)) { - match = ns2; - m = i; - break; - } - } - if (match && !EqualStrings(match->getNameURI(), ns->getNameURI())) { - ns2 = XMLARRAY_DELETE(cx, &xml->xml_namespaces, m, JS_TRUE, - JSObject); - JS_ASSERT(ns2 == match); - match->clearNamePrefix(); - if (!AddInScopeNamespace(cx, xml, match)) - return JS_FALSE; - } - if (!XMLARRAY_APPEND(cx, &xml->xml_namespaces, ns)) - return JS_FALSE; - } - - /* OPTION: enforce that descendants have superset namespaces. */ - return JS_TRUE; -} - -/* ECMA-357 9.2.1.6 XMLList [[Append]]. */ -static JSBool -Append(JSContext *cx, JSXML *list, JSXML *xml) -{ - JS_ASSERT(list->xml_class == JSXML_CLASS_LIST); - - uint32_t i = list->xml_kids.length; - if (xml->xml_class == JSXML_CLASS_LIST) { - list->xml_target = xml->xml_target; - list->xml_targetprop = xml->xml_targetprop; - uint32_t n = JSXML_LENGTH(xml); - if (!list->xml_kids.setCapacity(cx, i + n)) - return JS_FALSE; - for (uint32_t j = 0; j < n; j++) { - if (JSXML *kid = XMLARRAY_MEMBER(&xml->xml_kids, j, JSXML)) - XMLARRAY_SET_MEMBER(&list->xml_kids, i + j, kid); - } - return JS_TRUE; - } - - list->xml_target = xml->parent; - if (xml->xml_class == JSXML_CLASS_PROCESSING_INSTRUCTION) - list->xml_targetprop = NULL; - else - list->xml_targetprop = xml->name; - if (!XMLARRAY_ADD_MEMBER(cx, &list->xml_kids, i, xml)) - return JS_FALSE; - return JS_TRUE; -} - -/* ECMA-357 9.1.1.7 XML [[DeepCopy]] and 9.2.1.7 XMLList [[DeepCopy]]. */ -static JSXML * -DeepCopyInLRS(JSContext *cx, JSXML *xml, unsigned flags); - -static JSXML * -DeepCopy(JSContext *cx, JSXML *xml, JSObject *obj, unsigned flags) -{ - JSXML *copy; - - copy = DeepCopyInLRS(cx, xml, flags); - if (copy) { - if (obj) { - /* Caller provided the object for this copy, hook 'em up. */ - obj->setPrivateGCThing(copy); - copy->object = obj; - } else if (!js_GetXMLObject(cx, copy)) { - copy = NULL; - } - } - return copy; -} - -/* - * (i) We must be in a local root scope (InLRS). - * (ii) parent must have a rooted object. - * (iii) from's owning object must be locked if not thread-local. - */ -static JSBool -DeepCopySetInLRS(JSContext *cx, JSXMLArray *from, JSXMLArray *to, JSXML *parent, - unsigned flags) -{ - uint32_t j, n; - JSXML *kid2; - JSString *str; - - n = from->length; - if (!to->setCapacity(cx, n)) - return JS_FALSE; - - JSXMLArrayCursor cursor(from); - j = 0; - while (JSXML *kid = cursor.getNext()) { - if ((flags & XSF_IGNORE_COMMENTS) && - kid->xml_class == JSXML_CLASS_COMMENT) { - continue; - } - if ((flags & XSF_IGNORE_PROCESSING_INSTRUCTIONS) && - kid->xml_class == JSXML_CLASS_PROCESSING_INSTRUCTION) { - continue; - } - if ((flags & XSF_IGNORE_WHITESPACE) && - (kid->xml_flags & XMLF_WHITESPACE_TEXT)) { - continue; - } - kid2 = DeepCopyInLRS(cx, kid, flags); - if (!kid2) { - to->length = j; - return JS_FALSE; - } - - if ((flags & XSF_IGNORE_WHITESPACE) && - n > 1 && kid2->xml_class == JSXML_CLASS_TEXT) { - str = ChompXMLWhitespace(cx, kid2->xml_value); - if (!str) { - to->length = j; - return JS_FALSE; - } - kid2->xml_value = str; - } - - XMLARRAY_SET_MEMBER(to, j, kid2); - ++j; - if (parent->xml_class != JSXML_CLASS_LIST) - kid2->parent = parent; - } - - if (j < n) - to->trim(); - return JS_TRUE; -} - -static JSXML * -DeepCopyInLRS(JSContext *cx, JSXML *xml, unsigned flags) -{ - JSXML *copy; - JSObject *qn; - JSBool ok; - uint32_t i, n; - JSObject *ns, *ns2; - - JS_CHECK_RECURSION(cx, return NULL); - - copy = js_NewXML(cx, JSXMLClass(xml->xml_class)); - if (!copy) - return NULL; - qn = xml->name; - if (qn) { - qn = NewXMLQName(cx, qn->getNameURI(), qn->getNamePrefix(), qn->getQNameLocalName()); - if (!qn) { - ok = JS_FALSE; - goto out; - } - } - copy->name = qn; - copy->xml_flags = xml->xml_flags; - - if (JSXML_HAS_VALUE(xml)) { - copy->xml_value = xml->xml_value; - ok = JS_TRUE; - } else { - ok = DeepCopySetInLRS(cx, &xml->xml_kids, ©->xml_kids, copy, flags); - if (!ok) - goto out; - - if (xml->xml_class == JSXML_CLASS_LIST) { - copy->xml_target = xml->xml_target; - copy->xml_targetprop = xml->xml_targetprop; - } else { - n = xml->xml_namespaces.length; - ok = copy->xml_namespaces.setCapacity(cx, n); - if (!ok) - goto out; - for (i = 0; i < n; i++) { - ns = XMLARRAY_MEMBER(&xml->xml_namespaces, i, JSObject); - if (!ns) - continue; - ns2 = NewXMLNamespace(cx, ns->getNamePrefix(), ns->getNameURI(), - IsDeclared(ns)); - if (!ns2) { - copy->xml_namespaces.length = i; - ok = JS_FALSE; - goto out; - } - XMLARRAY_SET_MEMBER(©->xml_namespaces, i, ns2); - } - - ok = DeepCopySetInLRS(cx, &xml->xml_attrs, ©->xml_attrs, copy, - 0); - if (!ok) - goto out; - } - } - -out: - if (!ok) - return NULL; - return copy; -} - -/* ECMA-357 9.1.1.4 XML [[DeleteByIndex]]. */ -static void -DeleteByIndex(JSContext *cx, JSXML *xml, uint32_t index) -{ - JSXML *kid; - - if (JSXML_HAS_KIDS(xml) && index < xml->xml_kids.length) { - kid = XMLARRAY_MEMBER(&xml->xml_kids, index, JSXML); - if (kid) - kid->parent = NULL; - XMLArrayDelete(cx, &xml->xml_kids, index, JS_TRUE); - } -} - -typedef JSBool (*JSXMLNameMatcher)(JSObject *nameqn, JSXML *xml); - -static JSBool -MatchAttrName(JSObject *nameqn, JSXML *attr) -{ - JSObject *attrqn = attr->name; - JSLinearString *localName = nameqn->getQNameLocalName(); - JSLinearString *uri; - - return (IS_STAR(localName) || - EqualStrings(attrqn->getQNameLocalName(), localName)) && - (!(uri = nameqn->getNameURI()) || - EqualStrings(attrqn->getNameURI(), uri)); -} - -static JSBool -MatchElemName(JSObject *nameqn, JSXML *elem) -{ - JSLinearString *localName = nameqn->getQNameLocalName(); - JSLinearString *uri; - - return (IS_STAR(localName) || - (elem->xml_class == JSXML_CLASS_ELEMENT && - EqualStrings(elem->name->getQNameLocalName(), localName))) && - (!(uri = nameqn->getNameURI()) || - (elem->xml_class == JSXML_CLASS_ELEMENT && - EqualStrings(elem->name->getNameURI(), uri))); -} - -/* ECMA-357 9.1.1.8 XML [[Descendants]] and 9.2.1.8 XMLList [[Descendants]]. */ -static JSBool -DescendantsHelper(JSContext *cx, JSXML *xml, JSObject *nameqn, JSXML *list) -{ - uint32_t i, n; - JSXML *attr, *kid; - - JS_CHECK_RECURSION(cx, return JS_FALSE); - - if (xml->xml_class == JSXML_CLASS_ELEMENT && - nameqn->getClass() == &AttributeNameClass) { - for (i = 0, n = xml->xml_attrs.length; i < n; i++) { - attr = XMLARRAY_MEMBER(&xml->xml_attrs, i, JSXML); - if (attr && MatchAttrName(nameqn, attr)) { - if (!Append(cx, list, attr)) - return JS_FALSE; - } - } - } - - for (i = 0, n = JSXML_LENGTH(xml); i < n; i++) { - kid = XMLARRAY_MEMBER(&xml->xml_kids, i, JSXML); - if (!kid) - continue; - if (nameqn->getClass() != &AttributeNameClass && - MatchElemName(nameqn, kid)) { - if (!Append(cx, list, kid)) - return JS_FALSE; - } - if (!DescendantsHelper(cx, kid, nameqn, list)) - return JS_FALSE; - } - return JS_TRUE; -} - -static JSXML * -Descendants(JSContext *cx, JSXML *xml, jsval id) -{ - jsid funid; - JSObject *nameqn; - JSObject *listobj; - JSXML *list, *kid; - uint32_t i, n; - JSBool ok; - - nameqn = ToXMLName(cx, id, &funid); - if (!nameqn) - return NULL; - - listobj = js_NewXMLObject(cx, JSXML_CLASS_LIST); - if (!listobj) - return NULL; - list = (JSXML *) listobj->getPrivate(); - if (!JSID_IS_VOID(funid)) - return list; - - /* - * Protect nameqn's object and strings from GC by linking list to it - * temporarily. The newborn GC root for the last allocated object - * protects listobj, which protects list. Any other object allocations - * occurring beneath DescendantsHelper use local roots. - */ - list->name = nameqn; - if (xml->xml_class == JSXML_CLASS_LIST) { - ok = JS_TRUE; - for (i = 0, n = xml->xml_kids.length; i < n; i++) { - kid = XMLARRAY_MEMBER(&xml->xml_kids, i, JSXML); - if (kid && kid->xml_class == JSXML_CLASS_ELEMENT) { - ok = DescendantsHelper(cx, kid, nameqn, list); - if (!ok) - break; - } - } - } else { - ok = DescendantsHelper(cx, xml, nameqn, list); - } - if (!ok) - return NULL; - list->name = NULL; - return list; -} - -/* Recursive (JSXML *) parameterized version of Equals. */ -static JSBool -XMLEquals(JSContext *cx, JSXML *xml, JSXML *vxml, JSBool *bp) -{ - JSObject *qn, *vqn; - uint32_t i, j, n; - JSXML *kid, *vkid, *attr, *vattr; - JSObject *xobj, *vobj; - -retry: - if (xml->xml_class != vxml->xml_class) { - if (xml->xml_class == JSXML_CLASS_LIST && xml->xml_kids.length == 1) { - xml = XMLARRAY_MEMBER(&xml->xml_kids, 0, JSXML); - if (xml) - goto retry; - } - if (vxml->xml_class == JSXML_CLASS_LIST && vxml->xml_kids.length == 1) { - vxml = XMLARRAY_MEMBER(&vxml->xml_kids, 0, JSXML); - if (vxml) - goto retry; - } - *bp = JS_FALSE; - return JS_TRUE; - } - - qn = xml->name; - vqn = vxml->name; - if (qn) { - *bp = vqn && - EqualStrings(qn->getQNameLocalName(), vqn->getQNameLocalName()) && - EqualStrings(qn->getNameURI(), vqn->getNameURI()); - } else { - *bp = vqn == NULL; - } - if (!*bp) - return JS_TRUE; - - if (JSXML_HAS_VALUE(xml)) { - bool equal; - if (!EqualStrings(cx, xml->xml_value, vxml->xml_value, &equal)) - return JS_FALSE; - *bp = equal; - } else if (xml->xml_kids.length != vxml->xml_kids.length) { - *bp = JS_FALSE; - } else { - { - JSXMLArrayCursor cursor(&xml->xml_kids); - JSXMLArrayCursor vcursor(&vxml->xml_kids); - for (;;) { - kid = cursor.getNext(); - vkid = vcursor.getNext(); - if (!kid || !vkid) { - *bp = !kid && !vkid; - break; - } - xobj = js_GetXMLObject(cx, kid); - vobj = js_GetXMLObject(cx, vkid); - if (!xobj || !vobj || - !js_TestXMLEquality(cx, ObjectValue(*xobj), ObjectValue(*vobj), bp)) - return JS_FALSE; - if (!*bp) - break; - } - } - - if (*bp && xml->xml_class == JSXML_CLASS_ELEMENT) { - n = xml->xml_attrs.length; - if (n != vxml->xml_attrs.length) - *bp = JS_FALSE; - for (i = 0; *bp && i < n; i++) { - attr = XMLARRAY_MEMBER(&xml->xml_attrs, i, JSXML); - if (!attr) - continue; - j = XMLARRAY_FIND_MEMBER(&vxml->xml_attrs, attr, attr_identity); - if (j == XML_NOT_FOUND) { - *bp = JS_FALSE; - break; - } - vattr = XMLARRAY_MEMBER(&vxml->xml_attrs, j, JSXML); - if (!vattr) - continue; - bool equal; - if (!EqualStrings(cx, attr->xml_value, vattr->xml_value, &equal)) - return JS_FALSE; - *bp = equal; - } - } - } - - return JS_TRUE; -} - -/* ECMA-357 9.1.1.9 XML [[Equals]] and 9.2.1.9 XMLList [[Equals]]. */ -static JSBool -Equals(JSContext *cx, JSXML *xml, jsval v, JSBool *bp) -{ - JSObject *vobj; - JSXML *vxml; - - if (JSVAL_IS_PRIMITIVE(v)) { - *bp = JS_FALSE; - if (xml->xml_class == JSXML_CLASS_LIST) { - if (xml->xml_kids.length == 1) { - vxml = XMLARRAY_MEMBER(&xml->xml_kids, 0, JSXML); - if (!vxml) - return JS_TRUE; - vobj = js_GetXMLObject(cx, vxml); - if (!vobj) - return JS_FALSE; - return js_TestXMLEquality(cx, ObjectValue(*vobj), v, bp); - } - if (JSVAL_IS_VOID(v) && xml->xml_kids.length == 0) - *bp = JS_TRUE; - } - } else { - vobj = JSVAL_TO_OBJECT(v); - if (!vobj->isXML()) { - *bp = JS_FALSE; - } else { - vxml = (JSXML *) vobj->getPrivate(); - if (!XMLEquals(cx, xml, vxml, bp)) - return JS_FALSE; - } - } - return JS_TRUE; -} - -static JSBool -CheckCycle(JSContext *cx, JSXML *xml, JSXML *kid) -{ - JS_ASSERT(kid->xml_class != JSXML_CLASS_LIST); - - do { - if (xml == kid) { - JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, - JSMSG_CYCLIC_VALUE, js_XML_str); - return JS_FALSE; - } - } while ((xml = xml->parent) != NULL); - - return JS_TRUE; -} - -/* ECMA-357 9.1.1.11 XML [[Insert]]. */ -static JSBool -Insert(JSContext *cx, JSXML *xml, uint32_t i, jsval v) -{ - uint32_t j, n; - JSXML *vxml, *kid; - JSObject *vobj; - JSString *str; - - if (!JSXML_HAS_KIDS(xml)) - return JS_TRUE; - - n = 1; - vxml = NULL; - if (!JSVAL_IS_PRIMITIVE(v)) { - vobj = JSVAL_TO_OBJECT(v); - if (vobj->isXML()) { - vxml = (JSXML *) vobj->getPrivate(); - if (vxml->xml_class == JSXML_CLASS_LIST) { - n = vxml->xml_kids.length; - if (n == 0) - return JS_TRUE; - for (j = 0; j < n; j++) { - kid = XMLARRAY_MEMBER(&vxml->xml_kids, j, JSXML); - if (!kid) - continue; - if (!CheckCycle(cx, xml, kid)) - return JS_FALSE; - } - } else if (vxml->xml_class == JSXML_CLASS_ELEMENT) { - /* OPTION: enforce that descendants have superset namespaces. */ - if (!CheckCycle(cx, xml, vxml)) - return JS_FALSE; - } - } - } - if (!vxml) { - str = ToString(cx, v); - if (!str) - return JS_FALSE; - - vxml = js_NewXML(cx, JSXML_CLASS_TEXT); - if (!vxml) - return JS_FALSE; - vxml->xml_value = str; - } - - if (i > xml->xml_kids.length) - i = xml->xml_kids.length; - - if (!XMLArrayInsert(cx, &xml->xml_kids, i, n)) - return JS_FALSE; - - if (vxml->xml_class == JSXML_CLASS_LIST) { - for (j = 0; j < n; j++) { - kid = XMLARRAY_MEMBER(&vxml->xml_kids, j, JSXML); - if (!kid) - continue; - kid->parent = xml; - XMLARRAY_SET_MEMBER(&xml->xml_kids, i + j, kid); - - /* OPTION: enforce that descendants have superset namespaces. */ - } - } else { - vxml->parent = xml; - XMLARRAY_SET_MEMBER(&xml->xml_kids, i, vxml); - } - return JS_TRUE; -} - -/* ECMA-357 9.1.1.12 XML [[Replace]]. */ -static JSBool -Replace(JSContext *cx, JSXML *xml, uint32_t i, jsval v) -{ - uint32_t n; - JSXML *vxml, *kid; - JSObject *vobj; - JSString *str; - - if (!JSXML_HAS_KIDS(xml)) - return JS_TRUE; - - /* - * 9.1.1.12 - * [[Replace]] handles _i >= x.[[Length]]_ by incrementing _x.[[Length]_. - * It should therefore constrain callers to pass in _i <= x.[[Length]]_. - */ - n = xml->xml_kids.length; - if (i > n) - i = n; - - vxml = NULL; - if (!JSVAL_IS_PRIMITIVE(v)) { - vobj = JSVAL_TO_OBJECT(v); - if (vobj->isXML()) - vxml = (JSXML *) vobj->getPrivate(); - } - - switch (vxml ? JSXMLClass(vxml->xml_class) : JSXML_CLASS_LIMIT) { - case JSXML_CLASS_ELEMENT: - /* OPTION: enforce that descendants have superset namespaces. */ - if (!CheckCycle(cx, xml, vxml)) - return JS_FALSE; - case JSXML_CLASS_COMMENT: - case JSXML_CLASS_PROCESSING_INSTRUCTION: - case JSXML_CLASS_TEXT: - goto do_replace; - - case JSXML_CLASS_LIST: - if (i < n) - DeleteByIndex(cx, xml, i); - if (!Insert(cx, xml, i, v)) - return JS_FALSE; - break; - - default: - str = ToString(cx, v); - if (!str) - return JS_FALSE; - - vxml = js_NewXML(cx, JSXML_CLASS_TEXT); - if (!vxml) - return JS_FALSE; - vxml->xml_value = str; - - do_replace: - vxml->parent = xml; - if (i < n) { - kid = XMLARRAY_MEMBER(&xml->xml_kids, i, JSXML); - if (kid) - kid->parent = NULL; - } - if (!XMLARRAY_ADD_MEMBER(cx, &xml->xml_kids, i, vxml)) - return JS_FALSE; - break; - } - - return JS_TRUE; -} - -/* ECMA-357 9.1.1.3 XML [[Delete]], 9.2.1.3 XML [[Delete]] qname cases. */ -static void -DeleteNamedProperty(JSContext *cx, JSXML *xml, JSObject *nameqn, - JSBool attributes) -{ - JSXMLArray *array; - uint32_t index, deleteCount; - JSXML *kid; - JSXMLNameMatcher matcher; - - if (xml->xml_class == JSXML_CLASS_LIST) { - array = &xml->xml_kids; - for (index = 0; index < array->length; index++) { - kid = XMLARRAY_MEMBER(array, index, JSXML); - if (kid && kid->xml_class == JSXML_CLASS_ELEMENT) - DeleteNamedProperty(cx, kid, nameqn, attributes); - } - } else if (xml->xml_class == JSXML_CLASS_ELEMENT) { - if (attributes) { - array = &xml->xml_attrs; - matcher = MatchAttrName; - } else { - array = &xml->xml_kids; - matcher = MatchElemName; - } - deleteCount = 0; - for (index = 0; index < array->length; index++) { - kid = XMLARRAY_MEMBER(array, index, JSXML); - if (kid && matcher(nameqn, kid)) { - kid->parent = NULL; - XMLArrayDelete(cx, array, index, JS_FALSE); - ++deleteCount; - } else if (deleteCount != 0) { - XMLARRAY_SET_MEMBER(array, - index - deleteCount, - array->vector[index]); - } - } - array->length -= deleteCount; - } -} - -/* ECMA-357 9.2.1.3 index case. */ -static void -DeleteListElement(JSContext *cx, JSXML *xml, uint32_t index) -{ - JSXML *kid, *parent; - uint32_t kidIndex; - - JS_ASSERT(xml->xml_class == JSXML_CLASS_LIST); - - if (index < xml->xml_kids.length) { - kid = XMLARRAY_MEMBER(&xml->xml_kids, index, JSXML); - if (kid) { - parent = kid->parent; - if (parent) { - JS_ASSERT(parent != xml); - JS_ASSERT(JSXML_HAS_KIDS(parent)); - - if (kid->xml_class == JSXML_CLASS_ATTRIBUTE) { - DeleteNamedProperty(cx, parent, kid->name, JS_TRUE); - } else { - kidIndex = XMLARRAY_FIND_MEMBER(&parent->xml_kids, kid, - pointer_match); - JS_ASSERT(kidIndex != XML_NOT_FOUND); - DeleteByIndex(cx, parent, kidIndex); - } - } - XMLArrayDelete(cx, &xml->xml_kids, index, JS_TRUE); - } - } -} - -static JSBool -SyncInScopeNamespaces(JSContext *cx, JSXML *xml) -{ - JSXMLArray *nsarray; - uint32_t i, n; - JSObject *ns; - - nsarray = &xml->xml_namespaces; - while ((xml = xml->parent) != NULL) { - for (i = 0, n = xml->xml_namespaces.length; i < n; i++) { - ns = XMLARRAY_MEMBER(&xml->xml_namespaces, i, JSObject); - if (ns && !XMLARRAY_HAS_MEMBER(nsarray, ns, namespace_identity)) { - if (!XMLARRAY_APPEND(cx, nsarray, ns)) - return JS_FALSE; - } - } - } - return JS_TRUE; -} - -static JSBool -GetNamedProperty(JSContext *cx, JSXML *xml, JSObject* nameqn, JSXML *list) -{ - JSXMLArray *array; - JSXMLNameMatcher matcher; - JSBool attrs; - - if (xml->xml_class == JSXML_CLASS_LIST) { - JSXMLArrayCursor cursor(&xml->xml_kids); - while (JSXML *kid = cursor.getNext()) { - if (kid->xml_class == JSXML_CLASS_ELEMENT && - !GetNamedProperty(cx, kid, nameqn, list)) { - return JS_FALSE; - } - } - } else if (xml->xml_class == JSXML_CLASS_ELEMENT) { - attrs = (nameqn->getClass() == &AttributeNameClass); - if (attrs) { - array = &xml->xml_attrs; - matcher = MatchAttrName; - } else { - array = &xml->xml_kids; - matcher = MatchElemName; - } - - JSXMLArrayCursor cursor(array); - while (JSXML *kid = cursor.getNext()) { - if (matcher(nameqn, kid)) { - if (!attrs && - kid->xml_class == JSXML_CLASS_ELEMENT && - !SyncInScopeNamespaces(cx, kid)) { - return JS_FALSE; - } - if (!Append(cx, list, kid)) - return JS_FALSE; - } - } - } - - return JS_TRUE; -} - -/* ECMA-357 9.1.1.1 XML [[Get]] and 9.2.1.1 XMLList [[Get]]. */ -static JSBool -GetProperty(JSContext *cx, HandleObject obj, HandleId id, MutableHandleValue vp) -{ - JSXML *xml, *list, *kid; - uint32_t index; - JSObject *kidobj, *listobj; - JSObject *nameqn; - - if (!obj->isXML()) - return true; - xml = (JSXML *) obj->getPrivate(); - if (!xml) - return true; - - if (js_IdIsIndex(id, &index)) { - if (!JSXML_HAS_KIDS(xml)) { - vp.set((index == 0) ? OBJECT_TO_JSVAL(obj) : JSVAL_VOID); - } else { - /* - * ECMA-357 9.2.1.1 starts here. - * - * Erratum: 9.2 is not completely clear that indexed properties - * correspond to kids, but that's what it seems to say, and it's - * what any sane user would want. - */ - if (index < xml->xml_kids.length) { - kid = XMLARRAY_MEMBER(&xml->xml_kids, index, JSXML); - if (!kid) { - vp.setUndefined(); - return true; - } - kidobj = js_GetXMLObject(cx, kid); - if (!kidobj) - return false; - - vp.set(OBJECT_TO_JSVAL(kidobj)); - } else { - vp.setUndefined(); - } - } - return true; - } - - /* - * ECMA-357 9.2.1.1/9.1.1.1 qname case. - */ - RootedId funid(cx); - nameqn = ToXMLName(cx, IdToJsval(id), funid.address()); - if (!nameqn) - return false; - if (!JSID_IS_VOID(funid)) - return GetXMLFunction(cx, obj, funid, vp); - - jsval roots[2] = { OBJECT_TO_JSVAL(nameqn), JSVAL_NULL }; - AutoArrayRooter tvr(cx, ArrayLength(roots), roots); - - listobj = js_NewXMLObject(cx, JSXML_CLASS_LIST); - if (!listobj) - return false; - - roots[1] = OBJECT_TO_JSVAL(listobj); - - list = (JSXML *) listobj->getPrivate(); - if (!GetNamedProperty(cx, xml, nameqn, list)) - return false; - - /* - * Erratum: ECMA-357 9.1.1.1 misses that [[Append]] sets the - * given list's [[TargetProperty]] to the property that is being - * appended. This means that any use of the internal [[Get]] - * property returns a list which, when used by e.g. [[Insert]] - * duplicates the last element matched by id. See bug 336921. - */ - list->xml_target = xml; - list->xml_targetprop = nameqn; - vp.set(OBJECT_TO_JSVAL(listobj)); - return true; -} - -static JSXML * -CopyOnWrite(JSContext *cx, JSXML *xml, JSObject *obj) -{ - JS_ASSERT(xml->object != obj); - - xml = DeepCopy(cx, xml, obj, 0); - if (!xml) - return NULL; - - JS_ASSERT(xml->object == obj); - return xml; -} - -#define CHECK_COPY_ON_WRITE(cx,xml,obj) \ - (xml->object == obj ? xml : CopyOnWrite(cx, xml, obj)) - -static JSString * -KidToString(JSContext *cx, JSXML *xml, uint32_t index) -{ - JSXML *kid; - JSObject *kidobj; - - kid = XMLARRAY_MEMBER(&xml->xml_kids, index, JSXML); - if (!kid) - return cx->runtime->emptyString; - kidobj = js_GetXMLObject(cx, kid); - if (!kidobj) - return NULL; - return ToString(cx, ObjectValue(*kidobj)); -} - -/* Forward declared -- its implementation uses other statics that call it. */ -static JSBool -ResolveValue(JSContext *cx, JSXML *list, JSXML **result); - -/* ECMA-357 9.1.1.2 XML [[Put]] and 9.2.1.2 XMLList [[Put]]. */ -static JSBool -PutProperty(JSContext *cx, HandleObject obj_, HandleId id_, JSBool strict, MutableHandleValue vp) -{ - JSBool ok, primitiveAssign; - enum { OBJ_ROOT, ID_ROOT, VAL_ROOT }; - JSXML *xml, *vxml, *rxml, *kid, *attr, *parent, *copy, *kid2, *match; - JSObject *vobj, *nameobj, *attrobj, *copyobj; - JSObject *targetprop, *nameqn, *attrqn; - uint32_t index, i, j, k, n, q, matchIndex; - RootedValue attrval(cx), nsval(cx); - JSObject *ns; - - RootedObject obj(cx, obj_), kidobj(cx); - RootedId id(cx, id_), funid(cx); - - if (!obj->isXML()) - return JS_TRUE; - xml = (JSXML *) obj->getPrivate(); - if (!xml) - return JS_TRUE; - - xml = CHECK_COPY_ON_WRITE(cx, xml, obj); - if (!xml) - return JS_FALSE; - - /* Precompute vxml for 9.2.1.2 2(c)(vii)(2-3) and 2(d) and 9.1.1.2 1. */ - vxml = NULL; - if (!JSVAL_IS_PRIMITIVE(vp)) { - vobj = JSVAL_TO_OBJECT(vp); - if (vobj->isXML()) - vxml = (JSXML *) vobj->getPrivate(); - } - - ok = JS_TRUE; - - jsval roots[3]; - roots[OBJ_ROOT] = OBJECT_TO_JSVAL(obj); - roots[ID_ROOT] = IdToJsval(id); - roots[VAL_ROOT] = vp; - AutoArrayRooter tvr(cx, ArrayLength(roots), roots); - - if (js_IdIsIndex(id, &index)) { - if (xml->xml_class != JSXML_CLASS_LIST) { - /* See NOTE in spec: this variation is reserved for future use. */ - ReportBadXMLName(cx, IdToValue(id)); - goto bad; - } - - /* - * Step 1 of ECMA-357 9.2.1.2 index case sets i to the property index. - */ - i = index; - - /* 2(a-b). */ - if (xml->xml_target) { - ok = ResolveValue(cx, xml->xml_target, &rxml); - if (!ok) - goto out; - if (!rxml) - goto out; - JS_ASSERT(rxml->object); - } else { - rxml = NULL; - } - - /* 2(c). */ - if (index >= xml->xml_kids.length) { - /* 2(c)(i). */ - if (rxml) { - if (rxml->xml_class == JSXML_CLASS_LIST) { - if (rxml->xml_kids.length != 1) - goto out; - rxml = XMLARRAY_MEMBER(&rxml->xml_kids, 0, JSXML); - if (!rxml) - goto out; - ok = js_GetXMLObject(cx, rxml) != NULL; - if (!ok) - goto out; - } - - /* - * Erratum: ECMA-357 9.2.1.2 step 2(c)(ii) sets - * _y.[[Parent]] = r_ where _r_ is the result of - * [[ResolveValue]] called on _x.[[TargetObject]] in - * 2(a)(i). This can result in text parenting text: - * - * var MYXML = new XML(); - * MYXML.appendChild(new XML("Giants")); - * - * (testcase from Werner Sharp ). - * - * To match insertChildAfter, insertChildBefore, - * prependChild, and setChildren, we should silently - * do nothing in this case. - */ - if (!JSXML_HAS_KIDS(rxml)) - goto out; - } - - /* 2(c)(ii) is distributed below as several js_NewXML calls. */ - targetprop = xml->xml_targetprop; - if (!targetprop || IS_STAR(targetprop->getQNameLocalName())) { - /* 2(c)(iv)(1-2), out of order w.r.t. 2(c)(iii). */ - kid = js_NewXML(cx, JSXML_CLASS_TEXT); - if (!kid) - goto bad; - } else { - nameobj = targetprop; - if (nameobj->getClass() == &AttributeNameClass) { - /* - * 2(c)(iii)(1-3). - * Note that rxml can't be null here, because target - * and targetprop are non-null. - */ - Rooted robj(cx, rxml->object); - ok = GetProperty(cx, robj, id, &attrval); - if (!ok) - goto out; - if (JSVAL_IS_PRIMITIVE(attrval)) /* no such attribute */ - goto out; - attrobj = JSVAL_TO_OBJECT(attrval); - attr = (JSXML *) attrobj->getPrivate(); - if (JSXML_LENGTH(attr) != 0) - goto out; - - kid = js_NewXML(cx, JSXML_CLASS_ATTRIBUTE); - } else { - /* 2(c)(v). */ - kid = js_NewXML(cx, JSXML_CLASS_ELEMENT); - } - if (!kid) - goto bad; - - /* An important bit of 2(c)(ii). */ - kid->name = targetprop; - } - - /* Final important bit of 2(c)(ii). */ - kid->parent = rxml; - - /* 2(c)(vi-vii). */ - i = xml->xml_kids.length; - if (kid->xml_class != JSXML_CLASS_ATTRIBUTE) { - /* - * 2(c)(vii)(1) tests whether _y.[[Parent]]_ is not null. - * y.[[Parent]] is here called kid->parent, which we know - * from 2(c)(ii) is _r_, here called rxml. So let's just - * test that! Erratum, the spec should be simpler here. - */ - if (rxml) { - JS_ASSERT(JSXML_HAS_KIDS(rxml)); - n = rxml->xml_kids.length; - j = n - 1; - if (n != 0 && i != 0) { - for (n = j, j = 0; j < n; j++) { - if (rxml->xml_kids.vector[j] == - xml->xml_kids.vector[i-1]) { - break; - } - } - } - - kidobj = js_GetXMLObject(cx, kid); - if (!kidobj) - goto bad; - ok = Insert(cx, rxml, j + 1, OBJECT_TO_JSVAL(kidobj)); - if (!ok) - goto out; - } - - /* - * 2(c)(vii)(2-3). - * Erratum: [[PropertyName]] in 2(c)(vii)(3) must be a - * typo for [[TargetProperty]]. - */ - if (vxml) { - kid->name = (vxml->xml_class == JSXML_CLASS_LIST) - ? vxml->xml_targetprop - : vxml->name; - } - } - - /* 2(c)(viii). */ - ok = Append(cx, xml, kid); - if (!ok) - goto out; - } - - /* 2(d). */ - if (!vxml || - vxml->xml_class == JSXML_CLASS_TEXT || - vxml->xml_class == JSXML_CLASS_ATTRIBUTE) { - ok = JS_ConvertValue(cx, vp, JSTYPE_STRING, vp.address()); - if (!ok) - goto out; - roots[VAL_ROOT] = vp; - } - - /* 2(e). */ - kid = XMLARRAY_MEMBER(&xml->xml_kids, i, JSXML); - if (!kid) - goto out; - parent = kid->parent; - if (kid->xml_class == JSXML_CLASS_ATTRIBUTE) { - nameobj = kid->name; - if (nameobj->getClass() != &AttributeNameClass) { - nameobj = NewXMLAttributeName(cx, nameobj->getNameURI(), nameobj->getNamePrefix(), - nameobj->getQNameLocalName()); - if (!nameobj) - goto bad; - } - id = OBJECT_TO_JSID(nameobj); - - if (parent) { - /* 2(e)(i). */ - RootedObject parentobj(cx, js_GetXMLObject(cx, parent)); - if (!parentobj) - goto bad; - ok = PutProperty(cx, parentobj, id, strict, vp); - if (!ok) - goto out; - - /* 2(e)(ii). */ - ok = GetProperty(cx, parentobj, id, vp); - if (!ok) - goto out; - attr = (JSXML *) JSVAL_TO_OBJECT(vp)->getPrivate(); - - /* 2(e)(iii) - the length check comes from the bug 375406. */ - if (attr->xml_kids.length != 0) - xml->xml_kids.vector[i] = attr->xml_kids.vector[0]; - } - } - - /* 2(f). */ - else if (vxml && vxml->xml_class == JSXML_CLASS_LIST) { - /* - * 2(f)(i) - * - * Erratum: the spec says to create a shallow copy _c_ of _V_, but - * if we do that we never change the parent of each child in the - * list. Since [[Put]] when called on an XML object deeply copies - * the provided list _V_, we also do so here. Perhaps the shallow - * copy was a misguided optimization? - */ - copy = DeepCopyInLRS(cx, vxml, 0); - if (!copy) - goto bad; - copyobj = js_GetXMLObject(cx, copy); - if (!copyobj) - goto bad; - - JS_ASSERT(parent != xml); - if (parent) { - q = XMLARRAY_FIND_MEMBER(&parent->xml_kids, kid, pointer_match); - JS_ASSERT(q != XML_NOT_FOUND); - ok = Replace(cx, parent, q, OBJECT_TO_JSVAL(copyobj)); - if (!ok) - goto out; - -#ifdef DEBUG - /* Erratum: this loop in the spec is useless. */ - for (j = 0, n = copy->xml_kids.length; j < n; j++) { - kid2 = XMLARRAY_MEMBER(&parent->xml_kids, q + j, JSXML); - JS_ASSERT(XMLARRAY_MEMBER(©->xml_kids, j, JSXML) - == kid2); - } -#endif - } - - /* - * 2(f)(iv-vi). - * Erratum: notice the unhandled zero-length V basis case and - * the off-by-one errors for the n != 0 cases in the spec. - */ - n = copy->xml_kids.length; - if (n == 0) { - XMLArrayDelete(cx, &xml->xml_kids, i, JS_TRUE); - } else { - ok = XMLArrayInsert(cx, &xml->xml_kids, i + 1, n - 1); - if (!ok) - goto out; - - for (j = 0; j < n; j++) - xml->xml_kids.vector[i + j] = copy->xml_kids.vector[j]; - } - } - - /* 2(g). */ - else if (vxml || JSXML_HAS_VALUE(kid)) { - if (parent) { - q = XMLARRAY_FIND_MEMBER(&parent->xml_kids, kid, pointer_match); - JS_ASSERT(q != XML_NOT_FOUND); - ok = Replace(cx, parent, q, vp); - if (!ok) - goto out; - - vxml = XMLARRAY_MEMBER(&parent->xml_kids, q, JSXML); - if (!vxml) - goto out; - roots[VAL_ROOT] = OBJECT_TO_JSVAL(vxml->object); - vp.set(roots[VAL_ROOT]); - } - - /* - * 2(g)(iii). - * Erratum: _V_ may not be of type XML, but all index-named - * properties _x[i]_ in an XMLList _x_ must be of type XML, - * according to 9.2.1.1 Overview and other places in the spec. - * - * Thanks to 2(d), we know _V_ (*vp here) is either a string - * or an XML/XMLList object. If *vp is a string, call ToXML - * on it to satisfy the constraint. - */ - if (!vxml) { - JS_ASSERT(JSVAL_IS_STRING(vp)); - vobj = ToXML(cx, vp); - if (!vobj) - goto bad; - roots[VAL_ROOT] = OBJECT_TO_JSVAL(vobj); - vp.set(roots[VAL_ROOT]); - vxml = (JSXML *) vobj->getPrivate(); - } - XMLARRAY_SET_MEMBER(&xml->xml_kids, i, vxml); - } - - /* 2(h). */ - else { - kidobj = js_GetXMLObject(cx, kid); - if (!kidobj) - goto bad; - id = NameToId(cx->names().star); - ok = PutProperty(cx, kidobj, id, strict, vp); - if (!ok) - goto out; - } - } else { - /* - * ECMA-357 9.2.1.2/9.1.1.2 qname case. - */ - nameqn = ToXMLName(cx, IdToJsval(id), funid.address()); - if (!nameqn) - goto bad; - if (!JSID_IS_VOID(funid)) { - ok = baseops::SetPropertyHelper(cx, obj, obj, funid, 0, vp, false); - goto out; - } - nameobj = nameqn; - roots[ID_ROOT] = OBJECT_TO_JSVAL(nameobj); - - if (xml->xml_class == JSXML_CLASS_LIST) { - /* - * Step 3 of 9.2.1.2. - * Erratum: if x.[[Length]] > 1 or [[ResolveValue]] returns null - * or an r with r.[[Length]] != 1, throw TypeError. - */ - n = JSXML_LENGTH(xml); - if (n > 1) - goto type_error; - if (n == 0) { - ok = ResolveValue(cx, xml, &rxml); - if (!ok) - goto out; - if (!rxml || JSXML_LENGTH(rxml) != 1) - goto type_error; - ok = Append(cx, xml, rxml); - if (!ok) - goto out; - } - JS_ASSERT(JSXML_LENGTH(xml) == 1); - xml = XMLARRAY_MEMBER(&xml->xml_kids, 0, JSXML); - if (!xml) - goto out; - JS_ASSERT(xml->xml_class != JSXML_CLASS_LIST); - obj = js_GetXMLObject(cx, xml); - if (!obj) - goto bad; - roots[OBJ_ROOT] = OBJECT_TO_JSVAL(obj); - - /* FALL THROUGH to non-list case */ - } - - /* - * ECMA-357 9.1.1.2. - * Erratum: move steps 3 and 4 to before 1 and 2, to avoid wasted - * effort in ToString or [[DeepCopy]]. - */ - - if (JSXML_HAS_VALUE(xml)) - goto out; - - if (!vxml || - vxml->xml_class == JSXML_CLASS_TEXT || - vxml->xml_class == JSXML_CLASS_ATTRIBUTE) { - ok = JS_ConvertValue(cx, vp, JSTYPE_STRING, vp.address()); - if (!ok) - goto out; - } else { - rxml = DeepCopyInLRS(cx, vxml, 0); - if (!rxml || !js_GetXMLObject(cx, rxml)) - goto bad; - vxml = rxml; - vp.set(OBJECT_TO_JSVAL(vxml->object)); - } - roots[VAL_ROOT] = vp; - - /* - * 6. - * Erratum: why is this done here, so early? use is way later.... - */ - ok = js_GetDefaultXMLNamespace(cx, nsval.address()); - if (!ok) - goto out; - - if (nameobj->getClass() == &AttributeNameClass) { - /* 7(a). */ - if (!js_IsXMLName(cx, OBJECT_TO_JSVAL(nameobj))) - goto out; - - /* 7(b-c). */ - if (vxml && vxml->xml_class == JSXML_CLASS_LIST) { - n = vxml->xml_kids.length; - if (n == 0) { - vp.set(STRING_TO_JSVAL(cx->runtime->emptyString)); - } else { - RootedString left(cx, KidToString(cx, vxml, 0)); - if (!left) - goto bad; - - RootedString space(cx, cx->names().space); - for (i = 1; i < n; i++) { - left = ConcatStrings(cx, left, space); - if (!left) - goto bad; - RootedString right(cx, KidToString(cx, vxml, i)); - if (!right) - goto bad; - left = ConcatStrings(cx, left, right); - if (!left) - goto bad; - } - - roots[VAL_ROOT] = STRING_TO_JSVAL(left); - vp.set(roots[VAL_ROOT]); - } - } else { - ok = JS_ConvertValue(cx, vp, JSTYPE_STRING, vp.address()); - if (!ok) - goto out; - roots[VAL_ROOT] = vp; - } - - /* 7(d-e). */ - match = NULL; - for (i = 0, n = xml->xml_attrs.length; i < n; i++) { - attr = XMLARRAY_MEMBER(&xml->xml_attrs, i, JSXML); - if (!attr) - continue; - attrqn = attr->name; - if (EqualStrings(attrqn->getQNameLocalName(), nameqn->getQNameLocalName())) { - JSLinearString *uri = nameqn->getNameURI(); - if (!uri || EqualStrings(attrqn->getNameURI(), uri)) { - if (!match) { - match = attr; - } else { - DeleteNamedProperty(cx, xml, attrqn, JS_TRUE); - --i; - } - } - } - } - - /* 7(f). */ - attr = match; - if (!attr) { - /* 7(f)(i-ii). */ - JSLinearString *uri = nameqn->getNameURI(); - JSLinearString *left, *right; - if (!uri) { - left = right = cx->runtime->emptyString; - } else { - left = uri; - right = nameqn->getNamePrefix(); - } - nameqn = NewXMLQName(cx, left, right, nameqn->getQNameLocalName()); - if (!nameqn) - goto bad; - - /* 7(f)(iii). */ - attr = js_NewXML(cx, JSXML_CLASS_ATTRIBUTE); - if (!attr) - goto bad; - attr->parent = xml; - attr->name = nameqn; - - /* 7(f)(iv). */ - ok = XMLARRAY_ADD_MEMBER(cx, &xml->xml_attrs, n, attr); - if (!ok) - goto out; - - /* 7(f)(v-vi). */ - ns = GetNamespace(cx, nameqn, NULL); - if (!ns) - goto bad; - ok = AddInScopeNamespace(cx, xml, ns); - if (!ok) - goto out; - } - - /* 7(g). */ - attr->xml_value = JSVAL_TO_STRING(vp); - goto out; - } - - /* 8-9. */ - if (!js_IsXMLName(cx, OBJECT_TO_JSVAL(nameobj)) && - !IS_STAR(nameqn->getQNameLocalName())) { - goto out; - } - - /* 10-11. */ - id = JSID_VOID; - primitiveAssign = !vxml && !IS_STAR(nameqn->getQNameLocalName()); - - /* 12. */ - k = n = xml->xml_kids.length; - matchIndex = XML_NOT_FOUND; - kid2 = NULL; - while (k != 0) { - --k; - kid = XMLARRAY_MEMBER(&xml->xml_kids, k, JSXML); - if (kid && MatchElemName(nameqn, kid)) { - if (matchIndex != XML_NOT_FOUND) - DeleteByIndex(cx, xml, matchIndex); - matchIndex = k; - kid2 = kid; - } - } - - /* - * Erratum: ECMA-357 specified child insertion inconsistently: - * insertChildBefore and insertChildAfter insert an arbitrary XML - * instance, and therefore can create cycles, but appendChild as - * specified by the "Overview" of 13.4.4.3 calls [[DeepCopy]] on - * its argument. But the "Semantics" in 13.4.4.3 do not include - * any [[DeepCopy]] call. - * - * Fixing this (https://bugzilla.mozilla.org/show_bug.cgi?id=312692) - * required adding cycle detection, and allowing duplicate kids to - * be created (see comment 6 in the bug). Allowing duplicate kid - * references means the loop above will delete all but the lowest - * indexed reference, and each [[DeleteByIndex]] nulls the kid's - * parent. Thus the need to restore parent here. This is covered - * by https://bugzilla.mozilla.org/show_bug.cgi?id=327564. - */ - if (kid2) { - JS_ASSERT(kid2->parent == xml || !kid2->parent); - if (!kid2->parent) - kid2->parent = xml; - } - - /* 13. */ - if (matchIndex == XML_NOT_FOUND) { - /* 13(a). */ - matchIndex = n; - - /* 13(b). */ - if (primitiveAssign) { - JSLinearString *uri = nameqn->getNameURI(); - JSLinearString *left, *right; - if (!uri) { - ns = JSVAL_TO_OBJECT(nsval); - left = ns->getNameURI(); - right = ns->getNamePrefix(); - } else { - left = uri; - right = nameqn->getNamePrefix(); - } - nameqn = NewXMLQName(cx, left, right, nameqn->getQNameLocalName()); - if (!nameqn) - goto bad; - - /* 13(b)(iii). */ - vobj = js_NewXMLObject(cx, JSXML_CLASS_ELEMENT); - if (!vobj) - goto bad; - vxml = (JSXML *) vobj->getPrivate(); - vxml->parent = xml; - vxml->name = nameqn; - - /* 13(b)(iv-vi). */ - ns = GetNamespace(cx, nameqn, NULL); - if (!ns) - goto bad; - ok = Replace(cx, xml, matchIndex, OBJECT_TO_JSVAL(vobj)); - if (!ok) - goto out; - ok = AddInScopeNamespace(cx, vxml, ns); - if (!ok) - goto out; - } - } - - /* 14. */ - if (primitiveAssign) { - JSXMLArrayCursor cursor(&xml->xml_kids); - cursor.index = matchIndex; - kid = cursor.getCurrent(); - if (JSXML_HAS_KIDS(kid)) { - kid->xml_kids.finish(cx->runtime->defaultFreeOp()); - kid->xml_kids.init(); - ok = kid->xml_kids.setCapacity(cx, 1); - } - - /* 14(b-c). */ - /* XXXbe Erratum? redundant w.r.t. 7(b-c) else clause above */ - if (ok) { - ok = JS_ConvertValue(cx, vp, JSTYPE_STRING, vp.address()); - if (ok && !JSVAL_TO_STRING(vp)->empty()) { - roots[VAL_ROOT] = vp; - if (cursor.getCurrent() == kid) - ok = Replace(cx, kid, 0, vp); - } - } - } else { - /* 15(a). */ - ok = Replace(cx, xml, matchIndex, vp); - } - } - -out: - return ok; - -type_error: - { - JSAutoByteString bytes; - if (js_ValueToPrintable(cx, IdToValue(id), &bytes)) - JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_BAD_XMLLIST_PUT, bytes.ptr()); - } -bad: - ok = JS_FALSE; - goto out; -} - -/* ECMA-357 9.1.1.10 XML [[ResolveValue]], 9.2.1.10 XMLList [[ResolveValue]]. */ -static JSBool -ResolveValue(JSContext *cx, JSXML *list, JSXML **result) -{ - JSXML *target, *base; - JSObject *targetprop; - RootedValue tv(cx); - - if (list->xml_class != JSXML_CLASS_LIST || list->xml_kids.length != 0) { - if (!js_GetXMLObject(cx, list)) - return JS_FALSE; - *result = list; - return JS_TRUE; - } - - target = list->xml_target; - targetprop = list->xml_targetprop; - if (!target || !targetprop || IS_STAR(targetprop->getQNameLocalName())) { - *result = NULL; - return JS_TRUE; - } - - if (targetprop->getClass() == &AttributeNameClass) { - *result = NULL; - return JS_TRUE; - } - - if (!ResolveValue(cx, target, &base)) - return JS_FALSE; - if (!base) { - *result = NULL; - return JS_TRUE; - } - if (!js_GetXMLObject(cx, base)) - return JS_FALSE; - - RootedId id(cx, OBJECT_TO_JSID(targetprop)); - Rooted baseObj(cx, base->object); - if (!GetProperty(cx, baseObj, id, &tv)) - return JS_FALSE; - target = (JSXML *) JSVAL_TO_OBJECT(tv)->getPrivate(); - - if (JSXML_LENGTH(target) == 0) { - if (base->xml_class == JSXML_CLASS_LIST && JSXML_LENGTH(base) > 1) { - *result = NULL; - return JS_TRUE; - } - tv = STRING_TO_JSVAL(cx->runtime->emptyString); - if (!PutProperty(cx, baseObj, id, false, &tv)) - return JS_FALSE; - if (!GetProperty(cx, baseObj, id, &tv)) - return JS_FALSE; - target = (JSXML *) JSVAL_TO_OBJECT(tv)->getPrivate(); - } - - *result = target; - return JS_TRUE; -} - -static JSBool -HasNamedProperty(JSXML *xml, JSObject *nameqn) -{ - JSBool found; - JSXMLArray *array; - JSXMLNameMatcher matcher; - uint32_t i, n; - - if (xml->xml_class == JSXML_CLASS_LIST) { - found = JS_FALSE; - JSXMLArrayCursor cursor(&xml->xml_kids); - while (JSXML *kid = cursor.getNext()) { - found = HasNamedProperty(kid, nameqn); - if (found) - break; - } - return found; - } - - if (xml->xml_class == JSXML_CLASS_ELEMENT) { - if (nameqn->getClass() == &AttributeNameClass) { - array = &xml->xml_attrs; - matcher = MatchAttrName; - } else { - array = &xml->xml_kids; - matcher = MatchElemName; - } - for (i = 0, n = array->length; i < n; i++) { - JSXML *kid = XMLARRAY_MEMBER(array, i, JSXML); - if (kid && matcher(nameqn, kid)) - return JS_TRUE; - } - } - - return JS_FALSE; -} - -static JSBool -HasIndexedProperty(JSXML *xml, uint32_t i) -{ - if (xml->xml_class == JSXML_CLASS_LIST) - return i < JSXML_LENGTH(xml); - - if (xml->xml_class == JSXML_CLASS_ELEMENT) - return i == 0; - - return JS_FALSE; -} - -static JSBool -HasSimpleContent(JSXML *xml); - -static JSBool -HasFunctionProperty(JSContext *cx, JSObject *obj_, jsid funid_, JSBool *found) -{ - JSXML *xml; - - JS_ASSERT(obj_->getClass() == &XMLClass); - - RootedId funid(cx, funid_); - - Rooted obj(cx, obj_); - RootedObject pobj(cx); - RootedShape prop(cx); - if (!baseops::LookupProperty(cx, obj, funid, &pobj, &prop)) - return false; - if (!prop) { - xml = (JSXML *) obj->getPrivate(); - if (HasSimpleContent(xml)) { - /* - * Search in String.prototype to set found whenever - * GetXMLFunction returns existing function. - */ - RootedObject proto(cx, obj->global().getOrCreateStringPrototype(cx)); - if (!proto) - return false; - - if (!baseops::LookupProperty(cx, proto, funid, &pobj, &prop)) - return false; - } - } - *found = (prop != NULL); - return true; -} - -static bool -IdValIsIndex(JSContext *cx, jsval id, uint32_t *indexp, bool *isIndex) -{ - if (JSVAL_IS_INT(id)) { - int32_t i = JSVAL_TO_INT(id); - if (i < 0) { - *isIndex = false; - return true; - } - *indexp = (uint32_t)i; - *isIndex = true; - return true; - } - - if (!JSVAL_IS_STRING(id)) { - *isIndex = false; - return true; - } - - JSLinearString *str = JSVAL_TO_STRING(id)->ensureLinear(cx); - if (!str) - return false; - - *isIndex = StringIsArrayIndex(str, indexp); - return true; -} - -/* ECMA-357 9.1.1.6 XML [[HasProperty]] and 9.2.1.5 XMLList [[HasProperty]]. */ -static JSBool -HasProperty(JSContext *cx, JSObject *obj, jsval id, JSBool *found) -{ - JSXML *xml; - bool isIndex; - uint32_t i; - JSObject *qn; - jsid funid; - - xml = (JSXML *) obj->getPrivate(); - if (!IdValIsIndex(cx, id, &i, &isIndex)) - return JS_FALSE; - - if (isIndex) { - *found = HasIndexedProperty(xml, i); - } else { - qn = ToXMLName(cx, id, &funid); - if (!qn) - return JS_FALSE; - if (!JSID_IS_VOID(funid)) { - if (!HasFunctionProperty(cx, obj, funid, found)) - return JS_FALSE; - } else { - *found = HasNamedProperty(xml, qn); - } - } - return JS_TRUE; -} - -/* - * XML objects are native. Thus xml_lookupGeneric must return a valid - * Shape pointer parameter via *propp to signify "property found". Since the - * only call to xml_lookupGeneric is via JSObject::lookupGeneric, and then - * only from js_FindProperty (in jsobj.c, called from jsinterp.c) or from - * JSOP_IN case in the interpreter, the only time we add a Shape here is when - * an unqualified name is being accessed or when "name in xml" is called. - * - * This scope property keeps the JSOP_NAME code in js_Interpret happy by - * giving it an shape with (getter, setter) == (GetProperty, PutProperty). - * - * NB: xml_deleteProperty must take care to remove any property added here. - * - * FIXME This clashes with the function namespace implementation which also - * uses native properties. Effectively after xml_lookupGeneric any property - * stored previously using assignments to xml.function::name will be removed. - * We partially workaround the problem in GetXMLFunction. There we take - * advantage of the fact that typically function:: is used to access the - * functions from XML.prototype. So when js_GetProperty returns a non-function - * property, we assume that it represents the result of GetProperty setter - * hiding the function and use an extra prototype chain lookup to recover it. - * For a proper solution see bug 355257. -*/ -static JSBool -xml_lookupGeneric(JSContext *cx, HandleObject obj, HandleId id, - MutableHandleObject objp, MutableHandleShape propp) -{ - JSBool found; - JSXML *xml; - uint32_t i; - JSObject *qn; - - RootedId funid(cx); - - xml = (JSXML *) obj->getPrivate(); - if (js_IdIsIndex(id, &i)) { - found = HasIndexedProperty(xml, i); - } else { - qn = ToXMLName(cx, IdToJsval(id), funid.address()); - if (!qn) - return JS_FALSE; - if (!JSID_IS_VOID(funid)) - return baseops::LookupProperty(cx, obj, funid, objp, propp); - found = HasNamedProperty(xml, qn); - } - if (!found) { - objp.set(NULL); - propp.set(NULL); - } else { - RootedShape shape(cx, js_AddNativeProperty(cx, obj, id, GetProperty, PutProperty, - SHAPE_INVALID_SLOT, JSPROP_ENUMERATE, - 0, 0)); - if (!shape) - return JS_FALSE; - - objp.set(obj); - propp.set(shape); - } - return JS_TRUE; -} - -static JSBool -xml_lookupProperty(JSContext *cx, HandleObject obj, HandlePropertyName name, - MutableHandleObject objp, MutableHandleShape propp) -{ - Rooted id(cx, NameToId(name)); - return xml_lookupGeneric(cx, obj, id, objp, propp); -} - -static JSBool -xml_lookupElement(JSContext *cx, HandleObject obj, uint32_t index, MutableHandleObject objp, - MutableHandleShape propp) -{ - JSXML *xml = reinterpret_cast(obj->getPrivate()); - if (!HasIndexedProperty(xml, index)) { - objp.set(NULL); - propp.set(NULL); - return true; - } - - RootedId id(cx); - if (!IndexToId(cx, index, &id)) - return false; - - RootedShape shape(cx, js_AddNativeProperty(cx, obj, id, GetProperty, PutProperty, - SHAPE_INVALID_SLOT, JSPROP_ENUMERATE, 0, 0)); - if (!shape) - return false; - - objp.set(obj); - propp.set(shape); - return true; -} - -static JSBool -xml_lookupSpecial(JSContext *cx, HandleObject obj, HandleSpecialId sid, - MutableHandleObject objp, MutableHandleShape propp) -{ - Rooted id(cx, SPECIALID_TO_JSID(sid)); - return xml_lookupGeneric(cx, obj, id, objp, propp); -} - -static JSBool -xml_defineGeneric(JSContext *cx, HandleObject obj, HandleId id, HandleValue v, - PropertyOp getter, StrictPropertyOp setter, unsigned attrs) -{ - if (IsFunctionObject(v) || getter || setter || - (attrs & JSPROP_ENUMERATE) == 0 || - (attrs & (JSPROP_READONLY | JSPROP_PERMANENT | JSPROP_SHARED))) { - return baseops::DefineGeneric(cx, obj, id, v, getter, setter, attrs); - } - - RootedValue tmp(cx, v); - return PutProperty(cx, obj, id, false, &tmp); -} - -static JSBool -xml_defineProperty(JSContext *cx, HandleObject obj, HandlePropertyName name, HandleValue v, - PropertyOp getter, StrictPropertyOp setter, unsigned attrs) -{ - Rooted id(cx, NameToId(name)); - return xml_defineGeneric(cx, obj, id, v, getter, setter, attrs); -} - -static JSBool -xml_defineElement(JSContext *cx, HandleObject obj, uint32_t index, HandleValue v, - PropertyOp getter, StrictPropertyOp setter, unsigned attrs) -{ - RootedId id(cx); - if (!IndexToId(cx, index, &id)) - return false; - return xml_defineGeneric(cx, obj, id, v, getter, setter, attrs); -} - -static JSBool -xml_defineSpecial(JSContext *cx, HandleObject obj, HandleSpecialId sid, HandleValue v, - PropertyOp getter, StrictPropertyOp setter, unsigned attrs) -{ - Rooted id(cx, SPECIALID_TO_JSID(sid)); - return xml_defineGeneric(cx, obj, id, v, getter, setter, attrs); -} - -static JSBool -xml_getGeneric(JSContext *cx, HandleObject obj, HandleObject receiver, HandleId id, - MutableHandleValue vp) -{ - if (JSID_IS_DEFAULT_XML_NAMESPACE(id)) { - vp.setUndefined(); - return JS_TRUE; - } - - return GetProperty(cx, obj, id, vp); -} - -static JSBool -xml_getProperty(JSContext *cx, HandleObject obj, HandleObject receiver, HandlePropertyName name, - MutableHandleValue vp) -{ - Rooted id(cx, NameToId(name)); - return xml_getGeneric(cx, obj, receiver, id, vp); -} - -static JSBool -xml_getElement(JSContext *cx, HandleObject obj, HandleObject receiver, uint32_t index, MutableHandleValue vp) -{ - RootedId id(cx); - if (!IndexToId(cx, index, &id)) - return false; - return xml_getGeneric(cx, obj, receiver, id, vp); -} - -static JSBool -xml_getSpecial(JSContext *cx, HandleObject obj, HandleObject receiver, HandleSpecialId sid, MutableHandleValue vp) -{ - Rooted id(cx, SPECIALID_TO_JSID(sid)); - return xml_getGeneric(cx, obj, receiver, id, vp); -} - -static JSBool -xml_setGeneric(JSContext *cx, HandleObject obj, HandleId id, MutableHandleValue vp, JSBool strict) -{ - return PutProperty(cx, obj, id, strict, vp); -} - -static JSBool -xml_setProperty(JSContext *cx, HandleObject obj, HandlePropertyName name, MutableHandleValue vp, JSBool strict) -{ - Rooted id(cx, NameToId(name)); - return xml_setGeneric(cx, obj, id, vp, strict); -} - -static JSBool -xml_setElement(JSContext *cx, HandleObject obj, uint32_t index, MutableHandleValue vp, JSBool strict) -{ - RootedId id(cx); - if (!IndexToId(cx, index, &id)) - return false; - return xml_setGeneric(cx, obj, id, vp, strict); -} - -static JSBool -xml_setSpecial(JSContext *cx, HandleObject obj, HandleSpecialId sid, MutableHandleValue vp, JSBool strict) -{ - Rooted id(cx, SPECIALID_TO_JSID(sid)); - return xml_setGeneric(cx, obj, id, vp, strict); -} - -static JSBool -xml_getGenericAttributes(JSContext *cx, HandleObject obj, HandleId id, unsigned *attrsp) -{ - JSBool found; - if (!HasProperty(cx, obj, IdToJsval(id), &found)) - return false; - - *attrsp = found ? JSPROP_ENUMERATE : 0; - return JS_TRUE; -} - -static JSBool -xml_getPropertyAttributes(JSContext *cx, HandleObject obj, HandlePropertyName name, unsigned *attrsp) -{ - Rooted id(cx, NameToId(name)); - return xml_getGenericAttributes(cx, obj, id, attrsp); -} - -static JSBool -xml_getElementAttributes(JSContext *cx, HandleObject obj, uint32_t index, unsigned *attrsp) -{ - RootedId id(cx); - if (!IndexToId(cx, index, &id)) - return false; - return xml_getGenericAttributes(cx, obj, id, attrsp); -} - -static JSBool -xml_getSpecialAttributes(JSContext *cx, HandleObject obj, HandleSpecialId sid, unsigned *attrsp) -{ - Rooted id(cx, SPECIALID_TO_JSID(sid)); - return xml_getGenericAttributes(cx, obj, id, attrsp); -} - -static JSBool -xml_setGenericAttributes(JSContext *cx, HandleObject obj, HandleId id, unsigned *attrsp) -{ - JSBool found; - if (!HasProperty(cx, obj, IdToJsval(id), &found)) - return false; - - if (found) { - JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, - JSMSG_CANT_SET_XML_ATTRS); - return false; - } - return true; -} - -static JSBool -xml_setPropertyAttributes(JSContext *cx, HandleObject obj, HandlePropertyName name, unsigned *attrsp) -{ - Rooted id(cx, NameToId(name)); - return xml_setGenericAttributes(cx, obj, id, attrsp); -} - -static JSBool -xml_setElementAttributes(JSContext *cx, HandleObject obj, uint32_t index, unsigned *attrsp) -{ - RootedId id(cx); - if (!IndexToId(cx, index, &id)) - return false; - return xml_setGenericAttributes(cx, obj, id, attrsp); -} - -static JSBool -xml_setSpecialAttributes(JSContext *cx, HandleObject obj, HandleSpecialId sid, unsigned *attrsp) -{ - Rooted id(cx, SPECIALID_TO_JSID(sid)); - return xml_setGenericAttributes(cx, obj, id, attrsp); -} - -static JSBool -xml_deleteGeneric(JSContext *cx, HandleObject obj, HandleId id, MutableHandleValue rval, JSBool strict) -{ - uint32_t index; - JSObject *nameqn; - RootedId funid(cx); - - Value idval = IdToValue(id); - JSXML *xml = (JSXML *) obj->getPrivate(); - if (js_IdIsIndex(id, &index)) { - if (xml->xml_class != JSXML_CLASS_LIST) { - /* See NOTE in spec: this variation is reserved for future use. */ - ReportBadXMLName(cx, IdToValue(id)); - return false; - } - - /* ECMA-357 9.2.1.3. */ - DeleteListElement(cx, xml, index); - } else { - nameqn = ToXMLName(cx, idval, funid.address()); - if (!nameqn) - return false; - if (!JSID_IS_VOID(funid)) - return baseops::DeleteGeneric(cx, obj, funid, rval, false); - - DeleteNamedProperty(cx, xml, nameqn, - nameqn->getClass() == &AttributeNameClass); - } - - /* - * If this object has its own (mutable) scope, then we may have added a - * property to the scope in xml_lookupGeneric for it to return to mean - * "found" and to provide a handle for access operations to call the - * property's getter or setter. But now it's time to remove any such - * property, to purge the property cache and remove the scope entry. - */ - if (!obj->nativeEmpty() && !baseops::DeleteGeneric(cx, obj, id, rval, false)) - return false; - - rval.setBoolean(true); - return true; -} - -static JSBool -xml_deleteProperty(JSContext *cx, HandleObject obj, HandlePropertyName name, MutableHandleValue rval, JSBool strict) -{ - Rooted id(cx, NameToId(name)); - return xml_deleteGeneric(cx, obj, id, rval, strict); -} - -static JSBool -xml_deleteElement(JSContext *cx, HandleObject obj, uint32_t index, MutableHandleValue rval, JSBool strict) -{ - JSXML *xml = reinterpret_cast(obj->getPrivate()); - if (xml->xml_class != JSXML_CLASS_LIST) { - /* See NOTE in spec: this variation is reserved for future use. */ - ReportBadXMLName(cx, DoubleValue(index)); - return false; - } - - /* ECMA-357 9.2.1.3. */ - DeleteListElement(cx, xml, index); - - /* - * If this object has its own (mutable) scope, then we may have added a - * property to the scope in xml_lookupGeneric for it to return to mean - * "found" and to provide a handle for access operations to call the - * property's getter or setter. But now it's time to remove any such - * property, to purge the property cache and remove the scope entry. - */ - if (!obj->nativeEmpty() && !baseops::DeleteElement(cx, obj, index, rval, false)) - return false; - - rval.setBoolean(true); - return true; -} - -static JSBool -xml_deleteSpecial(JSContext *cx, HandleObject obj, HandleSpecialId sid, MutableHandleValue rval, JSBool strict) -{ - Rooted id(cx, SPECIALID_TO_JSID(sid)); - return xml_deleteGeneric(cx, obj, id, rval, strict); -} - -static JSString * -xml_toString_helper(JSContext *cx, JSXML *xml); - -JSBool -xml_convert(JSContext *cx, HandleObject obj, JSType hint, MutableHandleValue rval) -{ - JS_CHECK_RECURSION(cx, return false); - - JS_ASSERT(hint == JSTYPE_NUMBER || hint == JSTYPE_STRING || hint == JSTYPE_VOID); - JS_ASSERT(obj->isXML()); - - JS::Anchor anch(obj); - JSString *str = xml_toString_helper(cx, reinterpret_cast(obj->getPrivate())); - if (!str) - return false; - rval.setString(str); - return true; -} - -static JSBool -xml_enumerate(JSContext *cx, HandleObject obj, JSIterateOp enum_op, - MutableHandleValue statep, MutableHandleId idp) -{ - JSXML *xml; - uint32_t length, index; - JSXMLArrayCursor *cursor; - - xml = (JSXML *)obj->getPrivate(); - length = JSXML_LENGTH(xml); - - switch (enum_op) { - case JSENUMERATE_INIT: - case JSENUMERATE_INIT_ALL: - if (length == 0) { - statep.setInt32(0); - } else { - cursor = cx->new_< JSXMLArrayCursor >(&xml->xml_kids); - if (!cursor) - return JS_FALSE; - statep.address()->setPrivate(cursor); - } - idp.set(INT_TO_JSID(length)); - break; - - case JSENUMERATE_NEXT: - if (statep.address()->isInt32(0)) { - statep.setNull(); - break; - } - cursor = (JSXMLArrayCursor *) statep.address()->toPrivate(); - if (cursor && cursor->array && (index = cursor->index) < length) { - idp.set(INT_TO_JSID(index)); - cursor->index = index + 1; - break; - } - /* FALL THROUGH */ - - case JSENUMERATE_DESTROY: - if (!statep.address()->isInt32(0)) { - cursor = (JSXMLArrayCursor *) statep.address()->toPrivate(); - if (cursor) - js_delete(cursor); - } - statep.setNull(); - break; - } - return JS_TRUE; -} - -static JSType -xml_typeOf(JSContext *cx, HandleObject obj) -{ - return JSTYPE_XML; -} - -static JSBool -xml_hasInstance(JSContext *cx, HandleObject obj, MutableHandleValue v, JSBool *bp) -{ - return JS_TRUE; -} - -static void -xml_trace(JSTracer *trc, RawObject obj) -{ - JSXML *xml = (JSXML *) obj->getPrivate(); - /* - * This is safe to leave Unbarriered for incremental GC, but we'll need - * to fix somehow for generational. - */ - if (xml) { - MarkXMLUnbarriered(trc, &xml, "private"); - JS_ASSERT(xml == obj->getPrivate()); - } -} - -static JSBool -HasSimpleContent(JSXML *xml) -{ - JSXML *kid; - JSBool simple; - uint32_t i, n; - -again: - switch (xml->xml_class) { - case JSXML_CLASS_COMMENT: - case JSXML_CLASS_PROCESSING_INSTRUCTION: - return JS_FALSE; - case JSXML_CLASS_LIST: - if (xml->xml_kids.length == 0) - return JS_TRUE; - if (xml->xml_kids.length == 1) { - kid = XMLARRAY_MEMBER(&xml->xml_kids, 0, JSXML); - if (kid) { - xml = kid; - goto again; - } - } - /* FALL THROUGH */ - default: - simple = JS_TRUE; - for (i = 0, n = JSXML_LENGTH(xml); i < n; i++) { - kid = XMLARRAY_MEMBER(&xml->xml_kids, i, JSXML); - if (kid && kid->xml_class == JSXML_CLASS_ELEMENT) { - simple = JS_FALSE; - break; - } - } - return simple; - } -} - -/* - * 11.2.2.1 Step 3(d) onward. - */ -JSBool -js_GetXMLMethod(JSContext *cx, HandleObject obj, jsid id_, MutableHandleValue vp) -{ - JS_ASSERT(obj->isXML()); - - Rooted id(cx, id_); - if (JSID_IS_OBJECT(id)) - js_GetLocalNameFromFunctionQName(JSID_TO_OBJECT(id), id.address(), cx); - - return GetXMLFunction(cx, obj, id, vp); -} - -JSBool -js_TestXMLEquality(JSContext *cx, const Value &v1, const Value &v2, JSBool *bp) -{ - JSXML *xml, *vxml; - JSObject *vobj; - JSBool ok = JS_TRUE; - JSString *str, *vstr; - double d, d2; - - JSObject *obj; - jsval v; - if (v1.isObject() && v1.toObject().isXML()) { - obj = &v1.toObject(); - v = v2; - } else { - v = v1; - obj = &v2.toObject(); - } - - JS_ASSERT(obj->isXML()); - - xml = (JSXML *) obj->getPrivate(); - vxml = NULL; - if (!JSVAL_IS_PRIMITIVE(v)) { - vobj = JSVAL_TO_OBJECT(v); - if (vobj->isXML()) - vxml = (JSXML *) vobj->getPrivate(); - } - - if (xml->xml_class == JSXML_CLASS_LIST) { - ok = Equals(cx, xml, v, bp); - } else if (vxml) { - if (vxml->xml_class == JSXML_CLASS_LIST) { - ok = Equals(cx, vxml, OBJECT_TO_JSVAL(obj), bp); - } else { - if (((xml->xml_class == JSXML_CLASS_TEXT || - xml->xml_class == JSXML_CLASS_ATTRIBUTE) && - HasSimpleContent(vxml)) || - ((vxml->xml_class == JSXML_CLASS_TEXT || - vxml->xml_class == JSXML_CLASS_ATTRIBUTE) && - HasSimpleContent(xml))) - { - ok = (str = ToStringSlow(cx, ObjectValue(*obj))) && - (vstr = ToString(cx, v)); - if (ok) { - bool equal; - ok = EqualStrings(cx, str, vstr, &equal); - *bp = equal; - } - } else { - ok = XMLEquals(cx, xml, vxml, bp); - } - } - } else { - if (HasSimpleContent(xml)) { - ok = (str = ToString(cx, ObjectValue(*obj))) && - (vstr = ToString(cx, v)); - if (ok) { - bool equal; - ok = EqualStrings(cx, str, vstr, &equal); - *bp = equal; - } - } else if (JSVAL_IS_STRING(v) || JSVAL_IS_NUMBER(v)) { - str = ToString(cx, ObjectValue(*obj)); - if (!str) { - ok = JS_FALSE; - } else if (JSVAL_IS_STRING(v)) { - bool equal; - ok = EqualStrings(cx, str, JSVAL_TO_STRING(v), &equal); - if (ok) - *bp = equal; - } else { - ok = JS_ValueToNumber(cx, STRING_TO_JSVAL(str), &d); - if (ok) { - d2 = JSVAL_IS_INT(v) ? JSVAL_TO_INT(v) - : JSVAL_TO_DOUBLE(v); - *bp = (d == d2); - } - } - } else { - *bp = JS_FALSE; - } - } - return ok; -} - -JSBool -js_ConcatenateXML(JSContext *cx, JSObject *obj, JSObject *robj, Value *vp) -{ - JSBool ok; - JSObject *listobj; - JSXML *list, *lxml, *rxml; - - JS_ASSERT(obj->isXML()); - - listobj = js_NewXMLObject(cx, JSXML_CLASS_LIST); - if (!listobj) { - ok = JS_FALSE; - goto out; - } - - list = (JSXML *) listobj->getPrivate(); - lxml = (JSXML *) obj->getPrivate(); - ok = Append(cx, list, lxml); - if (!ok) - goto out; - - JS_ASSERT(robj->isXML()); - rxml = (JSXML *) robj->getPrivate(); - ok = Append(cx, list, rxml); - if (!ok) - goto out; - - vp->setObject(*listobj); -out: - return ok; -} - -JS_FRIEND_DATA(Class) js::XMLClass = { - js_XML_str, - JSCLASS_HAS_PRIVATE | JSCLASS_IMPLEMENTS_BARRIERS | - JSCLASS_HAS_CACHED_PROTO(JSProto_XML), - JS_PropertyStub, /* addProperty */ - JS_PropertyStub, /* delProperty */ - JS_PropertyStub, /* getProperty */ - JS_StrictPropertyStub, /* setProperty */ - JS_EnumerateStub, - JS_ResolveStub, - xml_convert, - NULL, /* finalize */ - NULL, /* checkAccess */ - NULL, /* call */ - xml_hasInstance, - NULL, /* construct */ - xml_trace, - JS_NULL_CLASS_EXT, - { - xml_lookupGeneric, - xml_lookupProperty, - xml_lookupElement, - xml_lookupSpecial, - xml_defineGeneric, - xml_defineProperty, - xml_defineElement, - xml_defineSpecial, - xml_getGeneric, - xml_getProperty, - xml_getElement, - NULL, /* getElementIfPresent */ - xml_getSpecial, - xml_setGeneric, - xml_setProperty, - xml_setElement, - xml_setSpecial, - xml_getGenericAttributes, - xml_getPropertyAttributes, - xml_getElementAttributes, - xml_getSpecialAttributes, - xml_setGenericAttributes, - xml_setPropertyAttributes, - xml_setElementAttributes, - xml_setSpecialAttributes, - xml_deleteProperty, - xml_deleteElement, - xml_deleteSpecial, - xml_enumerate, - xml_typeOf, - NULL, /* thisObject */ - } -}; - -static JSXML * -StartNonListXMLMethod(JSContext *cx, jsval *vp, MutableHandleObject objp) -{ - JSXML *xml; - JSFunction *fun; - char numBuf[12]; - - JS_ASSERT(!JSVAL_IS_PRIMITIVE(*vp)); - JS_ASSERT(JSVAL_TO_OBJECT(*vp)->isFunction()); - - objp.set(ToObject(cx, HandleValue::fromMarkedLocation(&vp[1]))); - if (!objp) - return NULL; - if (!objp->isXML()) { - ReportIncompatibleMethod(cx, CallReceiverFromVp(vp), &XMLClass); - return NULL; - } - xml = (JSXML *) objp->getPrivate(); - if (!xml || xml->xml_class != JSXML_CLASS_LIST) - return xml; - - if (xml->xml_kids.length == 1) { - xml = XMLARRAY_MEMBER(&xml->xml_kids, 0, JSXML); - if (xml) { - objp.set(js_GetXMLObject(cx, xml)); - if (!objp) - return NULL; - vp[1] = OBJECT_TO_JSVAL(objp); - return xml; - } - } - - fun = JSVAL_TO_OBJECT(*vp)->toFunction(); - JS_snprintf(numBuf, sizeof numBuf, "%u", xml->xml_kids.length); - JSAutoByteString funNameBytes; - if (const char *funName = GetFunctionNameBytes(cx, fun, &funNameBytes)) { - JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_NON_LIST_XML_METHOD, - funName, numBuf); - } - return NULL; -} - -/* Beware: these two are not bracketed by JS_BEGIN/END_MACRO. */ -#define XML_METHOD_PROLOG \ - JSObject *obj = ToObject(cx, HandleValue::fromMarkedLocation(&vp[1])); \ - if (!obj) \ - return JS_FALSE; \ - if (!obj->isXML()) { \ - ReportIncompatibleMethod(cx, CallReceiverFromVp(vp), &XMLClass); \ - return JS_FALSE; \ - } \ - JSXML *xml = (JSXML *)obj->getPrivate(); \ - if (!xml) \ - return JS_FALSE - -#define NON_LIST_XML_METHOD_PROLOG \ - RootedObject obj(cx); \ - JSXML *xml = StartNonListXMLMethod(cx, vp, &obj); \ - if (!xml) \ - return JS_FALSE; \ - JS_ASSERT(xml->xml_class != JSXML_CLASS_LIST) - -static JSBool -xml_addNamespace(JSContext *cx, unsigned argc, jsval *vp) -{ - JSObject *ns; - - NON_LIST_XML_METHOD_PROLOG; - if (xml->xml_class != JSXML_CLASS_ELEMENT) - goto done; - xml = CHECK_COPY_ON_WRITE(cx, xml, obj); - if (!xml) - return JS_FALSE; - - if (!NamespaceHelper(cx, argc == 0 ? -1 : 1, vp + 2, vp)) - return JS_FALSE; - JS_ASSERT(!JSVAL_IS_PRIMITIVE(*vp)); - - ns = JSVAL_TO_OBJECT(*vp); - if (!AddInScopeNamespace(cx, xml, ns)) - return JS_FALSE; - ns->setNamespaceDeclared(JSVAL_TRUE); - - done: - *vp = OBJECT_TO_JSVAL(obj); - return JS_TRUE; -} - -static JSBool -xml_appendChild(JSContext *cx, unsigned argc, jsval *vp) -{ - NON_LIST_XML_METHOD_PROLOG; - xml = CHECK_COPY_ON_WRITE(cx, xml, obj); - if (!xml) - return JS_FALSE; - - RootedId name(cx); - if (!js_GetAnyName(cx, name.address())) - return JS_FALSE; - - RootedValue v(cx); - if (!GetProperty(cx, obj, name, &v)) - return JS_FALSE; - - JS_ASSERT(!JSVAL_IS_PRIMITIVE(v)); - Rooted vobj(cx, &v.toObject()); - JS_ASSERT(vobj->isXML()); - JSXML *vxml = (JSXML *) vobj->getPrivate(); - JS_ASSERT(vxml->xml_class == JSXML_CLASS_LIST); - - if (!IndexToId(cx, vxml->xml_kids.length, &name)) - return JS_FALSE; - *vp = (argc != 0) ? vp[2] : JSVAL_VOID; - - if (!PutProperty(cx, vobj, name, false, MutableHandleValue::fromMarkedLocation(vp))) - return JS_FALSE; - - *vp = OBJECT_TO_JSVAL(obj); - return JS_TRUE; -} - -/* XML and XMLList */ -static JSBool -xml_attribute(JSContext *cx, unsigned argc, jsval *vp) -{ - JSObject *qn; - - if (argc == 0) { - RootedValue val(cx, *vp); - js_ReportMissingArg(cx, val, 0); - return JS_FALSE; - } - - qn = ToAttributeName(cx, vp[2]); - if (!qn) - return JS_FALSE; - vp[2] = OBJECT_TO_JSVAL(qn); /* local root */ - - RootedId id(cx, OBJECT_TO_JSID(qn)); - RootedObject obj(cx, ToObject(cx, HandleValue::fromMarkedLocation(&vp[1]))); - if (!obj) - return JS_FALSE; - return GetProperty(cx, obj, id, MutableHandleValue::fromMarkedLocation(vp)); -} - -/* XML and XMLList */ -static JSBool -xml_attributes(JSContext *cx, unsigned argc, jsval *vp) -{ - jsval name = STRING_TO_JSVAL(cx->names().star); - JSObject *qn = ToAttributeName(cx, name); - if (!qn) - return JS_FALSE; - - RootedId id(cx, OBJECT_TO_JSID(qn)); - RootedObject obj(cx, ToObject(cx, HandleValue::fromMarkedLocation(&vp[1]))); - if (!obj) - return JS_FALSE; - return GetProperty(cx, obj, id, MutableHandleValue::fromMarkedLocation(vp)); -} - -static JSXML * -xml_list_helper(JSContext *cx, JSXML *xml, jsval *rval) -{ - JSObject *listobj; - JSXML *list; - - listobj = js_NewXMLObject(cx, JSXML_CLASS_LIST); - if (!listobj) - return NULL; - - *rval = OBJECT_TO_JSVAL(listobj); - list = (JSXML *) listobj->getPrivate(); - list->xml_target = xml; - return list; -} - -static JSBool -ValueToIdForXML(JSContext *cx, jsval v, jsid *idp) -{ - if (JSVAL_IS_INT(v)) { - int32_t i = JSVAL_TO_INT(v); - if (INT_FITS_IN_JSID(i)) { - *idp = INT_TO_JSID(i); - } else { - RootedId id(cx); - if (!ValueToId(cx, v, &id)) - return JS_FALSE; - *idp = id; - } - } else if (JSVAL_IS_STRING(v)) { - JSAtom *atom = AtomizeString(cx, JSVAL_TO_STRING(v)); - if (!atom) - return JS_FALSE; - *idp = AtomToId(atom); - } else if (!JSVAL_IS_PRIMITIVE(v)) { - *idp = OBJECT_TO_JSID(JSVAL_TO_OBJECT(v)); - } else { - ReportBadXMLName(cx, v); - return JS_FALSE; - } - return JS_TRUE; -} - -static JSBool -xml_child_helper(JSContext *cx, JSObject *obj_, JSXML *xml, jsval name, - MutableHandleValue rval) -{ - bool isIndex; - uint32_t index; - JSXML *kid; - JSObject *kidobj; - - /* ECMA-357 13.4.4.6 */ - JS_ASSERT(xml->xml_class != JSXML_CLASS_LIST); - - Rooted obj(cx, obj_); - - if (!IdValIsIndex(cx, name, &index, &isIndex)) - return JS_FALSE; - - if (isIndex) { - if (index >= JSXML_LENGTH(xml)) { - rval.setUndefined(); - } else { - kid = XMLARRAY_MEMBER(&xml->xml_kids, index, JSXML); - if (!kid) { - rval.setUndefined(); - } else { - kidobj = js_GetXMLObject(cx, kid); - if (!kidobj) - return JS_FALSE; - rval.set(OBJECT_TO_JSVAL(kidobj)); - } - } - return JS_TRUE; - } - - RootedId id(cx); - if (!ValueToIdForXML(cx, name, id.address())) - return JS_FALSE; - - return GetProperty(cx, obj, id, rval); -} - -/* XML and XMLList */ -static JSBool -xml_child(JSContext *cx, unsigned argc, jsval *vp) -{ - RootedValue v(cx); - JSXML *list, *vxml; - JSObject *kidobj; - - XML_METHOD_PROLOG; - jsval name = argc != 0 ? vp[2] : JSVAL_VOID; - if (xml->xml_class == JSXML_CLASS_LIST) { - /* ECMA-357 13.5.4.4 */ - list = xml_list_helper(cx, xml, vp); - if (!list) - return JS_FALSE; - - JSXMLArrayCursor cursor(&xml->xml_kids); - while (JSXML *kid = cursor.getNext()) { - kidobj = js_GetXMLObject(cx, kid); - if (!kidobj) - return JS_FALSE; - if (!xml_child_helper(cx, kidobj, kid, name, &v)) - return JS_FALSE; - if (JSVAL_IS_VOID(v)) { - /* The property didn't exist in this kid. */ - continue; - } - - JS_ASSERT(!JSVAL_IS_PRIMITIVE(v)); - vxml = (JSXML *) JSVAL_TO_OBJECT(v)->getPrivate(); - if ((!JSXML_HAS_KIDS(vxml) || vxml->xml_kids.length != 0) && - !Append(cx, list, vxml)) { - return JS_FALSE; - } - } - return JS_TRUE; - } - - /* ECMA-357 Edition 2 13.3.4.6 (note 13.3, not 13.4 as in Edition 1). */ - if (!xml_child_helper(cx, obj, xml, name, MutableHandleValue::fromMarkedLocation(vp))) - return JS_FALSE; - if (JSVAL_IS_VOID(*vp) && !xml_list_helper(cx, xml, vp)) - return JS_FALSE; - return JS_TRUE; -} - -static JSBool -xml_childIndex(JSContext *cx, unsigned argc, jsval *vp) -{ - JSXML *parent; - uint32_t i, n; - - NON_LIST_XML_METHOD_PROLOG; - parent = xml->parent; - if (!parent || xml->xml_class == JSXML_CLASS_ATTRIBUTE) { - *vp = DOUBLE_TO_JSVAL(js_NaN); - return JS_TRUE; - } - for (i = 0, n = JSXML_LENGTH(parent); i < n; i++) { - if (XMLARRAY_MEMBER(&parent->xml_kids, i, JSXML) == xml) - break; - } - JS_ASSERT(i < n); - if (i <= JSVAL_INT_MAX) - *vp = INT_TO_JSVAL(i); - else - *vp = DOUBLE_TO_JSVAL(i); - return JS_TRUE; -} - -/* XML and XMLList */ -static JSBool -xml_children(JSContext *cx, unsigned argc, jsval *vp) -{ - RootedObject obj(cx, ToObject(cx, HandleValue::fromMarkedLocation(&vp[1]))); - if (!obj) - return false; - RootedId name(cx, NameToId(cx->names().star)); - return GetProperty(cx, obj, name, MutableHandleValue::fromMarkedLocation(vp)); -} - -/* XML and XMLList */ -static JSBool -xml_comments_helper(JSContext *cx, JSObject *obj, JSXML *xml, jsval *vp) -{ - JSXML *list, *kid, *vxml; - JSBool ok; - uint32_t i, n; - JSObject *kidobj; - jsval v; - - list = xml_list_helper(cx, xml, vp); - if (!list) - return JS_FALSE; - - ok = JS_TRUE; - - if (xml->xml_class == JSXML_CLASS_LIST) { - /* 13.5.4.6 Step 2. */ - for (i = 0, n = JSXML_LENGTH(xml); i < n; i++) { - kid = XMLARRAY_MEMBER(&xml->xml_kids, i, JSXML); - if (kid && kid->xml_class == JSXML_CLASS_ELEMENT) { - kidobj = js_GetXMLObject(cx, kid); - if (kidobj) { - ok = xml_comments_helper(cx, kidobj, kid, &v); - } else { - ok = JS_FALSE; - v = JSVAL_NULL; - } - if (!ok) - break; - vxml = (JSXML *) JSVAL_TO_OBJECT(v)->getPrivate(); - if (JSXML_LENGTH(vxml) != 0) { - ok = Append(cx, list, vxml); - if (!ok) - break; - } - } - } - } else { - /* 13.4.4.9 Step 2. */ - for (i = 0, n = JSXML_LENGTH(xml); i < n; i++) { - kid = XMLARRAY_MEMBER(&xml->xml_kids, i, JSXML); - if (kid && kid->xml_class == JSXML_CLASS_COMMENT) { - ok = Append(cx, list, kid); - if (!ok) - break; - } - } - } - - return ok; -} - -static JSBool -xml_comments(JSContext *cx, unsigned argc, jsval *vp) -{ - XML_METHOD_PROLOG; - return xml_comments_helper(cx, obj, xml, vp); -} - -/* XML and XMLList */ -static JSBool -xml_contains(JSContext *cx, unsigned argc, jsval *vp) -{ - jsval value; - JSBool eq; - JSObject *kidobj; - - XML_METHOD_PROLOG; - value = argc != 0 ? vp[2] : JSVAL_VOID; - if (xml->xml_class == JSXML_CLASS_LIST) { - eq = JS_FALSE; - JSXMLArrayCursor cursor(&xml->xml_kids); - while (JSXML *kid = cursor.getNext()) { - kidobj = js_GetXMLObject(cx, kid); - if (!kidobj || !js_TestXMLEquality(cx, ObjectValue(*kidobj), value, &eq)) - return JS_FALSE; - if (eq) - break; - } - } else { - if (!js_TestXMLEquality(cx, ObjectValue(*obj), value, &eq)) - return JS_FALSE; - } - *vp = BOOLEAN_TO_JSVAL(eq); - return JS_TRUE; -} - -/* XML and XMLList */ -static JSBool -xml_copy(JSContext *cx, unsigned argc, jsval *vp) -{ - JSXML *copy; - - XML_METHOD_PROLOG; - copy = DeepCopy(cx, xml, NULL, 0); - if (!copy) - return JS_FALSE; - *vp = OBJECT_TO_JSVAL(copy->object); - return JS_TRUE; -} - -/* XML and XMLList */ -static JSBool -xml_descendants(JSContext *cx, unsigned argc, jsval *vp) -{ - jsval name; - JSXML *list; - - XML_METHOD_PROLOG; - name = argc == 0 ? STRING_TO_JSVAL(cx->names().star) : vp[2]; - list = Descendants(cx, xml, name); - if (!list) - return JS_FALSE; - *vp = OBJECT_TO_JSVAL(list->object); - return JS_TRUE; -} - -/* XML and XMLList */ -static JSBool -xml_elements_helper(JSContext *cx, JSObject *obj, JSXML *xml, - JSObject *nameqn, jsval *vp) -{ - JSXML *list, *vxml; - jsval v; - JSBool ok; - JSObject *kidobj; - uint32_t i, n; - - list = xml_list_helper(cx, xml, vp); - if (!list) - return JS_FALSE; - - list->xml_targetprop = nameqn; - ok = JS_TRUE; - - if (xml->xml_class == JSXML_CLASS_LIST) { - /* 13.5.4.6 */ - JSXMLArrayCursor cursor(&xml->xml_kids); - while (JSXML *kid = cursor.getNext()) { - if (kid->xml_class == JSXML_CLASS_ELEMENT) { - kidobj = js_GetXMLObject(cx, kid); - if (kidobj) { - ok = xml_elements_helper(cx, kidobj, kid, nameqn, &v); - } else { - ok = JS_FALSE; - v = JSVAL_NULL; - } - if (!ok) - break; - vxml = (JSXML *) JSVAL_TO_OBJECT(v)->getPrivate(); - if (JSXML_LENGTH(vxml) != 0) { - ok = Append(cx, list, vxml); - if (!ok) - break; - } - } - } - } else { - for (i = 0, n = JSXML_LENGTH(xml); i < n; i++) { - JSXML *kid = XMLARRAY_MEMBER(&xml->xml_kids, i, JSXML); - if (kid && kid->xml_class == JSXML_CLASS_ELEMENT && - MatchElemName(nameqn, kid)) { - ok = Append(cx, list, kid); - if (!ok) - break; - } - } - } - - return ok; -} - -static JSBool -xml_elements(JSContext *cx, unsigned argc, jsval *vp) -{ - jsval name; - JSObject *nameqn; - jsid funid; - - XML_METHOD_PROLOG; - - name = (argc == 0) ? STRING_TO_JSVAL(cx->names().star) : vp[2]; - nameqn = ToXMLName(cx, name, &funid); - if (!nameqn) - return JS_FALSE; - - if (!JSID_IS_VOID(funid)) - return xml_list_helper(cx, xml, vp) != NULL; - - return xml_elements_helper(cx, obj, xml, nameqn, vp); -} - -/* XML and XMLList */ -static JSBool -xml_hasOwnProperty(JSContext *cx, unsigned argc, jsval *vp) -{ - CallArgs args = CallArgsFromVp(argc, vp); - - RootedObject obj(cx, ToObject(cx, args.thisv())); - if (!obj) - return false; - if (!obj->isXML()) { - ReportIncompatibleMethod(cx, CallReceiverFromVp(vp), &XMLClass); - return false; - } - - Value name = args.length() != 0 ? args[0] : UndefinedValue(); - JSBool found; - if (!HasProperty(cx, obj, name, &found)) - return false; - if (found) { - args.rval().setBoolean(true); - return true; - } - - RootedId id(cx); - if (!ValueToId(cx, name, &id)) - return false; - - RootedObject obj2(cx); - RootedShape prop(cx); - if (!HasOwnProperty(cx, baseops::LookupProperty, obj, id, &obj2, &prop)) - return false; - args.rval().setBoolean(!!prop); - return true; -} - -/* XML and XMLList */ -static JSBool -xml_hasComplexContent(JSContext *cx, unsigned argc, jsval *vp) -{ - JSXML *kid; - JSObject *kidobj; - uint32_t i, n; - - XML_METHOD_PROLOG; -again: - switch (xml->xml_class) { - case JSXML_CLASS_ATTRIBUTE: - case JSXML_CLASS_COMMENT: - case JSXML_CLASS_PROCESSING_INSTRUCTION: - case JSXML_CLASS_TEXT: - *vp = JSVAL_FALSE; - break; - case JSXML_CLASS_LIST: - if (xml->xml_kids.length == 0) { - *vp = JSVAL_TRUE; - } else if (xml->xml_kids.length == 1) { - kid = XMLARRAY_MEMBER(&xml->xml_kids, 0, JSXML); - if (kid) { - kidobj = js_GetXMLObject(cx, kid); - if (!kidobj) - return JS_FALSE; - obj = kidobj; - xml = (JSXML *) obj->getPrivate(); - goto again; - } - } - /* FALL THROUGH */ - default: - *vp = JSVAL_FALSE; - for (i = 0, n = xml->xml_kids.length; i < n; i++) { - kid = XMLARRAY_MEMBER(&xml->xml_kids, i, JSXML); - if (kid && kid->xml_class == JSXML_CLASS_ELEMENT) { - *vp = JSVAL_TRUE; - break; - } - } - break; - } - return JS_TRUE; -} - -/* XML and XMLList */ -static JSBool -xml_hasSimpleContent(JSContext *cx, unsigned argc, jsval *vp) -{ - XML_METHOD_PROLOG; - *vp = BOOLEAN_TO_JSVAL(HasSimpleContent(xml)); - return JS_TRUE; -} - -static JSBool -FindInScopeNamespaces(JSContext *cx, JSXML *xml, JSXMLArray *nsarray) -{ - uint32_t length, i, j, n; - JSObject *ns, *ns2; - JSLinearString *prefix, *prefix2; - - length = nsarray->length; - do { - if (xml->xml_class != JSXML_CLASS_ELEMENT) - continue; - for (i = 0, n = xml->xml_namespaces.length; i < n; i++) { - ns = XMLARRAY_MEMBER(&xml->xml_namespaces, i, JSObject); - if (!ns) - continue; - - prefix = ns->getNamePrefix(); - for (j = 0; j < length; j++) { - ns2 = XMLARRAY_MEMBER(nsarray, j, JSObject); - if (ns2) { - prefix2 = ns2->getNamePrefix(); - if ((prefix2 && prefix) - ? EqualStrings(prefix2, prefix) - : EqualStrings(ns2->getNameURI(), ns->getNameURI())) { - break; - } - } - } - - if (j == length) { - if (!XMLARRAY_APPEND(cx, nsarray, ns)) - return JS_FALSE; - ++length; - } - } - } while ((xml = xml->parent) != NULL); - JS_ASSERT(length == nsarray->length); - - return JS_TRUE; -} - -/* - * Populate a new JS array with elements of array and place the result into - * rval. rval must point to a rooted location. - */ -static bool -NamespacesToJSArray(JSContext *cx, JSXMLArray *array, jsval *rval) -{ - Rooted arrayobj(cx, NewDenseEmptyArray(cx)); - if (!arrayobj) - return false; - *rval = OBJECT_TO_JSVAL(arrayobj); - - RootedValue v(cx); - for (uint32_t i = 0, n = array->length; i < n; i++) { - JSObject *ns = XMLARRAY_MEMBER(array, i, JSObject); - if (!ns) - continue; - v.setObject(*ns); - if (!JSObject::setElement(cx, arrayobj, arrayobj, i, &v, false)) - return false; - } - return true; -} - -static JSBool -xml_inScopeNamespaces(JSContext *cx, unsigned argc, jsval *vp) -{ - NON_LIST_XML_METHOD_PROLOG; - - AutoNamespaceArray namespaces(cx); - return FindInScopeNamespaces(cx, xml, &namespaces.array) && - NamespacesToJSArray(cx, &namespaces.array, vp); -} - -static JSBool -xml_insertChildAfter(JSContext *cx, unsigned argc, jsval *vp) -{ - jsval arg; - JSXML *kid; - uint32_t i; - - NON_LIST_XML_METHOD_PROLOG; - *vp = OBJECT_TO_JSVAL(obj); - if (!JSXML_HAS_KIDS(xml) || argc == 0) - return JS_TRUE; - - arg = vp[2]; - if (JSVAL_IS_NULL(arg)) { - kid = NULL; - i = 0; - } else { - if (!VALUE_IS_XML(arg)) - return JS_TRUE; - kid = (JSXML *) JSVAL_TO_OBJECT(arg)->getPrivate(); - i = XMLARRAY_FIND_MEMBER(&xml->xml_kids, kid, pointer_match); - if (i == XML_NOT_FOUND) - return JS_TRUE; - ++i; - } - - xml = CHECK_COPY_ON_WRITE(cx, xml, obj); - if (!xml) - return JS_FALSE; - return Insert(cx, xml, i, argc >= 2 ? vp[3] : JSVAL_VOID); -} - -static JSBool -xml_insertChildBefore(JSContext *cx, unsigned argc, jsval *vp) -{ - jsval arg; - JSXML *kid; - uint32_t i; - - NON_LIST_XML_METHOD_PROLOG; - *vp = OBJECT_TO_JSVAL(obj); - if (!JSXML_HAS_KIDS(xml) || argc == 0) - return JS_TRUE; - - arg = vp[2]; - if (JSVAL_IS_NULL(arg)) { - kid = NULL; - i = xml->xml_kids.length; - } else { - if (!VALUE_IS_XML(arg)) - return JS_TRUE; - kid = (JSXML *) JSVAL_TO_OBJECT(arg)->getPrivate(); - i = XMLARRAY_FIND_MEMBER(&xml->xml_kids, kid, pointer_match); - if (i == XML_NOT_FOUND) - return JS_TRUE; - } - - xml = CHECK_COPY_ON_WRITE(cx, xml, obj); - if (!xml) - return JS_FALSE; - return Insert(cx, xml, i, argc >= 2 ? vp[3] : JSVAL_VOID); -} - -/* XML and XMLList */ -static JSBool -xml_length(JSContext *cx, unsigned argc, jsval *vp) -{ - XML_METHOD_PROLOG; - if (xml->xml_class != JSXML_CLASS_LIST) { - *vp = JSVAL_ONE; - } else { - uint32_t l = xml->xml_kids.length; - if (l <= JSVAL_INT_MAX) - *vp = INT_TO_JSVAL(l); - else - *vp = DOUBLE_TO_JSVAL(l); - } - return JS_TRUE; -} - -static JSBool -xml_localName(JSContext *cx, unsigned argc, jsval *vp) -{ - NON_LIST_XML_METHOD_PROLOG; - *vp = xml->name ? xml->name->getQNameLocalNameVal() : JSVAL_NULL; - return JS_TRUE; -} - -static JSBool -xml_name(JSContext *cx, unsigned argc, jsval *vp) -{ - NON_LIST_XML_METHOD_PROLOG; - *vp = OBJECT_TO_JSVAL(xml->name); - return JS_TRUE; -} - -static JSBool -xml_namespace(JSContext *cx, unsigned argc, jsval *vp) -{ - JSLinearString *prefix, *nsprefix; - uint32_t i, length; - JSObject *ns; - - NON_LIST_XML_METHOD_PROLOG; - if (argc == 0 && !JSXML_HAS_NAME(xml)) { - *vp = JSVAL_NULL; - return true; - } - - if (argc == 0) { - prefix = NULL; - } else { - JSString *str = ToString(cx, vp[2]); - if (!str) - return false; - prefix = str->ensureLinear(cx); - if (!prefix) - return false; - vp[2] = STRING_TO_JSVAL(prefix); /* local root */ - } - - AutoNamespaceArray inScopeNSes(cx); - if (!FindInScopeNamespaces(cx, xml, &inScopeNSes.array)) - return false; - - if (!prefix) { - ns = GetNamespace(cx, xml->name, &inScopeNSes.array); - if (!ns) - return false; - } else { - ns = NULL; - for (i = 0, length = inScopeNSes.array.length; i < length; i++) { - ns = XMLARRAY_MEMBER(&inScopeNSes.array, i, JSObject); - if (ns) { - nsprefix = ns->getNamePrefix(); - if (nsprefix && EqualStrings(nsprefix, prefix)) - break; - ns = NULL; - } - } - } - - *vp = (!ns) ? JSVAL_VOID : OBJECT_TO_JSVAL(ns); - return true; -} - -static JSBool -xml_namespaceDeclarations(JSContext *cx, unsigned argc, jsval *vp) -{ - NON_LIST_XML_METHOD_PROLOG; - if (JSXML_HAS_VALUE(xml)) - return true; - - AutoNamespaceArray ancestors(cx); - AutoNamespaceArray declared(cx); - - JSXML *yml = xml; - while ((yml = yml->parent) != NULL) { - JS_ASSERT(yml->xml_class == JSXML_CLASS_ELEMENT); - for (uint32_t i = 0, n = yml->xml_namespaces.length; i < n; i++) { - JSObject *ns = XMLARRAY_MEMBER(&yml->xml_namespaces, i, JSObject); - if (ns && !XMLARRAY_HAS_MEMBER(&ancestors.array, ns, namespace_match)) { - if (!XMLARRAY_APPEND(cx, &ancestors.array, ns)) - return false; - } - } - } - - for (uint32_t i = 0, n = xml->xml_namespaces.length; i < n; i++) { - JSObject *ns = XMLARRAY_MEMBER(&xml->xml_namespaces, i, JSObject); - if (!ns) - continue; - if (!IsDeclared(ns)) - continue; - if (!XMLARRAY_HAS_MEMBER(&ancestors.array, ns, namespace_match)) { - if (!XMLARRAY_APPEND(cx, &declared.array, ns)) - return false; - } - } - - return NamespacesToJSArray(cx, &declared.array, vp); -} - -static const char js_attribute_str[] = "attribute"; -static const char js_text_str[] = "text"; - -/* Exported to jsgc.c #ifdef DEBUG. */ -const char *js_xml_class_str[] = { - "list", - "element", - js_attribute_str, - "processing-instruction", - js_text_str, - "comment" -}; - -static JSBool -xml_nodeKind(JSContext *cx, unsigned argc, jsval *vp) -{ - JSString *str; - - NON_LIST_XML_METHOD_PROLOG; - str = JS_InternString(cx, js_xml_class_str[xml->xml_class]); - if (!str) - return JS_FALSE; - *vp = STRING_TO_JSVAL(str); - return JS_TRUE; -} - -static void -NormalizingDelete(JSContext *cx, JSXML *xml, uint32_t index) -{ - if (xml->xml_class == JSXML_CLASS_LIST) - DeleteListElement(cx, xml, index); - else - DeleteByIndex(cx, xml, index); -} - -/* XML and XMLList */ -static JSBool -xml_normalize_helper(JSContext *cx, JSObject *obj, JSXML *xml) -{ - JSXML *kid, *kid2; - uint32_t i, n; - JSObject *kidobj; - JSString *str; - - if (!JSXML_HAS_KIDS(xml)) - return JS_TRUE; - - xml = CHECK_COPY_ON_WRITE(cx, xml, obj); - if (!xml) - return JS_FALSE; - - for (i = 0, n = xml->xml_kids.length; i < n; i++) { - kid = XMLARRAY_MEMBER(&xml->xml_kids, i, JSXML); - if (!kid) - continue; - if (kid->xml_class == JSXML_CLASS_ELEMENT) { - kidobj = js_GetXMLObject(cx, kid); - if (!kidobj || !xml_normalize_helper(cx, kidobj, kid)) - return JS_FALSE; - } else if (kid->xml_class == JSXML_CLASS_TEXT) { - while (i + 1 < n && - (kid2 = XMLARRAY_MEMBER(&xml->xml_kids, i + 1, JSXML)) && - kid2->xml_class == JSXML_CLASS_TEXT) - { - Rooted lstr(cx, kid->xml_value); - Rooted rstr(cx, kid2->xml_value); - str = ConcatStrings(cx, lstr, rstr); - if (!str) - return JS_FALSE; - NormalizingDelete(cx, xml, i + 1); - n = xml->xml_kids.length; - kid->xml_value = str; - } - if (kid->xml_value->empty()) { - NormalizingDelete(cx, xml, i); - n = xml->xml_kids.length; - --i; - } - } - } - - return JS_TRUE; -} - -static JSBool -xml_normalize(JSContext *cx, unsigned argc, jsval *vp) -{ - XML_METHOD_PROLOG; - *vp = OBJECT_TO_JSVAL(obj); - return xml_normalize_helper(cx, obj, xml); -} - -/* XML and XMLList */ -static JSBool -xml_parent(JSContext *cx, unsigned argc, jsval *vp) -{ - JSXML *parent, *kid; - uint32_t i, n; - JSObject *parentobj; - - XML_METHOD_PROLOG; - parent = xml->parent; - if (xml->xml_class == JSXML_CLASS_LIST) { - *vp = JSVAL_VOID; - n = xml->xml_kids.length; - if (n == 0) - return JS_TRUE; - - kid = XMLARRAY_MEMBER(&xml->xml_kids, 0, JSXML); - if (!kid) - return JS_TRUE; - parent = kid->parent; - for (i = 1; i < n; i++) { - kid = XMLARRAY_MEMBER(&xml->xml_kids, i, JSXML); - if (kid && kid->parent != parent) - return JS_TRUE; - } - } - - if (!parent) { - *vp = JSVAL_NULL; - return JS_TRUE; - } - - parentobj = js_GetXMLObject(cx, parent); - if (!parentobj) - return JS_FALSE; - *vp = OBJECT_TO_JSVAL(parentobj); - return JS_TRUE; -} - -/* XML and XMLList */ -static JSBool -xml_processingInstructions_helper(JSContext *cx, JSObject *obj, JSXML *xml, - JSObject *nameqn, jsval *vp) -{ - JSXML *list, *vxml; - JSBool ok; - JSObject *kidobj; - jsval v; - uint32_t i, n; - - list = xml_list_helper(cx, xml, vp); - if (!list) - return JS_FALSE; - - list->xml_targetprop = nameqn; - ok = JS_TRUE; - - if (xml->xml_class == JSXML_CLASS_LIST) { - /* 13.5.4.17 Step 4 (misnumbered 9 -- Erratum?). */ - JSXMLArrayCursor cursor(&xml->xml_kids); - while (JSXML *kid = cursor.getNext()) { - if (kid->xml_class == JSXML_CLASS_ELEMENT) { - kidobj = js_GetXMLObject(cx, kid); - if (kidobj) { - ok = xml_processingInstructions_helper(cx, kidobj, kid, - nameqn, &v); - } else { - ok = JS_FALSE; - v = JSVAL_NULL; - } - if (!ok) - break; - vxml = (JSXML *) JSVAL_TO_OBJECT(v)->getPrivate(); - if (JSXML_LENGTH(vxml) != 0) { - ok = Append(cx, list, vxml); - if (!ok) - break; - } - } - } - } else { - /* 13.4.4.28 Step 4. */ - for (i = 0, n = JSXML_LENGTH(xml); i < n; i++) { - JSXML *kid = XMLARRAY_MEMBER(&xml->xml_kids, i, JSXML); - if (kid && kid->xml_class == JSXML_CLASS_PROCESSING_INSTRUCTION) { - JSLinearString *localName = nameqn->getQNameLocalName(); - if (IS_STAR(localName) || - EqualStrings(localName, kid->name->getQNameLocalName())) { - ok = Append(cx, list, kid); - if (!ok) - break; - } - } - } - } - - return ok; -} - -static JSBool -xml_processingInstructions(JSContext *cx, unsigned argc, jsval *vp) -{ - jsval name; - JSObject *nameqn; - jsid funid; - - XML_METHOD_PROLOG; - - name = (argc == 0) ? STRING_TO_JSVAL(cx->names().star) : vp[2]; - nameqn = ToXMLName(cx, name, &funid); - if (!nameqn) - return JS_FALSE; - vp[2] = OBJECT_TO_JSVAL(nameqn); - - if (!JSID_IS_VOID(funid)) - return xml_list_helper(cx, xml, vp) != NULL; - - return xml_processingInstructions_helper(cx, obj, xml, nameqn, vp); -} - -static JSBool -xml_prependChild(JSContext *cx, unsigned argc, jsval *vp) -{ - NON_LIST_XML_METHOD_PROLOG; - xml = CHECK_COPY_ON_WRITE(cx, xml, obj); - if (!xml) - return JS_FALSE; - *vp = OBJECT_TO_JSVAL(obj); - return Insert(cx, xml, 0, argc != 0 ? vp[2] : JSVAL_VOID); -} - -/* XML and XMLList */ -static JSBool -xml_propertyIsEnumerable(JSContext *cx, unsigned argc, jsval *vp) -{ - bool isIndex; - uint32_t index; - - XML_METHOD_PROLOG; - *vp = JSVAL_FALSE; - if (argc != 0) { - if (!IdValIsIndex(cx, vp[2], &index, &isIndex)) - return JS_FALSE; - - if (isIndex) { - if (xml->xml_class == JSXML_CLASS_LIST) { - /* 13.5.4.18. */ - *vp = BOOLEAN_TO_JSVAL(index < xml->xml_kids.length); - } else { - /* 13.4.4.30. */ - *vp = BOOLEAN_TO_JSVAL(index == 0); - } - } - } - return JS_TRUE; -} - -static JSBool -namespace_full_match(const JSObject *nsa, const JSObject *nsb) -{ - JSLinearString *prefixa = nsa->getNamePrefix(); - JSLinearString *prefixb; - - if (prefixa) { - prefixb = nsb->getNamePrefix(); - if (prefixb && !EqualStrings(prefixa, prefixb)) - return JS_FALSE; - } - return EqualStrings(nsa->getNameURI(), nsb->getNameURI()); -} - -static JSBool -xml_removeNamespace_helper(JSContext *cx, JSXML *xml, JSObject *ns) -{ - JSObject *thisns, *attrns; - uint32_t i, n; - JSXML *attr, *kid; - - thisns = GetNamespace(cx, xml->name, &xml->xml_namespaces); - JS_ASSERT(thisns); - if (thisns == ns) - return JS_TRUE; - - for (i = 0, n = xml->xml_attrs.length; i < n; i++) { - attr = XMLARRAY_MEMBER(&xml->xml_attrs, i, JSXML); - if (!attr) - continue; - attrns = GetNamespace(cx, attr->name, &xml->xml_namespaces); - JS_ASSERT(attrns); - if (attrns == ns) - return JS_TRUE; - } - - i = XMLARRAY_FIND_MEMBER(&xml->xml_namespaces, ns, namespace_full_match); - if (i != XML_NOT_FOUND) - XMLArrayDelete(cx, &xml->xml_namespaces, i, JS_TRUE); - - for (i = 0, n = xml->xml_kids.length; i < n; i++) { - kid = XMLARRAY_MEMBER(&xml->xml_kids, i, JSXML); - if (kid && kid->xml_class == JSXML_CLASS_ELEMENT) { - if (!xml_removeNamespace_helper(cx, kid, ns)) - return JS_FALSE; - } - } - return JS_TRUE; -} - -static JSBool -xml_removeNamespace(JSContext *cx, unsigned argc, jsval *vp) -{ - JSObject *ns; - - NON_LIST_XML_METHOD_PROLOG; - if (xml->xml_class != JSXML_CLASS_ELEMENT) - goto done; - xml = CHECK_COPY_ON_WRITE(cx, xml, obj); - if (!xml) - return JS_FALSE; - - if (!NamespaceHelper(cx, argc == 0 ? -1 : 1, vp + 2, vp)) - return JS_FALSE; - JS_ASSERT(!JSVAL_IS_PRIMITIVE(*vp)); - ns = JSVAL_TO_OBJECT(*vp); - - /* NOTE: remove ns from each ancestor if not used by that ancestor. */ - if (!xml_removeNamespace_helper(cx, xml, ns)) - return JS_FALSE; - done: - *vp = OBJECT_TO_JSVAL(obj); - return JS_TRUE; -} - -static JSBool -xml_replace(JSContext *cx, unsigned argc, jsval *vp) -{ - jsval value; - JSXML *vxml, *kid; - uint32_t index, i; - JSObject *nameqn; - - NON_LIST_XML_METHOD_PROLOG; - if (xml->xml_class != JSXML_CLASS_ELEMENT) - goto done; - - if (argc <= 1) { - value = STRING_TO_JSVAL(cx->names().undefined); - } else { - value = vp[3]; - vxml = VALUE_IS_XML(value) - ? (JSXML *) JSVAL_TO_OBJECT(value)->getPrivate() - : NULL; - if (!vxml) { - if (!JS_ConvertValue(cx, value, JSTYPE_STRING, &vp[3])) - return JS_FALSE; - value = vp[3]; - } else { - vxml = DeepCopy(cx, vxml, NULL, 0); - if (!vxml) - return JS_FALSE; - value = vp[3] = OBJECT_TO_JSVAL(vxml->object); - } - } - - xml = CHECK_COPY_ON_WRITE(cx, xml, obj); - if (!xml) - return JS_FALSE; - - bool haveIndex; - if (argc == 0) { - haveIndex = false; - } else { - if (!IdValIsIndex(cx, vp[2], &index, &haveIndex)) - return JS_FALSE; - } - - if (!haveIndex) { - /* - * Call function QName per spec, not ToXMLName, to avoid attribute - * names. - */ - if (!QNameHelper(cx, argc == 0 ? -1 : 1, vp + 2, vp)) - return JS_FALSE; - JS_ASSERT(!JSVAL_IS_PRIMITIVE(*vp)); - nameqn = JSVAL_TO_OBJECT(*vp); - - i = xml->xml_kids.length; - index = XML_NOT_FOUND; - while (i != 0) { - --i; - kid = XMLARRAY_MEMBER(&xml->xml_kids, i, JSXML); - if (kid && MatchElemName(nameqn, kid)) { - if (i != XML_NOT_FOUND) - DeleteByIndex(cx, xml, i); - index = i; - } - } - - if (index == XML_NOT_FOUND) - goto done; - } - - if (!Replace(cx, xml, index, value)) - return JS_FALSE; - - done: - *vp = OBJECT_TO_JSVAL(obj); - return JS_TRUE; -} - -static JSBool -xml_setChildren(JSContext *cx, unsigned argc, jsval *vp) -{ - RootedObject obj(cx); - - if (!StartNonListXMLMethod(cx, vp, &obj)) - return JS_FALSE; - - Rooted id(cx, NameToId(cx->names().star)); - *vp = argc != 0 ? vp[2] : JSVAL_VOID; /* local root */ - if (!PutProperty(cx, obj, id, false, MutableHandleValue::fromMarkedLocation(vp))) - return JS_FALSE; - - *vp = OBJECT_TO_JSVAL(obj); - return JS_TRUE; -} - -static JSBool -xml_setLocalName(JSContext *cx, unsigned argc, jsval *vp) -{ - NON_LIST_XML_METHOD_PROLOG; - if (!JSXML_HAS_NAME(xml)) { - vp[0] = JSVAL_VOID; - return JS_TRUE; - } - - JSAtom *namestr; - if (argc == 0) { - namestr = cx->names().undefined; - } else { - jsval name = vp[2]; - if (!JSVAL_IS_PRIMITIVE(name) && JSVAL_TO_OBJECT(name)->isQName()) { - namestr = JSVAL_TO_OBJECT(name)->getQNameLocalName(); - } else { - namestr = ToAtom(cx, name); - if (!namestr) - return false; - } - } - - xml = CHECK_COPY_ON_WRITE(cx, xml, obj); - if (!xml) - return JS_FALSE; - if (namestr) - xml->name->setQNameLocalName(namestr); - vp[0] = JSVAL_VOID; - return JS_TRUE; -} - -static JSBool -xml_setName(JSContext *cx, unsigned argc, jsval *vp) -{ - jsval name; - JSObject *nameqn; - JSXML *nsowner; - JSXMLArray *nsarray; - uint32_t i, n; - JSObject *ns; - - NON_LIST_XML_METHOD_PROLOG; - if (!JSXML_HAS_NAME(xml)) - return JS_TRUE; - - if (argc == 0) { - name = STRING_TO_JSVAL(cx->names().undefined); - } else { - name = vp[2]; - if (!JSVAL_IS_PRIMITIVE(name) && - JSVAL_TO_OBJECT(name)->getClass() == &QNameClass && - !(nameqn = JSVAL_TO_OBJECT(name))->getNameURI()) { - name = vp[2] = nameqn->getQNameLocalNameVal(); - } - } - - nameqn = ConstructObjectWithArguments(cx, &QNameClass, 1, &name); - if (!nameqn) - return JS_FALSE; - - /* ECMA-357 13.4.4.35 Step 4. */ - if (xml->xml_class == JSXML_CLASS_PROCESSING_INSTRUCTION) - nameqn->setNameURI(cx->runtime->emptyString); - - xml = CHECK_COPY_ON_WRITE(cx, xml, obj); - if (!xml) - return JS_FALSE; - xml->name = nameqn; - - /* - * Erratum: nothing in 13.4.4.35 talks about making the name match the - * in-scope namespaces, either by finding an in-scope namespace with a - * matching uri and setting the new name's prefix to that namespace's - * prefix, or by extending the in-scope namespaces for xml (which are in - * xml->parent if xml is an attribute or a PI). - */ - if (xml->xml_class == JSXML_CLASS_ELEMENT) { - nsowner = xml; - } else { - if (!xml->parent || xml->parent->xml_class != JSXML_CLASS_ELEMENT) - return JS_TRUE; - nsowner = xml->parent; - } - - if (nameqn->getNamePrefix()) { - /* - * The name being set has a prefix, which originally came from some - * namespace object (which may be the null namespace, where both the - * prefix and uri are the empty string). We must go through a full - * GetNamespace in case that namespace is in-scope in nsowner. - * - * If we find such an in-scope namespace, we return true right away, - * in this block. Otherwise, we fall through to the final return of - * AddInScopeNamespace(cx, nsowner, ns). - */ - ns = GetNamespace(cx, nameqn, &nsowner->xml_namespaces); - if (!ns) - return JS_FALSE; - - /* XXXbe have to test membership to see whether GetNamespace added */ - if (XMLARRAY_HAS_MEMBER(&nsowner->xml_namespaces, ns, pointer_match)) { - vp[0] = JSVAL_VOID; - return JS_TRUE; - } - } else { - /* - * At this point, we know prefix of nameqn is null, so its uri can't - * be the empty string (the null namespace always uses the empty string - * for both prefix and uri). - * - * This means we must inline GetNamespace and specialize it to match - * uri only, never prefix. If we find a namespace with nameqn's uri - * already in nsowner->xml_namespaces, then all that we need do is set - * prefix of nameqn to that namespace's prefix. - * - * If no such namespace exists, we can create one without going through - * the constructor, because we know uri of nameqn is non-empty (so - * prefix does not need to be converted from null to empty by QName). - */ - JS_ASSERT(!nameqn->getNameURI()->empty()); - - nsarray = &nsowner->xml_namespaces; - for (i = 0, n = nsarray->length; i < n; i++) { - ns = XMLARRAY_MEMBER(nsarray, i, JSObject); - if (ns && EqualStrings(ns->getNameURI(), nameqn->getNameURI())) { - nameqn->setNamePrefix(ns->getNamePrefix()); - vp[0] = JSVAL_VOID; - return JS_TRUE; - } - } - - ns = NewXMLNamespace(cx, NULL, nameqn->getNameURI(), JS_TRUE); - if (!ns) - return JS_FALSE; - } - - if (!AddInScopeNamespace(cx, nsowner, ns)) - return JS_FALSE; - vp[0] = JSVAL_VOID; - return JS_TRUE; -} - -/* Utility function used within xml_setNamespace */ -static JSBool qn_match(const JSXML *xml, const JSObject *qn) -{ - return qname_identity(xml->name, qn); -} - -/* ECMA-357 13.4.4.36 */ -static JSBool -xml_setNamespace(JSContext *cx, unsigned argc, jsval *vp) -{ - JSObject *qn; - JSObject *ns; - jsval qnargv[2]; - JSXML *nsowner; - - NON_LIST_XML_METHOD_PROLOG; - if (!JSXML_HAS_NAME(xml)) - return JS_TRUE; - - ns = ConstructObjectWithArguments(cx, &NamespaceClass, argc == 0 ? 0 : 1, vp + 2); - if (!ns) - return JS_FALSE; - vp[0] = OBJECT_TO_JSVAL(ns); - ns->setNamespaceDeclared(JSVAL_TRUE); - - qnargv[0] = OBJECT_TO_JSVAL(ns); - qnargv[1] = OBJECT_TO_JSVAL(xml->name); - qn = ConstructObjectWithArguments(cx, &QNameClass, 2, qnargv); - if (!qn) - return JS_FALSE; - - /* - * Erratum: setting the namespace of an attribute may cause it to duplicate - * an already-existing attribute. To preserve the invariant that there are - * not multiple attributes with the same name, we delete the existing - * attribute so that the mutated attribute will not be a duplicate. - */ - if (xml->xml_class == JSXML_CLASS_ATTRIBUTE && - xml->parent && xml->parent->xml_class == JSXML_CLASS_ELEMENT && - !qn_match(xml, qn)) - { - JSXMLArray *array = &xml->parent->xml_attrs; - uint32_t i = XMLArrayFindMember(array, qn, qn_match); - if (i != XML_NOT_FOUND) - XMLArrayDelete(cx, array, i, JS_TRUE); - } - - xml->name = qn; - - /* - * Erratum: the spec fails to update the governing in-scope namespaces. - * See the erratum noted in xml_setName, above. - */ - if (xml->xml_class == JSXML_CLASS_ELEMENT) { - nsowner = xml; - } else { - if (!xml->parent || xml->parent->xml_class != JSXML_CLASS_ELEMENT) - return JS_TRUE; - nsowner = xml->parent; - } - if (!AddInScopeNamespace(cx, nsowner, ns)) - return JS_FALSE; - vp[0] = JSVAL_VOID; - return JS_TRUE; -} - -/* XML and XMLList */ -static JSBool -xml_text_helper(JSContext *cx, JSObject *obj, JSXML *xml, jsval *vp) -{ - JSXML *list, *kid, *vxml; - uint32_t i, n; - JSObject *kidobj; - jsval v; - - list = xml_list_helper(cx, xml, vp); - if (!list) - return JS_FALSE; - - if (xml->xml_class == JSXML_CLASS_LIST) { - for (i = 0, n = xml->xml_kids.length; i < n; i++) { - kid = XMLARRAY_MEMBER(&xml->xml_kids, i, JSXML); - if (kid && kid->xml_class == JSXML_CLASS_ELEMENT) { - JSBool ok; - kidobj = js_GetXMLObject(cx, kid); - if (kidobj) { - ok = xml_text_helper(cx, kidobj, kid, &v); - } else { - ok = JS_FALSE; - v = JSVAL_NULL; - } - if (!ok) - return JS_FALSE; - vxml = (JSXML *) JSVAL_TO_OBJECT(v)->getPrivate(); - if (JSXML_LENGTH(vxml) != 0 && !Append(cx, list, vxml)) - return JS_FALSE; - } - } - } else { - for (i = 0, n = JSXML_LENGTH(xml); i < n; i++) { - kid = XMLARRAY_MEMBER(&xml->xml_kids, i, JSXML); - if (kid && kid->xml_class == JSXML_CLASS_TEXT) { - if (!Append(cx, list, kid)) - return JS_FALSE; - } - } - } - return JS_TRUE; -} - -static JSBool -xml_text(JSContext *cx, unsigned argc, jsval *vp) -{ - XML_METHOD_PROLOG; - return xml_text_helper(cx, obj, xml, vp); -} - -/* XML and XMLList */ -static JSString * -xml_toString_helper(JSContext *cx, JSXML *xml) -{ - if (xml->xml_class == JSXML_CLASS_ATTRIBUTE || - xml->xml_class == JSXML_CLASS_TEXT) { - return xml->xml_value; - } - - if (!HasSimpleContent(xml)) - return ToXMLString(cx, OBJECT_TO_JSVAL(xml->object), 0); - - RootedString str(cx, cx->runtime->emptyString); - JSXMLArrayCursor cursor(&xml->xml_kids); - while (JSXML *kid = cursor.getNext()) { - if (kid->xml_class != JSXML_CLASS_COMMENT && - kid->xml_class != JSXML_CLASS_PROCESSING_INSTRUCTION) { - RootedString kidstr(cx, xml_toString_helper(cx, kid)); - if (!kidstr) { - str = NULL; - break; - } - str = ConcatStrings(cx, str, kidstr); - if (!str) - break; - } - } - return str; -} - -static JSBool -xml_toSource(JSContext *cx, unsigned argc, jsval *vp) -{ - JSObject *obj = ToObject(cx, HandleValue::fromMarkedLocation(&vp[1])); - if (!obj) - return JS_FALSE; - JSString *str = ToXMLString(cx, OBJECT_TO_JSVAL(obj), TO_SOURCE_FLAG); - if (!str) - return JS_FALSE; - *vp = STRING_TO_JSVAL(str); - return JS_TRUE; -} - -static JSBool -xml_toString(JSContext *cx, unsigned argc, jsval *vp) -{ - JSString *str; - - XML_METHOD_PROLOG; - str = xml_toString_helper(cx, xml); - if (!str) - return JS_FALSE; - *vp = STRING_TO_JSVAL(str); - return JS_TRUE; -} - -/* XML and XMLList */ -static JSBool -xml_toXMLString(JSContext *cx, unsigned argc, jsval *vp) -{ - JSObject *obj = ToObject(cx, HandleValue::fromMarkedLocation(&vp[1])); - if (!obj) - return JS_FALSE; - JSString *str = ToXMLString(cx, OBJECT_TO_JSVAL(obj), 0); - if (!str) - return JS_FALSE; - *vp = STRING_TO_JSVAL(str); - return JS_TRUE; -} - -/* XML and XMLList */ -static JSBool -xml_valueOf(JSContext *cx, unsigned argc, jsval *vp) -{ - JSObject *obj = ToObject(cx, HandleValue::fromMarkedLocation(&vp[1])); - if (!obj) - return false; - *vp = OBJECT_TO_JSVAL(obj); - return true; -} - -static JSFunctionSpec xml_methods[] = { - JS_FN("addNamespace", xml_addNamespace, 1,0), - JS_FN("appendChild", xml_appendChild, 1,0), - JS_FN(js_attribute_str, xml_attribute, 1,0), - JS_FN("attributes", xml_attributes, 0,0), - JS_FN("child", xml_child, 1,0), - JS_FN("childIndex", xml_childIndex, 0,0), - JS_FN("children", xml_children, 0,0), - JS_FN("comments", xml_comments, 0,0), - JS_FN("contains", xml_contains, 1,0), - JS_FN("copy", xml_copy, 0,0), - JS_FN("descendants", xml_descendants, 1,0), - JS_FN("elements", xml_elements, 1,0), - JS_FN("hasOwnProperty", xml_hasOwnProperty, 1,0), - JS_FN("hasComplexContent", xml_hasComplexContent, 1,0), - JS_FN("hasSimpleContent", xml_hasSimpleContent, 1,0), - JS_FN("inScopeNamespaces", xml_inScopeNamespaces, 0,0), - JS_FN("insertChildAfter", xml_insertChildAfter, 2,0), - JS_FN("insertChildBefore", xml_insertChildBefore, 2,0), - JS_FN(js_length_str, xml_length, 0,0), - JS_FN(js_localName_str, xml_localName, 0,0), - JS_FN(js_name_str, xml_name, 0,0), - JS_FN(js_namespace_str, xml_namespace, 1,0), - JS_FN("namespaceDeclarations", xml_namespaceDeclarations, 0,0), - JS_FN("nodeKind", xml_nodeKind, 0,0), - JS_FN("normalize", xml_normalize, 0,0), - JS_FN(js_xml_parent_str, xml_parent, 0,0), - JS_FN("processingInstructions",xml_processingInstructions,1,0), - JS_FN("prependChild", xml_prependChild, 1,0), - JS_FN("propertyIsEnumerable", xml_propertyIsEnumerable, 1,0), - JS_FN("removeNamespace", xml_removeNamespace, 1,0), - JS_FN("replace", xml_replace, 2,0), - JS_FN("setChildren", xml_setChildren, 1,0), - JS_FN("setLocalName", xml_setLocalName, 1,0), - JS_FN("setName", xml_setName, 1,0), - JS_FN("setNamespace", xml_setNamespace, 1,0), - JS_FN(js_text_str, xml_text, 0,0), - JS_FN(js_toSource_str, xml_toSource, 0,0), - JS_FN(js_toString_str, xml_toString, 0,0), - JS_FN(js_toXMLString_str, xml_toXMLString, 0,0), - JS_FN(js_valueOf_str, xml_valueOf, 0,0), - JS_FS_END -}; - -static JSBool -CopyXMLSettings(JSContext *cx, HandleObject from, HandleObject to) -{ - int i; - const char *name; - jsval v; - - /* 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 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; - } - - return true; -} - -static JSBool -SetDefaultXMLSettings(JSContext *cx, HandleObject obj) -{ - int i; - jsval v; - - /* 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; - } - return true; -} - -static JSBool -xml_settings(JSContext *cx, unsigned argc, jsval *vp) -{ - RootedObject settings(cx, JS_NewObject(cx, NULL, NULL, NULL)); - if (!settings) - return false; - *vp = OBJECT_TO_JSVAL(settings); - RootedObject obj(cx, ToObject(cx, HandleValue::fromMarkedLocation(&vp[1]))); - if (!obj) - return false; - return CopyXMLSettings(cx, obj, settings); -} - -static JSBool -xml_setSettings(JSContext *cx, unsigned argc, jsval *vp) -{ - jsval v; - JSBool ok; - - RootedObject obj(cx, ToObject(cx, HandleValue::fromMarkedLocation(&vp[1]))); - if (!obj) - return JS_FALSE; - v = (argc == 0) ? JSVAL_VOID : vp[2]; - if (JSVAL_IS_NULL(v) || JSVAL_IS_VOID(v)) { - ok = SetDefaultXMLSettings(cx, obj); - } else { - if (JSVAL_IS_PRIMITIVE(v)) { - vp[0] = JSVAL_VOID; - return JS_TRUE; - } - RootedObject settings(cx, JSVAL_TO_OBJECT(v)); - ok = CopyXMLSettings(cx, settings, obj); - } - vp[0] = JSVAL_VOID; - return ok; -} - -static JSBool -xml_defaultSettings(JSContext *cx, unsigned argc, jsval *vp) -{ - RootedObject settings(cx, JS_NewObject(cx, NULL, NULL, NULL)); - if (!settings) - return JS_FALSE; - *vp = OBJECT_TO_JSVAL(settings); - return SetDefaultXMLSettings(cx, settings); -} - -static JSFunctionSpec xml_static_methods[] = { - JS_FN("settings", xml_settings, 0,0), - JS_FN("setSettings", xml_setSettings, 1,0), - JS_FN("defaultSettings", xml_defaultSettings, 0,0), - JS_FS_END -}; - -static JSBool -XML(JSContext *cx, unsigned argc, Value *vp) -{ - JSXML *xml, *copy; - JSObject *xobj, *vobj; - Class *clasp; - - jsval v = argc ? vp[2] : JSVAL_VOID; - - if (JSVAL_IS_NULL(v) || JSVAL_IS_VOID(v)) - v = STRING_TO_JSVAL(cx->runtime->emptyString); - - xobj = ToXML(cx, v); - if (!xobj) - return JS_FALSE; - xml = (JSXML *) xobj->getPrivate(); - - if (IsConstructing(vp) && !JSVAL_IS_PRIMITIVE(v)) { - vobj = JSVAL_TO_OBJECT(v); - clasp = vobj->getClass(); - if (clasp == &XMLClass) { - copy = DeepCopy(cx, xml, NULL, 0); - if (!copy) - return JS_FALSE; - vp->setObject(*copy->object); - return JS_TRUE; - } - } - - vp->setObject(*xobj); - return JS_TRUE; -} - -static JSBool -XMLList(JSContext *cx, unsigned argc, jsval *vp) -{ - JSObject *vobj, *listobj; - JSXML *xml, *list; - - jsval v = argc ? vp[2] : JSVAL_VOID; - - if (JSVAL_IS_NULL(v) || JSVAL_IS_VOID(v)) - v = STRING_TO_JSVAL(cx->runtime->emptyString); - - if (IsConstructing(vp) && !JSVAL_IS_PRIMITIVE(v)) { - vobj = JSVAL_TO_OBJECT(v); - if (vobj->isXML()) { - xml = (JSXML *) vobj->getPrivate(); - if (xml->xml_class == JSXML_CLASS_LIST) { - listobj = js_NewXMLObject(cx, JSXML_CLASS_LIST); - if (!listobj) - return JS_FALSE; - *vp = OBJECT_TO_JSVAL(listobj); - - list = (JSXML *) listobj->getPrivate(); - if (!Append(cx, list, xml)) - return JS_FALSE; - return JS_TRUE; - } - } - } - - /* Toggle on XML support since the script has explicitly requested it. */ - listobj = ToXMLList(cx, v); - if (!listobj) - return JS_FALSE; - - *vp = OBJECT_TO_JSVAL(listobj); - return JS_TRUE; -} - -#ifdef DEBUG_notme -JSCList xml_leaks = JS_INIT_STATIC_CLIST(&xml_leaks); -uint32_t xml_serial; -#endif - -JSXML * -js_NewXML(JSContext *cx, JSXMLClass xml_class) -{ - cx->runtime->gcExactScanningEnabled = false; - - JSXML *xml = js_NewGCXML(cx); - if (!xml) - return NULL; - - xml->object.init(NULL); - xml->domnode = NULL; - xml->parent.init(NULL); - xml->name.init(NULL); - xml->xml_class = xml_class; - xml->xml_flags = 0; - if (JSXML_CLASS_HAS_VALUE(xml_class)) { - xml->xml_value.init(cx->runtime->emptyString); - } else { - xml->xml_value.init(NULL); - xml->xml_kids.init(); - if (xml_class == JSXML_CLASS_LIST) { - xml->xml_target.init(NULL); - xml->xml_targetprop.init(NULL); - } else { - xml->xml_namespaces.init(); - xml->xml_attrs.init(); - } - } - -#ifdef DEBUG_notme - JS_APPEND_LINK(&xml->links, &xml_leaks); - xml->serial = xml_serial++; -#endif - return xml; -} - -void -JSXML::writeBarrierPre(JSXML *xml) -{ -#ifdef JSGC_INCREMENTAL - if (!xml) - return; - - JS::Zone *zone = xml->zone(); - if (zone->needsBarrier()) { - JSXML *tmp = xml; - MarkXMLUnbarriered(zone->barrierTracer(), &tmp, "write barrier"); - JS_ASSERT(tmp == xml); - } -#endif -} - -void -JSXML::writeBarrierPost(JSXML *xml, void *addr) -{ -} - -void -js_TraceXML(JSTracer *trc, JSXML *xml) -{ - if (xml->object) - MarkObject(trc, &xml->object, "object"); - if (xml->name) - MarkObject(trc, &xml->name, "name"); - if (xml->parent) - MarkXML(trc, &xml->parent, "xml_parent"); - - if (JSXML_HAS_VALUE(xml)) { - if (xml->xml_value) - MarkString(trc, &xml->xml_value, "value"); - return; - } - - MarkXMLRange(trc, xml->xml_kids.length, xml->xml_kids.vector, "xml_kids"); - js_XMLArrayCursorTrace(trc, xml->xml_kids.cursors); - - if (xml->xml_class == JSXML_CLASS_LIST) { - if (xml->xml_target) - MarkXML(trc, &xml->xml_target, "target"); - if (xml->xml_targetprop) - MarkObject(trc, &xml->xml_targetprop, "targetprop"); - } else { - MarkObjectRange(trc, xml->xml_namespaces.length, - xml->xml_namespaces.vector, - "xml_namespaces"); - js_XMLArrayCursorTrace(trc, xml->xml_namespaces.cursors); - - MarkXMLRange(trc, xml->xml_attrs.length, xml->xml_attrs.vector, "xml_attrs"); - js_XMLArrayCursorTrace(trc, xml->xml_attrs.cursors); - } -} - -JSObject * -js_NewXMLObject(JSContext *cx, JSXMLClass xml_class) -{ - JSXML *xml = js_NewXML(cx, xml_class); - if (!xml) - return NULL; - - AutoXMLRooter root(cx, xml); - return js_GetXMLObject(cx, xml); -} - -static JSObject * -NewXMLObject(JSContext *cx, JSXML *xml) -{ - JSObject *obj; - - obj = NewObjectWithClassProto(cx, &XMLClass, NULL, cx->global()); - if (!obj) - return NULL; - obj->setPrivateGCThing(xml); - return obj; -} - -JSObject * -js_GetXMLObject(JSContext *cx, JSXML *xmlArg) -{ - Rooted xml(cx, xmlArg); - JSObject *obj; - - obj = xml->object; - if (obj) { - JS_ASSERT(obj->getPrivate() == xml); - return obj; - } - - obj = NewXMLObject(cx, xml); - if (!obj) - return NULL; - xml->object = obj; - return obj; -} - -JSObject * -js_InitNamespaceClass(JSContext *cx, HandleObject obj) -{ - cx->runtime->gcExactScanningEnabled = false; - - JS_ASSERT(obj->isNative()); - Rooted global(cx, &obj->asGlobal()); - - JSObject *namespaceProto = global->createBlankPrototype(cx, &NamespaceClass); - if (!namespaceProto) - return NULL; - JSFlatString *empty = cx->runtime->emptyString; - namespaceProto->setNamePrefix(empty); - namespaceProto->setNameURI(empty); - - const unsigned NAMESPACE_CTOR_LENGTH = 2; - RootedFunction ctor(cx); - ctor = global->createConstructor(cx, Namespace, cx->names().Namespace, - NAMESPACE_CTOR_LENGTH); - if (!ctor) - return NULL; - - if (!LinkConstructorAndPrototype(cx, ctor, namespaceProto)) - return NULL; - - if (!DefinePropertiesAndBrand(cx, namespaceProto, namespace_props, namespace_methods)) - return NULL; - - if (!DefineConstructorAndPrototype(cx, global, JSProto_Namespace, ctor, namespaceProto)) - return NULL; - - return namespaceProto; -} - -JSObject * -js_InitQNameClass(JSContext *cx, HandleObject obj) -{ - cx->runtime->gcExactScanningEnabled = false; - - JS_ASSERT(obj->isNative()); - Rooted global(cx, &obj->asGlobal()); - - RootedObject qnameProto(cx, global->createBlankPrototype(cx, &QNameClass)); - if (!qnameProto) - return NULL; - JSAtom *empty = cx->runtime->emptyString; - if (!InitXMLQName(cx, qnameProto, empty, empty, empty)) - return NULL; - - const unsigned QNAME_CTOR_LENGTH = 2; - RootedFunction ctor(cx, global->createConstructor(cx, QName, cx->names().QName, - QNAME_CTOR_LENGTH)); - if (!ctor) - return NULL; - - if (!LinkConstructorAndPrototype(cx, ctor, qnameProto)) - return NULL; - - if (!DefinePropertiesAndBrand(cx, qnameProto, NULL, qname_methods)) - return NULL; - - if (!DefineConstructorAndPrototype(cx, global, JSProto_QName, ctor, qnameProto)) - return NULL; - - return qnameProto; -} - -JSObject * -js_InitXMLClass(JSContext *cx, HandleObject obj) -{ - cx->runtime->gcExactScanningEnabled = false; - Rooted global(cx, &obj->asGlobal()); - JS_ASSERT(obj->isNative()); - - RootedObject xmlProto(cx, global->createBlankPrototype(cx, &XMLClass)); - if (!xmlProto) - return NULL; - Rooted xml(cx, js_NewXML(cx, JSXML_CLASS_TEXT)); - if (!xml) - return NULL; - xmlProto->setPrivateGCThing(xml); - xml->object = xmlProto; - - /* Don't count this as a real content-created XML object. */ - if (!cx->runningWithTrustedPrincipals()) { - JS_ASSERT(sE4XObjectsCreated > 0); - --sE4XObjectsCreated; - } - - const unsigned XML_CTOR_LENGTH = 1; - RootedFunction ctor(cx); - ctor = global->createConstructor(cx, XML, cx->names().XML, XML_CTOR_LENGTH); - if (!ctor) - return NULL; - - if (!LinkConstructorAndPrototype(cx, ctor, xmlProto)) - return NULL; - - if (!DefinePropertiesAndBrand(cx, xmlProto, NULL, xml_methods) || - !DefinePropertiesAndBrand(cx, ctor, xml_static_props, xml_static_methods)) - { - return NULL; - } - - if (!SetDefaultXMLSettings(cx, ctor)) - return NULL; - - /* Define the XMLList function, and give it the same .prototype as XML. */ - RootedFunction xmllist(cx, JS_DefineFunction(cx, global, js_XMLList_str, XMLList, 1, JSFUN_CONSTRUCTOR)); - if (!xmllist) - return NULL; - RootedValue value(cx, ObjectValue(*xmlProto)); - if (!JSObject::defineProperty(cx, xmllist, cx->names().classPrototype, - value, JS_PropertyStub, JS_StrictPropertyStub, - JSPROP_PERMANENT | JSPROP_READONLY)) - { - return NULL; - } - - if (!DefineConstructorAndPrototype(cx, global, JSProto_XML, ctor, xmlProto)) - return NULL; - - /* Define the isXMLName function. */ - if (!JS_DefineFunction(cx, global, js_isXMLName_str, xml_isXMLName, 1, 0)) - return NULL; - - return xmlProto; -} - -JSObject * -js_InitXMLClasses(JSContext *cx, HandleObject obj) -{ - if (!js_InitNamespaceClass(cx, obj)) - return NULL; - if (!js_InitQNameClass(cx, obj)) - return NULL; - return js_InitXMLClass(cx, obj); -} - -bool -GlobalObject::getFunctionNamespace(JSContext *cx, Value *vp) -{ - Value v = getSlot(FUNCTION_NS); - if (v.isUndefined()) { - HandlePropertyName prefix = cx->names().function; - HandlePropertyName uri = cx->names().functionNamespaceURI; - RootedObject obj(cx, NewXMLNamespace(cx, prefix, uri, JS_FALSE)); - if (!obj) - return false; - - /* - * Avoid entraining any in-scope Object.prototype. The loss of - * Namespace.prototype is not detectable, as there is no way to - * refer to this instance in scripts. When used to qualify method - * names, its prefix and uri references are copied to the QName. - * The parent remains set and links back to global. - */ - if (!JSObject::clearType(cx, obj)) - return false; - - v = ObjectValue(*obj); - setSlot(FUNCTION_NS, v); - } - - *vp = v; - return true; -} - -/* - * Note the asymmetry between js_GetDefaultXMLNamespace and js_SetDefaultXML- - * Namespace. Get searches fp->scopeChain for JS_DEFAULT_XML_NAMESPACE_ID, - * while Set sets JS_DEFAULT_XML_NAMESPACE_ID in fp->varobj. There's no - * requirement that fp->varobj lie directly on fp->scopeChain, although - * it should be reachable using the prototype chain from a scope object (cf. - * JSOPTION_VAROBJFIX in jsapi.h). - * - * If Get can't find JS_DEFAULT_XML_NAMESPACE_ID along the scope chain, it - * creates a default namespace via 'new Namespace()'. In contrast, Set uses - * its v argument as the uri of a new Namespace, with "" as the prefix. See - * ECMA-357 12.1 and 12.1.1. Note that if Set is called with a Namespace n, - * the default XML namespace will be set to ("", n.uri). So the uri string - * is really the only usefully stored value of the default namespace. - */ -JSBool -js_GetDefaultXMLNamespace(JSContext *cx, jsval *vp) -{ - JSObject *ns; - RootedObject obj(cx); - RootedValue v(cx); - - RootedObject tmp(cx); - - JSObject *scopeChain = GetCurrentScopeChain(cx); - if (!scopeChain) - return false; - - obj = NULL; - for (tmp = scopeChain; tmp; tmp = tmp->enclosingScope()) { - if (tmp->isBlock() || tmp->isWith()) - continue; - if (!JSObject::getSpecial(cx, tmp, tmp, SpecialId::defaultXMLNamespace(), &v)) - return JS_FALSE; - if (!JSVAL_IS_PRIMITIVE(v)) { - *vp = v; - return JS_TRUE; - } - obj = tmp; - } - - ns = ConstructObjectWithArguments(cx, &NamespaceClass, 0, NULL); - if (!ns) - return JS_FALSE; - v = OBJECT_TO_JSVAL(ns); - if (!JSObject::defineSpecial(cx, obj, SpecialId::defaultXMLNamespace(), v, - JS_PropertyStub, JS_StrictPropertyStub, JSPROP_PERMANENT)) { - return JS_FALSE; - } - *vp = v; - return JS_TRUE; -} - -JSBool -js_SetDefaultXMLNamespace(JSContext *cx, const Value &v) -{ - Value argv[2]; - argv[0].setString(cx->runtime->emptyString); - argv[1] = v; - JSObject *ns = ConstructObjectWithArguments(cx, &NamespaceClass, 2, argv); - if (!ns) - return JS_FALSE; - - RootedObject varobj(cx, &cx->fp()->varObj()); - RootedValue value(cx, ObjectValue(*ns)); - if (!JSObject::defineSpecial(cx, varobj, SpecialId::defaultXMLNamespace(), value, - JS_PropertyStub, JS_StrictPropertyStub, JSPROP_PERMANENT)) { - return JS_FALSE; - } - return JS_TRUE; -} - -JSBool -js_ToAttributeName(JSContext *cx, Value *vp) -{ - JSObject *qn; - - qn = ToAttributeName(cx, *vp); - if (!qn) - return JS_FALSE; - vp->setObject(*qn); - return JS_TRUE; -} - -JSFlatString * -js_EscapeAttributeValue(JSContext *cx, JSString *str, JSBool quote) -{ - StringBuffer sb(cx); - return EscapeAttributeValue(cx, sb, str, quote); -} - -JSString * -js_AddAttributePart(JSContext *cx, JSBool isName, JSString *str, JSString *str2) -{ - size_t len = str->length(); - const jschar *chars = str->getChars(cx); - if (!chars) - return NULL; - - size_t len2 = str2->length(); - const jschar *chars2 = str2->getChars(cx); - if (!chars2) - return NULL; - - size_t newlen = (isName) ? len + 1 + len2 : len + 2 + len2 + 1; - jschar *newchars = cx->pod_malloc(newlen+1); - if (!newchars) - return NULL; - - js_strncpy(newchars, chars, len); - newchars += len; - if (isName) { - *newchars++ = ' '; - js_strncpy(newchars, chars2, len2); - newchars += len2; - } else { - *newchars++ = '='; - *newchars++ = '"'; - js_strncpy(newchars, chars2, len2); - newchars += len2; - *newchars++ = '"'; - } - *newchars = 0; - return js_NewString(cx, newchars - newlen, newlen); -} - -JSFlatString * -js_EscapeElementValue(JSContext *cx, JSString *str) -{ - StringBuffer sb(cx); - return EscapeElementValue(cx, sb, str, 0); -} - -JSString * -js_ValueToXMLString(JSContext *cx, const Value &v) -{ - return ToXMLString(cx, v, 0); -} - -JSBool -js_GetAnyName(JSContext *cx, jsid *idp) -{ - JSObject *global = cx->global(); - Value v = global->getReservedSlot(JSProto_AnyName); - if (v.isUndefined()) { - RootedObject obj(cx, NewObjectWithGivenProto(cx, &AnyNameClass, NULL, global)); - if (!obj) - return false; - - JS_ASSERT(!obj->getProto()); - - JSRuntime *rt = cx->runtime; - if (!InitXMLQName(cx, obj, rt->emptyString, rt->emptyString, rt->atomState.star)) - return false; - - v.setObject(*obj); - SetReservedSlot(global, JSProto_AnyName, v); - } - *idp = OBJECT_TO_JSID(&v.toObject()); - return true; -} - -JSBool -js_FindXMLProperty(JSContext *cx, const Value &nameval, MutableHandleObject objp, jsid *idp) -{ - JSObject *nameobj; - jsval v; - JSObject *qn; - RootedId funid(cx); - RootedObject target(cx); - JSObject *obj, *proto; - JSXML *xml; - JSBool found; - - JS_ASSERT(nameval.isObject()); - nameobj = &nameval.toObject(); - if (nameobj->getClass() == &AnyNameClass) { - v = STRING_TO_JSVAL(cx->names().star); - nameobj = ConstructObjectWithArguments(cx, &QNameClass, 1, &v); - if (!nameobj) - return JS_FALSE; - } else { - JS_ASSERT(nameobj->getClass() == &AttributeNameClass || - nameobj->getClass() == &QNameClass); - } - - qn = nameobj; - - JSAtom *name; - funid = GetLocalNameFromFunctionQName(qn, &name, cx) - ? AtomToId(name) - : JSID_VOID; - - obj = cx->stack.currentScriptedScopeChain(); - do { - /* Skip any With object that can wrap XML. */ - target = obj; - while (target->getClass() == &WithClass) { - proto = target->getProto(); - if (!proto) - break; - target = proto; - } - - if (target->isXML()) { - if (JSID_IS_VOID(funid)) { - xml = (JSXML *) target->getPrivate(); - found = HasNamedProperty(xml, qn); - } else { - if (!HasFunctionProperty(cx, target, funid, &found)) - return JS_FALSE; - } - if (found) { - *idp = OBJECT_TO_JSID(nameobj); - objp.set(target); - return JS_TRUE; - } - } else if (!JSID_IS_VOID(funid)) { - RootedObject pobj(cx); - RootedShape prop(cx); - if (!JSObject::lookupGeneric(cx, target, funid, &pobj, &prop)) - return JS_FALSE; - if (prop) { - *idp = funid; - objp.set(target); - return JS_TRUE; - } - } - } while ((obj = obj->enclosingScope()) != NULL); - - JSAutoByteString printable; - JSString *str = ConvertQNameToString(cx, nameobj); - if (str && js_ValueToPrintable(cx, StringValue(str), &printable)) { - JS_ReportErrorFlagsAndNumber(cx, JSREPORT_ERROR, js_GetErrorMessage, NULL, - JSMSG_UNDEFINED_XML_NAME, printable.ptr()); - } - return JS_FALSE; -} - -static JSBool -GetXMLFunction(JSContext *cx, HandleObject obj, HandleId id, MutableHandleValue vp) -{ - JS_ASSERT(obj->isXML()); - - /* - * See comments before xml_lookupGeneric about the need for the proto - * chain lookup. - */ - RootedObject target(cx, obj); - for (;;) { - if (!baseops::GetProperty(cx, target, id, vp)) - return false; - if (!JSVAL_IS_PRIMITIVE(vp) && JSVAL_TO_OBJECT(vp)->isFunction()) - return true; - target = target->getProto(); - if (target == NULL || !target->isNative()) - break; - } - - JSXML *xml = (JSXML *) obj->getPrivate(); - if (!HasSimpleContent(xml)) - return true; - - /* Search in String.prototype to implement 11.2.2.1 Step 3(f). */ - RootedObject proto(cx, obj->global().getOrCreateStringPrototype(cx)); - if (!proto) - return false; - - return JSObject::getGeneric(cx, proto, proto, id, vp); -} - -static JSXML * -GetPrivate(JSContext *cx, JSObject *obj, const char *method) -{ - if (!obj->isXML()) { - JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, - JSMSG_INCOMPATIBLE_METHOD, - js_XML_str, method, obj->getClass()->name); - return NULL; - } - return (JSXML *)obj->getPrivate(); -} - -JSBool -js_GetXMLDescendants(JSContext *cx, JSObject *obj, jsval id, jsval *vp) -{ - JSXML *xml, *list; - - xml = GetPrivate(cx, obj, "descendants internal method"); - if (!xml) - return JS_FALSE; - - list = Descendants(cx, xml, id); - if (!list) - return JS_FALSE; - *vp = OBJECT_TO_JSVAL(list->object); - return JS_TRUE; -} - -JSBool -js_DeleteXMLListElements(JSContext *cx, JSObject *listobj) -{ - JSXML *list; - uint32_t n; - - list = (JSXML *) listobj->getPrivate(); - for (n = list->xml_kids.length; n != 0; --n) - DeleteListElement(cx, list, 0); - - return JS_TRUE; -} - -struct JSXMLFilter -{ - HeapPtr list; - HeapPtr result; - HeapPtr kid; - JSXMLArrayCursor cursor; - - JSXMLFilter(JSXML *list, JSXMLArray *array) - : list(list), result(NULL), kid(NULL), cursor(array) {} - - ~JSXMLFilter() {} -}; - -static void -xmlfilter_trace(JSTracer *trc, RawObject obj) -{ - JSXMLFilter *filter = (JSXMLFilter *) obj->getPrivate(); - if (!filter) - return; - - JS_ASSERT(filter->list); - MarkXML(trc, &filter->list, "list"); - if (filter->result) - MarkXML(trc, &filter->result, "result"); - if (filter->kid) - MarkXML(trc, &filter->kid, "kid"); - - /* - * We do not need to trace the cursor as that would be done when - * tracing the filter->list. - */ -} - -static void -xmlfilter_finalize(FreeOp *fop, RawObject obj) -{ - JSXMLFilter *filter = (JSXMLFilter *) obj->getPrivate(); - if (!filter) - return; - - fop->delete_(filter); -} - -Class js_XMLFilterClass = { - "XMLFilter", - JSCLASS_HAS_PRIVATE | JSCLASS_IMPLEMENTS_BARRIERS | JSCLASS_IS_ANONYMOUS, - JS_PropertyStub, /* addProperty */ - JS_PropertyStub, /* delProperty */ - JS_PropertyStub, /* getProperty */ - JS_StrictPropertyStub, /* setProperty */ - JS_EnumerateStub, - JS_ResolveStub, - JS_ConvertStub, - xmlfilter_finalize, - NULL, /* checkAccess */ - NULL, /* call */ - NULL, /* construct */ - NULL, /* hasInstance */ - xmlfilter_trace -}; - -JSBool -js_StepXMLListFilter(JSContext *cx, JSBool initialized) -{ - jsval *sp; - JSObject *obj, *filterobj, *resobj, *kidobj; - JSXML *xml, *list; - JSXMLFilter *filter; - - sp = cx->regs().sp; - if (!initialized) { - /* - * We haven't iterated yet, so initialize the filter based on the - * value stored in sp[-2]. - */ - if (!VALUE_IS_XML(sp[-2])) { - RootedValue val(cx, sp[-2]); - js_ReportValueError(cx, JSMSG_NON_XML_FILTER, -2, val, NullPtr()); - return JS_FALSE; - } - obj = JSVAL_TO_OBJECT(sp[-2]); - xml = (JSXML *) obj->getPrivate(); - - if (xml->xml_class == JSXML_CLASS_LIST) { - list = xml; - } else { - obj = js_NewXMLObject(cx, JSXML_CLASS_LIST); - if (!obj) - return JS_FALSE; - - /* - * Root just-created obj. sp[-2] cannot be used yet for rooting - * as it may be the only root holding xml. - */ - sp[-1] = OBJECT_TO_JSVAL(obj); - list = (JSXML *) obj->getPrivate(); - if (!Append(cx, list, xml)) - return JS_FALSE; - } - - filterobj = NewObjectWithGivenProto(cx, &js_XMLFilterClass, NULL, cx->global()); - if (!filterobj) - return JS_FALSE; - - /* - * Init all filter fields before setPrivate exposes it to - * xmlfilter_trace or xmlfilter_finalize. - */ - filter = cx->new_(list, &list->xml_kids); - if (!filter) - return JS_FALSE; - filterobj->setPrivate(filter); - - /* Store filterobj to use in the later iterations. */ - sp[-2] = OBJECT_TO_JSVAL(filterobj); - - resobj = js_NewXMLObject(cx, JSXML_CLASS_LIST); - if (!resobj) - return JS_FALSE; - - /* This also roots resobj. */ - filter->result = (JSXML *) resobj->getPrivate(); - } else { - /* We have iterated at least once. */ - JS_ASSERT(!JSVAL_IS_PRIMITIVE(sp[-2])); - JS_ASSERT(JSVAL_TO_OBJECT(sp[-2])->getClass() == &js_XMLFilterClass); - filter = (JSXMLFilter *) JSVAL_TO_OBJECT(sp[-2])->getPrivate(); - JS_ASSERT(filter->kid); - - /* Check if the filter expression wants to append the element. */ - if (ToBoolean(sp[-1]) && - !Append(cx, filter->result, filter->kid)) { - return JS_FALSE; - } - } - - /* Do the iteration. */ - filter->kid = filter->cursor.getNext(); - if (!filter->kid) { - /* - * Do not defer finishing the cursor until the next GC cycle to avoid - * accumulation of dead cursors associated with filter->list. - */ - filter->cursor.disconnect(); - JS_ASSERT(filter->result->object); - sp[-2] = OBJECT_TO_JSVAL(filter->result->object); - kidobj = NULL; - } else { - kidobj = js_GetXMLObject(cx, filter->kid); - if (!kidobj) - return JS_FALSE; - } - - /* Null as kidobj at sp[-1] signals filter termination. */ - sp[-1] = OBJECT_TO_JSVAL(kidobj); - return JS_TRUE; -} - -JSObject * -js_ValueToXMLObject(JSContext *cx, const Value &v) -{ - return ToXML(cx, v); -} - -JSObject * -js_ValueToXMLListObject(JSContext *cx, const Value &v) -{ - return ToXMLList(cx, v); -} - -JSObject * -js_NewXMLSpecialObject(JSContext *cx, JSXMLClass xml_class, JSString *name, - JSString *value) -{ - unsigned flags; - JSObject *obj; - JSXML *xml; - JSObject *qn; - - if (!GetXMLSettingFlags(cx, &flags)) - return NULL; - - if ((xml_class == JSXML_CLASS_COMMENT && - (flags & XSF_IGNORE_COMMENTS)) || - (xml_class == JSXML_CLASS_PROCESSING_INSTRUCTION && - (flags & XSF_IGNORE_PROCESSING_INSTRUCTIONS))) { - return js_NewXMLObject(cx, JSXML_CLASS_TEXT); - } - - obj = js_NewXMLObject(cx, xml_class); - if (!obj) - return NULL; - xml = (JSXML *) obj->getPrivate(); - if (name) { - JSAtom *atomName = AtomizeString(cx, name); - if (!atomName) - return NULL; - qn = NewXMLQName(cx, cx->runtime->emptyString, NULL, atomName); - if (!qn) - return NULL; - xml->name = qn; - } - xml->xml_value = value; - return obj; -} - -JSString * -js_MakeXMLCDATAString(JSContext *cx, JSString *str) -{ - StringBuffer sb(cx); - return MakeXMLCDATAString(cx, sb, str); -} - -JSString * -js_MakeXMLCommentString(JSContext *cx, JSString *str) -{ - StringBuffer sb(cx); - return MakeXMLCommentString(cx, sb, str); -} - -JSString * -js_MakeXMLPIString(JSContext *cx, JSString *name, JSString *str) -{ - StringBuffer sb(cx); - return MakeXMLPIString(cx, sb, name, str); -} - -#endif /* JS_HAS_XML_SUPPORT */ diff --git a/js/src/jsxml.h b/js/src/jsxml.h deleted file mode 100644 index 62ddb3035370..000000000000 --- a/js/src/jsxml.h +++ /dev/null @@ -1,314 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * 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/. */ - -#ifndef jsxml_h___ -#define jsxml_h___ - -#include "jspubtd.h" -#include "jsobj.h" - -#include "gc/Barrier.h" -#include "gc/Heap.h" - -#if JS_HAS_XML_SUPPORT -extern JSObject * -js_InitXMLClass(JSContext *cx, js::HandleObject obj); -extern JSObject * -js_InitNamespaceClass(JSContext *cx, js::HandleObject obj); -extern JSObject * -js_InitQNameClass(JSContext *cx, js::HandleObject obj); -#else -#define js_InitXMLClass js_InitNullClass -#define js_InitNamespaceClass js_InitNullClass -#define js_InitQNameClass js_InitNullClass -#endif - -#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[]; -extern const char js_quot_entity_str[]; - -template -struct JSXMLArrayCursor; - -template -struct JSXMLArray -{ - uint32_t length; - uint32_t capacity; - js::HeapPtr *vector; - JSXMLArrayCursor *cursors; - - void init() { - length = capacity = 0; - vector = NULL; - cursors = NULL; - } - - void finish(js::FreeOp *fop); - - bool setCapacity(JSContext *cx, uint32_t capacity); - void trim(); -}; - -template -struct JSXMLArrayCursor -{ - typedef js::HeapPtr HeapPtrT; - - JSXMLArray *array; - uint32_t index; - JSXMLArrayCursor *next; - JSXMLArrayCursor **prevp; - HeapPtrT root; - - JSXMLArrayCursor(JSXMLArray *array) - : array(array), index(0), next(array->cursors), prevp(&array->cursors), - root(NULL) - { - if (next) - next->prevp = &next; - array->cursors = this; - } - - ~JSXMLArrayCursor() { disconnect(); } - - void disconnect() { - if (!array) - return; - if (next) - next->prevp = prevp; - *prevp = next; - array = NULL; - root.~HeapPtrT(); - } - - T *getNext() { - if (!array || index >= array->length) - return NULL; - return root = array->vector[index++]; - } - - T *getCurrent() { - if (!array || index >= array->length) - return NULL; - return root = array->vector[index]; - } -}; - -void js_XMLArrayCursorTrace(JSTracer *trc, JSXMLArrayCursor *cursor); -void js_XMLArrayCursorTrace(JSTracer *trc, JSXMLArrayCursor *cursor); - -#define JSXML_PRESET_CAPACITY JS_BIT(31) -#define JSXML_CAPACITY_MASK JS_BITMASK(31) -#define JSXML_CAPACITY(array) ((array)->capacity & JSXML_CAPACITY_MASK) - -/* - * NB: don't reorder this enum without changing all array initializers that - * depend on it in jsxml.c. - */ -typedef enum JSXMLClass { - JSXML_CLASS_LIST, - JSXML_CLASS_ELEMENT, - JSXML_CLASS_ATTRIBUTE, - JSXML_CLASS_PROCESSING_INSTRUCTION, - JSXML_CLASS_TEXT, - JSXML_CLASS_COMMENT, - JSXML_CLASS_LIMIT -} JSXMLClass; - -#define JSXML_CLASS_HAS_KIDS(class_) ((class_) < JSXML_CLASS_ATTRIBUTE) -#define JSXML_CLASS_HAS_VALUE(class_) ((class_) >= JSXML_CLASS_ATTRIBUTE) -#define JSXML_CLASS_HAS_NAME(class_) \ - ((unsigned)((class_) - JSXML_CLASS_ELEMENT) <= \ - (unsigned)(JSXML_CLASS_PROCESSING_INSTRUCTION - JSXML_CLASS_ELEMENT)) - -#ifdef DEBUG_notme -#include "jsclist.h" -#endif - -typedef struct JSXMLListVar { - JSXMLArray kids; /* NB: must come first */ - js::HeapPtrXML target; - js::HeapPtrObject targetprop; -} JSXMLListVar; - -typedef struct JSXMLElemVar { - JSXMLArray kids; /* NB: must come first */ - JSXMLArray namespaces; - JSXMLArray attrs; -} JSXMLElemVar; - -/* union member shorthands */ -#define xml_kids list.kids -#define xml_target list.target -#define xml_targetprop list.targetprop -#define xml_namespaces elem.namespaces -#define xml_attrs elem.attrs -#define xml_value value - -/* xml_class-testing macros */ -#define JSXML_HAS_KIDS(xml) JSXML_CLASS_HAS_KIDS((xml)->xml_class) -#define JSXML_HAS_VALUE(xml) JSXML_CLASS_HAS_VALUE((xml)->xml_class) -#define JSXML_HAS_NAME(xml) JSXML_CLASS_HAS_NAME((xml)->xml_class) -#define JSXML_LENGTH(xml) (JSXML_CLASS_HAS_KIDS((xml)->xml_class) \ - ? (xml)->xml_kids.length \ - : 0) - -struct JSXML : js::gc::Cell { -#ifdef DEBUG_notme - JSCList links; - uint32_t serial; -#endif - js::HeapPtrObject object; - void *domnode; /* DOM node if mapped info item */ - js::HeapPtrXML parent; - js::HeapPtrObject name; - uint32_t xml_class; /* discriminates u, below */ - uint32_t xml_flags; /* flags, see below */ - - JSXMLListVar list; - JSXMLElemVar elem; - js::HeapPtrString value; - -#if JS_BITS_PER_WORD == 32 - /* The size of every GC thing must be divisible by the FreeCell size. */ - void *pad; -#endif - - void finalize(js::FreeOp *fop); - - static void writeBarrierPre(JSXML *xml); - static void writeBarrierPost(JSXML *xml, void *addr); - - static inline js::ThingRootKind rootKind() { return js::THING_ROOT_XML; } -}; - -/* xml_flags values */ -#define XMLF_WHITESPACE_TEXT 0x1 - -extern JSXML * -js_NewXML(JSContext *cx, JSXMLClass xml_class); - -extern void -js_TraceXML(JSTracer *trc, JSXML *xml); - -extern JSObject * -js_NewXMLObject(JSContext *cx, JSXMLClass xml_class); - -extern JSObject * -js_GetXMLObject(JSContext *cx, JSXML *xml); - -extern JSObject * -js_InitXMLClasses(JSContext *cx, js::HandleObject obj); - -/* - * If obj is a QName corresponding to function::name, set *funidp to name's id - * and return true, else return false. - */ -extern bool -js_GetLocalNameFromFunctionQName(JSObject *obj, jsid *funidp, JSContext *cx); - -extern JSBool -js_GetDefaultXMLNamespace(JSContext *cx, jsval *vp); - -extern JSBool -js_SetDefaultXMLNamespace(JSContext *cx, const js::Value &v); - -/* - * Return true if v is a XML QName object, or if it converts to a string that - * contains a valid XML qualified name (one containing no :), false otherwise. - * NB: This function is an infallible predicate, it hides exceptions. - */ -extern JSBool -js_IsXMLName(JSContext *cx, jsval v); - -extern JSBool -js_ToAttributeName(JSContext *cx, js::Value *vp); - -extern JSFlatString * -js_EscapeAttributeValue(JSContext *cx, JSString *str, JSBool quote); - -extern JSString * -js_AddAttributePart(JSContext *cx, JSBool isName, JSString *str, - JSString *str2); - -extern JSFlatString * -js_EscapeElementValue(JSContext *cx, JSString *str); - -extern JSString * -js_ValueToXMLString(JSContext *cx, const js::Value &v); - -extern JSObject * -js_ConstructXMLQNameObject(JSContext *cx, const js::Value & nsval, - const js::Value & lnval); - -extern JSBool -js_GetAnyName(JSContext *cx, jsid *idp); - -/* - * Note: nameval must be either QName, AttributeName, or AnyName. - */ -extern JSBool -js_FindXMLProperty(JSContext *cx, const js::Value &nameval, - js::MutableHandleObject objp, jsid *idp); - -extern JSBool -js_GetXMLMethod(JSContext *cx, js::HandleObject obj, jsid id, js::MutableHandleValue vp); - -extern JSBool -js_GetXMLDescendants(JSContext *cx, JSObject *obj, jsval id, jsval *vp); - -extern JSBool -js_DeleteXMLListElements(JSContext *cx, JSObject *listobj); - -extern JSBool -js_StepXMLListFilter(JSContext *cx, JSBool initialized); - -extern JSObject * -js_ValueToXMLObject(JSContext *cx, const js::Value &v); - -extern JSObject * -js_ValueToXMLListObject(JSContext *cx, const js::Value &v); - -extern JSObject * -js_NewXMLSpecialObject(JSContext *cx, JSXMLClass xml_class, JSString *name, - JSString *value); - -extern JSString * -js_MakeXMLCDATAString(JSContext *cx, JSString *str); - -extern JSString * -js_MakeXMLCommentString(JSContext *cx, JSString *str); - -extern JSString * -js_MakeXMLPIString(JSContext *cx, JSString *name, JSString *str); - -/* The caller must ensure that either v1 or v2 is an object. */ -extern JSBool -js_TestXMLEquality(JSContext *cx, const js::Value &v1, const js::Value &v2, - JSBool *bp); - -extern JSBool -js_ConcatenateXML(JSContext *cx, JSObject *obj1, JSObject *obj2, js::Value *vp); - -namespace js { - -extern bool -GetLocalNameFromFunctionQName(JSObject *qn, JSAtom **namep, JSContext *cx); - -} /* namespace js */ - -#endif /* JS_HAS_XML_SUPPORT */ - -#endif /* jsxml_h___ */ diff --git a/js/src/methodjit/InvokeHelpers.cpp b/js/src/methodjit/InvokeHelpers.cpp index de59ca60f54d..650ff7cc7de5 100644 --- a/js/src/methodjit/InvokeHelpers.cpp +++ b/js/src/methodjit/InvokeHelpers.cpp @@ -13,7 +13,6 @@ #include "jslibmath.h" #include "jsiter.h" #include "jsnum.h" -#include "jsxml.h" #include "jsbool.h" #include "jstypes.h" diff --git a/js/src/methodjit/PolyIC.cpp b/js/src/methodjit/PolyIC.cpp index cd7066b8184c..c815dab6bb29 100644 --- a/js/src/methodjit/PolyIC.cpp +++ b/js/src/methodjit/PolyIC.cpp @@ -2638,16 +2638,6 @@ ic::GetElement(VMFrame &f, ic::GetElementIC *ic) if (!obj) THROW(); -#if JS_HAS_XML_SUPPORT - // Some XML properties behave differently when accessed in a call vs. normal - // context, so we fall back to stubs::GetElem. - if (obj->isXML()) { - ic->disable(f, "XML object"); - stubs::GetElem(f); - return; - } -#endif - Rooted id(cx); if (idval.isInt32() && INT_FITS_IN_JSID(idval.toInt32())) { id = INT_TO_JSID(idval.toInt32()); diff --git a/js/src/methodjit/StubCalls.cpp b/js/src/methodjit/StubCalls.cpp index 5d294fb2c335..2655e8bfa499 100644 --- a/js/src/methodjit/StubCalls.cpp +++ b/js/src/methodjit/StubCalls.cpp @@ -13,7 +13,6 @@ #include "jslibmath.h" #include "jsiter.h" #include "jsnum.h" -#include "jsxml.h" #include "jsbool.h" #include "assembler/assembler/MacroAssemblerCodeRef.h" #include "jstypes.h" @@ -485,19 +484,7 @@ StubEqualityOp(VMFrame &f) if (!EqualStrings(cx, l, r, &equal)) return false; cond = equal == EQ; - } else -#if JS_HAS_XML_SUPPORT - if ((lval.isObject() && lval.toObject().isXML()) || - (rval.isObject() && rval.toObject().isXML())) - { - JSBool equal; - if (!js_TestXMLEquality(cx, lval, rval, &equal)) - return false; - cond = !!equal == EQ; - } else -#endif - - if (SameType(lval, rval)) { + } else if (SameType(lval, rval)) { JS_ASSERT(!lval.isString()); /* this case is handled above */ if (lval.isDouble()) { double l = lval.toDouble(); @@ -597,18 +584,7 @@ stubs::Add(VMFrame &f) rstr = rval.toString(); goto string_concat; - } else -#if JS_HAS_XML_SUPPORT - if (lval.isObject() && lval.toObject().isXML() && - rval.isObject() && rval.toObject().isXML()) { - if (!js_ConcatenateXML(cx, &lval.toObject(), &rval.toObject(), &rval)) - THROW(); - regs.sp[-2] = rval; - regs.sp--; - TypeScript::MonitorUnknown(cx, f.script(), f.pc()); - } else -#endif - { + } else { bool lIsObject = lval.isObject(), rIsObject = rval.isObject(); if (!ToPrimitive(f.cx, &lval)) THROW(); diff --git a/js/src/shell/js.cpp b/js/src/shell/js.cpp index f1b4a8325acb..b5b808423645 100644 --- a/js/src/shell/js.cpp +++ b/js/src/shell/js.cpp @@ -41,7 +41,6 @@ #include "jstypedarray.h" #include "jstypedarrayinlines.h" #include "jsworkers.h" -#include "jsxml.h" #include "jsperf.h" #include "builtin/TestingFunctions.h" @@ -717,8 +716,6 @@ static const struct JSOption { {"strict", JSOPTION_STRICT}, {"typeinfer", JSOPTION_TYPE_INFERENCE}, {"werror", JSOPTION_WERROR}, - {"allow_xml", JSOPTION_ALLOW_XML}, - {"moar_xml", JSOPTION_MOAR_XML}, {"strict_mode", JSOPTION_STRICT_MODE}, }; diff --git a/js/src/vm/CommonPropertyNames.h b/js/src/vm/CommonPropertyNames.h index 430f9ad9d9ae..c7b4c6827a26 100644 --- a/js/src/vm/CommonPropertyNames.h +++ b/js/src/vm/CommonPropertyNames.h @@ -13,23 +13,6 @@ #include "jsprototypes.h" #include "jsversion.h" -#if JS_HAS_XML_SUPPORT -#define FOR_EACH_XML_ONLY_NAME(macro) \ - macro(etago, etago, "") \ - macro(qualifier, qualifier, "::") \ - macro(space, space, " ") \ - macro(stago, stago, "<") \ - macro(star, star, "*") \ - macro(starQualifier, starQualifier, "*::") \ - macro(tagc, tagc, ">") \ - macro(XMLList, XMLList, "XMLList") -#else -#define FOR_EACH_XML_ONLY_NAME(macro) /* nothing */ -#endif /* JS_HAS_XML_SUPPORT */ - #define FOR_EACH_COMMON_PROPERTYNAME(macro) \ macro(anonymous, anonymous, "anonymous") \ macro(apply, apply, "apply") \ @@ -90,7 +73,6 @@ macro(isFinite, isFinite, "isFinite") \ macro(isNaN, isNaN, "isNaN") \ macro(isPrototypeOf, isPrototypeOf, "isPrototypeOf") \ - macro(isXMLName, isXMLName, "isXMLName") \ macro(iterate, iterate, "iterate") \ macro(Infinity, Infinity, "Infinity") \ macro(iterator, iterator, "iterator") \ @@ -154,8 +136,6 @@ macro(string, string, "string") \ macro(number, number, "number") \ macro(boolean, boolean, "boolean") \ - macro(null, null, "null") \ - macro(xml, xml, "xml") \ - FOR_EACH_XML_ONLY_NAME(macro) + macro(null, null, "null") #endif /* CommonPropertyNames_h__ */ diff --git a/js/src/vm/GlobalObject.cpp b/js/src/vm/GlobalObject.cpp index 8d9ab146f56d..77be48ae629e 100644 --- a/js/src/vm/GlobalObject.cpp +++ b/js/src/vm/GlobalObject.cpp @@ -467,9 +467,6 @@ GlobalObject::initStandardClasses(JSContext *cx, Handle global) js_InitRegExpClass(cx, global) && js_InitStringClass(cx, global) && js_InitTypedArrayClasses(cx, global) && -#if JS_HAS_XML_SUPPORT - (!VersionHasAllowXML(cx->findVersion()) || js_InitXMLClasses(cx, global)) && -#endif js_InitIteratorClasses(cx, global) && js_InitDateClass(cx, global) && js_InitWeakMapClass(cx, global) && diff --git a/js/src/vm/GlobalObject.h b/js/src/vm/GlobalObject.h index 3dcc7e9be01d..a2b7b1bde589 100644 --- a/js/src/vm/GlobalObject.h +++ b/js/src/vm/GlobalObject.h @@ -49,11 +49,10 @@ class Debugger; * for the corresponding JSProtoKey offset from 2 * JSProto_LIMIT. * [3 * JSProto_LIMIT, RESERVED_SLOTS) * Various one-off values: ES5 13.2.3's [[ThrowTypeError]], RegExp statics, - * the Namespace object for E4X's function::, the original eval for this - * global object (implementing |var eval = otherWindow.eval; eval(...)| as an - * indirect eval), a bit indicating whether this object has been cleared - * (see JS_ClearScope), and a cache for whether eval is allowed (per the - * global's Content Security Policy). + * the original eval for this global object (implementing |var eval = + * otherWindow.eval; eval(...)| as an indirect eval), a bit indicating + * whether this object has been cleared (see JS_ClearScope), and a cache for + * whether eval is allowed (per the global's Content Security Policy). * * The first two ranges are necessary to implement js::FindClassObject, * FindClassPrototype, and spec language speaking in terms of "the original @@ -428,8 +427,6 @@ class GlobalObject : public JSObject return getSlot(EVAL); } - bool getFunctionNamespace(JSContext *cx, Value *vp); - // Implemented in jsiter.cpp. static bool initIteratorClasses(JSContext *cx, Handle global); diff --git a/js/src/vm/ObjectImpl.h b/js/src/vm/ObjectImpl.h index 1c0b25d7c818..5d1f8497c8d9 100644 --- a/js/src/vm/ObjectImpl.h +++ b/js/src/vm/ObjectImpl.h @@ -48,9 +48,8 @@ CastAsStrictPropertyOp(JSObject *object) * property storage, typed array data, and so on). All other properties are * stored using shapes and shape trees. Keys for these properties are either * PropertyNames (that is, atomized strings whose contents are not unsigned - * 32-bit integers) or SpecialIds (object values for E4X and a couple other - * things, see jsid for details); the union of these types, used in individual - * shapes, is PropertyId. + * 32-bit integers) or SpecialIds (see jsid for details); the union of these + * types, used in individual shapes, is PropertyId. */ class PropertyId { diff --git a/js/src/vm/Shape-inl.h b/js/src/vm/Shape-inl.h index 01af9c7025db..64734bcbb017 100644 --- a/js/src/vm/Shape-inl.h +++ b/js/src/vm/Shape-inl.h @@ -319,7 +319,7 @@ Shape::set(JSContext* cx, HandleObject obj, HandleObject receiver, bool strict, return false; /* - * |with (it) color;| ends up here, as do XML filter-expressions. + * |with (it) color='red';| ends up here. * Avoid exposing the With object to native setters. */ if (obj->isWith()) { diff --git a/js/src/vm/Stack.h b/js/src/vm/Stack.h index ac5f5032a430..ffb3b6fb991a 100644 --- a/js/src/vm/Stack.h +++ b/js/src/vm/Stack.h @@ -701,9 +701,8 @@ class StackFrame /* * With * - * Entering/leaving a with (or E4X filter) block pushes/pops an object - * on the scope chain. Pushing uses pushOnScopeChain, popping should use - * popWith. + * Entering/leaving a |with| block pushes/pops an object on the scope chain. + * Pushing uses pushOnScopeChain, popping should use popWith. */ void popWith(JSContext *cx); diff --git a/js/src/vm/String.h b/js/src/vm/String.h index 80c7f0347599..2ed109f7b7a2 100644 --- a/js/src/vm/String.h +++ b/js/src/vm/String.h @@ -836,8 +836,8 @@ class StaticStrings * - uint32_t indexes, * - PropertyName strings which don't encode uint32_t indexes, and * - jsspecial special properties (non-ES5 properties like object-valued - * jsids, JSID_EMPTY, JSID_VOID, E4X's default XML namespace, and maybe in - * the future Harmony-proposed private names). + * jsids, JSID_EMPTY, JSID_VOID, and maybe in the future Harmony-proposed + * private names). */ class PropertyName : public JSAtom {}; diff --git a/js/src/vm/Unicode.h b/js/src/vm/Unicode.h index 3ab57d07047b..941a2496cc3e 100644 --- a/js/src/vm/Unicode.h +++ b/js/src/vm/Unicode.h @@ -60,9 +60,6 @@ namespace unicode { * * NO_DELTA * See comment in CharacterInfo - * - * ENCLOSING_MARK / COMBINING_SPACING_MARK - * Something for E4X.... */ struct CharFlag { @@ -70,9 +67,7 @@ struct CharFlag { SPACE = 1 << 0, LETTER = 1 << 1, IDENTIFIER_PART = 1 << 2, - NO_DELTA = 1 << 3, - ENCLOSING_MARK = 1 << 4, - COMBINING_SPACING_MARK = 1 << 5 + NO_DELTA = 1 << 3 }; }; @@ -116,14 +111,6 @@ class CharacterInfo { inline bool isIdentifierPart() const { return flags & (CharFlag::IDENTIFIER_PART | CharFlag::LETTER); } - - inline bool isEnclosingMark() const { - return flags & CharFlag::ENCLOSING_MARK; - } - - inline bool isCombiningSpacingMark() const { - return flags & CharFlag::COMBINING_SPACING_MARK; - } }; extern const uint8_t index1[]; @@ -237,51 +224,6 @@ ToLowerCase(jschar ch) return uint16_t(ch) + info.lowerCase; } -/* XML support functions */ - -inline bool -IsXMLSpace(jschar ch) -{ - return ch == ' ' || ch == '\t' || ch == '\r' || ch == '\n'; -} - -inline bool -IsXMLNamespaceStart(jschar ch) -{ - if (ch == '_') - return true; - - return CharInfo(ch).isCombiningSpacingMark() || IsIdentifierStart(ch); -} - -inline bool -IsXMLNamespacePart(jschar ch) -{ - if (ch == '.' || ch == '-' || ch == '_') - return true; - - return CharInfo(ch).isEnclosingMark() || IsIdentifierPart(ch); -} - -inline bool -IsXMLNameStart(jschar ch) -{ - if (ch == '_' || ch == ':') - return true; - - return CharInfo(ch).isCombiningSpacingMark() || IsIdentifierStart(ch); -} - -inline bool -IsXMLNamePart(jschar ch) -{ - if (ch == '.' || ch == '-' || ch == '_' || ch == ':') - return true; - - return CharInfo(ch).isEnclosingMark() || IsIdentifierPart(ch); -} - - } /* namespace unicode */ } /* namespace js */ diff --git a/js/src/vm/Xdr.h b/js/src/vm/Xdr.h index 5c179e383a03..66e0aa4afc06 100644 --- a/js/src/vm/Xdr.h +++ b/js/src/vm/Xdr.h @@ -25,7 +25,7 @@ namespace js { * and saved versions. If deserialization fails, the data should be * invalidated if possible. */ -static const uint32_t XDR_BYTECODE_VERSION = uint32_t(0xb973c0de - 135); +static const uint32_t XDR_BYTECODE_VERSION = uint32_t(0xb973c0de - 136); class XDRBuffer { public: diff --git a/js/xpconnect/idl/xpccomponents.idl b/js/xpconnect/idl/xpccomponents.idl index 3b71dddc9af2..9d9c0874e1fa 100644 --- a/js/xpconnect/idl/xpccomponents.idl +++ b/js/xpconnect/idl/xpccomponents.idl @@ -384,9 +384,6 @@ interface nsIXPCComponents_Utils : nsISupports [implicit_jscontext] attribute boolean atline; - [implicit_jscontext] - attribute boolean xml; - [implicit_jscontext] attribute boolean methodjit; diff --git a/js/xpconnect/loader/mozJSComponentLoader.cpp b/js/xpconnect/loader/mozJSComponentLoader.cpp index 9e9ec749b0f4..1a14a5d54807 100644 --- a/js/xpconnect/loader/mozJSComponentLoader.cpp +++ b/js/xpconnect/loader/mozJSComponentLoader.cpp @@ -471,11 +471,6 @@ mozJSComponentLoader::ReallyInit() if (!mContext) return NS_ERROR_OUT_OF_MEMORY; - if (Preferences::GetBool("javascript.options.xml.chrome")) { - uint32_t options = JS_GetOptions(mContext); - JS_SetOptions(mContext, options | JSOPTION_ALLOW_XML | JSOPTION_MOAR_XML); - } - // Always use the latest js version JS_SetVersion(mContext, JSVERSION_LATEST); diff --git a/js/xpconnect/shell/xpcshell.cpp b/js/xpconnect/shell/xpcshell.cpp index d02b27648ff1..30c420e45718 100644 --- a/js/xpconnect/shell/xpcshell.cpp +++ b/js/xpconnect/shell/xpcshell.cpp @@ -702,8 +702,6 @@ static const struct JSOption { {"atline", JSOPTION_ATLINE}, {"strict", JSOPTION_STRICT}, {"werror", JSOPTION_WERROR}, - {"allow_xml", JSOPTION_ALLOW_XML}, - {"moar_xml", JSOPTION_MOAR_XML}, {"strict_mode", JSOPTION_STRICT_MODE}, }; @@ -1131,7 +1129,7 @@ static int usage(void) { fprintf(gErrFile, "%s\n", JS_GetImplementationVersion()); - fprintf(gErrFile, "usage: xpcshell [-g gredir] [-a appdir] [-r manifest]... [-PsSwWxCijmIn] [-v version] [-f scriptfile] [-e script] [scriptfile] [scriptarg...]\n"); + fprintf(gErrFile, "usage: xpcshell [-g gredir] [-a appdir] [-r manifest]... [-PsSwWCijmIn] [-v version] [-f scriptfile] [-e script] [scriptfile] [scriptarg...]\n"); return 2; } @@ -1156,9 +1154,6 @@ ProcessArgsForCompartment(JSContext *cx, char **argv, int argc) case 's': JS_ToggleOptions(cx, JSOPTION_STRICT); break; - case 'x': - JS_ToggleOptions(cx, JSOPTION_MOAR_XML); - break; case 'm': JS_ToggleOptions(cx, JSOPTION_METHODJIT); break; @@ -1830,7 +1825,6 @@ main(int argc, char **argv, char **envp) argv++; ProcessArgsForCompartment(cx, argv, argc); - JS_SetOptions(cx, JS_GetOptions(cx) | JSOPTION_ALLOW_XML); xpc_LocalizeContext(cx); nsCOMPtr xpc = do_GetService(nsIXPConnect::GetCID()); diff --git a/js/xpconnect/src/XPCComponents.cpp b/js/xpconnect/src/XPCComponents.cpp index cee97aab8b8a..3aad01c78f6b 100644 --- a/js/xpconnect/src/XPCComponents.cpp +++ b/js/xpconnect/src/XPCComponents.cpp @@ -3762,16 +3762,12 @@ ContextHolder::ContextHolder(JSContext *aOuterCx, DebugOnly rv = XPCWrapper::GetSecurityManager()-> IsSystemPrincipal(mPrincipal, &isChrome); MOZ_ASSERT(NS_SUCCEEDED(rv)); - bool allowXML = Preferences::GetBool(isChrome ? - "javascript.options.xml.chrome" : - "javascript.options.xml.content"); JSAutoRequest ar(mJSContext); JS_SetOptions(mJSContext, JS_GetOptions(mJSContext) | JSOPTION_DONT_REPORT_UNCAUGHT | - JSOPTION_PRIVATE_IS_NSISUPPORTS | - (allowXML ? JSOPTION_ALLOW_XML : 0)); + JSOPTION_PRIVATE_IS_NSISUPPORTS); JS_SetGlobalObject(mJSContext, aSandbox); JS_SetContextPrivate(mJSContext, this); JS_SetOperationCallback(mJSContext, ContextHolderOperationCallback); @@ -4494,7 +4490,6 @@ SetBoolOption(JSContext* cx, uint32_t aOption, bool aValue) GENERATE_JSOPTION_GETTER_SETTER(Strict, JSOPTION_STRICT) GENERATE_JSOPTION_GETTER_SETTER(Werror, JSOPTION_WERROR) GENERATE_JSOPTION_GETTER_SETTER(Atline, JSOPTION_ATLINE) -GENERATE_JSOPTION_GETTER_SETTER(Xml, JSOPTION_MOAR_XML) GENERATE_JSOPTION_GETTER_SETTER(Methodjit, JSOPTION_METHODJIT) GENERATE_JSOPTION_GETTER_SETTER(Methodjit_always, JSOPTION_METHODJIT_ALWAYS) GENERATE_JSOPTION_GETTER_SETTER(Strict_mode, JSOPTION_STRICT_MODE) diff --git a/js/xpconnect/src/XPCConvert.cpp b/js/xpconnect/src/XPCConvert.cpp index b3f86b581030..2546d553093d 100644 --- a/js/xpconnect/src/XPCConvert.cpp +++ b/js/xpconnect/src/XPCConvert.cpp @@ -1059,12 +1059,6 @@ XPCConvert::JSObject2NativeInterface(JSContext* cx, } // else... - // XXX E4X breaks the world. Don't try wrapping E4X objects! - // This hack can be removed (or changed accordingly) when the - // DOM <-> E4X bindings are complete, see bug 270553 - if (JS_TypeOfValue(cx, OBJECT_TO_JSVAL(src)) == JSTYPE_XML) - return false; - // Deal with slim wrappers here. if (GetISupportsFromJSObject(inner ? inner : src, &iface)) { if (iface) diff --git a/js/xpconnect/src/XPCJSRuntime.cpp b/js/xpconnect/src/XPCJSRuntime.cpp index c13e1f567b8e..0f378280b83c 100644 --- a/js/xpconnect/src/XPCJSRuntime.cpp +++ b/js/xpconnect/src/XPCJSRuntime.cpp @@ -1646,13 +1646,6 @@ ReportCompartmentStats(const JS::CompartmentStats &cStats, "heap that holds references to executable code pools " "used by IonMonkey."); -#if JS_HAS_XML_SUPPORT - CREPORT_GC_BYTES(cJSPathPrefix + NS_LITERAL_CSTRING("gc-heap/xml"), - cStats.gcHeapXML, - "Memory on the garbage-collected JavaScript " - "heap that holds E4X XML objects."); -#endif - CREPORT_BYTES(cJSPathPrefix + NS_LITERAL_CSTRING("objects-extra/slots"), cStats.objectsExtra.slots, "Memory allocated for the non-fixed object " diff --git a/js/xpconnect/src/XPCQuickStubs.cpp b/js/xpconnect/src/XPCQuickStubs.cpp index f0cbda4a3305..8e93e1263ca0 100644 --- a/js/xpconnect/src/XPCQuickStubs.cpp +++ b/js/xpconnect/src/XPCQuickStubs.cpp @@ -828,14 +828,6 @@ xpc_qsUnwrapArgImpl(JSContext *cx, // else... // Slow path. - // XXX E4X breaks the world. Don't try wrapping E4X objects! - // This hack can be removed (or changed accordingly) when the - // DOM <-> E4X bindings are complete, see bug 270553 - if (JS_TypeOfValue(cx, OBJECT_TO_JSVAL(src)) == JSTYPE_XML) { - *ppArgRef = nullptr; - return NS_ERROR_XPC_BAD_CONVERT_JS; - } - // Try to unwrap a slim wrapper. nsISupports *iface; if (XPCConvert::GetISupportsFromJSObject(src, &iface)) { diff --git a/js/xpconnect/src/nsXPConnect.cpp b/js/xpconnect/src/nsXPConnect.cpp index f348849e74eb..d25939b8b6f9 100644 --- a/js/xpconnect/src/nsXPConnect.cpp +++ b/js/xpconnect/src/nsXPConnect.cpp @@ -769,7 +769,6 @@ DescribeGCThing(bool isMarked, void *p, JSGCTraceKind traceKind, "String", "Script", "IonCode", - "Xml", "Shape", "BaseShape", "TypeObject", @@ -2516,13 +2515,8 @@ nsXPConnect::GetTelemetryValue(JSContext *cx, jsval *rval) unsigned attrs = JSPROP_ENUMERATE | JSPROP_READONLY | JSPROP_PERMANENT; - size_t i = JS_GetE4XObjectsCreated(cx); + size_t i = JS_SetProtoCalled(cx); jsval v = DOUBLE_TO_JSVAL(i); - if (!JS_DefineProperty(cx, obj, "e4x", v, NULL, NULL, attrs)) - return NS_ERROR_OUT_OF_MEMORY; - - i = JS_SetProtoCalled(cx); - v = DOUBLE_TO_JSVAL(i); if (!JS_DefineProperty(cx, obj, "setProto", v, NULL, NULL, attrs)) return NS_ERROR_OUT_OF_MEMORY; diff --git a/js/xpconnect/src/xpcprivate.h b/js/xpconnect/src/xpcprivate.h index 8826687a3ba3..ab30377f1aaa 100644 --- a/js/xpconnect/src/xpcprivate.h +++ b/js/xpconnect/src/xpcprivate.h @@ -451,12 +451,10 @@ private: // returned as function call result values they are not addref'd. Exceptions // to this rule are noted explicitly. -// JSTRACE_XML can recursively hold on to more JSTRACE_XML objects, adding it to -// the cycle collector avoids stack overflow. inline bool AddToCCKind(JSGCTraceKind kind) { - return kind == JSTRACE_OBJECT || kind == JSTRACE_XML || kind == JSTRACE_SCRIPT; + return kind == JSTRACE_OBJECT || kind == JSTRACE_SCRIPT; } class nsXPConnect : public nsIXPConnect, diff --git a/modules/libpref/src/init/all.js b/modules/libpref/src/init/all.js index 9a8f5a641e6d..d7dd0d77693a 100644 --- a/modules/libpref/src/init/all.js +++ b/modules/libpref/src/init/all.js @@ -743,8 +743,6 @@ pref("javascript.options.ion.parallel_compilation", true); pref("javascript.options.pccounts.content", false); pref("javascript.options.pccounts.chrome", false); pref("javascript.options.methodjit_always", false); -pref("javascript.options.xml.content", false); -pref("javascript.options.xml.chrome", false); pref("javascript.options.jit_hardening", true); pref("javascript.options.typeinference", true); // This preference limits the memory usage of javascript.