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

[quicksjs] changed forms code, but still does not work

This commit is contained in:
Witold Filipczyk 2021-11-11 20:43:59 +01:00
parent 7d51951d5f
commit 28fba3eab3
4 changed files with 224 additions and 228 deletions

View File

@ -402,6 +402,7 @@ void
ecmascript_detach_form_view(struct form_view *fv)
{
#ifdef CONFIG_QUICKJS
quickjs_detach_form_view(fv);
#else
spidermonkey_detach_form_view(fv);
#endif
@ -410,6 +411,7 @@ ecmascript_detach_form_view(struct form_view *fv)
void ecmascript_detach_form_state(struct form_state *fs)
{
#ifdef CONFIG_QUICKJS
quickjs_detach_form_state(fs);
#else
spidermonkey_detach_form_state(fs);
#endif
@ -418,6 +420,7 @@ void ecmascript_detach_form_state(struct form_state *fs)
void ecmascript_moved_form_state(struct form_state *fs)
{
#ifdef CONFIG_QUICKJS
quickjs_moved_form_state(fs);
#else
spidermonkey_moved_form_state(fs);
#endif

View File

@ -21,7 +21,7 @@
#include "document/view.h"
#include "ecmascript/ecmascript.h"
#include "ecmascript/quickjs.h"
//#include "ecmascript/spidermonkey/document.h"
#include "ecmascript/quickjs/document.h"
#include "ecmascript/quickjs/form.h"
#include "ecmascript/quickjs/forms.h"
#include "ecmascript/quickjs/input.h"
@ -47,59 +47,14 @@
#include "viewer/text/vs.h"
#include <libxml++/libxml++.h>
#include <map>
#define countof(x) (sizeof(x) / sizeof((x)[0]))
static JSClassID js_form_elements_class_id;
static JSClassID js_form_class_id;
#if 0
void
spidermonkey_detach_form_state(struct form_state *fs)
{
#ifdef ECMASCRIPT_DEBUG
fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__);
#endif
JSObject *jsinput = fs->ecmascript_obj;
if (jsinput) {
// JS::RootedObject r_jsinput(spidermonkey_empty_context, jsinput);
/* This assumes JS_GetInstancePrivate and JS_SetPrivate
* cannot GC. */
/* If this assertion fails, it is not clear whether
* the private pointer of jsinput should be reset;
* crashes seem possible either way. Resetting it is
* easiest. */
// assert(JS_GetInstancePrivate(spidermonkey_empty_context,
// r_jsinput,
// &input_class, NULL)
// == fs);
// if_assert_failed {}
JS_SetPrivate(jsinput, NULL);
fs->ecmascript_obj = NULL;
}
}
void
spidermonkey_moved_form_state(struct form_state *fs)
{
#ifdef ECMASCRIPT_DEBUG
fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__);
#endif
JSObject *jsinput = fs->ecmascript_obj;
if (jsinput) {
/* This assumes JS_SetPrivate cannot GC. If it could,
* then the GC might call input_finalize for some
* other object whose struct form_state has also been
* reallocated, and an assertion would fail in
* input_finalize. */
JS_SetPrivate(jsinput, fs);
}
}
#endif
static std::map<struct form_view *, JSValueConst> map_form_elements;
JSValue getForm(JSContext *ctx, struct form *form);
static JSValue
js_get_form_control_object(JSContext *ctx,
@ -132,7 +87,6 @@ js_get_form_control_object(JSContext *ctx,
}
}
static void
js_form_set_items(JSContext *ctx, JSValueConst this_val, void *node)
{
@ -169,15 +123,15 @@ js_form_set_items(JSContext *ctx, JSValueConst this_val, void *node)
}
JSValue obj = js_get_form_control_object(ctx, fc->type, fs);
JS_SetPropertyUint32(ctx, this_val, counter, obj);
JS_SetPropertyUint32(ctx, this_val, counter, JS_DupValue(ctx, obj));
if (fc->id) {
if (strcmp(fc->id, "item") && strcmp(fc->id, "namedItem")) {
JS_DefinePropertyValueStr(ctx, this_val, fc->id, obj, 0);
JS_SetPropertyStr(ctx, this_val, fc->id, JS_DupValue(ctx, obj));
}
} else if (fc->name) {
if (strcmp(fc->name, "item") && strcmp(fc->name, "namedItem")) {
JS_DefinePropertyValueStr(ctx, this_val, fc->name, obj, 0);
JS_SetPropertyStr(ctx, this_val, fc->name, JS_DupValue(ctx, obj));
}
}
counter++;
@ -212,16 +166,18 @@ js_form_set_items2(JSContext *ctx, JSValueConst this_val, void *node)
}
JSValue obj = js_get_form_control_object(ctx, fc->type, fs);
JS_SetPropertyUint32(ctx, this_val, counter, obj);
if (fc->id) {
if (strcmp(fc->id, "item") && strcmp(fc->id, "namedItem")) {
JS_DefinePropertyValueStr(ctx, this_val, fc->id, obj, 0);
JS_SetPropertyStr(ctx, this_val, fc->id, obj);
}
} else if (fc->name) {
if (strcmp(fc->name, "item") && strcmp(fc->name, "namedItem")) {
JS_DefinePropertyValueStr(ctx, this_val, fc->name, obj, 0);
JS_SetPropertyStr(ctx, this_val, fc->name, obj);
}
}
counter++;
}
}
@ -470,11 +426,74 @@ js_form_set_property_action(JSContext *ctx, JSValueConst this_val, JSValue val)
return JS_UNDEFINED;
}
static const JSCFunctionListEntry js_form_elements_proto_funcs[] = {
JS_CGETSET_DEF("length", js_form_elements_get_property_length, nullptr),
JS_CFUNC_DEF("item", 1, js_form_elements_item),
JS_CFUNC_DEF("namedItem", 1, js_form_elements_namedItem),
};
void
quickjs_detach_form_view(struct form_view *fv)
{
#ifdef ECMASCRIPT_DEBUG
fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__);
#endif
JSValue jsform = fv->ecmascript_obj;
if (!JS_IsNull(jsform)) {
map_form_elements.erase(fv);
JS_SetOpaque(jsform, nullptr);
fv->ecmascript_obj = JS_NULL;
}
}
static
void js_elements_finalizer(JSRuntime *rt, JSValue val)
{
#ifdef ECMASCRIPT_DEBUG
fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__);
#endif
struct form_view *fv = JS_GetOpaque(val, js_form_elements_class_id);
JS_SetOpaque(val, nullptr);
fv->ecmascript_obj = JS_NULL;
map_form_elements.erase(fv);
}
static JSClassDef js_form_elements_class = {
"elements",
js_elements_finalizer
};
JSValue
getFormElements(JSContext *ctx, struct form_view *fv)
{
// TODO
return JS_NULL;
#ifdef ECMASCRIPT_DEBUG
fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__);
#endif
auto node_find = map_form_elements.find(fv);
if (false && node_find != map_form_elements.end()) {
return JS_DupValue(ctx, node_find->second);
}
static int initialized;
/* create the element class */
if (!initialized) {
JS_NewClassID(&js_form_elements_class_id);
JS_NewClass(JS_GetRuntime(ctx), js_form_elements_class_id, &js_form_elements_class);
initialized = 1;
}
JSValue form_elements_obj = JS_NewObjectClass(ctx, js_form_elements_class_id);
JS_SetPropertyFunctionList(ctx, form_elements_obj, js_form_elements_proto_funcs, countof(js_form_elements_proto_funcs));
JS_SetClassProto(ctx, js_form_elements_class_id, form_elements_obj);
JS_SetOpaque(form_elements_obj, fv);
fv->ecmascript_obj = form_elements_obj;
js_form_set_items(ctx, form_elements_obj, fv);
map_form_elements[fv] = form_elements_obj;
return JS_DupValue(ctx, form_elements_obj);
}
static JSValue
@ -494,23 +513,6 @@ js_form_get_property_elements(JSContext *ctx, JSValueConst this_val)
}
return getFormElements(ctx, fv);
#if 0
/* 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);
JS_SetPrivate(jsform_elems, fv);
fv->ecmascript_obj = jsform_elems;
form_set_items(ctx, r_jsform_elems, fv);
args.rval().setObject(*r_jsform_elems);
return true;
#endif
}
static JSValue
@ -870,12 +872,6 @@ js_form_submit(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *ar
return JS_FALSE;
}
JSValue
getForm(JSContext *ctx, struct form *form)
{
// TODO
return JS_NULL;
}
JSValue
js_get_form_object(JSContext *ctx, JSValueConst jsdoc, struct form *form)
@ -883,96 +879,9 @@ js_get_form_object(JSContext *ctx, JSValueConst jsdoc, struct form *form)
#ifdef ECMASCRIPT_DEBUG
fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__);
#endif
JSValueConst jsform = form->ecmascript_obj;
if (!JS_IsNull(jsform)) {
assert(JS_GetOpaque(jsform, js_form_class_id) == form);
if_assert_failed return JS_NULL;
return jsform;
}
/* 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 */
return getForm(ctx, form);
#if 0
jsform = JS_NewObject(ctx, &form_class);
if (jsform == NULL)
return NULL;
JS::RootedObject r_jsform(ctx, jsform);
JS_DefineProperties(ctx, r_jsform, form_props);
spidermonkey_DefineFunctions(ctx, jsform, form_funcs);
JS_SetPrivate(jsform, form); /* to @form_class */
form->ecmascript_obj = jsform;
form_set_items2(ctx, r_jsform, form);
return jsform;
#endif
}
#if 0
static void
form_finalize(JSFreeOp *op, JSObject *jsform)
{
#ifdef ECMASCRIPT_DEBUG
fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__);
#endif
struct form *form = JS_GetPrivate(jsform);
if (form) {
/* If this assertion fails, leave fv->ecmascript_obj
* unchanged, because it may point to a different
* JSObject whose private pointer will later have to
* be updated to avoid crashes. */
assert(form->ecmascript_obj == jsform);
if_assert_failed return;
form->ecmascript_obj = NULL;
/* No need to JS_SetPrivate, because the object is
* being destroyed. */
}
}
#endif
void
js_spidermonkey_detach_form_view(struct form_view *fv)
{
#ifdef ECMASCRIPT_DEBUG
fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__);
#endif
JSValue jsform = fv->ecmascript_obj;
if (!JS_IsNull(jsform)) {
// JS::RootedObject r_jsform(spidermonkey_empty_context, jsform);
/* This assumes JS_GetInstancePrivate and JS_SetPrivate
* cannot GC. */
/* If this assertion fails, it is not clear whether
* the private pointer of jsform should be reset;
* crashes seem possible either way. Resetting it is
* easiest. */
// assert(JS_GetInstancePrivate(spidermonkey_empty_context,
// r_jsform,
// &form_class, NULL)
// == fv);
// if_assert_failed {}
JS_SetOpaque(jsform, nullptr);
fv->ecmascript_obj = JS_NULL;
}
}
static const JSCFunctionListEntry js_elements_proto_funcs[] = {
JS_CGETSET_DEF("length", js_form_elements_get_property_length, nullptr),
JS_CFUNC_DEF("item", 1, js_form_elements_item),
JS_CFUNC_DEF("namedItem", 1, js_form_elements_namedItem),
};
static JSClassDef js_elements_class = {
"elements",
};
static JSValue
js_elements_ctor(JSContext *ctx, JSValueConst new_target, int argc, JSValueConst *argv)
@ -1006,10 +915,10 @@ js_elements_init(JSContext *ctx, JSValue global_obj)
/* create the elements class */
JS_NewClassID(&js_form_elements_class_id);
JS_NewClass(JS_GetRuntime(ctx), js_form_elements_class_id, &js_elements_class);
JS_NewClass(JS_GetRuntime(ctx), js_form_elements_class_id, &js_form_elements_class);
elements_proto = JS_NewObject(ctx);
JS_SetPropertyFunctionList(ctx, elements_proto, js_elements_proto_funcs, countof(js_elements_proto_funcs));
JS_SetPropertyFunctionList(ctx, elements_proto, js_form_elements_proto_funcs, countof(js_form_elements_proto_funcs));
elements_class = JS_NewCFunction2(ctx, js_elements_ctor, "elements", 0, JS_CFUNC_constructor, 0);
/* set proto.constructor and ctor.prototype */
@ -1032,8 +941,20 @@ static const JSCFunctionListEntry js_form_proto_funcs[] = {
JS_CFUNC_DEF("submit", 0, js_form_submit),
};
static std::map<struct form *, JSValueConst> map_form;
static
void js_form_finalizer(JSRuntime *rt, JSValue val)
{
struct form *form = JS_GetOpaque(val, js_form_class_id);
form->ecmascript_obj = JS_NULL;
map_form.erase(form);
}
static JSClassDef js_form_class = {
"form",
js_form_finalizer
};
static JSValue
@ -1081,3 +1002,34 @@ js_form_init(JSContext *ctx, JSValue global_obj)
JS_SetPropertyStr(ctx, global_obj, "form", form_proto);
return 0;
}
JSValue
getForm(JSContext *ctx, struct form *form)
{
#ifdef ECMASCRIPT_DEBUG
fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__);
#endif
auto node_find = map_form.find(form);
if (node_find != map_form.end()) {
return JS_DupValue(ctx, node_find->second);
}
static int initialized;
/* create the element class */
if (!initialized) {
JS_NewClassID(&js_form_class_id);
JS_NewClass(JS_GetRuntime(ctx), js_form_class_id, &js_form_class);
initialized = 1;
}
JSValue form_obj = JS_NewObjectClass(ctx, js_form_class_id);
JS_SetPropertyFunctionList(ctx, form_obj, js_form_proto_funcs, countof(js_form_proto_funcs));
JS_SetClassProto(ctx, js_form_class_id, form_obj);
JS_SetOpaque(form_obj, form);
js_form_set_items2(ctx, form_obj, form);
form->ecmascript_obj = form_obj;
map_form[form] = form_obj;
return JS_DupValue(ctx, form_obj);
}

