author | Nicholas Nethercote <nnethercote@mozilla.com> |
Thu, 24 Jan 2013 21:24:57 -0800 (2013-01-25) | |
changeset 120561 | c929583ba8ae39a6e32752039fc538f3e94fde9a |
parent 120560 | ffacb7f986f03e056c7128b364e7477cb01e94bc |
child 120562 | c6e5bf0eb51a1a3c291e96c47bae8b30d52b56ba |
push id | 24256 |
push user | ryanvm@gmail.com |
push date | Fri, 01 Feb 2013 20:50:01 +0000 (2013-02-01) |
treeherder | mozilla-central@4e7c92906a79 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | jorendorff, terrence, evilpie |
bugs | 788293 |
milestone | 21.0a1 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
--- a/content/base/src/nsFrameMessageManager.cpp +++ b/content/base/src/nsFrameMessageManager.cpp @@ -1124,20 +1124,17 @@ nsFrameScriptExecutor::InitTabChildGloba JSContext* cx = JS_NewContext(rt, 8192); NS_ENSURE_TRUE(cx, false); mCx = cx; 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); xpc_LocalizeContext(cx); JSAutoRequest ar(cx); nsIXPConnect* xpc = nsContentUtils::XPConnect(); const uint32_t flags = nsIXPConnect::INIT_JS_STANDARD_CLASSES;
--- a/content/base/src/nsScriptLoader.cpp +++ b/content/base/src/nsScriptLoader.cpp @@ -393,30 +393,16 @@ ParseTypeAttribute(const nsAString& aTyp rv = parser.GetParameter("version", versionName); if (NS_SUCCEEDED(rv)) { *aVersion = nsContentUtils::ParseJavascriptVersion(versionName); } else if (rv != NS_ERROR_INVALID_ARG) { 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; } bool nsScriptLoader::ProcessScriptElement(nsIScriptElement *aElement) { // We need a document to evaluate scripts. NS_ENSURE_TRUE(mDocument, false);
--- a/content/xul/document/src/nsXULContentSink.cpp +++ b/content/xul/document/src/nsXULContentSink.cpp @@ -1,9 +1,10 @@ -/* -*- 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/. */ /* * An implementation for a Gecko-style content sink that knows how * to build a content model (the "prototype" document) from XUL. * @@ -868,54 +869,34 @@ XULContentSinkImpl::OpenScript(const PRU if (nsContentUtils::IsJavascriptMIMEType(mimeType)) { langID = nsIProgrammingLanguage::JAVASCRIPT; version = JSVERSION_LATEST; } else { langID = nsIProgrammingLanguage::UNKNOWN; } 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; } } } else if (key.EqualsLiteral("language")) { // Language is deprecated, and the impl in nsScriptLoader ignores the // various version strings anyway. So we make no attempt to support // languages other than JS for language= 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; } // Not all script languages have a "sandbox" concept. At time of // writing, Python is the only other language, and it does not. // For such languages, neither any inline script nor remote script are
--- a/dom/base/nsGlobalWindow.cpp +++ b/dom/base/nsGlobalWindow.cpp @@ -1901,27 +1901,18 @@ WindowStateHolder::~WindowStateHolder() NS_IMPL_ISUPPORTS1(WindowStateHolder, WindowStateHolder) nsresult 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 <!-- script hiding hack from JS-in-HTML daze - // (introduced in 1995 for graceful script degradation in Netscape 1, - // Mosaic, and other pre-JS browsers). - JS_SetOptions(cx, JS_GetOptions(cx) | JSOPTION_MOAR_XML); - } - JSObject* outer = NewOuterWindowProxy(cx, aNewInner->FastGetGlobalJSObject(), - isChrome); + IsChromeWindow()); if (!outer) { return NS_ERROR_FAILURE; } js::SetProxyExtra(outer, 0, js::PrivateValue(ToSupports(this))); return SetOuterObject(cx, outer); }
--- a/dom/base/nsJSEnvironment.cpp +++ b/dom/base/nsJSEnvironment.cpp @@ -998,32 +998,28 @@ nsJSContext::JSOptionChangedCallback(con bool useMethodJIT = Preferences::GetBool(chromeWindow || !contentWindow ? js_methodjit_chrome_str : js_methodjit_content_str); bool usePCCounts = Preferences::GetBool(chromeWindow || !contentWindow ? js_pccounts_chrome_str : js_pccounts_content_str); bool useMethodJITAlways = Preferences::GetBool(js_methodjit_always_str); bool useTypeInference = !chromeWindow && contentWindow && Preferences::GetBool(js_typeinfer_str); - bool useXML = Preferences::GetBool(chromeWindow || !contentWindow ? - "javascript.options.xml.chrome" : - "javascript.options.xml.content"); bool useHardening = Preferences::GetBool(js_jit_hardening_str); bool useIon = Preferences::GetBool(js_ion_content_str); bool parallelIonCompilation = Preferences::GetBool(js_ion_parallel_compilation_str); nsCOMPtr<nsIXULRuntime> xr = do_GetService(XULRUNTIME_SERVICE_CONTRACTID); if (xr) { bool safeMode = false; xr->GetInSafeMode(&safeMode); if (safeMode) { useMethodJIT = false; usePCCounts = false; useTypeInference = false; useMethodJITAlways = true; - useXML = false; useHardening = false; useIon = false; } } if (useMethodJIT) newDefaultJSOptions |= JSOPTION_METHODJIT; else @@ -1044,39 +1040,33 @@ nsJSContext::JSOptionChangedCallback(con else newDefaultJSOptions &= ~JSOPTION_TYPE_INFERENCE; if (useIon) newDefaultJSOptions |= JSOPTION_ION; else newDefaultJSOptions &= ~JSOPTION_ION; - if (useXML) - newDefaultJSOptions |= JSOPTION_ALLOW_XML; - else - newDefaultJSOptions &= ~JSOPTION_ALLOW_XML; - #ifdef DEBUG // In debug builds, warnings are enabled in chrome context if // javascript.options.strict.debug is true bool strictDebug = Preferences::GetBool(js_strict_debug_option_str); if (strictDebug && (newDefaultJSOptions & JSOPTION_STRICT) == 0) { if (chromeWindow || !contentWindow) newDefaultJSOptions |= JSOPTION_STRICT; } #endif bool werror = Preferences::GetBool(js_werror_option_str); if (werror) newDefaultJSOptions |= JSOPTION_WERROR; else newDefaultJSOptions &= ~JSOPTION_WERROR; - ::JS_SetOptions(context->mContext, - newDefaultJSOptions & (JSRUNOPTION_MASK | JSOPTION_ALLOW_XML)); + ::JS_SetOptions(context->mContext, newDefaultJSOptions & JSRUNOPTION_MASK); ::JS_SetParallelCompilationEnabled(context->mContext, parallelIonCompilation); // Save the new defaults for the next page load (InitContext). context->mDefaultJSOptions = newDefaultJSOptions; JSRuntime *rt = JS_GetRuntime(context->mContext); JS_SetJitHardening(rt, useHardening); @@ -1102,17 +1092,17 @@ nsJSContext::nsJSContext(JSRuntime *aRun mPrev = &sContextList; if (sContextList) { sContextList->mPrev = &mNext; } sContextList = this; ++sContextCount; - mDefaultJSOptions = JSOPTION_PRIVATE_IS_NSISUPPORTS | JSOPTION_ALLOW_XML; + mDefaultJSOptions = JSOPTION_PRIVATE_IS_NSISUPPORTS; mContext = ::JS_NewContext(aRuntime, gStackSize); if (mContext) { ::JS_SetContextPrivate(mContext, static_cast<nsIScriptContext *>(this)); // Preserve any flags the context callback might have set. mDefaultJSOptions |= ::JS_GetOptions(mContext);
--- a/dom/src/json/nsJSON.cpp +++ b/dom/src/json/nsJSON.cpp @@ -234,19 +234,19 @@ nsJSON::EncodeInternal(JSContext* cx, co return NS_ERROR_INVALID_ARG; } // GetMethod may have thrown else if (JS_IsExceptionPending(cx)) // passing NS_OK will throw the pending exception return NS_OK; // Backward compatibility: - // function/xml shall not pass, just "plain" objects and arrays + // function shall not pass, just "plain" objects and arrays JSType type = JS_TypeOfValue(cx, val); - if (type == JSTYPE_FUNCTION || type == JSTYPE_XML) + if (type == JSTYPE_FUNCTION) return NS_ERROR_INVALID_ARG; // We're good now; try to stringify if (!JS_Stringify(cx, &val, NULL, JSVAL_NULL, WriteCallback, writer)) return NS_ERROR_FAILURE; return NS_OK; }
--- a/dom/workers/RuntimeService.cpp +++ b/dom/workers/RuntimeService.cpp @@ -146,17 +146,16 @@ MOZ_STATIC_ASSERT(NS_ARRAY_LENGTH(gStrin "gStringChars should have the right length."); enum { PREF_strict = 0, PREF_werror, PREF_methodjit, PREF_methodjit_always, PREF_typeinference, - PREF_allow_xml, PREF_jit_hardening, PREF_mem_max, PREF_ion, PREF_mem_gc_allocation_threshold_mb, #ifdef JS_GC_ZEAL PREF_gczeal, #endif @@ -167,17 +166,16 @@ enum { #define JS_OPTIONS_DOT_STR "javascript.options." const char* gPrefsToWatch[] = { JS_OPTIONS_DOT_STR "strict", JS_OPTIONS_DOT_STR "werror", JS_OPTIONS_DOT_STR "methodjit.content", JS_OPTIONS_DOT_STR "methodjit_always", JS_OPTIONS_DOT_STR "typeinference", - JS_OPTIONS_DOT_STR "allow_xml", JS_OPTIONS_DOT_STR "jit_hardening", JS_OPTIONS_DOT_STR "mem.max", JS_OPTIONS_DOT_STR "ion.content", "dom.workers.mem.gc_allocation_threshold_mb" #ifdef JS_GC_ZEAL , PREF_WORKERS_GCZEAL #endif @@ -225,19 +223,16 @@ PrefCallback(const char* aPrefName, void newOptions |= JSOPTION_METHODJIT_ALWAYS; } if (Preferences::GetBool(gPrefsToWatch[PREF_typeinference])) { newOptions |= JSOPTION_TYPE_INFERENCE; } if (Preferences::GetBool(gPrefsToWatch[PREF_ion])) { newOptions |= JSOPTION_ION; } - if (Preferences::GetBool(gPrefsToWatch[PREF_allow_xml])) { - newOptions |= JSOPTION_ALLOW_XML; - } RuntimeService::SetDefaultJSContextOptions(newOptions); rts->UpdateAllWorkerJSContextOptions(); } #ifdef JS_GC_ZEAL else if (!strcmp(aPrefName, gPrefsToWatch[PREF_gczeal])) { int32_t gczeal = Preferences::GetInt(gPrefsToWatch[PREF_gczeal]); RuntimeService::SetDefaultGCZeal(uint8_t(clamped(gczeal, 0, 3)));
--- a/js/ipc/ObjectWrapperChild.cpp +++ b/js/ipc/ObjectWrapperChild.cpp @@ -168,18 +168,16 @@ ObjectWrapperChild::jsval_to_JSVariant(J *to = JSVAL_TO_INT(from); else if (JSVAL_IS_DOUBLE(from)) *to = JSVAL_TO_DOUBLE(from); else return false; return true; case JSTYPE_BOOLEAN: *to = !!JSVAL_TO_BOOLEAN(from); return true; - case JSTYPE_XML: - // fall through default: return false; } } /*static*/ bool ObjectWrapperChild:: JSObject_from_PObjectWrapperChild(JSContext*,
--- a/js/ipc/ObjectWrapperParent.cpp +++ b/js/ipc/ObjectWrapperParent.cpp @@ -239,18 +239,16 @@ ObjectWrapperParent::jsval_to_JSVariant( *to = JSVAL_TO_INT(from); else if (JSVAL_IS_DOUBLE(from)) *to = JSVAL_TO_DOUBLE(from); else return false; return true; case JSTYPE_BOOLEAN: *to = !!JSVAL_TO_BOOLEAN(from); return true; - case JSTYPE_XML: - return with_error(cx, false, "CPOWs currently cannot handle JSTYPE_XML"); default: return with_error(cx, false, "Bad jsval type"); } } /*static*/ bool ObjectWrapperParent::jsval_from_JSVariant(JSContext* cx, const JSVariant& from, jsval* to)
--- a/js/public/MemoryMetrics.h +++ b/js/public/MemoryMetrics.h @@ -155,19 +155,16 @@ struct CompartmentStats , gcHeapStringsShort(0) , gcHeapShapesTreeGlobalParented(0) , gcHeapShapesTreeNonGlobalParented(0) , gcHeapShapesDict(0) , gcHeapShapesBase(0) , gcHeapScripts(0) , gcHeapTypeObjects(0) , gcHeapIonCodes(0) -#if JS_HAS_XML_SUPPORT - , gcHeapXML(0) -#endif , objectsExtra() , stringCharsNonHuge(0) , shapesExtraTreeTables(0) , shapesExtraDictTables(0) , shapesExtraTreeShapeKids(0) , shapesCompartmentTables(0) , scriptData(0) , jaegerData(0) @@ -194,19 +191,16 @@ struct CompartmentStats , gcHeapStringsShort(other.gcHeapStringsShort) , gcHeapShapesTreeGlobalParented(other.gcHeapShapesTreeGlobalParented) , gcHeapShapesTreeNonGlobalParented(other.gcHeapShapesTreeNonGlobalParented) , gcHeapShapesDict(other.gcHeapShapesDict) , gcHeapShapesBase(other.gcHeapShapesBase) , gcHeapScripts(other.gcHeapScripts) , gcHeapTypeObjects(other.gcHeapTypeObjects) , gcHeapIonCodes(other.gcHeapIonCodes) -#if JS_HAS_XML_SUPPORT - , gcHeapXML(other.gcHeapXML) -#endif , objectsExtra(other.objectsExtra) , stringCharsNonHuge(other.stringCharsNonHuge) , shapesExtraTreeTables(other.shapesExtraTreeTables) , shapesExtraDictTables(other.shapesExtraDictTables) , shapesExtraTreeShapeKids(other.shapesExtraTreeShapeKids) , shapesCompartmentTables(other.shapesCompartmentTables) , scriptData(other.scriptData) , jaegerData(other.jaegerData) @@ -238,19 +232,16 @@ struct CompartmentStats size_t gcHeapStringsShort; size_t gcHeapShapesTreeGlobalParented; size_t gcHeapShapesTreeNonGlobalParented; size_t gcHeapShapesDict; size_t gcHeapShapesBase; size_t gcHeapScripts; size_t gcHeapTypeObjects; size_t gcHeapIonCodes; -#if JS_HAS_XML_SUPPORT - size_t gcHeapXML; -#endif ObjectsExtraSizes objectsExtra; size_t stringCharsNonHuge; size_t shapesExtraTreeTables; size_t shapesExtraDictTables; size_t shapesExtraTreeShapeKids; size_t shapesCompartmentTables; size_t scriptData; @@ -281,19 +272,16 @@ struct CompartmentStats ADD(gcHeapStringsShort); ADD(gcHeapShapesTreeGlobalParented); ADD(gcHeapShapesTreeNonGlobalParented); ADD(gcHeapShapesDict); ADD(gcHeapShapesBase); ADD(gcHeapScripts); ADD(gcHeapTypeObjects); ADD(gcHeapIonCodes); - #if JS_HAS_XML_SUPPORT - ADD(gcHeapXML); - #endif objectsExtra.add(cStats.objectsExtra); ADD(stringCharsNonHuge); ADD(shapesExtraTreeTables); ADD(shapesExtraDictTables); ADD(shapesExtraTreeShapeKids); ADD(shapesCompartmentTables); ADD(scriptData);
--- a/js/src/Makefile.in +++ b/js/src/Makefile.in @@ -114,17 +114,16 @@ CPPSRCS = \ jsutil.cpp \ jswatchpoint.cpp \ jsweakmap.cpp \ jsworkers.cpp \ ThreadPool.cpp \ Monitor.cpp \ ForkJoin.cpp \ jswrapper.cpp \ - jsxml.cpp \ prmjtime.cpp \ sharkctl.cpp \ ArgumentsObject.cpp \ DateTime.cpp \ Debugger.cpp \ GlobalObject.cpp \ Object.cpp \ ObjectImpl.cpp \
--- a/js/src/builtin/Object.cpp +++ b/js/src/builtin/Object.cpp @@ -706,22 +706,16 @@ obj_create(JSContext *cx, unsigned argc, return false; JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_UNEXPECTED_TYPE, bytes, "not an object or null"); js_free(bytes); return false; } JSObject *proto = v.toObjectOrNull(); -#if JS_HAS_XML_SUPPORT - if (proto && proto->isXML()) { - JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_XML_PROTO_FORBIDDEN); - return false; - } -#endif /* * Use the callee's global as the parent of the new object to avoid dynamic * scoping (i.e., using the caller's global). */ RootedObject obj(cx, NewObjectWithGivenProto(cx, &ObjectClass, proto, &args.callee().global())); if (!obj) return false;
--- a/js/src/builtin/TestingFunctions.cpp +++ b/js/src/builtin/TestingFunctions.cpp @@ -171,24 +171,16 @@ GetBuildConfiguration(JSContext *cx, uns #ifdef JS_METHODJIT value = BooleanValue(true); #else value = BooleanValue(false); #endif if (!JS_SetProperty(cx, info, "methodjit", &value)) return false; -#ifdef JS_HAS_XML_SUPPORT - value = BooleanValue(true); -#else - value = BooleanValue(false); -#endif - if (!JS_SetProperty(cx, info, "e4x", &value)) - return false; - *vp = ObjectValue(*info); return true; } static JSBool GC(JSContext *cx, unsigned argc, jsval *vp) { /* @@ -633,19 +625,16 @@ CountHeapNotify(JSTracer *trc, void **th static const struct TraceKindPair { const char *name; int32_t kind; } traceKindNames[] = { { "all", -1 }, { "object", JSTRACE_OBJECT }, { "string", JSTRACE_STRING }, -#if JS_HAS_XML_SUPPORT - { "xml", JSTRACE_XML }, -#endif }; static JSBool CountHeap(JSContext *cx, unsigned argc, jsval *vp) { void* startThing; JSGCTraceKind startTraceKind; jsval v; @@ -905,18 +894,18 @@ static JSFunctionSpecWithHelp TestingFun "getBuildConfiguration()", " Return an object describing some of the configuration options SpiderMonkey\n" " was built with."), JS_FN_HELP("countHeap", CountHeap, 0, 0, "countHeap([start[, kind]])", " Count the number of live GC things in the heap or things reachable from\n" " start when it is given and is not null. kind is either 'all' (default) to\n" -" count all things or one of 'object', 'double', 'string', 'function',\n" -" 'qname', 'namespace', 'xml' to count only things of that kind."), +" count all things or one of 'object', 'double', 'string', 'function'\n" +" to count only things of that kind."), JS_FN_HELP("makeFinalizeObserver", MakeFinalizeObserver, 0, 0, "makeFinalizeObserver()", " Get a special object whose finalization increases the counter returned\n" " by the finalizeCount function."), JS_FN_HELP("finalizeCount", FinalizeCount, 0, 0, "finalizeCount()", @@ -932,18 +921,18 @@ static JSFunctionSpecWithHelp TestingFun "gczeal(level, [period])", " Specifies how zealous the garbage collector should be. Values for level:\n" " 0: Normal amount of collection\n" " 1: Collect when roots are added or removed\n" " 2: Collect when memory is allocated\n" " 3: Collect 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 and Reflect)\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" " 11: Verify post write barriers between instructions\n" " 12: Verify post write barriers between paints\n" " 13: Purge analysis state when memory is allocated\n" " Period specifies that collection happens every n allocations.\n"),
--- a/js/src/configure.in +++ b/js/src/configure.in @@ -3810,25 +3810,16 @@ MOZ_ARG_WITH_STRING(jitreport-granularit 2 - per-line information 3 - per-op information], JITREPORT_GRANULARITY=$withval, JITREPORT_GRANULARITY=3) AC_DEFINE_UNQUOTED(JS_DEFAULT_JITREPORT_GRANULARITY, $JITREPORT_GRANULARITY) dnl ======================================================== -dnl = E4X support (ECMA-357) -dnl ======================================================== -JS_HAS_XML_SUPPORT=1 -MOZ_ARG_DISABLE_BOOL(e4x, -[ --disable-e4x Disable JS support for XML (ECMA-357)], - JS_HAS_XML_SUPPORT=0 ) -AC_DEFINE_UNQUOTED(JS_HAS_XML_SUPPORT, $JS_HAS_XML_SUPPORT) - -dnl ======================================================== dnl = dnl = Misc. Options dnl = dnl ======================================================== MOZ_ARG_HEADER(Misc. Options) dnl ======================================================== dnl update xterm title
--- a/js/src/frontend/BytecodeCompiler.cpp +++ b/js/src/frontend/BytecodeCompiler.cpp @@ -153,74 +153,50 @@ frontend::CompileScript(JSContext *cx, H JSFunction *fun = callerFrame.fun(); ObjectBox *funbox = parser.newFunctionBox(fun, &pc, fun->strict()); if (!funbox) return UnrootedScript(NULL); bce.objectList.add(funbox); } } - ParseNode *pn; -#if JS_HAS_XML_SUPPORT - pn = NULL; - bool onlyXML; - onlyXML = true; -#endif - TokenStream &tokenStream = parser.tokenStream; bool canHaveDirectives = true; for (;;) { TokenKind tt = tokenStream.peekToken(TSF_OPERAND); if (tt <= TOK_EOF) { if (tt == TOK_EOF) break; JS_ASSERT(tt == TOK_ERROR); return UnrootedScript(NULL); } - pn = parser.statement(); + ParseNode *pn = parser.statement(); if (!pn) return UnrootedScript(NULL); if (canHaveDirectives) { if (!parser.maybeParseDirective(pn, &canHaveDirectives)) return UnrootedScript(NULL); } if (!FoldConstants(cx, &pn, &parser)) return UnrootedScript(NULL); if (!NameFunctions(cx, pn)) return UnrootedScript(NULL); if (!EmitTree(cx, &bce, pn)) return UnrootedScript(NULL); -#if JS_HAS_XML_SUPPORT - if (!pn->isKind(PNK_SEMI) || !pn->pn_kid || !pn->pn_kid->isXMLItem()) - onlyXML = false; -#endif parser.freeTree(pn); } if (!SetSourceMap(cx, tokenStream, ss, script)) return UnrootedScript(NULL); -#if JS_HAS_XML_SUPPORT - /* - * Prevent XML data theft via <script src="http://victim.com/foo.xml">. - * For background, see: - * - * https://bugzilla.mozilla.org/show_bug.cgi?id=336551 - */ - if (pn && onlyXML && !callerFrame) { - parser.reportError(NULL, JSMSG_XML_WHOLE_PROGRAM); - return UnrootedScript(NULL); - } -#endif - // It's an error to use |arguments| in a function that has a rest parameter. if (callerFrame && callerFrame.isFunctionFrame() && callerFrame.fun()->hasRest()) { HandlePropertyName arguments = cx->names().arguments; for (AtomDefnRange r = pc.lexdeps->all(); !r.empty(); r.popFront()) { if (r.front().key() == arguments) { parser.reportError(NULL, JSMSG_ARGUMENTS_AND_REST); return UnrootedScript(NULL); }
--- a/js/src/frontend/BytecodeEmitter.cpp +++ b/js/src/frontend/BytecodeEmitter.cpp @@ -1579,22 +1579,16 @@ CheckSideEffects(JSContext *cx, Bytecode if (!BindNameToSlot(cx, bce, pn2)) return false; if (pn2->isConst()) { *answer = false; break; } /* FALL THROUGH */ case PNK_DOT: -#if JS_HAS_XML_SUPPORT - case PNK_DBLDOT: - JS_ASSERT_IF(pn2->getKind() == PNK_DBLDOT, !bce->sc->strict); - /* FALL THROUGH */ - -#endif case PNK_CALL: case PNK_ELEM: /* All these delete addressing modes have effects too. */ *answer = true; break; default: ok = CheckSideEffects(cx, bce, pn2, answer); break; @@ -1804,41 +1798,16 @@ EmitNameOp(JSContext *cx, BytecodeEmitte } if (Emit1(cx, bce, JSOP_NOTEARG) < 0) return false; } return true; } -#if JS_HAS_XML_SUPPORT -static bool -EmitXMLName(JSContext *cx, ParseNode *pn, JSOp op, BytecodeEmitter *bce) -{ - JS_ASSERT(!bce->sc->strict); - JS_ASSERT(pn->isKind(PNK_XMLUNARY)); - JS_ASSERT(pn->isOp(JSOP_XMLNAME)); - JS_ASSERT(op == JSOP_XMLNAME || op == JSOP_CALLXMLNAME); - - ParseNode *pn2 = pn->pn_kid; - bool oldEmittingForInit = bce->emittingForInit; - bce->emittingForInit = false; - if (!EmitTree(cx, bce, pn2)) - return false; - bce->emittingForInit = oldEmittingForInit; - if (NewSrcNote2(cx, bce, SRC_PCBASE, bce->offset() - pn2->pn_offset) < 0) - return false; - - if (Emit1(cx, bce, op) < 0) - return false; - - return true; -} -#endif - static inline bool EmitElemOpBase(JSContext *cx, BytecodeEmitter *bce, JSOp op) { if (Emit1(cx, bce, op) < 0) return false; CheckTypeSet(cx, bce, op); if (op == JSOP_CALLELEM) { @@ -2053,17 +2022,17 @@ EmitElemOp(JSContext *cx, ParseNode *pn, return false; left->setOp(JSOP_BINDNAME); left->pn_pos = pn->pn_pos; left->pn_atom = pn->pn_atom; } right = NullaryNode::create(PNK_STRING, bce->parser); if (!right) return false; - right->setOp(IsIdentifier(pn->pn_atom) ? JSOP_QNAMEPART : JSOP_STRING); + right->setOp(JSOP_STRING); right->pn_pos = pn->pn_pos; right->pn_atom = pn->pn_atom; } else { JS_ASSERT(pn->isArity(PN_BINARY)); left = pn->pn_left; right = pn->pn_right; } @@ -2073,19 +2042,16 @@ EmitElemOp(JSContext *cx, ParseNode *pn, } if (!EmitTree(cx, bce, left)) return false; if (op == JSOP_CALLELEM && Emit1(cx, bce, JSOP_DUP) < 0) return false; - /* The right side of the descendant operator is implicitly quoted. */ - JS_ASSERT(op != JSOP_DESCENDANTS || !right->isKind(PNK_STRING) || - right->isOp(JSOP_QNAMEPART)); if (!EmitTree(cx, bce, right)) return false; if (NewSrcNote2(cx, bce, SRC_PCBASE, bce->offset() - top) < 0) return false; return EmitElemOpBase(cx, bce, op); } static bool @@ -3470,27 +3436,16 @@ EmitAssignment(JSContext *cx, BytecodeEm break; #endif case PNK_CALL: if (!EmitTree(cx, bce, lhs)) return false; JS_ASSERT(lhs->pn_xflags & PNX_SETCALL); offset += 2; break; -#if JS_HAS_XML_SUPPORT - case PNK_XMLUNARY: - JS_ASSERT(!bce->sc->strict); - JS_ASSERT(lhs->isOp(JSOP_SETXMLNAME)); - if (!EmitTree(cx, bce, lhs->pn_kid)) - return false; - if (Emit1(cx, bce, JSOP_BINDXMLNAME) < 0) - return false; - offset += 2; - break; -#endif default: JS_ASSERT(0); } if (op != JSOP_NOP) { JS_ASSERT(rhs); switch (lhs->getKind()) { case PNK_NAME: @@ -3530,19 +3485,16 @@ EmitAssignment(JSContext *cx, BytecodeEm return false; bool isLength = (lhs->pn_atom == cx->names().length); if (!EmitIndex32(cx, isLength ? JSOP_LENGTH : JSOP_GETPROP, atomIndex, bce)) return false; break; } case PNK_ELEM: case PNK_CALL: -#if JS_HAS_XML_SUPPORT - case PNK_XMLUNARY: -#endif if (Emit1(cx, bce, JSOP_DUP2) < 0) return false; if (!EmitElemOpBase(cx, bce, JSOP_GETELEM)) return false; break; default:; } } @@ -3617,23 +3569,16 @@ EmitAssignment(JSContext *cx, BytecodeEm break; #if JS_HAS_DESTRUCTURING case PNK_ARRAY: case PNK_OBJECT: if (!EmitDestructuringOps(cx, bce, SRC_DECL_NONE, lhs)) return false; break; #endif -#if JS_HAS_XML_SUPPORT - case PNK_XMLUNARY: - JS_ASSERT(!bce->sc->strict); - if (Emit1(cx, bce, JSOP_SETXMLNAME) < 0) - return false; - break; -#endif default: JS_ASSERT(0); } return true; } #ifdef DEBUG static bool @@ -4311,98 +4256,16 @@ EmitLet(JSContext *cx, BytecodeEmitter * ptrdiff_t o = PackLetData((bodyEnd - bodyBegin) - (JSOP_ENTERLET0_LENGTH + JSOP_LEAVEBLOCK_LENGTH), letNotes.isGroupAssign()); return SetSrcNoteOffset(cx, bce, declNote, 0, o); } #endif -#if JS_HAS_XML_SUPPORT -/* - * Using MOZ_NEVER_INLINE in here is a workaround for llvm.org/pr14047. See - * the comment on EmitSwitch. - */ -MOZ_NEVER_INLINE static bool -EmitXMLTag(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn) -{ - JS_ASSERT(!bce->sc->strict); - - if (Emit1(cx, bce, JSOP_STARTXML) < 0) - return false; - - { - jsatomid index; - HandlePropertyName tagAtom = (pn->isKind(PNK_XMLETAGO)) - ? cx->names().etago - : cx->names().stago; - if (!bce->makeAtomIndex(tagAtom, &index)) - return false; - if (!EmitIndex32(cx, JSOP_STRING, index, bce)) - return false; - } - - JS_ASSERT(pn->pn_count != 0); - ParseNode *pn2 = pn->pn_head; - if (pn2->isKind(PNK_XMLCURLYEXPR) && Emit1(cx, bce, JSOP_STARTXMLEXPR) < 0) - return false; - if (!EmitTree(cx, bce, pn2)) - return false; - if (Emit1(cx, bce, JSOP_ADD) < 0) - return false; - - uint32_t i; - for (pn2 = pn2->pn_next, i = 0; pn2; pn2 = pn2->pn_next, i++) { - if (pn2->isKind(PNK_XMLCURLYEXPR) && Emit1(cx, bce, JSOP_STARTXMLEXPR) < 0) - return false; - if (!EmitTree(cx, bce, pn2)) - return false; - if ((i & 1) && pn2->isKind(PNK_XMLCURLYEXPR)) { - if (Emit1(cx, bce, JSOP_TOATTRVAL) < 0) - return false; - } - if (Emit1(cx, bce, (i & 1) ? JSOP_ADDATTRVAL : JSOP_ADDATTRNAME) < 0) - return false; - } - - { - jsatomid index; - HandlePropertyName tmp = pn->isKind(PNK_XMLPTAGC) - ? cx->names().ptagc - : cx->names().tagc; - if (!bce->makeAtomIndex(tmp, &index)) - return false; - if (!EmitIndex32(cx, JSOP_STRING, index, bce)) - return false; - } - if (Emit1(cx, bce, JSOP_ADD) < 0) - return false; - - if ((pn->pn_xflags & PNX_XMLROOT) && Emit1(cx, bce, pn->getOp()) < 0) - return false; - - return true; -} - -static bool -EmitXMLProcessingInstruction(JSContext *cx, BytecodeEmitter *bce, XMLProcessingInstruction &pi) -{ - JS_ASSERT(!bce->sc->strict); - - jsatomid index; - if (!bce->makeAtomIndex(pi.data(), &index)) - return false; - if (!EmitIndex32(cx, JSOP_QNAMEPART, index, bce)) - return false; - if (!EmitAtomOp(cx, pi.target(), JSOP_XMLPI, bce)) - return false; - return true; -} -#endif - /* * Using MOZ_NEVER_INLINE in here is a workaround for llvm.org/pr14047. See * the comment on EmitSwitch. */ MOZ_NEVER_INLINE static bool EmitLexicalScope(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn) { JS_ASSERT(pn->isKind(PNK_LEXICALSCOPE)); @@ -5249,23 +5112,16 @@ EmitDelete(JSContext *cx, BytecodeEmitte return false; } break; } case PNK_DOT: if (!EmitPropOp(cx, pn2, JSOP_DELPROP, bce, false)) return false; break; -#if JS_HAS_XML_SUPPORT - case PNK_DBLDOT: - JS_ASSERT(!bce->sc->strict); - if (!EmitElemOp(cx, pn2, JSOP_DELDESC, bce)) - return false; - break; -#endif case PNK_ELEM: if (!EmitElemOp(cx, pn2, JSOP_DELELEM, bce)) return false; break; default: { /* * If useless, just emit JSOP_TRUE; otherwise convert delete foo() @@ -5306,20 +5162,20 @@ EmitCallOrNew(JSContext *cx, BytecodeEmi { bool callop = pn->isKind(PNK_CALL); /* * Emit callable invocation or operator new (constructor call) code. * First, emit code for the left operand to evaluate the callable or * constructable object expression. * - * For operator new applied to other expressions than E4X ones, we emit - * JSOP_GETPROP instead of JSOP_CALLPROP, etc. This is necessary to - * interpose the lambda-initialized method read barrier -- see the code - * in jsinterp.cpp for JSOP_LAMBDA followed by JSOP_{SET,INIT}PROP. + * For operator new, we emit JSOP_GETPROP instead of JSOP_CALLPROP, etc. + * This is necessary to interpose the lambda-initialized method read + * barrier -- see the code in jsinterp.cpp for JSOP_LAMBDA followed by + * JSOP_{SET,INIT}PROP. * * Then (or in a call case that has no explicit reference-base * object) we emit JSOP_UNDEFINED to produce the undefined |this| * value required for calls (which non-strict mode functions * will box into the global object). */ uint32_t argc = pn->pn_count - 1; bool emitArgs = true; @@ -5371,24 +5227,16 @@ EmitCallOrNew(JSContext *cx, BytecodeEmi if (!EmitPropOp(cx, pn2, pn2->getOp(), bce, callop)) return false; break; case PNK_ELEM: JS_ASSERT(pn2->isOp(JSOP_GETELEM)); if (!EmitElemOp(cx, pn2, callop ? JSOP_CALLELEM : JSOP_GETELEM, bce)) return false; break; -#if JS_HAS_XML_SUPPORT - case PNK_XMLUNARY: - JS_ASSERT(pn2->isOp(JSOP_XMLNAME)); - if (!EmitXMLName(cx, pn2, JSOP_CALLXMLNAME, bce)) - return false; - callop = true; /* suppress JSOP_UNDEFINED after */ - break; -#endif case PNK_FUNCTION: /* * Top level lambdas which are immediately invoked should be * treated as only running once. Every time they execute we will * create new types and scripts for their contents, to increase * the quality of type information within them and enable more * backend optimizations. Note that this does not depend on the * lambda being invoked at most once (it may be named or be @@ -5557,28 +5405,16 @@ EmitIncOrDec(JSContext *cx, BytecodeEmit */ JS_ASSERT(js_CodeSpec[op].format & JOF_DECOMPOSE); JS_ASSERT(js_CodeSpec[op].format & JOF_ELEM); if (Emit1(cx, bce, (JSOp)1) < 0) return false; if (Emit1(cx, bce, JSOP_POP) < 0) return false; break; -#if JS_HAS_XML_SUPPORT - case PNK_XMLUNARY: - JS_ASSERT(!bce->sc->strict); - JS_ASSERT(pn2->isOp(JSOP_SETXMLNAME)); - if (!EmitTree(cx, bce, pn2->pn_kid)) - return false; - if (Emit1(cx, bce, JSOP_BINDXMLNAME) < 0) - return false; - if (!EmitElemIncDec(cx, NULL, op, bce)) - return false; - break; -#endif default: JS_ASSERT(pn2->isKind(PNK_NAME)); pn2->setOp(op); if (!BindNameToSlot(cx, bce, pn2)) return false; op = pn2->getOp(); if (op == JSOP_CALLEE) { if (Emit1(cx, bce, op) < 0) @@ -5941,17 +5777,16 @@ static bool EmitUnary(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn) { if (!UpdateSourceCoordNotes(cx, bce, pn->pn_pos.begin)) return false; /* Unary op, including unary +/-. */ JSOp op = pn->getOp(); ParseNode *pn2 = pn->pn_kid; - JS_ASSERT(op != JSOP_XMLNAME); if (op == JSOP_TYPEOF && !pn2->isKind(PNK_NAME)) op = JSOP_TYPEOFEXPR; bool oldEmittingForInit = bce->emittingForInit; bce->emittingForInit = false; if (!EmitTree(cx, bce, pn2)) return false; @@ -6176,26 +6011,16 @@ frontend::EmitTree(JSContext *cx, Byteco } if (pn->pn_hidden && NewSrcNote(cx, bce, SRC_HIDDEN) < 0) return false; if (Emit1(cx, bce, JSOP_YIELD) < 0) return false; break; #endif -#if JS_HAS_XML_SUPPORT - case PNK_XMLCURLYEXPR: - JS_ASSERT(pn->isArity(PN_UNARY)); - if (!EmitTree(cx, bce, pn->pn_kid)) - return false; - if (Emit1(cx, bce, pn->getOp()) < 0) - return false; - break; -#endif - case PNK_STATEMENTLIST: ok = EmitStatementList(cx, bce, pn, top); break; case PNK_SEQ: ok = EmitSyntheticStatements(cx, bce, pn, top); break; @@ -6289,79 +6114,27 @@ frontend::EmitTree(JSContext *cx, Byteco JSOp op = pn->getOp(); while ((pn2 = pn2->pn_next) != NULL) { if (!EmitTree(cx, bce, pn2)) return false; if (Emit1(cx, bce, op) < 0) return false; } } else { -#if JS_HAS_XML_SUPPORT - case PNK_DBLCOLON: - JS_ASSERT(pn->getOp() != JSOP_XMLNAME); - if (pn->isArity(PN_NAME)) { - if (!EmitTree(cx, bce, pn->expr())) - return false; - if (!EmitAtomOp(cx, pn, pn->getOp(), bce)) - return false; - break; - } - - /* - * Binary :: has a right operand that brackets arbitrary code, - * possibly including a let (a = b) ... expression. We must clear - * emittingForInit to avoid mis-compiling such beasts. - */ - bool oldEmittingForInit = bce->emittingForInit; - bce->emittingForInit = false; -#endif - /* Binary operators that evaluate both operands unconditionally. */ if (!EmitTree(cx, bce, pn->pn_left)) return false; if (!EmitTree(cx, bce, pn->pn_right)) return false; -#if JS_HAS_XML_SUPPORT - bce->emittingForInit = oldEmittingForInit; -#endif if (Emit1(cx, bce, pn->getOp()) < 0) return false; } break; -#if JS_HAS_XML_SUPPORT - case PNK_FUNCTIONNS: - ok = (Emit1(cx, bce, JSOP_GETFUNNS) >= 0); - break; - - case PNK_XMLUNARY: - if (pn->getOp() == JSOP_XMLNAME) { - if (!EmitXMLName(cx, pn, JSOP_XMLNAME, bce)) - return false; - } else { - JSOp op = pn->getOp(); - JS_ASSERT(op == JSOP_BINDXMLNAME || op == JSOP_SETXMLNAME); - bool oldEmittingForInit = bce->emittingForInit; - bce->emittingForInit = false; - if (!EmitTree(cx, bce, pn->pn_kid)) - return false; - bce->emittingForInit = oldEmittingForInit; - if (Emit1(cx, bce, op) < 0) - return false; - } - break; -#endif - case PNK_THROW: -#if JS_HAS_XML_SUPPORT - case PNK_AT: - case PNK_DEFXMLNS: - JS_ASSERT(pn->isArity(PN_UNARY)); - /* FALL THROUGH */ -#endif case PNK_TYPEOF: case PNK_VOID: case PNK_NOT: case PNK_BITNOT: case PNK_POS: case PNK_NEG: ok = EmitUnary(cx, bce, pn); break; @@ -6372,55 +6145,25 @@ frontend::EmitTree(JSContext *cx, Byteco case PNK_POSTDECREMENT: ok = EmitIncOrDec(cx, bce, pn); break; case PNK_DELETE: ok = EmitDelete(cx, bce, pn); break; -#if JS_HAS_XML_SUPPORT - case PNK_FILTER: - { - JS_ASSERT(!bce->sc->strict); - - if (!EmitTree(cx, bce, pn->pn_left)) - return false; - ptrdiff_t jmp = EmitJump(cx, bce, JSOP_FILTER, 0); - if (jmp < 0) - return false; - top = EmitLoopHead(cx, bce, pn->pn_right); - if (top < 0) - return false; - if (!EmitTree(cx, bce, pn->pn_right)) - return false; - SetJumpOffsetAt(bce, jmp); - if (!EmitLoopEntry(cx, bce, NULL)) - return false; - if (EmitJump(cx, bce, JSOP_ENDFILTER, top - bce->offset()) < 0) - return false; - break; - } -#endif - case PNK_DOT: /* * Pop a stack operand, convert it to object, get a property named by * this bytecode's immediate-indexed atom operand, and push its value * (not a reference to it). */ ok = EmitPropOp(cx, pn, pn->getOp(), bce, false); break; -#if JS_HAS_XML_SUPPORT - case PNK_DBLDOT: - JS_ASSERT(!bce->sc->strict); - /* FALL THROUGH */ -#endif - case PNK_ELEM: /* * Pop two operands, convert the left one to object and the right one * to property name (atom or tagged int), get the named property, and * push its value. Set the "obj" register to the result of ToObject * on the left operand. */ ok = EmitElemOp(cx, pn, pn->getOp(), bce); @@ -6475,133 +6218,42 @@ frontend::EmitTree(JSContext *cx, Byteco ok = EmitObject(cx, bce, pn); break; case PNK_NAME: if (!EmitNameOp(cx, bce, pn, false)) return false; break; -#if JS_HAS_XML_SUPPORT - case PNK_XMLATTR: - case PNK_XMLSPACE: - case PNK_XMLTEXT: - case PNK_XMLCDATA: - case PNK_XMLCOMMENT: - JS_ASSERT(!bce->sc->strict); - /* FALL THROUGH */ -#endif case PNK_STRING: ok = EmitAtomOp(cx, pn, pn->getOp(), bce); break; case PNK_NUMBER: ok = EmitNumberOp(cx, pn->pn_dval, bce); break; case PNK_REGEXP: JS_ASSERT(pn->isOp(JSOP_REGEXP)); ok = EmitRegExp(cx, bce->regexpList.add(pn->pn_objbox), bce); break; -#if JS_HAS_XML_SUPPORT - case PNK_ANYNAME: -#endif case PNK_TRUE: case PNK_FALSE: case PNK_THIS: case PNK_NULL: if (Emit1(cx, bce, pn->getOp()) < 0) return false; break; case PNK_DEBUGGER: if (Emit1(cx, bce, JSOP_DEBUGGER) < 0) return false; break; -#if JS_HAS_XML_SUPPORT - case PNK_XMLELEM: - case PNK_XMLLIST: - JS_ASSERT(!bce->sc->strict); - JS_ASSERT(pn->isKind(PNK_XMLLIST) || pn->pn_count != 0); - - switch (pn->pn_head ? pn->pn_head->getKind() : PNK_XMLLIST) { - case PNK_XMLETAGO: - JS_ASSERT(0); - /* FALL THROUGH */ - case PNK_XMLPTAGC: - case PNK_XMLSTAGO: - break; - default: - if (Emit1(cx, bce, JSOP_STARTXML) < 0) - return false; - } - - for (ParseNode *pn2 = pn->pn_head; pn2; pn2 = pn2->pn_next) { - if (pn2->isKind(PNK_XMLCURLYEXPR) && Emit1(cx, bce, JSOP_STARTXMLEXPR) < 0) - return false; - if (!EmitTree(cx, bce, pn2)) - return false; - if (pn2 != pn->pn_head && Emit1(cx, bce, JSOP_ADD) < 0) - return false; - } - - if (pn->pn_xflags & PNX_XMLROOT) { - if (pn->pn_count == 0) { - JS_ASSERT(pn->isKind(PNK_XMLLIST)); - jsatomid index; - if (!bce->makeAtomIndex(cx->names().empty, &index)) - return false; - if (!EmitIndex32(cx, JSOP_STRING, index, bce)) - return false; - } - if (Emit1(cx, bce, pn->getOp()) < 0) - return false; - } -#ifdef DEBUG - else - JS_ASSERT(pn->pn_count != 0); -#endif - break; - - case PNK_XMLPTAGC: - case PNK_XMLSTAGO: - case PNK_XMLETAGO: - if (!EmitXMLTag(cx, bce, pn)) - return false; - break; - - case PNK_XMLNAME: - JS_ASSERT(!bce->sc->strict); - - if (pn->isArity(PN_LIST)) { - JS_ASSERT(pn->pn_count != 0); - for (ParseNode *pn2 = pn->pn_head; pn2; pn2 = pn2->pn_next) { - if (pn2->isKind(PNK_XMLCURLYEXPR) && Emit1(cx, bce, JSOP_STARTXMLEXPR) < 0) - return false; - if (!EmitTree(cx, bce, pn2)) - return false; - if (pn2 != pn->pn_head && Emit1(cx, bce, JSOP_ADD) < 0) - return false; - } - } else { - JS_ASSERT(pn->isArity(PN_NULLARY)); - ok = pn->isOp(JSOP_OBJECT) - ? EmitObjectOp(cx, pn->pn_objbox, pn->getOp(), bce) - : EmitAtomOp(cx, pn, pn->getOp(), bce); - } - break; - - case PNK_XMLPI: - if (!EmitXMLProcessingInstruction(cx, bce, pn->as<XMLProcessingInstruction>())) - return false; - break; -#endif /* JS_HAS_XML_SUPPORT */ - case PNK_NOP: JS_ASSERT(pn->getArity() == PN_NULLARY); break; default: JS_ASSERT(0); }
--- a/js/src/frontend/FoldConstants.cpp +++ b/js/src/frontend/FoldConstants.cpp @@ -3,19 +3,16 @@ * * 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 "mozilla/FloatingPoint.h" #include "jslibmath.h" -#if JS_HAS_XML_SUPPORT -#include "jsxml.h" -#endif #include "frontend/FoldConstants.h" #include "frontend/ParseNode.h" #include "frontend/Parser.h" #include "vm/NumericConversions.h" #include "jsatominlines.h" @@ -197,181 +194,16 @@ FoldBinaryNumeric(JSContext *cx, JSOp op // list node. void ReplaceNode(ParseNode **pnp, ParseNode *pn) { pn->pn_next = (*pnp)->pn_next; *pnp = pn; } -#if JS_HAS_XML_SUPPORT - -static bool -FoldXMLConstants(JSContext *cx, ParseNode **pnp, Parser *parser) -{ - ParseNode *pn = *pnp; - JS_ASSERT(pn->isArity(PN_LIST)); - ParseNodeKind kind = pn->getKind(); - ParseNode **listp = &pn->pn_head; - ParseNode *pn1 = *listp; - RootedString accum(cx); - RootedString str(cx); - if ((pn->pn_xflags & PNX_CANTFOLD) == 0) { - if (kind == PNK_XMLETAGO) - accum = cx->names().etago; - else if (kind == PNK_XMLSTAGO || kind == PNK_XMLPTAGC) - accum = cx->names().stago; - } - - /* - * GC Rooting here is tricky: for most of the loop, |accum| is safe via - * the newborn string root. However, when |pn2->getKind()| is PNK_XMLCDATA, - * PNK_XMLCOMMENT, or PNK_XMLPI it is knocked out of the newborn root. - * Therefore, we have to add additonal protection from GC nesting under - * ConcatString. - */ - ParseNode *pn2; - uint32_t i, j; - for (pn2 = pn1, i = j = 0; pn2; pn2 = pn2->pn_next, i++) { - /* The parser already rejected end-tags with attributes. */ - JS_ASSERT(kind != PNK_XMLETAGO || i == 0); - switch (pn2->getKind()) { - case PNK_XMLATTR: - if (!accum) - goto cantfold; - /* FALL THROUGH */ - case PNK_XMLNAME: - case PNK_XMLSPACE: - case PNK_XMLTEXT: - case PNK_STRING: - if (pn2->isArity(PN_LIST)) - goto cantfold; - str = pn2->pn_atom; - break; - - case PNK_XMLCDATA: - str = js_MakeXMLCDATAString(cx, pn2->pn_atom); - if (!str) - return false; - break; - - case PNK_XMLCOMMENT: - str = js_MakeXMLCommentString(cx, pn2->pn_atom); - if (!str) - return false; - break; - - case PNK_XMLPI: { - XMLProcessingInstruction &pi = pn2->as<XMLProcessingInstruction>(); - str = js_MakeXMLPIString(cx, pi.target(), pi.data()); - if (!str) - return false; - break; - } - - cantfold: - default: - JS_ASSERT(*listp == pn1); - if ((kind == PNK_XMLSTAGO || kind == PNK_XMLPTAGC) && - (i & 1) ^ (j & 1)) { -#ifdef DEBUG_brendanXXX - printf("1: %d, %d => ", i, j); - if (accum) - FileEscapedString(stdout, accum, 0); - else - fputs("NULL", stdout); - fputc('\n', stdout); -#endif - } else if (accum && pn1 != pn2) { - while (pn1->pn_next != pn2) { - pn1 = parser->freeTree(pn1); - --pn->pn_count; - } - pn1->setKind(PNK_XMLTEXT); - pn1->setOp(JSOP_STRING); - pn1->setArity(PN_NULLARY); - pn1->pn_atom = AtomizeString<CanGC>(cx, accum); - if (!pn1->pn_atom) - return false; - JS_ASSERT(listp != &pn1->pn_next); - *listp = pn1; - } - listp = &pn2->pn_next; - pn1 = *listp; - accum = NULL; - continue; - } - - if (accum) { - { - str = ((kind == PNK_XMLSTAGO || kind == PNK_XMLPTAGC) && i != 0) - ? js_AddAttributePart(cx, i & 1, accum, str) - : ConcatStrings<CanGC>(cx, accum, str); - } - if (!str) - return false; -#ifdef DEBUG_brendanXXX - printf("2: %d, %d => ", i, j); - FileEscapedString(stdout, str, 0); - printf(" (%u)\n", str->length()); -#endif - ++j; - } - accum = str; - } - - if (accum) { - str = NULL; - if ((pn->pn_xflags & PNX_CANTFOLD) == 0) { - if (kind == PNK_XMLPTAGC) - str = cx->names().ptagc; - else if (kind == PNK_XMLSTAGO || kind == PNK_XMLETAGO) - str = cx->names().tagc; - } - if (str) { - accum = ConcatStrings<CanGC>(cx, accum, str); - if (!accum) - return false; - } - - JS_ASSERT(*listp == pn1); - while (pn1->pn_next) { - pn1 = parser->freeTree(pn1); - --pn->pn_count; - } - pn1->setKind(PNK_XMLTEXT); - pn1->setOp(JSOP_STRING); - pn1->setArity(PN_NULLARY); - pn1->pn_atom = AtomizeString<CanGC>(cx, accum); - if (!pn1->pn_atom) - return false; - JS_ASSERT(listp != &pn1->pn_next); - *listp = pn1; - } - - if (pn1 && pn->pn_count == 1) { - /* - * Only one node under pn, and it has been folded: move pn1 onto pn - * unless pn is an XML root (in which case we need it to tell the code - * generator to emit a JSOP_TOXML or JSOP_TOXMLLIST op). If pn is an - * XML root *and* it's a point-tag, rewrite it to PNK_XMLELEM to avoid - * extra "<" and "/>" bracketing at runtime. - */ - if (!(pn->pn_xflags & PNX_XMLROOT)) { - ReplaceNode(pnp, pn1); - } else if (kind == PNK_XMLPTAGC) { - pn->setKind(PNK_XMLELEM); - pn->setOp(JSOP_TOXML); - } - } - return true; -} - -#endif /* JS_HAS_XML_SUPPORT */ - enum Truthiness { Truthy, Falsy, Unknown }; static Truthiness Boolish(ParseNode *pn) { switch (pn->getOp()) { case JSOP_DOUBLE: return (pn->pn_dval != 0 && !MOZ_DOUBLE_IS_NaN(pn->pn_dval)) ? Truthy : Falsy; @@ -859,51 +691,16 @@ frontend::FoldConstants(JSContext *cx, P } else { pn->setKind(PNK_TRUE); pn->setOp(JSOP_TRUE); } } } break; -#if JS_HAS_XML_SUPPORT - case PNK_XMLELEM: - case PNK_XMLLIST: - case PNK_XMLPTAGC: - case PNK_XMLSTAGO: - case PNK_XMLETAGO: - case PNK_XMLNAME: - if (pn->isArity(PN_LIST)) { - JS_ASSERT(pn->isKind(PNK_XMLLIST) || pn->pn_count != 0); - if (!FoldXMLConstants(cx, pnp, parser)) - return false; - pn = *pnp; - } - break; - - case PNK_AT: - if (pn1->isKind(PNK_XMLNAME)) { - Value v = StringValue(pn1->pn_atom); - if (!js_ToAttributeName(cx, &v)) - return false; - JS_ASSERT(v.isObject()); - - ObjectBox *xmlbox = parser->newObjectBox(&v.toObject()); - if (!xmlbox) - return false; - - pn->setKind(PNK_XMLNAME); - pn->setOp(JSOP_OBJECT); - pn->setArity(PN_NULLARY); - pn->pn_objbox = xmlbox; - parser->freeTree(pn1); - } - break; -#endif /* JS_HAS_XML_SUPPORT */ - default:; } if (inCond) { Truthiness t = Boolish(pn); if (t != Unknown) { /* * We can turn function nodes into constant nodes here, but mutating function
--- a/js/src/frontend/ParseNode.cpp +++ b/js/src/frontend/ParseNode.cpp @@ -1,14 +1,15 @@ /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- * vim: set ts=8 sw=4 et tw=99: * * 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 "builtin/Module.h" #include "frontend/ParseNode.h" #include "frontend/Parser.h" #include "jsscriptinlines.h" #include "frontend/ParseMaps-inl.h" #include "frontend/ParseNode-inl.h" @@ -171,20 +172,16 @@ PushNodeChildren(ParseNode *pn, NodeStac if (pn->pn_left != pn->pn_right) stack->pushUnlessNull(pn->pn_left); stack->pushUnlessNull(pn->pn_right); break; case PN_UNARY: stack->pushUnlessNull(pn->pn_kid); break; case PN_NULLARY: - /* - * E4X function namespace nodes are PN_NULLARY, but can appear on use - * lists. - */ return !pn->isUsed() && !pn->isDefn(); default: ; } return true; } @@ -449,17 +446,16 @@ CloneParseTree(ParseNode *opn, Parser *p if (opn->isDefn()) { opn->setDefn(false); LinkUseToDef(opn, (Definition *) pn); } } break; case PN_NULLARY: - // Even PN_NULLARY may have data (xmlpi for E4X -- what a botch). pn->pn_u = opn->pn_u; break; #undef NULLCHECK } return pn; }
--- a/js/src/frontend/ParseNode.h +++ b/js/src/frontend/ParseNode.h @@ -80,17 +80,16 @@ class UpvarCookie F(PREINCREMENT) \ F(POSTINCREMENT) \ F(PREDECREMENT) \ F(POSTDECREMENT) \ F(DOT) \ F(ELEM) \ F(ARRAY) \ F(STATEMENTLIST) \ - F(XMLCURLYEXPR) \ F(OBJECT) \ F(CALL) \ F(NAME) \ F(NUMBER) \ F(STRING) \ F(REGEXP) \ F(TRUE) \ F(FALSE) \ @@ -116,37 +115,16 @@ class UpvarCookie F(DELETE) \ F(TRY) \ F(CATCH) \ F(CATCHLIST) \ F(FINALLY) \ F(THROW) \ F(INSTANCEOF) \ F(DEBUGGER) \ - F(DEFXMLNS) \ - F(XMLSTAGO) \ - F(XMLETAGO) \ - F(XMLPTAGC) \ - F(XMLTAGC) \ - F(XMLNAME) \ - F(XMLATTR) \ - F(XMLSPACE) \ - F(XMLTEXT) \ - F(XMLCOMMENT) \ - F(XMLCDATA) \ - F(XMLPI) \ - F(XMLUNARY) \ - F(AT) \ - F(FUNCTIONNS) \ - F(DBLCOLON) \ - F(ANYNAME) \ - F(DBLDOT) \ - F(FILTER) \ - F(XMLELEM) \ - F(XMLLIST) \ F(YIELD) \ F(GENEXP) \ F(ARRAYCOMP) \ F(ARRAYPUSH) \ F(LEXICALSCOPE) \ F(LET) \ F(SEQ) \ F(FORIN) \ @@ -361,18 +339,18 @@ enum ParseNodeKind { * PNK_PREINCREMENT, unary pn_kid: MEMBER expr * PNK_POSTINCREMENT, * PNK_PREDECREMENT, * PNK_POSTDECREMENT * PNK_NEW list pn_head: list of ctor, arg1, arg2, ... argN * pn_count: 1 + N (where N is number of args) * ctor is a MEMBER expr * PNK_DELETE unary pn_kid: MEMBER expr - * PNK_DOT, name pn_expr: MEMBER expr to left of . - * PNK_DBLDOT pn_atom: name to right of . + * PNK_DOT name pn_expr: MEMBER expr to left of . + * pn_atom: name to right of . * PNK_ELEM binary pn_left: MEMBER expr to left of [ * pn_right: expr between [ and ] * PNK_CALL list pn_head: list of call, arg1, arg2, ... argN * pn_count: 1 + N (where N is number of args) * call is a MEMBER expr naming a callable object * PNK_GENEXP list Exactly like PNK_CALL, used for the implicit call * in the desugaring of a generator-expression. * PNK_ARRAY list pn_head: list of pn_count array element exprs @@ -395,110 +373,42 @@ enum ParseNodeKind { * PNK_NAME name If pn_used, PNK_NAME uses the lexdef member instead * of the expr member it overlays * PNK_NUMBER dval pn_dval: double value of numeric literal * PNK_TRUE, nullary pn_op: JSOp bytecode * PNK_FALSE, * PNK_NULL, * PNK_THIS * - * <E4X node descriptions> - * PNK_XMLUNARY unary pn_kid: PNK_AT, PNK_ANYNAME, or PNK_DBLCOLON node - * pn_op: JSOP_XMLNAME, JSOP_BINDXMLNAME, or - * JSOP_SETXMLNAME - * PNK_DEFXMLNS name pn_kid: namespace expr - * PNK_FILTER binary pn_left: container expr, pn_right: filter expr - * PNK_DBLDOT binary pn_left: container expr, pn_right: selector expr - * PNK_ANYNAME nullary pn_op: JSOP_ANYNAME - * pn_atom: cx->runtime->atomState.starAtom - * PNK_AT unary pn_op: JSOP_TOATTRNAME; pn_kid attribute id/expr - * PNK_FUNCTIONNS nullary special E4X "function::" namespace - * PNK_DBLCOLON binary pn_op: JSOP_QNAME - * pn_left: PNK_ANYNAME or PNK_NAME node - * pn_right: PNK_STRING "*" node, or expr within [] - * name pn_op: JSOP_QNAMECONST - * pn_expr: PNK_ANYNAME or PNK_NAME left operand - * pn_atom: name on right of :: - * PNK_XMLELEM list XML element node - * pn_head: start tag, content1, ... contentN, end tag - * pn_count: 2 + N where N is number of content nodes - * N may be > x.length() if {expr} embedded - * After constant folding, these contents may be - * concatenated into string nodes. - * PNK_XMLLIST list XML list node - * pn_head: content1, ... contentN - * PNK_XMLSTAGO, list XML start, end, and point tag contents - * PNK_XMLETAGO, pn_head: tag name or {expr}, ... XML attrs ... - * PNK_XMLPTAGC - * PNK_XMLNAME nullary pn_atom: XML name, with no {expr} embedded - * PNK_XMLNAME list pn_head: tag name or {expr}, ... name or {expr} - * PNK_XMLATTR, nullary pn_atom: attribute value string; pn_op: JSOP_STRING - * PNK_XMLCDATA, - * PNK_XMLCOMMENT - * PNK_XMLPI nullary pn_pitarget: XML processing instruction target - * pn_pidata: XML PI data, or null if no data - * PNK_XMLTEXT nullary pn_atom: marked-up text, or null if empty string - * PNK_XMLCURLYEXPR unary {expr} in XML tag or content; pn_kid is expr - * - * So an XML tag with no {expr} and three attributes is a list with the form: - * - * (tagname attrname1 attrvalue1 attrname2 attrvalue2 attrname2 attrvalue3) - * - * An XML tag with embedded expressions like so: - * - * <name1{expr1} name2{expr2}name3={expr3}> - * - * would have the form: - * - * ((name1 {expr1}) (name2 {expr2} name3) {expr3}) - * - * where () bracket a list with elements separated by spaces, and {expr} is a - * PNK_XMLCURLYEXPR unary node with expr as its kid. - * - * Thus, the attribute name/value pairs occupy successive odd and even list - * locations, where pn_head is the PNK_XMLNAME node at list location 0. The - * parser builds the same sort of structures for elements: - * - * <a x={x}>Hi there!<b y={y}>How are you?</b><answer>{x + y}</answer></a> - * - * translates to: - * - * ((a x {x}) 'Hi there!' ((b y {y}) 'How are you?') ((answer) {x + y})) - * - * <Non-E4X node descriptions, continued> - * - * Label Variant Members - * ----- ------- ------- - * PNK_LEXICALSCOPE name pn_op: JSOP_LEAVEBLOCK or JSOP_LEAVEBLOCKEXPR - * pn_objbox: block object in ObjectBox holder - * pn_expr: block body - * PNK_ARRAYCOMP list pn_count: 1 - * pn_head: list of 1 element, which is block - * enclosing for loop(s) and optionally - * if-guarded PNK_ARRAYPUSH - * PNK_ARRAYPUSH unary pn_op: JSOP_ARRAYCOMP - * pn_kid: array comprehension expression - * PNK_NOP nullary + * PNK_LEXICALSCOPE name pn_op: JSOP_LEAVEBLOCK or JSOP_LEAVEBLOCKEXPR + * pn_objbox: block object in ObjectBox holder + * pn_expr: block body + * PNK_ARRAYCOMP list pn_count: 1 + * pn_head: list of 1 element, which is block + * enclosing for loop(s) and optionally + * if-guarded PNK_ARRAYPUSH + * PNK_ARRAYPUSH unary pn_op: JSOP_ARRAYCOMP + * pn_kid: array comprehension expression + * PNK_NOP nullary */ enum ParseNodeArity { PN_NULLARY, /* 0 kids, only pn_atom/pn_dval/etc. */ PN_UNARY, /* one kid, plus a couple of scalars */ PN_BINARY, /* two kids, plus a couple of scalars */ PN_TERNARY, /* three kids */ PN_FUNC, /* function definition node */ PN_LIST, /* generic singly linked list */ PN_NAME /* name use or definition node */ }; struct Definition; class LoopControlStatement; class BreakStatement; class ContinueStatement; -class XMLProcessingInstruction; class ConditionalExpression; class PropertyAccess; struct ParseNode { private: uint32_t pn_type : 16, /* PNK_* type */ pn_op : 8, /* see JSOp enum and jsopcode.tbl */ pn_arity : 5, /* see ParseNodeArity enum */ @@ -543,36 +453,21 @@ struct ParseNode { pn_type = kind; } bool isKind(ParseNodeKind kind) const { return getKind() == kind; } ParseNodeArity getArity() const { return ParseNodeArity(pn_arity); } bool isArity(ParseNodeArity a) const { return getArity() == a; } void setArity(ParseNodeArity a) { pn_arity = a; } - bool isXMLNameOp() const { - ParseNodeKind kind = getKind(); - return kind == PNK_ANYNAME || kind == PNK_AT || kind == PNK_DBLCOLON; - } bool isAssignment() const { ParseNodeKind kind = getKind(); return PNK_ASSIGNMENT_START <= kind && kind <= PNK_ASSIGNMENT_LAST; } - bool isXMLPropertyIdentifier() const { - ParseNodeKind kind = getKind(); - return kind == PNK_ANYNAME || kind == PNK_AT || kind == PNK_DBLCOLON; - } - - bool isXMLItem() const { - ParseNodeKind kind = getKind(); - return kind == PNK_XMLCOMMENT || kind == PNK_XMLCDATA || kind == PNK_XMLPI || - kind == PNK_XMLELEM || kind == PNK_XMLLIST; - } - /* Boolean attributes. */ bool isInParens() const { return pn_parens; } void setInParens(bool enabled) { pn_parens = enabled; } bool isUsed() const { return pn_used; } void setUsed(bool enabled) { pn_used = enabled; } bool isDefn() const { return pn_defn; } void setDefn(bool enabled) { pn_defn = enabled; } @@ -626,21 +521,16 @@ struct ParseNode { struct { double value; /* aligned numeric literal value */ DecimalPoint decimalPoint; /* Whether the number has a decimal point */ } number; class { friend class LoopControlStatement; PropertyName *label; /* target of break/continue statement */ } loopControl; - class { /* E4X <?target data?> XML PI */ - friend class XMLProcessingInstruction; - PropertyName *target; /* non-empty */ - JSAtom *data; /* may be empty, never null */ - } xmlpi; } pn_u; #define pn_funbox pn_u.name.funbox #define pn_body pn_u.name.expr #define pn_cookie pn_u.name.cookie #define pn_dflags pn_u.name.dflags #define pn_blockid pn_u.name.blockid #define pn_index pn_u.name.blockid /* reuse as object table index */ @@ -742,29 +632,28 @@ struct ParseNode { /* PN_LIST pn_xflags bits. */ #define PNX_STRCAT 0x01 /* PNK_ADD list has string term */ #define PNX_CANTFOLD 0x02 /* PNK_ADD list has unfoldable term */ #define PNX_POPVAR 0x04 /* PNK_VAR or PNK_CONST last result needs popping */ #define PNX_FORINVAR 0x08 /* PNK_VAR is left kid of PNK_FORIN node which is left kid of PNK_FOR */ #define PNX_ENDCOMMA 0x10 /* array literal has comma at end */ -#define PNX_XMLROOT 0x20 /* top-most node in XML literal tree */ -#define PNX_GROUPINIT 0x40 /* var [a, b] = [c, d]; unit list */ -#define PNX_NEEDBRACES 0x80 /* braces necessary due to closure */ -#define PNX_FUNCDEFS 0x100 /* contains top-level function statements */ -#define PNX_SETCALL 0x100 /* call expression in lvalue context */ -#define PNX_DESTRUCT 0x200 /* destructuring special cases: +#define PNX_GROUPINIT 0x20 /* var [a, b] = [c, d]; unit list */ +#define PNX_NEEDBRACES 0x40 /* braces necessary due to closure */ +#define PNX_FUNCDEFS 0x80 /* contains top-level function statements */ +#define PNX_SETCALL 0x80 /* call expression in lvalue context */ +#define PNX_DESTRUCT 0x100 /* destructuring special cases: 1. shorthand syntax used, at present object destructuring ({x,y}) only; 2. code evaluating destructuring arguments occurs before function body */ -#define PNX_HOLEY 0x400 /* array initialiser has holes */ -#define PNX_NONCONST 0x800 /* initialiser has non-constants */ +#define PNX_HOLEY 0x200 /* array initialiser has holes */ +#define PNX_NONCONST 0x400 /* initialiser has non-constants */ unsigned frameLevel() const { JS_ASSERT(pn_arity == PN_FUNC || pn_arity == PN_NAME); return pn_cookie.level(); } unsigned frameSlot() const { JS_ASSERT(pn_arity == PN_FUNC || pn_arity == PN_NAME); @@ -1133,43 +1022,16 @@ class ContinueStatement : public LoopCon class DebuggerStatement : public ParseNode { public: DebuggerStatement(const TokenPos &pos) : ParseNode(PNK_DEBUGGER, JSOP_NOP, PN_NULLARY, pos) { } }; -#if JS_HAS_XML_SUPPORT -class XMLProcessingInstruction : public ParseNode { - public: - XMLProcessingInstruction(PropertyName *target, JSAtom *data, const TokenPos &pos) - : ParseNode(PNK_XMLPI, JSOP_NOP, PN_NULLARY, pos) - { - pn_u.xmlpi.target = target; - pn_u.xmlpi.data = data; - } - - static bool test(const ParseNode &node) { - bool match = node.isKind(PNK_XMLPI); - JS_ASSERT_IF(match, node.isArity(PN_NULLARY)); - JS_ASSERT_IF(match, node.isOp(JSOP_NOP)); - return match; - } - - PropertyName *target() const { - return pn_u.xmlpi.target; - } - - JSAtom *data() const { - return pn_u.xmlpi.data; - } -}; -#endif - class ConditionalExpression : public ParseNode { public: ConditionalExpression(ParseNode *condition, ParseNode *thenExpr, ParseNode *elseExpr) : ParseNode(PNK_CONDITIONAL, JSOP_NOP, PN_TERNARY, TokenPos::make(condition->pn_pos.begin, elseExpr->pn_pos.end)) { JS_ASSERT(condition); JS_ASSERT(thenExpr); @@ -1211,74 +1073,16 @@ class NullLiteral : public ParseNode { class BooleanLiteral : public ParseNode { public: BooleanLiteral(bool b, const TokenPos &pos) : ParseNode(b ? PNK_TRUE : PNK_FALSE, b ? JSOP_TRUE : JSOP_FALSE, PN_NULLARY, pos) { } }; -class XMLDoubleColonProperty : public ParseNode { - public: - XMLDoubleColonProperty(ParseNode *lhs, ParseNode *rhs, - const TokenPtr &begin, const TokenPtr &end) - : ParseNode(PNK_ELEM, JSOP_GETELEM, PN_BINARY, TokenPos::make(begin, end)) - { - JS_ASSERT(rhs->isKind(PNK_DBLCOLON)); - pn_u.binary.left = lhs; - pn_u.binary.right = rhs; - } - - ParseNode &left() const { - return *pn_u.binary.left; - } - - ParseNode &right() const { - return *pn_u.binary.right; - } -}; - -class XMLFilterExpression : public ParseNode { - public: - XMLFilterExpression(ParseNode *lhs, ParseNode *filterExpr, - const TokenPtr &begin, const TokenPtr &end) - : ParseNode(PNK_FILTER, JSOP_FILTER, PN_BINARY, TokenPos::make(begin, end)) - { - pn_u.binary.left = lhs; - pn_u.binary.right = filterExpr; - } - - ParseNode &left() const { - return *pn_u.binary.left; - } - - ParseNode &filter() const { - return *pn_u.binary.right; - } -}; - -class XMLProperty : public ParseNode { - public: - XMLProperty(ParseNode *lhs, ParseNode *propertyId, - const TokenPtr &begin, const TokenPtr &end) - : ParseNode(PNK_ELEM, JSOP_GETELEM, PN_BINARY, TokenPos::make(begin, end)) - { - pn_u.binary.left = lhs; - pn_u.binary.right = propertyId; - } - - ParseNode &left() const { - return *pn_u.binary.left; - } - - ParseNode &right() const { - return *pn_u.binary.right; - } -}; - class PropertyAccess : public ParseNode { public: PropertyAccess(ParseNode *lhs, PropertyName *name, const TokenPtr &begin, const TokenPtr &end) : ParseNode(PNK_DOT, JSOP_GETPROP, PN_NAME, TokenPos::make(begin, end)) { JS_ASSERT(lhs != NULL); JS_ASSERT(name != NULL);
--- a/js/src/frontend/Parser.cpp +++ b/js/src/frontend/Parser.cpp @@ -42,20 +42,16 @@ #include "frontend/FoldConstants.h" #include "frontend/ParseMaps.h" #include "frontend/Parser.h" #include "frontend/TokenStream.h" #include "gc/Marking.h" #include "vm/Shape.h" -#if JS_HAS_XML_SUPPORT -#include "jsxml.h" -#endif - #include "jsatominlines.h" #include "jsscriptinlines.h" #include "frontend/ParseMaps-inl.h" #include "frontend/ParseNode-inl.h" #include "frontend/Parser-inl.h" #include "frontend/SharedContext-inl.h" @@ -1668,20 +1664,18 @@ Parser::functionArgsAndBody(ParseNode *p /* Initialize early for possible flags mutation via destructuringExpr. */ ParseContext funpc(this, funbox, outerpc->staticLevel + 1, outerpc->blockidGen); if (!funpc.init()) return false; /* Now parse formal argument list and compute fun->nargs. */ ParseNode *prelude = NULL; bool hasRest; - tokenStream.incBanXML(); if (!functionArguments(&prelude, pn, hasRest)) return false; - tokenStream.decBanXML(); fun->setArgCount(funpc.numArgs()); if (funbox->ndefaults) fun->setHasDefaults(); if (hasRest) fun->setHasRest(); if (type == Getter && fun->nargs > 0) { @@ -2355,23 +2349,16 @@ BindDestructuringLHS(JSContext *cx, Pars pn->setOp(JSOP_SETNAME); break; case PNK_CALL: if (!MakeSetCall(cx, pn, parser, JSMSG_BAD_LEFTSIDE_OF_ASS)) return false; break; -#if JS_HAS_XML_SUPPORT - case PNK_XMLUNARY: - JS_ASSERT(pn->isOp(JSOP_XMLNAME)); - pn->setOp(JSOP_BINDXMLNAME); - break; -#endif - default: parser->reportError(pn, JSMSG_BAD_LEFTSIDE_OF_ASS); return false; } return true; } @@ -2517,17 +2504,17 @@ CheckDestructuring(JSContext *cx, BindDa } ParseNode * Parser::destructuringExpr(BindData *data, TokenKind tt) { JS_ASSERT(tokenStream.isCurrentTokenType(tt)); pc->inDeclDestructuring = true; - ParseNode *pn = primaryExpr(tt, false); + ParseNode *pn = primaryExpr(tt); pc->inDeclDestructuring = false; if (!pn) return NULL; if (!CheckDestructuring(context, data, pn, this)) return NULL; return pn; } @@ -2960,17 +2947,16 @@ IsValidForStatementLHS(ParseNode *pn1, J #endif return true; } switch (pn1->getKind()) { case PNK_NAME: case PNK_DOT: case PNK_CALL: - case PNK_XMLUNARY: case PNK_ELEM: return true; #if JS_HAS_DESTRUCTURING case PNK_ARRAY: case PNK_OBJECT: // In JS 1.7 only, for ([K, V] in EXPR) has a special meaning. // Hence all other destructuring left-hand sides are banned there. @@ -3724,26 +3710,17 @@ ParseNode * Parser::statement() { ParseNode *pn; JS_CHECK_RECURSION(context, return NULL); switch (tokenStream.getToken(TSF_OPERAND)) { case TOK_FUNCTION: - { -#if JS_HAS_XML_SUPPORT - if (allowsXML()) { - TokenKind tt = tokenStream.peekToken(TSF_KEYWORD_IS_NAME); - if (tt == TOK_DBLCOLON) - return expressionStatement(); - } -#endif return functionStmt(); - } case TOK_IF: { /* An IF node has three kids: condition, then, and optional else. */ pn = TernaryNode::create(PNK_IF, this); if (!pn) return NULL; ParseNode *pn1 = condition(); @@ -4011,49 +3988,16 @@ Parser::statement() case TOK_DEBUGGER: pn = new_<DebuggerStatement>(tokenStream.currentToken().pos); if (!pn) return NULL; pc->sc->setBindingsAccessedDynamically(); break; -#if JS_HAS_XML_SUPPORT - case TOK_DEFAULT: - { - if (!allowsXML()) - return expressionStatement(); - - pn = UnaryNode::create(PNK_DEFXMLNS, this); - if (!pn) - return NULL; - if (!tokenStream.matchToken(TOK_NAME) || - tokenStream.currentToken().name() != context->names().xml || - !tokenStream.matchToken(TOK_NAME) || - tokenStream.currentToken().name() != context->names().namespace_ || - !tokenStream.matchToken(TOK_ASSIGN)) - { - reportError(NULL, JSMSG_BAD_DEFAULT_XML_NAMESPACE); - return NULL; - } - - JS_ASSERT(tokenStream.currentToken().t_op == JSOP_NOP); - - /* Is this an E4X dagger I see before me? */ - pc->sc->setBindingsAccessedDynamically(); - ParseNode *pn2 = expr(); - if (!pn2) - return NULL; - pn->setOp(JSOP_DEFXMLNS); - pn->pn_pos.end = pn2->pn_pos.end; - pn->pn_kid = pn2; - break; - } -#endif - case TOK_ERROR: return NULL; default: return expressionStatement(); } /* Check termination of this primitive statement. */ @@ -4096,17 +4040,17 @@ Parser::variables(ParseNodeKind kind, St data.initVarOrConst(pn->getOp()); ParseNode *pn2; do { TokenKind tt = tokenStream.getToken(); #if JS_HAS_DESTRUCTURING if (tt == TOK_LB || tt == TOK_LC) { pc->inDeclDestructuring = true; - pn2 = primaryExpr(tt, false); + pn2 = primaryExpr(tt); pc->inDeclDestructuring = false; if (!pn2) return NULL; if (!CheckDestructuring(context, &data, pn2, this)) return NULL; bool ignored; if (pc->parsingForInit && matchInOrOf(&ignored)) { @@ -4469,22 +4413,16 @@ Parser::setAssignmentLhsOps(ParseNode *p if (!CheckDestructuring(context, NULL, pn, this)) return false; break; #endif case PNK_CALL: if (!MakeSetCall(context, pn, this, JSMSG_BAD_LEFTSIDE_OF_ASS)) return false; break; -#if JS_HAS_XML_SUPPORT - case PNK_XMLUNARY: - JS_ASSERT(pn->isOp(JSOP_XMLNAME)); - pn->setOp(JSOP_SETXMLNAME); - break; -#endif default: reportError(NULL, JSMSG_BAD_LEFTSIDE_OF_ASS); return false; } return true; } ParseNode * @@ -4536,19 +4474,16 @@ static bool SetLvalKid(JSContext *cx, Parser *parser, ParseNode *pn, ParseNode *kid, const char *name) { if (!kid->isKind(PNK_NAME) && !kid->isKind(PNK_DOT) && (!kid->isKind(PNK_CALL) || (!kid->isOp(JSOP_CALL) && !kid->isOp(JSOP_EVAL) && !kid->isOp(JSOP_FUNCALL) && !kid->isOp(JSOP_FUNAPPLY))) && -#if JS_HAS_XML_SUPPORT - !kid->isKind(PNK_XMLUNARY) && -#endif !kid->isKind(PNK_ELEM)) { parser->reportError(NULL, JSMSG_BAD_OPERAND, name); return false; } if (!CheckStrictAssignment(cx, parser, kid)) return false; pn->pn_kid = kid; @@ -4578,22 +4513,16 @@ SetIncOpKid(JSContext *cx, Parser *parse ? (preorder ? JSOP_INCPROP : JSOP_PROPINC) : (preorder ? JSOP_DECPROP : JSOP_PROPDEC); break; case PNK_CALL: if (!MakeSetCall(cx, kid, parser, JSMSG_BAD_INCOP_OPERAND)) return false; /* FALL THROUGH */ -#if JS_HAS_XML_SUPPORT - case PNK_XMLUNARY: - if (kid->isOp(JSOP_XMLNAME)) - kid->setOp(JSOP_SETXMLNAME); - /* FALL THROUGH */ -#endif case PNK_ELEM: op = (tt == TOK_INC) ? (preorder ? JSOP_INCELEM : JSOP_ELEMINC) : (preorder ? JSOP_DECELEM : JSOP_ELEMDEC); break; default: JS_ASSERT(0); @@ -5133,17 +5062,17 @@ Parser::comprehensionTail(ParseNode *kid RootedPropertyName name(context); tt = tokenStream.getToken(); switch (tt) { #if JS_HAS_DESTRUCTURING case TOK_LB: case TOK_LC: pc->inDeclDestructuring = true; - pn3 = primaryExpr(tt, false); + pn3 = primaryExpr(tt); pc->inDeclDestructuring = false; if (!pn3) return NULL; break; #endif case TOK_NAME: name = tokenStream.currentToken().name(); @@ -5480,131 +5409,39 @@ Parser::memberExpr(bool allowCallSyntax) return NULL; if (lhs->pn_count > ARGC_LIMIT) { JS_ReportErrorNumber(context, js_GetErrorMessage, NULL, JSMSG_TOO_MANY_CON_ARGS); return NULL; } lhs->pn_pos.end = lhs->last()->pn_pos.end; } else { - lhs = primaryExpr(tt, false); + lhs = primaryExpr(tt); if (!lhs) return NULL; - - if (lhs->isXMLNameOp()) { - lhs = new_<UnaryNode>(PNK_XMLUNARY, JSOP_XMLNAME, lhs->pn_pos, lhs); - if (!lhs) - return NULL; - } } while ((tt = tokenStream.getToken()) > TOK_EOF) { ParseNode *nextMember; if (tt == TOK_DOT) { tt = tokenStream.getToken(TSF_KEYWORD_IS_NAME); if (tt == TOK_ERROR) return NULL; if (tt == TOK_NAME) { -#if JS_HAS_XML_SUPPORT - if (allowsXML() && tokenStream.peekToken() == TOK_DBLCOLON) { - ParseNode *propertyId = propertyQualifiedIdentifier(); - if (!propertyId) - return NULL; - - nextMember = new_<XMLDoubleColonProperty>(lhs, propertyId, - lhs->pn_pos.begin, - tokenStream.currentToken().pos.end); - if (!nextMember) - return NULL; - } else -#endif - { - PropertyName *field = tokenStream.currentToken().name(); - nextMember = new_<PropertyAccess>(lhs, field, - lhs->pn_pos.begin, - tokenStream.currentToken().pos.end); - if (!nextMember) - return NULL; - } - } -#if JS_HAS_XML_SUPPORT - else if (allowsXML()) { - TokenPtr begin = lhs->pn_pos.begin; - if (tt == TOK_LP) { - /* Filters are effectively 'with', so deoptimize names. */ - pc->sc->setBindingsAccessedDynamically(); - - StmtInfoPC stmtInfo(context); - bool oldParsingWith = pc->parsingWith; - pc->parsingWith = true; - PushStatementPC(pc, &stmtInfo, STMT_WITH); - - ParseNode *filter = bracketedExpr(); - if (!filter) - return NULL; - filter->setInParens(true); - MUST_MATCH_TOKEN(TOK_RP, JSMSG_PAREN_IN_PAREN); - - pc->parsingWith = oldParsingWith; - PopStatementPC(context, pc); - - nextMember = - new_<XMLFilterExpression>(lhs, filter, - begin, tokenStream.currentToken().pos.end); - if (!nextMember) - return NULL; - } else if (tt == TOK_AT || tt == TOK_STAR) { - ParseNode *propertyId = starOrAtPropertyIdentifier(tt); - if (!propertyId) - return NULL; - nextMember = new_<XMLProperty>(lhs, propertyId, - begin, tokenStream.currentToken().pos.end); - if (!nextMember) - return NULL; - } else { - reportError(NULL, JSMSG_NAME_AFTER_DOT); + PropertyName *field = tokenStream.currentToken().name(); + nextMember = new_<PropertyAccess>(lhs, field, + lhs->pn_pos.begin, + tokenStream.currentToken().pos.end); + if (!nextMember) return NULL; - } - } -#endif - else { + } else { reportError(NULL, JSMSG_NAME_AFTER_DOT); return NULL; } - } -#if JS_HAS_XML_SUPPORT - else if (tt == TOK_DBLDOT) { - if (!allowsXML()) { - reportError(NULL, JSMSG_NAME_AFTER_DOT); - return NULL; - } - - nextMember = BinaryNode::create(PNK_DBLDOT, this); - if (!nextMember) - return NULL; - tt = tokenStream.getToken(TSF_OPERAND | TSF_KEYWORD_IS_NAME); - ParseNode *pn3 = primaryExpr(tt, true); - if (!pn3) - return NULL; - if (pn3->isKind(PNK_NAME) && !pn3->isInParens()) { - pn3->setKind(PNK_STRING); - pn3->setArity(PN_NULLARY); - pn3->setOp(JSOP_QNAMEPART); - } else if (!pn3->isXMLPropertyIdentifier()) { - reportError(NULL, JSMSG_NAME_AFTER_DOT); - return NULL; - } - nextMember->setOp(JSOP_DESCENDANTS); - nextMember->pn_left = lhs; - nextMember->pn_right = pn3; - nextMember->pn_pos.begin = lhs->pn_pos.begin; - nextMember->pn_pos.end = tokenStream.currentToken().pos.end; - } -#endif - else if (tt == TOK_LB) { + } else if (tt == TOK_LB) { ParseNode *propExpr = expr(); if (!propExpr) return NULL; MUST_MATCH_TOKEN(TOK_RB, JSMSG_BRACKET_IN_INDEX); TokenPtr begin = lhs->pn_pos.begin, end = tokenStream.currentToken().pos.end; /* @@ -5710,730 +5547,34 @@ Parser::bracketedExpr() */ bool oldParsingForInit = pc->parsingForInit; pc->parsingForInit = false; ParseNode *pn = expr(); pc->parsingForInit = oldParsingForInit; return pn; } -#if JS_HAS_XML_SUPPORT - ParseNode * -Parser::endBracketedExpr() -{ - JS_ASSERT(allowsXML()); - - ParseNode *pn = bracketedExpr(); - if (!pn) - return NULL; - - MUST_MATCH_TOKEN(TOK_RB, JSMSG_BRACKET_AFTER_ATTR_EXPR); - return pn; -} - -/* - * From the ECMA-357 grammar in 11.1.1 and 11.1.2: - * - * AttributeIdentifier: - * @ PropertySelector - * @ QualifiedIdentifier - * @ [ Expression ] - * - * PropertySelector: - * Identifier - * * - * - * QualifiedIdentifier: - * PropertySelector :: PropertySelector - * PropertySelector :: [ Expression ] - * - * We adapt AttributeIdentifier and QualifiedIdentier to be LL(1), like so: - * - * AttributeIdentifier: - * @ QualifiedIdentifier - * @ [ Expression ] - * - * PropertySelector: - * Identifier - * * - * - * QualifiedIdentifier: - * PropertySelector :: PropertySelector - * PropertySelector :: [ Expression ] - * PropertySelector - * - * As PrimaryExpression: Identifier is in ECMA-262 and we want the semantics - * for that rule to result in a name node, but ECMA-357 extends the grammar - * to include PrimaryExpression: QualifiedIdentifier, we must factor further: - * - * QualifiedIdentifier: - * PropertySelector QualifiedSuffix - * - * QualifiedSuffix: - * :: PropertySelector - * :: [ Expression ] - * /nothing/ - * - * And use this production instead of PrimaryExpression: QualifiedIdentifier: - * - * PrimaryExpression: - * Identifier QualifiedSuffix - * - * We hoist the :: match into callers of QualifiedSuffix, in order to tweak - * PropertySelector vs. Identifier pn_arity, pn_op, and other members. - */ -ParseNode * -Parser::propertySelector() -{ - JS_ASSERT(allowsXML()); - - ParseNode *selector; - if (tokenStream.isCurrentTokenType(TOK_STAR)) { - selector = NullaryNode::create(PNK_ANYNAME, this); - if (!selector) - return NULL; - selector->setOp(JSOP_ANYNAME); - selector->pn_atom = context->names().star; - } else { - JS_ASSERT(tokenStream.isCurrentTokenType(TOK_NAME)); - selector = NullaryNode::create(PNK_NAME, this); - if (!selector) - return NULL; - selector->setOp(JSOP_QNAMEPART); - selector->setArity(PN_NAME); - selector->pn_atom = tokenStream.currentToken().name(); - selector->pn_cookie.makeFree(); - } - return selector; -} - -ParseNode * -Parser::qualifiedSuffix(ParseNode *pn) -{ - JS_ASSERT(allowsXML()); - - JS_ASSERT(tokenStream.currentToken().type == TOK_DBLCOLON); - ParseNode *pn2 = NameNode::create(PNK_DBLCOLON, NULL, this, this->pc); - if (!pn2) - return NULL; - - pc->sc->setBindingsAccessedDynamically(); - - /* Left operand of :: must be evaluated if it is an identifier. */ - if (pn->isOp(JSOP_QNAMEPART)) - pn->setOp(JSOP_NAME); - - TokenKind tt = tokenStream.getToken(TSF_KEYWORD_IS_NAME); - if (tt == TOK_STAR || tt == TOK_NAME) { - /* Inline and specialize propertySelector for JSOP_QNAMECONST. */ - pn2->setOp(JSOP_QNAMECONST); - pn2->pn_pos.begin = pn->pn_pos.begin; - pn2->pn_atom = (tt == TOK_STAR) - ? context->names().star - : tokenStream.currentToken().name(); - pn2->pn_expr = pn; - pn2->pn_cookie.makeFree(); - return pn2; - } - - if (tt != TOK_LB) { - reportError(NULL, JSMSG_SYNTAX_ERROR); - return NULL; - } - ParseNode *pn3 = endBracketedExpr(); - if (!pn3) - return NULL; - - pn2->setOp(JSOP_QNAME); - pn2->setArity(PN_BINARY); - pn2->pn_pos.begin = pn->pn_pos.begin; - pn2->pn_pos.end = pn3->pn_pos.end; - pn2->pn_left = pn; - pn2->pn_right = pn3; - return pn2; -} - -ParseNode * -Parser::qualifiedIdentifier() -{ - JS_ASSERT(allowsXML()); - - ParseNode *pn = propertySelector(); - if (!pn) - return NULL; - if (tokenStream.matchToken(TOK_DBLCOLON)) { - /* Hack for bug 496316. Slowing down E4X won't make it go away, alas. */ - pc->sc->setBindingsAccessedDynamically(); - pn = qualifiedSuffix(pn); - } - return pn; -} - -ParseNode * -Parser::attributeIdentifier() -{ - JS_ASSERT(allowsXML()); - - JS_ASSERT(tokenStream.currentToken().type == TOK_AT); - ParseNode *pn = UnaryNode::create(PNK_AT, this); - if (!pn) - return NULL; - pn->setOp(JSOP_TOATTRNAME); - - ParseNode *pn2; - TokenKind tt = tokenStream.getToken(TSF_KEYWORD_IS_NAME); - if (tt == TOK_STAR || tt == TOK_NAME) { - pn2 = qualifiedIdentifier(); - } else if (tt == TOK_LB) { - pn2 = endBracketedExpr(); - } else { - reportError(NULL, JSMSG_SYNTAX_ERROR); - return NULL; - } - if (!pn2) - return NULL; - pn->pn_kid = pn2; - pn->pn_pos.end = pn2->pn_pos.end; - return pn; -} - -/* - * Make a TOK_LC unary node whose pn_kid is an expression. - */ -ParseNode * -Parser::xmlExpr(bool inTag) -{ - JS_ASSERT(allowsXML()); - - JS_ASSERT(tokenStream.currentToken().type == TOK_LC); - ParseNode *pn = UnaryNode::create(PNK_XMLCURLYEXPR, this); - if (!pn) - return NULL; - - /* - * Turn off XML tag mode. We save the old value of the flag because it may - * already be off: XMLExpr is called both from within a tag, and from - * within text contained in an element, but outside of any start, end, or - * point tag. - */ - bool oldflag = tokenStream.isXMLTagMode(); - tokenStream.setXMLTagMode(false); - ParseNode *pn2 = expr(); - if (!pn2) - return NULL; - - MUST_MATCH_TOKEN(TOK_RC, JSMSG_CURLY_IN_XML_EXPR); - tokenStream.setXMLTagMode(oldflag); - pn->pn_kid = pn2; - pn->setOp(inTag ? JSOP_XMLTAGEXPR : JSOP_XMLELTEXPR); - pn->pn_pos.end = pn2->pn_pos.end; - return pn; -} - -/* - * Parse the productions: - * - * XMLNameExpr: - * XMLName XMLNameExpr? - * { Expr } XMLNameExpr? - * - * Return a PN_LIST, PN_UNARY, or PN_NULLARY according as XMLNameExpr produces - * a list of names and/or expressions, a single expression, or a single name. - * If PN_LIST or PN_NULLARY, getKind() will be PNK_XMLNAME. Otherwise if - * PN_UNARY, getKind() will be PNK_XMLCURLYEXPR. - */ -ParseNode * -Parser::xmlNameExpr() -{ - JS_ASSERT(allowsXML()); - - ParseNode *pn, *pn2, *list; - TokenKind tt; - - pn = list = NULL; - do { - tt = tokenStream.currentToken().type; - if (tt == TOK_LC) { - pn2 = xmlExpr(true); - if (!pn2) - return NULL; - } else { - JS_ASSERT(tt == TOK_XMLNAME); - JS_ASSERT(tokenStream.currentToken().t_op == JSOP_STRING); - pn2 = atomNode(PNK_XMLNAME, JSOP_STRING); - if (!pn2) - return NULL; - } - - if (!pn) { - pn = pn2; - } else { - if (!list) { - list = ListNode::create(PNK_XMLNAME, this); - if (!list) - return NULL; - list->pn_pos.begin = pn->pn_pos.begin; - list->initList(pn); - list->pn_xflags = PNX_CANTFOLD; - pn = list; - } - pn->pn_pos.end = pn2->pn_pos.end; - pn->append(pn2); - } - } while ((tt = tokenStream.getToken()) == TOK_XMLNAME || tt == TOK_LC); - - tokenStream.ungetToken(); - return pn; -} - -/* - * Macro to test whether an XMLNameExpr or XMLTagContent node can be folded - * at compile time into a JSXML tree. - */ -#define XML_FOLDABLE(pn) ((pn)->isArity(PN_LIST) \ - ? ((pn)->pn_xflags & PNX_CANTFOLD) == 0 \ - : !(pn)->isKind(PNK_XMLCURLYEXPR)) - -/* - * Parse the productions: - * - * XMLTagContent: - * XMLNameExpr - * XMLTagContent S XMLNameExpr S? = S? XMLAttr - * XMLTagContent S XMLNameExpr S? = S? { Expr } - * - * Return a PN_LIST, PN_UNARY, or PN_NULLARY according to how XMLTagContent - * produces a list of name and attribute values and/or braced expressions, a - * single expression, or a single name. - * - * If PN_LIST or PN_NULLARY, getKind() will be PNK_XMLNAME for the case where - * XMLTagContent: XMLNameExpr. If getKind() is not PNK_XMLNAME but getArity() - * is PN_LIST, getKind() will be tagkind. If PN_UNARY, getKind() will be - * PNK_XMLCURLYEXPR and we parsed exactly one expression. - */ -ParseNode * -Parser::xmlTagContent(ParseNodeKind tagkind, JSAtom **namep) -{ - JS_ASSERT(allowsXML()); - - ParseNode *pn, *pn2, *list; - TokenKind tt; - - pn = xmlNameExpr(); - if (!pn) - return NULL; - *namep = (pn->isArity(PN_NULLARY)) ? pn->pn_atom : NULL; - list = NULL; - - while (tokenStream.matchToken(TOK_XMLSPACE)) { - tt = tokenStream.getToken(); - if (tt != TOK_XMLNAME && tt != TOK_LC) { - tokenStream.ungetToken(); - break; - } - - pn2 = xmlNameExpr(); - if (!pn2) - return NULL; - if (!list) { - list = ListNode::create(tagkind, this); - if (!list) - return NULL; - list->pn_pos.begin = pn->pn_pos.begin; - list->initList(pn); - pn = list; - } - pn->append(pn2); - if (!XML_FOLDABLE(pn2)) - pn->pn_xflags |= PNX_CANTFOLD; - - tokenStream.matchToken(TOK_XMLSPACE); - MUST_MATCH_TOKEN(TOK_ASSIGN, JSMSG_NO_ASSIGN_IN_XML_ATTR); - tokenStream.matchToken(TOK_XMLSPACE); - - tt = tokenStream.getToken(); - if (tt == TOK_XMLATTR) { - JS_ASSERT(tokenStream.currentToken().t_op == JSOP_STRING); - pn2 = atomNode(PNK_XMLATTR, JSOP_STRING); - } else if (tt == TOK_LC) { - pn2 = xmlExpr(true); - pn->pn_xflags |= PNX_CANTFOLD; - } else { - reportError(NULL, JSMSG_BAD_XML_ATTR_VALUE); - return NULL; - } - if (!pn2) - return NULL; - pn->append(pn2); - } - - return pn; -} - -#define XML_CHECK_FOR_ERROR_AND_EOF(tt,result) \ - JS_BEGIN_MACRO \ - if ((tt) <= TOK_EOF) { \ - if ((tt) == TOK_EOF) { \ - reportError(NULL, JSMSG_END_OF_XML_SOURCE); \ - } \ - return result; \ - } \ - JS_END_MACRO - -/* - * Consume XML element tag content, including the TOK_XMLETAGO (</) sequence - * that opens the end tag for the container. - */ -bool -Parser::xmlElementContent(ParseNode *pn) -{ - JS_ASSERT(allowsXML()); - - tokenStream.setXMLTagMode(false); - for (;;) { - TokenKind tt = tokenStream.getToken(TSF_XMLTEXTMODE); - XML_CHECK_FOR_ERROR_AND_EOF(tt, false); - - JS_ASSERT(tt == TOK_XMLSPACE || tt == TOK_XMLTEXT); - JSAtom *textAtom = tokenStream.currentToken().atom(); - if (textAtom) { - /* Non-zero-length XML text scanned. */ - JS_ASSERT(tokenStream.currentToken().t_op == JSOP_STRING); - ParseNode *pn2 = atomNode(tt == TOK_XMLSPACE ? PNK_XMLSPACE : PNK_XMLTEXT, - JSOP_STRING); - if (!pn2) - return false; - pn->append(pn2); - } - - tt = tokenStream.getToken(TSF_OPERAND); - XML_CHECK_FOR_ERROR_AND_EOF(tt, false); - if (tt == TOK_XMLETAGO) - break; - - ParseNode *pn2; - if (tt == TOK_LC) { - pn2 = xmlExpr(false); - if (!pn2) - return false; - pn->pn_xflags |= PNX_CANTFOLD; - } else if (tt == TOK_XMLSTAGO) { - pn2 = xmlElementOrList(false); - if (!pn2) - return false; - pn2->pn_xflags &= ~PNX_XMLROOT; - pn->pn_xflags |= pn2->pn_xflags; - } else if (tt == TOK_XMLPI) { - const Token &tok = tokenStream.currentToken(); - pn2 = new_<XMLProcessingInstruction>(tok.xmlPITarget(), tok.xmlPIData(), tok.pos); - if (!pn2) - return false; - } else { - JS_ASSERT(tt == TOK_XMLCDATA || tt == TOK_XMLCOMMENT); - pn2 = atomNode(tt == TOK_XMLCDATA ? PNK_XMLCDATA : PNK_XMLCOMMENT, - tokenStream.currentToken().t_op); - if (!pn2) - return false; - } - pn->append(pn2); - } - tokenStream.setXMLTagMode(true); - - JS_ASSERT(tokenStream.currentToken().type == TOK_XMLETAGO); - return true; -} - -/* - * Return a PN_LIST node containing an XML or XMLList Initialiser. - */ -ParseNode * -Parser::xmlElementOrList(bool allowList) -{ - JS_ASSERT(allowsXML()); - - ParseNode *pn, *pn2, *list; - TokenKind tt; - RootedAtom startAtom(context), endAtom(context); - - JS_CHECK_RECURSION(context, return NULL); - - JS_ASSERT(tokenStream.currentToken().type == TOK_XMLSTAGO); - pn = ListNode::create(PNK_XMLSTAGO, this); - if (!pn) - return NULL; - - tokenStream.setXMLTagMode(true); - tt = tokenStream.getToken(); - if (tt == TOK_ERROR) - return NULL; - - if (tt == TOK_XMLNAME || tt == TOK_LC) { - /* - * XMLElement. Append the tag and its contents, if any, to pn. - */ - pn2 = xmlTagContent(PNK_XMLSTAGO, startAtom.address()); - if (!pn2) - return NULL; - tokenStream.matchToken(TOK_XMLSPACE); - - tt = tokenStream.getToken(); - if (tt == TOK_XMLPTAGC) { - /* Point tag (/>): recycle pn if pn2 is a list of tag contents. */ - if (pn2->isKind(PNK_XMLSTAGO)) { - pn->makeEmpty(); - freeTree(pn); - pn = pn2; - } else { - JS_ASSERT(pn2->isKind(PNK_XMLNAME) || pn2->isKind(PNK_XMLCURLYEXPR)); - pn->initList(pn2); - if (!XML_FOLDABLE(pn2)) - pn->pn_xflags |= PNX_CANTFOLD; - } - pn->setKind(PNK_XMLPTAGC); - pn->pn_xflags |= PNX_XMLROOT; - } else { - /* We had better have a tag-close (>) at this point. */ - if (tt != TOK_XMLTAGC) { - reportError(NULL, JSMSG_BAD_XML_TAG_SYNTAX); - return NULL; - } - pn2->pn_pos.end = tokenStream.currentToken().pos.end; - - /* Make sure pn2 is a TOK_XMLSTAGO list containing tag contents. */ - if (!pn2->isKind(PNK_XMLSTAGO)) { - pn->initList(pn2); - if (!XML_FOLDABLE(pn2)) - pn->pn_xflags |= PNX_CANTFOLD; - pn2 = pn; - pn = ListNode::create(PNK_XMLTAGC, this); - if (!pn) - return NULL; - pn->pn_pos = pn2->pn_pos; - } - - /* Now make pn a nominal-root TOK_XMLELEM list containing pn2. */ - pn->setKind(PNK_XMLELEM); - pn->pn_pos.begin = pn2->pn_pos.begin; - pn->initList(pn2); - if (!XML_FOLDABLE(pn2)) - pn->pn_xflags |= PNX_CANTFOLD; - pn->pn_xflags |= PNX_XMLROOT; - - /* Get element contents and delimiting end-tag-open sequence. */ - if (!xmlElementContent(pn)) - return NULL; - - tt = tokenStream.getToken(); - XML_CHECK_FOR_ERROR_AND_EOF(tt, NULL); - if (tt != TOK_XMLNAME && tt != TOK_LC) { - reportError(NULL, JSMSG_BAD_XML_TAG_SYNTAX); - return NULL; - } - - /* Parse end tag; check mismatch at compile-time if we can. */ - pn2 = xmlTagContent(PNK_XMLETAGO, endAtom.address()); - if (!pn2) - return NULL; - if (pn2->isKind(PNK_XMLETAGO)) { - /* Oops, end tag has attributes! */ - reportError(NULL, JSMSG_BAD_XML_TAG_SYNTAX); - return NULL; - } - if (endAtom && startAtom && endAtom != startAtom) { - /* End vs. start tag name mismatch: point to the tag name. */ - reportUcError(pn2, JSMSG_XML_TAG_NAME_MISMATCH, startAtom->chars()); - return NULL; - } - - /* Make a TOK_XMLETAGO list with pn2 as its single child. */ - JS_ASSERT(pn2->isKind(PNK_XMLNAME) || pn2->isKind(PNK_XMLCURLYEXPR)); - list = ListNode::create(PNK_XMLETAGO, this); - if (!list) - return NULL; - list->initList(pn2); - pn->append(list); - if (!XML_FOLDABLE(pn2)) { - list->pn_xflags |= PNX_CANTFOLD; - pn->pn_xflags |= PNX_CANTFOLD; - } - - tokenStream.matchToken(TOK_XMLSPACE); - MUST_MATCH_TOKEN(TOK_XMLTAGC, JSMSG_BAD_XML_TAG_SYNTAX); - } - - /* Set pn_op now that pn has been updated to its final value. */ - pn->setOp(JSOP_TOXML); - } else if (allowList && tt == TOK_XMLTAGC) { - /* XMLList Initialiser. */ - pn->setKind(PNK_XMLLIST); - pn->setOp(JSOP_TOXMLLIST); - pn->makeEmpty(); - pn->pn_xflags |= PNX_XMLROOT; - if (!xmlElementContent(pn)) - return NULL; - - MUST_MATCH_TOKEN(TOK_XMLTAGC, JSMSG_BAD_XML_LIST_SYNTAX); - } else { - reportError(NULL, JSMSG_BAD_XML_NAME_SYNTAX); - return NULL; - } - tokenStream.setXMLTagMode(false); - - pn->pn_pos.end = tokenStream.currentToken().pos.end; - return pn; -} - -ParseNode * -Parser::xmlElementOrListRoot(bool allowList) -{ - JS_ASSERT(allowsXML()); - - /* - * Turn on "moar XML" so that comments and CDATA literals are recognized, - * instead of <! followed by -- starting an HTML comment to end of line - * (used in script tags to hide content from old browsers that don't - * recognize <script>). - */ - bool hadMoarXML = tokenStream.hasMoarXML(); - tokenStream.setMoarXML(true); - ParseNode *pn = xmlElementOrList(allowList); - tokenStream.setMoarXML(hadMoarXML); - return pn; -} - -ParseNode * -Parser::parseXMLText(JSObject *chain, bool allowList) -{ - /* - * Push a compiler frame if we have no frames, or if the top frame is a - * lightweight function activation, or if its scope chain doesn't match - * the one passed to us. - */ - GlobalSharedContext xmlsc(context, chain, false); - ParseContext xmlpc(this, &xmlsc, /* staticLevel = */ 0, /* bodyid = */ 0); - if (!xmlpc.init()) - return NULL; - - /* Set XML-only mode to turn off special treatment of {expr} in XML. */ - tokenStream.setXMLOnlyMode(); - TokenKind tt = tokenStream.getToken(TSF_OPERAND); - - ParseNode *pn; - if (tt != TOK_XMLSTAGO) { - reportError(NULL, JSMSG_BAD_XML_MARKUP); - pn = NULL; - } else { - pn = xmlElementOrListRoot(allowList); - } - tokenStream.setXMLOnlyMode(false); - - return pn; -} - -#endif /* JS_HAS_XMLSUPPORT */ - -bool -Parser::checkForFunctionNode(PropertyName *name, ParseNode *node) -{ - /* - * In |a.ns::name|, |ns| refers to an in-scope variable, so |ns| can't be a - * keyword. (Exception: |function::name| is the actual name property, not - * what E4X would expose.) We parsed |ns| accepting a keyword as a name, - * so we must implement the keyword restriction manually in this case. - */ - if (const KeywordInfo *ki = FindKeyword(name->charsZ(), name->length())) { - if (ki->tokentype != TOK_FUNCTION) { - reportError(NULL, JSMSG_KEYWORD_NOT_NS); - return false; - } - - node->setArity(PN_NULLARY); - node->setKind(PNK_FUNCTIONNS); - } - - return true; -} - -#if JS_HAS_XML_SUPPORT -ParseNode * -Parser::propertyQualifiedIdentifier() -{ - JS_ASSERT(allowsXML()); - JS_ASSERT(tokenStream.isCurrentTokenType(TOK_NAME)); - JS_ASSERT(tokenStream.currentToken().t_op == JSOP_NAME); - JS_ASSERT(tokenStream.peekToken() == TOK_DBLCOLON); - - /* Deoptimize QualifiedIdentifier properties to avoid tricky analysis. */ - pc->sc->setBindingsAccessedDynamically(); - - PropertyName *name = tokenStream.currentToken().name(); - ParseNode *node = NameNode::create(PNK_NAME, name, this, this->pc); - if (!node) - return NULL; - node->setOp(JSOP_NAME); - node->pn_dflags |= PND_DEOPTIMIZED; - - if (!checkForFunctionNode(name, node)) - return NULL; - - tokenStream.consumeKnownToken(TOK_DBLCOLON); - return qualifiedSuffix(node); -} -#endif - -ParseNode * -Parser::identifierName(bool afterDoubleDot) +Parser::identifierName() { JS_ASSERT(tokenStream.isCurrentTokenType(TOK_NAME)); PropertyName *name = tokenStream.currentToken().name(); ParseNode *node = NameNode::create(PNK_NAME, name, this, this->pc); if (!node) return NULL; JS_ASSERT(tokenStream.currentToken().t_op == JSOP_NAME); node->setOp(JSOP_NAME); - if ((!afterDoubleDot -#if JS_HAS_XML_SUPPORT - || (allowsXML() && tokenStream.peekToken() == TOK_DBLCOLON) -#endif - ) && !pc->inDeclDestructuring) - { - if (!NoteNameUse(node, this)) - return NULL; - } - -#if JS_HAS_XML_SUPPORT - if (allowsXML() && tokenStream.matchToken(TOK_DBLCOLON)) { - if (afterDoubleDot) { - if (!checkForFunctionNode(name, node)) - return NULL; - } - node = qualifiedSuffix(node); - if (!node) - return NULL; - } -#endif + if (!pc->inDeclDestructuring && !NoteNameUse(node, this)) + return NULL; return node; } -#if JS_HAS_XML_SUPPORT -ParseNode * -Parser::starOrAtPropertyIdentifier(TokenKind tt) -{ - JS_ASSERT(tt == TOK_AT || tt == TOK_STAR); - if (allowsXML()) - return (tt == TOK_AT) ? attributeIdentifier() : qualifiedIdentifier(); - reportError(NULL, JSMSG_SYNTAX_ERROR); - return NULL; -} -#endif - ParseNode * Parser::atomNode(ParseNodeKind kind, JSOp op) { ParseNode *node = NullaryNode::create(kind, this); if (!node) return NULL; node->setOp(op); const Token &tok = tokenStream.currentToken(); @@ -6445,38 +5586,27 @@ Parser::atomNode(ParseNodeKind kind, JSO const size_t HUGE_STRING = 50000; if (sct && sct->active() && kind == PNK_STRING && node->pn_atom->length() >= HUGE_STRING) sct->abort(); return node; } ParseNode * -Parser::primaryExpr(TokenKind tt, bool afterDoubleDot) +Parser::primaryExpr(TokenKind tt) { JS_ASSERT(tokenStream.isCurrentTokenType(tt)); ParseNode *pn, *pn2, *pn3; JSOp op; JS_CHECK_RECURSION(context, return NULL); switch (tt) { case TOK_FUNCTION: -#if JS_HAS_XML_SUPPORT - if (allowsXML() && tokenStream.matchToken(TOK_DBLCOLON, TSF_KEYWORD_IS_NAME)) { - pn2 = NullaryNode::create(PNK_FUNCTIONNS, this); - if (!pn2) - return NULL; - pn = qualifiedSuffix(pn2); - if (!pn) - return NULL; - break; - } -#endif pn = functionExpr(); if (!pn) return NULL; break; case TOK_LB: { pn = ListNode::create(PNK_ARRAY, this); @@ -6873,61 +6003,18 @@ Parser::primaryExpr(TokenKind tt, bool a } case TOK_STRING: pn = atomNode(PNK_STRING, JSOP_STRING); if (!pn) return NULL; break; -#if JS_HAS_XML_SUPPORT - case TOK_AT: - case TOK_STAR: - if (!allowsXML()) - goto syntaxerror; - pn = starOrAtPropertyIdentifier(tt); - break; - - case TOK_XMLSTAGO: - if (!allowsXML()) - goto syntaxerror; - pn = xmlElementOrListRoot(true); - if (!pn) - return NULL; - break; - - case TOK_XMLCDATA: - if (!allowsXML()) - goto syntaxerror; - pn = atomNode(PNK_XMLCDATA, JSOP_XMLCDATA); - if (!pn) - return NULL; - break; - - case TOK_XMLCOMMENT: - if (!allowsXML()) - goto syntaxerror; - pn = atomNode(PNK_XMLCOMMENT, JSOP_XMLCOMMENT); - if (!pn) - return NULL; - break; - - case TOK_XMLPI: { - if (!allowsXML()) - goto syntaxerror; - const Token &tok = tokenStream.currentToken(); - pn = new_<XMLProcessingInstruction>(tok.xmlPITarget(), tok.xmlPIData(), tok.pos); - if (!pn) - return NULL; - break; - } -#endif - case TOK_NAME: - pn = identifierName(afterDoubleDot); + pn = identifierName(); break; case TOK_REGEXP: { pn = NullaryNode::create(PNK_REGEXP, this); if (!pn) return NULL; @@ -6976,17 +6063,16 @@ Parser::primaryExpr(TokenKind tt, bool a return new_<ThisLiteral>(tokenStream.currentToken().pos); case TOK_NULL: return new_<NullLiteral>(tokenStream.currentToken().pos); case TOK_ERROR: /* The scanner or one of its subroutines reported the error. */ return NULL; - syntaxerror: default: reportError(NULL, JSMSG_SYNTAX_ERROR); return NULL; } return pn; } ParseNode *
--- a/js/src/frontend/Parser.h +++ b/js/src/frontend/Parser.h @@ -174,19 +174,19 @@ struct ParseContext /* t bool funHasReturnExpr:1; /* function has 'return <expr>;' */ bool funHasReturnVoid:1; /* function has 'return;' */ // The following flags are set when parsing enters a particular region of // source code, and cleared when that region is exited. bool parsingForInit:1; /* true while parsing init expr of for; exclude 'in' */ bool parsingWith:1; /* true while we are within a - with-statement or E4X filter-expression - in the current ParseContext chain - (which stops at the top-level or an eval() */ + with-statement in the current + ParseContext chain (which stops at the + top-level or an eval() */ // Set when parsing a declaration-like destructuring pattern. This flag // causes PrimaryExpr to create PN_NAME parse nodes for variable references // which are not hooked into any definition's use chain, added to any tree // context's AtomList, etc. etc. CheckDestructuring will do that work // later. // // The comments atop CheckDestructuring explain the distinction between @@ -281,20 +281,16 @@ struct Parser : private AutoGCRooter const char *getFilename() const { return tokenStream.getFilename(); } JSVersion versionNumber() const { return tokenStream.versionNumber(); } /* * Parse a top-level JS script. */ ParseNode *parse(JSObject *chain); -#if JS_HAS_XML_SUPPORT - ParseNode *parseXMLText(JSObject *chain, bool allowList); -#endif - /* * Allocate a new parsed object or function container from * cx->tempLifoAlloc. */ ObjectBox *newObjectBox(JSObject *obj); FunctionBox *newFunctionBox(JSFunction *fun, ParseContext *pc, bool strict); @@ -412,17 +408,17 @@ struct Parser : private AutoGCRooter ParseNode *shiftExpr1i(); ParseNode *shiftExpr1n(); ParseNode *addExpr1i(); ParseNode *addExpr1n(); ParseNode *mulExpr1i(); ParseNode *mulExpr1n(); ParseNode *unaryExpr(); ParseNode *memberExpr(bool allowCallSyntax); - ParseNode *primaryExpr(TokenKind tt, bool afterDoubleDot); + ParseNode *primaryExpr(TokenKind tt); ParseNode *parenExpr(bool *genexp = NULL); /* * Additional JS parsers. */ enum FunctionType { Getter, Setter, Normal }; bool functionArguments(ParseNode **list, ParseNode *funcpn, bool &hasRest); @@ -439,45 +435,21 @@ struct Parser : private AutoGCRooter ParseNodeKind kind = PNK_SEMI, JSOp op = JSOP_NOP); ParseNode *generatorExpr(ParseNode *kid); bool argumentList(ParseNode *listNode); ParseNode *bracketedExpr(); ParseNode *letBlock(LetContext letContext); ParseNode *returnOrYield(bool useAssignExpr); ParseNode *destructuringExpr(BindData *data, TokenKind tt); - bool checkForFunctionNode(PropertyName *name, ParseNode *node); - - ParseNode *identifierName(bool afterDoubleDot); - -#if JS_HAS_XML_SUPPORT - bool allowsXML() const { return tokenStream.allowsXML(); } - - ParseNode *endBracketedExpr(); - - ParseNode *propertySelector(); - ParseNode *qualifiedSuffix(ParseNode *pn); - ParseNode *qualifiedIdentifier(); - ParseNode *attributeIdentifier(); - ParseNode *xmlExpr(bool inTag); - ParseNode *xmlNameExpr(); - ParseNode *xmlTagContent(ParseNodeKind tagkind, JSAtom **namep); - bool xmlElementContent(ParseNode *pn); - ParseNode *xmlElementOrList(bool allowList); - ParseNode *xmlElementOrListRoot(bool allowList); - - ParseNode *starOrAtPropertyIdentifier(TokenKind tt); - ParseNode *propertyQualifiedIdentifier(); -#endif /* JS_HAS_XML_SUPPORT */ + ParseNode *identifierName(); bool allowsForEachIn() { #if !JS_HAS_FOR_EACH_IN return false; -#elif JS_HAS_XML_SUPPORT - return allowsXML() || tokenStream.hasMoarXML(); #else return versionNumber() >= JSVERSION_1_6; #endif } bool setAssignmentLhsOps(ParseNode *pn, JSOp op); bool matchInOrOf(bool *isForOfp); };
--- a/js/src/frontend/SharedContext.h +++ b/js/src/frontend/SharedContext.h @@ -191,18 +191,17 @@ public: class FunctionBox : public ObjectBox, public SharedContext { public: Bindings bindings; /* bindings for this function */ size_t bufStart; size_t bufEnd; uint16_t ndefaults; - bool inWith:1; /* some enclosing scope is a with-statement - or E4X filter-expression */ + bool inWith:1; /* some enclosing scope is a with-statement */ bool inGenexpLambda:1; /* lambda from generator expression */ FunctionContextFlags funCxFlags; FunctionBox(JSContext *cx, ObjectBox* traceListHead, JSFunction *fun, ParseContext *pc, bool strict); ObjectBox *toObjectBox() { return this; }
--- a/js/src/frontend/TokenStream.cpp +++ b/js/src/frontend/TokenStream.cpp @@ -34,20 +34,16 @@ #include "frontend/TokenStream.h" #include "js/CharacterEncoding.h" #include "vm/Keywords.h" #include "vm/RegExpObject.h" #include "vm/StringBuffer.h" #include "jsscriptinlines.h" -#if JS_HAS_XML_SUPPORT -#include "jsxml.h" -#endif - using namespace js; using namespace js::frontend; using namespace js::unicode; static const KeywordInfo keywords[] = { #define KEYWORD_INFO(keyword, name, type, op, version) \ {js_##keyword##_str, type, op, version}, FOR_EACH_JAVASCRIPT_KEYWORD(KEYWORD_INFO) @@ -127,18 +123,16 @@ TokenStream::TokenStream(JSContext *cx, linebase(base.get()), prevLinebase(NULL), userbuf(base.get(), length), filename(options.filename), sourceMap(NULL), listenerTSData(), tokenbuf(cx), version(options.version), - banXML(VersionHasAllowXML(options.version) ? 0 : 1), - moarXML(VersionHasMoarXML(options.version)), cx(cx), originPrincipals(JSScript::normalizeOriginPrincipals(options.principals, options.originPrincipals)), strictModeGetter(smg), tokenSkip(cx, &tokens) { if (originPrincipals) JS_HoldPrincipals(originPrincipals); @@ -615,485 +609,16 @@ bool TokenStream::reportStrictWarningErrorNumberVA(ParseNode *pn, unsigned errorNumber, va_list args) { if (!cx->hasStrictOption()) return true; return reportCompileErrorNumberVA(NULL, JSREPORT_STRICT | JSREPORT_WARNING, errorNumber, args); } -#if JS_HAS_XML_SUPPORT - -bool -TokenStream::getXMLEntity() -{ - ptrdiff_t offset, length, i; - int c, d; - bool ispair; - jschar *bp, digit; - char *bytes; - JSErrNum msg; - - CharBuffer &tb = tokenbuf; - - /* Put the entity, including the '&' already scanned, in tokenbuf. */ - offset = tb.length(); - if (!tb.append('&')) - return false; - while ((c = getChar()) != ';') { - if (c == EOF || c == '\n') { - reportError(JSMSG_END_OF_XML_ENTITY); - return false; - } - if (!tb.append(c)) - return false; - } - - /* Let length be the number of jschars after the '&', including the ';'. */ - length = tb.length() - offset; - bp = tb.begin() + offset; - c = d = 0; - ispair = false; - if (length > 2 && bp[1] == '#') { - /* Match a well-formed XML Character Reference. */ - i = 2; - if (length > 3 && (bp[i] == 'x' || bp[i] == 'X')) { - if (length > 9) /* at most 6 hex digits allowed */ - goto badncr; - while (++i < length) { - digit = bp[i]; - if (!JS7_ISHEX(digit)) - goto badncr; - c = (c << 4) + JS7_UNHEX(digit); - } - } else { - while (i < length) { - digit = bp[i++]; - if (!JS7_ISDEC(digit)) - goto badncr; - c = (c * 10) + JS7_UNDEC(digit); - if (c < 0) - goto badncr; - } - } - - if (0x10000 <= c && c <= 0x10FFFF) { - /* Form a surrogate pair (c, d) -- c is the high surrogate. */ - d = 0xDC00 + (c & 0x3FF); - c = 0xD7C0 + (c >> 10); - ispair = true; - } else { - /* Enforce the http://www.w3.org/TR/REC-xml/#wf-Legalchar WFC. */ - if (c != 0x9 && c != 0xA && c != 0xD && - !(0x20 <= c && c <= 0xD7FF) && - !(0xE000 <= c && c <= 0xFFFD)) { - goto badncr; - } - } - } else { - /* Try to match one of the five XML 1.0 predefined entities. */ - switch (length) { - case 3: - if (bp[2] == 't') { - if (bp[1] == 'l') - c = '<'; - else if (bp[1] == 'g') - c = '>'; - } - break; - case 4: - if (bp[1] == 'a' && bp[2] == 'm' && bp[3] == 'p') - c = '&'; - break; - case 5: - if (bp[3] == 'o') { - if (bp[1] == 'a' && bp[2] == 'p' && bp[4] == 's') - c = '\''; - else if (bp[1] == 'q' && bp[2] == 'u' && bp[4] == 't') - c = '"'; - } - break; - } - if (c == 0) { - msg = JSMSG_UNKNOWN_XML_ENTITY; - goto bad; - } - } - - /* If we matched, retract tokenbuf and store the entity's value. */ - *bp++ = (jschar) c; - if (ispair) - *bp++ = (jschar) d; - tb.shrinkBy(tb.end() - bp); - return true; - - badncr: - msg = JSMSG_BAD_XML_NCR; - bad: - /* No match: throw a TypeError per ECMA-357 10.3.2.1 step 8(a). */ - JS_ASSERT((tb.end() - bp) >= 1); - TwoByteChars tbchars(bp + 1, (tb.end() - bp) - 1); - bytes = LossyTwoByteCharsToNewLatin1CharsZ(cx, tbchars).c_str(); - if (bytes) { - reportError(msg, bytes); - js_free(bytes); - } - return false; -} - -bool -TokenStream::getXMLTextOrTag(TokenKind *ttp, Token **tpp) -{ - TokenKind tt; - int c, qc; - Token *tp; - JSAtom *atom; - - /* - * Look for XML text. - */ - if (flags & TSF_XMLTEXTMODE) { - tt = TOK_XMLSPACE; /* veto if non-space, return TOK_XMLTEXT */ - tp = newToken(0); - tokenbuf.clear(); - qc = (flags & TSF_XMLONLYMODE) ? '<' : '{'; - - while ((c = getChar()) != qc && c != '<' && c != EOF) { - if (c == '&' && qc == '<') { - if (!getXMLEntity()) - goto error; - tt = TOK_XMLTEXT; - continue; - } - - if (!IsXMLSpace(c)) - tt = TOK_XMLTEXT; - if (!tokenbuf.append(c)) - goto error; - } - ungetChar(c); - - if (tokenbuf.empty()) { - atom = NULL; - } else { - atom = atomize(cx, tokenbuf); - if (!atom) - goto error; - } - tp->pos.end.lineno = lineno; - tp->setAtom(JSOP_STRING, atom); - goto out; - } - - /* - * XML tags. - */ - else { - JS_ASSERT(flags & TSF_XMLTAGMODE); - tp = newToken(0); - c = getChar(); - if (c != EOF && IsXMLSpace(c)) { - do { - c = getChar(); - if (c == EOF) - break; - } while (IsXMLSpace(c)); - ungetChar(c); - tp->pos.end.lineno = lineno; - tt = TOK_XMLSPACE; - goto out; - } - - if (c == EOF) { - tt = TOK_EOF; - goto out; - } - - tokenbuf.clear(); - if (IsXMLNamespaceStart(c)) { - bool sawColon = false; - - if (!tokenbuf.append(c)) - goto error; - while ((c = getChar()) != EOF && IsXMLNamePart(c)) { - if (c == ':') { - int nextc; - - if (sawColon || - (nextc = peekChar(), - ((flags & TSF_XMLONLYMODE) || nextc != '{') && - !IsXMLNamePart(nextc))) { - reportError(JSMSG_BAD_XML_QNAME); - goto error; - } - sawColon = true; - } - - if (!tokenbuf.append(c)) - goto error; - } - - ungetChar(c); - atom = atomize(cx, tokenbuf); - if (!atom) - goto error; - tp->setAtom(JSOP_STRING, atom); - tt = TOK_XMLNAME; - goto out; - } - - switch (c) { - case '{': - if (flags & TSF_XMLONLYMODE) - goto bad_xml_char; - tt = TOK_LC; - goto out; - - case '=': - tt = TOK_ASSIGN; - goto out; - - case '"': - case '\'': - qc = c; - while ((c = getChar()) != qc) { - if (c == EOF) { - reportError(JSMSG_UNTERMINATED_STRING); - goto error; - } - - /* - * XML attribute values are double-quoted when pretty-printed, - * so escape " if it is expressed directly in a single-quoted - * attribute value. - */ - if (c == '"' && !(flags & TSF_XMLONLYMODE)) { - JS_ASSERT(qc == '\''); - if (!tokenbuf.append(js_quot_entity_str, - strlen(js_quot_entity_str))) - goto error; - continue; - } - - if (c == '&' && (flags & TSF_XMLONLYMODE)) { - if (!getXMLEntity()) - goto error; - continue; - } - - if (!tokenbuf.append(c)) - goto error; - } - atom = atomize(cx, tokenbuf); - if (!atom) - goto error; - tp->pos.end.lineno = lineno; - tp->setAtom(JSOP_STRING, atom); - tt = TOK_XMLATTR; - goto out; - - case '>': - tt = TOK_XMLTAGC; - goto out; - - case '/': - if (matchChar('>')) { - tt = TOK_XMLPTAGC; - goto out; - } - /* FALL THROUGH */ - - bad_xml_char: - default: - reportError(JSMSG_BAD_XML_CHARACTER); - goto error; - } - JS_NOT_REACHED("getXMLTextOrTag 1"); - } - JS_NOT_REACHED("getXMLTextOrTag 2"); - - out: - *ttp = tt; - *tpp = tp; - return true; - - error: - *ttp = TOK_ERROR; - *tpp = tp; - return false; -} - -/* - * After much testing, it's clear that Postel's advice to protocol designers - * ("be liberal in what you accept, and conservative in what you send") invites - * a natural-law repercussion for JS as "protocol": - * - * "If you are liberal in what you accept, others will utterly fail to be - * conservative in what they send." - * - * Which means you will get <!-- comments to end of line in the middle of .js - * files, and after if conditions whose then statements are on the next line, - * and other wonders. See at least the following bugs: - * - https://bugzilla.mozilla.org/show_bug.cgi?id=309242 - * - https://bugzilla.mozilla.org/show_bug.cgi?id=309712 - * - https://bugzilla.mozilla.org/show_bug.cgi?id=310993 - * - * So without JSOPTION_MOAR_XML, we changed around Firefox 1.5 never to scan an - * XML comment or CDATA literal. Instead, we always scan <! as the start of an - * HTML comment hack to end of line, used since Netscape 2 to hide script tag - * content from script-unaware browsers. - * - * But this still leaves XML resources with certain internal structure - * vulnerable to being loaded as script cross-origin, and some internal data - * stolen, so for Firefox 3.5 and beyond, we reject programs whose source - * consists only of XML literals. See: - * - * https://bugzilla.mozilla.org/show_bug.cgi?id=336551 - * - * The check for this is in js::frontend::CompileScript. - */ -bool -TokenStream::getXMLMarkup(TokenKind *ttp, Token **tpp) -{ - TokenKind tt; - int c; - Token *tp = *tpp; - - /* Check for XML comment or CDATA section. */ - if (matchChar('!')) { - tokenbuf.clear(); - - /* Scan XML comment. */ - if (matchChar('-')) { - if (!matchChar('-')) - goto bad_xml_markup; - while ((c = getChar()) != '-' || !matchChar('-')) { - if (c == EOF) - goto bad_xml_markup; - if (!tokenbuf.append(c)) - goto error; - } - if (!matchChar('>')) - goto bad_xml_markup; - - JSAtom *commentText = atomize(cx, tokenbuf); - if (!commentText) - goto error; - tp->setAtom(JSOP_XMLCOMMENT, commentText); - tp->pos.end.lineno = lineno; - tt = TOK_XMLCOMMENT; - goto out; - } - - /* Scan CDATA section. */ - if (matchChar('[')) { - jschar cp[6]; - if (peekChars(6, cp) && - cp[0] == 'C' && - cp[1] == 'D' && - cp[2] == 'A' && - cp[3] == 'T' && - cp[4] == 'A' && - cp[5] == '[') { - skipChars(6); - while ((c = getChar()) != ']' || - !peekChars(2, cp) || - cp[0] != ']' || - cp[1] != '>') { - if (c == EOF) - goto bad_xml_markup; - if (!tokenbuf.append(c)) - goto error; - } - consumeKnownChar(']'); - consumeKnownChar('>'); - - JSAtom *cdataContent = atomize(cx, tokenbuf); - if (!cdataContent) - goto error; - - tp->setAtom(JSOP_XMLCDATA, cdataContent); - tp->pos.end.lineno = lineno; - tt = TOK_XMLCDATA; - goto out; - } - goto bad_xml_markup; - } - } - - /* Check for processing instruction. */ - if (matchChar('?')) { - bool inTarget = true; - size_t targetLength = 0; - ptrdiff_t contentIndex = -1; - - tokenbuf.clear(); - while ((c = getChar()) != '?' || peekChar() != '>') { - if (c == EOF) - goto bad_xml_markup; - if (inTarget) { - if (IsXMLSpace(c)) { - if (tokenbuf.empty()) - goto bad_xml_markup; - inTarget = false; - } else { - if (!(tokenbuf.empty() - ? IsXMLNamespaceStart(c) - : IsXMLNamespacePart(c))) { - goto bad_xml_markup; - } - ++targetLength; - } - } else { - if (contentIndex < 0 && !IsXMLSpace(c)) - contentIndex = tokenbuf.length(); - } - if (!tokenbuf.append(c)) - goto error; - } - if (targetLength == 0) - goto bad_xml_markup; - - JSAtom *data; - if (contentIndex < 0) { - data = cx->names().empty; - } else { - data = AtomizeChars<CanGC>(cx, tokenbuf.begin() + contentIndex, - tokenbuf.length() - contentIndex); - if (!data) - goto error; - } - tokenbuf.shrinkBy(tokenbuf.length() - targetLength); - consumeKnownChar('>'); - JSAtom *target = atomize(cx, tokenbuf); - if (!target) - goto error; - tp->setProcessingInstruction(target->asPropertyName(), data); - tp->pos.end.lineno = lineno; - tt = TOK_XMLPI; - goto out; - } - - /* An XML start-of-tag character. */ - tt = matchChar('/') ? TOK_XMLETAGO : TOK_XMLSTAGO; - - out: - *ttp = tt; - *tpp = tp; - return true; - - bad_xml_markup: - reportError(JSMSG_BAD_XML_MARKUP); - error: - *ttp = TOK_ERROR; - *tpp = tp; - return false; -} -#endif /* JS_HAS_XML_SUPPORT */ - /* * We have encountered a '\': check for a Unicode escape sequence after it. * Return 'true' and the character code value (by value) if we found a * Unicode escape sequence. Otherwise, return 'false'. In both cases, do not * advance along the buffer. */ bool TokenStream::peekUnicodeEscape(int *result) @@ -1297,29 +822,19 @@ IsTokenSane(Token *tp) */ if (tp->type < TOK_ERROR || tp->type >= TOK_LIMIT || tp->type == TOK_EOL) return false; if (tp->pos.begin.lineno == tp->pos.end.lineno) { if (tp->pos.begin.index > tp->pos.end.index) return false; } else { - /* Only certain token kinds can be multi-line. */ - switch (tp->type) { - case TOK_STRING: - case TOK_XMLATTR: - case TOK_XMLSPACE: - case TOK_XMLTEXT: - case TOK_XMLCOMMENT: - case TOK_XMLCDATA: - case TOK_XMLPI: - break; - default: + /* Only string tokens can be multi-line. */ + if (tp->type != TOK_STRING) return false; - } } return true; } #endif bool TokenStream::putIdentInTokenbuf(const jschar *identStart) { @@ -1439,27 +954,16 @@ TokenStream::getTokenInternal() Token *tp; FirstCharKind c1kind; const jschar *numStart; bool hasExp; DecimalPoint decimalPoint; const jschar *identStart; bool hadUnicodeEscape; -#if JS_HAS_XML_SUPPORT - /* - * Look for XML text and tags. - */ - if (flags & (TSF_XMLTEXTMODE|TSF_XMLTAGMODE)) { - if (!getXMLTextOrTag(&tt, &tp)) - goto error; - goto out; - } -#endif - retry: if (JS_UNLIKELY(!userbuf.hasRawChars())) { tp = newToken(0); tt = TOK_EOF; flags |= TSF_EOF; goto out; } @@ -1601,20 +1105,16 @@ TokenStream::getTokenInternal() } if (c == '.') { qc = getCharIgnoreEOL(); if (qc == '.') { tt = TOK_TRIPLEDOT; goto out; } ungetCharIgnoreEOL(qc); -#if JS_HAS_XML_SUPPORT - tt = TOK_DBLDOT; - goto out; -#endif } ungetCharIgnoreEOL(c); tt = TOK_DOT; goto out; } if (c1kind == Equals) { if (matchChar('=')) { @@ -1791,22 +1291,16 @@ TokenStream::getTokenInternal() goto error; } tp->setNumber(dval, decimalPoint); tt = TOK_NUMBER; goto out; } if (c1kind == Colon) { -#if JS_HAS_XML_SUPPORT - if (matchChar(':')) { - tt = TOK_DBLCOLON; - goto out; - } -#endif tp->t_op = JSOP_NOP; tt = TOK_COLON; goto out; } if (c1kind == Plus) { if (matchChar('=')) { tp->t_op = JSOP_ADD; @@ -1934,31 +1428,17 @@ TokenStream::getTokenInternal() tt = TOK_NE; } } else { tp->t_op = JSOP_NOT; tt = TOK_NOT; } break; -#if JS_HAS_XML_SUPPORT - case '@': - tt = TOK_AT; - break; -#endif - case '<': -#if JS_HAS_XML_SUPPORT - if ((flags & TSF_OPERAND) && allowsXML() && (hasMoarXML() || peekChar() != '!')) { - if (!getXMLMarkup(&tt, &tp)) - goto error; - goto out; - } -#endif - /* NB: treat HTML begin-comment as comment-till-end-of-line */ if (matchChar('!')) { if (matchChar('-')) { if (matchChar('-')) { flags |= TSF_IN_HTML_COMMENT; goto skipline; } ungetChar('-'); @@ -2275,33 +1755,16 @@ TokenKindToString(TokenKind tt) case TOK_NEW: return "TOK_NEW"; case TOK_DELETE: return "TOK_DELETE"; case TOK_TRY: return "TOK_TRY"; case TOK_CATCH: return "TOK_CATCH"; case TOK_FINALLY: return "TOK_FINALLY"; case TOK_THROW: return "TOK_THROW"; case TOK_INSTANCEOF: return "TOK_INSTANCEOF"; case TOK_DEBUGGER: return "TOK_DEBUGGER"; - case TOK_XMLSTAGO: return "TOK_XMLSTAGO"; - case TOK_XMLETAGO: return "TOK_XMLETAGO"; - case TOK_XMLPTAGC: return "TOK_XMLPTAGC"; - case TOK_XMLTAGC: return "TOK_XMLTAGC"; - case TOK_XMLNAME: return "TOK_XMLNAME"; - case TOK_XMLATTR: return "TOK_XMLATTR"; - case TOK_XMLSPACE: return "TOK_XMLSPACE"; - case TOK_XMLTEXT: return "TOK_XMLTEXT"; - case TOK_XMLCOMMENT: return "TOK_XMLCOMMENT"; - case TOK_XMLCDATA: return "TOK_XMLCDATA"; - case TOK_XMLPI: return "TOK_XMLPI"; - case TOK_AT: return "TOK_AT"; - case TOK_DBLCOLON: return "TOK_DBLCOLON"; - case TOK_DBLDOT: return "TOK_DBLDOT"; - case TOK_FILTER: return "TOK_FILTER"; - case TOK_XMLELEM: return "TOK_XMLELEM"; - case TOK_XMLLIST: return "TOK_XMLLIST"; case TOK_YIELD: return "TOK_YIELD"; case TOK_LEXICALSCOPE: return "TOK_LEXICALSCOPE"; case TOK_LET: return "TOK_LET"; case TOK_RESERVED: return "TOK_RESERVED"; case TOK_STRICT_RESERVED: return "TOK_STRICT_RESERVED"; case TOK_STRICTEQ: return "TOK_STRICTEQ"; case TOK_EQ: return "TOK_EQ"; case TOK_STRICTNE: return "TOK_STRICTNE";
--- a/js/src/frontend/TokenStream.h +++ b/js/src/frontend/TokenStream.h @@ -77,33 +77,16 @@ enum TokenKind { TOK_NEW, /* new keyword */ TOK_DELETE, /* delete keyword */ TOK_TRY, /* try keyword */ TOK_CATCH, /* catch keyword */ TOK_FINALLY, /* finally keyword */ TOK_THROW, /* throw keyword */ TOK_INSTANCEOF, /* instanceof keyword */ TOK_DEBUGGER, /* debugger keyword */ - TOK_XMLSTAGO, /* XML start tag open (<) */ - TOK_XMLETAGO, /* XML end tag open (</) */ - TOK_XMLPTAGC, /* XML point tag close (/>) */ - TOK_XMLTAGC, /* XML start or end tag close (>) */ - TOK_XMLNAME, /* XML start-tag non-final fragment */ - TOK_XMLATTR, /* XML quoted attribute value */ - TOK_XMLSPACE, /* XML whitespace */ - TOK_XMLTEXT, /* XML text */ - TOK_XMLCOMMENT, /* XML comment */ - TOK_XMLCDATA, /* XML CDATA section */ - TOK_XMLPI, /* XML processing instruction */ - TOK_AT, /* XML attribute op (@) */ - TOK_DBLCOLON, /* namespace qualified name op (::) */ - TOK_DBLDOT, /* XML descendant op (..) */ - TOK_FILTER, /* XML filtering predicate op (.()) */ - TOK_XMLELEM, /* XML element node type (no token) */ - TOK_XMLLIST, /* XML list node type (no token) */ TOK_YIELD, /* yield from generator function */ TOK_LEXICALSCOPE, /* block scope AST node label */ TOK_LET, /* let keyword */ TOK_EXPORT, /* export keyword */ TOK_IMPORT, /* import keyword */ TOK_RESERVED, /* reserved keywords */ TOK_STRICT_RESERVED, /* reserved keywords in strict mode */ @@ -287,20 +270,16 @@ struct Token { friend struct Token; PropertyName *name; /* non-numeric atom */ JSAtom *atom; /* potentially-numeric atom */ } n; } s; private: friend struct Token; - struct { /* pair for <?target data?> XML PI */ - PropertyName *target; /* non-empty */ - JSAtom *data; /* maybe empty, never null */ - } xmlpi; struct { double value; /* floating point number */ DecimalPoint decimalPoint; /* literal contains . or exponent */ } number; RegExpFlag reflags; /* regexp flags, use tokenbuf to access regexp chars */ } u; @@ -314,32 +293,22 @@ struct Token { void setName(JSOp op, PropertyName *name) { JS_ASSERT(op == JSOP_NAME); JS_ASSERT(!IsPoisonedPtr(name)); u.s.op = op; u.s.n.name = name; } void setAtom(JSOp op, JSAtom *atom) { - JS_ASSERT(op == JSOP_STRING || op == JSOP_XMLCOMMENT || JSOP_XMLCDATA); + JS_ASSERT(op == JSOP_STRING); JS_ASSERT(!IsPoisonedPtr(atom)); u.s.op = op; u.s.n.atom = atom; } - void setProcessingInstruction(PropertyName *target, JSAtom *data) { - JS_ASSERT(target); - JS_ASSERT(data); - JS_ASSERT(!target->empty()); - JS_ASSERT(!IsPoisonedPtr(target)); - JS_ASSERT(!IsPoisonedPtr(data)); - u.xmlpi.target = target; - u.xmlpi.data = data; - } - void setRegExpFlags(js::RegExpFlag flags) { JS_ASSERT((flags & AllFlags) == flags); u.reflags = flags; } void setNumber(double n, DecimalPoint decimalPoint) { u.number.value = n; u.number.decimalPoint = decimalPoint; @@ -348,35 +317,20 @@ struct Token { /* Type-safe accessors */ PropertyName *name() const { JS_ASSERT(type == TOK_NAME); return u.s.n.name->asPropertyName(); /* poor-man's type verification */ } JSAtom *atom() const { - JS_ASSERT(type == TOK_STRING || - type == TOK_XMLNAME || - type == TOK_XMLATTR || - type == TOK_XMLTEXT || - type == TOK_XMLCDATA || - type == TOK_XMLSPACE || - type == TOK_XMLCOMMENT); + JS_ASSERT(type == TOK_STRING); return u.s.n.atom; } - PropertyName *xmlPITarget() const { - JS_ASSERT(type == TOK_XMLPI); - return u.xmlpi.target; - } - JSAtom *xmlPIData() const { - JS_ASSERT(type == TOK_XMLPI); - return u.xmlpi.data; - } - js::RegExpFlag regExpFlags() const { JS_ASSERT(type == TOK_REGEXP); JS_ASSERT((u.reflags & AllFlags) == u.reflags); return u.reflags; } double number() const { JS_ASSERT(type == TOK_NUMBER); @@ -395,21 +349,18 @@ enum TokenStreamFlags { TSF_EOF = 0x02, /* hit end of file */ TSF_EOL = 0x04, /* an EOL was hit in whitespace or a multi-line comment */ TSF_OPERAND = 0x08, /* looking for operand, not operator */ TSF_UNEXPECTED_EOF = 0x10, /* unexpected end of input, i.e. TOK_EOF not at top-level. */ TSF_KEYWORD_IS_NAME = 0x20, /* Ignore keywords and return TOK_NAME instead to the parser. */ TSF_DIRTYLINE = 0x40, /* non-whitespace since start of line */ TSF_OWNFILENAME = 0x80, /* ts->filename is malloc'd */ - TSF_XMLTAGMODE = 0x100, /* scanning within an XML tag in E4X */ - TSF_XMLTEXTMODE = 0x200, /* scanning XMLText terminal from E4X */ - TSF_XMLONLYMODE = 0x400, /* don't scan {expr} within text/tag */ - TSF_OCTAL_CHAR = 0x800, /* observed a octal character escape */ - TSF_HAD_ERROR = 0x1000, /* returned TOK_ERROR from getToken */ + TSF_OCTAL_CHAR = 0x100, /* observed a octal character escape */ + TSF_HAD_ERROR = 0x200, /* returned TOK_ERROR from getToken */ /* * To handle the hard case of contiguous HTML comments, we want to clear the * TSF_DIRTYINPUT flag at the end of each such comment. But we'd rather not * scan for --> within every //-style comment unless we have to. So we set * TSF_IN_HTML_COMMENT when a <!-- is scanned as an HTML begin-comment, and * clear it (and TSF_DIRTYINPUT) when we scan --> either on a clean line, or * only if (ts->flags & TSF_IN_HTML_COMMENT), in a //-style comment. @@ -499,24 +450,18 @@ class TokenStream return type == type1 || type == type2; } size_t offsetOfToken(const Token &tok) const { return tok.ptr - userbuf.base(); } const CharBuffer &getTokenbuf() const { return tokenbuf; } const char *getFilename() const { return filename; } unsigned getLineno() const { return lineno; } - /* Note that the version and hasMoarXML can get out of sync via setMoarXML. */ JSVersion versionNumber() const { return VersionNumber(version); } JSVersion versionWithFlags() const { return version; } - bool allowsXML() const { return banXML == 0 && !strictMode(); } - bool hasMoarXML() const { return moarXML || VersionShouldParseXML(versionNumber()); } - void setMoarXML(bool enabled) { moarXML = enabled; } - void incBanXML() { banXML++; } - void decBanXML() { JS_ASSERT(banXML); banXML--; } bool hadError() const { return !!(flags & TSF_HAD_ERROR); } bool isCurrentTokenEquality() const { return TokenKindIsEquality(currentToken().type); } bool isCurrentTokenRelational() const { return TokenKindIsRelational(currentToken().type); @@ -526,22 +471,18 @@ class TokenStream return TokenKindIsShift(currentToken().type); } bool isCurrentTokenAssignment() const { return TokenKindIsAssignment(currentToken().type); } /* Flag methods. */ - void setXMLTagMode(bool enabled = true) { setFlag(enabled, TSF_XMLTAGMODE); } - void setXMLOnlyMode(bool enabled = true) { setFlag(enabled, TSF_XMLONLYMODE); } void setUnexpectedEOF(bool enabled = true) { setFlag(enabled, TSF_UNEXPECTED_EOF); } - bool isXMLTagMode() const { return !!(flags & TSF_XMLTAGMODE); } - bool isXMLOnlyMode() const { return !!(flags & TSF_XMLONLYMODE); } bool isUnexpectedEOF() const { return !!(flags & TSF_UNEXPECTED_EOF); } bool isEOF() const { return !!(flags & TSF_EOF); } bool sawOctalEscape() const { return !!(flags & TSF_OCTAL_CHAR); } // TokenStream-specific error reporters. bool reportError(unsigned errorNumber, ...); bool reportWarning(unsigned errorNumber, ...); @@ -590,17 +531,16 @@ class TokenStream public: /* * Get the next token from the stream, make it the current token, and * return its kind. */ TokenKind getToken() { /* Check for a pushed-back token resulting from mismatching lookahead. */ if (lookahead != 0) { - JS_ASSERT(!(flags & TSF_XMLTEXTMODE)); lookahead--; cursor = (cursor + 1) & ntokensMask; TokenKind tt = currentToken().type; JS_ASSERT(tt != TOK_EOL); return tt; } return getTokenInternal(); @@ -826,20 +766,16 @@ class TokenStream Token *newToken(ptrdiff_t adjust); bool peekUnicodeEscape(int32_t *c); bool matchUnicodeEscapeIdStart(int32_t *c); bool matchUnicodeEscapeIdent(int32_t *c); bool peekChars(int n, jschar *cp); bool getAtLine(); bool getAtSourceMappingURL(); - bool getXMLEntity(); - bool getXMLTextOrTag(TokenKind *ttp, Token **tpp); - bool getXMLMarkup(TokenKind *ttp, Token **tpp); - bool matchChar(int32_t expect) { int32_t c = getChar(); if (c == expect) return true; ungetChar(c); return false; } @@ -873,18 +809,16 @@ class TokenStream const char *filename; /* input filename or null */ jschar *sourceMap; /* source map's filename or null */ void *listenerTSData;/* listener data for this TokenStream */ CharBuffer tokenbuf; /* current token string buffer */ int8_t oneCharTokens[128]; /* table of one-char tokens */ bool maybeEOL[256]; /* probabilistic EOL lookup table */ bool maybeStrSpecial[256];/* speeds up string scanning */ JSVersion version; /* (i.e. to identify keywords) */ - unsigned banXML; /* see JSOPTION_ALLOW_XML */ - bool moarXML; /* see JSOPTION_MOAR_XML */ JSContext *const cx; JSPrincipals *const originPrincipals; StrictModeGetter *strictModeGetter; /* used to test for strict mode */ Position lastFunctionKeyword; /* used as a starting point for reparsing strict functions */ /* * The tokens array stores pointers to JSAtoms. These are rooted by the * atoms table using AutoKeepAtoms in the Parser. This SkipRoot tells the
--- a/js/src/gc/Barrier.h +++ b/js/src/gc/Barrier.h @@ -110,18 +110,16 @@ * * One additional note: not all object writes need to be barriered. Writes to * newly allocated objects do not need a pre-barrier. In these cases, we use * the "obj->field.init(value)" method instead of "obj->field = value". We use * the init naming idiom in many places to signify that a field is being * assigned for the first time. */ -struct JSXML; - namespace js { template<class T, typename Unioned = uintptr_t> class EncapsulatedPtr { protected: union { T *value; @@ -332,17 +330,16 @@ typedef RelocatablePtr<JSScript> Relocat typedef HeapPtr<JSObject> HeapPtrObject; typedef HeapPtr<JSFunction> HeapPtrFunction; typedef HeapPtr<JSString> HeapPtrString; typedef HeapPtr<JSScript> HeapPtrScript; typedef HeapPtr<Shape> HeapPtrShape; typedef HeapPtr<BaseShape> HeapPtrBaseShape; typedef HeapPtr<types::TypeObject> HeapPtrTypeObject; -typedef HeapPtr<JSXML> HeapPtrXML; /* Useful for hashtables with a HeapPtr as key. */ template<class T> struct HeapPtrHasher { typedef HeapPtr<T> Key; typedef T *Lookup;
--- a/js/src/gc/Heap.h +++ b/js/src/gc/Heap.h @@ -48,19 +48,16 @@ enum AllocKind { FINALIZE_OBJECT12_BACKGROUND, FINALIZE_OBJECT16, FINALIZE_OBJECT16_BACKGROUND, FINALIZE_OBJECT_LAST = FINALIZE_OBJECT16_BACKGROUND, FINALIZE_SCRIPT, FINALIZE_SHAPE, FINALIZE_BASE_SHAPE, FINALIZE_TYPE_OBJECT, -#if JS_HAS_XML_SUPPORT - FINALIZE_XML, -#endif FINALIZE_SHORT_STRING, FINALIZE_STRING, FINALIZE_EXTERNAL_STRING, FINALIZE_IONCODE, FINALIZE_LAST = FINALIZE_IONCODE }; static const unsigned FINALIZE_LIMIT = FINALIZE_LAST + 1;
--- a/js/src/gc/Marking.cpp +++ b/js/src/gc/Marking.cpp @@ -4,17 +4,16 @@ /* 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 "mozilla/DebugOnly.h" #include "jsprf.h" #include "jsstr.h" -#include "jsxml.h" #include "gc/Marking.h" #include "methodjit/MethodJIT.h" #include "vm/Shape.h" #include "jsobjinlines.h" #include "ion/IonCode.h" @@ -53,21 +52,16 @@ void * const js::NullPtr::constNullValue * The MarkX functions also handle non-GC object traversal. In this case, they * call a callback for each object visited. This is a recursive process; the * mark stacks are not involved. These callbacks may ask for the outgoing * pointers to be visited. Eventually, this leads to the MarkChildren functions * being called. These functions duplicate much of the functionality of * scanning functions, but they don't push onto an explicit stack. */ -#if JS_HAS_XML_SUPPORT -static inline void -PushMarkStack(GCMarker *gcmarker, JSXML *thing); -#endif - static inline void PushMarkStack(GCMarker *gcmarker, JSObject *thing); static inline void PushMarkStack(GCMarker *gcmarker, JSFunction *thing); static inline void PushMarkStack(GCMarker *gcmarker, UnrootedScript thing); @@ -85,19 +79,16 @@ namespace js { namespace gc { static void MarkChildren(JSTracer *trc, JSString *str); static void MarkChildren(JSTracer *trc, UnrootedScript script); static void MarkChildren(JSTracer *trc, UnrootedShape shape); static void MarkChildren(JSTracer *trc, UnrootedBaseShape base); static void MarkChildren(JSTracer *trc, types::TypeObject *type); static void MarkChildren(JSTracer *trc, ion::IonCode *code); -#if JS_HAS_XML_SUPPORT -static void MarkChildren(JSTracer *trc, JSXML *xml); -#endif } /* namespace gc */ } /* namespace js */ /*** Object Marking ***/ #ifdef DEBUG template<typename T> @@ -343,19 +334,16 @@ DeclMarkerImpl(Object, ScopeObject) DeclMarkerImpl(Script, JSScript) DeclMarkerImpl(Shape, Shape) DeclMarkerImpl(String, JSAtom) DeclMarkerImpl(String, JSString) DeclMarkerImpl(String, JSFlatString) DeclMarkerImpl(String, JSLinearString) DeclMarkerImpl(String, PropertyName) DeclMarkerImpl(TypeObject, js::types::TypeObject) -#if JS_HAS_XML_SUPPORT -DeclMarkerImpl(XML, JSXML) -#endif } /* namespace gc */ } /* namespace js */ /*** Externally Typed Marking ***/ void gc::MarkKind(JSTracer *trc, void **thingp, JSGCTraceKind kind) @@ -380,21 +368,16 @@ gc::MarkKind(JSTracer *trc, void **thing MarkInternal(trc, reinterpret_cast<RawBaseShape *>(thingp)); break; case JSTRACE_TYPE_OBJECT: MarkInternal(trc, reinterpret_cast<types::TypeObject **>(thingp)); break; case JSTRACE_IONCODE: MarkInternal(trc, reinterpret_cast<ion::IonCode **>(thingp)); break; -#if JS_HAS_XML_SUPPORT - case JSTRACE_XML: - MarkInternal(trc, reinterpret_cast<JSXML **>(thingp)); - break; -#endif } } static void MarkGCThingInternal(JSTracer *trc, void **thingp, const char *name) { JS_SET_TRACING_NAME(trc, name); JS_ASSERT(thingp); @@ -730,27 +713,16 @@ gc::IsCellAboutToBeFinalized(Cell **thin #define JS_COMPARTMENT_ASSERT(rt, thing) \ JS_ASSERT((thing)->zone()->isGCMarking()) #define JS_COMPARTMENT_ASSERT_STR(rt, thing) \ JS_ASSERT((thing)->zone()->isGCMarking() || \ (thing)->compartment() == (rt)->atomsCompartment); -#if JS_HAS_XML_SUPPORT -static void -PushMarkStack(GCMarker *gcmarker, JSXML *thing) -{ - JS_COMPARTMENT_ASSERT(gcmarker->runtime, thing); - - if (thing->markIfUnmarked(gcmarker->getMarkColor())) - gcmarker->pushXML(thing); -} -#endif - static void PushMarkStack(GCMarker *gcmarker, JSObject *thing) { JS_COMPARTMENT_ASSERT(gcmarker->runtime, thing); if (thing->markIfUnmarked(gcmarker->getMarkColor())) gcmarker->pushObject(thing); } @@ -1113,24 +1085,16 @@ gc::MarkChildren(JSTracer *trc, types::T static void gc::MarkChildren(JSTracer *trc, ion::IonCode *code) { #ifdef JS_ION code->trace(trc); #endif } -#if JS_HAS_XML_SUPPORT -static void -gc::MarkChildren(JSTracer *trc, JSXML *xml) -{ - js_TraceXML(trc, xml); -} -#endif - template<typename T> static void PushArenaTyped(GCMarker *gcmarker, ArenaHeader *aheader) { for (CellIterUnderGC i(aheader); !i.done(); i.next()) PushMarkStack(gcmarker, i.get<T>()); } @@ -1160,22 +1124,16 @@ gc::PushArena(GCMarker *gcmarker, ArenaH case JSTRACE_TYPE_OBJECT: PushArenaTyped<js::types::TypeObject>(gcmarker, aheader); break; case JSTRACE_IONCODE: PushArenaTyped<js::ion::IonCode>(gcmarker, aheader); break; - -#if JS_HAS_XML_SUPPORT - case JSTRACE_XML: - PushArenaTyped<JSXML>(gcmarker, aheader); - break; -#endif } } struct SlotArrayLayout { union { HeapSlot *end; HeapSlot::Kind kind; @@ -1321,23 +1279,16 @@ GCMarker::processMarkStackOther(SliceBud } } if (budget.isOverBudget()) { pushArenaList(aheader); return; } } } - -#if JS_HAS_XML_SUPPORT - else { - JS_ASSERT(tag == XmlTag); - MarkChildren(this, reinterpret_cast<JSXML *>(addr)); - } -#endif } inline void GCMarker::processMarkStackTop(SliceBudget &budget) { /* * The function uses explicit goto and implements the scanning of the * object directly. It allows to eliminate the tail recursion and @@ -1521,22 +1472,16 @@ js::TraceChildren(JSTracer *trc, void *t case JSTRACE_BASE_SHAPE: MarkChildren(trc, static_cast<RawBaseShape>(thing)); break; case JSTRACE_TYPE_OBJECT: MarkChildren(trc, (types::TypeObject *)thing); break; - -#if JS_HAS_XML_SUPPORT - case JSTRACE_XML: - MarkChildren(trc, static_cast<JSXML *>(thing)); - break; -#endif } } void js::CallTracer(JSTracer *trc, void *thing, JSGCTraceKind kind) { JS_ASSERT(thing); void *tmp = thing;
--- a/js/src/gc/Marking.h +++ b/js/src/gc/Marking.h @@ -101,19 +101,16 @@ DeclMarker(Object, ScopeObject) DeclMarker(Script, JSScript) DeclMarker(Shape, Shape) DeclMarker(String, JSAtom) DeclMarker(String, JSString) DeclMarker(String, JSFlatString) DeclMarker(String, JSLinearString) DeclMarker(String, PropertyName) DeclMarker(TypeObject, types::TypeObject) -#if JS_HAS_XML_SUPPORT -DeclMarker(XML, JSXML) -#endif #undef DeclMarker /*** Externally Typed Marking ***/ /* * Note: this must only be called by the GC and only when we are tracing through * MarkRoots. It is explicitly for ConservativeStackMarking and should go away @@ -264,24 +261,16 @@ Mark(JSTracer *trc, EncapsulatedPtrObjec } inline void Mark(JSTracer *trc, EncapsulatedPtrScript *o, const char *name) { MarkScript(trc, o, name); } -#if JS_HAS_XML_SUPPORT -inline void -Mark(JSTracer *trc, HeapPtr<JSXML> *xml, const char *name) -{ - MarkXML(trc, xml, name); -} -#endif - inline void Mark(JSTracer *trc, HeapPtr<ion::IonCode> *code, const char *name) { MarkIonCode(trc, code, name); } bool IsCellMarked(Cell **thingp);
--- a/js/src/gc/RootMarking.cpp +++ b/js/src/gc/RootMarking.cpp @@ -418,29 +418,16 @@ AutoGCRooter::trace(JSTracer *trc) if (desc.attrs & JSPROP_SETTER && desc.setter) { JSObject *tmp = JS_FUNC_TO_DATA_PTR(JSObject *, desc.setter); MarkObjectRoot(trc, &tmp, "Descriptor::set"); desc.setter = JS_DATA_TO_FUNC_PTR(JSStrictPropertyOp, tmp); } return; } -#if JS_HAS_XML_SUPPORT - case NAMESPACES: { - JSXMLArray<JSObject> &array = static_cast<AutoNamespaceArray *>(this)->array; - MarkObjectRange(trc, array.length, array.vector, "JSXMLArray.vector"); - js_XMLArrayCursorTrace(trc, array.cursors); - return; - } - - case XML: - js_TraceXML(trc, static_cast<AutoXMLRooter *>(this)->xml); - return; -#endif - case OBJECT: if (static_cast<AutoObjectRooter *>(this)->obj) MarkObjectRoot(trc, &static_cast<AutoObjectRooter *>(this)->obj, "JS::AutoObjectRooter.obj"); return; case ID: MarkIdRoot(trc, &static_cast<AutoIdRooter *>(this)->id_, "JS::AutoIdRooter.id_");
--- a/js/src/gc/StoreBuffer.h +++ b/js/src/gc/StoreBuffer.h @@ -7,19 +7,16 @@ #ifdef JSGC_GENERATIONAL #ifndef jsgc_storebuffer_h___ #define jsgc_storebuffer_h___ #ifndef JSGC_USE_EXACT_ROOTING # error "Generational GC requires exact rooting." #endif -#ifdef JSGC_HAS_XML_SUPPORT -# error "E4X must be disabled to enable generational GC." -#endif #include "jsgc.h" #include "jsalloc.h" #include "gc/Marking.h" namespace js { namespace gc {
--- a/js/src/gc/Verifier.cpp +++ b/js/src/gc/Verifier.cpp @@ -196,19 +196,17 @@ SuppressCheckRoots(Vector<Rooter, 0, Sys return false; } void JS::CheckStackRoots(JSContext *cx) { JSRuntime *rt = cx->runtime; - if (rt->gcZeal_ != ZealStackRootingSafeValue && rt->gcZeal_ != ZealStackRootingValue) - return; - if (rt->gcZeal_ == ZealStackRootingSafeValue && !rt->gcExactScanningEnabled) + if (rt->gcZeal_ != ZealStackRootingValue) return; // If this assertion fails, it means that an AutoAssertNoGC was placed // around code that could trigger GC, and is therefore wrong. The // AutoAssertNoGC should be removed and the code it was guarding should be // modified to properly root any gcthings, and very possibly any code // calling that function should also be modified if it was improperly // assuming that GC could not happen at all within the called function. @@ -643,18 +641,17 @@ struct VerifyPostTracer : JSTracer { * The post-barrier verifier runs the full store buffer and a fake nursery when * running and when it stops, walks the full heap to ensure that all the * important edges were inserted into the storebuffer. */ void gc::StartVerifyPostBarriers(JSRuntime *rt) { #ifdef JSGC_GENERATIONAL - if (!rt->gcExactScanningEnabled || - rt->gcVerifyPostData || + if (rt->gcVerifyPostData || rt->gcIncrementalState != NO_INCREMENTAL) { return; } VerifyPostTracer *trc = js_new<VerifyPostTracer>(); rt->gcVerifyPostData = trc; rt->gcNumber++; trc->number = rt->gcNumber; @@ -729,19 +726,16 @@ js::gc::EndVerifyPostBarriers(JSRuntime { #ifdef JSGC_GENERATIONAL AutoPrepareForTracing prep(rt); VerifyPostTracer *trc = (VerifyPostTracer *)rt->gcVerifyPostData; JS_TracerInit(trc, rt, PostVerifierVisitEdge); trc->count = 0; - if (!rt->gcExactScanningEnabled) - goto oom; - for (CompartmentsIter c(rt); !c.done(); c.next()) { if (c->gcStoreBuffer.hasOverflowed()) continue; if (!c->gcStoreBuffer.coalesceForVerification()) goto oom; } /* Walk the heap. */
--- a/js/src/gdb/mozilla/jsid.py +++ b/js/src/gdb/mozilla/jsid.py @@ -13,17 +13,16 @@ class jsid(object): # Since people don't always build with macro debugging info, I can't # think of any way to avoid copying these values here, short of using # inferior calls for every operation (which, I hear, is broken from # pretty-printers in some recent GDBs). TYPE_STRING = 0x0 TYPE_INT = 0x1 TYPE_VOID = 0x2 TYPE_OBJECT = 0x4 - TYPE_DEFAULT_XML_NAMESPACE = 0x6 TYPE_MASK = 0x7 def __init__(self, value, cache): self.value = value self.cache = cache # SpiderMonkey has two alternative definitions of jsid: a typedef for # ptrdiff_t, and a struct with == and != operators defined on it. @@ -44,13 +43,11 @@ class jsid(object): body = bits.cast(self.cache.JSString_ptr_t) elif tag & jsid.TYPE_INT: body = bits >> 1 elif tag == jsid.TYPE_VOID: return "JSID_VOID" elif tag == jsid.TYPE_OBJECT: body = ((bits & ~jsid.TYPE_MASK) .cast(self.cache.JSObject_ptr_t)) - elif tag == jsid.TYPE_DEFAULT_XML_NAMESPACE: - return "JS_DEFAULT_XML_NAMESPACE_ID" else: body = "<unrecognized>" return '$jsid(%s)' % (body,)
--- a/js/src/gdb/tests/test-jsid.cpp +++ b/js/src/gdb/tests/test-jsid.cpp @@ -2,20 +2,18 @@ FRAGMENT(jsid, simple) { js::Rooted<JSString *> string(cx, JS_NewStringCopyZ(cx, "moon")); js::Rooted<JSString *> interned(cx, JS_InternJSString(cx, string)); js::Rooted<jsid> string_id(cx, INTERNED_STRING_TO_JSID(cx, interned)); jsid int_id = INT_TO_JSID(1729); jsid void_id = JSID_VOID; js::Rooted<jsid> object_id(cx, OBJECT_TO_JSID(JS_GetGlobalObject(cx))); - jsid xml_id = JS_DEFAULT_XML_NAMESPACE_ID; breakpoint(); (void) string; (void) interned; (void) string_id; (void) int_id; (void) void_id; (void) object_id; - (void) xml_id; }
--- a/js/src/gdb/tests/test-jsid.py +++ b/js/src/gdb/tests/test-jsid.py @@ -3,9 +3,8 @@ assert_subprinter_registered('SpiderMonkey', 'jsid') run_fragment('jsid.simple') assert_pretty('string_id', '$jsid("moon")') assert_pretty('int_id', '$jsid(1729)') assert_pretty('void_id', 'JSID_VOID') assert_pretty('object_id', '$jsid((JSObject *) [object global] delegate)') -assert_pretty('xml_id', 'JS_DEFAULT_XML_NAMESPACE_ID')
--- a/js/src/ion/IonCaches.cpp +++ b/js/src/ion/IonCaches.cpp @@ -994,17 +994,17 @@ js::ion::GetPropertyCache(JSContext *cx, if (!topScript->hasIonScript()) return true; return Invalidate(cx, topScript); } RootedId id(cx, NameToId(name)); if (obj->getOps()->getProperty) { - if (!GetPropertyGenericMaybeCallXML(cx, JSOp(*pc), obj, id, vp)) + if (!JSObject::getGeneric(cx, obj, obj, id, vp)) return false; } else { if (!GetPropertyHelper(cx, obj, id, 0, vp)) return false; } if (!cache.idempotent()) { // If the cache is idempotent, the property exists so we don't have to
--- a/js/src/js-config.h.in +++ b/js/src/js-config.h.in @@ -57,12 +57,9 @@ #undef JS_INT64_TYPE #undef JS_INTPTR_TYPE #undef JS_BYTES_PER_WORD /* Some mozilla code uses JS-friend APIs that depend on JS_METHODJIT being correct. */ #undef JS_METHODJIT -/* Define to 1 to enable support for E4X (ECMA-357), 0 to disable it. */ -#undef JS_HAS_XML_SUPPORT - #endif /* js_config_h___ */
--- a/js/src/js.msg +++ b/js/src/js.msg @@ -124,17 +124,17 @@ MSG_DEF(JSMSG_MISSING_FORMAL, 7 MSG_DEF(JSMSG_PAREN_AFTER_FORMAL, 71, 0, JSEXN_SYNTAXERR, "missing ) after formal parameters") MSG_DEF(JSMSG_CURLY_BEFORE_BODY, 72, 0, JSEXN_SYNTAXERR, "missing { before function body") MSG_DEF(JSMSG_CURLY_AFTER_BODY, 73, 0, JSEXN_SYNTAXERR, "missing } after function body") MSG_DEF(JSMSG_PAREN_BEFORE_COND, 74, 0, JSEXN_SYNTAXERR, "missing ( before condition") MSG_DEF(JSMSG_PAREN_AFTER_COND, 75, 0, JSEXN_SYNTAXERR, "missing ) after condition") MSG_DEF(JSMSG_BAD_DUP_ARGS, 76, 0, JSEXN_SYNTAXERR, "duplicate argument names not allowed in this context") MSG_DEF(JSMSG_NAME_AFTER_DOT, 77, 0, JSEXN_SYNTAXERR, "missing name after . operator") MSG_DEF(JSMSG_BRACKET_IN_INDEX, 78, 0, JSEXN_SYNTAXERR, "missing ] in index expression") -MSG_DEF(JSMSG_XML_WHOLE_PROGRAM, 79, 0, JSEXN_SYNTAXERR, "XML can't be the whole program") +MSG_DEF(JSMSG_UNUSED79, 79, 0, JSEXN_NONE, "") MSG_DEF(JSMSG_PAREN_BEFORE_SWITCH, 80, 0, JSEXN_SYNTAXERR, "missing ( before switch expression") MSG_DEF(JSMSG_PAREN_AFTER_SWITCH, 81, 0, JSEXN_SYNTAXERR, "missing ) after switch expression") MSG_DEF(JSMSG_CURLY_BEFORE_SWITCH, 82, 0, JSEXN_SYNTAXERR, "missing { before switch body") MSG_DEF(JSMSG_COLON_AFTER_CASE, 83, 0, JSEXN_SYNTAXERR, "missing : after case label") MSG_DEF(JSMSG_WHILE_AFTER_DO, 84, 0, JSEXN_SYNTAXERR, "missing while after do-loop body") MSG_DEF(JSMSG_PAREN_AFTER_FOR, 85, 0, JSEXN_SYNTAXERR, "missing ( after for") MSG_DEF(JSMSG_SEMI_AFTER_FOR_INIT, 86, 0, JSEXN_SYNTAXERR, "missing ; after for-loop initializer") MSG_DEF(JSMSG_SEMI_AFTER_FOR_COND, 87, 0, JSEXN_SYNTAXERR, "missing ; after for-loop condition") @@ -215,66 +215,66 @@ MSG_DEF(JSMSG_IDSTART_AFTER_NUMBER, 16 MSG_DEF(JSMSG_UNDEFINED_PROP, 162, 1, JSEXN_REFERENCEERR, "reference to undefined property {0}") MSG_DEF(JSMSG_USELESS_EXPR, 163, 0, JSEXN_TYPEERR, "useless expression") MSG_DEF(JSMSG_REDECLARED_PARAM, 164, 1, JSEXN_TYPEERR, "redeclaration of formal parameter {0}") MSG_DEF(JSMSG_NEWREGEXP_FLAGGED, 165, 0, JSEXN_TYPEERR, "can't supply flags when constructing one RegExp from another") MSG_DEF(JSMSG_RESERVED_SLOT_RANGE, 166, 0, JSEXN_RANGEERR, "reserved slot index out of range") MSG_DEF(JSMSG_CANT_DECODE_PRINCIPALS, 167, 0, JSEXN_INTERNALERR, "can't decode JSPrincipals") MSG_DEF(JSMSG_CANT_SEAL_OBJECT, 168, 1, JSEXN_ERR, "can't seal {0} objects") MSG_DEF(JSMSG_TOO_MANY_CATCH_VARS, 169, 0, JSEXN_SYNTAXERR, "too many catch variables") -MSG_DEF(JSMSG_BAD_XML_MARKUP, 170, 0, JSEXN_SYNTAXERR, "invalid XML markup") -MSG_DEF(JSMSG_BAD_XML_CHARACTER, 171, 0, JSEXN_SYNTAXERR, "illegal XML character") -MSG_DEF(JSMSG_BAD_DEFAULT_XML_NAMESPACE,172,0,JSEXN_SYNTAXERR, "invalid default XML namespace") -MSG_DEF(JSMSG_BAD_XML_NAME_SYNTAX, 173, 0, JSEXN_SYNTAXERR, "invalid XML name") -MSG_DEF(JSMSG_BRACKET_AFTER_ATTR_EXPR,174, 0, JSEXN_SYNTAXERR, "missing ] after attribute expression") +MSG_DEF(JSMSG_UNUSED170, 170, 0, JSEXN_NONE, "") +MSG_DEF(JSMSG_UNUSED171, 171, 0, JSEXN_NONE, "") +MSG_DEF(JSMSG_UNUSED172, 172, 0, JSEXN_NONE, "") +MSG_DEF(JSMSG_UNUSED173, 173, 0, JSEXN_NONE, "") +MSG_DEF(JSMSG_UNUSED174, 174, 0, JSEXN_NONE, "") MSG_DEF(JSMSG_NESTING_GENERATOR, 175, 0, JSEXN_TYPEERR, "already executing generator") -MSG_DEF(JSMSG_CURLY_IN_XML_EXPR, 176, 0, JSEXN_SYNTAXERR, "missing } in XML expression") -MSG_DEF(JSMSG_BAD_XML_NAMESPACE, 177, 1, JSEXN_TYPEERR, "invalid XML namespace {0}") -MSG_DEF(JSMSG_BAD_XML_ATTR_NAME, 178, 1, JSEXN_TYPEERR, "invalid XML attribute name {0}") -MSG_DEF(JSMSG_BAD_XML_NAME, 179, 1, JSEXN_TYPEERR, "invalid XML name {0}") -MSG_DEF(JSMSG_BAD_XML_CONVERSION, 180, 1, JSEXN_TYPEERR, "can't convert {0} to XML") -MSG_DEF(JSMSG_BAD_XMLLIST_CONVERSION, 181, 1, JSEXN_TYPEERR, "can't convert {0} to XMLList") +MSG_DEF(JSMSG_UNUSED176, 176, 0, JSEXN_NONE, "") +MSG_DEF(JSMSG_UNUSED177, 177, 0, JSEXN_NONE, "") +MSG_DEF(JSMSG_UNUSED178, 178, 0, JSEXN_NONE, "") +MSG_DEF(JSMSG_UNUSED179, 179, 0, JSEXN_NONE, "") +MSG_DEF(JSMSG_UNUSED180, 180, 0, JSEXN_NONE, "") +MSG_DEF(JSMSG_UNUSED181, 181, 0, JSEXN_NONE, "") MSG_DEF(JSMSG_BAD_GENERATOR_SEND, 182, 1, JSEXN_TYPEERR, "attempt to send {0} to newborn generator") -MSG_DEF(JSMSG_NO_ASSIGN_IN_XML_ATTR, 183, 0, JSEXN_SYNTAXERR, "missing = in XML attribute") -MSG_DEF(JSMSG_BAD_XML_ATTR_VALUE, 184, 0, JSEXN_SYNTAXERR, "invalid XML attribute value") -MSG_DEF(JSMSG_XML_TAG_NAME_MISMATCH, 185, 1, JSEXN_SYNTAXERR, "XML tag name mismatch (expected {0})") -MSG_DEF(JSMSG_BAD_XML_TAG_SYNTAX, 186, 0, JSEXN_SYNTAXERR, "invalid XML tag syntax") -MSG_DEF(JSMSG_BAD_XML_LIST_SYNTAX, 187, 0, JSEXN_SYNTAXERR, "invalid XML list syntax") +MSG_DEF(JSMSG_UNUSED183, 183, 0, JSEXN_NONE, "") +MSG_DEF(JSMSG_UNUSED184, 184, 0, JSEXN_NONE, "") +MSG_DEF(JSMSG_UNUSED185, 185, 0, JSEXN_NONE, "") +MSG_DEF(JSMSG_UNUSED186, 186, 0, JSEXN_NONE, "") +MSG_DEF(JSMSG_UNUSED187, 187, 0, JSEXN_NONE, "") MSG_DEF(JSMSG_INCOMPATIBLE_METHOD, 188, 3, JSEXN_TYPEERR, "{0} {1} called on incompatible {2}") -MSG_DEF(JSMSG_CANT_SET_XML_ATTRS, 189, 0, JSEXN_INTERNALERR, "can't set XML property attributes") -MSG_DEF(JSMSG_END_OF_XML_SOURCE, 190, 0, JSEXN_SYNTAXERR, "unexpected end of XML source") -MSG_DEF(JSMSG_END_OF_XML_ENTITY, 191, 0, JSEXN_SYNTAXERR, "unexpected end of XML entity") -MSG_DEF(JSMSG_BAD_XML_QNAME, 192, 0, JSEXN_SYNTAXERR, "invalid XML qualified name") +MSG_DEF(JSMSG_UNUSED189, 189, 0, JSEXN_NONE, "") +MSG_DEF(JSMSG_UNUSED190, 190, 0, JSEXN_NONE, "") +MSG_DEF(JSMSG_UNUSED191, 191, 0, JSEXN_NONE, "") +MSG_DEF(JSMSG_UNUSED192, 192, 0, JSEXN_NONE, "") MSG_DEF(JSMSG_BAD_FOR_EACH_LOOP, 193, 0, JSEXN_SYNTAXERR, "invalid for each loop") -MSG_DEF(JSMSG_BAD_XMLLIST_PUT, 194, 1, JSEXN_TYPEERR, "can't set property {0} in XMLList") -MSG_DEF(JSMSG_UNKNOWN_XML_ENTITY, 195, 1, JSEXN_TYPEERR, "unknown XML entity {0}") -MSG_DEF(JSMSG_BAD_XML_NCR, 196, 1, JSEXN_TYPEERR, "malformed XML character {0}") -MSG_DEF(JSMSG_UNDEFINED_XML_NAME, 197, 1, JSEXN_REFERENCEERR, "reference to undefined XML name {0}") -MSG_DEF(JSMSG_DUPLICATE_XML_ATTR, 198, 1, JSEXN_TYPEERR, "duplicate XML attribute {0}") +MSG_DEF(JSMSG_UNUSED194, 194, 0, JSEXN_NONE, "") +MSG_DEF(JSMSG_UNUSED195, 195, 0, JSEXN_NONE, "") +MSG_DEF(JSMSG_UNUSED196, 196, 0, JSEXN_NONE, "") +MSG_DEF(JSMSG_UNUSED197, 197, 0, JSEXN_NONE, "") +MSG_DEF(JSMSG_UNUSED198, 198, 0, JSEXN_NONE, "") MSG_DEF(JSMSG_TOO_MANY_LOCALS, 199, 0, JSEXN_SYNTAXERR, "too many local variables") MSG_DEF(JSMSG_ARRAY_INIT_TOO_BIG, 200, 0, JSEXN_INTERNALERR, "array initialiser too large") MSG_DEF(JSMSG_REGEXP_TOO_COMPLEX, 201, 0, JSEXN_INTERNALERR, "regular expression too complex") MSG_DEF(JSMSG_BUFFER_TOO_SMALL, 202, 0, JSEXN_INTERNALERR, "buffer too small") MSG_DEF(JSMSG_BAD_SURROGATE_CHAR, 203, 1, JSEXN_TYPEERR, "bad surrogate character {0}") MSG_DEF(JSMSG_UTF8_CHAR_TOO_LARGE, 204, 1, JSEXN_TYPEERR, "UTF-8 character {0} too large") MSG_DEF(JSMSG_MALFORMED_UTF8_CHAR, 205, 1, JSEXN_TYPEERR, "malformed UTF-8 character sequence at offset {0}") MSG_DEF(JSMSG_USER_DEFINED_ERROR, 206, 0, JSEXN_ERR, "JS_ReportError was called") MSG_DEF(JSMSG_WRONG_CONSTRUCTOR, 207, 1, JSEXN_TYPEERR, "wrong constructor called for {0}") MSG_DEF(JSMSG_BAD_GENERATOR_RETURN, 208, 1, JSEXN_TYPEERR, "generator function {0} returns a value") MSG_DEF(JSMSG_BAD_ANON_GENERATOR_RETURN, 209, 0, JSEXN_TYPEERR, "anonymous generator function returns a value") MSG_DEF(JSMSG_NAME_AFTER_FOR_PAREN, 210, 0, JSEXN_SYNTAXERR, "missing name after for (") MSG_DEF(JSMSG_IN_AFTER_FOR_NAME, 211, 0, JSEXN_SYNTAXERR, "missing 'in' or 'of' after for") MSG_DEF(JSMSG_BAD_TRAP_RETURN_VALUE, 212, 2, JSEXN_TYPEERR,"trap {1} for {0} returned a primitive value") -MSG_DEF(JSMSG_KEYWORD_NOT_NS, 213, 0, JSEXN_SYNTAXERR, "keyword is used as namespace") +MSG_DEF(JSMSG_UNUSED213, 213, 0, JSEXN_NONE, "") MSG_DEF(JSMSG_BAD_GENERATOR_YIELD, 214, 1, JSEXN_TYPEERR, "yield from closing generator {0}") MSG_DEF(JSMSG_BAD_GENERATOR_SYNTAX, 215, 1, JSEXN_SYNTAXERR, "{0} expression must be parenthesized") MSG_DEF(JSMSG_ARRAY_COMP_LEFTSIDE, 216, 0, JSEXN_SYNTAXERR, "invalid array comprehension left-hand side") -MSG_DEF(JSMSG_NON_XML_FILTER, 217, 1, JSEXN_TYPEERR, "XML filter is applied to non-XML value {0}") +MSG_DEF(JSMSG_UNUSED217, 217, 0, JSEXN_NONE, "") MSG_DEF(JSMSG_EMPTY_ARRAY_REDUCE, 218, 0, JSEXN_TYPEERR, "reduce of empty array with no initial value") -MSG_DEF(JSMSG_NON_LIST_XML_METHOD, 219, 2, JSEXN_TYPEERR, "can't call {0} method on an XML list with {1} elements") +MSG_DEF(JSMSG_UNUSED219, 219, 0, JSEXN_NONE, "") MSG_DEF(JSMSG_BAD_DELETE_OPERAND, 220, 0, JSEXN_REFERENCEERR, "invalid delete operand") MSG_DEF(JSMSG_BAD_INCOP_OPERAND, 221, 0, JSEXN_REFERENCEERR, "invalid increment/decrement operand") MSG_DEF(JSMSG_UNEXPECTED_TYPE, 222, 2, JSEXN_TYPEERR, "{0} is {1}") MSG_DEF(JSMSG_LET_DECL_NOT_IN_BLOCK, 223, 0, JSEXN_SYNTAXERR, "let declaration not directly within block") MSG_DEF(JSMSG_BAD_OBJECT_INIT, 224, 0, JSEXN_SYNTAXERR, "invalid object initializer") MSG_DEF(JSMSG_CANT_SET_ARRAY_ATTRS, 225, 0, JSEXN_INTERNALERR, "can't set attributes on indexed array properties") MSG_DEF(JSMSG_EVAL_ARITY, 226, 0, JSEXN_TYPEERR, "eval accepts only one parameter") MSG_DEF(JSMSG_MISSING_FUN_ARG, 227, 2, JSEXN_TYPEERR, "missing argument {0} when calling function {1}") @@ -308,26 +308,26 @@ MSG_DEF(JSMSG_BAD_PARSE_NODE, 25 MSG_DEF(JSMSG_NOT_EXPECTED_TYPE, 255, 3, JSEXN_TYPEERR, "{0}: expected {1}, got {2}") MSG_DEF(JSMSG_CALLER_IS_STRICT, 256, 0, JSEXN_TYPEERR, "access to strict mode caller function is censored") MSG_DEF(JSMSG_NEED_DEBUG_MODE, 257, 0, JSEXN_ERR, "function can be called only in debug mode") MSG_DEF(JSMSG_STRICT_CODE_LET_EXPR_STMT, 258, 0, JSEXN_ERR, "strict mode code may not contain unparenthesized let expression statements") MSG_DEF(JSMSG_CANT_CHANGE_EXTENSIBILITY, 259, 0, JSEXN_TYPEERR, "can't change object's extensibility") MSG_DEF(JSMSG_SC_BAD_SERIALIZED_DATA, 260, 1, JSEXN_INTERNALERR, "bad serialized structured data ({0})") MSG_DEF(JSMSG_SC_UNSUPPORTED_TYPE, 261, 0, JSEXN_TYPEERR, "unsupported type for structured data") MSG_DEF(JSMSG_SC_RECURSION, 262, 0, JSEXN_INTERNALERR, "recursive object") -MSG_DEF(JSMSG_CANT_WRAP_XML_OBJECT, 263, 0, JSEXN_TYPEERR, "can't wrap XML objects") +MSG_DEF(JSMSG_UNUSED263, 263, 0, JSEXN_NONE, "") MSG_DEF(JSMSG_BAD_CLONE_VERSION, 264, 0, JSEXN_ERR, "unsupported structured clone version") MSG_DEF(JSMSG_CANT_CLONE_OBJECT, 265, 0, JSEXN_TYPEERR, "can't clone object") MSG_DEF(JSMSG_UNUSED266, 266, 0, JSEXN_NONE, "") MSG_DEF(JSMSG_STRICT_FUNCTION_STATEMENT, 267, 0, JSEXN_SYNTAXERR, "in strict mode code, functions may be declared only at top level or immediately within another function") MSG_DEF(JSMSG_INVALID_FOR_IN_INIT, 268, 0, JSEXN_SYNTAXERR, "for-in loop let declaration may not have an initializer") MSG_DEF(JSMSG_CLEARED_SCOPE, 269, 0, JSEXN_TYPEERR, "attempt to run compile-and-go script on a cleared scope") MSG_DEF(JSMSG_MALFORMED_ESCAPE, 270, 1, JSEXN_SYNTAXERR, "malformed {0} character escape sequence") MSG_DEF(JSMSG_BAD_GENEXP_BODY, 271, 1, JSEXN_SYNTAXERR, "illegal use of {0} in generator expression") -MSG_DEF(JSMSG_XML_PROTO_FORBIDDEN, 272, 0, JSEXN_TYPEERR, "can't set prototype of an object to an XML value") +MSG_DEF(JSMSG_UNUSED272, 272, 0, JSEXN_NONE, "") MSG_DEF(JSMSG_UNNAMED_FUNCTION_STMT, 273, 0, JSEXN_SYNTAXERR, "function statement requires a name") MSG_DEF(JSMSG_CCW_REQUIRED, 274, 1, JSEXN_TYPEERR, "{0}: argument must be an object from a different compartment") MSG_DEF(JSMSG_DEBUG_BAD_RESUMPTION, 275, 0, JSEXN_TYPEERR, "debugger resumption value must be undefined, {throw: val}, {return: val}, or null") MSG_DEF(JSMSG_ASSIGN_FUNCTION_OR_NULL, 276, 1, JSEXN_TYPEERR, "value assigned to {0} must be a function or null") MSG_DEF(JSMSG_DEBUG_NOT_LIVE, 277, 1, JSEXN_ERR, "{0} is not live") MSG_DEF(JSMSG_DEBUG_OBJECT_WRONG_OWNER, 278, 0, JSEXN_TYPEERR, "Debugger.Object belongs to a different Debugger") MSG_DEF(JSMSG_DEBUG_OBJECT_PROTO, 279, 0, JSEXN_TYPEERR, "Debugger.Object.prototype is not a valid Debugger.Object") MSG_DEF(JSMSG_DEBUG_LOOP, 280, 0, JSEXN_TYPEERR, "cannot debug an object in same compartment as debugger or a compartment that is already debugging the debugger")
--- a/js/src/jsanalyze.cpp +++ b/js/src/jsanalyze.cpp @@ -305,20 +305,16 @@ ScriptAnalysis::analyzeBytecode(JSContex break; case JSOP_SETRVAL: case JSOP_POPV: usesReturnValue_ = true; isJaegerInlineable = isIonInlineable = false; break; - case JSOP_QNAMEPART: - case JSOP_QNAMECONST: - isJaegerCompileable = false; - /* FALL THROUGH */ case JSOP_NAME: case JSOP_CALLNAME: case JSOP_BINDNAME: case JSOP_SETNAME: case JSOP_DELNAME: case JSOP_GETALIASEDVAR: case JSOP_CALLALIASEDVAR: case JSOP_SETALIASEDVAR: @@ -869,17 +865,17 @@ ScriptAnalysis::analyzeLifetimes(JSConte uint32_t entry = targetOffset; if (entry) { do { entry--; } while (!maybeCode(entry)); jsbytecode *entrypc = script_->code + entry; - if (JSOp(*entrypc) == JSOP_GOTO || JSOp(*entrypc) == JSOP_FILTER) + if (JSOp(*entrypc) == JSOP_GOTO) loop->entry = entry + GET_JUMP_OFFSET(entrypc); else loop->entry = targetOffset; } else { /* Do-while loop at the start of the script. */ loop->entry = targetOffset; } JS_ASSERT(script_->code[loop->entry] == JSOP_LOOPHEAD ||
--- a/js/src/jsanalyze.h +++ b/js/src/jsanalyze.h @@ -178,18 +178,16 @@ GetDefCount(UnrootedScript script, unsig /* * Add an extra pushed value for OR/AND opcodes, so that they are included * in the pushed array of stack values for type inference. */ switch (JSOp(*pc)) { case JSOP_OR: case JSOP_AND: return 1; - case JSOP_FILTER: - return 2; case JSOP_PICK: /* * Pick pops and pushes how deep it looks in the stack + 1 * items. i.e. if the stack were |a b[2] c[1] d[0]|, pick 2 * would pop b, c, and d to rearrange the stack to |a c[0] * d[1] b[2]|. */ return (pc[1] + 1); @@ -242,17 +240,16 @@ BytecodeNoFallThrough(JSOp op) switch (op) { case JSOP_GOTO: case JSOP_DEFAULT: case JSOP_RETURN: case JSOP_STOP: case JSOP_RETRVAL: case JSOP_THROW: case JSOP_TABLESWITCH: - case JSOP_FILTER: return true; case JSOP_GOSUB: /* These fall through indirectly, after executing a 'finally'. */ return false; default: return false; } }
--- a/js/src/jsapi.cpp +++ b/js/src/jsapi.cpp @@ -47,17 +47,16 @@ #include "jsproxy.h" #include "jsscript.h" #include "jsstr.h" #include "prmjtime.h" #include "jsweakmap.h" #include "jsworkers.h" #include "jswrapper.h" #include "jstypedarray.h" -#include "jsxml.h" #include "builtin/Eval.h" #include "builtin/Intl.h" #include "builtin/MapObject.h" #include "builtin/RegExp.h" #include "builtin/ParallelArray.h" #include "ds/LifoAlloc.h" #include "frontend/BytecodeCompiler.h" @@ -144,21 +143,16 @@ class AutoVersionAPI : cx(cx), oldDefaultVersion(cx->getDefaultVersion()), oldHasVersionOverride(cx->isVersionOverridden()), oldVersionOverride(oldHasVersionOverride ? cx->findVersion() : JSVERSION_UNKNOWN) #ifdef DEBUG , oldCompileOptions(cx->getCompileOptions()) #endif { -#if JS_HAS_XML_SUPPORT - // For backward compatibility, AutoVersionAPI clobbers the - // JSOPTION_MOAR_XML bit in cx, but not the JSOPTION_ALLOW_XML bit. - newVersion = JSVersion(newVersion | (oldDefaultVersion & VersionFlags::ALLOW_XML)); -#endif this->newVersion = newVersion; cx->clearVersionOverride(); cx->setDefaultVersion(newVersion); } ~AutoVersionAPI() { cx->setDefaultVersion(oldDefaultVersion); if (oldHasVersionOverride) @@ -174,17 +168,16 @@ class AutoVersionAPI #ifdef HAVE_VA_LIST_AS_ARRAY #define JS_ADDRESSOF_VA_LIST(ap) ((va_list *)(ap)) #else #define JS_ADDRESSOF_VA_LIST(ap) (&(ap)) #endif #ifdef JS_USE_JSID_STRUCT_TYPES -jsid JS_DEFAULT_XML_NAMESPACE_ID = { size_t(JSID_TYPE_DEFAULT_XML_NAMESPACE) }; jsid JSID_VOID = { size_t(JSID_TYPE_VOID) }; jsid JSID_EMPTY = { size_t(JSID_TYPE_OBJECT) }; #endif const jsval JSVAL_NULL = IMPL_TO_JSVAL(BUILD_JSVAL(JSVAL_TAG_NULL, 0)); const jsval JSVAL_ZERO = IMPL_TO_JSVAL(BUILD_JSVAL(JSVAL_TAG_INT32, 0)); const jsval JSVAL_ONE = IMPL_TO_JSVAL(BUILD_JSVAL(JSVAL_TAG_INT32, 1)); const jsval JSVAL_FALSE = IMPL_TO_JSVAL(BUILD_JSVAL(JSVAL_TAG_BOOLEAN, JS_FALSE)); @@ -812,17 +805,16 @@ JSRuntime::JSRuntime(JSUseHelperThreads gcAbortSweepAfterCurrentGroup(false), gcArenasAllocatedDuringSweep(NULL), #ifdef DEBUG gcMarkingValidator(NULL), #endif gcInterFrameGC(0), gcSliceBudget(SliceBudget::Unlimited), gcIncrementalEnabled(true), - gcExactScanningEnabled(true), gcManipulatingDeadCompartments(false), gcObjectsMarkedInDeadCompartments(0), gcPoke(false), heapState(Idle), #ifdef JS_GC_ZEAL gcZeal_(0), gcZealFrequency(0), gcNextScheduled(0), @@ -1788,21 +1780,16 @@ static JSStdName standard_class_atoms[] {js_InitArrayClass, EAGER_ATOM_AND_CLASP(Array)}, {js_InitBooleanClass, EAGER_ATOM_AND_CLASP(Boolean)}, {js_InitDateClass, EAGER_ATOM_AND_CLASP(Date)}, {js_InitMathClass, EAGER_ATOM_AND_CLASP(Math)}, {js_InitNumberClass, EAGER_ATOM_AND_CLASP(Number)}, {js_InitStringClass, EAGER_ATOM_AND_CLASP(String)}, {js_InitExceptionClasses, EAGER_ATOM_AND_CLASP(Error)}, {js_InitRegExpClass, EAGER_ATOM_AND_CLASP(RegExp)}, -#if JS_HAS_XML_SUPPORT - {js_InitXMLClass, EAGER_ATOM_AND_CLASP(XML)}, - {js_InitNamespaceClass, EAGER_ATOM_AND_CLASP(Namespace)}, - {js_InitQNameClass, EAGER_ATOM_AND_CLASP(QName)}, -#endif #if JS_HAS_GENERATORS {js_InitIteratorClasses, EAGER_ATOM_AND_CLASP(StopIteration)}, #endif {js_InitJSONClass, EAGER_ATOM_AND_CLASP(JSON)}, {js_InitTypedArrayClasses, EAGER_CLASS_ATOM(ArrayBuffer), &js::ArrayBufferObject::protoClass}, {js_InitWeakMapClass, EAGER_ATOM_AND_CLASP(WeakMap)}, {js_InitMapClass, EAGER_CLASS_ATOM(Map), &js::MapObject::class_}, {js_InitSetClass, EAGER_CLASS_ATOM(Set), &js::SetObject::class_}, @@ -1846,21 +1833,16 @@ static JSStdName standard_class_names[] {js_InitExceptionClasses, EAGER_CLASS_ATOM(InternalError), CLASP(Error)}, {js_InitExceptionClasses, EAGER_CLASS_ATOM(EvalError), CLASP(Error)}, {js_InitExceptionClasses, EAGER_CLASS_ATOM(RangeError), CLASP(Error)}, {js_InitExceptionClasses, EAGER_CLASS_ATOM(ReferenceError), CLASP(Error)}, {js_InitExceptionClasses, EAGER_CLASS_ATOM(SyntaxError), CLASP(Error)}, {js_InitExceptionClasses, EAGER_CLASS_ATOM(TypeError), CLASP(Error)}, {js_InitExceptionClasses, EAGER_CLASS_ATOM(URIError), CLASP(Error)}, -#if JS_HAS_XML_SUPPORT - {js_InitXMLClass, EAGER_ATOM(XMLList), CLASP(XML)}, - {js_InitXMLClass, EAGER_ATOM(isXMLName), CLASP(XML)}, -#endif - {js_InitIteratorClasses, EAGER_CLASS_ATOM(Iterator), &PropertyIteratorObject::class_}, /* Typed Arrays */ {js_InitTypedArrayClasses, EAGER_CLASS_ATOM(ArrayBuffer), &ArrayBufferClass}, {js_InitTypedArrayClasses, EAGER_CLASS_ATOM(Int8Array), TYPED_ARRAY_CLASP(TYPE_INT8)}, {js_InitTypedArrayClasses, EAGER_CLASS_ATOM(Uint8Array), TYPED_ARRAY_CLASP(TYPE_UINT8)}, {js_InitTypedArrayClasses, EAGER_CLASS_ATOM(Int16Array), TYPED_ARRAY_CLASP(TYPE_INT16)}, {js_InitTypedArrayClasses, EAGER_CLASS_ATOM(Uint16Array), TYPED_ARRAY_CLASP(TYPE_UINT16)}, @@ -1984,26 +1966,16 @@ JS_ResolveStandardClass(JSContext *cx, J */ JS_ASSERT(obj->isGlobal()); if (stdnm->clasp->flags & JSCLASS_IS_ANONYMOUS) return true; if (IsStandardClassResolved(obj, stdnm->clasp)) return true; -#if JS_HAS_XML_SUPPORT - if ((stdnm->init == js_InitXMLClass || - stdnm->init == js_InitNamespaceClass || - stdnm->init == js_InitQNameClass) && - !VersionHasAllowXML(cx->findVersion())) - { - return true; - } -#endif - if (!stdnm->init(cx, obj)) return false; *resolved = true; } return true; } JS_PUBLIC_API(JSBool) @@ -2025,25 +1997,17 @@ JS_EnumerateStandardClasses(JSContext *c JS_PropertyStub, JS_StrictPropertyStub, JSPROP_PERMANENT | JSPROP_READONLY)) { return false; } /* Initialize any classes that have not been initialized yet. */ for (unsigned i = 0; standard_class_atoms[i].init; i++) { const JSStdName &stdnm = standard_class_atoms[i]; - if (!js::IsStandardClassResolved(obj, stdnm.clasp) -#if JS_HAS_XML_SUPPORT - && ((stdnm.init != js_InitXMLClass && - stdnm.init != js_InitNamespaceClass && - stdnm.init != js_InitQNameClass) || - VersionHasAllowXML(cx->findVersion())) -#endif - ) - { + if (!js::IsStandardClassResolved(obj, stdnm.clasp)) { if (!stdnm.init(cx, obj)) return false; } } return true; } @@ -2521,22 +2485,16 @@ JS_GetTraceThingInfo(char *buf, size_t b case JSTRACE_BASE_SHAPE: name = "base_shape"; break; case JSTRACE_TYPE_OBJECT: name = "type_object"; break; - -#if JS_HAS_XML_SUPPORT - case JSTRACE_XML: - name = "xml"; - break; -#endif } n = strlen(name); if (n > bufsize - 1) n = bufsize - 1; js_memcpy(buf, name, n + 1); buf += n; bufsize -= n; @@ -2588,27 +2546,16 @@ JS_GetTraceThingInfo(char *buf, size_t b break; } case JSTRACE_IONCODE: case JSTRACE_SHAPE: case JSTRACE_BASE_SHAPE: case JSTRACE_TYPE_OBJECT: break; - -#if JS_HAS_XML_SUPPORT - case JSTRACE_XML: - { - extern const char *js_xml_class_str[]; - JSXML *xml = (JSXML *)thing; - - JS_snprintf(buf, bufsize, " %s", js_xml_class_str[xml->xml_class]); - break; - } -#endif } } buf[bufsize - 1] = '\0'; } extern JS_PUBLIC_API(const char *) JS_GetTraceEdgeName(JSTracer *trc, char *buffer, int bufferSize) {
--- a/js/src/jsapi.h +++ b/js/src/jsapi.h @@ -1063,18 +1063,18 @@ class JS_PUBLIC_API(AutoGCRooter) { enum { JSVAL = -1, /* js::AutoValueRooter */ VALARRAY = -2, /* js::AutoValueArrayRooter */ PARSER = -3, /* js::frontend::Parser */ SHAPEVECTOR = -4, /* js::AutoShapeVector */ IDARRAY = -6, /* js::AutoIdArray */ DESCRIPTORS = -7, /* js::AutoPropDescArrayRooter */ - NAMESPACES = -8, /* js::AutoNamespaceArray */ - XML = -9, /* js::AutoXMLRooter */ + // UNUSED -8 + // UNUSED -9 OBJECT = -10, /* js::AutoObjectRooter */ ID = -11, /* js::AutoIdRooter */ VALVECTOR = -12, /* js::AutoValueVector */ DESCRIPTOR = -13, /* js::AutoPropertyDescriptorRooter */ STRING = -14, /* js::AutoStringRooter */ IDVECTOR = -15, /* js::AutoIdVector */ OBJVECTOR = -16, /* js::AutoObjectVector */ STRINGVECTOR =-17, /* js::AutoStringVector */ @@ -2379,31 +2379,28 @@ JS_NumberValue(double d) return INT_TO_JSVAL(i); return DOUBLE_TO_JSVAL(d); } /************************************************************************/ /* * A jsid is an identifier for a property or method of an object which is - * either a 31-bit signed integer, interned string or object. If XML is - * enabled, there is an additional singleton jsid value; see - * JS_DEFAULT_XML_NAMESPACE_ID below. Finally, there is an additional jsid - * value, JSID_VOID, which does not occur in JS scripts but may be used to - * indicate the absence of a valid jsid. + * either a 31-bit signed integer, interned string or object. Also, there is + * an additional jsid value, JSID_VOID, which does not occur in JS scripts but + * may be used to indicate the absence of a valid jsid. * * A jsid is not implicitly convertible to or from a jsval; JS_ValueToId or * JS_IdToValue must be used instead. */ #define JSID_TYPE_STRING 0x0 #define JSID_TYPE_INT 0x1 #define JSID_TYPE_VOID 0x2 #define JSID_TYPE_OBJECT 0x4 -#define JSID_TYPE_DEFAULT_XML_NAMESPACE 0x6 #define JSID_TYPE_MASK 0x7 /* * Avoid using canonical 'id' for jsid parameters since this is a magic word in * Objective-C++ which, apparently, wants to be able to #include jsapi.h. */ #define id iden @@ -2502,35 +2499,16 @@ JSID_IS_GCTHING(jsid id) static JS_ALWAYS_INLINE void * JSID_TO_GCTHING(jsid id) { return (void *)(JSID_BITS(id) & ~(size_t)JSID_TYPE_MASK); } /* - * The magic XML namespace id is not a valid jsid. Global object classes in - * embeddings that enable JS_HAS_XML_SUPPORT (E4X) should handle this id. - */ - -static JS_ALWAYS_INLINE JSBool -JSID_IS_DEFAULT_XML_NAMESPACE(jsid id) -{ - JS_ASSERT_IF(((size_t)JSID_BITS(id) & JSID_TYPE_MASK) == JSID_TYPE_DEFAULT_XML_NAMESPACE, - JSID_BITS(id) == JSID_TYPE_DEFAULT_XML_NAMESPACE); - return ((size_t)JSID_BITS(id) == JSID_TYPE_DEFAULT_XML_NAMESPACE); -} - -#ifdef JS_USE_JSID_STRUCT_TYPES -extern JS_PUBLIC_DATA(jsid) JS_DEFAULT_XML_NAMESPACE_ID; -#else -# define JS_DEFAULT_XML_NAMESPACE_ID ((jsid)JSID_TYPE_DEFAULT_XML_NAMESPACE) -#endif - -/* * A void jsid is not a valid id and only arises as an exceptional API return * value, such as in JS_NextProperty. Embeddings must not pass JSID_VOID into * JSAPI entry points expecting a jsid and do not need to handle JSID_VOID in * hooks receiving a jsid except when explicitly noted in the API contract. */ static JS_ALWAYS_INLINE JSBool JSID_IS_VOID(const js::RawId id) @@ -3160,26 +3138,21 @@ JS_StringToVersion(const char *string); promises to execute compiled script once only; enables compile-time scope chain resolution of consts. */ #define JSOPTION_ATLINE JS_BIT(5) /* //@line number ["filename"] option supported for the XUL preprocessor and kindred beasts. */ -#define JSOPTION_ALLOW_XML JS_BIT(6) /* enable E4X syntax (deprecated) - and define the E4X-related - globals: XML, XMLList, - Namespace, etc. */ -#define JSOPTION_MOAR_XML JS_BIT(7) /* enable E4X even in versions - that don't normally get it; - parse <!-- --> 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 uncaught exceptions from being converted to error reports */ /* JS_BIT(9) is currently unused. */ @@ -3211,17 +3184,17 @@ JS_StringToVersion(const char *string); #define JSOPTION_STRICT_MODE JS_BIT(19) /* Provides a way to force strict mode for all code without requiring "use strict" annotations. */ #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) extern JS_PUBLIC_API(uint32_t) JS_GetOptions(JSContext *cx); extern JS_PUBLIC_API(uint32_t)
--- a/js/src/jsarray.cpp +++ b/js/src/jsarray.cpp @@ -88,17 +88,17 @@ js::GetLengthProperty(JSContext *cx, Han *lengthp = uint32_t(value.toInt32()); /* uint32_t cast does ToUint32_t */ return true; } return ToUint32(cx, value, (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): * * "Array objects give special treatment to a certain class of property names. * A property name P (in the form of a string value) is an array index if and * only if ToString(ToUint32(P)) is equal to P and ToUint32(P) is not equal * to 2^32-1." *
--- a/js/src/jsast.tbl +++ b/js/src/jsast.tbl @@ -61,28 +61,9 @@ ASTDEF(AST_LET_STMT, "LetSt ASTDEF(AST_CASE, "SwitchCase", "switchCase") ASTDEF(AST_CATCH, "CatchClause", "catchClause") ASTDEF(AST_COMP_BLOCK, "ComprehensionBlock", "comprehensionBlock") ASTDEF(AST_ARRAY_PATT, "ArrayPattern", "arrayPattern") 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 */
--- a/js/src/jsatom.cpp +++ b/js/src/jsatom.cpp @@ -19,17 +19,16 @@ #include "jsapi.h" #include "jsatom.h" #include "jscntxt.h" #include "jsgc.h" #include "jslock.h" #include "jsnum.h" #include "jsstr.h" #include "jsversion.h" -#include "jsxml.h" #include "frontend/Parser.h" #include "gc/Marking.h" #include "vm/Xdr.h" #include "jsstrinlines.h" #include "jsatominlines.h" #include "jsobjinlines.h" @@ -52,17 +51,16 @@ js_AtomToPrintableString(JSContext *cx, const char * js::TypeStrings[] = { js_undefined_str, js_object_str, js_function_str, js_string_str, 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; JS_FOR_EACH_PROTOTYPE(DEFINE_PROTO_STRING) #undef DEFINE_PROTO_STRING #define CONST_CHAR_STR(idpart, id, text) const char js_##idpart##_str[] = text; FOR_EACH_COMMON_PROPERTYNAME(CONST_CHAR_STR) @@ -447,42 +445,16 @@ template bool js::IndexToIdSlow<NoGC>(JSContext *cx, uint32_t index, FakeMutableHandle<jsid> idp); template <AllowGC allowGC> bool js::InternNonIntElementId(JSContext *cx, JSObject *obj, const Value &idval, typename MaybeRooted<jsid, allowGC>::MutableHandleType idp, typename MaybeRooted<Value, allowGC>::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<allowGC>(cx, idval); if (!atom) return false; idp.set(AtomToId(atom)); vp.setString(atom); return true; }
--- a/js/src/jsclass.h +++ b/js/src/jsclass.h @@ -28,32 +28,31 @@ static JS_ALWAYS_INLINE jsid SPECIALID_TO_JSID(const SpecialId &sid); /* * We partition the ways to refer to a property into three: by an index * (uint32_t); by a string whose characters do not represent an index * (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 { uintptr_t bits; /* Needs access to raw bits. */ friend JS_ALWAYS_INLINE jsid SPECIALID_TO_JSID(const SpecialId &sid); friend class PropertyId; 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) { } public: SpecialId() : bits(TYPE_VOID) { } /* Object-valued */ @@ -92,61 +91,45 @@ class SpecialId SpecialId sid(TYPE_VOID); JS_ASSERT(sid.isVoid()); return sid; } 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 SPECIALID_TO_JSID(const SpecialId &sid) { jsid id; JSID_BITS(id) = sid.bits; 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 JSID_TO_SPECIALID(jsid id) { JS_ASSERT(JSID_IS_SPECIAL(id)); if (JSID_IS_OBJECT(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<SpecialId> HandleSpecialId; /* js::Class operation signatures. */ typedef JSBool (* LookupGenericOp)(JSContext *cx, HandleObject obj, HandleId id,
--- a/js/src/jscntxt.h +++ b/js/src/jscntxt.h @@ -874,24 +874,16 @@ struct JSRuntime : js::RuntimeFriendFiel bool gcIncrementalEnabled; /* * GGC can be enabled from the command line while testing. */ 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 * dead compartments. */ bool gcManipulatingDeadCompartments; /* * This field is incremented each time we mark an object inside a @@ -1284,75 +1276,35 @@ struct JSRuntime : js::RuntimeFriendFiel /* Common macros to access thread-local caches in JSRuntime. */ #define JS_KEEP_ATOMS(rt) (rt)->gcKeepAtoms++; #define JS_UNKEEP_ATOMS(rt) (rt)->gcKeepAtoms--; 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 * appropriately compared in the eval cache across global option changes. An * example of the latter is enabling the top-level-anonymous-function-is-error * option: subsequent evals of the same, previously-valid script text may have * become invalid. */ 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 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) { return JSVersion(uint32_t(version) & ~VersionFlags::MASK); } static inline void VersionCopyFlags(JSVersion *version, JSVersion from) @@ -1364,32 +1316,25 @@ static inline bool VersionHasFlags(JSVersion version) { return !!VersionExtractFlags(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; } 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 VersionIsKnown(JSVersion version) { return VersionNumber(version) != JSVERSION_UNKNOWN; } @@ -1784,35 +1729,16 @@ struct AutoResolving { JSContext *const context; HandleObject object; HandleId id; Kind const kind; AutoResolving *const link; 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) #else # define JS_LOCK_GC(rt) do { } while (0) # define JS_UNLOCK_GC(rt) do { } while (0) #endif
--- a/js/src/jscntxtinlines.h +++ b/js/src/jscntxtinlines.h @@ -8,17 +8,16 @@ #ifndef jscntxtinlines_h___ #define jscntxtinlines_h___ #include "jscntxt.h" #include "jscompartment.h" #include "jsfriendapi.h" #include "jsinterp.h" #include "jsprobes.h" -#include "jsxml.h" #include "jsgc.h" #include "builtin/Object.h" // For js::obj_construct #include "frontend/ParseMaps.h" #include "vm/RegExpObject.h" #include "jsgcinlines.h" @@ -130,41 +129,16 @@ struct PreserveRegsGuard FrameRegs *prevContextRegs; private: JSContext *cx; 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<JSObject> array; -}; - -#endif /* JS_HAS_XML_SUPPORT */ - #ifdef JS_CRASH_DIAGNOSTICS class CompartmentChecker { JSContext *context; JSCompartment *compartment; public: explicit CompartmentChecker(JSContext *cx)
--- a/js/src/jsfriendapi.cpp +++ b/js/src/jsfriendapi.cpp @@ -496,25 +496,16 @@ js::SetPreserveWrapperCallback(JSRuntime rt->preserveWrapperCallback = callback; } /* * The below code is for temporary telemetry use. It can be removed when * 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; } JS_FRIEND_API(size_t) JS_SetProtoCalled(JSContext *) { @@ -713,23 +704,16 @@ js::DumpHeapComplete(JSRuntime *rt, FILE } JS_FRIEND_API(const JSStructuredCloneCallbacks *) 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) { return !!cx->runtime->debugHooks.debuggerHandler; } JS_FRIEND_API(JSTrapStatus) js::CallContextDebugHandler(JSContext *cx, JSScript *script, jsbytecode *bc, Value *rval)
--- a/js/src/jsfriendapi.h +++ b/js/src/jsfriendapi.h @@ -46,19 +46,16 @@ JS_SplicePrototype(JSContext *cx, JSObje extern JS_FRIEND_API(JSObject *) JS_NewObjectWithUniqueType(JSContext *cx, JSClass *clasp, JSObject *proto, JSObject *parent); 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); extern JS_FRIEND_API(size_t) JS_GetCustomIteratorCount(JSContext *cx); extern JS_FRIEND_API(JSBool) JS_NondeterministicGetWeakMapKeys(JSContext *cx, JSObject *obj, JSObject **ret); @@ -350,27 +347,22 @@ struct Function { struct Atom { size_t _; const jschar *chars; }; } /* 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 * GetObjectClass(RawObject obj) { return reinterpret_cast<const shadow::Object*>(obj)->type->clasp; } @@ -707,19 +699,16 @@ typedef void * idle and a request begins. */ JS_FRIEND_API(void) 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); extern JS_FRIEND_API(JSTrapStatus) CallContextDebugHandler(JSContext *cx, JSScript *script, jsbytecode *bc, Value *rval); extern JS_FRIEND_API(bool) IsContextRunningJS(JSContext *cx); @@ -1357,17 +1346,17 @@ static JS_ALWAYS_INLINE Value IdToValue(jsid id) { if (JSID_IS_STRING(id)) return StringValue(JSID_TO_STRING(id)); if (JS_LIKELY(JSID_IS_INT(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(); } static JS_ALWAYS_INLINE jsval IdToJsval(jsid id) { return IdToValue(id); }
--- a/js/src/jsgc.cpp +++ b/js/src/jsgc.cpp @@ -63,19 +63,16 @@ #include "jslock.h" #include "jsnum.h" #include "jsobj.h" #include "jsprobes.h" #include "jsproxy.h" #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" #include "gc/FindSCCs.h" #include "gc/GCInternals.h" #include "gc/Marking.h" #include "gc/Memory.h" #include "methodjit/MethodJIT.h" @@ -143,19 +140,16 @@ const uint32_t Arena::ThingSizes[] = { sizeof(JSObject_Slots12), /* FINALIZE_OBJECT12 */ sizeof(JSObject_Slots12), /* FINALIZE_OBJECT12_BACKGROUND */ sizeof(JSObject_Slots16), /* FINALIZE_OBJECT16 */ sizeof(JSObject_Slots16), /* FINALIZE_OBJECT16_BACKGROUND */ sizeof(JSScript), /* FINALIZE_SCRIPT */ 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 */ sizeof(ion::IonCode), /* FINALIZE_IONCODE */ }; #define OFFSET(type) uint32_t(sizeof(ArenaHeader) + (ArenaSize - sizeof(ArenaHeader)) % sizeof(type)) @@ -171,19 +165,16 @@ const uint32_t Arena::FirstThingOffsets[ OFFSET(JSObject_Slots12), /* FINALIZE_OBJECT12 */ OFFSET(JSObject_Slots12), /* FINALIZE_OBJECT12_BACKGROUND */ OFFSET(JSObject_Slots16), /* FINALIZE_OBJECT16 */ OFFSET(JSObject_Slots16), /* FINALIZE_OBJECT16_BACKGROUND */ OFFSET(JSScript), /* FINALIZE_SCRIPT */ 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 */ OFFSET(ion::IonCode), /* FINALIZE_IONCODE */ }; #undef OFFSET @@ -459,20 +450,16 @@ FinalizeArenas(FreeOp *fop, case FINALIZE_SCRIPT: return FinalizeTypedArenas<JSScript>(fop, src, dest, thingKind, budget); case FINALIZE_SHAPE: return FinalizeTypedArenas<Shape>(fop, src, dest, thingKind, budget); case FINALIZE_BASE_SHAPE: return FinalizeTypedArenas<BaseShape>(fop, src, dest, thingKind, budget); case FINALIZE_TYPE_OBJECT: return FinalizeTypedArenas<types::TypeObject>(fop, src, dest, thingKind, budget); -#if JS_HAS_XML_SUPPORT - case FINALIZE_XML: - return FinalizeTypedArenas<JSXML>(fop, src, dest, thingKind, budget); -#endif case FINALIZE_STRING: return FinalizeTypedArenas<JSString>(fop, src, dest, thingKind, budget); case FINALIZE_SHORT_STRING: return FinalizeTypedArenas<JSShortString>(fop, src, dest, thingKind, budget); case FINALIZE_EXTERNAL_STRING: return FinalizeTypedArenas<JSExternalString>(fop, src, dest, thingKind, budget); case FINALIZE_IONCODE: #ifdef JS_ION @@ -928,18 +915,18 @@ InitGCZeal(JSRuntime *rt) "Format: JS_GC_ZEAL=N[,F]\n" "N indicates \"zealousness\":\n" " 0: no additional GCs\n" " 1: additional GCs at common danger points\n" " 2: GC every F allocations (default: 100)\n" " 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" " 11: Verify post write barriers between instructions\n" " 12: Verify post write barriers between paints\n" " 13: Purge analysis state every F allocations (default: 100)\n"); return false; } @@ -1441,20 +1428,16 @@ ArenaLists::queueObjectsForSweep(FreeOp finalizeNow(fop, FINALIZE_OBJECT16); queueForBackgroundSweep(fop, FINALIZE_OBJECT0_BACKGROUND); queueForBackgroundSweep(fop, FINALIZE_OBJECT2_BACKGROUND); queueForBackgroundSweep(fop, FINALIZE_OBJECT4_BACKGROUND); 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 ArenaLists::queueStringsForSweep(FreeOp *fop) { gcstats::AutoPhase ap(fop->runtime()->gcStats, gcstats::PHASE_SWEEP_STRING); queueForBackgroundSweep(fop, FINALIZE_SHORT_STRING); @@ -4921,21 +4904,8 @@ AutoMaybeTouchDeadCompartments::~AutoMay { if (inIncremental && runtime->gcObjectsMarkedInDeadCompartments != markCount) { PrepareForFullGC(runtime); js::GC(runtime, GC_NORMAL, gcreason::TRANSPLANT); } runtime->gcManipulatingDeadCompartments = manipulatingDeadCompartments; } - -#if JS_HAS_XML_SUPPORT -extern size_t sE4XObjectsCreated; - -JSXML * -js_NewGCXML(JSContext *cx) -{ - if (!cx->runningWithTrustedPrincipals()) - ++sE4XObjectsCreated; - - return NewGCThing<JSXML, CanGC>(cx, js::gc::FINALIZE_XML, sizeof(JSXML)); -} -#endif
--- a/js/src/jsgc.h +++ b/js/src/jsgc.h @@ -103,19 +103,16 @@ MapAllocToTraceKind(AllocKind kind) JSTRACE_OBJECT, /* FINALIZE_OBJECT12 */ JSTRACE_OBJECT, /* FINALIZE_OBJECT12_BACKGROUND */ JSTRACE_OBJECT, /* FINALIZE_OBJECT16 */ JSTRACE_OBJECT, /* FINALIZE_OBJECT16_BACKGROUND */ JSTRACE_SCRIPT, /* FINALIZE_SCRIPT */ 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 */ JSTRACE_IONCODE, /* FINALIZE_IONCODE */ }; JS_STATIC_ASSERT(JS_ARRAY_LENGTH(map) == FINALIZE_LIMIT); return map[kind]; } @@ -137,19 +134,16 @@ IsNurseryAllocable(AllocKind kind) false, /* FINALIZE_OBJECT12 */ true, /* FINALIZE_OBJECT12_BACKGROUND */ false, /* FINALIZE_OBJECT16 */ true, /* FINALIZE_OBJECT16_BACKGROUND */ false, /* FINALIZE_SCRIPT */ 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 */ false, /* FINALIZE_IONCODE */ }; JS_STATIC_ASSERT(JS_ARRAY_LENGTH(map) == FINALIZE_LIMIT); return map[kind]; } @@ -171,19 +165,16 @@ IsBackgroundFinalized(AllocKind kind) false, /* FINALIZE_OBJECT12 */ true, /* FINALIZE_OBJECT12_BACKGROUND */ false, /* FINALIZE_OBJECT16 */ true, /* FINALIZE_OBJECT16_BACKGROUND */ false, /* FINALIZE_SCRIPT */ 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 */ false, /* FINALIZE_IONCODE */ }; JS_STATIC_ASSERT(JS_ARRAY_LENGTH(map) == FINALIZE_LIMIT); return map[kind]; } @@ -999,23 +990,16 @@ struct GCMarker : public JSTracer { void pushArenaList(gc::ArenaHeader *firstArena) { pushTaggedPtr(ArenaTag, firstArena); } void pushType(types::TypeObject *type) { pushTaggedPtr(TypeTag, type); } -#if JS_HAS_XML_SUPPORT - void pushXML(JSXML *xml) { - pushTaggedPtr(XmlTag, xml); - } - -#endif - void pushIonCode(ion::IonCode *code) { pushTaggedPtr(IonCodeTag, code); } uint32_t getMarkColor() const { return color; } @@ -1110,17 +1094,17 @@ struct GCMarker : public JSTracer { bool restoreValueArray(JSObject *obj, void **vpp, void **endp); void saveValueRanges(); inline void processMarkStackTop(SliceBudget &budget); void processMarkStackOther(SliceBudget &budget, uintptr_t tag, uintptr_t addr); 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<bool> started; /* Pointer to the top of the stack of arenas we are delaying marking on. */ js::gc::ArenaHeader *unmarkedArenaStackTop; /* Count of arenas that are currently in the stack. */ mozilla::DebugOnly<size_t> markLaterArenas; @@ -1192,18 +1176,20 @@ SetDeterministicGC(JSContext *cx, bool e void SetValidateGC(JSContext *cx, bool enabled); const int ZealPokeValue = 1; 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; const int ZealVerifierPostValue = 11; const int ZealFrameVerifierPostValue = 12; const int ZealPurgeAnalysisValue = 13; const int ZealLimit = 13;
--- a/js/src/jsgcinlines.h +++ b/js/src/jsgcinlines.h @@ -6,17 +6,16 @@ #ifndef jsgcinlines_h___ #define jsgcinlines_h___ #include "jsgc.h" #include "jscntxt.h" #include "jscompartment.h" #include "jslock.h" -#include "jsxml.h" #include "gc/Root.h" #include "js/TemplateLib.h" #include "vm/Shape.h" using JS::AssertCanGC; namespace js { @@ -599,14 +598,9 @@ js_NewGCShape(JSContext *cx) template <js::AllowGC allowGC> inline js::UnrootedBaseShape js_NewGCBaseShape(JSContext *cx) { return js::gc::NewGCThing<js::BaseShape, allowGC>(cx, js::gc::FINALIZE_BASE_SHAPE, sizeof(js::BaseShape)); } -#if JS_HAS_XML_SUPPORT -extern JSXML * -js_NewGCXML(JSContext *cx); -#endif - #endif /* jsgcinlines_h___ */
--- a/js/src/jsinfer.cpp +++ b/js/src/jsinfer.cpp @@ -40,20 +40,16 @@ #include "jsatominlines.h" #include "jsgcinlines.h" #include "jsinferinlines.h" #include "jsobjinlines.h" #include "jsscriptinlines.h" #include "vm/Stack-inl.h" -#ifdef JS_HAS_XML_SUPPORT -#include "jsxml.h" -#endif - #ifdef __SUNPRO_CC #include <alloca.h> #endif using namespace js; using namespace js::types; using namespace js::analyze; @@ -3986,19 +3982,16 @@ ScriptAnalysis::analyzeTypesBytecode(JSC case JSOP_RETRVAL: case JSOP_ENDITER: case JSOP_THROWING: case JSOP_GOSUB: case JSOP_RETSUB: 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: case JSOP_TABLESWITCH: case JSOP_TRY: case JSOP_LABEL: break; @@ -4030,31 +4023,24 @@ ScriptAnalysis::analyzeTypesBytecode(JSC case JSOP_LE: case JSOP_GT: case JSOP_GE: case JSOP_NOT: case JSOP_STRICTEQ: case JSOP_STRICTNE: case JSOP_IN: case JSOP_INSTANCEOF: - case JSOP_DELDESC: pushed[0].addType(cx, Type::BooleanType()); break; case JSOP_DOUBLE: pushed[0].addType(cx, Type::DoubleType()); break; 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: pushed[0].addType(cx, Type::NullType()); break; case JSOP_REGEXP: if (script->compileAndGo) { @@ -4634,49 +4620,16 @@ ScriptAnalysis::analyzeTypesBytecode(JSC case JSOP_GENERATOR: TypeScript::ReturnTypes(script)->addType(cx, Type::UnknownType()); break; case JSOP_YIELD: 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; default: /* Display fine-grained debug information first */ fprintf(stderr, "Unknown bytecode %02x at #%u:%05u\n", op, script->id(), offset); TypeFailure(cx, "Unknown bytecode %02x", op); @@ -5714,17 +5667,16 @@ types::TypeMonitorResult(JSContext *cx, static inline bool IgnorePushed(const jsbytecode *pc, unsigned index) { switch (JSOp(*pc)) { /* We keep track of the scopes pushed by BINDNAME separately. */ case JSOP_BINDNAME: case JSOP_BINDGNAME: case JSOP_BINDINTRINSIC: - case JSOP_BINDXMLNAME: return true; /* Stack not consistent in TRY_BRANCH_AFTER_COND. */ case JSOP_IN: case JSOP_EQ: case JSOP_NE: case JSOP_LT: case JSOP_LE: @@ -5735,18 +5687,16 @@ IgnorePushed(const jsbytecode *pc, unsig /* Value not determining result is not pushed by OR/AND. */ case JSOP_OR: case JSOP_AND: return (index == 0); /* 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: case JSOP_ENTERBLOCK: case JSOP_ENTERLET0: case JSOP_ENTERLET1: return true; @@ -6061,25 +6011,16 @@ JSObject::makeLazyType(JSContext *cx) type->interpretedFunction = self->toFunction(); if (type->interpretedFunction->nonLazyScript()->uninlineable) type->flags |= OBJECT_FLAG_UNINLINEABLE; } 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()) type->flags |= OBJECT_FLAG_EMULATES_UNDEFINED; /* * Adjust flags for objects which will have the wrong flags set by just * looking at the class prototype key. @@ -6210,22 +6151,16 @@ JSCompartment::getNewType(JSContext *cx, RootedObject obj(cx, proto.toObject()); if (obj->hasSpecialEquality()) type->flags |= OBJECT_FLAG_SPECIAL_EQUALITY; 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()); AddTypeProperty(cx, type, "ignoreCase", types::Type::BooleanType()); AddTypeProperty(cx, type, "multiline", types::Type::BooleanType()); AddTypeProperty(cx, type, "sticky", types::Type::BooleanType()); AddTypeProperty(cx, type, "lastIndex", types::Type::Int32Type()); }
--- a/js/src/jsinterp.cpp +++ b/js/src/jsinterp.cpp @@ -61,20 +61,16 @@ #include "jsscriptinlines.h" #include "jstypedarrayinlines.h" #include "builtin/Iterator-inl.h" #include "vm/Shape-inl.h" #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) #include "methodjit/MonoIC.h" #endif #if JS_TRACE_LOGGING #include "TraceLogging.h" @@ -200,25 +196,16 @@ js::OnUnknownMethod(JSContext *cx, Handl RootedValue value(cx); if (!GetMethod(cx, obj, id, 0, &value)) return false; TypeScript::MonitorUnknown(cx); 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; obj->setSlot(JSSLOT_FOUND_FUNCTION, value); obj->setSlot(JSSLOT_SAVED_ID, idval); vp.setObject(*obj); } @@ -587,27 +574,16 @@ js::HasInstance(JSContext *cx, HandleObj js_ReportValueError(cx, JSMSG_BAD_INSTANCEOF_RHS, JSDVG_SEARCH_STACK, val, NullPtr()); return JS_FALSE; } 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(); JSString *r = rval.toString(); return EqualStrings(cx, l, r, result); } if (lval.isDouble()) { @@ -961,17 +937,16 @@ js::AssertValidPropertyCacheHit(JSContex /* * Ensure that the intrepreter switch can close call-bytecode cases in the * same way as non-call bytecodes. */ 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 * remain distinct for the decompiler. */ JS_STATIC_ASSERT(JSOP_SETNAME_LENGTH == JSOP_SETPROP_LENGTH); /* See TRY_BRANCH_AFTER_COND. */ @@ -1341,35 +1316,54 @@ js::Interpret(JSContext *cx, StackFrame /* No-ops for ease of decompilation. */ ADD_EMPTY_CASE(JSOP_NOP) ADD_EMPTY_CASE(JSOP_UNUSED71) 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) ADD_EMPTY_CASE(JSOP_UNUSED200) ADD_EMPTY_CASE(JSOP_UNUSED201) ADD_EMPTY_CASE(JSOP_UNUSED208) ADD_EMPTY_CASE(JSOP_UNUSED209) ADD_EMPTY_CASE(JSOP_UNUSED210) ADD_EMPTY_CASE(JSOP_UNUSED219) ADD_EMPTY_CASE(JSOP_UNUSED220) ADD_EMPTY_CASE(JSOP_UNUSED221) 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) #ifdef JS_METHODJIT script->incrLoopCount(); #endif END_CASE(JSOP_LOOPHEAD) @@ -1611,22 +1605,16 @@ BEGIN_CASE(JSOP_AND) bool cond = ToBoolean(regs.sp[-1]); if (cond == false) { len = GET_JUMP_OFFSET(regs.pc); DO_NEXT_OP(len); } } 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]; \ if (!ValueToId<CanGC>(cx, obj, idval_, &id)) \ goto error; \ JS_END_MACRO #define TRY_BRANCH_AFTER_COND(cond,spdec) \ @@ -2134,20 +2122,19 @@ BEGIN_CASE(JSOP_DELELEM) regs.sp--; } 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]; idval = regs.sp[-1]; MutableHandleValue res = MutableHandleValue::fromMarkedLocation(®s.sp[-1]); if (!ToIdOperation(cx, script, regs.pc, objval, idval, res)) goto error; @@ -3121,349 +3108,16 @@ BEGIN_CASE(JSOP_DEBUGGER) case JSTRAP_THROW: cx->setPendingException(rval); goto error; default:; } } 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<CanGC>(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<CanGC>(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) { StaticBlockObject &blockObj = script->getObject(regs.pc)->asStaticBlock(); if (op == JSOP_ENTERBLOCK) { JS_ASSERT(regs.stackDepth() == blockObj.stackDepth());
--- a/js/src/jsinterpinlines.h +++ b/js/src/jsinterpinlines.h @@ -215,31 +215,16 @@ AssertValidPropertyCacheHit(JSContext *c #else inline void AssertValidPropertyCacheHit(JSContext *cx, JSObject *start, JSObject *found, PropertyCacheEntry *entry) {} #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) { /* Optimize length accesses on strings, arrays, and arguments. */ if (lval.isString()) { vp.setInt32(lval.toString()->length()); return true; } if (lval.isObject()) { @@ -299,17 +284,17 @@ GetPropertyOperation(JSContext *cx, JSSc } bool wasObject = lval.isObject(); RootedId id(cx, NameToId(name)); 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)) return false; } #if JS_HAS_NO_SUCH_METHOD if (op == JSOP_CALLPROP && @@ -572,25 +557,16 @@ AddOperation(JSContext *cx, HandleScript res->setDouble(double(l) + double(r)); types::TypeScript::MonitorOverflow(cx, script, pc); } else { res->setInt32(sum); } 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. */ bool lIsObject = lhs.isObject(), rIsObject = rhs.isObject(); if (!ToPrimitive(cx, lhs.address())) return false; @@ -762,30 +738,16 @@ ToIdOperation(JSContext *cx, HandleScrip return true; } static JS_ALWAYS_INLINE bool GetObjectElementOperation(JSContext *cx, JSOp op, JSObject *objArg, bool wasObject, 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(); uint32_t index; if (IsDefinitelyIndex(rref, &index)) { if (analyze && !objArg->isNative()) { JSScript *script = NULL; jsbytecode *pc = NULL;
--- a/js/src/jsiter.cpp +++ b/js/src/jsiter.cpp @@ -25,20 +25,16 @@ #include "jsiter.h" #include "jslock.h" #include "jsnum.h" #include "jsobj.h" #include "jsopcode.h" #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" #include "gc/Marking.h" #include "vm/GlobalObject.h" #include "vm/Shape.h" #include "jsinferinlines.h" @@ -146,21 +142,18 @@ EnumerateNativeProperties(JSContext *cx, size_t initialLength = props->length(); /* Collect all unique properties from this object's scope. */ Shape::Range r = pobj->lastProperty()->all(); Shape::Range::AutoRooter root(cx, &r); 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()); return true; } #ifdef JS_MORE_DETERMINISTIC @@ -259,20 +252,16 @@ Snapshot(JSContext *cx, RawObject pobj_, return false; } } } if (flags & JSITER_OWNONLY) break; -#if JS_HAS_XML_SUPPORT - if (pobj->isXML()) - break; -#endif } while ((pobj = pobj->getProto()) != NULL); #ifdef JS_MORE_DETERMINISTIC /* * In some cases the enumeration order for an object depends on the * execution mode (interpreter vs. JIT), especially for native objects * with a class enumerate hook (where resolving a property changes the
--- a/js/src/jsmemorymetrics.cpp +++ b/js/src/jsmemorymetrics.cpp @@ -59,19 +59,16 @@ CompartmentStats::gcHeapThingsSize() n += gcHeapStringsShort; n += gcHeapShapesTreeGlobalParented; n += gcHeapShapesTreeNonGlobalParented; n += gcHeapShapesDict; n += gcHeapShapesBase; n += gcHeapScripts; n += gcHeapTypeObjects; n += gcHeapIonCodes; -#if JS_HAS_XML_SUPPORT - n += gcHeapXML; -#endif #ifdef DEBUG size_t n2 = n; n2 += gcHeapArenaAdmin; n2 += gcHeapUnusedGcThings; // These numbers should sum to a multiple of the arena size. JS_ASSERT(n2 % gc::ArenaSize == 0); #endif @@ -244,23 +241,16 @@ StatsCellCallback(JSRuntime *rt, void *d } case JSTRACE_TYPE_OBJECT: { types::TypeObject *obj = static_cast<types::TypeObject *>(thing); cStats->gcHeapTypeObjects += thingSize; 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; } JS_PUBLIC_API(bool) JS::CollectRuntimeStats(JSRuntime *rt, RuntimeStats *rtStats, ObjectPrivateVisitor *opv) {
--- a/js/src/jsobj.cpp +++ b/js/src/jsobj.cpp @@ -37,17 +37,16 @@ #include "jsprototypes.h" #include "jsproxy.h" #include "jsscript.h" #include "jsstr.h" #include "jsdbgapi.h" #include "json.h" #include "jswatchpoint.h" #include "jswrapper.h" -#include "jsxml.h" #include "builtin/MapObject.h" #include "builtin/Module.h" #include "builtin/ParallelArray.h" #include "frontend/BytecodeCompiler.h" #include "frontend/Parser.h" #include "gc/Marking.h" #include "js/MemoryMetrics.h" @@ -2169,18 +2168,17 @@ js::DefineConstructorAndPrototype(JSCont RootedValue value(cx, ObjectValue(*fun)); if (!DefineStandardSlot(cx, obj, key, atom, value, 0, named)) goto bad; /* * 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)) goto bad; /* Bootstrap Function.prototype (see also JS_InitStandardClasses). */ Rooted<TaggedProto> tagged(cx, TaggedProto(proto)); if (ctor->getClass() == clasp && !ctor->splicePrototype(cx, clasp, tagged)) @@ -2786,23 +2784,16 @@ static JSClassInitializerOp lazy_prototy }; bool js::SetClassAndProto(JSContext *cx, HandleObject obj, Class *clasp, Handle<js::TaggedProto> proto, bool checkForCycles) { 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 * non-native object is found, prototype lookups will not be cached across * these. * * How this shape change is done is very delicate; the change can be made * either by marking the object's prototype as uncacheable (such that the @@ -3905,26 +3896,19 @@ baseops::GetPropertyDefault(JSContext *c } JSBool js::GetMethod(JSContext *cx, HandleObject obj, HandleId id, unsigned getHow, MutableHandleValue vp) { 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); } static bool MaybeReportUndeclaredVarAssignment(JSContext *cx, JSString *propname) { { UnrootedScript script = cx->stack.currentScript(NULL, ContextStack::ALLOW_CROSS_COMPARTMENT); @@ -4404,19 +4388,16 @@ MaybeCallMethod(JSContext *cx, HandleObj } return Invoke(cx, ObjectValue(*obj), vp, 0, NULL, vp.address()); } 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<jsid> id(cx); Class *clasp = obj->getClass(); if (hint == JSTYPE_STRING) { id = NameToId(cx->names().toString); /* Optimize (new String(...)).toString(). */
--- a/js/src/jsobj.h +++ b/js/src/jsobj.h @@ -232,17 +232,16 @@ extern Class ProxyClass; extern Class RegExpClass; extern Class RegExpStaticsClass; extern Class SetIteratorClass; extern Class StopIterationClass; extern Class StringClass; extern Class StrictArgumentsObjectClass; extern Class WeakMapClass; extern Class WithClass; -extern Class XMLFilterClass; class ArgumentsObject; class ArrayBufferObject; class BlockObject; class BooleanObject; class ClonedBlockObject; class DataViewObject; class DebugScopeObject; @@ -695,55 +694,16 @@ class JSObject : public js::ObjectImpl public: /* * Iterator-specific getters and setters. */ 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. */ inline bool isCallable(); inline void finish(js::FreeOp *fop); JS_ALWAYS_INLINE void finalize(js::FreeOp *fop); static inline bool hasProperty(JSContext *cx, js::HandleObject obj, @@ -1021,22 +981,16 @@ class JSObject : public js::ObjectImpl inline bool isRegExp() const; inline bool isRegExpStatics() const; inline bool isScope() const; inline bool isScript() const; inline bool isSetIterator() const; inline bool isStopIteration() const; inline bool isTypedArray() const; inline bool isWeakMap() const; -#if JS_HAS_XML_SUPPORT - inline bool isNamespace() const; - inline bool isQName() const; - inline bool isXML() const; - inline bool isXMLId() const; -#endif /* Subtypes of ScopeObject. */ inline bool isBlock() const; inline bool isCall() const; inline bool isDeclEnv() const; inline bool isNestedScope() const; inline bool isWith() const; inline bool isClonedBlock() const;
--- a/js/src/jsobjinlines.h +++ b/js/src/jsobjinlines.h @@ -17,17 +17,16 @@ #include "jslock.h" #include "jsnum.h" #include "jsobj.h" #include "jsprobes.h" #include "jspropertytree.h" #include "jsproxy.h" #include "jsstr.h" #include "jstypedarray.h" -#include "jsxml.h" #include "jswrapper.h" #include "builtin/MapObject.h" #include "builtin/Iterator-inl.h" #include "gc/Barrier.h" #include "gc/Marking.h" #include "gc/Root.h" #include "js/MemoryMetrics.h" @@ -744,107 +743,16 @@ JSObject::getDateUTCTime() const inline void JSObject::setDateUTCTime(const js::Value &time) { JS_ASSERT(isDate()); 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) { if (!cx->typeInferenceEnabled()) return true; JS_ASSERT(!obj->hasLazyType()); JS_ASSERT_IF(obj->getTaggedProto().isObject(), @@ -1027,37 +935,16 @@ JSObject::asString() inline bool JSObject::isDebugScope() const { extern bool js_IsDebugScopeSlow(js::RawObject obj); return getClass() == &js::ObjectProxyClass && js_IsDebugScopeSlow(const_cast<JSObject*>(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) { /* * Callers must use dynamicSlotsCount to size the initial slot array of the * object. We can't check the allocated capacity of the dynamic slots, but * make sure their presence is consistent with the shape. @@ -1478,35 +1365,16 @@ GetInnerObject(JSContext *cx, HandleObje inline JSObject * GetOuterObject(JSContext *cx, HandleObject obj) { if (JSObjectOp op = obj->getClass()->ext.outerObject) return op(cx, 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) { return v.isObject() && v.toObject().isStopIteration(); } static JS_ALWAYS_INLINE bool IsFunctionObject(const js::Value &v) @@ -1939,33 +1807,16 @@ ValueMightBeSpecial(const Value &propval { return propval.isObject(); } static JS_ALWAYS_INLINE bool ValueIsSpecial(JSObject *obj, MutableHandleValue propval, MutableHandle<SpecialId> 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; } JSObject * DefineConstructorAndPrototype(JSContext *cx, HandleObject obj, JSProtoKey key, HandleAtom atom, JSObject *protoProto, Class *clasp, Native constructor, unsigned nargs, JSPropertySpec *ps, JSFunctionSpec *fs,
--- a/js/src/json.cpp +++ b/js/src/json.cpp @@ -19,17 +19,16 @@ #include "jsnum.h" #include "jsobj.h" #include "json.h" #include "jsonparser.h" #include "jsprf.h" #include "jsstr.h" #include "jstypes.h" #include "jsutil.h" -#include "jsxml.h" #include "frontend/TokenStream.h" #include "vm/StringBuffer.h" #include "jsatominlines.h" #include "jsboolinlines.h" #include "jsinferinlines.h" #include "jsobjinlines.h" @@ -355,17 +354,17 @@ PreprocessValue(JSContext *cx, HandleObj * gauntlet will result in Str returning |undefined|. This function is used to * properly omit properties resulting in such values when stringifying objects, * while properly stringifying such properties as null when they're encountered * in arrays. */ static inline bool IsFilteredValue(const Value &v) { - return v.isUndefined() || js_IsCallable(v) || VALUE_IS_XML(v); + return v.isUndefined() || js_IsCallable(v); } /* ES5 15.12.3 JO. */ static JSBool JO(JSContext *cx, HandleObject obj, StringifyContext *scx) { /* * This method implements the JO algorithm in ES5 15.12.3, but:
--- a/js/src/jsopcode.cpp +++ b/js/src/jsopcode.cpp @@ -2101,24 +2101,20 @@ DecompileDestructuringLHS(SprintStack *s LOCAL_ASSERT(op == JSOP_ENUMELEM || op == JSOP_ENUMCONSTELEM); xval = PopStr(ss, JSOP_NOP); lval = PopStr(ss, JSOP_GETPROP); ss->sprinter.setOffset(todo); if (*lval == '\0') { /* 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; break; } } LOCAL_ASSERT(pc < endpc); @@ -2622,28 +2618,22 @@ Decompile(SprintStack *ss, jsbytecode *p int i, argc; RootedAtom atom(cx); JSObject *obj; RootedFunction fun(cx); JSString *str; 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"; static const char preindex_format[] = "%s%s[%s]"; static const char postindex_format[] = "%s[%s]%s"; static const char ss_format[] = "%s%s"; static const char sss_format[] = "%s%s%s"; @@ -2729,19 +2719,16 @@ Decompile(SprintStack *ss, jsbytecode *p endpc = (nb < 0) ? jp->script->code + jp->script->length : pc + nb; tail = -1; todo = -2; /* NB: different from Sprint() error return. */ saveop = JSOP_NOP; sn = NULL; rval = NULL; bool forOf = false; foreach = false; -#if JS_HAS_XML_SUPPORT - inXML = quoteAttr = false; -#endif while (nb < 0 || pc < endpc) { /* * Move saveop to lastop so prefixed bytecodes can take special action * while sharing maximal code. Set op and saveop to the new bytecode, * use op in POP_STR to trigger automatic parenthesization, but push * saveop at the bottom of the loop if this op pushes. Thus op may be * set to nop or otherwise mutated to suppress auto-parens. @@ -2836,19 +2823,16 @@ Decompile(SprintStack *ss, jsbytecode *p * uncategorized for our purposes, so we must write * per-op special case code here. */ switch (op) { case JSOP_ENUMELEM: case JSOP_ENUMCONSTELEM: op = JSOP_GETELEM; break; - case JSOP_SETXMLNAME: - op = JSOp(JSOP_GETELEM2); - break; default: LOCAL_ASSERT(0); } } } } saveop = op; @@ -2875,29 +2859,23 @@ Decompile(SprintStack *ss, jsbytecode *p * problem). */ op = (JSOp) pc[oplen]; rval = PopStr(ss, op, &lastrvalpc); (void)PopStr(ss, op, &lastlvalpc); /* 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; case 1: rval = PopStrDupe(ss, op, &rvalpc); todo = ss->sprinter.put(token); SprintOpcode(ss, rval, rvalpc, pc, todo); break; @@ -4169,21 +4147,17 @@ Decompile(SprintStack *ss, jsbytecode *p op = JSOP_GETELEM; /* lval must have high precedence */ lval = POP_STR(); op = saveop; rval = POP_STR(); LOCAL_ASSERT(strcmp(rval, forelem_cookie) == 0); 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; case JSOP_GETTER: case JSOP_SETTER: todo = -2; break; @@ -4447,33 +4421,19 @@ Decompile(SprintStack *ss, jsbytecode *p case JSOP_DELELEM: op = JSOP_NOP; /* turn off parens */ xval = POP_STR(); op = JSOP_GETPROP; 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: { const char *prefix = (op == JSOP_VOID) ? js_void_str : js_typeof_str; rval = PopStrDupe(ss, op, &rvalpc); todo = ss->sprinter.getOffset(); Sprint(&ss->sprinter, "%s ", prefix); @@ -4525,20 +4485,17 @@ Decompile(SprintStack *ss, jsbytecode *p case JSOP_INCELEM: case JSOP_DECELEM: op = JSOP_NOP; /* turn off parens */ xval = POP_STR(); 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 { todo = Sprint(&ss->sprinter, ss_format, js_incop_strs[!(cs->format & JOF_INC)], lval); } len += GetDecomposeLength(pc, JSOP_INCELEM_LENGTH); break; @@ -4586,21 +4543,17 @@ Decompile(SprintStack *ss, jsbytecode *p case JSOP_ELEMINC: case JSOP_ELEMDEC: op = JSOP_NOP; /* turn off parens */ xval = POP_STR(); 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, lval, js_incop_strs[!(cs->format & JOF_INC)]); } len += GetDecomposeLength(pc, JSOP_ELEMINC_LENGTH); break; @@ -4655,44 +4608,42 @@ Decompile(SprintStack *ss, jsbytecode *p op = JSOP_NOP; /* turn off parens */ xval = PopStrDupe(ss, op, &xvalpc); op = saveop; PROPAGATE_CALLNESS(); lval = PopStr(ss, op, &lvalpc); 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; case JSOP_SETELEM: { rval = PopStrDupe(ss, op, &rvalpc); op = JSOP_NOP; /* turn off parens */ xval = PopStrDupe(ss, op, &xvalpc); cs = &js_CodeSpec[ss->opcodes[ss->top]]; op = JSOP_GETELEM; /* lval must have high precedence */ lval = PopStr(ss, op, &lvalpc); op = saveop; 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; } case JSOP_CALLARG: case JSOP_GETARG: i = GET_ARGNO(pc); @@ -4709,21 +4660,18 @@ Decompile(SprintStack *ss, jsbytecode *p case JSOP_CALLNAME: case JSOP_NAME: case JSOP_GETGNAME: case JSOP_CALLGNAME: 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); todo = Sprint(&ss->sprinter, sss_format, VarPrefix(sn), lval, rval); break; case JSOP_UINT16: @@ -4748,17 +4696,17 @@ Decompile(SprintStack *ss, jsbytecode *p { val = jp->script->getConst(GET_UINT32_INDEX(pc)); todo = SprintDoubleValue(&ss->sprinter, val, &saveop); break; } 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); break; case JSOP_LAMBDA: #if JS_HAS_GENERATOR_EXPRS sn = js_GetSrcNote(cx, jp->script, pc); @@ -5261,182 +5209,16 @@ Decompile(SprintStack *ss, jsbytecode *p break; } case JSOP_DEBUGGER: js_printf(jp, "\tdebugger;\n"); 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("<![CDATA[", 9); - if (!QuoteString(&ss->sprinter, atom, DONT_ESCAPE)) - return NULL; - ss->sprinter.put("]]>", 3); - break; - - case JSOP_XMLCOMMENT: - LOAD_ATOM(0); - todo = ss->sprinter.put("<!--", 4); - if (!QuoteString(&ss->sprinter, atom, DONT_ESCAPE)) - return NULL; - 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("<?", 2); - ok = QuoteString(&ss->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); if (*pc == JSOP_UNDEFINED) pc += GetBytecodeLength(pc); if (*pc == JSOP_SETALIASEDVAR || *pc == JSOP_SETARG) { pc += GetBytecodeLength(pc); LOCAL_ASSERT(*pc == JSOP_POP); @@ -5467,29 +5249,22 @@ Decompile(SprintStack *ss, jsbytecode *p if (!UpdateDecompiledText(ss, pushpc, todo)) return NULL; if (!PushOff(ss, todo, saveop, pushpc)) return NULL; if (js_CodeSpec[*pc].format & JOF_DECOMPOSE) 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 #undef POP_STR_PREC #undef LOCAL_ASSERT #undef GET_QUOTE_AND_FMT #undef GET_ATOM_QUOTE_AND_FMT @@ -6420,17 +6195,16 @@ DecompileExpression(JSContext *cx, JSScr /* NAME ops are self-contained, others require left or right context. */ const JSCodeSpec *cs = &js_CodeSpec[op]; jsbytecode *begin = pc; jsbytecode *end = pc + cs->length; 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) return FAILED_EXPRESSION_DECOMPILER; switch (SN_TYPE(sn)) { case SRC_PCBASE: begin -= js_GetSrcNoteOffset(sn, 0); break;
--- a/js/src/jsopcode.h +++ b/js/src/jsopcode.h @@ -59,17 +59,16 @@ typedef enum JSOp { #define JOF_ATOMOBJECT 19 /* uint16_t constant index + object index */ #define JOF_UINT16PAIR 20 /* pair of uint16_t immediates */ #define JOF_SCOPECOORD 21 /* pair of uint16_t immediates followed by block index */ #define JOF_TYPEMASK 0x001f /* mask for above immediate types */ #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 */ #define JOF_DEC (1U<<10) /* decrement (--, not ++) opcode */ #define JOF_INC (2U<<10) /* increment (++, not --) opcode */ #define JOF_INCDEC (3U<<10) /* increment or decrement opcode */ #define JOF_POST (1U<<12) /* postorder increment or decrement */ #define JOF_ASSIGNING JOF_SET /* hint for Class.resolve, used for ops
--- a/js/src/jsopcode.tbl +++ b/js/src/jsopcode.tbl @@ -187,17 +187,17 @@ OPDEF(JSOP_SETCALL, 74, "setcall", */ OPDEF(JSOP_ITER, 75, "iter", NULL, 2, 1, 1, 0, JOF_UINT8) OPDEF(JSOP_MOREITER, 76, "moreiter", NULL, 1, 1, 2, 0, JOF_BYTE) OPDEF(JSOP_ITERNEXT, 77, "iternext", "<next>", 1, 0, 1, 0, JOF_BYTE) 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. */ OPDEF(JSOP_POP, 81, "pop", NULL, 1, 1, 0, 2, JOF_BYTE) /* Call a function as a constructor; operand is argc. */ OPDEF(JSOP_NEW, 82, js_new_str, NULL, 3, -1, 1, 17, JOF_UINT16|JOF_INVOKE|JOF_TYPESET) @@ -334,18 +334,18 @@ OPDEF(JSOP_PICK, 133, "pick", */ OPDEF(JSOP_TRY, 134,"try", NULL, 1, 0, 0, 0, JOF_BYTE) 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 * containing the variable being accessed * uint16 slot: the slot containing the variable in the ScopeObject (this * 'slot' does not include RESERVED_SLOTS). * uint32 block: the index (into the script object table) of the block chain * at the point of the variable access. @@ -391,40 +391,39 @@ OPDEF(JSOP_SETGNAME, 155,"setgname" OPDEF(JSOP_INCGNAME, 156,"incgname", NULL, 6, 0, 1, 15, JOF_ATOM|JOF_NAME|JOF_INC|JOF_TMPSLOT3|JOF_GNAME|JOF_DECOMPOSE) OPDEF(JSOP_DECGNAME, 157,"decgname", NULL, 6, 0, 1, 15, JOF_ATOM|JOF_NAME|JOF_DEC|JOF_TMPSLOT3|JOF_GNAME|JOF_DECOMPOSE) OPDEF(JSOP_GNAMEINC, 158,"gnameinc", NULL, 6, 0, 1, 15, JOF_ATOM|JOF_NAME|JOF_INC|JOF_POST|JOF_TMPSLOT3|JOF_GNAME|JOF_DECOMPOSE) OPDEF(JSOP_GNAMEDEC, 159,"gnamedec", NULL, 6, 0, 1, 15, JOF_ATOM|JOF_NAME|JOF_DEC|JOF_POST|JOF_TMPSLOT3|JOF_GNAME|JOF_DECOMPOSE) /* 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) /* Enter a let block/expr whose slots are at the top of the stack. */ OPDEF(JSOP_ENTERLET0, 185,"enterlet0", NULL, 5, -1, -1, 0, JOF_OBJECT) /* Enter a let block/expr whose slots are 1 below the top of the stack. */ OPDEF(JSOP_ENTERLET1, 186,"enterlet1", NULL, 5, -1, -1, 0, JOF_OBJECT) @@ -432,38 +431,34 @@ OPDEF(JSOP_ENTERLET1, 186,"enterlet1 /* * Opcode to hold 24-bit immediate integer operands. */ 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) /* * Stop interpretation, emitted at end of script to save the threaded bytecode * interpreter an extra branch test on every DO_NEXT_OP (see jsinterp.c). */ OPDEF(JSOP_STOP, 194,"stop", NULL, 1, 0, 0, 0, JOF_BYTE) /* * Get an extant property value, throwing ReferenceError if the identified * property does not exist. */ 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). */ OPDEF(JSOP_TYPEOFEXPR, 197,"typeofexpr", NULL, 1, 1, 1, 15, JOF_BYTE|JOF_DETECTING) /* * Block-local scope support.
--- a/js/src/jspropertytree.cpp +++ b/js/src/jspropertytree.cpp @@ -254,18 +254,16 @@ void Shape::dump(JSContext *cx, FILE *fp) const { jsid propid = this->propid(); JS_ASSERT(!JSID_IS_VOID(propid)); if (JSID_IS_INT(propid)) { fprintf(fp, "[%ld]", (long) JSID_TO_INT(propid)); - } else if (JSID_IS_DEFAULT_XML_NAMESPACE(propid)) { - fprintf(fp, "<default XML namespace>"); } else { JSLinearString *str; if (JSID_IS_ATOM(propid)) { str = JSID_TO_ATOM(propid); } else { JS_ASSERT(JSID_IS_OBJECT(propid)); JSString *s = ToStringSlow<CanGC>(cx, IdToValue(propid)); fputs("object ", fp);
--- a/js/src/jsprototypes.h +++ b/js/src/jsprototypes.h @@ -25,41 +25,37 @@ macro(Array, 3, js_InitArrayClass) \ macro(Boolean, 4, js_InitBooleanClass) \ macro(JSON, 5, js_InitJSONClass) \ macro(Date, 6, js_InitDateClass) \ macro(Math, 7, js_InitMathClass) \ 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___ */
--- a/js/src/jsprvtd.h +++ b/js/src/jsprvtd.h @@ -53,20 +53,16 @@ typedef struct JSTryNote JSTr /* Friend "Advanced API" typedefs. */ typedef struct JSAtomState JSAtomState; typedef struct JSCodeSpec JSCodeSpec; typedef struct JSPrinter JSPrinter; typedef struct JSStackHeader JSStackHeader; typedef struct JSSubString JSSubString; typedef struct JSSpecializedNative JSSpecializedNative; -#if JS_HAS_XML_SUPPORT -typedef struct JSXML JSXML; -#endif - /* * Template declarations. * * jsprvtd.h can be included in both C and C++ translation units. For C++, it * may possibly be wrapped in an extern "C" block which does not agree with * templates. */ #ifdef __cplusplus
--- a/js/src/jspubtd.h +++ b/js/src/jspubtd.h @@ -86,17 +86,16 @@ typedef enum JSVersion { typedef enum JSType { JSTYPE_VOID, /* undefined */ JSTYPE_OBJECT, /* object */ JSTYPE_FUNCTION, /* function */ JSTYPE_STRING, /* string */ JSTYPE_NUMBER, /* number */ JSTYPE_BOOLEAN, /* boolean */ JSTYPE_NULL, /* null */ - JSTYPE_XML, /* xml object */ JSTYPE_LIMIT } JSType; /* Dense index into cached prototypes and class atoms for standard objects. */ typedef enum JSProtoKey { #define PROTOKEY_AND_INITIALIZER(name,code,init) JSProto_##name = code, JS_FOR_EACH_PROTOTYPE(PROTOKEY_AND_INITIALIZER) #undef JS_PROTO @@ -149,19 +148,16 @@ typedef enum { JSTRACE_STRING, JSTRACE_SCRIPT, /* * Trace kinds internal to the engine. The embedding can only them if it * implements JSTraceCallback. */ JSTRACE_IONCODE, -#if JS_HAS_XML_SUPPORT - JSTRACE_XML, -#endif JSTRACE_SHAPE, JSTRACE_BASE_SHAPE, JSTRACE_TYPE_OBJECT, JSTRACE_LAST = JSTRACE_TYPE_OBJECT } JSGCTraceKind; /* Struct typedefs and class forward declarations. */ typedef struct JSClass JSClass; @@ -222,17 +218,16 @@ class SkipRoot; enum ThingRootKind { THING_ROOT_OBJECT, THING_ROOT_SHAPE, THING_ROOT_BASE_SHAPE, THING_ROOT_TYPE_OBJECT, THING_ROOT_STRING, THING_ROOT_SCRIPT, - THING_ROOT_XML, THING_ROOT_ID, THING_ROOT_PROPERTY_ID, THING_ROOT_VALUE, THING_ROOT_TYPE, THING_ROOT_BINDINGS, THING_ROOT_LIMIT };
--- a/js/src/jsreflect.cpp +++ b/js/src/jsreflect.cpp @@ -70,17 +70,16 @@ char const *js::binopNames[] = { "*", /* BINOP_STAR */ "/", /* BINOP_DIV */ "%", /* BINOP_MOD */ "|", /* BINOP_BITOR */ "^", /* BINOP_BITXOR */ "&", /* BINOP_BITAND */ "in", /* BINOP_IN */ "instanceof", /* BINOP_INSTANCEOF */ - "..", /* BINOP_DBLDOT */ }; char const *js::unopNames[] = { "delete", /* UNOP_DELETE */ "-", /* UNOP_NEG */ "+", /* UNOP_POS */ "!", /* UNOP_NOT */ "~", /* UNOP_BITNOT */ @@ -607,62 +606,16 @@ class NodeBuilder * patterns */ bool arrayPattern(NodeVector &elts, TokenPos *pos, MutableHandleValue dst); 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 NodeBuilder::newNode(ASTType type, TokenPos *pos, MutableHandleObject dst) { JS_ASSERT(type > AST_ERROR && type < AST_LIMIT); RootedValue tv(cx); @@ -1492,205 +1445,16 @@ NodeBuilder::function(ASTType type, Toke "defaults", defarray, "body", body, "rest", rest, "generator", isGeneratorVal, "expression", isExpressionVal, 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. * * All serialization methods take a non-nullable ParseNode pointer. */ class ASTSerializer { JSContext *cx; @@ -1703,17 +1467,16 @@ class ASTSerializer } BinaryOperator binop(ParseNodeKind kind, JSOp op); UnaryOperator unop(ParseNodeKind kind, JSOp op); AssignmentOperator aop(JSOp op); 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); bool sourceElement(ParseNode *pn, MutableHandleValue dst); bool declaration(ParseNode *pn, MutableHandleValue dst); bool variableDeclaration(ParseNode *pn, bool let, MutableHandleValue dst); @@ -1771,18 +1534,16 @@ class ASTSerializer bool functionArgsAndBody(ParseNode *pn, NodeVector &args, NodeVector &defaults, MutableHandleValue body, MutableHandleValue rest); bool functionBody(ParseNode *pn, TokenPos *pos, MutableHandleValue dst); bool comprehensionBlock(ParseNode *pn, MutableHandleValue dst); 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) , builder(c, l, src) #ifdef DEBUG , lineno(ln) #endif {} @@ -1897,18 +1658,16 @@ ASTSerializer::binop(ParseNodeKind kind, case PNK_BITXOR: return BINOP_BITXOR; case PNK_BITAND: return BINOP_BITAND; case PNK_IN: return BINOP_IN; case PNK_INSTANCEOF: return BINOP_INSTANCEOF; - case PNK_DBLDOT: - return BINOP_DBLDOT; default: return BINOP_ERR; } } bool ASTSerializer::statements(ParseNode *pn, NodeVector &elts) { @@ -1944,34 +1703,16 @@ ASTSerializer::expressions(ParseNode *pn return false; elts.infallibleAppend(elt); } 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) { JS_ASSERT(pn->isKind(PNK_STATEMENTLIST)); NodeVector stmts(cx); return statements(pn, stmts) && builder.blockStatement(stmts, &pn->pn_pos, dst); } @@ -2415,30 +2156,16 @@ ASTSerializer::statement(ParseNode *pn, (pn->isKind(PNK_THROW) ? builder.throwStatement(arg, &pn->pn_pos, dst) : builder.returnStatement(arg, &pn->pn_pos, 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); default: LOCAL_NOT_REACHED("unexpected statement type"); } } @@ -2672,17 +2399,16 @@ ASTSerializer::expression(ParseNode *pn, case PNK_STAR: case PNK_DIV: case PNK_MOD: case PNK_BITOR: case PNK_BITXOR: 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)); BinaryOperator op = binop(pn->getKind(), pn->getOp()); LOCAL_ASSERT(op > BINOP_ERR && op < BINOP_LIMIT); RootedValue left(cx), right(cx); @@ -2847,199 +2573,18 @@ ASTSerializer::expression(ParseNode *pn, LOCAL_ASSERT(pn->pn_count == 1); LOCAL_ASSERT(pn->pn_head->isKind(PNK_LEXICALSCOPE)); return comprehension(pn->pn_head->pn_expr, dst); case PNK_LET: return let(pn, true, dst); -#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<XMLProcessingInstruction>(); - 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"); } } bool ASTSerializer::propertyName(ParseNode *pn, MutableHandleValue dst) { if (pn->isKind(PNK_NAME)) return identifier(pn, dst);
--- a/js/src/jsreflect.h +++ b/js/src/jsreflect.h @@ -49,18 +49,16 @@ enum BinaryOperator { /* shift */ BINOP_LSH, BINOP_RSH, BINOP_URSH, /* arithmetic */ BINOP_ADD, BINOP_SUB, BINOP_STAR, BINOP_DIV, BINOP_MOD, /* binary */ BINOP_BITOR, BINOP_BITXOR, BINOP_BITAND, /* misc */ BINOP_IN, BINOP_INSTANCEOF, - /* xml */ - BINOP_DBLDOT, BINOP_LIMIT }; enum UnaryOperator { UNOP_ERR = -1, UNOP_DELETE = 0,
--- a/js/src/jswrapper.cpp +++ b/js/src/jswrapper.cpp @@ -40,38 +40,23 @@ Wrapper::getWrapperFamily() JSObject * Wrapper::New(JSContext *cx, JSObject *obj, JSObject *proto, JSObject *parent, Wrapper *handler) { JS_ASSERT(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); } 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)); } Wrapper * Wrapper::wrapperHandler(RawObject wrapper) { JS_ASSERT(wrapper->isWrapper());
deleted file mode 100644 --- 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 <stddef.h> -#include "jsversion.h" - -size_t sE4XObjectsCreated = 0; - -#if JS_HAS_XML_SUPPORT - -#include <math.h> -#include <stdlib.h> -#include <string.h> - -#include "mozilla/Util.h" - -#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 <string.h> /* 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<class T, class U> -struct IdentityOp -{ - typedef JSBool (* compare)(const T *a, const U *b); -}; - -template<class T> -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<CanGC>(cx, uri, qualstr); - if (!str) - return NULL; - } - Rooted<JSString*> localName(cx, obj->getQNameLocalName()); - str = ConcatStrings<CanGC>(cx, str, localName); - if (!str) - return NULL; - - if (obj->getClass() == &AttributeNameClass) { - JS::Anchor<JSString *> anchor(str); - size_t length = str->length(); - jschar *chars = cx->pod_malloc<jschar>(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<CanGC>(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<CanGC>(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<CanGC>(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<CanGC>(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<CanGC>(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<CanGC>(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<CanGC>(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<CanGC>(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<JSXML> *cursor) -{ - for (; cursor; cursor = cursor->next) { - if (cursor->root) - MarkXML(trc, &(HeapPtr<JSXML> &)cursor->root, "cursor_root"); - } -} - -void -js_XMLArrayCursorTrace(JSTracer *trc, JSXMLArrayCursor<JSObject> *cursor) -{ - for (; cursor; cursor = cursor->next) { - if (cursor->root) - MarkObject(trc, &(HeapPtr<JSObject> &)cursor->root, "cursor_root"); - } -} - -template<class T> -static HeapPtr<T> * -ReallocateVector(HeapPtr<T> *vector, size_t count) -{ -#if JS_BITS_PER_WORD == 32 - if (count > ~(size_t)0 / sizeof(HeapPtr<T>)) - return NULL; -#endif - - size_t size = count * sizeof(HeapPtr<T>); - return (HeapPtr<T> *) js_realloc(vector, size); -} - -/* NB: called with null cx from the GC, via xml_trace => JSXMLArray::trim. */ -template<class T> -bool -JSXMLArray<T>::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<T> *tmp = ReallocateVector(vector, newCapacity); - if (!tmp) { - if (cx) - JS_ReportOutOfMemory(cx); - return false; - } - vector = tmp; - } - capacity = JSXML_PRESET_CAPACITY | newCapacity; - return true; -} - -template<class T> -void -JSXMLArray<T>::trim() -{ - if (capacity & JSXML_PRESET_CAPACITY) - return; - if (length < capacity) - setCapacity(NULL, length); -} - -template<class T> -void -JSXMLArray<T>::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<T>(); - } - - fop->free_(vector); - - while (JSXMLArrayCursor<T> *cursor = cursors) - cursor->disconnect(); - -#ifdef DEBUG - memset(this, 0xd5, sizeof *this); -#endif -} - -#define XML_NOT_FOUND UINT32_MAX - -template<class T, class U> -static uint32_t -XMLArrayFindMember(const JSXMLArray<T> *array, U *elt, typename IdentityOp<T, U>::compare identity) -{ - HeapPtr<T> *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<class T> -static JSBool -XMLArrayAddMember(JSContext *cx, JSXMLArray<T> *array, uint32_t index, T *elt) -{ - uint32_t capacity, i; - int log2; - HeapPtr<T> *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<class T> -static JSBool -XMLArrayInsert(JSContext *cx, JSXMLArray<T> *array, uint32_t i, uint32_t n) -{ - uint32_t j, k; - JSXMLArrayCursor<T> *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<class T> -static T * -XMLArrayDelete(JSContext *cx, JSXMLArray<T> *array, uint32_t index, JSBool compress) -{ - uint32_t length; - HeapPtr<T> *vector; - T *elt; - JSXMLArrayCursor<T> *cursor; - - length = array->length; - if (index >= length) - return NULL; - - vector = array->vector; - elt = vector[index]; - if (compress) { - vector[length - 1].~HeapPtr<T>(); - 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<class T> -static void -XMLArrayTruncate(JSContext *cx, JSXMLArray<T> *array, uint32_t length) -{ - HeapPtr<T> *vector; - - JS_ASSERT(!array->cursors); - if (length >= array->length) - return; - - for (uint32_t i = length; i < array->length; i++) - array->vector[i].~HeapPtr<T>(); - - 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<t>(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<JSObject> *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<CanGC>(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<JSObject> *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<CanGC>(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<XMLProcessingInstruction>(); - 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[] = "<parent xmlns=\""; - static const char middle[] = "\">"; - static const char suffix[] = "</parent>"; - -#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<jschar>(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<CanGC>(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<CanGC>(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<JSObject> *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 = <t xmlns="http://foo.com"/> - * 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<JSObject> *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 = <f/>; - * 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<CanGC>(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<jschar>(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<jschar>(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<CanGC>(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<JSObject> *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<JSXML> 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<JSObject> 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<JSXML> 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<JSObject> 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<JSXML> 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("</")) - goto out; - - /* Step 26. */ - prefix = ns->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<CanGC>(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<CanGC>(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<JSObject *> anch(obj); - JSXML *xml = reinterpret_cast<JSXML *>(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<CanGC>(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<CanGC>(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<CanGC>(cx, v); - if (!name) - return NULL; - } - - atomizedName = AtomizeString<CanGC>(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<JSXML> *from, JSXMLArray<JSXML> *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<JSXML> 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<JSXML> cursor(&xml->xml_kids); - JSXMLArrayCursor<JSXML> 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<CanGC>(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<CanGC>(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<JSXML> *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<JSObject> *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<JSXML> *array; - JSXMLNameMatcher matcher; - JSBool attrs; - - if (xml->xml_class == JSXML_CLASS_LIST) { - JSXMLArrayCursor<JSXML> 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<JSXML> 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<CanGC>(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("<TEAM>Giants</TEAM>")); - * - * (testcase from Werner Sharp <wsharp@macromedia.com>). - * - * 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<JSObject*> 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<CanGC>(cx, left, space); - if (!left) - goto bad; - RootedString right(cx, KidToString(cx, vxml, i)); - if (!right) - goto bad; - left = ConcatStrings<CanGC>(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<JSXML> 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<JSObject*> 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<JSXML> *array; - JSXMLNameMatcher matcher; - uint32_t i, n; - - if (xml->xml_class == JSXML_CLASS_LIST) { - found = JS_FALSE; - JSXMLArrayCursor<JSXML> 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<JSObject*> obj(cx, obj_); - RootedObject pobj(cx); - RootedShape prop(cx); - if (!baseops::LookupProperty<CanGC>(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<CanGC>(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<CanGC>(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<jsid> 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<JSXML *>(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<jsid> 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<jsid> 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<jsid> 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<jsid> 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<jsid> 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<jsid> 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<jsid> 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<jsid> 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<jsid> 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<jsid> 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<jsid> 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<jsid> 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<JSXML *>(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<jsid> 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<JSObject *> anch(obj); - JSString *str = xml_toString_helper(cx, reinterpret_cast<JSXML *>(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<JSXML> *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<JSXML> >(&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<JSXML> *) 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<JSXML> *) 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<jsid> 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<CanGC>(cx, ObjectValue(*obj))) && - (vstr = ToString<CanGC>(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<CanGC>(cx, ObjectValue(*obj))) && - (vstr = ToString<CanGC>(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<CanGC>(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<JSObject*> 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<CanGC>(cx, v, &id)) - return JS_FALSE; - *idp = id; - } - } else if (JSVAL_IS_STRING(v)) { - JSAtom *atom = AtomizeString<CanGC>(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<JSObject*> 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<JSXML> 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<JSXML> 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<JSXML> 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<CanGC>(cx, name, &id)) - return false; - - RootedObject obj2(cx); - RootedShape prop(cx); - if (!HasOwnProperty<CanGC>(cx, baseops::LookupProperty<CanGC>, 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<JSObject> *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<JSObject> *array, jsval *rval) -{ - Rooted<JSObject*> 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<CanGC>(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<JSString*> lstr(cx, kid->xml_value); - Rooted<JSString*> rstr(cx, kid2->xml_value); - str = ConcatStrings<CanGC>(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<JSXML> 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<jsid> 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<CanGC>(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<JSObject> *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<JSXML> *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<JSXML> 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<CanGC>(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<JSXML*> 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<GlobalObject*> 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<GlobalObject*> 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<GlobalObject *> global(cx, &obj->asGlobal()); - JS_ASSERT(obj->isNative()); - - RootedObject xmlProto(cx, global->createBlankPrototype(cx, &XMLClass)); - if (!xmlProto) - return NULL; - Rooted<JSXML*> 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<jschar>(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<CanGC>(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<JSXML> list; - HeapPtr<JSXML> result; - HeapPtr<JSXML> kid; - JSXMLArrayCursor<JSXML> cursor; - - JSXMLFilter(JSXML *list, JSXMLArray<JSXML> *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_<JSXMLFilter>(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<CanGC>(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 */
deleted file mode 100644 --- 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<class T> -struct JSXMLArrayCursor; - -template<class T> -struct JSXMLArray -{ - uint32_t length; - uint32_t capacity; - js::HeapPtr<T> *vector; - JSXMLArrayCursor<T> *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<class T> -struct JSXMLArrayCursor -{ - typedef js::HeapPtr<T> HeapPtrT; - - JSXMLArray<T> *array; - uint32_t index; - JSXMLArrayCursor<T> *next; - JSXMLArrayCursor<T> **prevp; - HeapPtrT root; - - JSXMLArrayCursor(JSXMLArray<T> *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<JSXML> *cursor); -void js_XMLArrayCursorTrace(JSTracer *trc, JSXMLArrayCursor<JSObject> *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<JSXML> kids; /* NB: must come first */ - js::HeapPtrXML target; - js::HeapPtrObject targetprop; -} JSXMLListVar; - -typedef struct JSXMLElemVar { - JSXMLArray<JSXML> kids; /* NB: must come first */ - JSXMLArray<JSObject> namespaces; - JSXMLArray<JSXML> 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___ */
--- a/js/src/methodjit/InvokeHelpers.cpp +++ b/js/src/methodjit/InvokeHelpers.cpp @@ -8,17 +8,16 @@ #include "mozilla/DebugOnly.h" #include "jsanalyze.h" #include "jscntxt.h" #include "jsobj.h" #include "jslibmath.h" #include "jsiter.h" #include "jsnum.h" -#include "jsxml.h" #include "jsbool.h" #include "jstypes.h" #include "assembler/assembler/MacroAssemblerCodeRef.h" #include "assembler/assembler/CodeLocation.h" #include "builtin/Eval.h" #include "methodjit/StubCalls.h" #include "methodjit/MonoIC.h"
--- a/js/src/methodjit/PolyIC.cpp +++ b/js/src/methodjit/PolyIC.cpp @@ -2633,26 +2633,16 @@ ic::GetElement(VMFrame &f, ic::GetElemen RecompilationMonitor monitor(cx); RootedValue objval(f.cx, f.regs.sp[-2]); RootedObject obj(cx, ToObjectFromStack(cx, objval)); 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<jsid> id(cx); if (idval.isInt32() && INT_FITS_IN_JSID(idval.toInt32())) { id = INT_TO_JSID(idval.toInt32()); } else { if (!InternNonIntElementId<CanGC>(cx, obj, idval, &id)) THROW(); }
--- a/js/src/methodjit/StubCalls.cpp +++ b/js/src/methodjit/StubCalls.cpp @@ -8,17 +8,16 @@ #include "mozilla/DebugOnly.h" #include "mozilla/FloatingPoint.h" #include "jscntxt.h" #include "jsobj.h" #include "jslibmath.h" #include "jsiter.h" #include "jsnum.h" -#include "jsxml.h" #include "jsbool.h" #include "assembler/assembler/MacroAssemblerCodeRef.h" #include "jstypes.h" #include "gc/Marking.h" #include "vm/Debugger.h" #include "vm/NumericConversions.h" #include "vm/Shape.h" @@ -480,29 +479,17 @@ StubEqualityOp(VMFrame &f) /* The string==string case is easily the hottest; try it first. */ if (lval.isString() && rval.isString()) { JSString *l = lval.toString(); JSString *r = rval.toString(); bool equal; 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(); double r = rval.toDouble(); if (EQ) cond = (l == r); else cond = (l != r); @@ -592,28 +579,17 @@ stubs::Add(VMFrame &f) bool lIsString = lval.isString(); bool rIsString = rval.isString(); JSString *lstr, *rstr; if (lIsString && rIsString) { lstr = lval.toString(); 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(); if (!ToPrimitive(f.cx, &rval)) THROW(); if ((lIsString = lval.isString()) || (rIsString = rval.isString())) { if (lIsString) { lstr = lval.toString();
--- a/js/src/shell/js.cpp +++ b/js/src/shell/js.cpp @@ -36,17 +36,16 @@ #include "jsnum.h" #include "jsobj.h" #include "json.h" #include "jsreflect.h" #include "jsscript.h" #include "jstypedarray.h" #include "jstypedarrayinlines.h" #include "jsworkers.h" -#include "jsxml.h" #include "jsperf.h" #include "builtin/TestingFunctions.h" #include "frontend/BytecodeEmitter.h" #include "frontend/Parser.h" #include "methodjit/MethodJIT.h" #include "vm/Shape.h" @@ -712,18 +711,16 @@ static const struct JSOption { uint32_t flag; } js_options[] = { {"atline", JSOPTION_ATLINE}, {"methodjit", JSOPTION_METHODJIT}, {"methodjit_always",JSOPTION_METHODJIT_ALWAYS}, {"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}, }; static uint32_t MapContextOptionNameToFlag(JSContext* cx, const char* name) { for (size_t i = 0; i < ArrayLength(js_options); ++i) { if (strcmp(name, js_options[i].name) == 0)
--- a/js/src/vm/CommonPropertyNames.h +++ b/js/src/vm/CommonPropertyNames.h @@ -8,33 +8,16 @@ /* A higher-order macro for enumerating all cached property names. */ #ifndef CommonPropertyNames_h__ #define CommonPropertyNames_h__ #include "jsprototypes.h" #include "jsversion.h" -#if JS_HAS_XML_SUPPORT -#define FOR_EACH_XML_ONLY_NAME(macro) \ - macro(etago, etago, "</") \ - macro(functionNamespaceURI, functionNamespaceURI, "@mozilla.org/js/function") \ - macro(namespace, namespace_, "namespace") \ - macro(ptagc, ptagc, "/>") \ - 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") \ macro(arguments, arguments, "arguments") \ macro(buffer, buffer, "buffer") \ macro(builder, builder, "builder") \ macro(byteLength, byteLength, "byteLength") \ macro(byteOffset, byteOffset, "byteOffset") \ @@ -85,17 +68,16 @@ macro(InitializeCollator, InitializeCollator, "InitializeCollator") \ macro(InitializeDateTimeFormat, InitializeDateTimeFormat, "InitializeDateTimeFormat") \ macro(InitializeNumberFormat, InitializeNumberFormat, "InitializeNumberFormat") \ macro(innermost, innermost, "innermost") \ macro(input, input, "input") \ 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") \ macro(iteratorIntrinsic, iteratorIntrinsic, "__iterator__") \ macro(join, join, "join") \ macro(keys, keys, "keys") \ macro(lastIndex, lastIndex, "lastIndex") \ macro(length, length, "length") \ @@ -149,13 +131,11 @@ macro(writable, writable, "writable") \ /* Type names must be contiguous and ordered; see js::TypeName. */ \ macro(undefined, undefined, "undefined") \ macro(object, object, "object") \ macro(function, function, "function") \ 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__ */
--- a/js/src/vm/GlobalObject.cpp +++ b/js/src/vm/GlobalObject.cpp @@ -462,19 +462,16 @@ GlobalObject::initStandardClasses(JSCont js_InitBooleanClass(cx, global) && js_InitExceptionClasses(cx, global) && js_InitMathClass(cx, global) && js_InitNumberClass(cx, global) && js_InitJSONClass(cx, 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) && js_InitProxyClass(cx, global) && js_InitMapClass(cx, global) && GlobalObject::initMapIteratorProto(cx, global) && js_InitSetClass(cx, global) && GlobalObject::initSetIteratorProto(cx, global) &&
--- a/js/src/vm/GlobalObject.h +++ b/js/src/vm/GlobalObject.h @@ -44,21 +44,20 @@ class Debugger; * [JSProto_LIMIT, 2 * JSProto_LIMIT) * Stores the prototype, if any, for the constructor for the corresponding * JSProtoKey offset from JSProto_LIMIT. * [2 * JSProto_LIMIT, 3 * JSProto_LIMIT) * Stores the current value of the global property named for the JSProtoKey * 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 * Array prototype object", or "as if by the expression new Array()" referring * to the original Array constructor. The third range stores the (writable and * even deletable) Object, Array, &c. properties (although a slot won't be used * again if its property is deleted and readded). */ @@ -423,18 +422,16 @@ class GlobalObject : public JSObject bool isRuntimeCodeGenEnabled(JSContext *cx); const Value &getOriginalEval() const { JS_ASSERT(getSlot(EVAL).isObject()); return getSlot(EVAL); } - bool getFunctionNamespace(JSContext *cx, Value *vp); - // Implemented in jsiter.cpp. static bool initIteratorClasses(JSContext *cx, Handle<GlobalObject*> global); // Implemented in builtin/MapObject.cpp. static bool initMapIteratorProto(JSContext *cx, Handle<GlobalObject*> global); static bool initSetIteratorProto(JSContext *cx, Handle<GlobalObject*> global); // Implemented in Intl.cpp.
--- a/js/src/vm/ObjectImpl.h +++ b/js/src/vm/ObjectImpl.h @@ -43,19 +43,18 @@ CastAsStrictPropertyOp(JSObject *object) /* * Properties are stored differently depending on the type of the key. If the * key is an unsigned 32-bit integer (i.e. an index), we call such properties * "elements" and store them in one of a number of forms (optimized for dense * 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 { jsid id; public: bool isName() const { MOZ_ASSERT(JSID_IS_STRING(id) || JSID_IS_SPECIAL(id));
--- a/js/src/vm/Shape-inl.h +++ b/js/src/vm/Shape-inl.h @@ -314,17 +314,17 @@ Shape::set(JSContext* cx, HandleObject o return js_ReportGetterOnlyAssignment(cx); Rooted<Shape *> self(cx, this); RootedId id(cx); if (!self->getUserId(cx, &id)) 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()) { RootedObject nobj(cx, &obj->asWith().object()); return CallJSPropertyOpSetter(cx, self->setterOp(), nobj, id, strict, vp); } return CallJSPropertyOpSetter(cx, self->setterOp(), obj, id, strict, vp);
--- a/js/src/vm/Stack.h +++ b/js/src/vm/Stack.h @@ -696,19 +696,18 @@ class StackFrame } bool pushBlock(JSContext *cx, StaticBlockObject &block); void popBlock(JSContext *cx); /* * 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); /* * Script * * All function and global frames have an associated JSScript which holds
--- a/js/src/vm/String.h +++ b/js/src/vm/String.h @@ -831,18 +831,18 @@ class StaticStrings * * To more concretely illustrate the utility of PropertyName, consider that it * is used to partition, in a type-safe manner, the ways to refer to a * property, as follows: * * - 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 {}; JS_STATIC_ASSERT(sizeof(PropertyName) == sizeof(JSString)); static JS_ALWAYS_INLINE RawId NameToId(PropertyName *name)
--- a/js/src/vm/Unicode.h +++ b/js/src/vm/Unicode.h @@ -55,29 +55,24 @@ namespace unicode { * return True * if char in ['$', '_']: * return True * if GetFlag(char) & (FLAG_IDENTIFIER_PART | FLAG_LETTER): * return True * * NO_DELTA * See comment in CharacterInfo - * - * ENCLOSING_MARK / COMBINING_SPACING_MARK - * Something for E4X.... */ struct CharFlag { enum temp { 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 }; }; const jschar BYTE_ORDER_MARK2 = 0xFFFE; const jschar NO_BREAK_SPACE = 0x00A0; class CharacterInfo { /* @@ -111,24 +106,16 @@ class CharacterInfo { inline bool isLetter() const { return flags & CharFlag::LETTER; } 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[]; extern const uint8_t index2[]; extern const CharacterInfo js_charinfo[]; inline const CharacterInfo& CharInfo(jschar code) @@ -232,57 +219,12 @@ ToLowerCase(jschar ch) const CharacterInfo &info = CharInfo(ch); if (info.flags & CharFlag::NO_DELTA) return info.lowerCase; 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 */ #endif /* Unicode_h__ */
--- a/js/src/vm/Xdr.h +++ b/js/src/vm/Xdr.h @@ -20,17 +20,17 @@ namespace js { * Bytecode version number. Increment the subtrahend whenever JS bytecode * changes incompatibly. * * This version number is XDR'd near the front of xdr bytecode and * aborts deserialization if there is a mismatch between the current * 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: XDRBuffer(JSContext *cx) : context(cx), base(NULL), cursor(NULL), limit(NULL) { } JSContext *cx() const { return context;
--- a/js/xpconnect/idl/xpccomponents.idl +++ b/js/xpconnect/idl/xpccomponents.idl @@ -380,19 +380,16 @@ interface nsIXPCComponents_Utils : nsISu [implicit_jscontext] attribute boolean werror; [implicit_jscontext] attribute boolean atline; [implicit_jscontext] - attribute boolean xml; - - [implicit_jscontext] attribute boolean methodjit; [implicit_jscontext] attribute boolean methodjit_always; [implicit_jscontext] attribute boolean strict_mode;
--- a/js/xpconnect/loader/mozJSComponentLoader.cpp +++ b/js/xpconnect/loader/mozJSComponentLoader.cpp @@ -466,21 +466,16 @@ mozJSComponentLoader::ReallyInit() if (NS_FAILED(rv)) return rv; // Create our compilation context. mContext = JS_NewContext(mRuntime, 256); 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); nsCOMPtr<nsIScriptSecurityManager> secman = do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID); if (!secman) return NS_ERROR_FAILURE;
--- a/js/xpconnect/shell/xpcshell.cpp +++ b/js/xpconnect/shell/xpcshell.cpp @@ -697,18 +697,16 @@ GetChildGlobalObject(JSContext* cx, */ static const struct JSOption { const char *name; uint32_t flag; } js_options[] = { {"atline", JSOPTION_ATLINE}, {"strict", JSOPTION_STRICT}, {"werror", JSOPTION_WERROR}, - {"allow_xml", JSOPTION_ALLOW_XML}, - {"moar_xml", JSOPTION_MOAR_XML}, {"strict_mode", JSOPTION_STRICT_MODE}, }; static uint32_t MapContextOptionNameToFlag(JSContext* cx, const char* name) { for (size_t i = 0; i < ArrayLength(js_options); ++i) { if (strcmp(name, js_options[i].name) == 0) @@ -1126,17 +1124,17 @@ Process(JSContext *cx, JSObject *obj, co if (file != stdin) fclose(file); } 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; } extern JSClass global_class; static void ProcessArgsForCompartment(JSContext *cx, char **argv, int argc) { @@ -1151,19 +1149,16 @@ ProcessArgsForCompartment(JSContext *cx, if (++i == argc) return; break; case 'S': JS_ToggleOptions(cx, JSOPTION_WERROR); 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; case 'I': JS_ToggleOptions(cx, JSOPTION_COMPILE_N_GO); JS_ToggleOptions(cx, JSOPTION_ION); break; case 'n': @@ -1825,17 +1820,16 @@ main(int argc, char **argv, char **envp) printf("JS_NewContext failed!\n"); return 1; } argc--; argv++; ProcessArgsForCompartment(cx, argv, argc); - JS_SetOptions(cx, JS_GetOptions(cx) | JSOPTION_ALLOW_XML); xpc_LocalizeContext(cx); nsCOMPtr<nsIXPConnect> xpc = do_GetService(nsIXPConnect::GetCID()); if (!xpc) { printf("failed to get nsXPConnect service!\n"); return 1; }
--- a/js/xpconnect/src/XPCComponents.cpp +++ b/js/xpconnect/src/XPCComponents.cpp @@ -3757,26 +3757,22 @@ ContextHolder::ContextHolder(JSContext * mOrigCx(aOuterCx), mPrincipal(aPrincipal) { if (mJSContext) { bool isChrome; DebugOnly<nsresult> 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); } } ContextHolder::~ContextHolder() { @@ -4489,17 +4485,16 @@ SetBoolOption(JSContext* cx, uint32_t aO nsXPCComponents_Utils::Set## _attr(JSContext* cx, bool aValue) \ { \ return SetBoolOption(cx, _flag, 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) GENERATE_JSOPTION_GETTER_SETTER(Ion, JSOPTION_ION) #undef GENERATE_JSOPTION_GETTER_SETTER NS_IMETHODIMP
--- a/js/xpconnect/src/XPCConvert.cpp +++ b/js/xpconnect/src/XPCConvert.cpp @@ -1054,22 +1054,16 @@ XPCConvert::JSObject2NativeInterface(JSC ? inner : src); if (wrappedNative) { iface = wrappedNative->GetIdentityObject(); return NS_SUCCEEDED(iface->QueryInterface(*iid, dest)); } // 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) return NS_SUCCEEDED(iface->QueryInterface(*iid, dest)); return false; } }
--- a/js/xpconnect/src/XPCJSRuntime.cpp +++ b/js/xpconnect/src/XPCJSRuntime.cpp @@ -1641,23 +1641,16 @@ ReportCompartmentStats(const JS::Compart "heap that holds type inference information."); CREPORT_GC_BYTES(cJSPathPrefix + NS_LITERAL_CSTRING("gc-heap/ion-codes"), cStats.gcHeapIonCodes, "Memory on the garbage-collected JavaScript " "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 " "slot arrays, which are used to represent object properties. " "Some objects also contain a fixed number of slots which are " "stored on the JavaScript heap; those slots " "are not counted here, but in 'gc-heap/objects' instead.");
--- a/js/xpconnect/src/XPCQuickStubs.cpp +++ b/js/xpconnect/src/XPCQuickStubs.cpp @@ -823,24 +823,16 @@ xpc_qsUnwrapArgImpl(JSContext *cx, if (NS_FAILED(castNative(cx, wrapper, obj2, tearoff, iid, ppArg, ppArgRef, vp, nullptr))) return NS_ERROR_XPC_BAD_CONVERT_JS; return NS_OK; } // 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)) { if (!iface || NS_FAILED(iface->QueryInterface(iid, ppArg))) { *ppArgRef = nullptr; return NS_ERROR_XPC_BAD_CONVERT_JS; }
--- a/js/xpconnect/src/nsXPConnect.cpp +++ b/js/xpconnect/src/nsXPConnect.cpp @@ -764,17 +764,16 @@ DescribeGCThing(bool isMarked, void *p, clasp->name); } } else { static const char trace_types[][11] = { "Object", "String", "Script", "IonCode", - "Xml", "Shape", "BaseShape", "TypeObject", }; JS_STATIC_ASSERT(NS_ARRAY_LENGTH(trace_types) == JSTRACE_LAST + 1); JS_snprintf(name, sizeof(name), "JS %s", trace_types[traceKind]); } @@ -2511,23 +2510,18 @@ NS_IMETHODIMP nsXPConnect::GetTelemetryValue(JSContext *cx, jsval *rval) { JSObject *obj = JS_NewObject(cx, NULL, NULL, NULL); if (!obj) return NS_ERROR_OUT_OF_MEMORY; 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; i = JS_GetCustomIteratorCount(cx); v = DOUBLE_TO_JSVAL(i); if (!JS_DefineProperty(cx, obj, "customIter", v, NULL, NULL, attrs)) return NS_ERROR_OUT_OF_MEMORY;
--- a/js/xpconnect/src/xpcprivate.h +++ b/js/xpconnect/src/xpcprivate.h @@ -446,22 +446,20 @@ private: **************************************************************************** ***************************************************************************/ // We have a general rule internally that getters that return addref'd interface // pointer generally do so using an 'out' parm. When interface pointers are // 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, public nsIThreadObserver, public nsSupportsWeakReference, public nsCycleCollectionJSRuntime, public nsIJSRuntimeService, public nsIThreadJSContextStack,
--- a/modules/libpref/src/init/all.js +++ b/modules/libpref/src/init/all.js @@ -738,18 +738,16 @@ pref("javascript.options.strict.debug", #endif pref("javascript.options.methodjit.content", true); pref("javascript.options.methodjit.chrome", true); pref("javascript.options.ion.content", true); 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. // If you want to change these values for your device, // please find Bug 417052 comment 17 and Bug 456721 // Comment 32 and Bug 613551. pref("javascript.options.mem.high_water_mark", 128); pref("javascript.options.mem.max", -1);