If anybody wants a challenge...

Alex
I've been trying to fix a couple of problems with the WebEditor today - firstly, TinyMCE (the rich text editor used for editing room descriptions etc.) doesn't seem to like being unloaded and reloaded via AJAX, and somehow causes JQueryUI to break. This meant that after going into the web-based Editor, sometimes when you clicked on another room in the game, the tabs wouldn't be initialised properly and any subsequent calls to JQueryUI would fail - no buttons would work etc. The entire UI was broken.

So I've disabled TinyMCE for now in the WebEditor and it's just a plain textarea instead. So if anybody wants to look into that, that would be nice. If you need any help running WebEditor locally please let me know, but it's quite simple to create the WebEditorSettings.xml file from the defaults and you're good to go.

(Also if you want a consistent reproduction, in GameEdit.js in the initialiseElementEditor function, put the call to .tabs() inside a setTimeout of 100ms - this will mean TinyMCE will always get initialised before the tabs, and the tabs will never get loaded properly).

Secondly (and possibly related?) there's a JavaScript memory leak as you click between items in the tree. I thought this might be because we should be destroying JQueryUI tabs, unbinding events etc., when the new element editor loads, but I added code to do that and it doesn't help.

I doubt that debugging either of these really appeals to anybody, but they're nice meaty issues and are probably a good way of getting an overview of how the WebEditor code works. I'm happy as always to answer questions about the code on this forum or by email.

junichiro
how do you get web editor running and open in a browser? And what browsers are affected by the memory leak?

Alex
To run WebEditor locally:

- go to WebEditor\WebEditor\WebEditorSettings.default.xml and copy it to create a new file WebEditorSettings.xml
- in the XML file, set LibraryFolder to the path where the Core*.aslx files live - e.g. C:\Code\Quest\WorldModel\WorldModel\Core\
- set Templates Folder e.g. C:\Code\Quest\WorldModel\WorldModel\Core\Templates\
- PlayURL and PublishURL are optional - PlayURL is the URL you want to open when clicking the Play button (should be the URL that WebPlayer opens) and PublishURL is for when you click the Publish button (there's no open source for this as it would depend on the implementation of the site you were running WebEditor on, so just leave this setting as-is)
- uncomment the two settings at the bottom. This will activate the DebugFileManager plugin - all requests will open the specific game file as specified by the DebugFileManagerFile setting

Once you've done this, in Visual Studio set the Start-up project to WebEditor. Go to the Properties for this project and select the Web tab. Change the Start Action to "Start URL" and enter the URL http://localhost:50212/Edit/Game/1

Now when you Run, the DebugFileManager will be asked to load the game with id 1, and will return the ASLX file specified in your config. That game will then be loaded in the WebEditor.

The memory leak is reproducable using Chrome. You can see the memory usage creep up by pressing F12, go to the Timeline tab and then select Memory in the top-left.

junichiro
1. On unresponsive GUI:

On rare occasions I could reproduce this in Chrome, but now I can't seem to reproduce it al all. using setTimeout on $("#elementEditorTabs").tabs doesn't seem to make any difference, even if I try a timeout of 8000ms. If you can easily reproduce you could try putting some console.log statements in the javscript to see where the code fails.

2. On the memory leak:

In Chrome I can reproduce a pretty severe memory leak, yes! In Firefox it leaks memory for a short while, then reclaims it all again periodically. Actually I think there are multiple leaks, because by commenting out bits of code the leak becomes less severe, but still exists.

Commenting out "initialiseElementEditor" doesn't seem to stop leaking much at all, if anything.

Commenting out:

$("#elementEditor").load('@Html.Raw(@Url.Action("EditElement", new { id = Model.GameId, key = "KEY", tab = "TAB" }))'.replace("KEY", data.rslt.obj.attr("data-key").replace(/ /g, "%20")).replace("TAB", _selectTab), function () ...

makes the leak quite considerably smaller. So it seems most of the leak comes from inserting ElementEditor.cshtml into the page (or I guess more specfically, probably from not clearing up the memory used by what was previously there). I deleted all of EditorElement.cshtml except for a single div and that too greatly reduced the leak. You could try deleting various parts of ElementEditor.cshtml and see what difference it makes.

I also tried Chrome memory profile by going F12->profiles->heap snapshot. This shows huge number of objects created using the array constructor, but can't work out how to make it provide any useful information about where they got initialized.

3. Other:

a) Why:

function selectTreeNode(node) {
$("#gameTree").jstree("deselect_all");
$("#gameTree").jstree("select_node", "#tree-" + node.replace(/ /g, "-"));

when select_limit is 1?

b) click player, then click object in the same room as the player -> "Sorry, an internal error occurred: The method or operation is not implemented." I sometimes get this error on other objects, too.

c) F12 in chrome says that at all times the page has two elements with id "form-loading"

