Age | Commit message (Collapse) | Author |
|
fs: expose `getdelim()` functionality through `fd.read()`
|
|
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>
|
|
fs: use `getline()` for line wise read operations
|
|
lexer: fixes for regex literal parsing
|
|
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>
|
|
- 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>
|
|
lib: implement slice() function
|
|
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>
|
|
Various improvements
|
|
Introduce a new `-p` flag which works like `-e` but prints the final
expression result.
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
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>
|
|
- 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>
|
|
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>
|
|
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>
|
|
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>
|
|
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
ubus: various improvements
|
|
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>
|
|
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>
|
|
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>
|
|
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>
|
|
fs: add optional third permission argument to fs.open()
|
|
lib: remove fixed capture group limit in match() and regex replace()
|
|
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>
|
|
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>
|
|
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>
|
|
- 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>
|
|
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>
|
|
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>
|
|
lib: introduce three new functions call(), loadstring() and loadfile()
|
|
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>
|
|
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>
|
|
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>
|
|
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>
|
|
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>
|
|
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
Implement periodic GC
|
|
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>
|
|
Introduce a new stdlib function `gc()` which allows controlling the periodic
garbage collector from ucode.
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
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>
|
|
We must not free objects being in the module export registry.
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
Add import statement support for dynamic extensions
|
|
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>
|
|
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>
|
|
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>
|
|
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>
|
|
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>
|
|
|
|
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>
|
|
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>
|