diff --git a/Base/home/anon/www/welcome.html b/Base/home/anon/www/welcome.html
index 3084977afe..e07463e859 100644
--- a/Base/home/anon/www/welcome.html
+++ b/Base/home/anon/www/welcome.html
@@ -20,14 +20,12 @@ span#ua {
color: red;
}
-
+
Welcome to the Serenity Browser!
This is a very simple browser built on the LibWeb and LibJS engines.
- Your user agent is:
+ Your user agent is:
Some small test pages:
- querySelectorAll test
diff --git a/Base/home/anon/www/welcome.js b/Base/home/anon/www/welcome.js
new file mode 100644
index 0000000000..07497d0115
--- /dev/null
+++ b/Base/home/anon/www/welcome.js
@@ -0,0 +1,3 @@
+document.addEventListener("DOMContentLoaded", function() {
+ document.getElementById("ua").innerHTML = navigator.userAgent;
+});
diff --git a/Libraries/LibWeb/DOM/HTMLScriptElement.cpp b/Libraries/LibWeb/DOM/HTMLScriptElement.cpp
index 8361215704..5745878c48 100644
--- a/Libraries/LibWeb/DOM/HTMLScriptElement.cpp
+++ b/Libraries/LibWeb/DOM/HTMLScriptElement.cpp
@@ -30,6 +30,7 @@
#include
#include
#include
+#include
namespace Web {
@@ -42,17 +43,48 @@ HTMLScriptElement::~HTMLScriptElement()
{
}
-void HTMLScriptElement::inserted_into(Node& new_parent)
+void HTMLScriptElement::children_changed()
{
- HTMLElement::inserted_into(new_parent);
+ HTMLElement::children_changed();
+
+ if (has_attribute("src"))
+ return;
StringBuilder builder;
for_each_child([&](auto& child) {
if (is(child))
builder.append(to(child).text_content());
});
-
auto source = builder.to_string();
+ if (source.is_empty())
+ return;
+
+ auto program = JS::Parser(JS::Lexer(source)).parse_program();
+ document().interpreter().run(*program);
+}
+
+void HTMLScriptElement::inserted_into(Node& new_parent)
+{
+ HTMLElement::inserted_into(new_parent);
+
+ auto src = attribute("src");
+ if (src.is_null())
+ return;
+
+ String source;
+ URL src_url = document().complete_url(src);
+ ResourceLoader::the().load_sync(src_url, [&](auto& data) {
+ if (data.is_null()) {
+ dbg() << "HTMLScriptElement: Failed to load " << src;
+ return;
+ }
+ source = String::copy(data);
+ });
+ if (source.is_empty()) {
+ dbg() << "HTMLScriptElement: No source to parse :(";
+ return;
+ }
+
auto program = JS::Parser(JS::Lexer(source)).parse_program();
document().interpreter().run(*program);
}
diff --git a/Libraries/LibWeb/DOM/HTMLScriptElement.h b/Libraries/LibWeb/DOM/HTMLScriptElement.h
index bb9f7e139c..92f856d0a7 100644
--- a/Libraries/LibWeb/DOM/HTMLScriptElement.h
+++ b/Libraries/LibWeb/DOM/HTMLScriptElement.h
@@ -36,6 +36,7 @@ public:
virtual ~HTMLScriptElement() override;
virtual void inserted_into(Node&) override;
+ virtual void children_changed() override;
};
}
diff --git a/Libraries/LibWeb/DOM/HTMLStyleElement.cpp b/Libraries/LibWeb/DOM/HTMLStyleElement.cpp
index f3f7775348..83ae31b148 100644
--- a/Libraries/LibWeb/DOM/HTMLStyleElement.cpp
+++ b/Libraries/LibWeb/DOM/HTMLStyleElement.cpp
@@ -41,7 +41,7 @@ HTMLStyleElement::~HTMLStyleElement()
{
}
-void HTMLStyleElement::inserted_into(Node& new_parent)
+void HTMLStyleElement::children_changed()
{
StringBuilder builder;
for_each_child([&](auto& child) {
@@ -51,7 +51,7 @@ void HTMLStyleElement::inserted_into(Node& new_parent)
m_stylesheet = parse_css(builder.to_string());
if (m_stylesheet)
document().add_sheet(*m_stylesheet);
- HTMLElement::inserted_into(new_parent);
+ HTMLElement::children_changed();
}
void HTMLStyleElement::removed_from(Node& old_parent)
diff --git a/Libraries/LibWeb/DOM/HTMLStyleElement.h b/Libraries/LibWeb/DOM/HTMLStyleElement.h
index e7dac784c2..06bd7d9feb 100644
--- a/Libraries/LibWeb/DOM/HTMLStyleElement.h
+++ b/Libraries/LibWeb/DOM/HTMLStyleElement.h
@@ -37,7 +37,7 @@ public:
HTMLStyleElement(Document&, const FlyString& tag_name);
virtual ~HTMLStyleElement() override;
- virtual void inserted_into(Node&) override;
+ virtual void children_changed() override;
virtual void removed_from(Node&) override;
private:
diff --git a/Libraries/LibWeb/DOM/Node.h b/Libraries/LibWeb/DOM/Node.h
index 43359af872..479ec8960f 100644
--- a/Libraries/LibWeb/DOM/Node.h
+++ b/Libraries/LibWeb/DOM/Node.h
@@ -104,6 +104,7 @@ public:
virtual void inserted_into(Node&) {}
virtual void removed_from(Node&) {}
+ virtual void children_changed() {}
const LayoutNode* layout_node() const { return m_layout_node; }
LayoutNode* layout_node() { return m_layout_node; }
diff --git a/Libraries/LibWeb/Layout/LayoutNode.h b/Libraries/LibWeb/Layout/LayoutNode.h
index 22557a9fce..84f2f8bc14 100644
--- a/Libraries/LibWeb/Layout/LayoutNode.h
+++ b/Libraries/LibWeb/Layout/LayoutNode.h
@@ -111,6 +111,7 @@ public:
void inserted_into(LayoutNode&) {}
void removed_from(LayoutNode&) {}
+ void children_changed() {}
virtual void split_into_lines(LayoutBlock& container);
diff --git a/Libraries/LibWeb/Parser/HTMLParser.cpp b/Libraries/LibWeb/Parser/HTMLParser.cpp
index 7dfbfcdb10..c21fd30806 100644
--- a/Libraries/LibWeb/Parser/HTMLParser.cpp
+++ b/Libraries/LibWeb/Parser/HTMLParser.cpp
@@ -97,7 +97,7 @@ static bool parse_html_document(const StringView& html, Document& document, Pare
auto commit_text_node = [&] {
auto text_node = adopt(*new Text(document, text_buffer.to_string()));
- node_stack.last().append_child(text_node, false);
+ node_stack.last().append_child(text_node);
text_buffer.clear();
};
@@ -129,19 +129,20 @@ static bool parse_html_document(const StringView& html, Document& document, Pare
tag_name_buffer.clear();
new_element->set_attributes(move(attributes));
node_stack.append(new_element);
- if (node_stack.size() != 1)
- node_stack[node_stack.size() - 2].append_child(new_element, false);
+ if (node_stack.size() != 1) {
+ node_stack[node_stack.size() - 2].append_child(new_element);
+ }
if (is_self_closing_tag(new_element->tag_name()))
close_tag();
};
auto commit_doctype = [&] {
- node_stack.last().append_child(adopt(*new DocumentType(document)), false);
+ node_stack.last().append_child(adopt(*new DocumentType(document)));
};
auto commit_comment = [&] {
- node_stack.last().append_child(adopt(*new Comment(document, text_buffer.to_string())), false);
+ node_stack.last().append_child(adopt(*new Comment(document, text_buffer.to_string())));
};
auto commit_tag = [&] {
@@ -378,6 +379,7 @@ RefPtr parse_html_document(const StringView& html, const URL& url)
document->fixup();
+#if 0
Function fire_insertion_callbacks = [&](Node& node) {
for (auto* child = node.first_child(); child; child = child->next_sibling()) {
fire_insertion_callbacks(*child);
@@ -386,6 +388,7 @@ RefPtr parse_html_document(const StringView& html, const URL& url)
node.inserted_into(*node.parent());
};
fire_insertion_callbacks(document);
+#endif
document->dispatch_event(Event::create("DOMContentLoaded"));
diff --git a/Libraries/LibWeb/TreeNode.h b/Libraries/LibWeb/TreeNode.h
index 188d142ab3..5d96416b5b 100644
--- a/Libraries/LibWeb/TreeNode.h
+++ b/Libraries/LibWeb/TreeNode.h
@@ -108,9 +108,9 @@ public:
bool is_ancestor_of(const TreeNode&) const;
- void prepend_child(NonnullRefPtr node, bool call_inserted_into = true);
- void append_child(NonnullRefPtr node, bool call_inserted_into = true);
- NonnullRefPtr remove_child(NonnullRefPtr node, bool call_removed_from = true);
+ void prepend_child(NonnullRefPtr node);
+ void append_child(NonnullRefPtr node);
+ NonnullRefPtr remove_child(NonnullRefPtr node);
void donate_all_children_to(T& node);
bool is_child_allowed(const T&) const { return true; }
@@ -200,7 +200,7 @@ private:
};
template
-inline NonnullRefPtr TreeNode::remove_child(NonnullRefPtr node, bool call_removed_from)
+inline NonnullRefPtr TreeNode::remove_child(NonnullRefPtr node)
{
ASSERT(node->m_parent == this);
@@ -220,16 +220,17 @@ inline NonnullRefPtr TreeNode::remove_child(NonnullRefPtr node, bool ca
node->m_previous_sibling = nullptr;
node->m_parent = nullptr;
- if (call_removed_from)
- node->removed_from(static_cast(*this));
+ node->removed_from(static_cast(*this));
node->unref();
+ static_cast(this)->children_changed();
+
return node;
}
template
-inline void TreeNode::append_child(NonnullRefPtr node, bool call_inserted_into)
+inline void TreeNode::append_child(NonnullRefPtr node)
{
ASSERT(!node->m_parent);
@@ -243,13 +244,14 @@ inline void TreeNode::append_child(NonnullRefPtr node, bool call_inserted_
m_last_child = node.ptr();
if (!m_first_child)
m_first_child = m_last_child;
- if (call_inserted_into)
- node->inserted_into(static_cast(*this));
+ node->inserted_into(static_cast(*this));
(void)node.leak_ref();
+
+ static_cast(this)->children_changed();
}
template
-inline void TreeNode::prepend_child(NonnullRefPtr node, bool call_inserted_into)
+inline void TreeNode::prepend_child(NonnullRefPtr node)
{
ASSERT(!node->m_parent);
@@ -263,9 +265,10 @@ inline void TreeNode::prepend_child(NonnullRefPtr node, bool call_inserted
m_first_child = node.ptr();
if (!m_last_child)
m_last_child = m_first_child;
- if (call_inserted_into)
- node->inserted_into(static_cast(*this));
+ node->inserted_into(static_cast(*this));
(void)node.leak_ref();
+
+ static_cast(this)->children_changed();
}
template