Alex
1. Were you clicking on another element? The first call to .tabs() always works, then with the setTimeout applied I was consistently getting broken tabs when clicking on other elements in the tree. When it happens, there's a big callstack of JQueryUI code and JQuery code where an exception occurs, but it's not immediately clear (to me) why.

2. Yes there are probably lots of things contributing to the memory leak - my guess is a load of event bindings which are not released when you click on another element. Yet calling unbind didn't help so maybe it's something else, or I wasn't unbinding the events properly.

3. a) I don't know, maybe that was added before I set select_limit=1.
3. b) Would be good to know why that's happening. If you set Visual Studio to break on all exceptions it should be clear what exactly is throwing this exception.
3. c) Definitely sounds like a bug!

junichiro
Alex wrote:1. Were you clicking on another element? The first call to .tabs() always works, then with the setTimeout applied I was consistently getting broken tabs when clicking on other elements in the tree. When it happens, there's a big callstack of JQueryUI code and JQuery code where an exception occurs, but it's not immediately clear (to me) why.


Yes, I can click around the tree.

Alex wrote:2. Yes there are probably lots of things contributing to the memory leak - my guess is a load of event bindings which are not released when you click on another element. Yet calling unbind didn't help so maybe it's something else, or I wasn't unbinding the events properly.


I'm not sure there are any event bindings in ElementEditor.cshtml? But that file is largely some sort of special ASP.NET language that isn't very familiar to me.

Alex wrote:
3. b) Would be good to know why that's happening. If you set Visual Studio to break on all exceptions it should be clear what exactly is throwing this exception.


WebEditor.DLL!WebEditor.Services.EditorService.DataChanged(object oldValue = null, object newValue = 0) Line 455

junichiro
Removing everything from between

@using (Ajax.BeginForm("SaveElement", new { }, new AjaxOptions { InsertionMode = InsertionMode.Replace, HttpMethod = "POST", UpdateTargetId = "elementEditor", OnComplete = "initialiseElementEditor", OnFailure = "ajaxError", OnBegin = "beginFormSubmit" }))
{

and the closing bracket

}

seems to reduce the leak to about 25% for me.

Alex
The event bindings I'm referring to are the JQueryUI bindings in GameEdit.js in initialiseElementEditor.

The NotImplementedException from DataChanged must be because it's trying to set some attribute to 0 which was previously null - would be good to know what attribute that is, it probably just needs to have a default value set in CoreTypes.aslx. Is this on the stable or default branch?

Doesn't removing the Ajax.BeginForm block break the Editor entirely though? That's how it loads the new element editor as you click on elements in the tree.

junichiro
Alex wrote:The event bindings I'm referring to are the JQueryUI bindings in GameEdit.js in initialiseElementEditor.


as above, entirely commenting out initialiseElementEditor doesn't make much difference

Alex wrote:The NotImplementedException from DataChanged must be because it's trying to set some attribute to 0 which was previously null - would be good to know what attribute that is, it probably just needs to have a default value set in CoreTypes.aslx. Is this on the stable or default branch?


how would I know what the attribute is?

Alex wrote:Doesn't removing the Ajax.BeginForm block break the Editor entirely though? That's how it loads the new element editor as you click on elements in the tree.


Yes, certainly it breaks everything, but the fact that it is this which makes a big difference to the memory leak, not initialiseElementEditor, suggests the leak is related not to event bindings but somehow to Ajax.BeginForm, or otherwise the relationship between Ajax.BeginForm and jquery load()

This topic is now closed. Topics are closed after 60 days of inactivity.

Support

Forums