summaryrefslogtreecommitdiffhomepage
AgeCommit message (Collapse)Author
2022-10-18Merge pull request #118 from jow-/fs-read-getdelimJo-Philipp Wich
fs: expose `getdelim()` functionality through `fd.read()`
2022-10-18fs: expose `getdelim()` functionality through `fd.read()`Jo-Philipp Wich
When `fd.read()` is invoked with a single-character string argument, invoke `getdelim()` internally to read the input until the give character or EOF. This is useful for reading character delimited input data. For example `fd.read('\n')` will read any data up to the first newline (or EOF) while `fd.read('\0x00')` will read until the first null byte. Signed-off-by: Jo-Philipp Wich <jo@mein.io>
2022-10-08Merge pull request #115 from jow-/fs-use-getlineJo-Philipp Wich
fs: use `getline()` for line wise read operations
2022-10-08Merge pull request #113 from jow-/fix-regex-literal-parsingJo-Philipp Wich
lexer: fixes for regex literal parsing
2022-10-07fs: use `getline()` for line wise read operationsJo-Philipp Wich
Use `getline()` instead of a custom `fgets()` wrapper logic to perform line wise reads from open file handles. This is required to properly deal with lines containing embedded null bytes. Signed-off-by: Jo-Philipp Wich <jo@mein.io>
2022-10-05lexer: fixes for regex literal parsingJo-Philipp Wich
- Ensure that regexp extension escapes are consistently handled; substitute `\d`, `\D`, `\s`, `\S`, `\w` and `\W` with `[[:digit:]]`, `[^[:digit:]]`, `[[:space:]]`, `[^[:space:]]`, `[[:alnum:]_]` and `[^[:alnum:]_]` character classes respectively since not all POSIX regexp implementations implement all of those extensions - Preserve `\b`, `\B`, `\<` and `\>` boundary matches Fixes: a45f2a3 ("lexer: improve regex literal handling") Signed-off-by: Jo-Philipp Wich <jo@mein.io>
2022-10-05Merge pull request #110 from jow-/lib-add-sliceJo-Philipp Wich
lib: implement slice() function
2022-10-04lib: implement slice() functionJo-Philipp Wich
Implement a new function `slice()` to complement the existing `splice()` function and model it's semantics after the ES6 `Array.slice()` version. Fixes: #106 Signed-off-by: Jo-Philipp Wich <jo@mein.io>
2022-10-04Merge pull request #108 from jow-/optimizationsJo-Philipp Wich
Various improvements
2022-10-04main: implement print modeJo-Philipp Wich
Introduce a new `-p` flag which works like `-e` but prints the final expression result. Signed-off-by: Jo-Philipp Wich <jo@mein.io>
2022-10-04compiler: optimize function return opcode generationJo-Philipp Wich
Track last emitted statement type in compiled code and only generate final `return null` opcodes if there is no preceeding `return` statement. Also use this statement tracking to avoid emitting invalid return opcodes for arrow function bodies with trailing empty statements. Signed-off-by: Jo-Philipp Wich <jo@mein.io>
2022-10-04lexer: improve regex literal handlingJo-Philipp Wich
- Do not treat slashes within bracket expressions as delimitters - Do not escape slashes when stringifying regex sources - Allow all escape sequence types in regex literals Signed-off-by: Jo-Philipp Wich <jo@mein.io>
2022-09-30vm: maintain export symbol tables per programJo-Philipp Wich
Instead of having one global export table per VM instance maintain one table per program instance. This is required to avoid clobbering the export list in case `import` using code is loaded at runtime through `require()`, `loadfile()` etc. Signed-off-by: Jo-Philipp Wich <jo@mein.io>
2022-09-29uloop: task: gracefully handle absent output callbackJo-Philipp Wich
Both input and output callbacks for uloop tasks are optional, but the low level io callback implementation did not properly deal with an absent ucode output callback, triggering an exception in managed code due to invoking a null value as function. Fix this issue by checking for the availability of a callable output function and simply discarding the received task message otherwise. Signed-off-by: Jo-Philipp Wich <jo@mein.io>
2022-09-21ubus: hold reference to underlying connection until deferred is concludedJo-Philipp Wich
Prevent GC'ing (and thus tearing down) an active ubus connection as long as there's still unfinished deferred request contexts alive. Signed-off-by: Jo-Philipp Wich <jo@mein.io>
2022-09-21lib: uc_system(): retry waitpid() on EINTRJo-Philipp Wich
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
2022-09-09Merge pull request #104 from jow-/ubus-improvementsJo-Philipp Wich
ubus: various improvements
2022-09-09ubus: support obtaining numeric error codeJo-Philipp Wich
Some ubus users require access to the original ubus error status returned by various operations for fine grained error handling. Extend the error() function with an optional boolean argument which causes the function to return the numeric error code instead of a preformatted message when invoked. Signed-off-by: Jo-Philipp Wich <jo@mein.io>
2022-09-09ubus: add toplevel constants for ubus status codesJo-Philipp Wich
Add constants for ubus status codes to the toplevel module scope in order to avoid the need for magic values in the code. Suggested-by: Felix Fietkau <nbd@nbd.name> Signed-off-by: Jo-Philipp Wich <jo@mein.io>
2022-09-09ubus: allow object method call handlers to return a numeric status codeJo-Philipp Wich
The implicit return style for sending ubus method replies currently always emits an UBUS_STATUS_NO_DATA code in case neither req.reply() was called, nor a deferred or object were returned by the handler function. This slightly complicates the implementation of handlers that do not wish to send reply data but simply acknowledge the request with an UBUS_STATUS_OK code. In order to simplify this use case, allow handlers to override the default status by treating integer return values as ubus error codes. After this change, the following handler: function (request) { /* do some work */ request.reply(null, 0); } ... can be rewritten as: function (request) { /* do some work */ return 0; } Suggested-by: Felix Fietkau <nbd@nbd.name> Signed-off-by: Jo-Philipp Wich <jo@mein.io>
2022-09-05lib: add limit support to split() and replace()Jo-Philipp Wich
Extend the split() and replace() functions to accept an additional optional `limit` argument which limits the amount of split operations / substitutions performed by these functions. Signed-off-by: Jo-Philipp Wich <jo@mein.io>
2022-09-05Merge pull request #103 from jow-/fs-open-permission-argumentJo-Philipp Wich
fs: add optional third permission argument to fs.open()
2022-09-05Merge pull request #102 from jow-/lib-remove-regex-capture-group-limitsJo-Philipp Wich
lib: remove fixed capture group limit in match() and regex replace()
2022-09-05fs: add optional third permission argument to fs.open()Jo-Philipp Wich
Rework the `fs.open()` implementation to accept an optional third file permission argument which is applied to newly created files. Signed-off-by: Jo-Philipp Wich <jo@mein.io>
2022-09-05lib: remove fixed capture group limit in match() and regex replace()Jo-Philipp Wich
Instead of supporting only up to 10 potential regular expression captures, infer the amount of required captures directly from the compiled regexp structure and allocate the match range array dynamically. Signed-off-by: Jo-Philipp Wich <jo@mein.io>
2022-08-29lib: extend render() to support function valuesJo-Philipp Wich
Extend the `render()` function to accept a function value as first argument, which allows running arbitrary ucode functions and capturing their output. This is especially useful in conjunction with `loadfile()` or `loadstring()` to dynamically compile templates and rendering their output into a string. Signed-off-by: Jo-Philipp Wich <jo@mein.io>
2022-08-29lib: improve getenv() and split() implementationsJo-Philipp Wich
- getenv(): Allow querying the entire environment by omiting variable name - split(): Properly handle null bytes in subject and separator strings Signed-off-by: Jo-Philipp Wich <jo@mein.io>
2022-08-24examples: add module search path initialization and freeingJo-Philipp Wich
Since commit 3c168b5 ("vm, cli: move search path into global config...") it is required to explicitly initialize the module search path in the configuration structure for compile time module imports and run time require operations to work. Signed-off-by: Jo-Philipp Wich <jo@mein.io>
2022-08-24ubus: fix GCC strncpy() truncation warningJo-Philipp Wich
When building with gcc-10 and -O2, the following warning in ubus.c is triggered during the compilation: In function ‘uc_ubus_object_register’, inlined from ‘uc_ubus_publish’ at .../ubus.c:1521:10: .../ubus.c:1464:14: error: ‘strncpy’ output truncated before terminating nul copying as many bytes from a string as its length [-Werror=stringop-truncation] 1464 | obj->name = strncpy(onptr, ubus_object_name, namelen); | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .../ubus.c: In function ‘uc_ubus_publish’: .../ubus.c:1447:12: note: length computed here 1447 | namelen = strlen(ubus_object_name); | ^~~~~~~~~~~~~~~~~~~~~~~~ cc1: all warnings being treated as errors Solve this issue by using memcpy() instead. We already take care of allocating a zeroed, strlen() + 1 sized destination buffer so loosing the `\0` byte of the source string is perfectly fine. Fixes: #100 Signed-off-by: Jo-Philipp Wich <jo@mein.io>
2022-08-24Merge pull request #101 from jow-/loadfile-supportJo-Philipp Wich
lib: introduce three new functions call(), loadstring() and loadfile()
2022-08-24lib: introduce three new functions call(), loadstring() and loadfile()Jo-Philipp Wich
Introduce new functions dealing with on-the-fly compilation of code and execution of functions with different global scope. The `loadstring()` and `loadfile()` functions will compile the given ucode source string or ucode file path respectively and return the entry function of the resulting program. An optional dictionary specifying parse options may be given as second argument. Both functions return `null` on invalid arguments and throw an exception in case of compilation errors. The `call()` function allows invoking a given function value with a different `this` context and/or a different global environment. Finally refactor the existing `uc_require_ucode()` implementation to reuse the new `uc_loadfile()` and `uc_call()` implementations and adjust as well as simplify affected testcases. Signed-off-by: Jo-Philipp Wich <jo@mein.io>
2022-08-24lib: introduce helper function for indenting error messagesJo-Philipp Wich
Factor out the nested syntax error message indentation logic into a separate helper procedure for reuse in other places. Signed-off-by: Jo-Philipp Wich <jo@mein.io>
2022-08-24lib: simplify include_path()Jo-Philipp Wich
Align the path resolving logic with compiler.c and use strrchr() and a width limited printf pattern to extract the directory name portion. Signed-off-by: Jo-Philipp Wich <jo@mein.io>
2022-08-24source: avoid null pointer access in uc_source_runpath_set()Jo-Philipp Wich
When loading a precompiled program from stdin, the input source runpath is unset which subsequently leads to a null pointer being passed to uc_source_runpath_set() when will then attempt to strdup() it, leading to a null pointer access. Properly handle this case and only duplicate non-null pointers. Signed-off-by: Jo-Philipp Wich <jo@mein.io>
2022-08-24types: gracefully handle unpatched upvalues in ucv_free()Jo-Philipp Wich
When a module function with unpatched upvalues is freed, ucv_free() might access a NULL pointer through ucv_put_value(), so make sure to skip those unset upvalue slots when freeing a closure. Signed-off-by: Jo-Philipp Wich <jo@mein.io>
2022-08-24README.md: document gc() functionJo-Philipp Wich
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
2022-08-12Merge pull request #99 from jow-/gc-controlJo-Philipp Wich
Implement periodic GC
2022-08-12main: introduce -g flag to allow enabling periodic gc from cliJo-Philipp Wich
Implement a new flag `-g` which takes an interval value and enables the periodic GC with the given interval for cyclic object structures in the VM if specified. Signed-off-by: Jo-Philipp Wich <jo@mein.io>
2022-08-12lib: implement gc()Jo-Philipp Wich
Introduce a new stdlib function `gc()` which allows controlling the periodic garbage collector from ucode. Signed-off-by: Jo-Philipp Wich <jo@mein.io>
2022-08-12vm: support automatic periodic GC runsJo-Philipp Wich
Introduce two new VM api functions uc_vm_gc_start() and uc_vm_gc_stop() which allow starting and stopping automatic periodic garbage collection of cyclic objects in the VM context. Signed-off-by: Jo-Philipp Wich <jo@mein.io>
2022-08-12types: treat vm->exports as GC rootsJo-Philipp Wich
We must not free objects being in the module export registry. Signed-off-by: Jo-Philipp Wich <jo@mein.io>
2022-08-07Merge pull request #98 from jow-/dynlink-supportJo-Philipp Wich
Add import statement support for dynamic extensions
2022-08-06compiler: add import statement support for dynamic extensionsJo-Philipp Wich
Utilize the new I_DYNLINK vm opcode to support import statements referring to dynamic extension modules. During compilation, the compiler will try to infer the type of the imported module from the resolved file path; if it ends with `.so`, the module is assumed to by a dynamic extension and loading/binding of the module is deferred to runtime using I_DYNLINK opcodes. Additionally, the `-c` cli option gained support for a new compiler flag `dynlink=...` which allows forcing a particular module name expression to be treated as dynamic extension. This is useful to e.g. force resolving `import { x } from "foo"` to a dynamic extension `foo.so` loaded at runtime even if a plain `foo.uc` exists in the search path during compilation or if no such module is available at build time. Signed-off-by: Jo-Philipp Wich <jo@mein.io>
2022-08-06vm: introduce new I_DYNLOAD opcodeJo-Philipp Wich
The I_DYNLOAD opcode is basically a bytecode level instruction for uc_require() with semantics similar to I_IMPORT. It allows loading a dynamic extension library at runtime and treating values from the resulting module context object like exports from a compile time source module. For example the statement `import { readfile, writefile } from "fs"` would import the readfile() and writefile() functions of fs.so as readonly live bindings into the current file scope. Signed-off-by: Jo-Philipp Wich <jo@mein.io>
2022-08-06lib: internally expose new uc_require_library() helperJo-Philipp Wich
Break out the core logic of the uc_require() stl function into a new uc_require_library() helper function and make it available for usage outside of lib.c. Also add a new boolean parameter to the helper function which allows restricting runtime require operations of modules to dynamic libraries only. Signed-off-by: Jo-Philipp Wich <jo@mein.io>
2022-08-06vm: don't treat offset 0 special for exceptionsJo-Philipp Wich
Try to resolve the source offset to line and character position and only fall back to report the location as instruction offset if we weren't able to determine the line number. Signed-off-by: Jo-Philipp Wich <jo@mein.io>
2022-08-06compiler: don't treat offset 0 special at syntax errorsJo-Philipp Wich
If a compile error is raised at offset 0, try to resolve line and character position anyway. Signed-off-by: Jo-Philipp Wich <jo@mein.io>
2022-08-06Merge pull request #97 from jow-/module-import-export-fixesJo-Philipp Wich
2022-08-05compiler: improve formatting of nested syntax error messagesJo-Philipp Wich
Indent inner messages and prepend them with a vertical bar to increase visual separation of messages. Also include file name in source context output when the compiled program contains more than one source file. Adjust affected testcase outputs accordingly. Signed-off-by: Jo-Philipp Wich <jo@mein.io>
2022-08-05program: remove now unused uc_program_export_lookup()Jo-Philipp Wich
Since we track the offsets in the compiler directly now there's no need to keep this function. Signed-off-by: Jo-Philipp Wich <jo@mein.io>