Lazy loading knockoutjs with bookmarklet failing - javascript

I'm attempting to fix a bookmarklet I wrote to track the URL changes in a single page application, specifically recording timesheet while using asana. It uses a script loader to embed jQuery and KnockoutJS libraries before init. I'm unable to find the ko object in global scope after the KnockoutJS library has initialized and cannot figure out why. To test, login to https://app.asana.com, open the Google Chrome developer tools' Console tab and try the following code:
var koScript=document.createElement('script');
koScript.type='text/javascript';
koScript.src='//ajax.aspnetcdn.com/ajax/knockout/knockout-3.0.0.js';
document.getElementsByTagName('head')[0].appendChild(koScript);
The Network tab shows the script downloading. The Elements tab shows the script as the last child of the head element. Yet ko remains undefined.

The short version is that:
Asana uses an internal module system that uses module.exports and require - the CommonJS standard you may know from node.js.
The knockout.js file checks the environment to determine if it should be setting window.ko or using module.exports or AMD-style define. If it detects CommonJS-style require it sets properties on exports instead of on a global ko object.
Workaround:
You could temporarily "copy" require off first:
_require = require; require = null
And then it should set window.ko as you're expecting!

Related

How to find the source file that generate VM Script?

My Rails application generate incorrect JS VM Script as circled that cause a issue.
How can I track to the source that generate it? (Source JS that created it not the displayed one in screenshots)
I've check on Firefox but issue still occured with different file name.
FYI
I found this issue when I deployed this service into production in AWS EC2 only.
Start the service in local got no issue
TL DR;
Use Network tab to inspect suspecious call which cause additional VM_____ script.
I've inspect and check Network
There's a xhr called inside some widget
That xhr call this appilication script again as eval function
So all resource in this page loaded twice
I've disable that JS and it's work now.
There's no additional VM____ in the inspection anymore

jQuery not found with Django RGBField

