Browse Source

chore: cherry-pick 8 changes from Release-0-M114 (#38533)

* chore: [23-x-y] cherry-pick 6 changes from Release-0-M114

* c6ec59dcae7d from angle
* 93c6be3a42e7 from chromium
* e6b75a8b4900 from chromium
* 3b0607d14060 from v8
* 9c6dfc733fce from v8
* ea1cd76358e0 from chromium

* chore: remove 2 invalid patches, fix 2 others

* chore: add missing backports.

* chore: fix backports.

* chore: further fix a backport

* chore: update patches

---------

Co-authored-by: Pedro Pontes <[email protected]>
Co-authored-by: PatchUp <73610968+patchup[bot]@users.noreply.github.com>
Keeley Hammond 1 year ago
parent
commit
60c84cbd77

+ 3 - 0
patches/chromium/.patches

@@ -141,3 +141,6 @@ merge_m112_check_spdyproxyclientsocket_is_alive_after_write.patch
 check_callback_availability_in.patch
 m112_cherry_pick_libxml_cve_fix.patch
 m112_fix_scopedobservation_uaf_in.patch
+cherry-pick-ea1cd76358e0.patch
+m114_merge_fix_a_crash_caused_by_calling_trace_event.patch
+mojoipcz_copy_incoming_messages_early.patch

+ 200 - 0
patches/chromium/cherry-pick-ea1cd76358e0.patch

@@ -0,0 +1,200 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Kevin McNee <[email protected]>
+Date: Tue, 23 May 2023 15:46:16 +0000
+Subject: M114: Compute all webview find options before cloning them
+
+Compute all webview find options before cloning them
+
+In WebViewFindHelper::Find, we're cloning the find options before we've
+set the value for `new_session`. For requests that are part of the same
+session, in WebViewFindHelper::FindReply, we're using the incorrect
+value for `new_session` and we're destroying the FindInfo for what we
+think is a previous session but is actually for the request we're
+currently processing.
+
+We now fully compute the options before cloning them.
+
+(cherry picked from commit bb8e17b942b8b1de0a58b2dce34197e00a3b6525)
+
+Bug: 1443401
+Change-Id: Ife6747aedabaf74f9a4855a173349ffe612b6f95
+Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4533923
+Reviewed-by: James Maclean <[email protected]>
+Commit-Queue: James Maclean <[email protected]>
+Auto-Submit: Kevin McNee <[email protected]>
+Cr-Original-Commit-Position: refs/heads/main@{#1145265}
+Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4556646
+Commit-Queue: Rubber Stamper <[email protected]>
+Bot-Commit: Rubber Stamper <[email protected]>
+Cr-Commit-Position: refs/branch-heads/5735@{#941}
+Cr-Branched-From: 2f562e4ddbaf79a3f3cb338b4d1bd4398d49eb67-refs/heads/main@{#1135570}
+
+diff --git a/chrome/browser/apps/guest_view/web_view_browsertest.cc b/chrome/browser/apps/guest_view/web_view_browsertest.cc
+index cebe56b9e79cbe0e5a58f73e68faf1b93b17ce5c..3748f8119bf1d4f37635bdb4fb87d825881de7f0 100644
+--- a/chrome/browser/apps/guest_view/web_view_browsertest.cc
++++ b/chrome/browser/apps/guest_view/web_view_browsertest.cc
+@@ -3888,6 +3888,11 @@ IN_PROC_BROWSER_TEST_P(WebViewTest, Shim_testFindInMultipleWebViews) {
+   TestHelper("testFindInMultipleWebViews", "web_view/shim", NO_TEST_SERVER);
+ }
+ 
++IN_PROC_BROWSER_TEST_F(WebViewTest, Shim_TestFindAfterTerminate) {
++  content::ScopedAllowRendererCrashes scoped_allow_renderer_crashes;
++  TestHelper("testFindAfterTerminate", "web_view/shim", NO_TEST_SERVER);
++}
++
+ IN_PROC_BROWSER_TEST_P(WebViewTest, Shim_TestLoadDataAPI) {
+   TestHelper("testLoadDataAPI", "web_view/shim", NEEDS_TEST_SERVER);
+ 
+diff --git a/chrome/test/data/extensions/platform_apps/web_view/shim/main.js b/chrome/test/data/extensions/platform_apps/web_view/shim/main.js
+index 5ed4f0223346b01d83cc04c8cda6c0e92e1a72e3..4a1543d1751cc817a511594d0123deacc0e61ebb 100644
+--- a/chrome/test/data/extensions/platform_apps/web_view/shim/main.js
++++ b/chrome/test/data/extensions/platform_apps/web_view/shim/main.js
+@@ -2859,6 +2859,20 @@ function testFindInMultipleWebViews() {
+       });
+ }
+ 
++function testFindAfterTerminate() {
++  let webview = new WebView();
++  webview.src = 'data:text/html,<body><iframe></iframe></body>';
++  webview.addEventListener('loadstop', () => {
++    webview.find('A');
++    webview.terminate();
++    webview.find('B', {'backward': true});
++    webview.find('B', {'backward': true}, (results) => {
++      embedder.test.succeed();
++    });
++  });
++  document.body.appendChild(webview);
++}
++
+ function testLoadDataAPI() {
+   var webview = new WebView();
+   webview.src = 'about:blank';
+@@ -3600,6 +3614,7 @@ embedder.test.testList = {
+   'testFindAPI': testFindAPI,
+   'testFindAPI_findupdate': testFindAPI_findupdate,
+   'testFindInMultipleWebViews': testFindInMultipleWebViews,
++  'testFindAfterTerminate': testFindAfterTerminate,
+   'testLoadDataAPI': testLoadDataAPI,
+   'testLoadDataAPIAccessibleResources': testLoadDataAPIAccessibleResources,
+   'testResizeEvents': testResizeEvents,
+diff --git a/extensions/browser/guest_view/web_view/web_view_find_helper.cc b/extensions/browser/guest_view/web_view/web_view_find_helper.cc
+index 1e9148687f6871dff8a394cce53771e443775679..37630dc2f0a6365bbf33e765f4d126e2962fbb2a 100644
+--- a/extensions/browser/guest_view/web_view/web_view_find_helper.cc
++++ b/extensions/browser/guest_view/web_view/web_view_find_helper.cc
+@@ -36,12 +36,12 @@ void WebViewFindHelper::CancelAllFindSessions() {
+ 
+ void WebViewFindHelper::DispatchFindUpdateEvent(bool canceled,
+                                                 bool final_update) {
+-  DCHECK(find_update_event_.get());
++  CHECK(find_update_event_);
+   base::Value::Dict args;
+   find_update_event_->PrepareResults(args);
+   args.Set(webview::kFindCanceled, canceled);
+   args.Set(webview::kFindFinalUpdate, final_update);
+-  DCHECK(webview_guest_);
++  CHECK(webview_guest_);
+   webview_guest_->DispatchEventToView(std::make_unique<GuestViewEvent>(
+       webview::kEventFindReply, std::move(args)));
+ }
+@@ -94,6 +94,17 @@ void WebViewFindHelper::Find(
+   // Need a new request_id for each new find request.
+   ++current_find_request_id_;
+ 
++  if (current_find_session_) {
++    const std::u16string& current_search_text =
++        current_find_session_->search_text();
++    bool current_match_case = current_find_session_->options()->match_case;
++    options->new_session = current_search_text.empty() ||
++                           current_search_text != search_text ||
++                           current_match_case != options->match_case;
++  } else {
++    options->new_session = true;
++  }
++
+   // Stores the find request information by request_id so that its callback
+   // function can be called when the find results are available.
+   std::pair<FindInfoMap::iterator, bool> insert_result =
+@@ -102,32 +113,19 @@ void WebViewFindHelper::Find(
+           base::MakeRefCounted<FindInfo>(current_find_request_id_, search_text,
+                                          options.Clone(), find_function)));
+   // No duplicate insertions.
+-  DCHECK(insert_result.second);
+-
+-  blink::mojom::FindOptionsPtr full_options =
+-      insert_result.first->second->options().Clone();
+-
+-  if (current_find_session_) {
+-    const std::u16string& current_search_text =
+-        current_find_session_->search_text();
+-    bool current_match_case = current_find_session_->options()->match_case;
+-    full_options->new_session = current_search_text.empty() ||
+-                                current_search_text != search_text ||
+-                                current_match_case != options->match_case;
+-  } else {
+-    full_options->new_session = true;
+-  }
++  CHECK(insert_result.second);
+ 
+   // Link find requests that are a part of the same find session.
+-  if (!full_options->new_session && current_find_session_) {
+-    DCHECK(current_find_request_id_ != current_find_session_->request_id());
++  if (!options->new_session && current_find_session_) {
++    CHECK(current_find_request_id_ != current_find_session_->request_id());
+     current_find_session_->AddFindNextRequest(
+         insert_result.first->second->AsWeakPtr());
+   }
+ 
+   // Update the current find session, if necessary.
+-  if (full_options->new_session)
++  if (options->new_session) {
+     current_find_session_ = insert_result.first->second;
++  }
+ 
+   // Handle the empty |search_text| case internally.
+   if (search_text.empty()) {
+@@ -137,7 +135,7 @@ void WebViewFindHelper::Find(
+   }
+ 
+   guest_web_contents->Find(current_find_request_id_, search_text,
+-                           std::move(full_options), /*skip_delay=*/true);
++                           std::move(options), /*skip_delay=*/true);
+ }
+ 
+ void WebViewFindHelper::FindReply(int request_id,
+@@ -152,14 +150,14 @@ void WebViewFindHelper::FindReply(int request_id,
+     return;
+ 
+   // This find request must be a part of an existing find session.
+-  DCHECK(current_find_session_);
++  CHECK(current_find_session_);
+ 
+   WebViewFindHelper::FindInfo* find_info = find_iterator->second.get();
+   // Handle canceled find requests.
+   if (find_info->options()->new_session &&
+       find_info_map_.begin()->first < request_id) {
+-    DCHECK_NE(current_find_session_->request_id(),
+-              find_info_map_.begin()->first);
++    CHECK_NE(current_find_session_->request_id(),
++             find_info_map_.begin()->first);
+     if (find_update_event_)
+       DispatchFindUpdateEvent(true /* canceled */, true /* final_update */);
+     EndFindSession(find_info_map_.begin()->first, true /* canceled */);
+@@ -174,11 +172,12 @@ void WebViewFindHelper::FindReply(int request_id,
+   // Aggregate the find results.
+   find_info->AggregateResults(number_of_matches, selection_rect,
+                               active_match_ordinal, final_update);
+-  find_update_event_->AggregateResults(number_of_matches, selection_rect,
+-                                      active_match_ordinal, final_update);
+-
+-  // Propagate incremental results to the |findupdate| event.
+-  DispatchFindUpdateEvent(false /* canceled */, final_update);
++  if (find_update_event_) {
++    find_update_event_->AggregateResults(number_of_matches, selection_rect,
++                                         active_match_ordinal, final_update);
++    // Propagate incremental results to the |findupdate| event.
++    DispatchFindUpdateEvent(false /* canceled */, final_update);
++  }
+ 
+   // Call the callback functions of completed find requests.
+   if (final_update)

+ 38 - 0
patches/chromium/m114_merge_fix_a_crash_caused_by_calling_trace_event.patch

@@ -0,0 +1,38 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Maggie Chen <[email protected]>
+Date: Thu, 18 May 2023 00:20:34 +0000
+Subject: Fix a crash caused by calling TRACE_EVENT
+
+Now use literal constant for TRACE_EVENT. Passing a pointer instead of
+string content to TRACE_EVENT causes a crash in ScopedTracer.
+
+(cherry picked from commit 6f2e587807aff2306309025db1c15fc59290eb6f)
+
+Bug: 1444195
+Change-Id: I02aa1148d61e7596e9293ffc866135e99991e42e
+Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4522164
+Reviewed-by: Sunny Sachanandani <[email protected]>
+Commit-Queue: Maggie Chen <[email protected]>
+Cr-Original-Commit-Position: refs/heads/main@{#1144352}
+Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4544885
+Bot-Commit: Rubber Stamper <[email protected]>
+Cr-Commit-Position: refs/branch-heads/5735@{#749}
+Cr-Branched-From: 2f562e4ddbaf79a3f3cb338b4d1bd4398d49eb67-refs/heads/main@{#1135570}
+
+diff --git a/ui/gl/swap_chain_presenter.cc b/ui/gl/swap_chain_presenter.cc
+index 54a8dfdd931a22c5acfe3613204ea3a89b842d13..1e76a1a655d0f9de1dd218ad4025a6210ceafc57 100644
+--- a/ui/gl/swap_chain_presenter.cc
++++ b/ui/gl/swap_chain_presenter.cc
+@@ -1698,10 +1698,8 @@ bool SwapChainPresenter::ReallocateSwapChain(
+     }
+   }
+   if (!use_yuv_swap_chain) {
+-    std::ostringstream trace_event_stream;
+-    trace_event_stream << "SwapChainPresenter::ReallocateSwapChain::"
+-                       << DxgiFormatToString(swap_chain_format);
+-    TRACE_EVENT0("gpu", trace_event_stream.str().c_str());
++    TRACE_EVENT1("gpu", "SwapChainPresenter::ReallocateSwapChain::BGRA",
++                 "format", DxgiFormatToString(swap_chain_format));
+ 
+     desc.Format = swap_chain_format;
+     desc.Flags = DXGI_SWAP_CHAIN_FLAG_FULLSCREEN_VIDEO;

+ 51 - 0
patches/chromium/mojoipcz_copy_incoming_messages_early.patch

@@ -0,0 +1,51 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Ken Rockot <[email protected]>
+Date: Mon, 3 Apr 2023 19:43:13 +0000
+Subject: MojoIpcz: Copy incoming messages early
+
+Fixed: 1429720
+Change-Id: Id6cb7269d3a3e9118cc6ff1579b56e18bf911c07
+Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4390758
+Commit-Queue: Ken Rockot <[email protected]>
+Reviewed-by: Daniel Cheng <[email protected]>
+Cr-Commit-Position: refs/heads/main@{#1125510}
+
+diff --git a/mojo/core/ipcz_driver/mojo_message.cc b/mojo/core/ipcz_driver/mojo_message.cc
+index 6194c0c2da8292b8229972eadf9fd6fa56ef0c86..b8372a6281ddcaf0990f55856a9e815fb9d78195 100644
+--- a/mojo/core/ipcz_driver/mojo_message.cc
++++ b/mojo/core/ipcz_driver/mojo_message.cc
+@@ -112,23 +112,20 @@ void MojoMessage::SetParcel(ScopedIpczHandle parcel) {
+ 
+   // We always pass a parcel object in, so Begin/EndGet() must always succeed.
+   DCHECK_EQ(result, IPCZ_RESULT_OK);
++  if (num_bytes > 0) {
++    data_storage_.reset(
++        static_cast<uint8_t*>(base::AllocNonScannable(num_bytes)));
++    memcpy(data_storage_.get(), data, num_bytes);
++  } else {
++    data_storage_.reset();
++  }
++  data_ = {data_storage_.get(), num_bytes};
++  data_storage_size_ = num_bytes;
+ 
+-  // Grab only the handles.
+   handles_.resize(num_handles);
+-  result = GetIpczAPI().EndGet(parcel_.get(), 0, num_handles, IPCZ_NO_FLAGS,
+-                               nullptr, handles_.data());
+-  DCHECK_EQ(result, IPCZ_RESULT_OK);
+-
+-  // Now start a new two-phase get, which we'll leave active indefinitely for
+-  // `data_` to reference.
+-  result = GetIpczAPI().BeginGet(parcel_.get(), IPCZ_NO_FLAGS, nullptr, &data,
+-                                 &num_bytes, &num_handles);
++  result = GetIpczAPI().EndGet(parcel_.get(), num_bytes, num_handles,
++                               IPCZ_NO_FLAGS, nullptr, handles_.data());
+   DCHECK_EQ(result, IPCZ_RESULT_OK);
+-
+-  DCHECK_EQ(0u, num_handles);
+-  data_ = base::make_span(static_cast<uint8_t*>(const_cast<void*>(data)),
+-                          num_bytes);
+-
+   if (!FixUpDataPipeHandles(handles_)) {
+     // The handle list was malformed. Although this is a validation error, it
+     // is not safe to trigger MojoNotifyBadMessage from within MojoReadMessage,

+ 3 - 1
patches/config.json

@@ -25,5 +25,7 @@
 
   "src/electron/patches/webrtc": "src/third_party/webrtc",
 
-  "src/electron/patches/skia": "src/third_party/skia"
+  "src/electron/patches/skia": "src/third_party/skia",
+
+  "src/electron/patches/pdfium": "src/third_party/pdfium"
 }

+ 3 - 0
patches/pdfium/.patches

@@ -0,0 +1,3 @@
+m114_observe_cpwl_combobox_across_all_on_methods.patch
+m114_observe_widget_across_setoptionselection_calls.patch
+m114_always_check_return_code_from_cpwl_combobox_setpopup.patch

+ 236 - 0
patches/pdfium/m114_always_check_return_code_from_cpwl_combobox_setpopup.patch

@@ -0,0 +1,236 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Tom Sepez <[email protected]>
+Date: Fri, 19 May 2023 18:41:31 +0000
+Subject: Always check return code from CPWL_ComboBox::SetPopup().
+
+Operation must not continue when false is returned.
+
+Bug: chromium:1444238
+Change-Id: Ic8c29653ac185ac80b6248203649ce05d0e10f06
+Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/107390
+Commit-Queue: Tom Sepez <[email protected]>
+Reviewed-by: Lei Zhang <[email protected]>
+(cherry picked from commit 3eb3c4d77d4f9372f77aa4895b85a1d4e4755c89)
+Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/107812
+
+diff --git a/fpdfsdk/pwl/cpwl_combo_box.cpp b/fpdfsdk/pwl/cpwl_combo_box.cpp
+index 4cda2135433b07d641d773f184034b0f3dee7e58..f9a8550da29e7a7afca757167af257d95a67bd9f 100644
+--- a/fpdfsdk/pwl/cpwl_combo_box.cpp
++++ b/fpdfsdk/pwl/cpwl_combo_box.cpp
+@@ -400,7 +400,9 @@ bool CPWL_ComboBox::OnChar(uint16_t nChar, Mask<FWL_EVENTFLAG> nFlag) {
+   // options.
+   switch (nChar) {
+     case pdfium::ascii::kReturn:
+-      SetPopup(!IsPopup());
++      if (!SetPopup(!IsPopup())) {
++        return false;
++      }
+       SetSelectText();
+       return true;
+     case pdfium::ascii::kSpace:
+@@ -408,7 +410,9 @@ bool CPWL_ComboBox::OnChar(uint16_t nChar, Mask<FWL_EVENTFLAG> nFlag) {
+       // editable
+       if (!HasFlag(PCBS_ALLOWCUSTOMTEXT)) {
+         if (!IsPopup()) {
+-          SetPopup(/*bPopUp=*/true);
++          if (!SetPopup(/*bPopUp=*/true)) {
++            return false;
++          }
+           SetSelectText();
+         }
+         return true;
+@@ -438,7 +442,7 @@ bool CPWL_ComboBox::OnChar(uint16_t nChar, Mask<FWL_EVENTFLAG> nFlag) {
+ 
+ void CPWL_ComboBox::NotifyLButtonDown(CPWL_Wnd* child, const CFX_PointF& pos) {
+   if (child == m_pButton) {
+-    SetPopup(!m_bPopup);
++    (void)SetPopup(!m_bPopup);
+     // Note, |this| may no longer be viable at this point. If more work needs to
+     // be done, check the return value of SetPopup().
+   }
+@@ -451,7 +455,7 @@ void CPWL_ComboBox::NotifyLButtonUp(CPWL_Wnd* child, const CFX_PointF& pos) {
+   SetSelectText();
+   SelectAllText();
+   m_pEdit->SetFocus();
+-  SetPopup(false);
++  (void)SetPopup(false);
+   // Note, |this| may no longer be viable at this point. If more work needs to
+   // be done, check the return value of SetPopup().
+ }
+diff --git a/fpdfsdk/pwl/cpwl_combo_box.h b/fpdfsdk/pwl/cpwl_combo_box.h
+index 480da52d7a65538dee190e2a609215f9c424bb38..b1ac3d9e8ac29e9433330ff86df7ef4b71a3fabd 100644
+--- a/fpdfsdk/pwl/cpwl_combo_box.h
++++ b/fpdfsdk/pwl/cpwl_combo_box.h
+@@ -64,7 +64,7 @@ class CPWL_ComboBox final : public CPWL_Wnd {
+   void CreateListBox(const CreateParams& cp);
+ 
+   // Returns |true| iff this instance is still allocated.
+-  bool SetPopup(bool bPopup);
++  [[nodiscard]] bool SetPopup(bool bPopup);
+ 
+   UnownedPtr<CPWL_Edit> m_pEdit;
+   UnownedPtr<CPWL_CBButton> m_pButton;
+diff --git a/testing/resources/javascript/xfa_specific/bug_1444238.evt b/testing/resources/javascript/xfa_specific/bug_1444238.evt
+new file mode 100644
+index 0000000000000000000000000000000000000000..adca35aa0d756e76eb395c5d60ba41b86c3d0090
+--- /dev/null
++++ b/testing/resources/javascript/xfa_specific/bug_1444238.evt
+@@ -0,0 +1,3 @@
++mousedown,left,91,539
++mouseup,left,91,539
++charcode,32
+diff --git a/testing/resources/javascript/xfa_specific/bug_1444238.in b/testing/resources/javascript/xfa_specific/bug_1444238.in
+new file mode 100644
+index 0000000000000000000000000000000000000000..675178c9446b0181c3633a4b5c9bc664bb4c127d
+--- /dev/null
++++ b/testing/resources/javascript/xfa_specific/bug_1444238.in
+@@ -0,0 +1,149 @@
++{{header}}
++{{object 1 0}} <<
++  /Type /Catalog
++  /Pages 2 0 R
++  /AcroForm 4 0 R
++  /OpenAction 40 0 R
++>>
++endobj
++{{object 2 0}} <<
++  /Type /Pages
++  /Count 2
++  /Kids [
++    32 0 R
++    34 0 R
++  ]
++>>
++endobj
++% Forms
++{{object 4 0}} <<
++  /XFA 43 0 R
++  /Fields [
++    10 0 R
++    11 0 R
++  ]
++>>
++endobj
++% Fields
++{{object 10 0}} <<
++  /Type /Annot
++  /Subtype /Widget
++  /FT /Tx
++  /T (MyField5)
++  /V (myfield_5)
++  /Rect [0 500 600 600]
++>>
++% Fields
++{{object 11 0}} <<
++  /T (MyField3)
++  /Parent 4 0 R
++  /Kids [12 0 R]
++  /Opt [(a) (b) (c) (d)]
++  /V [(a) (b) (c)]
++>>
++endobj
++% Fields
++{{object 12 0}} <<
++  /Type /Annot
++  /Subtype /Widget
++  /FT /Ch
++  /Ff 131072
++  /Parent 11 0 R
++  /Kids [13 0 R]
++>>
++endobj
++% Fields
++{{object 13 0}} <<
++  /Type /Annot
++  /Subtype /Widget
++  /Parent 12 0 R
++  /Rect [0 400 600 600]
++>>
++endobj
++% Fields
++{{object 14 0}} <<
++  /Type /Annot
++  /Subtype /Widget
++  /Parent 12 0 R
++  /Rect [100 400 500 500]
++>>
++endobj
++% Page number 2.
++{{object 32 0}} <<
++  /Type /Page
++  /Parent 2 0 R
++  /MediaBox [0 0 612 792]
++  /Annots [13 0 R]
++
++>>
++endobj
++{{object 34 0}} <<
++  /Type /Page
++  /Parent 2 0 R
++  /MediaBox [0 0 612 792]
++  /Annots [10 0 R]
++>>
++endobj
++% Document JS Action
++{{object 40 0}} <<
++  /Type /Action
++  /S /JavaScript
++  /JS 41 0 R
++>>
++endobj
++% JS program to exexute
++{{object 41 0}} <<
++>>
++stream
++var f5 = this.getField("MyField5");
++var f3 = this.getField("MyField3");
++f3.setFocus();
++this.__defineGetter__("pageNum",function o(){f5.setFocus(); f3.borderStyle="dashed"; f3.setFocus();});
++endstream
++endobj
++{{object 43 0}} <<
++  {{streamlen}}
++>>
++stream
++<?xml version="1.0" encoding="UTF-8"?>
++<xdp:xdp xmlns:xdp="http://ns.adobe.com/xdp/">
++<config></config>
++<template xmlns="http://www.xfa.org/schema/xfa-template/2.8/">
++  <subform layout="tb" locale="en_US">
++    <pageSet>
++      <pageArea id="Page1" name="Page1">
++        <contentArea h="268.939mm" w="203.2mm" x="6.35mm" y="6.35mm"/>
++        <medium long="792pt" short="612pt" stock="default"/>
++      </pageArea>
++    </pageSet>
++    <field h="9.0001mm" name="MyField3" w="47.625mm" x="120mm" y="120mm">
++      <ui>
++        <choiceList open="onEntry">
++          <border>
++            <edge/>
++          </border>
++        </choiceList>
++      </ui>
++      <items save="1">
++        <text>apples</text>
++        <text>bananas</text>
++        <text>pears</text>
++      </items>
++      <value>
++        <text>apples</text>
++      </value>
++      <event activity="preOpen">
++        <script contentType="application/x-javascript">
++            var aa = this.pageNum;
++        </script>
++      </event>
++    </field>
++  </subform>
++</template>
++</xdp:xdp>
++endstream
++endobj
++{{xref}}
++{{trailer}}
++{{startxref}}
++%%EOF

+ 213 - 0
patches/pdfium/m114_observe_cpwl_combobox_across_all_on_methods.patch

@@ -0,0 +1,213 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Tom Sepez <[email protected]>
+Date: Fri, 19 May 2023 20:05:10 +0000
+Subject: Observe CPWL_ComboBox across all On* methods
+
+Bug: chromium:1445426
+Change-Id: I1d7ebf66fe170ca016c27a0df3ac4574e75c763c
+Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/107650
+Reviewed-by: Lei Zhang <[email protected]>
+Commit-Queue: Tom Sepez <[email protected]>
+(cherry picked from commit 29c665ea4c61b089746c3f502c30fcb5f4b11486)
+Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/107811
+
+diff --git a/fpdfsdk/pwl/cpwl_combo_box.cpp b/fpdfsdk/pwl/cpwl_combo_box.cpp
+index dde76521a7c15070c1245938063830a003986a69..4cda2135433b07d641d773f184034b0f3dee7e58 100644
+--- a/fpdfsdk/pwl/cpwl_combo_box.cpp
++++ b/fpdfsdk/pwl/cpwl_combo_box.cpp
+@@ -339,31 +339,42 @@ bool CPWL_ComboBox::OnKeyDown(FWL_VKEYCODE nKeyCode,
+   if (!m_pEdit)
+     return false;
+ 
++  ObservedPtr<CPWL_Wnd> thisObserved(this);
+   m_nSelectItem = -1;
+ 
+   switch (nKeyCode) {
+     case FWL_VKEY_Up:
+       if (m_pList->GetCurSel() > 0) {
+-        if (GetFillerNotify()->OnPopupPreOpen(GetAttachedData(), nFlag))
++        if (GetFillerNotify()->OnPopupPreOpen(GetAttachedData(), nFlag) ||
++            !thisObserved) {
+           return false;
+-        if (GetFillerNotify()->OnPopupPostOpen(GetAttachedData(), nFlag))
++        }
++        if (GetFillerNotify()->OnPopupPostOpen(GetAttachedData(), nFlag) ||
++            !thisObserved) {
+           return false;
++        }
+         if (m_pList->IsMovementKey(nKeyCode)) {
+-          if (m_pList->OnMovementKeyDown(nKeyCode, nFlag))
++          if (m_pList->OnMovementKeyDown(nKeyCode, nFlag) || !thisObserved) {
+             return false;
++          }
+           SetSelectText();
+         }
+       }
+       return true;
+     case FWL_VKEY_Down:
+       if (m_pList->GetCurSel() < m_pList->GetCount() - 1) {
+-        if (GetFillerNotify()->OnPopupPreOpen(GetAttachedData(), nFlag))
++        if (GetFillerNotify()->OnPopupPreOpen(GetAttachedData(), nFlag) ||
++            !thisObserved) {
+           return false;
+-        if (GetFillerNotify()->OnPopupPostOpen(GetAttachedData(), nFlag))
++        }
++        if (GetFillerNotify()->OnPopupPostOpen(GetAttachedData(), nFlag) ||
++            !thisObserved) {
+           return false;
++        }
+         if (m_pList->IsMovementKey(nKeyCode)) {
+-          if (m_pList->OnMovementKeyDown(nKeyCode, nFlag))
++          if (m_pList->OnMovementKeyDown(nKeyCode, nFlag) || !thisObserved) {
+             return false;
++          }
+           SetSelectText();
+         }
+       }
+@@ -411,10 +422,15 @@ bool CPWL_ComboBox::OnChar(uint16_t nChar, Mask<FWL_EVENTFLAG> nFlag) {
+   if (HasFlag(PCBS_ALLOWCUSTOMTEXT))
+     return m_pEdit->OnChar(nChar, nFlag);
+ 
+-  if (GetFillerNotify()->OnPopupPreOpen(GetAttachedData(), nFlag))
++  ObservedPtr<CPWL_Wnd> thisObserved(this);
++  if (GetFillerNotify()->OnPopupPreOpen(GetAttachedData(), nFlag) ||
++      !thisObserved) {
+     return false;
+-  if (GetFillerNotify()->OnPopupPostOpen(GetAttachedData(), nFlag))
++  }
++  if (GetFillerNotify()->OnPopupPostOpen(GetAttachedData(), nFlag) ||
++      !thisObserved) {
+     return false;
++  }
+   if (!m_pList->IsChar(nChar, nFlag))
+     return false;
+   return m_pList->OnCharNotify(nChar, nFlag);
+diff --git a/testing/resources/javascript/bug_1445426.evt b/testing/resources/javascript/bug_1445426.evt
+new file mode 100644
+index 0000000000000000000000000000000000000000..265e85b0471b33509568238ccae30d2395b4b4ab
+--- /dev/null
++++ b/testing/resources/javascript/bug_1445426.evt
+@@ -0,0 +1,3 @@
++mousedown,left,202,697
++mouseup,left,202,697
++keycode,40
+diff --git a/testing/resources/javascript/bug_1445426.in b/testing/resources/javascript/bug_1445426.in
+new file mode 100644
+index 0000000000000000000000000000000000000000..1483da72f5759e9f2c8fdb538d5c6fa0cd1611c5
+--- /dev/null
++++ b/testing/resources/javascript/bug_1445426.in
+@@ -0,0 +1,114 @@
++{{header}}
++{{object 1 0}} <<
++  /Type /Catalog
++  /Pages 2 0 R
++  /AcroForm 4 0 R
++  /OpenAction 40 0 R
++>>
++endobj
++{{object 2 0}} <<
++  /Type /Pages
++  /Count 2
++  /Kids [
++    32 0 R
++    34 0 R
++  ]
++>>
++endobj
++% Forms
++{{object 4 0}} <<
++  /Fields [
++    10 0 R
++    11 0 R
++  ]
++>>
++endobj
++% Fields
++{{object 10 0}} <<
++  /Type /Annot
++  /Subtype /Widget
++  /FT /Tx
++  /T (Field_TextEdit)
++  /Rect [0 0 612 792]
++>>
++{{object 11 0}} <<
++  /T (Field_ComboBox)
++  /Parent 4 0 R
++  /Kids [12 0 R]
++  /Opt [(a) (b) (c) (d)]
++  /V [(a)]
++>>
++endobj
++{{object 12 0}} <<
++  /Type /Annot
++  /Subtype /Widget
++  /FT /Ch
++  /Ff 131072
++  /Parent 11 0 R
++  /Kids [13 0 R]
++>>
++endobj
++{{object 13 0}} <<
++  /Parent 12 0 R
++  /Type /Annot
++  /Subtype /Widget
++  /Rect [0 0 612 792]
++  /AA << /K 20 0 R >>
++>>
++endobj
++% Pages
++{{object 32 0}} <<
++  /Type /Page
++  /Parent 2 0 R
++  /MediaBox [0 0 612 792]
++  /Annots [13 0 R]
++
++>>
++endobj
++{{object 34 0}} <<
++  /Type /Page
++  /Parent 2 0 R
++  /MediaBox [0 0 612 792]
++  /Annots [10 0 R]
++>>
++endobj
++% Document JS Action
++{{object 40 0}} <<
++  /Type /Action
++  /S /JavaScript
++  /JS 41 0 R
++>>
++endobj
++% JS program to exexute
++{{object 41 0}} <<
++  {{streamlen}}
++>>
++stream
++var field_text = this.getField("Field_TextEdit");
++var field_combobox = this.getField("Field_ComboBox");
++field_combobox.setFocus();
++this.__defineGetter__("filesize", function new_getter(){
++                                    field_text.setFocus();
++                                    field_combobox.borderStyle="dashed";
++                                    field_combobox.setFocus();
++                                  });
++endstream
++endobj
++% OpenAction action
++{{object 20 0}} <<
++  /S /JavaScript
++  /JS 21 0 R
++>>
++endobj
++% JS program to exexute
++{{object 21 0}} <<
++  {{streamlen}}
++>>
++stream
++var t = this.filesize;
++endstream
++endobj
++{{xref}}
++{{trailer}}
++{{startxref}}
++%%EOF

+ 40 - 0
patches/pdfium/m114_observe_widget_across_setoptionselection_calls.patch

@@ -0,0 +1,40 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Tom Sepez <[email protected]>
+Date: Thu, 18 May 2023 18:37:17 +0000
+Subject: Observe widget across SetOptionSelection() calls.
+
+Call may re-enter JavaScript.
+
+Bug: chromium:1444581
+Change-Id: Id7a2f17b3b81f822ca8f4496ac08c19b7794c48a
+Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/107394
+Commit-Queue: Tom Sepez <[email protected]>
+Reviewed-by: Lei Zhang <[email protected]>
+(cherry picked from commit a9ff918a86d700c3bdf9b5820faed35490c0cd25)
+Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/107735
+Auto-Submit: Tom Sepez <[email protected]>
+
+diff --git a/fpdfsdk/formfiller/cffl_listbox.cpp b/fpdfsdk/formfiller/cffl_listbox.cpp
+index ea119ec093c748c6c8bfb7b3c31b4ae97f959908..31134bb1e576003cc377eb90a61898f8097f080c 100644
+--- a/fpdfsdk/formfiller/cffl_listbox.cpp
++++ b/fpdfsdk/formfiller/cffl_listbox.cpp
+@@ -116,11 +116,18 @@ void CFFL_ListBox::SaveData(const CPDFSDK_PageView* pPageView) {
+   }
+   if (m_pWidget->GetFieldFlags() & pdfium::form_flags::kChoiceMultiSelect) {
+     for (int32_t i = 0, sz = pListBox->GetCount(); i < sz; i++) {
+-      if (pListBox->IsItemSelected(i))
++      if (pListBox->IsItemSelected(i)) {
+         m_pWidget->SetOptionSelection(i);
++        if (!observed_box) {
++          return;
++        }
++      }
+     }
+   } else {
+     m_pWidget->SetOptionSelection(pListBox->GetCurSel());
++    if (!observed_box) {
++      return;
++    }
+   }
+   ObservedPtr<CPDFSDK_Widget> observed_widget(m_pWidget);
+   ObservedPtr<CFFL_ListBox> observed_this(this);

+ 2 - 0
patches/v8/.patches

@@ -12,3 +12,5 @@ cherry-pick-c605df24af3c.patch
 cherry-pick-f4b66ae451c2.patch
 merged_ic_fix_store_handler_selection_for_arguments_objects.patch
 cherry-pick-73af1a19a901.patch
+cherry-pick-3b0607d14060.patch
+cherry-pick-9c6dfc733fce.patch

+ 186 - 0
patches/v8/cherry-pick-3b0607d14060.patch

@@ -0,0 +1,186 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Igor Sheludko <[email protected]>
+Date: Wed, 17 May 2023 13:47:36 +0200
+Subject: Merged: [runtime] Remove redundant calls to GetPropertyAttributes
+
+... when defining properties in favour of CheckIfCanDefine.
+
+Drive-by: move JSReceiver::CheckIfCanDefine to
+JSObject::CheckIfCanDefineAsConfigurable and fix handling of
+absent properties.
+
+Bug: chromium:1443452
+(cherry picked from commit e98baa3526426c0219bb0474028ca301b8bd0677)
+
+Change-Id: Ia1fd617778be608accee99dcee37f7d1ce3460b8
+Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/4545762
+Commit-Queue: Igor Sheludko <[email protected]>
+Reviewed-by: Toon Verwaest <[email protected]>
+Cr-Commit-Position: refs/branch-heads/11.4@{#22}
+Cr-Branched-From: 8a8a1e7086dacc426965d3875914efa66663c431-refs/heads/11.4.183@{#1}
+Cr-Branched-From: 5483d8e816e0bbce865cbbc3fa0ab357e6330bab-refs/heads/main@{#87241}
+
+diff --git a/src/ic/ic.cc b/src/ic/ic.cc
+index 93939fa4702922f58e8e5bcc019e569f42ab198e..1190b3dedfabee414fb49038e31b3cf2bbce68ee 100644
+--- a/src/ic/ic.cc
++++ b/src/ic/ic.cc
+@@ -1816,14 +1816,14 @@ MaybeHandle<Object> StoreIC::Store(Handle<Object> object, Handle<Name> name,
+   // been thrown if the private field already exists in the object.
+   if (IsAnyDefineOwn() && !name->IsPrivateName() && !object->IsJSProxy() &&
+       !Handle<JSObject>::cast(object)->HasNamedInterceptor()) {
+-    Maybe<bool> can_define = JSReceiver::CheckIfCanDefine(
++    Maybe<bool> can_define = JSObject::CheckIfCanDefineAsConfigurable(
+         isolate(), &it, value, Nothing<ShouldThrow>());
+     MAYBE_RETURN_NULL(can_define);
+     if (!can_define.FromJust()) {
+       return isolate()->factory()->undefined_value();
+     }
+-    // Restart the lookup iterator updated by CheckIfCanDefine() for
+-    // UpdateCaches() to handle access checks.
++    // Restart the lookup iterator updated by CheckIfCanDefineAsConfigurable()
++    // for UpdateCaches() to handle access checks.
+     if (use_ic && object->IsAccessCheckNeeded()) {
+       it.Restart();
+     }
+diff --git a/src/objects/js-objects.cc b/src/objects/js-objects.cc
+index 59c9f966036fdd3640b06b2d6962fc9994ab3c31..3abfd10ee4ad64c67c490d3f9d24f8e6efe08a1f 100644
+--- a/src/objects/js-objects.cc
++++ b/src/objects/js-objects.cc
+@@ -243,27 +243,6 @@ Maybe<bool> JSReceiver::CheckPrivateNameStore(LookupIterator* it,
+   return Just(true);
+ }
+ 
+-// static
+-Maybe<bool> JSReceiver::CheckIfCanDefine(Isolate* isolate, LookupIterator* it,
+-                                         Handle<Object> value,
+-                                         Maybe<ShouldThrow> should_throw) {
+-  if (it->IsFound()) {
+-    Maybe<PropertyAttributes> attributes = GetPropertyAttributes(it);
+-    MAYBE_RETURN(attributes, Nothing<bool>());
+-    if ((attributes.FromJust() & DONT_DELETE) != 0) {
+-      RETURN_FAILURE(
+-          isolate, GetShouldThrow(isolate, should_throw),
+-          NewTypeError(MessageTemplate::kRedefineDisallowed, it->GetName()));
+-    }
+-  } else if (!JSObject::IsExtensible(
+-                 Handle<JSObject>::cast(it->GetReceiver()))) {
+-    RETURN_FAILURE(
+-        isolate, GetShouldThrow(isolate, should_throw),
+-        NewTypeError(MessageTemplate::kDefineDisallowed, it->GetName()));
+-  }
+-  return Just(true);
+-}
+-
+ namespace {
+ 
+ bool HasExcludedProperty(
+@@ -3642,7 +3621,7 @@ Maybe<bool> JSObject::DefineOwnPropertyIgnoreAttributes(
+ 
+         if (semantics == EnforceDefineSemantics::kDefine) {
+           it->Restart();
+-          Maybe<bool> can_define = JSReceiver::CheckIfCanDefine(
++          Maybe<bool> can_define = JSObject::CheckIfCanDefineAsConfigurable(
+               it->isolate(), it, value, should_throw);
+           if (can_define.IsNothing() || !can_define.FromJust()) {
+             return can_define;
+@@ -4071,17 +4050,16 @@ Maybe<bool> JSObject::CreateDataProperty(LookupIterator* it,
+                                          Handle<Object> value,
+                                          Maybe<ShouldThrow> should_throw) {
+   DCHECK(it->GetReceiver()->IsJSObject());
+-  MAYBE_RETURN(JSReceiver::GetPropertyAttributes(it), Nothing<bool>());
+   Handle<JSReceiver> receiver = Handle<JSReceiver>::cast(it->GetReceiver());
+   Isolate* isolate = receiver->GetIsolate();
+ 
+-  Maybe<bool> can_define =
+-      JSReceiver::CheckIfCanDefine(isolate, it, value, should_throw);
++  Maybe<bool> can_define = JSObject::CheckIfCanDefineAsConfigurable(
++      isolate, it, value, should_throw);
+   if (can_define.IsNothing() || !can_define.FromJust()) {
+     return can_define;
+   }
+ 
+-  RETURN_ON_EXCEPTION_VALUE(it->isolate(),
++  RETURN_ON_EXCEPTION_VALUE(isolate,
+                             DefineOwnPropertyIgnoreAttributes(it, value, NONE),
+                             Nothing<bool>());
+ 
+@@ -4710,19 +4688,42 @@ MaybeHandle<Object> JSObject::SetAccessor(Handle<JSObject> object,
+     return it.factory()->undefined_value();
+   }
+ 
+-  CHECK(GetPropertyAttributes(&it).IsJust());
+-
+-  // ES5 forbids turning a property into an accessor if it's not
+-  // configurable. See 8.6.1 (Table 5).
+-  if (it.IsFound() && !it.IsConfigurable()) {
+-    return it.factory()->undefined_value();
+-  }
++  Maybe<bool> can_define = JSObject::CheckIfCanDefineAsConfigurable(
++      isolate, &it, info, Nothing<ShouldThrow>());
++  MAYBE_RETURN_NULL(can_define);
++  if (!can_define.FromJust()) return it.factory()->undefined_value();
+ 
+   it.TransitionToAccessorPair(info, attributes);
+ 
+   return object;
+ }
+ 
++// static
++Maybe<bool> JSObject::CheckIfCanDefineAsConfigurable(
++    Isolate* isolate, LookupIterator* it, Handle<Object> value,
++    Maybe<ShouldThrow> should_throw) {
++  DCHECK(it->GetReceiver()->IsJSObject());
++  if (it->IsFound()) {
++    Maybe<PropertyAttributes> attributes = GetPropertyAttributes(it);
++    MAYBE_RETURN(attributes, Nothing<bool>());
++    if (attributes.FromJust() != ABSENT) {
++      if ((attributes.FromJust() & DONT_DELETE) != 0) {
++        RETURN_FAILURE(
++            isolate, GetShouldThrow(isolate, should_throw),
++            NewTypeError(MessageTemplate::kRedefineDisallowed, it->GetName()));
++      }
++      return Just(true);
++    }
++    // Property does not exist, check object extensibility.
++  }
++  if (!JSObject::IsExtensible(Handle<JSObject>::cast(it->GetReceiver()))) {
++    RETURN_FAILURE(
++        isolate, GetShouldThrow(isolate, should_throw),
++        NewTypeError(MessageTemplate::kDefineDisallowed, it->GetName()));
++  }
++  return Just(true);
++}
++
+ Object JSObject::SlowReverseLookup(Object value) {
+   if (HasFastProperties()) {
+     DescriptorArray descs = map().instance_descriptors();
+diff --git a/src/objects/js-objects.h b/src/objects/js-objects.h
+index 06489c2b7bae61ecadbd8f020060e86ef50e11b6..f663af6ed8a445f8ef30a67bac176a1abe6c85f8 100644
+--- a/src/objects/js-objects.h
++++ b/src/objects/js-objects.h
+@@ -167,12 +167,6 @@ class JSReceiver : public TorqueGeneratedJSReceiver<JSReceiver, HeapObject> {
+   V8_WARN_UNUSED_RESULT static Maybe<bool> CheckPrivateNameStore(
+       LookupIterator* it, bool is_define);
+ 
+-  // Check if a data property can be created on the object. It will fail with
+-  // an error when it cannot.
+-  V8_WARN_UNUSED_RESULT static Maybe<bool> CheckIfCanDefine(
+-      Isolate* isolate, LookupIterator* it, Handle<Object> value,
+-      Maybe<ShouldThrow> should_throw);
+-
+   // ES6 7.3.4 (when passed kDontThrow)
+   V8_WARN_UNUSED_RESULT static Maybe<bool> CreateDataProperty(
+       Isolate* isolate, Handle<JSReceiver> object, Handle<Name> key,
+@@ -544,6 +538,12 @@ class JSObject : public TorqueGeneratedJSObject<JSObject, JSReceiver> {
+       Handle<JSObject> object, Handle<Name> name, Handle<AccessorInfo> info,
+       PropertyAttributes attributes);
+ 
++  // Check if a data property can be created on the object. It will fail with
++  // an error when it cannot.
++  V8_WARN_UNUSED_RESULT static Maybe<bool> CheckIfCanDefineAsConfigurable(
++      Isolate* isolate, LookupIterator* it, Handle<Object> value,
++      Maybe<ShouldThrow> should_throw);
++
+   // The result must be checked first for exceptions. If there's no exception,
+   // the output parameter |done| indicates whether the interceptor has a result
+   // or not.

+ 150 - 0
patches/v8/cherry-pick-9c6dfc733fce.patch

@@ -0,0 +1,150 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Igor Sheludko <[email protected]>
+Date: Tue, 16 May 2023 16:01:49 +0200
+Subject: Merged: [runtime] Fix handling of interceptors
+
+Drive-by: simplify creation of LookupIterator copies.
+
+Bug: chromium:1440695
+(cherry picked from commit d125c7329f6e22af4523de3c55de3a22f168acc9)
+
+Change-Id: I58416531b9af3456f53264566ec1eb7457328f94
+Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/4545763
+Reviewed-by: Toon Verwaest <[email protected]>
+Commit-Queue: Igor Sheludko <[email protected]>
+Cr-Commit-Position: refs/branch-heads/11.4@{#23}
+Cr-Branched-From: 8a8a1e7086dacc426965d3875914efa66663c431-refs/heads/11.4.183@{#1}
+Cr-Branched-From: 5483d8e816e0bbce865cbbc3fa0ab357e6330bab-refs/heads/main@{#87241}
+
+diff --git a/src/objects/js-objects.cc b/src/objects/js-objects.cc
+index 3abfd10ee4ad64c67c490d3f9d24f8e6efe08a1f..4046b3d1d1e4a36a15c7f0e859c4e51cd29185e4 100644
+--- a/src/objects/js-objects.cc
++++ b/src/objects/js-objects.cc
+@@ -3632,10 +3632,8 @@ Maybe<bool> JSObject::DefineOwnPropertyIgnoreAttributes(
+         // 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);
++        LookupIterator own_lookup(isolate, receiver, it->GetKey(),
++                                  LookupIterator::OWN_SKIP_INTERCEPTOR);
+         return JSObject::DefineOwnPropertyIgnoreAttributes(
+             &own_lookup, value, attributes, should_throw, handling, semantics,
+             store_origin);
+diff --git a/src/objects/lookup-inl.h b/src/objects/lookup-inl.h
+index 782698bd7c488f5570288119e49784e16a93ddd2..35eaed8ffbc23248c33230868f428bc192c5b790 100644
+--- a/src/objects/lookup-inl.h
++++ b/src/objects/lookup-inl.h
+@@ -130,6 +130,29 @@ PropertyKey::PropertyKey(Isolate* isolate, double index) {
+ #endif
+ }
+ 
++PropertyKey::PropertyKey(Isolate* isolate, Handle<Name> name, size_t index)
++    : name_(name), index_(index) {
++  DCHECK_IMPLIES(index_ == LookupIterator::kInvalidIndex, !name_.is_null());
++#if V8_TARGET_ARCH_32_BIT
++  DCHECK_IMPLIES(index_ != LookupIterator::kInvalidIndex,
++                 index_ <= JSObject::kMaxElementIndex);
++#endif
++#if DEBUG
++  if (index_ != LookupIterator::kInvalidIndex && !name_.is_null()) {
++    // If both valid index and name are given then the name is a string
++    // representation of the same index.
++    size_t integer_index;
++    CHECK(name_->AsIntegerIndex(&integer_index));
++    CHECK_EQ(index_, integer_index);
++  } else if (index_ == LookupIterator::kInvalidIndex) {
++    // If only name is given it must not be a string representing an integer
++    // index.
++    size_t integer_index;
++    CHECK(!name_->AsIntegerIndex(&integer_index));
++  }
++#endif
++}
++
+ PropertyKey::PropertyKey(Isolate* isolate, Handle<Name> name) {
+   if (name->AsIntegerIndex(&index_)) {
+     name_ = name;
+@@ -179,6 +202,10 @@ Handle<Name> LookupIterator::GetName() {
+   return name_;
+ }
+ 
++PropertyKey LookupIterator::GetKey() const {
++  return PropertyKey(isolate_, name_, index_);
++}
++
+ bool LookupIterator::IsElement(JSReceiver object) const {
+   return index_ <= JSObject::kMaxElementIndex ||
+          (index_ != kInvalidIndex &&
+diff --git a/src/objects/lookup.h b/src/objects/lookup.h
+index ef90316295c98d51b61c118cf331731f991d93d0..5d2d926b7e3dcecf8529f7d1c1e919033d9faa7f 100644
+--- a/src/objects/lookup.h
++++ b/src/objects/lookup.h
+@@ -36,6 +36,11 @@ class PropertyKey {
+   inline Handle<Name> GetName(Isolate* isolate);
+ 
+  private:
++  friend LookupIterator;
++
++  // Shortcut for constructing PropertyKey from an active LookupIterator.
++  inline PropertyKey(Isolate* isolate, Handle<Name> name, size_t index);
++
+   Handle<Name> name_;
+   size_t index_;
+ };
+@@ -108,6 +113,9 @@ class V8_EXPORT_PRIVATE LookupIterator final {
+     return static_cast<uint32_t>(index_);
+   }
+ 
++  // Helper method for creating a copy of of the iterator.
++  inline PropertyKey GetKey() const;
++
+   // Returns true if this LookupIterator has an index in the range
+   // [0, size_t::max).
+   bool IsElement() const { return index_ != kInvalidIndex; }
+diff --git a/src/objects/objects.cc b/src/objects/objects.cc
+index 01d826c43bf9ec8bb28aba0e59fd3fa8f5700bac..b57c68073e401bb34796689013213791d40af10a 100644
+--- a/src/objects/objects.cc
++++ b/src/objects/objects.cc
+@@ -2668,11 +2668,8 @@ Maybe<bool> Object::SetSuperProperty(LookupIterator* it, Handle<Object> value,
+ 
+   // Note, the callers rely on the fact that this code is redoing the full own
+   // lookup from scratch.
+-  LookupIterator::Configuration c = LookupIterator::OWN;
+-  LookupIterator own_lookup =
+-      it->IsElement() ? LookupIterator(isolate, receiver, it->index(), c)
+-                      : LookupIterator(isolate, receiver, it->name(), c);
+-
++  LookupIterator own_lookup(isolate, receiver, it->GetKey(),
++                            LookupIterator::OWN);
+   for (; own_lookup.IsFound(); own_lookup.Next()) {
+     switch (own_lookup.state()) {
+       case LookupIterator::ACCESS_CHECK:
+@@ -2709,6 +2706,8 @@ Maybe<bool> Object::SetSuperProperty(LookupIterator* it, Handle<Object> value,
+             JSReceiver::GetOwnPropertyDescriptor(&own_lookup, &desc);
+         MAYBE_RETURN(owned, Nothing<bool>());
+         if (!owned.FromJust()) {
++          // |own_lookup| might become outdated at this point anyway.
++          own_lookup.Restart();
+           if (!CheckContextualStoreToJSGlobalObject(&own_lookup,
+                                                     should_throw)) {
+             return Nothing<bool>();
+diff --git a/test/unittests/api/interceptor-unittest.cc b/test/unittests/api/interceptor-unittest.cc
+index 635bf6a0b72f8d49591be333b1314846c9c47269..416f9bd1eb4c59160eb03031e6011ae02dcf021e 100644
+--- a/test/unittests/api/interceptor-unittest.cc
++++ b/test/unittests/api/interceptor-unittest.cc
+@@ -174,8 +174,10 @@ TEST_F(InterceptorLoggingTest, DispatchTest) {
+   EXPECT_EQ(Run("obj.foo"), "named getter");
+   EXPECT_EQ(Run("obj[42]"), "indexed getter");
+ 
+-  EXPECT_EQ(Run("obj.foo = null"), "named setter, named descriptor");
+-  EXPECT_EQ(Run("obj[42] = null"), "indexed setter, indexed descriptor");
++  EXPECT_EQ(Run("obj.foo = null"),
++            "named setter, named descriptor, named query");
++  EXPECT_EQ(Run("obj[42] = null"),
++            "indexed setter, indexed descriptor, indexed query");
+ 
+   EXPECT_EQ(Run("Object.getOwnPropertyDescriptor(obj, 'foo')"),
+             "named descriptor");