Skip to content

Commit

Permalink
fix(import): correctly identify a default exported component (#6453)
Browse files Browse the repository at this point in the history
**Problem:**
Today we don't recognize when a default export is declared separately.
```ts
function App(){...}
export default App
```
this is not treated as a component when it's imported:

<video
src="https://github.com/user-attachments/assets/a52ce448-c324-44e9-bae1-9c64c3af21e5"></video>

**Fix:**
Use `isExportDefault` instead of a specific check for a function or a
class

**Manual Tests:**
I hereby swear that:

- [x] I opened a hydrogen project and it loaded
- [x] I could navigate to various routes in Play mode

Fixes #6439
  • Loading branch information
liady committed Dec 13, 2024
1 parent d10e894 commit cb088bc
Show file tree
Hide file tree
Showing 3 changed files with 86 additions and 4 deletions.
6 changes: 3 additions & 3 deletions editor/src/components/canvas/canvas-utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ import type {
HighlightBoundsForUids,
ExportsDetail,
} from '../../core/shared/project-file-types'
import { isParseSuccess, isTextFile } from '../../core/shared/project-file-types'
import { isExportDefault, isParseSuccess, isTextFile } from '../../core/shared/project-file-types'
import {
applyUtopiaJSXComponentsChanges,
getDefaultExportedTopLevelElement,
Expand Down Expand Up @@ -1730,9 +1730,9 @@ export function getValidElementPaths(
const { topLevelElements: resolvedTopLevelElements, exportsDetail } =
getParseSuccessForFilePath(resolvedFilePath, projectContents)
// Handle default exports as they may actually be named.
if (originTopLevelName == null) {
if (originTopLevelName == null || originTopLevelName === 'default') {
for (const exportDetail of exportsDetail) {
if (exportDetail.type === 'EXPORT_DEFAULT_FUNCTION_OR_CLASS') {
if (isExportDefault(exportDetail)) {
originTopLevelName = exportDetail.name
}
}
Expand Down
82 changes: 82 additions & 0 deletions editor/src/components/canvas/ui-jsx-canvas-bugs.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,88 @@ export default function App(props) {
`)
})

it('Handles importing default exports declared separately', () => {
const result = testCanvasRenderInlineMultifile(
null,
`
import React from 'react'
import Utopia, {
Scene,
Storyboard,
} from 'utopia-api'
import {default as Appy} from '/app'
export var storyboard = (
<Storyboard data-uid='sb'>
<Scene
data-uid='scene'
style={{ position: 'absolute', left: 0, top: 0, width: 375, height: 812 }}
>
<Appy data-uid='app' />
</Scene>
</Storyboard>
)
`,
{
'/app.js': `
import React from 'react'
function App(props) {
return <div data-uid='app-outer-div'>
<div data-uid='inner-div'>hello</div>
</div>
}
export default App`,
},
)

expect(result).toMatchInlineSnapshot(`
"<div style=\\"all: initial\\">
<div
id=\\"canvas-container\\"
data-testid=\\"canvas-container\\"
style=\\"position: absolute\\"
data-utopia-valid-paths=\\"sb sb/scene sb/scene/app sb/scene/app:app-outer-div sb/scene/app:app-outer-div/inner-div\\"
data-utopia-root-element-path=\\"sb\\"
>
<div
data-utopia-scene-id=\\"sb/scene\\"
data-path=\\"sb/scene\\"
style=\\"
overflow: hidden;
position: absolute;
background-color: var(--utopitheme-emphasizedBackground);
box-shadow: 0px 1px 2px 0px var(--utopitheme-shadow90),
0px 2px 4px -1px var(--utopitheme-shadow50);
background-image: conic-gradient(
var(--utopitheme-checkerboardLight) 0.25turn,
var(--utopitheme-checkerboardDark) 0.25turn 0.5turn,
var(--utopitheme-checkerboardLight) 0.5turn 0.75turn,
var(--utopitheme-checkerboardDark) 0.75turn
);
background-size: 12px 12px, 12px 12px, 12px 12px, 12px 12px;
background-position: -9px 0px, -3px -6px, 3px 6px, -3px 0;
left: 0;
top: 0;
width: 375px;
height: 812px;
\\"
data-uid=\\"scene\\"
>
<div data-uid=\\"app-outer-div\\" data-path=\\"sb/scene/app:app-outer-div\\">
<div
data-uid=\\"inner-div\\"
data-path=\\"sb/scene/app:app-outer-div/inner-div\\"
>
hello
</div>
</div>
</div>
</div>
</div>
"
`)
})

it('#1717 - Works with user components called Scene', () => {
const result = testCanvasRenderInlineMultifile(
null,
Expand Down
2 changes: 1 addition & 1 deletion editor/src/core/model/project-file-utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -840,7 +840,7 @@ export function getDefaultExportedTopLevelElement(file: TextFile): JSXElementChi
}

const defaultExportName =
file.fileContents.parsed.exportsDetail.find(isExportDefaultFunctionOrClass)?.name ?? null
file.fileContents.parsed.exportsDetail.find(isExportDefault)?.name ?? null

if (defaultExportName == null) {
return null
Expand Down

0 comments on commit cb088bc

Please sign in to comment.