mirror of
https://github.com/rkd77/elinks.git
synced 2024-12-04 14:46:47 -05:00
[getElementById] small success. see test/ecmascript/element.html
Now memory leaks, etc. are not taken into account. For the beginning I will implement read properties.
This commit is contained in:
parent
ff78bd6a86
commit
63d892838c
@ -211,6 +211,7 @@ struct document {
|
|||||||
/** used by setTimeout */
|
/** used by setTimeout */
|
||||||
timer_id_T timeout;
|
timer_id_T timeout;
|
||||||
int ecmascript_counter;
|
int ecmascript_counter;
|
||||||
|
void *dom;
|
||||||
#endif
|
#endif
|
||||||
#ifdef CONFIG_CSS
|
#ifdef CONFIG_CSS
|
||||||
/** @todo FIXME: We should externally maybe using cache_entry store the
|
/** @todo FIXME: We should externally maybe using cache_entry store the
|
||||||
|
@ -2,6 +2,6 @@ top_builddir=../../..
|
|||||||
include $(top_builddir)/Makefile.config
|
include $(top_builddir)/Makefile.config
|
||||||
INCLUDES += $(SPIDERMONKEY_CFLAGS)
|
INCLUDES += $(SPIDERMONKEY_CFLAGS)
|
||||||
|
|
||||||
OBJS = console.o document.o form.o heartbeat.o location.o localstorage.o localstorage-db.o navigator.o unibar.o window.o
|
OBJS = console.o document.o element.c form.o heartbeat.o location.o localstorage.o localstorage-db.o navigator.o unibar.o window.o
|
||||||
|
|
||||||
include $(top_srcdir)/Makefile.lib
|
include $(top_srcdir)/Makefile.lib
|
||||||
|
@ -27,6 +27,7 @@
|
|||||||
#include "ecmascript/spidermonkey/form.h"
|
#include "ecmascript/spidermonkey/form.h"
|
||||||
#include "ecmascript/spidermonkey/location.h"
|
#include "ecmascript/spidermonkey/location.h"
|
||||||
#include "ecmascript/spidermonkey/document.h"
|
#include "ecmascript/spidermonkey/document.h"
|
||||||
|
#include "ecmascript/spidermonkey/element.h"
|
||||||
#include "ecmascript/spidermonkey/window.h"
|
#include "ecmascript/spidermonkey/window.h"
|
||||||
#include "intl/gettext/libintl.h"
|
#include "intl/gettext/libintl.h"
|
||||||
#include "main/select.h"
|
#include "main/select.h"
|
||||||
@ -48,6 +49,10 @@
|
|||||||
#include "viewer/text/link.h"
|
#include "viewer/text/link.h"
|
||||||
#include "viewer/text/vs.h"
|
#include "viewer/text/vs.h"
|
||||||
|
|
||||||
|
#include <htmlcxx/html/ParserDom.h>
|
||||||
|
using namespace htmlcxx;
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
static bool document_get_property(JSContext *ctx, JS::HandleObject hobj, JS::HandleId hid, JS::MutableHandleValue hvp);
|
static bool document_get_property(JSContext *ctx, JS::HandleObject hobj, JS::HandleId hid, JS::MutableHandleValue hvp);
|
||||||
|
|
||||||
@ -678,6 +683,30 @@ document_replace(JSContext *ctx, unsigned int argc, JS::Value *vp)
|
|||||||
return(true);
|
return(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void *
|
||||||
|
document_parse(struct document *document)
|
||||||
|
{
|
||||||
|
struct cache_entry *cached = document->cached;
|
||||||
|
struct fragment *f = get_cache_fragment(cached);
|
||||||
|
|
||||||
|
if (!f || !f->length) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct string str;
|
||||||
|
init_string(&str);
|
||||||
|
|
||||||
|
add_bytes_to_string(&str, f->data, f->length);
|
||||||
|
|
||||||
|
HTML::ParserDom parser;
|
||||||
|
tree<HTML::Node> *dom = new tree<HTML::Node>;
|
||||||
|
*dom = parser.parseTree(str.source);
|
||||||
|
done_string(&str);
|
||||||
|
|
||||||
|
return (void *)dom;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
document_getElementById(JSContext *ctx, unsigned int argc, JS::Value *vp)
|
document_getElementById(JSContext *ctx, unsigned int argc, JS::Value *vp)
|
||||||
{
|
{
|
||||||
@ -687,7 +716,51 @@ document_getElementById(JSContext *ctx, unsigned int argc, JS::Value *vp)
|
|||||||
args.rval().setBoolean(false);
|
args.rval().setBoolean(false);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
JSCompartment *comp = js::GetContextCompartment(ctx);
|
||||||
|
struct ecmascript_interpreter *interpreter = JS_GetCompartmentPrivate(comp);
|
||||||
|
struct document_view *doc_view = interpreter->vs->doc_view;
|
||||||
|
struct document *document = doc_view->document;
|
||||||
|
|
||||||
|
if (!document->dom) {
|
||||||
|
document->dom = document_parse(document);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!document->dom) {
|
||||||
args.rval().setNull();
|
args.rval().setNull();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
tree<HTML::Node> *dom = document->dom;
|
||||||
|
tree<HTML::Node>::iterator it = dom->begin();
|
||||||
|
tree<HTML::Node>::iterator end = dom->end();
|
||||||
|
|
||||||
|
struct string idstr;
|
||||||
|
|
||||||
|
init_string(&idstr);
|
||||||
|
jshandle_value_to_char_string(&idstr, ctx, &args[0]);
|
||||||
|
std::string id = idstr.source;
|
||||||
|
|
||||||
|
JSObject *elem = nullptr;
|
||||||
|
|
||||||
|
for (; it != end; ++it) {
|
||||||
|
if (it->isTag()) {
|
||||||
|
it->parseAttributes();
|
||||||
|
if (it->attribute("id").first && it->attribute("id").second == id) {
|
||||||
|
tree<HTML::Node> *node = new tree<HTML::Node>;
|
||||||
|
*node = *it;
|
||||||
|
elem = getElement(ctx, node);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
done_string(&idstr);
|
||||||
|
if (elem) {
|
||||||
|
args.rval().setObject(*elem);
|
||||||
|
} else {
|
||||||
|
args.rval().setNull();
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
159
src/ecmascript/spidermonkey/element.c
Normal file
159
src/ecmascript/spidermonkey/element.c
Normal file
@ -0,0 +1,159 @@
|
|||||||
|
/* The SpiderMonkey html element objects implementation. */
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
#include "config.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "elinks.h"
|
||||||
|
|
||||||
|
#include "ecmascript/spidermonkey/util.h"
|
||||||
|
#include <jsfriendapi.h>
|
||||||
|
#include <htmlcxx/html/ParserDom.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/spidermonkey/element.h"
|
||||||
|
#include "ecmascript/spidermonkey/window.h"
|
||||||
|
#include "intl/gettext/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"
|
||||||
|
|
||||||
|
using namespace htmlcxx;
|
||||||
|
|
||||||
|
static bool element_get_property_id(JSContext *ctx, unsigned int argc, JS::Value *vp);
|
||||||
|
static bool element_set_property_id(JSContext *ctx, unsigned int argc, JS::Value *vp);
|
||||||
|
|
||||||
|
JSClassOps element_ops = {
|
||||||
|
JS_PropertyStub, nullptr,
|
||||||
|
JS_PropertyStub, JS_StrictPropertyStub,
|
||||||
|
nullptr, nullptr, nullptr, nullptr
|
||||||
|
};
|
||||||
|
|
||||||
|
JSClass element_class = {
|
||||||
|
"element",
|
||||||
|
JSCLASS_HAS_PRIVATE,
|
||||||
|
&element_ops
|
||||||
|
};
|
||||||
|
|
||||||
|
JSPropertySpec element_props[] = {
|
||||||
|
JS_PSGS("id", element_get_property_id, element_set_property_id, JSPROP_ENUMERATE),
|
||||||
|
JS_PS_END
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
static bool
|
||||||
|
element_get_property_id(JSContext *ctx, unsigned int argc, JS::Value *vp)
|
||||||
|
{
|
||||||
|
JS::CallArgs args = CallArgsFromVp(argc, vp);
|
||||||
|
JS::RootedObject hobj(ctx, &args.thisv().toObject());
|
||||||
|
|
||||||
|
struct view_state *vs;
|
||||||
|
JSCompartment *comp = js::GetContextCompartment(ctx);
|
||||||
|
|
||||||
|
if (!comp) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ecmascript_interpreter *interpreter = JS_GetCompartmentPrivate(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, &element_class, NULL))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
vs = interpreter->vs;
|
||||||
|
if (!vs) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
tree<HTML::Node> *el = JS_GetPrivate(hobj);
|
||||||
|
|
||||||
|
if (!el) {
|
||||||
|
args.rval().setNull();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
tree<HTML::Node>::iterator it = el->begin();
|
||||||
|
it->parseAttributes();
|
||||||
|
std::string v = it->attribute("id").second;
|
||||||
|
|
||||||
|
args.rval().setString(JS_NewStringCopyZ(ctx, v.c_str()));
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
element_set_property_id(JSContext *ctx, unsigned int argc, JS::Value *vp)
|
||||||
|
{
|
||||||
|
JS::CallArgs args = CallArgsFromVp(argc, vp);
|
||||||
|
JS::RootedObject hobj(ctx, &args.thisv().toObject());
|
||||||
|
|
||||||
|
JSCompartment *comp = js::GetContextCompartment(ctx);
|
||||||
|
|
||||||
|
if (!comp) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ecmascript_interpreter *interpreter = JS_GetCompartmentPrivate(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, &element_class, NULL))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
struct view_state *vs = interpreter->vs;
|
||||||
|
if (!vs) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
JSObject *
|
||||||
|
getElement(JSContext *ctx, void *node)
|
||||||
|
{
|
||||||
|
JSObject *el = JS_NewObject(ctx, &element_class);
|
||||||
|
|
||||||
|
if (!el) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
JS::RootedObject r_el(ctx, el);
|
||||||
|
|
||||||
|
JS_DefineProperties(ctx, r_el, (JSPropertySpec *) element_props);
|
||||||
|
// spidermonkey_DefineFunctions(ctx, el, element_funcs);
|
||||||
|
|
||||||
|
JS_SetPrivate(el, node);
|
||||||
|
|
||||||
|
return el;
|
||||||
|
}
|
14
src/ecmascript/spidermonkey/element.h
Normal file
14
src/ecmascript/spidermonkey/element.h
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
|
||||||
|
#ifndef EL__ECMASCRIPT_SPIDERMONKEY_ELEMENT_H
|
||||||
|
#define EL__ECMASCRIPT_SPIDERMONKEY_ELEMENT_H
|
||||||
|
|
||||||
|
#include "ecmascript/spidermonkey/util.h"
|
||||||
|
#include <htmlcxx/html/ParserDom.h>
|
||||||
|
using namespace htmlcxx;
|
||||||
|
|
||||||
|
extern JSClass element_class;
|
||||||
|
extern JSPropertySpec element_props[];
|
||||||
|
|
||||||
|
JSObject *getElement(JSContext *ctx, void *node);
|
||||||
|
|
||||||
|
#endif
|
@ -1,3 +1,3 @@
|
|||||||
#INCLUDES += $(SPIDERMONKEY_CFLAGS)
|
#INCLUDES += $(SPIDERMONKEY_CFLAGS)
|
||||||
|
|
||||||
srcs += files('console.c', 'document.c', 'form.c', 'heartbeat.c', 'location.c', 'localstorage.c', 'localstorage-db.c', 'navigator.c', 'unibar.c', 'window.c')
|
srcs += files('console.c', 'document.c', 'element.c', 'form.c', 'heartbeat.c', 'location.c', 'localstorage.c', 'localstorage-db.c', 'navigator.c', 'unibar.c', 'window.c')
|
||||||
|
15
test/ecmascript/element.html
Normal file
15
test/ecmascript/element.html
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
<html>
|
||||||
|
<body>
|
||||||
|
<a href="/home">BBB</a>
|
||||||
|
<b id="aaaa">bbb</b>
|
||||||
|
<a id="blabla" href="/">AAA</a>
|
||||||
|
<a id="bb" href="/">BB</a>
|
||||||
|
<script>
|
||||||
|
function aa()
|
||||||
|
{
|
||||||
|
alert(document.getElementById('blabla').id);
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<button onclick="return aa()">Click me!</button>
|
||||||
|
</body>
|
||||||
|
</html>
|
Loading…
Reference in New Issue
Block a user