11import { execFile } from 'child_process' ;
22import fs from 'fs' ;
3- import jsesc from 'jsesc' ;
43import circularSafeStringify from 'json-stringify-safe' ;
54import { EOL } from 'os' ;
65import path from 'path' ;
7- import { preview } from 'preview' ;
8- import { shape , Shape } from 'shape' ;
96import { file as makeTmpFile } from 'tmp-promise' ;
10- import {
11- Cancelled ,
12- EVAL_ERRORS ,
13- InvalidDependentPanelError ,
14- NoResultError ,
15- } from '../../shared/errors' ;
7+ import { Cancelled , EVAL_ERRORS , NoResultError } from '../../shared/errors' ;
168import log from '../../shared/log' ;
179import { newId } from '../../shared/object' ;
1810import { PanelBody } from '../../shared/rpc' ;
19- import {
20- ConnectorInfo ,
21- PanelInfo ,
22- PanelInfoType ,
23- PanelResult ,
24- ProjectState ,
25- } from '../../shared/state' ;
11+ import { ConnectorInfo , PanelInfo , PanelResult } from '../../shared/state' ;
2612import {
2713 CODE_ROOT ,
2814 DISK_ROOT ,
@@ -37,31 +23,6 @@ import { parsePartialJSONFile } from '../partial';
3723import { Dispatch , RPCHandler } from '../rpc' ;
3824import { getProjectResultsFile } from '../store' ;
3925import { getProjectAndPanel } from './shared' ;
40- import { EvalHandlerExtra , EvalHandlerResponse } from './types' ;
41-
42- type EvalHandler = (
43- project : ProjectState ,
44- panel : PanelInfo ,
45- extra : EvalHandlerExtra ,
46- dispatch : Dispatch
47- ) => Promise < EvalHandlerResponse > ;
48-
49- function unimplementedInJavaScript ( ) : EvalHandler {
50- return function ( ) {
51- throw new Error ( 'There is a bug, this condition should not be possible.' ) ;
52- } ;
53- }
54-
55- const EVAL_HANDLERS : { [ k in PanelInfoType ] : ( ) => EvalHandler } = {
56- table : ( ) => require ( './columns' ) . evalColumns ,
57- graph : ( ) => require ( './columns' ) . evalColumns ,
58- literal : unimplementedInJavaScript ,
59- database : unimplementedInJavaScript ,
60- file : unimplementedInJavaScript ,
61- http : unimplementedInJavaScript ,
62- program : unimplementedInJavaScript ,
63- filagg : unimplementedInJavaScript ,
64- } ;
6526
6627const runningProcesses : Record < string , Set < number > > = { } ;
6728const cancelledPids = new Set < number > ( ) ;
@@ -84,10 +45,6 @@ function killAllByPanelId(panelId: string) {
8445 }
8546}
8647
87- function canUseGoRunner ( panel : PanelInfo , connectors : ConnectorInfo [ ] ) {
88- return ! [ 'table' , 'graph' ] . includes ( panel . type ) ;
89- }
90-
9148export async function evalInSubprocess (
9249 subprocess : {
9350 node : string ;
@@ -122,7 +79,7 @@ export async function evalInSubprocess(
12279 args . push ( SETTINGS_FILE_FLAG , subprocess . settingsFileOverride ) ;
12380 }
12481
125- if ( subprocess . go && canUseGoRunner ( panel , connectors ) ) {
82+ if ( subprocess . go ) {
12683 base = subprocess . go ;
12784 args . shift ( ) ;
12885 }
@@ -213,6 +170,14 @@ export async function evalInSubprocess(
213170 throw e ;
214171 }
215172 }
173+
174+ // Table and graph panels get their results passed back to me displayed in the UI
175+ if ( [ 'table' , 'graph' ] . includes ( panel . type ) ) {
176+ const projectResultsFile = getProjectResultsFile ( projectName ) ;
177+ const bytes = fs . readFileSync ( projectResultsFile + panel . id ) ;
178+ rm . value = JSON . parse ( bytes . toString ( ) ) ;
179+ }
180+
216181 return [ { ...rm , ...resultMeta } , stderr ] ;
217182 } finally {
218183 try {
@@ -227,30 +192,6 @@ export async function evalInSubprocess(
227192 }
228193}
229194
230- function assertValidDependentPanels (
231- projectId : string ,
232- content : string ,
233- idMap : Record < string | number , string >
234- ) {
235- const projectResultsFile = getProjectResultsFile ( projectId ) ;
236- const re =
237- / ( D M _ g e t P a n e l \( (?< number > [ 0 - 9 ] + ) \) ) | ( D M _ g e t P a n e l \( (?< singlequote > ' (?: [ ^ ' \\ ] | \\ .) * \' ) \) ) | ( D M _ g e t P a n e l \( (?< doublequote > " (?: [ ^ " \\ ] | \\ .) * \" ) \) ) / g;
238- let match = null ;
239- while ( ( match = re . exec ( content ) ) !== null ) {
240- if ( match && match . groups ) {
241- const { number, singlequote, doublequote } = match . groups ;
242- let m = doublequote || singlequote || number ;
243- if ( [ "'" , '"' ] . includes ( m . charAt ( 0 ) ) ) {
244- m = m . slice ( 1 , m . length - 1 ) ;
245- }
246-
247- if ( ! fs . existsSync ( projectResultsFile + idMap [ m ] ) ) {
248- throw new InvalidDependentPanelError ( m ) ;
249- }
250- }
251- }
252- }
253-
254195async function evalNoUpdate (
255196 projectId : string ,
256197 body : PanelBody ,
@@ -260,7 +201,7 @@ async function evalNoUpdate(
260201 go ?: string ;
261202 }
262203) : Promise < [ Partial < PanelResult > , string ] > {
263- const { project, panel, panelPage } = await getProjectAndPanel (
204+ const { project, panel } = await getProjectAndPanel (
264205 dispatch ,
265206 projectId ,
266207 body . panelId
@@ -273,66 +214,16 @@ async function evalNoUpdate(
273214 body : { data : new PanelResult ( ) , panelId : panel . id } ,
274215 } ) ;
275216
276- if ( subprocessEval ) {
277- return evalInSubprocess (
278- subprocessEval ,
279- project . projectName ,
280- panel ,
281- project . connectors
282- ) ;
217+ if ( ! subprocessEval ) {
218+ throw new Error ( 'Developer error: all eval must use subprocess' ) ;
283219 }
284220
285- const idMap : Record < string | number , string > = { } ;
286- const idShapeMap : Record < string | number , Shape > = { } ;
287- project . pages [ panelPage ] . panels . forEach ( ( p , i ) => {
288- idMap [ i ] = p . id ;
289- idMap [ p . name ] = p . id ;
290- idShapeMap [ i ] = p . resultMeta . shape ;
291- idShapeMap [ p . name ] = p . resultMeta . shape ;
292- } ) ;
293-
294- assertValidDependentPanels ( projectId , panel . content , idMap ) ;
295-
296- const evalHandler = EVAL_HANDLERS [ panel . type ] ( ) ;
297- const res = await evalHandler (
298- project ,
221+ return evalInSubprocess (
222+ subprocessEval ,
223+ project . projectName ,
299224 panel ,
300- {
301- idMap,
302- idShapeMap,
303- } ,
304- dispatch
225+ project . connectors
305226 ) ;
306-
307- // TODO: is it a problem panels like Program skip this escaping?
308- // This library is important for escaping responses otherwise some
309- // characters can blow up various panel processes.
310- const json = jsesc ( res . value , { quotes : 'double' , json : true } ) ;
311-
312- if ( ! res . skipWrite ) {
313- const projectResultsFile = getProjectResultsFile ( projectId ) ;
314- fs . writeFileSync ( projectResultsFile + panel . id , json ) ;
315- }
316-
317- const s = shape ( res . value ) ;
318-
319- return [
320- {
321- stdout : res . stdout || '' ,
322- preview : preview ( res . value ) ,
323- shape : s ,
324- value : res . returnValue ? res . value : null ,
325- size : res . size === undefined ? json . length : res . size ,
326- arrayCount :
327- res . arrayCount === undefined
328- ? s . kind === 'array'
329- ? ( res . value || [ ] ) . length
330- : null
331- : res . arrayCount ,
332- contentType : res . contentType || 'application/json' ,
333- } ,
334- '' ,
335- ] ;
336227}
337228
338229export const makeEvalHandler = ( subprocessEval ?: {
0 commit comments