1
0
mirror of https://github.com/rkd77/elinks.git synced 2024-09-27 02:56:18 -04:00

[spidermonkey] Some random changes.

This commit is contained in:
Witold Filipczyk 2020-11-15 17:55:58 +01:00
parent 6171e286bd
commit b0ced9308b
5 changed files with 38 additions and 436 deletions

View File

@ -53,35 +53,29 @@ JSObject *spidermonkey_InitClass(JSContext *cx, JSObject *obj,
JSPropertySpec *static_ps,
const spidermonkeyFunctionSpec *static_fs);
static void undef_to_jsval(JSContext *ctx, JS::Value *vp);
static unsigned char *jsval_to_string(JSContext *ctx, JS::Value *vp);
static unsigned char *jsid_to_string(JSContext *ctx, jsid *id);
static unsigned char *jsid_to_string(JSContext *ctx, JS::HandleId hid);
/* Inline functions */
static inline void
undef_to_jsval(JSContext *ctx, JS::Value *vp)
{
*vp = JS::NullValue();
}
static inline unsigned char *
jsval_to_string(JSContext *ctx, JS::Value *vp)
jsval_to_string(JSContext *ctx, JS::HandleValue hvp)
{
JS::RootedValue r_vp(ctx, *vp);
JSString *str = r_vp.toString();
// JS::RootedValue r_vp(ctx, *vp);
JSString *str = hvp.toString();
//JS::RootedString r_str(ctx, str);
return empty_string_or_(JS_EncodeString(ctx, str));
}
static inline unsigned char *
jsid_to_string(JSContext *ctx, jsid *id)
jsid_to_string(JSContext *ctx, JS::HandleId hid)
{
JS::RootedValue v(ctx);
/* TODO: check returned value */
JS_IdToValue(ctx, *id, &v);
return jsval_to_string(ctx, v.address());
JS_IdToValue(ctx, hid, &v);
return jsval_to_string(ctx, v);
}
#define ELINKS_CAST_PROP_PARAMS JSObject *obj = (hobj.get()); \

View File

