Introduce API to trigger exception on JS execution.

R=jochen@chromium.org, pmarch@chromium.org

Review URL: https://codereview.chromium.org/203223013

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@20070 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
yangguo@chromium.org 2014-03-19 13:06:53 +00:00
parent 9be17fb30e
commit d8c3c5ef0a
5 changed files with 66 additions and 10 deletions

View File

@ -4090,10 +4090,14 @@ class V8_EXPORT Isolate {
*/
class DisallowJavascriptExecutionScope {
public:
explicit DisallowJavascriptExecutionScope(Isolate* isolate);
enum OnFailure { CRASH_ON_FAILURE, THROW_ON_FAILURE };
explicit DisallowJavascriptExecutionScope(Isolate* isolate,
OnFailure on_failure);
~DisallowJavascriptExecutionScope();
private:
bool on_failure_;
void* internal_;
// Prevent copying of Scope objects.
@ -4112,7 +4116,13 @@ class V8_EXPORT Isolate {
~AllowJavascriptExecutionScope();
private:
void* internal_;
void* internal_throws_;
void* internal_assert_;
// Prevent copying of Scope objects.
AllowJavascriptExecutionScope(const AllowJavascriptExecutionScope&);
AllowJavascriptExecutionScope& operator=(
const AllowJavascriptExecutionScope&);
};
/**

View File

@ -6515,28 +6515,43 @@ void Isolate::Exit() {
Isolate::DisallowJavascriptExecutionScope::DisallowJavascriptExecutionScope(
Isolate* isolate) {
Isolate* isolate,
Isolate::DisallowJavascriptExecutionScope::OnFailure on_failure)
: on_failure_(on_failure) {
i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
internal_ = reinterpret_cast<void*>(
new i::DisallowJavascriptExecution(i_isolate));
if (on_failure_ == CRASH_ON_FAILURE) {
internal_ = reinterpret_cast<void*>(
new i::DisallowJavascriptExecution(i_isolate));
} else {
ASSERT_EQ(THROW_ON_FAILURE, on_failure);
internal_ = reinterpret_cast<void*>(
new i::ThrowOnJavascriptExecution(i_isolate));
}
}
Isolate::DisallowJavascriptExecutionScope::~DisallowJavascriptExecutionScope() {
delete reinterpret_cast<i::DisallowJavascriptExecution*>(internal_);
if (on_failure_ == CRASH_ON_FAILURE) {
delete reinterpret_cast<i::DisallowJavascriptExecution*>(internal_);
} else {
delete reinterpret_cast<i::ThrowOnJavascriptExecution*>(internal_);
}
}
Isolate::AllowJavascriptExecutionScope::AllowJavascriptExecutionScope(
Isolate* isolate) {
i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
internal_ = reinterpret_cast<void*>(
internal_assert_ = reinterpret_cast<void*>(
new i::AllowJavascriptExecution(i_isolate));
internal_throws_ = reinterpret_cast<void*>(
new i::NoThrowOnJavascriptExecution(i_isolate));
}
Isolate::AllowJavascriptExecutionScope::~AllowJavascriptExecutionScope() {
delete reinterpret_cast<i::AllowJavascriptExecution*>(internal_);
delete reinterpret_cast<i::AllowJavascriptExecution*>(internal_assert_);
delete reinterpret_cast<i::NoThrowOnJavascriptExecution*>(internal_throws_);
}

View File

@ -49,6 +49,7 @@ enum PerThreadAssertType {
enum PerIsolateAssertType {
JAVASCRIPT_EXECUTION_ASSERT,
JAVASCRIPT_EXECUTION_THROWS,
ALLOCATION_FAILURE_ASSERT
};
@ -251,6 +252,14 @@ typedef PerIsolateAssertScope<JAVASCRIPT_EXECUTION_ASSERT, false>
typedef PerIsolateAssertScope<JAVASCRIPT_EXECUTION_ASSERT, true>
AllowJavascriptExecution;
// Scope in which javascript execution leads to exception being thrown.
typedef PerIsolateAssertScope<JAVASCRIPT_EXECUTION_THROWS, false>
ThrowOnJavascriptExecution;
// Scope to introduce an exception to ThrowOnJavascriptExecution.
typedef PerIsolateAssertScope<JAVASCRIPT_EXECUTION_THROWS, true>
NoThrowOnJavascriptExecution;
// Scope to document where we do not expect an allocation failure.
typedef PerIsolateAssertScopeDebugOnly<ALLOCATION_FAILURE_ASSERT, false>
DisallowAllocationFailure;

View File

@ -78,6 +78,12 @@ static Handle<Object> Invoke(bool is_construct,
// Entering JavaScript.
VMState<JS> state(isolate);
CHECK(AllowJavascriptExecution::IsAllowed(isolate));
if (!ThrowOnJavascriptExecution::IsAllowed(isolate)) {
isolate->ThrowIllegalOperation();
*has_pending_exception = true;
isolate->ReportPendingMessages();
return Handle<Object>();
}
// Placeholder for return value.
MaybeObject* value = reinterpret_cast<Object*>(kZapValue);

View File

@ -22399,7 +22399,8 @@ TEST(DisallowJavascriptExecutionScope) {
LocalContext context;
v8::Isolate* isolate = context->GetIsolate();
v8::HandleScope scope(isolate);
v8::Isolate::DisallowJavascriptExecutionScope no_js(isolate);
v8::Isolate::DisallowJavascriptExecutionScope no_js(
isolate, v8::Isolate::DisallowJavascriptExecutionScope::CRASH_ON_FAILURE);
CompileRun("2+2");
}
@ -22408,8 +22409,23 @@ TEST(AllowJavascriptExecutionScope) {
LocalContext context;
v8::Isolate* isolate = context->GetIsolate();
v8::HandleScope scope(isolate);
v8::Isolate::DisallowJavascriptExecutionScope no_js(isolate);
v8::Isolate::DisallowJavascriptExecutionScope no_js(
isolate, v8::Isolate::DisallowJavascriptExecutionScope::CRASH_ON_FAILURE);
v8::Isolate::DisallowJavascriptExecutionScope throw_js(
isolate, v8::Isolate::DisallowJavascriptExecutionScope::THROW_ON_FAILURE);
{ v8::Isolate::AllowJavascriptExecutionScope yes_js(isolate);
CompileRun("1+1");
}
}
TEST(ThrowOnJavascriptExecution) {
LocalContext context;
v8::Isolate* isolate = context->GetIsolate();
v8::HandleScope scope(isolate);
v8::TryCatch try_catch;
v8::Isolate::DisallowJavascriptExecutionScope throw_js(
isolate, v8::Isolate::DisallowJavascriptExecutionScope::THROW_ON_FAILURE);
CompileRun("1+1");
CHECK(try_catch.HasCaught());
}