469469 }
470470
471471 @media (max-width : 768px ) {
472+ body {
473+ height : auto;
474+ min-height : 100vh ;
475+ overflow-y : auto;
476+ }
477+
472478 .main-container {
473479 flex-direction : column;
480+ min-height : 500px ;
481+ height : auto;
482+ }
483+
484+ .pane {
485+ min-height : 300px ;
486+ }
487+
488+ .pane : first-child ,
489+ .pane : last-child {
490+ flex : 1 1 auto;
491+ height : auto;
492+ min-height : 300px ;
493+ }
494+
495+ # editor-wrapper {
496+ min-height : 250px ;
497+ }
498+
499+ .output-container {
500+ min-height : 250px ;
501+ }
502+
503+ .output-section : first-child ,
504+ .output-section : last-child {
505+ flex : 1 1 auto;
506+ min-height : 150px ;
474507 }
475508
476509 .divider {
481514
482515 .header {
483516 padding : 16px 20px ;
517+ flex-direction : column;
518+ align-items : flex-start;
519+ gap : 12px ;
484520 }
485521
486522 .header h1 {
487523 font-size : 24px ;
524+ margin-bottom : 4px ;
525+ }
526+
527+ .header p {
528+ font-size : 14px ;
529+ }
530+
531+ .header-links {
532+ align-self : flex-start;
488533 }
489534
490535 .controls {
491536 padding : 12px 20px ;
492537 }
538+
539+ .status {
540+ margin-left : 0 ;
541+ width : 100% ;
542+ justify-content : center;
543+ }
493544 }
494545 </ style >
495546</ head >
@@ -502,6 +553,13 @@ <h1>Null-Safe Clang Playground</h1>
502553 < p > Flow-sensitive null safety for C - Try the experimental compiler live in your browser</ p >
503554 </ div >
504555 < div class ="header-links ">
556+ < button id ="reportBugBtn " class ="header-link " style ="background: none; border: none; cursor: pointer; ">
557+ < svg width ="20 " height ="20 " fill ="currentColor " viewBox ="0 0 16 16 " style ="vertical-align: text-bottom; ">
558+ < path d ="M8 15A7 7 0 1 1 8 1a7 7 0 0 1 0 14zm0 1A8 8 0 1 0 8 0a8 8 0 0 0 0 16z "/>
559+ < path d ="M7.002 11a1 1 0 1 1 2 0 1 1 0 0 1-2 0zM7.1 4.995a.905.905 0 1 1 1.8 0l-.35 3.507a.552.552 0 0 1-1.1 0L7.1 4.995z "/>
560+ </ svg >
561+ Report Bug
562+ </ button >
505563 < a href ="https://github.com/cs01/llvm-project/ " target ="_blank " class ="header-link ">
506564 < svg width ="20 " height ="20 " fill ="currentColor " viewBox ="0 0 16 16 " style ="vertical-align: text-bottom; ">
507565 < path d ="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.012 8.012 0 0 0 16 8c0-4.42-3.58-8-8-8z "/>
@@ -530,6 +588,9 @@ <h1>Null-Safe Clang Playground</h1>
530588 </ select >
531589
532590 < button id ="shareBtn " class ="btn btn-secondary ">
591+ < svg width ="16 " height ="16 " fill ="currentColor " viewBox ="0 0 16 16 " style ="vertical-align: text-bottom; ">
592+ < path d ="M13.5 1a1.5 1.5 0 1 0 0 3 1.5 1.5 0 0 0 0-3zM11 2.5a2.5 2.5 0 1 1 .603 1.628l-6.718 3.12a2.499 2.499 0 0 1 0 1.504l6.718 3.12a2.5 2.5 0 1 1-.488.876l-6.718-3.12a2.5 2.5 0 1 1 0-3.256l6.718-3.12A2.5 2.5 0 0 1 11 2.5zm-8.5 4a1.5 1.5 0 1 0 0 3 1.5 1.5 0 0 0 0-3zm11 5.5a1.5 1.5 0 1 0 0 3 1.5 1.5 0 0 0 0-3z "/>
593+ </ svg >
533594 Share
534595 </ button >
535596
@@ -903,7 +964,6 @@ <h1>Null-Safe Clang Playground</h1>
903964 const example = e . target . value ;
904965 if ( example && examples [ example ] ) {
905966 setEditorValue ( examples [ example ] ) ;
906- showToast ( 'Example loaded!' ) ;
907967 }
908968 } ) ;
909969
@@ -923,6 +983,104 @@ <h1>Null-Safe Clang Playground</h1>
923983 }
924984 } ) ;
925985
986+ // Report bug button - create GitHub issue with context
987+ const reportBugBtn = document . getElementById ( 'reportBugBtn' ) ;
988+ reportBugBtn . addEventListener ( 'click' , ( ) => {
989+ // Check if compiler is loaded and code has been compiled
990+ if ( ! clangVersion || outputNullsafe . textContent === '' || outputNullsafe . textContent === '(no output yet)' ) {
991+ if ( ! confirm ( 'You haven\'t compiled any code yet. The bug report will be incomplete. Continue anyway?' ) ) {
992+ return ;
993+ }
994+ }
995+
996+ const code = getEditorValue ( ) ;
997+ const nullsafeOutput = outputNullsafe . textContent || '(no output yet)' ;
998+ const mainlineOutput = outputMainline . textContent || '(no output yet)' ;
999+
1000+ // Get browser info - parse user agent for readability
1001+ const ua = navigator . userAgent ;
1002+ let browserInfo = ua ;
1003+
1004+ // Try to parse browser name and version
1005+ let browserName = 'Unknown' ;
1006+ let browserVersion = '' ;
1007+ if ( ua . includes ( 'Chrome/' ) && ! ua . includes ( 'Edg/' ) ) {
1008+ browserName = 'Chrome' ;
1009+ browserVersion = ua . match ( / C h r o m e \/ ( [ 0 - 9 . ] + ) / ) ?. [ 1 ] || '' ;
1010+ } else if ( ua . includes ( 'Edg/' ) ) {
1011+ browserName = 'Edge' ;
1012+ browserVersion = ua . match ( / E d g \/ ( [ 0 - 9 . ] + ) / ) ?. [ 1 ] || '' ;
1013+ } else if ( ua . includes ( 'Firefox/' ) ) {
1014+ browserName = 'Firefox' ;
1015+ browserVersion = ua . match ( / F i r e f o x \/ ( [ 0 - 9 . ] + ) / ) ?. [ 1 ] || '' ;
1016+ } else if ( ua . includes ( 'Safari/' ) && ! ua . includes ( 'Chrome/' ) ) {
1017+ browserName = 'Safari' ;
1018+ browserVersion = ua . match ( / V e r s i o n \/ ( [ 0 - 9 . ] + ) / ) ?. [ 1 ] || '' ;
1019+ }
1020+
1021+ // Get OS info
1022+ let osInfo = 'Unknown' ;
1023+ if ( ua . includes ( 'Mac OS X' ) ) {
1024+ const osVersion = ua . match ( / M a c O S X ( [ 0 - 9 _ ] + ) / ) ?. [ 1 ] ?. replace ( / _ / g, '.' ) || '' ;
1025+ osInfo = `macOS ${ osVersion } ` ;
1026+ } else if ( ua . includes ( 'Windows' ) ) {
1027+ osInfo = 'Windows' ;
1028+ } else if ( ua . includes ( 'Linux' ) ) {
1029+ osInfo = 'Linux' ;
1030+ }
1031+
1032+ const formattedBrowser = `${ browserName } ${ browserVersion } on ${ osInfo } ` ;
1033+
1034+ // Build the issue body
1035+ const issueBody = `## Bug Report from Playground
1036+
1037+ ### Environment
1038+ - **Compiler Version:** ${ clangVersion || 'not loaded' }
1039+ - **Browser:** ${ formattedBrowser }
1040+ - **User Agent:** ${ ua }
1041+ - **Playground URL:** ${ window . location . href }
1042+
1043+ ### Code
1044+ \`\`\`c
1045+ ${ code }
1046+ \`\`\`
1047+
1048+ ### Compiler Output
1049+
1050+ #### With Null Warnings
1051+ \`\`\`
1052+ ${ nullsafeOutput }
1053+ \`\`\`
1054+
1055+ #### Without Null Warnings
1056+ \`\`\`
1057+ ${ mainlineOutput }
1058+ \`\`\`
1059+
1060+ ### Expected Behavior
1061+ <!-- Please describe what you expected to happen -->
1062+
1063+
1064+ ### Actual Behavior
1065+ <!-- Please describe what actually happened -->
1066+
1067+
1068+ ### Additional Context
1069+ <!-- Add any other context about the problem here -->
1070+ ` ;
1071+
1072+ // Create GitHub issue URL with pre-filled content
1073+ const repoUrl = 'https://github.com/cs01/llvm-project' ;
1074+ const issueUrl = new URL ( `${ repoUrl } /issues/new` ) ;
1075+ issueUrl . searchParams . set ( 'title' , '[Playground Bug] ' ) ;
1076+ issueUrl . searchParams . set ( 'body' , issueBody ) ;
1077+ issueUrl . searchParams . set ( 'labels' , 'bug,playground' ) ;
1078+
1079+ // Open in new tab
1080+ window . open ( issueUrl . toString ( ) , '_blank' ) ;
1081+ showToast ( 'Opening bug report in GitHub...' ) ;
1082+ } ) ;
1083+
9261084 // Load code from URL on page load
9271085 function loadCodeFromURL ( ) {
9281086 const urlParams = new URLSearchParams ( window . location . search ) ;
@@ -940,10 +1098,12 @@ <h1>Null-Safe Clang Playground</h1>
9401098 }
9411099
9421100 async function initCompiler ( ) {
943- setStatus ( 'Loading compiler (64MB) ...' , true , 0 ) ;
1101+ setStatus ( 'Loading compiler...' , true , 0 ) ;
9441102 status . className = 'status' ;
9451103 loadingBar . classList . add ( 'active' ) ;
9461104
1105+ let loaded = 0 ;
1106+
9471107 try {
9481108 // Determine script URL
9491109 const isDev = window . location . hostname === 'localhost' || window . location . hostname === '127.0.0.1' ;
@@ -958,10 +1118,20 @@ <h1>Null-Safe Clang Playground</h1>
9581118 // Pre-load the WASM binary ONCE with progress tracking
9591119 console . log ( 'Downloading WASM binary...' ) ;
9601120 const wasmResponse = await fetch ( wasmUrl ) ;
1121+
1122+ if ( ! wasmResponse . ok ) {
1123+ throw new Error ( `Failed to fetch WASM: ${ wasmResponse . status } ${ wasmResponse . statusText } ` ) ;
1124+ }
1125+
9611126 const contentLength = wasmResponse . headers . get ( 'content-length' ) ;
9621127 const total = parseInt ( contentLength , 10 ) ;
9631128
964- let loaded = 0 ;
1129+ // Update status with actual size if known
1130+ if ( total ) {
1131+ const sizeMB = ( total / ( 1024 * 1024 ) ) . toFixed ( 0 ) ;
1132+ setStatus ( `Loading compiler (${ sizeMB } MB)...` , true , 0 ) ;
1133+ }
1134+
9651135 const reader = wasmResponse . body . getReader ( ) ;
9661136 const chunks = [ ] ;
9671137
@@ -1008,12 +1178,30 @@ <h1>Null-Safe Clang Playground</h1>
10081178 setTimeout ( ( ) => compile ( ) , 500 ) ;
10091179
10101180 } catch ( error ) {
1011- status . textContent = 'Failed to load compiler' ;
1181+ console . error ( 'Failed to load Clang WASM:' , error ) ;
1182+
1183+ // Provide a helpful error message
1184+ let errorMessage = 'Failed to load compiler' ;
1185+ let toastMessage = 'Failed to load compiler' ;
1186+
1187+ if ( error . message && error . message . includes ( 'Failed to fetch' ) ) {
1188+ errorMessage = 'Network error - Cannot download compiler' ;
1189+ toastMessage = 'Network error: Unable to download the compiler. Please check your internet connection.' ;
1190+ } else if ( error . message && ( error . message . includes ( '404' ) || error . message . includes ( 'File not found' ) ) ) {
1191+ errorMessage = 'Compiler files not found' ;
1192+ toastMessage = 'Compiler files not found. The WASM binaries are missing from the server.' ;
1193+ } else if ( loaded === 0 || ( wasmBinary && wasmBinary . byteLength === 0 ) ) {
1194+ errorMessage = 'Download failed - 0 bytes received' ;
1195+ toastMessage = 'Failed to download compiler: Received 0 bytes. Please check your internet connection and try refreshing the page.' ;
1196+ } else {
1197+ toastMessage = `Failed to load compiler: ${ error . message } ` ;
1198+ }
1199+
1200+ status . textContent = errorMessage ;
10121201 status . className = 'status error' ;
10131202 status . title = '' ;
10141203 loadingBar . classList . remove ( 'active' ) ;
1015- showToast ( 'Failed to load compiler: ' + error . message , 4000 ) ;
1016- console . error ( 'Failed to load Clang WASM:' , error ) ;
1204+ showToast ( toastMessage , 6000 ) ;
10171205 }
10181206 }
10191207
0 commit comments