Titanium JIRA Archive
Titanium SDK/CLI (TIMOB)

[TIMOB-28394] iOS: openWindow transition broken / frame dropping (10.x regression)

GitHub Issuen/a
TypeBug
PriorityCritical
StatusClosed
ResolutionFixed
Resolution Date2021-04-07T17:11:22.000+0000
Affected Version/sRelease 10.1.0, Release 10.0.0
Fix Version/sRelease 10.0.0
ComponentsiOS
Labelsios, promises, regression, window
ReporterHans Knöchel
AssigneeVijay Singh
Created2021-03-15T12:41:54.000+0000
Updated2021-04-07T17:11:44.000+0000

Description

Since upgrading to SDK 10, it seems like the "openWindow" / "tab.open(window") transitions are broken. It seems like something is intercepting it on the wrong thread, causing the UI glitch. This does not happen with SDK 9.x (we swapped our production version to build with SDK 10 and it starts happening), so this is a pretty critical regression. Test-Case:
const window = Ti.UI.createWindow({
	backgroundColor: '#fff',
	title: 'Window 1'
});
const btn = Ti.UI.createButton({
	title: 'Trigger'
});
btn.addEventListener('click', () => {
	openWindow();
});
window.add(btn);
const tabGroup = Ti.UI.createTabGroup({
	tabs: [
		Ti.UI.createTab({
			title: 'Tab 1',
			window
		})
	]
});
tabGroup.open();

function openWindow() {
	const window2 = Ti.UI.createWindow({
		backgroundColor: 'blue'
	});
	const container = Ti.UI.createScrollView({
		layout: 'vertical'
	});
	window2.addEventListener('open', function onOpen() {
		window2.removeEventListener('open', onOpen);
		load(container);
	});
	window2.add(container);
	tabGroup.activeTab.open(window2);
}

function load(container) {
	for (let i = 0; i < 20; i++) {
		container.add(Ti.UI.createImageView({
			top: 10,
			width: 100,
			height: 100,
			image: Ti.UI.createView({
				height: 100,
				width: 100,
				backgroundColor: 'red',
			}).toImage()
		}));
	}
	var url = 'https://www.appcelerator.com';
	var client = Ti.Network.createHTTPClient({
		onload: () => {},
		onerror: () => {},
		timeout: 5000
	});
	client.open('GET', url);
	client.send();
}
Expected result: Red squares are drawn Actual result: No squares are drawn + (sometimes) the thread is blocked

Attachments

FileDateSize
bug.mov2021-04-06T07:55:42.000+0000868135
fix.mov2021-04-06T07:55:44.000+00001245414
NavWindowTest.js2021-03-16T03:40:57.000+0000809