@ -353,9 +353,6 @@ JSPropertySpec document_props[] = {
static bool
document_get_property(JSContext *ctx, JS::HandleObject hobj, JS::HandleId hid, JS::MutableHandleValue hvp)
{
ELINKS_CAST_PROP_PARAMS
jsid id = hid.get();
JS::RootedObject parent_win(ctx); /* instance of @window_class */
struct view_state *vs;
struct document_view *doc_view;
@ -363,7 +360,7 @@ document_get_property(JSContext *ctx, JS::HandleObject hobj, JS::HandleId hid, J
struct form *form;
unsigned char *string;
JSClass* classPtr = JS_GetClass(obj);
JSClass* classPtr = JS_GetClass(hobj);
if (classPtr != &document_class)
return false;
@ -376,13 +373,17 @@ document_get_property(JSContext *ctx, JS::HandleObject hobj, JS::HandleId hid, J
&window_class, NULL);
doc_view = vs->doc_view;
document = doc_view->document;
string = jsid_to_string(ctx, &id);
if (!JSID_IS_STRING(hid)) {
return true;
}
string = jsid_to_string(ctx, hid);
foreach (form, document->forms) {
if (!form->name || c_strcasecmp(string, form->name))
continue;
object_to_jsval(ctx, vp, get_form_object(ctx, obj, find_form_view(doc_view, form)));
hvp.setObject(*get_form_object(ctx, hobj, find_form_view(doc_view, form)));
break;
}
@ -417,7 +418,7 @@ document_write_do(JSContext *ctx, unsigned int argc, JS::Value *rval, int newlin
int i = 0;
for (; i < argc; ++i) {
unsigned char *code = jsval_to_string(ctx, args[i].address());
unsigned char *code = jsval_to_string(ctx, args[i]);
add_to_string(ret, code);
}

View File

@ -1439,9 +1439,6 @@ input_get_form_state(JSContext *ctx, JSObject *jsinput)
static bool
input_get_property(JSContext *ctx, JS::HandleObject hobj, JS::HandleId hid, JS::MutableHandleValue hvp)
{
ELINKS_CAST_PROP_PARAMS
jsid id = hid.get();
JS::RootedObject parent_form(ctx); /* instance of @form_class */
JS::RootedObject parent_doc(ctx); /* instance of @document_class */
struct view_state *vs;
@ -1469,125 +1466,8 @@ input_get_property(JSContext *ctx, JS::HandleObject hobj, JS::HandleId hid, JS::
// parent_win = js::GetGlobalForObjectCrossCompartment(parent_doc);
// assert(JS_InstanceOf(ctx, parent_win, &window_class, NULL));
// if_assert_failed return false;
JS::RootedObject parent_win(ctx, js::GetGlobalForObjectCrossCompartment(hobj));
hvp.setUndefined();
vs = JS_GetInstancePrivate(ctx, parent_win,
&window_class, NULL);
doc_view = vs->doc_view;
document = doc_view->document;
fs = input_get_form_state(ctx, hobj);
if (!fs) return false; /* detached */
fc = find_form_control(document, fs);
assert(fc);
assert(fc->form && fs);
if (!JSID_IS_INT(id))
return true;
linknum = get_form_control_link(document, fc);
/* Hiddens have no link. */
if (linknum >= 0) link = &document->links[linknum];
undef_to_jsval(ctx, vp);
switch (JSID_TO_INT(id)) {
case JSP_INPUT_ACCESSKEY:
{
JSString *keystr;
if (!link) break;
if (!link->accesskey) {
*vp = JS_GetEmptyStringValue(ctx);
} else {
keystr = unicode_to_jsstring(ctx, link->accesskey);
if (keystr)
*vp = JS::StringValue(keystr);
else
return false;
}
break;
}
case JSP_INPUT_ALT:
string_to_jsval(ctx, vp, fc->alt);
break;
case JSP_INPUT_CHECKED:
boolean_to_jsval(ctx, vp, fs->state);
break;
case JSP_INPUT_DEFAULT_CHECKED:
boolean_to_jsval(ctx, vp, fc->default_state);
break;
case JSP_INPUT_DEFAULT_VALUE:
/* FIXME (bug 805): convert from the charset of the document */
string_to_jsval(ctx, vp, fc->default_value);
break;
case JSP_INPUT_DISABLED:
/* FIXME: <input readonly disabled> --pasky */
boolean_to_jsval(ctx, vp, fc->mode == FORM_MODE_DISABLED);
break;
case JSP_INPUT_FORM:
object_to_jsval(ctx, vp, parent_form);
break;
case JSP_INPUT_MAX_LENGTH:
int_to_jsval(ctx, vp, fc->maxlength);
break;
case JSP_INPUT_NAME:
string_to_jsval(ctx, vp, fc->name);
break;
case JSP_INPUT_READONLY:
/* FIXME: <input readonly disabled> --pasky */
boolean_to_jsval(ctx, vp, fc->mode == FORM_MODE_READONLY);
break;
case JSP_INPUT_SIZE:
int_to_jsval(ctx, vp, fc->size);
break;
case JSP_INPUT_SRC:
if (link && link->where_img)
string_to_jsval(ctx, vp, link->where_img);
break;
case JSP_INPUT_TABINDEX:
if (link)
/* FIXME: This is WRONG. --pasky */
int_to_jsval(ctx, vp, link->number);
break;
case JSP_INPUT_TYPE:
{
unsigned char *s = NULL;
switch (fc->type) {
case FC_TEXT: s = "text"; break;
case FC_PASSWORD: s = "password"; break;
case FC_FILE: s = "file"; break;
case FC_CHECKBOX: s = "checkbox"; break;
case FC_RADIO: s = "radio"; break;
case FC_SUBMIT: s = "submit"; break;
case FC_IMAGE: s = "image"; break;
case FC_RESET: s = "reset"; break;
case FC_BUTTON: s = "button"; break;
case FC_HIDDEN: s = "hidden"; break;
case FC_SELECT: s = "select"; break;
default: INTERNAL("input_get_property() upon a non-input item."); break;
}
string_to_jsval(ctx, vp, s);
break;
}
case JSP_INPUT_VALUE:
string_to_jsval(ctx, vp, fs->value);
break;
case JSP_INPUT_SELECTED_INDEX:
if (fc->type == FC_SELECT) int_to_jsval(ctx, vp, fs->state);
break;
default:
/* Unrecognized integer property ID; someone is using
* the object as an array. SMJS builtin classes (e.g.
* js_RegExpClass) just return true in this case
* and leave *@vp unchanged. Do the same here.
* (Actually not quite the same, as we already used
* @undef_to_jsval.) */
break;
}
return true;
}
@ -1624,90 +1504,6 @@ input_set_property(JSContext *ctx, JS::HandleObject hobj, JS::HandleId hid, JS::
// parent_win = js::GetGlobalForObjectCrossCompartment(parent_doc);
// assert(JS_InstanceOf(ctx, parent_win, &window_class, NULL));
// if_assert_failed return false;
JS::RootedObject parent_win(ctx, js::GetGlobalForObjectCrossCompartment(hobj));
vs = JS_GetInstancePrivate(ctx, parent_win,
&window_class, NULL);
doc_view = vs->doc_view;
document = doc_view->document;
fs = input_get_form_state(ctx, hobj);
if (!fs) return false; /* detached */
fc = find_form_control(document, fs);
assert(fc);
assert(fc->form && fs);
if (!JSID_IS_INT(id))
return true;
linknum = get_form_control_link(document, fc);
/* Hiddens have no link. */
if (linknum >= 0) link = &document->links[linknum];
switch (JSID_TO_INT(id)) {
case JSP_INPUT_ACCESSKEY:
accesskey = jsval_to_accesskey(ctx, hvp);
if (accesskey == UCS_NO_CHAR)
return false;
else if (link)
link->accesskey = accesskey;
break;
case JSP_INPUT_ALT:
mem_free_set(&fc->alt, stracpy(jsval_to_string(ctx, vp)));
break;
case JSP_INPUT_CHECKED:
if (fc->type != FC_CHECKBOX && fc->type != FC_RADIO)
break;
fs->state = jsval_to_boolean(ctx, vp);
break;
case JSP_INPUT_DISABLED:
/* FIXME: <input readonly disabled> --pasky */
fc->mode = (jsval_to_boolean(ctx, vp) ? FORM_MODE_DISABLED
: fc->mode == FORM_MODE_READONLY ? FORM_MODE_READONLY
: FORM_MODE_NORMAL);
break;
case JSP_INPUT_MAX_LENGTH:
fc->maxlength = hvp.toInt32();
break;
case JSP_INPUT_NAME:
mem_free_set(&fc->name, stracpy(jsval_to_string(ctx, vp)));
break;
case JSP_INPUT_READONLY:
/* FIXME: <input readonly disabled> --pasky */
fc->mode = (jsval_to_boolean(ctx, vp) ? FORM_MODE_READONLY
: fc->mode == FORM_MODE_DISABLED ? FORM_MODE_DISABLED
: FORM_MODE_NORMAL);
break;
case JSP_INPUT_SRC:
if (link) {
mem_free_set(&link->where_img, stracpy(jsval_to_string(ctx, vp)));
}
break;
case JSP_INPUT_VALUE:
if (fc->type == FC_FILE)
break; /* A huge security risk otherwise. */
mem_free_set(&fs->value, stracpy(jsval_to_string(ctx, vp)));
if (fc->type == FC_TEXT || fc->type == FC_PASSWORD)
fs->state = strlen(fs->value);
break;
case JSP_INPUT_SELECTED_INDEX:
if (fc->type == FC_SELECT) {
int item = hvp.toInt32();
if (item >= 0 && item < fc->nvalues) {
fs->state = item;
mem_free_set(&fs->value, stracpy(fc->values[item]));
}
}
break;
default:
/* Unrecognized integer property ID; someone is using
* the object as an array. SMJS builtin classes (e.g.
* js_RegExpClass) just return true in this case.
* Do the same here. */
return true;
}
return true;
}
@ -2052,7 +1848,7 @@ form_elements_get_property(JSContext *ctx, JS::HandleObject hobj, JS::HandleId h
hvp.setUndefined();
switch (JSID_TO_INT(id)) {
switch (JSID_TO_INT(hid)) {
case JSP_FORM_ELEMENTS_LENGTH:
hvp.setInt32(list_size(&form->items));
break;
@ -2333,9 +2129,9 @@ form_get_property(JSContext *ctx, JS::HandleObject hobj, JS::HandleId hid, JS::M
assert(form);
if (JSID_IS_STRING(id)) {
if (JSID_IS_STRING(hid)) {
struct el_form_control *fc;
unsigned char *string = jsid_to_string(ctx, &id);
unsigned char *string = jsid_to_string(ctx, hid);
foreach (fc, form->items) {
JSObject *fcobj = NULL;
@ -2345,94 +2141,23 @@ form_get_property(JSContext *ctx, JS::HandleObject hobj, JS::HandleId hid, JS::M
&& (!fc->name || c_strcasecmp(string, fc->name)))
continue;
undef_to_jsval(ctx, vp);
hvp.setUndefined();
fs = find_form_state(doc_view, fc);
if (fs) {
fcobj = get_form_control_object(ctx, fc->type, fs);
if (fcobj)
object_to_jsval(ctx, vp, fcobj);
if (fcobj) {
hvp.setObject(*fcobj);
}
}
break;
}
return true;
}
if (!JSID_IS_INT(id))
if (!JSID_IS_INT(hid))
return true;
undef_to_jsval(ctx, vp);
switch (JSID_TO_INT(id)) {
case JSP_FORM_ACTION:
string_to_jsval(ctx, vp, form->action);
break;
case JSP_FORM_ELEMENTS:
{
/* jsform ('form') is form_elements' parent; who knows is that's correct */
JSObject *jsform_elems = JS_NewObjectWithGivenProto(ctx, &form_elements_class, hobj);
JS::RootedObject r_jsform_elems(ctx, jsform_elems);
JS_DefineProperties(ctx, r_jsform_elems, (JSPropertySpec *) form_elements_props);
spidermonkey_DefineFunctions(ctx, jsform_elems,
form_elements_funcs);
object_to_jsval(ctx, vp, jsform_elems);
/* SM will cache this property value for us so we create this
* just once per form. */
}
break;
case JSP_FORM_ENCODING:
switch (form->method) {
case FORM_METHOD_GET:
case FORM_METHOD_POST:
string_to_jsval(ctx, vp, "application/x-www-form-urlencoded");
break;
case FORM_METHOD_POST_MP:
string_to_jsval(ctx, vp, "multipart/form-data");
break;
case FORM_METHOD_POST_TEXT_PLAIN:
string_to_jsval(ctx, vp, "text/plain");
break;
}
break;
case JSP_FORM_LENGTH:
int_to_jsval(ctx, vp, list_size(&form->items));
break;
case JSP_FORM_METHOD:
switch (form->method) {
case FORM_METHOD_GET:
string_to_jsval(ctx, vp, "GET");
break;
case FORM_METHOD_POST:
case FORM_METHOD_POST_MP:
case FORM_METHOD_POST_TEXT_PLAIN:
string_to_jsval(ctx, vp, "POST");
break;
}
break;
case JSP_FORM_NAME:
string_to_jsval(ctx, vp, form->name);
break;
case JSP_FORM_TARGET:
string_to_jsval(ctx, vp, form->target);
break;
default:
/* Unrecognized integer property ID; someone is using
* the object as an array. SMJS builtin classes (e.g.
* js_RegExpClass) just return true in this case
* and leave *@vp unchanged. Do the same here.
* (Actually not quite the same, as we already used
* @undef_to_jsval.) */
break;
}
hvp.setUndefined();
return true;
}
@ -3228,8 +2953,8 @@ forms_get_property(JSContext *ctx, JS::HandleObject hobj, JS::HandleId hid, JS::
&window_class, NULL);
doc_view = vs->doc_view;
if (JSID_IS_STRING(id)) {
unsigned char *string = jsid_to_string(ctx, &id);
if (JSID_IS_STRING(hid)) {
unsigned char *string = jsid_to_string(ctx, hid);
char *end;
strtoll(string, &end, 10);

View File

@ -7,9 +7,6 @@
static void string_to_jsval(JSContext *ctx, JS::Value *vp, unsigned char *string);
static void astring_to_jsval(JSContext *ctx, JS::Value *vp, unsigned char *string);
static void int_to_jsval(JSContext *ctx, JS::Value *vp, int number);
static void object_to_jsval(JSContext *ctx, JS::Value *vp, JSObject *object);
static void boolean_to_jsval(JSContext *ctx, JS::Value *vp, int boolean);
static int jsval_to_boolean(JSContext *ctx, JS::Value *vp);
@ -34,25 +31,6 @@ astring_to_jsval(JSContext *ctx, JS::Value *vp, unsigned char *string)
mem_free_if(string);
}
static inline void
int_to_jsval(JSContext *ctx, JS::Value *vp, int number)
{
*vp = JS::Int32Value(number);
}
static inline void
object_to_jsval(JSContext *ctx, JS::Value *vp, JSObject *object)
{
*vp = JS::ObjectValue(*object);
}
static inline void
boolean_to_jsval(JSContext *ctx, JS::Value *vp, int boolean)
{
*vp = JS::BooleanValue(boolean);
}
static inline int
jsval_to_boolean(JSContext *ctx, JS::Value *vp)
{

View File

@ -134,8 +134,6 @@ find_child_frame(struct document_view *doc_view, struct frame_desc *tframe)
static bool
window_get_property(JSContext *ctx, JS::HandleObject hobj, JS::HandleId hid, JS::MutableHandleValue hvp)
{
jsid id = hid.get();
struct view_state *vs;
/* This can be called if @obj if not itself an instance of the
@ -150,9 +148,9 @@ window_get_property(JSContext *ctx, JS::HandleObject hobj, JS::HandleId hid, JS:
* location is then evaluated in string context, toString()
* is called which we overrode for that class below, so
* everything's fine. */
if (JSID_IS_STRING(id)) {
if (JSID_IS_STRING(hid)) {
struct document_view *doc_view = vs->doc_view;
JSObject *obj = try_resolve_frame(doc_view, jsid_to_string(ctx, &id));
JSObject *obj = try_resolve_frame(doc_view, jsid_to_string(ctx, hid));
/* TODO: Try other lookups (mainly element lookup) until
* something yields data. */
if (obj) {
@ -161,103 +159,11 @@ window_get_property(JSContext *ctx, JS::HandleObject hobj, JS::HandleId hid, JS:
return true;
}
if (!JSID_IS_INT(id))
if (!JSID_IS_INT(hid))
return true;
hvp.setUndefined();
switch (JSID_TO_INT(id)) {
case JSP_WIN_CLOSED:
/* TODO: It will be a major PITA to implement this properly.
* Well, perhaps not so much if we introduce reference tracking
* for (struct session)? Still... --pasky */
hvp.setBoolean(false);
break;
case JSP_WIN_SELF:
hvp.setObject(*hobj.get());
break;
case JSP_WIN_PARENT:
/* XXX: It would be nice if the following worked, yes.
* The problem is that we get called at the point where
* document.frame properties are going to be mostly NULL.
* But the problem is deeper because at that time we are
* yet building scrn_frames so our parent might not be there
* yet (XXX: is this true?). The true solution will be to just
* have struct document_view *(document_view.parent). --pasky */
/* FIXME: So now we alias window.parent to window.top, which is
* INCORRECT but works for the most common cases of just two
* frames. Better something than nothing. */
#if 0
{
/* This is horrible. */
struct document_view *doc_view = vs->doc_view;
struct session *ses = doc_view->session;
struct frame_desc *frame = doc_view->document->frame;
if (!ses->doc_view->document->frame_desc) {
INTERNAL("Looking for parent but there're no frames.");
break;
}
assert(frame);
doc_view = ses->doc_view;
if (find_child_frame(doc_view, frame))
goto found_parent;
foreach (doc_view, ses->scrn_frames) {
if (find_child_frame(doc_view, frame))
goto found_parent;
}
INTERNAL("Cannot find frame %s parent.",doc_view->name);
break;
found_parent:
some_domain_security_check();
if (doc_view->vs.ecmascript_fragile)
ecmascript_reset_state(&doc_view->vs);
assert(doc_view->ecmascript);
object_to_jsval(ctx, vp, JS_GetGlobalForScopeChain(doc_view->ecmascript->backend_data));
break;
}
#endif
case JSP_WIN_STATUS:
return false;
case JSP_WIN_TOP:
{
struct document_view *doc_view = vs->doc_view;
struct document_view *top_view = doc_view->session->doc_view;
JSObject *newjsframe;
assert(top_view && top_view->vs);
if (top_view->vs->ecmascript_fragile)
ecmascript_reset_state(top_view->vs);
if (!top_view->vs->ecmascript)
break;
newjsframe = JS::CurrentGlobalOrNull(top_view->vs->ecmascript->backend_data);
/* Keep this unrolled this way. Will have to check document.domain
* JS property. */
/* Note that this check is perhaps overparanoid. If top windows
* is alien but some other child window is not, we should still
* let the script walk thru. That'd mean moving the check to
* other individual properties in this switch. */
if (compare_uri(vs->uri, top_view->vs->uri, URI_HOST)) {
hvp.setObject(*newjsframe);
}
/* else */
/****X*X*X*** SECURITY VIOLATION! RED ALERT, SHIELDS UP! ***X*X*X****\
|* (Pasky was apparently looking at the Links2 JS code . ___ ^.^ *|
\* for too long.) `.(,_,)\o/ */
break;
}
default:
/* Unrecognized integer property ID; someone is using
* the object as an array. SMJS builtin classes (e.g.
* js_RegExpClass) just return true in this case
* and leave *@vp unchanged. Do the same here.
* (Actually not quite the same, as we already used
* @undef_to_jsval.) */
break;
}
return true;
}
@ -314,7 +220,6 @@ window_alert(JSContext *ctx, unsigned int argc, JS::Value *rval)
static bool
window_open(JSContext *ctx, unsigned int argc, JS::Value *rval)
{
JS::Value val;
JSObject *obj = JS_THIS_OBJECT(ctx, rval);
JS::RootedObject hobj(ctx, obj);
JS::CallArgs args = JS::CallArgsFromVp(argc, rval);
@ -356,7 +261,7 @@ window_open(JSContext *ctx, unsigned int argc, JS::Value *rval)
}
}
url = stracpy(jsval_to_string(ctx, args[0].address()));
url = stracpy(jsval_to_string(ctx, args[0]));
trim_chars(url, ' ', 0);
url2 = join_urls(doc_view->document->uri, url);
mem_free(url);
@ -364,7 +269,7 @@ window_open(JSContext *ctx, unsigned int argc, JS::Value *rval)
return true;
}
if (argc > 1) {
frame = stracpy(jsval_to_string(ctx, args[1].address()));
frame = stracpy(jsval_to_string(ctx, args[1]));
if (!frame) {
mem_free(url2);
return true;
@ -388,7 +293,7 @@ window_open(JSContext *ctx, unsigned int argc, JS::Value *rval)
deo->uri = get_uri_reference(uri);
deo->target = stracpy(frame);
register_bottom_half(delayed_goto_uri_frame, deo);
boolean_to_jsval(ctx, &val, 1);
args.rval().setBoolean(true);
goto end;
}
}
@ -399,7 +304,7 @@ window_open(JSContext *ctx, unsigned int argc, JS::Value *rval)
&& can_open_in_new(ses->tab->term)) {
open_uri_in_new_window(ses, uri, NULL, ENV_ANY,
CACHE_MODE_NORMAL, TASK_NONE);
boolean_to_jsval(ctx, &val, 1);
args.rval().setBoolean(true);
} else {
/* When opening a new tab, we might get rerendered, losing our
* context and triggerring a disaster, so postpone that. */
@ -409,9 +314,9 @@ window_open(JSContext *ctx, unsigned int argc, JS::Value *rval)
deo->ses = ses;
deo->uri = get_uri_reference(uri);
register_bottom_half(delayed_open, deo);
boolean_to_jsval(ctx, &val, 1);
args.rval().setBoolean(true);
} else {
undef_to_jsval(ctx, &val);
args.rval().setUndefined();
}
}
@ -419,7 +324,6 @@ end:
done_uri(uri);
mem_free_if(frame);
args.rval().set(val);
return true;
}
@ -443,7 +347,7 @@ window_setTimeout(JSContext *ctx, unsigned int argc, JS::Value *rval)
if (argc != 2)
return true;
code = jsval_to_string(ctx, args[0].address());
code = jsval_to_string(ctx, args[0]);
if (!*code)
return true;