Merge branch 'spidermonkey_version_nif' of github.com:apache/couchdb into spidermonkey_version_nif
diff --git a/rel/overlay/etc/vm.args b/rel/overlay/etc/vm.args
index cf75ff6..2c011e4 100644
--- a/rel/overlay/etc/vm.args
+++ b/rel/overlay/etc/vm.args
@@ -48,6 +48,15 @@
 -kernel error_logger silent
 -sasl sasl_error_logger false
 
+# This will toggle to true in Erlang 25+. However since we don't use global
+# any longer, and have our own auto-connection module, we can keep the
+# existing global behavior to avoid surprises. See
+# https://github.com/erlang/otp/issues/6470#issuecomment-1337421210 for more
+# information about possible increased coordination and messages being sent on
+# disconnections when this setting is enabled.
+#
+-kernel prevent_overlapping_partitions false
+
 # Increase the pool of dirty IO schedulers from 10 to 16
 # Dirty IO schedulers are used for file IO.
 +SDio 16
diff --git a/src/couch/priv/couch_spidermonkey/couch_spidermonkey.cpp b/src/couch/priv/couch_spidermonkey/couch_spidermonkey.cpp
index 98b28f3..5949910 100644
--- a/src/couch/priv/couch_spidermonkey/couch_spidermonkey.cpp
+++ b/src/couch/priv/couch_spidermonkey/couch_spidermonkey.cpp
@@ -12,33 +12,32 @@
  * the License.
  */
 
-#include <string>
+#include <string.h>
 #include <jsapi.h>
 #include "erl_nif.h"
 
-using namespace std;
-
 ERL_NIF_TERM
 get_spidermonkey_version(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
 {
-    const string JAVASCRIPT = "JavaScript-C";
-    int js_len = JAVASCRIPT.length();
+    const char *JAVASCRIPT = "JavaScript-C";
+    int js_len = strlen(JAVASCRIPT);
 
     // JS_GetImplementationVersion()
     // returns "JavaScript-CMAJOR.MINOR.PATCH"
-    const string FULLVERSION = JS_GetImplementationVersion();
+    const char *FULLVERSION = JS_GetImplementationVersion();
+    int fv_len = strlen(FULLVERSION);
 
-    string result;
-    size_t foundJSString = FULLVERSION.find(JAVASCRIPT);
-    if (foundJSString != string::npos) {
+    const char* foundJSString = strstr(FULLVERSION,JAVASCRIPT);
+    if (foundJSString != NULL) {
         //trim off "JavaScript-C",
-        result = FULLVERSION.substr(js_len);
+        char *buf = (char*) malloc((fv_len - js_len + 1) * sizeof(char));
+        strncpy(buf, &FULLVERSION[js_len], fv_len - js_len);
+        buf[fv_len - js_len] = '\0';
+        return enif_make_string(env, buf, ERL_NIF_LATIN1);
     } else {
         //something changed in JS_GetImplementationVersion(), return original
-        result = FULLVERSION;
+        return enif_make_string(env, FULLVERSION, ERL_NIF_LATIN1);
     }
-
-    return enif_make_string(env, result.c_str(), ERL_NIF_LATIN1);
 }
 
 static ErlNifFunc nif_functions[] = {
@@ -53,4 +52,4 @@
 
 #ifdef __cplusplus
 }
-#endif
\ No newline at end of file
+#endif
diff --git a/src/couch/src/couch_server.erl b/src/couch/src/couch_server.erl
index 271f782..55e64a4 100644
--- a/src/couch/src/couch_server.erl
+++ b/src/couch/src/couch_server.erl
@@ -416,10 +416,11 @@
                 true,
                 fun(Filename, AccIn) ->
                     NormFilename = couch_util:normpath(Filename),
-                    case NormFilename -- NormRoot of
-                        [$/ | RelativeFilename] -> ok;
-                        RelativeFilename -> ok
-                    end,
+                    RelativeFilename =
+                        case NormFilename -- NormRoot of
+                            [$/ | FName] -> FName;
+                            FName -> FName
+                        end,
                     Ext = filename:extension(RelativeFilename),
                     case Fun(?l2b(filename:rootname(RelativeFilename, Ext)), AccIn) of
                         {ok, NewAcc} -> NewAcc;
diff --git a/src/smoosh/test/smoosh_tests.erl b/src/smoosh/test/smoosh_tests.erl
index 9c0bcb0..cf8c9dc 100644
--- a/src/smoosh/test/smoosh_tests.erl
+++ b/src/smoosh/test/smoosh_tests.erl
@@ -37,6 +37,7 @@
 setup_all() ->
     meck:new(smoosh_server, [passthrough]),
     meck:new(smoosh_channel, [passthrough]),
+    meck:new(file, [unstick, passthrough]),
     meck:new(fabric, [passthrough]),
     meck:new(couch_emsort, [passthrough]),
     Ctx = test_util:start_couch([fabric]),
@@ -239,23 +240,24 @@
     setup_db_compactor_intercept(),
     {ok, _} = delete_doc(DbName, <<"doc1">>),
     ok = wait_to_enqueue(DbName),
-    ?debugHere,
     CompPid = wait_db_compactor_pid(),
-    ?debugHere,
     ChanPid = get_channel_pid("ratio_dbs"),
     config:set("smoosh", "persist", "true", false),
     meck:reset(smoosh_channel),
+    meck:reset(file),
     ChanPid ! checkpoint,
     % Wait for checkpoint process to exit
-    ?debugHere,
     ok = wait_normal_down(),
-    ?debugHere,
+    meck:wait(1, file, write_file, 3, 2000),
+    meck:wait(1, file, rename, 2, 2000),
     % Stop smoosh and then crash the compaction
     ok = application:stop(smoosh),
-    CompPid ! {raise, error, kapow},
-    % Smoosh should resume job and continue compacting
-    setup_db_compactor_intercept(),
-    meck:reset(smoosh_channel),
+    Ref = erlang:monitor(process, CompPid),
+    CompPid ! {raise, exit, kapow},
+    receive
+        {'DOWN', Ref, _, _, kapow} ->
+            ok
+    end,
     ok = application:start(smoosh),
     ?debugHere,
     CompPid2 = wait_db_compactor_pid(),