/** * call a method of Native JSObject. * * @param jEnv - JNIEnv on which the call is being made. * @param obj - A Native JS Object. * @param name - Name of a method. * @param jobjArr - Array of jobjects representing parameters of method being caled. * @param pjobj - return value. */ NS_METHOD nsCLiveconnect::Call(JNIEnv *jEnv, lcjsobject obj, const jchar *name, jsize length, jobjectArray java_args, void* principalsArray[], int numPrincipals, nsISupports *securitySupports, jobject *pjobj) { if(jEnv == NULL || obj == 0) { return NS_ERROR_FAILURE; } int i = 0; int argc = 0; int arg_num = 0; jsval *argv = 0; JSJavaThreadState *jsj_env = NULL; JSObjectHandle *handle = (JSObjectHandle*)obj; JSObject *js_obj = handle->js_obj; JSContext *cx = NULL; jsval js_val; jsval function_val = 0; int dummy_cost = 0; JSBool dummy_bool = PR_FALSE; JSErrorReporter saved_state = NULL; jobject result = NULL; jsj_env = jsj_enter_js(jEnv, mJavaClient, NULL, &cx, NULL, &saved_state, principalsArray, numPrincipals, securitySupports); if (!jsj_env) return NS_ERROR_FAILURE; result = NULL; AutoPushJSContext autopush(securitySupports, cx); if (NS_FAILED(autopush.ResultOfPush())) goto done; if (!name) { JS_ReportError(cx, "illegal null JavaScript function name"); goto done; } /* Allocate space for JS arguments */ argc = java_args ? jEnv->GetArrayLength(java_args) : 0; if (argc) { argv = (jsval*)JS_malloc(cx, argc * sizeof(jsval)); if (!argv) goto done; } else { argv = 0; } /* Convert arguments from Java to JS values */ for (arg_num = 0; arg_num < argc; arg_num++) { jobject arg = jEnv->GetObjectArrayElement(java_args, arg_num); JSBool ret = jsj_ConvertJavaObjectToJSValue(cx, jEnv, arg, &argv[arg_num]); jEnv->DeleteLocalRef(arg); if (!ret) goto cleanup_argv; JS_AddRoot(cx, &argv[arg_num]); } if (!JS_GetUCProperty(cx, js_obj, name, length, &function_val)) goto cleanup_argv; if (!JS_CallFunctionValue(cx, js_obj, function_val, argc, argv, &js_val)) goto cleanup_argv; jsj_ConvertJSValueToJavaObject(cx, jEnv, js_val, jsj_get_jlObject_descriptor(cx, jEnv), &dummy_cost, &result, &dummy_bool); cleanup_argv: if (argv) { for (i = 0; i < arg_num; i++) JS_RemoveRoot(cx, &argv[i]); JS_free(cx, argv); } done: if (!jsj_exit_js(cx, jsj_env, saved_state)) return NS_ERROR_FAILURE; *pjobj = result; return NS_OK; }
// convert a readable to a JSString, copying string data // static jsval XPCStringConvert::ReadableToJSVal(JSContext *cx, const nsAString &readable, nsStringBuffer** sharedBuffer) { JSString *str; *sharedBuffer = nsnull; PRUint32 length = readable.Length(); JSAtom *atom; if (length == 0 && (atom = cx->runtime->atomState.emptyAtom)) { return ATOM_TO_JSVAL(atom); } nsStringBuffer *buf = nsStringBuffer::FromString(readable); if (buf) { // yay, we can share the string's buffer! if (sDOMStringFinalizerIndex == -1) { sDOMStringFinalizerIndex = JS_AddExternalStringFinalizer(DOMStringFinalizer); if (sDOMStringFinalizerIndex == -1) return JSVAL_NULL; } str = JS_NewExternalString(cx, reinterpret_cast<jschar *>(buf->Data()), length, sDOMStringFinalizerIndex); if (str) { *sharedBuffer = buf; } } else { // blech, have to copy. jschar *chars = reinterpret_cast<jschar *> (JS_malloc(cx, (length + 1) * sizeof(jschar))); if (!chars) return JSVAL_NULL; if (length && !CopyUnicodeTo(readable, 0, reinterpret_cast<PRUnichar *>(chars), length)) { JS_free(cx, chars); return JSVAL_NULL; } chars[length] = 0; str = JS_NewUCString(cx, chars, length); if (!str) JS_free(cx, chars); } return STRING_TO_JSVAL(str); }
static JSBool InitExceptionObject(JSContext *cx, JSObject *obj, JSString *message, JSString *filename, uintN lineno) { JSCheckAccessOp checkAccess; JSErrorReporter older; JSExceptionState *state; jschar *stackbuf; size_t stacklen, stackmax; JSStackFrame *fp; jsval callerid, v; JSBool ok; JSString *argsrc, *stack; uintN i, ulineno; const char *cp; char ulnbuf[11]; if (!JS_DefineProperty(cx, obj, js_message_str, STRING_TO_JSVAL(message), NULL, NULL, JSPROP_ENUMERATE)) { return JS_FALSE; } if (!JS_DefineProperty(cx, obj, js_filename_str, STRING_TO_JSVAL(filename), NULL, NULL, JSPROP_ENUMERATE)) { return JS_FALSE; } if (!JS_DefineProperty(cx, obj, js_lineno_str, INT_TO_JSVAL(lineno), NULL, NULL, JSPROP_ENUMERATE)) { return JS_FALSE; } /* * Set the 'stack' property. * * First, set aside any error reporter for cx and save its exception state * so we can suppress any checkAccess failures. Such failures should stop * the backtrace procedure, not result in a failure of this constructor. */ checkAccess = cx->runtime->checkObjectAccess; if (checkAccess) { older = JS_SetErrorReporter(cx, NULL); state = JS_SaveExceptionState(cx); } #ifdef __GNUC__ /* suppress bogus gcc warnings */ else { older = NULL; state = NULL; } #endif callerid = ATOM_KEY(cx->runtime->atomState.callerAtom); /* * Prepare to allocate a jschar buffer at stackbuf, where stacklen indexes * the next free jschar slot, and with room for at most stackmax non-null * jschars. If stackbuf is non-null, it always contains an extra slot for * the null terminator we'll store at the end, as a backstop. * * All early returns must goto done after this point, till the after-loop * cleanup code has run! */ stackbuf = NULL; stacklen = stackmax = 0; ok = JS_TRUE; #define APPEND_CHAR_TO_STACK(c) \ JS_BEGIN_MACRO \ if (stacklen == stackmax) { \ void *ptr_; \ stackmax = stackmax ? 2 * stackmax : 64; \ ptr_ = JS_realloc(cx, stackbuf, (stackmax+1) * sizeof(jschar)); \ if (!ptr_) { \ ok = JS_FALSE; \ goto done; \ } \ stackbuf = ptr_; \ } \ stackbuf[stacklen++] = (c); \ JS_END_MACRO #define APPEND_STRING_TO_STACK(str) \ JS_BEGIN_MACRO \ JSString *str_ = str; \ size_t length_ = JSSTRING_LENGTH(str_); \ if (stacklen + length_ > stackmax) { \ void *ptr_; \ stackmax = JS_BIT(JS_CeilingLog2(stacklen + length_)); \ ptr_ = JS_realloc(cx, stackbuf, (stackmax+1) * sizeof(jschar)); \ if (!ptr_) { \ ok = JS_FALSE; \ goto done; \ } \ stackbuf = ptr_; \ } \ js_strncpy(stackbuf + stacklen, JSSTRING_CHARS(str_), length_); \ stacklen += length_; \ JS_END_MACRO for (fp = cx->fp; fp; fp = fp->down) { if (checkAccess) { v = (fp->fun && fp->argv) ? fp->argv[-2] : JSVAL_NULL; if (!JSVAL_IS_PRIMITIVE(v)) { ok = checkAccess(cx, fp->fun->object, callerid, JSACC_READ, &v); if (!ok) { ok = JS_TRUE; break; } } } if (fp->fun) { if (fp->fun->atom) APPEND_STRING_TO_STACK(ATOM_TO_STRING(fp->fun->atom)); APPEND_CHAR_TO_STACK('('); for (i = 0; i < fp->argc; i++) { argsrc = js_ValueToSource(cx, fp->argv[i]); if (!argsrc) { ok = JS_FALSE; goto done; } if (i > 0) APPEND_CHAR_TO_STACK(','); APPEND_STRING_TO_STACK(argsrc); } APPEND_CHAR_TO_STACK(')'); } APPEND_CHAR_TO_STACK('@'); if (fp->script && fp->script->filename) { for (cp = fp->script->filename; *cp; cp++) APPEND_CHAR_TO_STACK(*cp); } APPEND_CHAR_TO_STACK(':'); if (fp->script && fp->pc) { ulineno = js_PCToLineNumber(fp->script, fp->pc); JS_snprintf(ulnbuf, sizeof ulnbuf, "%u", ulineno); for (cp = ulnbuf; *cp; cp++) APPEND_CHAR_TO_STACK(*cp); } else { APPEND_CHAR_TO_STACK('0'); } APPEND_CHAR_TO_STACK('\n'); } #undef APPEND_CHAR_TO_STACK #undef APPEND_STRING_TO_STACK done: if (checkAccess) { if (ok) JS_RestoreExceptionState(cx, state); else JS_DropExceptionState(cx, state); JS_SetErrorReporter(cx, older); } if (!ok) { JS_free(cx, stackbuf); return JS_FALSE; } if (!stackbuf) { stack = cx->runtime->emptyString; } else { /* NB: if stackbuf was allocated, it has room for the terminator. */ JS_ASSERT(stacklen <= stackmax); if (stacklen < stackmax) { /* * Realloc can fail when shrinking on some FreeBSD versions, so * don't use JS_realloc here; simply let the oversized allocation * be owned by the string in that rare case. */ void *shrunk = realloc(stackbuf, (stacklen+1) * sizeof(jschar)); if (shrunk) stackbuf = shrunk; } stackbuf[stacklen] = 0; stack = js_NewString(cx, stackbuf, stacklen, 0); if (!stack) { JS_free(cx, stackbuf); return JS_FALSE; } } return JS_DefineProperty(cx, obj, js_stack_str, STRING_TO_JSVAL(stack), NULL, NULL, JSPROP_ENUMERATE); }
/* * Return a string that may eval to something similar to the original object. */ static JSBool exn_toSource(JSContext *cx, uintN argc, jsval *vp) { JSObject *obj; JSString *name, *message, *filename, *lineno_as_str, *result; jsval localroots[3] = {JSVAL_NULL, JSVAL_NULL, JSVAL_NULL}; JSTempValueRooter tvr; JSBool ok; uint32 lineno; size_t lineno_length, name_length, message_length, filename_length, length; jschar *chars, *cp; obj = JS_THIS_OBJECT(cx, vp); if (!obj || !OBJ_GET_PROPERTY(cx, obj, ATOM_TO_JSID(cx->runtime->atomState.nameAtom), vp)) { return JS_FALSE; } name = js_ValueToString(cx, *vp); if (!name) return JS_FALSE; *vp = STRING_TO_JSVAL(name); /* After this, control must flow through label out: to exit. */ JS_PUSH_TEMP_ROOT(cx, 3, localroots, &tvr); #ifdef __GNUC__ message = filename = NULL; #endif ok = JS_GetProperty(cx, obj, js_message_str, &localroots[0]) && (message = js_ValueToSource(cx, localroots[0])); if (!ok) goto out; localroots[0] = STRING_TO_JSVAL(message); ok = JS_GetProperty(cx, obj, js_fileName_str, &localroots[1]) && (filename = js_ValueToSource(cx, localroots[1])); if (!ok) goto out; localroots[1] = STRING_TO_JSVAL(filename); ok = JS_GetProperty(cx, obj, js_lineNumber_str, &localroots[2]); if (!ok) goto out; lineno = js_ValueToECMAUint32 (cx, &localroots[2]); ok = !JSVAL_IS_NULL(localroots[2]); if (!ok) goto out; if (lineno != 0) { lineno_as_str = js_ValueToString(cx, localroots[2]); if (!lineno_as_str) { ok = JS_FALSE; goto out; } lineno_length = JSSTRING_LENGTH(lineno_as_str); } else { lineno_as_str = NULL; lineno_length = 0; } /* Magic 8, for the characters in ``(new ())''. */ name_length = JSSTRING_LENGTH(name); message_length = JSSTRING_LENGTH(message); length = 8 + name_length + message_length; filename_length = JSSTRING_LENGTH(filename); if (filename_length != 0) { /* append filename as ``, {filename}'' */ length += 2 + filename_length; if (lineno_as_str) { /* append lineno as ``, {lineno_as_str}'' */ length += 2 + lineno_length; } } else { if (lineno_as_str) { /* * no filename, but have line number, * need to append ``, "", {lineno_as_str}'' */ length += 6 + lineno_length; } } cp = chars = (jschar *) JS_malloc(cx, (length + 1) * sizeof(jschar)); if (!chars) { ok = JS_FALSE; goto out; } *cp++ = '('; *cp++ = 'n'; *cp++ = 'e'; *cp++ = 'w'; *cp++ = ' '; js_strncpy(cp, JSSTRING_CHARS(name), name_length); cp += name_length; *cp++ = '('; if (message_length != 0) { js_strncpy(cp, JSSTRING_CHARS(message), message_length); cp += message_length; } if (filename_length != 0) { /* append filename as ``, {filename}'' */ *cp++ = ','; *cp++ = ' '; js_strncpy(cp, JSSTRING_CHARS(filename), filename_length); cp += filename_length; } else { if (lineno_as_str) { /* * no filename, but have line number, * need to append ``, "", {lineno_as_str}'' */ *cp++ = ','; *cp++ = ' '; *cp++ = '"'; *cp++ = '"'; } } if (lineno_as_str) { /* append lineno as ``, {lineno_as_str}'' */ *cp++ = ','; *cp++ = ' '; js_strncpy(cp, JSSTRING_CHARS(lineno_as_str), lineno_length); cp += lineno_length; } *cp++ = ')'; *cp++ = ')'; *cp = 0; result = js_NewString(cx, chars, length); if (!result) { JS_free(cx, chars); ok = JS_FALSE; goto out; } *vp = STRING_TO_JSVAL(result); ok = JS_TRUE; out: JS_POP_TEMP_ROOT(cx, &tvr); return ok; }
my_ErrorReporter(JSContext *cx, const char *message, JSErrorReport *report) { int i, j, k, n; char *prefix = NULL, *tmp; const char *ctmp; if (!report) { fprintf(gErrFile, "%s\n", message); return; } /* Conditionally ignore reported warnings. */ if (JSREPORT_IS_WARNING(report->flags) && !reportWarnings) return; if (report->filename) prefix = JS_smprintf("%s:", report->filename); if (report->lineno) { tmp = prefix; prefix = JS_smprintf("%s%u: ", tmp ? tmp : "", report->lineno); JS_free(cx, tmp); } if (JSREPORT_IS_WARNING(report->flags)) { tmp = prefix; prefix = JS_smprintf("%s%swarning: ", tmp ? tmp : "", JSREPORT_IS_STRICT(report->flags) ? "strict " : ""); JS_free(cx, tmp); } /* embedded newlines -- argh! */ while ((ctmp = strchr(message, '\n')) != 0) { ctmp++; if (prefix) fputs(prefix, gErrFile); fwrite(message, 1, ctmp - message, gErrFile); message = ctmp; } /* If there were no filename or lineno, the prefix might be empty */ if (prefix) fputs(prefix, gErrFile); fputs(message, gErrFile); if (!report->linebuf) { fputc('\n', gErrFile); goto out; } fprintf(gErrFile, ":\n%s%s\n%s", prefix, report->linebuf, prefix); n = report->tokenptr - report->linebuf; for (i = j = 0; i < n; i++) { if (report->linebuf[i] == '\t') { for (k = (j + 8) & ~7; j < k; j++) { fputc('.', gErrFile); } continue; } fputc('.', gErrFile); j++; } fputs("^\n", gErrFile); out: if (!JSREPORT_IS_WARNING(report->flags)) gExitCode = EXITCODE_RUNTIME_ERROR; JS_free(cx, prefix); }
/* * 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; SG_UNUSED(argc); 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, (int)(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; }
bool PrintError(JSContext *cx, FILE *file, const char *message, JSErrorReport *report, bool reportWarnings) { if (!report) { fprintf(file, "%s\n", message); fflush(file); return false; } /* Conditionally ignore reported warnings. */ if (JSREPORT_IS_WARNING(report->flags) && !reportWarnings) return false; char *prefix = NULL; if (report->filename) prefix = JS_smprintf("%s:", report->filename); if (report->lineno) { char *tmp = prefix; prefix = JS_smprintf("%s%u:%u ", tmp ? tmp : "", report->lineno, report->column); JS_free(cx, tmp); } if (JSREPORT_IS_WARNING(report->flags)) { char *tmp = prefix; prefix = JS_smprintf("%s%swarning: ", tmp ? tmp : "", JSREPORT_IS_STRICT(report->flags) ? "strict " : ""); JS_free(cx, tmp); } /* embedded newlines -- argh! */ const char *ctmp; while ((ctmp = strchr(message, '\n')) != 0) { ctmp++; if (prefix) fputs(prefix, file); fwrite(message, 1, ctmp - message, file); message = ctmp; } /* If there were no filename or lineno, the prefix might be empty */ if (prefix) fputs(prefix, file); fputs(message, file); if (report->linebuf) { /* report->linebuf usually ends with a newline. */ int n = strlen(report->linebuf); fprintf(file, ":\n%s%s%s%s", prefix, report->linebuf, (n > 0 && report->linebuf[n-1] == '\n') ? "" : "\n", prefix); n = report->tokenptr - report->linebuf; for (int i = 0, j = 0; i < n; i++) { if (report->linebuf[i] == '\t') { for (int k = (j + 8) & ~7; j < k; j++) { fputc('.', file); } continue; } fputc('.', file); j++; } fputc('^', file); } fputc('\n', file); fflush(file); JS_free(cx, prefix); return true; }
JSBool constructorVideo(JSContext *cx, uintN argc, jsval *vp) { if(argc>0){ char *fName = NULL; char defer_load = 0; if(JSVAL_IS_STRING(JS_ARGV(cx,vp)[0])){ JSString *str = NULL; str = JSVAL_TO_STRING(JS_ARGV(cx,vp)[0]); if(str) fName = JS_EncodeString(cx,str); } if(argc > 1 && JSVAL_IS_BOOLEAN(JS_ARGV(cx,vp)[1])){ defer_load = JSVAL_TO_BOOLEAN(JS_ARGV(cx,vp)[1]); } if(fName){ video *vid = NULL; //Turn this into a fullpath! char *fullpath = contextChroot(cx,fName); if(!fullpath) { fprint(stderr,"Unable to chroot filepath\n"); return JS_FALSE; } JS_free(cx,fName); struct video_backend* vb = get_video_backend(fullpath); if(!vb) { fprint(stderr,"No video backend to handle file %s\n.",fullpath); return JS_FALSE; } vid = vb->openVideo(fullpath,cx); free(fullpath); if(vid){ //set function pointer table vid->vb = vb; //if(!(vid->tx)) fprint(stderr,"ERROR in openVideo creating texture\n"); JSObject *ob = NULL; ob = JS_NewObject(cx, &videoClass,NULL,NULL); if(ob){ JS_SetPrivate(cx,ob,vid); imageAddProps(cx,ob); imageAddFuncs(cx,ob); if(defer_load) { print("Am deferring!\n"); vid->vb->destroyVideoPlayback(vid); //if(vid->tx) // SDL_DestroyTexture(vid->tx); //vid->tx = SDL_CreateTexture(renderer,SDL_PIXELFORMAT_RGB24 ,SDL_TEXTUREACCESS_STREAMING, 1, 1); //temporary } JS_SET_RVAL(cx,vp,OBJECT_TO_JSVAL(ob)); return JS_TRUE; } } else { fprint(stderr,"ERROR in openVideo\n"); } } fprint(stderr,"Unable to create video\n"); } return JS_TRUE; }
JSBool ToUnicode(JSContext* cx, const char* src, jsval* rval) { nsresult rv; if (!mDecoder) { // use app default locale nsCOMPtr<nsILocaleService> localeService = do_GetService(NS_LOCALESERVICE_CONTRACTID, &rv); if (NS_SUCCEEDED(rv)) { nsCOMPtr<nsILocale> appLocale; rv = localeService->GetApplicationLocale(getter_AddRefs(appLocale)); if (NS_SUCCEEDED(rv)) { nsAutoString localeStr; rv = appLocale-> GetCategory(NS_LITERAL_STRING(NSILOCALE_TIME), localeStr); NS_ASSERTION(NS_SUCCEEDED(rv), "failed to get app locale info"); nsCOMPtr<nsIPlatformCharset> platformCharset = do_GetService(NS_PLATFORMCHARSET_CONTRACTID, &rv); if (NS_SUCCEEDED(rv)) { nsCAutoString charset; rv = platformCharset->GetDefaultCharsetForLocale(localeStr, charset); if (NS_SUCCEEDED(rv)) { // get/create unicode decoder for charset nsCOMPtr<nsICharsetConverterManager> ccm = do_GetService(NS_CHARSETCONVERTERMANAGER_CONTRACTID, &rv); if (NS_SUCCEEDED(rv)) ccm->GetUnicodeDecoder(charset.get(), getter_AddRefs(mDecoder)); } } } } } JSString *str = nullptr; int32_t srcLength = PL_strlen(src); if (mDecoder) { int32_t unicharLength = srcLength; PRUnichar *unichars = (PRUnichar *)JS_malloc(cx, (srcLength + 1) * sizeof(PRUnichar)); if (unichars) { rv = mDecoder->Convert(src, &srcLength, unichars, &unicharLength); if (NS_SUCCEEDED(rv)) { // terminate the returned string unichars[unicharLength] = 0; // nsIUnicodeDecoder::Convert may use fewer than srcLength PRUnichars if (unicharLength + 1 < srcLength + 1) { PRUnichar *shrunkUnichars = (PRUnichar *)JS_realloc(cx, unichars, (unicharLength + 1) * sizeof(PRUnichar)); if (shrunkUnichars) unichars = shrunkUnichars; } str = JS_NewUCString(cx, reinterpret_cast<jschar*>(unichars), unicharLength); } if (!str) JS_free(cx, unichars); } } if (!str) { xpc::Throw(cx, NS_ERROR_OUT_OF_MEMORY); return false; } *rval = STRING_TO_JSVAL(str); return true; }
JS_SetWatchPoint(JSContext *cx, JSObject *obj, jsval id, JSWatchPointHandler handler, void *closure) { JSAtom *atom; jsid propid; JSObject *pobj; JSScopeProperty *sprop; JSRuntime *rt; JSWatchPoint *wp; JSPropertyOp watcher; if (!OBJ_IS_NATIVE(obj)) { JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_CANT_WATCH, OBJ_GET_CLASS(cx, obj)->name); return JS_FALSE; } if (JSVAL_IS_INT(id)) { propid = (jsid)id; atom = NULL; } else { atom = js_ValueToStringAtom(cx, id); if (!atom) return JS_FALSE; propid = (jsid)atom; } if (!js_LookupProperty(cx, obj, propid, &pobj, (JSProperty **)&sprop)) return JS_FALSE; rt = cx->runtime; if (!sprop) { /* Check for a deleted symbol watchpoint, which holds its property. */ sprop = js_FindWatchPoint(rt, OBJ_SCOPE(obj), propid); if (!sprop) { /* Make a new property in obj so we can watch for the first set. */ if (!js_DefineProperty(cx, obj, propid, JSVAL_VOID, NULL, NULL, JSPROP_ENUMERATE, (JSProperty **)&sprop)) { sprop = NULL; } } } else if (pobj != obj) { /* Clone the prototype property so we can watch the right object. */ jsval value; JSPropertyOp getter, setter; uintN attrs; if (OBJ_IS_NATIVE(pobj)) { value = SPROP_HAS_VALID_SLOT(sprop, OBJ_SCOPE(pobj)) ? LOCKED_OBJ_GET_SLOT(pobj, sprop->slot) : JSVAL_VOID; getter = sprop->getter; setter = sprop->setter; attrs = sprop->attrs; } else { if (!OBJ_GET_PROPERTY(cx, pobj, id, &value)) { OBJ_DROP_PROPERTY(cx, pobj, (JSProperty *)sprop); return JS_FALSE; } getter = setter = JS_PropertyStub; attrs = JSPROP_ENUMERATE; } OBJ_DROP_PROPERTY(cx, pobj, (JSProperty *)sprop); if (!js_DefineProperty(cx, obj, propid, value, getter, setter, attrs, (JSProperty **)&sprop)) { sprop = NULL; } } if (!sprop) return JS_FALSE; wp = FindWatchPoint(rt, OBJ_SCOPE(obj), propid); if (!wp) { watcher = js_WrapWatchedSetter(cx, propid, sprop->attrs, sprop->setter); if (!watcher) return JS_FALSE; wp = (JSWatchPoint *) JS_malloc(cx, sizeof *wp); if (!wp) return JS_FALSE; wp->handler = NULL; wp->closure = NULL; if (!js_AddRoot(cx, &wp->closure, "wp->closure")) { JS_free(cx, wp); return JS_FALSE; } JS_APPEND_LINK(&wp->links, &rt->watchPointList); wp->object = obj; wp->sprop = sprop; JS_ASSERT(sprop->setter != js_watch_set); wp->setter = sprop->setter; wp->nrefs = 1; sprop = js_ChangeNativePropertyAttrs(cx, obj, sprop, 0, sprop->attrs, sprop->getter, watcher); if (!sprop) return DropWatchPoint(cx, wp); } wp->handler = handler; wp->closure = closure; OBJ_DROP_PROPERTY(cx, obj, (JSProperty *)sprop); return JS_TRUE; }
/**doc $TOC_MEMBER $INAME $INAME( [init] ) Creates a new Transformation object. If no argument is given, the transformation is not initialized. If _init_ is $NULL, the transformation is initialized to identity. If _init_ is a matrix, the transormation is initialized with the matrix. **/ DEFINE_CONSTRUCTOR() { TransformationPrivate *pv = NULL; JL_DEFINE_ARGS; JL_DEFINE_CONSTRUCTOR_OBJ; JL_ASSERT_ARGC_RANGE(0, 16); // JL_ASSERT_CONSTRUCTING(); pv = (TransformationPrivate *)JS_malloc(cx, sizeof(TransformationPrivate)); JL_CHK(pv); pv->mat = NULL; // see bad: pv->mat = PoolIsEmpty(&matrixPool) ? Matrix44Alloc() : (Matrix44*)jl::PoolPop(&matrixPool); JL_ASSERT_ALLOC(pv->mat); if ( JL_ARGC >= 1 ) { if ( JL_ARG(1).isObject() ) { JL_ASSERT_ARGC(1); Matrix44 *m = pv->mat; JL_CHK( GetMatrixHelper(cx, JL_ARG(1), (float**)&m) ); if ( m != pv->mat ) // check if the pointer has been modified Matrix44Load(pv->mat, m); pv->isIdentity = false; } else /* if ( JSVAL_IS_NULL(JL_ARG(1)) ) { Matrix44Identity(pv->mat); pv->isIdentity = true; } else */ if ( JL_ARGC == 16 ) { float *tmp = (float*)&pv->mat->raw; for ( int i = 0; i < 16; ++i ) JL_CHK( jl::getValue(cx, JL_ARG(i+1), (tmp++)) ); // see JL_CHK( jl::getVector(cx, *JL_ARGV, tmp, 16, &len) ); pv->isIdentity = false; } else { JL_ERR( E_ARGC, E_EQUALS, E_NUM(16) ); } } // else uninitialized matrix JL_CHK( jl::setMatrix44GetInterface(cx, JL_OBJ, GetMatrix) ); JL_SetPrivate(JL_OBJ, pv); return true; bad: if ( pv ) { if ( pv->mat ) Matrix44Free(pv->mat); JS_free(cx, pv); } return false; }
int SpiderMonkeyMain(int argc, char ** argv, char ** envp) { JSContext * context = InitializeSpiderMonkey(); JSObject * global = JS_NewCompartmentAndGlobalObject(context, &global_class, NULL); JS_InitStandardClasses(context, global); int c, r = 0; JSObject * env; jsval result; while (1) { static struct option long_options[] = { /* These options set a flag. */ {"verbose", no_argument, &verbose_flag, 1}, {"brief", no_argument, &verbose_flag, 0}, /* These options don’t set a flag. We distinguish them by their indices. */ {"print-result", no_argument, 0, 'p'}, {"run-script", no_argument, 0, 'r'}, {"shell-script", required_argument, 0, 's'}, {0, 0, 0, 0} }; /* getopt_long stores the option index here. */ int option_index = 0; c = getopt_long(argc, argv, "prs:", long_options, &option_index); /* Detect the end of the options. */ if (c == -1) { //printf ("got end of options\n"); break; } switch (c) { case 0: /* If this option set a flag, do nothing else now. */ if (long_options[option_index].flag != 0) break; printf("option %s", long_options[option_index].name); if (optarg) printf(" with arg %s", optarg); printf("\n"); break; case 'p': print_result_flag = 1; break; case 'r': printf("option -r with value `%s'\n", optarg); break; case 's': r = ExecShellScript(optarg, argc - optind, argv + optind, context, global, &result); if (r == JS_FALSE && exitcode == 0) exitcode = 1; optind = argc; break; case '?': /* getopt_long already printed an error message. */ break; default: break; } } if (print_result_flag && result) { JSString * result_string = JS_ValueToString(context, result); char * bytes = JS_EncodeString(context, result_string); if (!bytes) { return 1; } else { printf("%s\n", bytes); JS_free(context, bytes); } } TerminateSpiderMonkey(context); /* Print any remaining command line arguments (not options). */ if (optind < argc) { printf("non-option ARGV-elements: "); while (optind < argc) printf("%s ", argv[optind++]); putchar('\n'); } return (exitcode); }
/* * Add a single field, described by java_field, to the JavaMemberDescriptor * named by field_name within the given JavaClassDescriptor. * * Returns JS_TRUE on success. Otherwise, returns JS_FALSE and reports an error. */ static JSBool add_java_field_to_class_descriptor(JSContext *cx, JNIEnv *jEnv, JavaClassDescriptor *class_descriptor, jstring field_name_jstr, jobject java_field, /* a java.lang.reflect.Field */ jint modifiers) { jclass fieldType; jfieldID fieldID; jclass java_class; JSBool is_static_field; JavaMemberDescriptor *member_descriptor = NULL; const char *sig_cstr = NULL; const char *field_name = NULL; JavaSignature *signature = NULL; JavaFieldSpec *field_spec = NULL; is_static_field = modifiers & ACC_STATIC; if (is_static_field) { member_descriptor = jsj_GetJavaStaticMemberDescriptor(cx, jEnv, class_descriptor, field_name_jstr); } else { member_descriptor = jsj_GetJavaMemberDescriptor(cx, jEnv, class_descriptor, field_name_jstr); } if (!member_descriptor) goto error; field_spec = (JavaFieldSpec*)JS_malloc(cx, sizeof(JavaFieldSpec)); if (!field_spec) goto error; field_spec->modifiers = modifiers; /* Get the Java class corresponding to the type of the field */ fieldType = (*jEnv)->CallObjectMethod(jEnv, java_field, jlrField_getType); if (!fieldType) { jsj_UnexpectedJavaError(cx, jEnv, "Unable to determine type of field using" " java.lang.reflect.Field.getType()"); goto error; } signature = jsj_GetJavaClassDescriptor(cx, jEnv, fieldType); (*jEnv)->DeleteLocalRef(jEnv, fieldType); if (!signature) goto error; field_spec->signature = signature; field_name = jsj_DupJavaStringUTF(cx, jEnv, field_name_jstr); if (!field_name) goto error; field_spec->name = field_name; /* Compute the JNI-style (string-based) signature of the field type */ sig_cstr = jsj_ConvertJavaSignatureToString(cx, signature); if (!sig_cstr) goto error; /* Compute the JNI fieldID and cache it for quick field access */ java_class = class_descriptor->java_class; if (is_static_field) fieldID = (*jEnv)->GetStaticFieldID(jEnv, java_class, field_name, sig_cstr); else fieldID = (*jEnv)->GetFieldID(jEnv, java_class, field_name, sig_cstr); if (!fieldID) { jsj_UnexpectedJavaError(cx, jEnv, "Can't get Java field ID for class %s, field %s (sig=%s)", class_descriptor->name, field_name, sig_cstr); goto error; } field_spec->fieldID = fieldID; JS_free(cx, (char*)sig_cstr); member_descriptor->field = field_spec; /* Success */ return JS_TRUE; error: if (field_spec) { JS_FREE_IF(cx, (char*)field_spec->name); JS_free(cx, field_spec); } JS_FREE_IF(cx, (char*)sig_cstr); if (signature) jsj_ReleaseJavaClassDescriptor(cx, jEnv, signature); return JS_FALSE; }
JSObject* Library::Create(JSContext* cx, jsval path, JSCTypesCallbacks* callbacks) { JSObject* libraryObj = JS_NewObject(cx, &sLibraryClass, NULL, NULL); if (!libraryObj) return NULL; js::AutoObjectRooter root(cx, libraryObj); // initialize the library if (!JS_SetReservedSlot(cx, libraryObj, SLOT_LIBRARY, PRIVATE_TO_JSVAL(NULL))) return NULL; // attach API functions if (!JS_DefineFunctions(cx, libraryObj, sLibraryFunctions)) return NULL; if (!JSVAL_IS_STRING(path)) { JS_ReportError(cx, "open takes a string argument"); return NULL; } PRLibSpec libSpec; JSFlatString* pathStr = JS_FlattenString(cx, JSVAL_TO_STRING(path)); if (!pathStr) return NULL; #ifdef XP_WIN // On Windows, converting to native charset may corrupt path string. // So, we have to use Unicode path directly. const PRUnichar* pathChars = JS_GetFlatStringChars(pathStr); if (!pathChars) return NULL; libSpec.value.pathname_u = pathChars; libSpec.type = PR_LibSpec_PathnameU; #else // Convert to platform native charset if the appropriate callback has been // provided. char* pathBytes; if (callbacks && callbacks->unicodeToNative) { pathBytes = callbacks->unicodeToNative(cx, pathStr->chars(), pathStr->length()); if (!pathBytes) return NULL; } else { // Fallback: assume the platform native charset is UTF-8. This is true // for Mac OS X, Android, and probably Linux. size_t nbytes = GetDeflatedUTF8StringLength(cx, pathStr->chars(), pathStr->length()); if (nbytes == (size_t) -1) return NULL; pathBytes = static_cast<char*>(JS_malloc(cx, nbytes + 1)); if (!pathBytes) return NULL; ASSERT_OK(DeflateStringToUTF8Buffer(cx, pathStr->chars(), pathStr->length(), pathBytes, &nbytes)); pathBytes[nbytes] = 0; } libSpec.value.pathname = pathBytes; libSpec.type = PR_LibSpec_Pathname; #endif PRLibrary* library = PR_LoadLibraryWithFlags(libSpec, 0); #ifndef XP_WIN JS_free(cx, pathBytes); #endif if (!library) { JS_ReportError(cx, "couldn't open library"); return NULL; } // stash the library if (!JS_SetReservedSlot(cx, libraryObj, SLOT_LIBRARY, PRIVATE_TO_JSVAL(library))) return NULL; return libraryObj; }
static void mem_finalize(JSXDRState *xdr) { JS_free(xdr->cx, MEM_BASE(xdr)); }
JSURL * lm_NewURL(JSContext *cx, MochaDecoder *decoder, LO_AnchorData *anchor_data, JSObject *document) { JSObject *obj; JSURL *url; JSString *str; if (!decoder->url_prototype) { obj = JS_InitClass(cx, decoder->window_object, decoder->event_receiver_prototype, &lm_url_class, Url, 0, url_props, NULL, NULL, NULL); if (!obj) return NULL; decoder->url_prototype = obj; } url = JS_malloc(cx, sizeof *url); if (!url) return NULL; XP_BZERO(url, sizeof *url); obj = JS_NewObject(cx, &lm_url_class, decoder->url_prototype, lm_GetOuterObject(decoder)); if (!obj || !JS_SetPrivate(cx, obj, url)) { JS_free(cx, url); return NULL; } if (!JS_DefineFunctions(cx, obj, url_methods)) return NULL; url->url_decoder = HOLD_BACK_COUNT(decoder); url->url_type = FORM_TYPE_NONE; url->index = URL_NOT_INDEXED; url->url_object = obj; str = JS_NewStringCopyZ(cx, (char *) anchor_data->anchor); if (!str) return NULL; url->href = str; if (!JS_AddNamedRoot(cx, &url->href, "url.href")) return NULL; if (anchor_data->target) { str = JS_NewStringCopyZ(cx, (char *) anchor_data->target); if (!str) return NULL; url->target = str; } if (!JS_AddNamedRoot(cx, &url->target, "url.target")) return NULL; if (anchor_data->element && anchor_data->element->type == LO_TEXT) { str = lm_LocalEncodingToStr(decoder->window_context, (char *) anchor_data->element->lo_text.text); if (!str) return NULL; url->text = str; } if (!JS_AddNamedRoot(cx, &url->text, "url.text")) return NULL; return url; }
/* Return a chunk of memory which is mapped to the underlying media */ static void * xdrfile_raw (JSXDRState *xdr, uint32 len) { /* If mmap is enabled, this is a rather simple case */ #ifdef XDR_USES_MMAP if (self->mappos) { void *rval = self->mappos; /* Bounds check */ if (self->mappos + len > self->mapend) { JS_ReportError(xdr->cx, "unexpected end of file"); return NULL; } self->mappos = (unsigned char*)self->mappos + len; return rval; } #endif /* Commit 'raw' chunk if necessary */ xdrfile_commit_raw(xdr); /* Do we need a bigger buffer than what we've already allocated? */ if (len > self->rawsize) { /* Free any previous buffer */ if (self->raw) JS_free(xdr->cx, self->raw); /* Allocate a new buffer */ self->raw = (void*)JS_malloc(xdr->cx, len); /* Make sure our buffer was successfully allocated */ if (!self->raw) { self->rawlen = 0; self->rawlive = 0; self->rawsize = 0; return NULL; } /* rawsize reflects the size of our actual buffer */ self->rawsize = len; } /* rawlen reflects the requested 'raw' chunk size */ self->rawlen = len; /* mark this 'raw' buffer as needing to be committed */ self->rawlive = 1; /* If we're deserializing, we need to read the file into the buffer */ if (xdr->mode != JSXDR_ENCODE) { size_t n; /* Fill our 'raw' chunk from the underlying file */ n = fread(self->raw, 1, len, self->f); if (n < len) { JS_ReportError(xdr->cx, "unexpected end of file"); return NULL; } } return self->raw; }
char *copy_jsstring(JSContext *cx, JSString *source) { char *buf = JS_EncodeString(cx, source); char *retval = copy_string(buf); JS_free(cx, buf); return retval; }
static JSBool global_resolve(JSContext *cx, JSObject *obj, jsid id, uintN flags, JSObject **objp) { if ((flags & JSRESOLVE_ASSIGNING) == 0) { JSBool resolved; if (!JS_ResolveStandardClass(cx, obj, id, &resolved)) return JS_FALSE; if (resolved) { *objp = obj; return JS_TRUE; } } #if defined(SHELL_HACK) && defined(DEBUG) && defined(XP_UNIX) if ((flags & (JSRESOLVE_QUALIFIED | JSRESOLVE_ASSIGNING)) == 0) { /* * Do this expensive hack only for unoptimized Unix builds, which are * not used for benchmarking. */ char *path, *comp, *full; const char *name; JSBool ok, found; JSFunction *fun; if (!JSVAL_IS_STRING(id)) return JS_TRUE; path = getenv("PATH"); if (!path) return JS_TRUE; path = JS_strdup(cx, path); if (!path) return JS_FALSE; name = JS_GetStringBytes(JSVAL_TO_STRING(id)); ok = JS_TRUE; for (comp = strtok(path, ":"); comp; comp = strtok(NULL, ":")) { if (*comp != '\0') { full = JS_smprintf("%s/%s", comp, name); if (!full) { JS_ReportOutOfMemory(cx); ok = JS_FALSE; break; } } else { full = (char *)name; } found = (access(full, X_OK) == 0); if (*comp != '\0') free(full); if (found) { fun = JS_DefineFunction(cx, obj, name, Exec, 0, JSPROP_ENUMERATE); ok = (fun != NULL); if (ok) *objp = obj; break; } } JS_free(cx, path); return ok; } #else return JS_TRUE; #endif }
void js_LeaveLocalRootScopeWithResult(JSContext *cx, jsval rval) { JSLocalRootStack *lrs; uint32 mark, m, n; JSLocalRootChunk *lrc; /* Defend against buggy native callers. */ lrs = cx->localRootStack; JS_ASSERT(lrs && lrs->rootCount != 0); if (!lrs || lrs->rootCount == 0) return; mark = lrs->scopeMark; JS_ASSERT(mark != JSLRS_NULL_MARK); if (mark == JSLRS_NULL_MARK) return; /* Free any chunks being popped by this leave operation. */ m = mark >> JSLRS_CHUNK_SHIFT; n = (lrs->rootCount - 1) >> JSLRS_CHUNK_SHIFT; while (n > m) { lrc = lrs->topChunk; JS_ASSERT(lrc != &lrs->firstChunk); lrs->topChunk = lrc->down; JS_free(cx, lrc); --n; } /* * Pop the scope, restoring lrs->scopeMark. If rval is a GC-thing, push * it on the caller's scope, or store it in lastInternalResult if we are * leaving the outermost scope. We don't need to allocate a new lrc * because we can overwrite the old mark's slot with rval. */ lrc = lrs->topChunk; m = mark & JSLRS_CHUNK_MASK; lrs->scopeMark = (uint32) JSVAL_TO_INT(lrc->roots[m]); if (JSVAL_IS_GCTHING(rval) && !JSVAL_IS_NULL(rval)) { if (mark == 0) { cx->weakRoots.lastInternalResult = rval; } else { /* * Increment m to avoid the "else if (m == 0)" case below. If * rval is not a GC-thing, that case would take care of freeing * any chunk that contained only the old mark. Since rval *is* * a GC-thing here, we want to reuse that old mark's slot. */ lrc->roots[m++] = rval; ++mark; } } lrs->rootCount = (uint32) mark; /* * Free the stack eagerly, risking malloc churn. The alternative would * require an lrs->entryCount member, maintained by Enter and Leave, and * tested by the GC in addition to the cx->localRootStack non-null test. * * That approach would risk hoarding 264 bytes (net) per context. Right * now it seems better to give fresh (dirty in CPU write-back cache, and * the data is no longer needed) memory back to the malloc heap. */ if (mark == 0) { cx->localRootStack = NULL; JS_free(cx, lrs); } else if (m == 0) { lrs->topChunk = lrc->down; JS_free(cx, lrc); } }
static JSString * StackTraceToString(JSContext *cx, JSExnPrivate *priv) { jschar *stackbuf; size_t stacklen, stackmax; JSStackTraceElem *elem, *endElem; jsval *values; size_t i; JSString *str; const char *cp; char ulnbuf[11]; /* After this point, failing control flow must goto bad. */ stackbuf = NULL; stacklen = stackmax = 0; /* Limit the stackbuf length to a reasonable value to avoid overflow checks. */ #define STACK_LENGTH_LIMIT JS_BIT(20) #define APPEND_CHAR_TO_STACK(c) \ JS_BEGIN_MACRO \ if (stacklen == stackmax) { \ void *ptr_; \ if (stackmax >= STACK_LENGTH_LIMIT) \ goto done; \ stackmax = stackmax ? 2 * stackmax : 64; \ ptr_ = JS_realloc(cx, stackbuf, (stackmax+1) * sizeof(jschar)); \ if (!ptr_) \ goto bad; \ stackbuf = (jschar *) ptr_; \ } \ stackbuf[stacklen++] = (c); \ JS_END_MACRO #define APPEND_STRING_TO_STACK(str) \ JS_BEGIN_MACRO \ JSString *str_ = str; \ jschar *chars_; \ size_t length_; \ \ JSSTRING_CHARS_AND_LENGTH(str_, chars_, length_); \ if (length_ > stackmax - stacklen) { \ void *ptr_; \ if (stackmax >= STACK_LENGTH_LIMIT || \ length_ >= STACK_LENGTH_LIMIT - stacklen) { \ goto done; \ } \ stackmax = JS_BIT(JS_CeilingLog2(stacklen + length_)); \ ptr_ = JS_realloc(cx, stackbuf, (stackmax+1) * sizeof(jschar)); \ if (!ptr_) \ goto bad; \ stackbuf = (jschar *) ptr_; \ } \ js_strncpy(stackbuf + stacklen, chars_, length_); \ stacklen += length_; \ JS_END_MACRO values = GetStackTraceValueBuffer(priv); elem = priv->stackElems; for (endElem = elem + priv->stackDepth; elem != endElem; elem++) { if (elem->funName) { APPEND_STRING_TO_STACK(elem->funName); APPEND_CHAR_TO_STACK('('); for (i = 0; i != elem->argc; i++, values++) { if (i > 0) APPEND_CHAR_TO_STACK(','); str = ValueToShortSource(cx, *values); if (!str) goto bad; APPEND_STRING_TO_STACK(str); } APPEND_CHAR_TO_STACK(')'); } APPEND_CHAR_TO_STACK('@'); if (elem->filename) { for (cp = elem->filename; *cp; cp++) APPEND_CHAR_TO_STACK(*cp); } APPEND_CHAR_TO_STACK(':'); JS_snprintf(ulnbuf, sizeof ulnbuf, "%u", elem->ulineno); for (cp = ulnbuf; *cp; cp++) APPEND_CHAR_TO_STACK(*cp); APPEND_CHAR_TO_STACK('\n'); } #undef APPEND_CHAR_TO_STACK #undef APPEND_STRING_TO_STACK #undef STACK_LENGTH_LIMIT done: if (stacklen == 0) { JS_ASSERT(!stackbuf); return cx->runtime->emptyString; } if (stacklen < stackmax) { /* * Realloc can fail when shrinking on some FreeBSD versions, so * don't use JS_realloc here; simply let the oversized allocation * be owned by the string in that rare case. */ void *shrunk = JS_realloc(cx, stackbuf, (stacklen+1) * sizeof(jschar)); if (shrunk) stackbuf = (jschar *) shrunk; } stackbuf[stacklen] = 0; str = js_NewString(cx, stackbuf, stacklen); if (str) return str; bad: if (stackbuf) JS_free(cx, stackbuf); return NULL; }
static JSBool go(JSContext* cx, JSObject* obj, HTTPData* http, char* body, size_t bodylen) { CurlState state; char* referer; JSString* jsbody; JSBool ret = JS_FALSE; jsval tmp; state.cx = cx; state.http = http; state.sendbuf = body; state.sendlen = bodylen; state.sent = 0; state.sent_once = 0; state.recvbuf = NULL; state.recvlen = 0; state.read = 0; if(HTTP_HANDLE == NULL) { HTTP_HANDLE = curl_easy_init(); curl_easy_setopt(HTTP_HANDLE, CURLOPT_READFUNCTION, send_body); curl_easy_setopt(HTTP_HANDLE, CURLOPT_SEEKFUNCTION, (curl_seek_callback) seek_body); curl_easy_setopt(HTTP_HANDLE, CURLOPT_HEADERFUNCTION, recv_header); curl_easy_setopt(HTTP_HANDLE, CURLOPT_WRITEFUNCTION, recv_body); curl_easy_setopt(HTTP_HANDLE, CURLOPT_NOPROGRESS, 1); curl_easy_setopt(HTTP_HANDLE, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4); curl_easy_setopt(HTTP_HANDLE, CURLOPT_ERRORBUFFER, ERRBUF); curl_easy_setopt(HTTP_HANDLE, CURLOPT_COOKIEFILE, ""); curl_easy_setopt(HTTP_HANDLE, CURLOPT_USERAGENT, "CouchHTTP Client - Relax"); } if(!HTTP_HANDLE) { JS_ReportError(cx, "Failed to initialize cURL handle."); goto done; } if(!JS_GetReservedSlot(cx, obj, 0, &tmp)) { JS_ReportError(cx, "Failed to readreserved slot."); goto done; } if(!(referer = enc_string(cx, tmp, NULL))) { JS_ReportError(cx, "Failed to encode referer."); goto done; } curl_easy_setopt(HTTP_HANDLE, CURLOPT_REFERER, referer); free(referer); if(http->method < 0 || http->method > OPTIONS) { JS_ReportError(cx, "INTERNAL: Unknown method."); goto done; } curl_easy_setopt(HTTP_HANDLE, CURLOPT_CUSTOMREQUEST, METHODS[http->method]); curl_easy_setopt(HTTP_HANDLE, CURLOPT_NOBODY, 0); curl_easy_setopt(HTTP_HANDLE, CURLOPT_FOLLOWLOCATION, 1); curl_easy_setopt(HTTP_HANDLE, CURLOPT_UPLOAD, 0); if(http->method == HEAD) { curl_easy_setopt(HTTP_HANDLE, CURLOPT_NOBODY, 1); curl_easy_setopt(HTTP_HANDLE, CURLOPT_FOLLOWLOCATION, 0); } else if(http->method == POST || http->method == PUT) { curl_easy_setopt(HTTP_HANDLE, CURLOPT_UPLOAD, 1); curl_easy_setopt(HTTP_HANDLE, CURLOPT_FOLLOWLOCATION, 0); } if(body && bodylen) { curl_easy_setopt(HTTP_HANDLE, CURLOPT_INFILESIZE, bodylen); } else { curl_easy_setopt(HTTP_HANDLE, CURLOPT_INFILESIZE, 0); } // curl_easy_setopt(HTTP_HANDLE, CURLOPT_VERBOSE, 1); curl_easy_setopt(HTTP_HANDLE, CURLOPT_URL, http->url); curl_easy_setopt(HTTP_HANDLE, CURLOPT_HTTPHEADER, http->req_headers); curl_easy_setopt(HTTP_HANDLE, CURLOPT_READDATA, &state); curl_easy_setopt(HTTP_HANDLE, CURLOPT_SEEKDATA, &state); curl_easy_setopt(HTTP_HANDLE, CURLOPT_WRITEHEADER, &state); curl_easy_setopt(HTTP_HANDLE, CURLOPT_WRITEDATA, &state); if(curl_easy_perform(HTTP_HANDLE) != 0) { JS_ReportError(cx, "Failed to execute HTTP request: %s", ERRBUF); goto done; } if(!state.resp_headers) { JS_ReportError(cx, "Failed to recieve HTTP headers."); goto done; } tmp = OBJECT_TO_JSVAL(state.resp_headers); if(!JS_DefineProperty( cx, obj, "_headers", tmp, NULL, NULL, JSPROP_READONLY )) { JS_ReportError(cx, "INTERNAL: Failed to set response headers."); goto done; } if(state.recvbuf) { state.recvbuf[state.read] = '\0'; jsbody = dec_string(cx, state.recvbuf, state.read+1); if(!jsbody) { // If we can't decode the body as UTF-8 we forcefully // convert it to a string by just forcing each byte // to a jschar. jsbody = str_from_binary(cx, state.recvbuf, state.read); if(!jsbody) { if(!JS_IsExceptionPending(cx)) { JS_ReportError(cx, "INTERNAL: Failed to decode body."); } goto done; } } tmp = STRING_TO_JSVAL(jsbody); } else { tmp = JS_GetEmptyStringValue(cx); } if(!JS_DefineProperty( cx, obj, "responseText", tmp, NULL, NULL, JSPROP_READONLY )) { JS_ReportError(cx, "INTERNAL: Failed to set responseText."); goto done; } ret = JS_TRUE; done: if(state.recvbuf) JS_free(cx, state.recvbuf); return ret; }
void js_DestroyContext(JSContext *cx, JSGCMode gcmode) { JSRuntime *rt; JSBool last; JSArgumentFormatMap *map; JSLocalRootStack *lrs; JSLocalRootChunk *lrc; rt = cx->runtime; /* Remove cx from context list first. */ JS_LOCK_GC(rt); JS_ASSERT(rt->state == JSRTS_UP || rt->state == JSRTS_LAUNCHING); JS_REMOVE_LINK(&cx->links); last = (rt->contextList.next == &rt->contextList); if (last) rt->state = JSRTS_LANDING; JS_UNLOCK_GC(rt); if (last) { #ifdef JS_THREADSAFE /* * If cx is not in a request already, begin one now so that we wait * for any racing GC started on a not-last context to finish, before * we plow ahead and unpin atoms. Note that even though we begin a * request here if necessary, we end all requests on cx below before * forcing a final GC. This lets any not-last context destruction * racing in another thread try to force or maybe run the GC, but by * that point, rt->state will not be JSRTS_UP, and that GC attempt * will return early. */ if (cx->requestDepth == 0) JS_BeginRequest(cx); #endif /* Unpin all pinned atoms before final GC. */ js_UnpinPinnedAtoms(&rt->atomState); /* Unlock and clear GC things held by runtime pointers. */ js_FinishRuntimeNumberState(cx); js_FinishRuntimeStringState(cx); /* Clear debugging state to remove GC roots. */ JS_ClearAllTraps(cx); JS_ClearAllWatchPoints(cx); } #if JS_HAS_REGEXPS /* * Remove more GC roots in regExpStatics, then collect garbage. * XXX anti-modularity alert: we rely on the call to js_RemoveRoot within * XXX this function call to wait for any racing GC to complete, in the * XXX case where JS_DestroyContext is called outside of a request on cx */ js_FreeRegExpStatics(cx, &cx->regExpStatics); #endif #ifdef JS_THREADSAFE /* * Destroying a context implicitly calls JS_EndRequest(). Also, we must * end our request here in case we are "last" -- in that event, another * js_DestroyContext that was not last might be waiting in the GC for our * request to end. We'll let it run below, just before we do the truly * final GC and then free atom state. * * At this point, cx must be inaccessible to other threads. It's off the * rt->contextList, and it should not be reachable via any object private * data structure. */ while (cx->requestDepth != 0) JS_EndRequest(cx); #endif if (last) { /* Always force, so we wait for any racing GC to finish. */ js_ForceGC(cx, GC_LAST_CONTEXT); /* Iterate until no finalizer removes a GC root or lock. */ while (rt->gcPoke) js_GC(cx, GC_LAST_CONTEXT); /* Try to free atom state, now that no unrooted scripts survive. */ if (rt->atomState.liveAtoms == 0) js_FreeAtomState(cx, &rt->atomState); /* Now after the last GC can we free the script filename table. */ js_FinishRuntimeScriptState(cx); /* Take the runtime down, now that it has no contexts or atoms. */ JS_LOCK_GC(rt); rt->state = JSRTS_DOWN; JS_NOTIFY_ALL_CONDVAR(rt->stateChange); JS_UNLOCK_GC(rt); } else { if (gcmode == JS_FORCE_GC) js_ForceGC(cx, 0); else if (gcmode == JS_MAYBE_GC) JS_MaybeGC(cx); } /* Free the stuff hanging off of cx. */ JS_FinishArenaPool(&cx->stackPool); JS_FinishArenaPool(&cx->tempPool); if (cx->lastMessage) free(cx->lastMessage); /* Remove any argument formatters. */ map = cx->argumentFormatMap; while (map) { JSArgumentFormatMap *temp = map; map = map->next; JS_free(cx, temp); } /* Destroy the resolve recursion damper. */ if (cx->resolvingTable) { JS_DHashTableDestroy(cx->resolvingTable); cx->resolvingTable = NULL; } lrs = cx->localRootStack; if (lrs) { while ((lrc = lrs->topChunk) != &lrs->firstChunk) { lrs->topChunk = lrc->down; JS_free(cx, lrc); } JS_free(cx, lrs); } /* Destroy the lint information */ if (cx->lint) { JS_free(cx, cx->lint); } /* Finally, free cx itself. */ free(cx); }
static JSBool vm_isCompilableUnit(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) { JSString *str; jsrefcount depth; size_t len, maxLen = 0; char *buf; size_t i; /** Coerce all args .toString() and calculate maximal buffer size */ for (i = 0; i < argc; i++) { if (!JSVAL_IS_STRING(argv[i])) { str = JS_ValueToString(cx, argv[i]); argv[i] = STRING_TO_JSVAL(str); } else str = JSVAL_TO_STRING(argv[i]); len = JS_GetStringLength(JSVAL_TO_STRING(argv[i])); if (len > maxLen) maxLen = len; } buf = JS_malloc(cx, maxLen + 1); if (!buf) return JS_FALSE; if (argc > 1) { for (i = 0; i < (argc - 1); i++) { str = JS_ValueToString(cx, argv[i]); if (!str) { JS_free(cx, buf); return JS_FALSE; } strcpy(buf, JS_GetStringBytes(str)); depth = JS_SuspendRequest(cx); gpsee_printf(cx, "%s%s", i ? " " : "", buf); JS_ResumeRequest(cx, depth); } } else i = 0; if (argc) { str = JS_ValueToString(cx, argv[i]); if (!str) { JS_free(cx, buf); return JS_FALSE; } strcpy(buf, JS_GetStringBytes(str)); } else *buf = (char)0; *rval = JS_BufferIsCompilableUnit(cx, obj, buf, strlen(buf)) == JS_TRUE ? JSVAL_TRUE : JSVAL_FALSE; JS_free(cx, buf); return JS_TRUE; }
JSBool openfiledlg(JSContext * cx, JSObject * obj, uintN argc, jsval * argv, jsval * rval) { JSObject * filterArray = NULL; LPWSTR initialDirectory = NULL; LPWSTR dlgTitle = NULL; LPWSTR defaultExtension = NULL; JSBool save = JS_FALSE; JS_BeginRequest(cx); if(!JS_ConvertArguments(cx, argc, argv, "W W W o/ b", &initialDirectory, &defaultExtension, &dlgTitle, &filterArray, &save)) { JS_ReportError(cx, "Error parsing arguments in OpenFileDialog"); JS_EndRequest(cx); return JS_FALSE; } jsuint nFilters; JS_GetArrayLength(cx, filterArray, &nFilters); LPWSTR filterBuffer = (LPWSTR)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, (50 * nFilters) * sizeof(WCHAR)); long filterBufferUsed = 0, filterBufferSize = (50 * nFilters); for(jsuint i = 0; i < nFilters; i++) { jsval curFilter; JS_GetElement(cx, filterArray, i, &curFilter); JSString * curFilterString = JS_ValueToString(cx, curFilter); LPWSTR curFilterRaw = (LPWSTR)JS_GetStringChars(curFilterString); int delta = wcslen(curFilterRaw); if(filterBufferSize - ( 2 + JS_GetStringLength(curFilterString) + filterBufferUsed) <= 0) { filterBufferSize += 50; HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, filterBuffer, filterBufferSize * sizeof(WCHAR)); } wcscpy_s(filterBuffer + filterBufferUsed, filterBufferSize - filterBufferUsed, (LPWSTR)JS_GetStringChars(curFilterString)); filterBufferUsed += JS_GetStringLength(curFilterString) + 1; } filterBuffer[filterBufferUsed] = TEXT('\0'); OPENFILENAME ofn; memset(&ofn, 0, sizeof(OPENFILENAME)); ofn.lStructSize = sizeof(OPENFILENAME); ofn.lpstrFilter = filterBuffer; ofn.nFilterIndex = 0; ofn.lpstrFile = (LPWSTR)JS_malloc(cx, 260 * sizeof(WCHAR)); memset(ofn.lpstrFile, 0, sizeof(WCHAR) * 260); ofn.nMaxFile = 260; ofn.lpstrFileTitle = (LPWSTR)JS_malloc(cx, 260 * sizeof(WCHAR)); memset(ofn.lpstrFileTitle, 0, sizeof(WCHAR) * 260); ofn.nMaxFileTitle = 260; ofn.lpstrInitialDir = initialDirectory; ofn.lpstrTitle = dlgTitle; ofn.lpstrDefExt = defaultExtension; ofn.lpfnHook = OFN_Hook; ofn.Flags = OFN_ENABLEHOOK | OFN_EXPLORER; jsrefcount rCount = JS_SuspendRequest(cx); BOOL ok; if(save) ok = GetSaveFileName(&ofn); else ok = GetOpenFileName(&ofn); DWORD errorCode = CommDlgExtendedError(); HeapFree(GetProcessHeap(), 0, filterBuffer); JS_ResumeRequest(cx, rCount); if(!ok) { JS_free(cx, ofn.lpstrFile); JS_free(cx, ofn.lpstrFileTitle); *rval = JSVAL_FALSE; return JS_TRUE; } JSObject * retObj = JS_NewObject(cx, NULL, NULL, obj); *rval = OBJECT_TO_JSVAL(retObj); jsval filePathVal = STRING_TO_JSVAL(JS_NewUCString(cx, (jschar*)ofn.lpstrFile, wcslen(ofn.lpstrFile))); JS_DefineProperty(cx, retObj, "filePath", filePathVal, NULL, NULL, JSPROP_PERMANENT | JSPROP_ENUMERATE); jsval fileTitleVal = STRING_TO_JSVAL(JS_NewUCString(cx, (jschar*)ofn.lpstrFileTitle, wcslen(ofn.lpstrFileTitle))); JS_DefineProperty(cx, retObj, "fileTitle", fileTitleVal, NULL, NULL, JSPROP_PERMANENT | JSPROP_ENUMERATE); JS_EndRequest(cx); return JS_TRUE; }
static JSBool array_join_sub(JSContext *cx, JSObject *obj, JSString *sep, JSBool literalize, jsval *rval, JSBool localeString) { JSBool ok; jsval v; jsuint length, index; jschar *chars, *ochars; size_t nchars, growth, seplen, tmplen; const jschar *sepstr; JSString *str; JSHashEntry *he; JSObject *obj2; ok = js_GetLengthProperty(cx, obj, &length); if (!ok) return JS_FALSE; he = js_EnterSharpObject(cx, obj, NULL, &chars); if (!he) return JS_FALSE; if (literalize) { if (IS_SHARP(he)) { #if JS_HAS_SHARP_VARS nchars = js_strlen(chars); #else chars[0] = '['; chars[1] = ']'; chars[2] = 0; nchars = 2; #endif goto make_string; } /* * Allocate 1 + 3 + 1 for "[", the worst-case closing ", ]", and the * terminating 0. */ growth = (1 + 3 + 1) * sizeof(jschar); if (!chars) { nchars = 0; chars = (jschar *) malloc(growth); if (!chars) goto done; } else { MAKE_SHARP(he); nchars = js_strlen(chars); chars = (jschar *) realloc((ochars = chars), nchars * sizeof(jschar) + growth); if (!chars) { free(ochars); goto done; } } chars[nchars++] = '['; } else { /* * Free any sharp variable definition in chars. Normally, we would * MAKE_SHARP(he) so that only the first sharp variable annotation is * a definition, and all the rest are references, but in the current * case of (!literalize), we don't need chars at all. */ if (chars) JS_free(cx, chars); chars = NULL; nchars = 0; /* Return the empty string on a cycle as well as on empty join. */ if (IS_BUSY(he) || length == 0) { js_LeaveSharpObject(cx, NULL); *rval = JS_GetEmptyStringValue(cx); return ok; } /* Flag he as BUSY so we can distinguish a cycle from a join-point. */ MAKE_BUSY(he); } sepstr = NULL; seplen = JSSTRING_LENGTH(sep); v = JSVAL_NULL; for (index = 0; index < length; index++) { ok = JS_GetElement(cx, obj, index, &v); if (!ok) goto done; if (!literalize && (JSVAL_IS_VOID(v) || JSVAL_IS_NULL(v))) { str = cx->runtime->emptyString; } else { if (localeString) { if (!js_ValueToObject(cx, v, &obj2) || !js_TryMethod(cx, obj2, cx->runtime->atomState.toLocaleStringAtom, 0, NULL, &v)) { str = NULL; } else { str = js_ValueToString(cx, v); } } else { str = (literalize ? js_ValueToSource : js_ValueToString)(cx, v); } if (!str) { ok = JS_FALSE; goto done; } } /* Allocate 3 + 1 at end for ", ", closing bracket, and zero. */ growth = (nchars + (sepstr ? seplen : 0) + JSSTRING_LENGTH(str) + 3 + 1) * sizeof(jschar); if (!chars) { chars = (jschar *) malloc(growth); if (!chars) goto done; } else { chars = (jschar *) realloc((ochars = chars), growth); if (!chars) { free(ochars); goto done; } } if (sepstr) { js_strncpy(&chars[nchars], sepstr, seplen); nchars += seplen; } sepstr = JSSTRING_CHARS(sep); tmplen = JSSTRING_LENGTH(str); js_strncpy(&chars[nchars], JSSTRING_CHARS(str), tmplen); nchars += tmplen; } done: if (literalize) { if (chars) { if (JSVAL_IS_VOID(v)) { chars[nchars++] = ','; chars[nchars++] = ' '; } chars[nchars++] = ']'; } } else { CLEAR_BUSY(he); } js_LeaveSharpObject(cx, NULL); if (!ok) { if (chars) free(chars); return ok; } make_string: if (!chars) { JS_ReportOutOfMemory(cx); return JS_FALSE; } chars[nchars] = 0; str = js_NewString(cx, chars, nchars, 0); if (!str) { free(chars); return JS_FALSE; } *rval = STRING_TO_JSVAL(str); return JS_TRUE; }
/* * Class: netscape_javascript_JSObject * Method: call * Signature: (Ljava/lang/String;[Ljava/lang/Object;)Ljava/lang/Object; */ JNIEXPORT jobject JNICALL Java_netscape_javascript_JSObject_call(JNIEnv *jEnv, jobject java_wrapper_obj, jstring function_name_jstr, jobjectArray java_args) { int i, argc, arg_num; jsval *argv; JSContext *cx = NULL; JSObject *js_obj; jsval js_val, function_val; int dummy_cost; JSBool dummy_bool; const jchar *function_name_ucs2; jsize function_name_len; JSErrorReporter saved_reporter; jboolean is_copy; jobject result; JSJavaThreadState *jsj_env; jsj_env = jsj_enter_js(jEnv, NULL, java_wrapper_obj, &cx, &js_obj, &saved_reporter, NULL, 0, NULL); if (!jsj_env) return NULL; function_name_ucs2 = NULL; result = NULL; if (!function_name_jstr) { JS_ReportErrorNumber(cx, jsj_GetErrorMessage, NULL, JSJMSG_NULL_FUNCTION_NAME); goto done; } /* Get the function name to eval as raw Unicode characters */ function_name_ucs2 = (*jEnv)->GetStringChars(jEnv, function_name_jstr, &is_copy); if (!function_name_ucs2) { JS_ASSERT(0); goto done; } function_name_len = (*jEnv)->GetStringLength(jEnv, function_name_jstr); /* Allocate space for JS arguments */ if (java_args) { argc = (*jEnv)->GetArrayLength(jEnv, java_args); argv = (jsval*)JS_malloc(cx, argc * sizeof(jsval)); } else { argc = 0; argv = 0; } /* Convert arguments from Java to JS values */ for (arg_num = 0; arg_num < argc; arg_num++) { jobject arg = (*jEnv)->GetObjectArrayElement(jEnv, java_args, arg_num); if (!jsj_ConvertJavaObjectToJSValue(cx, jEnv, arg, &argv[arg_num])) goto cleanup_argv; JS_AddNamedRoot(cx, &argv[arg_num], "&argv[arg_num]"); } if (!JS_GetUCProperty(cx, js_obj, function_name_ucs2, function_name_len, &function_val)) goto cleanup_argv; if (!JS_CallFunctionValue(cx, js_obj, function_val, argc, argv, &js_val)) goto cleanup_argv; jsj_ConvertJSValueToJavaObject(cx, jEnv, js_val, jsj_get_jlObject_descriptor(cx, jEnv), &dummy_cost, &result, &dummy_bool); cleanup_argv: if (argv) { for (i = 0; i < arg_num; i++) JS_RemoveRoot(cx, &argv[i]); JS_free(cx, argv); } done: if (function_name_ucs2) (*jEnv)->ReleaseStringChars(jEnv, function_name_jstr, function_name_ucs2); if (!jsj_exit_js(cx, jsj_env, saved_reporter)) return NULL; return result; }
/* XXXmccabe do the sort helper functions need to take int? (Or can we claim * that 2^32 * 32 is too large to worry about?) Something dumps when I change * to unsigned int; is qsort using -1 as a fencepost? */ static JSBool array_sort(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) { jsval fval; CompareArgs ca; jsuint len, newlen, i; jsval *vec; jsid id; size_t nbytes; /* * Optimize the default compare function case if all of obj's elements * have values of type string. */ JSBool all_strings; if (argc > 0) { if (JSVAL_IS_PRIMITIVE(argv[0])) { JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_BAD_SORT_ARG); return JS_FALSE; } fval = argv[0]; all_strings = JS_FALSE; /* non-default compare function */ } else { fval = JSVAL_NULL; all_strings = JS_TRUE; /* check for all string values */ } if (!js_GetLengthProperty(cx, obj, &len)) return JS_FALSE; if (len == 0) { *rval = OBJECT_TO_JSVAL(obj); return JS_TRUE; } /* * Test for size_t overflow, which could lead to indexing beyond the end * of the malloc'd vector. */ nbytes = len * sizeof(jsval); if (nbytes != (double) len * sizeof(jsval)) { JS_ReportOutOfMemory(cx); return JS_FALSE; } vec = (jsval *) JS_malloc(cx, nbytes); if (!vec) return JS_FALSE; #if JS_HAS_SPARSE_ARRAYS newlen = 0; #else newlen = len; #endif for (i = 0; i < len; i++) { ca.status = IndexToId(cx, i, &id); if (!ca.status) goto out; #if JS_HAS_SPARSE_ARRAYS { JSObject *obj2; JSProperty *prop; ca.status = OBJ_LOOKUP_PROPERTY(cx, obj, id, &obj2, &prop); if (!ca.status) goto out; if (!prop) { vec[i] = JSVAL_VOID; continue; } OBJ_DROP_PROPERTY(cx, obj2, prop); newlen++; } #endif ca.status = OBJ_GET_PROPERTY(cx, obj, id, &vec[i]); if (!ca.status) goto out; /* We know JSVAL_IS_STRING yields 0 or 1, so avoid a branch via &=. */ all_strings &= JSVAL_IS_STRING(vec[i]); } ca.context = cx; ca.fval = fval; ca.status = JS_TRUE; if (!js_HeapSort(vec, (size_t) len, sizeof(jsval), all_strings ? sort_compare_strings : sort_compare, &ca)) { JS_ReportOutOfMemory(cx); ca.status = JS_FALSE; } if (ca.status) { ca.status = InitArrayElements(cx, obj, newlen, vec); if (ca.status) *rval = OBJECT_TO_JSVAL(obj); #if JS_HAS_SPARSE_ARRAYS /* set length of newly-created array object to old length. */ if (ca.status && newlen < len) { ca.status = js_SetLengthProperty(cx, obj, len); /* Delete any leftover properties greater than newlen. */ while (ca.status && newlen < len) { jsval junk; ca.status = !IndexToId(cx, newlen, &id) || !OBJ_DELETE_PROPERTY(cx, obj, id, &junk); newlen++; } } #endif } out: if (vec) JS_free(cx, vec); return ca.status; }
/* * Return a string that may eval to something similar to the original object. */ static JSBool exn_toSource(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) { jsval v; JSString *name, *message, *filename, *lineno_as_str, *result; int32 lineno; size_t lineno_length, name_length, message_length, filename_length, length; jschar *chars, *cp; if (!OBJ_GET_PROPERTY(cx, obj, (jsid)cx->runtime->atomState.nameAtom, &v)) return JS_FALSE; name = js_ValueToString(cx, v); if (!name) return JS_FALSE; if (!JS_GetProperty(cx, obj, js_message_str, &v) || !(message = js_ValueToSource(cx, v))) { return JS_FALSE; } if (!JS_GetProperty(cx, obj, js_filename_str, &v) || !(filename = js_ValueToSource(cx, v))) { return JS_FALSE; } if (!JS_GetProperty(cx, obj, js_lineno_str, &v) || !js_ValueToInt32 (cx, v, &lineno)) { return JS_FALSE; } if (lineno != 0) { if (!(lineno_as_str = js_ValueToString(cx, v))) { return JS_FALSE; } lineno_length = JSSTRING_LENGTH(lineno_as_str); } else { lineno_as_str = NULL; lineno_length = 0; } /* Magic 8, for the characters in ``(new ())''. */ name_length = JSSTRING_LENGTH(name); message_length = JSSTRING_LENGTH(message); length = 8 + name_length + message_length; filename_length = JSSTRING_LENGTH(filename); if (filename_length != 0) { /* append filename as ``, {filename}'' */ length += 2 + filename_length; if (lineno_as_str) { /* append lineno as ``, {lineno_as_str}'' */ length += 2 + lineno_length; } } else { if (lineno_as_str) { /* * no filename, but have line number, * need to append ``, "", {lineno_as_str}'' */ length += 6 + lineno_length; } } cp = chars = (jschar*) JS_malloc(cx, (length + 1) * sizeof(jschar)); if (!chars) return JS_FALSE; *cp++ = '('; *cp++ = 'n'; *cp++ = 'e'; *cp++ = 'w'; *cp++ = ' '; js_strncpy(cp, JSSTRING_CHARS(name), name_length); cp += name_length; *cp++ = '('; if (message_length != 0) { js_strncpy(cp, JSSTRING_CHARS(message), message_length); cp += message_length; } if (filename_length != 0) { /* append filename as ``, {filename}'' */ *cp++ = ','; *cp++ = ' '; js_strncpy(cp, JSSTRING_CHARS(filename), filename_length); cp += filename_length; } else { if (lineno_as_str) { /* * no filename, but have line number, * need to append ``, "", {lineno_as_str}'' */ *cp++ = ','; *cp++ = ' '; *cp++ = '"'; *cp++ = '"'; } } if (lineno_as_str) { /* append lineno as ``, {lineno_as_str}'' */ *cp++ = ','; *cp++ = ' '; js_strncpy(cp, JSSTRING_CHARS(lineno_as_str), lineno_length); cp += lineno_length; } *cp++ = ')'; *cp++ = ')'; *cp = 0; result = js_NewString(cx, chars, length, 0); if (!result) { JS_free(cx, chars); return JS_FALSE; } *rval = STRING_TO_JSVAL(result); return JS_TRUE; }
JSObject* Library::Create(JSContext* cx, Value path_, const JSCTypesCallbacks* callbacks) { RootedValue path(cx, path_); RootedObject libraryObj(cx, JS_NewObject(cx, &sLibraryClass)); if (!libraryObj) return nullptr; // initialize the library JS_SetReservedSlot(libraryObj, SLOT_LIBRARY, PrivateValue(nullptr)); // attach API functions if (!JS_DefineFunctions(cx, libraryObj, sLibraryFunctions)) return nullptr; if (!path.isString()) { JS_ReportError(cx, "open takes a string argument"); return nullptr; } PRLibSpec libSpec; RootedFlatString pathStr(cx, JS_FlattenString(cx, path.toString())); if (!pathStr) return nullptr; AutoStableStringChars pathStrChars(cx); if (!pathStrChars.initTwoByte(cx, pathStr)) return nullptr; #ifdef XP_WIN // On Windows, converting to native charset may corrupt path string. // So, we have to use Unicode path directly. char16ptr_t pathChars = pathStrChars.twoByteChars(); libSpec.value.pathname_u = pathChars; libSpec.type = PR_LibSpec_PathnameU; #else // Convert to platform native charset if the appropriate callback has been // provided. char* pathBytes; if (callbacks && callbacks->unicodeToNative) { pathBytes = callbacks->unicodeToNative(cx, pathStrChars.twoByteChars(), pathStr->length()); if (!pathBytes) return nullptr; } else { // Fallback: assume the platform native charset is UTF-8. This is true // for Mac OS X, Android, and probably Linux. size_t nbytes = GetDeflatedUTF8StringLength(cx, pathStrChars.twoByteChars(), pathStr->length()); if (nbytes == (size_t) -1) return nullptr; pathBytes = static_cast<char*>(JS_malloc(cx, nbytes + 1)); if (!pathBytes) return nullptr; ASSERT_OK(DeflateStringToUTF8Buffer(cx, pathStrChars.twoByteChars(), pathStr->length(), pathBytes, &nbytes)); pathBytes[nbytes] = 0; } libSpec.value.pathname = pathBytes; libSpec.type = PR_LibSpec_Pathname; #endif PRLibrary* library = PR_LoadLibraryWithFlags(libSpec, 0); if (!library) { char* error = (char*) JS_malloc(cx, PR_GetErrorTextLength() + 1); if (error) PR_GetErrorText(error); #ifdef XP_WIN JS_ReportError(cx, "couldn't open library %hs: %s", pathChars, error); #else JS_ReportError(cx, "couldn't open library %s: %s", pathBytes, error); JS_free(cx, pathBytes); #endif JS_free(cx, error); return nullptr; } #ifndef XP_WIN JS_free(cx, pathBytes); #endif // stash the library JS_SetReservedSlot(libraryObj, SLOT_LIBRARY, PrivateValue(library)); return libraryObj; }