1
0
mirror of https://github.com/rkd77/elinks.git synced 2024-06-14 23:32:27 +00:00

[ecmascript] Rewritten document.write

spidermonkey segfaults on test/ecmascript/document_write.html
quickjs and mujs do not.
This commit is contained in:
Witold Filipczyk 2022-11-19 19:24:15 +01:00
parent 7d8e92703b
commit 865f3fa0d0
6 changed files with 58 additions and 109 deletions

View File

@ -302,6 +302,7 @@ ecmascript_get_interpreter(struct view_state *vs)
}
(void)init_string(&interpreter->code);
(void)init_string(&interpreter->writecode);
return interpreter;
}
@ -322,6 +323,7 @@ ecmascript_put_interpreter(struct ecmascript_interpreter *interpreter)
#endif
free_ecmascript_string_list(&interpreter->onload_snippets);
done_string(&interpreter->code);
done_string(&interpreter->writecode);
/* Is it superfluous? */
if (interpreter->vs->doc_view) {
struct ecmascript_timeout *t;
@ -369,6 +371,44 @@ check_for_rerender(struct ecmascript_interpreter *interpreter, const char* text)
struct session *ses = doc_view->session;
struct cache_entry *cached = document->cached;
if (!strcmp(text, "eval")) {
if (interpreter->element_offset) {
if (interpreter->writecode.length) {
std::map<int, xmlpp::Element *> *mapa = (std::map<int, xmlpp::Element *> *)document->element_map;
if (mapa) {
auto element = (*mapa).find(interpreter->element_offset);
if (element != (*mapa).end()) {
xmlpp::Element *el = element->second;
xmlpp::ustring text = "<root>";
text += interpreter->writecode.source;
text += "</root>";
xmlDoc* doc = htmlReadDoc((xmlChar*)text.c_str(), NULL, NULL, HTML_PARSE_RECOVER | HTML_PARSE_NOERROR | HTML_PARSE_NOWARNING);
// Encapsulate raw libxml document in a libxml++ wrapper
xmlpp::Document doc1(doc);
auto root = doc1.get_root_node();
auto root1 = root->find("//root")[0];
auto children2 = root1->get_children();
auto it2 = children2.begin();
auto end2 = children2.end();
for (; it2 != end2; ++it2) {
xmlAddPrevSibling(el->cobj(), (*it2)->cobj());
}
xmlpp::Node::remove_node(el);
}
}
}
} else {
if (interpreter->writecode.length) {
add_fragment(cached, 0, interpreter->writecode.source, interpreter->writecode.length);
document->ecmascript_counter++;
}
}
}
//fprintf(stderr, "%s\n", text);
if (document->dom) {

View File

@ -66,6 +66,9 @@ struct ecmascript_interpreter {
/* The code evaluated by setTimeout() */
struct string code;
/* document.write buffer */
struct string writecode;
struct heartbeat *heartbeat;
/* This is a cross-rerenderings accumulator of

View File

@ -858,12 +858,6 @@ mjs_document_write_do(js_State *J, int newline)
fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__);
#endif
struct ecmascript_interpreter *interpreter = (struct ecmascript_interpreter *)js_getcontext(J);
struct string code;
if (!init_string(&code)) {
js_pushnull(J);
return;
}
int argc = 1;
if (argc >= 1)
@ -873,47 +867,20 @@ mjs_document_write_do(js_State *J, int newline)
const char *str = js_tostring(J, i+1);
if (str) {
add_to_string(&code, str);
add_to_string(&interpreter->writecode, str);
}
}
if (newline)
{
add_to_string(&code, "\n");
add_to_string(&interpreter->writecode, "\n");
}
}
//DBG("%s",code.source);
/* XXX: I don't know about you, but I have *ENOUGH* of those 'Undefined
* function' errors, I want to see just the useful ones. So just
* lighting a led and going away, no muss, no fuss. --pasky */
/* TODO: Perhaps we can introduce ecmascript.error_report_unsupported
* -> "Show information about the document using some valid,
* nevertheless unsupported methods/properties." --pasky too */
struct document_view *doc_view = interpreter->vs->doc_view;
struct document *document;
document = doc_view->document;
struct cache_entry *cached = doc_view->document->cached;
cached = doc_view->document->cached;
struct fragment *f = get_cache_fragment(cached);
if (f && f->length)
{
if (false && document->ecmascript_counter==0)
{
add_fragment(cached,0,code.source,code.length);
} else {
add_fragment(cached,f->length,code.source,code.length);
}
document->ecmascript_counter++;
}
interpreter->changed = true;
#ifdef CONFIG_LEDS
set_led_value(interpreter->vs->doc_view->session->status.ecmascript_led, 'J');
#endif
done_string(&code);
js_pushundefined(J);
}

View File

@ -903,11 +903,6 @@ js_document_write_do(JSContext *ctx, JSValueConst this_val, int argc, JSValueCon
fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__);
#endif
struct ecmascript_interpreter *interpreter = (struct ecmascript_interpreter *)JS_GetContextOpaque(ctx);
struct string code;
if (!init_string(&code)) {
return JS_EXCEPTION;
}
if (argc >= 1)
{
@ -921,48 +916,20 @@ js_document_write_do(JSContext *ctx, JSValueConst this_val, int argc, JSValueCon
if (!str) {
return JS_EXCEPTION;
}
add_bytes_to_string(&code, str, len);
add_bytes_to_string(&interpreter->writecode, str, len);
JS_FreeCString(ctx, str);
}
if (newline)
{
add_to_string(&code, "\n");
add_to_string(&interpreter->writecode, "\n");
}
}
//DBG("%s",code.source);
/* XXX: I don't know about you, but I have *ENOUGH* of those 'Undefined
* function' errors, I want to see just the useful ones. So just
* lighting a led and going away, no muss, no fuss. --pasky */
/* TODO: Perhaps we can introduce ecmascript.error_report_unsupported
* -> "Show information about the document using some valid,
* nevertheless unsupported methods/properties." --pasky too */
struct document_view *doc_view = interpreter->vs->doc_view;
struct document *document;
document = doc_view->document;
struct cache_entry *cached = doc_view->document->cached;
cached = doc_view->document->cached;
struct fragment *f = get_cache_fragment(cached);
if (f && f->length)
{
if (false && document->ecmascript_counter==0)
{
add_fragment(cached,0,code.source,code.length);
} else {
add_fragment(cached,f->length,code.source,code.length);
}
document->ecmascript_counter++;
}
interpreter->changed = true;
#ifdef CONFIG_LEDS
set_led_value(interpreter->vs->doc_view->session->status.ecmascript_led, 'J');
#endif
done_string(&code);
return JS_FALSE;
}

View File

@ -1305,56 +1305,24 @@ document_write_do(JSContext *ctx, unsigned int argc, JS::Value *rval, int newlin
struct ecmascript_interpreter *interpreter = (struct ecmascript_interpreter *)JS::GetRealmPrivate(comp);
JS::CallArgs args = JS::CallArgsFromVp(argc, rval);
struct string code;
if (!init_string(&code)) {
return false;
}
if (argc >= 1)
{
for (unsigned int i = 0; i < argc; ++i)
{
jshandle_value_to_char_string(&code, ctx, args[i]);
jshandle_value_to_char_string(&interpreter->writecode, ctx, args[i]);
}
if (newline)
{
add_to_string(&code, "\n");
add_to_string(&interpreter->writecode, "\n");
}
}
//DBG("%s",code.source);
/* XXX: I don't know about you, but I have *ENOUGH* of those 'Undefined
* function' errors, I want to see just the useful ones. So just
* lighting a led and going away, no muss, no fuss. --pasky */
/* TODO: Perhaps we can introduce ecmascript.error_report_unsupported
* -> "Show information about the document using some valid,
* nevertheless unsupported methods/properties." --pasky too */
struct document_view *doc_view = interpreter->vs->doc_view;
struct document *document;
document = doc_view->document;
struct cache_entry *cached = doc_view->document->cached;
cached = doc_view->document->cached;
struct fragment *f = get_cache_fragment(cached);
if (f && f->length)
{
if (false && document->ecmascript_counter==0)
{
add_fragment(cached,0,code.source,code.length);
} else {
add_fragment(cached,f->length,code.source,code.length);
}
document->ecmascript_counter++;
}
interpreter->changed = true;
#ifdef CONFIG_LEDS
set_led_value(interpreter->vs->doc_view->session->status.ecmascript_led, 'J');
#endif
done_string(&code);
args.rval().setBoolean(false);
return true;

View File

@ -4,6 +4,9 @@
-| 16 colors |-
</title>
<script type="text/javascript">
function onl()
{
document.writeln('<html><head><title>-| 16 colors |-</title></head><pre>');
var colors=[
"white",
@ -53,8 +56,9 @@ document.writeln('<html><head><title>-| 16 colors |-</title></head><pre>');
document.writeln('<font color="red">and this is false: '+false+'</font>');
document.writeln('<font color="yellow">',"That's it as ... ","1+1=",2,'</font>');
document.writeln('</pre></body></html>');
</script>
}
</script>
</head>
<body>
<body onload="onl()">
</body>
</html>