Skip to content

Commit

Permalink
Do not enter contexts implicitly
Browse files Browse the repository at this point in the history
Blink uses Isolate::GetEnteredContext() to implement HTML's "entry
context" concept, and thus depends on it not being changed except
explicitly (by Blink.) To support this, stop entering contexts
implicitly in all external API entry points; rather just set the
context as current. The only thing that changes the entered context
is now Context::Enter()/Context::Exit() (and Context::Scope.)

BUG=v8:6307

Review-Url: https://codereview.chromium.org/2862483003
Cr-Commit-Position: refs/heads/master@{#45064}
  • Loading branch information
opera-jl authored and Commit bot committed May 3, 2017
1 parent 17a0a57 commit 40d0118
Show file tree
Hide file tree
Showing 2 changed files with 73 additions and 4 deletions.
11 changes: 7 additions & 4 deletions src/api.cc
Expand Up @@ -232,17 +232,20 @@ class CallDepthScope {
i::Handle<i::Context> env = Utils::OpenHandle(*context);
i::HandleScopeImplementer* impl = isolate->handle_scope_implementer();
if (isolate->context() != nullptr &&
isolate->context()->native_context() == env->native_context() &&
impl->LastEnteredContextWas(env)) {
isolate->context()->native_context() == env->native_context()) {
context_ = Local<Context>();
} else {
context_->Enter();
impl->SaveContext(isolate->context());
isolate->set_context(*env);
}
}
if (do_callback) isolate_->FireBeforeCallEnteredCallback();
}
~CallDepthScope() {
if (!context_.IsEmpty()) context_->Exit();
if (!context_.IsEmpty()) {
i::HandleScopeImplementer* impl = isolate_->handle_scope_implementer();
isolate_->set_context(impl->RestoreContext());
}
if (!escaped_) isolate_->handle_scope_implementer()->DecrementCallDepth();
if (do_callback) isolate_->FireCallCompletedCallback();
#ifdef DEBUG
Expand Down
66 changes: 66 additions & 0 deletions test/cctest/test-api.cc
Expand Up @@ -26601,3 +26601,69 @@ UNINITIALIZED_TEST(AllowAtomicsWait) {
}
isolate->Dispose();
}

enum ContextId { EnteredContext, CurrentContext };

void CheckContexts(v8::Isolate* isolate) {
CHECK_EQ(CurrentContext, isolate->GetCurrentContext()
->GetEmbedderData(1)
.As<v8::Integer>()
->Value());
CHECK_EQ(EnteredContext, isolate->GetEnteredContext()
->GetEmbedderData(1)
.As<v8::Integer>()
->Value());
}

void ContextCheckGetter(Local<String> name,
const v8::PropertyCallbackInfo<v8::Value>& info) {
CheckContexts(info.GetIsolate());
info.GetReturnValue().Set(true);
}

void ContextCheckSetter(Local<String> name, Local<Value>,
const v8::PropertyCallbackInfo<void>& info) {
CheckContexts(info.GetIsolate());
}

void ContextCheckToString(const v8::FunctionCallbackInfo<v8::Value>& info) {
CheckContexts(info.GetIsolate());
info.GetReturnValue().Set(v8_str("foo"));
}

TEST(CorrectEnteredContext) {
v8::HandleScope scope(CcTest::isolate());

LocalContext currentContext;
currentContext->SetEmbedderData(
1, v8::Integer::New(currentContext->GetIsolate(), CurrentContext));
LocalContext enteredContext;
enteredContext->SetEmbedderData(
1, v8::Integer::New(enteredContext->GetIsolate(), EnteredContext));

v8::Context::Scope contextScope(enteredContext.local());

v8::Local<v8::ObjectTemplate> object_template =
ObjectTemplate::New(currentContext->GetIsolate());
object_template->SetAccessor(v8_str("p"), &ContextCheckGetter,
&ContextCheckSetter);

v8::Local<v8::Object> object =
object_template->NewInstance(currentContext.local()).ToLocalChecked();

object->Get(currentContext.local(), v8_str("p")).ToLocalChecked();
object->Set(currentContext.local(), v8_str("p"), v8_int(0)).FromJust();

v8::Local<v8::Function> to_string =
v8::Function::New(currentContext.local(), ContextCheckToString)
.ToLocalChecked();

to_string->Call(currentContext.local(), object, 0, nullptr).ToLocalChecked();

object
->CreateDataProperty(currentContext.local(), v8_str("toString"),
to_string)
.FromJust();

object->ToString(currentContext.local()).ToLocalChecked();
}

0 comments on commit 40d0118

Please sign in to comment.