[api] Change CreationContext to return a MaybeHandle

The current API returns a Handle<NativeContext> which can be
optionally null and all the users of this API never actually
checked for this null value.

Previously, this wasn't a problem as all the possible JSObjects
that were user visible would return a valid NativeContext but now
there are wasm objects that don't have a valid constructor so don't
have a NativeContext.

Bug: v8:11451, chromium:1166077
Change-Id: I4fd5edf8f1a750e6f0abb931fd41358e5ae4dfcf
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2692695
Commit-Queue: Sathya Gunasekaran  <gsathya@chromium.org>
Reviewed-by: Toon Verwaest <verwaest@chromium.org>
Reviewed-by: Benedikt Meurer <bmeurer@chromium.org>
Reviewed-by: Ulan Degenbaev <ulan@chromium.org>
Cr-Commit-Position: refs/heads/master@{#72769}
This commit is contained in:
Sathya Gunasekaran 2021-02-16 10:27:07 +00:00 committed by Commit Bot
parent 88ba828575
commit b38bf5b0b1
20 changed files with 120 additions and 63 deletions

View File

@ -4222,12 +4222,18 @@ class V8_EXPORT Object : public Value {
/**
* Returns the context in which the object was created.
*/
V8_DEPRECATE_SOON("Use MaybeLocal<Context> GetCreationContext()")
Local<Context> CreationContext();
MaybeLocal<Context> GetCreationContext();
/** Same as above, but works for Persistents */
V8_INLINE static Local<Context> CreationContext(
V8_DEPRECATE_SOON(
"Use MaybeLocal<Context> GetCreationContext(const "
"PersistentBase<Object>& object)")
static Local<Context> CreationContext(const PersistentBase<Object>& object);
V8_INLINE static MaybeLocal<Context> GetCreationContext(
const PersistentBase<Object>& object) {
return object.val_->CreationContext();
return object.val_->GetCreationContext();
}
/**

View File

@ -4710,10 +4710,36 @@ Local<v8::Object> v8::Object::Clone() {
return Utils::ToLocal(result);
}
namespace {
Local<v8::Context> CreationContextImpl(i::Handle<i::JSReceiver> self) {
i::Handle<i::Context> context;
if (self->GetCreationContext().ToHandle(&context)) {
return Utils::ToLocal(context);
}
return Local<v8::Context>();
}
} // namespace
Local<v8::Context> v8::Object::CreationContext() {
auto self = Utils::OpenHandle(this);
i::Handle<i::Context> context = self->GetCreationContext();
return Utils::ToLocal(context);
return CreationContextImpl(self);
}
Local<v8::Context> v8::Object::CreationContext(
const PersistentBase<Object>& object) {
auto self = Utils::OpenHandle(object.val_);
return CreationContextImpl(self);
}
MaybeLocal<v8::Context> v8::Object::GetCreationContext() {
auto self = Utils::OpenHandle(this);
i::Handle<i::Context> context;
if (self->GetCreationContext().ToHandle(&context)) {
return Utils::ToLocal(context);
}
return MaybeLocal<v8::Context>();
}
int v8::Object::GetIdentityHash() {

View File

@ -157,8 +157,9 @@ Object ObjectLookupAccessor(Isolate* isolate, Handle<Object> object,
case LookupIterator::ACCESSOR: {
Handle<Object> maybe_pair = it.GetAccessors();
if (maybe_pair->IsAccessorPair()) {
Handle<NativeContext> native_context =
it.GetHolder<JSReceiver>()->GetCreationContext();
Handle<NativeContext> native_context = it.GetHolder<JSReceiver>()
->GetCreationContext()
.ToHandleChecked();
return *AccessorPair::GetComponent(
isolate, native_context, Handle<AccessorPair>::cast(maybe_pair),
component);

View File

@ -1527,7 +1527,12 @@ void Shell::RealmOwner(const v8::FunctionCallbackInfo<v8::Value>& args) {
i::Handle<i::JSGlobalProxy>::cast(i_object)->IsDetached()) {
return;
}
int index = data->RealmFind(object->CreationContext());
Local<Context> creation_context;
if (!object->GetCreationContext().ToLocal(&creation_context)) {
Throw(args.GetIsolate(), "object doesn't have creation context");
return;
}
int index = data->RealmFind(creation_context);
if (index == -1) return;
args.GetReturnValue().Set(index);
}

View File

@ -192,12 +192,12 @@ bool GetPrivateMembers(Local<Context> context, Local<Object> value,
return true;
}
Local<Context> GetCreationContext(Local<Object> value) {
MaybeLocal<Context> GetCreationContext(Local<Object> value) {
i::Handle<i::Object> val = Utils::OpenHandle(*value);
if (val->IsJSGlobalProxy()) {
return Local<Context>();
return MaybeLocal<Context>();
}
return value->CreationContext();
return value->GetCreationContext();
}
void ChangeBreakOnException(Isolate* isolate, ExceptionBreakState type) {

View File

@ -73,7 +73,7 @@ V8_EXPORT_PRIVATE bool GetPrivateMembers(Local<Context> context,
* Forwards to v8::Object::CreationContext, but with special handling for
* JSGlobalProxy objects.
*/
Local<Context> GetCreationContext(Local<Object> value);
MaybeLocal<Context> GetCreationContext(Local<Object> value);
enum ExceptionBreakState {
NoBreakOnException = 0,

View File

@ -1423,8 +1423,9 @@ void Debug::InstallDebugBreakTrampoline() {
}
if (recorded.find(accessor_pair) != recorded.end()) continue;
needs_instantiate.emplace_back(handle(accessor_pair, isolate_),
object.GetCreationContext());
needs_instantiate.emplace_back(
handle(accessor_pair, isolate_),
object.GetCreationContext().ToHandleChecked());
recorded.insert(accessor_pair);
}
}

View File

@ -304,8 +304,8 @@ MaybeHandle<Object> ErrorUtils::FormatStackTrace(Isolate* isolate,
Handle<FixedArray> elems = Handle<FixedArray>::cast(raw_stack);
const bool in_recursion = isolate->formatting_stack_trace();
if (!in_recursion) {
Handle<Context> error_context = error->GetCreationContext();
Handle<Context> error_context;
if (!in_recursion && error->GetCreationContext().ToHandle(&error_context)) {
DCHECK(error_context->IsNativeContext());
if (isolate->HasPrepareStackTraceCallback()) {

View File

@ -2574,7 +2574,8 @@ MaybeHandle<JSBoundFunction> Factory::NewJSBoundFunction(
isolate(), prototype,
JSReceiver::GetPrototype(isolate(), target_function), JSBoundFunction);
SaveAndSwitchContext save(isolate(), *target_function->GetCreationContext());
SaveAndSwitchContext save(
isolate(), *target_function->GetCreationContext().ToHandleChecked());
// Create the [[BoundArguments]] for the result.
Handle<FixedArray> bound_arguments;

View File

@ -249,7 +249,11 @@ void generateCustomPreview(int sessionId, const String16& groupName,
v8::Local<v8::Object> object,
v8::MaybeLocal<v8::Value> maybeConfig, int maxDepth,
std::unique_ptr<CustomPreview>* preview) {
v8::Local<v8::Context> context = object->CreationContext();
v8::Local<v8::Context> context;
if (!object->GetCreationContext().ToLocal(&context)) {
return;
}
v8::Isolate* isolate = context->GetIsolate();
v8::MicrotasksScope microtasksScope(isolate,
v8::MicrotasksScope::kDoNotRunMicrotasks);

View File

@ -43,8 +43,10 @@ class MatchPrototypePredicate : public v8::debug::QueryObjectPredicate {
bool Filter(v8::Local<v8::Object> object) override {
if (object->IsModuleNamespaceObject()) return false;
v8::Local<v8::Context> objectContext =
v8::debug::GetCreationContext(object);
v8::Local<v8::Context> objectContext;
if (!v8::debug::GetCreationContext(object).ToLocal(&objectContext)) {
return false;
}
if (objectContext != m_context) return false;
if (!m_inspector->client()->isInspectableHeapObject(object)) return false;
// Get prototype chain for current object until first visited prototype.

View File

@ -54,9 +54,13 @@ class GlobalObjectNameResolver final
: m_offset(0), m_strings(10000), m_session(session) {}
const char* GetName(v8::Local<v8::Object> object) override {
v8::Local<v8::Context> creationContext;
if (!object->GetCreationContext().ToLocal(&creationContext)) {
return "";
}
InspectedContext* context = m_session->inspector()->getContext(
m_session->contextGroupId(),
InspectedContext::contextId(object->CreationContext()));
InspectedContext::contextId(creationContext));
if (!context) return "";
String16 name = context->origin();
size_t length = name.length();
@ -286,7 +290,11 @@ Response V8HeapProfilerAgentImpl::getObjectByHeapObjectId(
if (!m_session->inspector()->client()->isInspectableHeapObject(heapObject))
return Response::ServerError("Object is not available");
*result = m_session->wrapObject(heapObject->CreationContext(), heapObject,
v8::Local<v8::Context> creationContext;
if (!heapObject->GetCreationContext().ToLocal(&creationContext)) {
return Response::ServerError("Object is not available");
}
*result = m_session->wrapObject(creationContext, heapObject,
objectGroup.fromMaybe(""), false);
if (!*result) return Response::ServerError("Object is not available");
return Response::Success();

View File

@ -534,7 +534,7 @@ Handle<String> JSReceiver::GetConstructorName(Handle<JSReceiver> receiver) {
return GetConstructorHelper(receiver).second;
}
Handle<NativeContext> JSReceiver::GetCreationContext() {
MaybeHandle<NativeContext> JSReceiver::GetCreationContext() {
JSReceiver receiver = *this;
// Externals are JSObjects with null as a constructor.
DCHECK(!receiver.IsExternal(GetIsolate()));
@ -544,20 +544,19 @@ Handle<NativeContext> JSReceiver::GetCreationContext() {
function = JSFunction::cast(constructor);
} else if (constructor.IsFunctionTemplateInfo()) {
// Remote objects don't have a creation context.
return Handle<NativeContext>::null();
return MaybeHandle<NativeContext>();
} else if (receiver.IsJSGeneratorObject()) {
function = JSGeneratorObject::cast(receiver).function();
} else {
// Functions have null as a constructor,
// but any JSFunction knows its context immediately.
CHECK(receiver.IsJSFunction());
} else if (receiver.IsJSFunction()) {
function = JSFunction::cast(receiver);
} else {
return MaybeHandle<NativeContext>();
}
return function.has_context()
? Handle<NativeContext>(function.context().native_context(),
receiver.GetIsolate())
: Handle<NativeContext>::null();
: MaybeHandle<NativeContext>();
}
// static
@ -1696,7 +1695,7 @@ Maybe<bool> JSReceiver::GetOwnPropertyDescriptor(LookupIterator* it,
Handle<AccessorPair> accessors =
Handle<AccessorPair>::cast(it->GetAccessors());
Handle<NativeContext> native_context =
it->GetHolder<JSReceiver>()->GetCreationContext();
it->GetHolder<JSReceiver>()->GetCreationContext().ToHandleChecked();
// 6a. Set D.[[Get]] to the value of X's [[Get]] attribute.
desc->set_get(AccessorPair::GetComponent(isolate, native_context, accessors,
ACCESSOR_GETTER));

View File

@ -227,7 +227,7 @@ class JSReceiver : public HeapObject {
// returned instead.
static Handle<String> GetConstructorName(Handle<JSReceiver> receiver);
V8_EXPORT_PRIVATE Handle<NativeContext> GetCreationContext();
V8_EXPORT_PRIVATE MaybeHandle<NativeContext> GetCreationContext();
V8_WARN_UNUSED_RESULT static inline Maybe<PropertyAttributes>
GetPropertyAttributes(Handle<JSReceiver> object, Handle<Name> name);

View File

@ -1490,7 +1490,8 @@ MaybeHandle<Object> Object::GetPropertyWithAccessor(LookupIterator* it) {
// Regular accessor.
Handle<Object> getter(accessor_pair->getter(), isolate);
if (getter->IsFunctionTemplateInfo()) {
SaveAndSwitchContext save(isolate, *holder->GetCreationContext());
SaveAndSwitchContext save(isolate,
*holder->GetCreationContext().ToHandleChecked());
return Builtins::InvokeApiFunction(
isolate, false, Handle<FunctionTemplateInfo>::cast(getter), receiver, 0,
nullptr, isolate->factory()->undefined_value());
@ -1595,7 +1596,8 @@ Maybe<bool> Object::SetPropertyWithAccessor(
// Regular accessor.
Handle<Object> setter(AccessorPair::cast(*structure).setter(), isolate);
if (setter->IsFunctionTemplateInfo()) {
SaveAndSwitchContext save(isolate, *holder->GetCreationContext());
SaveAndSwitchContext save(isolate,
*holder->GetCreationContext().ToHandleChecked());
Handle<Object> argv[] = {value};
RETURN_ON_EXCEPTION_VALUE(
isolate,

View File

@ -82,7 +82,9 @@ class TestEmbedderHeapTracer final : public v8::EmbedderHeapTracer {
void TracePrologue(EmbedderHeapTracer::TraceFlags) final {
if (prologue_behavior_ == TracePrologueBehavior::kCallV8WriteBarrier) {
auto local = array_.Get(isolate());
local->Set(local->CreationContext(), 0, v8::Object::New(isolate()))
local
->Set(local->GetCreationContext().ToLocalChecked(), 0,
v8::Object::New(isolate()))
.Check();
}
}

View File

@ -19079,49 +19079,49 @@ THREADED_TEST(CreationContext) {
{
Local<Context> other_context = Context::New(isolate);
Context::Scope scope(other_context);
CHECK(object1->CreationContext() == context1);
CHECK(object1->GetCreationContext().ToLocalChecked() == context1);
CheckContextId(object1, 1);
CHECK(func1->CreationContext() == context1);
CHECK(func1->GetCreationContext().ToLocalChecked() == context1);
CheckContextId(func1, 1);
CHECK(instance1->CreationContext() == context1);
CHECK(instance1->GetCreationContext().ToLocalChecked() == context1);
CheckContextId(instance1, 1);
CHECK(object2->CreationContext() == context2);
CHECK(object2->GetCreationContext().ToLocalChecked() == context2);
CheckContextId(object2, 2);
CHECK(func2->CreationContext() == context2);
CHECK(func2->GetCreationContext().ToLocalChecked() == context2);
CheckContextId(func2, 2);
CHECK(instance2->CreationContext() == context2);
CHECK(instance2->GetCreationContext().ToLocalChecked() == context2);
CheckContextId(instance2, 2);
}
{
Context::Scope scope(context1);
CHECK(object1->CreationContext() == context1);
CHECK(object1->GetCreationContext().ToLocalChecked() == context1);
CheckContextId(object1, 1);
CHECK(func1->CreationContext() == context1);
CHECK(func1->GetCreationContext().ToLocalChecked() == context1);
CheckContextId(func1, 1);
CHECK(instance1->CreationContext() == context1);
CHECK(instance1->GetCreationContext().ToLocalChecked() == context1);
CheckContextId(instance1, 1);
CHECK(object2->CreationContext() == context2);
CHECK(object2->GetCreationContext().ToLocalChecked() == context2);
CheckContextId(object2, 2);
CHECK(func2->CreationContext() == context2);
CHECK(func2->GetCreationContext().ToLocalChecked() == context2);
CheckContextId(func2, 2);
CHECK(instance2->CreationContext() == context2);
CHECK(instance2->GetCreationContext().ToLocalChecked() == context2);
CheckContextId(instance2, 2);
}
{
Context::Scope scope(context2);
CHECK(object1->CreationContext() == context1);
CHECK(object1->GetCreationContext().ToLocalChecked() == context1);
CheckContextId(object1, 1);
CHECK(func1->CreationContext() == context1);
CHECK(func1->GetCreationContext().ToLocalChecked() == context1);
CheckContextId(func1, 1);
CHECK(instance1->CreationContext() == context1);
CHECK(instance1->GetCreationContext().ToLocalChecked() == context1);
CheckContextId(instance1, 1);
CHECK(object2->CreationContext() == context2);
CHECK(object2->GetCreationContext().ToLocalChecked() == context2);
CheckContextId(object2, 2);
CHECK(func2->CreationContext() == context2);
CHECK(func2->GetCreationContext().ToLocalChecked() == context2);
CheckContextId(func2, 2);
CHECK(instance2->CreationContext() == context2);
CHECK(instance2->GetCreationContext().ToLocalChecked() == context2);
CheckContextId(instance2, 2);
}
}
@ -19140,7 +19140,7 @@ THREADED_TEST(CreationContextOfJsFunction) {
Local<Context> other_context = Context::New(CcTest::isolate());
Context::Scope scope(other_context);
CHECK(function->CreationContext() == context);
CHECK(function->GetCreationContext().ToLocalChecked() == context);
CheckContextId(function, 1);
}
@ -19171,13 +19171,12 @@ THREADED_TEST(CreationContextOfJsBoundFunction) {
Local<Context> other_context = Context::New(CcTest::isolate());
Context::Scope scope(other_context);
CHECK(bound_function1->CreationContext() == context1);
CHECK(bound_function1->GetCreationContext().ToLocalChecked() == context1);
CheckContextId(bound_function1, 1);
CHECK(bound_function2->CreationContext() == context1);
CHECK(bound_function2->GetCreationContext().ToLocalChecked() == context1);
CheckContextId(bound_function2, 1);
}
void HasOwnPropertyIndexedPropertyGetter(
uint32_t index,
const v8::PropertyCallbackInfo<v8::Value>& info) {
@ -24775,7 +24774,7 @@ TEST(ClassPrototypeCreationContext) {
Local<Object> result = Local<Object>::Cast(
CompileRun("'use strict'; class Example { }; Example.prototype"));
CHECK(env.local() == result->CreationContext());
CHECK(env.local() == result->GetCreationContext().ToLocalChecked());
}
@ -25554,7 +25553,7 @@ TEST(ObjectTemplatePerContextIntrinsics) {
object->Get(env.local(), v8_str("values")).ToLocalChecked());
auto fn = i::Handle<i::JSFunction>::cast(v8::Utils::OpenHandle(*values));
auto ctx = v8::Utils::OpenHandle(*env.local());
CHECK_EQ(*fn->GetCreationContext(), *ctx);
CHECK_EQ(*(fn->GetCreationContext().ToHandleChecked()), *ctx);
{
LocalContext env2;
@ -25570,7 +25569,7 @@ TEST(ObjectTemplatePerContextIntrinsics) {
object2->Get(env2.local(), v8_str("values")).ToLocalChecked());
auto fn2 = i::Handle<i::JSFunction>::cast(v8::Utils::OpenHandle(*values2));
auto ctx2 = v8::Utils::OpenHandle(*env2.local());
CHECK_EQ(*fn2->GetCreationContext(), *ctx2);
CHECK_EQ(*(fn2->GetCreationContext().ToHandleChecked()), *ctx2);
}
}

View File

@ -743,7 +743,7 @@ TEST(ModuleNamespace) {
Local<Value> ns = module->GetModuleNamespace();
CHECK_EQ(Module::kInstantiated, module->GetStatus());
Local<v8::Object> nsobj = ns->ToObject(env.local()).ToLocalChecked();
CHECK_EQ(nsobj->CreationContext(), env.local());
CHECK_EQ(nsobj->GetCreationContext().ToLocalChecked(), env.local());
// a, b
CHECK(nsobj->Get(env.local(), v8_str("a")).ToLocalChecked()->IsUndefined());

View File

@ -39,7 +39,7 @@ TEST_F(RemoteObjectTest, CreationContextOfRemoteContext) {
Local<Object> remote_context =
Context::NewRemoteContext(isolate(), global_template).ToLocalChecked();
EXPECT_TRUE(remote_context->CreationContext().IsEmpty());
EXPECT_TRUE(remote_context->GetCreationContext().IsEmpty());
}
TEST_F(RemoteObjectTest, CreationContextOfRemoteObject) {
@ -51,7 +51,7 @@ TEST_F(RemoteObjectTest, CreationContextOfRemoteObject) {
Local<Object> remote_object =
constructor_template->NewRemoteInstance().ToLocalChecked();
EXPECT_TRUE(remote_object->CreationContext().IsEmpty());
EXPECT_TRUE(remote_object->GetCreationContext().IsEmpty());
}
TEST_F(RemoteObjectTest, RemoteContextInstanceChecks) {

View File

@ -77,8 +77,9 @@ TEST_F(LapContextTest, CurrentContextInLazyAccessorOnPrototype) {
Local<Object> object =
interface_for_receiver->NewInstance(receiver_context).ToLocalChecked();
object->SetPrototype(caller_context, prototype).ToChecked();
EXPECT_EQ(receiver_context, object->CreationContext());
EXPECT_EQ(prototype_context, prototype->CreationContext());
EXPECT_EQ(receiver_context, object->GetCreationContext().ToLocalChecked());
EXPECT_EQ(prototype_context,
prototype->GetCreationContext().ToLocalChecked());
EXPECT_EQ(0, call_count);
object->Get(caller_context, property_key).ToLocalChecked();