1
0
mirror of https://github.com/rkd77/elinks.git synced 2024-06-28 01:35:32 +00:00

[mozjs52] It compiles, but often segfaults. No idea yet how to fix it.

This commit is contained in:
Witold Filipczyk 2020-10-27 14:53:24 +01:00
parent a5b68a25a1
commit d1ecd45828
35 changed files with 461 additions and 198 deletions

View File

@ -612,11 +612,11 @@ case "$with_spidermonkey" in
;; ;;
esac esac
for package in mozjs-45; do for package in mozjs-52; do
if test -n "$CONFIG_SPIDERMONKEY"; then if test -n "$CONFIG_SPIDERMONKEY"; then
break break
else else
AC_MSG_CHECKING([for SpiderMonkey (mozjs-45) in pkg-config $package]) AC_MSG_CHECKING([for SpiderMonkey (mozjs-52) in pkg-config $package])
if $PKG_CONFIG --cflags --libs $package > /dev/null 2>&AS_MESSAGE_LOG_FD; then if $PKG_CONFIG --cflags --libs $package > /dev/null 2>&AS_MESSAGE_LOG_FD; then
SPIDERMONKEY_LIBS="$($PKG_CONFIG --libs $package)" SPIDERMONKEY_LIBS="$($PKG_CONFIG --libs $package)"
SPIDERMONKEY_CFLAGS="$($PKG_CONFIG --cflags $package)" SPIDERMONKEY_CFLAGS="$($PKG_CONFIG --cflags $package)"

View File

@ -271,7 +271,7 @@ if conf_data.get('CONFIG_BZIP2')
endif endif
if conf_data.get('CONFIG_ECMASCRIPT') if conf_data.get('CONFIG_ECMASCRIPT')
mozjsdeps = dependency('mozjs-45') mozjsdeps = dependency('mozjs-52')
deps += mozjsdeps deps += mozjsdeps
endif endif

View File

@ -232,7 +232,7 @@ get_resource_info(struct terminal *term, void *data)
val_add(n_("%ld refreshing", "%ld refreshing", val, term)); val_add(n_("%ld refreshing", "%ld refreshing", val, term));
add_to_string(&info, ".\n"); add_to_string(&info, ".\n");
#ifdef CONFIG_ECMASCRIPT #ifdef CONFIG_ECMASCRIPT_SMJS
add_to_string(&info, _("ECMAScript", term)); add_to_string(&info, _("ECMAScript", term));
add_to_string(&info, ": "); add_to_string(&info, ": ");

View File

