Index: binaries/data/mods/public/globalscripts/vector.js =================================================================== --- binaries/data/mods/public/globalscripts/vector.js +++ binaries/data/mods/public/globalscripts/vector.js @@ -432,5 +432,5 @@ // make the prototypes easily accessible to C++ -const Vector2Dprototype = Vector2D.prototype; -const Vector3Dprototype = Vector3D.prototype; +Object.defineProperty(this, "Vector2Dprototype", { value: Vector2D.prototype }); +Object.defineProperty(this, "Vector3Dprototype", { value: Vector3D.prototype }); Index: build/premake/extern_libs5.lua =================================================================== --- build/premake/extern_libs5.lua +++ build/premake/extern_libs5.lua @@ -565,7 +565,7 @@ compile_settings = function() if _OPTIONS["with-system-mozjs38"] then if not _OPTIONS["android"] then - pkgconfig.add_includes("mozjs-38") + pkgconfig.add_includes("mozjs-45") end else if os.istarget("windows") then @@ -585,10 +585,10 @@ link_settings = function() if _OPTIONS["with-system-mozjs38"] 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 @@ -607,7 +607,7 @@ filter { "Debug", "action:not vs*" } links { "mozjs38-ps-debug" } filter { "Release", "action:not vs*" } - links { "mozjs38-ps-release" } + links { "mozjs45-ps-release" } filter { } add_source_lib_paths("spidermonkey") end Index: libraries/osx/build-osx-libs.sh =================================================================== --- libraries/osx/build-osx-libs.sh +++ libraries/osx/build-osx-libs.sh @@ -657,9 +657,9 @@ # 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.0" pushd ../source/spidermonkey/ > /dev/null @@ -681,9 +681,9 @@ 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 + perl -i.bak -pe 's/(^STATIC_LIBRARY_NAME\s+=).*/$1'\''mozjs45-ps-debug'\''/' moz.build - CONF_OPTS="--target=$ARCH-apple-darwin --prefix=${INSTALL_DIR} --with-system-nspr --with-nspr-prefix=${NSPR_DIR} --with-system-zlib=${ZLIB_DIR} --disable-tests --disable-shared-js" + CONF_OPTS="--target=$ARCH-apple-darwin --prefix=${INSTALL_DIR} --with-system-nspr --with-nspr-prefix=${NSPR_DIR} --with-system-zlib=${ZLIB_DIR} --disable-tests --disable-shared-js --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: @@ -705,7 +705,7 @@ 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 ../configure $CONF_OPTS --enable-optimize && make ${JOBS}) || die "Spidermonkey build failed" Index: libraries/source/spidermonkey/FixMozGlueStatic.diff =================================================================== --- /dev/null +++ libraries/source/spidermonkey/FixMozGlueStatic.diff @@ -0,0 +1,20 @@ +--- mozglue/build/moz.build ++++ mozglue/build/moz.build +@@ -4,12 +4,11 @@ + # License, v. 2.0. If a copy of the MPL was not distributed with this + # file, You can obtain one at http://mozilla.org/MPL/2.0/. + +-# Build mozglue as a shared lib on Windows, OSX and Android. +-# If this is ever changed, update MOZ_SHARED_MOZGLUE in browser/installer/Makefile.in +-if CONFIG['OS_TARGET'] in ('WINNT', 'Darwin', 'Android'): +- SharedLibrary('mozglue') +-else: +- Library('mozglue') ++# Build mozglue as a static lib for 0 A.D. ++Library('mozglue') ++ ++# Bundle it into js statically. ++FINAL_LIBRARY = 'js' + + if not CONFIG['MOZ_CRT']: + SDK_LIBRARY = True Index: libraries/source/spidermonkey/FixTracelogger.diff =================================================================== --- libraries/source/spidermonkey/FixTracelogger.diff +++ libraries/source/spidermonkey/FixTracelogger.diff @@ -1,15 +1,5 @@ -diff --git a/js/src/jit-test/tests/tracelogger/bug1231170.js b/js/src/jit-test/tests/tracelogger/bug1231170.js -new file mode 100644 -index 0000000..023e93e ---- /dev/null -+++ b/js/src/jit-test/tests/tracelogger/bug1231170.js -@@ -0,0 +1,3 @@ -+var du = new Debugger(); -+if (typeof du.drainTraceLogger === "function") -+ du.drainTraceLogger(); diff --git a/js/src/jit-test/tests/tracelogger/bug1266649.js b/js/src/jit-test/tests/tracelogger/bug1266649.js new file mode 100644 -index 0000000..81ae7ad --- /dev/null +++ b/js/src/jit-test/tests/tracelogger/bug1266649.js @@ -0,0 +1,10 @@ @@ -23,161 +13,14 @@ + }) + oomTest(() => function(){}); +} -diff --git a/js/src/jit/Ion.cpp b/js/src/jit/Ion.cpp -index 93e2fda..09049d6 100644 ---- a/js/src/jit/Ion.cpp -+++ b/js/src/jit/Ion.cpp -@@ -1055,6 +1055,8 @@ IonScript::Destroy(FreeOp* fop, IonScript* script) - - script->destroyCaches(); - script->unlinkFromRuntime(fop); -+ // Frees the potential event we have set. -+ script->traceLoggerScriptEvent_ = TraceLoggerEvent(); - fop->free_(script); - } - -diff --git a/js/src/vm/Debugger.cpp b/js/src/vm/Debugger.cpp -index 26262fd..af7f313 100644 ---- a/js/src/vm/Debugger.cpp -+++ b/js/src/vm/Debugger.cpp -@@ -369,10 +369,10 @@ Debugger::Debugger(JSContext* cx, NativeObject* dbg) - objects(cx), - environments(cx), - #ifdef NIGHTLY_BUILD -- traceLoggerLastDrainedId(0), -+ traceLoggerLastDrainedSize(0), - traceLoggerLastDrainedIteration(0), - #endif -- traceLoggerScriptedCallsLastDrainedId(0), -+ traceLoggerScriptedCallsLastDrainedSize(0), - traceLoggerScriptedCallsLastDrainedIteration(0) - { - assertSameCompartment(cx, dbg); -@@ -3907,9 +3907,9 @@ Debugger::drainTraceLogger(JSContext* cx, unsigned argc, Value* vp) - size_t num; - TraceLoggerThread* logger = TraceLoggerForMainThread(cx->runtime()); - bool lostEvents = logger->lostEvents(dbg->traceLoggerLastDrainedIteration, -- dbg->traceLoggerLastDrainedId); -+ dbg->traceLoggerLastDrainedSize); - EventEntry* events = logger->getEventsStartingAt(&dbg->traceLoggerLastDrainedIteration, -- &dbg->traceLoggerLastDrainedId, -+ &dbg->traceLoggerLastDrainedSize, - &num); - - RootedObject array(cx, NewDenseEmptyArray(cx)); -@@ -4002,10 +4002,10 @@ Debugger::drainTraceLoggerScriptCalls(JSContext* cx, unsigned argc, Value* vp) - size_t num; - TraceLoggerThread* logger = TraceLoggerForMainThread(cx->runtime()); - bool lostEvents = logger->lostEvents(dbg->traceLoggerScriptedCallsLastDrainedIteration, -- dbg->traceLoggerScriptedCallsLastDrainedId); -+ dbg->traceLoggerScriptedCallsLastDrainedSize); - EventEntry* events = logger->getEventsStartingAt( - &dbg->traceLoggerScriptedCallsLastDrainedIteration, -- &dbg->traceLoggerScriptedCallsLastDrainedId, -+ &dbg->traceLoggerScriptedCallsLastDrainedSize, - &num); - - RootedObject array(cx, NewDenseEmptyArray(cx)); -diff --git a/js/src/vm/Debugger.h b/js/src/vm/Debugger.h -index 8cac36a..c92d685 100644 ---- a/js/src/vm/Debugger.h -+++ b/js/src/vm/Debugger.h -@@ -314,10 +314,10 @@ class Debugger : private mozilla::LinkedListElement - * lost events. - */ - #ifdef NIGHTLY_BUILD -- uint32_t traceLoggerLastDrainedId; -+ uint32_t traceLoggerLastDrainedSize; - uint32_t traceLoggerLastDrainedIteration; - #endif -- uint32_t traceLoggerScriptedCallsLastDrainedId; -+ uint32_t traceLoggerScriptedCallsLastDrainedSize; - uint32_t traceLoggerScriptedCallsLastDrainedIteration; - - class FrameRange; diff --git a/js/src/vm/TraceLogging.cpp b/js/src/vm/TraceLogging.cpp -index 6715b36..9766a6f 100644 --- a/js/src/vm/TraceLogging.cpp +++ b/js/src/vm/TraceLogging.cpp -@@ -131,7 +131,7 @@ TraceLoggerThread::init() - { - if (!pointerMap.init()) - return false; -- if (!extraTextId.init()) -+ if (!textIdPayloads.init()) - return false; - if (!events.init()) - return false; -@@ -185,10 +185,10 @@ TraceLoggerThread::~TraceLoggerThread() - graph = nullptr; - } - -- for (TextIdHashMap::Range r = extraTextId.all(); !r.empty(); r.popFront()) -- js_delete(r.front().value()); -- extraTextId.finish(); -- pointerMap.finish(); -+ if (textIdPayloads.initialized()) { -+ for (TextIdHashMap::Range r = textIdPayloads.all(); !r.empty(); r.popFront()) -+ js_delete(r.front().value()); -+ } - } - - bool -@@ -287,7 +287,7 @@ TraceLoggerThread::eventText(uint32_t id) - if (id < TraceLogger_Last) - return TLTextIdString(static_cast(id)); - -- TextIdHashMap::Ptr p = extraTextId.lookup(id); -+ TextIdHashMap::Ptr p = textIdPayloads.lookup(id); - MOZ_ASSERT(p); - - return p->value()->string(); -@@ -341,13 +341,15 @@ TraceLoggerThread::extractScriptDetails(uint32_t textId, const char** filename, - TraceLoggerEventPayload* - TraceLoggerThread::getOrCreateEventPayload(TraceLoggerTextId textId) - { -- TextIdHashMap::AddPtr p = extraTextId.lookupForAdd(textId); -- if (p) -+ TextIdHashMap::AddPtr p = textIdPayloads.lookupForAdd(textId); -+ if (p) { -+ MOZ_ASSERT(p->value()->textId() == textId); // Sanity check. - return p->value(); -+ } - - TraceLoggerEventPayload* payload = js_new(textId, (char*)nullptr); - -- if (!extraTextId.add(p, textId, payload)) -+ if (!textIdPayloads.add(p, textId, payload)) - return nullptr; - - return payload; -@@ -357,8 +359,10 @@ TraceLoggerEventPayload* - TraceLoggerThread::getOrCreateEventPayload(const char* text) - { - PointerHashMap::AddPtr p = pointerMap.lookupForAdd((const void*)text); -- if (p) -+ if (p) { -+ MOZ_ASSERT(p->value()->textId() < nextTextId); // Sanity check. - return p->value(); -+ } - - size_t len = strlen(text); - char* str = js_pod_malloc(len + 1); -@@ -369,7 +373,7 @@ TraceLoggerThread::getOrCreateEventPayload(const char* text) - MOZ_ASSERT(ret == len); - MOZ_ASSERT(strlen(str) == len); - -- uint32_t textId = extraTextId.count() + TraceLogger_Last; -+ uint32_t textId = nextTextId; - - TraceLoggerEventPayload* payload = js_new(textId, str); - if (!payload) { -@@ -377,17 +381,19 @@ TraceLoggerThread::getOrCreateEventPayload(const char* text) +@@ -373,24 +373,24 @@ TraceLoggerThread::getOrCreateEventPaylo return nullptr; } -- if (!extraTextId.putNew(textId, payload)) { -+ if (!textIdPayloads.putNew(textId, payload)) { + if (!textIdPayloads.putNew(textId, payload)) { js_delete(payload); return nullptr; } @@ -188,46 +31,24 @@ if (graph.get()) graph->addTextId(textId, str); -+ nextTextId++; -+ + nextTextId++; + + if (!pointerMap.add(p, text, payload)) + return nullptr; + return payload; } -@@ -407,9 +413,14 @@ TraceLoggerThread::getOrCreateEventPayload(TraceLoggerTextId type, const char* f - if (!traceLoggerState->isTextIdEnabled(type)) - return getOrCreateEventPayload(type); - -- PointerHashMap::AddPtr p = pointerMap.lookupForAdd(ptr); -- if (p) -- return p->value(); -+ PointerHashMap::AddPtr p; -+ if (ptr) { -+ p = pointerMap.lookupForAdd(ptr); -+ if (p) { -+ MOZ_ASSERT(p->value()->textId() < nextTextId); // Sanity check. -+ return p->value(); -+ } -+ } - - // Compute the length of the string to create. - size_t lenFilename = strlen(filename); -@@ -428,24 +439,28 @@ TraceLoggerThread::getOrCreateEventPayload(TraceLoggerTextId type, const char* f - MOZ_ASSERT(ret == len); - MOZ_ASSERT(strlen(str) == len); - -- uint32_t textId = extraTextId.count() + TraceLogger_Last; -+ uint32_t textId = nextTextId; - TraceLoggerEventPayload* payload = js_new(textId, str); - if (!payload) { - js_free(str); + TraceLoggerEventPayload* + TraceLoggerThread::getOrCreateEventPayload(TraceLoggerTextId type, const char* filename, + size_t lineno, size_t colno, const void* ptr) + { + MOZ_ASSERT(type == TraceLogger_Scripts || type == TraceLogger_AnnotateScripts || +@@ -435,24 +435,24 @@ TraceLoggerThread::getOrCreateEventPaylo return nullptr; } -- if (!extraTextId.putNew(textId, payload)) { -+ if (!textIdPayloads.putNew(textId, payload)) { + if (!textIdPayloads.putNew(textId, payload)) { js_delete(payload); return nullptr; } @@ -238,328 +59,17 @@ if (graph.get()) graph->addTextId(textId, str); -+ nextTextId++; -+ -+ if (ptr) { -+ if (!pointerMap.add(p, ptr, payload)) -+ return nullptr; -+ } + nextTextId++; + ++ if (!pointerMap.add(p, ptr, payload)) ++ return nullptr; + return payload; } -@@ -453,14 +468,14 @@ TraceLoggerEventPayload* + TraceLoggerEventPayload* TraceLoggerThread::getOrCreateEventPayload(TraceLoggerTextId type, JSScript* script) { return getOrCreateEventPayload(type, script->filename(), script->lineno(), script->column(), -- script); -+ nullptr); - } - - TraceLoggerEventPayload* - TraceLoggerThread::getOrCreateEventPayload(TraceLoggerTextId type, - const JS::ReadOnlyCompileOptions& script) - { -- return getOrCreateEventPayload(type, script.filename(), script.lineno, script.column, &script); -+ return getOrCreateEventPayload(type, script.filename(), script.lineno, script.column, nullptr); - } - - void -@@ -485,7 +500,7 @@ TraceLoggerThread::startEvent(uint32_t id) - if (!traceLoggerState->isTextIdEnabled(id)) - return; - -- logTimestamp(id); -+ log(id); - } - - void -@@ -510,7 +525,7 @@ TraceLoggerThread::stopEvent(uint32_t id) - if (!traceLoggerState->isTextIdEnabled(id)) - return; - -- logTimestamp(TraceLogger_Stop); -+ log(TraceLogger_Stop); - } - - void -@@ -522,23 +537,57 @@ TraceLoggerThread::logTimestamp(TraceLoggerTextId id) - void - TraceLoggerThread::logTimestamp(uint32_t id) - { -+ MOZ_ASSERT(id > TraceLogger_LastTreeItem && id < TraceLogger_Last); -+ log(id); -+} -+ -+void -+TraceLoggerThread::log(uint32_t id) -+{ - if (enabled == 0) - return; - - MOZ_ASSERT(traceLoggerState); -- if (!events.ensureSpaceBeforeAdd()) { -+ -+ // We request for 3 items to add, since if we don't have enough room -+ // we record the time it took to make more place. To log this information -+ // we need 2 extra free entries. -+ if (!events.hasSpaceForAdd(3)) { - uint64_t start = rdtsc() - traceLoggerState->startupTime; - -- if (graph.get()) -- graph->log(events); -+ if (!events.ensureSpaceBeforeAdd(3)) { -+ if (graph.get()) -+ graph->log(events); -+ -+ iteration_++; -+ events.clear(); -+ -+ // Remove the item in the pointerMap for which the payloads -+ // have no uses anymore -+ for (PointerHashMap::Enum e(pointerMap); !e.empty(); e.popFront()) { -+ if (e.front().value()->uses() != 0) -+ continue; -+ -+ TextIdHashMap::Ptr p = textIdPayloads.lookup(e.front().value()->textId()); -+ MOZ_ASSERT(p); -+ textIdPayloads.remove(p); -+ -+ e.removeFront(); -+ } - -- iteration_++; -- events.clear(); -+ // Free all payloads that have no uses anymore. -+ for (TextIdHashMap::Enum e(textIdPayloads); !e.empty(); e.popFront()) { -+ if (e.front().value()->uses() == 0) { -+ js_delete(e.front().value()); -+ e.removeFront(); -+ } -+ } -+ } - - // Log the time it took to flush the events as being from the - // Tracelogger. - if (graph.get()) { -- MOZ_ASSERT(events.capacity() > 2); -+ MOZ_ASSERT(events.hasSpaceForAdd(2)); - EventEntry& entryStart = events.pushUninitialized(); - entryStart.time = start; - entryStart.textId = TraceLogger_Internal; -@@ -548,13 +597,6 @@ TraceLoggerThread::logTimestamp(uint32_t id) - entryStop.textId = TraceLogger_Stop; - } - -- // Free all TextEvents that have no uses anymore. -- for (TextIdHashMap::Enum e(extraTextId); !e.empty(); e.popFront()) { -- if (e.front().value()->uses() == 0) { -- js_delete(e.front().value()); -- e.removeFront(); -- } -- } - } - - uint64_t time = rdtsc() - traceLoggerState->startupTime; -@@ -956,3 +998,16 @@ TraceLoggerEvent::~TraceLoggerEvent() - if (payload_) - payload_->release(); - } -+ -+TraceLoggerEvent& -+TraceLoggerEvent::operator=(const TraceLoggerEvent& other) -+{ -+ if (hasPayload()) -+ payload()->release(); -+ if (other.hasPayload()) -+ other.payload()->use(); -+ -+ payload_ = other.payload_; -+ -+ return *this; -+} -diff --git a/js/src/vm/TraceLogging.h b/js/src/vm/TraceLogging.h -index a124dcb..91a1eb0 100644 ---- a/js/src/vm/TraceLogging.h -+++ b/js/src/vm/TraceLogging.h -@@ -110,6 +110,9 @@ class TraceLoggerEvent { - bool hasPayload() const { - return !!payload_; - } -+ -+ TraceLoggerEvent& operator=(const TraceLoggerEvent& other); -+ TraceLoggerEvent(const TraceLoggerEvent& event) = delete; - }; - - /** -@@ -130,6 +133,10 @@ class TraceLoggerEventPayload { - uses_(0) - { } - -+ ~TraceLoggerEventPayload() { -+ MOZ_ASSERT(uses_ == 0); -+ } -+ - uint32_t textId() { - return textId_; - } -@@ -166,7 +173,8 @@ class TraceLoggerThread - mozilla::UniquePtr graph; - - PointerHashMap pointerMap; -- TextIdHashMap extraTextId; -+ TextIdHashMap textIdPayloads; -+ uint32_t nextTextId; - - ContinuousSpace events; - -@@ -181,6 +189,7 @@ class TraceLoggerThread - : enabled(0), - failed(false), - graph(), -+ nextTextId(TraceLogger_Last), - iteration_(0), - top(nullptr) - { } -@@ -195,22 +204,22 @@ class TraceLoggerThread - bool enable(JSContext* cx); - bool disable(); - -- // Given the previous iteration and lastEntryId, return an array of events -+ // Given the previous iteration and size, return an array of events - // (there could be lost events). At the same time update the iteration and -- // lastEntry and gives back how many events there are. -- EventEntry* getEventsStartingAt(uint32_t* lastIteration, uint32_t* lastEntryId, size_t* num) { -+ // size and gives back how many events there are. -+ EventEntry* getEventsStartingAt(uint32_t* lastIteration, uint32_t* lastSize, size_t* num) { - EventEntry* start; - if (iteration_ == *lastIteration) { -- MOZ_ASSERT(events.lastEntryId() >= *lastEntryId); -- *num = events.lastEntryId() - *lastEntryId; -- start = events.data() + *lastEntryId + 1; -+ MOZ_ASSERT(*lastSize <= events.size()); -+ *num = events.size() - *lastSize; -+ start = events.data() + *lastSize; - } else { -- *num = events.lastEntryId() + 1; -+ *num = events.size(); - start = events.data(); - } - - *lastIteration = iteration_; -- *lastEntryId = events.lastEntryId(); -+ *lastSize = events.size(); - return start; - } - -@@ -220,16 +229,16 @@ class TraceLoggerThread - const char** lineno, size_t* lineno_len, const char** colno, - size_t* colno_len); - -- bool lostEvents(uint32_t lastIteration, uint32_t lastEntryId) { -+ bool lostEvents(uint32_t lastIteration, uint32_t lastSize) { - // If still logging in the same iteration, there are no lost events. - if (lastIteration == iteration_) { -- MOZ_ASSERT(lastEntryId <= events.lastEntryId()); -+ MOZ_ASSERT(lastSize <= events.size()); - return false; - } - -- // When proceeded to the next iteration and lastEntryId points to -- // the maximum capacity there are no logs that are lost. -- if (lastIteration + 1 == iteration_ && lastEntryId == events.capacity()) -+ // If we are in a consecutive iteration we are only sure we didn't lose any events, -+ // when the lastSize equals the maximum size 'events' can get. -+ if (lastIteration == iteration_ - 1 && lastSize == events.maxSize()) - return false; - - return true; -@@ -268,6 +277,7 @@ class TraceLoggerThread - void stopEvent(uint32_t id); - private: - void stopEvent(); -+ void log(uint32_t id); - - public: - static unsigned offsetOfEnabled() { -diff --git a/js/src/vm/TraceLoggingGraph.cpp b/js/src/vm/TraceLoggingGraph.cpp -index d1b7f2e..a4eb273 100644 ---- a/js/src/vm/TraceLoggingGraph.cpp -+++ b/js/src/vm/TraceLoggingGraph.cpp -@@ -276,7 +276,7 @@ TraceLoggerGraph::flush() - if (bytesWritten < tree.size()) - return false; - -- treeOffset += tree.lastEntryId(); -+ treeOffset += tree.size(); - tree.clear(); - } - -@@ -359,7 +359,7 @@ TraceLoggerGraph::startEventInternal(uint32_t id, uint64_t timestamp) - - if (parent.lastChildId() == 0) { - MOZ_ASSERT(!entry.hasChildren()); -- MOZ_ASSERT(parent.treeId() == tree.lastEntryId() + treeOffset); -+ MOZ_ASSERT(parent.treeId() == treeOffset + tree.size() - 1); - - if (!updateHasChildren(parent.treeId())) - return false; -diff --git a/js/src/vm/TraceLoggingTypes.h b/js/src/vm/TraceLoggingTypes.h -index f1c9d0c..10b76d6 100644 ---- a/js/src/vm/TraceLoggingTypes.h -+++ b/js/src/vm/TraceLoggingTypes.h -@@ -21,7 +21,6 @@ - _(Internal) \ - _(Interpreter) \ - _(InlinedScripts) \ -- _(Invalidation) \ - _(IonCompilation) \ - _(IonCompilationPaused) \ - _(IonLinking) \ -@@ -60,6 +59,7 @@ - - #define TRACELOGGER_LOG_ITEMS(_) \ - _(Bailout) \ -+ _(Invalidation) \ - _(Disable) \ - _(Enable) \ - _(Stop) -@@ -130,6 +130,9 @@ class ContinuousSpace { - uint32_t size_; - uint32_t capacity_; - -+ // The maximum amount of ram memory a continuous space structure can take (in bytes). -+ static const uint32_t LIMIT = 200 * 1024 * 1024; -+ - public: - ContinuousSpace () - : data_(nullptr) -@@ -151,6 +154,10 @@ class ContinuousSpace { - data_ = nullptr; - } - -+ static uint32_t maxSize() { -+ return LIMIT / sizeof(T); -+ } -+ - T* data() { - return data_; - } -@@ -187,11 +194,14 @@ class ContinuousSpace { - if (hasSpaceForAdd(count)) - return true; - -+ // Limit the size of a continuous buffer. -+ if (size_ + count > maxSize()) -+ return false; -+ - uint32_t nCapacity = capacity_ * 2; -- if (size_ + count > nCapacity) -- nCapacity = size_ + count; -- T* entries = (T*) js_realloc(data_, nCapacity * sizeof(T)); -+ nCapacity = (nCapacity < maxSize()) ? nCapacity : maxSize(); - -+ T* entries = (T*) js_realloc(data_, nCapacity * sizeof(T)); - if (!entries) - return false; - + script); + Index: libraries/source/spidermonkey/FixVersionDetection.diff =================================================================== --- libraries/source/spidermonkey/FixVersionDetection.diff +++ /dev/null @@ -1,137 +0,0 @@ - -# HG changeset patch -# User Sean Stangl -# Date 1426889983 25200 -# Node ID 4f8bbef857155fbee1d064e014b22dd72512b389 -# Parent 6f42f8ee82468d18acd65e0c2b5bf6c040696224 -Bug 1145882 - Part 1/2 - Only use $PYTHON after defined by MOZ_PYTHON. r=glandium - -diff --git a/js/src/configure.in b/js/src/configure.in ---- a/js/src/configure.in -+++ b/js/src/configure.in -@@ -228,61 +228,16 @@ if test -n "$gonkdir" ; then - fi - - AC_DEFINE(ANDROID) - AC_DEFINE(GONK) - else - MOZ_ANDROID_NDK - fi - --dnl ============================================================== --dnl Get mozilla version from central milestone file --dnl ============================================================== --MOZILLA_VERSION=`$PYTHON $srcdir/python/mozbuild/mozbuild/milestone.py --topsrcdir $srcdir` --MOZILLA_UAVERSION=`$PYTHON $srcdir/python/mozbuild/mozbuild/milestone.py --topsrcdir $srcdir --uaversion` --MOZILLA_SYMBOLVERSION=`$PYTHON $srcdir/python/mozbuild/mozbuild/milestone.py --topsrcdir $srcdir --symbolversion` -- --AC_DEFINE_UNQUOTED(MOZILLA_VERSION,"$MOZILLA_VERSION") --AC_DEFINE_UNQUOTED(MOZILLA_VERSION_U,$MOZILLA_VERSION) --AC_DEFINE_UNQUOTED(MOZILLA_UAVERSION,"$MOZILLA_UAVERSION") --AC_SUBST(MOZILLA_SYMBOLVERSION) -- --# Separate version into components for use in shared object naming etc --changequote(,) --MOZJS_MAJOR_VERSION=`echo $MOZILLA_VERSION | sed "s|\(^[0-9]*\)\.[0-9]*.*|\1|"` --MOZJS_MINOR_VERSION=`echo $MOZILLA_VERSION | sed "s|^[0-9]*\.\([0-9]*\).*|\1|"` --MOZJS_PATCH_VERSION=`echo $MOZILLA_VERSION | sed "s|^[0-9]*\.[0-9]*[^0-9]*||"` --IS_ALPHA=`echo $MOZILLA_VERSION | grep '[ab]'` -- --dnl XXX in a temporary bid to avoid developer anger at renaming files --dnl XXX before "js" symlinks exist, don't change names. --dnl --dnl if test -n "$JS_STANDALONE"; then --dnl JS_SHELL_NAME=js$MOZJS_MAJOR_VERSION --dnl JS_CONFIG_NAME=js$MOZJS_MAJOR_VERSION-config --dnl else --JS_SHELL_NAME=js --JS_CONFIG_NAME=js-config --dnl fi -- --changequote([,]) --if test -n "$IS_ALPHA"; then -- changequote(,) -- MOZJS_ALPHA=`echo $MOZILLA_VERSION | sed "s|^[0-9]*\.[0-9\.]*\([^0-9]\).*|\1|"` -- changequote([,]) --fi --AC_DEFINE_UNQUOTED(MOZJS_MAJOR_VERSION,$MOZJS_MAJOR_VERSION) --AC_DEFINE_UNQUOTED(MOZJS_MINOR_VERSION,$MOZJS_MINOR_VERSION) --AC_SUBST(JS_SHELL_NAME) --AC_SUBST(JS_CONFIG_NAME) --AC_SUBST(MOZJS_MAJOR_VERSION) --AC_SUBST(MOZJS_MINOR_VERSION) --AC_SUBST(MOZJS_PATCH_VERSION) --AC_SUBST(MOZJS_ALPHA) -- - dnl ======================================================== - dnl Checks for compilers. - dnl ======================================================== - - dnl AR_FLAGS set here so HOST_AR_FLAGS can be set correctly (see bug 538269) - AR_FLAGS='crs $@' - - if test "$COMPILE_ENVIRONMENT"; then -@@ -733,16 +688,62 @@ fi - if test "$COMPILE_ENVIRONMENT"; then - - AC_PATH_XTRA - - XCFLAGS="$X_CFLAGS" - - fi # COMPILE_ENVIRONMENT - -+dnl ============================================================== -+dnl Get mozilla version from central milestone file -+dnl ============================================================== -+MOZILLA_VERSION=`$PYTHON $srcdir/python/mozbuild/mozbuild/milestone.py --topsrcdir $srcdir` -+MOZILLA_UAVERSION=`$PYTHON $srcdir/python/mozbuild/mozbuild/milestone.py --topsrcdir $srcdir --uaversion` -+MOZILLA_SYMBOLVERSION=`$PYTHON $srcdir/python/mozbuild/mozbuild/milestone.py --topsrcdir $srcdir --symbolversion` -+ -+AC_DEFINE_UNQUOTED(MOZILLA_VERSION,"$MOZILLA_VERSION") -+AC_DEFINE_UNQUOTED(MOZILLA_VERSION_U,$MOZILLA_VERSION) -+AC_DEFINE_UNQUOTED(MOZILLA_UAVERSION,"$MOZILLA_UAVERSION") -+AC_SUBST(MOZILLA_SYMBOLVERSION) -+ -+# Separate version into components for use in shared object naming etc -+changequote(,) -+MOZJS_MAJOR_VERSION=`echo $MOZILLA_VERSION | sed "s|\(^[0-9]*\)\.[0-9]*.*|\1|"` -+MOZJS_MINOR_VERSION=`echo $MOZILLA_VERSION | sed "s|^[0-9]*\.\([0-9]*\).*|\1|"` -+MOZJS_PATCH_VERSION=`echo $MOZILLA_VERSION | sed "s|^[0-9]*\.[0-9]*[^0-9]*||"` -+IS_ALPHA=`echo $MOZILLA_VERSION | grep '[ab]'` -+ -+dnl XXX in a temporary bid to avoid developer anger at renaming files -+dnl XXX before "js" symlinks exist, don't change names. -+dnl -+dnl if test -n "$JS_STANDALONE"; then -+dnl JS_SHELL_NAME=js$MOZJS_MAJOR_VERSION -+dnl JS_CONFIG_NAME=js$MOZJS_MAJOR_VERSION-config -+dnl else -+JS_SHELL_NAME=js -+JS_CONFIG_NAME=js-config -+dnl fi -+ -+changequote([,]) -+if test -n "$IS_ALPHA"; then -+ changequote(,) -+ MOZJS_ALPHA=`echo $MOZILLA_VERSION | sed "s|^[0-9]*\.[0-9\.]*\([^0-9]\).*|\1|"` -+ changequote([,]) -+fi -+AC_DEFINE_UNQUOTED(MOZJS_MAJOR_VERSION,$MOZJS_MAJOR_VERSION) -+AC_DEFINE_UNQUOTED(MOZJS_MINOR_VERSION,$MOZJS_MINOR_VERSION) -+AC_SUBST(JS_SHELL_NAME) -+AC_SUBST(JS_CONFIG_NAME) -+AC_SUBST(MOZJS_MAJOR_VERSION) -+AC_SUBST(MOZJS_MINOR_VERSION) -+AC_SUBST(MOZJS_PATCH_VERSION) -+AC_SUBST(MOZJS_ALPHA) -+ -+ - dnl ======================================================== - dnl set the defaults first - dnl ======================================================== - AS_BIN=$AS - AR_LIST='$(AR) t' - AR_EXTRACT='$(AR) x' - AR_DELETE='$(AR) d' - AS='$(CC)' - Index: libraries/source/spidermonkey/FixVersionDetectionConfigure.diff =================================================================== --- libraries/source/spidermonkey/FixVersionDetectionConfigure.diff +++ /dev/null @@ -1,178 +0,0 @@ -Created from the patched (FixVersionDetection.diff) configure.in, ignoring -unrelated hunks (thus invalidating some hard-coded line numbers). This way -we do not add a dependency on autoconf-2.13. - -diff --git a/js/src/configure b/js/src/configure ---- a/js/src/configure -+++ b/js/src/configure -@@ -1662,70 +1662,6 @@ esac - - fi - --MOZILLA_VERSION=`$PYTHON $srcdir/python/mozbuild/mozbuild/milestone.py --topsrcdir $srcdir` --MOZILLA_UAVERSION=`$PYTHON $srcdir/python/mozbuild/mozbuild/milestone.py --topsrcdir $srcdir --uaversion` --MOZILLA_SYMBOLVERSION=`$PYTHON $srcdir/python/mozbuild/mozbuild/milestone.py --topsrcdir $srcdir --symbolversion` -- --cat >> confdefs.pytmp <> confdefs.h <> confdefs.pytmp <> confdefs.h <> confdefs.pytmp <> confdefs.h <> confdefs.pytmp <> confdefs.h <> confdefs.pytmp <> confdefs.h <> confdefs.pytmp <> confdefs.h <> confdefs.pytmp <> confdefs.h <> confdefs.pytmp <> confdefs.h <> confdefs.pytmp <> confdefs.h <> confdefs.pytmp <> confdefs.h <> $CONFIG_STATUS <> $CONFIG_STATUS <SetName(value); - return true; + return result.succeed(); } JS::RootedObject vpObj(cx); @@ -351,13 +351,13 @@ 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(); } // Retrieve the setting's type (and make sure it actually exists) @@ -365,7 +365,7 @@ if (e->GetSettingType(propName, Type) != PSRETURN_OK) { JS_ReportError(cx, "Invalid setting '%s'", propName.c_str()); - return true; + return !result.fail(JSMSG_TYPE_ERR_BAD_ARGS); } switch (Type) @@ -374,7 +374,7 @@ { std::string value; if (!ScriptInterface::FromJSVal(cx, vp, value)) - return false; + return !result.fail(JSMSG_UNDEFINED_PROP); GUI::SetSetting(e, propName, value); break; @@ -384,7 +384,7 @@ { std::wstring value; if (!ScriptInterface::FromJSVal(cx, vp, value)) - return false; + return !result.fail(JSMSG_UNDEFINED_PROP); GUI::SetSetting(e, propName, value); break; @@ -394,7 +394,7 @@ { std::string value; if (!ScriptInterface::FromJSVal(cx, vp, value)) - return false; + return !result.fail(JSMSG_UNDEFINED_PROP); GUI::SetSetting(e, propName, CGUISpriteInstance(value)); break; @@ -404,7 +404,7 @@ { std::wstring value; if (!ScriptInterface::FromJSVal(cx, vp, value)) - return false; + return !result.fail(JSMSG_UNDEFINED_PROP); CGUIString str; str.SetValue(value); @@ -416,7 +416,7 @@ { std::string value; if (!ScriptInterface::FromJSVal(cx, vp, value)) - return false; + return !result.fail(JSMSG_UNDEFINED_PROP); EAlign a; if (value == "left") a = EAlign_Left; @@ -425,7 +425,7 @@ else { JS_ReportError(cx, "Invalid alignment (should be 'left', 'right' or 'center')"); - return false; + return !result.fail(JSMSG_TYPE_ERR_BAD_ARGS); } GUI::SetSetting(e, propName, a); break; @@ -435,7 +435,7 @@ { std::string value; if (!ScriptInterface::FromJSVal(cx, vp, value)) - return false; + return !result.fail(JSMSG_UNDEFINED_PROP); EVAlign a; if (value == "top") a = EVAlign_Top; @@ -444,7 +444,7 @@ else { JS_ReportError(cx, "Invalid alignment (should be 'top', 'bottom' or 'center')"); - return false; + return !result.fail(JSMSG_TYPE_ERR_BAD_ARGS); } GUI::SetSetting(e, propName, a); break; @@ -458,7 +458,7 @@ else { JS_ReportError(cx, "Cannot convert value to int"); - return false; + return !result.fail(JSMSG_TYPE_ERR_BAD_ARGS); } break; } @@ -471,7 +471,7 @@ else { JS_ReportError(cx, "Cannot convert value to u32"); - return false; + return !result.fail(JSMSG_TYPE_ERR_BAD_ARGS); } break; } @@ -484,7 +484,7 @@ else { JS_ReportError(cx, "Cannot convert value to float"); - return false; + return !result.fail(JSMSG_TYPE_ERR_BAD_ARGS); } break; } @@ -502,12 +502,12 @@ { std::wstring value; if (!ScriptInterface::FromJSVal(cx, vp, value)) - return false; + return !result.fail(JSMSG_UNDEFINED_PROP); if (e->SetSetting(propName, value) != PSRETURN_OK) { JS_ReportError(cx, "Invalid value for setting '%s'", propName.c_str()); - return false; + return !result.fail(JSMSG_TYPE_ERR_BAD_ARGS); } } else if (vp.isObject() && JS_InstanceOf(cx, vpObj, &JSI_GUISize::JSI_class, NULL)) @@ -532,7 +532,7 @@ else { JS_ReportError(cx, "Size only accepts strings or GUISize objects"); - return false; + return !result.fail(JSMSG_TYPE_ERR_BAD_ARGS); } break; } @@ -543,12 +543,12 @@ { std::wstring value; if (!ScriptInterface::FromJSVal(cx, vp, value)) - return false; + return !result.fail(JSMSG_UNDEFINED_PROP); if (e->SetSetting(propName, value) != PSRETURN_OK) { JS_ReportError(cx, "Invalid value for setting '%s'", propName.c_str()); - return false; + return !result.fail(JSMSG_TYPE_ERR_BAD_ARGS); } } else if (vp.isObject() && JS_InstanceOf(cx, vpObj, &JSI_GUIColor::JSI_class, NULL)) @@ -571,7 +571,7 @@ else { JS_ReportError(cx, "Color only accepts strings or GUIColor objects"); - return false; + return !result.fail(JSMSG_TYPE_ERR_BAD_ARGS); } break; } @@ -584,7 +584,7 @@ else { JS_ReportError(cx, "Failed to get list '%s'", propName.c_str()); - return false; + return !result.fail(JSMSG_TYPE_ERR_BAD_ARGS); } break; } @@ -597,7 +597,7 @@ else { JS_ReportError(cx, "Invalid value for chart series '%s'", propName.c_str()); - return false; + return !result.fail(JSMSG_TYPE_ERR_BAD_ARGS); } break; } @@ -607,7 +607,7 @@ break; } - return !JS_IsExceptionPending(cx); + return result.succeed() && !JS_IsExceptionPending(cx); } @@ -635,13 +635,13 @@ void JSI_IGUIObject::init(ScriptInterface& scriptInterface) { - scriptInterface.DefineCustomObjectType(&JSI_class, construct, 1, JSI_props, JSI_methods, NULL, NULL); + scriptInterface.DefineCustomObjectType(&JSI_class, construct, 1, nullptr, JSI_methods, NULL, NULL); } bool JSI_IGUIObject::toString(JSContext* cx, uint UNUSED(argc), JS::Value* vp) { - JSAutoRequest rq(cx); JS::CallReceiver rec = JS::CallReceiverFromVp(vp); + JSAutoRequest rq(cx); JS::RootedObject thisObj(cx, JS_THIS_OBJECT(cx, vp)); Index: source/ps/GameSetup/GameSetup.cpp =================================================================== --- source/ps/GameSetup/GameSetup.cpp +++ source/ps/GameSetup/GameSetup.cpp @@ -182,8 +182,8 @@ // display progress / description in loading screen void GUI_DisplayLoadProgress(int percent, const wchar_t* pending_task) { - g_GUI->GetActiveGUI()->GetScriptInterface()->SetGlobal("g_Progress", percent, true); - g_GUI->GetActiveGUI()->GetScriptInterface()->SetGlobal("g_LoadDescription", pending_task, true); + g_GUI->GetActiveGUI()->GetScriptInterface()->SetGlobal("g_Progress", percent, true, false, true); + g_GUI->GetActiveGUI()->GetScriptInterface()->SetGlobal("g_LoadDescription", pending_task, true, false, true); g_GUI->GetActiveGUI()->SendEventToAll("progress"); } Index: source/ps/ModIo.cpp =================================================================== --- source/ps/ModIo.cpp +++ source/ps/ModIo.cpp @@ -591,7 +591,8 @@ JS::RootedObject data(cx, dataVal.toObjectOrNull()); u32 length; - if (!JS_IsArrayObject(cx, data) || !JS_GetArrayLength(cx, data, &length) || !length) + bool realArray; + if (!JS_IsArrayObject(cx, data, &realArray) || !JS_GetArrayLength(cx, data, &length) || !length) FAIL("data property not an array with at least one element."); // {"id": 42, ...} @@ -662,7 +663,8 @@ JS::RootedObject data(cx, dataVal.toObjectOrNull()); u32 length; - if (!JS_IsArrayObject(cx, data) || !JS_GetArrayLength(cx, data, &length) || !length) + bool realArray; + if (!JS_IsArrayObject(cx, data, &realArray) || !JS_GetArrayLength(cx, data, &length) || !length) FAIL("data property not an array with at least one element."); modData.clear(); Index: source/ps/VisualReplay.cpp =================================================================== --- source/ps/VisualReplay.cpp +++ source/ps/VisualReplay.cpp @@ -80,7 +80,8 @@ if (scriptInterface.ParseJSON(cacheStr, &cachedReplays)) { cachedReplaysObject.set(&cachedReplays.toObject()); - if (JS_IsArrayObject(cx, cachedReplaysObject)) + bool realArray; + if (JS_IsArrayObject(cx, cachedReplaysObject, &realArray)) return true; } @@ -328,7 +329,7 @@ const OsPath replayFile = GetDirectoryName() / directory / L"commands.txt"; if (!FileExists(replayFile)) - return JSVAL_NULL; + return JS::NullValue(); // Get file size and modification date CFileInfo fileInfo; @@ -336,7 +337,7 @@ const off_t fileSize = fileInfo.Size(); if (fileSize == 0) - return JSVAL_NULL; + return JS::NullValue(); std::ifstream* replayStream = new std::ifstream(OsString(replayFile).c_str()); @@ -345,14 +346,14 @@ { LOGERROR("Couldn't open %s.", replayFile.string8().c_str()); SAFE_DELETE(replayStream); - return JSVAL_NULL; + return JS::NullValue(); } if (type != "start") { LOGWARNING("The replay %s doesn't begin with 'start'!", replayFile.string8().c_str()); SAFE_DELETE(replayStream); - return JSVAL_NULL; + return JS::NullValue(); } // Parse header / first line @@ -365,14 +366,14 @@ { LOGERROR("Couldn't parse replay header of %s", replayFile.string8().c_str()); SAFE_DELETE(replayStream); - return JSVAL_NULL; + return JS::NullValue(); } // Ensure "turn" after header if (!(*replayStream >> type).good() || type != "turn") { SAFE_DELETE(replayStream); - return JSVAL_NULL; // there are no turns at all + return JS::NullValue(); // there are no turns at all } // Don't process files of rejoined clients @@ -381,7 +382,7 @@ if (turn != 0) { SAFE_DELETE(replayStream); - return JSVAL_NULL; + return JS::NullValue(); } int duration = getReplayDuration(replayStream, replayFile, fileSize); @@ -390,7 +391,7 @@ // Ensure minimum duration if (duration < minimumReplayDuration) - return JSVAL_NULL; + return JS::NullValue(); // Return the actual data JS::RootedValue replayData(cx); @@ -497,7 +498,7 @@ JS::Value VisualReplay::GetReplayMetadata(ScriptInterface::CxPrivate* pCxPrivate, const OsPath& directoryName) { if (!HasReplayMetadata(directoryName)) - return JSVAL_NULL; + return JS::NullValue(); JSContext* cx = pCxPrivate->pScriptInterface->GetContext(); JSAutoRequest rq(cx); Index: source/ps/scripting/JSInterface_VFS.cpp =================================================================== --- source/ps/scripting/JSInterface_VFS.cpp +++ source/ps/scripting/JSInterface_VFS.cpp @@ -99,7 +99,7 @@ BuildDirEntListState state(cx); vfs::ForEachFile(g_VFS, path, BuildDirEntListCB, (uintptr_t)&state, filter, flags); - return OBJECT_TO_JSVAL(state.filename_array); + return JS::ObjectValue(*state.filename_array); } // Return true iff the file exits @@ -157,7 +157,7 @@ CVFSFile file; if (file.Load(g_VFS, filename) != PSRETURN_OK) - return JSVAL_NULL; + return JS::NullValue(); CStr contents = file.DecodeUTF8(); // assume it's UTF-8 Index: source/scriptinterface/ScriptConversions.h =================================================================== --- source/scriptinterface/ScriptConversions.h +++ source/scriptinterface/ScriptConversions.h @@ -52,8 +52,9 @@ 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) || JS_IsTypedArrayObject(obj))) FAIL("Argument must be an array"); u32 length; Index: source/scriptinterface/ScriptEngine.h =================================================================== --- source/scriptinterface/ScriptEngine.h +++ source/scriptinterface/ScriptEngine.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2016 Wildfire Games. +/* Copyright (C) 2018 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -32,17 +32,9 @@ class ScriptEngine : public Singleton { public: - ScriptEngine() - { - ENSURE(m_Runtimes.size() == 0 && "JS_Init must be called before any runtimes are created!"); - JS_Init(); - } - - ~ScriptEngine() - { - ENSURE(m_Runtimes.size() == 0 && "All runtimes must be destroyed before calling JS_ShutDown!"); - JS_ShutDown(); - } + ScriptEngine(); + + ~ScriptEngine(); void RegisterRuntime(const JSRuntime* rt) { m_Runtimes.push_back(rt); } void UnRegisterRuntime(const JSRuntime* rt) { m_Runtimes.remove(rt); } Index: source/scriptinterface/ScriptEngine.cpp =================================================================== --- /dev/null +++ source/scriptinterface/ScriptEngine.cpp @@ -0,0 +1,31 @@ +/* Copyright (C) 2018 Wildfire Games. + * This file is part of 0 A.D. + * + * 0 A.D. is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * 0 A.D. is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with 0 A.D. If not, see . + */ + +#include "ScriptEngine.h" +#include + +ScriptEngine::ScriptEngine() +{ + ENSURE(m_Runtimes.size() == 0 && "JS_Init must be called before any runtimes are created!"); + JS_Init(); +} + +ScriptEngine::~ScriptEngine() +{ + ENSURE(m_Runtimes.size() == 0 && "All runtimes must be destroyed before calling JS_ShutDown!"); + JS_ShutDown(); +} Index: source/scriptinterface/ScriptInterface.h =================================================================== --- source/scriptinterface/ScriptInterface.h +++ source/scriptinterface/ScriptInterface.h @@ -142,7 +142,7 @@ * to set an already-defined value will fail. */ template - bool SetGlobal(const char* name, const T& value, bool replace = false); + bool SetGlobal(const char* name, const T& value, bool replace = false, bool constant = true, bool enumerate = true); /** * Set the named property on the given object. @@ -362,7 +362,7 @@ bool CallFunction_(JS::HandleValue val, const char* name, JS::HandleValueArray argv, JS::MutableHandleValue ret) const; bool Eval_(const char* code, JS::MutableHandleValue ret) const; bool Eval_(const wchar_t* code, JS::MutableHandleValue ret) const; - bool SetGlobal_(const char* name, JS::HandleValue value, bool replace); + bool SetGlobal_(const char* name, JS::HandleValue value, bool replace, bool constant, bool enumerate); bool SetProperty_(JS::HandleValue obj, const char* name, JS::HandleValue value, bool readonly, bool enumerate) const; bool SetProperty_(JS::HandleValue obj, const wchar_t* name, JS::HandleValue value, bool readonly, bool enumerate) const; bool SetPropertyInt_(JS::HandleValue obj, int name, JS::HandleValue value, bool readonly, bool enumerate) const; @@ -488,12 +488,12 @@ } template -bool ScriptInterface::SetGlobal(const char* name, const T& value, bool replace) +bool ScriptInterface::SetGlobal(const char* name, const T& value, bool replace, bool constant, bool enumerate) { JSAutoRequest rq(GetContext()); JS::RootedValue val(GetContext()); AssignOrToJSVal(GetContext(), &val, value); - return SetGlobal_(name, val, replace); + return SetGlobal_(name, val, replace, constant, enumerate); } template Index: source/scriptinterface/ScriptInterface.cpp =================================================================== --- source/scriptinterface/ScriptInterface.cpp +++ source/scriptinterface/ScriptInterface.cpp @@ -86,7 +86,6 @@ void ErrorReporter(JSContext* cx, const char* message, JSErrorReport* report) { - std::stringstream msg; bool isWarning = JSREPORT_IS_WARNING(report->flags); msg << (isWarning ? "JavaScript warning: " : "JavaScript error: "); @@ -102,17 +101,20 @@ JS::RootedValue excn(cx); if (JS_GetPendingException(cx, &excn) && excn.isObject()) { - JS::RootedObject excnObj(cx, &excn.toObject()); - // TODO: this violates the docs ("The error reporter callback must not reenter the JSAPI.") + // NB: this violates the docs ("The error reporter callback must not reenter the JSAPI.") + // It's unclear how bad this really is. - // Hide the exception from EvaluateScript + // Hide the exception from Evaluate JSExceptionState* excnState = JS_SaveExceptionState(cx); JS_ClearPendingException(cx); JS::RootedValue rval(cx); - const char dumpStack[] = "this.stack.trimRight().replace(/^/mg, ' ')"; // indent each line + const char dumpStack[] = "function __stackTrace(a) { return a.stack.trimRight().replace(/^/mg, ' '); }"; // indent each line JS::CompileOptions opts(cx); - if (JS::Evaluate(cx, excnObj, opts.setFileAndLine("(eval)", 1), dumpStack, ARRAY_SIZE(dumpStack)-1, &rval)) + JS::Evaluate(cx, opts.setFileAndLine("(ErrorReporter)", 1), dumpStack, ARRAY_SIZE(dumpStack)-1, &rval); + + JS::RootedObject glob(cx, JS::CurrentGlobalOrNull(cx)); + if (JS_CallFunctionName(cx, glob, "__stackTrace", JS::HandleValueArray(excn), &rval)) { std::string stackTrace; if (ScriptInterface::FromJSVal(cx, rval, stackTrace)) @@ -366,7 +368,6 @@ JS::RuntimeOptionsRef(m_cx).setExtraWarnings(1) .setWerror(0) - .setVarObjFix(1) .setStrictMode(1); JS::CompartmentOptions opt; @@ -551,7 +552,7 @@ } JS::RootedObject global(m->m_cx, m->m_glob); - JS::RootedObject obj(m->m_cx, JS_InitClass(m->m_cx, global, JS::NullPtr(), + JS::RootedObject obj(m->m_cx, JS_InitClass(m->m_cx, global, nullptr, clasp, constructor, minArgs, // Constructor, min args ps, fs, // Properties, methods @@ -602,7 +603,7 @@ return JS::ObjectValue(*JS::CurrentGlobalOrNull(m->m_cx)); } -bool ScriptInterface::SetGlobal_(const char* name, JS::HandleValue value, bool replace) +bool ScriptInterface::SetGlobal_(const char* name, JS::HandleValue value, bool replace, bool constant, bool enumerate) { JSAutoRequest rq(m->m_cx); JS::RootedObject global(m->m_cx, m->m_glob); @@ -618,8 +619,13 @@ } } - bool ok = JS_DefineProperty(m->m_cx, global, name, value, JSPROP_ENUMERATE | JSPROP_READONLY - | JSPROP_PERMANENT); + uint attrs = 0; + if (constant) + attrs |= JSPROP_READONLY | JSPROP_PERMANENT; + if (enumerate) + attrs |= JSPROP_ENUMERATE; + + bool ok = JS_DefineProperty(m->m_cx, global, name, value, attrs); return ok; } @@ -759,8 +765,9 @@ 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, m->m_cx); + bool hasProps = JS_Enumerate(m->m_cx, obj, &props); + if (!hasProps) return false; for (size_t i = 0; i < props.length(); ++i) @@ -848,7 +855,6 @@ JS::CompileOptions options(m->m_cx); options.setFileAndLine(filenameStr.c_str(), lineNo); - options.setCompileAndGo(true); JS::RootedFunction func(m->m_cx); JS::AutoObjectVector emptyScopeChain(m->m_cx); @@ -857,7 +863,7 @@ 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) @@ -868,7 +874,6 @@ 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. @@ -878,14 +883,13 @@ 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()); @@ -913,7 +917,7 @@ 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); } @@ -927,23 +931,21 @@ 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 @@ -1024,7 +1026,7 @@ 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"); @@ -1052,7 +1054,7 @@ // 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); Index: source/scriptinterface/ScriptTypes.h =================================================================== --- source/scriptinterface/ScriptTypes.h +++ 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 @@ 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 \ Index: source/simulation2/components/CCmpAIManager.cpp =================================================================== --- source/simulation2/components/CCmpAIManager.cpp +++ source/simulation2/components/CCmpAIManager.cpp @@ -554,8 +554,9 @@ 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); } } @@ -583,8 +584,9 @@ 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); } } Index: source/simulation2/scripting/EngineScriptConversions.cpp =================================================================== --- source/simulation2/scripting/EngineScriptConversions.cpp +++ source/simulation2/scripting/EngineScriptConversions.cpp @@ -256,7 +256,8 @@ // 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 shared; + memcpy((void*)JS_GetUint8ArrayData(objArr, &shared, nogc), val.m_Data, nbytes); } JS::RootedValue data(cx, JS::ObjectValue(*objArr)); @@ -282,7 +283,8 @@ // 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 shared; + memcpy((void*)JS_GetUint16ArrayData(objArr, &shared, nogc), val.m_Data, nbytes); } JS::RootedValue data(cx, JS::ObjectValue(*objArr)); @@ -306,7 +308,8 @@ JSAutoRequest rq(cx); JS::RootedObject obj(cx, &v.toObject()); - if (!JS_IsArrayObject(cx, obj)) + bool realArray; + if (!JS_IsArrayObject(cx, obj, &realArray)) FAIL("Argument must be an array"); u32 numberOfNodes = 0; Index: source/simulation2/scripting/MessageTypeConversions.cpp =================================================================== --- source/simulation2/scripting/MessageTypeConversions.cpp +++ source/simulation2/scripting/MessageTypeConversions.cpp @@ -291,7 +291,7 @@ SET_MSG_PROPERTY(j0); SET_MSG_PROPERTY(i1); SET_MSG_PROPERTY(j1); - return OBJECT_TO_JSVAL(obj); + return JS::ObjectValue(*obj); } CMessage* CMessageTerrainChanged::FromJSVal(const ScriptInterface& scriptInterface, JS::HandleValue val) @@ -331,7 +331,7 @@ JS::Value CMessageWaterChanged::ToJSVal(const ScriptInterface& scriptInterface) const { TOJSVAL_SETUP(); - return OBJECT_TO_JSVAL(obj); + return JS::ObjectValue(*obj); } CMessage* CMessageWaterChanged::FromJSVal(const ScriptInterface& UNUSED(scriptInterface), JS::HandleValue UNUSED(val)) Index: source/simulation2/serialization/BinarySerializer.cpp =================================================================== --- source/simulation2/serialization/BinarySerializer.cpp +++ source/simulation2/serialization/BinarySerializer.cpp @@ -99,7 +99,8 @@ } // Arrays are special cases of Object - if (JS_IsArrayObject(cx, obj)) + bool realArray; + if (JS_IsArrayObject(cx, obj, &realArray)) { m_Serializer.NumberU8_Unbounded("type", SCRIPT_TYPE_ARRAY); // TODO: probably should have a more efficient storage format @@ -119,9 +120,10 @@ m_Serializer.NumberU32_Unbounded("byte offset", JS_GetTypedArrayByteOffset(obj)); m_Serializer.NumberU32_Unbounded("length", JS_GetTypedArrayLength(obj)); + bool isShared; // 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, &isShared))); HandleScriptVal(bufferVal); break; } @@ -136,7 +138,8 @@ 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 isShared; + m_Serializer.RawBytes("buffer data", (const u8*)JS_GetArrayBufferData(obj, &isShared, nogc), length); break; } else @@ -145,11 +148,8 @@ 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,9 @@ } // Find all properties (ordered by insertion time) - JS::AutoIdArray ida (cx, JS_Enumerate(cx, obj)); - if (!ida) + JS::Rooted ida(cx, cx); + bool hasProps = JS_Enumerate(cx, obj, &ida); + if (!hasProps) throw PSERROR_Serialize_ScriptError("JS_Enumerate failed"); m_Serializer.NumberU32_Unbounded("num props", (u32)ida.length()); Index: source/simulation2/serialization/StdDeserializer.cpp =================================================================== --- source/simulation2/serialization/StdDeserializer.cpp +++ source/simulation2/serialization/StdDeserializer.cpp @@ -167,12 +167,7 @@ if (!proto) throw PSERROR_Deserialize_ScriptError("Failed to find serializable prototype for object"); - JS::RootedObject parent(cx, JS_GetParent(proto)); - if (!proto || !parent) - throw PSERROR_Deserialize_ScriptError(); - - // TODO: Remove support for parent since this is dropped upstream SpiderMonkey - obj.set(JS_NewObjectWithGivenProto(cx, nullptr, proto, parent)); + obj.set(JS_NewObjectWithGivenProto(cx, nullptr, proto)); if (!obj) throw PSERROR_Deserialize_ScriptError("JS_NewObject failed"); @@ -218,7 +213,7 @@ { 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. @@ -229,7 +224,7 @@ { 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(); @@ -338,7 +333,7 @@ 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(); @@ -410,8 +405,8 @@ 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); @@ -415,7 +415,7 @@ 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();