Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

solid/reactivity causes eslint crash [Error: This should never happen] ScopeStack.findDeepestDeclarationScope #110

Closed
1 task done
aronmal opened this issue Oct 31, 2023 · 2 comments
Assignees
Labels
bug Something isn't working

Comments

@aronmal
Copy link

aronmal commented Oct 31, 2023

Describe the bug
When running eslint it's crashing, I can fix it when I removing a helper function.

Console:
> eslint --fix "src/**/*.{ts,tsx,js,jsx}"


Oops! Something went wrong! :(

ESLint: 8.52.0

Error: This should never happen
Occurred while linting /home/aronmal/Documents/Github/praxis-siebers/src/frontend-helpers/formReducer.ts:72
Rule: "solid/reactivity"
    at ScopeStack.findDeepestDeclarationScope (/home/aronmal/Documents/Github/praxis-siebers/node_modules/.pnpm/[email protected][email protected][email protected]/node_modules/eslint-plugin-solid/dist/rules/reactivity.js:30:19)
    at ScopeStack.pushUniqueSignal (/home/aronmal/Documents/Github/praxis-siebers/node_modules/.pnpm/[email protected][email protected][email protected]/node_modules/eslint-plugin-solid/dist/rules/reactivity.js:48:49)
    at handleTrackedScopes (/home/aronmal/Documents/Github/praxis-siebers/node_modules/.pnpm/[email protected][email protected][email protected]/node_modules/eslint-plugin-solid/dist/rules/reactivity.js:200:40)
    at onFunctionExit (/home/aronmal/Documents/Github/praxis-siebers/node_modules/.pnpm/[email protected][email protected][email protected]/node_modules/eslint-plugin-solid/dist/rules/reactivity.js:331:25)
    at ruleErrorHandler (/home/aronmal/Documents/Github/praxis-siebers/node_modules/.pnpm/[email protected]/node_modules/eslint/lib/linter/linter.js:1091:28)
    at /home/aronmal/Documents/Github/praxis-siebers/node_modules/.pnpm/[email protected]/node_modules/eslint/lib/linter/safe-emitter.js:45:58
    at Array.forEach (<anonymous>)
    at Object.emit (/home/aronmal/Documents/Github/praxis-siebers/node_modules/.pnpm/[email protected]/node_modules/eslint/lib/linter/safe-emitter.js:45:38)
    at NodeEventGenerator.applySelector (/home/aronmal/Documents/Github/praxis-siebers/node_modules/.pnpm/[email protected]/node_modules/eslint/lib/linter/node-event-generator.js:297:26)
    at NodeEventGenerator.applySelectors (/home/aronmal/Documents/Github/praxis-siebers/node_modules/.pnpm/[email protected]/node_modules/eslint/lib/linter/node-event-generator.js:326:22)
 ELIFECYCLE  Command failed with exit code 2.
My helper function:
export interface FormFieldType {
  fieldName: string
  field: string
  value: string
  alertMessage: string
  type: string
  required: boolean
}

export type FormObjectType = FormFieldType[]

interface setValue {
  type: "setValue"
  payload: { field: string; value: string }
}
interface setAlert {
  type: "setAlert"
  payload: { field: string; alertMessage: string }
}
interface reset {
  type: "reset"
}
interface clearAlerts {
  type: "clearAlerts"
}

export type FormObjectDispatchType = setValue | setAlert | reset | clearAlerts

export const initialFormObject: FormObjectType = [
  {
    fieldName: "Ihr Name",
    field: "name",
    value: "",
    alertMessage: "",
    type: "input",
    required: true,
  },
  {
    fieldName: "Ihre E-Mail",
    field: "email",
    value: "",
    alertMessage: "",
    type: "input",
    required: true,
  },
  {
    fieldName: "Ihre Telefonnummer",
    field: "telephone",
    value: "",
    alertMessage: "",
    type: "input",
    required: false,
  },
  {
    fieldName: "Betreff",
    field: "subject",
    value: "",
    alertMessage: "",
    type: "input",
    required: true,
  },
  {
    fieldName: "Ihre Nachricht",
    field: "message",
    value: "",
    alertMessage: "",
    type: "textarea",
    required: true,
  },
]

export default function formObjectDispatch(
  formObject: FormObjectType,
  action: FormObjectDispatchType,
) {
  switch (action.type) {
    case "setValue": {
      const { field, value } = action.payload
      const fieldMatch = formObject.findIndex((props) => props.field === field)
      const fieldProps = formObject[fieldMatch]
      const result = Object.assign([...formObject], {
        [fieldMatch]: {
          ...fieldProps,
          value,
          alertMessage: "",
        },
      })
      return result
    }

    case "setAlert": {
      const { field, alertMessage } = action.payload
      const fieldMatch = formObject.findIndex((props) => props.field === field)
      const fieldProps = formObject[fieldMatch]
      const result = Object.assign([...formObject], {
        [fieldMatch]: {
          ...fieldProps,
          alertMessage,
        },
      })
      return result
    }

    case "reset": {
      return initialFormObject
    }

    case "clearAlerts": {
      const result = formObject.map((obj) => ({ ...obj, alertMessage: "" }))
      return result
    }

    default:
      return formObject
  }
}

To Reproduce
Have the helper function in a file in the src dir of the solid-start project.

Expected behavior
lint and not crash

Screenshots
See Console output.

Environment (please complete the following information):

  • OS: Pop!OS Linux
  • Node version v20.6.0:
  • eslint-plugin-solid version: 0.13.0
  • eslint version: 8.52.0

Additional context
Ask if you need more information. I would want to help, but I don't know how this plugin works in the background.

  • I would be willing to contribute a PR to fix this issue
@aronmal aronmal added the bug Something isn't working label Oct 31, 2023
@joshwilsonvu
Copy link
Collaborator

That's bizarre! You're not even using any Solid APIs here. I'll look into this when I get some time.

Seems like there's an edge case with the reactivity rule's inner workings—tricky code, so not really something I'd ask you to worry about, though thanks for offering!

@joshwilsonvu
Copy link
Collaborator

Whew, this was a tough one!

You managed to hit several different edge cases that only cause a problem when combined:

  • Having inline functions taking a parameter named props (like components do)
  • Having not one, but two of these functions
  • Having both of these functions inside findIndex, which is an Array method known by the rule to run synchronously

The problem was a subtle timing issue, and is fixed by reordering a few lines 😅

joshwilsonvu added a commit that referenced this issue Dec 30, 2023
Only mark props as reactive for non-sync callbacks, fixes #110.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants