1
0
mirror of https://github.com/rkd77/elinks.git synced 2025-02-02 15:09:23 -05:00

[spidermonkey] element.dataset (slow)

This commit is contained in:
Witold Filipczyk 2024-06-28 16:42:11 +02:00
parent a7bf39e9a6
commit fe5d5bcf68
7 changed files with 300 additions and 4 deletions

View File

@ -2,7 +2,7 @@ top_builddir=../../..
include $(top_builddir)/Makefile.config
INCLUDES += $(SPIDERMONKEY_CFLAGS)
OBJS = attr.obj attributes.obj collection.obj console.obj css.obj customevent.obj document.obj domrect.obj element.obj event.obj form.obj forms.obj heartbeat.obj history.obj implementation.obj input.obj \
OBJS = attr.obj attributes.obj collection.obj console.obj css.obj customevent.obj dataset.obj document.obj domrect.obj element.obj event.obj form.obj forms.obj heartbeat.obj history.obj implementation.obj input.obj \
keyboard.obj localstorage.obj location.obj message.obj navigator.obj nodelist.obj nodelist2.obj screen.obj style.obj tokenlist.obj unibar.obj url.obj urlsearchparams.obj window.obj xhr.obj
include $(top_srcdir)/Makefile.lib

View File

@ -0,0 +1,261 @@
/* The SpiderMonkey datasetobject implementation. */
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "elinks.h"
#include "ecmascript/libdom/dom.h"
#include "ecmascript/spidermonkey/util.h"
#include <jsfriendapi.h>
#include <js/Id.h>
#include "bfu/dialog.h"
#include "cache/cache.h"
#include "cookies/cookies.h"
#include "dialogs/menu.h"
#include "dialogs/status.h"
#include "document/html/frames.h"
#include "document/document.h"
#include "document/forms.h"
#include "document/libdom/corestrings.h"
#include "document/view.h"
#include "ecmascript/ecmascript.h"
#include "ecmascript/spidermonkey/dataset.h"
#include "ecmascript/spidermonkey/element.h"
#include "intl/libintl.h"
#include "main/select.h"
#include "osdep/newwin.h"
#include "osdep/sysname.h"
#include "protocol/http/http.h"
#include "protocol/uri.h"
#include "session/history.h"
#include "session/location.h"
#include "session/session.h"
#include "session/task.h"
#include "terminal/tab.h"
#include "terminal/terminal.h"
#include "util/conv.h"
#include "util/memory.h"
#include "util/string.h"
#include "viewer/text/draw.h"
#include "viewer/text/form.h"
#include "viewer/text/link.h"
#include "viewer/text/vs.h"
#include <iostream>
#include <algorithm>
#include <string>
static void dataset_finalize(JS::GCContext *op, JSObject *obj)
{
#ifdef ECMASCRIPT_DEBUG
fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__);
#endif
dom_node *element = JS::GetMaybePtrFromReservedSlot<dom_node>(obj, 0);
if (element) {
dom_node_unref(element);
}
}
static bool
dataset_obj_getProperty(JSContext* ctx, JS::HandleObject obj, JS::HandleValue receiver, JS::HandleId id, JS::MutableHandleValue vp)
{
#ifdef ECMASCRIPT_DEBUG
fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__);
#endif
vp.setUndefined();
if (!id.isString()) {
return true;
}
char *property = jsid_to_string(ctx, id);
if (!property) {
return true;
}
dom_node *el = JS::GetMaybePtrFromReservedSlot<dom_node>(obj, 0);
struct string data;
if (!el ||!init_string(&data)) {
mem_free(property);
return true;
}
add_to_string(&data, "data-");
add_to_string(&data, property);
mem_free(property);
dom_string *attr_name = NULL;
dom_exception exc = dom_string_create(data.source, data.length, &attr_name);
done_string(&data);
if (exc != DOM_NO_ERR || !attr_name) {
return true;
}
dom_string *attr_value = NULL;
exc = dom_element_get_attribute(el, attr_name, &attr_value);
dom_string_unref(attr_name);
if (exc != DOM_NO_ERR || !attr_value) {
return true;
}
vp.setString(JS_NewStringCopyZ(ctx, dom_string_data(attr_value)));
dom_string_unref(attr_value);
return true;
}
static bool
dataset_obj_setProperty(JSContext* ctx, JS::HandleObject obj, JS::HandleId id, JS::HandleValue v, JS::HandleValue receiver, JS::ObjectOpResult& result)
{
#ifdef ECMASCRIPT_DEBUG
fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__);
#endif
if (!id.isString()) {
return true;
}
char *property = jsid_to_string(ctx, id);
if (!property) {
return true;
}
char *value = jsval_to_string(ctx, v);
if (!value) {
mem_free(property);
return true;
}
dom_node *el = JS::GetMaybePtrFromReservedSlot<dom_node>(obj, 0);
struct string data;
if (!el ||!init_string(&data)) {
mem_free(property);
mem_free(value);
return true;
}
add_to_string(&data, "data-");
add_to_string(&data, property);
mem_free(property);
dom_string *attr_name = NULL;
dom_exception exc = dom_string_create(data.source, data.length, &attr_name);
done_string(&data);
if (exc != DOM_NO_ERR || !attr_name) {
return true;
}
dom_string *attr_value = NULL;
exc = dom_string_create(value, strlen(value), &attr_value);
mem_free(value);
if (exc != DOM_NO_ERR || !attr_value) {
dom_string_unref(attr_name);
return true;
}
exc = dom_element_set_attribute(el, attr_name, attr_value);
dom_string_unref(attr_name);
dom_string_unref(attr_value);
return true;
}
static bool
dataset_obj_deleteProperty(JSContext* ctx, JS::HandleObject obj, JS::HandleId id, JS::ObjectOpResult& result)
{
#ifdef ECMASCRIPT_DEBUG
fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__);
#endif
if (!id.isString()) {
return true;
}
char *property = jsid_to_string(ctx, id);
if (!property) {
return true;
}
dom_node *el = JS::GetMaybePtrFromReservedSlot<dom_node>(obj, 0);
struct string data;
if (!el ||!init_string(&data)) {
mem_free(property);
return true;
}
add_to_string(&data, "data-");
add_to_string(&data, property);
mem_free(property);
dom_string *attr_name = NULL;
dom_exception exc = dom_string_create(data.source, data.length, &attr_name);
done_string(&data);
if (exc != DOM_NO_ERR || !attr_name) {
return true;
}
dom_string *attr_value = NULL;
exc = dom_element_remove_attribute(el, attr_name);
dom_string_unref(attr_name);
return true;
}
JSClassOps dataset_ops = {
nullptr, // addProperty
nullptr, // deleteProperty
nullptr, // enumerate
nullptr, // newEnumerate
nullptr, // resolve
nullptr, // mayResolve
dataset_finalize, // finalize
nullptr, // call
nullptr, // construct
JS_GlobalObjectTraceHook
};
js::ObjectOps dataset_obj_ops = {
// .hasProperty = dataset_obj_hasProperty,
.getProperty = dataset_obj_getProperty,
.setProperty = dataset_obj_setProperty,
.deleteProperty = dataset_obj_deleteProperty
};
JSClass dataset_class = {
"dataset",
JSCLASS_HAS_RESERVED_SLOTS(1),
&dataset_ops,
.oOps = &dataset_obj_ops
};
static const spidermonkeyFunctionSpec dataset_funcs[] = {
{ NULL }
};
static JSPropertySpec dataset_props[] = {
JS_PS_END
};
JSObject *
getDataset(JSContext *ctx, void *node)
{
#ifdef ECMASCRIPT_DEBUG
fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__);
#endif
JSObject *ds = JS_NewObject(ctx, &dataset_class);
if (!ds) {
return NULL;
}
JS::RootedObject r_el(ctx, ds);
// JS_DefineProperties(ctx, r_el, (JSPropertySpec *)dataset_props);
// spidermonkey_DefineFunctions(ctx, el, dataset_funcs);
dom_node_ref(node);
JS::SetReservedSlot(ds, 0, JS::PrivateValue(node));
return ds;
}

