{ "id": "172326", "key": "TIMOB-26403", "fields": { "issuetype": { "id": "1", "description": "A problem which impairs or prevents the functions of the product.", "name": "Bug", "subtask": false }, "project": { "id": "10153", "key": "TIMOB", "name": "Titanium SDK/CLI", "projectCategory": { "id": "10100", "description": "Titanium and related SDKs used in application development", "name": "Client" } }, "fixVersions": [ { "id": "20238", "description": "", "name": "Release 7.5.0", "archived": false, "released": true, "releaseDate": "2018-11-15" }, { "id": "20374", "name": "node-titanium-sdk 0.6.4", "archived": false, "released": true, "releaseDate": "2018-10-02" } ], "resolution": { "id": "1", "description": "A fix for this issue is checked into the tree and tested.", "name": "Fixed" }, "resolutiondate": "2018-10-22T15:06:32.000+0000", "created": "2018-09-20T13:26:14.000+0000", "priority": { "name": "High", "id": "2" }, "labels": [], "versions": [ { "id": "20238", "description": "", "name": "Release 7.5.0", "archived": false, "released": true, "releaseDate": "2018-11-15" } ], "issuelinks": [ { "id": "57039", "type": { "id": "10122", "name": "Gantt: start-finish", "inward": "is triggered by", "outward": "is triggering" }, "outwardIssue": { "id": "172661", "key": "TIMOB-26593", "fields": { "summary": "Problem with variable scope in SDK 7.5.0GA", "status": { "description": "The issue is considered finished, the resolution is correct. Issues which are closed can be reopened.", "name": "Closed", "id": "6", "statusCategory": { "id": 3, "key": "done", "colorName": "green", "name": "Done" } }, "priority": { "name": "None", "id": "6" }, "issuetype": { "id": "7", "description": "gh.issue.story.desc", "name": "Story", "subtask": false } } } }, { "id": "56872", "type": { "id": "10003", "name": "Relates", "inward": "relates to", "outward": "relates to" }, "outwardIssue": { "id": "172362", "key": "ALOY-1633", "fields": { "summary": "Alloy should assign globals directly rather than using the implicit global scope of app.js", "status": { "description": "The issue is considered finished, the resolution is correct. Issues which are closed can be reopened.", "name": "Closed", "id": "6", "statusCategory": { "id": 3, "key": "done", "colorName": "green", "name": "Done" } }, "priority": { "name": "High", "id": "2" }, "issuetype": { "id": "1", "description": "A problem which impairs or prevents the functions of the product.", "name": "Bug", "subtask": false } } } } ], "assignee": { "name": "cwilliams", "key": "cwilliams", "displayName": "Christopher Williams", "active": true, "timeZone": "America/New_York" }, "updated": "2018-11-22T16:37:25.000+0000", "status": { "description": "The issue is considered finished, the resolution is correct. Issues which are closed can be reopened.", "name": "Closed", "id": "6", "statusCategory": { "id": 3, "key": "done", "colorName": "green", "name": "Done" } }, "components": [ { "id": "10202", "name": "Android", "description": "Android Platform" }, { "id": "13103", "name": "CLI", "description": "Node-based command line interface" }, { "id": "10206", "name": "iOS", "description": "iOS Platform" }, { "id": "12642", "name": "Windows", "description": "Windows authoring support" } ], "description": "On the latest version of the SDK in master (7.5.0.v20180920040518) kitchensink-v2 is broken and displays the following error on iOS (Looks like it broke in SDK Version 7.5.0.v20180919143608):\r\n\r\n{code:java}\r\n[ERROR] : Script Error {\r\n[ERROR] : column = 18;\r\n[ERROR] : line = 6;\r\n[ERROR] : message = \"Can't find variable: _\";\r\n[ERROR] : sourceURL = \"file:///Users/Samir/Library/Developer/CoreSimulator/Devices/2BA65AF9-7B80-486E-9A20-005A318A4424/data/Containers/Bundle/Application/5A64DDEB-EA50-4721-81B9-15B9BBC5D6DE/KitchenSink.app/logger.js\";\r\n[ERROR] : stack = \" at Logger(/logger.js:6:18)\\n at (/logger.js:33:41)\\n at global code(/logger.js:35:70)\\n at require@[native code]\\n at (/alloy/controllers/index.js:5:22)\\n at global code(/alloy/controllers/index.js:108:70)\\n at require@[native code]\\n at createController(/alloy.js:339:21)\\n at (/app.js:34:23)\\n at global code(/app.js:36:70)\\n at require@[native code]\\n at (/ti.main.js:27:10)\\n at loadAsync(/ti.internal/bootstrap.loader.js:106:11)\\n at global code(/ti.main.js:24:52)\";\r\n[ERROR] : toJSON = \"\";\r\n[ERROR] : }\r\n[ERROR] : Script Error Module \"logger.js\" failed to leave a valid exports object\r\n[ERROR] : Script Error Module \"alloy/controllers/index.js\" failed to leave a valid exports object\r\n[ERROR] : Script Error Module \"app.js\" failed to leave a valid exports object\r\n{code}\r\n\r\n*Android Error*\r\n{code:java}\r\n[ERROR] : TiExceptionHandler: (main) [213,213] /logger.js:6\r\n[ERROR] : TiExceptionHandler: \t\tthis.logger = _.extend({}, Backbone.Events);\r\n[ERROR] : TiExceptionHandler: ^\r\n[ERROR] : TiExceptionHandler: ReferenceError: _ is not defined\r\n[ERROR] : TiExceptionHandler: at new Logger (/logger.js:6:17)\r\n[ERROR] : TiExceptionHandler: at /logger.js:33:33\r\n[ERROR] : TiExceptionHandler: at Module._runScript (ti:/module.js:613:9)\r\n[ERROR] : TiExceptionHandler: at Module.load (ti:/module.js:105:7)\r\n[ERROR] : TiExceptionHandler: at Module.loadJavascriptText (ti:/module.js:457:9)\r\n[ERROR] : TiExceptionHandler: at Module.loadAsFile (ti:/module.js:512:15)\r\n[ERROR] : TiExceptionHandler: at Module.loadAsFileOrDirectory (ti:/module.js:429:20)\r\n[ERROR] : TiExceptionHandler: at Module.require (ti:/module.js:296:17)\r\n[ERROR] : TiExceptionHandler: at require (ti:/module.js:570:15)\r\n[ERROR] : TiExceptionHandler: at /alloy/controllers/index.js:5:15\r\n[ERROR] : TiExceptionHandler:\r\n[ERROR] : TiExceptionHandler: org.appcelerator.kroll.runtime.v8.V8Runtime.nativeRunModule(Native Method)\r\n[ERROR] : TiExceptionHandler: org.appcelerator.kroll.runtime.v8.V8Runtime.doRunModule(V8Runtime.java:180)\r\n[ERROR] : TiExceptionHandler: org.appcelerator.kroll.KrollRuntime.runModule(KrollRuntime.java:247)\r\n[ERROR] : TiExceptionHandler: org.appcelerator.titanium.TiLaunchActivity.loadActivityScript(TiLaunchActivity.java:135)\r\n[ERROR] : TiExceptionHandler: org.appcelerator.titanium.TiLaunchActivity.windowCreated(TiLaunchActivity.java:190)\r\n[ERROR] : TiExceptionHandler: org.appcelerator.titanium.TiRootActivity.windowCreated(TiRootActivity.java:174)\r\n[ERROR] : TiExceptionHandler: org.appcelerator.titanium.TiBaseActivity.onCreate(TiBaseActivity.java:675)\r\n[ERROR] : TiExceptionHandler: org.appcelerator.titanium.TiLaunchActivity.onCreate(TiLaunchActivity.java:176)\r\n[ERROR] : TiExceptionHandler: org.appcelerator.titanium.TiRootActivity.onCreate(TiRootActivity.java:163)\r\n[ERROR] : TiExceptionHandler: android.app.Activity.performCreate(Activity.java:6237)\r\n[DEBUG] : OpenGLRenderer: Use EGL_SWAP_BEHAVIOR_PRESERVED: true\r\n[ERROR] : GraphResponse: {HttpStatus: 400, errorCode: -1, subErrorCode: -1, errorType: null, errorMessage: null}\r\n[DEBUG] : D/com.facebook.FacebookSdk: getGraphApiVersion: v3.0\r\n[ERROR] : V8Exception: Exception occurred at /logger.js:6: Uncaught ReferenceError: _ is not defined\r\n{code}\r\n\r\n*Test Steps*\r\n# Download the latest SDK version from master {{appc ti sdk install -b master -d}}\r\n# Download the kitchensink-v2 app from https://github.com/appcelerator/kitchensink-v2\r\n# Run the kitchensink-v2 using the latest master build\r\n\r\n*Expected result*\r\nApplication should run without any issues \r\n\r\n*Actual result*\r\nAbove error is shown\r\n\r\n*Note:* kitchensink-v2 works as expected in SDK version 7.5.0.v20180919120117", "attachment": [], "flagged": false, "summary": "kitchensink-v2 broken on latest SDK build on master ", "creator": { "name": "smohammed", "key": "smohammed", "displayName": "Samir Mohammed", "active": true, "timeZone": "America/Los_Angeles" }, "subtasks": [], "reporter": { "name": "smohammed", "key": "smohammed", "displayName": "Samir Mohammed", "active": true, "timeZone": "America/Los_Angeles" }, "environment": "APPC Studio: 5.1.0.201808080937\r\nAPPC CLI: 7.0.7-master.1\r\niphone 7 (11.4) sim\r\nOperating System Name: Mac OS High Sierra\r\nOperating System Version: 10.13.6\r\nNode.js Version: 8.9.1\r\nXcode 10.0\r\nSDK Version : 7.5.0.v20180919143608\r\nSDK Version : 7.5.0.v20180920040518", "closedSprints": [ { "id": 1088, "state": "closed", "name": "2018 Sprint 22", "startDate": "2018-10-21T23:20:52.653Z", "endDate": "2018-11-04T23:20:00.000Z", "completeDate": "2018-11-04T23:29:59.423Z", "originBoardId": 114 } ], "comment": { "comments": [ { "id": "441845", "author": { "name": "eharris", "key": "eharris", "displayName": "Ewan Harris", "active": true, "timeZone": "Europe/Dublin" }, "body": "This might be down to a change in the handling of the global scope-ness of variables defined in app.js, Alloy uses this to expose {{Alloy}}, {{_}}, and {{Backbone}} variables to the global scope for a user.", "updateAuthor": { "name": "eharris", "key": "eharris", "displayName": "Ewan Harris", "active": true, "timeZone": "Europe/Dublin" }, "created": "2018-09-20T13:34:38.000+0000", "updated": "2018-09-20T13:34:38.000+0000" }, { "id": "441864", "author": { "name": "jquick", "key": "jquick", "displayName": "Joshua Quick", "active": true, "timeZone": "America/Los_Angeles" }, "body": "Oh bummer. This isn't just an Alloy issue. I can reproduce this issue in a Classic app as well.\r\n\r\nHow it's supposed to work is that all local {{var}} declared variables in the 1st script executed (in our case \"app.js\") must have global scope across all JS files in the app. JavaScript does this for us by default. What's changed is that we're launching with \"ti.main.js\" instead of \"app.js\" now.\r\n\r\nI wasn't aware of this behavior. I'm kind of bummed by this. :-/\r\n\r\n*Steps to reproduce:*\r\n# Set up an \"app.js\" with the below.\r\n# Build and run using Titanium 7.3.0.\r\n# On app startup, an alert will read: \"global.test: Hello World\"\r\n# Build and run using Titanium 7.5.0.\r\n# On app startup, an alert will read: \"global.test: undefined\" _(This is the bug.)_\r\n\r\n{code:javascript}\r\nvar test = \"Hello World\";\r\nalert(\"global.test: \" + global.test);\r\n{code}\r\n\r\n_*Edit:*_\r\n_If you build and run the above code with 7.5.0 and LiveView, then it works. LiveView appears to have a work-around for this issue since it's effectively a bootstrap script as well._", "updateAuthor": { "name": "jquick", "key": "jquick", "displayName": "Joshua Quick", "active": true, "timeZone": "America/Los_Angeles" }, "created": "2018-09-20T21:18:59.000+0000", "updated": "2018-09-20T21:45:45.000+0000" }, { "id": "441866", "author": { "name": "eharris", "key": "eharris", "displayName": "Ewan Harris", "active": true, "timeZone": "Europe/Dublin" }, "body": "For the liveview part, I imagine that's to do with [this piece of code|https://github.com/appcelerator/liveview/blob/master/lib/fserver.js#L298-L317] which removes var/let/const from all variable declarations in app.js when serving the code up to the device causing them to become globals variables", "updateAuthor": { "name": "eharris", "key": "eharris", "displayName": "Ewan Harris", "active": true, "timeZone": "Europe/Dublin" }, "created": "2018-09-20T22:01:26.000+0000", "updated": "2018-09-20T22:01:26.000+0000" }, { "id": "441900", "author": { "name": "jquick", "key": "jquick", "displayName": "Joshua Quick", "active": true, "timeZone": "America/Los_Angeles" }, "body": "FYI: [~kiguchi] and I are discussing this on the following Windows PR...\r\nhttps://github.com/appcelerator/titanium_mobile_windows/pull/1285#issuecomment-423415599\r\n\r\nWe \"can\" solve this by using the {{eval()}} function (which I think is a naughty solution), but we would have to ensure that stack-traces and debugger breakpoints work.", "updateAuthor": { "name": "jquick", "key": "jquick", "displayName": "Joshua Quick", "active": true, "timeZone": "America/Los_Angeles" }, "created": "2018-09-21T18:00:08.000+0000", "updated": "2018-09-21T18:00:08.000+0000" }, { "id": "442002", "author": { "name": "cwilliams", "key": "cwilliams", "displayName": "Christopher Williams", "active": true, "timeZone": "America/New_York" }, "body": "FWIW, Alloy is really relying on undefined/undocumented/unspec'd behavior. Ideally all of our code should assume we're going to be treated as a \"module\" (CommonJS or ES6) and therefore shouldn't implicitly assume that top-level vars will live on as globals so long as they're defined in the eventual {{app.js}}. I think we should fix Alloy immediately to future-proof it here: we have explicitly exposed a {{global}} object to use for hanging global functions/variables/state. (Also a note that we had undocumented behavior that the {{this}} binding referred to the {{global}} object in {{app.js}} before as well)", "updateAuthor": { "name": "cwilliams", "key": "cwilliams", "displayName": "Christopher Williams", "active": true, "timeZone": "America/New_York" }, "created": "2018-09-24T19:08:46.000+0000", "updated": "2018-09-24T19:08:46.000+0000" }, { "id": "442003", "author": { "name": "cwilliams", "key": "cwilliams", "displayName": "Christopher Williams", "active": true, "timeZone": "America/New_York" }, "body": "Oh yeah - and we had written a custom babel plugin to handle references to {{this}} in the top-level so that when we transpiled we'd replace with a reference to {{global}}. I assume we should be able to do the same exact thing here - gather all top-level variables and assign them as properties off {{global}}. It'd preserve backwards compatibility so long as the plugin got run.\r\n\r\n(See https://github.com/appcelerator/node-titanium-sdk/blob/master/lib/global-this.js)", "updateAuthor": { "name": "cwilliams", "key": "cwilliams", "displayName": "Christopher Williams", "active": true, "timeZone": "America/New_York" }, "created": "2018-09-24T19:11:33.000+0000", "updated": "2018-09-24T19:11:33.000+0000" }, { "id": "442007", "author": { "name": "eharris", "key": "eharris", "displayName": "Ewan Harris", "active": true, "timeZone": "Europe/Dublin" }, "body": "https://github.com/ewanharris/liveview/blob/TIMOB-25861/lib/global-plugin.js Might fit the bill for the global plugin, I wrote it for liveview transpilation support as it needs to do the same task as we need to achieve here (not sure why I didn't think of linking that in before), we'd just need to separate the transpile flag from running babel I assume, and remove the lvGlobal bits from it", "updateAuthor": { "name": "eharris", "key": "eharris", "displayName": "Ewan Harris", "active": true, "timeZone": "Europe/Dublin" }, "created": "2018-09-24T20:23:52.000+0000", "updated": "2018-09-24T20:25:50.000+0000" }, { "id": "442017", "author": { "name": "jquick", "key": "jquick", "displayName": "Joshua Quick", "active": true, "timeZone": "America/Los_Angeles" }, "body": "If our best practices state that you should not depend on \"app.js\" globals, then how about we add the following to the top of the [./app/lib/logger.js|https://github.com/appcelerator/kitchensink-v2/blob/master/app/lib/logger.js] file. The below will solve the problem for kitchensink-v2. (Note that Alloy injects the below code at the top of every controller JS file.)\r\n{code:javascript}\r\nvar Alloy = require('/alloy'),\r\n\tBackbone = Alloy.Backbone,\r\n\t_ = Alloy._;\r\n{code}\r\n\r\nWe can then write-up a separate ticket for the bootstrap breaking-change.\r\n\r\nSounds good?", "updateAuthor": { "name": "jquick", "key": "jquick", "displayName": "Joshua Quick", "active": true, "timeZone": "America/Los_Angeles" }, "created": "2018-09-24T22:46:36.000+0000", "updated": "2018-09-24T22:46:36.000+0000" }, { "id": "442069", "author": { "name": "eharris", "key": "eharris", "displayName": "Ewan Harris", "active": true, "timeZone": "Europe/Dublin" }, "body": "My opinion is that even if we change the app.js global scope behaviour, we should still make Alloy, Backbone and _ globals ourselves in Alloy, this is the route that Fokke took in his PR for ALOY-1259 (a kind of related ticket) [here|https://github.com/appcelerator/alloy/pull/675]. Requiring a developer to repeat the same 3 lines in most controller files seems meh to me, and there may be internal Alloy files that rely on that behaviour, not making those globals anymore just seems like a needless breaking change imo.\r\n\r\nCould you clarify on {{bootstrap breaking-change}} do you mean the change that caused this ticket? I'm not 100% certain why we'd break off from this one?", "updateAuthor": { "name": "eharris", "key": "eharris", "displayName": "Ewan Harris", "active": true, "timeZone": "Europe/Dublin" }, "created": "2018-09-26T14:59:57.000+0000", "updated": "2018-09-26T14:59:57.000+0000" }, { "id": "442084", "author": { "name": "cwilliams", "key": "cwilliams", "displayName": "Christopher Williams", "active": true, "timeZone": "America/New_York" }, "body": "My two cents:\r\n- File a new ticket to fix alloy to properly assign the globals.\r\n- Add a custom babel plugin that fixes the issue on app.js top-level vars by assigning them to global as properties explicitly. Possibly bake in some logging there to note that this is deprecated behavior we will eventually remove.\r\n- Always run this babel plugin, even if transpilation is turned off?\r\n\r\nI know that tehcnically speaking there are ways we could retain this behavior. On Android we have internal APIs for running JS code in a specific context. On Windows/iOS JSC allows us to pass in the `this` binding when evaluating code, etc. We could use eval to work around it. But I think all of these solutions aren't ideal, as we'd definitely need to tweak Windows/iOS to expose them, and it just doesn't feel very elegant to me.\r\n\r\nGiven that people are really relying on unspecified/documented behavior and that this is known to be a bad practice we should simply go with the easier fix of using the babel plugin to implicitly fix it for them (while complaining in the logs about usage), and deprecate it so that we can remove it in 9.0.0.", "updateAuthor": { "name": "cwilliams", "key": "cwilliams", "displayName": "Christopher Williams", "active": true, "timeZone": "America/New_York" }, "created": "2018-09-26T19:14:13.000+0000", "updated": "2018-09-26T19:14:13.000+0000" }, { "id": "442199", "author": { "name": "eharris", "key": "eharris", "displayName": "Ewan Harris", "active": true, "timeZone": "Europe/Dublin" }, "body": "I've taken the liveview plugin I wrote and converted it for general usage, the PR is here https://github.com/appcelerator/node-titanium-sdk/pull/47. It just needs a little bit more work to try figure out if it's possible to pass our logger instance in there", "updateAuthor": { "name": "eharris", "key": "eharris", "displayName": "Ewan Harris", "active": true, "timeZone": "Europe/Dublin" }, "created": "2018-10-01T16:56:13.000+0000", "updated": "2018-10-01T16:56:13.000+0000" }, { "id": "442215", "author": { "name": "cwilliams", "key": "cwilliams", "displayName": "Christopher Williams", "active": true, "timeZone": "America/New_York" }, "body": "There's a few fixes here to tackle this.\r\n\r\nSpecifically, we should update Alloy to explicitly expose any globals when there's a global object available.\r\n\r\nSecond, Ewan is working on a babel plugin to fix the general case of implicit globals from top-level variables in app.js.", "updateAuthor": { "name": "cwilliams", "key": "cwilliams", "displayName": "Christopher Williams", "active": true, "timeZone": "America/New_York" }, "created": "2018-10-02T15:59:24.000+0000", "updated": "2018-10-02T15:59:24.000+0000" }, { "id": "442216", "author": { "name": "cwilliams", "key": "cwilliams", "displayName": "Christopher Williams", "active": true, "timeZone": "America/New_York" }, "body": "Here's the alloy fix: https://github.com/appcelerator/alloy/pull/913", "updateAuthor": { "name": "cwilliams", "key": "cwilliams", "displayName": "Christopher Williams", "active": true, "timeZone": "America/New_York" }, "created": "2018-10-02T16:02:04.000+0000", "updated": "2018-10-02T16:02:04.000+0000" }, { "id": "442252", "author": { "name": "eharris", "key": "eharris", "displayName": "Ewan Harris", "active": true, "timeZone": "Europe/Dublin" }, "body": "titanium_mobile: https://github.com/appcelerator/titanium_mobile/pull/10364\r\ntitanium_mobile_windows: https://github.com/appcelerator/titanium_mobile_windows/pull/1288\r\n", "updateAuthor": { "name": "eharris", "key": "eharris", "displayName": "Ewan Harris", "active": true, "timeZone": "Europe/Dublin" }, "created": "2018-10-03T13:34:18.000+0000", "updated": "2018-10-03T13:34:18.000+0000" }, { "id": "442829", "author": { "name": "cwilliams", "key": "cwilliams", "displayName": "Christopher Williams", "active": true, "timeZone": "America/New_York" }, "body": "All PRs have been merged for this ticket.", "updateAuthor": { "name": "cwilliams", "key": "cwilliams", "displayName": "Christopher Williams", "active": true, "timeZone": "America/New_York" }, "created": "2018-10-22T15:06:32.000+0000", "updated": "2018-10-22T15:06:32.000+0000" }, { "id": "442837", "author": { "name": "kmahalingam", "key": "kmahalingam", "displayName": "Keerthi Mahalingam", "active": false, "timeZone": "America/Los_Angeles" }, "body": "Verified the fix on SDK 7.5.0.v20181018133006. Kitchensink-v2 app works fine on android and iOS. Closing.\r\n{code}\r\nOperating System\r\n Name = Mac OS X\r\n Version = 10.13.6\r\n Architecture = 64bit\r\nNode.js\r\n Node.js Version = 8.12.0\r\n npm Version = 6.4.1\r\nTitanium CLI\r\n CLI Version = 5.1.1\r\nTitanium SDK = 7.5.0.v20181018133006\r\nDevice =Samsung s5 android 6 device, pixel android 7 emulator\r\n iPhone 6s iOS 12 device, iPhone 6 iOS 11 simulator\r\n\r\n{code}", "updateAuthor": { "name": "kmahalingam", "key": "kmahalingam", "displayName": "Keerthi Mahalingam", "active": false, "timeZone": "America/Los_Angeles" }, "created": "2018-10-22T18:59:00.000+0000", "updated": "2018-10-22T18:59:00.000+0000" } ], "maxResults": 18, "total": 18, "startAt": 0 } } }