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

Scripting API logging objects crashes the editor #2763

Closed
MikeMnD opened this issue Mar 3, 2020 · 4 comments
Closed

Scripting API logging objects crashes the editor #2763

MikeMnD opened this issue Mar 3, 2020 · 4 comments
Labels
bug

Comments

@MikeMnD
Copy link

@MikeMnD MikeMnD commented Mar 3, 2020

Here a simple example script for making custom tilemap export:
You can check the comments and try different ways of crashing the editor:

export_to_cusotm_tilemap.js

var customMapFormat = {
    name: "Custom Map Format",
    extension: "ctxt",

    write: function(map, fileName) {

        // This works but it's not useful
        console.log(map) //result in qml: Tiled::EditableMap(0x9dbaf0)

        // This crashes the editor
        // console.log(JSON.stringify(map));

        // This also crashes the editor
        // console.log(Object.keys(map));

        // Both return empty string
        console.log(map.asset.fileName);
        console.log(map.fileName);

        let poolIntArrayString = '';

        map.tilesets.forEach(tileset => {

            // This works as intended - and returns the full path to the .tsx file
            console.log(tileset.asset.fileName);

            // This also works
            tiled.log(Object.keys(tileset))

        });
        
        const tileMapName = "TileMap";
        const file = new TextFile(fileName, TextFile.WriteOnly);
        const tileMapTemplate = "empty map in custom txt file";
        file.write(tileMapTemplate);
        file.commit();
        file.close();

    },


}

tiled.registerMapFormat("Custom", customMapFormat);

This is the log from the windows event log:
Windows 10, Tiled Version 1.3.2

Log Name:      Application
Source:        Application Error
Date:          3/3/2020 20:23:55
Event ID:      1000
Task Category: (100)
Level:         Error
Keywords:      Classic
User:          N/A
Computer:      DESKTOP-QL8D1P2
Description:
Faulting application name: tiled.exe, version: 1.0.0.0, time stamp: 0x5e286394
Faulting module name: Qt5Widgets.dll, version: 5.12.6.0, time stamp: 0x5dc71809
Exception code: 0xc0000005
Fault offset: 0x000000000030dff2
Faulting process id: 0x26d4
Faulting application start time: 0x01d5f188dad50ef9
Faulting application path: C:\Program Files\Tiled\tiled.exe
Faulting module path: C:\Program Files\Tiled\Qt5Widgets.dll
Report Id: c5b31c05-5478-473a-b819-d249462c68fd
Faulting package full name: 
Faulting package-relative application ID: 
Event Xml:
<Event xmlns="http://schemas.microsoft.com/win/2004/08/events/event">
  <System>
    <Provider Name="Application Error" />
    <EventID Qualifiers="0">1000</EventID>
    <Level>2</Level>
    <Task>100</Task>
    <Keywords>0x80000000000000</Keywords>
    <TimeCreated SystemTime="2020-03-03T18:23:55.717795200Z" />
    <EventRecordID>62920</EventRecordID>
    <Channel>Application</Channel>
    <Computer>DESKTOP-QL8D1P2</Computer>
    <Security />
  </System>
  <EventData>
    <Data>tiled.exe</Data>
    <Data>1.0.0.0</Data>
    <Data>5e286394</Data>
    <Data>Qt5Widgets.dll</Data>
    <Data>5.12.6.0</Data>
    <Data>5dc71809</Data>
    <Data>c0000005</Data>
    <Data>000000000030dff2</Data>
    <Data>26d4</Data>
    <Data>01d5f188dad50ef9</Data>
    <Data>C:\Program Files\Tiled\tiled.exe</Data>
    <Data>C:\Program Files\Tiled\Qt5Widgets.dll</Data>
    <Data>c5b31c05-5478-473a-b819-d249462c68fd</Data>
    <Data>
    </Data>
    <Data>
    </Data>
  </EventData>
</Event>
@bjorn bjorn added the bug label Mar 3, 2020
@MikeMnD

This comment has been minimized.

Copy link
Author

@MikeMnD MikeMnD commented Mar 7, 2020

The problem with a console.log or JSON.stringify is the circular reference:
tileset.tiles[0].tileset.tiles[0].tileset… and so on…
More on that:
https://stackoverflow.com/questions/4816099/chrome-sendrequest-error-typeerror-converting-circular-structure-to-json

