[TIMOB-24148] iOS: CommonJS modules/Library code cannot share names with native classes
GitHub Issue | n/a |
---|---|
Type | Bug |
Priority | High |
Status | Closed |
Resolution | Fixed |
Resolution Date | 2016-11-29T15:23:07.000+0000 |
Affected Version/s | Release 6.0.0 |
Fix Version/s | Release 6.0.1 |
Components | iOS |
Labels | qe-6.0.0 |
Reporter | Eric Wieber |
Assignee | Hans Knöchel |
Created | 2016-11-15T18:08:28.000+0000 |
Updated | 2016-11-30T18:12:50.000+0000 |
Description
Creating a commonJS module or using library code files that share a name with internal native classes throws an error.
[ERROR] : Script Error {
[ERROR] : column = 24;
[ERROR] : line = 12;
[ERROR] : message = "undefined is not a function (evaluating 'util.test()')";
[ERROR] : sourceURL = "file:///Users/Eric/Library/Developer/CoreSimulator/Devices/83A39029-8DC3-4231-90FA-C9394BF09F69/data/Containers/Bundle/Application/CF7DEB2C-4872-4B44-A119-48F7201E8CC8/checkit.app/alloy/controllers/index.js";
[ERROR] : stack = "doClick@file:///Users/Eric/Library/Developer/CoreSimulator/Devices/83A39029-8DC3-4231-90FA-C9394BF09F69/data/Containers/Bundle/Application/CF7DEB2C-4872-4B44-A119-48F7201E8CC8/checkit.app/alloy/controllers/index.js:12:24";
[ERROR] : }
*Steps to reproduce issue*
1. Create a new project
2. Add a js file to the app/lib folder that has the name of an internal native class (utils.js, for example)
3. Populate the file with an exported function
4. Require the module in the index.js and call the exported function
*Expected Results*
The exported function is called without issue
*Actual Results*
The above error is thrown
*Code*
For the default Alloy project, change the index.js
to:
var foo = require('utils');
function doClick(e) {
alert(foo.test());
}
$.index.open();
Then create a file called app/lib/utils.js
(Alloy) or Resources/utils.js
(Classic) and populate it with:
exports.test = function() {
return "I WAS CALLED";
};
As a side-note: You are actually able to use something like
var md5 = require('utils').md5HexDigest('mystr');
instead ofvar md5 = Ti.Utils.md5HexDigest('mystr');
which is pretty amazing and more "NodeJS'sh". But for the solution, we will now throw an error-log when the user tries to use the exact same name as one of the top moduels (UI, Utils, Filesystem, Calendar, ...) so they either prefix it correctly (e.g.require('./utils')
,require('./filesystem')
, ...) or rename it to something that does not collide. PR coming later today.PR (master): https://github.com/appcelerator/titanium_mobile/pull/8608 PR (6_0_X): https://github.com/appcelerator/titanium_mobile/pull/8609
[~cwilliams] Thinking about a proper unit-test, we could check if the local commonJS module fails and the native Ti method succeeds.
Fixes pushed to master: https://github.com/appcelerator/titanium_mobile/commit/9c564ab384ee3ea3c4e70a9d697eadf56fda0707 6_0_X: https://github.com/appcelerator/titanium_mobile/commit/a6667488f527e09b10acadea90162c4bc6eb9d22
Note that there is no real "fix" here, but instead we now detect when there's a name clash using the old style un-prefixed requires, such as
require('utils');
In that scenario where there's a clash between a native API/module and a JS file we will spit ou along warning to the logs stating that there was a collision and the native module/API was loaded in preference to the JS file, and if you intended to address the JS file you need to change the require to use a prefix such asrequire('./utils')
orrequire('/utils')
Verified "fixed" using: MacOS 10.12 (16A323) Studio 4.8.0.201611121409 Ti SDK 6.0.1.v20161130023500 Appc NPM 4.2.8 Appc CLI 6.0.0 Alloy 1.9.4 Xcode 8.1 (8B62) As Chris stated, the fix here is to display a warning message to use
./<module>
or/<module>
in order to use a CommonJS/library code with a naming conflict. This message is displayed when a conflict is detected and modifying the code, as described, will run without error.