Bug 1491890 [wpt PR 13032] - Improve the wasm idlharness test., a=testonly
authormoz-wptsync-bot <wptsync@mozilla.com>
Tue, 16 Oct 2018 09:47:10 +0000
changeset 500218 dc8dee7c2ab4ae9d505064b5d1af4ef5ee56a72f
parent 500217 8fcf84551a98592506dcd67cb4adff7a3b7b74ef
child 500219 60b569f455dd3d918c1e6858bc7c138dcf9a0c75
push id1864
push userffxbld-merge
push dateMon, 03 Dec 2018 15:51:40 +0000
treeherdermozilla-release@f040763d99ad [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerstestonly
bugs1491890, 13032
milestone64.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1491890 [wpt PR 13032] - Improve the wasm idlharness test., a=testonly Automatic update from web-platform-testsIdlHarness: Extract code that checks for interface objects on self. -- IdlHarness: Support LegacyNamespace in interface object checks. -- IdlHarness: Support LegacyNamespace in class string checks. -- Fix some bugs in wasm/idlharness.any.js. -- Move wasm/idlharness.any.js to the jsapi subdirectory. It only tests the IDL from the jsapi specification. -- wpt-commits: df681aeacb197d9690fff1160e8d6362fd872000, 10c3854cbb09b63f0af8a6624dd7e87edba031ff, e77d06135f5dc72398d0a562ce53da90ad6a0968, ebefd2d309525024a8a57f435aef5ee683846013, a69af5481cdd976c9696f97d9c6547ac87ba83d0 wpt-pr: 13032
testing/web-platform/tests/resources/idlharness.js
testing/web-platform/tests/resources/test/tests/unit/IdlInterface/get_interface_object.html
testing/web-platform/tests/resources/test/tests/unit/IdlInterface/get_interface_object_owner.html
testing/web-platform/tests/resources/test/tests/unit/IdlInterface/get_legacy_namespace.html
testing/web-platform/tests/resources/test/tests/unit/IdlInterface/get_qualified_name.html
testing/web-platform/tests/wasm/idlharness.any.js
testing/web-platform/tests/wasm/jsapi/idlharness.any.js
testing/web-platform/tests/wasm/resources/load_wasm.js
--- a/testing/web-platform/tests/resources/idlharness.js
+++ b/testing/web-platform/tests/resources/idlharness.js
@@ -1251,16 +1251,58 @@ IdlInterface.prototype.get_unscopables =
 
 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) {
@@ -1431,29 +1473,28 @@ IdlInterface.prototype.test_self = funct
         // 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?
-        assert_own_property(self, this.name,
-                            "self does not have own property " + format_value(this.name));
-        var desc = Object.getOwnPropertyDescriptor(self, this.name);
+        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(self[this.name]), Function.prototype,
+            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
@@ -1473,34 +1514,29 @@ IdlInterface.prototype.test_self = funct
 
         // "* 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(self[this.name], "Function", "class string of " + this.name);
+        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(self[this.name]);
+        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 has_interface_object =
-                !this.array
-                     .members[this.base]
-                     .has_extended_attribute("NoInterfaceObject");
-            if (has_interface_object) {
-                assert_own_property(self, this.base,
-                                    'should inherit from ' + this.base +
-                                    ', but self has no such property');
-                assert_equals(prototype, self[this.base],
+            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,
@@ -1508,73 +1544,72 @@ IdlInterface.prototype.test_self = funct
         }
 
         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() {
-                self[this.name]();
-            }.bind(this), "interface object didn't throw TypeError when called as a function");
+                interface_object();
+            }, "interface object didn't throw TypeError when called as a function");
             assert_throws(new TypeError(), function() {
-                new self[this.name]();
-            }.bind(this), "interface object didn't throw TypeError when called as a constructor");
+                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
 
-            assert_own_property(self, this.name,
-                                "self does not have own property " + format_value(this.name));
+            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(self[this.name], "length");
-            var desc = Object.getOwnPropertyDescriptor(self[this.name], "length");
+            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(self[this.name].length, expected_length, "wrong value for " + this.name + ".length");
+            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
 
-            assert_own_property(self, this.name,
-                                "self does not have own property " + format_value(this.name));
+            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(self[this.name], "name");
-            var desc = Object.getOwnPropertyDescriptor(self[this.name], "name");
+            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(self[this.name].name, this.name, "wrong value for " + this.name + ".name");
+            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"; });
@@ -1603,19 +1638,19 @@ IdlInterface.prototype.test_self = funct
                 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], self[this.name], "self." + alias + " should be the same value as self." + this.name);