Comments

  1. Vijay Singh 2021-03-15

    [~hknoechel] Can you provide a test case (small) to reproduce this?
  2. Joshua Quick 2021-03-16

    So, I noticed a NavigationWindow open/close animation issue in the iOS Simulator, but it happens in Titanium 9.3.0. Not sure if its the same as what [~hknoechel] is seeing though. Steps to reproduce:

    Build and run [^NavWindowTest.js] for the iOS Simulator.

    After app launches, wait at least 6 seconds.

    Click on the "Open Child Window" button.

    Notice that the orange child window opens without any animation.

    Wait at least 6 seconds.

    Click on the "Close Child Window" button.

    Notice the child window closes without any animation.

    Click on the "Open Child Window" button within 6 seconds.

    Notice the child window opens with a slide animation.

    Click on the "Close Child Window" button within 6 seconds.

    Notice the child window closes with a slide animation.

    For some reason, waiting 6 seconds or more causes open/close slide animation to not work. But I'm seeing this issue in Titanium 9.3.0 as well. I'm not sure if this is a Titanium issue or an iOS simulator issue, but that's my finding.
  3. Hans Knöchel 2021-03-16

    @Vijay: You can test it with our app (I just re-added you to the repo), by using the latest 10.x branch. *EDIT*: I added Chris W. as well
  4. Hans Knöchel 2021-03-17

    Any activity here? This is a huge SDK 10 blocker
  5. Vijay Singh 2021-03-18

    [~hknoechel] I have started lookin in this- While building your app, I am facing couple of issue. 1. Issue related extensions. (I resolved by disabling extensions) 2. Issue related with absence of Header folder inside xcframeworks (Resolved it by adding Header folder inside modules xcframework) 3. I am facing another issue related FBLPromises framework. Error says it is not found. I couldn't found this framework in project. Is it possible for you to create a small test case to reproduce it and a small video to understand the issue? I tried the test case shared by [~jquick]. It is working fine on device iPhone 11 (iOS 14.4) and simulator iPhone 12 Pro Max (iOS 14.4).
  6. Hans Knöchel 2021-03-18

    Hi Vijay! The FBLPromises error is usually an error caused by other issues on your end, e.g. missing libraries or incremental build issues. I was not able to create a test case for this so far, because it does not seem to happen with every window, indicating that it caused by interrupting the UI thread while drawing a more complex layout. I will try to create a test case, but the source of the bug is really the promise creation, because it works great if I revert [this commit](https://github.com/appcelerator/titanium_mobile/commit/5fa6258f9ec45eefc6a83b95c61b625d62386fd9) (likely [this line](https://github.com/appcelerator/titanium_mobile/commit/5fa6258f9ec45eefc6a83b95c61b625d62386fd9#diff-30207cc237420adbde6370f0966b5ace65298e900041ae900d71769d050ab57dR237)). Again, Chris would be best to look into this as he implemented this change. Btw, the CI is broken since 03/09, so latest 10_0_X from build.appcelerator.com is highly outdated
  7. Hans Knöchel 2021-03-18

    See the following test case and set a breakpoint [here](https://github.com/appcelerator/titanium_mobile/blob/master/iphone/TitaniumKit/TitaniumKit/Sources/Kroll/KrollPromise.m#L20) and [here](https://github.com/appcelerator/titanium_mobile/blob/master/iphone/TitaniumKit/TitaniumKit/Sources/API/TiWindowProxy.m#L229). During my tests, the Promise creation is performed multiple times and the "open:" selector rejects the promise when closing the window with Window is already opened or opening. There must be something wrong with the Promise creation.
       const window = Ti.UI.createWindow({
           backgroundColor: '#fff',
           title: 'Window 1'
       });
       
       const btn = Ti.UI.createButton({
           title: 'Trigger'
       });
       
       btn.addEventListener('click', () => {
           openWindow();
       });
       
       window.add(btn);
       
       const tabGroup = Ti.UI.createTabGroup({
           tabs: [
               Ti.UI.createTab({
                   title: 'Tab 1',
                   window
               })
           ]
       });
       
       tabGroup.open();
       
       function openWindow() {
           const window2 = Ti.UI.createWindow({
               backgroundColor: 'blue'
           });
           const container = Ti.UI.createScrollView({
               layout: 'vertical'
           });
       
           window2.addEventListener('open', function onOpen() {
               window2.removeEventListener('open', onOpen);
               load(container);
           });
           window2.add(container);
       
           tabGroup.activeTab.open(window2);
       }
       
       function load(container) {
           for (let i = 0; i < 100; i++) {
               container.add(Ti.UI.createView({
                   top: 10,
                   height: 200,
                   backgroundColor: 'red',
                   width: '90%'
               }));
           }
       
           var url = 'https://www.appcelerator.com';
           var client = Ti.Network.createHTTPClient({
               onload: function(e) {
                   for (let i = 0; i < 1000; i++) {
                       container.add(Ti.UI.createView({
                           top: 10,
                           height: 200,
                           backgroundColor: 'yellow',
                           width: '90%'
                       }));
                   }
               },
               onerror: function(e) {},
               timeout: 5000
           });
       
           client.open('GET', url);
           client.send();
       }
       
  8. Vijay Singh 2021-03-19

    [~hknoechel] I am not able to reproduce with the given test case also. Probably a video will be helpful. [~cwilliams] Can you please take a look if you can find anything as you have implemented this?
  9. Hans Knöchel 2021-03-23

    I reviewed all changes again and cannot find a fix so far. Reverting the mentioned commit helps, but I have no idea why. We will fork the SDK and rollback all Promise changes to be able to use SDK 10 again for now.
  10. Hans Knöchel 2021-03-30

    Any update here? This still prevents us from using the latest SDK 10 build.
  11. Marian Kucharcik 2021-03-30

    Hello guys, I have this problem too, as you can see on this video(taken on iP11Pro@14.4.1), app built with SDK10. [video](https://1drv.ms/v/s!AqYLRbx94HRJpA6pD_JiY6fcbw_i) It’s listview and when I click on listitem, tab1 opens new window(creates controller and opens it) Everything is ok with 9.3.2GA Thanks
  12. Vijay Singh 2021-03-30

    [~max87] Can you provide a reproducible test case? It will help us to debug it.
  13. Joshua Quick 2021-04-01

    [~hknoechel], [~max87], I can't reproduce this issue either... but I'm only able to test with the iOS Simulator. I tested with iOS 12.4 and iOS 14.2. The one concern I have in our Titanium 10.0.0 code is that we call JavaScriptCore's evaluateScript() and define 2 functions every time we create a Promise on iOS 12. (We don't do this on iOS 13 and higher.) https://github.com/appcelerator/titanium_mobile/blob/master/iphone/TitaniumKit/TitaniumKit/Sources/Kroll/KrollPromise.m#L35-L49 The issue with this is that Apple's docs state that whatever is defined in evaluateScript() will be added to the global context. JavaScript does allow you to define the same function name multiple times in the same script and the last one always wins. So, I'm curious if this will slowly bloat our JavaScript context on iOS 12. https://developer.apple.com/documentation/javascriptcore/jscontext/1451350-evaluatescript?language=objc But this may be off-topic. I'm guessing see this laggy behavior on iOS 14?
  14. Hans Knöchel 2021-04-01

    Yep, its tested on iOS 14. And it can definitely be reproduced with our app. Also, related to the incorrect Promise rejection, the test case I provided can be used. Should I do a pull request to request the open/close Promises for now?
  15. Joshua Quick 2021-04-01

    Like I said, I can't reproduce it. [~hknoechel], I've even tried running your test code under Xcode and I'm not seeing the "Window already opened" warning or anything suspicious in the log. Does the issue only happen on a real device for you? I ask because I've only tested under the iOS Simulator. The only other thing I can think of is that, this may not be so much a bug as really the timing has changed. APIs that have been transitioned to use promises (such as HTTPClient) will start their operation 1 frame later than before. For example, when you open a window, the "open" event on iOS is fired before the open-animation starts so that you can position your views before the window is shown. The "open" event will still happen at the same time as before, but other async operations that you may kick off in your open listener may start 1 frame later... and if you perform a long blocking operation during the open animation then that may cause the stutter effect you're talking about. It could be that your old code used to perform the async operation initiated by the open listener near immediately and before the open animation started. Honestly, I think that's the only thing I can think regarding what might cause a laggy open animation which means it has nothing to do with the Window.open() promise but more with async operations which proceed it. I personally don't object to removing promise support from Window.open() like APIs, but this was something [~cwilliams] was pushing for. We'd be be removing code for an issue we can't reproduce on our end. (I'm not 100% convinced that this is the actual issue. It clearly hasn't been isolated.)
  16. Hans Knöchel 2021-04-04

    Okay, guys, I found it. After digging through old commits for a whole evening and checking > 4 month of different head-hashes, this is the result:
        master / 10_0_X  <—— not working!!
        0446f8e86a37d385718dcdbfeb3f9cf3a02e7178 - 29.01 <—— not working!!
        b22f6b79268885d85e5df6b715fb1eb16b659d95 - 15.01. <—— not working!!
        12e8d24001d8468d89ab2ef4d2a2e6e52f7f756f - 13.01. <—— not working!!
        a6082fd827f92e8132d933a8f288ecb867c3a035 - 04.01. <—— not working!!
        aa9c9b4e45ccde2f5f79ea105da26dce5c5f4d7e - 15.12. <—— not working!!
        c7e65a507a060f49ad4db10888ad9d1c2c7bd745 - 15.12 <—— not working!!
        
        |
        | < — Regression!! https://github.com/appcelerator/titanium_mobile/commit/c7e65a507a060f49ad4db10888ad9d1c2c7bd745
        |
        
        df14d0aa3663ba66b2499522bc909795db2c69db - 15.12. <—— working!!
        2cc7ded1d4c9fa3eebf0a5a0be46c19b9bd8256d - 09.12. <—— working!!
        de43774adebbe6de3bc830b4f276946b7e64ca93 09.12. <—— working!!
        0e41ce77c276ff42b49d9bd980de2fd2e4381815 - 08.12. <—— working!!
        
    As seen in my little commit "hunting log", the bad commit was [this one](https://github.com/appcelerator/titanium_mobile/commit/c7e65a507a060f49ad4db10888ad9d1c2c7bd745) - not related to promises at all! The reason it caused the transition issues was that all affected views (somehow) used the toImage() function to render annotation images, which can probably also be put into a quick reproducible case for everyone now. I would suggest to just revert the commit for now, as it doesn't harm any code right now. If Chris / Vijay come up with an actual fix using the new API's (which this commit was meant for), I'd be happy to test that as well. We made it :-) *EDIT*: TIMOB-28394 can also be resolved as Duplicate of this one. Same cause, same fix!
  17. Hans Knöchel 2021-04-05

    I added a fully-reproducible test case (focussing rather on the squares than the transitions which are harder to reproduce, but it fixes both). PR (to revert the change for now): https://github.com/appcelerator/titanium_mobile/pull/12687
  18. Christopher Williams 2021-04-05

    https://github.com/appcelerator/titanium_mobile/pull/12687
  19. Hans Knöchel 2021-04-06

    Attached a video of the reproducible test case (*bug.mov*: Current state, *fix.mov*: The fix by reverting the old commit)
  20. Christopher Williams 2021-04-07

    merged to master, backport merged to 10_0_X for 10.0.0 target.

JSON Source