Titanium JIRA Archive
Appcelerator Community (AC)

[AC-6219] Runtime not finding function referenced within View

GitHub Issuen/a
TypeBug
Priorityn/a
StatusClosed
ResolutionNeeds more info
Resolution Date2019-09-13T18:34:34.000+0000
Affected Version/sAppcelerator Studio 4.5.0
Fix Version/sn/a
ComponentsTitanium SDK & CLI
Labelsn/a
ReporterNigel Underwood
AssigneeJoshua Quick
Created2019-04-19T15:14:58.000+0000
Updated2020-02-19T21:42:08.000+0000

Description

Since upgrading to SDK 8, any function referenced in a View is no longer found in the associated controller. For example, in my mainview.xml I have the following and in the mainview.js I have function myFunction() { // Do Something } In SDK7.5 this works fine, but in SDK8 I receive the error [ERROR] : Script Error { [ERROR] : column = 13; [ERROR] : line = 102; [ERROR] : message = "Can't find variable: myFunction"; I have had this in previous SDK versions on occasions and SDK point releases then resolved the issue. I would like to move to SDK8 but until this is resolved, I will have to stay on 7.5 as I have a lot of functions reference in my XML views. BTW, this is impassible to replicate on a standalone project so may be linked to the size/complexity of the project perhaps....

Comments

  1. Nigel Underwood 2019-04-21

    This is something I cannot replicate as I think it's linked to the size and complexity of the code. I have had this issue with previous SDK versions and after a few point releases the issue goes.
  2. Joshua Quick 2019-04-22

    [~developer@tpglobalpartners.com], when you build your app, do you see any "BABEL" warnings? I'm wondering if you're running into a transpile issue. Do a search for BABEL in your build log. For example, I've seen the following BABEL warning happen in the past. exceeds the max of "500KB"
  3. Nigel Underwood 2019-04-25

    Thanks for the suggestion, unfortunately no BABEL is in the build log, in fact there are no compilation errors at all. I turned off the Live View though and I received the following error, not sure if this is of any help [ERROR] : Script Error { [ERROR] : column = 13; [ERROR] : line = 102; [ERROR] : message = "Can't find variable: myFunction"; [ERROR] : sourceURL = "file:///Users/myuser/Library/Developer/CoreSimulator/Devices/699AE052-05D7-444F-BCFA-C6806B56C263/data/Containers/Bundle/Application/C8E83C3B-23E0-4823-81EF-074561834B38/myapp.app/alloy/controllers/myview.js"; [ERROR] : stack = " at Controller(/alloy/controllers/myview.js:102:13)\n at createController(/alloy.js:353:53)\n at Controller(/alloy/controllers/index.js:41:49)\n at createController(/alloy.js:353:53)\n at (/app.js:165:23)\n at global code(/app.js:167:70)\n at require@[native code]\n at require(/ti.internal/extensions/binding.js:21:25)\n at (/ti.main.js:40:10)\n at loadAsync(/ti.internal/bootstrap.loader.js:108:13)\n at global code(/ti.main.js:37:52)"; [ERROR] : toJSON = ""; [ERROR] : } [ERROR] : Script Error Module "app.js" failed to leave a valid exports object
  4. Joshua Quick 2019-04-25

    [~developer@tpglobalpartners.com], do you have a function named myFunction() in your "alloy.js" file? Because it sounds like your "myview.js" code is trying call myFunction() that I'm guessing exists in "alloy.js". If this is the case, then try adding myFunction() directly to the global object. For example, if your "alloy.js" looks like the below... _(Doing the below in Titanium 8.0.0 will log an "implicit global scope" warning at runtime.)_
       function myFunction() {
       	console.log("Hello World");
       }
       
    Then do the following instead. The below will explicitly add the function to the global namespace. _(Note that it's a lowercase global which works in both Alloy and Classic Titanium apps.)_
       global.myFunction = function() {
       	console.log("Hello World");
       }
       
  5. Nigel Underwood 2019-04-26

    Thanks for the update. The myFunction referenced in the myview.xml is defined within the myview.js and the scope is contained within that. For some background info, I had this issue on a couple of point releases in SDK 6, it then went away and came back in SDK8, so not sure what the issue is.
  6. Joshua Quick 2019-04-29

    I can't reproduce this yet. Try this. Do a build and then go to the following directory... <YourProjectDirectory>/Resources/<android|iphone>/alloy/controllers Under the above directory, you should have myview.js file generated by the Alloy build system. Look for all references to your myFunction in that code. Something in there must be wrong. For example, double check that a copy of your function code exists in there. And you should see Alloy generated code in that file where it sets up a "click" listener with it via addListener(). Any clues you can find would be a big help.
  7. Nigel Underwood 2019-05-09

    Check the file and it seems to be setting up the listener ok and the file looks the same between SDK7 and 8. With SDK8 though when it gives a runtime error [INFO] : [LiveView] Error Evaluating app.js @ Line: 65 [ERROR] : ReferenceError: Can't find variable: myFunction [ERROR] : File: app.js [ERROR] : Line: 65 [ERROR] : SourceId: [ERROR] : Backtrace: [ERROR] : undefined
  8. Sharif AbuDarda 2019-06-10

    Hello, Let us know the current status of the issue. Please provide a reproducible sample code for us to test the issue if it is still reproducible with the latest SDK. Thanks.
  9. Nigel Underwood 2019-06-14

    Same issue with the latest SDK. As mentioned, I cannot reproduce the test case, its an issue with some of the SDK versions and probably related to the size and complexity of the project. The core issue is the same, when a function is referenced within a view and the associated controller contains the functuon definition, at runtime the function is not found on SDK8. I receive an error ReferenceError: Can't find variable: myFunction On SDK 7 it works fine.
  10. Rakhi Mitro 2019-07-24

    [~developer@tpglobalpartners.com], Did you manage to test on 8.0.2.GA?We are looking forward to your response.
  11. Nigel Underwood 2019-07-24

    Just tried this on 8.0.2.GA and the same issue - go back to 7.5.0 SDK and it works fine.
  12. Sharif AbuDarda 2019-07-24

    Hello, We need a sample reproducible code, Can you please share your project that reproduces the issue? You can personally email us the project and we will look into it. Thanks.
  13. Nigel Underwood 2019-07-24

    I will strip down the project to the barest minimum and send this to you, that would be best.
  14. Rakhi Mitro 2019-08-12

    Hello, We have not heard back from you since our last update. I just wanted to follow up with you about this issue? Are you still experiencing this problem? Please let us know if you need more help with this issue.
  15. Rakhi Mitro 2019-08-25

    Hello, Just passing as followup here. Are you able to get that sorted out? Please let us know if you need more help with this issue.
  16. Nigel Underwood 2020-02-17

    Came back to this as I needed to move to SDK and resolved the issue. It was due to the controller class have a try catch wrapper around the entire controller code which caused the issue. So if I had a controller called myPage.js with the following code: try { function myFunction() { console.log("Hello World"); } } catch ( e) { console.log("Error"); } and in the related view file I have If in index.js I call try { var newPage = Alloy.createController("myPage"); } catch (e) { console.log ("Error in index.js"); } then I would receive a runtime error of {color:red}*[ERROR] :*{color} message = "Can't find variable: myFunction"; So to fix this, I removed the try-catch in myPage.js and then it would work no issues. This code however works in SDK7 as is, but fails in SDK8.
  17. Joshua Quick 2020-02-18

    I see. This sounds like a scoping issue. JavaScript "functions" are normally "hoisted" outside of their block scope like "var" declared variables.
  18. Joshua Quick 2020-02-19

    After some extensive testing, I'm concluding this is a breaking-change in Google's V8 JavaScript runtime, because I can reproduce this same scoping/hoisting issue in node.js as well (which uses V8 like Titanium). For example, the below throws an exception in node.js and Titanium. The below is the equivalent to what you are seeing in your Titanium project.
        var logMessageCallback = logMessage;
        try {
        	function logMessage() {
        		console.log("@@@ Hello World");
        	}
        } catch (err) {
        	console.log(err);
        }
        logMessageCallback();
        
    The below works fine in node.js and Titanium. It hoists the function without issue.
        var logMessageCallback = logMessage;
        function logMessage() {
        	console.log("@@@ Hello World");
        }
        logMessageCallback();
        
    The below works fine in node.js and Titanium as well. This proves hoisting works, but only after the function was defined.
        try {
        	function logMessage() {
        		console.log("@@@ Hello World");
        	}
        } catch (err) {
        	console.log(err);
        }
        logMessage();
        
    Also, wrapping the hoisted function like this doesn't work anyways. For example, try the below in node.js or Titanium. The exception cannot be caught because the logMessage() is really being declared outside of the try/catch block due to hoisting.
        try {
        	function logMessage() {
        		throw new Error("@@@ Uh-Oh");
        	}
        } catch (err) {
        	// You'll never get here.
        	console.log('@@@ The exception was caught.');
        }
        logMessage();
        
    Probably the best solution is to move your try/catch inside of the callback functions you are trying to safeguard.
  19. Nigel Underwood 2020-02-19

    Ok this makes sense and what you have suggested is what I have done in the end for this to work. Thanks for the full diagnosis and assistance.

JSON Source