+                    assert_equals(self[alias], this.get_interface_object(), "self." + alias + " should be the same value as the interface object");
                     var desc = Object.getOwnPropertyDescriptor(self, alias);
-                    assert_equals(desc.value, self[this.name], "wrong value in " + alias + " property descriptor");
+                    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) {
@@ -1631,35 +1666,34 @@ IdlInterface.prototype.test_self = funct
     {
         // This function tests WebIDL as of 2015-01-21.
         // https://heycam.github.io/webidl/#interface-object
 
         if (this.is_callback() && !this.has_constants()) {
             return;
         }
 
-        assert_own_property(self, this.name,
-                            "self does not have own property " + format_value(this.name));
+        this.assert_interface_object_exists();
 
         if (this.is_callback()) {
-            assert_false("prototype" in self[this.name],
+            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(self[this.name], "prototype",
+        assert_own_property(this.get_interface_object(), "prototype",
                             'interface "' + this.name + '" does not have own property "prototype"');
-        var desc = Object.getOwnPropertyDescriptor(self[this.name], "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
@@ -1682,144 +1716,143 @@ IdlInterface.prototype.test_self = funct
         // "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(self[this.name].prototype),
+            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_has_interface_object;
+            var inherit_interface, inherit_interface_interface_object;
             if (this.base) {
                 inherit_interface = this.base;
-                inherit_interface_has_interface_object =
-                    !this.array
-                         .members[inherit_interface]
-                         .has_extended_attribute("NoInterfaceObject");
+                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_has_interface_object = true;
+                inherit_interface_interface_object = self.Error;
             } else {
                 inherit_interface = 'Object';
-                inherit_interface_has_interface_object = true;
+                inherit_interface_interface_object = self.Object;
             }
-            if (inherit_interface_has_interface_object) {
-                assert_own_property(self, inherit_interface,
-                                    'should inherit from ' + inherit_interface + ', but self has no such property');
-                assert_own_property(self[inherit_interface], 'prototype',
+            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(self[this.name].prototype),
-                              self[inherit_interface].prototype,
+                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(self[this.name].prototype),
+                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 identifier and the string
+        // 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(self[this.name].prototype, this.name + "Prototype",
+        // 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(self[this.name].prototype), "[object " + this.name + "Prototype]",
+            // 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", self[this.name].prototype);
+        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;
         }
 
-        assert_own_property(self, this.name,
-                            "self does not have own property " + format_value(this.name));
+        this.assert_interface_object_exists();
 
         if (this.is_callback()) {
-            assert_false("prototype" in self[this.name],
+            assert_false("prototype" in this.get_interface_object(),
                          this.name + ' should not have a "prototype" property');
             return;
         }
 
-        assert_own_property(self[this.name], "prototype",
+        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(self[this.name].prototype, "constructor",
+        assert_own_property(this.get_interface_object().prototype, "constructor",
                             this.name + '.prototype does not have own property "constructor"');
-        var desc = Object.getOwnPropertyDescriptor(self[this.name].prototype, "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(self[this.name].prototype.constructor, self[this.name],
+        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;
         }
 
-        assert_own_property(self, this.name,
-                            "self does not have own property " + format_value(this.name));
+        this.assert_interface_object_exists();
 
         if (this.is_callback()) {
-            assert_false("prototype" in self[this.name],
+            assert_false("prototype" in this.get_interface_object(),
                          this.name + ' should not have a "prototype" property');
             return;
         }
 
-        assert_own_property(self[this.name], "prototype",
+        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 = self[this.name].prototype;
+        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");
@@ -1831,25 +1864,28 @@ IdlInterface.prototype.test_self = funct
             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');
 
-            // It would be nice to check that we do not have _extra_
-            // unscopables, but someone might be calling us with only a subset
-            // of the IDL the browser know about, and our subset may exclude
-            // unscopable things that really do exist.
+            // 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 {
-            // It would be nice to assert that there is no @@unscopables on this
-            // prototype, but someone might be calling us with only a subset of
-            // the IDL the browser know about, and our subset may exclude
-            // unscopable things that really do exist.
+            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;
@@ -1954,58 +1990,56 @@ IdlInterface.prototype.test_immutable_pr
 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()
     {
-        assert_own_property(self, this.name,
-                            "self does not have own property " + format_value(this.name));
+        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(self[this.name], member.name);
+        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(self[this.name][member.name], constValue(member.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(self[this.name], member.name);
+        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()
     {
-        assert_own_property(self, this.name,
-                            "self does not have own property " + format_value(this.name));
+        this.assert_interface_object_exists();
 
         if (this.is_callback()) {
-            assert_false("prototype" in self[this.name],
+            assert_false("prototype" in this.get_interface_object(),
                          this.name + ' should not have a "prototype" property');
             return;
         }
 
-        assert_own_property(self[this.name], "prototype",
+        assert_own_property(this.get_interface_object(), "prototype",
                             'interface "' + this.name + '" does not have own property "prototype"');
 
-        assert_own_property(self[this.name].prototype, member.name);
-        assert_equals(self[this.name].prototype[member.name], constValue(member.value),
+        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(self[this.name], member.name);
+        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");
 };
 
@@ -2018,36 +2052,35 @@ IdlInterface.prototype.test_member_attri
     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;
         }
 
-        assert_own_property(self, this.name,
-                            "self does not have own property " + format_value(this.name));
-        assert_own_property(self[this.name], "prototype",
+        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(self[this.name], member.name,
+            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 self[this.name].prototype,
+            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.
@@ -2065,44 +2098,44 @@ IdlInterface.prototype.test_member_attri
                 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 self[this.name].prototype,
+            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() {
-                        self[this.name].prototype[member.name];
+                        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(self[this.name].prototype, member, a_test);
+                    this.do_interface_attribute_asserts(this.get_interface_object().prototype, member, a_test);
                 } else {
                     promise_rejects(a_test, new TypeError(),
-                                    self[this.name].prototype[member.name])
+                                    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(self[this.name].prototype,
+                            this.do_interface_attribute_asserts(this.get_interface_object().prototype,
                                                                 member, a_test);
                         }.bind(this));
                 }
             } else {
-                assert_equals(self[this.name].prototype[member.name], undefined,
+                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(self[this.name].prototype, member, 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)) {
@@ -2117,74 +2150,71 @@ IdlInterface.prototype.test_member_opera
         // 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;
         }
 
-        assert_own_property(self, this.name,
-                            "self does not have own property " + format_value(this.name));
+        this.assert_interface_object_exists();
 
         if (this.is_callback()) {
-            assert_false("prototype" in self[this.name],
+            assert_false("prototype" in this.get_interface_object(),
                          this.name + ' should not have a "prototype" property');
             a_test.done();
             return;
         }
 
-        assert_own_property(self[this.name], "prototype",
+        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(self[this.name], member.name,
+            assert_own_property(this.get_interface_object(), member.name,
                     "interface object missing static operation");
-            memberHolderObject = self[this.name];
+            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(self[this.name].prototype, member.name,
+            assert_own_property(this.get_interface_object().prototype, member.name,
                     "interface prototype object missing non-static operation");
-            memberHolderObject = self[this.name].prototype;
+            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 = self[this.name].prototype[Symbol.unscopables];
-    assert_equals(typeof unscopables, "object",
-                  this.name + '.prototype[Symbol.unscopables] must exist');
+    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');
@@ -2302,63 +2332,61 @@ IdlInterface.prototype.test_to_json_oper
             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), "Test toJSON operation of " + instanceName);
     }
 };
 
 IdlInterface.prototype.test_member_iterable = function(member)
 {
-    var interfaceName = this.name;
     var isPairIterator = member.idlType.length === 2;
     subsetTestByKey(this.name, test, function()
     {
-        var descriptor = Object.getOwnPropertyDescriptor(self[interfaceName].prototype, Symbol.iterator);
+        var descriptor = Object.getOwnPropertyDescriptor(this.get_interface_object().prototype, Symbol.iterator);
         assert_true(descriptor.writable, "property should be writable");
         assert_true(descriptor.configurable, "property should be configurable");
         assert_false(descriptor.enumerable, "property should not be enumerable");
-        assert_equals(self[interfaceName].prototype[Symbol.iterator].name, isPairIterator ? "entries" : "values", "@@iterator function does not have the right name");
-    }, "Testing Symbol.iterator property of iterable interface " + interfaceName);
+        assert_equals(this.get_interface_object().prototype[Symbol.iterator].name, isPairIterator ? "entries" : "values", "@@iterator function does not have the right name");
+    }.bind(this), "Testing Symbol.iterator property of iterable interface " + this.name);
 
     if (isPairIterator) {
         subsetTestByKey(this.name, test, function() {
-            assert_equals(self[interfaceName].prototype[Symbol.iterator], self[interfaceName].prototype["entries"], "entries method is not the same as @@iterator");
-        }, "Testing pair iterable interface " + interfaceName);
+            assert_equals(this.get_interface_object().prototype[Symbol.iterator], this.get_interface_object().prototype["entries"], "entries method is not the same as @@iterator");
+        }.bind(this), "Testing pair iterable interface " + this.name);
     } else {
         subsetTestByKey(this.name, test, function() {
             ["entries", "keys", "values", "forEach", Symbol.Iterator].forEach(function(property) {
-                assert_equals(self[interfaceName].prototype[property], Array.prototype[property], property + " function is not the same as Array one");
-            });
-        }, "Testing value iterable interface " + interfaceName);
+                assert_equals(this.get_interface_object().prototype[property], Array.prototype[property], property + " function is not the same as Array one");
+            }.bind(this));
+        }.bind(this), "Testing value iterable interface " + this.name);
     }
 };
 
 IdlInterface.prototype.test_member_stringifier = function(member)
 {
     subsetTestByKey(this.name, test, function()
     {
         if (this.is_callback() && !this.has_constants()) {
             return;
         }
 
-        assert_own_property(self, this.name,
-                            "self does not have own property " + format_value(this.name));
+        this.assert_interface_object_exists();
 
         if (this.is_callback()) {
-            assert_false("prototype" in self[this.name],
+            assert_false("prototype" in this.get_interface_object(),
                          this.name + ' should not have a "prototype" property');
             return;
         }
 
-        assert_own_property(self[this.name], "prototype",
+        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 = self[this.name].prototype;
-        assert_own_property(self[this.name].prototype, "toString",
+        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");
@@ -2374,26 +2402,26 @@ IdlInterface.prototype.test_member_strin
                       "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() {
-            self[this.name].prototype.toString.apply(null, []);
+            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() {
-            self[this.name].prototype.toString.apply({}, []);
+            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++)
     {
@@ -2413,20 +2441,20 @@ IdlInterface.prototype.test_members = fu
         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 self[this.name],
+                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 self[this.name].prototype,
+                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":
@@ -2532,42 +2560,41 @@ IdlInterface.prototype.test_primary_inte
     // 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");
-            assert_own_property(self, this.name,
-                                "self does not have own property " + format_value(this.name));
-            assert_own_property(self[this.name], "prototype",
+            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),
-                          self[this.name].prototype,
+                          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 identifier of the primary interface of the
+    // 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.name, "class string of " + desc);
+        assert_class_string(obj, this.get_qualified_name(), "class string of " + desc);
         if (!this.has_stringifier())
         {
-            assert_equals(String(obj), "[object " + this.name + "]", "String(" + desc + ")");
+            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;
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/resources/test/tests/unit/IdlInterface/get_interface_object.html
@@ -0,0 +1,22 @@
+<!DOCTYPE HTML>
+<title>IdlInterface.prototype.get_interface_object()</title>
+<div id="log"></div>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/WebIDLParser.js"></script>
+<script src="/resources/idlharness.js"></script>
+<script src="../../../idl-helper.js"></script>
+<script>
+"use strict";
+test(function() {
+    window.A = {};
+    var i = interfaceFrom('interface A { };');
+    assert_equals(i.get_interface_object(), window.A);
+}, 'Interface does not have LegacyNamespace.');
+
+test(function() {
+    window.Foo = { A: {} };
+    var i = interfaceFrom('[LegacyNamespace=Foo] interface A { }; namespace Foo { };');
+    assert_equals(i.get_interface_object(), window.Foo.A);
+}, 'Interface has LegacyNamespace');
+</script>
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/resources/test/tests/unit/IdlInterface/get_interface_object_owner.html
@@ -0,0 +1,21 @@
+<!DOCTYPE HTML>
+<title>IdlInterface.prototype.get_interface_object_owner()</title>
+<div id="log"></div>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/WebIDLParser.js"></script>
+<script src="/resources/idlharness.js"></script>
+<script src="../../../idl-helper.js"></script>
+<script>
+"use strict";
+test(function() {
+    var i = interfaceFrom('interface A { };');
+    assert_equals(i.get_interface_object_owner(), window);
+}, 'Interface does not have LegacyNamespace.');
+
+test(function() {
+    window.Foo = {};
+    var i = interfaceFrom('[LegacyNamespace=Foo] interface A { }; namespace Foo { };');
+    assert_equals(i.get_interface_object_owner(), window.Foo);
+}, 'Interface has LegacyNamespace');
+</script>
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/resources/test/tests/unit/IdlInterface/get_legacy_namespace.html
@@ -0,0 +1,20 @@
+<!DOCTYPE HTML>
+<title>IdlInterface.prototype.get_legacy_namespace()</title>
+<div id="log"></div>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/WebIDLParser.js"></script>
+<script src="/resources/idlharness.js"></script>
+<script src="../../../idl-helper.js"></script>
+<script>
+"use strict";
+test(function() {
+    var i = interfaceFrom('interface A { };');
+    assert_equals(i.get_legacy_namespace(), undefined);
+}, 'Interface does not have LegacyNamespace.');
+
+test(function() {
+    var i = interfaceFrom('[LegacyNamespace=Foo] interface A { }; namespace Foo { };');
+    assert_equals(i.get_legacy_namespace(), "Foo");
+}, 'Interface has LegacyNamespace');
+</script>
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/resources/test/tests/unit/IdlInterface/get_qualified_name.html
@@ -0,0 +1,20 @@
+<!DOCTYPE HTML>
+<title>IdlInterface.prototype.get_qualified_name()</title>
+<div id="log"></div>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/WebIDLParser.js"></script>
+<script src="/resources/idlharness.js"></script>
+<script src="../../../idl-helper.js"></script>
+<script>
+"use strict";
+test(function() {
+    var i = interfaceFrom('interface A { };');
+    assert_equals(i.get_qualified_name(), "A");
+}, 'Interface does not have LegacyNamespace.');
+
+test(function() {
+    var i = interfaceFrom('[LegacyNamespace=Foo] interface A { }; namespace Foo { };');
+    assert_equals(i.get_qualified_name(), "Foo.A");
+}, 'Interface has LegacyNamespace');
+</script>
deleted file mode 100644
--- a/testing/web-platform/tests/wasm/idlharness.any.js
+++ /dev/null
@@ -1,33 +0,0 @@
-// META: script=/resources/WebIDLParser.js
-// META: script=/resources/idlharness.js
-// META: script=resources/load_wasm.js
-
-'use strict';
-
-// https://webassembly.github.io/spec/js-api/
-
-promise_test(async () => {
-  const srcs = ['wasm-js-api'];
-  const [wasm] = await Promise.all(
-    srcs.map(i => fetch(`/interfaces/${i}.idl`).then(r => r.text())));
-
-  const idl_array = new IdlArray();
-  idl_array.add_idls(wasm);
-  // Ignored errors are surfaced in idlharness.js's test_object below.
-  try {
-    self.memory = new Memory({initial: 1024});
-  } catch (e) { }
-
-  try {
-    self.mod = await createWasmModule();
-    self.instance = new Instance(self.mod);
-  } catch (e) { }
-
-  idl_array.add_objects({
-    Memory: ['memory'],
-    Module: ['mod'],
-    Instance: ['instance'],
-  });
-  idl_array.test();
-}, 'wasm-js-api interfaces.');
-
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/wasm/jsapi/idlharness.any.js
@@ -0,0 +1,40 @@
+// META: script=/resources/WebIDLParser.js
+// META: script=/resources/idlharness.js
+// META: script=../resources/load_wasm.js
+
+'use strict';
+
+// https://webassembly.github.io/spec/js-api/
+
+promise_test(async () => {
+  const srcs = ['wasm-js-api'];
+  const [wasm] = await Promise.all(
+    srcs.map(i => fetch(`/interfaces/${i}.idl`).then(r => r.text())));
+
+  const idl_array = new IdlArray();
+  idl_array.add_idls(wasm, {
+    // Note the prose requirements in the specification.
+    except: ['CompileError', 'LinkError', 'RuntimeError']
+  });
+
+  // https://github.com/web-platform-tests/wpt/issues/12850
+  idl_array.add_untested_idls('[Exposed=(Window,Worker)] interface ArrayBuffer {};');
+
+  // Ignored errors are surfaced in idlharness.js's test_object below.
+  try {
+    self.memory = new WebAssembly.Memory({initial: 1024});
+  } catch (e) { }
+
+  try {
+    self.mod = await createWasmModule();
+    self.instance = new WebAssembly.Instance(self.mod);
+  } catch (e) { }
+
+  idl_array.add_objects({
+    Memory: ['memory'],
+    Module: ['mod'],
+    Instance: ['instance'],
+  });
+  idl_array.test();
+}, 'wasm-js-api interfaces.');
+
--- a/testing/web-platform/tests/wasm/resources/load_wasm.js
+++ b/testing/web-platform/tests/wasm/resources/load_wasm.js
@@ -1,12 +1,12 @@
 // Copyright 2016 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
 function createWasmModule() {
-    return fetch('incrementer.wasm')
+    return fetch('/wasm/incrementer.wasm')
         .then(response => {
             if (!response.ok) throw new Error(response.statusText);
             return response.arrayBuffer();
         })
         .then(WebAssembly.compile);
 }