@@ -3,6 +3,8 @@ import type {
33 TslPreviewModuleResult ,
44 TslPreviewModuleRuntime ,
55} from '../../../../packages/schema/src/tsl-preview-module.ts'
6+ import { createPlainErrorReport , createTslErrorReport , TslPreviewError } from '../lib/tsl-error-reporting'
7+ import type { PlaygroundErrorReport } from '../lib/playground-types'
68
79type THREE = typeof import ( 'three/webgpu' )
810type TSL = typeof import ( 'three/tsl' )
@@ -12,7 +14,7 @@ type TslPreviewCanvasProps = {
1214 pipeline : string
1315 fallbackSvg ?: string | null
1416 uniformOverrides ?: Record < string , number | number [ ] | boolean >
15- onError ?: ( errors : string [ ] ) => void
17+ onError ?: ( report : PlaygroundErrorReport ) => void
1618 onScreenshotReady ?: ( base64 : string ) => void
1719}
1820
@@ -55,14 +57,14 @@ export default function TslPreviewCanvas(props: TslPreviewCanvasProps) {
5557 const [ loading , setLoading ] = createSignal ( true )
5658 const [ error , setError ] = createSignal ( '' )
5759
58- function setPreviewError ( message : string ) {
59- setError ( message )
60- props . onError ?.( [ message ] )
60+ function setPreviewError ( report : PlaygroundErrorReport ) {
61+ setError ( report . errors [ 0 ] ?? report . structuredErrors [ 0 ] ?. message ?? 'Preview unavailable' )
62+ props . onError ?.( report )
6163 }
6264
6365 function clearPreviewError ( ) {
6466 setError ( '' )
65- props . onError ?.( [ ] )
67+ props . onError ?.( createPlainErrorReport ( [ ] ) )
6668 }
6769
6870 function captureScreenshot ( ) {
@@ -110,7 +112,10 @@ export default function TslPreviewCanvas(props: TslPreviewCanvasProps) {
110112
111113 const module = ( await import ( /* @vite -ignore */ currentModuleUrl ) ) as PreviewModuleNamespace
112114 if ( typeof module . createPreview !== 'function' ) {
113- throw new Error ( 'TSL preview modules must export createPreview(runtime).' )
115+ throw new TslPreviewError (
116+ 'tsl-material-build' ,
117+ 'TSL preview modules must export createPreview(runtime).' ,
118+ )
114119 }
115120
116121 const nextPreview = module . createPreview ( {
@@ -123,7 +128,10 @@ export default function TslPreviewCanvas(props: TslPreviewCanvasProps) {
123128 } )
124129
125130 if ( ! nextPreview ?. material || typeof nextPreview . material !== 'object' ) {
126- throw new Error ( 'createPreview(runtime) must return an object with a material.' )
131+ throw new TslPreviewError (
132+ 'tsl-material-build' ,
133+ 'createPreview(runtime) must return an object with a material.' ,
134+ )
127135 }
128136
129137 previewInstance = nextPreview as PreviewInstance
@@ -144,9 +152,7 @@ export default function TslPreviewCanvas(props: TslPreviewCanvasProps) {
144152 } catch ( previewError ) {
145153 disposePreviewMesh ( )
146154 setPreviewError (
147- previewError instanceof Error
148- ? previewError . message
149- : 'Failed to build the TSL preview module.' ,
155+ createTslErrorReport ( previewError , 'tsl-runtime' , 'Failed to build the TSL preview module.' ) ,
150156 )
151157 } finally {
152158 setLoading ( false )
@@ -155,7 +161,13 @@ export default function TslPreviewCanvas(props: TslPreviewCanvasProps) {
155161
156162 onMount ( async ( ) => {
157163 if ( ! ( 'gpu' in navigator ) ) {
158- setPreviewError ( 'WebGPU is not available in this browser.' )
164+ setPreviewError (
165+ createTslErrorReport (
166+ new TslPreviewError ( 'tsl-runtime' , 'WebGPU is not available in this browser.' ) ,
167+ 'tsl-runtime' ,
168+ 'WebGPU is not available in this browser.' ,
169+ ) ,
170+ )
159171 setLoading ( false )
160172 return
161173 }
@@ -236,9 +248,7 @@ export default function TslPreviewCanvas(props: TslPreviewCanvasProps) {
236248 await renderPreview ( props . previewModule )
237249 } catch ( previewError ) {
238250 setPreviewError (
239- previewError instanceof Error
240- ? previewError . message
241- : 'Failed to initialize the TSL preview runtime.' ,
251+ createTslErrorReport ( previewError , 'tsl-runtime' , 'Failed to initialize the TSL preview runtime.' ) ,
242252 )
243253 setLoading ( false )
244254 }
0 commit comments