v8/test/unittests/api/interceptor-unittest.cc
Dan Elphick ec06bb6ce5 Reland "[include] Split out v8.h"
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}
2021-08-24 13:08:55 +00:00

213 lines
7.0 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-exception.h"
#include "include/v8-function.h"
#include "include/v8-local-handle.h"
#include "include/v8-object.h"
#include "include/v8-template.h"
#include "test/unittests/test-utils.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace v8 {
namespace {
using InterceptorTest = TestWithContext;
void NamedGetter(Local<Name> property,
const PropertyCallbackInfo<Value>& info) {}
TEST_F(InterceptorTest, FreezeApiObjectWithInterceptor) {
TryCatch try_catch(isolate());
Local<FunctionTemplate> tmpl = FunctionTemplate::New(isolate());
tmpl->InstanceTemplate()->SetHandler(
NamedPropertyHandlerConfiguration(NamedGetter));
Local<Function> ctor = tmpl->GetFunction(context()).ToLocalChecked();
Local<Object> obj = ctor->NewInstance(context()).ToLocalChecked();
ASSERT_TRUE(
obj->SetIntegrityLevel(context(), IntegrityLevel::kFrozen).IsNothing());
ASSERT_TRUE(try_catch.HasCaught());
}
} // namespace
namespace internal {
namespace {
class InterceptorLoggingTest : public TestWithNativeContext {
public:
InterceptorLoggingTest() = default;
static const int kTestIndex = 0;
static void NamedPropertyGetter(Local<v8::Name> name,
const v8::PropertyCallbackInfo<Value>& info) {
LogCallback(info, "named getter");
}
static void NamedPropertySetter(Local<v8::Name> name, Local<v8::Value> value,
const v8::PropertyCallbackInfo<Value>& info) {
LogCallback(info, "named setter");
}
static void NamedPropertyQuery(
Local<v8::Name> name, const v8::PropertyCallbackInfo<v8::Integer>& info) {
LogCallback(info, "named query");
}
static void NamedPropertyDeleter(
Local<v8::Name> name, const v8::PropertyCallbackInfo<v8::Boolean>& info) {
LogCallback(info, "named deleter");
}
static void NamedPropertyEnumerator(
const v8::PropertyCallbackInfo<Array>& info) {
LogCallback(info, "named enumerator");
}
static void NamedPropertyDefiner(
Local<v8::Name> name, const v8::PropertyDescriptor& desc,
const v8::PropertyCallbackInfo<Value>& info) {
LogCallback(info, "named definer");
}
static void NamedPropertyDescriptor(
Local<v8::Name> name, const v8::PropertyCallbackInfo<Value>& info) {
LogCallback(info, "named descriptor");
}
static void IndexedPropertyGetter(
uint32_t index, const v8::PropertyCallbackInfo<Value>& info) {
LogCallback(info, "indexed getter");
}
static void IndexedPropertySetter(
uint32_t index, Local<v8::Value> value,
const v8::PropertyCallbackInfo<Value>& info) {
LogCallback(info, "indexed setter");
}
static void IndexedPropertyQuery(
uint32_t index, const v8::PropertyCallbackInfo<v8::Integer>& info) {
LogCallback(info, "indexed query");
}
static void IndexedPropertyDeleter(
uint32_t index, const v8::PropertyCallbackInfo<v8::Boolean>& info) {
LogCallback(info, "indexed deleter");
}
static void IndexedPropertyEnumerator(
const v8::PropertyCallbackInfo<Array>& info) {
LogCallback(info, "indexed enumerator");
}
static void IndexedPropertyDefiner(
uint32_t index, const v8::PropertyDescriptor& desc,
const v8::PropertyCallbackInfo<Value>& info) {
LogCallback(info, "indexed definer");
}
static void IndexedPropertyDescriptor(
uint32_t index, const v8::PropertyCallbackInfo<Value>& info) {
LogCallback(info, "indexed descriptor");
}
template <class T>
static void LogCallback(const v8::PropertyCallbackInfo<T>& info,
const char* callback_name) {
InterceptorLoggingTest* test = reinterpret_cast<InterceptorLoggingTest*>(
info.This()->GetAlignedPointerFromInternalField(kTestIndex));
test->Log(callback_name);
}
void Log(const char* callback_name) {
if (log_is_empty_) {
log_is_empty_ = false;
} else {
log_ << ", ";
}
log_ << callback_name;
}
protected:
void SetUp() override {
// Set up the object that supports full interceptors.
v8::Local<v8::ObjectTemplate> templ = v8::ObjectTemplate::New(v8_isolate());
templ->SetInternalFieldCount(1);
templ->SetHandler(v8::NamedPropertyHandlerConfiguration(
NamedPropertyGetter, NamedPropertySetter, NamedPropertyQuery,
NamedPropertyDeleter, NamedPropertyEnumerator, NamedPropertyDefiner,
NamedPropertyDescriptor));
templ->SetHandler(v8::IndexedPropertyHandlerConfiguration(
IndexedPropertyGetter, IndexedPropertySetter, IndexedPropertyQuery,
IndexedPropertyDeleter, IndexedPropertyEnumerator,
IndexedPropertyDefiner, IndexedPropertyDescriptor));
v8::Local<v8::Object> instance =
templ->NewInstance(context()).ToLocalChecked();
instance->SetAlignedPointerInInternalField(kTestIndex, this);
SetGlobalProperty("obj", instance);
}
std::string Run(const char* script) {
log_is_empty_ = true;
log_.str(std::string());
log_.clear();
RunJS(script);
return log_.str();
}
private:
bool log_is_empty_ = false;
std::stringstream log_;
};
TEST_F(InterceptorLoggingTest, DispatchTest) {
EXPECT_EQ(Run("for (var p in obj) {}"),
"indexed enumerator, named enumerator");
EXPECT_EQ(Run("Object.keys(obj)"), "indexed enumerator, named enumerator");
EXPECT_EQ(Run("obj.foo"), "named getter");
EXPECT_EQ(Run("obj[42]"), "indexed getter");
EXPECT_EQ(Run("obj.foo = null"), "named setter");
EXPECT_EQ(Run("obj[42] = null"), "indexed setter");
EXPECT_EQ(Run("Object.getOwnPropertyDescriptor(obj, 'foo')"),
"named descriptor");
EXPECT_EQ(Run("Object.getOwnPropertyDescriptor(obj, 42)"),
"indexed descriptor");
EXPECT_EQ(Run("Object.defineProperty(obj, 'foo', {value: 42})"),
"named descriptor, named definer, named setter");
EXPECT_EQ(Run("Object.defineProperty(obj, 'foo', {get(){} })"),
"named descriptor, named definer");
EXPECT_EQ(Run("Object.defineProperty(obj, 'foo', {set(value){}})"),
"named descriptor, named definer");
EXPECT_EQ(Run("Object.defineProperty(obj, 'foo', {get(){}, set(value){}})"),
"named descriptor, named definer");
EXPECT_EQ(Run("Object.defineProperty(obj, 42, {value: 'foo'})"),
"indexed descriptor, "
// then attempt definer first and fallback to setter.
"indexed definer, indexed setter");
EXPECT_EQ(Run("Object.prototype.propertyIsEnumerable.call(obj, 'a')"),
"named query");
EXPECT_EQ(Run("Object.prototype.propertyIsEnumerable.call(obj, 42)"),
"indexed query");
EXPECT_EQ(Run("Object.prototype.hasOwnProperty.call(obj, 'a')"),
"named query");
// TODO(cbruni): Fix once hasOnwProperty is fixed (https://crbug.com/872628)
EXPECT_EQ(Run("Object.prototype.hasOwnProperty.call(obj, '42')"), "");
}
} // namespace
} // namespace internal
} // namespace v8