// This is a bit heavy-weight but hopefully will give values // that compare "better" (without introducing some tolerance) // when the test cases are expanded with more values. return ReflectionTests.parseFloat(String(val));
}
}
};
for (var type in ReflectionTests.typeMap) { var props = ReflectionTests.typeMap[type]; var cast = window[props.jsType[0].toUpperCase() + props.jsType.slice(1)]; if (props.domExpected === undefined) {
props.domExpected = props.domTests.map(cast);
} elseif (typeof props.domExpected == "function") {
props.domExpected = props.domTests.map(props.domExpected);
} if (props.idlTests === undefined) {
props.idlTests = props.domTests;
} if (props.idlDomExpected === undefined) {
props.idlDomExpected = props.idlTests.map(cast);
} elseif (typeof props.idlDomExpected == "function") {
props.idlDomExpected = props.idlTests.map(props.idlDomExpected);
} if (props.idlIdlExpected === undefined) {
props.idlIdlExpected = props.idlDomExpected;
} elseif (typeof props.idlIdlExpected == "function") {
props.idlIdlExpected = props.idlTests.map(props.idlIdlExpected);
}
}
/** *TeststhattheJavaScriptattributenamedidlNameontheobjectidlObj *reflectstheDOMattributenameddomNameondomObj.Thedataargumentisan *objectthatmustcontainatleastonekey,"type",whichcontainsthe *expectedtypeoftheIDLattribute("string","enum",etc.).The"comment" *keywilladdaparenthesizedcommentinthetypeinfoifthere'satest *failure,toindicatethatthere'ssomethingspecialabouttheelementyou're *testing(likeithasanattributesettosomevalue).Otherkeysinthe *dataobjectaretype-specific,e.g.,"defaultVal"fornumerictypes.Ifthe *dataobjectisastring,it'sconvertedto{"type":data}.IfidlObjisa *string,wesetidlObj=domObj=document.createElement(idlObj).
*/
ReflectionTests.reflects = function(data, idlName, idlObj, domName, domObj) { // Do some setup first so that getTypeDescription() works in testWrapper() if (typeof data == "string") {
data = {type: data};
} if (domName === undefined) {
domName = idlName;
} if (typeof idlObj == "string") {
idlObj = document.createElement(idlObj);
} if (domObj === undefined) {
domObj = idlObj;
}
// Note: probably a hack? This kind of assumes that the variables here // won't change over the course of the tests, which is wrong, but it's // probably safe enough. Just don't read stuff that will change.
ReflectionHarness.currentTestInfo = {data: data, idlName: idlName, idlObj: idlObj, domName: domName, domObj: domObj};
// If we don't recognize the type, testing is impossible. if (this.typeMap[data.type] === undefined) { if (unimplemented.indexOf(data.type) == -1) {
unimplemented.push(data.type);
} return;
}
var typeInfo = this.typeMap[data.type];
if (typeof data.isNullable == "undefined") {
data.isNullable = false;
}
// Test that typeof idlObj[idlName] is correct. If not, further tests are // probably pointless, so bail out if we're not running conformance tests. var expectedType = data.isNullable && data.defaultVal === null ? "object"
: typeInfo.jsType;
ReflectionHarness.test(function() {
ReflectionHarness.assertEquals(typeof idlObj[idlName], expectedType);
}, "typeof IDL attribute");
if (!ReflectionHarness.conformanceTesting && typeof idlObj[idlName] !== expectedType) { return;
}
// Test default var defaultVal = data.defaultVal; if (defaultVal === undefined) {
defaultVal = typeInfo.defaultVal;
} if ((domObj.localName === "form" && domName === "action") ||
(["button", "input"].includes(domObj.localName) &&
domName === "formAction")) { // Hard-coded special case
defaultVal = domObj.ownerDocument.URL;
} if (!data.customGetter && (defaultVal !== null || data.isNullable)) {
ReflectionHarness.test(function() { // Tests can pass an array of acceptable values if (Array.isArray(defaultVal)) {
ReflectionHarness.assertInArray(idlObj[idlName], defaultVal);
} else {
ReflectionHarness.assertEquals(idlObj[idlName], defaultVal);
}
}, "IDL get with DOM attribute unset");
}
var domTests = typeInfo.domTests.slice(0); var domExpected = typeInfo.domExpected.map(function(val) { return val === null ? defaultVal : val; }); var idlTests = typeInfo.idlTests.slice(0); var idlDomExpected = typeInfo.idlDomExpected.map(function(val) { return val === null ? defaultVal : val; }); var idlIdlExpected = typeInfo.idlIdlExpected.map(function(val) { return val === null ? defaultVal : val; }); switch (data.type) { // Extra tests and other special-casing case"boolean":
domTests.push(domName);
domExpected.push(true); break;
case"enum": // Whee, enum is complicated. if (typeof data.invalidVal == "undefined") {
data.invalidVal = defaultVal;
} if (typeof data.nonCanon == "undefined") {
data.nonCanon = {};
} for (var i = 0; i < data.keywords.length; i++) { if (data.keywords[i] != "") {
domTests.push(data.keywords[i], "x" + data.keywords[i], data.keywords[i] + "\0");
idlTests.push(data.keywords[i], "x" + data.keywords[i], data.keywords[i] + "\0");
}
if (data.keywords[i].length > 1) { var sliced = data.keywords[i].slice(1); // If slicing a value yields another valid value, then skip it since it results in duplicate tests. if (data.keywords.indexOf(sliced) == -1) {
domTests.push(sliced);
idlTests.push(sliced);
}
}
if (data.keywords[i] != data.keywords[i].toLowerCase()) {
domTests.push(data.keywords[i].toLowerCase());
idlTests.push(data.keywords[i].toLowerCase());
} if (data.keywords[i] != data.keywords[i].toUpperCase()) {
domTests.push(data.keywords[i].toUpperCase());
idlTests.push(data.keywords[i].toUpperCase());
} if (data.keywords[i].indexOf("k") != -1) {
domTests.push(data.keywords[i].replace(/k/g, "\u212A"));
idlTests.push(data.keywords[i].replace(/k/g, "\u212A"));
} if (data.keywords[i].indexOf("s") != -1) {
domTests.push(data.keywords[i].replace(/s/g, "\u017F"));
idlTests.push(data.keywords[i].replace(/s/g, "\u017F"));
}
}
// Per spec, the expected DOM values are the same as the value we set // it to. if (!data.isNullable) {
idlDomExpected = idlTests.slice(0);
} else {
idlDomExpected = []; for (var i = 0; i < idlTests.length; i++) {
idlDomExpected.push((idlTests[i] === null || idlTests[i] === undefined) ? null : idlTests[i]);
}
}
// Now we have the fun of calculating what the expected IDL values are.
domExpected = [];
idlIdlExpected = []; for (var i = 0; i < domTests.length; i++) {
domExpected.push(this.enumExpected(data.keywords, data.nonCanon, data.invalidVal, domTests[i]));
} for (var i = 0; i < idlTests.length; i++) { if (data.isNullable && (idlTests[i] === null || idlTests[i] === undefined)) {
idlIdlExpected.push(null);
} else {
idlIdlExpected.push(this.enumExpected(data.keywords, data.nonCanon, data.invalidVal, idlTests[i]));
}
} break;
case"string": 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; });
idlTests = idlTests.filter(function(element, index, array) { return idlIdlExpected[index] < 1000; });
idlDomExpected = idlDomExpected.filter(function(element, index, array) { return idlIdlExpected[index] < 1000; });
idlIdlExpected = idlIdlExpected.filter(function(element, index, array) { return idlIdlExpected[index] < 1000; });
} if ((domObj.localName === "form" && domName === "action") ||
(["button", "input"].includes(domObj.localName) &&
domName === "formAction")) { // Hard-coded special case for (var i = 0; i < domTests.length; i++) { if (domTests[i] === "") {
domExpected[i] = domObj.ownerDocument.URL;
}
} for (var i = 0; i < idlTests.length; i++) { if (idlTests[i] === "") {
idlIdlExpected[i] = domObj.ownerDocument.URL;
}
}
} if (data.customGetter) { // These are reflected only on setting, not getting
domTests = [];
domExpected = [];
idlIdlExpected = idlIdlExpected.map(() => null);
}
for (var i = 0; i < domTests.length; i++) { if (domExpected[i] === null && !data.isNullable) { // If you follow all the complicated logic here, you'll find that // this will only happen if there's no expected value at all (like // for tabIndex, where the default is too complicated). So skip // the test. continue;
}
ReflectionHarness.test(function() {
domObj.setAttribute(domName, domTests[i]);
ReflectionHarness.assertEquals(domObj.getAttribute(domName),
String(domTests[i]), "getAttribute()"); // Tests can pass an array of acceptable values if (Array.isArray(domExpected[i])) {
ReflectionHarness.assertInArray(idlObj[idlName], domExpected[i], "IDL get");
} else {
ReflectionHarness.assertEquals(idlObj[idlName], domExpected[i], "IDL get");
}
}, "setAttribute() to " + ReflectionHarness.stringRep(domTests[i]));
}
for (var i = 0; i < idlTests.length; i++) {
ReflectionHarness.test(function() { if ((data.type == "limited long" && idlTests[i] < 0) ||
(data.type == "limited unsigned long" && idlTests[i] == 0)) {
ReflectionHarness.assertThrows("IndexSizeError", function() {
idlObj[idlName] = idlTests[i];
});
} elseif (data.type == "limited double" && idlTests[i] <= 0) {
domObj.setAttribute(domName, "previous value"); var previousIdl = idlObj[idlName]; // should be the default value
idlObj[idlName] = idlTests[i];
ReflectionHarness.assertEquals(domObj.getAttribute(domName), "previous value", "getAttribute()");
ReflectionHarness.assertEquals(idlObj[idlName], previousIdl, "IDL get");
} else { var previousValue = domObj.getAttribute(domName);
idlObj[idlName] = idlTests[i]; if (data.type == "boolean") { // Special case yay
ReflectionHarness.assertEquals(domObj.hasAttribute(domName), Boolean(idlTests[i]), "hasAttribute()");
} elseif (idlDomExpected[i] !== null || data.isNullable) { var expected = idlDomExpected[i] + ""; if (data.isNullable && idlDomExpected[i] === null) {
expected = null;
} elseif (idlName == "nonce") { // nonce doesn't reflect the value, as per /content-security-policy/nonce-hiding/ // tests that confirm that retrieving the nonce value post IDL change does not // reflect back to the attribute (for security reasons)
expected = previousValue;
}
ReflectionHarness.assertEquals(domObj.getAttribute(domName), expected, "getAttribute()");
} // Ensure enumerated attributes never reflect in their non-canonical representations if (data.type == "enum" && data.nonCanon[idlObj[idlName]]) {
ReflectionHarness.assertEquals(idlObj[idlName], data.nonCanon[idlObj[idlName]], "IDL get canonical");
} // Tests can pass an array of acceptable values if (Array.isArray(idlIdlExpected[i])) {
ReflectionHarness.assertInArray(idlObj[idlName], idlIdlExpected[i], "IDL get");
} elseif (idlIdlExpected[i] !== null || data.isNullable) {
ReflectionHarness.assertEquals(idlObj[idlName], idlIdlExpected[i], "IDL get");
}
}
}, "IDL set to " + ReflectionHarness.stringRep(idlTests[i]));
}
};
// Now we actually run all the tests. var unimplemented = []; for (var element in elements) {
ReflectionTests.reflects("string", "title", element);
ReflectionTests.reflects("string", "lang", element);
ReflectionTests.reflects({type: "enum", keywords: ["ltr", "rtl", "auto"]}, "dir", element);
ReflectionTests.reflects("string", "className", element, "class");
ReflectionTests.reflects("tokenlist", "classList", element, "class");
ReflectionTests.reflects("boolean", "autofocus", element);
ReflectionTests.reflects("boolean", "hidden", element);
ReflectionTests.reflects("string", "accessKey", element); // Don't try to test the defaultVal -- it should be either 0 or -1, but the // rules are complicated, and a lot of them are SHOULDs.
ReflectionTests.reflects({type: "long", defaultVal: null}, "tabIndex", element); // TODO: classList, contextMenu, itemProp, itemRef
for (var idlAttrName in elements[element]) { var type = elements[element][idlAttrName];
ReflectionTests.reflects(type, idlAttrName, element, typeof type == "object" && "domAttrName" in type ? type.domAttrName : idlAttrName);
}
}
for (var i = 0; i < extraTests.length; i++) {
extraTests[i]();
}
var time = document.getElementById("time"); if (time) {
time.innerHTML = (new Date().getTime() - ReflectionTests.start)/1000;
}
if (unimplemented.length) { var p = document.createElement("p");
p.textContent = "(Note: missing tests for types " + unimplemented.join(", ") + ".)";
document.body.appendChild(p);
}
Messung V0.5 in Prozent
¤ Diese beiden folgenden Angebotsgruppen bietet das Unternehmen0.40Angebot
(Wie Sie bei der Firma Beratungs- und Dienstleistungen beauftragen können 2026-08-26)
¤
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.