/** * reflect.js is a collection of methods to test HTML attribute reflection. * Each of attribute is reflected differently, depending on various parameters, * see: * http://www.whatwg.org/html/#reflecting-content-attributes-in-idl-attributes * * Do not forget to add these line at the beginning of each new reflect* method: * ok(attr in element, attr + " should be an IDL attribute of this element"); * is(typeof element[attr], <type>, attr + " IDL attribute should be a <type>");
*/
/** * Checks that a given attribute is correctly reflected as a string. * * @param aParameters Object object containing the parameters, which are: * - element Element node to test * - attribute String name of the attribute * OR * attribute Object object containing two attributes, 'content' and 'idl' * - otherValues Array [optional] other values to test in addition of the default ones * - extendedAttributes Object object which can have 'TreatNullAs': "EmptyString"
*/ function reflectString(aParameters) { var element = aParameters.element; var contentAttr = typeof aParameters.attribute === "string"
? aParameters.attribute
: aParameters.attribute.content; var idlAttr = typeof aParameters.attribute === "string"
? aParameters.attribute
: aParameters.attribute.idl; var otherValues =
aParameters.otherValues !== undefined ? aParameters.otherValues : []; var treatNullAs = aParameters.extendedAttributes
? aParameters.extendedAttributes.TreatNullAs
: null;
ok(
idlAttr in element,
idlAttr + " should be an IDL attribute of this element"
);
is( typeof element[idlAttr], "string", "'" + idlAttr + "' IDL attribute should be a string"
);
// Tests when the attribute isn't set.
is(
element.getAttribute(contentAttr), null, "When not set, the content attribute should be null."
);
is(
element[idlAttr], "", "When not set, the IDL attribute should return the empty string"
);
/** * TODO: as long as null stringification doesn't follow the WebIDL * specifications, don't add it to the loop below and keep it here.
*/
element.setAttribute(contentAttr, null);
is(
element.getAttribute(contentAttr), "null", "null should have been stringified to 'null' for '" + contentAttr + "'"
);
is(
element[idlAttr], "null", "null should have been stringified to 'null' for '" + idlAttr + "'"
);
element.removeAttribute(contentAttr);
element[idlAttr] = null; if (treatNullAs == "EmptyString") {
is(
element.getAttribute(contentAttr), "", "null should have been stringified to '' for '" + contentAttr + "'"
);
is(
element[idlAttr], "", "null should have been stringified to '' for '" + idlAttr + "'"
);
} else {
is(
element.getAttribute(contentAttr), "null", "null should have been stringified to 'null' for '" + contentAttr + "'"
);
is(
element[idlAttr], "null", "null should have been stringified to 'null' for '" + contentAttr + "'"
);
}
element.removeAttribute(contentAttr);
stringsToTest.forEach(function ([v, r]) {
element.setAttribute(contentAttr, v);
is(
element[idlAttr],
r, "IDL attribute '" +
idlAttr + "' should return the value it has been set to."
);
is(
element.getAttribute(contentAttr),
r, "Content attribute '" +
contentAttr + "'should return the value it has been set to."
);
element.removeAttribute(contentAttr);
element[idlAttr] = v;
is(
element[idlAttr],
r, "IDL attribute '" +
idlAttr + "' should return the value it has been set to."
);
is(
element.getAttribute(contentAttr),
r, "Content attribute '" +
contentAttr + "' should return the value it has been set to."
);
element.removeAttribute(contentAttr);
});
// Tests after removeAttribute() is called. Should be equivalent with not set.
is(
element.getAttribute(contentAttr), null, "When not set, the content attribute should be null."
);
is(
element[idlAttr], "", "When not set, the IDL attribute should return the empty string"
);
}
/** * Checks that a given attribute name for a given element is correctly reflected * as an unsigned int. * * @param aParameters Object object containing the parameters, which are: * - element Element node to test on * - attribute String name of the attribute * - nonZero Boolean whether the attribute should be non-null * - defaultValue Integer [optional] default value, if different from the default one
*/ function reflectUnsignedInt(aParameters) { var element = aParameters.element; var attr = aParameters.attribute; var nonZero = aParameters.nonZero; var defaultValue = aParameters.defaultValue; var fallback = aParameters.fallback;
if (defaultValue === undefined) { if (nonZero) {
defaultValue = 1;
} else {
defaultValue = 0;
}
}
if (fallback === undefined) {
fallback = false;
}
ok(attr in element, attr + " should be an IDL attribute of this element");
is( typeof element[attr], "number",
attr + " IDL attribute should be a number"
);
// Check default value.
is(element[attr], defaultValue, "default value should be " + defaultValue);
ok(!element.hasAttribute(attr), attr + " shouldn't be present");
var values = [1, 3, 42, 2147483647];
for (var value of values) {
element[attr] = value;
is(element[attr], value, "." + attr + " should be equals " + value);
is(
element.getAttribute(attr),
String(value), "@" + attr + " should be equals " + value
);
element.setAttribute(attr, value);
is(element[attr], value, "." + attr + " should be equals " + value);
is(
element.getAttribute(attr),
String(value), "@" + attr + " should be equals " + value
);
}
// -3000000000 is equivalent to 1294967296 when using the IDL attribute.
element[attr] = -3000000000;
is(element[attr], 1294967296, "." + attr + " should be equals to 1294967296");
is(
element.getAttribute(attr), "1294967296", "@" + attr + " should be equals to 1294967296"
);
// When setting the content attribute, it's a string so it will be invalid.
element.setAttribute(attr, -3000000000);
is(
element.getAttribute(attr), "-3000000000", "@" + attr + " should be equals to " + -3000000000
);
is(
element[attr],
defaultValue, "." + attr + " should be equals to " + defaultValue
);
// When interpreted as unsigned 32-bit integers, all of these fall between // 2^31 and 2^32 - 1, so per spec they return the default value. var nonValidValues = [-2147483648, -1, 3147483647];
for (var value of nonValidValues) {
element[attr] = value;
is(
element.getAttribute(attr),
String(defaultValue), "@" + attr + " should be equals to " + defaultValue
);
is(
element[attr],
defaultValue, "." + attr + " should be equals to " + defaultValue
);
}
for (var values of nonValidValues) {
element.setAttribute(attr, values[0]);
is(
element.getAttribute(attr),
String(values[0]), "@" + attr + " should be equals to " + values[0]
);
is(
element[attr],
defaultValue, "." + attr + " should be equals to " + defaultValue
);
}
// Setting to 0 should throw an error if nonZero is true. var caught = false; try {
element[attr] = 0;
} catch (e) {
caught = true;
is(e.name, "IndexSizeError", "exception should be IndexSizeError");
is(
e.code,
DOMException.INDEX_SIZE_ERR, "exception code should be INDEX_SIZE_ERR"
);
}
if (nonZero && !fallback) {
ok(caught, "an exception should have been caught");
} else {
ok(!caught, "no exception should have been caught");
}
// If 0 is set in @attr, it will be ignored when calling .attr.
element.setAttribute(attr, "0");
is(element.getAttribute(attr), "0", "@" + attr + " should be equals to 0"); if (nonZero) {
is(
element[attr],
defaultValue, "." + attr + " should be equals to " + defaultValue
);
} else {
is(element[attr], 0, "." + attr + " should be equals to 0");
}
}
/** * Checks that a given attribute is correctly reflected as limited to known * values enumerated attribute. * * @param aParameters Object object containing the parameters, which are: * - element Element node to test on * - attribute String name of the attribute * OR * attribute Object object containing two attributes, 'content' and 'idl' * - validValues Array valid values we support * - invalidValues Array invalid values * - defaultValue String [optional] default value when no valid value is set * OR * defaultValue Object [optional] object containing two attributes, 'invalid' and 'missing' * - unsupportedValues Array [optional] valid values we do not support * - nullable boolean [optional] whether the attribute is nullable
*/ function reflectLimitedEnumerated(aParameters) { var element = aParameters.element; var contentAttr = typeof aParameters.attribute === "string"
? aParameters.attribute
: aParameters.attribute.content; var idlAttr = typeof aParameters.attribute === "string"
? aParameters.attribute
: aParameters.attribute.idl; var validValues = aParameters.validValues; var invalidValues = aParameters.invalidValues; var defaultValueInvalid =
aParameters.defaultValue === undefined
? ""
: typeof aParameters.defaultValue === "string"
? aParameters.defaultValue
: aParameters.defaultValue.invalid; var defaultValueMissing =
aParameters.defaultValue === undefined
? ""
: typeof aParameters.defaultValue === "string"
? aParameters.defaultValue
: aParameters.defaultValue.missing; var unsupportedValues =
aParameters.unsupportedValues !== undefined
? aParameters.unsupportedValues
: []; var nullable = aParameters.nullable;
ok(
idlAttr in element,
idlAttr + " should be an IDL attribute of this element"
); if (nullable) { // The missing value default is null, which is typeof == "object"
is( typeof element[idlAttr], "object", "'" +
idlAttr + "' IDL attribute should be null, which has typeof == object"
);
is(
element[idlAttr], null, "'" + idlAttr + "' IDL attribute should be null"
);
} else {
is( typeof element[idlAttr], "string", "'" + idlAttr + "' IDL attribute should be a string"
);
}
if (nullable) {
element.setAttribute(contentAttr, "something"); // Now it will be a string
is( typeof element[idlAttr], "string", "'" + idlAttr + "' IDL attribute should be a string"
);
}
// Explicitly check the default value.
element.removeAttribute(contentAttr);
is(
element[idlAttr],
defaultValueMissing, "When no attribute is set, the value should be the default value."
);
// Check valid values.
validValues.forEach(function (v) {
element.setAttribute(contentAttr, v);
is(
element[idlAttr],
v, "'" + v + "' should be accepted as a valid value for " + idlAttr
);
is(
element.getAttribute(contentAttr),
v, "Content attribute should return the value it has been set to."
);
element.removeAttribute(contentAttr);
element.setAttribute(contentAttr, v.toUpperCase());
is(
element[idlAttr],
v, "Enumerated attributes should be case-insensitive."
);
is(
element.getAttribute(contentAttr),
v.toUpperCase(), "Content attribute should not be lower-cased."
);
element.removeAttribute(contentAttr);
element[idlAttr] = v;
is(
element[idlAttr],
v, "'" + v + "' should be accepted as a valid value for " + idlAttr
);
is(
element.getAttribute(contentAttr),
v, "Content attribute should return the value it has been set to."
);
element.removeAttribute(contentAttr);
element[idlAttr] = v.toUpperCase();
is(
element[idlAttr],
v, "Enumerated attributes should be case-insensitive."
);
is(
element.getAttribute(contentAttr),
v.toUpperCase(), "Content attribute should not be lower-cased."
);
element.removeAttribute(contentAttr);
});
// Check invalid values.
invalidValues.forEach(function (v) {
element.setAttribute(contentAttr, v);
is(
element[idlAttr],
defaultValueInvalid, "When the content attribute is set to an invalid value, the default value should be returned."
);
is(
element.getAttribute(contentAttr),
v, "Content attribute should not have been changed."
);
element.removeAttribute(contentAttr);
element[idlAttr] = v;
is(
element[idlAttr],
defaultValueInvalid, "When the value is set to an invalid value, the default value should be returned."
);
is(
element.getAttribute(contentAttr),
v, "Content attribute should not have been changed."
);
element.removeAttribute(contentAttr);
});
// Check valid values we currently do not support. // Basically, it's like the checks for the valid values but with some todo's.
unsupportedValues.forEach(function (v) {
element.setAttribute(contentAttr, v);
todo_is(
element[idlAttr],
v, "'" + v + "' should be accepted as a valid value for " + idlAttr
);
is(
element.getAttribute(contentAttr),
v, "Content attribute should return the value it has been set to."
);
element.removeAttribute(contentAttr);
element.setAttribute(contentAttr, v.toUpperCase());
todo_is(
element[idlAttr],
v, "Enumerated attributes should be case-insensitive."
);
is(
element.getAttribute(contentAttr),
v.toUpperCase(), "Content attribute should not be lower-cased."
);
element.removeAttribute(contentAttr);
element[idlAttr] = v;
todo_is(
element[idlAttr],
v, "'" + v + "' should be accepted as a valid value for " + idlAttr
);
is(
element.getAttribute(contentAttr),
v, "Content attribute should return the value it has been set to."
);
element.removeAttribute(contentAttr);
element[idlAttr] = v.toUpperCase();
todo_is(
element[idlAttr],
v, "Enumerated attributes should be case-insensitive."
);
is(
element.getAttribute(contentAttr),
v.toUpperCase(), "Content attribute should not be lower-cased."
);
element.removeAttribute(contentAttr);
});
if (nullable) {
is(
defaultValueMissing, null, "Missing default value should be null for nullable attributes"
);
ok(validValues.length, "We better have at least one valid value");
element.setAttribute(contentAttr, validValues[0]);
ok(
element.hasAttribute(contentAttr), "Should have content attribute: we just set it"
);
element[idlAttr] = null;
ok(
!element.hasAttribute(contentAttr), "Should have removed content attribute"
);
}
}
/** * Checks that a given attribute is correctly reflected as a boolean. * * @param aParameters Object object containing the parameters, which are: * - element Element node to test on * - attribute String name of the attribute * OR * attribute Object object containing two attributes, 'content' and 'idl'
*/ function reflectBoolean(aParameters) { var element = aParameters.element; var contentAttr = typeof aParameters.attribute === "string"
? aParameters.attribute
: aParameters.attribute.content; var idlAttr = typeof aParameters.attribute === "string"
? aParameters.attribute
: aParameters.attribute.idl;
ok(
idlAttr in element,
idlAttr + " should be an IDL attribute of this element"
);
is( typeof element[idlAttr], "boolean",
idlAttr + " IDL attribute should be a boolean"
);
// Tests when the attribute isn't set.
is(
element.getAttribute(contentAttr), null, "When not set, the content attribute should be null."
);
is(
element[idlAttr], false, "When not set, the IDL attribute should return false"
);
valuesToTest.forEach(function (v) {
element.setAttribute(contentAttr, v.value);
is(
element[idlAttr], true, "IDL attribute should return always return 'true' if the content attribute has been set"
);
is(
element.getAttribute(contentAttr),
v.stringified, "Content attribute should return the stringified value it has been set to."
);
element.removeAttribute(contentAttr);
element[idlAttr] = v.value;
is(element[idlAttr], v.result, "IDL attribute should return " + v.result);
is(
element.getAttribute(contentAttr),
v.result ? "" : null,
v.result
? "Content attribute should return the empty string."
: "Content attribute should return null."
);
is(
element.hasAttribute(contentAttr),
v.result,
v.result
? contentAttr + " should not be present"
: contentAttr + " should be present"
);
element.removeAttribute(contentAttr);
});
// Tests after removeAttribute() is called. Should be equivalent with not set.
is(
element.getAttribute(contentAttr), null, "When not set, the content attribute should be null."
);
is(
element[contentAttr], false, "When not set, the IDL attribute should return false"
);
}
/** * Checks that a given attribute name for a given element is correctly reflected * as an signed integer. * * @param aParameters Object object containing the parameters, which are: * - element Element node to test on * - attribute String name of the attribute * - nonNegative Boolean true if the attribute is limited to 'non-negative numbers', false otherwise * - defaultValue Integer [optional] default value, if one exists
*/ function reflectInt(aParameters) { // Expected value returned by .getAttribute() when |value| has been previously passed to .setAttribute(). function expectedGetAttributeResult(value) { return String(value);
}
function stringToInteger(value, nonNegative, defaultValue) { // Parse: Ignore leading whitespace, find [+/-][numbers] var result = /^[ \t\n\f\r]*([\+\-]?[0-9]+)/.exec(value); if (result) { var resultInt = parseInt(result[1], 10); if (
(nonNegative ? 0 : -0x80000000) <= resultInt &&
resultInt <= 0x7fffffff
) { // If the value is within allowed value range for signed/unsigned // integer, return it -- but add 0 to it to convert a possible -0 into // +0, the only zero present in the signed integer range. return resultInt + 0;
}
} return defaultValue;
}
// Expected value returned by .getAttribute(attr) or .attr if |value| has been set via the IDL attribute. function expectedIdlAttributeResult(value) { // This returns the result of calling the ES ToInt32 algorithm on value. return value << 0;
}
var element = aParameters.element; var attr = aParameters.attribute; var nonNegative = aParameters.nonNegative;
ok(attr in element, attr + " should be an IDL attribute of this element");
is( typeof element[attr], "number",
attr + " IDL attribute should be a number"
);
// Check default value.
is(element[attr], defaultValue, "default value should be " + defaultValue);
ok(!element.hasAttribute(attr), attr + " shouldn't be present");
/** * Test various values. * value: The test value that will be set using both setAttribute(value) and * element[attr] = value
*/ var valuesToTest = [ // Test numeric inputs up to max signed integer 0, 1, 55555, 2147483647,
+42, // Test string inputs up to max signed integer "0", "1", "777777", "2147483647", "+42", // Test negative numeric inputs up to min signed integer
-0,
-1,
-3333,
-2147483648, // Test negative string inputs up to min signed integer "-0", "-1", "-222", "-2147483647", "-2147483648", // Test numeric inputs that are outside legal 32 bit signed values
-2147483649,
-3000000000,
-4294967296, 2147483649, 4000000000,
-4294967297, // Test string inputs with extra padding " 1111111", " 23456 ", // Test non-numeric string inputs "", " ", "+", "-", "foo", "+foo", "-foo", "+ foo", "- foo", "+-2", "-+2", "++2", "--2", "hello1234", "1234hello", "444 world 555", "why 567 what", "-3 nots", "2e5", "300e2", "42+-$", "+42foo", "-514not", "\vblah", "0x10FFFF", "-0xABCDEF", // Test decimal numbers 1.2345, 42.0, 3456789.1,
-2.3456,
-6789.12345,
-2147483649.1234, // Test decimal strings "1.2345", "42.0", "3456789.1", "-2.3456", "-6789.12345", "-2147483649.1234", // Test special values
undefined, null,
NaN,
Infinity,
-Infinity,
];
valuesToTest.forEach(function (v) { var intValue = stringToInteger(v, nonNegative, defaultValue);
// Tests after removeAttribute() is called. Should be equivalent with not set.
is(
element.getAttribute(attr), null, "When not set, the content attribute should be null."
);
is(
element[attr],
defaultValue, "When not set, the IDL attribute should return default value."
);
}
/** * Checks that a given attribute is correctly reflected as a url. * * @param aParameters Object object containing the parameters, which are: * - element Element node to test * - attribute String name of the attribute * OR * attribute Object object containing two attributes, 'content' and 'idl'
*/ function reflectURL(aParameters) { var element = aParameters.element; var contentAttr = typeof aParameters.attribute === "string"
? aParameters.attribute
: aParameters.attribute.content; var idlAttr = typeof aParameters.attribute === "string"
? aParameters.attribute
: aParameters.attribute.idl;
element[idlAttr] = "";
is(
element[idlAttr],
document.URL, "Empty string should resolve to document URL"
);
}
Messung V0.5 in Prozent
¤ Dauer der Verarbeitung: 0.30 Sekunden
(vorverarbeitet am 2026-06-08)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.