Skip to content

Commit 7877e93

Browse files
evaluate_string: document in API and allow custom environments
1 parent b238303 commit 7877e93

File tree

2 files changed

+56
-10
lines changed

2 files changed

+56
-10
lines changed

docs/addons.md

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -717,6 +717,42 @@ Both keys and values are copied. If `depth` is undefined then it defaults to `ma
717717
Additionally, the original table is stored in the `__original` field of the copy's metatable.
718718
The copy behaviour of the metatable itself is subject to change, but currently it is not copied.
719719

720+
#### `fb.evaluate_string(str: string, chunkname?: string, env?: table, defaults?: bool = true): unknown`
721+
722+
Loads `str` as a chunk of Lua statement(s) and runs them, returning the result.
723+
Errors are propagated to the caller. `chunkname` is used
724+
for debug output and error messages.
725+
726+
Each chunk has a separate global environment table that inherits
727+
from the main global table. This means new globals can be created safely,
728+
but the default globals can still be accessed. As such, this method
729+
cannot and should not be used for security or sandboxing.
730+
731+
A custom environment table can be provided with the `env` argument.
732+
Inheritance from the global table is disabled if `defaults` is `false`.
733+
734+
Examples:
735+
736+
```lua
737+
fb.evaluate_string('return 5 + 5') -- 10
738+
fb.evaluate_string('x = 20 ; return x * x') -- 400
739+
740+
local code = [[
741+
local arr = {1, 2, 3, 4}
742+
table.insert(arr, x)
743+
return unpack(arr)
744+
]]
745+
fb.evaluate_string(code, 'test3', {x = 5}) -- 1, 2, 3, 4, 5
746+
fb.evaluate_string(code, 'test4', nil, false) -- Lua error: [string "test4"]:2: attempt to index global 'table' (a nil value)
747+
748+
```
749+
750+
In an expression the `mp`, `mp.msg`, and `mp.utils` modules are available as `mp`, `msg`, and `utils` respectively.
751+
Additionally, in mpv v0.38+ the `mp.input` module is available as `input`.
752+
This addon API is available as `fb` and if [mpv-user-input](https://github.com/CogentRedTester/mpv-user-input)
753+
is installed then user-input will be available in `user_input`.
754+
These modules are all unavailable if `defaults` is `false`.
755+
720756
#### `fb.filter(list: list_table): list_table`
721757

722758
Iterates through the given list and removes items that don't pass the user set filters

modules/utils.lua

Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,10 @@ function fb_utils.redirect_table(t)
7676
return setmetatable({}, { __index = t })
7777
end
7878

79+
function fb_utils.set_prototype(t, proto)
80+
return setmetatable(t, { __index = proto })
81+
end
82+
7983
--prints an error if a coroutine returns an error
8084
--unlike the next function this one still returns the results of coroutine.resume()
8185
function fb_utils.coroutine.resume_catch(...)
@@ -372,21 +376,27 @@ end
372376
--evaluates and runs the given string in both Lua 5.1 and 5.2
373377
--the name argument is used for error reporting
374378
--provides the mpv modules and the fb module to the string
375-
function fb_utils.evaluate_string(str, name)
376-
local env = fb_utils.redirect_table(_G)
377-
env.mp = fb_utils.redirect_table(mp)
378-
env.msg = fb_utils.redirect_table(msg)
379-
env.utils = fb_utils.redirect_table(utils)
380-
env.fb = fb_utils.redirect_table(fb_utils)
381-
env.input = input_loaded and fb_utils.redirect_table(input)
382-
env.user_input = user_input_loaded and fb_utils.redirect_table(user_input)
379+
function fb_utils.evaluate_string(str, chunkname, custom_env, env_defaults)
380+
local env
381+
if env_defaults ~= false then
382+
env = fb_utils.redirect_table(_G)
383+
env.mp = fb_utils.redirect_table(mp)
384+
env.msg = fb_utils.redirect_table(msg)
385+
env.utils = fb_utils.redirect_table(utils)
386+
env.fb = fb_utils.redirect_table(fb_utils)
387+
env.input = input_loaded and fb_utils.redirect_table(input)
388+
env.user_input = user_input_loaded and fb_utils.redirect_table(user_input)
389+
env = fb_utils.set_prototype(custom_env or {}, env)
390+
else
391+
env = custom_env or {}
392+
end
383393

384394
local chunk, err
385395
if setfenv then
386-
chunk, err = loadstring(str, name)
396+
chunk, err = loadstring(str, chunkname)
387397
if chunk then setfenv(chunk, env) end
388398
else
389-
chunk, err = load(str, name, 't', env)
399+
chunk, err = load(str, chunkname, 't', env)
390400
end
391401
if not chunk then
392402
msg.warn('failed to load string:', str)

0 commit comments

Comments
 (0)