Skip to content
项目
群组
代码片段
帮助
当前项目
正在载入...
登录 / 注册
切换导航面板
B
bit-pm
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
图表
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
日程
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
图像
聊天
创建新问题
作业
提交
问题看板
Open sidebar
燕伟桐
bit-pm
Commits
79b7f865
Unverified
提交
79b7f865
authored
5月 02, 2025
作者:
Will Chen
提交者:
GitHub
5月 02, 2025
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Emit clean stack traces from iframe (#63)
上级
1bbfedc6
全部展开
显示空白字符变更
内嵌
并排
正在显示
5 个修改的文件
包含
208 行增加
和
21 行删除
+208
-21
dyad-shim.js
scaffold/dyad-shim.js
+185
-0
package.json
scaffold/package.json
+4
-2
pnpm-lock.yaml
scaffold/pnpm-lock.yaml
+0
-0
vite.config.ts
scaffold/vite.config.ts
+0
-0
PreviewIframe.tsx
src/components/preview_panel/PreviewIframe.tsx
+19
-19
没有找到文件。
scaffold/dyad-shim.js
0 → 100644
浏览文件 @
79b7f865
(
function
()
{
const
isInsideIframe
=
window
.
parent
!==
window
;
if
(
!
isInsideIframe
)
return
;
let
previousUrl
=
window
.
location
.
href
;
const
PARENT_TARGET_ORIGIN
=
"*"
;
// --- History API Overrides ---
const
originalPushState
=
history
.
pushState
;
const
originalReplaceState
=
history
.
replaceState
;
const
handleStateChangeAndNotify
=
(
originalMethod
,
state
,
title
,
url
)
=>
{
const
oldUrlForMessage
=
previousUrl
;
let
newUrl
;
try
{
newUrl
=
url
?
new
URL
(
url
,
window
.
location
.
href
).
href
:
window
.
location
.
href
;
}
catch
(
e
)
{
newUrl
=
window
.
location
.
href
;
}
const
navigationType
=
originalMethod
===
originalPushState
?
"pushState"
:
"replaceState"
;
try
{
// Pass the original state directly
originalMethod
.
call
(
history
,
state
,
title
,
url
);
previousUrl
=
window
.
location
.
href
;
window
.
parent
.
postMessage
(
{
type
:
navigationType
,
payload
:
{
oldUrl
:
oldUrlForMessage
,
newUrl
:
newUrl
},
},
PARENT_TARGET_ORIGIN
);
}
catch
(
e
)
{
console
.
error
(
`[vite-dev-plugin] Error calling original
${
navigationType
}
: `
,
e
);
window
.
parent
.
postMessage
(
{
type
:
"navigation-error"
,
payload
:
{
operation
:
navigationType
,
message
:
e
.
message
,
error
:
e
.
toString
(),
stateAttempted
:
state
,
urlAttempted
:
url
,
},
},
PARENT_TARGET_ORIGIN
);
}
};
history
.
pushState
=
function
(
state
,
title
,
url
)
{
handleStateChangeAndNotify
(
originalPushState
,
state
,
title
,
url
);
};
history
.
replaceState
=
function
(
state
,
title
,
url
)
{
handleStateChangeAndNotify
(
originalReplaceState
,
state
,
title
,
url
);
};
// --- Listener for Back/Forward Navigation (popstate event) ---
window
.
addEventListener
(
"popstate"
,
(
event
)
=>
{
const
currentUrl
=
window
.
location
.
href
;
previousUrl
=
currentUrl
;
});
// --- Listener for Commands from Parent ---
window
.
addEventListener
(
"message"
,
(
event
)
=>
{
if
(
event
.
source
!==
window
.
parent
||
!
event
.
data
||
typeof
event
.
data
!==
"object"
)
return
;
if
(
event
.
data
.
type
===
"navigate"
)
{
const
direction
=
event
.
data
.
payload
?.
direction
;
if
(
direction
===
"forward"
)
history
.
forward
();
else
if
(
direction
===
"backward"
)
history
.
back
();
}
});
// --- Sourcemapped Error Handling ---
function
sendSourcemappedErrorToParent
(
error
,
sourceType
)
{
if
(
typeof
window
.
StackTrace
===
"undefined"
)
{
console
.
error
(
"[vite-dev-plugin] StackTrace object not found."
);
// Send simplified raw data if StackTrace isn't available
window
.
parent
.
postMessage
(
{
type
:
sourceType
,
payload
:
{
message
:
error
?.
message
||
String
(
error
),
stack
:
error
?.
stack
||
"<no stack available - StackTrace.js missing>"
,
},
},
PARENT_TARGET_ORIGIN
);
return
;
}
window
.
StackTrace
.
fromError
(
error
)
.
then
((
stackFrames
)
=>
{
const
sourcemappedStack
=
stackFrames
.
map
((
sf
)
=>
sf
.
toString
())
.
join
(
"
\
n"
);
const
payload
=
{
message
:
error
?.
message
||
String
(
error
),
stack
:
sourcemappedStack
,
};
window
.
parent
.
postMessage
(
{
type
:
"iframe-sourcemapped-error"
,
payload
:
{
...
payload
,
originalSourceType
:
sourceType
},
},
PARENT_TARGET_ORIGIN
);
})
.
catch
((
mappingError
)
=>
{
console
.
error
(
"[vite-dev-plugin] Error during stacktrace sourcemapping:"
,
mappingError
);
const
payload
=
{
message
:
error
?.
message
||
String
(
error
),
// Provide the raw stack or an indication of mapping failure
stack
:
error
?.
stack
?
`Sourcemapping failed:
${
mappingError
.
message
}
\n--- Raw Stack ---\n
${
error
.
stack
}
`
:
`Sourcemapping failed:
${
mappingError
.
message
}
\n<no raw stack available>`
,
};
window
.
parent
.
postMessage
(
{
type
:
"iframe-sourcemapped-error"
,
payload
:
{
...
payload
,
originalSourceType
:
sourceType
},
},
PARENT_TARGET_ORIGIN
);
});
}
window
.
addEventListener
(
"error"
,
(
event
)
=>
{
let
error
=
event
.
error
;
if
(
!
(
error
instanceof
Error
))
{
window
.
parent
.
postMessage
(
{
type
:
"window-error"
,
payload
:
{
message
:
error
.
toString
(),
stack
:
"<no stack available - an improper error was thrown>"
,
},
},
PARENT_TARGET_ORIGIN
);
return
;
}
sendSourcemappedErrorToParent
(
error
,
"window-error"
);
});
window
.
addEventListener
(
"unhandledrejection"
,
(
event
)
=>
{
let
error
=
event
.
reason
;
if
(
!
(
error
instanceof
Error
))
{
window
.
parent
.
postMessage
(
{
type
:
"unhandled-rejection"
,
payload
:
{
message
:
event
.
reason
.
toString
(),
stack
:
"<no stack available - an improper error was thrown (promise)>"
,
},
},
PARENT_TARGET_ORIGIN
);
return
;
}
sendSourcemappedErrorToParent
(
error
,
"unhandled-rejection"
);
});
})();
scaffold/package.json
浏览文件 @
79b7f865
...
...
@@ -56,6 +56,7 @@
"react-router-dom"
:
"^6.26.2"
,
"recharts"
:
"^2.12.7"
,
"sonner"
:
"^1.5.0"
,
"stacktrace-js"
:
"^2.0.2"
,
"tailwind-merge"
:
"^2.5.2"
,
"tailwindcss-animate"
:
"^1.0.7"
,
"vaul"
:
"^0.9.3"
,
...
...
@@ -67,7 +68,7 @@
"@types/node"
:
"^22.5.5"
,
"@types/react"
:
"^18.3.3"
,
"@types/react-dom"
:
"^18.3.0"
,
"@vitejs/plugin-react-swc"
:
"^3.
5
.0"
,
"@vitejs/plugin-react-swc"
:
"^3.
9
.0"
,
"autoprefixer"
:
"^10.4.20"
,
"eslint"
:
"^9.9.0"
,
"eslint-plugin-react-hooks"
:
"^5.1.0-rc.0"
,
...
...
@@ -77,6 +78,6 @@
"tailwindcss"
:
"^3.4.11"
,
"typescript"
:
"^5.5.3"
,
"typescript-eslint"
:
"^8.0.1"
,
"vite"
:
"^
5.4.1
"
"vite"
:
"^
6.3.4
"
}
}
\ No newline at end of file
scaffold/pnpm-lock.yaml
浏览文件 @
79b7f865
差异被折叠。
点击展开。
scaffold/vite.config.ts
浏览文件 @
79b7f865
差异被折叠。
点击展开。
src/components/preview_panel/PreviewIframe.tsx
浏览文件 @
79b7f865
...
...
@@ -45,7 +45,9 @@ const ErrorBanner = ({ error, onDismiss, onAIFix }: ErrorBannerProps) => {
{
/* Error message in the middle */
}
<
div
className=
"px-6 py-1 text-sm"
>
<
div
className=
"text-red-700 dark:text-red-300 text-wrap"
>
{
error
}
</
div
>
<
div
className=
"text-red-700 dark:text-red-300 text-wrap font-mono whitespace-pre-wrap break-words text-xs"
>
{
error
}
</
div
>
</
div
>
{
/* Tip message */
}
...
...
@@ -159,8 +161,16 @@ export const PreviewIframe = ({
const
{
type
,
payload
}
=
event
.
data
;
if
(
type
===
"window-error"
)
{
const
errorMessage
=
`Error in
${
payload
.
filename
}
(line
${
payload
.
lineno
}
, col
${
payload
.
colno
}
):
${
payload
.
message
}
`
;
if
(
type
===
"window-error"
||
type
===
"unhandled-rejection"
||
type
===
"iframe-sourcemapped-error"
)
{
const
stack
=
type
===
"iframe-sourcemapped-error"
?
payload
.
stack
.
split
(
"
\
n"
).
slice
(
0
,
1
).
join
(
"
\
n"
)
:
payload
.
stack
;
const
errorMessage
=
`Error
${
payload
.
message
}
\nStack trace:
${
stack
}
`
;
console
.
error
(
"Iframe error:"
,
errorMessage
);
setErrorMessage
(
errorMessage
);
setAppOutput
((
prev
)
=>
[
...
...
@@ -171,18 +181,6 @@ export const PreviewIframe = ({
appId
:
selectedAppId
!
,
},
]);
}
else
if
(
type
===
"unhandled-rejection"
)
{
const
errorMessage
=
`Unhandled Promise Rejection:
${
payload
.
reason
}
`
;
console
.
error
(
"Iframe unhandled rejection:"
,
errorMessage
);
setErrorMessage
(
errorMessage
);
setAppOutput
((
prev
)
=>
[
...
prev
,
{
message
:
`Iframe unhandled rejection:
${
errorMessage
}
`
,
type
:
"client-error"
,
appId
:
selectedAppId
!
,
},
]);
}
else
if
(
type
===
"pushState"
||
type
===
"replaceState"
)
{
console
.
debug
(
`Navigation event:
${
type
}
`
,
payload
);
...
...
@@ -201,10 +199,6 @@ export const PreviewIframe = ({
newHistory
[
currentHistoryPosition
]
=
payload
.
newUrl
;
setNavigationHistory
(
newHistory
);
}
// Update navigation buttons state
setCanGoBack
(
currentHistoryPosition
>
0
);
setCanGoForward
(
currentHistoryPosition
<
navigationHistory
.
length
-
1
);
}
};
...
...
@@ -212,6 +206,12 @@ export const PreviewIframe = ({
return
()
=>
window
.
removeEventListener
(
"message"
,
handleMessage
);
},
[
navigationHistory
,
currentHistoryPosition
,
selectedAppId
]);
useEffect
(()
=>
{
// Update navigation buttons state
setCanGoBack
(
currentHistoryPosition
>
0
);
setCanGoForward
(
currentHistoryPosition
<
navigationHistory
.
length
-
1
);
},
[
navigationHistory
,
currentHistoryPosition
]);
// Initialize navigation history when iframe loads
useEffect
(()
=>
{
if
(
appUrl
)
{
...
...
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论