[TIMOB-4242] Calling Ti.API.info from global object reference in sub-context causes event exception
GitHub Issue | n/a |
---|---|
Type | Bug |
Priority | Medium |
Status | Closed |
Resolution | Fixed |
Resolution Date | 2011-06-03T14:36:32.000+0000 |
Affected Version/s | Release 1.7.0 |
Fix Version/s | Sprint 2011-22 |
Components | iOS |
Labels | ti.api |
Reporter | Jeffrey Clark |
Assignee | Blain Hamon |
Created | 2011-05-18T11:11:44.000+0000 |
Updated | 2011-06-06T14:04:56.000+0000 |
Description
The following code produces error (below) as summarized on iOS only. The error can be circumvented by placing a call to everywhere.test() or Ti.API.info before it is called by the event in win.js (sub-context reference).
/scopebug/Resources/app.js";
}
{noformat}
var everywhere = {
test: function() {
Ti.API.info('this is a test');
}
};
var win = Titanium.UI.createWindow({
url: 'win.js'
});
win.everywhere = everywhere;
win.open();
({
win: Ti.UI.currentWindow,
everywhere: Ti.UI.currentWindow.everywhere,
init: function() {
var self = this;
var button = Ti.UI.createButton({
title: "click me"
});
button.addEventListener('click', function(e) {
self.clicked();
});
this.win.add(button);
},
clicked: function() {
this.everywhere.test();
}
}).init();
{noformat}
[WARN] [object TopTiModule] tried to note the callback for API in the wrong thead.
[WARN] Exception in event callback. {
line = 6;
message = "-[__NSCFDictionary setObject:forKey:]: attempt to insert nil value (key: API)";
sourceId = 116344464;
sourceURL = "file://
Other users are reporting what appears to be the same issue in [a community support question](https://developer.appcelerator.com/question/119751/errors-with-latest-builds-17x-r3bed52c7-and-18x-r5a5f4522#header). I entered another ticket (TC-10) which, although the example code is different, it may fall under the same problem.
[Comment on github from development team](https://github.com/appcelerator/titanium_mobile/commit/7bef2bd0bcb7abbded1b9cccbbd187ee056788d7#commitcomment-390814)
Tested and works on Android 2.2, Titanium SDK 1.7.0 (05/27/11 17:53 8be59d3...)
A client is watching this now as well.
Associated Helpdesk Ticket
http://appc.me/c/APP-367438The fix won't make it into 1.7.0, but there's a workaround. The workaround is to put, in app.js, put as line 1: Ti.API; Cross-context function calls are dangerous things (It's better to use event handlers, because of threading issues. (JS objects in JSCore are not threadsafe, and cross-context function calls mean you could be modifying the same JS object at the same time.) When you first refer to a module, that's when it's generated and attached to the Titanium namespace. However, when you're doing a cross-context call, the Titanium namespace the function is accessing is NOT the Titanium of the context calling the function. Because it's the wrong namespace, the context that owns it refuses to register the module because it's the wrong thread (safety reasons). However, if the module was already registered in the right context, things are fine. We pre-register UI module since it will be used. Since API module is also common, it will now be pre-registered. However, other modules won't be pre-registered.
It's still not good to call cross-context, but pre-loading API is innocuous enough.
Verified fixed with Verizon iPhone 4 (4.2.8) , Titanium Studio, build: 1.0.0.201106021621, Titanium SDK version: 1.8.0 r477c7b27. No exception, simply a warning: [WARN] (null)->(null) [0]->[object APIModule] is being made in a thread not owned by