Bug 1172246. Make sure CallSetup's handling of exceptions it wants to deal with itself works even when the callable is a JSNative that use the JS_Report*Error APIs instead of throwing exceptions in the usual way. r=bholley

This commit is contained in:
Boris Zbarsky 2015-06-08 16:16:27 -04:00
Родитель 61fe741d44
Коммит 470161ae4a
5 изменённых файлов: 27 добавлений и 5 удалений

Просмотреть файл

@ -187,8 +187,7 @@ CallbackObject::CallSetup::CallSetup(CallbackObject* aCallback,
// Make sure the JS engine doesn't report exceptions we want to re-throw
if ((mCompartment && mExceptionHandling == eRethrowContentExceptions) ||
mExceptionHandling == eRethrowExceptions) {
mSavedJSContextOptions = JS::ContextOptionsRef(cx);
JS::ContextOptionsRef(cx).setDontReportUncaught(true);
mAutoEntryScript->TakeOwnershipOfErrorReporting();
}
}
@ -258,9 +257,8 @@ CallbackObject::CallSetup::~CallSetup()
bool needToDealWithException = JS_IsExceptionPending(mCx);
if ((mCompartment && mExceptionHandling == eRethrowContentExceptions) ||
mExceptionHandling == eRethrowExceptions) {
// Restore the old context options
JS::ContextOptionsRef(mCx) = mSavedJSContextOptions;
mErrorResult.MightThrowJSException();
MOZ_ASSERT(mAutoEntryScript->OwnsErrorReporting());
if (needToDealWithException) {
JS::Rooted<JS::Value> exn(mCx);
if (JS_GetPendingException(mCx, &exn) &&

Просмотреть файл

@ -219,7 +219,6 @@ protected:
// we should re-throw them.
ErrorResult& mErrorResult;
const ExceptionHandling mExceptionHandling;
JS::ContextOptions mSavedJSContextOptions;
const bool mIsMainThread;
};
};

Просмотреть файл

@ -61,3 +61,4 @@ skip-if = debug == false
[test_worker_UnwrapArg.html]
[test_unforgeablesonexpando.html]
[test_crossOriginWindowSymbolAccess.html]
[test_callback_exceptions.html]

Просмотреть файл

@ -0,0 +1,17 @@
<!DOCTYPE html>
<meta charset=utf-8>
<title>Test for ...</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<div id="log"></div>
<script>
promise_test(function(t) {
var iterator = document.createNodeIterator(document, NodeFilter.SHOW_ALL, JSON.parse);
return promise_rejects(t, new SyntaxError,
Promise.resolve().then(iterator.nextNode.bind(iterator)));
}, "Trying to use JSON.parse as filter should throw a catchable SyntaxError exception even when the filter is invoked async");
promise_test(function(t) {
return promise_rejects(t, new SyntaxError, Promise.resolve('{').then(JSON.parse));
}, "Trying to use JSON.parse as a promise callback should allow the next promise to handle the resulting exception.");
</script>

Просмотреть файл

@ -464,6 +464,12 @@ policies and contribution forms [3].
}));
}
function promise_rejects(test, expected, promise) {
return promise.then(test.unreached_func("Should have rejected.")).catch(function(e) {
assert_throws(expected, function() { throw e });
});
}
/**
* This constructor helper allows DOM events to be handled using Promises,
* which can make it a lot easier to test a very specific series of events,
@ -579,6 +585,7 @@ policies and contribution forms [3].
expose(test, 'test');
expose(async_test, 'async_test');
expose(promise_test, 'promise_test');
expose(promise_rejects, 'promise_rejects');
expose(generate_tests, 'generate_tests');
expose(setup, 'setup');
expose(done, 'done');