Subj : Newb; script library To : netscape.public.mozilla.jseng From : Lyndon Date : Mon Oct 18 2004 12:31 pm Setup: I have an application which is XSLT-like in nature; it transforms large XML datasets into other formats. I've added SpiderMonkey to it, and can successfully call a single function out of my library. It is when I try to have more than one function that I'm encountering trouble. At application initialization, I set up the run time, context, and global object (copy and paste from SpiderMonkey docs). Then, I truck through my script library, loading things up, using load_js_files() below. an example of a file is: function ucase( ucase_string ) { return( ucase_string.toUpperCase() ); } //------------------------------- void load_js_files() { extern char *sz_jsdir; jsval rval; char tfnam[MAX_STR_LEN]; DIR *d; FILE *f; char *b; struct dirent *de; struct stat sb; JSScript *jsp; if ( NULL != ( d = opendir( sz_jsdir ) ) ) { while( NULL != ( de = readdir( d ) ) ) { if ( 0 == strcmp( &de->d_name[de->d_namlen-3], ".js" ) ) { sprintf( (char *)&tfnam, "%s/%s%c", sz_jsdir, de->d_name, 0 ); stat( tfnam, &sb ); if ( NULL != ( f = fopen( tfnam, "r" ) ) ) { if ( NULL != ( b = (char *)malloc( sb.st_size + 1 ) ) ) { memset( b, 0, sb.st_size + 1 ); fread( b, sb.st_size, 1, f ); if ( NULL == ( jsp = JS_CompileScript( jscx, jsglob, b, sb.st_size, de->d_name, 0 ) ) ) { /* bad thing */ fprintf( stderr, "Error compiling script %s\n", de->d_name ); } else if ( JS_FALSE == JS_ExecuteScript( jscx, jsglob, jsp, &rval ) ) { /* bad thing */ fprintf( stderr, "Error executing script %s\n", de->d_name ); } free( b ); b = NULL; } fclose( f ); } } } closedir( d ); } } //------------------------------- For each datum I encounter, I add it as a variable in the global. This allows me to reference data using the tagnames in the original XML... e.g. Lyndon would, in the below snippit, produce "var myname = \"Lyndon\";" //------------------------------- char jstmp[MAX_STR_LEN]; jsval rval; sprintf( jstmp, "%s = \"%s\";", tag, tbuf ); if ( JS_FALSE == JS_EvaluateScript( jscx, jsglob, jstmp, strlen(jstmp), jstmp, 0, &rval ) ) { fprintf( stderr, "Error creating variable %s with value %s\n", tag, tbuf ); } //------------------------------- Of course I have a Processing Instructions file, something like a stylesheet. For the above example, it may do something like this: ucase( myname ); When I encounter this tag, I call into the Monkey: //------------------------------- case SEGMENT_TYPE_JSFUNC: /* javascript function */ if ( JS_TRUE == JS_EvaluateScript( jscx, jsglob, segments[seg_i].data, segments[seg_i].size, segments[seg_i].data, 0, &rval ) ) { JS_ConvertValue( jscx, rval, JSTYPE_STRING, &rval ); rstr = JS_ValueToString(jscx, rval); strncat( mbuf, JS_GetStringBytes( rstr ), JS_GetStringLength( rstr ) ); } break; //------------------------------- So, that all runs through fine, and I was actually pretty pleased with how easy it was to add this limited support that I have. To the point, though, if I have another JS file in my library (or even another function in the same file), that function fails to execute properly. To wit: Lyndonbilliards Name: ucase( hobby ) lcase( firstname ) Output should be: Name: LYNDON billiards but I get: Name: billiards when lcase() is loaded first, or Name: LYNDON when ucase() is loaded first. Please help; I'm confused about things like JS_CompileFunction, which partly appears to be for JavaScript, and partly appears to be for C callbacks. I'd like to just have all my functions in a global way, without worrying too much about keeping track of tons of JSScript* or other pointers. Any suggestions greatly appreciated. Thanks, <:) Lyndon .