pixijs / layout

Library for arranging/resizing pixiJS rendered elements basing on css like configs
https://pixijs.io/layout/
MIT License
75 stars 5 forks source link

Adding DisplayObject to a container causes this error : Uncaught RangeError: Maximum call stack size exceeded at ContentController.createContent #58

Open seafloyd16 opened 1 year ago

seafloyd16 commented 1 year ago

Why I get this error?

I am currently making an Electron app. Electron is basically uses commonjs so I run esbuild to get a cjs formatted bundle.

And here is my script for quick test.

const { Layout } = require('./layout');
const { Application, Graphics, Sprite, Text } = require('./pixi.min');

const app = new Application
(
    {
        resizeTo: window,
        background: 0xffffff
    }
);

$('#main').append(app.view);

let L = new Layout
(
    {
        id: 'root',
        content: new Text('This is a PixiJS text'), // This causes the error!
        styles:
        {
            background: 'black',
            position: 'center',
            borderRadius: 20,
            padding: 20,
            color: 'white',
        }
    }
);

L.eventMode = 'none';
L.refresh();
L.resize($('body').width(), $('body').height());
app.stage.addChild(L);

NodeJS v18.18.0 Electron v27.0.2

CyberDex commented 1 year ago

@seafloyd16

Under the hood. ContentController is checking the type of a given object, to decide how to proceed with it:

https://github.com/pixijs/layout/blob/e1d591bf8c86e59f6084afa676eb0ff27941c923/src/controllers/ContentController.ts#L268

So, maybe in electron it can not detect it proper way? Try to just pass 'This is a PixiJS text' instead of Text instance.

CyberDex commented 1 year ago

Tried to reproduce this one on a normal env, and there is no issue here.

CyberDex commented 1 year ago

So, when it is an instance of text, it should just add it there. In case if this is a layout config tree, it should go throughout it and parse -> add elements recursively. So if it recognises your Text instance as layout config, it can start trying to parse it and this could potentially end up in Maximum call stack error

seafloyd16 commented 1 year ago

Hi, thank you for your replying and taking your time. I know that if I want a text, just type desired text without any constructor. It is working. But, as I said in the title, DisplayObject, like sprite and graphics are also causing the error.

So the code from "Usage" section in the full doc won't work. Usage

new Layout({
    content: {
        content: Sprite.from("bunny.png"),
        styles: {
            position: "center",
            maxWidth: "100%",
            minHeight: "100%",
        },
    },
    styles: {
        background: "red",
        position: "center",
        width: `100%`,
        height: `100%`,
    },
});

I tried to add a rectangle to a layout using addChild() and it was added, but the layout won't recalculate its size.

let rect = new Graphics();
rect.beginFill(0xffffff);
rect.drawRect(0, 0, 50, 50);
rect.endFill();

let L = new Layout
(
    {
        id: 'root',
        content:
        {
            id: 'contentA',
            content: {},
            styles:
            {
                background: 'gray',
                position: 'center',
                borderRadius: 20,
                padding: 20,
                color: 'white',
            }
        },
        styles:
        {
            background: 'black',
            position: 'center',
            borderRadius: 20,
            padding: 20,
            color: 'white',
        }
    }
);

L.getChildByID('contentA').addChild(rect);
CyberDex commented 1 year ago

OK, that means, I am right and it can not recognise the instances. I could try to take a look into it if you would create some repo with this basic setup, but I am not en expert in electron so can not promise I will be able to fix this.

seafloyd16 commented 1 year ago

Thank you again. Exporting bundles with esbuild may itself be wrong. I gonna research more, and will change my app setup to support ESM, instead of CJS.

ViktorJakobsson commented 1 year ago

Don't know of the root cause is the same but I also got call stack exceeded (after upgrading to 0.3.4). After doing a little bit of digging I found that the check content instanceof Container in getContentType always returned false, even though I was sure that it in fact was a Container. That led med to believe I had some other interfering packages. I had pixi ui as well but didn't use it. As soon as I removed it things started working again.

I am not using electron by the way.

CyberDex commented 1 year ago

Hmmm. Interesting discovery, do you think you could put it together in some repo where I can reproduce it and maybe fix?

seafloyd16 commented 1 year ago

Don't know of the root cause is the same but I also got call stack exceeded (after upgrading to 0.3.4). After doing a little bit of digging I found that the check content instanceof Container in getContentType always returned false, even though I was sure that it in fact was a Container. That led med to believe I had some other interfering packages. I had pixi ui as well but didn't use it. As soon as I removed it things started working again.

I am not using electron by the way.

PixiJS UI is not installed in my project. Thank you anyway!

seafloyd16 commented 1 year ago

Tried to reproduce this one on a normal env, and there is no issue here.

Hi. Can you bundle PixiJS Layout to an IIFE script using esbuild by running command below and test your env with it please? I'm just curious that esbuild output a proper bundle or not.

npx esbuild --bundle src\index.ts --outfile=pixi-layout.js --format=iife --global-name=pixiLayout

The bundle format is IIFE so put a script tag to load the one in your html. index.html:

<script src="pixi.min.js"></script>
<script src="pixi-layout.js"></script>
<script src="index.js"></script>

And then put the script below and please tell me the script works or doesn't.

new pixiLayout.Layout({
    content: {
        content: new PIXI.Container(),
        styles: {
            position: "center",
            maxWidth: "100%",
            minHeight: "100%",
        },
    },
    styles: {
        background: "red",
        position: "center",
        width: `100%`,
        height: `100%`,
    },
});
CyberDex commented 1 year ago

got Maximum call stack size exceeded. Debugging shows content type is always object, so this is The issue I had in mind, will think how to improve that checks.

seafloyd16 commented 1 year ago

got Maximum call stack size exceeded. Debugging shows content type is always object, so this is The issue I had in mind, will think how to improve that checks.

Thank you again, CyberDex. So, bundling is making things bad?

CyberDex commented 11 months ago

@seafloyd16 , sorry for late answer. This may be related to the way imports are happening. The build is made with rollup, so using option iife makes it use different imports (https://rollupjs.org/configuration-options/).

Also as a potential reason it can be 2 different pixi folders used, one is when building pixiLayout, other one is when you import pixi from the file directly, so obviously, even if it is the same versions instanceof will detect them as 2 separated instances, so the check fails. Probably instanceof may be replaced with some better checks here.