diff --git a/idlharness.js b/idlharness.js index 02304ca..0c91d45 100644 --- a/idlharness.js +++ b/idlharness.js @@ -1381,6 +1381,10 @@ IdlInterface.prototype.test_primary_interface_of = function(desc, obj, exception IdlInterface.prototype.test_interface_of = function(desc, obj, exception, expected_typeof) //@{ { + // A map from operations' names to members, for tests that are only related to the + // instances' properties' descriptors. + var operations = {}; + // TODO: Indexed and named properties, more checks on interface members this.already_tested = true; @@ -1396,21 +1400,21 @@ IdlInterface.prototype.test_interface_of = function(desc, obj, exception, expect this.do_interface_attribute_asserts(obj, member); }.bind(this), this.name + " interface: " + desc + ' must have own property "' + member.name + '"'); } - else if (member.type == "operation" && - member.name && - member.isUnforgeable) - { - test(function() - { - assert_equals(exception, null, "Unexpected exception when evaluating object"); - assert_equals(typeof obj, expected_typeof, "wrong typeof object"); - assert_own_property(obj, member.name, - "Doesn't have the unforgeable operation property"); - this.do_member_operation_asserts(obj, member); - }.bind(this), this.name + " interface: " + desc + ' must have own property "' + member.name + '"'); + else if (member.type == "operation" && member.name) { + if (member.name in operations) { + if (operations[member.name].isUnforgeable != member.isUnforgeable) { + throw "All overloads of " + this.name + "." + member.name + " should be unforgeable or none of them."; + } + if (operations[member.name]["static"] != member["static"]) { + throw "All overloads of " + this.name + "." + member.name + "should be static or none of them."; + } + } else { + // We just take the first we find. This is safe because only their name, forgeableness + // and staticness are later used. + operations[member.name] = member; + } } else if ((member.type == "const" - || member.type == "attribute" || member.type == "operation") && member.name) { @@ -1418,62 +1422,51 @@ IdlInterface.prototype.test_interface_of = function(desc, obj, exception, expect { assert_equals(exception, null, "Unexpected exception when evaluating object"); assert_equals(typeof obj, expected_typeof, "wrong typeof object"); - if (!member["static"]) { - if (!this.is_global()) { - assert_inherits(obj, member.name); - } else { - assert_own_property(obj, member.name); - } + if (!this.is_global()) { + assert_inherits(obj, member.name); + } else { + assert_own_property(obj, member.name); + } - if (member.type == "const") + if (member.type == "const") + { + assert_equals(obj[member.name], constValue(member.value)); + } + if (member.type == "attribute") + { + // Attributes are accessor properties, so they might + // legitimately throw an exception rather than returning + // anything. + var property, thrown = false; + try { - assert_equals(obj[member.name], constValue(member.value)); + property = obj[member.name]; } - if (member.type == "attribute") + catch (e) { - // Attributes are accessor properties, so they might - // legitimately throw an exception rather than returning - // anything. - var property, thrown = false; - try - { - property = obj[member.name]; - } - catch (e) - { - thrown = true; - } - if (!thrown) - { - this.array.assert_type_is(property, member.idlType); - } + thrown = true; } - if (member.type == "operation") + if (!thrown) { - assert_equals(typeof obj[member.name], "function"); + this.array.assert_type_is(property, member.idlType); } } - }.bind(this), this.name + " interface: " + desc + ' must inherit property "' + member.name + '" with the proper type (' + i + ')'); + }.bind(this), this.name + " interface: " + desc + ' must inherit property "' + member.name + '" with the proper type'); } // TODO: This is wrong if there are multiple operations with the same // identifier. // TODO: Test passing arguments of the wrong type. - if (member.type == "operation" && member.name && member.arguments.length) + if (member.type == "operation" && + !member["static"] && member.name && member.arguments.length) { test(function() { assert_equals(exception, null, "Unexpected exception when evaluating object"); assert_equals(typeof obj, expected_typeof, "wrong typeof object"); - if (!member["static"]) { - if (!this.is_global() && !member.isUnforgeable) { - assert_inherits(obj, member.name); - } else { - assert_own_property(obj, member.name); - } - } - else - { - assert_false(member.name in obj); + if (!this.is_global() && !member.isUnforgeable) { + assert_inherits(obj, member.name); + } else { + assert_own_property(obj, member.name); } var minLength = minOverloadLength(this.members.filter(function(m) { @@ -1493,6 +1486,35 @@ IdlInterface.prototype.test_interface_of = function(desc, obj, exception, expect ") on " + desc + " with too few arguments must throw TypeError"); } } + + for (var name in operations) { + if (operations[name].isUnforgeable) { + test(function() { + assert_equals(exception, null, "Unexpected exception when evaluating object"); + assert_equals(typeof obj, expected_typeof, "wrong typeof object"); + assert_own_property(obj, name, + "Doesn't have the unforgeable operation property"); + this.do_member_operation_asserts(obj, operations[name]); + }.bind(this), this.name + " interface: " + desc + ' must have own property "' + name + '"'); + } else if (operations[name]["static"]) { + test(function() { + assert_equals(exception, null, "Unexpected exception when evaluating object"); + assert_equals(typeof obj, expected_typeof, "wrong typeof object"); + assert_false(name in obj); + }.bind(this), this.name + " interface: static operation " + name + " must not be a property on " + desc); + } else { + test(function() { + assert_equals(exception, null, "Unexpected exception when evaluating object"); + assert_equals(typeof obj, expected_typeof, "wrong typeof object"); + if (!this.is_global()) { + assert_inherits(obj, member.name); + } else { + assert_own_property(obj, member.name); + } + assert_equals(typeof obj[member.name], "function"); + }.bind(this), this.name + " interface: " + desc + ' must inherit property "' + name + '" with the proper type'); + } + } }; //@}