Titanium JIRA Archive
Titanium SDK/CLI (TIMOB)

[TIMOB-7025] iOS: CommonJS - JavaScript module require()d by a url-based Window can't see Ti.Network

GitHub Issuen/a
TypeBug
PriorityLow
StatusClosed
ResolutionWon't Fix
Resolution Date2018-03-12T14:24:53.000+0000
Affected Version/sRelease 1.8.0.1, Release 3.1.0
Fix Version/sn/a
ComponentsiOS
Labelsn/a
ReporterShawn Lipscomb
AssigneeIngo Muschenetz
Created2012-01-06T10:39:56.000+0000
Updated2018-03-12T15:55:10.000+0000

Description

Problem

A CommonJS (JavaScript) module which is require()d by a url-based Window (a window created with the 'url' property) from inside of that window's 'open' event tries to access Ti.Network.online, but instead a runtime error is produced:
[ERROR] Script Error = Result of expression 'Ti.Network' [undefined] is not an object.
Please see the attached project (code repeated at the bottom of this description). It's a 5-step process to expose this error. The attached code has been minimized down from an actual project, so while it may look weird and seem to contain unnecessary steps, keep in mind that this is an excerpt from a real project with a real problem. I have reduced it down to the bare minimum necessary to reproduce the problem. The normal workaround of adding a reference to "Ti.Network" in app.js does *not work* in this case. Another problem that is evident in the example: - In app.js, you shouldn't have to reference "Ti.App" to get past the use of Ti.App in deep.js, but without that line in app.js, you get the same "undefined" error on Ti.App. The problem does *not occur on Android*...the app works fine.

Steps to Reproduce

- Unzip the attached project and run it to the iPhone simulator. - Look at the console log. - Right after "** trying Network", you will see this error
[ERROR] Script Error = Result of expression 'Ti.Network' [undefined] is not an object.

Expected Result

The app should run without error and give the console message "** Network is there!".

Testcase Code

var Sequencer=require('Sequencer');
Sequencer.SetML('deep',require('deep'));

Ti.App; // without this here, the Ti.App in deep.js crashes.
Ti.Network; // this workaround doesn't work.

var w1=Ti.UI.createWindow({url:'win1.js'});
w1.Sequencer=Sequencer;
w1.open();
Ti.API.info('** Loading Sequencer');

exports.ML={};


exports.SetML=function(Prop,Val)
{
  exports.ML[Prop]=Val;
};


exports.GetML=function()
{
  return exports.ML;
};
exports.RegisterWindowLoadEvent=function(TheWindow,OnLoadEvent)
{
  Ti.App.CurrentWindow=TheWindow;
  Ti.App.CurrentWindow.addEventListener('open',OnLoadEvent);
};
var Sequencer=Ti.UI.currentWindow.Sequencer;
deep=Sequencer.GetML().deep;

deep.RegisterWindowLoadEvent(Ti.UI.currentWindow,MainWinLoad);


function MainWinLoad()
{
  Ti.API.info('** MainWinLoad');
  Ti.API.info('** step 1');
  var Killer=require('win2');
  Ti.API.info('** step 2');
}
Ti.API.info('** trying Network');
  if (Ti.Network.online)
    Ti.API.info('** Network is there!');
Ti.API.info('** done trying Network');

Attachments

FileDateSize
TiNamespaceTest.zip2012-01-06T10:39:56.000+0000745908

Comments

  1. Shawn Lipscomb 2012-01-06

  2. Paul Dowsett 2012-01-06

    If only all tickets were as well defined as this! Thank you, Shawn, I have escalated it immediately. :)
  3. Shawn Lipscomb 2012-01-07

    Thanks, Paul. It took me 1 whole work day to reduce this down to a small reproducable case from the actual project...it gave me one hell of a headache.
  4. Stephen Tramer 2012-02-07

    Note that the following version of win1 *does* work, for the same reasons that the above app.js does (namely, it preloads the module into the right context):
       var Sequencer=Ti.UI.currentWindow.Sequencer;
       deep=Sequencer.GetML().deep;
       
       Ti.Network; // Pre-loads Ti.Network into this context
       deep.RegisterWindowLoadEvent(Ti.UI.currentWindow,MainWinLoad);
       
       
       function MainWinLoad()
       {
         Ti.API.info('** MainWinLoad');
         Ti.API.info('** step 1');
         var Killer=require('win2');
         Ti.API.info('** step 2');
       }
       
    The problem is that the require()d module has its *page* in the context in which it was evaluated, which in this case, is always app.js. But the module is *executed* in win1.js and that's where the discrepancy comes from. This can only really be resolved by moving to single context, either within the app or changing the iOS infrastructure. Currently there is still the restriction that modules must be require()ed in the context in which they are evaluated.
  5. Shameer Jan 2013-04-19

    Issue reproduces Tested with Titanium Studio, build: 3.0.1.201212181159 Titanium SDK version: 3.1.0 Titanium SDK version: 3.0.2 iOS iPhone Simulator: iOS SDK version: 6.0
  6. Rene Pot 2018-03-12

    url-based window is no longer supported

JSON Source