{ "id": "168381", "key": "TIMOB-24830", "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": "19870", "description": "", "name": "Release 6.1.2", "archived": false, "released": true, "releaseDate": "2017-08-03" } ], "resolution": { "id": "1", "description": "A fix for this issue is checked into the tree and tested.", "name": "Fixed" }, "resolutiondate": "2017-07-27T08:33:54.000+0000", "created": "2017-06-14T00:56:31.000+0000", "priority": { "name": "Critical", "id": "1" }, "labels": [ "ios", "merge-6.1.2", "regression", "require" ], "versions": [ { "id": "17608", "name": "Release 6.1.0", "archived": false, "released": true, "releaseDate": "2017-05-26" } ], "issuelinks": [], "assignee": { "name": "cwilliams", "key": "cwilliams", "displayName": "Christopher Williams", "active": true, "timeZone": "America/New_York" }, "updated": "2017-07-27T16:38:40.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": "10206", "name": "iOS", "description": "iOS Platform" } ], "description": "After adding NodeJS style require we have a regression with huge performance issue. Previously all modules were required() only once. Now every module including Alloy models, controllers, and widgets are looking for a lot of places on each require call.\r\n\r\n\r\nsimple replace of this code in KrollBridge.m\r\n\r\n{code:objc}\r\nelse if ([path hasPrefix:@\"/\"]) {\r\n module = [self loadAsFileOrDirectory:[[path substringFromIndex:1] stringByStandardizingPath] withContext:context];\r\n if (module) {\r\n return module;\r\n }\r\n}\r\n{code}\r\n\r\nto old style:\r\n{code:objc}\r\nelse if ([path hasPrefix:@\"/\"]) {\r\n\tmodule = [modules objectForKey:path];\r\n\tif (module != nil) {\r\n\t return module;\r\n\t}\r\n\tmodule = [self loadAsFileOrDirectory:[[path substringFromIndex:1] stringByStandardizingPath] withContext:context];\r\n\tif (module) {\r\n\t [modules setObject:module forKey:path];\r\n\t return module;\r\n\t}\r\n}\r\n{code}\r\n\r\nmakes an application ten times more responsive in case you have a lot Alloy.createModel or Alloy.createController.\r\n\r\nand rid out logs like:\r\n{code}\r\n[DEBUG] : \b\b \bLoading: /Users/npatel/Library/Developer/CoreSimulator/Devices/E263476D-A174-40E7-A1BB-C300E0C1E468/data/Containers/Bundle/Application/CCB3551A-D92F-4555-8B85-1C17871EF502/Residential Test.app/node_modules/alloy/models/ServerCommonMasterTable/index.js, Resource: node_modules/alloy/models/ServerCommonMasterTable/index_js\r\n[DEBUG] : \b\b \bLoading: /Users/npatel/Library/Developer/CoreSimulator/Devices/E263476D-A174-40E7-A1BB-C300E0C1E468/data/Containers/Bundle/Application/CCB3551A-D92F-4555-8B85-1C17871EF502/Residential Test.app/node_modules/alloy/models/ServerCommonMasterTable/index.json, Resource: node_modules/alloy/models/ServerCommonMasterTable/index_json\r\n[DEBUG] : \b\b \bLoading: /Users/npatel/Library/Developer/CoreSimulator/Devices/E263476D-A174-40E7-A1BB-C300E0C1E468/data/Containers/Bundle/Application/CCB3551A-D92F-4555-8B85-1C17871EF502/Residential Test.app/alloy/models/ServerCommonMasterTable, Resource: alloy/models/ServerCommonMasterTable\r\n[DEBUG] : \b\b \bLoading: /Users/npatel/Library/Developer/CoreSimulator/Devices/E263476D-A174-40E7-A1BB-C300E0C1E468/data/Containers/Bundle/Application/CCB3551A-D92F-4555-8B85-1C17871EF502/Residential Test.app/alloy/models/ServerCommonMasterTable.js, Resource: alloy/models/ServerCommonMasterTable_js\r\n[DEBUG] : \b\b \bLoading: /Users/npatel/Library/Developer/CoreSimulator/Devices/E263476D-A174-40E7-A1BB-C300E0C1E468/data/Containers/Bundle/Application/CCB3551A-D92F-4555-8B85-1C17871EF502/Residential Test.app/node_modules/alloy/models/ServerCommonMasterTable, Resource: node_modules/alloy/models/ServerCommonMasterTable\r\n[DEBUG] : \b\b \bLoading: /Users/npatel/Library/Developer/CoreSimulator/Devices/E263476D-A174-40E7-A1BB-C300E0C1E468/data/Containers/Bundle/Application/CCB3551A-D92F-4555-8B85-1C17871EF502/Residential Test.app/node_modules/alloy/models/ServerCommonMasterTable.js, Resource: node_modules/alloy/models/ServerCommonMasterTable_js\r\n[DEBUG] : \b\b \bLoading: /Users/npatel/Library/Developer/CoreSimulator/Devices/E263476D-A174-40E7-A1BB-C300E0C1E468/data/Containers/Bundle/Application/CCB3551A-D92F-4555-8B85-1C17871EF502/Residential Test.app/node_modules/alloy/models/ServerCommonMasterTable.json, Resource: node_modules/alloy/models/ServerCommonMasterTable_json\r\n[DEBUG] : \b\b \bLoading: /Users/npatel/Library/Developer/CoreSimulator/Devices/E263476D-A174-40E7-A1BB-C300E0C1E468/data/Containers/Bundle/Application/CCB3551A-D92F-4555-8B85-1C17871EF502/Residential Test.app/node_modules/alloy/models/ServerCommonMasterTable/package.json, Resource: node_modules/alloy/models/ServerCommonMasterTable/package_json\r\n[DEBUG] : \b\b \bLoading: /Users/npatel/Library/Developer/CoreSimulator/Devices/E263476D-A174-40E7-A1BB-C300E0C1E468/data/Containers/Bundle/Application/CCB3551A-D92F-4555-8B85-1C17871EF502/Residential Test.app/node_modules/alloy/models/ServerCommonMasterTable/index.js, Resource: node_modules/alloy/models/ServerCommonMasterTable/index_js\r\n[DEBUG] : \b\b \bLoading: /Users/npatel/Library/Developer/CoreSimulator/Devices/E263476D-A174-40E7-A1BB-C300E0C1E468/data/Containers/Bundle/Application/CCB3551A-D92F-4555-8B85-1C17871EF502/Residential Test.app/node_modules/alloy/models/ServerCommonMasterTable/index.json, Resource: node_modules/alloy/models/ServerCommonMasterTable/index_json\r\n[DEBUG] : \b\b \bLoading: /Users/npatel/Library/Developer/CoreSimulator/Devices/E263476D-A174-40E7-A1BB-C300E0C1E468/data/Containers/Bundle/Application/CCB3551A-D92F-4555-8B85-1C17871EF502/Residential Test.app/node_modules/alloy/models/ServerCommonMasterTable, Resource: node_modules/alloy/models/ServerCommonMasterTable\r\n{code}", "attachment": [], "flagged": false, "summary": "iOS: Cache module after the first require() call (regression to 5.x)", "creator": { "name": "darknos", "key": "darknos", "displayName": "Sergey Nosenko", "active": true, "timeZone": "Europe/Helsinki" }, "subtasks": [], "reporter": { "name": "darknos", "key": "darknos", "displayName": "Sergey Nosenko", "active": true, "timeZone": "Europe/Helsinki" }, "environment": null, "comment": { "comments": [ { "id": "421913", "author": { "name": "darknos", "key": "darknos", "displayName": "Sergey Nosenko", "active": true, "timeZone": "Europe/Helsinki" }, "body": "this is how Nodjs works with require:\r\n{code}\r\nModule._load = function(request, parent, isMain) {\r\n // 1. Check Module._cache for the cached module.\r\n // 2. Create a new Module instance if cache is empty.\r\n // 3. Save it to the cache.\r\n // 4. Call module.load() with your the given filename.\r\n // This will call module.compile() after reading the file contents.\r\n // 5. If there was an error loading/parsing the file,\r\n // delete the bad module from the cache\r\n // 6. return module.exports\r\n};\r\n{code}", "updateAuthor": { "name": "darknos", "key": "darknos", "displayName": "Sergey Nosenko", "active": true, "timeZone": "Europe/Helsinki" }, "created": "2017-06-14T01:17:08.000+0000", "updated": "2017-06-14T01:17:08.000+0000" }, { "id": "422043", "author": { "name": "hknoechel", "key": "hansknoechel", "displayName": "Hans Knöchel", "active": true, "timeZone": "Europe/Berlin" }, "body": "Hey there, tackling the issue now. Discussed it with [~cwilliams], we should also cache the [relative paths|https://github.com/appcelerator/titanium_mobile/blob/master/iphone/Classes/KrollBridge.m#L1165] the same way. Preparing a PR now.", "updateAuthor": { "name": "hknoechel", "key": "hansknoechel", "displayName": "Hans Knöchel", "active": true, "timeZone": "Europe/Berlin" }, "created": "2017-06-15T16:01:26.000+0000", "updated": "2017-06-15T16:01:26.000+0000" }, { "id": "422066", "author": { "name": "darknos", "key": "darknos", "displayName": "Sergey Nosenko", "active": true, "timeZone": "Europe/Helsinki" }, "body": "I already did following. Do you need a PR?\r\n{code:objc}\r\n\t\t// 2. If X begins with './' or '/' or '../'\r\n if ([path hasPrefix:@\"./\"] || [path hasPrefix:@\"../\"]) {\r\n // Need base path to work from for relative modules...\r\n NSString *workingPath = [oldURL relativePath];\r\n NSString *relativePath = (workingPath == nil) ? path : [workingPath stringByAppendingPathComponent:path];\r\n module = [modules objectForKey:relativePath];\r\n if (module != nil) {\r\n return module;\r\n }\r\n module = [self loadAsFileOrDirectory:[relativePath stringByStandardizingPath] withContext:context];\r\n if (module) {\r\n [modules setObject:module forKey:relativePath];\r\n return module;\r\n }\r\n // Treat '/' special as absolute, drop the leading '/'\r\n }\r\n else if ([path hasPrefix:@\"/\"]) {\r\n module = [modules objectForKey:path];\r\n if (module != nil) {\r\n return module;\r\n }\r\n module = [self loadAsFileOrDirectory:[[path substringFromIndex:1] stringByStandardizingPath] withContext:context];\r\n if (module) {\r\n [modules setObject:module forKey:path];\r\n return module;\r\n } \r\n{code}", "updateAuthor": { "name": "darknos", "key": "darknos", "displayName": "Sergey Nosenko", "active": true, "timeZone": "Europe/Helsinki" }, "created": "2017-06-15T18:06:43.000+0000", "updated": "2017-06-15T18:06:43.000+0000" }, { "id": "422179", "author": { "name": "hknoechel", "key": "hansknoechel", "displayName": "Hans Knöchel", "active": true, "timeZone": "Europe/Berlin" }, "body": "*PR* (By Chris): https://github.com/appcelerator/titanium_mobile/pull/9158\r\n\r\n*Test-Case*:\r\n1. Create a new app with {{appc new -p ios}}\r\n2. Create a file called {{file.js}} in {{app/lib}} and paste the following into it:\r\n{code:js}\r\nexports.hello = 'World!';\r\n{code}\r\n3. Paste the following to the {{index.js}} (Alloy)\r\n{code:js}\r\nvar test1 = require('/file'); // Will load the module for the first time and cache it\r\nvar test2 = require('/file'); // Will use a cached reference of the module\r\n\r\nvar win = Ti.UI.createWindow({\r\n backgroundColor: '#fff'\r\n});\r\n\r\nvar btn = Ti.UI.createButton({\r\n title: 'Log Exports'\r\n});\r\n\r\nbtn.addEventListener('click', function() {\r\n\tconsole.log('#1' + test1.hello);\r\n\tconsole.log('#2 ' + test2.hello);\r\n});\r\n\r\nwin.add(btn);\r\nwin.open();\r\n{code}", "updateAuthor": { "name": "hknoechel", "key": "hansknoechel", "displayName": "Hans Knöchel", "active": true, "timeZone": "Europe/Berlin" }, "created": "2017-06-16T19:23:58.000+0000", "updated": "2017-07-20T22:21:54.000+0000" }, { "id": "424492", "author": { "name": "hknoechel", "key": "hansknoechel", "displayName": "Hans Knöchel", "active": true, "timeZone": "Europe/Berlin" }, "body": "Backport (6.1.2): https://github.com/appcelerator/titanium_mobile/pull/9232\r\nBackport (6.2.0): https://github.com/appcelerator/titanium_mobile/pull/9238", "updateAuthor": { "name": "hknoechel", "key": "hansknoechel", "displayName": "Hans Knöchel", "active": true, "timeZone": "Europe/Berlin" }, "created": "2017-07-20T22:24:45.000+0000", "updated": "2017-07-21T05:52:02.000+0000" }, { "id": "424862", "author": { "name": "amukherjee", "key": "amukherjee", "displayName": "Abir Mukherjee", "active": true, "timeZone": "America/Los_Angeles" }, "body": "Passed FR. Details are in github (in the PR). I'll merge as soon as [~hknoechel] confirms the intermittent failing unit tests are not an issue.", "updateAuthor": { "name": "amukherjee", "key": "amukherjee", "displayName": "Abir Mukherjee", "active": true, "timeZone": "America/Los_Angeles" }, "created": "2017-07-26T23:47:37.000+0000", "updated": "2017-07-26T23:47:37.000+0000" }, { "id": "424969", "author": { "name": "amukherjee", "key": "amukherjee", "displayName": "Abir Mukherjee", "active": true, "timeZone": "America/Los_Angeles" }, "body": "Closing ticket as fix is found in SDK 6.1.2.v20170727014823.", "updateAuthor": { "name": "amukherjee", "key": "amukherjee", "displayName": "Abir Mukherjee", "active": true, "timeZone": "America/Los_Angeles" }, "created": "2017-07-27T16:38:28.000+0000", "updated": "2017-07-27T16:38:28.000+0000" } ], "maxResults": 8, "total": 8, "startAt": 0 } } }