ericclemmons / click-to-component

Option+Click React components in your browser to instantly open the source in VS Code
MIT License
1.94k stars 75 forks source link

Fix bugs #89

Closed ericclemmons closed 3 weeks ago

ericclemmons commented 3 weeks ago

I was working on the bksy.app and found bugs. #85 #71

diff --git a/node_modules/click-to-react-component/src/ClickToComponent.js b/node_modules/click-to-react-component/src/ClickToComponent.js
index 7ed3ea5..aa91e0d 100644
--- a/node_modules/click-to-react-component/src/ClickToComponent.js
+++ b/node_modules/click-to-react-component/src/ClickToComponent.js
@@ -9,7 +9,8 @@ import * as React from 'react'

 import { ContextMenu } from './ContextMenu.js'
 import { getPathToSource } from './getPathToSource.js'
-import { getSourceForElement } from './getSourceForElement.js'
+import { getReactInstancesForElement } from './getReactInstancesForElement.js'
+import { getSourceForInstance } from './getSourceForInstance.js'
 import { getUrl } from './getUrl.js'

 export const State = /** @type {const} */ ({
@@ -40,7 +41,23 @@ export function ClickToComponent({ editor = 'vscode', pathModifier }) {
       event
     ) {
       if (state === State.HOVER && target instanceof HTMLElement) {
-        const source = getSourceForElement(target)
+        const instance = getReactInstancesForElement(target).find((instance) =>
+          getSourceForInstance(instance)
+        )
+
+        if (!instance) {
+          return console.warn('Could not find React instance for element', target)
+        }
+
+        const source = getSourceForInstance(instance)
+
+        if (!source) {
+          return console.warn(
+            'Could not find source for React instance',
+            instance
+          )
+        }
+
         const path = getPathToSource(source, pathModifier)
         const url = getUrl({
           editor,
diff --git a/node_modules/click-to-react-component/src/getDisplayNameFromReactInstance.js b/node_modules/click-to-react-component/src/getDisplayNameFromReactInstance.js
index 50d8a3c..64ed8ea 100644
--- a/node_modules/click-to-react-component/src/getDisplayNameFromReactInstance.js
+++ b/node_modules/click-to-react-component/src/getDisplayNameFromReactInstance.js
@@ -3,8 +3,9 @@
  * @param {Fiber} instance
  */
 export function getDisplayNameForInstance(instance) {
-  const { elementType, tag } = instance
+  const {elementType, tag} = instance

+  // https://github.com/facebook/react/blob/7c8e5e7ab8bb63de911637892392c5efd8ce1d0f/packages/react-reconciler/src/ReactWorkTags.js
   switch (tag) {
     case 0: // FunctionComponent
     case 1: // ClassComponent
@@ -12,6 +13,12 @@ export function getDisplayNameForInstance(instance) {
         elementType.displayName || elementType.name || 'Anonymous Component'
       )

+    case 3:
+      return 'HostRoot'
+
+    case 4:
+      return 'HostPortal'
+
     case 5: // HostComponent:
       return elementType

@@ -21,6 +28,9 @@ export function getDisplayNameForInstance(instance) {
     case 7: // Fragment
       return 'React.Fragment'

+    case 8:
+      return 'Mode'
+
     case 9: // ContextConsumer
       return 'Context.Consumer'

@@ -30,13 +40,58 @@ export function getDisplayNameForInstance(instance) {
     case 11: // ForwardRef
       return 'React.forwardRef'

-    case 15: // MemoComponent
+    case 12:
+      return 'Profiler'
+
+    case 13:
+      return 'SuspenseComponent'
+
+    case 14:
+      return 'MemoComponent'
+
+    case 15: // SimpleMemoComponent
       // Attempt to get name from wrapped component
-      return elementType.type.name || 'React.memo'
+      return elementType.type.name ?? 'MemoComponent'

     case 16: // LazyComponent
       return 'React.lazy'

+    case 17:
+      return 'IncompleteClassComponent'
+
+    case 18:
+      return 'DehydratedFragment'
+
+    case 19:
+      return 'SuspenseListComponent'
+
+    case 21:
+      return 'ScopeComponent'
+
+    case 22:
+      return 'OffscreenComponent'
+
+    case 23:
+      return 'LegacyHiddenComponent'
+
+    case 24:
+      return 'CacheComponent'
+
+    case 25:
+      return 'TracingMarkerComponent'
+
+    case 26:
+      return 'HostHoistable'
+
+    case 27:
+      return 'HostSingleton'
+
+    case 28:
+      return 'IncompleteFunctionComponent'
+
+    case 29:
+      return 'Throw'
+
     default:
       console.warn(`Unrecognized React Fiber tag: ${tag}`, instance)
       return 'Unknown Component'
diff --git a/node_modules/click-to-react-component/src/getSourceForInstance.js b/node_modules/click-to-react-component/src/getSourceForInstance.js
index a59e690..04adca7 100644
--- a/node_modules/click-to-react-component/src/getSourceForInstance.js
+++ b/node_modules/click-to-react-component/src/getSourceForInstance.js
@@ -8,7 +8,7 @@
  */
 export function getSourceForInstance({ _debugSource, _debugOwner }) {
   // source is sometimes stored on _debugOwner
-  const source = _debugSource || (_debugOwner && _debugOwner._debugSource)
+  const source = _debugSource ?? _debugOwner ? _debugOwner._debugSource : null

   if (!source) return