Titanium JIRA Archive
Appcelerator Community (AC)

[AC-6572] iOS: when running a on a device, Javascript compilation results in a particular block of code not being executed, without errors

GitHub Issuen/a
TypeBug
Priorityn/a
StatusClosed
ResolutionDone
Resolution Date2020-08-18T14:10:58.000+0000
Affected Version/sn/a
Fix Version/sn/a
Componentsn/a
Labelsn/a
ReporterRoman Avsec
AssigneeAbir Mukherjee
Created2020-07-08T22:35:36.000+0000
Updated2020-08-18T14:10:58.000+0000

Description

When running an Alloy project on a device or releasing an Adhoc or an App store version, thus running the project through a pipeline where Javascript files are additionally processed, odd behavior is observed where a block of code may not executed, without any compilation or runtime errors. *Steps to reproduce:* * Create a new default Alloy Project * add example code below to in index.js controller * run project on an iOS device (run directly, just without LiveView; or create and install an Adhoc build; or create and install AppStore build through Testflight) *Expected result:* * setTiProps function should've run in entirety and styling should be applied to the Label (correct_screenshot.png) * OR if any part of the example Javascript is invalid, a compilation error or a runtime error should've been triggered *Actual result:* * setTiProps function is somehow not executed in its entirety and styling is thus not applied to the Label (incorrect_screenshot.png)

Additional observations - please note that this is *not* a styling issue

The correct and expected result is shown in the following cases: * by running on an actual device _with_ LiveView enabled * by running on an iOS simulator _with_ or _without_ LiveView * most unexpectedly, by modifying the example code through inserting *any dummy line* into the setTiProps function just before the _for_ loop, such as: console.log("Here"); * (also, by compiling and running the code with SDK 7.4 and lower) The above observations lead me to postulate that one of the steps active in additional Javascript processing for device builds (minimization, obfuscation, encryption, ...?) encounters a situation in the example code that causes it to silently modify the function in a way that it makes it not run all the way through, all without triggering any compilation or runtime errors - this makes it particularly challenging to track down the real issue as most attempts to debug the code will cause it run correctly again (either by modifying the code with log statements or creating a debug build that then skips the troublesome Javascript processing pipeline). ---- _index.js:_
var ALLOWED_PROPS = [
	"backgroundColor",
	"borderColor",
	"borderRadius",
	"borderWidth",
	"height",
	"width",
];

function setTiProps(args, component) {

	if (!component) return;

	var args = args || {}, prop = '';

	for(var i = 0, j = ALLOWED_PROPS.length; i < j; i++){
		prop = ALLOWED_PROPS[i];
		if(typeof args[prop] !== "undefined") {
			component[prop] = args[prop];
		}
	}
};

setTiProps({
    "backgroundColor": "red",
    "borderColor": "green",
    "width": "100%",
    "height": "50dp"
}, $.label);

function doClick(e) {
	alert($.label.text);
}

$.index.open();

Attachments

FileDateSize
correct_screenshot.png2020-07-08T22:36:42.000+000083250
incorrect_screenshot.png2020-07-08T22:36:42.000+000082195
index.working-correctly.js2020-07-08T22:37:07.000+0000602
index.working-incorrectly.js2020-07-08T22:37:07.000+0000576

Comments

  1. Ewan Harris 2020-07-13

    [~ravsec] firstly, thank you for such a complete bug report! I've took a look into this and it does look to be a problem with the package we use for minification (babel-minify), it appears that when minifying the setTiProps function it inlines the declaration of args and prop into the for loop definition (code below) I believe this is the root cause of the issue you're seeing.
       function setTiProps(args,component){
       
       	if(component)
       
       	for(var args=args||{},prop="",i=0,j=ALLOWED_PROPS.length;void 0>i;i++) {
       		prop=ALLOWED_PROPS[i],
       		"undefined"!=typeof args[prop]&&(
       		component[prop]=args[prop]);
       	}
       };
       
    I was able to fix this without requiring disabling js minification by changing setTiProp to the following:
       function setTiProps(args, component) {
        
       	if (!component) return;
        
       	args = args || {};
       	for(const prop of ALLOWED_PROPS){
       		if(typeof args[prop] !== "undefined") {
       			component[prop] = args[prop];
       		}
       	}
       };
       
    Do you want to give that a try and let me know how it goes?
  2. Roman Avsec 2020-07-15

    Thank you for your response Ewan. In the meantime I've refactored that particular piece of code to more modern standards as well - it was a very old piece of code as evidenced by the coding standards used :) That seemed to have avoided triggering the minimization bug. Your approach works well too!
  3. Ewan Harris 2020-08-18

    I'm going to close this one out as the underlying issue was fixed

JSON Source