Titanium JIRA Archive
Titanium SDK/CLI (TIMOB)

[TIMOB-8974] iOS: May be using executionContext for proxy creation when pageContext should be used

GitHub Issuen/a
TypeBug
PriorityLow
StatusReopened
ResolutionUnresolved
Affected Version/sRelease 2.0.1
Fix Version/sn/a
ComponentsiOS
Labelscore
ReporterStephen Tramer
AssigneeUnknown
Created2012-05-03T10:30:34.000+0000
Updated2018-02-28T20:04:13.000+0000

Description

Currently, iOS has many situations in which -[TiProxy _initWithPageContext:] does not pass a page context, but rather an execution context. In many situations this is acceptable and they may be identical, but it could be leading to subtle memory-related bugs and cross-context issues. We need to investigate the problem and make sure that each proxy is initialized with an appropriate JS context for its scope and lifespan.

Comments

  1. Blain Hamon 2012-05-03

    The page context is the execution context in which the proxy was created. That is: app.js
       var win = Ti.UI.createWindow({url:'foo.js'});
       win.table = Ti.UI.createTableView();
       win.add(win.table);
       win.open();
       
    foo.js
       Ti.UI.currentWindow.table.setData([{title:'baz'}]);
       
    win and win.table are both created in app.js's execution context, and thus have the page context of the one running app.js, and that will be the case for the life of the proxies. Ti.UI.currentWindow.table is the same as app.js's win.table. And while it still has the pagecontext of the one running app.js, the setData command is done inside foo.js, and thus, its execution context will be foo.js's. So setData runs with the foo.js execution context, and creates a row as a side effect. The row's page context MUST be the context it was created in (as to establish relationship) which is foo.js, despite the table itself having a page context of app.js. The only time a proxy should be created with a value other than the creating proxy's execution context is when the execution context is nil -- which is probably indicative of a bug -- in which case the page context is used just as a workaround. Marking this bug as invalid.
  2. Stephen Tramer 2012-05-03

    There is the following edge case: Context A has a global event listener which creates an object. Context B fires this global event. The execution context is that of context B (or should be), but the page context is that of context A. This may be considered a larger cross-context global vs. context group issue but there is still a problem regarding where data should reside as a result of the callback invoke because of our allowing cross-context interactions.
  3. Blain Hamon 2012-05-03

    In the event of event listeners, this is actually moot. When Context B fires a global event (Via Ti.App.fireEvent), the event and its JSON payload is placed into each context's run loop. That is, Ti.App.fireEvent triggers the event listeners in the contexts to which they exist. For a more concerete example, suppose app.js added a 'buzz' event listener to win, and foo.js added a 'buzz' event listener. This one proxy now has two event listeners associated with it. One attached to the JS object living in the app.js context, and the other attached to the JS object living in the foo.js context. When win.fireEvent('buzz',{}) is called, there is an event given to app.js and an event given to foo.js. During app.js' run loop, the event listener attached to the JS object living in app.js is called. The execution context is correct and all is well. During foo.js' run loop, the event listener attached to the JS object living in foo.js is called. The execution context is correct and all is well. I'll have to think about a cross-context function call. There may be no right answer, but using the execution context as the pageContext, despite the JS code itself associated with another context, may be the right answer simply because the execution context is also known as 'that context which owns the JS thread, and therefore the only one you can interact with in terms of creating or modifying objects.' Leaving reopened because this is a sticky wicket.

JSON Source