@@ -116,6 +116,17 @@ interface DataViewRequestMessage {
116116
117117const dynamicDataViewPanels = new WeakSet < vscode . WebviewPanel > ( ) ;
118118
119+ function escapeHtml ( text : string ) : string {
120+ const map : Record < string , string > = {
121+ '&' : '&' ,
122+ '<' : '<' ,
123+ '>' : '>' ,
124+ '"' : '"' ,
125+ '\'' : ''' ,
126+ } ;
127+ return text . replace ( / [ & < > " ' ] / g, c => map [ c ] ) ;
128+ }
129+
119130function formatDataViewPanelTitle ( baseTitle : string , totalRows : number ) : string {
120131 return `${ baseTitle } (rows: ${ totalRows . toLocaleString ( ) } )` ;
121132}
@@ -144,7 +155,10 @@ function attachDynamicDataViewBridge(panel: vscode.WebviewPanel, viewId: string,
144155 const result = await sessionRequest ( {
145156 method : 'dataview_init' ,
146157 params : { view_id : viewId } ,
147- } ) as DataViewInitResult ;
158+ } ) as DataViewInitResult | undefined ;
159+ if ( ! result || typeof result . totalRows !== 'number' ) {
160+ throw new Error ( 'Invalid dataview_init response: missing or invalid totalRows' ) ;
161+ }
148162 if ( Number . isFinite ( result . totalRows ) ) {
149163 panel . title = formatDataViewPanelTitle ( baseTitle , result . totalRows ) ;
150164 }
@@ -162,7 +176,10 @@ function attachDynamicDataViewBridge(panel: vscode.WebviewPanel, viewId: string,
162176 sortModel : Array . isArray ( msg . sortModel ) ? msg . sortModel : [ ] ,
163177 filterModel : msg . filterModel ?? { } ,
164178 } ,
165- } ) as DataViewPageResult ;
179+ } ) as DataViewPageResult | undefined ;
180+ if ( ! result || typeof result . totalRows !== 'number' ) {
181+ throw new Error ( 'Invalid dataview_page response: missing or invalid totalRows' ) ;
182+ }
166183 if ( Number . isFinite ( result . totalRows ) ) {
167184 panel . title = formatDataViewPanelTitle ( baseTitle , result . totalRows ) ;
168185 }
@@ -175,6 +192,8 @@ function attachDynamicDataViewBridge(panel: vscode.WebviewPanel, viewId: string,
175192 method : 'dataview_dispose' ,
176193 params : { view_id : viewId } ,
177194 } ) ;
195+ // Remove from panels set to prevent duplicate disposal on panel close
196+ dynamicDataViewPanels . delete ( panel ) ;
178197 postResponse ( msg . requestId , true , true ) ;
179198 return ;
180199 }
@@ -661,7 +680,7 @@ export async function getTableHtml(webview: Webview, file: string | undefined, t
661680<head>
662681 <meta charset="utf-8">
663682 <meta name="viewport" content="width=device-width, initial-scale=1">
664- <title>${ title } </title>
683+ <title>${ escapeHtml ( title ) } </title>
665684 <style media="only screen">
666685 html, body {
667686 height: 100%;
@@ -1058,9 +1077,9 @@ export async function getTableHtml(webview: Webview, file: string | undefined, t
10581077 enableCellTextSelection: true,
10591078 ensureDomOrder: true,
10601079 tooltipShowDelay: 100,
1061- onFirstDataRendered: function() {
1062- if (gridApi ) {
1063- gridApi .columnApi? .autoSizeAllColumns(false);
1080+ onFirstDataRendered: function(params ) {
1081+ if (params.columnApi ) {
1082+ params .columnApi.autoSizeAllColumns(false);
10641083 }
10651084 updateFetchStatusPosition();
10661085 }
@@ -1124,7 +1143,7 @@ export async function getTableHtml(webview: Webview, file: string | undefined, t
11241143<head>
11251144 <meta charset="utf-8">
11261145 <meta name="viewport" content="width=device-width, initial-scale=1">
1127- <title>${ title } </title>
1146+ <title>${ escapeHtml ( title ) } </title>
11281147 <style media="only screen">
11291148 html, body {
11301149 height: 100%;
@@ -1326,7 +1345,7 @@ export async function getListHtml(webview: Webview, file: string, title: string)
13261345<head>
13271346 <meta charset="utf-8" />
13281347 <meta name="viewport" content="width=device-width, initial-scale=1">
1329- <title>${ title } </title>
1348+ <title>${ escapeHtml ( title ) } </title>
13301349 <script src="${ String ( webview . asWebviewUri ( Uri . file ( path . join ( resDir , 'jquery.min.js' ) ) ) ) } "></script>
13311350 <script src="${ String ( webview . asWebviewUri ( Uri . file ( path . join ( resDir , 'jquery.json-viewer.js' ) ) ) ) } "></script>
13321351 <link href="${ String ( webview . asWebviewUri ( Uri . file ( path . join ( resDir , 'jquery.json-viewer.css' ) ) ) ) } " rel="stylesheet">
0 commit comments