/*
Distributed under both the W3C Test Suite License [1] and the W3C
3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
policies and contribution forms [3].

[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
[3] http://www.w3.org/2004/10/27-testcases
*/

/* For user documentation see docs/_writing-tests/idlharness.md */

/**
 * Notes for people who want to edit this file (not just use it as a library):
 *
 * Most of the interesting stuff happens in the derived classes of IdlObject,
 * especially IdlInterface.  The entry point for all IdlObjects is .test(),
 * which is called by IdlArray.test().  An IdlObject is conceptually just
 * "thing we want to run tests on", and an IdlArray is an array of IdlObjects
 * with some additional data thrown in.
 *
 * The object model is based on what WebIDLParser.js produces, which is in turn
 * based on its pegjs grammar.  If you want to figure out what properties an
 * object will have from WebIDLParser.js, the best way is to look at the
 * grammar:
 *
 *   https://github.com/darobin/webidl.js/blob/master/lib/grammar.peg
 *
 * So for instance:
 *
 *   // interface definition
 *   interface
 *       =   extAttrs:extendedAttributeList? S? "interface" S name:identifier w herit:ifInheritance? w "{" w mem:ifMember* w "}" w ";" w
 *           { return { type: "interface", name: name, inheritance: herit, members: mem, extAttrs: extAttrs }; }
 *
 * This means that an "interface" object will have a .type property equal to
 * the string "interface", a .name property equal to the identifier that the
 * parser found, an .inheritance property equal to either null or the result of
 * the "ifInheritance" production found elsewhere in the grammar, and so on.
 * After each grammatical production is a JavaScript function in curly braces
 * that gets called with suitable arguments and returns some JavaScript value.
 *
 * (Note that the version of WebIDLParser.js we use might sometimes be
 * out-of-date or forked.)
 *
 * The members and methods of the classes defined by this file are all at least
 * briefly documented, hopefully.
 */
(function(){
"use strict";
// Support subsetTestByKey from /common/subset-tests-by-key.js, but make it optional
if (!('subsetTestByKey' in self)) {
    self.subsetTestByKey = function(key, callback, ...args) {
      return callback(...args);
    }
    self.shouldRunSubTest = () => true;
}
/// Helpers ///
function constValue (cnt)
{
    if (cnt.type === "null") return null;
    if (cnt.type === "NaN") return NaN;
    if (cnt.type === "Infinity") return cnt.negative ? -Infinity : Infinity;
    if (cnt.type === "number") return +cnt.value;
    return cnt.value;
}

function minOverloadLength(overloads)
{
    // "The value of the Function object’s “length” property is
    // a Number determined as follows:
    // ". . .
    // "Return the length of the shortest argument list of the
    // entries in S."
    if (!overloads.length) {
        return 0;
    }

    return overloads.map(function(attr) {
        return attr.arguments ? attr.arguments.filter(function(arg) {
            return !arg.optional && !arg.variadic;
        }).length : 0;
    })
    .reduce(function(m, n) { return Math.min(m, n); });
}

function throwOrReject(a_test, operation, fn, obj, args, message, cb)
{
    if (operation.idlType.generic !== "Promise") {
        assert_throws(new TypeError(), function() {
            fn.apply(obj, args);
        }, message);
        cb();
    } else {
        try {
            promise_rejects(a_test, new TypeError(), fn.apply(obj, args), message).then(cb, cb);
        } catch (e){
            a_test.step(function() {
                assert_unreached("Throws \"" + e + "\" instead of rejecting promise");
                cb();
            });
        }
    }
}

function awaitNCallbacks(n, cb, ctx)
{
    var counter = 0;
    return function() {
        counter++;
        if (counter >= n) {
            cb();
        }
    };
}

var fround =
(function(){
    if (Math.fround) return Math.fround;

    var arr = new Float32Array(1);
    return function fround(n) {
        arr[0] = n;
        return arr[0];
    };
})();

/// IdlHarnessError ///
// Entry point
self.IdlHarnessError = function(message)
{
    /**
     * Message to be printed as the error's toString invocation.
     */
    this.message = message;
};

IdlHarnessError.prototype = Object.create(Error.prototype);

IdlHarnessError.prototype.toString = function()
{
    return this.message;
};


/// IdlArray ///
// Entry point
self.IdlArray = function()
{
    /**
     * A map from strings to the corresponding named IdlObject, such as
     * IdlInterface or IdlException.  These are the things that test() will run
     * tests on.
     */
    this.members = {};

    /**
     * A map from strings to arrays of strings.  The keys are interface or
     * exception names, and are expected to also exist as keys in this.members
     * (otherwise they'll be ignored).  This is populated by add_objects() --
     * see documentation at the start of the file.  The actual tests will be
     * run by calling this.members[name].test_object(obj) for each obj in
     * this.objects[name].  obj is a string that will be eval'd to produce a
     * JavaScript value, which is supposed to be an object implementing the
     * given IdlObject (interface, exception, etc.).
     */
    this.objects = {};

    /**
     * When adding multiple collections of IDLs one at a time, an earlier one
     * might contain a partial interface or implements statement that depends
     * on a later one.  Save these up and handle them right before we run
     * tests.
     *
     * .partials is simply an array of objects from WebIDLParser.js'
     * "partialinterface" production.  .implements maps strings to arrays of
     * strings, such that
     *
     *   A implements B;
     *   A implements C;
     *   D implements E;
     *
     * results in this["implements"] = { A: ["B", "C"], D: ["E"] }.
     *
     * Similarly,
     *
     *   interface A : B {};
     *   interface B : C {};
     *
     * results in this["inheritance"] = { A: "B", B: "C" }
     */
    this.partials = [];
    this["implements"] = {};
    this["includes"] = {};
    this["inheritance"] = {};

    /**
     * Record of skipped IDL items, in case we later realize that they are a
     * dependency (to retroactively process them).
     */
    this.skipped = new Map();
};

IdlArray.prototype.add_idls = function(raw_idls, options)
{
    /** Entry point.  See documentation at beginning of file. */
    this.internal_add_idls(WebIDL2.parse(raw_idls), options);
};

IdlArray.prototype.add_untested_idls = function(raw_idls, options)
{
    /** Entry point.  See documentation at beginning of file. */
    var parsed_idls = WebIDL2.parse(raw_idls);
    this.mark_as_untested(parsed_idls);
    this.internal_add_idls(parsed_idls, options);
};

IdlArray.prototype.mark_as_untested = function (parsed_idls)
{
    for (var i = 0; i < parsed_idls.length; i++) {
        parsed_idls[i].untested = true;
        if ("members" in parsed_idls[i]) {
            for (var j = 0; j < parsed_idls[i].members.length; j++) {
                parsed_idls[i].members[j].untested = true;
            }
        }
    }
};

IdlArray.prototype.is_excluded_by_options = function (name, options)
{
    return options &&
        (options.except && options.except.includes(name)
         || options.only && !options.only.includes(name));
};

IdlArray.prototype.add_dependency_idls = function(raw_idls, options)
{
    return this.internal_add_dependency_idls(WebIDL2.parse(raw_idls), options);
};

IdlArray.prototype.internal_add_dependency_idls = function(parsed_idls, options)
{
    const new_options = { only: [] }

    const all_deps = new Set();
    Object.values(this.inheritance).forEach(v => all_deps.add(v));
    Object.entries(this.implements).forEach(([k, v]) => {
        all_deps.add(k);
        all_deps.add(v);
    });
    // NOTE: If 'A includes B' for B that we care about, then A is also a dep.
    Object.keys(this.includes).forEach(k => {
        all_deps.add(k);
        this.includes[k].forEach(v => all_deps.add(v));
    });
    this.partials.forEach(p => all_deps.add(p.name));
    // Add 'TypeOfType' for each "typedef TypeOfType MyType;" entry.
    Object.entries(this.members).forEach(([k, v]) => {
        if (v instanceof IdlTypedef) {
            let defs = v.idlType.union
                ? v.idlType.idlType.map(t => t.idlType)
                : [v.idlType.idlType];
            defs.forEach(d => all_deps.add(d));
        }
    });

    // Add the attribute idlTypes of all the nested members of idls.
    const attrDeps = parsedIdls => {
        return parsedIdls.reduce((deps, parsed) => {
            if (parsed.members) {
                for (const attr of Object.values(parsed.members).filter(m => m.type === 'attribute')) {
                    let attrType = attr.idlType;
                    // Check for generic members (e.g. FrozenArray<MyType>)
                    if (attrType.generic) {
                        deps.add(attrType.generic);
                        attrType = attrType.idlType;
                    }
                    deps.add(attrType.idlType);
                }
            }
            if (parsed.base in this.members) {
                attrDeps([this.members[parsed.base]]).forEach(dep => deps.add(dep));
            }
            return deps;
        }, new Set());
    };

    const testedMembers = Object.values(this.members).filter(m => !m.untested && m.members);
    attrDeps(testedMembers).forEach(dep => all_deps.add(dep));

    const testedPartials = this.partials.filter(m => !m.untested && m.members);
    attrDeps(testedPartials).forEach(dep => all_deps.add(dep));


    if (options && options.except && options.only) {
        throw new IdlHarnessError("The only and except options can't be used together.");
    }

    const defined_or_untested = name => {
        // NOTE: Deps are untested, so we're lenient, and skip re-encountered definitions.
        // e.g. for 'idl' containing A:B, B:C, C:D
        //      array.add_idls(idl, {only: ['A','B']}).
        //      array.add_dependency_idls(idl);
        // B would be encountered as tested, and encountered as a dep, so we ignore.
        return name in this.members
            || this.is_excluded_by_options(name, options);
    }
    // Maps name -> [parsed_idl, ...]
    const process = function(parsed) {
        var deps = [];
        if (parsed.name) {
            deps.push(parsed.name);
        } else if (parsed.type === "implements") {
            deps.push(parsed.target);
            deps.push(parsed.implements);
        } else if (parsed.type === "includes") {
            deps.push(parsed.target);
            deps.push(parsed.includes);
        }

        deps = deps.filter(function(name) {
            if (!name
                || name === parsed.name && defined_or_untested(name)
                || !all_deps.has(name)) {
                // Flag as skipped, if it's not already processed, so we can
                // come back to it later if we retrospectively call it a dep.
                if (name && !(name in this.members)) {
                    this.skipped.has(name)
                        ? this.skipped.get(name).push(parsed)
                        : this.skipped.set(name, [parsed]);
                }
                return false;
            }
            return true;
        }.bind(this));

        deps.forEach(function(name) {
            if (!new_options.only.includes(name)) {
                new_options.only.push(name);
            }

            const follow_up = new Set();
            for (const dep_type of ["inheritance", "implements", "includes"]) {
                if (parsed[dep_type]) {
                    const inheriting = parsed[dep_type];
                    const inheritor = parsed.name || parsed.target;
                    const deps = [inheriting];
                    // For A includes B, we can ignore A, unless B (or some of its
                    // members) is being tested.
                    if (dep_type !== "includes"
                        || inheriting in this.members && !this.members[inheriting].untested
                        || this.partials.some(function(p) {
                                return p.name === inheriting;
                            })) {
                        deps.push(inheritor);
                    }
                    for (const dep of deps) {
                        if (!new_options.only.includes(dep)) {
                            new_options.only.push(dep);
                        }
                        all_deps.add(dep);
                        follow_up.add(dep);
                    }
                }
            }

            for (const deferred of follow_up) {
                if (this.skipped.has(deferred)) {
                    const next = this.skipped.get(deferred);
                    this.skipped.delete(deferred);
                    next.forEach(process);
                }
            }
        }.bind(this));
    }.bind(this);

    for (let parsed of parsed_idls) {
        process(parsed);
    }

    this.mark_as_untested(parsed_idls);

    if (new_options.only.length) {
        this.internal_add_idls(parsed_idls, new_options);
    }
}

IdlArray.prototype.internal_add_idls = function(parsed_idls, options)
{
    /**
     * Internal helper called by add_idls() and add_untested_idls().
     *
     * parsed_idls is an array of objects that come from WebIDLParser.js's
     * "definitions" production.  The add_untested_idls() entry point
     * additionally sets an .untested property on each object (and its
     * .members) so that they'll be skipped by test() -- they'll only be
     * used for base interfaces of tested interfaces, return types, etc.
     *
     * options is a dictionary that can have an only or except member which are
     * arrays. If only is given then only members, partials and interface
     * targets listed will be added, and if except is given only those that
     * aren't listed will be added. Only one of only and except can be used.
     */

    if (options && options.only && options.except)
    {
        throw new IdlHarnessError("The only and except options can't be used together.");
    }

    var should_skip = name => {
        return this.is_excluded_by_options(name, options);
    }

    parsed_idls.forEach(function(parsed_idl)
    {
        var partial_types = [
            "interface",
            "interface mixin",
            "dictionary",
            "namespace",
        ];
        if (parsed_idl.partial && partial_types.includes(parsed_idl.type))
        {
            if (should_skip(parsed_idl.name))
            {
                return;
            }
            this.partials.push(parsed_idl);
            return;
        }

        if (parsed_idl.type == "implements")
        {
            if (should_skip(parsed_idl.target))
            {
                return;
            }
            if (!(parsed_idl.target in this["implements"]))
            {
                this["implements"][parsed_idl.target] = [];
            }
            this["implements"][parsed_idl.target].push(parsed_idl["implements"]);
            return;
        }

        if (parsed_idl.type == "includes")
        {
            if (should_skip(parsed_idl.target))
            {
                return;
            }
            if (!(parsed_idl.target in this["includes"]))
            {
                this["includes"][parsed_idl.target] = [];
            }
            this["includes"][parsed_idl.target].push(parsed_idl["includes"]);
            return;
        }

        parsed_idl.array = this;
        if (should_skip(parsed_idl.name))
        {
            return;
        }
        if (parsed_idl.name in this.members)
        {
            throw new IdlHarnessError("Duplicate identifier " + parsed_idl.name);
        }

        if (parsed_idl["inheritance"]) {
            // NOTE: Clash should be impossible (would require redefinition of parsed_idl.name).
            if (parsed_idl.name in this["inheritance"]
                && parsed_idl["inheritance"] != this["inheritance"][parsed_idl.name]) {
                throw new IdlHarnessError(
                    `Inheritance for ${parsed_idl.name} was already defined`);
            }
            this["inheritance"][parsed_idl.name] = parsed_idl["inheritance"];
        }

        switch(parsed_idl.type)
        {
        case "interface":
            this.members[parsed_idl.name] =
                new IdlInterface(parsed_idl, /* is_callback = */ false, /* is_mixin = */ false);
            break;

        case "interface mixin":
            this.members[parsed_idl.name] =
                new IdlInterface(parsed_idl, /* is_callback = */ false, /* is_mixin = */ true);
            break;

        case "dictionary":
            // Nothing to test, but we need the dictionary info around for type
            // checks
            this.members[parsed_idl.name] = new IdlDictionary(parsed_idl);
            break;

        case "typedef":
            this.members[parsed_idl.name] = new IdlTypedef(parsed_idl);
            break;

        case "callback":
            this.members[parsed_idl.name] = new IdlCallback(parsed_idl);
            break;

        case "enum":
            this.members[parsed_idl.name] = new IdlEnum(parsed_idl);
            break;

        case "callback interface":
            this.members[parsed_idl.name] =
                new IdlInterface(parsed_idl, /* is_callback = */ true, /* is_mixin = */ false);
            break;

        case "namespace":
            this.members[parsed_idl.name] = new IdlNamespace(parsed_idl);
            break;

        default:
            throw parsed_idl.name + ": " + parsed_idl.type + " not yet supported";
        }
    }.bind(this));
};

IdlArray.prototype.add_objects = function(dict)
{
    /** Entry point.  See documentation at beginning of file. */
    for (var k in dict)
    {
        if (k in this.objects)
        {
            this.objects[k] = this.objects[k].concat(dict[k]);
        }
        else
        {
            this.objects[k] = dict[k];
        }
    }
};

IdlArray.prototype.prevent_multiple_testing = function(name)
{
    /** Entry point.  See documentation at beginning of file. */
    this.members[name].prevent_multiple_testing = true;
};

IdlArray.prototype.recursively_get_implements = function(interface_name)
{
    /**
     * Helper function for test().  Returns an array of things that implement
     * interface_name, so if the IDL contains
     *
     *   A implements B;
     *   B implements C;
     *   B implements D;
     *
     * then recursively_get_implements("A") should return ["B", "C", "D"].
     */
    var ret = this["implements"][interface_name];
    if (ret === undefined)
    {
        return [];
    }
    for (var i = 0; i < this["implements"][interface_name].length; i++)
    {
        ret = ret.concat(this.recursively_get_implements(ret[i]));
        if (ret.indexOf(ret[i]) != ret.lastIndexOf(ret[i]))
        {
            throw new IdlHarnessError("Circular implements statements involving " + ret[i]);
        }
    }
    return ret;
};

IdlArray.prototype.recursively_get_includes = function(interface_name)
{
    /**
     * Helper function for test().  Returns an array of things that implement
     * interface_name, so if the IDL contains
     *
     *   A includes B;
     *   B includes C;
     *   B includes D;
     *
     * then recursively_get_includes("A") should return ["B", "C", "D"].
     */
    var ret = this["includes"][interface_name];
    if (ret === undefined)
    {
        return [];
    }
    for (var i = 0; i < this["includes"][interface_name].length; i++)
    {
        ret = ret.concat(this.recursively_get_includes(ret[i]));
        if (ret.indexOf(ret[i]) != ret.lastIndexOf(ret[i]))
        {
            throw new IdlHarnessError("Circular includes statements involving " + ret[i]);
        }
    }
    return ret;
};

IdlArray.prototype.is_json_type = function(type)
{
    /**
     * Checks whether type is a JSON type as per
     * https://heycam.github.io/webidl/#dfn-json-types
     */

    var idlType = type.idlType;

    if (type.generic == "Promise") { return false; }

    //  nullable and annotated types don't need to be handled separately,
    //  as webidl2 doesn't represent them wrapped-up (as they're described
    //  in WebIDL).

    // union and record types
    if (type.union || type.generic == "record") {
        return idlType.every(this.is_json_type, this);
    }

    // sequence types
    if (type.generic == "sequence" || type.generic == "FrozenArray") {
        return this.is_json_type(idlType[0]);
    }

    if (typeof idlType != "string") { throw new Error("Unexpected type " + JSON.stringify(idlType)); }

    switch (idlType)
    {
       //  Numeric types
       case "byte":
       case "octet":
       case "short":
       case "unsigned short":
       case "long":
       case "unsigned long":
       case "long long":
       case "unsigned long long":
       case "float":
       case "double":
       case "unrestricted float":
       case "unrestricted double":
       // boolean
       case "boolean":
       // string types
       case "DOMString":
       case "ByteString":
       case "USVString":
       // object type
       case "object":
           return true;
       case "Error":
       case "DOMException":
       case "Int8Array":
       case "Int16Array":
       case "Int32Array":
       case "Uint8Array":
       case "Uint16Array":
       case "Uint32Array":
       case "Uint8ClampedArray":
       case "Float32Array":
       case "ArrayBuffer":
       case "DataView":
       case "any":
           return false;
       default:
           var thing = this.members[idlType];
           if (!thing) { throw new Error("Type " + idlType + " not found"); }
           if (thing instanceof IdlEnum) { return true; }

           if (thing instanceof IdlTypedef) {
               return this.is_json_type(thing.idlType);
           }

           //  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)
                   });
               }
               return Array.from(map.values()).every(this.is_json_type, this);
           }

           //  interface types that have a toJSON operation declared on themselves or
           //  one of their inherited or consequential interfaces.
           if (thing instanceof IdlInterface) {
               var base;
               while (thing)
               {
                   if (thing.has_to_json_regular_operation()) { return true; }
                   var mixins = this.implements[thing.name] || this.includes[thing.name];
                   if (mixins) {
                       mixins = mixins.map(function(id) {
                           var mixin = this.members[id];
                           if (!mixin) {
                               throw new Error("Interface " + id + " not found (implemented by " + thing.name + ")");
                           }
                           return mixin;
                       }, this);
                       if (mixins.some(function(m) { return m.has_to_json_regular_operation() } )) { return true; }
                   }
                   if (!thing.base) { return false; }
                   base = this.members[thing.base];
                   if (!base) {
                       throw new Error("Interface " + thing.base + " not found (inherited by " + thing.name + ")");
                   }
                   thing = base;
               }
               return false;
           }
           return false;
    }
};

