Age | Commit message (Collapse) | Author |
|
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
The naming is an artifact from before the introduction of the new type
system. In the current code, there is nothing special about prototypes,
they're simple object values.
Also introduce a new singular uc_add_function() convenience macro while
we're at it.
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
Ensure to increase the refcount of the module scope value when caching it
in the global module registry to avoid a double free on VM teardown.
Fixes: 96f140b ("lib, vm: ensure that require() compiles modules only once")
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
Cache the result of a successful require operation in a global.modules
object and return the cached value for subsequent require calls on the
same module name.
This ensures that a given module is only compiled and executed once,
regardless of how many times it is used.
A reload of the module can be forced by deleting the corresponding
key in the global module table.
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
This allows us to drop some token->instruction mapping case switches
in the VM.
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
The new functions allow encoding and decoding base64 values respectively.
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
Do not walk up the entire call stack but specifically use the context of the
callframe calling the C function.
Fixes: 3e893e6 ("lib: pass-through "this" context to library function callbacks")
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
Ensure that callbacks invoked by filter(), map(), sort() and replace()
inherit the "this" context that invoked the respective C function.
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
The sourcepath() function allows querying the filesystem path of the source
file currently being executed by ucode.
The optional depth argument can be used to walk up the include stack to
determine the path of the file that included the current file, the path of
the parent file of the parent file and so on.
By specifying a truish value as second argument, only the directory portion
of the source file path is returned. This is useful to e.g. discover
ressources relative to the current source file directory.
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
The numeric return value was incorrectly stored in an unsigned size_t
variable which got later wrapped in an ucode signed 64bit integer value.
This worked by accident on 64bit systems since (int64_t)(size_t)(-1) == -1,
but it failed on 32bit ones where (int64_t)(size_t)(-1) yields 4294967295
due to the different sizes of the size_t and int64_t types.
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
Turn the Infinity and NaN keywords into global properties.
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
Turn `delete` into a proper operator mimicking ECMAScript semantics.
Also ensure to transparently turn deprecated `delete(obj, propname)`
function calls into `delete obj.propname` expressions during compilation.
When strict mode is active, legacy delete() calls throw a syntax error
instead.
Finally drop the `delete()` function from the stdlib as it is shadowed
by the delete operator syntax now.
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
Provide a new ucode function regexp() which allows constructing regular
expression instances from separate source and flag strings.
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
The internally used qsort(3) expects [-n, 0, n] return values from the
comparator function instead of a true/false value to denote lower than
or equal results.
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
Honour precision specifiers when parsing `J` format strings to enable or
disable JSON pretty printing.
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
- Ensure that split by string produces an initial empty string in the
result array when the string to split starts with the split substring
- Ensure that split by string produces a trailing empty string in the
result array when the string to split ends with the split substring
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
- Shuffle typedefs to avoid need for non-compliant forward declarations
- Fix non-compliant empty struct initializers
- Remove use of braced expressions
- Remove use of anonymous unions
- Avoid `void *` pointer arithmetic
- Fix several warnings reported by gcc -pedantic mode and clang 11 compilation
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
Instead of relying on json_object values internally, use custom types to
represent the different ucode value types which brings a number of
advantages compared to the previous approach:
- Due to the use of tagged pointers, small integer, string and bool
values can be stored directly in the pointer addresses, vastly
reducing required heap memory
- Ability to create circular data structures such as
`let o; o = { test: o };`
- Ability to register custom `tostring()` function through prototypes
- Initial mark/sweep GC implementation to tear down circular object
graphs on VM deinit
The change also paves the way for possible future extensions such as
constant variables and meta methods for custom ressource types.
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
Make sure to increase the refcount of items being moved since the
subsequent put operation will decrease it, prematurely freeing
moved items which will lead to use-after-free errors later on.
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
The ref count of the unshifted value returned by uc_unshift() must be
increased in order to prevent a subsequent double free within the VM
when the value eventually goes out of scope.
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
Use execvp() instead of execv() to lookup the specified executable in $PATH.
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
Change uc_include() to retain the prototype of the given scope object when
processing includes. Also change the default behaviour to register the
current VM scope as prototype on the passed scope object so that included
code has access to functions such as length(), print() etc. by default.
To actually sandbox the included code, the new `proto()` function can be
used to create a scope object with an empty prototype:
`include(..., proto({ ... }, {}))`
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
The proto() function allows getting and setting the prototype value of
array or object values, which is useful to build object instances.
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
Replace the former AST walking interpreter implementation with a single pass
bytecode compiler and a corresponding virtual machine.
The rewrite lays the groundwork for a couple of improvements with will be
subsequently implemented:
- Ability to precompile ucode sources into binary byte code
- Strippable debug information
- Reduced runtime memory usage
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
Instead of obtaining and caching direct opcode pointers, use relative
references when dealing with opcodes since direct or indirect calls to
uc_execute_op() might lead to reallocations of the opcode array, shifting
memory addresses and invalidating pointers taken before the invocation.
Such stale pointer accesses could be commonly triggered when one part
of the processed expression was a require() or include() call loading
relatively large ucode sources.
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
Instead of counting the keys individually, use the existing
json_object_object_length() function.
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|