summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Joseph Davis <davisp@apache.org>2011-09-08 05:05:19 +0000
committerPaul Joseph Davis <davisp@apache.org>2011-09-08 05:05:19 +0000
commit6cf2f036ece28c95988b8312c8532fac55a3c7a0 (patch)
tree1d01006b11b86c52e0155f60e65f805170a94312
parent71081311b2b11ed923869ce5bd11ce7b0fd1da2c (diff)
And the rest of the commit/
SVN != Git. Forgot to check svn status before committing. git-svn-id: https://svn.apache.org/repos/asf/couchdb/branches/1.1.x@1166526 13f79535-47bb-0310-9956-ffa450edef68
-rw-r--r--src/couchdb/priv/couch_js/sm170.c378
-rw-r--r--src/couchdb/priv/couch_js/sm180.c387
-rw-r--r--src/couchdb/priv/couch_js/sm185.c401
-rw-r--r--src/couchdb/priv/couch_js/util.c237
-rw-r--r--src/couchdb/priv/couch_js/util.h34
5 files changed, 1437 insertions, 0 deletions
diff --git a/src/couchdb/priv/couch_js/sm170.c b/src/couchdb/priv/couch_js/sm170.c
new file mode 100644
index 00000000..ebb6673f
--- /dev/null
+++ b/src/couchdb/priv/couch_js/sm170.c
@@ -0,0 +1,378 @@
+// 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>
+
+#include <jsapi.h>
+#include "http.h"
+#include "utf8.h"
+#include "util.h"
+
+
+#ifdef JS_THREADSAFE
+#define SETUP_REQUEST(cx) \
+ JS_SetContextThread(cx); \
+ JS_BeginRequest(cx);
+#define FINISH_REQUEST(cx) \
+ JS_EndRequest(cx); \
+ JS_ClearContextThread(cx);
+#else
+#define SETUP_REQUEST(cx)
+#define FINISH_REQUEST(cx)
+#endif
+
+
+static JSBool
+req_ctor(JSContext* cx, JSObject* obj, uintN argc, jsval* argv, jsval* rval)
+{
+ return http_ctor(cx, obj);
+}
+
+
+static void
+req_dtor(JSContext* cx, JSObject* obj)
+{
+ http_dtor(cx, obj);
+}
+
+
+static JSBool
+req_open(JSContext* cx, JSObject* obj, uintN argc, jsval* argv, jsval* rval)
+{
+ JSBool ret = JS_FALSE;
+
+ if(argc == 2) {
+ ret = http_open(cx, obj, argv[0], argv[1], JSVAL_FALSE);
+ } else if(argc == 3) {
+ ret = http_open(cx, obj, argv[0], argv[1], argv[2]);
+ } else {
+ JS_ReportError(cx, "Invalid call to CouchHTTP.open");
+ }
+
+ *rval = JSVAL_VOID;
+ return ret;
+}
+
+
+static JSBool
+req_set_hdr(JSContext* cx, JSObject* obj, uintN argc, jsval* argv, jsval* rval)
+{
+ JSBool ret = JS_FALSE;
+ if(argc == 2) {
+ ret = http_set_hdr(cx, obj, argv[0], argv[1]);
+ } else {
+ JS_ReportError(cx, "Invalid call to CouchHTTP.set_header");
+ }
+
+ *rval = JSVAL_VOID;
+ return ret;
+}
+
+
+static JSBool
+req_send(JSContext* cx, JSObject* obj, uintN argc, jsval* argv, jsval* rval)
+{
+ JSBool ret = JS_FALSE;
+ if(argc == 1) {
+ ret = http_send(cx, obj, argv[0]);
+ } else {
+ JS_ReportError(cx, "Invalid call to CouchHTTP.send");
+ }
+
+ *rval = JSVAL_VOID;
+ return ret;
+}
+
+
+static JSBool
+req_status(JSContext* cx, JSObject* obj, jsval idval, jsval* rval)
+{
+ int status = http_status(cx, obj);
+ if(status < 0)
+ return JS_FALSE;
+
+ if(INT_FITS_IN_JSVAL(status)) {
+ *rval = INT_TO_JSVAL(status);
+ return JS_TRUE;
+ } else {
+ JS_ReportError(cx, "Invalid HTTP status.");
+ return JS_FALSE;
+ }
+}
+
+
+static JSBool
+evalcx(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+{
+ JSString *str;
+ JSObject *sandbox;
+ JSContext *subcx;
+ const jschar *src;
+ size_t srclen;
+ JSBool ret = JS_FALSE;
+
+ sandbox = NULL;
+ if(!JS_ConvertArguments(cx, argc, argv, "S / o", &str, &sandbox)) {
+ return JS_FALSE;
+ }
+
+ subcx = JS_NewContext(JS_GetRuntime(cx), 8L * 1024L);
+ if(!subcx) {
+ JS_ReportOutOfMemory(cx);
+ return JS_FALSE;
+ }
+
+ SETUP_REQUEST(subcx);
+
+ src = JS_GetStringChars(str);
+ srclen = JS_GetStringLength(str);
+
+ if(!sandbox) {
+ sandbox = JS_NewObject(subcx, NULL, NULL, NULL);
+ if(!sandbox || !JS_InitStandardClasses(subcx, sandbox)) {
+ goto done;
+ }
+ }
+
+ if(srclen == 0) {
+ *rval = OBJECT_TO_JSVAL(sandbox);
+ } else {
+ JS_EvaluateUCScript(subcx, sandbox, src, srclen, NULL, 0, rval);
+ }
+
+ ret = JS_TRUE;
+
+done:
+ FINISH_REQUEST(subcx);
+ JS_DestroyContext(subcx);
+ return ret;
+}
+
+
+static JSBool
+gc(JSContext* cx, JSObject* obj, uintN argc, jsval* argv, jsval* rval)
+{
+ JS_GC(cx);
+ *rval = JSVAL_VOID;
+ return JS_TRUE;
+}
+
+
+static JSBool
+print(JSContext* cx, JSObject* obj, uintN argc, jsval* argv, jsval* rval)
+{
+ couch_print(cx, argc, argv);
+ *rval = JSVAL_VOID;
+ return JS_TRUE;
+}
+
+
+static JSBool
+quit(JSContext* cx, JSObject* obj, uintN argc, jsval* argv, jsval* rval)
+{
+ int exit_code = 0;
+ JS_ConvertArguments(cx, argc, argv, "/i", &exit_code);
+ exit(exit_code);
+}
+
+
+static JSBool
+readline(JSContext* cx, JSObject* obj, uintN argc, jsval* argv, jsval* rval)
+{
+ JSString* line;
+
+ /* GC Occasionally */
+ JS_MaybeGC(cx);
+
+ line = couch_readline(cx, stdin);
+ if(line == NULL) return JS_FALSE;
+
+ *rval = STRING_TO_JSVAL(line);
+ return JS_TRUE;
+}
+
+
+static JSBool
+seal(JSContext* cx, JSObject* obj, uintN argc, jsval* argv, jsval* rval)
+{
+ JSObject *target;
+ JSBool deep = JS_FALSE;
+
+ if(!JS_ConvertArguments(cx, argc, argv, "o/b", &target, &deep))
+ return JS_FALSE;
+
+ if(!target) {
+ *rval = JSVAL_VOID;
+ return JS_TRUE;
+ }
+
+ if(JS_SealObject(cx, obj, deep) != JS_TRUE)
+ return JS_FALSE;
+
+ *rval = JSVAL_VOID;
+ return JS_TRUE;
+}
+
+
+JSClass CouchHTTPClass = {
+ "CouchHTTP",
+ JSCLASS_HAS_PRIVATE
+ | JSCLASS_CONSTRUCT_PROTOTYPE
+ | JSCLASS_HAS_RESERVED_SLOTS(2),
+ JS_PropertyStub,
+ JS_PropertyStub,
+ JS_PropertyStub,
+ JS_PropertyStub,
+ JS_EnumerateStub,
+ JS_ResolveStub,
+ JS_ConvertStub,
+ req_dtor,
+ JSCLASS_NO_OPTIONAL_MEMBERS
+};
+
+
+JSPropertySpec CouchHTTPProperties[] = {
+ {"status", 0, JSPROP_READONLY, req_status, NULL},
+ {0, 0, 0, 0, 0}
+};
+
+
+JSFunctionSpec CouchHTTPFunctions[] = {
+ {"_open", req_open, 3, 0, 0},
+ {"_setRequestHeader", req_set_hdr, 2, 0, 0},
+ {"_send", req_send, 1, 0, 0},
+ {0, 0, 0, 0, 0}
+};
+
+
+static JSClass global_class = {
+ "GlobalClass",
+ JSCLASS_GLOBAL_FLAGS,
+ JS_PropertyStub,
+ JS_PropertyStub,
+ JS_PropertyStub,
+ JS_PropertyStub,
+ JS_EnumerateStub,
+ JS_ResolveStub,
+ JS_ConvertStub,
+ JS_FinalizeStub,
+ JSCLASS_NO_OPTIONAL_MEMBERS
+};
+
+
+static JSFunctionSpec global_functions[] = {
+ {"evalcx", evalcx, 0, 0, 0},
+ {"gc", gc, 0, 0, 0},
+ {"print", print, 0, 0, 0},
+ {"quit", quit, 0, 0, 0},
+ {"readline", readline, 0, 0, 0},
+ {"seal", seal, 0, 0, 0},
+ {0, 0, 0, 0, 0}
+};
+
+
+int
+main(int argc, const char* argv[])
+{
+ JSRuntime* rt = NULL;
+ JSContext* cx = NULL;
+ JSObject* global = NULL;
+ JSObject* klass = NULL;
+ JSScript* script;
+ JSString* scriptsrc;
+ jschar* schars;
+ size_t slen;
+ jsval sroot;
+ jsval result;
+
+ couch_args* args = couch_parse_args(argc, argv);
+
+ rt = JS_NewRuntime(64L * 1024L * 1024L);
+ if(rt == NULL)
+ return 1;
+
+ cx = JS_NewContext(rt, args->stack_size);
+ if(cx == NULL)
+ return 1;
+
+ JS_SetErrorReporter(cx, couch_error);
+ JS_ToggleOptions(cx, JSOPTION_XML);
+
+ SETUP_REQUEST(cx);
+
+ global = JS_NewObject(cx, &global_class, NULL, NULL);
+ if(global == NULL)
+ return 1;
+
+ JS_SetGlobalObject(cx, global);
+
+ if(!JS_InitStandardClasses(cx, global))
+ return 1;
+
+ if(couch_load_funcs(cx, global, global_functions) != JS_TRUE)
+ return 1;
+
+ if(args->use_http) {
+ http_check_enabled();
+
+ klass = JS_InitClass(
+ cx, global,
+ NULL,
+ &CouchHTTPClass, req_ctor,
+ 0,
+ CouchHTTPProperties, CouchHTTPFunctions,
+ NULL, NULL
+ );
+
+ if(!klass)
+ {
+ fprintf(stderr, "Failed to initialize CouchHTTP class.\n");
+ exit(2);
+ }
+ }
+
+ // Convert script source to jschars.
+ scriptsrc = dec_string(cx, args->script, strlen(args->script));
+ if(!scriptsrc)
+ return 1;
+
+ schars = JS_GetStringChars(scriptsrc);
+ slen = JS_GetStringLength(scriptsrc);
+
+ // Root it so GC doesn't collect it.
+ sroot = STRING_TO_JSVAL(scriptsrc);
+ if(JS_AddRoot(cx, &sroot) != JS_TRUE) {
+ fprintf(stderr, "Internal root error.\n");
+ return 1;
+ }
+
+ // Compile and run
+ script = JS_CompileUCScript(cx, global, schars, slen, args->script_name, 1);
+ if(!script) {
+ fprintf(stderr, "Failed to compile script.\n");
+ return 1;
+ }
+
+ JS_ExecuteScript(cx, global, script, &result);
+
+ // Warning message if we don't remove it.
+ JS_RemoveRoot(cx, &sroot);
+
+ FINISH_REQUEST(cx);
+ JS_DestroyContext(cx);
+ JS_DestroyRuntime(rt);
+ JS_ShutDown();
+
+ return 0;
+}
diff --git a/src/couchdb/priv/couch_js/sm180.c b/src/couchdb/priv/couch_js/sm180.c
new file mode 100644
index 00000000..dee16a78
--- /dev/null
+++ b/src/couchdb/priv/couch_js/sm180.c
@@ -0,0 +1,387 @@
+// 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>
+
+#include <jsapi.h>
+#include "http.h"
+#include "utf8.h"
+#include "util.h"
+
+
+#define SETUP_REQUEST(cx) \
+ JS_SetContextThread(cx); \
+ JS_BeginRequest(cx);
+#define FINISH_REQUEST(cx) \
+ JS_EndRequest(cx); \
+ JS_ClearContextThread(cx);
+
+
+static JSBool
+req_ctor(JSContext* cx, JSObject* obj, uintN argc, jsval* argv, jsval* rval)
+{
+ return http_ctor(cx, obj);
+}
+
+
+static void
+req_dtor(JSContext* cx, JSObject* obj)
+{
+ http_dtor(cx, obj);
+}
+
+
+static JSBool
+req_open(JSContext* cx, uintN argc, jsval* vp)
+{
+ JSObject* obj = JS_THIS_OBJECT(cx, vp);
+ jsval* argv = JS_ARGV(cx, vp);
+ JSBool ret = JS_FALSE;
+
+ if(argc == 2) {
+ ret = http_open(cx, obj, argv[0], argv[1], JSVAL_FALSE);
+ } else if(argc == 3) {
+ ret = http_open(cx, obj, argv[0], argv[1], argv[2]);
+ } else {
+ JS_ReportError(cx, "Invalid call to CouchHTTP.open");
+ }
+
+ JS_SET_RVAL(cx, vp, JSVAL_VOID);
+ return ret;
+}
+
+
+static JSBool
+req_set_hdr(JSContext* cx, uintN argc, jsval* vp)
+{
+ JSObject* obj = JS_THIS_OBJECT(cx, vp);
+ jsval* argv = JS_ARGV(cx, vp);
+ JSBool ret = JS_FALSE;
+
+ if(argc == 2) {
+ ret = http_set_hdr(cx, obj, argv[0], argv[1]);
+ } else {
+ JS_ReportError(cx, "Invalid call to CouchHTTP.set_header");
+ }
+
+ JS_SET_RVAL(cx, vp, JSVAL_VOID);
+ return ret;
+}
+
+
+static JSBool
+req_send(JSContext* cx, uintN argc, jsval* vp)
+{
+ JSObject* obj = JS_THIS_OBJECT(cx, vp);
+ jsval* argv = JS_ARGV(cx, vp);
+ JSBool ret = JS_FALSE;
+
+ if(argc == 1) {
+ ret = http_send(cx, obj, argv[0]);
+ } else {
+ JS_ReportError(cx, "Invalid call to CouchHTTP.send");
+ }
+
+ JS_SET_RVAL(cx, vp, JSVAL_VOID);
+ return ret;
+}
+
+
+static JSBool
+req_status(JSContext* cx, JSObject* obj, jsval idval, jsval* vp)
+{
+ int status = http_status(cx, obj);
+ if(status < 0)
+ return JS_FALSE;
+
+ if(INT_FITS_IN_JSVAL(status)) {
+ JS_SET_RVAL(cx, vp, INT_TO_JSVAL(status));
+ return JS_TRUE;
+ } else {
+ JS_ReportError(cx, "Invalid HTTP status.");
+ return JS_FALSE;
+ }
+}
+
+
+static JSBool
+evalcx(JSContext *cx, uintN argc, jsval* vp)
+{
+ jsval* argv = JS_ARGV(cx, vp);
+ JSString *str;
+ JSObject *sandbox;
+ JSContext *subcx;
+ const jschar *src;
+ size_t srclen;
+ jsval rval;
+ JSBool ret = JS_FALSE;
+
+ sandbox = NULL;
+ if(!JS_ConvertArguments(cx, argc, argv, "S / o", &str, &sandbox)) {
+ return JS_FALSE;
+ }
+
+ subcx = JS_NewContext(JS_GetRuntime(cx), 8L * 1024L);
+ if(!subcx) {
+ JS_ReportOutOfMemory(cx);
+ return JS_FALSE;
+ }
+
+ SETUP_REQUEST(subcx);
+
+ src = JS_GetStringChars(str);
+ srclen = JS_GetStringLength(str);
+
+ if(!sandbox) {
+ sandbox = JS_NewObject(subcx, NULL, NULL, NULL);
+ if(!sandbox || !JS_InitStandardClasses(subcx, sandbox)) {
+ goto done;
+ }
+ }
+
+ if(srclen == 0) {
+ JS_SET_RVAL(cx, vp, OBJECT_TO_JSVAL(sandbox));
+ } else {
+ JS_EvaluateUCScript(subcx, sandbox, src, srclen, NULL, 0, &rval);
+ JS_SET_RVAL(cx, vp, rval);
+ }
+
+ ret = JS_TRUE;
+
+done:
+ FINISH_REQUEST(subcx);
+ JS_DestroyContext(subcx);
+ return ret;
+}
+
+
+static JSBool
+gc(JSContext* cx, uintN argc, jsval* vp)
+{
+ JS_GC(cx);
+ JS_SET_RVAL(cx, vp, JSVAL_VOID);
+ return JS_TRUE;
+}
+
+
+static JSBool
+print(JSContext* cx, uintN argc, jsval* vp)
+{
+ jsval* argv = JS_ARGV(cx, vp);
+ couch_print(cx, argc, argv);
+ JS_SET_RVAL(cx, vp, JSVAL_VOID);
+ return JS_TRUE;
+}
+
+
+static JSBool
+quit(JSContext* cx, uintN argc, jsval* vp)
+{
+ jsval* argv = JS_ARGV(cx, vp);
+ int exit_code = 0;
+ JS_ConvertArguments(cx, argc, argv, "/i", &exit_code);
+ exit(exit_code);
+}
+
+
+static JSBool
+readline(JSContext* cx, uintN argc, jsval* vp)
+{
+ JSString* line;
+
+ /* GC Occasionally */
+ JS_MaybeGC(cx);
+
+ line = couch_readline(cx, stdin);
+ if(line == NULL) return JS_FALSE;
+
+ JS_SET_RVAL(cx, vp, STRING_TO_JSVAL(line));
+ return JS_TRUE;
+}
+
+
+static JSBool
+seal(JSContext* cx, uintN argc, jsval* vp)
+{
+ jsval* argv = JS_ARGV(cx, vp);
+ JSObject *target;
+ JSBool deep = JS_FALSE;
+
+ if(!JS_ConvertArguments(cx, argc, argv, "o/b", &target, &deep))
+ return JS_FALSE;
+
+ if(!target) {
+ JS_SET_RVAL(cx, vp, JSVAL_VOID);
+ return JS_TRUE;
+ }
+
+ if(JS_SealObject(cx, target, deep) != JS_TRUE)
+ return JS_FALSE;
+
+ JS_SET_RVAL(cx, vp, JSVAL_VOID);
+ return JS_TRUE;
+}
+
+
+JSClass CouchHTTPClass = {
+ "CouchHTTP",
+ JSCLASS_HAS_PRIVATE
+ | JSCLASS_CONSTRUCT_PROTOTYPE
+ | JSCLASS_HAS_RESERVED_SLOTS(2),
+ JS_PropertyStub,
+ JS_PropertyStub,
+ JS_PropertyStub,
+ JS_PropertyStub,
+ JS_EnumerateStub,
+ JS_ResolveStub,
+ JS_ConvertStub,
+ req_dtor,
+ JSCLASS_NO_OPTIONAL_MEMBERS
+};
+
+
+JSPropertySpec CouchHTTPProperties[] = {
+ {"status", 0, JSPROP_READONLY, req_status, NULL},
+ {0, 0, 0, 0, 0}
+};
+
+
+JSFunctionSpec CouchHTTPFunctions[] = {
+ JS_FS("_open", (JSNative) req_open, 3, JSFUN_FAST_NATIVE, 0),
+ JS_FS("_setRequestHeader", (JSNative) req_set_hdr, 2, JSFUN_FAST_NATIVE, 0),
+ JS_FS("_send", (JSNative) req_send, 1, JSFUN_FAST_NATIVE, 0),
+ JS_FS_END
+};
+
+
+static JSClass global_class = {
+ "GlobalClass",
+ JSCLASS_GLOBAL_FLAGS,
+ JS_PropertyStub,
+ JS_PropertyStub,
+ JS_PropertyStub,
+ JS_PropertyStub,
+ JS_EnumerateStub,
+ JS_ResolveStub,
+ JS_ConvertStub,
+ JS_FinalizeStub,
+ JSCLASS_NO_OPTIONAL_MEMBERS
+};
+
+
+static JSFunctionSpec global_functions[] = {
+ JS_FS("evalcx", (JSNative) evalcx, 0, JSFUN_FAST_NATIVE, 0),
+ JS_FS("gc", (JSNative) gc, 0, JSFUN_FAST_NATIVE, 0),
+ JS_FS("print", (JSNative) print, 0, JSFUN_FAST_NATIVE, 0),
+ JS_FS("quit", (JSNative) quit, 0, JSFUN_FAST_NATIVE, 0),
+ JS_FS("readline", (JSNative) readline, 0, JSFUN_FAST_NATIVE, 0),
+ JS_FS("seal", (JSNative) seal, 0, JSFUN_FAST_NATIVE, 0),
+ JS_FS_END
+};
+
+
+int
+main(int argc, const char* argv[])
+{
+ JSRuntime* rt = NULL;
+ JSContext* cx = NULL;
+ JSObject* global = NULL;
+ JSObject* klass = NULL;
+ JSScript* script;
+ JSString* scriptsrc;
+ jschar* schars;
+ size_t slen;
+ jsval sroot;
+ jsval result;
+
+ couch_args* args = couch_parse_args(argc, argv);
+
+ rt = JS_NewRuntime(64L * 1024L * 1024L);
+ if(rt == NULL)
+ return 1;
+
+ cx = JS_NewContext(rt, args->stack_size);
+ if(cx == NULL)
+ return 1;
+
+ JS_SetErrorReporter(cx, couch_error);
+ JS_ToggleOptions(cx, JSOPTION_XML);
+
+ SETUP_REQUEST(cx);
+
+ global = JS_NewObject(cx, &global_class, NULL, NULL);
+ if(global == NULL)
+ return 1;
+
+ JS_SetGlobalObject(cx, global);
+
+ if(!JS_InitStandardClasses(cx, global))
+ return 1;
+
+ if(couch_load_funcs(cx, global, global_functions) != JS_TRUE)
+ return 1;
+
+ if(args->use_http) {
+ http_check_enabled();
+
+ klass = JS_InitClass(
+ cx, global,
+ NULL,
+ &CouchHTTPClass, req_ctor,
+ 0,
+ CouchHTTPProperties, CouchHTTPFunctions,
+ NULL, NULL
+ );
+
+ if(!klass)
+ {
+ fprintf(stderr, "Failed to initialize CouchHTTP class.\n");
+ exit(2);
+ }
+ }
+
+ // Convert script source to jschars.
+ scriptsrc = dec_string(cx, args->script, strlen(args->script));
+ if(!scriptsrc)
+ return 1;
+
+ schars = JS_GetStringChars(scriptsrc);
+ slen = JS_GetStringLength(scriptsrc);
+
+ // Root it so GC doesn't collect it.
+ sroot = STRING_TO_JSVAL(scriptsrc);
+ if(JS_AddRoot(cx, &sroot) != JS_TRUE) {
+ fprintf(stderr, "Internal root error.\n");
+ return 1;
+ }
+
+ // Compile and run
+ script = JS_CompileUCScript(cx, global, schars, slen, args->script_name, 1);
+ if(!script) {
+ fprintf(stderr, "Failed to compile script.\n");
+ return 1;
+ }
+
+ JS_ExecuteScript(cx, global, script, &result);
+
+ // Warning message if we don't remove it.
+ JS_RemoveRoot(cx, &sroot);
+
+ FINISH_REQUEST(cx);
+ JS_DestroyContext(cx);
+ JS_DestroyRuntime(rt);
+ JS_ShutDown();
+
+ return 0;
+}
diff --git a/src/couchdb/priv/couch_js/sm185.c b/src/couchdb/priv/couch_js/sm185.c
new file mode 100644
index 00000000..701d5677
--- /dev/null
+++ b/src/couchdb/priv/couch_js/sm185.c
@@ -0,0 +1,401 @@
+// 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>
+
+#include <jsapi.h>
+#include "http.h"
+#include "utf8.h"
+#include "util.h"
+
+
+#define SETUP_REQUEST(cx) \
+ JS_SetContextThread(cx); \
+ JS_BeginRequest(cx);
+#define FINISH_REQUEST(cx) \
+ JS_EndRequest(cx); \
+ JS_ClearContextThread(cx);
+
+
+static JSClass global_class = {
+ "GlobalClass",
+ JSCLASS_GLOBAL_FLAGS,
+ JS_PropertyStub,
+ JS_PropertyStub,
+ JS_PropertyStub,
+ JS_StrictPropertyStub,
+ JS_EnumerateStub,
+ JS_ResolveStub,
+ JS_ConvertStub,
+ JS_FinalizeStub,
+ JSCLASS_NO_OPTIONAL_MEMBERS
+};
+
+
+static JSBool
+req_ctor(JSContext* cx, uintN argc, jsval* vp)
+{
+ JSBool ret;
+ JSObject* obj = JS_NewObjectForConstructor(cx, vp);
+ if(!obj) {
+ JS_ReportError(cx, "Failed to create CouchHTTP instance.\n");
+ return JS_FALSE;
+ }
+ ret = http_ctor(cx, obj);
+ JS_SET_RVAL(cx, vp, OBJECT_TO_JSVAL(obj));
+ return ret;
+}
+
+
+static void
+req_dtor(JSContext* cx, JSObject* obj)
+{
+ http_dtor(cx, obj);
+}
+
+
+static JSBool
+req_open(JSContext* cx, uintN argc, jsval* vp)
+{
+ JSObject* obj = JS_THIS_OBJECT(cx, vp);
+ jsval* argv = JS_ARGV(cx, vp);
+ JSBool ret = JS_FALSE;
+
+ if(argc == 2) {
+ ret = http_open(cx, obj, argv[0], argv[1], JSVAL_FALSE);
+ } else if(argc == 3) {
+ ret = http_open(cx, obj, argv[0], argv[1], argv[2]);
+ } else {
+ JS_ReportError(cx, "Invalid call to CouchHTTP.open");
+ }
+
+ JS_SET_RVAL(cx, vp, JSVAL_VOID);
+ return ret;
+}
+
+
+static JSBool
+req_set_hdr(JSContext* cx, uintN argc, jsval* vp)
+{
+ JSObject* obj = JS_THIS_OBJECT(cx, vp);
+ jsval* argv = JS_ARGV(cx, vp);
+ JSBool ret = JS_FALSE;
+
+ if(argc == 2) {
+ ret = http_set_hdr(cx, obj, argv[0], argv[1]);
+ } else {
+ JS_ReportError(cx, "Invalid call to CouchHTTP.set_header");
+ }
+
+ JS_SET_RVAL(cx, vp, JSVAL_VOID);
+ return ret;
+}
+
+
+static JSBool
+req_send(JSContext* cx, uintN argc, jsval* vp)
+{
+ JSObject* obj = JS_THIS_OBJECT(cx, vp);
+ jsval* argv = JS_ARGV(cx, vp);
+ JSBool ret = JS_FALSE;
+
+ if(argc == 1) {
+ ret = http_send(cx, obj, argv[0]);
+ } else {
+ JS_ReportError(cx, "Invalid call to CouchHTTP.send");
+ }
+
+ JS_SET_RVAL(cx, vp, JSVAL_VOID);
+ return ret;
+}
+
+
+static JSBool
+req_status(JSContext* cx, JSObject* obj, jsid pid, jsval* vp)
+{
+ int status = http_status(cx, obj);
+ if(status < 0)
+ return JS_FALSE;
+
+ JS_SET_RVAL(cx, vp, INT_TO_JSVAL(status));
+ return JS_TRUE;
+}
+
+
+static JSBool
+evalcx(JSContext *cx, uintN argc, jsval* vp)
+{
+ jsval* argv = JS_ARGV(cx, vp);
+ JSString* str;
+ JSObject* sandbox;
+ JSObject* global;
+ JSContext* subcx;
+ JSCrossCompartmentCall* call = NULL;
+ const jschar* src;
+ size_t srclen;
+ jsval rval;
+ JSBool ret = JS_FALSE;
+
+ sandbox = NULL;
+ if(!JS_ConvertArguments(cx, argc, argv, "S / o", &str, &sandbox)) {
+ return JS_FALSE;
+ }
+
+ subcx = JS_NewContext(JS_GetRuntime(cx), 8L * 1024L);
+ if(!subcx) {
+ JS_ReportOutOfMemory(cx);
+ return JS_FALSE;
+ }
+
+ SETUP_REQUEST(subcx);
+
+ src = JS_GetStringCharsAndLength(cx, str, &srclen);
+
+ // Re-use the compartment associated with the main context,
+ // rather than creating a new compartment */
+ global = JS_GetGlobalObject(cx);
+ if(global == NULL) goto done;
+ call = JS_EnterCrossCompartmentCall(subcx, global);
+
+ if(!sandbox) {
+ sandbox = JS_NewGlobalObject(subcx, &global_class);
+ if(!sandbox || !JS_InitStandardClasses(subcx, sandbox)) {
+ goto done;
+ }
+ }
+
+ if(srclen == 0) {
+ JS_SET_RVAL(cx, vp, OBJECT_TO_JSVAL(sandbox));
+ } else {
+ JS_EvaluateUCScript(subcx, sandbox, src, srclen, NULL, 0, &rval);
+ JS_SET_RVAL(cx, vp, rval);
+ }
+
+ ret = JS_TRUE;
+
+done:
+ JS_LeaveCrossCompartmentCall(call);
+ FINISH_REQUEST(subcx);
+ JS_DestroyContext(subcx);
+ return ret;
+}
+
+
+static JSBool
+gc(JSContext* cx, uintN argc, jsval* vp)
+{
+ JS_GC(cx);
+ JS_SET_RVAL(cx, vp, JSVAL_VOID);
+ return JS_TRUE;
+}
+
+
+static JSBool
+print(JSContext* cx, uintN argc, jsval* vp)
+{
+ jsval* argv = JS_ARGV(cx, vp);
+ couch_print(cx, argc, argv);
+ JS_SET_RVAL(cx, vp, JSVAL_VOID);
+ return JS_TRUE;
+}
+
+
+static JSBool
+quit(JSContext* cx, uintN argc, jsval* vp)
+{
+ jsval* argv = JS_ARGV(cx, vp);
+ int exit_code = 0;
+ JS_ConvertArguments(cx, argc, argv, "/i", &exit_code);
+ exit(exit_code);
+}
+
+
+static JSBool
+readline(JSContext* cx, uintN argc, jsval* vp)
+{
+ JSString* line;
+
+ /* GC Occasionally */
+ JS_MaybeGC(cx);
+
+ line = couch_readline(cx, stdin);
+ if(line == NULL) return JS_FALSE;
+
+ JS_SET_RVAL(cx, vp, STRING_TO_JSVAL(line));
+ return JS_TRUE;
+}
+
+
+static JSBool
+seal(JSContext* cx, uintN argc, jsval* vp)
+{
+ jsval* argv = JS_ARGV(cx, vp);
+ JSObject *target;
+ JSBool deep = JS_FALSE;
+ JSBool ret;
+
+ if(!JS_ConvertArguments(cx, argc, argv, "o/b", &target, &deep))
+ return JS_FALSE;
+
+ if(!target) {
+ JS_SET_RVAL(cx, vp, JSVAL_VOID);
+ return JS_TRUE;
+ }
+
+
+ ret = deep ? JS_DeepFreezeObject(cx, target) : JS_FreezeObject(cx, target);
+ JS_SET_RVAL(cx, vp, JSVAL_VOID);
+ return ret;
+}
+
+
+JSClass CouchHTTPClass = {
+ "CouchHTTP",
+ JSCLASS_HAS_PRIVATE
+ | JSCLASS_CONSTRUCT_PROTOTYPE
+ | JSCLASS_HAS_RESERVED_SLOTS(2),
+ JS_PropertyStub,
+ JS_PropertyStub,
+ JS_PropertyStub,
+ JS_StrictPropertyStub,
+ JS_EnumerateStub,
+ JS_ResolveStub,
+ JS_ConvertStub,
+ req_dtor,
+ JSCLASS_NO_OPTIONAL_MEMBERS
+};
+
+
+JSPropertySpec CouchHTTPProperties[] = {
+ {"status", 0, JSPROP_READONLY, req_status, NULL},
+ {0, 0, 0, 0, 0}
+};
+
+
+JSFunctionSpec CouchHTTPFunctions[] = {
+ JS_FS("_open", req_open, 3, 0),
+ JS_FS("_setRequestHeader", req_set_hdr, 2, 0),
+ JS_FS("_send", req_send, 1, 0),
+ JS_FS_END
+};
+
+
+static JSFunctionSpec global_functions[] = {
+ JS_FS("evalcx", evalcx, 0, 0),
+ JS_FS("gc", gc, 0, 0),
+ JS_FS("print", print, 0, 0),
+ JS_FS("quit", quit, 0, 0),
+ JS_FS("readline", readline, 0, 0),
+ JS_FS("seal", seal, 0, 0),
+ JS_FS_END
+};
+
+
+int
+main(int argc, const char* argv[])
+{
+ JSRuntime* rt = NULL;
+ JSContext* cx = NULL;
+ JSObject* global = NULL;
+ JSCrossCompartmentCall *call = NULL;
+ JSObject* klass = NULL;
+ JSObject* script;
+ JSString* scriptsrc;
+ const jschar* schars;
+ size_t slen;
+ jsval sroot;
+ jsval result;
+
+ couch_args* args = couch_parse_args(argc, argv);
+
+ rt = JS_NewRuntime(64L * 1024L * 1024L);
+ if(rt == NULL)
+ return 1;
+
+ cx = JS_NewContext(rt, args->stack_size);
+ if(cx == NULL)
+ return 1;
+
+ JS_SetErrorReporter(cx, couch_error);
+ JS_ToggleOptions(cx, JSOPTION_XML);
+
+ SETUP_REQUEST(cx);
+
+ global = JS_NewCompartmentAndGlobalObject(cx, &global_class, NULL);
+ if(global == NULL)
+ return 1;
+
+ call = JS_EnterCrossCompartmentCall(cx, global);
+
+ JS_SetGlobalObject(cx, global);
+
+ if(!JS_InitStandardClasses(cx, global))
+ return 1;
+
+ if(couch_load_funcs(cx, global, global_functions) != JS_TRUE)
+ return 1;
+
+ if(args->use_http) {
+ http_check_enabled();
+
+ klass = JS_InitClass(
+ cx, global,
+ NULL,
+ &CouchHTTPClass, req_ctor,
+ 0,
+ CouchHTTPProperties, CouchHTTPFunctions,
+ NULL, NULL
+ );
+
+ if(!klass)
+ {
+ fprintf(stderr, "Failed to initialize CouchHTTP class.\n");
+ exit(2);
+ }
+ }
+
+ // Convert script source to jschars.
+ scriptsrc = dec_string(cx, args->script, strlen(args->script));
+ if(!scriptsrc)
+ return 1;
+
+ schars = JS_GetStringCharsAndLength(cx, scriptsrc, &slen);
+
+ // Root it so GC doesn't collect it.
+ sroot = STRING_TO_JSVAL(scriptsrc);
+ if(JS_AddValueRoot(cx, &sroot) != JS_TRUE) {
+ fprintf(stderr, "Internal root error.\n");
+ return 1;
+ }
+
+ // Compile and run
+ script = JS_CompileUCScript(cx, global, schars, slen, args->script_name, 1);
+ if(!script) {
+ fprintf(stderr, "Failed to compile script.\n");
+ return 1;
+ }
+
+ JS_ExecuteScript(cx, global, script, &result);
+
+ // Warning message if we don't remove it.
+ JS_RemoveValueRoot(cx, &sroot);
+
+ JS_LeaveCrossCompartmentCall(call);
+ FINISH_REQUEST(cx);
+ JS_DestroyContext(cx);
+ JS_DestroyRuntime(rt);
+ JS_ShutDown();
+
+ return 0;
+}
diff --git a/src/couchdb/priv/couch_js/util.c b/src/couchdb/priv/couch_js/util.c
new file mode 100644
index 00000000..070d7172
--- /dev/null
+++ b/src/couchdb/priv/couch_js/util.c
@@ -0,0 +1,237 @@
+// 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 <jsapi.h>
+
+#include "util.h"
+#include "utf8.h"
+
+
+char*
+slurp_file(char* buf, const char* file)
+{
+ FILE* fp;
+ char fbuf[16384];
+ 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) {
+ buflen = nread;
+ buf = (char*) malloc(nread + 1);
+ if(buf == NULL) {
+ fprintf(stderr, "Out of memory.\n");
+ exit(3);
+ }
+ memcpy(buf, fbuf, buflen);
+ buf[buflen] = '\0';
+ } else {
+ buflen = strlen(buf);
+ tmp = (char*) malloc(buflen + nread + 1);
+ if(tmp == NULL) {
+ fprintf(stderr, "Out of memory.\n");
+ exit(3);
+ }
+ memcpy(tmp, buf, buflen);
+ memcpy(tmp+buflen, fbuf, nread);
+ tmp[buflen+nread] = '\0';
+ free(buf);
+ buf = tmp;
+ }
+ }
+ return buf;
+}
+
+couch_args*
+couch_parse_args(int argc, const char* argv[])
+{
+ couch_args* args;
+ int i = 1;
+
+ args = (couch_args*) malloc(sizeof(couch_args));
+ if(args == NULL)
+ return NULL;
+
+ memset(args, '\0', sizeof(couch_args));
+ args->stack_size = 8L * 1024L;
+
+ while(i < argc) {
+ if(strcmp("--http", argv[i]) == 0) {
+ args->use_http = 1;
+ } else if(strcmp("--stack-size", argv[i]) == 0) {
+ args->stack_size = atoi(argv[i+1]);
+ if(args->stack_size <= 0) {
+ fprintf(stderr, "Invalid stack size.\n");
+ exit(2);
+ }
+ } else {
+ args->script = slurp_file(args->script, argv[i]);
+ if(args->script_name == NULL) {
+ if(strcmp(argv[i], "-") == 0) {
+ args->script_name = "<stdin>";
+ } else {
+ args->script_name = argv[i];
+ }
+ } else {
+ args->script_name = "<multiple_files>";
+ }
+ }
+ i++;
+ }
+
+ if(args->script_name == NULL || args->script == NULL) {
+ fprintf(stderr, "No script provided.\n");
+ exit(3);
+ }
+
+ 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 readlen = 0;
+
+ bytes = 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.
+ byteslen *= 2;
+ tmp = JS_realloc(cx, bytes, byteslen);
+ if(!tmp) {
+ JS_free(cx, bytes);
+ return NULL;
+ }
+
+ bytes = tmp;
+ }
+
+ // Treat empty strings specially
+ if(used == 0) {
+ JS_free(cx, bytes);
+ return JSVAL_TO_STRING(JS_GetEmptyStringValue(cx));
+ }
+
+ // Shring the buffer to the actual data size
+ tmp = JS_realloc(cx, bytes, used);
+ if(!tmp) {
+ JS_free(cx, bytes);
+ return NULL;
+ }
+ bytes = tmp;
+ byteslen = used;
+
+ str = dec_string(cx, bytes, byteslen);
+ JS_free(cx, bytes);
+ return str;
+}
+
+
+JSObject*
+couch_readfile(JSContext* cx, FILE* fp)
+{
+ return NULL;
+}
+
+
+void
+couch_print(JSContext* cx, uintN argc, jsval* argv)
+{
+ char *bytes;
+ uintN i;
+
+ for(i = 0; i < argc; i++)
+ {
+ bytes = enc_string(cx, argv[i], NULL);
+ if(!bytes) return;
+
+ fprintf(stdout, "%s%s", i ? " " : "", bytes);
+ JS_free(cx, bytes);
+ }
+
+ fputc('\n', stdout);
+ fflush(stdout);
+}
+
+
+void
+couch_error(JSContext* cx, const char* mesg, JSErrorReport* report)
+{
+ if(!report || !JSREPORT_IS_WARNING(report->flags))
+ {
+ fprintf(stderr, "[couchjs] %s\n", mesg);
+ }
+}
+
+
+JSBool
+couch_load_funcs(JSContext* cx, JSObject* obj, JSFunctionSpec* funcs)
+{
+ JSFunctionSpec* f;
+ for(f = funcs; f->name != NULL; f++) {
+ if(!JS_DefineFunction(cx, obj, f->name, f->call, f->nargs, f->flags)) {
+ fprintf(stderr, "Failed to create function: %s\n", f->name);
+ return JS_FALSE;
+ }
+ }
+ return JS_TRUE;
+}
+
diff --git a/src/couchdb/priv/couch_js/util.h b/src/couchdb/priv/couch_js/util.h
new file mode 100644
index 00000000..6caebfa1
--- /dev/null
+++ b/src/couchdb/priv/couch_js/util.h
@@ -0,0 +1,34 @@
+// 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 use_http;
+ int stack_size;
+ const char* script_name;
+ char* script;
+} couch_args;
+
+void couch_usage();
+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);
+void couch_print(JSContext* cx, uintN argc, jsval* argv);
+void couch_error(JSContext* cx, const char* mesg, JSErrorReport* report);
+JSBool couch_load_funcs(JSContext* cx, JSObject* obj, JSFunctionSpec* funcs);
+
+
+#endif // Included util.h