Adapt 0 A.D. to SpiderMonkey ESR 102

This follows the migration guide at:
https://github.com/mozilla-spidermonkey/spidermonkey-embedding-examples

Based on patch by: wraitii
Differential Revision: https://code.wildfiregames.com/D5002
This commit is contained in:
Itms 2024-10-25 10:24:14 +02:00
parent 6a5488832e
commit cc72142205
No known key found for this signature in database
GPG key ID: C7E52BD14CE14E09
13 changed files with 49 additions and 42 deletions

View file

@ -639,7 +639,7 @@ extern_lib_defs = {
compile_settings = function()
if _OPTIONS["with-system-mozjs"] then
if not _OPTIONS["android"] then
pkgconfig.add_includes_after("mozjs-91")
pkgconfig.add_includes_after("mozjs-102")
end
else
filter "Debug"
@ -661,17 +661,17 @@ extern_lib_defs = {
link_settings = function()
if _OPTIONS["with-system-mozjs"] then
if _OPTIONS["android"] then
links { "mozjs-91" }
links { "mozjs-102" }
else
pkgconfig.add_links("mozjs-91")
pkgconfig.add_links("mozjs-102")
end
else
filter { "Debug" }
links { "mozjs91-debug" }
links { "mozjs102-debug" }
filter { "Release" }
links { "mozjs91-release" }
links { "mozjs102-release" }
filter { }
links { "mozjs91-rust" }
links { "mozjs102-rust" }
add_source_lib_paths("spidermonkey")
end
end,

View file

@ -8,7 +8,7 @@ newoption { trigger = "minimal-flags", description = "Only set compiler/linker f
newoption { trigger = "outpath", description = "Location for generated project files", default="../workspaces/default" }
newoption { trigger = "with-system-cxxtest", description = "Search standard paths for cxxtest, instead of using bundled copy" }
newoption { trigger = "with-lto", description = "Enable Link Time Optimization (LTO)" }
newoption { trigger = "with-system-mozjs", description = "Search standard paths for libmozjs91, instead of using bundled copy" }
newoption { trigger = "with-system-mozjs", description = "Search standard paths for libmozjs102, instead of using bundled copy" }
newoption { trigger = "with-system-nvtt", description = "Search standard paths for nvidia-texture-tools library, instead of using bundled copy" }
newoption { trigger = "with-valgrind", description = "Enable Valgrind support (non-Windows only)" }
newoption { trigger = "without-audio", description = "Disable use of OpenAL/Ogg/Vorbis APIs" }
@ -121,7 +121,7 @@ end
-- The pc file doesn't specify the required -DDEBUG needed in that case
local mozjs_is_debug_build = false
if _OPTIONS["with-system-mozjs"] then
local _, errorCode = os.outputof(cc .. " $(pkg-config mozjs-91 --cflags) ./tests/mozdebug.c -o /dev/null")
local _, errorCode = os.outputof(cc .. " $(pkg-config mozjs-102 --cflags) ./tests/mozdebug.c -o /dev/null")
if errorCode ~= 0 then
mozjs_is_debug_build = true
end

View file

@ -1,4 +1,4 @@
/* Copyright (C) 2021 Wildfire Games.
/* Copyright (C) 2024 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@ -30,7 +30,7 @@ JSClass JSI_GUISize::JSI_class = {
JSClassOps JSI_GUISize::JSI_classops = {
nullptr, nullptr,
nullptr, nullptr,
nullptr, nullptr, nullptr, nullptr,
nullptr, nullptr, nullptr,
nullptr, JSI_GUISize::construct, nullptr
};

View file

@ -1,4 +1,4 @@
/* Copyright (C) 2022 Wildfire Games.
/* Copyright (C) 2024 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@ -293,7 +293,6 @@ bool JSNodeData::Output(WriteBuffer& writeBuffer, JS::HandleValue value) const
switch (JS_TypeOfValue(rq.cx, value))
{
case JSTYPE_UNDEFINED:
case JSTYPE_NULL:
{
writeBuffer.Append("\0\0\0\0", 4);
break;

View file

@ -98,7 +98,7 @@ struct BuildDirEntListState
filename_array(rq.cx),
cur_idx(0)
{
filename_array = JS::NewArrayObject(rq.cx, JS::HandleValueArray::empty());
filename_array = JS::NewArrayObject(rq.cx, 0);
}
};

View file

@ -1,4 +1,4 @@
/* Copyright (C) 2021 Wildfire Games.
/* Copyright (C) 2024 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@ -41,7 +41,7 @@ inline bool GetProperty(const ScriptRequest& rq, JS::HandleValue obj, PropType n
JS::RootedObject object(rq.cx, &obj.toObject());
if constexpr (std::is_same_v<int, PropType>)
{
JS::RootedId id(rq.cx, INT_TO_JSID(name));
JS::RootedId id(rq.cx, JS::PropertyKey::Int(name));
return JS_GetPropertyById(rq.cx, object, id, out);
}
else if constexpr (std::is_same_v<const char*, PropType>)
@ -108,7 +108,7 @@ inline bool SetProperty(const ScriptRequest& rq, JS::HandleValue obj, PropType n
JS::RootedObject object(rq.cx, &obj.toObject());
if constexpr (std::is_same_v<int, PropType>)
{
JS::RootedId id(rq.cx, INT_TO_JSID(name));
JS::RootedId id(rq.cx, JS::PropertyKey::Int(name));
return JS_DefinePropertyById(rq.cx, object, id, value, attrs);
}
else if constexpr (std::is_same_v<const char*, PropType>)

View file

@ -171,7 +171,7 @@ void ScriptContext::MaybeIncrementalGC(double delay)
// The sweeping actually frees memory and it does this in a background thread (if JS_USE_HELPER_THREADS is set).
// While the sweeping is happening we already run scripts again and produce new garbage.
const int GCSliceTimeBudget = 30; // Milliseconds an incremental slice is allowed to run
const js::SliceBudget GCSliceTimeBudget = js::SliceBudget(js::TimeBudget(30)); // Milliseconds an incremental slice is allowed to run
// Have a minimum time in seconds to wait between GC slices and before starting a new GC to distribute the GC
// load and to hopefully make it unnoticeable for the player. This value should be high enough to distribute

View file

@ -107,7 +107,7 @@ JSClassOps global_classops = {
nullptr, nullptr,
nullptr, nullptr,
nullptr, nullptr, nullptr,
nullptr, nullptr, nullptr,
nullptr, nullptr,
JS_GlobalObjectTraceHook
};

View file

@ -1,4 +1,4 @@
/* Copyright (C) 2023 Wildfire Games.
/* Copyright (C) 2024 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@ -229,12 +229,21 @@ public:
static bool Math_random(JSContext* cx, uint argc, JS::Value* vp);
/**
* Retrieve the private data field of a JSObject that is an instance of the given JSClass.
* Name the reserved slots we may need to use in custom JSObjects.
* When using JSCLASS_HAS_RESERVED_SLOTS in the definition of your JSClass, use the number
* of the highest slot you need plus 1.
*/
enum JSObjectReservedSlots {
PRIVATE = 0
};
/**
* Retrieve the private data field of a JSObject.
*/
template <typename T>
static T* GetPrivate(const ScriptRequest& rq, JS::HandleObject thisobj, JSClass* jsClass)
static T* GetPrivate(const ScriptRequest& rq, JS::HandleObject thisobj)
{
T* value = static_cast<T*>(JS_GetInstancePrivate(rq.cx, thisobj, jsClass, nullptr));
T* value = JS::GetMaybePtrFromReservedSlot<T>(thisobj, JSObjectReservedSlots::PRIVATE);
if (value == nullptr)
ScriptException::Raise(rq, "Private data of the given object is null!");
@ -243,20 +252,20 @@ public:
}
/**
* Retrieve the private data field of a JS Object that is an instance of the given JSClass.
* Retrieve the private data field of a JS Object.
* If an error occurs, GetPrivate will report it with the according stack.
*/
template <typename T>
static T* GetPrivate(const ScriptRequest& rq, JS::CallArgs& callArgs, JSClass* jsClass)
static T* GetPrivate(const ScriptRequest& rq, JS::CallArgs& callArgs)
{
if (!callArgs.thisv().isObject())
{
ScriptException::Raise(rq, "Cannot retrieve private JS class data because from a non-object value!");
ScriptException::Raise(rq, "Cannot retrieve private JS object data because from a non-object value!");
return nullptr;
}
JS::RootedObject thisObj(rq.cx, &callArgs.thisv().toObject());
T* value = static_cast<T*>(JS_GetInstancePrivate(rq.cx, thisObj, jsClass, &callArgs));
T* value = JS::GetMaybePtrFromReservedSlot<T>(thisObj, JSObjectReservedSlots::PRIVATE);
if (value == nullptr)
ScriptException::Raise(rq, "Private data of the given object is null!");

View file

@ -1,4 +1,4 @@
/* Copyright (C) 2023 Wildfire Games.
/* Copyright (C) 2024 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@ -21,6 +21,10 @@
#define JSGC_GENERATIONAL 1
#define JSGC_USE_EXACT_ROOTING 1
#ifdef DEBUG
#define MOZ_DIAGNOSTIC_ASSERT_ENABLED
#endif
#ifdef _WIN32
# define XP_WIN
# ifndef WIN32
@ -73,7 +77,7 @@
# pragma GCC diagnostic pop
#endif
#if MOZJS_MAJOR_VERSION != 91
#if MOZJS_MAJOR_VERSION != 102
#error Your compiler is trying to use an incorrect major version of the \
SpiderMonkey library. The only version that works is the one in the \
libraries/spidermonkey/ directory, and it will not work with a typical \
@ -81,7 +85,7 @@ system-installed version. Make sure you have got all the right files and \
include paths.
#endif
#if MOZJS_MINOR_VERSION != 13
#if MOZJS_MINOR_VERSION != 15
#error Your compiler is trying to use an untested minor version of the \
SpiderMonkey library. If you are a package maintainer, please make sure \
to check very carefully that this version does not change the behaviour \

View file

@ -1,4 +1,4 @@
/* Copyright (C) 2023 Wildfire Games.
/* Copyright (C) 2024 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@ -62,7 +62,7 @@ template<> void Script::ToJSVal<IComponent*>(const ScriptRequest& rq, JS::Mutab
return;
}
JS::SetPrivate(obj, static_cast<void*>(val));
JS::SetReservedSlot(obj, ScriptInterface::JSObjectReservedSlots::PRIVATE, JS::PrivateValue(val));
ret.setObject(*obj);
}

View file

@ -1,4 +1,4 @@
/* Copyright (C) 2023 Wildfire Games.
/* Copyright (C) 2024 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@ -81,11 +81,6 @@ void CBinarySerializerScriptImpl::HandleScriptVal(JS::HandleValue val)
m_Serializer.NumberU8_Unbounded("type", SCRIPT_TYPE_VOID);
break;
}
case JSTYPE_NULL: // This type is never actually returned (it's a JS2 feature)
{
m_Serializer.NumberU8_Unbounded("type", SCRIPT_TYPE_NULL);
break;
}
case JSTYPE_OBJECT:
{
if (val.isNull())

View file

@ -1,4 +1,4 @@
/* Copyright (C) 2021 Wildfire Games.
/* Copyright (C) 2024 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@ -24,7 +24,7 @@
#define BEGIN_INTERFACE_WRAPPER(iname) \
JSClass class_ICmp##iname = { \
"ICmp" #iname, JSCLASS_HAS_PRIVATE \
"ICmp" #iname, JSCLASS_HAS_RESERVED_SLOTS( ScriptInterface::JSObjectReservedSlots::PRIVATE+1 ) \
}; \
static JSFunctionSpec methods_ICmp##iname[] = {
@ -43,13 +43,13 @@
ICmp##iname::InterfaceInit(scriptInterface); \
}
template <typename T, JSClass* jsClass>
template <typename T>
inline T* ComponentGetter(const ScriptRequest& rq, JS::CallArgs& args)
{
return ScriptInterface::GetPrivate<T>(rq, args, jsClass);
return ScriptInterface::GetPrivate<T>(rq, args);
}
#define DEFINE_INTERFACE_METHOD(scriptname, classname, methodname) \
ScriptFunction::Wrap<&classname::methodname, ComponentGetter<classname, &class_##classname>>(scriptname),
ScriptFunction::Wrap<&classname::methodname, ComponentGetter<classname>>(scriptname),
#endif // INCLUDED_INTERFACE_SCRIPTED