View File

@ -0,0 +1,8 @@
#ifndef EL__ECMASCRIPT_SPIDERMONKEY_DATASET_H
#define EL__ECMASCRIPT_SPIDERMONKEY_DATASET_H
#include "ecmascript/spidermonkey/util.h"
JSObject *getDataset(JSContext *ctx, void *element);
#endif

View File

@ -33,6 +33,7 @@
#include "ecmascript/spidermonkey/attr.h"
#include "ecmascript/spidermonkey/attributes.h"
#include "ecmascript/spidermonkey/collection.h"
#include "ecmascript/spidermonkey/dataset.h"
#include "ecmascript/spidermonkey/domrect.h"
#include "ecmascript/spidermonkey/event.h"
#include "ecmascript/spidermonkey/element.h"
@ -77,6 +78,7 @@ static bool element_get_property_childNodes(JSContext *ctx, unsigned int argc, J
static bool element_get_property_classList(JSContext *ctx, unsigned int argc, JS::Value *vp);
static bool element_get_property_className(JSContext *ctx, unsigned int argc, JS::Value *vp);
static bool element_set_property_className(JSContext *ctx, unsigned int argc, JS::Value *vp);
static bool element_get_property_dataset(JSContext *ctx, unsigned int argc, JS::Value *vp);
//static bool element_get_property_clientHeight(JSContext *ctx, unsigned int argc, JS::Value *vp);
//static bool element_get_property_clientLeft(JSContext *ctx, unsigned int argc, JS::Value *vp);
//static bool element_get_property_clientTop(JSContext *ctx, unsigned int argc, JS::Value *vp);
@ -173,6 +175,7 @@ JSPropertySpec element_props[] = {
// JS_PSG("clientLeft", element_get_property_clientLeft, JSPROP_ENUMERATE),
// JS_PSG("clientTop", element_get_property_clientTop, JSPROP_ENUMERATE),
// JS_PSG("clientWidth", element_get_property_clientWidth, JSPROP_ENUMERATE),
JS_PSG("dataset", element_get_property_dataset, JSPROP_ENUMERATE),
JS_PSGS("dir", element_get_property_dir, element_set_property_dir, JSPROP_ENUMERATE),
JS_PSG("firstChild", element_get_property_firstChild, JSPROP_ENUMERATE),
JS_PSG("firstElementChild", element_get_property_firstElementChild, JSPROP_ENUMERATE),
@ -667,6 +670,27 @@ element_get_property_className(JSContext *ctx, unsigned int argc, JS::Value *vp)
return true;
}
static bool
element_get_property_dataset(JSContext *ctx, unsigned int argc, JS::Value *vp)
{
#ifdef ECMASCRIPT_DEBUG
fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__);
#endif
JS::CallArgs args = CallArgsFromVp(argc, vp);
JS::RootedObject hobj(ctx, &args.thisv().toObject());
dom_node *el = (dom_node *)JS::GetMaybePtrFromReservedSlot<dom_node>(hobj, 0);
if (!el) {
args.rval().setNull();
return true;
}
JSObject *obj = getDataset(ctx, el);
args.rval().setObject(*obj);
return true;
}
#if 0 // it does not work yet
static bool
element_get_property_clientHeight(JSContext *ctx, unsigned int argc, JS::Value *vp)
@ -4460,7 +4484,6 @@ element_getAttribute(JSContext *ctx, unsigned int argc, JS::Value *rval)
return true;
}
len = strlen(str);
exc = dom_string_create((const uint8_t *)str, len, &attr_name);
mem_free(str);
@ -4468,7 +4491,6 @@ element_getAttribute(JSContext *ctx, unsigned int argc, JS::Value *rval)
args.rval().setNull();
return true;
}
exc = dom_element_get_attribute(el, attr_name, &attr_value);
dom_string_unref(attr_name);

