// static void XPCThrower::ThrowBadResult(nsresult rv, nsresult result, XPCCallContext& ccx) { char* sz; const char* format; const char* name; /* * If there is a pending exception when the native call returns and * it has the same error result as returned by the native call, then * the native call may be passing through an error from a previous JS * call. So we'll just throw that exception into our JS. */ if(CheckForPendingException(result, ccx)) return; // else... if(!nsXPCException::NameAndFormatForNSResult(rv, nsnull, &format) || !format) format = ""; if(nsXPCException::NameAndFormatForNSResult(result, &name, nsnull) && name) sz = JS_smprintf("%s 0x%x (%s)", format, result, name); else sz = JS_smprintf("%s 0x%x", format, result); if(sz && sVerbose) Verbosify(ccx, &sz, PR_TRUE); BuildAndThrowException(ccx, result, sz); if(sz) JS_smprintf_free(sz); }
/* * Convert a JavaSignature object into a string format as used by * the JNI functions, e.g. java.lang.Object ==> "Ljava/lang/Object;" * The caller is responsible for freeing the resulting string. * * If an error is encountered, NULL is returned and an error reported. */ const char * jsj_ConvertJavaSignatureToString(JSContext *cx, JavaSignature *signature) { char *sig; if (IS_OBJECT_TYPE(signature->type)) { /* A non-array object class */ sig = JS_smprintf("L%s;", signature->name); if (sig) jsj_MakeJNIClassname(sig); } else if (signature->type == JAVA_SIGNATURE_ARRAY) { /* An array class */ const char *component_signature_string; component_signature_string = jsj_ConvertJavaSignatureToString(cx, signature->array_component_signature); if (!component_signature_string) return NULL; sig = JS_smprintf("[%s", component_signature_string); JS_smprintf_free((char*)component_signature_string); } else { /* A primitive class */ sig = JS_smprintf("%c", get_jdk_signature_char(signature->type)); } if (!sig) { JS_ReportOutOfMemory(cx); return NULL; } return sig; }
static JSBool default_create_java_vm(SystemJavaVM* *jvm, JNIEnv* *initialEnv, void* initargs) { jint err; const char* user_classpath = (const char*)initargs; char* full_classpath = NULL; /* No Java VM supplied, so create our own */ JDK1_1InitArgs vm_args; memset(&vm_args, 0, sizeof(vm_args)); /* Magic constant indicates JRE version 1.1 */ vm_args.version = 0x00010001; JNI_GetDefaultJavaVMInitArgs(&vm_args); /* Prepend the classpath argument to the default JVM classpath */ if (user_classpath) { #if defined(XP_UNIX) || defined(XP_BEOS) full_classpath = JS_smprintf("%s:%s", user_classpath, vm_args.classpath); #else full_classpath = JS_smprintf("%s;%s", user_classpath, vm_args.classpath); #endif if (!full_classpath) { return JS_FALSE; } vm_args.classpath = (char*)full_classpath; } err = JNI_CreateJavaVM((JavaVM**)jvm, initialEnv, &vm_args); if (full_classpath) JS_smprintf_free(full_classpath); return err == 0; }
NS_IMETHODIMP nsScriptError::ToString(nsACString& /*UTF8*/ aResult) { static const char format0[] = "[%s: \"%s\" {file: \"%s\" line: %d column: %d source: \"%s\"}]"; static const char format1[] = "[%s: \"%s\" {file: \"%s\" line: %d}]"; static const char format2[] = "[%s: \"%s\"]"; static const char error[] = "JavaScript Error"; static const char warning[] = "JavaScript Warning"; const char* severity = !(mFlags & JSREPORT_WARNING) ? error : warning; char* temp; char* tempMessage = nullptr; char* tempSourceName = nullptr; char* tempSourceLine = nullptr; if (!mMessage.IsEmpty()) tempMessage = ToNewUTF8String(mMessage); if (!mSourceName.IsEmpty()) tempSourceName = ToNewUTF8String(mSourceName); if (!mSourceLine.IsEmpty()) tempSourceLine = ToNewUTF8String(mSourceLine); if (nullptr != tempSourceName && nullptr != tempSourceLine) temp = JS_smprintf(format0, severity, tempMessage, tempSourceName, mLineNumber, mColumnNumber, tempSourceLine); else if (!mSourceName.IsEmpty()) temp = JS_smprintf(format1, severity, tempMessage, tempSourceName, mLineNumber); else temp = JS_smprintf(format2, severity, tempMessage); if (nullptr != tempMessage) nsMemory::Free(tempMessage); if (nullptr != tempSourceName) nsMemory::Free(tempSourceName); if (nullptr != tempSourceLine) nsMemory::Free(tempSourceLine); if (!temp) return NS_ERROR_OUT_OF_MEMORY; aResult.Assign(temp); JS_smprintf_free(temp); return NS_OK; }
/* * Convert a JavaSignature object into a human-readable string format as seen * in Java source files, e.g. "byte", or "int[][]" or "java.lang.String". * The caller is responsible for freeing the resulting string. * * If an error is encountered, NULL is returned and an error reported. */ const char * jsj_ConvertJavaSignatureToHRString(JSContext *cx, JavaSignature *signature) { char *sig; JavaSignature *acs; if (signature->type == JAVA_SIGNATURE_ARRAY) { /* An array class */ const char *component_signature_string; acs = signature->array_component_signature; component_signature_string = jsj_ConvertJavaSignatureToHRString(cx, acs); if (!component_signature_string) return NULL; sig = JS_smprintf("%s[]", component_signature_string); JS_smprintf_free((char*)component_signature_string); } else { /* A primitive class or a non-array object class */ sig = JS_smprintf("%s", signature->name); } if (!sig) { JS_ReportOutOfMemory(cx); return NULL; } return sig; }
static nsresult ToStringHelper(const char* aSeverity, const nsString& aMessage, const nsString& aSourceName, const nsString* aSourceLine, uint32_t aLineNumber, uint32_t aColumnNumber, nsACString& /*UTF8*/ aResult) { static const char format0[] = "[%s: \"%s\" {file: \"%s\" line: %d column: %d source: \"%s\"}]"; static const char format1[] = "[%s: \"%s\" {file: \"%s\" line: %d}]"; static const char format2[] = "[%s: \"%s\"]"; UniqueChars temp; char* tempMessage = nullptr; char* tempSourceName = nullptr; char* tempSourceLine = nullptr; if (!aMessage.IsEmpty()) tempMessage = ToNewUTF8String(aMessage); if (!aSourceName.IsEmpty()) // Use at most 512 characters from mSourceName. tempSourceName = ToNewUTF8String(StringHead(aSourceName, 512)); if (aSourceLine && !aSourceLine->IsEmpty()) // Use at most 512 characters from mSourceLine. tempSourceLine = ToNewUTF8String(StringHead(*aSourceLine, 512)); if (nullptr != tempSourceName && nullptr != tempSourceLine) { temp = JS_smprintf(format0, aSeverity, tempMessage, tempSourceName, aLineNumber, aColumnNumber, tempSourceLine); } else if (!aSourceName.IsEmpty()) { temp = JS_smprintf(format1, aSeverity, tempMessage, tempSourceName, aLineNumber); } else { temp = JS_smprintf(format2, aSeverity, tempMessage); } if (nullptr != tempMessage) free(tempMessage); if (nullptr != tempSourceName) free(tempSourceName); if (nullptr != tempSourceLine) free(tempSourceLine); if (!temp) return NS_ERROR_OUT_OF_MEMORY; aResult.Assign(temp.get()); return NS_OK; }
// static void XPCThrower::Verbosify(XPCCallContext& ccx, char** psz, PRBool own) { char* sz = nsnull; if(ccx.HasInterfaceAndMember()) { XPCNativeInterface* iface = ccx.GetInterface(); jsid id = ccx.GetMember()->GetName(); JSAutoByteString bytes; const char *name = JSID_IS_VOID(id) ? "Unknown" : bytes.encode(ccx, JSID_TO_STRING(id)); if(!name) { name = ""; } sz = JS_smprintf("%s [%s.%s]", *psz, iface->GetNameString(), name); } if(sz) { if(own) JS_smprintf_free(*psz); *psz = sz; } }
/* * Unfortunately, there's no standard means to associate any private data with * a JNI thread environment, so we need to use the Java environment pointer as * the key in a lookup table that maps it to a JSJavaThreadState structure, * where we store all our per-thread private data. If no existing thread state * is found, a new one is created. * * If an error occurs, returns NULL and sets the errp argument to an error * message, which the caller is responsible for free'ing. */ JSJavaThreadState * jsj_MapJavaThreadToJSJavaThreadState(JNIEnv *jEnv, char **errp) { JSJavaThreadState *jsj_env; SystemJavaVM *java_vm; JSJavaVM *jsjava_vm; /* If we found an existing thread state, just return it. */ jsj_env = find_jsjava_thread(jEnv); if (jsj_env) return jsj_env; /* No one set up a LiveConnect thread state for a given Java thread. Invoke the callback to create one on-the-fly. */ /* First, figure out which Java VM is calling us */ if (JSJ_callbacks && JSJ_callbacks->get_java_vm) java_vm = JSJ_callbacks->get_java_vm(jEnv); if (java_vm == NULL) return NULL; /* Get our private JavaVM data */ jsjava_vm = map_java_vm_to_jsjava_vm(java_vm); if (!jsjava_vm) { *errp = JS_smprintf("Total weirdness: No JSJavaVM wrapper ever created " "for JavaVM 0x%08x", java_vm); return NULL; } jsj_env = new_jsjava_thread_state(jsjava_vm, NULL, jEnv); if (!jsj_env) return NULL; return jsj_env; }
// static void XPCThrower::Verbosify(XPCCallContext& ccx, char** psz, PRBool own) { char* sz = nsnull; if(ccx.HasInterfaceAndMember()) { XPCNativeInterface* iface = ccx.GetInterface(); #ifdef XPC_IDISPATCH_SUPPORT NS_ASSERTION(ccx.GetIDispatchMember() == nsnull || ccx.GetMember() == nsnull, "Both IDispatch member and regular XPCOM member " "were set in XPCCallContext"); char const * name; if(ccx.GetIDispatchMember()) { XPCDispInterface::Member * member = reinterpret_cast<XPCDispInterface::Member*>(ccx.GetIDispatchMember()); if(member && JSVAL_IS_STRING(member->GetName())) { name = JS_GetStringBytes(JSVAL_TO_STRING(member->GetName())); } else name = "Unknown"; } else name = iface->GetMemberName(ccx, ccx.GetMember()); sz = JS_smprintf("%s [%s.%s]", *psz, iface->GetNameString(), name); #else sz = JS_smprintf("%s [%s.%s]", *psz, iface->GetNameString(), iface->GetMemberName(ccx, ccx.GetMember())); #endif } if(sz) { if(own) JS_smprintf_free(*psz); *psz = sz; } }
static JSBool ThrowCallFailed(JSContext *cx, nsresult rv, const char *ifaceName, const char *memberName) { // From XPCThrower::ThrowBadResult. char* sz; const char* format; const char* name; /* * If there is a pending exception when the native call returns and * it has the same error result as returned by the native call, then * the native call may be passing through an error from a previous JS * call. So we'll just throw that exception into our JS. */ if(XPCThrower::CheckForPendingException(rv, cx)) return JS_FALSE; // else... if(!nsXPCException::NameAndFormatForNSResult( NS_ERROR_XPC_NATIVE_RETURNED_FAILURE, nsnull, &format) || !format) { format = ""; } if(nsXPCException::NameAndFormatForNSResult(rv, &name, nsnull) && name) { sz = JS_smprintf("%s 0x%x (%s) [%s.%s]", format, rv, name, ifaceName, memberName); } else { sz = JS_smprintf("%s 0x%x [%s.%s]", format, rv, ifaceName, memberName); } XPCThrower::BuildAndThrowException(cx, rv, sz); if(sz) JS_smprintf_free(sz); return JS_FALSE; }
static void _interpreterTrace(JSDContext* jsdc, JSContext *cx, JSStackFrame *fp, JSBool before) { JSDScript* jsdscript = NULL; JSScript * script; static indent = 0; char* buf; const char* funName = NULL; script = JS_GetFrameScript(cx, fp); if(script) { JSD_LOCK_SCRIPTS(jsdc); jsdscript = jsd_FindJSDScript(jsdc, script); JSD_UNLOCK_SCRIPTS(jsdc); if(jsdscript) funName = JSD_GetScriptFunctionName(jsdc, jsdscript); } if(!funName) funName = "TOP_LEVEL"; if(before) { buf = JS_smprintf("%sentering %s %s this: %0x\n", _indentSpaces(indent++), funName, JS_IsConstructorFrame(cx, fp) ? "constructing":"", (int)JS_GetFrameThis(cx, fp)); } else { buf = JS_smprintf("%sleaving %s\n", _indentSpaces(--indent), funName); } JS_ASSERT(indent >= 0); if(!buf) return; printf(buf); free(buf); }
/* This shutdown routine discards all JNI references to Java objects that have been reflected into JS, even if there are still references to them from JS. */ void jsj_DiscardJavaClassReflections(JNIEnv *jEnv) { JSJavaThreadState *jsj_env; char *err_msg; JSContext *cx; /* Get the per-thread state corresponding to the current Java thread */ jsj_env = jsj_MapJavaThreadToJSJavaThreadState(jEnv, &err_msg); JS_ASSERT(jsj_env); if (!jsj_env) goto error; /* Get the JSContext that we're supposed to use for this Java thread */ cx = jsj_env->cx; if (!cx) { /* We called spontaneously into JS from Java, rather than from JS into Java and back into JS. Invoke a callback to obtain/create a JSContext for us to use. */ if (JSJ_callbacks->map_jsj_thread_to_js_context) { #ifdef OJI cx = JSJ_callbacks->map_jsj_thread_to_js_context(jsj_env, NULL, /* FIXME: What should this argument be ? */ jEnv, &err_msg); #else cx = JSJ_callbacks->map_jsj_thread_to_js_context(jsj_env, jEnv, &err_msg); #endif if (!cx) goto error; } else { err_msg = JS_smprintf("Unable to find/create JavaScript execution " "context for JNI thread 0x%08x", jEnv); goto error; } } if (java_class_reflections) { JSJ_HashTableEnumerateEntries(java_class_reflections, enumerate_remove_java_class, (void*)jsj_env); JSJ_HashTableDestroy(java_class_reflections); java_class_reflections = NULL; } return; error: JS_ASSERT(!cx); if (err_msg) { jsj_LogError(err_msg); JS_smprintf_free(err_msg); } }
static char * _describeObj(JSDContext* jsdc, JSDObject *jsdobj) { return JS_smprintf("%0x new'd in %s at line %d using ctor %s in %s at line %d", (int)jsdobj, JSD_GetObjectNewURL(jsdc, jsdobj), JSD_GetObjectNewLineNumber(jsdc, jsdobj), JSD_GetObjectConstructorName(jsdc, jsdobj), JSD_GetObjectConstructorURL(jsdc, jsdobj), JSD_GetObjectConstructorLineNumber(jsdc, jsdobj)); }
/* * Same as jsj_ReportJavaError, except "internal error: " is prepended * to message. */ void jsj_UnexpectedJavaError(JSContext *cx, JNIEnv *env, const char *format, ...) { va_list ap; const char *format2; va_start(ap, format); format2 = JS_smprintf("internal error: %s", format); if (format2) { vreport_java_error(cx, env, format2, ap); JS_smprintf_free((void*)format2); } va_end(ap); }
/* * At certain times during initialization, there may be no JavaScript context * available to direct error reports to, in which case the error messages * are sent to this function. The caller is responsible for free'ing * the js_error_msg argument. */ static void report_java_initialization_error(JNIEnv *jEnv, const char *js_error_msg) { const char *error_msg, *java_error_msg; java_error_msg = NULL; if (jEnv) { java_error_msg = jsj_GetJavaErrorMessage(jEnv); (*jEnv)->ExceptionClear(jEnv); } if (java_error_msg) { error_msg = JS_smprintf("initialization error: %s (%s)\n", js_error_msg, java_error_msg); free((void*)java_error_msg); } else { error_msg = JS_smprintf("initialization error: %s\n", js_error_msg); } jsj_LogError(error_msg); free((void*)error_msg); }
JavaPackage_convert(JSContext *cx, JSObject *obj, JSType type, jsval *vp) { JSString *str; char *name, *cp; JavaPackage_Private *package = JS_GetPrivate(cx, obj); if (!package) { fprintf(stderr, "JavaPackage_resolve: no private data!\n"); return JS_FALSE; } switch (type) { /* Pretty-printing of JavaPackage */ case JSTYPE_VOID: /* Default value */ case JSTYPE_NUMBER: case JSTYPE_STRING: /* Convert '/' to '.' so that it looks like Java language syntax. */ if (!package->path) break; name = JS_smprintf("[JavaPackage %s]", package->path); if (!name) { JS_ReportOutOfMemory(cx); return JS_FALSE; } for (cp = name; *cp != '\0'; cp++) if (*cp == '/') *cp = '.'; str = JS_NewString(cx, name, strlen(name)); if (!str) { free(name); /* It's not necessary to call JS_ReportOutOfMemory(), as JS_NewString() will do so on failure. */ return JS_FALSE; } *vp = STRING_TO_JSVAL(str); break; case JSTYPE_OBJECT: *vp = OBJECT_TO_JSVAL(obj); break; default: break; } return JS_TRUE; }
/* string toString (); */ NS_IMETHODIMP nsXPCException::ToString(char **_retval) { if(!_retval) return NS_ERROR_NULL_POINTER; if(!mInitialized) return NS_ERROR_NOT_INITIALIZED; static const char defaultMsg[] = "<no message>"; static const char defaultLocation[] = "<unknown>"; static const char format[] = "[Exception... \"%s\" nsresult: \"0x%x (%s)\" location: \"%s\" data: %s]"; char* indicatedLocation = nsnull; if(mLocation) { // we need to free this if it does not fail nsresult rv = mLocation->ToString(&indicatedLocation); if(NS_FAILED(rv)) return rv; } const char* msg = mMessage ? mMessage : nsnull; const char* location = indicatedLocation ? indicatedLocation : defaultLocation; const char* resultName = mName; if(!resultName && !NameAndFormatForNSResult(mResult, &resultName, (!msg) ? &msg : nsnull)) { if(!msg) msg = defaultMsg; resultName = "<unknown>"; } const char* data = mData ? "yes" : "no"; char* temp = JS_smprintf(format, msg, mResult, resultName, location, data); if(indicatedLocation) nsMemory::Free(indicatedLocation); char* final = nsnull; if(temp) { final = (char*) nsMemory::Clone(temp, sizeof(char)*(strlen(temp)+1)); JS_smprintf_free(temp); }
static JSBool env_setProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp) { /* XXX porting may be easy, but these don't seem to supply setenv by default */ #if !defined XP_BEOS && !defined XP_OS2 && !defined SOLARIS JSString *idstr, *valstr; const char *name, *value; int rv; idstr = JS_ValueToString(cx, id); valstr = JS_ValueToString(cx, *vp); if (!idstr || !valstr) return JS_FALSE; name = JS_GetStringBytes(idstr); value = JS_GetStringBytes(valstr); #if defined XP_WIN || defined HPUX || defined OSF1 || defined IRIX \ || defined SCO { char *waste = JS_smprintf("%s=%s", name, value); if (!waste) { JS_ReportOutOfMemory(cx); return JS_FALSE; } rv = putenv(waste); #ifdef XP_WIN /* * HPUX9 at least still has the bad old non-copying putenv. * * Per mail from <*****@*****.**>, OSF1 also has a putenv * that will crash if you pass it an auto char array (so it must place * its argument directly in the char *environ[] array). */ free(waste); #endif } #else rv = setenv(name, value, 1); #endif if (rv < 0) { JS_ReportError(cx, "can't set envariable %s to %s", name, value); return JS_FALSE; } *vp = STRING_TO_JSVAL(valstr); #endif /* !defined XP_BEOS && !defined XP_OS2 && !defined SOLARIS */ return JS_TRUE; }
// static void XPCThrower::Verbosify(XPCCallContext& ccx, char** psz, PRBool own) { char* sz = nsnull; if(ccx.HasInterfaceAndMember()) { XPCNativeInterface* iface = ccx.GetInterface(); jsid id = JSID_VOID; #ifdef XPC_IDISPATCH_SUPPORT NS_ASSERTION(ccx.GetIDispatchMember() == nsnull || ccx.GetMember() == nsnull, "Both IDispatch member and regular XPCOM member " "were set in XPCCallContext"); if(ccx.GetIDispatchMember()) { XPCDispInterface::Member * member = reinterpret_cast<XPCDispInterface::Member*>(ccx.GetIDispatchMember()); if(member && JSID_IS_STRING(member->GetName())) { id = member->GetName(); } } else #endif { id = ccx.GetMember()->GetName(); } JSAutoByteString bytes; const char *name = JSID_IS_VOID(id) ? "Unknown" : bytes.encode(ccx, JSID_TO_STRING(id)); if(!name) { name = ""; } sz = JS_smprintf("%s [%s.%s]", *psz, iface->GetNameString(), name); } if(sz) { if(own) JS_smprintf_free(*psz); *psz = sz; } }
static void ThrowBadArg(JSContext *cx, nsresult rv, const char *ifaceName, const char *memberName, uintN paramnum) { // From XPCThrower::ThrowBadParam. char* sz; const char* format; if(!nsXPCException::NameAndFormatForNSResult(rv, nsnull, &format)) format = ""; sz = JS_smprintf("%s arg %u [%s.%s]", format, (unsigned int) paramnum, ifaceName, memberName); XPCThrower::BuildAndThrowException(cx, rv, sz); if(sz) JS_smprintf_free(sz); }
// static void XPCThrower::ThrowBadParam(nsresult rv, uintN paramNum, XPCCallContext& ccx) { char* sz; const char* format; if(!nsXPCException::NameAndFormatForNSResult(rv, nsnull, &format)) format = ""; sz = JS_smprintf("%s arg %d", format, paramNum); if(sz && sVerbose) Verbosify(ccx, &sz, PR_TRUE); BuildAndThrowException(ccx, rv, sz); if(sz) JS_smprintf_free(sz); }
JavaClass_convert(JSContext *cx, JSObject *obj, JSType type, jsval *vp) { char *name; JSString *str; JavaClassDescriptor *class_descriptor; class_descriptor = JS_GetPrivate(cx, obj); if (!class_descriptor) return JS_FALSE; switch(type) { case JSTYPE_STRING: /* Convert '/' to '.' so that it looks like Java language syntax. */ if (!class_descriptor->name) break; name = JS_smprintf("[JavaClass %s]", class_descriptor->name); if (!name) { JS_ReportOutOfMemory(cx); return JS_FALSE; } str = JS_NewString(cx, name, strlen(name)); if (!str) { free(name); /* It's not necessary to call JS_ReportOutOfMemory(), as JS_NewString() will do so on failure. */ return JS_FALSE; } *vp = STRING_TO_JSVAL(str); return JS_TRUE; default: break; } return JS_TRUE; }
JSBool PJS_invoke_perl_property_getter(JSContext *cx, JSObject *obj, jsval id, jsval *vp) { dSP; PJS_Context *pcx; PJS_Class *pcls; PJS_Property *pprop; SV *caller; char *name; jsint slot; U8 invocation_mode; if (!(JSVAL_IS_INT(id) || JSVAL_IS_STRING(id))) { return JS_TRUE; } if((pcx = PJS_GET_CONTEXT(cx)) == NULL) { JS_ReportError(cx, "Can't find context %d", cx); return JS_FALSE; } if (JS_TypeOfValue(cx, OBJECT_TO_JSVAL(obj)) == JSTYPE_OBJECT) { /* Called as instsance */ JSClass *clasp = PJS_GET_CLASS(cx, obj); name = (char *) clasp->name; invocation_mode = 1; } else { /* Called as static */ JSFunction *parent_jfunc = JS_ValueToFunction(cx, OBJECT_TO_JSVAL(obj)); if (parent_jfunc == NULL) { JS_ReportError(cx, "Failed to extract class for static property getter"); return JS_FALSE; } name = (char *) JS_GetFunctionName(parent_jfunc); invocation_mode = 0; } if ((pcls = PJS_GetClassByName(pcx, name)) == NULL) { JS_ReportError(cx, "Can't find class '%s'", name); return JS_FALSE; } if (invocation_mode) { caller = (SV *) JS_GetPrivate(cx, obj); } else { caller = newSVpv(pcls->pkg, 0); } if (JSVAL_IS_INT(id)) { slot = JSVAL_TO_INT(id); if ((pprop = PJS_get_property_by_id(pcls, (int8) slot)) == NULL) { if (SvTRUE(pcls->property_getter)) { if (perl_call_sv_with_jsvals(cx, obj, pcls->property_getter, caller, 1, &id, vp) < 0) { return JS_FALSE; } return JS_TRUE; } JS_ReportError(cx, "Can't find property handler"); return JS_FALSE; } if (pprop->getter == NULL) { JS_ReportError(cx, "Property is write-only"); return JS_FALSE; } if (perl_call_sv_with_jsvals(cx, obj, pprop->getter, caller, 0, NULL, vp) < 0) { return JS_FALSE; } } else if (JSVAL_IS_STRING(id) && SvTRUE(pcls->property_getter)) { SV *sv = sv_newmortal(); #ifdef JS_C_STRINGS_ARE_UTF8 char *tmp = JS_smprintf("%hs", JS_GetStringChars(JSVAL_TO_STRING(id))); sv_setpv(sv, tmp); SvUTF8_on(sv); free(tmp); #else sv_setpv(sv, JS_GetStringBytes(JSVAL_TO_STRING(id))); #endif if (PJS_get_method_by_name(pcls, SvPV_nolen(sv))) { return JS_TRUE; } if (perl_call_sv_with_jsvals(cx, obj, pcls->property_getter, caller, 1, &id, vp) < 0) { return JS_FALSE; } } return JS_TRUE; }
static JSBool global_resolve(JSContext *cx, JSHandleObject obj, JSHandleId id, unsigned flags, MutableHandleObject objp) { #ifdef LAZY_STANDARD_CLASSES if ((flags & JSRESOLVE_ASSIGNING) == 0) { JSBool resolved; if (!JS_ResolveStandardClass(cx, obj, id, &resolved)) return JS_FALSE; if (resolved) { objp.set(obj); return JS_TRUE; } } #endif #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.set(obj); break; } } JS_free(cx, path); return ok; } #else return JS_TRUE; #endif }
static JSCallsite * CallTree(uint32 *bp) { uint32 *bpup, *bpdown, pc; JSCallsite *parent, *site, **csp; Dl_info info; int ok, offset; const char *symbol; char *method; /* Reverse the stack frame list to avoid recursion. */ bpup = NULL; for (;;) { bpdown = (uint32*) bp[0]; bp[0] = (uint32) bpup; if ((uint32*) bpdown[0] < bpdown) break; bpup = bp; bp = bpdown; } /* Reverse the stack again, finding and building a path in the tree. */ parent = &js_calltree_root; do { bpup = (uint32*) bp[0]; bp[0] = (uint32) bpdown; pc = bp[1]; csp = &parent->kids; while ((site = *csp) != NULL) { if (site->pc == pc) { /* Put the most recently used site at the front of siblings. */ *csp = site->siblings; site->siblings = parent->kids; parent->kids = site; /* Site already built -- go up the stack. */ goto upward; } csp = &site->siblings; } /* Check for recursion: see if pc is on our ancestor line. */ for (site = parent; site; site = site->parent) { if (site->pc == pc) goto upward; } /* * Not in tree at all: let's find our symbolic callsite info. * XXX static syms are masked by nearest lower global */ info.dli_fname = info.dli_sname = NULL; ok = dladdr((void*) pc, &info); if (ok < 0) { fprintf(stderr, "dladdr failed!\n"); return NULL; } /* XXXbe sub 0x08040000? or something, see dbaron bug with tenthumbs comment */ symbol = info.dli_sname; offset = (char*)pc - (char*)info.dli_fbase; method = symbol ? strdup(symbol) : JS_smprintf("%s+%X", info.dli_fname ? info.dli_fname : "main", offset); if (!method) return NULL; /* Create a new callsite record. */ site = (JSCallsite *) malloc(sizeof(JSCallsite)); if (!site) return NULL; /* Insert the new site into the tree. */ site->pc = pc; site->name = method; site->library = info.dli_fname; site->offset = offset; site->parent = parent; site->siblings = parent->kids; parent->kids = site; site->kids = NULL; upward: parent = site; bpdown = bp; bp = bpup; } while (bp); return site; }
JSJavaThreadState * jsj_enter_js(JNIEnv *jEnv, void* applet_obj, jobject java_wrapper_obj, JSContext **cxp, JSObject **js_objp, JSErrorReporter *old_error_reporterp, void **pNSIPrincipaArray, int numPrincipals, void *pNSISecurityContext) { JSContext *cx; char *err_msg; JSObject *js_obj; JSJavaThreadState *jsj_env; cx = NULL; err_msg = NULL; /* Invoke callback, presumably used to implement concurrency constraints */ if (JSJ_callbacks && JSJ_callbacks->enter_js_from_java) { #ifdef OJI if (!JSJ_callbacks->enter_js_from_java(jEnv, &err_msg, pNSIPrincipaArray, numPrincipals, pNSISecurityContext,applet_obj)) #else if (!JSJ_callbacks->enter_js_from_java(jEnv, &err_msg)) #endif goto entry_failure; } /* Check the JSObject pointer in the wrapper object. */ if (js_objp) { #ifdef PRESERVE_JSOBJECT_IDENTITY #if JS_BYTES_PER_LONG == 8 js_obj = (JSObject *)((*jEnv)->GetLongField(jEnv, java_wrapper_obj, njJSObject_long_internal)); #else js_obj = (JSObject *)((*jEnv)->GetIntField(jEnv, java_wrapper_obj, njJSObject_internal)); #endif #else /* !PRESERVE_JSOBJECT_IDENTITY */ js_obj = jsj_UnwrapJSObjectWrapper(jEnv, java_wrapper_obj); #endif /* PRESERVE_JSOBJECT_IDENTITY */ JS_ASSERT(js_obj); if (!js_obj) goto error; *js_objp = js_obj; } /* Get the per-thread state corresponding to the current Java thread */ jsj_env = jsj_MapJavaThreadToJSJavaThreadState(jEnv, &err_msg); if (!jsj_env) goto error; /* Get the JSContext that we're supposed to use for this Java thread */ cx = jsj_env->cx; if (!cx) { /* We called spontaneously into JS from Java, rather than from JS into Java and back into JS. Invoke a callback to obtain/create a JSContext for us to use. */ if (JSJ_callbacks && JSJ_callbacks->map_jsj_thread_to_js_context) { #ifdef OJI cx = JSJ_callbacks->map_jsj_thread_to_js_context(jsj_env, applet_obj, jEnv, &err_msg); #else cx = JSJ_callbacks->map_jsj_thread_to_js_context(jsj_env, jEnv, &err_msg); #endif if (!cx) goto error; } else { err_msg = JS_smprintf("Unable to find/create JavaScript execution " "context for JNI thread 0x%08x", jEnv); goto error; } } *cxp = cx; /* * Capture all JS error reports so that they can be thrown into the Java * caller as an instance of netscape.javascript.JSException. */ *old_error_reporterp = JS_SetErrorReporter(cx, capture_js_error_reports_for_java); #ifdef JSJ_THREADSAFE JS_BeginRequest(cx); #endif return jsj_env; error: /* Invoke callback, presumably used to implement concurrency constraints */ if (JSJ_callbacks && JSJ_callbacks->exit_js) JSJ_callbacks->exit_js(jEnv, cx); entry_failure: if (err_msg) { if (cx) JS_ReportError(cx, err_msg); else jsj_LogError(err_msg); free(err_msg); } return NULL; }
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); }
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; }
JavaPackage_resolve(JSContext *cx, JSObject *obj, jsval id) { JavaPackage_Private *package; JSBool ok = JS_TRUE; jclass jclazz; char *subPath, *newPath; const char *path; JNIEnv *jEnv; JSJavaThreadState *jsj_env; /* Painful hack for pre_define_java_packages() */ if (quiet_resolve_failure) return JS_FALSE; package = (JavaPackage_Private *)JS_GetPrivate(cx, obj); if (!package) return JS_TRUE; if (!JSVAL_IS_STRING(id)) return JS_TRUE; subPath = JS_GetStringBytes(JSVAL_TO_STRING(id)); /* * There will be an attempt to invoke the toString() method when producing * the string representation of a JavaPackage. When this occurs, avoid * creating a bogus toString package. (This means that no one can ever * create a package with the simple name "toString", but we'll live with * that limitation.) */ if (!strcmp(subPath, "toString")) return JS_FALSE; path = package->path; newPath = JS_smprintf("%s%s%s", path, (path[0] ? "/" : ""), subPath); if (!newPath) { JS_ReportOutOfMemory(cx); return JS_FALSE; } jsj_env = jsj_EnterJava(cx, &jEnv); if (!jEnv) { ok = JS_FALSE; goto out; } /* Unfortunately, Java provides no way to find out whether a particular name is a package or not. The only way to tell is to try to load the name as a class file and, if that fails, assume it's a package. This makes things work as expected for the most part, but it has three noticeable problems that keep coming up: - You can refer to a package like java.lang.i.buried.paul without generating a complaint. Of course, you'll never be able to refer to any classes through it. - An annoying consequence of the above is that misspelling a class name results in a cryptic error about packages. - In a browser context, i.e. where applets are involved, figuring out whether something is a class may require looking for it over the net using the current classloader. This means that the first time you refer to java.lang.System in a js context, there will be an attempt to search for [[DOCBASE]]/java.class on the server. A solution is to explicitly tell jsjava the names of all the (local) packages on the CLASSPATH. (Not implemented yet.) */ jclazz = (*jEnv)->FindClass(jEnv, newPath); if (jclazz) { JSObject *newClass; newClass = jsj_define_JavaClass(cx, jEnv, obj, subPath, jclazz); (*jEnv)->DeleteLocalRef(jEnv, jclazz); if (!newClass) { ok = JS_FALSE; goto out; } } else { /* We assume that any failed attempt to load a class is because it doesn't exist. If we wanted to do a better job, we would check the exception type and make sure that it's NoClassDefFoundError */ (*jEnv)->ExceptionClear(jEnv); /* * If there's no class of the given name, then we must be referring to * a package. However, don't allow bogus sub-packages of pre-defined * system packages to be created. */ if (JS_InstanceOf(cx, obj, &JavaPackage_class, NULL)) { JavaPackage_Private *current_package; current_package = JS_GetPrivate(cx, obj); if (current_package->flags & PKG_SYSTEM) { char *msg, *cp; msg = JS_strdup(cx, newPath); /* Check for OOM */ if (msg) { /* Convert package of form "java/lang" to "java.lang" */ for (cp = msg; *cp != '\0'; cp++) if (*cp == '/') *cp = '.'; JS_ReportErrorNumber(cx, jsj_GetErrorMessage, NULL, JSJMSG_MISSING_PACKAGE, msg); free((char*)msg); } ok = JS_FALSE; goto out; } } if (!define_JavaPackage(cx, obj, subPath, newPath, 0, JSPROP_READONLY)) { ok = JS_FALSE; goto out; } #ifdef DEBUG /* printf("JavaPackage \'%s\' created\n", newPath); */ #endif } out: free(newPath); jsj_ExitJava(jsj_env); return ok; }