From fa0ff924859c1df28e77268f359b1c2fa34e6edd Mon Sep 17 00:00:00 2001 From: pmacdona Date: Tue, 13 Oct 2020 15:39:00 +0000 Subject: [PATCH] Release "3.2.3": Fix crash from issue #18 FossilOrigin-Name: 930e210f5d990ed4953cf49cb9d7528247c0d55d19b9158d60cec49f46649986 --- Makefile | 4 ++-- lib/Websrv.jsi | 27 +++++++++++++++----------- lib/web/docs/app.css | 7 ++----- lib/web/docs/app.js | 32 ++++++++++++++++++------------ lib/web/md/Builds.md | 8 ++++---- lib/web/md/Index.md | 4 +--- lib/web/md/Misc.md | 12 +----------- lib/web/md/Reference.md | 4 +++- lib/web/md/Start.md | 26 ++++++++++++++++++------- lib/web/md/index.json | 2 +- src/jsi.h | 2 +- src/jsiCmds.c | 2 -- src/jsiEval.c | 19 ++++++++---------- src/jsiProto.c | 4 ---- src/jsiWebSocket.c | 43 +++++++++++++++++++++++++++++------------ tools/protos.jsi | 2 +- 16 files changed, 110 insertions(+), 88 deletions(-) diff --git a/Makefile b/Makefile index 6a71bcd..90e53b7 100644 --- a/Makefile +++ b/Makefile @@ -539,8 +539,8 @@ JSICURVER=$(shell fgrep 'define JSI_VERSION_M' src/jsi.h | cut -b29- | xargs | s jsidone: @echo "" - @echo "MAKE IS DONE!!!" - @echo "To build from Configs/ try 'make clean all CONF=X' where X is one of:" + @echo "MAKE COMPLETE!!!" + @echo "To build from Configs/ try 'make remake CONF=X' where X is one of:" @echo " $(JSICONFS)." jsiminreq: diff --git a/lib/Websrv.jsi b/lib/Websrv.jsi index 8d4cb97..4b6d3ea 100644 --- a/lib/Websrv.jsi +++ b/lib/Websrv.jsi @@ -22,6 +22,7 @@ function Websrv(args:string|array, conf:object=void) closeTimeout:0, // Time til exit after close of final client websocket (ms). confFile :'', // JSON file of options (eg. for useridPass or wsOpts). docs :'', // Display markdown docs from this directory. + hist :false, // Let Vue employ history mode, short for urlFallback=url: useful for -docs/-app. ignoreExit :false, // Ignore exit request. initArg :[], // List of app modules to run. isFile :false, // Url is a file, so throw if not exists. @@ -34,7 +35,7 @@ function Websrv(args:string|array, conf:object=void) onRecv :null, // Callback command to handle websocket msgs. pageStr :'', // String to serve out as url. port :0, // Start search for port. - portMax :1000, // Max times to increment-retry port if busy. + portMax :999, // Max times to increment-retry port if busy. query :'', // Query to append to url. rootdir :null, // Base directory. server :false, // Server mode: same as noGui=true and closeTimout=0 @@ -42,13 +43,14 @@ function Websrv(args:string|array, conf:object=void) sslFnCert :'cert.pem',// File name in sslDir of cert. sslFnKey :'privkey.pem',// File name in sslDir of key. srcFile :'', // File of code to source inside the Websrv function. - uploadDir :'/tmp', // Upload files go here - timeout :60000, // Set timeout (in ms) to shutdown. This is idle time, unless negative. + timeout :59999, // Set timeout (in ms) to shutdown. This is idle time, unless negative. trace :false, // Tracing output. udata :{}, // Shortcut add of udata to wsOpts. + uploadDir :'/tmp', // Upload files go here url :"", // The file/url to serve out and clears timeout. urlPrefix :'', // Prefix for urls urlUnknown :'', // Url to redirect 404 to. + urlFallback :'', // File-url to serve out if page not found. useridPass :'', // USER:PASS for web GUI. vueConvert :false, // Util to convert file .vue files to .js, output in -rootdir wsdebug :0, // Debug option for websockets. @@ -430,7 +432,7 @@ function Websrv(args:string|array, conf:object=void) if (!File.exists(self.wsinc)) self.wsinc = ''; } - if (self.timeout != options.timeout) + if (self.timeout == options.timeout) self.timeout = 0; } if (self.docs) { if (self.rootdir || self.zip) @@ -441,13 +443,13 @@ function Websrv(args:string|array, conf:object=void) else if (File.isdir(sd) && File.exists(sd+'/'+surl)) self.rootdir = self.docs; else - throw('-docs must be a docs dir or "/"'+self.docs); + throw('expected docs dir or "/" in -docs '+self.docs); if (!self.wsinc) { self.wsinc = self.rootdir+'/docs/wsinc.jsi'; if (!File.exists(self.wsinc)) self.wsinc = ''; } - if (self.timeout != options.timeout) + if (self.timeout == options.timeout) self.timeout = 0; @@ -476,6 +478,8 @@ function Websrv(args:string|array, conf:object=void) } if (!self.rootdir) self.rootdir = '.'; + if (self.hist && !self.urlFallback) + self.urlFallback = self.url; // Provide default values for websocket. var wopts = self.wsopts = { @@ -491,8 +495,9 @@ function Websrv(args:string|array, conf:object=void) onFilter:WsFilter, port:self.port, rootdir:self.rootdir, - urlPrefix:self.urlPrefix, - urlUnknown:self.urlUnknown, + urlPrefix:(self.urlPrefix?self.urlPrefix:null), + urlUnknown:(self.urlUnknown?self.urlUnknown:null), + urlFallback:(self.urlFallback?self.urlFallback:null), sslCert:self.sslcert, sslKey:self.sslkey, ssl:self.ssl, @@ -512,7 +517,7 @@ function Websrv(args:string|array, conf:object=void) if (!self.app && !self.docs) throw('mod "'+self.mod+'" not one of: admin, menu'); } - if (urlOrig!=='' && self.timeout === 60000) + if (urlOrig!=='' && self.timeout === options.timeout) self.timeout = 0; if (!self.app && !self.docs && !self.server && !self.pageStr && self.mod === '' && urlOrig=='' && (!self.url || !File.exists(self.rootdir+'/'+self.url))) throw("url file empty or not found: "+self.url); @@ -523,7 +528,7 @@ function Websrv(args:string|array, conf:object=void) wopts.noCompress = true; if (self.server) { self.noGui = true; - if (self.timeout !== options.timeout) + if (self.timeout == options.timeout) self.timeout = 0; } else if (!self.noReload) wopts.onModify = onModify; @@ -551,7 +556,7 @@ function Websrv(args:string|array, conf:object=void) OpenWebsock(); // if (!self.ws.conf('extHandlers')) // self.ws.handler('vue', ConvertVue); // VUE BUILTIN NOW - LogTrace("Listening on port:",self.port); + LogTrace("Listening on port:",wsopts.port); if (!self.noGui && self.url && self.url.length) { OpenBrowser(self.url, self.anchor, self.query); diff --git a/lib/web/docs/app.css b/lib/web/docs/app.css index a6287cf..14f1099 100644 --- a/lib/web/docs/app.css +++ b/lib/web/docs/app.css @@ -51,7 +51,8 @@ body { color:#222; } -#jsi-sidebar a.active, #jsi-toc a.active, jsi-left-menu a.active, { +#jsi-sidebar a.active, #jsi-toc a.active, jsi-left-menu a.active, +.nav-link.active, .nav-item span.active { color:#000; font-weight:bold; } @@ -59,10 +60,6 @@ body { cursor:pointer; color:#222; } -.nav-link.active { - color:#000; - font-weight:bold; -} .bd-sidebar { position: -webkit-sticky; diff --git a/lib/web/docs/app.js b/lib/web/docs/app.js index 4c060ac..35a3a21 100644 --- a/lib/web/docs/app.js +++ b/lib/web/docs/app.js @@ -1,6 +1,6 @@ // Jsi docs viewer function dputs() {}; -//dputs = puts; +//var dputs = console.log; import Vuex from '../js/vuex.js'; Vue.use(Vuex) @@ -29,7 +29,7 @@ Vue.component('jsi-nav-bar', { - {{s_navBut.label}} + {{s_project.label}} {{r}} @@ -42,7 +42,7 @@ Vue.component('jsi-nav-bar', { Search - + @@ -114,7 +114,7 @@ Vue.component('jsi-nav-bar', { }, computed: { ...Vuex.mapState('Docs', ['s_searchList', 's_mdIndex', 's_showAllSub', 's_mdFile', 's_login', 's_websock', - 's_navFns', 's_navBut']), + 's_navFns', 's_project']), showMenu() { return this.s_websock }, menuClass() { return (this.s_websock ? "" : 'smalldev'); }, searchDis() { return (this.s_searchList.length==0); }, @@ -339,7 +339,8 @@ let DocsView = { methods: { ...Vuex.mapMutations('Docs', ['update_s_dirty', 'update_s_mdToc', 'update_s_mdAncs', 'update_s_curAnc', 'update_s_ancChain', 'update_s_curAncParent', 'update_s_mdFile', 'update_s_fileMod', - 'update_s_mdList', 'update_s_mdIndex', 'update_s_searchList', 'update_s_server']), + 'update_s_mdList', 'update_s_mdIndex', 'update_s_searchList', 'update_s_server', + 'update_s_project', 'update_s_navFns']), doLoadFile(path, hash, from) { let cr = this.$route; @@ -604,7 +605,7 @@ let DocsView = { this.update_s_mdIndex(src); let slst = [], svals = src.sections; if (src.navBut) - this.update_s_navBut(src.navBut); + this.update_s_project(src.navBut); if (src.navFns) this.update_s_navFns(src.navFns); for (var f in svals) { @@ -663,7 +664,14 @@ let DocsView = { /*============= CODE ===============*/ -let histmode = (location.port<=999); // TODO: config it. +let isfossil = $jsi.isfossil(); +let sess = $jsi.getCookie('sessionJsi'), iflags = 0, uflags = 0; +if (sess && !isfossil) { + var ssp = sess.split('.'); + iflags = parseInt(ssp[1]); + uflags = parseInt(ssp[2]); +} +let histmode = ((iflags&1) || location.port<=999 || location.protocol=='https'); let store = new Vuex.Store({ state: {}, @@ -684,7 +692,7 @@ let DocsStore = { s_searchList:[], s_server:null, s_websock:null, - s_isfossil:$jsi.isfossil(), + s_isfossil:isfossil, s_isjsi:$jsi.isjsi(), s_curAnc:0, s_curAncParent:-1, @@ -692,8 +700,8 @@ let DocsStore = { s_fileMod:null, s_dirty:false, s_showAllSub:false, - s_navFns:['Start', 'Reference', 'Index'], - s_navBut:{ label:'JSI', title:"jsish.org home page", href:"https://jsish.org" }, + s_navFns:[], + s_project:{ label:'JSI', title:"home page jsish.org", href:"https://jsish.org" }, }, @@ -704,8 +712,8 @@ let DocsStore = { update_s_curAnc(state, val) { state.s_curAnc = val; }, update_s_mdList(state, val) { state.s_mdList = val; }, update_s_mdIndex(state, val) { state.s_mdIndex = val; }, - update_s_navFns(state, val) { state.navFns = val; }, - update_s_navBut(state, val) { state.s_navBut = val; }, + update_s_navFns(state, val) { state.s_navFns = val; }, + update_s_project(state, val) { state.s_project = val; }, update_s_searchList(state, val) { state.s_searchList = val; }, update_s_server(state, val) { state.s_server = val; }, update_s_websock(state, val) { state.s_websock = val; }, diff --git a/lib/web/md/Builds.md b/lib/web/md/Builds.md index 6d7919b..836dad8 100644 --- a/lib/web/md/Builds.md +++ b/lib/web/md/Builds.md @@ -44,7 +44,7 @@ During the build it will download: Predefined configurations from **Configs/** can be made using: ``` -make clean all CONF=static +make remake CONF=static ``` Available values for `CONF` are: **default devel memdebug minimal musl muslssl noext release static win winssl** @@ -54,7 +54,7 @@ Jsi can be cross compiled from Linux to Windows using the Mingw32 package: ``` bash sudo apt-get install gcc-mingw-w64 -make clean all CONF=win +make remake CONF=win ``` **Warning**: Features such as signals are disabled in the Windows build. @@ -68,7 +68,7 @@ This is useful when you need an executable with no external dependancies. ``` bash sudo apt-get install musl-tools -make clean all CONF=musl +make remake CONF=musl ``` @@ -85,7 +85,7 @@ gmake To build with SSL support use the provided configs **muslssl** / **winssl**, or: ``` bash -make WITH_SSL=1 clean all +make remake WITH_SSL=1 ``` diff --git a/lib/web/md/Index.md b/lib/web/md/Index.md index e940b8f..7f11830 100644 --- a/lib/web/md/Index.md +++ b/lib/web/md/Index.md @@ -9,9 +9,7 @@ Index | [Testing](Testing.md) | Builtin test support | [Logging](Logging.md) | Logging support | | [Reference](Reference.md) | Command reference | [Debug](Debug.md) | Debugging in Jsi | - -### Advanced - +|----------------------------|-----------------------|---------------------------|--------------------------------| | DOC | DESCRIPTION | DOC | DESCRIPTION | |----------------------------|-----------------------|---------------------------|--------------------------------| | [Extensions](Extensions.md)| Rolling C extensions | [Builds](Builds.md) | Advanced build topics | diff --git a/lib/web/md/Misc.md b/lib/web/md/Misc.md index 3bdcf3d..bfb7b26 100644 --- a/lib/web/md/Misc.md +++ b/lib/web/md/Misc.md @@ -286,16 +286,6 @@ Compiling as C++ is supported, mostly for integrity checks. **Note**: C-integration is the main priority in Jsi, not speed of script execution. -## Shortcomings - -Following is a partial list of things that are either incomplete or unimplemented: - -- Creation of a complete test suite for code-coverage. -- Run applications directly from fossil. -- A PostgreSql extension. -- Extension for libmicrohttpd for use in post. -- Support for libevent/libev. - ## Rational @@ -747,7 +737,7 @@ Building SSL How do you build-in SSL support to jsish? -Answer: yes. make WITH_SSL=1 clean all +Answer: yes. make remake WITH_SSL=1 Note: Jsi now uses [lws](https://jsish.org/lws), a fork of LibWebsockets. diff --git a/lib/web/md/Reference.md b/lib/web/md/Reference.md index e59b4eb..b7dbd2b 100644 --- a/lib/web/md/Reference.md +++ b/lib/web/md/Reference.md @@ -1152,6 +1152,7 @@ Commands for managing WebSocket server/client connections. |redirMax|*BOOL*|Temporarily disable redirects when see more than this in 10 minutes.|| |rootdir|*STRING*|Directory to serve html from (".").|| |server|*STRKEY*|String to send out int the header SERVER (jsiWebSocket).|| +|sessFlag|*INT*|Flag to send in sessionJsi cookie.|initOnly| |ssiExts|*OBJ*|Object map of file extensions to apply SSI. eg. {myext:true, shtml:false} .|initOnly| |ssl|*BOOL*|Use https.|initOnly| |sslCert|*STRKEY*|SSL certificate file.|| @@ -1160,9 +1161,10 @@ Commands for managing WebSocket server/client connections. |startTime|*TIME_T*|Time of websocket start.|readOnly| |includeFile|*STRKEY*|Default file when no extension given (include.shtml).|| |udata|*OBJ*|User data.|| +|urlFallback|*STRKEY*|Fallback to serve when file not found..|| |urlPrefix|*STRKEY*|Prefix in url to strip from path; for reverse proxy..|| |urlRedirect|*STRKEY*|Redirect when no url or /, and adds cookie sessionJsi..|| -|urlUnknown|*STRKEY*|Redirect for unknown page or 404..|| +|urlUnknown|*STRKEY*|Redirect for 404 unknown page..|| |useridPass|*STRKEY*|The USERID:PASSWORD to use for basic authentication.|| |version|*OBJ*|WebSocket version info.|readOnly| ### WebSocket stats diff --git a/lib/web/md/Start.md b/lib/web/md/Start.md index 5e17a4b..0ab8deb 100644 --- a/lib/web/md/Start.md +++ b/lib/web/md/Start.md @@ -1,6 +1,6 @@ Start ==== - + [Index](Index.md "Jsi Documentation Index") / [Reference](Reference.md "Generated Command Reference") JSish is a **javascript**-interpreter / web-server with sqlite, websockets and **C**-extensibility. @@ -66,7 +66,7 @@ var o = {a:1, b, c, myfunc() { return 1;} }; Also, an extended Object.[freeze](Builtins.md#freeze) is supported. -### Input/Output +### Output Following are examples of input and output in Jsi. @@ -96,11 +96,11 @@ console.puts('console versions go to stderr'); ``` ``` +jsish output.jsi puts outputs a string printf omits newline output.jsi:4: "log adds line info", console versions go to stderr - ``` **File I/O**: @@ -112,7 +112,7 @@ var ch = new Channel('myfile.txt'); puts(ch.read()); ``` -See [Output Details](#output-details) below. +See [Input/Output](#input/output) below. ## Includes @@ -334,7 +334,7 @@ hello.jsi:2: "#1: < hello() <-- [ [], { a:1, b:2 } ][ [], { a:1, b:2 } ] ``` -## Output +## Input/Output The following are used for output and input: @@ -438,7 +438,7 @@ version 5.1 with numerous additions, ommissions and deviations: - UTF supported in strings, not code. - Prototype implementation is incomplete. -Syntactic difference is mostly that semicolons are required, ie: +The main syntactic difference is semicolons are required: ``` js function foo() { @@ -446,7 +446,7 @@ function foo() { return ++x; } ``` -not +**not** ``` js function foo() { var x = 1 @@ -454,6 +454,18 @@ function foo() { } ``` +## Shortcomings + +The following is a known memory leak: + +``` js +var x = {}; +x.x=x; +``` + +Solving this would require python style garbage collection: http://www.arctrix.com/nas/python/gc/. *[JSish]:JS-ish, or Jsi for short, is a Javascript-Like Interpreter + + diff --git a/lib/web/md/index.json b/lib/web/md/index.json index 79ed118..6b08a95 100644 --- a/lib/web/md/index.json +++ b/lib/web/md/index.json @@ -1 +1 @@ -{ "files":[ "Start.md", "Functions.md", "Modules.md", "Logging.md", "Testing.md", "Builtins.md", "Extensions.md", "Sqlite.md", "MySql.md", "Interp.md", "Debug.md", "Deploy.md", "Demos.md", "WebSocket.md", "Misc.md", "DBQuery.md", "Builds.md", "Reference.md", "Index.md" ], "navBut":{ "href":"https://jsish.org", "label":"JSI", "title":"jsish.org home page" }, "navFns":[ "Start", "Reference", "Index" ], "sections":{ "Builds.md":[ "source", "## Source", "building", "## Building", "configs", "## Configs", "windows", "### Windows", "static", "### Static", "freebsd", "### FreeBSD", "ssl", "### SSL", "debian-package", "### Debian Package", "embedding", "### Embedding", "use", "## Use", "interactive", "### Interactive", "script", "### Script", "help", "## Help", "apps", "## Apps", "shell", "## Shell", "editors", "## Editors", "geany", "### Geany", "vim", "### Vim" ], "Builtins.md":[ "channel", "## Channel", "cdata", "## CData", "event", "## Event", "settimeout", "### setTimeout", "setinterval", "### setInterval", "clearinterval", "### clearInterval", "update", "### update", "event", "### event", "file", "## File", "glob", "### glob", "info", "## Info", "interp", "## Interp", "json", "## JSON", "mysql", "## MySql", "object", "## Object", "freeze", "### freeze", "signal", "## Signal", "socket", "## Socket", "sqlite", "## Sqlite", "system", "## System", "exec", "### exec", "format", "### format", "source", "### source", "websocket", "## WebSocket", "zvfs", "## Zvfs", "executing-zips", "### Executing Zips", "zero-install", "### Zero-Install", "writing", "### Writing", "reading", "### Reading", "console", "## console", "log", "### log", "puts", "### puts", "input", "### input", "args", "### args" ], "DBQuery.md":[ "single-struct", "### Single Struct", "arrays-of-structs", "### Arrays of Structs", "static-arrays", "#### Static Arrays", "jsi_dbopts-flags", "#### Jsi_DbOpts Flags", "static-array-of-pointers", "#### Static Array of Pointers", "dynamic-array-of-pointers", "#### Dynamic Array of Pointers", "function-wrappers", "### Function Wrappers", "multi-struct-bind", "### Multi-Struct Bind", "supported-types", "### Supported Types", "custom", "### Custom", "custom-enum", "#### Custom Enum", "custom-bitset", "#### Custom Bitset", "select-markset-from-mytable;", "# SELECT markSet FROM mytable;", "field/column-mapping", "### Field/Column Mapping", "null-values", "### NULL Values", "dirty-field", "### Dirty Field", "rowid-field", "### Rowid Field", "javascript-initialization", "### Javascript Initialization", "the-cdata-command", "### The Cdata Command", "queries-with-cdata", "### Queries With Cdata", "schema-generation", "### Schema Generation", "schema-checking", "### Schema Checking", "configuration", "### Configuration", "begin/commit", "### BEGIN/COMMIT", "error-handling", "### Error Handling" ], "Debug.md":[ "debuggers", "## Debuggers", "commands", "### Commands", "example-session", "### Example Session", "listing", "### Listing", "print", "### Print", "eval", "### Eval", "breakpoints", "### Breakpoints", "where", "### Where", "implementation", "### Implementation", "debugging-aids", "## Debugging Aids", "error-diagnostics", "### Error Diagnostics", "method-introspection", "### Method Introspection", "displayed-arguments", "### Displayed Arguments" ], "Demos.md":[ "online", "## Online", "builtins", "## Builtins", "jsi-app", "## Jsi-App" ], "Deploy.md":[ "fossil", "## Fossil", "publish", "## Publish", "updating", "### Updating", "versioning", "### Versioning", "archive", "## Archive", "zip", "### Zip", "sqlar", "### Sqlar", "security", "## Security" ], "Extensions.md":[ "example", "## Example", "scripts", "## Scripts", "options", "## Options", "models", "## Models", "conventions", "## Conventions", "parameters", "### Parameters", "returns", "## Returns", "enums", "## Enums", "structs", "## Structs", "fields", "### Fields", "base-types", "### Base Types", "signatures", "## Signatures" ], "Functions.md":[ "checking", "## Checking", "defaults", "## Defaults", "unions", "## Unions", "argc", "## Argc", "implicit-types", "## Implicit Types", "supported-types", "## Supported Types", "any-/-void", "## Any / Void", "limitations", "## Limitations", "arrow", "## Arrow", "miscellaneous", "## Miscellaneous" ], "Index.md":[ "advanced", "### Advanced" ], "Interp.md":[ "options", "## Options", "subinterp", "## Subinterp", "alias", "## Alias", "safe-mode", "## Safe-Mode", "command-line", "### Command-Line", "lockdown", "### Lockdown", "config-file", "## Config-File", "events", "## Events", "threads", "## Threads", "json", "## JSON" ], "Logging.md":[ "elides", "## Elides", "modules", "## Modules", "mask/enable", "## Mask/Enable", "tracing", "## Tracing", "assert", "## assert", "conditionals", "## Conditionals", "navigation", "## Navigation" ], "Misc.md":[ "options", "## Options", "introspection", "## Introspection", "syntax", "## Syntax", "expressions", "### Expressions", "terminals", "### Terminals", "keywords", "### Keywords", "language-comparisons", "## Language Comparisons", "license", "## License", "libwebsockets", "### Libwebsockets", "others", "### Others", "design-and-origin", "## Design and Origin", "goals", "## Goals", "shortcomings", "## Shortcomings", "rational", "## Rational", "index-by-topic", "## Index By Topic", "packaging", "## Packaging", "security", "## Security", "extensions", "## Extensions", "expressions", "## Expressions", "conditionals", "## Conditionals", "for...of", "## for...of", "for...in", "## for...in", "for-(;;)", "## for (;;)", "function-callbacks", "## Function Callbacks", "speed-comparison", "## Speed Comparison", "case-study", "## Case Study", "conventional-js", "### Conventional JS", "jsi-solution", "### Jsi Solution", "conclusion", "### Conclusion", "notes", "## Notes", "todo", "## Todo", "alternatives", "## Alternatives", "debian", "## Debian", "windows", "## Windows", "standalone", "## Standalone", "amalgamation", "## Amalgamation", "web", "## Web", "client", "### Client", "server", "### Server", "sqlite", "## Sqlite", "usage", "### Usage", "gui", "## GUI", "database-dump", "### Database Dump", "applications", "## Applications", "ledger", "### Ledger", "pkgdirs", "### pkgDirs", "auto-load", "### Auto-Load", "auto-files", "### Auto-Files", "object-functions", "#### Object Functions", "c-api", "## C-API", "dstring", "## DString", "jsi_dsappend", "### Jsi_DSAppend", "jsi_dsappendlen", "### Jsi_DSAppendLen", "jsi_dsfree", "### Jsi_DSFree", "jsi_dsfreedup", "### Jsi_DSFreeDup", "jsi_dsprintf", "### Jsi_DSPrintf", "jsi_dsset", "### Jsi_DSSet", "jsi_dssetlength", "### Jsi_DSSetLength", "jsi_dsvalue", "### Jsi_DSValue", "`jsi_dstring_var`", "### `JSI_DSTRING_VAR`", "large-string-buffers", "### Large String Buffers", "c++-strings", "### C++ Strings", "safety", "### Safety", "json", "## JSON", "high-level", "### High-Level", "jsi_jsonparse", "#### Jsi_JSONParse", "jsi_jsonparsefmt", "#### Jsi_JSONParseFmt", "low-level", "### Low-Level", "sub-interps", "### Sub-Interps", "jsi-lite", "## Jsi-Lite", "jsi_dstring", "### Jsi_DString", "jsi_hash", "### Jsi_Hash", "jsi_tree", "### Jsi_Tree", "jsi_list", "### Jsi_List", "jsi_map", "### Jsi_Map", "example-code", "### Example Code", "options", "## Options", "example-usage", "### Example Usage", "field-specification", "### Field Specification", "option-types", "#### Option Types", "flags", "#### Flags", "custom-types", "#### Custom Types", "optionspec-fields", "#### OptionSpec Fields", "parse-flags", "### Parse Flags", "compile-time-validation", "### Compile-time Validation", "is-specified", "### Is Specified", "jsi-js", "## jsi-js" ], "Modules.md":[ "usage", "## Usage", "minimal", "### Minimal", "decomposed", "### Decomposed", "logging", "### Logging", "directives", "## Directives", "modulerun", "### moduleRun", "moduleopts", "### moduleOpts", "provide", "### provide", "require", "### require", "help", "## Help" ], "MySql.md":[ "eval", "## Eval", "oncolumn", "## Oncolumn", "query", "## Query", "query-options", "### Query Options", "outputs", "### Outputs", "json", "#### JSON", "callback-function", "#### Callback Function", "inputs", "### Inputs", "bindings", "#### Bindings", "named-binds", "#### Named-Binds", "types", "#### Types", "miscellaneous", "## Miscellaneous", "user-functions", "### User Functions", "timestamps", "### Timestamps", "caching", "### Caching", "differences-from-sqlite", "### Differences From Sqlite", "building", "### Building" ], "Reference.md":[ "reference", "# Reference", "array", "## Array", "array-sort", "### Array sort", "boolean", "## Boolean", "channel", "## Channel", "event", "## Event", "event-update", "### Event update", "file", "## File", "file-glob", "### File glob", "function", "## Function", "info", "## Info", "info-cmds", "### Info cmds", "interp", "## Interp", "interp-new", "### Interp new", "interp-debugopts", "### Interp debugOpts", "interp-logopts", "### Interp logOpts", "interp-subopts", "### Interp subOpts", "json", "## JSON", "math", "## Math", "mysql", "## MySql", "mysql-new", "### MySql new", "mysql-queryopts", "### MySql queryOpts", "mysql-obj", "### MySql obj", "mysql-query", "### MySql query", "mysql-query-obj", "### MySql query obj", "number", "## Number", "object", "## Object", "regexp", "## RegExp", "signal", "## Signal", "socket", "## Socket", "socket-new", "### Socket new", "socket-stats", "### Socket stats", "socket-idconf", "### Socket idconf", "socket-send", "### Socket send", "sqlite", "## Sqlite", "sqlite-new", "### Sqlite new", "sqlite-queryopts", "### Sqlite queryOpts", "sqlite-obj", "### Sqlite obj", "sqlite-import", "### Sqlite import", "sqlite-query", "### Sqlite query", "sqlite-query-obj", "### Sqlite query obj", "string", "## String", "system", "## System", "system-assert", "### System assert", "system-exec", "### System exec", "system-import", "### System import", "system-provide", "### System provide", "system-require", "### System require", "system-source", "### System source", "system-strftime", "### System strftime", "system-strptime", "### System strptime", "system-update", "### System update", "util", "## Util", "util-hash", "### Util hash", "vfs", "## Vfs", "vfs-conf", "### Vfs conf", "vfs-exec", "### Vfs exec", "vfs-fileconf", "### Vfs fileconf", "vfs-type", "### Vfs type", "vfs-vmount", "### Vfs vmount", "websocket", "## WebSocket", "websocket-new", "### WebSocket new", "websocket-stats", "### WebSocket stats", "websocket-idconf", "### WebSocket idconf", "websocket-idconf-stats", "### WebSocket idconf stats", "zvfs", "## Zvfs", "console", "## console", "console-assert", "### console assert" ], "Sqlite.md":[ "options", "## Options", "output", "## Output", "json", "### JSON", "callback", "### Callback", "input", "## Input", "arrays", "### Arrays", "objects", "### Objects", "create", "#### CREATE", "insert", "#### INSERT", "charjson", "#### CHARJSON", "variables", "### Variables", "types", "### Types", "user-functions", "## User Functions", "timestamps", "## Timestamps", "caching", "## Caching", "building", "## Building" ], "Start.md":[ "download", "## Download", "basics", "## Basics", "functions", "### Functions", "variables", "### Variables", "objects", "### Objects", "input/output", "### Input/Output", "includes", "## Includes", "source", "### source", "import", "### import", "load", "### load", "require", "### require", "modules", "## Modules", "help", "## Help", "options", "## Options", "diagnostics", "## Diagnostics", "logging", "### Logging", "backtrace", "### Backtrace", "tracing", "### Tracing", "output-details", "## Output Details", "puts", "### puts", "printf", "### printf", "log", "### log", "console", "### console", "file", "### File", "channel", "### Channel", "compatibility", "## Compatibility" ], "Testing.md":[ "scripts", "## Scripts", "passing", "### Passing", "failing", "### Failing", "exceptions", "### Exceptions", "comments", "### Comments", "restrictions", "### Restrictions", "advanced", "## Advanced", "relative-dirs", "### Relative Dirs", "time", "### Time", "directories", "### Directories", "inputs", "### Inputs", "arguments", "### Arguments", "assert", "### Assert", "options", "### Options", "embedding", "### Embedding", "preprocess", "### Preprocess", "navigation", "### Navigation", "builtins", "### Builtins", "execution-trace", "### Execution Trace", "code-profile", "### Code Profile", "code-coverage", "### Code Coverage" ], "WebSocket.md":[ "preprocessors", "## Preprocessors", "html-preprocessing", "### HTML Preprocessing", "css-preprocessing", "### CSS Preprocessing", "js-preprocessing", "### JS Preprocessing", "enabling-preprocessors", "## Enabling Preprocessors", "ssi", "## SSI", "utilities", "## Utilities", "ssl", "## SSL", "demos", "## Demos" ] } } \ No newline at end of file +{ "files":[ "Start.md", "Functions.md", "Modules.md", "Logging.md", "Testing.md", "Builtins.md", "Extensions.md", "Sqlite.md", "MySql.md", "Interp.md", "Debug.md", "Deploy.md", "Demos.md", "WebSocket.md", "Misc.md", "DBQuery.md", "Builds.md", "Reference.md", "Index.md" ], "navBut":{ "href":"https://jsish.org", "label":"JSI", "title":"jsish.org home page" }, "navFns":[ "Start", "Reference", "Index" ], "sections":{ "Builds.md":[ "source", "## Source", "building", "## Building", "configs", "## Configs", "windows", "### Windows", "static", "### Static", "freebsd", "### FreeBSD", "ssl", "### SSL", "debian-package", "### Debian Package", "embedding", "### Embedding", "use", "## Use", "interactive", "### Interactive", "script", "### Script", "help", "## Help", "apps", "## Apps", "shell", "## Shell", "editors", "## Editors", "geany", "### Geany", "vim", "### Vim" ], "Builtins.md":[ "channel", "## Channel", "cdata", "## CData", "event", "## Event", "settimeout", "### setTimeout", "setinterval", "### setInterval", "clearinterval", "### clearInterval", "update", "### update", "event", "### event", "file", "## File", "glob", "### glob", "info", "## Info", "interp", "## Interp", "json", "## JSON", "mysql", "## MySql", "object", "## Object", "freeze", "### freeze", "signal", "## Signal", "socket", "## Socket", "sqlite", "## Sqlite", "system", "## System", "exec", "### exec", "format", "### format", "source", "### source", "websocket", "## WebSocket", "zvfs", "## Zvfs", "executing-zips", "### Executing Zips", "zero-install", "### Zero-Install", "writing", "### Writing", "reading", "### Reading", "console", "## console", "log", "### log", "puts", "### puts", "input", "### input", "args", "### args" ], "DBQuery.md":[ "single-struct", "### Single Struct", "arrays-of-structs", "### Arrays of Structs", "static-arrays", "#### Static Arrays", "jsi_dbopts-flags", "#### Jsi_DbOpts Flags", "static-array-of-pointers", "#### Static Array of Pointers", "dynamic-array-of-pointers", "#### Dynamic Array of Pointers", "function-wrappers", "### Function Wrappers", "multi-struct-bind", "### Multi-Struct Bind", "supported-types", "### Supported Types", "custom", "### Custom", "custom-enum", "#### Custom Enum", "custom-bitset", "#### Custom Bitset", "select-markset-from-mytable;", "# SELECT markSet FROM mytable;", "field/column-mapping", "### Field/Column Mapping", "null-values", "### NULL Values", "dirty-field", "### Dirty Field", "rowid-field", "### Rowid Field", "javascript-initialization", "### Javascript Initialization", "the-cdata-command", "### The Cdata Command", "queries-with-cdata", "### Queries With Cdata", "schema-generation", "### Schema Generation", "schema-checking", "### Schema Checking", "configuration", "### Configuration", "begin/commit", "### BEGIN/COMMIT", "error-handling", "### Error Handling" ], "Debug.md":[ "debuggers", "## Debuggers", "commands", "### Commands", "example-session", "### Example Session", "listing", "### Listing", "print", "### Print", "eval", "### Eval", "breakpoints", "### Breakpoints", "where", "### Where", "implementation", "### Implementation", "debugging-aids", "## Debugging Aids", "error-diagnostics", "### Error Diagnostics", "method-introspection", "### Method Introspection", "displayed-arguments", "### Displayed Arguments" ], "Demos.md":[ "online", "## Online", "builtins", "## Builtins", "jsi-app", "## Jsi-App" ], "Deploy.md":[ "fossil", "## Fossil", "publish", "## Publish", "updating", "### Updating", "versioning", "### Versioning", "archive", "## Archive", "zip", "### Zip", "sqlar", "### Sqlar", "security", "## Security" ], "Extensions.md":[ "example", "## Example", "scripts", "## Scripts", "options", "## Options", "models", "## Models", "conventions", "## Conventions", "parameters", "### Parameters", "returns", "## Returns", "enums", "## Enums", "structs", "## Structs", "fields", "### Fields", "base-types", "### Base Types", "signatures", "## Signatures" ], "Functions.md":[ "checking", "## Checking", "defaults", "## Defaults", "unions", "## Unions", "argc", "## Argc", "implicit-types", "## Implicit Types", "supported-types", "## Supported Types", "any-/-void", "## Any / Void", "limitations", "## Limitations", "arrow", "## Arrow", "miscellaneous", "## Miscellaneous" ], "Index.md":[], "Interp.md":[ "options", "## Options", "subinterp", "## Subinterp", "alias", "## Alias", "safe-mode", "## Safe-Mode", "command-line", "### Command-Line", "lockdown", "### Lockdown", "config-file", "## Config-File", "events", "## Events", "threads", "## Threads", "json", "## JSON" ], "Logging.md":[ "elides", "## Elides", "modules", "## Modules", "mask/enable", "## Mask/Enable", "tracing", "## Tracing", "assert", "## assert", "conditionals", "## Conditionals", "navigation", "## Navigation" ], "Misc.md":[ "options", "## Options", "introspection", "## Introspection", "syntax", "## Syntax", "expressions", "### Expressions", "terminals", "### Terminals", "keywords", "### Keywords", "language-comparisons", "## Language Comparisons", "license", "## License", "libwebsockets", "### Libwebsockets", "others", "### Others", "design-and-origin", "## Design and Origin", "goals", "## Goals", "rational", "## Rational", "index-by-topic", "## Index By Topic", "packaging", "## Packaging", "security", "## Security", "extensions", "## Extensions", "expressions", "## Expressions", "conditionals", "## Conditionals", "for...of", "## for...of", "for...in", "## for...in", "for-(;;)", "## for (;;)", "function-callbacks", "## Function Callbacks", "speed-comparison", "## Speed Comparison", "case-study", "## Case Study", "conventional-js", "### Conventional JS", "jsi-solution", "### Jsi Solution", "conclusion", "### Conclusion", "notes", "## Notes", "todo", "## Todo", "alternatives", "## Alternatives", "debian", "## Debian", "windows", "## Windows", "standalone", "## Standalone", "amalgamation", "## Amalgamation", "web", "## Web", "client", "### Client", "server", "### Server", "sqlite", "## Sqlite", "usage", "### Usage", "gui", "## GUI", "database-dump", "### Database Dump", "applications", "## Applications", "ledger", "### Ledger", "pkgdirs", "### pkgDirs", "auto-load", "### Auto-Load", "auto-files", "### Auto-Files", "object-functions", "#### Object Functions", "c-api", "## C-API", "dstring", "## DString", "jsi_dsappend", "### Jsi_DSAppend", "jsi_dsappendlen", "### Jsi_DSAppendLen", "jsi_dsfree", "### Jsi_DSFree", "jsi_dsfreedup", "### Jsi_DSFreeDup", "jsi_dsprintf", "### Jsi_DSPrintf", "jsi_dsset", "### Jsi_DSSet", "jsi_dssetlength", "### Jsi_DSSetLength", "jsi_dsvalue", "### Jsi_DSValue", "`jsi_dstring_var`", "### `JSI_DSTRING_VAR`", "large-string-buffers", "### Large String Buffers", "c++-strings", "### C++ Strings", "safety", "### Safety", "json", "## JSON", "high-level", "### High-Level", "jsi_jsonparse", "#### Jsi_JSONParse", "jsi_jsonparsefmt", "#### Jsi_JSONParseFmt", "low-level", "### Low-Level", "sub-interps", "### Sub-Interps", "jsi-lite", "## Jsi-Lite", "jsi_dstring", "### Jsi_DString", "jsi_hash", "### Jsi_Hash", "jsi_tree", "### Jsi_Tree", "jsi_list", "### Jsi_List", "jsi_map", "### Jsi_Map", "example-code", "### Example Code", "options", "## Options", "example-usage", "### Example Usage", "field-specification", "### Field Specification", "option-types", "#### Option Types", "flags", "#### Flags", "custom-types", "#### Custom Types", "optionspec-fields", "#### OptionSpec Fields", "parse-flags", "### Parse Flags", "compile-time-validation", "### Compile-time Validation", "is-specified", "### Is Specified", "jsi-js", "## jsi-js" ], "Modules.md":[ "usage", "## Usage", "minimal", "### Minimal", "decomposed", "### Decomposed", "logging", "### Logging", "directives", "## Directives", "modulerun", "### moduleRun", "moduleopts", "### moduleOpts", "provide", "### provide", "require", "### require", "help", "## Help" ], "MySql.md":[ "eval", "## Eval", "oncolumn", "## Oncolumn", "query", "## Query", "query-options", "### Query Options", "outputs", "### Outputs", "json", "#### JSON", "callback-function", "#### Callback Function", "inputs", "### Inputs", "bindings", "#### Bindings", "named-binds", "#### Named-Binds", "types", "#### Types", "miscellaneous", "## Miscellaneous", "user-functions", "### User Functions", "timestamps", "### Timestamps", "caching", "### Caching", "differences-from-sqlite", "### Differences From Sqlite", "building", "### Building" ], "Reference.md":[ "reference", "# Reference", "array", "## Array", "array-sort", "### Array sort", "boolean", "## Boolean", "channel", "## Channel", "event", "## Event", "event-update", "### Event update", "file", "## File", "file-glob", "### File glob", "function", "## Function", "info", "## Info", "info-cmds", "### Info cmds", "interp", "## Interp", "interp-new", "### Interp new", "interp-debugopts", "### Interp debugOpts", "interp-logopts", "### Interp logOpts", "interp-subopts", "### Interp subOpts", "json", "## JSON", "math", "## Math", "mysql", "## MySql", "mysql-new", "### MySql new", "mysql-queryopts", "### MySql queryOpts", "mysql-obj", "### MySql obj", "mysql-query", "### MySql query", "mysql-query-obj", "### MySql query obj", "number", "## Number", "object", "## Object", "regexp", "## RegExp", "signal", "## Signal", "socket", "## Socket", "socket-new", "### Socket new", "socket-stats", "### Socket stats", "socket-idconf", "### Socket idconf", "socket-send", "### Socket send", "sqlite", "## Sqlite", "sqlite-new", "### Sqlite new", "sqlite-queryopts", "### Sqlite queryOpts", "sqlite-obj", "### Sqlite obj", "sqlite-import", "### Sqlite import", "sqlite-query", "### Sqlite query", "sqlite-query-obj", "### Sqlite query obj", "string", "## String", "system", "## System", "system-assert", "### System assert", "system-exec", "### System exec", "system-import", "### System import", "system-provide", "### System provide", "system-require", "### System require", "system-source", "### System source", "system-strftime", "### System strftime", "system-strptime", "### System strptime", "system-update", "### System update", "util", "## Util", "util-hash", "### Util hash", "vfs", "## Vfs", "vfs-conf", "### Vfs conf", "vfs-exec", "### Vfs exec", "vfs-fileconf", "### Vfs fileconf", "vfs-type", "### Vfs type", "vfs-vmount", "### Vfs vmount", "websocket", "## WebSocket", "websocket-new", "### WebSocket new", "websocket-stats", "### WebSocket stats", "websocket-idconf", "### WebSocket idconf", "websocket-idconf-stats", "### WebSocket idconf stats", "zvfs", "## Zvfs", "console", "## console", "console-assert", "### console assert" ], "Sqlite.md":[ "options", "## Options", "output", "## Output", "json", "### JSON", "callback", "### Callback", "input", "## Input", "arrays", "### Arrays", "objects", "### Objects", "create", "#### CREATE", "insert", "#### INSERT", "charjson", "#### CHARJSON", "variables", "### Variables", "types", "### Types", "user-functions", "## User Functions", "timestamps", "## Timestamps", "caching", "## Caching", "building", "## Building" ], "Start.md":[ "download", "## Download", "basics", "## Basics", "functions", "### Functions", "variables", "### Variables", "objects", "### Objects", "output", "### Output", "includes", "## Includes", "source", "### source", "import", "### import", "load", "### load", "require", "### require", "modules", "## Modules", "help", "## Help", "options", "## Options", "diagnostics", "## Diagnostics", "logging", "### Logging", "backtrace", "### Backtrace", "tracing", "### Tracing", "input/output", "## Input/Output", "puts", "### puts", "printf", "### printf", "log", "### log", "console", "### console", "file", "### File", "channel", "### Channel", "compatibility", "## Compatibility", "shortcomings", "## Shortcomings" ], "Testing.md":[ "scripts", "## Scripts", "passing", "### Passing", "failing", "### Failing", "exceptions", "### Exceptions", "comments", "### Comments", "restrictions", "### Restrictions", "advanced", "## Advanced", "relative-dirs", "### Relative Dirs", "time", "### Time", "directories", "### Directories", "inputs", "### Inputs", "arguments", "### Arguments", "assert", "### Assert", "options", "### Options", "embedding", "### Embedding", "preprocess", "### Preprocess", "navigation", "### Navigation", "builtins", "### Builtins", "execution-trace", "### Execution Trace", "code-profile", "### Code Profile", "code-coverage", "### Code Coverage" ], "WebSocket.md":[ "preprocessors", "## Preprocessors", "html-preprocessing", "### HTML Preprocessing", "css-preprocessing", "### CSS Preprocessing", "js-preprocessing", "### JS Preprocessing", "enabling-preprocessors", "## Enabling Preprocessors", "ssi", "## SSI", "utilities", "## Utilities", "ssl", "## SSL", "demos", "## Demos" ] } } \ No newline at end of file diff --git a/src/jsi.h b/src/jsi.h index c346925..e667b43 100644 --- a/src/jsi.h +++ b/src/jsi.h @@ -4,7 +4,7 @@ #define JSI_VERSION_MAJOR 3 #define JSI_VERSION_MINOR 2 -#define JSI_VERSION_RELEASE 2 +#define JSI_VERSION_RELEASE 3 #define JSI_VERSION (JSI_VERSION_MAJOR + ((Jsi_Number)JSI_VERSION_MINOR/100.0) + ((Jsi_Number)JSI_VERSION_RELEASE/10000.0)) diff --git a/src/jsiCmds.c b/src/jsiCmds.c index 884d08b..6c928e4 100644 --- a/src/jsiCmds.c +++ b/src/jsiCmds.c @@ -3801,8 +3801,6 @@ static Jsi_Value *CommandCreateWithSpec(Jsi_Interp *interp, Jsi_CmdSpec *cSpec, func->VD.label = "CMDspec"; func->VD.label2 = cmdSpec->name; #endif - //Jsi_IncrRefCount(interp, func); - //Jsi_HashSet(interp->genValueTbl, func, func); Jsi_ValueInsertFixed(interp, (iscons||!proto?interp->csc:proto), cmdSpec->name, func); f = func->d.obj->d.fobj->func; diff --git a/src/jsiEval.c b/src/jsiEval.c index 12e915a..293240b 100644 --- a/src/jsiEval.c +++ b/src/jsiEval.c @@ -971,7 +971,9 @@ static Jsi_RC jsiEvalSubscript(Jsi_Interp *interp, Jsi_Value *src, Jsi_Value *id if (bsc == 0 && interp->lastSubscriptFail && interp->lastSubscriptFail->vt != JSI_VT_UNDEF) Jsi_ValueReset(interp, &interp->lastSubscriptFail); - Jsi_ValueToObject(interp, src); + rc = Jsi_ValueToObject(interp, src); + if (rc != JSI_OK) + return rc; Jsi_Value res = VALINIT, *resPtr = &res, *vp = jsi_ValueSubscript(interp, src, idx, &resPtr, right_val); @@ -1265,7 +1267,6 @@ Jsi_RC jsiEvalCodeSub(jsi_Pstate *ps, Jsi_OpCodes *opcodes, } case OP_ASSIGN: { Jsi_Value *sval = _jsi_TOP, *dval = _jsi_TOQ; - bool globThis = (sval->vt == JSI_VT_OBJECT && sval->d.obj == interp->csc->d.obj); if ((uintptr_t)ip->data & 1) { jsiVarDeref(interp,1); rc = jsiValueAssign(interp, dval, sval, lop); @@ -1285,13 +1286,9 @@ Jsi_RC jsiEvalCodeSub(jsi_Pstate *ps, Jsi_OpCodes *opcodes, jsiClearStack(interp,3); Jsi_ValueCopy(interp,v3, sval); dval = v3; - jsiPop(interp, 2); - } - if (fp->level<=1 && globThis && rc == JSI_OK && dval && dval->vt == JSI_VT_VARIABLE) { - dval = dval->d.lval; - //printf("GLOBAL THIS: %p\n", dval); - Jsi_HashSet(interp->genValueTbl, dval, dval); + jsiPop(interp, 2);\ } + break; } case OP_PUSHREG: { @@ -1352,7 +1349,7 @@ Jsi_RC jsiEvalCodeSub(jsi_Pstate *ps, Jsi_OpCodes *opcodes, if (v->vt == JSI_VT_VARIABLE) { Jsi_ValueCopy(interp, v, v->d.lval); } - Jsi_ValueToObject(interp, v); + rc = Jsi_ValueToObject(interp, v); } break; } @@ -1587,7 +1584,7 @@ Jsi_RC jsiEvalCodeSub(jsi_Pstate *ps, Jsi_OpCodes *opcodes, break; } if (_jsi_TOP->vt != JSI_VT_UNDEF && _jsi_TOP->vt != JSI_VT_NULL) - Jsi_ValueToObject(interp, _jsi_TOP); + rc = Jsi_ValueToObject(interp, _jsi_TOP); Jsi_Value *spret = Jsi_ValueNew1(interp); jsi_ValueObjGetKeys(interp, _jsi_TOP, spret, ip->isof); Jsi_ValueReplace(interp, _jsi_STACK+fp->Sp, spret); @@ -2024,7 +2021,7 @@ Jsi_RC jsiEvalCodeSub(jsi_Pstate *ps, Jsi_OpCodes *opcodes, break; } jsiVarDeref(interp,1); - Jsi_ValueToObject(interp, _jsi_TOP); + rc = Jsi_ValueToObject(interp, _jsi_TOP); jsi_TryList *n = jsiTrylistNew(jsi_TL_WITH, scope, currentScope); diff --git a/src/jsiProto.c b/src/jsiProto.c index 7010331..ceb92c5 100644 --- a/src/jsiProto.c +++ b/src/jsiProto.c @@ -801,10 +801,6 @@ Jsi_RC jsi_InitProto(Jsi_Interp *interp, int release) Jsi_ValueInsert(interp, global, "Object", _Object, JSI_OM_DONTENUM); Jsi_ValueInsert(interp, global, "Function", _Function, JSI_OM_DONTENUM); - //Jsi_HashSet(interp->genValueTbl, _Object, _Object); - //Jsi_HashSet(interp->genValueTbl, _Function, _Function); - //Jsi_HashSet(interp->genValueTbl, interp->Object_prototype , interp->Object_prototype); - //Jsi_HashSet(interp->genValueTbl, interp->Function_prototype, interp->Function_prototype); Jsi_HashSet(interp->genObjTbl, interp->Function_prototype->d.obj, interp->Function_prototype->d.obj); interp->cleanObjs[0] = _Function->d.obj; diff --git a/src/jsiWebSocket.c b/src/jsiWebSocket.c index f6871db..07d057b 100644 --- a/src/jsiWebSocket.c +++ b/src/jsiWebSocket.c @@ -142,7 +142,7 @@ typedef struct { /* Per server data (or client if client-mode). */ int flags; jsi_wsStatData stats; char *iface; - const char* urlPrefix, *urlRedirect, *urlUnknown; + const char* urlPrefix, *urlRedirect, *urlUnknown, *urlFallback; const char *localhostName; const char *clientName; const char *clientIP; @@ -164,6 +164,7 @@ typedef struct { /* Per server data (or client if client-mode). */ int recvBufMax; int recvBufCnt; int recvBufTimeout; + int sessFlag; int lastRevCnt; // For update time_t createLast; time_t startTime; @@ -365,6 +366,7 @@ static Jsi_OptionSpec WSOptions[] = JSI_OPT(BOOL, jsi_wsCmdObj, redirMax, .help="Temporarily disable redirects when see more than this in 10 minutes"), JSI_OPT(STRING, jsi_wsCmdObj, rootdir, .help="Directory to serve html from (\".\")"), JSI_OPT(STRKEY, jsi_wsCmdObj, server, .help="String to send out int the header SERVER (jsiWebSocket)"), + JSI_OPT(INT, jsi_wsCmdObj, sessFlag, .help="Flag to send in sessionJsi cookie", jsi_IIOF), JSI_OPT(OBJ, jsi_wsCmdObj, ssiExts, .help="Object map of file extensions to apply SSI. eg. {myext:true, shtml:false} ", jsi_IIOF), JSI_OPT(BOOL, jsi_wsCmdObj, ssl, .help="Use https", jsi_IIOF), JSI_OPT(STRKEY, jsi_wsCmdObj, sslCert, .help="SSL certificate file"), @@ -373,9 +375,10 @@ static Jsi_OptionSpec WSOptions[] = JSI_OPT(TIME_T, jsi_wsCmdObj, startTime, .help="Time of websocket start", jsi_IIRO), JSI_OPT(STRKEY, jsi_wsCmdObj, includeFile,.help="Default file when no extension given (include.shtml)"), JSI_OPT(OBJ, jsi_wsCmdObj, udata, .help="User data"), + JSI_OPT(STRKEY, jsi_wsCmdObj, urlFallback,.help="Fallback to serve when file not found."), JSI_OPT(STRKEY, jsi_wsCmdObj, urlPrefix, .help="Prefix in url to strip from path; for reverse proxy."), JSI_OPT(STRKEY, jsi_wsCmdObj, urlRedirect,.help="Redirect when no url or /, and adds cookie sessionJsi."), - JSI_OPT(STRKEY, jsi_wsCmdObj, urlUnknown, .help="Redirect for unknown page or 404."), + JSI_OPT(STRKEY, jsi_wsCmdObj, urlUnknown, .help="Redirect for 404 unknown page."), JSI_OPT(STRKEY, jsi_wsCmdObj, useridPass, .help="The USERID:PASSWORD to use for basic authentication"), JSI_OPT(OBJ, jsi_wsCmdObj, version, .help="WebSocket version info", jsi_IIRO), JSI_OPT_END(jsi_wsCmdObj, .help="Websocket options") @@ -402,7 +405,9 @@ static bool jsi_wsAddHeader(Jsi_Interp *interp, jsi_wsCmdObj *cmdPtr, struct lws Jsi_DString *hStr); static void wss_MakeSessionKey( jsi_wsCmdObj *cmdPtr, jsi_wsPss *pss) { - snprintf(pss->key, sizeof(pss->key), "sessionJsi=%d%p%d", pss->wid, pss, (int)cmdPtr->startTime); + int flag = (cmdPtr->urlFallback && cmdPtr->urlFallback[0]); + snprintf(pss->key, sizeof(pss->key), "sessionJsi=%d%p%d.%d.%d", + pss->wid, pss, (int)cmdPtr->startTime, flag, cmdPtr->sessFlag); } // Allocate per-connection data using file descriptor. @@ -1463,9 +1468,10 @@ static int jsi_wsHttp(Jsi_Interp *interp, jsi_wsCmdObj *cmdPtr, struct lws *wsi, uchar *p = buffer, *end = &buffer[sizeof(buffer)-1]; int n; Jsi_Value* fname = NULL; - bool isJsiWeb = 0, isSSI = 0; + bool isJsiWeb = 0, isSSI = 0, fallbackTry = 0; cmdPtr->stats.httpLast = now; - + +falltry: if (inPtr[0] != '~') inPtr = Jsi_NormalPath(interp, inPtr, iStr); /* if a legal POST URL, let it continue and accept data */ @@ -1485,17 +1491,20 @@ static int jsi_wsHttp(Jsi_Interp *interp, jsi_wsCmdObj *cmdPtr, struct lws *wsi, else cmdPtr->redirDisable--; } - - if ((cmdPtr->urlRedirect && (inPtr == 0 || *inPtr == 0 || !Jsi_Strcmp(inPtr, "/")) && !cmdPtr->redirDisable) - && (inPtr = (char*)cmdPtr->urlRedirect) && inPtr[0]) + int redirCode = 301; + + bool doRedir = (inPtr == 0 || *inPtr == 0 || (inPtr[0] =='/' && !inPtr[1])); + if (doRedir && !cmdPtr->redirDisable && cmdPtr->urlRedirect && cmdPtr->urlRedirect[0]) { + inPtr = (char*)cmdPtr->urlRedirect; +doredir: cmdPtr->stats.redirCnt++; // TODO: system time change can disrupt the following. if (cmdPtr->redirMax>0 && !cmdPtr->redirDisable && cmdPtr->redirMax>0 && cmdPtr->stats.redirLast && difftime(now, cmdPtr->stats.redirLast)<600 && ++cmdPtr->redirAllCnt>cmdPtr->redirMax) cmdPtr->redirDisable = 100; cmdPtr->stats.redirLast = now; - rc = lws_http_redirect(wsi, 301, (uchar*)inPtr, Jsi_Strlen(inPtr), &p, end); + rc = lws_http_redirect(wsi, redirCode, (uchar*)inPtr, Jsi_Strlen(inPtr), &p, end); return (rc == 100 ? 0 : 1); } @@ -1791,9 +1800,19 @@ static int jsi_wsHttp(Jsi_Interp *interp, jsi_wsCmdObj *cmdPtr, struct lws *wsi, if ((native && Jsi_InterpSafe(interp) && Jsi_InterpAccess(interp, fname, JSI_INTACCESS_READ) != JSI_OK) || (Jsi_Stat(interp, fname, &jsb) || (jsb.st_size<=0 && !S_ISDIR(jsb.st_mode)))) { nofile: - if (cmdPtr->urlUnknown && cmdPtr->urlUnknown[0]) { - rc = lws_http_redirect(wsi, 301, (uchar*)cmdPtr->urlUnknown, Jsi_Strlen(cmdPtr->urlUnknown), &p, end); - goto done; + if (cmdPtr->urlFallback && cmdPtr->urlFallback[0] && !fallbackTry) { + inPtr = (char*)cmdPtr->urlFallback; + fallbackTry=1; + goto falltry; + } + if (!cmdPtr->redirDisable && cmdPtr->urlUnknown && cmdPtr->urlUnknown[0]) { + redirCode = 404; + inPtr = (char*)cmdPtr->urlUnknown; + goto doredir; + } + if (!cmdPtr->redirDisable && cmdPtr->urlRedirect && cmdPtr->urlRedirect[0]) { + inPtr = (char*)cmdPtr->urlRedirect; + goto doredir; } if (cmdPtr->onUnknown || pss->onUnknown) { Jsi_Value *uk = (pss->onUnknown?pss->onUnknown:cmdPtr->onUnknown); diff --git a/tools/protos.jsi b/tools/protos.jsi index 69bb17a..4790767 100644 --- a/tools/protos.jsi +++ b/tools/protos.jsi @@ -1,4 +1,4 @@ -//JSI Command Prototypes: version 3.2.2 +//JSI Command Prototypes: version 3.2.3 throw("NOT EXECUTABLE: USE FILE IN GEANY EDITOR FOR CMD LINE COMPLETION + GOTO TAG"); var Array = function(cmd,args) {};