RPM Package Manager, CVS Repository http://rpm5.org/cvs/ ____________________________________________________________________________
Server: rpm5.org Name: Jeff Johnson Root: /v/rpm/cvs Email: j...@rpm5.org Module: rpm Date: 23-Jun-2017 05:39:44 Branch: rpm-5_4 Handle: 2017062303394301 Added files: (Branch: rpm-5_4) rpm/rpmio rpmjss.h Modified files: (Branch: rpm-5_4) rpm/rpmio Makefile.am rpmjs17.cpp rpmjs185.cpp rpmjs24.cpp rpmjs31.cpp rpmjs38.cpp rpmjs45.cpp Log: - rpmjss: avoid "namesapce js" collision. Summary: Revision Changes Path 1.293.2.98 +7 -7 rpm/rpmio/Makefile.am 1.1.2.4 +419 -43 rpm/rpmio/rpmjs17.cpp 1.1.2.4 +389 -32 rpm/rpmio/rpmjs185.cpp 1.1.2.5 +38 -28 rpm/rpmio/rpmjs24.cpp 1.1.2.5 +33 -28 rpm/rpmio/rpmjs31.cpp 1.1.2.5 +33 -28 rpm/rpmio/rpmjs38.cpp 1.1.2.6 +679 -61 rpm/rpmio/rpmjs45.cpp 1.1.2.1 +141 -0 rpm/rpmio/rpmjss.h ____________________________________________________________________________ patch -p0 <<'@@ .' Index: rpm/rpmio/Makefile.am ============================================================================ $ cvs diff -u -r1.293.2.97 -r1.293.2.98 Makefile.am --- rpm/rpmio/Makefile.am 23 Jun 2017 00:43:55 -0000 1.293.2.97 +++ rpm/rpmio/Makefile.am 23 Jun 2017 03:39:43 -0000 1.293.2.98 @@ -551,27 +551,27 @@ rpmgpg_LDADD = $(RPMIO_LDADD_COMMON) rpmjs185_SOURCES = rpmjs185.cpp -rpmjs185_CPPFLAGS = -DXP_UNIX=1 -DJS_THREADSAFE=1 -I/usr/include/js -fPIC -DRPMJS_SELF_TEST +rpmjs185_CPPFLAGS = -DXP_UNIX=1 -DJS_THREADSAFE=1 -I/usr/include/js -fPIC -DRPMJSS_SELF_TEST rpmjs185_LDADD = -L/usr/lib64 -ljs rpmjs17_SOURCES = rpmjs17.cpp -rpmjs17_CPPFLAGS = -include /usr/include/js-17.0/js/RequiredDefines.h -I/usr/include/js-17.0 -fPIC -DRPMJS_SELF_TEST +rpmjs17_CPPFLAGS = -include /usr/include/js-17.0/js/RequiredDefines.h -I/usr/include/js-17.0 -fPIC -DRPMJSS_SELF_TEST rpmjs17_LDADD = -L/usr/lib64 -lmozjs-17.0 rpmjs24_SOURCES = rpmjs24.cpp -rpmjs24_CPPFLAGS = -include /usr/include/mozjs-24/js/RequiredDefines.h -I/usr/include/mozjs-24 -fPIC -DRPMJS_SELF_TEST +rpmjs24_CPPFLAGS = -include /usr/include/mozjs-24/js/RequiredDefines.h -I/usr/include/mozjs-24 -fPIC -DRPMJSS_SELF_TEST rpmjs24_LDADD = -L/usr/lib64 -lmozjs-24 rpmjs31_SOURCES = rpmjs31.cpp -rpmjs31_CPPFLAGS = -include /usr/include/mozjs-31/js/RequiredDefines.h -I/usr/include/mozjs-31 -fPIC -DRPMJS_SELF_TEST +rpmjs31_CPPFLAGS = -include /usr/include/mozjs-31/js/RequiredDefines.h -I/usr/include/mozjs-31 -fPIC -DRPMJSS_SELF_TEST rpmjs31_LDADD = -L/usr/lib64 -lmozjs-31 rpmjs38_SOURCES = rpmjs38.cpp -rpmjs38_CPPFLAGS = -include /usr/include/mozjs-38/js/RequiredDefines.h -I/usr/include/mozjs-38 -fPIC -DRPMJS_SELF_TEST +rpmjs38_CPPFLAGS = -include /usr/include/mozjs-38/js/RequiredDefines.h -I/usr/include/mozjs-38 -fPIC -DRPMJSS_SELF_TEST rpmjs38_LDADD = -L/usr/lib64 -lmozjs-38 rpmjs45_SOURCES = rpmjs45.cpp -rpmjs45_CPPFLAGS = -include /usr/include/mozjs-45/js/RequiredDefines.h -I/usr/include/mozjs-45 -fPIC -DRPMJS_SELF_TEST +rpmjs45_CPPFLAGS = -include /usr/include/mozjs-45/js/RequiredDefines.h -I/usr/include/mozjs-45 -fPIC -DRPMJSS_SELF_TEST rpmjs45_LDADD = -L/usr/lib64 -lmozjs-45 mozjs: rpmjs185 rpmjs17 rpmjs24 rpmjs31 rpmjs38 rpmjs45 @@ -582,7 +582,7 @@ -./rpmjs38 -./rpmjs45 -mozjs45: rpmjs45 +moz45: rpmjs45 @-env ASAN_OPTIONS=detect_leaks=0 ./rpmjs45 rpmpbzip2_SOURCES = rpmpbzip2.c @@ . patch -p0 <<'@@ .' Index: rpm/rpmio/rpmjs17.cpp ============================================================================ $ cvs diff -u -r1.1.2.3 -r1.1.2.4 rpmjs17.cpp --- rpm/rpmio/rpmjs17.cpp 22 Jun 2017 17:35:24 -0000 1.1.2.3 +++ rpm/rpmio/rpmjs17.cpp 23 Jun 2017 03:39:43 -0000 1.1.2.4 @@ -2,14 +2,14 @@ // #define __STDC_LIMIT_MACROS // #include <stdint.h> +#pragma GCC diagnostic ignored "-Winvalid-offsetof" + #include "system.h" -#define js jsns #include "jsapi.h" -#undef js -#define _RPMJS_INTERNAL -#include <rpmjs.h> +#define _RPMJSS_INTERNAL +#include <rpmjss.h> #include "debug.h" @@ -26,8 +26,12 @@ JS_ConvertStub, }; -struct rpmjs_s _js; -rpmjs js = &_js; +static int rpmjss_nopens; + +static int _rpmjss17_debug; +#define SPEW(_fmt, ...) \ + if (_rpmjss17_debug) \ + fprintf(stderr, _fmt, __VA_ARGS__) /*==============================================================*/ typedef struct JSI_s * JSI_t; @@ -38,7 +42,7 @@ }; static void -rpmjsReportError(JSContext *cx, const char *message, JSErrorReport *report) +rpmjssReportError(JSContext *cx, const char *message, JSErrorReport *report) { fprintf(stderr, "%s:%u:%s\n", report->filename ? report->filename : "<no filename=\"filename\">", @@ -46,11 +50,371 @@ } /*==============================================================*/ -static int rpmjs_nopens; +static JSBool compileOnly = JS_FALSE; -static void mozFini(rpmjs js) +static JSBool +Version(JSContext *cx, unsigned argc, jsval *vp) { - JSI_t I = (JSI_t) js->I; + jsval *argv = JS_ARGV(cx, vp); + if (argc > 0 && JSVAL_IS_INT(argv[0])) + *vp = INT_TO_JSVAL(JS_SetVersion(cx, (JSVersion) JSVAL_TO_INT(argv[0]))); + else + *vp = INT_TO_JSVAL(JS_GetVersion(cx)); + return JS_TRUE; +} + +static JSBool +Load(JSContext *cx, unsigned argc, jsval *vp) +{ +#ifdef FIXME + jsval *argv = JS_ARGV(cx, vp); + JSObject *thisobj = JS_THIS_OBJECT(cx, vp); + if (!thisobj) + return JS_FALSE; + + for (unsigned i = 0; i < argc; i++) { + JSString *str = JS_ValueToString(cx, argv[i]); + if (!str) + return false; + argv[i] = STRING_TO_JSVAL(str); + JSAutoByteString filename(cx, str); + if (!filename) + return JS_FALSE; + errno = 0; + uint32_t oldopts = JS_GetOptions(cx); + JS_SetOptions(cx, oldopts | JSOPTION_COMPILE_N_GO | JSOPTION_NO_SCRIPT_RVAL); + JSObject *scriptObj = JS_CompileFile(cx, thisobj, filename.ptr()); + JS_SetOptions(cx, oldopts); + if (!scriptObj) + return false; + + if (!compileOnly && !JS_ExecuteScript(cx, thisobj, scriptObj, NULL)) + return false; + } + + return true; +#else + return false; +#endif +} + +static JSBool +Evaluate(JSContext *cx, unsigned argc, jsval *vp) +{ +#ifdef FIXME + if (argc != 1 || !JSVAL_IS_STRING(JS_ARGV(cx, vp)[0])) { +#ifdef FIXME + JS_ReportErrorNumber(cx, my_GetErrorMessage, NULL, + (argc != 1) ? JSSMSG_NOT_ENOUGH_ARGS : JSSMSG_INVALID_ARGS, + "evaluate"); +#endif /* FIXME */ + return false; + } + + JSString *code = JSVAL_TO_STRING(JS_ARGV(cx, vp)[0]); + + size_t codeLength; + const jschar *codeChars = JS_GetStringCharsAndLength(cx, code, &codeLength); + if (!codeChars) + return false; + + JSObject *thisobj = JS_THIS_OBJECT(cx, vp); + if (!thisobj) + return false; + + if ((JS_GET_CLASS(cx, thisobj)->flags & JSCLASS_IS_GLOBAL) != JSCLASS_IS_GLOBAL) { +#ifdef FIXME + JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_UNEXPECTED_TYPE, + "this-value passed to evaluate()", "not a global object"); +#endif /* FIXME */ + return false; + } + + JS_SET_RVAL(cx, vp, JSVAL_VOID); + return JS_EvaluateUCScript(cx, thisobj, codeChars, codeLength, "@evaluate", 0, NULL); +#else /* FIXME */ + return false; +#endif /* FIXME */ +} + +static JSString * +FileAsString(JSContext *cx, const char *pathname) +{ + FILE *file; + JSString *str = NULL; + size_t len, cc; + char *buf; + + file = fopen(pathname, "rb"); + if (!file) { + JS_ReportError(cx, "can't open %s: %s", pathname, strerror(errno)); + return NULL; + } + + if (fseek(file, 0, SEEK_END) == EOF) { + JS_ReportError(cx, "can't seek end of %s", pathname); + } else { + len = ftell(file); + if (fseek(file, 0, SEEK_SET) == EOF) { + JS_ReportError(cx, "can't seek start of %s", pathname); + } else { + buf = (char*) JS_malloc(cx, len + 1); + if (buf) { + cc = fread(buf, 1, len, file); + if (cc != len) { + JS_ReportError(cx, "can't read %s: %s", pathname, + (ptrdiff_t(cc) < 0) ? strerror(errno) : "short read"); + } else { + len = (size_t)cc; + str = JS_NewStringCopyN(cx, buf, len); + } + JS_free(cx, buf); + } + } + } + fclose(file); + + return str; +} + +/* + * Function to run scripts and return compilation + execution time. Semantics + * are closely modelled after the equivalent function in WebKit, as this is used + * to produce benchmark timings by SunSpider. + */ +static JSBool +Run(JSContext *cx, unsigned argc, jsval *vp) +{ +#ifdef FIXME + if (argc != 1) { +#ifdef FIXME + JS_ReportErrorNumber(cx, my_GetErrorMessage, NULL, JSSMSG_INVALID_ARGS, "run"); +#endif /* FIXME */ + return false; + } + + JSObject *thisobj = JS_THIS_OBJECT(cx, vp); + if (!thisobj) + return false; + + jsval *argv = JS_ARGV(cx, vp); + JSString *str = JS_ValueToString(cx, argv[0]); + if (!str) + return false; + argv[0] = STRING_TO_JSVAL(str); + JSAutoByteString filename(cx, str); + if (!filename) + return false; + + const jschar *ucbuf = NULL; + size_t buflen; + str = FileAsString(cx, filename.ptr()); + if (str) + ucbuf = JS_GetStringCharsAndLength(cx, str, &buflen); + if (!ucbuf) + return false; + + JS::Anchor<JSString *> a_str(str); + uint32_t oldopts = JS_GetOptions(cx); + JS_SetOptions(cx, oldopts | JSOPTION_COMPILE_N_GO | JSOPTION_NO_SCRIPT_RVAL); + +#ifdef FIXME + int64 startClock = PRMJ_Now(); +#endif /* FIXME */ + JSObject *scriptObj = JS_CompileUCScript(cx, thisobj, ucbuf, buflen, filename.ptr(), 1); + JS_SetOptions(cx, oldopts); + if (!scriptObj || !JS_ExecuteScript(cx, thisobj, scriptObj, NULL)) + return false; + +#ifdef FIXME + int64 endClock = PRMJ_Now(); + JS_SET_RVAL(cx, vp, DOUBLE_TO_JSVAL((endClock - startClock) / double(PRMJ_USEC_PER_MSEC))); +#endif /* FIXME */ + return true; +#else /* FIXME */ + return false; +#endif /* FIXME */ +} + +#ifdef NOTYET +/* + * function readline() + * Provides a hook for scripts to read a line from stdin. + */ +static JSBool +ReadLine(JSContext *cx, unsigned argc, jsval *vp) +{ +#define BUFSIZE 256 + FILE *from; + char *buf, *tmp; + size_t bufsize, buflength, gotlength; + JSBool sawNewline; + JSString *str; + + from = stdin; + buflength = 0; + bufsize = BUFSIZE; + buf = (char *) JS_malloc(cx, bufsize); + if (!buf) + return JS_FALSE; + + sawNewline = JS_FALSE; + while ((gotlength = + js_fgets(buf + buflength, bufsize - buflength, from)) > 0) { + buflength += gotlength; + + /* Are we done? */ + if (buf[buflength - 1] == '\n') { + buf[buflength - 1] = '\0'; + sawNewline = JS_TRUE; + break; + } else if (buflength < bufsize - 1) { + break; + } + + /* Else, grow our buffer for another pass. */ + bufsize *= 2; + if (bufsize > buflength) { + tmp = (char *) JS_realloc(cx, buf, bufsize); + } else { + JS_ReportOutOfMemory(cx); + tmp = NULL; + } + + if (!tmp) { + JS_free(cx, buf); + return JS_FALSE; + } + + buf = tmp; + } + + /* Treat the empty string specially. */ + if (buflength == 0) { + *vp = feof(from) ? JSVAL_NULL : JS_GetEmptyStringValue(cx); + JS_free(cx, buf); + return JS_TRUE; + } + + /* Shrink the buffer to the real size. */ + tmp = (char *) JS_realloc(cx, buf, buflength); + if (!tmp) { + JS_free(cx, buf); + return JS_FALSE; + } + + buf = tmp; + + /* + * Turn buf into a JSString. Note that buflength includes the trailing null + * character. + */ + str = JS_NewStringCopyN(cx, buf, sawNewline ? buflength - 1 : buflength); + JS_free(cx, buf); + if (!str) + return JS_FALSE; + + *vp = STRING_TO_JSVAL(str); + return JS_TRUE; +} +#endif + +static JSBool +PutStr(JSContext *cx, unsigned argc, jsval *vp) +{ + FILE * gOutFile = stdout; + jsval * argv = JS_ARGV(cx, vp); + JSString *str; + char *bytes; + + if (argc != 0) { + str = JS_ValueToString(cx, argv[0]); + if (!str) + return JS_FALSE; + bytes = JS_EncodeString(cx, str); + if (!bytes) + return JS_FALSE; + fputs(bytes, gOutFile); + JS_free(cx, bytes); + fflush(gOutFile); + } + + JS_SET_RVAL(cx, vp, JSVAL_VOID); + return JS_TRUE; +} + +static JSBool +Now(JSContext *cx, unsigned argc, jsval *vp) +{ +#ifdef FIXME +#ifdef FIXME + jsdouble now = PRMJ_Now() / double(PRMJ_USEC_PER_MSEC); +#else + jsdouble now = time(NULL) * 1000; +#endif + JS_SET_RVAL(cx, vp, DOUBLE_TO_JSVAL(now)); + return true; +#else + return false; +#endif +} + +static JSBool +Print(JSContext *cx, unsigned argc, jsval *vp) +{ + FILE * gOutFile = stdout; + jsval * argv = JS_ARGV(cx, vp); + unsigned i; + JSString *str; + char *bytes; + + for (i = 0; i < argc; i++) { + str = JS_ValueToString(cx, argv[i]); + if (!str) + return JS_FALSE; + bytes = JS_EncodeString(cx, str); + if (!bytes) + return JS_FALSE; + fprintf(gOutFile, "%s%s", i ? " " : "", bytes); + JS_free(cx, bytes); + } + + fputc('\n', gOutFile); + fflush(gOutFile); + + JS_SET_RVAL(cx, vp, JSVAL_VOID); + return JS_TRUE; +} + +static JSBool +Require(JSContext *cx, unsigned argc, jsval *vp) +{ + jsval * argv = JS_ARGV(cx, vp); +SPEW("==> %s(%p,%p[%u],%p)\n", __FUNCTION__, cx, argv, (unsigned)argc, vp); + + JS_SET_RVAL(cx, vp, JSVAL_VOID); + return JS_TRUE; +} + +static JSFunctionSpec global_functions[] = { + JS_FN("version", Version, 0,0), + JS_FN("load", Load, 1,0), + JS_FN("evaluate", Evaluate, 1,0), + JS_FN("run", Run, 1,0), +#ifdef NOTYET + JS_FN("readline", ReadLine, 0,0), +#endif + JS_FN("print", Print, 0,0), + JS_FN("putstr", PutStr, 0,0), + JS_FN("dateNow", Now, 0,0), + JS_FS("require", Require, 0,0), + JS_FS_END +}; + +/*==============================================================*/ +static void mozFini(rpmjss jss) +{ + JSI_t I = (JSI_t) jss->I; if (I->cx) JS_DestroyContext(I->cx); @@ -60,22 +424,26 @@ JS_DestroyRuntime(I->rt); I->rt = NULL; - if (--rpmjs_nopens <= 0) { + if (--rpmjss_nopens <= 0) { JS_ShutDown(); - rpmjs_nopens = 0; + rpmjss_nopens = 0; } free(I); } -static void * mozInit(rpmjs js) +static void * mozInit(rpmjss jss) { JSI_t I = NULL; - uint32_t flags = js->flags; + uint32_t flags = jss->flags; static uint32_t _maxbytes = 8L * 1024L * 1024L; static size_t _stackChunkSize = 8192; + JSClass * _clasp = (JSClass *)&global_class; + JSFunctionSpec * _functions = global_functions; + JSPrincipals * _principals = NULL; + JSBool ok; - if (rpmjs_nopens++ == 0) { + if (rpmjss_nopens++ == 0) { #ifdef NOTYET /* XXX collides with ancient JS_NewRuntime */ JS_Init(); #endif @@ -86,45 +454,52 @@ I->rt = JS_NewRuntime(_maxbytes); assert(I->rt); - JS_SetRuntimePrivate(I->rt, (void *)js); + JS_SetRuntimePrivate(I->rt, (void *)jss); I->cx = JS_NewContext(I->rt, _stackChunkSize); assert(I->cx); - JS_SetContextPrivate(I->cx, (void *)js); + JS_SetContextPrivate(I->cx, (void *)jss); + + JS_SetOptions(I->cx, + JSOPTION_VAROBJFIX | JSOPTION_METHODJIT); + JS_SetVersion(I->cx, JSVERSION_LATEST); + JS_SetErrorReporter(I->cx, rpmjssReportError); + + JS::RootedObject global(I->cx, + JS_NewGlobalObject(I->cx, _clasp, _principals)); + I->global = global; +assert(I->global); + JS_SetGlobalObject(I->cx, I->global); + + ok = JS_InitStandardClasses(I->cx, global); +assert(ok); +#ifdef JS_HAS_CTYPES + ok = JS_InitCTypesClass(I->cx, I->global); +assert(ok); +#endif + + ok = JS_DefineFunctions(I->cx, I->global, _functions); +assert(ok); return I; } -static int mozRun(rpmjs js, +static int mozRun(rpmjss jss, const char * script, const char * filename, int lineno) { - JSI_t I = (JSI_t) js->I; + JSI_t I = (JSI_t) jss->I; - JSClass * _clasp = (JSClass *)&global_class; -#ifdef NOTYET - JSFunctionSpec * _functions = global_functions; -#endif - JSPrincipals * _principals = NULL; JSBool ok; // In practice, you would want to exit this any // time you're spinning the event loop JSAutoRequest ar(I->cx); - JS::RootedObject global(I->cx, - JS_NewGlobalObject(I->cx, _clasp, _principals)); - if (!global) - return 1; - I->global = global; -assert(I->global); - JS_SetGlobalObject(I->cx, I->global); - JS::RootedValue rval(I->cx); { // Scope for JSAutoCompartment - JSAutoCompartment ac(I->cx, global); - JS_InitStandardClasses(I->cx, global); + JSAutoCompartment ac(I->cx, I->global); - ok = JS_EvaluateScript(I->cx, global, + ok = JS_EvaluateScript(I->cx, I->global, script, strlen(script), filename, lineno, rval.address()); if (!ok) @@ -139,24 +514,25 @@ static struct JSIO_s _mozjs17 = { mozFini, mozInit, mozRun }; JSIO_t mozjs17 = &_mozjs17; -#if defined(RPMJS_SELF_TEST) +#if defined(RPMJSS_SELF_TEST) +struct rpmjss_s _jss; +rpmjss jss = &_jss; + /*==============================================================*/ int main(int argc, const char *argv[]) { int rc = 0; - JSI_t I = (JSI_t) mozInit(js); - js->I = I; + JSI_t I = (JSI_t) mozInit(jss); + jss->I = I; { const char *script = "'hello'+'world, it is '+new Date()"; - const char *filename = "noname"; - int lineno = 1; - rc = mozRun(js, script, filename, lineno); + rc = mozRun(jss, script, __FILE__, __LINE__); } - mozFini(js); + mozFini(jss); return rc; } -#endif /* RPMJS_SELF_TEST */ +#endif /* RPMJSS_SELF_TEST */ @@ . patch -p0 <<'@@ .' Index: rpm/rpmio/rpmjs185.cpp ============================================================================ $ cvs diff -u -r1.1.2.3 -r1.1.2.4 rpmjs185.cpp --- rpm/rpmio/rpmjs185.cpp 22 Jun 2017 17:35:24 -0000 1.1.2.3 +++ rpm/rpmio/rpmjs185.cpp 23 Jun 2017 03:39:43 -0000 1.1.2.4 @@ -2,14 +2,14 @@ // #define __STDC_LIMIT_MACROS // #include <stdint.h> +#pragma GCC diagnostic ignored "-Winvalid-offsetof" + #include "system.h" -#define js jsns #include "jsapi.h" -#undef js -#define _RPMJS_INTERNAL -#include <rpmjs.h> +#define _RPMJSS_INTERNAL +#include <rpmjss.h> #include "debug.h" @@ -26,8 +26,12 @@ JS_ConvertStub, }; -struct rpmjs_s _js; -rpmjs js = &_js; +static int rpmjss_nopens; + +static int _rpmjss185_debug; +#define SPEW(_fmt, ...) \ + if (_rpmjss185_debug) \ + fprintf(stderr, _fmt, __VA_ARGS__) /*==============================================================*/ typedef struct JSI_s * JSI_t; @@ -38,7 +42,7 @@ }; static void -rpmjsReportError(JSContext *cx, const char *message, JSErrorReport *report) +rpmjssReportError(JSContext *cx, const char *message, JSErrorReport *report) { fprintf(stderr, "%s:%u:%s\n", report->filename ? report->filename : "<no filename=\"filename\">", @@ -46,11 +50,355 @@ } /*==============================================================*/ -static int rpmjs_nopens; +static JSBool compileOnly = JS_FALSE; + +static JSBool +Version(JSContext *cx, uintN argc, jsval *vp) +{ + jsval *argv = JS_ARGV(cx, vp); + if (argc > 0 && JSVAL_IS_INT(argv[0])) + *vp = INT_TO_JSVAL(JS_SetVersion(cx, (JSVersion) JSVAL_TO_INT(argv[0]))); + else + *vp = INT_TO_JSVAL(JS_GetVersion(cx)); + return JS_TRUE; +} + +static JSBool +Load(JSContext *cx, uintN argc, jsval *vp) +{ + jsval *argv = JS_ARGV(cx, vp); + JSObject *thisobj = JS_THIS_OBJECT(cx, vp); + if (!thisobj) + return JS_FALSE; + + for (uintN i = 0; i < argc; i++) { + JSString *str = JS_ValueToString(cx, argv[i]); + if (!str) + return false; + argv[i] = STRING_TO_JSVAL(str); + JSAutoByteString filename(cx, str); + if (!filename) + return JS_FALSE; + errno = 0; + uint32 oldopts = JS_GetOptions(cx); + JS_SetOptions(cx, oldopts | JSOPTION_COMPILE_N_GO | JSOPTION_NO_SCRIPT_RVAL); + JSObject *scriptObj = JS_CompileFile(cx, thisobj, filename.ptr()); + JS_SetOptions(cx, oldopts); + if (!scriptObj) + return false; + + if (!compileOnly && !JS_ExecuteScript(cx, thisobj, scriptObj, NULL)) + return false; + } + + return true; +} + +static JSBool +Evaluate(JSContext *cx, uintN argc, jsval *vp) +{ + if (argc != 1 || !JSVAL_IS_STRING(JS_ARGV(cx, vp)[0])) { +#ifdef FIXME + JS_ReportErrorNumber(cx, my_GetErrorMessage, NULL, + (argc != 1) ? JSSMSG_NOT_ENOUGH_ARGS : JSSMSG_INVALID_ARGS, + "evaluate"); +#endif + return false; + } + + JSString *code = JSVAL_TO_STRING(JS_ARGV(cx, vp)[0]); + + size_t codeLength; + const jschar *codeChars = JS_GetStringCharsAndLength(cx, code, &codeLength); + if (!codeChars) + return false; + + JSObject *thisobj = JS_THIS_OBJECT(cx, vp); + if (!thisobj) + return false; + + if ((JS_GET_CLASS(cx, thisobj)->flags & JSCLASS_IS_GLOBAL) != JSCLASS_IS_GLOBAL) { +#ifdef FIXME + JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_UNEXPECTED_TYPE, + "this-value passed to evaluate()", "not a global object"); +#endif + return false; + } + + JS_SET_RVAL(cx, vp, JSVAL_VOID); + return JS_EvaluateUCScript(cx, thisobj, codeChars, codeLength, "@evaluate", 0, NULL); +} + +static JSString * +FileAsString(JSContext *cx, const char *pathname) +{ + FILE *file; + JSString *str = NULL; + size_t len, cc; + char *buf; + + file = fopen(pathname, "rb"); + if (!file) { + JS_ReportError(cx, "can't open %s: %s", pathname, strerror(errno)); + return NULL; + } + + if (fseek(file, 0, SEEK_END) == EOF) { + JS_ReportError(cx, "can't seek end of %s", pathname); + } else { + len = ftell(file); + if (fseek(file, 0, SEEK_SET) == EOF) { + JS_ReportError(cx, "can't seek start of %s", pathname); + } else { + buf = (char*) JS_malloc(cx, len + 1); + if (buf) { + cc = fread(buf, 1, len, file); + if (cc != len) { + JS_ReportError(cx, "can't read %s: %s", pathname, + (ptrdiff_t(cc) < 0) ? strerror(errno) : "short read"); + } else { + len = (size_t)cc; + str = JS_NewStringCopyN(cx, buf, len); + } + JS_free(cx, buf); + } + } + } + fclose(file); + + return str; +} + +/* + * Function to run scripts and return compilation + execution time. Semantics + * are closely modelled after the equivalent function in WebKit, as this is used + * to produce benchmark timings by SunSpider. + */ +static JSBool +Run(JSContext *cx, uintN argc, jsval *vp) +{ + if (argc != 1) { +#ifdef FIXME + JS_ReportErrorNumber(cx, my_GetErrorMessage, NULL, JSSMSG_INVALID_ARGS, "run"); +#endif + return false; + } + + JSObject *thisobj = JS_THIS_OBJECT(cx, vp); + if (!thisobj) + return false; + + jsval *argv = JS_ARGV(cx, vp); + JSString *str = JS_ValueToString(cx, argv[0]); + if (!str) + return false; + argv[0] = STRING_TO_JSVAL(str); + JSAutoByteString filename(cx, str); + if (!filename) + return false; + + const jschar *ucbuf = NULL; + size_t buflen; + str = FileAsString(cx, filename.ptr()); + if (str) + ucbuf = JS_GetStringCharsAndLength(cx, str, &buflen); + if (!ucbuf) + return false; + + JS::Anchor<JSString *> a_str(str); + uint32 oldopts = JS_GetOptions(cx); + JS_SetOptions(cx, oldopts | JSOPTION_COMPILE_N_GO | JSOPTION_NO_SCRIPT_RVAL); + +#ifdef FIXME + int64 startClock = PRMJ_Now(); +#endif + JSObject *scriptObj = JS_CompileUCScript(cx, thisobj, ucbuf, buflen, filename.ptr(), 1); + JS_SetOptions(cx, oldopts); + if (!scriptObj || !JS_ExecuteScript(cx, thisobj, scriptObj, NULL)) + return false; + +#ifdef FIXME + int64 endClock = PRMJ_Now(); + JS_SET_RVAL(cx, vp, DOUBLE_TO_JSVAL((endClock - startClock) / double(PRMJ_USEC_PER_MSEC))); +#endif + return true; +} + +#ifdef NOTYET +/* + * function readline() + * Provides a hook for scripts to read a line from stdin. + */ +static JSBool +ReadLine(JSContext *cx, uintN argc, jsval *vp) +{ +#define BUFSIZE 256 + FILE *from; + char *buf, *tmp; + size_t bufsize, buflength, gotlength; + JSBool sawNewline; + JSString *str; + + from = stdin; + buflength = 0; + bufsize = BUFSIZE; + buf = (char *) JS_malloc(cx, bufsize); + if (!buf) + return JS_FALSE; + + sawNewline = JS_FALSE; + while ((gotlength = + js_fgets(buf + buflength, bufsize - buflength, from)) > 0) { + buflength += gotlength; + + /* Are we done? */ + if (buf[buflength - 1] == '\n') { + buf[buflength - 1] = '\0'; + sawNewline = JS_TRUE; + break; + } else if (buflength < bufsize - 1) { + break; + } + + /* Else, grow our buffer for another pass. */ + bufsize *= 2; + if (bufsize > buflength) { + tmp = (char *) JS_realloc(cx, buf, bufsize); + } else { + JS_ReportOutOfMemory(cx); + tmp = NULL; + } + + if (!tmp) { + JS_free(cx, buf); + return JS_FALSE; + } + + buf = tmp; + } + + /* Treat the empty string specially. */ + if (buflength == 0) { + *vp = feof(from) ? JSVAL_NULL : JS_GetEmptyStringValue(cx); + JS_free(cx, buf); + return JS_TRUE; + } + + /* Shrink the buffer to the real size. */ + tmp = (char *) JS_realloc(cx, buf, buflength); + if (!tmp) { + JS_free(cx, buf); + return JS_FALSE; + } + + buf = tmp; -static void mozFini(rpmjs js) + /* + * Turn buf into a JSString. Note that buflength includes the trailing null + * character. + */ + str = JS_NewStringCopyN(cx, buf, sawNewline ? buflength - 1 : buflength); + JS_free(cx, buf); + if (!str) + return JS_FALSE; + + *vp = STRING_TO_JSVAL(str); + return JS_TRUE; +} +#endif + +static JSBool +PutStr(JSContext *cx, uintN argc, jsval *vp) { - JSI_t I = (JSI_t) js->I; + FILE * gOutFile = stdout; + jsval * argv = JS_ARGV(cx, vp); + JSString *str; + char *bytes; + + if (argc != 0) { + str = JS_ValueToString(cx, argv[0]); + if (!str) + return JS_FALSE; + bytes = JS_EncodeString(cx, str); + if (!bytes) + return JS_FALSE; + fputs(bytes, gOutFile); + JS_free(cx, bytes); + fflush(gOutFile); + } + + JS_SET_RVAL(cx, vp, JSVAL_VOID); + return JS_TRUE; +} + +static JSBool +Now(JSContext *cx, uintN argc, jsval *vp) +{ +#ifdef FIXME + jsdouble now = PRMJ_Now() / double(PRMJ_USEC_PER_MSEC); +#else + jsdouble now = time(NULL) * 1000; +#endif + JS_SET_RVAL(cx, vp, DOUBLE_TO_JSVAL(now)); + return true; +} + +static JSBool +Print(JSContext *cx, uintN argc, jsval *vp) +{ + FILE * gOutFile = stdout; + jsval * argv = JS_ARGV(cx, vp); + uintN i; + JSString *str; + char *bytes; + + for (i = 0; i < argc; i++) { + str = JS_ValueToString(cx, argv[i]); + if (!str) + return JS_FALSE; + bytes = JS_EncodeString(cx, str); + if (!bytes) + return JS_FALSE; + fprintf(gOutFile, "%s%s", i ? " " : "", bytes); + JS_free(cx, bytes); + } + + fputc('\n', gOutFile); + fflush(gOutFile); + + JS_SET_RVAL(cx, vp, JSVAL_VOID); + return JS_TRUE; +} + +static JSBool +Require(JSContext *cx, uintN argc, jsval *vp) +{ + jsval * argv = JS_ARGV(cx, vp); +SPEW("==> %s(%p,%p[%u],%p)\n", __FUNCTION__, cx, argv, (unsigned)argc, vp); + + JS_SET_RVAL(cx, vp, JSVAL_VOID); + return JS_TRUE; +} + +static JSFunctionSpec global_functions[] = { + JS_FN("version", Version, 0,0), + JS_FN("load", Load, 1,0), + JS_FN("evaluate", Evaluate, 1,0), + JS_FN("run", Run, 1,0), +#ifdef NOTYET + JS_FN("readline", ReadLine, 0,0), +#endif + JS_FN("print", Print, 0,0), + JS_FN("putstr", PutStr, 0,0), + JS_FN("dateNow", Now, 0,0), + JS_FS("require", Require, 0,0), + JS_FS_END +}; + +/*==============================================================*/ +static void mozFini(rpmjss jss) +{ + JSI_t I = (JSI_t) jss->I; if (I->cx) JS_DestroyContext(I->cx); @@ -60,27 +408,26 @@ JS_DestroyRuntime(I->rt); I->rt = NULL; - if (--rpmjs_nopens <= 0) { + if (--rpmjss_nopens <= 0) { JS_ShutDown(); - rpmjs_nopens = 0; + rpmjss_nopens = 0; } free(I); } -static void * mozInit(rpmjs js) +static void * mozInit(rpmjss jss) { JSI_t I = NULL; - uint32_t flags = js->flags; + uint32_t flags = jss->flags; static uint32 _maxbytes = 8L * 1024L * 1024L; static size_t _stackChunkSize = 8192; JSClass * _clasp = (JSClass *)&global_class; -#ifdef NOTYET JSFunctionSpec * _functions = global_functions; -#endif JSPrincipals * _principals = NULL; + JSBool ok; - if (rpmjs_nopens++ == 0) { + if (rpmjss_nopens++ == 0) { #ifdef NOTYET /* XXX collides with ancient JS_NewRuntime */ JS_Init(); #endif @@ -91,27 +438,38 @@ I->rt = JS_NewRuntime(_maxbytes); assert(I->rt); - JS_SetRuntimePrivate(I->rt, (void *)js); + JS_SetRuntimePrivate(I->rt, (void *)jss); I->cx = JS_NewContext(I->rt, _stackChunkSize); assert(I->cx); - JS_SetContextPrivate(I->cx, (void *)js); + JS_SetContextPrivate(I->cx, (void *)jss); JS_SetOptions(I->cx, JSOPTION_VAROBJFIX | JSOPTION_JIT | JSOPTION_METHODJIT); JS_SetVersion(I->cx, JSVERSION_LATEST); - JS_SetErrorReporter(I->cx, rpmjsReportError); + JS_SetErrorReporter(I->cx, rpmjssReportError); I->global = JS_NewCompartmentAndGlobalObject(I->cx, _clasp, _principals); +assert(I->global); + + ok = JS_InitStandardClasses(I->cx, I->global); +assert(ok); +#ifdef JS_HAS_CTYPES + ok = JS_InitCTypesClass(I->cx, I->global); +assert(ok); +#endif + + ok = JS_DefineFunctions(I->cx, I->global, _functions); +assert(ok); return I; } -static int mozRun(rpmjs js, +static int mozRun(rpmjss jss, const char * script, const char * filename, int lineno) { - JSI_t I = (JSI_t) js->I; + JSI_t I = (JSI_t) jss->I; JSClass * _clasp = (JSClass *)&global_class; #ifdef NOTYET @@ -128,8 +486,6 @@ if (!ac.enter(I->cx, I->global)) return 1; #endif - - JS_InitStandardClasses(I->cx, I->global); ok = JS_EvaluateScript(I->cx, I->global, script, strlen(script), filename, lineno, @@ -146,24 +502,25 @@ static struct JSIO_s _mozjs185 = { mozFini, mozInit, mozRun }; JSIO_t mozjs185 = &_mozjs185; -#if defined(RPMJS_SELF_TEST) +#if defined(RPMJSS_SELF_TEST) +struct rpmjss_s _jss; +rpmjss jss = &_jss; + /*==============================================================*/ int main(int argc, const char *argv[]) { int rc = 0; - JSI_t I = (JSI_t) mozInit(js); - js->I = I; + JSI_t I = (JSI_t) mozInit(jss); + jss->I = I; { const char *script = "'hello'+'world, it is '+new Date()"; - const char *filename = "noname"; - int lineno = 1; - rc = mozRun(js, script, filename, lineno); + rc = mozRun(jss, script, __FILE__, __LINE__); } - mozFini(js); + mozFini(jss); return rc; } -#endif /* RPMJS_SELF_TEST */ +#endif /* RPMJSS_SELF_TEST */ @@ . patch -p0 <<'@@ .' Index: rpm/rpmio/rpmjs24.cpp ============================================================================ $ cvs diff -u -r1.1.2.4 -r1.1.2.5 rpmjs24.cpp --- rpm/rpmio/rpmjs24.cpp 22 Jun 2017 17:35:24 -0000 1.1.2.4 +++ rpm/rpmio/rpmjs24.cpp 23 Jun 2017 03:39:43 -0000 1.1.2.5 @@ -2,14 +2,14 @@ // #define __STDC_LIMIT_MACROS // #include <stdint.h> +#pragma GCC diagnostic ignored "-Winvalid-offsetof" + #include "system.h" -#define js jsns #include "jsapi.h" -#undef js -#define _RPMJS_INTERNAL -#include <rpmjs.h> +#define _RPMJSS_INTERNAL +#include <rpmjss.h> #include "debug.h" @@ -28,8 +28,12 @@ #define JS_Init() -struct rpmjs_s _js; -rpmjs js = &_js; +static int rpmjss_nopens; + +static int _rpmjss24_debug; +#define SPEW(_fmt, ...) \ + if (_rpmjss24_debug) \ + fprintf(stderr, _fmt, __VA_ARGS__) /*==============================================================*/ typedef struct JSI_s * JSI_t; @@ -40,7 +44,7 @@ }; static void -rpmjsReportError(JSContext *cx, const char *message, JSErrorReport *report) +rpmjssReportError(JSContext *cx, const char *message, JSErrorReport *report) { fprintf(stderr, "%s:%u:%s\n", report->filename ? report->filename : "<no filename=\"filename\">", @@ -48,11 +52,9 @@ } /*==============================================================*/ -static int rpmjs_nopens; - -static void mozFini(rpmjs js) +static void mozFini(rpmjss jss) { - JSI_t I = (JSI_t) js->I; + JSI_t I = (JSI_t) jss->I; if (I->cx) JS_DestroyContext(I->cx); @@ -62,22 +64,22 @@ JS_DestroyRuntime(I->rt); I->rt = NULL; - if (--rpmjs_nopens <= 0) { + if (--rpmjss_nopens <= 0) { JS_ShutDown(); - rpmjs_nopens = 0; + rpmjss_nopens = 0; } free(I); } -static void * mozInit(rpmjs js) +static void * mozInit(rpmjss jss) { JSI_t I = NULL; - uint32_t flags = js->flags; + uint32_t flags = jss->flags; static uint32_t _maxbytes = 8L * 1024L * 1024L; static size_t _stackChunkSize = 8192; - if (rpmjs_nopens++ == 0) + if (rpmjss_nopens++ == 0) JS_Init(); I = (JSI_t) calloc(1, sizeof(*I)); @@ -85,19 +87,26 @@ I->rt = JS_NewRuntime(_maxbytes, JS_USE_HELPER_THREADS); assert(I->rt); - JS_SetRuntimePrivate(I->rt, (void *)js); + JS_SetRuntimePrivate(I->rt, (void *)jss); I->cx = JS_NewContext(I->rt, _stackChunkSize); assert(I->cx); - JS_SetContextPrivate(I->cx, (void *)js); + JS_SetContextPrivate(I->cx, (void *)jss); + + JS_SetOptions(I->cx, + JSOPTION_VAROBJFIX); +#ifdef NOTYET + JS_SetVersion(I->cx, JSVERSION_LATEST); +#endif + JS_SetErrorReporter(I->cx, rpmjssReportError); return I; } -static int mozRun(rpmjs js, +static int mozRun(rpmjss jss, const char * script, const char * filename, int lineno) { - JSI_t I = (JSI_t) js->I; + JSI_t I = (JSI_t) jss->I; JSClass * _clasp = (JSClass *)&global_class; #ifdef NOTYET @@ -138,24 +147,25 @@ static struct JSIO_s _mozjs24 = { mozFini, mozInit, mozRun }; JSIO_t mozjs24 = &_mozjs24; -#if defined(RPMJS_SELF_TEST) +#if defined(RPMJSS_SELF_TEST) +struct rpmjss_s _jss; +rpmjss jss = &_jss; + /*==============================================================*/ int main(int argc, const char *argv[]) { int rc = 0; - JSI_t I = (JSI_t) mozInit(js); - js->I = I; + JSI_t I = (JSI_t) mozInit(jss); + jss->I = I; { const char *script = "'hello'+'world, it is '+new Date()"; - const char *filename = "noname"; - int lineno = 1; - rc = mozRun(js, script, filename, lineno); + rc = mozRun(jss, script, __FILE__, __LINE__); } - mozFini(js); + mozFini(jss); return rc; } -#endif /* RPMJS_SELF_TEST */ +#endif /* RPMJSS_SELF_TEST */ @@ . patch -p0 <<'@@ .' Index: rpm/rpmio/rpmjs31.cpp ============================================================================ $ cvs diff -u -r1.1.2.4 -r1.1.2.5 rpmjs31.cpp --- rpm/rpmio/rpmjs31.cpp 22 Jun 2017 17:35:24 -0000 1.1.2.4 +++ rpm/rpmio/rpmjs31.cpp 23 Jun 2017 03:39:43 -0000 1.1.2.5 @@ -2,14 +2,14 @@ // #define __STDC_LIMIT_MACROS // #include <stdint.h> +#pragma GCC diagnostic ignored "-Winvalid-offsetof" + #include "system.h" -#define js jsns #include "jsapi.h" -#undef js -#define _RPMJS_INTERNAL -#include <rpmjs.h> +#define _RPMJSS_INTERNAL +#include <rpmjss.h> #include "debug.h" @@ -31,8 +31,12 @@ JS_GlobalObjectTraceHook }; -struct rpmjs_s _js; -rpmjs js = &_js; +static int rpmjss_nopens; + +static int _rpmjs31_debug; +#define SPEW(_fmt, ...) \ + if (_rpmjss31_debug) \ + fprintf(stderr, _fmt, __VA_ARGS__) /*==============================================================*/ typedef struct JSI_s * JSI_t; @@ -43,7 +47,7 @@ }; static void -rpmjsReportError(JSContext *cx, const char *message, JSErrorReport *report) +rpmjssReportError(JSContext *cx, const char *message, JSErrorReport *report) { fprintf(stderr, "%s:%u:%s\n", report->filename ? report->filename : "<no filename=\"filename\">", @@ -51,11 +55,9 @@ } /*==============================================================*/ -static int rpmjs_nopens; - -static void mozFini(rpmjs js) +static void mozFini(rpmjss jss) { - JSI_t I = (JSI_t) js->I; + JSI_t I = (JSI_t) jss->I; if (I->cx) JS_DestroyContext(I->cx); @@ -65,22 +67,22 @@ JS_DestroyRuntime(I->rt); I->rt = NULL; - if (--rpmjs_nopens <= 0) { + if (--rpmjss_nopens <= 0) { JS_ShutDown(); - rpmjs_nopens = 0; + rpmjss_nopens = 0; } free(I); } -static void * mozInit(rpmjs js) +static void * mozInit(rpmjss jss) { JSI_t I = NULL; - uint32_t flags = js->flags; + uint32_t flags = jss->flags; static uint32_t _maxbytes = 8L * 1024L * 1024L; static size_t _stackChunkSize = 8192; - if (rpmjs_nopens++ == 0) + if (rpmjss_nopens++ == 0) JS_Init(); I = (JSI_t) calloc(1, sizeof(*I)); @@ -88,19 +90,21 @@ I->rt = JS_NewRuntime(_maxbytes, JS_USE_HELPER_THREADS); assert(I->rt); - JS_SetRuntimePrivate(I->rt, (void *)js); + JS_SetRuntimePrivate(I->rt, (void *)jss); I->cx = JS_NewContext(I->rt, _stackChunkSize); assert(I->cx); - JS_SetContextPrivate(I->cx, (void *)js); + JS_SetContextPrivate(I->cx, (void *)jss); + + JS_SetErrorReporter(I->cx, rpmjssReportError); return I; } -static int mozRun(rpmjs js, +static int mozRun(rpmjss jss, const char * script, const char * filename, int lineno) { - JSI_t I = (JSI_t) js->I; + JSI_t I = (JSI_t) jss->I; JSClass * _clasp = (JSClass *)&global_class; #ifdef NOTYET @@ -140,24 +144,25 @@ static struct JSIO_s _mozjs31 = { mozFini, mozInit, mozRun }; JSIO_t mozjs31 = &_mozjs31; -#if defined(RPMJS_SELF_TEST) +#if defined(RPMJSS_SELF_TEST) +struct rpmjss_s _jss; +rpmjss jss = &_jss; + /*==============================================================*/ int main(int argc, const char *argv[]) { int rc = 0; - JSI_t I = (JSI_t) mozInit(js); - js->I = I; + JSI_t I = (JSI_t) mozInit(jss); + jss->I = I; { const char *script = "'hello'+'world, it is '+new Date()"; - const char *filename = "noname"; - int lineno = 1; - rc = mozRun(js, script, filename, lineno); + rc = mozRun(jss, script, __FILE__, __LINE__); } - mozFini(js); + mozFini(jss); return rc; } -#endif /* RPMJS_SELF_TEST */ +#endif /* RPMJSS_SELF_TEST */ @@ . patch -p0 <<'@@ .' Index: rpm/rpmio/rpmjs38.cpp ============================================================================ $ cvs diff -u -r1.1.2.4 -r1.1.2.5 rpmjs38.cpp --- rpm/rpmio/rpmjs38.cpp 22 Jun 2017 17:35:24 -0000 1.1.2.4 +++ rpm/rpmio/rpmjs38.cpp 23 Jun 2017 03:39:43 -0000 1.1.2.5 @@ -2,14 +2,14 @@ // #define __STDC_LIMIT_MACROS // #include <stdint.h> +#pragma GCC diagnostic ignored "-Winvalid-offsetof" + #include "system.h" -#define js jsns #include "jsapi.h" -#undef js -#define _RPMJS_INTERNAL -#include <rpmjs.h> +#define _RPMJSS_INTERNAL +#include <rpmjss.h> #include "debug.h" @@ -31,8 +31,12 @@ JS_GlobalObjectTraceHook }; -struct rpmjs_s _js; -rpmjs js = &_js; +static int rpmjss_nopens; + +static int _rpmjss38_debug; +#define SPEW(_fmt, ...) \ + if (_rpmjss38_debug) \ + fprintf(stderr, _fmt, __VA_ARGS__) /*==============================================================*/ typedef struct JSI_s * JSI_t; @@ -43,7 +47,7 @@ }; static void -rpmjsReportError(JSContext *cx, const char *message, JSErrorReport *report) +rpmjssReportError(JSContext *cx, const char *message, JSErrorReport *report) { fprintf(stderr, "%s:%u:%s\n", report->filename ? report->filename : "<no filename=\"filename\">", @@ -51,11 +55,9 @@ } /*==============================================================*/ -static int rpmjs_nopens; - -static void mozFini(rpmjs js) +static void mozFini(rpmjss jss) { - JSI_t I = (JSI_t) js->I; + JSI_t I = (JSI_t) jss->I; if (I->cx) JS_DestroyContext(I->cx); @@ -65,22 +67,22 @@ JS_DestroyRuntime(I->rt); I->rt = NULL; - if (--rpmjs_nopens <= 0) { + if (--rpmjss_nopens <= 0) { JS_ShutDown(); - rpmjs_nopens = 0; + rpmjss_nopens = 0; } free(I); } -static void * mozInit(rpmjs js) +static void * mozInit(rpmjss jss) { JSI_t I = NULL; - uint32_t flags = js->flags; + uint32_t flags = jss->flags; static uint32_t _maxbytes = 8L * 1024L * 1024L; static size_t _stackChunkSize = 8192; - if (rpmjs_nopens++ == 0) + if (rpmjss_nopens++ == 0) JS_Init(); I = (JSI_t) calloc(1, sizeof(*I)); @@ -88,19 +90,21 @@ I->rt = JS_NewRuntime(_maxbytes); assert(I->rt); - JS_SetRuntimePrivate(I->rt, (void *)js); + JS_SetRuntimePrivate(I->rt, (void *)jss); I->cx = JS_NewContext(I->rt, _stackChunkSize); assert(I->cx); - JS_SetContextPrivate(I->cx, (void *)js); + JS_SetContextPrivate(I->cx, (void *)jss); + + JS_SetErrorReporter(I->rt, rpmjssReportError); return I; } -static int mozRun(rpmjs js, +static int mozRun(rpmjss jss, const char * script, const char * filename, int lineno) { - JSI_t I = (JSI_t) js->I; + JSI_t I = (JSI_t) jss->I; JSClass * _clasp = (JSClass *)&global_class; #ifdef NOTYET @@ -140,24 +144,25 @@ static struct JSIO_s _mozjs38 = { mozFini, mozInit, mozRun }; JSIO_t mozjs38 = &_mozjs38; -#if defined(RPMJS_SELF_TEST) +#if defined(RPMJSS_SELF_TEST) +struct rpmjss_s _jss; +rpmjss jss = &_jss; + /*==============================================================*/ int main(int argc, const char *argv[]) { int rc = 0; - JSI_t I = (JSI_t) mozInit(js); - js->I = I; + JSI_t I = (JSI_t) mozInit(jss); + jss->I = I; { const char *script = "'hello'+'world, it is '+new Date()"; - const char *filename = "noname"; - int lineno = 1; - rc = mozRun(js, script, filename, lineno); + rc = mozRun(jss, script, __FILE__, __LINE__); } - mozFini(js); + mozFini(jss); return rc; } -#endif /* RPMJS_SELF_TEST */ +#endif /* RPMJSS_SELF_TEST */ @@ . patch -p0 <<'@@ .' Index: rpm/rpmio/rpmjs45.cpp ============================================================================ $ cvs diff -u -r1.1.2.5 -r1.1.2.6 rpmjs45.cpp --- rpm/rpmio/rpmjs45.cpp 23 Jun 2017 00:43:55 -0000 1.1.2.5 +++ rpm/rpmio/rpmjs45.cpp 23 Jun 2017 03:39:43 -0000 1.1.2.6 @@ -6,18 +6,18 @@ #include "system.h" -#define js jsns #include "jsapi.h" #include "js/Initialization.h" -#undef js +#include "js/Conversions.h" +using namespace JS; +using namespace js; -#define _RPMJS_INTERNAL -#include <rpmjs.h> +#define _RPMJSS_INTERNAL +#include <rpmjss.h> #include "debug.h" /*==============================================================*/ -#ifdef NOTYET /* XXX HandleObject and HandleId */ static bool global_enumerate(JSContext* cx, HandleObject obj) { @@ -43,7 +43,6 @@ { return JS_MayResolveStandardClass(names, id, maybeObj); } -#endif /* NOTYET */ static JSClass global_class = { "global", @@ -52,15 +51,9 @@ nullptr, nullptr, nullptr, -#ifdef NOTYET /* XXX HandleObject and HandleId */ global_enumerate, global_resolve, global_mayResolve, -#else - nullptr, - nullptr, - nullptr, -#endif nullptr, nullptr, nullptr, @@ -68,11 +61,11 @@ JS_GlobalObjectTraceHook }; -static int rpmjs_nopens; +static int rpmjss_nopens; -static int _rpmjs45_debug; +static int _rpmjss45_debug; #define SPEW(_fmt, ...) \ - if (_rpmjs45_debug) \ + if (_rpmjss45_debug) \ fprintf(stderr, _fmt, __VA_ARGS__) /*==============================================================*/ @@ -84,17 +77,652 @@ }; static void -rpmjsReportError(JSContext *cx, const char *message, JSErrorReport *report) +rpmjssReportError(JSContext *cx, const char *message, JSErrorReport *report) { fprintf(stderr, "%s:%u:%s\n", report->filename ? report->filename : "<no filename=\"filename\">", (unsigned int) report->lineno, message); } +static void +rpmjssOOMCallback(JSContext* cx, void* data) +{ +#ifdef NOTYET + // If a script is running, the engine is about to throw the string "out of + // memory", which may or may not be caught. Otherwise the engine will just + // unwind and return null/false, with no exception set. + if (!JS_IsRunning(cx)) + GetShellRuntime(cx)->gotError = true; +#endif +} + +enum JSShellErrNum { +#define MSG_DEF(name, count, exception, format) \ + name, +#include "jsshell.msg" +#undef MSG_DEF + JSShellErr_Limit +}; + +static const JSErrorFormatString jsShell_ErrorFormatString[JSShellErr_Limit] = { +#define MSG_DEF(name, count, exception, format) \ + { format, count, JSEXN_ERR } , +#include "jsshell.msg" +#undef MSG_DEF +}; + +const JSErrorFormatString* +my_GetErrorMessage(void* userRef, const unsigned errorNumber) +{ + if (errorNumber == 0 || errorNumber >= JSShellErr_Limit) + return nullptr; + + return &jsShell_ErrorFormatString[errorNumber]; +} + +/*==============================================================*/ +static bool compileOnly = false; + +static bool +Version(JSContext *cx, unsigned argc, Value* vp) +{ + CallArgs args = CallArgsFromVp(argc, vp); + JSVersion origVersion = JS_GetVersion(cx); + if (args.length() == 0 || args[0].isUndefined()) { + /* Get version. */ + args.rval().setInt32(origVersion); + } else { + /* Set version. */ + int32_t v = -1; + if (args[0].isInt32()) { + v = args[0].toInt32(); + } else + if (args[0].isDouble()) { + double fv = args[0].toDouble(); + int32_t fvi; + if (JS_DoubleIsInt32(fv, &fvi)) + v = fvi; + } + if (v < 0 || v > JSVERSION_LATEST) { + JS_ReportErrorNumber(cx, my_GetErrorMessage, nullptr, JSSMSG_INVALID_ARGS, "version"); + return false; + } + JS_SetVersionForCompartment(js::GetContextCompartment(cx), JSVersion(v)); + args.rval().setInt32(origVersion); + } + return true; +} + +#ifdef NOTYET +static bool +LoadScript(JSContext* cx, unsigned argc, Value* vp, bool scriptRelative) +{ + CallArgs args = CallArgsFromVp(argc, vp); + + RootedString str(cx); + for (unsigned i = 0; i < args.length(); i++) { + str = JS::ToString(cx, args[i]); + if (!str) { + JS_ReportErrorNumber(cx, my_GetErrorMessage, nullptr, JSSMSG_INVALID_ARGS, "load"); + return false; + } + str = ResolvePath(cx, str, scriptRelative ? ScriptRelative : RootRelative); + if (!str) { + JS_ReportError(cx, "unable to resolve path"); + return false; + } + JSAutoByteString filename(cx, str); + if (!filename) + return false; + errno = 0; + CompileOptions opts(cx); + opts.setIntroductionType("js shell load") + .setUTF8(true) + .setIsRunOnce(true) + .setNoScriptRval(true); + RootedScript script(cx); + RootedValue unused(cx); + if ((compileOnly && !Compile(cx, opts, filename.ptr(), &script)) || + !Evaluate(cx, opts, filename.ptr(), &unused)) + { + return false; + } + } + + args.rval().setUndefined(); + return true; +} + +static bool +Load(JSContext* cx, unsigned argc, Value* vp) +{ + return LoadScript(cx, argc, vp, false); +} +#endif /* NOTYET */ + +static const JSFunctionSpec global_functions[] = { + JS_FN("version", Version, 0,0), +#ifdef NOTYET + JS_FN("load", Load, 1,0), + JS_FN("evaluate", Evaluate, 1,0), + JS_FN("run", Run, 1,0), +#ifdef NOTYET + JS_FN("readline", ReadLine, 0,0), +#endif + JS_FN("print", Print, 0,0), + JS_FN("putstr", PutStr, 0,0), + JS_FN("dateNow", Now, 0,0), + JS_FS("require", Require, 0,0), +#endif + JS_FS_END +}; + +/*==============================================================*/ +#ifdef NOTYET +static const JSFunctionSpecWithHelp shell_functions[] = { + JS_FN_HELP("version", Version, 0, 0, +"version([number])", +" Get or force a script compilation version number."), + + JS_FN_HELP("options", Options, 0, 0, +"options([option ...])", +" Get or toggle JavaScript options."), + + JS_FN_HELP("load", Load, 1, 0, +"load(['foo.js' ...])", +" Load files named by string arguments. Filename is relative to the\n" +" current working directory."), + + JS_FN_HELP("loadRelativeToScript", LoadScriptRelativeToScript, 1, 0, +"loadRelativeToScript(['foo.js' ...])", +" Load files named by string arguments. Filename is relative to the\n" +" calling script."), + + JS_FN_HELP("evaluate", Evaluate, 2, 0, +"evaluate(code[, options])", +" Evaluate code as though it were the contents of a file.\n" +" options is an optional object that may have these properties:\n" +" isRunOnce: use the isRunOnce compiler option (default: false)\n" +" noScriptRval: use the no-script-rval compiler option (default: false)\n" +" fileName: filename for error messages and debug info\n" +" lineNumber: starting line number for error messages and debug info\n" +" columnNumber: starting column number for error messages and debug info\n" +" global: global in which to execute the code\n" +" newContext: if true, create and use a new cx (default: false)\n" +" saveFrameChain: if true, save the frame chain before evaluating code\n" +" and restore it afterwards\n" +" catchTermination: if true, catch termination (failure without\n" +" an exception value, as for slow scripts or out-of-memory)\n" +" and return 'terminated'\n" +" element: if present with value |v|, convert |v| to an object |o| and\n" +" mark the source as being attached to the DOM element |o|. If the\n" +" property is omitted or |v| is null, don't attribute the source to\n" +" any DOM element.\n" +" elementAttributeName: if present and not undefined, the name of\n" +" property of 'element' that holds this code. This is what\n" +" Debugger.Source.prototype.elementAttributeName returns.\n" +" sourceMapURL: if present with value |v|, convert |v| to a string, and\n" +" provide that as the code's source map URL. If omitted, attach no\n" +" source map URL to the code (although the code may provide one itself,\n" +" via a //#sourceMappingURL comment).\n" +" sourceIsLazy: if present and true, indicates that, after compilation, \n" + "script source should not be cached by the JS engine and should be \n" + "lazily loaded from the embedding as-needed.\n" +" loadBytecode: if true, and if the source is a CacheEntryObject,\n" +" the bytecode would be loaded and decoded from the cache entry instead\n" +" of being parsed, then it would be executed as usual.\n" +" saveBytecode: if true, and if the source is a CacheEntryObject,\n" +" the bytecode would be encoded and saved into the cache entry after\n" +" the script execution.\n" +" assertEqBytecode: if true, and if both loadBytecode and saveBytecode are \n" +" true, then the loaded bytecode and the encoded bytecode are compared.\n" +" and an assertion is raised if they differ.\n" +), + + JS_FN_HELP("run", Run, 1, 0, +"run('foo.js')", +" Run the file named by the first argument, returning the number of\n" +" of milliseconds spent compiling and executing it."), + + JS_FN_HELP("readline", ReadLine, 0, 0, +"readline()", +" Read a single line from stdin."), + + JS_FN_HELP("print", Print, 0, 0, +"print([exp ...])", +" Evaluate and print expressions to stdout."), + + JS_FN_HELP("printErr", PrintErr, 0, 0, +"printErr([exp ...])", +" Evaluate and print expressions to stderr."), + + JS_FN_HELP("putstr", PutStr, 0, 0, +"putstr([exp])", +" Evaluate and print expression without newline."), + + JS_FN_HELP("dateNow", Now, 0, 0, +"dateNow()", +" Return the current time with sub-ms precision."), + + JS_FN_HELP("help", Help, 0, 0, +"help([name ...])", +" Display usage and help messages."), + + JS_FN_HELP("quit", Quit, 0, 0, +"quit()", +" Quit the shell."), + + JS_FN_HELP("assertEq", AssertEq, 2, 0, +"assertEq(actual, expected[, msg])", +" Throw if the first two arguments are not the same (both +0 or both -0,\n" +" both NaN, or non-zero and ===)."), + + JS_FN_HELP("startTimingMutator", StartTimingMutator, 0, 0, +"startTimingMutator()", +" Start accounting time to mutator vs GC."), + + JS_FN_HELP("stopTimingMutator", StopTimingMutator, 0, 0, +"stopTimingMutator()", +" Stop accounting time to mutator vs GC and dump the results."), + + JS_FN_HELP("throwError", ThrowError, 0, 0, +"throwError()", +" Throw an error from JS_ReportError."), + +#ifdef DEBUG + JS_FN_HELP("disassemble", DisassembleToString, 1, 0, +"disassemble([fun/code])", +" Return the disassembly for the given function or code.\n" +" All disassembly functions take these options as leading string arguments:\n" +" \"-r\" (disassemble recursively)\n" +" \"-l\" (show line numbers)\n" +" \"-S\" (omit source notes)"), + + JS_FN_HELP("dis", Disassemble, 1, 0, +"dis([fun/code])", +" Disassemble functions into bytecodes."), + + JS_FN_HELP("disfile", DisassFile, 1, 0, +"disfile('foo.js')", +" Disassemble script file into bytecodes.\n"), + + JS_FN_HELP("dissrc", DisassWithSrc, 1, 0, +"dissrc([fun/code])", +" Disassemble functions with source lines."), + + JS_FN_HELP("notes", Notes, 1, 0, +"notes([fun])", +" Show source notes for functions."), + + JS_FN_HELP("stackDump", StackDump, 3, 0, +"stackDump(showArgs, showLocals, showThisProps)", +" Tries to print a lot of information about the current stack. \n" +" Similar to the DumpJSStack() function in the browser."), + +#endif + JS_FN_HELP("intern", Intern, 1, 0, +"intern(str)", +" Internalize str in the atom table."), + + JS_FN_HELP("getslx", GetSLX, 1, 0, +"getslx(obj)", +" Get script line extent."), + + JS_FN_HELP("evalcx", EvalInContext, 1, 0, +"evalcx(s[, o])", +" Evaluate s in optional sandbox object o.\n" +" if (s == '' && !o) return new o with eager standard classes\n" +" if (s == 'lazy' && !o) return new o with lazy standard classes"), + + JS_FN_HELP("evalInWorker", EvalInWorker, 1, 0, +"evalInWorker(str)", +" Evaluate 'str' in a separate thread with its own runtime.\n"), + + JS_FN_HELP("getSharedArrayBuffer", GetSharedArrayBuffer, 0, 0, +"getSharedArrayBuffer()", +" Retrieve the SharedArrayBuffer object from the cross-worker mailbox.\n" +" The object retrieved may not be identical to the object that was\n" +" installed, but it references the same shared memory.\n" +" getSharedArrayBuffer performs an ordering memory barrier.\n"), + + JS_FN_HELP("setSharedArrayBuffer", SetSharedArrayBuffer, 0, 0, +"setSharedArrayBuffer()", +" Install the SharedArrayBuffer object in the cross-worker mailbox.\n" +" setSharedArrayBuffer performs an ordering memory barrier.\n"), + + JS_FN_HELP("shapeOf", ShapeOf, 1, 0, +"shapeOf(obj)", +" Get the shape of obj (an implementation detail)."), + +#ifdef DEBUG + JS_FN_HELP("arrayInfo", ArrayInfo, 1, 0, +"arrayInfo(a1, a2, ...)", +" Report statistics about arrays."), +#endif + + JS_FN_HELP("sleep", Sleep_fn, 1, 0, +"sleep(dt)", +" Sleep for dt seconds."), + + JS_FN_HELP("compile", Compile, 1, 0, +"compile(code)", +" Compiles a string to bytecode, potentially throwing."), + + JS_FN_HELP("parseModule", ParseModule, 1, 0, +"parseModule(code)", +" Parses source text as a module and returns a Module object."), + + JS_FN_HELP("setModuleResolveHook", SetModuleResolveHook, 1, 0, +"setModuleResolveHook(function(module, specifier) {})", +" Set the HostResolveImportedModule hook to |function|.\n" +" This hook is used to look up a previously loaded module object. It should\n" +" be implemented by the module loader."), + + JS_FN_HELP("getModuleLoadPath", GetModuleLoadPath, 0, 0, +"getModuleLoadPath()", +" Return any --module-load-path argument passed to the shell. Used by the\n" +" module loader.\n"), + + JS_FN_HELP("parse", Parse, 1, 0, +"parse(code)", +" Parses a string, potentially throwing."), + + JS_FN_HELP("syntaxParse", SyntaxParse, 1, 0, +"syntaxParse(code)", +" Check the syntax of a string, returning success value"), + + JS_FN_HELP("offThreadCompileScript", OffThreadCompileScript, 1, 0, +"offThreadCompileScript(code[, options])", +" Compile |code| on a helper thread. To wait for the compilation to finish\n" +" and run the code, call |runOffThreadScript|. If present, |options| may\n" +" have properties saying how the code should be compiled:\n" +" noScriptRval: use the no-script-rval compiler option (default: false)\n" +" fileName: filename for error messages and debug info\n" +" lineNumber: starting line number for error messages and debug info\n" +" columnNumber: starting column number for error messages and debug info\n" +" element: if present with value |v|, convert |v| to an object |o| and\n" +" mark the source as being attached to the DOM element |o|. If the\n" +" property is omitted or |v| is null, don't attribute the source to\n" +" any DOM element.\n" +" elementAttributeName: if present and not undefined, the name of\n" +" property of 'element' that holds this code. This is what\n" +" Debugger.Source.prototype.elementAttributeName returns.\n"), + + JS_FN_HELP("runOffThreadScript", runOffThreadScript, 0, 0, +"runOffThreadScript()", +" Wait for off-thread compilation to complete. If an error occurred,\n" +" throw the appropriate exception; otherwise, run the script and return\n" +" its value."), + + JS_FN_HELP("timeout", Timeout, 1, 0, +"timeout([seconds], [func])", +" Get/Set the limit in seconds for the execution time for the current context.\n" +" A negative value (default) means that the execution time is unlimited.\n" +" If a second argument is provided, it will be invoked when the timer elapses.\n" +" Calling this function will replace any callback set by |setInterruptCallback|.\n"), + + JS_FN_HELP("interruptIf", InterruptIf, 1, 0, +"interruptIf(cond)", +" Requests interrupt callback if cond is true. If a callback function is set via\n" +" |timeout| or |setInterruptCallback|, it will be called. No-op otherwise."), + + JS_FN_HELP("invokeInterruptCallback", InvokeInterruptCallbackWrapper, 0, 0, +"invokeInterruptCallback(fun)", +" Forcefully set the interrupt flag and invoke the interrupt handler. If a\n" +" callback function is set via |timeout| or |setInterruptCallback|, it will\n" +" be called. Before returning, fun is called with the return value of the\n" +" interrupt handler."), + + JS_FN_HELP("setInterruptCallback", SetInterruptCallback, 1, 0, +"setInterruptCallback(func)", +" Sets func as the interrupt callback function.\n" +" Calling this function will replace any callback set by |timeout|.\n"), + + JS_FN_HELP("enableLastWarning", EnableLastWarning, 0, 0, +"enableLastWarning()", +" Enable storing the last warning."), + + JS_FN_HELP("disableLastWarning", DisableLastWarning, 0, 0, +"disableLastWarning()", +" Disable storing the last warning."), + + JS_FN_HELP("getLastWarning", GetLastWarning, 0, 0, +"getLastWarning()", +" Returns an object that represents the last warning."), + + JS_FN_HELP("clearLastWarning", ClearLastWarning, 0, 0, +"clearLastWarning()", +" Clear the last warning."), + + JS_FN_HELP("elapsed", Elapsed, 0, 0, +"elapsed()", +" Execution time elapsed for the current context."), + + JS_FN_HELP("decompileFunction", DecompileFunction, 1, 0, +"decompileFunction(func)", +" Decompile a function."), + + JS_FN_HELP("decompileThis", DecompileThisScript, 0, 0, +"decompileThis()", +" Decompile the currently executing script."), + + JS_FN_HELP("thisFilename", ThisFilename, 0, 0, +"thisFilename()", +" Return the filename of the current script"), + + JS_FN_HELP("newGlobal", NewGlobal, 1, 0, +"newGlobal([options])", +" Return a new global object in a new compartment. If options\n" +" is given, it may have any of the following properties:\n" +" sameZoneAs: the compartment will be in the same zone as the given object (defaults to a new zone)\n" +" invisibleToDebugger: the global will be invisible to the debugger (default false)\n" +" principal: if present, its value converted to a number must be an\n" +" integer that fits in 32 bits; use that as the new compartment's\n" +" principal. Shell principals are toys, meant only for testing; one\n" +" shell principal subsumes another if its set bits are a superset of\n" +" the other's. Thus, a principal of 0 subsumes nothing, while a\n" +" principals of ~0 subsumes all other principals. The absence of a\n" +" principal is treated as if its bits were 0xffff, for subsumption\n" +" purposes. If this property is omitted, supply no principal."), + + JS_FN_HELP("nukeCCW", NukeCCW, 1, 0, +"nukeCCW(wrapper)", +" Nuke a CrossCompartmentWrapper, which turns it into a DeadProxyObject."), + + JS_FN_HELP("createMappedArrayBuffer", CreateMappedArrayBuffer, 1, 0, +"createMappedArrayBuffer(filename, [offset, [size]])", +" Create an array buffer that mmaps the given file."), + + JS_FN_HELP("getMaxArgs", GetMaxArgs, 0, 0, +"getMaxArgs()", +" Return the maximum number of supported args for a call."), + + JS_FN_HELP("objectEmulatingUndefined", ObjectEmulatingUndefined, 0, 0, +"objectEmulatingUndefined()", +" Return a new object obj for which typeof obj === \"undefined\", obj == null\n" +" and obj == undefined (and vice versa for !=), and ToBoolean(obj) === false.\n"), + + JS_FN_HELP("isCachingEnabled", IsCachingEnabled, 0, 0, +"isCachingEnabled()", +" Return whether JS caching is enabled."), + + JS_FN_HELP("setCachingEnabled", SetCachingEnabled, 1, 0, +"setCachingEnabled(b)", +" Enable or disable JS caching."), + + JS_FN_HELP("cacheEntry", CacheEntry, 1, 0, +"cacheEntry(code)", +" Return a new opaque object which emulates a cache entry of a script. This\n" +" object encapsulates the code and its cached content. The cache entry is filled\n" +" and read by the \"evaluate\" function by using it in place of the source, and\n" +" by setting \"saveBytecode\" and \"loadBytecode\" options."), + + JS_FN_HELP("printProfilerEvents", PrintProfilerEvents, 0, 0, +"printProfilerEvents()", +" Register a callback with the profiler that prints javascript profiler events\n" +" to stderr. Callback is only registered if profiling is enabled."), + + JS_FN_HELP("enableSingleStepProfiling", EnableSingleStepProfiling, 0, 0, +"enableSingleStepProfiling()", +" This function will fail on platforms that don't support single-step profiling\n" +" (currently everything but ARM-simulator). When enabled, at every instruction a\n" +" backtrace will be recorded and stored in an array. Adjacent duplicate backtraces\n" +" are discarded."), + + JS_FN_HELP("disableSingleStepProfiling", DisableSingleStepProfiling, 0, 0, +"disableSingleStepProfiling()", +" Return the array of backtraces recorded by enableSingleStepProfiling."), + + JS_FN_HELP("isLatin1", IsLatin1, 1, 0, +"isLatin1(s)", +" Return true iff the string's characters are stored as Latin1."), + + JS_FN_HELP("stackPointerInfo", StackPointerInfo, 0, 0, +"stackPointerInfo()", +" Return an int32 value which corresponds to the offset of the latest stack\n" +" pointer, such that one can take the differences of 2 to estimate a frame-size."), + + JS_FN_HELP("entryPoints", EntryPoints, 1, 0, +"entryPoints(params)", +"Carry out some JSAPI operation as directed by |params|, and return an array of\n" +"objects describing which JavaScript entry points were invoked as a result.\n" +"|params| is an object whose properties indicate what operation to perform. Here\n" +"are the recognized groups of properties:\n" +"\n" +"{ function }: Call the object |params.function| with no arguments.\n" +"\n" +"{ object, property }: Fetch the property named |params.property| of\n" +"|params.object|.\n" +"\n" +"{ ToString }: Apply JS::ToString to |params.toString|.\n" +"\n" +"{ ToNumber }: Apply JS::ToNumber to |params.toNumber|.\n" +"\n" +"{ eval }: Apply JS::Evaluate to |params.eval|.\n" +"\n" +"The return value is an array of strings, with one element for each\n" +"JavaScript invocation that occurred as a result of the given\n" +"operation. Each element is the name of the function invoked, or the\n" +"string 'eval:FILENAME' if the code was invoked by 'eval' or something\n" +"similar.\n"), + + JS_FS_HELP_END +}; +#endif /* NOTYET */ + +/*==============================================================*/ +static JSObject* +NewGlobalObject(JSContext* cx, JS::CompartmentOptions& options, + JSPrincipals* principals) +{ + + JSClass * _clasp = (JSClass *)&global_class; + const JSFunctionSpec * _functions = global_functions; /* XXX shell_functions */ + + RootedObject glob(cx, + JS_NewGlobalObject(cx, _clasp, principals, JS::DontFireOnNewGlobalHook, options)); + if (!glob) + return nullptr; + + { + JSAutoCompartment ac(cx, glob); + +#ifndef LAZY_STANDARD_CLASSES + if (!JS_InitStandardClasses(cx, glob)) + return nullptr; +#endif + +#ifdef DYING + bool succeeded; + if (!JS_SetImmutablePrototype(cx, glob, &succeeded)) + return nullptr; + MOZ_ASSERT(succeeded, + "a fresh, unexposed global object is always capable of " + "having its [[Prototype]] be immutable"); +#endif + +#ifdef JS_HAS_CTYPES + if (!JS_InitCTypesClass(cx, glob)) + return nullptr; +#endif + +#ifdef MOZILLA_DYING + if (!JS_InitReflectParse(cx, glob)) + return nullptr; + if (!JS_DefineDebuggerObject(cx, glob)) + return nullptr; + if (!JS::RegisterPerfMeasurement(cx, glob)) + return nullptr; + if (!JS_DefineFunctionsWithHelp(cx, glob, shell_functions) || + !JS_DefineProfilingFunctions(cx, glob)) + { + return nullptr; + } +#else /* MOZILLA_DYING */ + if (!JS_DefineFunctions(cx, glob, _functions)) + { + return nullptr; + } +#endif /* MOZILLA_DYING */ + +#ifdef DYING + if (!js::DefineTestingFunctions(cx, glob, fuzzingSafe, disableOOMFunctions)) + return nullptr; + + if (!fuzzingSafe) { + if (!JS_DefineFunctionsWithHelp(cx, glob, fuzzing_unsafe_functions)) + return nullptr; + if (!DefineConsole(cx, glob)) + return nullptr; + } + + if (!DefineOS(cx, glob, fuzzingSafe)) + return nullptr; + + RootedObject performanceObj(cx, JS_NewObject(cx, nullptr)); + if (!performanceObj) + return nullptr; + RootedObject mozMemoryObj(cx, JS_NewObject(cx, nullptr)); + if (!mozMemoryObj) + return nullptr; + RootedObject gcObj(cx, gc::NewMemoryInfoObject(cx)); + if (!gcObj) + return nullptr; + if (!JS_DefineProperty(cx, glob, "performance", performanceObj, JSPROP_ENUMERATE)) + return nullptr; + if (!JS_DefineProperty(cx, performanceObj, "mozMemory", mozMemoryObj, JSPROP_ENUMERATE)) + return nullptr; + if (!JS_DefineProperty(cx, mozMemoryObj, "gc", gcObj, JSPROP_ENUMERATE)) + return nullptr; + + /* Initialize FakeDOMObject. */ + static const js::DOMCallbacks DOMcallbacks = { + InstanceClassHasProtoAtDepth + }; + SetDOMCallbacks(cx->runtime(), &DOMcallbacks); + + RootedObject domProto(cx, JS_InitClass(cx, glob, nullptr, &dom_class, dom_constructor, + 0, dom_props, dom_methods, nullptr, nullptr)); + if (!domProto) + return nullptr; + + /* Initialize FakeDOMObject.prototype */ + InitDOMObject(domProto); + + if (!js::InitModuleClasses(cx, glob)) + return nullptr; +#endif /* DYING */ + } + + JS_FireOnNewGlobalObject(cx, glob); + + return glob; +} + /*==============================================================*/ -static void mozFini(rpmjs js) +static void mozFini(rpmjss jss) { - JSI_t I = (JSI_t) js->I; + JSI_t I = (JSI_t) jss->I; if (I->cx) JS_DestroyContext(I->cx); @@ -104,23 +732,24 @@ JS_DestroyRuntime(I->rt); I->rt = NULL; - if (--rpmjs_nopens <= 0) { + if (--rpmjss_nopens <= 0) { JS_ShutDown(); - rpmjs_nopens = 0; + rpmjss_nopens = 0; } free(I); } -static void * mozInit(rpmjs js) +static void * mozInit(rpmjss jss) { JSI_t I = NULL; - uint32_t flags = js->flags; + uint32_t flags = jss->flags; static uint32_t _maxbytes = 8L * 1024L * 1024L; static size_t _stackChunkSize = 8192; + JSPrincipals * _principals = NULL; bool ok; - if (rpmjs_nopens++ == 0) + if (rpmjss_nopens++ == 0) JS_Init(); I = (JSI_t) calloc(1, sizeof(*I)); @@ -128,17 +757,27 @@ I->rt = JS_NewRuntime(_maxbytes); assert(I->rt); - JS_SetRuntimePrivate(I->rt, (void *)js); + JS_SetRuntimePrivate(I->rt, (void *)jss); I->cx = JS_NewContext(I->rt, _stackChunkSize); assert(I->cx); - JS_SetContextPrivate(I->cx, (void *)js); + JS_SetContextPrivate(I->cx, (void *)jss); -#ifdef NOTYET - JS_SetErrorReporter(I->cx, rpmjsReportError); -#endif + JS_SetErrorReporter(I->rt, rpmjssReportError); + SetOutOfMemoryCallback(I->rt, rpmjssOOMCallback, nullptr); + { + RootedObject glob(I->cx); + JS::CompartmentOptions options; + options.setVersion(JSVERSION_DEFAULT); + glob = NewGlobalObject(I->cx, options, _principals); + I->global = glob; +assert(I->global); + } + #ifdef HACK + ok = JS_InitStandardClasses(I->cx, global); +assert(ok); #ifdef JS_HAS_CTYPES ok = JS_InitCTypesClass(I->cx, I->global); assert(ok); @@ -153,39 +792,20 @@ return I; } -static int mozRun(rpmjs js, - const char * script, const char * filename, int lineno) +static int mozRun(rpmjss jss, + const char * script, const char * fn, int ln) { - JSI_t I = (JSI_t) js->I; + JSI_t I = (JSI_t) jss->I; - JSClass * _clasp = (JSClass *)&global_class; -#ifdef NOTYET - JSFunctionSpec * _functions = global_functions; -#endif - JSPrincipals * _principals = NULL; bool ok; - // In practice, you would want to exit this any - // time you're spinning the event loop - JSAutoRequest ar(I->cx); - - JS::RootedObject global(I->cx, - JS_NewGlobalObject(I->cx, _clasp, _principals, JS::FireOnNewGlobalHook)); - if (!global) - return 1; - - I->global = global; -assert(I->global); - JS::RootedValue rval(I->cx); { // Scope for JSAutoCompartment JSAutoCompartment ac(I->cx, I->global); - ok = JS_InitStandardClasses(I->cx, global); -assert(ok); JS::CompileOptions opts(I->cx); - opts.setFileAndLine(filename, lineno); + opts.setFileAndLine(fn, ln); ok = JS::Evaluate(I->cx, opts, script, strlen(script), &rval); if (!ok) @@ -201,27 +821,25 @@ static struct JSIO_s _mozjs45 = { mozFini, mozInit, mozRun }; JSIO_t mozjs45 = &_mozjs45; -#if defined(RPMJS_SELF_TEST) -struct rpmjs_s _js; -rpmjs js = &_js; +#if defined(RPMJSS_SELF_TEST) +struct rpmjss_s _jss; +rpmjss jss = &_jss; /*==============================================================*/ int main(int argc, const char *argv[]) { int rc = 0; - JSI_t I = (JSI_t) mozInit(js); - js->I = I; + JSI_t I = (JSI_t) mozInit(jss); + jss->I = I; { const char *script = "'hello'+'world, it is '+new Date()"; - const char *filename = "noname"; - int lineno = 1; - rc = mozRun(js, script, filename, lineno); + rc = mozRun(jss, script, __FILE__, __LINE__); } - mozFini(js); + mozFini(jss); return rc; } -#endif /* RPMJS_SELF_TEST */ +#endif /* RPMJSS_SELF_TEST */ @@ . patch -p0 <<'@@ .' Index: rpm/rpmio/rpmjss.h ============================================================================ $ cvs diff -u -r0 -r1.1.2.1 rpmjss.h --- /dev/null 2017-06-23 05:38:19.000000000 +0200 +++ rpmjss.h 2017-06-23 05:39:44.199733788 +0200 @@ -0,0 +1,141 @@ +#ifndef RPMJSS_H +#define RPMJSS_H + +/** \ingroup rpmio + * \file rpmio/rpmjss.h + */ + +#include <rpmiotypes.h> +#include <rpmio.h> + +typedef struct rpmjss_s * rpmjss; + +extern int _rpmjss_debug; + +extern rpmjss _rpmjssI; + +extern uint32_t _rpmjss_options; + +extern int _rpmjss_zeal; + +#if defined(_RPMJSS_INTERNAL) +/** + * Interpreter flags. + */ +enum rpmjssFlags_e { + RPMJSS_FLAGS_NONE = 0, + RPMJSS_FLAGS_STRICT = (1<< 0), /* JSOPTION_STRICT */ + RPMJSS_FLAGS_WERROR = (1<< 1), /* JSOPTION_WERROR */ + RPMJSS_FLAGS_VAROBJFIX = (1<< 2), /* JSOPTION_VAROBJFIX */ + RPMJSS_FLAGS_PRIVATE_IS_NSISUPPORTS = (1<< 3), /* JSOPTION_PRIVATE_IS_NSISUPPORTS */ + RPMJSS_FLAGS_COMPILE_N_GO = (1<< 4), /* JSOPTION_COMPILE_N_GO */ + RPMJSS_FLAGS_ATLINE = (1<< 5), /* JSOPTION_ATLINE */ + RPMJSS_FLAGS_XML = (1<< 6), /* JSOPTION_XML */ + /* bit 7 unused */ + RPMJSS_FLAGS_DONT_REPORT_UNCAUGHT = (1<< 8), /* JSOPTION_DONT_REPORT_UNCAUGHT */ + RPMJSS_FLAGS_RELIMIT = (1<< 9), /* JSOPTION_RELIMIT */ + RPMJSS_FLAGS_ANONFUNFIX = (1<<10), /* JSOPTION_ANONFUNFIX */ + RPMJSS_FLAGS_JIT = (1<<11), /* JSOPTION_JIT */ + RPMJSS_FLAGS_NO_SCRIPT_RVAL = (1<<12), /* JSOPTION_NO_SCRIPT_RVAL */ + RPMJSS_FLAGS_UNROOTED_GLOBAL = (1<<13), /* JSOPTION_UNROOTED_GLOBAL */ + /* bits 14-15 unused */ + RPMJSS_FLAGS_NOEXEC = (1<<16), /*!< -n */ + RPMJSS_FLAGS_SKIPSHEBANG = (1<<17), /*!< -F */ + RPMJSS_FLAGS_LOADRC = (1<<18), /*!< -R */ + RPMJSS_FLAGS_NOUTF8 = (1<<19), /*!< -U */ + RPMJSS_FLAGS_NOCACHE = (1<<20), /*!< -C */ + RPMJSS_FLAGS_NOWARN = (1<<21), /*!< -W */ + RPMJSS_FLAGS_ALLOW = (1<<22), /*!< -a */ + /* bits 23-30 unused */ + RPMJSS_FLAGS_GLOBAL = (1<<31), +}; + +typedef struct JSIO_s * JSIO_t; +struct JSIO_s { + void (*mozFini) (rpmjss jss); + void * (*mozInit) (rpmjss jss); + int (*mozRun) (rpmjss jss, const char * script, const char * filename, int lineno); +}; + +extern JSIO_t mozjs185; +extern JSIO_t mozjs17; +extern JSIO_t mozjs24; +extern JSIO_t mozjs31; +extern JSIO_t mozjs38; +extern JSIO_t mozjs45; + +struct rpmjss_s { + struct rpmioItem_s _item; /*!< usage mutex and pool identifier. */ + uint32_t flags; /*!< JSOPTION_FOO in 0xffff bits */ + JSIO_t jsio; + void * I; /*!< JS interpreter {rt, cx, globalObj} */ +}; + +struct rpmjss_s _rpmjss; + +#endif /* _RPMJSS_INTERNAL */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Unreference a js shell interpreter instance. + * @param jss js shell interpreter + * @return NULL on last dereference + */ +rpmjss rpmjssUnlink (rpmjss jss); +#define rpmjssUnlink(_jss) \ + ((rpmjss)rpmioUnlinkPoolItem((rpmioItem)(_jss), __FUNCTION__, __FILE__, __LINE__)) + +/** + * Reference a js shell interpreter instance. + * @param jss js shell interpreter + * @return new js shell interpreter reference + */ +rpmjss rpmjssLink (rpmjss jss); +#define rpmjssLink(_jss) \ + ((rpmjss)rpmioLinkPoolItem((rpmioItem)(_jss), __FUNCTION__, __FILE__, __LINE__)) + +/** + * Destroy a js shell interpreter. + * @param jss js shell interpreter + * @return NULL on last dereference + */ +rpmjss rpmjssFree(rpmjss jss); +#define rpmjssFree(_jss) \ + ((rpmjss)rpmioFreePoolItem((rpmioItem)(_jss), __FUNCTION__, __FILE__, __LINE__)) + +/** + * Create and load a js shell interpreter. + * @param av js shell interpreter args (or NULL) + * @param flags js shell interpreter flags ((1<<31): use global interpreter) + * @return new js interpreter + */ +rpmjss rpmjssNew(char ** av, uint32_t flags); + +/** + * Execute js from a file. + * @param js js interpreter (NULL uses global interpreter) + * @param fn js file to run (NULL returns RPMRC_FAIL) + * @param Iargv js script argv + * @param resultp *resultp js exec result + * @return RPMRC_OK on success + */ +rpmRC rpmjssRunFile(rpmjss jss, const char * fn, + char *const * Iargv, const char ** resultp); + +/** + * Execute js string. + * @param js js interpreter (NULL uses global interpreter) + * @param str js string to execute (NULL returns RPMRC_FAIL) + * @param resultp *resultp js exec result + * @return RPMRC_OK on success + */ +rpmRC rpmjssRun(rpmjss jss, const char * str, const char ** resultp); + +#ifdef __cplusplus +} +#endif + +#endif /* RPMJSS_H */ @@ . ______________________________________________________________________ RPM Package Manager http://rpm5.org CVS Sources Repository rpm-cvs@rpm5.org