Bug 1359822 - Match standard for colSpan/rowSpan
Previously, the spec for these attributes didn't match implementations
at all, and that was just fixed:
<https://github.com/whatwg/html/issues/1198>. There are two
differences to our previous implementation:
1) The IDL property should be set as an unsigned int, not signed. This
was just a bug.
2) When parsing the IDL property, the value is now clamped to the
minimum/maximum value instead of being set to 1. Negative values still
get set to 1 instead of 0, even for rowSpan which allows 0 as a value.
The test changes are copied from the wpt test submitted upstream. An
additional rendering test using getBoundingClientRect() is also accepted
upstream: https://github.com/w3c/web-platform-tests/pull/4115
MozReview-Commit-ID: FQzPhgqNTBy
--- a/dom/base/nsAttrValue.cpp
+++ b/dom/base/nsAttrValue.cpp
@@ -1529,16 +1529,50 @@ nsAttrValue::ParseIntWithFallback(const
(result & nsContentUtils::eParseHTMLInteger_NonStandard) ||
(result & nsContentUtils::eParseHTMLInteger_DidNotConsumeAllInput)) {
nonStrict = true;
}
SetIntValueAndType(val, eInteger, nonStrict ? &aString : nullptr);
}
+void
+nsAttrValue::ParseClampedNonNegativeInt(const nsAString& aString,
+ int32_t aDefault, int32_t aMin,
+ int32_t aMax)
+{
+ ResetIfSet();
+
+ nsContentUtils::ParseHTMLIntegerResultFlags result;
+ int32_t val = nsContentUtils::ParseHTMLInteger(aString, &result);
+ bool nonStrict = (result & nsContentUtils::eParseHTMLInteger_IsPercent) ||
+ (result & nsContentUtils::eParseHTMLInteger_NonStandard) ||
+ (result & nsContentUtils::eParseHTMLInteger_DidNotConsumeAllInput);
+
+ if (result & nsContentUtils::eParseHTMLInteger_ErrorOverflow) {
+ if (result & nsContentUtils::eParseHTMLInteger_Negative) {
+ val = aDefault;
+ } else {
+ val = aMax;
+ }
+ nonStrict = true;
+ } else if ((result & nsContentUtils::eParseHTMLInteger_Error) || val < 0) {
+ val = aDefault;
+ nonStrict = true;
+ } else if (val < aMin) {
+ val = aMin;
+ nonStrict = true;
+ } else if (val > aMax) {
+ val = aMax;
+ nonStrict = true;
+ }
+
+ SetIntValueAndType(val, eInteger, nonStrict ? &aString : nullptr);
+}
+
bool
nsAttrValue::ParseNonNegativeIntValue(const nsAString& aString)
{
ResetIfSet();
nsContentUtils::ParseHTMLIntegerResultFlags result;
int32_t originalVal = nsContentUtils::ParseHTMLInteger(aString, &result);
if ((result & nsContentUtils::eParseHTMLInteger_Error) || originalVal < 0) {
--- a/dom/base/nsAttrValue.h
+++ b/dom/base/nsAttrValue.h
@@ -358,16 +358,29 @@ public:
* http://dev.w3.org/html5/spec/infrastructure.html#rules-for-parsing-non-negative-integers
*
* @param aString the string to parse
* @return whether the value is valid
*/
bool ParseNonNegativeIntValue(const nsAString& aString);
/**
+ * Parse a string value into a clamped non-negative integer.
+ * This method follows the rules for parsing non-negative integer from:
+ * https://html.spec.whatwg.org/multipage/infrastructure.html#clamped-to-the-range
+ *
+ * @param aString the string to parse
+ * @param aDefault value to return for negative or invalid values
+ * @param aMin minimum value
+ * @param aMax maximum value
+ */
+ void ParseClampedNonNegativeInt(const nsAString& aString, int32_t aDefault,
+ int32_t aMin, int32_t aMax);
+
+ /**
* Parse a string value into a positive integer.
* This method follows the rules for parsing non-negative integer from:
* http://dev.w3.org/html5/spec/infrastructure.html#rules-for-parsing-non-negative-integers
* In addition of these rules, the value has to be greater than zero.
*
* This is generally used for parsing content attributes which reflecting IDL
* attributes are limited to only non-negative numbers greater than zero, see:
* http://dev.w3.org/html5/spec/common-dom-interfaces.html#limited-to-only-non-negative-numbers-greater-than-zero
--- a/dom/base/nsContentUtils.cpp
+++ b/dom/base/nsContentUtils.cpp
@@ -1114,16 +1114,17 @@ nsContentUtils::ParseHTMLInteger(const n
result |= eParseHTMLInteger_Error | eParseHTMLInteger_ErrorNoValue;
*aResult = (ParseHTMLIntegerResultFlags)result;
return 0;
}
int sign = 1;
if (*iter == char16_t('-')) {
sign = -1;
+ result |= eParseHTMLInteger_Negative;
++iter;
} else if (*iter == char16_t('+')) {
result |= eParseHTMLInteger_NonStandard;
++iter;
}
bool foundValue = false;
CheckedInt32 value = 0;
@@ -10269,9 +10270,9 @@ nsContentUtils::IsLocalRefURL(const nsSt
if (*current > 0x20) {
// if the first non-"C0 controls + space" character is '#', this is a
// local-ref URL.
return *current == '#';
}
}
return false;
-}
\ No newline at end of file
+}
--- a/dom/base/nsContentUtils.h
+++ b/dom/base/nsContentUtils.h
@@ -477,17 +477,19 @@ public:
eParseHTMLInteger_IsPercent = 1 << 0,
// eParseHTMLInteger_NonStandard is set if the string representation of the
// integer was not the canonical one (e.g. had extra leading '+' or '0').
eParseHTMLInteger_NonStandard = 1 << 1,
eParseHTMLInteger_DidNotConsumeAllInput = 1 << 2,
// Set if one or more error flags were set.
eParseHTMLInteger_Error = 1 << 3,
eParseHTMLInteger_ErrorNoValue = 1 << 4,
- eParseHTMLInteger_ErrorOverflow = 1 << 5
+ eParseHTMLInteger_ErrorOverflow = 1 << 5,
+ // Use this flag to detect the difference between overflow and underflow
+ eParseHTMLInteger_Negative = 1 << 6,
};
static int32_t ParseHTMLInteger(const nsAString& aValue,
ParseHTMLIntegerResultFlags *aResult);
/**
* Parse a margin string of format 'top, right, bottom, left' into
* an nsIntMargin.
*
--- a/dom/html/HTMLTableCellElement.cpp
+++ b/dom/html/HTMLTableCellElement.cpp
@@ -393,36 +393,26 @@ HTMLTableCellElement::ParseAttribute(int
/* ignore these attributes, stored simply as strings
abbr, axis, ch, headers
*/
if (aAttribute == nsGkAtoms::charoff) {
/* attributes that resolve to integers with a min of 0 */
return aResult.ParseIntWithBounds(aValue, 0);
}
if (aAttribute == nsGkAtoms::colspan) {
- bool res = aResult.ParseIntWithBounds(aValue, -1);
- if (res) {
- int32_t val = aResult.GetIntegerValue();
- // reset large colspan values as IE and opera do
- if (val > MAX_COLSPAN || val <= 0) {
- aResult.SetTo(1, &aValue);
- }
- }
- return res;
+ aResult.ParseClampedNonNegativeInt(aValue, 1, 1, MAX_COLSPAN);
+ return true;
}
if (aAttribute == nsGkAtoms::rowspan) {
- bool res = aResult.ParseIntWithBounds(aValue, -1, MAX_ROWSPAN);
- if (res) {
- int32_t val = aResult.GetIntegerValue();
- // quirks mode does not honor the special html 4 value of 0
- if (val < 0 || (0 == val && InNavQuirksMode(OwnerDoc()))) {
- aResult.SetTo(1, &aValue);
- }
+ aResult.ParseClampedNonNegativeInt(aValue, 1, 0, MAX_ROWSPAN);
+ // quirks mode does not honor the special html 4 value of 0
+ if (aResult.GetIntegerValue() == 0 && InNavQuirksMode(OwnerDoc())) {
+ aResult.SetTo(1, &aValue);
}
- return res;
+ return true;
}
if (aAttribute == nsGkAtoms::height) {
return aResult.ParseSpecialIntValue(aValue);
}
if (aAttribute == nsGkAtoms::width) {
return aResult.ParseSpecialIntValue(aValue);
}
if (aAttribute == nsGkAtoms::align) {
--- a/dom/html/HTMLTableCellElement.h
+++ b/dom/html/HTMLTableCellElement.h
@@ -32,25 +32,25 @@ public:
NS_DECL_NSIDOMHTMLTABLECELLELEMENT
uint32_t ColSpan() const
{
return GetIntAttr(nsGkAtoms::colspan, 1);
}
void SetColSpan(uint32_t aColSpan, ErrorResult& aError)
{
- SetHTMLIntAttr(nsGkAtoms::colspan, aColSpan, aError);
+ SetUnsignedIntAttr(nsGkAtoms::colspan, aColSpan, 1, aError);
}
uint32_t RowSpan() const
{
return GetIntAttr(nsGkAtoms::rowspan, 1);
}
void SetRowSpan(uint32_t aRowSpan, ErrorResult& aError)
{
- SetHTMLIntAttr(nsGkAtoms::rowspan, aRowSpan, aError);
+ SetUnsignedIntAttr(nsGkAtoms::rowspan, aRowSpan, 1, aError);
}
//already_AddRefed<nsDOMTokenList> Headers() const;
void GetHeaders(DOMString& aHeaders)
{
GetHTMLAttr(nsGkAtoms::headers, aHeaders);
}
void SetHeaders(const nsAString& aHeaders, ErrorResult& aError)
{
--- a/testing/web-platform/meta/html/dom/reflection-tabular.html.ini
+++ b/testing/web-platform/meta/html/dom/reflection-tabular.html.ini
@@ -1,485 +1,14 @@
[reflection-tabular.html]
type: testharness
- [table.tabIndex: setAttribute() to object "3" followed by getAttribute()]
- expected: FAIL
-
- [table.tabIndex: setAttribute() to object "3" followed by IDL get]
- expected: FAIL
-
- [table.sortable: typeof IDL attribute]
- expected: FAIL
-
- [table.sortable: IDL get with DOM attribute unset]
- expected: FAIL
-
- [table.sortable: setAttribute() to "" followed by IDL get]
- expected: FAIL
-
- [table.sortable: setAttribute() to " foo " followed by IDL get]
- expected: FAIL
-
- [table.sortable: setAttribute() to undefined followed by IDL get]
- expected: FAIL
-
- [table.sortable: setAttribute() to null followed by IDL get]
- expected: FAIL
-
- [table.sortable: setAttribute() to 7 followed by IDL get]
- expected: FAIL
-
- [table.sortable: setAttribute() to 1.5 followed by IDL get]
- expected: FAIL
-
- [table.sortable: setAttribute() to true followed by IDL get]
- expected: FAIL
-
- [table.sortable: setAttribute() to false followed by IDL get]
- expected: FAIL
-
- [table.sortable: setAttribute() to object "[object Object\]" followed by IDL get]
- expected: FAIL
-
- [table.sortable: setAttribute() to NaN followed by IDL get]
- expected: FAIL
-
- [table.sortable: setAttribute() to Infinity followed by IDL get]
- expected: FAIL
-
- [table.sortable: setAttribute() to -Infinity followed by IDL get]
- expected: FAIL
-
- [table.sortable: setAttribute() to "\\0" followed by IDL get]
- expected: FAIL
-
- [table.sortable: setAttribute() to object "test-toString" followed by IDL get]
- expected: FAIL
-
- [table.sortable: setAttribute() to object "test-valueOf" followed by IDL get]
- expected: FAIL
-
- [table.sortable: setAttribute() to "sortable" followed by IDL get]
- expected: FAIL
-
- [table.sortable: IDL set to "" followed by hasAttribute()]
- expected: FAIL
-
- [table.sortable: IDL set to "" followed by IDL get]
- expected: FAIL
-
- [table.sortable: IDL set to " foo " followed by IDL get]
- expected: FAIL
-
- [table.sortable: IDL set to undefined followed by hasAttribute()]
- expected: FAIL
-
- [table.sortable: IDL set to undefined followed by IDL get]
- expected: FAIL
-
- [table.sortable: IDL set to null followed by hasAttribute()]
- expected: FAIL
-
- [table.sortable: IDL set to null followed by IDL get]
- expected: FAIL
-
- [table.sortable: IDL set to 7 followed by IDL get]
- expected: FAIL
-
- [table.sortable: IDL set to 1.5 followed by IDL get]
- expected: FAIL
-
- [table.sortable: IDL set to false followed by hasAttribute()]
- expected: FAIL
-
- [table.sortable: IDL set to object "[object Object\]" followed by IDL get]
- expected: FAIL
-
- [table.sortable: IDL set to NaN followed by hasAttribute()]
- expected: FAIL
-
- [table.sortable: IDL set to NaN followed by IDL get]
- expected: FAIL
-
- [table.sortable: IDL set to Infinity followed by IDL get]
- expected: FAIL
-
- [table.sortable: IDL set to -Infinity followed by IDL get]
- expected: FAIL
-
- [table.sortable: IDL set to "\\0" followed by IDL get]
- expected: FAIL
-
- [table.sortable: IDL set to object "test-toString" followed by IDL get]
- expected: FAIL
-
- [table.sortable: IDL set to object "test-valueOf" followed by IDL get]
- expected: FAIL
-
- [caption.tabIndex: setAttribute() to object "3" followed by getAttribute()]
- expected: FAIL
-
- [caption.tabIndex: setAttribute() to object "3" followed by IDL get]
- expected: FAIL
-
- [colgroup.tabIndex: setAttribute() to object "3" followed by getAttribute()]
- expected: FAIL
-
- [colgroup.tabIndex: setAttribute() to object "3" followed by IDL get]
- expected: FAIL
-
- [colgroup.span: setAttribute() to 2147483647 followed by IDL get]
- expected: FAIL
-
- [colgroup.span: IDL set to 0 must throw INDEX_SIZE_ERR]
- expected: FAIL
-
- [colgroup.span: IDL set to 2147483647 followed by IDL get]
- expected: FAIL
-
- [col.tabIndex: setAttribute() to object "3" followed by getAttribute()]
- expected: FAIL
-
- [col.tabIndex: setAttribute() to object "3" followed by IDL get]
- expected: FAIL
-
- [col.span: setAttribute() to 2147483647 followed by IDL get]
- expected: FAIL
-
- [col.span: IDL set to 0 must throw INDEX_SIZE_ERR]
- expected: FAIL
-
- [col.span: IDL set to 2147483647 followed by IDL get]
- expected: FAIL
-
- [tbody.tabIndex: setAttribute() to object "3" followed by getAttribute()]
- expected: FAIL
-
- [tbody.tabIndex: setAttribute() to object "3" followed by IDL get]
- expected: FAIL
-
- [thead.tabIndex: setAttribute() to object "3" followed by getAttribute()]
- expected: FAIL
-
- [thead.tabIndex: setAttribute() to object "3" followed by IDL get]
- expected: FAIL
-
- [tfoot.tabIndex: setAttribute() to object "3" followed by getAttribute()]
- expected: FAIL
-
- [tfoot.tabIndex: setAttribute() to object "3" followed by IDL get]
- expected: FAIL
-
- [tr.tabIndex: setAttribute() to object "3" followed by getAttribute()]
- expected: FAIL
-
- [tr.tabIndex: setAttribute() to object "3" followed by IDL get]
- expected: FAIL
-
- [td.tabIndex: setAttribute() to object "3" followed by getAttribute()]
- expected: FAIL
-
- [td.tabIndex: setAttribute() to object "3" followed by IDL get]
- expected: FAIL
-
- [td.colSpan: setAttribute() to 2147483647 followed by IDL get]
- expected: FAIL
-
- [td.colSpan: IDL set to 2147483647 followed by IDL get]
- expected: FAIL
-
- [td.rowSpan: setAttribute() to 2147483647 followed by IDL get]
- expected: FAIL
-
- [td.rowSpan: IDL set to 2147483647 followed by IDL get]
- expected: FAIL
-
- [th.tabIndex: setAttribute() to object "3" followed by getAttribute()]
- expected: FAIL
-
- [th.tabIndex: setAttribute() to object "3" followed by IDL get]
- expected: FAIL
-
- [th.colSpan: setAttribute() to 2147483647 followed by IDL get]
- expected: FAIL
-
- [th.colSpan: IDL set to 2147483647 followed by IDL get]
- expected: FAIL
-
- [th.rowSpan: setAttribute() to 2147483647 followed by IDL get]
- expected: FAIL
-
- [th.rowSpan: IDL set to 2147483647 followed by IDL get]
- expected: FAIL
-
- [th.sorted: typeof IDL attribute]
- expected: FAIL
-
- [th.sorted: IDL get with DOM attribute unset]
- expected: FAIL
-
- [th.sorted: setAttribute() to "" followed by IDL get]
- expected: FAIL
-
- [th.sorted: setAttribute() to " \\0\\x01\\x02\\x03\\x04\\x05\\x06\\x07 \\b\\t\\n\\v\\f\\r\\x0e\\x0f \\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17 \\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f foo " followed by IDL get]
- expected: FAIL
-
- [th.sorted: setAttribute() to undefined followed by IDL get]
- expected: FAIL
-
- [th.sorted: setAttribute() to 7 followed by IDL get]
- expected: FAIL
-
- [th.sorted: setAttribute() to 1.5 followed by IDL get]
- expected: FAIL
-
- [th.sorted: setAttribute() to true followed by IDL get]
- expected: FAIL
-
- [th.sorted: setAttribute() to false followed by IDL get]
- expected: FAIL
-
- [th.sorted: setAttribute() to object "[object Object\]" followed by IDL get]
- expected: FAIL
-
- [th.sorted: setAttribute() to NaN followed by IDL get]
- expected: FAIL
-
- [th.sorted: setAttribute() to Infinity followed by IDL get]
- expected: FAIL
-
- [th.sorted: setAttribute() to -Infinity followed by IDL get]
- expected: FAIL
-
- [th.sorted: setAttribute() to "\\0" followed by IDL get]
- expected: FAIL
-
- [th.sorted: setAttribute() to null followed by IDL get]
- expected: FAIL
-
- [th.sorted: setAttribute() to object "test-toString" followed by IDL get]
- expected: FAIL
-
- [th.sorted: setAttribute() to object "test-valueOf" followed by IDL get]
- expected: FAIL
-
- [th.sorted: IDL set to "" followed by getAttribute()]
- expected: FAIL
-
- [th.sorted: IDL set to " \\0\\x01\\x02\\x03\\x04\\x05\\x06\\x07 \\b\\t\\n\\v\\f\\r\\x0e\\x0f \\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17 \\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f foo " followed by getAttribute()]
- expected: FAIL
-
- [th.sorted: IDL set to undefined followed by getAttribute()]
- expected: FAIL
-
- [th.sorted: IDL set to undefined followed by IDL get]
- expected: FAIL
-
- [th.sorted: IDL set to 7 followed by getAttribute()]
- expected: FAIL
-
- [th.sorted: IDL set to 7 followed by IDL get]
- expected: FAIL
-
- [th.sorted: IDL set to 1.5 followed by getAttribute()]
- expected: FAIL
-
- [th.sorted: IDL set to 1.5 followed by IDL get]
- expected: FAIL
-
- [th.sorted: IDL set to true followed by getAttribute()]
- expected: FAIL
-
- [th.sorted: IDL set to true followed by IDL get]
- expected: FAIL
-
- [th.sorted: IDL set to false followed by getAttribute()]
- expected: FAIL
-
- [th.sorted: IDL set to false followed by IDL get]
- expected: FAIL
-
- [th.sorted: IDL set to object "[object Object\]" followed by getAttribute()]
- expected: FAIL
-
- [th.sorted: IDL set to object "[object Object\]" followed by IDL get]
- expected: FAIL
-
- [th.sorted: IDL set to NaN followed by getAttribute()]
- expected: FAIL
-
- [th.sorted: IDL set to NaN followed by IDL get]
- expected: FAIL
-
- [th.sorted: IDL set to Infinity followed by getAttribute()]
- expected: FAIL
-
- [th.sorted: IDL set to Infinity followed by IDL get]
- expected: FAIL
-
- [th.sorted: IDL set to -Infinity followed by getAttribute()]
- expected: FAIL
-
- [th.sorted: IDL set to -Infinity followed by IDL get]
- expected: FAIL
-
- [th.sorted: IDL set to "\\0" followed by getAttribute()]
- expected: FAIL
-
- [th.sorted: IDL set to null followed by getAttribute()]
- expected: FAIL
-
- [th.sorted: IDL set to null followed by IDL get]
- expected: FAIL
-
- [th.sorted: IDL set to object "test-toString" followed by getAttribute()]
- expected: FAIL
-
- [th.sorted: IDL set to object "test-toString" followed by IDL get]
- expected: FAIL
-
- [th.sorted: IDL set to object "test-valueOf" followed by IDL get]
- expected: FAIL
-
- [td.colSpan: IDL set to 2147483648 followed by getAttribute()]
- expected: FAIL
-
- [td.colSpan: IDL set to 4294967295 followed by getAttribute()]
- expected: FAIL
-
- [td.rowSpan: IDL set to 2147483648 followed by getAttribute()]
- expected: FAIL
-
- [td.rowSpan: IDL set to 4294967295 followed by getAttribute()]
- expected: FAIL
-
- [th.colSpan: IDL set to 2147483648 followed by getAttribute()]
- expected: FAIL
-
- [th.colSpan: IDL set to 4294967295 followed by getAttribute()]
- expected: FAIL
-
- [th.rowSpan: IDL set to 2147483648 followed by getAttribute()]
- expected: FAIL
-
- [th.rowSpan: IDL set to 4294967295 followed by getAttribute()]
- expected: FAIL
-
- [td.colSpan: setAttribute() to 0 followed by IDL get]
- expected: FAIL
-
- [td.colSpan: setAttribute() to "-0" followed by IDL get]
- expected: FAIL
-
- [td.colSpan: setAttribute() to "0" followed by IDL get]
- expected: FAIL
-
- [td.colSpan: IDL set to 0 followed by IDL get]
- expected: FAIL
-
- [td.colSpan: IDL set to "-0" followed by IDL get]
- expected: FAIL
-
- [th.colSpan: setAttribute() to 0 followed by IDL get]
- expected: FAIL
-
- [th.colSpan: setAttribute() to "-0" followed by IDL get]
- expected: FAIL
-
- [th.colSpan: setAttribute() to "0" followed by IDL get]
- expected: FAIL
-
- [th.colSpan: IDL set to 0 followed by IDL get]
- expected: FAIL
-
- [th.colSpan: IDL set to "-0" followed by IDL get]
- expected: FAIL
-
[colgroup.span: setAttribute() to 2147483647]
expected: FAIL
[colgroup.span: IDL set to 2147483647]
expected: FAIL
[col.span: setAttribute() to 2147483647]
expected: FAIL
[col.span: IDL set to 2147483647]
expected: FAIL
- [td.colSpan: setAttribute() to 0]
- expected: FAIL
-
- [td.colSpan: setAttribute() to 2147483647]
- expected: FAIL
-
- [td.colSpan: setAttribute() to "-0"]
- expected: FAIL
-
- [td.colSpan: setAttribute() to "0"]
- expected: FAIL
-
- [td.colSpan: IDL set to 0]
- expected: FAIL
-
- [td.colSpan: IDL set to 2147483647]
- expected: FAIL
-
- [td.colSpan: IDL set to "-0"]
- expected: FAIL
-
- [td.colSpan: IDL set to 2147483648]
- expected: FAIL
-
- [td.colSpan: IDL set to 4294967295]
- expected: FAIL
-
- [td.rowSpan: setAttribute() to 2147483647]
- expected: FAIL
-
- [td.rowSpan: IDL set to 2147483647]
- expected: FAIL
-
- [td.rowSpan: IDL set to 2147483648]
- expected: FAIL
-
- [td.rowSpan: IDL set to 4294967295]
- expected: FAIL
-
- [th.colSpan: setAttribute() to 0]
- expected: FAIL
-
- [th.colSpan: setAttribute() to 2147483647]
- expected: FAIL
-
- [th.colSpan: setAttribute() to "-0"]
- expected: FAIL
-
- [th.colSpan: setAttribute() to "0"]
- expected: FAIL
-
- [th.colSpan: IDL set to 0]
- expected: FAIL
-
- [th.colSpan: IDL set to 2147483647]
- expected: FAIL
-
- [th.colSpan: IDL set to "-0"]
- expected: FAIL
-
- [th.colSpan: IDL set to 2147483648]
- expected: FAIL
-
- [th.colSpan: IDL set to 4294967295]
- expected: FAIL
-
- [th.rowSpan: setAttribute() to 2147483647]
- expected: FAIL
-
- [th.rowSpan: IDL set to 2147483647]
- expected: FAIL
-
- [th.rowSpan: IDL set to 2147483648]
- expected: FAIL
-
- [th.rowSpan: IDL set to 4294967295]
- expected: FAIL
-
--- a/testing/web-platform/tests/html/dom/elements-tabular.js
+++ b/testing/web-platform/tests/html/dom/elements-tabular.js
@@ -63,18 +63,18 @@ var tabularElements = {
align: "string",
ch: {type: "string", domAttrName: "char"},
chOff: {type: "string", domAttrName: "charoff"},
vAlign: "string",
bgColor: {type: "string", treatNullAsEmptyString: true},
},
td: {
// HTMLTableCellElement (Conforming)
- colSpan: {type: "unsigned long", defaultVal: 1},
- rowSpan: {type: "unsigned long", defaultVal: 1},
+ colSpan: {type: "clamped unsigned long", defaultVal: 1, min: 1, max: 1000},
+ rowSpan: {type: "clamped unsigned long", defaultVal: 1, min: 0, max: 65534},
headers: "settable tokenlist",
scope: {type: "enum", keywords: ["row", "col", "rowgroup", "colgroup"]},
abbr: "string",
// HTMLTableCellElement (Obsolete)
align: "string",
axis: "string",
height: "string",
@@ -82,18 +82,18 @@ var tabularElements = {
ch: {type: "string", domAttrName: "char"},
chOff: {type: "string", domAttrName: "charoff"},
noWrap: "boolean",
vAlign: "string",
bgColor: {type: "string", treatNullAsEmptyString: true},
},
th: {
// HTMLTableCellElement (Conforming)
- colSpan: {type: "unsigned long", defaultVal: 1},
- rowSpan: {type: "unsigned long", defaultVal: 1},
+ colSpan: {type: "clamped unsigned long", defaultVal: 1, min: 1, max: 1000},
+ rowSpan: {type: "clamped unsigned long", defaultVal: 1, min: 0, max: 65534},
headers: "settable tokenlist",
scope: {type: "enum", keywords: ["row", "col", "rowgroup", "colgroup"]},
abbr: "string",
// HTMLTableCellElement (Obsolete)
align: "string",
axis: "string",
height: "string",
--- a/testing/web-platform/tests/html/dom/reflection.js
+++ b/testing/web-platform/tests/html/dom/reflection.js
@@ -450,16 +450,47 @@ ReflectionTests.typeMap = {
return null;
}
return parsed;
},
"idlTests": [0, 1, maxInt, maxInt + 1, maxUnsigned],
"idlDomExpected": [null, 1, maxInt, null, null]
},
/**
+ * "If a reflecting IDL attribute has an unsigned integer type (unsigned
+ * long) that is clamped to the range [min, max], then on getting, the
+ * content attribute must first be parsed according to the rules for
+ * parsing non-negative integers, and if that is successful, and the value
+ * is between min and max inclusive, the resulting value must be returned.
+ * If it fails, the default value must be returned. If it succeeds but the
+ * value is less than min, min must be returned. If it succeeds but the
+ * value is greater than max, max must be returned. On setting, it behaves
+ * the same as a regular reflected unsigned integer."
+ *
+ * The data object passed to reflects must contain the keys defaultVal,
+ * min, and max. As with enum, domExpected is generated later once we have
+ * access to the min and max.
+ */
+ "clamped unsigned long": {
+ "jsType": "number",
+ "domTests": [minInt - 1, minInt, -36, -1, 0, 1, maxInt,
+ maxInt + 1, maxUnsigned, maxUnsigned + 1, "", "-1", "-0", "0", "1",
+ "\u00097", "\u000B7", "\u000C7", "\u00207", "\u00A07", "\uFEFF7",
+ "\u000A7", "\u000D7", "\u20287", "\u20297", "\u16807", "\u180E7",
+ "\u20007", "\u20017", "\u20027", "\u20037", "\u20047", "\u20057",
+ "\u20067", "\u20077", "\u20087", "\u20097", "\u200A7", "\u202F7",
+ "\u30007",
+ " " + binaryString + " foo ", undefined, 1.5, true, false,
+ {"test": 6}, NaN, +Infinity, -Infinity, "\0",
+ {toString:function() {return 2;}, valueOf: null},
+ {valueOf:function() {return 3;}}],
+ "idlTests": [0, 1, 257, maxInt, "-0", maxInt + 1, maxUnsigned],
+ "idlDomExpected": [0, 1, 257, maxInt, 0, null, null],
+ },
+ /**
* "If a reflecting IDL attribute is a floating point number type (double),
* then, on getting, the content attribute must be parsed according to the
* rules for parsing floating point number values, and if that is
* successful, the resulting value must be returned. If, on the other hand,
* it fails, or if the attribute is absent, the default value must be
* returned instead, or 0.0 if there is no default value. On setting, the
* given value must be converted to the best representation of the number
* as a floating point number and then that string must be used as the new
@@ -676,16 +707,64 @@ ReflectionTests.reflects = function(data
if ("treatNullAsEmptyString" in data) {
for (var i = 0; i < idlTests.length; i++) {
if (idlTests[i] === null) {
idlDomExpected[i] = idlIdlExpected[i] = "";
}
}
}
break;
+
+ case "clamped unsigned long":
+ [data.min - 1, data.min, data.max, data.max + 1].forEach(function(val) {
+ if (domTests.indexOf(val) == -1) {
+ domTests.push(val);
+ }
+ if (idlTests.indexOf(val) == -1 && 0 <= val && val <= maxUnsigned) {
+ idlTests.push(val);
+ if (typeof val != "number") {
+ val = ReflectionTests.parseNonneg(val);
+ }
+ idlDomExpected.push(val > maxInt ? null : val);
+ }
+ });
+
+ // Rewrite expected values
+ domExpected = domTests.map(function(val) {
+ var parsed = ReflectionTests.parseNonneg(String(val));
+ if (parsed === false) {
+ return defaultVal;
+ }
+ if (parsed < data.min) {
+ return data.min;
+ }
+ if (parsed > data.max) {
+ return data.max;
+ }
+ return parsed;
+ });
+ idlIdlExpected = idlTests.map(function(val) {
+ if (typeof val != "number") {
+ val = ReflectionTests.parseNonneg(val);
+ }
+ if (val < 0 || val > maxUnsigned) {
+ throw "Test bug: val should be an unsigned long";
+ }
+ if (val > maxInt) {
+ return defaultVal;
+ }
+ if (val < data.min) {
+ return data.min;
+ }
+ if (val > data.max) {
+ return data.max;
+ }
+ return val;
+ });
+ break;
}
if (domObj.tagName.toLowerCase() == "canvas" && (domName == "width" || domName == "height")) {
// Opera tries to allocate a canvas with the given width and height, so
// it OOMs when given excessive sizes. This is permissible under the
// hardware-limitations clause, so cut out those checks. TODO: Must be
// a way to make this more succinct.
domTests = domTests.filter(function(element, index, array) { return domExpected[index] < 1000; });
domExpected = domExpected.filter(function(element, index, array) { return element < 1000; });