@ -42,7 +42,7 @@
#include "viewer/text/vs.h" #include "viewer/text/vs.h"
#ifdef CONFIG_ECMASCRIPT #ifdef CONFIG_ECMASCRIPT_SMJS
/** @todo XXX: This function is de facto obsolete, since we do not need to copy /** @todo XXX: This function is de facto obsolete, since we do not need to copy
* snippets around anymore (we process them in one go after the document is * snippets around anymore (we process them in one go after the document is
* loaded; gradual processing was practically impossible because the snippets * loaded; gradual processing was practically impossible because the snippets
@ -331,7 +331,7 @@ render_document(struct view_state *vs, struct document_view *doc_view,
vs->doc_view->used = 0; /* A bit risky, but... */ vs->doc_view->used = 0; /* A bit risky, but... */
vs->doc_view->vs = NULL; vs->doc_view->vs = NULL;
vs->doc_view = NULL; vs->doc_view = NULL;
#ifdef CONFIG_ECMASCRIPT #ifdef CONFIG_ECMASCRIPT_SMJS
vs->ecmascript_fragile = 1; /* And is this good? ;-) */ vs->ecmascript_fragile = 1; /* And is this good? ;-) */
#endif #endif
} }
@ -385,7 +385,7 @@ render_document(struct view_state *vs, struct document_view *doc_view,
document->css_magic = get_document_css_magic(document); document->css_magic = get_document_css_magic(document);
#endif #endif
} }
#ifdef CONFIG_ECMASCRIPT #ifdef CONFIG_ECMASCRIPT_SMJS
if (!vs->ecmascript_fragile) if (!vs->ecmascript_fragile)
assert(vs->ecmascript); assert(vs->ecmascript);
if (!options->dump && !options->gradual_rerendering) { if (!options->dump && !options->gradual_rerendering) {

View File

@ -4,7 +4,7 @@ INCLUDES += $(SPIDERMONKEY_CFLAGS)
SUBDIRS-$(CONFIG_ECMASCRIPT_SMJS) += spidermonkey SUBDIRS-$(CONFIG_ECMASCRIPT_SMJS) += spidermonkey
OBJS-$(CONFIG_ECMASCRIPT_SMJS) += spidermonkey.o OBJS-$(CONFIG_ECMASCRIPT_SMJS) += ecmascript.o spidermonkey.o
ifeq ($(CONFIG_ECMASCRIPT_SMJS), yes) ifeq ($(CONFIG_ECMASCRIPT_SMJS), yes)
CONFIG_ANY_SPIDERMONKEY = yes CONFIG_ANY_SPIDERMONKEY = yes
@ -16,6 +16,4 @@ endif
OBJS-$(CONFIG_ANY_SPIDERMONKEY) += spidermonkey-shared.o OBJS-$(CONFIG_ANY_SPIDERMONKEY) += spidermonkey-shared.o
OBJS = ecmascript.o
include $(top_srcdir)/Makefile.lib include $(top_srcdir)/Makefile.lib

View File

@ -5,6 +5,7 @@
#endif #endif
#include <stdlib.h> #include <stdlib.h>
#include <stdio.h>
#include "elinks.h" #include "elinks.h"

View File

@ -53,6 +53,7 @@ struct ecmascript_interpreter {
* is reloaded in another tab and then you just cause the current tab * is reloaded in another tab and then you just cause the current tab
* to redraw. */ * to redraw. */
unsigned int onload_snippets_cache_id; unsigned int onload_snippets_cache_id;
void *ac;
}; };
/* Why is the interpreter bound to {struct view_state} instead of {struct /* Why is the interpreter bound to {struct view_state} instead of {struct

View File

@ -1,7 +1,7 @@
#INCLUDES += $(SPIDERMONKEY_CFLAGS) #INCLUDES += $(SPIDERMONKEY_CFLAGS)
if conf_data.get('CONFIG_ECMASCRIPT_SMJS') if conf_data.get('CONFIG_ECMASCRIPT_SMJS')
subdir('spidermonkey') subdir('spidermonkey')
srcs += files('spidermonkey.c') srcs += files('ecmascript.c', 'spidermonkey.c')
endif endif
if conf_data.get('CONFIG_ECMASCRIPT_SMJS') if conf_data.get('CONFIG_ECMASCRIPT_SMJS')
@ -16,4 +16,3 @@ if CONFIG_ANY_SPIDERMONKEY
srcs += files('spidermonkey-shared.c', 'empty.cpp') srcs += files('spidermonkey-shared.c', 'empty.cpp')
endif endif
srcs += files('ecmascript.c')

View File

@ -10,24 +10,12 @@
#include "ecmascript/spidermonkey-shared.h" #include "ecmascript/spidermonkey-shared.h"
#include <js/Initialization.h> #include <js/Initialization.h>
/** A shared runtime used for both user scripts (scripting/smjs/) and
* scripts on web pages (ecmascript/spidermonkey/).
*
* SpiderMonkey has bugs that corrupt memory when multiple JSRuntimes
* are used: https://bugzilla.mozilla.org/show_bug.cgi?id=378918 and
* perhaps others. */
JSRuntime *spidermonkey_runtime;
/** A JSContext that can be used in JS_SetPrivate and JS_GetPrivate /** A JSContext that can be used in JS_SetPrivate and JS_GetPrivate
* when no better one is available. This context has no global - * when no better one is available. This context has no global
* object, so scripts cannot be evaluated in it. - * object, so scripts cannot be evaluated in it.
* - */
* XXX: This also works around a crash on exit. SMJS will crash on
* JS_DestroyRuntime if the given runtime has never had any context
* created, which will be the case if one closes ELinks without having
* loaded any documents. */
JSContext *spidermonkey_empty_context;
JSContext *spidermonkey_empty_context;
/** A reference count for ::spidermonkey_runtime so that modules using /** A reference count for ::spidermonkey_runtime so that modules using
* it can be initialized and shut down in arbitrary order. */ * it can be initialized and shut down in arbitrary order. */
static int spidermonkey_runtime_refcount; static int spidermonkey_runtime_refcount;
@ -41,32 +29,18 @@ int
spidermonkey_runtime_addref(void) spidermonkey_runtime_addref(void)
{ {
if (spidermonkey_runtime_refcount == 0) { if (spidermonkey_runtime_refcount == 0) {
assert(spidermonkey_runtime == NULL);
assert(spidermonkey_empty_context == NULL);
if_assert_failed return 0;
if (!JS_Init()) { if (!JS_Init()) {
return 0; return 0;
} }
spidermonkey_runtime = JS_NewRuntime(4L * 1024L * 1024L); spidermonkey_empty_context = JS_NewContext(0);
if (!spidermonkey_runtime) return 0;
spidermonkey_empty_context = JS_NewContext(spidermonkey_runtime,
0);
if (!spidermonkey_empty_context) { if (!spidermonkey_empty_context) {
/* Perhaps JS_DestroyRuntime will now crash
* because no context was created, but there's
* not much else to do. */
JS_DestroyRuntime(spidermonkey_runtime);
spidermonkey_runtime = NULL;
JS_ShutDown(); JS_ShutDown();
return 0; return 0;
} }
} }
assert(spidermonkey_runtime);
assert(spidermonkey_empty_context);
spidermonkey_runtime_refcount++; spidermonkey_runtime_refcount++;
assert(spidermonkey_runtime_refcount > 0); assert(spidermonkey_runtime_refcount > 0);
if_assert_failed { spidermonkey_runtime_refcount--; return 0; } if_assert_failed { spidermonkey_runtime_refcount--; return 0; }
@ -80,16 +54,10 @@ void
spidermonkey_runtime_release(void) spidermonkey_runtime_release(void)
{ {
assert(spidermonkey_runtime_refcount > 0); assert(spidermonkey_runtime_refcount > 0);
assert(spidermonkey_runtime);
assert(spidermonkey_empty_context);
if_assert_failed return;
--spidermonkey_runtime_refcount; --spidermonkey_runtime_refcount;
if (spidermonkey_runtime_refcount == 0) { if (spidermonkey_runtime_refcount == 0) {
JS_DestroyContext(spidermonkey_empty_context); JS_DestroyContext(spidermonkey_empty_context);
spidermonkey_empty_context = NULL;
JS_DestroyRuntime(spidermonkey_runtime);
spidermonkey_runtime = NULL;
JS_ShutDown(); JS_ShutDown();
} }
} }

View File

@ -58,8 +58,88 @@
static int js_module_init_ok; static int js_module_init_ok;
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;
}
static void static void
error_reporter(JSContext *ctx, const char *message, JSErrorReport *report) error_reporter(JSContext *ctx, JSErrorReport *report)
{ {
struct ecmascript_interpreter *interpreter = JS_GetContextPrivate(ctx); struct ecmascript_interpreter *interpreter = JS_GetContextPrivate(ctx);
struct session *ses = interpreter->vs->doc_view->session; struct session *ses = interpreter->vs->doc_view->session;
@ -75,6 +155,8 @@ error_reporter(JSContext *ctx, const char *message, JSErrorReport *report)
term = ses->tab->term; term = ses->tab->term;
PrintError(ctx, stderr, JS::ConstUTF8CharsZ(), report, true/*reportWarnings*/);
#ifdef CONFIG_LEDS #ifdef CONFIG_LEDS
set_led_value(ses->status.ecmascript_led, 'J'); set_led_value(ses->status.ecmascript_led, 'J');
#endif #endif
@ -93,7 +175,6 @@ error_reporter(JSContext *ctx, const char *message, JSErrorReport *report)
strict, exception, warning, error); strict, exception, warning, error);
add_to_string(&msg, ":\n\n"); add_to_string(&msg, ":\n\n");
add_to_string(&msg, message);
if (report->filename) { if (report->filename) {
prefix = JS_smprintf("%s:", report->filename); prefix = JS_smprintf("%s:", report->filename);
@ -147,25 +228,30 @@ spidermonkey_get_interpreter(struct ecmascript_interpreter *interpreter)
JSContext *ctx; JSContext *ctx;
JSObject *document_obj, *forms_obj, *history_obj, *location_obj, JSObject *document_obj, *forms_obj, *history_obj, *location_obj,
*statusbar_obj, *menubar_obj, *navigator_obj; *statusbar_obj, *menubar_obj, *navigator_obj;
JSAutoCompartment *ac = NULL;
assert(interpreter); assert(interpreter);
if (!js_module_init_ok) return NULL; if (!js_module_init_ok) return NULL;
ctx = JS_NewContext(spidermonkey_runtime, // ctx = JS_NewContext(JS::DefaultHeapMaxBytes, JS::DefaultNurseryBytes);
8192 /* Stack allocation chunk size */); ctx = JS_NewContext(8L * 1024 * 1024);
if (!ctx) if (!ctx)
return NULL; return NULL;
interpreter->backend_data = ctx; interpreter->backend_data = ctx;
JSAutoRequest ar(ctx); JSAutoRequest ar(ctx);
JS_SetContextPrivate(ctx, interpreter); JS_SetContextPrivate(ctx, interpreter);
//JS_SetOptions(ctx, JSOPTION_VAROBJFIX | JS_METHODJIT); //JS_SetOptions(ctx, JSOPTION_VAROBJFIX | JS_METHODJIT);
JS_SetErrorReporter(spidermonkey_runtime, error_reporter); JS::SetWarningReporter(ctx, error_reporter);
JS_SetInterruptCallback(spidermonkey_runtime, heartbeat_callback); JS_AddInterruptCallback(ctx, heartbeat_callback);
JS::RootedObject window_obj(ctx, JS_NewGlobalObject(ctx, &window_class, NULL, JS::DontFireOnNewGlobalHook)); JS::CompartmentOptions options;
if (!JS::InitSelfHostedCode(ctx)) {
return NULL;
}
JS::RootedObject window_obj(ctx, JS_NewGlobalObject(ctx, &window_class, NULL, JS::FireOnNewGlobalHook, options));
if (window_obj) { if (window_obj) {
ac = new JSAutoCompartment(ctx, window_obj); interpreter->ac = new JSAutoCompartment(ctx, window_obj);
} else { } else {
goto release_and_fail; goto release_and_fail;
} }
@ -191,6 +277,7 @@ spidermonkey_get_interpreter(struct ecmascript_interpreter *interpreter)
if (!document_obj) { if (!document_obj) {
goto release_and_fail; goto release_and_fail;
} }
JS_SetPrivate(document_obj, interpreter->vs);
forms_obj = spidermonkey_InitClass(ctx, document_obj, NULL, forms_obj = spidermonkey_InitClass(ctx, document_obj, NULL,
&forms_class, NULL, 0, &forms_class, NULL, 0,
@ -266,8 +353,12 @@ spidermonkey_put_interpreter(struct ecmascript_interpreter *interpreter)
assert(interpreter); assert(interpreter);
if (!js_module_init_ok) return; if (!js_module_init_ok) return;
ctx = interpreter->backend_data; ctx = interpreter->backend_data;
if (interpreter->ac) {
delete (JSAutoCompartment *)interpreter->ac;
}
JS_DestroyContext(ctx); JS_DestroyContext(ctx);
interpreter->backend_data = NULL; interpreter->backend_data = NULL;
interpreter->ac = nullptr;
} }

View File

@ -50,13 +50,18 @@
static bool document_get_property(JSContext *ctx, JS::HandleObject hobj, JS::HandleId hid, JS::MutableHandleValue hvp); static bool document_get_property(JSContext *ctx, JS::HandleObject hobj, JS::HandleId hid, JS::MutableHandleValue hvp);
JSClassOps document_ops = {
JS_PropertyStub, nullptr,
document_get_property, JS_StrictPropertyStub,
nullptr, nullptr, nullptr
};
/* Each @document_class object must have a @window_class parent. */ /* Each @document_class object must have a @window_class parent. */
JSClass document_class = { JSClass document_class = {
"document", "document",
JSCLASS_HAS_PRIVATE, JSCLASS_HAS_PRIVATE,
JS_PropertyStub, nullptr, &document_ops
document_get_property, JS_StrictPropertyStub,
nullptr, nullptr, nullptr
}; };
#ifdef CONFIG_COOKIES #ifdef CONFIG_COOKIES
@ -249,16 +254,19 @@ document_set_property_title(JSContext *ctx, int argc, JS::Value *vp)
{ {
JS::CallArgs args = CallArgsFromVp(argc, vp); JS::CallArgs args = CallArgsFromVp(argc, vp);
JS::RootedObject hobj(ctx, &args.thisv().toObject()); JS::RootedObject hobj(ctx, &args.thisv().toObject());
JS::RootedObject parent_win(ctx, js::GetGlobalForObjectCrossCompartment(hobj)); // JS::RootedObject parent_win(ctx, js::GetGlobalForObjectCrossCompartment(hobj));
struct view_state *vs; struct view_state *vs;
struct document_view *doc_view; struct document_view *doc_view;
struct document *document; struct document *document;
assert(JS_InstanceOf(ctx, parent_win, &window_class, NULL)); assert(JS_InstanceOf(ctx, hobj, &document_class, NULL));
if_assert_failed return false; if_assert_failed return false;
vs = JS_GetInstancePrivate(ctx, parent_win, // assert(JS_InstanceOf(ctx, parent_win, &window_class, NULL));
&window_class, NULL); // if_assert_failed return false;
vs = JS_GetInstancePrivate(ctx, hobj,
&document_class, NULL);
if (!vs) { if (!vs) {
return false; return false;
} }

View File

@ -66,13 +66,17 @@ static bool form_set_property_target(JSContext *ctx, unsigned int argc, JS::Valu
static void form_finalize(JSFreeOp *op, JSObject *obj); static void form_finalize(JSFreeOp *op, JSObject *obj);
static JSClassOps form_ops = {
JS_PropertyStub, nullptr,
form_get_property, JS_StrictPropertyStub,
nullptr, nullptr, nullptr, form_finalize
};
/* Each @form_class object must have a @document_class parent. */ /* Each @form_class object must have a @document_class parent. */
static JSClass form_class = { static JSClass form_class = {
"form", "form",
JSCLASS_HAS_PRIVATE, /* struct form_view *, or NULL if detached */ JSCLASS_HAS_PRIVATE, /* struct form_view *, or NULL if detached */
JS_PropertyStub, nullptr, &form_ops
form_get_property, JS_StrictPropertyStub,
nullptr, nullptr, nullptr, form_finalize
}; };
@ -86,13 +90,17 @@ static bool input_get_property(JSContext *ctx, JS::HandleObject hobj, JS::Handle
static bool input_set_property(JSContext *ctx, JS::HandleObject hobj, JS::HandleId hid, JS::MutableHandleValue hvp); static bool input_set_property(JSContext *ctx, JS::HandleObject hobj, JS::HandleId hid, JS::MutableHandleValue hvp);
static void input_finalize(JSFreeOp *op, JSObject *obj); static void input_finalize(JSFreeOp *op, JSObject *obj);
static JSClassOps input_ops = {
JS_PropertyStub, nullptr,
input_get_property, input_set_property,
nullptr, nullptr, nullptr, input_finalize
};
/* Each @input_class object must have a @form_class parent. */ /* Each @input_class object must have a @form_class parent. */
static JSClass input_class = { static JSClass input_class = {
"input", /* here, we unleash ourselves */ "input", /* here, we unleash ourselves */
JSCLASS_HAS_PRIVATE, /* struct form_state *, or NULL if detached */ JSCLASS_HAS_PRIVATE, /* struct form_state *, or NULL if detached */
JS_PropertyStub, nullptr, &input_ops
input_get_property, input_set_property,
nullptr, nullptr, nullptr, input_finalize
}; };
/* Tinyids of properties. Use negative values to distinguish these /* Tinyids of properties. Use negative values to distinguish these
@ -264,7 +272,7 @@ input_set_property_accessKey(JSContext *ctx, unsigned int argc, JS::Value *vp)
} }
} }
if (accesskey == UCS_NO_CHAR) { if (accesskey == UCS_NO_CHAR) {
JS_ReportError(ctx, "Invalid UTF-16 sequence"); JS_ReportErrorUTF8(ctx, "Invalid UTF-16 sequence");
return false; return false;
} }
@ -1890,7 +1898,7 @@ spidermonkey_detach_form_state(struct form_state *fs)
JSObject *jsinput = fs->ecmascript_obj; JSObject *jsinput = fs->ecmascript_obj;
if (jsinput) { if (jsinput) {
JS::RootedObject r_jsinput(spidermonkey_empty_context, jsinput); // JS::RootedObject r_jsinput(spidermonkey_empty_context, jsinput);
/* This assumes JS_GetInstancePrivate and JS_SetPrivate /* This assumes JS_GetInstancePrivate and JS_SetPrivate
* cannot GC. */ * cannot GC. */
@ -1898,12 +1906,12 @@ spidermonkey_detach_form_state(struct form_state *fs)
* the private pointer of jsinput should be reset; * the private pointer of jsinput should be reset;
* crashes seem possible either way. Resetting it is * crashes seem possible either way. Resetting it is
* easiest. */ * easiest. */
assert(JS_GetInstancePrivate(spidermonkey_empty_context, // assert(JS_GetInstancePrivate(spidermonkey_empty_context,
r_jsinput, // r_jsinput,
&input_class, NULL) // &input_class, NULL)
== fs); // == fs);
if_assert_failed {} // if_assert_failed {}
//
JS_SetPrivate(jsinput, NULL); JS_SetPrivate(jsinput, NULL);
fs->ecmascript_obj = NULL; fs->ecmascript_obj = NULL;
} }
@ -1957,13 +1965,17 @@ get_form_control_object(JSContext *ctx,
static struct form_view *form_get_form_view(JSContext *ctx, JSObject *jsform, JS::Value *argv); static struct form_view *form_get_form_view(JSContext *ctx, JSObject *jsform, JS::Value *argv);
static bool form_elements_get_property(JSContext *ctx, JS::HandleObject hobj, JS::HandleId hid, JS::MutableHandleValue hvp); static bool form_elements_get_property(JSContext *ctx, JS::HandleObject hobj, JS::HandleId hid, JS::MutableHandleValue hvp);
static JSClassOps form_elements_ops = {
JS_PropertyStub, nullptr,
form_elements_get_property, JS_StrictPropertyStub,
nullptr, nullptr, nullptr, nullptr
};
/* Each @form_elements_class object must have a @form_class parent. */ /* Each @form_elements_class object must have a @form_class parent. */
static JSClass form_elements_class = { static JSClass form_elements_class = {
"elements", "elements",
JSCLASS_HAS_PRIVATE, JSCLASS_HAS_PRIVATE,
JS_PropertyStub, nullptr, &form_elements_ops
form_elements_get_property, JS_StrictPropertyStub,
nullptr, nullptr, nullptr, nullptr
}; };
static bool form_elements_item2(JSContext *ctx, JS::HandleObject hobj, int index, JS::MutableHandleValue hvp); static bool form_elements_item2(JSContext *ctx, JS::HandleObject hobj, int index, JS::MutableHandleValue hvp);
@ -3113,7 +3125,7 @@ spidermonkey_detach_form_view(struct form_view *fv)
JSObject *jsform = fv->ecmascript_obj; JSObject *jsform = fv->ecmascript_obj;
if (jsform) { if (jsform) {
JS::RootedObject r_jsform(spidermonkey_empty_context, jsform); // JS::RootedObject r_jsform(spidermonkey_empty_context, jsform);
/* This assumes JS_GetInstancePrivate and JS_SetPrivate /* This assumes JS_GetInstancePrivate and JS_SetPrivate
* cannot GC. */ * cannot GC. */
@ -3121,11 +3133,11 @@ spidermonkey_detach_form_view(struct form_view *fv)
* the private pointer of jsform should be reset; * the private pointer of jsform should be reset;
* crashes seem possible either way. Resetting it is * crashes seem possible either way. Resetting it is
* easiest. */ * easiest. */
assert(JS_GetInstancePrivate(spidermonkey_empty_context, // assert(JS_GetInstancePrivate(spidermonkey_empty_context,
r_jsform, // r_jsform,
&form_class, NULL) // &form_class, NULL)
== fv); // == fv);
if_assert_failed {} // if_assert_failed {}
JS_SetPrivate(jsform, NULL); JS_SetPrivate(jsform, NULL);
fv->ecmascript_obj = NULL; fv->ecmascript_obj = NULL;
@ -3136,13 +3148,17 @@ spidermonkey_detach_form_view(struct form_view *fv)
static bool forms_get_property(JSContext *ctx, JS::HandleObject hobj, JS::HandleId hid, JS::MutableHandleValue hvp); static bool forms_get_property(JSContext *ctx, JS::HandleObject hobj, JS::HandleId hid, JS::MutableHandleValue hvp);
static bool forms_get_property_length(JSContext *ctx, unsigned int argc, JS::Value *vp); static bool forms_get_property_length(JSContext *ctx, unsigned int argc, JS::Value *vp);
JSClassOps forms_ops = {
JS_PropertyStub, nullptr,
forms_get_property, JS_StrictPropertyStub,
nullptr, nullptr, nullptr, nullptr
};
/* Each @forms_class object must have a @document_class parent. */ /* Each @forms_class object must have a @document_class parent. */
JSClass forms_class = { JSClass forms_class = {
"forms", "forms",
JSCLASS_HAS_PRIVATE, JSCLASS_HAS_PRIVATE,
JS_PropertyStub, nullptr, &forms_ops
forms_get_property, JS_StrictPropertyStub,
nullptr, nullptr, nullptr, nullptr
}; };
static bool forms_item(JSContext *ctx, unsigned int argc, JS::Value *rval); static bool forms_item(JSContext *ctx, unsigned int argc, JS::Value *rval);
@ -3415,6 +3431,6 @@ jsval_to_accesskey(JSContext *ctx, JS::MutableHandleValue hvp)
return join_utf16_surrogates(chr[0], chr[1]); return join_utf16_surrogates(chr[0], chr[1]);
} }
} }
JS_ReportError(ctx, "Invalid UTF-16 sequence"); JS_ReportErrorUTF8(ctx, "Invalid UTF-16 sequence");
return UCS_NO_CHAR; /* which the caller will reject */ return UCS_NO_CHAR; /* which the caller will reject */
} }

View File

@ -36,6 +36,11 @@ static struct itimerval heartbeat_timer = { { 1, 0 }, { 1, 0 } };
bool bool
heartbeat_callback(JSContext *ctx) heartbeat_callback(JSContext *ctx)
{ {
struct ecmascript_interpreter *interpreter = JS_GetContextPrivate(ctx);
if (!interpreter->heartbeat || interpreter->heartbeat->ttl > 0) {
return true;
}
return false; return false;
} }
@ -63,7 +68,7 @@ check_heartbeats(void *data)
ecmascript_timeout_dialog(term, max_exec_time); ecmascript_timeout_dialog(term, max_exec_time);
} }
JS_RequestInterruptCallback(JS_GetRuntime(hb->interpreter->backend_data)); JS_RequestInterruptCallback(hb->interpreter->backend_data);
} }
} }
install_signal_handler(SIGVTALRM, check_heartbeats, NULL, 1); install_signal_handler(SIGVTALRM, check_heartbeats, NULL, 1);

