[idlharness.js] Let get_reverse_inheritance_stack() do the reversing (#28688)
As suggested by Ms2ger in https://github.com/web-platform-tests/wpt/pull/28650#discussion_r620065161
diff --git a/resources/idlharness.js b/resources/idlharness.js
index 3422d6e..eda7325 100644
--- a/resources/idlharness.js
+++ b/resources/idlharness.js
@@ -581,13 +581,11 @@
// dictionaries where all of their members are JSON types
if (thing instanceof IdlDictionary) {
- var stack = thing.get_inheritance_stack();
- var map = new Map();
- while (stack.length)
- {
- stack.pop().members.forEach(function(m) {
- map.set(m.name, m.idlType)
- });
+ const map = new Map();
+ for (const dict of thing.get_reverse_inheritance_stack()) {
+ for (const m of dict.members) {
+ map.set(m.name, m.idlType);
+ }
}
return Array.from(map.values()).every(this.is_json_type, this);
}
@@ -715,7 +713,7 @@
if (!rhs_is_interface) throw new IdlHarnessError(`${lhs} inherits ${rhs}, but ${rhs} is not an interface.`);
}
// Check for circular dependencies.
- member.get_inheritance_stack();
+ member.get_reverse_inheritance_stack();
}
Object.getOwnPropertyNames(this.members).forEach(function(memberName) {
@@ -1176,8 +1174,8 @@
IdlDictionary.prototype = Object.create(IdlObject.prototype);
-IdlDictionary.prototype.get_inheritance_stack = function() {
- return IdlInterface.prototype.get_inheritance_stack.call(this);
+IdlDictionary.prototype.get_reverse_inheritance_stack = function() {
+ return IdlInterface.prototype.get_reverse_inheritance_stack.call(this);
};
/// IdlInterface ///
@@ -1319,39 +1317,39 @@
});
};
-IdlInterface.prototype.get_inheritance_stack = function() {
- /**
- * See https://heycam.github.io/webidl/#create-an-inheritance-stack
- *
- * Returns an array of IdlInterface objects which contains itself
- * and all of its inherited interfaces.
- *
- * So given:
- *
- * A : B {};
- * B : C {};
- * C {};
- *
- * then A.get_inheritance_stack() should return [A, B, C],
- * and B.get_inheritance_stack() should return [B, C].
- *
- * Note: as dictionary inheritance is expressed identically by the AST,
- * this works just as well for getting a stack of inherited dictionaries.
- */
-
- var stack = [this];
- var idl_interface = this;
+/**
+ * Implementation of https://heycam.github.io/webidl/#create-an-inheritance-stack
+ * with the order reversed.
+ *
+ * The order is reversed so that the base class comes first in the list, because
+ * this is what all call sites need.
+ *
+ * So given:
+ *
+ * A : B {};
+ * B : C {};
+ * C {};
+ *
+ * then A.get_reverse_inheritance_stack() returns [C, B, A],
+ * and B.get_reverse_inheritance_stack() returns [C, B].
+ *
+ * Note: as dictionary inheritance is expressed identically by the AST,
+ * this works just as well for getting a stack of inherited dictionaries.
+ */
+IdlInterface.prototype.get_reverse_inheritance_stack = function() {
+ const stack = [this];
+ let idl_interface = this;
while (idl_interface.base) {
- var base = this.array.members[idl_interface.base];
+ const base = this.array.members[idl_interface.base];
if (!base) {
throw new Error(idl_interface.type + " " + idl_interface.base + " not found (inherited by " + idl_interface.name + ")");
} else if (stack.indexOf(base) > -1) {
- stack.push(base);
- let dep_chain = stack.map(i => i.name).join(',');
+ stack.unshift(base);
+ const dep_chain = stack.map(i => i.name).join(',');
throw new IdlHarnessError(`${this.name} has a circular dependency: ${dep_chain}`);
}
idl_interface = base;
- stack.push(idl_interface);
+ stack.unshift(idl_interface);
}
return stack;
};
@@ -1366,19 +1364,20 @@
* comparison with actual value
*/
IdlInterface.prototype.default_to_json_operation = function() {
- var map = new Map(), isDefault = false;
- this.get_inheritance_stack().reverse().forEach(function(I) {
+ const map = new Map()
+ let isDefault = false;
+ for (const I of this.get_reverse_inheritance_stack()) {
if (I.has_default_to_json_regular_operation()) {
isDefault = true;
- I.members.forEach(function(m) {
+ for (const m of I.members) {
if (m.special !== "static" && m.type == "attribute" && I.array.is_json_type(m.idlType)) {
map.set(m.name, m.idlType);
}
- });
+ }
} else if (I.has_to_json_regular_operation()) {
isDefault = false;
}
- });
+ }
return isDefault ? map : null;
};
diff --git a/resources/test/tests/unit/IdlDictionary/get_inheritance_stack.html b/resources/test/tests/unit/IdlDictionary/get_reverse_inheritance_stack.html
similarity index 77%
rename from resources/test/tests/unit/IdlDictionary/get_inheritance_stack.html
rename to resources/test/tests/unit/IdlDictionary/get_reverse_inheritance_stack.html
index 052592d..418bcde 100644
--- a/resources/test/tests/unit/IdlDictionary/get_inheritance_stack.html
+++ b/resources/test/tests/unit/IdlDictionary/get_reverse_inheritance_stack.html
@@ -1,7 +1,7 @@
<!DOCTYPE HTML>
<html>
<head>
-<title>IdlDictionary.prototype.get_inheritance_stack()</title>
+<title>IdlDictionary.prototype.get_reverse_inheritance_stack()</title>
</head>
<body>
<div id="log"></div>
@@ -13,13 +13,13 @@
<script>
"use strict";
test(function() {
- var stack = dictionaryFrom('dictionary A { };').get_inheritance_stack();
+ var stack = dictionaryFrom('dictionary A { };').get_reverse_inheritance_stack();
assert_array_equals(stack.map(d => d.name), ["A"]);
}, 'should return an array that includes itself.');
test(function() {
var d = dictionaryFrom('dictionary A : B { };');
- assert_throws_js(Error, _ => d.get_inheritance_stack());
+ assert_throws_js(Error, _ => d.get_reverse_inheritance_stack());
}, "should throw for dictionaries which inherit from another dictionary which wasn't added to the IdlArray");
test(function() {
@@ -27,8 +27,8 @@
idl.add_idls('dictionary A : B { };');
idl.add_untested_idls('dictionary B : C { }; dictionary C { };');
var A = idl.members["A"];
- assert_array_equals(A.get_inheritance_stack().map(d => d.name), ["A", "B", "C"]);
- }, 'should return an array of inherited dictionaries in order of inheritance, starting with itself.');
+ assert_array_equals(A.get_reverse_inheritance_stack().map(d => d.name), ["C", "B", "A"]);
+ }, 'should return an array of dictionaries in order of inheritance, starting with the base dictionary');
test(function () {
let i = new IdlArray();
diff --git a/resources/test/tests/unit/IdlInterface/get_inheritance_stack.html b/resources/test/tests/unit/IdlInterface/get_reverse_inheritance_stack.html
similarity index 77%
rename from resources/test/tests/unit/IdlInterface/get_inheritance_stack.html
rename to resources/test/tests/unit/IdlInterface/get_reverse_inheritance_stack.html
index 7e9188c..0c066ba 100644
--- a/resources/test/tests/unit/IdlInterface/get_inheritance_stack.html
+++ b/resources/test/tests/unit/IdlInterface/get_reverse_inheritance_stack.html
@@ -1,7 +1,7 @@
<!DOCTYPE HTML>
<html>
<head>
-<title>IdlInterface.prototype.get_inheritance_stack()</title>
+<title>IdlInterface.prototype.get_reverse_inheritance_stack()</title>
</head>
<body>
<div id="log"></div>
@@ -13,13 +13,13 @@
<script>
"use strict";
test(function() {
- var stack = interfaceFrom('interface A { };').get_inheritance_stack();
+ var stack = interfaceFrom('interface A { };').get_reverse_inheritance_stack();
assert_array_equals(stack.map(i => i.name), ["A"]);
}, 'should return an array that includes itself.');
test(function() {
var i = interfaceFrom('interface A : B { };');
- assert_throws_js(Error, _ => i.get_inheritance_stack());
+ assert_throws_js(Error, _ => i.get_reverse_inheritance_stack());
}, "should throw for interfaces which inherit from another interface which wasn't added to the IdlArray");
test(function() {
@@ -27,8 +27,8 @@
idl.add_idls('interface A : B { };');
idl.add_untested_idls('interface B : C { }; interface C { };');
var A = idl.members["A"];
- assert_array_equals(A.get_inheritance_stack().map(i => i.name), ["A", "B", "C"]);
- }, 'should return an array of inherited interfaces in order of inheritance, starting with itself.');
+ assert_array_equals(A.get_reverse_inheritance_stack().map(i => i.name), ["C", "B", "A"]);
+ }, 'should return an array of interfaces in order of inheritance, starting with the base interface');
test(function () {
var idl = new IdlArray();