mirror of
https://gitea.wildfiregames.com/0ad/0ad.git
synced 2026-09-21 20:06:40 +00:00
Support the import.meta property
Through the `import.meta` property the engine can pass some values to the module. Currently only the `path` of the script file is exposed.
This commit is contained in:
@@ -160,6 +160,10 @@ ModuleLoader::CompiledModule::CompiledModule(const ScriptRequest& rq, const VfsP
|
||||
throw std::invalid_argument{fmt::format("Unable to compile module: \"{}\".",
|
||||
filePathStr)};
|
||||
}
|
||||
|
||||
JS::RootedValue modInfo{rq.cx};
|
||||
Script::CreateObject(rq, &modInfo, "path", filePathStr);
|
||||
JS::SetModulePrivate(m_ModuleObject, modInfo);
|
||||
}
|
||||
|
||||
ModuleLoader::Future::Future(const ScriptRequest& rq, ModuleLoader& loader, const VfsPath& modulePath):
|
||||
@@ -236,6 +240,26 @@ void ModuleLoader::Future::SetReservedSlot(JS::Value privateValue) noexcept
|
||||
return Future{rq, *this, modulePath};
|
||||
}
|
||||
|
||||
/**
|
||||
* This is only executed once per module. Following accesses of `import.meta`
|
||||
* evaluate to the same object.
|
||||
*/
|
||||
[[nodiscard]] bool ModuleLoader::MetadataHook(JSContext* cx, JS::HandleValue privateValue,
|
||||
JS::HandleObject metaObject) noexcept
|
||||
{
|
||||
const ScriptRequest rq{cx};
|
||||
|
||||
JS::RootedValue path{cx};
|
||||
if (!Script::GetProperty(rq, privateValue, "path", &path))
|
||||
return false;
|
||||
|
||||
JS::RootedValue metaValue{cx, JS::ObjectValue(*metaObject)};
|
||||
if (!Script::SetProperty(rq, metaValue, "path", path))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
[[nodiscard]] JSObject* ModuleLoader::ResolveHook(JSContext* cx, JS::HandleValue,
|
||||
JS::HandleObject moduleRequest) noexcept
|
||||
{
|
||||
|
||||
@@ -100,6 +100,8 @@ public:
|
||||
|
||||
private:
|
||||
// Functions used by the `ScriptContext`.
|
||||
[[nodiscard]] static bool MetadataHook(JSContext* cx, JS::HandleValue privateValue,
|
||||
JS::HandleObject metaObject) noexcept;
|
||||
[[nodiscard]] static JSObject* ResolveHook(JSContext* cx, JS::HandleValue,
|
||||
JS::HandleObject moduleRequest) noexcept;
|
||||
[[nodiscard]] static bool DynamicImportHook(JSContext* cx, JS::HandleValue referencingPrivate,
|
||||
|
||||
@@ -155,6 +155,7 @@ ScriptContext::ScriptContext(int contextSize, uint32_t heapGrowthBytesGCTrigger)
|
||||
JS::SetPromiseRejectionTrackerCallback(m_cx, &Script::UnhandledRejectedPromise);
|
||||
|
||||
JSRuntime* runtime{JS_GetRuntime(m_cx)};
|
||||
JS::SetModuleMetadataHook(runtime, &Script::ModuleLoader::MetadataHook);
|
||||
JS::SetModuleResolveHook(runtime, &Script::ModuleLoader::ResolveHook);
|
||||
JS::SetModuleDynamicImportHook(runtime, &Script::ModuleLoader::DynamicImportHook);
|
||||
}
|
||||
@@ -166,6 +167,7 @@ ScriptContext::~ScriptContext()
|
||||
JSRuntime* runtime{JS_GetRuntime(m_cx)};
|
||||
JS::SetModuleDynamicImportHook(runtime, nullptr);
|
||||
JS::SetModuleResolveHook(runtime, nullptr);
|
||||
JS::SetModuleMetadataHook(runtime, nullptr);
|
||||
|
||||
// Switch back to normal performance mode to avoid assertion in debug mode.
|
||||
js::gc::SetPerformanceHint(m_cx, js::gc::PerformanceHint::Normal);
|
||||
|
||||
@@ -401,4 +401,24 @@ public:
|
||||
TS_ASSERT_LESS_THAN(pi, 3.1416);
|
||||
TS_ASSERT_LESS_THAN(3.1415, pi);
|
||||
}
|
||||
|
||||
void test_Meta()
|
||||
{
|
||||
ScriptInterface script{"Test", "Test", g_ScriptContext};
|
||||
const ScriptRequest rq{script};
|
||||
|
||||
auto future = script.GetModuleLoader().LoadModule(rq, "meta.js");
|
||||
|
||||
g_ScriptContext->RunJobs();
|
||||
|
||||
JS::RootedObject ns{rq.cx, future.Get()};
|
||||
const JS::RootedValue modNamespace{rq.cx, JS::ObjectValue(*ns)};
|
||||
|
||||
JS::RootedValue meta{rq.cx};
|
||||
TS_ASSERT(ScriptFunction::Call(rq, modNamespace, "getMeta", &meta));
|
||||
|
||||
std::string path;
|
||||
TS_ASSERT(Script::GetProperty(rq, meta, "path", path));
|
||||
TS_ASSERT_STR_EQUALS(path, "meta.js");
|
||||
}
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user