Titanium JIRA Archive
Titanium SDK/CLI (TIMOB)

[TIMOB-9560] iOS: addEventListener via call()/apply() fails with exception

GitHub Issuen/a
TypeBug
PriorityHigh
StatusClosed
ResolutionFixed
Resolution Date2012-07-12T14:48:24.000+0000
Affected Version/sRelease 2.0.2
Fix Version/sSprint 2012-14 Core, Release 3.0.0
ComponentsiOS
Labelscore, parity, qe-testadded
ReporterTony Lukasavage
AssigneeMax Stepanov
Created2012-06-14T16:44:35.000+0000
Updated2014-01-31T18:45:51.000+0000

Description

Problem

When a proxy's addEventListener or removeEventListener is called via Javascript's call() or apply() functions, as demonstrated in Test Case #1, you get the following exception on iOS:
[ERROR] Script Error = 'undefined' is not a function (evaluating 'al.call(win, 'click', function(e) { alert('clicked window'); })') at app.js (line 5).
The same call will work fine on Android and Mobileweb. On the other hand, calling these function without the call() function, as demonstrated in Test Case #2, fails on Android:
[ERROR][TiJSError(  352)] (main) [607,2357] ----- Titanium Javascript Runtime Error -----
[ERROR][TiJSError(  352)] (main) [3,2360] - In ti:/events.js:176,9
[ERROR][TiJSError(  352)] (main) [7,2367] - Message: Uncaught TypeError: Object #<Object> has no method '_hasListenersForEventType'
[ERROR][TiJSError(  352)] (main) [0,2367] - Source: 			this._hasListenersForEventType(type, true);
[ERROR][V8Exception(  352)] Exception occurred at ti:/events.js:176: Uncaught TypeError: Object #<Object> has no method '_hasListenersForEventType'
but works on iOS and Mobileweb.

Test Case #1

var win = Ti.UI.createWindow({
	backgroundColor: '#fff'
});
var al = win.addEventListener;
al.call(win, 'click', function(e) { alert('clicked window'); });
// al.apply(win, ['click', function(e) { alert('clicked window'); }]);
win.open();

Test Case #2

var win = Ti.UI.createWindow({
	backgroundColor: '#fff'
});
var al = win.addEventListener;
al('click', function(e) { alert('clicked window'); });
win.open();

Expected Result

Test Case #1 for calling the addEventListener and removeEventListener functions should function properly on Android, iOS, and Mobileweb with call() and apply().

Comments

  1. Jeff Haynie 2012-06-14

    We need to add test case for apply too
  2. Ivan Skugor 2012-06-14

    IMHO, second test case should not work since "var al = win.addEventListener;" unbinds "win" from that function (and changes "this" value to point to global object). Similar thing does not work in DOM environment. First test case opens Pandora's box. What if you do something like this:
       var win = Ti.UI.createWindow({
           backgroundColor: '#fff'
       });
       var button = Ti.UI.createButton({ title: 'Click me' });
       var al = win.addEventListener;
       al.call(button, 'click', function(e) { alert('clicked button'); });
       win.add(button);
       win.open();
       
    Or this:
       var win = Ti.UI.createWindow({
           backgroundColor: '#fff'
       });
       var customObject = {};
       var al = win.addEventListener;
       al.call(customObject, 'customEvent', function(e) { alert('Test'); });
       win.open();
       
    That should work in theory. In practice ... don't know. :)
  3. Tony Lukasavage 2012-06-15

    apply() added in Test Case #1. Ivan , you're probably right, I updated the Expected Result to indicate that Test Case #1 should work for all platforms.
  4. Max Stepanov 2012-07-11

    Complete test cases:
       var win = Ti.UI.createWindow({
           backgroundColor: '#fff'
       });
       var al = win.addEventListener;
       
       // test 1
       //al.call(win, 'click', function(e) { alert('clicked window'); });
       
       // test 2
       //al.apply(win, ['click', function(e) { alert('clicked window'); }]);
       
       // test 3
       //al('click', function(e) { alert('clicked window'); });
       
       // test 4
       //Ti.UI.createWindow().addEventListener.call(win, 'click', function(e) { alert('clicked window'); });
       
       // test 5
       //Ti.UI.createWindow().addEventListener.apply(win, ['click', function(e) { alert('clicked window'); }]);
       
       win.open();
       
  5. Max Stepanov 2012-07-11

    PR pending https://github.com/appcelerator/titanium_mobile/pull/2541

JSON Source