{ "id": "104896", "key": "TIMOB-11752", "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": "14164", "description": "Release 3.0.2", "name": "Release 3.0.2", "archived": true, "released": true, "releaseDate": "2013-02-19" }, { "id": "14162", "description": "Release 3.1.0", "name": "Release 3.1.0", "archived": true, "released": true, "releaseDate": "2013-04-16" }, { "id": "15070", "description": "2013 Sprint 02 Core", "name": "2013 Sprint 02 Core", "archived": true, "released": true, "releaseDate": "2013-01-28" }, { "id": "14812", "description": "2013 Sprint 02", "name": "2013 Sprint 02", "archived": true, "released": true, "releaseDate": "2013-01-28" } ], "resolution": { "id": "1", "description": "A fix for this issue is checked into the tree and tested.", "name": "Fixed" }, "resolutiondate": "2013-01-29T00:04:08.000+0000", "created": "2012-11-13T20:04:39.000+0000", "priority": { "name": "High", "id": "2" }, "labels": [ "qe-port", "triage" ], "versions": [ { "id": "13505", "description": "Release 3.0.0", "name": "Release 3.0.0", "archived": true, "released": true, "releaseDate": "2012-12-14" } ], "issuelinks": [ { "id": "22763", "type": { "id": "10020", "name": "Depends", "inward": "is dependent of", "outward": "depends on" }, "inwardIssue": { "id": "104898", "key": "ALOY-381", "fields": { "summary": "Resolve global variables in commonjs modules platform disparities", "status": { "description": "A resolution has been taken, and it is awaiting verification by reporter. From here issues are either reopened, or are closed.", "name": "Resolved", "id": "5", "statusCategory": { "id": 3, "key": "done", "colorName": "green", "name": "Done" } }, "priority": { "name": "High", "id": "2" }, "issuetype": { "id": "7", "description": "gh.issue.story.desc", "name": "Story", "subtask": false } } } }, { "id": "26203", "type": { "id": "10003", "name": "Relates", "inward": "relates to", "outward": "relates to" }, "outwardIssue": { "id": "110398", "key": "TIDOC-1048", "fields": { "summary": "Add documentation regarding deprecated usage of globals", "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": "Medium", "id": "3" }, "issuetype": { "id": "7", "description": "gh.issue.story.desc", "name": "Story", "subtask": false } } } }, { "id": "24548", "type": { "id": "10003", "name": "Relates", "inward": "relates to", "outward": "relates to" }, "inwardIssue": { "id": "107871", "key": "TIMOB-12286", "fields": { "summary": "Android: Memory leak when backing out and coming back to an app", "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 } } } }, { "id": "30562", "type": { "id": "10003", "name": "Relates", "inward": "relates to", "outward": "relates to" }, "inwardIssue": { "id": "117836", "key": "TIMOB-14721", "fields": { "summary": "LiveView: App.js Lexical Scope local vars not globally available ", "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 } } } }, { "id": "25650", "type": { "id": "10003", "name": "Relates", "inward": "relates to", "outward": "relates to" }, "inwardIssue": { "id": "109458", "key": "TIMOB-12648", "fields": { "summary": "TiAPI: Create a \"global\" variable", "status": { "description": "The issue is open and ready for the assignee to start work on it.", "name": "Open", "id": "1", "statusCategory": { "id": 2, "key": "new", "colorName": "blue-gray", "name": "To Do" } }, "priority": { "name": "Low", "id": "4" }, "issuetype": { "id": "2", "description": "A new feature of the product, which has yet to be developed.", "name": "New Feature", "subtask": false } } } } ], "assignee": { "name": "ingo", "key": "ingo", "displayName": "Ingo Muschenetz", "active": true, "timeZone": "America/Los_Angeles" }, "updated": "2013-08-01T16:30:52.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" } ], "description": "*DISCLAIMER:* I know this isn't technically an Android bug. It's just a \"one of these things is not like the others\" situation that is causing headaches for Alloy developers (others too i assume).\r\n\r\nh2. Problem\r\n\r\niOS and Mobileweb have access to global variables in their commonjs modules. Android does not. From what I understand, Android is actually implementing commonjs appropriately and globals should *NOT* be accessible in commonjs modules. \r\n\r\nThe typical complaint I hear is \"I did this code in iOS and it doesn't work on Android\". WRT Alloy, people constantly complain that the builtin Alloy namespace is not accessible in their custom, non-controller JS libraries on Android. This is because iOS and Mobileweb make Alloy available globally. While it may be convenient on those platforms, it's not actually how it should be implemented. This is just a symptom of the deeper problem of disparity in the commonjs implementations.\r\n\r\nWhile the technical issue is clear, the answer is a little muddier. The \"right\" answer would be to _not_ make globals available in commonjs modules in iOS and Mobileweb, just like Android, as this adheres to the actual Commonjs spec. Unfortunately, that is bound to break a lot of existing apps that rely on this improper implementation. The \"safe\" answer would likely be to make globals accessible in Android commonjs modules. It diverges from the spec, but will solve these problems and would be the change most transparent to the developer base. From Alloy's perspective, either is fine, but we just need parity one way or the other.\r\n\r\nh2. Proposed Solution\r\n\r\nOne of 2 solutions would create parity between the platforms:\r\n\r\n# Make globals inaccessible in commonjs modules in iOS and Mobileweb\r\n# Make globals accessible in commonjs modules in Android\r\n\r\nh2. Test Case\r\n\r\nh4. app.js\r\n{code:javascript}\r\nvar someGlobal = { someValue: 1 };\r\nrequire('someModule');\r\n{code}\r\n\r\nh4. someModule.js\r\n{code:javascript}\r\nalert(someGlobal.someValue);\r\n{code}\r\n\r\nOn iOS and Mobileweb the app will pop open an alert box with the number *1* in it. On Android, it will fail with the exception seen in the attached screenshot.", "attachment": [ { "id": "33430", "filename": "Screen Shot 2012-11-13 at 3.04.11 PM.png", "author": { "name": "tlukasavage", "key": "tlukasavage", "displayName": "Tony Lukasavage", "active": true, "timeZone": "America/Los_Angeles" }, "created": "2012-11-13T20:04:39.000+0000", "size": 58038, "mimeType": "image/png" } ], "flagged": false, "summary": "Android: Globals not accessible in CommonJS modules", "creator": { "name": "tlukasavage", "key": "tlukasavage", "displayName": "Tony Lukasavage", "active": true, "timeZone": "America/Los_Angeles" }, "subtasks": [], "reporter": { "name": "tlukasavage", "key": "tlukasavage", "displayName": "Tony Lukasavage", "active": true, "timeZone": "America/Los_Angeles" }, "environment": "TiStudio 3.0.0.x\r\nTiSDK 3.0.0", "comment": { "comments": [ { "id": "227820", "author": { "name": "joshroesslein", "key": "joshroesslein", "displayName": "Josh Roesslein", "active": true, "timeZone": "America/Los_Angeles" }, "body": "I think it may be fine exposing the globals and running all modules within the same JS context.\r\nIt's not clear if CommonJS requires complete isolation by running modules in their own contexts.\r\nI know Node by default does NOT create a new context for each module, so you can access the globals.\r\nI think the important thing about modules is providing a \"private\" space and allowing them to only\r\nexport what they want to be \"public\". I believe we do provide this important feature in all platforms.\r\n\r\nAs for why we use a new context for each module on Android, I recall there being a technical reason,\r\nbut we may be able to work around it. The plus side of not creating contexts is \"instanceof\" testing\r\nis less weird (since each module has its own context, they each have their own built-in objects).\r\n\r\nBefore we do anything we should probably put together a formal specification and testing strategy.\r\nI think this would go a long way in getting us to parity and documenting how modules work in Titanium. ", "updateAuthor": { "name": "joshroesslein", "key": "joshroesslein", "displayName": "Josh Roesslein", "active": true, "timeZone": "America/Los_Angeles" }, "created": "2012-11-17T10:10:17.000+0000", "updated": "2012-11-17T10:11:09.000+0000" }, { "id": "229327", "author": { "name": "tlukasavage", "key": "tlukasavage", "displayName": "Tony Lukasavage", "active": true, "timeZone": "America/Los_Angeles" }, "body": "So what is the path forward? Is this going to be addressed in a upcoming release? If so, is it safe to assume that Android will make globals accessible throughout modules like mobileweb and ios?", "updateAuthor": { "name": "tlukasavage", "key": "tlukasavage", "displayName": "Tony Lukasavage", "active": true, "timeZone": "America/Los_Angeles" }, "created": "2012-11-30T17:42:00.000+0000", "updated": "2012-11-30T17:42:00.000+0000" }, { "id": "230861", "author": { "name": "skypanther", "key": "skypanther", "displayName": "Tim Poulsen", "active": true, "timeZone": "America/New_York" }, "body": "I would prefer modules to be isolated and w/out access to the global space of the calling context. It's not that hard to pass in required objects or require() in a sub-module. It forces separation and discipline and better lends itself to creating stand-alone modules that can be easily dropped into another project.", "updateAuthor": { "name": "skypanther", "key": "skypanther", "displayName": "Tim Poulsen", "active": true, "timeZone": "America/New_York" }, "created": "2012-12-11T17:58:50.000+0000", "updated": "2012-12-11T17:58:50.000+0000" }, { "id": "234114", "author": { "name": "dbankier", "key": "dbankier", "displayName": "David Bankier", "active": true, "timeZone": "America/Los_Angeles" }, "body": "If you need a work around now, I released an example of how to make Android behave like iOS.\r\n\r\nBlog: http://www.yydigital.com/blog/2013/1/13/Achieving_Require_Parity\r\nGithub: https://github.com/dbankier/GlobalRequire", "updateAuthor": { "name": "dbankier", "key": "dbankier", "displayName": "David Bankier", "active": true, "timeZone": "America/Los_Angeles" }, "created": "2013-01-13T03:28:01.000+0000", "updated": "2013-01-13T03:28:01.000+0000" }, { "id": "234144", "author": { "name": "tlukasavage", "key": "tlukasavage", "displayName": "Tony Lukasavage", "active": true, "timeZone": "America/Los_Angeles" }, "body": "Nice work David. I'm not making the decisions, but I'm guessing the platform-level solution will take a similar route, giving Android the behavior of Mobileweb and iOS.", "updateAuthor": { "name": "tlukasavage", "key": "tlukasavage", "displayName": "Tony Lukasavage", "active": true, "timeZone": "America/Los_Angeles" }, "created": "2013-01-14T05:42:53.000+0000", "updated": "2013-01-14T05:42:53.000+0000" }, { "id": "234145", "author": { "name": "ivan.skugor", "key": "ivan.skugor", "displayName": "Ivan Skugor", "active": true, "timeZone": "Europe/Amsterdam" }, "body": "I totally agree with Tim.\r\n\r\n\r\n\r\nNodeJs permits access to global scope variables (by error or not) and it has its own mechanism of creating and using global variables (via \"GLOBALS\"), but - everybody everywhere discourages usage of global variables for a reason. We may not like tons of \"require\"s on top of every module (I hate it TBH), but it certainly has great benefits.", "updateAuthor": { "name": "ivan.skugor", "key": "ivan.skugor", "displayName": "Ivan Skugor", "active": true, "timeZone": "Europe/Amsterdam" }, "created": "2013-01-14T06:39:00.000+0000", "updated": "2013-01-14T06:39:00.000+0000" }, { "id": "235436", "author": { "name": "ayeung", "key": "ayeung", "displayName": "Allen Yeung", "active": true, "timeZone": "America/Los_Angeles" }, "body": "Solved by https://github.com/appcelerator/titanium_mobile/pull/3757", "updateAuthor": { "name": "ayeung", "key": "ayeung", "displayName": "Allen Yeung", "active": true, "timeZone": "America/Los_Angeles" }, "created": "2013-01-23T00:34:20.000+0000", "updated": "2013-01-23T00:34:20.000+0000" }, { "id": "236407", "author": { "name": "amittal", "key": "amittal", "displayName": "Anshu Mittal", "active": true, "timeZone": "America/Los_Angeles" }, "body": "Tested with: \r\nSDK:3.1.0.v20130128172329,3.0.2.v20130128174806\r\nStudio:3.0.2.201301251115\r\nDevice: iPhone3GS(v 5.0.1), Android Emulator(2.3)", "updateAuthor": { "name": "amittal", "key": "amittal", "displayName": "Anshu Mittal", "active": true, "timeZone": "America/Los_Angeles" }, "created": "2013-01-29T09:51:22.000+0000", "updated": "2013-01-29T09:51:22.000+0000" }, { "id": "237840", "author": { "name": "bhughes", "key": "bhughes", "displayName": "Bryan Hughes", "active": true, "timeZone": "America/Los_Angeles" }, "body": "FYI Mobile Web does NOT share global contexts between modules! app.js is evaluated in global space though, so variables declared _only in app.js_ are available globally. This is actually a bug in Mobile Web and is not supposed to be the behavior.", "updateAuthor": { "name": "bhughes", "key": "bhughes", "displayName": "Bryan Hughes", "active": true, "timeZone": "America/Los_Angeles" }, "created": "2013-02-08T22:33:07.000+0000", "updated": "2013-02-08T22:33:07.000+0000" }, { "id": "239216", "author": { "name": "mofle", "key": "mofle", "displayName": "Sindre Sorhus", "active": true, "timeZone": "Europe/Oslo" }, "body": "Sad to see you're going with fixing it for users using it wrong instead of fixing the actual problem correctly... Please consider changing this in the next major release.", "updateAuthor": { "name": "mofle", "key": "mofle", "displayName": "Sindre Sorhus", "active": true, "timeZone": "Europe/Oslo" }, "created": "2013-02-21T10:13:34.000+0000", "updated": "2013-02-21T10:13:34.000+0000" }, { "id": "240261", "author": { "name": "ingo", "key": "ingo", "displayName": "Ingo Muschenetz", "active": true, "timeZone": "America/Los_Angeles" }, "body": "To clarify, this was \"fixed\" as a side effect of TIMOB-12286, but this is not the intended end goal. We would prefer to not allow globals as specified above, but it is the lesser of two evils when compared with the Android memory leak.\n\nInstead, we are marking this usage as unsupported and deprecated, where it could be removed at any point, and likely will be in the future. In the meantime, users who wish to use globals in Alloy applications can use:\n\n{code}\nvar Alloy = require('alloy');\n{code}\n\ninstead. I have filed a related ticket to update the documentation discussing global usage and proper approaches.", "updateAuthor": { "name": "ingo", "key": "ingo", "displayName": "Ingo Muschenetz", "active": true, "timeZone": "America/Los_Angeles" }, "created": "2013-02-28T22:00:13.000+0000", "updated": "2013-02-28T22:00:13.000+0000" } ], "maxResults": 11, "total": 11, "startAt": 0 } } }