View File

@ -50,14 +50,18 @@ static bool history_back(JSContext *ctx, unsigned int argc, JS::Value *rval);
static bool history_forward(JSContext *ctx, unsigned int argc, JS::Value *rval); static bool history_forward(JSContext *ctx, unsigned int argc, JS::Value *rval);
static bool history_go(JSContext *ctx, unsigned int argc, JS::Value *rval); static bool history_go(JSContext *ctx, unsigned int argc, JS::Value *rval);
JSClass history_class = { JSClassOps history_ops = {
"history",
JSCLASS_HAS_PRIVATE,
JS_PropertyStub, nullptr, JS_PropertyStub, nullptr,
JS_PropertyStub, JS_StrictPropertyStub, JS_PropertyStub, JS_StrictPropertyStub,
nullptr, nullptr, nullptr, nullptr nullptr, nullptr, nullptr, nullptr
}; };
JSClass history_class = {
"history",
JSCLASS_HAS_PRIVATE,
&history_ops
};
const spidermonkeyFunctionSpec history_funcs[] = { const spidermonkeyFunctionSpec history_funcs[] = {
{ "back", history_back, 0 }, { "back", history_back, 0 },
{ "forward", history_forward, 0 }, { "forward", history_forward, 0 },
@ -134,13 +138,16 @@ history_go(JSContext *ctx, unsigned int argc, JS::Value *rval)
static bool location_get_property_href(JSContext *ctx, unsigned int argc, JS::Value *vp); static bool location_get_property_href(JSContext *ctx, unsigned int argc, JS::Value *vp);
static bool location_set_property_href(JSContext *ctx, unsigned int argc, JS::Value *vp); static bool location_set_property_href(JSContext *ctx, unsigned int argc, JS::Value *vp);
JSClassOps location_ops = {
JS_PropertyStub, nullptr,
JS_PropertyStub, JS_StrictPropertyStub,
nullptr, nullptr, nullptr, nullptr
};
/* Each @location_class object must have a @window_class parent. */ /* Each @location_class object must have a @window_class parent. */
JSClass location_class = { JSClass location_class = {
"location", "location",
JSCLASS_HAS_PRIVATE, JSCLASS_HAS_PRIVATE,
JS_PropertyStub, nullptr, &location_ops
JS_PropertyStub, JS_StrictPropertyStub,
nullptr, nullptr, nullptr, nullptr
}; };
/* Tinyids of properties. Use negative values to distinguish these /* Tinyids of properties. Use negative values to distinguish these

View File

@ -51,14 +51,18 @@ static bool navigator_get_property_language(JSContext *ctx, unsigned int argc, J
static bool navigator_get_property_platform(JSContext *ctx, unsigned int argc, JS::Value *vp); static bool navigator_get_property_platform(JSContext *ctx, unsigned int argc, JS::Value *vp);
static bool navigator_get_property_userAgent(JSContext *ctx, unsigned int argc, JS::Value *vp); static bool navigator_get_property_userAgent(JSContext *ctx, unsigned int argc, JS::Value *vp);
JSClass navigator_class = { JSClassOps navigator_ops = {
"navigator",
JSCLASS_HAS_PRIVATE,
JS_PropertyStub, nullptr, JS_PropertyStub, nullptr,
JS_PropertyStub, JS_StrictPropertyStub, JS_PropertyStub, JS_StrictPropertyStub,
nullptr, nullptr, nullptr, nullptr nullptr, nullptr, nullptr, nullptr
}; };
JSClass navigator_class = {
"navigator",
JSCLASS_HAS_PRIVATE,
&navigator_ops
};
/* Tinyids of properties. Use negative values to distinguish these /* Tinyids of properties. Use negative values to distinguish these
* from array indexes (even though this object has no array elements). * from array indexes (even though this object has no array elements).
* ECMAScript code should not use these directly as in navigator[-1]; * ECMAScript code should not use these directly as in navigator[-1];

View File

@ -48,10 +48,20 @@
static bool unibar_get_property_visible(JSContext *ctx, unsigned int argc, JS::Value *vp); static bool unibar_get_property_visible(JSContext *ctx, unsigned int argc, JS::Value *vp);
static bool unibar_set_property_visible(JSContext *ctx, unsigned int argc, JS::Value *vp); static bool unibar_set_property_visible(JSContext *ctx, unsigned int argc, JS::Value *vp);
JSClassOps menubar_ops = {
JS_PropertyStub, nullptr,
JS_PropertyStub, JS_StrictPropertyStub,
nullptr, nullptr, nullptr, nullptr
};
/* Each @menubar_class object must have a @window_class parent. */ /* Each @menubar_class object must have a @window_class parent. */
JSClass menubar_class = { JSClass menubar_class = {
"menubar", "menubar",
JSCLASS_HAS_PRIVATE, /* const char * "t" */ JSCLASS_HAS_PRIVATE, /* const char * "t" */
&menubar_ops
};
JSClassOps statusbar_ops = {
JS_PropertyStub, nullptr, JS_PropertyStub, nullptr,
JS_PropertyStub, JS_StrictPropertyStub, JS_PropertyStub, JS_StrictPropertyStub,
nullptr, nullptr, nullptr, nullptr nullptr, nullptr, nullptr, nullptr
@ -60,9 +70,7 @@ JSClass menubar_class = {
JSClass statusbar_class = { JSClass statusbar_class = {
"statusbar", "statusbar",
JSCLASS_HAS_PRIVATE, /* const char * "s" */ JSCLASS_HAS_PRIVATE, /* const char * "s" */
JS_PropertyStub, nullptr, &statusbar_ops
JS_PropertyStub, JS_StrictPropertyStub,
nullptr, nullptr, nullptr, nullptr
}; };
/* Tinyids of properties. Use negative values to distinguish these /* Tinyids of properties. Use negative values to distinguish these

View File

@ -53,14 +53,18 @@ static bool window_get_property_status(JSContext *ctx, unsigned int argc, JS::Va
static bool window_set_property_status(JSContext *ctx, unsigned int argc, JS::Value *vp); static bool window_set_property_status(JSContext *ctx, unsigned int argc, JS::Value *vp);
static bool window_get_property_top(JSContext *ctx, unsigned int argc, JS::Value *vp); static bool window_get_property_top(JSContext *ctx, unsigned int argc, JS::Value *vp);
JSClass window_class = { JSClassOps window_ops = {
"window",
JSCLASS_HAS_PRIVATE | JSCLASS_GLOBAL_FLAGS, /* struct view_state * */
JS_PropertyStub, nullptr, JS_PropertyStub, nullptr,
window_get_property, JS_StrictPropertyStub, window_get_property, JS_StrictPropertyStub,
nullptr, nullptr, nullptr, nullptr nullptr, nullptr, nullptr, nullptr
}; };
JSClass window_class = {
"window",
JSCLASS_HAS_PRIVATE | JSCLASS_GLOBAL_FLAGS, /* struct view_state * */
&window_ops
};
/* Tinyids of properties. Use negative values to distinguish these /* Tinyids of properties. Use negative values to distinguish these
* from array indexes (even though this object has no array elements). * from array indexes (even though this object has no array elements).
@ -440,6 +444,7 @@ window_setTimeout(JSContext *ctx, unsigned int argc, JS::Value *rval)
if (!code) if (!code)
return true; return true;
timeout = args[1].toInt32(); timeout = args[1].toInt32();
if (timeout <= 0) { if (timeout <= 0) {
mem_free(code); mem_free(code);
return true; return true;

View File

@ -60,7 +60,7 @@ struct module *builtin_modules[] = {
#ifdef CONFIG_COOKIES #ifdef CONFIG_COOKIES
&cookies_module, &cookies_module,
#endif #endif
#ifdef CONFIG_ECMASCRIPT #ifdef CONFIG_ECMASCRIPT_SMJS
&ecmascript_module, &ecmascript_module,
#endif #endif
#ifdef CONFIG_FORMHIST #ifdef CONFIG_FORMHIST

View File

@ -219,7 +219,7 @@ generic_external_protocol_handler(struct session *ses, struct uri *uri)
switch (uri->protocol) { switch (uri->protocol) {
case PROTOCOL_JAVASCRIPT: case PROTOCOL_JAVASCRIPT:
#ifdef CONFIG_ECMASCRIPT #ifdef CONFIG_ECMASCRIPT_SMJS
ecmascript_protocol_handler(ses, uri); ecmascript_protocol_handler(ses, uri);
return; return;
#else #else

View File

@ -26,9 +26,7 @@ struct smjs_action_fn_callback_hop {
static void smjs_action_fn_finalize(JSFreeOp *op, JSObject *obj); static void smjs_action_fn_finalize(JSFreeOp *op, JSObject *obj);
static bool smjs_action_fn_callback(JSContext *ctx, unsigned int argc, JS::Value *rval); static bool smjs_action_fn_callback(JSContext *ctx, unsigned int argc, JS::Value *rval);
static const JSClass action_fn_class = { static JSClassOps action_fn_ops = {
"action_fn",
JSCLASS_HAS_PRIVATE, /* struct smjs_action_fn_callback_hop * */
JS_PropertyStub, nullptr, JS_PropertyStub, nullptr,
JS_PropertyStub, JS_StrictPropertyStub, JS_PropertyStub, JS_StrictPropertyStub,
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
@ -37,6 +35,12 @@ static const JSClass action_fn_class = {
smjs_action_fn_callback, smjs_action_fn_callback,
}; };
static const JSClass action_fn_class = {
"action_fn",
JSCLASS_HAS_PRIVATE, /* struct smjs_action_fn_callback_hop * */
&action_fn_ops
};
/* @action_fn_class.finalize */ /* @action_fn_class.finalize */
static void static void
smjs_action_fn_finalize(JSFreeOp *op, JSObject *obj) smjs_action_fn_finalize(JSFreeOp *op, JSObject *obj)
@ -104,7 +108,7 @@ smjs_action_fn_callback(JSContext *ctx, unsigned int argc, JS::Value *rval)
* *
* The "%s" prevents interpretation of any percent * The "%s" prevents interpretation of any percent
* signs in translations. */ * signs in translations. */
JS_ReportError(ctx, "%s", JS_ReportErrorUTF8(ctx, "%s",
_("Cannot run actions in a tab that doesn't " _("Cannot run actions in a tab that doesn't "
"have the focus", hop->ses->tab->term)); "have the focus", hop->ses->tab->term));
return false; /* make JS propagate the exception */ return false; /* make JS propagate the exception */
@ -183,14 +187,18 @@ action_get_property(JSContext *ctx, JS::HandleObject hobj, JS::HandleId hid, JS:
return true; return true;
} }
static const JSClass action_class = { static JSClassOps action_ops = {
"action",
0,
JS_PropertyStub, nullptr, JS_PropertyStub, nullptr,
action_get_property, JS_StrictPropertyStub, action_get_property, JS_StrictPropertyStub,
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
}; };
static const JSClass action_class = {
"action",
0,
&action_ops
};
static JSObject * static JSObject *
smjs_get_action_object(void) smjs_get_action_object(void)
{ {

View File

@ -20,20 +20,28 @@
static void bookmark_finalize(JSFreeOp *op, JSObject *obj); static void bookmark_finalize(JSFreeOp *op, JSObject *obj);
static bool bookmark_folder_get_property(JSContext *ctx, JS::HandleObject hobj, JS::HandleId hid, JS::MutableHandleValue hvp); static bool bookmark_folder_get_property(JSContext *ctx, JS::HandleObject hobj, JS::HandleId hid, JS::MutableHandleValue hvp);
static JSClassOps bookmark_ops = {
JS_PropertyStub, nullptr,
JS_PropertyStub, JS_StrictPropertyStub,
nullptr, nullptr, nullptr, bookmark_finalize,
};
static const JSClass bookmark_class = { static const JSClass bookmark_class = {
"bookmark", "bookmark",
JSCLASS_HAS_PRIVATE, /* struct bookmark * */ JSCLASS_HAS_PRIVATE, /* struct bookmark * */
&bookmark_ops
};
static JSClassOps bookmark_folder_ops = {
JS_PropertyStub, nullptr, JS_PropertyStub, nullptr,
JS_PropertyStub, JS_StrictPropertyStub, bookmark_folder_get_property, JS_StrictPropertyStub,
nullptr, nullptr, nullptr, bookmark_finalize, nullptr, nullptr, nullptr, bookmark_finalize,
}; };
static const JSClass bookmark_folder_class = { static const JSClass bookmark_folder_class = {
"bookmark_folder", "bookmark_folder",
JSCLASS_HAS_PRIVATE, /* struct bookmark * */ JSCLASS_HAS_PRIVATE, /* struct bookmark * */
JS_PropertyStub, nullptr, &bookmark_folder_ops
bookmark_folder_get_property, JS_StrictPropertyStub,
nullptr, nullptr, nullptr, bookmark_finalize,
}; };
static JSObject * static JSObject *

View File

@ -17,14 +17,18 @@
static void cache_entry_finalize(JSFreeOp *op, JSObject *obj); static void cache_entry_finalize(JSFreeOp *op, JSObject *obj);
static const JSClass cache_entry_class = { static JSClassOps cache_entry_ops = {
"cache_entry",
JSCLASS_HAS_PRIVATE, /* struct cache_entry *; a weak reference */
JS_PropertyStub, nullptr, JS_PropertyStub, nullptr,
JS_PropertyStub, JS_StrictPropertyStub, JS_PropertyStub, JS_StrictPropertyStub,
nullptr, nullptr, nullptr, cache_entry_finalize nullptr, nullptr, nullptr, cache_entry_finalize
}; };
static const JSClass cache_entry_class = {
"cache_entry",
JSCLASS_HAS_PRIVATE, /* struct cache_entry *; a weak reference */
&cache_entry_ops
};
/* Tinyids of properties. Use negative values to distinguish these /* Tinyids of properties. Use negative values to distinguish these
* from array indexes (even though this object has no array elements). * from array indexes (even though this object has no array elements).
* ECMAScript code should not use these directly as in cache_entry[-1]; * ECMAScript code should not use these directly as in cache_entry[-1];

View File

@ -37,8 +37,88 @@ alert_smjs_error(unsigned char *msg)
smjs_ses, msg); smjs_ses, msg);
} }
static 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;
}
static void static void
error_reporter(JSContext *ctx, const char *message, JSErrorReport *report) error_reporter(JSContext *ctx, JSErrorReport *report)
{ {
unsigned char *strict, *exception, *warning, *error; unsigned char *strict, *exception, *warning, *error;
struct string msg; struct string msg;
@ -51,11 +131,12 @@ error_reporter(JSContext *ctx, const char *message, JSErrorReport *report)
warning = JSREPORT_IS_WARNING(report->flags) ? " warning" : ""; warning = JSREPORT_IS_WARNING(report->flags) ? " warning" : "";
error = !report->flags ? " error" : ""; error = !report->flags ? " error" : "";
PrintError(ctx, stderr, JS::ConstUTF8CharsZ(), report, true/*reportWarnings*/);
add_format_to_string(&msg, "A client script raised the following%s%s%s%s", add_format_to_string(&msg, "A client script raised the following%s%s%s%s",
strict, exception, warning, error); strict, exception, warning, error);
add_to_string(&msg, ":\n\n"); add_to_string(&msg, ":\n\n");
add_to_string(&msg, message);
add_format_to_string(&msg, "\n\n%d:%d ", report->lineno, report->column); add_format_to_string(&msg, "\n\n%d:%d ", report->lineno, report->column);
@ -153,13 +234,13 @@ init_smjs(struct module *module)
{ {
if (!spidermonkey_runtime_addref()) return; if (!spidermonkey_runtime_addref()) return;
smjs_ctx = JS_NewContext(spidermonkey_runtime, 8192); smjs_ctx = JS_NewContext(8L * 1024 * 1024);
if (!smjs_ctx) { if (!smjs_ctx) {
spidermonkey_runtime_release(); spidermonkey_runtime_release();
return; return;
} }
JS_SetErrorReporter(spidermonkey_runtime, error_reporter); JS::SetWarningReporter(smjs_ctx, error_reporter);
smjs_init_global_object(); smjs_init_global_object();

View File

@ -108,14 +108,18 @@ static const JSPropertySpec elinks_props[] = {
static bool elinks_get_property(JSContext *ctx, JS::HandleObject hobj, JS::HandleId hid, JS::MutableHandleValue hvp); static bool elinks_get_property(JSContext *ctx, JS::HandleObject hobj, JS::HandleId hid, JS::MutableHandleValue hvp);
static bool elinks_set_property(JSContext *ctx, JS::HandleObject hobj, JS::HandleId hid, JS::MutableHandleValue hvp); static bool elinks_set_property(JSContext *ctx, JS::HandleObject hobj, JS::HandleId hid, JS::MutableHandleValue hvp);
static const JSClass elinks_class = { static const JSClassOps elinks_ops = {
"elinks",
0,
JS_PropertyStub, nullptr, JS_PropertyStub, nullptr,
elinks_get_property, elinks_set_property, elinks_get_property, elinks_set_property,
nullptr, nullptr, nullptr, nullptr nullptr, nullptr, nullptr, nullptr
}; };
static const JSClass elinks_class = {
"elinks",
0,
&elinks_ops
};
/* @elinks_class.getProperty */ /* @elinks_class.getProperty */
static bool static bool
@ -263,15 +267,12 @@ smjs_invoke_elinks_object_method(unsigned char *method, int argc, JS::Value *arg
assert(argv); assert(argv);
JS::RootedObject r_smjs_elinks_object(smjs_ctx, smjs_elinks_object); JS::RootedObject r_smjs_elinks_object(smjs_ctx, smjs_elinks_object);
JS::Value val; JS::RootedValue fun(smjs_ctx);
JS::RootedValue fun(smjs_ctx, val);
if (false == JS_GetProperty(smjs_ctx, r_smjs_elinks_object, if (false == JS_GetProperty(smjs_ctx, r_smjs_elinks_object,
method, &fun)) method, &fun)) {
return false;
if (rval.isUndefined())
return false; return false;
}
return JS_CallFunctionValue(smjs_ctx, r_smjs_elinks_object, fun, args, rval); return JS_CallFunctionValue(smjs_ctx, r_smjs_elinks_object, fun, args, rval);
} }

View File

@ -15,14 +15,17 @@ using namespace JS;
JSObject *smjs_global_object; JSObject *smjs_global_object;
static const JSClassOps global_ops = {
static const JSClass global_class = {
"global", JSCLASS_GLOBAL_FLAGS,
JS_PropertyStub, nullptr, JS_PropertyStub, nullptr,
JS_PropertyStub, JS_StrictPropertyStub, JS_PropertyStub, JS_StrictPropertyStub,
nullptr, nullptr, nullptr, nullptr nullptr, nullptr, nullptr, nullptr
}; };
static const JSClass global_class = {
"global", JSCLASS_GLOBAL_FLAGS,
&global_ops
};
static JSObject * static JSObject *
smjs_get_global_object(void) smjs_get_global_object(void)
{ {
@ -30,9 +33,13 @@ smjs_get_global_object(void)
JSAutoCompartment *acc = NULL; JSAutoCompartment *acc = NULL;
JSAutoRequest ar(smjs_ctx); JSAutoRequest ar(smjs_ctx);
RootedObject jsobj(smjs_ctx); JS::CompartmentOptions opts;
jsobj = JS_NewGlobalObject(smjs_ctx, (JSClass *) &global_class, NULL, JS::DontFireOnNewGlobalHook); if (!JS::InitSelfHostedCode(smjs_ctx)) {
return NULL;
}
JS::RootedObject jsobj(smjs_ctx, JS_NewGlobalObject(smjs_ctx, (JSClass *) &global_class, NULL, JS::DontFireOnNewGlobalHook, opts));
if (!jsobj) return NULL; if (!jsobj) return NULL;

View File

@ -17,15 +17,19 @@ static bool smjs_globhist_item_set_property(JSContext *ctx, JS::HandleObject hob
static void smjs_globhist_item_finalize(JSFreeOp *op, JSObject *obj); static void smjs_globhist_item_finalize(JSFreeOp *op, JSObject *obj);
static const JSClass smjs_globhist_item_class = { static const JSClassOps smjs_globhist_item_ops = {
"global_history_item",
JSCLASS_HAS_PRIVATE, /* struct global_history_item * */
JS_PropertyStub, nullptr, JS_PropertyStub, nullptr,
smjs_globhist_item_get_property, smjs_globhist_item_set_property, smjs_globhist_item_get_property, smjs_globhist_item_set_property,
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
smjs_globhist_item_finalize, smjs_globhist_item_finalize,
}; };
static const JSClass smjs_globhist_item_class = {
"global_history_item",
JSCLASS_HAS_PRIVATE, /* struct global_history_item * */
&smjs_globhist_item_ops
};
/* @smjs_globhist_item_class.finalize */ /* @smjs_globhist_item_class.finalize */
static void static void
smjs_globhist_item_finalize(JSFreeOp *op, JSObject *obj) smjs_globhist_item_finalize(JSFreeOp *op, JSObject *obj)
@ -243,13 +247,17 @@ ret_null:
return true; return true;
} }
static const JSClass smjs_globhist_class = { static const JSClassOps smjs_globhist_ops = {
"global_history", 0,
JS_PropertyStub, nullptr, JS_PropertyStub, nullptr,
smjs_globhist_get_property, JS_StrictPropertyStub, smjs_globhist_get_property, JS_StrictPropertyStub,
nullptr, nullptr, nullptr, nullptr nullptr, nullptr, nullptr, nullptr
}; };
static const JSClass smjs_globhist_class = {
"global_history", 0,
&smjs_globhist_ops
};
static JSObject * static JSObject *
smjs_get_globhist_object(void) smjs_get_globhist_object(void)
{ {

View File

@ -27,8 +27,8 @@ script_hook_url(va_list ap, void *data)
unsigned char **url = va_arg(ap, unsigned char **); unsigned char **url = va_arg(ap, unsigned char **);
struct session *ses = va_arg(ap, struct session *); struct session *ses = va_arg(ap, struct session *);
enum evhook_status ret = EVENT_HOOK_STATUS_NEXT; enum evhook_status ret = EVENT_HOOK_STATUS_NEXT;
JS::Value args[3], rval; JS::Value args[3];
JS::RootedValue r_rval(smjs_ctx, rval); JS::RootedValue r_rval(smjs_ctx);
if (*url == NULL) return EVENT_HOOK_STATUS_NEXT; if (*url == NULL) return EVENT_HOOK_STATUS_NEXT;
@ -59,12 +59,14 @@ script_hook_pre_format_html(va_list ap, void *data)
struct cache_entry *cached = va_arg(ap, struct cache_entry *); struct cache_entry *cached = va_arg(ap, struct cache_entry *);
enum evhook_status ret = EVENT_HOOK_STATUS_NEXT; enum evhook_status ret = EVENT_HOOK_STATUS_NEXT;
JSObject *cache_entry_object, *view_state_object = NULL; JSObject *cache_entry_object, *view_state_object = NULL;
JS::Value args[4], rval; JS::Value args[4];
JS::RootedValue r_rval(smjs_ctx, rval); JS::RootedValue r_rval(smjs_ctx);
evhook_use_params(ses && cached); evhook_use_params(ses && cached);
if (!smjs_ctx || !cached->length) goto end; if (!smjs_ctx || !cached->length) {
goto end;
}
smjs_ses = ses; smjs_ses = ses;
@ -81,9 +83,10 @@ script_hook_pre_format_html(va_list ap, void *data)
args[3].setObject(*view_state_object); args[3].setObject(*view_state_object);
if (true == smjs_invoke_elinks_object_method("preformat_html", if (true == smjs_invoke_elinks_object_method("preformat_html",
2, args, &r_rval)) 2, args, &r_rval)) {
if (false == r_rval.toBoolean()) if (false == r_rval.toBoolean())
ret = EVENT_HOOK_STATUS_LAST; ret = EVENT_HOOK_STATUS_LAST;
}
end: end:
smjs_ses = NULL; smjs_ses = NULL;

View File

@ -17,14 +17,18 @@ static bool keymap_get_property(JSContext *ctx, JS::HandleObject hobj, JS::Handl
static bool keymap_set_property(JSContext *ctx, JS::HandleObject hobj, JS::HandleId hid, JS::MutableHandleValue hvp); static bool keymap_set_property(JSContext *ctx, JS::HandleObject hobj, JS::HandleId hid, JS::MutableHandleValue hvp);
static void keymap_finalize(JSFreeOp *op, JSObject *obj); static void keymap_finalize(JSFreeOp *op, JSObject *obj);
static const JSClass keymap_class = { static const JSClassOps keymap_ops = {
"keymap",
JSCLASS_HAS_PRIVATE, /* int * */
JS_PropertyStub, nullptr, JS_PropertyStub, nullptr,
keymap_get_property, keymap_set_property, keymap_get_property, keymap_set_property,
nullptr, nullptr, nullptr, keymap_finalize, nullptr, nullptr, nullptr, keymap_finalize,
}; };
static const JSClass keymap_class = {
"keymap",
JSCLASS_HAS_PRIVATE, /* int * */
&keymap_ops
};
/* @keymap_class.getProperty */ /* @keymap_class.getProperty */
static bool static bool
keymap_get_property(JSContext *ctx, JS::HandleObject hobj, JS::HandleId hid, JS::MutableHandleValue hvp) keymap_get_property(JSContext *ctx, JS::HandleObject hobj, JS::HandleId hid, JS::MutableHandleValue hvp)
@ -220,14 +224,18 @@ smjs_get_keymap_object(enum keymap_id keymap_id)
return keymap_object; return keymap_object;
} }
static const JSClass keymaps_hash_class = { static const JSClassOps keymap_hash_ops = {
"keymaps_hash",
JSCLASS_HAS_PRIVATE,
JS_PropertyStub, nullptr, JS_PropertyStub, nullptr,
JS_PropertyStub, JS_StrictPropertyStub, JS_PropertyStub, JS_StrictPropertyStub,
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
}; };
static const JSClass keymaps_hash_class = {
"keymaps_hash",
JSCLASS_HAS_PRIVATE,
&keymap_hash_ops
};
static JSObject * static JSObject *
smjs_get_keymap_hash_object(void) smjs_get_keymap_hash_object(void)
{ {

View File

@ -35,24 +35,32 @@ static bool session_set_property(JSContext *ctx, JS::HandleObject hobj, JS::Hand
static void session_finalize(JSFreeOp *op, JSObject *obj); static void session_finalize(JSFreeOp *op, JSObject *obj);
static bool session_construct(JSContext *ctx, unsigned int argc, JS::Value *rval); static bool session_construct(JSContext *ctx, unsigned int argc, JS::Value *rval);
static const JSClass session_class = { static const JSClassOps session_ops = {
"session",
JSCLASS_HAS_PRIVATE, /* struct session *; a weak reference */
JS_PropertyStub, nullptr, JS_PropertyStub, nullptr,
session_get_property, session_set_property, session_get_property, session_set_property,
nullptr, nullptr, nullptr, session_finalize, nullptr, nullptr, nullptr, session_finalize,
NULL, NULL, NULL, session_construct NULL, NULL, NULL, session_construct
}; };
static const JSClass session_class = {
"session",
JSCLASS_HAS_PRIVATE, /* struct session *; a weak reference */
&session_ops
};
static bool smjs_location_array_get_property(JSContext *ctx, JS::HandleObject hobj, JS::HandleId hid, JS::MutableHandleValue hvp); static bool smjs_location_array_get_property(JSContext *ctx, JS::HandleObject hobj, JS::HandleId hid, JS::MutableHandleValue hvp);
static void smjs_location_array_finalize(JSFreeOp *op, JSObject *obj); static void smjs_location_array_finalize(JSFreeOp *op, JSObject *obj);
static const JSClassOps location_array_ops = {
JS_PropertyStub, nullptr,
smjs_location_array_get_property, JS_StrictPropertyStub,
nullptr, nullptr, nullptr, smjs_location_array_finalize,
};
static const JSClass location_array_class = { static const JSClass location_array_class = {
"location_array", "location_array",
JSCLASS_HAS_PRIVATE, /* struct session *; a weak reference */ JSCLASS_HAS_PRIVATE, /* struct session *; a weak reference */
JS_PropertyStub, nullptr, &location_array_ops
smjs_location_array_get_property, JS_StrictPropertyStub,
nullptr, nullptr, nullptr, smjs_location_array_finalize,
}; };
/* location_array_class is the class for array object, the elements of which /* location_array_class is the class for array object, the elements of which
@ -1076,14 +1084,18 @@ session_array_get_property(JSContext *ctx, JS::HandleObject hobj, JS::HandleId h
return true; return true;
} }
static const JSClass session_array_class = { static const JSClassOps session_array_ops = {
"session_array",
JSCLASS_HAS_PRIVATE, /* struct terminal *term; a weak reference */
JS_PropertyStub, nullptr, JS_PropertyStub, nullptr,
session_array_get_property, JS_StrictPropertyStub, session_array_get_property, JS_StrictPropertyStub,
nullptr, nullptr, nullptr, nullptr nullptr, nullptr, nullptr, nullptr
}; };
static const JSClass session_array_class = {
"session_array",
JSCLASS_HAS_PRIVATE, /* struct terminal *term; a weak reference */
&session_array_ops
};
JSObject * JSObject *
smjs_get_session_array_object(struct terminal *term) smjs_get_session_array_object(struct terminal *term)
{ {

View File

@ -20,14 +20,18 @@
static bool terminal_get_property(JSContext *ctx, JS::HandleObject hobj, JS::HandleId hid, JS::MutableHandleValue hvp); static bool terminal_get_property(JSContext *ctx, JS::HandleObject hobj, JS::HandleId hid, JS::MutableHandleValue hvp);
static void terminal_finalize(JSFreeOp *op, JSObject *obj); static void terminal_finalize(JSFreeOp *op, JSObject *obj);
static const JSClass terminal_class = { static const JSClassOps terminal_ops = {
"terminal",
JSCLASS_HAS_PRIVATE, /* struct terminal *; a weak refernce */
JS_PropertyStub, nullptr, JS_PropertyStub, nullptr,
terminal_get_property, JS_StrictPropertyStub, terminal_get_property, JS_StrictPropertyStub,
nullptr, nullptr, nullptr, terminal_finalize nullptr, nullptr, nullptr, terminal_finalize
}; };
static const JSClass terminal_class = {
"terminal",
JSCLASS_HAS_PRIVATE, /* struct terminal *; a weak refernce */
&terminal_ops
};
enum terminal_prop { enum terminal_prop {
TERMINAL_TAB, TERMINAL_TAB,
}; };
@ -187,14 +191,18 @@ terminal_array_get_property(JSContext *ctx, JS::HandleObject hobj, JS::HandleId
; ;
} }
static const JSClass terminal_array_class = { static const JSClassOps terminal_array_ops = {
"terminal_array",
0,
JS_PropertyStub, nullptr, JS_PropertyStub, nullptr,
terminal_array_get_property, JS_StrictPropertyStub, terminal_array_get_property, JS_StrictPropertyStub,
nullptr, nullptr, nullptr, nullptr nullptr, nullptr, nullptr, nullptr
}; };
static const JSClass terminal_array_class = {
"terminal_array",
0,
&terminal_array_ops
};
/** Return an SMJS object that scripts can use an array to get terminal /** Return an SMJS object that scripts can use an array to get terminal
* objects. */ * objects. */
static JSObject * static JSObject *

View File

@ -24,14 +24,18 @@ static bool view_state_get_property(JSContext *ctx, JS::HandleObject hobj, JS::H
static bool view_state_set_property(JSContext *ctx, JS::HandleObject hobj, JS::HandleId hid, JS::MutableHandleValue hvp); static bool view_state_set_property(JSContext *ctx, JS::HandleObject hobj, JS::HandleId hid, JS::MutableHandleValue hvp);
static void view_state_finalize(JSFreeOp *op, JSObject *obj); static void view_state_finalize(JSFreeOp *op, JSObject *obj);
static const JSClass view_state_class = { static const JSClassOps view_state_ops = {
"view_state",
JSCLASS_HAS_PRIVATE, /* struct view_state * */
JS_PropertyStub, nullptr, JS_PropertyStub, nullptr,
view_state_get_property, view_state_set_property, view_state_get_property, view_state_set_property,
nullptr, nullptr, nullptr, view_state_finalize nullptr, nullptr, nullptr, view_state_finalize
}; };
static const JSClass view_state_class = {
"view_state",
JSCLASS_HAS_PRIVATE, /* struct view_state * */
&view_state_ops
};
/* Tinyids of properties. Use negative values to distinguish these /* Tinyids of properties. Use negative values to distinguish these
* from array indexes (even though this object has no array elements). * from array indexes (even though this object has no array elements).
* ECMAScript code should not use these directly as in view_state[-1]; * ECMAScript code should not use these directly as in view_state[-1];
@ -255,22 +259,22 @@ smjs_get_view_state_object(struct view_state *vs)
} }
static bool static bool
smjs_elinks_get_view_state(JSContext *ctx, JS::HandleObject hobj, JS::HandleId hid, JS::MutableHandleValue hvp) smjs_elinks_get_view_state(JSContext *ctx, unsigned int argc, JS::Value *vp)
{ {
JSObject *vs_obj; JS::CallArgs args = CallArgsFromVp(argc, vp);
struct view_state *vs; JS::RootedObject hobj(ctx, &args.thisv().toObject());
hvp.setNull(); args.rval().setNull();
if (!smjs_ses || !have_location(smjs_ses)) return true; if (!smjs_ses || !have_location(smjs_ses)) return true;
vs = &cur_loc(smjs_ses)->vs; struct view_state *vs = &cur_loc(smjs_ses)->vs;
if (!vs) return true; if (!vs) return true;
vs_obj = smjs_get_view_state_object(vs); JSObject *vs_obj = smjs_get_view_state_object(vs);
if (!vs_obj) return true; if (!vs_obj) return true;
hvp.setObject(*vs_obj); args.rval().setObject(*vs_obj);
return true; return true;
} }
@ -308,6 +312,6 @@ smjs_init_view_state_interface(void)
JS::RootedObject r_smjs_elinks_object(smjs_ctx, smjs_elinks_object); JS::RootedObject r_smjs_elinks_object(smjs_ctx, smjs_elinks_object);
JS_DefineProperty(smjs_ctx, r_smjs_elinks_object, "vs", (int32_t)0, JS_DefineProperty(smjs_ctx, r_smjs_elinks_object, "vs", (int32_t)0,
(unsigned int)(JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_READONLY), smjs_elinks_get_view_state, JS_StrictPropertyStub (unsigned int)(JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_READONLY), smjs_elinks_get_view_state, nullptr/*JS_StrictPropertyStub*/
); );
} }

View File

@ -252,7 +252,7 @@ find_form_state(struct document_view *doc_view, struct el_form_control *fc)
if (n >= vs->form_info_len) { if (n >= vs->form_info_len) {
int nn = n + 1; int nn = n + 1;
#ifdef CONFIG_ECMASCRIPT #ifdef CONFIG_ECMASCRIPT_SMJS
const struct form_state *const old_form_info = vs->form_info; const struct form_state *const old_form_info = vs->form_info;
#endif #endif
@ -261,7 +261,7 @@ find_form_state(struct document_view *doc_view, struct el_form_control *fc)
vs->form_info = fs; vs->form_info = fs;
vs->form_info_len = nn; vs->form_info_len = nn;
#ifdef CONFIG_ECMASCRIPT #ifdef CONFIG_ECMASCRIPT_SMJS
/* TODO: Standard C does not allow this comparison; /* TODO: Standard C does not allow this comparison;
* if the memory to which old_form_info pointed has * if the memory to which old_form_info pointed has
* been freed, then the value of the pointer itself is * been freed, then the value of the pointer itself is
@ -275,7 +275,7 @@ find_form_state(struct document_view *doc_view, struct el_form_control *fc)
for (nn = 0; nn < vs->form_info_len; nn++) for (nn = 0; nn < vs->form_info_len; nn++)
ecmascript_moved_form_state(&vs->form_info[nn]); ecmascript_moved_form_state(&vs->form_info[nn]);
} }
#endif /* CONFIG_ECMASCRIPT */ #endif /* CONFIG_ECMASCRIPT_SMJS */
} }
fs = &vs->form_info[n]; fs = &vs->form_info[n];
@ -353,7 +353,7 @@ find_form_by_form_view(struct document *document, struct form_view *fv)
void void
done_form_state(struct form_state *fs) done_form_state(struct form_state *fs)
{ {
#ifdef CONFIG_ECMASCRIPT #ifdef CONFIG_ECMASCRIPT_SMJS
ecmascript_detach_form_state(fs); ecmascript_detach_form_state(fs);
#endif #endif
mem_free_if(fs->value); mem_free_if(fs->value);
@ -365,7 +365,7 @@ done_form_state(struct form_state *fs)
void void
done_form_view(struct form_view *fv) done_form_view(struct form_view *fv)
{ {
#ifdef CONFIG_ECMASCRIPT #ifdef CONFIG_ECMASCRIPT_SMJS
ecmascript_detach_form_view(fv); ecmascript_detach_form_view(fv);
#endif #endif
mem_free(fv); mem_free(fv);

View File

@ -52,7 +52,7 @@
static int static int
current_link_evhook(struct document_view *doc_view, enum script_event_hook_type type) current_link_evhook(struct document_view *doc_view, enum script_event_hook_type type)
{ {
#ifdef CONFIG_ECMASCRIPT #ifdef CONFIG_ECMASCRIPT_SMJS
struct link *link; struct link *link;
struct script_event_hook *evhook; struct script_event_hook *evhook;
@ -915,7 +915,7 @@ call_onsubmit_and_submit(struct session *ses, struct document_view *doc_view,
assert(fc->form); /* regardless of whether there is a FORM element */ assert(fc->form); /* regardless of whether there is a FORM element */
if_assert_failed return 0; if_assert_failed return 0;
#ifdef CONFIG_ECMASCRIPT #ifdef CONFIG_ECMASCRIPT_SMJS
/* If the form has multiple submit buttons, this does not /* If the form has multiple submit buttons, this does not
* explicitly tell the ECMAScript code which of them was * explicitly tell the ECMAScript code which of them was
* pressed. W3C DOM Level 3 doesn't seem to include such a * pressed. W3C DOM Level 3 doesn't seem to include such a
@ -952,7 +952,7 @@ call_onsubmit_and_submit(struct session *ses, struct document_view *doc_view,
if (!res) return 1; if (!res) return 1;
} }
} }
#endif /* CONFIG_ECMASCRIPT */ #endif /* CONFIG_ECMASCRIPT_SMJS */
uri = get_form_uri(ses, doc_view, fc); uri = get_form_uri(ses, doc_view, fc);
if (!uri) return 0; if (!uri) return 0;

View File

@ -38,7 +38,7 @@ init_vs(struct view_state *vs, struct uri *uri, int plain)
vs->plain = plain; vs->plain = plain;
vs->uri = uri ? get_uri_reference(uri) : NULL; vs->uri = uri ? get_uri_reference(uri) : NULL;
vs->did_fragment = !uri->fragmentlen; vs->did_fragment = !uri->fragmentlen;
#ifdef CONFIG_ECMASCRIPT #ifdef CONFIG_ECMASCRIPT_SMJS
/* If we ever get to render this vs, give it an interpreter. */ /* If we ever get to render this vs, give it an interpreter. */
vs->ecmascript_fragile = 1; vs->ecmascript_fragile = 1;
#endif #endif
@ -67,7 +67,7 @@ destroy_vs(struct view_state *vs, int blast_ecmascript)
} }
if (vs->uri) done_uri(vs->uri); if (vs->uri) done_uri(vs->uri);
#ifdef CONFIG_ECMASCRIPT #ifdef CONFIG_ECMASCRIPT_SMJS
if (blast_ecmascript && vs->ecmascript) if (blast_ecmascript && vs->ecmascript)
ecmascript_put_interpreter(vs->ecmascript); ecmascript_put_interpreter(vs->ecmascript);
#endif #endif
@ -87,7 +87,7 @@ copy_vs(struct view_state *dst, struct view_state *src)
/* We do not copy ecmascript stuff around since it's specific for /* We do not copy ecmascript stuff around since it's specific for
* a single location, offsprings (followups and so) nedd their own. */ * a single location, offsprings (followups and so) nedd their own. */
#ifdef CONFIG_ECMASCRIPT #ifdef CONFIG_ECMASCRIPT_SMJS
dst->ecmascript = NULL; dst->ecmascript = NULL;
/* If we ever get to render this vs, give it an interpreter. */ /* If we ever get to render this vs, give it an interpreter. */
dst->ecmascript_fragile = 1; dst->ecmascript_fragile = 1;
@ -131,7 +131,7 @@ copy_vs(struct view_state *dst, struct view_state *src)
struct form_state *srcfs = &src->form_info[i]; struct form_state *srcfs = &src->form_info[i];
struct form_state *dstfs = &dst->form_info[i]; struct form_state *dstfs = &dst->form_info[i];
#ifdef CONFIG_ECMASCRIPT #ifdef CONFIG_ECMASCRIPT_SMJS
dstfs->ecmascript_obj = NULL; dstfs->ecmascript_obj = NULL;
#endif #endif
if (srcfs->value) if (srcfs->value)

View File

@ -6,7 +6,7 @@ function scrollText() {
tekst = tekst.substring(1, tekst.length) + znak; tekst = tekst.substring(1, tekst.length) + znak;
return tekst.substring(0, 80); return tekst.substring(0, 80);
} }
function scroll () { function scroll() {
document.title = scrollText(); document.title = scrollText();
setTimeout("scroll()", 100); setTimeout("scroll()", 100);
} }