function exposure_set(object, default_set) {
    var exposed = object.extAttrs && object.extAttrs.filter(a => a.name === "Exposed");
    if (exposed && exposed.length > 1) {
        throw new IdlHarnessError(
            `Multiple 'Exposed' extended attributes on ${object.name}`);
    }

    let result = default_set || ["Window"];
    if (result && !(result instanceof Set)) {
        result = new Set(result);
    }
    if (exposed && exposed.length) {
        const { rhs } = exposed[0];
        // Could be a list or a string.
        const set = rhs.type === "identifier-list" ?
            rhs.value.map(id => id.value) :
            [ rhs.value ];
        result = new Set(set);
    }
    if (result && result.has("Worker")) {
        result.delete("Worker");
        result.add("DedicatedWorker");
        result.add("ServiceWorker");
        result.add("SharedWorker");
    }
    return result;
}

function exposed_in(globals) {
    if ('document' in self) {
        return globals.has("Window");
    }
    if ('DedicatedWorkerGlobalScope' in self &&
        self instanceof DedicatedWorkerGlobalScope) {
        return globals.has("DedicatedWorker");
    }
    if ('SharedWorkerGlobalScope' in self &&
        self instanceof SharedWorkerGlobalScope) {
        return globals.has("SharedWorker");
    }
    if ('ServiceWorkerGlobalScope' in self &&
        self instanceof ServiceWorkerGlobalScope) {
        return globals.has("ServiceWorker");
    }
    throw new IdlHarnessError("Unexpected global object");
}

/**
 * Asserts that the given error message is thrown for the given function.
 * @param {string|IdlHarnessError} error Expected Error message.
 * @param {Function} idlArrayFunc Function operating on an IdlArray that should throw.
 */
IdlArray.prototype.assert_throws = function(error, idlArrayFunc)
{
    try {
        idlArrayFunc.call(this, this);
    } catch (e) {
        if (e instanceof AssertionError) {
            throw e;
        }
        // Assertions for behaviour of the idlharness.js engine.
        if (error instanceof IdlHarnessError) {
            error = error.message;
        }
        if (e.message !== error) {
            throw new IdlHarnessError(`${idlArrayFunc} threw "${e}", not the expected IdlHarnessError "${error}"`);
        }
        return;
    }
    throw new IdlHarnessError(`${idlArrayFunc} did not throw the expected IdlHarnessError`);
}

IdlArray.prototype.test = function()
{
    /** Entry point.  See documentation at beginning of file. */

    // First merge in all the partial interfaces and implements statements we
    // encountered.
    this.collapse_partials();

    for (var lhs in this["implements"])
    {
        this.recursively_get_implements(lhs).forEach(function(rhs)
        {
            var errStr = lhs + " implements " + rhs + ", but ";
            if (!(lhs in this.members)) throw errStr + lhs + " is undefined.";
            if (!(this.members[lhs] instanceof IdlInterface)) throw errStr + lhs + " is not an interface.";
            if (!(rhs in this.members)) throw errStr + rhs + " is undefined.";
            if (!(this.members[rhs] instanceof IdlInterface)) throw errStr + rhs + " is not an interface.";

            if (this.members[rhs].members.length) {
                test(function () {
                    var clash = this.members[rhs].members.find(function(member) {
                        return this.members[lhs].members.find(function(m) {
                            return this.are_duplicate_members(m, member);
                        }.bind(this));
                    }.bind(this));
                    this.members[rhs].members.forEach(function(member) {
                        this.members[lhs].members.push(new IdlInterfaceMember(member));
                    }.bind(this));
                    assert_true(!clash, "member " + (clash && clash.name) + " is unique");
                }.bind(this), lhs + " implements " + rhs + ": member names are unique");
            }
        }.bind(this));
    }
    this["implements"] = {};

    for (var lhs in this["includes"])
    {
        this.recursively_get_includes(lhs).forEach(function(rhs)
        {
            var errStr = lhs + " includes " + rhs + ", but ";
            if (!(lhs in this.members)) throw errStr + lhs + " is undefined.";
            if (!(this.members[lhs] instanceof IdlInterface)) throw errStr + lhs + " is not an interface.";
            if (!(rhs in this.members)) throw errStr + rhs + " is undefined.";
            if (!(this.members[rhs] instanceof IdlInterface)) throw errStr + rhs + " is not an interface.";

            if (this.members[rhs].members.length) {
                test(function () {
                    var clash = this.members[rhs].members.find(function(member) {
                        return this.members[lhs].members.find(function(m) {
                            return this.are_duplicate_members(m, member);
                        }.bind(this));
                    }.bind(this));
                    this.members[rhs].members.forEach(function(member) {
                        assert_true(
                            this.members[lhs].members.every(m => !this.are_duplicate_members(m, member)),
                            "member " + member.name + " is unique");
                        this.members[lhs].members.push(new IdlInterfaceMember(member));
                    }.bind(this));
                    assert_true(!clash, "member " + (clash && clash.name) + " is unique");
                }.bind(this), lhs + " includes " + rhs + ": member names are unique");
            }
        }.bind(this));
    }
    this["includes"] = {};

    // Assert B defined for A : B
    for (const member of Object.values(this.members).filter(m => m.base)) {
        const lhs = member.name;
        const rhs = member.base;
        if (!(rhs in this.members)) throw new IdlHarnessError(`${lhs} inherits ${rhs}, but ${rhs} is undefined.`);
        const lhs_is_interface = this.members[lhs] instanceof IdlInterface;
        const rhs_is_interface = this.members[rhs] instanceof IdlInterface;
        if (rhs_is_interface != lhs_is_interface) {
            if (!lhs_is_interface) throw new IdlHarnessError(`${lhs} inherits ${rhs}, but ${lhs} is not an interface.`);
            if (!rhs_is_interface) throw new IdlHarnessError(`${lhs} inherits ${rhs}, but ${rhs} is not an interface.`);
        }
        // Check for circular dependencies.
        member.get_inheritance_stack();
    }

    Object.getOwnPropertyNames(this.members).forEach(function(memberName) {
        var member = this.members[memberName];
        if (!(member instanceof IdlInterface)) {
            return;
        }

        var globals = exposure_set(member);
        member.exposed = exposed_in(globals);
        member.exposureSet = globals;
    }.bind(this));

    // Now run test() on every member, and test_object() for every object.
    for (var name in this.members)
    {
        this.members[name].test();
        if (name in this.objects)
        {
            const objects = this.objects[name];
            if (!objects || !Array.isArray(objects)) {
                throw new IdlHarnessError(`Invalid or empty objects for member ${name}`);
            }
            objects.forEach(function(str)
            {
                if (!this.members[name] || !(this.members[name] instanceof IdlInterface)) {
                    throw new IdlHarnessError(`Invalid object member name ${name}`);
                }
                this.members[name].test_object(str);
            }.bind(this));
        }
    }
};