The project I'm working on uses an RGBField, which inserts this script into the template (which is deep in the bowels of django somewhere because I can't find where it lives):
<script type="text/javascript">
(function($){
$(document).ready(function(){
$('#id_color').each(function(i, elm){
// Make sure html5 color element is not replaced
if (elm.type != 'color') $(elm).colorPicker({"colors": ["f1c40f", "2ecc71", "9b59b6", "e74c3c", "34495e", "3498db", "1abc9c", "f39c12", "d35400"]});
});
});
})('django' in window && django.jQuery ? django.jQuery: jQuery);
</script>
In the console I'm getting an error: Uncaught ReferenceError: jQuery is not defined I'm unable to inspect where the error is happening, but removing the RGBField prevents the issue.
Jquery is used in the project, and if I use jQuery in the template itself it works fine (so it's not a problem with the template per se).
I've added django-jquery to the project, and included {% load staticfiles %} at the start of the template. Does not resolve the problem.
I've been ignoring the whole thing happily but now I need to write a cypress test with this page and the error is blocking the test.
Is there a way in cypress to ignore this error? Or is there a way to prevent the error from happening in the first place? Is there a flag for RGBField to turn off the check for jquery?
Running 'django' in window produces false, and running django.jQuery produces the error. Running 'django' in window && django.jQuery produces false so in theory this the second option should be taken, which when I run in the console is fine (but clearly I am missing something).
EDIT:
List of installed apps:
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.humanize',
'whitenoise.runserver_nostatic',
'storages',
'django.contrib.staticfiles',
'django.contrib.flatpages',
'jquery',
'django.contrib.sites',
'django_activeurl',
'webpack_loader',
'widget_tweaks',
'argonauts',
'rest_framework',
'main',
The error most likely relates to this line of code:
'django' in window && django.jQuery ? django.jQuery: jQuery
It maybe helpful to understand and consider the ternary conditional.
Out of the box, the Django Admin sets up a 'django' variable on the window global and pins jQuery to it. This is because the admin makes use of jQuery. Outside of the admin, in custom templates, it's up to the developer to decide how to include jQuery if they want it.
So the statement 'django' in window && django.jQuery willl evaluate to true on Django Admin pages and in the "true" side of the ternary, the snippet goes ahead and references it. Alternatively on the false side of the ternary, it's assumed jQuery is already present on the global scope. The reference to jQuery is then passed as a parameter into the IIFE.
I would look closely at your page source to determine if/where the jQuery module is referenced and ensure it's being loaded properly prior to that snippet.
By default, Cypress fails tests when there is an uncaught exception thrown. This behavior can be useful for many users and oftentimes alerts developers to bugs they were not aware of.
That being said, there are times when an uncaught exception is thrown and you would like to ignore it and carry on with your test (especially if it is being thrown from a 3rd party plugin). You can do this by using Cypress events.
To turn off all uncaught exception handling:
Cypress.on('uncaught:exception', (err, runnable) => {
// returning false here prevents Cypress from failing the test
return false
})
Likely you will want to do this in a support file (cypress/support/index.js) so it is applied to all spec files.

Javascript acting differently in inappbrowser vs Chrome - Undefined global variables

My problem is that when I use inappbrowser to open my web page, the main javascript file seems to be ignored, even though it is referenced in the Head of the file that I am opening using ref = cordova.InAppBrowser.open('https://MYURLHERE:8484/home/login', '_self', 'location=yes');
I am using chrome://inspect/#devices to inspect the console and I get errors when hitting buttons.. Anything referenced in the main.js file is undefined.. whereas the actual code for the autocomplete and button seems to be executing.
Please note The url is working fine when viewed in the chrome browser. The javascript files seem to load correctly, and all variables are defined correctly. - It is only when I use inappbrowser that I see issues with undefined variables.
My code (cordova app):
ref = cordova.InAppBrowser.open('https://MYURLHERE:8484/home/login', '_self', 'location=yes');
var myInAppBrowserCallback = function(event) {
console.log(event.url, 'LOADED');
};
ref.addEventListener('loadstart', myInAppBrowserCallback);
//Works fine.
My code (from the actual website I'm trying to view in Inappbrowser):
<script src="/Scripts/commonFunctions.js"></script>
var p = 'Hello';
<script src="/Scripts/loginPage.js"></script>
$('#btnLogin').on('click', function() {
alert(p);
});
Returns an alert with undefined.
What I have tried:
Extensive googling! (all the answers seem to be related to javascript not being enabled.. or 404 errors or things like that.. Not with global variables from one js file being undefined in another js file.)
Removing inappbrowser, using window.open.. Won't work as the app needs to execute scripts to inspect localstorage of the site.
Re-installing the android platform using cordova.
Re-installing the plugin.
Checking chrome in the inspector to ensure the files are in sources tab (they are).
Checking that the functions in main.js also exist (they do).
Thanks, JFIT
Summary:
The problem was that a javascript file was trying to load 'SpeechSynthesis' which was undefined only in the inappbrowser.
Details:
The problem with this was confusing but here are the steps I found to debug / solve:
Set up Remote Debugging on the phone so that you can view the console of the phone using chrome://inspect/#devices
View the console of the inappbrowser site (which will show as a seperate page to the inappbrowser instance.
Identify which files are being loaded and remove files until 'undefined' errors disappear.
Add back in the most recent file and start to strip out various functions (especially functions/variables before document.ready (global variables also)
Find the line/variable that way. It was handy for me this way as the actual undefined variable showed up after I removed most of the files.
The actual cause of my error was the speechSynthesis functionality.
The speechsynthesis lines were removed, and I readded all remaining files and everything works. This function works fine in chrome on desktop/android but not in the inappbrowser.

Parent view not setting global variable on <webview> in Electron after updating

I am trying to require a module in a guest page (angular controller).
When the application used an older version of node (0.30.5) it worked perfectly well. However i've had to upgrade electron to the latest version (0.37.6), and ive updated all uses of ipc in the electron application, so that it's now ipcMain and ipcRenderer.
Previously the angular controller managed to require the module using:
var ipc = window['require']('ipc');
So i thought that changing it to:
var ipcRenderer = window['require']('electron').ipcRenderer;
However that does not work and it states that window.require is not a function. I've tried multiple times to get it to work with other methods, however nothing works so far.
The problem is that require is undefined, however require is set in the html file that contains the <webview>, so it should be defined.
The <webview> goes to a URL which returns a <div> that uses angular.
The angular controller that is used in that <div> is no longer working, as the module I need is the first thing to be set in the file, and it is undefined
EDIT:
I can now see that the property that I set in the html is visible in the application debugger, however it does not appear in the webview debugger.
So I can only assume the parent view does not pass on the value to the <webview>. So if anyone knows why it doesn't pass on the value or what I need to do to set it, I would appreciate any information.
So as of the current version of Electron (0.37.6) the way to set a global variable is to specify a preload script on the preload attribute on the <webview> tag. For example in the preload script:
window['ipcRenderer'] = require('electron').ipcRenderer;
This will allow the guest page that the <webview> is displaying, to use the ipcRenderer. It seems like the previous method i was using, which was setting the global variable in the parent view HTML, does not work anymore
It's a quite old way to require electron modules. Here's the new one:
var ipcRenderer = require('electron').ipcRenderer;

Firefox extension: Access to main document from sidebar

I'm brand new to writing Firefox extensions and I'm trying to create a sidebar which searches for certain elements in the main document and shows info about them in the sidebar. I followed the instructions here to create the sidebar with no problems.
Problem I'm having now is accessing the main window or document in my sidebar.js file.
The docs here say to use
var mainWindow = window.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
.getInterface(Components.interfaces.nsIWebNavigation)
.QueryInterface(Components.interfaces.nsIDocShellTreeItem)
.rootTreeItem
.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
.getInterface(Components.interfaces.nsIDOMWindow);
But that gives me this error:
TypeError: window.QueryInterface is not a function
I'm getting the warning:
The Components object is deprecated. It will soon be removed.
Which makes me think even if the code above worked for me it's not the best method.
The error messages indicate that your code is running in an unprivileged javascript context. .QueryInterface() is XPCOM code, i.e. accessing internal browser components which is only available to privileged code.
It is generally not advisable to for "leaf content" (windows/sidebars spawned by addons) to have direct control. Instead your addon main code should coordinate the individual views. Your sidebar should be dumb, just pass messages to addon code and the addon then modifies the content of the tab.
Due e10s various parts of the browser may end up running in separate processes in the future and will not have direct access to each other.
If you're not developing with the addon-sdk - which is designed with message-passing as its primary way of gluing components together - you will have to use the message manager to wire your addon, sidebar and content scripts together.
Use tabs.create() | MDN as in:
browser.tabs.create({url:"https://www.google.com"});
I also used that documentation and I also got that error. The documentation is too old.
browser.tabs.create({url:"https://www.google.com"})
will work fine

Categories

Resources