From e9389e0b170151ba5cdcc8c7951f28621e43fff2 Mon Sep 17 00:00:00 2001
From: Brandon Dail <Kierkegaurd@gmail.com>
Date: Sun, 24 Dec 2017 20:07:44 -0800
Subject: [PATCH 1/3] Trap click events for portal root

---
 packages/react-dom/src/client/ReactDOM.js               | 1 +
 packages/react-dom/src/client/ReactDOMFiberComponent.js | 2 +-
 2 files changed, 2 insertions(+), 1 deletion(-)

diff --git a/packages/react-dom/src/client/ReactDOM.js b/packages/react-dom/src/client/ReactDOM.js
index ea887f774c154..fb426f1839aed 100644
--- a/packages/react-dom/src/client/ReactDOM.js
+++ b/packages/react-dom/src/client/ReactDOM.js
@@ -577,6 +577,7 @@ function createPortal(
     isValidContainer(container),
     'Target container is not a DOM element.',
   );
+  ReactDOMFiberComponent.trapClickOnNonInteractiveElement(((container: any): HTMLElement));
   // TODO: pass ReactDOM portal implementation as third argument
   return ReactPortal.createPortal(children, container, null, key);
 }
diff --git a/packages/react-dom/src/client/ReactDOMFiberComponent.js b/packages/react-dom/src/client/ReactDOMFiberComponent.js
index a0f9bf40366cc..11bba1a1085c4 100644
--- a/packages/react-dom/src/client/ReactDOMFiberComponent.js
+++ b/packages/react-dom/src/client/ReactDOMFiberComponent.js
@@ -228,7 +228,7 @@ function getOwnerDocumentFromRootContainer(
 
 function noop() {}
 
-function trapClickOnNonInteractiveElement(node: HTMLElement) {
+export function trapClickOnNonInteractiveElement(node: HTMLElement) {
   // Mobile Safari does not fire properly bubble click events on
   // non-interactive elements, which means delegated click listeners do not
   // fire. The workaround for this bug involves attaching an empty click

From 11687a313f4361dbe2c23e434b4a07a8c945f0b6 Mon Sep 17 00:00:00 2001
From: Brandon Dail <Kierkegaurd@gmail.com>
Date: Fri, 5 Jan 2018 14:54:30 -0800
Subject: [PATCH 2/3] Trap click event on container in appendChildToContainer

---
 packages/react-dom/src/client/ReactDOM.js           | 1 -
 packages/react-dom/src/client/ReactDOMHostConfig.js | 5 +++++
 2 files changed, 5 insertions(+), 1 deletion(-)

diff --git a/packages/react-dom/src/client/ReactDOM.js b/packages/react-dom/src/client/ReactDOM.js
index fb426f1839aed..ea887f774c154 100644
--- a/packages/react-dom/src/client/ReactDOM.js
+++ b/packages/react-dom/src/client/ReactDOM.js
@@ -577,7 +577,6 @@ function createPortal(
     isValidContainer(container),
     'Target container is not a DOM element.',
   );
-  ReactDOMFiberComponent.trapClickOnNonInteractiveElement(((container: any): HTMLElement));
   // TODO: pass ReactDOM portal implementation as third argument
   return ReactPortal.createPortal(children, container, null, key);
 }
diff --git a/packages/react-dom/src/client/ReactDOMHostConfig.js b/packages/react-dom/src/client/ReactDOMHostConfig.js
index 8da30eacc43b6..3d3bd6d0fcff5 100644
--- a/packages/react-dom/src/client/ReactDOMHostConfig.js
+++ b/packages/react-dom/src/client/ReactDOMHostConfig.js
@@ -16,6 +16,7 @@ import {
   updateProperties,
   diffHydratedProperties,
   diffHydratedText,
+  trapClickOnNonInteractiveElement,
   warnForUnmatchedText,
   warnForDeletedHydratableElement,
   warnForDeletedHydratableText,
@@ -345,7 +346,11 @@ export function appendChildToContainer(
 ): void {
   if (container.nodeType === COMMENT_NODE) {
     (container.parentNode: any).insertBefore(child, container);
+    trapClickOnNonInteractiveElement(
+      ((container.parentNode: any): HTMLElement),
+    );
   } else {
+    trapClickOnNonInteractiveElement(((container: any): HTMLElement));
     container.appendChild(child);
   }
 }

From 4893ae2781d036dd9d22e81457846ce7a1ef4d56 Mon Sep 17 00:00:00 2001
From: Dan Abramov <dan.abramov@gmail.com>
Date: Sat, 18 Aug 2018 02:05:24 +0100
Subject: [PATCH 3/3] Add a comment

---
 .../src/client/ReactDOMHostConfig.js          | 22 ++++++++++++++-----
 1 file changed, 16 insertions(+), 6 deletions(-)

diff --git a/packages/react-dom/src/client/ReactDOMHostConfig.js b/packages/react-dom/src/client/ReactDOMHostConfig.js
index 3d3bd6d0fcff5..e288b6554db21 100644
--- a/packages/react-dom/src/client/ReactDOMHostConfig.js
+++ b/packages/react-dom/src/client/ReactDOMHostConfig.js
@@ -344,14 +344,24 @@ export function appendChildToContainer(
   container: Container,
   child: Instance | TextInstance,
 ): void {
+  let parentNode;
   if (container.nodeType === COMMENT_NODE) {
-    (container.parentNode: any).insertBefore(child, container);
-    trapClickOnNonInteractiveElement(
-      ((container.parentNode: any): HTMLElement),
-    );
+    parentNode = (container.parentNode: any);
+    parentNode.insertBefore(child, container);
   } else {
-    trapClickOnNonInteractiveElement(((container: any): HTMLElement));
-    container.appendChild(child);
+    parentNode = container;
+    parentNode.appendChild(child);
+  }
+  // This container might be used for a portal.
+  // If something inside a portal is clicked, that click should bubble
+  // through the React tree. However, on Mobile Safari the click would
+  // never bubble through the *DOM* tree unless an ancestor with onclick
+  // event exists. So we wouldn't see it and dispatch it.
+  // This is why we ensure that containers have inline onclick defined.
+  // https://github.com/facebook/react/issues/11918
+  if (parentNode.onclick === null) {
+    // TODO: This cast may not be sound for SVG, MathML or custom elements.
+    trapClickOnNonInteractiveElement(((parentNode: any): HTMLElement));
   }
 }