diff options
author | Andreas Kling <kling@serenityos.org> | 2020-03-14 13:15:11 +0100 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2020-03-14 13:25:40 +0100 |
commit | 1c406294fc426a2d083e7d5f30f7e4e97ef4a794 (patch) | |
tree | 9dbd3c6fce454018e1f0af6c9dd2ecad1b779898 | |
parent | 9c9d3f090429746df8a39232eb75467007463a9e (diff) | |
download | serenity-1c406294fc426a2d083e7d5f30f7e4e97ef4a794.zip |
LibWeb: Start implementing basic JavaScript DOM bindings
This patch introduces the Wrapper and Wrappable classes.
Node now inherits from Wrappable, and can be wrapped in a GC-allocated
Bindings::NodeWrapper object. The only property we expose right now is
the very simple nodeName property.
When a Document's JS::Interpreter is first instantiated, we add a
"document" property with a DocumentWrapper object to the global object.
This is pretty cool! :^)
-rw-r--r-- | Base/home/anon/www/dom.html | 12 | ||||
-rw-r--r-- | Base/home/anon/www/welcome.html | 1 | ||||
-rw-r--r-- | Libraries/LibWeb/Bindings/DocumentWrapper.cpp | 29 | ||||
-rw-r--r-- | Libraries/LibWeb/Bindings/DocumentWrapper.h | 21 | ||||
-rw-r--r-- | Libraries/LibWeb/Bindings/NodeWrapper.cpp | 20 | ||||
-rw-r--r-- | Libraries/LibWeb/Bindings/NodeWrapper.h | 23 | ||||
-rw-r--r-- | Libraries/LibWeb/Bindings/Wrappable.cpp | 18 | ||||
-rw-r--r-- | Libraries/LibWeb/Bindings/Wrappable.h | 31 | ||||
-rw-r--r-- | Libraries/LibWeb/Bindings/Wrapper.h | 19 | ||||
-rw-r--r-- | Libraries/LibWeb/DOM/Document.cpp | 3 | ||||
-rw-r--r-- | Libraries/LibWeb/DOM/Document.h | 2 | ||||
-rw-r--r-- | Libraries/LibWeb/DOM/Node.h | 5 | ||||
-rw-r--r-- | Libraries/LibWeb/Forward.h | 10 | ||||
-rw-r--r-- | Libraries/LibWeb/Makefile | 3 |
14 files changed, 196 insertions, 1 deletions
diff --git a/Base/home/anon/www/dom.html b/Base/home/anon/www/dom.html new file mode 100644 index 0000000000..0c6a15dfad --- /dev/null +++ b/Base/home/anon/www/dom.html @@ -0,0 +1,12 @@ +<!DOCTYPE> +<html> + <head></head> + <body> + <div id="foo"></div> + <script> + alert(document.nodeName); + //var e = document.getElementById("foo"); + //alert(e.nodeName); + </script> + </body> +</html> diff --git a/Base/home/anon/www/welcome.html b/Base/home/anon/www/welcome.html index 6f7f3a3a78..4f2d30a013 100644 --- a/Base/home/anon/www/welcome.html +++ b/Base/home/anon/www/welcome.html @@ -23,6 +23,7 @@ h1 { <p>This is a very simple browser built on the LibWeb engine.</p> <p>Some small test pages:</p> <ul> + <li><a href="dom.html">simple DOM JS test</a></li> <li><a href="alert.html">alert() test</a></li> <li><a href="small.html">small</a></li> <li><a href="first-child.html">:first-child</a></li> diff --git a/Libraries/LibWeb/Bindings/DocumentWrapper.cpp b/Libraries/LibWeb/Bindings/DocumentWrapper.cpp new file mode 100644 index 0000000000..91836d7c8e --- /dev/null +++ b/Libraries/LibWeb/Bindings/DocumentWrapper.cpp @@ -0,0 +1,29 @@ +#include <LibJS/PrimitiveString.h> +#include <LibJS/Value.h> +#include <LibWeb/Bindings/DocumentWrapper.h> +#include <LibWeb/DOM/Document.h> + +namespace Web { +namespace Bindings { + +DocumentWrapper::DocumentWrapper(Document& document) + : NodeWrapper(document) +{ +} + +DocumentWrapper::~DocumentWrapper() +{ +} + +Document& DocumentWrapper::node() +{ + return static_cast<Document&>(NodeWrapper::node()); +} + +const Document& DocumentWrapper::node() const +{ + return static_cast<const Document&>(NodeWrapper::node()); +} + +} +} diff --git a/Libraries/LibWeb/Bindings/DocumentWrapper.h b/Libraries/LibWeb/Bindings/DocumentWrapper.h new file mode 100644 index 0000000000..931720c696 --- /dev/null +++ b/Libraries/LibWeb/Bindings/DocumentWrapper.h @@ -0,0 +1,21 @@ +#pragma once + +#include <LibWeb/Bindings/NodeWrapper.h> + +namespace Web { +namespace Bindings { + +class DocumentWrapper : public NodeWrapper { +public: + explicit DocumentWrapper(Document&); + virtual ~DocumentWrapper() override; + + Document& node(); + const Document& node() const; + +private: + virtual const char* class_name() const override { return "Document"; } +}; + +} +} diff --git a/Libraries/LibWeb/Bindings/NodeWrapper.cpp b/Libraries/LibWeb/Bindings/NodeWrapper.cpp new file mode 100644 index 0000000000..9aaa9b21a4 --- /dev/null +++ b/Libraries/LibWeb/Bindings/NodeWrapper.cpp @@ -0,0 +1,20 @@ +#include <LibJS/PrimitiveString.h> +#include <LibJS/Value.h> +#include <LibWeb/Bindings/NodeWrapper.h> +#include <LibWeb/DOM/Node.h> + +namespace Web { +namespace Bindings { + +NodeWrapper::NodeWrapper(Node& node) + : m_node(node) +{ + put("nodeName", JS::js_string(heap(), node.tag_name())); +} + +NodeWrapper::~NodeWrapper() +{ +} + +} +} diff --git a/Libraries/LibWeb/Bindings/NodeWrapper.h b/Libraries/LibWeb/Bindings/NodeWrapper.h new file mode 100644 index 0000000000..b7a24b94b7 --- /dev/null +++ b/Libraries/LibWeb/Bindings/NodeWrapper.h @@ -0,0 +1,23 @@ +#pragma once + +#include <LibWeb/Bindings/Wrapper.h> + +namespace Web { +namespace Bindings { + +class NodeWrapper : public Wrapper { +public: + explicit NodeWrapper(Node&); + virtual ~NodeWrapper() override; + + Node& node() { return *m_node; } + const Node& node() const { return *m_node; } + +private: + virtual const char* class_name() const override { return "Node"; } + + NonnullRefPtr<Node> m_node; +}; + +} +} diff --git a/Libraries/LibWeb/Bindings/Wrappable.cpp b/Libraries/LibWeb/Bindings/Wrappable.cpp new file mode 100644 index 0000000000..2245e14723 --- /dev/null +++ b/Libraries/LibWeb/Bindings/Wrappable.cpp @@ -0,0 +1,18 @@ +#include <LibWeb/Bindings/Wrappable.h> +#include <LibWeb/Bindings/Wrapper.h> + +namespace Web { +namespace Bindings { + +Wrappable::~Wrappable() +{ +} + +void Wrappable::set_wrapper(Wrapper& wrapper) +{ + ASSERT(!m_wrapper); + m_wrapper = wrapper.make_weak_ptr(); +} + +} +} diff --git a/Libraries/LibWeb/Bindings/Wrappable.h b/Libraries/LibWeb/Bindings/Wrappable.h new file mode 100644 index 0000000000..4531f63935 --- /dev/null +++ b/Libraries/LibWeb/Bindings/Wrappable.h @@ -0,0 +1,31 @@ +#pragma once + +#include <AK/WeakPtr.h> +#include <LibJS/Heap.h> +#include <LibWeb/Forward.h> + +namespace Web { +namespace Bindings { + +class Wrappable { +public: + virtual ~Wrappable(); + + void set_wrapper(Wrapper&); + Wrapper* wrapper() { return m_wrapper; } + const Wrapper* wrapper() const { return m_wrapper; } + +private: + WeakPtr<Wrapper> m_wrapper; +}; + +template<class NativeObject> +inline Wrapper* wrap(JS::Heap& heap, NativeObject& native_object) +{ + if (!native_object.wrapper()) + native_object.set_wrapper(*heap.allocate<typename NativeObject::WrapperType>(native_object)); + return native_object.wrapper(); +} + +} +} diff --git a/Libraries/LibWeb/Bindings/Wrapper.h b/Libraries/LibWeb/Bindings/Wrapper.h new file mode 100644 index 0000000000..680200eaab --- /dev/null +++ b/Libraries/LibWeb/Bindings/Wrapper.h @@ -0,0 +1,19 @@ +#pragma once + +#include <AK/NonnullRefPtr.h> +#include <AK/Weakable.h> +#include <LibJS/Object.h> +#include <LibWeb/Forward.h> + +namespace Web { +namespace Bindings { + +class Wrapper + : public JS::Object + , public Weakable<Wrapper> { +protected: + explicit Wrapper() {} +}; + +} +} diff --git a/Libraries/LibWeb/DOM/Document.cpp b/Libraries/LibWeb/DOM/Document.cpp index 8e25cbf64d..669f399047 100644 --- a/Libraries/LibWeb/DOM/Document.cpp +++ b/Libraries/LibWeb/DOM/Document.cpp @@ -31,6 +31,7 @@ #include <LibGUI/MessageBox.h> #include <LibJS/GlobalObject.h> #include <LibJS/Interpreter.h> +#include <LibWeb/Bindings/DocumentWrapper.h> #include <LibWeb/CSS/StyleResolver.h> #include <LibWeb/DOM/Document.h> #include <LibWeb/DOM/DocumentType.h> @@ -346,6 +347,8 @@ JS::Interpreter& Document::interpreter() GUI::MessageBox::show(arguments[0].to_string(), "Alert", GUI::MessageBox::Type::Information); return JS::js_undefined(); }); + + m_interpreter->global_object().put("document", wrap(m_interpreter->heap(), *this)); } return *m_interpreter; } diff --git a/Libraries/LibWeb/DOM/Document.h b/Libraries/LibWeb/DOM/Document.h index bdfe6e6cb9..b4fef21bb2 100644 --- a/Libraries/LibWeb/DOM/Document.h +++ b/Libraries/LibWeb/DOM/Document.h @@ -51,6 +51,8 @@ class StyleSheet; class Document : public ParentNode { public: + using WrapperType = Bindings::DocumentWrapper; + Document(); virtual ~Document() override; diff --git a/Libraries/LibWeb/DOM/Node.h b/Libraries/LibWeb/DOM/Node.h index 51a48bdffd..3cf67681a3 100644 --- a/Libraries/LibWeb/DOM/Node.h +++ b/Libraries/LibWeb/DOM/Node.h @@ -30,6 +30,7 @@ #include <AK/RefPtr.h> #include <AK/String.h> #include <AK/Vector.h> +#include <LibWeb/Bindings/Wrappable.h> #include <LibWeb/TreeNode.h> namespace Web { @@ -53,7 +54,9 @@ class LayoutNode; class StyleResolver; class StyleProperties; -class Node : public TreeNode<Node> { +class Node + : public TreeNode<Node> + , public Bindings::Wrappable { public: virtual ~Node(); diff --git a/Libraries/LibWeb/Forward.h b/Libraries/LibWeb/Forward.h index d700b317c3..8c87919e5b 100644 --- a/Libraries/LibWeb/Forward.h +++ b/Libraries/LibWeb/Forward.h @@ -34,4 +34,14 @@ class Frame; class HtmlView; class Node; +namespace Bindings { + +class DocumentWrapper; +class NodeWrapper; +class Wrappable; +class Wrapper; + +} + + } diff --git a/Libraries/LibWeb/Makefile b/Libraries/LibWeb/Makefile index 96acd12078..2a4601ae0b 100644 --- a/Libraries/LibWeb/Makefile +++ b/Libraries/LibWeb/Makefile @@ -1,4 +1,7 @@ LIBWEB_OBJS = \ + Bindings/Wrappable.o \ + Bindings/NodeWrapper.o \ + Bindings/DocumentWrapper.o \ CSS/DefaultStyleSheetSource.o \ CSS/PropertyID.o \ CSS/Selector.o \ |