mirror of
https://gitea.wildfiregames.com/0ad/0ad.git
synced 2026-06-21 01:04:06 +00:00
Disalow importing some files
Not all modules should be able to load all other modules. A predicate function can to be passed to the `ScriptInterface`. That function returns whether the module is allowed to loat the module. If no predicate is passed in no modules can be loaded through that `ScriptInterface`.
This commit is contained in:
@@ -92,8 +92,14 @@ VfsPath GetBaseFilename(const VfsPath& filename)
|
||||
return filenames;
|
||||
}
|
||||
|
||||
[[nodiscard]] std::string GetCode(const VfsPath& filePath)
|
||||
[[nodiscard]] std::string GetCode(const ModuleLoader::AllowModuleFunc& allowModule,
|
||||
const VfsPath& filePath)
|
||||
{
|
||||
if (!allowModule || !allowModule(filePath))
|
||||
{
|
||||
throw std::runtime_error{fmt::format("Importing file \"{}\" is disallowed.",
|
||||
filePath.string8())};
|
||||
}
|
||||
if (!VfsFileExists(filePath))
|
||||
throw std::runtime_error{fmt::format("The file \"{}\" does not exist.", filePath.string8())};
|
||||
|
||||
@@ -115,18 +121,19 @@ VfsPath GetBaseFilename(const VfsPath& filename)
|
||||
}
|
||||
|
||||
template<typename Requester>
|
||||
[[nodiscard]] JSObject* CompileModule(const ScriptRequest& rq, ModuleLoader::RegistryType& registry,
|
||||
[[nodiscard]] JSObject* CompileModule(const ScriptRequest& rq,
|
||||
const ModuleLoader::AllowModuleFunc& allowModule, ModuleLoader::RegistryType& registry,
|
||||
const VfsPath& filePath, Requester&& requester)
|
||||
{
|
||||
const VfsPath normalizedPath{filePath.fileSystemPath().lexically_normal().generic_string()};
|
||||
const auto insertResult = registry.try_emplace(normalizedPath, rq, normalizedPath);
|
||||
const auto insertResult = registry.try_emplace(normalizedPath, rq, allowModule, normalizedPath);
|
||||
ModuleLoader::CompiledModule& compiledModule{std::get<1>(*std::get<0>(insertResult))};
|
||||
compiledModule.AddRequester(std::forward<Requester>(requester));
|
||||
return compiledModule.m_ModuleObject;
|
||||
}
|
||||
|
||||
[[nodiscard]] JSObject* Resolve(const ScriptRequest& rq, ModuleLoader::RegistryType& registry,
|
||||
JS::HandleValue referencingModule, JS::HandleObject moduleRequest)
|
||||
[[nodiscard]] JSObject* Resolve(const ScriptRequest& rq, const ModuleLoader::AllowModuleFunc& allowModule,
|
||||
ModuleLoader::RegistryType& registry, JS::HandleValue referencingModule,
|
||||
JS::HandleObject moduleRequest)
|
||||
{
|
||||
std::string includeString;
|
||||
const JS::RootedValue pathValue{rq.cx,
|
||||
@@ -138,7 +145,7 @@ template<typename Requester>
|
||||
if (!Script::FromJSProperty(rq, referencingModule, "path", includingModule))
|
||||
throw std::logic_error{"The importing module doesn't have a \"path\" property."};
|
||||
|
||||
return CompileModule(rq, registry, includeString, includingModule);
|
||||
return CompileModule(rq, allowModule, registry, includeString, includingModule);
|
||||
}
|
||||
|
||||
[[nodiscard]] JSObject* Evaluate(const ScriptRequest& rq, JS::HandleObject mod)
|
||||
@@ -236,14 +243,16 @@ template<bool reject>
|
||||
constexpr JSClass callbackClass{"Callback", JSCLASS_HAS_RESERVED_SLOTS(1), &callbackClassOps<reject>};
|
||||
} // anonymous namespace
|
||||
|
||||
ModuleLoader::CompiledModule::CompiledModule(const ScriptRequest& rq, const VfsPath& filePath):
|
||||
ModuleLoader::CompiledModule::CompiledModule(const ScriptRequest& rq, const AllowModuleFunc& allowModule,
|
||||
const VfsPath& filePath):
|
||||
m_ModuleObject(rq.cx)
|
||||
{
|
||||
const std::vector<VfsPath> appendices{GetAppendices(filePath)};
|
||||
const std::string code{std::accumulate(appendices.begin(), appendices.end(), GetCode(filePath),
|
||||
[](std::string code, const VfsPath& fileToAppend)
|
||||
const std::string code{std::accumulate(appendices.begin(), appendices.end(),
|
||||
GetCode(allowModule, filePath),
|
||||
[&](std::string code, const VfsPath& fileToAppend)
|
||||
{
|
||||
return std::move(code) + GetCode(fileToAppend);
|
||||
return std::move(code) + GetCode(allowModule, fileToAppend);
|
||||
})};
|
||||
|
||||
JS::CompileOptions options{rq.cx};
|
||||
@@ -294,7 +303,7 @@ void ModuleLoader::CompiledModule::RemoveRequester(Result* toErase)
|
||||
}), m_Callbacks.end());
|
||||
}
|
||||
|
||||
ModuleLoader::Future::Future(const ScriptRequest& rq, RegistryType& registry, Result& result,
|
||||
ModuleLoader::Future::Future(const ScriptRequest& rq, ModuleLoader& loader, Result& result,
|
||||
VfsPath modulePath):
|
||||
m_Status{Evaluating{{rq.cx, nullptr}, {rq.cx, JS_NewObject(rq.cx, &callbackClass<false>)},
|
||||
{rq.cx, JS_NewObject(rq.cx, &callbackClass<true>)}}}
|
||||
@@ -307,7 +316,8 @@ ModuleLoader::Future::Future(const ScriptRequest& rq, RegistryType& registry, Re
|
||||
// - Accessing values which are not yet exported results in an error. These errors might implicitly be
|
||||
// dropped.
|
||||
|
||||
JS::RootedObject mod{rq.cx, CompileModule(rq, registry, modulePath, result)};
|
||||
JS::RootedObject mod{rq.cx, CompileModule(rq, loader.m_AllowModule, loader.m_Registry, modulePath,
|
||||
result)};
|
||||
JS::RootedObject promise{rq.cx, Evaluate(rq, mod)};
|
||||
Evaluating& evaluatingStatus{std::get<Evaluating>(m_Status)};
|
||||
evaluatingStatus.moduleNamespace = JS::GetModuleNamespace(rq.cx, mod);
|
||||
@@ -412,16 +422,16 @@ ModuleLoader::Result::iterator& ModuleLoader::Result::iterator::operator++(int)
|
||||
|
||||
ModuleLoader::Result::Result(const ScriptRequest& rq, const VfsPath& modulePath):
|
||||
m_Cx{rq.cx},
|
||||
m_Registry{rq.GetScriptInterface().GetModuleLoader().m_Registry},
|
||||
m_Loader{rq.GetScriptInterface().GetModuleLoader()},
|
||||
m_ModulePath{modulePath},
|
||||
m_Storage{rq, m_Registry, *this, m_ModulePath}
|
||||
m_Storage{rq, m_Loader, *this, m_ModulePath}
|
||||
{
|
||||
}
|
||||
|
||||
ModuleLoader::Result::~Result()
|
||||
{
|
||||
const auto modIter = m_Registry.find(m_ModulePath);
|
||||
if (modIter == m_Registry.end())
|
||||
const auto modIter = m_Loader.m_Registry.find(m_ModulePath);
|
||||
if (modIter == m_Loader.m_Registry.end())
|
||||
return;
|
||||
|
||||
std::get<1>(*modIter).RemoveRequester(this);
|
||||
@@ -440,10 +450,11 @@ ModuleLoader::Result::~Result()
|
||||
void ModuleLoader::Result::Resume()
|
||||
{
|
||||
if (m_Storage.IsWaiting())
|
||||
m_Storage = ModuleLoader::Future{m_Cx, m_Registry, *this, m_ModulePath};
|
||||
m_Storage = ModuleLoader::Future{m_Cx, m_Loader, *this, m_ModulePath};
|
||||
}
|
||||
|
||||
ModuleLoader::ModuleLoader()
|
||||
ModuleLoader::ModuleLoader(ModuleLoader::AllowModuleFunc allowModule):
|
||||
m_AllowModule{std::move(allowModule)}
|
||||
{
|
||||
RegisterFileReloadFunc(FileChangedHook, static_cast<void*>(&m_Registry));
|
||||
}
|
||||
@@ -485,8 +496,8 @@ ModuleLoader::~ModuleLoader()
|
||||
try
|
||||
{
|
||||
const ScriptRequest rq{cx};
|
||||
return Resolve(rq, rq.GetScriptInterface().GetModuleLoader().m_Registry, referencingPrivate,
|
||||
request);
|
||||
ModuleLoader& loader{rq.GetScriptInterface().GetModuleLoader()};
|
||||
return Resolve(rq, loader.m_AllowModule, loader.m_Registry, referencingPrivate, request);
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
@@ -506,7 +517,8 @@ ModuleLoader::~ModuleLoader()
|
||||
const ScriptRequest rq{cx};
|
||||
try
|
||||
{
|
||||
JS::RootedObject mod{rq.cx, Resolve(rq, rq.GetScriptInterface().GetModuleLoader().m_Registry,
|
||||
ModuleLoader& loader{rq.GetScriptInterface().GetModuleLoader()};
|
||||
JS::RootedObject mod{rq.cx, Resolve(rq, loader.m_AllowModule, loader.m_Registry,
|
||||
referencingPrivate, moduleRequest)};
|
||||
JS::RootedObject evaluationPromise{rq.cx, Evaluate(rq, mod)};
|
||||
return JS::FinishDynamicModuleImport(rq.cx, evaluationPromise, referencingPrivate,
|
||||
|
||||
@@ -42,9 +42,10 @@ public:
|
||||
class Future;
|
||||
class Result;
|
||||
|
||||
using AllowModuleFunc = std::function<bool(const VfsPath&)>;
|
||||
using RegistryType = std::unordered_map<VfsPath, CompiledModule>;
|
||||
|
||||
ModuleLoader();
|
||||
ModuleLoader(AllowModuleFunc allowModule);
|
||||
ModuleLoader(const ModuleLoader&) = delete;
|
||||
ModuleLoader& operator=(const ModuleLoader&) = delete;
|
||||
ModuleLoader(ModuleLoader&&) = delete;
|
||||
@@ -72,13 +73,14 @@ private:
|
||||
[[nodiscard]] static bool DynamicImportHook(JSContext* cx, JS::HandleValue referencingPrivate,
|
||||
JS::HandleObject moduleRequest, JS::HandleObject promise) noexcept;
|
||||
|
||||
AllowModuleFunc m_AllowModule;
|
||||
RegistryType m_Registry;
|
||||
};
|
||||
|
||||
class ModuleLoader::CompiledModule
|
||||
{
|
||||
public:
|
||||
CompiledModule(const ScriptRequest& rq, const VfsPath& filePath);
|
||||
CompiledModule(const ScriptRequest& rq, const AllowModuleFunc& allowModule, const VfsPath& filePath);
|
||||
|
||||
std::tuple<const std::vector<VfsPath>&,
|
||||
const std::vector<std::reference_wrapper<Result>>&> GetRequesters() const;
|
||||
@@ -120,7 +122,7 @@ public:
|
||||
struct Invalid {};
|
||||
using Status = std::variant<Evaluating, Fulfilled, Rejected, WaitingForFileChange, Invalid>;
|
||||
|
||||
explicit Future(const ScriptRequest& rq, RegistryType& reqistry, Result& result, VfsPath modulePath);
|
||||
explicit Future(const ScriptRequest& rq, ModuleLoader& reqistry, Result& result, VfsPath modulePath);
|
||||
Future() = default;
|
||||
Future(const Future&) = delete;
|
||||
Future& operator=(const Future&) = delete;
|
||||
@@ -165,7 +167,7 @@ public:
|
||||
|
||||
private:
|
||||
JSContext* m_Cx;
|
||||
RegistryType& m_Registry;
|
||||
ModuleLoader& m_Loader;
|
||||
VfsPath m_ModulePath;
|
||||
Future m_Storage;
|
||||
};
|
||||
|
||||
@@ -53,7 +53,8 @@
|
||||
|
||||
struct ScriptInterface_impl
|
||||
{
|
||||
ScriptInterface_impl(const char* nativeScopeName, ScriptContext& context, JS::Compartment* compartment);
|
||||
ScriptInterface_impl(const char* nativeScopeName, ScriptContext& context,
|
||||
JS::Compartment* compartment, std::function<bool(const VfsPath&)> allowModule);
|
||||
~ScriptInterface_impl();
|
||||
|
||||
// Take care to keep this declaration before heap rooted members. Destructors of heap rooted
|
||||
@@ -303,9 +304,10 @@ bool ScriptInterface::Math_random(JSContext* cx, uint argc, JS::Value* vp)
|
||||
}
|
||||
|
||||
ScriptInterface_impl::ScriptInterface_impl(const char* nativeScopeName, ScriptContext& context,
|
||||
JS::Compartment* compartment) :
|
||||
JS::Compartment* compartment, std::function<bool(const VfsPath&)> allowModule) :
|
||||
m_context(context), m_cx(context.GetGeneralJSContext()), m_glob(context.GetGeneralJSContext()),
|
||||
m_nativeScope(context.GetGeneralJSContext())
|
||||
m_nativeScope(context.GetGeneralJSContext()),
|
||||
m_ModuleLoader{std::move(allowModule)}
|
||||
{
|
||||
JS::RealmCreationOptions creationOpt;
|
||||
// Keep JIT code during non-shrinking GCs. This brings a quite big performance improvement.
|
||||
@@ -351,8 +353,10 @@ ScriptInterface_impl::~ScriptInterface_impl()
|
||||
m_context.UnRegisterRealm(JS::GetObjectRealmOrNull(m_glob));
|
||||
}
|
||||
|
||||
ScriptInterface::ScriptInterface(const char* nativeScopeName, const char* debugName, ScriptContext& context) :
|
||||
m(std::make_unique<ScriptInterface_impl>(nativeScopeName, context, nullptr))
|
||||
ScriptInterface::ScriptInterface(const char* nativeScopeName, const char* debugName, ScriptContext& context,
|
||||
std::function<bool(const VfsPath&)> allowModule) :
|
||||
m{std::make_unique<ScriptInterface_impl>(nativeScopeName, context, nullptr,
|
||||
std::move(allowModule))}
|
||||
{
|
||||
// Profiler stats table isn't thread-safe, so only enable this on the main thread
|
||||
if (Threading::IsMainThread())
|
||||
@@ -366,11 +370,13 @@ ScriptInterface::ScriptInterface(const char* nativeScopeName, const char* debugN
|
||||
JS::SetRealmPrivate(JS::GetObjectRealmOrNull(rq.glob), (void*)&m_CmptPrivate);
|
||||
}
|
||||
|
||||
ScriptInterface::ScriptInterface(const char* nativeScopeName, const char* debugName, const ScriptInterface& neighbor)
|
||||
ScriptInterface::ScriptInterface(const char* nativeScopeName, const char* debugName,
|
||||
const ScriptInterface& neighbor, std::function<bool(const VfsPath& path)> allowModule)
|
||||
{
|
||||
ScriptRequest nrq(neighbor);
|
||||
JS::Compartment* comp = JS::GetCompartmentForRealm(JS::GetCurrentRealmOrNull(nrq.cx));
|
||||
m = std::make_unique<ScriptInterface_impl>(nativeScopeName, neighbor.GetContext(), comp);
|
||||
m = std::make_unique<ScriptInterface_impl>(nativeScopeName, neighbor.GetContext(), comp,
|
||||
std::move(allowModule));
|
||||
|
||||
// Profiler stats table isn't thread-safe, so only enable this on the main thread
|
||||
if (Threading::IsMainThread())
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
#include "scriptinterface/ScriptTypes.h"
|
||||
|
||||
#include <unordered_map>
|
||||
#include <functional>
|
||||
|
||||
ERROR_GROUP(Scripting);
|
||||
ERROR_TYPE(Scripting, SetupFailed);
|
||||
@@ -82,11 +83,13 @@ public:
|
||||
* @param debugName Name of this interface for CScriptStats purposes.
|
||||
* @param context ScriptContext to use when initializing this interface.
|
||||
*/
|
||||
ScriptInterface(const char* nativeScopeName, const char* debugName, ScriptContext& context);
|
||||
ScriptInterface(const char* nativeScopeName, const char* debugName, ScriptContext& context,
|
||||
std::function<bool(const VfsPath&)> allowModule = {});
|
||||
|
||||
template<typename Context>
|
||||
ScriptInterface(const char* nativeScopeName, const char* debugName, Context&& context) :
|
||||
ScriptInterface(nativeScopeName, debugName, *context)
|
||||
ScriptInterface(const char* nativeScopeName, const char* debugName, Context&& context,
|
||||
std::function<bool(const VfsPath&)> allowModule = {}) :
|
||||
ScriptInterface{nativeScopeName, debugName, *context, std::move(allowModule)}
|
||||
{
|
||||
static_assert(std::is_lvalue_reference_v<Context>, "`ScriptInterface` doesn't take ownership "
|
||||
"of the context.");
|
||||
@@ -99,8 +102,11 @@ public:
|
||||
* be placed into, as a scoping mechanism; typically "Engine"
|
||||
* @param debugName Name of this interface for CScriptStats purposes.
|
||||
* @param scriptInterface 'Neighbor' scriptInterface to share a compartment with.
|
||||
* @param allowModule A predicate deciding wheter to import the given
|
||||
* module.
|
||||
*/
|
||||
ScriptInterface(const char* nativeScopeName, const char* debugName, const ScriptInterface& neighbor);
|
||||
ScriptInterface(const char* nativeScopeName, const char* debugName, const ScriptInterface& neighbor,
|
||||
std::function<bool(const VfsPath&)> allowModule = {});
|
||||
|
||||
~ScriptInterface();
|
||||
|
||||
|
||||
@@ -65,6 +65,16 @@ void ClearFromCache(const VfsPath& path)
|
||||
|
||||
ReloadChangedFiles();
|
||||
}
|
||||
|
||||
bool AllowAllPredicate(const VfsPath&)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool DisallowedfilePredicate(const VfsPath& path)
|
||||
{
|
||||
return path != "restriction/disallowedfile.js";
|
||||
}
|
||||
}
|
||||
|
||||
class TestScriptModule : public CxxTest::TestSuite
|
||||
@@ -90,7 +100,7 @@ public:
|
||||
|
||||
void test_StaticImport()
|
||||
{
|
||||
ScriptInterface script{"Test", "Test", g_ScriptContext};
|
||||
ScriptInterface script{"Test", "Test", g_ScriptContext, AllowAllPredicate};
|
||||
const ScriptRequest rq{script};
|
||||
|
||||
TestLogger logger;
|
||||
@@ -103,12 +113,12 @@ public:
|
||||
void test_Sequential()
|
||||
{
|
||||
{
|
||||
ScriptInterface script{"Test", "Test", g_ScriptContext};
|
||||
ScriptInterface script{"Test", "Test", g_ScriptContext, AllowAllPredicate};
|
||||
const ScriptRequest rq{script};
|
||||
std::ignore = script.GetModuleLoader().LoadModule(rq, "empty.js");
|
||||
}
|
||||
{
|
||||
ScriptInterface script{"Test", "Test", g_ScriptContext};
|
||||
ScriptInterface script{"Test", "Test", g_ScriptContext, AllowAllPredicate};
|
||||
const ScriptRequest rq{script};
|
||||
std::ignore = script.GetModuleLoader().LoadModule(rq, "empty.js");
|
||||
}
|
||||
@@ -116,10 +126,10 @@ public:
|
||||
|
||||
void test_Stacked()
|
||||
{
|
||||
ScriptInterface scriptOuter{"Test", "Test", g_ScriptContext};
|
||||
ScriptInterface scriptOuter{"Test", "Test", g_ScriptContext, AllowAllPredicate};
|
||||
const ScriptRequest rqOuter{scriptOuter};
|
||||
{
|
||||
ScriptInterface scriptInner{"Test", "Test", g_ScriptContext};
|
||||
ScriptInterface scriptInner{"Test", "Test", g_ScriptContext, AllowAllPredicate};
|
||||
const ScriptRequest rqInner{scriptInner};
|
||||
std::ignore = scriptInner.GetModuleLoader().LoadModule(rqInner, "empty.js");
|
||||
}
|
||||
@@ -128,7 +138,7 @@ public:
|
||||
|
||||
void test_ImportInFunction()
|
||||
{
|
||||
ScriptInterface script{"Test", "Test", g_ScriptContext};
|
||||
ScriptInterface script{"Test", "Test", g_ScriptContext, AllowAllPredicate};
|
||||
const ScriptRequest rq{script};
|
||||
|
||||
TestLogger logger;
|
||||
@@ -141,7 +151,7 @@ public:
|
||||
|
||||
void test_NonExistent()
|
||||
{
|
||||
ScriptInterface script{"Test", "Test", g_ScriptContext};
|
||||
ScriptInterface script{"Test", "Test", g_ScriptContext, AllowAllPredicate};
|
||||
const ScriptRequest rq{script};
|
||||
|
||||
const TestLogger _;
|
||||
@@ -151,7 +161,7 @@ public:
|
||||
|
||||
void test_EvaluateOnce()
|
||||
{
|
||||
ScriptInterface script{"Test", "Test", g_ScriptContext};
|
||||
ScriptInterface script{"Test", "Test", g_ScriptContext, AllowAllPredicate};
|
||||
const ScriptRequest rq{script};
|
||||
|
||||
{
|
||||
@@ -168,7 +178,7 @@ public:
|
||||
|
||||
void test_TopLevelAwaitFinite()
|
||||
{
|
||||
ScriptInterface script{"Test", "Test", g_ScriptContext};
|
||||
ScriptInterface script{"Test", "Test", g_ScriptContext, AllowAllPredicate};
|
||||
const ScriptRequest rq{script};
|
||||
auto result = script.GetModuleLoader().LoadModule(rq, "top_level_await_finite.js");
|
||||
|
||||
@@ -181,7 +191,7 @@ public:
|
||||
|
||||
void test_TopLevelAwaitInfinite()
|
||||
{
|
||||
ScriptInterface script{"Test", "Test", g_ScriptContext};
|
||||
ScriptInterface script{"Test", "Test", g_ScriptContext, AllowAllPredicate};
|
||||
const ScriptRequest rq{script};
|
||||
|
||||
auto result = script.GetModuleLoader().LoadModule(rq, "top_level_await_infinite.js");
|
||||
@@ -194,7 +204,7 @@ public:
|
||||
|
||||
void test_MoveFulfilledFuture()
|
||||
{
|
||||
ScriptInterface script{"Test", "Test", g_ScriptContext};
|
||||
ScriptInterface script{"Test", "Test", g_ScriptContext, AllowAllPredicate};
|
||||
const ScriptRequest rq{script};
|
||||
|
||||
auto result{script.GetModuleLoader().LoadModule(rq, "empty.js")};
|
||||
@@ -214,7 +224,7 @@ public:
|
||||
|
||||
void test_MoveEvaluatingFuture()
|
||||
{
|
||||
ScriptInterface script{"Test", "Test", g_ScriptContext};
|
||||
ScriptInterface script{"Test", "Test", g_ScriptContext, AllowAllPredicate};
|
||||
const ScriptRequest rq{script};
|
||||
|
||||
auto result{script.GetModuleLoader().LoadModule(rq, "top_level_await_finite.js")};
|
||||
@@ -235,7 +245,7 @@ public:
|
||||
|
||||
void test_EvaluateReplacedFuture()
|
||||
{
|
||||
ScriptInterface script{"Test", "Test", g_ScriptContext};
|
||||
ScriptInterface script{"Test", "Test", g_ScriptContext, AllowAllPredicate};
|
||||
const ScriptRequest rq{script};
|
||||
|
||||
TestLogger logger;
|
||||
@@ -255,7 +265,7 @@ public:
|
||||
|
||||
void test_TopLevelThrow()
|
||||
{
|
||||
ScriptInterface script{"Test", "Test", g_ScriptContext};
|
||||
ScriptInterface script{"Test", "Test", g_ScriptContext, AllowAllPredicate};
|
||||
const ScriptRequest rq{script};
|
||||
|
||||
// To silence the error.
|
||||
@@ -271,7 +281,7 @@ public:
|
||||
|
||||
void test_Export()
|
||||
{
|
||||
ScriptInterface script{"Test", "Test", g_ScriptContext};
|
||||
ScriptInterface script{"Test", "Test", g_ScriptContext, AllowAllPredicate};
|
||||
const ScriptRequest rq{script};
|
||||
|
||||
auto result = script.GetModuleLoader().LoadModule(rq, "export.js");
|
||||
@@ -298,7 +308,7 @@ public:
|
||||
|
||||
void test_ExportSame()
|
||||
{
|
||||
ScriptInterface script{"Test", "Test", g_ScriptContext};
|
||||
ScriptInterface script{"Test", "Test", g_ScriptContext, AllowAllPredicate};
|
||||
const ScriptRequest rq{script};
|
||||
|
||||
{
|
||||
@@ -322,7 +332,7 @@ public:
|
||||
|
||||
void test_ExportIndirect()
|
||||
{
|
||||
ScriptInterface script{"Test", "Test", g_ScriptContext};
|
||||
ScriptInterface script{"Test", "Test", g_ScriptContext, AllowAllPredicate};
|
||||
const ScriptRequest rq{script};
|
||||
|
||||
{
|
||||
@@ -346,7 +356,7 @@ public:
|
||||
|
||||
void test_ExportDefaultImmutable()
|
||||
{
|
||||
ScriptInterface script{"Test", "Test", g_ScriptContext};
|
||||
ScriptInterface script{"Test", "Test", g_ScriptContext, AllowAllPredicate};
|
||||
const ScriptRequest rq{script};
|
||||
|
||||
auto result = script.GetModuleLoader().LoadModule(rq, "export_default/immutable.js");
|
||||
@@ -363,7 +373,7 @@ public:
|
||||
|
||||
void test_ExportDefaultInvalid()
|
||||
{
|
||||
ScriptInterface script{"Test", "Test", g_ScriptContext};
|
||||
ScriptInterface script{"Test", "Test", g_ScriptContext, AllowAllPredicate};
|
||||
const ScriptRequest rq{script};
|
||||
|
||||
TestLogger logger;
|
||||
@@ -375,7 +385,7 @@ public:
|
||||
|
||||
void test_ExportDefaultDoesNotWorkAround()
|
||||
{
|
||||
ScriptInterface script{"Test", "Test", g_ScriptContext};
|
||||
ScriptInterface script{"Test", "Test", g_ScriptContext, AllowAllPredicate};
|
||||
const ScriptRequest rq{script};
|
||||
|
||||
auto result = script.GetModuleLoader().LoadModule(rq, "export_default/does_not_work_around.js");
|
||||
@@ -394,7 +404,7 @@ public:
|
||||
|
||||
void test_ExportDefaultWorksAround()
|
||||
{
|
||||
ScriptInterface script{"Test", "Test", g_ScriptContext};
|
||||
ScriptInterface script{"Test", "Test", g_ScriptContext, AllowAllPredicate};
|
||||
const ScriptRequest rq{script};
|
||||
|
||||
auto result = script.GetModuleLoader().LoadModule(rq, "export_default/works_around.js");
|
||||
@@ -411,7 +421,7 @@ public:
|
||||
|
||||
void test_ReplaceEvaluatingFuture()
|
||||
{
|
||||
ScriptInterface script{"Test", "Test", g_ScriptContext};
|
||||
ScriptInterface script{"Test", "Test", g_ScriptContext, AllowAllPredicate};
|
||||
const ScriptRequest rq{script};
|
||||
|
||||
auto awaitResult = script.GetModuleLoader().LoadModule(rq, "top_level_await_finite.js");
|
||||
@@ -430,7 +440,7 @@ public:
|
||||
|
||||
void test_DynamicImport()
|
||||
{
|
||||
ScriptInterface script{"Test", "Test", g_ScriptContext};
|
||||
ScriptInterface script{"Test", "Test", g_ScriptContext, AllowAllPredicate};
|
||||
const ScriptRequest rq{script};
|
||||
|
||||
auto result = script.GetModuleLoader().LoadModule(rq, "dynamic_import.js");
|
||||
@@ -461,7 +471,7 @@ public:
|
||||
|
||||
void test_Meta()
|
||||
{
|
||||
ScriptInterface script{"Test", "Test", g_ScriptContext};
|
||||
ScriptInterface script{"Test", "Test", g_ScriptContext, AllowAllPredicate};
|
||||
const ScriptRequest rq{script};
|
||||
|
||||
auto result = script.GetModuleLoader().LoadModule(rq, "meta.js");
|
||||
@@ -481,7 +491,7 @@ public:
|
||||
|
||||
void test_Modified()
|
||||
{
|
||||
ScriptInterface script{"Test", "Test", g_ScriptContext};
|
||||
ScriptInterface script{"Test", "Test", g_ScriptContext, AllowAllPredicate};
|
||||
const ScriptRequest rq{script};
|
||||
|
||||
auto result = script.GetModuleLoader().LoadModule(rq, "modified/base.js");
|
||||
@@ -500,7 +510,7 @@ public:
|
||||
{
|
||||
constexpr int goal{2};
|
||||
|
||||
ScriptInterface script{"Test", "Test", g_ScriptContext};
|
||||
ScriptInterface script{"Test", "Test", g_ScriptContext, AllowAllPredicate};
|
||||
const ScriptRequest rq{script};
|
||||
|
||||
int counter{0};
|
||||
@@ -525,7 +535,7 @@ public:
|
||||
|
||||
void test_HotloadWithoutIncrement()
|
||||
{
|
||||
ScriptInterface script{"Test", "Test", g_ScriptContext};
|
||||
ScriptInterface script{"Test", "Test", g_ScriptContext, AllowAllPredicate};
|
||||
const ScriptRequest rq{script};
|
||||
|
||||
auto result = script.GetModuleLoader().LoadModule(rq, "top_level_await_finite.js");
|
||||
@@ -537,7 +547,7 @@ public:
|
||||
|
||||
void test_HotloadIndipendence()
|
||||
{
|
||||
ScriptInterface script{"Test", "Test", g_ScriptContext};
|
||||
ScriptInterface script{"Test", "Test", g_ScriptContext, AllowAllPredicate};
|
||||
const ScriptRequest rq{script};
|
||||
|
||||
// It's intended to be used as in the test above but it's easier to test when it's unrolled.
|
||||
@@ -576,7 +586,7 @@ public:
|
||||
|
||||
void test_HotloadModified()
|
||||
{
|
||||
ScriptInterface script{"Test", "Test", g_ScriptContext};
|
||||
ScriptInterface script{"Test", "Test", g_ScriptContext, AllowAllPredicate};
|
||||
const ScriptRequest rq{script};
|
||||
|
||||
auto result = script.GetModuleLoader().LoadModule(rq, "empty.js");
|
||||
@@ -595,7 +605,7 @@ public:
|
||||
|
||||
void test_HotloadIndirect()
|
||||
{
|
||||
ScriptInterface script{"Test", "Test", g_ScriptContext};
|
||||
ScriptInterface script{"Test", "Test", g_ScriptContext, AllowAllPredicate};
|
||||
const ScriptRequest rq{script};
|
||||
|
||||
auto result = script.GetModuleLoader().LoadModule(rq, "indirect.js");
|
||||
@@ -612,7 +622,7 @@ public:
|
||||
|
||||
void test_HotloadUnobserved()
|
||||
{
|
||||
ScriptInterface script{"Test", "Test", g_ScriptContext};
|
||||
ScriptInterface script{"Test", "Test", g_ScriptContext, AllowAllPredicate};
|
||||
{
|
||||
const ScriptRequest rq{script};
|
||||
|
||||
@@ -641,7 +651,7 @@ public:
|
||||
|
||||
void test_HotloadAfterResultDestruction()
|
||||
{
|
||||
ScriptInterface script{"Test", "Test", g_ScriptContext};
|
||||
ScriptInterface script{"Test", "Test", g_ScriptContext, AllowAllPredicate};
|
||||
{
|
||||
const ScriptRequest rq{script};
|
||||
|
||||
@@ -663,7 +673,65 @@ public:
|
||||
|
||||
void test_ResultDestructionAfterScriptRequestDestruction()
|
||||
{
|
||||
ScriptInterface script{"Test", "Test", g_ScriptContext};
|
||||
ScriptInterface script{"Test", "Test", g_ScriptContext, AllowAllPredicate};
|
||||
auto _ = script.GetModuleLoader().LoadModule(ScriptRequest{script}, "empty.js");
|
||||
}
|
||||
|
||||
void test_RestrictionNoPredicate()
|
||||
{
|
||||
ScriptInterface script{"Test", "Test", g_ScriptContext};
|
||||
const ScriptRequest rq{script};
|
||||
|
||||
TS_ASSERT_THROWS_EQUALS(std::ignore = script.GetModuleLoader().LoadModule(rq,
|
||||
"empty.js"), const std::runtime_error& e, e.what(),
|
||||
"Importing file \"empty.js\" is disallowed.");
|
||||
}
|
||||
|
||||
void test_RestrictionDirect()
|
||||
{
|
||||
ScriptInterface script{"Test", "Test", g_ScriptContext, DisallowedfilePredicate};
|
||||
const ScriptRequest rq{script};
|
||||
|
||||
TS_ASSERT_THROWS_EQUALS(std::ignore = script.GetModuleLoader().LoadModule(rq,
|
||||
"restriction/disallowedfile.js"), const std::runtime_error& e, e.what(),
|
||||
"Importing file \"restriction/disallowedfile.js\" is disallowed.");
|
||||
}
|
||||
|
||||
void test_RestrictionIndirect()
|
||||
{
|
||||
ScriptInterface script{"Test", "Test", g_ScriptContext, DisallowedfilePredicate};
|
||||
const ScriptRequest rq{script};
|
||||
TestLogger logger;
|
||||
TS_ASSERT_THROWS_EQUALS(std::ignore = script.GetModuleLoader().LoadModule(rq,
|
||||
"restriction/import.js"), const std::invalid_argument& e, e.what(),
|
||||
"Unable to link module.");
|
||||
TS_ASSERT_STR_CONTAINS(logger.GetOutput(),
|
||||
"Importing file \"restriction/disallowedfile.js\" is disallowed.");
|
||||
}
|
||||
|
||||
void test_RestrictionFancy()
|
||||
{
|
||||
ScriptInterface script{"Test", "Test", g_ScriptContext, DisallowedfilePredicate};
|
||||
const ScriptRequest rq{script};
|
||||
TestLogger logger;
|
||||
TS_ASSERT_THROWS_EQUALS(std::ignore = script.GetModuleLoader().LoadModule(rq,
|
||||
"restriction/fancy_import.js"), const std::invalid_argument& e, e.what(),
|
||||
"Unable to link module.");
|
||||
TS_ASSERT_STR_CONTAINS(logger.GetOutput(),
|
||||
"Importing file \"restriction/disallowedfile.js\" is disallowed.");
|
||||
}
|
||||
|
||||
void test_RestrictionDynamic()
|
||||
{
|
||||
ScriptInterface script{"Test", "Test", g_ScriptContext, DisallowedfilePredicate};
|
||||
const ScriptRequest rq{script};
|
||||
|
||||
TestLogger logger;
|
||||
auto result = script.GetModuleLoader().LoadModule(rq, "restriction/dynamic_import.js");
|
||||
TS_ASSERT_STR_CONTAINS(logger.GetOutput(),
|
||||
"Importing file \"restriction/disallowedfile.js\" is disallowed.");
|
||||
|
||||
g_ScriptContext->RunJobs();
|
||||
TS_ASSERT_THROWS_ANYTHING(std::ignore = result.begin()->Get());
|
||||
}
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user