mirror of
https://github.com/rkd77/elinks.git
synced 2025-06-30 22:19:29 -04:00
2165 lines
50 KiB
C
2165 lines
50 KiB
C
/* The QuickJS document object implementation. */
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
#include "config.h"
|
|
#endif
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
#ifdef CONFIG_LIBDOM
|
|
#include <dom/dom.h>
|
|
#include <dom/bindings/hubbub/parser.h>
|
|
#endif
|
|
|
|
#include "elinks.h"
|
|
|
|
#include "cookies/cookies.h"
|
|
#include "dialogs/status.h"
|
|
#include "document/document.h"
|
|
#include "document/libdom/doc.h"
|
|
#include "document/libdom/mapa.h"
|
|
#include "document/view.h"
|
|
#include "js/ecmascript.h"
|
|
#include "js/ecmascript-c.h"
|
|
#include "js/libdom/parse.h"
|
|
#include "js/quickjs/mapa.h"
|
|
#include "js/quickjs.h"
|
|
#include "js/quickjs/collection.h"
|
|
#include "js/quickjs/event.h"
|
|
#include "js/quickjs/form.h"
|
|
#include "js/quickjs/forms.h"
|
|
#include "js/quickjs/fragment.h"
|
|
#include "js/quickjs/implementation.h"
|
|
#include "js/quickjs/location.h"
|
|
#include "js/quickjs/document.h"
|
|
#include "js/quickjs/element.h"
|
|
#include "js/quickjs/nodelist.h"
|
|
#include "js/quickjs/nodelist2.h"
|
|
#include "js/quickjs/text.h"
|
|
#include "js/quickjs/window.h"
|
|
#include "session/session.h"
|
|
#include "viewer/text/vs.h"
|
|
|
|
#define countof(x) (sizeof(x) / sizeof((x)[0]))
|
|
|
|
static JSClassID js_doctype_class_id;
|
|
static JSClassID js_document_class_id;
|
|
|
|
struct document_listener {
|
|
LIST_HEAD_EL(struct document_listener);
|
|
char *typ;
|
|
JSValue fun;
|
|
};
|
|
|
|
enum readyState {
|
|
LOADING = 0,
|
|
INTERACTIVE,
|
|
COMPLETE
|
|
};
|
|
|
|
struct js_document_private {
|
|
LIST_OF(struct document_listener) listeners;
|
|
struct ecmascript_interpreter *interpreter;
|
|
JSValue thisval;
|
|
dom_event_listener *listener;
|
|
void *node;
|
|
enum readyState state;
|
|
};
|
|
|
|
static void document_event_handler(dom_event *event, void *pw);
|
|
|
|
void *
|
|
js_doc_getopaque(JSValueConst obj)
|
|
{
|
|
REF_JS(obj);
|
|
|
|
struct js_document_private *res = (struct js_document_private *)JS_GetOpaque(obj, js_document_class_id);
|
|
|
|
if (!res) {
|
|
return NULL;
|
|
}
|
|
|
|
return res->node;
|
|
}
|
|
|
|
void *
|
|
document_get_node(JSValueConst obj)
|
|
{
|
|
return js_doc_getopaque(obj);
|
|
}
|
|
|
|
static void
|
|
js_document_mark(JSRuntime *rt, JSValueConst val, JS_MarkFunc *mark_func)
|
|
{
|
|
#ifdef ECMASCRIPT_DEBUG
|
|
fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__);
|
|
#endif
|
|
REF_JS(val);
|
|
|
|
struct js_document_private *doc_private = (struct js_document_private *)JS_GetOpaque(val, js_document_class_id);
|
|
|
|
if (doc_private) {
|
|
struct document_listener *l;
|
|
|
|
foreach(l, doc_private->listeners) {
|
|
JS_MarkValue(rt, l->fun, mark_func);
|
|
}
|
|
}
|
|
}
|
|
|
|
static JSValue
|
|
js_document_get_property_anchors(JSContext *ctx, JSValueConst this_val)
|
|
{
|
|
#ifdef ECMASCRIPT_DEBUG
|
|
fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__);
|
|
#endif
|
|
REF_JS(this_val);
|
|
|
|
dom_html_document *doc = (struct dom_html_document *)js_doc_getopaque(this_val);
|
|
|
|
if (!doc) {
|
|
return JS_NULL;
|
|
}
|
|
//dom_node_ref(doc);
|
|
dom_html_collection *anchors = NULL;
|
|
dom_exception exc = dom_html_document_get_anchors(doc, &anchors);
|
|
|
|
if (exc != DOM_NO_ERR || !anchors) {
|
|
//dom_node_unref(doc);
|
|
return JS_NULL;
|
|
}
|
|
JSValue rr = getCollection(ctx, anchors);
|
|
//dom_node_unref(doc);
|
|
|
|
RETURN_JS(rr);
|
|
}
|
|
|
|
static JSValue
|
|
js_document_get_property_baseURI(JSContext *ctx, JSValueConst this_val)
|
|
{
|
|
#ifdef ECMASCRIPT_DEBUG
|
|
fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__);
|
|
#endif
|
|
REF_JS(this_val);
|
|
|
|
struct view_state *vs;
|
|
struct ecmascript_interpreter *interpreter = (struct ecmascript_interpreter *)JS_GetContextOpaque(ctx);
|
|
vs = interpreter->vs;
|
|
|
|
if (!vs) {
|
|
#ifdef ECMASCRIPT_DEBUG
|
|
fprintf(stderr, "%s:%s %d\n", __FILE__, __FUNCTION__, __LINE__);
|
|
#endif
|
|
return JS_NULL;
|
|
}
|
|
|
|
char *str = get_uri_string(vs->uri, URI_BASE);
|
|
|
|
if (!str) {
|
|
#ifdef ECMASCRIPT_DEBUG
|
|
fprintf(stderr, "%s:%s %d\n", __FILE__, __FUNCTION__, __LINE__);
|
|
#endif
|
|
return JS_NULL;
|
|
}
|
|
|
|
JSValue ret = JS_NewString(ctx, str);
|
|
mem_free(str);
|
|
|
|
RETURN_JS(ret);
|
|
}
|
|
|
|
static JSValue
|
|
js_document_get_property_body(JSContext *ctx, JSValueConst this_val)
|
|
{
|
|
#ifdef ECMASCRIPT_DEBUG
|
|
fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__);
|
|
#endif
|
|
REF_JS(this_val);
|
|
|
|
dom_html_document *doc = (struct dom_html_document *)js_doc_getopaque(this_val);
|
|
|
|
if (!doc) {
|
|
return JS_NULL;
|
|
}
|
|
//dom_node_ref(doc);
|
|
|
|
dom_html_element *body = NULL;
|
|
dom_exception exc = dom_html_document_get_body(doc, &body);
|
|
|
|
if (exc != DOM_NO_ERR || !body) {
|
|
//dom_node_unref(doc);
|
|
return JS_NULL;
|
|
}
|
|
//dom_node_unref(doc);
|
|
JSValue rr = getElement(ctx, body);
|
|
#ifdef ECMASCRIPT_DEBUG
|
|
fprintf(stderr, "Before: %s:%d\n", __FUNCTION__, __LINE__);
|
|
#endif
|
|
dom_node_unref(body);
|
|
|
|
return rr;
|
|
}
|
|
|
|
static JSValue
|
|
js_document_set_property_body(JSContext *ctx, JSValueConst this_val, JSValue val)
|
|
{
|
|
#ifdef ECMASCRIPT_DEBUG
|
|
fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__);
|
|
#endif
|
|
REF_JS(this_val);
|
|
REF_JS(val);
|
|
// TODO
|
|
return JS_UNDEFINED;
|
|
}
|
|
|
|
#ifdef CONFIG_COOKIES
|
|
static JSValue
|
|
js_document_get_property_cookie(JSContext *ctx, JSValueConst this_val)
|
|
{
|
|
#ifdef ECMASCRIPT_DEBUG
|
|
fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__);
|
|
#endif
|
|
REF_JS(this_val);
|
|
|
|
struct ecmascript_interpreter *interpreter = (struct ecmascript_interpreter *)JS_GetContextOpaque(ctx);
|
|
struct view_state *vs;
|
|
struct string *cookies;
|
|
vs = interpreter->vs;
|
|
|
|
if (!vs) {
|
|
#ifdef ECMASCRIPT_DEBUG
|
|
fprintf(stderr, "%s:%s %d\n", __FILE__, __FUNCTION__, __LINE__);
|
|
#endif
|
|
return JS_NULL;
|
|
}
|
|
cookies = send_cookies_js(vs->uri);
|
|
|
|
if (cookies) {
|
|
static char cookiestr[1024];
|
|
|
|
strncpy(cookiestr, cookies->source, 1023);
|
|
done_string(cookies);
|
|
|
|
JSValue r = JS_NewString(ctx, cookiestr);
|
|
|
|
RETURN_JS(r);
|
|
} else {
|
|
JSValue rr = JS_NewStringLen(ctx, "", 0);
|
|
|
|
RETURN_JS(rr);
|
|
}
|
|
}
|
|
|
|
static JSValue
|
|
js_document_set_property_cookie(JSContext *ctx, JSValueConst this_val, JSValue val)
|
|
{
|
|
#ifdef ECMASCRIPT_DEBUG
|
|
fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__);
|
|
#endif
|
|
REF_JS(this_val);
|
|
REF_JS(val);
|
|
|
|
struct ecmascript_interpreter *interpreter = (struct ecmascript_interpreter *)JS_GetContextOpaque(ctx);
|
|
struct view_state *vs;
|
|
vs = interpreter->vs;
|
|
|
|
if (!vs) {
|
|
#ifdef ECMASCRIPT_DEBUG
|
|
fprintf(stderr, "%s:%s %d\n", __FILE__, __FUNCTION__, __LINE__);
|
|
#endif
|
|
return JS_NULL;
|
|
}
|
|
const char *text;
|
|
char *str;
|
|
size_t len;
|
|
text = JS_ToCStringLen(ctx, &len, val);
|
|
|
|
if (!text) {
|
|
return JS_EXCEPTION;
|
|
}
|
|
str = stracpy(text);
|
|
if (str) {
|
|
set_cookie(vs->uri, str);
|
|
mem_free(str);
|
|
}
|
|
JS_FreeCString(ctx, text);
|
|
|
|
return JS_UNDEFINED;
|
|
}
|
|
|
|
#endif
|
|
|
|
static JSValue
|
|
js_document_get_property_charset(JSContext *ctx, JSValueConst this_val)
|
|
{
|
|
#ifdef ECMASCRIPT_DEBUG
|
|
fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__);
|
|
#endif
|
|
REF_JS(this_val);
|
|
|
|
// TODO
|
|
JSValue r = JS_NewStringLen(ctx, "utf-8", strlen("utf-8"));
|
|
|
|
RETURN_JS(r);
|
|
}
|
|
|
|
static JSValue
|
|
js_document_get_property_childNodes(JSContext *ctx, JSValueConst this_val)
|
|
{
|
|
#ifdef ECMASCRIPT_DEBUG
|
|
fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__);
|
|
#endif
|
|
REF_JS(this_val);
|
|
|
|
dom_html_document *doc = (struct dom_html_document *)js_doc_getopaque(this_val);
|
|
|
|
if (!doc) {
|
|
return JS_NULL;
|
|
}
|
|
//dom_node_ref(doc);
|
|
|
|
dom_element *root = NULL;
|
|
dom_exception exc = dom_document_get_document_element(doc, &root);
|
|
|
|
if (exc != DOM_NO_ERR || !root) {
|
|
//dom_node_unref(doc);
|
|
return JS_NULL;
|
|
}
|
|
dom_nodelist *nodes = NULL;
|
|
exc = dom_node_get_child_nodes(root, &nodes);
|
|
#ifdef ECMASCRIPT_DEBUG
|
|
fprintf(stderr, "Before: %s:%d\n", __FUNCTION__, __LINE__);
|
|
#endif
|
|
dom_node_unref(root);
|
|
|
|
if (exc != DOM_NO_ERR || !nodes) {
|
|
//dom_node_unref(doc);
|
|
return JS_NULL;
|
|
}
|
|
//dom_node_unref(doc);
|
|
|
|
return getNodeList(ctx, nodes);
|
|
}
|
|
|
|
static JSValue
|
|
js_document_get_property_currentScript(JSContext *ctx, JSValueConst this_val)
|
|
{
|
|
#ifdef ECMASCRIPT_DEBUG
|
|
fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__);
|
|
#endif
|
|
REF_JS(this_val);
|
|
|
|
struct ecmascript_interpreter *interpreter = (struct ecmascript_interpreter *)JS_GetContextOpaque(ctx);
|
|
struct view_state *vs;
|
|
struct document_view *doc_view;
|
|
struct document *document;
|
|
vs = interpreter->vs;
|
|
|
|
if (!vs) {
|
|
#ifdef ECMASCRIPT_DEBUG
|
|
fprintf(stderr, "%s:%s %d\n", __FILE__, __FUNCTION__, __LINE__);
|
|
#endif
|
|
return JS_NULL;
|
|
}
|
|
doc_view = vs->doc_view;
|
|
document = doc_view->document;
|
|
void *mapa = (void *)document->element_map;
|
|
|
|
if (mapa) {
|
|
dom_node *elem = (dom_node *)find_in_map(mapa, interpreter->element_offset);
|
|
|
|
if (elem) {
|
|
dom_string *tag_name = NULL;
|
|
dom_exception exc = dom_node_get_node_name(elem, &tag_name);
|
|
|
|
if (exc != DOM_NO_ERR || !tag_name) {
|
|
return JS_NULL;
|
|
}
|
|
bool isScript = !strcmp("SCRIPT", dom_string_data(tag_name));
|
|
dom_string_unref(tag_name);
|
|
|
|
if (isScript) {
|
|
return getElement(ctx, elem);
|
|
}
|
|
}
|
|
}
|
|
|
|
return JS_NULL;
|
|
}
|
|
|
|
|
|
static JSValue
|
|
js_document_get_property_defaultView(JSContext *ctx, JSValueConst this_val)
|
|
{
|
|
#ifdef ECMASCRIPT_DEBUG
|
|
fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__);
|
|
#endif
|
|
REF_JS(this_val);
|
|
JSValue global_obj = JS_GetGlobalObject(ctx);
|
|
|
|
RETURN_JS(global_obj);
|
|
}
|
|
|
|
static JSValue
|
|
js_document_get_property_doctype(JSContext *ctx, JSValueConst this_val)
|
|
{
|
|
#ifdef ECMASCRIPT_DEBUG
|
|
fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__);
|
|
#endif
|
|
REF_JS(this_val);
|
|
|
|
dom_html_document *doc = (struct dom_html_document *)js_doc_getopaque(this_val);
|
|
|
|
if (!doc) {
|
|
return JS_NULL;
|
|
}
|
|
//dom_node_ref(doc);
|
|
|
|
dom_document_type *dtd;
|
|
dom_document_get_doctype(doc, &dtd);
|
|
//dom_node_unref(doc);
|
|
|
|
return getDoctype(ctx, dtd);
|
|
}
|
|
|
|
static JSValue
|
|
js_document_get_property_documentElement(JSContext *ctx, JSValueConst this_val)
|
|
{
|
|
#ifdef ECMASCRIPT_DEBUG
|
|
fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__);
|
|
#endif
|
|
REF_JS(this_val);
|
|
|
|
dom_html_document *doc = (struct dom_html_document *)js_doc_getopaque(this_val);
|
|
|
|
if (!doc) {
|
|
return JS_NULL;
|
|
}
|
|
//dom_node_ref(doc);
|
|
|
|
dom_html_element *root = NULL;
|
|
dom_exception exc = dom_document_get_document_element(doc, &root);
|
|
|
|
if (exc != DOM_NO_ERR || !root) {
|
|
//dom_node_unref(doc);
|
|
return JS_NULL;
|
|
}
|
|
//dom_node_unref(doc);
|
|
JSValue rr = getElement(ctx, root);
|
|
#ifdef ECMASCRIPT_DEBUG
|
|
fprintf(stderr, "Before: %s:%d\n", __FUNCTION__, __LINE__);
|
|
#endif
|
|
dom_node_unref(root);
|
|
|
|
return rr;
|
|
}
|
|
|
|
static JSValue
|
|
js_document_get_property_documentURI(JSContext *ctx, JSValueConst this_val)
|
|
{
|
|
#ifdef ECMASCRIPT_DEBUG
|
|
fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__);
|
|
#endif
|
|
REF_JS(this_val);
|
|
|
|
struct view_state *vs;
|
|
struct ecmascript_interpreter *interpreter = (struct ecmascript_interpreter *)JS_GetContextOpaque(ctx);
|
|
vs = interpreter->vs;
|
|
|
|
if (!vs) {
|
|
return JS_NULL;
|
|
}
|
|
|
|
char *str = get_uri_string(vs->uri, URI_BASE);
|
|
|
|
if (!str) {
|
|
#ifdef ECMASCRIPT_DEBUG
|
|
fprintf(stderr, "%s:%s %d\n", __FILE__, __FUNCTION__, __LINE__);
|
|
#endif
|
|
return JS_NULL;
|
|
}
|
|
|
|
JSValue ret = JS_NewString(ctx, str);
|
|
mem_free(str);
|
|
|
|
RETURN_JS(ret);
|
|
}
|
|
|
|
static JSValue
|
|
js_document_get_property_domain(JSContext *ctx, JSValueConst this_val)
|
|
{
|
|
#ifdef ECMASCRIPT_DEBUG
|
|
fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__);
|
|
#endif
|
|
REF_JS(this_val);
|
|
|
|
struct view_state *vs;
|
|
struct ecmascript_interpreter *interpreter = (struct ecmascript_interpreter *)JS_GetContextOpaque(ctx);
|
|
vs = interpreter->vs;
|
|
|
|
if (!vs) {
|
|
#ifdef ECMASCRIPT_DEBUG
|
|
fprintf(stderr, "%s:%s %d\n", __FILE__, __FUNCTION__, __LINE__);
|
|
#endif
|
|
return JS_NULL;
|
|
}
|
|
|
|
char *str = get_uri_string(vs->uri, URI_HOST);
|
|
|
|
if (!str) {
|
|
#ifdef ECMASCRIPT_DEBUG
|
|
fprintf(stderr, "%s:%s %d\n", __FILE__, __FUNCTION__, __LINE__);
|
|
#endif
|
|
return JS_NULL;
|
|
}
|
|
|
|
JSValue ret = JS_NewString(ctx, str);
|
|
mem_free(str);
|
|
|
|
RETURN_JS(ret);
|
|
}
|
|
|
|
static JSValue
|
|
js_document_get_property_forms(JSContext *ctx, JSValueConst this_val)
|
|
{
|
|
#ifdef ECMASCRIPT_DEBUG
|
|
fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__);
|
|
#endif
|
|
REF_JS(this_val);
|
|
|
|
dom_html_document *doc = (struct dom_html_document *)js_doc_getopaque(this_val);
|
|
|
|
if (!doc) {
|
|
return JS_NULL;
|
|
}
|
|
//dom_node_ref(doc);
|
|
|
|
dom_html_collection *forms = NULL;
|
|
dom_exception exc = dom_html_document_get_forms(doc, &forms);
|
|
|
|
if (exc != DOM_NO_ERR || !forms) {
|
|
//dom_node_unref(doc);
|
|
return JS_NULL;
|
|
}
|
|
JSValue rr = getForms(ctx, forms);
|
|
JS_FreeValue(ctx, rr);
|
|
//dom_node_unref(doc);
|
|
|
|
RETURN_JS(rr);
|
|
}
|
|
|
|
static JSValue
|
|
js_document_get_property_head(JSContext *ctx, JSValueConst this_val)
|
|
{
|
|
#ifdef ECMASCRIPT_DEBUG
|
|
fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__);
|
|
#endif
|
|
REF_JS(this_val);
|
|
|
|
// TODO
|
|
return JS_NULL;
|
|
|
|
// return getElement(ctx, element);
|
|
}
|
|
|
|
static JSValue
|
|
js_document_get_property_images(JSContext *ctx, JSValueConst this_val)
|
|
{
|
|
#ifdef ECMASCRIPT_DEBUG
|
|
fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__);
|
|
#endif
|
|
REF_JS(this_val);
|
|
|
|
dom_html_document *doc = (struct dom_html_document *)js_doc_getopaque(this_val);
|
|
|
|
if (!doc) {
|
|
return JS_NULL;
|
|
}
|
|
//dom_node_ref(doc);
|
|
|
|
dom_html_collection *images = NULL;
|
|
dom_exception exc = dom_html_document_get_images(doc, &images);
|
|
|
|
if (exc != DOM_NO_ERR || !images) {
|
|
//dom_node_unref(doc);
|
|
return JS_NULL;
|
|
}
|
|
JSValue rr = getCollection(ctx, images);
|
|
//dom_node_unref(doc);
|
|
|
|
RETURN_JS(rr);
|
|
}
|
|
|
|
static JSValue
|
|
js_document_get_property_implementation(JSContext *ctx, JSValueConst this_val)
|
|
{
|
|
#ifdef ECMASCRIPT_DEBUG
|
|
fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__);
|
|
#endif
|
|
REF_JS(this_val);
|
|
|
|
return getImplementation(ctx);
|
|
}
|
|
|
|
static JSValue
|
|
js_document_get_property_links(JSContext *ctx, JSValueConst this_val)
|
|
{
|
|
#ifdef ECMASCRIPT_DEBUG
|
|
fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__);
|
|
#endif
|
|
REF_JS(this_val);
|
|
|
|
dom_html_document *doc = (struct dom_html_document *)js_doc_getopaque(this_val);
|
|
|
|
if (!doc) {
|
|
return JS_NULL;
|
|
}
|
|
//dom_node_ref(doc);
|
|
dom_html_collection *links = NULL;
|
|
dom_exception exc = dom_html_document_get_links(doc, &links);
|
|
|
|
if (exc != DOM_NO_ERR || !links) {
|
|
//dom_node_unref(doc);
|
|
return JS_NULL;
|
|
}
|
|
JSValue rr = getCollection(ctx, links);
|
|
//dom_node_unref(doc);
|
|
|
|
RETURN_JS(rr);
|
|
}
|
|
|
|
static JSValue
|
|
js_document_get_property_location(JSContext *ctx, JSValueConst this_val)
|
|
{
|
|
#ifdef ECMASCRIPT_DEBUG
|
|
fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__);
|
|
#endif
|
|
REF_JS(this_val);
|
|
JSValue ret = getLocation(ctx);
|
|
|
|
RETURN_JS(ret);
|
|
}
|
|
|
|
static JSValue
|
|
js_document_get_property_nodeType(JSContext *ctx, JSValueConst this_val)
|
|
{
|
|
#ifdef ECMASCRIPT_DEBUG
|
|
fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__);
|
|
#endif
|
|
REF_JS(this_val);
|
|
|
|
return JS_NewInt32(ctx, 9);
|
|
}
|
|
|
|
static JSValue
|
|
js_document_set_property_location(JSContext *ctx, JSValueConst this_val, JSValue val)
|
|
{
|
|
#ifdef ECMASCRIPT_DEBUG
|
|
fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__);
|
|
#endif
|
|
REF_JS(this_val);
|
|
REF_JS(val);
|
|
|
|
struct ecmascript_interpreter *interpreter = (struct ecmascript_interpreter *)JS_GetContextOpaque(ctx);
|
|
struct view_state *vs;
|
|
struct document_view *doc_view;
|
|
vs = interpreter->vs;
|
|
|
|
if (!vs) {
|
|
#ifdef ECMASCRIPT_DEBUG
|
|
fprintf(stderr, "%s:%s %d\n", __FILE__, __FUNCTION__, __LINE__);
|
|
#endif
|
|
return JS_NULL;
|
|
}
|
|
doc_view = vs->doc_view;
|
|
const char *url;
|
|
size_t len;
|
|
|
|
url = JS_ToCStringLen(ctx, &len, val);
|
|
|
|
if (!url) {
|
|
return JS_EXCEPTION;
|
|
}
|
|
|
|
location_goto_const(doc_view, url, 0);
|
|
JS_FreeCString(ctx, url);
|
|
|
|
return JS_UNDEFINED;
|
|
}
|
|
|
|
static JSValue
|
|
js_document_get_property_readyState(JSContext *ctx, JSValueConst this_val)
|
|
{
|
|
#ifdef ECMASCRIPT_DEBUG
|
|
fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__);
|
|
#endif
|
|
REF_JS(this_val);
|
|
struct js_document_private *doc_private = (struct js_document_private *)(JS_GetOpaque(this_val, js_document_class_id));
|
|
|
|
if (!doc_private) {
|
|
return JS_NULL;
|
|
}
|
|
JSValue r;
|
|
|
|
switch (doc_private->state) {
|
|
case LOADING:
|
|
r = JS_NewString(ctx, "loading");
|
|
break;
|
|
case INTERACTIVE:
|
|
r = JS_NewString(ctx, "interactive");
|
|
break;
|
|
case COMPLETE:
|
|
r = JS_NewString(ctx, "complete");
|
|
break;
|
|
}
|
|
RETURN_JS(r);
|
|
}
|
|
|
|
static JSValue
|
|
js_document_get_property_referrer(JSContext *ctx, JSValueConst this_val)
|
|
{
|
|
#ifdef ECMASCRIPT_DEBUG
|
|
fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__);
|
|
#endif
|
|
REF_JS(this_val);
|
|
|
|
struct ecmascript_interpreter *interpreter = (struct ecmascript_interpreter *)JS_GetContextOpaque(ctx);
|
|
struct view_state *vs;
|
|
struct document_view *doc_view;
|
|
struct document *document;
|
|
struct session *ses;
|
|
char *str;
|
|
vs = interpreter->vs;
|
|
|
|
if (!vs) {
|
|
#ifdef ECMASCRIPT_DEBUG
|
|
fprintf(stderr, "%s:%s %d\n", __FILE__, __FUNCTION__, __LINE__);
|
|
#endif
|
|
return JS_NULL;
|
|
}
|
|
doc_view = vs->doc_view;
|
|
document = doc_view->document;
|
|
ses = doc_view->session;
|
|
|
|
switch (get_opt_int("protocol.http.referer.policy", NULL)) {
|
|
case REFERER_NONE:
|
|
/* oh well */
|
|
return JS_UNDEFINED;
|
|
|
|
case REFERER_FAKE:
|
|
return JS_NewString(ctx, get_opt_str("protocol.http.referer.fake", NULL));
|
|
|
|
case REFERER_TRUE:
|
|
/* XXX: Encode as in add_url_to_httset_prop_string(&prop, ) ? --pasky */
|
|
if (ses->referrer) {
|
|
str = get_uri_string(ses->referrer, URI_HTTP_REFERRER);
|
|
|
|
if (str) {
|
|
JSValue ret = JS_NewString(ctx, str);
|
|
mem_free(str);
|
|
|
|
RETURN_JS(ret);
|
|
} else {
|
|
return JS_UNDEFINED;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case REFERER_SAME_URL:
|
|
str = get_uri_string(document->uri, URI_HTTP_REFERRER);
|
|
|
|
if (str) {
|
|
JSValue ret = JS_NewString(ctx, str);
|
|
mem_free(str);
|
|
|
|
RETURN_JS(ret);
|
|
} else {
|
|
return JS_UNDEFINED;
|
|
}
|
|
break;
|
|
}
|
|
|
|
return JS_UNDEFINED;
|
|
}
|
|
|
|
static JSValue
|
|
js_document_get_property_scripts(JSContext *ctx, JSValueConst this_val)
|
|
{
|
|
#ifdef ECMASCRIPT_DEBUG
|
|
fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__);
|
|
#endif
|
|
REF_JS(this_val);
|
|
|
|
// TODO
|
|
//dom_html_document *doc = (dom_html_document *)document->dom;
|
|
|
|
return JS_NULL;
|
|
|
|
// JSValue rr = getCollection(ctx, elements);
|
|
// JS_FreeValue(ctx, rr);
|
|
|
|
// RETURN_JS(rr);
|
|
}
|
|
|
|
static JSValue
|
|
js_document_get_property_title(JSContext *ctx, JSValueConst this_val)
|
|
{
|
|
#ifdef ECMASCRIPT_DEBUG
|
|
fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__);
|
|
#endif
|
|
REF_JS(this_val);
|
|
|
|
struct ecmascript_interpreter *interpreter = (struct ecmascript_interpreter *)JS_GetContextOpaque(ctx);
|
|
struct view_state *vs;
|
|
struct document_view *doc_view;
|
|
struct document *document;
|
|
|
|
vs = interpreter->vs;
|
|
|
|
if (!vs) {
|
|
#ifdef ECMASCRIPT_DEBUG
|
|
fprintf(stderr, "%s:%s %d\n", __FILE__, __FUNCTION__, __LINE__);
|
|
#endif
|
|
return JS_NULL;
|
|
}
|
|
doc_view = vs->doc_view;
|
|
document = doc_view->document;
|
|
JSValue r = JS_NewString(ctx, document->title);
|
|
RETURN_JS(r);
|
|
}
|
|
|
|
static JSValue
|
|
js_document_set_property_title(JSContext *ctx, JSValueConst this_val, JSValue val)
|
|
{
|
|
#ifdef ECMASCRIPT_DEBUG
|
|
fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__);
|
|
#endif
|
|
REF_JS(this_val);
|
|
REF_JS(val);
|
|
|
|
struct ecmascript_interpreter *interpreter = (struct ecmascript_interpreter *)JS_GetContextOpaque(ctx);
|
|
struct view_state *vs;
|
|
struct document_view *doc_view;
|
|
struct document *document;
|
|
vs = interpreter->vs;
|
|
|
|
if (!vs || !vs->doc_view) {
|
|
#ifdef ECMASCRIPT_DEBUG
|
|
fprintf(stderr, "%s:%s %d\n", __FILE__, __FUNCTION__, __LINE__);
|
|
#endif
|
|
return JS_NULL;
|
|
}
|
|
doc_view = vs->doc_view;
|
|
document = doc_view->document;
|
|
|
|
const char *str;
|
|
char *string;
|
|
size_t len;
|
|
|
|
str = JS_ToCStringLen(ctx, &len, val);
|
|
|
|
if (!str) {
|
|
return JS_EXCEPTION;
|
|
}
|
|
|
|
string = stracpy(str);
|
|
JS_FreeCString(ctx, str);
|
|
|
|
mem_free_set(&document->title, string);
|
|
print_screen_status(doc_view->session);
|
|
|
|
return JS_UNDEFINED;
|
|
}
|
|
|
|
static JSValue
|
|
js_document_get_property_url(JSContext *ctx, JSValueConst this_val)
|
|
{
|
|
#ifdef ECMASCRIPT_DEBUG
|
|
fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__);
|
|
#endif
|
|
REF_JS(this_val);
|
|
|
|
struct ecmascript_interpreter *interpreter = (struct ecmascript_interpreter *)JS_GetContextOpaque(ctx);
|
|
struct view_state *vs;
|
|
struct document_view *doc_view;
|
|
struct document *document;
|
|
vs = interpreter->vs;
|
|
|
|
if (!vs) {
|
|
#ifdef ECMASCRIPT_DEBUG
|
|
fprintf(stderr, "%s:%s %d\n", __FILE__, __FUNCTION__, __LINE__);
|
|
#endif
|
|
return JS_NULL;
|
|
}
|
|
doc_view = vs->doc_view;
|
|
document = doc_view->document;
|
|
char *str = get_uri_string(document->uri, URI_ORIGINAL);
|
|
|
|
if (str) {
|
|
JSValue ret = JS_NewString(ctx, str);
|
|
mem_free(str);
|
|
|
|
RETURN_JS(ret);
|
|
} else {
|
|
return JS_UNDEFINED;
|
|
}
|
|
}
|
|
|
|
static JSValue
|
|
js_document_set_property_url(JSContext *ctx, JSValueConst this_val, JSValue val)
|
|
{
|
|
#ifdef ECMASCRIPT_DEBUG
|
|
fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__);
|
|
#endif
|
|
REF_JS(this_val);
|
|
REF_JS(val);
|
|
|
|
struct ecmascript_interpreter *interpreter = (struct ecmascript_interpreter *)JS_GetContextOpaque(ctx);
|
|
struct view_state *vs;
|
|
struct document_view *doc_view;
|
|
vs = interpreter->vs;
|
|
|
|
if (!vs) {
|
|
#ifdef ECMASCRIPT_DEBUG
|
|
fprintf(stderr, "%s:%s %d\n", __FILE__, __FUNCTION__, __LINE__);
|
|
#endif
|
|
return JS_NULL;
|
|
}
|
|
doc_view = vs->doc_view;
|
|
const char *url;
|
|
size_t len;
|
|
|
|
url = JS_ToCStringLen(ctx, &len, val);
|
|
|
|
if (!url) {
|
|
return JS_EXCEPTION;
|
|
}
|
|
location_goto_const(doc_view, url, 0);
|
|
JS_FreeCString(ctx, url);
|
|
|
|
return JS_UNDEFINED;
|
|
}
|
|
|
|
|
|
static JSValue
|
|
js_document_write_do(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv, int newline)
|
|
{
|
|
#ifdef ECMASCRIPT_DEBUG
|
|
fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__);
|
|
#endif
|
|
REF_JS(this_val);
|
|
|
|
struct ecmascript_interpreter *interpreter = (struct ecmascript_interpreter *)JS_GetContextOpaque(ctx);
|
|
|
|
if (argc >= 1) {
|
|
int element_offset = interpreter->element_offset;
|
|
struct string string;
|
|
|
|
if (init_string(&string)) {
|
|
for (int i = 0; i < argc; ++i) {
|
|
const char *str;
|
|
size_t len;
|
|
|
|
str = JS_ToCStringLen(ctx, &len, argv[i]);
|
|
|
|
if (!str) {
|
|
done_string(&string);
|
|
return JS_EXCEPTION;
|
|
}
|
|
add_bytes_to_string(&string, str, len);
|
|
JS_FreeCString(ctx, str);
|
|
}
|
|
|
|
if (newline) {
|
|
add_to_string(&string, "\n");
|
|
}
|
|
|
|
if (element_offset == interpreter->current_writecode->element_offset) {
|
|
add_string_to_string(&interpreter->current_writecode->string, &string);
|
|
done_string(&string);
|
|
} else {
|
|
(void)add_to_ecmascript_string_list(&interpreter->writecode, string.source, string.length, element_offset);
|
|
done_string(&string);
|
|
interpreter->current_writecode = interpreter->current_writecode->next;
|
|
}
|
|
interpreter->changed = 1;
|
|
interpreter->was_write = 1;
|
|
}
|
|
}
|
|
|
|
#ifdef CONFIG_LEDS
|
|
set_led_value(interpreter->vs->doc_view->session->status.ecmascript_led, 'J');
|
|
#endif
|
|
return JS_FALSE;
|
|
}
|
|
|
|
/* @document_funcs{"write"} */
|
|
static JSValue
|
|
js_document_write(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
|
|
{
|
|
#ifdef ECMASCRIPT_DEBUG
|
|
fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__);
|
|
#endif
|
|
REF_JS(this_val);
|
|
|
|
return js_document_write_do(ctx, this_val, argc, argv, 0);
|
|
}
|
|
|
|
/* @document_funcs{"writeln"} */
|
|
static JSValue
|
|
js_document_writeln(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
|
|
{
|
|
#ifdef ECMASCRIPT_DEBUG
|
|
fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__);
|
|
#endif
|
|
REF_JS(this_val);
|
|
|
|
return js_document_write_do(ctx, this_val, argc, argv, 1);
|
|
}
|
|
|
|
/* @document_funcs{"replace"} */
|
|
static JSValue
|
|
js_document_replace(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
|
|
{
|
|
#ifdef ECMASCRIPT_DEBUG
|
|
fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__);
|
|
#endif
|
|
REF_JS(this_val);
|
|
|
|
struct ecmascript_interpreter *interpreter = (struct ecmascript_interpreter *)JS_GetContextOpaque(ctx);
|
|
struct document_view *doc_view = interpreter->vs->doc_view;
|
|
struct document *document;
|
|
document = doc_view->document;
|
|
|
|
if (argc != 2) {
|
|
return JS_FALSE;
|
|
}
|
|
|
|
struct string needle;
|
|
struct string heystack;
|
|
|
|
if (!init_string(&needle)) {
|
|
return JS_EXCEPTION;
|
|
}
|
|
if (!init_string(&heystack)) {
|
|
done_string(&needle);
|
|
return JS_EXCEPTION;
|
|
}
|
|
|
|
const char *str;
|
|
size_t len;
|
|
|
|
str = JS_ToCStringLen(ctx, &len, argv[0]);
|
|
|
|
if (str) {
|
|
add_bytes_to_string(&needle, str, len);
|
|
JS_FreeCString(ctx, str);
|
|
}
|
|
|
|
str = JS_ToCStringLen(ctx, &len, argv[1]);
|
|
|
|
if (str) {
|
|
add_bytes_to_string(&heystack, str, len);
|
|
JS_FreeCString(ctx, str);
|
|
}
|
|
//DBG("doc replace %s %s\n", needle.source, heystack.source);
|
|
|
|
struct cache_entry *cached = doc_view->document->cached;
|
|
struct fragment *f = get_cache_fragment(cached);
|
|
|
|
if (f && f->length)
|
|
{
|
|
struct string f_data;
|
|
if (init_string(&f_data)) {
|
|
add_bytes_to_string(&f_data, f->data, f->length);
|
|
|
|
struct string nu_str;
|
|
if (init_string(&nu_str)) {
|
|
el_string_replace(&nu_str, &f_data, &needle, &heystack);
|
|
delete_entry_content(cached);
|
|
/* TBD: somehow better rerender the document
|
|
* now it's places on the session level in doc_loading_callback */
|
|
add_fragment(cached, 0, nu_str.source, nu_str.length);
|
|
normalize_cache_entry(cached, nu_str.length);
|
|
document->ecmascript_counter++;
|
|
done_string(&nu_str);
|
|
}
|
|
//DBG("doc replace %s %s\n", needle.source, heystack.source);
|
|
done_string(&f_data);
|
|
}
|
|
}
|
|
|
|
done_string(&needle);
|
|
done_string(&heystack);
|
|
|
|
return JS_TRUE;
|
|
}
|
|
|
|
static JSValue
|
|
js_document_addEventListener(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
|
|
{
|
|
#ifdef ECMASCRIPT_DEBUG
|
|
fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__);
|
|
#endif
|
|
REF_JS(this_val);
|
|
|
|
struct js_document_private *doc_private = (struct js_document_private *)(JS_GetOpaque(this_val, js_document_class_id));
|
|
|
|
if (!doc_private) {
|
|
return JS_NULL;
|
|
}
|
|
dom_html_document *doc = doc_private->node;
|
|
|
|
if (argc < 2) {
|
|
return JS_UNDEFINED;
|
|
}
|
|
const char *str;
|
|
size_t len;
|
|
str = JS_ToCStringLen(ctx, &len, argv[0]);
|
|
|
|
if (!str) {
|
|
return JS_EXCEPTION;
|
|
}
|
|
char *method = stracpy(str);
|
|
JS_FreeCString(ctx, str);
|
|
|
|
if (!method) {
|
|
return JS_EXCEPTION;
|
|
}
|
|
JSValue fun = argv[1];
|
|
struct document_listener *l;
|
|
|
|
foreach(l, doc_private->listeners) {
|
|
if (strcmp(l->typ, method)) {
|
|
continue;
|
|
}
|
|
|
|
if (JS_VALUE_GET_PTR(l->fun) == JS_VALUE_GET_PTR(fun)) {
|
|
mem_free(method);
|
|
return JS_UNDEFINED;
|
|
}
|
|
}
|
|
struct document_listener *n = (struct document_listener *)mem_calloc(1, sizeof(*n));
|
|
|
|
if (!n) {
|
|
return JS_UNDEFINED;
|
|
}
|
|
n->fun = JS_DupValue(ctx, fun);
|
|
n->typ = method;
|
|
add_to_list_end(doc_private->listeners, n);
|
|
dom_exception exc;
|
|
|
|
if (doc_private->listener) {
|
|
dom_event_listener_ref(doc_private->listener);
|
|
} else {
|
|
exc = dom_event_listener_create(document_event_handler, doc_private, &doc_private->listener);
|
|
|
|
if (exc != DOM_NO_ERR || !doc_private->listener) {
|
|
return JS_UNDEFINED;
|
|
}
|
|
}
|
|
dom_string *typ = NULL;
|
|
exc = dom_string_create((const uint8_t *)method, strlen(method), &typ);
|
|
|
|
if (exc != DOM_NO_ERR || !typ) {
|
|
goto ex;
|
|
}
|
|
exc = dom_event_target_add_event_listener(doc, typ, doc_private->listener, false);
|
|
|
|
if (exc == DOM_NO_ERR) {
|
|
dom_event_listener_ref(doc_private->listener);
|
|
}
|
|
|
|
ex:
|
|
if (typ) {
|
|
dom_string_unref(typ);
|
|
}
|
|
dom_event_listener_unref(doc_private->listener);
|
|
|
|
return JS_UNDEFINED;
|
|
}
|
|
|
|
static JSValue
|
|
js_document_dispatchEvent(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
|
|
{
|
|
#ifdef ECMASCRIPT_DEBUG
|
|
fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__);
|
|
#endif
|
|
REF_JS(this_val);
|
|
|
|
struct js_document_private *doc_private = (struct js_document_private *)(JS_GetOpaque(this_val, js_document_class_id));
|
|
|
|
if (!doc_private) {
|
|
return JS_FALSE;
|
|
}
|
|
dom_html_document *doc = doc_private->node;
|
|
|
|
if (!doc) {
|
|
return JS_FALSE;
|
|
}
|
|
//dom_node_ref(doc);
|
|
|
|
if (argc < 1) {
|
|
//dom_node_unref(doc);
|
|
return JS_FALSE;
|
|
}
|
|
JSValue eve = argv[0];
|
|
dom_event *event = (dom_event *)(JS_GetOpaque(eve, js_event_class_id));
|
|
|
|
if (event) {
|
|
dom_event_ref(event);
|
|
}
|
|
bool result = false;
|
|
(void)dom_event_target_dispatch_event(doc, event, &result);
|
|
|
|
if (event) {
|
|
dom_event_unref(event);
|
|
}
|
|
//dom_node_unref(doc);
|
|
|
|
return JS_NewBool(ctx, result);
|
|
}
|
|
|
|
static JSValue
|
|
js_document_removeEventListener(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
|
|
{
|
|
#ifdef ECMASCRIPT_DEBUG
|
|
fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__);
|
|
#endif
|
|
REF_JS(this_val);
|
|
|
|
struct js_document_private *doc_private = (struct js_document_private *)(JS_GetOpaque(this_val, js_document_class_id));
|
|
|
|
if (!doc_private) {
|
|
return JS_NULL;
|
|
}
|
|
//dom_node_ref(doc);
|
|
|
|
if (argc < 2) {
|
|
//dom_node_unref(doc);
|
|
return JS_UNDEFINED;
|
|
}
|
|
const char *str;
|
|
size_t len;
|
|
str = JS_ToCStringLen(ctx, &len, argv[0]);
|
|
|
|
if (!str) {
|
|
//dom_node_unref(doc);
|
|
return JS_EXCEPTION;
|
|
}
|
|
char *method = stracpy(str);
|
|
JS_FreeCString(ctx, str);
|
|
|
|
if (!method) {
|
|
//dom_node_unref(doc);
|
|
return JS_EXCEPTION;
|
|
}
|
|
JSValue fun = argv[1];
|
|
struct document_listener *l;
|
|
|
|
foreach(l, doc_private->listeners) {
|
|
if (strcmp(l->typ, method)) {
|
|
continue;
|
|
}
|
|
|
|
if (JS_VALUE_GET_PTR(l->fun) == JS_VALUE_GET_PTR(fun)) {
|
|
dom_string *typ = NULL;
|
|
dom_exception exc = dom_string_create((const uint8_t *)method, strlen(method), &typ);
|
|
|
|
if (exc != DOM_NO_ERR || !typ) {
|
|
continue;
|
|
}
|
|
//dom_event_target_remove_event_listener(doc, typ, doc_private->listener, false);
|
|
dom_string_unref(typ);
|
|
|
|
del_from_list(l);
|
|
mem_free_set(&l->typ, NULL);
|
|
mem_free(l);
|
|
mem_free(method);
|
|
//dom_node_unref(doc);
|
|
|
|
return JS_UNDEFINED;
|
|
}
|
|
}
|
|
mem_free(method);
|
|
//dom_node_unref(doc);
|
|
|
|
return JS_UNDEFINED;
|
|
}
|
|
|
|
static JSValue
|
|
js_document_createComment(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
|
|
{
|
|
#ifdef ECMASCRIPT_DEBUG
|
|
fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__);
|
|
#endif
|
|
REF_JS(this_val);
|
|
|
|
if (argc != 1) {
|
|
return JS_FALSE;
|
|
}
|
|
dom_html_document *doc = (struct dom_html_document *)js_doc_getopaque(this_val);
|
|
|
|
if (!doc) {
|
|
return JS_NULL;
|
|
}
|
|
//dom_node_ref(doc);
|
|
|
|
dom_string *data = NULL;
|
|
dom_exception exc;
|
|
const char *str;
|
|
size_t len;
|
|
|
|
str = JS_ToCStringLen(ctx, &len, argv[0]);
|
|
|
|
if (!str) {
|
|
//dom_node_unref(doc);
|
|
return JS_EXCEPTION;
|
|
}
|
|
exc = dom_string_create((const uint8_t *)str, len, &data);
|
|
JS_FreeCString(ctx, str);
|
|
|
|
if (exc != DOM_NO_ERR || !data) {
|
|
//dom_node_unref(doc);
|
|
return JS_NULL;
|
|
}
|
|
dom_comment *comment = NULL;
|
|
exc = dom_document_create_comment(doc, data, &comment);
|
|
dom_string_unref(data);
|
|
|
|
if (exc != DOM_NO_ERR || !comment) {
|
|
//dom_node_unref(doc);
|
|
return JS_NULL;
|
|
}
|
|
//dom_node_unref(doc);
|
|
|
|
return getElement(ctx, comment);
|
|
}
|
|
|
|
static JSValue
|
|
js_document_createDocumentFragment(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
|
|
{
|
|
#ifdef ECMASCRIPT_DEBUG
|
|
fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__);
|
|
#endif
|
|
REF_JS(this_val);
|
|
|
|
if (argc != 0) {
|
|
return JS_FALSE;
|
|
}
|
|
dom_html_document *doc = (struct dom_html_document *)js_doc_getopaque(this_val);
|
|
|
|
if (!doc) {
|
|
return JS_NULL;
|
|
}
|
|
//dom_node_ref(doc);
|
|
|
|
dom_document_fragment *fragment = NULL;
|
|
dom_exception exc = dom_document_create_document_fragment(doc, &fragment);
|
|
|
|
if (exc != DOM_NO_ERR || !fragment) {
|
|
//dom_node_unref(doc);
|
|
return JS_NULL;
|
|
}
|
|
//dom_node_unref(doc);
|
|
|
|
return getDocumentFragment(ctx, fragment);
|
|
}
|
|
|
|
static JSValue
|
|
js_document_createElement(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
|
|
{
|
|
#ifdef ECMASCRIPT_DEBUG
|
|
fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__);
|
|
#endif
|
|
REF_JS(this_val);
|
|
|
|
if (argc != 1) {
|
|
return JS_FALSE;
|
|
}
|
|
dom_html_document *doc = (struct dom_html_document *)js_doc_getopaque(this_val);
|
|
|
|
if (!doc) {
|
|
return JS_NULL;
|
|
}
|
|
//dom_node_ref(doc);
|
|
|
|
dom_string *tag_name = NULL;
|
|
dom_exception exc;
|
|
const char *str;
|
|
size_t len;
|
|
|
|
str = JS_ToCStringLen(ctx, &len, argv[0]);
|
|
|
|
if (!str) {
|
|
//dom_node_unref(doc);
|
|
return JS_EXCEPTION;
|
|
}
|
|
exc = dom_string_create((const uint8_t *)str, len, &tag_name);
|
|
JS_FreeCString(ctx, str);
|
|
|
|
if (exc != DOM_NO_ERR || !tag_name) {
|
|
//dom_node_unref(doc);
|
|
return JS_NULL;
|
|
}
|
|
dom_element *element = NULL;
|
|
exc = dom_document_create_element(doc, tag_name, &element);
|
|
dom_string_unref(tag_name);
|
|
|
|
if (exc != DOM_NO_ERR || !element) {
|
|
//dom_node_unref(doc);
|
|
return JS_NULL;
|
|
}
|
|
//dom_node_unref(doc);
|
|
JSValue rr = getElement(ctx, element);
|
|
#ifdef ECMASCRIPT_DEBUG
|
|
fprintf(stderr, "Before: %s:%d\n", __FUNCTION__, __LINE__);
|
|
#endif
|
|
dom_node_unref(element);
|
|
|
|
return rr;
|
|
}
|
|
|
|
static JSValue
|
|
js_document_createTextNode(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
|
|
{
|
|
#ifdef ECMASCRIPT_DEBUG
|
|
fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__);
|
|
#endif
|
|
REF_JS(this_val);
|
|
|
|
if (argc != 1) {
|
|
return JS_FALSE;
|
|
}
|
|
dom_html_document *doc = (struct dom_html_document *)js_doc_getopaque(this_val);
|
|
|
|
if (!doc) {
|
|
return JS_NULL;
|
|
}
|
|
//dom_node_ref(doc);
|
|
|
|
dom_string *data = NULL;
|
|
dom_exception exc;
|
|
const char *str;
|
|
size_t len;
|
|
|
|
str = JS_ToCStringLen(ctx, &len, argv[0]);
|
|
|
|
if (!str) {
|
|
//dom_node_unref(doc);
|
|
return JS_EXCEPTION;
|
|
}
|
|
exc = dom_string_create((const uint8_t *)str, len, &data);
|
|
JS_FreeCString(ctx, str);
|
|
|
|
if (exc != DOM_NO_ERR || !data) {
|
|
//dom_node_unref(doc);
|
|
return JS_NULL;
|
|
}
|
|
dom_text *text_node = NULL;
|
|
exc = dom_document_create_text_node(doc, data, &text_node);
|
|
dom_string_unref(data);
|
|
|
|
if (exc != DOM_NO_ERR || !text_node) {
|
|
//dom_node_unref(doc);
|
|
return JS_NULL;
|
|
}
|
|
//dom_node_unref(doc);
|
|
|
|
return getText(ctx, text_node);
|
|
}
|
|
|
|
static JSValue
|
|
js_document_getElementById(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
|
|
{
|
|
#ifdef ECMASCRIPT_DEBUG
|
|
fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__);
|
|
#endif
|
|
REF_JS(this_val);
|
|
|
|
if (argc != 1) {
|
|
return JS_FALSE;
|
|
}
|
|
dom_html_document *doc = (struct dom_html_document *)js_doc_getopaque(this_val);
|
|
|
|
if (!doc) {
|
|
return JS_NULL;
|
|
}
|
|
//dom_node_ref(doc);
|
|
|
|
dom_string *id = NULL;
|
|
dom_exception exc;
|
|
const char *str;
|
|
size_t len;
|
|
|
|
str = JS_ToCStringLen(ctx, &len, argv[0]);
|
|
|
|
if (!str) {
|
|
//dom_node_unref(doc);
|
|
return JS_EXCEPTION;
|
|
}
|
|
exc = dom_string_create((const uint8_t *)str, len, &id);
|
|
JS_FreeCString(ctx, str);
|
|
|
|
if (exc != DOM_NO_ERR || !id) {
|
|
//dom_node_unref(doc);
|
|
return JS_NULL;
|
|
}
|
|
dom_element *element = NULL;
|
|
exc = dom_document_get_element_by_id(doc, id, &element);
|
|
dom_string_unref(id);
|
|
|
|
if (exc != DOM_NO_ERR || !element) {
|
|
//dom_node_unref(doc);
|
|
return JS_NULL;
|
|
}
|
|
//dom_node_unref(doc);
|
|
JSValue rr = getElement(ctx, element);
|
|
#ifdef ECMASCRIPT_DEBUG
|
|
fprintf(stderr, "Before: %s:%d\n", __FUNCTION__, __LINE__);
|
|
#endif
|
|
dom_node_unref(element);
|
|
|
|
return rr;
|
|
}
|
|
|
|
static JSValue
|
|
js_document_getElementsByClassName(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
|
|
{
|
|
#ifdef ECMASCRIPT_DEBUG
|
|
fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__);
|
|
#endif
|
|
REF_JS(this_val);
|
|
dom_html_document *doc = (struct dom_html_document *)js_doc_getopaque(this_val);
|
|
|
|
if (!doc) {
|
|
return JS_NULL;
|
|
}
|
|
|
|
if (argc != 1) {
|
|
return JS_NULL;
|
|
}
|
|
const char *classes = JS_ToCString(ctx, argv[0]);
|
|
dom_html_collection *col = (dom_html_collection *)get_elements_by_class_name(doc, (dom_node *)doc, classes);
|
|
|
|
if (classes) {
|
|
JS_FreeCString(ctx, classes);
|
|
}
|
|
if (!col) {
|
|
return JS_NULL;
|
|
}
|
|
JSValue ret = getCollection2(ctx, col);
|
|
|
|
RETURN_JS(ret);
|
|
}
|
|
|
|
#if 0
|
|
static JSValue
|
|
js_document_getElementsByName(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
|
|
{
|
|
#ifdef ECMASCRIPT_DEBUG
|
|
fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__);
|
|
#endif
|
|
REF_JS(this_val);
|
|
|
|
if (argc != 1) {
|
|
return JS_FALSE;
|
|
}
|
|
struct ecmascript_interpreter *interpreter = (struct ecmascript_interpreter *)JS_GetContextOpaque(ctx);
|
|
|
|
// TODO
|
|
return JS_NULL;
|
|
#if 0
|
|
xmlpp::Document *docu = (xmlpp::Document *)document->dom;
|
|
xmlpp::Element* root = (xmlpp::Element *)docu->get_root_node();
|
|
|
|
const char *str;
|
|
size_t len;
|
|
|
|
str = JS_ToCStringLen(ctx, &len, argv[0]);
|
|
|
|
if (!str) {
|
|
return JS_EXCEPTION;
|
|
}
|
|
xmlpp::ustring id = str;
|
|
JS_FreeCString(ctx, str);
|
|
xmlpp::ustring xpath = "//*[@id=\"";
|
|
xpath += id;
|
|
xpath += "\"]|//*[@name=\"";
|
|
xpath += id;
|
|
xpath += "\"]";
|
|
xmlpp::Node::NodeSet *elements = new(std::nothrow) xmlpp::Node::NodeSet;
|
|
|
|
if (!elements) {
|
|
return JS_NULL;
|
|
}
|
|
*elements = root->find(xpath);
|
|
JSValue rr = getCollection(ctx, elements);
|
|
JS_FreeValue(ctx, rr);
|
|
|
|
RETURN_JS(rr);
|
|
#endif
|
|
}
|
|
#endif
|
|
|
|
static JSValue
|
|
js_document_getElementsByTagName(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
|
|
{
|
|
#ifdef ECMASCRIPT_DEBUG
|
|
fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__);
|
|
#endif
|
|
REF_JS(this_val);
|
|
|
|
if (argc != 1) {
|
|
return JS_FALSE;
|
|
}
|
|
dom_html_document *doc = (struct dom_html_document *)js_doc_getopaque(this_val);
|
|
|
|
if (!doc) {
|
|
return JS_NULL;
|
|
}
|
|
//dom_node_ref(doc);
|
|
|
|
dom_string *tagname = NULL;
|
|
dom_exception exc;
|
|
const char *str;
|
|
size_t len;
|
|
|
|
str = JS_ToCStringLen(ctx, &len, argv[0]);
|
|
|
|
if (!str) {
|
|
//dom_node_unref(doc);
|
|
return JS_EXCEPTION;
|
|
}
|
|
exc = dom_string_create((const uint8_t *)str, len, &tagname);
|
|
JS_FreeCString(ctx, str);
|
|
|
|
if (exc != DOM_NO_ERR || !tagname) {
|
|
//dom_node_unref(doc);
|
|
return JS_NULL;
|
|
}
|
|
dom_nodelist *nodes = NULL;
|
|
exc = dom_document_get_elements_by_tag_name(doc, tagname, &nodes);
|
|
dom_string_unref(tagname);
|
|
|
|
if (exc != DOM_NO_ERR || !nodes) {
|
|
//dom_node_unref(doc);
|
|
return JS_NULL;
|
|
}
|
|
JSValue rr = getNodeList(ctx, nodes);
|
|
//dom_node_unref(doc);
|
|
|
|
RETURN_JS(rr);
|
|
}
|
|
|
|
static JSValue
|
|
js_document_querySelector(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
|
|
{
|
|
#ifdef ECMASCRIPT_DEBUG
|
|
fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__);
|
|
#endif
|
|
REF_JS(this_val);
|
|
|
|
if (argc != 1) {
|
|
return JS_FALSE;
|
|
}
|
|
dom_html_document *doc = (struct dom_html_document *)js_doc_getopaque(this_val);
|
|
|
|
if (!doc) {
|
|
return JS_NULL;
|
|
}
|
|
//dom_node_ref(doc);
|
|
|
|
dom_node *root = NULL; /* root element of document */
|
|
/* Get root element */
|
|
dom_exception exc = dom_document_get_document_element(doc, &root);
|
|
|
|
if (exc != DOM_NO_ERR) {
|
|
//dom_node_unref(doc);
|
|
return JS_NULL;
|
|
}
|
|
size_t len;
|
|
const char *selector = JS_ToCStringLen(ctx, &len, argv[0]);
|
|
|
|
if (!selector) {
|
|
//dom_node_unref(doc);
|
|
#ifdef ECMASCRIPT_DEBUG
|
|
fprintf(stderr, "Before: %s:%d\n", __FUNCTION__, __LINE__);
|
|
#endif
|
|
dom_node_unref(root);
|
|
return JS_NULL;
|
|
}
|
|
void *ret = walk_tree_query(root, selector, 0);
|
|
JS_FreeCString(ctx, selector);
|
|
#ifdef ECMASCRIPT_DEBUG
|
|
fprintf(stderr, "Before: %s:%d\n", __FUNCTION__, __LINE__);
|
|
#endif
|
|
dom_node_unref(root);
|
|
|
|
if (!ret) {
|
|
//dom_node_unref(doc);
|
|
return JS_NULL;
|
|
}
|
|
//dom_node_unref(doc);
|
|
|
|
return getElement(ctx, ret);
|
|
}
|
|
|
|
static JSValue
|
|
js_document_querySelectorAll(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
|
|
{
|
|
#ifdef ECMASCRIPT_DEBUG
|
|
fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__);
|
|
#endif
|
|
REF_JS(this_val);
|
|
|
|
if (argc != 1) {
|
|
return JS_FALSE;
|
|
}
|
|
dom_html_document *doc = (struct dom_html_document *)js_doc_getopaque(this_val);
|
|
|
|
if (!doc) {
|
|
return JS_NULL;
|
|
}
|
|
//dom_node_ref(doc);
|
|
dom_node *doc_root = NULL; /* root element of document */
|
|
/* Get root element */
|
|
dom_exception exc = dom_document_get_document_element(doc, &doc_root);
|
|
|
|
if (exc != DOM_NO_ERR) {
|
|
//dom_node_unref(doc);
|
|
return JS_NULL;
|
|
}
|
|
size_t len;
|
|
const char *selector = JS_ToCStringLen(ctx, &len, argv[0]);
|
|
|
|
if (!selector) {
|
|
//dom_node_unref(doc);
|
|
#ifdef ECMASCRIPT_DEBUG
|
|
fprintf(stderr, "Before: %s:%d\n", __FUNCTION__, __LINE__);
|
|
#endif
|
|
dom_node_unref(doc_root);
|
|
return JS_NULL;
|
|
}
|
|
LIST_OF(struct selector_node) *result_list = (LIST_OF(struct selector_node) *)mem_calloc(1, sizeof(*result_list));
|
|
|
|
if (!result_list) {
|
|
//dom_node_unref(doc);
|
|
#ifdef ECMASCRIPT_DEBUG
|
|
fprintf(stderr, "Before: %s:%d\n", __FUNCTION__, __LINE__);
|
|
#endif
|
|
dom_node_unref(doc_root);
|
|
JS_FreeCString(ctx, selector);
|
|
return JS_NULL;
|
|
}
|
|
init_list(*result_list);
|
|
|
|
walk_tree_query_append(doc_root, selector, 0, result_list);
|
|
#ifdef ECMASCRIPT_DEBUG
|
|
fprintf(stderr, "Before: %s:%d\n", __FUNCTION__, __LINE__);
|
|
#endif
|
|
dom_node_unref(doc_root);
|
|
JS_FreeCString(ctx, selector);
|
|
//dom_node_unref(doc);
|
|
|
|
JSValue rr = getNodeList2(ctx, result_list);
|
|
free_list(*result_list);
|
|
mem_free(result_list);
|
|
|
|
return rr;
|
|
}
|
|
|
|
#if 0
|
|
JSClass doctype_class = {
|
|
"doctype",
|
|
JSCLASS_HAS_PRIVATE,
|
|
&doctype_ops
|
|
};
|
|
#endif
|
|
|
|
static JSValue
|
|
js_doctype_get_property_name(JSContext *ctx, JSValueConst this_val)
|
|
{
|
|
#ifdef ECMASCRIPT_DEBUG
|
|
fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__);
|
|
#endif
|
|
REF_JS(this_val);
|
|
|
|
dom_document_type *dtd = (dom_document_type *)(JS_GetOpaque(this_val, js_doctype_class_id));
|
|
|
|
if (!dtd) {
|
|
return JS_NULL;
|
|
}
|
|
dom_string *name = NULL;
|
|
dom_exception exc = dom_document_type_get_name(dtd, &name);
|
|
|
|
if (exc != DOM_NO_ERR || !name) {
|
|
return JS_NULL;
|
|
}
|
|
JSValue ret = JS_NewStringLen(ctx, dom_string_data(name), dom_string_length(name));
|
|
dom_string_unref(name);
|
|
|
|
return ret;
|
|
}
|
|
|
|
static JSValue
|
|
js_doctype_get_property_publicId(JSContext *ctx, JSValueConst this_val)
|
|
{
|
|
#ifdef ECMASCRIPT_DEBUG
|
|
fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__);
|
|
#endif
|
|
REF_JS(this_val);
|
|
|
|
dom_document_type *dtd = (dom_document_type *)(JS_GetOpaque(this_val, js_doctype_class_id));
|
|
|
|
if (!dtd) {
|
|
return JS_NULL;
|
|
}
|
|
dom_string *public_id = NULL;
|
|
dom_exception exc = dom_document_type_get_public_id(dtd, &public_id);
|
|
|
|
if (exc != DOM_NO_ERR || !public_id) {
|
|
return JS_NULL;
|
|
}
|
|
JSValue ret = JS_NewStringLen(ctx, dom_string_data(public_id), dom_string_length(public_id));
|
|
dom_string_unref(public_id);
|
|
|
|
return ret;
|
|
}
|
|
|
|
static JSValue
|
|
js_doctype_get_property_systemId(JSContext *ctx, JSValueConst this_val)
|
|
{
|
|
#ifdef ECMASCRIPT_DEBUG
|
|
fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__);
|
|
#endif
|
|
REF_JS(this_val);
|
|
|
|
dom_document_type *dtd = (dom_document_type *)(JS_GetOpaque(this_val, js_doctype_class_id));
|
|
|
|
if (!dtd) {
|
|
return JS_NULL;
|
|
}
|
|
dom_string *system_id = NULL;
|
|
dom_exception exc = dom_document_type_get_system_id(dtd, &system_id);
|
|
|
|
if (exc != DOM_NO_ERR || !system_id) {
|
|
return JS_NULL;
|
|
}
|
|
JSValue ret = JS_NewStringLen(ctx, dom_string_data(system_id), dom_string_length(system_id));
|
|
dom_string_unref(system_id);
|
|
|
|
return ret;
|
|
}
|
|
|
|
static JSValue
|
|
js_document_toString(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
|
|
{
|
|
#ifdef ECMASCRIPT_DEBUG
|
|
fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__);
|
|
#endif
|
|
REF_JS(this_val);
|
|
|
|
return JS_NewString(ctx, "[document object]");
|
|
}
|
|
|
|
static const JSCFunctionListEntry js_document_proto_funcs[] = {
|
|
JS_CGETSET_DEF("anchors", js_document_get_property_anchors, NULL),
|
|
JS_CGETSET_DEF("baseURI", js_document_get_property_baseURI, NULL),
|
|
JS_CGETSET_DEF("body", js_document_get_property_body, js_document_set_property_body),
|
|
#ifdef CONFIG_COOKIES
|
|
JS_CGETSET_DEF("cookie", js_document_get_property_cookie, js_document_set_property_cookie),
|
|
#endif
|
|
JS_CGETSET_DEF("charset", js_document_get_property_charset, NULL),
|
|
JS_CGETSET_DEF("characterSet", js_document_get_property_charset, NULL),
|
|
JS_CGETSET_DEF("childNodes", js_document_get_property_childNodes, NULL),
|
|
JS_CGETSET_DEF("currentScript", js_document_get_property_currentScript, NULL),
|
|
JS_CGETSET_DEF("defaultView", js_document_get_property_defaultView, NULL),
|
|
JS_CGETSET_DEF("doctype", js_document_get_property_doctype, NULL),
|
|
JS_CGETSET_DEF("documentElement", js_document_get_property_documentElement, NULL),
|
|
JS_CGETSET_DEF("documentURI", js_document_get_property_documentURI, NULL),
|
|
JS_CGETSET_DEF("domain", js_document_get_property_domain, NULL),
|
|
JS_CGETSET_DEF("forms", js_document_get_property_forms, NULL),
|
|
JS_CGETSET_DEF("head", js_document_get_property_head, NULL),
|
|
JS_CGETSET_DEF("images", js_document_get_property_images, NULL),
|
|
JS_CGETSET_DEF("implementation", js_document_get_property_implementation, NULL),
|
|
JS_CGETSET_DEF("inputEncoding", js_document_get_property_charset, NULL),
|
|
JS_CGETSET_DEF("links", js_document_get_property_links, NULL),
|
|
JS_CGETSET_DEF("location", js_document_get_property_location, js_document_set_property_location),
|
|
JS_CGETSET_DEF("nodeType", js_document_get_property_nodeType, NULL),
|
|
JS_CGETSET_DEF("readyState", js_document_get_property_readyState, NULL),
|
|
JS_CGETSET_DEF("referrer", js_document_get_property_referrer, NULL),
|
|
JS_CGETSET_DEF("scripts", js_document_get_property_scripts, NULL),
|
|
JS_CGETSET_DEF("title", js_document_get_property_title, js_document_set_property_title), /* TODO: Charset? */
|
|
JS_CGETSET_DEF("URL", js_document_get_property_url, js_document_set_property_url),
|
|
|
|
JS_CFUNC_DEF("addEventListener", 3, js_document_addEventListener),
|
|
JS_CFUNC_DEF("createComment", 1, js_document_createComment),
|
|
JS_CFUNC_DEF("createDocumentFragment", 0, js_document_createDocumentFragment),
|
|
JS_CFUNC_DEF("createElement", 1, js_document_createElement),
|
|
JS_CFUNC_DEF("createTextNode", 1, js_document_createTextNode),
|
|
JS_CFUNC_DEF("dispatchEvent", 1, js_document_dispatchEvent),
|
|
JS_CFUNC_DEF("write", 1, js_document_write),
|
|
JS_CFUNC_DEF("writeln", 1, js_document_writeln),
|
|
JS_CFUNC_DEF("removeEventListener", 3, js_document_removeEventListener),
|
|
JS_CFUNC_DEF("replace", 2, js_document_replace),
|
|
JS_CFUNC_DEF("getElementById", 1, js_document_getElementById),
|
|
JS_CFUNC_DEF("getElementsByClassName", 1, js_document_getElementsByClassName),
|
|
// JS_CFUNC_DEF("getElementsByName", 1, js_document_getElementsByName),
|
|
JS_CFUNC_DEF("getElementsByTagName", 1, js_document_getElementsByTagName),
|
|
JS_CFUNC_DEF("querySelector", 1, js_document_querySelector),
|
|
JS_CFUNC_DEF("querySelectorAll", 1, js_document_querySelectorAll),
|
|
|
|
JS_CFUNC_DEF("toString", 0, js_document_toString)
|
|
};
|
|
|
|
static void
|
|
js_document_finalizer(JSRuntime *rt, JSValue val)
|
|
{
|
|
REF_JS(val);
|
|
|
|
struct js_document_private *doc_private = (struct js_document_private *)JS_GetOpaque(val, js_document_class_id);
|
|
|
|
if (doc_private) {
|
|
struct document_listener *l;
|
|
|
|
if (doc_private->listener) {
|
|
dom_event_listener_unref(doc_private->listener);
|
|
}
|
|
|
|
foreach(l, doc_private->listeners) {
|
|
mem_free_set(&l->typ, NULL);
|
|
JS_FreeValueRT(rt, l->fun);
|
|
}
|
|
free_list(doc_private->listeners);
|
|
if (doc_private->node) {
|
|
#ifdef ECMASCRIPT_DEBUG
|
|
fprintf(stderr, "Before: %s:%d\n", __FUNCTION__, __LINE__);
|
|
#endif
|
|
dom_node_unref((dom_node *)doc_private->node);
|
|
}
|
|
mem_free(doc_private);
|
|
}
|
|
}
|
|
|
|
static JSClassDef js_document_class = {
|
|
"document",
|
|
.finalizer = js_document_finalizer,
|
|
.gc_mark = js_document_mark
|
|
};
|
|
|
|
static JSValue
|
|
js_doctype_toString(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
|
|
{
|
|
#ifdef ECMASCRIPT_DEBUG
|
|
fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__);
|
|
#endif
|
|
REF_JS(this_val);
|
|
|
|
return JS_NewString(ctx, "[doctype object]");
|
|
}
|
|
|
|
static const JSCFunctionListEntry js_doctype_proto_funcs[] = {
|
|
JS_CGETSET_DEF("name", js_doctype_get_property_name, NULL),
|
|
JS_CGETSET_DEF("publicId", js_doctype_get_property_publicId, NULL),
|
|
JS_CGETSET_DEF("systemId", js_doctype_get_property_systemId, NULL),
|
|
JS_CFUNC_DEF("toString", 0, js_doctype_toString)
|
|
};
|
|
|
|
void *map_doctypes;
|
|
|
|
static void
|
|
js_doctype_finalizer(JSRuntime *rt, JSValue val)
|
|
{
|
|
REF_JS(val);
|
|
|
|
dom_node *node = (dom_node *)JS_GetOpaque(val, js_doctype_class_id);
|
|
|
|
if (node) {
|
|
#ifdef ECMASCRIPT_DEBUG
|
|
fprintf(stderr, "Before: %s:%d\n", __FUNCTION__, __LINE__);
|
|
#endif
|
|
dom_node_unref(node);
|
|
}
|
|
}
|
|
|
|
static JSClassDef js_doctype_class = {
|
|
"doctype",
|
|
js_doctype_finalizer
|
|
};
|
|
|
|
int
|
|
js_doctype_init(JSContext *ctx)
|
|
{
|
|
JSValue doctype_proto;
|
|
|
|
/* create the doctype class */
|
|
JS_NewClassID(&js_doctype_class_id);
|
|
JS_NewClass(JS_GetRuntime(ctx), js_doctype_class_id, &js_doctype_class);
|
|
|
|
JSValue global_obj = JS_GetGlobalObject(ctx);
|
|
REF_JS(global_obj);
|
|
|
|
doctype_proto = JS_NewObject(ctx);
|
|
REF_JS(doctype_proto);
|
|
|
|
JS_SetPropertyFunctionList(ctx, doctype_proto, js_doctype_proto_funcs, countof(js_doctype_proto_funcs));
|
|
JS_SetClassProto(ctx, js_doctype_class_id, doctype_proto);
|
|
JS_SetPropertyStr(ctx, global_obj, "doctype", JS_DupValue(ctx, doctype_proto));
|
|
|
|
JS_FreeValue(ctx, global_obj);
|
|
|
|
return 0;
|
|
}
|
|
|
|
JSValue
|
|
getDoctype(JSContext *ctx, void *node)
|
|
{
|
|
#ifdef ECMASCRIPT_DEBUG
|
|
fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__);
|
|
#endif
|
|
static int initialized;
|
|
/* create the element class */
|
|
if (!initialized) {
|
|
JS_NewClassID(&js_doctype_class_id);
|
|
JS_NewClass(JS_GetRuntime(ctx), js_doctype_class_id, &js_doctype_class);
|
|
initialized = 1;
|
|
}
|
|
JSValue doctype_obj = JS_NewObjectClass(ctx, js_doctype_class_id);
|
|
JS_SetPropertyFunctionList(ctx, doctype_obj, js_doctype_proto_funcs, countof(js_doctype_proto_funcs));
|
|
JS_SetClassProto(ctx, js_doctype_class_id, doctype_obj);
|
|
JS_SetOpaque(doctype_obj, node);
|
|
|
|
JSValue rr = JS_DupValue(ctx, doctype_obj);
|
|
RETURN_JS(rr);
|
|
}
|
|
|
|
JSValue
|
|
getDocument(JSContext *ctx, void *doc)
|
|
{
|
|
#ifdef ECMASCRIPT_DEBUG
|
|
fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__);
|
|
#endif
|
|
struct js_document_private *doc_private = (struct js_document_private *)mem_calloc(1, sizeof(*doc_private));
|
|
|
|
if (!doc_private) {
|
|
return JS_NULL;
|
|
}
|
|
init_list(doc_private->listeners);
|
|
|
|
if (doc) {
|
|
#ifdef ECMASCRIPT_DEBUG
|
|
fprintf(stderr, "Before: %s:%d\n", __FUNCTION__, __LINE__);
|
|
#endif
|
|
dom_node_ref((dom_node *)doc);
|
|
}
|
|
doc_private->node = doc;
|
|
struct ecmascript_interpreter *interpreter = (struct ecmascript_interpreter *)JS_GetContextOpaque(ctx);
|
|
doc_private->interpreter = interpreter;
|
|
static int initialized;
|
|
|
|
JSValue global_obj = JS_GetGlobalObject(ctx);
|
|
|
|
/* create the element class */
|
|
if (!initialized) {
|
|
JS_NewClassID(&js_document_class_id);
|
|
JS_NewClass(JS_GetRuntime(ctx), js_document_class_id, &js_document_class);
|
|
initialized = 1;
|
|
}
|
|
//REF_JS(global_obj);
|
|
|
|
JSValue document_obj = JS_NewObjectClass(ctx, js_document_class_id);
|
|
JS_SetPropertyFunctionList(ctx, document_obj, js_document_proto_funcs, countof(js_document_proto_funcs));
|
|
// document_class = JS_NewCFunction2(ctx, js_document_ctor, "document", 0, JS_CFUNC_constructor, 0);
|
|
// JS_SetConstructor(ctx, document_class, document_obj);
|
|
JS_SetOpaque(document_obj, doc_private);
|
|
// JS_SetClassProto(ctx, js_document_class_id, document_obj);
|
|
JS_SetPropertyStr(ctx, global_obj, "document", document_obj);
|
|
JS_FreeValue(ctx, global_obj);
|
|
doc_private->thisval = document_obj;
|
|
|
|
RETURN_JS(document_obj);
|
|
}
|
|
|
|
JSValue
|
|
getDocument2(JSContext *ctx, void *doc)
|
|
{
|
|
#ifdef ECMASCRIPT_DEBUG
|
|
fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__);
|
|
#endif
|
|
struct js_document_private *doc_private = (struct js_document_private *)mem_calloc(1, sizeof(*doc_private));
|
|
|
|
if (!doc_private) {
|
|
return JS_NULL;
|
|
}
|
|
init_list(doc_private->listeners);
|
|
|
|
// if (doc) {
|
|
// dom_node_ref((dom_node *)doc);
|
|
// }
|
|
doc_private->node = doc;
|
|
struct ecmascript_interpreter *interpreter = (struct ecmascript_interpreter *)JS_GetContextOpaque(ctx);
|
|
doc_private->interpreter = interpreter;
|
|
|
|
JSValue document_obj = JS_NewObjectClass(ctx, js_document_class_id);
|
|
JS_SetPropertyFunctionList(ctx, document_obj, js_document_proto_funcs, countof(js_document_proto_funcs));
|
|
JS_SetOpaque(document_obj, doc_private);
|
|
doc_private->thisval = document_obj;
|
|
|
|
RETURN_JS(document_obj);
|
|
}
|
|
|
|
static void
|
|
document_event_handler(dom_event *event, void *pw)
|
|
{
|
|
#ifdef ECMASCRIPT_DEBUG
|
|
fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__);
|
|
#endif
|
|
struct js_document_private *doc_private = (struct js_document_private *)pw;
|
|
struct ecmascript_interpreter *interpreter = (struct ecmascript_interpreter *)doc_private->interpreter;
|
|
|
|
if (!interp_find_in_map(map_interp, interpreter)) {
|
|
return;
|
|
}
|
|
JSContext *ctx = (JSContext *)interpreter->backend_data;
|
|
|
|
if (!event) {
|
|
return;
|
|
}
|
|
|
|
dom_string *typ = NULL;
|
|
dom_exception exc = dom_event_get_type(event, &typ);
|
|
|
|
if (exc != DOM_NO_ERR || !typ) {
|
|
return;
|
|
}
|
|
|
|
if (!strcmp("DOMContentLoaded", dom_string_data(typ))) {
|
|
if (doc_private->state == COMPLETE) {
|
|
dom_string_unref(typ);
|
|
return;
|
|
}
|
|
doc_private->state = COMPLETE;
|
|
}
|
|
// interpreter->heartbeat = add_heartbeat(interpreter);
|
|
|
|
struct document_listener *l, *next;
|
|
|
|
foreachsafe(l, next, doc_private->listeners) {
|
|
if (strcmp(l->typ, dom_string_data(typ))) {
|
|
continue;
|
|
}
|
|
JSValue func = JS_DupValue(ctx, l->fun);
|
|
JSValue arg = getEvent(ctx, event);
|
|
JSValue ret = JS_Call(ctx, func, doc_private->thisval, 1, (JSValueConst *) &arg);
|
|
JS_FreeValue(ctx, ret);
|
|
JS_FreeValue(ctx, func);
|
|
JS_FreeValue(ctx, arg);
|
|
}
|
|
// done_heartbeat(interpreter->heartbeat);
|
|
check_for_rerender(interpreter, dom_string_data(typ));
|
|
dom_string_unref(typ);
|
|
}
|