[TIMOB-5406] Android: commonjs exports object is undefined in some cases
GitHub Issue | n/a |
---|---|
Type | Bug |
Priority | High |
Status | Closed |
Resolution | Fixed |
Resolution Date | 2011-11-21T08:05:15.000+0000 |
Affected Version/s | Release 1.8.0 |
Fix Version/s | Sprint 2011-46, Release 1.8.0.1 |
Components | Android |
Labels | parity |
Reporter | Rick Blalock |
Assignee | Bill Dawson |
Created | 2011-10-03T14:13:00.000+0000 |
Updated | 2014-06-19T12:46:31.000+0000 |
Description
Sample code:
// app.js
var testmodule1 = require('testmodule');
Ti.API.info('TEST MODULE 1 TEST: ' + testmodule1.someprop); // This will be undefined
// Module
// This doesn't work
exports = {
someprop: 'coolbeans'
};
I'll grant that mine was a liberal reading of the CommonJS spec, but they shouldn't have called
exports
a free variable in the spec if it actually wasn't one (I think I am in the right on the Math/CS definition of free variable). In practicemodule.exports = {};
is non-standard, but it serves to address the lack of direct assignment toexports
, which is either a flaw in either the spec or in many implementations of it, depending on your opinion. So, do we suffer a flaw in the spec because that's what we think the spec dictates? Or do we provide a workable solution for users? I vote for the latter. This:is a clumsy implementation. I don't think module.exports is the right answer, though, because it introduces another magical variable that has no place in the spec. A common sense approach would be to allow direct assignment to the exports object.
To view the issue from a parity standpoint, do we want to take away a useful feature from one platform because we don't think it's standard? If it's not a maintainable solution on the Android side then maybe we do, but that's too bad. Sidenote: @Bill your mother is considered homely by many.
I know, she totally fooled Dad somehow. :) We're transitioning into using node.js's commonjs implementation (via the V8 team -- though it will be available for both V8 and Rhino AFAIK). So I imagine module.exports will automatically become available, since that's a node.js thang. So we can wait and see on that. Meanwhile this can just stay open till we can test the newer implementation.
Since we're now using node.js's module implementation, we support
module.exports = { ... };
, which is functionally equivalent to what is desired here.So the test case would be:
Hi. :) Just to add a bit more explanation to this discussion. I would like to explain why object can't be assigned directly to the "export" variable. The problem lies in some JS environments that can implement CommonJS (browser to be precise). In browser, scripts loaded via dynamically created script tag are evaluated in global scope. Because of that, module scope has to be improvised by creating new function scope that wraps module's source code and in which "exports" and "require" variables are injected via function parameters. Basically, after wrapping of module's source code this is created:
where "require" is a function (that loads dependencies) and "exports" is basically empty object - {} to which API is added. Changes to that object needs to be reflected on external object injected to that function because in module's wrapper function there is no return statement. And here the problem with assigning object (or anything else) directly to "exports" variable lies. If anything would be directly assigned to the "exports" variable, that change would not be reflected on the external object (because object are passed by the copy of reference, so "exports" variable contains reference copy of external object and changing what that variable points at, does not change that external object or other references to that external object). "module.exports" is a workaround actually. That said, I think you should be careful with CommonJS implementation in Mobile SDK's if you want Ti-related source code to work in browsers (or Mobile Web SDK's) - code portability is basic idea of CommonJS. Also, my bug report regarding global variables in CommonJS also suffers from similar problem. Anyway ... as you may noticed, CommonJS is not perfect, but new ECMAScript spec will have module system (which I hope will fix some of CommonJS issues) so maybe it should be taken into consideration right now (I don't know the current state of module specification, but I know there was some work involved).
Verified as Fixed. SDK: 1.8.0.1.v20111220190134 Android Runtimes: V8/Rhino Studio: 1.0.7.201112152014 OS: OS X Lion Devices Tested: Android Emulator 2.2, iPhone Simulator 5.0
Confirmed, ran test above on a 5.0 simulator with same SDK and Studio versions. Worked using: //test.js module.exports={someprop:'testing'}; //app.js var test1 = require('test'); alert(test1.someprop); // outputs testing Also confirmed this generates script { error on 1.7.5 SDK