Skip to content

Fix wrong ImageData test #52070

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

Taym95
Copy link

@Taym95 Taym95 commented Apr 20, 2025

This PR fixes a test for the ImageData(data, width[, height]) constructor that incorrectly expected a TypeError to be thrown when passing a TypedArray that is not a Uint8ClampedArray, such as Int8Array. This behavior is not correct per the WebIDL specification, and the test was passing in Servo due to a previous mismatch in the WebIDL bindings, not because the behavior was actually correct.

Thanks to @jdm explanation , we noticed that Servo was passing a Web Platform Test that every other browser fails. The test was written like this:

test(function() {
    assert_throws_js(TypeError, function() {
        new ImageData(new Int8Array(1), 1);
    });
}, "ImageData(buffer, w, opt h), Uint8ClampedArray argument type check");

this looks like it should call the constructor that takes a Uint8ClampedArray and throw a TypeError because the input is not of the right type. However, this is not what actually happens per spec.

According to WebIDL overload resolution, the selection of the correct constructor works as follows:

Constructors in the IDL:

[Throws] constructor(Uint8ClampedArray data, unsigned long sw, optional unsigned long sh);
[Throws] constructor(unsigned long sw, unsigned long sh);

Given call:

new ImageData(new Int8Array(1), 1);

Overload resolution steps:
The first argument (Int8Array) does not match Uint8ClampedArray.

  • Step 12.7 of the overload algorithm fails.

The algorithm continues to look for another overload that accepts a number as its first argument.

  • Step 12.16 finds the (sw, sh) constructor.

As a result, the second constructor is chosen, and no type error is thrown. The object is created incorrectly, but validly.

Why Servo Passed the Test Incorrectly:

[Throws] constructor(object data, unsigned long sw, optional unsigned long sh);

Because the overload used object, any typed array — including Int8Array — would match that overload, hitting Step 12.11 in the spec, and calling the constructor that then did manual type checking.

Proposed Fix:
To make the test correctly target the desired constructor (the one expecting a Uint8ClampedArray), we bypass the default overload resolution logic. This is done by directly calling the constructor function with .call():

test(function() {
    assert_throws_js(TypeError, function() {
        ImageData.prototype.constructor.call(
            Object.create(ImageData.prototype),
            new Int8Array(1),
            1
        );
    });
}, "ImageData(buffer, w, opt h), Uint8ClampedArray argument type check");

This PR fixes #44929.

Signed-off-by: Taym Haddadi <haddadi.taym@gmail.com>
@annevk
Copy link
Member

annevk commented Apr 22, 2025

I don't understand why using call would invoke the correct constructor. It seems to me you would still go down the same overload resolution code path.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

ImageData(buffer, w, opt h), Uint8ClampedArray argument type check test fails for all browsers
4 participants