mirror of
https://github.com/rkd77/elinks.git
synced 2024-09-25 02:36:23 -04:00
Compare commits
34 Commits
f2fbde2de7
...
7748eb5ab9
Author | SHA1 | Date | |
---|---|---|---|
|
7748eb5ab9 | ||
|
948c22ea79 | ||
|
786469da5f | ||
|
3d92071eba | ||
|
57202954bb | ||
|
4da6e1f85a | ||
|
786cbf9500 | ||
|
1b954141eb | ||
|
6f64f8e9db | ||
|
14bca39543 | ||
|
ff3b231e42 | ||
|
bd7f271b0a | ||
|
0e42cf7d63 | ||
|
6deeb720b9 | ||
|
3c81545b81 | ||
|
3406220379 | ||
|
7c9c3f83bf | ||
|
42d2da4be5 | ||
|
2a0afc9631 | ||
|
a6d368d2ab | ||
|
8bba9f8c4e | ||
|
15ac18c04f | ||
|
48ff6810d4 | ||
|
bbe14cddc3 | ||
|
ecd7662d1a | ||
|
610eb4b450 | ||
|
09447c7812 | ||
|
10555292b4 | ||
|
face74fd38 | ||
|
667167bd90 | ||
|
4a6b920586 | ||
|
3128c22c2e | ||
|
cc718c30b5 | ||
|
be67094940 |
@ -284,6 +284,8 @@ src/ecmascript/mujs/style.c
|
|||||||
src/ecmascript/mujs/style.h
|
src/ecmascript/mujs/style.h
|
||||||
src/ecmascript/mujs/unibar.c
|
src/ecmascript/mujs/unibar.c
|
||||||
src/ecmascript/mujs/unibar.h
|
src/ecmascript/mujs/unibar.h
|
||||||
|
src/ecmascript/mujs/url.c
|
||||||
|
src/ecmascript/mujs/url.h
|
||||||
src/ecmascript/mujs/window.c
|
src/ecmascript/mujs/window.c
|
||||||
src/ecmascript/mujs/window.h
|
src/ecmascript/mujs/window.h
|
||||||
src/ecmascript/mujs/xhr.c
|
src/ecmascript/mujs/xhr.c
|
||||||
@ -340,6 +342,8 @@ src/ecmascript/quickjs/style.c
|
|||||||
src/ecmascript/quickjs/style.h
|
src/ecmascript/quickjs/style.h
|
||||||
src/ecmascript/quickjs/unibar.c
|
src/ecmascript/quickjs/unibar.c
|
||||||
src/ecmascript/quickjs/unibar.h
|
src/ecmascript/quickjs/unibar.h
|
||||||
|
src/ecmascript/quickjs/url.c
|
||||||
|
src/ecmascript/quickjs/url.h
|
||||||
src/ecmascript/quickjs/window.c
|
src/ecmascript/quickjs/window.c
|
||||||
src/ecmascript/quickjs/window.h
|
src/ecmascript/quickjs/window.h
|
||||||
src/ecmascript/quickjs/xhr.c
|
src/ecmascript/quickjs/xhr.c
|
||||||
|
@ -97,7 +97,11 @@ static css_error node_presentational_hint(void *pw, void *node,
|
|||||||
return CSS_OK;
|
return CSS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static css_error
|
||||||
|
resolve_url_empty(void *pw, const char *base, lwc_string *rel, lwc_string **abs)
|
||||||
|
{
|
||||||
|
return CSS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
css_error
|
css_error
|
||||||
resolve_url(void *pw, const char *base, lwc_string *rel, lwc_string **abs)
|
resolve_url(void *pw, const char *base, lwc_string *rel, lwc_string **abs)
|
||||||
@ -2309,3 +2313,122 @@ import_css2(struct html_context *html_context, struct uri *uri)
|
|||||||
// css->import_level--;
|
// css->import_level--;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void *
|
||||||
|
el_match_selector(const char *selector, void *node)
|
||||||
|
{
|
||||||
|
struct string text;
|
||||||
|
css_error code;
|
||||||
|
size_t size;
|
||||||
|
uint32_t count;
|
||||||
|
css_stylesheet_params params;
|
||||||
|
css_stylesheet *sheet = NULL;
|
||||||
|
css_select_ctx *select_ctx = NULL;
|
||||||
|
css_select_results *style = NULL;
|
||||||
|
uint8_t color_type;
|
||||||
|
css_color color_shade;
|
||||||
|
|
||||||
|
css_media media = {
|
||||||
|
.type = CSS_MEDIA_SCREEN,
|
||||||
|
};
|
||||||
|
|
||||||
|
css_unit_ctx unit_len_ctx = {0};
|
||||||
|
unit_len_ctx.viewport_width = 800; // TODO
|
||||||
|
unit_len_ctx.viewport_height = 600; // TODO
|
||||||
|
unit_len_ctx.device_dpi = F_90; //device_dpi;
|
||||||
|
|
||||||
|
/** \todo Change nsoption font sizes to px. */
|
||||||
|
/// f_size = FDIV(FMUL(F_96, FDIV(INTTOFIX(nsoption_int(font_size)), F_10)), F_72);
|
||||||
|
/// f_min = FDIV(FMUL(F_96, FDIV(INTTOFIX(nsoption_int(font_min_size)), F_10)), F_72);
|
||||||
|
|
||||||
|
unsigned int f_size = FDIV(FMUL(F_96, FDIV(INTTOFIX(50), F_10)), F_72); // TODO
|
||||||
|
unsigned int f_min = FDIV(FMUL(F_96, FDIV(INTTOFIX(50), F_10)), F_72); // TODO
|
||||||
|
|
||||||
|
unit_len_ctx.font_size_default = f_size;
|
||||||
|
unit_len_ctx.font_size_minimum = f_min;
|
||||||
|
void *ret = NULL;
|
||||||
|
|
||||||
|
params.params_version = CSS_STYLESHEET_PARAMS_VERSION_1;
|
||||||
|
params.level = CSS_LEVEL_21;
|
||||||
|
params.charset = "UTF-8";
|
||||||
|
params.url = "foo";
|
||||||
|
params.title = "foo";
|
||||||
|
params.allow_quirks = false;
|
||||||
|
params.inline_style = false;
|
||||||
|
params.resolve = resolve_url_empty;
|
||||||
|
params.resolve_pw = NULL;
|
||||||
|
params.import = NULL;
|
||||||
|
params.import_pw = NULL;
|
||||||
|
params.color = NULL;
|
||||||
|
params.color_pw = NULL;
|
||||||
|
params.font = NULL;
|
||||||
|
params.font_pw = NULL;
|
||||||
|
|
||||||
|
if (!selector) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
if (!init_string(&text)) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
add_to_string(&text, selector);
|
||||||
|
add_to_string(&text, "{color:#123456}");
|
||||||
|
|
||||||
|
/* create a stylesheet */
|
||||||
|
code = css_stylesheet_create(¶ms, &sheet);
|
||||||
|
|
||||||
|
if (code != CSS_OK) {
|
||||||
|
goto empty;
|
||||||
|
}
|
||||||
|
code = css_stylesheet_append_data(sheet, (const uint8_t *) text.source, text.length);
|
||||||
|
|
||||||
|
if (code != CSS_OK && code != CSS_NEEDDATA) {
|
||||||
|
goto empty;
|
||||||
|
}
|
||||||
|
code = css_stylesheet_data_done(sheet);
|
||||||
|
if (code != CSS_OK) {
|
||||||
|
goto empty;
|
||||||
|
}
|
||||||
|
code = css_stylesheet_size(sheet, &size);
|
||||||
|
|
||||||
|
/* prepare a selection context containing the stylesheet */
|
||||||
|
code = css_select_ctx_create(&select_ctx);
|
||||||
|
|
||||||
|
if (code != CSS_OK) {
|
||||||
|
goto empty;
|
||||||
|
}
|
||||||
|
code = css_select_ctx_append_sheet(select_ctx, sheet, CSS_ORIGIN_AUTHOR, NULL);
|
||||||
|
|
||||||
|
if (code != CSS_OK) {
|
||||||
|
goto empty;
|
||||||
|
}
|
||||||
|
code = css_select_ctx_count_sheets(select_ctx, &count);
|
||||||
|
|
||||||
|
if (code != CSS_OK) {
|
||||||
|
goto empty;
|
||||||
|
}
|
||||||
|
code = css_select_style(select_ctx, node, &unit_len_ctx, &media, NULL, &selection_handler, 0, &style);
|
||||||
|
|
||||||
|
if (code != CSS_OK) {
|
||||||
|
goto empty;
|
||||||
|
}
|
||||||
|
|
||||||
|
color_type = css_computed_color(style->styles[CSS_PSEUDO_ELEMENT_NONE], &color_shade);
|
||||||
|
|
||||||
|
if (color_type && color_shade == 0xff123456) {
|
||||||
|
ret = node;
|
||||||
|
}
|
||||||
|
|
||||||
|
empty:
|
||||||
|
if (style) {
|
||||||
|
css_select_results_destroy(style);
|
||||||
|
}
|
||||||
|
if (select_ctx) {
|
||||||
|
css_select_ctx_destroy(select_ctx);
|
||||||
|
}
|
||||||
|
if (sheet) {
|
||||||
|
css_stylesheet_destroy(sheet);
|
||||||
|
}
|
||||||
|
done_string(&text);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
@ -11,6 +11,7 @@ struct string;
|
|||||||
void *document_parse_text(const char *charset, char *data, size_t length);
|
void *document_parse_text(const char *charset, char *data, size_t length);
|
||||||
void *document_parse(struct document *document, struct string *source);
|
void *document_parse(struct document *document, struct string *source);
|
||||||
void free_document(void *doc);
|
void free_document(void *doc);
|
||||||
|
void *el_match_selector(const char *selector, void *node);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
|
|
||||||
#include "dialogs/status.h"
|
#include "dialogs/status.h"
|
||||||
#include "document/document.h"
|
#include "document/document.h"
|
||||||
|
#include "document/libdom/doc.h"
|
||||||
#include "document/libdom/mapa.h"
|
#include "document/libdom/mapa.h"
|
||||||
#include "document/view.h"
|
#include "document/view.h"
|
||||||
#include "ecmascript/ecmascript.h"
|
#include "ecmascript/ecmascript.h"
|
||||||
@ -481,3 +482,114 @@ void ecmascript_moved_form_state(struct form_state *fs)
|
|||||||
spidermonkey_moved_form_state(fs);
|
spidermonkey_moved_form_state(fs);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void *
|
||||||
|
walk_tree_query(dom_node *node, const char *selector, int depth)
|
||||||
|
{
|
||||||
|
dom_exception exc;
|
||||||
|
dom_node *child;
|
||||||
|
void *res = NULL;
|
||||||
|
dom_node_type typ;
|
||||||
|
|
||||||
|
/* Only interested in element nodes */
|
||||||
|
exc = dom_node_get_node_type(node, &typ);
|
||||||
|
if (typ != DOM_ELEMENT_NODE) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (res = el_match_selector(selector, node)) {
|
||||||
|
/* There was an error; return */
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
/* Get the node's first child */
|
||||||
|
exc = dom_node_get_first_child(node, &child);
|
||||||
|
|
||||||
|
if (exc != DOM_NO_ERR) {
|
||||||
|
return NULL;
|
||||||
|
} else if (child != NULL) {
|
||||||
|
/* node has children; decend to children's depth */
|
||||||
|
depth++;
|
||||||
|
|
||||||
|
/* Loop though all node's children */
|
||||||
|
do {
|
||||||
|
dom_node *next_child;
|
||||||
|
|
||||||
|
/* Visit node's descendents */
|
||||||
|
res = walk_tree_query(child, selector, depth);
|
||||||
|
/* There was an error; return */
|
||||||
|
if (res) {
|
||||||
|
dom_node_unref(child);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Go to next sibling */
|
||||||
|
exc = dom_node_get_next_sibling(child, &next_child);
|
||||||
|
if (exc != DOM_NO_ERR) {
|
||||||
|
dom_node_unref(child);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
dom_node_unref(child);
|
||||||
|
child = next_child;
|
||||||
|
} while (child != NULL); /* No more children */
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
walk_tree_query_append(dom_node *root, dom_node *node, const char *selector, int depth)
|
||||||
|
{
|
||||||
|
dom_exception exc;
|
||||||
|
dom_node *child;
|
||||||
|
void *res = NULL;
|
||||||
|
dom_node_type typ;
|
||||||
|
|
||||||
|
/* Only interested in element nodes */
|
||||||
|
exc = dom_node_get_node_type(node, &typ);
|
||||||
|
|
||||||
|
if (typ != DOM_ELEMENT_NODE) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (res = el_match_selector(selector, node)) {
|
||||||
|
dom_node *clone = NULL;
|
||||||
|
exc = dom_node_clone_node(res, false, &clone);
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* Get the node's first child */
|
||||||
|
exc = dom_node_get_first_child(node, &child);
|
||||||
|
|
||||||
|
if (exc != DOM_NO_ERR) {
|
||||||
|
return;
|
||||||
|
} else if (child != NULL) {
|
||||||
|
/* node has children; decend to children's depth */
|
||||||
|
depth++;
|
||||||
|
|
||||||
|
/* Loop though all node's children */
|
||||||
|
do {
|
||||||
|
dom_node *next_child;
|
||||||
|
|
||||||
|
/* Visit node's descendents */
|
||||||
|
walk_tree_query_append(root, child, selector, depth);
|
||||||
|
|
||||||
|
/* Go to next sibling */
|
||||||
|
exc = dom_node_get_next_sibling(child, &next_child);
|
||||||
|
if (exc != DOM_NO_ERR) {
|
||||||
|
dom_node_unref(child);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
dom_node_unref(child);
|
||||||
|
child = next_child;
|
||||||
|
} while (child != NULL); /* No more children */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -40,6 +40,9 @@ void ecmascript_detach_form_view(struct form_view *fv);
|
|||||||
void ecmascript_detach_form_state(struct form_state *fs);
|
void ecmascript_detach_form_state(struct form_state *fs);
|
||||||
void ecmascript_moved_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);
|
||||||
|
|
||||||
extern struct module ecmascript_module;
|
extern struct module ecmascript_module;
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
@ -39,6 +39,7 @@
|
|||||||
#include "ecmascript/mujs/navigator.h"
|
#include "ecmascript/mujs/navigator.h"
|
||||||
#include "ecmascript/mujs/screen.h"
|
#include "ecmascript/mujs/screen.h"
|
||||||
#include "ecmascript/mujs/unibar.h"
|
#include "ecmascript/mujs/unibar.h"
|
||||||
|
#include "ecmascript/mujs/url.h"
|
||||||
#include "ecmascript/mujs/window.h"
|
#include "ecmascript/mujs/window.h"
|
||||||
#include "ecmascript/mujs/xhr.h"
|
#include "ecmascript/mujs/xhr.h"
|
||||||
#include "intl/libintl.h"
|
#include "intl/libintl.h"
|
||||||
@ -143,6 +144,7 @@ mujs_get_interpreter(struct ecmascript_interpreter *interpreter)
|
|||||||
mjs_keyboardEvent_init(J);
|
mjs_keyboardEvent_init(J);
|
||||||
mjs_messageEvent_init(J);
|
mjs_messageEvent_init(J);
|
||||||
mjs_customEvent_init(J);
|
mjs_customEvent_init(J);
|
||||||
|
mjs_url_init(J);
|
||||||
|
|
||||||
return J;
|
return J;
|
||||||
#if 0
|
#if 0
|
||||||
|
@ -2,6 +2,6 @@ top_builddir=../../..
|
|||||||
include $(top_builddir)/Makefile.config
|
include $(top_builddir)/Makefile.config
|
||||||
|
|
||||||
OBJS = attr.o attributes.o collection.o console.o css.o customevent.o document.o element.o event.o form.o forms.o history.o implementation.o input.o \
|
OBJS = attr.o attributes.o collection.o console.o css.o customevent.o document.o element.o event.o form.o forms.o history.o implementation.o input.o \
|
||||||
keyboard.o localstorage.o location.o mapa.o message.o navigator.o nodelist.o screen.o style.o unibar.o window.o xhr.o
|
keyboard.o localstorage.o location.o mapa.o message.o navigator.o nodelist.o screen.o style.o unibar.o url.o window.o xhr.o
|
||||||
|
|
||||||
include $(top_srcdir)/Makefile.lib
|
include $(top_srcdir)/Makefile.lib
|
||||||
|
@ -28,6 +28,7 @@
|
|||||||
#include "document/libdom/doc.h"
|
#include "document/libdom/doc.h"
|
||||||
#include "document/view.h"
|
#include "document/view.h"
|
||||||
#include "ecmascript/ecmascript.h"
|
#include "ecmascript/ecmascript.h"
|
||||||
|
#include "ecmascript/ecmascript-c.h"
|
||||||
#include "ecmascript/mujs/mapa.h"
|
#include "ecmascript/mujs/mapa.h"
|
||||||
#include "ecmascript/libdom/parse.h"
|
#include "ecmascript/libdom/parse.h"
|
||||||
#include "ecmascript/mujs.h"
|
#include "ecmascript/mujs.h"
|
||||||
@ -1337,36 +1338,29 @@ mjs_document_querySelector(js_State *J)
|
|||||||
js_pushnull(J);
|
js_pushnull(J);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// TODO
|
dom_node *root = NULL; /* root element of document */
|
||||||
#if 0
|
/* Get root element */
|
||||||
xmlpp::Document *docu = (xmlpp::Document *)document->dom;
|
dom_exception exc = dom_document_get_document_element(document->dom, &root);
|
||||||
xmlpp::Element* root = (xmlpp::Element *)docu->get_root_node();
|
|
||||||
const char *str = js_tostring(J, 1);
|
|
||||||
|
|
||||||
if (!str) {
|
if (exc != DOM_NO_ERR) {
|
||||||
js_error(J, "!str");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
xmlpp::ustring css = str;
|
|
||||||
xmlpp::ustring xpath = css2xpath(css);
|
|
||||||
|
|
||||||
xmlpp::Node::NodeSet elements;
|
|
||||||
|
|
||||||
try {
|
|
||||||
elements = root->find(xpath);
|
|
||||||
} catch (xmlpp::exception &e) {
|
|
||||||
js_pushnull(J);
|
js_pushnull(J);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
const char *selector = js_tostring(J, 1);
|
||||||
|
|
||||||
if (elements.size() == 0) {
|
if (!selector) {
|
||||||
|
dom_node_unref(root);
|
||||||
js_pushnull(J);
|
js_pushnull(J);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
auto node = elements[0];
|
void *ret = walk_tree_query(root, selector, 0);
|
||||||
mjs_push_element(J, node);
|
dom_node_unref(root);
|
||||||
#endif
|
|
||||||
|
if (!ret) {
|
||||||
js_pushnull(J);
|
js_pushnull(J);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
mjs_push_element(J, ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -1383,33 +1377,51 @@ mjs_document_querySelectorAll(js_State *J)
|
|||||||
js_pushnull(J);
|
js_pushnull(J);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
dom_node *doc_root = NULL; /* root element of document */
|
||||||
|
/* Get root element */
|
||||||
|
dom_exception exc = dom_document_get_document_element(document->dom, &doc_root);
|
||||||
|
|
||||||
// TODO
|
if (exc != DOM_NO_ERR) {
|
||||||
#if 0
|
js_pushnull(J);
|
||||||
xmlpp::Document *docu = (xmlpp::Document *)document->dom;
|
|
||||||
xmlpp::Element* root = (xmlpp::Element *)docu->get_root_node();
|
|
||||||
const char *str = js_tostring(J, 1);
|
|
||||||
|
|
||||||
if (!str) {
|
|
||||||
js_error(J, "!str");
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
xmlpp::ustring css = str;
|
const char *selector = js_tostring(J, 1);
|
||||||
xmlpp::ustring xpath = css2xpath(css);
|
|
||||||
xmlpp::Node::NodeSet *elements = new(std::nothrow) xmlpp::Node::NodeSet;
|
|
||||||
|
|
||||||
if (!elements) {
|
if (!selector) {
|
||||||
|
dom_node_unref(doc_root);
|
||||||
js_pushnull(J);
|
js_pushnull(J);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
dom_string *tag_name = NULL;
|
||||||
*elements = root->find(xpath);
|
exc = dom_string_create((const uint8_t *)"B", 1, &tag_name);
|
||||||
} catch (xmlpp::exception &e) {
|
|
||||||
}
|
if (exc != DOM_NO_ERR || !tag_name) {
|
||||||
mjs_push_collection(J, elements);
|
dom_node_unref(doc_root);
|
||||||
#endif
|
|
||||||
js_pushnull(J);
|
js_pushnull(J);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
dom_element *element = NULL;
|
||||||
|
exc = dom_document_create_element(document->dom, tag_name, &element);
|
||||||
|
dom_string_unref(tag_name);
|
||||||
|
|
||||||
|
if (exc != DOM_NO_ERR || !element) {
|
||||||
|
dom_node_unref(doc_root);
|
||||||
|
js_pushnull(J);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
walk_tree_query_append((dom_node *)element, doc_root, selector, 0);
|
||||||
|
dom_node_unref(doc_root);
|
||||||
|
|
||||||
|
dom_nodelist *nodes = NULL;
|
||||||
|
exc = dom_node_get_child_nodes(element, &nodes);
|
||||||
|
dom_node_unref(element);
|
||||||
|
|
||||||
|
if (exc != DOM_NO_ERR || !nodes) {
|
||||||
|
js_pushnull(J);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
mjs_push_nodelist(J, nodes);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -24,10 +24,12 @@
|
|||||||
#include "document/document.h"
|
#include "document/document.h"
|
||||||
#include "document/forms.h"
|
#include "document/forms.h"
|
||||||
#include "document/libdom/corestrings.h"
|
#include "document/libdom/corestrings.h"
|
||||||
|
#include "document/libdom/doc.h"
|
||||||
#include "document/libdom/mapa.h"
|
#include "document/libdom/mapa.h"
|
||||||
#include "document/libdom/renderer2.h"
|
#include "document/libdom/renderer2.h"
|
||||||
#include "document/view.h"
|
#include "document/view.h"
|
||||||
#include "ecmascript/ecmascript.h"
|
#include "ecmascript/ecmascript.h"
|
||||||
|
#include "ecmascript/ecmascript-c.h"
|
||||||
#include "ecmascript/mujs/mapa.h"
|
#include "ecmascript/mujs/mapa.h"
|
||||||
#include "ecmascript/mujs.h"
|
#include "ecmascript/mujs.h"
|
||||||
#include "ecmascript/mujs/attr.h"
|
#include "ecmascript/mujs/attr.h"
|
||||||
@ -2254,46 +2256,54 @@ mjs_element_closest(js_State *J)
|
|||||||
#ifdef ECMASCRIPT_DEBUG
|
#ifdef ECMASCRIPT_DEBUG
|
||||||
fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__);
|
fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__);
|
||||||
#endif
|
#endif
|
||||||
// TODO
|
dom_node *el = (dom_node *)(mjs_getprivate(J, 0));
|
||||||
#if 0
|
void *res = NULL;
|
||||||
xmlpp::Element *el = static_cast<xmlpp::Element *>(mjs_getprivate(J, 0));
|
struct ecmascript_interpreter *interpreter = (struct ecmascript_interpreter *)js_getcontext(J);
|
||||||
|
struct document_view *doc_view = interpreter->vs->doc_view;
|
||||||
|
struct document *document = doc_view->document;
|
||||||
|
|
||||||
if (!el) {
|
if (!document->dom) {
|
||||||
js_pushnull(J);
|
js_pushnull(J);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const char *str = js_tostring(J, 1);
|
const char *selector = js_tostring(J, 1);
|
||||||
xmlpp::ustring css = str;
|
|
||||||
xmlpp::ustring xpath = css2xpath(css);
|
|
||||||
|
|
||||||
xmlpp::Node::NodeSet elements;
|
if (!selector) {
|
||||||
|
js_pushnull(J);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
dom_node *root = NULL; /* root element of document */
|
||||||
|
/* Get root element */
|
||||||
|
dom_exception exc = dom_document_get_document_element(document->dom, &root);
|
||||||
|
|
||||||
try {
|
if (exc != DOM_NO_ERR || !root) {
|
||||||
elements = el->find(xpath);
|
|
||||||
} catch (xmlpp::exception &e) {
|
|
||||||
js_pushnull(J);
|
js_pushnull(J);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (elements.size() == 0) {
|
while (el) {
|
||||||
js_pushnull(J);
|
res = el_match_selector(selector, el);
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
while (el)
|
if (res) {
|
||||||
{
|
break;
|
||||||
for (auto node: elements)
|
}
|
||||||
{
|
if (el == root) {
|
||||||
if (isAncestor(el, node))
|
break;
|
||||||
{
|
}
|
||||||
mjs_push_element(J, node);
|
dom_node *node = NULL;
|
||||||
|
exc = dom_node_get_parent_node(el, &node);
|
||||||
|
if (exc != DOM_NO_ERR || !node) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
el = node;
|
||||||
|
}
|
||||||
|
dom_node_unref(root);
|
||||||
|
|
||||||
|
if (!res) {
|
||||||
|
js_pushnull(J);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
mjs_push_element(J, res);
|
||||||
el = el->get_parent();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
js_pushnull(J);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -2656,35 +2666,21 @@ mjs_element_matches(js_State *J)
|
|||||||
#ifdef ECMASCRIPT_DEBUG
|
#ifdef ECMASCRIPT_DEBUG
|
||||||
fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__);
|
fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__);
|
||||||
#endif
|
#endif
|
||||||
// TODO
|
dom_node *el = (dom_node *)(mjs_getprivate(J, 0));
|
||||||
#if 0
|
|
||||||
xmlpp::Element *el = static_cast<xmlpp::Element *>(mjs_getprivate(J, 0));
|
|
||||||
|
|
||||||
if (!el) {
|
if (!el) {
|
||||||
js_pushboolean(J, 0);
|
js_pushboolean(J, 0);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const char *str = js_tostring(J, 1);
|
const char *selector = js_tostring(J, 1);
|
||||||
xmlpp::ustring css = str;
|
|
||||||
xmlpp::ustring xpath = css2xpath(css);
|
|
||||||
|
|
||||||
xmlpp::Node::NodeSet elements;
|
if (!selector) {
|
||||||
|
|
||||||
try {
|
|
||||||
elements = el->find(xpath);
|
|
||||||
} catch (xmlpp::exception &e) {
|
|
||||||
js_pushboolean(J, 0);
|
js_pushboolean(J, 0);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
void *res = el_match_selector(selector, el);
|
||||||
|
|
||||||
for (auto node: elements) {
|
js_pushboolean(J, res);
|
||||||
if (node == el) {
|
|
||||||
js_pushboolean(J, 1);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
js_pushboolean(J, 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -2693,36 +2689,25 @@ mjs_element_querySelector(js_State *J)
|
|||||||
#ifdef ECMASCRIPT_DEBUG
|
#ifdef ECMASCRIPT_DEBUG
|
||||||
fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__);
|
fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__);
|
||||||
#endif
|
#endif
|
||||||
// TODO
|
dom_node *el = (dom_node *)(mjs_getprivate(J, 0));
|
||||||
#if 0
|
|
||||||
xmlpp::Element *el = static_cast<xmlpp::Element *>(mjs_getprivate(J, 0));
|
|
||||||
|
|
||||||
if (!el) {
|
if (!el) {
|
||||||
js_pushboolean(J, 0);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const char *str = js_tostring(J, 1);
|
|
||||||
xmlpp::ustring css = str;
|
|
||||||
xmlpp::ustring xpath = css2xpath(css);
|
|
||||||
xmlpp::Node::NodeSet elements;
|
|
||||||
|
|
||||||
try {
|
|
||||||
elements = el->find(xpath);
|
|
||||||
} catch (xmlpp::exception &e) {
|
|
||||||
js_pushnull(J);
|
js_pushnull(J);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
const char *selector = js_tostring(J, 1);
|
||||||
|
|
||||||
for (auto node: elements)
|
if (!selector) {
|
||||||
{
|
js_pushnull(J);
|
||||||
if (isAncestor(el, node))
|
|
||||||
{
|
|
||||||
mjs_push_element(J, node);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
void *ret = walk_tree_query(el, selector, 0);
|
||||||
#endif
|
|
||||||
|
if (!ret) {
|
||||||
js_pushnull(J);
|
js_pushnull(J);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
mjs_push_element(J, ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -2731,38 +2716,52 @@ mjs_element_querySelectorAll(js_State *J)
|
|||||||
#ifdef ECMASCRIPT_DEBUG
|
#ifdef ECMASCRIPT_DEBUG
|
||||||
fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__);
|
fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__);
|
||||||
#endif
|
#endif
|
||||||
// TODO
|
struct ecmascript_interpreter *interpreter = (struct ecmascript_interpreter *)js_getcontext(J);
|
||||||
#if 0
|
struct document_view *doc_view = interpreter->vs->doc_view;
|
||||||
xmlpp::Element *el = static_cast<xmlpp::Element *>(mjs_getprivate(J, 0));
|
struct document *document = doc_view->document;
|
||||||
|
|
||||||
|
if (!document->dom) {
|
||||||
|
js_pushnull(J);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
dom_node *el = (dom_node *)(mjs_getprivate(J, 0));
|
||||||
|
|
||||||
if (!el) {
|
if (!el) {
|
||||||
js_pushboolean(J, 0);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const char *str = js_tostring(J, 1);
|
|
||||||
xmlpp::ustring css = str;
|
|
||||||
xmlpp::ustring xpath = css2xpath(css);
|
|
||||||
xmlpp::Node::NodeSet elements;
|
|
||||||
xmlpp::Node::NodeSet *res = new(std::nothrow) xmlpp::Node::NodeSet;
|
|
||||||
|
|
||||||
if (!res) {
|
|
||||||
js_pushnull(J);
|
js_pushnull(J);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
const char *selector = js_tostring(J, 1);
|
||||||
|
|
||||||
try {
|
if (!selector) {
|
||||||
elements = el->find(xpath);
|
|
||||||
} catch (xmlpp::exception &e) {}
|
|
||||||
|
|
||||||
for (auto node: elements)
|
|
||||||
{
|
|
||||||
if (isAncestor(el, node)) {
|
|
||||||
res->push_back(node);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
mjs_push_collection(J, res);
|
|
||||||
#endif
|
|
||||||
js_pushnull(J);
|
js_pushnull(J);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
dom_string *tag_name = NULL;
|
||||||
|
dom_exception exc = dom_string_create((const uint8_t *)"B", 1, &tag_name);
|
||||||
|
|
||||||
|
if (exc != DOM_NO_ERR || !tag_name) {
|
||||||
|
js_pushnull(J);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
dom_element *element = NULL;
|
||||||
|
exc = dom_document_create_element(document->dom, tag_name, &element);
|
||||||
|
dom_string_unref(tag_name);
|
||||||
|
|
||||||
|
if (exc != DOM_NO_ERR || !element) {
|
||||||
|
js_pushnull(J);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
walk_tree_query_append((dom_node *)element, el, selector, 0);
|
||||||
|
|
||||||
|
dom_nodelist *nodes = NULL;
|
||||||
|
exc = dom_node_get_child_nodes(element, &nodes);
|
||||||
|
dom_node_unref(element);
|
||||||
|
|
||||||
|
if (exc != DOM_NO_ERR || !nodes) {
|
||||||
|
js_pushnull(J);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
mjs_push_nodelist(J, nodes);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -1,2 +1,2 @@
|
|||||||
srcs += files('attr.c', 'attributes.c', 'collection.c', 'console.c', 'css.c', 'customevent.c', 'document.c', 'element.c', 'event.c', 'form.c', 'forms.c', 'history.c', 'implementation.c', 'input.c', 'keyboard.c',
|
srcs += files('attr.c', 'attributes.c', 'collection.c', 'console.c', 'css.c', 'customevent.c', 'document.c', 'element.c', 'event.c', 'form.c', 'forms.c', 'history.c', 'implementation.c', 'input.c', 'keyboard.c',
|
||||||
'localstorage.c', 'location.c', 'mapa.c', 'message.c', 'navigator.c', 'nodelist.c', 'screen.c', 'style.c', 'unibar.c', 'window.c', 'xhr.c')
|
'localstorage.c', 'location.c', 'mapa.c', 'message.c', 'navigator.c', 'nodelist.c', 'screen.c', 'style.c', 'unibar.c', 'url.c', 'window.c', 'xhr.c')
|
||||||
|
606
src/ecmascript/mujs/url.c
Normal file
606
src/ecmascript/mujs/url.c
Normal file
@ -0,0 +1,606 @@
|
|||||||
|
/* The MuJS URL object implementation. */
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
#include "config.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "elinks.h"
|
||||||
|
|
||||||
|
#include "ecmascript/ecmascript.h"
|
||||||
|
#include "ecmascript/mujs.h"
|
||||||
|
#include "ecmascript/mujs/url.h"
|
||||||
|
#include "protocol/uri.h"
|
||||||
|
|
||||||
|
struct eljs_url {
|
||||||
|
struct uri uri;
|
||||||
|
char *hash;
|
||||||
|
char *host;
|
||||||
|
char *pathname;
|
||||||
|
char *port;
|
||||||
|
char *protocol;
|
||||||
|
char *search;
|
||||||
|
};
|
||||||
|
|
||||||
|
static void
|
||||||
|
mjs_url_finalizer(js_State *J, void *val)
|
||||||
|
{
|
||||||
|
#ifdef ECMASCRIPT_DEBUG
|
||||||
|
fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__);
|
||||||
|
#endif
|
||||||
|
struct eljs_url *url = (struct eljs_url *)val;
|
||||||
|
|
||||||
|
if (url) {
|
||||||
|
done_uri(&url->uri);
|
||||||
|
mem_free_if(url->hash);
|
||||||
|
mem_free_if(url->host);
|
||||||
|
mem_free_if(url->pathname);
|
||||||
|
mem_free_if(url->port);
|
||||||
|
mem_free_if(url->protocol);
|
||||||
|
mem_free_if(url->search);
|
||||||
|
mem_free(url);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
mjs_url_get_property_hash(js_State *J)
|
||||||
|
{
|
||||||
|
#ifdef ECMASCRIPT_DEBUG
|
||||||
|
fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__);
|
||||||
|
#endif
|
||||||
|
struct eljs_url *url = (struct eljs_url *)js_touserdata(J, 0, "URL");
|
||||||
|
|
||||||
|
if (!url) {
|
||||||
|
js_pushnull(J);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct string fragment;
|
||||||
|
if (!init_string(&fragment)) {
|
||||||
|
js_error(J, "out of memory");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (url->uri.fragmentlen) {
|
||||||
|
add_bytes_to_string(&fragment, url->uri.fragment, url->uri.fragmentlen);
|
||||||
|
}
|
||||||
|
js_pushstring(J, fragment.source);
|
||||||
|
done_string(&fragment);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
mjs_url_get_property_host(js_State *J)
|
||||||
|
{
|
||||||
|
#ifdef ECMASCRIPT_DEBUG
|
||||||
|
fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__);
|
||||||
|
#endif
|
||||||
|
struct eljs_url *url = (struct eljs_url *)js_touserdata(J, 0, "URL");
|
||||||
|
|
||||||
|
if (!url) {
|
||||||
|
js_pushnull(J);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
char *str = get_uri_string(&url->uri, URI_HOST_PORT);
|
||||||
|
|
||||||
|
if (!str) {
|
||||||
|
#ifdef ECMASCRIPT_DEBUG
|
||||||
|
fprintf(stderr, "%s:%s %d\n", __FILE__, __FUNCTION__, __LINE__);
|
||||||
|
#endif
|
||||||
|
js_error(J, "out of memory");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
js_pushstring(J, str);
|
||||||
|
mem_free(str);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
mjs_url_get_property_hostname(js_State *J)
|
||||||
|
{
|
||||||
|
#ifdef ECMASCRIPT_DEBUG
|
||||||
|
fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__);
|
||||||
|
#endif
|
||||||
|
struct eljs_url *url = (struct eljs_url *)js_touserdata(J, 0, "URL");
|
||||||
|
|
||||||
|
if (!url) {
|
||||||
|
js_pushnull(J);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
char *str = get_uri_string(&url->uri, URI_HOST);
|
||||||
|
|
||||||
|
if (!str) {
|
||||||
|
#ifdef ECMASCRIPT_DEBUG
|
||||||
|
fprintf(stderr, "%s:%s %d\n", __FILE__, __FUNCTION__, __LINE__);
|
||||||
|
#endif
|
||||||
|
js_error(J, "out of memory");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
js_pushstring(J, str);
|
||||||
|
mem_free(str);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
mjs_url_get_property_href(js_State *J)
|
||||||
|
{
|
||||||
|
#ifdef ECMASCRIPT_DEBUG
|
||||||
|
fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__);
|
||||||
|
#endif
|
||||||
|
struct eljs_url *url = (struct eljs_url *)js_touserdata(J, 0, "URL");
|
||||||
|
|
||||||
|
if (!url) {
|
||||||
|
js_pushnull(J);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
char *str = get_uri_string(&url->uri, URI_ORIGINAL);
|
||||||
|
|
||||||
|
if (!str) {
|
||||||
|
#ifdef ECMASCRIPT_DEBUG
|
||||||
|
fprintf(stderr, "%s:%s %d\n", __FILE__, __FUNCTION__, __LINE__);
|
||||||
|
#endif
|
||||||
|
js_error(J, "out of memory");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
js_pushstring(J, str);
|
||||||
|
mem_free(str);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
mjs_url_get_property_origin(js_State *J)
|
||||||
|
{
|
||||||
|
#ifdef ECMASCRIPT_DEBUG
|
||||||
|
fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__);
|
||||||
|
#endif
|
||||||
|
struct eljs_url *url = (struct eljs_url *)js_touserdata(J, 0, "URL");
|
||||||
|
|
||||||
|
if (!url) {
|
||||||
|
js_pushnull(J);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
char *str = get_uri_string(&url->uri, URI_SERVER);
|
||||||
|
|
||||||
|
if (!str) {
|
||||||
|
#ifdef ECMASCRIPT_DEBUG
|
||||||
|
fprintf(stderr, "%s:%s %d\n", __FILE__, __FUNCTION__, __LINE__);
|
||||||
|
#endif
|
||||||
|
js_error(J, "out of memory");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
js_pushstring(J, str);
|
||||||
|
mem_free(str);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
mjs_url_get_property_pathname(js_State *J)
|
||||||
|
{
|
||||||
|
#ifdef ECMASCRIPT_DEBUG
|
||||||
|
fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__);
|
||||||
|
#endif
|
||||||
|
struct eljs_url *url = (struct eljs_url *)js_touserdata(J, 0, "URL");
|
||||||
|
|
||||||
|
if (!url) {
|
||||||
|
js_pushnull(J);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
struct string pathname;
|
||||||
|
if (!init_string(&pathname)) {
|
||||||
|
js_error(J, "out of memory");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const char *query = (const char *)memchr(url->uri.data, '?', url->uri.datalen);
|
||||||
|
int len = (query ? query - url->uri.data : url->uri.datalen);
|
||||||
|
|
||||||
|
add_char_to_string(&pathname, '/');
|
||||||
|
add_bytes_to_string(&pathname, url->uri.data, len);
|
||||||
|
js_pushstring(J, pathname.source);
|
||||||
|
done_string(&pathname);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
mjs_url_get_property_port(js_State *J)
|
||||||
|
{
|
||||||
|
#ifdef ECMASCRIPT_DEBUG
|
||||||
|
fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__);
|
||||||
|
#endif
|
||||||
|
struct eljs_url *url = (struct eljs_url *)js_touserdata(J, 0, "URL");
|
||||||
|
|
||||||
|
if (!url) {
|
||||||
|
js_pushnull(J);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
struct string port;
|
||||||
|
if (!init_string(&port)) {
|
||||||
|
js_error(J, "out of memory");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (url->uri.portlen) {
|
||||||
|
add_bytes_to_string(&port, url->uri.port, url->uri.portlen);
|
||||||
|
}
|
||||||
|
js_pushstring(J, port.source);
|
||||||
|
done_string(&port);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
mjs_url_get_property_protocol(js_State *J)
|
||||||
|
{
|
||||||
|
#ifdef ECMASCRIPT_DEBUG
|
||||||
|
fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__);
|
||||||
|
#endif
|
||||||
|
struct eljs_url *url = (struct eljs_url *)js_touserdata(J, 0, "URL");
|
||||||
|
|
||||||
|
if (!url) {
|
||||||
|
js_pushnull(J);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
struct string proto;
|
||||||
|
if (!init_string(&proto)) {
|
||||||
|
js_error(J, "out of memory");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Custom or unknown keep the URI untouched. */
|
||||||
|
if (url->uri.protocol == PROTOCOL_UNKNOWN) {
|
||||||
|
add_to_string(&proto, struri(&url->uri));
|
||||||
|
} else {
|
||||||
|
add_bytes_to_string(&proto, url->uri.string, url->uri.protocollen);
|
||||||
|
add_char_to_string(&proto, ':');
|
||||||
|
}
|
||||||
|
js_pushstring(J, proto.source);
|
||||||
|
done_string(&proto);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
mjs_url_get_property_search(js_State *J)
|
||||||
|
{
|
||||||
|
#ifdef ECMASCRIPT_DEBUG
|
||||||
|
fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__);
|
||||||
|
#endif
|
||||||
|
struct eljs_url *url = (struct eljs_url *)js_touserdata(J, 0, "URL");
|
||||||
|
|
||||||
|
if (!url) {
|
||||||
|
js_pushnull(J);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
struct string search;
|
||||||
|
|
||||||
|
if (!init_string(&search)) {
|
||||||
|
js_error(J, "out of memory");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const char *query = (const char *)memchr(url->uri.data, '?', url->uri.datalen);
|
||||||
|
|
||||||
|
if (query) {
|
||||||
|
add_bytes_to_string(&search, query, strcspn(query, "#" POST_CHAR_S));
|
||||||
|
}
|
||||||
|
js_pushstring(J, search.source);
|
||||||
|
done_string(&search);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
mjs_url_set_property_hash(js_State *J)
|
||||||
|
{
|
||||||
|
#ifdef ECMASCRIPT_DEBUG
|
||||||
|
fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__);
|
||||||
|
#endif
|
||||||
|
struct eljs_url *url = (struct eljs_url *)js_touserdata(J, 0, "URL");
|
||||||
|
|
||||||
|
if (!url) {
|
||||||
|
js_pushnull(J);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const char *str = js_tostring(J, 1);
|
||||||
|
|
||||||
|
if (!str) {
|
||||||
|
js_error(J, "out of memory");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
char *hash = stracpy(str);
|
||||||
|
|
||||||
|
mem_free_set(&url->hash, hash);
|
||||||
|
|
||||||
|
if (hash) {
|
||||||
|
url->uri.fragment = hash;
|
||||||
|
url->uri.fragmentlen = strlen(hash);
|
||||||
|
}
|
||||||
|
js_pushundefined(J);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
mjs_url_set_property_host(js_State *J)
|
||||||
|
{
|
||||||
|
#ifdef ECMASCRIPT_DEBUG
|
||||||
|
fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__);
|
||||||
|
#endif
|
||||||
|
struct eljs_url *url = (struct eljs_url *)js_touserdata(J, 0, "URL");
|
||||||
|
|
||||||
|
if (!url) {
|
||||||
|
js_pushnull(J);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const char *str = js_tostring(J, 1);
|
||||||
|
|
||||||
|
if (!str) {
|
||||||
|
js_error(J, "out of memory");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
char *host = stracpy(str);
|
||||||
|
|
||||||
|
mem_free_set(&url->host, host);
|
||||||
|
|
||||||
|
if (host) {
|
||||||
|
url->uri.host = host;
|
||||||
|
url->uri.hostlen = strlen(str);
|
||||||
|
}
|
||||||
|
js_pushundefined(J);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
mjs_url_set_property_hostname(js_State *J)
|
||||||
|
{
|
||||||
|
#ifdef ECMASCRIPT_DEBUG
|
||||||
|
fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__);
|
||||||
|
#endif
|
||||||
|
struct eljs_url *url = (struct eljs_url *)js_touserdata(J, 0, "URL");
|
||||||
|
|
||||||
|
if (!url) {
|
||||||
|
js_pushnull(J);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const char *str = js_tostring(J, 1);
|
||||||
|
|
||||||
|
if (!str) {
|
||||||
|
js_error(J, "out of memory");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
char *hostname = stracpy(str);
|
||||||
|
|
||||||
|
mem_free_set(&url->host, hostname);
|
||||||
|
|
||||||
|
if (hostname) {
|
||||||
|
url->uri.host = hostname;
|
||||||
|
url->uri.hostlen = strlen(hostname);
|
||||||
|
}
|
||||||
|
js_pushundefined(J);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
mjs_url_set_property_href(js_State *J)
|
||||||
|
{
|
||||||
|
#ifdef ECMASCRIPT_DEBUG
|
||||||
|
fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__);
|
||||||
|
#endif
|
||||||
|
struct eljs_url *url = (struct eljs_url *)js_touserdata(J, 0, "URL");
|
||||||
|
|
||||||
|
if (!url) {
|
||||||
|
js_pushnull(J);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const char *str = js_tostring(J, 1);
|
||||||
|
|
||||||
|
if (!str) {
|
||||||
|
js_error(J, "out of memory");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
done_uri(&url->uri);
|
||||||
|
|
||||||
|
char *urlstring = stracpy(str);
|
||||||
|
|
||||||
|
if (!urlstring) {
|
||||||
|
js_error(J, "out of memory");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
int ret = parse_uri(&url->uri, urlstring);
|
||||||
|
|
||||||
|
if (ret != URI_ERRNO_OK) {
|
||||||
|
js_error(J, "error");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
js_pushundefined(J);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
mjs_url_set_property_pathname(js_State *J)
|
||||||
|
{
|
||||||
|
#ifdef ECMASCRIPT_DEBUG
|
||||||
|
fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__);
|
||||||
|
#endif
|
||||||
|
struct eljs_url *url = (struct eljs_url *)js_touserdata(J, 0, "URL");
|
||||||
|
|
||||||
|
if (!url) {
|
||||||
|
js_pushnull(J);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const char *str = js_tostring(J, 1);
|
||||||
|
|
||||||
|
if (!str) {
|
||||||
|
js_error(J, "out of memory");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
char *pathname = stracpy(str);
|
||||||
|
|
||||||
|
mem_free_set(&url->pathname, pathname);
|
||||||
|
|
||||||
|
if (pathname) {
|
||||||
|
url->uri.data = pathname;
|
||||||
|
url->uri.datalen = strlen(pathname);
|
||||||
|
}
|
||||||
|
js_pushundefined(J);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
mjs_url_set_property_port(js_State *J)
|
||||||
|
{
|
||||||
|
#ifdef ECMASCRIPT_DEBUG
|
||||||
|
fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__);
|
||||||
|
#endif
|
||||||
|
struct eljs_url *url = (struct eljs_url *)js_touserdata(J, 0, "URL");
|
||||||
|
|
||||||
|
if (!url) {
|
||||||
|
js_pushnull(J);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const char *str = js_tostring(J, 1);
|
||||||
|
|
||||||
|
if (!str) {
|
||||||
|
js_error(J, "out of memory");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
char *port = stracpy(str);
|
||||||
|
|
||||||
|
mem_free_set(&url->port, port);
|
||||||
|
|
||||||
|
if (port) {
|
||||||
|
url->uri.port = port;
|
||||||
|
url->uri.portlen = strlen(port);
|
||||||
|
}
|
||||||
|
js_pushundefined(J);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int
|
||||||
|
get_protocol_length(const char *url)
|
||||||
|
{
|
||||||
|
char *end = (char *) url;
|
||||||
|
|
||||||
|
/* Seek the end of the protocol name if any. */
|
||||||
|
/* RFC1738:
|
||||||
|
* scheme = 1*[ lowalpha | digit | "+" | "-" | "." ]
|
||||||
|
* (but per its recommendations we accept "upalpha" too) */
|
||||||
|
while (isalnum(*end) || *end == '+' || *end == '-' || *end == '.')
|
||||||
|
end++;
|
||||||
|
|
||||||
|
/* Now we make something to support our "IP version in protocol scheme
|
||||||
|
* name" hack and silently chop off the last digit if it's there. The
|
||||||
|
* IETF's not gonna notice I hope or it'd be going after us hard. */
|
||||||
|
if (end != url && isdigit(end[-1]))
|
||||||
|
end--;
|
||||||
|
|
||||||
|
/* Also return 0 if there's no protocol name (@end == @url). */
|
||||||
|
return (*end == ':' || isdigit(*end)) ? end - url : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
mjs_url_set_property_protocol(js_State *J)
|
||||||
|
{
|
||||||
|
#ifdef ECMASCRIPT_DEBUG
|
||||||
|
fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__);
|
||||||
|
#endif
|
||||||
|
struct eljs_url *url = (struct eljs_url *)js_touserdata(J, 0, "URL");
|
||||||
|
|
||||||
|
if (!url) {
|
||||||
|
js_pushnull(J);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const char *str = js_tostring(J, 1);
|
||||||
|
|
||||||
|
if (!str) {
|
||||||
|
js_error(J, "out of memory");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
char *protocol = stracpy(str);
|
||||||
|
|
||||||
|
mem_free_set(&url->protocol, protocol);
|
||||||
|
|
||||||
|
if (protocol) {
|
||||||
|
url->uri.protocollen = get_protocol_length(protocol);
|
||||||
|
/* Figure out whether the protocol is known */
|
||||||
|
url->uri.protocol = get_protocol(protocol, url->uri.protocollen);
|
||||||
|
}
|
||||||
|
js_pushundefined(J);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
mjs_url_set_property_search(js_State *J)
|
||||||
|
{
|
||||||
|
#ifdef ECMASCRIPT_DEBUG
|
||||||
|
fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__);
|
||||||
|
#endif
|
||||||
|
struct eljs_url *url = (struct eljs_url *)js_touserdata(J, 0, "URL");
|
||||||
|
|
||||||
|
if (!url) {
|
||||||
|
js_pushnull(J);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const char *str = js_tostring(J, 1);
|
||||||
|
|
||||||
|
if (!str) {
|
||||||
|
js_error(J, "out of memory");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
char *search = stracpy(str);
|
||||||
|
|
||||||
|
mem_free_set(&url->search, search);
|
||||||
|
|
||||||
|
if (search) {
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
js_pushundefined(J);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
mjs_url_toString(js_State *J)
|
||||||
|
{
|
||||||
|
#ifdef ECMASCRIPT_DEBUG
|
||||||
|
fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__);
|
||||||
|
#endif
|
||||||
|
mjs_url_get_property_href(J);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
mjs_url_fun(js_State *J)
|
||||||
|
{
|
||||||
|
#ifdef ECMASCRIPT_DEBUG
|
||||||
|
fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__);
|
||||||
|
#endif
|
||||||
|
js_pushundefined(J);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
mjs_url_constructor(js_State *J)
|
||||||
|
{
|
||||||
|
#ifdef ECMASCRIPT_DEBUG
|
||||||
|
fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__);
|
||||||
|
#endif
|
||||||
|
struct eljs_url *url = (struct eljs_url *)mem_calloc(1, sizeof(*url));
|
||||||
|
|
||||||
|
if (!url) {
|
||||||
|
js_error(J, "out of memory");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const char *urlstring = js_tostring(J, 1);
|
||||||
|
|
||||||
|
if (!urlstring) {
|
||||||
|
js_error(J, "out of memory");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
int ret = parse_uri(&url->uri, urlstring);
|
||||||
|
|
||||||
|
if (ret != URI_ERRNO_OK) {
|
||||||
|
js_error(J, "error");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
js_newobject(J);
|
||||||
|
{
|
||||||
|
js_newuserdata(J, "URL", url, mjs_url_finalizer);
|
||||||
|
addmethod(J, "toString", mjs_url_toString, 0);
|
||||||
|
|
||||||
|
addproperty(J, "hash", mjs_url_get_property_hash, mjs_url_set_property_hash);
|
||||||
|
addproperty(J, "host", mjs_url_get_property_host, mjs_url_set_property_host);
|
||||||
|
addproperty(J, "hostname", mjs_url_get_property_hostname, mjs_url_set_property_hostname);
|
||||||
|
addproperty(J, "href", mjs_url_get_property_href, mjs_url_set_property_href);
|
||||||
|
addproperty(J, "origin", mjs_url_get_property_origin, NULL);
|
||||||
|
addproperty(J, "pathname", mjs_url_get_property_pathname, mjs_url_set_property_pathname);
|
||||||
|
addproperty(J, "port", mjs_url_get_property_port, mjs_url_set_property_port);
|
||||||
|
addproperty(J, "protocol", mjs_url_get_property_protocol, mjs_url_set_property_protocol);
|
||||||
|
addproperty(J, "search", mjs_url_get_property_search, mjs_url_set_property_search);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
mjs_url_init(js_State *J)
|
||||||
|
{
|
||||||
|
js_pushglobal(J);
|
||||||
|
js_newcconstructor(J, mjs_url_fun, mjs_url_constructor, "URL", 0);
|
||||||
|
js_defglobal(J, "URL", JS_DONTENUM);
|
||||||
|
return 0;
|
||||||
|
}
|
16
src/ecmascript/mujs/url.h
Normal file
16
src/ecmascript/mujs/url.h
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
#ifndef EL__ECMASCRIPT_MUJS_URL_H
|
||||||
|
#define EL__ECMASCRIPT_MUJS_URL_H
|
||||||
|
|
||||||
|
#include <mujs.h>
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int mjs_url_init(js_State *J);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
@ -40,6 +40,7 @@
|
|||||||
#include "ecmascript/quickjs/navigator.h"
|
#include "ecmascript/quickjs/navigator.h"
|
||||||
#include "ecmascript/quickjs/screen.h"
|
#include "ecmascript/quickjs/screen.h"
|
||||||
#include "ecmascript/quickjs/unibar.h"
|
#include "ecmascript/quickjs/unibar.h"
|
||||||
|
#include "ecmascript/quickjs/url.h"
|
||||||
#include "ecmascript/quickjs/window.h"
|
#include "ecmascript/quickjs/window.h"
|
||||||
#include "ecmascript/quickjs/xhr.h"
|
#include "ecmascript/quickjs/xhr.h"
|
||||||
#include "intl/libintl.h"
|
#include "intl/libintl.h"
|
||||||
@ -182,6 +183,7 @@ quickjs_get_interpreter(struct ecmascript_interpreter *interpreter)
|
|||||||
js_keyboardEvent_init(ctx);
|
js_keyboardEvent_init(ctx);
|
||||||
js_messageEvent_init(ctx);
|
js_messageEvent_init(ctx);
|
||||||
js_customEvent_init(ctx);
|
js_customEvent_init(ctx);
|
||||||
|
js_url_init(ctx);
|
||||||
|
|
||||||
interpreter->document_obj = js_document_init(ctx);
|
interpreter->document_obj = js_document_init(ctx);
|
||||||
|
|
||||||
|
@ -2,6 +2,6 @@ top_builddir=../../..
|
|||||||
include $(top_builddir)/Makefile.config
|
include $(top_builddir)/Makefile.config
|
||||||
|
|
||||||
OBJS = attr.o attributes.o collection.o console.o css.o customevent.o document.o element.o event.o form.o forms.o heartbeat.o history.o implementation.o input.o \
|
OBJS = attr.o attributes.o collection.o console.o css.o customevent.o document.o element.o event.o form.o forms.o heartbeat.o history.o implementation.o input.o \
|
||||||
keyboard.o localstorage.o location.o mapa.o message.o navigator.o nodelist.o screen.o style.o unibar.o window.o xhr.o
|
keyboard.o localstorage.o location.o mapa.o message.o navigator.o nodelist.o screen.o style.o unibar.o url.o window.o xhr.o
|
||||||
|
|
||||||
include $(top_srcdir)/Makefile.lib
|
include $(top_srcdir)/Makefile.lib
|
||||||
|
@ -21,6 +21,7 @@
|
|||||||
#include "document/libdom/doc.h"
|
#include "document/libdom/doc.h"
|
||||||
#include "document/view.h"
|
#include "document/view.h"
|
||||||
#include "ecmascript/ecmascript.h"
|
#include "ecmascript/ecmascript.h"
|
||||||
|
#include "ecmascript/ecmascript-c.h"
|
||||||
#include "ecmascript/libdom/parse.h"
|
#include "ecmascript/libdom/parse.h"
|
||||||
#include "ecmascript/quickjs/mapa.h"
|
#include "ecmascript/quickjs/mapa.h"
|
||||||
#include "ecmascript/quickjs.h"
|
#include "ecmascript/quickjs.h"
|
||||||
@ -1475,7 +1476,6 @@ js_document_getElementsByTagName(JSContext *ctx, JSValueConst this_val, int argc
|
|||||||
return JS_NULL;
|
return JS_NULL;
|
||||||
}
|
}
|
||||||
JSValue rr = getNodeList(ctx, nodes);
|
JSValue rr = getNodeList(ctx, nodes);
|
||||||
JS_FreeValue(ctx, rr);
|
|
||||||
|
|
||||||
RETURN_JS(rr);
|
RETURN_JS(rr);
|
||||||
}
|
}
|
||||||
@ -1498,40 +1498,28 @@ js_document_querySelector(JSContext *ctx, JSValueConst this_val, int argc, JSVal
|
|||||||
if (!document->dom) {
|
if (!document->dom) {
|
||||||
return JS_NULL;
|
return JS_NULL;
|
||||||
}
|
}
|
||||||
|
dom_node *root = NULL; /* root element of document */
|
||||||
|
/* Get root element */
|
||||||
|
dom_exception exc = dom_document_get_document_element(document->dom, &root);
|
||||||
|
|
||||||
// TODO
|
if (exc != DOM_NO_ERR) {
|
||||||
return JS_NULL;
|
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;
|
size_t len;
|
||||||
|
const char *selector = JS_ToCStringLen(ctx, &len, argv[0]);
|
||||||
|
|
||||||
str = JS_ToCStringLen(ctx, &len, argv[0]);
|
if (!selector) {
|
||||||
|
dom_node_unref(root);
|
||||||
if (!str) {
|
|
||||||
return JS_EXCEPTION;
|
|
||||||
}
|
|
||||||
xmlpp::ustring css = str;
|
|
||||||
JS_FreeCString(ctx, str);
|
|
||||||
xmlpp::ustring xpath = css2xpath(css);
|
|
||||||
|
|
||||||
xmlpp::Node::NodeSet elements;
|
|
||||||
|
|
||||||
try {
|
|
||||||
elements = root->find(xpath);
|
|
||||||
} catch (xmlpp::exception &e) {
|
|
||||||
return JS_NULL;
|
return JS_NULL;
|
||||||
}
|
}
|
||||||
|
void *ret = walk_tree_query(root, selector, 0);
|
||||||
|
JS_FreeCString(ctx, selector);
|
||||||
|
dom_node_unref(root);
|
||||||
|
|
||||||
if (elements.size() == 0) {
|
if (!ret) {
|
||||||
return JS_NULL;
|
return JS_NULL;
|
||||||
}
|
}
|
||||||
|
return getElement(ctx, ret);
|
||||||
auto node = elements[0];
|
|
||||||
|
|
||||||
return getElement(ctx, node);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static JSValue
|
static JSValue
|
||||||
@ -1552,38 +1540,50 @@ js_document_querySelectorAll(JSContext *ctx, JSValueConst this_val, int argc, JS
|
|||||||
if (!document->dom) {
|
if (!document->dom) {
|
||||||
return JS_NULL;
|
return JS_NULL;
|
||||||
}
|
}
|
||||||
|
dom_node *doc_root = NULL; /* root element of document */
|
||||||
|
/* Get root element */
|
||||||
|
dom_exception exc = dom_document_get_document_element(document->dom, &doc_root);
|
||||||
|
|
||||||
// TODO
|
if (exc != DOM_NO_ERR) {
|
||||||
return JS_NULL;
|
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;
|
size_t len;
|
||||||
|
const char *selector = JS_ToCStringLen(ctx, &len, argv[0]);
|
||||||
|
|
||||||
str = JS_ToCStringLen(ctx, &len, argv[0]);
|
if (!selector) {
|
||||||
|
dom_node_unref(doc_root);
|
||||||
if (!str) {
|
|
||||||
return JS_EXCEPTION;
|
|
||||||
}
|
|
||||||
xmlpp::ustring css = str;
|
|
||||||
JS_FreeCString(ctx, str);
|
|
||||||
xmlpp::ustring xpath = css2xpath(css);
|
|
||||||
xmlpp::Node::NodeSet *elements = new(std::nothrow) xmlpp::Node::NodeSet;
|
|
||||||
|
|
||||||
if (!elements) {
|
|
||||||
return JS_NULL;
|
return JS_NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
dom_string *tag_name = NULL;
|
||||||
*elements = root->find(xpath);
|
exc = dom_string_create((const uint8_t *)"B", 1, &tag_name);
|
||||||
} catch (xmlpp::exception &e) {
|
|
||||||
}
|
|
||||||
JSValue rr = getCollection(ctx, elements);
|
|
||||||
JS_FreeValue(ctx, rr);
|
|
||||||
|
|
||||||
RETURN_JS(rr);
|
if (exc != DOM_NO_ERR || !tag_name) {
|
||||||
#endif
|
dom_node_unref(doc_root);
|
||||||
|
JS_FreeCString(ctx, selector);
|
||||||
|
return JS_NULL;
|
||||||
|
}
|
||||||
|
dom_element *element = NULL;
|
||||||
|
exc = dom_document_create_element(document->dom, tag_name, &element);
|
||||||
|
dom_string_unref(tag_name);
|
||||||
|
|
||||||
|
if (exc != DOM_NO_ERR || !element) {
|
||||||
|
dom_node_unref(doc_root);
|
||||||
|
JS_FreeCString(ctx, selector);
|
||||||
|
return JS_NULL;
|
||||||
|
}
|
||||||
|
walk_tree_query_append((dom_node *)element, doc_root, selector, 0);
|
||||||
|
dom_node_unref(doc_root);
|
||||||
|
JS_FreeCString(ctx, selector);
|
||||||
|
|
||||||
|
dom_nodelist *nodes = NULL;
|
||||||
|
exc = dom_node_get_child_nodes(element, &nodes);
|
||||||
|
dom_node_unref(element);
|
||||||
|
|
||||||
|
if (exc != DOM_NO_ERR || !nodes) {
|
||||||
|
return JS_NULL;
|
||||||
|
}
|
||||||
|
return getNodeList(ctx, nodes);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
|
@ -22,6 +22,7 @@
|
|||||||
#include "document/libdom/renderer2.h"
|
#include "document/libdom/renderer2.h"
|
||||||
#include "document/view.h"
|
#include "document/view.h"
|
||||||
#include "ecmascript/ecmascript.h"
|
#include "ecmascript/ecmascript.h"
|
||||||
|
#include "ecmascript/ecmascript-c.h"
|
||||||
#include "ecmascript/quickjs/mapa.h"
|
#include "ecmascript/quickjs/mapa.h"
|
||||||
#include "ecmascript/quickjs.h"
|
#include "ecmascript/quickjs.h"
|
||||||
#include "ecmascript/quickjs/attr.h"
|
#include "ecmascript/quickjs/attr.h"
|
||||||
@ -241,7 +242,6 @@ js_element_get_property_children(JSContext *ctx, JSValueConst this_val)
|
|||||||
return JS_NULL;
|
return JS_NULL;
|
||||||
}
|
}
|
||||||
JSValue rr = getNodeList(ctx, nodes);
|
JSValue rr = getNodeList(ctx, nodes);
|
||||||
JS_FreeValue(ctx, rr);
|
|
||||||
|
|
||||||
RETURN_JS(rr);
|
RETURN_JS(rr);
|
||||||
}
|
}
|
||||||
@ -294,7 +294,6 @@ js_element_get_property_childNodes(JSContext *ctx, JSValueConst this_val)
|
|||||||
return JS_NULL;
|
return JS_NULL;
|
||||||
}
|
}
|
||||||
JSValue rr = getNodeList(ctx, nodes);
|
JSValue rr = getNodeList(ctx, nodes);
|
||||||
JS_FreeValue(ctx, rr);
|
|
||||||
|
|
||||||
RETURN_JS(rr);
|
RETURN_JS(rr);
|
||||||
}
|
}
|
||||||
@ -2293,57 +2292,60 @@ js_element_closest(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst
|
|||||||
#ifdef ECMASCRIPT_DEBUG
|
#ifdef ECMASCRIPT_DEBUG
|
||||||
fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__);
|
fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// TODO
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
REF_JS(this_val);
|
REF_JS(this_val);
|
||||||
|
|
||||||
if (argc != 1) {
|
if (argc != 1) {
|
||||||
return JS_UNDEFINED;
|
return JS_UNDEFINED;
|
||||||
}
|
}
|
||||||
xmlpp::Element *el = static_cast<xmlpp::Element *>(js_getopaque(this_val, js_element_class_id));
|
dom_node *el = (dom_node *)(js_getopaque(this_val, js_element_class_id));
|
||||||
|
void *res = NULL;
|
||||||
|
|
||||||
if (!el) {
|
struct ecmascript_interpreter *interpreter = (struct ecmascript_interpreter *)JS_GetContextOpaque(ctx);
|
||||||
|
struct document_view *doc_view = interpreter->vs->doc_view;
|
||||||
|
struct document *document = doc_view->document;
|
||||||
|
|
||||||
|
if (!document->dom) {
|
||||||
return JS_NULL;
|
return JS_NULL;
|
||||||
}
|
}
|
||||||
const char *str;
|
|
||||||
size_t len;
|
size_t len;
|
||||||
str = JS_ToCStringLen(ctx, &len, argv[0]);
|
const char *selector = JS_ToCStringLen(ctx, &len, argv[0]);
|
||||||
|
|
||||||
if (!str) {
|
if (!selector) {
|
||||||
return JS_EXCEPTION;
|
return JS_NULL;
|
||||||
}
|
}
|
||||||
xmlpp::ustring css = str;
|
dom_node *root = NULL; /* root element of document */
|
||||||
xmlpp::ustring xpath = css2xpath(css);
|
/* Get root element */
|
||||||
JS_FreeCString(ctx, str);
|
dom_exception exc = dom_document_get_document_element(document->dom, &root);
|
||||||
|
|
||||||
xmlpp::Node::NodeSet elements;
|
if (exc != DOM_NO_ERR || !root) {
|
||||||
|
JS_FreeCString(ctx, selector);
|
||||||
try {
|
|
||||||
elements = el->find(xpath);
|
|
||||||
} catch (xmlpp::exception &e) {
|
|
||||||
return JS_NULL;
|
return JS_NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (elements.size() == 0) {
|
while (el) {
|
||||||
return JS_NULL;
|
res = el_match_selector(selector, el);
|
||||||
}
|
|
||||||
|
|
||||||
while (el)
|
if (res) {
|
||||||
{
|
break;
|
||||||
for (auto node: elements)
|
|
||||||
{
|
|
||||||
if (isAncestor(el, node))
|
|
||||||
{
|
|
||||||
return getElement(ctx, node);
|
|
||||||
}
|
}
|
||||||
|
if (el == root) {
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
el = el->get_parent();
|
dom_node *node = NULL;
|
||||||
|
exc = dom_node_get_parent_node(el, &node);
|
||||||
|
if (exc != DOM_NO_ERR || !node) {
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
#endif
|
el = node;
|
||||||
|
}
|
||||||
|
JS_FreeCString(ctx, selector);
|
||||||
|
dom_node_unref(root);
|
||||||
|
|
||||||
|
if (!res) {
|
||||||
return JS_NULL;
|
return JS_NULL;
|
||||||
}
|
}
|
||||||
|
return getElement(ctx, res);
|
||||||
|
}
|
||||||
|
|
||||||
static JSValue
|
static JSValue
|
||||||
js_element_contains(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
|
js_element_contains(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
|
||||||
@ -2555,7 +2557,6 @@ js_element_getElementsByTagName(JSContext *ctx, JSValueConst this_val, int argc,
|
|||||||
return JS_NULL;
|
return JS_NULL;
|
||||||
}
|
}
|
||||||
JSValue rr = getNodeList(ctx, nlist);
|
JSValue rr = getNodeList(ctx, nlist);
|
||||||
JS_FreeValue(ctx, rr);
|
|
||||||
|
|
||||||
RETURN_JS(rr);
|
RETURN_JS(rr);
|
||||||
}
|
}
|
||||||
@ -2786,44 +2787,25 @@ js_element_matches(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst
|
|||||||
fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__);
|
fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__);
|
||||||
#endif
|
#endif
|
||||||
REF_JS(this_val);
|
REF_JS(this_val);
|
||||||
|
|
||||||
// TODO
|
|
||||||
#if 0
|
|
||||||
if (argc != 1) {
|
if (argc != 1) {
|
||||||
return JS_UNDEFINED;
|
return JS_UNDEFINED;
|
||||||
}
|
}
|
||||||
xmlpp::Element *el = static_cast<xmlpp::Element *>(js_getopaque(this_val, js_element_class_id));
|
dom_node *el = (dom_node *)(js_getopaque(this_val, js_element_class_id));
|
||||||
|
|
||||||
if (!el) {
|
if (!el) {
|
||||||
return JS_FALSE;
|
return JS_FALSE;
|
||||||
}
|
}
|
||||||
const char *str;
|
const char *selector;
|
||||||
size_t len;
|
size_t len;
|
||||||
str = JS_ToCStringLen(ctx, &len, argv[0]);
|
selector = JS_ToCStringLen(ctx, &len, argv[0]);
|
||||||
|
|
||||||
if (!str) {
|
if (!selector) {
|
||||||
return JS_EXCEPTION;
|
|
||||||
}
|
|
||||||
xmlpp::ustring css = str;
|
|
||||||
xmlpp::ustring xpath = css2xpath(css);
|
|
||||||
JS_FreeCString(ctx, str);
|
|
||||||
|
|
||||||
xmlpp::Node::NodeSet elements;
|
|
||||||
|
|
||||||
try {
|
|
||||||
elements = el->find(xpath);
|
|
||||||
} catch (xmlpp::exception &e) {
|
|
||||||
return JS_FALSE;
|
return JS_FALSE;
|
||||||
}
|
}
|
||||||
|
void *res = el_match_selector(selector, el);
|
||||||
|
JS_FreeCString(ctx, selector);
|
||||||
|
|
||||||
for (auto node: elements) {
|
return JS_NewBool(ctx, res);
|
||||||
if (node == el) {
|
|
||||||
return JS_TRUE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return JS_FALSE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static JSValue
|
static JSValue
|
||||||
@ -2834,45 +2816,31 @@ js_element_querySelector(JSContext *ctx, JSValueConst this_val, int argc, JSValu
|
|||||||
#endif
|
#endif
|
||||||
REF_JS(this_val);
|
REF_JS(this_val);
|
||||||
|
|
||||||
// TODO
|
|
||||||
#if 0
|
|
||||||
if (argc != 1) {
|
if (argc != 1) {
|
||||||
|
#ifdef ECMASCRIPT_DEBUG
|
||||||
|
fprintf(stderr, "%s:%s %d\n", __FILE__, __FUNCTION__, __LINE__);
|
||||||
|
#endif
|
||||||
return JS_UNDEFINED;
|
return JS_UNDEFINED;
|
||||||
}
|
}
|
||||||
xmlpp::Element *el = static_cast<xmlpp::Element *>(js_getopaque(this_val, js_element_class_id));
|
dom_node *el = (dom_node *)(js_getopaque(this_val, js_element_class_id));
|
||||||
|
|
||||||
if (!el) {
|
if (!el) {
|
||||||
return JS_FALSE;
|
return JS_NULL;
|
||||||
}
|
}
|
||||||
const char *str;
|
|
||||||
size_t len;
|
size_t len;
|
||||||
str = JS_ToCStringLen(ctx, &len, argv[0]);
|
const char *selector = JS_ToCStringLen(ctx, &len, argv[0]);
|
||||||
|
|
||||||
if (!str) {
|
if (!selector) {
|
||||||
return JS_EXCEPTION;
|
return JS_NULL;
|
||||||
}
|
}
|
||||||
xmlpp::ustring css = str;
|
void *ret = walk_tree_query(el, selector, 0);
|
||||||
xmlpp::ustring xpath = css2xpath(css);
|
JS_FreeCString(ctx, selector);
|
||||||
|
|
||||||
JS_FreeCString(ctx, str);
|
if (!ret) {
|
||||||
xmlpp::Node::NodeSet elements;
|
|
||||||
|
|
||||||
try {
|
|
||||||
elements = el->find(xpath);
|
|
||||||
} catch (xmlpp::exception &e) {
|
|
||||||
return JS_NULL;
|
return JS_NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto node: elements)
|
return getElement(ctx, ret);
|
||||||
{
|
|
||||||
if (isAncestor(el, node))
|
|
||||||
{
|
|
||||||
return getElement(ctx, node);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return JS_NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static JSValue
|
static JSValue
|
||||||
@ -2882,50 +2850,54 @@ js_element_querySelectorAll(JSContext *ctx, JSValueConst this_val, int argc, JSV
|
|||||||
fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__);
|
fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__);
|
||||||
#endif
|
#endif
|
||||||
REF_JS(this_val);
|
REF_JS(this_val);
|
||||||
// TODO
|
|
||||||
#if 0
|
|
||||||
if (argc != 1) {
|
if (argc != 1) {
|
||||||
return JS_FALSE;
|
return JS_FALSE;
|
||||||
}
|
}
|
||||||
xmlpp::Element *el = static_cast<xmlpp::Element *>(js_getopaque(this_val, js_element_class_id));
|
struct ecmascript_interpreter *interpreter = (struct ecmascript_interpreter *)JS_GetContextOpaque(ctx);
|
||||||
|
struct document_view *doc_view = interpreter->vs->doc_view;
|
||||||
|
struct document *document = doc_view->document;
|
||||||
|
|
||||||
if (!el) {
|
if (!document->dom) {
|
||||||
return JS_FALSE;
|
|
||||||
}
|
|
||||||
const char *str;
|
|
||||||
size_t len;
|
|
||||||
str = JS_ToCStringLen(ctx, &len, argv[0]);
|
|
||||||
|
|
||||||
if (!str) {
|
|
||||||
return JS_EXCEPTION;
|
|
||||||
}
|
|
||||||
xmlpp::ustring css = str;
|
|
||||||
xmlpp::ustring xpath = css2xpath(css);
|
|
||||||
JS_FreeCString(ctx, str);
|
|
||||||
|
|
||||||
xmlpp::Node::NodeSet elements;
|
|
||||||
xmlpp::Node::NodeSet *res = new(std::nothrow) xmlpp::Node::NodeSet;
|
|
||||||
|
|
||||||
if (!res) {
|
|
||||||
return JS_NULL;
|
return JS_NULL;
|
||||||
}
|
}
|
||||||
|
dom_node *el = (dom_node *)(js_getopaque(this_val, js_element_class_id));
|
||||||
|
|
||||||
try {
|
if (!el) {
|
||||||
elements = el->find(xpath);
|
return JS_NULL;
|
||||||
} catch (xmlpp::exception &e) {}
|
|
||||||
|
|
||||||
for (auto node: elements)
|
|
||||||
{
|
|
||||||
if (isAncestor(el, node)) {
|
|
||||||
res->push_back(node);
|
|
||||||
}
|
}
|
||||||
}
|
size_t len;
|
||||||
JSValue rr = getCollection(ctx, res);
|
const char *selector = JS_ToCStringLen(ctx, &len, argv[0]);
|
||||||
JS_FreeValue(ctx, rr);
|
|
||||||
|
|
||||||
RETURN_JS(rr);
|
if (!selector) {
|
||||||
#endif
|
return JS_NULL;
|
||||||
return JS_FALSE;
|
}
|
||||||
|
dom_string *tag_name = NULL;
|
||||||
|
dom_exception exc = dom_string_create((const uint8_t *)"B", 1, &tag_name);
|
||||||
|
|
||||||
|
if (exc != DOM_NO_ERR || !tag_name) {
|
||||||
|
JS_FreeCString(ctx, selector);
|
||||||
|
return JS_NULL;
|
||||||
|
}
|
||||||
|
dom_element *element = NULL;
|
||||||
|
exc = dom_document_create_element(document->dom, tag_name, &element);
|
||||||
|
dom_string_unref(tag_name);
|
||||||
|
|
||||||
|
if (exc != DOM_NO_ERR || !element) {
|
||||||
|
JS_FreeCString(ctx, selector);
|
||||||
|
return JS_NULL;
|
||||||
|
}
|
||||||
|
walk_tree_query_append((dom_node *)element, el, selector, 0);
|
||||||
|
JS_FreeCString(ctx, selector);
|
||||||
|
|
||||||
|
dom_nodelist *nodes = NULL;
|
||||||
|
exc = dom_node_get_child_nodes(element, &nodes);
|
||||||
|
dom_node_unref(element);
|
||||||
|
|
||||||
|
if (exc != DOM_NO_ERR || !nodes) {
|
||||||
|
return JS_NULL;
|
||||||
|
}
|
||||||
|
return getNodeList(ctx, nodes);
|
||||||
}
|
}
|
||||||
|
|
||||||
static JSValue
|
static JSValue
|
||||||
|
@ -1,3 +1,3 @@
|
|||||||
srcs += files('attr.c', 'attributes.c', 'collection.c', 'console.c', 'css.c', 'customevent.c', 'document.c', 'element.c', 'event.c', 'form.c', 'forms.c', 'heartbeat.c', 'history.c',
|
srcs += files('attr.c', 'attributes.c', 'collection.c', 'console.c', 'css.c', 'customevent.c', 'document.c', 'element.c', 'event.c', 'form.c', 'forms.c', 'heartbeat.c', 'history.c',
|
||||||
'implementation.c', 'input.c', 'keyboard.c', 'localstorage.c', 'location.c',
|
'implementation.c', 'input.c', 'keyboard.c', 'localstorage.c', 'location.c',
|
||||||
'mapa.c', 'message.c', 'navigator.c', 'nodelist.c', 'screen.c', 'style.c', 'unibar.c', 'window.c', 'xhr.c')
|
'mapa.c', 'message.c', 'navigator.c', 'nodelist.c', 'screen.c', 'style.c', 'unibar.c', 'url.c', 'window.c', 'xhr.c')
|
||||||
|
@ -24,6 +24,8 @@
|
|||||||
|
|
||||||
#define countof(x) (sizeof(x) / sizeof((x)[0]))
|
#define countof(x) (sizeof(x) / sizeof((x)[0]))
|
||||||
|
|
||||||
|
static JSClassID js_nodelist_class_id;
|
||||||
|
|
||||||
void *map_nodelist;
|
void *map_nodelist;
|
||||||
void *map_rev_nodelist;
|
void *map_rev_nodelist;
|
||||||
|
|
||||||
@ -50,6 +52,30 @@ js_nodeList_SetOpaque(JSValueConst this_val, void *node)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static JSValue
|
||||||
|
js_nodeList_get_property_length(JSContext *ctx, JSValueConst this_val)
|
||||||
|
{
|
||||||
|
#ifdef ECMASCRIPT_DEBUG
|
||||||
|
fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__);
|
||||||
|
#endif
|
||||||
|
REF_JS(this_val);
|
||||||
|
|
||||||
|
dom_nodelist *nl = (dom_nodelist *)(js_nodeList_GetOpaque(this_val));
|
||||||
|
dom_exception err;
|
||||||
|
uint32_t size;
|
||||||
|
|
||||||
|
if (!nl) {
|
||||||
|
return JS_NewInt32(ctx, 0);
|
||||||
|
}
|
||||||
|
err = dom_nodelist_get_length(nl, &size);
|
||||||
|
|
||||||
|
if (err != DOM_NO_ERR) {
|
||||||
|
return JS_NewInt32(ctx, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
return JS_NewInt32(ctx, size);
|
||||||
|
}
|
||||||
|
|
||||||
static JSValue
|
static JSValue
|
||||||
js_nodeList_item2(JSContext *ctx, JSValueConst this_val, int idx)
|
js_nodeList_item2(JSContext *ctx, JSValueConst this_val, int idx)
|
||||||
{
|
{
|
||||||
@ -146,24 +172,36 @@ js_nodeList_toString(JSContext *ctx, JSValueConst this_val, int argc, JSValueCon
|
|||||||
}
|
}
|
||||||
|
|
||||||
static const JSCFunctionListEntry js_nodeList_proto_funcs[] = {
|
static const JSCFunctionListEntry js_nodeList_proto_funcs[] = {
|
||||||
// JS_CGETSET_DEF("length", js_nodeList_get_property_length, nullptr),
|
// JS_CGETSET_DEF("length", js_nodeList_get_property_length, NULL),
|
||||||
JS_CFUNC_DEF("item", 1, js_nodeList_item),
|
JS_CFUNC_DEF("item", 1, js_nodeList_item),
|
||||||
JS_CFUNC_DEF("toString", 0, js_nodeList_toString)
|
JS_CFUNC_DEF("toString", 0, js_nodeList_toString)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static JSClassDef js_nodelist_class = {
|
||||||
|
"nodelist",
|
||||||
|
};
|
||||||
|
|
||||||
JSValue
|
JSValue
|
||||||
getNodeList(JSContext *ctx, void *node)
|
getNodeList(JSContext *ctx, void *node)
|
||||||
{
|
{
|
||||||
#ifdef ECMASCRIPT_DEBUG
|
#ifdef ECMASCRIPT_DEBUG
|
||||||
fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__);
|
fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__);
|
||||||
#endif
|
#endif
|
||||||
JSValue nodeList_obj = JS_NewArray(ctx);
|
JSValue proto;
|
||||||
JS_SetPropertyFunctionList(ctx, nodeList_obj, js_nodeList_proto_funcs, countof(js_nodeList_proto_funcs));
|
|
||||||
|
|
||||||
attr_save_in_map(map_nodelist, node, nodeList_obj);
|
/* nodelist class */
|
||||||
js_nodeList_SetOpaque(nodeList_obj, node);
|
JS_NewClassID(&js_nodelist_class_id);
|
||||||
js_nodeList_set_items(ctx, nodeList_obj, node);
|
JS_NewClass(JS_GetRuntime(ctx), js_nodelist_class_id, &js_nodelist_class);
|
||||||
JSValue rr = JS_DupValue(ctx, nodeList_obj);
|
proto = JS_NewArray(ctx);
|
||||||
|
REF_JS(proto);
|
||||||
|
|
||||||
|
JS_SetPropertyFunctionList(ctx, proto, js_nodeList_proto_funcs, countof(js_nodeList_proto_funcs));
|
||||||
|
JS_SetClassProto(ctx, js_nodelist_class_id, proto);
|
||||||
|
|
||||||
|
attr_save_in_map(map_nodelist, node, proto);
|
||||||
|
js_nodeList_SetOpaque(proto, node);
|
||||||
|
js_nodeList_set_items(ctx, proto, node);
|
||||||
|
|
||||||
|
JSValue rr = JS_DupValue(ctx, proto);
|
||||||
RETURN_JS(rr);
|
RETURN_JS(rr);
|
||||||
}
|
}
|
||||||
|
745
src/ecmascript/quickjs/url.c
Normal file
745
src/ecmascript/quickjs/url.c
Normal file
@ -0,0 +1,745 @@
|
|||||||
|
/* The QuickJS URL object implementation. */
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
#include "config.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "elinks.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/quickjs.h"
|
||||||
|
#include "ecmascript/quickjs/url.h"
|
||||||
|
#include "ecmascript/timer.h"
|
||||||
|
#include "intl/libintl.h"
|
||||||
|
#include "main/select.h"
|
||||||
|
#include "main/timer.h"
|
||||||
|
#include "network/connection.h"
|
||||||
|
#include "osdep/newwin.h"
|
||||||
|
#include "osdep/sysname.h"
|
||||||
|
#include "protocol/http/http.h"
|
||||||
|
#include "protocol/uri.h"
|
||||||
|
#include "session/download.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"
|
||||||
|
|
||||||
|
#define countof(x) (sizeof(x) / sizeof((x)[0]))
|
||||||
|
|
||||||
|
static JSClassID js_url_class_id;
|
||||||
|
|
||||||
|
struct eljs_url {
|
||||||
|
struct uri uri;
|
||||||
|
char *hash;
|
||||||
|
char *host;
|
||||||
|
char *pathname;
|
||||||
|
char *port;
|
||||||
|
char *protocol;
|
||||||
|
char *search;
|
||||||
|
};
|
||||||
|
|
||||||
|
static
|
||||||
|
void js_url_finalizer(JSRuntime *rt, JSValue val)
|
||||||
|
{
|
||||||
|
#ifdef ECMASCRIPT_DEBUG
|
||||||
|
fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__);
|
||||||
|
#endif
|
||||||
|
REF_JS(val);
|
||||||
|
|
||||||
|
struct eljs_url *url = (struct eljs_url *)JS_GetOpaque(val, js_url_class_id);
|
||||||
|
|
||||||
|
if (url) {
|
||||||
|
done_uri(&url->uri);
|
||||||
|
mem_free_if(url->hash);
|
||||||
|
mem_free_if(url->host);
|
||||||
|
mem_free_if(url->pathname);
|
||||||
|
mem_free_if(url->port);
|
||||||
|
mem_free_if(url->protocol);
|
||||||
|
mem_free_if(url->search);
|
||||||
|
mem_free(url);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static JSValue
|
||||||
|
js_url_get_property_hash(JSContext *ctx, JSValueConst this_val)
|
||||||
|
{
|
||||||
|
#ifdef ECMASCRIPT_DEBUG
|
||||||
|
fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__);
|
||||||
|
#endif
|
||||||
|
REF_JS(this_val);
|
||||||
|
|
||||||
|
struct eljs_url *url = (struct eljs_url *)(JS_GetOpaque(this_val, js_url_class_id));
|
||||||
|
|
||||||
|
if (!url) {
|
||||||
|
return JS_NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct string fragment;
|
||||||
|
if (!init_string(&fragment)) {
|
||||||
|
return JS_EXCEPTION;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (url->uri.fragmentlen) {
|
||||||
|
add_bytes_to_string(&fragment, url->uri.fragment, url->uri.fragmentlen);
|
||||||
|
}
|
||||||
|
|
||||||
|
JSValue ret = JS_NewStringLen(ctx, fragment.source, fragment.length);
|
||||||
|
done_string(&fragment);
|
||||||
|
|
||||||
|
RETURN_JS(ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
static JSValue
|
||||||
|
js_url_get_property_host(JSContext *ctx, JSValueConst this_val)
|
||||||
|
{
|
||||||
|
#ifdef ECMASCRIPT_DEBUG
|
||||||
|
fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__);
|
||||||
|
#endif
|
||||||
|
REF_JS(this_val);
|
||||||
|
|
||||||
|
struct eljs_url *url = (struct eljs_url *)(JS_GetOpaque(this_val, js_url_class_id));
|
||||||
|
|
||||||
|
if (!url) {
|
||||||
|
return JS_NULL;
|
||||||
|
}
|
||||||
|
char *str = get_uri_string(&url->uri, URI_HOST_PORT);
|
||||||
|
|
||||||
|
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_url_get_property_hostname(JSContext *ctx, JSValueConst this_val)
|
||||||
|
{
|
||||||
|
#ifdef ECMASCRIPT_DEBUG
|
||||||
|
fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__);
|
||||||
|
#endif
|
||||||
|
REF_JS(this_val);
|
||||||
|
|
||||||
|
struct eljs_url *url = (struct eljs_url *)(JS_GetOpaque(this_val, js_url_class_id));
|
||||||
|
|
||||||
|
if (!url) {
|
||||||
|
return JS_NULL;
|
||||||
|
}
|
||||||
|
char *str = get_uri_string(&url->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_url_get_property_href(JSContext *ctx, JSValueConst this_val)
|
||||||
|
{
|
||||||
|
#ifdef ECMASCRIPT_DEBUG
|
||||||
|
fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__);
|
||||||
|
#endif
|
||||||
|
REF_JS(this_val);
|
||||||
|
|
||||||
|
struct eljs_url *url = (struct eljs_url *)(JS_GetOpaque(this_val, js_url_class_id));
|
||||||
|
|
||||||
|
if (!url) {
|
||||||
|
return JS_NULL;
|
||||||
|
}
|
||||||
|
char *str = get_uri_string(&url->uri, URI_ORIGINAL);
|
||||||
|
|
||||||
|
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_url_get_property_origin(JSContext *ctx, JSValueConst this_val)
|
||||||
|
{
|
||||||
|
#ifdef ECMASCRIPT_DEBUG
|
||||||
|
fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__);
|
||||||
|
#endif
|
||||||
|
REF_JS(this_val);
|
||||||
|
|
||||||
|
struct eljs_url *url = (struct eljs_url *)(JS_GetOpaque(this_val, js_url_class_id));
|
||||||
|
|
||||||
|
if (!url) {
|
||||||
|
return JS_NULL;
|
||||||
|
}
|
||||||
|
char *str = get_uri_string(&url->uri, URI_SERVER);
|
||||||
|
|
||||||
|
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_url_get_property_pathname(JSContext *ctx, JSValueConst this_val)
|
||||||
|
{
|
||||||
|
#ifdef ECMASCRIPT_DEBUG
|
||||||
|
fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__);
|
||||||
|
#endif
|
||||||
|
REF_JS(this_val);
|
||||||
|
|
||||||
|
struct eljs_url *url = (struct eljs_url *)(JS_GetOpaque(this_val, js_url_class_id));
|
||||||
|
|
||||||
|
if (!url) {
|
||||||
|
return JS_NULL;
|
||||||
|
}
|
||||||
|
struct string pathname;
|
||||||
|
if (!init_string(&pathname)) {
|
||||||
|
return JS_NULL;
|
||||||
|
}
|
||||||
|
const char *query = (const char *)memchr(url->uri.data, '?', url->uri.datalen);
|
||||||
|
int len = (query ? query - url->uri.data : url->uri.datalen);
|
||||||
|
|
||||||
|
add_char_to_string(&pathname, '/');
|
||||||
|
add_bytes_to_string(&pathname, url->uri.data, len);
|
||||||
|
|
||||||
|
JSValue ret = JS_NewStringLen(ctx, pathname.source, pathname.length);
|
||||||
|
done_string(&pathname);
|
||||||
|
|
||||||
|
RETURN_JS(ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
static JSValue
|
||||||
|
js_url_get_property_port(JSContext *ctx, JSValueConst this_val)
|
||||||
|
{
|
||||||
|
#ifdef ECMASCRIPT_DEBUG
|
||||||
|
fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__);
|
||||||
|
#endif
|
||||||
|
REF_JS(this_val);
|
||||||
|
|
||||||
|
struct eljs_url *url = (struct eljs_url *)(JS_GetOpaque(this_val, js_url_class_id));
|
||||||
|
|
||||||
|
if (!url) {
|
||||||
|
return JS_NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct string port;
|
||||||
|
if (!init_string(&port)) {
|
||||||
|
return JS_NULL;
|
||||||
|
}
|
||||||
|
if (url->uri.portlen) {
|
||||||
|
add_bytes_to_string(&port, url->uri.port, url->uri.portlen);
|
||||||
|
}
|
||||||
|
JSValue ret = JS_NewStringLen(ctx, port.source, port.length);
|
||||||
|
done_string(&port);
|
||||||
|
|
||||||
|
RETURN_JS(ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
static JSValue
|
||||||
|
js_url_get_property_protocol(JSContext *ctx, JSValueConst this_val)
|
||||||
|
{
|
||||||
|
#ifdef ECMASCRIPT_DEBUG
|
||||||
|
fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__);
|
||||||
|
#endif
|
||||||
|
REF_JS(this_val);
|
||||||
|
|
||||||
|
struct eljs_url *url = (struct eljs_url *)(JS_GetOpaque(this_val, js_url_class_id));
|
||||||
|
|
||||||
|
if (!url) {
|
||||||
|
return JS_NULL;
|
||||||
|
}
|
||||||
|
struct string proto;
|
||||||
|
if (!init_string(&proto)) {
|
||||||
|
return JS_NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Custom or unknown keep the URI untouched. */
|
||||||
|
if (url->uri.protocol == PROTOCOL_UNKNOWN) {
|
||||||
|
add_to_string(&proto, struri(&url->uri));
|
||||||
|
} else {
|
||||||
|
add_bytes_to_string(&proto, url->uri.string, url->uri.protocollen);
|
||||||
|
add_char_to_string(&proto, ':');
|
||||||
|
}
|
||||||
|
JSValue ret = JS_NewStringLen(ctx, proto.source, proto.length);
|
||||||
|
done_string(&proto);
|
||||||
|
|
||||||
|
RETURN_JS(ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
static JSValue
|
||||||
|
js_url_get_property_search(JSContext *ctx, JSValueConst this_val)
|
||||||
|
{
|
||||||
|
#ifdef ECMASCRIPT_DEBUG
|
||||||
|
fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__);
|
||||||
|
#endif
|
||||||
|
REF_JS(this_val);
|
||||||
|
|
||||||
|
struct eljs_url *url = (struct eljs_url *)(JS_GetOpaque(this_val, js_url_class_id));
|
||||||
|
|
||||||
|
if (!url) {
|
||||||
|
return JS_NULL;
|
||||||
|
}
|
||||||
|
struct string search;
|
||||||
|
|
||||||
|
if (!init_string(&search)) {
|
||||||
|
return JS_NULL;
|
||||||
|
}
|
||||||
|
const char *query = (const char *)memchr(url->uri.data, '?', url->uri.datalen);
|
||||||
|
|
||||||
|
if (query) {
|
||||||
|
add_bytes_to_string(&search, query, strcspn(query, "#" POST_CHAR_S));
|
||||||
|
}
|
||||||
|
JSValue ret = JS_NewStringLen(ctx, search.source, search.length);
|
||||||
|
done_string(&search);
|
||||||
|
|
||||||
|
RETURN_JS(ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
static JSValue
|
||||||
|
js_url_set_property_hash(JSContext *ctx, JSValueConst this_val, JSValue val)
|
||||||
|
{
|
||||||
|
#ifdef ECMASCRIPT_DEBUG
|
||||||
|
fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__);
|
||||||
|
#endif
|
||||||
|
REF_JS(this_val);
|
||||||
|
|
||||||
|
struct eljs_url *url = (struct eljs_url *)(JS_GetOpaque(this_val, js_url_class_id));
|
||||||
|
|
||||||
|
if (!url) {
|
||||||
|
return JS_NULL;
|
||||||
|
}
|
||||||
|
size_t len;
|
||||||
|
const char *str = JS_ToCStringLen(ctx, &len, val);
|
||||||
|
|
||||||
|
if (!str) {
|
||||||
|
return JS_EXCEPTION;
|
||||||
|
}
|
||||||
|
char *hash = memacpy(str, len);
|
||||||
|
|
||||||
|
mem_free_set(&url->hash, hash);
|
||||||
|
|
||||||
|
if (hash) {
|
||||||
|
url->uri.fragment = hash;
|
||||||
|
url->uri.fragmentlen = len;
|
||||||
|
}
|
||||||
|
JS_FreeCString(ctx, str);
|
||||||
|
|
||||||
|
return JS_UNDEFINED;
|
||||||
|
}
|
||||||
|
|
||||||
|
static JSValue
|
||||||
|
js_url_set_property_host(JSContext *ctx, JSValueConst this_val, JSValue val)
|
||||||
|
{
|
||||||
|
#ifdef ECMASCRIPT_DEBUG
|
||||||
|
fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__);
|
||||||
|
#endif
|
||||||
|
REF_JS(this_val);
|
||||||
|
|
||||||
|
struct eljs_url *url = (struct eljs_url *)(JS_GetOpaque(this_val, js_url_class_id));
|
||||||
|
|
||||||
|
if (!url) {
|
||||||
|
return JS_NULL;
|
||||||
|
}
|
||||||
|
size_t len;
|
||||||
|
const char *str = JS_ToCStringLen(ctx, &len, val);
|
||||||
|
|
||||||
|
if (!str) {
|
||||||
|
return JS_EXCEPTION;
|
||||||
|
}
|
||||||
|
char *host = memacpy(str, len);
|
||||||
|
|
||||||
|
mem_free_set(&url->host, host);
|
||||||
|
|
||||||
|
if (host) {
|
||||||
|
url->uri.host = host;
|
||||||
|
url->uri.hostlen = len;
|
||||||
|
}
|
||||||
|
JS_FreeCString(ctx, str);
|
||||||
|
|
||||||
|
return JS_UNDEFINED;
|
||||||
|
}
|
||||||
|
|
||||||
|
static JSValue
|
||||||
|
js_url_set_property_hostname(JSContext *ctx, JSValueConst this_val, JSValue val)
|
||||||
|
{
|
||||||
|
#ifdef ECMASCRIPT_DEBUG
|
||||||
|
fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__);
|
||||||
|
#endif
|
||||||
|
REF_JS(this_val);
|
||||||
|
|
||||||
|
struct eljs_url *url = (struct eljs_url *)(JS_GetOpaque(this_val, js_url_class_id));
|
||||||
|
|
||||||
|
if (!url) {
|
||||||
|
return JS_NULL;
|
||||||
|
}
|
||||||
|
size_t len;
|
||||||
|
const char *str = JS_ToCStringLen(ctx, &len, val);
|
||||||
|
|
||||||
|
if (!str) {
|
||||||
|
return JS_EXCEPTION;
|
||||||
|
}
|
||||||
|
char *hostname = memacpy(str, len);
|
||||||
|
|
||||||
|
mem_free_set(&url->host, hostname);
|
||||||
|
|
||||||
|
if (hostname) {
|
||||||
|
url->uri.host = hostname;
|
||||||
|
url->uri.hostlen = len;
|
||||||
|
}
|
||||||
|
JS_FreeCString(ctx, str);
|
||||||
|
|
||||||
|
return JS_UNDEFINED;
|
||||||
|
}
|
||||||
|
|
||||||
|
static JSValue
|
||||||
|
js_url_set_property_href(JSContext *ctx, JSValueConst this_val, JSValue val)
|
||||||
|
{
|
||||||
|
#ifdef ECMASCRIPT_DEBUG
|
||||||
|
fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__);
|
||||||
|
#endif
|
||||||
|
REF_JS(this_val);
|
||||||
|
|
||||||
|
struct eljs_url *url = (struct eljs_url *)(JS_GetOpaque(this_val, js_url_class_id));
|
||||||
|
|
||||||
|
if (!url) {
|
||||||
|
return JS_NULL;
|
||||||
|
}
|
||||||
|
size_t len;
|
||||||
|
const char *str = JS_ToCStringLen(ctx, &len, val);
|
||||||
|
|
||||||
|
if (!str) {
|
||||||
|
return JS_EXCEPTION;
|
||||||
|
}
|
||||||
|
done_uri(&url->uri);
|
||||||
|
|
||||||
|
char *urlstring = memacpy(str, len);
|
||||||
|
JS_FreeCString(ctx, str);
|
||||||
|
|
||||||
|
if (!urlstring) {
|
||||||
|
return JS_EXCEPTION;
|
||||||
|
}
|
||||||
|
int ret = parse_uri(&url->uri, urlstring);
|
||||||
|
|
||||||
|
if (ret != URI_ERRNO_OK) {
|
||||||
|
return JS_EXCEPTION;
|
||||||
|
}
|
||||||
|
|
||||||
|
return JS_UNDEFINED;
|
||||||
|
}
|
||||||
|
|
||||||
|
static JSValue
|
||||||
|
js_url_set_property_pathname(JSContext *ctx, JSValueConst this_val, JSValue val)
|
||||||
|
{
|
||||||
|
#ifdef ECMASCRIPT_DEBUG
|
||||||
|
fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__);
|
||||||
|
#endif
|
||||||
|
REF_JS(this_val);
|
||||||
|
|
||||||
|
struct eljs_url *url = (struct eljs_url *)(JS_GetOpaque(this_val, js_url_class_id));
|
||||||
|
|
||||||
|
if (!url) {
|
||||||
|
return JS_NULL;
|
||||||
|
}
|
||||||
|
size_t len;
|
||||||
|
const char *str = JS_ToCStringLen(ctx, &len, val);
|
||||||
|
|
||||||
|
if (!str) {
|
||||||
|
return JS_EXCEPTION;
|
||||||
|
}
|
||||||
|
char *pathname = memacpy(str, len);
|
||||||
|
JS_FreeCString(ctx, str);
|
||||||
|
|
||||||
|
mem_free_set(&url->pathname, pathname);
|
||||||
|
|
||||||
|
if (pathname) {
|
||||||
|
url->uri.data = pathname;
|
||||||
|
url->uri.datalen = len;
|
||||||
|
}
|
||||||
|
return JS_UNDEFINED;
|
||||||
|
}
|
||||||
|
|
||||||
|
static JSValue
|
||||||
|
js_url_set_property_port(JSContext *ctx, JSValueConst this_val, JSValue val)
|
||||||
|
{
|
||||||
|
#ifdef ECMASCRIPT_DEBUG
|
||||||
|
fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__);
|
||||||
|
#endif
|
||||||
|
REF_JS(this_val);
|
||||||
|
|
||||||
|
struct eljs_url *url = (struct eljs_url *)(JS_GetOpaque(this_val, js_url_class_id));
|
||||||
|
|
||||||
|
if (!url) {
|
||||||
|
return JS_NULL;
|
||||||
|
}
|
||||||
|
size_t len;
|
||||||
|
const char *str = JS_ToCStringLen(ctx, &len, val);
|
||||||
|
|
||||||
|
if (!str) {
|
||||||
|
return JS_EXCEPTION;
|
||||||
|
}
|
||||||
|
char *port = memacpy(str, len);
|
||||||
|
JS_FreeCString(ctx, str);
|
||||||
|
|
||||||
|
mem_free_set(&url->port, port);
|
||||||
|
|
||||||
|
if (port) {
|
||||||
|
url->uri.port = port;
|
||||||
|
url->uri.portlen = strlen(port);
|
||||||
|
}
|
||||||
|
return JS_UNDEFINED;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int
|
||||||
|
get_protocol_length(const char *url)
|
||||||
|
{
|
||||||
|
char *end = (char *) url;
|
||||||
|
|
||||||
|
/* Seek the end of the protocol name if any. */
|
||||||
|
/* RFC1738:
|
||||||
|
* scheme = 1*[ lowalpha | digit | "+" | "-" | "." ]
|
||||||
|
* (but per its recommendations we accept "upalpha" too) */
|
||||||
|
while (isalnum(*end) || *end == '+' || *end == '-' || *end == '.')
|
||||||
|
end++;
|
||||||
|
|
||||||
|
/* Now we make something to support our "IP version in protocol scheme
|
||||||
|
* name" hack and silently chop off the last digit if it's there. The
|
||||||
|
* IETF's not gonna notice I hope or it'd be going after us hard. */
|
||||||
|
if (end != url && isdigit(end[-1]))
|
||||||
|
end--;
|
||||||
|
|
||||||
|
/* Also return 0 if there's no protocol name (@end == @url). */
|
||||||
|
return (*end == ':' || isdigit(*end)) ? end - url : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static JSValue
|
||||||
|
js_url_set_property_protocol(JSContext *ctx, JSValueConst this_val, JSValue val)
|
||||||
|
{
|
||||||
|
#ifdef ECMASCRIPT_DEBUG
|
||||||
|
fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__);
|
||||||
|
#endif
|
||||||
|
REF_JS(this_val);
|
||||||
|
|
||||||
|
struct eljs_url *url = (struct eljs_url *)(JS_GetOpaque(this_val, js_url_class_id));
|
||||||
|
|
||||||
|
if (!url) {
|
||||||
|
return JS_NULL;
|
||||||
|
}
|
||||||
|
size_t len;
|
||||||
|
const char *str = JS_ToCStringLen(ctx, &len, val);
|
||||||
|
|
||||||
|
if (!str) {
|
||||||
|
return JS_EXCEPTION;
|
||||||
|
}
|
||||||
|
char *protocol = memacpy(str, len);
|
||||||
|
JS_FreeCString(ctx, str);
|
||||||
|
|
||||||
|
mem_free_set(&url->protocol, protocol);
|
||||||
|
|
||||||
|
if (protocol) {
|
||||||
|
url->uri.protocollen = get_protocol_length(protocol);
|
||||||
|
/* Figure out whether the protocol is known */
|
||||||
|
url->uri.protocol = get_protocol(protocol, url->uri.protocollen);
|
||||||
|
}
|
||||||
|
|
||||||
|
return JS_UNDEFINED;
|
||||||
|
}
|
||||||
|
|
||||||
|
static JSValue
|
||||||
|
js_url_set_property_search(JSContext *ctx, JSValueConst this_val, JSValue val)
|
||||||
|
{
|
||||||
|
#ifdef ECMASCRIPT_DEBUG
|
||||||
|
fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__);
|
||||||
|
#endif
|
||||||
|
REF_JS(this_val);
|
||||||
|
|
||||||
|
struct eljs_url *url = (struct eljs_url *)(JS_GetOpaque(this_val, js_url_class_id));
|
||||||
|
|
||||||
|
if (!url) {
|
||||||
|
return JS_NULL;
|
||||||
|
}
|
||||||
|
size_t len;
|
||||||
|
const char *str = JS_ToCStringLen(ctx, &len, val);
|
||||||
|
|
||||||
|
if (!str) {
|
||||||
|
return JS_EXCEPTION;
|
||||||
|
}
|
||||||
|
char *search = memacpy(str, len);
|
||||||
|
JS_FreeCString(ctx, str);
|
||||||
|
|
||||||
|
mem_free_set(&url->search, search);
|
||||||
|
|
||||||
|
if (search) {
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
return JS_UNDEFINED;
|
||||||
|
}
|
||||||
|
|
||||||
|
static JSValue
|
||||||
|
js_url_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_url_get_property_href(ctx, this_val);
|
||||||
|
}
|
||||||
|
|
||||||
|
static JSClassDef js_url_class = {
|
||||||
|
"URL",
|
||||||
|
js_url_finalizer
|
||||||
|
};
|
||||||
|
|
||||||
|
static const JSCFunctionListEntry js_url_proto_funcs[] = {
|
||||||
|
JS_CGETSET_DEF("hash", js_url_get_property_hash, js_url_set_property_hash),
|
||||||
|
JS_CGETSET_DEF("host", js_url_get_property_host, js_url_set_property_host),
|
||||||
|
JS_CGETSET_DEF("hostname", js_url_get_property_hostname, js_url_set_property_hostname),
|
||||||
|
JS_CGETSET_DEF("href", js_url_get_property_href, js_url_set_property_href),
|
||||||
|
JS_CGETSET_DEF("origin", js_url_get_property_origin, NULL),
|
||||||
|
JS_CGETSET_DEF("pathname", js_url_get_property_pathname, js_url_set_property_pathname),
|
||||||
|
JS_CGETSET_DEF("port", js_url_get_property_port, js_url_set_property_port),
|
||||||
|
JS_CGETSET_DEF("protocol", js_url_get_property_protocol, js_url_set_property_protocol),
|
||||||
|
JS_CGETSET_DEF("search", js_url_get_property_search, js_url_set_property_search),
|
||||||
|
JS_CFUNC_DEF("toString", 0, js_url_toString),
|
||||||
|
};
|
||||||
|
|
||||||
|
static JSValue
|
||||||
|
js_url_constructor(JSContext *ctx, JSValueConst new_target, int argc, JSValueConst *argv)
|
||||||
|
{
|
||||||
|
#ifdef ECMASCRIPT_DEBUG
|
||||||
|
fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__);
|
||||||
|
#endif
|
||||||
|
REF_JS(new_target);
|
||||||
|
|
||||||
|
JSValue obj = JS_NewObjectClass(ctx, js_url_class_id);
|
||||||
|
REF_JS(obj);
|
||||||
|
|
||||||
|
if (JS_IsException(obj)) {
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
struct eljs_url *url = (struct eljs_url *)mem_calloc(1, sizeof(*url));
|
||||||
|
|
||||||
|
if (!url) {
|
||||||
|
JS_FreeValue(ctx, obj);
|
||||||
|
return JS_EXCEPTION;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (argc > 0) {
|
||||||
|
const char *str;
|
||||||
|
size_t len;
|
||||||
|
|
||||||
|
str = JS_ToCStringLen(ctx, &len, argv[0]);
|
||||||
|
|
||||||
|
if (!str) {
|
||||||
|
JS_FreeValue(ctx, obj);
|
||||||
|
return JS_EXCEPTION;
|
||||||
|
}
|
||||||
|
char *urlstring = memacpy(str, len);
|
||||||
|
JS_FreeCString(ctx, str);
|
||||||
|
|
||||||
|
if (!urlstring) {
|
||||||
|
return JS_EXCEPTION;
|
||||||
|
}
|
||||||
|
int ret = parse_uri(&url->uri, urlstring);
|
||||||
|
|
||||||
|
if (ret != URI_ERRNO_OK) {
|
||||||
|
JS_FreeValue(ctx, obj);
|
||||||
|
return JS_EXCEPTION;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
JS_SetOpaque(obj, url);
|
||||||
|
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
JS_NewGlobalCConstructor2(JSContext *ctx, JSValue func_obj, const char *name, JSValueConst proto)
|
||||||
|
{
|
||||||
|
REF_JS(func_obj);
|
||||||
|
REF_JS(proto);
|
||||||
|
|
||||||
|
JSValue global_object = JS_GetGlobalObject(ctx);
|
||||||
|
|
||||||
|
JS_DefinePropertyValueStr(ctx, global_object, name,
|
||||||
|
JS_DupValue(ctx, func_obj), JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE);
|
||||||
|
JS_SetConstructor(ctx, func_obj, proto);
|
||||||
|
JS_FreeValue(ctx, func_obj);
|
||||||
|
JS_FreeValue(ctx, global_object);
|
||||||
|
}
|
||||||
|
|
||||||
|
static JSValueConst
|
||||||
|
JS_NewGlobalCConstructor(JSContext *ctx, const char *name, JSCFunction *func, int length, JSValueConst proto)
|
||||||
|
{
|
||||||
|
JSValue func_obj;
|
||||||
|
func_obj = JS_NewCFunction2(ctx, func, name, length, JS_CFUNC_constructor_or_func, 0);
|
||||||
|
REF_JS(func_obj);
|
||||||
|
REF_JS(proto);
|
||||||
|
|
||||||
|
JS_NewGlobalCConstructor2(ctx, func_obj, name, proto);
|
||||||
|
|
||||||
|
return func_obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
js_url_init(JSContext *ctx)
|
||||||
|
{
|
||||||
|
#ifdef ECMASCRIPT_DEBUG
|
||||||
|
fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__);
|
||||||
|
#endif
|
||||||
|
JSValue proto, obj;
|
||||||
|
|
||||||
|
/* url class */
|
||||||
|
JS_NewClassID(&js_url_class_id);
|
||||||
|
JS_NewClass(JS_GetRuntime(ctx), js_url_class_id, &js_url_class);
|
||||||
|
proto = JS_NewObject(ctx);
|
||||||
|
REF_JS(proto);
|
||||||
|
|
||||||
|
JS_SetPropertyFunctionList(ctx, proto, js_url_proto_funcs, countof(js_url_proto_funcs));
|
||||||
|
JS_SetClassProto(ctx, js_url_class_id, proto);
|
||||||
|
|
||||||
|
/* url object */
|
||||||
|
obj = JS_NewGlobalCConstructor(ctx, "URL", js_url_constructor, 1, proto);
|
||||||
|
REF_JS(obj);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
16
src/ecmascript/quickjs/url.h
Normal file
16
src/ecmascript/quickjs/url.h
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
#ifndef EL__ECMASCRIPT_QUICKJS_URL_H
|
||||||
|
#define EL__ECMASCRIPT_QUICKJS_URL_H
|
||||||
|
|
||||||
|
#include <quickjs/quickjs.h>
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int js_url_init(JSContext *ctx);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
@ -28,6 +28,7 @@
|
|||||||
#include "document/view.h"
|
#include "document/view.h"
|
||||||
#include "ecmascript/css2xpath.h"
|
#include "ecmascript/css2xpath.h"
|
||||||
#include "ecmascript/ecmascript.h"
|
#include "ecmascript/ecmascript.h"
|
||||||
|
#include "ecmascript/ecmascript-c.h"
|
||||||
#include "ecmascript/libdom/parse.h"
|
#include "ecmascript/libdom/parse.h"
|
||||||
#include "ecmascript/spidermonkey/collection.h"
|
#include "ecmascript/spidermonkey/collection.h"
|
||||||
#include "ecmascript/spidermonkey/form.h"
|
#include "ecmascript/spidermonkey/form.h"
|
||||||
@ -1561,7 +1562,7 @@ document_createElement(JSContext *ctx, unsigned int argc, JS::Value *vp)
|
|||||||
args.rval().setBoolean(false);
|
args.rval().setBoolean(false);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
// TODO
|
|
||||||
JS::Realm *comp = js::GetContextRealm(ctx);
|
JS::Realm *comp = js::GetContextRealm(ctx);
|
||||||
struct ecmascript_interpreter *interpreter = (struct ecmascript_interpreter *)JS::GetRealmPrivate(comp);
|
struct ecmascript_interpreter *interpreter = (struct ecmascript_interpreter *)JS::GetRealmPrivate(comp);
|
||||||
struct document_view *doc_view = interpreter->vs->doc_view;
|
struct document_view *doc_view = interpreter->vs->doc_view;
|
||||||
@ -1841,8 +1842,31 @@ document_querySelector(JSContext *ctx, unsigned int argc, JS::Value *vp)
|
|||||||
args.rval().setNull();
|
args.rval().setNull();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
// TODO
|
dom_node *root = NULL; /* root element of document */
|
||||||
|
/* Get root element */
|
||||||
|
dom_exception exc = dom_document_get_document_element(document->dom, &root);
|
||||||
|
|
||||||
|
if (exc != DOM_NO_ERR) {
|
||||||
args.rval().setNull();
|
args.rval().setNull();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
char *selector = jsval_to_string(ctx, args[0]);
|
||||||
|
|
||||||
|
if (!selector) {
|
||||||
|
dom_node_unref(root);
|
||||||
|
args.rval().setNull();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
void *ret = walk_tree_query(root, selector, 0);
|
||||||
|
mem_free(selector);
|
||||||
|
dom_node_unref(root);
|
||||||
|
|
||||||
|
if (!ret) {
|
||||||
|
args.rval().setNull();
|
||||||
|
} else {
|
||||||
|
JSObject *el = getElement(ctx, ret);
|
||||||
|
args.rval().setObject(*el);
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -1859,7 +1883,6 @@ document_querySelectorAll(JSContext *ctx, unsigned int argc, JS::Value *vp)
|
|||||||
args.rval().setBoolean(false);
|
args.rval().setBoolean(false);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
JS::Realm *comp = js::GetContextRealm(ctx);
|
JS::Realm *comp = js::GetContextRealm(ctx);
|
||||||
struct ecmascript_interpreter *interpreter = (struct ecmascript_interpreter *)JS::GetRealmPrivate(comp);
|
struct ecmascript_interpreter *interpreter = (struct ecmascript_interpreter *)JS::GetRealmPrivate(comp);
|
||||||
struct document_view *doc_view = interpreter->vs->doc_view;
|
struct document_view *doc_view = interpreter->vs->doc_view;
|
||||||
@ -1869,8 +1892,55 @@ document_querySelectorAll(JSContext *ctx, unsigned int argc, JS::Value *vp)
|
|||||||
args.rval().setNull();
|
args.rval().setNull();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
// TODO
|
dom_node *doc_root = NULL; /* root element of document */
|
||||||
|
/* Get root element */
|
||||||
|
dom_exception exc = dom_document_get_document_element(document->dom, &doc_root);
|
||||||
|
|
||||||
|
if (exc != DOM_NO_ERR) {
|
||||||
args.rval().setNull();
|
args.rval().setNull();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
char *selector = jsval_to_string(ctx, args[0]);
|
||||||
|
|
||||||
|
if (!selector) {
|
||||||
|
dom_node_unref(doc_root);
|
||||||
|
args.rval().setNull();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
dom_string *tag_name = NULL;
|
||||||
|
exc = dom_string_create((const uint8_t *)"B", 1, &tag_name);
|
||||||
|
|
||||||
|
if (exc != DOM_NO_ERR || !tag_name) {
|
||||||
|
dom_node_unref(doc_root);
|
||||||
|
mem_free(selector);
|
||||||
|
args.rval().setNull();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
dom_element *element = NULL;
|
||||||
|
exc = dom_document_create_element(document->dom, tag_name, &element);
|
||||||
|
dom_string_unref(tag_name);
|
||||||
|
|
||||||
|
if (exc != DOM_NO_ERR || !element) {
|
||||||
|
dom_node_unref(doc_root);
|
||||||
|
mem_free(selector);
|
||||||
|
args.rval().setNull();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
walk_tree_query_append((dom_node *)element, doc_root, selector, 0);
|
||||||
|
dom_node_unref(doc_root);
|
||||||
|
mem_free(selector);
|
||||||
|
|
||||||
|
dom_nodelist *nodes = NULL;
|
||||||
|
exc = dom_node_get_child_nodes(element, &nodes);
|
||||||
|
dom_node_unref(element);
|
||||||
|
|
||||||
|
if (exc != DOM_NO_ERR || !nodes) {
|
||||||
|
args.rval().setNull();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
JSObject *obj = getNodeList(ctx, nodes);
|
||||||
|
args.rval().setObject(*obj);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -24,10 +24,12 @@
|
|||||||
#include "document/document.h"
|
#include "document/document.h"
|
||||||
#include "document/forms.h"
|
#include "document/forms.h"
|
||||||
#include "document/libdom/corestrings.h"
|
#include "document/libdom/corestrings.h"
|
||||||
|
#include "document/libdom/doc.h"
|
||||||
#include "document/libdom/mapa.h"
|
#include "document/libdom/mapa.h"
|
||||||
#include "document/libdom/renderer2.h"
|
#include "document/libdom/renderer2.h"
|
||||||
#include "document/view.h"
|
#include "document/view.h"
|
||||||
#include "ecmascript/ecmascript.h"
|
#include "ecmascript/ecmascript.h"
|
||||||
|
#include "ecmascript/ecmascript-c.h"
|
||||||
#include "ecmascript/spidermonkey/attr.h"
|
#include "ecmascript/spidermonkey/attr.h"
|
||||||
#include "ecmascript/spidermonkey/attributes.h"
|
#include "ecmascript/spidermonkey/attributes.h"
|
||||||
#include "ecmascript/spidermonkey/collection.h"
|
#include "ecmascript/spidermonkey/collection.h"
|
||||||
@ -4023,56 +4025,59 @@ element_closest(JSContext *ctx, unsigned int argc, JS::Value *vp)
|
|||||||
#endif
|
#endif
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
char *selector = jsval_to_string(ctx, args[0]);
|
||||||
// TODO
|
if (!selector) {
|
||||||
#if 0
|
|
||||||
xmlpp::Element *el = JS::GetMaybePtrFromReservedSlot<xmlpp::Element>(hobj, 0);
|
|
||||||
|
|
||||||
if (!el) {
|
|
||||||
args.rval().setNull();
|
args.rval().setNull();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct string cssstr;
|
dom_node *el = (dom_node *)JS::GetMaybePtrFromReservedSlot<dom_node>(hobj, 0);
|
||||||
if (!init_string(&cssstr)) {
|
void *res = NULL;
|
||||||
return false;
|
|
||||||
}
|
|
||||||
jshandle_value_to_char_string(&cssstr, ctx, args[0]);
|
|
||||||
xmlpp::ustring css = cssstr.source;
|
|
||||||
xmlpp::ustring xpath = css2xpath(css);
|
|
||||||
done_string(&cssstr);
|
|
||||||
|
|
||||||
xmlpp::Node::NodeSet elements;
|
JS::Realm *comp = js::GetContextRealm(ctx);
|
||||||
|
struct ecmascript_interpreter *interpreter = (struct ecmascript_interpreter *)JS::GetRealmPrivate(comp);
|
||||||
|
struct document_view *doc_view = interpreter->vs->doc_view;
|
||||||
|
struct document *document = doc_view->document;
|
||||||
|
|
||||||
try {
|
if (!document->dom) {
|
||||||
elements = el->find(xpath);
|
|
||||||
} catch (xmlpp::exception &e) {
|
|
||||||
args.rval().setNull();
|
args.rval().setNull();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
dom_node *root = NULL; /* root element of document */
|
||||||
|
/* Get root element */
|
||||||
|
dom_exception exc = dom_document_get_document_element(document->dom, &root);
|
||||||
|
|
||||||
if (elements.size() == 0) {
|
if (exc != DOM_NO_ERR || !root) {
|
||||||
args.rval().setNull();
|
args.rval().setNull();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
while (el)
|
while (el) {
|
||||||
{
|
res = el_match_selector(selector, el);
|
||||||
for (auto node: elements)
|
|
||||||
{
|
|
||||||
if (isAncestor(el, static_cast<xmlpp::Element *>(node)))
|
|
||||||
{
|
|
||||||
JSObject *elem = getElement(ctx, node);
|
|
||||||
args.rval().setObject(*elem);
|
|
||||||
|
|
||||||
|
if (res) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (el == root) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
dom_node *node = NULL;
|
||||||
|
exc = dom_node_get_parent_node(el, &node);
|
||||||
|
if (exc != DOM_NO_ERR || !node) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
el = node;
|
||||||
|
}
|
||||||
|
mem_free(selector);
|
||||||
|
dom_node_unref(root);
|
||||||
|
|
||||||
|
if (!res) {
|
||||||
|
args.rval().setNull();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
JSObject *ret = getElement(ctx, res);
|
||||||
el = el->get_parent();
|
args.rval().setObject(*ret);
|
||||||
}
|
|
||||||
args.rval().setNull();
|
|
||||||
#endif
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4676,44 +4681,24 @@ element_matches(JSContext *ctx, unsigned int argc, JS::Value *vp)
|
|||||||
#endif
|
#endif
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
dom_node *el = (dom_node *)JS::GetMaybePtrFromReservedSlot<dom_node>(hobj, 0);
|
||||||
// TODO
|
|
||||||
#if 0
|
|
||||||
xmlpp::Element *el = JS::GetMaybePtrFromReservedSlot<xmlpp::Element>(hobj, 0);
|
|
||||||
|
|
||||||
if (!el) {
|
if (!el) {
|
||||||
args.rval().setBoolean(false);
|
args.rval().setBoolean(false);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
char *selector = jsval_to_string(ctx, args[0]);
|
||||||
|
|
||||||
struct string cssstr;
|
if (!selector) {
|
||||||
if (!init_string(&cssstr)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
jshandle_value_to_char_string(&cssstr, ctx, args[0]);
|
|
||||||
xmlpp::ustring css = cssstr.source;
|
|
||||||
xmlpp::ustring xpath = css2xpath(css);
|
|
||||||
done_string(&cssstr);
|
|
||||||
|
|
||||||
xmlpp::Node::NodeSet elements;
|
|
||||||
|
|
||||||
try {
|
|
||||||
elements = el->find(xpath);
|
|
||||||
} catch (xmlpp::exception &e) {
|
|
||||||
args.rval().setBoolean(false);
|
args.rval().setBoolean(false);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
for (auto node: elements) {
|
void *res = el_match_selector(selector, el);
|
||||||
if (node == el) {
|
mem_free(selector);
|
||||||
args.rval().setBoolean(true);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
args.rval().setBoolean(false);
|
|
||||||
#endif
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
args.rval().setBoolean(res);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
element_querySelector(JSContext *ctx, unsigned int argc, JS::Value *vp)
|
element_querySelector(JSContext *ctx, unsigned int argc, JS::Value *vp)
|
||||||
@ -4735,48 +4720,28 @@ element_querySelector(JSContext *ctx, unsigned int argc, JS::Value *vp)
|
|||||||
#endif
|
#endif
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
dom_node *el = (dom_node *)JS::GetMaybePtrFromReservedSlot<dom_node>(hobj, 0);
|
||||||
// TODO
|
|
||||||
#if 0
|
|
||||||
xmlpp::Element *el = JS::GetMaybePtrFromReservedSlot<xmlpp::Element>(hobj, 0);
|
|
||||||
|
|
||||||
if (!el) {
|
if (!el) {
|
||||||
args.rval().setBoolean(false);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct string cssstr;
|
|
||||||
if (!init_string(&cssstr)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
jshandle_value_to_char_string(&cssstr, ctx, args[0]);
|
|
||||||
xmlpp::ustring css = cssstr.source;
|
|
||||||
xmlpp::ustring xpath = css2xpath(css);
|
|
||||||
done_string(&cssstr);
|
|
||||||
|
|
||||||
xmlpp::Node::NodeSet elements;
|
|
||||||
|
|
||||||
try {
|
|
||||||
elements = el->find(xpath);
|
|
||||||
} catch (xmlpp::exception &e) {
|
|
||||||
args.rval().setNull();
|
args.rval().setNull();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
char *selector = jsval_to_string(ctx, args[0]);
|
||||||
|
|
||||||
for (auto node: elements)
|
if (!selector) {
|
||||||
{
|
args.rval().setNull();
|
||||||
if (isAncestor(el, static_cast<xmlpp::Element *>(node)))
|
|
||||||
{
|
|
||||||
JSObject *elem = getElement(ctx, node);
|
|
||||||
|
|
||||||
if (elem) {
|
|
||||||
args.rval().setObject(*elem);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
void *ret = walk_tree_query(el, selector, 0);
|
||||||
}
|
mem_free(selector);
|
||||||
|
|
||||||
|
if (!ret) {
|
||||||
args.rval().setNull();
|
args.rval().setNull();
|
||||||
#endif
|
} else {
|
||||||
|
JSObject *el = getElement(ctx, ret);
|
||||||
|
args.rval().setObject(*el);
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4800,50 +4765,58 @@ element_querySelectorAll(JSContext *ctx, unsigned int argc, JS::Value *vp)
|
|||||||
#endif
|
#endif
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
// TODO
|
JS::Realm *comp = js::GetContextRealm(ctx);
|
||||||
#if 0
|
struct ecmascript_interpreter *interpreter = (struct ecmascript_interpreter *)JS::GetRealmPrivate(comp);
|
||||||
xmlpp::Element *el = JS::GetMaybePtrFromReservedSlot<xmlpp::Element>(hobj, 0);
|
struct document_view *doc_view = interpreter->vs->doc_view;
|
||||||
|
struct document *document = doc_view->document;
|
||||||
|
|
||||||
if (!el) {
|
if (!document->dom) {
|
||||||
args.rval().setBoolean(false);
|
args.rval().setNull();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
dom_node *el = (dom_node *)JS::GetMaybePtrFromReservedSlot<dom_node>(hobj, 0);
|
||||||
|
|
||||||
struct string cssstr;
|
if (!el) {
|
||||||
|
|
||||||
if (!init_string(&cssstr)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
jshandle_value_to_char_string(&cssstr, ctx, args[0]);
|
|
||||||
xmlpp::ustring css = cssstr.source;
|
|
||||||
xmlpp::ustring xpath = css2xpath(css);
|
|
||||||
done_string(&cssstr);
|
|
||||||
xmlpp::Node::NodeSet *res = new(std::nothrow) xmlpp::Node::NodeSet;
|
|
||||||
|
|
||||||
if (!res) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
xmlpp::Node::NodeSet elements;
|
|
||||||
|
|
||||||
try {
|
|
||||||
elements = el->find(xpath);
|
|
||||||
} catch (xmlpp::exception &e) {}
|
|
||||||
|
|
||||||
for (auto node : elements)
|
|
||||||
{
|
|
||||||
if (isAncestor(el, static_cast<xmlpp::Element *>(node))) {
|
|
||||||
res->push_back(node);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
JSObject *elem = getCollection(ctx, res);
|
|
||||||
|
|
||||||
if (elem) {
|
|
||||||
args.rval().setObject(*elem);
|
|
||||||
} else {
|
|
||||||
args.rval().setNull();
|
args.rval().setNull();
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
#endif
|
char *selector = jsval_to_string(ctx, args[0]);
|
||||||
|
|
||||||
|
if (!selector) {
|
||||||
|
args.rval().setNull();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
dom_string *tag_name = NULL;
|
||||||
|
dom_exception exc = dom_string_create((const uint8_t *)"B", 1, &tag_name);
|
||||||
|
|
||||||
|
if (exc != DOM_NO_ERR || !tag_name) {
|
||||||
|
mem_free(selector);
|
||||||
|
args.rval().setNull();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
dom_element *element = NULL;
|
||||||
|
exc = dom_document_create_element(document->dom, tag_name, &element);
|
||||||
|
dom_string_unref(tag_name);
|
||||||
|
|
||||||
|
if (exc != DOM_NO_ERR || !element) {
|
||||||
|
mem_free(selector);
|
||||||
|
args.rval().setNull();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
walk_tree_query_append((dom_node *)element, el, selector, 0);
|
||||||
|
mem_free(selector);
|
||||||
|
|
||||||
|
dom_nodelist *nodes = NULL;
|
||||||
|
exc = dom_node_get_child_nodes(element, &nodes);
|
||||||
|
dom_node_unref(element);
|
||||||
|
|
||||||
|
if (exc != DOM_NO_ERR || !nodes) {
|
||||||
|
args.rval().setNull();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
JSObject *obj = getNodeList(ctx, nodes);
|
||||||
|
args.rval().setObject(*obj);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -82,7 +82,7 @@ JSClassOps nodeList_ops = {
|
|||||||
|
|
||||||
JSClass nodeList_class = {
|
JSClass nodeList_class = {
|
||||||
"nodeList",
|
"nodeList",
|
||||||
JSCLASS_HAS_RESERVED_SLOTS(1),
|
JSCLASS_HAS_RESERVED_SLOTS(1) | JSCLASS_HAS_CACHED_PROTO(JSProto_Array),
|
||||||
&nodeList_ops
|
&nodeList_ops
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -506,7 +506,7 @@ int
|
|||||||
init_interlink(void)
|
init_interlink(void)
|
||||||
{
|
{
|
||||||
int pipefds[2];
|
int pipefds[2];
|
||||||
char trigger;
|
char trigger = 0;
|
||||||
ssize_t n;
|
ssize_t n;
|
||||||
int fd = connect_to_af_unix();
|
int fd = connect_to_af_unix();
|
||||||
|
|
||||||
|
24
test/ecmascript/assert/document.querySelector.html
Normal file
24
test/ecmascript/assert/document.querySelector.html
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<body>
|
||||||
|
<p class="a">Class a.</p>
|
||||||
|
<p class="b">Class b.</p>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
function myFunction() {
|
||||||
|
var x = document.querySelector('.nonexistent');
|
||||||
|
console.assert(x === null, 'nonexistent element');
|
||||||
|
|
||||||
|
var y = document.querySelector('.b');
|
||||||
|
console.assert(!(y === null), 'Class b');
|
||||||
|
var inp = y.innerHTML;
|
||||||
|
console.assert(inp === 'Class b.', 'Class b.');
|
||||||
|
}
|
||||||
|
|
||||||
|
console.error('document.querySelector.html');
|
||||||
|
myFunction();
|
||||||
|
console.exit(0);
|
||||||
|
</script>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
22
test/ecmascript/assert/document.querySelectorAll.html
Normal file
22
test/ecmascript/assert/document.querySelectorAll.html
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<body>
|
||||||
|
<p class="a">Class a.</p>
|
||||||
|
<p class="b">Class b.</p>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
function myFunction() {
|
||||||
|
var x = document.querySelectorAll('.nonexistent');
|
||||||
|
console.assert(x.length === 0, 'nonexistent elements');
|
||||||
|
|
||||||
|
var y = document.querySelectorAll('p');
|
||||||
|
console.assert(y.length == 2, 'Two p');
|
||||||
|
}
|
||||||
|
|
||||||
|
console.error('document.querySelectorAll.html');
|
||||||
|
myFunction();
|
||||||
|
console.exit(0);
|
||||||
|
</script>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
@ -10,11 +10,16 @@
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
var element = document.getElementById("myElement");
|
var element = document.getElementById("myElement");
|
||||||
var closest = element.closest(".container");
|
var closes2 = element.closest("div.container");
|
||||||
|
|
||||||
console.error('element.closest.html');
|
console.error('element.closest.html');
|
||||||
console.assert(closest.outerHTML === '<DIV class="demo container">Parent\n <DIV id="myElement" class="demo">The outer HTML of closest element will be shown.</DIV>\n </DIV>', 'TODO');
|
console.assert(closes2, 'not null');
|
||||||
console.exit(1);
|
//console.assert(closes2.outerHTML === '<DIV class="demo container">Parent\n <DIV id="myElement" class="demo">The outer HTML of closest element will be shown.</DIV>\n </DIV>', 'TODO');
|
||||||
|
|
||||||
|
closes2 = element.closest("p.test");
|
||||||
|
console.assert(closes2 === null, 'NULL');
|
||||||
|
|
||||||
|
console.exit(0);
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
</body>
|
</body>
|
||||||
|
@ -6,15 +6,27 @@
|
|||||||
|
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
|
|
||||||
console.error('element.matches');
|
console.error('element.matches.html');
|
||||||
|
|
||||||
var birds = document.getElementsByTagName('li');
|
var birds = document.getElementsByTagName('li');
|
||||||
|
var ch = false;
|
||||||
|
console.assert(birds.length === 3, '3');
|
||||||
|
|
||||||
for (var i = 0; i < birds.length; i++) {
|
for (var i = 0; i < birds.length; i++) {
|
||||||
if (birds[i].matches('.endangered')) {
|
if (birds.item(i).matches('.endangered')) {
|
||||||
console.assert(birds[i].textContent === 'Philippine eagle', 'endangered');
|
console.assert(birds.item(i).innerHTML === 'Philippine eagle', birds.item(i).innerHTML);
|
||||||
|
ch = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
console.assert(ch, 'was matched');
|
||||||
|
// birds = document.querySelectorAll('li');
|
||||||
|
|
||||||
|
ch = false;
|
||||||
|
// var counter = 0;
|
||||||
|
// birds.forEach(function(b) {
|
||||||
|
// counter++;
|
||||||
|
// });
|
||||||
|
// console.assert(counter === 3, 'Three');
|
||||||
|
|
||||||
console.exit(0);
|
console.exit(0);
|
||||||
|
|
||||||
|
31
test/ecmascript/assert/element.querySelector.html
Normal file
31
test/ecmascript/assert/element.querySelector.html
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<body>
|
||||||
|
<p class="a">Class a.</p>
|
||||||
|
<p class="b">Class b.</p>
|
||||||
|
<p id="start">
|
||||||
|
<b class="a">This a class.</b>
|
||||||
|
<b class="b">This b class.</b>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
function myFunction() {
|
||||||
|
var el = document.getElementById('start');
|
||||||
|
console.assert(!(el === null), 'start exists');
|
||||||
|
|
||||||
|
var x = el.querySelector('.nonexistent');
|
||||||
|
console.assert(x === null, 'nonexistent element');
|
||||||
|
|
||||||
|
var y = el.querySelector('.b');
|
||||||
|
console.assert(!(y === null), 'Class b');
|
||||||
|
var inp = y.innerHTML;
|
||||||
|
console.assert(inp === 'This b class.', 'Class b.');
|
||||||
|
}
|
||||||
|
|
||||||
|
console.error('element.querySelector.html');
|
||||||
|
myFunction();
|
||||||
|
console.exit(0);
|
||||||
|
</script>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
27
test/ecmascript/assert/element.querySelectorAll.html
Normal file
27
test/ecmascript/assert/element.querySelectorAll.html
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<body>
|
||||||
|
<p class="a">Class a.</p>
|
||||||
|
<p class="b">Class b.</p>
|
||||||
|
<p id="start">
|
||||||
|
<b class="a">This a class.</b>
|
||||||
|
<b class="b">This b class.</b>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
function myFunction() {
|
||||||
|
var el = document.getElementById('start');
|
||||||
|
var x = el.querySelectorAll('.nonexistent');
|
||||||
|
console.assert(x.length === 0, 'nonexistent element');
|
||||||
|
|
||||||
|
var y = el.querySelectorAll('.b');
|
||||||
|
console.assert(y.length === 1, 'b class b.');
|
||||||
|
}
|
||||||
|
|
||||||
|
console.error('element.querySelectorAll.html');
|
||||||
|
myFunction();
|
||||||
|
console.exit(0);
|
||||||
|
</script>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
20
test/ecmascript/assert/nodelist.forEach.html
Normal file
20
test/ecmascript/assert/nodelist.forEach.html
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
<ul id="birds">
|
||||||
|
<li>Orange-winged parrot</li>
|
||||||
|
<li class="endangered">Philippine eagle</li>
|
||||||
|
<li>Great white pelican</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<script type="text/javascript">
|
||||||
|
|
||||||
|
console.error('nodelist.forEach.html');
|
||||||
|
var birds = document.querySelectorAll('li');
|
||||||
|
|
||||||
|
var counter = 0;
|
||||||
|
birds.forEach(function(b) {
|
||||||
|
counter++;
|
||||||
|
});
|
||||||
|
console.assert(counter === 3, 'Three');
|
||||||
|
|
||||||
|
console.exit(0);
|
||||||
|
|
||||||
|
</script>
|
Loading…
Reference in New Issue
Block a user