Skip to content
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

Set Signal within Image onload event fails with NG0600 error #55461

Open
nicolaric opened this issue Apr 22, 2024 · 3 comments
Open

Set Signal within Image onload event fails with NG0600 error #55461

nicolaric opened this issue Apr 22, 2024 · 3 comments
Labels
area: core Issues related to the framework runtime cross-cutting: signals
Milestone

Comments

@nicolaric
Copy link

Which @angular/* package(s) are the source of the bug?

core

Is this a regression?

Yes

Description

Hey y'all
I am currently trying to run tests against my image crop component. There, I have the following method:

    loadImage(file: File, fn?: () => void) {
        this._primaryAreaWidth = this.config().width;
        this._primaryAreaHeight = this.config().height;

        this._currentLoadConfig = file;

        // const src = normalizeSVG(file);

        const img = createHtmlImg(file);

        const cropEvent = { ...this.config() } as ImgCropperEvent;

        img.onload = () => {
            this._imgLoaded(img);
            this._positionImg(cropEvent, fn);
            this.isLoadedImg.set(true);
            this.cd.markForCheck();
        };
    }

the createHtmlImg function looks like this:

function createHtmlImg(src: File): HTMLImageElement {
    const img = new Image();
    img.crossOrigin = 'anonymous';
    img.src = URL.createObjectURL(src);
    return img;
}```

The test throwing the error looks like this:
    ```ts
it('should emit ready event when image is loaded', () => {
        global.Image = jest.fn().mockImplementation(() => ({
            onerror: jest.fn(),
            src: '',
            set onload(value: () => void) {
                value();
            },
        }));

        let ready;

        spectator.output('ready').subscribe((output) => (ready = output));

        spectator.setInput(
            'image',
            new File(
                [
                    'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAIAQMAAAD+wSzIAAAABlBMVEX///+/v7+jQ3Y5AAAADklEQVQI12P4AIX8EAgALgAD/aNpbtEAAAAASUVORK5CYII',
                ],
                'filename.png',
                { type: 'image/png' },
            ),
        );

        expect(ready).not.toBe(undefined);
    });

Does someone know, why the issue below happens?

Please provide a link to a minimal reproduction of the bug

No response

Please provide the exception or error you saw

ERROR RuntimeError: NG0600: Writing to signals is not allowed in a `computed` or an `effect` by default. Use `allowSignalWrites` in the `CreateEffectOptions` to enable this inside effects.
        at /Users/nicolaric/projects/akenza-ui/node_modules/@angular/core/fesm2022/core.mjs:31219:15

Please provide the environment you discovered this bug in (run ng version)

Angular 17.3.5

Anything else?

No response

@pkozlowski-opensource
Copy link
Member

Could you please share a reproduction scenario in a stackblitz? It is not clear when the loadImage is called / runs.

@nicolaric
Copy link
Author

@pkozlowski-opensource here you go:
https://stackblitz.com/edit/stackblitz-starters-kvmfjv?file=src%2Fimage-crop%2Fimage-crop.component.ts

it works when not running in the test. it fails when running the test.

@pkozlowski-opensource
Copy link
Member

it works when not running in the test. it fails when running the test.

This is because your test resolves the image loading synchronously which means that your onload event handler runs as part of the effect defined in the constructor. In this sense your test and production code behave differently.

You've got several options to address the warning:

  • make the test asynchronous;
  • add the allowSignalWrites option;

Idle though - it would help debugging those scenarios if we could easily / quickly identify an effect that triggers a warning.

@pkozlowski-opensource pkozlowski-opensource added area: core Issues related to the framework runtime cross-cutting: signals labels Apr 22, 2024
@ngbot ngbot bot modified the milestone: needsTriage Apr 22, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area: core Issues related to the framework runtime cross-cutting: signals
Projects
None yet
Development

No branches or pull requests

2 participants