[runtime] Fix handling of interceptors, pt.3

... in JSObject::DefineOwnPropertyIgnoreAttributes().
Don't execute interceptor again if it declined to handle the operation.

Bug: chromium:1311641
Change-Id: If61ed40665ff7d81e96fa6bf29bbb5dfbeadfcc1
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3562979
Reviewed-by: Toon Verwaest <verwaest@chromium.org>
Commit-Queue: Igor Sheludko <ishell@chromium.org>
Cr-Commit-Position: refs/heads/main@{#79707}
This commit is contained in:
Igor Sheludko 2022-03-31 23:47:27 +02:00 committed by V8 LUCI CQ
parent 28f5698277
commit c4e66b89b4
2 changed files with 69 additions and 5 deletions

View File

@ -3512,9 +3512,19 @@ Maybe<bool> JSObject::DefineOwnPropertyIgnoreAttributes(
if (can_define.IsNothing() || !can_define.FromJust()) {
return can_define;
}
it->Restart();
}
break;
// The interceptor declined to handle the operation, so proceed defining
// own property without the interceptor.
Isolate* isolate = it->isolate();
Handle<Object> receiver = it->GetReceiver();
LookupIterator::Configuration c = LookupIterator::OWN_SKIP_INTERCEPTOR;
LookupIterator own_lookup =
it->IsElement() ? LookupIterator(isolate, receiver, it->index(), c)
: LookupIterator(isolate, receiver, it->name(), c);
return JSObject::DefineOwnPropertyIgnoreAttributes(
&own_lookup, value, attributes, should_throw, handling, semantics,
store_origin);
}
case LookupIterator::ACCESSOR: {

View File

@ -60,6 +60,16 @@ void EmptyInterceptorDeleter(
void EmptyInterceptorEnumerator(
const v8::PropertyCallbackInfo<v8::Array>& info) {}
void EmptyInterceptorDefinerWithSideEffect(
Local<Name> name, const v8::PropertyDescriptor& desc,
const v8::PropertyCallbackInfo<v8::Value>& info) {
ApiTestFuzzer::Fuzz();
v8::Local<v8::Value> result = CompileRun("interceptor_definer_side_effect()");
if (!result->IsNull()) {
info.GetReturnValue().Set(result);
}
}
void SimpleAccessorGetter(Local<String> name,
const v8::PropertyCallbackInfo<v8::Value>& info) {
Local<Object> self = info.This().As<Object>();
@ -869,13 +879,17 @@ THREADED_TEST(InterceptorHasOwnPropertyCausingGC) {
namespace {
void CheckInterceptorIC(v8::GenericNamedPropertyGetterCallback getter,
v8::GenericNamedPropertySetterCallback setter,
v8::GenericNamedPropertyQueryCallback query,
const char* source, int expected) {
v8::GenericNamedPropertyDefinerCallback definer,
v8::PropertyHandlerFlags flags, const char* source,
int expected) {
v8::Isolate* isolate = CcTest::isolate();
v8::HandleScope scope(isolate);
v8::Local<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
templ->SetHandler(v8::NamedPropertyHandlerConfiguration(
getter, nullptr, query, nullptr, nullptr, v8_str("data")));
getter, setter, query, nullptr /* deleter */, nullptr /* enumerator */,
definer, nullptr /* descriptor */, v8_str("data"), flags));
LocalContext context;
context->Global()
->Set(context.local(), v8_str("o"),
@ -885,9 +899,17 @@ void CheckInterceptorIC(v8::GenericNamedPropertyGetterCallback getter,
CHECK_EQ(expected, value->Int32Value(context.local()).FromJust());
}
void CheckInterceptorIC(v8::GenericNamedPropertyGetterCallback getter,
v8::GenericNamedPropertyQueryCallback query,
const char* source, int expected) {
CheckInterceptorIC(getter, nullptr, query, nullptr,
v8::PropertyHandlerFlags::kNone, source, expected);
}
void CheckInterceptorLoadIC(v8::GenericNamedPropertyGetterCallback getter,
const char* source, int expected) {
CheckInterceptorIC(getter, nullptr, source, expected);
CheckInterceptorIC(getter, nullptr, nullptr, nullptr,
v8::PropertyHandlerFlags::kNone, source, expected);
}
void InterceptorLoadICGetter(Local<Name> name,
@ -1581,6 +1603,38 @@ THREADED_TEST(InterceptorStoreICWithSideEffectfulCallbacks) {
19);
}
THREADED_TEST(InterceptorDefineICWithSideEffectfulCallbacks) {
CheckInterceptorIC(EmptyInterceptorGetter, EmptyInterceptorSetter,
EmptyInterceptorQuery,
EmptyInterceptorDefinerWithSideEffect,
v8::PropertyHandlerFlags::kNonMasking,
"let inside_side_effect = false;"
"let interceptor_definer_side_effect = function() {"
" if (!inside_side_effect) {"
" inside_side_effect = true;"
" o.y = 153;"
" inside_side_effect = false;"
" }"
" return null;"
"};"
"class Base {"
" constructor(arg) {"
" return arg;"
" }"
"}"
"class ClassWithField extends Base {"
" y = (() => {"
" return 42;"
" })();"
" constructor(arg) {"
" super(arg);"
" }"
"}"
"new ClassWithField(o);"
"o.y",
42);
}
static void InterceptorStoreICSetter(
Local<Name> key, Local<Value> value,
const v8::PropertyCallbackInfo<v8::Value>& info) {