[AC-6219] Runtime not finding function referenced within View
GitHub Issue | n/a |
---|---|
Type | Bug |
Priority | n/a |
Status | Closed |
Resolution | Needs more info |
Resolution Date | 2019-09-13T18:34:34.000+0000 |
Affected Version/s | Appcelerator Studio 4.5.0 |
Fix Version/s | n/a |
Components | Titanium SDK & CLI |
Labels | n/a |
Reporter | Nigel Underwood |
Assignee | Joshua Quick |
Created | 2019-04-19T15:14:58.000+0000 |
Updated | 2020-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....
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.
[~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"
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 = "[~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 callmyFunction()
that I'm guessing exists in "alloy.js". If this is the case, then try addingmyFunction()
directly to theglobal
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.)_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.)_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.
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 havemyview.js
file generated by the Alloy build system. Look for all references to yourmyFunction
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 viaaddListener()
. Any clues you can find would be a big help.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:
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.
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.
[~developer@tpglobalpartners.com], Did you manage to test on 8.0.2.GA?We are looking forward to your response.
Just tried this on 8.0.2.GA and the same issue - go back to 7.5.0 SDK and it works fine.
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.
I will strip down the project to the barest minimum and send this to you, that would be best.
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.
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.
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
I see. This sounds like a scoping issue. JavaScript "functions" are normally "hoisted" outside of their block scope like "var" declared variables.
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.
The below works fine in node.js and Titanium. It hoists the function without issue.
The below works fine in node.js and Titanium as well. This proves hoisting works, but only after the function was defined.
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.Probably the best solution is to move your try/catch inside of the callback functions you are trying to safeguard.
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.