View File

@ -24,7 +24,7 @@
#include "ecmascript/quickjs/document.h"
#include "ecmascript/quickjs/form.h"
#include "ecmascript/quickjs/forms.h"
//#include "ecmascript/quickjs/input.h"
#include "ecmascript/quickjs/input.h"
#include "ecmascript/quickjs/window.h"
#include "intl/libintl.h"
#include "main/select.h"
@ -47,6 +47,7 @@
#include "viewer/text/vs.h"
#include <libxml++/libxml++.h>
#include <map>
#define countof(x) (sizeof(x) / sizeof((x)[0]))
@ -100,7 +101,7 @@ js_forms_set_items(JSContext *ctx, JSValueConst this_val, void *node)
if (form->name) {
if (strcmp(form->name, "item") && strcmp(form->name, "namedItem")) {
JS_DefinePropertyValueStr(ctx, this_val, form->name, v, 0);
JS_SetPropertyStr(ctx, this_val, form->name, v);
}
}
counter++;
@ -272,8 +273,20 @@ static const JSCFunctionListEntry js_forms_proto_funcs[] = {
JS_CFUNC_DEF("namedItem", 1, js_forms_namedItem),
};
static std::map<void *, JSValueConst> map_forms;
static
void js_forms_finalizer(JSRuntime *rt, JSValue val)
{
void *node = JS_GetOpaque(val, js_forms_class_id);
map_forms.erase(node);
}
static JSClassDef js_forms_class = {
"forms",
js_forms_finalizer
};
static JSValue
@ -328,13 +341,26 @@ getForms(JSContext *ctx, void *node)
#ifdef ECMASCRIPT_DEBUG
fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__);
#endif
JSValue forms_obj = JS_NewObject(ctx);
auto node_find = map_forms.find(node);
if (node_find != map_forms.end()) {
return JS_DupValue(ctx, node_find->second);
}
static int initialized;
/* create the element class */
if (!initialized) {
JS_NewClassID(&js_forms_class_id);
JS_NewClass(JS_GetRuntime(ctx), js_forms_class_id, &js_forms_class);
initialized = 1;
}
JSValue forms_obj = JS_NewObjectClass(ctx, js_forms_class_id);
JS_SetPropertyFunctionList(ctx, forms_obj, js_forms_proto_funcs, countof(js_forms_proto_funcs));
// forms_class = JS_NewCFunction2(ctx, js_forms_ctor, "forms", 0, JS_CFUNC_constructor, 0);
// JS_SetConstructor(ctx, forms_class, forms_obj);
JS_SetClassProto(ctx, js_forms_class_id, forms_obj);
JS_SetOpaque(forms_obj, node);
js_forms_set_items(ctx, forms_obj, node);
return forms_obj;
map_forms[node] = forms_obj;
return JS_DupValue(ctx, forms_obj);
}

