1031: Add spidermonkey-shared.c used for both web and user scripts
[elinks.git] / src / scripting / smjs / core.c
blob60fe7ba01f29f92fc11f37a85d4198c627173e3c
1 /* ECMAScript browser scripting module */
3 #ifdef HAVE_CONFIG_H
4 #include "config.h"
5 #endif
7 #include "elinks.h"
9 #include "config/home.h"
10 #include "ecmascript/spidermonkey-shared.h"
11 #include "main/module.h"
12 #include "osdep/osdep.h"
13 #include "scripting/scripting.h"
14 #include "scripting/smjs/core.h"
15 #include "scripting/smjs/elinks_object.h"
16 #include "scripting/smjs/global_object.h"
17 #include "scripting/smjs/smjs.h"
18 #include "util/file.h"
19 #include "util/string.h"
22 #define SMJS_HOOKS_FILENAME "hooks.js"
24 JSContext *smjs_ctx;
25 JSObject *smjs_elinks_object;
26 struct session *smjs_ses;
29 void
30 alert_smjs_error(unsigned char *msg)
32 report_scripting_error(&smjs_scripting_module,
33 smjs_ses, msg);
36 static void
37 error_reporter(JSContext *ctx, const char *message, JSErrorReport *report)
39 unsigned char *strict, *exception, *warning, *error;
40 struct string msg;
42 if (!init_string(&msg)) goto reported;
44 strict = JSREPORT_IS_STRICT(report->flags) ? " strict" : "";
45 exception = JSREPORT_IS_EXCEPTION(report->flags) ? " exception" : "";
46 warning = JSREPORT_IS_WARNING(report->flags) ? " warning" : "";
47 error = !report->flags ? " error" : "";
49 add_format_to_string(&msg, "A client script raised the following%s%s%s%s",
50 strict, exception, warning, error);
52 add_to_string(&msg, ":\n\n");
53 add_to_string(&msg, message);
55 if (report->linebuf && report->tokenptr) {
56 int pos = report->tokenptr - report->linebuf;
58 add_format_to_string(&msg, "\n\n%s\n.%*s^%*s.",
59 report->linebuf,
60 pos - 2, " ",
61 strlen(report->linebuf) - pos - 1, " ");
64 alert_smjs_error(msg.source);
65 done_string(&msg);
67 reported:
68 JS_ClearPendingException(ctx);
71 static JSRuntime *smjs_rt;
73 static int
74 smjs_do_file(unsigned char *path)
76 int ret = 1;
77 jsval rval;
78 struct string script;
80 if (!init_string(&script)) return 0;
82 if (!add_file_to_string(&script, path)
83 || JS_FALSE == JS_EvaluateScript(smjs_ctx,
84 JS_GetGlobalObject(smjs_ctx),
85 script.source, script.length, path, 1, &rval)) {
86 alert_smjs_error("error loading script file");
87 ret = 0;
90 done_string(&script);
92 return ret;
95 static JSBool
96 smjs_do_file_wrapper(JSContext *ctx, JSObject *obj, uintN argc,
97 jsval *argv, jsval *rval)
99 JSString *jsstr = JS_ValueToString(smjs_ctx, *argv);
100 unsigned char *path = JS_GetStringBytes(jsstr);
102 if (smjs_do_file(path))
103 return JS_TRUE;
105 return JS_FALSE;
108 static void
109 smjs_load_hooks(void)
111 unsigned char *path;
113 assert(smjs_ctx);
115 if (elinks_home) {
116 path = straconcat(elinks_home, SMJS_HOOKS_FILENAME,
117 (unsigned char *) NULL);
118 } else {
119 path = stracpy(CONFDIR STRING_DIR_SEP SMJS_HOOKS_FILENAME);
122 if (file_exists(path))
123 smjs_do_file(path);
124 mem_free(path);
127 void
128 init_smjs(struct module *module)
130 smjs_rt = JS_NewRuntime(1L * 1024L * 1024L);
131 if (!smjs_rt) return;
133 smjs_ctx = JS_NewContext(smjs_rt, 8192);
134 if (!smjs_ctx) {
135 JS_DestroyRuntime(smjs_rt);
136 smjs_rt = NULL;
137 return;
140 JS_SetErrorReporter(smjs_ctx, error_reporter);
142 smjs_init_global_object();
144 smjs_init_elinks_object();
146 JS_DefineFunction(smjs_ctx, smjs_global_object, "do_file",
147 &smjs_do_file_wrapper, 1, 0);
149 smjs_load_hooks();
152 void
153 cleanup_smjs(struct module *module)
155 if (!smjs_ctx) return;
157 /* These calls also finalize all JSObjects that have been
158 * allocated in the JSRuntime, so cache_entry_finalize gets
159 * called and resets each cache_entry.jsobject = NULL. */
160 JS_DestroyContext(smjs_ctx);
161 JS_DestroyRuntime(smjs_rt);