/ Check-in [5b595c6944]
DEMO | DOWNLOAD | DEPLOY | SEARCH
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Release "2.5.24". Windows fixes.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1:5b595c6944906bef7aa94b32843101f28fc3632d
User & Date: pmacdona 2018-10-26 15:28:33
Context
2018-10-26
20:18
Release "2.6". check-in: 3fb2997346 user: pmacdona tags: trunk, v2.6
15:28
Release "2.5.24". Windows fixes. check-in: 5b595c6944 user: pmacdona tags: trunk
2018-10-18
23:00
Release "2.5.23". Fix new RegExp arg 2 bug. Expand module -m to support templates. Fix File.chmod bug. Add SqliteUI -dump option. check-in: 81b5253abf user: pmacdona tags: trunk
Changes

Added Configs/make_devel.conf.







































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
# make.conf : Devel
DEFCONFIG_VER=2.5.23
JSI_CONFIG_DEFINED=1
JSI__BASE64=1
JSI__CDATA=1
JSI__DEBUG=1
JSI__ENCRYPT=1
JSI__EVENT=1
JSI__FILESYS=1
JSI__INFO=1
JSI__LOAD=1
JSI__MARKDOWN=1
JSI__MATH=1
JSI__MD5=1
JSI__READLINE=1
JSI__SHA1=1
JSI__SHA256=1
JSI__SIGNAL=1
JSI__STUBS=1
JSI__THREADS=1
JSI__ZVFS=1
JSI__MEMDEBUG=1
JSI__SANITIZE=1
WITH_EXT_SOCKET=1
WITH_EXT_SQLITE=1
WITH_EXT_WEBSOCKET=1
WITH_EXT_SQLITE=1
WITH_EXT_WEBSOCKET=1
WITH_EXT_MYSQL=1
BUILDIN_SQLITE=1
BUILDIN_WEBSOCKET=1
JSI__ZIPLIB=1
PROGRAM=jsish
TARGET=unix
PREFIX=/usr/local
LINKSTATIC=0
XCPREFIX=
BUILDMODS=

PROGFLAGS=  -DJSI__BASE64=1 -DJSI__CDATA=1 -DJSI__DEBUG=1 -DJSI__ENCRYPT=1 -DJSI__EVENT=1 -DJSI__FILESYS=1 -DJSI__INFO=1 -DJSI__LOAD=1 -DJSI__MARKDOWN=1 -DJSI__MATH=1 -DJSI__MD5=1 -DJSI__READLINE=1 -DJSI__SHA1=1 -DJSI__SHA256=1 -DJSI__SIGNAL=1 -DJSI__STUBS=1 -DJSI__THREADS=1 -DJSI__ZVFS=1 -DJSI__MEMDEBUG=1 -DJSI__MINIZ=0 -DJSI__REGEX=0 -DJSI__SANITIZE=1 -DJSI__SOCKET=1 -DJSI__SQLITE=1 -DJSI__WEBSOCKET=1 -DJSI__SQLITE=1 -DJSI__WEBSOCKET=1 -DJSI__MYSQL=1
MODFLAGS= 

# command: ./configure --ext=+sqlite,websocket,mysql --label=Devel --opt=+sanitize,memdebug
# prefix : /usr/local
# program: jsish
# target : unix
# shared : 0
# nozip  : 0
# opt    : base64,cdata,debug,encrypt,event,filesys,info,load,markdown,math,md5,readline,sha1,sha256,signal,stubs,threads,zvfs,sanitize,memdebug
# ext    : socket,sqlite,websocket,sqlite,websocket,mysql
# mod    : 

Added Configs/make_static.conf.





































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
# make.conf : Release
DEFCONFIG_VER=2.0332
JSI_CONFIG_DEFINED=1
JSI__BASE64=1
JSI__CDATA=1
JSI__DEBUG=1
JSI__ENCRYPT=1
JSI__EVENT=1
JSI__FILESYS=1
JSI__INFO=1
JSI__LOAD=1
JSI__MARKDOWN=1
JSI__MATH=1
JSI__MD5=1
JSI__READLINE=1
JSI__SANITIZE=0
JSI__SHA1=1
JSI__SHA256=1
JSI__SIGNAL=1
JSI__STUBS=1
JSI__THREADS=1
JSI__ZVFS=1
WITH_EXT_SOCKET=1
WITH_EXT_SQLITE=1
WITH_EXT_WEBSOCKET=1
WITH_EXT_SQLITE=1
WITH_EXT_WEBSOCKET=1
WITH_MOD_MYSQL=1
BUILDIN_SQLITE=1
BUILDIN_WEBSOCKET=1
JSI__ZIPLIB=1
PROGRAM=jsish
TARGET=unix
PREFIX=/usr/local
LINKSTATIC=1
XCPREFIX=
BUILDMODS=

PROGFLAGS=  -DJSI__BASE64=1 -DJSI__CDATA=1 -DJSI__DEBUG=1 -DJSI__ENCRYPT=1 -DJSI__EVENT=1 -DJSI__FILESYS=1 -DJSI__INFO=1 -DJSI__LOAD=1 -DJSI__MARKDOWN=1 -DJSI__MATH=1 -DJSI__MD5=1 -DJSI__READLINE=1 -DJSI__SHA1=1 -DJSI__SHA256=1 -DJSI__SIGNAL=1 -DJSI__STUBS=1 -DJSI__THREADS=1 -DJSI__ZVFS=1 -DJSI__MEMDEBUG=0 -DJSI__MINIZ=0 -DJSI__REGEX=0 -DJSI__SANITIZE=0 -DJSI__SOCKET=1 -DJSI__SQLITE=1 -DJSI__WEBSOCKET=1 -DJSI__SQLITE=1 -DJSI__WEBSOCKET=1
MODFLAGS=  -DJSI__MYSQL=1

# command: ./configure --ext=+sqlite,websocket,mysql --label=Release
# prefix : /usr/local
# program: jsish
# target : unix
# shared : 0
# nozip  : 0
# opt    : base64,cdata,debug,encrypt,event,filesys,info,load,markdown,math,md5,readline,sha1,sha256,signal,stubs,threads,zvfs
# ext    : socket,sqlite,websocket,sqlite,websocket,mysql
# mod    : 

Changes to js-demos/wsdemo.jsi.

4
5
6
7
8
9
10

11
12
13
14
15
16
17
..
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58

