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 */
|
||||
timer_id_T timeout;
|
||||
int ecmascript_counter;
|
||||
void *dom;
|
||||
#endif
|
||||
#ifdef CONFIG_CSS
|
||||
/** @todo FIXME: We should externally maybe using cache_entry store the
|
||||
|
@ -2,6 +2,6 @@ top_builddir=../../..
|
||||
include $(top_builddir)/Makefile.config
|
||||
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
|
||||
|
@ -27,6 +27,7 @@
|
||||
#include "ecmascript/spidermonkey/form.h"
|
||||
#include "ecmascript/spidermonkey/location.h"
|
||||
#include "ecmascript/spidermonkey/document.h"
|
||||
#include "ecmascript/spidermonkey/element.h"
|
||||
#include "ecmascript/spidermonkey/window.h"
|
||||
#include "intl/gettext/libintl.h"
|
||||
#include "main/select.h"
|
||||
@ -48,6 +49,10 @@
|
||||
#include "viewer/text/link.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);
|
||||
|
||||
@ -678,6 +683,30 @@ document_replace(JSContext *ctx, unsigned int argc, JS::Value *vp)
|
||||
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
|
||||
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);
|
||||
return true;
|
||||
}
|
||||
args.rval().setNull();
|
||||
|
||||
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();
|
||||
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;
|
||||
}
|
||||
|
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)
|
||||
|
||||
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