summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorRobert Newson <rnewson@apache.org>2011-10-06 10:39:21 +0100
committerRobert Newson <rnewson@apache.org>2011-10-06 10:39:21 +0100
commit5b558c81ed9709fb286a6821e9ae6d6478012c2c (patch)
treedf5689ac2ecfda77d4129a4c814dc21f68b93653 /src
parente6c0fc955ea2be0fd3c4e894fd0c7cc87202c5a5 (diff)
Remove SpiderMonkey 1.8.5 compatibility
This commit reverts 1.8.5 compatibility including the corresponding couchjs paren hack as this leads to significant breakage in existing functions.
Diffstat (limited to 'src')
-rw-r--r--src/couchdb/priv/Makefile.am11
-rw-r--r--src/couchdb/priv/couch_js/http.c318
-rw-r--r--src/couchdb/priv/couch_js/http.h10
-rw-r--r--src/couchdb/priv/couch_js/main.c327
-rw-r--r--src/couchdb/priv/couch_js/utf8.c9
5 files changed, 535 insertions, 140 deletions
diff --git a/src/couchdb/priv/Makefile.am b/src/couchdb/priv/Makefile.am
index b55b5905..ae1b3e38 100644
--- a/src/couchdb/priv/Makefile.am
+++ b/src/couchdb/priv/Makefile.am
@@ -20,10 +20,7 @@ endif
EXTRA_DIST = \
spawnkillable/couchspawnkillable.sh \
- stat_descriptions.cfg.in \
- couch_js/sm170.c \
- couch_js/sm180.c \
- couch_js/sm185.c
+ stat_descriptions.cfg.in
CLEANFILES = $(dist_man1_MANS) stat_descriptions.cfg
@@ -50,14 +47,12 @@ COUCHJS_SRCS = \
couch_js/http.h \
couch_js/main.c \
couch_js/utf8.c \
- couch_js/utf8.h \
- couch_js/util.h \
- couch_js/util.c
+ couch_js/utf8.h
locallibbin_PROGRAMS = couchjs
couchjs_SOURCES = $(COUCHJS_SRCS)
couchjs_LDFLAGS = $(CURL_LDFLAGS)
-couchjs_CFLAGS = -g -Wall -Werror -D_BSD_SOURCE $(CURL_CFLAGS)
+couchjs_CFLAGS = -D_BSD_SOURCE $(CURL_CFLAGS)
couchjs_LDADD = $(CURL_LDFLAGS) @JSLIB@
couchpriv_DATA = stat_descriptions.cfg
diff --git a/src/couchdb/priv/couch_js/http.c b/src/couchdb/priv/couch_js/http.c
index 77078e35..6c2a8a82 100644
--- a/src/couchdb/priv/couch_js/http.c
+++ b/src/couchdb/priv/couch_js/http.c
@@ -14,31 +14,19 @@
#include <stdlib.h>
#include <string.h>
#include <jsapi.h>
-#include "config.h"
-#include "utf8.h"
-
-
#include <curl/curl.h>
+#include "utf8.h"
-void
-http_check_enabled()
-{
- return;
-}
-
-
-// Map some of the string function names to things which exist on Windows
#ifdef XP_WIN
+// Map some of the string function names to things which exist on Windows
#define strcasecmp _strcmpi
#define strncasecmp _strnicmp
#define snprintf _snprintf
#endif
-
typedef struct curl_slist CurlHeaders;
-
typedef struct {
int method;
char* url;
@@ -46,10 +34,8 @@ typedef struct {
jsint last_status;
} HTTPData;
-
char* METHODS[] = {"GET", "HEAD", "POST", "PUT", "DELETE", "COPY", NULL};
-
#define GET 0
#define HEAD 1
#define POST 2
@@ -57,17 +43,14 @@ char* METHODS[] = {"GET", "HEAD", "POST", "PUT", "DELETE", "COPY", NULL};
#define DELETE 4
#define COPY 5
-
static JSBool
go(JSContext* cx, JSObject* obj, HTTPData* http, char* body, size_t blen);
-
static JSString*
str_from_binary(JSContext* cx, char* data, size_t length);
-
-JSBool
-http_ctor(JSContext* cx, JSObject* req)
+static JSBool
+constructor(JSContext* cx, JSObject* obj, uintN argc, jsval* argv, jsval* rval)
{
HTTPData* http = NULL;
JSBool ret = JS_FALSE;
@@ -84,12 +67,12 @@ http_ctor(JSContext* cx, JSObject* req)
http->req_headers = NULL;
http->last_status = -1;
- if(!JS_SetPrivate(cx, req, http))
+ if(!JS_SetPrivate(cx, obj, http))
{
JS_ReportError(cx, "Failed to set private CouchHTTP data.");
goto error;
}
-
+
ret = JS_TRUE;
goto success;
@@ -100,76 +83,90 @@ success:
return ret;
}
-
-void
-http_dtor(JSContext* cx, JSObject* obj)
+static void
+destructor(JSContext* cx, JSObject* obj)
{
HTTPData* http = (HTTPData*) JS_GetPrivate(cx, obj);
- if(http) {
+ if(!http)
+ {
+ fprintf(stderr, "Unable to destroy invalid CouchHTTP instance.\n");
+ }
+ else
+ {
if(http->url) free(http->url);
if(http->req_headers) curl_slist_free_all(http->req_headers);
free(http);
}
}
-
-JSBool
-http_open(JSContext* cx, JSObject* req, jsval mth, jsval url, jsval snc)
-{
- HTTPData* http = (HTTPData*) JS_GetPrivate(cx, req);
+static JSBool
+open(JSContext* cx, JSObject* obj, uintN argc, jsval* argv, jsval* rval)
+{
+ HTTPData* http = (HTTPData*) JS_GetPrivate(cx, obj);
char* method = NULL;
- int methid;
+ char* url = NULL;
JSBool ret = JS_FALSE;
+ int methid;
- if(!http) {
+ if(!http)
+ {
JS_ReportError(cx, "Invalid CouchHTTP instance.");
goto done;
}
- if(mth == JSVAL_VOID) {
+ if(argv[0] == JSVAL_VOID)
+ {
JS_ReportError(cx, "You must specify a method.");
goto done;
}
- method = enc_string(cx, mth, NULL);
- if(!method) {
+ method = enc_string(cx, argv[0], NULL);
+ if(!method)
+ {
JS_ReportError(cx, "Failed to encode method.");
goto done;
}
- for(methid = 0; METHODS[methid] != NULL; methid++) {
+ for(methid = 0; METHODS[methid] != NULL; methid++)
+ {
if(strcasecmp(METHODS[methid], method) == 0) break;
}
- if(methid > COPY) {
+ if(methid > COPY)
+ {
JS_ReportError(cx, "Invalid method specified.");
goto done;
}
http->method = methid;
- if(url == JSVAL_VOID) {
+ if(argv[1] == JSVAL_VOID)
+ {
JS_ReportError(cx, "You must specify a URL.");
goto done;
}
- if(http->url != NULL) {
+ if(http->url)
+ {
free(http->url);
http->url = NULL;
}
- http->url = enc_string(cx, url, NULL);
- if(http->url == NULL) {
+ http->url = enc_string(cx, argv[1], NULL);
+ if(!http->url)
+ {
JS_ReportError(cx, "Failed to encode URL.");
goto done;
}
- if(snc != JSVAL_FALSE) {
- JS_ReportError(cx, "Synchronous flag must be false.");
+ if(argv[2] != JSVAL_VOID && argv[2] != JSVAL_FALSE)
+ {
+ JS_ReportError(cx, "Synchronous flag must be false if specified.");
goto done;
}
- if(http->req_headers) {
+ if(http->req_headers)
+ {
curl_slist_free_all(http->req_headers);
http->req_headers = NULL;
}
@@ -184,42 +181,42 @@ done:
return ret;
}
-
-JSBool
-http_set_hdr(JSContext* cx, JSObject* req, jsval name, jsval val)
-{
- HTTPData* http = (HTTPData*) JS_GetPrivate(cx, req);
+static JSBool
+setheader(JSContext* cx, JSObject* obj, uintN argc, jsval* argv, jsval* rval)
+{
+ HTTPData* http = (HTTPData*) JS_GetPrivate(cx, obj);
char* keystr = NULL;
char* valstr = NULL;
char* hdrbuf = NULL;
size_t hdrlen = -1;
JSBool ret = JS_FALSE;
- if(!http) {
+ if(!http)
+ {
JS_ReportError(cx, "Invalid CouchHTTP instance.");
goto done;
}
- if(name == JSVAL_VOID)
+ if(argv[0] == JSVAL_VOID)
{
JS_ReportError(cx, "You must speciy a header name.");
goto done;
}
- keystr = enc_string(cx, name, NULL);
+ keystr = enc_string(cx, argv[0], NULL);
if(!keystr)
{
JS_ReportError(cx, "Failed to encode header name.");
goto done;
}
- if(val == JSVAL_VOID)
+ if(argv[1] == JSVAL_VOID)
{
JS_ReportError(cx, "You must specify a header value.");
goto done;
}
- valstr = enc_string(cx, val, NULL);
+ valstr = enc_string(cx, argv[1], NULL);
if(!valstr)
{
JS_ReportError(cx, "Failed to encode header value.");
@@ -228,7 +225,8 @@ http_set_hdr(JSContext* cx, JSObject* req, jsval name, jsval val)
hdrlen = strlen(keystr) + strlen(valstr) + 3;
hdrbuf = (char*) malloc(hdrlen * sizeof(char));
- if(!hdrbuf) {
+ if(!hdrbuf)
+ {
JS_ReportError(cx, "Failed to allocate header buffer.");
goto done;
}
@@ -242,50 +240,121 @@ done:
if(keystr) free(keystr);
if(valstr) free(valstr);
if(hdrbuf) free(hdrbuf);
+
return ret;
}
-JSBool
-http_send(JSContext* cx, JSObject* req, jsval body)
+static JSBool
+sendreq(JSContext* cx, JSObject* obj, uintN argc, jsval* argv, jsval* rval)
{
- HTTPData* http = (HTTPData*) JS_GetPrivate(cx, req);
- char* bodystr = NULL;
+ HTTPData* http = (HTTPData*) JS_GetPrivate(cx, obj);
+ char* body = NULL;
size_t bodylen = 0;
JSBool ret = JS_FALSE;
- if(!http) {
+ if(!http)
+ {
JS_ReportError(cx, "Invalid CouchHTTP instance.");
goto done;
}
- if(body != JSVAL_VOID && body != JS_GetEmptyStringValue(cx)) {
- bodystr = enc_string(cx, body, &bodylen);
- if(!bodystr) {
+ if(argv[0] != JSVAL_VOID && argv[0] != JS_GetEmptyStringValue(cx))
+ {
+ body = enc_string(cx, argv[0], &bodylen);
+ if(!body)
+ {
JS_ReportError(cx, "Failed to encode body.");
goto done;
}
}
- ret = go(cx, req, http, bodystr, bodylen);
+ ret = go(cx, obj, http, body, bodylen);
done:
- if(bodystr) free(bodystr);
+ if(body) free(body);
return ret;
}
-int
-http_status(JSContext* cx, JSObject* req)
+static JSBool
+status(JSContext* cx, JSObject* obj, jsval idval, jsval* vp)
{
- HTTPData* http = (HTTPData*) JS_GetPrivate(cx, req);
+ HTTPData* http = (HTTPData*) JS_GetPrivate(cx, obj);
- if(!http) {
+ if(!http)
+ {
JS_ReportError(cx, "Invalid CouchHTTP instance.");
return JS_FALSE;
}
+
+ if(INT_FITS_IN_JSVAL(http->last_status))
+ {
+ *vp = INT_TO_JSVAL(http->last_status);
+ return JS_TRUE;
+ }
+ else
+ {
+ JS_ReportError(cx, "INTERNAL: Invalid last_status");
+ return JS_FALSE;
+ }
+}
+
+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,
+ destructor,
+ JSCLASS_NO_OPTIONAL_MEMBERS
+};
+
+JSPropertySpec CouchHTTPProperties[] = {
+ {"status", 0, JSPROP_READONLY, status, NULL},
+ {0, 0, 0, 0, 0}
+};
+
+JSFunctionSpec CouchHTTPFunctions[] = {
+ {"_open", open, 3, 0, 0},
+ {"_setRequestHeader", setheader, 2, 0, 0},
+ {"_send", sendreq, 1, 0, 0},
+ {0, 0, 0, 0, 0}
+};
+
+JSObject*
+install_http(JSContext* cx, JSObject* glbl)
+{
+ JSObject* klass = NULL;
+ HTTPData* http = NULL;
- return http->last_status;
+ klass = JS_InitClass(
+ cx,
+ glbl,
+ NULL,
+ &CouchHTTPClass,
+ constructor,
+ 0,
+ CouchHTTPProperties,
+ CouchHTTPFunctions,
+ NULL,
+ NULL
+ );
+
+ if(!klass)
+ {
+ fprintf(stderr, "Failed to initialize CouchHTTP class.\n");
+ return NULL;
+ }
+
+ return klass;
}
+
// Curl Helpers
typedef struct {
@@ -295,7 +364,6 @@ typedef struct {
char* sendbuf;
size_t sendlen;
size_t sent;
- int sent_once;
char* recvbuf;
size_t recvlen;
size_t read;
@@ -327,13 +395,13 @@ go(JSContext* cx, JSObject* obj, HTTPData* http, char* body, size_t bodylen)
state.sendbuf = body;
state.sendlen = bodylen;
state.sent = 0;
- state.sent_once = 0;
state.recvbuf = NULL;
state.recvlen = 0;
state.read = 0;
- if(HTTP_HANDLE == NULL) {
+ if(HTTP_HANDLE == NULL)
+ {
HTTP_HANDLE = curl_easy_init();
curl_easy_setopt(HTTP_HANDLE, CURLOPT_READFUNCTION, send_body);
curl_easy_setopt(HTTP_HANDLE, CURLOPT_SEEKFUNCTION,
@@ -348,12 +416,14 @@ go(JSContext* cx, JSObject* obj, HTTPData* http, char* body, size_t bodylen)
"CouchHTTP Client - Relax");
}
- if(!HTTP_HANDLE) {
+ if(!HTTP_HANDLE)
+ {
JS_ReportError(cx, "Failed to initialize cURL handle.");
goto done;
}
- if(http->method < 0 || http->method > COPY) {
+ if(http->method < 0 || http->method > COPY)
+ {
JS_ReportError(cx, "INTERNAL: Unknown method.");
goto done;
}
@@ -363,21 +433,27 @@ go(JSContext* cx, JSObject* obj, HTTPData* http, char* body, size_t bodylen)
curl_easy_setopt(HTTP_HANDLE, CURLOPT_FOLLOWLOCATION, 1);
curl_easy_setopt(HTTP_HANDLE, CURLOPT_UPLOAD, 0);
- if(http->method == HEAD) {
+ if(http->method == HEAD)
+ {
curl_easy_setopt(HTTP_HANDLE, CURLOPT_NOBODY, 1);
curl_easy_setopt(HTTP_HANDLE, CURLOPT_FOLLOWLOCATION, 0);
- } else if(http->method == POST || http->method == PUT) {
+ }
+ else if(http->method == POST || http->method == PUT)
+ {
curl_easy_setopt(HTTP_HANDLE, CURLOPT_UPLOAD, 1);
curl_easy_setopt(HTTP_HANDLE, CURLOPT_FOLLOWLOCATION, 0);
}
- if(body && bodylen) {
+ if(body && bodylen)
+ {
curl_easy_setopt(HTTP_HANDLE, CURLOPT_INFILESIZE, bodylen);
- } else {
+ }
+ else
+ {
curl_easy_setopt(HTTP_HANDLE, CURLOPT_INFILESIZE, 0);
}
- // curl_easy_setopt(HTTP_HANDLE, CURLOPT_VERBOSE, 1);
+ //curl_easy_setopt(HTTP_HANDLE, CURLOPT_VERBOSE, 1);
curl_easy_setopt(HTTP_HANDLE, CURLOPT_URL, http->url);
curl_easy_setopt(HTTP_HANDLE, CURLOPT_HTTPHEADER, http->req_headers);
@@ -386,32 +462,39 @@ go(JSContext* cx, JSObject* obj, HTTPData* http, char* body, size_t bodylen)
curl_easy_setopt(HTTP_HANDLE, CURLOPT_WRITEHEADER, &state);
curl_easy_setopt(HTTP_HANDLE, CURLOPT_WRITEDATA, &state);
- if(curl_easy_perform(HTTP_HANDLE) != 0) {
+ if(curl_easy_perform(HTTP_HANDLE) != 0)
+ {
JS_ReportError(cx, "Failed to execute HTTP request: %s", ERRBUF);
goto done;
}
- if(!state.resp_headers) {
+ if(!state.resp_headers)
+ {
JS_ReportError(cx, "Failed to recieve HTTP headers.");
goto done;
}
tmp = OBJECT_TO_JSVAL(state.resp_headers);
if(!JS_DefineProperty(
- cx, obj,
+ cx,
+ obj,
"_headers",
tmp,
- NULL, NULL,
+ NULL,
+ NULL,
JSPROP_READONLY
- )) {
+ ))
+ {
JS_ReportError(cx, "INTERNAL: Failed to set response headers.");
goto done;
}
- if(state.recvbuf) {
+ if(state.recvbuf) // Is good enough?
+ {
state.recvbuf[state.read] = '\0';
jsbody = dec_string(cx, state.recvbuf, state.read+1);
- if(!jsbody) {
+ if(!jsbody)
+ {
// If we can't decode the body as UTF-8 we forcefully
// convert it to a string by just forcing each byte
// to a jschar.
@@ -424,17 +507,22 @@ go(JSContext* cx, JSObject* obj, HTTPData* http, char* body, size_t bodylen)
}
}
tmp = STRING_TO_JSVAL(jsbody);
- } else {
+ }
+ else
+ {
tmp = JS_GetEmptyStringValue(cx);
}
if(!JS_DefineProperty(
- cx, obj,
+ cx,
+ obj,
"responseText",
tmp,
- NULL, NULL,
+ NULL,
+ NULL,
JSPROP_READONLY
- )) {
+ ))
+ {
JS_ReportError(cx, "INTERNAL: Failed to set responseText.");
goto done;
}
@@ -452,20 +540,15 @@ send_body(void *ptr, size_t size, size_t nmem, void *data)
CurlState* state = (CurlState*) data;
size_t length = size * nmem;
size_t towrite = state->sendlen - state->sent;
-
- // Assume this is cURL trying to resend a request that
- // failed.
- if(towrite == 0 && state->sent_once == 0) {
- state->sent_once = 1;
+ if(towrite == 0)
+ {
return 0;
- } else if(towrite == 0) {
- state->sent = 0;
- state->sent_once = 0;
- towrite = state->sendlen;
}
if(length < towrite) towrite = length;
+ //fprintf(stderr, "%lu %lu %lu %lu\n", state->bodyused, state->bodyread, length, towrite);
+
memcpy(ptr, state->sendbuf + state->sent, towrite);
state->sent += towrite;
@@ -489,12 +572,15 @@ recv_header(void *ptr, size_t size, size_t nmem, void *data)
char code[4];
char* header = (char*) ptr;
size_t length = size * nmem;
+ size_t index = 0;
JSString* hdr = NULL;
jsuint hdrlen;
jsval hdrval;
- if(length > 7 && strncasecmp(header, "HTTP/1.", 7) == 0) {
- if(length < 12) {
+ if(length > 7 && strncasecmp(header, "HTTP/1.", 7) == 0)
+ {
+ if(length < 12)
+ {
return CURLE_WRITE_ERROR;
}
@@ -503,7 +589,8 @@ recv_header(void *ptr, size_t size, size_t nmem, void *data)
state->http->last_status = atoi(code);
state->resp_headers = JS_NewArrayObject(state->cx, 0, NULL);
- if(!state->resp_headers) {
+ if(!state->resp_headers)
+ {
return CURLE_WRITE_ERROR;
}
@@ -511,22 +598,26 @@ recv_header(void *ptr, size_t size, size_t nmem, void *data)
}
// We get a notice at the \r\n\r\n after headers.
- if(length <= 2) {
+ if(length <= 2)
+ {
return length;
}
// Append the new header to our array.
hdr = dec_string(state->cx, header, length);
- if(!hdr) {
+ if(!hdr)
+ {
return CURLE_WRITE_ERROR;
}
- if(!JS_GetArrayLength(state->cx, state->resp_headers, &hdrlen)) {
+ if(!JS_GetArrayLength(state->cx, state->resp_headers, &hdrlen))
+ {
return CURLE_WRITE_ERROR;
}
hdrval = STRING_TO_JSVAL(hdr);
- if(!JS_SetElement(state->cx, state->resp_headers, hdrlen, &hdrval)) {
+ if(!JS_SetElement(state->cx, state->resp_headers, hdrlen, &hdrval))
+ {
return CURLE_WRITE_ERROR;
}
@@ -540,13 +631,15 @@ recv_body(void *ptr, size_t size, size_t nmem, void *data)
size_t length = size * nmem;
char* tmp = NULL;
- if(!state->recvbuf) {
+ if(!state->recvbuf)
+ {
state->recvlen = 4096;
state->read = 0;
state->recvbuf = JS_malloc(state->cx, state->recvlen);
}
- if(!state->recvbuf) {
+ if(!state->recvbuf)
+ {
return CURLE_WRITE_ERROR;
}
@@ -570,7 +663,8 @@ str_from_binary(JSContext* cx, char* data, size_t length)
if(!conv) return NULL;
- for(i = 0; i < length; i++) {
+ for(i = 0; i < length; i++)
+ {
conv[i] = (jschar) data[i];
}
diff --git a/src/couchdb/priv/couch_js/http.h b/src/couchdb/priv/couch_js/http.h
index 373d1e48..b5f8c70f 100644
--- a/src/couchdb/priv/couch_js/http.h
+++ b/src/couchdb/priv/couch_js/http.h
@@ -13,12 +13,6 @@
#ifndef COUCH_JS_HTTP_H
#define COUCH_JS_HTTP_H
-void http_check_enabled();
-JSBool http_ctor(JSContext* cx, JSObject* req);
-void http_dtor(JSContext* cx, JSObject* req);
-JSBool http_open(JSContext* cx, JSObject* req, jsval mth, jsval url, jsval snc);
-JSBool http_set_hdr(JSContext* cx, JSObject* req, jsval name, jsval val);
-JSBool http_send(JSContext* cx, JSObject* req, jsval body);
-int http_status(JSContext* cx, JSObject* req);
+JSObject* install_http(JSContext* cx, JSObject* global);
-#endif
+#endif \ No newline at end of file
diff --git a/src/couchdb/priv/couch_js/main.c b/src/couchdb/priv/couch_js/main.c
index 209bb023..376aa15b 100644
--- a/src/couchdb/priv/couch_js/main.c
+++ b/src/couchdb/priv/couch_js/main.c
@@ -10,12 +10,329 @@
// 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 "config.h"
-#if defined(SM185)
-#include "sm185.c"
-#elif defined(SM180)
-#include "sm180.c"
+#include "utf8.h"
+#include "http.h"
+
+int gExitCode = 0;
+
+#ifdef JS_THREADSAFE
+#define SETUP_REQUEST(cx) \
+ JS_SetContextThread(cx); \
+ JS_BeginRequest(cx);
+#define FINISH_REQUEST(cx) \
+ JS_EndRequest(cx); \
+ JS_ClearContextThread(cx);
#else
-#include "sm170.c"
+#define SETUP_REQUEST(cx)
+#define FINISH_REQUEST(cx)
#endif
+
+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;
+ jsval v;
+
+ 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);
+ return JS_TRUE;
+}
+
+static JSBool
+print(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+{
+ uintN i;
+ char *bytes;
+
+ for(i = 0; i < argc; i++)
+ {
+ bytes = enc_string(cx, argv[i], NULL);
+ if(!bytes) return JS_FALSE;
+
+ fprintf(stdout, "%s%s", i ? " " : "", bytes);
+ JS_free(cx, bytes);
+ }
+
+ fputc('\n', stdout);
+ fflush(stdout);
+ return JS_TRUE;
+}
+
+static JSBool
+quit(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+{
+ JS_ConvertArguments(cx, argc, argv, "/ i", &gExitCode);
+ return JS_FALSE;
+}
+
+static char*
+readfp(JSContext* cx, FILE* fp, size_t* buflen)
+{
+ 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 = js_fgets(bytes+used, byteslen-used, stdin)) > 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;
+ }
+
+ *buflen = used;
+ return bytes;
+}
+
+static JSBool
+readline(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) {
+ jschar *chars;
+ JSString *str;
+ char* bytes;
+ char* tmp;
+ size_t byteslen;
+
+ /* GC Occasionally */
+ JS_MaybeGC(cx);
+
+ bytes = readfp(cx, stdin, &byteslen);
+ if(!bytes) return JS_FALSE;
+
+ /* Treat the empty string specially */
+ if(byteslen == 0)
+ {
+ *rval = JS_GetEmptyStringValue(cx);
+ JS_free(cx, bytes);
+ return JS_TRUE;
+ }
+
+ /* Shrink the buffer to the real size */
+ tmp = JS_realloc(cx, bytes, byteslen);
+ if(!tmp)
+ {
+ JS_free(cx, bytes);
+ return JS_FALSE;
+ }
+ bytes = tmp;
+
+ str = dec_string(cx, bytes, byteslen);
+ JS_free(cx, bytes);
+
+ if(!str) return JS_FALSE;
+
+ *rval = STRING_TO_JSVAL(str);
+
+ 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)
+ return JS_TRUE;
+ return JS_SealObject(cx, target, deep);
+}
+
+static void
+execute_script(JSContext *cx, JSObject *obj, const char *filename) {
+ FILE *file;
+ JSScript *script;
+ jsval result;
+
+ if(!filename || strcmp(filename, "-") == 0)
+ {
+ file = stdin;
+ }
+ else
+ {
+ file = fopen(filename, "r");
+ if (!file)
+ {
+ fprintf(stderr, "could not open script file %s\n", filename);
+ gExitCode = 1;
+ return;
+ }
+ }
+
+ script = JS_CompileFileHandle(cx, obj, filename, file);
+ if(script)
+ {
+ JS_ExecuteScript(cx, obj, script, &result);
+ JS_DestroyScript(cx, script);
+ }
+}
+
+static void
+printerror(JSContext *cx, const char *mesg, JSErrorReport *report)
+{
+ if(!report || !JSREPORT_IS_WARNING(report->flags))
+ {
+ fprintf(stderr, "%s\n", mesg);
+ }
+}
+
+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}
+};
+
+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
+};
+
+int
+main(int argc, const char * argv[])
+{
+ JSRuntime* rt = NULL;
+ JSContext* cx = NULL;
+ JSObject* global = NULL;
+ JSFunctionSpec* sp = NULL;
+ int i = 0;
+
+ rt = JS_NewRuntime(64L * 1024L * 1024L);
+ if (!rt) return 1;
+
+ cx = JS_NewContext(rt, 8L * 1024L);
+ if (!cx) return 1;
+
+ JS_SetErrorReporter(cx, printerror);
+ JS_ToggleOptions(cx, JSOPTION_XML);
+
+ SETUP_REQUEST(cx);
+
+ global = JS_NewObject(cx, &global_class, NULL, NULL);
+ if (!global) return 1;
+ if (!JS_InitStandardClasses(cx, global)) return 1;
+
+ for(sp = global_functions; sp->name != NULL; sp++)
+ {
+ if(!JS_DefineFunction(cx, global,
+ sp->name, sp->call, sp->nargs, sp->flags))
+ {
+ fprintf(stderr, "Failed to create function: %s\n", sp->name);
+ return 1;
+ }
+ }
+
+ if(!install_http(cx, global))
+ {
+ return 1;
+ }
+
+ JS_SetGlobalObject(cx, global);
+
+ if(argc > 2)
+ {
+ fprintf(stderr, "incorrect number of arguments\n\n");
+ fprintf(stderr, "usage: %s <scriptfile>\n", argv[0]);
+ return 2;
+ }
+
+ if(argc == 0)
+ {
+ execute_script(cx, global, NULL);
+ }
+ else
+ {
+ execute_script(cx, global, argv[1]);
+ }
+
+ FINISH_REQUEST(cx);
+
+ JS_DestroyContext(cx);
+ JS_DestroyRuntime(rt);
+ JS_ShutDown();
+
+ return gExitCode;
+}
diff --git a/src/couchdb/priv/couch_js/utf8.c b/src/couchdb/priv/couch_js/utf8.c
index d6064267..699a6fee 100644
--- a/src/couchdb/priv/couch_js/utf8.c
+++ b/src/couchdb/priv/couch_js/utf8.c
@@ -11,7 +11,6 @@
// the License.
#include <jsapi.h>
-#include "config.h"
static int
enc_char(uint8 *utf8Buffer, uint32 ucs4Char)
@@ -122,7 +121,7 @@ char*
enc_string(JSContext* cx, jsval arg, size_t* buflen)
{
JSString* str = NULL;
- const jschar* src = NULL;
+ jschar* src = NULL;
char* bytes = NULL;
size_t srclen = 0;
size_t byteslen = 0;
@@ -130,12 +129,8 @@ enc_string(JSContext* cx, jsval arg, size_t* buflen)
str = JS_ValueToString(cx, arg);
if(!str) goto error;
-#ifdef HAVE_JS_GET_STRING_CHARS_AND_LENGTH
- src = JS_GetStringCharsAndLength(cx, str, &srclen);
-#else
src = JS_GetStringChars(str);
srclen = JS_GetStringLength(str);
-#endif
if(!enc_charbuf(src, srclen, NULL, &byteslen)) goto error;
@@ -288,4 +283,4 @@ error:
success:
return str;
-}
+} \ No newline at end of file