View File

@ -1,4 +1,4 @@
srcs += files('attr.cpp', 'attributes.cpp', 'collection.cpp', 'console.cpp', 'css.cpp', 'customevent.cpp', 'document.cpp', 'domrect.cpp', 'element.cpp', 'event.cpp',
srcs += files('attr.cpp', 'attributes.cpp', 'collection.cpp', 'console.cpp', 'css.cpp', 'customevent.cpp', 'dataset.cpp', 'document.cpp', 'domrect.cpp', 'element.cpp', 'event.cpp',
'form.cpp', 'forms.cpp', 'heartbeat.cpp', 'history.cpp', 'implementation.cpp', 'input.cpp', 'keyboard.cpp',
'localstorage.cpp', 'location.cpp', 'message.cpp', 'navigator.cpp', 'nodelist.cpp', 'nodelist2.cpp', 'screen.cpp', 'style.cpp', 'tokenlist.cpp', 'unibar.cpp', 'url.cpp',
'urlsearchparams.cpp', 'window.cpp', 'xhr.cpp')

View File

@ -14,6 +14,10 @@ function myFunction() {
console.assert(div.dataset.b === 'abc', 'abc');
div.dataset.b = '123';
console.assert(div.dataset.b === '123', '123');
console.assert(div.dataset.abc === undefined, 'undefined');
delete(div.dataset.b);
console.assert(div.dataset.b === undefined, 'undefined because deleted');
}
console.error('element.dataset.html');

View File

@ -33,6 +33,7 @@ took = [
'element.cloneNode.html',
'element.closest.html',
'element.contains.html',
'element.dataset.html',
'element.dir.html',
'element.eventListener.html',
'element.firstChild.html',