mirror of
https://github.com/rkd77/elinks.git
synced 2024-11-04 08:17:17 -05:00
[spidermonkey] own implementation of nodeList for querySelectorAll
This commit is contained in:
parent
5329a84cb5
commit
89dde0e0b6
@ -559,7 +559,7 @@ walk_tree_query(dom_node *node, const char *selector, int depth)
|
||||
}
|
||||
|
||||
void
|
||||
walk_tree_query_append(dom_node *root, dom_node *node, const char *selector, int depth)
|
||||
walk_tree_query_append(dom_node *root, dom_node *node, const char *selector, int depth, LIST_OF(struct selector_node) *result_list)
|
||||
{
|
||||
dom_exception exc;
|
||||
dom_node *child;
|
||||
@ -574,17 +574,11 @@ walk_tree_query_append(dom_node *root, dom_node *node, const char *selector, int
|
||||
}
|
||||
|
||||
if (res = el_match_selector(selector, node)) {
|
||||
dom_node *clone = NULL;
|
||||
exc = dom_node_clone_node(res, false, &clone);
|
||||
struct selector_node *sn = (struct selector_node *)mem_calloc(1, sizeof(*sn));
|
||||
|
||||
if (exc != DOM_NO_ERR || !clone) {
|
||||
} else {
|
||||
dom_node *result = NULL;
|
||||
exc = dom_node_append_child(root, clone, &result);
|
||||
}
|
||||
|
||||
if (exc != DOM_NO_ERR) {
|
||||
return;
|
||||
if (sn) {
|
||||
sn->node = res;
|
||||
add_to_list_end(*result_list, sn);
|
||||
}
|
||||
}
|
||||
/* Get the node's first child */
|
||||
@ -601,7 +595,7 @@ walk_tree_query_append(dom_node *root, dom_node *node, const char *selector, int
|
||||
dom_node *next_child;
|
||||
|
||||
/* Visit node's descendents */
|
||||
walk_tree_query_append(root, child, selector, depth);
|
||||
walk_tree_query_append(root, child, selector, depth, result_list);
|
||||
|
||||
/* Go to next sibling */
|
||||
exc = dom_node_get_next_sibling(child, &next_child);
|
||||
@ -615,4 +609,3 @@ walk_tree_query_append(dom_node *root, dom_node *node, const char *selector, int
|
||||
} while (child != NULL); /* No more children */
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -5,6 +5,7 @@
|
||||
#include "ecmascript/libdom/dom.h"
|
||||
#include "main/module.h"
|
||||
#include "terminal/kbd.h"
|
||||
#include "util/lists.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
@ -22,6 +23,12 @@ struct term_event;
|
||||
struct uri;
|
||||
struct view_state;
|
||||
|
||||
struct selector_node {
|
||||
LIST_HEAD_EL(struct selector_node);
|
||||
|
||||
void *node;
|
||||
};
|
||||
|
||||
int ecmascript_get_interpreter_count(void);
|
||||
void ecmascript_put_interpreter(struct ecmascript_interpreter *interpreter);
|
||||
void toggle_ecmascript(struct session *ses);
|
||||
@ -42,7 +49,7 @@ void ecmascript_detach_form_state(struct form_state *fs);
|
||||
void ecmascript_moved_form_state(struct form_state *fs);
|
||||
|
||||
void *walk_tree_query(dom_node *node, const char *selector, int depth);
|
||||
void walk_tree_query_append(dom_node *root, dom_node *node, const char *selector, int depth);
|
||||
void walk_tree_query_append(dom_node *root, dom_node *node, const char *selector, int depth, LIST_OF(struct selector_node) *result_list);
|
||||
|
||||
extern struct module ecmascript_module;
|
||||
|
||||
|
@ -3,6 +3,6 @@ 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 \
|
||||
keyboard.obj localstorage.obj location.obj message.obj navigator.obj nodelist.obj screen.obj style.obj unibar.obj url.obj urlsearchparams.obj window.obj xhr.obj
|
||||
keyboard.obj localstorage.obj location.obj message.obj navigator.obj nodelist.obj nodelist2.obj screen.obj style.obj unibar.obj url.obj urlsearchparams.obj window.obj xhr.obj
|
||||
|
||||
include $(top_srcdir)/Makefile.lib
|
||||
|
@ -41,6 +41,7 @@
|
||||
#include "ecmascript/spidermonkey/event.h"
|
||||
#include "ecmascript/spidermonkey/heartbeat.h"
|
||||
#include "ecmascript/spidermonkey/nodelist.h"
|
||||
#include "ecmascript/spidermonkey/nodelist2.h"
|
||||
#include "ecmascript/spidermonkey/util.h"
|
||||
#include "ecmascript/spidermonkey/window.h"
|
||||
#include "intl/libintl.h"
|
||||
@ -2181,19 +2182,21 @@ document_querySelectorAll(JSContext *ctx, unsigned int argc, JS::Value *vp)
|
||||
args.rval().setNull();
|
||||
return true;
|
||||
}
|
||||
walk_tree_query_append((dom_node *)element, doc_root, selector, 0);
|
||||
dom_node_unref(doc_root);
|
||||
mem_free(selector);
|
||||
LIST_OF(struct selector_node) *result_list = (LIST_OF(struct selector_node) *)mem_calloc(1, sizeof(*result_list));
|
||||
|
||||
dom_nodelist *nodes = NULL;
|
||||
exc = dom_node_get_child_nodes(element, &nodes);
|
||||
dom_node_unref(element);
|
||||
|
||||
if (exc != DOM_NO_ERR || !nodes) {
|
||||
if (!result_list) {
|
||||
dom_node_unref(doc_root);
|
||||
mem_free(selector);
|
||||
args.rval().setNull();
|
||||
return true;
|
||||
}
|
||||
JSObject *obj = getNodeList(ctx, nodes);
|
||||
init_list(*result_list);
|
||||
|
||||
walk_tree_query_append((dom_node *)element, doc_root, selector, 0, result_list);
|
||||
dom_node_unref(doc_root);
|
||||
mem_free(selector);
|
||||
|
||||
JSObject *obj = getNodeList2(ctx, result_list);
|
||||
args.rval().setObject(*obj);
|
||||
|
||||
return true;
|
||||
|
@ -39,6 +39,7 @@
|
||||
#include "ecmascript/spidermonkey/heartbeat.h"
|
||||
#include "ecmascript/spidermonkey/keyboard.h"
|
||||
#include "ecmascript/spidermonkey/nodelist.h"
|
||||
#include "ecmascript/spidermonkey/nodelist2.h"
|
||||
#include "ecmascript/spidermonkey/style.h"
|
||||
#include "ecmascript/spidermonkey/window.h"
|
||||
#include "intl/libintl.h"
|
||||
@ -5058,18 +5059,17 @@ element_querySelectorAll(JSContext *ctx, unsigned int argc, JS::Value *vp)
|
||||
args.rval().setNull();
|
||||
return true;
|
||||
}
|
||||
walk_tree_query_append((dom_node *)element, el, selector, 0);
|
||||
mem_free(selector);
|
||||
LIST_OF(struct selector_node) *result_list = (LIST_OF(struct selector_node) *)mem_calloc(1, sizeof(*result_list));
|
||||
|
||||
dom_nodelist *nodes = NULL;
|
||||
exc = dom_node_get_child_nodes(element, &nodes);
|
||||
dom_node_unref(element);
|
||||
|
||||
if (exc != DOM_NO_ERR || !nodes) {
|
||||
if (!result_list) {
|
||||
mem_free(selector);
|
||||
args.rval().setNull();
|
||||
return true;
|
||||
}
|
||||
JSObject *obj = getNodeList(ctx, nodes);
|
||||
init_list(*result_list);
|
||||
walk_tree_query_append((dom_node *)element, el, selector, 0, result_list);
|
||||
mem_free(selector);
|
||||
JSObject *obj = getNodeList2(ctx, result_list);
|
||||
args.rval().setObject(*obj);
|
||||
|
||||
return true;
|
||||
|
@ -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',
|
||||
'form.cpp', 'forms.cpp', 'heartbeat.cpp', 'history.cpp', 'implementation.cpp', 'input.cpp', 'keyboard.cpp',
|
||||
'localstorage.cpp', 'location.cpp', 'message.cpp', 'navigator.cpp', 'nodelist.cpp', 'screen.cpp', 'style.cpp', 'unibar.cpp', 'url.cpp',
|
||||
'localstorage.cpp', 'location.cpp', 'message.cpp', 'navigator.cpp', 'nodelist.cpp', 'nodelist2.cpp', 'screen.cpp', 'style.cpp', 'unibar.cpp', 'url.cpp',
|
||||
'urlsearchparams.cpp', 'window.cpp', 'xhr.cpp')
|
||||
|
204
src/ecmascript/spidermonkey/nodelist2.cpp
Normal file
204
src/ecmascript/spidermonkey/nodelist2.cpp
Normal file
@ -0,0 +1,204 @@
|
||||
/* The SpiderMonkey nodeList2 object 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 "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/view.h"
|
||||
#include "ecmascript/ecmascript.h"
|
||||
#include "ecmascript/ecmascript-c.h"
|
||||
#include "ecmascript/spidermonkey/element.h"
|
||||
#include "ecmascript/spidermonkey/nodelist2.h"
|
||||
#include "ecmascript/spidermonkey/window.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/lists.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 bool nodeList2_item(JSContext *ctx, unsigned int argc, JS::Value *rval);
|
||||
static bool nodeList2_item2(JSContext *ctx, JS::HandleObject hobj, int index, JS::MutableHandleValue hvp);
|
||||
|
||||
static void nodeList2_finalize(JS::GCContext *op, JSObject *obj)
|
||||
{
|
||||
#ifdef ECMASCRIPT_DEBUG
|
||||
fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__);
|
||||
#endif
|
||||
LIST_OF(struct selector_node) *sni = JS::GetMaybePtrFromReservedSlot<LIST_OF(struct selector_node)>(obj, 0);
|
||||
|
||||
if (sni) {
|
||||
free_list(*sni);
|
||||
}
|
||||
}
|
||||
|
||||
JSClassOps nodeList2_ops = {
|
||||
nullptr, // addProperty
|
||||
nullptr, // deleteProperty
|
||||
nullptr, // enumerate
|
||||
nullptr, // newEnumerate
|
||||
nullptr, // resolve
|
||||
nullptr, // mayResolve
|
||||
nodeList2_finalize, // finalize
|
||||
nullptr, // call
|
||||
nullptr, // construct
|
||||
JS_GlobalObjectTraceHook
|
||||
};
|
||||
|
||||
JSClass nodeList2_class = {
|
||||
"nodeList2",
|
||||
JSCLASS_HAS_RESERVED_SLOTS(1) | JSCLASS_HAS_CACHED_PROTO(JSProto_Array),
|
||||
&nodeList2_ops
|
||||
};
|
||||
|
||||
static const spidermonkeyFunctionSpec nodeList2_funcs[] = {
|
||||
{ "item", nodeList2_item, 1 },
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
static bool nodeList2_get_property_length(JSContext *ctx, unsigned int argc, JS::Value *vp);
|
||||
|
||||
static JSPropertySpec nodeList2_props[] = {
|
||||
JS_PSG("length", nodeList2_get_property_length, JSPROP_ENUMERATE),
|
||||
JS_PS_END
|
||||
};
|
||||
|
||||
static bool
|
||||
nodeList2_get_property_length(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());
|
||||
|
||||
struct view_state *vs;
|
||||
JS::Realm *comp = js::GetContextRealm(ctx);
|
||||
|
||||
if (!comp) {
|
||||
#ifdef ECMASCRIPT_DEBUG
|
||||
fprintf(stderr, "%s:%s %d\n", __FILE__, __FUNCTION__, __LINE__);
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
struct ecmascript_interpreter *interpreter = (struct ecmascript_interpreter *)JS::GetRealmPrivate(comp);
|
||||
|
||||
/* This can be called if @obj if not itself an instance of the
|
||||
* appropriate class but has one in its prototype chain. Fail
|
||||
* such calls. */
|
||||
if (!JS_InstanceOf(ctx, hobj, &nodeList2_class, NULL)) {
|
||||
#ifdef ECMASCRIPT_DEBUG
|
||||
fprintf(stderr, "%s:%s %d\n", __FILE__, __FUNCTION__, __LINE__);
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
LIST_OF(struct selector_node) *sni = JS::GetMaybePtrFromReservedSlot<LIST_OF(struct selector_node)>(hobj, 0);
|
||||
args.rval().setInt32(list_size(sni));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
nodeList2_item(JSContext *ctx, unsigned int argc, JS::Value *vp)
|
||||
{
|
||||
#ifdef ECMASCRIPT_DEBUG
|
||||
fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__);
|
||||
#endif
|
||||
JS::Value val;
|
||||
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
|
||||
JS::RootedObject hobj(ctx, &args.thisv().toObject());
|
||||
JS::RootedValue rval(ctx, val);
|
||||
LIST_OF(struct selector_node) *sni = JS::GetMaybePtrFromReservedSlot<LIST_OF(struct selector_node)>(hobj, 0);
|
||||
int index = args[0].toInt32();
|
||||
int counter = 0;
|
||||
struct selector_node *sn = NULL;
|
||||
|
||||
foreach (sn, *sni) {
|
||||
if (counter == index) {
|
||||
break;
|
||||
}
|
||||
counter++;
|
||||
}
|
||||
|
||||
if (!sn || !sn->node) {
|
||||
args.rval().setNull();
|
||||
return true;
|
||||
}
|
||||
|
||||
JSObject *res = getElement(ctx, sn->node);
|
||||
args.rval().setObject(*res);
|
||||
return true;
|
||||
}
|
||||
|
||||
JSObject *
|
||||
getNodeList2(JSContext *ctx, void *res)
|
||||
{
|
||||
#ifdef ECMASCRIPT_DEBUG
|
||||
fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__);
|
||||
#endif
|
||||
LIST_OF(struct selector_node) *sni = (LIST_OF(struct selector_node) *)res;
|
||||
JSObject *el = JS_NewObject(ctx, &nodeList2_class);
|
||||
|
||||
if (!el) {
|
||||
return NULL;
|
||||
}
|
||||
JS::RootedObject r_el(ctx, el);
|
||||
|
||||
JS_DefineProperties(ctx, r_el, (JSPropertySpec *) nodeList2_props);
|
||||
spidermonkey_DefineFunctions(ctx, el, nodeList2_funcs);
|
||||
|
||||
struct selector_node *sn = NULL;
|
||||
int i = 0;
|
||||
|
||||
foreach (sn, *sni) {
|
||||
JSObject *obj = getElement(ctx, sn->node);
|
||||
|
||||
if (obj) {
|
||||
JS::RootedObject v(ctx, obj);
|
||||
JS::RootedValue ro(ctx, JS::ObjectOrNullValue(v));
|
||||
JS_SetElement(ctx, r_el, i, ro);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
JS::SetReservedSlot(el, 0, JS::PrivateValue(res));
|
||||
|
||||
return el;
|
||||
}
|
8
src/ecmascript/spidermonkey/nodelist2.h
Normal file
8
src/ecmascript/spidermonkey/nodelist2.h
Normal file
@ -0,0 +1,8 @@
|
||||
#ifndef EL__ECMASCRIPT_SPIDERMONKEY_NODELIST2_H
|
||||
#define EL__ECMASCRIPT_SPIDERMONKEY_NODELIST2_H
|
||||
|
||||
#include "ecmascript/spidermonkey/util.h"
|
||||
|
||||
JSObject *getNodeList2(JSContext *ctx, void *result_list);
|
||||
|
||||
#endif
|
@ -9,7 +9,7 @@
|
||||
console.error('nodelist.forEach.html');
|
||||
var birds = document.querySelectorAll('li');
|
||||
|
||||
console.assert(birds.length === 3, birds.length);
|
||||
console.assert(birds.length === 3, 'birds.length');
|
||||
|
||||
var counter = 0;
|
||||
birds.forEach(function(b) {
|
||||
|
Loading…
Reference in New Issue
Block a user