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

952, 954: Finalize form_view.ecmascript_obj for SEE

This commit is contained in:
Kalle Olavi Niemitalo 2008-07-18 20:43:23 +03:00 committed by Kalle Olavi Niemitalo
parent c81e2051f8
commit ae8080b172
2 changed files with 96 additions and 15 deletions

View File

@ -7,7 +7,7 @@ struct string;
void *see_get_interpreter(struct ecmascript_interpreter *interpreter);
void see_put_interpreter(struct ecmascript_interpreter *interpreter);
#define see_detach_form_view(fv) ((fv)->ecmascript_obj = NULL)
void see_detach_form_view(struct form_view *fv);
void see_detach_form_state(struct form_state *fs);
void see_moved_form_state(struct form_state *fs);

View File

@ -77,6 +77,7 @@ static int form_canput(struct SEE_interpreter *, struct SEE_object *, struct SEE
static int form_hasproperty(struct SEE_interpreter *, struct SEE_object *, struct SEE_string *);
static void js_form_reset(struct SEE_interpreter *, struct SEE_object *, struct SEE_object *, int, struct SEE_value **, struct SEE_value *);
static void js_form_submit(struct SEE_interpreter *, struct SEE_object *, struct SEE_object *, int, struct SEE_value **, struct SEE_value *);
static void form_finalize(struct SEE_interpreter *, void *, void *);
struct SEE_objectclass js_input_object_class = {
@ -598,6 +599,24 @@ see_moved_form_state(struct form_state *fs)
}
static inline struct form_view *
form_view_of_js_form(struct SEE_interpreter *interp,
const struct js_form *jsform)
{
struct form_view *fv = jsform->fv;
if (!fv)
SEE_error_throw(interp, interp->Error,
"Form has been destroyed");
assert(fv->ecmascript_obj == jsform);
if_assert_failed
SEE_error_throw(interp, interp->Error,
"Internal corruption");
return fv;
}
static void
js_form_elems_item(struct SEE_interpreter *interp, struct SEE_object *self,
struct SEE_object *thisobj, int argc, struct SEE_value **argv,
@ -611,7 +630,7 @@ js_form_elems_item(struct SEE_interpreter *interp, struct SEE_object *self,
see_check_class(interp, thisobj, &js_form_elems_class),
(struct js_form_elems *)thisobj);
struct js_form *parent_form = jsfe->parent;
struct form_view *fv = parent_form->fv;
struct form_view *fv = form_view_of_js_form(interp, parent_form);
struct form *form = find_form_by_form_view(document, fv);
struct form_control *fc;
unsigned char *string;
@ -657,7 +676,7 @@ js_form_elems_namedItem(struct SEE_interpreter *interp, struct SEE_object *self,
see_check_class(interp, thisobj, &js_form_elems_class),
(struct js_form_elems *)thisobj);
struct js_form *parent_form = jsfe->parent;
struct form_view *fv = parent_form->fv;
struct form_view *fv = form_view_of_js_form(interp, parent_form);
struct form *form = find_form_by_form_view(document, fv);
struct form_control *fc;
unsigned char *string;
@ -695,7 +714,7 @@ form_elems_get(struct SEE_interpreter *interp, struct SEE_object *o,
struct document *document = doc_view->document;
struct js_form_elems *jsfe = (struct js_form_elems *)o;
struct js_form *parent_form = jsfe->parent;
struct form_view *fv = parent_form->fv;
struct form_view *fv = form_view_of_js_form(interp, parent_form);
struct form *form = find_form_by_form_view(document, fv);
if (p == s_length) {
@ -863,7 +882,7 @@ form_get(struct SEE_interpreter *interp, struct SEE_object *o,
struct view_state *vs = g->win->vs;
struct document_view *doc_view = vs->doc_view;
struct js_form *js_form = (struct js_form *)o;
struct form_view *fv = js_form->fv;
struct form_view *fv = form_view_of_js_form(interp, js_form);
struct form *form = find_form_by_form_view(doc_view->document, fv);
struct SEE_string *str;
@ -956,7 +975,7 @@ form_put(struct SEE_interpreter *interp, struct SEE_object *o,
struct view_state *vs = g->win->vs;
struct document_view *doc_view = vs->doc_view;
struct js_form *js_form = (struct js_form *)o;
struct form_view *fv = js_form->fv;
struct form_view *fv = form_view_of_js_form(interp, js_form);
struct form *form = find_form_by_form_view(doc_view->document, fv);
unsigned char *string = see_value_to_unsigned_char(interp, val);
@ -1018,7 +1037,7 @@ js_form_reset(struct SEE_interpreter *interp, struct SEE_object *self,
struct js_form *js_form = (
see_check_class(interp, thisobj, &js_form_class),
(struct js_form *)thisobj);
struct form_view *fv = js_form->fv;
struct form_view *fv = form_view_of_js_form(interp, js_form);
struct form *form = find_form_by_form_view(doc_view->document, fv);
assert(form);
@ -1040,7 +1059,7 @@ js_form_submit(struct SEE_interpreter *interp, struct SEE_object *self,
struct js_form *js_form = (
see_check_class(interp, thisobj, &js_form_class),
(struct js_form *)thisobj);
struct form_view *fv = js_form->fv;
struct form_view *fv = form_view_of_js_form(interp, js_form);
struct form *form = find_form_by_form_view(doc_view->document, fv);
assert(form);
@ -1051,27 +1070,89 @@ js_form_submit(struct SEE_interpreter *interp, struct SEE_object *self,
struct js_form *js_get_form_object(struct SEE_interpreter *interp,
struct js_document_object *doc, struct form_view *fv)
{
struct js_form *js_form;
struct js_form *js_form = fv->ecmascript_obj;
if (js_form) {
assert(js_form->fv == fv);
if_assert_failed return NULL;
return js_form;
}
#if 0
if (fv->ecmascript_obj)
return fv->ecmascript_obj;
#endif
/* jsdoc ('document') is fv's parent */
/* FIXME: That is NOT correct since the real containing element
* should be its parent, but gimme DOM first. --pasky */
js_form = SEE_NEW(interp, struct js_form);
js_form = SEE_NEW_FINALIZE(interp, struct js_form,
form_finalize, NULL);
js_form->object.objectclass = &js_form_class;
js_form->object.Prototype = NULL; /* TODO: use prototype for form */
js_form->parent = doc;
js_form->reset = SEE_cfunction_make(interp, js_form_reset, s_reset, 0);
js_form->submit = SEE_cfunction_make(interp, js_form_submit, s_submit, 0);
js_form->fv = fv;
js_form->fv = fv;
fv->ecmascript_obj = js_form;
return js_form;
}
static void
form_finalize(struct SEE_interpreter *interp, void *jsform_void, void *dummy)
{
struct js_form *jsform = jsform_void;
struct form_view *fv = jsform->fv;
if (fv) {
/* Reset jsform->fv in case some ELinks code uses it
* even after this finalizer has run. Such use should
* not be possible but the explanation is somewhat
* complex so it seems safest to do this.
*
* Unlike SpiderMonkey, Boehm's GC allows a finalizer
* to resurrect the object by making something point
* to it. And it's a conservative GC so it can see
* such a pointer where none actually exists. However
* it also implicitly unregisters the finalizer before
* calling it, so the object becomes just a chunk of
* memory that nothing really uses, even if the GC
* never realizes it is garbage. */
jsform->fv = NULL;
/* If this assertion fails, leave fv->ecmascript_obj
* unchanged, because it may point to a different
* structure whose js_form.fv pointer will later have
* to be updated to avoid crashes.
*
* If the assertion fails and we leave jsform->fv
* unchanged, and something then deletes fv,
* jsform->fv becomes a dangling pointer because fv
* does not know about jsform. So that's why the
* assertion comes after the jsform->fv assignment
* above. */
assert(fv->ecmascript_obj == jsform);
if_assert_failed return;
fv->ecmascript_obj = NULL;
}
}
void
see_detach_form_view(struct form_view *fv)
{
struct js_form *jsform = fv->ecmascript_obj;
if (jsform) {
/* If this assertion fails, it is not clear whether
* jsform->fv should be reset; crashes seem possible
* either way. Resetting it is easiest. */
assert(jsform->fv == fv);
if_assert_failed {}
jsform->fv = NULL;
fv->ecmascript_obj = NULL;
}
}
void
init_js_forms_object(struct ecmascript_interpreter *interpreter)
{