View File

@ -21,7 +21,7 @@
#include "document/view.h"
#include "ecmascript/ecmascript.h"
#include "ecmascript/quickjs.h"
//#include "ecmascript/quickjs/document.h"
#include "ecmascript/quickjs/document.h"
#include "ecmascript/quickjs/form.h"
#include "ecmascript/quickjs/forms.h"
#include "ecmascript/quickjs/input.h"
@ -47,10 +47,13 @@
#include "viewer/text/vs.h"
#include <libxml++/libxml++.h>
#include <map>
#define countof(x) (sizeof(x) / sizeof((x)[0]))
static JSClassID js_input_class_id;
JSValue getInput(JSContext *ctx, struct form_state *fs);
/* Accordingly to the JS specs, each input type should own object. That'd be a
* huge PITA though, however DOM comes to the rescue and defines just a single
@ -1342,49 +1345,13 @@ js_input_select(JSContext *ctx, JSValueConst this_val, unsigned int argc, JSValu
return JS_UNDEFINED;
}
JSValue
getInput(JSContext *ctx, struct form_state *fs)
{
// TODO
return JS_NULL;
}
JSValue
js_get_input_object(JSContext *ctx, struct form_state *fs)
{
#ifdef ECMASCRIPT_DEBUG
fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__);
#endif
JSValue jsinput = fs->ecmascript_obj;
if (!JS_IsNull(jsinput)) {
assert(JS_GetOpaque(jsinput, js_input_class_id) == fs);
if_assert_failed return JS_NULL;
return jsinput;
}
/* jsform ('form') is input's parent */
/* FIXME: That is NOT correct since the real containing element
* should be its parent, but gimme DOM first. --pasky */
return getInput(ctx, fs);
#if 0
jsinput = JS_NewObject(ctx, &input_class);
if (!jsinput)
return NULL;
JS::RootedObject r_jsinput(ctx, jsinput);
JS_DefineProperties(ctx, r_jsinput, (JSPropertySpec *) input_props);
spidermonkey_DefineFunctions(ctx, jsinput, input_funcs);
JS_SetPrivate(jsinput, fs); /* to @input_class */
fs->ecmascript_obj = jsinput;
return jsinput;
#endif
}
static const JSCFunctionListEntry js_input_proto_funcs[] = {
@ -1410,8 +1377,52 @@ static const JSCFunctionListEntry js_input_proto_funcs[] = {
JS_CFUNC_DEF("select", 0 , js_input_select),
};
static std::map<struct form_state *, JSValueConst> map_inputs;
void
quickjs_detach_form_state(struct form_state *fs)
{
#ifdef ECMASCRIPT_DEBUG
fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__);
#endif
JSValue jsinput = fs->ecmascript_obj;
if (!JS_IsNull(jsinput)) {
map_inputs.erase(fs);
JS_SetOpaque(jsinput, nullptr);
fs->ecmascript_obj = JS_NULL;
}
}
void
quickjs_moved_form_state(struct form_state *fs)
{
#ifdef ECMASCRIPT_DEBUG
fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__);
#endif
JSValue jsinput = fs->ecmascript_obj;
if (!JS_IsNull(jsinput)) {
map_inputs.erase(fs);
JS_SetOpaque(jsinput, fs);
map_inputs[fs] = jsinput;
}
}
static
void js_input_finalizer(JSRuntime *rt, JSValue val)
{
struct form_state *fs = JS_GetOpaque(val, js_input_class_id);
JS_SetOpaque(val, nullptr);
fs->ecmascript_obj = JS_NULL;
map_inputs.erase(fs);
}
static JSClassDef js_input_class = {
"input",
js_input_finalizer
};
static JSValue
@ -1460,26 +1471,30 @@ js_input_init(JSContext *ctx, JSValue global_obj)
return 0;
}
#if 0
static void
input_finalize(JSFreeOp *op, JSObject *jsinput)
JSValue
getInput(JSContext *ctx, struct form_state *fs)
{
#ifdef ECMASCRIPT_DEBUG
fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__);
#endif
struct form_state *fs = JS_GetPrivate(jsinput);
auto node_find = map_inputs.find(fs);
if (fs) {
/* If this assertion fails, leave fs->ecmascript_obj
* unchanged, because it may point to a different
* JSObject whose private pointer will later have to
* be updated to avoid crashes. */
assert(fs->ecmascript_obj == jsinput);
if_assert_failed return;
fs->ecmascript_obj = NULL;
/* No need to JS_SetPrivate, because jsinput is being
* destroyed. */
if (node_find != map_inputs.end()) {
return JS_DupValue(ctx, node_find->second);
}
static int initialized;
if (!initialized) {
JS_NewClassID(&js_input_class_id);
JS_NewClass(JS_GetRuntime(ctx), js_input_class_id, &js_input_class);
initialized = 1;
}
JSValue input_obj = JS_NewObjectClass(ctx, js_input_class_id);
JS_SetPropertyFunctionList(ctx, input_obj, js_input_proto_funcs, countof(js_input_proto_funcs));
JS_SetClassProto(ctx, js_input_class_id, input_obj);
JS_SetOpaque(input_obj, fs);
fs->ecmascript_obj = input_obj;
map_inputs[fs] = input_obj;
return JS_DupValue(ctx, input_obj);
}
#endif