1
0
forked from 0ad/0ad

Upgrade SpiderMonkey to version 45.0.2, refs #4893.

- Various build changes, in particular NSPR is not needed on Unix
anymore
- Add js/Initialization.h to source/scriptinterface/ScriptEngine.h
- Use nullptr instead of JS::NullPtr(), see
https://bugzilla.mozilla.org/show_bug.cgi?id=1164602
- Remove `JS::RuntimeOptionsRef.varObjFix`, see
https://bugzilla.mozilla.org/show_bug.cgi?id=1171177
- Remove uses of `AutoIdArray`, see
https://bugzilla.mozilla.org/show_bug.cgi?id=1191529
- `JS_InternUCStringN` has been renamed, see
https://bugzilla.mozilla.org/show_bug.cgi?id=1178581
- `JS::Evaluate` now takes scope chains explicitly, see
https://bugzilla.mozilla.org/show_bug.cgi?id=1097987
- Array functions (such as `JS_IsArrayObject`) are fallible and output
to params, see https://bugzilla.mozilla.org/show_bug.cgi?id=f3d35d8
- Remove `JSCLASS_CACHED_PROTO_WIDTH` workaround in our code, see
https://bugzilla.mozilla.org/show_bug.cgi?id=1236373
- Remove compile'n go (`setCompileAndGo`) and replace it by
`setIsRunOnce` which will become the default in the future, see
https://bugzilla.mozilla.org/show_bug.cgi?id=679939
- Mark shared memory in direct access operations
(`JS_GetUint16ArrayData` and `JS_GetUint8ArrayData`), see
https://bugzilla.mozilla.org/show_bug.cgi?id=1176214
- Use new `JS::ObjectOpResult`, see
https://bugzilla.mozilla.org/show_bug.cgi?id=1113369

Thanks to wraitii, elexis, Krinkle and historic_bruno for contributions
and comments, and to gentz, madpilot, s0600204 and Stan for testing and
indirect contributions.

Differential Revision: https://code.wildfiregames.com/D1510
This was SVN commit r22627.
This commit is contained in:
Nicolas Auvray 2019-08-07 22:37:43 +00:00
parent 7876ca7acb
commit 64b477625d
18 changed files with 99 additions and 135 deletions

View File

