Discussion:
call C function from JS: how to get "original" name
Dzianis Barzakouski
2011-05-25 19:20:41 UTC
Permalink
Hi All,

I have a simple app that uses SpiderMonkey for scripting purposes
( calls C functions from JS ). I do following (example from
http://www.mozilla.org/js/spidermonkey/tutorial.html) :

#define DOIT_MINARGS 2
static JSBool
doit_in_c(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval
*rval)
{
...
}

ok = JS_DefineFunction(cx, global, "doit", doit_in_c, DOIT_MINARGS,
0);

everything works fine and and I get doit_in_c executed when I call
doit(..) in JS. Now I have a lot of small functions with same params,
only name differs and I would like to do some code refactoring and
place all functions logic under the same c-handler. Is there any
opportunity to get functions java-script name defined as third
parameter in JS_DefineFunction from doit_in_c? Is java-script function
name placed somewhere in JSContext or JSObject? I have spent without
success a lot of time looking for it in a debugger..

Thanks for help!

bz
Mark Giffin
2011-05-26 20:26:04 UTC
Permalink
Hi,

SpiderMonkey embedding question. I'm on Windows XP using the Visual C++
2008 (a.k.a. version 9) command line compiler cl.exe to build a very
simple "hello world" embedded SpiderMonkey app. I am using the
MozillaBuild bash shell. I got it to compile without errors, but when I
run the .exe it gives an error and does not print "Hello world" like
it's supposed to. The error is:

Runtime Error!

Program: c:\js-1.8.5\js\src\hello-world.exe.

6034

An application has made an attempt to load the C runtime library incorrectly. Please contact the application's support team for more information.


I googled the error and it looks like a manifest needs to be made and
added to the .exe. Does anyone know if this is necessary, before I
figure out how to do it? My full source code is here:

https://developer.mozilla.org/User:Mark_Giffin/Sandbox

Thanks,
Mark
marco
2011-05-27 15:42:06 UTC
Permalink
Post by Dzianis Barzakouski
Hi All,
I have a simple app that uses SpiderMonkey for scripting purposes
#define DOIT_MINARGS 2
static JSBool
doit_in_c(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval
*rval)
{
 ...
}
ok = JS_DefineFunction(cx, global, "doit", doit_in_c, DOIT_MINARGS,
0);
everything works fine and and I get doit_in_c executed when I call
doit(..) in JS. Now I have a lot of small functions with same params,
only name differs and I would like to do some code refactoring and
place all functions logic under the same c-handler. Is there any
opportunity to get functions java-script name defined as third
parameter in JS_DefineFunction from doit_in_c? Is java-script function
name placed somewhere in JSContext or JSObject? I have spent without
success a lot of time looking for it in a debugger..
Thanks for help!
bz
Hey,

we ran into the exact same problem and solved it by essentially
storing the JS function's name in the JS context's private data. I
didn't do this myself, but here's the code :



/* But ensure that we have a scope chain. */
if (!frame.scopeChain)
frame.scopeChain = parent;


//
====================================================================================================
// our code begin
//
====================================================================================================

MyJavaScriptContextPrivateData* ctx_data =
(MyJavaScriptContextPrivateData*)JS_GetContextPrivate(cx);

if((ctx_data != NULL) && (ctx_data->m_magic == MY_JS_JSCP_MAGIC)) //
check
{
ctx_data->m_js_function_name = NULL;

if((fun != NULL) && (fun->atom != NULL))
{
// WARNING: this is a GC thing!!!
ctx_data->m_js_function_name = js_AtomToPrintableString(cx, fun-
Post by Dzianis Barzakouski
atom);
}
}

//
====================================================================================================
// our code end
//
====================================================================================================

ok = native(cx, frame.thisp, argc, frame.argv, &frame.rval);



This of course assumes that you allocated and set the context's
private data accordingly and that there's a field in there called
"m_js_function_name". When you're in your native C function, you can
then get the context's private data again and extract the function
name.
We use Spidermonkey 1.8.0. This code goes into jsinterp.c in
js_Invoke(), around line 1305. the "frame.scopeChain" check and
"native()" are from the original code, the stuff in between is ours.

This solution is far from perfect or elegant. The developer who
implemented this couldn't find any other way, but if anyone knows of a
better approach, I'd be very interested in it.

Cheers,

Marco
Wes Garland
2011-05-27 16:07:10 UTC
Permalink
IIRC argv[-2] holds a function object which is the invoking function. Can
you use that to get what you need? I bet you can.

Wes
Post by marco
Post by Dzianis Barzakouski
Hi All,
I have a simple app that uses SpiderMonkey for scripting purposes
( calls C functions from JS ). I do following (example fromhttp://
#define DOIT_MINARGS 2
static JSBool
doit_in_c(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval
*rval)
{
...
}
ok = JS_DefineFunction(cx, global, "doit", doit_in_c, DOIT_MINARGS,
0);
everything works fine and and I get doit_in_c executed when I call
doit(..) in JS. Now I have a lot of small functions with same params,
only name differs and I would like to do some code refactoring and
place all functions logic under the same c-handler. Is there any
opportunity to get functions java-script name defined as third
parameter in JS_DefineFunction from doit_in_c? Is java-script function
name placed somewhere in JSContext or JSObject? I have spent without
success a lot of time looking for it in a debugger..
Thanks for help!
bz
Hey,
we ran into the exact same problem and solved it by essentially
storing the JS function's name in the JS context's private data. I
/* But ensure that we have a scope chain. */
if (!frame.scopeChain)
frame.scopeChain = parent;
//
====================================================================================================
// our code begin
//
====================================================================================================
MyJavaScriptContextPrivateData* ctx_data =
(MyJavaScriptContextPrivateData*)JS_GetContextPrivate(cx);
if((ctx_data != NULL) && (ctx_data->m_magic == MY_JS_JSCP_MAGIC)) //
check
{
ctx_data->m_js_function_name = NULL;
if((fun != NULL) && (fun->atom != NULL))
{
// WARNING: this is a GC thing!!!
ctx_data->m_js_function_name = js_AtomToPrintableString(cx, fun-
Post by Dzianis Barzakouski
atom);
}
}
//
====================================================================================================
// our code end
//
====================================================================================================
ok = native(cx, frame.thisp, argc, frame.argv, &frame.rval);
This of course assumes that you allocated and set the context's
private data accordingly and that there's a field in there called
"m_js_function_name". When you're in your native C function, you can
then get the context's private data again and extract the function
name.
We use Spidermonkey 1.8.0. This code goes into jsinterp.c in
js_Invoke(), around line 1305. the "frame.scopeChain" check and
"native()" are from the original code, the stuff in between is ours.
This solution is far from perfect or elegant. The developer who
implemented this couldn't find any other way, but if anyone knows of a
better approach, I'd be very interested in it.
Cheers,
Marco
_______________________________________________
dev-tech-js-engine mailing list
https://lists.mozilla.org/listinfo/dev-tech-js-engine
--
Wesley W. Garland
Director, Product Development
PageMail, Inc.
+1 613 542 2787 x 102
marco
2011-05-27 16:25:05 UTC
Permalink
Post by Wes Garland
IIRC argv[-2] holds a function object which is the invoking function. Can
you use that to get what you need?  I bet you can.
Wes
Post by marco
Post by Dzianis Barzakouski
Hi All,
I have a simple app that uses SpiderMonkey for scripting purposes
( calls C functions from JS ). I do following (example fromhttp://
#define DOIT_MINARGS 2
static JSBool
doit_in_c(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval
*rval)
{
 ...
}
ok = JS_DefineFunction(cx, global, "doit", doit_in_c, DOIT_MINARGS,
0);
everything works fine and and I get doit_in_c executed when I call
doit(..) in JS. Now I have a lot of small functions with same params,
only name differs and I would like to do some code refactoring and
place all functions logic under the same c-handler. Is there any
opportunity to get functions java-script name defined as third
parameter in JS_DefineFunction from doit_in_c? Is java-script function
name placed somewhere in JSContext or JSObject? I have spent without
success a lot of time looking for it in a debugger..
Thanks for help!
bz
Hey,
we ran into the exact same problem and solved it by essentially
storing the JS function's name in the JS context's private data. I
/* But ensure that we have a scope chain. */
if (!frame.scopeChain)
       frame.scopeChain = parent;
//
=========================================================================== =========================
// our code begin
//
=========================================================================== =========================
MyJavaScriptContextPrivateData* ctx_data =
(MyJavaScriptContextPrivateData*)JS_GetContextPrivate(cx);
if((ctx_data != NULL) && (ctx_data->m_magic == MY_JS_JSCP_MAGIC))   //
check
{
       ctx_data->m_js_function_name = NULL;
       if((fun != NULL) && (fun->atom != NULL))
       {
               // WARNING: this is a GC thing!!!
               ctx_data->m_js_function_name = js_AtomToPrintableString(cx,
fun-
Post by Dzianis Barzakouski
atom);
       }
}
//
=========================================================================== =========================
// our code end
//
=========================================================================== =========================
ok = native(cx, frame.thisp, argc, frame.argv, &frame.rval);
This of course assumes that you allocated and set the context's
private data accordingly and that there's a field in there called
"m_js_function_name". When you're in your native C function, you can
then get the context's private data again and extract the function
name.
We use Spidermonkey 1.8.0. This code goes into jsinterp.c in
js_Invoke(), around line 1305. the "frame.scopeChain" check and
"native()" are from the original code, the stuff in between is ours.
This solution is far from perfect or elegant. The developer who
implemented this couldn't find any other way, but if anyone knows of a
better approach, I'd be very interested in it.
Cheers,
Marco
_______________________________________________
dev-tech-js-engine mailing list
https://lists.mozilla.org/listinfo/dev-tech-js-engine
--
Wesley W. Garland
Director, Product Development
PageMail, Inc.
+1 613 542 2787 x 102
Hey Wes,

you're right, the following seems to work:

JSFunction* function = (JSFunction*) JSVAL_TO_OBJECT(argv[-2]);
const char* functionName = js_AtomToPrintableString(context, function-
Post by Wes Garland
atom);
It just always seems so weird for me to use argv[-2]... Negative
indices aren't something that comes to my mind right away.
Is this "the official way (TM)" to do it? It just seems so strange
that there's no public API that does this.

Thanks for the help!

Cheers,

Marco
Nat
2011-05-30 04:10:30 UTC
Permalink
It does if you use v1.8 api, JS_CALLEE (https://developer.mozilla.org/en/JSFastNative)
Continue reading on narkive:
Loading...