Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Fix COUCHDB-1078 - Port couchjs to newest libmozjs

As usually, please test and report any build system problems as I
cannot test every configuration.

Thanks to Chris Coulson for the original patch.

git-svn-id: https://svn.apache.org/repos/asf/couchdb/trunk@1137464 13f79535-47bb-0310-9956-ffa450edef68
  • Loading branch information...
commit 7b0f330627c9f3ef1ccb9e3ffe1e909e3a27f1bf 1 parent 0cd6405
@tilgovi tilgovi authored
View
1  THANKS
@@ -83,6 +83,7 @@ suggesting improvements or submitting changes. Some of these people are:
* Nathan Vander Wilt <natevw@yahoo.com>
* Caolan McMahon <caolan.mcmahon@googlemail.com>
* Andrey Somov <trophybase@gmail.com>
+ * Chris Coulson <chrisccoulson.googlemail.com>
For a list of authors see the `AUTHORS` file.
View
82 configure.ac
@@ -121,15 +121,19 @@ AC_ARG_WITH([erlang], [AC_HELP_STRING([--with-erlang=PATH],
])
AC_SUBST(ERLANG_FLAGS)
-PKG_CHECK_MODULES([JS], [mozilla-js >= 1.7], [
- JS_LIB_DIR="$(${PKG_CONFIG} --variable=sdkdir mozilla-js)/lib"
+PKG_CHECK_MODULES([JS], [mozjs185], [
+ JS_LIB_DIR="$(${PKG_CONFIG} --variable=libdir mozjs185)"
+], [
+ PKG_CHECK_MODULES([JS], [mozilla-js >= 1.7], [
+ JS_LIB_DIR="$(${PKG_CONFIG} --variable=sdkdir mozilla-js)/lib"
], [
- JS_LIB_DIR="${libdir}"
- JS_CFLAGS="-I/usr/include"
- JS_CFLAGS="$JS_CFLAGS -I/usr/include/js"
- JS_CFLAGS="$JS_CFLAGS -I/usr/include/mozjs"
- JS_CFLAGS="$JS_CFLAGS -I/usr/local/include/js"
- JS_CFLAGS="$JS_CFLAGS -I/opt/local/include/js"
+ JS_LIB_DIR="${libdir}"
+ JS_CFLAGS="-I/usr/include"
+ JS_CFLAGS="$JS_CFLAGS -I/usr/include/js"
+ JS_CFLAGS="$JS_CFLAGS -I/usr/include/mozjs"
+ JS_CFLAGS="$JS_CFLAGS -I/usr/local/include/js"
+ JS_CFLAGS="$JS_CFLAGS -I/opt/local/include/js"
+ ])
])
AC_ARG_WITH([js-include], [AC_HELP_STRING([--with-js-include=PATH],
@@ -175,16 +179,40 @@ AM_CONDITIONAL([WINDOWS], [test x$IS_WINDOWS = xTRUE])
OLD_LIBS="$LIBS"
LIBS="$JS_LIBS $LIBS"
-AC_CHECK_LIB([mozjs], [JS_NewContext], [JS_LIB_BASE=mozjs], [
- AC_CHECK_LIB([js], [JS_NewContext], [JS_LIB_BASE=js], [
- AC_CHECK_LIB([js3250], [JS_NewContext], [JS_LIB_BASE=js3250], [
- AC_CHECK_LIB([js32], [JS_NewContext], [JS_LIB_BASE=js32], [
- AC_MSG_ERROR([Could not find the js library.
-
-Is the Mozilla SpiderMonkey library installed?])])])])])
+AC_CHECK_LIB([mozjs185], [JS_NewContext], [JS_LIB_BASE=mozjs185], [
+ AC_CHECK_LIB([mozjs], [JS_NewContext], [JS_LIB_BASE=mozjs], [
+ AC_CHECK_LIB([js], [JS_NewContext], [JS_LIB_BASE=js], [
+ AC_CHECK_LIB([js3250], [JS_NewContext], [JS_LIB_BASE=js3250], [
+ AC_CHECK_LIB([js32], [JS_NewContext], [JS_LIB_BASE=js32], [
+ AC_MSG_ERROR([Could not find the js library.
+
+Is the Mozilla SpiderMonkey library installed?])])])])])])
+
+AC_CHECK_LIB([$JS_LIB_BASE], [JS_FreezeObject],
+ AC_DEFINE([HAVE_JS_FREEZE_OBJECT], [1],
+ [Define whether we have JS_FreezeObject]))
+
+AC_CHECK_LIB([$JS_LIB_BASE], [JS_NewGlobalObject],
+ AC_DEFINE([HAVE_JS_NEW_GLOBAL_OBJECT], [1],
+ [Define whether we have JS_NewGlobalObject]))
+
+AC_CHECK_LIB([$JS_LIB_BASE], [JS_GetStringCharsAndLength],
+ AC_DEFINE([HAVE_JS_GET_STRING_CHARS_AND_LENGTH], [1],
+ [Define whether we have JS_GetStringCharsAndLength]))
+
+AC_CHECK_LIB([$JS_LIB_BASE], [JS_NewCompartmentAndGlobalObject],
+ AC_DEFINE([HAVE_COMPARTMENTS], [1],
+ [Define whether we have JS_NewCompartmentAndGlobalObject]))
+
+AC_CHECK_LIB([$JS_LIB_BASE], [JS_StrictPropertyStub],
+ AC_DEFINE([HAVE_JS_STRICT_PROPERTY_STUB], [1],
+ [Define whether we have JS_StrictPropertyStub]))
+
+AC_CHECK_LIB([$JS_LIB_BASE], [JS_DestroyScript],
+ AC_DEFINE([HAVE_SCRIPT_TYPE], [1],
+ [Define whether scripts have a special JSScript type]))
LIBS="$OLD_LIBS"
-
if test x${IS_WINDOWS} = xTRUE; then
if test -f "$JS_LIB_DIR/$JS_LIB_BASE.dll"; then
# seamonkey 1.7- build layout on Windows
@@ -247,7 +275,7 @@ CPPFLAGS="$OLD_CPPFLAGS"
AC_LANG_PUSH(C)
OLDCFLAGS="$CFLAGS"
-CFLAGS="-Werror-implicit-function-declaration $CFLAGS"
+CFLAGS="-Werror-implicit-function-declaration $JS_CFLAGS $OLDCFLAGS"
AC_COMPILE_IFELSE(
[AC_LANG_PROGRAM(
[[#include <jsapi.h>]],
@@ -255,6 +283,26 @@ AC_COMPILE_IFELSE(
)],
AC_DEFINE([USE_JS_SETOPCB], [], [Use new JS_SetOperationCallback])
)
+CFLAGS="$JS_CFLAGS $OLDCFLAGS"
+AC_COMPILE_IFELSE(
+ [AC_LANG_PROGRAM(
+ [[#include <jsapi.h>]],
+ [[static JSFunctionSpec fs;
+ fs.extra = 0;]]
+ )],
+ AC_DEFINE([JS_FS_HAS_EXTRA], [1], [JSFunctionSpec has an extra member])
+)
+CFLAGS="$JS_CFLAGS $OLDCFLAGS -Werror"
+AC_COMPILE_IFELSE(
+ [AC_LANG_PROGRAM(
+ [[#include <jsapi.h>
+ static JSBool op(JSContext* cx, JSObject* obj, jsid id, jsval* vp) {}]],
+ [[static JSPropertySpec spec;
+ spec.getter = op;]]
+ )],
+ AC_DEFINE([JS_PROPERTY_OP_HAS_ID_AS_JSID], [1],
+ [The type of "id" in the prototype for JSPropertyOp is a jsid])
+)
CFLAGS="$OLD_CFLAGS"
AC_LANG_POP(C)
View
57 src/couchdb/priv/couch_js/http.c
@@ -10,12 +10,11 @@
// License for the specific language governing permissions and limitations under
// the License.
-#include "config.h"
-
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <jsapi.h>
+#include "config.h"
#ifndef HAVE_CURL
@@ -34,6 +33,7 @@ install_http(JSContext* cx, JSObject* glbl)
#include <curl/curl.h>
#include "utf8.h"
+#include "jscompat.h"
#ifdef XP_WIN
// Map some of the string function names to things which exist on Windows
@@ -66,12 +66,14 @@ go(JSContext* cx, JSObject* obj, HTTPData* http, char* body, size_t blen);
static JSString*
str_from_binary(JSContext* cx, char* data, size_t length);
-static JSBool
-constructor(JSContext* cx, JSObject* obj, uintN argc, jsval* argv, jsval* rval)
+COUCHJS_CONSTRUCTOR_DECLARE(constructor)
{
+ COUCHJS_CONSTRUCTOR_INIT_VARS
HTTPData* http = NULL;
JSBool ret = JS_FALSE;
+ COUCHJS_CONSTRUCTOR_CONSTRUCT
+
http = (HTTPData*) malloc(sizeof(HTTPData));
if(!http)
{
@@ -89,7 +91,8 @@ constructor(JSContext* cx, JSObject* obj, uintN argc, jsval* argv, jsval* rval)
JS_ReportError(cx, "Failed to set private CouchHTTP data.");
goto error;
}
-
+
+ COUCHJS_CONSTRUCTOR_FINISH
ret = JS_TRUE;
goto success;
@@ -106,7 +109,10 @@ destructor(JSContext* cx, JSObject* obj)
HTTPData* http = (HTTPData*) JS_GetPrivate(cx, obj);
if(!http)
{
- fprintf(stderr, "Unable to destroy invalid CouchHTTP instance.\n");
+ // mozjs185 seems to create a ghost object that gets finalized
+ // No messing about with flags seems to prevent this or ensure it's
+ // constructed properly.
+ fprintf(stderr, "No valid CouchHTTP instance to destroy [harmless].\n");
}
else
{
@@ -117,8 +123,9 @@ destructor(JSContext* cx, JSObject* obj)
}
static JSBool
-open(JSContext* cx, JSObject* obj, uintN argc, jsval* argv, jsval* rval)
-{
+open(JSContext* cx, uintN argc, jsval* vp)
+{
+ COUCHJS_NATIVE_INIT_VARS(argv, obj)
HTTPData* http = (HTTPData*) JS_GetPrivate(cx, obj);
char* method = NULL;
char* url = NULL;
@@ -191,6 +198,7 @@ open(JSContext* cx, JSObject* obj, uintN argc, jsval* argv, jsval* rval)
// Disable Expect: 100-continue
http->req_headers = curl_slist_append(http->req_headers, "Expect:");
+ JS_SET_RVAL(cx, vp, JSVAL_VOID);
ret = JS_TRUE;
done:
@@ -199,8 +207,9 @@ open(JSContext* cx, JSObject* obj, uintN argc, jsval* argv, jsval* rval)
}
static JSBool
-setheader(JSContext* cx, JSObject* obj, uintN argc, jsval* argv, jsval* rval)
-{
+setheader(JSContext* cx, uintN argc, jsval* vp)
+{
+ COUCHJS_NATIVE_INIT_VARS(argv, obj)
HTTPData* http = (HTTPData*) JS_GetPrivate(cx, obj);
char* keystr = NULL;
char* valstr = NULL;
@@ -251,6 +260,7 @@ setheader(JSContext* cx, JSObject* obj, uintN argc, jsval* argv, jsval* rval)
snprintf(hdrbuf, hdrlen, "%s: %s", keystr, valstr);
http->req_headers = curl_slist_append(http->req_headers, hdrbuf);
+ JS_SET_RVAL(cx, vp, JSVAL_VOID);
ret = JS_TRUE;
done:
@@ -262,8 +272,9 @@ setheader(JSContext* cx, JSObject* obj, uintN argc, jsval* argv, jsval* rval)
}
static JSBool
-sendreq(JSContext* cx, JSObject* obj, uintN argc, jsval* argv, jsval* rval)
+sendreq(JSContext* cx, uintN argc, jsval* vp)
{
+ COUCHJS_NATIVE_INIT_VARS(argv, obj)
HTTPData* http = (HTTPData*) JS_GetPrivate(cx, obj);
char* body = NULL;
size_t bodylen = 0;
@@ -286,14 +297,15 @@ sendreq(JSContext* cx, JSObject* obj, uintN argc, jsval* argv, jsval* rval)
}
ret = go(cx, obj, http, body, bodylen);
+ if (ret == JS_TRUE)
+ JS_SET_RVAL(cx, vp, JSVAL_VOID);
done:
if(body) free(body);
return ret;
}
-static JSBool
-status(JSContext* cx, JSObject* obj, jsval idval, jsval* vp)
+COUCHJS_GETTER_DECLARE(status)
{
HTTPData* http = (HTTPData*) JS_GetPrivate(cx, obj);
@@ -302,7 +314,13 @@ status(JSContext* cx, JSObject* obj, jsval idval, jsval* vp)
JS_ReportError(cx, "Invalid CouchHTTP instance.");
return JS_FALSE;
}
-
+
+#ifndef INT_FITS_IN_JSVAL
+ // jsval's are 64-bits wide in mozjs >= 2.0, so a jsint can use a full
+ // 32-bits now no bits are reserved for tagging
+ *vp = INT_TO_JSVAL(http->last_status);
+ return JS_TRUE;
+#else
if(INT_FITS_IN_JSVAL(http->last_status))
{
*vp = INT_TO_JSVAL(http->last_status);
@@ -313,6 +331,7 @@ status(JSContext* cx, JSObject* obj, jsval idval, jsval* vp)
JS_ReportError(cx, "INTERNAL: Invalid last_status");
return JS_FALSE;
}
+#endif
}
JSClass CouchHTTPClass = {
@@ -323,7 +342,7 @@ JSClass CouchHTTPClass = {
JS_PropertyStub,
JS_PropertyStub,
JS_PropertyStub,
- JS_PropertyStub,
+ JS_SETPROPERTY_PROPERTY_STUB,
JS_EnumerateStub,
JS_ResolveStub,
JS_ConvertStub,
@@ -337,10 +356,10 @@ JSPropertySpec CouchHTTPProperties[] = {
};
JSFunctionSpec CouchHTTPFunctions[] = {
- {"_open", open, 3, 0, 0},
- {"_setRequestHeader", setheader, 2, 0, 0},
- {"_send", sendreq, 1, 0, 0},
- {0, 0, 0, 0, 0}
+ JS_FS("_open", COUCHJS_NATIVE_FUNC(open), 3, JSFUN_FAST_NATIVE),
+ JS_FS("_setRequestHeader", COUCHJS_NATIVE_FUNC(setheader), 2, JSFUN_FAST_NATIVE),
+ JS_FS("_send", COUCHJS_NATIVE_FUNC(sendreq), 1, JSFUN_FAST_NATIVE),
+ JS_FS_END
};
JSObject*
View
91 src/couchdb/priv/couch_js/jscompat.h
@@ -0,0 +1,91 @@
+// 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 COUCH_JS_JS_COMPAT_H
+#define COUCH_JS_JS_COMPAT_H
+
+#ifdef JS_FS_HAS_EXTRA
+# undef JS_FS
+# undef JS_FS_END
+# define JS_FS(name,call,nargs,flags) {name, call, nargs, flags, 0}
+# define JS_FS_END JS_FS(0, 0, 0, 0)
+#endif
+
+#ifdef JSFUN_CONSTRUCTOR
+# define JSFUN_FAST_NATIVE 0
+# define COUCHJS_CONSTRUCTOR_DECLARE(name) \
+ static JSBool \
+ name(JSContext* cx, uintN argc, jsval* vp)
+# define COUCHJS_CONSTRUCTOR_INIT_VARS \
+ JSObject *obj = NULL; \
+ jsval *argv = JS_ARGV(cx, vp);
+# define COUCHJS_CONSTRUCTOR_CONSTRUCT \
+ obj = JS_NewObjectForConstructor(cx, vp); \
+ if(!obj) { \
+ JS_ReportError(cx, "Failed to create 'this' object"); \
+ return JS_FALSE; \
+ }
+# define COUCHJS_CONSTRUCTOR_FINISH \
+ JS_SET_RVAL(cx, vp, OBJECT_TO_JSVAL(obj));
+# define COUCHJS_NATIVE_FUNC(func) func
+#else
+# define COUCHJS_CONSTRUCTOR_DECLARE(name) \
+ static JSBool \
+ name(JSContext* cx, JSObject* obj, uintN argc, jsval* argv, jsval* rval)
+# define COUCHJS_CONSTRUCTOR_INIT_VARS
+# define COUCHJS_CONSTRUCTOR_CONSTRUCT
+# define COUCHJS_CONSTRUCTOR_FINISH
+# define COUCHJS_NATIVE_FUNC(func) (JSNative) func
+#endif
+
+#ifdef HAVE_JS_STRICT_PROPERTY_STUB
+# define JS_SETPROPERTY_PROPERTY_STUB JS_StrictPropertyStub
+#else
+# define JS_SETPROPERTY_PROPERTY_STUB JS_PropertyStub
+#endif
+
+#ifdef HAVE_SCRIPT_TYPE
+# define COUCHJS_SCRIPT JSScript
+# define COUCHJS_DESTROY_SCRIPT(cx, script) \
+ JS_DestroyScript(cx, script)
+#else
+# define COUCHJS_SCRIPT JSObject
+# define COUCHJS_DESTROY_SCRIPT(cx, script)
+#endif
+
+#ifdef HAVE_JS_FREEZE_OBJECT
+# define COUCHJS_SEAL_OBJECT(res, cx, target, deep) \
+ res = deep ? JS_DeepFreezeObject(cx, target) : JS_FreezeObject(cx, target);
+#else
+# define COUCHJS_SEAL_OBJECT(res, cx, target, deep) \
+ res = JS_SealObject(cx, target, deep);
+#endif
+
+#define COUCHJS_NATIVE_INIT_VARS(argv, obj) \
+ jsval* argv = JS_ARGV(cx, vp); \
+ JSObject* obj = JS_THIS_OBJECT(cx, vp); \
+ if (!obj) { \
+ JS_ReportError(cx, "No 'this' object"); \
+ return JS_FALSE; \
+ }
+
+#ifdef JS_PROPERTY_OP_HAS_ID_AS_JSID
+# define COUCHJS_GETTER_DECLARE(name) \
+ static JSBool \
+ status(JSContext* cx, JSObject* obj, jsid id, jsval* vp)
+#else
+# define COUCHJS_GETTER_DECLARE(name) \
+ static JSBool \
+ status(JSContext* cx, JSObject* obj, jsval idval, jsval* vp)
+#endif
+
+#endif
View
161 src/couchdb/priv/couch_js/main.c
@@ -18,6 +18,7 @@
#include "utf8.h"
#include "http.h"
+#include "jscompat.h"
int gExitCode = 0;
@@ -33,9 +34,25 @@ int gExitCode = 0;
#define FINISH_REQUEST(cx)
#endif
+
+static JSClass global_class = {
+ "GlobalClass",
+ JSCLASS_GLOBAL_FLAGS,
+ JS_PropertyStub,
+ JS_PropertyStub,
+ JS_PropertyStub,
+ JS_SETPROPERTY_PROPERTY_STUB,
+ JS_EnumerateStub,
+ JS_ResolveStub,
+ JS_ConvertStub,
+ JS_FinalizeStub,
+ JSCLASS_NO_OPTIONAL_MEMBERS
+};
+
static JSBool
-evalcx(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+evalcx(JSContext* cx, uintN argc, jsval* vp)
{
+ jsval* argv = JS_ARGV(cx, vp);
JSString *str;
JSObject *sandbox;
JSContext *subcx;
@@ -43,6 +60,9 @@ evalcx(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
size_t srclen;
JSBool ret = JS_FALSE;
jsval v;
+#ifdef HAVE_COMPARTMENTS
+ JSCrossCompartmentCall *call = NULL;
+#endif
sandbox = NULL;
if(!JS_ConvertArguments(cx, argc, argv, "S / o", &str, &sandbox))
@@ -59,42 +79,69 @@ evalcx(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
SETUP_REQUEST(subcx);
+#ifdef HAVE_JS_GET_STRING_CHARS_AND_LENGTH
+ src = JS_GetStringCharsAndLength(cx, str, &srclen);
+#else
src = JS_GetStringChars(str);
srclen = JS_GetStringLength(str);
+#endif
+
+#ifdef HAVE_COMPARTMENTS
+ // Re-use the compartment associated with the main context,
+ // rather than creating a new compartment */
+ JSObject *global = JS_GetGlobalObject(cx);
+ if(!global)
+ {
+ goto done;
+ }
+ call = JS_EnterCrossCompartmentCall(subcx, global);
+#endif
if(!sandbox)
{
+#ifdef HAVE_JS_NEW_GLOBAL_OBJECT
+ sandbox = JS_NewGlobalObject(subcx, &global_class);
+#else
sandbox = JS_NewObject(subcx, NULL, NULL, NULL);
+#endif
if(!sandbox || !JS_InitStandardClasses(subcx, sandbox)) goto done;
}
if(srclen == 0)
{
- *rval = OBJECT_TO_JSVAL(sandbox);
+ JS_SET_RVAL(cx, vp, OBJECT_TO_JSVAL(sandbox));
}
else
{
- JS_EvaluateUCScript(subcx, sandbox, src, srclen, NULL, 0, rval);
+ JS_EvaluateUCScript(subcx, sandbox, src, srclen, NULL, 0, &JS_RVAL(cx, vp));
}
ret = JS_TRUE;
done:
+#ifdef HAVE_COMPARTMENTS
+ if(call)
+ {
+ JS_LeaveCrossCompartmentCall(call);
+ }
+#endif
FINISH_REQUEST(subcx);
JS_DestroyContext(subcx);
return ret;
}
static JSBool
-gc(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+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, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+print(JSContext *cx, uintN argc, jsval *vp)
{
+ jsval *argv = JS_ARGV(cx, vp);
uintN i;
char *bytes;
@@ -109,16 +156,47 @@ print(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
fputc('\n', stdout);
fflush(stdout);
+ JS_SET_RVAL(cx, vp, JSVAL_VOID);
return JS_TRUE;
}
static JSBool
-quit(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+quit(JSContext *cx, uintN argc, jsval *vp)
{
+ jsval *argv = JS_ARGV(cx, vp);
JS_ConvertArguments(cx, argc, argv, "/ i", &gExitCode);
return JS_FALSE;
}
+static int
+couchjs_fgets(char *buf, int size, FILE *file)
+{
+ int n, i, c;
+ JSBool crflag;
+
+ n = size - 1;
+ if (n < 0)
+ return -1;
+
+ crflag = JS_FALSE;
+ for (i = 0; i < n && (c = getc(file)) != EOF; i++)
+ {
+ buf[i] = c;
+ if (c == '\n') { /* any \n ends a line */
+ i++; /* keep the \n; we know there is room for \0 */
+ break;
+ }
+ if (crflag) { /* \r not followed by \n ends line at the \r */
+ ungetc(c, file);
+ break; /* and overwrite c in buf with \0 */
+ }
+ crflag = (c == '\r');
+ }
+
+ buf[i] = '\0';
+ return i;
+}
+
static char*
readfp(JSContext* cx, FILE* fp, size_t* buflen)
{
@@ -131,7 +209,7 @@ readfp(JSContext* cx, FILE* fp, size_t* buflen)
bytes = JS_malloc(cx, byteslen);
if(bytes == NULL) return NULL;
- while((readlen = js_fgets(bytes+used, byteslen-used, stdin)) > 0)
+ while((readlen = couchjs_fgets(bytes+used, byteslen-used, stdin)) > 0)
{
used += readlen;
@@ -157,7 +235,7 @@ readfp(JSContext* cx, FILE* fp, size_t* buflen)
}
static JSBool
-readline(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) {
+readline(JSContext *cx, uintN argc, jsval *vp) {
jschar *chars;
JSString *str;
char* bytes;
@@ -173,7 +251,7 @@ readline(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) {
/* Treat the empty string specially */
if(byteslen == 0)
{
- *rval = JS_GetEmptyStringValue(cx);
+ JS_SET_RVAL(cx, vp, JS_GetEmptyStringValue(cx));
JS_free(cx, bytes);
return JS_TRUE;
}
@@ -192,27 +270,37 @@ readline(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) {
if(!str) return JS_FALSE;
- *rval = STRING_TO_JSVAL(str);
+ JS_SET_RVAL(cx, vp, STRING_TO_JSVAL(str));
return JS_TRUE;
}
static JSBool
-seal(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) {
+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;
- return JS_SealObject(cx, target, deep);
+ }
+
+ COUCHJS_SEAL_OBJECT(ret, cx, target, deep);
+ if (ret == JS_TRUE)
+ JS_SET_RVAL(cx, vp, JSVAL_VOID);
+
+ return ret;
}
static void
execute_script(JSContext *cx, JSObject *obj, const char *filename) {
FILE *file;
- JSScript *script;
+ COUCHJS_SCRIPT *script;
jsval result;
if(!filename || strcmp(filename, "-") == 0)
@@ -234,7 +322,7 @@ execute_script(JSContext *cx, JSObject *obj, const char *filename) {
if(script)
{
JS_ExecuteScript(cx, obj, script, &result);
- JS_DestroyScript(cx, script);
+ COUCHJS_DESTROY_SCRIPT(cx, script);
}
}
@@ -248,27 +336,13 @@ printerror(JSContext *cx, const char *mesg, JSErrorReport *report)
}
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
+ JS_FS("evalcx", COUCHJS_NATIVE_FUNC(evalcx), 0, JSFUN_FAST_NATIVE),
+ JS_FS("gc", COUCHJS_NATIVE_FUNC(gc), 0, JSFUN_FAST_NATIVE),
+ JS_FS("print", COUCHJS_NATIVE_FUNC(print), 0, JSFUN_FAST_NATIVE),
+ JS_FS("quit", COUCHJS_NATIVE_FUNC(quit), 0, JSFUN_FAST_NATIVE),
+ JS_FS("readline", COUCHJS_NATIVE_FUNC(readline), 0, JSFUN_FAST_NATIVE),
+ JS_FS("seal", COUCHJS_NATIVE_FUNC(seal), 0, JSFUN_FAST_NATIVE),
+ JS_FS_END
};
int
@@ -284,6 +358,9 @@ main(int argc, const char * argv[])
JSRuntime* rt = NULL;
JSContext* cx = NULL;
JSObject* global = NULL;
+#ifdef HAVE_COMPARTMENTS
+ JSCrossCompartmentCall *call = NULL;
+#endif
JSFunctionSpec* sp = NULL;
const char* script_name = NULL;
int use_http = 0;
@@ -325,8 +402,18 @@ main(int argc, const char * argv[])
SETUP_REQUEST(cx);
+#ifdef HAVE_COMPARTMENTS
+ global = JS_NewCompartmentAndGlobalObject(cx, &global_class, NULL);
+ if (!global) return 1;
+ call = JS_EnterCrossCompartmentCall(cx, global);
+#elif HAVE_JS_NEW_GLOBAL_OBJECT
+ global = JS_NewGlobalObject(cx, &global_class);
+ if (!global) return 1;
+#else
global = JS_NewObject(cx, &global_class, NULL, NULL);
if (!global) return 1;
+ JS_SetGlobalObject(cx, global);
+#endif
if (!JS_InitStandardClasses(cx, global)) return 1;
for(sp = global_functions; sp->name != NULL; sp++)
@@ -344,9 +431,11 @@ main(int argc, const char * argv[])
return 2;
}
- JS_SetGlobalObject(cx, global);
execute_script(cx, global, script_name);
+#ifdef HAVE_COMPARTMENTS
+ JS_LeaveCrossCompartmentCall(call);
+#endif
FINISH_REQUEST(cx);
JS_DestroyContext(cx);
View
9 src/couchdb/priv/couch_js/utf8.c
@@ -11,6 +11,7 @@
// the License.
#include <jsapi.h>
+#include "config.h"
static int
enc_char(uint8 *utf8Buffer, uint32 ucs4Char)
@@ -121,7 +122,7 @@ char*
enc_string(JSContext* cx, jsval arg, size_t* buflen)
{
JSString* str = NULL;
- jschar* src = NULL;
+ const jschar* src = NULL;
char* bytes = NULL;
size_t srclen = 0;
size_t byteslen = 0;
@@ -129,8 +130,12 @@ 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;
@@ -283,4 +288,4 @@ dec_string(JSContext* cx, const char* bytes, size_t byteslen)
success:
return str;
-}
+}
Please sign in to comment.
Something went wrong with that request. Please try again.