mirror of
https://github.com/ChaiScript/ChaiScript.git
synced 2026-07-31 00:37:02 +08:00
Fix #146: Add configuration options to selectively disable built-in functions
Add new Options enum values (No_Stdlib, No_IO, No_Prelude, No_JSON) that allow users to control which parts of the standard library are registered. Std_Lib::library() now accepts an options vector, and the ChaiScript convenience class forwards its options to the library builder. This enables use cases where only custom functions should be exposed to script users. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
2eb3279c39
commit
c3aa9ee6d5
@ -825,7 +825,7 @@ namespace chaiscript {
|
||||
ChaiScript(std::vector<std::string> t_modulepaths = {},
|
||||
std::vector<std::string> t_usepaths = {},
|
||||
std::vector<Options> t_opts = chaiscript::default_options())
|
||||
: ChaiScript_Basic(chaiscript::Std_Lib::library(),
|
||||
: ChaiScript_Basic(chaiscript::Std_Lib::library(t_opts),
|
||||
std::make_unique<parser::ChaiScript_Parser<eval::Noop_Tracer, optimizer::Optimizer_Default>>(),
|
||||
std::move(t_modulepaths),
|
||||
std::move(t_usepaths),
|
||||
|
||||
@ -208,7 +208,11 @@ namespace chaiscript {
|
||||
No_Load_Modules,
|
||||
Load_Modules,
|
||||
No_External_Scripts,
|
||||
External_Scripts
|
||||
External_Scripts,
|
||||
No_Stdlib,
|
||||
No_IO,
|
||||
No_Prelude,
|
||||
No_JSON
|
||||
};
|
||||
|
||||
template<typename From, typename To>
|
||||
|
||||
@ -38,9 +38,18 @@
|
||||
namespace chaiscript {
|
||||
class Std_Lib {
|
||||
public:
|
||||
[[nodiscard]] static ModulePtr library() {
|
||||
[[nodiscard]] static ModulePtr library(const std::vector<Options> &t_opts = {}) {
|
||||
if (std::find(t_opts.begin(), t_opts.end(), Options::No_Stdlib) != t_opts.end()) {
|
||||
return std::make_shared<Module>();
|
||||
}
|
||||
|
||||
auto lib = std::make_shared<Module>();
|
||||
bootstrap::Bootstrap::bootstrap(*lib);
|
||||
|
||||
const bool no_io = std::find(t_opts.begin(), t_opts.end(), Options::No_IO) != t_opts.end();
|
||||
const bool no_prelude = std::find(t_opts.begin(), t_opts.end(), Options::No_Prelude) != t_opts.end();
|
||||
const bool no_json = std::find(t_opts.begin(), t_opts.end(), Options::No_JSON) != t_opts.end();
|
||||
|
||||
bootstrap::Bootstrap::bootstrap(*lib, no_io);
|
||||
|
||||
bootstrap::standard_library::vector_type<std::vector<Boxed_Value>>("Vector", *lib);
|
||||
bootstrap::standard_library::string_type<std::string>("string", *lib);
|
||||
@ -54,9 +63,13 @@ namespace chaiscript {
|
||||
"async");
|
||||
#endif
|
||||
|
||||
json_wrap::library(*lib);
|
||||
if (!no_json) {
|
||||
json_wrap::library(*lib);
|
||||
}
|
||||
|
||||
lib->eval(ChaiScript_Prelude::chaiscript_prelude() /*, "standard prelude"*/);
|
||||
if (!no_prelude) {
|
||||
lib->eval(ChaiScript_Prelude::chaiscript_prelude() /*, "standard prelude"*/);
|
||||
}
|
||||
|
||||
return lib;
|
||||
}
|
||||
|
||||
@ -266,8 +266,8 @@ namespace chaiscript::bootstrap {
|
||||
public:
|
||||
/// \brief perform all common bootstrap functions for std::string, void and POD types
|
||||
/// \param[in,out] m Module to add bootstrapped functions to
|
||||
/// \returns passed in Module
|
||||
static void bootstrap(Module &m) {
|
||||
/// \param[in] t_no_io If true, skip registering print_string and println_string
|
||||
static void bootstrap(Module &m, const bool t_no_io = false) {
|
||||
m.add(user_type<void>(), "void");
|
||||
m.add(user_type<bool>(), "bool");
|
||||
m.add(user_type<Boxed_Value>(), "Object");
|
||||
@ -435,8 +435,10 @@ namespace chaiscript::bootstrap {
|
||||
m.add(fun(&Build_Info::compiler_id), "compiler_id");
|
||||
m.add(fun(&Build_Info::debug_build), "debug_build");
|
||||
|
||||
m.add(fun(&print), "print_string");
|
||||
m.add(fun(&println), "println_string");
|
||||
if (!t_no_io) {
|
||||
m.add(fun(&print), "print_string");
|
||||
m.add(fun(&println), "println_string");
|
||||
}
|
||||
|
||||
m.add(dispatch::make_dynamic_proxy_function(&bind_function), "bind");
|
||||
|
||||
|
||||
@ -1283,3 +1283,93 @@ TEST_CASE("Test if non copyable/movable types can be registered") {
|
||||
chai.add(chaiscript::user_type<Nothing>(), "Nothing");
|
||||
chai.add(chaiscript::constructor<Nothing()>(), "Nothing");
|
||||
}
|
||||
|
||||
// Tests for issue #146: configuration to bypass registering built-in functions
|
||||
|
||||
TEST_CASE("No_Stdlib option disables all standard library functions") {
|
||||
chaiscript::ChaiScript_Basic chai(chaiscript::Std_Lib::library({chaiscript::Options::No_Stdlib}),
|
||||
create_chaiscript_parser(),
|
||||
{},
|
||||
{},
|
||||
{chaiscript::Options::No_Load_Modules, chaiscript::Options::No_External_Scripts});
|
||||
|
||||
// Core types should still work (they are part of bootstrap)
|
||||
CHECK_NOTHROW(chai.eval("var x = 5"));
|
||||
|
||||
// print should not exist
|
||||
CHECK_THROWS(chai.eval("print(\"hello\")"));
|
||||
|
||||
// Vector should not exist
|
||||
CHECK_THROWS(chai.eval("var v = Vector()"));
|
||||
|
||||
// String methods from prelude should not exist
|
||||
CHECK_THROWS(chai.eval("\"hello\".trim()"));
|
||||
|
||||
// JSON should not exist
|
||||
CHECK_THROWS(chai.eval("from_json(\"[1,2,3]\")"));
|
||||
}
|
||||
|
||||
TEST_CASE("No_IO option disables print functions") {
|
||||
chaiscript::ChaiScript_Basic chai(chaiscript::Std_Lib::library({chaiscript::Options::No_IO}),
|
||||
create_chaiscript_parser(),
|
||||
{},
|
||||
{},
|
||||
{chaiscript::Options::No_Load_Modules, chaiscript::Options::No_External_Scripts});
|
||||
|
||||
// print_string and println_string should not exist
|
||||
CHECK_THROWS(chai.eval("print_string(\"hello\")"));
|
||||
CHECK_THROWS(chai.eval("println_string(\"hello\")"));
|
||||
|
||||
// Other functionality should still work
|
||||
CHECK(chai.eval<int>("5 + 3") == 8);
|
||||
CHECK_NOTHROW(chai.eval("var v = Vector()"));
|
||||
}
|
||||
|
||||
TEST_CASE("No_Prelude option disables prelude functions") {
|
||||
chaiscript::ChaiScript_Basic chai(chaiscript::Std_Lib::library({chaiscript::Options::No_Prelude}),
|
||||
create_chaiscript_parser(),
|
||||
{},
|
||||
{},
|
||||
{chaiscript::Options::No_Load_Modules, chaiscript::Options::No_External_Scripts});
|
||||
|
||||
// print (from prelude) should not exist
|
||||
CHECK_THROWS(chai.eval("print(\"hello\")"));
|
||||
|
||||
// But print_string (from bootstrap) should still work
|
||||
CHECK_NOTHROW(chai.eval("print_string(\"hello\")"));
|
||||
|
||||
// Prelude utility functions should not exist
|
||||
CHECK_THROWS(chai.eval("filter([1,2,3], fun(x) { x > 1 })"));
|
||||
|
||||
// Core arithmetic should still work
|
||||
CHECK(chai.eval<int>("5 + 3") == 8);
|
||||
}
|
||||
|
||||
TEST_CASE("No_JSON option disables JSON support") {
|
||||
chaiscript::ChaiScript_Basic chai(chaiscript::Std_Lib::library({chaiscript::Options::No_JSON}),
|
||||
create_chaiscript_parser(),
|
||||
{},
|
||||
{},
|
||||
{chaiscript::Options::No_Load_Modules, chaiscript::Options::No_External_Scripts});
|
||||
|
||||
// JSON functions should not exist
|
||||
CHECK_THROWS(chai.eval("from_json(\"[1,2,3]\")"));
|
||||
|
||||
// Other functionality should still work
|
||||
CHECK(chai.eval<int>("5 + 3") == 8);
|
||||
CHECK_NOTHROW(chai.eval("print(\"hello\")"));
|
||||
}
|
||||
|
||||
TEST_CASE("Default library has all functions") {
|
||||
chaiscript::ChaiScript_Basic chai(chaiscript::Std_Lib::library(),
|
||||
create_chaiscript_parser(),
|
||||
{},
|
||||
{},
|
||||
{chaiscript::Options::No_Load_Modules, chaiscript::Options::No_External_Scripts});
|
||||
|
||||
// Everything should work with default options
|
||||
CHECK_NOTHROW(chai.eval("print(\"hello\")"));
|
||||
CHECK_NOTHROW(chai.eval("print_string(\"hello\")"));
|
||||
CHECK_NOTHROW(chai.eval("var v = Vector()"));
|
||||
CHECK(chai.eval<int>("5 + 3") == 8);
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user