IdlArray.prototype.collapse_partials = function()
{
    const testedPartials = new Map();
    this.partials.forEach(function(parsed_idl)
    {
        const originalExists = parsed_idl.name in this.members
            && (this.members[parsed_idl.name] instanceof IdlInterface
                || this.members[parsed_idl.name] instanceof IdlDictionary
                || this.members[parsed_idl.name] instanceof IdlNamespace);

        // Ensure unique test name in case of multiple partials.
        let partialTestName = parsed_idl.name;
        let partialTestCount = 1;
        if (testedPartials.has(parsed_idl.name)) {
            partialTestCount += testedPartials.get(parsed_idl.name);
            partialTestName = `${partialTestName}[${partialTestCount}]`;
        }
        testedPartials.set(parsed_idl.name, partialTestCount);

        if (!parsed_idl.untested) {
            test(function () {
                assert_true(originalExists, `Original ${parsed_idl.type} should be defined`);

                var expected;
                switch (parsed_idl.type) {
                    case 'dictionary': expected = IdlDictionary; break;
                    case 'namespace': expected = IdlNamespace; break;
                    case 'interface':
                    case 'interface mixin':
                    default:
                        expected = IdlInterface; break;
                }
                assert_true(
                    expected.prototype.isPrototypeOf(this.members[parsed_idl.name]),
                    `Original ${parsed_idl.name} definition should have type ${parsed_idl.type}`);
            }.bind(this), `Partial ${parsed_idl.type} ${partialTestName}: original ${parsed_idl.type} defined`);
        }
        if (!originalExists) {
            // Not good.. but keep calm and carry on.
            return;
        }

        if (parsed_idl.extAttrs)
        {
            // Special-case "Exposed". Must be a subset of original interface's exposure.
            // Exposed on a partial is the equivalent of having the same Exposed on all nested members.
            // See https://github.com/heycam/webidl/issues/154 for discrepency between Exposed and
            // other extended attributes on partial interfaces.
            const exposureAttr = parsed_idl.extAttrs.find(a => a.name === "Exposed");
            if (exposureAttr) {
                if (!parsed_idl.untested) {
                    test(function () {
                        const partialExposure = exposure_set(parsed_idl);
                        const memberExposure = exposure_set(this.members[parsed_idl.name]);
                        partialExposure.forEach(name => {
                            if (!memberExposure || !memberExposure.has(name)) {
                                throw new IdlHarnessError(
                                    `Partial ${parsed_idl.name} ${parsed_idl.type} is exposed to '${name}', the original ${parsed_idl.type} is not.`);
                            }
                        });
                    }.bind(this), `Partial ${parsed_idl.type} ${partialTestName}: valid exposure set`);
                }
                parsed_idl.members.forEach(function (member) {
                    member.extAttrs.push(exposureAttr);
                }.bind(this));
            }

            parsed_idl.extAttrs.forEach(function(extAttr)
            {
                // "Exposed" already handled above.
                if (extAttr.name === "Exposed") {
                    return;
                }
                this.members[parsed_idl.name].extAttrs.push(extAttr);
            }.bind(this));
        }
        if (parsed_idl.members.length) {
            test(function () {
                var clash = parsed_idl.members.find(function(member) {
                    return this.members[parsed_idl.name].members.find(function(m) {
                        return this.are_duplicate_members(m, member);
                    }.bind(this));
                }.bind(this));
                parsed_idl.members.forEach(function(member)
                {
                    this.members[parsed_idl.name].members.push(new IdlInterfaceMember(member));
                }.bind(this));
                assert_true(!clash, "member " + (clash && clash.name) + " is unique");
            }.bind(this), `Partial ${parsed_idl.type} ${partialTestName}: member names are unique`);
        }
    }.bind(this));
    this.partials = [];
}

IdlArray.prototype.are_duplicate_members = function(m1, m2) {
    if (m1.name !== m2.name) {
        return false;
    }
    if (m1.type === 'operation' && m2.type === 'operation'
        && m1.arguments.length !== m2.arguments.length) {
        // Method overload. TODO: Deep comparison of arguments.
        return false;
    }
    return true;
}

IdlArray.prototype.assert_type_is = function(value, type)
{
    if (type.idlType in this.members
    && this.members[type.idlType] instanceof IdlTypedef) {
        this.assert_type_is(value, this.members[type.idlType].idlType);
        return;
    }
    if (type.union) {
        for (var i = 0; i < type.idlType.length; i++) {
            try {
                this.assert_type_is(value, type.idlType[i]);
                // No AssertionError, so we match one type in the union
                return;
            } catch(e) {
                if (e instanceof AssertionError) {
                    // We didn't match this type, let's try some others
                    continue;
                }
                throw e;
            }
        }
        // TODO: Is there a nice way to list the union's types in the message?
        assert_true(false, "Attribute has value " + format_value(value)
                    + " which doesn't match any of the types in the union");

    }

    /**
     * Helper function that tests that value is an instance of type according
     * to the rules of WebIDL.  value is any JavaScript value, and type is an
     * object produced by WebIDLParser.js' "type" production.  That production
     * is fairly elaborate due to the complexity of WebIDL's types, so it's
     * best to look at the grammar to figure out what properties it might have.
     */
    if (type.idlType == "any")
    {
        // No assertions to make
        return;
    }

    if (type.nullable && value === null)
    {
        // This is fine
        return;
    }

    if (type.array)
    {
        // TODO: not supported yet
        return;
    }

    if (type.generic === "sequence")
    {
        assert_true(Array.isArray(value), "should be an Array");
        if (!value.length)
        {
            // Nothing we can do.
            return;
        }
        this.assert_type_is(value[0], type.idlType[0]);
        return;
    }

    if (type.generic === "Promise") {
        assert_true("then" in value, "Attribute with a Promise type should have a then property");
        // TODO: Ideally, we would check on project fulfillment
        // that we get the right type
        // but that would require making the type check async
        return;
    }

    if (type.generic === "FrozenArray") {
        assert_true(Array.isArray(value), "Value should be array");
        assert_true(Object.isFrozen(value), "Value should be frozen");
        if (!value.length)
        {
            // Nothing we can do.
            return;
        }
        this.assert_type_is(value[0], type.idlType[0]);
        return;
    }

    type = Array.isArray(type.idlType) ? type.idlType[0] : type.idlType;

    switch(type)
    {
        case "void":
            assert_equals(value, undefined);
            return;

        case "boolean":
            assert_equals(typeof value, "boolean");
            return;

        case "byte":
            assert_equals(typeof value, "number");
            assert_equals(value, Math.floor(value), "should be an integer");
            assert_true(-128 <= value && value <= 127, "byte " + value + " should be in range [-128, 127]");
            return;

        case "octet":
            assert_equals(typeof value, "number");
            assert_equals(value, Math.floor(value), "should be an integer");
            assert_true(0 <= value && value <= 255, "octet " + value + " should be in range [0, 255]");
            return;

        case "short":
            assert_equals(typeof value, "number");
            assert_equals(value, Math.floor(value), "should be an integer");
            assert_true(-32768 <= value && value <= 32767, "short " + value + " should be in range [-32768, 32767]");
            return;

        case "unsigned short":
            assert_equals(typeof value, "number");
            assert_equals(value, Math.floor(value), "should be an integer");
            assert_true(0 <= value && value <= 65535, "unsigned short " + value + " should be in range [0, 65535]");
            return;

        case "long":
            assert_equals(typeof value, "number");
            assert_equals(value, Math.floor(value), "should be an integer");
            assert_true(-2147483648 <= value && value <= 2147483647, "long " + value + " should be in range [-2147483648, 2147483647]");
            return;

        case "unsigned long":
            assert_equals(typeof value, "number");
            assert_equals(value, Math.floor(value), "should be an integer");
            assert_true(0 <= value && value <= 4294967295, "unsigned long " + value + " should be in range [0, 4294967295]");
            return;

        case "long long":
            assert_equals(typeof value, "number");
            return;

        case "unsigned long long":
        case "DOMTimeStamp":
            assert_equals(typeof value, "number");
            assert_true(0 <= value, "unsigned long long should be positive");
            return;

        case "float":
            assert_equals(typeof value, "number");
            assert_equals(value, fround(value), "float rounded to 32-bit float should be itself");
            assert_not_equals(value, Infinity);
            assert_not_equals(value, -Infinity);
            assert_not_equals(value, NaN);
            return;

        case "DOMHighResTimeStamp":
        case "double":
            assert_equals(typeof value, "number");
            assert_not_equals(value, Infinity);
            assert_not_equals(value, -Infinity);
            assert_not_equals(value, NaN);
            return;

        case "unrestricted float":
            assert_equals(typeof value, "number");
            assert_equals(value, fround(value), "unrestricted float rounded to 32-bit float should be itself");
            return;

        case "unrestricted double":
            assert_equals(typeof value, "number");
            return;

        case "DOMString":
            assert_equals(typeof value, "string");
            return;

        case "ByteString":
            assert_equals(typeof value, "string");
            assert_regexp_match(value, /^[\x00-\x7F]*$/);
            return;

        case "USVString":
            assert_equals(typeof value, "string");
            assert_regexp_match(value, /^([\x00-\ud7ff\ue000-\uffff]|[\ud800-\udbff][\udc00-\udfff])*$/);
            return;

        case "object":
            assert_in_array(typeof value, ["object", "function"], "wrong type: not object or function");
            return;
    }

    if (!(type in this.members))
    {
        throw new IdlHarnessError("Unrecognized type " + type);
    }

    if (this.members[type] instanceof IdlInterface)
    {
        // We don't want to run the full
        // IdlInterface.prototype.test_instance_of, because that could result
        // in an infinite loop.  TODO: This means we don't have tests for
        // NoInterfaceObject interfaces, and we also can't test objects that
        // come from another self.
        assert_in_array(typeof value, ["object", "function"], "wrong type: not object or function");
        if (value instanceof Object
        && !this.members[type].has_extended_attribute("NoInterfaceObject")
        && type in self)
        {
            assert_true(value instanceof self[type], "instanceof " + type);
        }
    }
    else if (this.members[type] instanceof IdlEnum)
    {
        assert_equals(typeof value, "string");
    }
    else if (this.members[type] instanceof IdlDictionary)
    {
        // TODO: Test when we actually have something to test this on
    }
    else if (this.members[type] instanceof IdlCallback)
    {
        assert_equals(typeof value, "function");
    }
    else
    {
        throw new IdlHarnessError("Type " + type + " isn't an interface, callback or dictionary");
    }
};

/// IdlObject ///
function IdlObject() {}
IdlObject.prototype.test = function()
{
    /**
     * By default, this does nothing, so no actual tests are run for IdlObjects
     * that don't define any (e.g., IdlDictionary at the time of this writing).
     */
};

IdlObject.prototype.has_extended_attribute = function(name)
{
    /**
     * This is only meaningful for things that support extended attributes,
     * such as interfaces, exceptions, and members.
     */
    return this.extAttrs.some(function(o)
    {
        return o.name == name;
    });
};


/// IdlDictionary ///
// Used for IdlArray.prototype.assert_type_is
function IdlDictionary(obj)
{
    /**
     * obj is an object produced by the WebIDLParser.js "dictionary"
     * production.
     */

    /** Self-explanatory. */
    this.name = obj.name;

    /** A back-reference to our IdlArray. */
    this.array = obj.array;

    /** An array of objects produced by the "dictionaryMember" production. */
    this.members = obj.members;

    /**
     * The name (as a string) of the dictionary type we inherit from, or null
     * if there is none.
     */
    this.base = obj.inheritance;
}

IdlDictionary.prototype = Object.create(IdlObject.prototype);

IdlDictionary.prototype.get_inheritance_stack = function() {
    return IdlInterface.prototype.get_inheritance_stack.call(this);
};

/// IdlInterface ///
function IdlInterface(obj, is_callback, is_mixin)
{
    /**
     * obj is an object produced by the WebIDLParser.js "interface" production.
     */

    /** Self-explanatory. */
    this.name = obj.name;

    /** A back-reference to our IdlArray. */
    this.array = obj.array;

    /**
     * An indicator of whether we should run tests on the interface object and
     * interface prototype object. Tests on members are controlled by .untested
     * on each member, not this.
     */
    this.untested = obj.untested;

    /** An array of objects produced by the "ExtAttr" production. */
    this.extAttrs = obj.extAttrs;

    /** An array of IdlInterfaceMembers. */
    this.members = obj.members.map(function(m){return new IdlInterfaceMember(m); });
    if (this.has_extended_attribute("Unforgeable")) {
        this.members
            .filter(function(m) { return m.special !== "static" && (m.type == "attribute" || m.type == "operation"); })
            .forEach(function(m) { return m.isUnforgeable = true; });
    }

    /**
     * The name (as a string) of the type we inherit from, or null if there is
     * none.
     */
    this.base = obj.inheritance;

    this._is_callback = is_callback;
    this._is_mixin = is_mixin;
}
IdlInterface.prototype = Object.create(IdlObject.prototype);
IdlInterface.prototype.is_callback = function()
{
    return this._is_callback;
};

IdlInterface.prototype.is_mixin = function()
{
    return this._is_mixin;
};

IdlInterface.prototype.has_constants = function()
{
    return this.members.some(function(member) {
        return member.type === "const";
    });
};

IdlInterface.prototype.get_unscopables = function()
{
    return this.members.filter(function(member) {
        return member.isUnscopable;
    });
};

IdlInterface.prototype.is_global = function()
{
    return this.extAttrs.some(function(attribute) {
        return attribute.name === "Global";
    });
};

/**
 * Value of the LegacyNamespace extended attribute, if any.
 *
 * https://heycam.github.io/webidl/#LegacyNamespace
 */
IdlInterface.prototype.get_legacy_namespace = function()
{
    var legacyNamespace = this.extAttrs.find(function(attribute) {
        return attribute.name === "LegacyNamespace";
    });
    return legacyNamespace ? legacyNamespace.rhs.value : undefined;
};

IdlInterface.prototype.get_interface_object_owner = function()
{
    var legacyNamespace = this.get_legacy_namespace();
    return legacyNamespace ? self[legacyNamespace] : self;
};

IdlInterface.prototype.assert_interface_object_exists = function()
{
    var owner = this.get_legacy_namespace() || "self";
    assert_own_property(self[owner], this.name, owner + " does not have own property " + format_value(this.name));
};

IdlInterface.prototype.get_interface_object = function() {
    if (this.has_extended_attribute("NoInterfaceObject")) {
        throw new IdlHarnessError(this.name + " has no interface object due to NoInterfaceObject");
    }

    return this.get_interface_object_owner()[this.name];
};

IdlInterface.prototype.get_qualified_name = function() {
    // https://heycam.github.io/webidl/#qualified-name
    var legacyNamespace = this.get_legacy_namespace();
    if (legacyNamespace) {
        return legacyNamespace + "." + this.name;
    }
    return this.name;
};

IdlInterface.prototype.has_to_json_regular_operation = function() {
    return this.members.some(function(m) {
        return m.is_to_json_regular_operation();
    });
};

IdlInterface.prototype.has_default_to_json_regular_operation = function() {
    return this.members.some(function(m) {
        return m.is_to_json_regular_operation() && m.has_extended_attribute("Default");
    });
};

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;
    while (idl_interface.base) {
        var 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(',');
            throw new IdlHarnessError(`${this.name} has a circular dependency: ${dep_chain}`);
        }
        idl_interface = base;
        stack.push(idl_interface);
    }
    return stack;
};

/**
 * Implementation of
 * https://heycam.github.io/webidl/#default-tojson-operation
 * for testing purposes.
 *
 * Collects the IDL types of the attributes that meet the criteria
 * for inclusion in the default toJSON operation for easy
 * comparison with actual value
 */
IdlInterface.prototype.default_to_json_operation = function(callback) {
    var map = new Map(), isDefault = false;
    this.traverse_inherited_and_consequential_interfaces(function(I) {
        if (I.has_default_to_json_regular_operation()) {
            isDefault = true;
            I.members.forEach(function(m) {
                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;
};

/**
 * Traverses inherited interfaces from the top down
 * and imeplemented interfaces inside out.
 * Invokes |callback| on each interface.
 *
 * This is an abstract implementation of the traversal
 * algorithm specified in:
 * https://heycam.github.io/webidl/#collect-attribute-values
 * Given the following inheritance tree:
 *
 *           F
 *           |
 *       C   E - I
 *       |   |
 *       B - D
 *       |
 *   G - A - H - J
 *
 * Invoking traverse_inherited_and_consequential_interfaces() on A
 * would traverse the tree in the following order:
 * C -> B -> F -> E -> I -> D -> A -> G -> H -> J
 */

IdlInterface.prototype.traverse_inherited_and_consequential_interfaces = function(callback) {
    if (typeof callback != "function") {
        throw new TypeError();
    }
    var stack = this.get_inheritance_stack();
    _traverse_inherited_and_consequential_interfaces(stack, callback);
};

function _traverse_inherited_and_consequential_interfaces(stack, callback) {
    var I = stack.pop();
    callback(I);
    var mixins = I.array["implements"][I.name] || I.array["includes"][I.name];
    if (mixins) {
        mixins.forEach(function(id) {
            var mixin = I.array.members[id];
            if (!mixin) {
                throw new Error("Interface " + id + " not found (implemented by " + I.name + ")");
            }
            var interfaces = mixin.get_inheritance_stack();
            _traverse_inherited_and_consequential_interfaces(interfaces, callback);
        });
    }
    if (stack.length > 0) {
        _traverse_inherited_and_consequential_interfaces(stack, callback);
    }
}

IdlInterface.prototype.test = function()
{
    if (this.has_extended_attribute("NoInterfaceObject") || this.is_mixin())
    {
        // No tests to do without an instance.  TODO: We should still be able
        // to run tests on the prototype object, if we obtain one through some
        // other means.
        return;
    }

    if (!this.exposed) {
        subsetTestByKey(this.name, test, function() {
            assert_false(this.name in self);
        }.bind(this), this.name + " interface: existence and properties of interface object");
        return;
    }

    if (!this.untested)
    {
        // First test things to do with the exception/interface object and
        // exception/interface prototype object.
        this.test_self();
    }
    // Then test things to do with its members (constants, fields, attributes,
    // operations, . . .).  These are run even if .untested is true, because
    // members might themselves be marked as .untested.  This might happen to
    // interfaces if the interface itself is untested but a partial interface
    // that extends it is tested -- then the interface itself and its initial
    // members will be marked as untested, but the members added by the partial
    // interface are still tested.
    this.test_members();
};

// This supports both Constructor extended attributes and constructor
// operations until all idl fragments have been updated.
IdlInterface.prototype.constructors = function()
{
    var extendedAttributes = this.extAttrs
        .filter(function(attr) { return attr.name == "Constructor"; });
    var operations = this.members
        .filter(function(m) { return m.type == "constructor"; });
    return extendedAttributes.concat(operations);
}

IdlInterface.prototype.test_self = function()
{
    subsetTestByKey(this.name, test, function()
    {
        // This function tests WebIDL as of 2015-01-13.

        // "For every interface that is exposed in a given ECMAScript global
        // environment and:
        // * is a callback interface that has constants declared on it, or
        // * is a non-callback interface that is not declared with the
        //   [NoInterfaceObject] extended attribute,
        // a corresponding property MUST exist on the ECMAScript global object.
        // The name of the property is the identifier of the interface, and its
        // value is an object called the interface object.
        // The property has the attributes { [[Writable]]: true,
        // [[Enumerable]]: false, [[Configurable]]: true }."
        if (this.is_callback() && !this.has_constants()) {
            return;
        }

        // TODO: Should we test here that the property is actually writable
        // etc., or trust getOwnPropertyDescriptor?
        this.assert_interface_object_exists();
        var desc = Object.getOwnPropertyDescriptor(this.get_interface_object_owner(), this.name);
        assert_false("get" in desc, "self's property " + format_value(this.name) + " should not have a getter");
        assert_false("set" in desc, "self's property " + format_value(this.name) + " should not have a setter");
        assert_true(desc.writable, "self's property " + format_value(this.name) + " should be writable");
        assert_false(desc.enumerable, "self's property " + format_value(this.name) + " should not be enumerable");
        assert_true(desc.configurable, "self's property " + format_value(this.name) + " should be configurable");

        if (this.is_callback()) {
            // "The internal [[Prototype]] property of an interface object for
            // a callback interface must be the Function.prototype object."
            assert_equals(Object.getPrototypeOf(this.get_interface_object()), Function.prototype,
                          "prototype of self's property " + format_value(this.name) + " is not Object.prototype");

            return;
        }

        // "The interface object for a given non-callback interface is a
        // function object."
        // "If an object is defined to be a function object, then it has
        // characteristics as follows:"

        // Its [[Prototype]] internal property is otherwise specified (see
        // below).

        // "* Its [[Get]] internal property is set as described in ECMA-262
        //    section 9.1.8."
        // Not much to test for this.

        // "* Its [[Construct]] internal property is set as described in
        //    ECMA-262 section 19.2.2.3."
        // Tested below if no constructor is defined.  TODO: test constructors
        // if defined.

        // "* Its @@hasInstance property is set as described in ECMA-262
        //    section 19.2.3.8, unless otherwise specified."
        // TODO

        // ES6 (rev 30) 19.1.3.6:
        // "Else, if O has a [[Call]] internal method, then let builtinTag be
        // "Function"."
        assert_class_string(this.get_interface_object(), "Function", "class string of " + this.name);

        // "The [[Prototype]] internal property of an interface object for a
        // non-callback interface is determined as follows:"
        var prototype = Object.getPrototypeOf(this.get_interface_object());
        if (this.base) {
            // "* If the interface inherits from some other interface, the
            //    value of [[Prototype]] is the interface object for that other
            //    interface."
            var inherited_interface = this.array.members[this.base];
            if (!inherited_interface.has_extended_attribute("NoInterfaceObject")) {
                inherited_interface.assert_interface_object_exists();
                assert_equals(prototype, inherited_interface.get_interface_object(),
                              'prototype of ' + this.name + ' is not ' +
                              this.base);
            }
        } else {
            // "If the interface doesn't inherit from any other interface, the
            // value of [[Prototype]] is %FunctionPrototype% ([ECMA-262],
            // section 6.1.7.4)."
            assert_equals(prototype, Function.prototype,
                          "prototype of self's property " + format_value(this.name) + " is not Function.prototype");
        }

        if (!this.constructors().length) {
            // "The internal [[Call]] method of the interface object behaves as
            // follows . . .
            //
            // "If I was not declared with a [Constructor] extended attribute,
            // then throw a TypeError."
            var interface_object = this.get_interface_object();
            assert_throws(new TypeError(), function() {
                interface_object();
            }, "interface object didn't throw TypeError when called as a function");
            assert_throws(new TypeError(), function() {
                new interface_object();
            }, "interface object didn't throw TypeError when called as a constructor");
        }
    }.bind(this), this.name + " interface: existence and properties of interface object");

    if (!this.is_callback()) {
        subsetTestByKey(this.name, test, function() {
            // This function tests WebIDL as of 2014-10-25.
            // https://heycam.github.io/webidl/#es-interface-call

            this.assert_interface_object_exists();

            // "Interface objects for non-callback interfaces MUST have a
            // property named “length” with attributes { [[Writable]]: false,
            // [[Enumerable]]: false, [[Configurable]]: true } whose value is
            // a Number."
            assert_own_property(this.get_interface_object(), "length");
            var desc = Object.getOwnPropertyDescriptor(this.get_interface_object(), "length");
            assert_false("get" in desc, this.name + ".length should not have a getter");
            assert_false("set" in desc, this.name + ".length should not have a setter");
            assert_false(desc.writable, this.name + ".length should not be writable");
            assert_false(desc.enumerable, this.name + ".length should not be enumerable");
            assert_true(desc.configurable, this.name + ".length should be configurable");

            var constructors = this.constructors();
            var expected_length = minOverloadLength(constructors);
            assert_equals(this.get_interface_object().length, expected_length, "wrong value for " + this.name + ".length");
        }.bind(this), this.name + " interface object length");
    }

    if (!this.is_callback() || this.has_constants()) {
        subsetTestByKey(this.name, test, function() {
            // This function tests WebIDL as of 2015-11-17.
            // https://heycam.github.io/webidl/#interface-object

            this.assert_interface_object_exists();

            // "All interface objects must have a property named “name” with
            // attributes { [[Writable]]: false, [[Enumerable]]: false,
            // [[Configurable]]: true } whose value is the identifier of the
            // corresponding interface."

            assert_own_property(this.get_interface_object(), "name");
            var desc = Object.getOwnPropertyDescriptor(this.get_interface_object(), "name");
            assert_false("get" in desc, this.name + ".name should not have a getter");
            assert_false("set" in desc, this.name + ".name should not have a setter");
            assert_false(desc.writable, this.name + ".name should not be writable");
            assert_false(desc.enumerable, this.name + ".name should not be enumerable");
            assert_true(desc.configurable, this.name + ".name should be configurable");
            assert_equals(this.get_interface_object().name, this.name, "wrong value for " + this.name + ".name");
        }.bind(this), this.name + " interface object name");
    }


    if (this.has_extended_attribute("LegacyWindowAlias")) {
        subsetTestByKey(this.name, test, function()
        {
            var aliasAttrs = this.extAttrs.filter(function(o) { return o.name === "LegacyWindowAlias"; });
            if (aliasAttrs.length > 1) {
                throw new IdlHarnessError("Invalid IDL: multiple LegacyWindowAlias extended attributes on " + this.name);
            }
            if (this.is_callback()) {
                throw new IdlHarnessError("Invalid IDL: LegacyWindowAlias extended attribute on non-interface " + this.name);
            }
            if (!this.exposureSet.has("Window")) {
                throw new IdlHarnessError("Invalid IDL: LegacyWindowAlias extended attribute on " + this.name + " which is not exposed in Window");
            }
            // TODO: when testing of [NoInterfaceObject] interfaces is supported,
            // check that it's not specified together with LegacyWindowAlias.

            // TODO: maybe check that [LegacyWindowAlias] is not specified on a partial interface.

            var rhs = aliasAttrs[0].rhs;
            if (!rhs) {
                throw new IdlHarnessError("Invalid IDL: LegacyWindowAlias extended attribute on " + this.name + " without identifier");
            }
            var aliases;
            if (rhs.type === "identifier-list") {
                aliases = rhs.value.map(id => id.value);
            } else { // rhs.type === identifier
                aliases = [ rhs.value ];
            }

            // OK now actually check the aliases...
            var alias;
            if (exposed_in(exposure_set(this, this.exposureSet)) && 'document' in self) {
                for (alias of aliases) {
                    assert_true(alias in self, alias + " should exist");
                    assert_equals(self[alias], this.get_interface_object(), "self." + alias + " should be the same value as self." + this.get_qualified_name());
                    var desc = Object.getOwnPropertyDescriptor(self, alias);
                    assert_equals(desc.value, this.get_interface_object(), "wrong value in " + alias + " property descriptor");
                    assert_true(desc.writable, alias + " should be writable");
                    assert_false(desc.enumerable, alias + " should not be enumerable");
                    assert_true(desc.configurable, alias + " should be configurable");
                    assert_false('get' in desc, alias + " should not have a getter");
                    assert_false('set' in desc, alias + " should not have a setter");
                }
            } else {
                for (alias of aliases) {
                    assert_false(alias in self, alias + " should not exist");
                }
            }

        }.bind(this), this.name + " interface: legacy window alias");
    }

    if (this.has_extended_attribute("NamedConstructor")) {
        var constructors = this.extAttrs
            .filter(function(attr) { return attr.name == "NamedConstructor"; });
        if (constructors.length !== 1) {
            throw new IdlHarnessError("Internal error: missing support for multiple NamedConstructor extended attributes");
        }
        var constructor = constructors[0];
        var min_length = minOverloadLength([constructor]);

        subsetTestByKey(this.name, test, function()
        {
            // This function tests WebIDL as of 2019-01-14.

            // "for every [NamedConstructor] extended attribute on an exposed
            // interface, a corresponding property must exist on the ECMAScript
            // global object. The name of the property is the
            // [NamedConstructor]'s identifier, and its value is an object
            // called a named constructor, ... . The property has the attributes
            // { [[Writable]]: true, [[Enumerable]]: false,
            // [[Configurable]]: true }."
            var name = constructor.rhs.value;
            assert_own_property(self, name);
            var desc = Object.getOwnPropertyDescriptor(self, name);
            assert_equals(desc.value, self[name], "wrong value in " + name + " property descriptor");
            assert_true(desc.writable, name + " should be writable");
            assert_false(desc.enumerable, name + " should not be enumerable");
            assert_true(desc.configurable, name + " should be configurable");
            assert_false("get" in desc, name + " should not have a getter");
            assert_false("set" in desc, name + " should not have a setter");
        }.bind(this), this.name + " interface: named constructor");

        subsetTestByKey(this.name, test, function()
        {
            // This function tests WebIDL as of 2019-01-14.

            // "2. Let F be ! CreateBuiltinFunction(realm, steps,
            //     realm.[[Intrinsics]].[[%FunctionPrototype%]])."
            var name = constructor.rhs.value;
            var value = self[name];
            assert_equals(typeof value, "function", "type of value in " + name + " property descriptor");
            assert_not_equals(value, this.get_interface_object(), "wrong value in " + name + " property descriptor");
            assert_equals(Object.getPrototypeOf(value), Function.prototype, "wrong value for " + name + "'s prototype");
        }.bind(this), this.name + " interface: named constructor object");

        subsetTestByKey(this.name, test, function()
        {
            // This function tests WebIDL as of 2019-01-14.

            // "7. Let proto be the interface prototype object of interface I
            //     in realm.
            // "8. Perform ! DefinePropertyOrThrow(F, "prototype",
            //     PropertyDescriptor{
            //         [[Value]]: proto, [[Writable]]: false,
            //         [[Enumerable]]: false, [[Configurable]]: false
            //     })."
            var name = constructor.rhs.value;
            var expected = this.get_interface_object().prototype;
            var desc = Object.getOwnPropertyDescriptor(self[name], "prototype");
            assert_equals(desc.value, expected, "wrong value for " + name + ".prototype");
            assert_false(desc.writable, "prototype should not be writable");
            assert_false(desc.enumerable, "prototype should not be enumerable");
            assert_false(desc.configurable, "prototype should not be configurable");
            assert_false("get" in desc, "prototype should not have a getter");
            assert_false("set" in desc, "prototype should not have a setter");
        }.bind(this), this.name + " interface: named constructor prototype property");

        subsetTestByKey(this.name, test, function()
        {
            // This function tests WebIDL as of 2019-01-14.

            // "3. Perform ! SetFunctionName(F, id)."
            var name = constructor.rhs.value;
            var desc = Object.getOwnPropertyDescriptor(self[name], "name");
            assert_equals(desc.value, name, "wrong value for " + name + ".name");
            assert_false(desc.writable, "name should not be writable");
            assert_false(desc.enumerable, "name should not be enumerable");
            assert_true(desc.configurable, "name should be configurable");
            assert_false("get" in desc, "name should not have a getter");
            assert_false("set" in desc, "name should not have a setter");
        }.bind(this), this.name + " interface: named constructor name");

        subsetTestByKey(this.name, test, function()
        {
            // This function tests WebIDL as of 2019-01-14.

            // "4. Initialize S to the effective overload set for constructors
            //     with identifier id on interface I and with argument count 0.
            // "5. Let length be the length of the shortest argument list of
            //     the entries in S.
            // "6. Perform ! SetFunctionLength(F, length)."
            var name = constructor.rhs.value;
            var desc = Object.getOwnPropertyDescriptor(self[name], "length");
            assert_equals(desc.value, min_length, "wrong value for " + name + ".length");
            assert_false(desc.writable, "length should not be writable");
            assert_false(desc.enumerable, "length should not be enumerable");
            assert_true(desc.configurable, "length should be configurable");
            assert_false("get" in desc, "length should not have a getter");
            assert_false("set" in desc, "length should not have a setter");
        }.bind(this), this.name + " interface: named constructor length");

        subsetTestByKey(this.name, test, function()
        {
            // This function tests WebIDL as of 2019-01-14.

            // "1. Let steps be the following steps:
            // "    1. If NewTarget is undefined, then throw a TypeError."
            var name = constructor.rhs.value;
            var args = constructor.arguments.map(function(arg) {
                return create_suitable_object(arg.idlType);
            });
            assert_throws(new TypeError(), function() {
                self[name](...args);
            }.bind(this));
        }.bind(this), this.name + " interface: named constructor without 'new'");
    }

    subsetTestByKey(this.name, test, function()
    {
        // This function tests WebIDL as of 2015-01-21.
        // https://heycam.github.io/webidl/#interface-object

        if (this.is_callback() && !this.has_constants()) {
            return;
        }

        this.assert_interface_object_exists();

        if (this.is_callback()) {
            assert_false("prototype" in this.get_interface_object(),
                         this.name + ' should not have a "prototype" property');
            return;
        }

        // "An interface object for a non-callback interface must have a
        // property named “prototype” with attributes { [[Writable]]: false,
        // [[Enumerable]]: false, [[Configurable]]: false } whose value is an
        // object called the interface prototype object. This object has
        // properties that correspond to the regular attributes and regular
        // operations defined on the interface, and is described in more detail
        // in section 4.5.4 below."
        assert_own_property(this.get_interface_object(), "prototype",
                            'interface "' + this.name + '" does not have own property "prototype"');
        var desc = Object.getOwnPropertyDescriptor(this.get_interface_object(), "prototype");
        assert_false("get" in desc, this.name + ".prototype should not have a getter");
        assert_false("set" in desc, this.name + ".prototype should not have a setter");
        assert_false(desc.writable, this.name + ".prototype should not be writable");
        assert_false(desc.enumerable, this.name + ".prototype should not be enumerable");
        assert_false(desc.configurable, this.name + ".prototype should not be configurable");

        // Next, test that the [[Prototype]] of the interface prototype object
        // is correct. (This is made somewhat difficult by the existence of
        // [NoInterfaceObject].)
        // TODO: Aryeh thinks there's at least other place in this file where
        //       we try to figure out if an interface prototype object is
        //       correct. Consolidate that code.

        // "The interface prototype object for a given interface A must have an
        // internal [[Prototype]] property whose value is returned from the
        // following steps:
        // "If A is declared with the [Global] extended
        // attribute, and A supports named properties, then return the named
        // properties object for A, as defined in §3.6.4 Named properties
        // object.
        // "Otherwise, if A is declared to inherit from another interface, then
        // return the interface prototype object for the inherited interface.
        // "Otherwise, return %ObjectPrototype%.
        //
        // "In the ECMAScript binding, the DOMException type has some additional
        // requirements:
        //
        //     "Unlike normal interface types, the interface prototype object
        //     for DOMException must have as its [[Prototype]] the intrinsic
        //     object %ErrorPrototype%."
        //
        if (this.name === "Window") {
            assert_class_string(Object.getPrototypeOf(this.get_interface_object().prototype),
                                'WindowProperties',
                                'Class name for prototype of Window' +
                                '.prototype is not "WindowProperties"');
        } else {
            var inherit_interface, inherit_interface_interface_object;
            if (this.base) {
                inherit_interface = this.base;
                var parent = this.array.members[inherit_interface];
                if (!parent.has_extended_attribute("NoInterfaceObject")) {
                    parent.assert_interface_object_exists();
                    inherit_interface_interface_object = parent.get_interface_object();
                }
            } else if (this.name === "DOMException") {
                inherit_interface = 'Error';
                inherit_interface_interface_object = self.Error;
            } else {
                inherit_interface = 'Object';
                inherit_interface_interface_object = self.Object;
            }
            if (inherit_interface_interface_object) {
                assert_not_equals(inherit_interface_interface_object, undefined,
                                  'should inherit from ' + inherit_interface + ', but there is no such property');
                assert_own_property(inherit_interface_interface_object, 'prototype',
                                    'should inherit from ' + inherit_interface + ', but that object has no "prototype" property');
                assert_equals(Object.getPrototypeOf(this.get_interface_object().prototype),
                              inherit_interface_interface_object.prototype,
                              'prototype of ' + this.name + '.prototype is not ' + inherit_interface + '.prototype');
            } else {
                // We can't test that we get the correct object, because this is the
                // only way to get our hands on it. We only test that its class
                // string, at least, is correct.
                assert_class_string(Object.getPrototypeOf(this.get_interface_object().prototype),
                                    inherit_interface + 'Prototype',
                                    'Class name for prototype of ' + this.name +
                                    '.prototype is not "' + inherit_interface + 'Prototype"');
            }
        }

        // "The class string of an interface prototype object is the
        // concatenation of the interface’s qualified identifier and the string
        // “Prototype”."

        // Skip these tests for now due to a specification issue about
        // prototype name.
        // https://www.w3.org/Bugs/Public/show_bug.cgi?id=28244

        // assert_class_string(this.get_interface_object().prototype, this.get_qualified_name() + "Prototype",
        //                     "class string of " + this.name + ".prototype");

        // String() should end up calling {}.toString if nothing defines a
        // stringifier.
        if (!this.has_stringifier()) {
            // assert_equals(String(this.get_interface_object().prototype), "[object " + this.get_qualified_name() + "Prototype]",
            //         "String(" + this.name + ".prototype)");
        }
    }.bind(this), this.name + " interface: existence and properties of interface prototype object");

    // "If the interface is declared with the [Global]
    // extended attribute, or the interface is in the set of inherited
    // interfaces for any other interface that is declared with one of these
    // attributes, then the interface prototype object must be an immutable
    // prototype exotic object."
    // https://heycam.github.io/webidl/#interface-prototype-object
    if (this.is_global()) {
        this.test_immutable_prototype("interface prototype object", this.get_interface_object().prototype);
    }

    subsetTestByKey(this.name, test, function()
    {
        if (this.is_callback() && !this.has_constants()) {
            return;
        }

        this.assert_interface_object_exists();

        if (this.is_callback()) {
            assert_false("prototype" in this.get_interface_object(),
                         this.name + ' should not have a "prototype" property');
            return;
        }

        assert_own_property(this.get_interface_object(), "prototype",
                            'interface "' + this.name + '" does not have own property "prototype"');

        // "If the [NoInterfaceObject] extended attribute was not specified on
        // the interface, then the interface prototype object must also have a
        // property named “constructor” with attributes { [[Writable]]: true,
        // [[Enumerable]]: false, [[Configurable]]: true } whose value is a
        // reference to the interface object for the interface."
        assert_own_property(this.get_interface_object().prototype, "constructor",
                            this.name + '.prototype does not have own property "constructor"');
        var desc = Object.getOwnPropertyDescriptor(this.get_interface_object().prototype, "constructor");
        assert_false("get" in desc, this.name + ".prototype.constructor should not have a getter");
        assert_false("set" in desc, this.name + ".prototype.constructor should not have a setter");
        assert_true(desc.writable, this.name + ".prototype.constructor should be writable");
        assert_false(desc.enumerable, this.name + ".prototype.constructor should not be enumerable");
        assert_true(desc.configurable, this.name + ".prototype.constructor should be configurable");
        assert_equals(this.get_interface_object().prototype.constructor, this.get_interface_object(),
                      this.name + '.prototype.constructor is not the same object as ' + this.name);
    }.bind(this), this.name + ' interface: existence and properties of interface prototype object\'s "constructor" property');


    subsetTestByKey(this.name, test, function()
    {
        if (this.is_callback() && !this.has_constants()) {
            return;
        }

        this.assert_interface_object_exists();

        if (this.is_callback()) {
            assert_false("prototype" in this.get_interface_object(),
                         this.name + ' should not have a "prototype" property');
            return;
        }

        assert_own_property(this.get_interface_object(), "prototype",
                            'interface "' + this.name + '" does not have own property "prototype"');

        // If the interface has any member declared with the [Unscopable] extended
        // attribute, then there must be a property on the interface prototype object
        // whose name is the @@unscopables symbol, which has the attributes
        // { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true },
        // and whose value is an object created as follows...
        var unscopables = this.get_unscopables().map(m => m.name);
        var proto = this.get_interface_object().prototype;
        if (unscopables.length != 0) {
            assert_own_property(
                proto, Symbol.unscopables,
                this.name + '.prototype should have an @@unscopables property');
            var desc = Object.getOwnPropertyDescriptor(proto, Symbol.unscopables);
            assert_false("get" in desc,
                         this.name + ".prototype[Symbol.unscopables] should not have a getter");
            assert_false("set" in desc, this.name + ".prototype[Symbol.unscopables] should not have a setter");
            assert_false(desc.writable, this.name + ".prototype[Symbol.unscopables] should not be writable");
            assert_false(desc.enumerable, this.name + ".prototype[Symbol.unscopables] should not be enumerable");
            assert_true(desc.configurable, this.name + ".prototype[Symbol.unscopables] should be configurable");
            assert_equals(desc.value, proto[Symbol.unscopables],
                          this.name + '.prototype[Symbol.unscopables] should be in the descriptor');
            assert_equals(typeof desc.value, "object",
                          this.name + '.prototype[Symbol.unscopables] should be an object');
            assert_equals(Object.getPrototypeOf(desc.value), null,
                          this.name + '.prototype[Symbol.unscopables] should have a null prototype');
            assert_equals(Object.getOwnPropertySymbols(desc.value).length,
                          0,
                          this.name + '.prototype[Symbol.unscopables] should have the right number of symbol-named properties');

            // Check that we do not have _extra_ unscopables.  Checking that we
            // have all the ones we should will happen in the per-member tests.
            var observed = Object.getOwnPropertyNames(desc.value);
            for (var prop of observed) {
                assert_not_equals(unscopables.indexOf(prop),
                                  -1,
                                  this.name + '.prototype[Symbol.unscopables] has unexpected property "' + prop + '"');
            }
        } else {
            assert_equals(Object.getOwnPropertyDescriptor(this.get_interface_object().prototype, Symbol.unscopables),
                          undefined,
                          this.name + '.prototype should not have @@unscopables');
        }
    }.bind(this), this.name + ' interface: existence and properties of interface prototype object\'s @@unscopables property');
};

IdlInterface.prototype.test_immutable_prototype = function(type, obj)
{
    if (typeof Object.setPrototypeOf !== "function") {
        return;
    }

    subsetTestByKey(this.name, test, function(t) {
        var originalValue = Object.getPrototypeOf(obj);
        var newValue = Object.create(null);

        t.add_cleanup(function() {
            try {
                Object.setPrototypeOf(obj, originalValue);
            } catch (err) {}
        });

        assert_throws(new TypeError(), function() {
            Object.setPrototypeOf(obj, newValue);
        });

        assert_equals(
                Object.getPrototypeOf(obj),
                originalValue,
                "original value not modified"
            );
    }.bind(this), this.name + " interface: internal [[SetPrototypeOf]] method " +
        "of " + type + " - setting to a new value via Object.setPrototypeOf " +
        "should throw a TypeError");

    subsetTestByKey(this.name, test, function(t) {
        var originalValue = Object.getPrototypeOf(obj);
        var newValue = Object.create(null);

        t.add_cleanup(function() {
            var setter = Object.getOwnPropertyDescriptor(
                Object.prototype, '__proto__'
            ).set;

            try {
                setter.call(obj, originalValue);
            } catch (err) {}
        });

        assert_throws(new TypeError(), function() {
            obj.__proto__ = newValue;
        });

        assert_equals(
                Object.getPrototypeOf(obj),
                originalValue,
                "original value not modified"
            );
    }.bind(this), this.name + " interface: internal [[SetPrototypeOf]] method " +
        "of " + type + " - setting to a new value via __proto__ " +
        "should throw a TypeError");

    subsetTestByKey(this.name, test, function(t) {
        var originalValue = Object.getPrototypeOf(obj);
        var newValue = Object.create(null);

        t.add_cleanup(function() {
            try {
                Reflect.setPrototypeOf(obj, originalValue);
            } catch (err) {}
        });

        assert_false(Reflect.setPrototypeOf(obj, newValue));

        assert_equals(
                Object.getPrototypeOf(obj),
                originalValue,
                "original value not modified"
            );
    }.bind(this), this.name + " interface: internal [[SetPrototypeOf]] method " +
        "of " + type + " - setting to a new value via Reflect.setPrototypeOf " +
        "should return false");

    subsetTestByKey(this.name, test, function() {
        var originalValue = Object.getPrototypeOf(obj);

        Object.setPrototypeOf(obj, originalValue);
    }.bind(this), this.name + " interface: internal [[SetPrototypeOf]] method " +
        "of " + type + " - setting to its original value via Object.setPrototypeOf " +
        "should not throw");

    subsetTestByKey(this.name, test, function() {
        var originalValue = Object.getPrototypeOf(obj);

        obj.__proto__ = originalValue;
    }.bind(this), this.name + " interface: internal [[SetPrototypeOf]] method " +
        "of " + type + " - setting to its original value via __proto__ " +
        "should not throw");

    subsetTestByKey(this.name, test, function() {
        var originalValue = Object.getPrototypeOf(obj);

        assert_true(Reflect.setPrototypeOf(obj, originalValue));
    }.bind(this), this.name + " interface: internal [[SetPrototypeOf]] method " +
        "of " + type + " - setting to its original value via Reflect.setPrototypeOf " +
        "should return true");
};

IdlInterface.prototype.test_member_const = function(member)
{
    if (!this.has_constants()) {
        throw new IdlHarnessError("Internal error: test_member_const called without any constants");
    }

    subsetTestByKey(this.name, test, function()
    {
        this.assert_interface_object_exists();

        // "For each constant defined on an interface A, there must be
        // a corresponding property on the interface object, if it
        // exists."
        assert_own_property(this.get_interface_object(), member.name);
        // "The value of the property is that which is obtained by
        // converting the constant’s IDL value to an ECMAScript
        // value."
        assert_equals(this.get_interface_object()[member.name], constValue(member.value),
                      "property has wrong value");
        // "The property has attributes { [[Writable]]: false,
        // [[Enumerable]]: true, [[Configurable]]: false }."
        var desc = Object.getOwnPropertyDescriptor(this.get_interface_object(), member.name);
        assert_false("get" in desc, "property should not have a getter");
        assert_false("set" in desc, "property should not have a setter");
        assert_false(desc.writable, "property should not be writable");
        assert_true(desc.enumerable, "property should be enumerable");
        assert_false(desc.configurable, "property should not be configurable");
    }.bind(this), this.name + " interface: constant " + member.name + " on interface object");

    // "In addition, a property with the same characteristics must
    // exist on the interface prototype object."
    subsetTestByKey(this.name, test, function()
    {
        this.assert_interface_object_exists();

        if (this.is_callback()) {
            assert_false("prototype" in this.get_interface_object(),
                         this.name + ' should not have a "prototype" property');
            return;
        }

        assert_own_property(this.get_interface_object(), "prototype",
                            'interface "' + this.name + '" does not have own property "prototype"');

        assert_own_property(this.get_interface_object().prototype, member.name);
        assert_equals(this.get_interface_object().prototype[member.name], constValue(member.value),
                      "property has wrong value");
        var desc = Object.getOwnPropertyDescriptor(this.get_interface_object(), member.name);
        assert_false("get" in desc, "property should not have a getter");
        assert_false("set" in desc, "property should not have a setter");
        assert_false(desc.writable, "property should not be writable");
        assert_true(desc.enumerable, "property should be enumerable");
        assert_false(desc.configurable, "property should not be configurable");
    }.bind(this), this.name + " interface: constant " + member.name + " on interface prototype object");
};


IdlInterface.prototype.test_member_attribute = function(member)
  {
    if (!shouldRunSubTest(this.name)) {
        return;
    }
    var a_test = subsetTestByKey(this.name, async_test, this.name + " interface: attribute " + member.name);
    a_test.step(function()
    {
        if (this.is_callback() && !this.has_constants()) {
            a_test.done()
            return;
        }

        this.assert_interface_object_exists();
        assert_own_property(this.get_interface_object(), "prototype",
                            'interface "' + this.name + '" does not have own property "prototype"');

        if (member.special === "static") {
            assert_own_property(this.get_interface_object(), member.name,
                "The interface object must have a property " +
                format_value(member.name));
            a_test.done();
            return;
        }

        this.do_member_unscopable_asserts(member);

        if (this.is_global()) {
            assert_own_property(self, member.name,
                "The global object must have a property " +
                format_value(member.name));
            assert_false(member.name in this.get_interface_object().prototype,
                "The prototype object should not have a property " +
                format_value(member.name));

            var getter = Object.getOwnPropertyDescriptor(self, member.name).get;
            assert_equals(typeof(getter), "function",
                          format_value(member.name) + " must have a getter");

            // Try/catch around the get here, since it can legitimately throw.
            // If it does, we obviously can't check for equality with direct
            // invocation of the getter.
            var gotValue;
            var propVal;
            try {
                propVal = self[member.name];
                gotValue = true;
            } catch (e) {
                gotValue = false;
            }
            if (gotValue) {
                assert_equals(propVal, getter.call(undefined),
                              "Gets on a global should not require an explicit this");
            }

            // do_interface_attribute_asserts must be the last thing we do,
            // since it will call done() on a_test.
            this.do_interface_attribute_asserts(self, member, a_test);
        } else {
            assert_true(member.name in this.get_interface_object().prototype,
                "The prototype object must have a property " +
                format_value(member.name));

            if (!member.has_extended_attribute("LenientThis")) {
                if (member.idlType.generic !== "Promise") {
                    assert_throws(new TypeError(), function() {
                        this.get_interface_object().prototype[member.name];
                    }.bind(this), "getting property on prototype object must throw TypeError");
                    // do_interface_attribute_asserts must be the last thing we
                    // do, since it will call done() on a_test.
                    this.do_interface_attribute_asserts(this.get_interface_object().prototype, member, a_test);
                } else {
                    promise_rejects(a_test, new TypeError(),
                                    this.get_interface_object().prototype[member.name])
                        .then(function() {
                            // do_interface_attribute_asserts must be the last
                            // thing we do, since it will call done() on a_test.
                            this.do_interface_attribute_asserts(this.get_interface_object().prototype,
                                                                member, a_test);
                        }.bind(this));
                }
            } else {
                assert_equals(this.get_interface_object().prototype[member.name], undefined,
                              "getting property on prototype object must return undefined");
              // do_interface_attribute_asserts must be the last thing we do,
              // since it will call done() on a_test.
              this.do_interface_attribute_asserts(this.get_interface_object().prototype, member, a_test);
            }
        }
    }.bind(this));
};

IdlInterface.prototype.test_member_operation = function(member)
{
    if (!shouldRunSubTest(this.name)) {
        return;
    }
    var a_test = subsetTestByKey(this.name, async_test, this.name + " interface: operation " + member.name +
                            "(" + member.arguments.map(
                                function(m) {return m.idlType.idlType; } ).join(", ")
                            +")");
    a_test.step(function()
    {
        // This function tests WebIDL as of 2015-12-29.
        // https://heycam.github.io/webidl/#es-operations

        if (this.is_callback() && !this.has_constants()) {
            a_test.done();
            return;
        }

        this.assert_interface_object_exists();

        if (this.is_callback()) {
            assert_false("prototype" in this.get_interface_object(),
                         this.name + ' should not have a "prototype" property');
            a_test.done();
            return;
        }

        assert_own_property(this.get_interface_object(), "prototype",
                            'interface "' + this.name + '" does not have own property "prototype"');

        // "For each unique identifier of an exposed operation defined on the
        // interface, there must exist a corresponding property, unless the
        // effective overload set for that identifier and operation and with an
        // argument count of 0 has no entries."

        // TODO: Consider [Exposed].

        // "The location of the property is determined as follows:"
        var memberHolderObject;
        // "* If the operation is static, then the property exists on the
        //    interface object."
        if (member.special === "static") {
            assert_own_property(this.get_interface_object(), member.name,
                    "interface object missing static operation");
            memberHolderObject = this.get_interface_object();
        // "* Otherwise, [...] if the interface was declared with the [Global]
        //    extended attribute, then the property exists
        //    on every object that implements the interface."
        } else if (this.is_global()) {
            assert_own_property(self, member.name,
                    "global object missing non-static operation");
            memberHolderObject = self;
        // "* Otherwise, the property exists solely on the interface’s
        //    interface prototype object."
        } else {
            assert_own_property(this.get_interface_object().prototype, member.name,
                    "interface prototype object missing non-static operation");
            memberHolderObject = this.get_interface_object().prototype;
        }
        this.do_member_unscopable_asserts(member);
        this.do_member_operation_asserts(memberHolderObject, member, a_test);
    }.bind(this));
};

IdlInterface.prototype.do_member_unscopable_asserts = function(member)
{
    // Check that if the member is unscopable then it's in the
    // @@unscopables object properly.
    if (!member.isUnscopable) {
        return;
    }

    var unscopables = this.get_interface_object().prototype[Symbol.unscopables];
    var prop = member.name;
    var propDesc = Object.getOwnPropertyDescriptor(unscopables, prop);
    assert_equals(typeof propDesc, "object",
                  this.name + '.prototype[Symbol.unscopables].' + prop + ' must exist')
    assert_false("get" in propDesc,
                 this.name + '.prototype[Symbol.unscopables].' + prop + ' must have no getter');
    assert_false("set" in propDesc,
                 this.name + '.prototype[Symbol.unscopables].' + prop + ' must have no setter');
    assert_true(propDesc.writable,
                this.name + '.prototype[Symbol.unscopables].' + prop + ' must be writable');
    assert_true(propDesc.enumerable,
                this.name + '.prototype[Symbol.unscopables].' + prop + ' must be enumerable');
    assert_true(propDesc.configurable,
                this.name + '.prototype[Symbol.unscopables].' + prop + ' must be configurable');
    assert_equals(propDesc.value, true,
                  this.name + '.prototype[Symbol.unscopables].' + prop + ' must have the value `true`');
};

IdlInterface.prototype.do_member_operation_asserts = function(memberHolderObject, member, a_test)
{
    var done = a_test.done.bind(a_test);
    var operationUnforgeable = member.isUnforgeable;
    var desc = Object.getOwnPropertyDescriptor(memberHolderObject, member.name);
    // "The property has attributes { [[Writable]]: B,
    // [[Enumerable]]: true, [[Configurable]]: B }, where B is false if the
    // operation is unforgeable on the interface, and true otherwise".
    assert_false("get" in desc, "property should not have a getter");
    assert_false("set" in desc, "property should not have a setter");
    assert_equals(desc.writable, !operationUnforgeable,
                  "property should be writable if and only if not unforgeable");
    assert_true(desc.enumerable, "property should be enumerable");
    assert_equals(desc.configurable, !operationUnforgeable,
                  "property should be configurable if and only if not unforgeable");
    // "The value of the property is a Function object whose
    // behavior is as follows . . ."
    assert_equals(typeof memberHolderObject[member.name], "function",
                  "property must be a function");

    const ctors = this.members.filter(function(m) {
        return m.type == "operation" && m.name == member.name;
    });
    assert_equals(
        memberHolderObject[member.name].length,
        minOverloadLength(ctors),
        "property has wrong .length");

    // Make some suitable arguments
    var args = member.arguments.map(function(arg) {
        return create_suitable_object(arg.idlType);
    });

    // "Let O be a value determined as follows:
    // ". . .
    // "Otherwise, throw a TypeError."
    // This should be hit if the operation is not static, there is
    // no [ImplicitThis] attribute, and the this value is null.
    //
    // TODO: We currently ignore the [ImplicitThis] case.  Except we manually
    // check for globals, since otherwise we'll invoke window.close().  And we
    // have to skip this test for anything that on the proto chain of "self",
    // since that does in fact have implicit-this behavior.
    if (member.special !== "static") {
        var cb;
        if (!this.is_global() &&
            memberHolderObject[member.name] != self[member.name])
        {
            cb = awaitNCallbacks(2, done);
            throwOrReject(a_test, member, memberHolderObject[member.name], null, args,
                          "calling operation with this = null didn't throw TypeError", cb);
        } else {
            cb = awaitNCallbacks(1, done);
        }

        // ". . . If O is not null and is also not a platform object
        // that implements interface I, throw a TypeError."
        //
        // TODO: Test a platform object that implements some other
        // interface.  (Have to be sure to get inheritance right.)
        throwOrReject(a_test, member, memberHolderObject[member.name], {}, args,
                      "calling operation with this = {} didn't throw TypeError", cb);
    } else {
        done();
    }
}

IdlInterface.prototype.test_to_json_operation = function(desc, memberHolderObject, member) {
    var instanceName = memberHolderObject && memberHolderObject.constructor.name
        || member.name + " object";
    if (member.has_extended_attribute("Default")) {
        subsetTestByKey(this.name, test, function() {
            var map = this.default_to_json_operation();
            var json = memberHolderObject.toJSON();
            map.forEach(function(type, k) {
                assert_true(k in json, "property " + JSON.stringify(k) + " should be present in the output of " + this.name + ".prototype.toJSON()");
                var descriptor = Object.getOwnPropertyDescriptor(json, k);
                assert_true(descriptor.writable, "property " + k + " should be writable");
                assert_true(descriptor.configurable, "property " + k + " should be configurable");
                assert_true(descriptor.enumerable, "property " + k + " should be enumerable");
                this.array.assert_type_is(json[k], type);
                delete json[k];
            }, this);
        }.bind(this), this.name + " interface: default toJSON operation on " + desc);
    } else {
        subsetTestByKey(this.name, test, function() {
            assert_true(this.array.is_json_type(member.idlType), JSON.stringify(member.idlType) + " is not an appropriate return value for the toJSON operation of " + instanceName);
            this.array.assert_type_is(memberHolderObject.toJSON(), member.idlType);
        }.bind(this), this.name + " interface: toJSON operation on " + desc);
    }
};

IdlInterface.prototype.test_member_iterable = function(member)
{
    subsetTestByKey(this.name, test, function()
    {
        var isPairIterator = member.idlType.length === 2;
        var proto = this.get_interface_object().prototype;
        var descriptor = Object.getOwnPropertyDescriptor(proto, Symbol.iterator);

        assert_true(descriptor.writable, "@@iterator property should be writable");
        assert_true(descriptor.configurable, "@@iterator property should be configurable");
        assert_false(descriptor.enumerable, "@@iterator property should not be enumerable");
        assert_equals(typeof descriptor.value, "function", "@@iterator property should be a function");
        assert_equals(descriptor.value.length, 0, "@@iterator function object length should be 0");
        assert_equals(descriptor.value.name, isPairIterator ? "entries" : "values", "@@iterator function object should have the right name");

        if (isPairIterator) {
            assert_equals(proto["entries"], proto[Symbol.iterator], "entries method should be the same as @@iterator method");
        } else {
            assert_equals(proto[Symbol.iterator], Array.prototype[Symbol.iterator], "@@iterator method should be the same as Array prototype's");
            ["entries", "keys", "values", "forEach", Symbol.iterator].forEach(function(property) {
                var propertyName = property === Symbol.iterator ? "@@iterator" : property;
                assert_equals(proto[property], Array.prototype[property], propertyName + " method should be the same as Array prototype's");
            }.bind(this));
        }
    }.bind(this), this.name + " interface: iterable<" + member.idlType.map(function(t) { return t.idlType; }).join(", ") + ">");
};

IdlInterface.prototype.test_member_stringifier = function(member)
{
    subsetTestByKey(this.name, test, function()
    {
        if (this.is_callback() && !this.has_constants()) {
            return;
        }

        this.assert_interface_object_exists();

        if (this.is_callback()) {
            assert_false("prototype" in this.get_interface_object(),
                         this.name + ' should not have a "prototype" property');
            return;
        }

        assert_own_property(this.get_interface_object(), "prototype",
                            'interface "' + this.name + '" does not have own property "prototype"');

        // ". . . the property exists on the interface prototype object."
        var interfacePrototypeObject = this.get_interface_object().prototype;
        assert_own_property(interfacePrototypeObject, "toString",
                "interface prototype object missing non-static operation");

        var stringifierUnforgeable = member.isUnforgeable;
        var desc = Object.getOwnPropertyDescriptor(interfacePrototypeObject, "toString");
        // "The property has attributes { [[Writable]]: B,
        // [[Enumerable]]: true, [[Configurable]]: B }, where B is false if the
        // stringifier is unforgeable on the interface, and true otherwise."
        assert_false("get" in desc, "property should not have a getter");
        assert_false("set" in desc, "property should not have a setter");
        assert_equals(desc.writable, !stringifierUnforgeable,
                      "property should be writable if and only if not unforgeable");
        assert_true(desc.enumerable, "property should be enumerable");
        assert_equals(desc.configurable, !stringifierUnforgeable,
                      "property should be configurable if and only if not unforgeable");
        // "The value of the property is a Function object, which behaves as
        // follows . . ."
        assert_equals(typeof interfacePrototypeObject.toString, "function",
                      "property must be a function");
        // "The value of the Function object’s “length” property is the Number
        // value 0."
        assert_equals(interfacePrototypeObject.toString.length, 0,
            "property has wrong .length");

        // "Let O be the result of calling ToObject on the this value."
        assert_throws(new TypeError(), function() {
            interfacePrototypeObject.toString.apply(null, []);
        }, "calling stringifier with this = null didn't throw TypeError");

        // "If O is not an object that implements the interface on which the
        // stringifier was declared, then throw a TypeError."
        //
        // TODO: Test a platform object that implements some other
        // interface.  (Have to be sure to get inheritance right.)
        assert_throws(new TypeError(), function() {
            interfacePrototypeObject.toString.apply({}, []);
        }, "calling stringifier with this = {} didn't throw TypeError");
    }.bind(this), this.name + " interface: stringifier");
};

IdlInterface.prototype.test_members = function()
{
    for (var i = 0; i < this.members.length; i++)
    {
        var member = this.members[i];
        if (member.untested) {
            continue;
        }

        if (!exposed_in(exposure_set(member, this.exposureSet))) {
            subsetTestByKey(this.name, test, function() {
                // It's not exposed, so we shouldn't find it anywhere.
                assert_false(member.name in this.get_interface_object(),
                             "The interface object must not have a property " +
                             format_value(member.name));
                assert_false(member.name in this.get_interface_object().prototype,
                             "The prototype object must not have a property " +
                             format_value(member.name));
            }.bind(this), this.name + " interface: member " + member.name);
            continue;
        }

        switch (member.type) {
        case "const":
            this.test_member_const(member);
            break;

        case "attribute":
            // For unforgeable attributes, we do the checks in
            // test_interface_of instead.
            if (!member.isUnforgeable)
            {
                this.test_member_attribute(member);
            }
            if (member.special === "stringifier") {
                this.test_member_stringifier(member);
            }
            break;

        case "operation":
            // TODO: Need to correctly handle multiple operations with the same
            // identifier.
            // For unforgeable operations, we do the checks in
            // test_interface_of instead.
            if (member.name) {
                if (!member.isUnforgeable)
                {
                    this.test_member_operation(member);
                }
            } else if (member.special === "stringifier") {
                this.test_member_stringifier(member);
            }
            break;

        case "iterable":
            this.test_member_iterable(member);
            break;
        default:
            // TODO: check more member types.
            break;
        }
    }
};

IdlInterface.prototype.test_object = function(desc)
{
    var obj, exception = null;
    try
    {
        obj = eval(desc);
    }
    catch(e)
    {
        exception = e;
    }

    var expected_typeof =
        this.members.some(function(member) { return member.legacycaller; })
        ? "function"
        : "object";

    this.test_primary_interface_of(desc, obj, exception, expected_typeof);

    var current_interface = this;
    while (current_interface)
    {
        if (!(current_interface.name in this.array.members))
        {
            throw new IdlHarnessError("Interface " + current_interface.name + " not found (inherited by " + this.name + ")");
        }
        if (current_interface.prevent_multiple_testing && current_interface.already_tested)
        {
            return;
        }
        current_interface.test_interface_of(desc, obj, exception, expected_typeof);
        current_interface = this.array.members[current_interface.base];
    }
};

IdlInterface.prototype.test_primary_interface_of = function(desc, obj, exception, expected_typeof)
{
    // Only the object itself, not its members, are tested here, so if the
    // interface is untested, there is nothing to do.
    if (this.untested)
    {
        return;
    }

    // "The internal [[SetPrototypeOf]] method of every platform object that
    // implements an interface with the [Global] extended
    // attribute must execute the same algorithm as is defined for the
    // [[SetPrototypeOf]] internal method of an immutable prototype exotic
    // object."
    // https://heycam.github.io/webidl/#platform-object-setprototypeof
    if (this.is_global())
    {
        this.test_immutable_prototype("global platform object", obj);
    }


    // We can't easily test that its prototype is correct if there's no
    // interface object, or the object is from a different global environment
    // (not instanceof Object).  TODO: test in this case that its prototype at
    // least looks correct, even if we can't test that it's actually correct.
    if (!this.has_extended_attribute("NoInterfaceObject")
    && (typeof obj != expected_typeof || obj instanceof Object))
    {
        subsetTestByKey(this.name, test, function()
        {
            assert_equals(exception, null, "Unexpected exception when evaluating object");
            assert_equals(typeof obj, expected_typeof, "wrong typeof object");
            this.assert_interface_object_exists();
            assert_own_property(this.get_interface_object(), "prototype",
                                'interface "' + this.name + '" does not have own property "prototype"');

            // "The value of the internal [[Prototype]] property of the
            // platform object is the interface prototype object of the primary
            // interface from the platform object’s associated global
            // environment."
            assert_equals(Object.getPrototypeOf(obj),
                          this.get_interface_object().prototype,
                          desc + "'s prototype is not " + this.name + ".prototype");
        }.bind(this), this.name + " must be primary interface of " + desc);
    }

    // "The class string of a platform object that implements one or more
    // interfaces must be the qualified name of the primary interface of the
    // platform object."
    subsetTestByKey(this.name, test, function()
    {
        assert_equals(exception, null, "Unexpected exception when evaluating object");
        assert_equals(typeof obj, expected_typeof, "wrong typeof object");
        assert_class_string(obj, this.get_qualified_name(), "class string of " + desc);
        if (!this.has_stringifier())
        {
            assert_equals(String(obj), "[object " + this.get_qualified_name() + "]", "String(" + desc + ")");
        }
    }.bind(this), "Stringification of " + desc);
};

IdlInterface.prototype.test_interface_of = function(desc, obj, exception, expected_typeof)
{
    // TODO: Indexed and named properties, more checks on interface members
    this.already_tested = true;
    if (!shouldRunSubTest(this.name)) {
        return;
    }

    for (var i = 0; i < this.members.length; i++)
    {
        var member = this.members[i];
        if (member.untested) {
            continue;
        }
        if (!exposed_in(exposure_set(member, this.exposureSet))) {
            subsetTestByKey(this.name, test, function() {
                assert_equals(exception, null, "Unexpected exception when evaluating object");
                assert_false(member.name in obj);
            }.bind(this), this.name + " interface: " + desc + ' must not have property "' + member.name + '"');
            continue;
        }
        if (member.type == "attribute" && member.isUnforgeable)
        {
            var a_test = subsetTestByKey(this.name, async_test, this.name + " interface: " + desc + ' must have own property "' + member.name + '"');
            a_test.step(function() {
                assert_equals(exception, null, "Unexpected exception when evaluating object");
                assert_equals(typeof obj, expected_typeof, "wrong typeof object");
                // Call do_interface_attribute_asserts last, since it will call a_test.done()
                this.do_interface_attribute_asserts(obj, member, a_test);
            }.bind(this));
        }
        else if (member.type == "operation" &&
                 member.name &&
                 member.isUnforgeable)
        {
            var a_test = subsetTestByKey(this.name, async_test, this.name + " interface: " + desc + ' must have own property "' + member.name + '"');
            a_test.step(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, a_test);
            }.bind(this));
        }
        else if ((member.type == "const"
        || member.type == "attribute"
        || member.type == "operation")
        && member.name)
        {
            var described_name = member.name;
            if (member.type == "operation")
            {
                described_name += "(" + member.arguments.map(arg => arg.idlType.idlType).join(", ") + ")";
            }
            subsetTestByKey(this.name, test, function()
            {
                assert_equals(exception, null, "Unexpected exception when evaluating object");
                assert_equals(typeof obj, expected_typeof, "wrong typeof object");
                if (member.special !== "static") {
                    if (!this.is_global()) {
                        assert_inherits(obj, member.name);
                    } else {
                        assert_own_property(obj, member.name);
                    }

                    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
                        {
                            property = obj[member.name];
                        }
                        catch (e)
                        {
                            thrown = true;
                        }
                        if (!thrown)
                        {
                            this.array.assert_type_is(property, member.idlType);
                        }
                    }
                    if (member.type == "operation")
                    {
                        assert_equals(typeof obj[member.name], "function");
                    }
                }
            }.bind(this), this.name + " interface: " + desc + ' must inherit property "' + described_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)
        {
            var a_test = subsetTestByKey(this.name, async_test, this.name + " interface: calling " + member.name +
            "(" + member.arguments.map(function(m) { return m.idlType.idlType; }).join(", ") +
            ") on " + desc + " with too few arguments must throw TypeError");
            a_test.step(function()
            {
                assert_equals(exception, null, "Unexpected exception when evaluating object");
                assert_equals(typeof obj, expected_typeof, "wrong typeof object");
                var fn;
                if (member.special !== "static") {
                    if (!this.is_global() && !member.isUnforgeable) {
                        assert_inherits(obj, member.name);
                    } else {
                        assert_own_property(obj, member.name);
                    }
                    fn = obj[member.name];
                }
                else
                {
                    assert_own_property(obj.constructor, member.name, "interface object must have static operation as own property");
                    fn = obj.constructor[member.name];
                }

                var minLength = minOverloadLength(this.members.filter(function(m) {
                    return m.type == "operation" && m.name == member.name;
                }));
                var args = [];
                var cb = awaitNCallbacks(minLength, a_test.done.bind(a_test));
                for (var i = 0; i < minLength; i++) {
                    throwOrReject(a_test, member, fn, obj, args, "Called with " + i + " arguments", cb);

                    args.push(create_suitable_object(member.arguments[i].idlType));
                }
                if (minLength === 0) {
                    cb();
                }
            }.bind(this));
        }

        if (member.is_to_json_regular_operation()) {
            this.test_to_json_operation(desc, obj, member);
        }
    }
};

IdlInterface.prototype.has_stringifier = function()
{
    if (this.name === "DOMException") {
        // toString is inherited from Error, so don't assume we have the
        // default stringifer
        return true;
    }
    if (this.members.some(function(member) { return member.special === "stringifier"; })) {
        return true;
    }
    if (this.base &&
        this.array.members[this.base].has_stringifier()) {
        return true;
    }
    return false;
};

IdlInterface.prototype.do_interface_attribute_asserts = function(obj, member, a_test)
{
    // This function tests WebIDL as of 2015-01-27.
    // TODO: Consider [Exposed].

    // This is called by test_member_attribute() with the prototype as obj if
    // it is not a global, and the global otherwise, and by test_interface_of()
    // with the object as obj.

    var pendingPromises = [];

    // "For each exposed attribute of the interface, whether it was declared on
    // the interface itself or one of its consequential interfaces, there MUST
    // exist a corresponding property. The characteristics of this property are
    // as follows:"

    // "The name of the property is the identifier of the attribute."
    assert_own_property(obj, member.name);

    // "The property has attributes { [[Get]]: G, [[Set]]: S, [[Enumerable]]:
    // true, [[Configurable]]: configurable }, where:
    // "configurable is false if the attribute was declared with the
    // [Unforgeable] extended attribute and true otherwise;
    // "G is the attribute getter, defined below; and
    // "S is the attribute setter, also defined below."
    var desc = Object.getOwnPropertyDescriptor(obj, member.name);
    assert_false("value" in desc, 'property descriptor should not have a "value" field');
    assert_false("writable" in desc, 'property descriptor should not have a "writable" field');
    assert_true(desc.enumerable, "property should be enumerable");
    if (member.isUnforgeable)
    {
        assert_false(desc.configurable, "[Unforgeable] property must not be configurable");
    }
    else
    {
        assert_true(desc.configurable, "property must be configurable");
    }


    // "The attribute getter is a Function object whose behavior when invoked
    // is as follows:"
    assert_equals(typeof desc.get, "function", "getter must be Function");

    // "If the attribute is a regular attribute, then:"
    if (member.special !== "static") {
        // "If O is not a platform object that implements I, then:
        // "If the attribute was specified with the [LenientThis] extended
        // attribute, then return undefined.
        // "Otherwise, throw a TypeError."
        if (!member.has_extended_attribute("LenientThis")) {
            if (member.idlType.generic !== "Promise") {
                assert_throws(new TypeError(), function() {
                    desc.get.call({});
                }.bind(this), "calling getter on wrong object type must throw TypeError");
            } else {
                pendingPromises.push(
                    promise_rejects(a_test, new TypeError(), desc.get.call({}),
                                    "calling getter on wrong object type must reject the return promise with TypeError"));
            }
        } else {
            assert_equals(desc.get.call({}), undefined,
                          "calling getter on wrong object type must return undefined");
        }
    }

    // "The value of the Function object’s “length” property is the Number
    // value 0."
    assert_equals(desc.get.length, 0, "getter length must be 0");

    // "Let name be the string "get " prepended to attribute’s identifier."
    // "Perform ! SetFunctionName(F, name)."
    assert_equals(desc.get.name, "get " + member.name,
        "getter must have the name 'get " + member.name + "'");


    // TODO: Test calling setter on the interface prototype (should throw
    // TypeError in most cases).
    if (member.readonly
    && !member.has_extended_attribute("LenientSetter")
    && !member.has_extended_attribute("PutForwards")
    && !member.has_extended_attribute("Replaceable"))
    {
        // "The attribute setter is undefined if the attribute is declared
        // readonly and has neither a [PutForwards] nor a [Replaceable]
        // extended attribute declared on it."
        assert_equals(desc.set, undefined, "setter must be undefined for readonly attributes");
    }
    else
    {
        // "Otherwise, it is a Function object whose behavior when
        // invoked is as follows:"
        assert_equals(typeof desc.set, "function", "setter must be function for PutForwards, Replaceable, or non-readonly attributes");

        // "If the attribute is a regular attribute, then:"
        if (member.special !== "static") {
            // "If /validThis/ is false and the attribute was not specified
            // with the [LenientThis] extended attribute, then throw a
            // TypeError."
            // "If the attribute is declared with a [Replaceable] extended
            // attribute, then: ..."
            // "If validThis is false, then return."
            if (!member.has_extended_attribute("LenientThis")) {
                assert_throws(new TypeError(), function() {
                    desc.set.call({});
                }.bind(this), "calling setter on wrong object type must throw TypeError");
            } else {
                assert_equals(desc.set.call({}), undefined,
                              "calling setter on wrong object type must return undefined");
            }
        }

        // "The value of the Function object’s “length” property is the Number
        // value 1."
        assert_equals(desc.set.length, 1, "setter length must be 1");

        // "Let name be the string "set " prepended to id."
        // "Perform ! SetFunctionName(F, name)."
        assert_equals(desc.set.name, "set " + member.name,
            "The attribute setter must have the name 'set " + member.name + "'");
    }

    Promise.all(pendingPromises).then(a_test.done.bind(a_test));
}

/// IdlInterfaceMember ///
function IdlInterfaceMember(obj)
{
    /**
     * obj is an object produced by the WebIDLParser.js "ifMember" production.
     * We just forward all properties to this object without modification,
     * except for special extAttrs handling.
     */
    for (var k in obj.toJSON())
    {
        this[k] = obj[k];
    }
    if (!("extAttrs" in this))
    {
        this.extAttrs = [];
    }

    this.isUnforgeable = this.has_extended_attribute("Unforgeable");
    this.isUnscopable = this.has_extended_attribute("Unscopable");
}

IdlInterfaceMember.prototype = Object.create(IdlObject.prototype);

IdlInterfaceMember.prototype.toJSON = function() {
    return this;
};

IdlInterfaceMember.prototype.is_to_json_regular_operation = function() {
    return this.type == "operation" && this.special !== "static" && this.name == "toJSON";
};

/// Internal helper functions ///
function create_suitable_object(type)
{
    /**
     * type is an object produced by the WebIDLParser.js "type" production.  We
     * return a JavaScript value that matches the type, if we can figure out
     * how.
     */
    if (type.nullable)
    {
        return null;
    }
    switch (type.idlType)
    {
        case "any":
        case "boolean":
            return true;

        case "byte": case "octet": case "short": case "unsigned short":
        case "long": case "unsigned long": case "long long":
        case "unsigned long long": case "float": case "double":
        case "unrestricted float": case "unrestricted double":
            return 7;

        case "DOMString":
        case "ByteString":
        case "USVString":
            return "foo";

        case "object":
            return {a: "b"};

        case "Node":
            return document.createTextNode("abc");
    }
    return null;
}

/// IdlEnum ///
// Used for IdlArray.prototype.assert_type_is
function IdlEnum(obj)
{
    /**
     * obj is an object produced by the WebIDLParser.js "dictionary"
     * production.
     */

    /** Self-explanatory. */
    this.name = obj.name;

    /** An array of values produced by the "enum" production. */
    this.values = obj.values;

}

IdlEnum.prototype = Object.create(IdlObject.prototype);

/// IdlCallback ///
// Used for IdlArray.prototype.assert_type_is
function IdlCallback(obj)
{
    /**
     * obj is an object produced by the WebIDLParser.js "callback"
     * production.
     */

    /** Self-explanatory. */
    this.name = obj.name;

    /** Arguments for the callback. */
    this.arguments = obj.arguments;
}

IdlCallback.prototype = Object.create(IdlObject.prototype);

/// IdlTypedef ///
// Used for IdlArray.prototype.assert_type_is
function IdlTypedef(obj)
{
    /**
     * obj is an object produced by the WebIDLParser.js "typedef"
     * production.
     */

    /** Self-explanatory. */
    this.name = obj.name;

    /** The idlType that we are supposed to be typedeffing to. */
    this.idlType = obj.idlType;

}

IdlTypedef.prototype = Object.create(IdlObject.prototype);

/// IdlNamespace ///
function IdlNamespace(obj)
{
    this.name = obj.name;
    this.extAttrs = obj.extAttrs;
    this.untested = obj.untested;
    /** A back-reference to our IdlArray. */
    this.array = obj.array;

    /** An array of IdlInterfaceMembers. */
    this.members = obj.members.map(m => new IdlInterfaceMember(m));
}

IdlNamespace.prototype = Object.create(IdlObject.prototype);

IdlNamespace.prototype.do_member_operation_asserts = function (memberHolderObject, member, a_test)
{
    var desc = Object.getOwnPropertyDescriptor(memberHolderObject, member.name);

    assert_false("get" in desc, "property should not have a getter");
    assert_false("set" in desc, "property should not have a setter");
    assert_equals(
        desc.writable,
        !member.isUnforgeable,
        "property should be writable if and only if not unforgeable");
    assert_true(desc.enumerable, "property should be enumerable");
    assert_equals(
        desc.configurable,
        !member.isUnforgeable,
        "property should be configurable if and only if not unforgeable");

    assert_equals(
        typeof memberHolderObject[member.name],
        "function",
         "property must be a function");

    assert_equals(
        memberHolderObject[member.name].length,
        minOverloadLength(this.members.filter(function(m) {
            return m.type == "operation" && m.name == member.name;
        })),
        "operation has wrong .length");
    a_test.done();
}

IdlNamespace.prototype.test_member_operation = function(member)
{
    if (!shouldRunSubTest(this.name)) {
        return;
    }
    var args = member.arguments.map(function(a) {
        var s = a.idlType.idlType;
        if (a.variadic) {
            s += '...';
        }
        return s;
    }).join(", ");
    var a_test = subsetTestByKey(
        this.name,
        async_test,
        this.name + ' namespace: operation ' + member.name + '(' + args + ')');
    a_test.step(function() {
        assert_own_property(
            self[this.name],
            member.name,
            'namespace object missing operation ' + format_value(member.name));

        this.do_member_operation_asserts(self[this.name], member, a_test);
    }.bind(this));
};

IdlNamespace.prototype.test_member_attribute = function (member)
{
    if (!shouldRunSubTest(this.name)) {
        return;
    }
    var a_test = subsetTestByKey(
        this.name,
        async_test,
        this.name + ' namespace: attribute ' + member.name);
    a_test.step(function()
    {
        assert_own_property(
            self[this.name],
            member.name,
            this.name + ' does not have property ' + format_value(member.name));

        var desc = Object.getOwnPropertyDescriptor(self[this.name], member.name);
        assert_equals(desc.set, undefined, "setter must be undefined for namespace members");
        a_test.done();
    }.bind(this));
};

IdlNamespace.prototype.test = function ()
{
    /**
     * TODO(lukebjerring): Assert:
     * - "Note that unlike interfaces or dictionaries, namespaces do not create types."
     * - "Of the extended attributes defined in this specification, only the
     *     [Exposed] and [SecureContext] extended attributes are applicable to namespaces."
     * - "Namespaces must be annotated with the [Exposed] extended attribute."
     */

    for (const v of Object.values(this.members)) {
        switch (v.type) {

        case 'operation':
            this.test_member_operation(v);
            break;

        case 'attribute':
            this.test_member_attribute(v);
            break;

        default:
            throw 'Invalid namespace member ' + v.name + ': ' + v.type + ' not supported';
        }
    };
};

}());

/**
 * idl_test is a promise_test wrapper that handles the fetching of the IDL,
 * avoiding repetitive boilerplate.
 *
 * @param {String|String[]} srcs Spec name(s) for source idl files (fetched from
 *      /interfaces/{name}.idl).
 * @param {String|String[]} deps Spec name(s) for dependency idl files (fetched
 *      from /interfaces/{name}.idl). Order is important - dependencies from
 *      each source will only be included if they're already know to be a
 *      dependency (i.e. have already been seen).
 * @param {Function} setup_func Function for extra setup of the idl_array, such
 *      as adding objects. Do not call idl_array.test() in the setup; it is
 *      called by this function (idl_test).
 */
function idl_test(srcs, deps, idl_setup_func) {
    return promise_test(function (t) {
        var idl_array = new IdlArray();
        srcs = (srcs instanceof Array) ? srcs : [srcs] || [];
        deps = (deps instanceof Array) ? deps : [deps] || [];
        var setup_error = null;
        const validationIgnored = [
            "constructor-member",
            "dict-arg-default",
            "require-exposed"
        ];
        return Promise.all(
            srcs.concat(deps).map(fetch_spec))
            .then(function(results) {
                const astArray = results.map(result =>
                    WebIDL2.parse(result.idl, { sourceName: result.spec })
                );
                test(() => {
                    const validations = WebIDL2.validate(astArray)
                        .filter(v => !validationIgnored.includes(v.ruleName));
                    if (validations.length) {
                        const message = validations.map(v => v.message).join("\n\n");
                        throw new Error(message);
                    }
                }, "idl_test validation");
                for (var i = 0; i < srcs.length; i++) {
                    idl_array.internal_add_idls(astArray[i]);
                }
                for (var i = srcs.length; i < srcs.length + deps.length; i++) {
                    idl_array.internal_add_dependency_idls(astArray[i]);
                }
            })
            .then(function() {
                if (idl_setup_func) {
                    return idl_setup_func(idl_array, t);
                }
            })
            .catch(function(e) { setup_error = e || 'IDL setup failed.'; })
            .then(function () {
                var error = setup_error;
                try {
                    idl_array.test(); // Test what we can.
                } catch (e) {
                    // If testing fails hard here, the original setup error
                    // is more likely to be the real cause.
                    error = error || e;
                }
                if (error) {
                    throw error;
                }
            });
    }, 'idl_test setup');
}

/**
 * fetch_spec is a shorthand for a Promise that fetches the spec's content.
 */
function fetch_spec(spec) {
    var url = '/interfaces/' + spec + '.idl';
    return fetch(url).then(function (r) {
        if (!r.ok) {
            throw new IdlHarnessError("Error fetching " + url + ".");
        }
        return r.text();
    }).then(idl => ({ spec, idl }));
}
// vim: set expandtab shiftwidth=4 tabstop=4 foldmarker=@{,@} foldmethod=marker:
