Subject: | patch for detecting lib, plus a JS_THREADSAFE problem |
1) the patch Makefile.PL.diff allows my libmozjs to be detected (Ubuntu).
It does make a bit more changes that strictly necessary, so you might
decide to do it differently (I tried to make it more general, but...).
This let it compile from the `cpan` shell instead of dropping into
`look` and all that.
2) But, the tests don't all pass. In particular, the tests using
$js->array_by_path (00array.t, 06form2.t, 10elobj.t) fail mysteriously.
I isolated the reason! My libmozjs was compiled with JS_THREADSAFE,
while JavaScript::SpiderMonkey doesn't take this into account. I don't
blame it; the moz/spidermonkey devs are assholes for making an API
dependent on a compile option.
Here's the thing: I can't really give you a patch to fix it,
because I can't think of a "good" way to fix it. But here's a path
showing how to fix it. Inside `object_by_path' in SpiderMonkey.pm,
there's a call to JS_GetClass; that is the fatal call. If you look
in for example, js/docs/jsref.xml in the spidermonkey distribution,
it says
JSClass * JS_GetClass(JSObject *obj);
Alternative syntax when JS_THREADSAFE is defined in a multithreaded
environment:
JSClass * JS_GetClass(JSContext *cx, JSObject *obj)
.....
If your application runs in a multithreaded environment, define
<C>JS_THREADSAFE</C>, and pass
a thread context as the first argument to <C>JS_GetClass</C>.<P/>
so you have to have this patch to SpiderMonkey.pm:
-my $class = JavaScript::SpiderMonkey::JS_GetClass($newobj);
+my $class = JavaScript::SpiderMonkey::JS_GetClass($self->{context},
$newobj);
and in SpiderMonkey.xs:
JSClass *
-JS_GetClass(obj)
+JS_GetClass(cx, obj)
+ JSContext *cx
JSObject * obj
######################################################################
PREINIT:
JSClass *rc;
CODE:
{
- rc = JS_GetClass(obj);
+ rc = JS_GetClass(cx, obj);
And in fact, after making those changes, all the tests pass.
But it assumes I know that my libmozjs has been compiled
with JS_THREADSAFE! If I knew that, I could add an #if/#else/#endif
to the .xs, an if/else to the .pm, and something to Makefile.PL,
and it would be fine. But I don't see how to find this value
(I tried looking in `pkg-config firefox-js`, for example, and while it
gives the -DXP_UNIX flag, it for some reason leaves out
-DJS_THREADSAFE....),
other than maybe having Makefile.PL do a manual call to test which
function signature works in the particular library being used.
Another option might be to have a separate call, like
JS_GetClass_threadsafe, to do the "new" version with the context
as the first argument, then do an eval on JS_GetClass and
JS_GetClass_threadsafe from `object_by_path' and take whatever succeeds.
It still leaves it up to people using the API directly to have to
handle whether their library is threadsafe or not. Very ugly situation
that people who put out libraries should not put onto people....
Subject: | Makefile.PL.diff |
--- JavaScript-SpiderMonkey-0.17-sFbu8e/Makefile.PL 2006-07-28 11:30:08.000000000 +0200
+++ JavaScript-SpiderMonkey-0.17-RZp6mZ/Makefile.PL 2007-05-26 14:29:55.000000000 +0200
@@ -14,10 +14,10 @@
use ExtUtils::MakeMaker;
use Getopt::Long;
-# Get the right lib and include dirs for different platforms
+# Get the right lib and include dirs for different platforms,
+# determine library name and system-related defines
-my $JS_LIB_DIR;
-my @JS_INCL_DIRS;
+my ($JS_LIB_DIR, @JS_INCL_DIRS, $JS_LIB_NAME, $JS_DEFINE);
my @c_header_files = qw(
jsapi.h
@@ -25,6 +25,7 @@
);
my @possible_libraries = qw(
+ libmozjs.so
libjs.a
js32.dll
);
@@ -33,6 +34,7 @@
"../js/src/*" => "../js/src",
"/usr/lib" => "/usr/include",
"/usr/local/lib" => "/usr/local/include",
+ "/usr/lib/firefox" => "/usr/include/firefox",
);
foreach my $install_path(keys %possible_install_paths) {
@@ -55,6 +57,17 @@
if (scalar(@JS_INCL_DIRS) == scalar(@c_header_files)) {
$JS_LIB_DIR = $libfile;
$JS_LIB_DIR =~ s/$possible_lib$//;
+
+ $JS_LIB_NAME = $possible_lib;
+ $JS_LIB_NAME =~ s/\..*$//;
+ $JS_LIB_NAME =~ s/^lib//;
+
+ if ($^O ne 'MSWin32') {
+ $JS_DEFINE = '-DXP_UNIX -DJS_THREADSAFE';
+ } else {
+ $JS_DEFINE = '-DXP_WIN';
+ };
+
last;
} else {
@JS_INCL_DIRS = ();
@@ -89,19 +102,6 @@
}
}
-## Determine library name and system-related defines
-
-my $JS_LIB_NAME;
-my $JS_DEFINE;
-
-if ($^O ne 'MSWin32') {
- $JS_LIB_NAME = 'js';
- $JS_DEFINE = '-DXP_UNIX';
-} else {
- $JS_LIB_NAME = 'js32';
- $JS_DEFINE = '-DXP_WIN';
-};
-
my $E4X = 0;
GetOptions(
"E4X" => \$E4X,