JSXMLHttpRequestCustom.cpp [plain text]
#include "config.h"
#include "JSXMLHttpRequest.h"
#include "Blob.h"
#include "DOMFormData.h"
#include "DOMWindow.h"
#include "Document.h"
#include "Event.h"
#include "Frame.h"
#include "FrameLoader.h"
#include "HTMLDocument.h"
#include "InspectorInstrumentation.h"
#include "JSBlob.h"
#include "JSDOMFormData.h"
#include "JSDOMWindowCustom.h"
#include "JSDocument.h"
#include "JSEvent.h"
#include "JSEventListener.h"
#include "XMLHttpRequest.h"
#include <interpreter/StackVisitor.h>
#include <runtime/ArrayBuffer.h>
#include <runtime/Error.h>
#include <runtime/JSArrayBuffer.h>
#include <runtime/JSArrayBufferView.h>
#include <runtime/JSONObject.h>
using namespace JSC;
namespace WebCore {
void JSXMLHttpRequest::visitAdditionalChildren(SlotVisitor& visitor)
{
if (XMLHttpRequestUpload* upload = wrapped().optionalUpload())
visitor.addOpaqueRoot(upload);
if (Document* responseDocument = wrapped().optionalResponseXML())
visitor.addOpaqueRoot(responseDocument);
}
class SendFunctor {
public:
SendFunctor()
: m_hasSkippedFirstFrame(false)
, m_line(0)
, m_column(0)
{
}
unsigned line() const { return m_line; }
unsigned column() const { return m_column; }
String url() const { return m_url; }
StackVisitor::Status operator()(StackVisitor& visitor) const
{
if (!m_hasSkippedFirstFrame) {
m_hasSkippedFirstFrame = true;
return StackVisitor::Continue;
}
unsigned line = 0;
unsigned column = 0;
visitor->computeLineAndColumn(line, column);
m_line = line;
m_column = column;
m_url = visitor->sourceURL();
return StackVisitor::Done;
}
private:
mutable bool m_hasSkippedFirstFrame;
mutable unsigned m_line;
mutable unsigned m_column;
mutable String m_url;
};
JSValue JSXMLHttpRequest::send(ExecState& state)
{
InspectorInstrumentation::willSendXMLHttpRequest(wrapped().scriptExecutionContext(), wrapped().url());
JSValue value = state.argument(0);
ExceptionOr<void> result;
if (value.isUndefinedOrNull())
result = wrapped().send();
else if (value.inherits(JSDocument::info()))
result = wrapped().send(*JSDocument::toWrapped(value));
else if (value.inherits(JSBlob::info()))
result = wrapped().send(*JSBlob::toWrapped(value));
else if (value.inherits(JSDOMFormData::info()))
result = wrapped().send(*JSDOMFormData::toWrapped(value));
else if (RefPtr<ArrayBuffer> arrayBuffer = toUnsharedArrayBuffer(value))
result = wrapped().send(*arrayBuffer);
else if (RefPtr<ArrayBufferView> arrayBufferView = toUnsharedArrayBufferView(value))
result = wrapped().send(*arrayBufferView);
else {
result = wrapped().send(value.toWTFString(&state));
}
SendFunctor functor;
state.iterate(functor);
wrapped().setLastSendLineAndColumnNumber(functor.line(), functor.column());
wrapped().setLastSendURL(functor.url());
if (UNLIKELY(result.hasException())) {
propagateException(state, result.releaseException());
return { };
}
return jsUndefined();
}
JSValue JSXMLHttpRequest::responseText(ExecState& state) const
{
auto result = wrapped().responseText();
if (UNLIKELY(result.hasException())) {
propagateException(state, result.releaseException());
return { };
}
return jsOwnedStringOrNull(&state, result.releaseReturnValue());
}
JSValue JSXMLHttpRequest::retrieveResponse(ExecState& state)
{
auto type = wrapped().responseType();
switch (type) {
case XMLHttpRequest::ResponseType::EmptyString:
case XMLHttpRequest::ResponseType::Text:
return responseText(state);
default:
break;
}
if (!wrapped().doneWithoutErrors())
return jsNull();
JSValue value;
switch (type) {
case XMLHttpRequest::ResponseType::EmptyString:
case XMLHttpRequest::ResponseType::Text:
ASSERT_NOT_REACHED();
return jsUndefined();
case XMLHttpRequest::ResponseType::Json:
value = JSONParse(&state, wrapped().responseTextIgnoringResponseType());
if (!value)
value = jsNull();
break;
case XMLHttpRequest::ResponseType::Document: {
auto document = wrapped().responseXML();
ASSERT(!document.hasException());
value = toJS(&state, globalObject(), document.releaseReturnValue());
break;
}
case XMLHttpRequest::ResponseType::Blob:
value = toJSNewlyCreated(&state, globalObject(), wrapped().createResponseBlob());
break;
case XMLHttpRequest::ResponseType::Arraybuffer:
value = toJS(&state, globalObject(), wrapped().createResponseArrayBuffer());
break;
}
wrapped().didCacheResponse();
return value;
}
}