--- a/content/events/src/nsEventListenerManager.cpp
+++ b/content/events/src/nsEventListenerManager.cpp
@@ -807,16 +807,17 @@ nsEventListenerManager::AddScriptEventLi
PRUint32 argCount;
const char **argNames;
nsContentUtils::GetEventArgNames(nameSpace, aName, &argCount,
&argNames);
rv = context->CompileEventHandler(aName, argCount, argNames,
aBody,
url.get(), lineNo,
+ SCRIPTVERSION_DEFAULT, // for now?
handler);
if (rv == NS_ERROR_ILLEGAL_VALUE) {
NS_WARNING("Probably a syntax error in the event handler!");
return NS_SUCCESS_LOSS_OF_INSIGNIFICANT_DATA;
}
NS_ENSURE_SUCCESS(rv, rv);
// And bind it.
rv = context->BindCompiledEventHandler(aObject, scope,
@@ -1022,16 +1023,17 @@ nsEventListenerManager::CompileEventHand
const char **argNames;
nsContentUtils::GetEventArgNames(content->GetNameSpaceID(), aName,
&argCount, &argNames);
result = aContext->CompileEventHandler(aName,
argCount, argNames,
handlerBody,
url.get(), lineNo,
+ SCRIPTVERSION_DEFAULT, // for now?
handler);
NS_ENSURE_SUCCESS(result, result);
// And bind it.
result = aContext->BindCompiledEventHandler(aObject, aScope,
aName, handler);
NS_ENSURE_SUCCESS(result, result);
}
--- a/content/html/content/src/nsHTMLScriptElement.cpp
+++ b/content/html/content/src/nsHTMLScriptElement.cpp
@@ -278,16 +278,17 @@ nsHTMLScriptEventHandler::Invoke(nsISupp
rv = scriptContext->CompileFunction(scriptObject,
funcName, // method name
argc, // no of arguments
args, // argument names
scriptBody, // script text
nsnull, // XXX: URL
lineNumber, // line no (for errors)
+ JSVERSION_DEFAULT, // Default for now?
PR_FALSE, // shared ?
&funcObject);
// Free the argument names array if it was heap allocated...
if (args != stackArgs) {
delete [] args;
}
// Fail if there was an error compiling the script.
--- a/content/xbl/src/nsXBLProtoImpl.cpp
+++ b/content/xbl/src/nsXBLProtoImpl.cpp
@@ -78,22 +78,28 @@ nsXBLProtoImpl::InstallImplementation(ns
void * targetClassObject = nsnull;
nsresult rv = InitTargetObjects(aBinding, context, aBoundElement,
getter_AddRefs(holder), &targetClassObject);
NS_ENSURE_SUCCESS(rv, rv); // kick out if we were unable to properly intialize our target objects
JSObject * targetScriptObject;
holder->GetJSObject(&targetScriptObject);
+ JSContext *cx = (JSContext *)context->GetNativeContext();
+ // Set version up front so we don't thrash it
+ JSVersion oldVersion = ::JS_SetVersion(cx, JSVERSION_LATEST);
+
// Walk our member list and install each one in turn.
for (nsXBLProtoImplMember* curr = mMembers;
curr;
curr = curr->GetNext())
curr->InstallMember(context, aBoundElement, targetScriptObject,
targetClassObject, mClassName);
+
+ ::JS_SetVersion(cx, oldVersion);
return NS_OK;
}
nsresult
nsXBLProtoImpl::InitTargetObjects(nsXBLPrototypeBinding* aBinding,
nsIScriptContext* aContext,
nsIContent* aBoundElement,
nsIXPConnectJSObjectHolder** aScriptObjectHolder,
@@ -166,41 +172,48 @@ nsXBLProtoImpl::CompilePrototypeMembers(
// context.
nsCOMPtr<nsIScriptGlobalObjectOwner> globalOwner(
do_QueryInterface(aBinding->XBLDocumentInfo()));
nsIScriptGlobalObject* globalObject = globalOwner->GetScriptGlobalObject();
NS_ENSURE_TRUE(globalObject, NS_ERROR_UNEXPECTED);
nsIScriptContext *context = globalObject->GetContext();
NS_ENSURE_TRUE(context, NS_ERROR_OUT_OF_MEMORY);
+
+ JSContext *cx = (JSContext *)context->GetNativeContext();
JSObject *global = globalObject->GetGlobalJSObject();
+
void* classObject;
- nsresult rv = aBinding->InitClass(mClassName,
- (JSContext *)context->GetNativeContext(),
- global, global,
+ nsresult rv = aBinding->InitClass(mClassName, cx, global, global,
&classObject);
if (NS_FAILED(rv))
return rv;
mClassObject = (JSObject*) classObject;
if (!mClassObject)
return NS_ERROR_FAILURE;
+ // Set version up front so we don't thrash it
+ JSVersion oldVersion = ::JS_SetVersion(cx, JSVERSION_LATEST);
+
// Now that we have a class object installed, we walk our member list and compile each of our
// properties and methods in turn.
for (nsXBLProtoImplMember* curr = mMembers;
curr;
curr = curr->GetNext()) {
nsresult rv = curr->CompileMember(context, mClassName, mClassObject);
if (NS_FAILED(rv)) {
DestroyMembers();
+ ::JS_SetVersion(cx, oldVersion);
return rv;
}
}
+
+ ::JS_SetVersion(cx, oldVersion);
return NS_OK;
}
void
nsXBLProtoImpl::Trace(TraceCallback aCallback, void *aClosure) const
{
// If we don't have a class object then we either didn't compile members
// or we only have fields, in both cases there are no cycles through our
@@ -233,29 +246,33 @@ nsXBLProtoImpl::FindField(const nsString
}
return nsnull;
}
PRBool
nsXBLProtoImpl::ResolveAllFields(JSContext *cx, JSObject *obj) const
{
+ // Set version up front so we don't thrash it
+ JSVersion oldVersion = ::JS_SetVersion(cx, JSVERSION_LATEST);
for (nsXBLProtoImplField* f = mFields; f; f = f->GetNext()) {
// Using OBJ_LOOKUP_PROPERTY is a pain, since what we have is a
// PRUnichar* for the property name. Let's just use the public API and
// all.
nsDependentString name(f->GetName());
jsval dummy;
if (!::JS_LookupUCProperty(cx, obj,
reinterpret_cast<const jschar*>(name.get()),
name.Length(), &dummy)) {
+ ::JS_SetVersion(cx, oldVersion);
return PR_FALSE;
}
}
+ ::JS_SetVersion(cx, oldVersion);
return PR_TRUE;
}
void
nsXBLProtoImpl::UndefineFields(JSContext *cx, JSObject *obj) const
{
JSAutoRequest ar(cx);
for (nsXBLProtoImplField* f = mFields; f; f = f->GetNext()) {
--- a/content/xbl/src/nsXBLProtoImplField.cpp
+++ b/content/xbl/src/nsXBLProtoImplField.cpp
@@ -123,17 +123,17 @@ nsXBLProtoImplField::InstallField(nsIScr
// XXX Could we produce a better principal here? Should be able
// to, really!
PRBool undefined;
nsCOMPtr<nsIScriptContext> context = aContext;
rv = context->EvaluateStringWithValue(nsDependentString(mFieldText,
mFieldTextLength),
aBoundNode,
nsnull, uriSpec.get(),
- mLineNumber, nsnull,
+ mLineNumber, JSVERSION_LATEST,
(void*) &result, &undefined);
if (NS_FAILED(rv))
return rv;
if (undefined) {
result = JSVAL_VOID;
}
--- a/content/xbl/src/nsXBLProtoImplMethod.cpp
+++ b/content/xbl/src/nsXBLProtoImplMethod.cpp
@@ -235,16 +235,17 @@ nsXBLProtoImplMethod::CompileMember(nsIS
JSObject* methodObject = nsnull;
nsresult rv = aContext->CompileFunction(aClassObject,
cname,
paramCount,
(const char**)args,
body,
functionUri.get(),
uncompiledMethod->mBodyText.GetLineNumber(),
+ JSVERSION_LATEST,
PR_TRUE,
(void **) &methodObject);
// Destroy our uncompiled method and delete our arg list.
delete uncompiledMethod;
delete [] args;
if (NS_FAILED(rv)) {
SetUncompiledMethod(nsnull);
--- a/content/xbl/src/nsXBLProtoImplProperty.cpp
+++ b/content/xbl/src/nsXBLProtoImplProperty.cpp
@@ -237,16 +237,17 @@ nsXBLProtoImplProperty::CompileMember(ns
rv = aContext->CompileFunction(aClassObject,
NS_LITERAL_CSTRING("get_") +
NS_ConvertUTF16toUTF8(mName),
0,
nsnull,
getter,
functionUri.get(),
mGetterText->GetLineNumber(),
+ JSVERSION_LATEST,
PR_TRUE,
(void **) &getterObject);
// Make sure we free mGetterText here before setting mJSGetterObject, since
// that'll overwrite mGetterText
delete mGetterText;
deletedGetter = PR_TRUE;
mJSGetterObject = getterObject;
@@ -286,16 +287,17 @@ nsXBLProtoImplProperty::CompileMember(ns
rv = aContext->CompileFunction(aClassObject,
NS_LITERAL_CSTRING("set_") +
NS_ConvertUTF16toUTF8(mName),
1,
gPropertyArgs,
setter,
functionUri.get(),
mSetterText->GetLineNumber(),
+ JSVERSION_LATEST,
PR_TRUE,
(void **) &setterObject);
// Make sure we free mSetterText here before setting mJSGetterObject, since
// that'll overwrite mSetterText
delete mSetterText;
deletedSetter = PR_TRUE;
mJSSetterObject = setterObject;
--- a/content/xbl/src/nsXBLPrototypeHandler.cpp
+++ b/content/xbl/src/nsXBLPrototypeHandler.cpp
@@ -369,18 +369,20 @@ nsXBLPrototypeHandler::EnsureEventHandle
nsCAutoString bindingURI;
mPrototypeBinding->DocURI()->GetSpec(bindingURI);
PRUint32 argCount;
const char **argNames;
nsContentUtils::GetEventArgNames(kNameSpaceID_XBL, aName, &argCount,
&argNames);
nsresult rv = aBoundContext->CompileEventHandler(aName, argCount, argNames,
- handlerText, bindingURI.get(),
- mLineNumber, aHandler);
+ handlerText,
+ bindingURI.get(),
+ mLineNumber,
+ JSVERSION_LATEST, aHandler);
NS_ENSURE_SUCCESS(rv, rv);
if (pWindow) {
pWindow->CacheXBLPrototypeHandler(this, aHandler);
}
return NS_OK;
}
--- a/content/xbl/test/Makefile.in
+++ b/content/xbl/test/Makefile.in
@@ -49,16 +49,17 @@ include $(topsrcdir)/config/rules.mk
_TEST_FILES = \
test_bug296375.xul \
test_bug310107.html \
test_bug366770.html \
test_bug371724.xhtml \
test_bug372769.xhtml \
test_bug378866.xhtml \
test_bug397934.xhtml \
+ test_bug389322.xhtml \
test_bug398135.xhtml \
test_bug398492.xul \
test_bug400705.xhtml \
test_bug401907.xhtml \
test_bug403162.xhtml \
bug310107-resource.xhtml \
$(NULL)
new file mode 100644
--- /dev/null
+++ b/content/xbl/test/test_bug389322.xhtml
@@ -0,0 +1,126 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=389322
+-->
+<head>
+ <title>Test for Bug 389322</title>
+ <script type="text/javascript" src="/MochiKit/packed.js"></script>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+ <script>var ctorRan = false;</script>
+ <bindings xmlns="http://www.mozilla.org/xbl">
+ <binding id="test">
+ <implementation>
+ <field name="field"><![CDATA[
+ (function () {
+ try {
+ let (x=1) (x);
+ var success = true;
+ }
+ catch (e) { success = false; }
+ report("XBL fields", success)
+ return ""
+ }())
+ ]]></field>
+ <property name="property">
+ <getter><![CDATA[
+ try {
+ let (x=1) (x);
+ var success = true;
+ }
+ catch (e) { success = false; }
+ report("XBL property getters", success)
+ return 1
+ ]]></getter>
+ <setter><![CDATA[
+ try {
+ let (x=1) (x);
+ var success = true
+ }
+ catch (e) { success = false }
+ report("XBL property setters", success)
+ return val
+ ]]></setter>
+ </property>
+ <method name="method">
+ <body><![CDATA[
+ try {
+ let (x=1) (x);
+ var success = true;
+ }
+ catch (e) { success = false; }
+ report("XBL methods", success)
+ ]]></body>
+ </method>
+ <constructor><![CDATA[
+ this.property += 1
+ var x = this.field;
+ this.method()
+ try {
+ let (x=1) (x);
+ var success = true
+ }
+ catch (e) { success = false }
+ report("XBL constructors", success)
+
+ var ev = document.createEvent("Events")
+ ev.initEvent("custom", false, false)
+ this.dispatchEvent(ev)
+ ctorRan = true;
+ ]]></constructor>
+ </implementation>
+ <handlers>
+ <handler action='
+ try {
+ let (x=1) (x);
+ var success = true
+ }
+ catch (e) { success = false }
+ report("XBL event handlers", success);
+ ' event="custom"/>
+ </handlers>
+ </binding>
+ </bindings>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=389322">Mozilla Bug 389322</a>
+<p id="display" style="-moz-binding: url(#test)"></p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+<![CDATA[
+
+/** Test for Bug 389322 **/
+SimpleTest.waitForExplicitFinish();
+addLoadEvent(function() {
+ is(ctorRan, true, "Constructor should have run");
+});
+addLoadEvent(SimpleTest.finish);
+
+function report(testName, success) {
+ is(success, true, "JS 1.7 should work in " + testName);
+}
+]]>
+</script>
+<script type="text/javascript; version=1.7"><![CDATA[
+ try {
+ let (x=1) (x);
+ var success = true;
+ }
+ catch (e) { success = false; }
+ report("HTML script tags with explicit version", success)
+]]></script>
+<script type="text/javascript"><![CDATA[
+ try {
+ let (x=1) (x);
+ var success = false;
+ }
+ catch (e) { success = true; }
+ is(success, true, "JS 1.7 should not work in versionless HTML script tags");
+]]></script>
+</pre>
+</body>
+</html>
+
--- a/content/xul/content/src/nsXULElement.cpp
+++ b/content/xul/content/src/nsXULElement.cpp
@@ -733,17 +733,19 @@ nsScriptEventHandlerOwnerTearoff::Compil
}
// Compile the event handler
PRUint32 argCount;
const char **argNames;
nsContentUtils::GetEventArgNames(kNameSpaceID_XUL, aName, &argCount,
&argNames);
rv = context->CompileEventHandler(aName, argCount, argNames,
- aBody, aURL, aLineNo, aHandler);
+ aBody, aURL, aLineNo,
+ SCRIPTVERSION_DEFAULT, // for now?
+ aHandler);
if (NS_FAILED(rv)) return rv;
// XXX: Shouldn't this use context and not aContext?
// XXXmarkh - is GetNativeGlobal() the correct scope?
rv = aContext->BindCompiledEventHandler(aTarget, aContext->GetNativeGlobal(),
aName, aHandler);
if (NS_FAILED(rv)) return rv;
--- a/dom/public/nsIScriptContext.h
+++ b/dom/public/nsIScriptContext.h
@@ -52,19 +52,23 @@ class nsIArray;
class nsIVariant;
class nsIObjectInputStream;
class nsIObjectOutputStream;
class nsScriptObjectHolder;
typedef void (*nsScriptTerminationFunc)(nsISupports* aRef);
#define NS_ISCRIPTCONTEXT_IID \
-{ /* {52B46C37-A078-4952-AED7-035D83C810C0} */ \
- 0x52b46c37, 0xa078, 0x4952, \
- {0xae, 0xd7, 0x3, 0x5d, 0x83, 0xc8, 0x10, 0xc0 } }
+{ /* {09316a0e-8d05-4d26-9efd-8f907a7c79d2} */ \
+ 0x09316a0e, 0x8d05, 0x4d26, \
+ { 0x9e, 0xfd, 0x8f, 0x90, 0x7a, 0x7c, 0x79, 0xd2 } }
+
+/* This MUST match JSVERSION_DEFAULT. This version stuff if we don't
+ know what language we have is a little silly... */
+#define SCRIPTVERSION_DEFAULT JSVERSION_DEFAULT
/**
* It is used by the application to initialize a runtime and run scripts.
* A script runtime would implement this interface.
* <P><I>It does have a bit too much java script information now, that
* should be removed in a short time. Ideally this interface will be
* language neutral</I>
*/
@@ -171,26 +175,29 @@ public:
*
* @param aName an nsIAtom pointer naming the function; it must be lowercase
* and ASCII, and should not be longer than 63 chars. This bound on
* length is enforced only by assertions, so caveat caller!
* @param aEventName the name that the event object should be bound to
* @param aBody the event handler function's body
* @param aURL the URL or filename for error messages
* @param aLineNo the starting line number of the script for error messages
+ * @param aVersion the script language version to use when executing
* @param aHandler the out parameter in which a void pointer to the compiled
* function object is stored on success
*
* @return NS_OK if the function body was valid and got compiled
*/
virtual nsresult CompileEventHandler(nsIAtom* aName,
PRUint32 aArgCount,
const char** aArgNames,
const nsAString& aBody,
- const char* aURL, PRUint32 aLineNo,
+ const char* aURL,
+ PRUint32 aLineNo,
+ PRUint32 aVersion,
nsScriptObjectHolder &aHandler) = 0;
/**
* Call the function object with given args and return its boolean result,
* or true if the result isn't boolean.
*
* @param aTarget the event target
* @param aScript an object telling the scope in which to call the compiled
@@ -250,16 +257,17 @@ public:
**/
virtual nsresult CompileFunction(void* aTarget,
const nsACString& aName,
PRUint32 aArgCount,
const char** aArgArray,
const nsAString& aBody,
const char* aURL,
PRUint32 aLineNo,
+ PRUint32 aVersion,
PRBool aShared,
void **aFunctionObject) = 0;
/**
* Set the default scripting language version for this context, which must
* be a context specific to a particular scripting language.
*
**/
--- a/dom/src/base/nsJSEnvironment.cpp
+++ b/dom/src/base/nsJSEnvironment.cpp
@@ -294,16 +294,60 @@ NS_IMPL_ISUPPORTS1(nsCCMemoryPressureObs
NS_IMETHODIMP
nsCCMemoryPressureObserver::Observe(nsISupports* aSubject, const char* aTopic,
const PRUnichar* aData)
{
nsJSContext::CC();
return NS_OK;
}
+class nsJSVersionSetter {
+public:
+ nsJSVersionSetter(JSContext *aContext, PRUint32 aVersion);
+ ~nsJSVersionSetter();
+
+private:
+ JSContext* mContext;
+ uint32 mOldOptions;
+ JSVersion mOldVersion;
+ JSBool mOptionsChanged;
+};
+
+nsJSVersionSetter::nsJSVersionSetter(JSContext *aContext, PRUint32 aVersion)
+ : mContext(aContext)
+{
+ // JSVERSION_HAS_XML may be set in our version mask - however, we can't
+ // simply pass this directly to JS_SetOptions as it masks out that bit -
+ // the only way to make this happen is via JS_SetOptions.
+ JSBool hasxml = (aVersion & JSVERSION_HAS_XML) != 0;
+ mOldOptions = ::JS_GetOptions(mContext);
+ mOptionsChanged = ((hasxml) ^ !!(mOldOptions & JSOPTION_XML));
+
+ if (mOptionsChanged) {
+ ::JS_SetOptions(mContext,
+ hasxml
+ ? mOldOptions | JSOPTION_XML
+ : mOldOptions & ~JSOPTION_XML);
+ }
+
+ // Change the version - this is cheap when the versions match, so no need
+ // to optimize here...
+ JSVersion newVer = (JSVersion)(aVersion & JSVERSION_MASK);
+ mOldVersion = ::JS_SetVersion(mContext, newVer);
+}
+
+nsJSVersionSetter::~nsJSVersionSetter()
+{
+ ::JS_SetVersion(mContext, mOldVersion);
+
+ if (mOptionsChanged) {
+ ::JS_SetOptions(mContext, mOldOptions);
+ }
+}
+
/****************************************************************
************************** AutoFree ****************************
****************************************************************/
class AutoFree {
public:
AutoFree(void *aPtr) : mPtr(aPtr) {
@@ -1255,55 +1299,32 @@ nsJSContext::EvaluateStringWithValue(con
return NS_ERROR_FAILURE;
}
jsval val;
nsJSContext::TerminationFuncHolder holder(this);
// SecurityManager said "ok", but don't compile if aVersion is unknown.
- // Do compile with the default version (and avoid thrashing the context's
- // version) if aVersion is the default.
- // As the caller is responsible for parsing the version strings, we just
+ // Since the caller is responsible for parsing the version strings, we just
// check it isn't JSVERSION_UNKNOWN.
if (ok && ((JSVersion)aVersion) != JSVERSION_UNKNOWN) {
- // JSVERSION_HAS_XML may be set in our version mask - however, we can't
- // simply pass this directly to JS_SetOptions as it masks out that bit -
- // the only way to make this happen is via JS_SetOptions.
- JSBool hasxml = (aVersion & JSVERSION_HAS_XML) != 0;
- uint32 jsoptions = ::JS_GetOptions(mContext);
- JSBool optionsChanged = ((hasxml) ^ !!(jsoptions & JSOPTION_XML));
-
- if (optionsChanged) {
- ::JS_SetOptions(mContext,
- hasxml
- ? jsoptions | JSOPTION_XML
- : jsoptions & ~JSOPTION_XML);
- }
- // Change the version - this is cheap when the versions match, so no need
- // to optimize here...
- JSVersion newVer = (JSVersion)(aVersion & JSVERSION_MASK);
- JSVersion oldVer = ::JS_SetVersion(mContext, newVer);
+
JSAutoRequest ar(mContext);
+ nsJSVersionSetter setVersion(mContext, aVersion);
ok = ::JS_EvaluateUCScriptForPrincipals(mContext,
(JSObject *)aScopeObject,
jsprin,
(jschar*)PromiseFlatString(aScript).get(),
aScript.Length(),
aURL,
aLineNo,
&val);
- ::JS_SetVersion(mContext, oldVer);
-
- if (optionsChanged) {
- ::JS_SetOptions(mContext, jsoptions);
- }
-
if (!ok) {
// Tell XPConnect about any pending exceptions. This is needed
// to avoid dropping JS exceptions in case we got here through
// nested calls through XPConnect.
nsContentUtils::NotifyXPCIfExceptionPending(mContext);
}
}
@@ -1458,55 +1479,31 @@ nsJSContext::EvaluateString(const nsAStr
//
// TODO: use JS_Begin/EndRequest to keep the GC from racing with JS
// execution on any thread.
jsval val;
nsJSContext::TerminationFuncHolder holder(this);
// SecurityManager said "ok", but don't compile if aVersion is unknown.
- // Do compile with the default version (and avoid thrashing the context's
- // version) if aVersion is the default.
- // As the caller is responsible for parsing the version strings, we just
+ // Since the caller is responsible for parsing the version strings, we just
// check it isn't JSVERSION_UNKNOWN.
if (ok && ((JSVersion)aVersion) != JSVERSION_UNKNOWN) {
JSAutoRequest ar(mContext);
- // JSVERSION_HAS_XML may be set in our version mask - however, we can't
- // simply pass this directly to JS_SetOptions as it masks out that bit -
- // the only way to make this happen is via JS_SetOptions.
- JSBool hasxml = (aVersion & JSVERSION_HAS_XML) != 0;
- uint32 jsoptions = ::JS_GetOptions(mContext);
- JSBool optionsChanged = ((hasxml) ^ !!(jsoptions & JSOPTION_XML));
-
- if (optionsChanged) {
- ::JS_SetOptions(mContext,
- hasxml
- ? jsoptions | JSOPTION_XML
- : jsoptions & ~JSOPTION_XML);
- }
- // Change the version - this is cheap when the versions match, so no need
- // to optimize here...
- JSVersion newVer = (JSVersion)(aVersion & JSVERSION_MASK);
- JSVersion oldVer = ::JS_SetVersion(mContext, newVer);
+ nsJSVersionSetter setVersion(mContext, aVersion);
ok = ::JS_EvaluateUCScriptForPrincipals(mContext,
(JSObject *)aScopeObject,
jsprin,
(jschar*)PromiseFlatString(aScript).get(),
aScript.Length(),
aURL,
aLineNo,
&val);
- ::JS_SetVersion(mContext, oldVer);
-
- if (optionsChanged) {
- ::JS_SetOptions(mContext, jsoptions);
- }
-
if (!ok) {
// Tell XPConnect about any pending exceptions. This is needed
// to avoid dropping JS exceptions in case we got here through
// nested calls through XPConnect.
nsContentUtils::NotifyXPCIfExceptionPending(mContext);
}
}
@@ -1567,39 +1564,21 @@ nsJSContext::CompileScript(const PRUnich
if (NS_FAILED(rv)) {
JSPRINCIPALS_DROP(mContext, jsprin);
return NS_ERROR_FAILURE;
}
aScriptObject.drop(); // ensure old object not used on failure...
// SecurityManager said "ok", but don't compile if aVersion is unknown.
- // Do compile with the default version (and avoid thrashing the context's
- // version) if aVersion is the default.
- // As the caller is responsible for parsing the version strings, we just
+ // Since the caller is responsible for parsing the version strings, we just
// check it isn't JSVERSION_UNKNOWN.
if (ok && ((JSVersion)aVersion) != JSVERSION_UNKNOWN) {
- // JSVERSION_HAS_XML may be set in our version mask - however, we can't
- // simply pass this directly to JS_SetOptions as it masks out that bit -
- // the only way to make this happen is via JS_SetOptions.
JSAutoRequest ar(mContext);
- JSBool hasxml = (aVersion & JSVERSION_HAS_XML) != 0;
- uint32 jsoptions = ::JS_GetOptions(mContext);
- JSBool optionsChanged = ((hasxml) ^ !!(jsoptions & JSOPTION_XML));
-
- if (optionsChanged) {
- ::JS_SetOptions(mContext,
- hasxml
- ? jsoptions | JSOPTION_XML
- : jsoptions & ~JSOPTION_XML);
- }
- // Change the version - this is cheap when the versions match, so no need
- // to optimize here...
- JSVersion newVer = (JSVersion)(aVersion & JSVERSION_MASK);
- JSVersion oldVer = ::JS_SetVersion(mContext, newVer);
+ nsJSVersionSetter setVersion(mContext, aVersion);
JSScript* script =
::JS_CompileUCScriptForPrincipals(mContext,
(JSObject *)aScopeObject,
jsprin,
(jschar*) aText,
aTextLength,
aURL,
@@ -1609,23 +1588,18 @@ nsJSContext::CompileScript(const PRUnich
if (scriptObject) {
NS_ASSERTION(aScriptObject.getScriptTypeID()==JAVASCRIPT,
"Expecting JS script object holder");
rv = aScriptObject.set(scriptObject);
} else {
::JS_DestroyScript(mContext, script);
script = nsnull;
}
- } else
+ } else {
rv = NS_ERROR_OUT_OF_MEMORY;
-
- ::JS_SetVersion(mContext, oldVer);
-
- if (optionsChanged) {
- ::JS_SetOptions(mContext, jsoptions);
}
}
// Whew! Finally done.
JSPRINCIPALS_DROP(mContext, jsprin);
return rv;
}
@@ -1755,33 +1729,42 @@ nsJSContext::JSObjectFromInterface(nsISu
nsresult
nsJSContext::CompileEventHandler(nsIAtom *aName,
PRUint32 aArgCount,
const char** aArgNames,
const nsAString& aBody,
const char *aURL, PRUint32 aLineNo,
+ PRUint32 aVersion,
nsScriptObjectHolder &aHandler)
{
NS_ENSURE_TRUE(mIsInitialized, NS_ERROR_NOT_INITIALIZED);
if (!sSecurityManager) {
NS_ERROR("Huh, we need a script security manager to compile "
"an event handler!");
return NS_ERROR_UNEXPECTED;
}
+ // Don't compile if aVersion is unknown. Since the caller is responsible for
+ // parsing the version strings, we just check it isn't JSVERSION_UNKNOWN.
+ if ((JSVersion)aVersion == JSVERSION_UNKNOWN) {
+ return NS_ERROR_ILLEGAL_VALUE;
+ }
+
const char *charName = AtomToEventHandlerName(aName);
// Event handlers are always shared, and must be bound before use.
// Therefore we never bother compiling with principals.
// (that probably means we should avoid JS_CompileUCFunctionForPrincipals!)
JSAutoRequest ar(mContext);
+ nsJSVersionSetter setVersion(mContext, aVersion);
+
JSFunction* fun =
::JS_CompileUCFunctionForPrincipals(mContext,
nsnull, nsnull,
charName, aArgCount, aArgNames,
(jschar*)PromiseFlatString(aBody).get(),
aBody.Length(),
aURL, aLineNo);
@@ -1800,21 +1783,28 @@ nsJSContext::CompileEventHandler(nsIAtom
nsresult
nsJSContext::CompileFunction(void* aTarget,
const nsACString& aName,
PRUint32 aArgCount,
const char** aArgArray,
const nsAString& aBody,
const char* aURL,
PRUint32 aLineNo,
+ PRUint32 aVersion,
PRBool aShared,
void** aFunctionObject)
{
NS_ENSURE_TRUE(mIsInitialized, NS_ERROR_NOT_INITIALIZED);
+ // Don't compile if aVersion is unknown. Since the caller is responsible for
+ // parsing the version strings, we just check it isn't JSVERSION_UNKNOWN.
+ if ((JSVersion)aVersion == JSVERSION_UNKNOWN) {
+ return NS_ERROR_ILLEGAL_VALUE;
+ }
+
JSPrincipals *jsprin = nsnull;
nsIScriptGlobalObject *global = GetGlobalObject();
if (global) {
// XXXbe why the two-step QI? speed up via a new GetGlobalObjectData func?
nsCOMPtr<nsIScriptObjectPrincipal> globalData = do_QueryInterface(global);
if (globalData) {
nsIPrincipal *prin = globalData->GetPrincipal();
@@ -1822,16 +1812,17 @@ nsJSContext::CompileFunction(void* aTarg
return NS_ERROR_FAILURE;
prin->GetJSPrincipals(mContext, &jsprin);
}
}
JSObject *target = (JSObject*)aTarget;
JSAutoRequest ar(mContext);
+ nsJSVersionSetter setVersion(mContext, aVersion);
JSFunction* fun =
::JS_CompileUCFunctionForPrincipals(mContext,
aShared ? nsnull : target, jsprin,
PromiseFlatCString(aName).get(),
aArgCount, aArgArray,
(jschar*)PromiseFlatString(aBody).get(),
aBody.Length(),
--- a/dom/src/base/nsJSEnvironment.h
+++ b/dom/src/base/nsJSEnvironment.h
@@ -94,16 +94,17 @@ public:
nsAString* aRetValue,
PRBool* aIsUndefined);
virtual nsresult CompileEventHandler(nsIAtom *aName,
PRUint32 aArgCount,
const char** aArgNames,
const nsAString& aBody,
const char *aURL, PRUint32 aLineNo,
+ PRUint32 aVersion,
nsScriptObjectHolder &aHandler);
virtual nsresult CallEventHandler(nsISupports* aTarget, void *aScope,
void* aHandler,
nsIArray *argv, nsIVariant **rv);
virtual nsresult BindCompiledEventHandler(nsISupports *aTarget,
void *aScope,
nsIAtom *aName,
void *aHandler);
@@ -112,16 +113,17 @@ public:
nsScriptObjectHolder &aHandler);
virtual nsresult CompileFunction(void* aTarget,
const nsACString& aName,
PRUint32 aArgCount,
const char** aArgArray,
const nsAString& aBody,
const char* aURL,
PRUint32 aLineNo,
+ PRUint32 aVersion,
PRBool aShared,
void** aFunctionObject);
virtual void SetDefaultLanguageVersion(PRUint32 aVersion);
virtual nsIScriptGlobalObject *GetGlobalObject();
virtual void *GetNativeContext();
virtual void *GetNativeGlobal();
virtual nsresult CreateNativeGlobalForInner(
--- a/extensions/python/dom/nsdom/context.py
+++ b/extensions/python/dom/nsdom/context.py
@@ -440,17 +440,17 @@ class ScriptContext:
assert type(scriptObject) == types.CodeType, \
"Script object should be a code object (got %r)" % (scriptObject,)
exec scriptObject in scopeObject
def CompileScript(self, text, scopeObject, principal, url, lineno, version):
# The line number passed is the first; offset is -1
return domcompile.compile(text, url, lineno=lineno-1)
- def CompileEventHandler(self, name, argNames, body, url, lineno):
+ def CompileEventHandler(self, name, argNames, body, url, lineno, version):
if __debug__:
logger.debug("%s.CompileEventHandler %s %s:%s ('%s')",
self, name, url, lineno, body[:100])
co = domcompile.compile_function(body, url, name, argNames,
lineno=lineno-1)
g = {}
exec co in g
handler = g[name]
--- a/extensions/python/dom/src/nsPyContext.cpp
+++ b/extensions/python/dom/src/nsPyContext.cpp
@@ -470,16 +470,17 @@ nsPythonContext::CompileScript(const PRU
}
nsresult
nsPythonContext::CompileEventHandler(nsIAtom *aName,
PRUint32 aArgCount,
const char** aArgNames,
const nsAString& aBody,
const char *aURL, PRUint32 aLineNo,
+ PRUint32 aVersion;
nsScriptObjectHolder &aHandler)
{
NS_ENSURE_TRUE(mIsInitialized, NS_ERROR_NOT_INITIALIZED);
NS_TIMELINE_MARK_FUNCTION("nsPythonContext::CompileEventHandler");
NS_ASSERTION(mDelegate, "Script context has no delegate");
NS_ENSURE_TRUE(mDelegate, NS_ERROR_UNEXPECTED);
@@ -493,17 +494,17 @@ nsPythonContext::CompileEventHandler(nsI
for (PRUint32 i=0;i<aArgCount;i++) {
PyList_SET_ITEM(argNames, i, PyString_FromString(aArgNames[i]));
}
PyObject *ret = PyObject_CallMethod(mDelegate, "CompileEventHandler",
"sNNsi",
AtomToEventHandlerName(aName),
argNames,
PyObject_FromNSString(aBody),
- aURL, aLineNo);
+ aURL, aLineNo, aVersion);
if (!ret)
return HandlePythonError();
NS_ASSERTION(aHandler.getScriptTypeID()==nsIProgrammingLanguage::PYTHON,
"Expecting Python script object holder");
aHandler.set(ret);
Py_DECREF(ret);
return NS_OK;
@@ -538,16 +539,17 @@ nsPythonContext::BindCompiledEventHandle
nsresult
nsPythonContext::CompileFunction(void* aTarget,
const nsACString& aName,
PRUint32 aArgCount,
const char** aArgArray,
const nsAString& aBody,
const char* aURL,
PRUint32 aLineNo,
+ PRUint32 aVersion,
PRBool aShared,
void** aFunctionObject)
{
NS_TIMELINE_MARK_FUNCTION("nsPythonContext::CompileFunction");
NS_ENSURE_TRUE(mIsInitialized, NS_ERROR_NOT_INITIALIZED);
NS_ERROR("CompileFunction not implemented");
return NS_ERROR_NOT_IMPLEMENTED;
--- a/extensions/python/dom/src/nsPyContext.h
+++ b/extensions/python/dom/src/nsPyContext.h
@@ -142,16 +142,17 @@ public:
nsAString* aRetValue,
PRBool* aIsUndefined);
virtual nsresult CompileEventHandler(nsIAtom *aName,
PRUint32 aArgCount,
const char** aArgNames,
const nsAString& aBody,
const char *aURL,
PRUint32 aLineNo,
+ PRUint32 aVersion,
nsScriptObjectHolder &aHandler);
virtual nsresult CallEventHandler(nsISupports* aTarget, void *aScope,
void* aHandler,
nsIArray *argv, nsIVariant **rv);
virtual nsresult BindCompiledEventHandler(nsISupports*aTarget, void *aScope,
nsIAtom *aName,
void *aHandler);
virtual nsresult GetBoundEventHandler(nsISupports* aTarget, void *aScope,
@@ -159,16 +160,17 @@ public:
nsScriptObjectHolder &aHandler);
virtual nsresult CompileFunction(void* aTarget,
const nsACString& aName,
PRUint32 aArgCount,
const char** aArgArray,
const nsAString& aBody,
const char* aURL,
PRUint32 aLineNo,
+ PRUint32 aVersion,
PRBool aShared,
void** aFunctionObject);
virtual void SetDefaultLanguageVersion(PRUint32 aVersion);
virtual nsIScriptGlobalObject *GetGlobalObject();
virtual void *GetNativeContext();
virtual void *GetNativeGlobal();
virtual nsresult CreateNativeGlobalForInner(