function wsdemo(args:array|string=void, conf:object=void) {
    
    var self = { done:false };
    var options = { // A minimal WebSocket demo
        client  :false,         // Run in client mode.  Default is server mode.
        count   :10,            // Number of times client sends a string.

        port    :8818,          // Port number for server.
        file    :'wspage.html', // File to serve out: can also be given as cmdline arg.
        wsdebug :0,             // WebSockets debug level.
        wsOpts  :{}             // WebSockets options.
    };
    
    parseOpts(self, options, conf);
................................................................................
         if (typeof args == 'string' && args !== '')
            self.file = args;
        else if (typeof args === 'array' && args.length)
            self.file = args[0];

        var wsopts = {
            port:self.port, client:self.client, onRecv:WsRecv, debug:self.wsdebug,
            onFilter:WsFilter, onCloseLast:WsCloseLast
        };
        for (var i in self.wsOpts) {
            wsopts[i] = self.wsOpts[i];
        }
        LogDebug("Starting:\n", conf, wsopts);
        debugger;
        self.ws = new WebSocket( wsopts );







>







 







|







4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
..
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59

function wsdemo(args:array|string=void, conf:object=void) {
    
    var self = { done:false };
    var options = { // A minimal WebSocket demo
        client  :false,         // Run in client mode.  Default is server mode.
        count   :10,            // Number of times client sends a string.
        local   :true,          // Connection listens only on localhost.
        port    :8818,          // Port number for server.
        file    :'wspage.html', // File to serve out: can also be given as cmdline arg.
        wsdebug :0,             // WebSockets debug level.
        wsOpts  :{}             // WebSockets options.
    };
    
    parseOpts(self, options, conf);
................................................................................
         if (typeof args == 'string' && args !== '')
            self.file = args;
        else if (typeof args === 'array' && args.length)
            self.file = args[0];

        var wsopts = {
            port:self.port, client:self.client, onRecv:WsRecv, debug:self.wsdebug,
            onFilter:WsFilter, onCloseLast:WsCloseLast, local:self.local
        };
        for (var i in self.wsOpts) {
            wsopts[i] = self.wsOpts[i];
        }
        LogDebug("Starting:\n", conf, wsopts);
        debugger;
        self.ws = new WebSocket( wsopts );

Changes to lib/Jsi_DebugUI/Jsi_DebugUI.jsi.

701
702
703
704
705
706
707

708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
        if (!File.exists(self.dbfile)) {
            throw("script file required: "+self.dbfile);
            return(1);
        }
       
        var i;
        var defws = {

            urlRedirect :'/DebugUI/html/main.htmli',
            port        :self.port, 
            rootdir     :self.rootdir, 
            onRecv      :webRecv, 
            onCloseLast :webCloseLast, 
            debug       :self.wsdebug,
            extHandlers :true,      // Sets up preprocess handlers for .htmli, .cssi, and .jsi files
            urlPrefix   :'/DebugUI'
        };
        if (self.local && Info.platform().platform != 'win')
            defws.interface = 'lo';
        for (i in defws)
            if (self.wsopts[i] === undefined)
                self.wsopts[i] = defws[i];
        
        self.ws = new WebSocket(self.wsopts);
        self.wsopts.port = self.ws.conf('port');
                    







>









<
<







701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717


718
719
720
721
722
723
724
        if (!File.exists(self.dbfile)) {
            throw("script file required: "+self.dbfile);
            return(1);
        }
       
        var i;
        var defws = {
            local       :self.local,
            urlRedirect :'/DebugUI/html/main.htmli',
            port        :self.port, 
            rootdir     :self.rootdir, 
            onRecv      :webRecv, 
            onCloseLast :webCloseLast, 
            debug       :self.wsdebug,
            extHandlers :true,      // Sets up preprocess handlers for .htmli, .cssi, and .jsi files
            urlPrefix   :'/DebugUI'
        };


        for (i in defws)
            if (self.wsopts[i] === undefined)
                self.wsopts[i] = defws[i];
        
        self.ws = new WebSocket(self.wsopts);
        self.wsopts.port = self.ws.conf('port');
                    

Changes to lib/Jsi_Help.jsi.

268
269
270
271
272
273
274
275
276
277
278
279

280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
        arv += index + rv + "<p><i>(page auto-generated)</i>";
        return arv;
    }
    
    function ljoin(lst:array, max:number, pre:string) {
        var rv = '', rc = pre;
        for (var i of lst) {
            rc += i+' ';
            if (rc.length>max) {
                rv += rc + '\n';
                rc = pre;
            }

        }
        rv += rc;
        return rv;
    }
    
    function help(str:string) {
        LogDebug('HELP:',str);
        str = str.trim();
        var rv = '';
        if (str === '' || str === '?' || str === 'help') {
            rv += 'Jsish interactive executes commands, uses tab for completions, and has help for '
                + 'the following builtin commands:\n\n'+ljoin(Info.cmds(), 80, '     ');
                rv += "\n\nHelp can also take options.  For example to display in a web browser try: 'help -web true WebSocket'";
                rv += "\n\nModule help can also be displayed (non-web), as in 'help Jsi_Websrv`. ";
                rv += 'Builtin modules include:\n\n';
                var nowork = ['Jsi_Conf', 'Jsi_Conf', 'Jsi_Opts', 'Jsi_Zip', 'Jsi_AutoMake', 'Jsi_Make', 
                    'Jsi_Main', 'Jsi_AutoPkg', 'Jsi_LogFile', 'Jsi_Run'],
                    modl=[];
                for (var i of Jsi_Auto.keys()) {
                    if (i.substr(0,4) != 'Jsi_') continue;
                    if (nowork.indexOf(i)>=0) continue;
                    modl.push(i);
                }
                rv += ljoin(modl, 80, '     ');
             
        } else {
            var lst, alst = str.split('. ');
            if (alst.length===1 || alst.length == 2) {
                var anam=alst.join('.'), tinf=Info.cmds(anam);
                LogTrace('Tinf:', tinf);
                if (!tinf.length) {







|



|
>











|
|
|









|







268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
        arv += index + rv + "<p><i>(page auto-generated)</i>";
        return arv;
    }
    
    function ljoin(lst:array, max:number, pre:string) {
        var rv = '', rc = pre;
        for (var i of lst) {
            rc += i;
            if (rc.length>max) {
                rv += rc + '\n';
                rc = pre;
            } else
                rc += ' ';
        }
        rv += rc;
        return rv;
    }
    
    function help(str:string) {
        LogDebug('HELP:',str);
        str = str.trim();
        var rv = '';
        if (str === '' || str === '?' || str === 'help') {
            rv += 'Jsish interactive executes commands, uses tab for completions, and has help for '
                + 'the following builtin commands:\n\n'+ljoin(Info.cmds(), 68, '     ');
                rv += "\n\nHelp can also take options.  For example to display in a web browser try:\n\n    help -web true WebSocket";
                rv += "\n\nModule help can also be displayed (non-web), as in 'help Jsi_Websrv`.\n";
                rv += 'Builtin modules include:\n\n';
                var nowork = ['Jsi_Conf', 'Jsi_Conf', 'Jsi_Opts', 'Jsi_Zip', 'Jsi_AutoMake', 'Jsi_Make', 
                    'Jsi_Main', 'Jsi_AutoPkg', 'Jsi_LogFile', 'Jsi_Run'],
                    modl=[];
                for (var i of Jsi_Auto.keys()) {
                    if (i.substr(0,4) != 'Jsi_') continue;
                    if (nowork.indexOf(i)>=0) continue;
                    modl.push(i);
                }
                rv += ljoin(modl, 68, '     ');
             
        } else {
            var lst, alst = str.split('. ');
            if (alst.length===1 || alst.length == 2) {
                var anam=alst.join('.'), tinf=Info.cmds(anam);
                LogTrace('Tinf:', tinf);
                if (!tinf.length) {

Changes to lib/Jsi_Proxy.jsi.

219
220
221
222
223
224
225

226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
        
        if (self.url && self.url.length)
            if ((self.isFile || self.url.substr(0,2) === './') && !File.isfile(self.url))
                throw("file not found: "+ufn);
                
        // Provide default values for websocket.
        self.wsopts = {

            debug:self.wsdebug,
            //getRegexp:/^\/[a-zA-Z0-9_]+$/,
            onGet:WsGet,
            onOpen:WsOpen,
            onClose:WsClose,
            onCloseLast:WsCloseLast,
            onFilter:onFilter,
            onRecv:WsRecv, 
            port:self.port,
            rootdir:self.rootdir,
            extHandlers:true,
            urlPrefix:'/Proxy'
        };
        if (self.local)
            self.wsopts.interface = 'lo';
        if (self.wsOptStr.length)
            self.wsOpts = JSON.parse(self.wsOptStr);
        for (var i in self.wsOpts)
            self.wsopts[i] = self.wsOpts[i];

        self.ws = new WebSocket(self.wsopts);
        self.wsopts.port = self.ws.conf('port');







>













<
<







219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239


240
241
242
243
244
245
246
        
        if (self.url && self.url.length)
            if ((self.isFile || self.url.substr(0,2) === './') && !File.isfile(self.url))
                throw("file not found: "+ufn);
                
        // Provide default values for websocket.
        self.wsopts = {
            local:self.local,
            debug:self.wsdebug,
            //getRegexp:/^\/[a-zA-Z0-9_]+$/,
            onGet:WsGet,
            onOpen:WsOpen,
            onClose:WsClose,
            onCloseLast:WsCloseLast,
            onFilter:onFilter,
            onRecv:WsRecv, 
            port:self.port,
            rootdir:self.rootdir,
            extHandlers:true,
            urlPrefix:'/Proxy'
        };


        if (self.wsOptStr.length)
            self.wsOpts = JSON.parse(self.wsOptStr);
        for (var i in self.wsOpts)
            self.wsopts[i] = self.wsOpts[i];

        self.ws = new WebSocket(self.wsopts);
        self.wsopts.port = self.ws.conf('port');

Changes to lib/Jsi_SqliteUI/Jsi_SqliteUI.jsi.

580
581
582
583
584
585
586

587
588
589
590
591
592
593
...
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612

613
614
615
616
617
618
619
            for (i=1; i<files.length; i++) {
                var fn = files[i];
                var dbn = File.rootname(File.tail(fn));
                self.db.query("ATTACH DATABASE '"+fn+"' AS "+dbn);
            }
        }
        self.wsopts = {

            port:self.port, 
            rootdir:self.rootdir, 
            onRecv:WsRecv,
            onOpen:WsOpen,
            onCloseLast:CloseLast,
            debug:self.wsdebug,
            extHandlers:true,
................................................................................
            urlPrefix:'/SqliteUI'
        };
        if (self.server) {
            self.closeTimeout = 0;
            self.noGui = true;
        }
        self.cleanup = cleanup;
        if (self.local) self.wsopts.interface = 'lo';
        /* Open websockets on first available port. */
        var i, emsg = '';
        if (self.wsObj && self.wsId) {
            // External proxy
            self.ws = self.wsObj;
            self.wsObj.idconf(self.wsId, {onRecv:WsRecv, rootdir:self.rootdir});
            self.noUpdate = 1;
            self.noGui = 1;
            return self;
        } else {

            self.ws = new WebSocket(self.wsopts);
            self.wsopts.port = self.ws.conf('port');
        }
        /* Setup options. */
        if (self.optdbfile && self.optdbfile != '') {
            self.optdb = new Sqlite(self.optdbfile);
            self.optdb.eval(self.optSchema);







>







 







<










>







580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
...
596
597
598
599
600
601
602

603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
            for (i=1; i<files.length; i++) {
                var fn = files[i];
                var dbn = File.rootname(File.tail(fn));
                self.db.query("ATTACH DATABASE '"+fn+"' AS "+dbn);
            }
        }
        self.wsopts = {
            local:self.local,
            port:self.port, 
            rootdir:self.rootdir, 
            onRecv:WsRecv,
            onOpen:WsOpen,
            onCloseLast:CloseLast,
            debug:self.wsdebug,
            extHandlers:true,
................................................................................
            urlPrefix:'/SqliteUI'
        };
        if (self.server) {
            self.closeTimeout = 0;
            self.noGui = true;
        }
        self.cleanup = cleanup;

        /* Open websockets on first available port. */
        var i, emsg = '';
        if (self.wsObj && self.wsId) {
            // External proxy
            self.ws = self.wsObj;
            self.wsObj.idconf(self.wsId, {onRecv:WsRecv, rootdir:self.rootdir});
            self.noUpdate = 1;
            self.noGui = 1;
            return self;
        } else {
            LogDebug('WSopts', self.wsopts);
            self.ws = new WebSocket(self.wsopts);
            self.wsopts.port = self.ws.conf('port');
        }
        /* Setup options. */
        if (self.optdbfile && self.optdbfile != '') {
            self.optdb = new Sqlite(self.optdbfile);
            self.optdb.eval(self.optSchema);

Changes to lib/Jsi_Websrv.jsi.

345
346
347
348
349
350
351

352
353
354
355
356
357
358
...
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
        if (!self.rootdir)
            self.rootdir = '.';
        if (!self.server && !self.pageStr && (!self.url || !File.isfile(self.rootdir+'/'+self.url)))
            throw("url file empty or not found: "+self.url);
        
        // Provide default values for websocket.
        var wo = self.wsopts = {

            debug:self.wsdebug,
            extHandler:true,
            onOpen:WsOpen,
            onClose:WsClose,
            onCloseLast:WsCloseLast,
            onRecv:WsRecv,
            onUpload:WsUpload,
................................................................................
        if (self.useridPass != '') {
            wo.useridPass = self.useridPass;
            if (self.useridPass === ':') // Exercise onAuth callback.
                wo.onAuth = WsAuth;
        }
        for (var i in self.wsOpts)
            wo[i] = self.wsOpts[i];
        if (self.local)
            wo.interface = 'lo';

        OpenWebsock();
        
        var nargs = null;
       // if (self.noCheck)
       //     nargs = '{noCheck:true}';
       // self.ws.handler('.htmli', 'Jsi_Htmlpp', null);  // Associate .htmli with Web Pre-Processor (for. <? ... ?> tags).







>







 







<
<







345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
...
387
388
389
390
391
392
393


394
395
396
397
398
399
400
        if (!self.rootdir)
            self.rootdir = '.';
        if (!self.server && !self.pageStr && (!self.url || !File.isfile(self.rootdir+'/'+self.url)))
            throw("url file empty or not found: "+self.url);
        
        // Provide default values for websocket.
        var wo = self.wsopts = {
            local:self.local,
            debug:self.wsdebug,
            extHandler:true,
            onOpen:WsOpen,
            onClose:WsClose,
            onCloseLast:WsCloseLast,
            onRecv:WsRecv,
            onUpload:WsUpload,
................................................................................
        if (self.useridPass != '') {
            wo.useridPass = self.useridPass;
            if (self.useridPass === ':') // Exercise onAuth callback.
                wo.onAuth = WsAuth;
        }
        for (var i in self.wsOpts)
            wo[i] = self.wsOpts[i];



        OpenWebsock();
        
        var nargs = null;
       // if (self.noCheck)
       //     nargs = '{noCheck:true}';
       // self.ws.handler('.htmli', 'Jsi_Htmlpp', null);  // Associate .htmli with Web Pre-Processor (for. <? ... ?> tags).

Changes to lib/Jsi_Wget.jsi.

3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
..
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
..
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
function Jsi_Wget(fileargs:array|string=void, conf:object=void) {
    
    var options = { // Web client for downloading files from url
        force       : false,        // Overwrite output file, if exists.
        headers     : [],           // Header fields to send.
        nowait      : false,        // Just return object: caller will call update.
        onDone      : null,         // Callback when done.
        out         : '',           // Output file name, or - for stdout: default is url tail.
        wsdebug     : 0             // WebSockets debug level.
    };
    
    var self = {
        address     : '',
        done        : false,
        fd          : null,
................................................................................
    if (self.port === -1)
        self.port = 80;
        
    function WsRecv(ws:userobj, id:number, str:string) {
        LogDebug("LEN: "+str.length);
        LogTrace("DATA", str);
        if (!self.fd)
            self.fd = new Channel((self.out==='-'?"stdout":self.out), 'w+');
        self.fd.write(str);
    }
    
    function WsClose(ws:userobj|null, id:number) {
        LogDebug("CLOSE");
        self.done = true;
        if (self.fd) {
................................................................................
        var as = self.address.split(':');
        if (as.length==2) {
            self.port = parseInt(as[1]);
            self.address = as[0];
        } else  if (as.length != 1)
            throw('bad port in address: '+self.address);
        
        if (self.out == '')
            self.out = File.tail(self.path);
        if (self.out !== '-' && File.exists(self.out)) {
            if (!self.force)
                throw('output file already exists: '+self.path);
            File.remove(self.out);
        }
        if (self.post.length)
            self.protocol = 'post';
        
        var wsopts = {
            client:true,
            onRecv:WsRecv,







|







 







|







 







|
|
|

|
|







3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
..
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
..
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
function Jsi_Wget(fileargs:array|string=void, conf:object=void) {
    
    var options = { // Web client for downloading files from url
        force       : false,        // Overwrite output file, if exists.
        headers     : [],           // Header fields to send.
        nowait      : false,        // Just return object: caller will call update.
        onDone      : null,         // Callback when done.
        O           : '',           // Output file name, or - for stdout: default is url tail.
        wsdebug     : 0             // WebSockets debug level.
    };
    
    var self = {
        address     : '',
        done        : false,
        fd          : null,
................................................................................
    if (self.port === -1)
        self.port = 80;
        
    function WsRecv(ws:userobj, id:number, str:string) {
        LogDebug("LEN: "+str.length);
        LogTrace("DATA", str);
        if (!self.fd)
            self.fd = new Channel((self.O==='-'?"stdout":self.O), 'wb+');
        self.fd.write(str);
    }
    
    function WsClose(ws:userobj|null, id:number) {
        LogDebug("CLOSE");
        self.done = true;
        if (self.fd) {
................................................................................
        var as = self.address.split(':');
        if (as.length==2) {
            self.port = parseInt(as[1]);
            self.address = as[0];
        } else  if (as.length != 1)
            throw('bad port in address: '+self.address);
        
        if (self.O == '')
            self.O = File.tail(self.path);
        if (self.O !== '-' && File.exists(self.O)) {
            if (!self.force)
                throw('output file already exists: '+self.O);
            File.remove(self.O);
        }
        if (self.post.length)
            self.protocol = 'post';
        
        var wsopts = {
            client:true,
            onRecv:WsRecv,

Changes to lib/templates/WebApp.jsi.

3
4
5
6
7
8
9
10
11
12
13

14
15
16
17
18
19
20
..
73
74
75
76
77
78
79

80
81
82
83
84
85
86
require('WebSocket');

function WebApp(args:array|string=void, conf:object=void) {
    
    var self = { done:false };
    var options = { // A  WebSocket server module
        file        :'html/main.htmli', // Source file.
        server      :false,         // Just the server: do not open a browser.
        port        :0,             // Port number for server.
        quiet       :false,         // No info messages.
        rootdir     :'',            // Root directory

        useridPass  :'',            // USER:PASS for web GUI.
        wsdebug     :0,             // WebSockets debug level.
        wsOpts      :{}             // WebSockets options.
    };
    
    parseOpts(self, options, conf);

................................................................................
        } else if (self.rootdir === '')
            self.rootdir=File.realpath(File.dirname(req.loadFile));

        if (!File.exists(self.rootdir+'/'+self.file))
            throw('file not found: '+self.file);

        var wsopts = {

            rootdir     :self.rootdir, 
            port        :self.port,
            debug       :self.wsdebug,
            onFilter    :onFilter,
            onCloseLast :onCloseLast,
            onRecv      :onRecv,
            onOpen      :onOpen,







|



>







 







>







3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
..
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
require('WebSocket');

function WebApp(args:array|string=void, conf:object=void) {
    
    var self = { done:false };
    var options = { // A  WebSocket server module
        file        :'html/main.htmli', // Source file.
        local       :true,      // Connection listens only on localhost.
        port        :0,             // Port number for server.
        quiet       :false,         // No info messages.
        rootdir     :'',            // Root directory
        server      :false,         // Just the server: do not open a browser.
        useridPass  :'',            // USER:PASS for web GUI.
        wsdebug     :0,             // WebSockets debug level.
        wsOpts      :{}             // WebSockets options.
    };
    
    parseOpts(self, options, conf);

................................................................................
        } else if (self.rootdir === '')
            self.rootdir=File.realpath(File.dirname(req.loadFile));

        if (!File.exists(self.rootdir+'/'+self.file))
            throw('file not found: '+self.file);

        var wsopts = {
            local:self.local,
            rootdir     :self.rootdir, 
            port        :self.port,
            debug       :self.wsdebug,
            onFilter    :onFilter,
            onCloseLast :onCloseLast,
            onRecv      :onRecv,
            onOpen      :onOpen,

Changes to lib/templates/module.jsi.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
..
20
21
22
23
24
25
26
27
28
29
#!/usr/bin/env jsish

require('Jsi');

function module(args:array, conf:object=void) {

    var options = { // module description.
        rootdir      :''      // Root directory.
    };
    var self = {
    };

    parseOpts(self, options, conf);
    
    function main() {
        LogDebug('Starting');
        if (self.rootdir === '')
            self.rootdir=Info.scriptDir();
        debugger;
................................................................................
        LogDebug('Done');
    }
    
    return main();
}

provide(module, 1);

if (isMain())
    runModule(module);


<
<

<





<







 







<


1
2


3

4
5
6
7
8

9
10
11
12
13
14
15
..
16
17
18
19
20
21
22

23
24
#!/usr/bin/env jsish



function module(args:array, conf:object=void) {

    var options = { // module description.
        rootdir      :''      // Root directory.
    };
    var self = {
    };

    parseOpts(self, options, conf);
    
    function main() {
        LogDebug('Starting');
        if (self.rootdir === '')
            self.rootdir=Info.scriptDir();
        debugger;
................................................................................
        LogDebug('Done');
    }
    
    return main();
}

provide(module, 1);

if (isMain())
    runModule(module);

Changes to src/jsi.c.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
.....
13323
13324
13325
13326
13327
13328
13329
13330
13331
13332
13333
13334
13335
13336
13337
.....
19102
19103
19104
19105
19106
19107
19108
19109

19110
19111
19112
19113
19114
19115
19116
19117
19118
.....
19154
19155
19156
19157
19158
19159
19160
19161
19162
19163
19164
19165
19166
19167
19168
.....
19452
19453
19454
19455
19456
19457
19458
19459
19460
19461
19462
19463
19464
19465
19466
.....
25525
25526
25527
25528
25529
25530
25531
25532
25533
25534
25535
25536
25537
25538
25539
25540
25541
25542
25543
25544
25545
25546
25547
25548
25549
25550
25551
25552
25553
25554
25555
25556
25557
25558








25559
25560
25561
25562
25563
25564
25565
.....
25599
25600
25601
25602
25603
25604
25605



25606

25607
25608
25609
25610
25611
25612
25613
.....
25705
25706
25707
25708
25709
25710
25711
25712
25713
25714
25715
25716
25717
25718
25719
.....
27015
27016
27017
27018
27019
27020
27021
27022
27023
27024
27025
27026
27027
27028
27029
.....
34828
34829
34830
34831
34832
34833
34834
34835
34836





34837
34838
34839
34840
34841
34842
34843
.....
36766
36767
36768
36769
36770
36771
36772
36773

36774
36775
36776
36777
36778
36779
36780
36781
36782
36783
36784
36785
36786
.....
49337
49338
49339
49340
49341
49342
49343
49344
49345
49346
49347
49348
49349
49350
49351
.....
50180
50181
50182
50183
50184
50185
50186
50187
50188
50189
50190
50191
50192
50193
50194
.....
51818
51819
51820
51821
51822
51823
51824

51825
51826
51827
51828
51829

51830
51831
51832
51833
51834
51835
51836
.....
52799
52800
52801
52802
52803
52804
52805





52806
52807
52808
52809
52810
52811
52812
.....
64116
64117
64118
64119
64120
64121
64122
64123
64124
64125
64126
64127

64128
64129
64130
64131
64132
64133
64134
64135
64136
64137
64138
64139
64140
/* jsi.h : External API header file for Jsi. */
#ifndef __JSI_H__
#define __JSI_H__

#define JSI_VERSION_MAJOR   2
#define JSI_VERSION_MINOR   5
#define JSI_VERSION_RELEASE 23

#define JSI_VERSION (JSI_VERSION_MAJOR + ((Jsi_Number)JSI_VERSION_MINOR/100.0) + ((Jsi_Number)JSI_VERSION_RELEASE/10000.0))

#ifndef JSI_EXTERN
#define JSI_EXTERN extern
#endif

................................................................................
typedef struct {
    bool istty;
    bool noRegex;
    bool noReadline;
    bool noproto;
    bool noCacheOpCodes;
    bool outUndef;
    bool strictFiles;
    bool logAllowDups;
    bool logColNums;
    bool privKeys;
    bool compat;
    bool mutexUnlock;
    int dblPrec;
    const char *blacklist;
................................................................................
    if (argc == 1) {
iact:
        if (interp->opts.no_interactive)
            return interp;
        rc = Jsi_Interactive(interp, JSI_OUTPUT_QUOTE|JSI_OUTPUT_NEWLINES);
    } else {
        if (argc == 2 && !Jsi_Strcmp(argv[1], "-h" )) {
            puts("usage: jsish -h/--help | -v/--version | -d/--debug | -D/--debugui | -u/--unittest | -U/-UU\n\t"

            "| -s/--safe | -Z/--zip | -S/--sqliteui | -w/--wget | -W/--websrv | -H/--htmli | -J/--jsi\n\t"
            "| -C/--cssi | -c/--cdata | -m/--module | -M/--make | -e/--eval | -t/--tracecall\n\t"
            "| -a/--archive | -T/--typecheck OPT | -IOPT VAL | FILE arg arg ...\nUse --help for long help.");
            return jsi_DoExit(interp, 1);
        }
        if (argc == 2 && !Jsi_Strcmp(argv[1], "--help")) {
            puts("jsish arguments:\n"
              "  -a/--archive FILE\tMount an archive (zip, sqlar or fossil repo) and run module.\n"
              "  -c/--cdata FILE\tGenerate .c or JSON output from a .jsc description.\n"
................................................................................
        }
        if (argc > 2 && (Jsi_Strcmp(argv[1], "--module")==0 || Jsi_Strcmp(argv[1], "-m" )==0)) {
            if (argv[2][0] == '-')
                rc = Jsi_EvalString(interp, "runModule('Jsi_Module');", JSI_EVAL_ISMAIN);
            else {
                Jsi_DString dStr = {};
                const char* cpe = Jsi_Strrchr(argv[2], '.');
                int len = (cpe?cpe-argv[2]:Jsi_Strlen(argv[2]));
                Jsi_DSPrintf(&dStr, "source(\"%s\"); puts(runModule(\"%.*s\",console.args.slice(1)));", argv[2], len, argv[2]);
                rc = Jsi_EvalString(interp, Jsi_DSValue(&dStr), JSI_EVAL_NOSKIPBANG);
                Jsi_DSFree(&dStr);
            }
        }
        else if (argc == 3 && (Jsi_Strcmp(argv[1], "--eval")==0 || Jsi_Strcmp(argv[1], "-e" )==0))
            rc = Jsi_EvalString(interp, argv[2], JSI_EVAL_NOSKIPBANG);
................................................................................
            Jsi_LogError("exceeded max subinterp depth");
            return NULL;
        }
    }
    interp->maxDepth = JSI_MAX_EVAL_DEPTH;
    interp->maxIncDepth = JSI_MAX_INCLUDE_DEPTH;
    interp->typeWarnMax = 50;
    interp->subOpts.dblPrec = DBL_DECIMAL_DIG-1;

    int iocnt;
    if (iopts) {
        iopts->interp = interp;
        interp->opts = *iopts;
    }
    interp->logOpts.file = 1;
................................................................................
    char cdbuf[PATH_MAX];
    Jsi_DSInit(dStr);
    if (!path || !path[0]) return NULL;
    if (*path == '/')
        Jsi_DSAppend(dStr, path, NULL);
#ifdef __WIN32  /* TODO: add proper handling for windows paths. */
    else if (*path && path[1] == ':') {
        prefix[0] = *path;
        prefix[1] = path[1];
        prefix[2] = 0;
        path += 2;
        goto full;
    }
#endif
    else if (path[0] == '~') {
        Jsi_DSAppend(dStr, jsi_GetHomeDir(interp), (path[1] == '/' ? "" : "/"), path+1, NULL);
    } else if (path[0] == '.' && path[1] == 0) {
        if (jsiIntData.pwd) {
            Jsi_DSAppend(dStr, jsiIntData.pwd, NULL);
        } else {
            Jsi_DSAppend(dStr, getcwd(cdbuf, sizeof(cdbuf)), NULL);
        }
    } else {
#ifdef __WIN32
full:
#endif
        if (jsiIntData.pwd) {
            Jsi_DSAppend(dStr, jsiIntData.pwd, "/", path, NULL);
        } else {
            Jsi_DSAppend(dStr, getcwd(cdbuf, sizeof(cdbuf)), "/", path, NULL);
        }
    }
    Jsi_DString sStr = {};
    char *cp = Jsi_DSValue(dStr);








    int i=0, n=0, m, nmax, unclean=0, slens[PATH_MAX];
    char *sp = cp, *ss;
    char *sptrs[PATH_MAX];
    while (*cp && n<PATH_MAX) {
        while (*cp && *cp == '/') {
            cp++;
            if (*cp == '/')
................................................................................
        }
        n--;
    }
    /* TODO: prefix for windows. */
    Jsi_DSAppend(&sStr, prefix, NULL);
    for (i=0; i<nmax; i++) {
        if (slens[i]) {



            Jsi_DSAppend(&sStr, "/", NULL);

            Jsi_DSAppendLen(&sStr, sptrs[i], slens[i]);
        }
    }
    Jsi_DSSetLength(dStr, 0);
    Jsi_DSAppend(dStr, Jsi_DSValue(&sStr), NULL);
    Jsi_DSFree(&sStr);
    return Jsi_DSValue(dStr);
................................................................................
        const char *homedrv = getenv("HOMEDRIVE");
        if (!homedrv) homedrv = "";
        Jsi_DSAppend(&dStr, homedrv, homedir, path[1] == '/' ? "" : "/", path+1, NULL);
#endif
        npath = Jsi_DSValue(&dStr);
    }
#ifdef __WIN32
    if (Jsi_Strncmp(path, "/zvfs", 5)==0)
        apath = NULL;
    else
#endif
    apath = realpath(npath, newname);
    if (!apath) {
        if (newname)
            Jsi_Strcpy(newname, apath=npath);
................................................................................
{
    Jsi_Number r = INFINITY;
    return (Jsi_NumberIsNaN(value)==0 && value != r && r != -value);
}

void Jsi_NumberDtoA(Jsi_Interp *interp, Jsi_Number value, char* buf, int bsiz, int prec)
{
    int dp = interp->subOpts.dblPrec, dm = DBL_DECIMAL_DIG;
    if (prec==0)
        prec = (dp<=0?dm+dp:dp);
    else if (prec<0)
            prec = dm+prec;
    if (prec<=0)
        prec = dm-1;
    if (Jsi_NumberIsNaN(value))
................................................................................
    int thrd = 1;
#else
    int thrd = 0;
#endif
    if (Jsi_FunctionReturnIgnored(interp, funcPtr))
        return JSI_OK;
    snprintf(buf, sizeof(buf),
        "{os:\"%s\", platform:\"%s\", hasThreads:%s, pointerSize:%zu, timeSize:%zu "
        "intSize:%zu, wideSize:%zu, numberSize:%zu, crc:%x, isBigEndian:%s, confArgs:\"%s\"}",





        os, platform, thrd?"true":"false", sizeof(void*), sizeof(time_t), sizeof(int),
        sizeof(Jsi_Wide), sizeof(Jsi_Number), Jsi_Crc32(0, (uchar*)crcSizes, sizeof(crcSizes)),
        isBigEndian()? "true" : "false", interp->confArgs);
        
    return Jsi_JSONParse(interp, buf, ret, 0);
}

................................................................................
FSS_Owned, FSS_Isdir, FSS_Isfile };

static Jsi_RC _FileSubstat(Jsi_Interp *interp, Jsi_Value *args, Jsi_Value *_this,
    Jsi_Value **ret, Jsi_Func *funcPtr, int sub)
{
    Jsi_Value *fnam = Jsi_ValueArrayIndex(interp, args, 0);
    int rc;
    Jsi_StatBuf st, lst;

    rc = Jsi_Stat(interp, fnam, &st) | Jsi_Lstat(interp, fnam, &lst);
    if (rc != 0 && sub != FSS_Exists && sub != FSS_Writable && sub != FSS_Readable && sub != FSS_Isdir && sub != FSS_Isfile) {
        if (!interp->subOpts.strictFiles)
            return JSI_OK;
        return Jsi_LogError("file access failed: %s", GSVal(fnam));
    }
    switch (sub) {
        case FSS_Exists: Jsi_ValueMakeBool(interp, ret, (rc == 0)); break;
        case FSS_Atime: Jsi_ValueMakeNumber(interp, ret, st.st_atime); break;
        case FSS_Mtime: Jsi_ValueMakeNumber(interp, ret, st.st_mtime); break;
        case FSS_Writable: Jsi_ValueMakeBool(interp, ret, (Jsi_Access(interp, fnam, W_OK) != -1));  break;
        case FSS_Readable: Jsi_ValueMakeBool(interp, ret, (Jsi_Access(interp, fnam, R_OK) != -1));  break;
        case FSS_Executable:
................................................................................
        flags |= SQLITE_OPEN_FULLMUTEX;
        flags &= ~SQLITE_OPEN_NOMUTEX;
    } else {
        flags &= ~SQLITE_OPEN_FULLMUTEX;
    }
  
    if (SQLITE_OK != sqlite3_open_v2(zFile, &db->db, flags, vfs)) {
        Jsi_LogError("db open failed");
        goto bail;
    }
    //Jsi_DSFree(&translatedFilename);

    if( SQLITE_OK!=sqlite3_errcode(db->db) ) {
        zErrMsg = sqlite3_mprintf("%s", sqlite3_errmsg(db->db));
        DbClose(db->db);
................................................................................
    } else {
        flags &= ~SQLITE_OPEN_FULLMUTEX;
    }
    char cpath[PATH_MAX];
    char *npath = Jsi_FileRealpathStr(NULL, zFile, cpath);
    
    if (SQLITE_OK != sqlite3_open_v2(npath, &db->db, flags, NULL)) {
        JSI_DBQUERY_PRINTF( "db open failed\n");
        goto bail;
    }
    //Jsi_DSFree(&translatedFilename);

    if( SQLITE_OK!=sqlite3_errcode(db->db) ) {
        zErrMsg = sqlite3_mprintf("%s", sqlite3_errmsg(db->db));
        DbClose(db->db);
................................................................................
        if (cmdPtr->clientName || cmdPtr->clientIP) {
            const char *loname = cmdPtr->localhostName;
            if (!loname) loname = "localhost";
            cmdPtr->instCtx = context;
            if (cmdPtr->debug>1)
                fprintf(stderr,  "Received network connect from %s (%s)\n",
                     cmdPtr->clientName, cmdPtr->clientIP);

            if (cmdPtr->local && (cmdPtr->clientName && Jsi_Strcmp(cmdPtr->clientName, loname))) {
                if (cmdPtr->debug>1)
                    fprintf(stderr,  "Dropping non-localhost connection\n");
                return 1;
            }

        }

        if (cmdPtr->maxConnects && cmdPtr->stats.connectCnt>=cmdPtr->maxConnects) {
            if (cmdPtr->debug>1)
                fprintf(stderr, "maxConnects exceeded: rejecting connection <%p>\n", user);
            rc = -1;
        }
................................................................................
        cmdPtr->protocols[JWS_PROTOCOL_WEBSOCK].rx_buffer_size=(1<<cmdPtr->bufferPwr2);
    }

    cmdPtr->pssTable = Jsi_HashNew(interp, JSI_KEYS_ONEWORD, jsi_wsfreePss);
    cmdPtr->info.port = (cmdPtr->client ? CONTEXT_PORT_NO_LISTEN : cmdPtr->port);
    cmdPtr->info.user = cmdPtr;
    cmdPtr->info.iface = cmdPtr->interface ? Jsi_ValueString(interp, cmdPtr->interface, NULL) : NULL;





    cmdPtr->info.protocols = cmdPtr->protocols;
    if (!cmdPtr->noCompress)
        cmdPtr->info.extensions = jsi_lws_exts;

    cmdPtr->info.ssl_cert_filepath = cmdPtr->ssl_cert_filepath;
    cmdPtr->info.ssl_private_key_filepath = cmdPtr->ssl_private_key_filepath;
    cmdPtr->info.gid = cmdPtr->ws_gid;
................................................................................
#ifndef USE_STATIC_STACK
        if ((interp->maxStack-interp->framePtr->Sp)<STACK_MIN_PAD)
            jsiSetupStack(interp);
#endif
        jsiPush(interp,0);
        interp->curIp = ip;
        // Carry forward line/file info from previous OPs.
        if (!ip->Line) {
            ip->Line = curLine;
            ip->fname = curFile;
        } else {
            curLine = ip->Line;

            curFile = ip->fname;
        }
        if (interp->debugOpts.hook) {
            interp->framePtr->fileName = ip->fname;
            interp->framePtr->line = ip->Line;
            if ((rc = (*interp->debugOpts.hook)(interp, ip->fname, ip->Line, interp->framePtr->level, interp->curFunction, jsi_opcode_string(ip->op), ip, NULL)) != JSI_OK)
                break;
        }

        switch(ip->op) {
            case OP_NOP:
            case OP_LASTOP:
                break;






|







 







<







 







|
>
|
|







 







|







 







|







 







|
|
<
<
<











<
<
<








>
>
>
>
>
>
>
>







 







>
>
>

>







 







|







 







|







 







|

>
>
>
>
>







 







|
>

<
<
<
<
<







 







|







 







|







 







>





>







 







>
>
>
>
>







 







|

<
|

>

<

|
|
|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
.....
13323
13324
13325
13326
13327
13328
13329

13330
13331
13332
13333
13334
13335
13336
.....
19101
19102
19103
19104
19105
19106
19107
19108
19109
19110
19111
19112
19113
19114
19115
19116
19117
19118
.....
19154
19155
19156
19157
19158
19159
19160
19161
19162
19163
19164
19165
19166
19167
19168
.....
19452
19453
19454
19455
19456
19457
19458
19459
19460
19461
19462
19463
19464
19465
19466
.....
25525
25526
25527
25528
25529
25530
25531
25532
25533



25534
25535
25536
25537
25538
25539
25540
25541
25542
25543
25544



25545
25546
25547
25548
25549
25550
25551
25552
25553
25554
25555
25556
25557
25558
25559
25560
25561
25562
25563
25564
25565
25566
25567
.....
25601
25602
25603
25604
25605
25606
25607
25608
25609
25610
25611
25612
25613
25614
25615
25616
25617
25618
25619
.....
25711
25712
25713
25714
25715
25716
25717
25718
25719
25720
25721
25722
25723
25724
25725
.....
27021
27022
27023
27024
27025
27026
27027
27028
27029
27030
27031
27032
27033
27034
27035
.....
34834
34835
34836
34837
34838
34839
34840
34841
34842
34843
34844
34845
34846
34847
34848
34849
34850
34851
34852
34853
34854
.....
36777
36778
36779
36780
36781
36782
36783
36784
36785
36786





36787
36788
36789
36790
36791
36792
36793
.....
49344
49345
49346
49347
49348
49349
49350
49351
49352
49353
49354
49355
49356
49357
49358
.....
50187
50188
50189
50190
50191
50192
50193
50194
50195
50196
50197
50198
50199
50200
50201
.....
51825
51826
51827
51828
51829
51830
51831
51832
51833
51834
51835
51836
51837
51838
51839
51840
51841
51842
51843
51844
51845
.....
52808
52809
52810
52811
52812
52813
52814
52815
52816
52817
52818
52819
52820
52821
52822
52823
52824
52825
52826
.....
64130
64131
64132
64133
64134
64135
64136
64137
64138

64139
64140
64141
64142

64143
64144
64145
64146
64147
64148
64149
64150
64151
64152
64153
/* jsi.h : External API header file for Jsi. */
#ifndef __JSI_H__
#define __JSI_H__

#define JSI_VERSION_MAJOR   2
#define JSI_VERSION_MINOR   5
#define JSI_VERSION_RELEASE 24

#define JSI_VERSION (JSI_VERSION_MAJOR + ((Jsi_Number)JSI_VERSION_MINOR/100.0) + ((Jsi_Number)JSI_VERSION_RELEASE/10000.0))

#ifndef JSI_EXTERN
#define JSI_EXTERN extern
#endif

................................................................................
typedef struct {
    bool istty;
    bool noRegex;
    bool noReadline;
    bool noproto;
    bool noCacheOpCodes;
    bool outUndef;

    bool logAllowDups;
    bool logColNums;
    bool privKeys;
    bool compat;
    bool mutexUnlock;
    int dblPrec;
    const char *blacklist;
................................................................................
    if (argc == 1) {
iact:
        if (interp->opts.no_interactive)
            return interp;
        rc = Jsi_Interactive(interp, JSI_OUTPUT_QUOTE|JSI_OUTPUT_NEWLINES);
    } else {
        if (argc == 2 && !Jsi_Strcmp(argv[1], "-h" )) {
            puts("usage: jsish -h/--help | -v/--version | -d/--debug | -D/--debugui\n\t"
            "| -u/--unittest | -U/-UU | -s/--safe | -Z/--zip | -S/--sqliteui\n\t"
            "| -w/--wget | -W/--websrv | -H/--htmli | -J/--jsi | -C/--cssi\n\t"
            "| -c/--cdata | -m/--module | -M/--make | -e/--eval | -t/--tracecall\n\t"
            "| -a/--archive | -T/--typecheck OPT | -IOPT VAL | FILE arg arg ...\nUse --help for long help.");
            return jsi_DoExit(interp, 1);
        }
        if (argc == 2 && !Jsi_Strcmp(argv[1], "--help")) {
            puts("jsish arguments:\n"
              "  -a/--archive FILE\tMount an archive (zip, sqlar or fossil repo) and run module.\n"
              "  -c/--cdata FILE\tGenerate .c or JSON output from a .jsc description.\n"
................................................................................
        }
        if (argc > 2 && (Jsi_Strcmp(argv[1], "--module")==0 || Jsi_Strcmp(argv[1], "-m" )==0)) {
            if (argv[2][0] == '-')
                rc = Jsi_EvalString(interp, "runModule('Jsi_Module');", JSI_EVAL_ISMAIN);
            else {
                Jsi_DString dStr = {};
                const char* cpe = Jsi_Strrchr(argv[2], '.');
                int len = (cpe?cpe-argv[2]:(int)Jsi_Strlen(argv[2]));
                Jsi_DSPrintf(&dStr, "source(\"%s\"); puts(runModule(\"%.*s\",console.args.slice(1)));", argv[2], len, argv[2]);
                rc = Jsi_EvalString(interp, Jsi_DSValue(&dStr), JSI_EVAL_NOSKIPBANG);
                Jsi_DSFree(&dStr);
            }
        }
        else if (argc == 3 && (Jsi_Strcmp(argv[1], "--eval")==0 || Jsi_Strcmp(argv[1], "-e" )==0))
            rc = Jsi_EvalString(interp, argv[2], JSI_EVAL_NOSKIPBANG);
................................................................................
            Jsi_LogError("exceeded max subinterp depth");
            return NULL;
        }
    }
    interp->maxDepth = JSI_MAX_EVAL_DEPTH;
    interp->maxIncDepth = JSI_MAX_INCLUDE_DEPTH;
    interp->typeWarnMax = 50;
    interp->subOpts.dblPrec = __DBL_DECIMAL_DIG__-1;

    int iocnt;
    if (iopts) {
        iopts->interp = interp;
        interp->opts = *iopts;
    }
    interp->logOpts.file = 1;
................................................................................
    char cdbuf[PATH_MAX];
    Jsi_DSInit(dStr);
    if (!path || !path[0]) return NULL;
    if (*path == '/')
        Jsi_DSAppend(dStr, path, NULL);
#ifdef __WIN32  /* TODO: add proper handling for windows paths. */
    else if (*path && path[1] == ':') {
        Jsi_DSAppend(dStr, path, NULL);
        return Jsi_DSValue(dStr);



    }
#endif
    else if (path[0] == '~') {
        Jsi_DSAppend(dStr, jsi_GetHomeDir(interp), (path[1] == '/' ? "" : "/"), path+1, NULL);
    } else if (path[0] == '.' && path[1] == 0) {
        if (jsiIntData.pwd) {
            Jsi_DSAppend(dStr, jsiIntData.pwd, NULL);
        } else {
            Jsi_DSAppend(dStr, getcwd(cdbuf, sizeof(cdbuf)), NULL);
        }
    } else {



        if (jsiIntData.pwd) {
            Jsi_DSAppend(dStr, jsiIntData.pwd, "/", path, NULL);
        } else {
            Jsi_DSAppend(dStr, getcwd(cdbuf, sizeof(cdbuf)), "/", path, NULL);
        }
    }
    Jsi_DString sStr = {};
    char *cp = Jsi_DSValue(dStr);
#ifdef __WIN32
    if (*cp && cp[1] == ':') {
        prefix[0] = *cp;
        prefix[1] = cp[1];
        prefix[2] = 0;
        cp += 2;
    }
#endif
    int i=0, n=0, m, nmax, unclean=0, slens[PATH_MAX];
    char *sp = cp, *ss;
    char *sptrs[PATH_MAX];
    while (*cp && n<PATH_MAX) {
        while (*cp && *cp == '/') {
            cp++;
            if (*cp == '/')
................................................................................
        }
        n--;
    }
    /* TODO: prefix for windows. */
    Jsi_DSAppend(&sStr, prefix, NULL);
    for (i=0; i<nmax; i++) {
        if (slens[i]) {
#ifdef __WIN32
            Jsi_DSAppend(&sStr, "/" /*"\\"*/, NULL);
#else
            Jsi_DSAppend(&sStr, "/", NULL);
#endif
            Jsi_DSAppendLen(&sStr, sptrs[i], slens[i]);
        }
    }
    Jsi_DSSetLength(dStr, 0);
    Jsi_DSAppend(dStr, Jsi_DSValue(&sStr), NULL);
    Jsi_DSFree(&sStr);
    return Jsi_DSValue(dStr);
................................................................................
        const char *homedrv = getenv("HOMEDRIVE");
        if (!homedrv) homedrv = "";
        Jsi_DSAppend(&dStr, homedrv, homedir, path[1] == '/' ? "" : "/", path+1, NULL);
#endif
        npath = Jsi_DSValue(&dStr);
    }
#ifdef __WIN32
    if (Jsi_Strncmp(path, JSI_ZVFS_DIR, sizeof(JSI_ZVFS_DIR)-1)==0 || Jsi_Strncmp(path, JSI_VFS_DIR, sizeof(JSI_VFS_DIR)-1)==0)
        apath = NULL;
    else
#endif
    apath = realpath(npath, newname);
    if (!apath) {
        if (newname)
            Jsi_Strcpy(newname, apath=npath);
................................................................................
{
    Jsi_Number r = INFINITY;
    return (Jsi_NumberIsNaN(value)==0 && value != r && r != -value);
}

void Jsi_NumberDtoA(Jsi_Interp *interp, Jsi_Number value, char* buf, int bsiz, int prec)
{
    int dp = interp->subOpts.dblPrec, dm = __DBL_DECIMAL_DIG__;
    if (prec==0)
        prec = (dp<=0?dm+dp:dp);
    else if (prec<0)
            prec = dm+prec;
    if (prec<=0)
        prec = dm-1;
    if (Jsi_NumberIsNaN(value))
................................................................................
    int thrd = 1;
#else
    int thrd = 0;
#endif
    if (Jsi_FunctionReturnIgnored(interp, funcPtr))
        return JSI_OK;
    snprintf(buf, sizeof(buf),
        "{exeExt:\"%s\", dllExt:\"%s\", os:\"%s\", platform:\"%s\", hasThreads:%s, pointerSize:%zu, timeSize:%zu "
        "intSize:%zu, wideSize:%zu, numberSize:%zu, crc:%x, isBigEndian:%s, confArgs:\"%s\"}",
#ifdef __WIN32
        ".exe", ".dll",
#else
        "", ".so",
#endif
        os, platform, thrd?"true":"false", sizeof(void*), sizeof(time_t), sizeof(int),
        sizeof(Jsi_Wide), sizeof(Jsi_Number), Jsi_Crc32(0, (uchar*)crcSizes, sizeof(crcSizes)),
        isBigEndian()? "true" : "false", interp->confArgs);
        
    return Jsi_JSONParse(interp, buf, ret, 0);
}

................................................................................
FSS_Owned, FSS_Isdir, FSS_Isfile };

static Jsi_RC _FileSubstat(Jsi_Interp *interp, Jsi_Value *args, Jsi_Value *_this,
    Jsi_Value **ret, Jsi_Func *funcPtr, int sub)
{
    Jsi_Value *fnam = Jsi_ValueArrayIndex(interp, args, 0);
    int rc;
    Jsi_StatBuf st = {}, lst = {};
    st.st_uid = -1;
    rc = Jsi_Stat(interp, fnam, &st) | Jsi_Lstat(interp, fnam, &lst);





    switch (sub) {
        case FSS_Exists: Jsi_ValueMakeBool(interp, ret, (rc == 0)); break;
        case FSS_Atime: Jsi_ValueMakeNumber(interp, ret, st.st_atime); break;
        case FSS_Mtime: Jsi_ValueMakeNumber(interp, ret, st.st_mtime); break;
        case FSS_Writable: Jsi_ValueMakeBool(interp, ret, (Jsi_Access(interp, fnam, W_OK) != -1));  break;
        case FSS_Readable: Jsi_ValueMakeBool(interp, ret, (Jsi_Access(interp, fnam, R_OK) != -1));  break;
        case FSS_Executable:
................................................................................
        flags |= SQLITE_OPEN_FULLMUTEX;
        flags &= ~SQLITE_OPEN_NOMUTEX;
    } else {
        flags &= ~SQLITE_OPEN_FULLMUTEX;
    }
  
    if (SQLITE_OK != sqlite3_open_v2(zFile, &db->db, flags, vfs)) {
        Jsi_LogError("db open failed: %s", zFile);
        goto bail;
    }
    //Jsi_DSFree(&translatedFilename);

    if( SQLITE_OK!=sqlite3_errcode(db->db) ) {
        zErrMsg = sqlite3_mprintf("%s", sqlite3_errmsg(db->db));
        DbClose(db->db);
................................................................................
    } else {
        flags &= ~SQLITE_OPEN_FULLMUTEX;
    }
    char cpath[PATH_MAX];
    char *npath = Jsi_FileRealpathStr(NULL, zFile, cpath);
    
    if (SQLITE_OK != sqlite3_open_v2(npath, &db->db, flags, NULL)) {
        JSI_DBQUERY_PRINTF( "db open failed: %s\n", npath);
        goto bail;
    }
    //Jsi_DSFree(&translatedFilename);

    if( SQLITE_OK!=sqlite3_errcode(db->db) ) {
        zErrMsg = sqlite3_mprintf("%s", sqlite3_errmsg(db->db));
        DbClose(db->db);
................................................................................
        if (cmdPtr->clientName || cmdPtr->clientIP) {
            const char *loname = cmdPtr->localhostName;
            if (!loname) loname = "localhost";
            cmdPtr->instCtx = context;
            if (cmdPtr->debug>1)
                fprintf(stderr,  "Received network connect from %s (%s)\n",
                     cmdPtr->clientName, cmdPtr->clientIP);
#ifndef __WIN32
            if (cmdPtr->local && (cmdPtr->clientName && Jsi_Strcmp(cmdPtr->clientName, loname))) {
                if (cmdPtr->debug>1)
                    fprintf(stderr,  "Dropping non-localhost connection\n");
                return 1;
            }
#endif
        }

        if (cmdPtr->maxConnects && cmdPtr->stats.connectCnt>=cmdPtr->maxConnects) {
            if (cmdPtr->debug>1)
                fprintf(stderr, "maxConnects exceeded: rejecting connection <%p>\n", user);
            rc = -1;
        }
................................................................................
        cmdPtr->protocols[JWS_PROTOCOL_WEBSOCK].rx_buffer_size=(1<<cmdPtr->bufferPwr2);
    }

    cmdPtr->pssTable = Jsi_HashNew(interp, JSI_KEYS_ONEWORD, jsi_wsfreePss);
    cmdPtr->info.port = (cmdPtr->client ? CONTEXT_PORT_NO_LISTEN : cmdPtr->port);
    cmdPtr->info.user = cmdPtr;
    cmdPtr->info.iface = cmdPtr->interface ? Jsi_ValueString(interp, cmdPtr->interface, NULL) : NULL;
    if (cmdPtr->local && !cmdPtr->info.iface)
        cmdPtr->info.iface = "lo";
#ifdef __WIN32
    cmdPtr->info.iface = NULL;
#endif
    cmdPtr->info.protocols = cmdPtr->protocols;
    if (!cmdPtr->noCompress)
        cmdPtr->info.extensions = jsi_lws_exts;

    cmdPtr->info.ssl_cert_filepath = cmdPtr->ssl_cert_filepath;
    cmdPtr->info.ssl_private_key_filepath = cmdPtr->ssl_private_key_filepath;
    cmdPtr->info.gid = cmdPtr->ws_gid;
................................................................................
#ifndef USE_STATIC_STACK
        if ((interp->maxStack-interp->framePtr->Sp)<STACK_MIN_PAD)
            jsiSetupStack(interp);
#endif
        jsiPush(interp,0);
        interp->curIp = ip;
        // Carry forward line/file info from previous OPs.
        if (!ip->Line)
            ip->Line = curLine;

        else
            curLine = ip->Line;
        if (ip->fname)
            curFile = ip->fname;

        if (interp->debugOpts.hook) {
            interp->framePtr->fileName = curFile;
            interp->framePtr->line = curLine;
            if ((rc = (*interp->debugOpts.hook)(interp, curFile, curLine, interp->framePtr->level, interp->curFunction, jsi_opcode_string(ip->op), ip, NULL)) != JSI_OK)
                break;
        }

        switch(ip->op) {
            case OP_NOP:
            case OP_LASTOP:
                break;

Changes to src/jsi.h.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
/* jsi.h : External API header file for Jsi. */
#ifndef __JSI_H__
#define __JSI_H__

#define JSI_VERSION_MAJOR   2
#define JSI_VERSION_MINOR   5
#define JSI_VERSION_RELEASE 23

#define JSI_VERSION (JSI_VERSION_MAJOR + ((Jsi_Number)JSI_VERSION_MINOR/100.0) + ((Jsi_Number)JSI_VERSION_RELEASE/10000.0))

#ifndef JSI_EXTERN
#define JSI_EXTERN extern
#endif







|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
/* jsi.h : External API header file for Jsi. */
#ifndef __JSI_H__
#define __JSI_H__

#define JSI_VERSION_MAJOR   2
#define JSI_VERSION_MINOR   5
#define JSI_VERSION_RELEASE 24

#define JSI_VERSION (JSI_VERSION_MAJOR + ((Jsi_Number)JSI_VERSION_MINOR/100.0) + ((Jsi_Number)JSI_VERSION_RELEASE/10000.0))

#ifndef JSI_EXTERN
#define JSI_EXTERN extern
#endif

Changes to src/jsiCmds.c.

2563
2564
2565
2566
2567
2568
2569
2570
2571





2572
2573
2574
2575
2576
2577
2578
    int thrd = 1;
#else
    int thrd = 0;
#endif
    if (Jsi_FunctionReturnIgnored(interp, funcPtr))
        return JSI_OK;
    snprintf(buf, sizeof(buf),
        "{os:\"%s\", platform:\"%s\", hasThreads:%s, pointerSize:%zu, timeSize:%zu "
        "intSize:%zu, wideSize:%zu, numberSize:%zu, crc:%x, isBigEndian:%s, confArgs:\"%s\"}",





        os, platform, thrd?"true":"false", sizeof(void*), sizeof(time_t), sizeof(int),
        sizeof(Jsi_Wide), sizeof(Jsi_Number), Jsi_Crc32(0, (uchar*)crcSizes, sizeof(crcSizes)),
        isBigEndian()? "true" : "false", interp->confArgs);
        
    return Jsi_JSONParse(interp, buf, ret, 0);
}








|

>
>
>
>
>







2563
2564
2565
2566
2567
2568
2569
2570
2571
2572
2573
2574
2575
2576
2577
2578
2579
2580
2581
2582
2583
    int thrd = 1;
#else
    int thrd = 0;
#endif
    if (Jsi_FunctionReturnIgnored(interp, funcPtr))
        return JSI_OK;
    snprintf(buf, sizeof(buf),
        "{exeExt:\"%s\", dllExt:\"%s\", os:\"%s\", platform:\"%s\", hasThreads:%s, pointerSize:%zu, timeSize:%zu "
        "intSize:%zu, wideSize:%zu, numberSize:%zu, crc:%x, isBigEndian:%s, confArgs:\"%s\"}",
#ifdef __WIN32
        ".exe", ".dll",
#else
        "", ".so",
#endif
        os, platform, thrd?"true":"false", sizeof(void*), sizeof(time_t), sizeof(int),
        sizeof(Jsi_Wide), sizeof(Jsi_Number), Jsi_Crc32(0, (uchar*)crcSizes, sizeof(crcSizes)),
        isBigEndian()? "true" : "false", interp->confArgs);
        
    return Jsi_JSONParse(interp, buf, ret, 0);
}

Changes to src/jsiEval.c.

1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192

1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
#ifndef USE_STATIC_STACK
        if ((interp->maxStack-interp->framePtr->Sp)<STACK_MIN_PAD)
            jsiSetupStack(interp);
#endif
        jsiPush(interp,0);
        interp->curIp = ip;
        // Carry forward line/file info from previous OPs.
        if (!ip->Line) {
            ip->Line = curLine;
            ip->fname = curFile;
        } else {
            curLine = ip->Line;

            curFile = ip->fname;
        }
        if (interp->debugOpts.hook) {
            interp->framePtr->fileName = ip->fname;
            interp->framePtr->line = ip->Line;
            if ((rc = (*interp->debugOpts.hook)(interp, ip->fname, ip->Line, interp->framePtr->level, interp->curFunction, jsi_opcode_string(ip->op), ip, NULL)) != JSI_OK)
                break;
        }

        switch(ip->op) {
            case OP_NOP:
            case OP_LASTOP:
                break;







|

<
|

>

<

|
|
|







1181
1182
1183
1184
1185
1186
1187
1188
1189

1190
1191
1192
1193

1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
#ifndef USE_STATIC_STACK
        if ((interp->maxStack-interp->framePtr->Sp)<STACK_MIN_PAD)
            jsiSetupStack(interp);
#endif
        jsiPush(interp,0);
        interp->curIp = ip;
        // Carry forward line/file info from previous OPs.
        if (!ip->Line)
            ip->Line = curLine;

        else
            curLine = ip->Line;
        if (ip->fname)
            curFile = ip->fname;

        if (interp->debugOpts.hook) {
            interp->framePtr->fileName = curFile;
            interp->framePtr->line = curLine;
            if ((rc = (*interp->debugOpts.hook)(interp, curFile, curLine, interp->framePtr->level, interp->curFunction, jsi_opcode_string(ip->op), ip, NULL)) != JSI_OK)
                break;
        }

        switch(ip->op) {
            case OP_NOP:
            case OP_LASTOP:
                break;

Changes to src/jsiFileCmds.c.

133
134
135
136
137
138
139
140

141
142
143
144
145
146
147
148
149
150
151
152
153
FSS_Owned, FSS_Isdir, FSS_Isfile };

static Jsi_RC _FileSubstat(Jsi_Interp *interp, Jsi_Value *args, Jsi_Value *_this,
    Jsi_Value **ret, Jsi_Func *funcPtr, int sub)
{
    Jsi_Value *fnam = Jsi_ValueArrayIndex(interp, args, 0);
    int rc;
    Jsi_StatBuf st, lst;

    rc = Jsi_Stat(interp, fnam, &st) | Jsi_Lstat(interp, fnam, &lst);
    if (rc != 0 && sub != FSS_Exists && sub != FSS_Writable && sub != FSS_Readable && sub != FSS_Isdir && sub != FSS_Isfile) {
        if (!interp->subOpts.strictFiles)
            return JSI_OK;
        return Jsi_LogError("file access failed: %s", GSVal(fnam));
    }
    switch (sub) {
        case FSS_Exists: Jsi_ValueMakeBool(interp, ret, (rc == 0)); break;
        case FSS_Atime: Jsi_ValueMakeNumber(interp, ret, st.st_atime); break;
        case FSS_Mtime: Jsi_ValueMakeNumber(interp, ret, st.st_mtime); break;
        case FSS_Writable: Jsi_ValueMakeBool(interp, ret, (Jsi_Access(interp, fnam, W_OK) != -1));  break;
        case FSS_Readable: Jsi_ValueMakeBool(interp, ret, (Jsi_Access(interp, fnam, R_OK) != -1));  break;
        case FSS_Executable:







|
>

<
<
<
<
<







133
134
135
136
137
138
139
140
141
142





143
144
145
146
147
148
149
FSS_Owned, FSS_Isdir, FSS_Isfile };

static Jsi_RC _FileSubstat(Jsi_Interp *interp, Jsi_Value *args, Jsi_Value *_this,
    Jsi_Value **ret, Jsi_Func *funcPtr, int sub)
{
    Jsi_Value *fnam = Jsi_ValueArrayIndex(interp, args, 0);
    int rc;
    Jsi_StatBuf st = {}, lst = {};
    st.st_uid = -1;
    rc = Jsi_Stat(interp, fnam, &st) | Jsi_Lstat(interp, fnam, &lst);





    switch (sub) {
        case FSS_Exists: Jsi_ValueMakeBool(interp, ret, (rc == 0)); break;
        case FSS_Atime: Jsi_ValueMakeNumber(interp, ret, st.st_atime); break;
        case FSS_Mtime: Jsi_ValueMakeNumber(interp, ret, st.st_mtime); break;
        case FSS_Writable: Jsi_ValueMakeBool(interp, ret, (Jsi_Access(interp, fnam, W_OK) != -1));  break;
        case FSS_Readable: Jsi_ValueMakeBool(interp, ret, (Jsi_Access(interp, fnam, R_OK) != -1));  break;
        case FSS_Executable:

Changes to src/jsiFilesys.c.

1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199








1200
1201
1202
1203
1204
1205
1206
....
1240
1241
1242
1243
1244
1245
1246



1247

1248
1249
1250
1251
1252
1253
1254
....
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
    char cdbuf[PATH_MAX];
    Jsi_DSInit(dStr);
    if (!path || !path[0]) return NULL;
    if (*path == '/')
        Jsi_DSAppend(dStr, path, NULL);
#ifdef __WIN32  /* TODO: add proper handling for windows paths. */
    else if (*path && path[1] == ':') {
        prefix[0] = *path;
        prefix[1] = path[1];
        prefix[2] = 0;
        path += 2;
        goto full;
    }
#endif
    else if (path[0] == '~') {
        Jsi_DSAppend(dStr, jsi_GetHomeDir(interp), (path[1] == '/' ? "" : "/"), path+1, NULL);
    } else if (path[0] == '.' && path[1] == 0) {
        if (jsiIntData.pwd) {
            Jsi_DSAppend(dStr, jsiIntData.pwd, NULL);
        } else {
            Jsi_DSAppend(dStr, getcwd(cdbuf, sizeof(cdbuf)), NULL);
        }
    } else {
#ifdef __WIN32
full:
#endif
        if (jsiIntData.pwd) {
            Jsi_DSAppend(dStr, jsiIntData.pwd, "/", path, NULL);
        } else {
            Jsi_DSAppend(dStr, getcwd(cdbuf, sizeof(cdbuf)), "/", path, NULL);
        }
    }
    Jsi_DString sStr = {};
    char *cp = Jsi_DSValue(dStr);








    int i=0, n=0, m, nmax, unclean=0, slens[PATH_MAX];
    char *sp = cp, *ss;
    char *sptrs[PATH_MAX];
    while (*cp && n<PATH_MAX) {
        while (*cp && *cp == '/') {
            cp++;
            if (*cp == '/')
................................................................................
        }
        n--;
    }
    /* TODO: prefix for windows. */
    Jsi_DSAppend(&sStr, prefix, NULL);
    for (i=0; i<nmax; i++) {
        if (slens[i]) {



            Jsi_DSAppend(&sStr, "/", NULL);

            Jsi_DSAppendLen(&sStr, sptrs[i], slens[i]);
        }
    }
    Jsi_DSSetLength(dStr, 0);
    Jsi_DSAppend(dStr, Jsi_DSValue(&sStr), NULL);
    Jsi_DSFree(&sStr);
    return Jsi_DSValue(dStr);
................................................................................
        const char *homedrv = getenv("HOMEDRIVE");
        if (!homedrv) homedrv = "";
        Jsi_DSAppend(&dStr, homedrv, homedir, path[1] == '/' ? "" : "/", path+1, NULL);
#endif
        npath = Jsi_DSValue(&dStr);
    }
#ifdef __WIN32
    if (Jsi_Strncmp(path, "/zvfs", 5)==0)
        apath = NULL;
    else
#endif
    apath = realpath(npath, newname);
    if (!apath) {
        if (newname)
            Jsi_Strcpy(newname, apath=npath);







|
|
<
<
<











<
<
<








>
>
>
>
>
>
>
>







 







>
>
>

>







 







|







1166
1167
1168
1169
1170
1171
1172
1173
1174



1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185



1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
....
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
....
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
    char cdbuf[PATH_MAX];
    Jsi_DSInit(dStr);
    if (!path || !path[0]) return NULL;
    if (*path == '/')
        Jsi_DSAppend(dStr, path, NULL);
#ifdef __WIN32  /* TODO: add proper handling for windows paths. */
    else if (*path && path[1] == ':') {
        Jsi_DSAppend(dStr, path, NULL);
        return Jsi_DSValue(dStr);



    }
#endif
    else if (path[0] == '~') {
        Jsi_DSAppend(dStr, jsi_GetHomeDir(interp), (path[1] == '/' ? "" : "/"), path+1, NULL);
    } else if (path[0] == '.' && path[1] == 0) {
        if (jsiIntData.pwd) {
            Jsi_DSAppend(dStr, jsiIntData.pwd, NULL);
        } else {
            Jsi_DSAppend(dStr, getcwd(cdbuf, sizeof(cdbuf)), NULL);
        }
    } else {



        if (jsiIntData.pwd) {
            Jsi_DSAppend(dStr, jsiIntData.pwd, "/", path, NULL);
        } else {
            Jsi_DSAppend(dStr, getcwd(cdbuf, sizeof(cdbuf)), "/", path, NULL);
        }
    }
    Jsi_DString sStr = {};
    char *cp = Jsi_DSValue(dStr);
#ifdef __WIN32
    if (*cp && cp[1] == ':') {
        prefix[0] = *cp;
        prefix[1] = cp[1];
        prefix[2] = 0;
        cp += 2;
    }
#endif
    int i=0, n=0, m, nmax, unclean=0, slens[PATH_MAX];
    char *sp = cp, *ss;
    char *sptrs[PATH_MAX];
    while (*cp && n<PATH_MAX) {
        while (*cp && *cp == '/') {
            cp++;
            if (*cp == '/')
................................................................................
        }
        n--;
    }
    /* TODO: prefix for windows. */
    Jsi_DSAppend(&sStr, prefix, NULL);
    for (i=0; i<nmax; i++) {
        if (slens[i]) {
#ifdef __WIN32
            Jsi_DSAppend(&sStr, "/" /*"\\"*/, NULL);
#else
            Jsi_DSAppend(&sStr, "/", NULL);
#endif
            Jsi_DSAppendLen(&sStr, sptrs[i], slens[i]);
        }
    }
    Jsi_DSSetLength(dStr, 0);
    Jsi_DSAppend(dStr, Jsi_DSValue(&sStr), NULL);
    Jsi_DSFree(&sStr);
    return Jsi_DSValue(dStr);
................................................................................
        const char *homedrv = getenv("HOMEDRIVE");
        if (!homedrv) homedrv = "";
        Jsi_DSAppend(&dStr, homedrv, homedir, path[1] == '/' ? "" : "/", path+1, NULL);
#endif
        npath = Jsi_DSValue(&dStr);
    }
#ifdef __WIN32
    if (Jsi_Strncmp(path, JSI_ZVFS_DIR, sizeof(JSI_ZVFS_DIR)-1)==0 || Jsi_Strncmp(path, JSI_VFS_DIR, sizeof(JSI_VFS_DIR)-1)==0)
        apath = NULL;
    else
#endif
    apath = realpath(npath, newname);
    if (!apath) {
        if (newname)
            Jsi_Strcpy(newname, apath=npath);

Changes to src/jsiInt.h.

1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
typedef struct {
    bool istty;
    bool noRegex;
    bool noReadline;
    bool noproto;
    bool noCacheOpCodes;
    bool outUndef;
    bool strictFiles;
    bool logAllowDups;
    bool logColNums;
    bool privKeys;
    bool compat;
    bool mutexUnlock;
    int dblPrec;
    const char *blacklist;







<







1002
1003
1004
1005
1006
1007
1008

1009
1010
1011
1012
1013
1014
1015
typedef struct {
    bool istty;
    bool noRegex;
    bool noReadline;
    bool noproto;
    bool noCacheOpCodes;
    bool outUndef;

    bool logAllowDups;
    bool logColNums;
    bool privKeys;
    bool compat;
    bool mutexUnlock;
    int dblPrec;
    const char *blacklist;

Changes to src/jsiInterp.c.

673
674
675
676
677
678
679
680

681
682
683
684
685
686
687
688
689
...
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
....
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
    if (argc == 1) {
iact:
        if (interp->opts.no_interactive)
            return interp;
        rc = Jsi_Interactive(interp, JSI_OUTPUT_QUOTE|JSI_OUTPUT_NEWLINES);
    } else {
        if (argc == 2 && !Jsi_Strcmp(argv[1], "-h" )) {
            puts("usage: jsish -h/--help | -v/--version | -d/--debug | -D/--debugui | -u/--unittest | -U/-UU\n\t"

            "| -s/--safe | -Z/--zip | -S/--sqliteui | -w/--wget | -W/--websrv | -H/--htmli | -J/--jsi\n\t"
            "| -C/--cssi | -c/--cdata | -m/--module | -M/--make | -e/--eval | -t/--tracecall\n\t"
            "| -a/--archive | -T/--typecheck OPT | -IOPT VAL | FILE arg arg ...\nUse --help for long help.");
            return jsi_DoExit(interp, 1);
        }
        if (argc == 2 && !Jsi_Strcmp(argv[1], "--help")) {
            puts("jsish arguments:\n"
              "  -a/--archive FILE\tMount an archive (zip, sqlar or fossil repo) and run module.\n"
              "  -c/--cdata FILE\tGenerate .c or JSON output from a .jsc description.\n"
................................................................................
        }
        if (argc > 2 && (Jsi_Strcmp(argv[1], "--module")==0 || Jsi_Strcmp(argv[1], "-m" )==0)) {
            if (argv[2][0] == '-')
                rc = Jsi_EvalString(interp, "runModule('Jsi_Module');", JSI_EVAL_ISMAIN);
            else {
                Jsi_DString dStr = {};
                const char* cpe = Jsi_Strrchr(argv[2], '.');
                int len = (cpe?cpe-argv[2]:Jsi_Strlen(argv[2]));
                Jsi_DSPrintf(&dStr, "source(\"%s\"); puts(runModule(\"%.*s\",console.args.slice(1)));", argv[2], len, argv[2]);
                rc = Jsi_EvalString(interp, Jsi_DSValue(&dStr), JSI_EVAL_NOSKIPBANG);
                Jsi_DSFree(&dStr);
            }
        }
        else if (argc == 3 && (Jsi_Strcmp(argv[1], "--eval")==0 || Jsi_Strcmp(argv[1], "-e" )==0))
            rc = Jsi_EvalString(interp, argv[2], JSI_EVAL_NOSKIPBANG);
................................................................................
            Jsi_LogError("exceeded max subinterp depth");
            return NULL;
        }
    }
    interp->maxDepth = JSI_MAX_EVAL_DEPTH;
    interp->maxIncDepth = JSI_MAX_INCLUDE_DEPTH;
    interp->typeWarnMax = 50;
    interp->subOpts.dblPrec = DBL_DECIMAL_DIG-1;

    int iocnt;
    if (iopts) {
        iopts->interp = interp;
        interp->opts = *iopts;
    }
    interp->logOpts.file = 1;







|
>
|
|







 







|







 







|







673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
...
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
....
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
    if (argc == 1) {
iact:
        if (interp->opts.no_interactive)
            return interp;
        rc = Jsi_Interactive(interp, JSI_OUTPUT_QUOTE|JSI_OUTPUT_NEWLINES);
    } else {
        if (argc == 2 && !Jsi_Strcmp(argv[1], "-h" )) {
            puts("usage: jsish -h/--help | -v/--version | -d/--debug | -D/--debugui\n\t"
            "| -u/--unittest | -U/-UU | -s/--safe | -Z/--zip | -S/--sqliteui\n\t"
            "| -w/--wget | -W/--websrv | -H/--htmli | -J/--jsi | -C/--cssi\n\t"
            "| -c/--cdata | -m/--module | -M/--make | -e/--eval | -t/--tracecall\n\t"
            "| -a/--archive | -T/--typecheck OPT | -IOPT VAL | FILE arg arg ...\nUse --help for long help.");
            return jsi_DoExit(interp, 1);
        }
        if (argc == 2 && !Jsi_Strcmp(argv[1], "--help")) {
            puts("jsish arguments:\n"
              "  -a/--archive FILE\tMount an archive (zip, sqlar or fossil repo) and run module.\n"
              "  -c/--cdata FILE\tGenerate .c or JSON output from a .jsc description.\n"
................................................................................
        }
        if (argc > 2 && (Jsi_Strcmp(argv[1], "--module")==0 || Jsi_Strcmp(argv[1], "-m" )==0)) {
            if (argv[2][0] == '-')
                rc = Jsi_EvalString(interp, "runModule('Jsi_Module');", JSI_EVAL_ISMAIN);
            else {
                Jsi_DString dStr = {};
                const char* cpe = Jsi_Strrchr(argv[2], '.');
                int len = (cpe?cpe-argv[2]:(int)Jsi_Strlen(argv[2]));
                Jsi_DSPrintf(&dStr, "source(\"%s\"); puts(runModule(\"%.*s\",console.args.slice(1)));", argv[2], len, argv[2]);
                rc = Jsi_EvalString(interp, Jsi_DSValue(&dStr), JSI_EVAL_NOSKIPBANG);
                Jsi_DSFree(&dStr);
            }
        }
        else if (argc == 3 && (Jsi_Strcmp(argv[1], "--eval")==0 || Jsi_Strcmp(argv[1], "-e" )==0))
            rc = Jsi_EvalString(interp, argv[2], JSI_EVAL_NOSKIPBANG);
................................................................................
            Jsi_LogError("exceeded max subinterp depth");
            return NULL;
        }
    }
    interp->maxDepth = JSI_MAX_EVAL_DEPTH;
    interp->maxIncDepth = JSI_MAX_INCLUDE_DEPTH;
    interp->typeWarnMax = 50;
    interp->subOpts.dblPrec = __DBL_DECIMAL_DIG__-1;

    int iocnt;
    if (iopts) {
        iopts->interp = interp;
        interp->opts = *iopts;
    }
    interp->logOpts.file = 1;

Changes to src/jsiNumber.c.

57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
{
    Jsi_Number r = INFINITY;
    return (Jsi_NumberIsNaN(value)==0 && value != r && r != -value);
}

void Jsi_NumberDtoA(Jsi_Interp *interp, Jsi_Number value, char* buf, int bsiz, int prec)
{
    int dp = interp->subOpts.dblPrec, dm = DBL_DECIMAL_DIG;
    if (prec==0)
        prec = (dp<=0?dm+dp:dp);
    else if (prec<0)
            prec = dm+prec;
    if (prec<=0)
        prec = dm-1;
    if (Jsi_NumberIsNaN(value))







|







57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
{
    Jsi_Number r = INFINITY;
    return (Jsi_NumberIsNaN(value)==0 && value != r && r != -value);
}

void Jsi_NumberDtoA(Jsi_Interp *interp, Jsi_Number value, char* buf, int bsiz, int prec)
{
    int dp = interp->subOpts.dblPrec, dm = __DBL_DECIMAL_DIG__;
    if (prec==0)
        prec = (dp<=0?dm+dp:dp);
    else if (prec<0)
            prec = dm+prec;
    if (prec<=0)
        prec = dm-1;
    if (Jsi_NumberIsNaN(value))

Changes to src/jsiSqlite.c.

3630
3631
3632
3633
3634
3635
3636
3637
3638
3639
3640
3641
3642
3643
3644
....
4473
4474
4475
4476
4477
4478
4479
4480
4481
4482
4483
4484
4485
4486
4487
        flags |= SQLITE_OPEN_FULLMUTEX;
        flags &= ~SQLITE_OPEN_NOMUTEX;
    } else {
        flags &= ~SQLITE_OPEN_FULLMUTEX;
    }
  
    if (SQLITE_OK != sqlite3_open_v2(zFile, &db->db, flags, vfs)) {
        Jsi_LogError("db open failed");
        goto bail;
    }
    //Jsi_DSFree(&translatedFilename);

    if( SQLITE_OK!=sqlite3_errcode(db->db) ) {
        zErrMsg = sqlite3_mprintf("%s", sqlite3_errmsg(db->db));
        DbClose(db->db);
................................................................................
    } else {
        flags &= ~SQLITE_OPEN_FULLMUTEX;
    }
    char cpath[PATH_MAX];
    char *npath = Jsi_FileRealpathStr(NULL, zFile, cpath);
    
    if (SQLITE_OK != sqlite3_open_v2(npath, &db->db, flags, NULL)) {
        JSI_DBQUERY_PRINTF( "db open failed\n");
        goto bail;
    }
    //Jsi_DSFree(&translatedFilename);

    if( SQLITE_OK!=sqlite3_errcode(db->db) ) {
        zErrMsg = sqlite3_mprintf("%s", sqlite3_errmsg(db->db));
        DbClose(db->db);







|







 







|







3630
3631
3632
3633
3634
3635
3636
3637
3638
3639
3640
3641
3642
3643
3644
....
4473
4474
4475
4476
4477
4478
4479
4480
4481
4482
4483
4484
4485
4486
4487
        flags |= SQLITE_OPEN_FULLMUTEX;
        flags &= ~SQLITE_OPEN_NOMUTEX;
    } else {
        flags &= ~SQLITE_OPEN_FULLMUTEX;
    }
  
    if (SQLITE_OK != sqlite3_open_v2(zFile, &db->db, flags, vfs)) {
        Jsi_LogError("db open failed: %s", zFile);
        goto bail;
    }
    //Jsi_DSFree(&translatedFilename);

    if( SQLITE_OK!=sqlite3_errcode(db->db) ) {
        zErrMsg = sqlite3_mprintf("%s", sqlite3_errmsg(db->db));
        DbClose(db->db);
................................................................................
    } else {
        flags &= ~SQLITE_OPEN_FULLMUTEX;
    }
    char cpath[PATH_MAX];
    char *npath = Jsi_FileRealpathStr(NULL, zFile, cpath);
    
    if (SQLITE_OK != sqlite3_open_v2(npath, &db->db, flags, NULL)) {
        JSI_DBQUERY_PRINTF( "db open failed: %s\n", npath);
        goto bail;
    }
    //Jsi_DSFree(&translatedFilename);

    if( SQLITE_OK!=sqlite3_errcode(db->db) ) {
        zErrMsg = sqlite3_mprintf("%s", sqlite3_errmsg(db->db));
        DbClose(db->db);

Changes to src/jsiWebSocket.c.

1519
1520
1521
1522
1523
1524
1525

1526
1527
1528
1529
1530

1531
1532
1533
1534
1535
1536
1537
....
2500
2501
2502
2503
2504
2505
2506





2507
2508
2509
2510
2511
2512
2513
        if (cmdPtr->clientName || cmdPtr->clientIP) {
            const char *loname = cmdPtr->localhostName;
            if (!loname) loname = "localhost";
            cmdPtr->instCtx = context;
            if (cmdPtr->debug>1)
                fprintf(stderr,  "Received network connect from %s (%s)\n",
                     cmdPtr->clientName, cmdPtr->clientIP);

            if (cmdPtr->local && (cmdPtr->clientName && Jsi_Strcmp(cmdPtr->clientName, loname))) {
                if (cmdPtr->debug>1)
                    fprintf(stderr,  "Dropping non-localhost connection\n");
                return 1;
            }

        }

        if (cmdPtr->maxConnects && cmdPtr->stats.connectCnt>=cmdPtr->maxConnects) {
            if (cmdPtr->debug>1)
                fprintf(stderr, "maxConnects exceeded: rejecting connection <%p>\n", user);
            rc = -1;
        }
................................................................................
        cmdPtr->protocols[JWS_PROTOCOL_WEBSOCK].rx_buffer_size=(1<<cmdPtr->bufferPwr2);
    }

    cmdPtr->pssTable = Jsi_HashNew(interp, JSI_KEYS_ONEWORD, jsi_wsfreePss);
    cmdPtr->info.port = (cmdPtr->client ? CONTEXT_PORT_NO_LISTEN : cmdPtr->port);
    cmdPtr->info.user = cmdPtr;
    cmdPtr->info.iface = cmdPtr->interface ? Jsi_ValueString(interp, cmdPtr->interface, NULL) : NULL;





    cmdPtr->info.protocols = cmdPtr->protocols;
    if (!cmdPtr->noCompress)
        cmdPtr->info.extensions = jsi_lws_exts;

    cmdPtr->info.ssl_cert_filepath = cmdPtr->ssl_cert_filepath;
    cmdPtr->info.ssl_private_key_filepath = cmdPtr->ssl_private_key_filepath;
    cmdPtr->info.gid = cmdPtr->ws_gid;







>





>







 







>
>
>
>
>







1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
....
2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519
2520
        if (cmdPtr->clientName || cmdPtr->clientIP) {
            const char *loname = cmdPtr->localhostName;
            if (!loname) loname = "localhost";
            cmdPtr->instCtx = context;
            if (cmdPtr->debug>1)
                fprintf(stderr,  "Received network connect from %s (%s)\n",
                     cmdPtr->clientName, cmdPtr->clientIP);
#ifndef __WIN32
            if (cmdPtr->local && (cmdPtr->clientName && Jsi_Strcmp(cmdPtr->clientName, loname))) {
                if (cmdPtr->debug>1)
                    fprintf(stderr,  "Dropping non-localhost connection\n");
                return 1;
            }
#endif
        }

        if (cmdPtr->maxConnects && cmdPtr->stats.connectCnt>=cmdPtr->maxConnects) {
            if (cmdPtr->debug>1)
                fprintf(stderr, "maxConnects exceeded: rejecting connection <%p>\n", user);
            rc = -1;
        }
................................................................................
        cmdPtr->protocols[JWS_PROTOCOL_WEBSOCK].rx_buffer_size=(1<<cmdPtr->bufferPwr2);
    }

    cmdPtr->pssTable = Jsi_HashNew(interp, JSI_KEYS_ONEWORD, jsi_wsfreePss);
    cmdPtr->info.port = (cmdPtr->client ? CONTEXT_PORT_NO_LISTEN : cmdPtr->port);
    cmdPtr->info.user = cmdPtr;
    cmdPtr->info.iface = cmdPtr->interface ? Jsi_ValueString(interp, cmdPtr->interface, NULL) : NULL;
    if (cmdPtr->local && !cmdPtr->info.iface)
        cmdPtr->info.iface = "lo";
#ifdef __WIN32
    cmdPtr->info.iface = NULL;
#endif
    cmdPtr->info.protocols = cmdPtr->protocols;
    if (!cmdPtr->noCompress)
        cmdPtr->info.extensions = jsi_lws_exts;

    cmdPtr->info.ssl_cert_filepath = cmdPtr->ssl_cert_filepath;
    cmdPtr->info.ssl_private_key_filepath = cmdPtr->ssl_private_key_filepath;
    cmdPtr->info.gid = cmdPtr->ws_gid;

Changes to tools/configure.js.

158
159
160
161
162
163
164
165
166
167








168
169
170
171
172
173
174
...
218
219
220
221
222
223
224




225
226
227
228
229
230
231
232
                s+=dumpSub(Conf.target);
        }
        return s;
    }
    
    // Parse command line arguments.
    function parseArgs() {
        var icnt = 0;
        for (var ai=0; ai<input.length; ai++) {
            var farg = input[ai];








            if (!farg.match(/^--/))
                throw("Options must start with --: "+farg);
            var copt=farg.substr(2),
                cslist=copt.split('='),
                cpre=cslist[0],
                carg=cslist[1];
            if ((copt.indexOf('=')>=0 && cslist[1] === undefined) ||
................................................................................
                    exit(0);
                    break;
                case 'config':
                    if (icnt++>100)
                        throw("loop bug");
                    if (carg === 'default')
                        break;;




                    var fn = 'Configs/make_'+carg+'.conf';
                    if (!File.exists(fn)) {
                        var tlst = [], flst = File.glob('Configs/make_*.conf');
                        for (var i in flst) {
                            var fnv = File.rootname(File.tail(flst[i])).split('_')[1];
                            tlst.push(fnv);
                        }
                        puts('Bad --config.  Not one of: '+tlst.sort().join(', '));







|
|
|
>
>
>
>
>
>
>
>







 







>
>
>
>
|







158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
...
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
                s+=dumpSub(Conf.target);
        }
        return s;
    }
    
    // Parse command line arguments.
    function parseArgs() {
        var ai, farg, icnt = 0;
        for (ai=0; ai<input.length; ai++) {
            farg = input[ai];
            if (farg.match(/^--config=/))
                break;
        }
        if (ai>=input.length) {
            input.unshift('--config=.');
        }
        for (ai=0; ai<input.length; ai++) {
            farg = input[ai];
            if (!farg.match(/^--/))
                throw("Options must start with --: "+farg);
            var copt=farg.substr(2),
                cslist=copt.split('='),
                cpre=cslist[0],
                carg=cslist[1];
            if ((copt.indexOf('=')>=0 && cslist[1] === undefined) ||
................................................................................
                    exit(0);
                    break;
                case 'config':
                    if (icnt++>100)
                        throw("loop bug");
                    if (carg === 'default')
                        break;;
                    var fn;
                    if (carg == "." && File.exists('make.conf'))
                        fn = 'make.conf';
                    else
                        fn = 'Configs/make_'+carg+'.conf';
                    if (!File.exists(fn)) {
                        var tlst = [], flst = File.glob('Configs/make_*.conf');
                        for (var i in flst) {
                            var fnv = File.rootname(File.tail(flst[i])).split('_')[1];
                            tlst.push(fnv);
                        }
                        puts('Bad --config.  Not one of: '+tlst.sort().join(', '));

Changes to tools/protos.jsi.

1
2
3
4
5
6
7
8
//JSI Command Prototypes: version 2.5.23
throw("NOT EXECUTABLE: USE FILE IN GEANY EDITOR FOR CMD LINE COMPLETION + GOTO TAG");

var Array = function(cmd,args) {};
Array.prototype.concat = function(...):array {};
Array.prototype.every = function(callback:function):any {};
Array.prototype.fill = function(value:any, start:number=0, end:number=-1):array {};
Array.prototype.filter = function(callback:function, this:object=void):array {};
|







1
2
3
4
5
6
7
8
//JSI Command Prototypes: version 2.5.24
throw("NOT EXECUTABLE: USE FILE IN GEANY EDITOR FOR CMD LINE COMPLETION + GOTO TAG");

var Array = function(cmd,args) {};
Array.prototype.concat = function(...):array {};
Array.prototype.every = function(callback:function):any {};
Array.prototype.fill = function(value:any, start:number=0, end:number=-1):array {};
Array.prototype.filter = function(callback:function, this:object=void):array {};

Changes to www/archive.wiki.

57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
    <nowiki><pre class=verbatim>
<b>wget -O jsiapp.zip</b> http://jsish.org/jsiapp/zip
</pre></nowiki>

or you can use:

    <nowiki><pre class=verbatim>
<b>jsish -w</b> -out jsiapp.zip http://jsish.org/jsiapp/zip
</pre></nowiki>

Alternatively the [http://jsish.org/jsiapp|fossil UI] supports
<b>Zip Archive</b> download.

<h3 id=zip>Sqlar Archive</h3>








|







57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
    <nowiki><pre class=verbatim>
<b>wget -O jsiapp.zip</b> http://jsish.org/jsiapp/zip
</pre></nowiki>

or you can use:

    <nowiki><pre class=verbatim>
<b>jsish --wget</b> -O jsiapp.zip http://jsish.org/jsiapp/zip
</pre></nowiki>

Alternatively the [http://jsish.org/jsiapp|fossil UI] supports
<b>Zip Archive</b> download.

<h3 id=zip>Sqlar Archive</h3>