JSBool ADM_JSAvidemuxAudio::mixer(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) { uint32_t nb=0,nw=0; uint32_t *infos=NULL; // default return value ADM_JSAvidemuxAudio *p = (ADM_JSAvidemuxAudio *)JS_GetPrivate(cx, obj); // default return value if(argc != 1) return JS_FALSE; char *pArg0 = JS_GetStringBytes(JSVAL_TO_STRING(argv[0])); enterLock(); if(setCurrentMixerFromString(pArg0)) *rval=BOOLEAN_TO_JSVAL(true); else *rval=BOOLEAN_TO_JSVAL(false); leaveLock() return JS_TRUE; }// end Codec
xpc_qsAString::xpc_qsAString(JSContext *cx, jsval *pval) { // From the T_ASTRING case in XPCConvert::JSData2Native. typedef implementation_type::char_traits traits; jsval v; JSString *s; const PRUnichar *chars; size_t len; v = *pval; if(JSVAL_IS_STRING(v)) { s = JSVAL_TO_STRING(v); } else { if(JSVAL_IS_NULL(v) || JSVAL_IS_VOID(v)) { (new(mBuf) implementation_type( traits::sEmptyBuffer, PRUint32(0)))->SetIsVoid(PR_TRUE); mValid = JS_TRUE; return; } s = JS_ValueToString(cx, v); if(!s) { mValid = JS_FALSE; return; } *pval = STRING_TO_JSVAL(s); // Root the new string. } len = JS_GetStringLength(s); chars = (len == 0 ? traits::sEmptyBuffer : (const PRUnichar*)JS_GetStringChars(s)); new(mBuf) implementation_type(chars, len); mValid = JS_TRUE; }
NativeSetSweeper(JSDHashTable *table, JSDHashEntryHdr *hdr, uint32 number, void *arg) { XPCNativeSet* set = ((NativeSetMap::Entry*)hdr)->key_value; if(set->IsMarked()) { set->Unmark(); return JS_DHASH_NEXT; } #ifdef XPC_REPORT_NATIVE_INTERFACE_AND_SET_FLUSHING printf("- Destroying XPCNativeSet for:\n"); PRUint16 count = set->GetInterfaceCount(); for(PRUint16 k = 0; k < count; k++) { XPCNativeInterface* iface = set->GetInterfaceAt(k); printf(" %s\n",JS_GetStringBytes(JSVAL_TO_STRING(iface->GetName()))); } #endif XPCNativeSet::DestroyInstance(set); return JS_DHASH_REMOVE; }
SV * PrimJSVALToSV( pTHX_ JSContext *cx, jsval v ) { SV *sv = NULL; if(JSVAL_IS_NULL(v) || JSVAL_IS_VOID(v)) sv = newSV(0); else if(JSVAL_IS_BOOLEAN(v)) { sv = newSV(0); sv_setref_iv(sv, PJS_BOOLEAN, (IV)JSVAL_TO_BOOLEAN(v)); } else if(JSVAL_IS_INT(v)) sv = newSViv((IV)JSVAL_TO_INT(v)); else if(JSVAL_IS_DOUBLE(v)) sv = newSVnv(*JSVAL_TO_DOUBLE(v)); else if(JSVAL_IS_STRING(v)) sv = PJS_JSString2SV(aTHX_ JSVAL_TO_STRING(v)); else croak("PJS_Assert: Unknown primitive type"); return sv; }
LWQQ_EXPORT char* lwqq_js_enc_pwd(const char* pwd, const char* salt, const char* vcode, lwqq_js_t* js) { JSObject* global = JS_GetGlobalObject(js->context); jsval res; jsval argv[3]; char* res_; JSString* pwd_ = JS_NewStringCopyZ(js->context, pwd); JSString* salt_ = JS_NewStringCopyZ(js->context, salt); JSString* vcode_ = JS_NewStringCopyZ(js->context, vcode); argv[0] = STRING_TO_JSVAL(pwd_); argv[1] = STRING_TO_JSVAL(salt_); argv[2] = STRING_TO_JSVAL(vcode_); JS_CallFunctionName(js->context, global, "encryption", 3, argv, &res); res_ = JS_EncodeString(js->context, JSVAL_TO_STRING(res)); char* ret = strdup(res_); JS_free(js->context, res_); return ret; }
static void getUTF8StringArgument(JSContext *cx, JSObject *obj, PRUint16 argNum, uintN argc, jsval *argv, nsCString& aRetval) { if (argc <= argNum || !JSVAL_IS_STRING(argv[argNum])) { JS_ReportError(cx, "String argument expected"); aRetval.Truncate(); return; } /* * We don't want to use JS_ValueToString because we want to be able * to have an object to represent a target in subsequent versions. */ JSString *str = JSVAL_TO_STRING(argv[argNum]); if (!str) { aRetval.Truncate(); return; } PRUnichar *data = (PRUnichar*)JS_GetStringChars(str); CopyUTF16toUTF8(data, aRetval); }
JSBool S_SimpleNativeClass::jsPropertySet(JSContext *cx, JSObject *obj, jsid _id, JSBool strict, jsval *val) { int32_t propId = JSID_TO_INT(_id); S_SimpleNativeClass *cobj; JSGET_PTRSHELL(S_SimpleNativeClass, cobj, obj); if (!cobj) return JS_FALSE; switch(propId) { case kSomeField: do { uint32_t tmp; JS_ValueToECMAUint32(cx, *val, &tmp); cobj->setSomeField(tmp); } while (0); break; case kSomeOtherField: do { uint32_t tmp; JS_ValueToECMAUint32(cx, *val, &tmp); cobj->setSomeOtherField(tmp); } while (0); break; case kAnotherMoreComplexField: do { char *tmp = JS_EncodeString(cx, JSVAL_TO_STRING(*val)); if (tmp) { cobj->setAnotherMoreComplexField(tmp); } } while (0); break; default: break; } return JS_TRUE; }
JSBool jsval_to_std_vector_string(JSContext* cx, jsval v, std::vector<std::string>* ret) { JSObject *jsobj; JSBool ok = JS_ValueToObject( cx, v, &jsobj ); JSB_PRECONDITION2( ok, cx, JS_FALSE, "Error converting value to object"); JSB_PRECONDITION2( jsobj && JS_IsArrayObject( cx, jsobj), cx, JS_FALSE, "Object must be an array"); uint32_t len = 0; JS_GetArrayLength(cx, jsobj, &len); for (uint32_t i=0; i < len; i++) { jsval elt; if (JS_GetElement(cx, jsobj, i, &elt)) { if (JSVAL_IS_STRING(elt)) { JSStringWrapper str(JSVAL_TO_STRING(elt)); ret->push_back(str.get()); } } } return JS_TRUE; }
//--------------------------------------------------------------------------- void JS_TO_CONCEPT(void *member, jsval rval) { INVOKE_CALL InvokePtr = 0; CALL_BACK_VARIABLE_SET SetVariable = _SetVariable; void *HANDLER = CONCEPT_HANDLER; if (JSVAL_IS_DOUBLE(rval)) { SET_NUMBER_VARIABLE(member, *JSVAL_TO_DOUBLE(rval)); } else if (JSVAL_IS_INT(rval)) { SET_NUMBER_VARIABLE(member, JSVAL_TO_INT(rval)); } else if (JSVAL_IS_STRING(rval)) { struct JSString *str = JSVAL_TO_STRING(rval); SET_BUFFER_VARIABLE(member, JS_GetStringBytes(str), str->length); } else if (JSVAL_IS_BOOLEAN(rval)) { SET_NUMBER_VARIABLE(member, (NUMBER)JSVAL_TO_BOOLEAN(rval)); } else if ((JSVAL_IS_NULL(rval)) || (JSVAL_IS_VOID(rval))) { SET_NUMBER_VARIABLE(member, 0); } else SET_NUMBER_VARIABLE(member, 1); }
JSBool getVar(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) {// begin getVar int out=0; char *dupe=NULL; // default return value if(argc != 1) return JS_FALSE; if(JSVAL_IS_STRING(argv[0]) == false) return JS_FALSE; char *stringa = JS_GetStringBytes(JSVAL_TO_STRING(argv[0])); dupe=script_getVar(stringa ,&out); if(!dupe) return JS_FALSE; // if out=1 it is a string else a number if(out) *rval = STRING_TO_JSVAL(JS_NewStringCopyZ(cx,dupe)); else *rval = INT_TO_JSVAL(atoi(dupe)); return JS_TRUE; }// end getVar
int js_prop_from_object(JSContext *cx, JSObject *obj, prop_t *p) { JSIdArray *ida; int i, r = 0; const char *n; if((ida = JS_Enumerate(cx, obj)) == NULL) return -1; for(i = 0; i < ida->length; i++) { jsval name, value; if(!JS_IdToValue(cx, ida->vector[i], &name)) continue; if(JSVAL_IS_STRING(name)) { n = JS_GetStringBytes(JSVAL_TO_STRING(name)); if(!JS_GetProperty(cx, obj, n, &value)) continue; } else if(JSVAL_IS_INT(name)) { if(!JS_GetElement(cx, obj, JSVAL_TO_INT(name), &value) || JSVAL_IS_VOID(value)) continue; n = NULL; } else { continue; } if(JSVAL_TO_OBJECT(value) == obj) continue; js_prop_set_from_jsval(cx, prop_create(p, n), value); } JS_DestroyIdArray(cx, ida); return r; }
static JSBool JSB_IOSiAP_requestProducts(JSContext *cx, uint32_t argc, jsval *vp) { JSB_PRECONDITION2(argc==1, cx, JS_FALSE, "Invalid number of arguments"); jsval *argv = JS_ARGV(cx,vp); JSObject *obj = (JSObject *)JS_THIS_OBJECT(cx, vp); IOSiAP_Bridge *bridge = (IOSiAP_Bridge *)JS_GetPrivate(obj); // parse array param // JSObject like a array which hold jsval JSObject *arrayObj = JSVAL_TO_OBJECT(argv[0]); // safety check for type if (JS_FALSE == JS_IsArrayObject(cx, arrayObj)) { JS_SET_RVAL(cx, vp, BOOLEAN_TO_JSVAL(JS_FALSE)); return JS_TRUE; } std::vector <std::string> productIdentifiers; uint32_t length = 0; JS_GetArrayLength(cx, arrayObj, &length); for(int index = 0; index < length; index++) { // jsval ==> JSString ==> char * jsval argVal; JS_GetElement(cx, arrayObj, index, &argVal); JSString *jsIdentifier = JSVAL_TO_STRING(argVal); JSStringWrapper wrapper(jsIdentifier); // fill into C++ vector productIdentifiers.push_back(std::string(wrapper.get())); } // now safe to call native function. bridge->iap->requestProducts(productIdentifiers); JS_SET_RVAL(cx, vp, BOOLEAN_TO_JSVAL(JS_TRUE)); return JS_TRUE; }
static JSBool JSB_IOSiAP_iOSProductByIdentifier(JSContext *cx, uint32_t argc, jsval *vp) { JSB_PRECONDITION2(argc==1, cx, JS_FALSE, "Invalid number of arguments"); jsval *argv = JS_ARGV(cx,vp); JSObject *obj = (JSObject *)JS_THIS_OBJECT(cx, vp); IOSiAP_Bridge *bridge = (IOSiAP_Bridge *)JS_GetPrivate(obj); // safety check for type if (JS_FALSE == JSVAL_IS_STRING(argv[0])) { JS_SET_RVAL(cx, vp, JSVAL_VOID); return JS_TRUE; } JSString *jsIdentifier = JSVAL_TO_STRING(argv[0]); JSStringWrapper wrapper(jsIdentifier); std::string identifier = wrapper.get(); IOSProduct *product = bridge->iap->iOSProductByIdentifier(identifier); // return a js object JSObject *productObj = JS_NewObject(cx, JSB_Product_class, JSB_Product_object, NULL); JS_SetPrivate(productObj, product); JS_SET_RVAL(cx, vp, OBJECT_TO_JSVAL(productObj)); return JS_TRUE; }
/* * Convert a JS value to a Java value of the given type signature. The cost * variable is incremented if coercion is required, e.g. the source value is * a string, but the target type is a boolean. * * Returns JS_FALSE if no conversion is possible, either because the jsval has * a type that is wholly incompatible with the Java value, or because a scalar * jsval can't be represented in a variable of the target type without loss of * precision, e.g. the source value is "4.2" but the destination type is byte. * If conversion is not possible and java_value is non-NULL, the JS error * reporter is called with an appropriate message. */ JSBool jsj_ConvertJSValueToJavaValue(JSContext *cx, JNIEnv *jEnv, jsval v_arg, JavaSignature *signature, int *cost, jvalue *java_value, JSBool *is_local_refp) { JavaSignatureChar type; jsval v; JSBool success = JS_FALSE; /* Initialize to default case, in which no new Java object is synthesized to perform the conversion and, therefore, no JNI local references are being held. */ *is_local_refp = JS_FALSE; type = signature->type; v = v_arg; switch (type) { case JAVA_SIGNATURE_BOOLEAN: if (!JSVAL_IS_BOOLEAN(v)) { if (!JS_ConvertValue(cx, v, JSTYPE_BOOLEAN, &v)) goto conversion_error; if (JSVAL_IS_VOID(v)) goto conversion_error; (*cost)++; } if (java_value) java_value->z = (jboolean)(JSVAL_TO_BOOLEAN(v) == JS_TRUE); break; case JAVA_SIGNATURE_SHORT: JSVAL_TO_INTEGRAL_JVALUE(short, s, jshort, v, java_value); break; case JAVA_SIGNATURE_BYTE: JSVAL_TO_INTEGRAL_JVALUE(byte, b, jbyte, v, java_value); break; case JAVA_SIGNATURE_CHAR: /* A one-character string can be converted into a character */ if (JSVAL_IS_STRING(v) && (JS_GetStringLength(JSVAL_TO_STRING(v)) == 1)) { v = INT_TO_JSVAL(*JS_GetStringChars(JSVAL_TO_STRING(v))); } JSVAL_TO_INTEGRAL_JVALUE(char, c, jchar, v, java_value); break; case JAVA_SIGNATURE_INT: JSVAL_TO_INTEGRAL_JVALUE(int, i, jint, v, java_value); break; case JAVA_SIGNATURE_LONG: #if defined(XP_MAC) || (defined(XP_OS2) && !defined(HAVE_LONG_LONG)) JSVAL_TO_JLONG_JVALUE(j, jlong, v, java_value); #else JSVAL_TO_INTEGRAL_JVALUE(long, j, jlong, v, java_value); #endif break; case JAVA_SIGNATURE_FLOAT: if (!JSVAL_IS_NUMBER(v)) { if (!JS_ConvertValue(cx, v, JSTYPE_NUMBER, &v)) goto conversion_error; (*cost)++; } if (java_value) { if (JSVAL_IS_INT(v)) java_value->f = (jfloat) JSVAL_TO_INT(v); else java_value->f = (jfloat) *JSVAL_TO_DOUBLE(v); } break; case JAVA_SIGNATURE_DOUBLE: if (!JSVAL_IS_NUMBER(v)) { if (!JS_ConvertValue(cx, v, JSTYPE_NUMBER, &v)) goto conversion_error; (*cost)++; } if (java_value) { if (JSVAL_IS_INT(v)) java_value->d = (jdouble) JSVAL_TO_INT(v); else java_value->d = (jdouble) *JSVAL_TO_DOUBLE(v); } break; /* Non-primitive (reference) type */ default: JS_ASSERT(IS_REFERENCE_TYPE(type)); if (!jsj_ConvertJSValueToJavaObject(cx, jEnv, v, signature, cost, &java_value->l, is_local_refp)) goto conversion_error; break; case JAVA_SIGNATURE_UNKNOWN: case JAVA_SIGNATURE_VOID: JS_ASSERT(0); return JS_FALSE; } /* Success */ return JS_TRUE; numeric_conversion_error: success = JS_TRUE; /* Fall through ... */ conversion_error: if (java_value) { const char *jsval_string; const char *class_name; JSString *jsstr; jsval_string = NULL; jsstr = JS_ValueToString(cx, v_arg); if (jsstr) jsval_string = JS_GetStringBytes(jsstr); if (!jsval_string) jsval_string = ""; class_name = jsj_ConvertJavaSignatureToHRString(cx, signature); JS_ReportErrorNumber(cx, jsj_GetErrorMessage, NULL, JSJMSG_CANT_CONVERT_JS, jsval_string, class_name); return JS_FALSE; } return success; }
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 = js_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(js_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 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 }
char* launchApp(char *appName,int isMenu){ static int nruns = 0; char* tmp = NULL,*script = NULL, *addrBack = NULL; if(appName){ static JSContext *cx = NULL; static JSObject *gl = NULL; script = fileToString(LIBRARY); if(!(cx = JS_NewContext(runtime, 8192))){ fprint(stderr,"Problem creating runtime\n"); exit(EXIT_FAILURE); } JS_SetErrorReporter(cx, reportError); //if(!(gl = JS_NewCompartmentAndGlobalObject(cx, &global_class, NULL))){ static struct JSPrincipals def_principles = {0}; if(!(gl = JS_NewGlobalObject(cx, &global_class, NULL))){ fprint(stderr,"Problem creating global object\n"); exit(EXIT_FAILURE); } JSCompartment *cmp = JS_EnterCompartment(cx, gl); if (!(JS_InitStandardClasses(cx, gl))){ fprint(stderr,"Problem creating standard classes\n"); exit(EXIT_FAILURE); } if(!JS_DefineFunctions(cx, gl, jsFunctions)){ fprint(stderr,"Unable to load native functions\n"); exit(EXIT_FAILURE); } globalObject = gl; char *pathToFile = NULL; if(isMenu){ pathToFile = (char*)malloc(1+strlen(MENU_DIR)); strcpy(pathToFile,MENU_DIR); } else { pathToFile = (char*)malloc(strlen(appName) + 1 + strlen(GAMES_DIR)); strcpy(pathToFile,GAMES_DIR); strcat(pathToFile,appName); //strcat(pathToFile,"/"); } JSBool ran = JS_FALSE; jsval retVal; obj.chrootPath = pathToFile; JS_SetPrivate(cx,gl,&obj); SDL_FlushEvents(); //clear queue of events before starting a new app. if(isMenu && 0 == nruns) { //define the property first_run = true; JS_DefineProperty(cx,JS_GetGlobalObject(cx),"first_run",BOOLEAN_TO_JSVAL(JS_TRUE),NULL,NULL,0); } if(script){ loadBaseClasses(appName,pathToFile,cx); //appName is without the extension, appPath needs the directory to chroot ran = JS_EvaluateScript(cx, gl, script, strlen(script) , LIBRARY,0, &retVal); } nruns++; clearModules(cx); JS_GC(JS_GetRuntime(cx)); JS_LeaveCompartment(cx,cmp); //The user requested to quit. if(SDL_QuitRequested()){ if(script)free(script); exitProgram(cx); exit(EXIT_SUCCESS); } if(isMenu && (ran == JS_FALSE)){ if(script) free(script); exitProgram(cx); exit(EXIT_FAILURE); } if(ran != JS_FALSE){ if(JSVAL_IS_STRING(retVal)){ addrBack = JS_EncodeString(cx,JSVAL_TO_STRING(retVal)); tmp = (char*)malloc(strlen(addrBack) +1); strcpy(tmp,addrBack); JS_free(cx,addrBack); addrBack = tmp; } if(JSVAL_IS_BOOLEAN(retVal) && isMenu){ if(script) free(script); if(pathToFile) free(pathToFile); exitProgram(cx); exit(EXIT_SUCCESS); } } else { addrBack = NULL; } if(script) free(script); if(pathToFile) free(pathToFile); JS_DestroyContext(cx); return addrBack; } }
void Dump(Handle<String> str) { jsval v = str->native(); js_DumpString(JSVAL_TO_STRING(v)); }
static JSBool access_java_array_element(JSContext *cx, JNIEnv *jEnv, JSObject *obj, jsid id, jsval *vp, JSBool do_assignment) { jsval idval; jarray java_array; JavaClassDescriptor *class_descriptor; JavaObjectWrapper *java_wrapper; jsize array_length, index; JavaSignature *array_component_signature; /* printf("In JavaArray_getProperty\n"); */ java_wrapper = JS_GetPrivate(cx, obj); if (!java_wrapper) { const char *property_name; if (JS_IdToValue(cx, id, &idval) && JSVAL_IS_STRING(idval) && (property_name = JS_GetStringBytes(JSVAL_TO_STRING(idval))) != NULL) { if (!strcmp(property_name, "constructor")) { if (vp) *vp = JSVAL_VOID; return JS_TRUE; } } JS_ReportErrorNumber(cx, jsj_GetErrorMessage, NULL, JSJMSG_BAD_OP_JARRAY); return JS_FALSE; } class_descriptor = java_wrapper->class_descriptor; java_array = java_wrapper->java_obj; JS_ASSERT(class_descriptor->type == JAVA_SIGNATURE_ARRAY); JS_IdToValue(cx, id, &idval); if (!JSVAL_IS_INT(idval)) idval = try_convert_to_jsint(cx, idval); if (!JSVAL_IS_INT(idval)) { /* * Usually, properties of JavaArray objects are indexed by integers, but * Java arrays also inherit all the methods of java.lang.Object, so a * string-valued property is also possible. */ if (JSVAL_IS_STRING(idval)) { const char *member_name; member_name = JS_GetStringBytes(JSVAL_TO_STRING(idval)); if (do_assignment) { JSVersion version = JS_GetVersion(cx); if (!JSVERSION_IS_ECMA(version)) { JS_ReportErrorNumber(cx, jsj_GetErrorMessage, NULL, JSJMSG_CANT_WRITE_JARRAY, member_name); return JS_FALSE; } else { if (vp) *vp = JSVAL_VOID; return JS_TRUE; } } else { if (!strcmp(member_name, "length")) { array_length = jsj_GetJavaArrayLength(cx, jEnv, java_array); if (array_length < 0) return JS_FALSE; if (vp) *vp = INT_TO_JSVAL(array_length); return JS_TRUE; } /* Check to see if we're reflecting a Java array method */ return JavaObject_getPropertyById(cx, obj, id, vp); } } JS_ReportErrorNumber(cx, jsj_GetErrorMessage, NULL, JSJMSG_BAD_INDEX_EXPR); return JS_FALSE; } index = JSVAL_TO_INT(idval); #if 0 array_length = jsj_GetJavaArrayLength(cx, jEnv, java_array); if (array_length < 0) return JS_FALSE; /* Just let Java throw an exception instead of checking array bounds here */ if (index < 0 || index >= array_length) { char numBuf[12]; sprintf(numBuf, "%d", index); JS_ReportErrorNumber(cx, jsj_GetErrorMessage, NULL, JSJMSG_BAD_JARRAY_INDEX, numBuf); return JS_FALSE; } #endif array_component_signature = class_descriptor->array_component_signature; if (!vp) return JS_TRUE; if (do_assignment) { return jsj_SetJavaArrayElement(cx, jEnv, java_array, index, array_component_signature, *vp); } else { return jsj_GetJavaArrayElement(cx, jEnv, java_array, index, array_component_signature, vp); } }
static const char * name_by_id(jsval id) { return JSVAL_IS_STRING(id) ? JS_GetStringBytes(JSVAL_TO_STRING(id)) : NULL; }
/** * This method is called when setting a Property in HTMLInput */ static JSBool jhtml_input_setProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp) { WebcJSScript *jsscr = (WebcJSScript *) jhutil_GetContextPrivate(cx); WebcJSDocumentContext *jsmgr = (jsscr)? jsscr->GetJSMgr() : 0; HTMLInput *element = (HTMLInput *) jhutil_GetPrivate(cx, obj); if (!element) { return JS_TRUE; } switch (JSVAL_TO_INT(id)) { case HTMLINPUTELEMENT_VALUE: { element->SetValue(WEBC_JS_STRING_TO_WEBC_STRING(JS_ValueToString(cx, *vp))); return JS_TRUE; } case HTMLINPUTELEMENT_DEFAULTVALUE: { element->SetDefValue(WEBC_JS_STRING_TO_WEBC_STRING(JS_ValueToString(cx, *vp))); return JS_TRUE; } case HTMLINPUTELEMENT_CHECKED: case HTMLINPUTELEMENT_DEFAULTCHECKED: { int on = 0; if (JSVAL_IS_BOOLEAN(*vp)) { if (JSVAL_TO_BOOLEAN(*vp) == JS_TRUE) { on = 1; } element->SetChecked(on); return JS_TRUE; } } break; case HTMLINPUTELEMENT_ACCEPT: { if (JSVAL_IS_STRINGABLE(*vp)) { element->SetAccept(WEBC_JS_STRING_TO_WEBC_STRING(JS_ValueToString(cx, *vp))); return JS_TRUE; } } break; case HTMLINPUTELEMENT_ACCESSKEY: { char *str = JS_GetStringBytes(JS_ValueToString(cx, *vp)); if (str && *str) { element->SetAccessKey((WEBC_UINT16)str[0]); } return JS_TRUE; } case HTMLINPUTELEMENT_ALIGN: { WEBC_CHAR *str = WEBC_JS_STRING_TO_WEBC_STRING(JSVAL_TO_STRING(*vp)); if(str) element->SetHtmlAlign(HTML_ParseAlignType(str, 0)); } break; case HTMLINPUTELEMENT_ALT: { element->SetAlt(WEBC_JS_STRING_TO_WEBC_STRING(JS_ValueToString(cx, *vp))); return JS_TRUE; } case HTMLINPUTELEMENT_SRC: { element->SetSrc(WEBC_JS_STRING_TO_WEBC_STRING(JS_ValueToString(cx, *vp))); element->Update(0,0); return JS_TRUE; } case HTMLINPUTELEMENT_DISABLED: { if (JSVAL_IS_BOOLEAN(*vp)) { element->SetDisabled((JSVAL_TO_BOOLEAN(*vp) == JS_TRUE)? 1 : 0); return JS_TRUE; } } break; case HTMLINPUTELEMENT_MAXLENGTH: { long newMaxLength = webc_atoi(WEBC_JS_STRING_TO_WEBC_STRING(JS_ValueToString(cx, *vp))); element->SetMaxLength(newMaxLength); return JS_TRUE; } case HTMLINPUTELEMENT_NAME: { if (JSVAL_IS_STRINGABLE(*vp)) { element->SetName(WEBC_JS_STRING_TO_WEBC_STRING(JS_ValueToString(cx, *vp))); return JS_TRUE; } } break; case HTMLINPUTELEMENT_READONLY: { if (JSVAL_IS_BOOLEAN(*vp)) { if (JSVAL_TO_BOOLEAN(*vp) == JS_FALSE) { element->ClearFlag(HINPUT_FLAG_READONLY); } else { element->SetFlag(HINPUT_FLAG_READONLY); } element->StyleUpdate(); return JS_TRUE; } } break; case HTMLINPUTELEMENT_SIZE: { long newSize = webc_atoi(WEBC_JS_STRING_TO_WEBC_STRING(JS_ValueToString(cx, *vp))); element->SetSize(newSize); return JS_TRUE; } case HTMLINPUTELEMENT_TABINDEX: { if (JSVAL_IS_NUMBER(*vp)) { int32 ti; JS_ValueToInt32(cx, *vp, &ti); element->SetTabIndex((short)ti); return JS_TRUE; } } break; case HTMLINPUTELEMENT_TYPE: { HTMLElement *pNewElement = 0; HTMLInputType newInputType = jhtml_input_determine_type(WEBC_JS_STRING_TO_WEBC_STRING(JS_ValueToString(cx, *vp))); pNewElement = jhtml_input_change_type((HTMLInput *) element, newInputType, jsmgr->GetDocument()); // WARNING: pInput has potentially been deleted by the call to jhtml_input_change_type above if(pNewElement) { jhutil_SetPrivate(cx, obj, pNewElement); } } break; default: break; } //end switch return JS_TRUE; }
JSBool XPCVariant::InitializeData(XPCCallContext& ccx) { if(JSVAL_IS_INT(mJSVal)) return NS_SUCCEEDED(nsVariant::SetFromInt32(&mData, JSVAL_TO_INT(mJSVal))); if(JSVAL_IS_DOUBLE(mJSVal)) return NS_SUCCEEDED(nsVariant::SetFromDouble(&mData, *JSVAL_TO_DOUBLE(mJSVal))); if(JSVAL_IS_BOOLEAN(mJSVal)) return NS_SUCCEEDED(nsVariant::SetFromBool(&mData, JSVAL_TO_BOOLEAN(mJSVal))); if(JSVAL_IS_VOID(mJSVal)) return NS_SUCCEEDED(nsVariant::SetToEmpty(&mData)); if(JSVAL_IS_NULL(mJSVal)) return NS_SUCCEEDED(nsVariant::SetToEmpty(&mData)); if(JSVAL_IS_STRING(mJSVal)) { return NS_SUCCEEDED(nsVariant::SetFromWStringWithSize(&mData, (PRUint32)JS_GetStringLength(JSVAL_TO_STRING(mJSVal)), (PRUnichar*)JS_GetStringChars(JSVAL_TO_STRING(mJSVal)))); } // leaving only JSObject... NS_ASSERTION(JSVAL_IS_OBJECT(mJSVal), "invalid type of jsval!"); JSObject* jsobj = JSVAL_TO_OBJECT(mJSVal); // Let's see if it is a xpcJSID. // XXX It might be nice to have a non-allocing version of xpc_JSObjectToID. nsID* id = xpc_JSObjectToID(ccx, jsobj); if(id) { JSBool success = NS_SUCCEEDED(nsVariant::SetFromID(&mData, *id)); nsMemory::Free((char*)id); return success; } // Let's see if it is a js array object. jsuint len; if(JS_IsArrayObject(ccx, jsobj) && JS_GetArrayLength(ccx, jsobj, &len)) { if(!len) { // Zero length array nsVariant::SetToEmptyArray(&mData); return JS_TRUE; } nsXPTType type; nsID id; if(!XPCArrayHomogenizer::GetTypeForArray(ccx, jsobj, len, &type, &id)) return JS_FALSE; if(!XPCConvert::JSArray2Native(ccx, &mData.u.array.mArrayValue, mJSVal, len, len, type, type.IsPointer(), &id, nsnull)) return JS_FALSE; mData.mType = nsIDataType::VTYPE_ARRAY; if(type.IsInterfacePointer()) mData.u.array.mArrayInterfaceID = id; mData.u.array.mArrayCount = len; mData.u.array.mArrayType = type.TagPart(); return JS_TRUE; } // XXX This could be smarter and pick some more interesting iface. nsXPConnect* xpc; nsCOMPtr<nsISupports> wrapper; const nsIID& iid = NS_GET_IID(nsISupports); return nsnull != (xpc = nsXPConnect::GetXPConnect()) && NS_SUCCEEDED(xpc->WrapJS(ccx, jsobj, iid, getter_AddRefs(wrapper))) && NS_SUCCEEDED(nsVariant::SetFromInterface(&mData, iid, wrapper)); }
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; }
JSBool Library::Declare(JSContext* cx, uintN argc, jsval* vp) { JSObject* obj = JS_THIS_OBJECT(cx, vp); if (!obj || !IsLibrary(cx, obj)) { JS_ReportError(cx, "not a library"); return JS_FALSE; } PRLibrary* library = GetLibrary(cx, obj); if (!library) { JS_ReportError(cx, "library not open"); return JS_FALSE; } // We allow two API variants: // 1) library.declare(name, abi, returnType, argType1, ...) // declares a function with the given properties, and resolves the symbol // address in the library. // 2) library.declare(name, type) // declares a symbol of 'type', and resolves it. The object that comes // back will be of type 'type', and will point into the symbol data. // This data will be both readable and writable via the usual CData // accessors. If 'type' is a PointerType to a FunctionType, the result will // be a function pointer, as with 1). if (argc < 2) { JS_ReportError(cx, "declare requires at least two arguments"); return JS_FALSE; } jsval* argv = JS_ARGV(cx, vp); if (!JSVAL_IS_STRING(argv[0])) { JS_ReportError(cx, "first argument must be a string"); return JS_FALSE; } JSObject* fnObj = NULL; JSObject* typeObj; js::AutoObjectRooter root(cx); bool isFunction = argc > 2; if (isFunction) { // Case 1). // Create a FunctionType representing the function. fnObj = FunctionType::CreateInternal(cx, argv[1], argv[2], &argv[3], argc - 3); if (!fnObj) return JS_FALSE; root.setObject(fnObj); // Make a function pointer type. typeObj = PointerType::CreateInternal(cx, fnObj); if (!typeObj) return JS_FALSE; root.setObject(typeObj); } else { // Case 2). if (JSVAL_IS_PRIMITIVE(argv[1]) || !CType::IsCType(cx, JSVAL_TO_OBJECT(argv[1])) || !CType::IsSizeDefined(cx, JSVAL_TO_OBJECT(argv[1]))) { JS_ReportError(cx, "second argument must be a type of defined size"); return JS_FALSE; } typeObj = JSVAL_TO_OBJECT(argv[1]); if (CType::GetTypeCode(cx, typeObj) == TYPE_pointer) { fnObj = PointerType::GetBaseType(cx, typeObj); isFunction = fnObj && CType::GetTypeCode(cx, fnObj) == TYPE_function; } } void* data; PRFuncPtr fnptr; JSString* nameStr = JSVAL_TO_STRING(argv[0]); AutoCString symbol; if (isFunction) { // Build the symbol, with mangling if necessary. FunctionType::BuildSymbolName(cx, nameStr, fnObj, symbol); AppendString(symbol, "\0"); // Look up the function symbol. fnptr = PR_FindFunctionSymbol(library, symbol.begin()); if (!fnptr) { JS_ReportError(cx, "couldn't find function symbol in library"); return JS_FALSE; } data = &fnptr; } else { // 'typeObj' is another data type. Look up the data symbol. AppendString(symbol, nameStr); AppendString(symbol, "\0"); data = PR_FindSymbol(library, symbol.begin()); if (!data) { JS_ReportError(cx, "couldn't find symbol in library"); return JS_FALSE; } } JSObject* result = CData::Create(cx, typeObj, obj, data, isFunction); if (!result) return JS_FALSE; JS_SET_RVAL(cx, vp, OBJECT_TO_JSVAL(result)); // Seal the CData object, to prevent modification of the function pointer. // This permanently associates this object with the library, and avoids // having to do things like reset SLOT_REFERENT when someone tries to // change the pointer value. // XXX This will need to change when bug 541212 is fixed -- CData::ValueSetter // could be called on a sealed object. if (isFunction && !JS_FreezeObject(cx, result)) return JS_FALSE; 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; }
const char* XPCNativeInterface::GetMemberName(XPCCallContext& ccx, const XPCNativeMember* member) const { return JS_GetStringBytes(JSVAL_TO_STRING(member->GetName())); }
NS_IMETHODIMP TCPSocketParent::SendCallback(const nsAString& aType, const JS::Value& aDataVal, const nsAString& aReadyState, uint32_t aBuffered, JSContext* aCx) { if (!mIPCOpen) { NS_WARNING("Dropping callback due to no IPC connection"); return NS_OK; } CallbackData data; if (aDataVal.isString()) { JSString* jsstr = aDataVal.toString(); nsDependentJSString str; if (!str.init(aCx, jsstr)) { FireInteralError(this, __LINE__); return NS_ERROR_OUT_OF_MEMORY; } data = SendableData(str); } else if (aDataVal.isUndefined() || aDataVal.isNull()) { data = mozilla::void_t(); } else if (aDataVal.isObject()) { JSObject* obj = &aDataVal.toObject(); if (JS_IsArrayBufferObject(obj)) { uint32_t nbytes = JS_GetArrayBufferByteLength(obj); uint8_t* buffer = JS_GetArrayBufferData(obj); if (!buffer) { FireInteralError(this, __LINE__); return NS_ERROR_OUT_OF_MEMORY; } FallibleTArray<uint8_t> fallibleArr; if (!fallibleArr.InsertElementsAt(0, buffer, nbytes)) { FireInteralError(this, __LINE__); return NS_ERROR_OUT_OF_MEMORY; } InfallibleTArray<uint8_t> arr; arr.SwapElements(fallibleArr); data = SendableData(arr); } else { nsDependentJSString name; JS::Rooted<JS::Value> val(aCx); if (!JS_GetProperty(aCx, obj, "name", val.address())) { NS_ERROR("No name property on supposed error object"); } else if (JSVAL_IS_STRING(val)) { if (!name.init(aCx, JSVAL_TO_STRING(val))) { NS_WARNING("couldn't initialize string"); } } data = TCPError(name); } } else { NS_ERROR("Unexpected JS value encountered"); FireInteralError(this, __LINE__); return NS_ERROR_FAILURE; } mozilla::unused << PTCPSocketParent::SendCallback(nsString(aType), data, nsString(aReadyState), aBuffered); return NS_OK; }
static int json_encode_from_object(JSContext *cx, JSObject *obj, htsbuf_queue_t *out) { int objtype = 0; JSIdArray *ida; int i; const char *n; if((ida = JS_Enumerate(cx, obj)) == NULL) return -1; for(i = 0; i < ida->length; i++) { jsval name, value; if(!JS_IdToValue(cx, ida->vector[i], &name)) continue; if(JSVAL_IS_STRING(name)) { JSString *str = JSVAL_TO_STRING(name); n = JS_GetStringBytes(str); if(!JS_GetProperty(cx, obj, n, &value)) continue; if(objtype == 0) { htsbuf_append(out, "{", 1); objtype = OBJTYPE_MAP; } else if(objtype != OBJTYPE_MAP) continue; else htsbuf_append(out, ",", 1); htsbuf_append_and_escape_jsonstr(out, n); htsbuf_append(out, ":", 1); } else if(JSVAL_IS_INT(name)) { if(!JS_GetElement(cx, obj, JSVAL_TO_INT(name), &value) || JSVAL_IS_VOID(value)) continue; if(objtype == 0) { htsbuf_append(out, "[", 1); objtype = OBJTYPE_LIST; } else if(objtype != OBJTYPE_LIST) continue; else htsbuf_append(out, ",", 1); } else { continue; } js_json_emit_jsval(cx, value, out); } JS_DestroyIdArray(cx, ida); switch(objtype) { case OBJTYPE_LIST: htsbuf_append(out, "]", 1); break; case OBJTYPE_MAP: htsbuf_append(out, "}", 1); break; default: return -1; } return 0; }
// Convert from a jsval to an AtNode static AtSmartPtr<AtNode> ConvertNode(JSContext* cx, jsval node) { AtSmartPtr<AtNode> obj (new AtNode()); // Non-objects get converted into strings if (!JSVAL_IS_OBJECT(node)) { JSString* str = JS_ValueToString(cx, node); if (!str) return obj; // error size_t valueLen; const jschar* valueChars = JS_GetStringCharsAndLength(cx, str, &valueLen); if (!valueChars) return obj; // error wxString valueWx(reinterpret_cast<const char*>(valueChars), wxMBConvUTF16(), valueLen*2); obj->value = valueWx.c_str(); // Annotate numbers/booleans specially, to allow round-tripping if (JSVAL_IS_NUMBER(node)) { obj->children.insert(AtNode::child_pairtype( "@number", AtSmartPtr<AtNode>(new AtNode()) )); } else if (JSVAL_IS_BOOLEAN(node)) { obj->children.insert(AtNode::child_pairtype( "@boolean", AtSmartPtr<AtNode>(new AtNode()) )); } return obj; } JSObject* it = JS_NewPropertyIterator(cx, JSVAL_TO_OBJECT(node)); if (!it) return obj; // error while (true) { jsid idp; jsval val; if (! JS_NextProperty(cx, it, &idp) || ! JS_IdToValue(cx, idp, &val)) return obj; // error if (val == JSVAL_VOID) break; // end of iteration if (! JSVAL_IS_STRING(val)) continue; // ignore integer properties JSString* name = JSVAL_TO_STRING(val); size_t len; const jschar* chars = JS_GetStringCharsAndLength(cx, name, &len); wxString nameWx(reinterpret_cast<const char*>(chars), wxMBConvUTF16(), len*2); std::string nameStr(nameWx.ToUTF8().data()); jsval vp; if (!JS_GetPropertyById(cx, JSVAL_TO_OBJECT(node), idp, &vp)) return obj; // error // Unwrap arrays into a special format like <$name><item>$i0</item><item>... // (This assumes arrays aren't nested) if (JSVAL_IS_OBJECT(vp) && JS_IsArrayObject(cx, JSVAL_TO_OBJECT(vp))) { AtSmartPtr<AtNode> child(new AtNode()); child->children.insert(AtNode::child_pairtype( "@array", AtSmartPtr<AtNode>(new AtNode()) )); jsuint arrayLength; if (!JS_GetArrayLength(cx, JSVAL_TO_OBJECT(vp), &arrayLength)) return obj; // error for (jsuint i = 0; i < arrayLength; ++i) { jsval val; if (!JS_GetElement(cx, JSVAL_TO_OBJECT(vp), i, &val)) return obj; // error child->children.insert(AtNode::child_pairtype( "item", ConvertNode(cx, val) )); } obj->children.insert(AtNode::child_pairtype( nameStr, child )); } else { obj->children.insert(AtNode::child_pairtype( nameStr, ConvertNode(cx, vp) )); } } return obj; }
// Clone a new value (and root it and add it to the mapping) jsval Clone(jsval val) { if (JSVAL_IS_DOUBLE(val)) { jsval rval; CLONE_REQUIRE(JS_NewNumberValue(cxTo, JSVAL_TO_DOUBLE(val), &rval), L"JS_NewNumberValue"); m_RooterTo.Push(rval); return rval; } if (JSVAL_IS_STRING(val)) { size_t len; const jschar* chars = JS_GetStringCharsAndLength(cxFrom, JSVAL_TO_STRING(val), &len); CLONE_REQUIRE(chars, L"JS_GetStringCharsAndLength"); JSString* str = JS_NewUCStringCopyN(cxTo, chars, len); CLONE_REQUIRE(str, L"JS_NewUCStringCopyN"); jsval rval = STRING_TO_JSVAL(str); m_Mapping[JSVAL_TO_GCTHING(val)] = rval; m_RooterTo.Push(rval); return rval; } ENSURE(JSVAL_IS_OBJECT(val)); JSObject* newObj; if (JS_IsArrayObject(cxFrom, JSVAL_TO_OBJECT(val))) { jsuint length; CLONE_REQUIRE(JS_GetArrayLength(cxFrom, JSVAL_TO_OBJECT(val), &length), L"JS_GetArrayLength"); newObj = JS_NewArrayObject(cxTo, length, NULL); CLONE_REQUIRE(newObj, L"JS_NewArrayObject"); } else { newObj = JS_NewObject(cxTo, NULL, NULL, NULL); CLONE_REQUIRE(newObj, L"JS_NewObject"); } m_Mapping[JSVAL_TO_GCTHING(val)] = OBJECT_TO_JSVAL(newObj); m_RooterTo.Push(newObj); AutoJSIdArray ida (cxFrom, JS_Enumerate(cxFrom, JSVAL_TO_OBJECT(val))); CLONE_REQUIRE(ida.get(), L"JS_Enumerate"); AutoGCRooter idaRooter(scriptInterfaceFrom); idaRooter.Push(ida.get()); for (size_t i = 0; i < ida.length(); ++i) { jsid id = ida[i]; jsval idval, propval; CLONE_REQUIRE(JS_IdToValue(cxFrom, id, &idval), L"JS_IdToValue"); CLONE_REQUIRE(JS_GetPropertyById(cxFrom, JSVAL_TO_OBJECT(val), id, &propval), L"JS_GetPropertyById"); jsval newPropval = GetOrClone(propval); if (JSVAL_IS_INT(idval)) { // int jsids are portable across runtimes CLONE_REQUIRE(JS_SetPropertyById(cxTo, newObj, id, &newPropval), L"JS_SetPropertyById"); } else if (JSVAL_IS_STRING(idval)) { // string jsids are runtime-specific, so we need to copy the string content JSString* idstr = JS_ValueToString(cxFrom, idval); CLONE_REQUIRE(idstr, L"JS_ValueToString (id)"); size_t len; const jschar* chars = JS_GetStringCharsAndLength(cxFrom, idstr, &len); CLONE_REQUIRE(idstr, L"JS_GetStringCharsAndLength (id)"); CLONE_REQUIRE(JS_SetUCProperty(cxTo, newObj, chars, len, &newPropval), L"JS_SetUCProperty"); } else { // this apparently could be an XML object; ignore it } } return OBJECT_TO_JSVAL(newObj); }