From afba3fcd104eba54fc558eba22defc8b14798ed3 Mon Sep 17 00:00:00 2001
From: Joe Haddad <timer150@gmail.com>
Date: Thu, 11 May 2017 13:57:15 -0400
Subject: [PATCH 01/21] Browser sort is not stable

---
 .../react-error-overlay/src/utils/unmapper.js | 41 ++++++++++---------
 1 file changed, 21 insertions(+), 20 deletions(-)

diff --git a/packages/react-error-overlay/src/utils/unmapper.js b/packages/react-error-overlay/src/utils/unmapper.js
index 415d18dc1..a251d20a6 100644
--- a/packages/react-error-overlay/src/utils/unmapper.js
+++ b/packages/react-error-overlay/src/utils/unmapper.js
@@ -4,6 +4,12 @@ import { getSourceMap } from './getSourceMap';
 import { getLinesAround } from './getLinesAround';
 import path from 'path';
 
+function count(search: string, string: string): number {
+  let count = -1, index = 0;
+  for (; index !== -1; count++, (index = string.indexOf(search, index + 1)));
+  return count;
+}
+
 /**
  * Turns a set of mapped <code>StackFrame</code>s back into their generated code position and enhances them with code.
  * @param {string} fileUri The URI of the <code>bundle.js</code> file.
@@ -39,28 +45,22 @@ async function unmap(
       return frame;
     }
     const fN: string = fileName;
-    const splitCache1: any = {}, splitCache2: any = {}, splitCache3: any = {};
     const source = map
       .getSources()
-      .map(s => s.replace(/[\\]+/g, '/'))
-      .filter(s => {
-        s = path.normalize(s);
-        return s.indexOf(fN) === s.length - fN.length;
-      })
-      .sort((a, b) => {
-        let a2 = splitCache1[a] || (splitCache1[a] = a.split(path.sep)),
-          b2 = splitCache1[b] || (splitCache1[b] = b.split(path.sep));
-        return Math.sign(a2.length - b2.length);
-      })
-      .sort((a, b) => {
-        let a2 = splitCache2[a] || (splitCache2[a] = a.split('node_modules')),
-          b2 = splitCache2[b] || (splitCache2[b] = b.split('node_modules'));
-        return Math.sign(a2.length - b2.length);
+      .map(s => path.normalize(s.replace(/[\\]+/g, '/')))
+      .filter(p => {
+        const i = p.lastIndexOf(fN);
+        return i !== -1 && i === p.length - fN.length;
       })
+      .map(p => ({
+        token: p,
+        seps: count(path.sep, p),
+        penalties: count('node_modules', p) + count('~', p),
+      }))
       .sort((a, b) => {
-        let a2 = splitCache3[a] || (splitCache3[a] = a.split('~')),
-          b2 = splitCache3[b] || (splitCache3[b] = b.split('~'));
-        return Math.sign(a2.length - b2.length);
+        const s = Math.sign(a.seps - b.seps);
+        if (s !== 0) return s;
+        return Math.sign(a.penalties - b.penalties);
       });
     if (source.length < 1 || lineNumber == null) {
       return new StackFrame(
@@ -76,13 +76,14 @@ async function unmap(
         null
       );
     }
+    const sourceT = source[0].token;
     const { line, column } = map.getGeneratedPosition(
-      source[0],
+      sourceT,
       lineNumber,
       // $FlowFixMe
       columnNumber
     );
-    const originalSource = map.getSource(source[0]);
+    const originalSource = map.getSource(sourceT);
     return new StackFrame(
       functionName,
       fileUri,
-- 
GitLab


From 47cd783be74cb6e378186a1adcbd58e1834d56f3 Mon Sep 17 00:00:00 2001
From: Joe Haddad <timer150@gmail.com>
Date: Thu, 11 May 2017 14:02:03 -0400
Subject: [PATCH 02/21] Fix ordering of final message

---
 packages/react-error-overlay/src/components/overlay.js | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/packages/react-error-overlay/src/components/overlay.js b/packages/react-error-overlay/src/components/overlay.js
index 1a337d2f5..3acd5b34c 100644
--- a/packages/react-error-overlay/src/components/overlay.js
+++ b/packages/react-error-overlay/src/components/overlay.js
@@ -52,7 +52,7 @@ function createOverlay(
   applyStyles(header, headerStyle);
 
   // Make message prettier
-  let finalMessage = message.match(/^\w*:/) ? name + ': ' + message : message;
+  let finalMessage = message.match(/^\w*:/) ? message : name + ': ' + message;
   finalMessage = finalMessage
     // TODO: maybe remove this prefix from fbjs?
     // It's just scaring people
-- 
GitLab


From cf897f0d02cba190e904acbef2d7f60d589cc6d1 Mon Sep 17 00:00:00 2001
From: Joe Haddad <timer150@gmail.com>
Date: Thu, 11 May 2017 14:08:51 -0400
Subject: [PATCH 03/21] Register the warning capture

---
 packages/react-error-overlay/src/overlay.js | 23 +++++++++++++++++++++
 1 file changed, 23 insertions(+)

diff --git a/packages/react-error-overlay/src/overlay.js b/packages/react-error-overlay/src/overlay.js
index 63c919409..d65b1313b 100644
--- a/packages/react-error-overlay/src/overlay.js
+++ b/packages/react-error-overlay/src/overlay.js
@@ -19,6 +19,9 @@ import {
   register as registerStackTraceLimit,
   unregister as unregisterStackTraceLimit,
 } from './effects/stackTraceLimit';
+import {
+  permanentRegister as permanentRegisterConsole,
+} from './effects/proxyConsole';
 
 import {
   consume as consumeError,
@@ -205,6 +208,26 @@ function inject() {
   registerPromise(window, error => crash(error, true));
   registerShortcuts(window, shortcutHandler);
   registerStackTraceLimit();
+
+  permanentRegisterConsole('error', warning => {
+    const nIndex = warning.indexOf('\n');
+    let message = warning;
+    if (nIndex !== -1) {
+      message = message.substring(0, nIndex);
+    }
+    const stack = warning.substring(nIndex + 1);
+    window.requestAnimationFrame(function() {
+      return crash(
+        // $FlowFixMe
+        {
+          message: message,
+          stack: stack,
+          __unmap_source: '/static/js/bundle.js',
+        },
+        false
+      );
+    });
+  });
 }
 
 function uninject() {
-- 
GitLab


From a150609f82721c0dcab602abc3fa5a14f40ce577 Mon Sep 17 00:00:00 2001
From: Joe Haddad <timer150@gmail.com>
Date: Thu, 11 May 2017 14:50:24 -0400
Subject: [PATCH 04/21] Display only createElement warnings

---
 packages/react-error-overlay/src/overlay.js   | 29 ++++++-------
 .../react-error-overlay/src/utils/warnings.js | 43 +++++++++++++++++++
 2 files changed, 55 insertions(+), 17 deletions(-)
 create mode 100644 packages/react-error-overlay/src/utils/warnings.js

diff --git a/packages/react-error-overlay/src/overlay.js b/packages/react-error-overlay/src/overlay.js
index d65b1313b..4c1d1f481 100644
--- a/packages/react-error-overlay/src/overlay.js
+++ b/packages/react-error-overlay/src/overlay.js
@@ -22,6 +22,7 @@ import {
 import {
   permanentRegister as permanentRegisterConsole,
 } from './effects/proxyConsole';
+import { massage as massageWarning } from './utils/warnings';
 
 import {
   consume as consumeError,
@@ -210,23 +211,17 @@ function inject() {
   registerStackTraceLimit();
 
   permanentRegisterConsole('error', warning => {
-    const nIndex = warning.indexOf('\n');
-    let message = warning;
-    if (nIndex !== -1) {
-      message = message.substring(0, nIndex);
-    }
-    const stack = warning.substring(nIndex + 1);
-    window.requestAnimationFrame(function() {
-      return crash(
-        // $FlowFixMe
-        {
-          message: message,
-          stack: stack,
-          __unmap_source: '/static/js/bundle.js',
-        },
-        false
-      );
-    });
+    const data = massageWarning(warning);
+    if (data == null) return;
+    crash(
+      // $FlowFixMe
+      {
+        message: data.message,
+        stack: data.stack,
+        __unmap_source: '/static/js/bundle.js',
+      },
+      false
+    );
   });
 }
 
diff --git a/packages/react-error-overlay/src/utils/warnings.js b/packages/react-error-overlay/src/utils/warnings.js
new file mode 100644
index 000000000..d64b3d34d
--- /dev/null
+++ b/packages/react-error-overlay/src/utils/warnings.js
@@ -0,0 +1,43 @@
+// @flow
+
+// This is a list of React warnings to display
+// There must be zero or one capture group; and the capture group is assumed to be a missing stack frame.
+const warnings = [
+  /^.*React.createElement: type is invalid.+Check your code at (.*?:.*)[.]$/,
+];
+// This is a list of information to remove from React warnings, it's not particularly useful to show
+const removals = [/Check your code at (.*?:.*)[.]/];
+
+function massage(warning: string): { message: string, stack: string } | null {
+  const nIndex = warning.indexOf('\n');
+  let message = warning;
+  if (nIndex !== -1) {
+    message = message.substring(0, nIndex);
+  }
+  let stack = warning.substring(nIndex + 1);
+
+  let found = false;
+  for (const warning of warnings) {
+    const m = message.match(warning);
+    if (!m) {
+      continue;
+    }
+    found = true;
+    if (!m[1]) {
+      break;
+    }
+    stack = `in render (at ${m[1]})\n${stack}`;
+    break;
+  }
+  if (!found) {
+    return null;
+  }
+
+  for (const trim of removals) {
+    message = message.replace(trim, '');
+  }
+
+  return { message, stack };
+}
+
+export { massage };
-- 
GitLab


From 8dfb007b47599530282562bea1ec74c906fac20f Mon Sep 17 00:00:00 2001
From: Joe Haddad <timer150@gmail.com>
Date: Thu, 11 May 2017 14:53:32 -0400
Subject: [PATCH 05/21] Use different method name

---
 packages/react-error-overlay/src/utils/warnings.js | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/packages/react-error-overlay/src/utils/warnings.js b/packages/react-error-overlay/src/utils/warnings.js
index d64b3d34d..28d66e994 100644
--- a/packages/react-error-overlay/src/utils/warnings.js
+++ b/packages/react-error-overlay/src/utils/warnings.js
@@ -26,7 +26,7 @@ function massage(warning: string): { message: string, stack: string } | null {
     if (!m[1]) {
       break;
     }
-    stack = `in render (at ${m[1]})\n${stack}`;
+    stack = `in (render function) (at ${m[1]})\n${stack}`;
     break;
   }
   if (!found) {
-- 
GitLab


From 4bae90da63e7b5e5968a60898a0c57bbf4b6f1ad Mon Sep 17 00:00:00 2001
From: Joe Haddad <timer150@gmail.com>
Date: Thu, 11 May 2017 15:00:22 -0400
Subject: [PATCH 06/21] Fix regression

---
 packages/react-error-overlay/src/utils/unmapper.js | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/packages/react-error-overlay/src/utils/unmapper.js b/packages/react-error-overlay/src/utils/unmapper.js
index a251d20a6..628383f71 100644
--- a/packages/react-error-overlay/src/utils/unmapper.js
+++ b/packages/react-error-overlay/src/utils/unmapper.js
@@ -47,14 +47,15 @@ async function unmap(
     const fN: string = fileName;
     const source = map
       .getSources()
-      .map(s => path.normalize(s.replace(/[\\]+/g, '/')))
+      .map(s => s.replace(/[\\]+/g, '/'))
       .filter(p => {
+        p = path.normalize(p);
         const i = p.lastIndexOf(fN);
         return i !== -1 && i === p.length - fN.length;
       })
       .map(p => ({
         token: p,
-        seps: count(path.sep, p),
+        seps: count(path.sep, path.normalize(p)),
         penalties: count('node_modules', p) + count('~', p),
       }))
       .sort((a, b) => {
-- 
GitLab


From ab812623bbf91efefe09d8f73cb26b2cdfbb8ffb Mon Sep 17 00:00:00 2001
From: Joe Haddad <timer150@gmail.com>
Date: Thu, 11 May 2017 15:15:07 -0400
Subject: [PATCH 07/21] Ignore errors with only node_module files

---
 packages/react-error-overlay/src/overlay.js             | 4 ++++
 packages/react-error-overlay/src/utils/errorRegister.js | 9 ++++++++-
 2 files changed, 12 insertions(+), 1 deletion(-)

diff --git a/packages/react-error-overlay/src/overlay.js b/packages/react-error-overlay/src/overlay.js
index 4c1d1f481..8edefef1c 100644
--- a/packages/react-error-overlay/src/overlay.js
+++ b/packages/react-error-overlay/src/overlay.js
@@ -160,6 +160,10 @@ function crash(error: Error, unhandledRejection = false) {
   }
   consumeError(error, unhandledRejection, CONTEXT_SIZE)
     .then(ref => {
+      if (ref == null) {
+        console.warn('react-error-overlay ignored:', error);
+        return;
+      }
       errorReferences.push(ref);
       if (iframeReference !== null && additionalReference !== null) {
         updateAdditional(
diff --git a/packages/react-error-overlay/src/utils/errorRegister.js b/packages/react-error-overlay/src/utils/errorRegister.js
index f14ff9d92..769d9f755 100644
--- a/packages/react-error-overlay/src/utils/errorRegister.js
+++ b/packages/react-error-overlay/src/utils/errorRegister.js
@@ -19,7 +19,7 @@ function consume(
   error: Error,
   unhandledRejection: boolean = false,
   contextSize: number = 3
-): Promise<ErrorRecordReference> {
+): Promise<ErrorRecordReference | null> {
   const parsedFrames = parse(error);
   let enhancedFramesPromise;
   if (error.__unmap_source) {
@@ -33,6 +33,13 @@ function consume(
     enhancedFramesPromise = map(parsedFrames, contextSize);
   }
   return enhancedFramesPromise.then(enhancedFrames => {
+    if (
+      enhancedFrames
+        .map(f => f._originalFileName)
+        .filter(f => f == null || f.indexOf('node_modules') === -1).length === 0
+    ) {
+      return null;
+    }
     enhancedFrames = enhancedFrames.filter(
       ({ functionName }) =>
         functionName == null ||
-- 
GitLab


From 79af0fc56162179cd58fa227d3d1d018f4c40e37 Mon Sep 17 00:00:00 2001
From: Joe Haddad <timer150@gmail.com>
Date: Thu, 11 May 2017 15:15:46 -0400
Subject: [PATCH 08/21] Ignore null files, too

---
 packages/react-error-overlay/src/utils/errorRegister.js | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/packages/react-error-overlay/src/utils/errorRegister.js b/packages/react-error-overlay/src/utils/errorRegister.js
index 769d9f755..3fc1ab6b9 100644
--- a/packages/react-error-overlay/src/utils/errorRegister.js
+++ b/packages/react-error-overlay/src/utils/errorRegister.js
@@ -36,7 +36,7 @@ function consume(
     if (
       enhancedFrames
         .map(f => f._originalFileName)
-        .filter(f => f == null || f.indexOf('node_modules') === -1).length === 0
+        .filter(f => f != null && f.indexOf('node_modules') === -1).length === 0
     ) {
       return null;
     }
-- 
GitLab


From ec12b8cf7e873c50f1d8896a62aad46d109cf177 Mon Sep 17 00:00:00 2001
From: Joe Haddad <timer150@gmail.com>
Date: Fri, 12 May 2017 16:58:37 -0400
Subject: [PATCH 09/21] Revise count

---
 packages/react-error-overlay/src/utils/unmapper.js | 11 +++++++++--
 1 file changed, 9 insertions(+), 2 deletions(-)

diff --git a/packages/react-error-overlay/src/utils/unmapper.js b/packages/react-error-overlay/src/utils/unmapper.js
index 628383f71..bf6e5917d 100644
--- a/packages/react-error-overlay/src/utils/unmapper.js
+++ b/packages/react-error-overlay/src/utils/unmapper.js
@@ -5,8 +5,15 @@ import { getLinesAround } from './getLinesAround';
 import path from 'path';
 
 function count(search: string, string: string): number {
-  let count = -1, index = 0;
-  for (; index !== -1; count++, (index = string.indexOf(search, index + 1)));
+  // Count starts at -1 becuse a do-while loop always runs at least once
+  let count = -1, index = -1;
+  do {
+    // First call or the while case evaluated true, meaning we have to make
+    // count 0 or we found a character
+    ++count;
+    // Find the index of our search string, starting after the previous index
+    index = string.indexOf(search, index + 1);
+  } while (index !== -1);
   return count;
 }
 
-- 
GitLab


From fb7411b03cc7eaba835206bf84e3bc29a3d8b8c4 Mon Sep 17 00:00:00 2001
From: Joe Haddad <timer150@gmail.com>
Date: Fri, 12 May 2017 16:58:43 -0400
Subject: [PATCH 10/21] Revise warning

---
 packages/react-error-overlay/src/overlay.js | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/packages/react-error-overlay/src/overlay.js b/packages/react-error-overlay/src/overlay.js
index 8edefef1c..43d9e2d51 100644
--- a/packages/react-error-overlay/src/overlay.js
+++ b/packages/react-error-overlay/src/overlay.js
@@ -161,7 +161,11 @@ function crash(error: Error, unhandledRejection = false) {
   consumeError(error, unhandledRejection, CONTEXT_SIZE)
     .then(ref => {
       if (ref == null) {
-        console.warn('react-error-overlay ignored:', error);
+        console.warn(
+          `react-error-overlay could not deduce if the previous error was from your code. Since we can't display anything useful, we're giving you this warning instead.
+This error is most likely a bug with the package you see in the stack trace, however, it may be caused indirectly by something you are calling within the package.
+Try searching or opening an issue with the relevant package.`
+        );
         return;
       }
       errorReferences.push(ref);
-- 
GitLab


From cd9c43f06b37bb232df17c44f3412676e520cb07 Mon Sep 17 00:00:00 2001
From: Joe Haddad <timer150@gmail.com>
Date: Fri, 12 May 2017 19:20:29 -0400
Subject: [PATCH 11/21] Update overlay.js

---
 packages/react-error-overlay/src/overlay.js | 5 -----
 1 file changed, 5 deletions(-)

diff --git a/packages/react-error-overlay/src/overlay.js b/packages/react-error-overlay/src/overlay.js
index 43d9e2d51..7c3ebb536 100644
--- a/packages/react-error-overlay/src/overlay.js
+++ b/packages/react-error-overlay/src/overlay.js
@@ -161,11 +161,6 @@ function crash(error: Error, unhandledRejection = false) {
   consumeError(error, unhandledRejection, CONTEXT_SIZE)
     .then(ref => {
       if (ref == null) {
-        console.warn(
-          `react-error-overlay could not deduce if the previous error was from your code. Since we can't display anything useful, we're giving you this warning instead.
-This error is most likely a bug with the package you see in the stack trace, however, it may be caused indirectly by something you are calling within the package.
-Try searching or opening an issue with the relevant package.`
-        );
         return;
       }
       errorReferences.push(ref);
-- 
GitLab


From 83e63242511dd64a11b47a9fce4f7937cf4962f7 Mon Sep 17 00:00:00 2001
From: Joe Haddad <timer150@gmail.com>
Date: Fri, 12 May 2017 21:23:26 -0400
Subject: [PATCH 12/21] Add support for
 https://github.com/facebook/react/pull/9679

---
 .../src/effects/proxyConsole.js               | 33 ++++++++++--
 packages/react-error-overlay/src/overlay.js   |  8 ++-
 .../react-error-overlay/src/utils/warnings.js | 52 +++++++++----------
 3 files changed, 60 insertions(+), 33 deletions(-)

diff --git a/packages/react-error-overlay/src/effects/proxyConsole.js b/packages/react-error-overlay/src/effects/proxyConsole.js
index a0a771f0e..d66bb8fb0 100644
--- a/packages/react-error-overlay/src/effects/proxyConsole.js
+++ b/packages/react-error-overlay/src/effects/proxyConsole.js
@@ -1,5 +1,32 @@
 /* @flow */
