2005-09-15 09:58:31 -04:00
|
|
|
/* The SpiderMonkey ECMAScript backend. */
|
|
|
|
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
|
|
#include "config.h"
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
|
|
|
|
|
|
|
#include "elinks.h"
|
|
|
|
|
|
|
|
#include "ecmascript/spidermonkey/util.h"
|
2020-10-23 16:34:58 -04:00
|
|
|
#include <jsprf.h>
|
2005-09-15 09:58:31 -04:00
|
|
|
|
|
|
|
#include "bfu/dialog.h"
|
|
|
|
#include "cache/cache.h"
|
2009-07-18 19:36:37 -04:00
|
|
|
#include "config/options.h"
|
2005-09-15 09:58:31 -04:00
|
|
|
#include "cookies/cookies.h"
|
|
|
|
#include "dialogs/menu.h"
|
|
|
|
#include "dialogs/status.h"
|
|
|
|
#include "document/html/frames.h"
|
|
|
|
#include "document/document.h"
|
|
|
|
#include "document/forms.h"
|
2021-06-11 11:23:27 -04:00
|
|
|
#include "document/renderer.h"
|
2005-09-15 09:58:31 -04:00
|
|
|
#include "document/view.h"
|
|
|
|
#include "ecmascript/ecmascript.h"
|
|
|
|
#include "ecmascript/spidermonkey.h"
|
2021-02-21 16:33:29 -05:00
|
|
|
#include "ecmascript/spidermonkey/console.h"
|
2005-09-15 09:58:31 -04:00
|
|
|
#include "ecmascript/spidermonkey/document.h"
|
|
|
|
#include "ecmascript/spidermonkey/form.h"
|
2009-07-18 19:41:01 -04:00
|
|
|
#include "ecmascript/spidermonkey/heartbeat.h"
|
2005-09-15 09:58:31 -04:00
|
|
|
#include "ecmascript/spidermonkey/location.h"
|
2021-02-22 17:27:19 -05:00
|
|
|
#include "ecmascript/spidermonkey/localstorage.h"
|
2005-09-15 09:58:31 -04:00
|
|
|
#include "ecmascript/spidermonkey/navigator.h"
|
2021-05-28 11:51:42 -04:00
|
|
|
#include "ecmascript/spidermonkey/screen.h"
|
2005-09-15 09:58:31 -04:00
|
|
|
#include "ecmascript/spidermonkey/unibar.h"
|
|
|
|
#include "ecmascript/spidermonkey/window.h"
|
|
|
|
#include "intl/gettext/libintl.h"
|
|
|
|
#include "main/select.h"
|
|
|
|
#include "osdep/newwin.h"
|
|
|
|
#include "osdep/sysname.h"
|
|
|
|
#include "protocol/http/http.h"
|
|
|
|
#include "protocol/uri.h"
|
|
|
|
#include "session/history.h"
|
|
|
|
#include "session/location.h"
|
|
|
|
#include "session/session.h"
|
|
|
|
#include "session/task.h"
|
|
|
|
#include "terminal/tab.h"
|
|
|
|
#include "terminal/terminal.h"
|
|
|
|
#include "util/conv.h"
|
|
|
|
#include "util/string.h"
|
|
|
|
#include "viewer/text/draw.h"
|
|
|
|
#include "viewer/text/form.h"
|
|
|
|
#include "viewer/text/link.h"
|
2021-06-05 15:58:29 -04:00
|
|
|
#include "viewer/text/view.h"
|
2005-09-15 09:58:31 -04:00
|
|
|
#include "viewer/text/vs.h"
|
|
|
|
|
2021-06-05 15:58:29 -04:00
|
|
|
#include <libxml++/libxml++.h>
|
|
|
|
|
2005-09-15 09:58:31 -04:00
|
|
|
/*** Global methods */
|
|
|
|
|
|
|
|
|
|
|
|
/* TODO? Are there any which need to be implemented? */
|
|
|
|
|
2008-07-16 07:50:41 -04:00
|
|
|
static int js_module_init_ok;
|
2005-09-15 09:58:31 -04:00
|
|
|
|
2020-10-27 09:53:24 -04:00
|
|
|
bool
|
|
|
|
PrintError(JSContext* cx, FILE* file, JS::ConstUTF8CharsZ toStringResult,
|
|
|
|
JSErrorReport* report, bool reportWarnings)
|
|
|
|
{
|
|
|
|
MOZ_ASSERT(report);
|
|
|
|
|
|
|
|
/* Conditionally ignore reported warnings. */
|
|
|
|
if (JSREPORT_IS_WARNING(report->flags) && !reportWarnings)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
char* prefix = nullptr;
|
|
|
|
if (report->filename)
|
|
|
|
prefix = JS_smprintf("%s:", report->filename);
|
|
|
|
if (report->lineno) {
|
|
|
|
char* tmp = prefix;
|
|
|
|
prefix = JS_smprintf("%s%u:%u ", tmp ? tmp : "", report->lineno, report->column);
|
|
|
|
JS_free(cx, tmp);
|
|
|
|
}
|
|
|
|
if (JSREPORT_IS_WARNING(report->flags)) {
|
|
|
|
char* tmp = prefix;
|
|
|
|
prefix = JS_smprintf("%s%swarning: ",
|
|
|
|
tmp ? tmp : "",
|
|
|
|
JSREPORT_IS_STRICT(report->flags) ? "strict " : "");
|
|
|
|
JS_free(cx, tmp);
|
|
|
|
}
|
|
|
|
|
|
|
|
const char* message = toStringResult ? toStringResult.c_str() : report->message().c_str();
|
|
|
|
|
|
|
|
/* embedded newlines -- argh! */
|
|
|
|
const char* ctmp;
|
|
|
|
while ((ctmp = strchr(message, '\n')) != 0) {
|
|
|
|
ctmp++;
|
|
|
|
if (prefix)
|
|
|
|
fputs(prefix, file);
|
|
|
|
fwrite(message, 1, ctmp - message, file);
|
|
|
|
message = ctmp;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* If there were no filename or lineno, the prefix might be empty */
|
|
|
|
if (prefix)
|
|
|
|
fputs(prefix, file);
|
|
|
|
fputs(message, file);
|
|
|
|
|
|
|
|
if (const char16_t* linebuf = report->linebuf()) {
|
|
|
|
size_t n = report->linebufLength();
|
|
|
|
|
|
|
|
fputs(":\n", file);
|
|
|
|
if (prefix)
|
|
|
|
fputs(prefix, file);
|
|
|
|
|
|
|
|
for (size_t i = 0; i < n; i++)
|
|
|
|
fputc(static_cast<char>(linebuf[i]), file);
|
|
|
|
|
|
|
|
// linebuf usually ends with a newline. If not, add one here.
|
|
|
|
if (n == 0 || linebuf[n-1] != '\n')
|
|
|
|
fputc('\n', file);
|
|
|
|
|
|
|
|
if (prefix)
|
|
|
|
fputs(prefix, file);
|
|
|
|
|
|
|
|
n = report->tokenOffset();
|
|
|
|
for (size_t i = 0, j = 0; i < n; i++) {
|
|
|
|
if (linebuf[i] == '\t') {
|
|
|
|
for (size_t k = (j + 8) & ~7; j < k; j++)
|
|
|
|
fputc('.', file);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
fputc('.', file);
|
|
|
|
j++;
|
|
|
|
}
|
|
|
|
fputc('^', file);
|
|
|
|
}
|
|
|
|
fputc('\n', file);
|
|
|
|
fflush(file);
|
|
|
|
JS_free(cx, prefix);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2009-02-26 15:56:33 -05:00
|
|
|
static void
|
2020-10-27 09:53:24 -04:00
|
|
|
error_reporter(JSContext *ctx, JSErrorReport *report)
|
2005-09-15 09:58:31 -04:00
|
|
|
{
|
2020-10-28 17:32:20 -04:00
|
|
|
JSCompartment *comp = js::GetContextCompartment(ctx);
|
|
|
|
|
|
|
|
if (!comp) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
struct ecmascript_interpreter *interpreter = JS_GetCompartmentPrivate(comp);
|
2007-08-30 17:11:51 -04:00
|
|
|
struct session *ses = interpreter->vs->doc_view->session;
|
2005-09-15 09:58:31 -04:00
|
|
|
struct terminal *term;
|
2021-01-02 10:20:27 -05:00
|
|
|
char *strict, *exception, *warning, *error;
|
2019-04-21 06:27:40 -04:00
|
|
|
struct string msg;
|
2021-02-24 03:56:06 -05:00
|
|
|
char str_lineno[256]="";
|
2005-09-15 09:58:31 -04:00
|
|
|
|
2020-10-23 16:34:58 -04:00
|
|
|
char *prefix = nullptr;
|
|
|
|
|
2005-09-15 09:58:31 -04:00
|
|
|
assert(interpreter && interpreter->vs && interpreter->vs->doc_view
|
2007-08-30 17:11:51 -04:00
|
|
|
&& ses && ses->tab);
|
2005-09-15 09:58:31 -04:00
|
|
|
if_assert_failed goto reported;
|
|
|
|
|
2007-08-30 17:11:51 -04:00
|
|
|
term = ses->tab->term;
|
2005-09-15 09:58:31 -04:00
|
|
|
|
|
|
|
#ifdef CONFIG_LEDS
|
2007-08-30 17:11:51 -04:00
|
|
|
set_led_value(ses->status.ecmascript_led, 'J');
|
2005-09-15 09:58:31 -04:00
|
|
|
#endif
|
|
|
|
|
2007-08-30 17:11:51 -04:00
|
|
|
if (!get_opt_bool("ecmascript.error_reporting", ses)
|
2005-09-15 09:58:31 -04:00
|
|
|
|| !init_string(&msg))
|
|
|
|
goto reported;
|
|
|
|
|
|
|
|
strict = JSREPORT_IS_STRICT(report->flags) ? " strict" : "";
|
|
|
|
exception = JSREPORT_IS_EXCEPTION(report->flags) ? " exception" : "";
|
|
|
|
warning = JSREPORT_IS_WARNING(report->flags) ? " warning" : "";
|
|
|
|
error = !report->flags ? " error" : "";
|
|
|
|
|
|
|
|
add_format_to_string(&msg, _("A script embedded in the current "
|
|
|
|
"document raised the following%s%s%s%s", term),
|
|
|
|
strict, exception, warning, error);
|
|
|
|
|
2021-02-22 11:26:45 -05:00
|
|
|
/* Report message and line number of SpiderMonkey error */
|
|
|
|
/* Sometimes the line number is zero */
|
|
|
|
add_to_string(&msg, "\n\n");
|
2020-11-23 12:06:17 -05:00
|
|
|
add_to_string(&msg, report->message().c_str());
|
2021-02-22 11:26:45 -05:00
|
|
|
sprintf(str_lineno,"\n at line: %d",report->lineno);
|
|
|
|
add_to_string(&msg, str_lineno);
|
2005-09-15 09:58:31 -04:00
|
|
|
|
|
|
|
info_box(term, MSGBOX_FREE_TEXT, N_("JavaScript Error"), ALIGN_CENTER,
|
|
|
|
msg.source);
|
|
|
|
|
|
|
|
reported:
|
|
|
|
/* Im clu'les. --pasky */
|
|
|
|
JS_ClearPendingException(ctx);
|
|
|
|
}
|
|
|
|
|
2006-02-26 03:51:36 -05:00
|
|
|
static void
|
|
|
|
spidermonkey_init(struct module *xxx)
|
2005-09-15 09:58:31 -04:00
|
|
|
{
|
2008-07-16 07:50:41 -04:00
|
|
|
js_module_init_ok = spidermonkey_runtime_addref();
|
2005-09-15 09:58:31 -04:00
|
|
|
}
|
|
|
|
|
2006-02-26 03:51:36 -05:00
|
|
|
static void
|
|
|
|
spidermonkey_done(struct module *xxx)
|
2005-09-15 09:58:31 -04:00
|
|
|
{
|
2008-07-16 07:50:41 -04:00
|
|
|
if (js_module_init_ok)
|
|
|
|
spidermonkey_runtime_release();
|
2005-09-15 09:58:31 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void *
|
|
|
|
spidermonkey_get_interpreter(struct ecmascript_interpreter *interpreter)
|
|
|
|
{
|
|
|
|
JSContext *ctx;
|
2021-05-23 12:34:33 -04:00
|
|
|
JSObject *console_obj, *document_obj, /* *forms_obj,*/ *history_obj, *location_obj,
|
2021-05-28 11:51:42 -04:00
|
|
|
*statusbar_obj, *menubar_obj, *navigator_obj, *localstorage_obj, *screen_obj;
|
2005-09-15 09:58:31 -04:00
|
|
|
|
2020-10-28 17:32:20 -04:00
|
|
|
static int initialized = 0;
|
|
|
|
|
2005-09-15 09:58:31 -04:00
|
|
|
assert(interpreter);
|
2008-07-16 07:50:41 -04:00
|
|
|
if (!js_module_init_ok) return NULL;
|
2005-09-15 09:58:31 -04:00
|
|
|
|
2020-10-28 17:32:20 -04:00
|
|
|
ctx = main_ctx;
|
|
|
|
|
|
|
|
if (!ctx) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2005-09-15 09:58:31 -04:00
|
|
|
interpreter->backend_data = ctx;
|
2020-10-28 17:32:20 -04:00
|
|
|
interpreter->ar = new JSAutoRequest(ctx);
|
2021-02-22 11:26:45 -05:00
|
|
|
// JSAutoRequest ar(ctx);
|
2020-10-28 17:32:20 -04:00
|
|
|
|
2021-02-22 11:26:45 -05:00
|
|
|
// JS_SetContextPrivate(ctx, interpreter);
|
|
|
|
|
|
|
|
// JS_SetOptions(main_ctx, JSOPTION_VAROBJFIX | JS_METHODJIT);
|
|
|
|
/* This is obsolete since mozjs52 */
|
|
|
|
//JS::SetWarningReporter(ctx, error_reporter);
|
2020-10-28 17:32:20 -04:00
|
|
|
|
2020-10-27 09:53:24 -04:00
|
|
|
JS_AddInterruptCallback(ctx, heartbeat_callback);
|
|
|
|
JS::CompartmentOptions options;
|
|
|
|
|
|
|
|
JS::RootedObject window_obj(ctx, JS_NewGlobalObject(ctx, &window_class, NULL, JS::FireOnNewGlobalHook, options));
|
2019-02-10 15:00:37 -05:00
|
|
|
|
2020-10-05 14:14:55 -04:00
|
|
|
if (window_obj) {
|
2020-11-16 16:00:48 -05:00
|
|
|
interpreter->ac = window_obj;
|
|
|
|
interpreter->ac2 = new JSAutoCompartment(ctx, window_obj);
|
2020-10-05 14:14:55 -04:00
|
|
|
} else {
|
|
|
|
goto release_and_fail;
|
|
|
|
}
|
2019-02-10 15:00:37 -05:00
|
|
|
|
|
|
|
if (!JS_InitStandardClasses(ctx, window_obj)) {
|
2009-06-27 12:48:56 -04:00
|
|
|
goto release_and_fail;
|
2019-02-10 15:00:37 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
if (!JS_DefineProperties(ctx, window_obj, window_props)) {
|
2009-06-27 12:48:56 -04:00
|
|
|
goto release_and_fail;
|
2019-02-10 15:00:37 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
if (!spidermonkey_DefineFunctions(ctx, window_obj, window_funcs)) {
|
2009-06-27 12:48:56 -04:00
|
|
|
goto release_and_fail;
|
2019-02-10 15:00:37 -05:00
|
|
|
}
|
2020-11-16 16:00:48 -05:00
|
|
|
//JS_SetPrivate(window_obj, interpreter); /* to @window_class */
|
2005-09-15 09:58:31 -04:00
|
|
|
|
2008-06-16 17:25:59 -04:00
|
|
|
document_obj = spidermonkey_InitClass(ctx, window_obj, NULL,
|
2019-02-10 15:00:37 -05:00
|
|
|
&document_class, NULL, 0,
|
|
|
|
document_props,
|
2008-06-16 17:25:59 -04:00
|
|
|
document_funcs,
|
|
|
|
NULL, NULL);
|
2019-02-10 15:00:37 -05:00
|
|
|
if (!document_obj) {
|
|
|
|
goto release_and_fail;
|
|
|
|
}
|
2008-06-16 17:25:59 -04:00
|
|
|
|
2021-05-19 13:05:03 -04:00
|
|
|
interpreter->document_obj = document_obj;
|
|
|
|
|
2021-05-23 12:34:33 -04:00
|
|
|
/*
|
2008-06-16 17:25:59 -04:00
|
|
|
forms_obj = spidermonkey_InitClass(ctx, document_obj, NULL,
|
2019-02-10 15:00:37 -05:00
|
|
|
&forms_class, NULL, 0,
|
|
|
|
forms_props,
|
2008-06-16 17:25:59 -04:00
|
|
|
forms_funcs,
|
|
|
|
NULL, NULL);
|
2019-02-10 15:00:37 -05:00
|
|
|
if (!forms_obj) {
|
|
|
|
goto release_and_fail;
|
|
|
|
}
|
2021-05-23 12:34:33 -04:00
|
|
|
*/
|
2008-06-16 17:25:59 -04:00
|
|
|
|
|
|
|
history_obj = spidermonkey_InitClass(ctx, window_obj, NULL,
|
2019-02-10 15:00:37 -05:00
|
|
|
&history_class, NULL, 0,
|
2008-06-16 17:25:59 -04:00
|
|
|
(JSPropertySpec *) NULL,
|
|
|
|
history_funcs,
|
|
|
|
NULL, NULL);
|
2019-02-10 15:00:37 -05:00
|
|
|
if (!history_obj) {
|
|
|
|
goto release_and_fail;
|
|
|
|
}
|
2008-06-16 17:25:59 -04:00
|
|
|
|
|
|
|
location_obj = spidermonkey_InitClass(ctx, window_obj, NULL,
|
2019-02-10 15:00:37 -05:00
|
|
|
&location_class, NULL, 0,
|
|
|
|
location_props,
|
2008-06-16 17:25:59 -04:00
|
|
|
location_funcs,
|
|
|
|
NULL, NULL);
|
2019-02-10 15:00:37 -05:00
|
|
|
if (!location_obj) {
|
|
|
|
goto release_and_fail;
|
|
|
|
}
|
2005-09-15 09:58:31 -04:00
|
|
|
|
2021-05-28 11:51:42 -04:00
|
|
|
screen_obj = spidermonkey_InitClass(ctx, window_obj, NULL,
|
|
|
|
&screen_class, NULL, 0,
|
|
|
|
screen_props,
|
|
|
|
NULL,
|
|
|
|
NULL, NULL);
|
|
|
|
|
|
|
|
if (!screen_obj) {
|
|
|
|
goto release_and_fail;
|
|
|
|
}
|
|
|
|
|
2020-10-23 16:34:58 -04:00
|
|
|
menubar_obj = JS_InitClass(ctx, window_obj, nullptr,
|
2019-02-10 15:00:37 -05:00
|
|
|
&menubar_class, NULL, 0,
|
|
|
|
unibar_props, NULL,
|
2005-09-15 09:58:31 -04:00
|
|
|
NULL, NULL);
|
2019-02-10 15:00:37 -05:00
|
|
|
if (!menubar_obj) {
|
2009-06-27 12:48:56 -04:00
|
|
|
goto release_and_fail;
|
2019-02-10 15:00:37 -05:00
|
|
|
}
|
|
|
|
JS_SetPrivate(menubar_obj, "t"); /* to @menubar_class */
|
2005-09-15 09:58:31 -04:00
|
|
|
|
2020-10-23 16:34:58 -04:00
|
|
|
statusbar_obj = JS_InitClass(ctx, window_obj, nullptr,
|
2019-02-10 15:00:37 -05:00
|
|
|
&statusbar_class, NULL, 0,
|
|
|
|
unibar_props, NULL,
|
2005-09-15 09:58:31 -04:00
|
|
|
NULL, NULL);
|
2019-02-10 15:00:37 -05:00
|
|
|
if (!statusbar_obj) {
|
2009-06-27 12:48:56 -04:00
|
|
|
goto release_and_fail;
|
2019-02-10 15:00:37 -05:00
|
|
|
}
|
|
|
|
JS_SetPrivate(statusbar_obj, "s"); /* to @statusbar_class */
|
2005-09-15 09:58:31 -04:00
|
|
|
|
2020-10-23 16:34:58 -04:00
|
|
|
navigator_obj = JS_InitClass(ctx, window_obj, nullptr,
|
2019-02-10 15:00:37 -05:00
|
|
|
&navigator_class, NULL, 0,
|
|
|
|
navigator_props, NULL,
|
2005-09-15 09:58:31 -04:00
|
|
|
NULL, NULL);
|
2019-02-10 15:00:37 -05:00
|
|
|
if (!navigator_obj) {
|
|
|
|
goto release_and_fail;
|
|
|
|
}
|
2021-02-21 16:33:29 -05:00
|
|
|
|
|
|
|
console_obj = spidermonkey_InitClass(ctx, window_obj, NULL,
|
|
|
|
&console_class, NULL, 0,
|
|
|
|
console_props,
|
|
|
|
console_funcs,
|
|
|
|
NULL, NULL);
|
|
|
|
if (!console_obj) {
|
|
|
|
goto release_and_fail;
|
|
|
|
}
|
|
|
|
|
2021-02-22 17:27:19 -05:00
|
|
|
localstorage_obj = spidermonkey_InitClass(ctx, window_obj, NULL,
|
|
|
|
&localstorage_class, NULL, 0,
|
|
|
|
localstorage_props,
|
|
|
|
localstorage_funcs,
|
|
|
|
NULL, NULL);
|
|
|
|
if (!localstorage_obj) {
|
|
|
|
goto release_and_fail;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2020-10-28 17:32:20 -04:00
|
|
|
JS_SetCompartmentPrivate(js::GetContextCompartment(ctx), interpreter);
|
|
|
|
|
2005-09-15 09:58:31 -04:00
|
|
|
return ctx;
|
2009-06-27 12:48:56 -04:00
|
|
|
|
|
|
|
release_and_fail:
|
|
|
|
spidermonkey_put_interpreter(interpreter);
|
|
|
|
return NULL;
|
2005-09-15 09:58:31 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
spidermonkey_put_interpreter(struct ecmascript_interpreter *interpreter)
|
|
|
|
{
|
|
|
|
JSContext *ctx;
|
|
|
|
|
|
|
|
assert(interpreter);
|
2008-07-16 07:50:41 -04:00
|
|
|
if (!js_module_init_ok) return;
|
2020-10-28 17:32:20 -04:00
|
|
|
|
2005-09-15 09:58:31 -04:00
|
|
|
ctx = interpreter->backend_data;
|
2020-11-27 11:21:11 -05:00
|
|
|
if (interpreter->ac2) {
|
|
|
|
delete (JSAutoCompartment *)interpreter->ac2;
|
2020-10-27 09:53:24 -04:00
|
|
|
}
|
2020-10-28 17:32:20 -04:00
|
|
|
if (interpreter->ar) {
|
|
|
|
delete (JSAutoRequest *)interpreter->ar;
|
|
|
|
}
|
|
|
|
// JS_DestroyContext(ctx);
|
2005-09-15 09:58:31 -04:00
|
|
|
interpreter->backend_data = NULL;
|
2020-10-27 09:53:24 -04:00
|
|
|
interpreter->ac = nullptr;
|
2020-11-27 11:21:11 -05:00
|
|
|
interpreter->ac2 = nullptr;
|
2020-10-28 17:32:20 -04:00
|
|
|
interpreter->ar = nullptr;
|
2005-09-15 09:58:31 -04:00
|
|
|
}
|
|
|
|
|
2021-02-22 11:26:45 -05:00
|
|
|
void
|
|
|
|
spidermonkey_check_for_exception(JSContext *ctx) {
|
|
|
|
if (JS_IsExceptionPending(ctx))
|
|
|
|
{
|
|
|
|
JS::RootedValue exception(ctx);
|
|
|
|
if(JS_GetPendingException(ctx,&exception) && exception.isObject()) {
|
|
|
|
JS::AutoSaveExceptionState savedExc(ctx);
|
|
|
|
JS::Rooted<JSObject*> exceptionObject(ctx, &exception.toObject());
|
|
|
|
JSErrorReport *report = JS_ErrorFromException(ctx,exceptionObject);
|
|
|
|
if(report) {
|
|
|
|
if (report->lineno>0) {
|
|
|
|
/* Somehow the reporter alway reports first error
|
|
|
|
* Undefined and with line 0. Let's filter this. */
|
|
|
|
/* Optional printing javascript error to file */
|
|
|
|
//FILE *f = fopen("js.err","a");
|
|
|
|
//PrintError(ctx, f, report->message(), report, true);
|
|
|
|
/* Send the error to the tui */
|
|
|
|
error_reporter(ctx, report);
|
|
|
|
//DBG("file: %s",report->filename);
|
|
|
|
//DBG("file: %s",report->message());
|
|
|
|
//DBG("file: %d",(int) report->lineno);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
//JS_ClearPendingException(ctx);
|
|
|
|
}
|
2021-02-24 05:23:34 -05:00
|
|
|
/* This absorbs all following exceptions
|
|
|
|
* probably not the 100% correct solution
|
|
|
|
* to the javascript error handling but
|
|
|
|
* at least there isn't too much click-bait
|
|
|
|
* on each site with javascript enabled */
|
|
|
|
JS_ClearPendingException(ctx);
|
2021-02-22 11:26:45 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2021-06-10 09:01:15 -04:00
|
|
|
void
|
|
|
|
free_document(void *doc)
|
|
|
|
{
|
|
|
|
if (!doc) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
xmlpp::Document *docu = doc;
|
|
|
|
delete docu;
|
|
|
|
}
|
|
|
|
|
2021-06-05 15:58:29 -04:00
|
|
|
static void
|
|
|
|
delayed_reload(void *data)
|
|
|
|
{
|
|
|
|
struct delayed_rel *rel = data;
|
|
|
|
|
|
|
|
assert(rel);
|
|
|
|
doc_rerender_after_document_update(rel->ses);
|
2021-06-10 09:01:15 -04:00
|
|
|
free_document(rel->doc);
|
2021-06-05 15:58:29 -04:00
|
|
|
mem_free(rel);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2021-06-11 11:23:27 -04:00
|
|
|
check_for_rerender(struct ecmascript_interpreter *interpreter, const char* text)
|
2021-06-05 15:58:29 -04:00
|
|
|
{
|
|
|
|
if (interpreter->changed) {
|
|
|
|
struct document_view *doc_view = interpreter->vs->doc_view;
|
|
|
|
struct document *document = doc_view->document;
|
|
|
|
struct session *ses = doc_view->session;
|
|
|
|
struct cache_entry *cached = document->cached;
|
|
|
|
struct fragment *f = get_cache_fragment(cached);
|
|
|
|
|
2021-06-11 11:23:27 -04:00
|
|
|
//fprintf(stderr, "%s\n", text);
|
|
|
|
|
2021-06-05 15:58:29 -04:00
|
|
|
if (document->dom && f && f->length) {
|
|
|
|
xmlpp::Document *docu = (xmlpp::Document *)document->dom;
|
|
|
|
std::string doc1_string = docu->write_to_string_formatted();
|
|
|
|
//delete docu;
|
|
|
|
document->dom = NULL;
|
|
|
|
|
|
|
|
size_t fd_len=f->length;
|
|
|
|
delete_entry_content(cached);
|
|
|
|
/* This is very ugly, indeed. And Yes fd_len isn't
|
|
|
|
* logically correct. But using nu_len will cause
|
|
|
|
* the document to render improperly.
|
|
|
|
* TBD: somehow better rerender the document
|
|
|
|
* now it's places on the session level in doc_loading_callback */
|
|
|
|
int ret = add_fragment(cached, 0, doc1_string.c_str(), doc1_string.size());
|
|
|
|
normalize_cache_entry(cached, doc1_string.size());
|
|
|
|
document->ecmascript_counter++;
|
|
|
|
interpreter->changed = false;
|
|
|
|
|
|
|
|
struct delayed_rel *rel = mem_calloc(1, sizeof(*rel));
|
|
|
|
|
|
|
|
if (rel) {
|
|
|
|
rel->ses = ses;
|
2021-06-06 09:23:21 -04:00
|
|
|
rel->doc = docu;
|
2021-06-05 15:58:29 -04:00
|
|
|
register_bottom_half(delayed_reload, rel);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2005-09-15 09:58:31 -04:00
|
|
|
|
|
|
|
void
|
|
|
|
spidermonkey_eval(struct ecmascript_interpreter *interpreter,
|
2019-04-21 06:27:40 -04:00
|
|
|
struct string *code, struct string *ret)
|
2005-09-15 09:58:31 -04:00
|
|
|
{
|
|
|
|
JSContext *ctx;
|
2020-10-23 16:34:58 -04:00
|
|
|
JS::Value rval;
|
2005-09-15 09:58:31 -04:00
|
|
|
|
|
|
|
assert(interpreter);
|
2019-02-10 15:00:37 -05:00
|
|
|
if (!js_module_init_ok) {
|
|
|
|
return;
|
|
|
|
}
|
2005-09-15 09:58:31 -04:00
|
|
|
ctx = interpreter->backend_data;
|
2020-11-16 16:00:48 -05:00
|
|
|
JS_BeginRequest(ctx);
|
|
|
|
JSCompartment *comp = JS_EnterCompartment(ctx, interpreter->ac);
|
2019-02-10 15:00:37 -05:00
|
|
|
|
2009-07-18 19:41:01 -04:00
|
|
|
interpreter->heartbeat = add_heartbeat(interpreter);
|
2006-01-27 06:07:45 -05:00
|
|
|
interpreter->ret = ret;
|
2019-02-10 15:00:37 -05:00
|
|
|
|
2020-10-11 09:41:27 -04:00
|
|
|
JS::RootedObject cg(ctx, JS::CurrentGlobalOrNull(ctx));
|
|
|
|
JS::RootedValue r_val(ctx, rval);
|
2020-10-16 13:54:02 -04:00
|
|
|
JS::CompileOptions options(ctx);
|
2020-10-11 09:41:27 -04:00
|
|
|
|
2020-10-23 16:34:58 -04:00
|
|
|
JS::Evaluate(ctx, options, code->source, code->length, &r_val);
|
2021-02-22 11:26:45 -05:00
|
|
|
|
|
|
|
spidermonkey_check_for_exception(ctx);
|
|
|
|
|
2009-07-18 19:41:01 -04:00
|
|
|
done_heartbeat(interpreter->heartbeat);
|
2020-11-16 16:00:48 -05:00
|
|
|
JS_LeaveCompartment(ctx, comp);
|
|
|
|
JS_EndRequest(ctx);
|
2021-06-05 15:58:29 -04:00
|
|
|
|
2021-06-11 11:23:27 -04:00
|
|
|
check_for_rerender(interpreter, "eval");
|
2005-09-15 09:58:31 -04:00
|
|
|
}
|
|
|
|
|
2020-11-22 10:42:23 -05:00
|
|
|
void
|
|
|
|
spidermonkey_call_function(struct ecmascript_interpreter *interpreter,
|
|
|
|
JS::HandleValue fun, struct string *ret)
|
|
|
|
{
|
|
|
|
JSContext *ctx;
|
|
|
|
JS::Value rval;
|
|
|
|
|
|
|
|
assert(interpreter);
|
|
|
|
if (!js_module_init_ok) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
ctx = interpreter->backend_data;
|
|
|
|
JS_BeginRequest(ctx);
|
|
|
|
JSCompartment *comp = JS_EnterCompartment(ctx, interpreter->ac);
|
|
|
|
|
|
|
|
interpreter->heartbeat = add_heartbeat(interpreter);
|
|
|
|
interpreter->ret = ret;
|
|
|
|
|
|
|
|
JS::RootedValue r_val(ctx, rval);
|
|
|
|
JS::RootedObject cg(ctx, JS::CurrentGlobalOrNull(ctx));
|
|
|
|
JS_CallFunctionValue(ctx, cg, fun, JS::HandleValueArray::empty(), &r_val);
|
|
|
|
done_heartbeat(interpreter->heartbeat);
|
|
|
|
JS_LeaveCompartment(ctx, comp);
|
|
|
|
JS_EndRequest(ctx);
|
2021-06-05 15:58:29 -04:00
|
|
|
|
2021-06-11 11:23:27 -04:00
|
|
|
check_for_rerender(interpreter, "call function");
|
2020-11-22 10:42:23 -05:00
|
|
|
}
|
|
|
|
|
2005-09-15 09:58:31 -04:00
|
|
|
|
2021-01-02 10:20:27 -05:00
|
|
|
char *
|
2005-09-15 09:58:31 -04:00
|
|
|
spidermonkey_eval_stringback(struct ecmascript_interpreter *interpreter,
|
2019-04-21 06:27:40 -04:00
|
|
|
struct string *code)
|
2005-09-15 09:58:31 -04:00
|
|
|
{
|
2020-10-11 09:41:27 -04:00
|
|
|
bool ret;
|
2005-09-15 09:58:31 -04:00
|
|
|
JSContext *ctx;
|
2020-10-23 16:34:58 -04:00
|
|
|
JS::Value rval;
|
2021-01-02 10:20:27 -05:00
|
|
|
char *result = NULL;
|
2005-09-15 09:58:31 -04:00
|
|
|
|
|
|
|
assert(interpreter);
|
2008-07-16 07:50:41 -04:00
|
|
|
if (!js_module_init_ok) return NULL;
|
2005-09-15 09:58:31 -04:00
|
|
|
ctx = interpreter->backend_data;
|
2006-01-27 06:07:45 -05:00
|
|
|
interpreter->ret = NULL;
|
2009-07-18 19:41:01 -04:00
|
|
|
interpreter->heartbeat = add_heartbeat(interpreter);
|
2019-02-10 15:00:37 -05:00
|
|
|
|
2020-11-16 16:00:48 -05:00
|
|
|
JS_BeginRequest(ctx);
|
|
|
|
JSCompartment *comp = JS_EnterCompartment(ctx, interpreter->ac);
|
|
|
|
|
2020-10-11 09:41:27 -04:00
|
|
|
JS::RootedObject cg(ctx, JS::CurrentGlobalOrNull(ctx));
|
|
|
|
JS::RootedValue r_rval(ctx, rval);
|
2020-10-16 13:54:02 -04:00
|
|
|
JS::CompileOptions options(ctx);
|
|
|
|
|
|
|
|
// options.setIntroductionType("js shell load")
|
|
|
|
// .setUTF8(true)
|
|
|
|
// .setCompileAndGo(true)
|
|
|
|
// .setNoScriptRval(true);
|
|
|
|
|
2020-10-23 16:34:58 -04:00
|
|
|
ret = JS::Evaluate(ctx, options, code->source, code->length, &r_rval);
|
2009-07-18 19:41:01 -04:00
|
|
|
done_heartbeat(interpreter->heartbeat);
|
2020-10-05 14:14:55 -04:00
|
|
|
|
2020-10-11 09:41:27 -04:00
|
|
|
if (ret == false) {
|
2020-11-16 16:00:48 -05:00
|
|
|
result = NULL;
|
2005-09-15 09:58:31 -04:00
|
|
|
}
|
2020-11-16 16:00:48 -05:00
|
|
|
else if (r_rval.isNullOrUndefined()) {
|
2005-09-15 09:58:31 -04:00
|
|
|
/* Undefined value. */
|
2020-11-16 16:00:48 -05:00
|
|
|
result = NULL;
|
|
|
|
} else {
|
|
|
|
result = stracpy(JS_EncodeString(ctx, r_rval.toString()));
|
2005-09-15 09:58:31 -04:00
|
|
|
}
|
2020-11-16 16:00:48 -05:00
|
|
|
JS_LeaveCompartment(ctx, comp);
|
|
|
|
JS_EndRequest(ctx);
|
2021-06-05 15:58:29 -04:00
|
|
|
|
2021-06-11 11:23:27 -04:00
|
|
|
check_for_rerender(interpreter, "eval stringback");
|
2021-06-05 15:58:29 -04:00
|
|
|
|
2020-11-16 16:00:48 -05:00
|
|
|
return result;
|
2005-09-15 09:58:31 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
spidermonkey_eval_boolback(struct ecmascript_interpreter *interpreter,
|
2019-04-21 06:27:40 -04:00
|
|
|
struct string *code)
|
2005-09-15 09:58:31 -04:00
|
|
|
{
|
|
|
|
JSContext *ctx;
|
2020-10-23 16:34:58 -04:00
|
|
|
JS::Value rval;
|
2005-09-15 09:58:31 -04:00
|
|
|
int ret;
|
2020-11-16 16:00:48 -05:00
|
|
|
int result = 0;
|
2005-09-15 09:58:31 -04:00
|
|
|
|
|
|
|
assert(interpreter);
|
2008-07-16 07:50:41 -04:00
|
|
|
if (!js_module_init_ok) return 0;
|
2005-09-15 09:58:31 -04:00
|
|
|
ctx = interpreter->backend_data;
|
2006-01-27 06:07:45 -05:00
|
|
|
interpreter->ret = NULL;
|
2019-02-10 15:00:37 -05:00
|
|
|
|
2020-11-16 16:00:48 -05:00
|
|
|
JSCompartment *comp = JS_EnterCompartment(ctx, interpreter->ac);
|
|
|
|
JS_BeginRequest(ctx);
|
|
|
|
|
2020-10-23 16:34:58 -04:00
|
|
|
JS::RootedFunction fun(ctx);
|
|
|
|
|
2020-10-11 09:41:27 -04:00
|
|
|
JS::CompileOptions options(ctx);
|
2020-10-16 13:54:02 -04:00
|
|
|
JS::AutoObjectVector ag(ctx);
|
2020-10-23 16:34:58 -04:00
|
|
|
if (!JS::CompileFunction(ctx, ag, options, "aaa", 0, nullptr, code->source,
|
2020-10-16 13:54:02 -04:00
|
|
|
code->length, &fun)) {
|
2007-05-19 14:54:08 -04:00
|
|
|
return -1;
|
2020-10-16 13:54:02 -04:00
|
|
|
};
|
2007-05-19 14:54:08 -04:00
|
|
|
|
2009-07-18 19:41:01 -04:00
|
|
|
interpreter->heartbeat = add_heartbeat(interpreter);
|
2020-10-11 09:41:27 -04:00
|
|
|
JS::RootedValue r_val(ctx, rval);
|
2020-10-16 13:54:02 -04:00
|
|
|
JS::RootedObject cg(ctx, JS::CurrentGlobalOrNull(ctx));
|
|
|
|
ret = JS_CallFunction(ctx, cg, fun, JS::HandleValueArray::empty(), &r_val);
|
2009-07-18 19:41:01 -04:00
|
|
|
done_heartbeat(interpreter->heartbeat);
|
2020-10-05 14:14:55 -04:00
|
|
|
|
2005-09-15 09:58:31 -04:00
|
|
|
if (ret == 2) { /* onClick="history.back()" */
|
2020-11-16 16:00:48 -05:00
|
|
|
result = 0;
|
2005-09-15 09:58:31 -04:00
|
|
|
}
|
2020-11-16 16:00:48 -05:00
|
|
|
else if (ret == false) {
|
|
|
|
result = -1;
|
2005-09-15 09:58:31 -04:00
|
|
|
}
|
2020-11-16 16:00:48 -05:00
|
|
|
else if (r_val.isUndefined()) {
|
2005-09-15 09:58:31 -04:00
|
|
|
/* Undefined value. */
|
2020-11-16 16:00:48 -05:00
|
|
|
result = -1;
|
|
|
|
} else {
|
|
|
|
result = r_val.toBoolean();
|
2005-09-15 09:58:31 -04:00
|
|
|
}
|
|
|
|
|
2020-11-16 16:00:48 -05:00
|
|
|
JS_LeaveCompartment(ctx, comp);
|
|
|
|
JS_EndRequest(ctx);
|
|
|
|
|
2021-06-11 11:23:27 -04:00
|
|
|
check_for_rerender(interpreter, "eval boolback");
|
2021-06-05 15:58:29 -04:00
|
|
|
|
2020-11-16 16:00:48 -05:00
|
|
|
return result;
|
2005-09-15 09:58:31 -04:00
|
|
|
}
|
2006-01-16 08:14:14 -05:00
|
|
|
|
|
|
|
struct module spidermonkey_module = struct_module(
|
2007-03-21 06:01:06 -04:00
|
|
|
/* name: */ N_("SpiderMonkey"),
|
2006-01-16 08:14:14 -05:00
|
|
|
/* options: */ NULL,
|
|
|
|
/* events: */ NULL,
|
|
|
|
/* submodules: */ NULL,
|
|
|
|
/* data: */ NULL,
|
2006-02-26 03:51:36 -05:00
|
|
|
/* init: */ spidermonkey_init,
|
|
|
|
/* done: */ spidermonkey_done
|
2006-01-16 08:14:14 -05:00
|
|
|
);
|