From 64b477625d3185953b57ac4cb67c3ec20573e065 Mon Sep 17 00:00:00 2001 From: Itms Date: Wed, 7 Aug 2019 22:37:43 +0000 Subject: [PATCH] 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. --- build/premake/extern_libs5.lua | 28 ++++---- build/workspaces/clean-workspaces.sh | 3 +- libraries/osx/build-osx-libs.sh | 65 ++++--------------- source/gui/IGUIObject.cpp | 2 +- source/gui/IGUIObject.h | 2 +- .../gui/scripting/JSInterface_IGUIObject.cpp | 20 +++--- source/gui/scripting/JSInterface_IGUIObject.h | 2 +- source/ps/ModIo.cpp | 6 +- source/ps/VisualReplay.cpp | 3 +- source/scriptinterface/ScriptConversions.h | 5 +- source/scriptinterface/ScriptEngine.h | 2 + source/scriptinterface/ScriptInterface.cpp | 39 +++++------ source/scriptinterface/ScriptTypes.h | 4 +- .../simulation2/components/CCmpAIManager.cpp | 6 +- .../scripting/EngineScriptConversions.cpp | 9 ++- .../serialization/BinarySerializer.cpp | 20 +++--- .../serialization/StdDeserializer.cpp | 14 ++-- source/simulation2/system/ParamNode.cpp | 4 +- 18 files changed, 99 insertions(+), 135 deletions(-) diff --git a/build/premake/extern_libs5.lua b/build/premake/extern_libs5.lua index 48adad55a4..4b39de04f8 100644 --- a/build/premake/extern_libs5.lua +++ b/build/premake/extern_libs5.lua @@ -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 diff --git a/build/workspaces/clean-workspaces.sh b/build/workspaces/clean-workspaces.sh index 024bd20344..d24a7b9bcb 100755 --- a/build/workspaces/clean-workspaces.sh +++ b/build/workspaces/clean-workspaces.sh @@ -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) diff --git a/libraries/osx/build-osx-libs.sh b/libraries/osx/build-osx-libs.sh index 9ac4deb349..c97deb6425 100755 --- a/libraries/osx/build-osx-libs.sh +++ b/libraries/osx/build-osx-libs.sh @@ -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 diff --git a/source/gui/IGUIObject.cpp b/source/gui/IGUIObject.cpp index 297e18cc3b..a128e1b007 100644 --- a/source/gui/IGUIObject.cpp +++ b/source/gui/IGUIObject.cpp @@ -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); diff --git a/source/gui/IGUIObject.h b/source/gui/IGUIObject.h index b6fd854e44..770df18583 100644 --- a/source/gui/IGUIObject.h +++ b/source/gui/IGUIObject.h @@ -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: diff --git a/source/gui/scripting/JSInterface_IGUIObject.cpp b/source/gui/scripting/JSInterface_IGUIObject.cpp index 8c91f1b59c..ae1a36985a 100644 --- a/source/gui/scripting/JSInterface_IGUIObject.cpp +++ b/source/gui/scripting/JSInterface_IGUIObject.cpp @@ -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) diff --git a/source/gui/scripting/JSInterface_IGUIObject.h b/source/gui/scripting/JSInterface_IGUIObject.h index 5649db0fdd..828667044e 100644 --- a/source/gui/scripting/JSInterface_IGUIObject.h +++ b/source/gui/scripting/JSInterface_IGUIObject.h @@ -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); diff --git a/source/ps/ModIo.cpp b/source/ps/ModIo.cpp index 548d67dbe8..b0039a2ffb 100644 --- a/source/ps/ModIo.cpp +++ b/source/ps/ModIo.cpp @@ -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(); diff --git a/source/ps/VisualReplay.cpp b/source/ps/VisualReplay.cpp index 5eb1bb7a3a..b3dea66e6d 100644 --- a/source/ps/VisualReplay.cpp +++ b/source/ps/VisualReplay.cpp @@ -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; } diff --git a/source/scriptinterface/ScriptConversions.h b/source/scriptinterface/ScriptConversions.h index 095ec6cf89..42f3105602 100644 --- a/source/scriptinterface/ScriptConversions.h +++ b/source/scriptinterface/ScriptConversions.h @@ -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 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; diff --git a/source/scriptinterface/ScriptEngine.h b/source/scriptinterface/ScriptEngine.h index f9d6bb60d7..b26745db97 100644 --- a/source/scriptinterface/ScriptEngine.h +++ b/source/scriptinterface/ScriptEngine.h @@ -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 diff --git a/source/scriptinterface/ScriptInterface.cpp b/source/scriptinterface/ScriptInterface.cpp index 8f0ff0f4dd..9dfa709a73 100644 --- a/source/scriptinterface/ScriptInterface.cpp +++ b/source/scriptinterface/ScriptInterface.cpp @@ -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 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 ScriptInterface::CreateRuntime(shared_ptr parentRuntime, int runtimeSize, int heapGrowthBytesGCTrigger) @@ -885,7 +884,6 @@ shared_ptr ScriptInterface::CreateRuntime(shared_ptrm_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(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(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(codeUtf16.c_str()), (uint)codeUtf16.length(), rval); + return JS::Evaluate(m->m_cx, opts, reinterpret_cast(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(codeUtf16.c_str()), (uint)codeUtf16.length(), rval); + return JS::Evaluate(m->m_cx, opts, reinterpret_cast(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); diff --git a/source/scriptinterface/ScriptTypes.h b/source/scriptinterface/ScriptTypes.h index dfdfab61be..7a7ff7075e 100644 --- a/source/scriptinterface/ScriptTypes.h +++ b/source/scriptinterface/ScriptTypes.h @@ -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 \ diff --git a/source/simulation2/components/CCmpAIManager.cpp b/source/simulation2/components/CCmpAIManager.cpp index 60b0e9f065..a7f600381b 100644 --- a/source/simulation2/components/CCmpAIManager.cpp +++ b/source/simulation2/components/CCmpAIManager.cpp @@ -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); } } diff --git a/source/simulation2/scripting/EngineScriptConversions.cpp b/source/simulation2/scripting/EngineScriptConversions.cpp index eb836c4fe6..89ae84eaf9 100644 --- a/source/simulation2/scripting/EngineScriptConversions.cpp +++ b/source/simulation2/scripting/EngineScriptConversions.cpp @@ -241,7 +241,8 @@ template<> void ScriptInterface::ToJSVal >(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 >(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(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; diff --git a/source/simulation2/serialization/BinarySerializer.cpp b/source/simulation2/serialization/BinarySerializer.cpp index 2f1e737132..9125184ec8 100644 --- a/source/simulation2/serialization/BinarySerializer.cpp +++ b/source/simulation2/serialization/BinarySerializer.cpp @@ -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 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()); diff --git a/source/simulation2/serialization/StdDeserializer.cpp b/source/simulation2/serialization/StdDeserializer.cpp index aad37c80d8..331e6582d6 100644 --- a/source/simulation2/serialization/StdDeserializer.cpp +++ b/source/simulation2/serialization/StdDeserializer.cpp @@ -213,7 +213,7 @@ JS::Value CStdDeserializer::ReadScriptVal(const char* UNUSED(name), JS::HandleOb { std::vector 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(text.data()), text.length())); + JS::RootedString str(cx, JS_AtomizeAndPinUCStringN(cx, reinterpret_cast(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(text.data()), text.length())); + JS::RootedString str(cx, JS_AtomizeAndPinUCStringN(cx, reinterpret_cast(text.data()), text.length())); if (!str) { ret.setUndefined();