Titanium JIRA Archive
Titanium SDK/CLI (TIMOB)

[TIMOB-25785] iOS: Sending events that cannot be serialized fail on SDK 7.0.0+

GitHub Issuen/a
TypeBug
PriorityCritical
StatusClosed
ResolutionFixed
Resolution Date2018-04-23T19:38:56.000+0000
Affected Version/sRelease 7.0.0
Fix Version/sRelease 7.3.0
ComponentsiOS
Labelsevents, ios, json, regression
ReporterGuile
AssigneeHans Knöchel
Created2018-02-16T12:54:35.000+0000
Updated2018-06-26T20:44:34.000+0000

Description

Here is a code : alloy.js
Ti.Gesture.addEventListener('orientationchange', function (e) {
    Ti.App.fireEvent('_customEvent', e);
});

Ti.App.addEventListener('_customEvent', function () {});

This triggers an error on orientation change {noformat} [ERROR] : Script Error { [ERROR] : column = 19; [ERROR] : line = 13; [ERROR] : message = "Invalid type in JSON write (GestureModule)"; [ERROR] : sourceURL = "file:///Users/houra/Library/Developer/CoreSimulator/Devices/599E21F7-4A9F-4B60-8864-1CE1485B4360/data/Containers/Bundle/Application/F13B31FA-B6FE-4372-A3FF-AFC5B5E2F1F9/Clean.app/app.js"; [ERROR] : } {noformat}

Comments

  1. Hans Knöchel 2018-02-16

    Hey there, did this work before 7? If so, it actually shouldn't, because you are passing a whole namespace to the event which is a) very very expensive in terms of performance and b) bad for your app scope. The underlaying reason is that an object cannot be stringified which is required to send over the event. *EDIT*: I just tested on 6.3.0 and it works, so we will fix it. Test-Case:
       /**
        * This file is used to validate iOS test-cases. It is ran using the Xcode
        * project in titanium_mobile/iphone/iphone/Titanium.xcodeproj.
        *
        * Change the below code to fit your use-case. By default, it included a button
        * to trigger a log that is displayed in the Xcode console.
        */
       
       var win = Ti.UI.createWindow({
           backgroundColor: '#fff'
       });
       
       var btn = Ti.UI.createButton({
           title: 'Trigger'
       });
       
       btn.addEventListener('click', function() {
         var validObject, validArray, invalidObject, invalidArray;
       
         validObject = {
           nl: null,
           num: 123,
           str: 'tirocks',
           arr: [null, 123, 'tirocks', { num: 123, str: 'tirocks' }],
           obj: {
             nl: null,
             num: 321,
             str: 'skcorit'
           }
         };
       
         validArray = [null, 123, 'tirocks', { nl: null, num: 123, str: 'tirocks' }, [null, 123, 'tirocks', { num: 123, str: 'tirocks' }]];
       
         invalidObject = {
           tiGesture: Ti.Gesture,
           proxy: Ti.UI.createLabel({ text: 'Whoops' }),
           num: 123,
           str: 'tirocks',
           arr: [123, 'tirocks', { num: 123, str: 'tirocks' }],
           obj: {
             num: 321,
             str: 'skcorit'
           }
         };
       
         invalidArray = [Ti.Gesture, Ti.UI.createLabel({ text: 'Whoops' }), 123, 'tirocks', { num: 123, str: 'tirocks' }, [123, 'tirocks', { num: 123, str: 'tirocks' }]];
       
         Ti.App.fireEvent('test', validObject);
         Ti.App.fireEvent('test', { arr: validArray });
         Ti.App.fireEvent('test', invalidObject);
         Ti.App.fireEvent('test', { arr: invalidArray });
       });
       
       Ti.App.addEventListener('test', function (e) {
         Ti.API.info(e);
       });
       
       win.add(btn);
       win.open();
       
    PR: https://github.com/appcelerator/titanium_mobile/pull/9856
  2. Guile 2018-02-20

    I've seen your PR, there is something uncomfortable : you should assume the BC Break, as it exists right now in GA and not going back to your initial decision in the serialization of the event parameter. The fact is that I changed my code to make it work with 7.0.2 and I won't go back on it. So let's assume that TI.Gesture can not be stringify in JSON. Document it clearly. What do you think about it ?
  3. Hans Knöchel 2018-02-21

    Hey there! The PR fixes exactly that by restoring the old behavior. In addition, it now throws a warning if you still do. In case of your exact case, you are sending the whole event you receive for convenience, although not all properties of the event are required. The PR basically checks for unserializable object fragments and removes them + warns you in case it finds them. This was done before as well, but using a third party library that was removed in Titanium 7. Would you agree on the change? And again, if it really is such an issue, you can simply replace
       Ti.App.fireEvent('_customEvent', e);
       
    with
       delete e.source;
       Ti.App.fireEvent('_customEvent', e);
       
    A more elegant solution really would be to only pass the required info, e.g. the orientation, but thats fine. I will also document the general behavior.
  4. Guile 2018-02-21

    The warning is fine, so the PR ;-) I've already fixed my code by not passing through the event object. Thank you !
  5. Hans Knöchel 2018-02-21

    Happy to hear, thank you! And sorry for causing this, this is properly unit-tested now as well :-).
  6. Samir Mohammed 2018-06-26

    *Closing ticket.* Verified fix can be seen in SDK Version: 7.3.0.v20180618182516 *FR (Passed) Test Steps:*

    Created an application with the code above in the comments

    Ran the program

    Application no longer errors out and the following warnings can be seen

       [DEBUG] :  Firing app event: test
       [WARN] :   Cannot serialize object, trying to repair ...
       [WARN] :   Found invalid value "[object GestureModule]" that cannot be serialized, skipping it ...
       [WARN] :   Found invalid value "[object TiUILabel]" that cannot be serialized, skipping it ...
       
    *Test Environment*
       APPC Studio: 5.0.0.201712081732
       APPC CLI: 7.0.4
       iphone 6 (11.2) Emulator
       Operating System Name: Mac OS High Sierra
       Operating System Version: 10.13
       Node.js Version: 8.9.1
       Xcode 9.2
       

JSON Source