and the workaround is using this small package:
https://www.npmjs.com/package/flatted

Then you can use it like:

    console.log("--- tileset start ---");
    console.log(Flatted.stringify(tileset));
    console.log("--- tileset end ---");

That way the console in the Editor shows a text representation of the whole object.

@bjorn

This comment has been minimized.

Copy link
Owner

@bjorn bjorn commented Mar 16, 2020

    // This crashes the editor
    // console.log(JSON.stringify(map));

In my tests this does not crash the editor. I'm consistently getting:

TypeError: Type error
Stack traceback:
  write@file:///home/bjorn/.config/tiled/extensions/tiled-extensions/maptestformat.js:11

Though, I don't think I've tested this with the Tiled release yet, so it maybe it does crash when using Qt 5.12.6. In that case it would be fixed when we build against Qt 5.12.7.

    // This also crashes the editor
    // console.log(Object.keys(map));

For me, this outputs:

qml: [objectName,asset,readOnly,fileName,modified,isTileMap,isTileset,width,height,size,tileWidth,tileHeight,infinite,hexSideLength,staggerAxis,staggerIndex,orientation,renderOrder,backgroundColor,layerDataFormat,layerCount,tilesets,selectedArea,currentLayer,selectedLayers,selectedObjects,objectNameChanged,property,setProperty,properties,setProperties,removeProperty,modifiedChanged,fileNameChanged,undo,redo,macro,sizeChanged,tileWidthChanged,tileHeightChanged,currentLayerChanged,selectedLayersChanged,selectedObjectsChanged,layerAt,removeLayerAt,removeLayer,insertLayerAt,addLayer,addTileset,replaceTileset,removeTileset,usedTilesets,merge,merge,resize,resize,resize,autoMap,autoMap,autoMap,autoMap,autoMap,autoMap,autoMap,autoMap,setSize,setTileSize]
    // Both return empty string
    console.log(map.asset.fileName);
    console.log(map.fileName);

This may be surprising, but indeed this object does not have a file name. In this case, the map object is a temporary script wrapper around the map's data and map.asset just points back to itself. Note that even if this object would have the file name, it may be the current file name rather than the file name you're saving as, which is available as the fileName parameter.

        // This works as intended - and returns the full path to the .tsx file
        console.log(tileset.asset.fileName);

Yes, though you don't need the .asset part, which again points back at itself for tilesets.

console.log("--- tileset start ---");
console.log(Flatted.stringify(tileset));
console.log("--- tileset end ---");

That's a nice way to serialize! Just curious, but so far I didn't manage to get includes / requires to work. Did you find a way or did you just copy source code to your script file?

@MikeMnD

This comment has been minimized.

Copy link
Author

@MikeMnD MikeMnD commented Mar 16, 2020

Just curious, but so far I didn't manage to get includes / requires to work. Did you find a way or did you just copy source code to your script file?

I've pasted the source code in a utils.js and used it from there after Tiled autoloaded the utils.js
var Flatted=function(a,l) ...

That's what I found about the topic:
https://stackoverflow.com/questions/38057170/qt-qjsengine-import-js-files

The .import statement does not work with QJSEngine. QJSEngine is just a bare interpreter if you want to have some "import" functionality you might switch to QQmlEngine, which is built on top of QJSEngine: http://doc.qt.io/qt-5/qtqml-syntax-imports.html#qml-import-path

With QJSEngine you basically need to manually populate the js global object (and QtCreator sintax checker will not recognize the statements you use across the different files).

So maybe we can close this issue.

@bjorn

This comment has been minimized.

Copy link
Owner

@bjorn bjorn commented Mar 16, 2020

I've pasted the source code in a utils.js and used it from there after Tiled autoloaded the utils.js

Ah yes, that works of course!

QJSEngine is just a bare interpreter if you want to have some "import" functionality you might switch to QQmlEngine, which is built on top of QJSEngine

Hmm, I'm already using QQmlEngine so just using this subclass does not appear to suffice for getting imports to work.

Anyway, yeah, let's close this issue.

@bjorn bjorn closed this Mar 16, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Linked pull requests

Successfully merging a pull request may close this issue.

None yet
2 participants
You can’t perform that action at this time.