Subj : SpiderMonkey: JS_InitStandardClasses allways fails To : netscape.public.mozilla.jseng From : =?ISO-8859-1?Q?Georg_Maa=DF?= Date : Mon May 05 2003 08:36 pm Hi, I have problems to make SpiderMonkey work correctly when called from my application (C++). 1. problem: JS_InitStandardClasses allways fails (return value is false). In js.c from js1.5rc5 there is a macro flag called LAZY_STANDARD_CLASSES, which triggers whether this function is used there or not. The macro flag is set, which causes JS_InitStandardClasses not to be called. Because of allways failing of JS_InitStandardClasses I defined this macro flag too in my own attempt, to circumvent that function. 2. problem: any name insiede JavaScript code causes the whole script to fail without any error message. Scripts like "2*3;" are evaluated perfectly resulting in "6". Scripts like "10;0815;" result as expected in an error message: "test.js:4711: warning: 08 is not a legal ECMA-262 octal constant: test.js:4711: warning: 15;0815; test.js:4711: warning: ...^"; This means my function ErrorReporter is connected correctly to the engine and seams to work correctly. But scripts like "Math.max(1,2)" fail without error message. Also scripts like "var a = 1; 2 * 3 + a;" fail without error message, when JS_EvaluateScript is called. The behaviour is the same when first failing with JS_InitStandardClasses or just not calling JS_InitStandardClasses. I assume, that I did something simple but essential wrong, but I have no idea, what I did wrong. 3. problem: how can I get a std::string or at least a char* from a JSVAL that is a JSVAL_STRING. The JSString struct is different to std::string and also not a real char*. But char* is also not really nice, because this expects 0 as end mark and not als legal character, where std::string also allows 0 as character. I've pasted two functions. init sets up SpiderMonkey and does a test call to the second function evaluateJavaScript to evaluate a small test script and transfer the result into the variables of my application. I hope one of you can help me to solve the problems. bool init() // globale Initialisierung der Mozilla-Engine { // available = false; // Flag löschen, da wir noch nicht wisssen, ob die Mozilla- // Engine tatsächlich funktioniert. version = JSVERSION_DEFAULT; // Mozilla-Engine JavaScript-Version festlegen if(runtime) JS_DestroyRuntime(runtime); // Falls wir schon eine Runtime-Umgebung haben, entsorgen wir sie // if(runtime = JS_Init(8L * 1024L * 1024L)) // Runtime-Umgebung initialisieren. if(runtime = JS_NewRuntime(8L * 1024L * 1024L)) // Runtime-Umgebung initialisieren. { if(global_context = JS_NewContext(runtime, STACK_CHUNK_SIZE)) { JS_SetErrorReporter(global_context, ErrorReporter); // Error-Reporter anschließen #ifdef __mozilla_stub__ if(global_object = JS_NewObject ( // Das globale Objekt initialisieren global_context , &global_class , 0 , 0 )) { #ifdef LAZY_STANDARD_CLASSES JS_SetGlobalObject ( // JavaScript-Objekte intialisieren und festhalten, ob die // Mozilla-Engine funktioniert. global_context , global_object ); available = true; // Da wir keine Information über Erfolg oder Mißerfolg // erhalten, gehen wir vom Erfolg aus. evaluateJavaScript("2*3;","test.js",4711); // TEST #else available = JS_InitStandardClasses ( // JavaScript-Objekte intialisieren und festhalten, ob die // Mozilla-Engine funktioniert. global_context , global_object ); if(!available) ERRORS.push_back ( // Beim Versuch, die JavaScript-Objekte zu initialisieren, Error ( // trat ein Fehler auf. "gmL_mozilla::init" , Error_failed_setup_js_javascript_objects ) ); #endif } else ERRORS.push_back ( // Beim Versuch das Globale-Object der Mozilla-Engine zu Error ( // initialisieren, trat ein Fehler auf. "gmL_mozilla::init" , Error_failed_setup_js_global_object ) ); #else #endif } else ERRORS.push_back ( // Beim Versuch einen Context der Mozilla-Engine zu Error ( // initialisieren, trat ein Fehler auf. "gmL_mozilla::init" , Error_failed_setup_js_context ) ); } else ERRORS.push_back ( // Beim Versuch die Runtime-Umgebung der Mozilla-Engine zu Error ( // initialisieren, trat ein Fehler auf. "gmL_mozilla::init" , Error_failed_setup_js_runtime ) ); pair pa = GLOBALS.insert(pair("mozilla_enabled",0)); if(pa.first->second) // Wurde eine bestehende Variable mit einem Wert-Objekt gefunden? { // JA, also müssen wir ihren Typ nun aufbool festlegen pa.first->second->setType(Wert_bool); } else { // NEIN, ein Zeiger für eine neue Variable wurde angelegt // oder ein Zeiger für eine gelöschte Variable gefunden. pa.first->second = new Wert(Wert_bool); // Neue Variable erzeugen und dem Zeiger zuweisen } pa.first->second->setValue(available); // festhalten, ob die Mozilla-Engine funktioniert return available; } Wert* evaluateJavaScript ( const std::string& Quelltext , const std::string& Datei , unsigned long Zeile ) { jsval rval; bool ok = JS_EvaluateScript ( global_context , global_object , Quelltext.c_str() , Quelltext.size() , Datei.c_str() , Zeile , &rval ); pair pa = GLOBALS.insert(pair("mozilla_result",0)); switch(JS_TypeOfValue(global_context, rval)) { case JSTYPE_VOID: { if(pa.first->second) pa.first->second->setType(0); // Typ auf "undefined" setzen else pa.first->second = new Wert(0); // Variable mit Typ "undefined" erzeugen und Zeiger zuweisen break; } case JSTYPE_BOOLEAN: { if(pa.first->second) pa.first->second->setType(Wert_bool); // Typ auf bool setzen else pa.first->second = new Wert(Wert_bool); // Variable mit Typ bool erzeugen und Zeiger zuweisen pa.first->second->setValue(JSVAL_TO_BOOLEAN(rval)); // Wert speichern break; } case JSTYPE_NUMBER: { if(JSVAL_IS_INT(rval)) { if(pa.first->second) pa.first->second->setType(Wert_int); // Typ auf int setzen else pa.first->second = new Wert(Wert_int); // Variable mit Typ int erzeugen und Zeiger zuweisen pa.first->second->setValue(JSVAL_TO_INT(rval)); // Wert speichern } else { jsdouble d; ok = JS_ValueToNumber(global_context, rval, &d); if(pa.first->second) pa.first->second->setType(Wert_double); // Typ auf double setzen else pa.first->second = new Wert(Wert_double); // Variable mit Typ double erzeugen und Zeiger zuweisen if(ok) pa.first->second->setValue(d); // Wenn wie einen Wert erhielten, Wert speichern; else pa.first->second->setType(0); // sonst Typ auf "undefined" setzen } break; } case JSTYPE_STRING: { /* Das funktioniert nicht! JSVAL_TO_STRING erzeugt keinen char* if(pa.first->second) pa.first->second->setType(Wert_string); // Typ auf string setzen else pa.first->second = new Wert(Wert_string); // Variable mit Typ string erzeugen und Zeiger zuweisen pa.first->second->setValue(JSVAL_TO_STRING(rval)); // Wert speichern break; */ } case JSTYPE_OBJECT: { //### ToDo ### Hier soll ein Quelltext-Literal des Objektes entstehen (uneval) // break; } case JSTYPE_FUNCTION: { //### ToDo ### Hier soll ein Quelltext-Literal der Funktion entstehen (uneval) // break; } default: { // Autsch! Es ist irgend ein Typ, den wir nicht unterstützen if(pa.first->second) pa.first->second->setType(0); // Typ auf "undefined" setzen else pa.first->second = new Wert(0); // Variable mit Typ "undefined" erzeugen und Zeiger zuweisen } } if(ok) return pa.first->second; // Wir geben einen Zeiger auf das Result-Objekt zurück } if(!ok) { std::ostringstream oS; oS << Zeile; ERRORS.push_back ( // Ein unbekannter JavaScript-Fehler trat auf. Error ( "gmL_mozilla::evaluateJavaScript" , Error_js_error , Quelltext // problematischer Quelltext , Datei // Datei , oS.str() // Zeilennummer ) ); } return 0; // Wir signalisieren den Fehler durch einen null-Zeiger } -- Georg Maaß - bioshop.de D-93466 Chamerau, Roßbergweg 42 JavaScript, C++ Engineering - The ultimative DHTML engine: http://gml-modul.sourceforge.net - http://sourceforge.net/projects/gml-modul .