@ -533,9 +533,9 @@ extern_lib_defs = {
},
spidermonkey = {
compile_settings = function()
if _OPTIONS["with-system-mozjs38"] then
if _OPTIONS["with-system-mozjs45"] then
if not _OPTIONS["android"] then
pkgconfig.add_includes("mozjs-38")
pkgconfig.add_includes("mozjs-45")
end
else
if os.istarget("windows") then
@ -553,31 +553,25 @@ extern_lib_defs = {
end
end,
link_settings = function()
if _OPTIONS["with-system-mozjs38"] then
if _OPTIONS["with-system-mozjs45"] then
if _OPTIONS["android"] then
links { "mozjs-38" }
links { "mozjs-45" }
else
pkgconfig.add_links("nspr")
pkgconfig.add_links("mozjs-38")
pkgconfig.add_links("mozjs-45")
end
else
if os.istarget("macosx") then
add_default_lib_paths("nspr")
links { "nspr4", "plc4", "plds4" }
end
filter { "Debug", "action:vs2013" }
links { "mozjs38-ps-debug-vc120" }
links { "mozjs45-ps-debug-vc120" }
filter { "Release", "action:vs2013" }
links { "mozjs38-ps-release-vc120" }
links { "mozjs45-ps-release-vc120" }
filter { "Debug", "action:vs2015" }
links { "mozjs38-ps-debug-vc140" }
links { "mozjs45-ps-debug-vc140" }
filter { "Release", "action:vs2015" }
links { "mozjs38-ps-release-vc140" }
links { "mozjs45-ps-release-vc140" }
filter { "Debug", "action:not vs*" }
links { "mozjs38-ps-debug" }
links { "mozjs45-ps-debug" }
filter { "Release", "action:not vs*" }
links { "mozjs38-ps-release" }
links { "mozjs45-ps-release" }
filter { }
add_source_lib_paths("spidermonkey")
end

View File

@ -33,11 +33,12 @@ if [ "$preserve_libs" != "true" ]; then
(cd ../../libraries/source/fcollada/src && rm -rf ./output)
(cd ../../libraries/source/nvtt/src && rm -rf ./build)
(cd ../../libraries/source/spidermonkey && rm -f .already-built)
(cd ../../libraries/source/spidermonkey && rm -rf ./mozjs-38.0.0)
(cd ../../libraries/source/spidermonkey && rm -rf ./mozjs-45.0.2)
fi
# Still delete the directory of previous SpiderMonkey versions to
# avoid wasting disk space if people clean workspaces after updating.
(cd ../../libraries/source/spidermonkey && rm -rf ./mozjs-38.0.0)
(cd ../../libraries/source/spidermonkey && rm -rf ./mozjs31)
(cd ../../libraries/source/spidermonkey && rm -rf ./mozjs24)

View File

@ -39,8 +39,6 @@ NETTLE_VERSION="nettle-3.5.1"
# NOTE: remember to also update LIB_URL below when changing version
GNUTLS_VERSION="gnutls-3.6.8"
GLOOX_VERSION="gloox-1.0.22"
# NSPR is necessary for threadsafe Spidermonkey
NSPR_VERSION="4.15"
# OS X only includes part of ICU, and only the dylib
# NOTE: remember to also update LIB_URL below when changing version
ICU_VERSION="icu4c-59_1"
@ -49,7 +47,7 @@ MINIUPNPC_VERSION="miniupnpc-2.0.20180222"
SODIUM_VERSION="libsodium-1.0.16"
# --------------------------------------------------------------
# Bundled with the game:
# * SpiderMonkey 38
# * SpiderMonkey 45
# * NVTT
# * FCollada
# --------------------------------------------------------------
@ -750,41 +748,6 @@ else
fi
popd > /dev/null
# --------------------------------------------------------------
echo -e "Building NSPR..."
LIB_VERSION="${NSPR_VERSION}"
LIB_ARCHIVE="nspr-$LIB_VERSION.tar.gz"
LIB_DIRECTORY="nspr-$LIB_VERSION"
LIB_URL="https://ftp.mozilla.org/pub/mozilla.org/nspr/releases/v$LIB_VERSION/src/"
mkdir -p nspr
pushd nspr > /dev/null
NSPR_DIR="$(pwd)"
if [[ "$force_rebuild" = "true" ]] || [[ ! -e .already-built ]] || [[ .already-built -ot $LIB_DIRECTORY ]]
then
rm -f .already-built
download_lib $LIB_URL $LIB_ARCHIVE
rm -rf $LIB_DIRECTORY bin include lib share
tar -xf $LIB_ARCHIVE
pushd $LIB_DIRECTORY/nspr
(CFLAGS="$CFLAGS" CXXFLAGS="$CXXFLAGS" LDFLAGS="$LDFLAGS" \
./configure --prefix="$NSPR_DIR" \
--enable-64bit \
&& make ${JOBS} && make install) || die "NSPR build failed"
popd
# TODO: how can we not build the dylibs?
rm -f lib/*.dylib
touch .already-built
else
already_built
fi
popd > /dev/null
# --------------------------------------------------------------
echo -e "Building ICU..."
@ -940,9 +903,9 @@ popd > /dev/null
# be customized, so we build and install them from bundled sources
# --------------------------------------------------------------------
echo -e "Building Spidermonkey..."
LIB_VERSION="mozjs-38.2.1"
LIB_ARCHIVE="$LIB_VERSION.rc0.tar.bz2"
LIB_DIRECTORY="mozjs-38.0.0"
LIB_VERSION="mozjs-45.0.2"
LIB_ARCHIVE="$LIB_VERSION.tar.bz2"
LIB_DIRECTORY="mozjs-45.0.2"
pushd ../source/spidermonkey/ > /dev/null
@ -963,20 +926,17 @@ then
popd
pushd $LIB_DIRECTORY/js/src
# We want separate debug/release versions of the library, so change their install name in the Makefile
perl -i.bak -pe 's/(^STATIC_LIBRARY_NAME\s+=).*/$1'\''mozjs38-ps-debug'\''/' moz.build
CONF_OPTS="--target=$ARCH-apple-darwin
--prefix=${INSTALL_DIR}
--with-system-nspr
--with-nspr-prefix=${NSPR_DIR}
--enable-posix-nspr-emulation
--with-system-zlib=${ZLIB_DIR}
--disable-tests
--disable-shared-js"
--disable-shared-js
--disable-jemalloc
--without-intl-api"
# Change the default location where the tracelogger should store its output, which is /tmp/ on OSX.
TLCXXFLAGS='-DTRACE_LOG_DIR="\"../../source/tools/tracelogger/\""'
# Uncomment this line for 32-bit 10.5 cross compile:
#CONF_OPTS="$CONF_OPTS --target=i386-apple-darwin9.0.0"
if [[ $MIN_OSX_VERSION && ${MIN_OSX_VERSION-_} ]]; then
CONF_OPTS="$CONF_OPTS --enable-macos-target=$MIN_OSX_VERSION"
fi
@ -984,6 +944,8 @@ then
CONF_OPTS="$CONF_OPTS --with-macosx-sdk=$SYSROOT"
fi
# We want separate debug/release versions of the library, so change their install name in the Makefile
perl -i.bak -pe 's/(^STATIC_LIBRARY_NAME\s+=).*/$1'\''mozjs45-ps-debug'\''/' moz.build
mkdir -p build-debug
pushd build-debug
(CC="clang" CXX="clang++" CXXFLAGS="${TLCXXFLAGS}" AR=ar CROSS_COMPILE=1 \
@ -996,11 +958,11 @@ then
# js-config.h is different for debug and release builds, so we need different include directories for both
mkdir -p $INCLUDE_DIR_DEBUG
cp -R -L dist/include/* $INCLUDE_DIR_DEBUG/
cp dist/lib/*.a $INSTALL_DIR/lib
cp dist/sdk/lib/*.a $INSTALL_DIR/lib
popd
mv moz.build.bak moz.build
perl -i.bak -pe 's/(^STATIC_LIBRARY_NAME\s+=).*/$1'\''mozjs38-ps-release'\''/' moz.build
perl -i.bak -pe 's/(^STATIC_LIBRARY_NAME\s+=).*/$1'\''mozjs45-ps-release'\''/' moz.build
mkdir -p build-release
pushd build-release
(CC="clang" CXX="clang++" CXXFLAGS="${TLCXXFLAGS}" AR=ar CROSS_COMPILE=1 \
@ -1010,7 +972,8 @@ then
# js-config.h is different for debug and release builds, so we need different include directories for both
mkdir -p $INCLUDE_DIR_RELEASE
cp -R -L dist/include/* $INCLUDE_DIR_RELEASE/
cp dist/lib/*.a $INSTALL_DIR/lib
cp dist/sdk/lib/*.a $INSTALL_DIR/lib
cp js/src/*.a $INSTALL_DIR/lib
popd
mv moz.build.bak moz.build

View File

@ -346,7 +346,7 @@ void IGUIObject::RegisterScriptHandler(const CStr& Action, const CStr& Code, CGU
JS::CompileOptions options(cx);
options.setFileAndLine(CodeName.c_str(), 0);
options.setCompileAndGo(true);
options.setIsRunOnce(true);
JS::RootedFunction func(cx);
JS::AutoObjectVector emptyScopeChain(cx);

View File

@ -56,7 +56,7 @@ class IGUIObject
// Allow getProperty to access things like GetParent()
friend bool JSI_IGUIObject::getProperty(JSContext* cx, JS::HandleObject obj, JS::HandleId id, JS::MutableHandleValue vp);
friend bool JSI_IGUIObject::setProperty(JSContext* cx, JS::HandleObject obj, JS::HandleId id, bool UNUSED(strict), JS::MutableHandleValue vp);
friend bool JSI_IGUIObject::setProperty(JSContext* cx, JS::HandleObject obj, JS::HandleId id, JS::MutableHandleValue vp, JS::ObjectOpResult& result);
friend bool JSI_IGUIObject::getComputedSize(JSContext* cx, uint argc, JS::Value* vp);
public:

View File

@ -124,28 +124,28 @@ bool JSI_IGUIObject::getProperty(JSContext* cx, JS::HandleObject obj, JS::Handle
return false;
}
bool JSI_IGUIObject::setProperty(JSContext* cx, JS::HandleObject obj, JS::HandleId id, bool UNUSED(strict), JS::MutableHandleValue vp)
bool JSI_IGUIObject::setProperty(JSContext* cx, JS::HandleObject obj, JS::HandleId id, JS::MutableHandleValue vp, JS::ObjectOpResult& result)
{
IGUIObject* e = (IGUIObject*)JS_GetInstancePrivate(cx, obj, &JSI_IGUIObject::JSI_class, NULL);
if (!e)
return false;
return result.fail(JSMSG_NOT_NONNULL_OBJECT);
JSAutoRequest rq(cx);
JS::RootedValue idval(cx);
if (!JS_IdToValue(cx, id, &idval))
return false;
return result.fail(JSMSG_NOT_NONNULL_OBJECT);
std::string propName;
if (!ScriptInterface::FromJSVal(cx, idval, propName))
return false;
return result.fail(JSMSG_UNDEFINED_PROP);
if (propName == "name")
{
std::string value;
if (!ScriptInterface::FromJSVal(cx, vp, value))
return false;
return result.fail(JSMSG_UNDEFINED_PROP);
e->SetName(value);
return true;
return result.succeed();
}
JS::RootedObject vpObj(cx);
@ -158,20 +158,20 @@ bool JSI_IGUIObject::setProperty(JSContext* cx, JS::HandleObject obj, JS::Handle
if (vp.isPrimitive() || vp.isNull() || !JS_ObjectIsFunction(cx, &vp.toObject()))
{
JS_ReportError(cx, "on- event-handlers must be functions");
return false;
return result.fail(JSMSG_NOT_FUNCTION);
}
CStr eventName(CStr(propName.substr(2)).LowerCase());
e->SetScriptHandler(eventName, vpObj);
return true;
return result.succeed();
}
if (e->SettingExists(propName))
return e->m_Settings[propName]->FromJSVal(cx, vp);
return e->m_Settings[propName]->FromJSVal(cx, vp) ? result.succeed() : result.fail(JSMSG_TYPE_ERR_BAD_ARGS);
JS_ReportError(cx, "Property '%s' does not exist!", propName.c_str());
return false;
return result.fail(JSMSG_UNDEFINED_PROP);
}
void JSI_IGUIObject::init(ScriptInterface& scriptInterface)

View File

@ -25,7 +25,7 @@ namespace JSI_IGUIObject
extern JSClass JSI_class;
extern JSFunctionSpec JSI_methods[];
bool getProperty(JSContext* cx, JS::HandleObject obj, JS::HandleId id, JS::MutableHandleValue vp);
bool setProperty(JSContext* cx, JS::HandleObject obj, JS::HandleId id, bool UNUSED(strict), JS::MutableHandleValue vp);
bool setProperty(JSContext* cx, JS::HandleObject obj, JS::HandleId id, JS::MutableHandleValue vp, JS::ObjectOpResult& result);
bool toString(JSContext* cx, uint argc, JS::Value* vp);
bool focus(JSContext* cx, uint argc, JS::Value* vp);
bool blur(JSContext* cx, uint argc, JS::Value* vp);

View File

@ -608,7 +608,8 @@ bool ModIo::ParseGameIdResponse(const ScriptInterface& scriptInterface, const st
JS::RootedObject data(cx, dataVal.toObjectOrNull());
u32 length;
if (!JS_IsArrayObject(cx, data) || !JS_GetArrayLength(cx, data, &length) || !length)
bool isArray;
if (!JS_IsArrayObject(cx, data, &isArray) || !isArray || !JS_GetArrayLength(cx, data, &length) || !length)
FAIL("data property not an array with at least one element.");
// {"id": 42, ...}
@ -679,7 +680,8 @@ bool ModIo::ParseModsResponse(const ScriptInterface& scriptInterface, const std:
JS::RootedObject data(cx, dataVal.toObjectOrNull());
u32 length;
if (!JS_IsArrayObject(cx, data) || !JS_GetArrayLength(cx, data, &length) || !length)
bool isArray;
if (!JS_IsArrayObject(cx, data, &isArray) || !isArray || !JS_GetArrayLength(cx, data, &length) || !length)
FAIL("data property not an array with at least one element.");
modData.clear();

View File

@ -86,7 +86,8 @@ bool VisualReplay::ReadCacheFile(const ScriptInterface& scriptInterface, JS::Mut
if (scriptInterface.ParseJSON(cacheStr, &cachedReplays))
{
cachedReplaysObject.set(&cachedReplays.toObject());
if (JS_IsArrayObject(cx, cachedReplaysObject))
bool isArray;
if (JS_IsArrayObject(cx, cachedReplaysObject, &isArray) && isArray)
return true;
}

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2017 Wildfire Games.
/* Copyright (C) 2019 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@ -52,8 +52,9 @@ template<typename T> static bool FromJSVal_vector(JSContext* cx, JS::HandleValue
if (!v.isObject())
FAIL("Argument must be an array");
bool isArray;
obj = &v.toObject();
if (!(JS_IsArrayObject(cx, obj) || JS_IsTypedArrayObject(obj)))
if ((!JS_IsArrayObject(cx, obj, &isArray) || !isArray) && !JS_IsTypedArrayObject(obj))
FAIL("Argument must be an array");
u32 length;

View File

@ -21,6 +21,8 @@
#include "ScriptTypes.h"
#include "ps/Singleton.h"
#include "js/Initialization.h"
/**
* A class using the RAII (Resource Acquisition Is Initialization) idiom to manage initialization
* and shutdown of the SpiderMonkey script engine. It also keeps a count of active script runtimes

View File

@ -352,7 +352,6 @@ ScriptInterface_impl::ScriptInterface_impl(const char* nativeScopeName, const sh
JS::RuntimeOptionsRef(m_cx)
.setExtraWarnings(true)
.setWerror(false)
.setVarObjFix(true)
.setStrictMode(true);
JS::CompartmentOptions opt;
@ -523,11 +522,11 @@ void ScriptInterface::DefineCustomObjectType(JSClass *clasp, JSNative constructo
}
JS::RootedObject global(m->m_cx, m->m_glob);
JS::RootedObject obj(m->m_cx, JS_InitClass(m->m_cx, global, JS::NullPtr(),
clasp,
constructor, minArgs, // Constructor, min args
ps, fs, // Properties, methods
static_ps, static_fs)); // Constructor properties, methods
JS::RootedObject obj(m->m_cx, JS_InitClass(m->m_cx, global, nullptr,
clasp,
constructor, minArgs, // Constructor, min args
ps, fs, // Properties, methods
static_ps, static_fs)); // Constructor properties, methods
if (obj == NULL)
throw PSERROR_Scripting_DefineType_CreationFailed();
@ -610,7 +609,7 @@ bool ScriptInterface::SetGlobal_(const char* name, JS::HandleValue value, bool r
if (!JS_GetOwnPropertyDescriptor(m->m_cx, global, name, &desc))
return false;
if (desc.isReadonly())
if (!desc.writable())
{
if (!replace)
{
@ -620,7 +619,7 @@ bool ScriptInterface::SetGlobal_(const char* name, JS::HandleValue value, bool r
// This is not supposed to happen, unless the user has called SetProperty with constant = true on the global object
// instead of using SetGlobal.
if (desc.isPermanent())
if (!desc.configurable())
{
JS_ReportError(m->m_cx, "The global \"%s\" is permanent and cannot be hotloaded", name);
return false;
@ -776,8 +775,8 @@ bool ScriptInterface::EnumeratePropertyNamesWithPrefix(JS::HandleValue objVal, c
return true; // reached the end of the prototype chain
JS::RootedObject obj(m->m_cx, &objVal.toObject());
JS::AutoIdArray props(m->m_cx, JS_Enumerate(m->m_cx, obj));
if (!props)
JS::Rooted<JS::IdVector> props(m->m_cx, JS::IdVector(m->m_cx));
if (!JS_Enumerate(m->m_cx, obj, &props))
return false;
for (size_t i = 0; i < props.length(); ++i)
@ -865,7 +864,7 @@ bool ScriptInterface::LoadScript(const VfsPath& filename, const std::string& cod
JS::CompileOptions options(m->m_cx);
options.setFileAndLine(filenameStr.c_str(), lineNo);
options.setCompileAndGo(true);
options.setIsRunOnce(true);
JS::RootedFunction func(m->m_cx);
JS::AutoObjectVector emptyScopeChain(m->m_cx);
@ -874,7 +873,7 @@ bool ScriptInterface::LoadScript(const VfsPath& filename, const std::string& cod
return false;
JS::RootedValue rval(m->m_cx);
return JS_CallFunction(m->m_cx, JS::NullPtr(), func, JS::HandleValueArray::empty(), &rval);
return JS_CallFunction(m->m_cx, nullptr, func, JS::HandleValueArray::empty(), &rval);
}
shared_ptr<ScriptRuntime> ScriptInterface::CreateRuntime(shared_ptr<ScriptRuntime> parentRuntime, int runtimeSize, int heapGrowthBytesGCTrigger)
@ -885,7 +884,6 @@ shared_ptr<ScriptRuntime> ScriptInterface::CreateRuntime(shared_ptr<ScriptRuntim
bool ScriptInterface::LoadGlobalScript(const VfsPath& filename, const std::wstring& code) const
{
JSAutoRequest rq(m->m_cx);
JS::RootedObject global(m->m_cx, m->m_glob);
utf16string codeUtf16(code.begin(), code.end());
uint lineNo = 1;
// CompileOptions does not copy the contents of the filename string pointer.
@ -895,14 +893,13 @@ bool ScriptInterface::LoadGlobalScript(const VfsPath& filename, const std::wstri
JS::RootedValue rval(m->m_cx);
JS::CompileOptions opts(m->m_cx);
opts.setFileAndLine(filenameStr.c_str(), lineNo);
return JS::Evaluate(m->m_cx, global, opts,
return JS::Evaluate(m->m_cx, opts,
reinterpret_cast<const char16_t*>(codeUtf16.c_str()), (uint)(codeUtf16.length()), &rval);
}
bool ScriptInterface::LoadGlobalScriptFile(const VfsPath& path) const
{
JSAutoRequest rq(m->m_cx);
JS::RootedObject global(m->m_cx, m->m_glob);
if (!VfsFileExists(path))
{
LOGERROR("File '%s' does not exist", path.string8());
@ -930,7 +927,7 @@ bool ScriptInterface::LoadGlobalScriptFile(const VfsPath& path) const
JS::RootedValue rval(m->m_cx);
JS::CompileOptions opts(m->m_cx);
opts.setFileAndLine(filenameStr.c_str(), lineNo);
return JS::Evaluate(m->m_cx, global, opts,
return JS::Evaluate(m->m_cx, opts,
reinterpret_cast<const char16_t*>(codeUtf16.c_str()), (uint)(codeUtf16.length()), &rval);
}
@ -944,23 +941,21 @@ bool ScriptInterface::Eval(const char* code) const
bool ScriptInterface::Eval_(const char* code, JS::MutableHandleValue rval) const
{
JSAutoRequest rq(m->m_cx);
JS::RootedObject global(m->m_cx, m->m_glob);
utf16string codeUtf16(code, code+strlen(code));
JS::CompileOptions opts(m->m_cx);
opts.setFileAndLine("(eval)", 1);
return JS::Evaluate(m->m_cx, global, opts, reinterpret_cast<const char16_t*>(codeUtf16.c_str()), (uint)codeUtf16.length(), rval);
return JS::Evaluate(m->m_cx, opts, reinterpret_cast<const char16_t*>(codeUtf16.c_str()), (uint)codeUtf16.length(), rval);
}
bool ScriptInterface::Eval_(const wchar_t* code, JS::MutableHandleValue rval) const
{
JSAutoRequest rq(m->m_cx);
JS::RootedObject global(m->m_cx, m->m_glob);
utf16string codeUtf16(code, code+wcslen(code));
JS::CompileOptions opts(m->m_cx);
opts.setFileAndLine("(eval)", 1);
return JS::Evaluate(m->m_cx, global, opts, reinterpret_cast<const char16_t*>(codeUtf16.c_str()), (uint)codeUtf16.length(), rval);
return JS::Evaluate(m->m_cx, opts, reinterpret_cast<const char16_t*>(codeUtf16.c_str()), (uint)codeUtf16.length(), rval);
}
bool ScriptInterface::ParseJSON(const std::string& string_utf8, JS::MutableHandleValue out) const
@ -1041,7 +1036,7 @@ std::string ScriptInterface::StringifyJSON(JS::MutableHandleValue obj, bool inde
JSAutoRequest rq(m->m_cx);
Stringifier str;
JS::RootedValue indentVal(m->m_cx, indent ? JS::Int32Value(2) : JS::UndefinedValue());
if (!JS_Stringify(m->m_cx, obj, JS::NullPtr(), indentVal, &Stringifier::callback, &str))
if (!JS_Stringify(m->m_cx, obj, nullptr, indentVal, &Stringifier::callback, &str))
{
JS_ClearPendingException(m->m_cx);
LOGERROR("StringifyJSON failed");
@ -1069,7 +1064,7 @@ std::string ScriptInterface::ToString(JS::MutableHandleValue obj, bool pretty) c
// Temporary disable the error reporter, so we don't print complaints about cyclic values
JSErrorReporter er = JS_SetErrorReporter(m->m_runtime->m_rt, NULL);
bool ok = JS_Stringify(m->m_cx, obj, JS::NullPtr(), indentVal, &Stringifier::callback, &str);
bool ok = JS_Stringify(m->m_cx, obj, nullptr, indentVal, &Stringifier::callback, &str);
// Restore error reporter
JS_SetErrorReporter(m->m_runtime->m_rt, er);

View File

@ -71,7 +71,7 @@
# pragma GCC diagnostic pop
#endif
#if MOZJS_MAJOR_VERSION != 38
#if MOZJS_MAJOR_VERSION != 45
#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 \
@ -79,7 +79,7 @@ system-installed version. Make sure you have got all the right files and \
include paths.
#endif
#if MOZJS_MINOR_VERSION != 3
#if MOZJS_MINOR_VERSION != 0
#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

@ -562,8 +562,9 @@ public:
ENSURE(JS_GetArrayLength(cx, dataObj, &length));
u32 nbytes = (u32)(length * sizeof(NavcellData));
bool sharedMemory;
JS::AutoCheckCannotGC nogc;
memcpy((void*)JS_GetUint16ArrayData(dataObj, nogc), m_PassabilityMap.m_Data, nbytes);
memcpy((void*)JS_GetUint16ArrayData(dataObj, &sharedMemory, nogc), m_PassabilityMap.m_Data, nbytes);
}
}
@ -591,8 +592,9 @@ public:
ENSURE(JS_GetArrayLength(cx, dataObj, &length));
u32 nbytes = (u32)(length * sizeof(u8));
bool sharedMemory;
JS::AutoCheckCannotGC nogc;
memcpy((void*)JS_GetUint8ArrayData(dataObj, nogc), m_TerritoryMap.m_Data, nbytes);
memcpy((void*)JS_GetUint8ArrayData(dataObj, &sharedMemory, nogc), m_TerritoryMap.m_Data, nbytes);
}
}

View File

@ -241,7 +241,8 @@ template<> void ScriptInterface::ToJSVal<Grid<u8> >(JSContext* cx, JS::MutableHa
// Copy the array data and then remove the no-GC check to allow further changes to the JS data
{
JS::AutoCheckCannotGC nogc;
memcpy((void*)JS_GetUint8ArrayData(objArr, nogc), val.m_Data, nbytes);
bool sharedMemory;
memcpy((void*)JS_GetUint8ArrayData(objArr, &sharedMemory, nogc), val.m_Data, nbytes);
}
JS::RootedValue data(cx, JS::ObjectValue(*objArr));
@ -267,7 +268,8 @@ template<> void ScriptInterface::ToJSVal<Grid<u16> >(JSContext* cx, JS::MutableH
// Copy the array data and then remove the no-GC check to allow further changes to the JS data
{
JS::AutoCheckCannotGC nogc;
memcpy((void*)JS_GetUint16ArrayData(objArr, nogc), val.m_Data, nbytes);
bool sharedMemory;
memcpy((void*)JS_GetUint16ArrayData(objArr, &sharedMemory, nogc), val.m_Data, nbytes);
}
JS::RootedValue data(cx, JS::ObjectValue(*objArr));
@ -291,7 +293,8 @@ template<> bool ScriptInterface::FromJSVal<TNSpline>(JSContext* cx, JS::HandleVa
JSAutoRequest rq(cx);
JS::RootedObject obj(cx, &v.toObject());
if (!JS_IsArrayObject(cx, obj))
bool isArray;
if (!JS_IsArrayObject(cx, obj, &isArray) || !isArray)
FAIL("Argument must be an array");
u32 numberOfNodes = 0;

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2017 Wildfire Games.
/* Copyright (C) 2019 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@ -99,7 +99,8 @@ void CBinarySerializerScriptImpl::HandleScriptVal(JS::HandleValue val)
}
// Arrays are special cases of Object
if (JS_IsArrayObject(cx, obj))
bool isArray;
if (JS_IsArrayObject(cx, obj, &isArray) && isArray)
{
m_Serializer.NumberU8_Unbounded("type", SCRIPT_TYPE_ARRAY);
// TODO: probably should have a more efficient storage format
@ -119,9 +120,10 @@ void CBinarySerializerScriptImpl::HandleScriptVal(JS::HandleValue val)
m_Serializer.NumberU32_Unbounded("byte offset", JS_GetTypedArrayByteOffset(obj));
m_Serializer.NumberU32_Unbounded("length", JS_GetTypedArrayLength(obj));
bool sharedMemory;
// Now handle its array buffer
// this may be a backref, since ArrayBuffers can be shared by multiple views
JS::RootedValue bufferVal(cx, JS::ObjectValue(*JS_GetArrayBufferViewBuffer(cx, obj)));
JS::RootedValue bufferVal(cx, JS::ObjectValue(*JS_GetArrayBufferViewBuffer(cx, obj, &sharedMemory)));
HandleScriptVal(bufferVal);
break;
}
@ -136,7 +138,8 @@ void CBinarySerializerScriptImpl::HandleScriptVal(JS::HandleValue val)
u32 length = JS_GetArrayBufferByteLength(obj);
m_Serializer.NumberU32_Unbounded("buffer length", length);
JS::AutoCheckCannotGC nogc;
m_Serializer.RawBytes("buffer data", (const u8*)JS_GetArrayBufferData(obj, nogc), length);
bool sharedMemory;
m_Serializer.RawBytes("buffer data", (const u8*)JS_GetArrayBufferData(obj, &sharedMemory, nogc), length);
break;
}
else
@ -145,11 +148,8 @@ void CBinarySerializerScriptImpl::HandleScriptVal(JS::HandleValue val)
const JSClass* jsclass = JS_GetClass(obj);
if (!jsclass)
throw PSERROR_Serialize_ScriptError("JS_GetClass failed");
// TODO: Remove this workaround for upstream API breakage when updating SpiderMonkey
// See https://bugzilla.mozilla.org/show_bug.cgi?id=1236373
#define JSCLASS_CACHED_PROTO_WIDTH js::JSCLASS_CACHED_PROTO_WIDTH
JSProtoKey protokey = JSCLASS_CACHED_PROTO_KEY(jsclass);
#undef JSCLASS_CACHED_PROTO_WIDTH
if (protokey == JSProto_Object)
{
@ -302,8 +302,8 @@ void CBinarySerializerScriptImpl::HandleScriptVal(JS::HandleValue val)
}
// Find all properties (ordered by insertion time)
JS::AutoIdArray ida (cx, JS_Enumerate(cx, obj));
if (!ida)
JS::Rooted<JS::IdVector> ida(cx, JS::IdVector(cx));
if (!JS_Enumerate(cx, obj, &ida))
throw PSERROR_Serialize_ScriptError("JS_Enumerate failed");
m_Serializer.NumberU32_Unbounded("num props", (u32)ida.length());

View File

@ -213,7 +213,7 @@ JS::Value CStdDeserializer::ReadScriptVal(const char* UNUSED(name), JS::HandleOb
{
std::vector<JS::Latin1Char> propname;
ReadStringLatin1("prop name", propname);
JS::RootedValue propval(cx, ReadScriptVal("prop value", JS::NullPtr()));
JS::RootedValue propval(cx, ReadScriptVal("prop value", nullptr));
utf16string prp(propname.begin(), propname.end());;
// TODO: Should ask upstream about getting a variant of JS_SetProperty with a length param.
@ -224,7 +224,7 @@ JS::Value CStdDeserializer::ReadScriptVal(const char* UNUSED(name), JS::HandleOb
{
utf16string propname;
ReadStringUTF16("prop name", propname);
JS::RootedValue propval(cx, ReadScriptVal("prop value", JS::NullPtr()));
JS::RootedValue propval(cx, ReadScriptVal("prop value", nullptr));
if (!JS_SetUCProperty(cx, obj, (const char16_t*)propname.data(), propname.length(), propval))
throw PSERROR_Deserialize_ScriptError();
@ -333,7 +333,7 @@ JS::Value CStdDeserializer::ReadScriptVal(const char* UNUSED(name), JS::HandleOb
AddScriptBackref(arrayObj);
// Get buffer object
JS::RootedValue bufferVal(cx, ReadScriptVal("buffer", JS::NullPtr()));
JS::RootedValue bufferVal(cx, ReadScriptVal("buffer", nullptr));
if (!bufferVal.isObject())
throw PSERROR_Deserialize_ScriptError();
@ -405,8 +405,8 @@ JS::Value CStdDeserializer::ReadScriptVal(const char* UNUSED(name), JS::HandleOb
for (u32 i=0; i<mapSize; ++i)
{
JS::RootedValue key(cx, ReadScriptVal("map key", JS::NullPtr()));
JS::RootedValue value(cx, ReadScriptVal("map value", JS::NullPtr()));
JS::RootedValue key(cx, ReadScriptVal("map key", nullptr));
JS::RootedValue value(cx, ReadScriptVal("map value", nullptr));
JS::MapSet(cx, obj, key, value);
}
@ -425,7 +425,7 @@ JS::Value CStdDeserializer::ReadScriptVal(const char* UNUSED(name), JS::HandleOb
for (u32 i=0; i<setSize; ++i)
{
JS::RootedValue value(cx, ReadScriptVal("set value", JS::NullPtr()));
JS::RootedValue value(cx, ReadScriptVal("set value", nullptr));
m_ScriptInterface.CallFunctionVoid(setVal, "add", value);
}
@ -487,7 +487,7 @@ void CStdDeserializer::ScriptString(const char* name, JS::MutableHandleString ou
void CStdDeserializer::ScriptVal(const char* name, JS::MutableHandleValue out)
{
out.set(ReadScriptVal(name, JS::NullPtr()));
out.set(ReadScriptVal(name, nullptr));
}
void CStdDeserializer::ScriptObjectAppend(const char* name, JS::HandleValue objVal)

View File

@ -386,7 +386,7 @@ void CParamNode::ConstructJSVal(JSContext* cx, JS::MutableHandleValue ret) const
// Just a string
utf16string text(m_Value.begin(), m_Value.end());
JS::RootedString str(cx, JS_InternUCStringN(cx, reinterpret_cast<const char16_t*>(text.data()), text.length()));
JS::RootedString str(cx, JS_AtomizeAndPinUCStringN(cx, reinterpret_cast<const char16_t*>(text.data()), text.length()));
if (str)
{
ret.setString(str);
@ -421,7 +421,7 @@ void CParamNode::ConstructJSVal(JSContext* cx, JS::MutableHandleValue ret) const
if (!m_Value.empty())
{
utf16string text(m_Value.begin(), m_Value.end());
JS::RootedString str(cx, JS_InternUCStringN(cx, reinterpret_cast<const char16_t*>(text.data()), text.length()));
JS::RootedString str(cx, JS_AtomizeAndPinUCStringN(cx, reinterpret_cast<const char16_t*>(text.data()), text.length()));
if (!str)
{
ret.setUndefined();