{ "id": "99720", "key": "TIMOB-10829", "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": [], "resolution": null, "resolutiondate": null, "created": "2012-08-24T07:24:02.000+0000", "epic": { "id": 170942, "key": "TIMOB-25710", "name": "SDK Parity effort", "summary": "SDK Parity effort", "color": { "key": "color_1" }, "done": false }, "priority": { "name": "Low", "id": "4" }, "labels": [ "api", "exalture" ], "versions": [ { "id": "14096", "description": "Release 2.1.2", "name": "Release 2.1.2", "archived": true, "released": true, "releaseDate": "2012-08-31" }, { "id": "14162", "description": "Release 3.1.0", "name": "Release 3.1.0", "archived": true, "released": true, "releaseDate": "2013-04-16" } ], "issuelinks": [ { "id": "56518", "type": { "id": "10003", "name": "Relates", "inward": "relates to", "outward": "relates to" }, "outwardIssue": { "id": "81773", "key": "TIMOB-5818", "fields": { "summary": "Ti API: View proxies should behave like real JS objects - or they should be wrapped", "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": "Medium", "id": "3" }, "issuetype": { "id": "2", "description": "A new feature of the product, which has yet to be developed.", "name": "New Feature", "subtask": false } } } }, { "id": "56681", "type": { "id": "10003", "name": "Relates", "inward": "relates to", "outward": "relates to" }, "inwardIssue": { "id": "171876", "key": "TIMOB-26179", "fields": { "summary": "iOS: Property check on proxy always returns true", "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": "Critical", "id": "1" }, "issuetype": { "id": "1", "description": "A problem which impairs or prevents the functions of the product.", "name": "Bug", "subtask": false } } } } ], "assignee": null, "updated": "2018-07-11T20:58:34.000+0000", "status": { "description": "This issue was once resolved, but the resolution was deemed incorrect. From here issues are either marked assigned or resolved.", "name": "Reopened", "id": "4", "statusCategory": { "id": 2, "key": "new", "colorName": "blue-gray", "name": "To Do" } }, "components": [ { "id": "10202", "name": "Android", "description": "Android Platform" } ], "description": "h2. The problem\r\n\r\n\r\nWell, I don't know how to explain the problem, or what precisely is causing it ... so it's the best if I just jump to example. :D\r\n\r\n\r\nh2. Test case\r\n\r\n\r\n{code}\r\nvar i = 0;\r\n\r\nvar win = {\r\n backgroundColor: '#000',\r\n __TiElement: null,\r\n __getTiElement: function() {\r\n if (!this.__TiElement) {\r\n this.__TiElement = Ti.UI.createWindow(this);\r\n }\r\n return this.__TiElement;\r\n },\r\n open: function() {\r\n Ti.API.info(i++);\r\n this.__getTiElement().open();\r\n }\r\n};\r\n\r\nwin.open();\r\n{code}\r\n\r\n\r\nRun this example, and you should get infinite loop (see in DDMS, i goes from 0 to infinity).\r\n\r\n\r\n\r\nAs I said, I'm not sure what's causing the problem, but it seems that \"this\" value is somehow set to wrong value (TiUIWindow because \"win\" and that causes infinite loop).\r\n\r\n\r\nThe problem can be solved if non-enumerable properties are used (by using \"Object.defineProperty\").\r\n\r\n\r\nThe issue does not exist on iOS.", "attachment": [], "flagged": false, "summary": "Android: Case of infinite loop", "creator": { "name": "ivan.skugor", "key": "ivan.skugor", "displayName": "Ivan Skugor", "active": true, "timeZone": "Europe/Amsterdam" }, "subtasks": [], "reporter": { "name": "ivan.skugor", "key": "ivan.skugor", "displayName": "Ivan Skugor", "active": true, "timeZone": "Europe/Amsterdam" }, "environment": "* Titanium SDK 2.2.0.v20120823190912\r\n* Android 4.0.3\r\n* v8\r\n* Thinkpad Tablet\r\n* OSX Mountain Lion", "comment": { "comments": [ { "id": "242646", "author": { "name": "jithinv@exalture.com", "key": "jithinv@exalture.com", "displayName": "jithinpv", "active": true, "timeZone": "America/Los_Angeles" }, "body": "infinite loop exists\n\nIssue reproduces with\n\nTitanium Studio, build: 3.0.1.201212181159\nTitanium SDK version: 3.1.0 (03/11/13 15:43 0c88429)\nTitanium SDK version: 3.0.2 (02/07/13 16:46 a4def81)\nDevice: Samsung galaxy s duos Android version: 4.0.4\n\njithinpv", "updateAuthor": { "name": "jithinv@exalture.com", "key": "jithinv@exalture.com", "displayName": "jithinpv", "active": true, "timeZone": "America/Los_Angeles" }, "created": "2013-03-18T12:35:22.000+0000", "updated": "2013-03-18T12:35:22.000+0000" }, { "id": "245441", "author": { "name": "sunila", "key": "sunila", "displayName": "Sunila", "active": true, "timeZone": "Asia/Kolkata" }, "body": "By giving 'this' to the createWindow, the execution context is set to 'this' which is the 'win'. so calling 'open' on the __TiElement actually calls the win.open. The behavior can be reproduced in a standalone javascript by replacing Ti.UI.createWindow(this) with 'new Object(this)' and replacing Ti.API.info with 'alert'.", "updateAuthor": { "name": "sunila", "key": "sunila", "displayName": "Sunila", "active": true, "timeZone": "Asia/Kolkata" }, "created": "2013-04-03T15:10:15.000+0000", "updated": "2013-04-03T15:10:15.000+0000" }, { "id": "245449", "author": { "name": "ivan.skugor", "key": "ivan.skugor", "displayName": "Ivan Skugor", "active": true, "timeZone": "Europe/Amsterdam" }, "body": "Hi Sunila.\r\n\r\n\r\nThat is not the same thing. \"win.open\" is different function from \"TiWindow.open\" (at least it should be). Your explanation of the cause of infinite loop could be right, but the problem still exists (that is, it should not happen). The same thing works on iOS - how come? ;)", "updateAuthor": { "name": "ivan.skugor", "key": "ivan.skugor", "displayName": "Ivan Skugor", "active": true, "timeZone": "Europe/Amsterdam" }, "created": "2013-04-03T15:54:19.000+0000", "updated": "2013-04-03T15:54:19.000+0000" }, { "id": "246414", "author": { "name": "bhughes", "key": "bhughes", "displayName": "Bryan Hughes", "active": true, "timeZone": "America/Los_Angeles" }, "body": "In the above example, win.open() does NOT set the this binding to the open window, or global object, or module object (if one exists). The this binding is set to the object \"win\", just as you would expect. At least that is what should happen according to the ECMAScript 5 spec.\r\n\r\nThis is definitely a bug in Android. I'm reopening it. If whoever works on this bug doesn't understand the details of how the this pointer is set in a function call, then come talk to me. FWIW the way that the this pointer is set in JavaScript calls is somewhat simple and _completely_ not what you would expect it to be.", "updateAuthor": { "name": "bhughes", "key": "bhughes", "displayName": "Bryan Hughes", "active": true, "timeZone": "America/Los_Angeles" }, "created": "2013-04-08T16:02:51.000+0000", "updated": "2013-04-08T16:05:40.000+0000" }, { "id": "250550", "author": { "name": "sunila", "key": "sunila", "displayName": "Sunila", "active": true, "timeZone": "Asia/Kolkata" }, "body": "Looks like a JS implementation bug.", "updateAuthor": { "name": "sunila", "key": "sunila", "displayName": "Sunila", "active": true, "timeZone": "Asia/Kolkata" }, "created": "2013-05-07T14:06:33.000+0000", "updated": "2013-05-07T14:06:33.000+0000" }, { "id": "437588", "author": { "name": "cwilliams", "key": "cwilliams", "displayName": "Christopher Williams", "active": true, "timeZone": "America/New_York" }, "body": "Man is this an oldie. Anyhow, I believe this is because Android is applying {{this}} to the window proxy it generates (like it applies any supplied properties, not as the context to execute under) - therefore what happens is that the window instance has it's {{open}} property (the native one we supply to actually open a window) replaced by the wrapper ({{win}} object here) {{open}} function. So calling open() on the window proxy is going to result in an infinite loop.\r\n\r\nThis actually relates to TIMOB-5818 in that I believe this is a result of Android and iOS having different property attributes on that open method. iOS defines The open method as not being writable which is why the wrapper can't overwrite the native method.\r\n\r\nAndroid gives this for the property descriptor:\r\n{code:javascript}\r\nopen = {\r\n \"writable\": true,\r\n \"enumerable\": true,\r\n \"configurable\": true\r\n}\r\n{code}\r\n\r\nWhile iOS gives:\r\n{code:javascript}\r\nopen = {\r\n \"writable\": false,\r\n \"enumerable\": false,\r\n \"configurable\": true\r\n}\r\n{code}\r\n(And will return that for made up properties on proxies that don't actually exist!)", "updateAuthor": { "name": "cwilliams", "key": "cwilliams", "displayName": "Christopher Williams", "active": true, "timeZone": "America/New_York" }, "created": "2018-05-11T21:00:21.000+0000", "updated": "2018-05-11T21:00:21.000+0000" } ], "maxResults": 6, "total": 6, "startAt": 0 } } }