1 /** SpiderMonkey support for both user scripts and web scripts.
10 #include "ecmascript/spidermonkey-shared.h"
12 /** A shared runtime used for both user scripts (scripting/smjs/) and
13 * scripts on web pages (ecmascript/spidermonkey/).
15 * SpiderMonkey has bugs that corrupt memory when multiple JSRuntimes
16 * are used: https://bugzilla.mozilla.org/show_bug.cgi?id=378918 and
18 JSRuntime
*spidermonkey_runtime
;
20 /** A JSContext that can be used in JS_SetPrivate and JS_GetPrivate
21 * when no better one is available. This context has no global
22 * object, so scripts cannot be evaluated in it.
24 * XXX: This also works around a crash on exit. SMJS will crash on
25 * JS_DestroyRuntime if the given runtime has never had any context
26 * created, which will be the case if one closes ELinks without having
27 * loaded any documents. */
28 JSContext
*spidermonkey_empty_context
;
30 /** A reference count for ::spidermonkey_runtime so that modules using
31 * it can be initialized and shut down in arbitrary order. */
32 static int spidermonkey_runtime_refcount
;
34 /** Initialize ::spidermonkey_runtime and ::spidermonkey_empty_context.
35 * If already initialized, just increment the reference count.
37 * @return 1 if successful or 0 on error. If this succeeds, the
38 * caller must eventually call spidermonkey_runtime_release(). */
40 spidermonkey_runtime_addref(void)
42 if (spidermonkey_runtime_refcount
== 0) {
43 assert(spidermonkey_runtime
== NULL
);
44 assert(spidermonkey_empty_context
== NULL
);
45 if_assert_failed
return 0;
47 spidermonkey_runtime
= JS_NewRuntime(4L * 1024L * 1024L);
48 if (!spidermonkey_runtime
) return 0;
50 spidermonkey_empty_context
= JS_NewContext(spidermonkey_runtime
,
52 if (!spidermonkey_empty_context
) {
53 /* Perhaps JS_DestroyRuntime will now crash
54 * because no context was created, but there's
55 * not much else to do. */
56 JS_DestroyRuntime(spidermonkey_runtime
);
57 spidermonkey_runtime
= NULL
;
62 assert(spidermonkey_runtime
);
63 assert(spidermonkey_empty_context
);
64 spidermonkey_runtime_refcount
++;
65 assert(spidermonkey_runtime_refcount
> 0);
66 if_assert_failed
{ spidermonkey_runtime_refcount
--; return 0; }
70 /** Release a reference to ::spidermonkey_runtime, and destroy it if
71 * that was the last reference. If spidermonkey_runtime_addref()
72 * failed, then this must not be called. */
74 spidermonkey_runtime_release(void)
76 assert(spidermonkey_runtime_refcount
> 0);
77 assert(spidermonkey_runtime
);
78 assert(spidermonkey_empty_context
);
79 if_assert_failed
return;
81 --spidermonkey_runtime_refcount
;
82 if (spidermonkey_runtime_refcount
== 0) {
83 JS_DestroyContext(spidermonkey_empty_context
);
84 spidermonkey_empty_context
= NULL
;
85 JS_DestroyRuntime(spidermonkey_runtime
);
86 spidermonkey_runtime
= NULL
;
91 /** An ELinks-specific replacement for JS_DefineFunctions().
93 * @relates spidermonkeyFunctionSpec */
95 spidermonkey_DefineFunctions(JSContext
*cx
, JSObject
*obj
,
96 const spidermonkeyFunctionSpec
*fs
)
98 for (; fs
->name
; fs
++) {
99 if (!JS_DefineFunction(cx
, obj
, fs
->name
, fs
->call
,
106 /** An ELinks-specific replacement for JS_InitClass().
108 * @relates spidermonkeyFunctionSpec */
110 spidermonkey_InitClass(JSContext
*cx
, JSObject
*obj
,
111 JSObject
*parent_proto
, JSClass
*clasp
,
112 JSNative constructor
, uintN nargs
,
114 const spidermonkeyFunctionSpec
*fs
,
115 JSPropertySpec
*static_ps
,
116 const spidermonkeyFunctionSpec
*static_fs
)
118 JSObject
*proto
= JS_InitClass(cx
, obj
, parent_proto
, clasp
,
120 ps
, NULL
, static_ps
, NULL
);
126 if (!spidermonkey_DefineFunctions(cx
, proto
, fs
))
131 JSObject
*cons_obj
= JS_GetConstructor(cx
, proto
);
133 if (cons_obj
== NULL
)
135 if (!spidermonkey_DefineFunctions(cx
, cons_obj
, static_fs
))