Commit 7a02ba0d authored by Yuki Shiino's avatar Yuki Shiino Committed by Commit Bot

Supports the Incumbent realm (Isolate::GetIncumbentContext).

Adds new APIs Isolate::GetIncumbentContext() and
Context::BackupIncumbentScope to support
"the backup incumbent settings object stack" [1].

[1] https://html.spec.whatwg.org/multipage/webappapis.html#backup-incumbent-settings-object-stack

Bug: 
Cq-Include-Trybots: master.tryserver.chromium.linux:linux_chromium_rel_ng
Change-Id: I1ccea0e6fe2743fe5f3072b9e1236111ce2b1a42
Reviewed-on: https://chromium-review.googlesource.com/536728Reviewed-by: 's avatarToon Verwaest <verwaest@chromium.org>
Commit-Queue: Yuki Shiino <yukishiino@chromium.org>
Cr-Commit-Position: refs/heads/master@{#46246}
parent 3c04ee6d
......@@ -7167,6 +7167,12 @@ class V8_EXPORT Isolate {
*/
Local<Context> GetEnteredOrMicrotaskContext();
/**
* Returns the Context that corresponds to the Incumbent realm in HTML spec.
* https://html.spec.whatwg.org/multipage/webappapis.html#incumbent
*/
Local<Context> GetIncumbentContext();
/**
* Schedules an exception to be thrown when returning to JavaScript. When an
* exception has been scheduled it is illegal to invoke any JavaScript
......@@ -8647,6 +8653,27 @@ class V8_EXPORT Context {
Local<Context> context_;
};
/**
* Stack-allocated class to support the backup incumbent settings object
* stack.
* https://html.spec.whatwg.org/multipage/webappapis.html#backup-incumbent-settings-object-stack
*/
class BackupIncumbentScope {
public:
/**
* |backup_incumbent_context| is pushed onto the backup incumbent settings
* object stack.
*/
explicit BackupIncumbentScope(Local<Context> backup_incumbent_context);
~BackupIncumbentScope();
private:
friend class internal::Isolate;
Local<Context> backup_incumbent_context_;
const BackupIncumbentScope* prev_ = nullptr;
};
private:
friend class Value;
friend class Script;
......
......@@ -1117,7 +1117,6 @@ void Context::Enter() {
isolate->set_context(*env);
}
void Context::Exit() {
i::Handle<i::Context> env = Utils::OpenHandle(this);
i::Isolate* isolate = env->GetIsolate();
......@@ -1132,6 +1131,22 @@ void Context::Exit() {
isolate->set_context(impl->RestoreContext());
}
Context::BackupIncumbentScope::BackupIncumbentScope(
Local<Context> backup_incumbent_context)
: backup_incumbent_context_(backup_incumbent_context) {
DCHECK(!backup_incumbent_context_.IsEmpty());
i::Handle<i::Context> env = Utils::OpenHandle(*backup_incumbent_context_);
i::Isolate* isolate = env->GetIsolate();
prev_ = isolate->top_backup_incumbent_scope();
isolate->set_top_backup_incumbent_scope(this);
}
Context::BackupIncumbentScope::~BackupIncumbentScope() {
i::Handle<i::Context> env = Utils::OpenHandle(*backup_incumbent_context_);
i::Isolate* isolate = env->GetIsolate();
isolate->set_top_backup_incumbent_scope(prev_);
}
static void* DecodeSmiToAligned(i::Object* value, const char* location) {
Utils::ApiCheck(value->IsSmi(), location, "Not a Smi");
......@@ -8293,6 +8308,12 @@ v8::Local<v8::Context> Isolate::GetEnteredOrMicrotaskContext() {
return Utils::ToLocal(i::Handle<i::Context>::cast(last));
}
v8::Local<v8::Context> Isolate::GetIncumbentContext() {
i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
i::Handle<i::Context> context = isolate->GetIncumbentContext();
return Utils::ToLocal(context);
}
v8::Local<Value> Isolate::ThrowException(v8::Local<v8::Value> value) {
i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
ENTER_V8_DO_NOT_USE(isolate);
......
......@@ -138,13 +138,24 @@ void JavaScriptFrameIterator::Advance() {
} while (!iterator_.done() && !iterator_.frame()->is_java_script());
}
void JavaScriptFrameIterator::AdvanceToArgumentsFrame() {
if (!frame()->has_adapted_arguments()) return;
iterator_.Advance();
DCHECK(iterator_.frame()->is_arguments_adaptor());
}
void JavaScriptFrameIterator::AdvanceWhileDebugContext(Debug* debug) {
if (!debug->in_debug_scope()) return;
while (!done()) {
Context* context = Context::cast(frame()->context());
if (context->native_context() == *debug->debug_context()) {
Advance();
} else {
break;
}
}
}
// -------------------------------------------------------------------------
......
......@@ -15,6 +15,7 @@ namespace v8 {
namespace internal {
class AbstractCode;
class Debug;
class ObjectVisitor;
class StringStream;
......@@ -1543,6 +1544,9 @@ class JavaScriptFrameIterator BASE_EMBEDDED {
// arguments.
void AdvanceToArgumentsFrame();
// Skips the frames that point to the debug context.
void AdvanceWhileDebugContext(Debug* debug);
private:
StackFrameIterator iterator_;
};
......
......@@ -2028,23 +2028,40 @@ void Isolate::SetAbortOnUncaughtExceptionCallback(
Handle<Context> Isolate::GetCallingNativeContext() {
JavaScriptFrameIterator it(this);
if (debug_->in_debug_scope()) {
while (!it.done()) {
JavaScriptFrame* frame = it.frame();
Context* context = Context::cast(frame->context());
if (context->native_context() == *debug_->debug_context()) {
it.Advance();
} else {
break;
}
}
}
it.AdvanceWhileDebugContext(debug_);
if (it.done()) return Handle<Context>::null();
JavaScriptFrame* frame = it.frame();
Context* context = Context::cast(frame->context());
return Handle<Context>(context->native_context(), this);
}
Handle<Context> Isolate::GetIncumbentContext() {
JavaScriptFrameIterator it(this);
it.AdvanceWhileDebugContext(debug_);
// 1st candidate: most-recently-entered author function's context
// if it's newer than the last Context::BackupIncumbentScope entry.
if (!it.done() &&
static_cast<const void*>(it.frame()) >
static_cast<const void*>(top_backup_incumbent_scope())) {
Context* context = Context::cast(it.frame()->context());
return Handle<Context>(context->native_context(), this);
}
// 2nd candidate: the last Context::Scope's incumbent context if any.
if (top_backup_incumbent_scope()) {
return Utils::OpenHandle(
*top_backup_incumbent_scope()->backup_incumbent_context_);
}
// Last candidate: the entered context.
// Given that there is no other author function is running, there must be
// no cross-context function running, then the incumbent realm must match
// the entry realm.
v8::Local<v8::Context> entered_context =
reinterpret_cast<v8::Isolate*>(this)->GetEnteredContext();
return Utils::OpenHandle(*entered_context);
}
char* Isolate::ArchiveThread(char* to) {
MemCopy(to, reinterpret_cast<char*>(thread_local_top()),
......
......@@ -808,6 +808,8 @@ class Isolate {
// is, the native context of the top-most JavaScript frame.
Handle<Context> GetCallingNativeContext();
Handle<Context> GetIncumbentContext();
void RegisterTryCatchHandler(v8::TryCatch* that);
void UnregisterTryCatchHandler(v8::TryCatch* that);
......@@ -1284,6 +1286,14 @@ class Isolate {
elements_deletion_counter_ = value;
}
const v8::Context::BackupIncumbentScope* top_backup_incumbent_scope() const {
return top_backup_incumbent_scope_;
}
void set_top_backup_incumbent_scope(
const v8::Context::BackupIncumbentScope* top_backup_incumbent_scope) {
top_backup_incumbent_scope_ = top_backup_incumbent_scope;
}
protected:
explicit Isolate(bool enable_serializer);
bool IsArrayOrObjectPrototype(Object* object);
......@@ -1573,6 +1583,10 @@ class Isolate {
size_t elements_deletion_counter_ = 0;
// The top entry of the v8::Context::BackupIncumbentScope stack.
const v8::Context::BackupIncumbentScope* top_backup_incumbent_scope_ =
nullptr;
friend class ExecutionAccess;
friend class HandleScopeImplementer;
friend class HeapTester;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment