/*
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"] = {};
};

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)
{
    const parsed_idls = WebIDL2.parse(raw_idls);
    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.map(p => p.name).forEach(v => all_deps.add(v));
    // Add the attribute idlTypes of all the nested members of all tested idls.
    for (const obj of [this.members, this.partials]) {
        const tested = Object.values(obj).filter(m => !m.untested && m.members);
        for (const parsed of tested) {
            for (const attr of Object.values(parsed.members).filter(m => !m.untested && m.type === 'attribute')) {
                all_deps.add(attr.idlType.idlType);
            }
        }
    }

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

    const should_skip = 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);
    }
    // Record of skipped items, in case we later determine they are a dependency.
    // Maps name -> [parsed_idl, ...]
    const skipped = new Map();
    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 || should_skip(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)) {
                    skipped.has(name)
                        ? skipped.get(name).push(parsed)
                        : 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 (skipped.has(deferred)) {
                    const next = skipped.get(deferred);
                    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":
            // TODO
            console.log("callback not yet supported");
            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);
    }

    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) {
        var set = exposed[0].rhs.value;
        // Could be a list or a string.
        if (typeof set == "string") {
            set = [ set ];
        }
        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.";
            this.members[rhs].members.forEach(function(member)
            {
                this.members[lhs].members.push(new IdlInterfaceMember(member));
            }.bind(this));
        }.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.";
            this.members[rhs].members.forEach(function(member)
            {
                this.members[lhs].members.push(new IdlInterfaceMember(member));
            }.bind(this));
        }.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);

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

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

                var expected = IdlInterface;
                switch (parsed_idl.type) {
                    case 'interface': expected = IdlInterface; break;
                    case 'dictionary': expected = IdlDictionary; break;
                    case 'namespace': expected = IdlNamespace; 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));
        }
        parsed_idl.members.forEach(function(member)
        {
            this.members[parsed_idl.name].members.push(new IdlInterfaceMember(member));
        }.bind(this));
    }.bind(this));
    this.partials = [];
}

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);
        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);
        return;
    }

    type = 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
    {
        throw new IdlHarnessError("Type " + type + " isn't an interface 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["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.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();
};

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.has_extended_attribute("Constructor")) {
            // "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.extAttrs
                .filter(function(attr) { return attr.name == "Constructor"; });
            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;
            } 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["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["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["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.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.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["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["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.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["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["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)
    {
        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.is_to_json_regular_operation = function() {
    return this.type == "operation" && !this.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);

/// 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;
        return Promise.all(
            srcs.concat(deps).map(function(spec) {
                return fetch_spec(spec);
            }))
            .then(function(idls) {
                for (var i = 0; i < srcs.length; i++) {
                    idl_array.add_idls(idls[i]);
                }
                for (var i = srcs.length; i < srcs.length + deps.length; i++) {
                    idl_array.add_dependency_idls(idls[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();
    });
}
// vim: set expandtab shiftwidth=4 tabstop=4 foldmarker=@{,@} foldmethod=marker:
