Bug 753885 - Part 2: Add JSOPTION_ALLOW_XML, making E4X support optional per-context. r=Waldo.

This commit is contained in:
Jason Orendorff 2012-05-30 15:05:59 -05:00
parent 80dda6d7a5
commit 9ec40fdc02
20 changed files with 104 additions and 26 deletions

View File

@ -831,7 +831,9 @@ nsFrameScriptExecutor::InitTabChildGlobalInternal(nsISupports* aScope)
nsContentUtils::GetSecurityManager()->GetSystemPrincipal(getter_AddRefs(mPrincipal));
JS_SetOptions(cx, JS_GetOptions(cx) | JSOPTION_PRIVATE_IS_NSISUPPORTS);
JS_SetOptions(cx, JS_GetOptions(cx) |
JSOPTION_PRIVATE_IS_NSISUPPORTS |
JSOPTION_ALLOW_XML);
JS_SetVersion(cx, JSVERSION_LATEST);
JS_SetErrorReporter(cx, ContentScriptErrorReporter);

View File

@ -954,7 +954,7 @@ nsJSContext::JSOptionChangedCallback(const char *pref, void *data)
useMethodJITAlways = true;
useHardening = false;
}
}
}
if (useMethodJIT)
newDefaultJSOptions |= JSOPTION_METHODJIT;
@ -998,7 +998,8 @@ nsJSContext::JSOptionChangedCallback(const char *pref, void *data)
else
newDefaultJSOptions &= ~JSOPTION_RELIMIT;
::JS_SetOptions(context->mContext, newDefaultJSOptions & JSRUNOPTION_MASK);
::JS_SetOptions(context->mContext,
newDefaultJSOptions & (JSRUNOPTION_MASK | JSOPTION_ALLOW_XML));
// Save the new defaults for the next page load (InitContext).
context->mDefaultJSOptions = newDefaultJSOptions;
@ -1030,7 +1031,7 @@ nsJSContext::nsJSContext(JSRuntime *aRuntime)
++sContextCount;
mDefaultJSOptions = JSOPTION_PRIVATE_IS_NSISUPPORTS;
mDefaultJSOptions = JSOPTION_PRIVATE_IS_NSISUPPORTS | JSOPTION_ALLOW_XML;
mContext = ::JS_NewContext(aRuntime, gStackSize);
if (mContext) {

View File

@ -214,6 +214,7 @@ PrefCallback(const char* aPrefName, void* aClosure)
if (Preferences::GetBool(gPrefsToWatch[PREF_typeinference])) {
newOptions |= JSOPTION_TYPE_INFERENCE;
}
newOptions |= JSOPTION_ALLOW_XML;
RuntimeService::SetDefaultJSContextOptions(newOptions);
rts->UpdateAllWorkerJSContextOptions();

View File

@ -106,6 +106,7 @@ _newJSDContext(JSRuntime* jsrt,
goto label_newJSDContext_failure;
JS_BeginRequest(jsdc->dumbContext);
JS_SetOptions(jsdc->dumbContext, JS_GetOptions(jsdc->dumbContext) | JSOPTION_ALLOW_XML);
jsdc->glob = JS_NewCompartmentAndGlobalObject(jsdc->dumbContext, &global_class, NULL);

View File

@ -232,7 +232,7 @@ struct Parser : private AutoGCRooter
#if JS_HAS_XML_SUPPORT
// True if E4X syntax is allowed in the current syntactic context.
bool allowsXML() const { return !tc->sc->inStrictMode(); }
bool allowsXML() const { return !tc->sc->inStrictMode() && tokenStream.allowsXML(); }
ParseNode *endBracketedExpr();

View File

@ -139,6 +139,7 @@ TokenStream::TokenStream(JSContext *cx, JSPrincipals *prin, JSPrincipals *origin
listenerTSData(),
tokenbuf(cx),
version(v),
allowXML(VersionHasAllowXML(v)),
moarXML(VersionHasMoarXML(v)),
cx(cx),
originPrincipals(JSScript::normalizeOriginPrincipals(prin, originPrin)),

View File

@ -467,7 +467,7 @@ class TokenStream
/* 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 !isStrictMode(); }
bool allowsXML() const { return allowXML && !isStrictMode(); }
bool hasMoarXML() const { return moarXML || VersionShouldParseXML(versionNumber()); }
void setMoarXML(bool enabled) { moarXML = enabled; }
@ -797,6 +797,7 @@ class TokenStream
bool maybeEOL[256]; /* probabilistic EOL lookup table */
bool maybeStrSpecial[256];/* speeds up string scanning */
JSVersion version; /* (i.e. to identify keywords) */
bool allowXML; /* see JSOPTION_ALLOW_XML */
bool moarXML; /* see JSOPTION_MOAR_XML */
JSContext *const cx;
JSPrincipals *const originPrincipals;

View File

@ -23,3 +23,6 @@ if (!("gcslice" in this)) {
if (!("selectforgc" in this)) {
selectforgc = function() { }
}
if ("options" in this)
options("allow_xml");

View File

@ -0,0 +1,16 @@
// XML syntax is not available unless JSOPTION_ALLOW_XML is enabled.
load(libdir + "asserts.js");
var exprs = ["<a/>", "x..y", "x.@id", "x.(@id === '13')", "x.*", "x.function::length",
"function::parseInt", "a::b"];
assertEq(options().split(",").indexOf("allow_xml") >= 0, true);
options("allow_xml"); // turn it off
for (var e of exprs)
assertThrowsInstanceOf(function () { Function("return " + e + ";"); }, SyntaxError);
options("allow_xml"); // turn it back on
for (var e of exprs)
assertEq(typeof Function("return " + e + ";"), "function");

View File

@ -128,7 +128,8 @@ ThrowHook(JSContext *cx, JSScript *, jsbytecode *, jsval *rval, void *closure)
BEGIN_TEST(testDebugger_throwHook)
{
uint32_t newopts = JS_GetOptions(cx) | JSOPTION_METHODJIT | JSOPTION_METHODJIT_ALWAYS;
uint32_t newopts =
JS_GetOptions(cx) | JSOPTION_METHODJIT | JSOPTION_METHODJIT_ALWAYS | JSOPTION_ALLOW_XML;
uint32_t oldopts = JS_SetOptions(cx, newopts);
CHECK(JS_SetThrowHook(rt, ThrowHook, NULL));

View File

@ -36,6 +36,7 @@ struct VersionFixture : public JSAPITest
virtual bool init() {
if (!JSAPITest::init())
return false;
JS_SetOptions(cx, JS_GetOptions(cx) | JSOPTION_ALLOW_XML);
callbackData = this;
captured = JSVERSION_UNKNOWN;
return JS_DefineFunction(cx, global, "checkVersionHasMoarXML", CheckVersionHasMoarXML, 0, 0) &&
@ -187,7 +188,7 @@ CheckOverride(JSContext *cx, unsigned argc, jsval *vp)
* JSAPI call is propagated to newly compiled scripts, instead of inheriting
* the XML setting from a script on the stack.
*/
BEGIN_FIXTURE_TEST(VersionFixture, testOptionsAreUsedForVersionFlags)
BEGIN_FIXTURE_TEST(VersionFixture, testVersion_OptionsAreUsedForVersionFlags)
{
callbackData = this;
@ -209,7 +210,7 @@ BEGIN_FIXTURE_TEST(VersionFixture, testOptionsAreUsedForVersionFlags)
CHECK(JS_ExecuteScript(cx, global, toActivate, &dummy));
return true;
}
END_FIXTURE_TEST(VersionFixture, testOptionsAreUsedForVersionFlags)
END_FIXTURE_TEST(VersionFixture, testVersion_OptionsAreUsedForVersionFlags)
/*
* When re-entering the virtual machine through a *Version API the version
@ -217,7 +218,7 @@ END_FIXTURE_TEST(VersionFixture, testOptionsAreUsedForVersionFlags)
* version progression. This is maintained by the |AutoVersionAPI| class in
* jsapi.cpp.
*/
BEGIN_FIXTURE_TEST(VersionFixture, testEntryLosesOverride)
BEGIN_FIXTURE_TEST(VersionFixture, testVersion_EntryLosesOverride)
{
EXEC("overrideVersion15(); evalScriptVersion16('checkOverride(false); captureVersion()');");
CHECK_EQUAL(captured, JSVERSION_1_6);
@ -230,7 +231,7 @@ BEGIN_FIXTURE_TEST(VersionFixture, testEntryLosesOverride)
CHECK(!cx->isVersionOverridden());
return true;
}
END_FIXTURE_TEST(VersionFixture, testEntryLosesOverride)
END_FIXTURE_TEST(VersionFixture, testVersion_EntryLosesOverride)
/*
* EvalScriptVersion does not propagate overrides to its caller, it
@ -238,7 +239,7 @@ END_FIXTURE_TEST(VersionFixture, testEntryLosesOverride)
* the normal (no Version suffix) API which propagates overrides
* to the caller.
*/
BEGIN_FIXTURE_TEST(VersionFixture, testReturnLosesOverride)
BEGIN_FIXTURE_TEST(VersionFixture, testVersion_ReturnLosesOverride)
{
CHECK_EQUAL(JS_GetVersion(cx), JSVERSION_ECMA_5);
EXEC(
@ -250,9 +251,9 @@ BEGIN_FIXTURE_TEST(VersionFixture, testReturnLosesOverride)
CHECK_EQUAL(captured, JSVERSION_ECMA_5);
return true;
}
END_FIXTURE_TEST(VersionFixture, testReturnLosesOverride)
END_FIXTURE_TEST(VersionFixture, testVersion_ReturnLosesOverride)
BEGIN_FIXTURE_TEST(VersionFixture, testEvalPropagatesOverride)
BEGIN_FIXTURE_TEST(VersionFixture, testVersion_EvalPropagatesOverride)
{
CHECK_EQUAL(JS_GetVersion(cx), JSVERSION_ECMA_5);
EXEC(
@ -264,4 +265,22 @@ BEGIN_FIXTURE_TEST(VersionFixture, testEvalPropagatesOverride)
CHECK_EQUAL(captured, JSVERSION_1_5);
return true;
}
END_FIXTURE_TEST(VersionFixture, testEvalPropagatesOverride)
END_FIXTURE_TEST(VersionFixture, testVersion_EvalPropagatesOverride)
BEGIN_TEST(testVersion_AllowXML)
{
JSBool ok;
static const char code[] = "var m = <x/>;";
ok = JS_EvaluateScriptForPrincipalsVersion(cx, global, NULL, code, strlen(code),
__FILE__, __LINE__, NULL, JSVERSION_ECMA_5);
CHECK_EQUAL(ok, JS_FALSE);
JS_ClearPendingException(cx);
JS_SetOptions(cx, JS_GetOptions(cx) | JSOPTION_ALLOW_XML);
ok = JS_EvaluateScriptForPrincipalsVersion(cx, global, NULL, code, strlen(code),
__FILE__, __LINE__, NULL, JSVERSION_ECMA_5);
CHECK_EQUAL(ok, JS_TRUE);
return true;
}
END_TEST(testVersion_AllowXML)

View File

@ -88,7 +88,7 @@ using namespace js::gc;
using namespace js::types;
/*
* This class is a version-establising barrier at the head of a VM entry or
* This class is a version-establishing barrier at the head of a VM entry or
* re-entry. It ensures that:
*
* - |newVersion| is the starting (default) version used for the context.
@ -107,7 +107,7 @@ class AutoVersionAPI
JSVersion newVersion;
public:
explicit AutoVersionAPI(JSContext *cx, JSVersion newVersion)
AutoVersionAPI(JSContext *cx, JSVersion newVersion)
: cx(cx),
oldDefaultVersion(cx->getDefaultVersion()),
oldHasVersionOverride(cx->isVersionOverridden()),
@ -116,6 +116,11 @@ class AutoVersionAPI
, 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);

View File

@ -2730,12 +2730,14 @@ JS_StringToVersion(const char *string);
option supported for the
XUL preprocessor and kindred
beasts. */
#define JSOPTION_MOAR_XML JS_BIT(6) /* EMCAScript for XML support:
#define JSOPTION_ALLOW_XML JS_BIT(6) /* enable E4X syntax (deprecated) */
#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. */
#define JSOPTION_DONT_REPORT_UNCAUGHT \
#define JSOPTION_DONT_REPORT_UNCAUGHT \
JS_BIT(8) /* When returning from the
outermost API call, prevent
uncaught exceptions from
@ -2777,7 +2779,7 @@ JS_StringToVersion(const char *string);
"use strict" annotations. */
/* Options which reflect compile-time properties of scripts. */
#define JSCOMPILEOPTION_MASK (JSOPTION_MOAR_XML)
#define JSCOMPILEOPTION_MASK (JSOPTION_ALLOW_XML | JSOPTION_MOAR_XML)
#define JSRUNOPTION_MASK (JS_BITMASK(20) & ~JSCOMPILEOPTION_MASK)
#define JSALLOPTION_MASK (JSCOMPILEOPTION_MASK | JSRUNOPTION_MASK)

View File

@ -905,6 +905,12 @@ namespace js {
struct AutoResolving;
static inline bool
OptionsHasAllowXML(uint32_t options)
{
return !!(options & JSOPTION_ALLOW_XML);
}
static inline bool
OptionsHasMoarXML(uint32_t options)
{
@ -928,7 +934,8 @@ OptionsSameVersionFlags(uint32_t self, uint32_t other)
*/
namespace VersionFlags {
static const unsigned MASK = 0x0FFF; /* see JSVersion in jspubtd.h */
static const unsigned MOAR_XML = 0x1000; /* flag induced by JSOPTION_MOAR_XML */
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;
} /* namespace VersionFlags */
@ -938,6 +945,12 @@ 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)
{
@ -972,7 +985,8 @@ VersionHasFlags(JSVersion version)
static inline unsigned
VersionFlagsToOptions(JSVersion version)
{
unsigned copts = VersionHasMoarXML(version) ? JSOPTION_MOAR_XML : 0;
unsigned copts = (VersionHasAllowXML(version) ? JSOPTION_ALLOW_XML : 0) |
(VersionHasMoarXML(version) ? JSOPTION_MOAR_XML : 0);
JS_ASSERT((copts & JSCOMPILEOPTION_MASK) == copts);
return copts;
}
@ -980,7 +994,13 @@ VersionFlagsToOptions(JSVersion version)
static inline JSVersion
OptionFlagsToVersion(unsigned options, JSVersion version)
{
return VersionSetMoarXML(version, OptionsHasMoarXML(options));
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);
}
static inline bool

View File

@ -584,6 +584,7 @@ static const struct JSOption {
{"strict", JSOPTION_STRICT},
{"typeinfer", JSOPTION_TYPE_INFERENCE},
{"werror", JSOPTION_WERROR},
{"allow_xml", JSOPTION_ALLOW_XML},
{"moar_xml", JSOPTION_MOAR_XML},
{"strict_mode", JSOPTION_STRICT_MODE},
};

View File

@ -679,6 +679,7 @@ if (typeof options == 'function')
{
optionsInit();
optionsClear();
options("allow_xml");
}
function getTestCaseResult(expected, actual)

View File

@ -25,7 +25,7 @@ namespace js {
* and saved versions. If deserialization fails, the data should be
* invalidated if possible.
*/
static const uint32_t XDR_BYTECODE_VERSION = uint32_t(0xb973c0de - 116);
static const uint32_t XDR_BYTECODE_VERSION = uint32_t(0xb973c0de - 117);
class XDRBuffer {
public:

View File

@ -403,7 +403,7 @@ mozJSComponentLoader::ReallyInit()
return NS_ERROR_OUT_OF_MEMORY;
uint32_t options = JS_GetOptions(mContext);
JS_SetOptions(mContext, options | JSOPTION_MOAR_XML);
JS_SetOptions(mContext, options | JSOPTION_ALLOW_XML | JSOPTION_MOAR_XML);
// Always use the latest js version
JS_SetVersion(mContext, JSVERSION_LATEST);

View File

@ -683,6 +683,7 @@ static const struct JSOption {
{"relimit", JSOPTION_RELIMIT},
{"strict", JSOPTION_STRICT},
{"werror", JSOPTION_WERROR},
{"allow_xml", JSOPTION_ALLOW_XML},
{"moar_xml", JSOPTION_MOAR_XML},
{"strict_mode", JSOPTION_STRICT_MODE},
};
@ -1811,6 +1812,7 @@ main(int argc, char **argv, char **envp)
return 1;
}
JS_SetOptions(cx, JS_GetOptions(cx) | JSOPTION_ALLOW_XML);
xpc_LocalizeContext(cx);
nsCOMPtr<nsIXPConnect> xpc = do_GetService(nsIXPConnect::GetCID());

View File

@ -3496,7 +3496,8 @@ ContextHolder::ContextHolder(JSContext *aOuterCx, JSObject *aSandbox)
JS_SetOptions(mJSContext,
JS_GetOptions(mJSContext) |
JSOPTION_DONT_REPORT_UNCAUGHT |
JSOPTION_PRIVATE_IS_NSISUPPORTS);
JSOPTION_PRIVATE_IS_NSISUPPORTS |
JSOPTION_ALLOW_XML);
JS_SetGlobalObject(mJSContext, aSandbox);
JS_SetContextPrivate(mJSContext, this);
JS_SetOperationCallback(mJSContext, ContextHolderOperationCallback);