diff --git a/test/fixtures/wpt/README.md b/test/fixtures/wpt/README.md index 4d35030d0ef766..3c70ab626d6a0b 100644 --- a/test/fixtures/wpt/README.md +++ b/test/fixtures/wpt/README.md @@ -35,6 +35,7 @@ Last update: - wasm/webapi: https://github.com/web-platform-tests/wpt/tree/fd1b23eeaa/wasm/webapi - web-locks: https://github.com/web-platform-tests/wpt/tree/10a122a6bc/web-locks - WebCryptoAPI: https://github.com/web-platform-tests/wpt/tree/1e4933113d/WebCryptoAPI +- webidl: https://github.com/web-platform-tests/wpt/tree/63ca529a02/webidl - webidl/ecmascript-binding/es-exceptions: https://github.com/web-platform-tests/wpt/tree/2f96fa1996/webidl/ecmascript-binding/es-exceptions - webmessaging/broadcastchannel: https://github.com/web-platform-tests/wpt/tree/6495c91853/webmessaging/broadcastchannel - webstorage: https://github.com/web-platform-tests/wpt/tree/1d2c5fb36a/webstorage diff --git a/test/fixtures/wpt/versions.json b/test/fixtures/wpt/versions.json index ea80904af6527b..b764ca61fa9b4c 100644 --- a/test/fixtures/wpt/versions.json +++ b/test/fixtures/wpt/versions.json @@ -99,6 +99,10 @@ "commit": "1e4933113d2028e092d07a9e865db8f606b21026", "path": "WebCryptoAPI" }, + "webidl": { + "commit": "63ca529a021fec15b2996db82fd7dd04c11abe85", + "path": "webidl" + }, "webidl/ecmascript-binding/es-exceptions": { "commit": "2f96fa19966d6bc19e979a09479ac8a7aa337c54", "path": "webidl/ecmascript-binding/es-exceptions" diff --git a/test/fixtures/wpt/webidl/META.yml b/test/fixtures/wpt/webidl/META.yml new file mode 100644 index 00000000000000..9a1192f6704842 --- /dev/null +++ b/test/fixtures/wpt/webidl/META.yml @@ -0,0 +1,3 @@ +spec: https://webidl.spec.whatwg.org/ +suggested_reviewers: + - yuki3 diff --git a/test/fixtures/wpt/webidl/README.md b/test/fixtures/wpt/webidl/README.md new file mode 100644 index 00000000000000..136a7649981ea4 --- /dev/null +++ b/test/fixtures/wpt/webidl/README.md @@ -0,0 +1 @@ +Tests for the [Web IDL Standard](https://webidl.spec.whatwg.org/). diff --git a/test/fixtures/wpt/webidl/current-realm.html b/test/fixtures/wpt/webidl/current-realm.html new file mode 100644 index 00000000000000..29e07d1f79edc0 --- /dev/null +++ b/test/fixtures/wpt/webidl/current-realm.html @@ -0,0 +1,168 @@ + + + +Current Realm + + +
+ + diff --git a/test/fixtures/wpt/webidl/ecmascript-binding/allow-resizable.html b/test/fixtures/wpt/webidl/ecmascript-binding/allow-resizable.html new file mode 100644 index 00000000000000..54daa57bce676a --- /dev/null +++ b/test/fixtures/wpt/webidl/ecmascript-binding/allow-resizable.html @@ -0,0 +1,31 @@ + + + + + diff --git a/test/fixtures/wpt/webidl/ecmascript-binding/attributes-accessors-unique-function-objects.html b/test/fixtures/wpt/webidl/ecmascript-binding/attributes-accessors-unique-function-objects.html new file mode 100644 index 00000000000000..167f55bcef7ead --- /dev/null +++ b/test/fixtures/wpt/webidl/ecmascript-binding/attributes-accessors-unique-function-objects.html @@ -0,0 +1,35 @@ + + +All attributes accessors are unique function objects + + + + diff --git a/test/fixtures/wpt/webidl/ecmascript-binding/builtin-function-properties.any.js b/test/fixtures/wpt/webidl/ecmascript-binding/builtin-function-properties.any.js new file mode 100644 index 00000000000000..885bb441ead442 --- /dev/null +++ b/test/fixtures/wpt/webidl/ecmascript-binding/builtin-function-properties.any.js @@ -0,0 +1,23 @@ +"use strict"; + +test(() => { + const ownPropKeys = Reflect.ownKeys(Blob).slice(0, 3); + assert_array_equals(ownPropKeys, ["length", "name", "prototype"]); +}, 'Constructor property enumeration order of "length", "name", and "prototype"'); + +test(() => { + assert_own_property(Blob.prototype, "slice"); + + const ownPropKeys = Reflect.ownKeys(Blob.prototype.slice).slice(0, 2); + assert_array_equals(ownPropKeys, ["length", "name"]); +}, 'Method property enumeration order of "length" and "name"'); + +test(() => { + assert_own_property(Blob.prototype, "size"); + + const desc = Reflect.getOwnPropertyDescriptor(Blob.prototype, "size"); + assert_equals(typeof desc.get, "function"); + + const ownPropKeys = Reflect.ownKeys(desc.get).slice(0, 2); + assert_array_equals(ownPropKeys, ["length", "name"]); +}, 'Getter property enumeration order of "length" and "name"'); diff --git a/test/fixtures/wpt/webidl/ecmascript-binding/class-string-interface.any.js b/test/fixtures/wpt/webidl/ecmascript-binding/class-string-interface.any.js new file mode 100644 index 00000000000000..ee792d5368389b --- /dev/null +++ b/test/fixtures/wpt/webidl/ecmascript-binding/class-string-interface.any.js @@ -0,0 +1,62 @@ +"use strict"; + +test(() => { + assert_own_property(Blob.prototype, Symbol.toStringTag); + + const propDesc = Object.getOwnPropertyDescriptor(Blob.prototype, Symbol.toStringTag); + assert_equals(propDesc.value, "Blob", "value"); + assert_equals(propDesc.configurable, true, "configurable"); + assert_equals(propDesc.enumerable, false, "enumerable"); + assert_equals(propDesc.writable, false, "writable"); +}, "@@toStringTag exists on the prototype with the appropriate descriptor"); + +test(() => { + assert_not_own_property(new Blob(), Symbol.toStringTag); +}, "@@toStringTag must not exist on the instance"); + +test(() => { + assert_equals(Object.prototype.toString.call(Blob.prototype), "[object Blob]"); +}, "Object.prototype.toString applied to the prototype"); + +test(() => { + assert_equals(Object.prototype.toString.call(new Blob()), "[object Blob]"); +}, "Object.prototype.toString applied to an instance"); + +test(t => { + assert_own_property(Blob.prototype, Symbol.toStringTag, "Precondition for this test: @@toStringTag on the prototype"); + + t.add_cleanup(() => { + Object.defineProperty(Blob.prototype, Symbol.toStringTag, { value: "Blob" }); + }); + + Object.defineProperty(Blob.prototype, Symbol.toStringTag, { value: "NotABlob" }); + assert_equals(Object.prototype.toString.call(Blob.prototype), "[object NotABlob]", "prototype"); + assert_equals(Object.prototype.toString.call(new Blob()), "[object NotABlob]", "instance"); +}, "Object.prototype.toString applied after modifying the prototype's @@toStringTag"); + +test(t => { + const instance = new Blob(); + assert_not_own_property(instance, Symbol.toStringTag, "Precondition for this test: no @@toStringTag on the instance"); + + Object.defineProperty(instance, Symbol.toStringTag, { value: "NotABlob" }); + assert_equals(Object.prototype.toString.call(instance), "[object NotABlob]"); +}, "Object.prototype.toString applied to the instance after modifying the instance's @@toStringTag"); + +// Chrome had a bug (https://bugs.chromium.org/p/chromium/issues/detail?id=793406) where if there +// was no @@toStringTag in the prototype, it would fall back to a magic class string. This tests +// that the bug is fixed. + +test(() => { + const instance = new Blob(); + Object.setPrototypeOf(instance, null); + + assert_equals(Object.prototype.toString.call(instance), "[object Object]"); +}, "Object.prototype.toString applied to a null-prototype instance"); + +// This test must be last. +test(() => { + delete Blob.prototype[Symbol.toStringTag]; + + assert_equals(Object.prototype.toString.call(Blob.prototype), "[object Object]", "prototype"); + assert_equals(Object.prototype.toString.call(new Blob()), "[object Object]", "instance"); +}, "Object.prototype.toString applied after deleting @@toStringTag"); diff --git a/test/fixtures/wpt/webidl/ecmascript-binding/class-string-iterator-prototype-object.any.js b/test/fixtures/wpt/webidl/ecmascript-binding/class-string-iterator-prototype-object.any.js new file mode 100644 index 00000000000000..5ca549d69cff81 --- /dev/null +++ b/test/fixtures/wpt/webidl/ecmascript-binding/class-string-iterator-prototype-object.any.js @@ -0,0 +1,51 @@ +"use strict"; + +const iteratorProto = Object.getPrototypeOf((new URLSearchParams()).entries()); + +test(() => { + assert_own_property(iteratorProto, Symbol.toStringTag); + + const propDesc = Object.getOwnPropertyDescriptor(iteratorProto, Symbol.toStringTag); + assert_equals(propDesc.value, "URLSearchParams Iterator", "value"); + assert_equals(propDesc.configurable, true, "configurable"); + assert_equals(propDesc.enumerable, false, "enumerable"); + assert_equals(propDesc.writable, false, "writable"); +}, "@@toStringTag exists with the appropriate descriptor"); + +test(() => { + assert_equals(Object.prototype.toString.call(iteratorProto), "[object URLSearchParams Iterator]"); +}, "Object.prototype.toString"); + +test(t => { + assert_own_property(iteratorProto, Symbol.toStringTag, "Precondition for this test: @@toStringTag exists"); + + t.add_cleanup(() => { + Object.defineProperty(iteratorProto, Symbol.toStringTag, { value: "URLSearchParams Iterator" }); + }); + + Object.defineProperty(iteratorProto, Symbol.toStringTag, { value: "Not URLSearchParams Iterator" }); + assert_equals(Object.prototype.toString.call(iteratorProto), "[object Not URLSearchParams Iterator]"); +}, "Object.prototype.toString applied after modifying @@toStringTag"); + +// Chrome had a bug (https://bugs.chromium.org/p/chromium/issues/detail?id=793406) where if there +// was no @@toStringTag, it would fall back to a magic class string. This tests that the bug is +// fixed. + +test(() => { + const iterator = (new URLSearchParams()).keys(); + assert_equals(Object.prototype.toString.call(iterator), "[object URLSearchParams Iterator]"); + + Object.setPrototypeOf(iterator, null); + assert_equals(Object.prototype.toString.call(iterator), "[object Object]"); +}, "Object.prototype.toString applied to a null-prototype instance"); + +test(t => { + const proto = Object.getPrototypeOf(iteratorProto); + t.add_cleanup(() => { + Object.setPrototypeOf(iteratorProto, proto); + }); + + Object.setPrototypeOf(iteratorProto, null); + + assert_equals(Object.prototype.toString.call(iteratorProto), "[object URLSearchParams Iterator]"); +}, "Object.prototype.toString applied after nulling the prototype"); diff --git a/test/fixtures/wpt/webidl/ecmascript-binding/class-string-named-properties-object.window.js b/test/fixtures/wpt/webidl/ecmascript-binding/class-string-named-properties-object.window.js new file mode 100644 index 00000000000000..a427a2f8142e53 --- /dev/null +++ b/test/fixtures/wpt/webidl/ecmascript-binding/class-string-named-properties-object.window.js @@ -0,0 +1,23 @@ +"use strict"; + +const namedPropertiesObject = Object.getPrototypeOf(Window.prototype); + +test(() => { + assert_own_property(namedPropertiesObject, Symbol.toStringTag); + + const propDesc = Object.getOwnPropertyDescriptor(namedPropertiesObject, Symbol.toStringTag); + assert_equals(propDesc.value, "WindowProperties", "value"); + assert_equals(propDesc.configurable, true, "configurable"); + assert_equals(propDesc.enumerable, false, "enumerable"); + assert_equals(propDesc.writable, false, "writable"); +}, "@@toStringTag exists with the appropriate descriptor"); + +test(() => { + assert_equals(Object.prototype.toString.call(namedPropertiesObject), "[object WindowProperties]"); +}, "Object.prototype.toString"); + +// Chrome had a bug (https://bugs.chromium.org/p/chromium/issues/detail?id=793406) where if there +// was no @@toStringTag, it would fall back to a magic class string. Tests for this are present in +// the sibling class-string*.any.js tests. However, the named properties object always fails calls +// to [[DefineOwnProperty]] or [[SetPrototypeOf]] per the Web IDL spec, so there is no way to +// trigger the buggy behavior for it. diff --git a/test/fixtures/wpt/webidl/ecmascript-binding/constructors.html b/test/fixtures/wpt/webidl/ecmascript-binding/constructors.html new file mode 100644 index 00000000000000..61993a6200ed56 --- /dev/null +++ b/test/fixtures/wpt/webidl/ecmascript-binding/constructors.html @@ -0,0 +1,132 @@ + + +Realm for constructed objects + + +
+ diff --git a/test/fixtures/wpt/webidl/ecmascript-binding/default-iterator-object.html b/test/fixtures/wpt/webidl/ecmascript-binding/default-iterator-object.html new file mode 100644 index 00000000000000..c7e9188521a2ae --- /dev/null +++ b/test/fixtures/wpt/webidl/ecmascript-binding/default-iterator-object.html @@ -0,0 +1,27 @@ + + +Default iterator objects + + + diff --git a/test/fixtures/wpt/webidl/ecmascript-binding/default-toJSON-cross-realm.html b/test/fixtures/wpt/webidl/ecmascript-binding/default-toJSON-cross-realm.html new file mode 100644 index 00000000000000..79c3097f339b58 --- /dev/null +++ b/test/fixtures/wpt/webidl/ecmascript-binding/default-toJSON-cross-realm.html @@ -0,0 +1,26 @@ + + +Cross-realm [Default] toJSON() creates result object in its realm + + + + + + + + + diff --git a/test/fixtures/wpt/webidl/ecmascript-binding/global-immutable-prototype.any.js b/test/fixtures/wpt/webidl/ecmascript-binding/global-immutable-prototype.any.js new file mode 100644 index 00000000000000..6291c3ae935608 --- /dev/null +++ b/test/fixtures/wpt/webidl/ecmascript-binding/global-immutable-prototype.any.js @@ -0,0 +1,25 @@ +// META: global=window,worker +// META: title=Immutability of the global prototype chain + +const objects = []; +setup(() => { + for (let object = self; object; object = Object.getPrototypeOf(object)) { + objects.push(object); + } +}); + +test(() => { + for (const object of objects) { + assert_throws_js(TypeError, () => { + Object.setPrototypeOf(object, {}); + }); + } +}, "Setting to a different prototype"); + +test(() => { + for (const object of objects) { + const expected = Object.getPrototypeOf(object); + Object.setPrototypeOf(object, expected); + assert_equals(Object.getPrototypeOf(object), expected); + } +}, "Setting to the same prototype"); diff --git a/test/fixtures/wpt/webidl/ecmascript-binding/global-mutable-prototype.any.js b/test/fixtures/wpt/webidl/ecmascript-binding/global-mutable-prototype.any.js new file mode 100644 index 00000000000000..eba96e9adf4647 --- /dev/null +++ b/test/fixtures/wpt/webidl/ecmascript-binding/global-mutable-prototype.any.js @@ -0,0 +1,27 @@ +// META: global=shadowrealm +// META: title=Mutability of the global prototype chain + +const objects = []; +setup(() => { + for (let object = self; object; object = Object.getPrototypeOf(object)) { + objects.push(object); + } +}); + +test(() => { + for (const object of objects) { + const proto = Object.getPrototypeOf(object); + const plainObject = {}; + Object.setPrototypeOf(object, plainObject); + assert_equals(Object.getPrototypeOf(object), plainObject); + Object.setPrototypeOf(object, proto); + } +}, "Setting to a different prototype"); + +test(() => { + for (const object of objects) { + const expected = Object.getPrototypeOf(object); + Object.setPrototypeOf(object, expected); + assert_equals(Object.getPrototypeOf(object), expected); + } +}, "Setting to the same prototype"); diff --git a/test/fixtures/wpt/webidl/ecmascript-binding/global-object-implicit-this-value-cross-realm.html b/test/fixtures/wpt/webidl/ecmascript-binding/global-object-implicit-this-value-cross-realm.html new file mode 100644 index 00000000000000..b9939b801cbd80 --- /dev/null +++ b/test/fixtures/wpt/webidl/ecmascript-binding/global-object-implicit-this-value-cross-realm.html @@ -0,0 +1,97 @@ + + +Cross-realm getter / setter / operation doesn't use lexical global object if |this| value is incompatible object / null / undefined + + + + + + + + + + diff --git a/test/fixtures/wpt/webidl/ecmascript-binding/global-object-implicit-this-value.any.js b/test/fixtures/wpt/webidl/ecmascript-binding/global-object-implicit-this-value.any.js new file mode 100644 index 00000000000000..4c159c67519c0b --- /dev/null +++ b/test/fixtures/wpt/webidl/ecmascript-binding/global-object-implicit-this-value.any.js @@ -0,0 +1,85 @@ +// META: global=window,worker + +// https://webidl.spec.whatwg.org/#dfn-attribute-getter (step 1.1.2.1) +// https://webidl.spec.whatwg.org/#dfn-attribute-setter (step 4.5.1) +// https://webidl.spec.whatwg.org/#dfn-create-operation-function (step 2.1.2.1) + +const notGlobalObject = Object.create(Object.getPrototypeOf(globalThis)); + +test(() => { + assert_throws_js(TypeError, () => { Object.create(globalThis).self; }); + assert_throws_js(TypeError, () => { getGlobalPropertyDescriptor("location").get.call(notGlobalObject); }); + assert_throws_js(TypeError, () => { Reflect.get(globalThis, "navigator", notGlobalObject); }); + assert_throws_js(TypeError, () => { new Proxy(globalThis, {}).onerror; }); +}, "Global object's getter throws when called on incompatible object"); + +test(() => { + assert_throws_js(TypeError, () => { Object.create(globalThis).origin = origin; }); + assert_throws_js(TypeError, () => { getGlobalPropertyDescriptor("onerror").set.call(notGlobalObject, onerror); }); + assert_throws_js(TypeError, () => { Reflect.set(globalThis, "onoffline", onoffline, notGlobalObject); }); + assert_throws_js(TypeError, () => { new Proxy(globalThis, {}).ononline = ononline; }); +}, "Global object's setter throws when called on incompatible object"); + +test(() => { + assert_throws_js(TypeError, () => { Object.create(globalThis).setInterval(() => {}, 100); }); + assert_throws_js(TypeError, () => { clearTimeout.call(notGlobalObject, () => {}); }); + assert_throws_js(TypeError, () => { Reflect.apply(btoa, notGlobalObject, [""]); }); + assert_throws_js(TypeError, () => { new Proxy(globalThis, {}).removeEventListener("foo", () => {}); }); +}, "Global object's operation throws when called on incompatible object"); + +if (typeof document !== "undefined") { + test(() => { + assert_throws_js(TypeError, () => { Object.getOwnPropertyDescriptor(window, "document").get.call(document.all); }); + }, "Global object's getter throws when called on incompatible object (document.all)"); + + test(() => { + assert_throws_js(TypeError, () => { Object.getOwnPropertyDescriptor(window, "name").set.call(document.all); }); + }, "Global object's setter throws when called on incompatible object (document.all)"); + + test(() => { + assert_throws_js(TypeError, () => { focus.call(document.all); }); + }, "Global object's operation throws when called on incompatible object (document.all)"); +} + +// An engine might have different code path for calling a function from outer scope to implement step 1.b.iii of https://tc39.es/ecma262/#sec-evaluatecall +const locationGetter = getGlobalPropertyDescriptor("location").get; +test(() => { + assert_equals(getGlobalPropertyDescriptor("self").get.call(null), self); + assert_equals((() => locationGetter())(), location); + assert_equals(Reflect.get(globalThis, "origin", null), origin); + assert_equals(Reflect.get(globalThis, "onoffline", undefined), onoffline); +}, "Global object's getter works when called on null / undefined"); + +test(() => { + const fn = () => {}; + + // origin is [Replaceable] + getGlobalPropertyDescriptor("origin").set.call(null, "foo"); + assert_equals(origin, "foo"); + getGlobalPropertyDescriptor("onerror").set.call(undefined, fn); + assert_equals(onerror, fn); + assert_true(Reflect.set(globalThis, "onoffline", fn, null)); + assert_equals(onoffline, fn); + + const ononlineSetter = getGlobalPropertyDescriptor("ononline").set; + (() => { ononlineSetter(fn); })(); + assert_equals(ononline, fn); +}, "Global object's setter works when called on null / undefined"); + +// An engine might have different code path for calling a function from outer scope to implement step 1.b.iii of https://tc39.es/ecma262/#sec-evaluatecall +const __addEventListener = addEventListener; +test(() => { + assert_equals(atob.call(null, ""), ""); + assert_equals(typeof (0, setInterval)(() => {}, 100), "number"); + + (() => { __addEventListener("foo", event => { event.preventDefault(); }); })(); + const __dispatchEvent = dispatchEvent; + (() => { assert_false(__dispatchEvent(new Event("foo", { cancelable: true }))); })(); +}, "Global object's operation works when called on null / undefined"); + +function getGlobalPropertyDescriptor(key) { + for (let obj = globalThis; obj; obj = Object.getPrototypeOf(obj)) { + const desc = Object.getOwnPropertyDescriptor(obj, key); + if (desc) return desc; + } +} diff --git a/test/fixtures/wpt/webidl/ecmascript-binding/has-instance.html b/test/fixtures/wpt/webidl/ecmascript-binding/has-instance.html new file mode 100644 index 00000000000000..caf0be47290607 --- /dev/null +++ b/test/fixtures/wpt/webidl/ecmascript-binding/has-instance.html @@ -0,0 +1,26 @@ + + +instanceof behavior + + + + + + diff --git a/test/fixtures/wpt/webidl/ecmascript-binding/interface-object-set-receiver.html b/test/fixtures/wpt/webidl/ecmascript-binding/interface-object-set-receiver.html new file mode 100644 index 00000000000000..ca75a96bbad52e --- /dev/null +++ b/test/fixtures/wpt/webidl/ecmascript-binding/interface-object-set-receiver.html @@ -0,0 +1,37 @@ + + +window.Interface is defined on [[Set]] receiver + + + + diff --git a/test/fixtures/wpt/webidl/ecmascript-binding/interface-object.html b/test/fixtures/wpt/webidl/ecmascript-binding/interface-object.html new file mode 100644 index 00000000000000..132c61ddaed4a3 --- /dev/null +++ b/test/fixtures/wpt/webidl/ecmascript-binding/interface-object.html @@ -0,0 +1,28 @@ + + +Interface objects + + + diff --git a/test/fixtures/wpt/webidl/ecmascript-binding/interface-prototype-constructor-set-receiver.html b/test/fixtures/wpt/webidl/ecmascript-binding/interface-prototype-constructor-set-receiver.html new file mode 100644 index 00000000000000..64a2da8eb2da2d --- /dev/null +++ b/test/fixtures/wpt/webidl/ecmascript-binding/interface-prototype-constructor-set-receiver.html @@ -0,0 +1,36 @@ + + +Interface.prototype.constructor is defined on [[Set]] receiver + + + + diff --git a/test/fixtures/wpt/webidl/ecmascript-binding/interface-prototype-object.html b/test/fixtures/wpt/webidl/ecmascript-binding/interface-prototype-object.html new file mode 100644 index 00000000000000..299bcf926dc23d --- /dev/null +++ b/test/fixtures/wpt/webidl/ecmascript-binding/interface-prototype-object.html @@ -0,0 +1,15 @@ + + +Interface prototype objects + + + + diff --git a/test/fixtures/wpt/webidl/ecmascript-binding/invalid-this-value-cross-realm.html b/test/fixtures/wpt/webidl/ecmascript-binding/invalid-this-value-cross-realm.html new file mode 100644 index 00000000000000..0535115ac61f43 --- /dev/null +++ b/test/fixtures/wpt/webidl/ecmascript-binding/invalid-this-value-cross-realm.html @@ -0,0 +1,45 @@ + + +Cross-realm getter / setter / operation doesn't use lexical global object to throw an error for incompatible |this| value + + + + + + + + + + diff --git a/test/fixtures/wpt/webidl/ecmascript-binding/iterator-invalidation-foreach.html b/test/fixtures/wpt/webidl/ecmascript-binding/iterator-invalidation-foreach.html new file mode 100644 index 00000000000000..9d2e3b9cb25ce6 --- /dev/null +++ b/test/fixtures/wpt/webidl/ecmascript-binding/iterator-invalidation-foreach.html @@ -0,0 +1,40 @@ + + +Behavior of iterators when modified within foreach + + + + + diff --git a/test/fixtures/wpt/webidl/ecmascript-binding/iterator-prototype-object.html b/test/fixtures/wpt/webidl/ecmascript-binding/iterator-prototype-object.html new file mode 100644 index 00000000000000..7859c1e46ac464 --- /dev/null +++ b/test/fixtures/wpt/webidl/ecmascript-binding/iterator-prototype-object.html @@ -0,0 +1,47 @@ + + +Iterator prototype objects + + + diff --git a/test/fixtures/wpt/webidl/ecmascript-binding/legacy-callback-interface-object.html b/test/fixtures/wpt/webidl/ecmascript-binding/legacy-callback-interface-object.html new file mode 100644 index 00000000000000..627d29507f7dad --- /dev/null +++ b/test/fixtures/wpt/webidl/ecmascript-binding/legacy-callback-interface-object.html @@ -0,0 +1,69 @@ + + +Legacy callback interface objects + + + + + + diff --git a/test/fixtures/wpt/webidl/ecmascript-binding/legacy-factor-function-subclass.window.js b/test/fixtures/wpt/webidl/ecmascript-binding/legacy-factor-function-subclass.window.js new file mode 100644 index 00000000000000..1fd64f41bb2e8e --- /dev/null +++ b/test/fixtures/wpt/webidl/ecmascript-binding/legacy-factor-function-subclass.window.js @@ -0,0 +1,13 @@ +"use strict"; + +test(() => { + class CustomImage extends Image {} + var instance = new CustomImage(); + + assert_equals( + Object.getPrototypeOf(instance), CustomImage.prototype, + "Object.getPrototypeOf(instance) === CustomImage.prototype"); + + assert_true(instance instanceof CustomImage, "instance instanceof CustomImage"); + assert_true(instance instanceof HTMLImageElement, "instance instanceof HTMLImageElement"); +}, "[LegacyFactoryFunction] can be subclassed and correctly handles NewTarget"); diff --git a/test/fixtures/wpt/webidl/ecmascript-binding/legacy-factory-function-builtin-properties.window.js b/test/fixtures/wpt/webidl/ecmascript-binding/legacy-factory-function-builtin-properties.window.js new file mode 100644 index 00000000000000..fc5c48aca380c0 --- /dev/null +++ b/test/fixtures/wpt/webidl/ecmascript-binding/legacy-factory-function-builtin-properties.window.js @@ -0,0 +1,6 @@ +"use strict"; + +test(() => { + const ownPropKeys = Reflect.ownKeys(Image).slice(0, 3); + assert_array_equals(ownPropKeys, ["length", "name", "prototype"]); +}, 'Legacy factory function property enumeration order of "length", "name", and "prototype"'); diff --git a/test/fixtures/wpt/webidl/ecmascript-binding/legacy-platform-object/DefineOwnProperty.html b/test/fixtures/wpt/webidl/ecmascript-binding/legacy-platform-object/DefineOwnProperty.html new file mode 100644 index 00000000000000..bd7ba19c1a90b6 --- /dev/null +++ b/test/fixtures/wpt/webidl/ecmascript-binding/legacy-platform-object/DefineOwnProperty.html @@ -0,0 +1,165 @@ + + +Legacy platform objects [[DefineOwnProperty]] method + + + + + diff --git a/test/fixtures/wpt/webidl/ecmascript-binding/legacy-platform-object/GetOwnProperty.html b/test/fixtures/wpt/webidl/ecmascript-binding/legacy-platform-object/GetOwnProperty.html new file mode 100644 index 00000000000000..be3bcc61f0a3aa --- /dev/null +++ b/test/fixtures/wpt/webidl/ecmascript-binding/legacy-platform-object/GetOwnProperty.html @@ -0,0 +1,84 @@ + + +Legacy platform objects [[GetOwnProperty]] method + + + + + diff --git a/test/fixtures/wpt/webidl/ecmascript-binding/legacy-platform-object/OwnPropertyKeys.html b/test/fixtures/wpt/webidl/ecmascript-binding/legacy-platform-object/OwnPropertyKeys.html new file mode 100644 index 00000000000000..d33980517b1a94 --- /dev/null +++ b/test/fixtures/wpt/webidl/ecmascript-binding/legacy-platform-object/OwnPropertyKeys.html @@ -0,0 +1,65 @@ + + +Legacy platform objects [[OwnPropertyKeys]] method + + + + diff --git a/test/fixtures/wpt/webidl/ecmascript-binding/legacy-platform-object/Set.html b/test/fixtures/wpt/webidl/ecmascript-binding/legacy-platform-object/Set.html new file mode 100644 index 00000000000000..1390b51cd03b51 --- /dev/null +++ b/test/fixtures/wpt/webidl/ecmascript-binding/legacy-platform-object/Set.html @@ -0,0 +1,94 @@ + + +Legacy platform objects [[Set]] method + + + + diff --git a/test/fixtures/wpt/webidl/ecmascript-binding/legacy-platform-object/helper.js b/test/fixtures/wpt/webidl/ecmascript-binding/legacy-platform-object/helper.js new file mode 100644 index 00000000000000..01c1d00694eb9b --- /dev/null +++ b/test/fixtures/wpt/webidl/ecmascript-binding/legacy-platform-object/helper.js @@ -0,0 +1,22 @@ +function assert_prop_desc_equals(object, property_key, expected) { + let actual = Object.getOwnPropertyDescriptor(object, property_key); + if (expected === undefined) { + assert_equals( + actual, undefined, + "(assert_prop_desc_equals: no property descriptor expected)"); + return; + } + for (p in actual) { + assert_true( + expected.hasOwnProperty(p), + "(assert_prop_desc_equals: property '" + p + "' is not expected)"); + assert_equals( + actual[p], expected[p], + "(assert_prop_desc_equals: property '" + p + "')"); + } + for (p in expected) { + assert_true( + actual.hasOwnProperty(p), + "(assert_prop_desc_equals: expected property '" + p + "' missing)"); + } +} diff --git a/test/fixtures/wpt/webidl/ecmascript-binding/no-regexp-special-casing.any.js b/test/fixtures/wpt/webidl/ecmascript-binding/no-regexp-special-casing.any.js new file mode 100644 index 00000000000000..4446dbf69c02ab --- /dev/null +++ b/test/fixtures/wpt/webidl/ecmascript-binding/no-regexp-special-casing.any.js @@ -0,0 +1,47 @@ +"use strict"; +// RegExps used to be special-cased in Web IDL, but that was removed in +// https://github.com/heycam/webidl/commit/bbb2bde. These tests check that implementations no longer +// do any such special-casing. + +test(() => { + const regExp = new RegExp(); + regExp.message = "some message"; + + const errorEvent = new ErrorEvent("type", regExp); + + assert_equals(errorEvent.message, "some message"); +}, "Conversion to a dictionary works"); + +test(() => { + const messageChannel = new MessageChannel(); + const regExp = new RegExp(); + regExp[Symbol.iterator] = function* () { + yield messageChannel.port1; + }; + + const messageEvent = new MessageEvent("type", { ports: regExp }); + + assert_array_equals(messageEvent.ports, [messageChannel.port1]); +}, "Conversion to a sequence works"); + +promise_test(async () => { + const regExp = new RegExp(); + + const response = new Response(regExp); + + assert_equals(await response.text(), "/(?:)/"); +}, "Can convert a RegExp to a USVString"); + +test(() => { + let functionCalled = false; + + const regExp = new RegExp(); + regExp.handleEvent = () => { + functionCalled = true; + }; + + self.addEventListener("testevent", regExp); + self.dispatchEvent(new Event("testevent")); + + assert_true(functionCalled); +}, "Can be used as an object implementing a callback interface"); diff --git a/test/fixtures/wpt/webidl/ecmascript-binding/observable-array-no-leak-of-internals.window.js b/test/fixtures/wpt/webidl/ecmascript-binding/observable-array-no-leak-of-internals.window.js new file mode 100644 index 00000000000000..f93464005d017f --- /dev/null +++ b/test/fixtures/wpt/webidl/ecmascript-binding/observable-array-no-leak-of-internals.window.js @@ -0,0 +1,18 @@ +"use strict"; + +test(() => { + const observableArray = document.adoptedStyleSheets; + + let leaked_target = null; + let leaked_handler = null; + + let target_leaker = (target) => { leaked_target = target; return null; }; + Object.defineProperty(Object.prototype, "getPrototypeOf", {get: function() { + leaked_handler = this; + return target_leaker; + }}) + Object.getPrototypeOf(observableArray); + + assert_equals(leaked_target, null, "The proxy target leaked."); + assert_equals(leaked_handler, null, "The proxy handler leaked."); +}, "ObservableArray's internals won't leak"); diff --git a/test/fixtures/wpt/webidl/ecmascript-binding/observable-array-ownkeys.window.js b/test/fixtures/wpt/webidl/ecmascript-binding/observable-array-ownkeys.window.js new file mode 100644 index 00000000000000..29b537c4750a38 --- /dev/null +++ b/test/fixtures/wpt/webidl/ecmascript-binding/observable-array-ownkeys.window.js @@ -0,0 +1,34 @@ +"use strict"; + +test(() => { + const observableArray = document.adoptedStyleSheets; + assert_array_equals( + Object.getOwnPropertyNames(observableArray), + ["length"], + "Initially only \"length\"."); + + observableArray["zzz"] = true; + observableArray["aaa"] = true; + assert_array_equals( + Object.getOwnPropertyNames(observableArray), + ["length", "zzz", "aaa"], + "Own properties whose key is a string have been added."); + + observableArray[0] = new CSSStyleSheet(); + observableArray[1] = new CSSStyleSheet(); + assert_array_equals( + Object.getOwnPropertyNames(observableArray), + ["0", "1", "length", "zzz", "aaa"], + "Own properties whose key is an array index have been added."); + + observableArray[Symbol.toStringTag] = "string_tag"; + observableArray[Symbol.toPrimitive] = "primitive"; + assert_array_equals( + Object.getOwnPropertyNames(observableArray), + ["0", "1", "length", "zzz", "aaa"], + "Own properties whose key is a symbol have been added (non-symbol)."); + assert_array_equals( + Object.getOwnPropertySymbols(observableArray), + [Symbol.toStringTag, Symbol.toPrimitive], + "Own properties whose key is a symbol have been added (symbol)."); +}, "ObservableArray's ownKeys trap"); diff --git a/test/fixtures/wpt/webidl/ecmascript-binding/put-forwards.html b/test/fixtures/wpt/webidl/ecmascript-binding/put-forwards.html new file mode 100644 index 00000000000000..7d99d65aa21385 --- /dev/null +++ b/test/fixtures/wpt/webidl/ecmascript-binding/put-forwards.html @@ -0,0 +1,148 @@ + + +[PutForwards] behavior + + + + + + diff --git a/test/fixtures/wpt/webidl/ecmascript-binding/replaceable-setter-throws-if-defineownproperty-fails.html b/test/fixtures/wpt/webidl/ecmascript-binding/replaceable-setter-throws-if-defineownproperty-fails.html new file mode 100644 index 00000000000000..872bbff9604265 --- /dev/null +++ b/test/fixtures/wpt/webidl/ecmascript-binding/replaceable-setter-throws-if-defineownproperty-fails.html @@ -0,0 +1,38 @@ + + +[Replaceable] setter throws TypeError if [[DefineOwnProperty]] fails + + + + + + + diff --git a/test/fixtures/wpt/webidl/ecmascript-binding/sequence-conversion.html b/test/fixtures/wpt/webidl/ecmascript-binding/sequence-conversion.html new file mode 100644 index 00000000000000..40764e9f577603 --- /dev/null +++ b/test/fixtures/wpt/webidl/ecmascript-binding/sequence-conversion.html @@ -0,0 +1,157 @@ + + +Sequence conversion + + + + + + + + + diff --git a/test/fixtures/wpt/webidl/ecmascript-binding/setter-argument.html b/test/fixtures/wpt/webidl/ecmascript-binding/setter-argument.html new file mode 100644 index 00000000000000..bfa4291b236533 --- /dev/null +++ b/test/fixtures/wpt/webidl/ecmascript-binding/setter-argument.html @@ -0,0 +1,176 @@ + + +Setter should treat no arguments as undefined + + + + diff --git a/test/fixtures/wpt/webidl/ecmascript-binding/support/constructors-support.html b/test/fixtures/wpt/webidl/ecmascript-binding/support/constructors-support.html new file mode 100644 index 00000000000000..3b2616170b1d4f --- /dev/null +++ b/test/fixtures/wpt/webidl/ecmascript-binding/support/constructors-support.html @@ -0,0 +1,8 @@ + + diff --git a/test/fixtures/wpt/webidl/ecmascript-binding/support/create-realm.js b/test/fixtures/wpt/webidl/ecmascript-binding/support/create-realm.js new file mode 100644 index 00000000000000..45ded884fc1f22 --- /dev/null +++ b/test/fixtures/wpt/webidl/ecmascript-binding/support/create-realm.js @@ -0,0 +1,12 @@ +"use strict"; + +function createRealm(t) { + return new Promise(resolve => { + const iframe = document.createElement("iframe"); + t.add_cleanup(() => { iframe.remove(); }); + iframe.onload = () => { resolve(iframe.contentWindow); }; + iframe.name = "dummy"; + iframe.src = "support/dummy-iframe.html"; + document.body.append(iframe); + }); +} diff --git a/test/fixtures/wpt/webidl/ecmascript-binding/support/dummy-iframe.html b/test/fixtures/wpt/webidl/ecmascript-binding/support/dummy-iframe.html new file mode 100644 index 00000000000000..3f773ae6f811ac --- /dev/null +++ b/test/fixtures/wpt/webidl/ecmascript-binding/support/dummy-iframe.html @@ -0,0 +1,7 @@ + + +foo + + diff --git a/test/fixtures/wpt/webidl/ecmascript-binding/window-named-properties-object.html b/test/fixtures/wpt/webidl/ecmascript-binding/window-named-properties-object.html new file mode 100644 index 00000000000000..cc4976890683f4 --- /dev/null +++ b/test/fixtures/wpt/webidl/ecmascript-binding/window-named-properties-object.html @@ -0,0 +1,284 @@ + + +Internal methods of Window's named properties object + + + + + + diff --git a/test/fixtures/wpt/webidl/idlharness.any.js b/test/fixtures/wpt/webidl/idlharness.any.js new file mode 100644 index 00000000000000..f8b285c485c43a --- /dev/null +++ b/test/fixtures/wpt/webidl/idlharness.any.js @@ -0,0 +1,17 @@ +// META: script=/resources/WebIDLParser.js +// META: script=/resources/idlharness.js +// META: global=window,dedicatedworker,shadowrealm-in-window + +"use strict"; + +idl_test( + ['webidl'], + [], + idl_array => { + idl_array.add_objects({ + DOMException: ['new DOMException()', + 'new DOMException("my message")', + 'new DOMException("my message", "myName")'] + }); + } +); diff --git a/test/wpt/status/webidl.json b/test/wpt/status/webidl.json new file mode 100644 index 00000000000000..b29a000a9d8b92 --- /dev/null +++ b/test/wpt/status/webidl.json @@ -0,0 +1,70 @@ +{ + "ecmascript-binding/class-string-named-properties-object.window.js": { + "fail": { + "expected": [ + "evaluation in WPTRunner.runJsTests()" + ] + } + }, + "ecmascript-binding/global-immutable-prototype.any.js": { + "fail": { + "expected": [ + "Setting to a different prototype" + ] + } + }, + "ecmascript-binding/global-mutable-prototype.any.js": { + "fail": { + "expected": [ + "Setting to a different prototype" + ] + } + }, + "ecmascript-binding/global-object-implicit-this-value.any.js": { + "fail": { + "expected": [ + "Global object's getter throws when called on incompatible object", + "Global object's setter throws when called on incompatible object", + "Global object's operation throws when called on incompatible object", + "Global object's getter works when called on null / undefined", + "Global object's setter works when called on null / undefined", + "evaluation in WPTRunner.runJsTests()" + ] + } + }, + "ecmascript-binding/legacy-factor-function-subclass.window.js": { + "fail": { + "expected": [ + "[LegacyFactoryFunction] can be subclassed and correctly handles NewTarget" + ] + } + }, + "ecmascript-binding/legacy-factory-function-builtin-properties.window.js": { + "fail": { + "expected": [ + "Legacy factory function property enumeration order of \"length\", \"name\", and \"prototype\"" + ] + } + }, + "ecmascript-binding/no-regexp-special-casing.any.js": { + "fail": { + "expected": [ + "Can be used as an object implementing a callback interface" + ] + } + }, + "ecmascript-binding/observable-array-no-leak-of-internals.window.js": { + "fail": { + "expected": [ + "ObservableArray's internals won't leak" + ] + } + }, + "ecmascript-binding/observable-array-ownkeys.window.js": { + "fail": { + "expected": [ + "ObservableArray's ownKeys trap" + ] + } + } +} diff --git a/test/wpt/test-webidl.js b/test/wpt/test-webidl.js new file mode 100644 index 00000000000000..682616608ea169 --- /dev/null +++ b/test/wpt/test-webidl.js @@ -0,0 +1,8 @@ +'use strict'; + +require('../common'); +const { WPTRunner } = require('../common/wpt'); + +const runner = new WPTRunner('webidl'); + +runner.runJsTests();