diff --git a/Libraries/LibWeb/Bindings/XMLHttpRequestConstructor.cpp b/Libraries/LibWeb/Bindings/XMLHttpRequestConstructor.cpp index 092df6206fa..7fea4c1cc11 100644 --- a/Libraries/LibWeb/Bindings/XMLHttpRequestConstructor.cpp +++ b/Libraries/LibWeb/Bindings/XMLHttpRequestConstructor.cpp @@ -39,6 +39,12 @@ XMLHttpRequestConstructor::XMLHttpRequestConstructor() : NativeFunction(*interpreter().global_object().function_prototype()) { put("length", JS::Value(1)); + + put("UNSENT", JS::Value((i32)XMLHttpRequest::ReadyState::Unsent)); + put("OPENED", JS::Value((i32)XMLHttpRequest::ReadyState::Opened)); + put("HEADERS_RECEIVED", JS::Value((i32)XMLHttpRequest::ReadyState::HeadersReceived)); + put("LOADING", JS::Value((i32)XMLHttpRequest::ReadyState::Loading)); + put("DONE", JS::Value((i32)XMLHttpRequest::ReadyState::Done)); } XMLHttpRequestConstructor::~XMLHttpRequestConstructor() diff --git a/Libraries/LibWeb/Bindings/XMLHttpRequestPrototype.cpp b/Libraries/LibWeb/Bindings/XMLHttpRequestPrototype.cpp index 0a72097790b..d749663c206 100644 --- a/Libraries/LibWeb/Bindings/XMLHttpRequestPrototype.cpp +++ b/Libraries/LibWeb/Bindings/XMLHttpRequestPrototype.cpp @@ -40,7 +40,14 @@ XMLHttpRequestPrototype::XMLHttpRequestPrototype() { put_native_function("open", open, 2); put_native_function("send", send, 0); + put_native_property("readyState", ready_state_getter, nullptr); put_native_property("responseText", response_text_getter, nullptr); + + put("UNSENT", JS::Value((i32)XMLHttpRequest::ReadyState::Unsent)); + put("OPENED", JS::Value((i32)XMLHttpRequest::ReadyState::Opened)); + put("HEADERS_RECEIVED", JS::Value((i32)XMLHttpRequest::ReadyState::HeadersReceived)); + put("LOADING", JS::Value((i32)XMLHttpRequest::ReadyState::Loading)); + put("DONE", JS::Value((i32)XMLHttpRequest::ReadyState::Done)); } XMLHttpRequestPrototype::~XMLHttpRequestPrototype() @@ -77,6 +84,14 @@ JS::Value XMLHttpRequestPrototype::send(JS::Interpreter& interpreter) return JS::js_undefined(); } +JS::Value XMLHttpRequestPrototype::ready_state_getter(JS::Interpreter& interpreter) +{ + auto* impl = impl_from(interpreter); + if (!impl) + return {}; + return JS::Value((i32)impl->ready_state()); +} + JS::Value XMLHttpRequestPrototype::response_text_getter(JS::Interpreter& interpreter) { auto* impl = impl_from(interpreter); diff --git a/Libraries/LibWeb/Bindings/XMLHttpRequestPrototype.h b/Libraries/LibWeb/Bindings/XMLHttpRequestPrototype.h index 3f760250543..3fa5d48869a 100644 --- a/Libraries/LibWeb/Bindings/XMLHttpRequestPrototype.h +++ b/Libraries/LibWeb/Bindings/XMLHttpRequestPrototype.h @@ -42,6 +42,7 @@ private: static JS::Value open(JS::Interpreter&); static JS::Value send(JS::Interpreter&); + static JS::Value ready_state_getter(JS::Interpreter&); static JS::Value response_text_getter(JS::Interpreter&); }; diff --git a/Libraries/LibWeb/DOM/XMLHttpRequest.cpp b/Libraries/LibWeb/DOM/XMLHttpRequest.cpp index 757ce79bb3a..95e36e047d4 100644 --- a/Libraries/LibWeb/DOM/XMLHttpRequest.cpp +++ b/Libraries/LibWeb/DOM/XMLHttpRequest.cpp @@ -46,6 +46,12 @@ XMLHttpRequest::~XMLHttpRequest() { } +void XMLHttpRequest::set_ready_state(ReadyState ready_state) +{ + // FIXME: call onreadystatechange once we have that + m_ready_state = ready_state; +} + String XMLHttpRequest::response_text() const { if (m_response.is_null()) @@ -57,22 +63,27 @@ void XMLHttpRequest::open(const String& method, const String& url) { m_method = method; m_url = url; + set_ready_state(ReadyState::Opened); } void XMLHttpRequest::send() { + // FIXME: in order to properly set ReadyState::HeadersReceived and ReadyState::Loading, + // we need to make ResourceLoader give us more detailed updates than just "done" and "error". ResourceLoader::the().load( m_window->document().complete_url(m_url), [weak_this = make_weak_ptr()](auto& data) { if (!weak_this) return; const_cast(*weak_this).m_response = data; + const_cast(*weak_this).set_ready_state(ReadyState::Done); const_cast(*weak_this).dispatch_event(Event::create("load")); }, [weak_this = make_weak_ptr()](auto& error) { if (!weak_this) return; dbg() << "XHR failed to load: " << error; + const_cast(*weak_this).set_ready_state(ReadyState::Done); const_cast(*weak_this).dispatch_event(Event::create("error")); }); } diff --git a/Libraries/LibWeb/DOM/XMLHttpRequest.h b/Libraries/LibWeb/DOM/XMLHttpRequest.h index 88c197be072..0b9917d607a 100644 --- a/Libraries/LibWeb/DOM/XMLHttpRequest.h +++ b/Libraries/LibWeb/DOM/XMLHttpRequest.h @@ -40,6 +40,14 @@ class XMLHttpRequest final , public EventTarget , public Bindings::Wrappable { public: + enum class ReadyState { + Unsent, + Opened, + HeadersReceived, + Loading, + Done, + }; + using WrapperType = Bindings::XMLHttpRequestWrapper; static NonnullRefPtr create(Window& window) { return adopt(*new XMLHttpRequest(window)); } @@ -49,6 +57,7 @@ public: using RefCounted::ref; using RefCounted::unref; + ReadyState ready_state() const { return m_ready_state; }; String response_text() const; void open(const String& method, const String& url); void send(); @@ -58,10 +67,14 @@ private: virtual void unref_event_target() override { unref(); } virtual void dispatch_event(NonnullRefPtr) override; + void set_ready_state(ReadyState); + explicit XMLHttpRequest(Window&); NonnullRefPtr m_window; + ReadyState m_ready_state { ReadyState::Unsent }; + String m_method; String m_url;