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
.