ec06bb6ce5
This is a reland of d1b27019d3
Fixes include:
Adding missing file to bazel build
Forward-declaring classing before friend-classing them to fix win/gcc
Add missing v8-isolate.h include for vtune builds
Original change's description:
> [include] Split out v8.h
>
> This moves every single class/function out of include/v8.h into a
> separate header in include/, which v8.h then includes so that
> externally nothing appears to have changed.
>
> Every include of v8.h from inside v8 has been changed to a more
> fine-grained include.
>
> Previously inline functions defined at the bottom of v8.h would call
> private non-inline functions in the V8 class. Since that class is now
> in v8-initialization.h and is rarely included (as that would create
> dependency cycles), this is not possible and so those methods have been
> moved out of the V8 class into the namespace v8::api_internal.
>
> None of the previous files in include/ now #include v8.h, which means
> if embedders were relying on this transitive dependency then it will
> give compile failures.
>
> v8-inspector.h does depend on v8-scripts.h for the time being to ensure
> that Chrome continue to compile but that change will be reverted once
> those transitive #includes in chrome are changed to include it directly.
>
> Full design:
> https://docs.google.com/document/d/1rTD--I8hCAr-Rho1WTumZzFKaDpEp0IJ8ejZtk4nJdA/edit?usp=sharing
>
> Bug: v8:11965
> Change-Id: I53b84b29581632710edc80eb11f819c2097a2877
> Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3097448
> Reviewed-by: Yang Guo <yangguo@chromium.org>
> Reviewed-by: Camillo Bruni <cbruni@chromium.org>
> Reviewed-by: Jakob Kummerow <jkummerow@chromium.org>
> Reviewed-by: Leszek Swirski <leszeks@chromium.org>
> Reviewed-by: Michael Lippautz <mlippautz@chromium.org>
> Commit-Queue: Dan Elphick <delphick@chromium.org>
> Cr-Commit-Position: refs/heads/main@{#76424}
Cq-Include-Trybots: luci.v8.try:v8_linux_vtunejit
Bug: v8:11965
Change-Id: I99f5d3a73bf8fe25b650adfaf9567dc4e44a09e6
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3113629
Reviewed-by: Leszek Swirski <leszeks@chromium.org>
Reviewed-by: Camillo Bruni <cbruni@chromium.org>
Reviewed-by: Michael Lippautz <mlippautz@chromium.org>
Reviewed-by: Jakob Kummerow <jkummerow@chromium.org>
Reviewed-by: Simon Zünd <szuend@chromium.org>
Commit-Queue: Dan Elphick <delphick@chromium.org>
Cr-Commit-Position: refs/heads/main@{#76460}
189 lines
7.4 KiB
C++
189 lines
7.4 KiB
C++
// Copyright 2017 the V8 project authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style license that can be
|
|
// found in the LICENSE file.
|
|
|
|
#include "include/v8-context.h"
|
|
#include "include/v8-function.h"
|
|
#include "include/v8-isolate.h"
|
|
#include "include/v8-local-handle.h"
|
|
#include "include/v8-primitive.h"
|
|
#include "include/v8-script.h"
|
|
#include "include/v8-template.h"
|
|
#include "src/debug/debug.h"
|
|
#include "test/unittests/test-utils.h"
|
|
#include "testing/gtest/include/gtest/gtest.h"
|
|
|
|
namespace v8 {
|
|
|
|
using AccessCheckTest = TestWithIsolate;
|
|
|
|
namespace {
|
|
|
|
bool AccessCheck(Local<Context> accessing_context,
|
|
Local<Object> accessed_object, Local<Value> data) {
|
|
return false;
|
|
}
|
|
|
|
MaybeLocal<Value> CompileRun(Isolate* isolate, const char* source) {
|
|
Local<String> source_string =
|
|
String::NewFromUtf8(isolate, source).ToLocalChecked();
|
|
Local<Context> context = isolate->GetCurrentContext();
|
|
Local<Script> script =
|
|
Script::Compile(context, source_string).ToLocalChecked();
|
|
return script->Run(context);
|
|
}
|
|
|
|
v8::Local<v8::String> v8_str(const char* x) {
|
|
return v8::String::NewFromUtf8(v8::Isolate::GetCurrent(), x).ToLocalChecked();
|
|
}
|
|
|
|
} // namespace
|
|
|
|
TEST_F(AccessCheckTest, GetOwnPropertyDescriptor) {
|
|
isolate()->SetFailedAccessCheckCallbackFunction(
|
|
[](v8::Local<v8::Object> host, v8::AccessType type,
|
|
v8::Local<v8::Value> data) {});
|
|
Local<ObjectTemplate> global_template = ObjectTemplate::New(isolate());
|
|
global_template->SetAccessCheckCallback(AccessCheck);
|
|
|
|
Local<FunctionTemplate> getter_template = FunctionTemplate::New(
|
|
isolate(), [](const FunctionCallbackInfo<Value>& info) { FAIL(); });
|
|
getter_template->SetAcceptAnyReceiver(false);
|
|
Local<FunctionTemplate> setter_template = FunctionTemplate::New(
|
|
isolate(), [](const FunctionCallbackInfo<v8::Value>& info) { FAIL(); });
|
|
setter_template->SetAcceptAnyReceiver(false);
|
|
global_template->SetAccessorProperty(v8_str("property"), getter_template,
|
|
setter_template);
|
|
|
|
Local<Context> target_context =
|
|
Context::New(isolate(), nullptr, global_template);
|
|
Local<Context> accessing_context =
|
|
Context::New(isolate(), nullptr, global_template);
|
|
|
|
accessing_context->Global()
|
|
->Set(accessing_context, v8_str("other"), target_context->Global())
|
|
.FromJust();
|
|
|
|
Context::Scope context_scope(accessing_context);
|
|
Local<Value> result =
|
|
CompileRun(isolate(),
|
|
"Object.getOwnPropertyDescriptor(this, 'property')"
|
|
" .get.call(other);")
|
|
.ToLocalChecked();
|
|
EXPECT_TRUE(result->IsUndefined());
|
|
CompileRun(isolate(),
|
|
"Object.getOwnPropertyDescriptor(this, 'property')"
|
|
" .set.call(other, 42);");
|
|
}
|
|
|
|
class AccessRegressionTest : public AccessCheckTest {
|
|
protected:
|
|
i::Handle<i::JSFunction> RetrieveFunctionFrom(Local<Context> context,
|
|
const char* script) {
|
|
Context::Scope context_scope(context);
|
|
Local<Value> getter = CompileRun(isolate(), script).ToLocalChecked();
|
|
EXPECT_TRUE(getter->IsFunction());
|
|
|
|
i::Handle<i::JSReceiver> r =
|
|
Utils::OpenHandle(*Local<Function>::Cast(getter));
|
|
EXPECT_TRUE(r->IsJSFunction());
|
|
return i::Handle<i::JSFunction>::cast(r);
|
|
}
|
|
};
|
|
|
|
TEST_F(AccessRegressionTest,
|
|
InstantiatedLazyAccessorPairsHaveCorrectNativeContext) {
|
|
// The setup creates two contexts and sets an object created
|
|
// in context 1 on the global of context 2.
|
|
// The object has an accessor pair {property}. Accessing the
|
|
// property descriptor of {property} causes instantiation of the
|
|
// accessor pair. The test checks that the access pair has the
|
|
// correct native context.
|
|
Local<FunctionTemplate> getter_template = FunctionTemplate::New(
|
|
isolate(), [](const FunctionCallbackInfo<Value>&) { FAIL(); });
|
|
Local<FunctionTemplate> setter_template = FunctionTemplate::New(
|
|
isolate(), [](const FunctionCallbackInfo<v8::Value>&) { FAIL(); });
|
|
|
|
Local<ObjectTemplate> object_template = ObjectTemplate::New(isolate());
|
|
object_template->SetAccessorProperty(v8_str("property"), getter_template,
|
|
setter_template);
|
|
|
|
Local<Context> context1 = Context::New(isolate(), nullptr);
|
|
Local<Context> context2 = Context::New(isolate(), nullptr);
|
|
|
|
Local<Object> object =
|
|
object_template->NewInstance(context1).ToLocalChecked();
|
|
context2->Global()
|
|
->Set(context2, v8_str("object_from_context1"), object)
|
|
.Check();
|
|
|
|
i::Handle<i::JSFunction> getter = RetrieveFunctionFrom(
|
|
context2,
|
|
"Object.getOwnPropertyDescriptor(object_from_context1, 'property').get");
|
|
|
|
ASSERT_EQ(getter->native_context(), *Utils::OpenHandle(*context1));
|
|
}
|
|
|
|
// Regression test for https://crbug.com/986063.
|
|
TEST_F(AccessRegressionTest,
|
|
InstantiatedLazyAccessorPairsHaveCorrectNativeContextDebug) {
|
|
// The setup creates two contexts and installs an object "object"
|
|
// on the global this for each context.
|
|
// The object consists of:
|
|
// - an accessor pair "property".
|
|
// - a normal function "breakfn".
|
|
//
|
|
// The test sets a break point on {object.breakfn} in the first context.
|
|
// This forces instantation of the JSFunction for the {object.property}
|
|
// accessor pair. The test verifies afterwards that the respective
|
|
// JSFunction of the getter have the correct native context.
|
|
|
|
Local<FunctionTemplate> getter_template = FunctionTemplate::New(
|
|
isolate(), [](const FunctionCallbackInfo<Value>&) { FAIL(); });
|
|
Local<FunctionTemplate> setter_template = FunctionTemplate::New(
|
|
isolate(), [](const FunctionCallbackInfo<v8::Value>&) { FAIL(); });
|
|
Local<FunctionTemplate> break_template = FunctionTemplate::New(
|
|
isolate(), [](const FunctionCallbackInfo<v8::Value>&) { FAIL(); });
|
|
|
|
Local<Context> context1 = Context::New(isolate(), nullptr);
|
|
Local<Context> context2 = Context::New(isolate(), nullptr);
|
|
|
|
Local<ObjectTemplate> object_template = ObjectTemplate::New(isolate());
|
|
object_template->Set(isolate(), "breakfn", break_template);
|
|
object_template->SetAccessorProperty(v8_str("property"), getter_template,
|
|
setter_template);
|
|
|
|
Local<Object> object1 =
|
|
object_template->NewInstance(context1).ToLocalChecked();
|
|
EXPECT_TRUE(
|
|
context1->Global()->Set(context1, v8_str("object"), object1).IsJust());
|
|
|
|
Local<Object> object2 =
|
|
object_template->NewInstance(context2).ToLocalChecked();
|
|
EXPECT_TRUE(
|
|
context2->Global()->Set(context2, v8_str("object"), object2).IsJust());
|
|
|
|
// Force instantiation of the JSFunction for the getter and setter
|
|
// of {object.property} by setting a break point on {object.breakfn}
|
|
{
|
|
Context::Scope context_scope(context1);
|
|
i::Isolate* iso = reinterpret_cast<i::Isolate*>(isolate());
|
|
i::Handle<i::JSFunction> break_fn =
|
|
RetrieveFunctionFrom(context1, "object.breakfn");
|
|
|
|
int id;
|
|
iso->debug()->SetBreakpointForFunction(i::handle(break_fn->shared(), iso),
|
|
iso->factory()->empty_string(), &id);
|
|
}
|
|
|
|
i::Handle<i::JSFunction> getter_c1 = RetrieveFunctionFrom(
|
|
context1, "Object.getOwnPropertyDescriptor(object, 'property').get");
|
|
i::Handle<i::JSFunction> getter_c2 = RetrieveFunctionFrom(
|
|
context2, "Object.getOwnPropertyDescriptor(object, 'property').get");
|
|
|
|
ASSERT_EQ(getter_c1->native_context(), *Utils::OpenHandle(*context1));
|
|
ASSERT_EQ(getter_c2->native_context(), *Utils::OpenHandle(*context2));
|
|
}
|
|
|
|
} // namespace v8
|