Titanium JIRA Archive
Titanium SDK/CLI (TIMOB)

[TIMOB-24148] iOS: CommonJS modules/Library code cannot share names with native classes

GitHub Issuen/a
TypeBug
PriorityHigh
StatusClosed
ResolutionFixed
Resolution Date2016-11-29T15:23:07.000+0000
Affected Version/sRelease 6.0.0
Fix Version/sRelease 6.0.1
ComponentsiOS
Labelsqe-6.0.0
ReporterEric Wieber
AssigneeHans Knöchel
Created2016-11-15T18:08:28.000+0000
Updated2016-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";
};

Comments

  1. Hans Knöchel 2016-11-15

    As a side-note: You are actually able to use something like var md5 = require('utils').md5HexDigest('mystr'); instead of var 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.
  2. Hans Knöchel 2016-11-16

    PR (master): https://github.com/appcelerator/titanium_mobile/pull/8608 PR (6_0_X): https://github.com/appcelerator/titanium_mobile/pull/8609
  3. Hans Knöchel 2016-11-16

    [~cwilliams] Thinking about a proper unit-test, we could check if the local commonJS module fails and the native Ti method succeeds.
  4. Christopher Williams 2016-11-29

    Fixes pushed to master: https://github.com/appcelerator/titanium_mobile/commit/9c564ab384ee3ea3c4e70a9d697eadf56fda0707 6_0_X: https://github.com/appcelerator/titanium_mobile/commit/a6667488f527e09b10acadea90162c4bc6eb9d22
  5. Christopher Williams 2016-11-29

    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 as require('./utils') or require('/utils')
  6. Eric Wieber 2016-11-30

    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.

JSON Source