{ "id": "175387", "key": "ALOY-1734", "fields": { "issuetype": { "id": "1", "description": "A problem which impairs or prevents the functions of the product.", "name": "Bug", "subtask": false }, "project": { "id": "11113", "key": "ALOY", "name": "Alloy", "projectCategory": { "id": "10400", "description": "Tools for developing applications", "name": "Tooling" } }, "fixVersions": [ { "id": "21028", "description": "", "name": "CLI Release 8.1.0", "archived": false, "released": true, "releaseDate": "2020-08-25" } ], "resolution": { "id": "1", "description": "A fix for this issue is checked into the tree and tested.", "name": "Fixed" }, "resolutiondate": "2020-08-11T20:24:48.000+0000", "created": "2020-07-30T20:48:49.000+0000", "priority": { "name": "High", "id": "2" }, "labels": [ "alloy", "globals", "regression" ], "versions": [], "issuelinks": [], "assignee": { "name": "eharris", "key": "eharris", "displayName": "Ewan Harris", "active": true, "timeZone": "Europe/Dublin" }, "updated": "2020-08-11T20:24:48.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": [], "description": "*Summary:*\r\nAs of Titanium 9.0.0, a JS files loaded via {{import}} in the \"alloy.js\" won't have access to globals {{Alloy}}, {{Backbone}}, or {{_}} (aka: lodash).\r\n\r\nThis is not an issue if JS files are loaded via the {{require()}} function.\r\n\r\n*Steps to reproduce:*\r\n# Download [kitchensink-v2|https://github.com/appcelerator/kitchensink-v2].\r\n# Open project file: {{./app/lib/actionbar.js}}\r\n# Add the following line to the end of the JS file:\r\n{code:javascript}\r\nconsole.log(\"@@@ Alloy = \" + (typeof Alloy));\r\n{code}\r\n# Build and run on Android or iOS.\r\n# Notice the following gets logged as undefined.\r\n{code}\r\n[INFO] @@@ Alloy = undefined\r\n{code}\r\n\r\n*Cause:*\r\nLook at the \"app.js\" that gets generated. The babel transpile is turning the JavaScript {{import}} statement into a {{require()}} function call at the top of the \"app.js\", above where we assign {{Alloy}} globals. Also note that \"var\" variables in \"app.js\" and \"alloy.js\" no longer have global scope as of Titanium 9.0.0, which is why it wasn't an issue before.\r\n\r\nThe top of the generated \"app.js\" looks like this.\r\n{code:javascript}\r\nvar _actionbar=_interopRequireDefault(require(\"actionbar\"));\r\nfunction _interopRequireDefault(obj){\r\n\treturn obj&&obj.__esModule?obj:{default:obj}\r\n}\r\n\"use strict\";\r\nvar Alloy=require(\"/alloy\"),\r\n\t_=Alloy._,\r\n\tBackbone=Alloy.Backbone;\r\nglobal.Alloy=Alloy,\r\nglobal._=_,\r\nglobal.Backbone=Backbone,\r\n{code}\r\n\r\n*Note:*\r\nJavaScript {{import}} statements are \"hoisted\". This is in the ES6 specification, which means this is not a babel transpile issue. So, {{import}} statements will always be executed first within the same JS file.\r\n\r\n*Possible Fix:*\r\nAdd an \"alloy.bootstrap.js\" to the project and assign the Alloy globals there. Bootstrap scripts are loaded before the \"app.js\", which works-around the problem. This also means we can remove the global Alloy assignment from the generated \"app.js\".\r\n\r\n*Work-Around:*\r\nDon't {{import}} JS files in the \"alloy.js\". Use {{require()}} function instead.\r\n", "attachment": [], "flagged": false, "summary": "JS files imported in \"alloy.js\" don't have access to Alloy globals as of Titanium 9.0.0", "creator": { "name": "jquick", "key": "jquick", "displayName": "Joshua Quick", "active": true, "timeZone": "America/Los_Angeles" }, "subtasks": [], "reporter": { "name": "jquick", "key": "jquick", "displayName": "Joshua Quick", "active": true, "timeZone": "America/Los_Angeles" }, "environment": null, "closedSprints": [ { "id": 1203, "state": "closed", "name": "2020 Sprint 16", "startDate": "2020-08-03T20:57:55.114Z", "endDate": "2020-08-14T20:57:00.000Z", "completeDate": "2020-08-14T15:19:51.647Z", "originBoardId": 114 } ], "comment": { "comments": [ { "id": "456296", "author": { "name": "eharris", "key": "eharris", "displayName": "Ewan Harris", "active": true, "timeZone": "Europe/Dublin" }, "body": "Adding the bootstrap file will be the only solution here, bable is adhering to the modules spec by hoisting the import statements like they would if they were actually ran in a JS environment (as opposed to being transpiled) https://exploringjs.com/es6/ch_modules.html#_imports-are-hoisted", "updateAuthor": { "name": "eharris", "key": "eharris", "displayName": "Ewan Harris", "active": true, "timeZone": "Europe/Dublin" }, "created": "2020-07-30T21:09:06.000+0000", "updated": "2020-07-30T21:09:06.000+0000" }, { "id": "456321", "author": { "name": "jquick", "key": "jquick", "displayName": "Joshua Quick", "active": true, "timeZone": "America/Los_Angeles" }, "body": "I can think of another solution.\r\n\r\nInstead of inserting the \"alloy.js\" code into the \"app.js\" template's {{__MAPMARKER_ALLOY_JS__}}, we could keep the \"alloy.js\" file and require it in instead.\r\nhttps://github.com/appcelerator/alloy/blob/master/Alloy/template/app.js\r\n\r\nSo Alloy's \"app.js\" code becomes the below.\r\n\r\n{code:javascript}\r\n//app.js\r\nvar Alloy = require('/alloy'),\r\n\t_ = Alloy._,\r\n\tBackbone = Alloy.Backbone;\r\nglobal.Alloy = Alloy;\r\nglobal._ = _;\r\nglobal.Backbone = Backbone;\r\n\r\n// Don't do this anymore.\r\n//__MAPMARKER_ALLOY_JS__\r\n\r\n// Require the \"alloy.js\" file instead.\r\nrequire('alloy');\r\n{code}\r\n\r\nThis means we're no longer generating an \"app.js\" and we would just copy this file and the developer's \"alloy.js\" as-is.", "updateAuthor": { "name": "jquick", "key": "jquick", "displayName": "Joshua Quick", "active": true, "timeZone": "America/Los_Angeles" }, "created": "2020-07-31T21:09:22.000+0000", "updated": "2020-07-31T21:09:22.000+0000" }, { "id": "456323", "author": { "name": "hknoechel", "key": "hansknoechel", "displayName": "Hans Knöchel", "active": true, "timeZone": "Europe/Berlin" }, "body": "Could we also (as a workaround) move not only the Alloy.Globals but the whole alloy.js contents to the bootstrap? Does this affect boot time?", "updateAuthor": { "name": "hknoechel", "key": "hansknoechel", "displayName": "Hans Knöchel", "active": true, "timeZone": "Europe/Berlin" }, "created": "2020-08-01T12:06:55.000+0000", "updated": "2020-08-01T12:06:55.000+0000" }, { "id": "456326", "author": { "name": "jquick", "key": "jquick", "displayName": "Joshua Quick", "active": true, "timeZone": "America/Los_Angeles" }, "body": "bq. Could we also (as a workaround) move not only the Alloy.Globals but the whole alloy.js contents to the bootstrap? Does this affect boot time?\r\n\r\nYes, that's exactly what I'm suggesting. And it wouldn't effect the boot time. We would simply be loading the \"alloy.js\" sooner than before (ie: before the \"app.js\"). A bootstrap script can only add a delay when using its optional async execute function, which we're not going to do in this case.\r\n\r\nAlso, it looks like JS imports being \"hoisted\" above JS statements is part of the ES6 specification. So, this isn't a babel issue. The babel transpile is doing the correct thing.", "updateAuthor": { "name": "jquick", "key": "jquick", "displayName": "Joshua Quick", "active": true, "timeZone": "America/Los_Angeles" }, "created": "2020-08-03T18:40:49.000+0000", "updated": "2020-08-03T18:40:49.000+0000" }, { "id": "456345", "author": { "name": "eharris", "key": "eharris", "displayName": "Ewan Harris", "active": true, "timeZone": "Europe/Dublin" }, "body": "PR: https://github.com/appcelerator/alloy/pull/964\r\n\r\nI did some small tests to see how this impacted the startup time of KS-v2 on Android and there's averaged out I'm seeing similar numbers, I'll continue to try collect data and also get some results for iOS ", "updateAuthor": { "name": "eharris", "key": "eharris", "displayName": "Ewan Harris", "active": true, "timeZone": "Europe/Dublin" }, "created": "2020-08-05T12:35:55.000+0000", "updated": "2020-08-05T12:35:55.000+0000" }, { "id": "456358", "author": { "name": "eharris", "key": "eharris", "displayName": "Ewan Harris", "active": true, "timeZone": "Europe/Dublin" }, "body": "Available in alloy 1.15.0 and appc CLI 8.1.0-master.9. Appc cli currently only preprod, so internal only", "updateAuthor": { "name": "eharris", "key": "eharris", "displayName": "Ewan Harris", "active": true, "timeZone": "Europe/Dublin" }, "created": "2020-08-06T12:56:36.000+0000", "updated": "2020-08-06T12:56:36.000+0000" }, { "id": "456419", "author": { "name": "ssekhri", "key": "ssekhri", "displayName": "Satyam Sekhri", "active": true, "timeZone": "America/Los_Angeles" }, "body": "Verified on:\r\nMac OS: 10.15.4\r\nSDK: 9.1.0.v20200810095016\r\nAppc CLI: 8.1.0-master.9\r\nJDK: 11.0.4\r\nNode: 10.17.0", "updateAuthor": { "name": "ssekhri", "key": "ssekhri", "displayName": "Satyam Sekhri", "active": true, "timeZone": "America/Los_Angeles" }, "created": "2020-08-11T20:24:48.000+0000", "updated": "2020-08-11T20:24:48.000+0000" } ], "maxResults": 7, "total": 7, "startAt": 0 } } }