deps: cherry-pick e1a7699 from upstream V8
Original commit message:
[api][runtime] Support all-in ctors of {Named,Indexed}PropertyHandlerConfiguration
- Explicitly allows construction of
{Named,Indexed}PropertyHandlerConfiguration with all the members filled.
Bug: v8:7612
Cq-Include-Trybots: luci.chromium.try:linux_chromium_rel_ng
Change-Id: I426ea33846b5dbf2b3482c722c963a6e4b0abded
Reviewed-on: https://chromium-review.googlesource.com/1163882
Reviewed-by: Toon Verwaest <verwaest@chromium.org>
Reviewed-by: Adam Klein <adamk@chromium.org>
Commit-Queue: Camillo Bruni <cbruni@chromium.org>
Cr-Commit-Position: refs/heads/master@{#55142}
PR-URL: https://github.com/nodejs/node/pull/22390
Fixes: https://github.com/nodejs/node/issues/17480
Fixes: https://github.com/nodejs/node/issues/17481
Refs: e1a76995ef
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Reviewed-By: Gus Caplan <me@gus.host>
Reviewed-By: James M Snell <jasnell@gmail.com>
This commit is contained in:
parent
2f9dabd0d8
commit
349612b233
@ -29,7 +29,7 @@
|
|||||||
|
|
||||||
# Reset this number to 0 on major V8 upgrades.
|
# Reset this number to 0 on major V8 upgrades.
|
||||||
# Increment by one for each non-official patch applied to deps/v8.
|
# Increment by one for each non-official patch applied to deps/v8.
|
||||||
'v8_embedder_string': '-node.17',
|
'v8_embedder_string': '-node.18',
|
||||||
|
|
||||||
# Enable disassembler for `--print-code` v8 options
|
# Enable disassembler for `--print-code` v8 options
|
||||||
'v8_enable_disassembler': 1,
|
'v8_enable_disassembler': 1,
|
||||||
|
39
deps/v8/include/v8.h
vendored
39
deps/v8/include/v8.h
vendored
@ -5878,6 +5878,26 @@ enum class PropertyHandlerFlags {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct NamedPropertyHandlerConfiguration {
|
struct NamedPropertyHandlerConfiguration {
|
||||||
|
NamedPropertyHandlerConfiguration(
|
||||||
|
GenericNamedPropertyGetterCallback getter,
|
||||||
|
GenericNamedPropertySetterCallback setter,
|
||||||
|
GenericNamedPropertyQueryCallback query,
|
||||||
|
GenericNamedPropertyDeleterCallback deleter,
|
||||||
|
GenericNamedPropertyEnumeratorCallback enumerator,
|
||||||
|
GenericNamedPropertyDefinerCallback definer,
|
||||||
|
GenericNamedPropertyDescriptorCallback descriptor,
|
||||||
|
Local<Value> data = Local<Value>(),
|
||||||
|
PropertyHandlerFlags flags = PropertyHandlerFlags::kNone)
|
||||||
|
: getter(getter),
|
||||||
|
setter(setter),
|
||||||
|
query(query),
|
||||||
|
deleter(deleter),
|
||||||
|
enumerator(enumerator),
|
||||||
|
definer(definer),
|
||||||
|
descriptor(descriptor),
|
||||||
|
data(data),
|
||||||
|
flags(flags) {}
|
||||||
|
|
||||||
NamedPropertyHandlerConfiguration(
|
NamedPropertyHandlerConfiguration(
|
||||||
/** Note: getter is required */
|
/** Note: getter is required */
|
||||||
GenericNamedPropertyGetterCallback getter = 0,
|
GenericNamedPropertyGetterCallback getter = 0,
|
||||||
@ -5929,6 +5949,25 @@ struct NamedPropertyHandlerConfiguration {
|
|||||||
|
|
||||||
|
|
||||||
struct IndexedPropertyHandlerConfiguration {
|
struct IndexedPropertyHandlerConfiguration {
|
||||||
|
IndexedPropertyHandlerConfiguration(
|
||||||
|
IndexedPropertyGetterCallback getter,
|
||||||
|
IndexedPropertySetterCallback setter, IndexedPropertyQueryCallback query,
|
||||||
|
IndexedPropertyDeleterCallback deleter,
|
||||||
|
IndexedPropertyEnumeratorCallback enumerator,
|
||||||
|
IndexedPropertyDefinerCallback definer,
|
||||||
|
IndexedPropertyDescriptorCallback descriptor,
|
||||||
|
Local<Value> data = Local<Value>(),
|
||||||
|
PropertyHandlerFlags flags = PropertyHandlerFlags::kNone)
|
||||||
|
: getter(getter),
|
||||||
|
setter(setter),
|
||||||
|
query(query),
|
||||||
|
deleter(deleter),
|
||||||
|
enumerator(enumerator),
|
||||||
|
definer(definer),
|
||||||
|
descriptor(descriptor),
|
||||||
|
data(data),
|
||||||
|
flags(flags) {}
|
||||||
|
|
||||||
IndexedPropertyHandlerConfiguration(
|
IndexedPropertyHandlerConfiguration(
|
||||||
/** Note: getter is required */
|
/** Note: getter is required */
|
||||||
IndexedPropertyGetterCallback getter = 0,
|
IndexedPropertyGetterCallback getter = 0,
|
||||||
|
4
deps/v8/src/api.cc
vendored
4
deps/v8/src/api.cc
vendored
@ -1811,10 +1811,6 @@ static i::Handle<i::InterceptorInfo> CreateInterceptorInfo(
|
|||||||
i::Isolate* isolate, Getter getter, Setter setter, Query query,
|
i::Isolate* isolate, Getter getter, Setter setter, Query query,
|
||||||
Descriptor descriptor, Deleter remover, Enumerator enumerator,
|
Descriptor descriptor, Deleter remover, Enumerator enumerator,
|
||||||
Definer definer, Local<Value> data, PropertyHandlerFlags flags) {
|
Definer definer, Local<Value> data, PropertyHandlerFlags flags) {
|
||||||
// Either intercept attributes or descriptor.
|
|
||||||
DCHECK(query == nullptr || descriptor == nullptr);
|
|
||||||
// Only use descriptor callback with definer callback.
|
|
||||||
DCHECK(query == nullptr || definer == nullptr);
|
|
||||||
auto obj = i::Handle<i::InterceptorInfo>::cast(
|
auto obj = i::Handle<i::InterceptorInfo>::cast(
|
||||||
isolate->factory()->NewStruct(i::INTERCEPTOR_INFO_TYPE, i::TENURED));
|
isolate->factory()->NewStruct(i::INTERCEPTOR_INFO_TYPE, i::TENURED));
|
||||||
obj->set_flags(0);
|
obj->set_flags(0);
|
||||||
|
63
deps/v8/src/objects.cc
vendored
63
deps/v8/src/objects.cc
vendored
@ -7672,41 +7672,42 @@ Maybe<bool> GetPropertyDescriptorWithInterceptor(LookupIterator* it,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (it->state() == LookupIterator::INTERCEPTOR) {
|
if (it->state() != LookupIterator::INTERCEPTOR) return Just(false);
|
||||||
Isolate* isolate = it->isolate();
|
|
||||||
Handle<InterceptorInfo> interceptor = it->GetInterceptor();
|
|
||||||
if (!interceptor->descriptor()->IsUndefined(isolate)) {
|
|
||||||
Handle<Object> result;
|
|
||||||
Handle<JSObject> holder = it->GetHolder<JSObject>();
|
|
||||||
|
|
||||||
Handle<Object> receiver = it->GetReceiver();
|
Isolate* isolate = it->isolate();
|
||||||
if (!receiver->IsJSReceiver()) {
|
Handle<InterceptorInfo> interceptor = it->GetInterceptor();
|
||||||
ASSIGN_RETURN_ON_EXCEPTION_VALUE(
|
if (interceptor->descriptor()->IsUndefined(isolate)) return Just(false);
|
||||||
isolate, receiver, Object::ConvertReceiver(isolate, receiver),
|
|
||||||
Nothing<bool>());
|
|
||||||
}
|
|
||||||
|
|
||||||
PropertyCallbackArguments args(isolate, interceptor->data(), *receiver,
|
Handle<Object> result;
|
||||||
*holder, kDontThrow);
|
Handle<JSObject> holder = it->GetHolder<JSObject>();
|
||||||
if (it->IsElement()) {
|
|
||||||
result = args.CallIndexedDescriptor(interceptor, it->index());
|
|
||||||
} else {
|
|
||||||
result = args.CallNamedDescriptor(interceptor, it->name());
|
|
||||||
}
|
|
||||||
if (!result.is_null()) {
|
|
||||||
// Request successfully intercepted, try to set the property
|
|
||||||
// descriptor.
|
|
||||||
Utils::ApiCheck(
|
|
||||||
PropertyDescriptor::ToPropertyDescriptor(isolate, result, desc),
|
|
||||||
it->IsElement() ? "v8::IndexedPropertyDescriptorCallback"
|
|
||||||
: "v8::NamedPropertyDescriptorCallback",
|
|
||||||
"Invalid property descriptor.");
|
|
||||||
|
|
||||||
return Just(true);
|
Handle<Object> receiver = it->GetReceiver();
|
||||||
}
|
if (!receiver->IsJSReceiver()) {
|
||||||
it->Next();
|
ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, receiver,
|
||||||
}
|
Object::ConvertReceiver(isolate, receiver),
|
||||||
|
Nothing<bool>());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PropertyCallbackArguments args(isolate, interceptor->data(), *receiver,
|
||||||
|
*holder, kDontThrow);
|
||||||
|
if (it->IsElement()) {
|
||||||
|
result = args.CallIndexedDescriptor(interceptor, it->index());
|
||||||
|
} else {
|
||||||
|
result = args.CallNamedDescriptor(interceptor, it->name());
|
||||||
|
}
|
||||||
|
if (!result.is_null()) {
|
||||||
|
// Request successfully intercepted, try to set the property
|
||||||
|
// descriptor.
|
||||||
|
Utils::ApiCheck(
|
||||||
|
PropertyDescriptor::ToPropertyDescriptor(isolate, result, desc),
|
||||||
|
it->IsElement() ? "v8::IndexedPropertyDescriptorCallback"
|
||||||
|
: "v8::NamedPropertyDescriptorCallback",
|
||||||
|
"Invalid property descriptor.");
|
||||||
|
|
||||||
|
return Just(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
it->Next();
|
||||||
return Just(false);
|
return Just(false);
|
||||||
}
|
}
|
||||||
} // namespace
|
} // namespace
|
||||||
|
176
deps/v8/test/unittests/api/interceptor-unittest.cc
vendored
176
deps/v8/test/unittests/api/interceptor-unittest.cc
vendored
@ -29,4 +29,180 @@ TEST_F(InterceptorTest, FreezeApiObjectWithInterceptor) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
|
namespace internal {
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
class InterceptorLoggingTest : public TestWithNativeContext {
|
||||||
|
public:
|
||||||
|
InterceptorLoggingTest() {}
|
||||||
|
|
||||||
|
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
|
} // namespace v8
|
||||||
|
Loading…
x
Reference in New Issue
Block a user