Bug 865998: Implement WebIDL union return values r=bz

This commit is contained in:
David Zbarsky 2013-07-26 11:25:54 -07:00
parent cc5560c810
commit 7837d54bf0
18 changed files with 284 additions and 207 deletions

View File

@ -186,8 +186,6 @@ MOCHITEST_BROWSER_FILES += \
test-bug-595934-svg.xhtml \
test-bug-595934-workers.html \
test-bug-595934-workers.js \
test-bug-595934-canvas.html \
test-bug-595934-canvas.js \
test-bug-595934-css-parser.html \
test-bug-595934-css-parser.css \
test-bug-595934-canvas-css.html \

View File

@ -46,31 +46,26 @@ const TESTS = [
matchString: "fooBarSVG",
},
{ // #6
file: "test-bug-595934-canvas.html",
category: "Canvas",
matchString: "strokeStyle",
},
{ // #7
file: "test-bug-595934-css-parser.html",
category: "CSS Parser",
matchString: "foobarCssParser",
},
{ // #8
{ // #7
file: "test-bug-595934-malformedxml-external.html",
category: "malformed-xml",
matchString: "</html>",
},
{ // #9
{ // #8
file: "test-bug-595934-empty-getelementbyid.html",
category: "DOM",
matchString: "getElementById",
},
{ // #10
{ // #9
file: "test-bug-595934-canvas-css.html",
category: "CSS Parser",
matchString: "foobarCanvasCssParser",
},
{ // #11
{ // #10
file: "test-bug-595934-image.html",
category: "Image",
matchString: "corrupt",

View File

@ -1,15 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Web Console test for bug 595934 - category: Canvas</title>
<!-- Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ -->
<script type="text/javascript"
src="test-bug-595934-canvas.js"></script>
</head>
<body>
<p>Web Console test for bug 595934 - category "Canvas".</p>
<p><canvas width="200" height="200">Canvas support is required!</canvas></p>
</body>
</html>

View File

@ -1,11 +0,0 @@
/*
* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/
*/
window.addEventListener("DOMContentLoaded", function() {
var canvas = document.querySelector("canvas");
var context = canvas.getContext("2d");
context.strokeStyle = document;
}, false);

View File

@ -13,9 +13,6 @@
#include "mozilla/gfx/2D.h"
#include "nsWrapperCache.h"
#define NS_CANVASGRADIENTAZURE_PRIVATE_IID \
{0x28425a6a, 0x90e0, 0x4d42, {0x9c, 0x75, 0xff, 0x60, 0x09, 0xb3, 0x10, 0xa8}}
namespace mozilla {
namespace dom {
@ -23,7 +20,6 @@ class CanvasGradient : public nsISupports,
public nsWrapperCache
{
public:
NS_DECLARE_STATIC_IID_ACCESSOR(NS_CANVASGRADIENTAZURE_PRIVATE_IID)
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(CanvasGradient)

View File

@ -12,8 +12,6 @@
#include "nsISupports.h"
#include "nsWrapperCache.h"
#define NS_CANVASPATTERNAZURE_PRIVATE_IID \
{0xc9bacc25, 0x28da, 0x421e, {0x9a, 0x4b, 0xbb, 0xd6, 0x93, 0x05, 0x12, 0xbc}}
class nsIPrincipal;
namespace mozilla {
@ -27,7 +25,6 @@ class CanvasPattern MOZ_FINAL : public nsISupports,
public nsWrapperCache
{
public:
NS_DECLARE_STATIC_IID_ACCESSOR(NS_CANVASPATTERNAZURE_PRIVATE_IID)
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(CanvasPattern)

View File

@ -92,10 +92,11 @@
#include "nsJSUtils.h"
#include "XPCQuickStubs.h"
#include "mozilla/dom/BindingUtils.h"
#include "mozilla/dom/CanvasRenderingContext2DBinding.h"
#include "mozilla/dom/HTMLImageElement.h"
#include "mozilla/dom/HTMLVideoElement.h"
#include "mozilla/dom/CanvasRenderingContext2DBinding.h"
#include "mozilla/dom/TextMetrics.h"
#include "mozilla/dom/UnionTypes.h"
#ifdef USE_SKIA_GPU
#undef free // apparently defined by some windows header, clashing with a free()
@ -400,8 +401,6 @@ CanvasGradient::AddColorStop(float offset, const nsAString& colorstr, ErrorResul
mRawStops.AppendElement(newStop);
}
NS_DEFINE_STATIC_IID_ACCESSOR(CanvasGradient, NS_CANVASGRADIENTAZURE_PRIVATE_IID)
NS_IMPL_CYCLE_COLLECTING_ADDREF(CanvasGradient)
NS_IMPL_CYCLE_COLLECTING_RELEASE(CanvasGradient)
@ -409,12 +408,9 @@ NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_1(CanvasGradient, mContext)
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(CanvasGradient)
NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
NS_INTERFACE_MAP_ENTRY(mozilla::dom::CanvasGradient)
NS_INTERFACE_MAP_ENTRY(nsISupports)
NS_INTERFACE_MAP_END
NS_DEFINE_STATIC_IID_ACCESSOR(CanvasPattern, NS_CANVASPATTERNAZURE_PRIVATE_IID)
NS_IMPL_CYCLE_COLLECTING_ADDREF(CanvasPattern)
NS_IMPL_CYCLE_COLLECTING_RELEASE(CanvasPattern)
@ -422,7 +418,6 @@ NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_1(CanvasPattern, mContext)
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(CanvasPattern)
NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
NS_INTERFACE_MAP_ENTRY(mozilla::dom::CanvasPattern)
NS_INTERFACE_MAP_ENTRY(nsISupports)
NS_INTERFACE_MAP_END
@ -648,17 +643,6 @@ CanvasRenderingContext2D::Reset()
return NS_OK;
}
static void
WarnAboutUnexpectedStyle(HTMLCanvasElement* canvasElement)
{
nsContentUtils::ReportToConsole(
nsIScriptError::warningFlag,
"Canvas",
canvasElement ? canvasElement->OwnerDoc() : nullptr,
nsContentUtils::eDOM_PROPERTIES,
"UnexpectedCanvasVariantStyle");
}
void
CanvasRenderingContext2D::SetStyleFromString(const nsAString& str,
Style whichStyle)
@ -673,27 +657,18 @@ CanvasRenderingContext2D::SetStyleFromString(const nsAString& str,
CurrentState().SetColorStyle(whichStyle, color);
}
nsISupports*
CanvasRenderingContext2D::GetStyleAsStringOrInterface(nsAString& aStr,
CanvasMultiGetterType& aType,
Style aWhichStyle)
void
CanvasRenderingContext2D::GetStyleAsUnion(StringOrCanvasGradientOrCanvasPatternReturnValue& aValue,
Style aWhichStyle)
{
const ContextState &state = CurrentState();
nsISupports* supports;
if (state.patternStyles[aWhichStyle]) {
aStr.SetIsVoid(true);
supports = state.patternStyles[aWhichStyle];
aType = CMG_STYLE_PATTERN;
aValue.SetAsCanvasPattern() = state.patternStyles[aWhichStyle];
} else if (state.gradientStyles[aWhichStyle]) {
aStr.SetIsVoid(true);
supports = state.gradientStyles[aWhichStyle];
aType = CMG_STYLE_GRADIENT;
aValue.SetAsCanvasGradient() = state.gradientStyles[aWhichStyle];
} else {
StyleColorToString(state.colorStyles[aWhichStyle], aStr);
supports = nullptr;
aType = CMG_STYLE_STRING;
StyleColorToString(state.colorStyles[aWhichStyle], aValue.SetAsString());
}
return supports;
}
// static
@ -1349,92 +1324,25 @@ CanvasRenderingContext2D::GetMozCurrentTransformInverse(JSContext* cx,
//
void
CanvasRenderingContext2D::SetStyleFromJSValue(JSContext* cx,
JS::Handle<JS::Value> value,
Style whichStyle)
CanvasRenderingContext2D::SetStyleFromUnion(const StringOrCanvasGradientOrCanvasPattern& value,
Style whichStyle)
{
if (value.isString()) {
nsDependentJSString strokeStyle;
if (strokeStyle.init(cx, value.toString())) {
SetStyleFromString(strokeStyle, whichStyle);
}
if (value.IsString()) {
SetStyleFromString(value.GetAsString(), whichStyle);
return;
}
if (value.isObject()) {
nsCOMPtr<nsISupports> holder;
CanvasGradient* gradient;
JS::Rooted<JS::Value> rootedVal(cx, value);
nsresult rv = xpc_qsUnwrapArg<CanvasGradient>(cx, value, &gradient,
static_cast<nsISupports**>(getter_AddRefs(holder)),
rootedVal.address());
if (NS_SUCCEEDED(rv)) {
SetStyleFromGradient(gradient, whichStyle);
return;
}
CanvasPattern* pattern;
rv = xpc_qsUnwrapArg<CanvasPattern>(cx, value, &pattern,
static_cast<nsISupports**>(getter_AddRefs(holder)),
rootedVal.address());
if (NS_SUCCEEDED(rv)) {
SetStyleFromPattern(pattern, whichStyle);
return;
}
if (value.IsCanvasGradient()) {
SetStyleFromGradient(value.GetAsCanvasGradient(), whichStyle);
return;
}
WarnAboutUnexpectedStyle(mCanvasElement);
}
static JS::Value
WrapStyle(JSContext* cx, JSObject* objArg,
CanvasRenderingContext2D::CanvasMultiGetterType type,
nsAString& str, nsISupports* supports, ErrorResult& error)
{
JS::Rooted<JS::Value> v(cx);
bool ok;
switch (type) {
case CanvasRenderingContext2D::CMG_STYLE_STRING:
{
ok = xpc::StringToJsval(cx, str, v.address());
break;
}
case CanvasRenderingContext2D::CMG_STYLE_PATTERN:
case CanvasRenderingContext2D::CMG_STYLE_GRADIENT:
{
JS::Rooted<JSObject*> obj(cx, objArg);
ok = dom::WrapObject(cx, obj, supports, &v);
break;
}
default:
MOZ_CRASH("unexpected CanvasMultiGetterType");
if (value.IsCanvasPattern()) {
SetStyleFromPattern(value.GetAsCanvasPattern(), whichStyle);
return;
}
if (!ok) {
error.Throw(NS_ERROR_FAILURE);
}
return v;
}
JS::Value
CanvasRenderingContext2D::GetStrokeStyle(JSContext* cx,
ErrorResult& error)
{
nsString str;
CanvasMultiGetterType t;
nsISupports* supports = GetStyleAsStringOrInterface(str, t, STYLE_STROKE);
return WrapStyle(cx, GetWrapper(), t, str, supports, error);
}
JS::Value
CanvasRenderingContext2D::GetFillStyle(JSContext* cx,
ErrorResult& error)
{
nsString str;
CanvasMultiGetterType t;
nsISupports* supports = GetStyleAsStringOrInterface(str, t, STYLE_FILL);
return WrapStyle(cx, GetWrapper(), t, str, supports, error);
MOZ_ASSUME_UNREACHABLE("Invalid union value");
}
void

View File

@ -17,7 +17,6 @@
#include "gfxFont.h"
#include "mozilla/ErrorResult.h"
#include "mozilla/dom/ImageData.h"
#include "mozilla/dom/UnionTypes.h"
#include "mozilla/dom/CanvasGradient.h"
#include "mozilla/dom/CanvasRenderingContext2DBinding.h"
#include "mozilla/dom/CanvasPattern.h"
@ -31,6 +30,9 @@ class SourceSurface;
}
namespace dom {
class HTMLImageElementOrHTMLCanvasElementOrHTMLVideoElement;
class StringOrCanvasGradientOrCanvasPattern;
class StringOrCanvasGradientOrCanvasPatternReturnValue;
class TextMetrics;
extern const mozilla::gfx::Float SIGMA_MAX;
@ -47,7 +49,7 @@ class CanvasRenderingContext2D :
public nsICanvasRenderingContextInternal,
public nsWrapperCache
{
typedef mozilla::dom::HTMLImageElementOrHTMLCanvasElementOrHTMLVideoElement
typedef HTMLImageElementOrHTMLCanvasElementOrHTMLVideoElement
HTMLImageOrCanvasOrVideoElement;
public:
@ -91,18 +93,25 @@ public:
void GetGlobalCompositeOperation(nsAString& op, mozilla::ErrorResult& error);
void SetGlobalCompositeOperation(const nsAString& op,
mozilla::ErrorResult& error);
JS::Value GetStrokeStyle(JSContext* cx, mozilla::ErrorResult& error);
void SetStrokeStyle(JSContext* cx, JS::Handle<JS::Value> value)
void GetStrokeStyle(StringOrCanvasGradientOrCanvasPatternReturnValue& value)
{
SetStyleFromJSValue(cx, value, STYLE_STROKE);
GetStyleAsUnion(value, STYLE_STROKE);
}
JS::Value GetFillStyle(JSContext* cx, mozilla::ErrorResult& error);
void SetFillStyle(JSContext* cx, JS::Handle<JS::Value> value)
void SetStrokeStyle(const StringOrCanvasGradientOrCanvasPattern& value)
{
SetStyleFromJSValue(cx, value, STYLE_FILL);
SetStyleFromUnion(value, STYLE_STROKE);
}
void GetFillStyle(StringOrCanvasGradientOrCanvasPatternReturnValue& value)
{
GetStyleAsUnion(value, STYLE_FILL);
}
void SetFillStyle(const StringOrCanvasGradientOrCanvasPattern& value)
{
SetStyleFromUnion(value, STYLE_FILL);
}
already_AddRefed<CanvasGradient>
@ -162,10 +171,10 @@ public:
bool IsPointInPath(double x, double y, const CanvasWindingRule& winding);
bool IsPointInStroke(double x, double y);
void FillText(const nsAString& text, double x, double y,
const mozilla::dom::Optional<double>& maxWidth,
const Optional<double>& maxWidth,
mozilla::ErrorResult& error);
void StrokeText(const nsAString& text, double x, double y,
const mozilla::dom::Optional<double>& maxWidth,
const Optional<double>& maxWidth,
mozilla::ErrorResult& error);
TextMetrics*
MeasureText(const nsAString& rawText, mozilla::ErrorResult& error);
@ -190,18 +199,18 @@ public:
DrawImage(image, sx, sy, sw, sh, dx, dy, dw, dh, 6, error);
}
already_AddRefed<mozilla::dom::ImageData>
already_AddRefed<ImageData>
CreateImageData(JSContext* cx, double sw, double sh,
mozilla::ErrorResult& error);
already_AddRefed<mozilla::dom::ImageData>
CreateImageData(JSContext* cx, mozilla::dom::ImageData& imagedata,
already_AddRefed<ImageData>
CreateImageData(JSContext* cx, ImageData& imagedata,
mozilla::ErrorResult& error);
already_AddRefed<mozilla::dom::ImageData>
already_AddRefed<ImageData>
GetImageData(JSContext* cx, double sx, double sy, double sw, double sh,
mozilla::ErrorResult& error);
void PutImageData(mozilla::dom::ImageData& imageData,
void PutImageData(ImageData& imageData,
double dx, double dy, mozilla::ErrorResult& error);
void PutImageData(mozilla::dom::ImageData& imageData,
void PutImageData(ImageData& imageData,
double dx, double dy, double dirtyX, double dirtyY,
double dirtyWidth, double dirtyHeight,
mozilla::ErrorResult& error);
@ -271,7 +280,7 @@ public:
void LineTo(double x, double y)
{
EnsureWritablePath();
LineTo(mozilla::gfx::Point(ToFloat(x), ToFloat(y)));
}
@ -474,21 +483,22 @@ protected:
static mozilla::gfx::DrawTarget* sErrorTarget;
// Some helpers. Doesn't modify a color on failure.
void SetStyleFromJSValue(JSContext* cx, JS::Handle<JS::Value> value,
Style whichStyle);
void SetStyleFromUnion(const StringOrCanvasGradientOrCanvasPattern& value,
Style whichStyle);
void SetStyleFromString(const nsAString& str, Style whichStyle);
void SetStyleFromGradient(CanvasGradient *gradient, Style whichStyle)
void SetStyleFromGradient(CanvasGradient& gradient, Style whichStyle)
{
CurrentState().SetGradientStyle(whichStyle, gradient);
CurrentState().SetGradientStyle(whichStyle, &gradient);
}
void SetStyleFromPattern(CanvasPattern *pattern, Style whichStyle)
void SetStyleFromPattern(CanvasPattern& pattern, Style whichStyle)
{
CurrentState().SetPatternStyle(whichStyle, pattern);
CurrentState().SetPatternStyle(whichStyle, &pattern);
}
nsISupports* GetStyleAsStringOrInterface(nsAString& aStr, CanvasMultiGetterType& aType, Style aWhichStyle);
void GetStyleAsUnion(StringOrCanvasGradientOrCanvasPatternReturnValue& aValue,
Style aWhichStyle);
// Returns whether a color was successfully parsed.
bool ParseColor(const nsAString& aString, nscolor* aColor);
@ -716,7 +726,7 @@ protected:
nsresult DrawOrMeasureText(const nsAString& text,
float x,
float y,
const mozilla::dom::Optional<double>& maxWidth,
const Optional<double>& maxWidth,
TextDrawOperation op,
float* aWidth);

View File

@ -13,6 +13,7 @@
#include "mozilla/CheckedInt.h"
#include "mozilla/dom/CanvasRenderingContext2D.h"
#include "mozilla/dom/HTMLCanvasElementBinding.h"
#include "mozilla/dom/UnionTypes.h"
#include "mozilla/gfx/Rect.h"
#include "mozilla/Preferences.h"
#include "mozilla/Telemetry.h"

View File

@ -159,8 +159,7 @@ DOMInterfaces = {
'CanvasRenderingContext2D': {
'implicitJSContext': [
'createImageData', 'getImageData', 'strokeStyle',
'fillStyle', 'mozDash'
'createImageData', 'getImageData', 'mozDash'
],
'resultNotAddRefed': [ 'canvas', 'measureText' ],
'binaryNames': {

View File

@ -9,6 +9,7 @@ import os
import re
import string
import math
import itertools
from WebIDL import BuiltinTypes, IDLBuiltinType, IDLNullValue, IDLSequenceType, IDLType
from Configuration import NoSuchDescriptorError, getTypesFromDescriptor, getTypesFromDictionary, getTypesFromCallback, Descriptor
@ -735,6 +736,7 @@ def UnionTypes(descriptors, dictionaries, callbacks, config):
implheaders = set(["UnionTypes.h"])
declarations = set()
unionStructs = dict()
unionReturnValues = dict()
def addInfoForType(t, descriptor=None, dictionary=None):
"""
@ -751,6 +753,10 @@ def UnionTypes(descriptors, dictionaries, callbacks, config):
config)
# FIXME: Unions are broken in workers. See bug 809899.
unionStructs[name] = CGUnionStruct(t, providers[0])
# Unions cannot contain JSObject*.
if not any(member.isObject() or member.isSpiderMonkeyInterface() for member in t.flatMemberTypes):
unionReturnValues[name] = CGUnionReturnValueStruct(t, providers[0])
for f in t.flatMemberTypes:
f = f.unroll()
if f.isInterface():
@ -772,7 +778,8 @@ def UnionTypes(descriptors, dictionaries, callbacks, config):
callForEachType(descriptors, dictionaries, callbacks, addInfoForType)
return (headers, implheaders, declarations,
CGList(SortedDictValues(unionStructs), "\n"))
CGList(itertools.chain(SortedDictValues(unionStructs),
SortedDictValues(unionReturnValues)), "\n"))
def UnionConversions(descriptors, dictionaries, callbacks, config):
"""
@ -2069,7 +2076,7 @@ def InitUnforgeablePropertiesOnObject(descriptor, obj, properties, failureReturn
if len(failureReturnValue) > 0:
failureReturn += " " + failureReturnValue
failureReturn += ";"
defineUnforgeables = ("if (!DefineUnforgeableAttributes(aCx, " + obj + ", %s)) {\n"
" " + failureReturn + "\n"
"}")
@ -2488,6 +2495,7 @@ def getJSToNativeConversionInfo(type, descriptorProvider, failureCode=None,
lenientFloatCode=None,
allowTreatNonCallableAsNull=False,
isCallbackReturnValue=False,
isInUnionReturnValue=False,
sourceDescription="value"):
"""
Get a template for converting a JS value to a native object based on the
@ -3036,13 +3044,16 @@ for (uint32_t i = 0; i < length; ++i) {
isCallbackReturnValue)
# Sequences and non-worker callbacks have to hold a strong ref to the
# thing being passed down. Also, callback return values always end up
# thing being passed down. Union return values must hold a strong ref
# because they may be returning an addrefed pointer.
# Also, callback return values always end up
# addrefing anyway, so there is no point trying to avoid it here and it
# makes other things simpler since we can assume the return value is a
# strong ref.
forceOwningType = ((descriptor.interface.isCallback() and
not descriptor.workers) or
isMember or
isInUnionReturnValue or
isCallbackReturnValue)
typeName = descriptor.nativeType
@ -3259,6 +3270,8 @@ for (uint32_t i = 0; i < length; ++i) {
if isOptional:
declType = "Optional<nsAString>"
elif isInUnionReturnValue:
declType = "nsString"
else:
declType = "NonNull<nsAString>"
@ -4100,15 +4113,7 @@ if (!returnArray) {
# NB: setValue(..., True) calls JS_WrapValue(), so is fallible
return (setValue(toValue % result, wrapType), False)
if type.isUnion():
if type.nullable():
prefix = "%s->"
else:
prefix = "%s."
return (wrapAndSetPtr((prefix % result) +
"ToJSVal(cx, ${obj}, ${jsvalHandle})"), False)
if not (type.isPrimitive() or type.isDictionary() or type.isDate()):
if not (type.isUnion() or type.isPrimitive() or type.isDictionary() or type.isDate()):
raise TypeError("Need to learn to wrap %s" % type)
if type.nullable():
@ -4119,6 +4124,10 @@ if (!returnArray) {
CGIndenter(CGGeneric(setValue("JSVAL_NULL"))).define() + "\n" +
"}\n" + recTemplate, recInfal)
if type.isUnion():
return (wrapAndSetPtr("%s.ToJSVal(cx, ${obj}, ${jsvalHandle})" % result),
False)
if type.isDictionary():
return (wrapAndSetPtr("%s.ToObject(cx, ${obj}, ${jsvalHandle})" % result),
False)
@ -4322,7 +4331,10 @@ def getRetvalDeclarationForType(returnType, descriptorProvider,
resultArgs = None
return result, True, None, resultArgs
if returnType.isUnion():
raise TypeError("Need to sort out ownership model for union retvals");
result = CGGeneric(returnType.unroll().name + "ReturnValue")
if returnType.nullable():
result = CGTemplatedType("Nullable", result)
return result, True, None, None
if returnType.isDate():
result = CGGeneric("Date")
if returnType.nullable():
@ -4430,7 +4442,7 @@ class CGCallGenerator(CGThing):
if isFallible:
self.cgRoot.prepend(CGGeneric("ErrorResult rv;"))
self.cgRoot.append(CGGeneric("rv.WouldReportJSException();"));
self.cgRoot.append(CGGeneric("rv.WouldReportJSException();"))
self.cgRoot.append(CGGeneric("if (rv.Failed()) {"))
self.cgRoot.append(CGIndenter(errorReport))
self.cgRoot.append(CGGeneric("}"))
@ -5839,7 +5851,7 @@ def getUnionAccessorSignatureType(type, descriptorProvider):
typeName = CGTemplatedType("Nullable", typeName, isReference=True)
return typeName
def getUnionTypeTemplateVars(unionType, type, descriptorProvider):
def getUnionTypeTemplateVars(unionType, type, descriptorProvider, isReturnValue=False):
# For dictionaries and sequences we need to pass None as the failureCode
# for getJSToNativeConversionInfo.
# Also, for dictionaries we would need to handle conversion of
@ -5864,7 +5876,7 @@ return true;"""
}""" % name) + tryNextCode
conversionInfo = getJSToNativeConversionInfo(
type, descriptorProvider, failureCode=tryNextCode,
isDefinitelyObject=True,
isDefinitelyObject=True, isInUnionReturnValue=isReturnValue,
sourceDescription="member of %s" % unionType)
# This is ugly, but UnionMember needs to call a constructor with no
@ -5958,7 +5970,7 @@ class CGUnionStruct(CGThing):
}"""
methods.extend(mapTemplate(methodTemplate, templateVars))
# Now have to be careful: we do not want the SetAsObject() method!
setterTemplate = """ ${structType}& SetAs${name}()
setterTemplate = """ ${structType}& SetAs${name}()
{
mType = e${name};
return mValue.m${name}.SetValue();
@ -6020,7 +6032,7 @@ ${destructors}
if self.type.hasNullableType:
conversionsToJS.append(" case eNull:\n"
" {\n"
" rval.set(JS::NullValue());\n"
" rval.setNull();\n"
" return true;\n"
" }")
conversionsToJS.extend(
@ -6062,7 +6074,161 @@ ${doConversionsToJS}
"jsvalHandle": "rval",
"obj": "scopeObj",
"result": val,
"objectCanBeNonNull": True
})
return CGIndenter(CGList([CGGeneric("case e%(name)s:" % templateVars),
CGWrapper(CGIndenter(CGGeneric(wrapCode)),
pre="{\n",
post="\n}")],
"\n"),
4).define()
class CGUnionReturnValueStruct(CGThing):
def __init__(self, type, descriptorProvider):
CGThing.__init__(self)
self.type = type.unroll()
self.descriptorProvider = descriptorProvider
self.templateVars = map(
lambda t: getUnionTypeTemplateVars(self.type, t,
self.descriptorProvider,
isReturnValue=True),
self.type.flatMemberTypes)
def declare(self):
templateVars = self.templateVars
enumValues = []
methods = []
if self.type.hasNullableType:
enumValues.append("eNull")
methods.append(""" bool IsNull() const
{
return mType == eNull;
}
bool SetNull()
{
mType = eNull;
return true;
}""")
enumValues.extend(mapTemplate("e${name}", templateVars))
methodTemplate = " ${structType}& SetAs${name}();"
methods.extend(mapTemplate(methodTemplate, templateVars))
values = mapTemplate("UnionMember<${structType} > m${name};", templateVars)
return string.Template("""
class ${structName}ReturnValue {
public:
${structName}ReturnValue() : mType(eUninitialized)
{
}
~${structName}ReturnValue();
${methods}
bool ToJSVal(JSContext* cx, JS::Handle<JSObject*> scopeObj,
JS::MutableHandle<JS::Value> rval) const;
private:
enum Type {
eUninitialized,
${enumValues}
};
union Value {
${values}
};
Type mType;
Value mValue;
};
""").substitute(
{
"structName": self.type.__str__(),
"methods": "\n\n".join(methods),
"enumValues": ",\n ".join(enumValues),
"values": "\n ".join(values)
})
def define(self):
templateVars = self.templateVars
conversionsToJS = []
if self.type.hasNullableType:
conversionsToJS.append(" case eNull:\n"
" {\n"
" rval.setNull();\n"
" return true;\n"
" }")
conversionsToJS.extend(
map(self.getConversionToJS,
zip(templateVars, self.type.flatMemberTypes)))
toJSVal = string.Template("""
bool
${structName}ReturnValue::ToJSVal(JSContext* cx, JS::Handle<JSObject*> scopeObj, JS::MutableHandle<JS::Value> rval) const
{
switch (mType) {
${doConversionsToJS}
case eUninitialized:
{
break;
}
}
return false;
}
""").substitute({
"structName": str(self.type),
"doConversionsToJS": "\n\n".join(conversionsToJS)
})
templateVars = self.templateVars
methods = []
methodTemplate = """${structType}&
%sReturnValue::SetAs${name}()
{
mType = e${name};
return mValue.m${name}.SetValue();
}""" % str(self.type)
methods.extend(mapTemplate(methodTemplate, templateVars))
callDestructors = []
if self.type.hasNullableType:
callDestructors.append(" case eNull:\n"
" break;")
callDestructors.extend(mapTemplate(" case e${name}:\n"
" mValue.m${name}.Destroy();\n"
" mType = eUninitialized;\n"
" break;", templateVars))
destructor = string.Template("""
${structName}ReturnValue::~${structName}ReturnValue()
{
switch (mType) {
${callDestructors}
case eUninitialized:
break;
}
}
""").substitute(
{
"structName": self.type.__str__(),
"callDestructors": "\n".join(callDestructors),
})
return destructor + "\n\n".join(methods) + toJSVal
def getConversionToJS(self, arg):
(templateVars, type) = arg
assert not type.nullable() # flatMemberTypes never has nullable types
val = "mValue.m%(name)s.Value()" % templateVars
wrapCode = wrapForType(
type, self.descriptorProvider,
{
"jsvalRef": "rval",
"jsvalHandle": "rval",
"obj": "scopeObj",
"result": val,
})
return CGIndenter(CGList([CGGeneric("case e%(name)s:" % templateVars),
CGWrapper(CGIndenter(CGGeneric(wrapCode)),

View File

@ -2504,7 +2504,7 @@ class IDLAttribute(IDLInterfaceMember):
raise WebIDLError("An attribute cannot be of a sequence type",
[self.location])
if self.type.isUnion():
for f in self.type.flatMemberTypes:
for f in self.type.unroll().flatMemberTypes:
if f.isDictionary():
raise WebIDLError("An attribute cannot be of a union "
"type if one of its member types (or "

View File

@ -507,6 +507,16 @@ public:
//void PassUnionWithCallback(JSContext*, const TestCallbackOrLong&);
void PassUnionWithObject(JSContext*, const ObjectOrLong&);
void ReceiveUnion(const CanvasPatternOrCanvasGradientReturnValue&);
void ReceiveUnionContainingNull(const CanvasPatternOrNullOrCanvasGradientReturnValue&);
void ReceiveNullableUnion(const Nullable<CanvasPatternOrCanvasGradientReturnValue>&);
void GetWritableUnion(const CanvasPatternOrCanvasGradientReturnValue&);
void SetWritableUnion(const CanvasPatternOrCanvasGradient&);
void GetWritableUnionContainingNull(const CanvasPatternOrNullOrCanvasGradientReturnValue&);
void SetWritableUnionContainingNull(const CanvasPatternOrNullOrCanvasGradient&);
void GetWritableNullableUnion(const Nullable<CanvasPatternOrCanvasGradientReturnValue>&);
void SetWritableNullableUnion(const Nullable<CanvasPatternOrCanvasGradient>&);
// Date types
void PassDate(Date);
void PassNullableDate(const Nullable<Date>&);

View File

@ -452,6 +452,14 @@ interface TestInterface {
void passUnionWithObject((object or long) arg);
//void passUnionWithDict((Dict or long) arg);
(CanvasPattern or CanvasGradient) receiveUnion();
(CanvasPattern? or CanvasGradient) receiveUnionContainingNull();
(CanvasPattern or CanvasGradient)? receiveNullableUnion();
attribute (CanvasPattern or CanvasGradient) writableUnion;
attribute (CanvasPattern? or CanvasGradient) writableUnionContainingNull;
attribute (CanvasPattern or CanvasGradient)? writableNullableUnion;
// Date types
void passDate(Date arg);
void passNullableDate(Date? arg);

View File

@ -348,6 +348,14 @@ interface TestExampleInterface {
void passUnionWithObject((object or long) arg);
//void passUnionWithDict((Dict or long) arg);
//(CanvasPattern or CanvasGradient) receiveUnion();
//(CanvasPattern? or CanvasGradient) receiveUnionContainingNull();
//(CanvasPattern or CanvasGradient)? receiveNullableUnion();
//attribute (CanvasPattern or CanvasGradient) writableUnion;
//attribute (CanvasPattern? or CanvasGradient) writableUnionContainingNull;
//attribute (CanvasPattern or CanvasGradient)? writableNullableUnion;
// Date types
void passDate(Date arg);
void passNullableDate(Date? arg);

View File

@ -372,6 +372,14 @@ interface TestJSImplInterface {
void passUnionWithObject((object or long) arg);
//void passUnionWithDict((Dict or long) arg);
//(CanvasPattern or CanvasGradient) receiveUnion();
//(CanvasPattern? or CanvasGradient) receiveUnionContainingNull();
//(CanvasPattern or CanvasGradient)? receiveNullableUnion();
//attribute (CanvasPattern or CanvasGradient) writableUnion;
//attribute (CanvasPattern? or CanvasGradient) writableUnionContainingNull;
//attribute (CanvasPattern or CanvasGradient)? writableNullableUnion;
// Date types
void passDate(Date arg);
void passNullableDate(Date? arg);

View File

@ -17,4 +17,5 @@ LIBXUL_LIBRARY = 1
include $(topsrcdir)/config/rules.mk
INCLUDES += -I$(topsrcdir)/dom/base
INCLUDES += -I$(topsrcdir)/content/base/src

View File

@ -46,10 +46,8 @@ interface CanvasRenderingContext2D {
attribute DOMString globalCompositeOperation; // (default source-over)
// colors and styles (see also the CanvasDrawingStyles interface)
[GetterThrows]
attribute any strokeStyle; // (default black)
[GetterThrows]
attribute any fillStyle; // (default black)
attribute (DOMString or CanvasGradient or CanvasPattern) strokeStyle; // (default black)
attribute (DOMString or CanvasGradient or CanvasPattern) fillStyle; // (default black)
[Creator]
CanvasGradient createLinearGradient(double x0, double y0, double x1, double y1);
[Creator, Throws]