[TIMOB-5123] Android: CommonJS Modules not included/functional in distribution build
GitHub Issue | n/a |
---|---|
Type | Bug |
Priority | Critical |
Status | Closed |
Resolution | Fixed |
Resolution Date | 2012-01-06T12:02:29.000+0000 |
Affected Version/s | Release 1.7.2 |
Fix Version/s | Release 1.7.4, Sprint 2011-47, Release 1.8.0 |
Components | Android |
Labels | branch-v8, dr-list, qe-testadded, verified-1.7.3 |
Reporter | Kevin Whinnery |
Assignee | Bill Dawson |
Created | 2011-08-26T13:32:37.000+0000 |
Updated | 2012-01-06T12:02:29.000+0000 |
Description
Multiple reports have come in from the community that CommonJS modules (in the Resources directory) are not being found in Android .apk files that have been packaged for distribution. I have confirmed this to be the case myself on both Gingerbread and Froyo devices with a .apk I built for distribution through Titanium Studio
To reproduce, try packaging an application for distribution using CommonJS JavaScript modules. Any simple module should be able to reproduce it, but you can use my sample app from here:
https://github.com/appcelerator-developer-relations/Forging-Titanium/tree/master/ep-003/CustomComponents
The stack trace I got from my device is located here:
http://www.pastie.org/pastes/2435429/text
Attachments
File | Date | Size |
---|---|---|
device-2011-11-10-171754.png | 2011-11-10T17:37:08.000+0000 | 129320 |
device-2011-11-10-173441.png | 2011-11-10T17:37:08.000+0000 | 68192 |
timob5123.zip | 2011-10-25T09:53:38.000+0000 | 2328708 |
Also, reported in the Q&A here: http://developer.appcelerator.com/question/124473/commonjs-modules---typeerror-in-production
NOTE: on iOS, it appears that packaged apps crash when trying to run code from a CommonJS module. I'm not sure if this is related, or is a separate bug.
I finally got my Galaxy Tab working with adb under Lion. As a result, I can run the CommonJS test project on the Android device (by selecting "Android Device" from the drop-down menu.) So it's only the Distribute command that does not work. Summary: Run on Android device WORKS Distribute - Android FAILS Distribute - iOS FAILS All emulators WORK
Any word on when this issue might be addressed? Without the ability to deploy, a lot of us are hedging our plans for refactoring code to use the CommonJS module format.
Please escalate this problem! We are dying on the vine, having just tried to release our app on the Android Market, and our very first customer ran into this. Is there a workaround? We have got to do something, and quick.
Looking for a workaround for this, or possibly a fix in one of the nightly builds of the SDK. This is a complete show stopper for us.
We are having the same problem. Is there a quick fix? Hate to be a pain but I need something.
After lots of hard work and overtime our team was very excited to deploy. Our library is built around the "require" feature so there is no quick fix! Now we have to tell the president of the company that we had to pull the app off the market. It sure would be nice to give him a time frame as to when this issue will be addressed! To make matters worse, there is a board of directors meeting this week. A demo of the new Titanium based Smartphone app is on the agenda. Please help our president save face by escalating this ASAP!
I have documented a workaround here. This is issue is starting to be addressed in 1.8, but as a platform team we need to verify CommonJS use cases before 1.8 ships: http://developer.appcelerator.com/question/124473/commonjs-modules---typeerror-in-production#answer-218739
Pull requests ready: Rhino: https://github.com/appcelerator/rhino_titanium/pull/4 TiMobile: https://github.com/appcelerator/titanium_mobile/pull/493
It would be super fantastically awesome if these commonJS changes would get processed sooner rather than later - lots of folks running up against it with current prod release now that we've been demoing CommonJS so much (and since it's the wave of the future).
Totally agree. The relevant peeps (those who will review my changes) won't see your comment since they don't watch here, but I'd anyway already told them it's high prio.
Thanks!
Going to merge into 1.7.X, so re-opening.
Merged into 1_7_X as well
We have a regression whereby if you put a forward slash in the front of the module path (require("/lib/mymodule"), for example), it will fail.
New testing notes: Please test Kevin's original failcase (in the description) in *production* (i.e., "Distribute - Android" in Titanium Studio). THEN, test the attached app in timob5123.zip. Test it twice: once with the tiapp.xml's "compilejs" setting to false, once to true.
Newer fix in master and 1_7_X
Verified fixed with Mac OS X 10.6.8, Titanium Studio build: 1.0.5.201109261308 , SDK 1.7.3.v20110928185013. Packaged CustomComponents sample, and TIMOB5123 Zip with
It seems is not fixed yet. ( 1.7.3 and 1.8 ) I'm trying to deploy to device with Android 2.1 and I get this error: ~~~ 10-05 10:53:33.819: ERROR/TiJSError(29889): (kroll$6: app://mycards/carddetail.js) [2,56885] - Message: TypeError: Cannot find function makeInit in object [object Object]. (app://mycards/carddetail.js#76) ~~~ Of course that the module is ok and it works with 1.7.2 without any problem. With or without
Were you setting the
exports
object directly, by chance? Such as ...If so, note that that is **not** part of the CommonJS standard. The fact that it worked in previous versions of the Android
require()
implementation (and in iOS) was more or less accident. We now use the official Rhino (the javascript engine) CommonJS implementation in Android. Regarding it not being part of CommonJS, see http://groups.google.com/group/commonjs/browse_thread/thread/1f4fa28f304d4d35 Node (nodejs) does not support if either, for example.FYI re the
exports = ...
issue that I note above, we have already a parity ticket for that, meaning a ticket to address the fact that it works in iOS but not Android. So it will either be removed from iOS or a new solution will be found for Android. TIMOB-5406Yes sir, it seems that setting an object that will be assigned to exports later breaks the things :) It would be better (imho) to be removed from ios to stick with the standard. Thank you.
The module spec provides for assignment of an object to the exports variable. This is a case where an addition to Android is needed.
I haven't been able to find it in any spec. Where do you see it?
I'm lost. So
is valid (from the standard point of view)? if so
will still work ? thnx
Dan, you are correct, the first format should work. The Module spec: http://wiki.commonjs.org/wiki/Modules/1.1 indicates that exports must be a free variable - a free variable (in computer science terms) is a placeholder value to which other values can be assigned. By that definition, it should be possible to assign a value to the exports object.
The above should be a valid use of CommonJS modules.
Period? End of story? I think not! :) Anyway, I'm moving my response to the appropriate place, TIMOB-5406. We need any more comments here. We already have the ticket that came out specifically because of this issue.
Re-opened for full re-test after changes to be made for TIMOB-5748
New pull request ready: https://github.com/appcelerator/titanium_mobile/pull/578
Uploaded new version of timob5123.zip. The other one accidentally had a file with an underscore beginning its name.
Now occurring with timob5123.apk on both rhino and v8 with SDK 1.8.0.1.v20111109152300. See attached screenshots
It's not related to distributed mode, so I'll create a different ticket. It's related to forward slashes, and occurs also on emulators and non-distributed-mode devices. If you took my two forward-slashed references out of timob5123.zip, it works fine in distributed build. To test that, here is the modified app.js
Just to make sure, quoting Kevin Whinnery above, is the following now working on android and iOS without problems? {quote} Dan, you are correct, the first format should work. The Module spec: http://wiki.commonjs.org/wiki/Modules/1.1 indicates that exports must be a free variable - a free variable (in computer science terms) is a placeholder value to which other values can be assigned. By that definition, it should be possible to assign a value to the exports object. function MyObject() {} MyObject.prototype.sayHello() { alert('hello'); }; exports = MyObject; var MyObject = require('MyObject'); var o = new MyObject(); The above should be a valid use of CommonJS modules. {quote}
Tested with Titanium Studio 1.0.7.201112152014 Ti Mob SDK 1.8.0.1.RC3 OSX Lion Nexus One OS 2.2.2 Tested both CustomComponents with true/false, and timob5123 with true/false
Updating tags