-type ConsoleProxyCallback = (message: string) => void;
+
+type ReactFrame = {
+  fileName: string | null,
+  lineNumber: number | null,
+  functionName: string | null,
+};
+const ReactFrameStack: Array<ReactFrame[]> = [];
+
+export type { ReactFrame };
+
+const registerReactStack = () => {
+  // $FlowFixMe
+  console.stack = frames => ReactFrameStack.push(frames);
+  // $FlowFixMe
+  console.stackEnd = frames => ReactFrameStack.pop();
+};
+
+const unregisterReactStack = () => {
+  // $FlowFixMe
+  console.stack = undefined;
+  // $FlowFixMe
+  console.stackEnd = undefined;
+};
+
+type ConsoleProxyCallback = (
+  message: string,
+  frames: ReactFrame[] | void
+) => void;
 const permanentRegister = function proxyConsole(
   type: string,
   callback: ConsoleProxyCallback
@@ -7,9 +34,9 @@ const permanentRegister = function proxyConsole(
   const orig = console[type];
   console[type] = function __stack_frame_overlay_proxy_console__() {
     const message = [].slice.call(arguments).join(' ');
-    callback(message);
+    callback(message, ReactFrameStack[ReactFrameStack.length - 1]);
     return orig.apply(this, arguments);
   };
 };
 
-export { permanentRegister };
+export { permanentRegister, registerReactStack, unregisterReactStack };
diff --git a/packages/react-error-overlay/src/overlay.js b/packages/react-error-overlay/src/overlay.js
index 7c3ebb536..273c9ecb0 100644
--- a/packages/react-error-overlay/src/overlay.js
+++ b/packages/react-error-overlay/src/overlay.js
@@ -21,6 +21,8 @@ import {
 } from './effects/stackTraceLimit';
 import {
   permanentRegister as permanentRegisterConsole,
+  registerReactStack,
+  unregisterReactStack,
 } from './effects/proxyConsole';
 import { massage as massageWarning } from './utils/warnings';
 
@@ -213,8 +215,9 @@ function inject() {
   registerShortcuts(window, shortcutHandler);
   registerStackTraceLimit();
 
-  permanentRegisterConsole('error', warning => {
-    const data = massageWarning(warning);
+  registerReactStack();
+  permanentRegisterConsole('error', (warning, stack) => {
+    const data = massageWarning(warning, stack);
     if (data == null) return;
     crash(
       // $FlowFixMe
@@ -233,6 +236,7 @@ function uninject() {
   unregisterShortcuts(window);
   unregisterPromise(window);
   unregisterError(window);
+  unregisterReactStack();
 }
 
 export { inject, uninject };
diff --git a/packages/react-error-overlay/src/utils/warnings.js b/packages/react-error-overlay/src/utils/warnings.js
index 28d66e994..8a0a660c6 100644
--- a/packages/react-error-overlay/src/utils/warnings.js
+++ b/packages/react-error-overlay/src/utils/warnings.js
@@ -1,42 +1,38 @@
 // @flow
+import type { ReactFrame } from '../effects/proxyConsole';
 
-// This is a list of React warnings to display
-// There must be zero or one capture group; and the capture group is assumed to be a missing stack frame.
-const warnings = [
-  /^.*React.createElement: type is invalid.+Check your code at (.*?:.*)[.]$/,
-];
-// This is a list of information to remove from React warnings, it's not particularly useful to show
+// This is a list of information to remove from React warnings, it's not particularly useful to show.
 const removals = [/Check your code at (.*?:.*)[.]/];
 
-function massage(warning: string): { message: string, stack: string } | null {
-  const nIndex = warning.indexOf('\n');
-  let message = warning;
-  if (nIndex !== -1) {
-    message = message.substring(0, nIndex);
-  }
-  let stack = warning.substring(nIndex + 1);
-
-  let found = false;
-  for (const warning of warnings) {
-    const m = message.match(warning);
-    if (!m) {
-      continue;
-    }
-    found = true;
-    if (!m[1]) {
-      break;
-    }
-    stack = `in (render function) (at ${m[1]})\n${stack}`;
-    break;
-  }
-  if (!found) {
+function massage(
+  warning: string,
+  frames: ReactFrame[] | void
+): { message: string, stack: string } | null {
+  if (!frames) {
     return null;
   }
 
+  let message = warning;
+  const nIndex = message.indexOf('\n');
+  if (nIndex !== -1) message = message.substring(0, nIndex);
+
   for (const trim of removals) {
     message = message.replace(trim, '');
   }
 
+  let stack = '';
+  for (let index = 0; index < frames.length; ++index) {
+    const { fileName, lineNumber } = frames[index];
+    if (fileName == null || lineNumber == null) continue;
+    let { functionName } = frames[index];
+    if (functionName == null && index === 0 && index + 1 < frames.length) {
+      functionName = frames[index + 1].functionName;
+      if (functionName !== null) functionName = `(${functionName})`;
+    }
+    functionName = functionName || '(unknown function)';
+
+    stack += `in ${functionName} (at ${fileName}:${lineNumber})\n`;
+  }
   return { message, stack };
 }
 
-- 
GitLab


From ede4f9bf52ed20942edf56ecf0aee6101cb3f16a Mon Sep 17 00:00:00 2001
From: Joe Haddad <timer150@gmail.com>
Date: Fri, 12 May 2017 21:23:36 -0400
Subject: [PATCH 13/21] Use absolute paths

---
 packages/react-scripts/config/webpack.config.dev.js | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/packages/react-scripts/config/webpack.config.dev.js b/packages/react-scripts/config/webpack.config.dev.js
index e7ab84a2e..3d18991c5 100644
--- a/packages/react-scripts/config/webpack.config.dev.js
+++ b/packages/react-scripts/config/webpack.config.dev.js
@@ -77,7 +77,7 @@ module.exports = {
     publicPath: publicPath,
     // Point sourcemap entries to original disk location
     devtoolModuleFilenameTemplate: info =>
-      path.relative(paths.appSrc, info.absoluteResourcePath),
+      path.resolve(info.absoluteResourcePath),
   },
   resolve: {
     // This allows you to set a fallback for where Webpack should look for modules.
-- 
GitLab


From 8997f580bb2af94a4f83157f8444d1c6dd7fbc16 Mon Sep 17 00:00:00 2001
From: Joe Haddad <timer150@gmail.com>
Date: Fri, 12 May 2017 21:23:59 -0400
Subject: [PATCH 14/21] Trim path if it's absolute

---
 .../src/components/frame.js                   |  7 +++++--
 packages/react-scripts/template/src/App.js    | 19 +++++++++++++++++--
 .../react-scripts/template/src/fold/Bad.js    |  6 ++++++
 3 files changed, 28 insertions(+), 4 deletions(-)
 create mode 100644 packages/react-scripts/template/src/fold/Bad.js

diff --git a/packages/react-error-overlay/src/components/frame.js b/packages/react-error-overlay/src/components/frame.js
index 1b6a1d5d8..f4bcd4d17 100644
--- a/packages/react-error-overlay/src/components/frame.js
+++ b/packages/react-error-overlay/src/components/frame.js
@@ -127,13 +127,12 @@ function createFrame(
   lastElement: boolean
 ) {
   const { compiled } = frameSetting;
-  let { functionName } = frame;
+  let { functionName, _originalFileName: sourceFileName } = frame;
   const {
     fileName,
     lineNumber,
     columnNumber,
     _scriptCode: scriptLines,
-    _originalFileName: sourceFileName,
     _originalLineNumber: sourceLineNumber,
     _originalColumnNumber: sourceColumnNumber,
     _originalScriptCode: sourceLines,
@@ -149,6 +148,10 @@ function createFrame(
 
   let url;
   if (!compiled && sourceFileName && sourceLineNumber) {
+    // Remove everything up to the first /src/
+    const trimMatch = /.*?[/|\\](src[/|\\].*)/.exec(sourceFileName);
+    if (trimMatch && trimMatch[1]) sourceFileName = trimMatch[1];
+
     url = sourceFileName + ':' + sourceLineNumber;
     if (sourceColumnNumber) {
       url += ':' + sourceColumnNumber;
diff --git a/packages/react-scripts/template/src/App.js b/packages/react-scripts/template/src/App.js
index d7d52a7f3..c2f914571 100644
--- a/packages/react-scripts/template/src/App.js
+++ b/packages/react-scripts/template/src/App.js
@@ -2,13 +2,28 @@ import React, { Component } from 'react';
 import logo from './logo.svg';
 import './App.css';
 
+import Bad from './fold/Bad';
+
 class App extends Component {
   render() {
     return (
       <div className="App">
         <div className="App-header">
-          <img src={logo} className="App-logo" alt="logo" />
-          <h2>Welcome to React</h2>
+          <div>
+            <div>
+              <div>
+                <div>
+                  <div>
+                    <div>
+                      <img src={logo} className="App-logo" alt="logo" />
+                      <Bad>Welcome to React</Bad>
+                      {[1, 2, 3].map(s => <span>{s}</span>)}
+                    </div>{' '}
+                  </div>{' '}
+                </div>{' '}
+              </div>{' '}
+            </div>{' '}
+          </div>
         </div>
         <p className="App-intro">
           To get started, edit <code>src/App.js</code> and save to reload.
diff --git a/packages/react-scripts/template/src/fold/Bad.js b/packages/react-scripts/template/src/fold/Bad.js
new file mode 100644
index 000000000..c27d878fd
--- /dev/null
+++ b/packages/react-scripts/template/src/fold/Bad.js
@@ -0,0 +1,6 @@
+import React from 'react';
+
+let Lol = null;
+export default function Bad() {
+  return <div><h2><Lol /></h2></div>;
+}
-- 
GitLab


From 19eadc2075c8dcd9a60b6b29f134ad4c4d7f4075 Mon Sep 17 00:00:00 2001
From: Joe Haddad <timer150@gmail.com>
Date: Fri, 12 May 2017 21:26:55 -0400
Subject: [PATCH 15/21] Make sure it's an absolute path

---
 packages/react-error-overlay/src/components/frame.js | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/packages/react-error-overlay/src/components/frame.js b/packages/react-error-overlay/src/components/frame.js
index f4bcd4d17..f42ff3d4d 100644
--- a/packages/react-error-overlay/src/components/frame.js
+++ b/packages/react-error-overlay/src/components/frame.js
@@ -149,7 +149,7 @@ function createFrame(
   let url;
   if (!compiled && sourceFileName && sourceLineNumber) {
     // Remove everything up to the first /src/
-    const trimMatch = /.*?[/|\\](src[/|\\].*)/.exec(sourceFileName);
+    const trimMatch = /^[/|\\].*?[/|\\](src[/|\\].*)/.exec(sourceFileName);
     if (trimMatch && trimMatch[1]) sourceFileName = trimMatch[1];
 
     url = sourceFileName + ':' + sourceLineNumber;
-- 
GitLab


From 43a97e3e0d070f94f1a368a69063707032304c4f Mon Sep 17 00:00:00 2001
From: Joe Haddad <timer150@gmail.com>
Date: Fri, 12 May 2017 21:30:32 -0400
Subject: [PATCH 16/21] Oops

---
 packages/react-scripts/template/src/App.js    | 19 ++-----------------
 .../react-scripts/template/src/fold/Bad.js    |  6 ------
 2 files changed, 2 insertions(+), 23 deletions(-)
 delete mode 100644 packages/react-scripts/template/src/fold/Bad.js

diff --git a/packages/react-scripts/template/src/App.js b/packages/react-scripts/template/src/App.js
index c2f914571..d7d52a7f3 100644
--- a/packages/react-scripts/template/src/App.js
+++ b/packages/react-scripts/template/src/App.js
@@ -2,28 +2,13 @@ import React, { Component } from 'react';
 import logo from './logo.svg';
 import './App.css';
 
-import Bad from './fold/Bad';
-
 class App extends Component {
   render() {
     return (
       <div className="App">
         <div className="App-header">
-          <div>
-            <div>
-              <div>
-                <div>
-                  <div>
-                    <div>
-                      <img src={logo} className="App-logo" alt="logo" />
-                      <Bad>Welcome to React</Bad>
-                      {[1, 2, 3].map(s => <span>{s}</span>)}
-                    </div>{' '}
-                  </div>{' '}
-                </div>{' '}
-              </div>{' '}
-            </div>{' '}
-          </div>
+          <img src={logo} className="App-logo" alt="logo" />
+          <h2>Welcome to React</h2>
         </div>
         <p className="App-intro">
           To get started, edit <code>src/App.js</code> and save to reload.
diff --git a/packages/react-scripts/template/src/fold/Bad.js b/packages/react-scripts/template/src/fold/Bad.js
deleted file mode 100644
index c27d878fd..000000000
--- a/packages/react-scripts/template/src/fold/Bad.js
+++ /dev/null
@@ -1,6 +0,0 @@
-import React from 'react';
-
-let Lol = null;
-export default function Bad() {
-  return <div><h2><Lol /></h2></div>;
-}
-- 
GitLab


From 52a39a4e93de0e746df7efe59c80fe39c35dc98f Mon Sep 17 00:00:00 2001
From: Dan Abramov <dan.abramov@gmail.com>
Date: Sat, 13 May 2017 12:39:23 +0100
Subject: [PATCH 17/21] Tweak for new behavior

---
 .../react-error-overlay/src/utils/warnings.js     | 15 +++++++--------
 1 file changed, 7 insertions(+), 8 deletions(-)

diff --git a/packages/react-error-overlay/src/utils/warnings.js b/packages/react-error-overlay/src/utils/warnings.js
index 8a0a660c6..8858c3798 100644
--- a/packages/react-error-overlay/src/utils/warnings.js
+++ b/packages/react-error-overlay/src/utils/warnings.js
@@ -14,7 +14,9 @@ function massage(
 
   let message = warning;
   const nIndex = message.indexOf('\n');
-  if (nIndex !== -1) message = message.substring(0, nIndex);
+  if (nIndex !== -1) {
+    message = message.substring(0, nIndex);
+  }
 
   for (const trim of removals) {
     message = message.replace(trim, '');
@@ -23,14 +25,11 @@ function massage(
   let stack = '';
   for (let index = 0; index < frames.length; ++index) {
     const { fileName, lineNumber } = frames[index];
-    if (fileName == null || lineNumber == null) continue;
-    let { functionName } = frames[index];
-    if (functionName == null && index === 0 && index + 1 < frames.length) {
-      functionName = frames[index + 1].functionName;
-      if (functionName !== null) functionName = `(${functionName})`;
+    if (fileName == null || lineNumber == null) {
+      continue;
     }
-    functionName = functionName || '(unknown function)';
-
+    let { functionName } = frames[index];
+    functionName = functionName || '(anonymous function)';
     stack += `in ${functionName} (at ${fileName}:${lineNumber})\n`;
   }
   return { message, stack };
-- 
GitLab


From 4d9f647298346169f9ce482ae6b53c773a967c9d Mon Sep 17 00:00:00 2001
From: Dan Abramov <dan.abramov@gmail.com>
Date: Sat, 13 May 2017 12:52:54 +0100
Subject: [PATCH 18/21] Make it safer

---
 .../src/effects/proxyConsole.js               | 19 ++++++++++++++-----
 1 file changed, 14 insertions(+), 5 deletions(-)

diff --git a/packages/react-error-overlay/src/effects/proxyConsole.js b/packages/react-error-overlay/src/effects/proxyConsole.js
index d66bb8fb0..7541dd74c 100644
--- a/packages/react-error-overlay/src/effects/proxyConsole.js
+++ b/packages/react-error-overlay/src/effects/proxyConsole.js
@@ -5,15 +5,15 @@ type ReactFrame = {
   lineNumber: number | null,
   functionName: string | null,
 };
-const ReactFrameStack: Array<ReactFrame[]> = [];
+const reactFrameStack: Array<ReactFrame[]> = [];
 
 export type { ReactFrame };
 
 const registerReactStack = () => {
   // $FlowFixMe
-  console.stack = frames => ReactFrameStack.push(frames);
+  console.stack = frames => reactFrameStack.push(frames);
   // $FlowFixMe
-  console.stackEnd = frames => ReactFrameStack.pop();
+  console.stackEnd = frames => reactFrameStack.pop();
 };
 
 const unregisterReactStack = () => {
@@ -33,8 +33,17 @@ const permanentRegister = function proxyConsole(
 ) {
   const orig = console[type];
   console[type] = function __stack_frame_overlay_proxy_console__() {
-    const message = [].slice.call(arguments).join(' ');
-    callback(message, ReactFrameStack[ReactFrameStack.length - 1]);
+    try {
+      const message = arguments[0];
+      if (typeof message === 'string' && reactFrameStack.length > 0) {
+        callback(message, reactFrameStack[reactFrameStack.length - 1]);
+      }
+    } catch (err) {
+      // Warnings must never crash. Rethrow with a clean stack.
+      setTimeout(function() {
+        throw err;
+      });
+    }
     return orig.apply(this, arguments);
   };
 };
-- 
GitLab


From d7f81e7e22fcaf279cf531caa9b41e0b5a7b2605 Mon Sep 17 00:00:00 2001
From: Dan Abramov <dan.abramov@gmail.com>
Date: Sat, 13 May 2017 13:20:50 +0100
Subject: [PATCH 19/21] More resilient warnings

---
 .../src/components/frame.js                   |  4 ++-
 .../src/components/overlay.js                 |  7 ++++--
 packages/react-error-overlay/src/overlay.js   |  3 +--
 .../react-error-overlay/src/utils/warnings.js | 25 +++++++------------
 4 files changed, 18 insertions(+), 21 deletions(-)

diff --git a/packages/react-error-overlay/src/components/frame.js b/packages/react-error-overlay/src/components/frame.js
index f42ff3d4d..db9812cc3 100644
--- a/packages/react-error-overlay/src/components/frame.js
+++ b/packages/react-error-overlay/src/components/frame.js
@@ -150,7 +150,9 @@ function createFrame(
   if (!compiled && sourceFileName && sourceLineNumber) {
     // Remove everything up to the first /src/
     const trimMatch = /^[/|\\].*?[/|\\](src[/|\\].*)/.exec(sourceFileName);
-    if (trimMatch && trimMatch[1]) sourceFileName = trimMatch[1];
+    if (trimMatch && trimMatch[1]) {
+      sourceFileName = trimMatch[1];
+    }
 
     url = sourceFileName + ':' + sourceLineNumber;
     if (sourceColumnNumber) {
diff --git a/packages/react-error-overlay/src/components/overlay.js b/packages/react-error-overlay/src/components/overlay.js
index 3acd5b34c..85a0c814e 100644
--- a/packages/react-error-overlay/src/components/overlay.js
+++ b/packages/react-error-overlay/src/components/overlay.js
@@ -12,7 +12,7 @@ import type { SwitchCallback } from './additional';
 
 function createOverlay(
   document: Document,
-  name: string,
+  name: ?string,
   message: string,
   frames: StackFrame[],
   contextSize: number,
@@ -52,7 +52,10 @@ function createOverlay(
   applyStyles(header, headerStyle);
 
   // Make message prettier
-  let finalMessage = message.match(/^\w*:/) ? message : name + ': ' + message;
+  let finalMessage = message.match(/^\w*:/) || !name
+    ? message
+    : name + ': ' + message;
+
   finalMessage = finalMessage
     // TODO: maybe remove this prefix from fbjs?
     // It's just scaring people
diff --git a/packages/react-error-overlay/src/overlay.js b/packages/react-error-overlay/src/overlay.js
index 273c9ecb0..fe29a6c7b 100644
--- a/packages/react-error-overlay/src/overlay.js
+++ b/packages/react-error-overlay/src/overlay.js
@@ -72,7 +72,7 @@ const css = [
   '}',
 ].join('\n');
 
-function render(name: string, message: string, resolvedFrames: StackFrame[]) {
+function render(name: ?string, message: string, resolvedFrames: StackFrame[]) {
   disposeCurrentView();
 
   const iframe = window.document.createElement('iframe');
@@ -218,7 +218,6 @@ function inject() {
   registerReactStack();
   permanentRegisterConsole('error', (warning, stack) => {
     const data = massageWarning(warning, stack);
-    if (data == null) return;
     crash(
       // $FlowFixMe
       {
diff --git a/packages/react-error-overlay/src/utils/warnings.js b/packages/react-error-overlay/src/utils/warnings.js
index 8858c3798..ce9fcd3c0 100644
--- a/packages/react-error-overlay/src/utils/warnings.js
+++ b/packages/react-error-overlay/src/utils/warnings.js
@@ -1,25 +1,17 @@
 // @flow
 import type { ReactFrame } from '../effects/proxyConsole';
 
-// This is a list of information to remove from React warnings, it's not particularly useful to show.
-const removals = [/Check your code at (.*?:.*)[.]/];
+function stripInlineStacktrace(message: string): string {
+  return message.split('\n').filter(line => !line.match(/^\s*in/)).join('\n'); // "  in Foo"
+}
 
 function massage(
   warning: string,
-  frames: ReactFrame[] | void
-): { message: string, stack: string } | null {
-  if (!frames) {
-    return null;
-  }
-
-  let message = warning;
-  const nIndex = message.indexOf('\n');
-  if (nIndex !== -1) {
-    message = message.substring(0, nIndex);
-  }
-
-  for (const trim of removals) {
-    message = message.replace(trim, '');
+  frames: ReactFrame[]
+): { message: string, stack: string } {
+  let message = stripInlineStacktrace(warning);
+  if (message.indexOf('Warning: ') === 0) {
+    message = message.substring('Warning: '.length);
   }
 
   let stack = '';
@@ -32,6 +24,7 @@ function massage(
     functionName = functionName || '(anonymous function)';
     stack += `in ${functionName} (at ${fileName}:${lineNumber})\n`;
   }
+
   return { message, stack };
 }
 
-- 
GitLab


From 4cb6be38572d4250f9498c4a1d156eb5875a4c15 Mon Sep 17 00:00:00 2001
From: Dan Abramov <dan.abramov@gmail.com>
Date: Sat, 13 May 2017 13:27:26 +0100
Subject: [PATCH 20/21] Prettier output

---
 packages/react-error-overlay/src/components/overlay.js | 7 +++++--
 packages/react-error-overlay/src/utils/warnings.js     | 4 +---
 2 files changed, 6 insertions(+), 5 deletions(-)

diff --git a/packages/react-error-overlay/src/components/overlay.js b/packages/react-error-overlay/src/components/overlay.js
index 85a0c814e..e812bb441 100644
--- a/packages/react-error-overlay/src/components/overlay.js
+++ b/packages/react-error-overlay/src/components/overlay.js
@@ -59,10 +59,13 @@ function createOverlay(
   finalMessage = finalMessage
     // TODO: maybe remove this prefix from fbjs?
     // It's just scaring people
-    .replace('Invariant Violation: ', '')
+    .replace(/^Invariant Violation:\s*/, '')
+    // This is not helpful either:
+    .replace(/^Warning:\s*/, '')
     // Break the actionable part to the next line.
     // AFAIK React 16+ should already do this.
-    .replace(' Check the render method', '\n\nCheck the render method');
+    .replace(' Check the render method', '\n\nCheck the render method')
+    .replace(' Check your code at', '\n\nCheck your code at');
 
   // Put it in the DOM
   header.appendChild(document.createTextNode(finalMessage));
diff --git a/packages/react-error-overlay/src/utils/warnings.js b/packages/react-error-overlay/src/utils/warnings.js
index ce9fcd3c0..b2fc34bb4 100644
--- a/packages/react-error-overlay/src/utils/warnings.js
+++ b/packages/react-error-overlay/src/utils/warnings.js
@@ -10,10 +10,8 @@ function massage(
   frames: ReactFrame[]
 ): { message: string, stack: string } {
   let message = stripInlineStacktrace(warning);
-  if (message.indexOf('Warning: ') === 0) {
-    message = message.substring('Warning: '.length);
-  }
 
+  // Reassemble the stack with full filenames provided by React
   let stack = '';
   for (let index = 0; index < frames.length; ++index) {
     const { fileName, lineNumber } = frames[index];
-- 
GitLab


From 9da83b304b38d2d06a46878bee639b39b057a89f Mon Sep 17 00:00:00 2001
From: Dan Abramov <dan.abramov@gmail.com>
Date: Sat, 13 May 2017 13:32:34 +0100
Subject: [PATCH 21/21] Fix flow

---
 packages/react-error-overlay/src/effects/proxyConsole.js | 5 +----
 1 file changed, 1 insertion(+), 4 deletions(-)

diff --git a/packages/react-error-overlay/src/effects/proxyConsole.js b/packages/react-error-overlay/src/effects/proxyConsole.js
index 7541dd74c..062055e0b 100644
--- a/packages/react-error-overlay/src/effects/proxyConsole.js
+++ b/packages/react-error-overlay/src/effects/proxyConsole.js
@@ -23,10 +23,7 @@ const unregisterReactStack = () => {
   console.stackEnd = undefined;
 };
 
-type ConsoleProxyCallback = (
-  message: string,
-  frames: ReactFrame[] | void
-) => void;
+type ConsoleProxyCallback = (message: string, frames: ReactFrame[]) => void;
 const permanentRegister = function proxyConsole(
   type: string,
   callback: ConsoleProxyCallback
-- 
GitLab