mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-12 04:45:45 +00:00
Bug 749864. Codegen for typed array and arraybuffer arguments. r=peterv
This commit is contained in:
parent
93aee7cacc
commit
cd87a47887
@ -2606,15 +2606,14 @@ GetRequestBody(nsIXHRSendable* aSendable, nsIInputStream** aResult,
|
||||
}
|
||||
|
||||
static nsresult
|
||||
GetRequestBody(JSObject* aArrayBuffer, JSContext *aCx, nsIInputStream** aResult,
|
||||
GetRequestBody(ArrayBuffer* aArrayBuffer, JSContext *aCx, nsIInputStream** aResult,
|
||||
nsACString& aContentType, nsACString& aCharset)
|
||||
{
|
||||
NS_ASSERTION(JS_IsArrayBufferObject(aArrayBuffer, aCx), "Not an ArrayBuffer!");
|
||||
aContentType.SetIsVoid(true);
|
||||
aCharset.Truncate();
|
||||
|
||||
PRInt32 length = JS_GetArrayBufferByteLength(aArrayBuffer, aCx);
|
||||
char* data = reinterpret_cast<char*>(JS_GetArrayBufferData(aArrayBuffer, aCx));
|
||||
PRInt32 length = aArrayBuffer->mLength;
|
||||
char* data = reinterpret_cast<char*>(aArrayBuffer->mData);
|
||||
|
||||
nsCOMPtr<nsIInputStream> stream;
|
||||
nsresult rv = NS_NewByteInputStream(getter_AddRefs(stream), data, length,
|
||||
@ -2679,7 +2678,8 @@ GetRequestBody(nsIVariant* aBody, JSContext *aCx, nsIInputStream** aResult,
|
||||
if (NS_SUCCEEDED(rv) && !JSVAL_IS_PRIMITIVE(realVal) &&
|
||||
(obj = JSVAL_TO_OBJECT(realVal)) &&
|
||||
(JS_IsArrayBufferObject(obj, aCx))) {
|
||||
return GetRequestBody(obj, aCx, aResult, aContentType, aCharset);
|
||||
ArrayBuffer buf(aCx, obj);
|
||||
return GetRequestBody(&buf, aCx, aResult, aContentType, aCharset);
|
||||
}
|
||||
}
|
||||
else if (dataType == nsIDataType::VTYPE_VOID ||
|
||||
|
@ -41,6 +41,7 @@
|
||||
#include "mozilla/dom/XMLHttpRequestUploadBinding.h"
|
||||
|
||||
#include "mozilla/Assertions.h"
|
||||
#include "mozilla/dom/TypedArray.h"
|
||||
|
||||
class nsILoadGroup;
|
||||
class AsyncVerifyRedirectCallbackForwarder;
|
||||
@ -278,7 +279,7 @@ private:
|
||||
RequestBody() : mType(Uninitialized)
|
||||
{
|
||||
}
|
||||
RequestBody(JSObject* aArrayBuffer) : mType(ArrayBuffer)
|
||||
RequestBody(mozilla::dom::ArrayBuffer* aArrayBuffer) : mType(ArrayBuffer)
|
||||
{
|
||||
mValue.mArrayBuffer = aArrayBuffer;
|
||||
}
|
||||
@ -313,7 +314,7 @@ private:
|
||||
InputStream
|
||||
};
|
||||
union Value {
|
||||
JSObject* mArrayBuffer;
|
||||
mozilla::dom::ArrayBuffer* mArrayBuffer;
|
||||
nsIDOMBlob* mBlob;
|
||||
nsIDocument* mDocument;
|
||||
const nsAString* mString;
|
||||
@ -359,10 +360,9 @@ public:
|
||||
{
|
||||
aRv = Send(aCx, Nullable<RequestBody>());
|
||||
}
|
||||
void Send(JSContext *aCx, JSObject* aArrayBuffer, ErrorResult& aRv)
|
||||
void Send(JSContext *aCx, mozilla::dom::ArrayBuffer& aArrayBuffer, ErrorResult& aRv)
|
||||
{
|
||||
NS_ASSERTION(aArrayBuffer, "Null should go to string version");
|
||||
aRv = Send(aCx, RequestBody(aArrayBuffer));
|
||||
aRv = Send(aCx, RequestBody(&aArrayBuffer));
|
||||
}
|
||||
void Send(JSContext *aCx, nsIDOMBlob* aBlob, ErrorResult& aRv)
|
||||
{
|
||||
|
@ -352,8 +352,9 @@ class CGHeaders(CGWrapper):
|
||||
|
||||
for t in types:
|
||||
if t.unroll().isInterface():
|
||||
if t.unroll().isArrayBuffer():
|
||||
if t.unroll().isSpiderMonkeyInterface():
|
||||
bindingHeaders.add("jsfriendapi.h")
|
||||
bindingHeaders.add("mozilla/dom/TypedArray.h")
|
||||
else:
|
||||
typeDesc = d.getDescriptor(t.unroll().inner.identifier.name)
|
||||
if typeDesc is not None:
|
||||
@ -1439,7 +1440,7 @@ ${declName}.SwapElements(arr);
|
||||
descriptorProvider.workers)
|
||||
return (templateBody, typeName, None)
|
||||
|
||||
if type.isInterface() and not type.isArrayBuffer():
|
||||
if type.isGeckoInterface():
|
||||
descriptor = descriptorProvider.getDescriptor(
|
||||
type.unroll().inner.identifier.name)
|
||||
# This is an interface that we implement as a concrete class
|
||||
@ -1536,34 +1537,47 @@ ${declName}.SwapElements(arr);
|
||||
|
||||
templateBody = wrapObjectTemplate(templateBody, isDefinitelyObject,
|
||||
type, "${declName} = NULL",
|
||||
descriptor.workers)
|
||||
descriptor.workers, failureCode)
|
||||
|
||||
declType = CGGeneric(declType)
|
||||
if holderType is not None:
|
||||
holderType = CGGeneric(holderType)
|
||||
return (templateBody, declType, holderType)
|
||||
|
||||
if type.isArrayBuffer():
|
||||
if type.isSpiderMonkeyInterface():
|
||||
if isSequenceMember:
|
||||
raise TypeError("Can't handle sequences of arraybuffers")
|
||||
declType = "JSObject*"
|
||||
template = (
|
||||
"if (${val}.isObject() && JS_IsArrayBufferObject(&${val}.toObject(), cx)) {\n"
|
||||
" ${declName} = &${val}.toObject();\n"
|
||||
"}")
|
||||
raise TypeError("Can't handle sequences of arraybuffers or "
|
||||
"arraybuffer views because making sure all the "
|
||||
"objects are properly rooted is hard")
|
||||
name = type.name
|
||||
if type.isArrayBuffer():
|
||||
jsname = "ArrayBufferObject"
|
||||
elif type.isArrayBufferView():
|
||||
jsname = "TypedArrayObject"
|
||||
else:
|
||||
jsname = type.name
|
||||
|
||||
holderType = "Maybe<%s>" % name
|
||||
if type.nullable():
|
||||
template += (
|
||||
" else if (${val}.isNullOrUndefined()) {\n"
|
||||
" ${declName} = NULL;\n"
|
||||
"}")
|
||||
declType = name + "*"
|
||||
else:
|
||||
declType = "NonNull<" + name + ">"
|
||||
template = (
|
||||
"if (!JS_Is%s(&${val}.toObject(), cx)) {\n"
|
||||
" %s" # No newline here because onFailure() handles that
|
||||
"}\n"
|
||||
"${holderName}.construct(cx, &${val}.toObject());\n" %
|
||||
(jsname, onFailure(failureCode, descriptorProvider.workers).define()))
|
||||
if type.nullable:
|
||||
template += "${declName} = ${holderName}.addr();"
|
||||
else:
|
||||
template += "${declName} = ${holderName}.ref();"
|
||||
template = wrapObjectTemplate(template, isDefinitelyObject, type,
|
||||
"${declName} = NULL",
|
||||
descriptorProvider.workers,
|
||||
failureCode)
|
||||
|
||||
template += (
|
||||
" else {\n" +
|
||||
CGIndenter(onFailure(failureCode,
|
||||
descriptorProvider.workers)).define() +
|
||||
"}")
|
||||
|
||||
return (template, CGGeneric(declType), None)
|
||||
return (template, CGGeneric(declType), CGGeneric(holderType))
|
||||
|
||||
if type.isString():
|
||||
if isSequenceMember:
|
||||
@ -1829,7 +1843,7 @@ for (uint32_t i = 0; i < length; ++i) {
|
||||
%s
|
||||
}\n""" % (result, innerTemplate)) + setValue("JS::ObjectValue(*returnArray)")
|
||||
|
||||
if type.isInterface() and not type.isArrayBuffer():
|
||||
if type.isGeckoInterface():
|
||||
descriptor = descriptorProvider.getDescriptor(type.unroll().inner.identifier.name)
|
||||
if type.nullable():
|
||||
wrappingCode = ("if (!%s) {\n" % (result) +
|
||||
@ -1976,7 +1990,7 @@ def getRetvalDeclarationForType(returnType, descriptorProvider,
|
||||
if returnType.nullable():
|
||||
raise TypeError("We don't support nullable enum return values")
|
||||
return CGGeneric(returnType.inner.identifier.name), False
|
||||
if returnType.isInterface() and not returnType.isArrayBuffer():
|
||||
if returnType.isGeckoInterface():
|
||||
result = CGGeneric(descriptorProvider.getDescriptor(
|
||||
returnType.unroll().inner.identifier.name).nativeType)
|
||||
if resultAlreadyAddRefed:
|
||||
@ -2351,29 +2365,31 @@ class CGMethodCall(CGThing):
|
||||
pickFirstSignature("%s.isNullOrUndefined()" % distinguishingArg,
|
||||
lambda s: s[1][distinguishingIndex].type.nullable())
|
||||
|
||||
# Now check for distinguishingArg being a platform object.
|
||||
# We can actually check separately for array buffers and
|
||||
# other things.
|
||||
# XXXbz Do we need to worry about security
|
||||
# wrappers around the array buffer?
|
||||
pickFirstSignature("%s.isObject() && JS_IsArrayBufferObject(&%s.toObject(), cx)" %
|
||||
(distinguishingArg, distinguishingArg),
|
||||
lambda s: (s[1][distinguishingIndex].type.isArrayBuffer() or
|
||||
s[1][distinguishingIndex].type.isObject()))
|
||||
|
||||
# Now check for distinguishingArg being an object that implements a
|
||||
# non-callback interface. That includes typed arrays and
|
||||
# arraybuffers.
|
||||
interfacesSigs = [
|
||||
s for s in possibleSignatures
|
||||
if (s[1][distinguishingIndex].type.isObject() or
|
||||
(s[1][distinguishingIndex].type.isInterface() and
|
||||
not s[1][distinguishingIndex].type.isArrayBuffer() and
|
||||
not s[1][distinguishingIndex].type.isCallback())) ]
|
||||
# There might be more than one of these; we need to check
|
||||
# which ones we unwrap to.
|
||||
|
||||
if len(interfacesSigs) > 0:
|
||||
caseBody.append(CGGeneric("if (%s.isObject() &&\n"
|
||||
" IsPlatformObject(cx, &%s.toObject())) {" %
|
||||
(distinguishingArg, distinguishingArg)))
|
||||
# The spec says that we should check for "platform objects
|
||||
# implementing an interface", but it's enough to guard on these
|
||||
# being an object. The code for unwrapping non-callback
|
||||
# interfaces and typed arrays will just bail out and move on to
|
||||
# the next overload if the object fails to unwrap correctly. We
|
||||
# could even not do the isObject() check up front here, but in
|
||||
# cases where we have multiple object overloads it makes sense
|
||||
# to do it only once instead of for each overload. That will
|
||||
# also allow the unwrapping test to skip having to do codegen
|
||||
# for the null-or-undefined case, which we already handled
|
||||
# above.
|
||||
caseBody.append(CGGeneric("if (%s.isObject()) {" %
|
||||
(distinguishingArg)))
|
||||
for sig in interfacesSigs:
|
||||
caseBody.append(CGIndenter(CGGeneric("do {")));
|
||||
type = sig[1][distinguishingIndex].type
|
||||
|
@ -12,6 +12,8 @@
|
||||
// Need this for XMLHttpRequestResponseType.
|
||||
#include "mozilla/dom/XMLHttpRequestBinding.h"
|
||||
|
||||
#include "mozilla/dom/TypedArray.h"
|
||||
|
||||
BEGIN_WORKERS_NAMESPACE
|
||||
|
||||
class Proxy;
|
||||
@ -155,6 +157,11 @@ public:
|
||||
void
|
||||
Send(JSObject* aBody, ErrorResult& aRv);
|
||||
|
||||
void
|
||||
Send(ArrayBuffer& aBody, ErrorResult& aRv) {
|
||||
return Send(aBody.mObj, aRv);
|
||||
}
|
||||
|
||||
void
|
||||
SendAsBinary(const nsAString& aBody, ErrorResult& aRv);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user