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

Extract, unit test, and improve getLabelFromStackTrace #2534

Merged
merged 38 commits into from
Nov 19, 2021

Conversation

srmagura
Copy link
Member

@srmagura srmagura commented Oct 31, 2021

What:

There were a few of cases where extracting the label from the stack trace did not work correctly.

Why:

  • The stack trace parsing code is complex but was lacking tests.
  • There were multiple reports of labels being different between SSR and client-side rendering during development.

How:

  • Create function getLabelFromStackTrace to encapsulate the regex logic.
  • Write unit tests for it.
  • Playgrounds:
    • Recreate the CRA playground which was on react-scripts v1.
    • Add Next.js playground for testing SSR.
    • Remove broken Razzle playground. If it is needed in the future, we can just recreate it.

Checklist:

  • Documentation
  • Tests
  • Code complete
  • Changeset

Before changing the implementation of getLabelByStackTrace

tests-before

After changing the implementation

All tests pass.

Safari is weird

This section is now outdated.

It looks like Safari likes to inline function calls, resulting in that function being omitted from the stack trace. In both of the following cases, there will be a "class name mismatch" warning if SSR is used.

  • typical function component - runtime=classic, Safari: component name does not appear in stack trace. The label should be undefined in this case.
    • I'm not worried about this because it only affects the old JSX runtime.
  • function component within object, Safari: component name is omitted from stack trace. The label should be the parent component's name in this case.
    • Andarist, do you have any idea how common this pattern is in practice? const test = { MyComp() { return <div css={{}} /> } }. If this is a corner case, we may not have to worry about it.

If either of these are going to be a problem, we could introduce a feature flag that disables label extraction. Label extraction would still be on by default.

@changeset-bot
Copy link

changeset-bot bot commented Oct 31, 2021

🦋 Changeset detected

Latest commit: 5888e15

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
@emotion/react Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@codesandbox-ci
Copy link

codesandbox-ci bot commented Oct 31, 2021

This pull request is automatically built and testable in CodeSandbox.

To see build info of the built libraries, click here or the icon next to each commit SHA.

Latest deployment of this branch, based on commit 5888e15:

Sandbox Source
Emotion Configuration
Emotion issue template Issue #2134

@codecov
Copy link

codecov bot commented Oct 31, 2021

Codecov Report

Merging #2534 (5888e15) into main (2bac69b) will increase coverage by 0.02%.
The diff coverage is 100.00%.

Impacted Files Coverage Δ
packages/react/src/emotion-element.js 100.00% <100.00%> (ø)
packages/react/src/get-label-from-stack-trace.js 100.00% <100.00%> (ø)

@Andarist
Copy link
Member

Andarist commented Nov 1, 2021

Amazing work so far, thank you ❤️

I would also take a look at this PR and the included comments: https://github.com/emotion-js/emotion/pull/2136/files . It's fine to continue with our current strategy - just mentioning this for completeness, might give you some new ideas/test cases.

Please ping me when this will be ready for review. As far as I can see you are still working on this one.

@srmagura
Copy link
Member Author

srmagura commented Nov 2, 2021

Thank you!!! The links were very helpful. 😁

I will let you know when the work is done.

@srmagura
Copy link
Member Author

srmagura commented Nov 2, 2021

@Andarist What are your thoughts on my "Safari is weird" section in the original post?

@Andarist
Copy link
Member

Andarist commented Nov 2, 2021

typical function component - runtime=classic, Safari: component name does not appear in stack trace. The label should be undefined in this case.

This is bizarre 😢 Especially that I don't see what's the difference between both runtimes here - their stack traces have the same structure in all browsers, only the jsx factory name is different.

Andarist, do you have any idea how common this pattern is in practice? const test = { MyComp() { return

} }. If this is a corner case, we may not have to worry about it.

AFAIK this is not common so I think it's OK to not care about it right now. If we could distinguish this situation in other stack traces reliably to return undefined there then that would be great. But if that's too problematic - then it shouldn't block the work done here.

@srmagura
Copy link
Member Author

Btw, I tested this in IE and the new code didn't cause any errors. Of course, the runtime label extraction does not actually work — new Error().stack is actually undefined.

Since we plan to fix this one way or another.
@srmagura
Copy link
Member Author

Removed the "SSR & Safari" section from the docs since we are planning to fix that one way or another. I also updated the initial comment of the PR to not close the issue about class name mismatch in Safari, since that is still an issue.

This should be ready for merge as far as I'm concerned. Thanks.

})

test('SSR', () => {
const stackTrace = `Error
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

huh, it's interesting that the same case has produced different-looking stack traces in Chrome and in node, even though they are both using V8 🤔

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is interesting. It is likely because the Chrome stack trace is from CRA while the SSR one is from Next.js and there are differences in build tooling. Let me know if you want me to redo the Chrome one using the Next.js playground.

test('Safari', () => {
const stackTrace = `createEmotionProps@http://localhost:3000/static/js/main.chunk.js:844:49
jsxDEV@http://localhost:3000/static/js/main.chunk.js:1126:247
MyComponent$9@http://localhost:3000/static/js/main.chunk.js:2274:92
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is somewhat interesting, why the TCO has not been applied here? 🤔

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah it is odd. I can redo this one using the exact code from the comment block if you want. I've noticed that very minor things can affect whether TCO is performed.

})
})

test('Chrome: Module.jsx', () => {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

could you add a note above this block mentioning how one reproduce this situation?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I never encountered a stack trace containing Module. during all of my testing so I'm not sure how this happens. It's complicated because it could depend on stuff like which version of Webpack is used.

Copy link
Member

@Andarist Andarist left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I left a couple of minor comments/questions. It looks great to me ❤️

@srmagura
Copy link
Member Author

Thanks! Please see my latest changes as well as my replies to a few of your comments.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
3 participants