summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNick Vatamaniuc <vatamane@gmail.com>2022-12-11 00:48:01 -0500
committerNick Vatamaniuc <vatamane@gmail.com>2022-12-13 12:13:54 -0500
commitaa73f3bf2f22d08f04b66bf1a7c8545f0541f57e (patch)
tree1e3a07f5cd271fa2899fbb510634ec28e232efb4
parent99a8f666c8b9d1f5a6ebbb09c83e59e1916c0205 (diff)
downloadcouchdb-spidermonkey-102.tar.gz
try compiling for sm 102spidermonkey-102
-rw-r--r--src/couch/priv/couch_js/102/help.h79
-rw-r--r--src/couch/priv/couch_js/102/main.cpp343
-rw-r--r--src/couch/priv/couch_js/102/util.cpp348
-rw-r--r--src/couch/priv/couch_js/102/util.h41
-rw-r--r--src/couch/rebar.config.script17
5 files changed, 827 insertions, 1 deletions
diff --git a/src/couch/priv/couch_js/102/help.h b/src/couch/priv/couch_js/102/help.h
new file mode 100644
index 000000000..6a23172af
--- /dev/null
+++ b/src/couch/priv/couch_js/102/help.h
@@ -0,0 +1,79 @@
+// Licensed under the Apache License, Version 2.0 (the "License"); you may not
+// use this file except in compliance with the License. You may obtain a copy of
+// the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+// License for the specific language governing permissions and limitations under
+// the License.
+
+#ifndef COUCHJS_HELP_H
+#define COUCHJS_HELP_H
+
+#include "config.h"
+
+static const char VERSION_TEMPLATE[] =
+ "%s - %s (SpiderMonkey 86)\n"
+ "\n"
+ "Licensed under the Apache License, Version 2.0 (the \"License\"); you may "
+ "not use\n"
+ "this file except in compliance with the License. You may obtain a copy of"
+ "the\n"
+ "License at\n"
+ "\n"
+ " http://www.apache.org/licenses/LICENSE-2.0\n"
+ "\n"
+ "Unless required by applicable law or agreed to in writing, software "
+ "distributed\n"
+ "under the License is distributed on an \"AS IS\" BASIS, WITHOUT "
+ "WARRANTIES OR\n"
+ "CONDITIONS OF ANY KIND, either express or implied. See the License "
+ "for the\n"
+ "specific language governing permissions and limitations under the "
+ "License.\n";
+
+static const char USAGE_TEMPLATE[] =
+ "Usage: %s [FILE]\n"
+ "\n"
+ "The %s command runs the %s JavaScript interpreter.\n"
+ "\n"
+ "The exit status is 0 for success or 1 for failure.\n"
+ "\n"
+ "Options:\n"
+ "\n"
+ " -h display a short help message and exit\n"
+ " -V display version information and exit\n"
+ " -S SIZE specify that the runtime should allow at\n"
+ " most SIZE bytes of memory to be allocated\n"
+ " default is 64 MiB\n"
+ " --eval Enable runtime code evaluation (dangerous!)\n"
+ "\n"
+ "Report bugs at <%s>.\n";
+
+#define BASENAME COUCHJS_NAME
+
+#define couch_version(basename) \
+ fprintf( \
+ stdout, \
+ VERSION_TEMPLATE, \
+ basename, \
+ PACKAGE_STRING)
+
+#define DISPLAY_VERSION couch_version(BASENAME)
+
+
+#define couch_usage(basename) \
+ fprintf( \
+ stdout, \
+ USAGE_TEMPLATE, \
+ basename, \
+ basename, \
+ PACKAGE_NAME, \
+ PACKAGE_BUGREPORT)
+
+#define DISPLAY_USAGE couch_usage(BASENAME)
+
+#endif // Included help.h
diff --git a/src/couch/priv/couch_js/102/main.cpp b/src/couch/priv/couch_js/102/main.cpp
new file mode 100644
index 000000000..4d11c983d
--- /dev/null
+++ b/src/couch/priv/couch_js/102/main.cpp
@@ -0,0 +1,343 @@
+// Licensed under the Apache License, Version 2.0 (the "License"); you may not
+// use this file except in compliance with the License. You may obtain a copy of
+// the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+// License for the specific language governing permissions and limitations under
+// the License.
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#ifdef XP_WIN
+#define NOMINMAX
+#include <windows.h>
+#else
+#include <unistd.h>
+#endif
+
+#include <jsapi.h>
+#include <js/CompilationAndEvaluation.h>
+#include <js/Conversions.h>
+#include <js/Initialization.h>
+#include <js/SourceText.h>
+#include <js/StableStringChars.h>
+#include <js/Warnings.h>
+#include <js/Wrapper.h>
+
+#include "config.h"
+#include "util.h"
+
+static bool enableSharedMemory = true;
+static bool enableToSource = true;
+
+static JSClassOps global_ops = {
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ JS_GlobalObjectTraceHook
+};
+
+/* The class of the global object. */
+static JSClass global_class = {
+ "global",
+ JSCLASS_GLOBAL_FLAGS,
+ &global_ops
+};
+
+static JSObject*
+NewSandbox(JSContext* cx, bool lazy)
+{
+ JS::RealmOptions options;
+ options.creationOptions().setSharedMemoryAndAtomicsEnabled(enableSharedMemory);
+ options.creationOptions().setNewCompartmentAndZone();
+ // we need this in the query server error handling
+ options.creationOptions().setToSourceEnabled(enableToSource);
+ JS::RootedObject obj(cx, JS_NewGlobalObject(cx, &global_class, nullptr,
+ JS::DontFireOnNewGlobalHook, options));
+ if (!obj)
+ return nullptr;
+
+ {
+ JSAutoRealm ac(cx, obj);
+ if (!lazy && !JS::InitRealmStandardClasses(cx))
+ return nullptr;
+
+ JS::RootedValue value(cx, JS::BooleanValue(lazy));
+ if (!JS_DefineProperty(cx, obj, "lazy", value, JSPROP_PERMANENT | JSPROP_READONLY))
+ return nullptr;
+
+ JS_FireOnNewGlobalObject(cx, obj);
+ }
+
+ if (!JS_WrapObject(cx, &obj))
+ return nullptr;
+ return obj;
+}
+
+static bool
+evalcx(JSContext *cx, unsigned int argc, JS::Value* vp)
+{
+ JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+ bool ret = false;
+
+ JS::RootedString str(cx, args[0].toString());
+ if (!str)
+ return false;
+
+ JS::RootedObject sandbox(cx);
+ if (args.hasDefined(1)) {
+ sandbox = JS::ToObject(cx, args[1]);
+ if (!sandbox)
+ return false;
+ }
+
+ if (!sandbox) {
+ sandbox = NewSandbox(cx, false);
+ if (!sandbox)
+ return false;
+ }
+
+ JS::AutoStableStringChars strChars(cx);
+ if (!strChars.initTwoByte(cx, str))
+ return false;
+
+ mozilla::Range<const char16_t> chars = strChars.twoByteRange();
+ JS::SourceText<char16_t> srcBuf;
+ if (!srcBuf.init(cx, chars.begin().get(), chars.length(),
+ JS::SourceOwnership::Borrowed)) {
+ return false;
+ }
+
+ if(srcBuf.length() == 0) {
+ args.rval().setObject(*sandbox);
+ } else {
+ mozilla::Maybe<JSAutoRealm> ar;
+ unsigned flags;
+ JSObject* unwrapped = UncheckedUnwrap(sandbox, true, &flags);
+ if (flags & js::Wrapper::CROSS_COMPARTMENT) {
+ sandbox = unwrapped;
+ ar.emplace(cx, sandbox);
+ }
+
+ JS::CompileOptions opts(cx);
+ JS::RootedValue rval(cx);
+ opts.setFileAndLine("<unknown>", 1);
+
+ if (!JS::Evaluate(cx, opts, srcBuf, args.rval())) {
+ return false;
+ }
+ }
+ ret = true;
+ if (!JS_WrapValue(cx, args.rval()))
+ return false;
+
+ return ret;
+}
+
+
+static bool
+gc(JSContext* cx, unsigned int argc, JS::Value* vp)
+{
+ JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+ JS_GC(cx);
+ args.rval().setUndefined();
+ return true;
+}
+
+
+static bool
+print(JSContext* cx, unsigned int argc, JS::Value* vp)
+{
+ JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+
+ bool use_stderr = false;
+ if(argc > 1 && args[1].isTrue()) {
+ use_stderr = true;
+ }
+
+ if(!args[0].isString()) {
+ JS_ReportErrorUTF8(cx, "Unable to print non-string value.");
+ return false;
+ }
+
+ couch_print(cx, args[0], use_stderr);
+
+ args.rval().setUndefined();
+ return true;
+}
+
+
+static bool
+quit(JSContext* cx, unsigned int argc, JS::Value* vp)
+{
+ JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+
+ int exit_code = args[0].toInt32();;
+ JS_DestroyContext(cx);
+ JS_ShutDown();
+ exit(exit_code);
+}
+
+
+static bool
+readline(JSContext* cx, unsigned int argc, JS::Value* vp)
+{
+ JSString* line;
+ JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+
+ /* GC Occasionally */
+ JS_MaybeGC(cx);
+
+ line = couch_readline(cx, stdin);
+ if(line == NULL) return false;
+
+ // return with JSString* instead of JSValue in the past
+ args.rval().setString(line);
+ return true;
+}
+
+
+static bool
+seal(JSContext* cx, unsigned int argc, JS::Value* vp)
+{
+ JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+ JS::RootedObject target(cx);
+ target = JS::ToObject(cx, args[0]);
+ if (!target) {
+ args.rval().setUndefined();
+ return true;
+ }
+ bool deep = false;
+ deep = args[1].toBoolean();
+ bool ret = deep ? JS_DeepFreezeObject(cx, target) : JS_FreezeObject(cx, target);
+ args.rval().setUndefined();
+ return ret;
+}
+
+
+static JSFunctionSpec global_functions[] = {
+ JS_FN("evalcx", evalcx, 0, 0),
+ JS_FN("gc", gc, 0, 0),
+ JS_FN("print", print, 0, 0),
+ JS_FN("quit", quit, 0, 0),
+ JS_FN("readline", readline, 0, 0),
+ JS_FN("seal", seal, 0, 0),
+ JS_FS_END
+};
+
+
+static bool
+csp_allows(JSContext* cx, JS::RuntimeCode kind, JS::HandleString code)
+{
+ couch_args* args = static_cast<couch_args*>(JS_GetContextPrivate(cx));
+ if(args->eval) {
+ return true;
+ } else {
+ return false;
+ }
+}
+
+
+static JSSecurityCallbacks security_callbacks = {
+ csp_allows,
+ nullptr
+};
+
+int runWithContext(JSContext* cx, couch_args* args) {
+ JS_SetGlobalJitCompilerOption(cx, JSJITCOMPILER_BASELINE_ENABLE, 0);
+ JS_SetGlobalJitCompilerOption(cx, JSJITCOMPILER_ION_ENABLE, 0);
+
+ if (!JS::InitSelfHostedCode(cx))
+ return 1;
+
+ JS::SetWarningReporter(cx, couch_error);
+ JS::SetOutOfMemoryCallback(cx, couch_oom, NULL);
+ JS_SetContextPrivate(cx, args);
+ JS_SetSecurityCallbacks(cx, &security_callbacks);
+
+ JS::RealmOptions options;
+ // we need this in the query server error handling
+ options.creationOptions().setToSourceEnabled(enableToSource);
+ JS::RootedObject global(cx, JS_NewGlobalObject(cx, &global_class, nullptr,
+ JS::FireOnNewGlobalHook, options));
+ if (!global)
+ return 1;
+
+ JSAutoRealm ar(cx, global);
+
+ if(!JS::InitRealmStandardClasses(cx))
+ return 1;
+
+ if(couch_load_funcs(cx, global, global_functions) != true)
+ return 1;
+
+ for(int i = 0 ; args->scripts[i] ; i++) {
+ const char* filename = args->scripts[i];
+
+ // Compile and run
+ JS::CompileOptions options(cx);
+ JS::RootedScript script(cx);
+
+ script = JS::CompileUtf8Path(cx, options, filename);
+ if (!script) {
+ JS::RootedValue exc(cx);
+ if(!JS_GetPendingException(cx, &exc)) {
+ fprintf(stderr, "Failed to compile file: %s\n", filename);
+ } else {
+ JS::RootedObject exc_obj(cx, &exc.toObject());
+ JSErrorReport* report = JS_ErrorFromException(cx, exc_obj);
+ couch_error(cx, report);
+ }
+ return 1;
+ }
+
+ JS::RootedValue result(cx);
+ if(JS_ExecuteScript(cx, script, &result) != true) {
+ JS::RootedValue exc(cx);
+ if(!JS_GetPendingException(cx, &exc)) {
+ fprintf(stderr, "Failed to execute script.\n");
+ } else {
+ JS::RootedObject exc_obj(cx, &exc.toObject());
+ JSErrorReport* report = JS_ErrorFromException(cx, exc_obj);
+ couch_error(cx, report);
+ }
+ }
+
+ // Give the GC a chance to run.
+ JS_MaybeGC(cx);
+ }
+ return 0;
+}
+
+int
+main(int argc, const char* argv[])
+{
+ JSContext* cx = NULL;
+ int ret;
+
+ couch_args* args = couch_parse_args(argc, argv);
+
+ JS_Init();
+ cx = JS_NewContext(args->stack_size);
+ if(cx == NULL) {
+ JS_ShutDown();
+ return 1;
+ }
+ ret = runWithContext(cx, args);
+ JS_DestroyContext(cx);
+ JS_ShutDown();
+
+ return ret;
+}
diff --git a/src/couch/priv/couch_js/102/util.cpp b/src/couch/priv/couch_js/102/util.cpp
new file mode 100644
index 000000000..b61c76ad2
--- /dev/null
+++ b/src/couch/priv/couch_js/102/util.cpp
@@ -0,0 +1,348 @@
+// Licensed under the Apache License, Version 2.0 (the "License"); you may not
+// use this file except in compliance with the License. You may obtain a copy of
+// the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+// License for the specific language governing permissions and limitations under
+// the License.
+
+#include <stdlib.h>
+#include <string.h>
+
+#include <sstream>
+
+#include <jsapi.h>
+#include <jsfriendapi.h>
+#include <js/CharacterEncoding.h>
+#include <js/Conversions.h>
+#include <js/Initialization.h>
+#include <js/MemoryFunctions.h>
+#include <js/RegExp.h>
+
+#include "help.h"
+#include "util.h"
+
+std::string
+js_to_string(JSContext* cx, JS::HandleValue val)
+{
+ JS::AutoSaveExceptionState exc_state(cx);
+ JS::RootedString sval(cx);
+ sval = val.toString();
+
+ JS::UniqueChars chars(JS_EncodeStringToUTF8(cx, sval));
+ if(!chars) {
+ JS_ClearPendingException(cx);
+ return std::string();
+ }
+
+ return chars.get();
+}
+
+bool
+js_to_string(JSContext* cx, JS::HandleValue val, std::string& str)
+{
+ if(!val.isString()) {
+ return false;
+ }
+
+ if(JS_GetStringLength(val.toString()) == 0) {
+ str = "";
+ return true;
+ }
+
+ std::string conv = js_to_string(cx, val);
+ if(!conv.size()) {
+ return false;
+ }
+
+ str = conv;
+ return true;
+}
+
+JSString*
+string_to_js(JSContext* cx, const std::string& raw)
+{
+ JS::UTF8Chars utf8(raw.c_str(), raw.size());
+ JS::UniqueTwoByteChars utf16;
+ size_t len;
+
+ utf16.reset(JS::UTF8CharsToNewTwoByteCharsZ(cx, utf8, &len, js::MallocArena).get());
+ if(!utf16) {
+ return nullptr;
+ }
+
+ return JS_NewUCString(cx, std::move(utf16), len);
+}
+
+size_t
+couch_readfile(const char* file, char** outbuf_p)
+{
+ FILE* fp;
+ char fbuf[16384];
+ char *buf = NULL;
+ char* tmp;
+ size_t nread = 0;
+ size_t buflen = 0;
+
+ if(strcmp(file, "-") == 0) {
+ fp = stdin;
+ } else {
+ fp = fopen(file, "r");
+ if(fp == NULL) {
+ fprintf(stderr, "Failed to read file: %s\n", file);
+ exit(3);
+ }
+ }
+
+ while((nread = fread(fbuf, 1, 16384, fp)) > 0) {
+ if(buf == NULL) {
+ buf = new char[nread + 1];
+ if(buf == NULL) {
+ fprintf(stderr, "Out of memory.\n");
+ exit(3);
+ }
+ memcpy(buf, fbuf, nread);
+ } else {
+ tmp = new char[buflen + nread + 1];
+ if(tmp == NULL) {
+ fprintf(stderr, "Out of memory.\n");
+ exit(3);
+ }
+ memcpy(tmp, buf, buflen);
+ memcpy(tmp+buflen, fbuf, nread);
+ delete buf;
+ buf = tmp;
+ }
+ buflen += nread;
+ buf[buflen] = '\0';
+ }
+ *outbuf_p = buf;
+ return buflen ;
+}
+
+couch_args*
+couch_parse_args(int argc, const char* argv[])
+{
+ couch_args* args;
+ int i = 1;
+
+ args = new couch_args();
+ if(args == NULL)
+ return NULL;
+
+ args->eval = 0;
+ args->stack_size = 64L * 1024L * 1024L;
+ args->scripts = nullptr;
+
+ while(i < argc) {
+ if(strcmp("-h", argv[i]) == 0) {
+ DISPLAY_USAGE;
+ exit(0);
+ } else if(strcmp("-V", argv[i]) == 0) {
+ DISPLAY_VERSION;
+ exit(0);
+ } else if(strcmp("-S", argv[i]) == 0) {
+ args->stack_size = atoi(argv[++i]);
+ if(args->stack_size <= 0) {
+ fprintf(stderr, "Invalid stack size.\n");
+ exit(2);
+ }
+ } else if(strcmp("--eval", argv[i]) == 0) {
+ args->eval = 1;
+ } else if(strcmp("--", argv[i]) == 0) {
+ i++;
+ break;
+ } else {
+ break;
+ }
+ i++;
+ }
+
+ if(i >= argc) {
+ DISPLAY_USAGE;
+ exit(3);
+ }
+ args->scripts = argv + i;
+
+ return args;
+}
+
+
+int
+couch_fgets(char* buf, int size, FILE* fp)
+{
+ int n, i, c;
+
+ if(size <= 0) return -1;
+ n = size - 1;
+
+ for(i = 0; i < n && (c = getc(fp)) != EOF; i++) {
+ buf[i] = c;
+ if(c == '\n') {
+ i++;
+ break;
+ }
+ }
+
+ buf[i] = '\0';
+ return i;
+}
+
+
+JSString*
+couch_readline(JSContext* cx, FILE* fp)
+{
+ JSString* str;
+ char* bytes = NULL;
+ char* tmp = NULL;
+ size_t used = 0;
+ size_t byteslen = 256;
+ size_t oldbyteslen = 256;
+ size_t readlen = 0;
+
+ bytes = static_cast<char*>(JS_malloc(cx, byteslen));
+ if(bytes == NULL) return NULL;
+
+ while((readlen = couch_fgets(bytes+used, byteslen-used, fp)) > 0) {
+ used += readlen;
+
+ if(bytes[used-1] == '\n') {
+ bytes[used-1] = '\0';
+ break;
+ }
+
+ // Double our buffer and read more.
+ oldbyteslen = byteslen;
+ byteslen *= 2;
+ tmp = static_cast<char*>(JS_realloc(cx, bytes, oldbyteslen, byteslen));
+ if(!tmp) {
+ JS_free(cx, bytes);
+ return NULL;
+ }
+
+ bytes = tmp;
+ }
+
+ // Treat empty strings specially
+ if(used == 0) {
+ JS_free(cx, bytes);
+ return JS_NewStringCopyZ(cx, nullptr);
+ }
+
+ // Shrink the buffer to the actual data size
+ tmp = static_cast<char*>(JS_realloc(cx, bytes, byteslen, used));
+ if(!tmp) {
+ JS_free(cx, bytes);
+ return NULL;
+ }
+ bytes = tmp;
+ byteslen = used;
+
+ str = string_to_js(cx, std::string(tmp));
+ JS_free(cx, bytes);
+ return str;
+}
+
+
+void
+couch_print(JSContext* cx, JS::HandleValue obj, bool use_stderr)
+{
+ FILE *stream = stdout;
+
+ if (use_stderr) {
+ stream = stderr;
+ }
+ std::string val = js_to_string(cx, obj);
+ fprintf(stream, "%s\n", val.c_str());
+ fflush(stream);
+}
+
+
+void
+couch_error(JSContext* cx, JSErrorReport* report)
+{
+ if(!report) {
+ return;
+ }
+
+ if(report->isWarning()) {
+ return;
+ }
+
+ std::ostringstream msg;
+ msg << "error: " << report->message().c_str();
+
+ mozilla::Maybe<JSAutoRealm> ar;
+ JS::RootedValue exc(cx);
+ JS::RootedObject exc_obj(cx);
+ JS::RootedObject stack_obj(cx);
+ JS::RootedString stack_str(cx);
+ JS::RootedValue stack_val(cx);
+ JSPrincipals* principals = GetRealmPrincipals(js::GetContextRealm(cx));
+
+ if(!JS_GetPendingException(cx, &exc)) {
+ goto done;
+ }
+
+ // Clear the exception before an JS method calls or the result is
+ // infinite, recursive error report generation.
+ JS_ClearPendingException(cx);
+
+ exc_obj.set(exc.toObjectOrNull());
+ stack_obj.set(JS::ExceptionStackOrNull(exc_obj));
+
+ if(!stack_obj) {
+ // Compilation errors don't have a stack
+
+ msg << " at ";
+
+ if(report->filename) {
+ msg << report->filename;
+ } else {
+ msg << "<unknown>";
+ }
+
+ if(report->lineno) {
+ msg << ':' << report->lineno << ':' << report->column;
+ }
+
+ goto done;
+ }
+
+ if(!JS::BuildStackString(cx, principals, stack_obj, &stack_str, 2)) {
+ goto done;
+ }
+
+ stack_val.set(JS::StringValue(stack_str));
+ msg << std::endl << std::endl << js_to_string(cx, stack_val).c_str();
+
+done:
+ msg << std::endl;
+ fprintf(stderr, "%s", msg.str().c_str());
+}
+
+
+void
+couch_oom(JSContext* cx, void* data)
+{
+ fprintf(stderr, "out of memory\n");
+ _Exit(1);
+}
+
+
+bool
+couch_load_funcs(JSContext* cx, JS::HandleObject obj, JSFunctionSpec* funcs)
+{
+ JSFunctionSpec* f;
+ for(f = funcs; f->name; f++) {
+ if(!JS_DefineFunction(cx, obj, f->name.string(), f->call.op, f->nargs, f->flags)) {
+ fprintf(stderr, "Failed to create function: %s\n", f->name.string());
+ return false;
+ }
+ }
+ return true;
+}
diff --git a/src/couch/priv/couch_js/102/util.h b/src/couch/priv/couch_js/102/util.h
new file mode 100644
index 000000000..bd7843eb9
--- /dev/null
+++ b/src/couch/priv/couch_js/102/util.h
@@ -0,0 +1,41 @@
+// Licensed under the Apache License, Version 2.0 (the "License"); you may not
+// use this file except in compliance with the License. You may obtain a copy of
+// the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+// License for the specific language governing permissions and limitations under
+// the License.
+
+#ifndef COUCHJS_UTIL_H
+#define COUCHJS_UTIL_H
+
+#include <jsapi.h>
+
+typedef struct {
+ int eval;
+ int use_http;
+ int use_test_funs;
+ int stack_size;
+ const char** scripts;
+ const char* uri_file;
+ JSString* uri;
+} couch_args;
+
+std::string js_to_string(JSContext* cx, JS::HandleValue val);
+bool js_to_string(JSContext* cx, JS::HandleValue val, std::string& str);
+JSString* string_to_js(JSContext* cx, const std::string& s);
+
+couch_args* couch_parse_args(int argc, const char* argv[]);
+int couch_fgets(char* buf, int size, FILE* fp);
+JSString* couch_readline(JSContext* cx, FILE* fp);
+size_t couch_readfile(const char* file, char** outbuf_p);
+void couch_print(JSContext* cx, JS::HandleValue str, bool use_stderr);
+void couch_error(JSContext* cx, JSErrorReport* report);
+void couch_oom(JSContext* cx, void* data);
+bool couch_load_funcs(JSContext* cx, JS::HandleObject obj, JSFunctionSpec* funcs);
+
+#endif // Included util.h
diff --git a/src/couch/rebar.config.script b/src/couch/rebar.config.script
index f0b465135..db987c305 100644
--- a/src/couch/rebar.config.script
+++ b/src/couch/rebar.config.script
@@ -69,6 +69,8 @@ SMVsn = case lists:keyfind(spidermonkey_version, 1, CouchConfig) of
"86";
{_, "91"} ->
"91";
+ {_, "102"} ->
+ "102";
undefined ->
"1.8.5";
{_, Unsupported} ->
@@ -95,6 +97,8 @@ CouchJSConfig = case SMVsn of
"priv/couch_js/86/config.h";
"91" ->
"priv/couch_js/86/config.h";
+ "102" ->
+ "priv/couch_js/102/config.h";
_ ->
"priv/couch_js/" ++ SMVsn ++ "/config.h"
end.
@@ -160,10 +164,20 @@ end.
"$CFLAGS -DXP_UNIX -I/usr/include/mozjs-91 -I/usr/local/include/mozjs-91 -I/opt/homebrew/include/mozjs-91/ -std=c++17 -Wno-invalid-offsetof",
"$LDFLAGS -L/usr/local/lib -L /opt/homebrew/lib/ -std=c++17 -lmozjs-91 -lm"
};
+ {unix, _} when SMVsn == "102" ->
+ {
+ "$CFLAGS -DXP_UNIX -I/usr/include/mozjs-102 -I/usr/local/include/mozjs-102 -I/opt/homebrew/include/mozjs-102/ -std=c++17 -Wno-invalid-offsetof",
+ "$LDFLAGS -L/usr/local/lib -L /opt/homebrew/lib/ -std=c++17 -lmozjs-102 -lm"
+ };
{win32, _} when SMVsn == "91" ->
{
"/std:c++17 /DXP_WIN",
"$LDFLAGS mozjs-91.lib"
+ };
+ {win32, _} when SMVsn == "102" ->
+ {
+ "/std:c++17 /DXP_WIN",
+ "$LDFLAGS mozjs-102.lib"
}
end.
@@ -173,7 +187,8 @@ CouchJSSrc = case SMVsn of
"68" -> ["priv/couch_js/68/*.cpp"];
"78" -> ["priv/couch_js/86/*.cpp"];
"86" -> ["priv/couch_js/86/*.cpp"];
- "91" -> ["priv/couch_js/86/*.cpp"]
+ "91" -> ["priv/couch_js/86/*.cpp"];
+ "102" -> ["priv/couch_js/102/*.cpp"]
end.
CouchJSEnv = case SMVsn of